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