|
|
1.1 root 1: /*============================================================================
2: This source file is an extension to the SoftFloat IEC/IEEE Floating-point
3: Arithmetic Package, Release 2b, written for Bochs (x86 achitecture simulator)
4: floating point emulation.
5: float_raise(float_flag_invalid)
6: THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has
7: been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
8: RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
9: AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES,
10: COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE
11: EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE
12: INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR
13: OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE.
14:
15: Derivative works are acceptable, even for commercial purposes, so long as
16: (1) the source code for the derivative work includes prominent notice that
17: the work is derivative, and (2) the source code includes prominent notice with
18: these four paragraphs for those parts of this code that are retained.
19: =============================================================================*/
20:
21: /*============================================================================
22: * Written for Bochs (x86 achitecture simulator) by
23: * Stanislav Shwartsman [sshwarts at sourceforge net]
24: * Adapted for lib/softfloat in MESS by Hans Ostermeyer (03/2012)
25: * ==========================================================================*/
26:
27: #define FLOAT128
28:
29: #define USE_estimateDiv128To64
30: #include "mamesf.h"
31: #include "softfloat.h"
32: #include "fpu_constant.h"
33:
34: static const floatx80 floatx80_log10_2 = { 0x3ffd, 0x9a209a84fbcff798U };
35: static const floatx80 floatx80_ln_2 = { 0x3ffe, 0xb17217f7d1cf79acU };
36: static const floatx80 floatx80_one = { 0x3fff, 0x8000000000000000U };
37: static const floatx80 floatx80_default_nan = { floatx80_default_nan_high, floatx80_default_nan_low };
38:
39: #define packFloat_128(zHi, zLo) {(zHi), (zLo)}
40: #define PACK_FLOAT_128(hi,lo) packFloat_128(LIT64(hi),LIT64(lo))
41:
42: #define EXP_BIAS 0x3FFF
43:
44:
45: static const float128 float128_one =
46: packFloat_128(0x3fff000000000000U, 0x0000000000000000U);
47: static const float128 float128_two =
48: packFloat_128(0x4000000000000000U, 0x0000000000000000U);
49:
50: static const float128 float128_ln2inv2 =
51: packFloat_128(0x400071547652b82fU, 0xe1777d0ffda0d23aU);
52:
53: #define SQRT2_HALF_SIG 0xb504f333f9de6484U
54:
55: extern float128 OddPoly(float128 x, float128 *arr, unsigned n);
56:
57: #define L2_ARR_SIZE 9
58:
59: static float128 ln_arr[L2_ARR_SIZE] =
60: {
61: PACK_FLOAT_128(0x3fff000000000000, 0x0000000000000000), /* 1 */
62: PACK_FLOAT_128(0x3ffd555555555555, 0x5555555555555555), /* 3 */
63: PACK_FLOAT_128(0x3ffc999999999999, 0x999999999999999a), /* 5 */
64: PACK_FLOAT_128(0x3ffc249249249249, 0x2492492492492492), /* 7 */
65: PACK_FLOAT_128(0x3ffbc71c71c71c71, 0xc71c71c71c71c71c), /* 9 */
66: PACK_FLOAT_128(0x3ffb745d1745d174, 0x5d1745d1745d1746), /* 11 */
67: PACK_FLOAT_128(0x3ffb3b13b13b13b1, 0x3b13b13b13b13b14), /* 13 */
68: PACK_FLOAT_128(0x3ffb111111111111, 0x1111111111111111), /* 15 */
69: PACK_FLOAT_128(0x3ffae1e1e1e1e1e1, 0xe1e1e1e1e1e1e1e2) /* 17 */
70: };
71:
72: static float128 poly_ln(float128 x1)
73: {
74: /*
75: //
76: // 3 5 7 9 11 13 15
77: // 1+u u u u u u u u
78: // 1/2 ln --- ~ u + --- + --- + --- + --- + ---- + ---- + ---- =
79: // 1-u 3 5 7 9 11 13 15
80: //
81: // 2 4 6 8 10 12 14
82: // u u u u u u u
83: // = u * [ 1 + --- + --- + --- + --- + ---- + ---- + ---- ] =
84: // 3 5 7 9 11 13 15
85: //
86: // 3 3
87: // -- 4k -- 4k+2
88: // p(u) = > C * u q(u) = > C * u
89: // -- 2k -- 2k+1
90: // k=0 k=0
91: //
92: // 1+u 2
93: // 1/2 ln --- ~ u * [ p(u) + u * q(u) ]
94: // 1-u
95: //
96: */
97: return OddPoly(x1, ln_arr, L2_ARR_SIZE);
98: }
99:
100: /* required sqrt(2)/2 < x < sqrt(2) */
101: static float128 poly_l2(float128 x)
102: {
103: /* using float128 for approximation */
104: float128 x_p1 = float128_add(x, float128_one);
105: float128 x_m1 = float128_sub(x, float128_one);
106: x = float128_div(x_m1, x_p1);
107: x = poly_ln(x);
108: x = float128_mul(x, float128_ln2inv2);
109: return x;
110: }
111:
112: static float128 poly_l2p1(float128 x)
113: {
114: /* using float128 for approximation */
115: float128 x_p2 = float128_add(x, float128_two);
116: x = float128_div(x, x_p2);
117: x = poly_ln(x);
118: x = float128_mul(x, float128_ln2inv2);
119: return x;
120: }
121:
122: // =================================================
123: // FYL2X Compute y * log (x)
124: // 2
125: // =================================================
126:
127: //
128: // Uses the following identities:
129: //
130: // 1. ----------------------------------------------------------
131: // ln(x)
132: // log (x) = -------, ln (x*y) = ln(x) + ln(y)
133: // 2 ln(2)
134: //
135: // 2. ----------------------------------------------------------
136: // 1+u x-1
137: // ln (x) = ln -----, when u = -----
138: // 1-u x+1
139: //
140: // 3. ----------------------------------------------------------
141: // 3 5 7 2n+1
142: // 1+u u u u u
143: // ln ----- = 2 [ u + --- + --- + --- + ... + ------ + ... ]
144: // 1-u 3 5 7 2n+1
145: //
146:
147: static floatx80 fyl2x(floatx80 a, floatx80 b)
148: {
149: uint64_t aSig = extractFloatx80Frac(a);
150: int32_t aExp = extractFloatx80Exp(a);
151: int aSign = extractFloatx80Sign(a);
152: uint64_t bSig = extractFloatx80Frac(b);
153: int32_t bExp = extractFloatx80Exp(b);
154: int bSign = extractFloatx80Sign(b);
155:
156: int zSign = bSign ^ 1;
157:
158: if (aExp == 0x7FFF) {
159: if ((uint64_t) (aSig<<1)
160: || ((bExp == 0x7FFF) && (uint64_t) (bSig<<1)))
161: {
162: return propagateFloatx80NaN(a, b);
163: }
164: if (aSign)
165: {
166: invalid:
167: float_raise(float_flag_invalid);
168: return floatx80_default_nan;
169: }
170: else {
171: if (bExp == 0) {
172: if (bSig == 0) goto invalid;
173: float_raise(float_flag_denormal);
174: }
175: return packFloatx80(bSign, 0x7FFF, floatx80_default_infinity_low);
176: }
177: }
178: if (bExp == 0x7FFF)
179: {
180: if ((uint64_t) (bSig<<1)) return propagateFloatx80NaN(a, b);
181: if (aSign && (uint64_t)(aExp | aSig)) goto invalid;
182: if (aSig && (aExp == 0))
183: float_raise(float_flag_denormal);
184: if (aExp < 0x3FFF) {
185: return packFloatx80(zSign, 0x7FFF, floatx80_default_infinity_low);
186: }
187: if (aExp == 0x3FFF && ((uint64_t) (aSig<<1) == 0)) goto invalid;
188: return packFloatx80(bSign, 0x7FFF, floatx80_default_infinity_low);
189: }
190: if (aExp == 0) {
191: if (aSig == 0) {
192: if ((bExp | bSig) == 0) goto invalid;
193: float_raise(float_flag_divbyzero);
194: return packFloatx80(zSign, 0x7FFF, floatx80_default_infinity_low);
195: }
196: if (aSign) goto invalid;
197: float_raise(float_flag_denormal);
198: normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
199: }
200: if (aSign) goto invalid;
201: if (bExp == 0) {
202: if (bSig == 0) {
203: if (aExp < 0x3FFF) return packFloatx80(zSign, 0, 0);
204: return packFloatx80(bSign, 0, 0);
205: }
206: float_raise(float_flag_denormal);
207: normalizeFloatx80Subnormal(bSig, &bExp, &bSig);
208: }
209: if (aExp == 0x3FFF && ((uint64_t) (aSig<<1) == 0))
210: return packFloatx80(bSign, 0, 0);
211:
212: float_raise(float_flag_inexact);
213:
214: int ExpDiff = aExp - 0x3FFF;
215: aExp = 0;
216: if (aSig >= SQRT2_HALF_SIG) {
217: ExpDiff++;
218: aExp--;
219: }
220:
221: /* ******************************** */
222: /* using float128 for approximation */
223: /* ******************************** */
224:
225: uint64_t zSig0, zSig1;
226: shift128Right(aSig<<1, 0, 16, &zSig0, &zSig1);
227: float128 x = packFloat128(0, aExp+0x3FFF, zSig0, zSig1);
228: x = poly_l2(x);
229: x = float128_add(x, int64_to_float128((int64_t) ExpDiff));
230: return floatx80_mul(b, float128_to_floatx80(x));
231: }
232:
233: // =================================================
234: // FYL2XP1 Compute y * log (x + 1)
235: // 2
236: // =================================================
237:
238: //
239: // Uses the following identities:
240: //
241: // 1. ----------------------------------------------------------
242: // ln(x)
243: // log (x) = -------
244: // 2 ln(2)
245: //
246: // 2. ----------------------------------------------------------
247: // 1+u x
248: // ln (x+1) = ln -----, when u = -----
249: // 1-u x+2
250: //
251: // 3. ----------------------------------------------------------
252: // 3 5 7 2n+1
253: // 1+u u u u u
254: // ln ----- = 2 [ u + --- + --- + --- + ... + ------ + ... ]
255: // 1-u 3 5 7 2n+1
256: //
257:
258: floatx80 fyl2xp1(floatx80 a, floatx80 b)
259: {
260: int32_t aExp, bExp;
261: uint64_t aSig, bSig, zSig0, zSig1, zSig2;
262: int aSign, bSign;
263:
264: aSig = extractFloatx80Frac(a);
265: aExp = extractFloatx80Exp(a);
266: aSign = extractFloatx80Sign(a);
267: bSig = extractFloatx80Frac(b);
268: bExp = extractFloatx80Exp(b);
269: bSign = extractFloatx80Sign(b);
270: int zSign = aSign ^ bSign;
271:
272: if (aExp == 0x7FFF) {
273: if ((uint64_t) (aSig<<1)
274: || ((bExp == 0x7FFF) && (uint64_t) (bSig<<1)))
275: {
276: return propagateFloatx80NaN(a, b);
277: }
278: if (aSign)
279: {
280: invalid:
281: float_raise(float_flag_invalid);
282: return floatx80_default_nan;
283: }
284: else {
285: if (bExp == 0) {
286: if (bSig == 0) goto invalid;
287: float_raise(float_flag_denormal);
288: }
289: return packFloatx80(bSign, 0x7FFF, floatx80_default_infinity_low);
290: }
291: }
292: if (bExp == 0x7FFF)
293: {
294: if ((uint64_t) (bSig<<1))
295: return propagateFloatx80NaN(a, b);
296:
297: if (aExp == 0) {
298: if (aSig == 0) goto invalid;
299: float_raise(float_flag_denormal);
300: }
301:
302: return packFloatx80(zSign, 0x7FFF, floatx80_default_infinity_low);
303: }
304: if (aExp == 0) {
305: if (aSig == 0) {
306: if (bSig && (bExp == 0)) float_raise(float_flag_denormal);
307: return packFloatx80(zSign, 0, 0);
308: }
309: float_raise(float_flag_denormal);
310: normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
311: }
312: if (bExp == 0) {
313: if (bSig == 0) return packFloatx80(zSign, 0, 0);
314: float_raise(float_flag_denormal);
315: normalizeFloatx80Subnormal(bSig, &bExp, &bSig);
316: }
317:
318: float_raise(float_flag_inexact);
319:
320: if (aSign && aExp >= 0x3FFF)
321: return a;
322:
323: if (aExp >= 0x3FFC) // big argument
324: {
325: return fyl2x(floatx80_add(a, floatx80_one), b);
326: }
327:
328: // handle tiny argument
329: if (aExp < EXP_BIAS-70)
330: {
331: // first order approximation, return (a*b)/ln(2)
332: int32_t zExp = aExp + FLOAT_LN2INV_EXP - 0x3FFE;
333:
334: mul128By64To192(FLOAT_LN2INV_HI, FLOAT_LN2INV_LO, aSig, &zSig0, &zSig1, &zSig2);
335: if (0 < (int64_t) zSig0) {
336: shortShift128Left(zSig0, zSig1, 1, &zSig0, &zSig1);
337: --zExp;
338: }
339:
340: zExp = zExp + bExp - 0x3FFE;
341: mul128By64To192(zSig0, zSig1, bSig, &zSig0, &zSig1, &zSig2);
342: if (0 < (int64_t) zSig0) {
343: shortShift128Left(zSig0, zSig1, 1, &zSig0, &zSig1);
344: --zExp;
345: }
346:
347: return
348: roundAndPackFloatx80(80, aSign ^ bSign, zExp, zSig0, zSig1);
349: }
350:
351: /* ******************************** */
352: /* using float128 for approximation */
353: /* ******************************** */
354:
355: shift128Right(aSig<<1, 0, 16, &zSig0, &zSig1);
356: float128 x = packFloat128(aSign, aExp, zSig0, zSig1);
357: x = poly_l2p1(x);
358: return floatx80_mul(b, float128_to_floatx80(x));
359: }
360:
361: floatx80 floatx80_flognp1(floatx80 a)
362: {
363: return fyl2xp1(a, floatx80_ln_2);
364: }
365:
366: floatx80 floatx80_flogn(floatx80 a)
367: {
368: return fyl2x(a, floatx80_ln_2);
369: }
370:
371: floatx80 floatx80_flog2(floatx80 a)
372: {
373: return fyl2x(a, floatx80_one);
374: }
375:
376: floatx80 floatx80_flog10(floatx80 a)
377: {
378: return fyl2x(a, floatx80_log10_2);
379: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.