fpu_exp.c revision 1.7 1 1.7 isaki /* $NetBSD: fpu_exp.c,v 1.7 2013/04/20 04:38:51 isaki Exp $ */
2 1.1 briggs
3 1.1 briggs /*
4 1.1 briggs * Copyright (c) 1995 Ken Nakata
5 1.1 briggs * All rights reserved.
6 1.1 briggs *
7 1.1 briggs * Redistribution and use in source and binary forms, with or without
8 1.1 briggs * modification, are permitted provided that the following conditions
9 1.1 briggs * are met:
10 1.1 briggs * 1. Redistributions of source code must retain the above copyright
11 1.1 briggs * notice, this list of conditions and the following disclaimer.
12 1.1 briggs * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 briggs * notice, this list of conditions and the following disclaimer in the
14 1.1 briggs * documentation and/or other materials provided with the distribution.
15 1.1 briggs * 3. Neither the name of the author nor the names of its contributors
16 1.1 briggs * may be used to endorse or promote products derived from this software
17 1.1 briggs * without specific prior written permission.
18 1.1 briggs *
19 1.1 briggs * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 1.1 briggs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 1.1 briggs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 1.1 briggs * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23 1.1 briggs * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 1.1 briggs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 1.1 briggs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 1.1 briggs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 1.1 briggs * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 1.1 briggs * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 1.1 briggs * SUCH DAMAGE.
30 1.1 briggs *
31 1.1 briggs * @(#)fpu_exp.c 10/24/95
32 1.1 briggs */
33 1.2 lukem
34 1.2 lukem #include <sys/cdefs.h>
35 1.7 isaki __KERNEL_RCSID(0, "$NetBSD: fpu_exp.c,v 1.7 2013/04/20 04:38:51 isaki Exp $");
36 1.1 briggs
37 1.1 briggs #include "fpu_emulate.h"
38 1.1 briggs
39 1.7 isaki /* The number of items to terminate the Taylor expansion */
40 1.7 isaki #define MAX_ITEMS (2000)
41 1.7 isaki
42 1.1 briggs /*
43 1.1 briggs * fpu_exp.c: defines fpu_etox(), fpu_etoxm1(), fpu_tentox(), and fpu_twotox();
44 1.1 briggs */
45 1.1 briggs
46 1.6 isaki /*
47 1.6 isaki * x^2 x^3 x^4
48 1.6 isaki * exp(x) = 1 + x + --- + --- + --- + ...
49 1.6 isaki * 2! 3! 4!
50 1.6 isaki */
51 1.6 isaki static struct fpn *
52 1.6 isaki fpu_etox_taylor(struct fpemu *fe)
53 1.6 isaki {
54 1.6 isaki struct fpn res;
55 1.6 isaki struct fpn x;
56 1.6 isaki struct fpn s0;
57 1.6 isaki struct fpn *s1;
58 1.6 isaki struct fpn *r;
59 1.6 isaki uint32_t k;
60 1.6 isaki
61 1.6 isaki CPYFPN(&x, &fe->fe_f2);
62 1.6 isaki CPYFPN(&s0, &fe->fe_f2);
63 1.6 isaki
64 1.6 isaki /* res := 1 + x */
65 1.6 isaki fpu_const(&fe->fe_f1, FPU_CONST_1);
66 1.6 isaki r = fpu_add(fe);
67 1.6 isaki CPYFPN(&res, r);
68 1.6 isaki
69 1.6 isaki k = 2;
70 1.7 isaki for (; k < MAX_ITEMS; k++) {
71 1.6 isaki /* s1 = s0 * x / k */
72 1.6 isaki CPYFPN(&fe->fe_f1, &s0);
73 1.6 isaki CPYFPN(&fe->fe_f2, &x);
74 1.6 isaki r = fpu_mul(fe);
75 1.6 isaki
76 1.6 isaki CPYFPN(&fe->fe_f1, r);
77 1.6 isaki fpu_explode(fe, &fe->fe_f2, FTYPE_LNG, &k);
78 1.6 isaki s1 = fpu_div(fe);
79 1.6 isaki
80 1.6 isaki /* break if s1 is enough small */
81 1.6 isaki if (ISZERO(s1))
82 1.6 isaki break;
83 1.6 isaki if (res.fp_exp - s1->fp_exp >= FP_NMANT)
84 1.6 isaki break;
85 1.6 isaki
86 1.6 isaki /* s0 := s1 for next loop */
87 1.6 isaki CPYFPN(&s0, s1);
88 1.6 isaki
89 1.6 isaki /* res += s1 */
90 1.6 isaki CPYFPN(&fe->fe_f2, s1);
91 1.6 isaki CPYFPN(&fe->fe_f1, &res);
92 1.6 isaki r = fpu_add(fe);
93 1.6 isaki CPYFPN(&res, r);
94 1.6 isaki }
95 1.6 isaki
96 1.6 isaki CPYFPN(&fe->fe_f2, &res);
97 1.6 isaki return &fe->fe_f2;
98 1.6 isaki }
99 1.6 isaki
100 1.6 isaki /*
101 1.6 isaki * exp(x)
102 1.6 isaki */
103 1.1 briggs struct fpn *
104 1.4 dsl fpu_etox(struct fpemu *fe)
105 1.1 briggs {
106 1.6 isaki struct fpn *fp;
107 1.6 isaki
108 1.6 isaki if (ISNAN(&fe->fe_f2))
109 1.6 isaki return &fe->fe_f2;
110 1.6 isaki if (ISINF(&fe->fe_f2)) {
111 1.6 isaki if (fe->fe_f2.fp_sign)
112 1.6 isaki fpu_const(&fe->fe_f2, FPU_CONST_0);
113 1.6 isaki return &fe->fe_f2;
114 1.6 isaki }
115 1.6 isaki
116 1.6 isaki if (fe->fe_f2.fp_sign == 0) {
117 1.6 isaki /* exp(x) */
118 1.6 isaki fp = fpu_etox_taylor(fe);
119 1.6 isaki } else {
120 1.6 isaki /* 1/exp(-x) */
121 1.6 isaki fe->fe_f2.fp_sign = 0;
122 1.6 isaki fp = fpu_etox_taylor(fe);
123 1.6 isaki
124 1.6 isaki CPYFPN(&fe->fe_f2, fp);
125 1.6 isaki fpu_const(&fe->fe_f1, FPU_CONST_1);
126 1.6 isaki fp = fpu_div(fe);
127 1.6 isaki }
128 1.6 isaki
129 1.6 isaki return fp;
130 1.1 briggs }
131 1.1 briggs
132 1.6 isaki /*
133 1.6 isaki * exp(x) - 1
134 1.6 isaki */
135 1.1 briggs struct fpn *
136 1.4 dsl fpu_etoxm1(struct fpemu *fe)
137 1.1 briggs {
138 1.6 isaki struct fpn *fp;
139 1.6 isaki
140 1.6 isaki fp = fpu_etox(fe);
141 1.6 isaki
142 1.6 isaki CPYFPN(&fe->fe_f1, fp);
143 1.6 isaki /* build a 1.0 */
144 1.6 isaki fp = fpu_const(&fe->fe_f2, FPU_CONST_1);
145 1.6 isaki fe->fe_f2.fp_sign = !fe->fe_f2.fp_sign;
146 1.6 isaki /* fp = f2 - 1.0 */
147 1.6 isaki fp = fpu_add(fe);
148 1.6 isaki
149 1.6 isaki return fp;
150 1.1 briggs }
151 1.1 briggs
152 1.6 isaki /*
153 1.6 isaki * 10^x = exp(x * ln10)
154 1.6 isaki */
155 1.1 briggs struct fpn *
156 1.4 dsl fpu_tentox(struct fpemu *fe)
157 1.1 briggs {
158 1.6 isaki struct fpn *fp;
159 1.6 isaki
160 1.6 isaki /* build a ln10 */
161 1.6 isaki fp = fpu_const(&fe->fe_f1, FPU_CONST_LN_10);
162 1.6 isaki /* fp = ln10 * f2 */
163 1.6 isaki fp = fpu_mul(fe);
164 1.6 isaki
165 1.6 isaki /* copy the result to the src opr */
166 1.6 isaki CPYFPN(&fe->fe_f2, fp);
167 1.6 isaki
168 1.6 isaki return fpu_etox(fe);
169 1.1 briggs }
170 1.1 briggs
171 1.6 isaki /*
172 1.6 isaki * 2^x = exp(x * ln2)
173 1.6 isaki */
174 1.1 briggs struct fpn *
175 1.4 dsl fpu_twotox(struct fpemu *fe)
176 1.1 briggs {
177 1.6 isaki struct fpn *fp;
178 1.6 isaki
179 1.6 isaki /* build a ln2 */
180 1.6 isaki fp = fpu_const(&fe->fe_f1, FPU_CONST_LN_2);
181 1.6 isaki /* fp = ln2 * f2 */
182 1.6 isaki fp = fpu_mul(fe);
183 1.6 isaki
184 1.6 isaki /* copy the result to the src opr */
185 1.6 isaki CPYFPN(&fe->fe_f2, fp);
186 1.6 isaki
187 1.6 isaki return fpu_etox(fe);
188 1.1 briggs }
189