Annotation of nono/fpe/fpu_rem.c, revision 1.1.1.1

1.1       root        1: /*     $NetBSD: fpu_rem.c,v 1.17 2015/02/05 12:22:06 isaki Exp $       */
                      2: 
                      3: /*
                      4:  * Copyright (c) 1995  Ken Nakata
                      5:  *     All rights reserved.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  * 3. Neither the name of the author nor the names of its contributors
                     16:  *    may be used to endorse or promote products derived from this software
                     17:  *    without specific prior written permission.
                     18:  *
                     19:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
                     20:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     21:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     22:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
                     23:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     24:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     25:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     26:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     27:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     28:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     29:  * SUCH DAMAGE.
                     30:  *
                     31:  *     @(#)fpu_rem.c   10/24/95
                     32:  */
                     33: 
                     34: #include "fpu_emulate.h"
                     35: 
                     36: /*
                     37:  *       ALGORITHM
                     38:  *
                     39:  *       Step 1.  Save and strip signs of X and Y: signX := sign(X),
                     40:  *                signY := sign(Y), X := *X*, Y := *Y*,
                     41:  *                signQ := signX EOR signY. Record whether MOD or REM
                     42:  *                is requested.
                     43:  *
                     44:  *       Step 2.  Set L := expo(X)-expo(Y), k := 0, Q := 0.
                     45:  *                If (L < 0) then
                     46:  *                   R := X, go to Step 4.
                     47:  *                else
                     48:  *                   R := 2^(-L)X, j := L.
                     49:  *                endif
                     50:  *
                     51:  *       Step 3.  Perform MOD(X,Y)
                     52:  *            3.1 If R = Y, then
                     53:  *                Q := Q + 1, R := 0 with signX, go to Step 7.
                     54:  *            3.2 If R > Y, then { R := R - Y, Q := Q + 1}
                     55:  *            3.3 If j = 0, go to Step 4.
                     56:  *            3.4 k := k + 1, j := j - 1, Q := 2Q, R := 2R. Go to
                     57:  *                Step 3.1.
                     58:  *
                     59:  *       Step 4.  R := signX*R.
                     60:  *
                     61:  *       Step 5.  If MOD is requested, go to Step 7.
                     62:  *
                     63:  *       Step 6.  Now, R = MOD(X,Y), convert to REM(X,Y) is requested.
                     64:  *                Do banker's rounding.
                     65:  *                If   abs(R) > Y/2
                     66:  *                 || (abs(R) == Y/2 && Q % 2 == 1) then
                     67:  *                 { Q := Q + 1, R := R - signX * Y }.
                     68:  *
                     69:  *       Step 7.  Return signQ, last 7 bits of Q, and R as required.
                     70:  */
                     71: 
                     72: static int abscmp3(const struct fpn *a, const struct fpn *b);
                     73: 
                     74: /* Absolute FORTRAN Compare */
                     75: static int
                     76: abscmp3(const struct fpn *a, const struct fpn *b)
                     77: {
                     78:        int i;
                     79: 
                     80:        if (a->fp_exp < b->fp_exp) {
                     81:                return -1;
                     82:        } else if (a->fp_exp > b->fp_exp) {
                     83:                return 1;
                     84:        } else {
                     85:                for (i = 0; i < 3; i++) {
                     86:                        if (a->fp_mant[i] < b->fp_mant[i])
                     87:                                return -1;
                     88:                        else if (a->fp_mant[i] > b->fp_mant[i])
                     89:                                return 1;
                     90:                }
                     91:        }
                     92:        return 0;
                     93: }
                     94: 
                     95: struct fpn *
                     96: fpu_modrem(struct fpemu *fe, int is_mod)
                     97: {
                     98:        struct fpn X, Y;
                     99:        struct fpn *x, *y, *r;
                    100:        uint32_t signX, signY, signQ;
                    101:        int j, k, l, q;
                    102:        int cmp;
                    103: 
                    104:        if (ISNAN(&fe->fe_f1))
                    105:                return &fe->fe_f1;
                    106:        if (ISNAN(&fe->fe_f2))
                    107:                return &fe->fe_f2;
                    108:        if (ISINF(&fe->fe_f1) || ISZERO(&fe->fe_f2))
                    109:                return fpu_newnan(fe);
                    110: 
                    111:        CPYFPN(&X, &fe->fe_f1);
                    112:        CPYFPN(&Y, &fe->fe_f2);
                    113:        x = &X;
                    114:        y = &Y;
                    115:        q = 0;
                    116:        r = &fe->fe_f2;
                    117: 
                    118:        /*
                    119:         * Step 1
                    120:         */
                    121:        signX = x->fp_sign;
                    122:        signY = y->fp_sign;
                    123:        signQ = (signX ^ signY);
                    124:        x->fp_sign = y->fp_sign = 0;
                    125: 
                    126:        /* Special treatment that just return input value but Q is necessary */
                    127:        if (ISZERO(x) || ISINF(y)) {
                    128:                r = &fe->fe_f1;
                    129:                goto Step7;
                    130:        }
                    131: 
                    132:        /*
                    133:         * Step 2
                    134:         */
                    135:        l = x->fp_exp - y->fp_exp;
                    136:        k = 0;
                    137:        CPYFPN(r, x);
                    138:        if (l >= 0) {
                    139:                r->fp_exp -= l;
                    140:                j = l;
                    141: 
                    142:                /*
                    143:                 * Step 3
                    144:                 */
                    145:                for (;;) {
                    146:                        cmp = abscmp3(r, y);
                    147: 
                    148:                        /* Step 3.1 */
                    149:                        if (cmp == 0) {
                    150:                                r->fp_sign = signX;
                    151:                                break;
                    152:                        }
                    153: 
                    154:                        /* Step 3.2 */
                    155:                        if (cmp > 0) {
                    156:                                CPYFPN(&fe->fe_f1, r);
                    157:                                CPYFPN(&fe->fe_f2, y);
                    158:                                fe->fe_f2.fp_sign = 1;
                    159:                                r = fpu_add(fe);
                    160:                                q++;
                    161:                        }
                    162: 
                    163:                        /* Step 3.3 */
                    164:                        if (j == 0)
                    165:                                goto Step4;
                    166: 
                    167:                        /* Step 3.4 */
                    168:                        k++;
                    169:                        j--;
                    170:                        q += q;
                    171:                        r->fp_exp++;
                    172:                }
                    173:                /* R == Y */
                    174:                q++;
                    175:                q <<= (j > 7) ? 8 : j;
                    176:                r->fp_class = FPC_ZERO;
                    177:                goto Step7;
                    178:        }
                    179:  Step4:
                    180:        r->fp_sign = signX;
                    181: 
                    182:        /*
                    183:         * Step 5
                    184:         */
                    185:        if (is_mod)
                    186:                goto Step7;
                    187: 
                    188:        /*
                    189:         * Step 6
                    190:         */
                    191:        /* y = y / 2 */
                    192:        y->fp_exp--;
                    193:        /* abscmp3 ignore sign */
                    194:        cmp = abscmp3(r, y);
                    195:        /* revert y */
                    196:        y->fp_exp++;
                    197: 
                    198:        if (cmp > 0 || (cmp == 0 && q % 2)) {
                    199:                q++;
                    200:                CPYFPN(&fe->fe_f1, r);
                    201:                CPYFPN(&fe->fe_f2, y);
                    202:                fe->fe_f2.fp_sign = !signX;
                    203:                r = fpu_add(fe);
                    204:        }
                    205: 
                    206:        /*
                    207:         * Step 7
                    208:         */
                    209:  Step7:
                    210:        q &= 0x7f;
                    211:        q |= (signQ << 7);
                    212:        fe->fe_fpsr = (fe->fe_fpsr & ~FPSR_QTT) | (q << 16);
                    213:        return r;
                    214: }
                    215: 
                    216: struct fpn *
                    217: fpu_rem(struct fpemu *fe)
                    218: {
                    219:        struct fpn *fp;
                    220: 
                    221:        fp = fpu_modrem(fe, 0);
                    222: 
                    223:        /* Update Quotient Byte */
                    224:        fe->fe_fpframe->fpf_fpsr &= ~FPSR_QTT;
                    225:        fe->fe_fpframe->fpf_fpsr |= (fe->fe_fpsr & FPSR_QTT);
                    226: 
                    227:        return fp;
                    228: }
                    229: 
                    230: struct fpn *
                    231: fpu_mod(struct fpemu *fe)
                    232: {
                    233:        struct fpn *fp;
                    234: 
                    235:        fp = fpu_modrem(fe, 1);
                    236: 
                    237:        /* Update Quotient Byte */
                    238:        fe->fe_fpframe->fpf_fpsr &= ~FPSR_QTT;
                    239:        fe->fe_fpframe->fpf_fpsr |= (fe->fe_fpsr & FPSR_QTT);
                    240: 
                    241:        return fp;
                    242: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.