Annotation of sys/arch/hppa/spmath/dfadd.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: dfadd.c,v 1.7 2002/11/29 09:27:34 deraadt Exp $ */
! 2: /*
! 3: (c) Copyright 1986 HEWLETT-PACKARD COMPANY
! 4: To anyone who acknowledges that this file is provided "AS IS"
! 5: without any express or implied warranty:
! 6: permission to use, copy, modify, and distribute this file
! 7: for any purpose is hereby granted without fee, provided that
! 8: the above copyright notice and this notice appears in all
! 9: copies, and that the name of Hewlett-Packard Company not be
! 10: used in advertising or publicity pertaining to distribution
! 11: of the software without specific, written prior permission.
! 12: Hewlett-Packard Company makes no representations about the
! 13: suitability of this software for any purpose.
! 14: */
! 15: /* @(#)dfadd.c: Revision: 2.7.88.1 Date: 93/12/07 15:05:35 */
! 16:
! 17: #include "float.h"
! 18: #include "dbl_float.h"
! 19:
! 20: /*
! 21: * Double_add: add two double precision values.
! 22: */
! 23: int
! 24: dbl_fadd(leftptr, rightptr, dstptr, status)
! 25: dbl_floating_point *leftptr, *rightptr, *dstptr;
! 26: unsigned int *status;
! 27: {
! 28: register unsigned int signless_upper_left, signless_upper_right, save;
! 29: register unsigned int leftp1, leftp2, rightp1, rightp2, extent;
! 30: register unsigned int resultp1 = 0, resultp2 = 0;
! 31:
! 32: register int result_exponent, right_exponent, diff_exponent;
! 33: register int sign_save, jumpsize;
! 34: register int inexact = FALSE;
! 35: register int underflowtrap;
! 36:
! 37: /* Create local copies of the numbers */
! 38: Dbl_copyfromptr(leftptr,leftp1,leftp2);
! 39: Dbl_copyfromptr(rightptr,rightp1,rightp2);
! 40:
! 41: /* A zero "save" helps discover equal operands (for later), *
! 42: * and is used in swapping operands (if needed). */
! 43: Dbl_xortointp1(leftp1,rightp1,/*to*/save);
! 44:
! 45: /*
! 46: * check first operand for NaN's or infinity
! 47: */
! 48: if ((result_exponent = Dbl_exponent(leftp1)) == DBL_INFINITY_EXPONENT)
! 49: {
! 50: if (Dbl_iszero_mantissa(leftp1,leftp2))
! 51: {
! 52: if (Dbl_isnotnan(rightp1,rightp2))
! 53: {
! 54: if (Dbl_isinfinity(rightp1,rightp2) && save!=0)
! 55: {
! 56: /*
! 57: * invalid since operands are opposite signed infinity's
! 58: */
! 59: if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
! 60: Set_invalidflag();
! 61: Dbl_makequietnan(resultp1,resultp2);
! 62: Dbl_copytoptr(resultp1,resultp2,dstptr);
! 63: return(NOEXCEPTION);
! 64: }
! 65: /*
! 66: * return infinity
! 67: */
! 68: Dbl_copytoptr(leftp1,leftp2,dstptr);
! 69: return(NOEXCEPTION);
! 70: }
! 71: }
! 72: else
! 73: {
! 74: /*
! 75: * is NaN; signaling or quiet?
! 76: */
! 77: if (Dbl_isone_signaling(leftp1))
! 78: {
! 79: /* trap if INVALIDTRAP enabled */
! 80: if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
! 81: /* make NaN quiet */
! 82: Set_invalidflag();
! 83: Dbl_set_quiet(leftp1);
! 84: }
! 85: /*
! 86: * is second operand a signaling NaN?
! 87: */
! 88: else if (Dbl_is_signalingnan(rightp1))
! 89: {
! 90: /* trap if INVALIDTRAP enabled */
! 91: if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
! 92: /* make NaN quiet */
! 93: Set_invalidflag();
! 94: Dbl_set_quiet(rightp1);
! 95: Dbl_copytoptr(rightp1,rightp2,dstptr);
! 96: return(NOEXCEPTION);
! 97: }
! 98: /*
! 99: * return quiet NaN
! 100: */
! 101: Dbl_copytoptr(leftp1,leftp2,dstptr);
! 102: return(NOEXCEPTION);
! 103: }
! 104: } /* End left NaN or Infinity processing */
! 105: /*
! 106: * check second operand for NaN's or infinity
! 107: */
! 108: if (Dbl_isinfinity_exponent(rightp1))
! 109: {
! 110: if (Dbl_iszero_mantissa(rightp1,rightp2))
! 111: {
! 112: /* return infinity */
! 113: Dbl_copytoptr(rightp1,rightp2,dstptr);
! 114: return(NOEXCEPTION);
! 115: }
! 116: /*
! 117: * is NaN; signaling or quiet?
! 118: */
! 119: if (Dbl_isone_signaling(rightp1))
! 120: {
! 121: /* trap if INVALIDTRAP enabled */
! 122: if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
! 123: /* make NaN quiet */
! 124: Set_invalidflag();
! 125: Dbl_set_quiet(rightp1);
! 126: }
! 127: /*
! 128: * return quiet NaN
! 129: */
! 130: Dbl_copytoptr(rightp1,rightp2,dstptr);
! 131: return(NOEXCEPTION);
! 132: } /* End right NaN or Infinity processing */
! 133:
! 134: /* Invariant: Must be dealing with finite numbers */
! 135:
! 136: /* Compare operands by removing the sign */
! 137: Dbl_copytoint_exponentmantissap1(leftp1,signless_upper_left);
! 138: Dbl_copytoint_exponentmantissap1(rightp1,signless_upper_right);
! 139:
! 140: /* sign difference selects add or sub operation. */
! 141: if(Dbl_ismagnitudeless(leftp2,rightp2,signless_upper_left,signless_upper_right))
! 142: {
! 143: /* Set the left operand to the larger one by XOR swap *
! 144: * First finish the first word using "save" */
! 145: Dbl_xorfromintp1(save,rightp1,/*to*/rightp1);
! 146: Dbl_xorfromintp1(save,leftp1,/*to*/leftp1);
! 147: Dbl_swap_lower(leftp2,rightp2);
! 148: result_exponent = Dbl_exponent(leftp1);
! 149: }
! 150: /* Invariant: left is not smaller than right. */
! 151:
! 152: if((right_exponent = Dbl_exponent(rightp1)) == 0)
! 153: {
! 154: /* Denormalized operands. First look for zeroes */
! 155: if(Dbl_iszero_mantissa(rightp1,rightp2))
! 156: {
! 157: /* right is zero */
! 158: if(Dbl_iszero_exponentmantissa(leftp1,leftp2))
! 159: {
! 160: /* Both operands are zeros */
! 161: if(Is_rounding_mode(ROUNDMINUS))
! 162: {
! 163: Dbl_or_signs(leftp1,/*with*/rightp1);
! 164: }
! 165: else
! 166: {
! 167: Dbl_and_signs(leftp1,/*with*/rightp1);
! 168: }
! 169: }
! 170: else
! 171: {
! 172: /* Left is not a zero and must be the result. Trapped
! 173: * underflows are signaled if left is denormalized. Result
! 174: * is always exact. */
! 175: if( (result_exponent == 0) && Is_underflowtrap_enabled() )
! 176: {
! 177: /* need to normalize results mantissa */
! 178: sign_save = Dbl_signextendedsign(leftp1);
! 179: Dbl_leftshiftby1(leftp1,leftp2);
! 180: Dbl_normalize(leftp1,leftp2,result_exponent);
! 181: Dbl_set_sign(leftp1,/*using*/sign_save);
! 182: Dbl_setwrapped_exponent(leftp1,result_exponent,unfl);
! 183: Dbl_copytoptr(leftp1,leftp2,dstptr);
! 184: /* inexact = FALSE */
! 185: return(UNDERFLOWEXCEPTION);
! 186: }
! 187: }
! 188: Dbl_copytoptr(leftp1,leftp2,dstptr);
! 189: return(NOEXCEPTION);
! 190: }
! 191:
! 192: /* Neither are zeroes */
! 193: Dbl_clear_sign(rightp1); /* Exponent is already cleared */
! 194: if(result_exponent == 0 )
! 195: {
! 196: /* Both operands are denormalized. The result must be exact
! 197: * and is simply calculated. A sum could become normalized and a
! 198: * difference could cancel to a true zero. */
! 199: if( (/*signed*/int) save < 0 )
! 200: {
! 201: Dbl_subtract(leftp1,leftp2,/*minus*/rightp1,rightp2,
! 202: /*into*/resultp1,resultp2);
! 203: if(Dbl_iszero_mantissa(resultp1,resultp2))
! 204: {
! 205: if(Is_rounding_mode(ROUNDMINUS))
! 206: {
! 207: Dbl_setone_sign(resultp1);
! 208: }
! 209: else
! 210: {
! 211: Dbl_setzero_sign(resultp1);
! 212: }
! 213: Dbl_copytoptr(resultp1,resultp2,dstptr);
! 214: return(NOEXCEPTION);
! 215: }
! 216: }
! 217: else
! 218: {
! 219: Dbl_addition(leftp1,leftp2,rightp1,rightp2,
! 220: /*into*/resultp1,resultp2);
! 221: if(Dbl_isone_hidden(resultp1))
! 222: {
! 223: Dbl_copytoptr(resultp1,resultp2,dstptr);
! 224: return(NOEXCEPTION);
! 225: }
! 226: }
! 227: if(Is_underflowtrap_enabled())
! 228: {
! 229: /* need to normalize result */
! 230: sign_save = Dbl_signextendedsign(resultp1);
! 231: Dbl_leftshiftby1(resultp1,resultp2);
! 232: Dbl_normalize(resultp1,resultp2,result_exponent);
! 233: Dbl_set_sign(resultp1,/*using*/sign_save);
! 234: Dbl_setwrapped_exponent(resultp1,result_exponent,unfl);
! 235: Dbl_copytoptr(resultp1,resultp2,dstptr);
! 236: /* inexact = FALSE */
! 237: return(UNDERFLOWEXCEPTION);
! 238: }
! 239: Dbl_copytoptr(resultp1,resultp2,dstptr);
! 240: return(NOEXCEPTION);
! 241: }
! 242: right_exponent = 1; /* Set exponent to reflect different bias
! 243: * with denomalized numbers. */
! 244: }
! 245: else
! 246: {
! 247: Dbl_clear_signexponent_set_hidden(rightp1);
! 248: }
! 249: Dbl_clear_exponent_set_hidden(leftp1);
! 250: diff_exponent = result_exponent - right_exponent;
! 251:
! 252: /*
! 253: * Special case alignment of operands that would force alignment
! 254: * beyond the extent of the extension. A further optimization
! 255: * could special case this but only reduces the path length for this
! 256: * infrequent case.
! 257: */
! 258: if(diff_exponent > DBL_THRESHOLD)
! 259: {
! 260: diff_exponent = DBL_THRESHOLD;
! 261: }
! 262:
! 263: /* Align right operand by shifting to right */
! 264: Dbl_right_align(/*operand*/rightp1,rightp2,/*shifted by*/diff_exponent,
! 265: /*and lower to*/extent);
! 266:
! 267: /* Treat sum and difference of the operands separately. */
! 268: if( (/*signed*/int) save < 0 )
! 269: {
! 270: /*
! 271: * Difference of the two operands. Their can be no overflow. A
! 272: * borrow can occur out of the hidden bit and force a post
! 273: * normalization phase.
! 274: */
! 275: Dbl_subtract_withextension(leftp1,leftp2,/*minus*/rightp1,rightp2,
! 276: /*with*/extent,/*into*/resultp1,resultp2);
! 277: if(Dbl_iszero_hidden(resultp1))
! 278: {
! 279: /* Handle normalization */
! 280: /* A straight forward algorithm would now shift the result
! 281: * and extension left until the hidden bit becomes one. Not
! 282: * all of the extension bits need participate in the shift.
! 283: * Only the two most significant bits (round and guard) are
! 284: * needed. If only a single shift is needed then the guard
! 285: * bit becomes a significant low order bit and the extension
! 286: * must participate in the rounding. If more than a single
! 287: * shift is needed, then all bits to the right of the guard
! 288: * bit are zeros, and the guard bit may or may not be zero. */
! 289: sign_save = Dbl_signextendedsign(resultp1);
! 290: Dbl_leftshiftby1_withextent(resultp1,resultp2,extent,resultp1,resultp2);
! 291:
! 292: /* Need to check for a zero result. The sign and exponent
! 293: * fields have already been zeroed. The more efficient test
! 294: * of the full object can be used.
! 295: */
! 296: if(Dbl_iszero(resultp1,resultp2))
! 297: /* Must have been "x-x" or "x+(-x)". */
! 298: {
! 299: if(Is_rounding_mode(ROUNDMINUS)) Dbl_setone_sign(resultp1);
! 300: Dbl_copytoptr(resultp1,resultp2,dstptr);
! 301: return(NOEXCEPTION);
! 302: }
! 303: result_exponent--;
! 304: /* Look to see if normalization is finished. */
! 305: if(Dbl_isone_hidden(resultp1))
! 306: {
! 307: if(result_exponent==0)
! 308: {
! 309: /* Denormalized, exponent should be zero. Left operand *
! 310: * was normalized, so extent (guard, round) was zero */
! 311: goto underflow;
! 312: }
! 313: else
! 314: {
! 315: /* No further normalization is needed. */
! 316: Dbl_set_sign(resultp1,/*using*/sign_save);
! 317: Ext_leftshiftby1(extent);
! 318: goto round;
! 319: }
! 320: }
! 321:
! 322: /* Check for denormalized, exponent should be zero. Left *
! 323: * operand was normalized, so extent (guard, round) was zero */
! 324: if(!(underflowtrap = Is_underflowtrap_enabled()) &&
! 325: result_exponent==0) goto underflow;
! 326:
! 327: /* Shift extension to complete one bit of normalization and
! 328: * update exponent. */
! 329: Ext_leftshiftby1(extent);
! 330:
! 331: /* Discover first one bit to determine shift amount. Use a
! 332: * modified binary search. We have already shifted the result
! 333: * one position right and still not found a one so the remainder
! 334: * of the extension must be zero and simplifies rounding. */
! 335: /* Scan bytes */
! 336: while(Dbl_iszero_hiddenhigh7mantissa(resultp1))
! 337: {
! 338: Dbl_leftshiftby8(resultp1,resultp2);
! 339: if((result_exponent -= 8) <= 0 && !underflowtrap)
! 340: goto underflow;
! 341: }
! 342: /* Now narrow it down to the nibble */
! 343: if(Dbl_iszero_hiddenhigh3mantissa(resultp1))
! 344: {
! 345: /* The lower nibble contains the normalizing one */
! 346: Dbl_leftshiftby4(resultp1,resultp2);
! 347: if((result_exponent -= 4) <= 0 && !underflowtrap)
! 348: goto underflow;
! 349: }
! 350: /* Select case were first bit is set (already normalized)
! 351: * otherwise select the proper shift. */
! 352: if((jumpsize = Dbl_hiddenhigh3mantissa(resultp1)) > 7)
! 353: {
! 354: /* Already normalized */
! 355: if(result_exponent <= 0) goto underflow;
! 356: Dbl_set_sign(resultp1,/*using*/sign_save);
! 357: Dbl_set_exponent(resultp1,/*using*/result_exponent);
! 358: Dbl_copytoptr(resultp1,resultp2,dstptr);
! 359: return(NOEXCEPTION);
! 360: }
! 361: Dbl_sethigh4bits(resultp1,/*using*/sign_save);
! 362: switch(jumpsize)
! 363: {
! 364: case 1:
! 365: {
! 366: Dbl_leftshiftby3(resultp1,resultp2);
! 367: result_exponent -= 3;
! 368: break;
! 369: }
! 370: case 2:
! 371: case 3:
! 372: {
! 373: Dbl_leftshiftby2(resultp1,resultp2);
! 374: result_exponent -= 2;
! 375: break;
! 376: }
! 377: case 4:
! 378: case 5:
! 379: case 6:
! 380: case 7:
! 381: {
! 382: Dbl_leftshiftby1(resultp1,resultp2);
! 383: result_exponent -= 1;
! 384: break;
! 385: }
! 386: }
! 387: if(result_exponent > 0)
! 388: {
! 389: Dbl_set_exponent(resultp1,/*using*/result_exponent);
! 390: Dbl_copytoptr(resultp1,resultp2,dstptr);
! 391: return(NOEXCEPTION); /* Sign bit is already set */
! 392: }
! 393: /* Fixup potential underflows */
! 394: underflow:
! 395: if(Is_underflowtrap_enabled())
! 396: {
! 397: Dbl_set_sign(resultp1,sign_save);
! 398: Dbl_setwrapped_exponent(resultp1,result_exponent,unfl);
! 399: Dbl_copytoptr(resultp1,resultp2,dstptr);
! 400: /* inexact = FALSE */
! 401: return(UNDERFLOWEXCEPTION);
! 402: }
! 403: /*
! 404: * Since we cannot get an inexact denormalized result,
! 405: * we can now return.
! 406: */
! 407: Dbl_fix_overshift(resultp1,resultp2,(1-result_exponent),extent);
! 408: Dbl_clear_signexponent(resultp1);
! 409: Dbl_set_sign(resultp1,sign_save);
! 410: Dbl_copytoptr(resultp1,resultp2,dstptr);
! 411: return(NOEXCEPTION);
! 412: } /* end if(hidden...)... */
! 413: /* Fall through and round */
! 414: } /* end if(save < 0)... */
! 415: else
! 416: {
! 417: /* Add magnitudes */
! 418: Dbl_addition(leftp1,leftp2,rightp1,rightp2,/*to*/resultp1,resultp2);
! 419: if(Dbl_isone_hiddenoverflow(resultp1))
! 420: {
! 421: /* Prenormalization required. */
! 422: Dbl_rightshiftby1_withextent(resultp2,extent,extent);
! 423: Dbl_arithrightshiftby1(resultp1,resultp2);
! 424: result_exponent++;
! 425: } /* end if hiddenoverflow... */
! 426: } /* end else ...add magnitudes... */
! 427:
! 428: /* Round the result. If the extension is all zeros,then the result is
! 429: * exact. Otherwise round in the correct direction. No underflow is
! 430: * possible. If a postnormalization is necessary, then the mantissa is
! 431: * all zeros so no shift is needed. */
! 432: round:
! 433: if(Ext_isnotzero(extent))
! 434: {
! 435: inexact = TRUE;
! 436: switch(Rounding_mode())
! 437: {
! 438: case ROUNDNEAREST: /* The default. */
! 439: if(Ext_isone_sign(extent))
! 440: {
! 441: /* at least 1/2 ulp */
! 442: if(Ext_isnotzero_lower(extent) ||
! 443: Dbl_isone_lowmantissap2(resultp2))
! 444: {
! 445: /* either exactly half way and odd or more than 1/2ulp */
! 446: Dbl_increment(resultp1,resultp2);
! 447: }
! 448: }
! 449: break;
! 450:
! 451: case ROUNDPLUS:
! 452: if(Dbl_iszero_sign(resultp1))
! 453: {
! 454: /* Round up positive results */
! 455: Dbl_increment(resultp1,resultp2);
! 456: }
! 457: break;
! 458:
! 459: case ROUNDMINUS:
! 460: if(Dbl_isone_sign(resultp1))
! 461: {
! 462: /* Round down negative results */
! 463: Dbl_increment(resultp1,resultp2);
! 464: }
! 465:
! 466: case ROUNDZERO:;
! 467: /* truncate is simple */
! 468: } /* end switch... */
! 469: if(Dbl_isone_hiddenoverflow(resultp1)) result_exponent++;
! 470: }
! 471: if(result_exponent == DBL_INFINITY_EXPONENT)
! 472: {
! 473: /* Overflow */
! 474: if(Is_overflowtrap_enabled())
! 475: {
! 476: Dbl_setwrapped_exponent(resultp1,result_exponent,ovfl);
! 477: Dbl_copytoptr(resultp1,resultp2,dstptr);
! 478: if (inexact) {
! 479: if (Is_inexacttrap_enabled())
! 480: return(OVERFLOWEXCEPTION | INEXACTEXCEPTION);
! 481: else
! 482: Set_inexactflag();
! 483: }
! 484: return(OVERFLOWEXCEPTION);
! 485: }
! 486: else
! 487: {
! 488: inexact = TRUE;
! 489: Set_overflowflag();
! 490: Dbl_setoverflow(resultp1,resultp2);
! 491: }
! 492: }
! 493: else Dbl_set_exponent(resultp1,result_exponent);
! 494: Dbl_copytoptr(resultp1,resultp2,dstptr);
! 495: if(inexact) {
! 496: if(Is_inexacttrap_enabled())
! 497: return(INEXACTEXCEPTION);
! 498: else
! 499: Set_inexactflag();
! 500: }
! 501: return(NOEXCEPTION);
! 502: }
CVSweb