fpc.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,417 行 · 第 1/3 页

C
1,417
字号
        if( isDstNeg ) fneg( dst, dst );
    } else if( f_isZero( src1 ) && f_isZero( src2 ) ) {
        *(uint32*)dst = FLOAT_NAN;
    } else if( f_isZero( src1 ) ) {
        *(uint32*)dst = FLOAT_POS_ZERO;
        if( isDstNeg ) fneg( dst, dst );
    } else if( f_isZero( src2 ) ) {
        *(uint32*)dst = FLOAT_POS_INF;
        if( isDstNeg ) fneg( dst, dst );
    } else {
        parseFloat( *(float*)src1, &f1, &e1 );
        parseFloat( *(float*)src2, &f2, &e2 );
        mp_init( &num1, f1 );
        mp_init( &num2, f2 );
        mp_init( &rem, 0 );
        if( mp_lt( &num1, &num2 ) ) {
            adjust = 1;
            e1--;
        }
        newexp = e1 - e2 + float_bias;
        if( newexp <= 0 && newexp > -23 ) {
            mp_shiftleft( &num1, &num1, 22 + newexp + adjust );
        } else {
            mp_shiftleft( &num1, &num1, 23 + adjust );
        }
        mp_div( &num1, &rem, &num1, &num2 );
        mp_mulsc( &rem, &rem, 2 );
        rc = mp_cmp( &rem, &num2 );
        if( (rc == 0 && (rem.num[0] & 2)) || rc == -1 ) {
            /* round up */
            mp_addsc( &num1, &num1, 1 );
        }
        if( newexp <= 0 && newexp > -23 ) {
            /* denormalized result */
            uint64 temp;
            mp_touint64( &temp, &num1 );
            makeFloat( dst, temp, 0 - float_bias );
        } else {
            mp_tofloat( dst, &num1 );
            changeFloatExponent( dst, dst, e1 - e2 - 23 );
        }
        if( isDstNeg ) fneg( dst, dst );
        mp_free( &num1 );
        mp_free( &num2 );
        mp_free( &rem );
    }
}

void frem( void *dst, void *src1, void *src2 ) {
    uint64 f1, f2;
    int e1, e2;
    mpnum num1, num2, zero;
    int emin;
    int newexp;

    /* special cases */
    if( f_isNan( src1 ) || f_isNan( src2 ) ) {
        *(uint32*)dst = FLOAT_NAN;
    } else if( f_isInf( src1 ) || f_isZero( src2 ) ) {
        *(uint32*)dst = FLOAT_NAN;
    } else if( f_isZero( src1 ) || f_isInf( src2 ) ) {
        *(uint32*)dst = *(uint32*)src1;
    } else {
        parseFloat( *(float*)src1, &f1, &e1 );
        parseFloat( *(float*)src2, &f2, &e2 );
        mp_init( &num1, f1 );
        mp_init( &num2, f2 );
        mp_init( &zero, 0 );
        emin = min( e1, e2 );
        if( e2 > e1 ) {
            mp_shiftleft( &num2, &num2, e2 - e1 );
        } else {
            mp_shiftleft( &num1, &num1, e1 - e2 );
        }
        mp_div( &num1, &num2, &num1, &num2 ); /* num2 will get the remainder */
        if( mp_eq( &num2, &zero ) ) {
            *(uint32*)dst = FLOAT_POS_ZERO;
        } else {
            newexp = emin - 24 + mp_bitsize( &num2 ) + float_bias;
            if( newexp <= 0 && newexp > -24 ) {
                /* denormalized result */
                uint64 temp;
                mp_binround( &num2, &num2, -newexp + 1 );
                mp_shiftright( &num2, &num2, -newexp + 1 );
                mp_touint64( &temp, &num2 );
                makeFloat( dst, temp, 0 - float_bias );
            } else {
                mp_tofloat( dst, &num2 );
                changeFloatExponent( dst, dst, emin - 23 );
            }
        }
        if( f_isNeg( src1 ) ) fneg( dst, dst );
        mp_free( &num1 );
        mp_free( &num2 );
        mp_free( &zero );
    }
}

void fneg( void *dst, void *src ) {
    memcpy( dst, src, 4 );
    if( !d_isNan( dst ) ) {
        ((char*)dst)[3] ^= 128;
    }
}

void eadd( void *dst, void *src1, void *src2 ) {
    uint64 f1, f2;
    int e1, e2;
    int diff;
    int emax, emin;
    mpnum num1, num2, zero;
    int isNeg1 = e_isNeg( src1 );
    int isNeg2 = e_isNeg( src2 );
    int isNeg;
    int newexp;

    /* special cases */
    if( e_isNan( src1 ) || e_isNan( src2 ) ) {
        makeExtNan( dst );
    } else if( e_isPosInf( src1 ) && e_isNegInf( src2 ) ) {
        makeExtNan( dst );
    } else if( e_isNegInf( src1 ) && e_isPosInf( src2 ) ) {
        makeExtNan( dst );
    } else if( e_isPosInf( src1 ) || e_isPosInf( src2 ) ) {
        makeExtPosInf( dst );
    } else if( e_isNegInf( src1 ) || e_isNegInf( src2 ) ) {
        makeExtNegInf( dst );
    } else if( e_isPosZero( src1 ) && e_isNegZero( src2 ) ) {
        makeExtPosZero( dst );
    } else if( e_isNegZero( src1 ) && e_isPosZero( src2 ) ) {
        makeExtPosZero( dst );
    } else if( e_isPosZero( src1 ) && e_isPosZero( src2 ) ) {
        makeExtPosZero( dst );
    } else if( e_isNegZero( src1 ) && e_isNegZero( src2 ) ) {
        makeExtNegZero( dst );
    } else if( e_isZero( src1 ) ) {
        memcpy( dst, src2, 10 );
    } else if( e_isZero( src2 ) ) {
        memcpy( dst, src1, 10 );
    } else {
        parseExtended( (char*)src1, &f1, &e1 );
        parseExtended( (char*)src2, &f2, &e2 );
        diff = abs( (e1 - e2) );
        emax = max( e1, e2 );
        emin = min( e1, e2 );
        mp_init( &num1, f1 );
        mp_init( &num2, f2 );
        mp_init( &zero, 0 );
        if( e1 > e2 ) {
            mp_shiftleft( &num1, &num1, (uint64)diff );
        } else if( e2 > e1 ) {
            mp_shiftleft( &num2, &num2, (uint64)diff );
        }
        if( (isNeg1 && isNeg2) || (!isNeg1 && !isNeg2 ) ) {
            mp_add( &num1, &num1, &num2 );
            if( isNeg1 ) isNeg = TRUE;
        } else {
            if( mp_gt( &num1, &num2 ) ) {
                mp_sub( &num1, &num1, &num2 );
                if( isNeg1 ) isNeg = TRUE;
            } else {
                mp_sub( &num1, &num2, &num1 );
                if( isNeg2 ) isNeg = TRUE;
            }
        }
        if( mp_eq( &num1, &zero ) ) {
            makeExtPosZero( dst );
        } else {
            newexp = emax - diff - 64 + mp_bitsize( &num1 ) + extended_bias;
            if( newexp <= 0 && newexp > -64 ) {
                /* denormalized result */
                uint64 temp;
                mp_binround( &num1, &num1, -(emin + extended_bias) + 1 );
                mp_shiftright( &num1, &num1, -(emin + extended_bias) + 1 );
                mp_touint64( &temp, &num1 );
                makeExtended( dst, temp, 0 - extended_bias );
            } else {
                mp_toextended( dst, &num1 );
                changeExtendedExponent( dst, dst, emax - diff - 63 );
            }
            if( isNeg ) eneg( dst, dst );
        }
        mp_free( &num1 );
        mp_free( &num2 );
        mp_free( &zero );
    }
}

void esub( void *dst, void *src1, void *src2 ) {
    char nsrc2[10];
    eneg( &nsrc2, src2 );
    eadd( dst, src1, &nsrc2 );
}

void emul( void *dst, void *src1, void *src2 ) {
    uint64 f1, f2;
    int e1, e2;
    mpnum num1, num2;
    int isNeg1 = e_isNeg( src1 );
    int isNeg2 = e_isNeg( src2 );
    int isDstNeg = (isNeg1 && !isNeg2) || (!isNeg1 && isNeg2);
    int newexp;

    /* special cases */
    if( e_isNan( src1 ) || e_isNan( src2 ) ) {
        makeExtNan( dst );
    } else if( e_isInf( src1 ) && e_isZero( src2 ) ) {
        makeExtNan( dst );
    } else if( e_isZero( src1 ) && e_isInf( src2 ) ) {
        makeExtNan( dst );
    } else if( e_isInf( src1 ) ) {
        makeExtPosInf( dst );
        if( isDstNeg ) eneg( dst, dst );
    } else if( e_isInf( src2 ) ) {
        makeExtPosInf( dst );
        if( isDstNeg ) eneg( dst, dst );
    } else if( e_isZero( src1 ) || e_isZero( src2 ) ) {
        makeExtPosZero( dst );
        if( isDstNeg ) eneg( dst, dst );
    } else {
        parseExtended( (char*)src1, &f1, &e1 );
        parseExtended( (char*)src2, &f2, &e2 );
        mp_init( &num1, f1 );
        mp_init( &num2, f2 );
        mp_mul( &num1, &num1, &num2 );
        newexp = e1 + e2 - 127 + mp_bitsize( &num1 ) + extended_bias;
        if( newexp <= 0 && newexp > -64 ) {
            /* denormalized result */
            uint64 temp;
            mp_binround( &num1, &num1, -newexp + 64 );
            mp_shiftright( &num1, &num1, -newexp + 64 );
            mp_touint64( &temp, &num1 );
            makeExtended( dst, temp, 0 - extended_bias );
        } else {
            mp_toextended( dst, &num1 );
            changeExtendedExponent( dst, dst, e1 + e2 - 126 );
        }
        if( isDstNeg ) eneg( dst, dst );
        mp_free( &num1 );
        mp_free( &num2 );
    }
}

void ediv( void *dst, void *src1, void *src2 ) {
    uint64 f1, f2;
    int e1, e2;
    mpnum num1, num2, rem;
    int isNeg1 = e_isNeg( src1 );
    int isNeg2 = e_isNeg( src2 );
    int isDstNeg = (isNeg1 && !isNeg2) || (!isNeg1 && isNeg2);
    int newexp, rc;
    int adjust = 0;

    /* special cases */
    if( e_isNan( src1 ) || e_isNan( src2 ) ) {
        makeExtNan( dst );
    } else if( e_isInf( src1 ) && e_isInf( src2 ) ) {
        makeExtNan( dst );
    } else if( e_isInf( src1 ) ) {
        makeExtPosInf( dst );
        if( isDstNeg ) eneg( dst, dst );
    } else if( e_isInf( src2 ) ) {
        makeExtPosZero( dst );
        if( isDstNeg ) eneg( dst, dst );
    } else if( e_isZero( src1 ) && e_isZero( src2 ) ) {
        makeExtNan( dst );
    } else if( e_isZero( src1 ) ) {
        makeExtPosZero( dst );
        if( isDstNeg ) eneg( dst, dst );
    } else if( e_isZero( src2 ) ) {
        makeExtPosInf( dst );
        if( isDstNeg ) eneg( dst, dst );
    } else {
        parseExtended( (char*)src1, &f1, &e1 );
        parseExtended( (char*)src2, &f2, &e2 );
        mp_init( &num1, f1 );
        mp_init( &num2, f2 );
        mp_init( &rem, 0 );
        if( mp_lt( &num1, &num2 ) ) {
            adjust = 1;
            e1--;
        }
        newexp = e1 - e2 + extended_bias;
        if( newexp <= 0 && newexp > -63 ) {
            mp_shiftleft( &num1, &num1, 62 + newexp + adjust );
        } else {
            mp_shiftleft( &num1, &num1, 63 + adjust );
        }
        mp_div( &num1, &rem, &num1, &num2 );
        mp_mulsc( &rem, &rem, 2 );
        rc = mp_cmp( &rem, &num2 );
        if( (rc == 0 && (rem.num[0] & 2)) || rc == -1 ) {
            /* round up */
            mp_addsc( &num1, &num1, 1 );
        }
        if( newexp <= 0 && newexp > -63 ) {
            /* denormalized result */
            uint64 temp;
            mp_touint64( &temp, &num1 );
            makeExtended( dst, temp, 0 - extended_bias );
        } else {
            mp_toextended( dst, &num1 );
            changeExtendedExponent( dst, dst, e1 - e2 - 63 );
        }
        if( isDstNeg ) eneg( dst, dst );
        mp_free( &num1 );
        mp_free( &num2 );
        mp_free( &rem );
    }
}

void erem( void *dst, void *src1, void *src2 ) {
    uint64 f1, f2;
    int e1, e2;
    mpnum num1, num2, zero;
    int emin;
    int newexp;

    /* special cases */
    if( e_isNan( src1 ) || e_isNan( src2 ) ) {
        makeExtNan( dst );
    } else if( e_isInf( src1 ) || e_isZero( src2 ) ) {
        makeExtNan( dst );
    } else if( e_isZero( src1 ) || e_isInf( src2 ) ) {
        memcpy( dst, src1, 10 );
    } else {
        parseExtended( (char*)src1, &f1, &e1 );
        parseExtended( (char*)src2, &f2, &e2 );
        mp_init( &num1, f1 );
        mp_init( &num2, f2 );
        mp_init( &zero, 0 );
        emin = min( e1, e2 );
        if( e2 > e1 ) {
            mp_shiftleft( &num2, &num2, e2 - e1 );
        } else {
            mp_shiftleft( &num1, &num1, e1 - e2 );
        }
        mp_div( &num1, &num2, &num1, &num2 ); /* num2 will get the remainder */
        if( mp_eq( &num2, &zero ) ) {
            makeExtPosZero( dst );
        } else {
            newexp = emin - 64 + mp_bitsize( &num2 ) + extended_bias;
            if( newexp <= 0 && newexp >= -64 ) {
                /* denormalized result */
                uint64 temp;
                mp_binround( &num2, &num2, -newexp + 1 );
                mp_shiftright( &num2, &num2, -newexp + 1 );
                mp_touint64( &temp, &num2 );
                makeExtended( dst, temp, 0 - extended_bias );
            } else {
                mp_toextended( dst, &num2 );
                changeExtendedExponent( dst, dst, emin - 63 );
            }
        }
        if( e_isNeg( src1 ) ) eneg( dst, dst );
        mp_free( &num1 );
        mp_free( &num2 );
        mp_free( &zero );
    }
}

void eneg( void *dst, void *src ) {
    memcpy( dst, src, 10 );
    if( !d_isNan( dst ) ) {
        ((char*)dst)[9] ^= 128;
    }
}

void f2d( void *dst, void *src )
{
    uint64 f;
    int e;

    if( f_isNan( src ) ) {
        *(uint64*)dst = DOUBLE_NAN;
    } else if( f_isPosInf( src ) ) {
        *(uint64*)dst = DOUBLE_POS_INF;
    } else if( f_isNegInf( src ) ) {
        *(uint64*)dst = DOUBLE_NEG_INF;
    } else if( f_isPosZero( src ) ) {
        *(uint64*)dst = DOUBLE_POS_ZERO;
    } else if( f_isNegZero( src ) ) {
        *(uint64*)dst = DOUBLE_NEG_ZERO;
    } else {
        parseFloat( *(float*)src, &f, &e );
        f <<= 29;
        makeDouble( (double*)dst, f, e );
        if( f_isNeg( src ) ) {
            dneg( dst, dst );
        }
    }
}

void d2f( void *dst, void *src ) {
    uint64 f;
    int e;
    mpnum temp;

    if( d_isNan( src ) ) {
        *(uint32*)dst = FLOAT_NAN;
    } else if( d_isPosInf( src ) ) {
        *(uint32*)dst = FLOAT_POS_INF;
    } else if( d_isNegInf( src ) ) {
        *(uint32*)dst = FLOAT_NEG_INF;
    } else if( d_isPosZero( src ) ) {
        *(uint32*)dst = FLOAT_POS_ZERO;
    } else if( d_isNegZero( src ) ) {
        *(uint32*)dst = FLOAT_NEG_ZERO;
    } else {
        parseDouble( *(double*)src, &f, &e );
        mp_init( &temp, f );
        if( e + float_bias <= 0 && e + float_bias > -24 ) {
            mp_binround( &temp, &temp, 29 - (e + float_bias) + 1 );
            mp_shiftright( &temp, &temp, 29 - (e + float_bias) + 1 );
        } else {
            mp_binround( &temp, &temp, 29 );
            mp_shiftright( &temp, &temp, 29 );
        }
        mp_touint64( &f, &temp );
        makeFloat( (float*)dst, f, e );
        mp_free( &temp );
        if( d_isNeg( src ) ) {
            fneg( dst, dst );
        }
    }
}

void e2d( void *dst, void *src ) {
    uint64 f;
    int e;
    mpnum temp;

    if( e_isNan( src ) ) {
        *(uint64*)dst = DOUBLE_NAN;
    } else if( e_isPosInf( src ) ) {
        *(uint64*)dst = DOUBLE_POS_INF;
    } else if( e_isNegInf( src ) ) {
        *(uint64*)dst = DOUBLE_NEG_INF;
    } else if( e_isPosZero( src ) ) {
        *(uint64*)dst = DOUBLE_POS_ZERO;
    } else if( e_isNegZero( src ) ) {
        *(uint64*)dst = DOUBLE_NEG_ZERO;
    } else {
        parseExtended( (char*)src, &f, &e );
        mp_init( &temp, f );
        if( e + double_bias <= 0 && e + double_bias > -53 ) {
            mp_binround( &temp, &temp, 11 - (e + double_bias) + 1 );
            mp_shiftright( &temp, &temp, 11 - (e + double_bias) + 1 );
        } else {
            mp_binround( &temp, &temp, 11 );
            mp_shiftright( &temp, &temp, 11 );
        }
        mp_touint64( &f, &temp );
        makeDouble( (double*)dst, f, e );
        mp_free( &temp );
        if( e_isNeg( src ) ) {
            dneg( dst, dst );
        }
    }
}

void d2e( void *dst, void *src ) {
    uint64 f;
    int e;

    if( d_isNan( src ) ) {
        makeExtNan( dst );
    } else if( d_isPosInf( src ) ) {
        makeExtPosInf( dst );
    } else if( d_isNegInf( src ) ) {
        makeExtNegInf( dst );
    } else if( d_isPosZero( src ) ) {
        makeExtPosZero( dst );

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?