Annotation of sys/arch/hppa/spmath/dfdiv.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: dfdiv.c,v 1.5 2002/05/07 22:19:30 mickey 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: /* @(#)dfdiv.c: Revision: 2.11.88.1 Date: 93/12/07 15:05:39 */
! 16:
! 17: #include "float.h"
! 18: #include "dbl_float.h"
! 19:
! 20: /*
! 21: * Double Precision Floating-point Divide
! 22: */
! 23:
! 24: int
! 25: dbl_fdiv(srcptr1,srcptr2,dstptr,status)
! 26: dbl_floating_point *srcptr1, *srcptr2, *dstptr;
! 27: unsigned int *status;
! 28: {
! 29: register unsigned int opnd1p1, opnd1p2, opnd2p1, opnd2p2;
! 30: register unsigned int opnd3p1, opnd3p2, resultp1, resultp2;
! 31: register int dest_exponent, count;
! 32: register int inexact = FALSE, guardbit = FALSE, stickybit = FALSE;
! 33: int is_tiny;
! 34:
! 35: Dbl_copyfromptr(srcptr1,opnd1p1,opnd1p2);
! 36: Dbl_copyfromptr(srcptr2,opnd2p1,opnd2p2);
! 37: /*
! 38: * set sign bit of result
! 39: */
! 40: if (Dbl_sign(opnd1p1) ^ Dbl_sign(opnd2p1))
! 41: Dbl_setnegativezerop1(resultp1);
! 42: else Dbl_setzerop1(resultp1);
! 43: /*
! 44: * check first operand for NaN's or infinity
! 45: */
! 46: if (Dbl_isinfinity_exponent(opnd1p1)) {
! 47: if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
! 48: if (Dbl_isnotnan(opnd2p1,opnd2p2)) {
! 49: if (Dbl_isinfinity(opnd2p1,opnd2p2)) {
! 50: /*
! 51: * invalid since both operands
! 52: * are infinity
! 53: */
! 54: if (Is_invalidtrap_enabled())
! 55: return(INVALIDEXCEPTION);
! 56: Set_invalidflag();
! 57: Dbl_makequietnan(resultp1,resultp2);
! 58: Dbl_copytoptr(resultp1,resultp2,dstptr);
! 59: return(NOEXCEPTION);
! 60: }
! 61: /*
! 62: * return infinity
! 63: */
! 64: Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
! 65: Dbl_copytoptr(resultp1,resultp2,dstptr);
! 66: return(NOEXCEPTION);
! 67: }
! 68: }
! 69: else {
! 70: /*
! 71: * is NaN; signaling or quiet?
! 72: */
! 73: if (Dbl_isone_signaling(opnd1p1)) {
! 74: /* trap if INVALIDTRAP enabled */
! 75: if (Is_invalidtrap_enabled())
! 76: return(INVALIDEXCEPTION);
! 77: /* make NaN quiet */
! 78: Set_invalidflag();
! 79: Dbl_set_quiet(opnd1p1);
! 80: }
! 81: /*
! 82: * is second operand a signaling NaN?
! 83: */
! 84: else if (Dbl_is_signalingnan(opnd2p1)) {
! 85: /* trap if INVALIDTRAP enabled */
! 86: if (Is_invalidtrap_enabled())
! 87: return(INVALIDEXCEPTION);
! 88: /* make NaN quiet */
! 89: Set_invalidflag();
! 90: Dbl_set_quiet(opnd2p1);
! 91: Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
! 92: return(NOEXCEPTION);
! 93: }
! 94: /*
! 95: * return quiet NaN
! 96: */
! 97: Dbl_copytoptr(opnd1p1,opnd1p2,dstptr);
! 98: return(NOEXCEPTION);
! 99: }
! 100: }
! 101: /*
! 102: * check second operand for NaN's or infinity
! 103: */
! 104: if (Dbl_isinfinity_exponent(opnd2p1)) {
! 105: if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) {
! 106: /*
! 107: * return zero
! 108: */
! 109: Dbl_setzero_exponentmantissa(resultp1,resultp2);
! 110: Dbl_copytoptr(resultp1,resultp2,dstptr);
! 111: return(NOEXCEPTION);
! 112: }
! 113: /*
! 114: * is NaN; signaling or quiet?
! 115: */
! 116: if (Dbl_isone_signaling(opnd2p1)) {
! 117: /* trap if INVALIDTRAP enabled */
! 118: if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
! 119: /* make NaN quiet */
! 120: Set_invalidflag();
! 121: Dbl_set_quiet(opnd2p1);
! 122: }
! 123: /*
! 124: * return quiet NaN
! 125: */
! 126: Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
! 127: return(NOEXCEPTION);
! 128: }
! 129: /*
! 130: * check for division by zero
! 131: */
! 132: if (Dbl_iszero_exponentmantissa(opnd2p1,opnd2p2)) {
! 133: if (Dbl_iszero_exponentmantissa(opnd1p1,opnd1p2)) {
! 134: /* invalid since both operands are zero */
! 135: if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
! 136: Set_invalidflag();
! 137: Dbl_makequietnan(resultp1,resultp2);
! 138: Dbl_copytoptr(resultp1,resultp2,dstptr);
! 139: return(NOEXCEPTION);
! 140: }
! 141: if (Is_divisionbyzerotrap_enabled())
! 142: return(DIVISIONBYZEROEXCEPTION);
! 143: Set_divisionbyzeroflag();
! 144: Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
! 145: Dbl_copytoptr(resultp1,resultp2,dstptr);
! 146: return(NOEXCEPTION);
! 147: }
! 148: /*
! 149: * Generate exponent
! 150: */
! 151: dest_exponent = Dbl_exponent(opnd1p1) - Dbl_exponent(opnd2p1) + DBL_BIAS;
! 152:
! 153: /*
! 154: * Generate mantissa
! 155: */
! 156: if (Dbl_isnotzero_exponent(opnd1p1)) {
! 157: /* set hidden bit */
! 158: Dbl_clear_signexponent_set_hidden(opnd1p1);
! 159: }
! 160: else {
! 161: /* check for zero */
! 162: if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
! 163: Dbl_setzero_exponentmantissa(resultp1,resultp2);
! 164: Dbl_copytoptr(resultp1,resultp2,dstptr);
! 165: return(NOEXCEPTION);
! 166: }
! 167: /* is denormalized, want to normalize */
! 168: Dbl_clear_signexponent(opnd1p1);
! 169: Dbl_leftshiftby1(opnd1p1,opnd1p2);
! 170: Dbl_normalize(opnd1p1,opnd1p2,dest_exponent);
! 171: }
! 172: /* opnd2 needs to have hidden bit set with msb in hidden bit */
! 173: if (Dbl_isnotzero_exponent(opnd2p1)) {
! 174: Dbl_clear_signexponent_set_hidden(opnd2p1);
! 175: }
! 176: else {
! 177: /* is denormalized; want to normalize */
! 178: Dbl_clear_signexponent(opnd2p1);
! 179: Dbl_leftshiftby1(opnd2p1,opnd2p2);
! 180: while (Dbl_iszero_hiddenhigh7mantissa(opnd2p1)) {
! 181: dest_exponent+=8;
! 182: Dbl_leftshiftby8(opnd2p1,opnd2p2);
! 183: }
! 184: if (Dbl_iszero_hiddenhigh3mantissa(opnd2p1)) {
! 185: dest_exponent+=4;
! 186: Dbl_leftshiftby4(opnd2p1,opnd2p2);
! 187: }
! 188: while (Dbl_iszero_hidden(opnd2p1)) {
! 189: dest_exponent++;
! 190: Dbl_leftshiftby1(opnd2p1,opnd2p2);
! 191: }
! 192: }
! 193:
! 194: /* Divide the source mantissas */
! 195:
! 196: /*
! 197: * A non-restoring divide algorithm is used.
! 198: */
! 199: Twoword_subtract(opnd1p1,opnd1p2,opnd2p1,opnd2p2);
! 200: Dbl_setzero(opnd3p1,opnd3p2);
! 201: for (count=1; count <= DBL_P && (opnd1p1 || opnd1p2); count++) {
! 202: Dbl_leftshiftby1(opnd1p1,opnd1p2);
! 203: Dbl_leftshiftby1(opnd3p1,opnd3p2);
! 204: if (Dbl_iszero_sign(opnd1p1)) {
! 205: Dbl_setone_lowmantissap2(opnd3p2);
! 206: Twoword_subtract(opnd1p1,opnd1p2,opnd2p1,opnd2p2);
! 207: }
! 208: else {
! 209: Twoword_add(opnd1p1, opnd1p2, opnd2p1, opnd2p2);
! 210: }
! 211: }
! 212: if (count <= DBL_P) {
! 213: Dbl_leftshiftby1(opnd3p1,opnd3p2);
! 214: Dbl_setone_lowmantissap2(opnd3p2);
! 215: Dbl_leftshift(opnd3p1,opnd3p2,(DBL_P-count));
! 216: if (Dbl_iszero_hidden(opnd3p1)) {
! 217: Dbl_leftshiftby1(opnd3p1,opnd3p2);
! 218: dest_exponent--;
! 219: }
! 220: }
! 221: else {
! 222: if (Dbl_iszero_hidden(opnd3p1)) {
! 223: /* need to get one more bit of result */
! 224: Dbl_leftshiftby1(opnd1p1,opnd1p2);
! 225: Dbl_leftshiftby1(opnd3p1,opnd3p2);
! 226: if (Dbl_iszero_sign(opnd1p1)) {
! 227: Dbl_setone_lowmantissap2(opnd3p2);
! 228: Twoword_subtract(opnd1p1,opnd1p2,opnd2p1,opnd2p2);
! 229: }
! 230: else {
! 231: Twoword_add(opnd1p1,opnd1p2,opnd2p1,opnd2p2);
! 232: }
! 233: dest_exponent--;
! 234: }
! 235: if (Dbl_iszero_sign(opnd1p1)) guardbit = TRUE;
! 236: stickybit = Dbl_allp1(opnd1p1) || Dbl_allp2(opnd1p2);
! 237: }
! 238: inexact = guardbit | stickybit;
! 239:
! 240: /*
! 241: * round result
! 242: */
! 243: if (inexact && (dest_exponent > 0 || Is_underflowtrap_enabled())) {
! 244: Dbl_clear_signexponent(opnd3p1);
! 245: switch (Rounding_mode()) {
! 246: case ROUNDPLUS:
! 247: if (Dbl_iszero_sign(resultp1))
! 248: Dbl_increment(opnd3p1,opnd3p2);
! 249: break;
! 250: case ROUNDMINUS:
! 251: if (Dbl_isone_sign(resultp1))
! 252: Dbl_increment(opnd3p1,opnd3p2);
! 253: break;
! 254: case ROUNDNEAREST:
! 255: if (guardbit && (stickybit ||
! 256: Dbl_isone_lowmantissap2(opnd3p2))) {
! 257: Dbl_increment(opnd3p1,opnd3p2);
! 258: }
! 259: }
! 260: if (Dbl_isone_hidden(opnd3p1)) dest_exponent++;
! 261: }
! 262: Dbl_set_mantissa(resultp1,resultp2,opnd3p1,opnd3p2);
! 263:
! 264: /*
! 265: * Test for overflow
! 266: */
! 267: if (dest_exponent >= DBL_INFINITY_EXPONENT) {
! 268: /* trap if OVERFLOWTRAP enabled */
! 269: if (Is_overflowtrap_enabled()) {
! 270: /*
! 271: * Adjust bias of result
! 272: */
! 273: Dbl_setwrapped_exponent(resultp1,dest_exponent,ovfl);
! 274: Dbl_copytoptr(resultp1,resultp2,dstptr);
! 275: if (inexact) {
! 276: if (Is_inexacttrap_enabled())
! 277: return(OVERFLOWEXCEPTION | INEXACTEXCEPTION);
! 278: else
! 279: Set_inexactflag();
! 280: }
! 281: return(OVERFLOWEXCEPTION);
! 282: }
! 283: Set_overflowflag();
! 284: /* set result to infinity or largest number */
! 285: Dbl_setoverflow(resultp1,resultp2);
! 286: inexact = TRUE;
! 287: }
! 288: /*
! 289: * Test for underflow
! 290: */
! 291: else if (dest_exponent <= 0) {
! 292: /* trap if UNDERFLOWTRAP enabled */
! 293: if (Is_underflowtrap_enabled()) {
! 294: /*
! 295: * Adjust bias of result
! 296: */
! 297: Dbl_setwrapped_exponent(resultp1,dest_exponent,unfl);
! 298: Dbl_copytoptr(resultp1,resultp2,dstptr);
! 299: if (inexact) {
! 300: if (Is_inexacttrap_enabled())
! 301: return(UNDERFLOWEXCEPTION | INEXACTEXCEPTION);
! 302: else
! 303: Set_inexactflag();
! 304: }
! 305: return(UNDERFLOWEXCEPTION);
! 306: }
! 307:
! 308: /* Determine if should set underflow flag */
! 309: is_tiny = TRUE;
! 310: if (dest_exponent == 0 && inexact) {
! 311: switch (Rounding_mode()) {
! 312: case ROUNDPLUS:
! 313: if (Dbl_iszero_sign(resultp1)) {
! 314: Dbl_increment(opnd3p1,opnd3p2);
! 315: if (Dbl_isone_hiddenoverflow(opnd3p1))
! 316: is_tiny = FALSE;
! 317: Dbl_decrement(opnd3p1,opnd3p2);
! 318: }
! 319: break;
! 320: case ROUNDMINUS:
! 321: if (Dbl_isone_sign(resultp1)) {
! 322: Dbl_increment(opnd3p1,opnd3p2);
! 323: if (Dbl_isone_hiddenoverflow(opnd3p1))
! 324: is_tiny = FALSE;
! 325: Dbl_decrement(opnd3p1,opnd3p2);
! 326: }
! 327: break;
! 328: case ROUNDNEAREST:
! 329: if (guardbit && (stickybit ||
! 330: Dbl_isone_lowmantissap2(opnd3p2))) {
! 331: Dbl_increment(opnd3p1,opnd3p2);
! 332: if (Dbl_isone_hiddenoverflow(opnd3p1))
! 333: is_tiny = FALSE;
! 334: Dbl_decrement(opnd3p1,opnd3p2);
! 335: }
! 336: break;
! 337: }
! 338: }
! 339:
! 340: /*
! 341: * denormalize result or set to signed zero
! 342: */
! 343: stickybit = inexact;
! 344: Dbl_denormalize(opnd3p1,opnd3p2,dest_exponent,guardbit,
! 345: stickybit,inexact);
! 346:
! 347: /* return rounded number */
! 348: if (inexact) {
! 349: switch (Rounding_mode()) {
! 350: case ROUNDPLUS:
! 351: if (Dbl_iszero_sign(resultp1)) {
! 352: Dbl_increment(opnd3p1,opnd3p2);
! 353: }
! 354: break;
! 355: case ROUNDMINUS:
! 356: if (Dbl_isone_sign(resultp1)) {
! 357: Dbl_increment(opnd3p1,opnd3p2);
! 358: }
! 359: break;
! 360: case ROUNDNEAREST:
! 361: if (guardbit && (stickybit ||
! 362: Dbl_isone_lowmantissap2(opnd3p2))) {
! 363: Dbl_increment(opnd3p1,opnd3p2);
! 364: }
! 365: break;
! 366: }
! 367: if (is_tiny)
! 368: Set_underflowflag();
! 369: }
! 370: Dbl_set_exponentmantissa(resultp1,resultp2,opnd3p1,opnd3p2);
! 371: }
! 372: else Dbl_set_exponent(resultp1,dest_exponent);
! 373: Dbl_copytoptr(resultp1,resultp2,dstptr);
! 374:
! 375: /* check for inexact */
! 376: if (inexact) {
! 377: if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
! 378: else Set_inexactflag();
! 379: }
! 380: return(NOEXCEPTION);
! 381: }
CVSweb