tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

Decimal.cpp (27643B)


      1 /*
      2 * Copyright (C) 2012 Google Inc. All rights reserved.
      3 *
      4 * Redistribution and use in source and binary forms, with or without
      5 * modification, are permitted provided that the following conditions are
      6 * met:
      7 *
      8 *     * Redistributions of source code must retain the above copyright
      9 * notice, this list of conditions and the following disclaimer.
     10 *     * Redistributions in binary form must reproduce the above
     11 * copyright notice, this list of conditions and the following disclaimer
     12 * in the documentation and/or other materials provided with the
     13 * distribution.
     14 *     * Neither the name of Google Inc. nor the names of its
     15 * contributors may be used to endorse or promote products derived from
     16 * this software without specific prior written permission.
     17 *
     18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29 */
     30 
     31 #include "Decimal.h"
     32 #include "moz-decimal-utils.h"
     33 #include "DoubleConversion.h"
     34 
     35 using namespace moz_decimal_utils;
     36 
     37 #include <algorithm>
     38 #include <float.h>
     39 
     40 namespace blink {
     41 
     42 namespace DecimalPrivate {
     43 
     44 // This class handles Decimal special values.
     45 class SpecialValueHandler {
     46    STACK_ALLOCATED();
     47    WTF_MAKE_NONCOPYABLE(SpecialValueHandler);
     48 public:
     49    enum HandleResult {
     50        BothFinite,
     51        BothInfinity,
     52        EitherNaN,
     53        LHSIsInfinity,
     54        RHSIsInfinity,
     55    };
     56 
     57    SpecialValueHandler(const Decimal& lhs, const Decimal& rhs);
     58    HandleResult handle();
     59    Decimal value() const;
     60 
     61 private:
     62    enum Result {
     63        ResultIsLHS,
     64        ResultIsRHS,
     65        ResultIsUnknown,
     66    };
     67 
     68    const Decimal& m_lhs;
     69    const Decimal& m_rhs;
     70    Result m_result;
     71 };
     72 
     73 SpecialValueHandler::SpecialValueHandler(const Decimal& lhs, const Decimal& rhs)
     74    : m_lhs(lhs), m_rhs(rhs), m_result(ResultIsUnknown)
     75 {
     76 }
     77 
     78 SpecialValueHandler::HandleResult SpecialValueHandler::handle()
     79 {
     80    if (m_lhs.isFinite() && m_rhs.isFinite())
     81        return BothFinite;
     82 
     83    const Decimal::EncodedData::FormatClass lhsClass = m_lhs.value().formatClass();
     84    const Decimal::EncodedData::FormatClass rhsClass = m_rhs.value().formatClass();
     85    if (lhsClass == Decimal::EncodedData::ClassNaN) {
     86        m_result = ResultIsLHS;
     87        return EitherNaN;
     88    }
     89 
     90    if (rhsClass == Decimal::EncodedData::ClassNaN) {
     91        m_result = ResultIsRHS;
     92        return EitherNaN;
     93    }
     94 
     95    if (lhsClass == Decimal::EncodedData::ClassInfinity)
     96        return rhsClass == Decimal::EncodedData::ClassInfinity ? BothInfinity : LHSIsInfinity;
     97 
     98    if (rhsClass == Decimal::EncodedData::ClassInfinity)
     99        return RHSIsInfinity;
    100 
    101    ASSERT_NOT_REACHED();
    102    return BothFinite;
    103 }
    104 
    105 Decimal SpecialValueHandler::value() const
    106 {
    107    switch (m_result) {
    108    case ResultIsLHS:
    109        return m_lhs;
    110    case ResultIsRHS:
    111        return m_rhs;
    112    case ResultIsUnknown:
    113    default:
    114        ASSERT_NOT_REACHED();
    115        return m_lhs;
    116    }
    117 }
    118 
    119 // This class is used for 128 bit unsigned integer arithmetic.
    120 class UInt128 {
    121 public:
    122    UInt128(uint64_t low, uint64_t high)
    123        : m_high(high), m_low(low)
    124    {
    125    }
    126 
    127    UInt128& operator/=(uint32_t);
    128 
    129    uint64_t high() const { return m_high; }
    130    uint64_t low() const { return m_low; }
    131 
    132    static UInt128 multiply(uint64_t u, uint64_t v) { return UInt128(u * v, multiplyHigh(u, v)); }
    133 
    134 private:
    135    static uint32_t highUInt32(uint64_t x) { return static_cast<uint32_t>(x >> 32); }
    136    static uint32_t lowUInt32(uint64_t x) { return static_cast<uint32_t>(x & ((static_cast<uint64_t>(1) << 32) - 1)); }
    137    static uint64_t makeUInt64(uint32_t low, uint32_t high) { return low | (static_cast<uint64_t>(high) << 32); }
    138 
    139    static uint64_t multiplyHigh(uint64_t, uint64_t);
    140 
    141    uint64_t m_high;
    142    uint64_t m_low;
    143 };
    144 
    145 UInt128& UInt128::operator/=(const uint32_t divisor)
    146 {
    147    ASSERT(divisor);
    148 
    149    if (!m_high) {
    150        m_low /= divisor;
    151        return *this;
    152    }
    153 
    154    uint32_t dividend[4];
    155    dividend[0] = lowUInt32(m_low);
    156    dividend[1] = highUInt32(m_low);
    157    dividend[2] = lowUInt32(m_high);
    158    dividend[3] = highUInt32(m_high);
    159 
    160    uint32_t quotient[4];
    161    uint32_t remainder = 0;
    162    for (int i = 3; i >= 0; --i) {
    163        const uint64_t work = makeUInt64(dividend[i], remainder);
    164        remainder = static_cast<uint32_t>(work % divisor);
    165        quotient[i] = static_cast<uint32_t>(work / divisor);
    166    }
    167    m_low = makeUInt64(quotient[0], quotient[1]);
    168    m_high = makeUInt64(quotient[2], quotient[3]);
    169    return *this;
    170 }
    171 
    172 // Returns high 64bit of 128bit product.
    173 uint64_t UInt128::multiplyHigh(uint64_t u, uint64_t v)
    174 {
    175    const uint64_t uLow = lowUInt32(u);
    176    const uint64_t uHigh = highUInt32(u);
    177    const uint64_t vLow = lowUInt32(v);
    178    const uint64_t vHigh = highUInt32(v);
    179    const uint64_t partialProduct = uHigh * vLow + highUInt32(uLow * vLow);
    180    return uHigh * vHigh + highUInt32(partialProduct) + highUInt32(uLow * vHigh + lowUInt32(partialProduct));
    181 }
    182 
    183 static int countDigits(uint64_t x)
    184 {
    185    int numberOfDigits = 0;
    186    for (uint64_t powerOfTen = 1; x >= powerOfTen; powerOfTen *= 10) {
    187        ++numberOfDigits;
    188        if (powerOfTen >= std::numeric_limits<uint64_t>::max() / 10)
    189            break;
    190    }
    191    return numberOfDigits;
    192 }
    193 
    194 static uint64_t scaleDown(uint64_t x, int n)
    195 {
    196    ASSERT(n >= 0);
    197    while (n > 0 && x) {
    198        x /= 10;
    199        --n;
    200    }
    201    return x;
    202 }
    203 
    204 static uint64_t scaleUp(uint64_t x, int n)
    205 {
    206    ASSERT(n >= 0);
    207    ASSERT(n <= Precision);
    208 
    209    uint64_t y = 1;
    210    uint64_t z = 10;
    211    for (;;) {
    212        if (n & 1)
    213            y = y * z;
    214 
    215        n >>= 1;
    216        if (!n)
    217            return x * y;
    218 
    219        z = z * z;
    220    }
    221 }
    222 
    223 } // namespace DecimalPrivate
    224 
    225 using namespace DecimalPrivate;
    226 
    227 bool Decimal::EncodedData::operator==(const EncodedData& another) const
    228 {
    229    return m_sign == another.m_sign
    230        && m_formatClass == another.m_formatClass
    231        && m_exponent == another.m_exponent
    232        && m_coefficient == another.m_coefficient;
    233 }
    234 
    235 
    236 Decimal::Decimal(int32_t i32)
    237    : Decimal(DecimalLiteral{i32}) {}
    238 
    239 Decimal::Decimal(Sign sign, int exponent, uint64_t coefficient)
    240    : m_data(sign, coefficient ? exponent : 0, coefficient) {}
    241 
    242 Decimal::Decimal(const Decimal& other)
    243    : m_data(other.m_data)
    244 {
    245 }
    246 
    247 Decimal& Decimal::operator=(const Decimal& other)
    248 {
    249    m_data = other.m_data;
    250    return *this;
    251 }
    252 
    253 Decimal& Decimal::operator+=(const Decimal& other)
    254 {
    255    m_data = (*this + other).m_data;
    256    return *this;
    257 }
    258 
    259 Decimal& Decimal::operator-=(const Decimal& other)
    260 {
    261    m_data = (*this - other).m_data;
    262    return *this;
    263 }
    264 
    265 Decimal& Decimal::operator*=(const Decimal& other)
    266 {
    267    m_data = (*this * other).m_data;
    268    return *this;
    269 }
    270 
    271 Decimal& Decimal::operator/=(const Decimal& other)
    272 {
    273    m_data = (*this / other).m_data;
    274    return *this;
    275 }
    276 
    277 Decimal Decimal::operator-() const
    278 {
    279    if (isNaN())
    280        return *this;
    281 
    282    Decimal result(*this);
    283    result.m_data.setSign(invertSign(m_data.sign()));
    284    return result;
    285 }
    286 
    287 Decimal Decimal::operator+(const Decimal& rhs) const
    288 {
    289    const Decimal& lhs = *this;
    290    const Sign lhsSign = lhs.sign();
    291    const Sign rhsSign = rhs.sign();
    292 
    293    SpecialValueHandler handler(lhs, rhs);
    294    switch (handler.handle()) {
    295    case SpecialValueHandler::BothFinite:
    296        break;
    297 
    298    case SpecialValueHandler::BothInfinity:
    299        return lhsSign == rhsSign ? lhs : nan();
    300 
    301    case SpecialValueHandler::EitherNaN:
    302        return handler.value();
    303 
    304    case SpecialValueHandler::LHSIsInfinity:
    305        return lhs;
    306 
    307    case SpecialValueHandler::RHSIsInfinity:
    308        return rhs;
    309    }
    310 
    311    const AlignedOperands alignedOperands = alignOperands(lhs, rhs);
    312 
    313    const uint64_t result = lhsSign == rhsSign
    314        ? alignedOperands.lhsCoefficient + alignedOperands.rhsCoefficient
    315        : alignedOperands.lhsCoefficient - alignedOperands.rhsCoefficient;
    316 
    317    if (lhsSign == Negative && rhsSign == Positive && !result)
    318        return Decimal(Positive, alignedOperands.exponent, 0);
    319 
    320    return static_cast<int64_t>(result) >= 0
    321        ? Decimal(lhsSign, alignedOperands.exponent, result)
    322        : Decimal(invertSign(lhsSign), alignedOperands.exponent, -static_cast<int64_t>(result));
    323 }
    324 
    325 Decimal Decimal::operator-(const Decimal& rhs) const
    326 {
    327    const Decimal& lhs = *this;
    328    const Sign lhsSign = lhs.sign();
    329    const Sign rhsSign = rhs.sign();
    330 
    331    SpecialValueHandler handler(lhs, rhs);
    332    switch (handler.handle()) {
    333    case SpecialValueHandler::BothFinite:
    334        break;
    335 
    336    case SpecialValueHandler::BothInfinity:
    337        return lhsSign == rhsSign ? nan() : lhs;
    338 
    339    case SpecialValueHandler::EitherNaN:
    340        return handler.value();
    341 
    342    case SpecialValueHandler::LHSIsInfinity:
    343        return lhs;
    344 
    345    case SpecialValueHandler::RHSIsInfinity:
    346        return infinity(invertSign(rhsSign));
    347    }
    348 
    349    const AlignedOperands alignedOperands = alignOperands(lhs, rhs);
    350 
    351    const uint64_t result = lhsSign == rhsSign
    352        ? alignedOperands.lhsCoefficient - alignedOperands.rhsCoefficient
    353        : alignedOperands.lhsCoefficient + alignedOperands.rhsCoefficient;
    354 
    355    if (lhsSign == Negative && rhsSign == Negative && !result)
    356        return Decimal(Positive, alignedOperands.exponent, 0);
    357 
    358    return static_cast<int64_t>(result) >= 0
    359        ? Decimal(lhsSign, alignedOperands.exponent, result)
    360        : Decimal(invertSign(lhsSign), alignedOperands.exponent, -static_cast<int64_t>(result));
    361 }
    362 
    363 Decimal Decimal::operator*(const Decimal& rhs) const
    364 {
    365    const Decimal& lhs = *this;
    366    const Sign lhsSign = lhs.sign();
    367    const Sign rhsSign = rhs.sign();
    368    const Sign resultSign = lhsSign == rhsSign ? Positive : Negative;
    369 
    370    SpecialValueHandler handler(lhs, rhs);
    371    switch (handler.handle()) {
    372    case SpecialValueHandler::BothFinite: {
    373        const uint64_t lhsCoefficient = lhs.m_data.coefficient();
    374        const uint64_t rhsCoefficient = rhs.m_data.coefficient();
    375        int resultExponent = lhs.exponent() + rhs.exponent();
    376        UInt128 work(UInt128::multiply(lhsCoefficient, rhsCoefficient));
    377        while (work.high()) {
    378            work /= 10;
    379            ++resultExponent;
    380        }
    381        return Decimal(resultSign, resultExponent, work.low());
    382    }
    383 
    384    case SpecialValueHandler::BothInfinity:
    385        return infinity(resultSign);
    386 
    387    case SpecialValueHandler::EitherNaN:
    388        return handler.value();
    389 
    390    case SpecialValueHandler::LHSIsInfinity:
    391        return rhs.isZero() ? nan() : infinity(resultSign);
    392 
    393    case SpecialValueHandler::RHSIsInfinity:
    394        return lhs.isZero() ? nan() : infinity(resultSign);
    395    }
    396 
    397    ASSERT_NOT_REACHED();
    398    return nan();
    399 }
    400 
    401 Decimal Decimal::operator/(const Decimal& rhs) const
    402 {
    403    const Decimal& lhs = *this;
    404    const Sign lhsSign = lhs.sign();
    405    const Sign rhsSign = rhs.sign();
    406    const Sign resultSign = lhsSign == rhsSign ? Positive : Negative;
    407 
    408    SpecialValueHandler handler(lhs, rhs);
    409    switch (handler.handle()) {
    410    case SpecialValueHandler::BothFinite:
    411        break;
    412 
    413    case SpecialValueHandler::BothInfinity:
    414        return nan();
    415 
    416    case SpecialValueHandler::EitherNaN:
    417        return handler.value();
    418 
    419    case SpecialValueHandler::LHSIsInfinity:
    420        return infinity(resultSign);
    421 
    422    case SpecialValueHandler::RHSIsInfinity:
    423        return zero(resultSign);
    424    }
    425 
    426    ASSERT(lhs.isFinite());
    427    ASSERT(rhs.isFinite());
    428 
    429    if (rhs.isZero())
    430        return lhs.isZero() ? nan() : infinity(resultSign);
    431 
    432    int resultExponent = lhs.exponent() - rhs.exponent();
    433 
    434    if (lhs.isZero())
    435        return Decimal(resultSign, resultExponent, 0);
    436 
    437    uint64_t remainder = lhs.m_data.coefficient();
    438    const uint64_t divisor = rhs.m_data.coefficient();
    439    uint64_t result = 0;
    440    for (;;) {
    441        while (remainder < divisor && result < MaxCoefficient / 10) {
    442            remainder *= 10;
    443            result *= 10;
    444            --resultExponent;
    445        }
    446        if (remainder < divisor)
    447            break;
    448        uint64_t quotient = remainder / divisor;
    449        if (result > MaxCoefficient - quotient)
    450            break;
    451        result += quotient;
    452        remainder %= divisor;
    453        if (!remainder)
    454            break;
    455    }
    456 
    457    if (remainder > divisor / 2)
    458        ++result;
    459 
    460    return Decimal(resultSign, resultExponent, result);
    461 }
    462 
    463 bool Decimal::operator==(const Decimal& rhs) const
    464 {
    465    if (isNaN() || rhs.isNaN())
    466        return false;
    467    return m_data == rhs.m_data || compareTo(rhs).isZero();
    468 }
    469 
    470 bool Decimal::operator!=(const Decimal& rhs) const
    471 {
    472    if (isNaN() || rhs.isNaN())
    473        return true;
    474    if (m_data == rhs.m_data)
    475        return false;
    476    const Decimal result = compareTo(rhs);
    477    if (result.isNaN())
    478        return false;
    479    return !result.isZero();
    480 }
    481 
    482 bool Decimal::operator<(const Decimal& rhs) const
    483 {
    484    const Decimal result = compareTo(rhs);
    485    if (result.isNaN())
    486        return false;
    487    return !result.isZero() && result.isNegative();
    488 }
    489 
    490 bool Decimal::operator<=(const Decimal& rhs) const
    491 {
    492    if (isNaN() || rhs.isNaN())
    493        return false;
    494    if (m_data == rhs.m_data)
    495        return true;
    496    const Decimal result = compareTo(rhs);
    497    if (result.isNaN())
    498        return false;
    499    return result.isZero() || result.isNegative();
    500 }
    501 
    502 bool Decimal::operator>(const Decimal& rhs) const
    503 {
    504    const Decimal result = compareTo(rhs);
    505    if (result.isNaN())
    506        return false;
    507    return !result.isZero() && result.isPositive();
    508 }
    509 
    510 bool Decimal::operator>=(const Decimal& rhs) const
    511 {
    512    if (isNaN() || rhs.isNaN())
    513        return false;
    514    if (m_data == rhs.m_data)
    515        return true;
    516    const Decimal result = compareTo(rhs);
    517    if (result.isNaN())
    518        return false;
    519    return result.isZero() || !result.isNegative();
    520 }
    521 
    522 Decimal Decimal::abs() const
    523 {
    524    Decimal result(*this);
    525    result.m_data.setSign(Positive);
    526    return result;
    527 }
    528 
    529 Decimal::AlignedOperands Decimal::alignOperands(const Decimal& lhs, const Decimal& rhs)
    530 {
    531    ASSERT(lhs.isFinite());
    532    ASSERT(rhs.isFinite());
    533 
    534    const int lhsExponent = lhs.exponent();
    535    const int rhsExponent = rhs.exponent();
    536    int exponent = std::min(lhsExponent, rhsExponent);
    537    uint64_t lhsCoefficient = lhs.m_data.coefficient();
    538    uint64_t rhsCoefficient = rhs.m_data.coefficient();
    539 
    540    if (lhsExponent > rhsExponent) {
    541        const int numberOfLHSDigits = countDigits(lhsCoefficient);
    542        if (numberOfLHSDigits) {
    543            const int lhsShiftAmount = lhsExponent - rhsExponent;
    544            const int overflow = numberOfLHSDigits + lhsShiftAmount - Precision;
    545            if (overflow <= 0) {
    546                lhsCoefficient = scaleUp(lhsCoefficient, lhsShiftAmount);
    547            } else {
    548                lhsCoefficient = scaleUp(lhsCoefficient, lhsShiftAmount - overflow);
    549                rhsCoefficient = scaleDown(rhsCoefficient, overflow);
    550                exponent += overflow;
    551            }
    552        }
    553 
    554    } else if (lhsExponent < rhsExponent) {
    555        const int numberOfRHSDigits = countDigits(rhsCoefficient);
    556        if (numberOfRHSDigits) {
    557            const int rhsShiftAmount = rhsExponent - lhsExponent;
    558            const int overflow = numberOfRHSDigits + rhsShiftAmount - Precision;
    559            if (overflow <= 0) {
    560                rhsCoefficient = scaleUp(rhsCoefficient, rhsShiftAmount);
    561            } else {
    562                rhsCoefficient = scaleUp(rhsCoefficient, rhsShiftAmount - overflow);
    563                lhsCoefficient = scaleDown(lhsCoefficient, overflow);
    564                exponent += overflow;
    565            }
    566        }
    567    }
    568 
    569    AlignedOperands alignedOperands;
    570    alignedOperands.exponent = exponent;
    571    alignedOperands.lhsCoefficient = lhsCoefficient;
    572    alignedOperands.rhsCoefficient = rhsCoefficient;
    573    return alignedOperands;
    574 }
    575 
    576 static bool isMultiplePowersOfTen(uint64_t coefficient, int n)
    577 {
    578    return !coefficient || !(coefficient % scaleUp(1, n));
    579 }
    580 
    581 // Round toward positive infinity.
    582 Decimal Decimal::ceil() const
    583 {
    584    if (isSpecial())
    585        return *this;
    586 
    587    if (exponent() >= 0)
    588        return *this;
    589 
    590    uint64_t result = m_data.coefficient();
    591    const int numberOfDigits = countDigits(result);
    592    const int numberOfDropDigits = -exponent();
    593    if (numberOfDigits <= numberOfDropDigits)
    594        return isPositive() ? Decimal(1) : zero(Positive);
    595 
    596    result = scaleDown(result, numberOfDropDigits);
    597    if (isPositive() && !isMultiplePowersOfTen(m_data.coefficient(), numberOfDropDigits))
    598        ++result;
    599    return Decimal(sign(), 0, result);
    600 }
    601 
    602 Decimal Decimal::compareTo(const Decimal& rhs) const
    603 {
    604    const Decimal result(*this - rhs);
    605    switch (result.m_data.formatClass()) {
    606    case EncodedData::ClassInfinity:
    607        return result.isNegative() ? Decimal(-1) : Decimal(1);
    608 
    609    case EncodedData::ClassNaN:
    610    case EncodedData::ClassNormal:
    611        return result;
    612 
    613    case EncodedData::ClassZero:
    614        return zero(Positive);
    615 
    616    default:
    617        ASSERT_NOT_REACHED();
    618        return nan();
    619    }
    620 }
    621 
    622 // Round toward negative infinity.
    623 Decimal Decimal::floor() const
    624 {
    625    if (isSpecial())
    626        return *this;
    627 
    628    if (exponent() >= 0)
    629        return *this;
    630 
    631    uint64_t result = m_data.coefficient();
    632    const int numberOfDigits = countDigits(result);
    633    const int numberOfDropDigits = -exponent();
    634    if (numberOfDigits < numberOfDropDigits)
    635        return isPositive() ? zero(Positive) : Decimal(-1);
    636 
    637    result = scaleDown(result, numberOfDropDigits);
    638    if (isNegative() && !isMultiplePowersOfTen(m_data.coefficient(), numberOfDropDigits))
    639        ++result;
    640    return Decimal(sign(), 0, result);
    641 }
    642 
    643 Decimal Decimal::fromDouble(double doubleValue)
    644 {
    645    if (std::isfinite(doubleValue))
    646        return fromString(mozToString(doubleValue));
    647 
    648    if (std::isinf(doubleValue))
    649        return infinity(doubleValue < 0 ? Negative : Positive);
    650 
    651    return nan();
    652 }
    653 
    654 Decimal Decimal::fromString(const String& str)
    655 {
    656    int exponent = 0;
    657    Sign exponentSign = Positive;
    658    int numberOfDigits = 0;
    659    int numberOfDigitsAfterDot = 0;
    660    int numberOfExtraDigits = 0;
    661    Sign sign = Positive;
    662 
    663    enum {
    664        StateDigit,
    665        StateDot,
    666        StateDotDigit,
    667        StateE,
    668        StateEDigit,
    669        StateESign,
    670        StateSign,
    671        StateStart,
    672        StateZero,
    673    } state = StateStart;
    674 
    675 #define HandleCharAndBreak(expected, nextState) \
    676    if (ch == expected) { \
    677        state = nextState; \
    678        break; \
    679    }
    680 
    681 #define HandleTwoCharsAndBreak(expected1, expected2, nextState) \
    682    if (ch == expected1 || ch == expected2) { \
    683        state = nextState; \
    684        break; \
    685    }
    686 
    687    uint64_t accumulator = 0;
    688    for (unsigned index = 0; index < str.length(); ++index) {
    689        const int ch = str[index];
    690        switch (state) {
    691        case StateDigit:
    692            if (ch >= '0' && ch <= '9') {
    693                if (numberOfDigits < Precision) {
    694                    ++numberOfDigits;
    695                    accumulator *= 10;
    696                    accumulator += ch - '0';
    697                } else {
    698                    ++numberOfExtraDigits;
    699                }
    700                break;
    701            }
    702 
    703            HandleCharAndBreak('.', StateDot);
    704            HandleTwoCharsAndBreak('E', 'e', StateE);
    705            return nan();
    706 
    707        case StateDot:
    708        case StateDotDigit:
    709            if (ch >= '0' && ch <= '9') {
    710                if (numberOfDigits < Precision) {
    711                    ++numberOfDigits;
    712                    ++numberOfDigitsAfterDot;
    713                    accumulator *= 10;
    714                    accumulator += ch - '0';
    715                }
    716                state = StateDotDigit;
    717                break;
    718            }
    719 
    720            HandleTwoCharsAndBreak('E', 'e', StateE);
    721            return nan();
    722 
    723        case StateE:
    724            if (ch == '+') {
    725                exponentSign = Positive;
    726                state = StateESign;
    727                break;
    728            }
    729 
    730            if (ch == '-') {
    731                exponentSign = Negative;
    732                state = StateESign;
    733                break;
    734            }
    735 
    736            if (ch >= '0' && ch <= '9') {
    737                exponent = ch - '0';
    738                state = StateEDigit;
    739                break;
    740            }
    741 
    742            return nan();
    743 
    744        case StateEDigit:
    745            if (ch >= '0' && ch <= '9') {
    746                exponent *= 10;
    747                exponent += ch - '0';
    748                if (exponent > ExponentMax + Precision) {
    749                    if (accumulator)
    750                        return exponentSign == Negative ? zero(Positive) : infinity(sign);
    751                    return zero(sign);
    752                }
    753                state = StateEDigit;
    754                break;
    755            }
    756 
    757            return nan();
    758 
    759        case StateESign:
    760            if (ch >= '0' && ch <= '9') {
    761                exponent = ch - '0';
    762                state = StateEDigit;
    763                break;
    764            }
    765 
    766            return nan();
    767 
    768        case StateSign:
    769            if (ch >= '1' && ch <= '9') {
    770                accumulator = ch - '0';
    771                numberOfDigits = 1;
    772                state = StateDigit;
    773                break;
    774            }
    775 
    776            HandleCharAndBreak('0', StateZero);
    777            return nan();
    778 
    779        case StateStart:
    780            if (ch >= '1' && ch <= '9') {
    781                accumulator = ch - '0';
    782                numberOfDigits = 1;
    783                state = StateDigit;
    784                break;
    785            }
    786 
    787            if (ch == '-') {
    788                sign = Negative;
    789                state = StateSign;
    790                break;
    791            }
    792 
    793            if (ch == '+') {
    794                sign = Positive;
    795                state = StateSign;
    796                break;
    797            }
    798 
    799            HandleCharAndBreak('0', StateZero);
    800            HandleCharAndBreak('.', StateDot);
    801            return nan();
    802 
    803        case StateZero:
    804            if (ch == '0')
    805                break;
    806 
    807            if (ch >= '1' && ch <= '9') {
    808                accumulator = ch - '0';
    809                numberOfDigits = 1;
    810                state = StateDigit;
    811                break;
    812            }
    813 
    814            HandleCharAndBreak('.', StateDot);
    815            HandleTwoCharsAndBreak('E', 'e', StateE);
    816            return nan();
    817 
    818        default:
    819            ASSERT_NOT_REACHED();
    820            return nan();
    821        }
    822    }
    823 
    824    if (state == StateZero)
    825        return zero(sign);
    826 
    827    if (state == StateDigit || state == StateEDigit || state == StateDotDigit) {
    828        int resultExponent = exponent * (exponentSign == Negative ? -1 : 1) - numberOfDigitsAfterDot + numberOfExtraDigits;
    829        if (resultExponent < ExponentMin)
    830            return zero(Positive);
    831 
    832        const int overflow = resultExponent - ExponentMax + 1;
    833        if (overflow > 0) {
    834            if (overflow + numberOfDigits - numberOfDigitsAfterDot > Precision)
    835                return infinity(sign);
    836            accumulator = scaleUp(accumulator, overflow);
    837            resultExponent -= overflow;
    838        }
    839 
    840        return Decimal(sign, resultExponent, accumulator);
    841    }
    842 
    843    return nan();
    844 }
    845 
    846 Decimal Decimal::infinity(const Sign sign)
    847 {
    848    return Decimal(EncodedData(sign, EncodedData::ClassInfinity));
    849 }
    850 
    851 Decimal Decimal::remainder(const Decimal& rhs) const
    852 {
    853    const Decimal quotient = *this / rhs;
    854    return quotient.isSpecial() ? quotient : *this - (quotient.isNegative() ? quotient.ceil() : quotient.floor()) * rhs;
    855 }
    856 
    857 Decimal Decimal::round() const
    858 {
    859    if (isSpecial())
    860        return *this;
    861 
    862    if (exponent() >= 0)
    863        return *this;
    864 
    865    uint64_t result = m_data.coefficient();
    866    const int numberOfDigits = countDigits(result);
    867    const int numberOfDropDigits = -exponent();
    868    if (numberOfDigits < numberOfDropDigits)
    869        return zero(Positive);
    870 
    871    result = scaleDown(result, numberOfDropDigits - 1);
    872    if (result % 10 >= 5)
    873        result += 10;
    874    result /= 10;
    875    return Decimal(sign(), 0, result);
    876 }
    877 
    878 double Decimal::toDouble() const
    879 {
    880    if (isFinite()) {
    881        bool valid;
    882        const double doubleValue = mozToDouble(toString(), &valid);
    883        return valid ? doubleValue : std::numeric_limits<double>::quiet_NaN();
    884    }
    885 
    886    if (isInfinity())
    887        return isNegative() ? -std::numeric_limits<double>::infinity() : std::numeric_limits<double>::infinity();
    888 
    889    return std::numeric_limits<double>::quiet_NaN();
    890 }
    891 
    892 String Decimal::toString() const
    893 {
    894    switch (m_data.formatClass()) {
    895    case EncodedData::ClassInfinity:
    896        return sign() ? "-Infinity" : "Infinity";
    897 
    898    case EncodedData::ClassNaN:
    899        return "NaN";
    900 
    901    case EncodedData::ClassNormal:
    902    case EncodedData::ClassZero:
    903        break;
    904 
    905    default:
    906        ASSERT_NOT_REACHED();
    907        return "";
    908    }
    909 
    910    StringBuilder builder;
    911    if (sign())
    912        builder.append('-');
    913 
    914    int originalExponent = exponent();
    915    uint64_t coefficient = m_data.coefficient();
    916 
    917    if (originalExponent < 0) {
    918        const int maxDigits = DBL_DIG;
    919        uint64_t lastDigit = 0;
    920        while (countDigits(coefficient) > maxDigits) {
    921            lastDigit = coefficient % 10;
    922            coefficient /= 10;
    923            ++originalExponent;
    924        }
    925 
    926        if (lastDigit >= 5)
    927            ++coefficient;
    928 
    929        while (originalExponent < 0 && coefficient && !(coefficient % 10)) {
    930            coefficient /= 10;
    931            ++originalExponent;
    932        }
    933    }
    934 
    935    const String digits = mozToString(coefficient);
    936    int coefficientLength = static_cast<int>(digits.length());
    937    const int adjustedExponent = originalExponent + coefficientLength - 1;
    938    if (originalExponent <= 0 && adjustedExponent >= -6) {
    939        if (!originalExponent) {
    940            builder.append(digits);
    941            return builder.toString();
    942        }
    943 
    944        if (adjustedExponent >= 0) {
    945            for (int i = 0; i < coefficientLength; ++i) {
    946                builder.append(digits[i]);
    947                if (i == adjustedExponent)
    948                    builder.append('.');
    949            }
    950            return builder.toString();
    951        }
    952 
    953        builder.appendLiteral("0.");
    954        for (int i = adjustedExponent + 1; i < 0; ++i)
    955            builder.append('0');
    956 
    957        builder.append(digits);
    958 
    959    } else {
    960        builder.append(digits[0]);
    961        while (coefficientLength >= 2 && digits[coefficientLength - 1] == '0')
    962            --coefficientLength;
    963        if (coefficientLength >= 2) {
    964            builder.append('.');
    965            for (int i = 1; i < coefficientLength; ++i)
    966                builder.append(digits[i]);
    967        }
    968 
    969        if (adjustedExponent) {
    970            builder.append(adjustedExponent < 0 ? "e" : "e+");
    971            builder.appendNumber(adjustedExponent);
    972        }
    973    }
    974    return builder.toString();
    975 }
    976 
    977 Decimal Decimal::zero(Sign sign)
    978 {
    979    return Decimal(EncodedData(sign, EncodedData::ClassZero));
    980 }
    981 
    982 } // namespace blink
    983 
    984 // Implementation of DoubleConversion.h:
    985 
    986 namespace mozilla {
    987 
    988 Maybe<double> StringToDouble(Span<const char> aStringSpan) {
    989    bool valid = false;
    990    double result = mozToDouble(aStringSpan, &valid);
    991    return valid ? Some(result) : Nothing();
    992 }
    993 
    994 }