LCOV - code coverage report
Current view: top level - mfbt/decimal - Decimal.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 12 557 2.2 %
Date: 2017-07-14 16:53:18 Functions: 2 54 3.7 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13