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

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:  *
1.1.1.2 ! root       44:  *       Step 2.  Set L := expo(X)-expo(Y), Q := 0.
1.1       root       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.
1.1.1.2 ! root       56:  *            3.4 j := j - 1, Q := 2Q, R := 2R. Go to Step 3.1.
1.1       root       57:  *
                     58:  *       Step 4.  R := signX*R.
                     59:  *
                     60:  *       Step 5.  If MOD is requested, go to Step 7.
                     61:  *
                     62:  *       Step 6.  Now, R = MOD(X,Y), convert to REM(X,Y) is requested.
                     63:  *                Do banker's rounding.
                     64:  *                If   abs(R) > Y/2
                     65:  *                 || (abs(R) == Y/2 && Q % 2 == 1) then
                     66:  *                 { Q := Q + 1, R := R - signX * Y }.
                     67:  *
                     68:  *       Step 7.  Return signQ, last 7 bits of Q, and R as required.
                     69:  */
                     70: 
                     71: static int abscmp3(const struct fpn *a, const struct fpn *b);
                     72: 
                     73: /* Absolute FORTRAN Compare */
                     74: static int
                     75: abscmp3(const struct fpn *a, const struct fpn *b)
                     76: {
                     77:        int i;
                     78: 
                     79:        if (a->fp_exp < b->fp_exp) {
                     80:                return -1;
                     81:        } else if (a->fp_exp > b->fp_exp) {
                     82:                return 1;
                     83:        } else {
                     84:                for (i = 0; i < 3; i++) {
                     85:                        if (a->fp_mant[i] < b->fp_mant[i])
                     86:                                return -1;
                     87:                        else if (a->fp_mant[i] > b->fp_mant[i])
                     88:                                return 1;
                     89:                }
                     90:        }
                     91:        return 0;
                     92: }
                     93: 
                     94: struct fpn *
                     95: fpu_modrem(struct fpemu *fe, int is_mod)
                     96: {
                     97:        struct fpn X, Y;
                     98:        struct fpn *x, *y, *r;
                     99:        uint32_t signX, signY, signQ;
1.1.1.2 ! root      100:        int j, l, q;
1.1       root      101:        int cmp;
                    102: 
                    103:        if (ISNAN(&fe->fe_f1))
                    104:                return &fe->fe_f1;
                    105:        if (ISNAN(&fe->fe_f2))
                    106:                return &fe->fe_f2;
                    107:        if (ISINF(&fe->fe_f1) || ISZERO(&fe->fe_f2))
                    108:                return fpu_newnan(fe);
                    109: 
                    110:        CPYFPN(&X, &fe->fe_f1);
                    111:        CPYFPN(&Y, &fe->fe_f2);
                    112:        x = &X;
                    113:        y = &Y;
                    114:        q = 0;
                    115:        r = &fe->fe_f2;
                    116: 
                    117:        /*
                    118:         * Step 1
                    119:         */
                    120:        signX = x->fp_sign;
                    121:        signY = y->fp_sign;
                    122:        signQ = (signX ^ signY);
                    123:        x->fp_sign = y->fp_sign = 0;
                    124: 
                    125:        /* Special treatment that just return input value but Q is necessary */
                    126:        if (ISZERO(x) || ISINF(y)) {
                    127:                r = &fe->fe_f1;
                    128:                goto Step7;
                    129:        }
                    130: 
                    131:        /*
                    132:         * Step 2
                    133:         */
                    134:        l = x->fp_exp - y->fp_exp;
                    135:        CPYFPN(r, x);
                    136:        if (l >= 0) {
                    137:                r->fp_exp -= l;
                    138:                j = l;
                    139: 
                    140:                /*
                    141:                 * Step 3
                    142:                 */
                    143:                for (;;) {
                    144:                        cmp = abscmp3(r, y);
                    145: 
                    146:                        /* Step 3.1 */
                    147:                        if (cmp == 0) {
                    148:                                r->fp_sign = signX;
                    149:                                break;
                    150:                        }
                    151: 
                    152:                        /* Step 3.2 */
                    153:                        if (cmp > 0) {
                    154:                                CPYFPN(&fe->fe_f1, r);
                    155:                                CPYFPN(&fe->fe_f2, y);
                    156:                                fe->fe_f2.fp_sign = 1;
                    157:                                r = fpu_add(fe);
                    158:                                q++;
                    159:                        }
                    160: 
                    161:                        /* Step 3.3 */
                    162:                        if (j == 0)
                    163:                                goto Step4;
                    164: 
                    165:                        /* Step 3.4 */
                    166:                        j--;
                    167:                        q += q;
                    168:                        r->fp_exp++;
                    169:                }
                    170:                /* R == Y */
                    171:                q++;
                    172:                q <<= (j > 7) ? 8 : j;
                    173:                r->fp_class = FPC_ZERO;
                    174:                goto Step7;
                    175:        }
                    176:  Step4:
                    177:        r->fp_sign = signX;
                    178: 
                    179:        /*
                    180:         * Step 5
                    181:         */
                    182:        if (is_mod)
                    183:                goto Step7;
                    184: 
                    185:        /*
                    186:         * Step 6
                    187:         */
                    188:        /* y = y / 2 */
                    189:        y->fp_exp--;
                    190:        /* abscmp3 ignore sign */
                    191:        cmp = abscmp3(r, y);
                    192:        /* revert y */
                    193:        y->fp_exp++;
                    194: 
                    195:        if (cmp > 0 || (cmp == 0 && q % 2)) {
                    196:                q++;
                    197:                CPYFPN(&fe->fe_f1, r);
                    198:                CPYFPN(&fe->fe_f2, y);
                    199:                fe->fe_f2.fp_sign = !signX;
                    200:                r = fpu_add(fe);
                    201:        }
                    202: 
                    203:        /*
                    204:         * Step 7
                    205:         */
                    206:  Step7:
                    207:        q &= 0x7f;
                    208:        q |= (signQ << 7);
                    209:        fe->fe_fpsr = (fe->fe_fpsr & ~FPSR_QTT) | (q << 16);
                    210:        return r;
                    211: }
                    212: 
                    213: struct fpn *
                    214: fpu_rem(struct fpemu *fe)
                    215: {
                    216:        struct fpn *fp;
                    217: 
                    218:        fp = fpu_modrem(fe, 0);
                    219: 
                    220:        /* Update Quotient Byte */
                    221:        fe->fe_fpframe->fpf_fpsr &= ~FPSR_QTT;
                    222:        fe->fe_fpframe->fpf_fpsr |= (fe->fe_fpsr & FPSR_QTT);
                    223: 
                    224:        return fp;
                    225: }
                    226: 
                    227: struct fpn *
                    228: fpu_mod(struct fpemu *fe)
                    229: {
                    230:        struct fpn *fp;
                    231: 
                    232:        fp = fpu_modrem(fe, 1);
                    233: 
                    234:        /* Update Quotient Byte */
                    235:        fe->fe_fpframe->fpf_fpsr &= ~FPSR_QTT;
                    236:        fe->fe_fpframe->fpf_fpsr |= (fe->fe_fpsr & FPSR_QTT);
                    237: 
                    238:        return fp;
                    239: }

unix.superglobalmegacorp.com

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