fpu_exp.c revision 1.6 1 1.6 isaki /* $NetBSD: fpu_exp.c,v 1.6 2013/04/20 03:06:19 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.6 isaki __KERNEL_RCSID(0, "$NetBSD: fpu_exp.c,v 1.6 2013/04/20 03:06:19 isaki Exp $");
36 1.1 briggs
37 1.1 briggs #include "fpu_emulate.h"
38 1.1 briggs
39 1.1 briggs /*
40 1.1 briggs * fpu_exp.c: defines fpu_etox(), fpu_etoxm1(), fpu_tentox(), and fpu_twotox();
41 1.1 briggs */
42 1.1 briggs
43 1.6 isaki /*
44 1.6 isaki * x^2 x^3 x^4
45 1.6 isaki * exp(x) = 1 + x + --- + --- + --- + ...
46 1.6 isaki * 2! 3! 4!
47 1.6 isaki */
48 1.6 isaki static struct fpn *
49 1.6 isaki fpu_etox_taylor(struct fpemu *fe)
50 1.6 isaki {
51 1.6 isaki struct fpn res;
52 1.6 isaki struct fpn x;
53 1.6 isaki struct fpn s0;
54 1.6 isaki struct fpn *s1;
55 1.6 isaki struct fpn *r;
56 1.6 isaki uint32_t k;
57 1.6 isaki
58 1.6 isaki CPYFPN(&x, &fe->fe_f2);
59 1.6 isaki CPYFPN(&s0, &fe->fe_f2);
60 1.6 isaki
61 1.6 isaki /* res := 1 + x */
62 1.6 isaki fpu_const(&fe->fe_f1, FPU_CONST_1);
63 1.6 isaki r = fpu_add(fe);
64 1.6 isaki CPYFPN(&res, r);
65 1.6 isaki
66 1.6 isaki k = 2;
67 1.6 isaki for (;; k++) {
68 1.6 isaki /* s1 = s0 * x / k */
69 1.6 isaki CPYFPN(&fe->fe_f1, &s0);
70 1.6 isaki CPYFPN(&fe->fe_f2, &x);
71 1.6 isaki r = fpu_mul(fe);
72 1.6 isaki
73 1.6 isaki CPYFPN(&fe->fe_f1, r);
74 1.6 isaki fpu_explode(fe, &fe->fe_f2, FTYPE_LNG, &k);
75 1.6 isaki s1 = fpu_div(fe);
76 1.6 isaki
77 1.6 isaki /* break if s1 is enough small */
78 1.6 isaki if (ISZERO(s1))
79 1.6 isaki break;
80 1.6 isaki if (res.fp_exp - s1->fp_exp >= FP_NMANT)
81 1.6 isaki break;
82 1.6 isaki
83 1.6 isaki /* s0 := s1 for next loop */
84 1.6 isaki CPYFPN(&s0, s1);
85 1.6 isaki
86 1.6 isaki /* res += s1 */
87 1.6 isaki CPYFPN(&fe->fe_f2, s1);
88 1.6 isaki CPYFPN(&fe->fe_f1, &res);
89 1.6 isaki r = fpu_add(fe);
90 1.6 isaki CPYFPN(&res, r);
91 1.6 isaki }
92 1.6 isaki
93 1.6 isaki CPYFPN(&fe->fe_f2, &res);
94 1.6 isaki return &fe->fe_f2;
95 1.6 isaki }
96 1.6 isaki
97 1.6 isaki /*
98 1.6 isaki * exp(x)
99 1.6 isaki */
100 1.1 briggs struct fpn *
101 1.4 dsl fpu_etox(struct fpemu *fe)
102 1.1 briggs {
103 1.6 isaki struct fpn *fp;
104 1.6 isaki
105 1.6 isaki if (ISNAN(&fe->fe_f2))
106 1.6 isaki return &fe->fe_f2;
107 1.6 isaki if (ISINF(&fe->fe_f2)) {
108 1.6 isaki if (fe->fe_f2.fp_sign)
109 1.6 isaki fpu_const(&fe->fe_f2, FPU_CONST_0);
110 1.6 isaki return &fe->fe_f2;
111 1.6 isaki }
112 1.6 isaki
113 1.6 isaki if (fe->fe_f2.fp_sign == 0) {
114 1.6 isaki /* exp(x) */
115 1.6 isaki fp = fpu_etox_taylor(fe);
116 1.6 isaki } else {
117 1.6 isaki /* 1/exp(-x) */
118 1.6 isaki fe->fe_f2.fp_sign = 0;
119 1.6 isaki fp = fpu_etox_taylor(fe);
120 1.6 isaki
121 1.6 isaki CPYFPN(&fe->fe_f2, fp);
122 1.6 isaki fpu_const(&fe->fe_f1, FPU_CONST_1);
123 1.6 isaki fp = fpu_div(fe);
124 1.6 isaki }
125 1.6 isaki
126 1.6 isaki return fp;
127 1.1 briggs }
128 1.1 briggs
129 1.6 isaki /*
130 1.6 isaki * exp(x) - 1
131 1.6 isaki */
132 1.1 briggs struct fpn *
133 1.4 dsl fpu_etoxm1(struct fpemu *fe)
134 1.1 briggs {
135 1.6 isaki struct fpn *fp;
136 1.6 isaki
137 1.6 isaki fp = fpu_etox(fe);
138 1.6 isaki
139 1.6 isaki CPYFPN(&fe->fe_f1, fp);
140 1.6 isaki /* build a 1.0 */
141 1.6 isaki fp = fpu_const(&fe->fe_f2, FPU_CONST_1);
142 1.6 isaki fe->fe_f2.fp_sign = !fe->fe_f2.fp_sign;
143 1.6 isaki /* fp = f2 - 1.0 */
144 1.6 isaki fp = fpu_add(fe);
145 1.6 isaki
146 1.6 isaki return fp;
147 1.1 briggs }
148 1.1 briggs
149 1.6 isaki /*
150 1.6 isaki * 10^x = exp(x * ln10)
151 1.6 isaki */
152 1.1 briggs struct fpn *
153 1.4 dsl fpu_tentox(struct fpemu *fe)
154 1.1 briggs {
155 1.6 isaki struct fpn *fp;
156 1.6 isaki
157 1.6 isaki /* build a ln10 */
158 1.6 isaki fp = fpu_const(&fe->fe_f1, FPU_CONST_LN_10);
159 1.6 isaki /* fp = ln10 * f2 */
160 1.6 isaki fp = fpu_mul(fe);
161 1.6 isaki
162 1.6 isaki /* copy the result to the src opr */
163 1.6 isaki CPYFPN(&fe->fe_f2, fp);
164 1.6 isaki
165 1.6 isaki return fpu_etox(fe);
166 1.1 briggs }
167 1.1 briggs
168 1.6 isaki /*
169 1.6 isaki * 2^x = exp(x * ln2)
170 1.6 isaki */
171 1.1 briggs struct fpn *
172 1.4 dsl fpu_twotox(struct fpemu *fe)
173 1.1 briggs {
174 1.6 isaki struct fpn *fp;
175 1.6 isaki
176 1.6 isaki /* build a ln2 */
177 1.6 isaki fp = fpu_const(&fe->fe_f1, FPU_CONST_LN_2);
178 1.6 isaki /* fp = ln2 * f2 */
179 1.6 isaki fp = fpu_mul(fe);
180 1.6 isaki
181 1.6 isaki /* copy the result to the src opr */
182 1.6 isaki CPYFPN(&fe->fe_f2, fp);
183 1.6 isaki
184 1.6 isaki return fpu_etox(fe);
185 1.1 briggs }
186