// Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
//       copyright notice, this list of conditions and the following
//       disclaimer in the documentation and/or other materials provided
//       with the distribution.
//     * Neither the name of Google Inc. nor the names of its
//       contributors may be used to endorse or promote products derived
//       from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "config.h"

#include <stdarg.h>
#include <limits.h>

#include "strtod.h"
#include "bignum.h"
#include "cached-powers.h"
#include "double.h"

namespace WTF {

namespace double_conversion {

#if defined(DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS)
    // 2^53 = 9007199254740992.
    // Any integer with at most 15 decimal digits will hence fit into a double
    // (which has a 53bit significand) without loss of precision.
    static const int kMaxExactDoubleIntegerDecimalDigits = 15;
#endif
    // 2^64 = 18446744073709551616 > 10^19
    static const int kMaxUint64DecimalDigits = 19;
    
    // Max double: 1.7976931348623157 x 10^308
    // Min non-zero double: 4.9406564584124654 x 10^-324
    // Any x >= 10^309 is interpreted as +infinity.
    // Any x <= 10^-324 is interpreted as 0.
    // Note that 2.5e-324 (despite being smaller than the min double) will be read
    // as non-zero (equal to the min non-zero double).
    static const int kMaxDecimalPower = 309;
    static const int kMinDecimalPower = -324;
    
    // 2^64 = 18446744073709551616
    static const uint64_t kMaxUint64 = UINT64_2PART_C(0xFFFFFFFF, FFFFFFFF);
    
#if defined(DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS)
    static const double exact_powers_of_ten[] = {
        1.0,  // 10^0
        10.0,
        100.0,
        1000.0,
        10000.0,
        100000.0,
        1000000.0,
        10000000.0,
        100000000.0,
        1000000000.0,
        10000000000.0,  // 10^10
        100000000000.0,
        1000000000000.0,
        10000000000000.0,
        100000000000000.0,
        1000000000000000.0,
        10000000000000000.0,
        100000000000000000.0,
        1000000000000000000.0,
        10000000000000000000.0,
        100000000000000000000.0,  // 10^20
        1000000000000000000000.0,
        // 10^22 = 0x21e19e0c9bab2400000 = 0x878678326eac9 * 2^22
        10000000000000000000000.0
    };
    static const int kExactPowersOfTenSize = ARRAY_SIZE(exact_powers_of_ten);
#endif
    
    // Maximum number of significant digits in the decimal representation.
    // In fact the value is 772 (see conversions.cc), but to give us some margin
    // we round up to 780.
    static const int kMaxSignificantDecimalDigits = 780;
    
    static BufferReference<const char> TrimLeadingZeros(BufferReference<const char> buffer) {
        for (int i = 0; i < buffer.length(); i++) {
            if (buffer[i] != '0') {
                return buffer.SubBufferReference(i, buffer.length());
            }
        }
        return BufferReference<const char>(buffer.start(), 0);
    }
    
    
    static BufferReference<const char> TrimTrailingZeros(BufferReference<const char> buffer) {
        for (int i = buffer.length() - 1; i >= 0; --i) {
            if (buffer[i] != '0') {
                return buffer.SubBufferReference(0, i + 1);
            }
        }
        return BufferReference<const char>(buffer.start(), 0);
    }
    
    
    static void TrimToMaxSignificantDigits(BufferReference<const char> buffer,
                                           int exponent,
                                           char* significant_buffer,
                                           int* significant_exponent) {
        for (int i = 0; i < kMaxSignificantDecimalDigits - 1; ++i) {
            significant_buffer[i] = buffer[i];
        }
        // The input buffer has been trimmed. Therefore the last digit must be
        // different from '0'.
        ASSERT(buffer[buffer.length() - 1] != '0');
        // Set the last digit to be non-zero. This is sufficient to guarantee
        // correct rounding.
        significant_buffer[kMaxSignificantDecimalDigits - 1] = '1';
        *significant_exponent =
        exponent + (buffer.length() - kMaxSignificantDecimalDigits);
    }
    
    // Reads digits from the buffer and converts them to a uint64.
    // Reads in as many digits as fit into a uint64.
    // When the string starts with "1844674407370955161" no further digit is read.
    // Since 2^64 = 18446744073709551616 it would still be possible read another
    // digit if it was less or equal than 6, but this would complicate the code.
    static uint64_t ReadUint64(BufferReference<const char> buffer,
                               int* number_of_read_digits) {
        uint64_t result = 0;
        int i = 0;
        while (i < buffer.length() && result <= (kMaxUint64 / 10 - 1)) {
            int digit = buffer[i++] - '0';
            ASSERT(0 <= digit && digit <= 9);
            result = 10 * result + digit;
        }
        *number_of_read_digits = i;
        return result;
    }
    
    
    // Reads a DiyFp from the buffer.
    // The returned DiyFp is not necessarily normalized.
    // If remaining_decimals is zero then the returned DiyFp is accurate.
    // Otherwise it has been rounded and has error of at most 1/2 ulp.
    static void ReadDiyFp(BufferReference<const char> buffer,
                          DiyFp* result,
                          int* remaining_decimals) {
        int read_digits;
        uint64_t significand = ReadUint64(buffer, &read_digits);
        if (buffer.length() == read_digits) {
            *result = DiyFp(significand, 0);
            *remaining_decimals = 0;
        } else {
            // Round the significand.
            if (buffer[read_digits] >= '5') {
                significand++;
            }
            // Compute the binary exponent.
            int exponent = 0;
            *result = DiyFp(significand, exponent);
            *remaining_decimals = buffer.length() - read_digits;
        }
    }
    
    
    static bool DoubleStrtod(BufferReference<const char> trimmed,
                             int exponent,
                             double* result) {
#if !defined(DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS)
        UNUSED_PARAM(trimmed);
        UNUSED_PARAM(exponent);
        UNUSED_PARAM(result);
        // On x86 the floating-point stack can be 64 or 80 bits wide. If it is
        // 80 bits wide (as is the case on Linux) then double-rounding occurs and the
        // result is not accurate.
        // We know that Windows32 uses 64 bits and is therefore accurate.
        // Note that the ARM simulator is compiled for 32bits. It therefore exhibits
        // the same problem.
        return false;
#else
        if (trimmed.length() <= kMaxExactDoubleIntegerDecimalDigits) {
            int read_digits;
            // The trimmed input fits into a double.
            // If the 10^exponent (resp. 10^-exponent) fits into a double too then we
            // can compute the result-double simply by multiplying (resp. dividing) the
            // two numbers.
            // This is possible because IEEE guarantees that floating-point operations
            // return the best possible approximation.
            if (exponent < 0 && -exponent < kExactPowersOfTenSize) {
                // 10^-exponent fits into a double.
                *result = static_cast<double>(ReadUint64(trimmed, &read_digits));
                ASSERT(read_digits == trimmed.length());
                *result /= exact_powers_of_ten[-exponent];
                return true;
            }
            if (0 <= exponent && exponent < kExactPowersOfTenSize) {
                // 10^exponent fits into a double.
                *result = static_cast<double>(ReadUint64(trimmed, &read_digits));
                ASSERT(read_digits == trimmed.length());
                *result *= exact_powers_of_ten[exponent];
                return true;
            }
            int remaining_digits =
            kMaxExactDoubleIntegerDecimalDigits - trimmed.length();
            if ((0 <= exponent) &&
                (exponent - remaining_digits < kExactPowersOfTenSize)) {
                // The trimmed string was short and we can multiply it with
                // 10^remaining_digits. As a result the remaining exponent now fits
                // into a double too.
                *result = static_cast<double>(ReadUint64(trimmed, &read_digits));
                ASSERT(read_digits == trimmed.length());
                *result *= exact_powers_of_ten[remaining_digits];
                *result *= exact_powers_of_ten[exponent - remaining_digits];
                return true;
            }
        }
        return false;
#endif
    }
    
    
    // Returns 10^exponent as an exact DiyFp.
    // The given exponent must be in the range [1; kDecimalExponentDistance[.
    static DiyFp AdjustmentPowerOfTen(int exponent) {
        ASSERT(0 < exponent);
        ASSERT(exponent < PowersOfTenCache::kDecimalExponentDistance);
        // Simply hardcode the remaining powers for the given decimal exponent
        // distance.
        ASSERT(PowersOfTenCache::kDecimalExponentDistance == 8);
        switch (exponent) {
            case 1: return DiyFp(UINT64_2PART_C(0xa0000000, 00000000), -60);
            case 2: return DiyFp(UINT64_2PART_C(0xc8000000, 00000000), -57);
            case 3: return DiyFp(UINT64_2PART_C(0xfa000000, 00000000), -54);
            case 4: return DiyFp(UINT64_2PART_C(0x9c400000, 00000000), -50);
            case 5: return DiyFp(UINT64_2PART_C(0xc3500000, 00000000), -47);
            case 6: return DiyFp(UINT64_2PART_C(0xf4240000, 00000000), -44);
            case 7: return DiyFp(UINT64_2PART_C(0x98968000, 00000000), -40);
            default:
                UNREACHABLE();
                return DiyFp(0, 0);
        }
    }
    
    
    // If the function returns true then the result is the correct double.
    // Otherwise it is either the correct double or the double that is just below
    // the correct double.
    static bool DiyFpStrtod(BufferReference<const char> buffer,
                            int exponent,
                            double* result) {
        DiyFp input;
        int remaining_decimals;
        ReadDiyFp(buffer, &input, &remaining_decimals);
        // Since we may have dropped some digits the input is not accurate.
        // If remaining_decimals is different than 0 than the error is at most
        // .5 ulp (unit in the last place).
        // We don't want to deal with fractions and therefore keep a common
        // denominator.
        const int kDenominatorLog = 3;
        const int kDenominator = 1 << kDenominatorLog;
        // Move the remaining decimals into the exponent.
        exponent += remaining_decimals;
        int error = (remaining_decimals == 0 ? 0 : kDenominator / 2);
        
        int old_e = input.e();
        input.Normalize();
        error <<= old_e - input.e();
        
        ASSERT(exponent <= PowersOfTenCache::kMaxDecimalExponent);
        if (exponent < PowersOfTenCache::kMinDecimalExponent) {
            *result = 0.0;
            return true;
        }
        DiyFp cached_power;
        int cached_decimal_exponent;
        PowersOfTenCache::GetCachedPowerForDecimalExponent(exponent,
                                                           &cached_power,
                                                           &cached_decimal_exponent);
        
        if (cached_decimal_exponent != exponent) {
            int adjustment_exponent = exponent - cached_decimal_exponent;
            DiyFp adjustment_power = AdjustmentPowerOfTen(adjustment_exponent);
            input.Multiply(adjustment_power);
            if (kMaxUint64DecimalDigits - buffer.length() >= adjustment_exponent) {
                // The product of input with the adjustment power fits into a 64 bit
                // integer.
                ASSERT(DiyFp::kSignificandSize == 64);
            } else {
                // The adjustment power is exact. There is hence only an error of 0.5.
                error += kDenominator / 2;
            }
        }
        
        input.Multiply(cached_power);
        // The error introduced by a multiplication of a*b equals
        //   error_a + error_b + error_a*error_b/2^64 + 0.5
        // Substituting a with 'input' and b with 'cached_power' we have
        //   error_b = 0.5  (all cached powers have an error of less than 0.5 ulp),
        //   error_ab = 0 or 1 / kDenominator > error_a*error_b/ 2^64
        int error_b = kDenominator / 2;
        int error_ab = (error == 0 ? 0 : 1);  // We round up to 1.
        int fixed_error = kDenominator / 2;
        error += error_b + error_ab + fixed_error;
        
        old_e = input.e();
        input.Normalize();
        error <<= old_e - input.e();
        
        // See if the double's significand changes if we add/subtract the error.
        int order_of_magnitude = DiyFp::kSignificandSize + input.e();
        int effective_significand_size =
        Double::SignificandSizeForOrderOfMagnitude(order_of_magnitude);
        int precision_digits_count =
        DiyFp::kSignificandSize - effective_significand_size;
        if (precision_digits_count + kDenominatorLog >= DiyFp::kSignificandSize) {
            // This can only happen for very small denormals. In this case the
            // half-way multiplied by the denominator exceeds the range of an uint64.
            // Simply shift everything to the right.
            int shift_amount = (precision_digits_count + kDenominatorLog) -
            DiyFp::kSignificandSize + 1;
            input.set_f(input.f() >> shift_amount);
            input.set_e(input.e() + shift_amount);
            // We add 1 for the lost precision of error, and kDenominator for
            // the lost precision of input.f().
            error = (error >> shift_amount) + 1 + kDenominator;
            precision_digits_count -= shift_amount;
        }
        // We use uint64_ts now. This only works if the DiyFp uses uint64_ts too.
        ASSERT(DiyFp::kSignificandSize == 64);
        ASSERT(precision_digits_count < 64);
        uint64_t one64 = 1;
        uint64_t precision_bits_mask = (one64 << precision_digits_count) - 1;
        uint64_t precision_bits = input.f() & precision_bits_mask;
        uint64_t half_way = one64 << (precision_digits_count - 1);
        precision_bits *= kDenominator;
        half_way *= kDenominator;
        DiyFp rounded_input(input.f() >> precision_digits_count,
                            input.e() + precision_digits_count);
        if (precision_bits >= half_way + error) {
            rounded_input.set_f(rounded_input.f() + 1);
        }
        // If the last_bits are too close to the half-way case than we are too
        // inaccurate and round down. In this case we return false so that we can
        // fall back to a more precise algorithm.
        
        *result = Double(rounded_input).value();
        if (half_way - error < precision_bits && precision_bits < half_way + error) {
            // Too imprecise. The caller will have to fall back to a slower version.
            // However the returned number is guaranteed to be either the correct
            // double, or the next-lower double.
            return false;
        } else {
            return true;
        }
    }
    
    
    // Returns the correct double for the buffer*10^exponent.
    // The variable guess should be a close guess that is either the correct double
    // or its lower neighbor (the nearest double less than the correct one).
    // Preconditions:
    //   buffer.length() + exponent <= kMaxDecimalPower + 1
    //   buffer.length() + exponent > kMinDecimalPower
    //   buffer.length() <= kMaxDecimalSignificantDigits
    static double BignumStrtod(BufferReference<const char> buffer,
                               int exponent,
                               double guess) {
        if (guess == Double::Infinity()) {
            return guess;
        }
        
        DiyFp upper_boundary = Double(guess).UpperBoundary();
        
        ASSERT(buffer.length() + exponent <= kMaxDecimalPower + 1);
        ASSERT(buffer.length() + exponent > kMinDecimalPower);
        ASSERT(buffer.length() <= kMaxSignificantDecimalDigits);
        // Make sure that the Bignum will be able to hold all our numbers.
        // Our Bignum implementation has a separate field for exponents. Shifts will
        // consume at most one bigit (< 64 bits).
        // ln(10) == 3.3219...
        ASSERT(((kMaxDecimalPower + 1) * 333 / 100) < Bignum::kMaxSignificantBits);
        Bignum input;
        Bignum boundary;
        input.AssignDecimalString(buffer);
        boundary.AssignUInt64(upper_boundary.f());
        if (exponent >= 0) {
            input.MultiplyByPowerOfTen(exponent);
        } else {
            boundary.MultiplyByPowerOfTen(-exponent);
        }
        if (upper_boundary.e() > 0) {
            boundary.ShiftLeft(upper_boundary.e());
        } else {
            input.ShiftLeft(-upper_boundary.e());
        }
        int comparison = Bignum::Compare(input, boundary);
        if (comparison < 0) {
            return guess;
        } else if (comparison > 0) {
            return Double(guess).NextDouble();
        } else if ((Double(guess).Significand() & 1) == 0) {
            // Round towards even.
            return guess;
        } else {
            return Double(guess).NextDouble();
        }
    }
    
    
    double Strtod(BufferReference<const char> buffer, int exponent) {
        BufferReference<const char> left_trimmed = TrimLeadingZeros(buffer);
        BufferReference<const char> trimmed = TrimTrailingZeros(left_trimmed);
        exponent += left_trimmed.length() - trimmed.length();
        if (trimmed.length() == 0) return 0.0;
        if (trimmed.length() > kMaxSignificantDecimalDigits) {
            char significant_buffer[kMaxSignificantDecimalDigits];
            int significant_exponent;
            TrimToMaxSignificantDigits(trimmed, exponent,
                                       significant_buffer, &significant_exponent);
            return Strtod(BufferReference<const char>(significant_buffer,
                                             kMaxSignificantDecimalDigits),
                          significant_exponent);
        }
        if (exponent + trimmed.length() - 1 >= kMaxDecimalPower) {
            return Double::Infinity();
        }
        if (exponent + trimmed.length() <= kMinDecimalPower) {
            return 0.0;
        }
        
        double guess;
        if (DoubleStrtod(trimmed, exponent, &guess) ||
            DiyFpStrtod(trimmed, exponent, &guess)) {
            return guess;
        }
        return BignumStrtod(trimmed, exponent, guess);
    }
    
}  // namespace double_conversion

} // namespace WTF
