[BACK]Return to dfrem.c CVS log [TXT][DIR] Up to [local] / sys / arch / hppa / spmath

Annotation of sys/arch/hppa/spmath/dfrem.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: dfrem.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: /* @(#)dfrem.c: Revision: 1.7.88.1 Date: 93/12/07 15:05:43 */
                     16:
                     17: #include "float.h"
                     18: #include "dbl_float.h"
                     19:
                     20: /*
                     21:  *  Double Precision Floating-point Remainder
                     22:  */
                     23: int
                     24: dbl_frem(srcptr1,srcptr2,dstptr,status)
                     25:        dbl_floating_point *srcptr1, *srcptr2, *dstptr;
                     26:        unsigned int *status;
                     27: {
                     28:        register unsigned int opnd1p1, opnd1p2, opnd2p1, opnd2p2;
                     29:        register unsigned int resultp1, resultp2;
                     30:        register int opnd1_exponent, opnd2_exponent, dest_exponent, stepcount;
                     31:        register int roundup = FALSE;
                     32:
                     33:        Dbl_copyfromptr(srcptr1,opnd1p1,opnd1p2);
                     34:        Dbl_copyfromptr(srcptr2,opnd2p1,opnd2p2);
                     35:        /*
                     36:         * check first operand for NaN's or infinity
                     37:         */
                     38:        if ((opnd1_exponent = Dbl_exponent(opnd1p1)) == DBL_INFINITY_EXPONENT) {
                     39:                if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
                     40:                        if (Dbl_isnotnan(opnd2p1,opnd2p2)) {
                     41:                                /* invalid since first operand is infinity */
                     42:                                if (Is_invalidtrap_enabled())
                     43:                                        return(INVALIDEXCEPTION);
                     44:                                Set_invalidflag();
                     45:                                Dbl_makequietnan(resultp1,resultp2);
                     46:                                Dbl_copytoptr(resultp1,resultp2,dstptr);
                     47:                                return(NOEXCEPTION);
                     48:                        }
                     49:                }
                     50:                else {
                     51:                        /*
                     52:                         * is NaN; signaling or quiet?
                     53:                         */
                     54:                        if (Dbl_isone_signaling(opnd1p1)) {
                     55:                                /* trap if INVALIDTRAP enabled */
                     56:                                if (Is_invalidtrap_enabled())
                     57:                                        return(INVALIDEXCEPTION);
                     58:                                /* make NaN quiet */
                     59:                                Set_invalidflag();
                     60:                                Dbl_set_quiet(opnd1p1);
                     61:                        }
                     62:                        /*
                     63:                         * is second operand a signaling NaN?
                     64:                         */
                     65:                        else if (Dbl_is_signalingnan(opnd2p1)) {
                     66:                                /* trap if INVALIDTRAP enabled */
                     67:                                if (Is_invalidtrap_enabled())
                     68:                                        return(INVALIDEXCEPTION);
                     69:                                /* make NaN quiet */
                     70:                                Set_invalidflag();
                     71:                                Dbl_set_quiet(opnd2p1);
                     72:                                Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
                     73:                                return(NOEXCEPTION);
                     74:                        }
                     75:                        /*
                     76:                         * return quiet NaN
                     77:                         */
                     78:                        Dbl_copytoptr(opnd1p1,opnd1p2,dstptr);
                     79:                        return(NOEXCEPTION);
                     80:                }
                     81:        }
                     82:        /*
                     83:         * check second operand for NaN's or infinity
                     84:         */
                     85:        if ((opnd2_exponent = Dbl_exponent(opnd2p1)) == DBL_INFINITY_EXPONENT) {
                     86:                if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) {
                     87:                        /*
                     88:                         * return first operand
                     89:                         */
                     90:                        Dbl_copytoptr(opnd1p1,opnd1p2,dstptr);
                     91:                        return(NOEXCEPTION);
                     92:                }
                     93:                /*
                     94:                 * is NaN; signaling or quiet?
                     95:                 */
                     96:                if (Dbl_isone_signaling(opnd2p1)) {
                     97:                        /* trap if INVALIDTRAP enabled */
                     98:                        if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
                     99:                        /* make NaN quiet */
                    100:                        Set_invalidflag();
                    101:                        Dbl_set_quiet(opnd2p1);
                    102:                }
                    103:                /*
                    104:                 * return quiet NaN
                    105:                 */
                    106:                Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
                    107:                return(NOEXCEPTION);
                    108:        }
                    109:        /*
                    110:         * check second operand for zero
                    111:         */
                    112:        if (Dbl_iszero_exponentmantissa(opnd2p1,opnd2p2)) {
                    113:                /* invalid since second operand is zero */
                    114:                if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
                    115:                Set_invalidflag();
                    116:                Dbl_makequietnan(resultp1,resultp2);
                    117:                Dbl_copytoptr(resultp1,resultp2,dstptr);
                    118:                return(NOEXCEPTION);
                    119:        }
                    120:
                    121:        /*
                    122:         * get sign of result
                    123:         */
                    124:        resultp1 = opnd1p1;
                    125:
                    126:        /*
                    127:         * check for denormalized operands
                    128:         */
                    129:        if (opnd1_exponent == 0) {
                    130:                /* check for zero */
                    131:                if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
                    132:                        Dbl_copytoptr(opnd1p1,opnd1p2,dstptr);
                    133:                        return(NOEXCEPTION);
                    134:                }
                    135:                /* normalize, then continue */
                    136:                opnd1_exponent = 1;
                    137:                Dbl_normalize(opnd1p1,opnd1p2,opnd1_exponent);
                    138:        }
                    139:        else {
                    140:                Dbl_clear_signexponent_set_hidden(opnd1p1);
                    141:        }
                    142:        if (opnd2_exponent == 0) {
                    143:                /* normalize, then continue */
                    144:                opnd2_exponent = 1;
                    145:                Dbl_normalize(opnd2p1,opnd2p2,opnd2_exponent);
                    146:        }
                    147:        else {
                    148:                Dbl_clear_signexponent_set_hidden(opnd2p1);
                    149:        }
                    150:
                    151:        /* find result exponent and divide step loop count */
                    152:        dest_exponent = opnd2_exponent - 1;
                    153:        stepcount = opnd1_exponent - opnd2_exponent;
                    154:
                    155:        /*
                    156:         * check for opnd1/opnd2 < 1
                    157:         */
                    158:        if (stepcount < 0) {
                    159:                /*
                    160:                 * check for opnd1/opnd2 > 1/2
                    161:                 *
                    162:                 * In this case n will round to 1, so
                    163:                 *    r = opnd1 - opnd2
                    164:                 */
                    165:                if (stepcount == -1 &&
                    166:                    Dbl_isgreaterthan(opnd1p1,opnd1p2,opnd2p1,opnd2p2)) {
                    167:                        /* set sign */
                    168:                        Dbl_allp1(resultp1) = ~Dbl_allp1(resultp1);
                    169:                        /* align opnd2 with opnd1 */
                    170:                        Dbl_leftshiftby1(opnd2p1,opnd2p2);
                    171:                        Dbl_subtract(opnd2p1,opnd2p2,opnd1p1,opnd1p2,
                    172:                         opnd2p1,opnd2p2);
                    173:                        /* now normalize */
                    174:                        while (Dbl_iszero_hidden(opnd2p1)) {
                    175:                                Dbl_leftshiftby1(opnd2p1,opnd2p2);
                    176:                                dest_exponent--;
                    177:                        }
                    178:                        Dbl_set_exponentmantissa(resultp1,resultp2,opnd2p1,opnd2p2);
                    179:                        goto testforunderflow;
                    180:                }
                    181:                /*
                    182:                 * opnd1/opnd2 <= 1/2
                    183:                 *
                    184:                 * In this case n will round to zero, so
                    185:                 *    r = opnd1
                    186:                 */
                    187:                Dbl_set_exponentmantissa(resultp1,resultp2,opnd1p1,opnd1p2);
                    188:                dest_exponent = opnd1_exponent;
                    189:                goto testforunderflow;
                    190:        }
                    191:
                    192:        /*
                    193:         * Generate result
                    194:         *
                    195:         * Do iterative subtract until remainder is less than operand 2.
                    196:         */
                    197:        while (stepcount-- > 0 && (Dbl_allp1(opnd1p1) || Dbl_allp2(opnd1p2))) {
                    198:                if (Dbl_isnotlessthan(opnd1p1,opnd1p2,opnd2p1,opnd2p2)) {
                    199:                        Dbl_subtract(opnd1p1,opnd1p2,opnd2p1,opnd2p2,opnd1p1,opnd1p2);
                    200:                }
                    201:                Dbl_leftshiftby1(opnd1p1,opnd1p2);
                    202:        }
                    203:        /*
                    204:         * Do last subtract, then determine which way to round if remainder
                    205:         * is exactly 1/2 of opnd2
                    206:         */
                    207:        if (Dbl_isnotlessthan(opnd1p1,opnd1p2,opnd2p1,opnd2p2)) {
                    208:                Dbl_subtract(opnd1p1,opnd1p2,opnd2p1,opnd2p2,opnd1p1,opnd1p2);
                    209:                roundup = TRUE;
                    210:        }
                    211:        if (stepcount > 0 || Dbl_iszero(opnd1p1,opnd1p2)) {
                    212:                /* division is exact, remainder is zero */
                    213:                Dbl_setzero_exponentmantissa(resultp1,resultp2);
                    214:                Dbl_copytoptr(resultp1,resultp2,dstptr);
                    215:                return(NOEXCEPTION);
                    216:        }
                    217:
                    218:        /*
                    219:         * Check for cases where opnd1/opnd2 < n
                    220:         *
                    221:         * In this case the result's sign will be opposite that of
                    222:         * opnd1.  The mantissa also needs some correction.
                    223:         */
                    224:        Dbl_leftshiftby1(opnd1p1,opnd1p2);
                    225:        if (Dbl_isgreaterthan(opnd1p1,opnd1p2,opnd2p1,opnd2p2)) {
                    226:                Dbl_invert_sign(resultp1);
                    227:                Dbl_leftshiftby1(opnd2p1,opnd2p2);
                    228:                Dbl_subtract(opnd2p1,opnd2p2,opnd1p1,opnd1p2,opnd1p1,opnd1p2);
                    229:        }
                    230:        /* check for remainder being exactly 1/2 of opnd2 */
                    231:        else if (Dbl_isequal(opnd1p1,opnd1p2,opnd2p1,opnd2p2) && roundup) {
                    232:                Dbl_invert_sign(resultp1);
                    233:        }
                    234:
                    235:        /* normalize result's mantissa */
                    236:        while (Dbl_iszero_hidden(opnd1p1)) {
                    237:                dest_exponent--;
                    238:                Dbl_leftshiftby1(opnd1p1,opnd1p2);
                    239:        }
                    240:        Dbl_set_exponentmantissa(resultp1,resultp2,opnd1p1,opnd1p2);
                    241:
                    242:        /*
                    243:         * Test for underflow
                    244:         */
                    245:     testforunderflow:
                    246:        if (dest_exponent <= 0) {
                    247:                /* trap if UNDERFLOWTRAP enabled */
                    248:                if (Is_underflowtrap_enabled()) {
                    249:                        /*
                    250:                         * Adjust bias of result
                    251:                         */
                    252:                        Dbl_setwrapped_exponent(resultp1,dest_exponent,unfl);
                    253:                        /* frem is always exact */
                    254:                        Dbl_copytoptr(resultp1,resultp2,dstptr);
                    255:                        return(UNDERFLOWEXCEPTION);
                    256:                }
                    257:                /*
                    258:                 * denormalize result or set to signed zero
                    259:                 */
                    260:                if (dest_exponent >= (1 - DBL_P)) {
                    261:                        Dbl_rightshift_exponentmantissa(resultp1,resultp2,
                    262:                         1-dest_exponent);
                    263:                }
                    264:                else {
                    265:                        Dbl_setzero_exponentmantissa(resultp1,resultp2);
                    266:                }
                    267:        }
                    268:        else Dbl_set_exponent(resultp1,dest_exponent);
                    269:        Dbl_copytoptr(resultp1,resultp2,dstptr);
                    270:        return(NOEXCEPTION);
                    271: }

CVSweb