|
|
1.1.1.2 ! root 1: /* $NetBSD: fpu_exp.c,v 1.11 2017/01/15 11:56:11 isaki Exp $ */
1.1 root 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_exp.c 10/24/95
32: */
33:
34: #include "fpu_emulate.h"
35:
36: /* The number of items to terminate the Taylor expansion */
37: #define MAX_ITEMS (2000)
38:
39: /*
40: * fpu_exp.c: defines fpu_etox(), fpu_etoxm1(), fpu_tentox(), and fpu_twotox();
41: */
42:
43: /*
44: * x^2 x^3 x^4
45: * exp(x) = 1 + x + --- + --- + --- + ...
46: * 2! 3! 4!
47: */
48: static struct fpn *
49: fpu_etox_taylor(struct fpemu *fe)
50: {
51: struct fpn res;
52: struct fpn x;
53: struct fpn s0;
54: struct fpn *s1;
55: struct fpn *r;
56: uint32_t k;
57:
58: CPYFPN(&x, &fe->fe_f2);
59: CPYFPN(&s0, &fe->fe_f2);
60:
61: /* res := 1 + x */
62: fpu_const(&fe->fe_f1, FPU_CONST_1);
63: r = fpu_add(fe);
64: CPYFPN(&res, r);
65:
66: k = 2;
67: for (; k < MAX_ITEMS; k++) {
68: /* s1 = s0 * x / k */
69: CPYFPN(&fe->fe_f1, &s0);
70: CPYFPN(&fe->fe_f2, &x);
71: r = fpu_mul(fe);
72:
73: CPYFPN(&fe->fe_f1, r);
74: fpu_explode(fe, &fe->fe_f2, FTYPE_LNG, &k);
75: s1 = fpu_div(fe);
76:
77: /* break if s1 is enough small */
78: if (ISZERO(s1))
79: break;
80: if (res.fp_exp - s1->fp_exp >= EXT_FRACBITS)
81: break;
82:
83: /* s0 := s1 for next loop */
84: CPYFPN(&s0, s1);
85:
86: /* res += s1 */
87: CPYFPN(&fe->fe_f2, s1);
88: CPYFPN(&fe->fe_f1, &res);
89: r = fpu_add(fe);
90: CPYFPN(&res, r);
91: }
92:
93: CPYFPN(&fe->fe_f2, &res);
94: return &fe->fe_f2;
95: }
96:
97: /*
98: * exp(x) = 2^k * exp(r) with k = round(x / ln2) and r = x - k * ln2
99: *
100: * Algorithm partially taken from libm, where exp(r) is approximated by a
101: * rational function of r. We use the Taylor expansion instead.
102: */
103: struct fpn *
104: fpu_etox(struct fpemu *fe)
105: {
106: struct fpn x, *fp;
107: int k;
108:
109: if (ISNAN(&fe->fe_f2))
110: return &fe->fe_f2;
111: if (ISINF(&fe->fe_f2)) {
112: if (fe->fe_f2.fp_sign)
113: fpu_const(&fe->fe_f2, FPU_CONST_0);
114: return &fe->fe_f2;
115: }
116: if (ISZERO(&fe->fe_f2)) {
117: fpu_const(&fe->fe_f2, FPU_CONST_1);
118: return &fe->fe_f2;
119: }
120:
121: /*
122: * return inf if x >= 2^14
123: * return +0 if x <= -2^14
124: */
125: if (fe->fe_f2.fp_exp >= 14) {
126: if (fe->fe_f2.fp_sign) {
127: fe->fe_f2.fp_class = FPC_ZERO;
128: fe->fe_f2.fp_sign = 0;
129: } else {
130: fe->fe_f2.fp_class = FPC_INF;
131: }
132: return &fe->fe_f2;
133: }
134:
135: CPYFPN(&x, &fe->fe_f2);
136:
137: /* k = round(x / ln2) */
138: CPYFPN(&fe->fe_f1, &fe->fe_f2);
139: fpu_const(&fe->fe_f2, FPU_CONST_LN_2);
140: fp = fpu_div(fe);
141: CPYFPN(&fe->fe_f2, fp);
142: fp = fpu_int(fe);
143: if (ISZERO(fp)) {
144: /* k = 0 */
145: CPYFPN(&fe->fe_f2, &x);
146: fp = fpu_etox_taylor(fe);
147: return fp;
148: }
149: /* extract k as integer format from fpn format */
150: k = fp->fp_mant[0] >> (FP_LG - fp->fp_exp);
151: if (fp->fp_sign)
152: k *= -1;
153:
154: /* exp(r) = exp(x - k * ln2) */
155: CPYFPN(&fe->fe_f1, fp);
156: fpu_const(&fe->fe_f2, FPU_CONST_LN_2);
157: fp = fpu_mul(fe);
158: fp->fp_sign = !fp->fp_sign;
159: CPYFPN(&fe->fe_f1, fp);
160: CPYFPN(&fe->fe_f2, &x);
161: fp = fpu_add(fe);
162: CPYFPN(&fe->fe_f2, fp);
163: fp = fpu_etox_taylor(fe);
164:
165: /* 2^k */
166: fp->fp_exp += k;
167:
168: return fp;
169: }
170:
171: /*
172: * exp(x) - 1
173: */
174: struct fpn *
175: fpu_etoxm1(struct fpemu *fe)
176: {
177: struct fpn *fp;
178:
179: /* if x is +0/-0, return +0/-0 */
180: if (ISZERO(&fe->fe_f2))
181: return &fe->fe_f2;
182:
183: fp = fpu_etox(fe);
184:
185: CPYFPN(&fe->fe_f1, fp);
186: /* build a 1.0 */
187: fp = fpu_const(&fe->fe_f2, FPU_CONST_1);
188: fe->fe_f2.fp_sign = !fe->fe_f2.fp_sign;
189: /* fp = f2 - 1.0 */
190: fp = fpu_add(fe);
191:
192: return fp;
193: }
194:
195: /*
196: * 10^x = exp(x * ln10)
197: */
198: struct fpn *
199: fpu_tentox(struct fpemu *fe)
200: {
201: struct fpn *fp;
202:
203: /* build a ln10 */
204: fp = fpu_const(&fe->fe_f1, FPU_CONST_LN_10);
205: /* fp = ln10 * f2 */
206: fp = fpu_mul(fe);
207:
208: /* copy the result to the src opr */
209: CPYFPN(&fe->fe_f2, fp);
210:
211: return fpu_etox(fe);
212: }
213:
214: /*
215: * 2^x = exp(x * ln2)
216: */
217: struct fpn *
218: fpu_twotox(struct fpemu *fe)
219: {
220: struct fpn *fp;
221:
222: /* build a ln2 */
223: fp = fpu_const(&fe->fe_f1, FPU_CONST_LN_2);
224: /* fp = ln2 * f2 */
225: fp = fpu_mul(fe);
226:
227: /* copy the result to the src opr */
228: CPYFPN(&fe->fe_f2, fp);
229:
230: return fpu_etox(fe);
231: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.