// 
// Decompiled by Procyon v0.6.0
// 

package ch.randelshofer.fastdoubleparser;

import ch.randelshofer.fastdoubleparser.bte.ByteDigitSet;
import java.math.BigInteger;
import java.math.BigDecimal;
import ch.randelshofer.fastdoubleparser.chr.CharDigitSet;

final class SlowDoubleConversionPath
{
    private static final int[] powersOfTen;
    
    private SlowDoubleConversionPath() {
    }
    
    static double toDouble(final CharSequence str, final CharDigitSet digitSet, final int integerStartIndex, final int integerEndIndex, final int fractionStartIndex, final int fractionEndIndex, final boolean isSignificandNegative, final long exponentValue) {
        final double v = toBigDecimal(str, digitSet, integerStartIndex, integerEndIndex, fractionStartIndex, fractionEndIndex, 768, exponentValue).doubleValue();
        return isSignificandNegative ? (-v) : v;
    }
    
    static BigDecimal toBigDecimal(final CharSequence str, final CharDigitSet digitSet, int integerStartIndex, final int integerEndIndex, int fractionStartIndex, int fractionEndIndex, final int maxRequiredDigits, final long exponentValue) {
        while (integerStartIndex < integerEndIndex) {
            final char ch = str.charAt(integerStartIndex);
            final int digit = digitSet.toDigit(ch);
            final boolean isDigit = digit < 10;
            if (isDigit && digit > 0) {
                break;
            }
            ++integerStartIndex;
        }
        int skippedFractionDigits = 0;
        if (integerStartIndex == integerEndIndex) {
            while (fractionStartIndex < fractionEndIndex) {
                final char ch2 = str.charAt(fractionStartIndex);
                final int digit2 = digitSet.toDigit(ch2);
                if (digit2 > 0 && digit2 < 10) {
                    break;
                }
                ++skippedFractionDigits;
                ++fractionStartIndex;
            }
        }
        final int estimatedNumDigits = integerEndIndex - integerStartIndex + fractionEndIndex - fractionStartIndex;
        final BigSignificand b = new BigSignificand(FastIntegerMath.estimateNumBits(Math.min(estimatedNumDigits, maxRequiredDigits)));
        int numIntegerDigits = 0;
        int acc = 0;
        int i;
        for (i = integerStartIndex; i < integerEndIndex && numIntegerDigits < maxRequiredDigits; ++i) {
            final char ch3 = str.charAt(i);
            final int digit3 = digitSet.toDigit(ch3);
            if (digit3 < 10) {
                acc = acc * 10 + digit3;
                if (++numIntegerDigits % 8 == 0) {
                    b.fma(100000000, acc);
                    acc = 0;
                }
            }
        }
        int mul = SlowDoubleConversionPath.powersOfTen[numIntegerDigits % 8];
        if (mul != 0) {
            b.fma(mul, acc);
        }
        int skippedIntegerDigits = 0;
        while (i < integerEndIndex) {
            final char ch4 = str.charAt(i);
            final int digit4 = digitSet.toDigit(ch4);
            if (digit4 < 10) {
                ++skippedIntegerDigits;
            }
            ++i;
        }
        fractionEndIndex = Math.min(fractionEndIndex, fractionStartIndex + Math.max(maxRequiredDigits - numIntegerDigits, 0));
        int numFractionDigits = 0;
        acc = 0;
        for (i = fractionStartIndex; i < fractionEndIndex; ++i) {
            final char ch5 = str.charAt(i);
            acc = acc * 10 + digitSet.toDigit(ch5);
            if (++numFractionDigits % 8 == 0) {
                b.fma(100000000, acc);
                acc = 0;
            }
        }
        mul = SlowDoubleConversionPath.powersOfTen[numFractionDigits % 8];
        if (mul != 0) {
            b.fma(mul, acc);
        }
        final int exponent = (int)(exponentValue + skippedIntegerDigits - numFractionDigits - skippedFractionDigits);
        final BigInteger bigInteger = b.toBigInteger();
        return new BigDecimal(bigInteger, -exponent);
    }
    
    static double toDouble(final char[] str, final CharDigitSet digitSet, final int integerStartIndex, final int integerEndIndex, final int fractionStartIndex, final int fractionEndIndex, final boolean isSignificandNegative, final long exponentValue) {
        final double v = toBigDecimal(str, digitSet, integerStartIndex, integerEndIndex, fractionStartIndex, fractionEndIndex, 768, exponentValue).doubleValue();
        return isSignificandNegative ? (-v) : v;
    }
    
    static double toDouble(final byte[] str, final ByteDigitSet digitSet, final int integerStartIndex, final int integerEndIndex, final int fractionStartIndex, final int fractionEndIndex, final boolean isSignificandNegative, final long exponentValue) {
        final double v = toBigDecimal(str, digitSet, integerStartIndex, integerEndIndex, fractionStartIndex, fractionEndIndex, 768, exponentValue).doubleValue();
        return isSignificandNegative ? (-v) : v;
    }
    
    static BigDecimal toBigDecimal(final char[] str, final CharDigitSet digitSet, int integerStartIndex, final int integerEndIndex, int fractionStartIndex, int fractionEndIndex, final int maxRequiredDigits, final long exponentValue) {
        while (integerStartIndex < integerEndIndex) {
            final char ch = str[integerStartIndex];
            final int digit = digitSet.toDigit(ch);
            final boolean isDigit = digit < 10;
            if (isDigit && digit > 0) {
                break;
            }
            ++integerStartIndex;
        }
        int skippedFractionDigits = 0;
        if (integerStartIndex == integerEndIndex) {
            while (fractionStartIndex < fractionEndIndex) {
                final char ch2 = str[fractionStartIndex];
                final int digit2 = digitSet.toDigit(ch2);
                if (digit2 > 0 && digit2 < 10) {
                    break;
                }
                ++skippedFractionDigits;
                ++fractionStartIndex;
            }
        }
        final int estimatedNumDigits = integerEndIndex - integerStartIndex + fractionEndIndex - fractionStartIndex;
        final BigSignificand b = new BigSignificand(FastIntegerMath.estimateNumBits(Math.min(estimatedNumDigits, maxRequiredDigits)));
        int numIntegerDigits = 0;
        int acc = 0;
        int i;
        for (i = integerStartIndex; i < integerEndIndex && numIntegerDigits < maxRequiredDigits; ++i) {
            final char ch3 = str[i];
            final int digit3 = digitSet.toDigit(ch3);
            if (digit3 < 10) {
                acc = acc * 10 + digit3;
                if (++numIntegerDigits % 8 == 0) {
                    b.fma(100000000, acc);
                    acc = 0;
                }
            }
        }
        int mul = SlowDoubleConversionPath.powersOfTen[numIntegerDigits % 8];
        if (mul != 0) {
            b.fma(mul, acc);
        }
        int skippedIntegerDigits = 0;
        while (i < integerEndIndex) {
            final char ch4 = str[i];
            final int digit4 = digitSet.toDigit(ch4);
            if (digit4 < 10) {
                ++skippedIntegerDigits;
            }
            ++i;
        }
        fractionEndIndex = Math.min(fractionEndIndex, fractionStartIndex + Math.max(maxRequiredDigits - numIntegerDigits, 0));
        int numFractionDigits = 0;
        acc = 0;
        for (i = fractionStartIndex; i < fractionEndIndex; ++i) {
            final char ch5 = str[i];
            acc = acc * 10 + digitSet.toDigit(ch5);
            if (++numFractionDigits % 8 == 0) {
                b.fma(100000000, acc);
                acc = 0;
            }
        }
        mul = SlowDoubleConversionPath.powersOfTen[numFractionDigits % 8];
        if (mul != 0) {
            b.fma(mul, acc);
        }
        final int exponent = (int)(exponentValue + skippedIntegerDigits - numFractionDigits - skippedFractionDigits);
        final BigInteger bigInteger = b.toBigInteger();
        return new BigDecimal(bigInteger, -exponent);
    }
    
    static BigDecimal toBigDecimal(final byte[] str, final ByteDigitSet digitSet, int integerStartIndex, final int integerEndIndex, int fractionStartIndex, int fractionEndIndex, final int maxRequiredDigits, final long exponentValue) {
        while (integerStartIndex < integerEndIndex) {
            final byte ch = str[integerStartIndex];
            final int digit = digitSet.toDigit(ch);
            final boolean isDigit = digit < 10;
            if (isDigit && digit > 0) {
                break;
            }
            ++integerStartIndex;
        }
        int skippedFractionDigits = 0;
        if (integerStartIndex == integerEndIndex) {
            while (fractionStartIndex < fractionEndIndex) {
                final byte ch2 = str[fractionStartIndex];
                final int digit2 = digitSet.toDigit(ch2);
                if (digit2 > 0 && digit2 < 10) {
                    break;
                }
                ++skippedFractionDigits;
                ++fractionStartIndex;
            }
        }
        final int estimatedNumDigits = integerEndIndex - integerStartIndex + fractionEndIndex - fractionStartIndex;
        final BigSignificand b = new BigSignificand(FastIntegerMath.estimateNumBits(Math.min(estimatedNumDigits, maxRequiredDigits)));
        int numIntegerDigits = 0;
        int acc = 0;
        int i;
        for (i = integerStartIndex; i < integerEndIndex && numIntegerDigits < maxRequiredDigits; ++i) {
            final byte ch3 = str[i];
            final int digit3 = digitSet.toDigit(ch3);
            if (digit3 < 10) {
                acc = acc * 10 + digit3;
                if (++numIntegerDigits % 8 == 0) {
                    b.fma(100000000, acc);
                    acc = 0;
                }
            }
        }
        int mul = SlowDoubleConversionPath.powersOfTen[numIntegerDigits % 8];
        if (mul != 0) {
            b.fma(mul, acc);
        }
        int skippedIntegerDigits = 0;
        while (i < integerEndIndex) {
            final byte ch4 = str[i];
            final int digit4 = digitSet.toDigit(ch4);
            if (digit4 < 10) {
                ++skippedIntegerDigits;
            }
            ++i;
        }
        fractionEndIndex = Math.min(fractionEndIndex, fractionStartIndex + Math.max(maxRequiredDigits - numIntegerDigits, 0));
        int numFractionDigits = 0;
        acc = 0;
        for (i = fractionStartIndex; i < fractionEndIndex; ++i) {
            final byte ch5 = str[i];
            acc = acc * 10 + digitSet.toDigit(ch5);
            if (++numFractionDigits % 8 == 0) {
                b.fma(100000000, acc);
                acc = 0;
            }
        }
        mul = SlowDoubleConversionPath.powersOfTen[numFractionDigits % 8];
        if (mul != 0) {
            b.fma(mul, acc);
        }
        final int exponent = (int)(exponentValue + skippedIntegerDigits - numFractionDigits - skippedFractionDigits);
        final BigInteger bigInteger = b.toBigInteger();
        return new BigDecimal(bigInteger, -exponent);
    }
    
    static {
        powersOfTen = new int[] { 0, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000 };
    }
}
