|
|
1.1.1.8 root 1: /*
2: * QEMU float support
3: *
4: * Derived from SoftFloat.
5: */
1.1 root 6:
7: /*============================================================================
8:
9: This C source file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic
10: Package, Release 2b.
11:
12: Written by John R. Hauser. This work was made possible in part by the
13: International Computer Science Institute, located at Suite 600, 1947 Center
14: Street, Berkeley, California 94704. Funding was partially provided by the
15: National Science Foundation under grant MIP-9311980. The original version
16: of this code was written as part of a project to build a fixed-point vector
17: processor in collaboration with the University of California at Berkeley,
18: overseen by Profs. Nelson Morgan and John Wawrzynek. More information
19: is available through the Web page `http://www.cs.berkeley.edu/~jhauser/
20: arithmetic/SoftFloat.html'.
21:
22: THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has
23: been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
24: RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
25: AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES,
26: COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE
27: EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE
28: INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR
29: OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE.
30:
31: Derivative works are acceptable, even for commercial purposes, so long as
32: (1) the source code for the derivative work includes prominent notice that
33: the work is derivative, and (2) the source code includes prominent notice with
34: these four paragraphs for those parts of this code that are retained.
35:
36: =============================================================================*/
37:
1.1.1.9 root 38: /* softfloat (and in particular the code in softfloat-specialize.h) is
39: * target-dependent and needs the TARGET_* macros.
40: */
41: #include "config.h"
42:
1.1 root 43: #include "softfloat.h"
44:
45: /*----------------------------------------------------------------------------
46: | Primitive arithmetic functions, including multi-word arithmetic, and
47: | division and square root approximations. (Can be specialized to target if
48: | desired.)
49: *----------------------------------------------------------------------------*/
50: #include "softfloat-macros.h"
51:
52: /*----------------------------------------------------------------------------
53: | Functions and definitions to determine: (1) whether tininess for underflow
54: | is detected before or after rounding by default, (2) what (if anything)
55: | happens when exceptions are raised, (3) how signaling NaNs are distinguished
56: | from quiet NaNs, (4) the default generated quiet NaNs, and (5) how NaNs
57: | are propagated from function inputs to output. These details are target-
58: | specific.
59: *----------------------------------------------------------------------------*/
60: #include "softfloat-specialize.h"
61:
62: void set_float_rounding_mode(int val STATUS_PARAM)
63: {
64: STATUS(float_rounding_mode) = val;
65: }
66:
67: void set_float_exception_flags(int val STATUS_PARAM)
68: {
69: STATUS(float_exception_flags) = val;
70: }
71:
72: void set_floatx80_rounding_precision(int val STATUS_PARAM)
73: {
74: STATUS(floatx80_rounding_precision) = val;
75: }
1.1.1.8 root 76:
77: /*----------------------------------------------------------------------------
78: | Returns the fraction bits of the half-precision floating-point value `a'.
79: *----------------------------------------------------------------------------*/
80:
81: INLINE uint32_t extractFloat16Frac(float16 a)
82: {
83: return float16_val(a) & 0x3ff;
84: }
85:
86: /*----------------------------------------------------------------------------
87: | Returns the exponent bits of the half-precision floating-point value `a'.
88: *----------------------------------------------------------------------------*/
89:
1.1.1.10! root 90: INLINE int_fast16_t extractFloat16Exp(float16 a)
1.1.1.8 root 91: {
92: return (float16_val(a) >> 10) & 0x1f;
93: }
94:
95: /*----------------------------------------------------------------------------
96: | Returns the sign bit of the single-precision floating-point value `a'.
97: *----------------------------------------------------------------------------*/
98:
99: INLINE flag extractFloat16Sign(float16 a)
100: {
101: return float16_val(a)>>15;
102: }
1.1 root 103:
104: /*----------------------------------------------------------------------------
105: | Takes a 64-bit fixed-point value `absZ' with binary point between bits 6
106: | and 7, and returns the properly rounded 32-bit integer corresponding to the
107: | input. If `zSign' is 1, the input is negated before being converted to an
108: | integer. Bit 63 of `absZ' must be zero. Ordinarily, the fixed-point input
109: | is simply rounded to an integer, with the inexact exception raised if the
110: | input cannot be represented exactly as an integer. However, if the fixed-
111: | point input is too large, the invalid exception is raised and the largest
112: | positive or negative integer is returned.
113: *----------------------------------------------------------------------------*/
114:
1.1.1.8 root 115: static int32 roundAndPackInt32( flag zSign, uint64_t absZ STATUS_PARAM)
1.1 root 116: {
117: int8 roundingMode;
118: flag roundNearestEven;
119: int8 roundIncrement, roundBits;
1.1.1.10! root 120: int32_t z;
1.1 root 121:
122: roundingMode = STATUS(float_rounding_mode);
123: roundNearestEven = ( roundingMode == float_round_nearest_even );
124: roundIncrement = 0x40;
125: if ( ! roundNearestEven ) {
126: if ( roundingMode == float_round_to_zero ) {
127: roundIncrement = 0;
128: }
129: else {
130: roundIncrement = 0x7F;
131: if ( zSign ) {
132: if ( roundingMode == float_round_up ) roundIncrement = 0;
133: }
134: else {
135: if ( roundingMode == float_round_down ) roundIncrement = 0;
136: }
137: }
138: }
139: roundBits = absZ & 0x7F;
140: absZ = ( absZ + roundIncrement )>>7;
141: absZ &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven );
142: z = absZ;
143: if ( zSign ) z = - z;
144: if ( ( absZ>>32 ) || ( z && ( ( z < 0 ) ^ zSign ) ) ) {
145: float_raise( float_flag_invalid STATUS_VAR);
1.1.1.8 root 146: return zSign ? (int32_t) 0x80000000 : 0x7FFFFFFF;
1.1 root 147: }
148: if ( roundBits ) STATUS(float_exception_flags) |= float_flag_inexact;
149: return z;
150:
151: }
152:
153: /*----------------------------------------------------------------------------
154: | Takes the 128-bit fixed-point value formed by concatenating `absZ0' and
155: | `absZ1', with binary point between bits 63 and 64 (between the input words),
156: | and returns the properly rounded 64-bit integer corresponding to the input.
157: | If `zSign' is 1, the input is negated before being converted to an integer.
158: | Ordinarily, the fixed-point input is simply rounded to an integer, with
159: | the inexact exception raised if the input cannot be represented exactly as
160: | an integer. However, if the fixed-point input is too large, the invalid
161: | exception is raised and the largest positive or negative integer is
162: | returned.
163: *----------------------------------------------------------------------------*/
164:
1.1.1.8 root 165: static int64 roundAndPackInt64( flag zSign, uint64_t absZ0, uint64_t absZ1 STATUS_PARAM)
1.1 root 166: {
167: int8 roundingMode;
168: flag roundNearestEven, increment;
1.1.1.10! root 169: int64_t z;
1.1 root 170:
171: roundingMode = STATUS(float_rounding_mode);
172: roundNearestEven = ( roundingMode == float_round_nearest_even );
1.1.1.8 root 173: increment = ( (int64_t) absZ1 < 0 );
1.1 root 174: if ( ! roundNearestEven ) {
175: if ( roundingMode == float_round_to_zero ) {
176: increment = 0;
177: }
178: else {
179: if ( zSign ) {
180: increment = ( roundingMode == float_round_down ) && absZ1;
181: }
182: else {
183: increment = ( roundingMode == float_round_up ) && absZ1;
184: }
185: }
186: }
187: if ( increment ) {
188: ++absZ0;
189: if ( absZ0 == 0 ) goto overflow;
1.1.1.8 root 190: absZ0 &= ~ ( ( (uint64_t) ( absZ1<<1 ) == 0 ) & roundNearestEven );
1.1 root 191: }
192: z = absZ0;
193: if ( zSign ) z = - z;
194: if ( z && ( ( z < 0 ) ^ zSign ) ) {
195: overflow:
196: float_raise( float_flag_invalid STATUS_VAR);
197: return
1.1.1.8 root 198: zSign ? (int64_t) LIT64( 0x8000000000000000 )
1.1 root 199: : LIT64( 0x7FFFFFFFFFFFFFFF );
200: }
201: if ( absZ1 ) STATUS(float_exception_flags) |= float_flag_inexact;
202: return z;
203:
204: }
205:
206: /*----------------------------------------------------------------------------
207: | Returns the fraction bits of the single-precision floating-point value `a'.
208: *----------------------------------------------------------------------------*/
209:
1.1.1.8 root 210: INLINE uint32_t extractFloat32Frac( float32 a )
1.1 root 211: {
212:
1.1.1.3 root 213: return float32_val(a) & 0x007FFFFF;
1.1 root 214:
215: }
216:
217: /*----------------------------------------------------------------------------
218: | Returns the exponent bits of the single-precision floating-point value `a'.
219: *----------------------------------------------------------------------------*/
220:
1.1.1.10! root 221: INLINE int_fast16_t extractFloat32Exp(float32 a)
1.1 root 222: {
223:
1.1.1.3 root 224: return ( float32_val(a)>>23 ) & 0xFF;
1.1 root 225:
226: }
227:
228: /*----------------------------------------------------------------------------
229: | Returns the sign bit of the single-precision floating-point value `a'.
230: *----------------------------------------------------------------------------*/
231:
232: INLINE flag extractFloat32Sign( float32 a )
233: {
234:
1.1.1.3 root 235: return float32_val(a)>>31;
1.1 root 236:
237: }
238:
239: /*----------------------------------------------------------------------------
1.1.1.7 root 240: | If `a' is denormal and we are in flush-to-zero mode then set the
241: | input-denormal exception and return zero. Otherwise just return the value.
242: *----------------------------------------------------------------------------*/
243: static float32 float32_squash_input_denormal(float32 a STATUS_PARAM)
244: {
245: if (STATUS(flush_inputs_to_zero)) {
246: if (extractFloat32Exp(a) == 0 && extractFloat32Frac(a) != 0) {
247: float_raise(float_flag_input_denormal STATUS_VAR);
248: return make_float32(float32_val(a) & 0x80000000);
249: }
250: }
251: return a;
252: }
253:
254: /*----------------------------------------------------------------------------
1.1 root 255: | Normalizes the subnormal single-precision floating-point value represented
256: | by the denormalized significand `aSig'. The normalized exponent and
257: | significand are stored at the locations pointed to by `zExpPtr' and
258: | `zSigPtr', respectively.
259: *----------------------------------------------------------------------------*/
260:
261: static void
1.1.1.10! root 262: normalizeFloat32Subnormal(uint32_t aSig, int_fast16_t *zExpPtr, uint32_t *zSigPtr)
1.1 root 263: {
264: int8 shiftCount;
265:
266: shiftCount = countLeadingZeros32( aSig ) - 8;
267: *zSigPtr = aSig<<shiftCount;
268: *zExpPtr = 1 - shiftCount;
269:
270: }
271:
272: /*----------------------------------------------------------------------------
273: | Packs the sign `zSign', exponent `zExp', and significand `zSig' into a
274: | single-precision floating-point value, returning the result. After being
275: | shifted into the proper positions, the three fields are simply added
276: | together to form the result. This means that any integer portion of `zSig'
277: | will be added into the exponent. Since a properly normalized significand
278: | will have an integer portion equal to 1, the `zExp' input should be 1 less
279: | than the desired result exponent whenever `zSig' is a complete, normalized
280: | significand.
281: *----------------------------------------------------------------------------*/
282:
1.1.1.10! root 283: INLINE float32 packFloat32(flag zSign, int_fast16_t zExp, uint32_t zSig)
1.1 root 284: {
285:
1.1.1.3 root 286: return make_float32(
1.1.1.8 root 287: ( ( (uint32_t) zSign )<<31 ) + ( ( (uint32_t) zExp )<<23 ) + zSig);
1.1 root 288:
289: }
290:
291: /*----------------------------------------------------------------------------
292: | Takes an abstract floating-point value having sign `zSign', exponent `zExp',
293: | and significand `zSig', and returns the proper single-precision floating-
294: | point value corresponding to the abstract input. Ordinarily, the abstract
295: | value is simply rounded and packed into the single-precision format, with
296: | the inexact exception raised if the abstract input cannot be represented
297: | exactly. However, if the abstract value is too large, the overflow and
298: | inexact exceptions are raised and an infinity or maximal finite value is
299: | returned. If the abstract value is too small, the input value is rounded to
300: | a subnormal number, and the underflow and inexact exceptions are raised if
301: | the abstract input cannot be represented exactly as a subnormal single-
302: | precision floating-point number.
303: | The input significand `zSig' has its binary point between bits 30
304: | and 29, which is 7 bits to the left of the usual location. This shifted
305: | significand must be normalized or smaller. If `zSig' is not normalized,
306: | `zExp' must be 0; in that case, the result returned is a subnormal number,
307: | and it must not require rounding. In the usual case that `zSig' is
308: | normalized, `zExp' must be 1 less than the ``true'' floating-point exponent.
309: | The handling of underflow and overflow follows the IEC/IEEE Standard for
310: | Binary Floating-Point Arithmetic.
311: *----------------------------------------------------------------------------*/
312:
1.1.1.10! root 313: static float32 roundAndPackFloat32(flag zSign, int_fast16_t zExp, uint32_t zSig STATUS_PARAM)
1.1 root 314: {
315: int8 roundingMode;
316: flag roundNearestEven;
317: int8 roundIncrement, roundBits;
318: flag isTiny;
319:
320: roundingMode = STATUS(float_rounding_mode);
321: roundNearestEven = ( roundingMode == float_round_nearest_even );
322: roundIncrement = 0x40;
323: if ( ! roundNearestEven ) {
324: if ( roundingMode == float_round_to_zero ) {
325: roundIncrement = 0;
326: }
327: else {
328: roundIncrement = 0x7F;
329: if ( zSign ) {
330: if ( roundingMode == float_round_up ) roundIncrement = 0;
331: }
332: else {
333: if ( roundingMode == float_round_down ) roundIncrement = 0;
334: }
335: }
336: }
337: roundBits = zSig & 0x7F;
1.1.1.8 root 338: if ( 0xFD <= (uint16_t) zExp ) {
1.1 root 339: if ( ( 0xFD < zExp )
340: || ( ( zExp == 0xFD )
1.1.1.8 root 341: && ( (int32_t) ( zSig + roundIncrement ) < 0 ) )
1.1 root 342: ) {
343: float_raise( float_flag_overflow | float_flag_inexact STATUS_VAR);
1.1.1.3 root 344: return packFloat32( zSign, 0xFF, - ( roundIncrement == 0 ));
1.1 root 345: }
346: if ( zExp < 0 ) {
1.1.1.8 root 347: if (STATUS(flush_to_zero)) {
348: float_raise(float_flag_output_denormal STATUS_VAR);
349: return packFloat32(zSign, 0, 0);
350: }
1.1 root 351: isTiny =
352: ( STATUS(float_detect_tininess) == float_tininess_before_rounding )
353: || ( zExp < -1 )
354: || ( zSig + roundIncrement < 0x80000000 );
355: shift32RightJamming( zSig, - zExp, &zSig );
356: zExp = 0;
357: roundBits = zSig & 0x7F;
358: if ( isTiny && roundBits ) float_raise( float_flag_underflow STATUS_VAR);
359: }
360: }
361: if ( roundBits ) STATUS(float_exception_flags) |= float_flag_inexact;
362: zSig = ( zSig + roundIncrement )>>7;
363: zSig &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven );
364: if ( zSig == 0 ) zExp = 0;
365: return packFloat32( zSign, zExp, zSig );
366:
367: }
368:
369: /*----------------------------------------------------------------------------
370: | Takes an abstract floating-point value having sign `zSign', exponent `zExp',
371: | and significand `zSig', and returns the proper single-precision floating-
372: | point value corresponding to the abstract input. This routine is just like
373: | `roundAndPackFloat32' except that `zSig' does not have to be normalized.
374: | Bit 31 of `zSig' must be zero, and `zExp' must be 1 less than the ``true''
375: | floating-point exponent.
376: *----------------------------------------------------------------------------*/
377:
378: static float32
1.1.1.10! root 379: normalizeRoundAndPackFloat32(flag zSign, int_fast16_t zExp, uint32_t zSig STATUS_PARAM)
1.1 root 380: {
381: int8 shiftCount;
382:
383: shiftCount = countLeadingZeros32( zSig ) - 1;
384: return roundAndPackFloat32( zSign, zExp - shiftCount, zSig<<shiftCount STATUS_VAR);
385:
386: }
387:
388: /*----------------------------------------------------------------------------
389: | Returns the fraction bits of the double-precision floating-point value `a'.
390: *----------------------------------------------------------------------------*/
391:
1.1.1.8 root 392: INLINE uint64_t extractFloat64Frac( float64 a )
1.1 root 393: {
394:
1.1.1.3 root 395: return float64_val(a) & LIT64( 0x000FFFFFFFFFFFFF );
1.1 root 396:
397: }
398:
399: /*----------------------------------------------------------------------------
400: | Returns the exponent bits of the double-precision floating-point value `a'.
401: *----------------------------------------------------------------------------*/
402:
1.1.1.10! root 403: INLINE int_fast16_t extractFloat64Exp(float64 a)
1.1 root 404: {
405:
1.1.1.3 root 406: return ( float64_val(a)>>52 ) & 0x7FF;
1.1 root 407:
408: }
409:
410: /*----------------------------------------------------------------------------
411: | Returns the sign bit of the double-precision floating-point value `a'.
412: *----------------------------------------------------------------------------*/
413:
414: INLINE flag extractFloat64Sign( float64 a )
415: {
416:
1.1.1.3 root 417: return float64_val(a)>>63;
1.1 root 418:
419: }
420:
421: /*----------------------------------------------------------------------------
1.1.1.7 root 422: | If `a' is denormal and we are in flush-to-zero mode then set the
423: | input-denormal exception and return zero. Otherwise just return the value.
424: *----------------------------------------------------------------------------*/
425: static float64 float64_squash_input_denormal(float64 a STATUS_PARAM)
426: {
427: if (STATUS(flush_inputs_to_zero)) {
428: if (extractFloat64Exp(a) == 0 && extractFloat64Frac(a) != 0) {
429: float_raise(float_flag_input_denormal STATUS_VAR);
430: return make_float64(float64_val(a) & (1ULL << 63));
431: }
432: }
433: return a;
434: }
435:
436: /*----------------------------------------------------------------------------
1.1 root 437: | Normalizes the subnormal double-precision floating-point value represented
438: | by the denormalized significand `aSig'. The normalized exponent and
439: | significand are stored at the locations pointed to by `zExpPtr' and
440: | `zSigPtr', respectively.
441: *----------------------------------------------------------------------------*/
442:
443: static void
1.1.1.10! root 444: normalizeFloat64Subnormal(uint64_t aSig, int_fast16_t *zExpPtr, uint64_t *zSigPtr)
1.1 root 445: {
446: int8 shiftCount;
447:
448: shiftCount = countLeadingZeros64( aSig ) - 11;
449: *zSigPtr = aSig<<shiftCount;
450: *zExpPtr = 1 - shiftCount;
451:
452: }
453:
454: /*----------------------------------------------------------------------------
455: | Packs the sign `zSign', exponent `zExp', and significand `zSig' into a
456: | double-precision floating-point value, returning the result. After being
457: | shifted into the proper positions, the three fields are simply added
458: | together to form the result. This means that any integer portion of `zSig'
459: | will be added into the exponent. Since a properly normalized significand
460: | will have an integer portion equal to 1, the `zExp' input should be 1 less
461: | than the desired result exponent whenever `zSig' is a complete, normalized
462: | significand.
463: *----------------------------------------------------------------------------*/
464:
1.1.1.10! root 465: INLINE float64 packFloat64(flag zSign, int_fast16_t zExp, uint64_t zSig)
1.1 root 466: {
467:
1.1.1.3 root 468: return make_float64(
1.1.1.8 root 469: ( ( (uint64_t) zSign )<<63 ) + ( ( (uint64_t) zExp )<<52 ) + zSig);
1.1 root 470:
471: }
472:
473: /*----------------------------------------------------------------------------
474: | Takes an abstract floating-point value having sign `zSign', exponent `zExp',
475: | and significand `zSig', and returns the proper double-precision floating-
476: | point value corresponding to the abstract input. Ordinarily, the abstract
477: | value is simply rounded and packed into the double-precision format, with
478: | the inexact exception raised if the abstract input cannot be represented
479: | exactly. However, if the abstract value is too large, the overflow and
480: | inexact exceptions are raised and an infinity or maximal finite value is
481: | returned. If the abstract value is too small, the input value is rounded
482: | to a subnormal number, and the underflow and inexact exceptions are raised
483: | if the abstract input cannot be represented exactly as a subnormal double-
484: | precision floating-point number.
485: | The input significand `zSig' has its binary point between bits 62
486: | and 61, which is 10 bits to the left of the usual location. This shifted
487: | significand must be normalized or smaller. If `zSig' is not normalized,
488: | `zExp' must be 0; in that case, the result returned is a subnormal number,
489: | and it must not require rounding. In the usual case that `zSig' is
490: | normalized, `zExp' must be 1 less than the ``true'' floating-point exponent.
491: | The handling of underflow and overflow follows the IEC/IEEE Standard for
492: | Binary Floating-Point Arithmetic.
493: *----------------------------------------------------------------------------*/
494:
1.1.1.10! root 495: static float64 roundAndPackFloat64(flag zSign, int_fast16_t zExp, uint64_t zSig STATUS_PARAM)
1.1 root 496: {
497: int8 roundingMode;
498: flag roundNearestEven;
1.1.1.10! root 499: int_fast16_t roundIncrement, roundBits;
1.1 root 500: flag isTiny;
501:
502: roundingMode = STATUS(float_rounding_mode);
503: roundNearestEven = ( roundingMode == float_round_nearest_even );
504: roundIncrement = 0x200;
505: if ( ! roundNearestEven ) {
506: if ( roundingMode == float_round_to_zero ) {
507: roundIncrement = 0;
508: }
509: else {
510: roundIncrement = 0x3FF;
511: if ( zSign ) {
512: if ( roundingMode == float_round_up ) roundIncrement = 0;
513: }
514: else {
515: if ( roundingMode == float_round_down ) roundIncrement = 0;
516: }
517: }
518: }
519: roundBits = zSig & 0x3FF;
1.1.1.8 root 520: if ( 0x7FD <= (uint16_t) zExp ) {
1.1 root 521: if ( ( 0x7FD < zExp )
522: || ( ( zExp == 0x7FD )
1.1.1.8 root 523: && ( (int64_t) ( zSig + roundIncrement ) < 0 ) )
1.1 root 524: ) {
525: float_raise( float_flag_overflow | float_flag_inexact STATUS_VAR);
1.1.1.3 root 526: return packFloat64( zSign, 0x7FF, - ( roundIncrement == 0 ));
1.1 root 527: }
528: if ( zExp < 0 ) {
1.1.1.8 root 529: if (STATUS(flush_to_zero)) {
530: float_raise(float_flag_output_denormal STATUS_VAR);
531: return packFloat64(zSign, 0, 0);
532: }
1.1 root 533: isTiny =
534: ( STATUS(float_detect_tininess) == float_tininess_before_rounding )
535: || ( zExp < -1 )
536: || ( zSig + roundIncrement < LIT64( 0x8000000000000000 ) );
537: shift64RightJamming( zSig, - zExp, &zSig );
538: zExp = 0;
539: roundBits = zSig & 0x3FF;
540: if ( isTiny && roundBits ) float_raise( float_flag_underflow STATUS_VAR);
541: }
542: }
543: if ( roundBits ) STATUS(float_exception_flags) |= float_flag_inexact;
544: zSig = ( zSig + roundIncrement )>>10;
545: zSig &= ~ ( ( ( roundBits ^ 0x200 ) == 0 ) & roundNearestEven );
546: if ( zSig == 0 ) zExp = 0;
547: return packFloat64( zSign, zExp, zSig );
548:
549: }
550:
551: /*----------------------------------------------------------------------------
552: | Takes an abstract floating-point value having sign `zSign', exponent `zExp',
553: | and significand `zSig', and returns the proper double-precision floating-
554: | point value corresponding to the abstract input. This routine is just like
555: | `roundAndPackFloat64' except that `zSig' does not have to be normalized.
556: | Bit 63 of `zSig' must be zero, and `zExp' must be 1 less than the ``true''
557: | floating-point exponent.
558: *----------------------------------------------------------------------------*/
559:
560: static float64
1.1.1.10! root 561: normalizeRoundAndPackFloat64(flag zSign, int_fast16_t zExp, uint64_t zSig STATUS_PARAM)
1.1 root 562: {
563: int8 shiftCount;
564:
565: shiftCount = countLeadingZeros64( zSig ) - 1;
566: return roundAndPackFloat64( zSign, zExp - shiftCount, zSig<<shiftCount STATUS_VAR);
567:
568: }
569:
570: /*----------------------------------------------------------------------------
571: | Returns the fraction bits of the extended double-precision floating-point
572: | value `a'.
573: *----------------------------------------------------------------------------*/
574:
1.1.1.8 root 575: INLINE uint64_t extractFloatx80Frac( floatx80 a )
1.1 root 576: {
577:
578: return a.low;
579:
580: }
581:
582: /*----------------------------------------------------------------------------
583: | Returns the exponent bits of the extended double-precision floating-point
584: | value `a'.
585: *----------------------------------------------------------------------------*/
586:
587: INLINE int32 extractFloatx80Exp( floatx80 a )
588: {
589:
590: return a.high & 0x7FFF;
591:
592: }
593:
594: /*----------------------------------------------------------------------------
595: | Returns the sign bit of the extended double-precision floating-point value
596: | `a'.
597: *----------------------------------------------------------------------------*/
598:
599: INLINE flag extractFloatx80Sign( floatx80 a )
600: {
601:
602: return a.high>>15;
603:
604: }
605:
606: /*----------------------------------------------------------------------------
607: | Normalizes the subnormal extended double-precision floating-point value
608: | represented by the denormalized significand `aSig'. The normalized exponent
609: | and significand are stored at the locations pointed to by `zExpPtr' and
610: | `zSigPtr', respectively.
611: *----------------------------------------------------------------------------*/
612:
613: static void
1.1.1.8 root 614: normalizeFloatx80Subnormal( uint64_t aSig, int32 *zExpPtr, uint64_t *zSigPtr )
1.1 root 615: {
616: int8 shiftCount;
617:
618: shiftCount = countLeadingZeros64( aSig );
619: *zSigPtr = aSig<<shiftCount;
620: *zExpPtr = 1 - shiftCount;
621:
622: }
623:
624: /*----------------------------------------------------------------------------
625: | Packs the sign `zSign', exponent `zExp', and significand `zSig' into an
626: | extended double-precision floating-point value, returning the result.
627: *----------------------------------------------------------------------------*/
628:
1.1.1.8 root 629: INLINE floatx80 packFloatx80( flag zSign, int32 zExp, uint64_t zSig )
1.1 root 630: {
631: floatx80 z;
632:
633: z.low = zSig;
1.1.1.8 root 634: z.high = ( ( (uint16_t) zSign )<<15 ) + zExp;
1.1 root 635: return z;
636:
637: }
638:
639: /*----------------------------------------------------------------------------
640: | Takes an abstract floating-point value having sign `zSign', exponent `zExp',
641: | and extended significand formed by the concatenation of `zSig0' and `zSig1',
642: | and returns the proper extended double-precision floating-point value
643: | corresponding to the abstract input. Ordinarily, the abstract value is
644: | rounded and packed into the extended double-precision format, with the
645: | inexact exception raised if the abstract input cannot be represented
646: | exactly. However, if the abstract value is too large, the overflow and
647: | inexact exceptions are raised and an infinity or maximal finite value is
648: | returned. If the abstract value is too small, the input value is rounded to
649: | a subnormal number, and the underflow and inexact exceptions are raised if
650: | the abstract input cannot be represented exactly as a subnormal extended
651: | double-precision floating-point number.
652: | If `roundingPrecision' is 32 or 64, the result is rounded to the same
653: | number of bits as single or double precision, respectively. Otherwise, the
654: | result is rounded to the full precision of the extended double-precision
655: | format.
656: | The input significand must be normalized or smaller. If the input
657: | significand is not normalized, `zExp' must be 0; in that case, the result
658: | returned is a subnormal number, and it must not require rounding. The
659: | handling of underflow and overflow follows the IEC/IEEE Standard for Binary
660: | Floating-Point Arithmetic.
661: *----------------------------------------------------------------------------*/
662:
663: static floatx80
664: roundAndPackFloatx80(
1.1.1.8 root 665: int8 roundingPrecision, flag zSign, int32 zExp, uint64_t zSig0, uint64_t zSig1
1.1 root 666: STATUS_PARAM)
667: {
668: int8 roundingMode;
669: flag roundNearestEven, increment, isTiny;
670: int64 roundIncrement, roundMask, roundBits;
671:
672: roundingMode = STATUS(float_rounding_mode);
673: roundNearestEven = ( roundingMode == float_round_nearest_even );
674: if ( roundingPrecision == 80 ) goto precision80;
675: if ( roundingPrecision == 64 ) {
676: roundIncrement = LIT64( 0x0000000000000400 );
677: roundMask = LIT64( 0x00000000000007FF );
678: }
679: else if ( roundingPrecision == 32 ) {
680: roundIncrement = LIT64( 0x0000008000000000 );
681: roundMask = LIT64( 0x000000FFFFFFFFFF );
682: }
683: else {
684: goto precision80;
685: }
686: zSig0 |= ( zSig1 != 0 );
687: if ( ! roundNearestEven ) {
688: if ( roundingMode == float_round_to_zero ) {
689: roundIncrement = 0;
690: }
691: else {
692: roundIncrement = roundMask;
693: if ( zSign ) {
694: if ( roundingMode == float_round_up ) roundIncrement = 0;
695: }
696: else {
697: if ( roundingMode == float_round_down ) roundIncrement = 0;
698: }
699: }
700: }
701: roundBits = zSig0 & roundMask;
1.1.1.8 root 702: if ( 0x7FFD <= (uint32_t) ( zExp - 1 ) ) {
1.1 root 703: if ( ( 0x7FFE < zExp )
704: || ( ( zExp == 0x7FFE ) && ( zSig0 + roundIncrement < zSig0 ) )
705: ) {
706: goto overflow;
707: }
708: if ( zExp <= 0 ) {
1.1.1.8 root 709: if (STATUS(flush_to_zero)) {
710: float_raise(float_flag_output_denormal STATUS_VAR);
711: return packFloatx80(zSign, 0, 0);
712: }
1.1 root 713: isTiny =
714: ( STATUS(float_detect_tininess) == float_tininess_before_rounding )
715: || ( zExp < 0 )
716: || ( zSig0 <= zSig0 + roundIncrement );
717: shift64RightJamming( zSig0, 1 - zExp, &zSig0 );
718: zExp = 0;
719: roundBits = zSig0 & roundMask;
720: if ( isTiny && roundBits ) float_raise( float_flag_underflow STATUS_VAR);
721: if ( roundBits ) STATUS(float_exception_flags) |= float_flag_inexact;
722: zSig0 += roundIncrement;
1.1.1.8 root 723: if ( (int64_t) zSig0 < 0 ) zExp = 1;
1.1 root 724: roundIncrement = roundMask + 1;
725: if ( roundNearestEven && ( roundBits<<1 == roundIncrement ) ) {
726: roundMask |= roundIncrement;
727: }
728: zSig0 &= ~ roundMask;
729: return packFloatx80( zSign, zExp, zSig0 );
730: }
731: }
732: if ( roundBits ) STATUS(float_exception_flags) |= float_flag_inexact;
733: zSig0 += roundIncrement;
734: if ( zSig0 < roundIncrement ) {
735: ++zExp;
736: zSig0 = LIT64( 0x8000000000000000 );
737: }
738: roundIncrement = roundMask + 1;
739: if ( roundNearestEven && ( roundBits<<1 == roundIncrement ) ) {
740: roundMask |= roundIncrement;
741: }
742: zSig0 &= ~ roundMask;
743: if ( zSig0 == 0 ) zExp = 0;
744: return packFloatx80( zSign, zExp, zSig0 );
745: precision80:
1.1.1.8 root 746: increment = ( (int64_t) zSig1 < 0 );
1.1 root 747: if ( ! roundNearestEven ) {
748: if ( roundingMode == float_round_to_zero ) {
749: increment = 0;
750: }
751: else {
752: if ( zSign ) {
753: increment = ( roundingMode == float_round_down ) && zSig1;
754: }
755: else {
756: increment = ( roundingMode == float_round_up ) && zSig1;
757: }
758: }
759: }
1.1.1.8 root 760: if ( 0x7FFD <= (uint32_t) ( zExp - 1 ) ) {
1.1 root 761: if ( ( 0x7FFE < zExp )
762: || ( ( zExp == 0x7FFE )
763: && ( zSig0 == LIT64( 0xFFFFFFFFFFFFFFFF ) )
764: && increment
765: )
766: ) {
767: roundMask = 0;
768: overflow:
769: float_raise( float_flag_overflow | float_flag_inexact STATUS_VAR);
770: if ( ( roundingMode == float_round_to_zero )
771: || ( zSign && ( roundingMode == float_round_up ) )
772: || ( ! zSign && ( roundingMode == float_round_down ) )
773: ) {
774: return packFloatx80( zSign, 0x7FFE, ~ roundMask );
775: }
776: return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
777: }
778: if ( zExp <= 0 ) {
779: isTiny =
780: ( STATUS(float_detect_tininess) == float_tininess_before_rounding )
781: || ( zExp < 0 )
782: || ! increment
783: || ( zSig0 < LIT64( 0xFFFFFFFFFFFFFFFF ) );
784: shift64ExtraRightJamming( zSig0, zSig1, 1 - zExp, &zSig0, &zSig1 );
785: zExp = 0;
786: if ( isTiny && zSig1 ) float_raise( float_flag_underflow STATUS_VAR);
787: if ( zSig1 ) STATUS(float_exception_flags) |= float_flag_inexact;
788: if ( roundNearestEven ) {
1.1.1.8 root 789: increment = ( (int64_t) zSig1 < 0 );
1.1 root 790: }
791: else {
792: if ( zSign ) {
793: increment = ( roundingMode == float_round_down ) && zSig1;
794: }
795: else {
796: increment = ( roundingMode == float_round_up ) && zSig1;
797: }
798: }
799: if ( increment ) {
800: ++zSig0;
801: zSig0 &=
1.1.1.8 root 802: ~ ( ( (uint64_t) ( zSig1<<1 ) == 0 ) & roundNearestEven );
803: if ( (int64_t) zSig0 < 0 ) zExp = 1;
1.1 root 804: }
805: return packFloatx80( zSign, zExp, zSig0 );
806: }
807: }
808: if ( zSig1 ) STATUS(float_exception_flags) |= float_flag_inexact;
809: if ( increment ) {
810: ++zSig0;
811: if ( zSig0 == 0 ) {
812: ++zExp;
813: zSig0 = LIT64( 0x8000000000000000 );
814: }
815: else {
1.1.1.8 root 816: zSig0 &= ~ ( ( (uint64_t) ( zSig1<<1 ) == 0 ) & roundNearestEven );
1.1 root 817: }
818: }
819: else {
820: if ( zSig0 == 0 ) zExp = 0;
821: }
822: return packFloatx80( zSign, zExp, zSig0 );
823:
824: }
825:
826: /*----------------------------------------------------------------------------
827: | Takes an abstract floating-point value having sign `zSign', exponent
828: | `zExp', and significand formed by the concatenation of `zSig0' and `zSig1',
829: | and returns the proper extended double-precision floating-point value
830: | corresponding to the abstract input. This routine is just like
831: | `roundAndPackFloatx80' except that the input significand does not have to be
832: | normalized.
833: *----------------------------------------------------------------------------*/
834:
835: static floatx80
836: normalizeRoundAndPackFloatx80(
1.1.1.8 root 837: int8 roundingPrecision, flag zSign, int32 zExp, uint64_t zSig0, uint64_t zSig1
1.1 root 838: STATUS_PARAM)
839: {
840: int8 shiftCount;
841:
842: if ( zSig0 == 0 ) {
843: zSig0 = zSig1;
844: zSig1 = 0;
845: zExp -= 64;
846: }
847: shiftCount = countLeadingZeros64( zSig0 );
848: shortShift128Left( zSig0, zSig1, shiftCount, &zSig0, &zSig1 );
849: zExp -= shiftCount;
850: return
851: roundAndPackFloatx80( roundingPrecision, zSign, zExp, zSig0, zSig1 STATUS_VAR);
852:
853: }
854:
855: /*----------------------------------------------------------------------------
856: | Returns the least-significant 64 fraction bits of the quadruple-precision
857: | floating-point value `a'.
858: *----------------------------------------------------------------------------*/
859:
1.1.1.8 root 860: INLINE uint64_t extractFloat128Frac1( float128 a )
1.1 root 861: {
862:
863: return a.low;
864:
865: }
866:
867: /*----------------------------------------------------------------------------
868: | Returns the most-significant 48 fraction bits of the quadruple-precision
869: | floating-point value `a'.
870: *----------------------------------------------------------------------------*/
871:
1.1.1.8 root 872: INLINE uint64_t extractFloat128Frac0( float128 a )
1.1 root 873: {
874:
875: return a.high & LIT64( 0x0000FFFFFFFFFFFF );
876:
877: }
878:
879: /*----------------------------------------------------------------------------
880: | Returns the exponent bits of the quadruple-precision floating-point value
881: | `a'.
882: *----------------------------------------------------------------------------*/
883:
884: INLINE int32 extractFloat128Exp( float128 a )
885: {
886:
887: return ( a.high>>48 ) & 0x7FFF;
888:
889: }
890:
891: /*----------------------------------------------------------------------------
892: | Returns the sign bit of the quadruple-precision floating-point value `a'.
893: *----------------------------------------------------------------------------*/
894:
895: INLINE flag extractFloat128Sign( float128 a )
896: {
897:
898: return a.high>>63;
899:
900: }
901:
902: /*----------------------------------------------------------------------------
903: | Normalizes the subnormal quadruple-precision floating-point value
904: | represented by the denormalized significand formed by the concatenation of
905: | `aSig0' and `aSig1'. The normalized exponent is stored at the location
906: | pointed to by `zExpPtr'. The most significant 49 bits of the normalized
907: | significand are stored at the location pointed to by `zSig0Ptr', and the
908: | least significant 64 bits of the normalized significand are stored at the
909: | location pointed to by `zSig1Ptr'.
910: *----------------------------------------------------------------------------*/
911:
912: static void
913: normalizeFloat128Subnormal(
1.1.1.8 root 914: uint64_t aSig0,
915: uint64_t aSig1,
1.1 root 916: int32 *zExpPtr,
1.1.1.8 root 917: uint64_t *zSig0Ptr,
918: uint64_t *zSig1Ptr
1.1 root 919: )
920: {
921: int8 shiftCount;
922:
923: if ( aSig0 == 0 ) {
924: shiftCount = countLeadingZeros64( aSig1 ) - 15;
925: if ( shiftCount < 0 ) {
926: *zSig0Ptr = aSig1>>( - shiftCount );
927: *zSig1Ptr = aSig1<<( shiftCount & 63 );
928: }
929: else {
930: *zSig0Ptr = aSig1<<shiftCount;
931: *zSig1Ptr = 0;
932: }
933: *zExpPtr = - shiftCount - 63;
934: }
935: else {
936: shiftCount = countLeadingZeros64( aSig0 ) - 15;
937: shortShift128Left( aSig0, aSig1, shiftCount, zSig0Ptr, zSig1Ptr );
938: *zExpPtr = 1 - shiftCount;
939: }
940:
941: }
942:
943: /*----------------------------------------------------------------------------
944: | Packs the sign `zSign', the exponent `zExp', and the significand formed
945: | by the concatenation of `zSig0' and `zSig1' into a quadruple-precision
946: | floating-point value, returning the result. After being shifted into the
947: | proper positions, the three fields `zSign', `zExp', and `zSig0' are simply
948: | added together to form the most significant 32 bits of the result. This
949: | means that any integer portion of `zSig0' will be added into the exponent.
950: | Since a properly normalized significand will have an integer portion equal
951: | to 1, the `zExp' input should be 1 less than the desired result exponent
952: | whenever `zSig0' and `zSig1' concatenated form a complete, normalized
953: | significand.
954: *----------------------------------------------------------------------------*/
955:
956: INLINE float128
1.1.1.8 root 957: packFloat128( flag zSign, int32 zExp, uint64_t zSig0, uint64_t zSig1 )
1.1 root 958: {
959: float128 z;
960:
961: z.low = zSig1;
1.1.1.8 root 962: z.high = ( ( (uint64_t) zSign )<<63 ) + ( ( (uint64_t) zExp )<<48 ) + zSig0;
1.1 root 963: return z;
964:
965: }
966:
967: /*----------------------------------------------------------------------------
968: | Takes an abstract floating-point value having sign `zSign', exponent `zExp',
969: | and extended significand formed by the concatenation of `zSig0', `zSig1',
970: | and `zSig2', and returns the proper quadruple-precision floating-point value
971: | corresponding to the abstract input. Ordinarily, the abstract value is
972: | simply rounded and packed into the quadruple-precision format, with the
973: | inexact exception raised if the abstract input cannot be represented
974: | exactly. However, if the abstract value is too large, the overflow and
975: | inexact exceptions are raised and an infinity or maximal finite value is
976: | returned. If the abstract value is too small, the input value is rounded to
977: | a subnormal number, and the underflow and inexact exceptions are raised if
978: | the abstract input cannot be represented exactly as a subnormal quadruple-
979: | precision floating-point number.
980: | The input significand must be normalized or smaller. If the input
981: | significand is not normalized, `zExp' must be 0; in that case, the result
982: | returned is a subnormal number, and it must not require rounding. In the
983: | usual case that the input significand is normalized, `zExp' must be 1 less
984: | than the ``true'' floating-point exponent. The handling of underflow and
985: | overflow follows the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
986: *----------------------------------------------------------------------------*/
987:
988: static float128
989: roundAndPackFloat128(
1.1.1.8 root 990: flag zSign, int32 zExp, uint64_t zSig0, uint64_t zSig1, uint64_t zSig2 STATUS_PARAM)
1.1 root 991: {
992: int8 roundingMode;
993: flag roundNearestEven, increment, isTiny;
994:
995: roundingMode = STATUS(float_rounding_mode);
996: roundNearestEven = ( roundingMode == float_round_nearest_even );
1.1.1.8 root 997: increment = ( (int64_t) zSig2 < 0 );
1.1 root 998: if ( ! roundNearestEven ) {
999: if ( roundingMode == float_round_to_zero ) {
1000: increment = 0;
1001: }
1002: else {
1003: if ( zSign ) {
1004: increment = ( roundingMode == float_round_down ) && zSig2;
1005: }
1006: else {
1007: increment = ( roundingMode == float_round_up ) && zSig2;
1008: }
1009: }
1010: }
1.1.1.8 root 1011: if ( 0x7FFD <= (uint32_t) zExp ) {
1.1 root 1012: if ( ( 0x7FFD < zExp )
1013: || ( ( zExp == 0x7FFD )
1014: && eq128(
1015: LIT64( 0x0001FFFFFFFFFFFF ),
1016: LIT64( 0xFFFFFFFFFFFFFFFF ),
1017: zSig0,
1018: zSig1
1019: )
1020: && increment
1021: )
1022: ) {
1023: float_raise( float_flag_overflow | float_flag_inexact STATUS_VAR);
1024: if ( ( roundingMode == float_round_to_zero )
1025: || ( zSign && ( roundingMode == float_round_up ) )
1026: || ( ! zSign && ( roundingMode == float_round_down ) )
1027: ) {
1028: return
1029: packFloat128(
1030: zSign,
1031: 0x7FFE,
1032: LIT64( 0x0000FFFFFFFFFFFF ),
1033: LIT64( 0xFFFFFFFFFFFFFFFF )
1034: );
1035: }
1036: return packFloat128( zSign, 0x7FFF, 0, 0 );
1037: }
1038: if ( zExp < 0 ) {
1.1.1.8 root 1039: if (STATUS(flush_to_zero)) {
1040: float_raise(float_flag_output_denormal STATUS_VAR);
1041: return packFloat128(zSign, 0, 0, 0);
1042: }
1.1 root 1043: isTiny =
1044: ( STATUS(float_detect_tininess) == float_tininess_before_rounding )
1045: || ( zExp < -1 )
1046: || ! increment
1047: || lt128(
1048: zSig0,
1049: zSig1,
1050: LIT64( 0x0001FFFFFFFFFFFF ),
1051: LIT64( 0xFFFFFFFFFFFFFFFF )
1052: );
1053: shift128ExtraRightJamming(
1054: zSig0, zSig1, zSig2, - zExp, &zSig0, &zSig1, &zSig2 );
1055: zExp = 0;
1056: if ( isTiny && zSig2 ) float_raise( float_flag_underflow STATUS_VAR);
1057: if ( roundNearestEven ) {
1.1.1.8 root 1058: increment = ( (int64_t) zSig2 < 0 );
1.1 root 1059: }
1060: else {
1061: if ( zSign ) {
1062: increment = ( roundingMode == float_round_down ) && zSig2;
1063: }
1064: else {
1065: increment = ( roundingMode == float_round_up ) && zSig2;
1066: }
1067: }
1068: }
1069: }
1070: if ( zSig2 ) STATUS(float_exception_flags) |= float_flag_inexact;
1071: if ( increment ) {
1072: add128( zSig0, zSig1, 0, 1, &zSig0, &zSig1 );
1073: zSig1 &= ~ ( ( zSig2 + zSig2 == 0 ) & roundNearestEven );
1074: }
1075: else {
1076: if ( ( zSig0 | zSig1 ) == 0 ) zExp = 0;
1077: }
1078: return packFloat128( zSign, zExp, zSig0, zSig1 );
1079:
1080: }
1081:
1082: /*----------------------------------------------------------------------------
1083: | Takes an abstract floating-point value having sign `zSign', exponent `zExp',
1084: | and significand formed by the concatenation of `zSig0' and `zSig1', and
1085: | returns the proper quadruple-precision floating-point value corresponding
1086: | to the abstract input. This routine is just like `roundAndPackFloat128'
1087: | except that the input significand has fewer bits and does not have to be
1088: | normalized. In all cases, `zExp' must be 1 less than the ``true'' floating-
1089: | point exponent.
1090: *----------------------------------------------------------------------------*/
1091:
1092: static float128
1093: normalizeRoundAndPackFloat128(
1.1.1.8 root 1094: flag zSign, int32 zExp, uint64_t zSig0, uint64_t zSig1 STATUS_PARAM)
1.1 root 1095: {
1096: int8 shiftCount;
1.1.1.8 root 1097: uint64_t zSig2;
1.1 root 1098:
1099: if ( zSig0 == 0 ) {
1100: zSig0 = zSig1;
1101: zSig1 = 0;
1102: zExp -= 64;
1103: }
1104: shiftCount = countLeadingZeros64( zSig0 ) - 15;
1105: if ( 0 <= shiftCount ) {
1106: zSig2 = 0;
1107: shortShift128Left( zSig0, zSig1, shiftCount, &zSig0, &zSig1 );
1108: }
1109: else {
1110: shift128ExtraRightJamming(
1111: zSig0, zSig1, 0, - shiftCount, &zSig0, &zSig1, &zSig2 );
1112: }
1113: zExp -= shiftCount;
1114: return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 STATUS_VAR);
1115:
1116: }
1117:
1118: /*----------------------------------------------------------------------------
1119: | Returns the result of converting the 32-bit two's complement integer `a'
1120: | to the single-precision floating-point format. The conversion is performed
1121: | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
1122: *----------------------------------------------------------------------------*/
1123:
1124: float32 int32_to_float32( int32 a STATUS_PARAM )
1125: {
1126: flag zSign;
1127:
1.1.1.3 root 1128: if ( a == 0 ) return float32_zero;
1.1.1.8 root 1129: if ( a == (int32_t) 0x80000000 ) return packFloat32( 1, 0x9E, 0 );
1.1 root 1130: zSign = ( a < 0 );
1131: return normalizeRoundAndPackFloat32( zSign, 0x9C, zSign ? - a : a STATUS_VAR );
1132:
1133: }
1134:
1135: /*----------------------------------------------------------------------------
1136: | Returns the result of converting the 32-bit two's complement integer `a'
1137: | to the double-precision floating-point format. The conversion is performed
1138: | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
1139: *----------------------------------------------------------------------------*/
1140:
1141: float64 int32_to_float64( int32 a STATUS_PARAM )
1142: {
1143: flag zSign;
1144: uint32 absA;
1145: int8 shiftCount;
1.1.1.8 root 1146: uint64_t zSig;
1.1 root 1147:
1.1.1.3 root 1148: if ( a == 0 ) return float64_zero;
1.1 root 1149: zSign = ( a < 0 );
1150: absA = zSign ? - a : a;
1151: shiftCount = countLeadingZeros32( absA ) + 21;
1152: zSig = absA;
1153: return packFloat64( zSign, 0x432 - shiftCount, zSig<<shiftCount );
1154:
1155: }
1156:
1157: /*----------------------------------------------------------------------------
1158: | Returns the result of converting the 32-bit two's complement integer `a'
1159: | to the extended double-precision floating-point format. The conversion
1160: | is performed according to the IEC/IEEE Standard for Binary Floating-Point
1161: | Arithmetic.
1162: *----------------------------------------------------------------------------*/
1163:
1164: floatx80 int32_to_floatx80( int32 a STATUS_PARAM )
1165: {
1166: flag zSign;
1167: uint32 absA;
1168: int8 shiftCount;
1.1.1.8 root 1169: uint64_t zSig;
1.1 root 1170:
1171: if ( a == 0 ) return packFloatx80( 0, 0, 0 );
1172: zSign = ( a < 0 );
1173: absA = zSign ? - a : a;
1174: shiftCount = countLeadingZeros32( absA ) + 32;
1175: zSig = absA;
1176: return packFloatx80( zSign, 0x403E - shiftCount, zSig<<shiftCount );
1177:
1178: }
1179:
1180: /*----------------------------------------------------------------------------
1181: | Returns the result of converting the 32-bit two's complement integer `a' to
1182: | the quadruple-precision floating-point format. The conversion is performed
1183: | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
1184: *----------------------------------------------------------------------------*/
1185:
1186: float128 int32_to_float128( int32 a STATUS_PARAM )
1187: {
1188: flag zSign;
1189: uint32 absA;
1190: int8 shiftCount;
1.1.1.8 root 1191: uint64_t zSig0;
1.1 root 1192:
1193: if ( a == 0 ) return packFloat128( 0, 0, 0, 0 );
1194: zSign = ( a < 0 );
1195: absA = zSign ? - a : a;
1196: shiftCount = countLeadingZeros32( absA ) + 17;
1197: zSig0 = absA;
1198: return packFloat128( zSign, 0x402E - shiftCount, zSig0<<shiftCount, 0 );
1199:
1200: }
1201:
1202: /*----------------------------------------------------------------------------
1203: | Returns the result of converting the 64-bit two's complement integer `a'
1204: | to the single-precision floating-point format. The conversion is performed
1205: | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
1206: *----------------------------------------------------------------------------*/
1207:
1208: float32 int64_to_float32( int64 a STATUS_PARAM )
1209: {
1210: flag zSign;
1211: uint64 absA;
1212: int8 shiftCount;
1213:
1.1.1.3 root 1214: if ( a == 0 ) return float32_zero;
1.1 root 1215: zSign = ( a < 0 );
1216: absA = zSign ? - a : a;
1217: shiftCount = countLeadingZeros64( absA ) - 40;
1218: if ( 0 <= shiftCount ) {
1219: return packFloat32( zSign, 0x95 - shiftCount, absA<<shiftCount );
1220: }
1221: else {
1222: shiftCount += 7;
1223: if ( shiftCount < 0 ) {
1224: shift64RightJamming( absA, - shiftCount, &absA );
1225: }
1226: else {
1227: absA <<= shiftCount;
1228: }
1229: return roundAndPackFloat32( zSign, 0x9C - shiftCount, absA STATUS_VAR );
1230: }
1231:
1232: }
1233:
1.1.1.3 root 1234: float32 uint64_to_float32( uint64 a STATUS_PARAM )
1235: {
1236: int8 shiftCount;
1237:
1238: if ( a == 0 ) return float32_zero;
1239: shiftCount = countLeadingZeros64( a ) - 40;
1240: if ( 0 <= shiftCount ) {
1241: return packFloat32( 1 > 0, 0x95 - shiftCount, a<<shiftCount );
1242: }
1243: else {
1244: shiftCount += 7;
1245: if ( shiftCount < 0 ) {
1246: shift64RightJamming( a, - shiftCount, &a );
1247: }
1248: else {
1249: a <<= shiftCount;
1250: }
1251: return roundAndPackFloat32( 1 > 0, 0x9C - shiftCount, a STATUS_VAR );
1252: }
1253: }
1254:
1.1 root 1255: /*----------------------------------------------------------------------------
1256: | Returns the result of converting the 64-bit two's complement integer `a'
1257: | to the double-precision floating-point format. The conversion is performed
1258: | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
1259: *----------------------------------------------------------------------------*/
1260:
1261: float64 int64_to_float64( int64 a STATUS_PARAM )
1262: {
1263: flag zSign;
1264:
1.1.1.3 root 1265: if ( a == 0 ) return float64_zero;
1.1.1.8 root 1266: if ( a == (int64_t) LIT64( 0x8000000000000000 ) ) {
1.1 root 1267: return packFloat64( 1, 0x43E, 0 );
1268: }
1269: zSign = ( a < 0 );
1270: return normalizeRoundAndPackFloat64( zSign, 0x43C, zSign ? - a : a STATUS_VAR );
1271:
1272: }
1273:
1.1.1.3 root 1274: float64 uint64_to_float64( uint64 a STATUS_PARAM )
1275: {
1276: if ( a == 0 ) return float64_zero;
1277: return normalizeRoundAndPackFloat64( 0, 0x43C, a STATUS_VAR );
1278:
1279: }
1280:
1.1 root 1281: /*----------------------------------------------------------------------------
1282: | Returns the result of converting the 64-bit two's complement integer `a'
1283: | to the extended double-precision floating-point format. The conversion
1284: | is performed according to the IEC/IEEE Standard for Binary Floating-Point
1285: | Arithmetic.
1286: *----------------------------------------------------------------------------*/
1287:
1288: floatx80 int64_to_floatx80( int64 a STATUS_PARAM )
1289: {
1290: flag zSign;
1291: uint64 absA;
1292: int8 shiftCount;
1293:
1294: if ( a == 0 ) return packFloatx80( 0, 0, 0 );
1295: zSign = ( a < 0 );
1296: absA = zSign ? - a : a;
1297: shiftCount = countLeadingZeros64( absA );
1298: return packFloatx80( zSign, 0x403E - shiftCount, absA<<shiftCount );
1299:
1300: }
1301:
1302: /*----------------------------------------------------------------------------
1303: | Returns the result of converting the 64-bit two's complement integer `a' to
1304: | the quadruple-precision floating-point format. The conversion is performed
1305: | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
1306: *----------------------------------------------------------------------------*/
1307:
1308: float128 int64_to_float128( int64 a STATUS_PARAM )
1309: {
1310: flag zSign;
1311: uint64 absA;
1312: int8 shiftCount;
1313: int32 zExp;
1.1.1.8 root 1314: uint64_t zSig0, zSig1;
1.1 root 1315:
1316: if ( a == 0 ) return packFloat128( 0, 0, 0, 0 );
1317: zSign = ( a < 0 );
1318: absA = zSign ? - a : a;
1319: shiftCount = countLeadingZeros64( absA ) + 49;
1320: zExp = 0x406E - shiftCount;
1321: if ( 64 <= shiftCount ) {
1322: zSig1 = 0;
1323: zSig0 = absA;
1324: shiftCount -= 64;
1325: }
1326: else {
1327: zSig1 = absA;
1328: zSig0 = 0;
1329: }
1330: shortShift128Left( zSig0, zSig1, shiftCount, &zSig0, &zSig1 );
1331: return packFloat128( zSign, zExp, zSig0, zSig1 );
1332:
1333: }
1334:
1335: /*----------------------------------------------------------------------------
1336: | Returns the result of converting the single-precision floating-point value
1337: | `a' to the 32-bit two's complement integer format. The conversion is
1338: | performed according to the IEC/IEEE Standard for Binary Floating-Point
1339: | Arithmetic---which means in particular that the conversion is rounded
1340: | according to the current rounding mode. If `a' is a NaN, the largest
1341: | positive integer is returned. Otherwise, if the conversion overflows, the
1342: | largest integer with the same sign as `a' is returned.
1343: *----------------------------------------------------------------------------*/
1344:
1345: int32 float32_to_int32( float32 a STATUS_PARAM )
1346: {
1347: flag aSign;
1.1.1.10! root 1348: int_fast16_t aExp, shiftCount;
1.1.1.8 root 1349: uint32_t aSig;
1350: uint64_t aSig64;
1.1 root 1351:
1.1.1.7 root 1352: a = float32_squash_input_denormal(a STATUS_VAR);
1.1 root 1353: aSig = extractFloat32Frac( a );
1354: aExp = extractFloat32Exp( a );
1355: aSign = extractFloat32Sign( a );
1356: if ( ( aExp == 0xFF ) && aSig ) aSign = 0;
1357: if ( aExp ) aSig |= 0x00800000;
1358: shiftCount = 0xAF - aExp;
1359: aSig64 = aSig;
1360: aSig64 <<= 32;
1361: if ( 0 < shiftCount ) shift64RightJamming( aSig64, shiftCount, &aSig64 );
1362: return roundAndPackInt32( aSign, aSig64 STATUS_VAR );
1363:
1364: }
1365:
1366: /*----------------------------------------------------------------------------
1367: | Returns the result of converting the single-precision floating-point value
1368: | `a' to the 32-bit two's complement integer format. The conversion is
1369: | performed according to the IEC/IEEE Standard for Binary Floating-Point
1370: | Arithmetic, except that the conversion is always rounded toward zero.
1371: | If `a' is a NaN, the largest positive integer is returned. Otherwise, if
1372: | the conversion overflows, the largest integer with the same sign as `a' is
1373: | returned.
1374: *----------------------------------------------------------------------------*/
1375:
1376: int32 float32_to_int32_round_to_zero( float32 a STATUS_PARAM )
1377: {
1378: flag aSign;
1.1.1.10! root 1379: int_fast16_t aExp, shiftCount;
1.1.1.8 root 1380: uint32_t aSig;
1.1.1.10! root 1381: int32_t z;
1.1.1.7 root 1382: a = float32_squash_input_denormal(a STATUS_VAR);
1.1 root 1383:
1384: aSig = extractFloat32Frac( a );
1385: aExp = extractFloat32Exp( a );
1386: aSign = extractFloat32Sign( a );
1387: shiftCount = aExp - 0x9E;
1388: if ( 0 <= shiftCount ) {
1.1.1.3 root 1389: if ( float32_val(a) != 0xCF000000 ) {
1.1 root 1390: float_raise( float_flag_invalid STATUS_VAR);
1391: if ( ! aSign || ( ( aExp == 0xFF ) && aSig ) ) return 0x7FFFFFFF;
1392: }
1.1.1.8 root 1393: return (int32_t) 0x80000000;
1.1 root 1394: }
1395: else if ( aExp <= 0x7E ) {
1396: if ( aExp | aSig ) STATUS(float_exception_flags) |= float_flag_inexact;
1397: return 0;
1398: }
1399: aSig = ( aSig | 0x00800000 )<<8;
1400: z = aSig>>( - shiftCount );
1.1.1.8 root 1401: if ( (uint32_t) ( aSig<<( shiftCount & 31 ) ) ) {
1.1 root 1402: STATUS(float_exception_flags) |= float_flag_inexact;
1403: }
1404: if ( aSign ) z = - z;
1405: return z;
1406:
1407: }
1408:
1409: /*----------------------------------------------------------------------------
1410: | Returns the result of converting the single-precision floating-point value
1.1.1.7 root 1411: | `a' to the 16-bit two's complement integer format. The conversion is
1412: | performed according to the IEC/IEEE Standard for Binary Floating-Point
1413: | Arithmetic, except that the conversion is always rounded toward zero.
1414: | If `a' is a NaN, the largest positive integer is returned. Otherwise, if
1415: | the conversion overflows, the largest integer with the same sign as `a' is
1416: | returned.
1417: *----------------------------------------------------------------------------*/
1418:
1.1.1.10! root 1419: int_fast16_t float32_to_int16_round_to_zero(float32 a STATUS_PARAM)
1.1.1.7 root 1420: {
1421: flag aSign;
1.1.1.10! root 1422: int_fast16_t aExp, shiftCount;
1.1.1.8 root 1423: uint32_t aSig;
1.1.1.7 root 1424: int32 z;
1425:
1426: aSig = extractFloat32Frac( a );
1427: aExp = extractFloat32Exp( a );
1428: aSign = extractFloat32Sign( a );
1429: shiftCount = aExp - 0x8E;
1430: if ( 0 <= shiftCount ) {
1431: if ( float32_val(a) != 0xC7000000 ) {
1432: float_raise( float_flag_invalid STATUS_VAR);
1433: if ( ! aSign || ( ( aExp == 0xFF ) && aSig ) ) {
1434: return 0x7FFF;
1435: }
1436: }
1.1.1.8 root 1437: return (int32_t) 0xffff8000;
1.1.1.7 root 1438: }
1439: else if ( aExp <= 0x7E ) {
1440: if ( aExp | aSig ) {
1441: STATUS(float_exception_flags) |= float_flag_inexact;
1442: }
1443: return 0;
1444: }
1445: shiftCount -= 0x10;
1446: aSig = ( aSig | 0x00800000 )<<8;
1447: z = aSig>>( - shiftCount );
1.1.1.8 root 1448: if ( (uint32_t) ( aSig<<( shiftCount & 31 ) ) ) {
1.1.1.7 root 1449: STATUS(float_exception_flags) |= float_flag_inexact;
1450: }
1451: if ( aSign ) {
1452: z = - z;
1453: }
1454: return z;
1455:
1456: }
1457:
1458: /*----------------------------------------------------------------------------
1459: | Returns the result of converting the single-precision floating-point value
1.1 root 1460: | `a' to the 64-bit two's complement integer format. The conversion is
1461: | performed according to the IEC/IEEE Standard for Binary Floating-Point
1462: | Arithmetic---which means in particular that the conversion is rounded
1463: | according to the current rounding mode. If `a' is a NaN, the largest
1464: | positive integer is returned. Otherwise, if the conversion overflows, the
1465: | largest integer with the same sign as `a' is returned.
1466: *----------------------------------------------------------------------------*/
1467:
1468: int64 float32_to_int64( float32 a STATUS_PARAM )
1469: {
1470: flag aSign;
1.1.1.10! root 1471: int_fast16_t aExp, shiftCount;
1.1.1.8 root 1472: uint32_t aSig;
1473: uint64_t aSig64, aSigExtra;
1.1.1.7 root 1474: a = float32_squash_input_denormal(a STATUS_VAR);
1.1 root 1475:
1476: aSig = extractFloat32Frac( a );
1477: aExp = extractFloat32Exp( a );
1478: aSign = extractFloat32Sign( a );
1479: shiftCount = 0xBE - aExp;
1480: if ( shiftCount < 0 ) {
1481: float_raise( float_flag_invalid STATUS_VAR);
1482: if ( ! aSign || ( ( aExp == 0xFF ) && aSig ) ) {
1483: return LIT64( 0x7FFFFFFFFFFFFFFF );
1484: }
1.1.1.8 root 1485: return (int64_t) LIT64( 0x8000000000000000 );
1.1 root 1486: }
1487: if ( aExp ) aSig |= 0x00800000;
1488: aSig64 = aSig;
1489: aSig64 <<= 40;
1490: shift64ExtraRightJamming( aSig64, 0, shiftCount, &aSig64, &aSigExtra );
1491: return roundAndPackInt64( aSign, aSig64, aSigExtra STATUS_VAR );
1492:
1493: }
1494:
1495: /*----------------------------------------------------------------------------
1496: | Returns the result of converting the single-precision floating-point value
1497: | `a' to the 64-bit two's complement integer format. The conversion is
1498: | performed according to the IEC/IEEE Standard for Binary Floating-Point
1499: | Arithmetic, except that the conversion is always rounded toward zero. If
1500: | `a' is a NaN, the largest positive integer is returned. Otherwise, if the
1501: | conversion overflows, the largest integer with the same sign as `a' is
1502: | returned.
1503: *----------------------------------------------------------------------------*/
1504:
1505: int64 float32_to_int64_round_to_zero( float32 a STATUS_PARAM )
1506: {
1507: flag aSign;
1.1.1.10! root 1508: int_fast16_t aExp, shiftCount;
1.1.1.8 root 1509: uint32_t aSig;
1510: uint64_t aSig64;
1.1 root 1511: int64 z;
1.1.1.7 root 1512: a = float32_squash_input_denormal(a STATUS_VAR);
1.1 root 1513:
1514: aSig = extractFloat32Frac( a );
1515: aExp = extractFloat32Exp( a );
1516: aSign = extractFloat32Sign( a );
1517: shiftCount = aExp - 0xBE;
1518: if ( 0 <= shiftCount ) {
1.1.1.3 root 1519: if ( float32_val(a) != 0xDF000000 ) {
1.1 root 1520: float_raise( float_flag_invalid STATUS_VAR);
1521: if ( ! aSign || ( ( aExp == 0xFF ) && aSig ) ) {
1522: return LIT64( 0x7FFFFFFFFFFFFFFF );
1523: }
1524: }
1.1.1.8 root 1525: return (int64_t) LIT64( 0x8000000000000000 );
1.1 root 1526: }
1527: else if ( aExp <= 0x7E ) {
1528: if ( aExp | aSig ) STATUS(float_exception_flags) |= float_flag_inexact;
1529: return 0;
1530: }
1531: aSig64 = aSig | 0x00800000;
1532: aSig64 <<= 40;
1533: z = aSig64>>( - shiftCount );
1.1.1.8 root 1534: if ( (uint64_t) ( aSig64<<( shiftCount & 63 ) ) ) {
1.1 root 1535: STATUS(float_exception_flags) |= float_flag_inexact;
1536: }
1537: if ( aSign ) z = - z;
1538: return z;
1539:
1540: }
1541:
1542: /*----------------------------------------------------------------------------
1543: | Returns the result of converting the single-precision floating-point value
1544: | `a' to the double-precision floating-point format. The conversion is
1545: | performed according to the IEC/IEEE Standard for Binary Floating-Point
1546: | Arithmetic.
1547: *----------------------------------------------------------------------------*/
1548:
1549: float64 float32_to_float64( float32 a STATUS_PARAM )
1550: {
1551: flag aSign;
1.1.1.10! root 1552: int_fast16_t aExp;
1.1.1.8 root 1553: uint32_t aSig;
1.1.1.7 root 1554: a = float32_squash_input_denormal(a STATUS_VAR);
1.1 root 1555:
1556: aSig = extractFloat32Frac( a );
1557: aExp = extractFloat32Exp( a );
1558: aSign = extractFloat32Sign( a );
1559: if ( aExp == 0xFF ) {
1.1.1.8 root 1560: if ( aSig ) return commonNaNToFloat64( float32ToCommonNaN( a STATUS_VAR ) STATUS_VAR );
1.1 root 1561: return packFloat64( aSign, 0x7FF, 0 );
1562: }
1563: if ( aExp == 0 ) {
1564: if ( aSig == 0 ) return packFloat64( aSign, 0, 0 );
1565: normalizeFloat32Subnormal( aSig, &aExp, &aSig );
1566: --aExp;
1567: }
1.1.1.8 root 1568: return packFloat64( aSign, aExp + 0x380, ( (uint64_t) aSig )<<29 );
1.1 root 1569:
1570: }
1571:
1572: /*----------------------------------------------------------------------------
1573: | Returns the result of converting the single-precision floating-point value
1574: | `a' to the extended double-precision floating-point format. The conversion
1575: | is performed according to the IEC/IEEE Standard for Binary Floating-Point
1576: | Arithmetic.
1577: *----------------------------------------------------------------------------*/
1578:
1579: floatx80 float32_to_floatx80( float32 a STATUS_PARAM )
1580: {
1581: flag aSign;
1.1.1.10! root 1582: int_fast16_t aExp;
1.1.1.8 root 1583: uint32_t aSig;
1.1 root 1584:
1.1.1.7 root 1585: a = float32_squash_input_denormal(a STATUS_VAR);
1.1 root 1586: aSig = extractFloat32Frac( a );
1587: aExp = extractFloat32Exp( a );
1588: aSign = extractFloat32Sign( a );
1589: if ( aExp == 0xFF ) {
1.1.1.8 root 1590: if ( aSig ) return commonNaNToFloatx80( float32ToCommonNaN( a STATUS_VAR ) STATUS_VAR );
1.1 root 1591: return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
1592: }
1593: if ( aExp == 0 ) {
1594: if ( aSig == 0 ) return packFloatx80( aSign, 0, 0 );
1595: normalizeFloat32Subnormal( aSig, &aExp, &aSig );
1596: }
1597: aSig |= 0x00800000;
1.1.1.8 root 1598: return packFloatx80( aSign, aExp + 0x3F80, ( (uint64_t) aSig )<<40 );
1.1 root 1599:
1600: }
1601:
1602: /*----------------------------------------------------------------------------
1603: | Returns the result of converting the single-precision floating-point value
1604: | `a' to the double-precision floating-point format. The conversion is
1605: | performed according to the IEC/IEEE Standard for Binary Floating-Point
1606: | Arithmetic.
1607: *----------------------------------------------------------------------------*/
1608:
1609: float128 float32_to_float128( float32 a STATUS_PARAM )
1610: {
1611: flag aSign;
1.1.1.10! root 1612: int_fast16_t aExp;
1.1.1.8 root 1613: uint32_t aSig;
1.1 root 1614:
1.1.1.7 root 1615: a = float32_squash_input_denormal(a STATUS_VAR);
1.1 root 1616: aSig = extractFloat32Frac( a );
1617: aExp = extractFloat32Exp( a );
1618: aSign = extractFloat32Sign( a );
1619: if ( aExp == 0xFF ) {
1.1.1.8 root 1620: if ( aSig ) return commonNaNToFloat128( float32ToCommonNaN( a STATUS_VAR ) STATUS_VAR );
1.1 root 1621: return packFloat128( aSign, 0x7FFF, 0, 0 );
1622: }
1623: if ( aExp == 0 ) {
1624: if ( aSig == 0 ) return packFloat128( aSign, 0, 0, 0 );
1625: normalizeFloat32Subnormal( aSig, &aExp, &aSig );
1626: --aExp;
1627: }
1.1.1.8 root 1628: return packFloat128( aSign, aExp + 0x3F80, ( (uint64_t) aSig )<<25, 0 );
1.1 root 1629:
1630: }
1631:
1632: /*----------------------------------------------------------------------------
1633: | Rounds the single-precision floating-point value `a' to an integer, and
1634: | returns the result as a single-precision floating-point value. The
1635: | operation is performed according to the IEC/IEEE Standard for Binary
1636: | Floating-Point Arithmetic.
1637: *----------------------------------------------------------------------------*/
1638:
1639: float32 float32_round_to_int( float32 a STATUS_PARAM)
1640: {
1641: flag aSign;
1.1.1.10! root 1642: int_fast16_t aExp;
1.1.1.8 root 1643: uint32_t lastBitMask, roundBitsMask;
1.1 root 1644: int8 roundingMode;
1.1.1.8 root 1645: uint32_t z;
1.1.1.7 root 1646: a = float32_squash_input_denormal(a STATUS_VAR);
1.1 root 1647:
1648: aExp = extractFloat32Exp( a );
1649: if ( 0x96 <= aExp ) {
1650: if ( ( aExp == 0xFF ) && extractFloat32Frac( a ) ) {
1651: return propagateFloat32NaN( a, a STATUS_VAR );
1652: }
1653: return a;
1654: }
1655: if ( aExp <= 0x7E ) {
1.1.1.8 root 1656: if ( (uint32_t) ( float32_val(a)<<1 ) == 0 ) return a;
1.1 root 1657: STATUS(float_exception_flags) |= float_flag_inexact;
1658: aSign = extractFloat32Sign( a );
1659: switch ( STATUS(float_rounding_mode) ) {
1660: case float_round_nearest_even:
1661: if ( ( aExp == 0x7E ) && extractFloat32Frac( a ) ) {
1662: return packFloat32( aSign, 0x7F, 0 );
1663: }
1664: break;
1665: case float_round_down:
1.1.1.3 root 1666: return make_float32(aSign ? 0xBF800000 : 0);
1.1 root 1667: case float_round_up:
1.1.1.3 root 1668: return make_float32(aSign ? 0x80000000 : 0x3F800000);
1.1 root 1669: }
1670: return packFloat32( aSign, 0, 0 );
1671: }
1672: lastBitMask = 1;
1673: lastBitMask <<= 0x96 - aExp;
1674: roundBitsMask = lastBitMask - 1;
1.1.1.3 root 1675: z = float32_val(a);
1.1 root 1676: roundingMode = STATUS(float_rounding_mode);
1677: if ( roundingMode == float_round_nearest_even ) {
1678: z += lastBitMask>>1;
1679: if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask;
1680: }
1681: else if ( roundingMode != float_round_to_zero ) {
1.1.1.3 root 1682: if ( extractFloat32Sign( make_float32(z) ) ^ ( roundingMode == float_round_up ) ) {
1.1 root 1683: z += roundBitsMask;
1684: }
1685: }
1686: z &= ~ roundBitsMask;
1.1.1.3 root 1687: if ( z != float32_val(a) ) STATUS(float_exception_flags) |= float_flag_inexact;
1688: return make_float32(z);
1.1 root 1689:
1690: }
1691:
1692: /*----------------------------------------------------------------------------
1693: | Returns the result of adding the absolute values of the single-precision
1694: | floating-point values `a' and `b'. If `zSign' is 1, the sum is negated
1695: | before being returned. `zSign' is ignored if the result is a NaN.
1696: | The addition is performed according to the IEC/IEEE Standard for Binary
1697: | Floating-Point Arithmetic.
1698: *----------------------------------------------------------------------------*/
1699:
1700: static float32 addFloat32Sigs( float32 a, float32 b, flag zSign STATUS_PARAM)
1701: {
1.1.1.10! root 1702: int_fast16_t aExp, bExp, zExp;
1.1.1.8 root 1703: uint32_t aSig, bSig, zSig;
1.1.1.10! root 1704: int_fast16_t expDiff;
1.1 root 1705:
1706: aSig = extractFloat32Frac( a );
1707: aExp = extractFloat32Exp( a );
1708: bSig = extractFloat32Frac( b );
1709: bExp = extractFloat32Exp( b );
1710: expDiff = aExp - bExp;
1711: aSig <<= 6;
1712: bSig <<= 6;
1713: if ( 0 < expDiff ) {
1714: if ( aExp == 0xFF ) {
1715: if ( aSig ) return propagateFloat32NaN( a, b STATUS_VAR );
1716: return a;
1717: }
1718: if ( bExp == 0 ) {
1719: --expDiff;
1720: }
1721: else {
1722: bSig |= 0x20000000;
1723: }
1724: shift32RightJamming( bSig, expDiff, &bSig );
1725: zExp = aExp;
1726: }
1727: else if ( expDiff < 0 ) {
1728: if ( bExp == 0xFF ) {
1729: if ( bSig ) return propagateFloat32NaN( a, b STATUS_VAR );
1730: return packFloat32( zSign, 0xFF, 0 );
1731: }
1732: if ( aExp == 0 ) {
1733: ++expDiff;
1734: }
1735: else {
1736: aSig |= 0x20000000;
1737: }
1738: shift32RightJamming( aSig, - expDiff, &aSig );
1739: zExp = bExp;
1740: }
1741: else {
1742: if ( aExp == 0xFF ) {
1743: if ( aSig | bSig ) return propagateFloat32NaN( a, b STATUS_VAR );
1744: return a;
1745: }
1.1.1.4 root 1746: if ( aExp == 0 ) {
1.1.1.8 root 1747: if (STATUS(flush_to_zero)) {
1748: if (aSig | bSig) {
1749: float_raise(float_flag_output_denormal STATUS_VAR);
1750: }
1751: return packFloat32(zSign, 0, 0);
1752: }
1.1.1.4 root 1753: return packFloat32( zSign, 0, ( aSig + bSig )>>6 );
1754: }
1.1 root 1755: zSig = 0x40000000 + aSig + bSig;
1756: zExp = aExp;
1757: goto roundAndPack;
1758: }
1759: aSig |= 0x20000000;
1760: zSig = ( aSig + bSig )<<1;
1761: --zExp;
1.1.1.8 root 1762: if ( (int32_t) zSig < 0 ) {
1.1 root 1763: zSig = aSig + bSig;
1764: ++zExp;
1765: }
1766: roundAndPack:
1767: return roundAndPackFloat32( zSign, zExp, zSig STATUS_VAR );
1768:
1769: }
1770:
1771: /*----------------------------------------------------------------------------
1772: | Returns the result of subtracting the absolute values of the single-
1773: | precision floating-point values `a' and `b'. If `zSign' is 1, the
1774: | difference is negated before being returned. `zSign' is ignored if the
1775: | result is a NaN. The subtraction is performed according to the IEC/IEEE
1776: | Standard for Binary Floating-Point Arithmetic.
1777: *----------------------------------------------------------------------------*/
1778:
1779: static float32 subFloat32Sigs( float32 a, float32 b, flag zSign STATUS_PARAM)
1780: {
1.1.1.10! root 1781: int_fast16_t aExp, bExp, zExp;
1.1.1.8 root 1782: uint32_t aSig, bSig, zSig;
1.1.1.10! root 1783: int_fast16_t expDiff;
1.1 root 1784:
1785: aSig = extractFloat32Frac( a );
1786: aExp = extractFloat32Exp( a );
1787: bSig = extractFloat32Frac( b );
1788: bExp = extractFloat32Exp( b );
1789: expDiff = aExp - bExp;
1790: aSig <<= 7;
1791: bSig <<= 7;
1792: if ( 0 < expDiff ) goto aExpBigger;
1793: if ( expDiff < 0 ) goto bExpBigger;
1794: if ( aExp == 0xFF ) {
1795: if ( aSig | bSig ) return propagateFloat32NaN( a, b STATUS_VAR );
1796: float_raise( float_flag_invalid STATUS_VAR);
1797: return float32_default_nan;
1798: }
1799: if ( aExp == 0 ) {
1800: aExp = 1;
1801: bExp = 1;
1802: }
1803: if ( bSig < aSig ) goto aBigger;
1804: if ( aSig < bSig ) goto bBigger;
1805: return packFloat32( STATUS(float_rounding_mode) == float_round_down, 0, 0 );
1806: bExpBigger:
1807: if ( bExp == 0xFF ) {
1808: if ( bSig ) return propagateFloat32NaN( a, b STATUS_VAR );
1809: return packFloat32( zSign ^ 1, 0xFF, 0 );
1810: }
1811: if ( aExp == 0 ) {
1812: ++expDiff;
1813: }
1814: else {
1815: aSig |= 0x40000000;
1816: }
1817: shift32RightJamming( aSig, - expDiff, &aSig );
1818: bSig |= 0x40000000;
1819: bBigger:
1820: zSig = bSig - aSig;
1821: zExp = bExp;
1822: zSign ^= 1;
1823: goto normalizeRoundAndPack;
1824: aExpBigger:
1825: if ( aExp == 0xFF ) {
1826: if ( aSig ) return propagateFloat32NaN( a, b STATUS_VAR );
1827: return a;
1828: }
1829: if ( bExp == 0 ) {
1830: --expDiff;
1831: }
1832: else {
1833: bSig |= 0x40000000;
1834: }
1835: shift32RightJamming( bSig, expDiff, &bSig );
1836: aSig |= 0x40000000;
1837: aBigger:
1838: zSig = aSig - bSig;
1839: zExp = aExp;
1840: normalizeRoundAndPack:
1841: --zExp;
1842: return normalizeRoundAndPackFloat32( zSign, zExp, zSig STATUS_VAR );
1843:
1844: }
1845:
1846: /*----------------------------------------------------------------------------
1847: | Returns the result of adding the single-precision floating-point values `a'
1848: | and `b'. The operation is performed according to the IEC/IEEE Standard for
1849: | Binary Floating-Point Arithmetic.
1850: *----------------------------------------------------------------------------*/
1851:
1852: float32 float32_add( float32 a, float32 b STATUS_PARAM )
1853: {
1854: flag aSign, bSign;
1.1.1.7 root 1855: a = float32_squash_input_denormal(a STATUS_VAR);
1856: b = float32_squash_input_denormal(b STATUS_VAR);
1.1 root 1857:
1858: aSign = extractFloat32Sign( a );
1859: bSign = extractFloat32Sign( b );
1860: if ( aSign == bSign ) {
1861: return addFloat32Sigs( a, b, aSign STATUS_VAR);
1862: }
1863: else {
1864: return subFloat32Sigs( a, b, aSign STATUS_VAR );
1865: }
1866:
1867: }
1868:
1869: /*----------------------------------------------------------------------------
1870: | Returns the result of subtracting the single-precision floating-point values
1871: | `a' and `b'. The operation is performed according to the IEC/IEEE Standard
1872: | for Binary Floating-Point Arithmetic.
1873: *----------------------------------------------------------------------------*/
1874:
1875: float32 float32_sub( float32 a, float32 b STATUS_PARAM )
1876: {
1877: flag aSign, bSign;
1.1.1.7 root 1878: a = float32_squash_input_denormal(a STATUS_VAR);
1879: b = float32_squash_input_denormal(b STATUS_VAR);
1.1 root 1880:
1881: aSign = extractFloat32Sign( a );
1882: bSign = extractFloat32Sign( b );
1883: if ( aSign == bSign ) {
1884: return subFloat32Sigs( a, b, aSign STATUS_VAR );
1885: }
1886: else {
1887: return addFloat32Sigs( a, b, aSign STATUS_VAR );
1888: }
1889:
1890: }
1891:
1892: /*----------------------------------------------------------------------------
1893: | Returns the result of multiplying the single-precision floating-point values
1894: | `a' and `b'. The operation is performed according to the IEC/IEEE Standard
1895: | for Binary Floating-Point Arithmetic.
1896: *----------------------------------------------------------------------------*/
1897:
1898: float32 float32_mul( float32 a, float32 b STATUS_PARAM )
1899: {
1900: flag aSign, bSign, zSign;
1.1.1.10! root 1901: int_fast16_t aExp, bExp, zExp;
1.1.1.8 root 1902: uint32_t aSig, bSig;
1903: uint64_t zSig64;
1904: uint32_t zSig;
1.1 root 1905:
1.1.1.7 root 1906: a = float32_squash_input_denormal(a STATUS_VAR);
1907: b = float32_squash_input_denormal(b STATUS_VAR);
1908:
1.1 root 1909: aSig = extractFloat32Frac( a );
1910: aExp = extractFloat32Exp( a );
1911: aSign = extractFloat32Sign( a );
1912: bSig = extractFloat32Frac( b );
1913: bExp = extractFloat32Exp( b );
1914: bSign = extractFloat32Sign( b );
1915: zSign = aSign ^ bSign;
1916: if ( aExp == 0xFF ) {
1917: if ( aSig || ( ( bExp == 0xFF ) && bSig ) ) {
1918: return propagateFloat32NaN( a, b STATUS_VAR );
1919: }
1920: if ( ( bExp | bSig ) == 0 ) {
1921: float_raise( float_flag_invalid STATUS_VAR);
1922: return float32_default_nan;
1923: }
1924: return packFloat32( zSign, 0xFF, 0 );
1925: }
1926: if ( bExp == 0xFF ) {
1927: if ( bSig ) return propagateFloat32NaN( a, b STATUS_VAR );
1928: if ( ( aExp | aSig ) == 0 ) {
1929: float_raise( float_flag_invalid STATUS_VAR);
1930: return float32_default_nan;
1931: }
1932: return packFloat32( zSign, 0xFF, 0 );
1933: }
1934: if ( aExp == 0 ) {
1935: if ( aSig == 0 ) return packFloat32( zSign, 0, 0 );
1936: normalizeFloat32Subnormal( aSig, &aExp, &aSig );
1937: }
1938: if ( bExp == 0 ) {
1939: if ( bSig == 0 ) return packFloat32( zSign, 0, 0 );
1940: normalizeFloat32Subnormal( bSig, &bExp, &bSig );
1941: }
1942: zExp = aExp + bExp - 0x7F;
1943: aSig = ( aSig | 0x00800000 )<<7;
1944: bSig = ( bSig | 0x00800000 )<<8;
1.1.1.8 root 1945: shift64RightJamming( ( (uint64_t) aSig ) * bSig, 32, &zSig64 );
1.1 root 1946: zSig = zSig64;
1.1.1.8 root 1947: if ( 0 <= (int32_t) ( zSig<<1 ) ) {
1.1 root 1948: zSig <<= 1;
1949: --zExp;
1950: }
1951: return roundAndPackFloat32( zSign, zExp, zSig STATUS_VAR );
1952:
1953: }
1954:
1955: /*----------------------------------------------------------------------------
1956: | Returns the result of dividing the single-precision floating-point value `a'
1957: | by the corresponding value `b'. The operation is performed according to the
1958: | IEC/IEEE Standard for Binary Floating-Point Arithmetic.
1959: *----------------------------------------------------------------------------*/
1960:
1961: float32 float32_div( float32 a, float32 b STATUS_PARAM )
1962: {
1963: flag aSign, bSign, zSign;
1.1.1.10! root 1964: int_fast16_t aExp, bExp, zExp;
1.1.1.8 root 1965: uint32_t aSig, bSig, zSig;
1.1.1.7 root 1966: a = float32_squash_input_denormal(a STATUS_VAR);
1967: b = float32_squash_input_denormal(b STATUS_VAR);
1.1 root 1968:
1969: aSig = extractFloat32Frac( a );
1970: aExp = extractFloat32Exp( a );
1971: aSign = extractFloat32Sign( a );
1972: bSig = extractFloat32Frac( b );
1973: bExp = extractFloat32Exp( b );
1974: bSign = extractFloat32Sign( b );
1975: zSign = aSign ^ bSign;
1976: if ( aExp == 0xFF ) {
1977: if ( aSig ) return propagateFloat32NaN( a, b STATUS_VAR );
1978: if ( bExp == 0xFF ) {
1979: if ( bSig ) return propagateFloat32NaN( a, b STATUS_VAR );
1980: float_raise( float_flag_invalid STATUS_VAR);
1981: return float32_default_nan;
1982: }
1983: return packFloat32( zSign, 0xFF, 0 );
1984: }
1985: if ( bExp == 0xFF ) {
1986: if ( bSig ) return propagateFloat32NaN( a, b STATUS_VAR );
1987: return packFloat32( zSign, 0, 0 );
1988: }
1989: if ( bExp == 0 ) {
1990: if ( bSig == 0 ) {
1991: if ( ( aExp | aSig ) == 0 ) {
1992: float_raise( float_flag_invalid STATUS_VAR);
1993: return float32_default_nan;
1994: }
1995: float_raise( float_flag_divbyzero STATUS_VAR);
1996: return packFloat32( zSign, 0xFF, 0 );
1997: }
1998: normalizeFloat32Subnormal( bSig, &bExp, &bSig );
1999: }
2000: if ( aExp == 0 ) {
2001: if ( aSig == 0 ) return packFloat32( zSign, 0, 0 );
2002: normalizeFloat32Subnormal( aSig, &aExp, &aSig );
2003: }
2004: zExp = aExp - bExp + 0x7D;
2005: aSig = ( aSig | 0x00800000 )<<7;
2006: bSig = ( bSig | 0x00800000 )<<8;
2007: if ( bSig <= ( aSig + aSig ) ) {
2008: aSig >>= 1;
2009: ++zExp;
2010: }
1.1.1.8 root 2011: zSig = ( ( (uint64_t) aSig )<<32 ) / bSig;
1.1 root 2012: if ( ( zSig & 0x3F ) == 0 ) {
1.1.1.8 root 2013: zSig |= ( (uint64_t) bSig * zSig != ( (uint64_t) aSig )<<32 );
1.1 root 2014: }
2015: return roundAndPackFloat32( zSign, zExp, zSig STATUS_VAR );
2016:
2017: }
2018:
2019: /*----------------------------------------------------------------------------
2020: | Returns the remainder of the single-precision floating-point value `a'
2021: | with respect to the corresponding value `b'. The operation is performed
2022: | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
2023: *----------------------------------------------------------------------------*/
2024:
2025: float32 float32_rem( float32 a, float32 b STATUS_PARAM )
2026: {
1.1.1.6 root 2027: flag aSign, zSign;
1.1.1.10! root 2028: int_fast16_t aExp, bExp, expDiff;
1.1.1.8 root 2029: uint32_t aSig, bSig;
2030: uint32_t q;
2031: uint64_t aSig64, bSig64, q64;
2032: uint32_t alternateASig;
2033: int32_t sigMean;
1.1.1.7 root 2034: a = float32_squash_input_denormal(a STATUS_VAR);
2035: b = float32_squash_input_denormal(b STATUS_VAR);
1.1 root 2036:
2037: aSig = extractFloat32Frac( a );
2038: aExp = extractFloat32Exp( a );
2039: aSign = extractFloat32Sign( a );
2040: bSig = extractFloat32Frac( b );
2041: bExp = extractFloat32Exp( b );
2042: if ( aExp == 0xFF ) {
2043: if ( aSig || ( ( bExp == 0xFF ) && bSig ) ) {
2044: return propagateFloat32NaN( a, b STATUS_VAR );
2045: }
2046: float_raise( float_flag_invalid STATUS_VAR);
2047: return float32_default_nan;
2048: }
2049: if ( bExp == 0xFF ) {
2050: if ( bSig ) return propagateFloat32NaN( a, b STATUS_VAR );
2051: return a;
2052: }
2053: if ( bExp == 0 ) {
2054: if ( bSig == 0 ) {
2055: float_raise( float_flag_invalid STATUS_VAR);
2056: return float32_default_nan;
2057: }
2058: normalizeFloat32Subnormal( bSig, &bExp, &bSig );
2059: }
2060: if ( aExp == 0 ) {
2061: if ( aSig == 0 ) return a;
2062: normalizeFloat32Subnormal( aSig, &aExp, &aSig );
2063: }
2064: expDiff = aExp - bExp;
2065: aSig |= 0x00800000;
2066: bSig |= 0x00800000;
2067: if ( expDiff < 32 ) {
2068: aSig <<= 8;
2069: bSig <<= 8;
2070: if ( expDiff < 0 ) {
2071: if ( expDiff < -1 ) return a;
2072: aSig >>= 1;
2073: }
2074: q = ( bSig <= aSig );
2075: if ( q ) aSig -= bSig;
2076: if ( 0 < expDiff ) {
1.1.1.8 root 2077: q = ( ( (uint64_t) aSig )<<32 ) / bSig;
1.1 root 2078: q >>= 32 - expDiff;
2079: bSig >>= 2;
2080: aSig = ( ( aSig>>1 )<<( expDiff - 1 ) ) - bSig * q;
2081: }
2082: else {
2083: aSig >>= 2;
2084: bSig >>= 2;
2085: }
2086: }
2087: else {
2088: if ( bSig <= aSig ) aSig -= bSig;
1.1.1.8 root 2089: aSig64 = ( (uint64_t) aSig )<<40;
2090: bSig64 = ( (uint64_t) bSig )<<40;
1.1 root 2091: expDiff -= 64;
2092: while ( 0 < expDiff ) {
2093: q64 = estimateDiv128To64( aSig64, 0, bSig64 );
2094: q64 = ( 2 < q64 ) ? q64 - 2 : 0;
2095: aSig64 = - ( ( bSig * q64 )<<38 );
2096: expDiff -= 62;
2097: }
2098: expDiff += 64;
2099: q64 = estimateDiv128To64( aSig64, 0, bSig64 );
2100: q64 = ( 2 < q64 ) ? q64 - 2 : 0;
2101: q = q64>>( 64 - expDiff );
2102: bSig <<= 6;
2103: aSig = ( ( aSig64>>33 )<<( expDiff - 1 ) ) - bSig * q;
2104: }
2105: do {
2106: alternateASig = aSig;
2107: ++q;
2108: aSig -= bSig;
1.1.1.8 root 2109: } while ( 0 <= (int32_t) aSig );
1.1 root 2110: sigMean = aSig + alternateASig;
2111: if ( ( sigMean < 0 ) || ( ( sigMean == 0 ) && ( q & 1 ) ) ) {
2112: aSig = alternateASig;
2113: }
1.1.1.8 root 2114: zSign = ( (int32_t) aSig < 0 );
1.1 root 2115: if ( zSign ) aSig = - aSig;
2116: return normalizeRoundAndPackFloat32( aSign ^ zSign, bExp, aSig STATUS_VAR );
2117:
2118: }
2119:
2120: /*----------------------------------------------------------------------------
1.1.1.9 root 2121: | Returns the result of multiplying the single-precision floating-point values
2122: | `a' and `b' then adding 'c', with no intermediate rounding step after the
2123: | multiplication. The operation is performed according to the IEC/IEEE
2124: | Standard for Binary Floating-Point Arithmetic 754-2008.
2125: | The flags argument allows the caller to select negation of the
2126: | addend, the intermediate product, or the final result. (The difference
2127: | between this and having the caller do a separate negation is that negating
2128: | externally will flip the sign bit on NaNs.)
2129: *----------------------------------------------------------------------------*/
2130:
2131: float32 float32_muladd(float32 a, float32 b, float32 c, int flags STATUS_PARAM)
2132: {
2133: flag aSign, bSign, cSign, zSign;
1.1.1.10! root 2134: int_fast16_t aExp, bExp, cExp, pExp, zExp, expDiff;
1.1.1.9 root 2135: uint32_t aSig, bSig, cSig;
2136: flag pInf, pZero, pSign;
2137: uint64_t pSig64, cSig64, zSig64;
2138: uint32_t pSig;
2139: int shiftcount;
2140: flag signflip, infzero;
2141:
2142: a = float32_squash_input_denormal(a STATUS_VAR);
2143: b = float32_squash_input_denormal(b STATUS_VAR);
2144: c = float32_squash_input_denormal(c STATUS_VAR);
2145: aSig = extractFloat32Frac(a);
2146: aExp = extractFloat32Exp(a);
2147: aSign = extractFloat32Sign(a);
2148: bSig = extractFloat32Frac(b);
2149: bExp = extractFloat32Exp(b);
2150: bSign = extractFloat32Sign(b);
2151: cSig = extractFloat32Frac(c);
2152: cExp = extractFloat32Exp(c);
2153: cSign = extractFloat32Sign(c);
2154:
2155: infzero = ((aExp == 0 && aSig == 0 && bExp == 0xff && bSig == 0) ||
2156: (aExp == 0xff && aSig == 0 && bExp == 0 && bSig == 0));
2157:
2158: /* It is implementation-defined whether the cases of (0,inf,qnan)
2159: * and (inf,0,qnan) raise InvalidOperation or not (and what QNaN
2160: * they return if they do), so we have to hand this information
2161: * off to the target-specific pick-a-NaN routine.
2162: */
2163: if (((aExp == 0xff) && aSig) ||
2164: ((bExp == 0xff) && bSig) ||
2165: ((cExp == 0xff) && cSig)) {
2166: return propagateFloat32MulAddNaN(a, b, c, infzero STATUS_VAR);
2167: }
2168:
2169: if (infzero) {
2170: float_raise(float_flag_invalid STATUS_VAR);
2171: return float32_default_nan;
2172: }
2173:
2174: if (flags & float_muladd_negate_c) {
2175: cSign ^= 1;
2176: }
2177:
2178: signflip = (flags & float_muladd_negate_result) ? 1 : 0;
2179:
2180: /* Work out the sign and type of the product */
2181: pSign = aSign ^ bSign;
2182: if (flags & float_muladd_negate_product) {
2183: pSign ^= 1;
2184: }
2185: pInf = (aExp == 0xff) || (bExp == 0xff);
2186: pZero = ((aExp | aSig) == 0) || ((bExp | bSig) == 0);
2187:
2188: if (cExp == 0xff) {
2189: if (pInf && (pSign ^ cSign)) {
2190: /* addition of opposite-signed infinities => InvalidOperation */
2191: float_raise(float_flag_invalid STATUS_VAR);
2192: return float32_default_nan;
2193: }
2194: /* Otherwise generate an infinity of the same sign */
2195: return packFloat32(cSign ^ signflip, 0xff, 0);
2196: }
2197:
2198: if (pInf) {
2199: return packFloat32(pSign ^ signflip, 0xff, 0);
2200: }
2201:
2202: if (pZero) {
2203: if (cExp == 0) {
2204: if (cSig == 0) {
2205: /* Adding two exact zeroes */
2206: if (pSign == cSign) {
2207: zSign = pSign;
2208: } else if (STATUS(float_rounding_mode) == float_round_down) {
2209: zSign = 1;
2210: } else {
2211: zSign = 0;
2212: }
2213: return packFloat32(zSign ^ signflip, 0, 0);
2214: }
2215: /* Exact zero plus a denorm */
2216: if (STATUS(flush_to_zero)) {
2217: float_raise(float_flag_output_denormal STATUS_VAR);
2218: return packFloat32(cSign ^ signflip, 0, 0);
2219: }
2220: }
2221: /* Zero plus something non-zero : just return the something */
1.1.1.10! root 2222: return make_float32(float32_val(c) ^ (signflip << 31));
1.1.1.9 root 2223: }
2224:
2225: if (aExp == 0) {
2226: normalizeFloat32Subnormal(aSig, &aExp, &aSig);
2227: }
2228: if (bExp == 0) {
2229: normalizeFloat32Subnormal(bSig, &bExp, &bSig);
2230: }
2231:
2232: /* Calculate the actual result a * b + c */
2233:
2234: /* Multiply first; this is easy. */
2235: /* NB: we subtract 0x7e where float32_mul() subtracts 0x7f
2236: * because we want the true exponent, not the "one-less-than"
2237: * flavour that roundAndPackFloat32() takes.
2238: */
2239: pExp = aExp + bExp - 0x7e;
2240: aSig = (aSig | 0x00800000) << 7;
2241: bSig = (bSig | 0x00800000) << 8;
2242: pSig64 = (uint64_t)aSig * bSig;
2243: if ((int64_t)(pSig64 << 1) >= 0) {
2244: pSig64 <<= 1;
2245: pExp--;
2246: }
2247:
2248: zSign = pSign ^ signflip;
2249:
2250: /* Now pSig64 is the significand of the multiply, with the explicit bit in
2251: * position 62.
2252: */
2253: if (cExp == 0) {
2254: if (!cSig) {
2255: /* Throw out the special case of c being an exact zero now */
2256: shift64RightJamming(pSig64, 32, &pSig64);
2257: pSig = pSig64;
2258: return roundAndPackFloat32(zSign, pExp - 1,
2259: pSig STATUS_VAR);
2260: }
2261: normalizeFloat32Subnormal(cSig, &cExp, &cSig);
2262: }
2263:
2264: cSig64 = (uint64_t)cSig << (62 - 23);
2265: cSig64 |= LIT64(0x4000000000000000);
2266: expDiff = pExp - cExp;
2267:
2268: if (pSign == cSign) {
2269: /* Addition */
2270: if (expDiff > 0) {
2271: /* scale c to match p */
2272: shift64RightJamming(cSig64, expDiff, &cSig64);
2273: zExp = pExp;
2274: } else if (expDiff < 0) {
2275: /* scale p to match c */
2276: shift64RightJamming(pSig64, -expDiff, &pSig64);
2277: zExp = cExp;
2278: } else {
2279: /* no scaling needed */
2280: zExp = cExp;
2281: }
2282: /* Add significands and make sure explicit bit ends up in posn 62 */
2283: zSig64 = pSig64 + cSig64;
2284: if ((int64_t)zSig64 < 0) {
2285: shift64RightJamming(zSig64, 1, &zSig64);
2286: } else {
2287: zExp--;
2288: }
2289: } else {
2290: /* Subtraction */
2291: if (expDiff > 0) {
2292: shift64RightJamming(cSig64, expDiff, &cSig64);
2293: zSig64 = pSig64 - cSig64;
2294: zExp = pExp;
2295: } else if (expDiff < 0) {
2296: shift64RightJamming(pSig64, -expDiff, &pSig64);
2297: zSig64 = cSig64 - pSig64;
2298: zExp = cExp;
2299: zSign ^= 1;
2300: } else {
2301: zExp = pExp;
2302: if (cSig64 < pSig64) {
2303: zSig64 = pSig64 - cSig64;
2304: } else if (pSig64 < cSig64) {
2305: zSig64 = cSig64 - pSig64;
2306: zSign ^= 1;
2307: } else {
2308: /* Exact zero */
2309: zSign = signflip;
2310: if (STATUS(float_rounding_mode) == float_round_down) {
2311: zSign ^= 1;
2312: }
2313: return packFloat32(zSign, 0, 0);
2314: }
2315: }
2316: --zExp;
2317: /* Normalize to put the explicit bit back into bit 62. */
2318: shiftcount = countLeadingZeros64(zSig64) - 1;
2319: zSig64 <<= shiftcount;
2320: zExp -= shiftcount;
2321: }
2322: shift64RightJamming(zSig64, 32, &zSig64);
2323: return roundAndPackFloat32(zSign, zExp, zSig64 STATUS_VAR);
2324: }
2325:
2326:
2327: /*----------------------------------------------------------------------------
1.1 root 2328: | Returns the square root of the single-precision floating-point value `a'.
2329: | The operation is performed according to the IEC/IEEE Standard for Binary
2330: | Floating-Point Arithmetic.
2331: *----------------------------------------------------------------------------*/
2332:
2333: float32 float32_sqrt( float32 a STATUS_PARAM )
2334: {
2335: flag aSign;
1.1.1.10! root 2336: int_fast16_t aExp, zExp;
1.1.1.8 root 2337: uint32_t aSig, zSig;
2338: uint64_t rem, term;
1.1.1.7 root 2339: a = float32_squash_input_denormal(a STATUS_VAR);
1.1 root 2340:
2341: aSig = extractFloat32Frac( a );
2342: aExp = extractFloat32Exp( a );
2343: aSign = extractFloat32Sign( a );
2344: if ( aExp == 0xFF ) {
1.1.1.3 root 2345: if ( aSig ) return propagateFloat32NaN( a, float32_zero STATUS_VAR );
1.1 root 2346: if ( ! aSign ) return a;
2347: float_raise( float_flag_invalid STATUS_VAR);
2348: return float32_default_nan;
2349: }
2350: if ( aSign ) {
2351: if ( ( aExp | aSig ) == 0 ) return a;
2352: float_raise( float_flag_invalid STATUS_VAR);
2353: return float32_default_nan;
2354: }
2355: if ( aExp == 0 ) {
1.1.1.3 root 2356: if ( aSig == 0 ) return float32_zero;
1.1 root 2357: normalizeFloat32Subnormal( aSig, &aExp, &aSig );
2358: }
2359: zExp = ( ( aExp - 0x7F )>>1 ) + 0x7E;
2360: aSig = ( aSig | 0x00800000 )<<8;
2361: zSig = estimateSqrt32( aExp, aSig ) + 2;
2362: if ( ( zSig & 0x7F ) <= 5 ) {
2363: if ( zSig < 2 ) {
2364: zSig = 0x7FFFFFFF;
2365: goto roundAndPack;
2366: }
2367: aSig >>= aExp & 1;
1.1.1.8 root 2368: term = ( (uint64_t) zSig ) * zSig;
2369: rem = ( ( (uint64_t) aSig )<<32 ) - term;
2370: while ( (int64_t) rem < 0 ) {
1.1 root 2371: --zSig;
1.1.1.8 root 2372: rem += ( ( (uint64_t) zSig )<<1 ) | 1;
1.1 root 2373: }
2374: zSig |= ( rem != 0 );
2375: }
2376: shift32RightJamming( zSig, 1, &zSig );
2377: roundAndPack:
2378: return roundAndPackFloat32( 0, zExp, zSig STATUS_VAR );
2379:
2380: }
2381:
2382: /*----------------------------------------------------------------------------
1.1.1.6 root 2383: | Returns the binary exponential of the single-precision floating-point value
2384: | `a'. The operation is performed according to the IEC/IEEE Standard for
2385: | Binary Floating-Point Arithmetic.
2386: |
2387: | Uses the following identities:
2388: |
2389: | 1. -------------------------------------------------------------------------
2390: | x x*ln(2)
2391: | 2 = e
2392: |
2393: | 2. -------------------------------------------------------------------------
2394: | 2 3 4 5 n
2395: | x x x x x x x
2396: | e = 1 + --- + --- + --- + --- + --- + ... + --- + ...
2397: | 1! 2! 3! 4! 5! n!
2398: *----------------------------------------------------------------------------*/
2399:
2400: static const float64 float32_exp2_coefficients[15] =
2401: {
1.1.1.8 root 2402: const_float64( 0x3ff0000000000000ll ), /* 1 */
2403: const_float64( 0x3fe0000000000000ll ), /* 2 */
2404: const_float64( 0x3fc5555555555555ll ), /* 3 */
2405: const_float64( 0x3fa5555555555555ll ), /* 4 */
2406: const_float64( 0x3f81111111111111ll ), /* 5 */
2407: const_float64( 0x3f56c16c16c16c17ll ), /* 6 */
2408: const_float64( 0x3f2a01a01a01a01all ), /* 7 */
2409: const_float64( 0x3efa01a01a01a01all ), /* 8 */
2410: const_float64( 0x3ec71de3a556c734ll ), /* 9 */
2411: const_float64( 0x3e927e4fb7789f5cll ), /* 10 */
2412: const_float64( 0x3e5ae64567f544e4ll ), /* 11 */
2413: const_float64( 0x3e21eed8eff8d898ll ), /* 12 */
2414: const_float64( 0x3de6124613a86d09ll ), /* 13 */
2415: const_float64( 0x3da93974a8c07c9dll ), /* 14 */
2416: const_float64( 0x3d6ae7f3e733b81fll ), /* 15 */
1.1.1.6 root 2417: };
2418:
2419: float32 float32_exp2( float32 a STATUS_PARAM )
2420: {
2421: flag aSign;
1.1.1.10! root 2422: int_fast16_t aExp;
1.1.1.8 root 2423: uint32_t aSig;
1.1.1.6 root 2424: float64 r, x, xn;
2425: int i;
1.1.1.7 root 2426: a = float32_squash_input_denormal(a STATUS_VAR);
1.1.1.6 root 2427:
2428: aSig = extractFloat32Frac( a );
2429: aExp = extractFloat32Exp( a );
2430: aSign = extractFloat32Sign( a );
2431:
2432: if ( aExp == 0xFF) {
2433: if ( aSig ) return propagateFloat32NaN( a, float32_zero STATUS_VAR );
2434: return (aSign) ? float32_zero : a;
2435: }
2436: if (aExp == 0) {
2437: if (aSig == 0) return float32_one;
2438: }
2439:
2440: float_raise( float_flag_inexact STATUS_VAR);
2441:
2442: /* ******************************* */
2443: /* using float64 for approximation */
2444: /* ******************************* */
2445: x = float32_to_float64(a STATUS_VAR);
2446: x = float64_mul(x, float64_ln2 STATUS_VAR);
2447:
2448: xn = x;
2449: r = float64_one;
2450: for (i = 0 ; i < 15 ; i++) {
2451: float64 f;
2452:
2453: f = float64_mul(xn, float32_exp2_coefficients[i] STATUS_VAR);
2454: r = float64_add(r, f STATUS_VAR);
2455:
2456: xn = float64_mul(xn, x STATUS_VAR);
2457: }
2458:
2459: return float64_to_float32(r, status);
2460: }
2461:
2462: /*----------------------------------------------------------------------------
1.1.1.4 root 2463: | Returns the binary log of the single-precision floating-point value `a'.
2464: | The operation is performed according to the IEC/IEEE Standard for Binary
2465: | Floating-Point Arithmetic.
2466: *----------------------------------------------------------------------------*/
2467: float32 float32_log2( float32 a STATUS_PARAM )
2468: {
2469: flag aSign, zSign;
1.1.1.10! root 2470: int_fast16_t aExp;
1.1.1.8 root 2471: uint32_t aSig, zSig, i;
1.1.1.4 root 2472:
1.1.1.7 root 2473: a = float32_squash_input_denormal(a STATUS_VAR);
1.1.1.4 root 2474: aSig = extractFloat32Frac( a );
2475: aExp = extractFloat32Exp( a );
2476: aSign = extractFloat32Sign( a );
2477:
2478: if ( aExp == 0 ) {
2479: if ( aSig == 0 ) return packFloat32( 1, 0xFF, 0 );
2480: normalizeFloat32Subnormal( aSig, &aExp, &aSig );
2481: }
2482: if ( aSign ) {
2483: float_raise( float_flag_invalid STATUS_VAR);
2484: return float32_default_nan;
2485: }
2486: if ( aExp == 0xFF ) {
2487: if ( aSig ) return propagateFloat32NaN( a, float32_zero STATUS_VAR );
2488: return a;
2489: }
2490:
2491: aExp -= 0x7F;
2492: aSig |= 0x00800000;
2493: zSign = aExp < 0;
2494: zSig = aExp << 23;
2495:
2496: for (i = 1 << 22; i > 0; i >>= 1) {
1.1.1.8 root 2497: aSig = ( (uint64_t)aSig * aSig ) >> 23;
1.1.1.4 root 2498: if ( aSig & 0x01000000 ) {
2499: aSig >>= 1;
2500: zSig |= i;
2501: }
2502: }
2503:
2504: if ( zSign )
2505: zSig = -zSig;
2506:
2507: return normalizeRoundAndPackFloat32( zSign, 0x85, zSig STATUS_VAR );
2508: }
2509:
2510: /*----------------------------------------------------------------------------
1.1 root 2511: | Returns 1 if the single-precision floating-point value `a' is equal to
1.1.1.8 root 2512: | the corresponding value `b', and 0 otherwise. The invalid exception is
2513: | raised if either operand is a NaN. Otherwise, the comparison is performed
1.1 root 2514: | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
2515: *----------------------------------------------------------------------------*/
2516:
1.1.1.2 root 2517: int float32_eq( float32 a, float32 b STATUS_PARAM )
1.1 root 2518: {
1.1.1.8 root 2519: uint32_t av, bv;
1.1.1.7 root 2520: a = float32_squash_input_denormal(a STATUS_VAR);
2521: b = float32_squash_input_denormal(b STATUS_VAR);
1.1 root 2522:
2523: if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
2524: || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
2525: ) {
1.1.1.8 root 2526: float_raise( float_flag_invalid STATUS_VAR);
1.1 root 2527: return 0;
2528: }
1.1.1.8 root 2529: av = float32_val(a);
2530: bv = float32_val(b);
2531: return ( av == bv ) || ( (uint32_t) ( ( av | bv )<<1 ) == 0 );
1.1 root 2532: }
2533:
2534: /*----------------------------------------------------------------------------
2535: | Returns 1 if the single-precision floating-point value `a' is less than
1.1.1.8 root 2536: | or equal to the corresponding value `b', and 0 otherwise. The invalid
2537: | exception is raised if either operand is a NaN. The comparison is performed
2538: | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
1.1 root 2539: *----------------------------------------------------------------------------*/
2540:
1.1.1.2 root 2541: int float32_le( float32 a, float32 b STATUS_PARAM )
1.1 root 2542: {
2543: flag aSign, bSign;
1.1.1.8 root 2544: uint32_t av, bv;
1.1.1.7 root 2545: a = float32_squash_input_denormal(a STATUS_VAR);
2546: b = float32_squash_input_denormal(b STATUS_VAR);
1.1 root 2547:
2548: if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
2549: || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
2550: ) {
2551: float_raise( float_flag_invalid STATUS_VAR);
2552: return 0;
2553: }
2554: aSign = extractFloat32Sign( a );
2555: bSign = extractFloat32Sign( b );
1.1.1.3 root 2556: av = float32_val(a);
2557: bv = float32_val(b);
1.1.1.8 root 2558: if ( aSign != bSign ) return aSign || ( (uint32_t) ( ( av | bv )<<1 ) == 0 );
1.1.1.3 root 2559: return ( av == bv ) || ( aSign ^ ( av < bv ) );
1.1 root 2560:
2561: }
2562:
2563: /*----------------------------------------------------------------------------
2564: | Returns 1 if the single-precision floating-point value `a' is less than
1.1.1.8 root 2565: | the corresponding value `b', and 0 otherwise. The invalid exception is
2566: | raised if either operand is a NaN. The comparison is performed according
2567: | to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
1.1 root 2568: *----------------------------------------------------------------------------*/
2569:
1.1.1.2 root 2570: int float32_lt( float32 a, float32 b STATUS_PARAM )
1.1 root 2571: {
2572: flag aSign, bSign;
1.1.1.8 root 2573: uint32_t av, bv;
1.1.1.7 root 2574: a = float32_squash_input_denormal(a STATUS_VAR);
2575: b = float32_squash_input_denormal(b STATUS_VAR);
1.1 root 2576:
2577: if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
2578: || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
2579: ) {
2580: float_raise( float_flag_invalid STATUS_VAR);
2581: return 0;
2582: }
2583: aSign = extractFloat32Sign( a );
2584: bSign = extractFloat32Sign( b );
1.1.1.3 root 2585: av = float32_val(a);
2586: bv = float32_val(b);
1.1.1.8 root 2587: if ( aSign != bSign ) return aSign && ( (uint32_t) ( ( av | bv )<<1 ) != 0 );
1.1.1.3 root 2588: return ( av != bv ) && ( aSign ^ ( av < bv ) );
1.1 root 2589:
2590: }
2591:
2592: /*----------------------------------------------------------------------------
1.1.1.8 root 2593: | Returns 1 if the single-precision floating-point values `a' and `b' cannot
2594: | be compared, and 0 otherwise. The invalid exception is raised if either
2595: | operand is a NaN. The comparison is performed according to the IEC/IEEE
2596: | Standard for Binary Floating-Point Arithmetic.
1.1 root 2597: *----------------------------------------------------------------------------*/
2598:
1.1.1.8 root 2599: int float32_unordered( float32 a, float32 b STATUS_PARAM )
1.1 root 2600: {
1.1.1.7 root 2601: a = float32_squash_input_denormal(a STATUS_VAR);
2602: b = float32_squash_input_denormal(b STATUS_VAR);
1.1 root 2603:
2604: if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
2605: || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
2606: ) {
2607: float_raise( float_flag_invalid STATUS_VAR);
1.1.1.8 root 2608: return 1;
1.1 root 2609: }
1.1.1.8 root 2610: return 0;
2611: }
2612:
2613: /*----------------------------------------------------------------------------
2614: | Returns 1 if the single-precision floating-point value `a' is equal to
2615: | the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an
2616: | exception. The comparison is performed according to the IEC/IEEE Standard
2617: | for Binary Floating-Point Arithmetic.
2618: *----------------------------------------------------------------------------*/
2619:
2620: int float32_eq_quiet( float32 a, float32 b STATUS_PARAM )
2621: {
2622: a = float32_squash_input_denormal(a STATUS_VAR);
2623: b = float32_squash_input_denormal(b STATUS_VAR);
1.1 root 2624:
1.1.1.8 root 2625: if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
2626: || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
2627: ) {
2628: if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) {
2629: float_raise( float_flag_invalid STATUS_VAR);
2630: }
2631: return 0;
2632: }
2633: return ( float32_val(a) == float32_val(b) ) ||
2634: ( (uint32_t) ( ( float32_val(a) | float32_val(b) )<<1 ) == 0 );
1.1 root 2635: }
2636:
2637: /*----------------------------------------------------------------------------
2638: | Returns 1 if the single-precision floating-point value `a' is less than or
2639: | equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not
2640: | cause an exception. Otherwise, the comparison is performed according to the
2641: | IEC/IEEE Standard for Binary Floating-Point Arithmetic.
2642: *----------------------------------------------------------------------------*/
2643:
1.1.1.2 root 2644: int float32_le_quiet( float32 a, float32 b STATUS_PARAM )
1.1 root 2645: {
2646: flag aSign, bSign;
1.1.1.8 root 2647: uint32_t av, bv;
1.1.1.7 root 2648: a = float32_squash_input_denormal(a STATUS_VAR);
2649: b = float32_squash_input_denormal(b STATUS_VAR);
1.1 root 2650:
2651: if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
2652: || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
2653: ) {
2654: if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) {
2655: float_raise( float_flag_invalid STATUS_VAR);
2656: }
2657: return 0;
2658: }
2659: aSign = extractFloat32Sign( a );
2660: bSign = extractFloat32Sign( b );
1.1.1.3 root 2661: av = float32_val(a);
2662: bv = float32_val(b);
1.1.1.8 root 2663: if ( aSign != bSign ) return aSign || ( (uint32_t) ( ( av | bv )<<1 ) == 0 );
1.1.1.3 root 2664: return ( av == bv ) || ( aSign ^ ( av < bv ) );
1.1 root 2665:
2666: }
2667:
2668: /*----------------------------------------------------------------------------
2669: | Returns 1 if the single-precision floating-point value `a' is less than
2670: | the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an
2671: | exception. Otherwise, the comparison is performed according to the IEC/IEEE
2672: | Standard for Binary Floating-Point Arithmetic.
2673: *----------------------------------------------------------------------------*/
2674:
1.1.1.2 root 2675: int float32_lt_quiet( float32 a, float32 b STATUS_PARAM )
1.1 root 2676: {
2677: flag aSign, bSign;
1.1.1.8 root 2678: uint32_t av, bv;
1.1.1.7 root 2679: a = float32_squash_input_denormal(a STATUS_VAR);
2680: b = float32_squash_input_denormal(b STATUS_VAR);
1.1 root 2681:
2682: if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
2683: || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
2684: ) {
2685: if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) {
2686: float_raise( float_flag_invalid STATUS_VAR);
2687: }
2688: return 0;
2689: }
2690: aSign = extractFloat32Sign( a );
2691: bSign = extractFloat32Sign( b );
1.1.1.3 root 2692: av = float32_val(a);
2693: bv = float32_val(b);
1.1.1.8 root 2694: if ( aSign != bSign ) return aSign && ( (uint32_t) ( ( av | bv )<<1 ) != 0 );
1.1.1.3 root 2695: return ( av != bv ) && ( aSign ^ ( av < bv ) );
1.1 root 2696:
2697: }
2698:
2699: /*----------------------------------------------------------------------------
1.1.1.8 root 2700: | Returns 1 if the single-precision floating-point values `a' and `b' cannot
2701: | be compared, and 0 otherwise. Quiet NaNs do not cause an exception. The
2702: | comparison is performed according to the IEC/IEEE Standard for Binary
2703: | Floating-Point Arithmetic.
2704: *----------------------------------------------------------------------------*/
2705:
2706: int float32_unordered_quiet( float32 a, float32 b STATUS_PARAM )
2707: {
2708: a = float32_squash_input_denormal(a STATUS_VAR);
2709: b = float32_squash_input_denormal(b STATUS_VAR);
2710:
2711: if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
2712: || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
2713: ) {
2714: if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) {
2715: float_raise( float_flag_invalid STATUS_VAR);
2716: }
2717: return 1;
2718: }
2719: return 0;
2720: }
2721:
2722: /*----------------------------------------------------------------------------
1.1 root 2723: | Returns the result of converting the double-precision floating-point value
2724: | `a' to the 32-bit two's complement integer format. The conversion is
2725: | performed according to the IEC/IEEE Standard for Binary Floating-Point
2726: | Arithmetic---which means in particular that the conversion is rounded
2727: | according to the current rounding mode. If `a' is a NaN, the largest
2728: | positive integer is returned. Otherwise, if the conversion overflows, the
2729: | largest integer with the same sign as `a' is returned.
2730: *----------------------------------------------------------------------------*/
2731:
2732: int32 float64_to_int32( float64 a STATUS_PARAM )
2733: {
2734: flag aSign;
1.1.1.10! root 2735: int_fast16_t aExp, shiftCount;
1.1.1.8 root 2736: uint64_t aSig;
1.1.1.7 root 2737: a = float64_squash_input_denormal(a STATUS_VAR);
1.1 root 2738:
2739: aSig = extractFloat64Frac( a );
2740: aExp = extractFloat64Exp( a );
2741: aSign = extractFloat64Sign( a );
2742: if ( ( aExp == 0x7FF ) && aSig ) aSign = 0;
2743: if ( aExp ) aSig |= LIT64( 0x0010000000000000 );
2744: shiftCount = 0x42C - aExp;
2745: if ( 0 < shiftCount ) shift64RightJamming( aSig, shiftCount, &aSig );
2746: return roundAndPackInt32( aSign, aSig STATUS_VAR );
2747:
2748: }
2749:
2750: /*----------------------------------------------------------------------------
2751: | Returns the result of converting the double-precision floating-point value
2752: | `a' to the 32-bit two's complement integer format. The conversion is
2753: | performed according to the IEC/IEEE Standard for Binary Floating-Point
2754: | Arithmetic, except that the conversion is always rounded toward zero.
2755: | If `a' is a NaN, the largest positive integer is returned. Otherwise, if
2756: | the conversion overflows, the largest integer with the same sign as `a' is
2757: | returned.
2758: *----------------------------------------------------------------------------*/
2759:
2760: int32 float64_to_int32_round_to_zero( float64 a STATUS_PARAM )
2761: {
2762: flag aSign;
1.1.1.10! root 2763: int_fast16_t aExp, shiftCount;
1.1.1.8 root 2764: uint64_t aSig, savedASig;
1.1.1.10! root 2765: int32_t z;
1.1.1.7 root 2766: a = float64_squash_input_denormal(a STATUS_VAR);
1.1 root 2767:
2768: aSig = extractFloat64Frac( a );
2769: aExp = extractFloat64Exp( a );
2770: aSign = extractFloat64Sign( a );
2771: if ( 0x41E < aExp ) {
2772: if ( ( aExp == 0x7FF ) && aSig ) aSign = 0;
2773: goto invalid;
2774: }
2775: else if ( aExp < 0x3FF ) {
2776: if ( aExp || aSig ) STATUS(float_exception_flags) |= float_flag_inexact;
2777: return 0;
2778: }
2779: aSig |= LIT64( 0x0010000000000000 );
2780: shiftCount = 0x433 - aExp;
2781: savedASig = aSig;
2782: aSig >>= shiftCount;
2783: z = aSig;
2784: if ( aSign ) z = - z;
2785: if ( ( z < 0 ) ^ aSign ) {
2786: invalid:
2787: float_raise( float_flag_invalid STATUS_VAR);
1.1.1.8 root 2788: return aSign ? (int32_t) 0x80000000 : 0x7FFFFFFF;
1.1 root 2789: }
2790: if ( ( aSig<<shiftCount ) != savedASig ) {
2791: STATUS(float_exception_flags) |= float_flag_inexact;
2792: }
2793: return z;
2794:
2795: }
2796:
2797: /*----------------------------------------------------------------------------
2798: | Returns the result of converting the double-precision floating-point value
1.1.1.7 root 2799: | `a' to the 16-bit two's complement integer format. The conversion is
2800: | performed according to the IEC/IEEE Standard for Binary Floating-Point
2801: | Arithmetic, except that the conversion is always rounded toward zero.
2802: | If `a' is a NaN, the largest positive integer is returned. Otherwise, if
2803: | the conversion overflows, the largest integer with the same sign as `a' is
2804: | returned.
2805: *----------------------------------------------------------------------------*/
2806:
1.1.1.10! root 2807: int_fast16_t float64_to_int16_round_to_zero(float64 a STATUS_PARAM)
1.1.1.7 root 2808: {
2809: flag aSign;
1.1.1.10! root 2810: int_fast16_t aExp, shiftCount;
1.1.1.8 root 2811: uint64_t aSig, savedASig;
1.1.1.7 root 2812: int32 z;
2813:
2814: aSig = extractFloat64Frac( a );
2815: aExp = extractFloat64Exp( a );
2816: aSign = extractFloat64Sign( a );
2817: if ( 0x40E < aExp ) {
2818: if ( ( aExp == 0x7FF ) && aSig ) {
2819: aSign = 0;
2820: }
2821: goto invalid;
2822: }
2823: else if ( aExp < 0x3FF ) {
2824: if ( aExp || aSig ) {
2825: STATUS(float_exception_flags) |= float_flag_inexact;
2826: }
2827: return 0;
2828: }
2829: aSig |= LIT64( 0x0010000000000000 );
2830: shiftCount = 0x433 - aExp;
2831: savedASig = aSig;
2832: aSig >>= shiftCount;
2833: z = aSig;
2834: if ( aSign ) {
2835: z = - z;
2836: }
2837: if ( ( (int16_t)z < 0 ) ^ aSign ) {
2838: invalid:
2839: float_raise( float_flag_invalid STATUS_VAR);
1.1.1.8 root 2840: return aSign ? (int32_t) 0xffff8000 : 0x7FFF;
1.1.1.7 root 2841: }
2842: if ( ( aSig<<shiftCount ) != savedASig ) {
2843: STATUS(float_exception_flags) |= float_flag_inexact;
2844: }
2845: return z;
2846: }
2847:
2848: /*----------------------------------------------------------------------------
2849: | Returns the result of converting the double-precision floating-point value
1.1 root 2850: | `a' to the 64-bit two's complement integer format. The conversion is
2851: | performed according to the IEC/IEEE Standard for Binary Floating-Point
2852: | Arithmetic---which means in particular that the conversion is rounded
2853: | according to the current rounding mode. If `a' is a NaN, the largest
2854: | positive integer is returned. Otherwise, if the conversion overflows, the
2855: | largest integer with the same sign as `a' is returned.
2856: *----------------------------------------------------------------------------*/
2857:
2858: int64 float64_to_int64( float64 a STATUS_PARAM )
2859: {
2860: flag aSign;
1.1.1.10! root 2861: int_fast16_t aExp, shiftCount;
1.1.1.8 root 2862: uint64_t aSig, aSigExtra;
1.1.1.7 root 2863: a = float64_squash_input_denormal(a STATUS_VAR);
1.1 root 2864:
2865: aSig = extractFloat64Frac( a );
2866: aExp = extractFloat64Exp( a );
2867: aSign = extractFloat64Sign( a );
2868: if ( aExp ) aSig |= LIT64( 0x0010000000000000 );
2869: shiftCount = 0x433 - aExp;
2870: if ( shiftCount <= 0 ) {
2871: if ( 0x43E < aExp ) {
2872: float_raise( float_flag_invalid STATUS_VAR);
2873: if ( ! aSign
2874: || ( ( aExp == 0x7FF )
2875: && ( aSig != LIT64( 0x0010000000000000 ) ) )
2876: ) {
2877: return LIT64( 0x7FFFFFFFFFFFFFFF );
2878: }
1.1.1.8 root 2879: return (int64_t) LIT64( 0x8000000000000000 );
1.1 root 2880: }
2881: aSigExtra = 0;
2882: aSig <<= - shiftCount;
2883: }
2884: else {
2885: shift64ExtraRightJamming( aSig, 0, shiftCount, &aSig, &aSigExtra );
2886: }
2887: return roundAndPackInt64( aSign, aSig, aSigExtra STATUS_VAR );
2888:
2889: }
2890:
2891: /*----------------------------------------------------------------------------
2892: | Returns the result of converting the double-precision floating-point value
2893: | `a' to the 64-bit two's complement integer format. The conversion is
2894: | performed according to the IEC/IEEE Standard for Binary Floating-Point
2895: | Arithmetic, except that the conversion is always rounded toward zero.
2896: | If `a' is a NaN, the largest positive integer is returned. Otherwise, if
2897: | the conversion overflows, the largest integer with the same sign as `a' is
2898: | returned.
2899: *----------------------------------------------------------------------------*/
2900:
2901: int64 float64_to_int64_round_to_zero( float64 a STATUS_PARAM )
2902: {
2903: flag aSign;
1.1.1.10! root 2904: int_fast16_t aExp, shiftCount;
1.1.1.8 root 2905: uint64_t aSig;
1.1 root 2906: int64 z;
1.1.1.7 root 2907: a = float64_squash_input_denormal(a STATUS_VAR);
1.1 root 2908:
2909: aSig = extractFloat64Frac( a );
2910: aExp = extractFloat64Exp( a );
2911: aSign = extractFloat64Sign( a );
2912: if ( aExp ) aSig |= LIT64( 0x0010000000000000 );
2913: shiftCount = aExp - 0x433;
2914: if ( 0 <= shiftCount ) {
2915: if ( 0x43E <= aExp ) {
1.1.1.3 root 2916: if ( float64_val(a) != LIT64( 0xC3E0000000000000 ) ) {
1.1 root 2917: float_raise( float_flag_invalid STATUS_VAR);
2918: if ( ! aSign
2919: || ( ( aExp == 0x7FF )
2920: && ( aSig != LIT64( 0x0010000000000000 ) ) )
2921: ) {
2922: return LIT64( 0x7FFFFFFFFFFFFFFF );
2923: }
2924: }
1.1.1.8 root 2925: return (int64_t) LIT64( 0x8000000000000000 );
1.1 root 2926: }
2927: z = aSig<<shiftCount;
2928: }
2929: else {
2930: if ( aExp < 0x3FE ) {
2931: if ( aExp | aSig ) STATUS(float_exception_flags) |= float_flag_inexact;
2932: return 0;
2933: }
2934: z = aSig>>( - shiftCount );
1.1.1.8 root 2935: if ( (uint64_t) ( aSig<<( shiftCount & 63 ) ) ) {
1.1 root 2936: STATUS(float_exception_flags) |= float_flag_inexact;
2937: }
2938: }
2939: if ( aSign ) z = - z;
2940: return z;
2941:
2942: }
2943:
2944: /*----------------------------------------------------------------------------
2945: | Returns the result of converting the double-precision floating-point value
2946: | `a' to the single-precision floating-point format. The conversion is
2947: | performed according to the IEC/IEEE Standard for Binary Floating-Point
2948: | Arithmetic.
2949: *----------------------------------------------------------------------------*/
2950:
2951: float32 float64_to_float32( float64 a STATUS_PARAM )
2952: {
2953: flag aSign;
1.1.1.10! root 2954: int_fast16_t aExp;
1.1.1.8 root 2955: uint64_t aSig;
2956: uint32_t zSig;
1.1.1.7 root 2957: a = float64_squash_input_denormal(a STATUS_VAR);
1.1 root 2958:
2959: aSig = extractFloat64Frac( a );
2960: aExp = extractFloat64Exp( a );
2961: aSign = extractFloat64Sign( a );
2962: if ( aExp == 0x7FF ) {
1.1.1.8 root 2963: if ( aSig ) return commonNaNToFloat32( float64ToCommonNaN( a STATUS_VAR ) STATUS_VAR );
1.1 root 2964: return packFloat32( aSign, 0xFF, 0 );
2965: }
2966: shift64RightJamming( aSig, 22, &aSig );
2967: zSig = aSig;
2968: if ( aExp || zSig ) {
2969: zSig |= 0x40000000;
2970: aExp -= 0x381;
2971: }
2972: return roundAndPackFloat32( aSign, aExp, zSig STATUS_VAR );
2973:
2974: }
2975:
1.1.1.5 root 2976:
2977: /*----------------------------------------------------------------------------
2978: | Packs the sign `zSign', exponent `zExp', and significand `zSig' into a
2979: | half-precision floating-point value, returning the result. After being
2980: | shifted into the proper positions, the three fields are simply added
2981: | together to form the result. This means that any integer portion of `zSig'
2982: | will be added into the exponent. Since a properly normalized significand
2983: | will have an integer portion equal to 1, the `zExp' input should be 1 less
2984: | than the desired result exponent whenever `zSig' is a complete, normalized
2985: | significand.
2986: *----------------------------------------------------------------------------*/
1.1.1.10! root 2987: static float16 packFloat16(flag zSign, int_fast16_t zExp, uint16_t zSig)
1.1.1.5 root 2988: {
1.1.1.8 root 2989: return make_float16(
2990: (((uint32_t)zSign) << 15) + (((uint32_t)zExp) << 10) + zSig);
1.1.1.5 root 2991: }
2992:
2993: /* Half precision floats come in two formats: standard IEEE and "ARM" format.
2994: The latter gains extra exponent range by omitting the NaN/Inf encodings. */
1.1.1.8 root 2995:
2996: float32 float16_to_float32(float16 a, flag ieee STATUS_PARAM)
1.1.1.5 root 2997: {
2998: flag aSign;
1.1.1.10! root 2999: int_fast16_t aExp;
1.1.1.8 root 3000: uint32_t aSig;
1.1.1.5 root 3001:
1.1.1.8 root 3002: aSign = extractFloat16Sign(a);
3003: aExp = extractFloat16Exp(a);
3004: aSig = extractFloat16Frac(a);
1.1.1.5 root 3005:
3006: if (aExp == 0x1f && ieee) {
3007: if (aSig) {
1.1.1.8 root 3008: return commonNaNToFloat32(float16ToCommonNaN(a STATUS_VAR) STATUS_VAR);
1.1.1.5 root 3009: }
3010: return packFloat32(aSign, 0xff, aSig << 13);
3011: }
3012: if (aExp == 0) {
3013: int8 shiftCount;
3014:
3015: if (aSig == 0) {
3016: return packFloat32(aSign, 0, 0);
3017: }
3018:
3019: shiftCount = countLeadingZeros32( aSig ) - 21;
3020: aSig = aSig << shiftCount;
3021: aExp = -shiftCount;
3022: }
3023: return packFloat32( aSign, aExp + 0x70, aSig << 13);
3024: }
3025:
1.1.1.8 root 3026: float16 float32_to_float16(float32 a, flag ieee STATUS_PARAM)
1.1.1.5 root 3027: {
3028: flag aSign;
1.1.1.10! root 3029: int_fast16_t aExp;
1.1.1.8 root 3030: uint32_t aSig;
3031: uint32_t mask;
3032: uint32_t increment;
1.1.1.5 root 3033: int8 roundingMode;
1.1.1.7 root 3034: a = float32_squash_input_denormal(a STATUS_VAR);
1.1.1.5 root 3035:
3036: aSig = extractFloat32Frac( a );
3037: aExp = extractFloat32Exp( a );
3038: aSign = extractFloat32Sign( a );
3039: if ( aExp == 0xFF ) {
3040: if (aSig) {
1.1.1.8 root 3041: /* Input is a NaN */
3042: float16 r = commonNaNToFloat16( float32ToCommonNaN( a STATUS_VAR ) STATUS_VAR );
3043: if (!ieee) {
3044: return packFloat16(aSign, 0, 0);
3045: }
3046: return r;
3047: }
3048: /* Infinity */
3049: if (!ieee) {
3050: float_raise(float_flag_invalid STATUS_VAR);
3051: return packFloat16(aSign, 0x1f, 0x3ff);
1.1.1.5 root 3052: }
1.1.1.8 root 3053: return packFloat16(aSign, 0x1f, 0);
1.1.1.5 root 3054: }
1.1.1.8 root 3055: if (aExp == 0 && aSig == 0) {
1.1.1.5 root 3056: return packFloat16(aSign, 0, 0);
3057: }
3058: /* Decimal point between bits 22 and 23. */
3059: aSig |= 0x00800000;
3060: aExp -= 0x7f;
3061: if (aExp < -14) {
1.1.1.8 root 3062: mask = 0x00ffffff;
3063: if (aExp >= -24) {
3064: mask >>= 25 + aExp;
1.1.1.5 root 3065: }
3066: } else {
3067: mask = 0x00001fff;
3068: }
3069: if (aSig & mask) {
3070: float_raise( float_flag_underflow STATUS_VAR );
3071: roundingMode = STATUS(float_rounding_mode);
3072: switch (roundingMode) {
3073: case float_round_nearest_even:
3074: increment = (mask + 1) >> 1;
3075: if ((aSig & mask) == increment) {
3076: increment = aSig & (increment << 1);
3077: }
3078: break;
3079: case float_round_up:
3080: increment = aSign ? 0 : mask;
3081: break;
3082: case float_round_down:
3083: increment = aSign ? mask : 0;
3084: break;
3085: default: /* round_to_zero */
3086: increment = 0;
3087: break;
3088: }
3089: aSig += increment;
3090: if (aSig >= 0x01000000) {
3091: aSig >>= 1;
3092: aExp++;
3093: }
3094: } else if (aExp < -14
3095: && STATUS(float_detect_tininess) == float_tininess_before_rounding) {
3096: float_raise( float_flag_underflow STATUS_VAR);
3097: }
3098:
3099: if (ieee) {
3100: if (aExp > 15) {
3101: float_raise( float_flag_overflow | float_flag_inexact STATUS_VAR);
3102: return packFloat16(aSign, 0x1f, 0);
3103: }
3104: } else {
3105: if (aExp > 16) {
1.1.1.8 root 3106: float_raise(float_flag_invalid | float_flag_inexact STATUS_VAR);
1.1.1.5 root 3107: return packFloat16(aSign, 0x1f, 0x3ff);
3108: }
3109: }
3110: if (aExp < -24) {
3111: return packFloat16(aSign, 0, 0);
3112: }
3113: if (aExp < -14) {
3114: aSig >>= -14 - aExp;
3115: aExp = -14;
3116: }
3117: return packFloat16(aSign, aExp + 14, aSig >> 13);
3118: }
3119:
1.1 root 3120: /*----------------------------------------------------------------------------
3121: | Returns the result of converting the double-precision floating-point value
3122: | `a' to the extended double-precision floating-point format. The conversion
3123: | is performed according to the IEC/IEEE Standard for Binary Floating-Point
3124: | Arithmetic.
3125: *----------------------------------------------------------------------------*/
3126:
3127: floatx80 float64_to_floatx80( float64 a STATUS_PARAM )
3128: {
3129: flag aSign;
1.1.1.10! root 3130: int_fast16_t aExp;
1.1.1.8 root 3131: uint64_t aSig;
1.1 root 3132:
1.1.1.7 root 3133: a = float64_squash_input_denormal(a STATUS_VAR);
1.1 root 3134: aSig = extractFloat64Frac( a );
3135: aExp = extractFloat64Exp( a );
3136: aSign = extractFloat64Sign( a );
3137: if ( aExp == 0x7FF ) {
1.1.1.8 root 3138: if ( aSig ) return commonNaNToFloatx80( float64ToCommonNaN( a STATUS_VAR ) STATUS_VAR );
1.1 root 3139: return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
3140: }
3141: if ( aExp == 0 ) {
3142: if ( aSig == 0 ) return packFloatx80( aSign, 0, 0 );
3143: normalizeFloat64Subnormal( aSig, &aExp, &aSig );
3144: }
3145: return
3146: packFloatx80(
3147: aSign, aExp + 0x3C00, ( aSig | LIT64( 0x0010000000000000 ) )<<11 );
3148:
3149: }
3150:
3151: /*----------------------------------------------------------------------------
3152: | Returns the result of converting the double-precision floating-point value
3153: | `a' to the quadruple-precision floating-point format. The conversion is
3154: | performed according to the IEC/IEEE Standard for Binary Floating-Point
3155: | Arithmetic.
3156: *----------------------------------------------------------------------------*/
3157:
3158: float128 float64_to_float128( float64 a STATUS_PARAM )
3159: {
3160: flag aSign;
1.1.1.10! root 3161: int_fast16_t aExp;
1.1.1.8 root 3162: uint64_t aSig, zSig0, zSig1;
1.1 root 3163:
1.1.1.7 root 3164: a = float64_squash_input_denormal(a STATUS_VAR);
1.1 root 3165: aSig = extractFloat64Frac( a );
3166: aExp = extractFloat64Exp( a );
3167: aSign = extractFloat64Sign( a );
3168: if ( aExp == 0x7FF ) {
1.1.1.8 root 3169: if ( aSig ) return commonNaNToFloat128( float64ToCommonNaN( a STATUS_VAR ) STATUS_VAR );
1.1 root 3170: return packFloat128( aSign, 0x7FFF, 0, 0 );
3171: }
3172: if ( aExp == 0 ) {
3173: if ( aSig == 0 ) return packFloat128( aSign, 0, 0, 0 );
3174: normalizeFloat64Subnormal( aSig, &aExp, &aSig );
3175: --aExp;
3176: }
3177: shift128Right( aSig, 0, 4, &zSig0, &zSig1 );
3178: return packFloat128( aSign, aExp + 0x3C00, zSig0, zSig1 );
3179:
3180: }
3181:
3182: /*----------------------------------------------------------------------------
3183: | Rounds the double-precision floating-point value `a' to an integer, and
3184: | returns the result as a double-precision floating-point value. The
3185: | operation is performed according to the IEC/IEEE Standard for Binary
3186: | Floating-Point Arithmetic.
3187: *----------------------------------------------------------------------------*/
3188:
3189: float64 float64_round_to_int( float64 a STATUS_PARAM )
3190: {
3191: flag aSign;
1.1.1.10! root 3192: int_fast16_t aExp;
1.1.1.8 root 3193: uint64_t lastBitMask, roundBitsMask;
1.1 root 3194: int8 roundingMode;
1.1.1.8 root 3195: uint64_t z;
1.1.1.7 root 3196: a = float64_squash_input_denormal(a STATUS_VAR);
1.1 root 3197:
3198: aExp = extractFloat64Exp( a );
3199: if ( 0x433 <= aExp ) {
3200: if ( ( aExp == 0x7FF ) && extractFloat64Frac( a ) ) {
3201: return propagateFloat64NaN( a, a STATUS_VAR );
3202: }
3203: return a;
3204: }
3205: if ( aExp < 0x3FF ) {
1.1.1.8 root 3206: if ( (uint64_t) ( float64_val(a)<<1 ) == 0 ) return a;
1.1 root 3207: STATUS(float_exception_flags) |= float_flag_inexact;
3208: aSign = extractFloat64Sign( a );
3209: switch ( STATUS(float_rounding_mode) ) {
3210: case float_round_nearest_even:
3211: if ( ( aExp == 0x3FE ) && extractFloat64Frac( a ) ) {
3212: return packFloat64( aSign, 0x3FF, 0 );
3213: }
3214: break;
3215: case float_round_down:
1.1.1.3 root 3216: return make_float64(aSign ? LIT64( 0xBFF0000000000000 ) : 0);
1.1 root 3217: case float_round_up:
1.1.1.3 root 3218: return make_float64(
3219: aSign ? LIT64( 0x8000000000000000 ) : LIT64( 0x3FF0000000000000 ));
1.1 root 3220: }
3221: return packFloat64( aSign, 0, 0 );
3222: }
3223: lastBitMask = 1;
3224: lastBitMask <<= 0x433 - aExp;
3225: roundBitsMask = lastBitMask - 1;
1.1.1.3 root 3226: z = float64_val(a);
1.1 root 3227: roundingMode = STATUS(float_rounding_mode);
3228: if ( roundingMode == float_round_nearest_even ) {
3229: z += lastBitMask>>1;
3230: if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask;
3231: }
3232: else if ( roundingMode != float_round_to_zero ) {
1.1.1.3 root 3233: if ( extractFloat64Sign( make_float64(z) ) ^ ( roundingMode == float_round_up ) ) {
1.1 root 3234: z += roundBitsMask;
3235: }
3236: }
3237: z &= ~ roundBitsMask;
1.1.1.3 root 3238: if ( z != float64_val(a) )
3239: STATUS(float_exception_flags) |= float_flag_inexact;
3240: return make_float64(z);
1.1 root 3241:
3242: }
3243:
1.1.1.2 root 3244: float64 float64_trunc_to_int( float64 a STATUS_PARAM)
3245: {
3246: int oldmode;
3247: float64 res;
3248: oldmode = STATUS(float_rounding_mode);
3249: STATUS(float_rounding_mode) = float_round_to_zero;
3250: res = float64_round_to_int(a STATUS_VAR);
3251: STATUS(float_rounding_mode) = oldmode;
3252: return res;
3253: }
3254:
1.1 root 3255: /*----------------------------------------------------------------------------
3256: | Returns the result of adding the absolute values of the double-precision
3257: | floating-point values `a' and `b'. If `zSign' is 1, the sum is negated
3258: | before being returned. `zSign' is ignored if the result is a NaN.
3259: | The addition is performed according to the IEC/IEEE Standard for Binary
3260: | Floating-Point Arithmetic.
3261: *----------------------------------------------------------------------------*/
3262:
3263: static float64 addFloat64Sigs( float64 a, float64 b, flag zSign STATUS_PARAM )
3264: {
1.1.1.10! root 3265: int_fast16_t aExp, bExp, zExp;
1.1.1.8 root 3266: uint64_t aSig, bSig, zSig;
1.1.1.10! root 3267: int_fast16_t expDiff;
1.1 root 3268:
3269: aSig = extractFloat64Frac( a );
3270: aExp = extractFloat64Exp( a );
3271: bSig = extractFloat64Frac( b );
3272: bExp = extractFloat64Exp( b );
3273: expDiff = aExp - bExp;
3274: aSig <<= 9;
3275: bSig <<= 9;
3276: if ( 0 < expDiff ) {
3277: if ( aExp == 0x7FF ) {
3278: if ( aSig ) return propagateFloat64NaN( a, b STATUS_VAR );
3279: return a;
3280: }
3281: if ( bExp == 0 ) {
3282: --expDiff;
3283: }
3284: else {
3285: bSig |= LIT64( 0x2000000000000000 );
3286: }
3287: shift64RightJamming( bSig, expDiff, &bSig );
3288: zExp = aExp;
3289: }
3290: else if ( expDiff < 0 ) {
3291: if ( bExp == 0x7FF ) {
3292: if ( bSig ) return propagateFloat64NaN( a, b STATUS_VAR );
3293: return packFloat64( zSign, 0x7FF, 0 );
3294: }
3295: if ( aExp == 0 ) {
3296: ++expDiff;
3297: }
3298: else {
3299: aSig |= LIT64( 0x2000000000000000 );
3300: }
3301: shift64RightJamming( aSig, - expDiff, &aSig );
3302: zExp = bExp;
3303: }
3304: else {
3305: if ( aExp == 0x7FF ) {
3306: if ( aSig | bSig ) return propagateFloat64NaN( a, b STATUS_VAR );
3307: return a;
3308: }
1.1.1.4 root 3309: if ( aExp == 0 ) {
1.1.1.8 root 3310: if (STATUS(flush_to_zero)) {
3311: if (aSig | bSig) {
3312: float_raise(float_flag_output_denormal STATUS_VAR);
3313: }
3314: return packFloat64(zSign, 0, 0);
3315: }
1.1.1.4 root 3316: return packFloat64( zSign, 0, ( aSig + bSig )>>9 );
3317: }
1.1 root 3318: zSig = LIT64( 0x4000000000000000 ) + aSig + bSig;
3319: zExp = aExp;
3320: goto roundAndPack;
3321: }
3322: aSig |= LIT64( 0x2000000000000000 );
3323: zSig = ( aSig + bSig )<<1;
3324: --zExp;
1.1.1.8 root 3325: if ( (int64_t) zSig < 0 ) {
1.1 root 3326: zSig = aSig + bSig;
3327: ++zExp;
3328: }
3329: roundAndPack:
3330: return roundAndPackFloat64( zSign, zExp, zSig STATUS_VAR );
3331:
3332: }
3333:
3334: /*----------------------------------------------------------------------------
3335: | Returns the result of subtracting the absolute values of the double-
3336: | precision floating-point values `a' and `b'. If `zSign' is 1, the
3337: | difference is negated before being returned. `zSign' is ignored if the
3338: | result is a NaN. The subtraction is performed according to the IEC/IEEE
3339: | Standard for Binary Floating-Point Arithmetic.
3340: *----------------------------------------------------------------------------*/
3341:
3342: static float64 subFloat64Sigs( float64 a, float64 b, flag zSign STATUS_PARAM )
3343: {
1.1.1.10! root 3344: int_fast16_t aExp, bExp, zExp;
1.1.1.8 root 3345: uint64_t aSig, bSig, zSig;
1.1.1.10! root 3346: int_fast16_t expDiff;
1.1 root 3347:
3348: aSig = extractFloat64Frac( a );
3349: aExp = extractFloat64Exp( a );
3350: bSig = extractFloat64Frac( b );
3351: bExp = extractFloat64Exp( b );
3352: expDiff = aExp - bExp;
3353: aSig <<= 10;
3354: bSig <<= 10;
3355: if ( 0 < expDiff ) goto aExpBigger;
3356: if ( expDiff < 0 ) goto bExpBigger;
3357: if ( aExp == 0x7FF ) {
3358: if ( aSig | bSig ) return propagateFloat64NaN( a, b STATUS_VAR );
3359: float_raise( float_flag_invalid STATUS_VAR);
3360: return float64_default_nan;
3361: }
3362: if ( aExp == 0 ) {
3363: aExp = 1;
3364: bExp = 1;
3365: }
3366: if ( bSig < aSig ) goto aBigger;
3367: if ( aSig < bSig ) goto bBigger;
3368: return packFloat64( STATUS(float_rounding_mode) == float_round_down, 0, 0 );
3369: bExpBigger:
3370: if ( bExp == 0x7FF ) {
3371: if ( bSig ) return propagateFloat64NaN( a, b STATUS_VAR );
3372: return packFloat64( zSign ^ 1, 0x7FF, 0 );
3373: }
3374: if ( aExp == 0 ) {
3375: ++expDiff;
3376: }
3377: else {
3378: aSig |= LIT64( 0x4000000000000000 );
3379: }
3380: shift64RightJamming( aSig, - expDiff, &aSig );
3381: bSig |= LIT64( 0x4000000000000000 );
3382: bBigger:
3383: zSig = bSig - aSig;
3384: zExp = bExp;
3385: zSign ^= 1;
3386: goto normalizeRoundAndPack;
3387: aExpBigger:
3388: if ( aExp == 0x7FF ) {
3389: if ( aSig ) return propagateFloat64NaN( a, b STATUS_VAR );
3390: return a;
3391: }
3392: if ( bExp == 0 ) {
3393: --expDiff;
3394: }
3395: else {
3396: bSig |= LIT64( 0x4000000000000000 );
3397: }
3398: shift64RightJamming( bSig, expDiff, &bSig );
3399: aSig |= LIT64( 0x4000000000000000 );
3400: aBigger:
3401: zSig = aSig - bSig;
3402: zExp = aExp;
3403: normalizeRoundAndPack:
3404: --zExp;
3405: return normalizeRoundAndPackFloat64( zSign, zExp, zSig STATUS_VAR );
3406:
3407: }
3408:
3409: /*----------------------------------------------------------------------------
3410: | Returns the result of adding the double-precision floating-point values `a'
3411: | and `b'. The operation is performed according to the IEC/IEEE Standard for
3412: | Binary Floating-Point Arithmetic.
3413: *----------------------------------------------------------------------------*/
3414:
3415: float64 float64_add( float64 a, float64 b STATUS_PARAM )
3416: {
3417: flag aSign, bSign;
1.1.1.7 root 3418: a = float64_squash_input_denormal(a STATUS_VAR);
3419: b = float64_squash_input_denormal(b STATUS_VAR);
1.1 root 3420:
3421: aSign = extractFloat64Sign( a );
3422: bSign = extractFloat64Sign( b );
3423: if ( aSign == bSign ) {
3424: return addFloat64Sigs( a, b, aSign STATUS_VAR );
3425: }
3426: else {
3427: return subFloat64Sigs( a, b, aSign STATUS_VAR );
3428: }
3429:
3430: }
3431:
3432: /*----------------------------------------------------------------------------
3433: | Returns the result of subtracting the double-precision floating-point values
3434: | `a' and `b'. The operation is performed according to the IEC/IEEE Standard
3435: | for Binary Floating-Point Arithmetic.
3436: *----------------------------------------------------------------------------*/
3437:
3438: float64 float64_sub( float64 a, float64 b STATUS_PARAM )
3439: {
3440: flag aSign, bSign;
1.1.1.7 root 3441: a = float64_squash_input_denormal(a STATUS_VAR);
3442: b = float64_squash_input_denormal(b STATUS_VAR);
1.1 root 3443:
3444: aSign = extractFloat64Sign( a );
3445: bSign = extractFloat64Sign( b );
3446: if ( aSign == bSign ) {
3447: return subFloat64Sigs( a, b, aSign STATUS_VAR );
3448: }
3449: else {
3450: return addFloat64Sigs( a, b, aSign STATUS_VAR );
3451: }
3452:
3453: }
3454:
3455: /*----------------------------------------------------------------------------
3456: | Returns the result of multiplying the double-precision floating-point values
3457: | `a' and `b'. The operation is performed according to the IEC/IEEE Standard
3458: | for Binary Floating-Point Arithmetic.
3459: *----------------------------------------------------------------------------*/
3460:
3461: float64 float64_mul( float64 a, float64 b STATUS_PARAM )
3462: {
3463: flag aSign, bSign, zSign;
1.1.1.10! root 3464: int_fast16_t aExp, bExp, zExp;
1.1.1.8 root 3465: uint64_t aSig, bSig, zSig0, zSig1;
1.1 root 3466:
1.1.1.7 root 3467: a = float64_squash_input_denormal(a STATUS_VAR);
3468: b = float64_squash_input_denormal(b STATUS_VAR);
3469:
1.1 root 3470: aSig = extractFloat64Frac( a );
3471: aExp = extractFloat64Exp( a );
3472: aSign = extractFloat64Sign( a );
3473: bSig = extractFloat64Frac( b );
3474: bExp = extractFloat64Exp( b );
3475: bSign = extractFloat64Sign( b );
3476: zSign = aSign ^ bSign;
3477: if ( aExp == 0x7FF ) {
3478: if ( aSig || ( ( bExp == 0x7FF ) && bSig ) ) {
3479: return propagateFloat64NaN( a, b STATUS_VAR );
3480: }
3481: if ( ( bExp | bSig ) == 0 ) {
3482: float_raise( float_flag_invalid STATUS_VAR);
3483: return float64_default_nan;
3484: }
3485: return packFloat64( zSign, 0x7FF, 0 );
3486: }
3487: if ( bExp == 0x7FF ) {
3488: if ( bSig ) return propagateFloat64NaN( a, b STATUS_VAR );
3489: if ( ( aExp | aSig ) == 0 ) {
3490: float_raise( float_flag_invalid STATUS_VAR);
3491: return float64_default_nan;
3492: }
3493: return packFloat64( zSign, 0x7FF, 0 );
3494: }
3495: if ( aExp == 0 ) {
3496: if ( aSig == 0 ) return packFloat64( zSign, 0, 0 );
3497: normalizeFloat64Subnormal( aSig, &aExp, &aSig );
3498: }
3499: if ( bExp == 0 ) {
3500: if ( bSig == 0 ) return packFloat64( zSign, 0, 0 );
3501: normalizeFloat64Subnormal( bSig, &bExp, &bSig );
3502: }
3503: zExp = aExp + bExp - 0x3FF;
3504: aSig = ( aSig | LIT64( 0x0010000000000000 ) )<<10;
3505: bSig = ( bSig | LIT64( 0x0010000000000000 ) )<<11;
3506: mul64To128( aSig, bSig, &zSig0, &zSig1 );
3507: zSig0 |= ( zSig1 != 0 );
1.1.1.8 root 3508: if ( 0 <= (int64_t) ( zSig0<<1 ) ) {
1.1 root 3509: zSig0 <<= 1;
3510: --zExp;
3511: }
3512: return roundAndPackFloat64( zSign, zExp, zSig0 STATUS_VAR );
3513:
3514: }
3515:
3516: /*----------------------------------------------------------------------------
3517: | Returns the result of dividing the double-precision floating-point value `a'
3518: | by the corresponding value `b'. The operation is performed according to
3519: | the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
3520: *----------------------------------------------------------------------------*/
3521:
3522: float64 float64_div( float64 a, float64 b STATUS_PARAM )
3523: {
3524: flag aSign, bSign, zSign;
1.1.1.10! root 3525: int_fast16_t aExp, bExp, zExp;
1.1.1.8 root 3526: uint64_t aSig, bSig, zSig;
3527: uint64_t rem0, rem1;
3528: uint64_t term0, term1;
1.1.1.7 root 3529: a = float64_squash_input_denormal(a STATUS_VAR);
3530: b = float64_squash_input_denormal(b STATUS_VAR);
1.1 root 3531:
3532: aSig = extractFloat64Frac( a );
3533: aExp = extractFloat64Exp( a );
3534: aSign = extractFloat64Sign( a );
3535: bSig = extractFloat64Frac( b );
3536: bExp = extractFloat64Exp( b );
3537: bSign = extractFloat64Sign( b );
3538: zSign = aSign ^ bSign;
3539: if ( aExp == 0x7FF ) {
3540: if ( aSig ) return propagateFloat64NaN( a, b STATUS_VAR );
3541: if ( bExp == 0x7FF ) {
3542: if ( bSig ) return propagateFloat64NaN( a, b STATUS_VAR );
3543: float_raise( float_flag_invalid STATUS_VAR);
3544: return float64_default_nan;
3545: }
3546: return packFloat64( zSign, 0x7FF, 0 );
3547: }
3548: if ( bExp == 0x7FF ) {
3549: if ( bSig ) return propagateFloat64NaN( a, b STATUS_VAR );
3550: return packFloat64( zSign, 0, 0 );
3551: }
3552: if ( bExp == 0 ) {
3553: if ( bSig == 0 ) {
3554: if ( ( aExp | aSig ) == 0 ) {
3555: float_raise( float_flag_invalid STATUS_VAR);
3556: return float64_default_nan;
3557: }
3558: float_raise( float_flag_divbyzero STATUS_VAR);
3559: return packFloat64( zSign, 0x7FF, 0 );
3560: }
3561: normalizeFloat64Subnormal( bSig, &bExp, &bSig );
3562: }
3563: if ( aExp == 0 ) {
3564: if ( aSig == 0 ) return packFloat64( zSign, 0, 0 );
3565: normalizeFloat64Subnormal( aSig, &aExp, &aSig );
3566: }
3567: zExp = aExp - bExp + 0x3FD;
3568: aSig = ( aSig | LIT64( 0x0010000000000000 ) )<<10;
3569: bSig = ( bSig | LIT64( 0x0010000000000000 ) )<<11;
3570: if ( bSig <= ( aSig + aSig ) ) {
3571: aSig >>= 1;
3572: ++zExp;
3573: }
3574: zSig = estimateDiv128To64( aSig, 0, bSig );
3575: if ( ( zSig & 0x1FF ) <= 2 ) {
3576: mul64To128( bSig, zSig, &term0, &term1 );
3577: sub128( aSig, 0, term0, term1, &rem0, &rem1 );
1.1.1.8 root 3578: while ( (int64_t) rem0 < 0 ) {
1.1 root 3579: --zSig;
3580: add128( rem0, rem1, 0, bSig, &rem0, &rem1 );
3581: }
3582: zSig |= ( rem1 != 0 );
3583: }
3584: return roundAndPackFloat64( zSign, zExp, zSig STATUS_VAR );
3585:
3586: }
3587:
3588: /*----------------------------------------------------------------------------
3589: | Returns the remainder of the double-precision floating-point value `a'
3590: | with respect to the corresponding value `b'. The operation is performed
3591: | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
3592: *----------------------------------------------------------------------------*/
3593:
3594: float64 float64_rem( float64 a, float64 b STATUS_PARAM )
3595: {
1.1.1.6 root 3596: flag aSign, zSign;
1.1.1.10! root 3597: int_fast16_t aExp, bExp, expDiff;
1.1.1.8 root 3598: uint64_t aSig, bSig;
3599: uint64_t q, alternateASig;
3600: int64_t sigMean;
1.1 root 3601:
1.1.1.7 root 3602: a = float64_squash_input_denormal(a STATUS_VAR);
3603: b = float64_squash_input_denormal(b STATUS_VAR);
1.1 root 3604: aSig = extractFloat64Frac( a );
3605: aExp = extractFloat64Exp( a );
3606: aSign = extractFloat64Sign( a );
3607: bSig = extractFloat64Frac( b );
3608: bExp = extractFloat64Exp( b );
3609: if ( aExp == 0x7FF ) {
3610: if ( aSig || ( ( bExp == 0x7FF ) && bSig ) ) {
3611: return propagateFloat64NaN( a, b STATUS_VAR );
3612: }
3613: float_raise( float_flag_invalid STATUS_VAR);
3614: return float64_default_nan;
3615: }
3616: if ( bExp == 0x7FF ) {
3617: if ( bSig ) return propagateFloat64NaN( a, b STATUS_VAR );
3618: return a;
3619: }
3620: if ( bExp == 0 ) {
3621: if ( bSig == 0 ) {
3622: float_raise( float_flag_invalid STATUS_VAR);
3623: return float64_default_nan;
3624: }
3625: normalizeFloat64Subnormal( bSig, &bExp, &bSig );
3626: }
3627: if ( aExp == 0 ) {
3628: if ( aSig == 0 ) return a;
3629: normalizeFloat64Subnormal( aSig, &aExp, &aSig );
3630: }
3631: expDiff = aExp - bExp;
3632: aSig = ( aSig | LIT64( 0x0010000000000000 ) )<<11;
3633: bSig = ( bSig | LIT64( 0x0010000000000000 ) )<<11;
3634: if ( expDiff < 0 ) {
3635: if ( expDiff < -1 ) return a;
3636: aSig >>= 1;
3637: }
3638: q = ( bSig <= aSig );
3639: if ( q ) aSig -= bSig;
3640: expDiff -= 64;
3641: while ( 0 < expDiff ) {
3642: q = estimateDiv128To64( aSig, 0, bSig );
3643: q = ( 2 < q ) ? q - 2 : 0;
3644: aSig = - ( ( bSig>>2 ) * q );
3645: expDiff -= 62;
3646: }
3647: expDiff += 64;
3648: if ( 0 < expDiff ) {
3649: q = estimateDiv128To64( aSig, 0, bSig );
3650: q = ( 2 < q ) ? q - 2 : 0;
3651: q >>= 64 - expDiff;
3652: bSig >>= 2;
3653: aSig = ( ( aSig>>1 )<<( expDiff - 1 ) ) - bSig * q;
3654: }
3655: else {
3656: aSig >>= 2;
3657: bSig >>= 2;
3658: }
3659: do {
3660: alternateASig = aSig;
3661: ++q;
3662: aSig -= bSig;
1.1.1.8 root 3663: } while ( 0 <= (int64_t) aSig );
1.1 root 3664: sigMean = aSig + alternateASig;
3665: if ( ( sigMean < 0 ) || ( ( sigMean == 0 ) && ( q & 1 ) ) ) {
3666: aSig = alternateASig;
3667: }
1.1.1.8 root 3668: zSign = ( (int64_t) aSig < 0 );
1.1 root 3669: if ( zSign ) aSig = - aSig;
3670: return normalizeRoundAndPackFloat64( aSign ^ zSign, bExp, aSig STATUS_VAR );
3671:
3672: }
3673:
3674: /*----------------------------------------------------------------------------
1.1.1.9 root 3675: | Returns the result of multiplying the double-precision floating-point values
3676: | `a' and `b' then adding 'c', with no intermediate rounding step after the
3677: | multiplication. The operation is performed according to the IEC/IEEE
3678: | Standard for Binary Floating-Point Arithmetic 754-2008.
3679: | The flags argument allows the caller to select negation of the
3680: | addend, the intermediate product, or the final result. (The difference
3681: | between this and having the caller do a separate negation is that negating
3682: | externally will flip the sign bit on NaNs.)
3683: *----------------------------------------------------------------------------*/
3684:
3685: float64 float64_muladd(float64 a, float64 b, float64 c, int flags STATUS_PARAM)
3686: {
3687: flag aSign, bSign, cSign, zSign;
1.1.1.10! root 3688: int_fast16_t aExp, bExp, cExp, pExp, zExp, expDiff;
1.1.1.9 root 3689: uint64_t aSig, bSig, cSig;
3690: flag pInf, pZero, pSign;
3691: uint64_t pSig0, pSig1, cSig0, cSig1, zSig0, zSig1;
3692: int shiftcount;
3693: flag signflip, infzero;
3694:
3695: a = float64_squash_input_denormal(a STATUS_VAR);
3696: b = float64_squash_input_denormal(b STATUS_VAR);
3697: c = float64_squash_input_denormal(c STATUS_VAR);
3698: aSig = extractFloat64Frac(a);
3699: aExp = extractFloat64Exp(a);
3700: aSign = extractFloat64Sign(a);
3701: bSig = extractFloat64Frac(b);
3702: bExp = extractFloat64Exp(b);
3703: bSign = extractFloat64Sign(b);
3704: cSig = extractFloat64Frac(c);
3705: cExp = extractFloat64Exp(c);
3706: cSign = extractFloat64Sign(c);
3707:
3708: infzero = ((aExp == 0 && aSig == 0 && bExp == 0x7ff && bSig == 0) ||
3709: (aExp == 0x7ff && aSig == 0 && bExp == 0 && bSig == 0));
3710:
3711: /* It is implementation-defined whether the cases of (0,inf,qnan)
3712: * and (inf,0,qnan) raise InvalidOperation or not (and what QNaN
3713: * they return if they do), so we have to hand this information
3714: * off to the target-specific pick-a-NaN routine.
3715: */
3716: if (((aExp == 0x7ff) && aSig) ||
3717: ((bExp == 0x7ff) && bSig) ||
3718: ((cExp == 0x7ff) && cSig)) {
3719: return propagateFloat64MulAddNaN(a, b, c, infzero STATUS_VAR);
3720: }
3721:
3722: if (infzero) {
3723: float_raise(float_flag_invalid STATUS_VAR);
3724: return float64_default_nan;
3725: }
3726:
3727: if (flags & float_muladd_negate_c) {
3728: cSign ^= 1;
3729: }
3730:
3731: signflip = (flags & float_muladd_negate_result) ? 1 : 0;
3732:
3733: /* Work out the sign and type of the product */
3734: pSign = aSign ^ bSign;
3735: if (flags & float_muladd_negate_product) {
3736: pSign ^= 1;
3737: }
3738: pInf = (aExp == 0x7ff) || (bExp == 0x7ff);
3739: pZero = ((aExp | aSig) == 0) || ((bExp | bSig) == 0);
3740:
3741: if (cExp == 0x7ff) {
3742: if (pInf && (pSign ^ cSign)) {
3743: /* addition of opposite-signed infinities => InvalidOperation */
3744: float_raise(float_flag_invalid STATUS_VAR);
3745: return float64_default_nan;
3746: }
3747: /* Otherwise generate an infinity of the same sign */
3748: return packFloat64(cSign ^ signflip, 0x7ff, 0);
3749: }
3750:
3751: if (pInf) {
3752: return packFloat64(pSign ^ signflip, 0x7ff, 0);
3753: }
3754:
3755: if (pZero) {
3756: if (cExp == 0) {
3757: if (cSig == 0) {
3758: /* Adding two exact zeroes */
3759: if (pSign == cSign) {
3760: zSign = pSign;
3761: } else if (STATUS(float_rounding_mode) == float_round_down) {
3762: zSign = 1;
3763: } else {
3764: zSign = 0;
3765: }
3766: return packFloat64(zSign ^ signflip, 0, 0);
3767: }
3768: /* Exact zero plus a denorm */
3769: if (STATUS(flush_to_zero)) {
3770: float_raise(float_flag_output_denormal STATUS_VAR);
3771: return packFloat64(cSign ^ signflip, 0, 0);
3772: }
3773: }
3774: /* Zero plus something non-zero : just return the something */
1.1.1.10! root 3775: return make_float64(float64_val(c) ^ ((uint64_t)signflip << 63));
1.1.1.9 root 3776: }
3777:
3778: if (aExp == 0) {
3779: normalizeFloat64Subnormal(aSig, &aExp, &aSig);
3780: }
3781: if (bExp == 0) {
3782: normalizeFloat64Subnormal(bSig, &bExp, &bSig);
3783: }
3784:
3785: /* Calculate the actual result a * b + c */
3786:
3787: /* Multiply first; this is easy. */
3788: /* NB: we subtract 0x3fe where float64_mul() subtracts 0x3ff
3789: * because we want the true exponent, not the "one-less-than"
3790: * flavour that roundAndPackFloat64() takes.
3791: */
3792: pExp = aExp + bExp - 0x3fe;
3793: aSig = (aSig | LIT64(0x0010000000000000))<<10;
3794: bSig = (bSig | LIT64(0x0010000000000000))<<11;
3795: mul64To128(aSig, bSig, &pSig0, &pSig1);
3796: if ((int64_t)(pSig0 << 1) >= 0) {
3797: shortShift128Left(pSig0, pSig1, 1, &pSig0, &pSig1);
3798: pExp--;
3799: }
3800:
3801: zSign = pSign ^ signflip;
3802:
3803: /* Now [pSig0:pSig1] is the significand of the multiply, with the explicit
3804: * bit in position 126.
3805: */
3806: if (cExp == 0) {
3807: if (!cSig) {
3808: /* Throw out the special case of c being an exact zero now */
3809: shift128RightJamming(pSig0, pSig1, 64, &pSig0, &pSig1);
3810: return roundAndPackFloat64(zSign, pExp - 1,
3811: pSig1 STATUS_VAR);
3812: }
3813: normalizeFloat64Subnormal(cSig, &cExp, &cSig);
3814: }
3815:
3816: /* Shift cSig and add the explicit bit so [cSig0:cSig1] is the
3817: * significand of the addend, with the explicit bit in position 126.
3818: */
3819: cSig0 = cSig << (126 - 64 - 52);
3820: cSig1 = 0;
3821: cSig0 |= LIT64(0x4000000000000000);
3822: expDiff = pExp - cExp;
3823:
3824: if (pSign == cSign) {
3825: /* Addition */
3826: if (expDiff > 0) {
3827: /* scale c to match p */
3828: shift128RightJamming(cSig0, cSig1, expDiff, &cSig0, &cSig1);
3829: zExp = pExp;
3830: } else if (expDiff < 0) {
3831: /* scale p to match c */
3832: shift128RightJamming(pSig0, pSig1, -expDiff, &pSig0, &pSig1);
3833: zExp = cExp;
3834: } else {
3835: /* no scaling needed */
3836: zExp = cExp;
3837: }
3838: /* Add significands and make sure explicit bit ends up in posn 126 */
3839: add128(pSig0, pSig1, cSig0, cSig1, &zSig0, &zSig1);
3840: if ((int64_t)zSig0 < 0) {
3841: shift128RightJamming(zSig0, zSig1, 1, &zSig0, &zSig1);
3842: } else {
3843: zExp--;
3844: }
3845: shift128RightJamming(zSig0, zSig1, 64, &zSig0, &zSig1);
3846: return roundAndPackFloat64(zSign, zExp, zSig1 STATUS_VAR);
3847: } else {
3848: /* Subtraction */
3849: if (expDiff > 0) {
3850: shift128RightJamming(cSig0, cSig1, expDiff, &cSig0, &cSig1);
3851: sub128(pSig0, pSig1, cSig0, cSig1, &zSig0, &zSig1);
3852: zExp = pExp;
3853: } else if (expDiff < 0) {
3854: shift128RightJamming(pSig0, pSig1, -expDiff, &pSig0, &pSig1);
3855: sub128(cSig0, cSig1, pSig0, pSig1, &zSig0, &zSig1);
3856: zExp = cExp;
3857: zSign ^= 1;
3858: } else {
3859: zExp = pExp;
3860: if (lt128(cSig0, cSig1, pSig0, pSig1)) {
3861: sub128(pSig0, pSig1, cSig0, cSig1, &zSig0, &zSig1);
3862: } else if (lt128(pSig0, pSig1, cSig0, cSig1)) {
3863: sub128(cSig0, cSig1, pSig0, pSig1, &zSig0, &zSig1);
3864: zSign ^= 1;
3865: } else {
3866: /* Exact zero */
3867: zSign = signflip;
3868: if (STATUS(float_rounding_mode) == float_round_down) {
3869: zSign ^= 1;
3870: }
3871: return packFloat64(zSign, 0, 0);
3872: }
3873: }
3874: --zExp;
3875: /* Do the equivalent of normalizeRoundAndPackFloat64() but
3876: * starting with the significand in a pair of uint64_t.
3877: */
3878: if (zSig0) {
3879: shiftcount = countLeadingZeros64(zSig0) - 1;
3880: shortShift128Left(zSig0, zSig1, shiftcount, &zSig0, &zSig1);
3881: if (zSig1) {
3882: zSig0 |= 1;
3883: }
3884: zExp -= shiftcount;
3885: } else {
3886: shiftcount = countLeadingZeros64(zSig1) - 1;
3887: zSig0 = zSig1 << shiftcount;
3888: zExp -= (shiftcount + 64);
3889: }
3890: return roundAndPackFloat64(zSign, zExp, zSig0 STATUS_VAR);
3891: }
3892: }
3893:
3894: /*----------------------------------------------------------------------------
1.1 root 3895: | Returns the square root of the double-precision floating-point value `a'.
3896: | The operation is performed according to the IEC/IEEE Standard for Binary
3897: | Floating-Point Arithmetic.
3898: *----------------------------------------------------------------------------*/
3899:
3900: float64 float64_sqrt( float64 a STATUS_PARAM )
3901: {
3902: flag aSign;
1.1.1.10! root 3903: int_fast16_t aExp, zExp;
1.1.1.8 root 3904: uint64_t aSig, zSig, doubleZSig;
3905: uint64_t rem0, rem1, term0, term1;
1.1.1.7 root 3906: a = float64_squash_input_denormal(a STATUS_VAR);
1.1 root 3907:
3908: aSig = extractFloat64Frac( a );
3909: aExp = extractFloat64Exp( a );
3910: aSign = extractFloat64Sign( a );
3911: if ( aExp == 0x7FF ) {
3912: if ( aSig ) return propagateFloat64NaN( a, a STATUS_VAR );
3913: if ( ! aSign ) return a;
3914: float_raise( float_flag_invalid STATUS_VAR);
3915: return float64_default_nan;
3916: }
3917: if ( aSign ) {
3918: if ( ( aExp | aSig ) == 0 ) return a;
3919: float_raise( float_flag_invalid STATUS_VAR);
3920: return float64_default_nan;
3921: }
3922: if ( aExp == 0 ) {
1.1.1.3 root 3923: if ( aSig == 0 ) return float64_zero;
1.1 root 3924: normalizeFloat64Subnormal( aSig, &aExp, &aSig );
3925: }
3926: zExp = ( ( aExp - 0x3FF )>>1 ) + 0x3FE;
3927: aSig |= LIT64( 0x0010000000000000 );
3928: zSig = estimateSqrt32( aExp, aSig>>21 );
3929: aSig <<= 9 - ( aExp & 1 );
3930: zSig = estimateDiv128To64( aSig, 0, zSig<<32 ) + ( zSig<<30 );
3931: if ( ( zSig & 0x1FF ) <= 5 ) {
3932: doubleZSig = zSig<<1;
3933: mul64To128( zSig, zSig, &term0, &term1 );
3934: sub128( aSig, 0, term0, term1, &rem0, &rem1 );
1.1.1.8 root 3935: while ( (int64_t) rem0 < 0 ) {
1.1 root 3936: --zSig;
3937: doubleZSig -= 2;
3938: add128( rem0, rem1, zSig>>63, doubleZSig | 1, &rem0, &rem1 );
3939: }
3940: zSig |= ( ( rem0 | rem1 ) != 0 );
3941: }
3942: return roundAndPackFloat64( 0, zExp, zSig STATUS_VAR );
3943:
3944: }
3945:
3946: /*----------------------------------------------------------------------------
1.1.1.4 root 3947: | Returns the binary log of the double-precision floating-point value `a'.
3948: | The operation is performed according to the IEC/IEEE Standard for Binary
3949: | Floating-Point Arithmetic.
3950: *----------------------------------------------------------------------------*/
3951: float64 float64_log2( float64 a STATUS_PARAM )
3952: {
3953: flag aSign, zSign;
1.1.1.10! root 3954: int_fast16_t aExp;
1.1.1.8 root 3955: uint64_t aSig, aSig0, aSig1, zSig, i;
1.1.1.7 root 3956: a = float64_squash_input_denormal(a STATUS_VAR);
1.1.1.4 root 3957:
3958: aSig = extractFloat64Frac( a );
3959: aExp = extractFloat64Exp( a );
3960: aSign = extractFloat64Sign( a );
3961:
3962: if ( aExp == 0 ) {
3963: if ( aSig == 0 ) return packFloat64( 1, 0x7FF, 0 );
3964: normalizeFloat64Subnormal( aSig, &aExp, &aSig );
3965: }
3966: if ( aSign ) {
3967: float_raise( float_flag_invalid STATUS_VAR);
3968: return float64_default_nan;
3969: }
3970: if ( aExp == 0x7FF ) {
3971: if ( aSig ) return propagateFloat64NaN( a, float64_zero STATUS_VAR );
3972: return a;
3973: }
3974:
3975: aExp -= 0x3FF;
3976: aSig |= LIT64( 0x0010000000000000 );
3977: zSign = aExp < 0;
1.1.1.8 root 3978: zSig = (uint64_t)aExp << 52;
1.1.1.4 root 3979: for (i = 1LL << 51; i > 0; i >>= 1) {
3980: mul64To128( aSig, aSig, &aSig0, &aSig1 );
3981: aSig = ( aSig0 << 12 ) | ( aSig1 >> 52 );
3982: if ( aSig & LIT64( 0x0020000000000000 ) ) {
3983: aSig >>= 1;
3984: zSig |= i;
3985: }
3986: }
3987:
3988: if ( zSign )
3989: zSig = -zSig;
3990: return normalizeRoundAndPackFloat64( zSign, 0x408, zSig STATUS_VAR );
3991: }
3992:
3993: /*----------------------------------------------------------------------------
1.1 root 3994: | Returns 1 if the double-precision floating-point value `a' is equal to the
1.1.1.8 root 3995: | corresponding value `b', and 0 otherwise. The invalid exception is raised
3996: | if either operand is a NaN. Otherwise, the comparison is performed
1.1 root 3997: | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
3998: *----------------------------------------------------------------------------*/
3999:
1.1.1.2 root 4000: int float64_eq( float64 a, float64 b STATUS_PARAM )
1.1 root 4001: {
1.1.1.8 root 4002: uint64_t av, bv;
1.1.1.7 root 4003: a = float64_squash_input_denormal(a STATUS_VAR);
4004: b = float64_squash_input_denormal(b STATUS_VAR);
1.1 root 4005:
4006: if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
4007: || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
4008: ) {
1.1.1.8 root 4009: float_raise( float_flag_invalid STATUS_VAR);
1.1 root 4010: return 0;
4011: }
1.1.1.3 root 4012: av = float64_val(a);
4013: bv = float64_val(b);
1.1.1.8 root 4014: return ( av == bv ) || ( (uint64_t) ( ( av | bv )<<1 ) == 0 );
1.1 root 4015:
4016: }
4017:
4018: /*----------------------------------------------------------------------------
4019: | Returns 1 if the double-precision floating-point value `a' is less than or
1.1.1.8 root 4020: | equal to the corresponding value `b', and 0 otherwise. The invalid
4021: | exception is raised if either operand is a NaN. The comparison is performed
4022: | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
1.1 root 4023: *----------------------------------------------------------------------------*/
4024:
1.1.1.2 root 4025: int float64_le( float64 a, float64 b STATUS_PARAM )
1.1 root 4026: {
4027: flag aSign, bSign;
1.1.1.8 root 4028: uint64_t av, bv;
1.1.1.7 root 4029: a = float64_squash_input_denormal(a STATUS_VAR);
4030: b = float64_squash_input_denormal(b STATUS_VAR);
1.1 root 4031:
4032: if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
4033: || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
4034: ) {
4035: float_raise( float_flag_invalid STATUS_VAR);
4036: return 0;
4037: }
4038: aSign = extractFloat64Sign( a );
4039: bSign = extractFloat64Sign( b );
1.1.1.3 root 4040: av = float64_val(a);
4041: bv = float64_val(b);
1.1.1.8 root 4042: if ( aSign != bSign ) return aSign || ( (uint64_t) ( ( av | bv )<<1 ) == 0 );
1.1.1.3 root 4043: return ( av == bv ) || ( aSign ^ ( av < bv ) );
1.1 root 4044:
4045: }
4046:
4047: /*----------------------------------------------------------------------------
4048: | Returns 1 if the double-precision floating-point value `a' is less than
1.1.1.8 root 4049: | the corresponding value `b', and 0 otherwise. The invalid exception is
4050: | raised if either operand is a NaN. The comparison is performed according
4051: | to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
1.1 root 4052: *----------------------------------------------------------------------------*/
4053:
1.1.1.2 root 4054: int float64_lt( float64 a, float64 b STATUS_PARAM )
1.1 root 4055: {
4056: flag aSign, bSign;
1.1.1.8 root 4057: uint64_t av, bv;
1.1 root 4058:
1.1.1.7 root 4059: a = float64_squash_input_denormal(a STATUS_VAR);
4060: b = float64_squash_input_denormal(b STATUS_VAR);
1.1 root 4061: if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
4062: || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
4063: ) {
4064: float_raise( float_flag_invalid STATUS_VAR);
4065: return 0;
4066: }
4067: aSign = extractFloat64Sign( a );
4068: bSign = extractFloat64Sign( b );
1.1.1.3 root 4069: av = float64_val(a);
4070: bv = float64_val(b);
1.1.1.8 root 4071: if ( aSign != bSign ) return aSign && ( (uint64_t) ( ( av | bv )<<1 ) != 0 );
1.1.1.3 root 4072: return ( av != bv ) && ( aSign ^ ( av < bv ) );
1.1 root 4073:
4074: }
4075:
4076: /*----------------------------------------------------------------------------
1.1.1.8 root 4077: | Returns 1 if the double-precision floating-point values `a' and `b' cannot
4078: | be compared, and 0 otherwise. The invalid exception is raised if either
4079: | operand is a NaN. The comparison is performed according to the IEC/IEEE
4080: | Standard for Binary Floating-Point Arithmetic.
1.1 root 4081: *----------------------------------------------------------------------------*/
4082:
1.1.1.8 root 4083: int float64_unordered( float64 a, float64 b STATUS_PARAM )
1.1 root 4084: {
1.1.1.7 root 4085: a = float64_squash_input_denormal(a STATUS_VAR);
4086: b = float64_squash_input_denormal(b STATUS_VAR);
1.1 root 4087:
4088: if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
4089: || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
4090: ) {
4091: float_raise( float_flag_invalid STATUS_VAR);
1.1.1.8 root 4092: return 1;
4093: }
4094: return 0;
4095: }
4096:
4097: /*----------------------------------------------------------------------------
4098: | Returns 1 if the double-precision floating-point value `a' is equal to the
4099: | corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an
4100: | exception.The comparison is performed according to the IEC/IEEE Standard
4101: | for Binary Floating-Point Arithmetic.
4102: *----------------------------------------------------------------------------*/
4103:
4104: int float64_eq_quiet( float64 a, float64 b STATUS_PARAM )
4105: {
4106: uint64_t av, bv;
4107: a = float64_squash_input_denormal(a STATUS_VAR);
4108: b = float64_squash_input_denormal(b STATUS_VAR);
4109:
4110: if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
4111: || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
4112: ) {
4113: if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) {
4114: float_raise( float_flag_invalid STATUS_VAR);
4115: }
1.1 root 4116: return 0;
4117: }
1.1.1.3 root 4118: av = float64_val(a);
4119: bv = float64_val(b);
1.1.1.8 root 4120: return ( av == bv ) || ( (uint64_t) ( ( av | bv )<<1 ) == 0 );
1.1 root 4121:
4122: }
4123:
4124: /*----------------------------------------------------------------------------
4125: | Returns 1 if the double-precision floating-point value `a' is less than or
4126: | equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not
4127: | cause an exception. Otherwise, the comparison is performed according to the
4128: | IEC/IEEE Standard for Binary Floating-Point Arithmetic.
4129: *----------------------------------------------------------------------------*/
4130:
1.1.1.2 root 4131: int float64_le_quiet( float64 a, float64 b STATUS_PARAM )
1.1 root 4132: {
4133: flag aSign, bSign;
1.1.1.8 root 4134: uint64_t av, bv;
1.1.1.7 root 4135: a = float64_squash_input_denormal(a STATUS_VAR);
4136: b = float64_squash_input_denormal(b STATUS_VAR);
1.1 root 4137:
4138: if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
4139: || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
4140: ) {
4141: if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) {
4142: float_raise( float_flag_invalid STATUS_VAR);
4143: }
4144: return 0;
4145: }
4146: aSign = extractFloat64Sign( a );
4147: bSign = extractFloat64Sign( b );
1.1.1.3 root 4148: av = float64_val(a);
4149: bv = float64_val(b);
1.1.1.8 root 4150: if ( aSign != bSign ) return aSign || ( (uint64_t) ( ( av | bv )<<1 ) == 0 );
1.1.1.3 root 4151: return ( av == bv ) || ( aSign ^ ( av < bv ) );
1.1 root 4152:
4153: }
4154:
4155: /*----------------------------------------------------------------------------
4156: | Returns 1 if the double-precision floating-point value `a' is less than
4157: | the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an
4158: | exception. Otherwise, the comparison is performed according to the IEC/IEEE
4159: | Standard for Binary Floating-Point Arithmetic.
4160: *----------------------------------------------------------------------------*/
4161:
1.1.1.2 root 4162: int float64_lt_quiet( float64 a, float64 b STATUS_PARAM )
1.1 root 4163: {
4164: flag aSign, bSign;
1.1.1.8 root 4165: uint64_t av, bv;
1.1.1.7 root 4166: a = float64_squash_input_denormal(a STATUS_VAR);
4167: b = float64_squash_input_denormal(b STATUS_VAR);
1.1 root 4168:
4169: if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
4170: || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
4171: ) {
4172: if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) {
4173: float_raise( float_flag_invalid STATUS_VAR);
4174: }
4175: return 0;
4176: }
4177: aSign = extractFloat64Sign( a );
4178: bSign = extractFloat64Sign( b );
1.1.1.3 root 4179: av = float64_val(a);
4180: bv = float64_val(b);
1.1.1.8 root 4181: if ( aSign != bSign ) return aSign && ( (uint64_t) ( ( av | bv )<<1 ) != 0 );
1.1.1.3 root 4182: return ( av != bv ) && ( aSign ^ ( av < bv ) );
1.1 root 4183:
4184: }
4185:
1.1.1.8 root 4186: /*----------------------------------------------------------------------------
4187: | Returns 1 if the double-precision floating-point values `a' and `b' cannot
4188: | be compared, and 0 otherwise. Quiet NaNs do not cause an exception. The
4189: | comparison is performed according to the IEC/IEEE Standard for Binary
4190: | Floating-Point Arithmetic.
4191: *----------------------------------------------------------------------------*/
4192:
4193: int float64_unordered_quiet( float64 a, float64 b STATUS_PARAM )
4194: {
4195: a = float64_squash_input_denormal(a STATUS_VAR);
4196: b = float64_squash_input_denormal(b STATUS_VAR);
4197:
4198: if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
4199: || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
4200: ) {
4201: if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) {
4202: float_raise( float_flag_invalid STATUS_VAR);
4203: }
4204: return 1;
4205: }
4206: return 0;
4207: }
1.1 root 4208:
4209: /*----------------------------------------------------------------------------
4210: | Returns the result of converting the extended double-precision floating-
4211: | point value `a' to the 32-bit two's complement integer format. The
4212: | conversion is performed according to the IEC/IEEE Standard for Binary
4213: | Floating-Point Arithmetic---which means in particular that the conversion
4214: | is rounded according to the current rounding mode. If `a' is a NaN, the
4215: | largest positive integer is returned. Otherwise, if the conversion
4216: | overflows, the largest integer with the same sign as `a' is returned.
4217: *----------------------------------------------------------------------------*/
4218:
4219: int32 floatx80_to_int32( floatx80 a STATUS_PARAM )
4220: {
4221: flag aSign;
4222: int32 aExp, shiftCount;
1.1.1.8 root 4223: uint64_t aSig;
1.1 root 4224:
4225: aSig = extractFloatx80Frac( a );
4226: aExp = extractFloatx80Exp( a );
4227: aSign = extractFloatx80Sign( a );
1.1.1.8 root 4228: if ( ( aExp == 0x7FFF ) && (uint64_t) ( aSig<<1 ) ) aSign = 0;
1.1 root 4229: shiftCount = 0x4037 - aExp;
4230: if ( shiftCount <= 0 ) shiftCount = 1;
4231: shift64RightJamming( aSig, shiftCount, &aSig );
4232: return roundAndPackInt32( aSign, aSig STATUS_VAR );
4233:
4234: }
4235:
4236: /*----------------------------------------------------------------------------
4237: | Returns the result of converting the extended double-precision floating-
4238: | point value `a' to the 32-bit two's complement integer format. The
4239: | conversion is performed according to the IEC/IEEE Standard for Binary
4240: | Floating-Point Arithmetic, except that the conversion is always rounded
4241: | toward zero. If `a' is a NaN, the largest positive integer is returned.
4242: | Otherwise, if the conversion overflows, the largest integer with the same
4243: | sign as `a' is returned.
4244: *----------------------------------------------------------------------------*/
4245:
4246: int32 floatx80_to_int32_round_to_zero( floatx80 a STATUS_PARAM )
4247: {
4248: flag aSign;
4249: int32 aExp, shiftCount;
1.1.1.8 root 4250: uint64_t aSig, savedASig;
1.1.1.10! root 4251: int32_t z;
1.1 root 4252:
4253: aSig = extractFloatx80Frac( a );
4254: aExp = extractFloatx80Exp( a );
4255: aSign = extractFloatx80Sign( a );
4256: if ( 0x401E < aExp ) {
1.1.1.8 root 4257: if ( ( aExp == 0x7FFF ) && (uint64_t) ( aSig<<1 ) ) aSign = 0;
1.1 root 4258: goto invalid;
4259: }
4260: else if ( aExp < 0x3FFF ) {
4261: if ( aExp || aSig ) STATUS(float_exception_flags) |= float_flag_inexact;
4262: return 0;
4263: }
4264: shiftCount = 0x403E - aExp;
4265: savedASig = aSig;
4266: aSig >>= shiftCount;
4267: z = aSig;
4268: if ( aSign ) z = - z;
4269: if ( ( z < 0 ) ^ aSign ) {
4270: invalid:
4271: float_raise( float_flag_invalid STATUS_VAR);
1.1.1.8 root 4272: return aSign ? (int32_t) 0x80000000 : 0x7FFFFFFF;
1.1 root 4273: }
4274: if ( ( aSig<<shiftCount ) != savedASig ) {
4275: STATUS(float_exception_flags) |= float_flag_inexact;
4276: }
4277: return z;
4278:
4279: }
4280:
4281: /*----------------------------------------------------------------------------
4282: | Returns the result of converting the extended double-precision floating-
4283: | point value `a' to the 64-bit two's complement integer format. The
4284: | conversion is performed according to the IEC/IEEE Standard for Binary
4285: | Floating-Point Arithmetic---which means in particular that the conversion
4286: | is rounded according to the current rounding mode. If `a' is a NaN,
4287: | the largest positive integer is returned. Otherwise, if the conversion
4288: | overflows, the largest integer with the same sign as `a' is returned.
4289: *----------------------------------------------------------------------------*/
4290:
4291: int64 floatx80_to_int64( floatx80 a STATUS_PARAM )
4292: {
4293: flag aSign;
4294: int32 aExp, shiftCount;
1.1.1.8 root 4295: uint64_t aSig, aSigExtra;
1.1 root 4296:
4297: aSig = extractFloatx80Frac( a );
4298: aExp = extractFloatx80Exp( a );
4299: aSign = extractFloatx80Sign( a );
4300: shiftCount = 0x403E - aExp;
4301: if ( shiftCount <= 0 ) {
4302: if ( shiftCount ) {
4303: float_raise( float_flag_invalid STATUS_VAR);
4304: if ( ! aSign
4305: || ( ( aExp == 0x7FFF )
4306: && ( aSig != LIT64( 0x8000000000000000 ) ) )
4307: ) {
4308: return LIT64( 0x7FFFFFFFFFFFFFFF );
4309: }
1.1.1.8 root 4310: return (int64_t) LIT64( 0x8000000000000000 );
1.1 root 4311: }
4312: aSigExtra = 0;
4313: }
4314: else {
4315: shift64ExtraRightJamming( aSig, 0, shiftCount, &aSig, &aSigExtra );
4316: }
4317: return roundAndPackInt64( aSign, aSig, aSigExtra STATUS_VAR );
4318:
4319: }
4320:
4321: /*----------------------------------------------------------------------------
4322: | Returns the result of converting the extended double-precision floating-
4323: | point value `a' to the 64-bit two's complement integer format. The
4324: | conversion is performed according to the IEC/IEEE Standard for Binary
4325: | Floating-Point Arithmetic, except that the conversion is always rounded
4326: | toward zero. If `a' is a NaN, the largest positive integer is returned.
4327: | Otherwise, if the conversion overflows, the largest integer with the same
4328: | sign as `a' is returned.
4329: *----------------------------------------------------------------------------*/
4330:
4331: int64 floatx80_to_int64_round_to_zero( floatx80 a STATUS_PARAM )
4332: {
4333: flag aSign;
4334: int32 aExp, shiftCount;
1.1.1.8 root 4335: uint64_t aSig;
1.1 root 4336: int64 z;
4337:
4338: aSig = extractFloatx80Frac( a );
4339: aExp = extractFloatx80Exp( a );
4340: aSign = extractFloatx80Sign( a );
4341: shiftCount = aExp - 0x403E;
4342: if ( 0 <= shiftCount ) {
4343: aSig &= LIT64( 0x7FFFFFFFFFFFFFFF );
4344: if ( ( a.high != 0xC03E ) || aSig ) {
4345: float_raise( float_flag_invalid STATUS_VAR);
4346: if ( ! aSign || ( ( aExp == 0x7FFF ) && aSig ) ) {
4347: return LIT64( 0x7FFFFFFFFFFFFFFF );
4348: }
4349: }
1.1.1.8 root 4350: return (int64_t) LIT64( 0x8000000000000000 );
1.1 root 4351: }
4352: else if ( aExp < 0x3FFF ) {
4353: if ( aExp | aSig ) STATUS(float_exception_flags) |= float_flag_inexact;
4354: return 0;
4355: }
4356: z = aSig>>( - shiftCount );
1.1.1.8 root 4357: if ( (uint64_t) ( aSig<<( shiftCount & 63 ) ) ) {
1.1 root 4358: STATUS(float_exception_flags) |= float_flag_inexact;
4359: }
4360: if ( aSign ) z = - z;
4361: return z;
4362:
4363: }
4364:
4365: /*----------------------------------------------------------------------------
4366: | Returns the result of converting the extended double-precision floating-
4367: | point value `a' to the single-precision floating-point format. The
4368: | conversion is performed according to the IEC/IEEE Standard for Binary
4369: | Floating-Point Arithmetic.
4370: *----------------------------------------------------------------------------*/
4371:
4372: float32 floatx80_to_float32( floatx80 a STATUS_PARAM )
4373: {
4374: flag aSign;
4375: int32 aExp;
1.1.1.8 root 4376: uint64_t aSig;
1.1 root 4377:
4378: aSig = extractFloatx80Frac( a );
4379: aExp = extractFloatx80Exp( a );
4380: aSign = extractFloatx80Sign( a );
4381: if ( aExp == 0x7FFF ) {
1.1.1.8 root 4382: if ( (uint64_t) ( aSig<<1 ) ) {
4383: return commonNaNToFloat32( floatx80ToCommonNaN( a STATUS_VAR ) STATUS_VAR );
1.1 root 4384: }
4385: return packFloat32( aSign, 0xFF, 0 );
4386: }
4387: shift64RightJamming( aSig, 33, &aSig );
4388: if ( aExp || aSig ) aExp -= 0x3F81;
4389: return roundAndPackFloat32( aSign, aExp, aSig STATUS_VAR );
4390:
4391: }
4392:
4393: /*----------------------------------------------------------------------------
4394: | Returns the result of converting the extended double-precision floating-
4395: | point value `a' to the double-precision floating-point format. The
4396: | conversion is performed according to the IEC/IEEE Standard for Binary
4397: | Floating-Point Arithmetic.
4398: *----------------------------------------------------------------------------*/
4399:
4400: float64 floatx80_to_float64( floatx80 a STATUS_PARAM )
4401: {
4402: flag aSign;
4403: int32 aExp;
1.1.1.8 root 4404: uint64_t aSig, zSig;
1.1 root 4405:
4406: aSig = extractFloatx80Frac( a );
4407: aExp = extractFloatx80Exp( a );
4408: aSign = extractFloatx80Sign( a );
4409: if ( aExp == 0x7FFF ) {
1.1.1.8 root 4410: if ( (uint64_t) ( aSig<<1 ) ) {
4411: return commonNaNToFloat64( floatx80ToCommonNaN( a STATUS_VAR ) STATUS_VAR );
1.1 root 4412: }
4413: return packFloat64( aSign, 0x7FF, 0 );
4414: }
4415: shift64RightJamming( aSig, 1, &zSig );
4416: if ( aExp || aSig ) aExp -= 0x3C01;
4417: return roundAndPackFloat64( aSign, aExp, zSig STATUS_VAR );
4418:
4419: }
4420:
4421: /*----------------------------------------------------------------------------
4422: | Returns the result of converting the extended double-precision floating-
4423: | point value `a' to the quadruple-precision floating-point format. The
4424: | conversion is performed according to the IEC/IEEE Standard for Binary
4425: | Floating-Point Arithmetic.
4426: *----------------------------------------------------------------------------*/
4427:
4428: float128 floatx80_to_float128( floatx80 a STATUS_PARAM )
4429: {
4430: flag aSign;
1.1.1.10! root 4431: int_fast16_t aExp;
1.1.1.8 root 4432: uint64_t aSig, zSig0, zSig1;
1.1 root 4433:
4434: aSig = extractFloatx80Frac( a );
4435: aExp = extractFloatx80Exp( a );
4436: aSign = extractFloatx80Sign( a );
1.1.1.8 root 4437: if ( ( aExp == 0x7FFF ) && (uint64_t) ( aSig<<1 ) ) {
4438: return commonNaNToFloat128( floatx80ToCommonNaN( a STATUS_VAR ) STATUS_VAR );
1.1 root 4439: }
4440: shift128Right( aSig<<1, 0, 16, &zSig0, &zSig1 );
4441: return packFloat128( aSign, aExp, zSig0, zSig1 );
4442:
4443: }
4444:
4445: /*----------------------------------------------------------------------------
4446: | Rounds the extended double-precision floating-point value `a' to an integer,
4447: | and returns the result as an extended quadruple-precision floating-point
4448: | value. The operation is performed according to the IEC/IEEE Standard for
4449: | Binary Floating-Point Arithmetic.
4450: *----------------------------------------------------------------------------*/
4451:
4452: floatx80 floatx80_round_to_int( floatx80 a STATUS_PARAM )
4453: {
4454: flag aSign;
4455: int32 aExp;
1.1.1.8 root 4456: uint64_t lastBitMask, roundBitsMask;
1.1 root 4457: int8 roundingMode;
4458: floatx80 z;
4459:
4460: aExp = extractFloatx80Exp( a );
4461: if ( 0x403E <= aExp ) {
1.1.1.8 root 4462: if ( ( aExp == 0x7FFF ) && (uint64_t) ( extractFloatx80Frac( a )<<1 ) ) {
1.1 root 4463: return propagateFloatx80NaN( a, a STATUS_VAR );
4464: }
4465: return a;
4466: }
4467: if ( aExp < 0x3FFF ) {
4468: if ( ( aExp == 0 )
1.1.1.8 root 4469: && ( (uint64_t) ( extractFloatx80Frac( a )<<1 ) == 0 ) ) {
1.1 root 4470: return a;
4471: }
4472: STATUS(float_exception_flags) |= float_flag_inexact;
4473: aSign = extractFloatx80Sign( a );
4474: switch ( STATUS(float_rounding_mode) ) {
4475: case float_round_nearest_even:
1.1.1.8 root 4476: if ( ( aExp == 0x3FFE ) && (uint64_t) ( extractFloatx80Frac( a )<<1 )
1.1 root 4477: ) {
4478: return
4479: packFloatx80( aSign, 0x3FFF, LIT64( 0x8000000000000000 ) );
4480: }
4481: break;
4482: case float_round_down:
4483: return
4484: aSign ?
4485: packFloatx80( 1, 0x3FFF, LIT64( 0x8000000000000000 ) )
4486: : packFloatx80( 0, 0, 0 );
4487: case float_round_up:
4488: return
4489: aSign ? packFloatx80( 1, 0, 0 )
4490: : packFloatx80( 0, 0x3FFF, LIT64( 0x8000000000000000 ) );
4491: }
4492: return packFloatx80( aSign, 0, 0 );
4493: }
4494: lastBitMask = 1;
4495: lastBitMask <<= 0x403E - aExp;
4496: roundBitsMask = lastBitMask - 1;
4497: z = a;
4498: roundingMode = STATUS(float_rounding_mode);
4499: if ( roundingMode == float_round_nearest_even ) {
4500: z.low += lastBitMask>>1;
4501: if ( ( z.low & roundBitsMask ) == 0 ) z.low &= ~ lastBitMask;
4502: }
4503: else if ( roundingMode != float_round_to_zero ) {
4504: if ( extractFloatx80Sign( z ) ^ ( roundingMode == float_round_up ) ) {
4505: z.low += roundBitsMask;
4506: }
4507: }
4508: z.low &= ~ roundBitsMask;
4509: if ( z.low == 0 ) {
4510: ++z.high;
4511: z.low = LIT64( 0x8000000000000000 );
4512: }
4513: if ( z.low != a.low ) STATUS(float_exception_flags) |= float_flag_inexact;
4514: return z;
4515:
4516: }
4517:
4518: /*----------------------------------------------------------------------------
4519: | Returns the result of adding the absolute values of the extended double-
4520: | precision floating-point values `a' and `b'. If `zSign' is 1, the sum is
4521: | negated before being returned. `zSign' is ignored if the result is a NaN.
4522: | The addition is performed according to the IEC/IEEE Standard for Binary
4523: | Floating-Point Arithmetic.
4524: *----------------------------------------------------------------------------*/
4525:
4526: static floatx80 addFloatx80Sigs( floatx80 a, floatx80 b, flag zSign STATUS_PARAM)
4527: {
4528: int32 aExp, bExp, zExp;
1.1.1.8 root 4529: uint64_t aSig, bSig, zSig0, zSig1;
1.1 root 4530: int32 expDiff;
4531:
4532: aSig = extractFloatx80Frac( a );
4533: aExp = extractFloatx80Exp( a );
4534: bSig = extractFloatx80Frac( b );
4535: bExp = extractFloatx80Exp( b );
4536: expDiff = aExp - bExp;
4537: if ( 0 < expDiff ) {
4538: if ( aExp == 0x7FFF ) {
1.1.1.8 root 4539: if ( (uint64_t) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b STATUS_VAR );
1.1 root 4540: return a;
4541: }
4542: if ( bExp == 0 ) --expDiff;
4543: shift64ExtraRightJamming( bSig, 0, expDiff, &bSig, &zSig1 );
4544: zExp = aExp;
4545: }
4546: else if ( expDiff < 0 ) {
4547: if ( bExp == 0x7FFF ) {
1.1.1.8 root 4548: if ( (uint64_t) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b STATUS_VAR );
1.1 root 4549: return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
4550: }
4551: if ( aExp == 0 ) ++expDiff;
4552: shift64ExtraRightJamming( aSig, 0, - expDiff, &aSig, &zSig1 );
4553: zExp = bExp;
4554: }
4555: else {
4556: if ( aExp == 0x7FFF ) {
1.1.1.8 root 4557: if ( (uint64_t) ( ( aSig | bSig )<<1 ) ) {
1.1 root 4558: return propagateFloatx80NaN( a, b STATUS_VAR );
4559: }
4560: return a;
4561: }
4562: zSig1 = 0;
4563: zSig0 = aSig + bSig;
4564: if ( aExp == 0 ) {
4565: normalizeFloatx80Subnormal( zSig0, &zExp, &zSig0 );
4566: goto roundAndPack;
4567: }
4568: zExp = aExp;
4569: goto shiftRight1;
4570: }
4571: zSig0 = aSig + bSig;
1.1.1.8 root 4572: if ( (int64_t) zSig0 < 0 ) goto roundAndPack;
1.1 root 4573: shiftRight1:
4574: shift64ExtraRightJamming( zSig0, zSig1, 1, &zSig0, &zSig1 );
4575: zSig0 |= LIT64( 0x8000000000000000 );
4576: ++zExp;
4577: roundAndPack:
4578: return
4579: roundAndPackFloatx80(
4580: STATUS(floatx80_rounding_precision), zSign, zExp, zSig0, zSig1 STATUS_VAR );
4581:
4582: }
4583:
4584: /*----------------------------------------------------------------------------
4585: | Returns the result of subtracting the absolute values of the extended
4586: | double-precision floating-point values `a' and `b'. If `zSign' is 1, the
4587: | difference is negated before being returned. `zSign' is ignored if the
4588: | result is a NaN. The subtraction is performed according to the IEC/IEEE
4589: | Standard for Binary Floating-Point Arithmetic.
4590: *----------------------------------------------------------------------------*/
4591:
4592: static floatx80 subFloatx80Sigs( floatx80 a, floatx80 b, flag zSign STATUS_PARAM )
4593: {
4594: int32 aExp, bExp, zExp;
1.1.1.8 root 4595: uint64_t aSig, bSig, zSig0, zSig1;
1.1 root 4596: int32 expDiff;
4597: floatx80 z;
4598:
4599: aSig = extractFloatx80Frac( a );
4600: aExp = extractFloatx80Exp( a );
4601: bSig = extractFloatx80Frac( b );
4602: bExp = extractFloatx80Exp( b );
4603: expDiff = aExp - bExp;
4604: if ( 0 < expDiff ) goto aExpBigger;
4605: if ( expDiff < 0 ) goto bExpBigger;
4606: if ( aExp == 0x7FFF ) {
1.1.1.8 root 4607: if ( (uint64_t) ( ( aSig | bSig )<<1 ) ) {
1.1 root 4608: return propagateFloatx80NaN( a, b STATUS_VAR );
4609: }
4610: float_raise( float_flag_invalid STATUS_VAR);
4611: z.low = floatx80_default_nan_low;
4612: z.high = floatx80_default_nan_high;
4613: return z;
4614: }
4615: if ( aExp == 0 ) {
4616: aExp = 1;
4617: bExp = 1;
4618: }
4619: zSig1 = 0;
4620: if ( bSig < aSig ) goto aBigger;
4621: if ( aSig < bSig ) goto bBigger;
4622: return packFloatx80( STATUS(float_rounding_mode) == float_round_down, 0, 0 );
4623: bExpBigger:
4624: if ( bExp == 0x7FFF ) {
1.1.1.8 root 4625: if ( (uint64_t) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b STATUS_VAR );
1.1 root 4626: return packFloatx80( zSign ^ 1, 0x7FFF, LIT64( 0x8000000000000000 ) );
4627: }
4628: if ( aExp == 0 ) ++expDiff;
4629: shift128RightJamming( aSig, 0, - expDiff, &aSig, &zSig1 );
4630: bBigger:
4631: sub128( bSig, 0, aSig, zSig1, &zSig0, &zSig1 );
4632: zExp = bExp;
4633: zSign ^= 1;
4634: goto normalizeRoundAndPack;
4635: aExpBigger:
4636: if ( aExp == 0x7FFF ) {
1.1.1.8 root 4637: if ( (uint64_t) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b STATUS_VAR );
1.1 root 4638: return a;
4639: }
4640: if ( bExp == 0 ) --expDiff;
4641: shift128RightJamming( bSig, 0, expDiff, &bSig, &zSig1 );
4642: aBigger:
4643: sub128( aSig, 0, bSig, zSig1, &zSig0, &zSig1 );
4644: zExp = aExp;
4645: normalizeRoundAndPack:
4646: return
4647: normalizeRoundAndPackFloatx80(
4648: STATUS(floatx80_rounding_precision), zSign, zExp, zSig0, zSig1 STATUS_VAR );
4649:
4650: }
4651:
4652: /*----------------------------------------------------------------------------
4653: | Returns the result of adding the extended double-precision floating-point
4654: | values `a' and `b'. The operation is performed according to the IEC/IEEE
4655: | Standard for Binary Floating-Point Arithmetic.
4656: *----------------------------------------------------------------------------*/
4657:
4658: floatx80 floatx80_add( floatx80 a, floatx80 b STATUS_PARAM )
4659: {
4660: flag aSign, bSign;
4661:
4662: aSign = extractFloatx80Sign( a );
4663: bSign = extractFloatx80Sign( b );
4664: if ( aSign == bSign ) {
4665: return addFloatx80Sigs( a, b, aSign STATUS_VAR );
4666: }
4667: else {
4668: return subFloatx80Sigs( a, b, aSign STATUS_VAR );
4669: }
4670:
4671: }
4672:
4673: /*----------------------------------------------------------------------------
4674: | Returns the result of subtracting the extended double-precision floating-
4675: | point values `a' and `b'. The operation is performed according to the
4676: | IEC/IEEE Standard for Binary Floating-Point Arithmetic.
4677: *----------------------------------------------------------------------------*/
4678:
4679: floatx80 floatx80_sub( floatx80 a, floatx80 b STATUS_PARAM )
4680: {
4681: flag aSign, bSign;
4682:
4683: aSign = extractFloatx80Sign( a );
4684: bSign = extractFloatx80Sign( b );
4685: if ( aSign == bSign ) {
4686: return subFloatx80Sigs( a, b, aSign STATUS_VAR );
4687: }
4688: else {
4689: return addFloatx80Sigs( a, b, aSign STATUS_VAR );
4690: }
4691:
4692: }
4693:
4694: /*----------------------------------------------------------------------------
4695: | Returns the result of multiplying the extended double-precision floating-
4696: | point values `a' and `b'. The operation is performed according to the
4697: | IEC/IEEE Standard for Binary Floating-Point Arithmetic.
4698: *----------------------------------------------------------------------------*/
4699:
4700: floatx80 floatx80_mul( floatx80 a, floatx80 b STATUS_PARAM )
4701: {
4702: flag aSign, bSign, zSign;
4703: int32 aExp, bExp, zExp;
1.1.1.8 root 4704: uint64_t aSig, bSig, zSig0, zSig1;
1.1 root 4705: floatx80 z;
4706:
4707: aSig = extractFloatx80Frac( a );
4708: aExp = extractFloatx80Exp( a );
4709: aSign = extractFloatx80Sign( a );
4710: bSig = extractFloatx80Frac( b );
4711: bExp = extractFloatx80Exp( b );
4712: bSign = extractFloatx80Sign( b );
4713: zSign = aSign ^ bSign;
4714: if ( aExp == 0x7FFF ) {
1.1.1.8 root 4715: if ( (uint64_t) ( aSig<<1 )
4716: || ( ( bExp == 0x7FFF ) && (uint64_t) ( bSig<<1 ) ) ) {
1.1 root 4717: return propagateFloatx80NaN( a, b STATUS_VAR );
4718: }
4719: if ( ( bExp | bSig ) == 0 ) goto invalid;
4720: return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
4721: }
4722: if ( bExp == 0x7FFF ) {
1.1.1.8 root 4723: if ( (uint64_t) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b STATUS_VAR );
1.1 root 4724: if ( ( aExp | aSig ) == 0 ) {
4725: invalid:
4726: float_raise( float_flag_invalid STATUS_VAR);
4727: z.low = floatx80_default_nan_low;
4728: z.high = floatx80_default_nan_high;
4729: return z;
4730: }
4731: return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
4732: }
4733: if ( aExp == 0 ) {
4734: if ( aSig == 0 ) return packFloatx80( zSign, 0, 0 );
4735: normalizeFloatx80Subnormal( aSig, &aExp, &aSig );
4736: }
4737: if ( bExp == 0 ) {
4738: if ( bSig == 0 ) return packFloatx80( zSign, 0, 0 );
4739: normalizeFloatx80Subnormal( bSig, &bExp, &bSig );
4740: }
4741: zExp = aExp + bExp - 0x3FFE;
4742: mul64To128( aSig, bSig, &zSig0, &zSig1 );
1.1.1.8 root 4743: if ( 0 < (int64_t) zSig0 ) {
1.1 root 4744: shortShift128Left( zSig0, zSig1, 1, &zSig0, &zSig1 );
4745: --zExp;
4746: }
4747: return
4748: roundAndPackFloatx80(
4749: STATUS(floatx80_rounding_precision), zSign, zExp, zSig0, zSig1 STATUS_VAR );
4750:
4751: }
4752:
4753: /*----------------------------------------------------------------------------
4754: | Returns the result of dividing the extended double-precision floating-point
4755: | value `a' by the corresponding value `b'. The operation is performed
4756: | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
4757: *----------------------------------------------------------------------------*/
4758:
4759: floatx80 floatx80_div( floatx80 a, floatx80 b STATUS_PARAM )
4760: {
4761: flag aSign, bSign, zSign;
4762: int32 aExp, bExp, zExp;
1.1.1.8 root 4763: uint64_t aSig, bSig, zSig0, zSig1;
4764: uint64_t rem0, rem1, rem2, term0, term1, term2;
1.1 root 4765: floatx80 z;
4766:
4767: aSig = extractFloatx80Frac( a );
4768: aExp = extractFloatx80Exp( a );
4769: aSign = extractFloatx80Sign( a );
4770: bSig = extractFloatx80Frac( b );
4771: bExp = extractFloatx80Exp( b );
4772: bSign = extractFloatx80Sign( b );
4773: zSign = aSign ^ bSign;
4774: if ( aExp == 0x7FFF ) {
1.1.1.8 root 4775: if ( (uint64_t) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b STATUS_VAR );
1.1 root 4776: if ( bExp == 0x7FFF ) {
1.1.1.8 root 4777: if ( (uint64_t) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b STATUS_VAR );
1.1 root 4778: goto invalid;
4779: }
4780: return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
4781: }
4782: if ( bExp == 0x7FFF ) {
1.1.1.8 root 4783: if ( (uint64_t) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b STATUS_VAR );
1.1 root 4784: return packFloatx80( zSign, 0, 0 );
4785: }
4786: if ( bExp == 0 ) {
4787: if ( bSig == 0 ) {
4788: if ( ( aExp | aSig ) == 0 ) {
4789: invalid:
4790: float_raise( float_flag_invalid STATUS_VAR);
4791: z.low = floatx80_default_nan_low;
4792: z.high = floatx80_default_nan_high;
4793: return z;
4794: }
4795: float_raise( float_flag_divbyzero STATUS_VAR);
4796: return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
4797: }
4798: normalizeFloatx80Subnormal( bSig, &bExp, &bSig );
4799: }
4800: if ( aExp == 0 ) {
4801: if ( aSig == 0 ) return packFloatx80( zSign, 0, 0 );
4802: normalizeFloatx80Subnormal( aSig, &aExp, &aSig );
4803: }
4804: zExp = aExp - bExp + 0x3FFE;
4805: rem1 = 0;
4806: if ( bSig <= aSig ) {
4807: shift128Right( aSig, 0, 1, &aSig, &rem1 );
4808: ++zExp;
4809: }
4810: zSig0 = estimateDiv128To64( aSig, rem1, bSig );
4811: mul64To128( bSig, zSig0, &term0, &term1 );
4812: sub128( aSig, rem1, term0, term1, &rem0, &rem1 );
1.1.1.8 root 4813: while ( (int64_t) rem0 < 0 ) {
1.1 root 4814: --zSig0;
4815: add128( rem0, rem1, 0, bSig, &rem0, &rem1 );
4816: }
4817: zSig1 = estimateDiv128To64( rem1, 0, bSig );
1.1.1.8 root 4818: if ( (uint64_t) ( zSig1<<1 ) <= 8 ) {
1.1 root 4819: mul64To128( bSig, zSig1, &term1, &term2 );
4820: sub128( rem1, 0, term1, term2, &rem1, &rem2 );
1.1.1.8 root 4821: while ( (int64_t) rem1 < 0 ) {
1.1 root 4822: --zSig1;
4823: add128( rem1, rem2, 0, bSig, &rem1, &rem2 );
4824: }
4825: zSig1 |= ( ( rem1 | rem2 ) != 0 );
4826: }
4827: return
4828: roundAndPackFloatx80(
4829: STATUS(floatx80_rounding_precision), zSign, zExp, zSig0, zSig1 STATUS_VAR );
4830:
4831: }
4832:
4833: /*----------------------------------------------------------------------------
4834: | Returns the remainder of the extended double-precision floating-point value
4835: | `a' with respect to the corresponding value `b'. The operation is performed
4836: | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
4837: *----------------------------------------------------------------------------*/
4838:
4839: floatx80 floatx80_rem( floatx80 a, floatx80 b STATUS_PARAM )
4840: {
1.1.1.6 root 4841: flag aSign, zSign;
1.1 root 4842: int32 aExp, bExp, expDiff;
1.1.1.8 root 4843: uint64_t aSig0, aSig1, bSig;
4844: uint64_t q, term0, term1, alternateASig0, alternateASig1;
1.1 root 4845: floatx80 z;
4846:
4847: aSig0 = extractFloatx80Frac( a );
4848: aExp = extractFloatx80Exp( a );
4849: aSign = extractFloatx80Sign( a );
4850: bSig = extractFloatx80Frac( b );
4851: bExp = extractFloatx80Exp( b );
4852: if ( aExp == 0x7FFF ) {
1.1.1.8 root 4853: if ( (uint64_t) ( aSig0<<1 )
4854: || ( ( bExp == 0x7FFF ) && (uint64_t) ( bSig<<1 ) ) ) {
1.1 root 4855: return propagateFloatx80NaN( a, b STATUS_VAR );
4856: }
4857: goto invalid;
4858: }
4859: if ( bExp == 0x7FFF ) {
1.1.1.8 root 4860: if ( (uint64_t) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b STATUS_VAR );
1.1 root 4861: return a;
4862: }
4863: if ( bExp == 0 ) {
4864: if ( bSig == 0 ) {
4865: invalid:
4866: float_raise( float_flag_invalid STATUS_VAR);
4867: z.low = floatx80_default_nan_low;
4868: z.high = floatx80_default_nan_high;
4869: return z;
4870: }
4871: normalizeFloatx80Subnormal( bSig, &bExp, &bSig );
4872: }
4873: if ( aExp == 0 ) {
1.1.1.8 root 4874: if ( (uint64_t) ( aSig0<<1 ) == 0 ) return a;
1.1 root 4875: normalizeFloatx80Subnormal( aSig0, &aExp, &aSig0 );
4876: }
4877: bSig |= LIT64( 0x8000000000000000 );
4878: zSign = aSign;
4879: expDiff = aExp - bExp;
4880: aSig1 = 0;
4881: if ( expDiff < 0 ) {
4882: if ( expDiff < -1 ) return a;
4883: shift128Right( aSig0, 0, 1, &aSig0, &aSig1 );
4884: expDiff = 0;
4885: }
4886: q = ( bSig <= aSig0 );
4887: if ( q ) aSig0 -= bSig;
4888: expDiff -= 64;
4889: while ( 0 < expDiff ) {
4890: q = estimateDiv128To64( aSig0, aSig1, bSig );
4891: q = ( 2 < q ) ? q - 2 : 0;
4892: mul64To128( bSig, q, &term0, &term1 );
4893: sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 );
4894: shortShift128Left( aSig0, aSig1, 62, &aSig0, &aSig1 );
4895: expDiff -= 62;
4896: }
4897: expDiff += 64;
4898: if ( 0 < expDiff ) {
4899: q = estimateDiv128To64( aSig0, aSig1, bSig );
4900: q = ( 2 < q ) ? q - 2 : 0;
4901: q >>= 64 - expDiff;
4902: mul64To128( bSig, q<<( 64 - expDiff ), &term0, &term1 );
4903: sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 );
4904: shortShift128Left( 0, bSig, 64 - expDiff, &term0, &term1 );
4905: while ( le128( term0, term1, aSig0, aSig1 ) ) {
4906: ++q;
4907: sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 );
4908: }
4909: }
4910: else {
4911: term1 = 0;
4912: term0 = bSig;
4913: }
4914: sub128( term0, term1, aSig0, aSig1, &alternateASig0, &alternateASig1 );
4915: if ( lt128( alternateASig0, alternateASig1, aSig0, aSig1 )
4916: || ( eq128( alternateASig0, alternateASig1, aSig0, aSig1 )
4917: && ( q & 1 ) )
4918: ) {
4919: aSig0 = alternateASig0;
4920: aSig1 = alternateASig1;
4921: zSign = ! zSign;
4922: }
4923: return
4924: normalizeRoundAndPackFloatx80(
4925: 80, zSign, bExp + expDiff, aSig0, aSig1 STATUS_VAR );
4926:
4927: }
4928:
4929: /*----------------------------------------------------------------------------
4930: | Returns the square root of the extended double-precision floating-point
4931: | value `a'. The operation is performed according to the IEC/IEEE Standard
4932: | for Binary Floating-Point Arithmetic.
4933: *----------------------------------------------------------------------------*/
4934:
4935: floatx80 floatx80_sqrt( floatx80 a STATUS_PARAM )
4936: {
4937: flag aSign;
4938: int32 aExp, zExp;
1.1.1.8 root 4939: uint64_t aSig0, aSig1, zSig0, zSig1, doubleZSig0;
4940: uint64_t rem0, rem1, rem2, rem3, term0, term1, term2, term3;
1.1 root 4941: floatx80 z;
4942:
4943: aSig0 = extractFloatx80Frac( a );
4944: aExp = extractFloatx80Exp( a );
4945: aSign = extractFloatx80Sign( a );
4946: if ( aExp == 0x7FFF ) {
1.1.1.8 root 4947: if ( (uint64_t) ( aSig0<<1 ) ) return propagateFloatx80NaN( a, a STATUS_VAR );
1.1 root 4948: if ( ! aSign ) return a;
4949: goto invalid;
4950: }
4951: if ( aSign ) {
4952: if ( ( aExp | aSig0 ) == 0 ) return a;
4953: invalid:
4954: float_raise( float_flag_invalid STATUS_VAR);
4955: z.low = floatx80_default_nan_low;
4956: z.high = floatx80_default_nan_high;
4957: return z;
4958: }
4959: if ( aExp == 0 ) {
4960: if ( aSig0 == 0 ) return packFloatx80( 0, 0, 0 );
4961: normalizeFloatx80Subnormal( aSig0, &aExp, &aSig0 );
4962: }
4963: zExp = ( ( aExp - 0x3FFF )>>1 ) + 0x3FFF;
4964: zSig0 = estimateSqrt32( aExp, aSig0>>32 );
4965: shift128Right( aSig0, 0, 2 + ( aExp & 1 ), &aSig0, &aSig1 );
4966: zSig0 = estimateDiv128To64( aSig0, aSig1, zSig0<<32 ) + ( zSig0<<30 );
4967: doubleZSig0 = zSig0<<1;
4968: mul64To128( zSig0, zSig0, &term0, &term1 );
4969: sub128( aSig0, aSig1, term0, term1, &rem0, &rem1 );
1.1.1.8 root 4970: while ( (int64_t) rem0 < 0 ) {
1.1 root 4971: --zSig0;
4972: doubleZSig0 -= 2;
4973: add128( rem0, rem1, zSig0>>63, doubleZSig0 | 1, &rem0, &rem1 );
4974: }
4975: zSig1 = estimateDiv128To64( rem1, 0, doubleZSig0 );
4976: if ( ( zSig1 & LIT64( 0x3FFFFFFFFFFFFFFF ) ) <= 5 ) {
4977: if ( zSig1 == 0 ) zSig1 = 1;
4978: mul64To128( doubleZSig0, zSig1, &term1, &term2 );
4979: sub128( rem1, 0, term1, term2, &rem1, &rem2 );
4980: mul64To128( zSig1, zSig1, &term2, &term3 );
4981: sub192( rem1, rem2, 0, 0, term2, term3, &rem1, &rem2, &rem3 );
1.1.1.8 root 4982: while ( (int64_t) rem1 < 0 ) {
1.1 root 4983: --zSig1;
4984: shortShift128Left( 0, zSig1, 1, &term2, &term3 );
4985: term3 |= 1;
4986: term2 |= doubleZSig0;
4987: add192( rem1, rem2, rem3, 0, term2, term3, &rem1, &rem2, &rem3 );
4988: }
4989: zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 );
4990: }
4991: shortShift128Left( 0, zSig1, 1, &zSig0, &zSig1 );
4992: zSig0 |= doubleZSig0;
4993: return
4994: roundAndPackFloatx80(
4995: STATUS(floatx80_rounding_precision), 0, zExp, zSig0, zSig1 STATUS_VAR );
4996:
4997: }
4998:
4999: /*----------------------------------------------------------------------------
1.1.1.8 root 5000: | Returns 1 if the extended double-precision floating-point value `a' is equal
5001: | to the corresponding value `b', and 0 otherwise. The invalid exception is
5002: | raised if either operand is a NaN. Otherwise, the comparison is performed
5003: | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
1.1 root 5004: *----------------------------------------------------------------------------*/
5005:
1.1.1.2 root 5006: int floatx80_eq( floatx80 a, floatx80 b STATUS_PARAM )
1.1 root 5007: {
5008:
5009: if ( ( ( extractFloatx80Exp( a ) == 0x7FFF )
1.1.1.8 root 5010: && (uint64_t) ( extractFloatx80Frac( a )<<1 ) )
1.1 root 5011: || ( ( extractFloatx80Exp( b ) == 0x7FFF )
1.1.1.8 root 5012: && (uint64_t) ( extractFloatx80Frac( b )<<1 ) )
1.1 root 5013: ) {
1.1.1.8 root 5014: float_raise( float_flag_invalid STATUS_VAR);
1.1 root 5015: return 0;
5016: }
5017: return
5018: ( a.low == b.low )
5019: && ( ( a.high == b.high )
5020: || ( ( a.low == 0 )
1.1.1.8 root 5021: && ( (uint16_t) ( ( a.high | b.high )<<1 ) == 0 ) )
1.1 root 5022: );
5023:
5024: }
5025:
5026: /*----------------------------------------------------------------------------
5027: | Returns 1 if the extended double-precision floating-point value `a' is
5028: | less than or equal to the corresponding value `b', and 0 otherwise. The
1.1.1.8 root 5029: | invalid exception is raised if either operand is a NaN. The comparison is
5030: | performed according to the IEC/IEEE Standard for Binary Floating-Point
5031: | Arithmetic.
1.1 root 5032: *----------------------------------------------------------------------------*/
5033:
1.1.1.2 root 5034: int floatx80_le( floatx80 a, floatx80 b STATUS_PARAM )
1.1 root 5035: {
5036: flag aSign, bSign;
5037:
5038: if ( ( ( extractFloatx80Exp( a ) == 0x7FFF )
1.1.1.8 root 5039: && (uint64_t) ( extractFloatx80Frac( a )<<1 ) )
1.1 root 5040: || ( ( extractFloatx80Exp( b ) == 0x7FFF )
1.1.1.8 root 5041: && (uint64_t) ( extractFloatx80Frac( b )<<1 ) )
1.1 root 5042: ) {
5043: float_raise( float_flag_invalid STATUS_VAR);
5044: return 0;
5045: }
5046: aSign = extractFloatx80Sign( a );
5047: bSign = extractFloatx80Sign( b );
5048: if ( aSign != bSign ) {
5049: return
5050: aSign
1.1.1.8 root 5051: || ( ( ( (uint16_t) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
1.1 root 5052: == 0 );
5053: }
5054: return
5055: aSign ? le128( b.high, b.low, a.high, a.low )
5056: : le128( a.high, a.low, b.high, b.low );
5057:
5058: }
5059:
5060: /*----------------------------------------------------------------------------
5061: | Returns 1 if the extended double-precision floating-point value `a' is
1.1.1.8 root 5062: | less than the corresponding value `b', and 0 otherwise. The invalid
5063: | exception is raised if either operand is a NaN. The comparison is performed
5064: | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
1.1 root 5065: *----------------------------------------------------------------------------*/
5066:
1.1.1.2 root 5067: int floatx80_lt( floatx80 a, floatx80 b STATUS_PARAM )
1.1 root 5068: {
5069: flag aSign, bSign;
5070:
5071: if ( ( ( extractFloatx80Exp( a ) == 0x7FFF )
1.1.1.8 root 5072: && (uint64_t) ( extractFloatx80Frac( a )<<1 ) )
1.1 root 5073: || ( ( extractFloatx80Exp( b ) == 0x7FFF )
1.1.1.8 root 5074: && (uint64_t) ( extractFloatx80Frac( b )<<1 ) )
1.1 root 5075: ) {
5076: float_raise( float_flag_invalid STATUS_VAR);
5077: return 0;
5078: }
5079: aSign = extractFloatx80Sign( a );
5080: bSign = extractFloatx80Sign( b );
5081: if ( aSign != bSign ) {
5082: return
5083: aSign
1.1.1.8 root 5084: && ( ( ( (uint16_t) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
1.1 root 5085: != 0 );
5086: }
5087: return
5088: aSign ? lt128( b.high, b.low, a.high, a.low )
5089: : lt128( a.high, a.low, b.high, b.low );
5090:
5091: }
5092:
5093: /*----------------------------------------------------------------------------
1.1.1.8 root 5094: | Returns 1 if the extended double-precision floating-point values `a' and `b'
5095: | cannot be compared, and 0 otherwise. The invalid exception is raised if
5096: | either operand is a NaN. The comparison is performed according to the
5097: | IEC/IEEE Standard for Binary Floating-Point Arithmetic.
5098: *----------------------------------------------------------------------------*/
5099: int floatx80_unordered( floatx80 a, floatx80 b STATUS_PARAM )
5100: {
5101: if ( ( ( extractFloatx80Exp( a ) == 0x7FFF )
5102: && (uint64_t) ( extractFloatx80Frac( a )<<1 ) )
5103: || ( ( extractFloatx80Exp( b ) == 0x7FFF )
5104: && (uint64_t) ( extractFloatx80Frac( b )<<1 ) )
5105: ) {
5106: float_raise( float_flag_invalid STATUS_VAR);
5107: return 1;
5108: }
5109: return 0;
5110: }
5111:
5112: /*----------------------------------------------------------------------------
5113: | Returns 1 if the extended double-precision floating-point value `a' is
5114: | equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not
5115: | cause an exception. The comparison is performed according to the IEC/IEEE
5116: | Standard for Binary Floating-Point Arithmetic.
1.1 root 5117: *----------------------------------------------------------------------------*/
5118:
1.1.1.8 root 5119: int floatx80_eq_quiet( floatx80 a, floatx80 b STATUS_PARAM )
1.1 root 5120: {
5121:
5122: if ( ( ( extractFloatx80Exp( a ) == 0x7FFF )
1.1.1.8 root 5123: && (uint64_t) ( extractFloatx80Frac( a )<<1 ) )
1.1 root 5124: || ( ( extractFloatx80Exp( b ) == 0x7FFF )
1.1.1.8 root 5125: && (uint64_t) ( extractFloatx80Frac( b )<<1 ) )
1.1 root 5126: ) {
1.1.1.8 root 5127: if ( floatx80_is_signaling_nan( a )
5128: || floatx80_is_signaling_nan( b ) ) {
5129: float_raise( float_flag_invalid STATUS_VAR);
5130: }
1.1 root 5131: return 0;
5132: }
5133: return
5134: ( a.low == b.low )
5135: && ( ( a.high == b.high )
5136: || ( ( a.low == 0 )
1.1.1.8 root 5137: && ( (uint16_t) ( ( a.high | b.high )<<1 ) == 0 ) )
1.1 root 5138: );
5139:
5140: }
5141:
5142: /*----------------------------------------------------------------------------
5143: | Returns 1 if the extended double-precision floating-point value `a' is less
5144: | than or equal to the corresponding value `b', and 0 otherwise. Quiet NaNs
5145: | do not cause an exception. Otherwise, the comparison is performed according
5146: | to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
5147: *----------------------------------------------------------------------------*/
5148:
1.1.1.2 root 5149: int floatx80_le_quiet( floatx80 a, floatx80 b STATUS_PARAM )
1.1 root 5150: {
5151: flag aSign, bSign;
5152:
5153: if ( ( ( extractFloatx80Exp( a ) == 0x7FFF )
1.1.1.8 root 5154: && (uint64_t) ( extractFloatx80Frac( a )<<1 ) )
1.1 root 5155: || ( ( extractFloatx80Exp( b ) == 0x7FFF )
1.1.1.8 root 5156: && (uint64_t) ( extractFloatx80Frac( b )<<1 ) )
1.1 root 5157: ) {
5158: if ( floatx80_is_signaling_nan( a )
5159: || floatx80_is_signaling_nan( b ) ) {
5160: float_raise( float_flag_invalid STATUS_VAR);
5161: }
5162: return 0;
5163: }
5164: aSign = extractFloatx80Sign( a );
5165: bSign = extractFloatx80Sign( b );
5166: if ( aSign != bSign ) {
5167: return
5168: aSign
1.1.1.8 root 5169: || ( ( ( (uint16_t) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
1.1 root 5170: == 0 );
5171: }
5172: return
5173: aSign ? le128( b.high, b.low, a.high, a.low )
5174: : le128( a.high, a.low, b.high, b.low );
5175:
5176: }
5177:
5178: /*----------------------------------------------------------------------------
5179: | Returns 1 if the extended double-precision floating-point value `a' is less
5180: | than the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause
5181: | an exception. Otherwise, the comparison is performed according to the
5182: | IEC/IEEE Standard for Binary Floating-Point Arithmetic.
5183: *----------------------------------------------------------------------------*/
5184:
1.1.1.2 root 5185: int floatx80_lt_quiet( floatx80 a, floatx80 b STATUS_PARAM )
1.1 root 5186: {
5187: flag aSign, bSign;
5188:
5189: if ( ( ( extractFloatx80Exp( a ) == 0x7FFF )
1.1.1.8 root 5190: && (uint64_t) ( extractFloatx80Frac( a )<<1 ) )
1.1 root 5191: || ( ( extractFloatx80Exp( b ) == 0x7FFF )
1.1.1.8 root 5192: && (uint64_t) ( extractFloatx80Frac( b )<<1 ) )
1.1 root 5193: ) {
5194: if ( floatx80_is_signaling_nan( a )
5195: || floatx80_is_signaling_nan( b ) ) {
5196: float_raise( float_flag_invalid STATUS_VAR);
5197: }
5198: return 0;
5199: }
5200: aSign = extractFloatx80Sign( a );
5201: bSign = extractFloatx80Sign( b );
5202: if ( aSign != bSign ) {
5203: return
5204: aSign
1.1.1.8 root 5205: && ( ( ( (uint16_t) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
1.1 root 5206: != 0 );
5207: }
5208: return
5209: aSign ? lt128( b.high, b.low, a.high, a.low )
5210: : lt128( a.high, a.low, b.high, b.low );
5211:
5212: }
5213:
1.1.1.8 root 5214: /*----------------------------------------------------------------------------
5215: | Returns 1 if the extended double-precision floating-point values `a' and `b'
5216: | cannot be compared, and 0 otherwise. Quiet NaNs do not cause an exception.
5217: | The comparison is performed according to the IEC/IEEE Standard for Binary
5218: | Floating-Point Arithmetic.
5219: *----------------------------------------------------------------------------*/
5220: int floatx80_unordered_quiet( floatx80 a, floatx80 b STATUS_PARAM )
5221: {
5222: if ( ( ( extractFloatx80Exp( a ) == 0x7FFF )
5223: && (uint64_t) ( extractFloatx80Frac( a )<<1 ) )
5224: || ( ( extractFloatx80Exp( b ) == 0x7FFF )
5225: && (uint64_t) ( extractFloatx80Frac( b )<<1 ) )
5226: ) {
5227: if ( floatx80_is_signaling_nan( a )
5228: || floatx80_is_signaling_nan( b ) ) {
5229: float_raise( float_flag_invalid STATUS_VAR);
5230: }
5231: return 1;
5232: }
5233: return 0;
5234: }
1.1 root 5235:
5236: /*----------------------------------------------------------------------------
5237: | Returns the result of converting the quadruple-precision floating-point
5238: | value `a' to the 32-bit two's complement integer format. The conversion
5239: | is performed according to the IEC/IEEE Standard for Binary Floating-Point
5240: | Arithmetic---which means in particular that the conversion is rounded
5241: | according to the current rounding mode. If `a' is a NaN, the largest
5242: | positive integer is returned. Otherwise, if the conversion overflows, the
5243: | largest integer with the same sign as `a' is returned.
5244: *----------------------------------------------------------------------------*/
5245:
5246: int32 float128_to_int32( float128 a STATUS_PARAM )
5247: {
5248: flag aSign;
5249: int32 aExp, shiftCount;
1.1.1.8 root 5250: uint64_t aSig0, aSig1;
1.1 root 5251:
5252: aSig1 = extractFloat128Frac1( a );
5253: aSig0 = extractFloat128Frac0( a );
5254: aExp = extractFloat128Exp( a );
5255: aSign = extractFloat128Sign( a );
5256: if ( ( aExp == 0x7FFF ) && ( aSig0 | aSig1 ) ) aSign = 0;
5257: if ( aExp ) aSig0 |= LIT64( 0x0001000000000000 );
5258: aSig0 |= ( aSig1 != 0 );
5259: shiftCount = 0x4028 - aExp;
5260: if ( 0 < shiftCount ) shift64RightJamming( aSig0, shiftCount, &aSig0 );
5261: return roundAndPackInt32( aSign, aSig0 STATUS_VAR );
5262:
5263: }
5264:
5265: /*----------------------------------------------------------------------------
5266: | Returns the result of converting the quadruple-precision floating-point
5267: | value `a' to the 32-bit two's complement integer format. The conversion
5268: | is performed according to the IEC/IEEE Standard for Binary Floating-Point
5269: | Arithmetic, except that the conversion is always rounded toward zero. If
5270: | `a' is a NaN, the largest positive integer is returned. Otherwise, if the
5271: | conversion overflows, the largest integer with the same sign as `a' is
5272: | returned.
5273: *----------------------------------------------------------------------------*/
5274:
5275: int32 float128_to_int32_round_to_zero( float128 a STATUS_PARAM )
5276: {
5277: flag aSign;
5278: int32 aExp, shiftCount;
1.1.1.8 root 5279: uint64_t aSig0, aSig1, savedASig;
1.1.1.10! root 5280: int32_t z;
1.1 root 5281:
5282: aSig1 = extractFloat128Frac1( a );
5283: aSig0 = extractFloat128Frac0( a );
5284: aExp = extractFloat128Exp( a );
5285: aSign = extractFloat128Sign( a );
5286: aSig0 |= ( aSig1 != 0 );
5287: if ( 0x401E < aExp ) {
5288: if ( ( aExp == 0x7FFF ) && aSig0 ) aSign = 0;
5289: goto invalid;
5290: }
5291: else if ( aExp < 0x3FFF ) {
5292: if ( aExp || aSig0 ) STATUS(float_exception_flags) |= float_flag_inexact;
5293: return 0;
5294: }
5295: aSig0 |= LIT64( 0x0001000000000000 );
5296: shiftCount = 0x402F - aExp;
5297: savedASig = aSig0;
5298: aSig0 >>= shiftCount;
5299: z = aSig0;
5300: if ( aSign ) z = - z;
5301: if ( ( z < 0 ) ^ aSign ) {
5302: invalid:
5303: float_raise( float_flag_invalid STATUS_VAR);
1.1.1.8 root 5304: return aSign ? (int32_t) 0x80000000 : 0x7FFFFFFF;
1.1 root 5305: }
5306: if ( ( aSig0<<shiftCount ) != savedASig ) {
5307: STATUS(float_exception_flags) |= float_flag_inexact;
5308: }
5309: return z;
5310:
5311: }
5312:
5313: /*----------------------------------------------------------------------------
5314: | Returns the result of converting the quadruple-precision floating-point
5315: | value `a' to the 64-bit two's complement integer format. The conversion
5316: | is performed according to the IEC/IEEE Standard for Binary Floating-Point
5317: | Arithmetic---which means in particular that the conversion is rounded
5318: | according to the current rounding mode. If `a' is a NaN, the largest
5319: | positive integer is returned. Otherwise, if the conversion overflows, the
5320: | largest integer with the same sign as `a' is returned.
5321: *----------------------------------------------------------------------------*/
5322:
5323: int64 float128_to_int64( float128 a STATUS_PARAM )
5324: {
5325: flag aSign;
5326: int32 aExp, shiftCount;
1.1.1.8 root 5327: uint64_t aSig0, aSig1;
1.1 root 5328:
5329: aSig1 = extractFloat128Frac1( a );
5330: aSig0 = extractFloat128Frac0( a );
5331: aExp = extractFloat128Exp( a );
5332: aSign = extractFloat128Sign( a );
5333: if ( aExp ) aSig0 |= LIT64( 0x0001000000000000 );
5334: shiftCount = 0x402F - aExp;
5335: if ( shiftCount <= 0 ) {
5336: if ( 0x403E < aExp ) {
5337: float_raise( float_flag_invalid STATUS_VAR);
5338: if ( ! aSign
5339: || ( ( aExp == 0x7FFF )
5340: && ( aSig1 || ( aSig0 != LIT64( 0x0001000000000000 ) ) )
5341: )
5342: ) {
5343: return LIT64( 0x7FFFFFFFFFFFFFFF );
5344: }
1.1.1.8 root 5345: return (int64_t) LIT64( 0x8000000000000000 );
1.1 root 5346: }
5347: shortShift128Left( aSig0, aSig1, - shiftCount, &aSig0, &aSig1 );
5348: }
5349: else {
5350: shift64ExtraRightJamming( aSig0, aSig1, shiftCount, &aSig0, &aSig1 );
5351: }
5352: return roundAndPackInt64( aSign, aSig0, aSig1 STATUS_VAR );
5353:
5354: }
5355:
5356: /*----------------------------------------------------------------------------
5357: | Returns the result of converting the quadruple-precision floating-point
5358: | value `a' to the 64-bit two's complement integer format. The conversion
5359: | is performed according to the IEC/IEEE Standard for Binary Floating-Point
5360: | Arithmetic, except that the conversion is always rounded toward zero.
5361: | If `a' is a NaN, the largest positive integer is returned. Otherwise, if
5362: | the conversion overflows, the largest integer with the same sign as `a' is
5363: | returned.
5364: *----------------------------------------------------------------------------*/
5365:
5366: int64 float128_to_int64_round_to_zero( float128 a STATUS_PARAM )
5367: {
5368: flag aSign;
5369: int32 aExp, shiftCount;
1.1.1.8 root 5370: uint64_t aSig0, aSig1;
1.1 root 5371: int64 z;
5372:
5373: aSig1 = extractFloat128Frac1( a );
5374: aSig0 = extractFloat128Frac0( a );
5375: aExp = extractFloat128Exp( a );
5376: aSign = extractFloat128Sign( a );
5377: if ( aExp ) aSig0 |= LIT64( 0x0001000000000000 );
5378: shiftCount = aExp - 0x402F;
5379: if ( 0 < shiftCount ) {
5380: if ( 0x403E <= aExp ) {
5381: aSig0 &= LIT64( 0x0000FFFFFFFFFFFF );
5382: if ( ( a.high == LIT64( 0xC03E000000000000 ) )
5383: && ( aSig1 < LIT64( 0x0002000000000000 ) ) ) {
5384: if ( aSig1 ) STATUS(float_exception_flags) |= float_flag_inexact;
5385: }
5386: else {
5387: float_raise( float_flag_invalid STATUS_VAR);
5388: if ( ! aSign || ( ( aExp == 0x7FFF ) && ( aSig0 | aSig1 ) ) ) {
5389: return LIT64( 0x7FFFFFFFFFFFFFFF );
5390: }
5391: }
1.1.1.8 root 5392: return (int64_t) LIT64( 0x8000000000000000 );
1.1 root 5393: }
5394: z = ( aSig0<<shiftCount ) | ( aSig1>>( ( - shiftCount ) & 63 ) );
1.1.1.8 root 5395: if ( (uint64_t) ( aSig1<<shiftCount ) ) {
1.1 root 5396: STATUS(float_exception_flags) |= float_flag_inexact;
5397: }
5398: }
5399: else {
5400: if ( aExp < 0x3FFF ) {
5401: if ( aExp | aSig0 | aSig1 ) {
5402: STATUS(float_exception_flags) |= float_flag_inexact;
5403: }
5404: return 0;
5405: }
5406: z = aSig0>>( - shiftCount );
5407: if ( aSig1
1.1.1.8 root 5408: || ( shiftCount && (uint64_t) ( aSig0<<( shiftCount & 63 ) ) ) ) {
1.1 root 5409: STATUS(float_exception_flags) |= float_flag_inexact;
5410: }
5411: }
5412: if ( aSign ) z = - z;
5413: return z;
5414:
5415: }
5416:
5417: /*----------------------------------------------------------------------------
5418: | Returns the result of converting the quadruple-precision floating-point
5419: | value `a' to the single-precision floating-point format. The conversion
5420: | is performed according to the IEC/IEEE Standard for Binary Floating-Point
5421: | Arithmetic.
5422: *----------------------------------------------------------------------------*/
5423:
5424: float32 float128_to_float32( float128 a STATUS_PARAM )
5425: {
5426: flag aSign;
5427: int32 aExp;
1.1.1.8 root 5428: uint64_t aSig0, aSig1;
5429: uint32_t zSig;
1.1 root 5430:
5431: aSig1 = extractFloat128Frac1( a );
5432: aSig0 = extractFloat128Frac0( a );
5433: aExp = extractFloat128Exp( a );
5434: aSign = extractFloat128Sign( a );
5435: if ( aExp == 0x7FFF ) {
5436: if ( aSig0 | aSig1 ) {
1.1.1.8 root 5437: return commonNaNToFloat32( float128ToCommonNaN( a STATUS_VAR ) STATUS_VAR );
1.1 root 5438: }
5439: return packFloat32( aSign, 0xFF, 0 );
5440: }
5441: aSig0 |= ( aSig1 != 0 );
5442: shift64RightJamming( aSig0, 18, &aSig0 );
5443: zSig = aSig0;
5444: if ( aExp || zSig ) {
5445: zSig |= 0x40000000;
5446: aExp -= 0x3F81;
5447: }
5448: return roundAndPackFloat32( aSign, aExp, zSig STATUS_VAR );
5449:
5450: }
5451:
5452: /*----------------------------------------------------------------------------
5453: | Returns the result of converting the quadruple-precision floating-point
5454: | value `a' to the double-precision floating-point format. The conversion
5455: | is performed according to the IEC/IEEE Standard for Binary Floating-Point
5456: | Arithmetic.
5457: *----------------------------------------------------------------------------*/
5458:
5459: float64 float128_to_float64( float128 a STATUS_PARAM )
5460: {
5461: flag aSign;
5462: int32 aExp;
1.1.1.8 root 5463: uint64_t aSig0, aSig1;
1.1 root 5464:
5465: aSig1 = extractFloat128Frac1( a );
5466: aSig0 = extractFloat128Frac0( a );
5467: aExp = extractFloat128Exp( a );
5468: aSign = extractFloat128Sign( a );
5469: if ( aExp == 0x7FFF ) {
5470: if ( aSig0 | aSig1 ) {
1.1.1.8 root 5471: return commonNaNToFloat64( float128ToCommonNaN( a STATUS_VAR ) STATUS_VAR );
1.1 root 5472: }
5473: return packFloat64( aSign, 0x7FF, 0 );
5474: }
5475: shortShift128Left( aSig0, aSig1, 14, &aSig0, &aSig1 );
5476: aSig0 |= ( aSig1 != 0 );
5477: if ( aExp || aSig0 ) {
5478: aSig0 |= LIT64( 0x4000000000000000 );
5479: aExp -= 0x3C01;
5480: }
5481: return roundAndPackFloat64( aSign, aExp, aSig0 STATUS_VAR );
5482:
5483: }
5484:
5485: /*----------------------------------------------------------------------------
5486: | Returns the result of converting the quadruple-precision floating-point
5487: | value `a' to the extended double-precision floating-point format. The
5488: | conversion is performed according to the IEC/IEEE Standard for Binary
5489: | Floating-Point Arithmetic.
5490: *----------------------------------------------------------------------------*/
5491:
5492: floatx80 float128_to_floatx80( float128 a STATUS_PARAM )
5493: {
5494: flag aSign;
5495: int32 aExp;
1.1.1.8 root 5496: uint64_t aSig0, aSig1;
1.1 root 5497:
5498: aSig1 = extractFloat128Frac1( a );
5499: aSig0 = extractFloat128Frac0( a );
5500: aExp = extractFloat128Exp( a );
5501: aSign = extractFloat128Sign( a );
5502: if ( aExp == 0x7FFF ) {
5503: if ( aSig0 | aSig1 ) {
1.1.1.8 root 5504: return commonNaNToFloatx80( float128ToCommonNaN( a STATUS_VAR ) STATUS_VAR );
1.1 root 5505: }
5506: return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
5507: }
5508: if ( aExp == 0 ) {
5509: if ( ( aSig0 | aSig1 ) == 0 ) return packFloatx80( aSign, 0, 0 );
5510: normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 );
5511: }
5512: else {
5513: aSig0 |= LIT64( 0x0001000000000000 );
5514: }
5515: shortShift128Left( aSig0, aSig1, 15, &aSig0, &aSig1 );
5516: return roundAndPackFloatx80( 80, aSign, aExp, aSig0, aSig1 STATUS_VAR );
5517:
5518: }
5519:
5520: /*----------------------------------------------------------------------------
5521: | Rounds the quadruple-precision floating-point value `a' to an integer, and
5522: | returns the result as a quadruple-precision floating-point value. The
5523: | operation is performed according to the IEC/IEEE Standard for Binary
5524: | Floating-Point Arithmetic.
5525: *----------------------------------------------------------------------------*/
5526:
5527: float128 float128_round_to_int( float128 a STATUS_PARAM )
5528: {
5529: flag aSign;
5530: int32 aExp;
1.1.1.8 root 5531: uint64_t lastBitMask, roundBitsMask;
1.1 root 5532: int8 roundingMode;
5533: float128 z;
5534:
5535: aExp = extractFloat128Exp( a );
5536: if ( 0x402F <= aExp ) {
5537: if ( 0x406F <= aExp ) {
5538: if ( ( aExp == 0x7FFF )
5539: && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) )
5540: ) {
5541: return propagateFloat128NaN( a, a STATUS_VAR );
5542: }
5543: return a;
5544: }
5545: lastBitMask = 1;
5546: lastBitMask = ( lastBitMask<<( 0x406E - aExp ) )<<1;
5547: roundBitsMask = lastBitMask - 1;
5548: z = a;
5549: roundingMode = STATUS(float_rounding_mode);
5550: if ( roundingMode == float_round_nearest_even ) {
5551: if ( lastBitMask ) {
5552: add128( z.high, z.low, 0, lastBitMask>>1, &z.high, &z.low );
5553: if ( ( z.low & roundBitsMask ) == 0 ) z.low &= ~ lastBitMask;
5554: }
5555: else {
1.1.1.8 root 5556: if ( (int64_t) z.low < 0 ) {
1.1 root 5557: ++z.high;
1.1.1.8 root 5558: if ( (uint64_t) ( z.low<<1 ) == 0 ) z.high &= ~1;
1.1 root 5559: }
5560: }
5561: }
5562: else if ( roundingMode != float_round_to_zero ) {
5563: if ( extractFloat128Sign( z )
5564: ^ ( roundingMode == float_round_up ) ) {
5565: add128( z.high, z.low, 0, roundBitsMask, &z.high, &z.low );
5566: }
5567: }
5568: z.low &= ~ roundBitsMask;
5569: }
5570: else {
5571: if ( aExp < 0x3FFF ) {
1.1.1.8 root 5572: if ( ( ( (uint64_t) ( a.high<<1 ) ) | a.low ) == 0 ) return a;
1.1 root 5573: STATUS(float_exception_flags) |= float_flag_inexact;
5574: aSign = extractFloat128Sign( a );
5575: switch ( STATUS(float_rounding_mode) ) {
5576: case float_round_nearest_even:
5577: if ( ( aExp == 0x3FFE )
5578: && ( extractFloat128Frac0( a )
5579: | extractFloat128Frac1( a ) )
5580: ) {
5581: return packFloat128( aSign, 0x3FFF, 0, 0 );
5582: }
5583: break;
5584: case float_round_down:
5585: return
5586: aSign ? packFloat128( 1, 0x3FFF, 0, 0 )
5587: : packFloat128( 0, 0, 0, 0 );
5588: case float_round_up:
5589: return
5590: aSign ? packFloat128( 1, 0, 0, 0 )
5591: : packFloat128( 0, 0x3FFF, 0, 0 );
5592: }
5593: return packFloat128( aSign, 0, 0, 0 );
5594: }
5595: lastBitMask = 1;
5596: lastBitMask <<= 0x402F - aExp;
5597: roundBitsMask = lastBitMask - 1;
5598: z.low = 0;
5599: z.high = a.high;
5600: roundingMode = STATUS(float_rounding_mode);
5601: if ( roundingMode == float_round_nearest_even ) {
5602: z.high += lastBitMask>>1;
5603: if ( ( ( z.high & roundBitsMask ) | a.low ) == 0 ) {
5604: z.high &= ~ lastBitMask;
5605: }
5606: }
5607: else if ( roundingMode != float_round_to_zero ) {
5608: if ( extractFloat128Sign( z )
5609: ^ ( roundingMode == float_round_up ) ) {
5610: z.high |= ( a.low != 0 );
5611: z.high += roundBitsMask;
5612: }
5613: }
5614: z.high &= ~ roundBitsMask;
5615: }
5616: if ( ( z.low != a.low ) || ( z.high != a.high ) ) {
5617: STATUS(float_exception_flags) |= float_flag_inexact;
5618: }
5619: return z;
5620:
5621: }
5622:
5623: /*----------------------------------------------------------------------------
5624: | Returns the result of adding the absolute values of the quadruple-precision
5625: | floating-point values `a' and `b'. If `zSign' is 1, the sum is negated
5626: | before being returned. `zSign' is ignored if the result is a NaN.
5627: | The addition is performed according to the IEC/IEEE Standard for Binary
5628: | Floating-Point Arithmetic.
5629: *----------------------------------------------------------------------------*/
5630:
5631: static float128 addFloat128Sigs( float128 a, float128 b, flag zSign STATUS_PARAM)
5632: {
5633: int32 aExp, bExp, zExp;
1.1.1.8 root 5634: uint64_t aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2;
1.1 root 5635: int32 expDiff;
5636:
5637: aSig1 = extractFloat128Frac1( a );
5638: aSig0 = extractFloat128Frac0( a );
5639: aExp = extractFloat128Exp( a );
5640: bSig1 = extractFloat128Frac1( b );
5641: bSig0 = extractFloat128Frac0( b );
5642: bExp = extractFloat128Exp( b );
5643: expDiff = aExp - bExp;
5644: if ( 0 < expDiff ) {
5645: if ( aExp == 0x7FFF ) {
5646: if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, b STATUS_VAR );
5647: return a;
5648: }
5649: if ( bExp == 0 ) {
5650: --expDiff;
5651: }
5652: else {
5653: bSig0 |= LIT64( 0x0001000000000000 );
5654: }
5655: shift128ExtraRightJamming(
5656: bSig0, bSig1, 0, expDiff, &bSig0, &bSig1, &zSig2 );
5657: zExp = aExp;
5658: }
5659: else if ( expDiff < 0 ) {
5660: if ( bExp == 0x7FFF ) {
5661: if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b STATUS_VAR );
5662: return packFloat128( zSign, 0x7FFF, 0, 0 );
5663: }
5664: if ( aExp == 0 ) {
5665: ++expDiff;
5666: }
5667: else {
5668: aSig0 |= LIT64( 0x0001000000000000 );
5669: }
5670: shift128ExtraRightJamming(
5671: aSig0, aSig1, 0, - expDiff, &aSig0, &aSig1, &zSig2 );
5672: zExp = bExp;
5673: }
5674: else {
5675: if ( aExp == 0x7FFF ) {
5676: if ( aSig0 | aSig1 | bSig0 | bSig1 ) {
5677: return propagateFloat128NaN( a, b STATUS_VAR );
5678: }
5679: return a;
5680: }
5681: add128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 );
1.1.1.4 root 5682: if ( aExp == 0 ) {
1.1.1.8 root 5683: if (STATUS(flush_to_zero)) {
5684: if (zSig0 | zSig1) {
5685: float_raise(float_flag_output_denormal STATUS_VAR);
5686: }
5687: return packFloat128(zSign, 0, 0, 0);
5688: }
1.1.1.4 root 5689: return packFloat128( zSign, 0, zSig0, zSig1 );
5690: }
1.1 root 5691: zSig2 = 0;
5692: zSig0 |= LIT64( 0x0002000000000000 );
5693: zExp = aExp;
5694: goto shiftRight1;
5695: }
5696: aSig0 |= LIT64( 0x0001000000000000 );
5697: add128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 );
5698: --zExp;
5699: if ( zSig0 < LIT64( 0x0002000000000000 ) ) goto roundAndPack;
5700: ++zExp;
5701: shiftRight1:
5702: shift128ExtraRightJamming(
5703: zSig0, zSig1, zSig2, 1, &zSig0, &zSig1, &zSig2 );
5704: roundAndPack:
5705: return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 STATUS_VAR );
5706:
5707: }
5708:
5709: /*----------------------------------------------------------------------------
5710: | Returns the result of subtracting the absolute values of the quadruple-
5711: | precision floating-point values `a' and `b'. If `zSign' is 1, the
5712: | difference is negated before being returned. `zSign' is ignored if the
5713: | result is a NaN. The subtraction is performed according to the IEC/IEEE
5714: | Standard for Binary Floating-Point Arithmetic.
5715: *----------------------------------------------------------------------------*/
5716:
5717: static float128 subFloat128Sigs( float128 a, float128 b, flag zSign STATUS_PARAM)
5718: {
5719: int32 aExp, bExp, zExp;
1.1.1.8 root 5720: uint64_t aSig0, aSig1, bSig0, bSig1, zSig0, zSig1;
1.1 root 5721: int32 expDiff;
5722: float128 z;
5723:
5724: aSig1 = extractFloat128Frac1( a );
5725: aSig0 = extractFloat128Frac0( a );
5726: aExp = extractFloat128Exp( a );
5727: bSig1 = extractFloat128Frac1( b );
5728: bSig0 = extractFloat128Frac0( b );
5729: bExp = extractFloat128Exp( b );
5730: expDiff = aExp - bExp;
5731: shortShift128Left( aSig0, aSig1, 14, &aSig0, &aSig1 );
5732: shortShift128Left( bSig0, bSig1, 14, &bSig0, &bSig1 );
5733: if ( 0 < expDiff ) goto aExpBigger;
5734: if ( expDiff < 0 ) goto bExpBigger;
5735: if ( aExp == 0x7FFF ) {
5736: if ( aSig0 | aSig1 | bSig0 | bSig1 ) {
5737: return propagateFloat128NaN( a, b STATUS_VAR );
5738: }
5739: float_raise( float_flag_invalid STATUS_VAR);
5740: z.low = float128_default_nan_low;
5741: z.high = float128_default_nan_high;
5742: return z;
5743: }
5744: if ( aExp == 0 ) {
5745: aExp = 1;
5746: bExp = 1;
5747: }
5748: if ( bSig0 < aSig0 ) goto aBigger;
5749: if ( aSig0 < bSig0 ) goto bBigger;
5750: if ( bSig1 < aSig1 ) goto aBigger;
5751: if ( aSig1 < bSig1 ) goto bBigger;
5752: return packFloat128( STATUS(float_rounding_mode) == float_round_down, 0, 0, 0 );
5753: bExpBigger:
5754: if ( bExp == 0x7FFF ) {
5755: if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b STATUS_VAR );
5756: return packFloat128( zSign ^ 1, 0x7FFF, 0, 0 );
5757: }
5758: if ( aExp == 0 ) {
5759: ++expDiff;
5760: }
5761: else {
5762: aSig0 |= LIT64( 0x4000000000000000 );
5763: }
5764: shift128RightJamming( aSig0, aSig1, - expDiff, &aSig0, &aSig1 );
5765: bSig0 |= LIT64( 0x4000000000000000 );
5766: bBigger:
5767: sub128( bSig0, bSig1, aSig0, aSig1, &zSig0, &zSig1 );
5768: zExp = bExp;
5769: zSign ^= 1;
5770: goto normalizeRoundAndPack;
5771: aExpBigger:
5772: if ( aExp == 0x7FFF ) {
5773: if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, b STATUS_VAR );
5774: return a;
5775: }
5776: if ( bExp == 0 ) {
5777: --expDiff;
5778: }
5779: else {
5780: bSig0 |= LIT64( 0x4000000000000000 );
5781: }
5782: shift128RightJamming( bSig0, bSig1, expDiff, &bSig0, &bSig1 );
5783: aSig0 |= LIT64( 0x4000000000000000 );
5784: aBigger:
5785: sub128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 );
5786: zExp = aExp;
5787: normalizeRoundAndPack:
5788: --zExp;
5789: return normalizeRoundAndPackFloat128( zSign, zExp - 14, zSig0, zSig1 STATUS_VAR );
5790:
5791: }
5792:
5793: /*----------------------------------------------------------------------------
5794: | Returns the result of adding the quadruple-precision floating-point values
5795: | `a' and `b'. The operation is performed according to the IEC/IEEE Standard
5796: | for Binary Floating-Point Arithmetic.
5797: *----------------------------------------------------------------------------*/
5798:
5799: float128 float128_add( float128 a, float128 b STATUS_PARAM )
5800: {
5801: flag aSign, bSign;
5802:
5803: aSign = extractFloat128Sign( a );
5804: bSign = extractFloat128Sign( b );
5805: if ( aSign == bSign ) {
5806: return addFloat128Sigs( a, b, aSign STATUS_VAR );
5807: }
5808: else {
5809: return subFloat128Sigs( a, b, aSign STATUS_VAR );
5810: }
5811:
5812: }
5813:
5814: /*----------------------------------------------------------------------------
5815: | Returns the result of subtracting the quadruple-precision floating-point
5816: | values `a' and `b'. The operation is performed according to the IEC/IEEE
5817: | Standard for Binary Floating-Point Arithmetic.
5818: *----------------------------------------------------------------------------*/
5819:
5820: float128 float128_sub( float128 a, float128 b STATUS_PARAM )
5821: {
5822: flag aSign, bSign;
5823:
5824: aSign = extractFloat128Sign( a );
5825: bSign = extractFloat128Sign( b );
5826: if ( aSign == bSign ) {
5827: return subFloat128Sigs( a, b, aSign STATUS_VAR );
5828: }
5829: else {
5830: return addFloat128Sigs( a, b, aSign STATUS_VAR );
5831: }
5832:
5833: }
5834:
5835: /*----------------------------------------------------------------------------
5836: | Returns the result of multiplying the quadruple-precision floating-point
5837: | values `a' and `b'. The operation is performed according to the IEC/IEEE
5838: | Standard for Binary Floating-Point Arithmetic.
5839: *----------------------------------------------------------------------------*/
5840:
5841: float128 float128_mul( float128 a, float128 b STATUS_PARAM )
5842: {
5843: flag aSign, bSign, zSign;
5844: int32 aExp, bExp, zExp;
1.1.1.8 root 5845: uint64_t aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2, zSig3;
1.1 root 5846: float128 z;
5847:
5848: aSig1 = extractFloat128Frac1( a );
5849: aSig0 = extractFloat128Frac0( a );
5850: aExp = extractFloat128Exp( a );
5851: aSign = extractFloat128Sign( a );
5852: bSig1 = extractFloat128Frac1( b );
5853: bSig0 = extractFloat128Frac0( b );
5854: bExp = extractFloat128Exp( b );
5855: bSign = extractFloat128Sign( b );
5856: zSign = aSign ^ bSign;
5857: if ( aExp == 0x7FFF ) {
5858: if ( ( aSig0 | aSig1 )
5859: || ( ( bExp == 0x7FFF ) && ( bSig0 | bSig1 ) ) ) {
5860: return propagateFloat128NaN( a, b STATUS_VAR );
5861: }
5862: if ( ( bExp | bSig0 | bSig1 ) == 0 ) goto invalid;
5863: return packFloat128( zSign, 0x7FFF, 0, 0 );
5864: }
5865: if ( bExp == 0x7FFF ) {
5866: if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b STATUS_VAR );
5867: if ( ( aExp | aSig0 | aSig1 ) == 0 ) {
5868: invalid:
5869: float_raise( float_flag_invalid STATUS_VAR);
5870: z.low = float128_default_nan_low;
5871: z.high = float128_default_nan_high;
5872: return z;
5873: }
5874: return packFloat128( zSign, 0x7FFF, 0, 0 );
5875: }
5876: if ( aExp == 0 ) {
5877: if ( ( aSig0 | aSig1 ) == 0 ) return packFloat128( zSign, 0, 0, 0 );
5878: normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 );
5879: }
5880: if ( bExp == 0 ) {
5881: if ( ( bSig0 | bSig1 ) == 0 ) return packFloat128( zSign, 0, 0, 0 );
5882: normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 );
5883: }
5884: zExp = aExp + bExp - 0x4000;
5885: aSig0 |= LIT64( 0x0001000000000000 );
5886: shortShift128Left( bSig0, bSig1, 16, &bSig0, &bSig1 );
5887: mul128To256( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1, &zSig2, &zSig3 );
5888: add128( zSig0, zSig1, aSig0, aSig1, &zSig0, &zSig1 );
5889: zSig2 |= ( zSig3 != 0 );
5890: if ( LIT64( 0x0002000000000000 ) <= zSig0 ) {
5891: shift128ExtraRightJamming(
5892: zSig0, zSig1, zSig2, 1, &zSig0, &zSig1, &zSig2 );
5893: ++zExp;
5894: }
5895: return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 STATUS_VAR );
5896:
5897: }
5898:
5899: /*----------------------------------------------------------------------------
5900: | Returns the result of dividing the quadruple-precision floating-point value
5901: | `a' by the corresponding value `b'. The operation is performed according to
5902: | the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
5903: *----------------------------------------------------------------------------*/
5904:
5905: float128 float128_div( float128 a, float128 b STATUS_PARAM )
5906: {
5907: flag aSign, bSign, zSign;
5908: int32 aExp, bExp, zExp;
1.1.1.8 root 5909: uint64_t aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2;
5910: uint64_t rem0, rem1, rem2, rem3, term0, term1, term2, term3;
1.1 root 5911: float128 z;
5912:
5913: aSig1 = extractFloat128Frac1( a );
5914: aSig0 = extractFloat128Frac0( a );
5915: aExp = extractFloat128Exp( a );
5916: aSign = extractFloat128Sign( a );
5917: bSig1 = extractFloat128Frac1( b );
5918: bSig0 = extractFloat128Frac0( b );
5919: bExp = extractFloat128Exp( b );
5920: bSign = extractFloat128Sign( b );
5921: zSign = aSign ^ bSign;
5922: if ( aExp == 0x7FFF ) {
5923: if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, b STATUS_VAR );
5924: if ( bExp == 0x7FFF ) {
5925: if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b STATUS_VAR );
5926: goto invalid;
5927: }
5928: return packFloat128( zSign, 0x7FFF, 0, 0 );
5929: }
5930: if ( bExp == 0x7FFF ) {
5931: if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b STATUS_VAR );
5932: return packFloat128( zSign, 0, 0, 0 );
5933: }
5934: if ( bExp == 0 ) {
5935: if ( ( bSig0 | bSig1 ) == 0 ) {
5936: if ( ( aExp | aSig0 | aSig1 ) == 0 ) {
5937: invalid:
5938: float_raise( float_flag_invalid STATUS_VAR);
5939: z.low = float128_default_nan_low;
5940: z.high = float128_default_nan_high;
5941: return z;
5942: }
5943: float_raise( float_flag_divbyzero STATUS_VAR);
5944: return packFloat128( zSign, 0x7FFF, 0, 0 );
5945: }
5946: normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 );
5947: }
5948: if ( aExp == 0 ) {
5949: if ( ( aSig0 | aSig1 ) == 0 ) return packFloat128( zSign, 0, 0, 0 );
5950: normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 );
5951: }
5952: zExp = aExp - bExp + 0x3FFD;
5953: shortShift128Left(
5954: aSig0 | LIT64( 0x0001000000000000 ), aSig1, 15, &aSig0, &aSig1 );
5955: shortShift128Left(
5956: bSig0 | LIT64( 0x0001000000000000 ), bSig1, 15, &bSig0, &bSig1 );
5957: if ( le128( bSig0, bSig1, aSig0, aSig1 ) ) {
5958: shift128Right( aSig0, aSig1, 1, &aSig0, &aSig1 );
5959: ++zExp;
5960: }
5961: zSig0 = estimateDiv128To64( aSig0, aSig1, bSig0 );
5962: mul128By64To192( bSig0, bSig1, zSig0, &term0, &term1, &term2 );
5963: sub192( aSig0, aSig1, 0, term0, term1, term2, &rem0, &rem1, &rem2 );
1.1.1.8 root 5964: while ( (int64_t) rem0 < 0 ) {
1.1 root 5965: --zSig0;
5966: add192( rem0, rem1, rem2, 0, bSig0, bSig1, &rem0, &rem1, &rem2 );
5967: }
5968: zSig1 = estimateDiv128To64( rem1, rem2, bSig0 );
5969: if ( ( zSig1 & 0x3FFF ) <= 4 ) {
5970: mul128By64To192( bSig0, bSig1, zSig1, &term1, &term2, &term3 );
5971: sub192( rem1, rem2, 0, term1, term2, term3, &rem1, &rem2, &rem3 );
1.1.1.8 root 5972: while ( (int64_t) rem1 < 0 ) {
1.1 root 5973: --zSig1;
5974: add192( rem1, rem2, rem3, 0, bSig0, bSig1, &rem1, &rem2, &rem3 );
5975: }
5976: zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 );
5977: }
5978: shift128ExtraRightJamming( zSig0, zSig1, 0, 15, &zSig0, &zSig1, &zSig2 );
5979: return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 STATUS_VAR );
5980:
5981: }
5982:
5983: /*----------------------------------------------------------------------------
5984: | Returns the remainder of the quadruple-precision floating-point value `a'
5985: | with respect to the corresponding value `b'. The operation is performed
5986: | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
5987: *----------------------------------------------------------------------------*/
5988:
5989: float128 float128_rem( float128 a, float128 b STATUS_PARAM )
5990: {
1.1.1.6 root 5991: flag aSign, zSign;
1.1 root 5992: int32 aExp, bExp, expDiff;
1.1.1.8 root 5993: uint64_t aSig0, aSig1, bSig0, bSig1, q, term0, term1, term2;
5994: uint64_t allZero, alternateASig0, alternateASig1, sigMean1;
5995: int64_t sigMean0;
1.1 root 5996: float128 z;
5997:
5998: aSig1 = extractFloat128Frac1( a );
5999: aSig0 = extractFloat128Frac0( a );
6000: aExp = extractFloat128Exp( a );
6001: aSign = extractFloat128Sign( a );
6002: bSig1 = extractFloat128Frac1( b );
6003: bSig0 = extractFloat128Frac0( b );
6004: bExp = extractFloat128Exp( b );
6005: if ( aExp == 0x7FFF ) {
6006: if ( ( aSig0 | aSig1 )
6007: || ( ( bExp == 0x7FFF ) && ( bSig0 | bSig1 ) ) ) {
6008: return propagateFloat128NaN( a, b STATUS_VAR );
6009: }
6010: goto invalid;
6011: }
6012: if ( bExp == 0x7FFF ) {
6013: if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b STATUS_VAR );
6014: return a;
6015: }
6016: if ( bExp == 0 ) {
6017: if ( ( bSig0 | bSig1 ) == 0 ) {
6018: invalid:
6019: float_raise( float_flag_invalid STATUS_VAR);
6020: z.low = float128_default_nan_low;
6021: z.high = float128_default_nan_high;
6022: return z;
6023: }
6024: normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 );
6025: }
6026: if ( aExp == 0 ) {
6027: if ( ( aSig0 | aSig1 ) == 0 ) return a;
6028: normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 );
6029: }
6030: expDiff = aExp - bExp;
6031: if ( expDiff < -1 ) return a;
6032: shortShift128Left(
6033: aSig0 | LIT64( 0x0001000000000000 ),
6034: aSig1,
6035: 15 - ( expDiff < 0 ),
6036: &aSig0,
6037: &aSig1
6038: );
6039: shortShift128Left(
6040: bSig0 | LIT64( 0x0001000000000000 ), bSig1, 15, &bSig0, &bSig1 );
6041: q = le128( bSig0, bSig1, aSig0, aSig1 );
6042: if ( q ) sub128( aSig0, aSig1, bSig0, bSig1, &aSig0, &aSig1 );
6043: expDiff -= 64;
6044: while ( 0 < expDiff ) {
6045: q = estimateDiv128To64( aSig0, aSig1, bSig0 );
6046: q = ( 4 < q ) ? q - 4 : 0;
6047: mul128By64To192( bSig0, bSig1, q, &term0, &term1, &term2 );
6048: shortShift192Left( term0, term1, term2, 61, &term1, &term2, &allZero );
6049: shortShift128Left( aSig0, aSig1, 61, &aSig0, &allZero );
6050: sub128( aSig0, 0, term1, term2, &aSig0, &aSig1 );
6051: expDiff -= 61;
6052: }
6053: if ( -64 < expDiff ) {
6054: q = estimateDiv128To64( aSig0, aSig1, bSig0 );
6055: q = ( 4 < q ) ? q - 4 : 0;
6056: q >>= - expDiff;
6057: shift128Right( bSig0, bSig1, 12, &bSig0, &bSig1 );
6058: expDiff += 52;
6059: if ( expDiff < 0 ) {
6060: shift128Right( aSig0, aSig1, - expDiff, &aSig0, &aSig1 );
6061: }
6062: else {
6063: shortShift128Left( aSig0, aSig1, expDiff, &aSig0, &aSig1 );
6064: }
6065: mul128By64To192( bSig0, bSig1, q, &term0, &term1, &term2 );
6066: sub128( aSig0, aSig1, term1, term2, &aSig0, &aSig1 );
6067: }
6068: else {
6069: shift128Right( aSig0, aSig1, 12, &aSig0, &aSig1 );
6070: shift128Right( bSig0, bSig1, 12, &bSig0, &bSig1 );
6071: }
6072: do {
6073: alternateASig0 = aSig0;
6074: alternateASig1 = aSig1;
6075: ++q;
6076: sub128( aSig0, aSig1, bSig0, bSig1, &aSig0, &aSig1 );
1.1.1.8 root 6077: } while ( 0 <= (int64_t) aSig0 );
1.1 root 6078: add128(
1.1.1.8 root 6079: aSig0, aSig1, alternateASig0, alternateASig1, (uint64_t *)&sigMean0, &sigMean1 );
1.1 root 6080: if ( ( sigMean0 < 0 )
6081: || ( ( ( sigMean0 | sigMean1 ) == 0 ) && ( q & 1 ) ) ) {
6082: aSig0 = alternateASig0;
6083: aSig1 = alternateASig1;
6084: }
1.1.1.8 root 6085: zSign = ( (int64_t) aSig0 < 0 );
1.1 root 6086: if ( zSign ) sub128( 0, 0, aSig0, aSig1, &aSig0, &aSig1 );
6087: return
6088: normalizeRoundAndPackFloat128( aSign ^ zSign, bExp - 4, aSig0, aSig1 STATUS_VAR );
6089:
6090: }
6091:
6092: /*----------------------------------------------------------------------------
6093: | Returns the square root of the quadruple-precision floating-point value `a'.
6094: | The operation is performed according to the IEC/IEEE Standard for Binary
6095: | Floating-Point Arithmetic.
6096: *----------------------------------------------------------------------------*/
6097:
6098: float128 float128_sqrt( float128 a STATUS_PARAM )
6099: {
6100: flag aSign;
6101: int32 aExp, zExp;
1.1.1.8 root 6102: uint64_t aSig0, aSig1, zSig0, zSig1, zSig2, doubleZSig0;
6103: uint64_t rem0, rem1, rem2, rem3, term0, term1, term2, term3;
1.1 root 6104: float128 z;
6105:
6106: aSig1 = extractFloat128Frac1( a );
6107: aSig0 = extractFloat128Frac0( a );
6108: aExp = extractFloat128Exp( a );
6109: aSign = extractFloat128Sign( a );
6110: if ( aExp == 0x7FFF ) {
6111: if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, a STATUS_VAR );
6112: if ( ! aSign ) return a;
6113: goto invalid;
6114: }
6115: if ( aSign ) {
6116: if ( ( aExp | aSig0 | aSig1 ) == 0 ) return a;
6117: invalid:
6118: float_raise( float_flag_invalid STATUS_VAR);
6119: z.low = float128_default_nan_low;
6120: z.high = float128_default_nan_high;
6121: return z;
6122: }
6123: if ( aExp == 0 ) {
6124: if ( ( aSig0 | aSig1 ) == 0 ) return packFloat128( 0, 0, 0, 0 );
6125: normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 );
6126: }
6127: zExp = ( ( aExp - 0x3FFF )>>1 ) + 0x3FFE;
6128: aSig0 |= LIT64( 0x0001000000000000 );
6129: zSig0 = estimateSqrt32( aExp, aSig0>>17 );
6130: shortShift128Left( aSig0, aSig1, 13 - ( aExp & 1 ), &aSig0, &aSig1 );
6131: zSig0 = estimateDiv128To64( aSig0, aSig1, zSig0<<32 ) + ( zSig0<<30 );
6132: doubleZSig0 = zSig0<<1;
6133: mul64To128( zSig0, zSig0, &term0, &term1 );
6134: sub128( aSig0, aSig1, term0, term1, &rem0, &rem1 );
1.1.1.8 root 6135: while ( (int64_t) rem0 < 0 ) {
1.1 root 6136: --zSig0;
6137: doubleZSig0 -= 2;
6138: add128( rem0, rem1, zSig0>>63, doubleZSig0 | 1, &rem0, &rem1 );
6139: }
6140: zSig1 = estimateDiv128To64( rem1, 0, doubleZSig0 );
6141: if ( ( zSig1 & 0x1FFF ) <= 5 ) {
6142: if ( zSig1 == 0 ) zSig1 = 1;
6143: mul64To128( doubleZSig0, zSig1, &term1, &term2 );
6144: sub128( rem1, 0, term1, term2, &rem1, &rem2 );
6145: mul64To128( zSig1, zSig1, &term2, &term3 );
6146: sub192( rem1, rem2, 0, 0, term2, term3, &rem1, &rem2, &rem3 );
1.1.1.8 root 6147: while ( (int64_t) rem1 < 0 ) {
1.1 root 6148: --zSig1;
6149: shortShift128Left( 0, zSig1, 1, &term2, &term3 );
6150: term3 |= 1;
6151: term2 |= doubleZSig0;
6152: add192( rem1, rem2, rem3, 0, term2, term3, &rem1, &rem2, &rem3 );
6153: }
6154: zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 );
6155: }
6156: shift128ExtraRightJamming( zSig0, zSig1, 0, 14, &zSig0, &zSig1, &zSig2 );
6157: return roundAndPackFloat128( 0, zExp, zSig0, zSig1, zSig2 STATUS_VAR );
6158:
6159: }
6160:
6161: /*----------------------------------------------------------------------------
6162: | Returns 1 if the quadruple-precision floating-point value `a' is equal to
1.1.1.8 root 6163: | the corresponding value `b', and 0 otherwise. The invalid exception is
6164: | raised if either operand is a NaN. Otherwise, the comparison is performed
1.1 root 6165: | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
6166: *----------------------------------------------------------------------------*/
6167:
1.1.1.2 root 6168: int float128_eq( float128 a, float128 b STATUS_PARAM )
1.1 root 6169: {
6170:
6171: if ( ( ( extractFloat128Exp( a ) == 0x7FFF )
6172: && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) )
6173: || ( ( extractFloat128Exp( b ) == 0x7FFF )
6174: && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) )
6175: ) {
1.1.1.8 root 6176: float_raise( float_flag_invalid STATUS_VAR);
1.1 root 6177: return 0;
6178: }
6179: return
6180: ( a.low == b.low )
6181: && ( ( a.high == b.high )
6182: || ( ( a.low == 0 )
1.1.1.8 root 6183: && ( (uint64_t) ( ( a.high | b.high )<<1 ) == 0 ) )
1.1 root 6184: );
6185:
6186: }
6187:
6188: /*----------------------------------------------------------------------------
6189: | Returns 1 if the quadruple-precision floating-point value `a' is less than
1.1.1.8 root 6190: | or equal to the corresponding value `b', and 0 otherwise. The invalid
6191: | exception is raised if either operand is a NaN. The comparison is performed
6192: | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
1.1 root 6193: *----------------------------------------------------------------------------*/
6194:
1.1.1.2 root 6195: int float128_le( float128 a, float128 b STATUS_PARAM )
1.1 root 6196: {
6197: flag aSign, bSign;
6198:
6199: if ( ( ( extractFloat128Exp( a ) == 0x7FFF )
6200: && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) )
6201: || ( ( extractFloat128Exp( b ) == 0x7FFF )
6202: && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) )
6203: ) {
6204: float_raise( float_flag_invalid STATUS_VAR);
6205: return 0;
6206: }
6207: aSign = extractFloat128Sign( a );
6208: bSign = extractFloat128Sign( b );
6209: if ( aSign != bSign ) {
6210: return
6211: aSign
1.1.1.8 root 6212: || ( ( ( (uint64_t) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
1.1 root 6213: == 0 );
6214: }
6215: return
6216: aSign ? le128( b.high, b.low, a.high, a.low )
6217: : le128( a.high, a.low, b.high, b.low );
6218:
6219: }
6220:
6221: /*----------------------------------------------------------------------------
6222: | Returns 1 if the quadruple-precision floating-point value `a' is less than
1.1.1.8 root 6223: | the corresponding value `b', and 0 otherwise. The invalid exception is
6224: | raised if either operand is a NaN. The comparison is performed according
6225: | to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
1.1 root 6226: *----------------------------------------------------------------------------*/
6227:
1.1.1.2 root 6228: int float128_lt( float128 a, float128 b STATUS_PARAM )
1.1 root 6229: {
6230: flag aSign, bSign;
6231:
6232: if ( ( ( extractFloat128Exp( a ) == 0x7FFF )
6233: && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) )
6234: || ( ( extractFloat128Exp( b ) == 0x7FFF )
6235: && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) )
6236: ) {
6237: float_raise( float_flag_invalid STATUS_VAR);
6238: return 0;
6239: }
6240: aSign = extractFloat128Sign( a );
6241: bSign = extractFloat128Sign( b );
6242: if ( aSign != bSign ) {
6243: return
6244: aSign
1.1.1.8 root 6245: && ( ( ( (uint64_t) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
1.1 root 6246: != 0 );
6247: }
6248: return
6249: aSign ? lt128( b.high, b.low, a.high, a.low )
6250: : lt128( a.high, a.low, b.high, b.low );
6251:
6252: }
6253:
6254: /*----------------------------------------------------------------------------
1.1.1.8 root 6255: | Returns 1 if the quadruple-precision floating-point values `a' and `b' cannot
6256: | be compared, and 0 otherwise. The invalid exception is raised if either
6257: | operand is a NaN. The comparison is performed according to the IEC/IEEE
6258: | Standard for Binary Floating-Point Arithmetic.
6259: *----------------------------------------------------------------------------*/
6260:
6261: int float128_unordered( float128 a, float128 b STATUS_PARAM )
6262: {
6263: if ( ( ( extractFloat128Exp( a ) == 0x7FFF )
6264: && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) )
6265: || ( ( extractFloat128Exp( b ) == 0x7FFF )
6266: && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) )
6267: ) {
6268: float_raise( float_flag_invalid STATUS_VAR);
6269: return 1;
6270: }
6271: return 0;
6272: }
6273:
6274: /*----------------------------------------------------------------------------
1.1 root 6275: | Returns 1 if the quadruple-precision floating-point value `a' is equal to
1.1.1.8 root 6276: | the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an
6277: | exception. The comparison is performed according to the IEC/IEEE Standard
6278: | for Binary Floating-Point Arithmetic.
1.1 root 6279: *----------------------------------------------------------------------------*/
6280:
1.1.1.8 root 6281: int float128_eq_quiet( float128 a, float128 b STATUS_PARAM )
1.1 root 6282: {
6283:
6284: if ( ( ( extractFloat128Exp( a ) == 0x7FFF )
6285: && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) )
6286: || ( ( extractFloat128Exp( b ) == 0x7FFF )
6287: && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) )
6288: ) {
1.1.1.8 root 6289: if ( float128_is_signaling_nan( a )
6290: || float128_is_signaling_nan( b ) ) {
6291: float_raise( float_flag_invalid STATUS_VAR);
6292: }
1.1 root 6293: return 0;
6294: }
6295: return
6296: ( a.low == b.low )
6297: && ( ( a.high == b.high )
6298: || ( ( a.low == 0 )
1.1.1.8 root 6299: && ( (uint64_t) ( ( a.high | b.high )<<1 ) == 0 ) )
1.1 root 6300: );
6301:
6302: }
6303:
6304: /*----------------------------------------------------------------------------
6305: | Returns 1 if the quadruple-precision floating-point value `a' is less than
6306: | or equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not
6307: | cause an exception. Otherwise, the comparison is performed according to the
6308: | IEC/IEEE Standard for Binary Floating-Point Arithmetic.
6309: *----------------------------------------------------------------------------*/
6310:
1.1.1.2 root 6311: int float128_le_quiet( float128 a, float128 b STATUS_PARAM )
1.1 root 6312: {
6313: flag aSign, bSign;
6314:
6315: if ( ( ( extractFloat128Exp( a ) == 0x7FFF )
6316: && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) )
6317: || ( ( extractFloat128Exp( b ) == 0x7FFF )
6318: && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) )
6319: ) {
6320: if ( float128_is_signaling_nan( a )
6321: || float128_is_signaling_nan( b ) ) {
6322: float_raise( float_flag_invalid STATUS_VAR);
6323: }
6324: return 0;
6325: }
6326: aSign = extractFloat128Sign( a );
6327: bSign = extractFloat128Sign( b );
6328: if ( aSign != bSign ) {
6329: return
6330: aSign
1.1.1.8 root 6331: || ( ( ( (uint64_t) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
1.1 root 6332: == 0 );
6333: }
6334: return
6335: aSign ? le128( b.high, b.low, a.high, a.low )
6336: : le128( a.high, a.low, b.high, b.low );
6337:
6338: }
6339:
6340: /*----------------------------------------------------------------------------
6341: | Returns 1 if the quadruple-precision floating-point value `a' is less than
6342: | the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an
6343: | exception. Otherwise, the comparison is performed according to the IEC/IEEE
6344: | Standard for Binary Floating-Point Arithmetic.
6345: *----------------------------------------------------------------------------*/
6346:
1.1.1.2 root 6347: int float128_lt_quiet( float128 a, float128 b STATUS_PARAM )
1.1 root 6348: {
6349: flag aSign, bSign;
6350:
6351: if ( ( ( extractFloat128Exp( a ) == 0x7FFF )
6352: && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) )
6353: || ( ( extractFloat128Exp( b ) == 0x7FFF )
6354: && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) )
6355: ) {
6356: if ( float128_is_signaling_nan( a )
6357: || float128_is_signaling_nan( b ) ) {
6358: float_raise( float_flag_invalid STATUS_VAR);
6359: }
6360: return 0;
6361: }
6362: aSign = extractFloat128Sign( a );
6363: bSign = extractFloat128Sign( b );
6364: if ( aSign != bSign ) {
6365: return
6366: aSign
1.1.1.8 root 6367: && ( ( ( (uint64_t) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
1.1 root 6368: != 0 );
6369: }
6370: return
6371: aSign ? lt128( b.high, b.low, a.high, a.low )
6372: : lt128( a.high, a.low, b.high, b.low );
6373:
6374: }
6375:
1.1.1.8 root 6376: /*----------------------------------------------------------------------------
6377: | Returns 1 if the quadruple-precision floating-point values `a' and `b' cannot
6378: | be compared, and 0 otherwise. Quiet NaNs do not cause an exception. The
6379: | comparison is performed according to the IEC/IEEE Standard for Binary
6380: | Floating-Point Arithmetic.
6381: *----------------------------------------------------------------------------*/
6382:
6383: int float128_unordered_quiet( float128 a, float128 b STATUS_PARAM )
6384: {
6385: if ( ( ( extractFloat128Exp( a ) == 0x7FFF )
6386: && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) )
6387: || ( ( extractFloat128Exp( b ) == 0x7FFF )
6388: && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) )
6389: ) {
6390: if ( float128_is_signaling_nan( a )
6391: || float128_is_signaling_nan( b ) ) {
6392: float_raise( float_flag_invalid STATUS_VAR);
6393: }
6394: return 1;
6395: }
6396: return 0;
6397: }
1.1 root 6398:
6399: /* misc functions */
1.1.1.9 root 6400: float32 uint32_to_float32( uint32 a STATUS_PARAM )
1.1 root 6401: {
6402: return int64_to_float32(a STATUS_VAR);
6403: }
6404:
1.1.1.9 root 6405: float64 uint32_to_float64( uint32 a STATUS_PARAM )
1.1 root 6406: {
6407: return int64_to_float64(a STATUS_VAR);
6408: }
6409:
1.1.1.9 root 6410: uint32 float32_to_uint32( float32 a STATUS_PARAM )
1.1 root 6411: {
6412: int64_t v;
1.1.1.9 root 6413: uint32 res;
1.1 root 6414:
6415: v = float32_to_int64(a STATUS_VAR);
6416: if (v < 0) {
6417: res = 0;
6418: float_raise( float_flag_invalid STATUS_VAR);
6419: } else if (v > 0xffffffff) {
6420: res = 0xffffffff;
6421: float_raise( float_flag_invalid STATUS_VAR);
6422: } else {
6423: res = v;
6424: }
6425: return res;
6426: }
6427:
1.1.1.9 root 6428: uint32 float32_to_uint32_round_to_zero( float32 a STATUS_PARAM )
1.1 root 6429: {
6430: int64_t v;
1.1.1.9 root 6431: uint32 res;
1.1 root 6432:
6433: v = float32_to_int64_round_to_zero(a STATUS_VAR);
6434: if (v < 0) {
6435: res = 0;
6436: float_raise( float_flag_invalid STATUS_VAR);
6437: } else if (v > 0xffffffff) {
6438: res = 0xffffffff;
6439: float_raise( float_flag_invalid STATUS_VAR);
6440: } else {
6441: res = v;
6442: }
6443: return res;
6444: }
6445:
1.1.1.10! root 6446: uint_fast16_t float32_to_uint16_round_to_zero(float32 a STATUS_PARAM)
1.1.1.7 root 6447: {
6448: int64_t v;
1.1.1.10! root 6449: uint_fast16_t res;
1.1.1.7 root 6450:
6451: v = float32_to_int64_round_to_zero(a STATUS_VAR);
6452: if (v < 0) {
6453: res = 0;
6454: float_raise( float_flag_invalid STATUS_VAR);
6455: } else if (v > 0xffff) {
6456: res = 0xffff;
6457: float_raise( float_flag_invalid STATUS_VAR);
6458: } else {
6459: res = v;
6460: }
6461: return res;
6462: }
6463:
1.1.1.9 root 6464: uint32 float64_to_uint32( float64 a STATUS_PARAM )
1.1 root 6465: {
6466: int64_t v;
1.1.1.9 root 6467: uint32 res;
1.1 root 6468:
6469: v = float64_to_int64(a STATUS_VAR);
6470: if (v < 0) {
6471: res = 0;
6472: float_raise( float_flag_invalid STATUS_VAR);
6473: } else if (v > 0xffffffff) {
6474: res = 0xffffffff;
6475: float_raise( float_flag_invalid STATUS_VAR);
6476: } else {
6477: res = v;
6478: }
6479: return res;
6480: }
6481:
1.1.1.9 root 6482: uint32 float64_to_uint32_round_to_zero( float64 a STATUS_PARAM )
1.1 root 6483: {
6484: int64_t v;
1.1.1.9 root 6485: uint32 res;
1.1 root 6486:
6487: v = float64_to_int64_round_to_zero(a STATUS_VAR);
6488: if (v < 0) {
6489: res = 0;
6490: float_raise( float_flag_invalid STATUS_VAR);
6491: } else if (v > 0xffffffff) {
6492: res = 0xffffffff;
6493: float_raise( float_flag_invalid STATUS_VAR);
6494: } else {
6495: res = v;
6496: }
6497: return res;
6498: }
6499:
1.1.1.10! root 6500: uint_fast16_t float64_to_uint16_round_to_zero(float64 a STATUS_PARAM)
1.1.1.7 root 6501: {
6502: int64_t v;
1.1.1.10! root 6503: uint_fast16_t res;
1.1.1.7 root 6504:
6505: v = float64_to_int64_round_to_zero(a STATUS_VAR);
6506: if (v < 0) {
6507: res = 0;
6508: float_raise( float_flag_invalid STATUS_VAR);
6509: } else if (v > 0xffff) {
6510: res = 0xffff;
6511: float_raise( float_flag_invalid STATUS_VAR);
6512: } else {
6513: res = v;
6514: }
6515: return res;
6516: }
6517:
1.1.1.3 root 6518: /* FIXME: This looks broken. */
6519: uint64_t float64_to_uint64 (float64 a STATUS_PARAM)
6520: {
6521: int64_t v;
6522:
6523: v = float64_val(int64_to_float64(INT64_MIN STATUS_VAR));
6524: v += float64_val(a);
6525: v = float64_to_int64(make_float64(v) STATUS_VAR);
6526:
6527: return v - INT64_MIN;
6528: }
6529:
6530: uint64_t float64_to_uint64_round_to_zero (float64 a STATUS_PARAM)
6531: {
6532: int64_t v;
6533:
6534: v = float64_val(int64_to_float64(INT64_MIN STATUS_VAR));
6535: v += float64_val(a);
6536: v = float64_to_int64_round_to_zero(make_float64(v) STATUS_VAR);
6537:
6538: return v - INT64_MIN;
6539: }
6540:
1.1 root 6541: #define COMPARE(s, nan_exp) \
1.1.1.2 root 6542: INLINE int float ## s ## _compare_internal( float ## s a, float ## s b, \
1.1 root 6543: int is_quiet STATUS_PARAM ) \
6544: { \
6545: flag aSign, bSign; \
1.1.1.8 root 6546: uint ## s ## _t av, bv; \
1.1.1.7 root 6547: a = float ## s ## _squash_input_denormal(a STATUS_VAR); \
6548: b = float ## s ## _squash_input_denormal(b STATUS_VAR); \
1.1 root 6549: \
6550: if (( ( extractFloat ## s ## Exp( a ) == nan_exp ) && \
6551: extractFloat ## s ## Frac( a ) ) || \
6552: ( ( extractFloat ## s ## Exp( b ) == nan_exp ) && \
6553: extractFloat ## s ## Frac( b ) )) { \
6554: if (!is_quiet || \
6555: float ## s ## _is_signaling_nan( a ) || \
6556: float ## s ## _is_signaling_nan( b ) ) { \
6557: float_raise( float_flag_invalid STATUS_VAR); \
6558: } \
6559: return float_relation_unordered; \
6560: } \
6561: aSign = extractFloat ## s ## Sign( a ); \
6562: bSign = extractFloat ## s ## Sign( b ); \
1.1.1.3 root 6563: av = float ## s ## _val(a); \
6564: bv = float ## s ## _val(b); \
1.1 root 6565: if ( aSign != bSign ) { \
1.1.1.8 root 6566: if ( (uint ## s ## _t) ( ( av | bv )<<1 ) == 0 ) { \
1.1 root 6567: /* zero case */ \
6568: return float_relation_equal; \
6569: } else { \
6570: return 1 - (2 * aSign); \
6571: } \
6572: } else { \
1.1.1.3 root 6573: if (av == bv) { \
1.1 root 6574: return float_relation_equal; \
6575: } else { \
1.1.1.3 root 6576: return 1 - 2 * (aSign ^ ( av < bv )); \
1.1 root 6577: } \
6578: } \
6579: } \
6580: \
1.1.1.2 root 6581: int float ## s ## _compare( float ## s a, float ## s b STATUS_PARAM ) \
1.1 root 6582: { \
6583: return float ## s ## _compare_internal(a, b, 0 STATUS_VAR); \
6584: } \
6585: \
1.1.1.2 root 6586: int float ## s ## _compare_quiet( float ## s a, float ## s b STATUS_PARAM ) \
1.1 root 6587: { \
6588: return float ## s ## _compare_internal(a, b, 1 STATUS_VAR); \
6589: }
6590:
6591: COMPARE(32, 0xff)
6592: COMPARE(64, 0x7ff)
1.1.1.3 root 6593:
1.1.1.8 root 6594: INLINE int floatx80_compare_internal( floatx80 a, floatx80 b,
6595: int is_quiet STATUS_PARAM )
6596: {
6597: flag aSign, bSign;
6598:
6599: if (( ( extractFloatx80Exp( a ) == 0x7fff ) &&
6600: ( extractFloatx80Frac( a )<<1 ) ) ||
6601: ( ( extractFloatx80Exp( b ) == 0x7fff ) &&
6602: ( extractFloatx80Frac( b )<<1 ) )) {
6603: if (!is_quiet ||
6604: floatx80_is_signaling_nan( a ) ||
6605: floatx80_is_signaling_nan( b ) ) {
6606: float_raise( float_flag_invalid STATUS_VAR);
6607: }
6608: return float_relation_unordered;
6609: }
6610: aSign = extractFloatx80Sign( a );
6611: bSign = extractFloatx80Sign( b );
6612: if ( aSign != bSign ) {
6613:
6614: if ( ( ( (uint16_t) ( ( a.high | b.high ) << 1 ) ) == 0) &&
6615: ( ( a.low | b.low ) == 0 ) ) {
6616: /* zero case */
6617: return float_relation_equal;
6618: } else {
6619: return 1 - (2 * aSign);
6620: }
6621: } else {
6622: if (a.low == b.low && a.high == b.high) {
6623: return float_relation_equal;
6624: } else {
6625: return 1 - 2 * (aSign ^ ( lt128( a.high, a.low, b.high, b.low ) ));
6626: }
6627: }
6628: }
6629:
6630: int floatx80_compare( floatx80 a, floatx80 b STATUS_PARAM )
6631: {
6632: return floatx80_compare_internal(a, b, 0 STATUS_VAR);
6633: }
6634:
6635: int floatx80_compare_quiet( floatx80 a, floatx80 b STATUS_PARAM )
6636: {
6637: return floatx80_compare_internal(a, b, 1 STATUS_VAR);
6638: }
6639:
1.1.1.3 root 6640: INLINE int float128_compare_internal( float128 a, float128 b,
6641: int is_quiet STATUS_PARAM )
6642: {
6643: flag aSign, bSign;
6644:
6645: if (( ( extractFloat128Exp( a ) == 0x7fff ) &&
6646: ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) ||
6647: ( ( extractFloat128Exp( b ) == 0x7fff ) &&
6648: ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) )) {
6649: if (!is_quiet ||
6650: float128_is_signaling_nan( a ) ||
6651: float128_is_signaling_nan( b ) ) {
6652: float_raise( float_flag_invalid STATUS_VAR);
6653: }
6654: return float_relation_unordered;
6655: }
6656: aSign = extractFloat128Sign( a );
6657: bSign = extractFloat128Sign( b );
6658: if ( aSign != bSign ) {
6659: if ( ( ( ( a.high | b.high )<<1 ) | a.low | b.low ) == 0 ) {
6660: /* zero case */
6661: return float_relation_equal;
6662: } else {
6663: return 1 - (2 * aSign);
6664: }
6665: } else {
6666: if (a.low == b.low && a.high == b.high) {
6667: return float_relation_equal;
6668: } else {
6669: return 1 - 2 * (aSign ^ ( lt128( a.high, a.low, b.high, b.low ) ));
6670: }
6671: }
6672: }
6673:
6674: int float128_compare( float128 a, float128 b STATUS_PARAM )
6675: {
6676: return float128_compare_internal(a, b, 0 STATUS_VAR);
6677: }
6678:
6679: int float128_compare_quiet( float128 a, float128 b STATUS_PARAM )
6680: {
6681: return float128_compare_internal(a, b, 1 STATUS_VAR);
6682: }
6683:
1.1.1.8 root 6684: /* min() and max() functions. These can't be implemented as
6685: * 'compare and pick one input' because that would mishandle
6686: * NaNs and +0 vs -0.
6687: */
6688: #define MINMAX(s, nan_exp) \
6689: INLINE float ## s float ## s ## _minmax(float ## s a, float ## s b, \
6690: int ismin STATUS_PARAM ) \
6691: { \
6692: flag aSign, bSign; \
6693: uint ## s ## _t av, bv; \
6694: a = float ## s ## _squash_input_denormal(a STATUS_VAR); \
6695: b = float ## s ## _squash_input_denormal(b STATUS_VAR); \
6696: if (float ## s ## _is_any_nan(a) || \
6697: float ## s ## _is_any_nan(b)) { \
6698: return propagateFloat ## s ## NaN(a, b STATUS_VAR); \
6699: } \
6700: aSign = extractFloat ## s ## Sign(a); \
6701: bSign = extractFloat ## s ## Sign(b); \
6702: av = float ## s ## _val(a); \
6703: bv = float ## s ## _val(b); \
6704: if (aSign != bSign) { \
6705: if (ismin) { \
6706: return aSign ? a : b; \
6707: } else { \
6708: return aSign ? b : a; \
6709: } \
6710: } else { \
6711: if (ismin) { \
6712: return (aSign ^ (av < bv)) ? a : b; \
6713: } else { \
6714: return (aSign ^ (av < bv)) ? b : a; \
6715: } \
6716: } \
6717: } \
6718: \
6719: float ## s float ## s ## _min(float ## s a, float ## s b STATUS_PARAM) \
6720: { \
6721: return float ## s ## _minmax(a, b, 1 STATUS_VAR); \
6722: } \
6723: \
6724: float ## s float ## s ## _max(float ## s a, float ## s b STATUS_PARAM) \
6725: { \
6726: return float ## s ## _minmax(a, b, 0 STATUS_VAR); \
6727: }
6728:
6729: MINMAX(32, 0xff)
6730: MINMAX(64, 0x7ff)
6731:
6732:
1.1.1.3 root 6733: /* Multiply A by 2 raised to the power N. */
6734: float32 float32_scalbn( float32 a, int n STATUS_PARAM )
6735: {
6736: flag aSign;
1.1.1.8 root 6737: int16_t aExp;
6738: uint32_t aSig;
1.1.1.3 root 6739:
1.1.1.7 root 6740: a = float32_squash_input_denormal(a STATUS_VAR);
1.1.1.3 root 6741: aSig = extractFloat32Frac( a );
6742: aExp = extractFloat32Exp( a );
6743: aSign = extractFloat32Sign( a );
6744:
6745: if ( aExp == 0xFF ) {
1.1.1.8 root 6746: if ( aSig ) {
6747: return propagateFloat32NaN( a, a STATUS_VAR );
6748: }
1.1.1.3 root 6749: return a;
6750: }
1.1.1.4 root 6751: if ( aExp != 0 )
6752: aSig |= 0x00800000;
6753: else if ( aSig == 0 )
6754: return a;
6755:
1.1.1.8 root 6756: if (n > 0x200) {
6757: n = 0x200;
6758: } else if (n < -0x200) {
6759: n = -0x200;
6760: }
6761:
1.1.1.4 root 6762: aExp += n - 1;
6763: aSig <<= 7;
6764: return normalizeRoundAndPackFloat32( aSign, aExp, aSig STATUS_VAR );
1.1.1.3 root 6765: }
6766:
6767: float64 float64_scalbn( float64 a, int n STATUS_PARAM )
6768: {
6769: flag aSign;
1.1.1.8 root 6770: int16_t aExp;
6771: uint64_t aSig;
1.1.1.3 root 6772:
1.1.1.7 root 6773: a = float64_squash_input_denormal(a STATUS_VAR);
1.1.1.3 root 6774: aSig = extractFloat64Frac( a );
6775: aExp = extractFloat64Exp( a );
6776: aSign = extractFloat64Sign( a );
6777:
6778: if ( aExp == 0x7FF ) {
1.1.1.8 root 6779: if ( aSig ) {
6780: return propagateFloat64NaN( a, a STATUS_VAR );
6781: }
1.1.1.3 root 6782: return a;
6783: }
1.1.1.4 root 6784: if ( aExp != 0 )
6785: aSig |= LIT64( 0x0010000000000000 );
6786: else if ( aSig == 0 )
6787: return a;
6788:
1.1.1.8 root 6789: if (n > 0x1000) {
6790: n = 0x1000;
6791: } else if (n < -0x1000) {
6792: n = -0x1000;
6793: }
6794:
1.1.1.4 root 6795: aExp += n - 1;
6796: aSig <<= 10;
6797: return normalizeRoundAndPackFloat64( aSign, aExp, aSig STATUS_VAR );
1.1.1.3 root 6798: }
6799:
6800: floatx80 floatx80_scalbn( floatx80 a, int n STATUS_PARAM )
6801: {
6802: flag aSign;
1.1.1.8 root 6803: int32_t aExp;
6804: uint64_t aSig;
1.1.1.3 root 6805:
6806: aSig = extractFloatx80Frac( a );
6807: aExp = extractFloatx80Exp( a );
6808: aSign = extractFloatx80Sign( a );
6809:
1.1.1.8 root 6810: if ( aExp == 0x7FFF ) {
6811: if ( aSig<<1 ) {
6812: return propagateFloatx80NaN( a, a STATUS_VAR );
6813: }
1.1.1.3 root 6814: return a;
6815: }
1.1.1.8 root 6816:
1.1.1.4 root 6817: if (aExp == 0 && aSig == 0)
6818: return a;
6819:
1.1.1.8 root 6820: if (n > 0x10000) {
6821: n = 0x10000;
6822: } else if (n < -0x10000) {
6823: n = -0x10000;
6824: }
6825:
1.1.1.3 root 6826: aExp += n;
1.1.1.4 root 6827: return normalizeRoundAndPackFloatx80( STATUS(floatx80_rounding_precision),
6828: aSign, aExp, aSig, 0 STATUS_VAR );
1.1.1.3 root 6829: }
6830:
6831: float128 float128_scalbn( float128 a, int n STATUS_PARAM )
6832: {
6833: flag aSign;
1.1.1.8 root 6834: int32_t aExp;
6835: uint64_t aSig0, aSig1;
1.1.1.3 root 6836:
6837: aSig1 = extractFloat128Frac1( a );
6838: aSig0 = extractFloat128Frac0( a );
6839: aExp = extractFloat128Exp( a );
6840: aSign = extractFloat128Sign( a );
6841: if ( aExp == 0x7FFF ) {
1.1.1.8 root 6842: if ( aSig0 | aSig1 ) {
6843: return propagateFloat128NaN( a, a STATUS_VAR );
6844: }
1.1.1.3 root 6845: return a;
6846: }
1.1.1.4 root 6847: if ( aExp != 0 )
6848: aSig0 |= LIT64( 0x0001000000000000 );
6849: else if ( aSig0 == 0 && aSig1 == 0 )
6850: return a;
6851:
1.1.1.8 root 6852: if (n > 0x10000) {
6853: n = 0x10000;
6854: } else if (n < -0x10000) {
6855: n = -0x10000;
6856: }
6857:
1.1.1.4 root 6858: aExp += n - 1;
6859: return normalizeRoundAndPackFloat128( aSign, aExp, aSig0, aSig1
6860: STATUS_VAR );
1.1.1.3 root 6861:
6862: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.