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