2878 lines · 108.8 KB · Java
RawDownload
        boolean isNegative = false;        boolean signSeen   = false;        int     decExp;        char    c;     parseNumber:        try{            in = in.trim(); // don't fool around with white space.                            // throws NullPointerException if null            int l = in.length();            if ( l == 0 ) throw new NumberFormatException("empty String");            int i = 0;            switch ( c = in.charAt( i ) ){            case '-':                isNegative = true;                //FALLTHROUGH            case '+':                i++;                signSeen = true;            }             // Check for NaN and Infinity strings            c = in.charAt(i);            if(c == 'N' || c == 'I') { // possible NaN or infinity                boolean potentialNaN = false;                char targetChars[] = null;  // char array of "NaN" or "Infinity"                 if(c == 'N') {                    targetChars = notANumber;                    potentialNaN = true;                } else {                    targetChars = infinity;                }                 // compare Input string to "NaN" or "Infinity"                int j = 0;                while(i < l && j < targetChars.length) {                    if(in.charAt(i) == targetChars[j]) {                        i++; j++;                    }                    else // something is amiss, throw exception                        break parseNumber;                }                 // For the candidate string to be a NaN or infinity,                // all characters in input string and target char[]                // must be matched ==> j must equal targetChars.length                // and i must equal l                if( (j == targetChars.length) && (i == l) ) { // return NaN or infinity                    return (potentialNaN ? new FloatingDecimal(Double.NaN) // NaN has no sign                            : new FloatingDecimal(isNegative?                                                  Double.NEGATIVE_INFINITY:                                                  Double.POSITIVE_INFINITY)) ;                }                else { // something went wrong, throw exception                    break parseNumber;                }             } else if (c == '0')  { // check for hexadecimal floating-point number                if (l > i+1 ) {                    char ch = in.charAt(i+1);                    if (ch == 'x' || ch == 'X' ) // possible hex string                        return parseHexString(in);                }            }  // look for and process decimal floating-point string             char[] digits = new char[ l ];            int    nDigits= 0;            boolean decSeen = false;            int decPt = 0;            int nLeadZero = 0;            int nTrailZero= 0;        digitLoop:            while ( i < l ){                switch ( c = in.charAt( i ) ){                case '0':                    if ( nDigits > 0 ){                        nTrailZero += 1;                    } else {                        nLeadZero += 1;                    }                    break; // out of switch.                case '1':                case '2':                case '3':                case '4':                case '5':                case '6':                case '7':                case '8':                case '9':                    while ( nTrailZero > 0 ){                        digits[nDigits++] = '0';                        nTrailZero -= 1;                    }                    digits[nDigits++] = c;                    break; // out of switch.                case '.':                    if ( decSeen ){                        // already saw one ., this is the 2nd.                        throw new NumberFormatException("multiple points");                    }                    decPt = i;                    if ( signSeen ){                        decPt -= 1;                    }                    decSeen = true;                    break; // out of switch.                default:                    break digitLoop;                }                i++;            }            /*             * At this point, we've scanned all the digits and decimal             * point we're going to see. Trim off leading and trailing             * zeros, which will just confuse us later, and adjust             * our initial decimal exponent accordingly.             * To review:             * we have seen i total characters.             * nLeadZero of them were zeros before any other digits.             * nTrailZero of them were zeros after any other digits.             * if ( decSeen ), then a . was seen after decPt characters             * ( including leading zeros which have been discarded )             * nDigits characters were neither lead nor trailing             * zeros, nor point             */            /*             * special hack: if we saw no non-zero digits, then the             * answer is zero!             * Unfortunately, we feel honor-bound to keep parsing!             */            if ( nDigits == 0 ){                digits = zero;                nDigits = 1;                if ( nLeadZero == 0 ){                    // we saw NO DIGITS AT ALL,                    // not even a crummy 0!                    // this is not allowed.                    break parseNumber; // go throw exception                }             }             /* Our initial exponent is decPt, adjusted by the number of             * discarded zeros. Or, if there was no decPt,             * then its just nDigits adjusted by discarded trailing zeros.             */            if ( decSeen ){                decExp = decPt - nLeadZero;            } else {                decExp = nDigits+nTrailZero;            }             /*             * Look for 'e' or 'E' and an optionally signed integer.             */            if ( (i < l) &&  (((c = in.charAt(i) )=='e') || (c == 'E') ) ){                int expSign = 1;                int expVal  = 0;                int reallyBig = Integer.MAX_VALUE / 10;                boolean expOverflow = false;                switch( in.charAt(++i) ){                case '-':                    expSign = -1;                    //FALLTHROUGH                case '+':                    i++;                }                int expAt = i;            expLoop:                while ( i < l  ){                    if ( expVal >= reallyBig ){                        // the next character will cause integer                        // overflow.                        expOverflow = true;                    }                    switch ( c = in.charAt(i++) ){                    case '0':                    case '1':                    case '2':                    case '3':                    case '4':                    case '5':                    case '6':                    case '7':                    case '8':                    case '9':                        expVal = expVal*10 + ( (int)c - (int)'0' );                        continue;                    default:                        i--;           // back up.                        break expLoop; // stop parsing exponent.                    }                }                int expLimit = bigDecimalExponent+nDigits+nTrailZero;                if ( expOverflow || ( expVal > expLimit ) ){                    //                    // The intent here is to end up with                    // infinity or zero, as appropriate.                    // The reason for yielding such a small decExponent,                    // rather than something intuitive such as                    // expSign*Integer.MAX_VALUE, is that this value                    // is subject to further manipulation in                    // doubleValue() and floatValue(), and I don't want                    // it to be able to cause overflow there!                    // (The only way we can get into trouble here is for                    // really outrageous nDigits+nTrailZero, such as 2 billion. )                    //                    decExp = expSign*expLimit;                } else {                    // this should not overflow, since we tested                    // for expVal > (MAX+N), where N >= abs(decExp)                    decExp = decExp + expSign*expVal;                }                 // if we saw something not a digit ( or end of string )                // after the [Ee][+-], without seeing any digits at all                // this is certainly an error. If we saw some digits,                // but then some trailing garbage, that might be ok.                // so we just fall through in that case.                // HUMBUG                if ( i == expAt )                    break parseNumber; // certainly bad            }            /*             * We parsed everything we could.             * If there are leftovers, then this is not good input!             */            if ( i < l &&                ((i != l - 1) ||                (in.charAt(i) != 'f' &&                 in.charAt(i) != 'F' &&                 in.charAt(i) != 'd' &&                 in.charAt(i) != 'D'))) {                break parseNumber; // go throw exception            }             return new FloatingDecimal( isNegative, decExp, digits, nDigits,  false );        } catch ( StringIndexOutOfBoundsException e ){ }        throw new NumberFormatException("For input string: \"" + in + "\"");    }     /*     * Take a FloatingDecimal, which we presumably just scanned in,     * and find out what its value is, as a double.     *     * AS A SIDE EFFECT, SET roundDir TO INDICATE PREFERRED     * ROUNDING DIRECTION in case the result is really destined     * for a single-precision float.     */     public strictfp double doubleValue(){        int     kDigits = Math.min( nDigits, maxDecimalDigits+1 );        long    lValue;        double  dValue;        double  rValue, tValue;         // First, check for NaN and Infinity values        if(digits == infinity || digits == notANumber) {            if(digits == notANumber)                return Double.NaN;            else                return (isNegative?Double.NEGATIVE_INFINITY:Double.POSITIVE_INFINITY);        }        else {            if (mustSetRoundDir) {                roundDir = 0;            }            /*             * convert the lead kDigits to a long integer.             */            // (special performance hack: start to do it using int)            int iValue = (int)digits[0]-(int)'0';            int iDigits = Math.min( kDigits, intDecimalDigits );            for ( int i=1; i < iDigits; i++ ){                iValue = iValue*10 + (int)digits[i]-(int)'0';            }            lValue = (long)iValue;            for ( int i=iDigits; i < kDigits; i++ ){                lValue = lValue*10L + (long)((int)digits[i]-(int)'0');            }            dValue = (double)lValue;            int exp = decExponent-kDigits;            /*             * lValue now contains a long integer with the value of             * the first kDigits digits of the number.             * dValue contains the (double) of the same.             */             if ( nDigits <= maxDecimalDigits ){                /*                 * possibly an easy case.                 * We know that the digits can be represented                 * exactly. And if the exponent isn't too outrageous,                 * the whole thing can be done with one operation,                 * thus one rounding error.                 * Note that all our constructors trim all leading and                 * trailing zeros, so simple values (including zero)                 * will always end up here                 */                if (exp == 0 || dValue == 0.0)                    return (isNegative)? -dValue : dValue; // small floating integer                else if ( exp >= 0 ){                    if ( exp <= maxSmallTen ){                        /*                         * Can get the answer with one operation,                         * thus one roundoff.                         */                        rValue = dValue * small10pow[exp];                        if ( mustSetRoundDir ){                            tValue = rValue / small10pow[exp];                            roundDir = ( tValue ==  dValue ) ? 0                                :( tValue < dValue ) ? 1                                : -1;                        }                        return (isNegative)? -rValue : rValue;                    }                    int slop = maxDecimalDigits - kDigits;                    if ( exp <= maxSmallTen+slop ){                        /*                         * We can multiply dValue by 10^(slop)                         * and it is still "small" and exact.                         * Then we can multiply by 10^(exp-slop)                         * with one rounding.                         */                        dValue *= small10pow[slop];                        rValue = dValue * small10pow[exp-slop];                         if ( mustSetRoundDir ){                            tValue = rValue / small10pow[exp-slop];                            roundDir = ( tValue ==  dValue ) ? 0                                :( tValue < dValue ) ? 1                                : -1;                        }                        return (isNegative)? -rValue : rValue;                    }                    /*                     * Else we have a hard case with a positive exp.                     */                } else {                    if ( exp >= -maxSmallTen ){                        /*                         * Can get the answer in one division.                         */                        rValue = dValue / small10pow[-exp];                        tValue = rValue * small10pow[-exp];                        if ( mustSetRoundDir ){                            roundDir = ( tValue ==  dValue ) ? 0                                :( tValue < dValue ) ? 1                                : -1;                        }                        return (isNegative)? -rValue : rValue;                    }                    /*                     * Else we have a hard case with a negative exp.                     */                }            }             /*             * Harder cases:             * The sum of digits plus exponent is greater than             * what we think we can do with one error.             *             * Start by approximating the right answer by,             * naively, scaling by powers of 10.             */            if ( exp > 0 ){                if ( decExponent > maxDecimalExponent+1 ){                    /*                     * Lets face it. This is going to be                     * Infinity. Cut to the chase.                     */                    return (isNegative)? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;                }                if ( (exp&15) != 0 ){                    dValue *= small10pow[exp&15];                }                if ( (exp>>=4) != 0 ){                    int j;                    for( j = 0; exp > 1; j++, exp>>=1 ){                        if ( (exp&1)!=0)                            dValue *= big10pow[j];                    }                    /*                     * The reason for the weird exp > 1 condition                     * in the above loop was so that the last multiply                     * would get unrolled. We handle it here.                     * It could overflow.                     */                    double t = dValue * big10pow[j];                    if ( Double.isInfinite( t ) ){                        /*                         * It did overflow.                         * Look more closely at the result.                         * If the exponent is just one too large,                         * then use the maximum finite as our estimate                         * value. Else call the result infinity                         * and punt it.                         * ( I presume this could happen because                         * rounding forces the result here to be                         * an ULP or two larger than                         * Double.MAX_VALUE ).                         */                        t = dValue / 2.0;                        t *= big10pow[j];                        if ( Double.isInfinite( t ) ){                            return (isNegative)? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;                        }                        t = Double.MAX_VALUE;                    }                    dValue = t;                }            } else if ( exp < 0 ){                exp = -exp;                if ( decExponent < minDecimalExponent-1 ){                    /*                     * Lets face it. This is going to be                     * zero. Cut to the chase.                     */                    return (isNegative)? -0.0 : 0.0;                }                if ( (exp&15) != 0 ){                    dValue /= small10pow[exp&15];                }                if ( (exp>>=4) != 0 ){                    int j;                    for( j = 0; exp > 1; j++, exp>>=1 ){                        if ( (exp&1)!=0)                            dValue *= tiny10pow[j];                    }                    /*                     * The reason for the weird exp > 1 condition                     * in the above loop was so that the last multiply                     * would get unrolled. We handle it here.                     * It could underflow.                     */                    double t = dValue * tiny10pow[j];                    if ( t == 0.0 ){                        /*                         * It did underflow.                         * Look more closely at the result.                         * If the exponent is just one too small,                         * then use the minimum finite as our estimate                         * value. Else call the result 0.0                         * and punt it.                         * ( I presume this could happen because                         * rounding forces the result here to be                         * an ULP or two less than                         * Double.MIN_VALUE ).                         */                        t = dValue * 2.0;                        t *= tiny10pow[j];                        if ( t == 0.0 ){                            return (isNegative)? -0.0 : 0.0;                        }                        t = Double.MIN_VALUE;                    }                    dValue = t;                }            }             /*             * dValue is now approximately the result.             * The hard part is adjusting it, by comparison             * with FDBigInt arithmetic.             * Formulate the EXACT big-number result as             * bigD0 * 10^exp             */            FDBigInt bigD0 = new FDBigInt( lValue, digits, kDigits, nDigits );            exp   = decExponent - nDigits;             correctionLoop:            while(true){                /* AS A SIDE EFFECT, THIS METHOD WILL SET THE INSTANCE VARIABLES                 * bigIntExp and bigIntNBits                 */                FDBigInt bigB = doubleToBigInt( dValue );                 /*                 * Scale bigD, bigB appropriately for                 * big-integer operations.                 * Naively, we multiply by powers of ten                 * and powers of two. What we actually do                 * is keep track of the powers of 5 and                 * powers of 2 we would use, then factor out                 * common divisors before doing the work.                 */                int B2, B5; // powers of 2, 5 in bigB                int     D2, D5; // powers of 2, 5 in bigD                int Ulp2;   // powers of 2 in halfUlp.                if ( exp >= 0 ){                    B2 = B5 = 0;                    D2 = D5 = exp;                } else {                    B2 = B5 = -exp;                    D2 = D5 = 0;                }                if ( bigIntExp >= 0 ){

Lines 1001–1500 of 2878. Previous lines