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

package ch.randelshofer.fastdoubleparser;

final class FastFloatMath
{
    private static final int FLOAT_EXPONENT_BIAS = 127;
    private static final int FLOAT_SIGNIFICAND_WIDTH = 24;
    private static final int FLOAT_MIN_EXPONENT_POWER_OF_TEN = -45;
    private static final int FLOAT_MAX_EXPONENT_POWER_OF_TEN = 38;
    private static final int FLOAT_MIN_EXPONENT_POWER_OF_TWO = -126;
    private static final int FLOAT_MAX_EXPONENT_POWER_OF_TWO = 127;
    private static final float[] FLOAT_POWER_OF_TEN;
    
    private FastFloatMath() {
    }
    
    static float tryDecFloatToFloatTruncated(final boolean isNegative, final long significand, final int exponent, final boolean isSignificandTruncated, final int exponentOfTruncatedSignificand) {
        if (significand == 0L) {
            return isNegative ? -0.0f : 0.0f;
        }
        float result;
        if (isSignificandTruncated) {
            if (-45 <= exponentOfTruncatedSignificand && exponentOfTruncatedSignificand <= 38) {
                final float withoutRounding = tryDecToFloatWithFastAlgorithm(isNegative, significand, exponentOfTruncatedSignificand);
                final float roundedUp = tryDecToFloatWithFastAlgorithm(isNegative, significand + 1L, exponentOfTruncatedSignificand);
                if (roundedUp == withoutRounding) {
                    return withoutRounding;
                }
            }
            result = Float.NaN;
        }
        else if (-45 <= exponent && exponent <= 38) {
            result = tryDecToFloatWithFastAlgorithm(isNegative, significand, exponent);
        }
        else {
            result = Float.NaN;
        }
        return result;
    }
    
    static float tryHexFloatToFloatTruncated(final boolean isNegative, final long significand, final int exponent, final boolean isSignificandTruncated, final int exponentOfTruncatedSignificand) {
        final int power = isSignificandTruncated ? exponentOfTruncatedSignificand : exponent;
        if (-126 <= power && power <= 127) {
            float d = significand + ((significand < 0L) ? 1.8446744E19f : 0.0f);
            d = fastScalb(d, power);
            return isNegative ? (-d) : d;
        }
        return Float.NaN;
    }
    
    static float tryDecToFloatWithFastAlgorithm(final boolean isNegative, final long significand, final int power) {
        if (-10 <= power && power <= 10 && Long.compareUnsigned(significand, 16777215L) <= 0) {
            float d = (float)significand;
            if (power < 0) {
                d /= FastFloatMath.FLOAT_POWER_OF_TEN[-power];
            }
            else {
                d *= FastFloatMath.FLOAT_POWER_OF_TEN[power];
            }
            return isNegative ? (-d) : d;
        }
        final long factorMantissa = FastDoubleMath.MANTISSA_64[power + 325];
        final long exponent = (217706L * power >> 16) + 127L + 64L;
        int lz = Long.numberOfLeadingZeros(significand);
        final long shiftedSignificand = significand << lz;
        final long upper = FastIntegerMath.unsignedMultiplyHigh(shiftedSignificand, factorMantissa);
        final long upperbit = upper >>> 63;
        long mantissa = upper >>> (int)(upperbit + 38L);
        lz += (int)(0x1L ^ upperbit);
        if ((upper & 0x3FFFFFFFFFL) == 0x3FFFFFFFFFL || ((upper & 0x3FFFFFFFFFL) == 0x0L && (mantissa & 0x3L) == 0x1L)) {
            return Float.NaN;
        }
        ++mantissa;
        mantissa >>>= 1;
        if (mantissa >= 16777216L) {
            mantissa = 8388608L;
            --lz;
        }
        mantissa &= 0xFFFFFFFFFF7FFFFFL;
        final long real_exponent = exponent - lz;
        if (real_exponent < 1L || real_exponent > 254L) {
            return Float.NaN;
        }
        final int bits = (int)(mantissa | real_exponent << 23 | (isNegative ? 2147483648L : 0L));
        return Float.intBitsToFloat(bits);
    }
    
    static float fastScalb(final float number, final int scaleFactor) {
        return number * Float.intBitsToFloat(scaleFactor + 127 << 23);
    }
    
    static {
        FLOAT_POWER_OF_TEN = new float[] { 1.0f, 10.0f, 100.0f, 1000.0f, 10000.0f, 100000.0f, 1000000.0f, 1.0E7f, 1.0E8f, 1.0E9f, 1.0E10f };
    }
}
