xref: /netbsd-src/sys/arch/m68k/fpe/fpu_hyperb.c (revision 6e812b739f88d38be6a7f2cb40994f78f91cbb09)
1 /*	$NetBSD: fpu_hyperb.c,v 1.17 2016/12/05 15:31:01 isaki Exp $	*/
2 
3 /*
4  * Copyright (c) 1995  Ken Nakata
5  *	All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. Neither the name of the author nor the names of its contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  *
31  *	@(#)fpu_hyperb.c	10/24/95
32  */
33 
34 /*
35  * Copyright (c) 2011 Tetsuya Isaki. All rights reserved.
36  *
37  * Redistribution and use in source and binary forms, with or without
38  * modification, are permitted provided that the following conditions
39  * are met:
40  * 1. Redistributions of source code must retain the above copyright
41  *    notice, this list of conditions and the following disclaimer.
42  * 2. Redistributions in binary form must reproduce the above copyright
43  *    notice, this list of conditions and the following disclaimer in the
44  *    documentation and/or other materials provided with the distribution.
45  *
46  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
47  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
48  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
49  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
50  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
51  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
52  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
53  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
54  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
55  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56  * SUCH DAMAGE.
57  */
58 
59 #include <sys/cdefs.h>
60 __KERNEL_RCSID(0, "$NetBSD: fpu_hyperb.c,v 1.17 2016/12/05 15:31:01 isaki Exp $");
61 
62 #include <machine/ieee.h>
63 
64 #include "fpu_emulate.h"
65 
66 /*
67  * fpu_hyperb.c: defines the following functions
68  *
69  *	fpu_atanh(), fpu_cosh(), fpu_sinh(), and fpu_tanh()
70  */
71 
72 /*
73  *             1       1 + x
74  * atanh(x) = ---*log(-------)
75  *             2       1 - x
76  */
77 struct fpn *
fpu_atanh(struct fpemu * fe)78 fpu_atanh(struct fpemu *fe)
79 {
80 	struct fpn x;
81 	struct fpn t;
82 	struct fpn *r;
83 
84 	if (ISNAN(&fe->fe_f2))
85 		return &fe->fe_f2;
86 	if (ISINF(&fe->fe_f2))
87 		return fpu_newnan(fe);
88 
89 	/* if x is +0/-0, return +0/-0 */
90 	if (ISZERO(&fe->fe_f2))
91 		return &fe->fe_f2;
92 
93 	/*
94 	 * -INF if x == -1
95 	 * +INF if x ==  1
96 	 */
97 	r = &fe->fe_f2;
98 	if (r->fp_exp == 0 && r->fp_mant[0] == FP_1 &&
99 	    r->fp_mant[1] == 0 && r->fp_mant[2] == 0) {
100 		r->fp_class = FPC_INF;
101 		return r;
102 	}
103 
104 	/* NAN if |x| > 1 */
105 	if (fe->fe_f2.fp_exp >= 0)
106 		return fpu_newnan(fe);
107 
108 	CPYFPN(&x, &fe->fe_f2);
109 
110 	/* t := 1 - x */
111 	fpu_const(&fe->fe_f1, FPU_CONST_1);
112 	fe->fe_f2.fp_sign = !fe->fe_f2.fp_sign;
113 	r = fpu_add(fe);
114 	CPYFPN(&t, r);
115 
116 	/* r := 1 + x */
117 	fpu_const(&fe->fe_f1, FPU_CONST_1);
118 	CPYFPN(&fe->fe_f2, &x);
119 	r = fpu_add(fe);
120 
121 	/* (1-x)/(1+x) */
122 	CPYFPN(&fe->fe_f1, r);
123 	CPYFPN(&fe->fe_f2, &t);
124 	r = fpu_div(fe);
125 
126 	/* log((1-x)/(1+x)) */
127 	CPYFPN(&fe->fe_f2, r);
128 	r = fpu_logn(fe);
129 
130 	/* r /= 2 */
131 	r->fp_exp--;
132 
133 	return r;
134 }
135 
136 /*
137  *            exp(x) + exp(-x)
138  * cosh(x) = ------------------
139  *                   2
140  */
141 struct fpn *
fpu_cosh(struct fpemu * fe)142 fpu_cosh(struct fpemu *fe)
143 {
144 	struct fpn x, *fp;
145 
146 	if (ISNAN(&fe->fe_f2))
147 		return &fe->fe_f2;
148 
149 	if (ISINF(&fe->fe_f2)) {
150 		fe->fe_f2.fp_sign = 0;
151 		return &fe->fe_f2;
152 	}
153 
154 	/* if x is +0/-0, return 1 */ /* XXX is this necessary? */
155 	if (ISZERO(&fe->fe_f2)) {
156 		fpu_const(&fe->fe_f2, FPU_CONST_1);
157 		return &fe->fe_f2;
158 	}
159 
160 	fp = fpu_etox(fe);
161 	CPYFPN(&x, fp);
162 
163 	fpu_const(&fe->fe_f1, FPU_CONST_1);
164 	CPYFPN(&fe->fe_f2, fp);
165 	fp = fpu_div(fe);
166 
167 	CPYFPN(&fe->fe_f1, fp);
168 	CPYFPN(&fe->fe_f2, &x);
169 	fp = fpu_add(fe);
170 
171 	fp->fp_exp--;
172 
173 	return fp;
174 }
175 
176 /*
177  *            exp(x) - exp(-x)
178  * sinh(x) = ------------------
179  *                   2
180  */
181 struct fpn *
fpu_sinh(struct fpemu * fe)182 fpu_sinh(struct fpemu *fe)
183 {
184 	struct fpn x, *fp;
185 
186 	if (ISNAN(&fe->fe_f2))
187 		return &fe->fe_f2;
188 	if (ISINF(&fe->fe_f2))
189 		return &fe->fe_f2;
190 
191 	/* if x is +0/-0, return +0/-0 */
192 	if (ISZERO(&fe->fe_f2))
193 		return &fe->fe_f2;
194 
195 	fp = fpu_etox(fe);
196 	CPYFPN(&x, fp);
197 
198 	fpu_const(&fe->fe_f1, FPU_CONST_1);
199 	CPYFPN(&fe->fe_f2, fp);
200 	fp = fpu_div(fe);
201 
202 	fp->fp_sign = 1;
203 	CPYFPN(&fe->fe_f1, fp);
204 	CPYFPN(&fe->fe_f2, &x);
205 	fp = fpu_add(fe);
206 
207 	fp->fp_exp--;
208 
209 	return fp;
210 }
211 
212 /*
213  *            sinh(x)
214  * tanh(x) = ---------
215  *            cosh(x)
216  */
217 struct fpn *
fpu_tanh(struct fpemu * fe)218 fpu_tanh(struct fpemu *fe)
219 {
220 	struct fpn x;
221 	struct fpn s;
222 	struct fpn *r;
223 	int sign;
224 
225 	if (ISNAN(&fe->fe_f2))
226 		return &fe->fe_f2;
227 
228 	/* if x is +0/-0, return +0/-0 */
229 	if (ISZERO(&fe->fe_f2))
230 		return &fe->fe_f2;
231 
232 	if (ISINF(&fe->fe_f2)) {
233 		sign = fe->fe_f2.fp_sign;
234 		fpu_const(&fe->fe_f2, FPU_CONST_1);
235 		fe->fe_f2.fp_sign = sign;
236 		return &fe->fe_f2;
237 	}
238 
239 	CPYFPN(&x, &fe->fe_f2);
240 
241 	/* sinh(x) */
242 	CPYFPN(&fe->fe_f2, &x);
243 	r = fpu_sinh(fe);
244 	CPYFPN(&s, r);
245 
246 	/* cosh(x) */
247 	CPYFPN(&fe->fe_f2, &x);
248 	r = fpu_cosh(fe);
249 	CPYFPN(&fe->fe_f2, r);
250 
251 	CPYFPN(&fe->fe_f1, &s);
252 	r = fpu_div(fe);
253 
254 	return r;
255 }
256