2878 lines · 108.8 KB · Java
RawDownload
                    exponentAdjust = 4*(leftDigits - 1);                } else {                // Cases 3 and 4                    exponentAdjust = -4*( rightDigits - signifLength + 1);                }                 // If the significand is zero, the exponent doesn't                // matter; return a properly signed zero.                 if (signifLength == 0) { // Only zeros in input                    return new FloatingDecimal(sign * 0.0);                }            }             //  Extract Exponent            /*             * Use an int to read in the exponent value; this should             * provide more than sufficient range for non-contrived             * inputs.  If reading the exponent in as an int does             * overflow, examine the sign of the exponent and             * significand to determine what to do.             */            String group8 = m.group(8);            boolean positiveExponent = ( group8 == null ) || group8.equals("+");            long unsignedRawExponent;            try {                unsignedRawExponent = Integer.parseInt(m.group(9));            }            catch (NumberFormatException e) {                // At this point, we know the exponent is                // syntactically well-formed as a sequence of                // digits.  Therefore, if an NumberFormatException                // is thrown, it must be due to overflowing int's                // range.  Also, at this point, we have already                // checked for a zero significand.  Thus the signs                // of the exponent and significand determine the                // final result:                //                //                      significand                //                      +               -                // exponent     +       +infinity       -infinity                //              -       +0.0            -0.0                return new FloatingDecimal(sign * (positiveExponent ?                                                   Double.POSITIVE_INFINITY : 0.0));            }             long rawExponent =                (positiveExponent ? 1L : -1L) * // exponent sign                unsignedRawExponent;            // exponent magnitude             // Calculate partially adjusted exponent            long exponent = rawExponent + exponentAdjust ;             // Starting copying non-zero bits into proper position in            // a long; copy explicit bit too; this will be masked            // later for normal values.             boolean round = false;            boolean sticky = false;            int bitsCopied=0;            int nextShift=0;            long significand=0L;            // First iteration is different, since we only copy            // from the leading significand bit; one more exponent            // adjust will be needed...             // IMPORTANT: make leadingDigit a long to avoid            // surprising shift semantics!            long leadingDigit = getHexDigit(significandString, 0);             /*             * Left shift the leading digit (53 - (bit position of             * leading 1 in digit)); this sets the top bit of the             * significand to 1.  The nextShift value is adjusted             * to take into account the number of bit positions of             * the leadingDigit actually used.  Finally, the             * exponent is adjusted to normalize the significand             * as a binary value, not just a hex value.             */            if (leadingDigit == 1) {                significand |= leadingDigit << 52;                nextShift = 52 - 4;                /* exponent += 0 */     }            else if (leadingDigit <= 3) { // [2, 3]                significand |= leadingDigit << 51;                nextShift = 52 - 5;                exponent += 1;            }            else if (leadingDigit <= 7) { // [4, 7]                significand |= leadingDigit << 50;                nextShift = 52 - 6;                exponent += 2;            }            else if (leadingDigit <= 15) { // [8, f]                significand |= leadingDigit << 49;                nextShift = 52 - 7;                exponent += 3;            } else {                throw new AssertionError("Result from digit conversion too large!");            }            // The preceding if-else could be replaced by a single            // code block based on the high-order bit set in            // leadingDigit.  Given leadingOnePosition,             // significand |= leadingDigit << (SIGNIFICAND_WIDTH - leadingOnePosition);            // nextShift = 52 - (3 + leadingOnePosition);            // exponent += (leadingOnePosition-1);              /*             * Now the exponent variable is equal to the normalized             * binary exponent.  Code below will make representation             * adjustments if the exponent is incremented after             * rounding (includes overflows to infinity) or if the             * result is subnormal.             */             // Copy digit into significand until the significand can't            // hold another full hex digit or there are no more input            // hex digits.            int i = 0;            for(i = 1;                i < signifLength && nextShift >= 0;                i++) {                long currentDigit = getHexDigit(significandString, i);                significand |= (currentDigit << nextShift);                nextShift-=4;            }             // After the above loop, the bulk of the string is copied.            // Now, we must copy any partial hex digits into the            // significand AND compute the round bit and start computing            // sticky bit.             if ( i < signifLength ) { // at least one hex input digit exists                long currentDigit = getHexDigit(significandString, i);                 // from nextShift, figure out how many bits need                // to be copied, if any                switch(nextShift) { // must be negative                case -1:                    // three bits need to be copied in; can                    // set round bit                    significand |= ((currentDigit & 0xEL) >> 1);                    round = (currentDigit & 0x1L)  != 0L;                    break;                 case -2:                    // two bits need to be copied in; can                    // set round and start sticky                    significand |= ((currentDigit & 0xCL) >> 2);                    round = (currentDigit &0x2L)  != 0L;                    sticky = (currentDigit & 0x1L) != 0;                    break;                 case -3:                    // one bit needs to be copied in                    significand |= ((currentDigit & 0x8L)>>3);                    // Now set round and start sticky, if possible                    round = (currentDigit &0x4L)  != 0L;                    sticky = (currentDigit & 0x3L) != 0;                    break;                 case -4:                    // all bits copied into significand; set                    // round and start sticky                    round = ((currentDigit & 0x8L) != 0);  // is top bit set?                    // nonzeros in three low order bits?                    sticky = (currentDigit & 0x7L) != 0;                    break;                 default:                    throw new AssertionError("Unexpected shift distance remainder.");                    // break;                }                 // Round is set; sticky might be set.                 // For the sticky bit, it suffices to check the                // current digit and test for any nonzero digits in                // the remaining unprocessed input.                i++;                while(i < signifLength && !sticky) {                    currentDigit =  getHexDigit(significandString,i);                    sticky = sticky || (currentDigit != 0);                    i++;                }             }            // else all of string was seen, round and sticky are            // correct as false.              // Check for overflow and update exponent accordingly.             if (exponent > DoubleConsts.MAX_EXPONENT) {         // Infinite result                // overflow to properly signed infinity                return new FloatingDecimal(sign * Double.POSITIVE_INFINITY);            } else {  // Finite return value                if (exponent <= DoubleConsts.MAX_EXPONENT && // (Usually) normal result                    exponent >= DoubleConsts.MIN_EXPONENT) {                     // The result returned in this block cannot be a                    // zero or subnormal; however after the                    // significand is adjusted from rounding, we could                    // still overflow in infinity.                     // AND exponent bits into significand; if the                    // significand is incremented and overflows from                    // rounding, this combination will update the                    // exponent correctly, even in the case of                    // Double.MAX_VALUE overflowing to infinity.                     significand = (( ((long)exponent +                                     (long)DoubleConsts.EXP_BIAS) <<                                     (DoubleConsts.SIGNIFICAND_WIDTH-1))                                   & DoubleConsts.EXP_BIT_MASK) |                        (DoubleConsts.SIGNIF_BIT_MASK & significand);                 }  else  {  // Subnormal or zero                    // (exponent < DoubleConsts.MIN_EXPONENT)                     if (exponent < (DoubleConsts.MIN_SUB_EXPONENT -1 )) {                        // No way to round back to nonzero value                        // regardless of significand if the exponent is                        // less than -1075.                        return new FloatingDecimal(sign * 0.0);                    } else { //  -1075 <= exponent <= MIN_EXPONENT -1 = -1023                        /*                         * Find bit position to round to; recompute                         * round and sticky bits, and shift                         * significand right appropriately.                         */                         sticky = sticky || round;                        round = false;                         // Number of bits of significand to preserve is                        // exponent - abs_min_exp +1                        // check:                        // -1075 +1074 + 1 = 0                        // -1023 +1074 + 1 = 52                         int bitsDiscarded = 53 -                            ((int)exponent - DoubleConsts.MIN_SUB_EXPONENT + 1);                        assert bitsDiscarded >= 1 && bitsDiscarded <= 53;                         // What to do here:                        // First, isolate the new round bit                        round = (significand & (1L << (bitsDiscarded -1))) != 0L;                        if (bitsDiscarded > 1) {                            // create mask to update sticky bits; low                            // order bitsDiscarded bits should be 1                            long mask = ~((~0L) << (bitsDiscarded -1));                            sticky = sticky || ((significand & mask) != 0L ) ;                        }                         // Now, discard the bits                        significand = significand >> bitsDiscarded;                         significand = (( ((long)(DoubleConsts.MIN_EXPONENT -1) + // subnorm exp.                                          (long)DoubleConsts.EXP_BIAS) <<                                         (DoubleConsts.SIGNIFICAND_WIDTH-1))                                       & DoubleConsts.EXP_BIT_MASK) |                            (DoubleConsts.SIGNIF_BIT_MASK & significand);                    }                }                 // The significand variable now contains the currently                // appropriate exponent bits too.                 /*                 * Determine if significand should be incremented;                 * making this determination depends on the least                 * significant bit and the round and sticky bits.                 *                 * Round to nearest even rounding table, adapted from                 * table 4.7 in "Computer Arithmetic" by IsraelKoren.                 * The digit to the left of the "decimal" point is the                 * least significant bit, the digits to the right of                 * the point are the round and sticky bits                 *                 * Number       Round(x)                 * x0.00        x0.                 * x0.01        x0.                 * x0.10        x0.                 * x0.11        x1. = x0. +1                 * x1.00        x1.                 * x1.01        x1.                 * x1.10        x1. + 1                 * x1.11        x1. + 1                 */                boolean incremented = false;                boolean leastZero  = ((significand & 1L) == 0L);                if( (  leastZero  && round && sticky ) ||                    ((!leastZero) && round )) {                    incremented = true;                    significand++;                }                 FloatingDecimal fd = new FloatingDecimal(FpUtils.rawCopySign(                                                                 Double.longBitsToDouble(significand),                                                                 sign));                 /*                 * Set roundingDir variable field of fd properly so                 * that the input string can be properly rounded to a                 * float value.  There are two cases to consider:                 *                 * 1. rounding to double discards sticky bit                 * information that would change the result of a float                 * rounding (near halfway case between two floats)                 *                 * 2. rounding to double rounds up when rounding up                 * would not occur when rounding to float.                 *                 * For former case only needs to be considered when                 * the bits rounded away when casting to float are all                 * zero; otherwise, float round bit is properly set                 * and sticky will already be true.                 *                 * The lower exponent bound for the code below is the                 * minimum (normalized) subnormal exponent - 1 since a                 * value with that exponent can round up to the                 * minimum subnormal value and the sticky bit                 * information must be preserved (i.e. case 1).                 */                if ((exponent >= FloatConsts.MIN_SUB_EXPONENT-1) &&                    (exponent <= FloatConsts.MAX_EXPONENT ) ){                    // Outside above exponent range, the float value                    // will be zero or infinity.                     /*                     * If the low-order 28 bits of a rounded double                     * significand are 0, the double could be a                     * half-way case for a rounding to float.  If the                     * double value is a half-way case, the double                     * significand may have to be modified to round                     * the the right float value (see the stickyRound                     * method).  If the rounding to double has lost                     * what would be float sticky bit information, the                     * double significand must be incremented.  If the                     * double value's significand was itself                     * incremented, the float value may end up too                     * large so the increment should be undone.                     */                    if ((significand & 0xfffffffL) ==  0x0L) {                        // For negative values, the sign of the                        // roundDir is the same as for positive values                        // since adding 1 increasing the significand's                        // magnitude and subtracting 1 decreases the                        // significand's magnitude.  If neither round                        // nor sticky is true, the double value is                        // exact and no adjustment is required for a                        // proper float rounding.                        if( round || sticky) {                            if (leastZero) { // prerounding lsb is 0                                // If round and sticky were both true,                                // and the least significant                                // significand bit were 0, the rounded                                // significand would not have its                                // low-order bits be zero.  Therefore,                                // we only need to adjust the                                // significand if round XOR sticky is                                // true.                                if (round ^ sticky) {                                    fd.roundDir =  1;                                }                            }                            else { // prerounding lsb is 1                                // If the prerounding lsb is 1 and the                                // resulting significand has its                                // low-order bits zero, the significand                                // was incremented.  Here, we undo the                                // increment, which will ensure the                                // right guard and sticky bits for the                                // float rounding.                                if (round)                                    fd.roundDir =  -1;                            }                        }                    }                }                 fd.fromHex = true;                return fd;            }        }    }     /**     * Return <code>s</code> with any leading zeros removed.     */    static String stripLeadingZeros(String s) {        return  s.replaceFirst("^0+", "");    }     /**     * Extract a hexadecimal digit from position <code>position</code>     * of string <code>s</code>.     */    static int getHexDigit(String s, int position) {        int value = Character.digit(s.charAt(position), 16);        if (value <= -1 || value >= 16) {            throw new AssertionError("Unexpected failure of digit conversion of " +                                     s.charAt(position));        }        return value;    }  } /* * A really, really simple bigint package * tailored to the needs of floating base conversion. */class FDBigInt {    int nWords; // number of words used    int data[]; // value: data[0] is least significant      public FDBigInt( int v ){        nWords = 1;        data = new int[1];        data[0] = v;    }     public FDBigInt( long v ){        data = new int[2];        data[0] = (int)v;        data[1] = (int)(v>>>32);        nWords = (data[1]==0) ? 1 : 2;    }     public FDBigInt( FDBigInt other ){        data = new int[nWords = other.nWords];        System.arraycopy( other.data, 0, data, 0, nWords );    }     private FDBigInt( int [] d, int n ){        data = d;        nWords = n;    }     public FDBigInt( long seed, char digit[], int nd0, int nd ){        int n= (nd+8)/9;        // estimate size needed.        if ( n < 2 ) n = 2;        data = new int[n];      // allocate enough space        data[0] = (int)seed;    // starting value        data[1] = (int)(seed>>>32);        nWords = (data[1]==0) ? 1 : 2;        int i = nd0;        int limit = nd-5;       // slurp digits 5 at a time.        int v;        while ( i < limit ){            int ilim = i+5;            v = (int)digit[i++]-(int)'0';            while( i <ilim ){                v = 10*v + (int)digit[i++]-(int)'0';            }            multaddMe( 100000, v); // ... where 100000 is 10^5.        }        int factor = 1;        v = 0;        while ( i < nd ){            v = 10*v + (int)digit[i++]-(int)'0';            factor *= 10;        }        if ( factor != 1 ){            multaddMe( factor, v );        }    }     /*     * Left shift by c bits.     * Shifts this in place.     */    public void    lshiftMe( int c )throws IllegalArgumentException {        if ( c <= 0 ){            if ( c == 0 )                return; // silly.            else                throw new IllegalArgumentException("negative shift count");        }        int wordcount = c>>5;        int bitcount  = c & 0x1f;        int anticount = 32-bitcount;        int t[] = data;        int s[] = data;        if ( nWords+wordcount+1 > t.length ){            // reallocate.            t = new int[ nWords+wordcount+1 ];        }        int target = nWords+wordcount;        int src    = nWords-1;        if ( bitcount == 0 ){            // special hack, since an anticount of 32 won't go!            System.arraycopy( s, 0, t, wordcount, nWords );            target = wordcount-1;

Lines 2001–2500 of 2878. Previous lines