|
|
1.1 root 1:
2: /*============================================================================
3:
4: This C source file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic
5: Package, Release 2b.
6:
7: Written by John R. Hauser. This work was made possible in part by the
8: International Computer Science Institute, located at Suite 600, 1947 Center
9: Street, Berkeley, California 94704. Funding was partially provided by the
10: National Science Foundation under grant MIP-9311980. The original version
11: of this code was written as part of a project to build a fixed-point vector
12: processor in collaboration with the University of California at Berkeley,
13: overseen by Profs. Nelson Morgan and John Wawrzynek. More information
14: is available through the Web page `http://www.cs.berkeley.edu/~jhauser/
15: arithmetic/SoftFloat.html'.
16:
17: THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has
18: been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
19: RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
20: AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES,
21: COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE
22: EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE
23: INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR
24: OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE.
25:
26: Derivative works are acceptable, even for commercial purposes, so long as
27: (1) the source code for the derivative work includes prominent notice that
28: the work is derivative, and (2) the source code includes prominent notice with
29: these four paragraphs for those parts of this code that are retained.
30:
31: =============================================================================*/
32:
33: #include "softfloat.h"
34:
35: /*----------------------------------------------------------------------------
36: | Primitive arithmetic functions, including multi-word arithmetic, and
37: | division and square root approximations. (Can be specialized to target if
38: | desired.)
39: *----------------------------------------------------------------------------*/
40: #include "softfloat-macros.h"
41:
42: /*----------------------------------------------------------------------------
43: | Functions and definitions to determine: (1) whether tininess for underflow
44: | is detected before or after rounding by default, (2) what (if anything)
45: | happens when exceptions are raised, (3) how signaling NaNs are distinguished
46: | from quiet NaNs, (4) the default generated quiet NaNs, and (5) how NaNs
47: | are propagated from function inputs to output. These details are target-
48: | specific.
49: *----------------------------------------------------------------------------*/
50: #include "softfloat-specialize.h"
51:
52: void set_float_rounding_mode(int val STATUS_PARAM)
53: {
54: STATUS(float_rounding_mode) = val;
55: }
56:
57: void set_float_exception_flags(int val STATUS_PARAM)
58: {
59: STATUS(float_exception_flags) = val;
60: }
61:
62: #ifdef FLOATX80
63: void set_floatx80_rounding_precision(int val STATUS_PARAM)
64: {
65: STATUS(floatx80_rounding_precision) = val;
66: }
67: #endif
68:
69: /*----------------------------------------------------------------------------
70: | Takes a 64-bit fixed-point value `absZ' with binary point between bits 6
71: | and 7, and returns the properly rounded 32-bit integer corresponding to the
72: | input. If `zSign' is 1, the input is negated before being converted to an
73: | integer. Bit 63 of `absZ' must be zero. Ordinarily, the fixed-point input
74: | is simply rounded to an integer, with the inexact exception raised if the
75: | input cannot be represented exactly as an integer. However, if the fixed-
76: | point input is too large, the invalid exception is raised and the largest
77: | positive or negative integer is returned.
78: *----------------------------------------------------------------------------*/
79:
80: static int32 roundAndPackInt32( flag zSign, bits64 absZ STATUS_PARAM)
81: {
82: int8 roundingMode;
83: flag roundNearestEven;
84: int8 roundIncrement, roundBits;
85: int32 z;
86:
87: roundingMode = STATUS(float_rounding_mode);
88: roundNearestEven = ( roundingMode == float_round_nearest_even );
89: roundIncrement = 0x40;
90: if ( ! roundNearestEven ) {
91: if ( roundingMode == float_round_to_zero ) {
92: roundIncrement = 0;
93: }
94: else {
95: roundIncrement = 0x7F;
96: if ( zSign ) {
97: if ( roundingMode == float_round_up ) roundIncrement = 0;
98: }
99: else {
100: if ( roundingMode == float_round_down ) roundIncrement = 0;
101: }
102: }
103: }
104: roundBits = absZ & 0x7F;
105: absZ = ( absZ + roundIncrement )>>7;
106: absZ &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven );
107: z = absZ;
108: if ( zSign ) z = - z;
109: if ( ( absZ>>32 ) || ( z && ( ( z < 0 ) ^ zSign ) ) ) {
110: float_raise( float_flag_invalid STATUS_VAR);
111: return zSign ? (sbits32) 0x80000000 : 0x7FFFFFFF;
112: }
113: if ( roundBits ) STATUS(float_exception_flags) |= float_flag_inexact;
114: return z;
115:
116: }
117:
118: /*----------------------------------------------------------------------------
119: | Takes the 128-bit fixed-point value formed by concatenating `absZ0' and
120: | `absZ1', with binary point between bits 63 and 64 (between the input words),
121: | and returns the properly rounded 64-bit integer corresponding to the input.
122: | If `zSign' is 1, the input is negated before being converted to an integer.
123: | Ordinarily, the fixed-point input is simply rounded to an integer, with
124: | the inexact exception raised if the input cannot be represented exactly as
125: | an integer. However, if the fixed-point input is too large, the invalid
126: | exception is raised and the largest positive or negative integer is
127: | returned.
128: *----------------------------------------------------------------------------*/
129:
130: static int64 roundAndPackInt64( flag zSign, bits64 absZ0, bits64 absZ1 STATUS_PARAM)
131: {
132: int8 roundingMode;
133: flag roundNearestEven, increment;
134: int64 z;
135:
136: roundingMode = STATUS(float_rounding_mode);
137: roundNearestEven = ( roundingMode == float_round_nearest_even );
138: increment = ( (sbits64) absZ1 < 0 );
139: if ( ! roundNearestEven ) {
140: if ( roundingMode == float_round_to_zero ) {
141: increment = 0;
142: }
143: else {
144: if ( zSign ) {
145: increment = ( roundingMode == float_round_down ) && absZ1;
146: }
147: else {
148: increment = ( roundingMode == float_round_up ) && absZ1;
149: }
150: }
151: }
152: if ( increment ) {
153: ++absZ0;
154: if ( absZ0 == 0 ) goto overflow;
155: absZ0 &= ~ ( ( (bits64) ( absZ1<<1 ) == 0 ) & roundNearestEven );
156: }
157: z = absZ0;
158: if ( zSign ) z = - z;
159: if ( z && ( ( z < 0 ) ^ zSign ) ) {
160: overflow:
161: float_raise( float_flag_invalid STATUS_VAR);
162: return
163: zSign ? (sbits64) LIT64( 0x8000000000000000 )
164: : LIT64( 0x7FFFFFFFFFFFFFFF );
165: }
166: if ( absZ1 ) STATUS(float_exception_flags) |= float_flag_inexact;
167: return z;
168:
169: }
170:
171: /*----------------------------------------------------------------------------
172: | Returns the fraction bits of the single-precision floating-point value `a'.
173: *----------------------------------------------------------------------------*/
174:
175: INLINE bits32 extractFloat32Frac( float32 a )
176: {
177:
178: return a & 0x007FFFFF;
179:
180: }
181:
182: /*----------------------------------------------------------------------------
183: | Returns the exponent bits of the single-precision floating-point value `a'.
184: *----------------------------------------------------------------------------*/
185:
186: INLINE int16 extractFloat32Exp( float32 a )
187: {
188:
189: return ( a>>23 ) & 0xFF;
190:
191: }
192:
193: /*----------------------------------------------------------------------------
194: | Returns the sign bit of the single-precision floating-point value `a'.
195: *----------------------------------------------------------------------------*/
196:
197: INLINE flag extractFloat32Sign( float32 a )
198: {
199:
200: return a>>31;
201:
202: }
203:
204: /*----------------------------------------------------------------------------
205: | Normalizes the subnormal single-precision floating-point value represented
206: | by the denormalized significand `aSig'. The normalized exponent and
207: | significand are stored at the locations pointed to by `zExpPtr' and
208: | `zSigPtr', respectively.
209: *----------------------------------------------------------------------------*/
210:
211: static void
212: normalizeFloat32Subnormal( bits32 aSig, int16 *zExpPtr, bits32 *zSigPtr )
213: {
214: int8 shiftCount;
215:
216: shiftCount = countLeadingZeros32( aSig ) - 8;
217: *zSigPtr = aSig<<shiftCount;
218: *zExpPtr = 1 - shiftCount;
219:
220: }
221:
222: /*----------------------------------------------------------------------------
223: | Packs the sign `zSign', exponent `zExp', and significand `zSig' into a
224: | single-precision floating-point value, returning the result. After being
225: | shifted into the proper positions, the three fields are simply added
226: | together to form the result. This means that any integer portion of `zSig'
227: | will be added into the exponent. Since a properly normalized significand
228: | will have an integer portion equal to 1, the `zExp' input should be 1 less
229: | than the desired result exponent whenever `zSig' is a complete, normalized
230: | significand.
231: *----------------------------------------------------------------------------*/
232:
233: INLINE float32 packFloat32( flag zSign, int16 zExp, bits32 zSig )
234: {
235:
236: return ( ( (bits32) zSign )<<31 ) + ( ( (bits32) zExp )<<23 ) + zSig;
237:
238: }
239:
240: /*----------------------------------------------------------------------------
241: | Takes an abstract floating-point value having sign `zSign', exponent `zExp',
242: | and significand `zSig', and returns the proper single-precision floating-
243: | point value corresponding to the abstract input. Ordinarily, the abstract
244: | value is simply rounded and packed into the single-precision format, with
245: | the inexact exception raised if the abstract input cannot be represented
246: | exactly. However, if the abstract value is too large, the overflow and
247: | inexact exceptions are raised and an infinity or maximal finite value is
248: | returned. If the abstract value is too small, the input value is rounded to
249: | a subnormal number, and the underflow and inexact exceptions are raised if
250: | the abstract input cannot be represented exactly as a subnormal single-
251: | precision floating-point number.
252: | The input significand `zSig' has its binary point between bits 30
253: | and 29, which is 7 bits to the left of the usual location. This shifted
254: | significand must be normalized or smaller. If `zSig' is not normalized,
255: | `zExp' must be 0; in that case, the result returned is a subnormal number,
256: | and it must not require rounding. In the usual case that `zSig' is
257: | normalized, `zExp' must be 1 less than the ``true'' floating-point exponent.
258: | The handling of underflow and overflow follows the IEC/IEEE Standard for
259: | Binary Floating-Point Arithmetic.
260: *----------------------------------------------------------------------------*/
261:
262: static float32 roundAndPackFloat32( flag zSign, int16 zExp, bits32 zSig STATUS_PARAM)
263: {
264: int8 roundingMode;
265: flag roundNearestEven;
266: int8 roundIncrement, roundBits;
267: flag isTiny;
268:
269: roundingMode = STATUS(float_rounding_mode);
270: roundNearestEven = ( roundingMode == float_round_nearest_even );
271: roundIncrement = 0x40;
272: if ( ! roundNearestEven ) {
273: if ( roundingMode == float_round_to_zero ) {
274: roundIncrement = 0;
275: }
276: else {
277: roundIncrement = 0x7F;
278: if ( zSign ) {
279: if ( roundingMode == float_round_up ) roundIncrement = 0;
280: }
281: else {
282: if ( roundingMode == float_round_down ) roundIncrement = 0;
283: }
284: }
285: }
286: roundBits = zSig & 0x7F;
287: if ( 0xFD <= (bits16) zExp ) {
288: if ( ( 0xFD < zExp )
289: || ( ( zExp == 0xFD )
290: && ( (sbits32) ( zSig + roundIncrement ) < 0 ) )
291: ) {
292: float_raise( float_flag_overflow | float_flag_inexact STATUS_VAR);
293: return packFloat32( zSign, 0xFF, 0 ) - ( roundIncrement == 0 );
294: }
295: if ( zExp < 0 ) {
296: isTiny =
297: ( STATUS(float_detect_tininess) == float_tininess_before_rounding )
298: || ( zExp < -1 )
299: || ( zSig + roundIncrement < 0x80000000 );
300: shift32RightJamming( zSig, - zExp, &zSig );
301: zExp = 0;
302: roundBits = zSig & 0x7F;
303: if ( isTiny && roundBits ) float_raise( float_flag_underflow STATUS_VAR);
304: }
305: }
306: if ( roundBits ) STATUS(float_exception_flags) |= float_flag_inexact;
307: zSig = ( zSig + roundIncrement )>>7;
308: zSig &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven );
309: if ( zSig == 0 ) zExp = 0;
310: return packFloat32( zSign, zExp, zSig );
311:
312: }
313:
314: /*----------------------------------------------------------------------------
315: | Takes an abstract floating-point value having sign `zSign', exponent `zExp',
316: | and significand `zSig', and returns the proper single-precision floating-
317: | point value corresponding to the abstract input. This routine is just like
318: | `roundAndPackFloat32' except that `zSig' does not have to be normalized.
319: | Bit 31 of `zSig' must be zero, and `zExp' must be 1 less than the ``true''
320: | floating-point exponent.
321: *----------------------------------------------------------------------------*/
322:
323: static float32
324: normalizeRoundAndPackFloat32( flag zSign, int16 zExp, bits32 zSig STATUS_PARAM)
325: {
326: int8 shiftCount;
327:
328: shiftCount = countLeadingZeros32( zSig ) - 1;
329: return roundAndPackFloat32( zSign, zExp - shiftCount, zSig<<shiftCount STATUS_VAR);
330:
331: }
332:
333: /*----------------------------------------------------------------------------
334: | Returns the fraction bits of the double-precision floating-point value `a'.
335: *----------------------------------------------------------------------------*/
336:
337: INLINE bits64 extractFloat64Frac( float64 a )
338: {
339:
340: return a & LIT64( 0x000FFFFFFFFFFFFF );
341:
342: }
343:
344: /*----------------------------------------------------------------------------
345: | Returns the exponent bits of the double-precision floating-point value `a'.
346: *----------------------------------------------------------------------------*/
347:
348: INLINE int16 extractFloat64Exp( float64 a )
349: {
350:
351: return ( a>>52 ) & 0x7FF;
352:
353: }
354:
355: /*----------------------------------------------------------------------------
356: | Returns the sign bit of the double-precision floating-point value `a'.
357: *----------------------------------------------------------------------------*/
358:
359: INLINE flag extractFloat64Sign( float64 a )
360: {
361:
362: return a>>63;
363:
364: }
365:
366: /*----------------------------------------------------------------------------
367: | Normalizes the subnormal double-precision floating-point value represented
368: | by the denormalized significand `aSig'. The normalized exponent and
369: | significand are stored at the locations pointed to by `zExpPtr' and
370: | `zSigPtr', respectively.
371: *----------------------------------------------------------------------------*/
372:
373: static void
374: normalizeFloat64Subnormal( bits64 aSig, int16 *zExpPtr, bits64 *zSigPtr )
375: {
376: int8 shiftCount;
377:
378: shiftCount = countLeadingZeros64( aSig ) - 11;
379: *zSigPtr = aSig<<shiftCount;
380: *zExpPtr = 1 - shiftCount;
381:
382: }
383:
384: /*----------------------------------------------------------------------------
385: | Packs the sign `zSign', exponent `zExp', and significand `zSig' into a
386: | double-precision floating-point value, returning the result. After being
387: | shifted into the proper positions, the three fields are simply added
388: | together to form the result. This means that any integer portion of `zSig'
389: | will be added into the exponent. Since a properly normalized significand
390: | will have an integer portion equal to 1, the `zExp' input should be 1 less
391: | than the desired result exponent whenever `zSig' is a complete, normalized
392: | significand.
393: *----------------------------------------------------------------------------*/
394:
395: INLINE float64 packFloat64( flag zSign, int16 zExp, bits64 zSig )
396: {
397:
398: return ( ( (bits64) zSign )<<63 ) + ( ( (bits64) zExp )<<52 ) + zSig;
399:
400: }
401:
402: /*----------------------------------------------------------------------------
403: | Takes an abstract floating-point value having sign `zSign', exponent `zExp',
404: | and significand `zSig', and returns the proper double-precision floating-
405: | point value corresponding to the abstract input. Ordinarily, the abstract
406: | value is simply rounded and packed into the double-precision format, with
407: | the inexact exception raised if the abstract input cannot be represented
408: | exactly. However, if the abstract value is too large, the overflow and
409: | inexact exceptions are raised and an infinity or maximal finite value is
410: | returned. If the abstract value is too small, the input value is rounded
411: | to a subnormal number, and the underflow and inexact exceptions are raised
412: | if the abstract input cannot be represented exactly as a subnormal double-
413: | precision floating-point number.
414: | The input significand `zSig' has its binary point between bits 62
415: | and 61, which is 10 bits to the left of the usual location. This shifted
416: | significand must be normalized or smaller. If `zSig' is not normalized,
417: | `zExp' must be 0; in that case, the result returned is a subnormal number,
418: | and it must not require rounding. In the usual case that `zSig' is
419: | normalized, `zExp' must be 1 less than the ``true'' floating-point exponent.
420: | The handling of underflow and overflow follows the IEC/IEEE Standard for
421: | Binary Floating-Point Arithmetic.
422: *----------------------------------------------------------------------------*/
423:
424: static float64 roundAndPackFloat64( flag zSign, int16 zExp, bits64 zSig STATUS_PARAM)
425: {
426: int8 roundingMode;
427: flag roundNearestEven;
428: int16 roundIncrement, roundBits;
429: flag isTiny;
430:
431: roundingMode = STATUS(float_rounding_mode);
432: roundNearestEven = ( roundingMode == float_round_nearest_even );
433: roundIncrement = 0x200;
434: if ( ! roundNearestEven ) {
435: if ( roundingMode == float_round_to_zero ) {
436: roundIncrement = 0;
437: }
438: else {
439: roundIncrement = 0x3FF;
440: if ( zSign ) {
441: if ( roundingMode == float_round_up ) roundIncrement = 0;
442: }
443: else {
444: if ( roundingMode == float_round_down ) roundIncrement = 0;
445: }
446: }
447: }
448: roundBits = zSig & 0x3FF;
449: if ( 0x7FD <= (bits16) zExp ) {
450: if ( ( 0x7FD < zExp )
451: || ( ( zExp == 0x7FD )
452: && ( (sbits64) ( zSig + roundIncrement ) < 0 ) )
453: ) {
454: float_raise( float_flag_overflow | float_flag_inexact STATUS_VAR);
455: return packFloat64( zSign, 0x7FF, 0 ) - ( roundIncrement == 0 );
456: }
457: if ( zExp < 0 ) {
458: isTiny =
459: ( STATUS(float_detect_tininess) == float_tininess_before_rounding )
460: || ( zExp < -1 )
461: || ( zSig + roundIncrement < LIT64( 0x8000000000000000 ) );
462: shift64RightJamming( zSig, - zExp, &zSig );
463: zExp = 0;
464: roundBits = zSig & 0x3FF;
465: if ( isTiny && roundBits ) float_raise( float_flag_underflow STATUS_VAR);
466: }
467: }
468: if ( roundBits ) STATUS(float_exception_flags) |= float_flag_inexact;
469: zSig = ( zSig + roundIncrement )>>10;
470: zSig &= ~ ( ( ( roundBits ^ 0x200 ) == 0 ) & roundNearestEven );
471: if ( zSig == 0 ) zExp = 0;
472: return packFloat64( zSign, zExp, zSig );
473:
474: }
475:
476: /*----------------------------------------------------------------------------
477: | Takes an abstract floating-point value having sign `zSign', exponent `zExp',
478: | and significand `zSig', and returns the proper double-precision floating-
479: | point value corresponding to the abstract input. This routine is just like
480: | `roundAndPackFloat64' except that `zSig' does not have to be normalized.
481: | Bit 63 of `zSig' must be zero, and `zExp' must be 1 less than the ``true''
482: | floating-point exponent.
483: *----------------------------------------------------------------------------*/
484:
485: static float64
486: normalizeRoundAndPackFloat64( flag zSign, int16 zExp, bits64 zSig STATUS_PARAM)
487: {
488: int8 shiftCount;
489:
490: shiftCount = countLeadingZeros64( zSig ) - 1;
491: return roundAndPackFloat64( zSign, zExp - shiftCount, zSig<<shiftCount STATUS_VAR);
492:
493: }
494:
495: #ifdef FLOATX80
496:
497: /*----------------------------------------------------------------------------
498: | Returns the fraction bits of the extended double-precision floating-point
499: | value `a'.
500: *----------------------------------------------------------------------------*/
501:
502: INLINE bits64 extractFloatx80Frac( floatx80 a )
503: {
504:
505: return a.low;
506:
507: }
508:
509: /*----------------------------------------------------------------------------
510: | Returns the exponent bits of the extended double-precision floating-point
511: | value `a'.
512: *----------------------------------------------------------------------------*/
513:
514: INLINE int32 extractFloatx80Exp( floatx80 a )
515: {
516:
517: return a.high & 0x7FFF;
518:
519: }
520:
521: /*----------------------------------------------------------------------------
522: | Returns the sign bit of the extended double-precision floating-point value
523: | `a'.
524: *----------------------------------------------------------------------------*/
525:
526: INLINE flag extractFloatx80Sign( floatx80 a )
527: {
528:
529: return a.high>>15;
530:
531: }
532:
533: /*----------------------------------------------------------------------------
534: | Normalizes the subnormal extended double-precision floating-point value
535: | represented by the denormalized significand `aSig'. The normalized exponent
536: | and significand are stored at the locations pointed to by `zExpPtr' and
537: | `zSigPtr', respectively.
538: *----------------------------------------------------------------------------*/
539:
540: static void
541: normalizeFloatx80Subnormal( bits64 aSig, int32 *zExpPtr, bits64 *zSigPtr )
542: {
543: int8 shiftCount;
544:
545: shiftCount = countLeadingZeros64( aSig );
546: *zSigPtr = aSig<<shiftCount;
547: *zExpPtr = 1 - shiftCount;
548:
549: }
550:
551: /*----------------------------------------------------------------------------
552: | Packs the sign `zSign', exponent `zExp', and significand `zSig' into an
553: | extended double-precision floating-point value, returning the result.
554: *----------------------------------------------------------------------------*/
555:
556: INLINE floatx80 packFloatx80( flag zSign, int32 zExp, bits64 zSig )
557: {
558: floatx80 z;
559:
560: z.low = zSig;
561: z.high = ( ( (bits16) zSign )<<15 ) + zExp;
562: return z;
563:
564: }
565:
566: /*----------------------------------------------------------------------------
567: | Takes an abstract floating-point value having sign `zSign', exponent `zExp',
568: | and extended significand formed by the concatenation of `zSig0' and `zSig1',
569: | and returns the proper extended double-precision floating-point value
570: | corresponding to the abstract input. Ordinarily, the abstract value is
571: | rounded and packed into the extended double-precision format, with the
572: | inexact exception raised if the abstract input cannot be represented
573: | exactly. However, if the abstract value is too large, the overflow and
574: | inexact exceptions are raised and an infinity or maximal finite value is
575: | returned. If the abstract value is too small, the input value is rounded to
576: | a subnormal number, and the underflow and inexact exceptions are raised if
577: | the abstract input cannot be represented exactly as a subnormal extended
578: | double-precision floating-point number.
579: | If `roundingPrecision' is 32 or 64, the result is rounded to the same
580: | number of bits as single or double precision, respectively. Otherwise, the
581: | result is rounded to the full precision of the extended double-precision
582: | format.
583: | The input significand must be normalized or smaller. If the input
584: | significand is not normalized, `zExp' must be 0; in that case, the result
585: | returned is a subnormal number, and it must not require rounding. The
586: | handling of underflow and overflow follows the IEC/IEEE Standard for Binary
587: | Floating-Point Arithmetic.
588: *----------------------------------------------------------------------------*/
589:
590: static floatx80
591: roundAndPackFloatx80(
592: int8 roundingPrecision, flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1
593: STATUS_PARAM)
594: {
595: int8 roundingMode;
596: flag roundNearestEven, increment, isTiny;
597: int64 roundIncrement, roundMask, roundBits;
598:
599: roundingMode = STATUS(float_rounding_mode);
600: roundNearestEven = ( roundingMode == float_round_nearest_even );
601: if ( roundingPrecision == 80 ) goto precision80;
602: if ( roundingPrecision == 64 ) {
603: roundIncrement = LIT64( 0x0000000000000400 );
604: roundMask = LIT64( 0x00000000000007FF );
605: }
606: else if ( roundingPrecision == 32 ) {
607: roundIncrement = LIT64( 0x0000008000000000 );
608: roundMask = LIT64( 0x000000FFFFFFFFFF );
609: }
610: else {
611: goto precision80;
612: }
613: zSig0 |= ( zSig1 != 0 );
614: if ( ! roundNearestEven ) {
615: if ( roundingMode == float_round_to_zero ) {
616: roundIncrement = 0;
617: }
618: else {
619: roundIncrement = roundMask;
620: if ( zSign ) {
621: if ( roundingMode == float_round_up ) roundIncrement = 0;
622: }
623: else {
624: if ( roundingMode == float_round_down ) roundIncrement = 0;
625: }
626: }
627: }
628: roundBits = zSig0 & roundMask;
629: if ( 0x7FFD <= (bits32) ( zExp - 1 ) ) {
630: if ( ( 0x7FFE < zExp )
631: || ( ( zExp == 0x7FFE ) && ( zSig0 + roundIncrement < zSig0 ) )
632: ) {
633: goto overflow;
634: }
635: if ( zExp <= 0 ) {
636: isTiny =
637: ( STATUS(float_detect_tininess) == float_tininess_before_rounding )
638: || ( zExp < 0 )
639: || ( zSig0 <= zSig0 + roundIncrement );
640: shift64RightJamming( zSig0, 1 - zExp, &zSig0 );
641: zExp = 0;
642: roundBits = zSig0 & roundMask;
643: if ( isTiny && roundBits ) float_raise( float_flag_underflow STATUS_VAR);
644: if ( roundBits ) STATUS(float_exception_flags) |= float_flag_inexact;
645: zSig0 += roundIncrement;
646: if ( (sbits64) zSig0 < 0 ) zExp = 1;
647: roundIncrement = roundMask + 1;
648: if ( roundNearestEven && ( roundBits<<1 == roundIncrement ) ) {
649: roundMask |= roundIncrement;
650: }
651: zSig0 &= ~ roundMask;
652: return packFloatx80( zSign, zExp, zSig0 );
653: }
654: }
655: if ( roundBits ) STATUS(float_exception_flags) |= float_flag_inexact;
656: zSig0 += roundIncrement;
657: if ( zSig0 < roundIncrement ) {
658: ++zExp;
659: zSig0 = LIT64( 0x8000000000000000 );
660: }
661: roundIncrement = roundMask + 1;
662: if ( roundNearestEven && ( roundBits<<1 == roundIncrement ) ) {
663: roundMask |= roundIncrement;
664: }
665: zSig0 &= ~ roundMask;
666: if ( zSig0 == 0 ) zExp = 0;
667: return packFloatx80( zSign, zExp, zSig0 );
668: precision80:
669: increment = ( (sbits64) zSig1 < 0 );
670: if ( ! roundNearestEven ) {
671: if ( roundingMode == float_round_to_zero ) {
672: increment = 0;
673: }
674: else {
675: if ( zSign ) {
676: increment = ( roundingMode == float_round_down ) && zSig1;
677: }
678: else {
679: increment = ( roundingMode == float_round_up ) && zSig1;
680: }
681: }
682: }
683: if ( 0x7FFD <= (bits32) ( zExp - 1 ) ) {
684: if ( ( 0x7FFE < zExp )
685: || ( ( zExp == 0x7FFE )
686: && ( zSig0 == LIT64( 0xFFFFFFFFFFFFFFFF ) )
687: && increment
688: )
689: ) {
690: roundMask = 0;
691: overflow:
692: float_raise( float_flag_overflow | float_flag_inexact STATUS_VAR);
693: if ( ( roundingMode == float_round_to_zero )
694: || ( zSign && ( roundingMode == float_round_up ) )
695: || ( ! zSign && ( roundingMode == float_round_down ) )
696: ) {
697: return packFloatx80( zSign, 0x7FFE, ~ roundMask );
698: }
699: return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
700: }
701: if ( zExp <= 0 ) {
702: isTiny =
703: ( STATUS(float_detect_tininess) == float_tininess_before_rounding )
704: || ( zExp < 0 )
705: || ! increment
706: || ( zSig0 < LIT64( 0xFFFFFFFFFFFFFFFF ) );
707: shift64ExtraRightJamming( zSig0, zSig1, 1 - zExp, &zSig0, &zSig1 );
708: zExp = 0;
709: if ( isTiny && zSig1 ) float_raise( float_flag_underflow STATUS_VAR);
710: if ( zSig1 ) STATUS(float_exception_flags) |= float_flag_inexact;
711: if ( roundNearestEven ) {
712: increment = ( (sbits64) zSig1 < 0 );
713: }
714: else {
715: if ( zSign ) {
716: increment = ( roundingMode == float_round_down ) && zSig1;
717: }
718: else {
719: increment = ( roundingMode == float_round_up ) && zSig1;
720: }
721: }
722: if ( increment ) {
723: ++zSig0;
724: zSig0 &=
725: ~ ( ( (bits64) ( zSig1<<1 ) == 0 ) & roundNearestEven );
726: if ( (sbits64) zSig0 < 0 ) zExp = 1;
727: }
728: return packFloatx80( zSign, zExp, zSig0 );
729: }
730: }
731: if ( zSig1 ) STATUS(float_exception_flags) |= float_flag_inexact;
732: if ( increment ) {
733: ++zSig0;
734: if ( zSig0 == 0 ) {
735: ++zExp;
736: zSig0 = LIT64( 0x8000000000000000 );
737: }
738: else {
739: zSig0 &= ~ ( ( (bits64) ( zSig1<<1 ) == 0 ) & roundNearestEven );
740: }
741: }
742: else {
743: if ( zSig0 == 0 ) zExp = 0;
744: }
745: return packFloatx80( zSign, zExp, zSig0 );
746:
747: }
748:
749: /*----------------------------------------------------------------------------
750: | Takes an abstract floating-point value having sign `zSign', exponent
751: | `zExp', and significand formed by the concatenation of `zSig0' and `zSig1',
752: | and returns the proper extended double-precision floating-point value
753: | corresponding to the abstract input. This routine is just like
754: | `roundAndPackFloatx80' except that the input significand does not have to be
755: | normalized.
756: *----------------------------------------------------------------------------*/
757:
758: static floatx80
759: normalizeRoundAndPackFloatx80(
760: int8 roundingPrecision, flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1
761: STATUS_PARAM)
762: {
763: int8 shiftCount;
764:
765: if ( zSig0 == 0 ) {
766: zSig0 = zSig1;
767: zSig1 = 0;
768: zExp -= 64;
769: }
770: shiftCount = countLeadingZeros64( zSig0 );
771: shortShift128Left( zSig0, zSig1, shiftCount, &zSig0, &zSig1 );
772: zExp -= shiftCount;
773: return
774: roundAndPackFloatx80( roundingPrecision, zSign, zExp, zSig0, zSig1 STATUS_VAR);
775:
776: }
777:
778: #endif
779:
780: #ifdef FLOAT128
781:
782: /*----------------------------------------------------------------------------
783: | Returns the least-significant 64 fraction bits of the quadruple-precision
784: | floating-point value `a'.
785: *----------------------------------------------------------------------------*/
786:
787: INLINE bits64 extractFloat128Frac1( float128 a )
788: {
789:
790: return a.low;
791:
792: }
793:
794: /*----------------------------------------------------------------------------
795: | Returns the most-significant 48 fraction bits of the quadruple-precision
796: | floating-point value `a'.
797: *----------------------------------------------------------------------------*/
798:
799: INLINE bits64 extractFloat128Frac0( float128 a )
800: {
801:
802: return a.high & LIT64( 0x0000FFFFFFFFFFFF );
803:
804: }
805:
806: /*----------------------------------------------------------------------------
807: | Returns the exponent bits of the quadruple-precision floating-point value
808: | `a'.
809: *----------------------------------------------------------------------------*/
810:
811: INLINE int32 extractFloat128Exp( float128 a )
812: {
813:
814: return ( a.high>>48 ) & 0x7FFF;
815:
816: }
817:
818: /*----------------------------------------------------------------------------
819: | Returns the sign bit of the quadruple-precision floating-point value `a'.
820: *----------------------------------------------------------------------------*/
821:
822: INLINE flag extractFloat128Sign( float128 a )
823: {
824:
825: return a.high>>63;
826:
827: }
828:
829: /*----------------------------------------------------------------------------
830: | Normalizes the subnormal quadruple-precision floating-point value
831: | represented by the denormalized significand formed by the concatenation of
832: | `aSig0' and `aSig1'. The normalized exponent is stored at the location
833: | pointed to by `zExpPtr'. The most significant 49 bits of the normalized
834: | significand are stored at the location pointed to by `zSig0Ptr', and the
835: | least significant 64 bits of the normalized significand are stored at the
836: | location pointed to by `zSig1Ptr'.
837: *----------------------------------------------------------------------------*/
838:
839: static void
840: normalizeFloat128Subnormal(
841: bits64 aSig0,
842: bits64 aSig1,
843: int32 *zExpPtr,
844: bits64 *zSig0Ptr,
845: bits64 *zSig1Ptr
846: )
847: {
848: int8 shiftCount;
849:
850: if ( aSig0 == 0 ) {
851: shiftCount = countLeadingZeros64( aSig1 ) - 15;
852: if ( shiftCount < 0 ) {
853: *zSig0Ptr = aSig1>>( - shiftCount );
854: *zSig1Ptr = aSig1<<( shiftCount & 63 );
855: }
856: else {
857: *zSig0Ptr = aSig1<<shiftCount;
858: *zSig1Ptr = 0;
859: }
860: *zExpPtr = - shiftCount - 63;
861: }
862: else {
863: shiftCount = countLeadingZeros64( aSig0 ) - 15;
864: shortShift128Left( aSig0, aSig1, shiftCount, zSig0Ptr, zSig1Ptr );
865: *zExpPtr = 1 - shiftCount;
866: }
867:
868: }
869:
870: /*----------------------------------------------------------------------------
871: | Packs the sign `zSign', the exponent `zExp', and the significand formed
872: | by the concatenation of `zSig0' and `zSig1' into a quadruple-precision
873: | floating-point value, returning the result. After being shifted into the
874: | proper positions, the three fields `zSign', `zExp', and `zSig0' are simply
875: | added together to form the most significant 32 bits of the result. This
876: | means that any integer portion of `zSig0' will be added into the exponent.
877: | Since a properly normalized significand will have an integer portion equal
878: | to 1, the `zExp' input should be 1 less than the desired result exponent
879: | whenever `zSig0' and `zSig1' concatenated form a complete, normalized
880: | significand.
881: *----------------------------------------------------------------------------*/
882:
883: INLINE float128
884: packFloat128( flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1 )
885: {
886: float128 z;
887:
888: z.low = zSig1;
889: z.high = ( ( (bits64) zSign )<<63 ) + ( ( (bits64) zExp )<<48 ) + zSig0;
890: return z;
891:
892: }
893:
894: /*----------------------------------------------------------------------------
895: | Takes an abstract floating-point value having sign `zSign', exponent `zExp',
896: | and extended significand formed by the concatenation of `zSig0', `zSig1',
897: | and `zSig2', and returns the proper quadruple-precision floating-point value
898: | corresponding to the abstract input. Ordinarily, the abstract value is
899: | simply rounded and packed into the quadruple-precision format, with the
900: | inexact exception raised if the abstract input cannot be represented
901: | exactly. However, if the abstract value is too large, the overflow and
902: | inexact exceptions are raised and an infinity or maximal finite value is
903: | returned. If the abstract value is too small, the input value is rounded to
904: | a subnormal number, and the underflow and inexact exceptions are raised if
905: | the abstract input cannot be represented exactly as a subnormal quadruple-
906: | precision floating-point number.
907: | The input significand must be normalized or smaller. If the input
908: | significand is not normalized, `zExp' must be 0; in that case, the result
909: | returned is a subnormal number, and it must not require rounding. In the
910: | usual case that the input significand is normalized, `zExp' must be 1 less
911: | than the ``true'' floating-point exponent. The handling of underflow and
912: | overflow follows the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
913: *----------------------------------------------------------------------------*/
914:
915: static float128
916: roundAndPackFloat128(
917: flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1, bits64 zSig2 STATUS_PARAM)
918: {
919: int8 roundingMode;
920: flag roundNearestEven, increment, isTiny;
921:
922: roundingMode = STATUS(float_rounding_mode);
923: roundNearestEven = ( roundingMode == float_round_nearest_even );
924: increment = ( (sbits64) zSig2 < 0 );
925: if ( ! roundNearestEven ) {
926: if ( roundingMode == float_round_to_zero ) {
927: increment = 0;
928: }
929: else {
930: if ( zSign ) {
931: increment = ( roundingMode == float_round_down ) && zSig2;
932: }
933: else {
934: increment = ( roundingMode == float_round_up ) && zSig2;
935: }
936: }
937: }
938: if ( 0x7FFD <= (bits32) zExp ) {
939: if ( ( 0x7FFD < zExp )
940: || ( ( zExp == 0x7FFD )
941: && eq128(
942: LIT64( 0x0001FFFFFFFFFFFF ),
943: LIT64( 0xFFFFFFFFFFFFFFFF ),
944: zSig0,
945: zSig1
946: )
947: && increment
948: )
949: ) {
950: float_raise( float_flag_overflow | float_flag_inexact STATUS_VAR);
951: if ( ( roundingMode == float_round_to_zero )
952: || ( zSign && ( roundingMode == float_round_up ) )
953: || ( ! zSign && ( roundingMode == float_round_down ) )
954: ) {
955: return
956: packFloat128(
957: zSign,
958: 0x7FFE,
959: LIT64( 0x0000FFFFFFFFFFFF ),
960: LIT64( 0xFFFFFFFFFFFFFFFF )
961: );
962: }
963: return packFloat128( zSign, 0x7FFF, 0, 0 );
964: }
965: if ( zExp < 0 ) {
966: isTiny =
967: ( STATUS(float_detect_tininess) == float_tininess_before_rounding )
968: || ( zExp < -1 )
969: || ! increment
970: || lt128(
971: zSig0,
972: zSig1,
973: LIT64( 0x0001FFFFFFFFFFFF ),
974: LIT64( 0xFFFFFFFFFFFFFFFF )
975: );
976: shift128ExtraRightJamming(
977: zSig0, zSig1, zSig2, - zExp, &zSig0, &zSig1, &zSig2 );
978: zExp = 0;
979: if ( isTiny && zSig2 ) float_raise( float_flag_underflow STATUS_VAR);
980: if ( roundNearestEven ) {
981: increment = ( (sbits64) zSig2 < 0 );
982: }
983: else {
984: if ( zSign ) {
985: increment = ( roundingMode == float_round_down ) && zSig2;
986: }
987: else {
988: increment = ( roundingMode == float_round_up ) && zSig2;
989: }
990: }
991: }
992: }
993: if ( zSig2 ) STATUS(float_exception_flags) |= float_flag_inexact;
994: if ( increment ) {
995: add128( zSig0, zSig1, 0, 1, &zSig0, &zSig1 );
996: zSig1 &= ~ ( ( zSig2 + zSig2 == 0 ) & roundNearestEven );
997: }
998: else {
999: if ( ( zSig0 | zSig1 ) == 0 ) zExp = 0;
1000: }
1001: return packFloat128( zSign, zExp, zSig0, zSig1 );
1002:
1003: }
1004:
1005: /*----------------------------------------------------------------------------
1006: | Takes an abstract floating-point value having sign `zSign', exponent `zExp',
1007: | and significand formed by the concatenation of `zSig0' and `zSig1', and
1008: | returns the proper quadruple-precision floating-point value corresponding
1009: | to the abstract input. This routine is just like `roundAndPackFloat128'
1010: | except that the input significand has fewer bits and does not have to be
1011: | normalized. In all cases, `zExp' must be 1 less than the ``true'' floating-
1012: | point exponent.
1013: *----------------------------------------------------------------------------*/
1014:
1015: static float128
1016: normalizeRoundAndPackFloat128(
1017: flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1 STATUS_PARAM)
1018: {
1019: int8 shiftCount;
1020: bits64 zSig2;
1021:
1022: if ( zSig0 == 0 ) {
1023: zSig0 = zSig1;
1024: zSig1 = 0;
1025: zExp -= 64;
1026: }
1027: shiftCount = countLeadingZeros64( zSig0 ) - 15;
1028: if ( 0 <= shiftCount ) {
1029: zSig2 = 0;
1030: shortShift128Left( zSig0, zSig1, shiftCount, &zSig0, &zSig1 );
1031: }
1032: else {
1033: shift128ExtraRightJamming(
1034: zSig0, zSig1, 0, - shiftCount, &zSig0, &zSig1, &zSig2 );
1035: }
1036: zExp -= shiftCount;
1037: return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 STATUS_VAR);
1038:
1039: }
1040:
1041: #endif
1042:
1043: /*----------------------------------------------------------------------------
1044: | Returns the result of converting the 32-bit two's complement integer `a'
1045: | to the single-precision floating-point format. The conversion is performed
1046: | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
1047: *----------------------------------------------------------------------------*/
1048:
1049: float32 int32_to_float32( int32 a STATUS_PARAM )
1050: {
1051: flag zSign;
1052:
1053: if ( a == 0 ) return 0;
1054: if ( a == (sbits32) 0x80000000 ) return packFloat32( 1, 0x9E, 0 );
1055: zSign = ( a < 0 );
1056: return normalizeRoundAndPackFloat32( zSign, 0x9C, zSign ? - a : a STATUS_VAR );
1057:
1058: }
1059:
1060: /*----------------------------------------------------------------------------
1061: | Returns the result of converting the 32-bit two's complement integer `a'
1062: | to the double-precision floating-point format. The conversion is performed
1063: | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
1064: *----------------------------------------------------------------------------*/
1065:
1066: float64 int32_to_float64( int32 a STATUS_PARAM )
1067: {
1068: flag zSign;
1069: uint32 absA;
1070: int8 shiftCount;
1071: bits64 zSig;
1072:
1073: if ( a == 0 ) return 0;
1074: zSign = ( a < 0 );
1075: absA = zSign ? - a : a;
1076: shiftCount = countLeadingZeros32( absA ) + 21;
1077: zSig = absA;
1078: return packFloat64( zSign, 0x432 - shiftCount, zSig<<shiftCount );
1079:
1080: }
1081:
1082: #ifdef FLOATX80
1083:
1084: /*----------------------------------------------------------------------------
1085: | Returns the result of converting the 32-bit two's complement integer `a'
1086: | to the extended double-precision floating-point format. The conversion
1087: | is performed according to the IEC/IEEE Standard for Binary Floating-Point
1088: | Arithmetic.
1089: *----------------------------------------------------------------------------*/
1090:
1091: floatx80 int32_to_floatx80( int32 a STATUS_PARAM )
1092: {
1093: flag zSign;
1094: uint32 absA;
1095: int8 shiftCount;
1096: bits64 zSig;
1097:
1098: if ( a == 0 ) return packFloatx80( 0, 0, 0 );
1099: zSign = ( a < 0 );
1100: absA = zSign ? - a : a;
1101: shiftCount = countLeadingZeros32( absA ) + 32;
1102: zSig = absA;
1103: return packFloatx80( zSign, 0x403E - shiftCount, zSig<<shiftCount );
1104:
1105: }
1106:
1107: #endif
1108:
1109: #ifdef FLOAT128
1110:
1111: /*----------------------------------------------------------------------------
1112: | Returns the result of converting the 32-bit two's complement integer `a' to
1113: | the quadruple-precision floating-point format. The conversion is performed
1114: | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
1115: *----------------------------------------------------------------------------*/
1116:
1117: float128 int32_to_float128( int32 a STATUS_PARAM )
1118: {
1119: flag zSign;
1120: uint32 absA;
1121: int8 shiftCount;
1122: bits64 zSig0;
1123:
1124: if ( a == 0 ) return packFloat128( 0, 0, 0, 0 );
1125: zSign = ( a < 0 );
1126: absA = zSign ? - a : a;
1127: shiftCount = countLeadingZeros32( absA ) + 17;
1128: zSig0 = absA;
1129: return packFloat128( zSign, 0x402E - shiftCount, zSig0<<shiftCount, 0 );
1130:
1131: }
1132:
1133: #endif
1134:
1135: /*----------------------------------------------------------------------------
1136: | Returns the result of converting the 64-bit two's complement integer `a'
1137: | to the single-precision floating-point format. The conversion is performed
1138: | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
1139: *----------------------------------------------------------------------------*/
1140:
1141: float32 int64_to_float32( int64 a STATUS_PARAM )
1142: {
1143: flag zSign;
1144: uint64 absA;
1145: int8 shiftCount;
1146:
1147: if ( a == 0 ) return 0;
1148: zSign = ( a < 0 );
1149: absA = zSign ? - a : a;
1150: shiftCount = countLeadingZeros64( absA ) - 40;
1151: if ( 0 <= shiftCount ) {
1152: return packFloat32( zSign, 0x95 - shiftCount, absA<<shiftCount );
1153: }
1154: else {
1155: shiftCount += 7;
1156: if ( shiftCount < 0 ) {
1157: shift64RightJamming( absA, - shiftCount, &absA );
1158: }
1159: else {
1160: absA <<= shiftCount;
1161: }
1162: return roundAndPackFloat32( zSign, 0x9C - shiftCount, absA STATUS_VAR );
1163: }
1164:
1165: }
1166:
1167: /*----------------------------------------------------------------------------
1168: | Returns the result of converting the 64-bit two's complement integer `a'
1169: | to the double-precision floating-point format. The conversion is performed
1170: | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
1171: *----------------------------------------------------------------------------*/
1172:
1173: float64 int64_to_float64( int64 a STATUS_PARAM )
1174: {
1175: flag zSign;
1176:
1177: if ( a == 0 ) return 0;
1178: if ( a == (sbits64) LIT64( 0x8000000000000000 ) ) {
1179: return packFloat64( 1, 0x43E, 0 );
1180: }
1181: zSign = ( a < 0 );
1182: return normalizeRoundAndPackFloat64( zSign, 0x43C, zSign ? - a : a STATUS_VAR );
1183:
1184: }
1185:
1186: #ifdef FLOATX80
1187:
1188: /*----------------------------------------------------------------------------
1189: | Returns the result of converting the 64-bit two's complement integer `a'
1190: | to the extended double-precision floating-point format. The conversion
1191: | is performed according to the IEC/IEEE Standard for Binary Floating-Point
1192: | Arithmetic.
1193: *----------------------------------------------------------------------------*/
1194:
1195: floatx80 int64_to_floatx80( int64 a STATUS_PARAM )
1196: {
1197: flag zSign;
1198: uint64 absA;
1199: int8 shiftCount;
1200:
1201: if ( a == 0 ) return packFloatx80( 0, 0, 0 );
1202: zSign = ( a < 0 );
1203: absA = zSign ? - a : a;
1204: shiftCount = countLeadingZeros64( absA );
1205: return packFloatx80( zSign, 0x403E - shiftCount, absA<<shiftCount );
1206:
1207: }
1208:
1209: #endif
1210:
1211: #ifdef FLOAT128
1212:
1213: /*----------------------------------------------------------------------------
1214: | Returns the result of converting the 64-bit two's complement integer `a' to
1215: | the quadruple-precision floating-point format. The conversion is performed
1216: | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
1217: *----------------------------------------------------------------------------*/
1218:
1219: float128 int64_to_float128( int64 a STATUS_PARAM )
1220: {
1221: flag zSign;
1222: uint64 absA;
1223: int8 shiftCount;
1224: int32 zExp;
1225: bits64 zSig0, zSig1;
1226:
1227: if ( a == 0 ) return packFloat128( 0, 0, 0, 0 );
1228: zSign = ( a < 0 );
1229: absA = zSign ? - a : a;
1230: shiftCount = countLeadingZeros64( absA ) + 49;
1231: zExp = 0x406E - shiftCount;
1232: if ( 64 <= shiftCount ) {
1233: zSig1 = 0;
1234: zSig0 = absA;
1235: shiftCount -= 64;
1236: }
1237: else {
1238: zSig1 = absA;
1239: zSig0 = 0;
1240: }
1241: shortShift128Left( zSig0, zSig1, shiftCount, &zSig0, &zSig1 );
1242: return packFloat128( zSign, zExp, zSig0, zSig1 );
1243:
1244: }
1245:
1246: #endif
1247:
1248: /*----------------------------------------------------------------------------
1249: | Returns the result of converting the single-precision floating-point value
1250: | `a' to the 32-bit two's complement integer format. The conversion is
1251: | performed according to the IEC/IEEE Standard for Binary Floating-Point
1252: | Arithmetic---which means in particular that the conversion is rounded
1253: | according to the current rounding mode. If `a' is a NaN, the largest
1254: | positive integer is returned. Otherwise, if the conversion overflows, the
1255: | largest integer with the same sign as `a' is returned.
1256: *----------------------------------------------------------------------------*/
1257:
1258: int32 float32_to_int32( float32 a STATUS_PARAM )
1259: {
1260: flag aSign;
1261: int16 aExp, shiftCount;
1262: bits32 aSig;
1263: bits64 aSig64;
1264:
1265: aSig = extractFloat32Frac( a );
1266: aExp = extractFloat32Exp( a );
1267: aSign = extractFloat32Sign( a );
1268: if ( ( aExp == 0xFF ) && aSig ) aSign = 0;
1269: if ( aExp ) aSig |= 0x00800000;
1270: shiftCount = 0xAF - aExp;
1271: aSig64 = aSig;
1272: aSig64 <<= 32;
1273: if ( 0 < shiftCount ) shift64RightJamming( aSig64, shiftCount, &aSig64 );
1274: return roundAndPackInt32( aSign, aSig64 STATUS_VAR );
1275:
1276: }
1277:
1278: /*----------------------------------------------------------------------------
1279: | Returns the result of converting the single-precision floating-point value
1280: | `a' to the 32-bit two's complement integer format. The conversion is
1281: | performed according to the IEC/IEEE Standard for Binary Floating-Point
1282: | Arithmetic, except that the conversion is always rounded toward zero.
1283: | If `a' is a NaN, the largest positive integer is returned. Otherwise, if
1284: | the conversion overflows, the largest integer with the same sign as `a' is
1285: | returned.
1286: *----------------------------------------------------------------------------*/
1287:
1288: int32 float32_to_int32_round_to_zero( float32 a STATUS_PARAM )
1289: {
1290: flag aSign;
1291: int16 aExp, shiftCount;
1292: bits32 aSig;
1293: int32 z;
1294:
1295: aSig = extractFloat32Frac( a );
1296: aExp = extractFloat32Exp( a );
1297: aSign = extractFloat32Sign( a );
1298: shiftCount = aExp - 0x9E;
1299: if ( 0 <= shiftCount ) {
1300: if ( a != 0xCF000000 ) {
1301: float_raise( float_flag_invalid STATUS_VAR);
1302: if ( ! aSign || ( ( aExp == 0xFF ) && aSig ) ) return 0x7FFFFFFF;
1303: }
1304: return (sbits32) 0x80000000;
1305: }
1306: else if ( aExp <= 0x7E ) {
1307: if ( aExp | aSig ) STATUS(float_exception_flags) |= float_flag_inexact;
1308: return 0;
1309: }
1310: aSig = ( aSig | 0x00800000 )<<8;
1311: z = aSig>>( - shiftCount );
1312: if ( (bits32) ( aSig<<( shiftCount & 31 ) ) ) {
1313: STATUS(float_exception_flags) |= float_flag_inexact;
1314: }
1315: if ( aSign ) z = - z;
1316: return z;
1317:
1318: }
1319:
1320: /*----------------------------------------------------------------------------
1321: | Returns the result of converting the single-precision floating-point value
1322: | `a' to the 64-bit two's complement integer format. The conversion is
1323: | performed according to the IEC/IEEE Standard for Binary Floating-Point
1324: | Arithmetic---which means in particular that the conversion is rounded
1325: | according to the current rounding mode. If `a' is a NaN, the largest
1326: | positive integer is returned. Otherwise, if the conversion overflows, the
1327: | largest integer with the same sign as `a' is returned.
1328: *----------------------------------------------------------------------------*/
1329:
1330: int64 float32_to_int64( float32 a STATUS_PARAM )
1331: {
1332: flag aSign;
1333: int16 aExp, shiftCount;
1334: bits32 aSig;
1335: bits64 aSig64, aSigExtra;
1336:
1337: aSig = extractFloat32Frac( a );
1338: aExp = extractFloat32Exp( a );
1339: aSign = extractFloat32Sign( a );
1340: shiftCount = 0xBE - aExp;
1341: if ( shiftCount < 0 ) {
1342: float_raise( float_flag_invalid STATUS_VAR);
1343: if ( ! aSign || ( ( aExp == 0xFF ) && aSig ) ) {
1344: return LIT64( 0x7FFFFFFFFFFFFFFF );
1345: }
1346: return (sbits64) LIT64( 0x8000000000000000 );
1347: }
1348: if ( aExp ) aSig |= 0x00800000;
1349: aSig64 = aSig;
1350: aSig64 <<= 40;
1351: shift64ExtraRightJamming( aSig64, 0, shiftCount, &aSig64, &aSigExtra );
1352: return roundAndPackInt64( aSign, aSig64, aSigExtra STATUS_VAR );
1353:
1354: }
1355:
1356: /*----------------------------------------------------------------------------
1357: | Returns the result of converting the single-precision floating-point value
1358: | `a' to the 64-bit two's complement integer format. The conversion is
1359: | performed according to the IEC/IEEE Standard for Binary Floating-Point
1360: | Arithmetic, except that the conversion is always rounded toward zero. If
1361: | `a' is a NaN, the largest positive integer is returned. Otherwise, if the
1362: | conversion overflows, the largest integer with the same sign as `a' is
1363: | returned.
1364: *----------------------------------------------------------------------------*/
1365:
1366: int64 float32_to_int64_round_to_zero( float32 a STATUS_PARAM )
1367: {
1368: flag aSign;
1369: int16 aExp, shiftCount;
1370: bits32 aSig;
1371: bits64 aSig64;
1372: int64 z;
1373:
1374: aSig = extractFloat32Frac( a );
1375: aExp = extractFloat32Exp( a );
1376: aSign = extractFloat32Sign( a );
1377: shiftCount = aExp - 0xBE;
1378: if ( 0 <= shiftCount ) {
1379: if ( a != 0xDF000000 ) {
1380: float_raise( float_flag_invalid STATUS_VAR);
1381: if ( ! aSign || ( ( aExp == 0xFF ) && aSig ) ) {
1382: return LIT64( 0x7FFFFFFFFFFFFFFF );
1383: }
1384: }
1385: return (sbits64) LIT64( 0x8000000000000000 );
1386: }
1387: else if ( aExp <= 0x7E ) {
1388: if ( aExp | aSig ) STATUS(float_exception_flags) |= float_flag_inexact;
1389: return 0;
1390: }
1391: aSig64 = aSig | 0x00800000;
1392: aSig64 <<= 40;
1393: z = aSig64>>( - shiftCount );
1394: if ( (bits64) ( aSig64<<( shiftCount & 63 ) ) ) {
1395: STATUS(float_exception_flags) |= float_flag_inexact;
1396: }
1397: if ( aSign ) z = - z;
1398: return z;
1399:
1400: }
1401:
1402: /*----------------------------------------------------------------------------
1403: | Returns the result of converting the single-precision floating-point value
1404: | `a' to the double-precision floating-point format. The conversion is
1405: | performed according to the IEC/IEEE Standard for Binary Floating-Point
1406: | Arithmetic.
1407: *----------------------------------------------------------------------------*/
1408:
1409: float64 float32_to_float64( float32 a STATUS_PARAM )
1410: {
1411: flag aSign;
1412: int16 aExp;
1413: bits32 aSig;
1414:
1415: aSig = extractFloat32Frac( a );
1416: aExp = extractFloat32Exp( a );
1417: aSign = extractFloat32Sign( a );
1418: if ( aExp == 0xFF ) {
1419: if ( aSig ) return commonNaNToFloat64( float32ToCommonNaN( a STATUS_VAR ));
1420: return packFloat64( aSign, 0x7FF, 0 );
1421: }
1422: if ( aExp == 0 ) {
1423: if ( aSig == 0 ) return packFloat64( aSign, 0, 0 );
1424: normalizeFloat32Subnormal( aSig, &aExp, &aSig );
1425: --aExp;
1426: }
1427: return packFloat64( aSign, aExp + 0x380, ( (bits64) aSig )<<29 );
1428:
1429: }
1430:
1431: #ifdef FLOATX80
1432:
1433: /*----------------------------------------------------------------------------
1434: | Returns the result of converting the single-precision floating-point value
1435: | `a' to the extended double-precision floating-point format. The conversion
1436: | is performed according to the IEC/IEEE Standard for Binary Floating-Point
1437: | Arithmetic.
1438: *----------------------------------------------------------------------------*/
1439:
1440: floatx80 float32_to_floatx80( float32 a STATUS_PARAM )
1441: {
1442: flag aSign;
1443: int16 aExp;
1444: bits32 aSig;
1445:
1446: aSig = extractFloat32Frac( a );
1447: aExp = extractFloat32Exp( a );
1448: aSign = extractFloat32Sign( a );
1449: if ( aExp == 0xFF ) {
1450: if ( aSig ) return commonNaNToFloatx80( float32ToCommonNaN( a STATUS_VAR ) );
1451: return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
1452: }
1453: if ( aExp == 0 ) {
1454: if ( aSig == 0 ) return packFloatx80( aSign, 0, 0 );
1455: normalizeFloat32Subnormal( aSig, &aExp, &aSig );
1456: }
1457: aSig |= 0x00800000;
1458: return packFloatx80( aSign, aExp + 0x3F80, ( (bits64) aSig )<<40 );
1459:
1460: }
1461:
1462: #endif
1463:
1464: #ifdef FLOAT128
1465:
1466: /*----------------------------------------------------------------------------
1467: | Returns the result of converting the single-precision floating-point value
1468: | `a' to the double-precision floating-point format. The conversion is
1469: | performed according to the IEC/IEEE Standard for Binary Floating-Point
1470: | Arithmetic.
1471: *----------------------------------------------------------------------------*/
1472:
1473: float128 float32_to_float128( float32 a STATUS_PARAM )
1474: {
1475: flag aSign;
1476: int16 aExp;
1477: bits32 aSig;
1478:
1479: aSig = extractFloat32Frac( a );
1480: aExp = extractFloat32Exp( a );
1481: aSign = extractFloat32Sign( a );
1482: if ( aExp == 0xFF ) {
1483: if ( aSig ) return commonNaNToFloat128( float32ToCommonNaN( a STATUS_VAR ) );
1484: return packFloat128( aSign, 0x7FFF, 0, 0 );
1485: }
1486: if ( aExp == 0 ) {
1487: if ( aSig == 0 ) return packFloat128( aSign, 0, 0, 0 );
1488: normalizeFloat32Subnormal( aSig, &aExp, &aSig );
1489: --aExp;
1490: }
1491: return packFloat128( aSign, aExp + 0x3F80, ( (bits64) aSig )<<25, 0 );
1492:
1493: }
1494:
1495: #endif
1496:
1497: /*----------------------------------------------------------------------------
1498: | Rounds the single-precision floating-point value `a' to an integer, and
1499: | returns the result as a single-precision floating-point value. The
1500: | operation is performed according to the IEC/IEEE Standard for Binary
1501: | Floating-Point Arithmetic.
1502: *----------------------------------------------------------------------------*/
1503:
1504: float32 float32_round_to_int( float32 a STATUS_PARAM)
1505: {
1506: flag aSign;
1507: int16 aExp;
1508: bits32 lastBitMask, roundBitsMask;
1509: int8 roundingMode;
1510: float32 z;
1511:
1512: aExp = extractFloat32Exp( a );
1513: if ( 0x96 <= aExp ) {
1514: if ( ( aExp == 0xFF ) && extractFloat32Frac( a ) ) {
1515: return propagateFloat32NaN( a, a STATUS_VAR );
1516: }
1517: return a;
1518: }
1519: if ( aExp <= 0x7E ) {
1520: if ( (bits32) ( a<<1 ) == 0 ) return a;
1521: STATUS(float_exception_flags) |= float_flag_inexact;
1522: aSign = extractFloat32Sign( a );
1523: switch ( STATUS(float_rounding_mode) ) {
1524: case float_round_nearest_even:
1525: if ( ( aExp == 0x7E ) && extractFloat32Frac( a ) ) {
1526: return packFloat32( aSign, 0x7F, 0 );
1527: }
1528: break;
1529: case float_round_down:
1530: return aSign ? 0xBF800000 : 0;
1531: case float_round_up:
1532: return aSign ? 0x80000000 : 0x3F800000;
1533: }
1534: return packFloat32( aSign, 0, 0 );
1535: }
1536: lastBitMask = 1;
1537: lastBitMask <<= 0x96 - aExp;
1538: roundBitsMask = lastBitMask - 1;
1539: z = a;
1540: roundingMode = STATUS(float_rounding_mode);
1541: if ( roundingMode == float_round_nearest_even ) {
1542: z += lastBitMask>>1;
1543: if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask;
1544: }
1545: else if ( roundingMode != float_round_to_zero ) {
1546: if ( extractFloat32Sign( z ) ^ ( roundingMode == float_round_up ) ) {
1547: z += roundBitsMask;
1548: }
1549: }
1550: z &= ~ roundBitsMask;
1551: if ( z != a ) STATUS(float_exception_flags) |= float_flag_inexact;
1552: return z;
1553:
1554: }
1555:
1556: /*----------------------------------------------------------------------------
1557: | Returns the result of adding the absolute values of the single-precision
1558: | floating-point values `a' and `b'. If `zSign' is 1, the sum is negated
1559: | before being returned. `zSign' is ignored if the result is a NaN.
1560: | The addition is performed according to the IEC/IEEE Standard for Binary
1561: | Floating-Point Arithmetic.
1562: *----------------------------------------------------------------------------*/
1563:
1564: static float32 addFloat32Sigs( float32 a, float32 b, flag zSign STATUS_PARAM)
1565: {
1566: int16 aExp, bExp, zExp;
1567: bits32 aSig, bSig, zSig;
1568: int16 expDiff;
1569:
1570: aSig = extractFloat32Frac( a );
1571: aExp = extractFloat32Exp( a );
1572: bSig = extractFloat32Frac( b );
1573: bExp = extractFloat32Exp( b );
1574: expDiff = aExp - bExp;
1575: aSig <<= 6;
1576: bSig <<= 6;
1577: if ( 0 < expDiff ) {
1578: if ( aExp == 0xFF ) {
1579: if ( aSig ) return propagateFloat32NaN( a, b STATUS_VAR );
1580: return a;
1581: }
1582: if ( bExp == 0 ) {
1583: --expDiff;
1584: }
1585: else {
1586: bSig |= 0x20000000;
1587: }
1588: shift32RightJamming( bSig, expDiff, &bSig );
1589: zExp = aExp;
1590: }
1591: else if ( expDiff < 0 ) {
1592: if ( bExp == 0xFF ) {
1593: if ( bSig ) return propagateFloat32NaN( a, b STATUS_VAR );
1594: return packFloat32( zSign, 0xFF, 0 );
1595: }
1596: if ( aExp == 0 ) {
1597: ++expDiff;
1598: }
1599: else {
1600: aSig |= 0x20000000;
1601: }
1602: shift32RightJamming( aSig, - expDiff, &aSig );
1603: zExp = bExp;
1604: }
1605: else {
1606: if ( aExp == 0xFF ) {
1607: if ( aSig | bSig ) return propagateFloat32NaN( a, b STATUS_VAR );
1608: return a;
1609: }
1610: if ( aExp == 0 ) return packFloat32( zSign, 0, ( aSig + bSig )>>6 );
1611: zSig = 0x40000000 + aSig + bSig;
1612: zExp = aExp;
1613: goto roundAndPack;
1614: }
1615: aSig |= 0x20000000;
1616: zSig = ( aSig + bSig )<<1;
1617: --zExp;
1618: if ( (sbits32) zSig < 0 ) {
1619: zSig = aSig + bSig;
1620: ++zExp;
1621: }
1622: roundAndPack:
1623: return roundAndPackFloat32( zSign, zExp, zSig STATUS_VAR );
1624:
1625: }
1626:
1627: /*----------------------------------------------------------------------------
1628: | Returns the result of subtracting the absolute values of the single-
1629: | precision floating-point values `a' and `b'. If `zSign' is 1, the
1630: | difference is negated before being returned. `zSign' is ignored if the
1631: | result is a NaN. The subtraction is performed according to the IEC/IEEE
1632: | Standard for Binary Floating-Point Arithmetic.
1633: *----------------------------------------------------------------------------*/
1634:
1635: static float32 subFloat32Sigs( float32 a, float32 b, flag zSign STATUS_PARAM)
1636: {
1637: int16 aExp, bExp, zExp;
1638: bits32 aSig, bSig, zSig;
1639: int16 expDiff;
1640:
1641: aSig = extractFloat32Frac( a );
1642: aExp = extractFloat32Exp( a );
1643: bSig = extractFloat32Frac( b );
1644: bExp = extractFloat32Exp( b );
1645: expDiff = aExp - bExp;
1646: aSig <<= 7;
1647: bSig <<= 7;
1648: if ( 0 < expDiff ) goto aExpBigger;
1649: if ( expDiff < 0 ) goto bExpBigger;
1650: if ( aExp == 0xFF ) {
1651: if ( aSig | bSig ) return propagateFloat32NaN( a, b STATUS_VAR );
1652: float_raise( float_flag_invalid STATUS_VAR);
1653: return float32_default_nan;
1654: }
1655: if ( aExp == 0 ) {
1656: aExp = 1;
1657: bExp = 1;
1658: }
1659: if ( bSig < aSig ) goto aBigger;
1660: if ( aSig < bSig ) goto bBigger;
1661: return packFloat32( STATUS(float_rounding_mode) == float_round_down, 0, 0 );
1662: bExpBigger:
1663: if ( bExp == 0xFF ) {
1664: if ( bSig ) return propagateFloat32NaN( a, b STATUS_VAR );
1665: return packFloat32( zSign ^ 1, 0xFF, 0 );
1666: }
1667: if ( aExp == 0 ) {
1668: ++expDiff;
1669: }
1670: else {
1671: aSig |= 0x40000000;
1672: }
1673: shift32RightJamming( aSig, - expDiff, &aSig );
1674: bSig |= 0x40000000;
1675: bBigger:
1676: zSig = bSig - aSig;
1677: zExp = bExp;
1678: zSign ^= 1;
1679: goto normalizeRoundAndPack;
1680: aExpBigger:
1681: if ( aExp == 0xFF ) {
1682: if ( aSig ) return propagateFloat32NaN( a, b STATUS_VAR );
1683: return a;
1684: }
1685: if ( bExp == 0 ) {
1686: --expDiff;
1687: }
1688: else {
1689: bSig |= 0x40000000;
1690: }
1691: shift32RightJamming( bSig, expDiff, &bSig );
1692: aSig |= 0x40000000;
1693: aBigger:
1694: zSig = aSig - bSig;
1695: zExp = aExp;
1696: normalizeRoundAndPack:
1697: --zExp;
1698: return normalizeRoundAndPackFloat32( zSign, zExp, zSig STATUS_VAR );
1699:
1700: }
1701:
1702: /*----------------------------------------------------------------------------
1703: | Returns the result of adding the single-precision floating-point values `a'
1704: | and `b'. The operation is performed according to the IEC/IEEE Standard for
1705: | Binary Floating-Point Arithmetic.
1706: *----------------------------------------------------------------------------*/
1707:
1708: float32 float32_add( float32 a, float32 b STATUS_PARAM )
1709: {
1710: flag aSign, bSign;
1711:
1712: aSign = extractFloat32Sign( a );
1713: bSign = extractFloat32Sign( b );
1714: if ( aSign == bSign ) {
1715: return addFloat32Sigs( a, b, aSign STATUS_VAR);
1716: }
1717: else {
1718: return subFloat32Sigs( a, b, aSign STATUS_VAR );
1719: }
1720:
1721: }
1722:
1723: /*----------------------------------------------------------------------------
1724: | Returns the result of subtracting the single-precision floating-point values
1725: | `a' and `b'. The operation is performed according to the IEC/IEEE Standard
1726: | for Binary Floating-Point Arithmetic.
1727: *----------------------------------------------------------------------------*/
1728:
1729: float32 float32_sub( float32 a, float32 b STATUS_PARAM )
1730: {
1731: flag aSign, bSign;
1732:
1733: aSign = extractFloat32Sign( a );
1734: bSign = extractFloat32Sign( b );
1735: if ( aSign == bSign ) {
1736: return subFloat32Sigs( a, b, aSign STATUS_VAR );
1737: }
1738: else {
1739: return addFloat32Sigs( a, b, aSign STATUS_VAR );
1740: }
1741:
1742: }
1743:
1744: /*----------------------------------------------------------------------------
1745: | Returns the result of multiplying the single-precision floating-point values
1746: | `a' and `b'. The operation is performed according to the IEC/IEEE Standard
1747: | for Binary Floating-Point Arithmetic.
1748: *----------------------------------------------------------------------------*/
1749:
1750: float32 float32_mul( float32 a, float32 b STATUS_PARAM )
1751: {
1752: flag aSign, bSign, zSign;
1753: int16 aExp, bExp, zExp;
1754: bits32 aSig, bSig;
1755: bits64 zSig64;
1756: bits32 zSig;
1757:
1758: aSig = extractFloat32Frac( a );
1759: aExp = extractFloat32Exp( a );
1760: aSign = extractFloat32Sign( a );
1761: bSig = extractFloat32Frac( b );
1762: bExp = extractFloat32Exp( b );
1763: bSign = extractFloat32Sign( b );
1764: zSign = aSign ^ bSign;
1765: if ( aExp == 0xFF ) {
1766: if ( aSig || ( ( bExp == 0xFF ) && bSig ) ) {
1767: return propagateFloat32NaN( a, b STATUS_VAR );
1768: }
1769: if ( ( bExp | bSig ) == 0 ) {
1770: float_raise( float_flag_invalid STATUS_VAR);
1771: return float32_default_nan;
1772: }
1773: return packFloat32( zSign, 0xFF, 0 );
1774: }
1775: if ( bExp == 0xFF ) {
1776: if ( bSig ) return propagateFloat32NaN( a, b STATUS_VAR );
1777: if ( ( aExp | aSig ) == 0 ) {
1778: float_raise( float_flag_invalid STATUS_VAR);
1779: return float32_default_nan;
1780: }
1781: return packFloat32( zSign, 0xFF, 0 );
1782: }
1783: if ( aExp == 0 ) {
1784: if ( aSig == 0 ) return packFloat32( zSign, 0, 0 );
1785: normalizeFloat32Subnormal( aSig, &aExp, &aSig );
1786: }
1787: if ( bExp == 0 ) {
1788: if ( bSig == 0 ) return packFloat32( zSign, 0, 0 );
1789: normalizeFloat32Subnormal( bSig, &bExp, &bSig );
1790: }
1791: zExp = aExp + bExp - 0x7F;
1792: aSig = ( aSig | 0x00800000 )<<7;
1793: bSig = ( bSig | 0x00800000 )<<8;
1794: shift64RightJamming( ( (bits64) aSig ) * bSig, 32, &zSig64 );
1795: zSig = zSig64;
1796: if ( 0 <= (sbits32) ( zSig<<1 ) ) {
1797: zSig <<= 1;
1798: --zExp;
1799: }
1800: return roundAndPackFloat32( zSign, zExp, zSig STATUS_VAR );
1801:
1802: }
1803:
1804: /*----------------------------------------------------------------------------
1805: | Returns the result of dividing the single-precision floating-point value `a'
1806: | by the corresponding value `b'. The operation is performed according to the
1807: | IEC/IEEE Standard for Binary Floating-Point Arithmetic.
1808: *----------------------------------------------------------------------------*/
1809:
1810: float32 float32_div( float32 a, float32 b STATUS_PARAM )
1811: {
1812: flag aSign, bSign, zSign;
1813: int16 aExp, bExp, zExp;
1814: bits32 aSig, bSig, zSig;
1815:
1816: aSig = extractFloat32Frac( a );
1817: aExp = extractFloat32Exp( a );
1818: aSign = extractFloat32Sign( a );
1819: bSig = extractFloat32Frac( b );
1820: bExp = extractFloat32Exp( b );
1821: bSign = extractFloat32Sign( b );
1822: zSign = aSign ^ bSign;
1823: if ( aExp == 0xFF ) {
1824: if ( aSig ) return propagateFloat32NaN( a, b STATUS_VAR );
1825: if ( bExp == 0xFF ) {
1826: if ( bSig ) return propagateFloat32NaN( a, b STATUS_VAR );
1827: float_raise( float_flag_invalid STATUS_VAR);
1828: return float32_default_nan;
1829: }
1830: return packFloat32( zSign, 0xFF, 0 );
1831: }
1832: if ( bExp == 0xFF ) {
1833: if ( bSig ) return propagateFloat32NaN( a, b STATUS_VAR );
1834: return packFloat32( zSign, 0, 0 );
1835: }
1836: if ( bExp == 0 ) {
1837: if ( bSig == 0 ) {
1838: if ( ( aExp | aSig ) == 0 ) {
1839: float_raise( float_flag_invalid STATUS_VAR);
1840: return float32_default_nan;
1841: }
1842: float_raise( float_flag_divbyzero STATUS_VAR);
1843: return packFloat32( zSign, 0xFF, 0 );
1844: }
1845: normalizeFloat32Subnormal( bSig, &bExp, &bSig );
1846: }
1847: if ( aExp == 0 ) {
1848: if ( aSig == 0 ) return packFloat32( zSign, 0, 0 );
1849: normalizeFloat32Subnormal( aSig, &aExp, &aSig );
1850: }
1851: zExp = aExp - bExp + 0x7D;
1852: aSig = ( aSig | 0x00800000 )<<7;
1853: bSig = ( bSig | 0x00800000 )<<8;
1854: if ( bSig <= ( aSig + aSig ) ) {
1855: aSig >>= 1;
1856: ++zExp;
1857: }
1858: zSig = ( ( (bits64) aSig )<<32 ) / bSig;
1859: if ( ( zSig & 0x3F ) == 0 ) {
1860: zSig |= ( (bits64) bSig * zSig != ( (bits64) aSig )<<32 );
1861: }
1862: return roundAndPackFloat32( zSign, zExp, zSig STATUS_VAR );
1863:
1864: }
1865:
1866: /*----------------------------------------------------------------------------
1867: | Returns the remainder of the single-precision floating-point value `a'
1868: | with respect to the corresponding value `b'. The operation is performed
1869: | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
1870: *----------------------------------------------------------------------------*/
1871:
1872: float32 float32_rem( float32 a, float32 b STATUS_PARAM )
1873: {
1874: flag aSign, bSign, zSign;
1875: int16 aExp, bExp, expDiff;
1876: bits32 aSig, bSig;
1877: bits32 q;
1878: bits64 aSig64, bSig64, q64;
1879: bits32 alternateASig;
1880: sbits32 sigMean;
1881:
1882: aSig = extractFloat32Frac( a );
1883: aExp = extractFloat32Exp( a );
1884: aSign = extractFloat32Sign( a );
1885: bSig = extractFloat32Frac( b );
1886: bExp = extractFloat32Exp( b );
1887: bSign = extractFloat32Sign( b );
1888: if ( aExp == 0xFF ) {
1889: if ( aSig || ( ( bExp == 0xFF ) && bSig ) ) {
1890: return propagateFloat32NaN( a, b STATUS_VAR );
1891: }
1892: float_raise( float_flag_invalid STATUS_VAR);
1893: return float32_default_nan;
1894: }
1895: if ( bExp == 0xFF ) {
1896: if ( bSig ) return propagateFloat32NaN( a, b STATUS_VAR );
1897: return a;
1898: }
1899: if ( bExp == 0 ) {
1900: if ( bSig == 0 ) {
1901: float_raise( float_flag_invalid STATUS_VAR);
1902: return float32_default_nan;
1903: }
1904: normalizeFloat32Subnormal( bSig, &bExp, &bSig );
1905: }
1906: if ( aExp == 0 ) {
1907: if ( aSig == 0 ) return a;
1908: normalizeFloat32Subnormal( aSig, &aExp, &aSig );
1909: }
1910: expDiff = aExp - bExp;
1911: aSig |= 0x00800000;
1912: bSig |= 0x00800000;
1913: if ( expDiff < 32 ) {
1914: aSig <<= 8;
1915: bSig <<= 8;
1916: if ( expDiff < 0 ) {
1917: if ( expDiff < -1 ) return a;
1918: aSig >>= 1;
1919: }
1920: q = ( bSig <= aSig );
1921: if ( q ) aSig -= bSig;
1922: if ( 0 < expDiff ) {
1923: q = ( ( (bits64) aSig )<<32 ) / bSig;
1924: q >>= 32 - expDiff;
1925: bSig >>= 2;
1926: aSig = ( ( aSig>>1 )<<( expDiff - 1 ) ) - bSig * q;
1927: }
1928: else {
1929: aSig >>= 2;
1930: bSig >>= 2;
1931: }
1932: }
1933: else {
1934: if ( bSig <= aSig ) aSig -= bSig;
1935: aSig64 = ( (bits64) aSig )<<40;
1936: bSig64 = ( (bits64) bSig )<<40;
1937: expDiff -= 64;
1938: while ( 0 < expDiff ) {
1939: q64 = estimateDiv128To64( aSig64, 0, bSig64 );
1940: q64 = ( 2 < q64 ) ? q64 - 2 : 0;
1941: aSig64 = - ( ( bSig * q64 )<<38 );
1942: expDiff -= 62;
1943: }
1944: expDiff += 64;
1945: q64 = estimateDiv128To64( aSig64, 0, bSig64 );
1946: q64 = ( 2 < q64 ) ? q64 - 2 : 0;
1947: q = q64>>( 64 - expDiff );
1948: bSig <<= 6;
1949: aSig = ( ( aSig64>>33 )<<( expDiff - 1 ) ) - bSig * q;
1950: }
1951: do {
1952: alternateASig = aSig;
1953: ++q;
1954: aSig -= bSig;
1955: } while ( 0 <= (sbits32) aSig );
1956: sigMean = aSig + alternateASig;
1957: if ( ( sigMean < 0 ) || ( ( sigMean == 0 ) && ( q & 1 ) ) ) {
1958: aSig = alternateASig;
1959: }
1960: zSign = ( (sbits32) aSig < 0 );
1961: if ( zSign ) aSig = - aSig;
1962: return normalizeRoundAndPackFloat32( aSign ^ zSign, bExp, aSig STATUS_VAR );
1963:
1964: }
1965:
1966: /*----------------------------------------------------------------------------
1967: | Returns the square root of the single-precision floating-point value `a'.
1968: | The operation is performed according to the IEC/IEEE Standard for Binary
1969: | Floating-Point Arithmetic.
1970: *----------------------------------------------------------------------------*/
1971:
1972: float32 float32_sqrt( float32 a STATUS_PARAM )
1973: {
1974: flag aSign;
1975: int16 aExp, zExp;
1976: bits32 aSig, zSig;
1977: bits64 rem, term;
1978:
1979: aSig = extractFloat32Frac( a );
1980: aExp = extractFloat32Exp( a );
1981: aSign = extractFloat32Sign( a );
1982: if ( aExp == 0xFF ) {
1983: if ( aSig ) return propagateFloat32NaN( a, 0 STATUS_VAR );
1984: if ( ! aSign ) return a;
1985: float_raise( float_flag_invalid STATUS_VAR);
1986: return float32_default_nan;
1987: }
1988: if ( aSign ) {
1989: if ( ( aExp | aSig ) == 0 ) return a;
1990: float_raise( float_flag_invalid STATUS_VAR);
1991: return float32_default_nan;
1992: }
1993: if ( aExp == 0 ) {
1994: if ( aSig == 0 ) return 0;
1995: normalizeFloat32Subnormal( aSig, &aExp, &aSig );
1996: }
1997: zExp = ( ( aExp - 0x7F )>>1 ) + 0x7E;
1998: aSig = ( aSig | 0x00800000 )<<8;
1999: zSig = estimateSqrt32( aExp, aSig ) + 2;
2000: if ( ( zSig & 0x7F ) <= 5 ) {
2001: if ( zSig < 2 ) {
2002: zSig = 0x7FFFFFFF;
2003: goto roundAndPack;
2004: }
2005: aSig >>= aExp & 1;
2006: term = ( (bits64) zSig ) * zSig;
2007: rem = ( ( (bits64) aSig )<<32 ) - term;
2008: while ( (sbits64) rem < 0 ) {
2009: --zSig;
2010: rem += ( ( (bits64) zSig )<<1 ) | 1;
2011: }
2012: zSig |= ( rem != 0 );
2013: }
2014: shift32RightJamming( zSig, 1, &zSig );
2015: roundAndPack:
2016: return roundAndPackFloat32( 0, zExp, zSig STATUS_VAR );
2017:
2018: }
2019:
2020: /*----------------------------------------------------------------------------
2021: | Returns 1 if the single-precision floating-point value `a' is equal to
2022: | the corresponding value `b', and 0 otherwise. The comparison is performed
2023: | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
2024: *----------------------------------------------------------------------------*/
2025:
2026: flag float32_eq( float32 a, float32 b STATUS_PARAM )
2027: {
2028:
2029: if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
2030: || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
2031: ) {
2032: if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) {
2033: float_raise( float_flag_invalid STATUS_VAR);
2034: }
2035: return 0;
2036: }
2037: return ( a == b ) || ( (bits32) ( ( a | b )<<1 ) == 0 );
2038:
2039: }
2040:
2041: /*----------------------------------------------------------------------------
2042: | Returns 1 if the single-precision floating-point value `a' is less than
2043: | or equal to the corresponding value `b', and 0 otherwise. The comparison
2044: | is performed according to the IEC/IEEE Standard for Binary Floating-Point
2045: | Arithmetic.
2046: *----------------------------------------------------------------------------*/
2047:
2048: flag float32_le( float32 a, float32 b STATUS_PARAM )
2049: {
2050: flag aSign, bSign;
2051:
2052: if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
2053: || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
2054: ) {
2055: float_raise( float_flag_invalid STATUS_VAR);
2056: return 0;
2057: }
2058: aSign = extractFloat32Sign( a );
2059: bSign = extractFloat32Sign( b );
2060: if ( aSign != bSign ) return aSign || ( (bits32) ( ( a | b )<<1 ) == 0 );
2061: return ( a == b ) || ( aSign ^ ( a < b ) );
2062:
2063: }
2064:
2065: /*----------------------------------------------------------------------------
2066: | Returns 1 if the single-precision floating-point value `a' is less than
2067: | the corresponding value `b', and 0 otherwise. The comparison is performed
2068: | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
2069: *----------------------------------------------------------------------------*/
2070:
2071: flag float32_lt( float32 a, float32 b STATUS_PARAM )
2072: {
2073: flag aSign, bSign;
2074:
2075: if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
2076: || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
2077: ) {
2078: float_raise( float_flag_invalid STATUS_VAR);
2079: return 0;
2080: }
2081: aSign = extractFloat32Sign( a );
2082: bSign = extractFloat32Sign( b );
2083: if ( aSign != bSign ) return aSign && ( (bits32) ( ( a | b )<<1 ) != 0 );
2084: return ( a != b ) && ( aSign ^ ( a < b ) );
2085:
2086: }
2087:
2088: /*----------------------------------------------------------------------------
2089: | Returns 1 if the single-precision floating-point value `a' is equal to
2090: | the corresponding value `b', and 0 otherwise. The invalid exception is
2091: | raised if either operand is a NaN. Otherwise, the comparison is performed
2092: | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
2093: *----------------------------------------------------------------------------*/
2094:
2095: flag float32_eq_signaling( float32 a, float32 b STATUS_PARAM )
2096: {
2097:
2098: if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
2099: || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
2100: ) {
2101: float_raise( float_flag_invalid STATUS_VAR);
2102: return 0;
2103: }
2104: return ( a == b ) || ( (bits32) ( ( a | b )<<1 ) == 0 );
2105:
2106: }
2107:
2108: /*----------------------------------------------------------------------------
2109: | Returns 1 if the single-precision floating-point value `a' is less than or
2110: | equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not
2111: | cause an exception. Otherwise, the comparison is performed according to the
2112: | IEC/IEEE Standard for Binary Floating-Point Arithmetic.
2113: *----------------------------------------------------------------------------*/
2114:
2115: flag float32_le_quiet( float32 a, float32 b STATUS_PARAM )
2116: {
2117: flag aSign, bSign;
2118:
2119: if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
2120: || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
2121: ) {
2122: if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) {
2123: float_raise( float_flag_invalid STATUS_VAR);
2124: }
2125: return 0;
2126: }
2127: aSign = extractFloat32Sign( a );
2128: bSign = extractFloat32Sign( b );
2129: if ( aSign != bSign ) return aSign || ( (bits32) ( ( a | b )<<1 ) == 0 );
2130: return ( a == b ) || ( aSign ^ ( a < b ) );
2131:
2132: }
2133:
2134: /*----------------------------------------------------------------------------
2135: | Returns 1 if the single-precision floating-point value `a' is less than
2136: | the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an
2137: | exception. Otherwise, the comparison is performed according to the IEC/IEEE
2138: | Standard for Binary Floating-Point Arithmetic.
2139: *----------------------------------------------------------------------------*/
2140:
2141: flag float32_lt_quiet( float32 a, float32 b STATUS_PARAM )
2142: {
2143: flag aSign, bSign;
2144:
2145: if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
2146: || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
2147: ) {
2148: if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) {
2149: float_raise( float_flag_invalid STATUS_VAR);
2150: }
2151: return 0;
2152: }
2153: aSign = extractFloat32Sign( a );
2154: bSign = extractFloat32Sign( b );
2155: if ( aSign != bSign ) return aSign && ( (bits32) ( ( a | b )<<1 ) != 0 );
2156: return ( a != b ) && ( aSign ^ ( a < b ) );
2157:
2158: }
2159:
2160: /*----------------------------------------------------------------------------
2161: | Returns the result of converting the double-precision floating-point value
2162: | `a' to the 32-bit two's complement integer format. The conversion is
2163: | performed according to the IEC/IEEE Standard for Binary Floating-Point
2164: | Arithmetic---which means in particular that the conversion is rounded
2165: | according to the current rounding mode. If `a' is a NaN, the largest
2166: | positive integer is returned. Otherwise, if the conversion overflows, the
2167: | largest integer with the same sign as `a' is returned.
2168: *----------------------------------------------------------------------------*/
2169:
2170: int32 float64_to_int32( float64 a STATUS_PARAM )
2171: {
2172: flag aSign;
2173: int16 aExp, shiftCount;
2174: bits64 aSig;
2175:
2176: aSig = extractFloat64Frac( a );
2177: aExp = extractFloat64Exp( a );
2178: aSign = extractFloat64Sign( a );
2179: if ( ( aExp == 0x7FF ) && aSig ) aSign = 0;
2180: if ( aExp ) aSig |= LIT64( 0x0010000000000000 );
2181: shiftCount = 0x42C - aExp;
2182: if ( 0 < shiftCount ) shift64RightJamming( aSig, shiftCount, &aSig );
2183: return roundAndPackInt32( aSign, aSig STATUS_VAR );
2184:
2185: }
2186:
2187: /*----------------------------------------------------------------------------
2188: | Returns the result of converting the double-precision floating-point value
2189: | `a' to the 32-bit two's complement integer format. The conversion is
2190: | performed according to the IEC/IEEE Standard for Binary Floating-Point
2191: | Arithmetic, except that the conversion is always rounded toward zero.
2192: | If `a' is a NaN, the largest positive integer is returned. Otherwise, if
2193: | the conversion overflows, the largest integer with the same sign as `a' is
2194: | returned.
2195: *----------------------------------------------------------------------------*/
2196:
2197: int32 float64_to_int32_round_to_zero( float64 a STATUS_PARAM )
2198: {
2199: flag aSign;
2200: int16 aExp, shiftCount;
2201: bits64 aSig, savedASig;
2202: int32 z;
2203:
2204: aSig = extractFloat64Frac( a );
2205: aExp = extractFloat64Exp( a );
2206: aSign = extractFloat64Sign( a );
2207: if ( 0x41E < aExp ) {
2208: if ( ( aExp == 0x7FF ) && aSig ) aSign = 0;
2209: goto invalid;
2210: }
2211: else if ( aExp < 0x3FF ) {
2212: if ( aExp || aSig ) STATUS(float_exception_flags) |= float_flag_inexact;
2213: return 0;
2214: }
2215: aSig |= LIT64( 0x0010000000000000 );
2216: shiftCount = 0x433 - aExp;
2217: savedASig = aSig;
2218: aSig >>= shiftCount;
2219: z = aSig;
2220: if ( aSign ) z = - z;
2221: if ( ( z < 0 ) ^ aSign ) {
2222: invalid:
2223: float_raise( float_flag_invalid STATUS_VAR);
2224: return aSign ? (sbits32) 0x80000000 : 0x7FFFFFFF;
2225: }
2226: if ( ( aSig<<shiftCount ) != savedASig ) {
2227: STATUS(float_exception_flags) |= float_flag_inexact;
2228: }
2229: return z;
2230:
2231: }
2232:
2233: /*----------------------------------------------------------------------------
2234: | Returns the result of converting the double-precision floating-point value
2235: | `a' to the 64-bit two's complement integer format. The conversion is
2236: | performed according to the IEC/IEEE Standard for Binary Floating-Point
2237: | Arithmetic---which means in particular that the conversion is rounded
2238: | according to the current rounding mode. If `a' is a NaN, the largest
2239: | positive integer is returned. Otherwise, if the conversion overflows, the
2240: | largest integer with the same sign as `a' is returned.
2241: *----------------------------------------------------------------------------*/
2242:
2243: int64 float64_to_int64( float64 a STATUS_PARAM )
2244: {
2245: flag aSign;
2246: int16 aExp, shiftCount;
2247: bits64 aSig, aSigExtra;
2248:
2249: aSig = extractFloat64Frac( a );
2250: aExp = extractFloat64Exp( a );
2251: aSign = extractFloat64Sign( a );
2252: if ( aExp ) aSig |= LIT64( 0x0010000000000000 );
2253: shiftCount = 0x433 - aExp;
2254: if ( shiftCount <= 0 ) {
2255: if ( 0x43E < aExp ) {
2256: float_raise( float_flag_invalid STATUS_VAR);
2257: if ( ! aSign
2258: || ( ( aExp == 0x7FF )
2259: && ( aSig != LIT64( 0x0010000000000000 ) ) )
2260: ) {
2261: return LIT64( 0x7FFFFFFFFFFFFFFF );
2262: }
2263: return (sbits64) LIT64( 0x8000000000000000 );
2264: }
2265: aSigExtra = 0;
2266: aSig <<= - shiftCount;
2267: }
2268: else {
2269: shift64ExtraRightJamming( aSig, 0, shiftCount, &aSig, &aSigExtra );
2270: }
2271: return roundAndPackInt64( aSign, aSig, aSigExtra STATUS_VAR );
2272:
2273: }
2274:
2275: /*----------------------------------------------------------------------------
2276: | Returns the result of converting the double-precision floating-point value
2277: | `a' to the 64-bit two's complement integer format. The conversion is
2278: | performed according to the IEC/IEEE Standard for Binary Floating-Point
2279: | Arithmetic, except that the conversion is always rounded toward zero.
2280: | If `a' is a NaN, the largest positive integer is returned. Otherwise, if
2281: | the conversion overflows, the largest integer with the same sign as `a' is
2282: | returned.
2283: *----------------------------------------------------------------------------*/
2284:
2285: int64 float64_to_int64_round_to_zero( float64 a STATUS_PARAM )
2286: {
2287: flag aSign;
2288: int16 aExp, shiftCount;
2289: bits64 aSig;
2290: int64 z;
2291:
2292: aSig = extractFloat64Frac( a );
2293: aExp = extractFloat64Exp( a );
2294: aSign = extractFloat64Sign( a );
2295: if ( aExp ) aSig |= LIT64( 0x0010000000000000 );
2296: shiftCount = aExp - 0x433;
2297: if ( 0 <= shiftCount ) {
2298: if ( 0x43E <= aExp ) {
2299: if ( a != LIT64( 0xC3E0000000000000 ) ) {
2300: float_raise( float_flag_invalid STATUS_VAR);
2301: if ( ! aSign
2302: || ( ( aExp == 0x7FF )
2303: && ( aSig != LIT64( 0x0010000000000000 ) ) )
2304: ) {
2305: return LIT64( 0x7FFFFFFFFFFFFFFF );
2306: }
2307: }
2308: return (sbits64) LIT64( 0x8000000000000000 );
2309: }
2310: z = aSig<<shiftCount;
2311: }
2312: else {
2313: if ( aExp < 0x3FE ) {
2314: if ( aExp | aSig ) STATUS(float_exception_flags) |= float_flag_inexact;
2315: return 0;
2316: }
2317: z = aSig>>( - shiftCount );
2318: if ( (bits64) ( aSig<<( shiftCount & 63 ) ) ) {
2319: STATUS(float_exception_flags) |= float_flag_inexact;
2320: }
2321: }
2322: if ( aSign ) z = - z;
2323: return z;
2324:
2325: }
2326:
2327: /*----------------------------------------------------------------------------
2328: | Returns the result of converting the double-precision floating-point value
2329: | `a' to the single-precision floating-point format. The conversion is
2330: | performed according to the IEC/IEEE Standard for Binary Floating-Point
2331: | Arithmetic.
2332: *----------------------------------------------------------------------------*/
2333:
2334: float32 float64_to_float32( float64 a STATUS_PARAM )
2335: {
2336: flag aSign;
2337: int16 aExp;
2338: bits64 aSig;
2339: bits32 zSig;
2340:
2341: aSig = extractFloat64Frac( a );
2342: aExp = extractFloat64Exp( a );
2343: aSign = extractFloat64Sign( a );
2344: if ( aExp == 0x7FF ) {
2345: if ( aSig ) return commonNaNToFloat32( float64ToCommonNaN( a STATUS_VAR ) );
2346: return packFloat32( aSign, 0xFF, 0 );
2347: }
2348: shift64RightJamming( aSig, 22, &aSig );
2349: zSig = aSig;
2350: if ( aExp || zSig ) {
2351: zSig |= 0x40000000;
2352: aExp -= 0x381;
2353: }
2354: return roundAndPackFloat32( aSign, aExp, zSig STATUS_VAR );
2355:
2356: }
2357:
2358: #ifdef FLOATX80
2359:
2360: /*----------------------------------------------------------------------------
2361: | Returns the result of converting the double-precision floating-point value
2362: | `a' to the extended double-precision floating-point format. The conversion
2363: | is performed according to the IEC/IEEE Standard for Binary Floating-Point
2364: | Arithmetic.
2365: *----------------------------------------------------------------------------*/
2366:
2367: floatx80 float64_to_floatx80( float64 a STATUS_PARAM )
2368: {
2369: flag aSign;
2370: int16 aExp;
2371: bits64 aSig;
2372:
2373: aSig = extractFloat64Frac( a );
2374: aExp = extractFloat64Exp( a );
2375: aSign = extractFloat64Sign( a );
2376: if ( aExp == 0x7FF ) {
2377: if ( aSig ) return commonNaNToFloatx80( float64ToCommonNaN( a STATUS_VAR ) );
2378: return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
2379: }
2380: if ( aExp == 0 ) {
2381: if ( aSig == 0 ) return packFloatx80( aSign, 0, 0 );
2382: normalizeFloat64Subnormal( aSig, &aExp, &aSig );
2383: }
2384: return
2385: packFloatx80(
2386: aSign, aExp + 0x3C00, ( aSig | LIT64( 0x0010000000000000 ) )<<11 );
2387:
2388: }
2389:
2390: #endif
2391:
2392: #ifdef FLOAT128
2393:
2394: /*----------------------------------------------------------------------------
2395: | Returns the result of converting the double-precision floating-point value
2396: | `a' to the quadruple-precision floating-point format. The conversion is
2397: | performed according to the IEC/IEEE Standard for Binary Floating-Point
2398: | Arithmetic.
2399: *----------------------------------------------------------------------------*/
2400:
2401: float128 float64_to_float128( float64 a STATUS_PARAM )
2402: {
2403: flag aSign;
2404: int16 aExp;
2405: bits64 aSig, zSig0, zSig1;
2406:
2407: aSig = extractFloat64Frac( a );
2408: aExp = extractFloat64Exp( a );
2409: aSign = extractFloat64Sign( a );
2410: if ( aExp == 0x7FF ) {
2411: if ( aSig ) return commonNaNToFloat128( float64ToCommonNaN( a STATUS_VAR ) );
2412: return packFloat128( aSign, 0x7FFF, 0, 0 );
2413: }
2414: if ( aExp == 0 ) {
2415: if ( aSig == 0 ) return packFloat128( aSign, 0, 0, 0 );
2416: normalizeFloat64Subnormal( aSig, &aExp, &aSig );
2417: --aExp;
2418: }
2419: shift128Right( aSig, 0, 4, &zSig0, &zSig1 );
2420: return packFloat128( aSign, aExp + 0x3C00, zSig0, zSig1 );
2421:
2422: }
2423:
2424: #endif
2425:
2426: /*----------------------------------------------------------------------------
2427: | Rounds the double-precision floating-point value `a' to an integer, and
2428: | returns the result as a double-precision floating-point value. The
2429: | operation is performed according to the IEC/IEEE Standard for Binary
2430: | Floating-Point Arithmetic.
2431: *----------------------------------------------------------------------------*/
2432:
2433: float64 float64_round_to_int( float64 a STATUS_PARAM )
2434: {
2435: flag aSign;
2436: int16 aExp;
2437: bits64 lastBitMask, roundBitsMask;
2438: int8 roundingMode;
2439: float64 z;
2440:
2441: aExp = extractFloat64Exp( a );
2442: if ( 0x433 <= aExp ) {
2443: if ( ( aExp == 0x7FF ) && extractFloat64Frac( a ) ) {
2444: return propagateFloat64NaN( a, a STATUS_VAR );
2445: }
2446: return a;
2447: }
2448: if ( aExp < 0x3FF ) {
2449: if ( (bits64) ( a<<1 ) == 0 ) return a;
2450: STATUS(float_exception_flags) |= float_flag_inexact;
2451: aSign = extractFloat64Sign( a );
2452: switch ( STATUS(float_rounding_mode) ) {
2453: case float_round_nearest_even:
2454: if ( ( aExp == 0x3FE ) && extractFloat64Frac( a ) ) {
2455: return packFloat64( aSign, 0x3FF, 0 );
2456: }
2457: break;
2458: case float_round_down:
2459: return aSign ? LIT64( 0xBFF0000000000000 ) : 0;
2460: case float_round_up:
2461: return
2462: aSign ? LIT64( 0x8000000000000000 ) : LIT64( 0x3FF0000000000000 );
2463: }
2464: return packFloat64( aSign, 0, 0 );
2465: }
2466: lastBitMask = 1;
2467: lastBitMask <<= 0x433 - aExp;
2468: roundBitsMask = lastBitMask - 1;
2469: z = a;
2470: roundingMode = STATUS(float_rounding_mode);
2471: if ( roundingMode == float_round_nearest_even ) {
2472: z += lastBitMask>>1;
2473: if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask;
2474: }
2475: else if ( roundingMode != float_round_to_zero ) {
2476: if ( extractFloat64Sign( z ) ^ ( roundingMode == float_round_up ) ) {
2477: z += roundBitsMask;
2478: }
2479: }
2480: z &= ~ roundBitsMask;
2481: if ( z != a ) STATUS(float_exception_flags) |= float_flag_inexact;
2482: return z;
2483:
2484: }
2485:
2486: /*----------------------------------------------------------------------------
2487: | Returns the result of adding the absolute values of the double-precision
2488: | floating-point values `a' and `b'. If `zSign' is 1, the sum is negated
2489: | before being returned. `zSign' is ignored if the result is a NaN.
2490: | The addition is performed according to the IEC/IEEE Standard for Binary
2491: | Floating-Point Arithmetic.
2492: *----------------------------------------------------------------------------*/
2493:
2494: static float64 addFloat64Sigs( float64 a, float64 b, flag zSign STATUS_PARAM )
2495: {
2496: int16 aExp, bExp, zExp;
2497: bits64 aSig, bSig, zSig;
2498: int16 expDiff;
2499:
2500: aSig = extractFloat64Frac( a );
2501: aExp = extractFloat64Exp( a );
2502: bSig = extractFloat64Frac( b );
2503: bExp = extractFloat64Exp( b );
2504: expDiff = aExp - bExp;
2505: aSig <<= 9;
2506: bSig <<= 9;
2507: if ( 0 < expDiff ) {
2508: if ( aExp == 0x7FF ) {
2509: if ( aSig ) return propagateFloat64NaN( a, b STATUS_VAR );
2510: return a;
2511: }
2512: if ( bExp == 0 ) {
2513: --expDiff;
2514: }
2515: else {
2516: bSig |= LIT64( 0x2000000000000000 );
2517: }
2518: shift64RightJamming( bSig, expDiff, &bSig );
2519: zExp = aExp;
2520: }
2521: else if ( expDiff < 0 ) {
2522: if ( bExp == 0x7FF ) {
2523: if ( bSig ) return propagateFloat64NaN( a, b STATUS_VAR );
2524: return packFloat64( zSign, 0x7FF, 0 );
2525: }
2526: if ( aExp == 0 ) {
2527: ++expDiff;
2528: }
2529: else {
2530: aSig |= LIT64( 0x2000000000000000 );
2531: }
2532: shift64RightJamming( aSig, - expDiff, &aSig );
2533: zExp = bExp;
2534: }
2535: else {
2536: if ( aExp == 0x7FF ) {
2537: if ( aSig | bSig ) return propagateFloat64NaN( a, b STATUS_VAR );
2538: return a;
2539: }
2540: if ( aExp == 0 ) return packFloat64( zSign, 0, ( aSig + bSig )>>9 );
2541: zSig = LIT64( 0x4000000000000000 ) + aSig + bSig;
2542: zExp = aExp;
2543: goto roundAndPack;
2544: }
2545: aSig |= LIT64( 0x2000000000000000 );
2546: zSig = ( aSig + bSig )<<1;
2547: --zExp;
2548: if ( (sbits64) zSig < 0 ) {
2549: zSig = aSig + bSig;
2550: ++zExp;
2551: }
2552: roundAndPack:
2553: return roundAndPackFloat64( zSign, zExp, zSig STATUS_VAR );
2554:
2555: }
2556:
2557: /*----------------------------------------------------------------------------
2558: | Returns the result of subtracting the absolute values of the double-
2559: | precision floating-point values `a' and `b'. If `zSign' is 1, the
2560: | difference is negated before being returned. `zSign' is ignored if the
2561: | result is a NaN. The subtraction is performed according to the IEC/IEEE
2562: | Standard for Binary Floating-Point Arithmetic.
2563: *----------------------------------------------------------------------------*/
2564:
2565: static float64 subFloat64Sigs( float64 a, float64 b, flag zSign STATUS_PARAM )
2566: {
2567: int16 aExp, bExp, zExp;
2568: bits64 aSig, bSig, zSig;
2569: int16 expDiff;
2570:
2571: aSig = extractFloat64Frac( a );
2572: aExp = extractFloat64Exp( a );
2573: bSig = extractFloat64Frac( b );
2574: bExp = extractFloat64Exp( b );
2575: expDiff = aExp - bExp;
2576: aSig <<= 10;
2577: bSig <<= 10;
2578: if ( 0 < expDiff ) goto aExpBigger;
2579: if ( expDiff < 0 ) goto bExpBigger;
2580: if ( aExp == 0x7FF ) {
2581: if ( aSig | bSig ) return propagateFloat64NaN( a, b STATUS_VAR );
2582: float_raise( float_flag_invalid STATUS_VAR);
2583: return float64_default_nan;
2584: }
2585: if ( aExp == 0 ) {
2586: aExp = 1;
2587: bExp = 1;
2588: }
2589: if ( bSig < aSig ) goto aBigger;
2590: if ( aSig < bSig ) goto bBigger;
2591: return packFloat64( STATUS(float_rounding_mode) == float_round_down, 0, 0 );
2592: bExpBigger:
2593: if ( bExp == 0x7FF ) {
2594: if ( bSig ) return propagateFloat64NaN( a, b STATUS_VAR );
2595: return packFloat64( zSign ^ 1, 0x7FF, 0 );
2596: }
2597: if ( aExp == 0 ) {
2598: ++expDiff;
2599: }
2600: else {
2601: aSig |= LIT64( 0x4000000000000000 );
2602: }
2603: shift64RightJamming( aSig, - expDiff, &aSig );
2604: bSig |= LIT64( 0x4000000000000000 );
2605: bBigger:
2606: zSig = bSig - aSig;
2607: zExp = bExp;
2608: zSign ^= 1;
2609: goto normalizeRoundAndPack;
2610: aExpBigger:
2611: if ( aExp == 0x7FF ) {
2612: if ( aSig ) return propagateFloat64NaN( a, b STATUS_VAR );
2613: return a;
2614: }
2615: if ( bExp == 0 ) {
2616: --expDiff;
2617: }
2618: else {
2619: bSig |= LIT64( 0x4000000000000000 );
2620: }
2621: shift64RightJamming( bSig, expDiff, &bSig );
2622: aSig |= LIT64( 0x4000000000000000 );
2623: aBigger:
2624: zSig = aSig - bSig;
2625: zExp = aExp;
2626: normalizeRoundAndPack:
2627: --zExp;
2628: return normalizeRoundAndPackFloat64( zSign, zExp, zSig STATUS_VAR );
2629:
2630: }
2631:
2632: /*----------------------------------------------------------------------------
2633: | Returns the result of adding the double-precision floating-point values `a'
2634: | and `b'. The operation is performed according to the IEC/IEEE Standard for
2635: | Binary Floating-Point Arithmetic.
2636: *----------------------------------------------------------------------------*/
2637:
2638: float64 float64_add( float64 a, float64 b STATUS_PARAM )
2639: {
2640: flag aSign, bSign;
2641:
2642: aSign = extractFloat64Sign( a );
2643: bSign = extractFloat64Sign( b );
2644: if ( aSign == bSign ) {
2645: return addFloat64Sigs( a, b, aSign STATUS_VAR );
2646: }
2647: else {
2648: return subFloat64Sigs( a, b, aSign STATUS_VAR );
2649: }
2650:
2651: }
2652:
2653: /*----------------------------------------------------------------------------
2654: | Returns the result of subtracting the double-precision floating-point values
2655: | `a' and `b'. The operation is performed according to the IEC/IEEE Standard
2656: | for Binary Floating-Point Arithmetic.
2657: *----------------------------------------------------------------------------*/
2658:
2659: float64 float64_sub( float64 a, float64 b STATUS_PARAM )
2660: {
2661: flag aSign, bSign;
2662:
2663: aSign = extractFloat64Sign( a );
2664: bSign = extractFloat64Sign( b );
2665: if ( aSign == bSign ) {
2666: return subFloat64Sigs( a, b, aSign STATUS_VAR );
2667: }
2668: else {
2669: return addFloat64Sigs( a, b, aSign STATUS_VAR );
2670: }
2671:
2672: }
2673:
2674: /*----------------------------------------------------------------------------
2675: | Returns the result of multiplying the double-precision floating-point values
2676: | `a' and `b'. The operation is performed according to the IEC/IEEE Standard
2677: | for Binary Floating-Point Arithmetic.
2678: *----------------------------------------------------------------------------*/
2679:
2680: float64 float64_mul( float64 a, float64 b STATUS_PARAM )
2681: {
2682: flag aSign, bSign, zSign;
2683: int16 aExp, bExp, zExp;
2684: bits64 aSig, bSig, zSig0, zSig1;
2685:
2686: aSig = extractFloat64Frac( a );
2687: aExp = extractFloat64Exp( a );
2688: aSign = extractFloat64Sign( a );
2689: bSig = extractFloat64Frac( b );
2690: bExp = extractFloat64Exp( b );
2691: bSign = extractFloat64Sign( b );
2692: zSign = aSign ^ bSign;
2693: if ( aExp == 0x7FF ) {
2694: if ( aSig || ( ( bExp == 0x7FF ) && bSig ) ) {
2695: return propagateFloat64NaN( a, b STATUS_VAR );
2696: }
2697: if ( ( bExp | bSig ) == 0 ) {
2698: float_raise( float_flag_invalid STATUS_VAR);
2699: return float64_default_nan;
2700: }
2701: return packFloat64( zSign, 0x7FF, 0 );
2702: }
2703: if ( bExp == 0x7FF ) {
2704: if ( bSig ) return propagateFloat64NaN( a, b STATUS_VAR );
2705: if ( ( aExp | aSig ) == 0 ) {
2706: float_raise( float_flag_invalid STATUS_VAR);
2707: return float64_default_nan;
2708: }
2709: return packFloat64( zSign, 0x7FF, 0 );
2710: }
2711: if ( aExp == 0 ) {
2712: if ( aSig == 0 ) return packFloat64( zSign, 0, 0 );
2713: normalizeFloat64Subnormal( aSig, &aExp, &aSig );
2714: }
2715: if ( bExp == 0 ) {
2716: if ( bSig == 0 ) return packFloat64( zSign, 0, 0 );
2717: normalizeFloat64Subnormal( bSig, &bExp, &bSig );
2718: }
2719: zExp = aExp + bExp - 0x3FF;
2720: aSig = ( aSig | LIT64( 0x0010000000000000 ) )<<10;
2721: bSig = ( bSig | LIT64( 0x0010000000000000 ) )<<11;
2722: mul64To128( aSig, bSig, &zSig0, &zSig1 );
2723: zSig0 |= ( zSig1 != 0 );
2724: if ( 0 <= (sbits64) ( zSig0<<1 ) ) {
2725: zSig0 <<= 1;
2726: --zExp;
2727: }
2728: return roundAndPackFloat64( zSign, zExp, zSig0 STATUS_VAR );
2729:
2730: }
2731:
2732: /*----------------------------------------------------------------------------
2733: | Returns the result of dividing the double-precision floating-point value `a'
2734: | by the corresponding value `b'. The operation is performed according to
2735: | the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
2736: *----------------------------------------------------------------------------*/
2737:
2738: float64 float64_div( float64 a, float64 b STATUS_PARAM )
2739: {
2740: flag aSign, bSign, zSign;
2741: int16 aExp, bExp, zExp;
2742: bits64 aSig, bSig, zSig;
2743: bits64 rem0, rem1;
2744: bits64 term0, term1;
2745:
2746: aSig = extractFloat64Frac( a );
2747: aExp = extractFloat64Exp( a );
2748: aSign = extractFloat64Sign( a );
2749: bSig = extractFloat64Frac( b );
2750: bExp = extractFloat64Exp( b );
2751: bSign = extractFloat64Sign( b );
2752: zSign = aSign ^ bSign;
2753: if ( aExp == 0x7FF ) {
2754: if ( aSig ) return propagateFloat64NaN( a, b STATUS_VAR );
2755: if ( bExp == 0x7FF ) {
2756: if ( bSig ) return propagateFloat64NaN( a, b STATUS_VAR );
2757: float_raise( float_flag_invalid STATUS_VAR);
2758: return float64_default_nan;
2759: }
2760: return packFloat64( zSign, 0x7FF, 0 );
2761: }
2762: if ( bExp == 0x7FF ) {
2763: if ( bSig ) return propagateFloat64NaN( a, b STATUS_VAR );
2764: return packFloat64( zSign, 0, 0 );
2765: }
2766: if ( bExp == 0 ) {
2767: if ( bSig == 0 ) {
2768: if ( ( aExp | aSig ) == 0 ) {
2769: float_raise( float_flag_invalid STATUS_VAR);
2770: return float64_default_nan;
2771: }
2772: float_raise( float_flag_divbyzero STATUS_VAR);
2773: return packFloat64( zSign, 0x7FF, 0 );
2774: }
2775: normalizeFloat64Subnormal( bSig, &bExp, &bSig );
2776: }
2777: if ( aExp == 0 ) {
2778: if ( aSig == 0 ) return packFloat64( zSign, 0, 0 );
2779: normalizeFloat64Subnormal( aSig, &aExp, &aSig );
2780: }
2781: zExp = aExp - bExp + 0x3FD;
2782: aSig = ( aSig | LIT64( 0x0010000000000000 ) )<<10;
2783: bSig = ( bSig | LIT64( 0x0010000000000000 ) )<<11;
2784: if ( bSig <= ( aSig + aSig ) ) {
2785: aSig >>= 1;
2786: ++zExp;
2787: }
2788: zSig = estimateDiv128To64( aSig, 0, bSig );
2789: if ( ( zSig & 0x1FF ) <= 2 ) {
2790: mul64To128( bSig, zSig, &term0, &term1 );
2791: sub128( aSig, 0, term0, term1, &rem0, &rem1 );
2792: while ( (sbits64) rem0 < 0 ) {
2793: --zSig;
2794: add128( rem0, rem1, 0, bSig, &rem0, &rem1 );
2795: }
2796: zSig |= ( rem1 != 0 );
2797: }
2798: return roundAndPackFloat64( zSign, zExp, zSig STATUS_VAR );
2799:
2800: }
2801:
2802: /*----------------------------------------------------------------------------
2803: | Returns the remainder of the double-precision floating-point value `a'
2804: | with respect to the corresponding value `b'. The operation is performed
2805: | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
2806: *----------------------------------------------------------------------------*/
2807:
2808: float64 float64_rem( float64 a, float64 b STATUS_PARAM )
2809: {
2810: flag aSign, bSign, zSign;
2811: int16 aExp, bExp, expDiff;
2812: bits64 aSig, bSig;
2813: bits64 q, alternateASig;
2814: sbits64 sigMean;
2815:
2816: aSig = extractFloat64Frac( a );
2817: aExp = extractFloat64Exp( a );
2818: aSign = extractFloat64Sign( a );
2819: bSig = extractFloat64Frac( b );
2820: bExp = extractFloat64Exp( b );
2821: bSign = extractFloat64Sign( b );
2822: if ( aExp == 0x7FF ) {
2823: if ( aSig || ( ( bExp == 0x7FF ) && bSig ) ) {
2824: return propagateFloat64NaN( a, b STATUS_VAR );
2825: }
2826: float_raise( float_flag_invalid STATUS_VAR);
2827: return float64_default_nan;
2828: }
2829: if ( bExp == 0x7FF ) {
2830: if ( bSig ) return propagateFloat64NaN( a, b STATUS_VAR );
2831: return a;
2832: }
2833: if ( bExp == 0 ) {
2834: if ( bSig == 0 ) {
2835: float_raise( float_flag_invalid STATUS_VAR);
2836: return float64_default_nan;
2837: }
2838: normalizeFloat64Subnormal( bSig, &bExp, &bSig );
2839: }
2840: if ( aExp == 0 ) {
2841: if ( aSig == 0 ) return a;
2842: normalizeFloat64Subnormal( aSig, &aExp, &aSig );
2843: }
2844: expDiff = aExp - bExp;
2845: aSig = ( aSig | LIT64( 0x0010000000000000 ) )<<11;
2846: bSig = ( bSig | LIT64( 0x0010000000000000 ) )<<11;
2847: if ( expDiff < 0 ) {
2848: if ( expDiff < -1 ) return a;
2849: aSig >>= 1;
2850: }
2851: q = ( bSig <= aSig );
2852: if ( q ) aSig -= bSig;
2853: expDiff -= 64;
2854: while ( 0 < expDiff ) {
2855: q = estimateDiv128To64( aSig, 0, bSig );
2856: q = ( 2 < q ) ? q - 2 : 0;
2857: aSig = - ( ( bSig>>2 ) * q );
2858: expDiff -= 62;
2859: }
2860: expDiff += 64;
2861: if ( 0 < expDiff ) {
2862: q = estimateDiv128To64( aSig, 0, bSig );
2863: q = ( 2 < q ) ? q - 2 : 0;
2864: q >>= 64 - expDiff;
2865: bSig >>= 2;
2866: aSig = ( ( aSig>>1 )<<( expDiff - 1 ) ) - bSig * q;
2867: }
2868: else {
2869: aSig >>= 2;
2870: bSig >>= 2;
2871: }
2872: do {
2873: alternateASig = aSig;
2874: ++q;
2875: aSig -= bSig;
2876: } while ( 0 <= (sbits64) aSig );
2877: sigMean = aSig + alternateASig;
2878: if ( ( sigMean < 0 ) || ( ( sigMean == 0 ) && ( q & 1 ) ) ) {
2879: aSig = alternateASig;
2880: }
2881: zSign = ( (sbits64) aSig < 0 );
2882: if ( zSign ) aSig = - aSig;
2883: return normalizeRoundAndPackFloat64( aSign ^ zSign, bExp, aSig STATUS_VAR );
2884:
2885: }
2886:
2887: /*----------------------------------------------------------------------------
2888: | Returns the square root of the double-precision floating-point value `a'.
2889: | The operation is performed according to the IEC/IEEE Standard for Binary
2890: | Floating-Point Arithmetic.
2891: *----------------------------------------------------------------------------*/
2892:
2893: float64 float64_sqrt( float64 a STATUS_PARAM )
2894: {
2895: flag aSign;
2896: int16 aExp, zExp;
2897: bits64 aSig, zSig, doubleZSig;
2898: bits64 rem0, rem1, term0, term1;
2899:
2900: aSig = extractFloat64Frac( a );
2901: aExp = extractFloat64Exp( a );
2902: aSign = extractFloat64Sign( a );
2903: if ( aExp == 0x7FF ) {
2904: if ( aSig ) return propagateFloat64NaN( a, a STATUS_VAR );
2905: if ( ! aSign ) return a;
2906: float_raise( float_flag_invalid STATUS_VAR);
2907: return float64_default_nan;
2908: }
2909: if ( aSign ) {
2910: if ( ( aExp | aSig ) == 0 ) return a;
2911: float_raise( float_flag_invalid STATUS_VAR);
2912: return float64_default_nan;
2913: }
2914: if ( aExp == 0 ) {
2915: if ( aSig == 0 ) return 0;
2916: normalizeFloat64Subnormal( aSig, &aExp, &aSig );
2917: }
2918: zExp = ( ( aExp - 0x3FF )>>1 ) + 0x3FE;
2919: aSig |= LIT64( 0x0010000000000000 );
2920: zSig = estimateSqrt32( aExp, aSig>>21 );
2921: aSig <<= 9 - ( aExp & 1 );
2922: zSig = estimateDiv128To64( aSig, 0, zSig<<32 ) + ( zSig<<30 );
2923: if ( ( zSig & 0x1FF ) <= 5 ) {
2924: doubleZSig = zSig<<1;
2925: mul64To128( zSig, zSig, &term0, &term1 );
2926: sub128( aSig, 0, term0, term1, &rem0, &rem1 );
2927: while ( (sbits64) rem0 < 0 ) {
2928: --zSig;
2929: doubleZSig -= 2;
2930: add128( rem0, rem1, zSig>>63, doubleZSig | 1, &rem0, &rem1 );
2931: }
2932: zSig |= ( ( rem0 | rem1 ) != 0 );
2933: }
2934: return roundAndPackFloat64( 0, zExp, zSig STATUS_VAR );
2935:
2936: }
2937:
2938: /*----------------------------------------------------------------------------
2939: | Returns 1 if the double-precision floating-point value `a' is equal to the
2940: | corresponding value `b', and 0 otherwise. The comparison is performed
2941: | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
2942: *----------------------------------------------------------------------------*/
2943:
2944: flag float64_eq( float64 a, float64 b STATUS_PARAM )
2945: {
2946:
2947: if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
2948: || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
2949: ) {
2950: if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) {
2951: float_raise( float_flag_invalid STATUS_VAR);
2952: }
2953: return 0;
2954: }
2955: return ( a == b ) || ( (bits64) ( ( a | b )<<1 ) == 0 );
2956:
2957: }
2958:
2959: /*----------------------------------------------------------------------------
2960: | Returns 1 if the double-precision floating-point value `a' is less than or
2961: | equal to the corresponding value `b', and 0 otherwise. The comparison is
2962: | performed according to the IEC/IEEE Standard for Binary Floating-Point
2963: | Arithmetic.
2964: *----------------------------------------------------------------------------*/
2965:
2966: flag float64_le( float64 a, float64 b STATUS_PARAM )
2967: {
2968: flag aSign, bSign;
2969:
2970: if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
2971: || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
2972: ) {
2973: float_raise( float_flag_invalid STATUS_VAR);
2974: return 0;
2975: }
2976: aSign = extractFloat64Sign( a );
2977: bSign = extractFloat64Sign( b );
2978: if ( aSign != bSign ) return aSign || ( (bits64) ( ( a | b )<<1 ) == 0 );
2979: return ( a == b ) || ( aSign ^ ( a < b ) );
2980:
2981: }
2982:
2983: /*----------------------------------------------------------------------------
2984: | Returns 1 if the double-precision floating-point value `a' is less than
2985: | the corresponding value `b', and 0 otherwise. The comparison is performed
2986: | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
2987: *----------------------------------------------------------------------------*/
2988:
2989: flag float64_lt( float64 a, float64 b STATUS_PARAM )
2990: {
2991: flag aSign, bSign;
2992:
2993: if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
2994: || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
2995: ) {
2996: float_raise( float_flag_invalid STATUS_VAR);
2997: return 0;
2998: }
2999: aSign = extractFloat64Sign( a );
3000: bSign = extractFloat64Sign( b );
3001: if ( aSign != bSign ) return aSign && ( (bits64) ( ( a | b )<<1 ) != 0 );
3002: return ( a != b ) && ( aSign ^ ( a < b ) );
3003:
3004: }
3005:
3006: /*----------------------------------------------------------------------------
3007: | Returns 1 if the double-precision floating-point value `a' is equal to the
3008: | corresponding value `b', and 0 otherwise. The invalid exception is raised
3009: | if either operand is a NaN. Otherwise, the comparison is performed
3010: | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
3011: *----------------------------------------------------------------------------*/
3012:
3013: flag float64_eq_signaling( float64 a, float64 b STATUS_PARAM )
3014: {
3015:
3016: if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
3017: || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
3018: ) {
3019: float_raise( float_flag_invalid STATUS_VAR);
3020: return 0;
3021: }
3022: return ( a == b ) || ( (bits64) ( ( a | b )<<1 ) == 0 );
3023:
3024: }
3025:
3026: /*----------------------------------------------------------------------------
3027: | Returns 1 if the double-precision floating-point value `a' is less than or
3028: | equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not
3029: | cause an exception. Otherwise, the comparison is performed according to the
3030: | IEC/IEEE Standard for Binary Floating-Point Arithmetic.
3031: *----------------------------------------------------------------------------*/
3032:
3033: flag float64_le_quiet( float64 a, float64 b STATUS_PARAM )
3034: {
3035: flag aSign, bSign;
3036:
3037: if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
3038: || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
3039: ) {
3040: if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) {
3041: float_raise( float_flag_invalid STATUS_VAR);
3042: }
3043: return 0;
3044: }
3045: aSign = extractFloat64Sign( a );
3046: bSign = extractFloat64Sign( b );
3047: if ( aSign != bSign ) return aSign || ( (bits64) ( ( a | b )<<1 ) == 0 );
3048: return ( a == b ) || ( aSign ^ ( a < b ) );
3049:
3050: }
3051:
3052: /*----------------------------------------------------------------------------
3053: | Returns 1 if the double-precision floating-point value `a' is less than
3054: | the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an
3055: | exception. Otherwise, the comparison is performed according to the IEC/IEEE
3056: | Standard for Binary Floating-Point Arithmetic.
3057: *----------------------------------------------------------------------------*/
3058:
3059: flag float64_lt_quiet( float64 a, float64 b STATUS_PARAM )
3060: {
3061: flag aSign, bSign;
3062:
3063: if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
3064: || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
3065: ) {
3066: if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) {
3067: float_raise( float_flag_invalid STATUS_VAR);
3068: }
3069: return 0;
3070: }
3071: aSign = extractFloat64Sign( a );
3072: bSign = extractFloat64Sign( b );
3073: if ( aSign != bSign ) return aSign && ( (bits64) ( ( a | b )<<1 ) != 0 );
3074: return ( a != b ) && ( aSign ^ ( a < b ) );
3075:
3076: }
3077:
3078: #ifdef FLOATX80
3079:
3080: /*----------------------------------------------------------------------------
3081: | Returns the result of converting the extended double-precision floating-
3082: | point value `a' to the 32-bit two's complement integer format. The
3083: | conversion is performed according to the IEC/IEEE Standard for Binary
3084: | Floating-Point Arithmetic---which means in particular that the conversion
3085: | is rounded according to the current rounding mode. If `a' is a NaN, the
3086: | largest positive integer is returned. Otherwise, if the conversion
3087: | overflows, the largest integer with the same sign as `a' is returned.
3088: *----------------------------------------------------------------------------*/
3089:
3090: int32 floatx80_to_int32( floatx80 a STATUS_PARAM )
3091: {
3092: flag aSign;
3093: int32 aExp, shiftCount;
3094: bits64 aSig;
3095:
3096: aSig = extractFloatx80Frac( a );
3097: aExp = extractFloatx80Exp( a );
3098: aSign = extractFloatx80Sign( a );
3099: if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) aSign = 0;
3100: shiftCount = 0x4037 - aExp;
3101: if ( shiftCount <= 0 ) shiftCount = 1;
3102: shift64RightJamming( aSig, shiftCount, &aSig );
3103: return roundAndPackInt32( aSign, aSig STATUS_VAR );
3104:
3105: }
3106:
3107: /*----------------------------------------------------------------------------
3108: | Returns the result of converting the extended double-precision floating-
3109: | point value `a' to the 32-bit two's complement integer format. The
3110: | conversion is performed according to the IEC/IEEE Standard for Binary
3111: | Floating-Point Arithmetic, except that the conversion is always rounded
3112: | toward zero. If `a' is a NaN, the largest positive integer is returned.
3113: | Otherwise, if the conversion overflows, the largest integer with the same
3114: | sign as `a' is returned.
3115: *----------------------------------------------------------------------------*/
3116:
3117: int32 floatx80_to_int32_round_to_zero( floatx80 a STATUS_PARAM )
3118: {
3119: flag aSign;
3120: int32 aExp, shiftCount;
3121: bits64 aSig, savedASig;
3122: int32 z;
3123:
3124: aSig = extractFloatx80Frac( a );
3125: aExp = extractFloatx80Exp( a );
3126: aSign = extractFloatx80Sign( a );
3127: if ( 0x401E < aExp ) {
3128: if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) aSign = 0;
3129: goto invalid;
3130: }
3131: else if ( aExp < 0x3FFF ) {
3132: if ( aExp || aSig ) STATUS(float_exception_flags) |= float_flag_inexact;
3133: return 0;
3134: }
3135: shiftCount = 0x403E - aExp;
3136: savedASig = aSig;
3137: aSig >>= shiftCount;
3138: z = aSig;
3139: if ( aSign ) z = - z;
3140: if ( ( z < 0 ) ^ aSign ) {
3141: invalid:
3142: float_raise( float_flag_invalid STATUS_VAR);
3143: return aSign ? (sbits32) 0x80000000 : 0x7FFFFFFF;
3144: }
3145: if ( ( aSig<<shiftCount ) != savedASig ) {
3146: STATUS(float_exception_flags) |= float_flag_inexact;
3147: }
3148: return z;
3149:
3150: }
3151:
3152: /*----------------------------------------------------------------------------
3153: | Returns the result of converting the extended double-precision floating-
3154: | point value `a' to the 64-bit two's complement integer format. The
3155: | conversion is performed according to the IEC/IEEE Standard for Binary
3156: | Floating-Point Arithmetic---which means in particular that the conversion
3157: | is rounded according to the current rounding mode. If `a' is a NaN,
3158: | the largest positive integer is returned. Otherwise, if the conversion
3159: | overflows, the largest integer with the same sign as `a' is returned.
3160: *----------------------------------------------------------------------------*/
3161:
3162: int64 floatx80_to_int64( floatx80 a STATUS_PARAM )
3163: {
3164: flag aSign;
3165: int32 aExp, shiftCount;
3166: bits64 aSig, aSigExtra;
3167:
3168: aSig = extractFloatx80Frac( a );
3169: aExp = extractFloatx80Exp( a );
3170: aSign = extractFloatx80Sign( a );
3171: shiftCount = 0x403E - aExp;
3172: if ( shiftCount <= 0 ) {
3173: if ( shiftCount ) {
3174: float_raise( float_flag_invalid STATUS_VAR);
3175: if ( ! aSign
3176: || ( ( aExp == 0x7FFF )
3177: && ( aSig != LIT64( 0x8000000000000000 ) ) )
3178: ) {
3179: return LIT64( 0x7FFFFFFFFFFFFFFF );
3180: }
3181: return (sbits64) LIT64( 0x8000000000000000 );
3182: }
3183: aSigExtra = 0;
3184: }
3185: else {
3186: shift64ExtraRightJamming( aSig, 0, shiftCount, &aSig, &aSigExtra );
3187: }
3188: return roundAndPackInt64( aSign, aSig, aSigExtra STATUS_VAR );
3189:
3190: }
3191:
3192: /*----------------------------------------------------------------------------
3193: | Returns the result of converting the extended double-precision floating-
3194: | point value `a' to the 64-bit two's complement integer format. The
3195: | conversion is performed according to the IEC/IEEE Standard for Binary
3196: | Floating-Point Arithmetic, except that the conversion is always rounded
3197: | toward zero. If `a' is a NaN, the largest positive integer is returned.
3198: | Otherwise, if the conversion overflows, the largest integer with the same
3199: | sign as `a' is returned.
3200: *----------------------------------------------------------------------------*/
3201:
3202: int64 floatx80_to_int64_round_to_zero( floatx80 a STATUS_PARAM )
3203: {
3204: flag aSign;
3205: int32 aExp, shiftCount;
3206: bits64 aSig;
3207: int64 z;
3208:
3209: aSig = extractFloatx80Frac( a );
3210: aExp = extractFloatx80Exp( a );
3211: aSign = extractFloatx80Sign( a );
3212: shiftCount = aExp - 0x403E;
3213: if ( 0 <= shiftCount ) {
3214: aSig &= LIT64( 0x7FFFFFFFFFFFFFFF );
3215: if ( ( a.high != 0xC03E ) || aSig ) {
3216: float_raise( float_flag_invalid STATUS_VAR);
3217: if ( ! aSign || ( ( aExp == 0x7FFF ) && aSig ) ) {
3218: return LIT64( 0x7FFFFFFFFFFFFFFF );
3219: }
3220: }
3221: return (sbits64) LIT64( 0x8000000000000000 );
3222: }
3223: else if ( aExp < 0x3FFF ) {
3224: if ( aExp | aSig ) STATUS(float_exception_flags) |= float_flag_inexact;
3225: return 0;
3226: }
3227: z = aSig>>( - shiftCount );
3228: if ( (bits64) ( aSig<<( shiftCount & 63 ) ) ) {
3229: STATUS(float_exception_flags) |= float_flag_inexact;
3230: }
3231: if ( aSign ) z = - z;
3232: return z;
3233:
3234: }
3235:
3236: /*----------------------------------------------------------------------------
3237: | Returns the result of converting the extended double-precision floating-
3238: | point value `a' to the single-precision floating-point format. The
3239: | conversion is performed according to the IEC/IEEE Standard for Binary
3240: | Floating-Point Arithmetic.
3241: *----------------------------------------------------------------------------*/
3242:
3243: float32 floatx80_to_float32( floatx80 a STATUS_PARAM )
3244: {
3245: flag aSign;
3246: int32 aExp;
3247: bits64 aSig;
3248:
3249: aSig = extractFloatx80Frac( a );
3250: aExp = extractFloatx80Exp( a );
3251: aSign = extractFloatx80Sign( a );
3252: if ( aExp == 0x7FFF ) {
3253: if ( (bits64) ( aSig<<1 ) ) {
3254: return commonNaNToFloat32( floatx80ToCommonNaN( a STATUS_VAR ) );
3255: }
3256: return packFloat32( aSign, 0xFF, 0 );
3257: }
3258: shift64RightJamming( aSig, 33, &aSig );
3259: if ( aExp || aSig ) aExp -= 0x3F81;
3260: return roundAndPackFloat32( aSign, aExp, aSig STATUS_VAR );
3261:
3262: }
3263:
3264: /*----------------------------------------------------------------------------
3265: | Returns the result of converting the extended double-precision floating-
3266: | point value `a' to the double-precision floating-point format. The
3267: | conversion is performed according to the IEC/IEEE Standard for Binary
3268: | Floating-Point Arithmetic.
3269: *----------------------------------------------------------------------------*/
3270:
3271: float64 floatx80_to_float64( floatx80 a STATUS_PARAM )
3272: {
3273: flag aSign;
3274: int32 aExp;
3275: bits64 aSig, zSig;
3276:
3277: aSig = extractFloatx80Frac( a );
3278: aExp = extractFloatx80Exp( a );
3279: aSign = extractFloatx80Sign( a );
3280: if ( aExp == 0x7FFF ) {
3281: if ( (bits64) ( aSig<<1 ) ) {
3282: return commonNaNToFloat64( floatx80ToCommonNaN( a STATUS_VAR ) );
3283: }
3284: return packFloat64( aSign, 0x7FF, 0 );
3285: }
3286: shift64RightJamming( aSig, 1, &zSig );
3287: if ( aExp || aSig ) aExp -= 0x3C01;
3288: return roundAndPackFloat64( aSign, aExp, zSig STATUS_VAR );
3289:
3290: }
3291:
3292: #ifdef FLOAT128
3293:
3294: /*----------------------------------------------------------------------------
3295: | Returns the result of converting the extended double-precision floating-
3296: | point value `a' to the quadruple-precision floating-point format. The
3297: | conversion is performed according to the IEC/IEEE Standard for Binary
3298: | Floating-Point Arithmetic.
3299: *----------------------------------------------------------------------------*/
3300:
3301: float128 floatx80_to_float128( floatx80 a STATUS_PARAM )
3302: {
3303: flag aSign;
3304: int16 aExp;
3305: bits64 aSig, zSig0, zSig1;
3306:
3307: aSig = extractFloatx80Frac( a );
3308: aExp = extractFloatx80Exp( a );
3309: aSign = extractFloatx80Sign( a );
3310: if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) {
3311: return commonNaNToFloat128( floatx80ToCommonNaN( a STATUS_VAR ) );
3312: }
3313: shift128Right( aSig<<1, 0, 16, &zSig0, &zSig1 );
3314: return packFloat128( aSign, aExp, zSig0, zSig1 );
3315:
3316: }
3317:
3318: #endif
3319:
3320: /*----------------------------------------------------------------------------
3321: | Rounds the extended double-precision floating-point value `a' to an integer,
3322: | and returns the result as an extended quadruple-precision floating-point
3323: | value. The operation is performed according to the IEC/IEEE Standard for
3324: | Binary Floating-Point Arithmetic.
3325: *----------------------------------------------------------------------------*/
3326:
3327: floatx80 floatx80_round_to_int( floatx80 a STATUS_PARAM )
3328: {
3329: flag aSign;
3330: int32 aExp;
3331: bits64 lastBitMask, roundBitsMask;
3332: int8 roundingMode;
3333: floatx80 z;
3334:
3335: aExp = extractFloatx80Exp( a );
3336: if ( 0x403E <= aExp ) {
3337: if ( ( aExp == 0x7FFF ) && (bits64) ( extractFloatx80Frac( a )<<1 ) ) {
3338: return propagateFloatx80NaN( a, a STATUS_VAR );
3339: }
3340: return a;
3341: }
3342: if ( aExp < 0x3FFF ) {
3343: if ( ( aExp == 0 )
3344: && ( (bits64) ( extractFloatx80Frac( a )<<1 ) == 0 ) ) {
3345: return a;
3346: }
3347: STATUS(float_exception_flags) |= float_flag_inexact;
3348: aSign = extractFloatx80Sign( a );
3349: switch ( STATUS(float_rounding_mode) ) {
3350: case float_round_nearest_even:
3351: if ( ( aExp == 0x3FFE ) && (bits64) ( extractFloatx80Frac( a )<<1 )
3352: ) {
3353: return
3354: packFloatx80( aSign, 0x3FFF, LIT64( 0x8000000000000000 ) );
3355: }
3356: break;
3357: case float_round_down:
3358: return
3359: aSign ?
3360: packFloatx80( 1, 0x3FFF, LIT64( 0x8000000000000000 ) )
3361: : packFloatx80( 0, 0, 0 );
3362: case float_round_up:
3363: return
3364: aSign ? packFloatx80( 1, 0, 0 )
3365: : packFloatx80( 0, 0x3FFF, LIT64( 0x8000000000000000 ) );
3366: }
3367: return packFloatx80( aSign, 0, 0 );
3368: }
3369: lastBitMask = 1;
3370: lastBitMask <<= 0x403E - aExp;
3371: roundBitsMask = lastBitMask - 1;
3372: z = a;
3373: roundingMode = STATUS(float_rounding_mode);
3374: if ( roundingMode == float_round_nearest_even ) {
3375: z.low += lastBitMask>>1;
3376: if ( ( z.low & roundBitsMask ) == 0 ) z.low &= ~ lastBitMask;
3377: }
3378: else if ( roundingMode != float_round_to_zero ) {
3379: if ( extractFloatx80Sign( z ) ^ ( roundingMode == float_round_up ) ) {
3380: z.low += roundBitsMask;
3381: }
3382: }
3383: z.low &= ~ roundBitsMask;
3384: if ( z.low == 0 ) {
3385: ++z.high;
3386: z.low = LIT64( 0x8000000000000000 );
3387: }
3388: if ( z.low != a.low ) STATUS(float_exception_flags) |= float_flag_inexact;
3389: return z;
3390:
3391: }
3392:
3393: /*----------------------------------------------------------------------------
3394: | Returns the result of adding the absolute values of the extended double-
3395: | precision floating-point values `a' and `b'. If `zSign' is 1, the sum is
3396: | negated before being returned. `zSign' is ignored if the result is a NaN.
3397: | The addition is performed according to the IEC/IEEE Standard for Binary
3398: | Floating-Point Arithmetic.
3399: *----------------------------------------------------------------------------*/
3400:
3401: static floatx80 addFloatx80Sigs( floatx80 a, floatx80 b, flag zSign STATUS_PARAM)
3402: {
3403: int32 aExp, bExp, zExp;
3404: bits64 aSig, bSig, zSig0, zSig1;
3405: int32 expDiff;
3406:
3407: aSig = extractFloatx80Frac( a );
3408: aExp = extractFloatx80Exp( a );
3409: bSig = extractFloatx80Frac( b );
3410: bExp = extractFloatx80Exp( b );
3411: expDiff = aExp - bExp;
3412: if ( 0 < expDiff ) {
3413: if ( aExp == 0x7FFF ) {
3414: if ( (bits64) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b STATUS_VAR );
3415: return a;
3416: }
3417: if ( bExp == 0 ) --expDiff;
3418: shift64ExtraRightJamming( bSig, 0, expDiff, &bSig, &zSig1 );
3419: zExp = aExp;
3420: }
3421: else if ( expDiff < 0 ) {
3422: if ( bExp == 0x7FFF ) {
3423: if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b STATUS_VAR );
3424: return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
3425: }
3426: if ( aExp == 0 ) ++expDiff;
3427: shift64ExtraRightJamming( aSig, 0, - expDiff, &aSig, &zSig1 );
3428: zExp = bExp;
3429: }
3430: else {
3431: if ( aExp == 0x7FFF ) {
3432: if ( (bits64) ( ( aSig | bSig )<<1 ) ) {
3433: return propagateFloatx80NaN( a, b STATUS_VAR );
3434: }
3435: return a;
3436: }
3437: zSig1 = 0;
3438: zSig0 = aSig + bSig;
3439: if ( aExp == 0 ) {
3440: normalizeFloatx80Subnormal( zSig0, &zExp, &zSig0 );
3441: goto roundAndPack;
3442: }
3443: zExp = aExp;
3444: goto shiftRight1;
3445: }
3446: zSig0 = aSig + bSig;
3447: if ( (sbits64) zSig0 < 0 ) goto roundAndPack;
3448: shiftRight1:
3449: shift64ExtraRightJamming( zSig0, zSig1, 1, &zSig0, &zSig1 );
3450: zSig0 |= LIT64( 0x8000000000000000 );
3451: ++zExp;
3452: roundAndPack:
3453: return
3454: roundAndPackFloatx80(
3455: STATUS(floatx80_rounding_precision), zSign, zExp, zSig0, zSig1 STATUS_VAR );
3456:
3457: }
3458:
3459: /*----------------------------------------------------------------------------
3460: | Returns the result of subtracting the absolute values of the extended
3461: | double-precision floating-point values `a' and `b'. If `zSign' is 1, the
3462: | difference is negated before being returned. `zSign' is ignored if the
3463: | result is a NaN. The subtraction is performed according to the IEC/IEEE
3464: | Standard for Binary Floating-Point Arithmetic.
3465: *----------------------------------------------------------------------------*/
3466:
3467: static floatx80 subFloatx80Sigs( floatx80 a, floatx80 b, flag zSign STATUS_PARAM )
3468: {
3469: int32 aExp, bExp, zExp;
3470: bits64 aSig, bSig, zSig0, zSig1;
3471: int32 expDiff;
3472: floatx80 z;
3473:
3474: aSig = extractFloatx80Frac( a );
3475: aExp = extractFloatx80Exp( a );
3476: bSig = extractFloatx80Frac( b );
3477: bExp = extractFloatx80Exp( b );
3478: expDiff = aExp - bExp;
3479: if ( 0 < expDiff ) goto aExpBigger;
3480: if ( expDiff < 0 ) goto bExpBigger;
3481: if ( aExp == 0x7FFF ) {
3482: if ( (bits64) ( ( aSig | bSig )<<1 ) ) {
3483: return propagateFloatx80NaN( a, b STATUS_VAR );
3484: }
3485: float_raise( float_flag_invalid STATUS_VAR);
3486: z.low = floatx80_default_nan_low;
3487: z.high = floatx80_default_nan_high;
3488: return z;
3489: }
3490: if ( aExp == 0 ) {
3491: aExp = 1;
3492: bExp = 1;
3493: }
3494: zSig1 = 0;
3495: if ( bSig < aSig ) goto aBigger;
3496: if ( aSig < bSig ) goto bBigger;
3497: return packFloatx80( STATUS(float_rounding_mode) == float_round_down, 0, 0 );
3498: bExpBigger:
3499: if ( bExp == 0x7FFF ) {
3500: if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b STATUS_VAR );
3501: return packFloatx80( zSign ^ 1, 0x7FFF, LIT64( 0x8000000000000000 ) );
3502: }
3503: if ( aExp == 0 ) ++expDiff;
3504: shift128RightJamming( aSig, 0, - expDiff, &aSig, &zSig1 );
3505: bBigger:
3506: sub128( bSig, 0, aSig, zSig1, &zSig0, &zSig1 );
3507: zExp = bExp;
3508: zSign ^= 1;
3509: goto normalizeRoundAndPack;
3510: aExpBigger:
3511: if ( aExp == 0x7FFF ) {
3512: if ( (bits64) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b STATUS_VAR );
3513: return a;
3514: }
3515: if ( bExp == 0 ) --expDiff;
3516: shift128RightJamming( bSig, 0, expDiff, &bSig, &zSig1 );
3517: aBigger:
3518: sub128( aSig, 0, bSig, zSig1, &zSig0, &zSig1 );
3519: zExp = aExp;
3520: normalizeRoundAndPack:
3521: return
3522: normalizeRoundAndPackFloatx80(
3523: STATUS(floatx80_rounding_precision), zSign, zExp, zSig0, zSig1 STATUS_VAR );
3524:
3525: }
3526:
3527: /*----------------------------------------------------------------------------
3528: | Returns the result of adding the extended double-precision floating-point
3529: | values `a' and `b'. The operation is performed according to the IEC/IEEE
3530: | Standard for Binary Floating-Point Arithmetic.
3531: *----------------------------------------------------------------------------*/
3532:
3533: floatx80 floatx80_add( floatx80 a, floatx80 b STATUS_PARAM )
3534: {
3535: flag aSign, bSign;
3536:
3537: aSign = extractFloatx80Sign( a );
3538: bSign = extractFloatx80Sign( b );
3539: if ( aSign == bSign ) {
3540: return addFloatx80Sigs( a, b, aSign STATUS_VAR );
3541: }
3542: else {
3543: return subFloatx80Sigs( a, b, aSign STATUS_VAR );
3544: }
3545:
3546: }
3547:
3548: /*----------------------------------------------------------------------------
3549: | Returns the result of subtracting the extended double-precision floating-
3550: | point values `a' and `b'. The operation is performed according to the
3551: | IEC/IEEE Standard for Binary Floating-Point Arithmetic.
3552: *----------------------------------------------------------------------------*/
3553:
3554: floatx80 floatx80_sub( floatx80 a, floatx80 b STATUS_PARAM )
3555: {
3556: flag aSign, bSign;
3557:
3558: aSign = extractFloatx80Sign( a );
3559: bSign = extractFloatx80Sign( b );
3560: if ( aSign == bSign ) {
3561: return subFloatx80Sigs( a, b, aSign STATUS_VAR );
3562: }
3563: else {
3564: return addFloatx80Sigs( a, b, aSign STATUS_VAR );
3565: }
3566:
3567: }
3568:
3569: /*----------------------------------------------------------------------------
3570: | Returns the result of multiplying the extended double-precision floating-
3571: | point values `a' and `b'. The operation is performed according to the
3572: | IEC/IEEE Standard for Binary Floating-Point Arithmetic.
3573: *----------------------------------------------------------------------------*/
3574:
3575: floatx80 floatx80_mul( floatx80 a, floatx80 b STATUS_PARAM )
3576: {
3577: flag aSign, bSign, zSign;
3578: int32 aExp, bExp, zExp;
3579: bits64 aSig, bSig, zSig0, zSig1;
3580: floatx80 z;
3581:
3582: aSig = extractFloatx80Frac( a );
3583: aExp = extractFloatx80Exp( a );
3584: aSign = extractFloatx80Sign( a );
3585: bSig = extractFloatx80Frac( b );
3586: bExp = extractFloatx80Exp( b );
3587: bSign = extractFloatx80Sign( b );
3588: zSign = aSign ^ bSign;
3589: if ( aExp == 0x7FFF ) {
3590: if ( (bits64) ( aSig<<1 )
3591: || ( ( bExp == 0x7FFF ) && (bits64) ( bSig<<1 ) ) ) {
3592: return propagateFloatx80NaN( a, b STATUS_VAR );
3593: }
3594: if ( ( bExp | bSig ) == 0 ) goto invalid;
3595: return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
3596: }
3597: if ( bExp == 0x7FFF ) {
3598: if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b STATUS_VAR );
3599: if ( ( aExp | aSig ) == 0 ) {
3600: invalid:
3601: float_raise( float_flag_invalid STATUS_VAR);
3602: z.low = floatx80_default_nan_low;
3603: z.high = floatx80_default_nan_high;
3604: return z;
3605: }
3606: return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
3607: }
3608: if ( aExp == 0 ) {
3609: if ( aSig == 0 ) return packFloatx80( zSign, 0, 0 );
3610: normalizeFloatx80Subnormal( aSig, &aExp, &aSig );
3611: }
3612: if ( bExp == 0 ) {
3613: if ( bSig == 0 ) return packFloatx80( zSign, 0, 0 );
3614: normalizeFloatx80Subnormal( bSig, &bExp, &bSig );
3615: }
3616: zExp = aExp + bExp - 0x3FFE;
3617: mul64To128( aSig, bSig, &zSig0, &zSig1 );
3618: if ( 0 < (sbits64) zSig0 ) {
3619: shortShift128Left( zSig0, zSig1, 1, &zSig0, &zSig1 );
3620: --zExp;
3621: }
3622: return
3623: roundAndPackFloatx80(
3624: STATUS(floatx80_rounding_precision), zSign, zExp, zSig0, zSig1 STATUS_VAR );
3625:
3626: }
3627:
3628: /*----------------------------------------------------------------------------
3629: | Returns the result of dividing the extended double-precision floating-point
3630: | value `a' by the corresponding value `b'. The operation is performed
3631: | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
3632: *----------------------------------------------------------------------------*/
3633:
3634: floatx80 floatx80_div( floatx80 a, floatx80 b STATUS_PARAM )
3635: {
3636: flag aSign, bSign, zSign;
3637: int32 aExp, bExp, zExp;
3638: bits64 aSig, bSig, zSig0, zSig1;
3639: bits64 rem0, rem1, rem2, term0, term1, term2;
3640: floatx80 z;
3641:
3642: aSig = extractFloatx80Frac( a );
3643: aExp = extractFloatx80Exp( a );
3644: aSign = extractFloatx80Sign( a );
3645: bSig = extractFloatx80Frac( b );
3646: bExp = extractFloatx80Exp( b );
3647: bSign = extractFloatx80Sign( b );
3648: zSign = aSign ^ bSign;
3649: if ( aExp == 0x7FFF ) {
3650: if ( (bits64) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b STATUS_VAR );
3651: if ( bExp == 0x7FFF ) {
3652: if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b STATUS_VAR );
3653: goto invalid;
3654: }
3655: return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
3656: }
3657: if ( bExp == 0x7FFF ) {
3658: if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b STATUS_VAR );
3659: return packFloatx80( zSign, 0, 0 );
3660: }
3661: if ( bExp == 0 ) {
3662: if ( bSig == 0 ) {
3663: if ( ( aExp | aSig ) == 0 ) {
3664: invalid:
3665: float_raise( float_flag_invalid STATUS_VAR);
3666: z.low = floatx80_default_nan_low;
3667: z.high = floatx80_default_nan_high;
3668: return z;
3669: }
3670: float_raise( float_flag_divbyzero STATUS_VAR);
3671: return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
3672: }
3673: normalizeFloatx80Subnormal( bSig, &bExp, &bSig );
3674: }
3675: if ( aExp == 0 ) {
3676: if ( aSig == 0 ) return packFloatx80( zSign, 0, 0 );
3677: normalizeFloatx80Subnormal( aSig, &aExp, &aSig );
3678: }
3679: zExp = aExp - bExp + 0x3FFE;
3680: rem1 = 0;
3681: if ( bSig <= aSig ) {
3682: shift128Right( aSig, 0, 1, &aSig, &rem1 );
3683: ++zExp;
3684: }
3685: zSig0 = estimateDiv128To64( aSig, rem1, bSig );
3686: mul64To128( bSig, zSig0, &term0, &term1 );
3687: sub128( aSig, rem1, term0, term1, &rem0, &rem1 );
3688: while ( (sbits64) rem0 < 0 ) {
3689: --zSig0;
3690: add128( rem0, rem1, 0, bSig, &rem0, &rem1 );
3691: }
3692: zSig1 = estimateDiv128To64( rem1, 0, bSig );
3693: if ( (bits64) ( zSig1<<1 ) <= 8 ) {
3694: mul64To128( bSig, zSig1, &term1, &term2 );
3695: sub128( rem1, 0, term1, term2, &rem1, &rem2 );
3696: while ( (sbits64) rem1 < 0 ) {
3697: --zSig1;
3698: add128( rem1, rem2, 0, bSig, &rem1, &rem2 );
3699: }
3700: zSig1 |= ( ( rem1 | rem2 ) != 0 );
3701: }
3702: return
3703: roundAndPackFloatx80(
3704: STATUS(floatx80_rounding_precision), zSign, zExp, zSig0, zSig1 STATUS_VAR );
3705:
3706: }
3707:
3708: /*----------------------------------------------------------------------------
3709: | Returns the remainder of the extended double-precision floating-point value
3710: | `a' with respect to the corresponding value `b'. The operation is performed
3711: | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
3712: *----------------------------------------------------------------------------*/
3713:
3714: floatx80 floatx80_rem( floatx80 a, floatx80 b STATUS_PARAM )
3715: {
3716: flag aSign, bSign, zSign;
3717: int32 aExp, bExp, expDiff;
3718: bits64 aSig0, aSig1, bSig;
3719: bits64 q, term0, term1, alternateASig0, alternateASig1;
3720: floatx80 z;
3721:
3722: aSig0 = extractFloatx80Frac( a );
3723: aExp = extractFloatx80Exp( a );
3724: aSign = extractFloatx80Sign( a );
3725: bSig = extractFloatx80Frac( b );
3726: bExp = extractFloatx80Exp( b );
3727: bSign = extractFloatx80Sign( b );
3728: if ( aExp == 0x7FFF ) {
3729: if ( (bits64) ( aSig0<<1 )
3730: || ( ( bExp == 0x7FFF ) && (bits64) ( bSig<<1 ) ) ) {
3731: return propagateFloatx80NaN( a, b STATUS_VAR );
3732: }
3733: goto invalid;
3734: }
3735: if ( bExp == 0x7FFF ) {
3736: if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b STATUS_VAR );
3737: return a;
3738: }
3739: if ( bExp == 0 ) {
3740: if ( bSig == 0 ) {
3741: invalid:
3742: float_raise( float_flag_invalid STATUS_VAR);
3743: z.low = floatx80_default_nan_low;
3744: z.high = floatx80_default_nan_high;
3745: return z;
3746: }
3747: normalizeFloatx80Subnormal( bSig, &bExp, &bSig );
3748: }
3749: if ( aExp == 0 ) {
3750: if ( (bits64) ( aSig0<<1 ) == 0 ) return a;
3751: normalizeFloatx80Subnormal( aSig0, &aExp, &aSig0 );
3752: }
3753: bSig |= LIT64( 0x8000000000000000 );
3754: zSign = aSign;
3755: expDiff = aExp - bExp;
3756: aSig1 = 0;
3757: if ( expDiff < 0 ) {
3758: if ( expDiff < -1 ) return a;
3759: shift128Right( aSig0, 0, 1, &aSig0, &aSig1 );
3760: expDiff = 0;
3761: }
3762: q = ( bSig <= aSig0 );
3763: if ( q ) aSig0 -= bSig;
3764: expDiff -= 64;
3765: while ( 0 < expDiff ) {
3766: q = estimateDiv128To64( aSig0, aSig1, bSig );
3767: q = ( 2 < q ) ? q - 2 : 0;
3768: mul64To128( bSig, q, &term0, &term1 );
3769: sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 );
3770: shortShift128Left( aSig0, aSig1, 62, &aSig0, &aSig1 );
3771: expDiff -= 62;
3772: }
3773: expDiff += 64;
3774: if ( 0 < expDiff ) {
3775: q = estimateDiv128To64( aSig0, aSig1, bSig );
3776: q = ( 2 < q ) ? q - 2 : 0;
3777: q >>= 64 - expDiff;
3778: mul64To128( bSig, q<<( 64 - expDiff ), &term0, &term1 );
3779: sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 );
3780: shortShift128Left( 0, bSig, 64 - expDiff, &term0, &term1 );
3781: while ( le128( term0, term1, aSig0, aSig1 ) ) {
3782: ++q;
3783: sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 );
3784: }
3785: }
3786: else {
3787: term1 = 0;
3788: term0 = bSig;
3789: }
3790: sub128( term0, term1, aSig0, aSig1, &alternateASig0, &alternateASig1 );
3791: if ( lt128( alternateASig0, alternateASig1, aSig0, aSig1 )
3792: || ( eq128( alternateASig0, alternateASig1, aSig0, aSig1 )
3793: && ( q & 1 ) )
3794: ) {
3795: aSig0 = alternateASig0;
3796: aSig1 = alternateASig1;
3797: zSign = ! zSign;
3798: }
3799: return
3800: normalizeRoundAndPackFloatx80(
3801: 80, zSign, bExp + expDiff, aSig0, aSig1 STATUS_VAR );
3802:
3803: }
3804:
3805: /*----------------------------------------------------------------------------
3806: | Returns the square root of the extended double-precision floating-point
3807: | value `a'. The operation is performed according to the IEC/IEEE Standard
3808: | for Binary Floating-Point Arithmetic.
3809: *----------------------------------------------------------------------------*/
3810:
3811: floatx80 floatx80_sqrt( floatx80 a STATUS_PARAM )
3812: {
3813: flag aSign;
3814: int32 aExp, zExp;
3815: bits64 aSig0, aSig1, zSig0, zSig1, doubleZSig0;
3816: bits64 rem0, rem1, rem2, rem3, term0, term1, term2, term3;
3817: floatx80 z;
3818:
3819: aSig0 = extractFloatx80Frac( a );
3820: aExp = extractFloatx80Exp( a );
3821: aSign = extractFloatx80Sign( a );
3822: if ( aExp == 0x7FFF ) {
3823: if ( (bits64) ( aSig0<<1 ) ) return propagateFloatx80NaN( a, a STATUS_VAR );
3824: if ( ! aSign ) return a;
3825: goto invalid;
3826: }
3827: if ( aSign ) {
3828: if ( ( aExp | aSig0 ) == 0 ) return a;
3829: invalid:
3830: float_raise( float_flag_invalid STATUS_VAR);
3831: z.low = floatx80_default_nan_low;
3832: z.high = floatx80_default_nan_high;
3833: return z;
3834: }
3835: if ( aExp == 0 ) {
3836: if ( aSig0 == 0 ) return packFloatx80( 0, 0, 0 );
3837: normalizeFloatx80Subnormal( aSig0, &aExp, &aSig0 );
3838: }
3839: zExp = ( ( aExp - 0x3FFF )>>1 ) + 0x3FFF;
3840: zSig0 = estimateSqrt32( aExp, aSig0>>32 );
3841: shift128Right( aSig0, 0, 2 + ( aExp & 1 ), &aSig0, &aSig1 );
3842: zSig0 = estimateDiv128To64( aSig0, aSig1, zSig0<<32 ) + ( zSig0<<30 );
3843: doubleZSig0 = zSig0<<1;
3844: mul64To128( zSig0, zSig0, &term0, &term1 );
3845: sub128( aSig0, aSig1, term0, term1, &rem0, &rem1 );
3846: while ( (sbits64) rem0 < 0 ) {
3847: --zSig0;
3848: doubleZSig0 -= 2;
3849: add128( rem0, rem1, zSig0>>63, doubleZSig0 | 1, &rem0, &rem1 );
3850: }
3851: zSig1 = estimateDiv128To64( rem1, 0, doubleZSig0 );
3852: if ( ( zSig1 & LIT64( 0x3FFFFFFFFFFFFFFF ) ) <= 5 ) {
3853: if ( zSig1 == 0 ) zSig1 = 1;
3854: mul64To128( doubleZSig0, zSig1, &term1, &term2 );
3855: sub128( rem1, 0, term1, term2, &rem1, &rem2 );
3856: mul64To128( zSig1, zSig1, &term2, &term3 );
3857: sub192( rem1, rem2, 0, 0, term2, term3, &rem1, &rem2, &rem3 );
3858: while ( (sbits64) rem1 < 0 ) {
3859: --zSig1;
3860: shortShift128Left( 0, zSig1, 1, &term2, &term3 );
3861: term3 |= 1;
3862: term2 |= doubleZSig0;
3863: add192( rem1, rem2, rem3, 0, term2, term3, &rem1, &rem2, &rem3 );
3864: }
3865: zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 );
3866: }
3867: shortShift128Left( 0, zSig1, 1, &zSig0, &zSig1 );
3868: zSig0 |= doubleZSig0;
3869: return
3870: roundAndPackFloatx80(
3871: STATUS(floatx80_rounding_precision), 0, zExp, zSig0, zSig1 STATUS_VAR );
3872:
3873: }
3874:
3875: /*----------------------------------------------------------------------------
3876: | Returns 1 if the extended double-precision floating-point value `a' is
3877: | equal to the corresponding value `b', and 0 otherwise. The comparison is
3878: | performed according to the IEC/IEEE Standard for Binary Floating-Point
3879: | Arithmetic.
3880: *----------------------------------------------------------------------------*/
3881:
3882: flag floatx80_eq( floatx80 a, floatx80 b STATUS_PARAM )
3883: {
3884:
3885: if ( ( ( extractFloatx80Exp( a ) == 0x7FFF )
3886: && (bits64) ( extractFloatx80Frac( a )<<1 ) )
3887: || ( ( extractFloatx80Exp( b ) == 0x7FFF )
3888: && (bits64) ( extractFloatx80Frac( b )<<1 ) )
3889: ) {
3890: if ( floatx80_is_signaling_nan( a )
3891: || floatx80_is_signaling_nan( b ) ) {
3892: float_raise( float_flag_invalid STATUS_VAR);
3893: }
3894: return 0;
3895: }
3896: return
3897: ( a.low == b.low )
3898: && ( ( a.high == b.high )
3899: || ( ( a.low == 0 )
3900: && ( (bits16) ( ( a.high | b.high )<<1 ) == 0 ) )
3901: );
3902:
3903: }
3904:
3905: /*----------------------------------------------------------------------------
3906: | Returns 1 if the extended double-precision floating-point value `a' is
3907: | less than or equal to the corresponding value `b', and 0 otherwise. The
3908: | comparison is performed according to the IEC/IEEE Standard for Binary
3909: | Floating-Point Arithmetic.
3910: *----------------------------------------------------------------------------*/
3911:
3912: flag floatx80_le( floatx80 a, floatx80 b STATUS_PARAM )
3913: {
3914: flag aSign, bSign;
3915:
3916: if ( ( ( extractFloatx80Exp( a ) == 0x7FFF )
3917: && (bits64) ( extractFloatx80Frac( a )<<1 ) )
3918: || ( ( extractFloatx80Exp( b ) == 0x7FFF )
3919: && (bits64) ( extractFloatx80Frac( b )<<1 ) )
3920: ) {
3921: float_raise( float_flag_invalid STATUS_VAR);
3922: return 0;
3923: }
3924: aSign = extractFloatx80Sign( a );
3925: bSign = extractFloatx80Sign( b );
3926: if ( aSign != bSign ) {
3927: return
3928: aSign
3929: || ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
3930: == 0 );
3931: }
3932: return
3933: aSign ? le128( b.high, b.low, a.high, a.low )
3934: : le128( a.high, a.low, b.high, b.low );
3935:
3936: }
3937:
3938: /*----------------------------------------------------------------------------
3939: | Returns 1 if the extended double-precision floating-point value `a' is
3940: | less than the corresponding value `b', and 0 otherwise. The comparison
3941: | is performed according to the IEC/IEEE Standard for Binary Floating-Point
3942: | Arithmetic.
3943: *----------------------------------------------------------------------------*/
3944:
3945: flag floatx80_lt( floatx80 a, floatx80 b STATUS_PARAM )
3946: {
3947: flag aSign, bSign;
3948:
3949: if ( ( ( extractFloatx80Exp( a ) == 0x7FFF )
3950: && (bits64) ( extractFloatx80Frac( a )<<1 ) )
3951: || ( ( extractFloatx80Exp( b ) == 0x7FFF )
3952: && (bits64) ( extractFloatx80Frac( b )<<1 ) )
3953: ) {
3954: float_raise( float_flag_invalid STATUS_VAR);
3955: return 0;
3956: }
3957: aSign = extractFloatx80Sign( a );
3958: bSign = extractFloatx80Sign( b );
3959: if ( aSign != bSign ) {
3960: return
3961: aSign
3962: && ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
3963: != 0 );
3964: }
3965: return
3966: aSign ? lt128( b.high, b.low, a.high, a.low )
3967: : lt128( a.high, a.low, b.high, b.low );
3968:
3969: }
3970:
3971: /*----------------------------------------------------------------------------
3972: | Returns 1 if the extended double-precision floating-point value `a' is equal
3973: | to the corresponding value `b', and 0 otherwise. The invalid exception is
3974: | raised if either operand is a NaN. Otherwise, the comparison is performed
3975: | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
3976: *----------------------------------------------------------------------------*/
3977:
3978: flag floatx80_eq_signaling( floatx80 a, floatx80 b STATUS_PARAM )
3979: {
3980:
3981: if ( ( ( extractFloatx80Exp( a ) == 0x7FFF )
3982: && (bits64) ( extractFloatx80Frac( a )<<1 ) )
3983: || ( ( extractFloatx80Exp( b ) == 0x7FFF )
3984: && (bits64) ( extractFloatx80Frac( b )<<1 ) )
3985: ) {
3986: float_raise( float_flag_invalid STATUS_VAR);
3987: return 0;
3988: }
3989: return
3990: ( a.low == b.low )
3991: && ( ( a.high == b.high )
3992: || ( ( a.low == 0 )
3993: && ( (bits16) ( ( a.high | b.high )<<1 ) == 0 ) )
3994: );
3995:
3996: }
3997:
3998: /*----------------------------------------------------------------------------
3999: | Returns 1 if the extended double-precision floating-point value `a' is less
4000: | than or equal to the corresponding value `b', and 0 otherwise. Quiet NaNs
4001: | do not cause an exception. Otherwise, the comparison is performed according
4002: | to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
4003: *----------------------------------------------------------------------------*/
4004:
4005: flag floatx80_le_quiet( floatx80 a, floatx80 b STATUS_PARAM )
4006: {
4007: flag aSign, bSign;
4008:
4009: if ( ( ( extractFloatx80Exp( a ) == 0x7FFF )
4010: && (bits64) ( extractFloatx80Frac( a )<<1 ) )
4011: || ( ( extractFloatx80Exp( b ) == 0x7FFF )
4012: && (bits64) ( extractFloatx80Frac( b )<<1 ) )
4013: ) {
4014: if ( floatx80_is_signaling_nan( a )
4015: || floatx80_is_signaling_nan( b ) ) {
4016: float_raise( float_flag_invalid STATUS_VAR);
4017: }
4018: return 0;
4019: }
4020: aSign = extractFloatx80Sign( a );
4021: bSign = extractFloatx80Sign( b );
4022: if ( aSign != bSign ) {
4023: return
4024: aSign
4025: || ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
4026: == 0 );
4027: }
4028: return
4029: aSign ? le128( b.high, b.low, a.high, a.low )
4030: : le128( a.high, a.low, b.high, b.low );
4031:
4032: }
4033:
4034: /*----------------------------------------------------------------------------
4035: | Returns 1 if the extended double-precision floating-point value `a' is less
4036: | than the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause
4037: | an exception. Otherwise, the comparison is performed according to the
4038: | IEC/IEEE Standard for Binary Floating-Point Arithmetic.
4039: *----------------------------------------------------------------------------*/
4040:
4041: flag floatx80_lt_quiet( floatx80 a, floatx80 b STATUS_PARAM )
4042: {
4043: flag aSign, bSign;
4044:
4045: if ( ( ( extractFloatx80Exp( a ) == 0x7FFF )
4046: && (bits64) ( extractFloatx80Frac( a )<<1 ) )
4047: || ( ( extractFloatx80Exp( b ) == 0x7FFF )
4048: && (bits64) ( extractFloatx80Frac( b )<<1 ) )
4049: ) {
4050: if ( floatx80_is_signaling_nan( a )
4051: || floatx80_is_signaling_nan( b ) ) {
4052: float_raise( float_flag_invalid STATUS_VAR);
4053: }
4054: return 0;
4055: }
4056: aSign = extractFloatx80Sign( a );
4057: bSign = extractFloatx80Sign( b );
4058: if ( aSign != bSign ) {
4059: return
4060: aSign
4061: && ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
4062: != 0 );
4063: }
4064: return
4065: aSign ? lt128( b.high, b.low, a.high, a.low )
4066: : lt128( a.high, a.low, b.high, b.low );
4067:
4068: }
4069:
4070: #endif
4071:
4072: #ifdef FLOAT128
4073:
4074: /*----------------------------------------------------------------------------
4075: | Returns the result of converting the quadruple-precision floating-point
4076: | value `a' to the 32-bit two's complement integer format. The conversion
4077: | is performed according to the IEC/IEEE Standard for Binary Floating-Point
4078: | Arithmetic---which means in particular that the conversion is rounded
4079: | according to the current rounding mode. If `a' is a NaN, the largest
4080: | positive integer is returned. Otherwise, if the conversion overflows, the
4081: | largest integer with the same sign as `a' is returned.
4082: *----------------------------------------------------------------------------*/
4083:
4084: int32 float128_to_int32( float128 a STATUS_PARAM )
4085: {
4086: flag aSign;
4087: int32 aExp, shiftCount;
4088: bits64 aSig0, aSig1;
4089:
4090: aSig1 = extractFloat128Frac1( a );
4091: aSig0 = extractFloat128Frac0( a );
4092: aExp = extractFloat128Exp( a );
4093: aSign = extractFloat128Sign( a );
4094: if ( ( aExp == 0x7FFF ) && ( aSig0 | aSig1 ) ) aSign = 0;
4095: if ( aExp ) aSig0 |= LIT64( 0x0001000000000000 );
4096: aSig0 |= ( aSig1 != 0 );
4097: shiftCount = 0x4028 - aExp;
4098: if ( 0 < shiftCount ) shift64RightJamming( aSig0, shiftCount, &aSig0 );
4099: return roundAndPackInt32( aSign, aSig0 STATUS_VAR );
4100:
4101: }
4102:
4103: /*----------------------------------------------------------------------------
4104: | Returns the result of converting the quadruple-precision floating-point
4105: | value `a' to the 32-bit two's complement integer format. The conversion
4106: | is performed according to the IEC/IEEE Standard for Binary Floating-Point
4107: | Arithmetic, except that the conversion is always rounded toward zero. If
4108: | `a' is a NaN, the largest positive integer is returned. Otherwise, if the
4109: | conversion overflows, the largest integer with the same sign as `a' is
4110: | returned.
4111: *----------------------------------------------------------------------------*/
4112:
4113: int32 float128_to_int32_round_to_zero( float128 a STATUS_PARAM )
4114: {
4115: flag aSign;
4116: int32 aExp, shiftCount;
4117: bits64 aSig0, aSig1, savedASig;
4118: int32 z;
4119:
4120: aSig1 = extractFloat128Frac1( a );
4121: aSig0 = extractFloat128Frac0( a );
4122: aExp = extractFloat128Exp( a );
4123: aSign = extractFloat128Sign( a );
4124: aSig0 |= ( aSig1 != 0 );
4125: if ( 0x401E < aExp ) {
4126: if ( ( aExp == 0x7FFF ) && aSig0 ) aSign = 0;
4127: goto invalid;
4128: }
4129: else if ( aExp < 0x3FFF ) {
4130: if ( aExp || aSig0 ) STATUS(float_exception_flags) |= float_flag_inexact;
4131: return 0;
4132: }
4133: aSig0 |= LIT64( 0x0001000000000000 );
4134: shiftCount = 0x402F - aExp;
4135: savedASig = aSig0;
4136: aSig0 >>= shiftCount;
4137: z = aSig0;
4138: if ( aSign ) z = - z;
4139: if ( ( z < 0 ) ^ aSign ) {
4140: invalid:
4141: float_raise( float_flag_invalid STATUS_VAR);
4142: return aSign ? (sbits32) 0x80000000 : 0x7FFFFFFF;
4143: }
4144: if ( ( aSig0<<shiftCount ) != savedASig ) {
4145: STATUS(float_exception_flags) |= float_flag_inexact;
4146: }
4147: return z;
4148:
4149: }
4150:
4151: /*----------------------------------------------------------------------------
4152: | Returns the result of converting the quadruple-precision floating-point
4153: | value `a' to the 64-bit two's complement integer format. The conversion
4154: | is performed according to the IEC/IEEE Standard for Binary Floating-Point
4155: | Arithmetic---which means in particular that the conversion is rounded
4156: | according to the current rounding mode. If `a' is a NaN, the largest
4157: | positive integer is returned. Otherwise, if the conversion overflows, the
4158: | largest integer with the same sign as `a' is returned.
4159: *----------------------------------------------------------------------------*/
4160:
4161: int64 float128_to_int64( float128 a STATUS_PARAM )
4162: {
4163: flag aSign;
4164: int32 aExp, shiftCount;
4165: bits64 aSig0, aSig1;
4166:
4167: aSig1 = extractFloat128Frac1( a );
4168: aSig0 = extractFloat128Frac0( a );
4169: aExp = extractFloat128Exp( a );
4170: aSign = extractFloat128Sign( a );
4171: if ( aExp ) aSig0 |= LIT64( 0x0001000000000000 );
4172: shiftCount = 0x402F - aExp;
4173: if ( shiftCount <= 0 ) {
4174: if ( 0x403E < aExp ) {
4175: float_raise( float_flag_invalid STATUS_VAR);
4176: if ( ! aSign
4177: || ( ( aExp == 0x7FFF )
4178: && ( aSig1 || ( aSig0 != LIT64( 0x0001000000000000 ) ) )
4179: )
4180: ) {
4181: return LIT64( 0x7FFFFFFFFFFFFFFF );
4182: }
4183: return (sbits64) LIT64( 0x8000000000000000 );
4184: }
4185: shortShift128Left( aSig0, aSig1, - shiftCount, &aSig0, &aSig1 );
4186: }
4187: else {
4188: shift64ExtraRightJamming( aSig0, aSig1, shiftCount, &aSig0, &aSig1 );
4189: }
4190: return roundAndPackInt64( aSign, aSig0, aSig1 STATUS_VAR );
4191:
4192: }
4193:
4194: /*----------------------------------------------------------------------------
4195: | Returns the result of converting the quadruple-precision floating-point
4196: | value `a' to the 64-bit two's complement integer format. The conversion
4197: | is performed according to the IEC/IEEE Standard for Binary Floating-Point
4198: | Arithmetic, except that the conversion is always rounded toward zero.
4199: | If `a' is a NaN, the largest positive integer is returned. Otherwise, if
4200: | the conversion overflows, the largest integer with the same sign as `a' is
4201: | returned.
4202: *----------------------------------------------------------------------------*/
4203:
4204: int64 float128_to_int64_round_to_zero( float128 a STATUS_PARAM )
4205: {
4206: flag aSign;
4207: int32 aExp, shiftCount;
4208: bits64 aSig0, aSig1;
4209: int64 z;
4210:
4211: aSig1 = extractFloat128Frac1( a );
4212: aSig0 = extractFloat128Frac0( a );
4213: aExp = extractFloat128Exp( a );
4214: aSign = extractFloat128Sign( a );
4215: if ( aExp ) aSig0 |= LIT64( 0x0001000000000000 );
4216: shiftCount = aExp - 0x402F;
4217: if ( 0 < shiftCount ) {
4218: if ( 0x403E <= aExp ) {
4219: aSig0 &= LIT64( 0x0000FFFFFFFFFFFF );
4220: if ( ( a.high == LIT64( 0xC03E000000000000 ) )
4221: && ( aSig1 < LIT64( 0x0002000000000000 ) ) ) {
4222: if ( aSig1 ) STATUS(float_exception_flags) |= float_flag_inexact;
4223: }
4224: else {
4225: float_raise( float_flag_invalid STATUS_VAR);
4226: if ( ! aSign || ( ( aExp == 0x7FFF ) && ( aSig0 | aSig1 ) ) ) {
4227: return LIT64( 0x7FFFFFFFFFFFFFFF );
4228: }
4229: }
4230: return (sbits64) LIT64( 0x8000000000000000 );
4231: }
4232: z = ( aSig0<<shiftCount ) | ( aSig1>>( ( - shiftCount ) & 63 ) );
4233: if ( (bits64) ( aSig1<<shiftCount ) ) {
4234: STATUS(float_exception_flags) |= float_flag_inexact;
4235: }
4236: }
4237: else {
4238: if ( aExp < 0x3FFF ) {
4239: if ( aExp | aSig0 | aSig1 ) {
4240: STATUS(float_exception_flags) |= float_flag_inexact;
4241: }
4242: return 0;
4243: }
4244: z = aSig0>>( - shiftCount );
4245: if ( aSig1
4246: || ( shiftCount && (bits64) ( aSig0<<( shiftCount & 63 ) ) ) ) {
4247: STATUS(float_exception_flags) |= float_flag_inexact;
4248: }
4249: }
4250: if ( aSign ) z = - z;
4251: return z;
4252:
4253: }
4254:
4255: /*----------------------------------------------------------------------------
4256: | Returns the result of converting the quadruple-precision floating-point
4257: | value `a' to the single-precision floating-point format. The conversion
4258: | is performed according to the IEC/IEEE Standard for Binary Floating-Point
4259: | Arithmetic.
4260: *----------------------------------------------------------------------------*/
4261:
4262: float32 float128_to_float32( float128 a STATUS_PARAM )
4263: {
4264: flag aSign;
4265: int32 aExp;
4266: bits64 aSig0, aSig1;
4267: bits32 zSig;
4268:
4269: aSig1 = extractFloat128Frac1( a );
4270: aSig0 = extractFloat128Frac0( a );
4271: aExp = extractFloat128Exp( a );
4272: aSign = extractFloat128Sign( a );
4273: if ( aExp == 0x7FFF ) {
4274: if ( aSig0 | aSig1 ) {
4275: return commonNaNToFloat32( float128ToCommonNaN( a STATUS_VAR ) );
4276: }
4277: return packFloat32( aSign, 0xFF, 0 );
4278: }
4279: aSig0 |= ( aSig1 != 0 );
4280: shift64RightJamming( aSig0, 18, &aSig0 );
4281: zSig = aSig0;
4282: if ( aExp || zSig ) {
4283: zSig |= 0x40000000;
4284: aExp -= 0x3F81;
4285: }
4286: return roundAndPackFloat32( aSign, aExp, zSig STATUS_VAR );
4287:
4288: }
4289:
4290: /*----------------------------------------------------------------------------
4291: | Returns the result of converting the quadruple-precision floating-point
4292: | value `a' to the double-precision floating-point format. The conversion
4293: | is performed according to the IEC/IEEE Standard for Binary Floating-Point
4294: | Arithmetic.
4295: *----------------------------------------------------------------------------*/
4296:
4297: float64 float128_to_float64( float128 a STATUS_PARAM )
4298: {
4299: flag aSign;
4300: int32 aExp;
4301: bits64 aSig0, aSig1;
4302:
4303: aSig1 = extractFloat128Frac1( a );
4304: aSig0 = extractFloat128Frac0( a );
4305: aExp = extractFloat128Exp( a );
4306: aSign = extractFloat128Sign( a );
4307: if ( aExp == 0x7FFF ) {
4308: if ( aSig0 | aSig1 ) {
4309: return commonNaNToFloat64( float128ToCommonNaN( a STATUS_VAR ) );
4310: }
4311: return packFloat64( aSign, 0x7FF, 0 );
4312: }
4313: shortShift128Left( aSig0, aSig1, 14, &aSig0, &aSig1 );
4314: aSig0 |= ( aSig1 != 0 );
4315: if ( aExp || aSig0 ) {
4316: aSig0 |= LIT64( 0x4000000000000000 );
4317: aExp -= 0x3C01;
4318: }
4319: return roundAndPackFloat64( aSign, aExp, aSig0 STATUS_VAR );
4320:
4321: }
4322:
4323: #ifdef FLOATX80
4324:
4325: /*----------------------------------------------------------------------------
4326: | Returns the result of converting the quadruple-precision floating-point
4327: | value `a' to the extended double-precision floating-point format. The
4328: | conversion is performed according to the IEC/IEEE Standard for Binary
4329: | Floating-Point Arithmetic.
4330: *----------------------------------------------------------------------------*/
4331:
4332: floatx80 float128_to_floatx80( float128 a STATUS_PARAM )
4333: {
4334: flag aSign;
4335: int32 aExp;
4336: bits64 aSig0, aSig1;
4337:
4338: aSig1 = extractFloat128Frac1( a );
4339: aSig0 = extractFloat128Frac0( a );
4340: aExp = extractFloat128Exp( a );
4341: aSign = extractFloat128Sign( a );
4342: if ( aExp == 0x7FFF ) {
4343: if ( aSig0 | aSig1 ) {
4344: return commonNaNToFloatx80( float128ToCommonNaN( a STATUS_VAR ) );
4345: }
4346: return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
4347: }
4348: if ( aExp == 0 ) {
4349: if ( ( aSig0 | aSig1 ) == 0 ) return packFloatx80( aSign, 0, 0 );
4350: normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 );
4351: }
4352: else {
4353: aSig0 |= LIT64( 0x0001000000000000 );
4354: }
4355: shortShift128Left( aSig0, aSig1, 15, &aSig0, &aSig1 );
4356: return roundAndPackFloatx80( 80, aSign, aExp, aSig0, aSig1 STATUS_VAR );
4357:
4358: }
4359:
4360: #endif
4361:
4362: /*----------------------------------------------------------------------------
4363: | Rounds the quadruple-precision floating-point value `a' to an integer, and
4364: | returns the result as a quadruple-precision floating-point value. The
4365: | operation is performed according to the IEC/IEEE Standard for Binary
4366: | Floating-Point Arithmetic.
4367: *----------------------------------------------------------------------------*/
4368:
4369: float128 float128_round_to_int( float128 a STATUS_PARAM )
4370: {
4371: flag aSign;
4372: int32 aExp;
4373: bits64 lastBitMask, roundBitsMask;
4374: int8 roundingMode;
4375: float128 z;
4376:
4377: aExp = extractFloat128Exp( a );
4378: if ( 0x402F <= aExp ) {
4379: if ( 0x406F <= aExp ) {
4380: if ( ( aExp == 0x7FFF )
4381: && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) )
4382: ) {
4383: return propagateFloat128NaN( a, a STATUS_VAR );
4384: }
4385: return a;
4386: }
4387: lastBitMask = 1;
4388: lastBitMask = ( lastBitMask<<( 0x406E - aExp ) )<<1;
4389: roundBitsMask = lastBitMask - 1;
4390: z = a;
4391: roundingMode = STATUS(float_rounding_mode);
4392: if ( roundingMode == float_round_nearest_even ) {
4393: if ( lastBitMask ) {
4394: add128( z.high, z.low, 0, lastBitMask>>1, &z.high, &z.low );
4395: if ( ( z.low & roundBitsMask ) == 0 ) z.low &= ~ lastBitMask;
4396: }
4397: else {
4398: if ( (sbits64) z.low < 0 ) {
4399: ++z.high;
4400: if ( (bits64) ( z.low<<1 ) == 0 ) z.high &= ~1;
4401: }
4402: }
4403: }
4404: else if ( roundingMode != float_round_to_zero ) {
4405: if ( extractFloat128Sign( z )
4406: ^ ( roundingMode == float_round_up ) ) {
4407: add128( z.high, z.low, 0, roundBitsMask, &z.high, &z.low );
4408: }
4409: }
4410: z.low &= ~ roundBitsMask;
4411: }
4412: else {
4413: if ( aExp < 0x3FFF ) {
4414: if ( ( ( (bits64) ( a.high<<1 ) ) | a.low ) == 0 ) return a;
4415: STATUS(float_exception_flags) |= float_flag_inexact;
4416: aSign = extractFloat128Sign( a );
4417: switch ( STATUS(float_rounding_mode) ) {
4418: case float_round_nearest_even:
4419: if ( ( aExp == 0x3FFE )
4420: && ( extractFloat128Frac0( a )
4421: | extractFloat128Frac1( a ) )
4422: ) {
4423: return packFloat128( aSign, 0x3FFF, 0, 0 );
4424: }
4425: break;
4426: case float_round_down:
4427: return
4428: aSign ? packFloat128( 1, 0x3FFF, 0, 0 )
4429: : packFloat128( 0, 0, 0, 0 );
4430: case float_round_up:
4431: return
4432: aSign ? packFloat128( 1, 0, 0, 0 )
4433: : packFloat128( 0, 0x3FFF, 0, 0 );
4434: }
4435: return packFloat128( aSign, 0, 0, 0 );
4436: }
4437: lastBitMask = 1;
4438: lastBitMask <<= 0x402F - aExp;
4439: roundBitsMask = lastBitMask - 1;
4440: z.low = 0;
4441: z.high = a.high;
4442: roundingMode = STATUS(float_rounding_mode);
4443: if ( roundingMode == float_round_nearest_even ) {
4444: z.high += lastBitMask>>1;
4445: if ( ( ( z.high & roundBitsMask ) | a.low ) == 0 ) {
4446: z.high &= ~ lastBitMask;
4447: }
4448: }
4449: else if ( roundingMode != float_round_to_zero ) {
4450: if ( extractFloat128Sign( z )
4451: ^ ( roundingMode == float_round_up ) ) {
4452: z.high |= ( a.low != 0 );
4453: z.high += roundBitsMask;
4454: }
4455: }
4456: z.high &= ~ roundBitsMask;
4457: }
4458: if ( ( z.low != a.low ) || ( z.high != a.high ) ) {
4459: STATUS(float_exception_flags) |= float_flag_inexact;
4460: }
4461: return z;
4462:
4463: }
4464:
4465: /*----------------------------------------------------------------------------
4466: | Returns the result of adding the absolute values of the quadruple-precision
4467: | floating-point values `a' and `b'. If `zSign' is 1, the sum is negated
4468: | before being returned. `zSign' is ignored if the result is a NaN.
4469: | The addition is performed according to the IEC/IEEE Standard for Binary
4470: | Floating-Point Arithmetic.
4471: *----------------------------------------------------------------------------*/
4472:
4473: static float128 addFloat128Sigs( float128 a, float128 b, flag zSign STATUS_PARAM)
4474: {
4475: int32 aExp, bExp, zExp;
4476: bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2;
4477: int32 expDiff;
4478:
4479: aSig1 = extractFloat128Frac1( a );
4480: aSig0 = extractFloat128Frac0( a );
4481: aExp = extractFloat128Exp( a );
4482: bSig1 = extractFloat128Frac1( b );
4483: bSig0 = extractFloat128Frac0( b );
4484: bExp = extractFloat128Exp( b );
4485: expDiff = aExp - bExp;
4486: if ( 0 < expDiff ) {
4487: if ( aExp == 0x7FFF ) {
4488: if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, b STATUS_VAR );
4489: return a;
4490: }
4491: if ( bExp == 0 ) {
4492: --expDiff;
4493: }
4494: else {
4495: bSig0 |= LIT64( 0x0001000000000000 );
4496: }
4497: shift128ExtraRightJamming(
4498: bSig0, bSig1, 0, expDiff, &bSig0, &bSig1, &zSig2 );
4499: zExp = aExp;
4500: }
4501: else if ( expDiff < 0 ) {
4502: if ( bExp == 0x7FFF ) {
4503: if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b STATUS_VAR );
4504: return packFloat128( zSign, 0x7FFF, 0, 0 );
4505: }
4506: if ( aExp == 0 ) {
4507: ++expDiff;
4508: }
4509: else {
4510: aSig0 |= LIT64( 0x0001000000000000 );
4511: }
4512: shift128ExtraRightJamming(
4513: aSig0, aSig1, 0, - expDiff, &aSig0, &aSig1, &zSig2 );
4514: zExp = bExp;
4515: }
4516: else {
4517: if ( aExp == 0x7FFF ) {
4518: if ( aSig0 | aSig1 | bSig0 | bSig1 ) {
4519: return propagateFloat128NaN( a, b STATUS_VAR );
4520: }
4521: return a;
4522: }
4523: add128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 );
4524: if ( aExp == 0 ) return packFloat128( zSign, 0, zSig0, zSig1 );
4525: zSig2 = 0;
4526: zSig0 |= LIT64( 0x0002000000000000 );
4527: zExp = aExp;
4528: goto shiftRight1;
4529: }
4530: aSig0 |= LIT64( 0x0001000000000000 );
4531: add128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 );
4532: --zExp;
4533: if ( zSig0 < LIT64( 0x0002000000000000 ) ) goto roundAndPack;
4534: ++zExp;
4535: shiftRight1:
4536: shift128ExtraRightJamming(
4537: zSig0, zSig1, zSig2, 1, &zSig0, &zSig1, &zSig2 );
4538: roundAndPack:
4539: return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 STATUS_VAR );
4540:
4541: }
4542:
4543: /*----------------------------------------------------------------------------
4544: | Returns the result of subtracting the absolute values of the quadruple-
4545: | precision floating-point values `a' and `b'. If `zSign' is 1, the
4546: | difference is negated before being returned. `zSign' is ignored if the
4547: | result is a NaN. The subtraction is performed according to the IEC/IEEE
4548: | Standard for Binary Floating-Point Arithmetic.
4549: *----------------------------------------------------------------------------*/
4550:
4551: static float128 subFloat128Sigs( float128 a, float128 b, flag zSign STATUS_PARAM)
4552: {
4553: int32 aExp, bExp, zExp;
4554: bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1;
4555: int32 expDiff;
4556: float128 z;
4557:
4558: aSig1 = extractFloat128Frac1( a );
4559: aSig0 = extractFloat128Frac0( a );
4560: aExp = extractFloat128Exp( a );
4561: bSig1 = extractFloat128Frac1( b );
4562: bSig0 = extractFloat128Frac0( b );
4563: bExp = extractFloat128Exp( b );
4564: expDiff = aExp - bExp;
4565: shortShift128Left( aSig0, aSig1, 14, &aSig0, &aSig1 );
4566: shortShift128Left( bSig0, bSig1, 14, &bSig0, &bSig1 );
4567: if ( 0 < expDiff ) goto aExpBigger;
4568: if ( expDiff < 0 ) goto bExpBigger;
4569: if ( aExp == 0x7FFF ) {
4570: if ( aSig0 | aSig1 | bSig0 | bSig1 ) {
4571: return propagateFloat128NaN( a, b STATUS_VAR );
4572: }
4573: float_raise( float_flag_invalid STATUS_VAR);
4574: z.low = float128_default_nan_low;
4575: z.high = float128_default_nan_high;
4576: return z;
4577: }
4578: if ( aExp == 0 ) {
4579: aExp = 1;
4580: bExp = 1;
4581: }
4582: if ( bSig0 < aSig0 ) goto aBigger;
4583: if ( aSig0 < bSig0 ) goto bBigger;
4584: if ( bSig1 < aSig1 ) goto aBigger;
4585: if ( aSig1 < bSig1 ) goto bBigger;
4586: return packFloat128( STATUS(float_rounding_mode) == float_round_down, 0, 0, 0 );
4587: bExpBigger:
4588: if ( bExp == 0x7FFF ) {
4589: if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b STATUS_VAR );
4590: return packFloat128( zSign ^ 1, 0x7FFF, 0, 0 );
4591: }
4592: if ( aExp == 0 ) {
4593: ++expDiff;
4594: }
4595: else {
4596: aSig0 |= LIT64( 0x4000000000000000 );
4597: }
4598: shift128RightJamming( aSig0, aSig1, - expDiff, &aSig0, &aSig1 );
4599: bSig0 |= LIT64( 0x4000000000000000 );
4600: bBigger:
4601: sub128( bSig0, bSig1, aSig0, aSig1, &zSig0, &zSig1 );
4602: zExp = bExp;
4603: zSign ^= 1;
4604: goto normalizeRoundAndPack;
4605: aExpBigger:
4606: if ( aExp == 0x7FFF ) {
4607: if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, b STATUS_VAR );
4608: return a;
4609: }
4610: if ( bExp == 0 ) {
4611: --expDiff;
4612: }
4613: else {
4614: bSig0 |= LIT64( 0x4000000000000000 );
4615: }
4616: shift128RightJamming( bSig0, bSig1, expDiff, &bSig0, &bSig1 );
4617: aSig0 |= LIT64( 0x4000000000000000 );
4618: aBigger:
4619: sub128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 );
4620: zExp = aExp;
4621: normalizeRoundAndPack:
4622: --zExp;
4623: return normalizeRoundAndPackFloat128( zSign, zExp - 14, zSig0, zSig1 STATUS_VAR );
4624:
4625: }
4626:
4627: /*----------------------------------------------------------------------------
4628: | Returns the result of adding the quadruple-precision floating-point values
4629: | `a' and `b'. The operation is performed according to the IEC/IEEE Standard
4630: | for Binary Floating-Point Arithmetic.
4631: *----------------------------------------------------------------------------*/
4632:
4633: float128 float128_add( float128 a, float128 b STATUS_PARAM )
4634: {
4635: flag aSign, bSign;
4636:
4637: aSign = extractFloat128Sign( a );
4638: bSign = extractFloat128Sign( b );
4639: if ( aSign == bSign ) {
4640: return addFloat128Sigs( a, b, aSign STATUS_VAR );
4641: }
4642: else {
4643: return subFloat128Sigs( a, b, aSign STATUS_VAR );
4644: }
4645:
4646: }
4647:
4648: /*----------------------------------------------------------------------------
4649: | Returns the result of subtracting the quadruple-precision floating-point
4650: | values `a' and `b'. The operation is performed according to the IEC/IEEE
4651: | Standard for Binary Floating-Point Arithmetic.
4652: *----------------------------------------------------------------------------*/
4653:
4654: float128 float128_sub( float128 a, float128 b STATUS_PARAM )
4655: {
4656: flag aSign, bSign;
4657:
4658: aSign = extractFloat128Sign( a );
4659: bSign = extractFloat128Sign( b );
4660: if ( aSign == bSign ) {
4661: return subFloat128Sigs( a, b, aSign STATUS_VAR );
4662: }
4663: else {
4664: return addFloat128Sigs( a, b, aSign STATUS_VAR );
4665: }
4666:
4667: }
4668:
4669: /*----------------------------------------------------------------------------
4670: | Returns the result of multiplying the quadruple-precision floating-point
4671: | values `a' and `b'. The operation is performed according to the IEC/IEEE
4672: | Standard for Binary Floating-Point Arithmetic.
4673: *----------------------------------------------------------------------------*/
4674:
4675: float128 float128_mul( float128 a, float128 b STATUS_PARAM )
4676: {
4677: flag aSign, bSign, zSign;
4678: int32 aExp, bExp, zExp;
4679: bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2, zSig3;
4680: float128 z;
4681:
4682: aSig1 = extractFloat128Frac1( a );
4683: aSig0 = extractFloat128Frac0( a );
4684: aExp = extractFloat128Exp( a );
4685: aSign = extractFloat128Sign( a );
4686: bSig1 = extractFloat128Frac1( b );
4687: bSig0 = extractFloat128Frac0( b );
4688: bExp = extractFloat128Exp( b );
4689: bSign = extractFloat128Sign( b );
4690: zSign = aSign ^ bSign;
4691: if ( aExp == 0x7FFF ) {
4692: if ( ( aSig0 | aSig1 )
4693: || ( ( bExp == 0x7FFF ) && ( bSig0 | bSig1 ) ) ) {
4694: return propagateFloat128NaN( a, b STATUS_VAR );
4695: }
4696: if ( ( bExp | bSig0 | bSig1 ) == 0 ) goto invalid;
4697: return packFloat128( zSign, 0x7FFF, 0, 0 );
4698: }
4699: if ( bExp == 0x7FFF ) {
4700: if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b STATUS_VAR );
4701: if ( ( aExp | aSig0 | aSig1 ) == 0 ) {
4702: invalid:
4703: float_raise( float_flag_invalid STATUS_VAR);
4704: z.low = float128_default_nan_low;
4705: z.high = float128_default_nan_high;
4706: return z;
4707: }
4708: return packFloat128( zSign, 0x7FFF, 0, 0 );
4709: }
4710: if ( aExp == 0 ) {
4711: if ( ( aSig0 | aSig1 ) == 0 ) return packFloat128( zSign, 0, 0, 0 );
4712: normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 );
4713: }
4714: if ( bExp == 0 ) {
4715: if ( ( bSig0 | bSig1 ) == 0 ) return packFloat128( zSign, 0, 0, 0 );
4716: normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 );
4717: }
4718: zExp = aExp + bExp - 0x4000;
4719: aSig0 |= LIT64( 0x0001000000000000 );
4720: shortShift128Left( bSig0, bSig1, 16, &bSig0, &bSig1 );
4721: mul128To256( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1, &zSig2, &zSig3 );
4722: add128( zSig0, zSig1, aSig0, aSig1, &zSig0, &zSig1 );
4723: zSig2 |= ( zSig3 != 0 );
4724: if ( LIT64( 0x0002000000000000 ) <= zSig0 ) {
4725: shift128ExtraRightJamming(
4726: zSig0, zSig1, zSig2, 1, &zSig0, &zSig1, &zSig2 );
4727: ++zExp;
4728: }
4729: return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 STATUS_VAR );
4730:
4731: }
4732:
4733: /*----------------------------------------------------------------------------
4734: | Returns the result of dividing the quadruple-precision floating-point value
4735: | `a' by the corresponding value `b'. The operation is performed according to
4736: | the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
4737: *----------------------------------------------------------------------------*/
4738:
4739: float128 float128_div( float128 a, float128 b STATUS_PARAM )
4740: {
4741: flag aSign, bSign, zSign;
4742: int32 aExp, bExp, zExp;
4743: bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2;
4744: bits64 rem0, rem1, rem2, rem3, term0, term1, term2, term3;
4745: float128 z;
4746:
4747: aSig1 = extractFloat128Frac1( a );
4748: aSig0 = extractFloat128Frac0( a );
4749: aExp = extractFloat128Exp( a );
4750: aSign = extractFloat128Sign( a );
4751: bSig1 = extractFloat128Frac1( b );
4752: bSig0 = extractFloat128Frac0( b );
4753: bExp = extractFloat128Exp( b );
4754: bSign = extractFloat128Sign( b );
4755: zSign = aSign ^ bSign;
4756: if ( aExp == 0x7FFF ) {
4757: if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, b STATUS_VAR );
4758: if ( bExp == 0x7FFF ) {
4759: if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b STATUS_VAR );
4760: goto invalid;
4761: }
4762: return packFloat128( zSign, 0x7FFF, 0, 0 );
4763: }
4764: if ( bExp == 0x7FFF ) {
4765: if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b STATUS_VAR );
4766: return packFloat128( zSign, 0, 0, 0 );
4767: }
4768: if ( bExp == 0 ) {
4769: if ( ( bSig0 | bSig1 ) == 0 ) {
4770: if ( ( aExp | aSig0 | aSig1 ) == 0 ) {
4771: invalid:
4772: float_raise( float_flag_invalid STATUS_VAR);
4773: z.low = float128_default_nan_low;
4774: z.high = float128_default_nan_high;
4775: return z;
4776: }
4777: float_raise( float_flag_divbyzero STATUS_VAR);
4778: return packFloat128( zSign, 0x7FFF, 0, 0 );
4779: }
4780: normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 );
4781: }
4782: if ( aExp == 0 ) {
4783: if ( ( aSig0 | aSig1 ) == 0 ) return packFloat128( zSign, 0, 0, 0 );
4784: normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 );
4785: }
4786: zExp = aExp - bExp + 0x3FFD;
4787: shortShift128Left(
4788: aSig0 | LIT64( 0x0001000000000000 ), aSig1, 15, &aSig0, &aSig1 );
4789: shortShift128Left(
4790: bSig0 | LIT64( 0x0001000000000000 ), bSig1, 15, &bSig0, &bSig1 );
4791: if ( le128( bSig0, bSig1, aSig0, aSig1 ) ) {
4792: shift128Right( aSig0, aSig1, 1, &aSig0, &aSig1 );
4793: ++zExp;
4794: }
4795: zSig0 = estimateDiv128To64( aSig0, aSig1, bSig0 );
4796: mul128By64To192( bSig0, bSig1, zSig0, &term0, &term1, &term2 );
4797: sub192( aSig0, aSig1, 0, term0, term1, term2, &rem0, &rem1, &rem2 );
4798: while ( (sbits64) rem0 < 0 ) {
4799: --zSig0;
4800: add192( rem0, rem1, rem2, 0, bSig0, bSig1, &rem0, &rem1, &rem2 );
4801: }
4802: zSig1 = estimateDiv128To64( rem1, rem2, bSig0 );
4803: if ( ( zSig1 & 0x3FFF ) <= 4 ) {
4804: mul128By64To192( bSig0, bSig1, zSig1, &term1, &term2, &term3 );
4805: sub192( rem1, rem2, 0, term1, term2, term3, &rem1, &rem2, &rem3 );
4806: while ( (sbits64) rem1 < 0 ) {
4807: --zSig1;
4808: add192( rem1, rem2, rem3, 0, bSig0, bSig1, &rem1, &rem2, &rem3 );
4809: }
4810: zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 );
4811: }
4812: shift128ExtraRightJamming( zSig0, zSig1, 0, 15, &zSig0, &zSig1, &zSig2 );
4813: return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 STATUS_VAR );
4814:
4815: }
4816:
4817: /*----------------------------------------------------------------------------
4818: | Returns the remainder of the quadruple-precision floating-point value `a'
4819: | with respect to the corresponding value `b'. The operation is performed
4820: | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
4821: *----------------------------------------------------------------------------*/
4822:
4823: float128 float128_rem( float128 a, float128 b STATUS_PARAM )
4824: {
4825: flag aSign, bSign, zSign;
4826: int32 aExp, bExp, expDiff;
4827: bits64 aSig0, aSig1, bSig0, bSig1, q, term0, term1, term2;
4828: bits64 allZero, alternateASig0, alternateASig1, sigMean1;
4829: sbits64 sigMean0;
4830: float128 z;
4831:
4832: aSig1 = extractFloat128Frac1( a );
4833: aSig0 = extractFloat128Frac0( a );
4834: aExp = extractFloat128Exp( a );
4835: aSign = extractFloat128Sign( a );
4836: bSig1 = extractFloat128Frac1( b );
4837: bSig0 = extractFloat128Frac0( b );
4838: bExp = extractFloat128Exp( b );
4839: bSign = extractFloat128Sign( b );
4840: if ( aExp == 0x7FFF ) {
4841: if ( ( aSig0 | aSig1 )
4842: || ( ( bExp == 0x7FFF ) && ( bSig0 | bSig1 ) ) ) {
4843: return propagateFloat128NaN( a, b STATUS_VAR );
4844: }
4845: goto invalid;
4846: }
4847: if ( bExp == 0x7FFF ) {
4848: if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b STATUS_VAR );
4849: return a;
4850: }
4851: if ( bExp == 0 ) {
4852: if ( ( bSig0 | bSig1 ) == 0 ) {
4853: invalid:
4854: float_raise( float_flag_invalid STATUS_VAR);
4855: z.low = float128_default_nan_low;
4856: z.high = float128_default_nan_high;
4857: return z;
4858: }
4859: normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 );
4860: }
4861: if ( aExp == 0 ) {
4862: if ( ( aSig0 | aSig1 ) == 0 ) return a;
4863: normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 );
4864: }
4865: expDiff = aExp - bExp;
4866: if ( expDiff < -1 ) return a;
4867: shortShift128Left(
4868: aSig0 | LIT64( 0x0001000000000000 ),
4869: aSig1,
4870: 15 - ( expDiff < 0 ),
4871: &aSig0,
4872: &aSig1
4873: );
4874: shortShift128Left(
4875: bSig0 | LIT64( 0x0001000000000000 ), bSig1, 15, &bSig0, &bSig1 );
4876: q = le128( bSig0, bSig1, aSig0, aSig1 );
4877: if ( q ) sub128( aSig0, aSig1, bSig0, bSig1, &aSig0, &aSig1 );
4878: expDiff -= 64;
4879: while ( 0 < expDiff ) {
4880: q = estimateDiv128To64( aSig0, aSig1, bSig0 );
4881: q = ( 4 < q ) ? q - 4 : 0;
4882: mul128By64To192( bSig0, bSig1, q, &term0, &term1, &term2 );
4883: shortShift192Left( term0, term1, term2, 61, &term1, &term2, &allZero );
4884: shortShift128Left( aSig0, aSig1, 61, &aSig0, &allZero );
4885: sub128( aSig0, 0, term1, term2, &aSig0, &aSig1 );
4886: expDiff -= 61;
4887: }
4888: if ( -64 < expDiff ) {
4889: q = estimateDiv128To64( aSig0, aSig1, bSig0 );
4890: q = ( 4 < q ) ? q - 4 : 0;
4891: q >>= - expDiff;
4892: shift128Right( bSig0, bSig1, 12, &bSig0, &bSig1 );
4893: expDiff += 52;
4894: if ( expDiff < 0 ) {
4895: shift128Right( aSig0, aSig1, - expDiff, &aSig0, &aSig1 );
4896: }
4897: else {
4898: shortShift128Left( aSig0, aSig1, expDiff, &aSig0, &aSig1 );
4899: }
4900: mul128By64To192( bSig0, bSig1, q, &term0, &term1, &term2 );
4901: sub128( aSig0, aSig1, term1, term2, &aSig0, &aSig1 );
4902: }
4903: else {
4904: shift128Right( aSig0, aSig1, 12, &aSig0, &aSig1 );
4905: shift128Right( bSig0, bSig1, 12, &bSig0, &bSig1 );
4906: }
4907: do {
4908: alternateASig0 = aSig0;
4909: alternateASig1 = aSig1;
4910: ++q;
4911: sub128( aSig0, aSig1, bSig0, bSig1, &aSig0, &aSig1 );
4912: } while ( 0 <= (sbits64) aSig0 );
4913: add128(
4914: aSig0, aSig1, alternateASig0, alternateASig1, &sigMean0, &sigMean1 );
4915: if ( ( sigMean0 < 0 )
4916: || ( ( ( sigMean0 | sigMean1 ) == 0 ) && ( q & 1 ) ) ) {
4917: aSig0 = alternateASig0;
4918: aSig1 = alternateASig1;
4919: }
4920: zSign = ( (sbits64) aSig0 < 0 );
4921: if ( zSign ) sub128( 0, 0, aSig0, aSig1, &aSig0, &aSig1 );
4922: return
4923: normalizeRoundAndPackFloat128( aSign ^ zSign, bExp - 4, aSig0, aSig1 STATUS_VAR );
4924:
4925: }
4926:
4927: /*----------------------------------------------------------------------------
4928: | Returns the square root of the quadruple-precision floating-point value `a'.
4929: | The operation is performed according to the IEC/IEEE Standard for Binary
4930: | Floating-Point Arithmetic.
4931: *----------------------------------------------------------------------------*/
4932:
4933: float128 float128_sqrt( float128 a STATUS_PARAM )
4934: {
4935: flag aSign;
4936: int32 aExp, zExp;
4937: bits64 aSig0, aSig1, zSig0, zSig1, zSig2, doubleZSig0;
4938: bits64 rem0, rem1, rem2, rem3, term0, term1, term2, term3;
4939: float128 z;
4940:
4941: aSig1 = extractFloat128Frac1( a );
4942: aSig0 = extractFloat128Frac0( a );
4943: aExp = extractFloat128Exp( a );
4944: aSign = extractFloat128Sign( a );
4945: if ( aExp == 0x7FFF ) {
4946: if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, a STATUS_VAR );
4947: if ( ! aSign ) return a;
4948: goto invalid;
4949: }
4950: if ( aSign ) {
4951: if ( ( aExp | aSig0 | aSig1 ) == 0 ) return a;
4952: invalid:
4953: float_raise( float_flag_invalid STATUS_VAR);
4954: z.low = float128_default_nan_low;
4955: z.high = float128_default_nan_high;
4956: return z;
4957: }
4958: if ( aExp == 0 ) {
4959: if ( ( aSig0 | aSig1 ) == 0 ) return packFloat128( 0, 0, 0, 0 );
4960: normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 );
4961: }
4962: zExp = ( ( aExp - 0x3FFF )>>1 ) + 0x3FFE;
4963: aSig0 |= LIT64( 0x0001000000000000 );
4964: zSig0 = estimateSqrt32( aExp, aSig0>>17 );
4965: shortShift128Left( aSig0, aSig1, 13 - ( 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 );
4970: while ( (sbits64) rem0 < 0 ) {
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 & 0x1FFF ) <= 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 );
4982: while ( (sbits64) rem1 < 0 ) {
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: shift128ExtraRightJamming( zSig0, zSig1, 0, 14, &zSig0, &zSig1, &zSig2 );
4992: return roundAndPackFloat128( 0, zExp, zSig0, zSig1, zSig2 STATUS_VAR );
4993:
4994: }
4995:
4996: /*----------------------------------------------------------------------------
4997: | Returns 1 if the quadruple-precision floating-point value `a' is equal to
4998: | the corresponding value `b', and 0 otherwise. The comparison is performed
4999: | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
5000: *----------------------------------------------------------------------------*/
5001:
5002: flag float128_eq( float128 a, float128 b STATUS_PARAM )
5003: {
5004:
5005: if ( ( ( extractFloat128Exp( a ) == 0x7FFF )
5006: && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) )
5007: || ( ( extractFloat128Exp( b ) == 0x7FFF )
5008: && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) )
5009: ) {
5010: if ( float128_is_signaling_nan( a )
5011: || float128_is_signaling_nan( b ) ) {
5012: float_raise( float_flag_invalid STATUS_VAR);
5013: }
5014: return 0;
5015: }
5016: return
5017: ( a.low == b.low )
5018: && ( ( a.high == b.high )
5019: || ( ( a.low == 0 )
5020: && ( (bits64) ( ( a.high | b.high )<<1 ) == 0 ) )
5021: );
5022:
5023: }
5024:
5025: /*----------------------------------------------------------------------------
5026: | Returns 1 if the quadruple-precision floating-point value `a' is less than
5027: | or equal to the corresponding value `b', and 0 otherwise. The comparison
5028: | is performed according to the IEC/IEEE Standard for Binary Floating-Point
5029: | Arithmetic.
5030: *----------------------------------------------------------------------------*/
5031:
5032: flag float128_le( float128 a, float128 b STATUS_PARAM )
5033: {
5034: flag aSign, bSign;
5035:
5036: if ( ( ( extractFloat128Exp( a ) == 0x7FFF )
5037: && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) )
5038: || ( ( extractFloat128Exp( b ) == 0x7FFF )
5039: && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) )
5040: ) {
5041: float_raise( float_flag_invalid STATUS_VAR);
5042: return 0;
5043: }
5044: aSign = extractFloat128Sign( a );
5045: bSign = extractFloat128Sign( b );
5046: if ( aSign != bSign ) {
5047: return
5048: aSign
5049: || ( ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
5050: == 0 );
5051: }
5052: return
5053: aSign ? le128( b.high, b.low, a.high, a.low )
5054: : le128( a.high, a.low, b.high, b.low );
5055:
5056: }
5057:
5058: /*----------------------------------------------------------------------------
5059: | Returns 1 if the quadruple-precision floating-point value `a' is less than
5060: | the corresponding value `b', and 0 otherwise. The comparison is performed
5061: | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
5062: *----------------------------------------------------------------------------*/
5063:
5064: flag float128_lt( float128 a, float128 b STATUS_PARAM )
5065: {
5066: flag aSign, bSign;
5067:
5068: if ( ( ( extractFloat128Exp( a ) == 0x7FFF )
5069: && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) )
5070: || ( ( extractFloat128Exp( b ) == 0x7FFF )
5071: && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) )
5072: ) {
5073: float_raise( float_flag_invalid STATUS_VAR);
5074: return 0;
5075: }
5076: aSign = extractFloat128Sign( a );
5077: bSign = extractFloat128Sign( b );
5078: if ( aSign != bSign ) {
5079: return
5080: aSign
5081: && ( ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
5082: != 0 );
5083: }
5084: return
5085: aSign ? lt128( b.high, b.low, a.high, a.low )
5086: : lt128( a.high, a.low, b.high, b.low );
5087:
5088: }
5089:
5090: /*----------------------------------------------------------------------------
5091: | Returns 1 if the quadruple-precision floating-point value `a' is equal to
5092: | the corresponding value `b', and 0 otherwise. The invalid exception is
5093: | raised if either operand is a NaN. Otherwise, the comparison is performed
5094: | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
5095: *----------------------------------------------------------------------------*/
5096:
5097: flag float128_eq_signaling( float128 a, float128 b STATUS_PARAM )
5098: {
5099:
5100: if ( ( ( extractFloat128Exp( a ) == 0x7FFF )
5101: && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) )
5102: || ( ( extractFloat128Exp( b ) == 0x7FFF )
5103: && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) )
5104: ) {
5105: float_raise( float_flag_invalid STATUS_VAR);
5106: return 0;
5107: }
5108: return
5109: ( a.low == b.low )
5110: && ( ( a.high == b.high )
5111: || ( ( a.low == 0 )
5112: && ( (bits64) ( ( a.high | b.high )<<1 ) == 0 ) )
5113: );
5114:
5115: }
5116:
5117: /*----------------------------------------------------------------------------
5118: | Returns 1 if the quadruple-precision floating-point value `a' is less than
5119: | or equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not
5120: | cause an exception. Otherwise, the comparison is performed according to the
5121: | IEC/IEEE Standard for Binary Floating-Point Arithmetic.
5122: *----------------------------------------------------------------------------*/
5123:
5124: flag float128_le_quiet( float128 a, float128 b STATUS_PARAM )
5125: {
5126: flag aSign, bSign;
5127:
5128: if ( ( ( extractFloat128Exp( a ) == 0x7FFF )
5129: && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) )
5130: || ( ( extractFloat128Exp( b ) == 0x7FFF )
5131: && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) )
5132: ) {
5133: if ( float128_is_signaling_nan( a )
5134: || float128_is_signaling_nan( b ) ) {
5135: float_raise( float_flag_invalid STATUS_VAR);
5136: }
5137: return 0;
5138: }
5139: aSign = extractFloat128Sign( a );
5140: bSign = extractFloat128Sign( b );
5141: if ( aSign != bSign ) {
5142: return
5143: aSign
5144: || ( ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
5145: == 0 );
5146: }
5147: return
5148: aSign ? le128( b.high, b.low, a.high, a.low )
5149: : le128( a.high, a.low, b.high, b.low );
5150:
5151: }
5152:
5153: /*----------------------------------------------------------------------------
5154: | Returns 1 if the quadruple-precision floating-point value `a' is less than
5155: | the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an
5156: | exception. Otherwise, the comparison is performed according to the IEC/IEEE
5157: | Standard for Binary Floating-Point Arithmetic.
5158: *----------------------------------------------------------------------------*/
5159:
5160: flag float128_lt_quiet( float128 a, float128 b STATUS_PARAM )
5161: {
5162: flag aSign, bSign;
5163:
5164: if ( ( ( extractFloat128Exp( a ) == 0x7FFF )
5165: && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) )
5166: || ( ( extractFloat128Exp( b ) == 0x7FFF )
5167: && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) )
5168: ) {
5169: if ( float128_is_signaling_nan( a )
5170: || float128_is_signaling_nan( b ) ) {
5171: float_raise( float_flag_invalid STATUS_VAR);
5172: }
5173: return 0;
5174: }
5175: aSign = extractFloat128Sign( a );
5176: bSign = extractFloat128Sign( b );
5177: if ( aSign != bSign ) {
5178: return
5179: aSign
5180: && ( ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
5181: != 0 );
5182: }
5183: return
5184: aSign ? lt128( b.high, b.low, a.high, a.low )
5185: : lt128( a.high, a.low, b.high, b.low );
5186:
5187: }
5188:
5189: #endif
5190:
5191: /* misc functions */
5192: float32 uint32_to_float32( unsigned int a STATUS_PARAM )
5193: {
5194: return int64_to_float32(a STATUS_VAR);
5195: }
5196:
5197: float64 uint32_to_float64( unsigned int a STATUS_PARAM )
5198: {
5199: return int64_to_float64(a STATUS_VAR);
5200: }
5201:
5202: unsigned int float32_to_uint32( float32 a STATUS_PARAM )
5203: {
5204: int64_t v;
5205: unsigned int res;
5206:
5207: v = float32_to_int64(a STATUS_VAR);
5208: if (v < 0) {
5209: res = 0;
5210: float_raise( float_flag_invalid STATUS_VAR);
5211: } else if (v > 0xffffffff) {
5212: res = 0xffffffff;
5213: float_raise( float_flag_invalid STATUS_VAR);
5214: } else {
5215: res = v;
5216: }
5217: return res;
5218: }
5219:
5220: unsigned int float32_to_uint32_round_to_zero( float32 a STATUS_PARAM )
5221: {
5222: int64_t v;
5223: unsigned int res;
5224:
5225: v = float32_to_int64_round_to_zero(a STATUS_VAR);
5226: if (v < 0) {
5227: res = 0;
5228: float_raise( float_flag_invalid STATUS_VAR);
5229: } else if (v > 0xffffffff) {
5230: res = 0xffffffff;
5231: float_raise( float_flag_invalid STATUS_VAR);
5232: } else {
5233: res = v;
5234: }
5235: return res;
5236: }
5237:
5238: unsigned int float64_to_uint32( float64 a STATUS_PARAM )
5239: {
5240: int64_t v;
5241: unsigned int res;
5242:
5243: v = float64_to_int64(a STATUS_VAR);
5244: if (v < 0) {
5245: res = 0;
5246: float_raise( float_flag_invalid STATUS_VAR);
5247: } else if (v > 0xffffffff) {
5248: res = 0xffffffff;
5249: float_raise( float_flag_invalid STATUS_VAR);
5250: } else {
5251: res = v;
5252: }
5253: return res;
5254: }
5255:
5256: unsigned int float64_to_uint32_round_to_zero( float64 a STATUS_PARAM )
5257: {
5258: int64_t v;
5259: unsigned int res;
5260:
5261: v = float64_to_int64_round_to_zero(a STATUS_VAR);
5262: if (v < 0) {
5263: res = 0;
5264: float_raise( float_flag_invalid STATUS_VAR);
5265: } else if (v > 0xffffffff) {
5266: res = 0xffffffff;
5267: float_raise( float_flag_invalid STATUS_VAR);
5268: } else {
5269: res = v;
5270: }
5271: return res;
5272: }
5273:
5274: #define COMPARE(s, nan_exp) \
5275: INLINE char float ## s ## _compare_internal( float ## s a, float ## s b, \
5276: int is_quiet STATUS_PARAM ) \
5277: { \
5278: flag aSign, bSign; \
5279: \
5280: if (( ( extractFloat ## s ## Exp( a ) == nan_exp ) && \
5281: extractFloat ## s ## Frac( a ) ) || \
5282: ( ( extractFloat ## s ## Exp( b ) == nan_exp ) && \
5283: extractFloat ## s ## Frac( b ) )) { \
5284: if (!is_quiet || \
5285: float ## s ## _is_signaling_nan( a ) || \
5286: float ## s ## _is_signaling_nan( b ) ) { \
5287: float_raise( float_flag_invalid STATUS_VAR); \
5288: } \
5289: return float_relation_unordered; \
5290: } \
5291: aSign = extractFloat ## s ## Sign( a ); \
5292: bSign = extractFloat ## s ## Sign( b ); \
5293: if ( aSign != bSign ) { \
5294: if ( (bits ## s) ( ( a | b )<<1 ) == 0 ) { \
5295: /* zero case */ \
5296: return float_relation_equal; \
5297: } else { \
5298: return 1 - (2 * aSign); \
5299: } \
5300: } else { \
5301: if (a == b) { \
5302: return float_relation_equal; \
5303: } else { \
5304: return 1 - 2 * (aSign ^ ( a < b )); \
5305: } \
5306: } \
5307: } \
5308: \
5309: char float ## s ## _compare( float ## s a, float ## s b STATUS_PARAM ) \
5310: { \
5311: return float ## s ## _compare_internal(a, b, 0 STATUS_VAR); \
5312: } \
5313: \
5314: char float ## s ## _compare_quiet( float ## s a, float ## s b STATUS_PARAM ) \
5315: { \
5316: return float ## s ## _compare_internal(a, b, 1 STATUS_VAR); \
5317: }
5318:
5319: COMPARE(32, 0xff)
5320: COMPARE(64, 0x7ff)
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.