Backed out changeset b71c8c052463 (bug 1943846) for causing mass failures. CLOSED...
[gecko.git] / mozglue / misc / decimal / Decimal.cpp
blob922b636f563b2d24d5fbc90885242408b9abccf0
1 /*
2 * Copyright (C) 2012 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
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.
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.
31 #include "Decimal.h"
32 #include "moz-decimal-utils.h"
33 #include "DoubleConversion.h"
35 using namespace moz_decimal_utils;
37 #include <algorithm>
38 #include <float.h>
40 namespace blink {
42 namespace DecimalPrivate {
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,
57 SpecialValueHandler(const Decimal& lhs, const Decimal& rhs);
58 HandleResult handle();
59 Decimal value() const;
61 private:
62 enum Result {
63 ResultIsLHS,
64 ResultIsRHS,
65 ResultIsUnknown,
68 const Decimal& m_lhs;
69 const Decimal& m_rhs;
70 Result m_result;
73 SpecialValueHandler::SpecialValueHandler(const Decimal& lhs, const Decimal& rhs)
74 : m_lhs(lhs), m_rhs(rhs), m_result(ResultIsUnknown)
78 SpecialValueHandler::HandleResult SpecialValueHandler::handle()
80 if (m_lhs.isFinite() && m_rhs.isFinite())
81 return BothFinite;
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;
90 if (rhsClass == Decimal::EncodedData::ClassNaN) {
91 m_result = ResultIsRHS;
92 return EitherNaN;
95 if (lhsClass == Decimal::EncodedData::ClassInfinity)
96 return rhsClass == Decimal::EncodedData::ClassInfinity ? BothInfinity : LHSIsInfinity;
98 if (rhsClass == Decimal::EncodedData::ClassInfinity)
99 return RHSIsInfinity;
101 ASSERT_NOT_REACHED();
102 return BothFinite;
105 Decimal SpecialValueHandler::value() const
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;
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)
127 UInt128& operator/=(uint32_t);
129 uint64_t high() const { return m_high; }
130 uint64_t low() const { return m_low; }
132 static UInt128 multiply(uint64_t u, uint64_t v) { return UInt128(u * v, multiplyHigh(u, v)); }
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); }
139 static uint64_t multiplyHigh(uint64_t, uint64_t);
141 uint64_t m_high;
142 uint64_t m_low;
145 UInt128& UInt128::operator/=(const uint32_t divisor)
147 ASSERT(divisor);
149 if (!m_high) {
150 m_low /= divisor;
151 return *this;
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);
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);
167 m_low = makeUInt64(quotient[0], quotient[1]);
168 m_high = makeUInt64(quotient[2], quotient[3]);
169 return *this;
172 // Returns high 64bit of 128bit product.
173 uint64_t UInt128::multiplyHigh(uint64_t u, uint64_t v)
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));
183 static int countDigits(uint64_t x)
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;
191 return numberOfDigits;
194 static uint64_t scaleDown(uint64_t x, int n)
196 ASSERT(n >= 0);
197 while (n > 0 && x) {
198 x /= 10;
199 --n;
201 return x;
204 static uint64_t scaleUp(uint64_t x, int n)
206 ASSERT(n >= 0);
207 ASSERT(n <= Precision);
209 uint64_t y = 1;
210 uint64_t z = 10;
211 for (;;) {
212 if (n & 1)
213 y = y * z;
215 n >>= 1;
216 if (!n)
217 return x * y;
219 z = z * z;
223 } // namespace DecimalPrivate
225 using namespace DecimalPrivate;
227 bool Decimal::EncodedData::operator==(const EncodedData& another) const
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;
236 Decimal::Decimal(int32_t i32)
237 : Decimal(DecimalLiteral{i32}) {}
239 Decimal::Decimal(Sign sign, int exponent, uint64_t coefficient)
240 : m_data(sign, coefficient ? exponent : 0, coefficient) {}
242 Decimal::Decimal(const Decimal& other)
243 : m_data(other.m_data)
247 Decimal& Decimal::operator=(const Decimal& other)
249 m_data = other.m_data;
250 return *this;
253 Decimal& Decimal::operator+=(const Decimal& other)
255 m_data = (*this + other).m_data;
256 return *this;
259 Decimal& Decimal::operator-=(const Decimal& other)
261 m_data = (*this - other).m_data;
262 return *this;
265 Decimal& Decimal::operator*=(const Decimal& other)
267 m_data = (*this * other).m_data;
268 return *this;
271 Decimal& Decimal::operator/=(const Decimal& other)
273 m_data = (*this / other).m_data;
274 return *this;
277 Decimal Decimal::operator-() const
279 if (isNaN())
280 return *this;
282 Decimal result(*this);
283 result.m_data.setSign(invertSign(m_data.sign()));
284 return result;
287 Decimal Decimal::operator+(const Decimal& rhs) const
289 const Decimal& lhs = *this;
290 const Sign lhsSign = lhs.sign();
291 const Sign rhsSign = rhs.sign();
293 SpecialValueHandler handler(lhs, rhs);
294 switch (handler.handle()) {
295 case SpecialValueHandler::BothFinite:
296 break;
298 case SpecialValueHandler::BothInfinity:
299 return lhsSign == rhsSign ? lhs : nan();
301 case SpecialValueHandler::EitherNaN:
302 return handler.value();
304 case SpecialValueHandler::LHSIsInfinity:
305 return lhs;
307 case SpecialValueHandler::RHSIsInfinity:
308 return rhs;
311 const AlignedOperands alignedOperands = alignOperands(lhs, rhs);
313 const uint64_t result = lhsSign == rhsSign
314 ? alignedOperands.lhsCoefficient + alignedOperands.rhsCoefficient
315 : alignedOperands.lhsCoefficient - alignedOperands.rhsCoefficient;
317 if (lhsSign == Negative && rhsSign == Positive && !result)
318 return Decimal(Positive, alignedOperands.exponent, 0);
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));
325 Decimal Decimal::operator-(const Decimal& rhs) const
327 const Decimal& lhs = *this;
328 const Sign lhsSign = lhs.sign();
329 const Sign rhsSign = rhs.sign();
331 SpecialValueHandler handler(lhs, rhs);
332 switch (handler.handle()) {
333 case SpecialValueHandler::BothFinite:
334 break;
336 case SpecialValueHandler::BothInfinity:
337 return lhsSign == rhsSign ? nan() : lhs;
339 case SpecialValueHandler::EitherNaN:
340 return handler.value();
342 case SpecialValueHandler::LHSIsInfinity:
343 return lhs;
345 case SpecialValueHandler::RHSIsInfinity:
346 return infinity(invertSign(rhsSign));
349 const AlignedOperands alignedOperands = alignOperands(lhs, rhs);
351 const uint64_t result = lhsSign == rhsSign
352 ? alignedOperands.lhsCoefficient - alignedOperands.rhsCoefficient
353 : alignedOperands.lhsCoefficient + alignedOperands.rhsCoefficient;
355 if (lhsSign == Negative && rhsSign == Negative && !result)
356 return Decimal(Positive, alignedOperands.exponent, 0);
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));
363 Decimal Decimal::operator*(const Decimal& rhs) const
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;
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;
381 return Decimal(resultSign, resultExponent, work.low());
384 case SpecialValueHandler::BothInfinity:
385 return infinity(resultSign);
387 case SpecialValueHandler::EitherNaN:
388 return handler.value();
390 case SpecialValueHandler::LHSIsInfinity:
391 return rhs.isZero() ? nan() : infinity(resultSign);
393 case SpecialValueHandler::RHSIsInfinity:
394 return lhs.isZero() ? nan() : infinity(resultSign);
397 ASSERT_NOT_REACHED();
398 return nan();
401 Decimal Decimal::operator/(const Decimal& rhs) const
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;
408 SpecialValueHandler handler(lhs, rhs);
409 switch (handler.handle()) {
410 case SpecialValueHandler::BothFinite:
411 break;
413 case SpecialValueHandler::BothInfinity:
414 return nan();
416 case SpecialValueHandler::EitherNaN:
417 return handler.value();
419 case SpecialValueHandler::LHSIsInfinity:
420 return infinity(resultSign);
422 case SpecialValueHandler::RHSIsInfinity:
423 return zero(resultSign);
426 ASSERT(lhs.isFinite());
427 ASSERT(rhs.isFinite());
429 if (rhs.isZero())
430 return lhs.isZero() ? nan() : infinity(resultSign);
432 int resultExponent = lhs.exponent() - rhs.exponent();
434 if (lhs.isZero())
435 return Decimal(resultSign, resultExponent, 0);
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;
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;
457 if (remainder > divisor / 2)
458 ++result;
460 return Decimal(resultSign, resultExponent, result);
463 bool Decimal::operator==(const Decimal& rhs) const
465 if (isNaN() || rhs.isNaN())
466 return false;
467 return m_data == rhs.m_data || compareTo(rhs).isZero();
470 bool Decimal::operator!=(const Decimal& rhs) const
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();
482 bool Decimal::operator<(const Decimal& rhs) const
484 const Decimal result = compareTo(rhs);
485 if (result.isNaN())
486 return false;
487 return !result.isZero() && result.isNegative();
490 bool Decimal::operator<=(const Decimal& rhs) const
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();
502 bool Decimal::operator>(const Decimal& rhs) const
504 const Decimal result = compareTo(rhs);
505 if (result.isNaN())
506 return false;
507 return !result.isZero() && result.isPositive();
510 bool Decimal::operator>=(const Decimal& rhs) const
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();
522 Decimal Decimal::abs() const
524 Decimal result(*this);
525 result.m_data.setSign(Positive);
526 return result;
529 Decimal::AlignedOperands Decimal::alignOperands(const Decimal& lhs, const Decimal& rhs)
531 ASSERT(lhs.isFinite());
532 ASSERT(rhs.isFinite());
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();
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;
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;
569 AlignedOperands alignedOperands;
570 alignedOperands.exponent = exponent;
571 alignedOperands.lhsCoefficient = lhsCoefficient;
572 alignedOperands.rhsCoefficient = rhsCoefficient;
573 return alignedOperands;
576 static bool isMultiplePowersOfTen(uint64_t coefficient, int n)
578 return !coefficient || !(coefficient % scaleUp(1, n));
581 // Round toward positive infinity.
582 Decimal Decimal::ceil() const
584 if (isSpecial())
585 return *this;
587 if (exponent() >= 0)
588 return *this;
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);
596 result = scaleDown(result, numberOfDropDigits);
597 if (isPositive() && !isMultiplePowersOfTen(m_data.coefficient(), numberOfDropDigits))
598 ++result;
599 return Decimal(sign(), 0, result);
602 Decimal Decimal::compareTo(const Decimal& rhs) const
604 const Decimal result(*this - rhs);
605 switch (result.m_data.formatClass()) {
606 case EncodedData::ClassInfinity:
607 return result.isNegative() ? Decimal(-1) : Decimal(1);
609 case EncodedData::ClassNaN:
610 case EncodedData::ClassNormal:
611 return result;
613 case EncodedData::ClassZero:
614 return zero(Positive);
616 default:
617 ASSERT_NOT_REACHED();
618 return nan();
622 // Round toward negative infinity.
623 Decimal Decimal::floor() const
625 if (isSpecial())
626 return *this;
628 if (exponent() >= 0)
629 return *this;
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);
637 result = scaleDown(result, numberOfDropDigits);
638 if (isNegative() && !isMultiplePowersOfTen(m_data.coefficient(), numberOfDropDigits))
639 ++result;
640 return Decimal(sign(), 0, result);
643 Decimal Decimal::fromDouble(double doubleValue)
645 if (std::isfinite(doubleValue))
646 return fromString(mozToString(doubleValue));
648 if (std::isinf(doubleValue))
649 return infinity(doubleValue < 0 ? Negative : Positive);
651 return nan();
654 Decimal Decimal::fromString(const String& str)
656 int exponent = 0;
657 Sign exponentSign = Positive;
658 int numberOfDigits = 0;
659 int numberOfDigitsAfterDot = 0;
660 int numberOfExtraDigits = 0;
661 Sign sign = Positive;
663 enum {
664 StateDigit,
665 StateDot,
666 StateDotDigit,
667 StateE,
668 StateEDigit,
669 StateESign,
670 StateSign,
671 StateStart,
672 StateZero,
673 } state = StateStart;
675 #define HandleCharAndBreak(expected, nextState) \
676 if (ch == expected) { \
677 state = nextState; \
678 break; \
681 #define HandleTwoCharsAndBreak(expected1, expected2, nextState) \
682 if (ch == expected1 || ch == expected2) { \
683 state = nextState; \
684 break; \
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;
700 break;
703 HandleCharAndBreak('.', StateDot);
704 HandleTwoCharsAndBreak('E', 'e', StateE);
705 return nan();
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';
716 state = StateDotDigit;
717 break;
720 HandleTwoCharsAndBreak('E', 'e', StateE);
721 return nan();
723 case StateE:
724 if (ch == '+') {
725 exponentSign = Positive;
726 state = StateESign;
727 break;
730 if (ch == '-') {
731 exponentSign = Negative;
732 state = StateESign;
733 break;
736 if (ch >= '0' && ch <= '9') {
737 exponent = ch - '0';
738 state = StateEDigit;
739 break;
742 return nan();
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);
753 state = StateEDigit;
754 break;
757 return nan();
759 case StateESign:
760 if (ch >= '0' && ch <= '9') {
761 exponent = ch - '0';
762 state = StateEDigit;
763 break;
766 return nan();
768 case StateSign:
769 if (ch >= '1' && ch <= '9') {
770 accumulator = ch - '0';
771 numberOfDigits = 1;
772 state = StateDigit;
773 break;
776 HandleCharAndBreak('0', StateZero);
777 return nan();
779 case StateStart:
780 if (ch >= '1' && ch <= '9') {
781 accumulator = ch - '0';
782 numberOfDigits = 1;
783 state = StateDigit;
784 break;
787 if (ch == '-') {
788 sign = Negative;
789 state = StateSign;
790 break;
793 if (ch == '+') {
794 sign = Positive;
795 state = StateSign;
796 break;
799 HandleCharAndBreak('0', StateZero);
800 HandleCharAndBreak('.', StateDot);
801 return nan();
803 case StateZero:
804 if (ch == '0')
805 break;
807 if (ch >= '1' && ch <= '9') {
808 accumulator = ch - '0';
809 numberOfDigits = 1;
810 state = StateDigit;
811 break;
814 HandleCharAndBreak('.', StateDot);
815 HandleTwoCharsAndBreak('E', 'e', StateE);
816 return nan();
818 default:
819 ASSERT_NOT_REACHED();
820 return nan();
824 if (state == StateZero)
825 return zero(sign);
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);
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;
840 return Decimal(sign, resultExponent, accumulator);
843 return nan();
846 Decimal Decimal::infinity(const Sign sign)
848 return Decimal(EncodedData(sign, EncodedData::ClassInfinity));
851 Decimal Decimal::remainder(const Decimal& rhs) const
853 const Decimal quotient = *this / rhs;
854 return quotient.isSpecial() ? quotient : *this - (quotient.isNegative() ? quotient.ceil() : quotient.floor()) * rhs;
857 Decimal Decimal::round() const
859 if (isSpecial())
860 return *this;
862 if (exponent() >= 0)
863 return *this;
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);
871 result = scaleDown(result, numberOfDropDigits - 1);
872 if (result % 10 >= 5)
873 result += 10;
874 result /= 10;
875 return Decimal(sign(), 0, result);
878 double Decimal::toDouble() const
880 if (isFinite()) {
881 bool valid;
882 const double doubleValue = mozToDouble(toString(), &valid);
883 return valid ? doubleValue : std::numeric_limits<double>::quiet_NaN();
886 if (isInfinity())
887 return isNegative() ? -std::numeric_limits<double>::infinity() : std::numeric_limits<double>::infinity();
889 return std::numeric_limits<double>::quiet_NaN();
892 String Decimal::toString() const
894 switch (m_data.formatClass()) {
895 case EncodedData::ClassInfinity:
896 return sign() ? "-Infinity" : "Infinity";
898 case EncodedData::ClassNaN:
899 return "NaN";
901 case EncodedData::ClassNormal:
902 case EncodedData::ClassZero:
903 break;
905 default:
906 ASSERT_NOT_REACHED();
907 return "";
910 StringBuilder builder;
911 if (sign())
912 builder.append('-');
914 int originalExponent = exponent();
915 uint64_t coefficient = m_data.coefficient();
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;
926 if (lastDigit >= 5)
927 ++coefficient;
929 while (originalExponent < 0 && coefficient && !(coefficient % 10)) {
930 coefficient /= 10;
931 ++originalExponent;
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();
944 if (adjustedExponent >= 0) {
945 for (int i = 0; i < coefficientLength; ++i) {
946 builder.append(digits[i]);
947 if (i == adjustedExponent)
948 builder.append('.');
950 return builder.toString();
953 builder.appendLiteral("0.");
954 for (int i = adjustedExponent + 1; i < 0; ++i)
955 builder.append('0');
957 builder.append(digits);
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]);
969 if (adjustedExponent) {
970 builder.append(adjustedExponent < 0 ? "e" : "e+");
971 builder.appendNumber(adjustedExponent);
974 return builder.toString();
977 Decimal Decimal::zero(Sign sign)
979 return Decimal(EncodedData(sign, EncodedData::ClassZero));
982 } // namespace blink
984 // Implementation of DoubleConversion.h:
986 namespace mozilla {
988 Maybe<double> StringToDouble(Span<const char> aStringSpan) {
989 bool valid = false;
990 double result = mozToDouble(aStringSpan, &valid);
991 return valid ? Some(result) : Nothing();