Logo Search packages:      
Sourcecode: jikes version File versions  Download package

double.cpp

// $Id: double.cpp,v 1.35 2004/06/02 11:26:21 elliott-oss Exp $
//
// This software is subject to the terms of the IBM Jikes Compiler
// License Agreement available at the following URL:
// http://ibm.com/developerworks/opensource/jikes.
// Copyright (C) 1996, 2004 IBM Corporation and others.  All Rights Reserved.
// You must accept the terms of that agreement to use this software.
//
//
// NOTES: The IEEE 754 emulation code in double.h and double.cpp within
// Jikes are adapted from code written by Alan M. Webb of IBM's Hursley
// lab in porting the Sun JDK to System/390.
//
//
//
// In addition, the code for emulating the remainder operator, %, is
// adapted from e_fmod.c, part of fdlibm, the Freely Distributable Math
// Library mentioned in the documentation of java.lang.StrictMath.  The
// original library is available at http://netlib2.cs.utk.edu/fdlibm.
//
// The code from fdlibm is copyrighted, as follows:
// ====================================================
// Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
//
// Developed at SunSoft, a Sun Microsystems, Inc. business.
// Permission to use, copy, modify, and distribute this
// software is freely granted, provided that this notice
// is preserved.
// ====================================================
//
//
//
// Likewise, the code for accurate conversions between floating point
// and decimal strings, in double.h, double.cpp, platform.h, and
// platform.cpp, is adapted from dtoa.c.  The original code can be
// found at http://netlib2.cs.utk.edu/fp/dtoa.c.
//
// The code in dtoa.c is copyrighted as follows:
//****************************************************************
//*
//* The author of this software is David M. Gay.
//*
//* Copyright (c) 1991, 2000, 2001 by Lucent Technologies.
//*
//* Permission to use, copy, modify, and distribute this software for any
//* purpose without fee is hereby granted, provided that this entire notice
//* is included in all copies of any software which is or includes a copy
//* or modification of this software and in all copies of the supporting
//* documentation for such software.
//*
//* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
//* WARRANTY.  IN PARTICULAR, NEITHER THE AUTHOR NOR LUCENT MAKES ANY
//* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
//* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
//*
//***************************************************************/
//
//

#include "double.h"
#include "long.h"
#include "code.h"

#ifdef HAVE_JIKES_NAMESPACE
namespace Jikes { // Open namespace Jikes block
#endif

#ifndef HAVE_MEMBER_CONSTANTS
// VC++ can't cope with constant class members
IEEEfloat IEEEfloat::tens[] = {
    1e0f, 1e1f, 1e2f, 1e3f, 1e4f, 1e5f, 1e6f,
    1e7f, 1e8f, 1e9f, 1e10f
};
IEEEfloat IEEEfloat::bigtens[] = {
    1e8f, 1e16f, 1e32f
};

IEEEdouble IEEEdouble::tens[] = {
    1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7,
    1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15,
    1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22
};
IEEEdouble IEEEdouble::bigtens[] = {
    1e16, 1e32, 1e64, 1e128, 1e256
};
#else
const IEEEfloat IEEEfloat::tens[] = {
    1e0f, 1e1f, 1e2f, 1e3f, 1e4f, 1e5f, 1e6f,
    1e7f, 1e8f, 1e9f, 1e10f
};
const IEEEfloat IEEEfloat::bigtens[] = {
    1e8f, 1e16f, 1e32f
};

const IEEEdouble IEEEdouble::tens[] = {
    1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7,
    1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15,
    1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22
};
const IEEEdouble IEEEdouble::bigtens[] = {
    1e16, 1e32, 1e64, 1e128, 1e256
};
#endif


IEEEfloat::IEEEfloat(i4 a)
{
#ifdef HAVE_IEEE754
    value.float_value = (float) a;
#else
    int sign = 0;

    if (a < 0)
    {
        a  = -a; // even works for MIN_INT!
        sign = 1;
    }
    *this = (a == 0) ? POSITIVE_ZERO()
        : Normalize(sign, FRACT_SIZE, (u4) a);
#endif // HAVE_IEEE754
}

IEEEfloat::IEEEfloat(const LongInt &a)
{
#ifdef HAVE_IEEE754
# ifdef HAVE_64BIT_TYPES
    value.float_value = (float)(i8) a.Words();
# else
    value.float_value = ((float)(i4) a.HighWord() * (float) 0x40000000 * 4.0f)
        + (float) a.LowWord();
# endif // HAVE_64BIT_TYPES
#else
    //
    // Unfortunately, we cannot recycle the LongInt.DoubleValue() method, since
    // in rare cases the double rounding puts us off by one bit.
    //
    int sign = 0;
    LongInt l = a;

    if (a < 0)
    {
        l = -a;
        sign = 1;
        if (l < 0) // special case MIN_LONG
        {
            value.word = MIN_LONG_F;
            return;
        }
    }
    if (l == 0)
        *this = POSITIVE_ZERO();
    else if (l.HighWord() == 0)
        *this = Normalize(sign, FRACT_SIZE, l.LowWord());
    else
    {
        int exponent = FRACT_SIZE - 1, sticky = 0;
        while (l.HighWord())
        {
            sticky |= (l.LowWord() & BYTE_MASK) ? 1 : 0;
            l >>= 8;
            exponent += 8;
        }
        u4 low = l.LowWord();
        if ((i4) low < 0)
        {
            sticky |= (low & BYTE_MASK) ? 1 : 0;
            low >>= 8;
            exponent += 8;
        }
        *this = Normalize(sign, exponent, low + low + sticky);
    }
#endif // HAVE_IEEE754
}

IEEEfloat::IEEEfloat(const IEEEdouble &d)
{
#ifdef HAVE_IEEE754
    value.float_value = (float) d.DoubleView();
#else
    // Either true zero, denormalized, or too small
    if (d.Exponent() < -BIAS - 30)
        *this = (d.IsPositive() ? POSITIVE_ZERO() : NEGATIVE_ZERO());
    else
    {
        if (d.IsPositiveInfinity())
            *this = POSITIVE_INFINITY();
        else if (d.IsNegativeInfinity())
            *this = NEGATIVE_INFINITY();
        else if (d.IsNaN())
            *this = NaN();
        else
        {
            //
            // A regular, normalized number - do work on the parts
            // Shift to 26th position, add implicit msb, rounding bits
            //
            LongInt fract = d.Fraction() << 5;
            u4 fraction = fract.HighWord() | (fract.LowWord() ? 0x02000001
                                                              : 0x02000000);

            *this = Normalize(d.Sign(), d.Exponent() - 2, fraction);
        }
    }
#endif // HAVE_IEEE754
}

bool IEEEfloat::Adjust(const BigInt &delta, const BigInt &bs, const bool dsign)
{
    IEEEfloat aadj, aadj1;
    i4 y;

    aadj = Ratio(delta, bs);
    if (aadj <= 2)
    {
        if (dsign)
            aadj = aadj1 = 1;
        else if (FractBits())
        {
            if (value.word == 1)
            {
                // underflow
                *this = POSITIVE_ZERO();
                return true;
            }
            aadj = 1;
            aadj1 = -1;
        }
        else
        {
            //
            // special case - mantissa is power of 2
            //
            if (aadj < 1.0f)
                aadj = 0.5f;
            else
                aadj *= 0.5f;
            aadj1 = -aadj;
        }
    }
    else
    {
        aadj *= 0.5f;
        aadj1 = dsign ? aadj : -aadj;
    }
    y = Exponent();
    //
    // Check for overflow
    //
    if (y == BIAS)
    {
        IEEEfloat tmp(*this);
        value.word -= (FRACT_SIZE + 1) * MIN_FRACT;
        *this += aadj1 * Ulp();
        if (Exponent() >= BIAS - FRACT_SIZE)
        {
            if (tmp.value.word == POS_INF - 1)
            {
                // overflow
                *this = POSITIVE_INFINITY();
                return true;
            }
            value.word = POS_INF - 1;
            return false;
        }
        else
            value.word += (FRACT_SIZE + 1) * MIN_FRACT;
    }
    else
    {
        //
        // Compute adj so that the IEEE rounding rules will
        // correctly round *this + adj in some half-way cases.
        // If *this * Ulp() is denormalized, we must adjust aadj
        // to avoid trouble from bits lost to denormalization.
        //
        if (y <= FRACT_SIZE - BIAS || aadj > 1)
        {
            aadj1 = IEEEfloat((aadj + 0.5f).IntValue());
            if (! dsign)
                aadj1 = -aadj1;
        }
        *this += aadj1 * Ulp();
    }
    if (y == Exponent())
    {
        //
        // Can we stop now?
        // The tolerances below are conservative.
        //
        aadj -= aadj.IntValue();
        if (dsign || FractBits())
        {
            if (aadj < .4999999f || aadj > .5000001f)
                return true;
        }
        else if (aadj < .4999999f / 2)
            return true;
    }
    return false;
}

IEEEfloat::IEEEfloat(const char *str, bool check_invalid)
{
    int bb2, bb5, bbe, bd2, bd5, bbbits, bs2,
        e, e1, i, j, k;
    int nd, // number of digits in mantissa (except extra '0's)
        nd0, // number of digits before '.' (except leading '0's)
        nf, // number of digits after '.' (except trailing '0's)
        nz; // number of consecutive '0' digits
    bool nz0, // whether leading zero exists
         roundup, // whether to round up long string
         sign, // if the string represents a negative
         dsign, // the sign of delta
         esign; // the sign of the exponent
    char c;
    const char *s, *s0, *s1;
    i4 L;
    i4 y, z;

    sign = nz0 = roundup = false;
    nz = 0;

    //
    // consume whitespace
    //
    for (s = str; ; s++)
    {
        switch (*s)
        {
        case U_MINUS:
            sign = true;
            // fallthrough
        case U_PLUS:
            if (*++s)
                goto break2;
            // fallthrough
        case U_NU:
            *this = NaN();
            return;
        case U_SP:
        case U_HT:
        case U_FF:
        case U_LF:
        case U_CR:
            continue;
        default:
            goto break2;
        }
    }
 break2:
    //
    // Consume leading zeroes.
    //
    if (*s == U_0)
    {
        nz0 = true;
        while (*++s == U_0);

        if (! *s)
        {
            *this = sign ? NEGATIVE_ZERO() : POSITIVE_ZERO();
            return;
        }
        //
        // Parse hexadecimal floating point.
        //
        else if (*s == U_x || *s == U_X)
        {
            i4 fraction = 0;
            // Exponent adjustment, based on '.' location.
            int shift = FRACT_SIZE;
            bool seen_dot = false;
            while (*++s && *s == U_0); // Consume leading zeroes.
            c = *s;
            if (c == U_DOT)
            {
                seen_dot = true;
                while (*++s && *s == U_0)
                    shift -= 4;
                c = *s;
            }
            if (! c || c == U_p || c == U_P)
            {
                *this = sign ? NEGATIVE_ZERO() : POSITIVE_ZERO();
                return;
            }
            // To avoid overflow, stop after enough bits have been read.
            for (i = 0; i < (FRACT_SIZE >> 2) + 2 && c; i++, c = *++s)
            {
                if (c == U_DOT)
                {
                    if (seen_dot)
                        break;
                    c = *++s;
                    seen_dot = true;
                }
                int value;
                if (Code::IsHexDigit(c))
                    value = Code::Value(c);
                else break;
                if (seen_dot)
                    shift -= 4;
                fraction = (fraction << 4) + value;
            }
            // Round any remaining bits.
            bool sticky = false;
            while (c == U_DOT || Code::IsHexDigit(c))
            {
                if (c == U_DOT)
                {
                    if (seen_dot)
                        break;
                    seen_dot = true;
                }
                else
                {
                    if (! seen_dot)
                        shift += 4;
                    if (c != U_0)
                        sticky = true;
                }
                c = *++s;
            }
            assert(fraction != 0);
            if (sticky)
                fraction++;
            // On to the expononet.
            int exponent = 0;
            esign = false;
            if (c == U_p || c == U_P)
            {
                if (*++s == U_MINUS)
                {
                    esign = true;
                    s++;
                }
                else if (*s == U_PLUS)
                    s++;
                while ((c = *s++))
                {
                    if (! Code::IsDecimalDigit(c))
                        break;
                    exponent = exponent * 10 + c - U_0;
                    // Check for exponent overflow
                    if (exponent + shift > 19999)
                    {
                        if (check_invalid)
                            *this = NaN();
                        else
                        {
                            *this = esign ? POSITIVE_ZERO()
                                : POSITIVE_INFINITY();
                            if (sign)
                                *this = - *this;
                        }
                        return;
                    }
                }
            }
            if (esign)
                exponent = - exponent;
            *this = Normalize(sign, exponent + shift, fraction);
            if (check_invalid && (IsZero() || IsInfinite()))
                *this = NaN();
            return;
        }
    }

    //
    // parse before '.'
    //
    s0 = s;
    y = z = 0;
    for (nd = nf = 0; Code::IsDecimalDigit(c = *s); nd++, s++)
        if (nd < 8)
            y = 10 * y + c - U_0;
    nd0 = nd;
    if (c == U_DOT)
    {
        //
        // parse after '.'
        //
        c = *++s;
        if (!nd)
        {
            for ( ; c == U_0; c = *++s)
                nz++;
            if (c > U_0 && c <= U_9)
            {
                s0 = s;
                nf += nz;
                nz = 0;
            }
        }
        for ( ; Code::IsDecimalDigit(c); c = *++s)
        {
            nz++;
            if (c -= U_0)
            {
                nf += nz;
                for (i = 1; i < nz; i++)
                    if (nd++ < 8)
                        y *= 10;
                if (nd++ < 8)
                    y = 10 * y + c;
                nz = 0;
            }
        }
    }
    //
    // consume exponent
    //
    e = 0;
    if (c == U_e || c == U_E) {
        str = s;
        esign = false;
        switch (c = *++s)
        {
        case U_MINUS:
            esign = true;
            // fallthrough
        case U_PLUS:
            c = *++s;
        }
        if (Code::IsDecimalDigit(c))
        {
            if (!nd && !nz && !nz0)
            {
                *this = sign ? NEGATIVE_ZERO() : POSITIVE_ZERO();
                return;
            }
            while (c == U_0)
                c = *++s;
            if (c > U_0 && c <= U_9)
            {
                L = c - U_0;
                s1 = s;
                while (Code::IsDecimalDigit(c = *++s))
                    L = 10 * L + c - U_0;
                //
                // Avoid confusion from exponents so large that e might
                // overflow
                if (s - s1 > 8 || L > 19999)
                    e = 19999;
                else
                    e = L;
                if (esign)
                    e = -e;
            }
            else
                e = 0;
        }
        else
            s = str;
    }
    if (!nd) {
        *this = (!nz && !nz0) ? NaN()
                              : sign ? NEGATIVE_ZERO() : POSITIVE_ZERO();
        return;
    }
    //
    // for long strings, round away all digits beyond maximum precise string
    // for fraction, there are n decimal digits after '.' if lsb is 2^n;
    // but the first m of these digits are '0', for d = x*10^m
    // so, digits after MAX_DIGITS may be ignored
    //
    if (nd > MAX_DIGITS)
    {
        k = nd - MAX_DIGITS;
        i = MAX_DIGITS - nd0;
        if (i <= 0)
        {
            // decimal after last precise digit
            nd0 = MAX_DIGITS;
            nf = i;
            j = 0;
        }
        else if (i == MAX_DIGITS)
        {
            // decimal before first precise digit
            nf -= k;
            j = 0;
        }
        else
        {
            // decimal inside precise digits
            nf -= k;
            j = 1;
        }
        roundup = s0[MAX_DIGITS - 1 + j] != U_4;
        nd = MAX_DIGITS;
    }
    e1 = e -= nf;

    //
    // Now we have nd0 digits, starting at s0, followed by a
    // decimal point, followed by nd-nd0 digits.  The number we're
    // after is the integer represented by those digits times 10**e
    //
    if (! nd0)
        nd0 = nd;
    k = nd < 8 ? nd : 8;
    *this = IEEEfloat(y);
    if (nd < 8)
    {
        if (!e)
        {
            if (sign)
                *this = -*this;
            return;
        }
        if (e > 0)
        {
            if (e <= 10)
            {
                *this *= tens[e];
                if (sign)
                    *this = -*this;
                return;
            }
            i = 7 - nd;
            if (e <= 10 + i)
            {
                e -= i;
                *this *= tens[i];
                *this *= tens[e];
                if (sign)
                    *this = -*this;
                return;
            }
        }
        else if (e >= -10 )
        {
            *this /= tens[-e];
            if (sign)
                *this = -*this;
            return;
        }
    }
    e1 += nd - k;

    //
    // Get starting approximation: *this * 10**e1
    //
    if (e1 > 0)
    {
        i = e1 & 7;
        if (i)
            *this *= tens[i];
        if (e1 >>= 3)
        {
            if (e1 > MAX_DEC_EXP >> 3)
            {
                *this = check_invalid ? NaN()
                                      : sign ? NEGATIVE_INFINITY()
                                             : POSITIVE_INFINITY();
                return;
            }
            for (j = 0; e1 > 1; j++, e1 >>= 1)
                if (e1 & 1)
                    *this *= bigtens[j];
            //
            // The last multiplication could overflow.
            //
            value.word -= (FRACT_SIZE + 1) * MIN_FRACT;
            *this *= bigtens[j];
            z = Exponent();
            if (z > BIAS - FRACT_SIZE)
            {
                *this = check_invalid ? NaN()
                                      : sign ? NEGATIVE_INFINITY()
                                             : POSITIVE_INFINITY();
                return;
            }
            if (z > BIAS - FRACT_SIZE - 1)
                value.word = POS_INF - 1;
            else
                value.word += (FRACT_SIZE + 1) * MIN_FRACT;
        }
    }
    else if (e1 < 0)
    {
        e1 = -e1;
        i = e1 & 7;
        if (i)
            *this /= tens[i];
        if (e1 >>= 3)
        {
            if (e1 >= 1 << 3)
            {
                *this = check_invalid ? NaN()
                                      : sign ? NEGATIVE_ZERO()
                                             : POSITIVE_ZERO();
                return;
            }
            for (j = 0; e1 > 1; j++, e1 >>= 1)
                if (e1 & 1)
                    *this /= bigtens[j];
            //
            // The last multiplication could underflow.
            //
            IEEEfloat tmp(*this);
            *this /= bigtens[j];
            if (IsZero())
            {
                *this = tmp * 2;
                *this /= bigtens[j];
                if (IsZero())
                {
                    *this = check_invalid ? NaN()
                                          : sign ? NEGATIVE_ZERO()
                                                 : POSITIVE_ZERO();
                    return;
                }
                value.word = 1;
            }
        }
    }

    //
    // Now the hard part -- adjusting *this to the correct value.
    // Put digits into bd: true value = bd * 10^e
    //
    BigInt bd0(s0, nd0, nd, y, 8);
    if (roundup)
        ++bd0;
    while (true) {
        BigInt bd(bd0);
        BigInt bb(*this, bbe, bbbits); // *this = bb * 2^bbe
        BigInt bs(1);
        if (e >= 0)
        {
            bb2 = bb5 = 0;
            bd2 = bd5 = e;
        }
        else
        {
            bb2 = bb5 = -e;
            bd2 = bd5 = 0;
        }
        if (bbe >= 0)
            bb2 += bbe;
        else
            bd2 -= bbe;
        bs2 = bb2;
        j = bbe;
        i = j + bbbits - 1; // logb(*this)
        if (i < 1 - BIAS) // denormal
            j += BIAS + FRACT_SIZE;
        else
            j = FRACT_SIZE + 2 - bbbits;
        bb2 += j;
        bd2 += j;
        i = bb2 < bd2 ? bb2 : bd2;
        if (i > bs2)
            i = bs2;
        if (i > 0)
        {
            bb2 -= i;
            bd2 -= i;
            bs2 -= i;
        }
        if (bb5 > 0) {
            bs.pow5mult(bb5);
            bb *= bs;
        }
        if (bb2 > 0)
            bb <<= bb2;
        if (bd5 > 0)
            bd.pow5mult(bd5);
        if (bd2 > 0)
            bd <<= bd2;
        if (bs2 > 0)
            bs <<= bs2;
        BigInt delta = bb - bd;
        dsign = delta.IsNegative();
        if (dsign)
            delta.IsNegative(false);
        i = delta.compareTo(bs);
        //
        // Error is less than half an ulp -- check for
        // special case of mantissa a power of two.
        //
        if (i < 0)
        {
            if (dsign || FractBits() || Exponent() <= 1 - BIAS
                || delta.IsZero())
                break;
            delta <<= 1;
            if (delta.compareTo(bs) > 0)
                // boundary case -- decrement exponent
                value.word--;
            break;
        }
        //
        // exactly half-way between
        //
        else if (i == 0)
        {
            if (value.word & 1)
                value.word += dsign ? 1 : -1;
            break;
        }
        //
        // more than 1/2 ulp off - try again
        //
        // This is broken into a separate method because mingw gcc 2.95.2
        // has an ICE caused by register over-allocation if it is inline.
        //
        if (Adjust(delta, bs, dsign))
            break;
    }
    if (check_invalid && (IsZero() || IsInfinite()))
        *this = NaN();
    else if (sign)
        *this = -*this;
}

i4 IEEEfloat::IntValue() const
{
    if (IsNaN())
        return 0;

    int sign = Sign(),
        exponent = Exponent();

    if (exponent > 30)
        return sign ? Int::MIN_INT() : Int::MAX_INT();

    // This covers true zero and denorms.
    if (exponent < 0)
        return 0;

    i4 result = Fraction();

    if (exponent > FRACT_SIZE)
        result <<= (exponent - FRACT_SIZE);
    else if (exponent < FRACT_SIZE)
        result >>= (FRACT_SIZE - exponent);

    return sign ? -result : result;
}

LongInt IEEEfloat::LongValue() const
{
    if (IsNaN())
        return LongInt(0);

    int sign = Sign(),
        exponent = Exponent();

    if (exponent > 62)
        return sign ? LongInt::MIN_LONG() : LongInt::MAX_LONG();

    // This covers true zero and denorms.
    if (exponent < 0)
        return LongInt(0);

    LongInt result(Fraction());

    if (exponent > FRACT_SIZE)
        result <<= (exponent - FRACT_SIZE);
    else if (exponent < FRACT_SIZE)
        result >>= (FRACT_SIZE - exponent);

    return sign ? (LongInt) -result : result;
}

IEEEfloat IEEEfloat::Normalize(int sign, int exponent, u4 fraction)
{
    bool round = false, sticky = false;

    assert(fraction != 0);

    //
    // Normalize right. Shift until value < MAX_FRACT.
    //
    if (fraction >= MAX_FRACT)
    {
        while (fraction >= MAX_FRACT)
        {
            sticky |= round;
            round = (fraction & 1) != 0;
            fraction >>= 1;
            exponent++;
        }
        if (round && (sticky || (fraction & 1)) && exponent > -BIAS)
            //
            // Capture any overflow caused by rounding. No other checks are
            // required because if overflow occurred, the the low order bit
            // was guaranteed to be zero. Do not round denorms yet.
            //
            if (++fraction >= MAX_FRACT)
            {
                fraction >>= 1;
                exponent++;
            }
    }

    //
    // Normalize left.  Shift until value >= MIN_FRACT.
    //
    else
        while (fraction < MIN_FRACT)
        {
            fraction <<= 1;
            exponent--;
        }

    //
    // Check and respond to overflow
    //
    if (exponent > BIAS)
        return sign ? NEGATIVE_INFINITY() : POSITIVE_INFINITY();

    //
    // Check and respond to underflow
    //
    if (exponent <= -BIAS)
    {
        if (exponent < -BIAS - FRACT_SIZE)
            return sign ? NEGATIVE_ZERO() : POSITIVE_ZERO();
        while (exponent <= -BIAS)
        {
            sticky |= round;
            round = (fraction & 1) != 0;
            fraction >>= 1;
            exponent++;
        }
        if (round && (sticky || (fraction & 1)))
            fraction++;
        exponent = -BIAS;
        if (fraction == 0)
            return sign ? NEGATIVE_ZERO() : POSITIVE_ZERO();
    }

    fraction &= FRACT_BITS;
    fraction |= ((exponent + BIAS) << FRACT_SIZE);
    if (sign)
        fraction |= SIGN_BIT;
    return IEEEfloat(fraction);
}

int IEEEfloat::SplitInto(u4 &fraction) const
{
    int exponent = Exponent();
    fraction = Fraction();

    if (exponent == -BIAS)
    {
        exponent++;
        while (fraction < MIN_FRACT)
        {
            fraction <<= 1;
            exponent--;
        }
    }

    return exponent;
}

IEEEfloat IEEEfloat::Ulp() const
{
    i4 L;
    IEEEfloat f;
    f.value.float_value = value.float_value;

    L = (i4) f.ExpBits() - FRACT_SIZE * MIN_FRACT;
    if (L > 0)
        f.value.iword = L;
    else
    {
        L = -L >> FRACT_SIZE;
        f.value.iword = L >= (i4) FRACT_SIZE ? 1 : 0x400000 >> L;
    }
    return f;
}

IEEEfloat IEEEfloat::Ratio(const BigInt &a, const BigInt &b)
{
    IEEEfloat fa, fb;
    int k;
    fa = a.FloatValue();
    fb = b.FloatValue();
    k = b.hi0bits() - a.hi0bits() + 32 * (a.wds - b.wds);
    if (k > 0)
        fa.value.word += k * MIN_FRACT;
    else
        fb.value.word -= k * MIN_FRACT;
    return fa / fb;
}

bool IEEEfloat::operator== (const IEEEfloat op) const
{
    // FIXME: This could be sped up by inlining
#ifdef HAVE_IEEE754
    return value.float_value == op.value.float_value;
#else
    return (IsNaN() || op.IsNaN() ? false
            : IsZero() && op.IsZero() ? true
            : value.word == op.value.word);
#endif
}

bool IEEEfloat::operator!= (const IEEEfloat op) const
{
    // FIXME: This could be sped up by inlining
#ifdef HAVE_IEEE754
    return value.float_value != op.value.float_value;
#else
    return ! (*this == op);
#endif
}

bool IEEEfloat::operator< (const IEEEfloat op) const
{
    // FIXME: This could be sped up by inlining
#ifdef HAVE_IEEE754
    return (value.float_value < op.value.float_value);
#else
    if (IsNaN() || op.IsNaN())
        return false; // NaNs are unordered
    if (IsZero() && op.IsZero())
        return false;
    // Exploit fact that all other IEEE floating point numbers sort like
    // ints after worrying about sign.
    if (IsNegative())
        return op.IsPositive() ||
            (value.word & ABS_BITS) > (op.value.word & ABS_BITS);
    return op.IsPositive() &&
        (value.word & ABS_BITS) < (op.value.word & ABS_BITS);
#endif
}

bool IEEEfloat::operator<= (const IEEEfloat op) const
{
    // FIXME: This could be sped up by inlining
#ifdef HAVE_IEEE754
    return (value.float_value <= op.value.float_value);
#else
    return *this < op || *this == op;
#endif
}

bool IEEEfloat::operator> (const IEEEfloat op) const
{
    // FIXME: This could be sped up by inlining
#ifdef HAVE_IEEE754
    return (value.float_value > op.value.float_value);
#else
    if (IsNaN() || op.IsNaN())
        return false; // NaNs are unordered.
    if (IsZero() && op.IsZero())
        return false;
    // Exploit fact that all other IEEE floating point numbers sort like
    // ints after worrying about sign.
    if (IsPositive())
        return op.IsNegative() ||
            (value.word & ABS_BITS) > (op.value.word & ABS_BITS);
    return op.IsNegative() &&
        (value.word & ABS_BITS) < (op.value.word & ABS_BITS);
#endif
}

bool IEEEfloat::operator>= (const IEEEfloat op) const
{
    // FIXME: This could be sped up by inlining
#ifdef HAVE_IEEE754
    return (value.float_value >= op.value.float_value);
#else
    return *this > op || *this == op;
#endif
}

IEEEfloat IEEEfloat::operator+ (const IEEEfloat op) const
{
#ifdef HAVE_IEEE754
    // FIXME: This could be sped up by inlining
    return IEEEfloat(value.float_value + op.value.float_value);
#else
    if (IsNaN() || op.IsNaN())
        return NaN(); // arithmetic on NaNs not allowed

    //
    // Adding unlike infinities not allowed
    // Adding infinities of same sign is infinity of that sign
    // Adding finite and infinity produces infinity
    //
    if (IsInfinite())
        return op.IsInfinite() && (Sign() != op.Sign()) ? NaN() : *this;
    if (op.IsInfinite())
        return op;

    //
    // Adding zero is easy
    //
    if (IsZero())
        return (op.IsZero()) ? (Sign() != op.Sign()) ? POSITIVE_ZERO()
                                                     : *this
                             : op;
    if (op.IsZero())
        return *this;

    //
    // Now for the real work - do manipulations on copies
    //
    i4 x, y, round = 0;
    int expx, expy, signx, signy;

    expx = SplitInto((u4 &) x);
    expy = op.SplitInto((u4 &) y);

    signx = Sign();
    signy = op.Sign();

    // If the exponents are far enough apart, the answer is easy
    if (expx > expy + 25)
        return *this;
    if (expy > expx + 25)
        return op;

    //
    // Denormalize the fractions, so that the exponents are
    // the same and then set the exponent for the result.
    // Leave enough space for overflow and INT_MIN avoidance!
    //
    if (signx)
        x = -x;
    if (signy)
        y = -y;

    x <<= 6;
    y <<= 6;

    if (expx > expy) {
        round = y << (32 + expy - expx);
        y >>= expx - expy;
    }
    else if (expy > expx)
    {
        round = x << (32 + expx - expy);
        x >>= expy - expx;
        expx = expy;
    }

    //
    // Do the arithmetic. The excess magnitude of 32-bit arithmetic means
    // overflow is impossible (we only need 1 spare bit!). We ensure that
    // pre-alignment avoids any question of INT_MIN negation problems.
    //
    x += y;
    if (round)
        x |= 1;

    //
    // If the result is negative, then make the fraction positive again
    // and remember the sign.
    //
    if (x < 0)
    {
        x = -x;
        signx = 1;
    }
    else
        signx = 0;

    if (x == 0)
        return signx ? NEGATIVE_ZERO() : POSITIVE_ZERO();

    //
    // Time to normalize again! If we need to shift left (the addition was
    // effectively a subtraction), then there cannot be any reason to round.
    // If the number fits exactly we don't have anything to do either.
    //
    return Normalize(signx, expx - 6, (u4) x);
#endif
}

IEEEfloat IEEEfloat::operator- () const
{
    // FIXME: This could be sped up by inlining
#ifdef HAVE_IEEE754
    return IEEEfloat(-value.float_value);
#else
    if (IsNaN())
        return *this;
    return IEEEfloat(value.word ^ SIGN_BIT);
#endif
}

IEEEfloat IEEEfloat::operator* (const IEEEfloat op) const
{
#ifdef HAVE_IEEE754
    return IEEEfloat(value.float_value * op.value.float_value);
#else
    if (IsNaN() || op.IsNaN())
        return NaN(); // arithmetic on NaNs not allowed

    int sign = Sign() ^ op.Sign();

    //
    // If either operand is zero or infinite, then the answer is easy.
    //
    if (IsZero())
        return op.IsInfinite() ? NaN()
                               : sign ? NEGATIVE_ZERO() : POSITIVE_ZERO();

    if (op.IsZero())
        return IsInfinite() ? NaN()
                            : sign ? NEGATIVE_ZERO() : POSITIVE_ZERO();

    if (IsInfinite() || op.IsInfinite())
        return sign ? NEGATIVE_INFINITY() : POSITIVE_INFINITY();

    //
    // Now for the real work - do manipulations on copies
    //
    u4 x, y;
    int exponent;

    exponent = SplitInto(x) + op.SplitInto(y);

    //
    // The numbers to be multiplied are 24 bits in length (stored in 32 bit
    // integers). Using ULongInt to perform the multiplication, the result
    // will be 46-48 bits (unsigned); shift it back to 28 bits for Normalize,
    // while folding the low 20 bits into the lsb for rounding purposes.
    //

    ULongInt a = x,
             b = y;
    a *= b;
    b = a & 0xfffff;
    a >>= 20;
    x = a.LowWord() | ((b > 0) ? 1 : 0);

    return Normalize(sign, exponent - 3, x);
#endif // HAVE_IEEE754
}

IEEEfloat IEEEfloat::operator/ (const IEEEfloat op) const
{
#ifdef HAVE_IEEE754
    return op.IsZero() ? ((IsNaN() || IsZero()) ? NaN()
                               : (IsPositive() ^ op.IsPositive())
                                       ? NEGATIVE_INFINITY()
                                       : POSITIVE_INFINITY())
                       : IEEEfloat(value.float_value / op.value.float_value);
#else // HAVE_IEEE754
    if (IsNaN() || op.IsNaN())
        return NaN(); // arithmetic on NaNs not allowed

    int sign = Sign() ^ op.Sign();

    //
    // Infinities and zeroes are special.
    //

    if (IsInfinite())
        return (op.IsInfinite() ? NaN()
                : sign ? NEGATIVE_INFINITY() : POSITIVE_INFINITY());

    if (op.IsInfinite())
        return sign ? NEGATIVE_ZERO() : POSITIVE_ZERO();

    if (IsZero())
        return op.IsZero() ? NaN()
                           : sign ? NEGATIVE_ZERO() : POSITIVE_ZERO();

    if (op.IsZero())
        return sign ? NEGATIVE_INFINITY() : POSITIVE_INFINITY();

    //
    // Now for the real work - do manipulations on copies
    //
    u4 x, y;
    int exponent;

    exponent = SplitInto(x) - op.SplitInto(y);

    u4  mask   = 0x80000000,
        result = 0;

    // Because both values are normalised, a single shift guarantees results.

    if (x < y)
    {
        x <<= 1;
        exponent--;
    }

    //
    // If the numerator is larger, then it is divisible.
    // Reflect this in the result, and do the subtraction.
    // Magnify the numerator again and reduce the mask.
    //
    while (mask)
    {
        if (x >= y)
        {
            result += mask;
            x -= y;
            if (x == 0)
                break;
        }
        x <<= 1;
        mask >>= 1;
    }

    return Normalize(sign, exponent - 8, result);
#endif // HAVE_IEEE754
}

IEEEfloat IEEEfloat::operator% (const IEEEfloat op) const
{
#ifdef HAVE_IEEE754
    return IEEEfloat((op.IsZero() ? NaN().value.float_value
                      : (float) fmod((double) value.float_value,
                                     (double) op.value.float_value)));
#else // HAVE_IEEE754
    if (IsNaN() || op.IsNaN())
        return NaN(); // arithmetic on NaNs not allowed

    //
    // Infinities and zeroes are special.
    //

    if (IsInfinite() || op.IsZero())
        return NaN();

    if (IsZero() || op.IsInfinite())
        return *this;

    //
    // Now for the real work - do manipulations on copies
    // This algorithm is from fdlibm.c - see above notice
    //

    int sign = Sign();
    u4 x, y;
    int expy, exponent;
    i4 z;

    expy = op.SplitInto(y);
    exponent = SplitInto(x) - expy;

    if (exponent < 0 || (exponent == 0 && x < y))
        return *this;

    while (exponent--)
    {
        z = x - y;
        if (z < 0)
            x <<= 1;
        else if (z == 0)
            return sign ? NEGATIVE_ZERO() : POSITIVE_ZERO();
        else
            x = z + z;
    }
    z = x - y;
    if (z >= 0)
        x = z;

    if (x == 0)
        return sign ? NEGATIVE_ZERO() : POSITIVE_ZERO();
    return Normalize(sign, expy, x);
#endif // HAVE_IEEE754
}



IEEEdouble::IEEEdouble(const IEEEfloat &f)
{
#ifdef HAVE_IEEE754
    value.double_value = (double) f.FloatView();
#else
    int sign = f.Sign();
    int exponent = f.Exponent();

    if (exponent == -IEEEfloat::Bias())
    {
        if (f.IsZero())
            *this = sign ? NEGATIVE_ZERO() : POSITIVE_ZERO();
        else
        {
            //
            // This is a denormalized number, shift it to fit double format
            //
            *this = Normalize(sign, 1 - IEEEfloat::Bias(),
                              ULongInt(f.Fraction()) << 29);
        }
    }
    else
    {
        if (f.IsInfinite())
            *this = sign ? NEGATIVE_INFINITY() : POSITIVE_INFINITY();
        else if (f.IsNaN())
            *this = NaN();
        else
        {
            // Regular, normalized number.  Shift it to fit double format
            *this = Normalize(sign, exponent, ULongInt(f.Fraction()) << 29);
        }
    }
#endif // HAVE_IEEE754
}

IEEEdouble::IEEEdouble(i4 a)
{
#ifdef HAVE_IEEE754
    value.double_value = (double) a;
#else
    int sign = 0;

    if (a < 0)
    {
        a  = -a; // even works for MIN_INT!
        sign = 1;
    }
    *this = (a == 0) ? POSITIVE_ZERO()
        : Normalize(sign, FRACT_SIZE, ULongInt((u4) a));
#endif // HAVE_IEEE754
}

IEEEdouble::IEEEdouble(const LongInt &a)
{
#ifdef HAVE_IEEE754
# ifdef HAVE_64BIT_TYPES
    value.double_value = (double)(i8) a.Words();
# else
    value.double_value = ((double)(i4) a.HighWord() * (double) 0x40000000 *
                          4.0) + (double) a.LowWord();
# endif // HAVE_64BIT_TYPES
#else
    int sign = 0;
    LongInt l = a;

    if (a < 0)
    {
        l  = -a; // even works for MIN_LONG!
        sign = 1;
    }
    *this = (l == 0) ? POSITIVE_ZERO()
        : Normalize(sign, FRACT_SIZE, ULongInt(l));
#endif // HAVE_IEEE754
}

IEEEdouble::IEEEdouble(const char *str, bool check_invalid)
{
    int bb2, bb5, bbe, bd2, bd5, bbbits, bs2,
        e, e1, i, j, k;
    int nd, // number of digits in mantissa (except extra '0's)
        nd0, // number of digits before '.' (except leading '0's)
        nf, // number of digits after '.' (except trailing '0's)
        nz; // number of consecutive '0' digits
    bool nz0, // whether leading zero exists
         roundup, // whether to round up long string
         sign, // if the string represents a negative
         dsign, // the sign of delta
         esign; // the sign of the exponent
    char c;
    const char *s, *s0, *s1;
    IEEEdouble aadj, aadj1;
    i4 L;
    i4 y, z;

    sign = nz0 = roundup = false;
    nz = 0;

    //
    // consume whitespace
    //
    for (s = str; ; s++)
    {
        switch (*s)
        {
        case U_MINUS:
            sign = true;
            // fallthrough
        case U_PLUS:
            if (*++s)
                goto break2;
            // fallthrough
        case U_NU:
            *this = NaN();
            return;
        case U_SPACE:
        case U_HT:
        case U_FF:
        case U_LF:
        case U_CR:
            continue;
        default:
            goto break2;
        }
    }
 break2:
    //
    // Consume leading zeroes.
    //
    if (*s == U_0)
    {
        nz0 = true;
        while (*++s == U_0);

        if (! *s)
        {
            *this = sign ? NEGATIVE_ZERO() : POSITIVE_ZERO();
            return;
        }
        //
        // Parse hexadecimal floating point.
        //
        else if (*s == U_x || *s == U_X)
        {
            LongInt fraction = 0;
            // Exponent adjustment, based on '.' location.
            int shift = FRACT_SIZE;
            bool seen_dot = false;
            while (*++s && *s == U_0); // Consume leading zeroes.
            c = *s;
            if (c == U_DOT)
            {
                seen_dot = true;
                while (*++s && *s == U_0)
                    shift -= 4;
                c = *s;
            }
            if (! c || c == U_p || c == U_P)
            {
                *this = sign ? NEGATIVE_ZERO() : POSITIVE_ZERO();
                return;
            }
            // To avoid overflow, stop after enough bits have been read.
            for (i = 0; i < (FRACT_SIZE >> 2) + 2 && c; i++, c = *++s)
            {
                if (c == U_DOT)
                {
                    if (seen_dot)
                        break;
                    c = *++s;
                    seen_dot = true;
                }
                int value;
                if (Code::IsHexDigit(c))
                    value = Code::Value(c);
                else break;
                if (seen_dot)
                    shift -= 4;
                fraction = (fraction << 4) + value;
            }
            // Round any remaining bits.
            bool sticky = false;
            while (c == U_DOT || Code::IsHexDigit(c))
            {
                if (c == U_DOT)
                {
                    if (seen_dot)
                        break;
                    seen_dot = true;
                }
                else
                {
                    if (! seen_dot)
                        shift += 4;
                    if (c != U_0)
                        sticky = true;
                }
                c = *++s;
            }
            assert(fraction != 0);
            if (sticky)
                fraction++;
            // On to the expononet.
            int exponent = 0;
            esign = false;
            if (c == U_p || c == U_P)
            {
                if (*++s == U_MINUS)
                {
                    esign = true;
                    s++;
                }
                else if (*s == U_PLUS)
                    s++;
                while ((c = *s++))
                {
                    if (! Code::IsDecimalDigit(c))
                        break;
                    exponent = exponent * 10 + c - U_0;
                    // Check for exponent overflow
                    if (exponent + shift > 19999)
                    {
                        if (check_invalid)
                            *this = NaN();
                        else
                        {
                            *this = esign ? POSITIVE_ZERO()
                                : POSITIVE_INFINITY();
                            if (sign)
                                *this = - *this;
                        }
                        return;
                    }
                }
            }
            if (esign)
                exponent = - exponent;
            *this = Normalize(sign, exponent + shift, fraction);
            if (check_invalid && (IsZero() || IsInfinite()))
                *this = NaN();
            return;
        }
    }

    //
    // parse before '.'
    //
    s0 = s;
    y = z = 0;
    for (nd = nf = 0; Code::IsDecimalDigit(c = *s); nd++, s++)
        if (nd < 9)
            y = 10 * y + c - U_0;
        else if (nd < 16)
            z = 10 * z + c - U_0;
    nd0 = nd;
    if (c == U_DOT)
    {
        //
        // parse after '.'
        //
        c = *++s;
        if (!nd)
        {
            for ( ; c == U_0; c = *++s)
                nz++;
            if (c > U_0 && c <= U_9)
            {
                s0 = s;
                nf += nz;
                nz = 0;
            }
        }
        for ( ; Code::IsDecimalDigit(c); c = *++s)
        {
            nz++;
            if (c -= U_0)
            {
                nf += nz;
                for (i = 1; i < nz; i++)
                    if (nd++ < 9)
                        y *= 10;
                    else if (nd <= 16)
                        z *= 10;
                if (nd++ < 9)
                    y = 10 * y + c;
                else if (nd <= 16)
                    z = 10 * z + c;
                nz = 0;
            }
        }
    }
    //
    // consume exponent
    //
    e = 0;
    if (c == U_e || c == U_E) {
        str = s;
        esign = false;
        switch (c = *++s)
        {
        case U_MINUS:
            esign = true;
            // fallthrough
        case U_PLUS:
            c = *++s;
        }
        if (Code::IsDecimalDigit(c))
        {
            if (!nd && !nz && !nz0)
            {
                *this = sign ? NEGATIVE_ZERO() : POSITIVE_ZERO();
                return;
            }
            while (c == U_0)
                c = *++s;
            if (c > U_0 && c <= U_9)
            {
                L = c - U_0;
                s1 = s;
                while (Code::IsDecimalDigit(c = *++s))
                    L = 10 * L + c - U_0;
                //
                // Avoid confusion from exponents so large that e might
                // overflow
                if (s - s1 > 8 || L > 19999)
                    e = 19999;
                else
                    e = L;
                if (esign)
                    e = -e;
            }
            else
                e = 0;
        }
        else
            s = str;
    }
    if (!nd) {
        *this = (!nz && !nz0) ? NaN()
                              : sign ? NEGATIVE_ZERO() : POSITIVE_ZERO();
        return;
    }
    //
    // for long strings, round away all digits beyond maximum precise string
    // for fraction, there are n decimal digits after '.' if lsb is 2^n;
    // but the first m of these digits are '0', for d = x*10^m
    // so, digits after MAX_DIGITS may be ignored
    //
    if (nd > MAX_DIGITS)
    {
        k = nd - MAX_DIGITS;
        i = MAX_DIGITS - nd0;
        if (i <= 0)
        {
            // decimal after last precise digit
            nd0 = MAX_DIGITS;
            nf = i;
            j = 0;
        }
        else if (i == MAX_DIGITS)
        {
            // decimal before first precise digit
            nf -= k;
            j = 0;
        }
        else
        {
            // decimal inside precise digits
            nf -= k;
            j = 1;
        }
        roundup = s0[MAX_DIGITS - 1 + j] != U_4;
        nd = MAX_DIGITS;
    }
    e1 = e -= nf;

    //
    // Now we have nd0 digits, starting at s0, followed by a
    // decimal point, followed by nd-nd0 digits.  The number we're
    // after is the integer represented by those digits times 10**e
    //
    if (! nd0)
        nd0 = nd;
    k = nd < 16 ? nd : 16;
    *this = IEEEdouble(y);
    if (k > 9)
        *this = *this * tens[k - 9] + z;
    if (nd < 16)
    {
        if (!e)
        {
            if (sign)
                *this = -*this;
            return;
        }
        if (e > 0)
        {
            if (e <= 22)
            {
                *this *= tens[e];
                if (sign)
                    *this = -*this;
                return;
            }
            i = 15 - nd;
            if (e <= 22 + i)
            {
                e -= i;
                *this *= tens[i];
                *this *= tens[e];
                if (sign)
                    *this = -*this;
                return;
            }
        }
        else if (e >= -22 )
        {
            *this /= tens[-e];
            if (sign)
                *this = -*this;
            return;
        }
    }
    e1 += nd - k;

    //
    // Get starting approximation: *this * 10**e1
    //
    if (e1 > 0)
    {
        i = e1 & 0xf;
        if (i)
            *this *= tens[i];
        if (e1 >>= 4)
        {
            if (e1 > MAX_DEC_EXP >> 4)
            {
                *this = check_invalid ? NaN()
                                      : sign ? NEGATIVE_INFINITY()
                                             : POSITIVE_INFINITY();
                return;
            }
            for (j = 0; e1 > 1; j++, e1 >>= 1)
                if (e1 & 1)
                    *this *= bigtens[j];
            //
            // The last multiplication could overflow.
            //
            setHighWord(HighWord() - (FRACT_SIZE + 1) * MIN_FRACT);
            *this *= bigtens[j];
            z = Exponent();
            if (z > BIAS - FRACT_SIZE)
            {
                *this = check_invalid ? NaN()
                                      : sign ? NEGATIVE_INFINITY()
                                             : POSITIVE_INFINITY();
                return;
            }
            if (z > BIAS - FRACT_SIZE - 1)
                setHighAndLowWords(POS_INF_HI - 1, ZERO_LO - 1);
            else
                setHighWord(HighWord() + (FRACT_SIZE + 1) * MIN_FRACT);
        }
    }
    else if (e1 < 0)
    {
        e1 = -e1;
        i = e1 & 0xf;
        if (i)
            *this /= tens[i];
        if (e1 >>= 4)
        {
            if (e1 >= 1 << 5)
            {
                *this = check_invalid ? NaN()
                                      : sign ? NEGATIVE_ZERO()
                                             : POSITIVE_ZERO();
                return;
            }
            for (j = 0; e1 > 1; j++, e1 >>= 1)
                if (e1 & 1)
                    *this /= bigtens[j];
            //
            // The last multiplication could underflow.
            //
            IEEEdouble tmp(*this);
            *this /= bigtens[j];
            if (IsZero())
            {
                *this = tmp * 2;
                *this /= bigtens[j];
                if (IsZero())
                {
                    *this = check_invalid ? NaN()
                                          : sign ? NEGATIVE_ZERO()
                                                 : POSITIVE_ZERO();
                    return;
                }
                setHighAndLowWords(0, 1);
            }
        }
    }

    //
    // Now the hard part -- adjusting *this to the correct value.
    // Put digits into bd: true value = bd * 10^e
    //
    BigInt bd0(s0, nd0, nd, y, 9);
    if (roundup)
        ++bd0;
    while (true) {
        BigInt bd(bd0);
        BigInt bb(*this, bbe, bbbits); // *this = bb * 2^bbe
        BigInt bs(1);
        if (e >= 0)
        {
            bb2 = bb5 = 0;
            bd2 = bd5 = e;
        }
        else
        {
            bb2 = bb5 = -e;
            bd2 = bd5 = 0;
        }
        if (bbe >= 0)
            bb2 += bbe;
        else
            bd2 -= bbe;
        bs2 = bb2;
        j = bbe;
        i = j + bbbits - 1; // logb(*this)
        if (i < 1 - BIAS) // denormal
            j += BIAS + FRACT_SIZE;
        else
            j = FRACT_SIZE + 2 - bbbits;
        bb2 += j;
        bd2 += j;
        i = bb2 < bd2 ? bb2 : bd2;
        if (i > bs2)
            i = bs2;
        if (i > 0)
        {
            bb2 -= i;
            bd2 -= i;
            bs2 -= i;
        }
        if (bb5 > 0) {
            bs.pow5mult(bb5);
            bb *= bs;
        }
        if (bb2 > 0)
            bb <<= bb2;
        if (bd5 > 0)
            bd.pow5mult(bd5);
        if (bd2 > 0)
            bd <<= bd2;
        if (bs2 > 0)
            bs <<= bs2;
        BigInt delta = bb - bd;
        dsign = delta.IsNegative();
        if (dsign)
            delta.IsNegative(false);
        i = delta.compareTo(bs);
        //
        // Error is less than half an ulp -- check for
        // special case of mantissa a power of two.
        //
        if (i < 0)
        {
            if (dsign || LowWord() || FractBits()
                || Exponent() <= 1 - BIAS || delta.IsZero())
                break;
            delta <<= 1;
            if (delta.compareTo(bs) > 0)
                // boundary case -- decrement exponent
                BaseLong::operator --();
            break;
        }
        //
        // exactly half-way between
        //
        else if (i == 0)
        {
            if (LowWord() & 1)
                BaseLong::operator +=(dsign ? 1 : -1);
            break;
        }
        //
        // more than 1/2 ulp off - try again
        //
        aadj = Ratio(delta, bs);
        if (aadj <= 2)
        {
            if (dsign)
                aadj = aadj1 = 1;
            else if (FractBits() || LowWord())
            {
                if (!HighWord() && LowWord() == 1)
                {
                    // underflow
                    *this = POSITIVE_ZERO();
                    break;
                }
                aadj = 1;
                aadj1 = -1;
            }
            else
            {
                //
                // special case - mantissa is power of 2
                //
                if (aadj < 1.0)
                    aadj = 0.5;
                else
                    aadj *= 0.5;
                aadj1 = -aadj;
            }
        }
        else
        {
            aadj *= 0.5;
            //
            // gcc 2.95.2 has an ICE from too many registers with this line:
            //            aadj1 = dsign ? aadj : -aadj;
            //
            if (dsign)
                aadj1 = aadj;
            else
                aadj1 = -aadj;
        }
        y = Exponent();
        //
        // Check for overflow
        //
        if (y == BIAS)
        {
            IEEEdouble tmp(*this);
            setHighWord(HighWord() - (FRACT_SIZE + 1) * MIN_FRACT);
            *this += aadj1 * Ulp();
            if (Exponent() >= BIAS - FRACT_SIZE)
            {
                if (tmp.HighWord() == POS_INF_HI - 1 &&
                    tmp.LowWord() == ZERO_LO - 1)
                {
                    // overflow
                    *this = POSITIVE_INFINITY();
                    break;
                }
                setHighAndLowWords(POS_INF_HI - 1, ZERO_LO - 1);
                continue;
            }
            else
                setHighWord(HighWord() + (FRACT_SIZE + 1) * MIN_FRACT);
        }
        else
        {
            //
            // Compute adj so that the IEEE rounding rules will
            // correctly round *this + adj in some half-way cases.
            // If *this * Ulp() is denormalized, we must adjust aadj
            // to avoid trouble from bits lost to denormalization.
            //
            if (y <= FRACT_SIZE - BIAS || aadj > 1)
            {
                aadj1 = IEEEdouble((aadj + 0.5).IntValue());
                if (! dsign)
                    aadj1 = -aadj1;
            }
            *this += aadj1 * Ulp();
        }
        if (y == Exponent())
        {
            //
            // Can we stop now?
            // The tolerances below are conservative.
            //
            aadj -= aadj.IntValue();
            if (dsign || FractBits() || LowWord())
            {
                if (aadj < .4999999 || aadj > .5000001)
                    break;
            }
            else if (aadj < .4999999 / 2)
                break;
        }
    }
    if (check_invalid && (IsZero() || IsInfinite()))
        *this = NaN();
    else if (sign)
        *this = -*this;
}

i4 IEEEdouble::IntValue() const
{
    if (IsNaN())
        return 0;

#ifdef HAVE_IEEE754
    if (value.double_value < (double)(i4) Int::MIN_INT())
        return Int::MIN_INT();
    else if (value.double_value > (double) Int::MAX_INT())
        return Int::MAX_INT();
    return (i4) value.double_value;
#else
    int sign = Sign(),
        exponent = Exponent();

    if (exponent > 30)
        return sign ? Int::MIN_INT() : Int::MAX_INT();

    // This includes true zero and denorms.
    if (exponent < 0)
        return 0;

    i4 result = (i4) (Fraction() >> (FRACT_SIZE - exponent)).LowWord();

    return sign ? -result : result;
#endif // ! HAVE_IEEE754
}

LongInt IEEEdouble::LongValue() const
{
    if (IsNaN())
        return LongInt(0);

    int sign = Sign(),
        exponent = Exponent();

    if (exponent > 62)
        return sign ? LongInt::MIN_LONG() : LongInt::MAX_LONG();

    // This covers true zero and denorms.
    if (exponent < 0)
        return LongInt(0);

    LongInt result = Fraction();

    if (exponent > (int) FRACT_SIZE)
        result <<= (exponent - FRACT_SIZE);
    else if (exponent < (int) FRACT_SIZE)
        result >>= (FRACT_SIZE - exponent);

    return sign ? (LongInt) -result : result;
}

IEEEdouble IEEEdouble::Normalize(int sign, int exponent, ULongInt fraction)
{
    bool round = false, sticky = false;

    assert(fraction != 0);

    //
    // Normalize right. Shift until value < MAX_FRACT.
    //
    if (fraction.HighWord() >= MAX_FRACT)
    {
        while (fraction.HighWord() >= MAX_FRACT)
        {
            sticky |= round;
            round = (fraction.LowWord() & 1) != 0;
            fraction >>= 1;
            exponent++;
        }
        if (round && (sticky || (fraction.LowWord() & 1)) &&
            exponent > -(int) BIAS)
        {
            //
            // Capture any overflow caused by rounding. No other checks are
            // required because if overflow occurred, the the low order bit
            // was guaranteed to be zero. Do not round denorms yet.
            //
            if ((++fraction).HighWord() >= MAX_FRACT)
            {
                fraction >>= 1;
                exponent++;
            }
        }
    }

    //
    // Normalize left. Shift until value >= MIN_FRACT.
    //
    else
        while (fraction.HighWord() < MIN_FRACT)
        {
            fraction <<= 1;
            exponent--;
        }

    //
    // Check and respond to overflow
    //
    if (exponent > BIAS)
        return sign ? NEGATIVE_INFINITY() : POSITIVE_INFINITY();

    //
    // Check and respond to underflow
    //
    if (exponent <= -BIAS)
    {
        if (exponent < -BIAS - FRACT_SIZE)
            return sign ? NEGATIVE_ZERO() : POSITIVE_ZERO();
        while (exponent <= -BIAS)
        {
            sticky |= round;
            round = (fraction.LowWord() & 1) != 0;
            fraction >>= 1;
            exponent++;
        }
        if (round && (sticky || (fraction.LowWord() & 1)))
            fraction++;
        exponent = -BIAS;
        if (fraction == 0)
            return sign ? NEGATIVE_ZERO() : POSITIVE_ZERO();
    }

    return IEEEdouble((sign << 31) | ((exponent + BIAS) << FRACT_SIZE_HI)
                                   | (fraction.HighWord() & FRACT_BITS),
                      fraction.LowWord());
}

int IEEEdouble::SplitInto(BaseLong &fraction) const
{
    int exponent = Exponent();
    fraction = Fraction();

    if (exponent == -(int) BIAS)
    {
        exponent++;
        while (fraction.HighWord() < MIN_FRACT)
        {
            fraction <<= 1;
            exponent--;
        }
    }

    return exponent;
}

IEEEdouble IEEEdouble::Ulp() const
{
    i4 L;
    IEEEdouble d;
    d.value.double_value = value.double_value;

    L = (i4) d.ExpBits() - FRACT_SIZE * MIN_FRACT;
    if (L > 0)
        d.setHighAndLowWords((u4) L, 0);
    else
    {
        L = -L >> FRACT_SIZE_HI;
        if (L < (i4) FRACT_SIZE_HI)
            d.setHighAndLowWords(MIN_FRACT >> (L + 1), 0);
        else
        {
            L -= FRACT_SIZE_HI;
            d.setHighAndLowWords(0, L >= 31 ? 1 : 1 << (31 - L));
        }
    }
    return d;
}

IEEEdouble IEEEdouble::Ratio(const BigInt &a, const BigInt &b)
{
    IEEEdouble da, db;
    int k;
    da = a.DoubleValue();
    db = b.DoubleValue();
    k = b.hi0bits() - a.hi0bits() + 32 * (a.wds - b.wds);
    if (k > 0)
        da.setHighWord(da.HighWord() + k * MIN_FRACT);
    else
        db.setHighWord(db.HighWord() - k * MIN_FRACT);
    return da / db;
}

bool IEEEdouble::operator== (const IEEEdouble op) const
{
    // FIXME: This could be sped up by inlining
#ifdef HAVE_IEEE754
    // TODO: Microsoft VC++ botches this, mixing 12.0 and NaN
    return value.double_value == op.value.double_value;
#else
    return (IsNaN() || op.IsNaN() ? false
            : IsZero() && op.IsZero() ? true
            : (BaseLong) *this == (BaseLong) op);
#endif
}

bool IEEEdouble::operator!= (const IEEEdouble op) const
{
    // FIXME: This could be sped up by inlining
#ifdef HAVE_IEEE754
    return value.double_value != op.value.double_value;
#else
    return !(*this == op);
#endif
}

IEEEdouble IEEEdouble::operator+ (const IEEEdouble op) const
{
#ifdef HAVE_IEEE754
    // FIXME: This could be sped up by inlining
    return IEEEdouble(value.double_value + op.value.double_value);
#else
    if (IsNaN() || op.IsNaN())
        return NaN(); // arithmetic on NaNs not allowed

    //
    // Adding unlike infinities not allowed
    // Adding infinities of same sign is infinity of that sign
    // Adding finite and infinity produces infinity
    //
    if (IsInfinite())
        return op.IsInfinite() && (Sign() != op.Sign()) ? NaN() : *this;
    if (op.IsInfinite())
        return op;

    //
    // Adding zero is easy
    //
    if (IsZero())
        return (op.IsZero()) ? (Sign() != op.Sign()) ? POSITIVE_ZERO()
                                                     : *this
                             : op;
    if (op.IsZero())
        return *this;

    //
    // Now for the real work - do manipulations on copies
    //
    LongInt x, y, round = 0;
    int expx, expy, signx, signy;

    expx = SplitInto(x);
    expy = op.SplitInto(y);

    signx = Sign();
    signy = op.Sign();

    // If the exponents are far enough apart, the answer is easy
    if (expx > expy + 54)
        return *this;
    if (expy > expx + 54)
        return op;

    //
    // Denormalize the fractions, so that the exponents are
    // the same and then set the exponent for the result.
    // Leave enough space for overflow and LONG_MIN avoidance!
    //
    if (signx)
        x = -x;
    if (signy)
        y = -y;

    x <<= 8;
    y <<= 8;

    if (expx > expy)
    {
        round = y << (64 + expy - expx);
        y >>= expx - expy;
    }
    else if (expy > expx)
    {
        round = x << (64 + expx - expy);
        x >>= expy - expx;
        expx = expy;
    }

    //
    // Do the arithmetic. The excess magnitude of 64-bit arithmetic means
    // overflow is impossible (we only need 1 spare bit!). We ensure that
    // pre-alignment avoids any question of LONG_MIN negation problems.
    //
    x += y;
    if (round != 0)
        x |= 1;

    //
    // If the result is negative, then make the fraction positive again
    // and remember the sign.
    //
    if (x < 0)
    {
        x = -x;
        signx = 1;
    }
    else
        signx = 0;

    if (x == 0)
        return signx ? NEGATIVE_ZERO() : POSITIVE_ZERO();

    //
    // Time to normalize again! If we need to shift left (the addition was
    // effectively a subtraction), then there cannot be any reason to round.
    // If the number fits exactly we don't have anything to do either.
    //
    return Normalize(signx, expx - 8, (ULongInt) x);
#endif
}

IEEEdouble IEEEdouble::operator- () const
{
    // FIXME: This could be sped up by inlining
#ifdef HAVE_IEEE754
    return IEEEdouble(-value.double_value);
#else
    if (IsNaN())
        return *this;
    return IEEEdouble(HighWord() ^ SIGN_BIT, LowWord());
#endif // HAVE_IEEE754
}

IEEEdouble IEEEdouble::operator* (const IEEEdouble op) const
{
#ifdef HAVE_IEEE754
    return IEEEdouble(value.double_value * op.value.double_value);
#else
    if (IsNaN() || op.IsNaN())
        return NaN(); // arithmetic on NaNs not allowed

    int sign = Sign() ^ op.Sign();

    //
    // If either operand is zero or infinite, then the answer is easy.
    //
    if (IsZero())
        return op.IsInfinite() ? NaN()
                               : sign ? NEGATIVE_ZERO() : POSITIVE_ZERO();

    if (op.IsZero())
        return IsInfinite() ? NaN()
                            : sign ? NEGATIVE_ZERO() : POSITIVE_ZERO();

    if (IsInfinite() || op.IsInfinite())
        return sign ? NEGATIVE_INFINITY() : POSITIVE_INFINITY();

    //
    // Now for the real work - do manipulations on copies
    //
    ULongInt x, y, z, w, pr1, pr2;
    u4 round;
    int exponent;

    exponent = SplitInto(x) + op.SplitInto(y);

    //
    // The numbers to be multiplied are 53 bits in length (stored in 64 bit
    // integers). Split them in 32 bit parts, then shift result into place.
    // Fold the low order bits into the lsb for rounding purposes.
    //
    z = ULongInt(x.LowWord());
    w = ULongInt(y.LowWord());
    x >>= 32;
    y >>= 32;

    pr1 = z * w; // low*low
    pr2 = z * y + x * w + pr1.HighWord(); // low*high + high*low + adjusted pr1
    round = pr1.LowWord();
    x = (x * y) << 20; // high*high, adjusted

    round |= pr2.LowWord() & 0xFFF;
    pr2 >>= 12;

    x += pr2 | (round ? 1 : 0);

    return Normalize(sign, exponent - 8, x);
#endif // HAVE_IEEE754
}

IEEEdouble IEEEdouble::operator/ (const IEEEdouble op) const
{
#ifdef HAVE_IEEE754
    return op.IsZero() ? ((IsNaN() || IsZero()) ? NaN()
                          : ((IsPositive() ^ op.IsPositive())
                             ? NEGATIVE_INFINITY()
                             : POSITIVE_INFINITY()))
        : IEEEdouble(value.double_value / op.value.double_value);
#else // HAVE_IEEE754
    if (IsNaN() || op.IsNaN())
        return NaN(); // arithmetic on NaNs not allowed

    int sign = Sign() ^ op.Sign();

    //
    // Infinities and zeroes are special.
    //

    if (IsInfinite())
        return (op.IsInfinite() ? NaN()
                : sign ? NEGATIVE_INFINITY() : POSITIVE_INFINITY());

    if (op.IsInfinite())
        return sign ? NEGATIVE_ZERO() : POSITIVE_ZERO();

    if (IsZero())
        return op.IsZero() ? NaN()
                           : sign ? NEGATIVE_ZERO() : POSITIVE_ZERO();

    if (op.IsZero())
        return sign ? NEGATIVE_INFINITY() : POSITIVE_INFINITY();

    //
    // Now for the real work - do manipulations on copies
    //
    ULongInt x, y;
    int exponent;

    exponent = SplitInto(x) - op.SplitInto(y);

    ULongInt mask  (0x80000000, 0x00000000),
             result(0x00000000, 0x00000000);

    // Because both values are normalised, a single shift guarantees results.

    if (x < y)
    {
        x <<= 1;
        exponent--;
    }

    //
    // If the numerator is larger, then it is divisible.
    // Reflect this in the result, and do the subtraction.
    // Magnify the numerator again and reduce the mask.
    //
    while (mask != 0)
    {
        if (x >= y)
        {
            result += mask;
            x -= y;
            if (x == 0)
                break;
        }
        x <<= 1;
        mask >>= 1;
    }

    return Normalize(sign, exponent - 11, result);
#endif // HAVE_IEEE754
}

IEEEdouble IEEEdouble::operator% (const IEEEdouble op) const
{
#ifdef HAVE_IEEE754
    return IEEEdouble((op.IsZero() ? NaN().value.double_value
                       : fmod(value.double_value, op.value.double_value)));
#else // HAVE_IEEE754
    if (IsNaN() || op.IsNaN())
        return NaN(); // arithmetic on NaNs not allowed

    //
    // Infinities and zeroes are special.
    //

    if (IsInfinite() || op.IsZero())
        return NaN();

    if (IsZero() || op.IsInfinite())
        return *this;

    //
    // Now for the real work - do manipulations on copies
    // This algorithm is from fdlibm.c - see above notice
    //

    int sign = Sign();
    ULongInt x, y;
    int expy, exponent;
    LongInt z;

    expy = op.SplitInto(y);
    exponent = SplitInto(x) - expy;

    if (exponent < 0 || (exponent == 0 && x < y))
        return *this;

    while (exponent--)
    {
        z = x - y;
        if (z < 0)
            x <<= 1;
        else if (z == 0)
            return sign ? NEGATIVE_ZERO() : POSITIVE_ZERO();
        else
            x = z + z;
    }
    z = x - y;
    if (z >= 0)
        x = z;

    if (x == 0)
        return sign ? NEGATIVE_ZERO() : POSITIVE_ZERO();
    return Normalize(sign, expy, x);
#endif // HAVE_IEEE754
}

bool IEEEdouble::operator< (const IEEEdouble op) const
{
    // FIXME: This could be sped up by inlining
#ifdef HAVE_IEEE754
    return (value.double_value < op.value.double_value);
#else
    if (IsNaN() || op.IsNaN())
        return false; // NaNs are unordered
    if (IsZero() && op.IsZero())
        return false;
    // Exploit fact that all other IEEE floating point numbers sort like
    // ints after worrying about sign.
    u4 a = HighWord() & ABS_BITS, b = op.HighWord() & ABS_BITS;
    if (IsNegative())
        return op.IsPositive() ||
            (a > b || (a == b && LowWord() > op.LowWord()));
    return op.IsPositive() &&
        (a < b || (a == b && LowWord() < op.LowWord()));
#endif
}

bool IEEEdouble::operator<= (const IEEEdouble op) const
{
    // FIXME: This could be sped up by inlining
#ifdef HAVE_IEEE754
    return (value.double_value <= op.value.double_value);
#else
    return *this < op || *this == op;
#endif
}

bool IEEEdouble::operator> (const IEEEdouble op) const
{
    // FIXME: This could be sped up by inlining
#ifdef HAVE_IEEE754
    return (value.double_value > op.value.double_value);
#else
    if (IsNaN() || op.IsNaN())
        return false; // NaNs are unordered.
    if (IsZero() && op.IsZero())
        return false;
    // Exploit fact that all other IEEE floating point numbers sort like
    // ints after worrying about sign.
    u4 a = HighWord() & ABS_BITS, b = op.HighWord() & ABS_BITS;
    if (IsPositive())
        return op.IsNegative() ||
            (a > b || (a == b && LowWord() > op.LowWord()));
    return op.IsNegative() &&
        (a < b || (a == b && LowWord() < op.LowWord()));
#endif
}

bool IEEEdouble::operator>= (const IEEEdouble op) const
{
    // FIXME: This could be sped up by inlining
#ifdef HAVE_IEEE754
    return (value.double_value >= op.value.double_value);
#else
    return *this > op || *this == op;
#endif
}


#ifndef HAVE_MEMBER_CONSTANTS
u4 BigInt::fives[] = {
    1, 5, 25, 125, 625, 3125, 15625, 78125
};
BigInt *BigInt::bigfives[] = {
    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
};
#else // HAVE_MEMBER_CONSTANTS
const u4 BigInt::fives[] = {
    1, 5, 25, 125, 625, 3125, 15625, 78125
};
const BigInt *BigInt::bigfives[] = {
    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
};
#endif // HAVE_MEMBER_CONSTANTS

BigInt::BigInt(const IEEEfloat &f, int &e, int &bits) : data(NULL)
{
    int fe, k;
    u4 z;
    resize(0);
    z = f.Fraction();
    fe = f.Exponent();
    k = lo0bits(z);
    data[0] = z;
    wds = 1;
    if (fe + IEEEfloat::Bias())
    {
        e = k + fe - IEEEfloat::FractSize();
        bits = IEEEfloat::FractSize() - k + 1;
    }
    else
    {
        e = k + fe - IEEEfloat::FractSize() + 1;
        bits = 32 - hi0bits(z);
    }
}

BigInt::BigInt(const IEEEdouble &d, int &e, int &bits) : data(NULL)
{
    int de, k;
    LongInt x;
    u4 y, z;

    resize(1);
    x = d.Fraction();
    z = x.HighWord();
    de = d.Exponent();
    if ((y = x.LowWord()) != 0)
    {
        if ((k = lo0bits(y)) != 0)
        {
            data[0] = y | z << (32 - k);
            z >>= k;
        }
        else
            data[0] = y;
        wds = (data[1] = z) ? 2 : 1;
    }
    else
    {
        k = lo0bits(z) + 32;
        data[0] = z;
        wds = 1;
    }
    if (de + IEEEdouble::Bias())
    {
        e = k + de - IEEEdouble::FractSize();
        bits = IEEEdouble::FractSize() - k + 1;
    }
    else
    {
        e = k + de - IEEEdouble::FractSize() + 1;
        bits = 32 * wds - hi0bits(data[wds - 1]);
    }
}

BigInt::BigInt(const char *s, int nd0, int nd, u4 start, int startsize) :
    data(NULL)
{
    int i, k;
    u4 x, y;
    x = (nd + 8) / 9;
    for (k = 0, y = 1; x > y; y <<= 1, k++);

    resize(k);
    data[0] = start;
    wds = 1;
    i = startsize;
    if (startsize < nd0)
    {
        s += startsize;
        do
            multadd(10, *s++ - U_0);
        while (++i < nd0);
        s++;
    }
    else
        s += startsize + 1;

    for ( ; i < nd; i++)
        multadd(10, *s++ - U_0);
}

BigInt &BigInt::operator =(const BigInt &b)
{
    if (this != &b)
    {
        k = b.k;
        maxwds = b.maxwds;
        neg = b.neg;
        wds = b.wds;
        delete data;
        data = new u4[maxwds];
        memcpy(data, b.data, wds * sizeof(u4));
    }
    return *this;
}

int BigInt::hi0bits(u4 x)
{
    int k = 0;
    if (! (x & 0xffff0000))
    {
        k = 16;
        x <<= 16;
    }
    if (! (x & 0xff000000))
    {
        k += 8;
        x <<= 8;
    }
    if (! (x & 0xf0000000))
    {
        k += 4;
        x <<= 4;
    }
    if (! (x & 0xc0000000))
    {
        k += 2;
        x <<= 2;
    }
    if (! (x & 0x80000000))
    {
        k++;
        if (! (x & 0x40000000))
            return 32;
    }
    return k;
}

int BigInt::lo0bits(u4 &y)
{
    int k;
    if (y & 7)
    {
        if (y & 1)
            return 0;
        if (y & 2)
        {
            y >>= 1;
            return 1;
        }
        y >>= 2;
        return 2;
    }
    k = 0;
    if (! (y & 0xffff))
    {
        k = 16;
        y >>= 16;
    }
    if (! (y & 0xff))
    {
        k += 8;
        y >>= 8;
    }
    if (! (y & 0xf))
    {
        k += 4;
        y >>= 4;
    }
    if (! (y & 0x3))
    {
        k += 2;
        y >>= 2;
    }
    if (! (y & 1))
    {
        k++;
        y >>= 1;
        if (! y)
            return 32;
    }
    return k;
}

BigInt BigInt::operator +(const unsigned op) const
{
    int i = 0; // counter
    u4 carry = op; // carry between words
    ULongInt sum; // sum
    BigInt result(*this);
    u4 *x = result.data; // access to data

    do
    {
        sum = ULongInt(*x) + carry;
        carry = sum.HighWord();
        *x++ = sum.LowWord();
    } while (carry && ++i < wds);
    if (carry && i == wds)
    {
        if (wds == maxwds)
        {
            result.maxwds = 1 << (++result.k);
            x = new u4[result.maxwds];
            memcpy(x, result.data, wds * sizeof(u4));
            delete result.data;
            result.data = x;
        }
        result.data[result.wds++] = carry;
    }
    return result;
}

BigInt BigInt::operator -(const BigInt &op) const
{
    const BigInt *a = this, *b = &op;
    BigInt zero(0);
    int i, wa, wb;
    u4 *xa, *xae, *xb, *xbe, *xc;
    u4 borrow;
    ULongInt y;

    i = a -> compareTo(op);
    if (! i)
        return zero;
    if (i < 0)
    {
        const BigInt *tmp = a;
        a = b;
        b = tmp;
        i = 1;
    }
    else
        i = 0;

    BigInt c(0);
    c.resize(a -> k);
    c.neg = i != 0;
    wa = a -> wds;
    xa = a -> data;
    xae = xa + wa;
    wb = b -> wds;
    xb = b -> data;
    xbe = xb + wb;
    xc = c.data;
    borrow = 0;
    do
    {
        y = ULongInt(*xa++) - *xb++ - borrow;
        borrow = y.HighWord() & 1;
        *xc++ = y.LowWord();
    } while (xb < xbe);
    while (xa < xae)
    {
        y = ULongInt(*xa++) - borrow;
        borrow = y.HighWord() & 1;
        *xc++ = y.LowWord();
    }
    while (!*--xc)
        wa--;
    c.wds = wa;
    return c;
}

BigInt BigInt::operator *(unsigned op) const
{
    int i = 0; // counter
    u4 carry = 0; // carry between words
    ULongInt product; // product
    BigInt result(*this);
    u4 *x = result.data; // access to data
    ULongInt factor = (u4) op; // avoid creating object multiple times

    do
    {
        product = ULongInt(*x) * factor + carry;
        carry = product.HighWord();
        *x++ = product.LowWord();
    } while (++i < wds);
    if (carry)
    {
        if (wds == maxwds)
        {
            result.maxwds = 1 << (++result.k);
            x = new u4[result.maxwds];
            memcpy(x, result.data, wds * sizeof(u4));
            delete result.data;
            result.data = x;
        }
        result.data[result.wds++] = carry;
    }
    return result;
}

BigInt BigInt::operator *(const BigInt &op) const
{
    const BigInt *a = this, *b = &op;
    int k; // c -> k
    int wa, wb, wc; // wds in each of a, b, c
    u4 *x, *xa, *xae, *xb, *xbe, *xc, *xc0;
    u4 y, carry;
    ULongInt z;

    if (a -> wds < b -> wds)
    {
        const BigInt *tmp = a;
        a = b;
        b = tmp;
    }
    k = a -> k;
    wa = a -> wds;
    wb = b -> wds;
    wc = wa + wb;
    if (wc > a -> maxwds)
        k++;
    BigInt c(0);
    c.resize(k);
    c.neg = a -> neg ^ b -> neg;
    for (x = c.data, xa = x + wc; x < xa; x++)
        *x = 0;
    xa = a -> data;
    xae = xa + wa;
    xb = b -> data;
    xbe = xb + wb;
    xc0 = c.data;
    for ( ; xb < xbe; xc0++)
    {
        if ((y = *xb++) != 0)
        {
            x = xa;
            xc = xc0;
            carry = 0;
            do
            {
                z = ULongInt(*x++) * y + *xc + carry;
                carry = z.HighWord();
                *xc++ = z.LowWord();
            } while (x < xae);
            *xc = carry;
        }
    }
    for (xc0 = c.data, xc = xc0 + wc; wc > 0 && !*--xc; --wc);

    c.wds = wc;
    return c;
}

BigInt BigInt::operator <<(unsigned op) const
{
    int i, k1, n, n1;
    u4 *x, *x1, *xe, z;
    n = op >> 5;
    k1 = k;
    n1 = n + wds + 1;
    for (i = maxwds; n1 > i; i <<= 1)
        k1++;
    BigInt result(*this);
    result.maxwds = 1 << k1;
    result.k = k1;
    delete result.data;
    result.data = x1 = new u4[result.maxwds];
    for (i = 0; i < n; i++)
        *x1++ = 0;
    x = data;
    xe = x + wds;
    if (op &= 0x1f)
    {
        k1 = 32 - op;
        z = 0;
        do
        {
            *x1++ = *x << op | z;
            z = *x++ >> k1;
        } while (x < xe);
        if ((*x1 = z) != 0)
            ++n1;
    }
    else
        do
            *x1++ = *x++;
        while (x < xe);
    result.wds = n1 - 1;
    return result;
}

BigInt &BigInt::multadd(unsigned m, unsigned a)
{
    int i = 0; // counter
    u4 *x = data; // access to data
    u4 carry = a; // carry between words
    ULongInt product; // product
    ULongInt factor = (u4) m; // avoid creating object multiple times

    do
    {
        product = ULongInt(*x) * factor + carry;
        carry = product.HighWord();
        *x++ = product.LowWord();
    } while (++i < wds);
    if (carry)
    {
        if (wds == maxwds)
        {
            maxwds = 1 << (++k);
            x = new u4[maxwds];
            memcpy(x, data, wds * sizeof(u4));
            delete data;
            data = x;
        }
        data[wds++] = carry;
    }
    return *this;
}

BigInt &BigInt::pow5mult(unsigned k)
{
    const BigInt *p5;
    int i;
    assert(k < 0x800);
    if ((i = k & 0x7) != 0)
        *this *= fives[i];
    if (! (k >>= 3))
        return *this;
    if (! (p5 = bigfives[i = 0]))
        p5 = bigfives[i] = new BigInt(390625);
    while (true)
    {
        if (k & 1)
            *this *= *p5;
        if (! (k >>= 1))
            break;
        if (! (p5 = bigfives[++i]))
            p5 = bigfives[i] = new BigInt(*bigfives[i-1] * *bigfives[i-1]);
    }
    return *this;
}

int BigInt::compareTo(const BigInt &b) const
{
    u4 *xa, *xa0, *xb, *xb0;
    int i, j;
    i = wds;
    j = b.wds;
    if (i -= j)
        return i;
    xa0 = data;
    xa = xa0 + j;
    xb0 = b.data;
    xb = xb0 + j;
    while (xa > xa0)
        if (*--xa != *--xb)
            return *xa < *xb ? -1 : 1;
    return 0;
}

int BigInt::quorem(const BigInt &S)
{
    int n;
    u4 *bx, *bxe, q, *sx, *sxe;
    u4 borrow, carry;
    ULongInt y, ys;
    n = S.wds;
    if (wds < n)
        return 0;
    sx = S.data;
    sxe = sx + --n;
    bx = data;
    bxe = bx + n;
    q = *bxe / (*sxe + 1);
    if (q)
    {
        borrow = 0;
        carry = 0;
        do
        {
            ys = ULongInt(*sx++) * q + carry;
            carry = ys.HighWord();
            y = ULongInt(*bx) - ys.LowWord() - borrow;
            borrow = y.HighWord() & 1;
            *bx++ = y.LowWord();
        } while (sx <= sxe);
        if (!*bxe)
        {
            bx = data;
            while (--bxe > bx && !*bxe)
                --n;
            wds = n;
        }
    }
    if (compareTo(S) >= 0)
    {
        q++;
        borrow = 0;
        carry = 0;
        bx = data;
        sx = S.data;
        do
        {
            ys = ULongInt(*sx++) + carry;
            carry = ys.HighWord();
            y = ULongInt(*bx) - ys.LowWord() - borrow;
            borrow = y.HighWord() & 1;
            *bx++ = y.LowWord();
        } while (sx <= sxe);
        bx = data;
        bxe = bx + n;
        if (!*bxe)
        {
            while (--bxe > bx && !*bxe)
                --n;
            wds = n;
        }
    }
    return q;
}

IEEEfloat BigInt::FloatValue() const
{
    u4 *xa, y, z;
    int k;
    xa = data + wds;
    y = *--xa;
    k = hi0bits(y);
    if (k < 8)
        return IEEEfloat(0x3f800000 | y >> (8 - k));
    z = xa > data ? *--xa : 0;
    if (k -= 8)
        return IEEEfloat(0x3f800000 | y << k | z >> (32 - k));
    else
        return IEEEfloat(0x3f800000 | y);
}

IEEEdouble BigInt::DoubleValue() const
{
    u4 *xa, w, y, z, hi, lo;
    int k;
    xa = data + wds;
    y = *--xa;
    k = hi0bits(y);
    if (k < 11)
    {
        hi = 0x3ff00000 | y >> (11 - k);
        w = xa > data ? *--xa : 0;
        lo = y << (32 - 11 + k) | w >> (11 - k);
        return IEEEdouble(hi, lo);
    }
    z = xa > data ? *--xa : 0;
    if (k -= 11)
    {
        hi = 0x3ff00000 | y << k | z >> (32 - k);
        y = xa > data ? *--xa : 0;
        lo = z << k | y >> (32 - k);
    }
    else
    {
        hi = 0x3ff00000 | y;
        lo = z;
    }
    return IEEEdouble(hi, lo);
}



#ifdef HAVE_JIKES_NAMESPACE
} // Close namespace Jikes block
#endif


Generated by  Doxygen 1.6.0   Back to index