1*b466ace6Sderaadt /* $OpenBSD: dfsub.c,v 1.7 2002/11/29 09:27:34 deraadt Exp $ */
2c2feb252Smickey /*
3c2feb252Smickey (c) Copyright 1986 HEWLETT-PACKARD COMPANY
4c2feb252Smickey To anyone who acknowledges that this file is provided "AS IS"
5c2feb252Smickey without any express or implied warranty:
6c2feb252Smickey permission to use, copy, modify, and distribute this file
7c2feb252Smickey for any purpose is hereby granted without fee, provided that
8c2feb252Smickey the above copyright notice and this notice appears in all
9c2feb252Smickey copies, and that the name of Hewlett-Packard Company not be
10c2feb252Smickey used in advertising or publicity pertaining to distribution
11c2feb252Smickey of the software without specific, written prior permission.
12c2feb252Smickey Hewlett-Packard Company makes no representations about the
13c2feb252Smickey suitability of this software for any purpose.
14c2feb252Smickey */
15c2feb252Smickey /* @(#)dfsub.c: Revision: 2.8.88.1 Date: 93/12/07 15:05:48 */
16b94afd46Smickey
17c2feb252Smickey #include "float.h"
18c2feb252Smickey #include "dbl_float.h"
198a472b3eSmickey
208a472b3eSmickey /*
218a472b3eSmickey * Double_subtract: subtract two double precision values.
228a472b3eSmickey */
23b94afd46Smickey int
dbl_fsub(leftptr,rightptr,dstptr,status)248a472b3eSmickey dbl_fsub(leftptr, rightptr, dstptr, status)
258a472b3eSmickey dbl_floating_point *leftptr, *rightptr, *dstptr;
268a472b3eSmickey unsigned int *status;
278a472b3eSmickey {
288a472b3eSmickey register unsigned int signless_upper_left, signless_upper_right, save;
298a472b3eSmickey register unsigned int leftp1, leftp2, rightp1, rightp2, extent;
308a472b3eSmickey register unsigned int resultp1 = 0, resultp2 = 0;
318a472b3eSmickey
328a472b3eSmickey register int result_exponent, right_exponent, diff_exponent;
338a472b3eSmickey register int sign_save, jumpsize;
34628bbdd4Smickey register int inexact = FALSE, underflowtrap;
358a472b3eSmickey
368a472b3eSmickey /* Create local copies of the numbers */
378a472b3eSmickey Dbl_copyfromptr(leftptr,leftp1,leftp2);
388a472b3eSmickey Dbl_copyfromptr(rightptr,rightp1,rightp2);
398a472b3eSmickey
408a472b3eSmickey /* A zero "save" helps discover equal operands (for later), *
418a472b3eSmickey * and is used in swapping operands (if needed). */
428a472b3eSmickey Dbl_xortointp1(leftp1,rightp1,/*to*/save);
438a472b3eSmickey
448a472b3eSmickey /*
458a472b3eSmickey * check first operand for NaN's or infinity
468a472b3eSmickey */
478a472b3eSmickey if ((result_exponent = Dbl_exponent(leftp1)) == DBL_INFINITY_EXPONENT)
488a472b3eSmickey {
498a472b3eSmickey if (Dbl_iszero_mantissa(leftp1,leftp2))
508a472b3eSmickey {
518a472b3eSmickey if (Dbl_isnotnan(rightp1,rightp2))
528a472b3eSmickey {
538a472b3eSmickey if (Dbl_isinfinity(rightp1,rightp2) && save==0)
548a472b3eSmickey {
558a472b3eSmickey /*
568a472b3eSmickey * invalid since operands are same signed infinity's
578a472b3eSmickey */
588a472b3eSmickey if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
598a472b3eSmickey Set_invalidflag();
608a472b3eSmickey Dbl_makequietnan(resultp1,resultp2);
618a472b3eSmickey Dbl_copytoptr(resultp1,resultp2,dstptr);
628a472b3eSmickey return(NOEXCEPTION);
638a472b3eSmickey }
648a472b3eSmickey /*
658a472b3eSmickey * return infinity
668a472b3eSmickey */
678a472b3eSmickey Dbl_copytoptr(leftp1,leftp2,dstptr);
688a472b3eSmickey return(NOEXCEPTION);
698a472b3eSmickey }
708a472b3eSmickey }
718a472b3eSmickey else
728a472b3eSmickey {
738a472b3eSmickey /*
748a472b3eSmickey * is NaN; signaling or quiet?
758a472b3eSmickey */
768a472b3eSmickey if (Dbl_isone_signaling(leftp1))
778a472b3eSmickey {
788a472b3eSmickey /* trap if INVALIDTRAP enabled */
798a472b3eSmickey if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
808a472b3eSmickey /* make NaN quiet */
818a472b3eSmickey Set_invalidflag();
828a472b3eSmickey Dbl_set_quiet(leftp1);
838a472b3eSmickey }
848a472b3eSmickey /*
858a472b3eSmickey * is second operand a signaling NaN?
868a472b3eSmickey */
878a472b3eSmickey else if (Dbl_is_signalingnan(rightp1))
888a472b3eSmickey {
898a472b3eSmickey /* trap if INVALIDTRAP enabled */
908a472b3eSmickey if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
918a472b3eSmickey /* make NaN quiet */
928a472b3eSmickey Set_invalidflag();
938a472b3eSmickey Dbl_set_quiet(rightp1);
948a472b3eSmickey Dbl_copytoptr(rightp1,rightp2,dstptr);
958a472b3eSmickey return(NOEXCEPTION);
968a472b3eSmickey }
978a472b3eSmickey /*
988a472b3eSmickey * return quiet NaN
998a472b3eSmickey */
1008a472b3eSmickey Dbl_copytoptr(leftp1,leftp2,dstptr);
1018a472b3eSmickey return(NOEXCEPTION);
1028a472b3eSmickey }
1038a472b3eSmickey } /* End left NaN or Infinity processing */
1048a472b3eSmickey /*
1058a472b3eSmickey * check second operand for NaN's or infinity
1068a472b3eSmickey */
1078a472b3eSmickey if (Dbl_isinfinity_exponent(rightp1))
1088a472b3eSmickey {
1098a472b3eSmickey if (Dbl_iszero_mantissa(rightp1,rightp2))
1108a472b3eSmickey {
1118a472b3eSmickey /* return infinity */
1128a472b3eSmickey Dbl_invert_sign(rightp1);
1138a472b3eSmickey Dbl_copytoptr(rightp1,rightp2,dstptr);
1148a472b3eSmickey return(NOEXCEPTION);
1158a472b3eSmickey }
1168a472b3eSmickey /*
1178a472b3eSmickey * is NaN; signaling or quiet?
1188a472b3eSmickey */
1198a472b3eSmickey if (Dbl_isone_signaling(rightp1))
1208a472b3eSmickey {
1218a472b3eSmickey /* trap if INVALIDTRAP enabled */
1228a472b3eSmickey if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
1238a472b3eSmickey /* make NaN quiet */
1248a472b3eSmickey Set_invalidflag();
1258a472b3eSmickey Dbl_set_quiet(rightp1);
1268a472b3eSmickey }
1278a472b3eSmickey /*
1288a472b3eSmickey * return quiet NaN
1298a472b3eSmickey */
1308a472b3eSmickey Dbl_copytoptr(rightp1,rightp2,dstptr);
1318a472b3eSmickey return(NOEXCEPTION);
1328a472b3eSmickey } /* End right NaN or Infinity processing */
1338a472b3eSmickey
1348a472b3eSmickey /* Invariant: Must be dealing with finite numbers */
1358a472b3eSmickey
1368a472b3eSmickey /* Compare operands by removing the sign */
1378a472b3eSmickey Dbl_copytoint_exponentmantissap1(leftp1,signless_upper_left);
1388a472b3eSmickey Dbl_copytoint_exponentmantissap1(rightp1,signless_upper_right);
1398a472b3eSmickey
1408a472b3eSmickey /* sign difference selects add or sub operation. */
1418a472b3eSmickey if(Dbl_ismagnitudeless(leftp2,rightp2,signless_upper_left,signless_upper_right))
1428a472b3eSmickey {
1438a472b3eSmickey /* Set the left operand to the larger one by XOR swap *
1448a472b3eSmickey * First finish the first word using "save" */
1458a472b3eSmickey Dbl_xorfromintp1(save,rightp1,/*to*/rightp1);
1468a472b3eSmickey Dbl_xorfromintp1(save,leftp1,/*to*/leftp1);
1478a472b3eSmickey Dbl_swap_lower(leftp2,rightp2);
1488a472b3eSmickey result_exponent = Dbl_exponent(leftp1);
1498a472b3eSmickey Dbl_invert_sign(leftp1);
1508a472b3eSmickey }
1518a472b3eSmickey /* Invariant: left is not smaller than right. */
1528a472b3eSmickey
1538a472b3eSmickey if((right_exponent = Dbl_exponent(rightp1)) == 0)
1548a472b3eSmickey {
1558a472b3eSmickey /* Denormalized operands. First look for zeroes */
1568a472b3eSmickey if(Dbl_iszero_mantissa(rightp1,rightp2))
1578a472b3eSmickey {
1588a472b3eSmickey /* right is zero */
1598a472b3eSmickey if(Dbl_iszero_exponentmantissa(leftp1,leftp2))
1608a472b3eSmickey {
1618a472b3eSmickey /* Both operands are zeros */
1628a472b3eSmickey Dbl_invert_sign(rightp1);
1638a472b3eSmickey if(Is_rounding_mode(ROUNDMINUS))
1648a472b3eSmickey {
1658a472b3eSmickey Dbl_or_signs(leftp1,/*with*/rightp1);
1668a472b3eSmickey }
1678a472b3eSmickey else
1688a472b3eSmickey {
1698a472b3eSmickey Dbl_and_signs(leftp1,/*with*/rightp1);
1708a472b3eSmickey }
1718a472b3eSmickey }
1728a472b3eSmickey else
1738a472b3eSmickey {
1748a472b3eSmickey /* Left is not a zero and must be the result. Trapped
1758a472b3eSmickey * underflows are signaled if left is denormalized. Result
1768a472b3eSmickey * is always exact. */
1778a472b3eSmickey if( (result_exponent == 0) && Is_underflowtrap_enabled() )
1788a472b3eSmickey {
1798a472b3eSmickey /* need to normalize results mantissa */
1808a472b3eSmickey sign_save = Dbl_signextendedsign(leftp1);
1818a472b3eSmickey Dbl_leftshiftby1(leftp1,leftp2);
1828a472b3eSmickey Dbl_normalize(leftp1,leftp2,result_exponent);
1838a472b3eSmickey Dbl_set_sign(leftp1,/*using*/sign_save);
1848a472b3eSmickey Dbl_setwrapped_exponent(leftp1,result_exponent,unfl);
1858a472b3eSmickey Dbl_copytoptr(leftp1,leftp2,dstptr);
1868a472b3eSmickey /* inexact = FALSE */
1878a472b3eSmickey return(UNDERFLOWEXCEPTION);
1888a472b3eSmickey }
1898a472b3eSmickey }
1908a472b3eSmickey Dbl_copytoptr(leftp1,leftp2,dstptr);
1918a472b3eSmickey return(NOEXCEPTION);
1928a472b3eSmickey }
1938a472b3eSmickey
1948a472b3eSmickey /* Neither are zeroes */
1958a472b3eSmickey Dbl_clear_sign(rightp1); /* Exponent is already cleared */
1968a472b3eSmickey if(result_exponent == 0 )
1978a472b3eSmickey {
1988a472b3eSmickey /* Both operands are denormalized. The result must be exact
1998a472b3eSmickey * and is simply calculated. A sum could become normalized and a
2008a472b3eSmickey * difference could cancel to a true zero. */
2018a472b3eSmickey if( (/*signed*/int) save >= 0 )
2028a472b3eSmickey {
2038a472b3eSmickey Dbl_subtract(leftp1,leftp2,/*minus*/rightp1,rightp2,
2048a472b3eSmickey /*into*/resultp1,resultp2);
2058a472b3eSmickey if(Dbl_iszero_mantissa(resultp1,resultp2))
2068a472b3eSmickey {
2078a472b3eSmickey if(Is_rounding_mode(ROUNDMINUS))
2088a472b3eSmickey {
2098a472b3eSmickey Dbl_setone_sign(resultp1);
2108a472b3eSmickey }
2118a472b3eSmickey else
2128a472b3eSmickey {
2138a472b3eSmickey Dbl_setzero_sign(resultp1);
2148a472b3eSmickey }
2158a472b3eSmickey Dbl_copytoptr(resultp1,resultp2,dstptr);
2168a472b3eSmickey return(NOEXCEPTION);
2178a472b3eSmickey }
2188a472b3eSmickey }
2198a472b3eSmickey else
2208a472b3eSmickey {
2218a472b3eSmickey Dbl_addition(leftp1,leftp2,rightp1,rightp2,
2228a472b3eSmickey /*into*/resultp1,resultp2);
2238a472b3eSmickey if(Dbl_isone_hidden(resultp1))
2248a472b3eSmickey {
2258a472b3eSmickey Dbl_copytoptr(resultp1,resultp2,dstptr);
2268a472b3eSmickey return(NOEXCEPTION);
2278a472b3eSmickey }
2288a472b3eSmickey }
2298a472b3eSmickey if(Is_underflowtrap_enabled())
2308a472b3eSmickey {
2318a472b3eSmickey /* need to normalize result */
2328a472b3eSmickey sign_save = Dbl_signextendedsign(resultp1);
2338a472b3eSmickey Dbl_leftshiftby1(resultp1,resultp2);
2348a472b3eSmickey Dbl_normalize(resultp1,resultp2,result_exponent);
2358a472b3eSmickey Dbl_set_sign(resultp1,/*using*/sign_save);
2368a472b3eSmickey Dbl_setwrapped_exponent(resultp1,result_exponent,unfl);
2378a472b3eSmickey Dbl_copytoptr(resultp1,resultp2,dstptr);
2388a472b3eSmickey /* inexact = FALSE */
2398a472b3eSmickey return(UNDERFLOWEXCEPTION);
2408a472b3eSmickey }
2418a472b3eSmickey Dbl_copytoptr(resultp1,resultp2,dstptr);
2428a472b3eSmickey return(NOEXCEPTION);
2438a472b3eSmickey }
2448a472b3eSmickey right_exponent = 1; /* Set exponent to reflect different bias
2458a472b3eSmickey * with denomalized numbers. */
2468a472b3eSmickey }
2478a472b3eSmickey else
2488a472b3eSmickey {
2498a472b3eSmickey Dbl_clear_signexponent_set_hidden(rightp1);
2508a472b3eSmickey }
2518a472b3eSmickey Dbl_clear_exponent_set_hidden(leftp1);
2528a472b3eSmickey diff_exponent = result_exponent - right_exponent;
2538a472b3eSmickey
2548a472b3eSmickey /*
2558a472b3eSmickey * Special case alignment of operands that would force alignment
2568a472b3eSmickey * beyond the extent of the extension. A further optimization
2578a472b3eSmickey * could special case this but only reduces the path length for this
2588a472b3eSmickey * infrequent case.
2598a472b3eSmickey */
2608a472b3eSmickey if(diff_exponent > DBL_THRESHOLD)
2618a472b3eSmickey {
2628a472b3eSmickey diff_exponent = DBL_THRESHOLD;
2638a472b3eSmickey }
2648a472b3eSmickey
2658a472b3eSmickey /* Align right operand by shifting to right */
2668a472b3eSmickey Dbl_right_align(/*operand*/rightp1,rightp2,/*shifted by*/diff_exponent,
2678a472b3eSmickey /*and lower to*/extent);
2688a472b3eSmickey
2698a472b3eSmickey /* Treat sum and difference of the operands separately. */
2708a472b3eSmickey if( (/*signed*/int) save >= 0 )
2718a472b3eSmickey {
2728a472b3eSmickey /*
2738a472b3eSmickey * Difference of the two operands. Their can be no overflow. A
2748a472b3eSmickey * borrow can occur out of the hidden bit and force a post
2758a472b3eSmickey * normalization phase.
2768a472b3eSmickey */
2778a472b3eSmickey Dbl_subtract_withextension(leftp1,leftp2,/*minus*/rightp1,rightp2,
2788a472b3eSmickey /*with*/extent,/*into*/resultp1,resultp2);
2798a472b3eSmickey if(Dbl_iszero_hidden(resultp1))
2808a472b3eSmickey {
2818a472b3eSmickey /* Handle normalization */
282*b466ace6Sderaadt /* A straight forward algorithm would now shift the result
2838a472b3eSmickey * and extension left until the hidden bit becomes one. Not
2848a472b3eSmickey * all of the extension bits need participate in the shift.
2858a472b3eSmickey * Only the two most significant bits (round and guard) are
2868a472b3eSmickey * needed. If only a single shift is needed then the guard
2878a472b3eSmickey * bit becomes a significant low order bit and the extension
2888a472b3eSmickey * must participate in the rounding. If more than a single
2898a472b3eSmickey * shift is needed, then all bits to the right of the guard
2908a472b3eSmickey * bit are zeros, and the guard bit may or may not be zero. */
2918a472b3eSmickey sign_save = Dbl_signextendedsign(resultp1);
2928a472b3eSmickey Dbl_leftshiftby1_withextent(resultp1,resultp2,extent,resultp1,resultp2);
2938a472b3eSmickey
2948a472b3eSmickey /* Need to check for a zero result. The sign and exponent
2958a472b3eSmickey * fields have already been zeroed. The more efficient test
2968a472b3eSmickey * of the full object can be used.
2978a472b3eSmickey */
2988a472b3eSmickey if(Dbl_iszero(resultp1,resultp2))
2998a472b3eSmickey /* Must have been "x-x" or "x+(-x)". */
3008a472b3eSmickey {
3018a472b3eSmickey if(Is_rounding_mode(ROUNDMINUS)) Dbl_setone_sign(resultp1);
3028a472b3eSmickey Dbl_copytoptr(resultp1,resultp2,dstptr);
3038a472b3eSmickey return(NOEXCEPTION);
3048a472b3eSmickey }
3058a472b3eSmickey result_exponent--;
3068a472b3eSmickey /* Look to see if normalization is finished. */
307628bbdd4Smickey if(Dbl_isone_hidden(resultp1)) {
308628bbdd4Smickey if(result_exponent==0) {
3098a472b3eSmickey /* Denormalized, exponent should be zero. Left operand *
3108a472b3eSmickey * was normalized, so extent (guard, round) was zero */
3118a472b3eSmickey goto underflow;
312628bbdd4Smickey } else {
3138a472b3eSmickey /* No further normalization is needed. */
3148a472b3eSmickey Dbl_set_sign(resultp1,/*using*/sign_save);
3158a472b3eSmickey Ext_leftshiftby1(extent);
3168a472b3eSmickey goto round;
3178a472b3eSmickey }
3188a472b3eSmickey }
3198a472b3eSmickey
3208a472b3eSmickey /* Check for denormalized, exponent should be zero. Left *
3218a472b3eSmickey * operand was normalized, so extent (guard, round) was zero */
3228a472b3eSmickey if(!(underflowtrap = Is_underflowtrap_enabled()) &&
3238a472b3eSmickey result_exponent==0) goto underflow;
3248a472b3eSmickey
3258a472b3eSmickey /* Shift extension to complete one bit of normalization and
3268a472b3eSmickey * update exponent. */
3278a472b3eSmickey Ext_leftshiftby1(extent);
3288a472b3eSmickey
3298a472b3eSmickey /* Discover first one bit to determine shift amount. Use a
3308a472b3eSmickey * modified binary search. We have already shifted the result
3318a472b3eSmickey * one position right and still not found a one so the remainder
3328a472b3eSmickey * of the extension must be zero and simplifies rounding. */
3338a472b3eSmickey /* Scan bytes */
3348a472b3eSmickey while(Dbl_iszero_hiddenhigh7mantissa(resultp1))
3358a472b3eSmickey {
3368a472b3eSmickey Dbl_leftshiftby8(resultp1,resultp2);
3378a472b3eSmickey if((result_exponent -= 8) <= 0 && !underflowtrap)
3388a472b3eSmickey goto underflow;
3398a472b3eSmickey }
3408a472b3eSmickey /* Now narrow it down to the nibble */
3418a472b3eSmickey if(Dbl_iszero_hiddenhigh3mantissa(resultp1))
3428a472b3eSmickey {
3438a472b3eSmickey /* The lower nibble contains the normalizing one */
3448a472b3eSmickey Dbl_leftshiftby4(resultp1,resultp2);
3458a472b3eSmickey if((result_exponent -= 4) <= 0 && !underflowtrap)
3468a472b3eSmickey goto underflow;
3478a472b3eSmickey }
3488a472b3eSmickey /* Select case were first bit is set (already normalized)
3498a472b3eSmickey * otherwise select the proper shift. */
3508a472b3eSmickey if((jumpsize = Dbl_hiddenhigh3mantissa(resultp1)) > 7)
3518a472b3eSmickey {
3528a472b3eSmickey /* Already normalized */
3538a472b3eSmickey if(result_exponent <= 0) goto underflow;
3548a472b3eSmickey Dbl_set_sign(resultp1,/*using*/sign_save);
3558a472b3eSmickey Dbl_set_exponent(resultp1,/*using*/result_exponent);
3568a472b3eSmickey Dbl_copytoptr(resultp1,resultp2,dstptr);
3578a472b3eSmickey return(NOEXCEPTION);
3588a472b3eSmickey }
3598a472b3eSmickey Dbl_sethigh4bits(resultp1,/*using*/sign_save);
3608a472b3eSmickey switch(jumpsize)
3618a472b3eSmickey {
3628a472b3eSmickey case 1:
3638a472b3eSmickey {
3648a472b3eSmickey Dbl_leftshiftby3(resultp1,resultp2);
3658a472b3eSmickey result_exponent -= 3;
3668a472b3eSmickey break;
3678a472b3eSmickey }
3688a472b3eSmickey case 2:
3698a472b3eSmickey case 3:
3708a472b3eSmickey {
3718a472b3eSmickey Dbl_leftshiftby2(resultp1,resultp2);
3728a472b3eSmickey result_exponent -= 2;
3738a472b3eSmickey break;
3748a472b3eSmickey }
3758a472b3eSmickey case 4:
3768a472b3eSmickey case 5:
3778a472b3eSmickey case 6:
3788a472b3eSmickey case 7:
3798a472b3eSmickey {
3808a472b3eSmickey Dbl_leftshiftby1(resultp1,resultp2);
3818a472b3eSmickey result_exponent -= 1;
3828a472b3eSmickey break;
3838a472b3eSmickey }
3848a472b3eSmickey }
3858a472b3eSmickey if(result_exponent > 0)
3868a472b3eSmickey {
3878a472b3eSmickey Dbl_set_exponent(resultp1,/*using*/result_exponent);
3888a472b3eSmickey Dbl_copytoptr(resultp1,resultp2,dstptr);
3898a472b3eSmickey return(NOEXCEPTION); /* Sign bit is already set */
3908a472b3eSmickey }
3918a472b3eSmickey /* Fixup potential underflows */
3928a472b3eSmickey underflow:
3938a472b3eSmickey if(Is_underflowtrap_enabled())
3948a472b3eSmickey {
3958a472b3eSmickey Dbl_set_sign(resultp1,sign_save);
3968a472b3eSmickey Dbl_setwrapped_exponent(resultp1,result_exponent,unfl);
3978a472b3eSmickey Dbl_copytoptr(resultp1,resultp2,dstptr);
3988a472b3eSmickey /* inexact = FALSE */
3998a472b3eSmickey return(UNDERFLOWEXCEPTION);
4008a472b3eSmickey }
4018a472b3eSmickey /*
4028a472b3eSmickey * Since we cannot get an inexact denormalized result,
4038a472b3eSmickey * we can now return.
4048a472b3eSmickey */
4058a472b3eSmickey Dbl_fix_overshift(resultp1,resultp2,(1-result_exponent),extent);
4068a472b3eSmickey Dbl_clear_signexponent(resultp1);
4078a472b3eSmickey Dbl_set_sign(resultp1,sign_save);
4088a472b3eSmickey Dbl_copytoptr(resultp1,resultp2,dstptr);
4098a472b3eSmickey return(NOEXCEPTION);
4108a472b3eSmickey } /* end if(hidden...)... */
4118a472b3eSmickey /* Fall through and round */
4128a472b3eSmickey } /* end if(save >= 0)... */
4138a472b3eSmickey else
4148a472b3eSmickey {
4158a472b3eSmickey /* Subtract magnitudes */
4168a472b3eSmickey Dbl_addition(leftp1,leftp2,rightp1,rightp2,/*to*/resultp1,resultp2);
4178a472b3eSmickey if(Dbl_isone_hiddenoverflow(resultp1))
4188a472b3eSmickey {
4198a472b3eSmickey /* Prenormalization required. */
4208a472b3eSmickey Dbl_rightshiftby1_withextent(resultp2,extent,extent);
4218a472b3eSmickey Dbl_arithrightshiftby1(resultp1,resultp2);
4228a472b3eSmickey result_exponent++;
4238a472b3eSmickey } /* end if hiddenoverflow... */
4248a472b3eSmickey } /* end else ...subtract magnitudes... */
4258a472b3eSmickey
4268a472b3eSmickey /* Round the result. If the extension is all zeros,then the result is
4278a472b3eSmickey * exact. Otherwise round in the correct direction. No underflow is
4288a472b3eSmickey * possible. If a postnormalization is necessary, then the mantissa is
4298a472b3eSmickey * all zeros so no shift is needed. */
4308a472b3eSmickey round:
4318a472b3eSmickey if(Ext_isnotzero(extent))
4328a472b3eSmickey {
4338a472b3eSmickey inexact = TRUE;
4348a472b3eSmickey switch(Rounding_mode())
4358a472b3eSmickey {
4368a472b3eSmickey case ROUNDNEAREST: /* The default. */
4378a472b3eSmickey if(Ext_isone_sign(extent))
4388a472b3eSmickey {
4398a472b3eSmickey /* at least 1/2 ulp */
4408a472b3eSmickey if(Ext_isnotzero_lower(extent) ||
4418a472b3eSmickey Dbl_isone_lowmantissap2(resultp2))
4428a472b3eSmickey {
4438a472b3eSmickey /* either exactly half way and odd or more than 1/2ulp */
4448a472b3eSmickey Dbl_increment(resultp1,resultp2);
4458a472b3eSmickey }
4468a472b3eSmickey }
4478a472b3eSmickey break;
4488a472b3eSmickey
4498a472b3eSmickey case ROUNDPLUS:
4508a472b3eSmickey if(Dbl_iszero_sign(resultp1))
4518a472b3eSmickey {
4528a472b3eSmickey /* Round up positive results */
4538a472b3eSmickey Dbl_increment(resultp1,resultp2);
4548a472b3eSmickey }
4558a472b3eSmickey break;
4568a472b3eSmickey
4578a472b3eSmickey case ROUNDMINUS:
4588a472b3eSmickey if(Dbl_isone_sign(resultp1))
4598a472b3eSmickey {
4608a472b3eSmickey /* Round down negative results */
4618a472b3eSmickey Dbl_increment(resultp1,resultp2);
4628a472b3eSmickey }
4638a472b3eSmickey
4648a472b3eSmickey case ROUNDZERO:;
4658a472b3eSmickey /* truncate is simple */
4668a472b3eSmickey } /* end switch... */
4678a472b3eSmickey if(Dbl_isone_hiddenoverflow(resultp1)) result_exponent++;
4688a472b3eSmickey }
4698a472b3eSmickey if(result_exponent == DBL_INFINITY_EXPONENT)
4708a472b3eSmickey {
4718a472b3eSmickey /* Overflow */
4728a472b3eSmickey if(Is_overflowtrap_enabled())
4738a472b3eSmickey {
4748a472b3eSmickey Dbl_setwrapped_exponent(resultp1,result_exponent,ovfl);
4758a472b3eSmickey Dbl_copytoptr(resultp1,resultp2,dstptr);
476b94afd46Smickey if (inexact) {
4778a472b3eSmickey if (Is_inexacttrap_enabled())
4788a472b3eSmickey return(OVERFLOWEXCEPTION | INEXACTEXCEPTION);
479b94afd46Smickey else
480b94afd46Smickey Set_inexactflag();
481b94afd46Smickey }
4828a472b3eSmickey return(OVERFLOWEXCEPTION);
4838a472b3eSmickey }
4848a472b3eSmickey else
4858a472b3eSmickey {
4868a472b3eSmickey inexact = TRUE;
4878a472b3eSmickey Set_overflowflag();
4888a472b3eSmickey Dbl_setoverflow(resultp1,resultp2);
4898a472b3eSmickey }
4908a472b3eSmickey }
4918a472b3eSmickey else Dbl_set_exponent(resultp1,result_exponent);
4928a472b3eSmickey Dbl_copytoptr(resultp1,resultp2,dstptr);
493b94afd46Smickey if(inexact) {
494b94afd46Smickey if(Is_inexacttrap_enabled())
495b94afd46Smickey return(INEXACTEXCEPTION);
496b94afd46Smickey else
497b94afd46Smickey Set_inexactflag();
498b94afd46Smickey }
4998a472b3eSmickey return(NOEXCEPTION);
5008a472b3eSmickey }
501