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 "third_party/blink/renderer/platform/wtf/decimal.h"
32
33 #include <algorithm>
34 #include <cfloat>
35
36 #include "base/macros.h"
37 #include "base/notreached.h"
38 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
39 #include "third_party/blink/renderer/platform/wtf/math_extras.h"
40 #include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
41
42 namespace blink {
43
44 namespace {
45
46 constexpr int kExponentMax = 1023;
47 constexpr int kExponentMin = -1023;
48 constexpr int kPrecision = 18;
49
50 constexpr uint64_t kMaxCoefficient =
51 UINT64_C(0xDE0B6B3A763FFFF); // 999999999999999999 == 18 9's
52
53 // This class handles Decimal special values.
54 class SpecialValueHandler {
55 STACK_ALLOCATED();
56
57 public:
58 enum HandleResult {
59 kBothFinite,
60 kBothInfinity,
61 kEitherNaN,
62 kLHSIsInfinity,
63 kRHSIsInfinity,
64 };
65
66 SpecialValueHandler(const Decimal& lhs, const Decimal& rhs);
67 HandleResult Handle();
68 Decimal Value() const;
69
70 private:
71 enum Result {
72 kResultIsLHS,
73 kResultIsRHS,
74 kResultIsUnknown,
75 };
76
77 const Decimal& lhs_;
78 const Decimal& rhs_;
79 Result result_ = kResultIsUnknown;
80
81 DISALLOW_COPY_AND_ASSIGN(SpecialValueHandler);
82 };
83
SpecialValueHandler(const Decimal & lhs,const Decimal & rhs)84 SpecialValueHandler::SpecialValueHandler(const Decimal& lhs, const Decimal& rhs)
85 : lhs_(lhs), rhs_(rhs) {}
86
Handle()87 SpecialValueHandler::HandleResult SpecialValueHandler::Handle() {
88 if (lhs_.IsFinite() && rhs_.IsFinite())
89 return kBothFinite;
90
91 if (lhs_.IsNaN()) {
92 result_ = kResultIsLHS;
93 return kEitherNaN;
94 }
95
96 if (rhs_.IsNaN()) {
97 result_ = kResultIsRHS;
98 return kEitherNaN;
99 }
100
101 if (lhs_.IsInfinity())
102 return rhs_.IsInfinity() ? kBothInfinity : kLHSIsInfinity;
103
104 DCHECK(rhs_.IsInfinity());
105 return kRHSIsInfinity;
106 }
107
Value() const108 Decimal SpecialValueHandler::Value() const {
109 DCHECK(result_ == kResultIsLHS || result_ == kResultIsRHS);
110 return (result_ == kResultIsLHS) ? lhs_ : rhs_;
111 }
112
113 // This class is used for 128 bit unsigned integer arithmetic.
114 class UInt128 {
115 STACK_ALLOCATED();
116
117 public:
UInt128(uint64_t low,uint64_t high)118 UInt128(uint64_t low, uint64_t high) : high_(high), low_(low) {}
119
120 UInt128& operator/=(uint32_t);
121
High() const122 uint64_t High() const { return high_; }
Low() const123 uint64_t Low() const { return low_; }
124
Multiply(uint64_t u,uint64_t v)125 static UInt128 Multiply(uint64_t u, uint64_t v) {
126 return UInt128(u * v, MultiplyHigh(u, v));
127 }
128
129 private:
HighUInt32(uint64_t x)130 static uint32_t HighUInt32(uint64_t x) {
131 return static_cast<uint32_t>(x >> 32);
132 }
LowUInt32(uint64_t x)133 static uint32_t LowUInt32(uint64_t x) {
134 return static_cast<uint32_t>(x & ((static_cast<uint64_t>(1) << 32) - 1));
135 }
MakeUInt64(uint32_t low,uint32_t high)136 static uint64_t MakeUInt64(uint32_t low, uint32_t high) {
137 return low | (static_cast<uint64_t>(high) << 32);
138 }
139
140 static uint64_t MultiplyHigh(uint64_t, uint64_t);
141
142 uint64_t high_;
143 uint64_t low_;
144 };
145
operator /=(const uint32_t divisor)146 UInt128& UInt128::operator/=(const uint32_t divisor) {
147 DCHECK(divisor);
148
149 if (!high_) {
150 low_ /= divisor;
151 return *this;
152 }
153
154 uint32_t dividend[4];
155 dividend[0] = LowUInt32(low_);
156 dividend[1] = HighUInt32(low_);
157 dividend[2] = LowUInt32(high_);
158 dividend[3] = HighUInt32(high_);
159
160 uint32_t quotient[4];
161 uint32_t remainder = 0;
162 for (int i = 3; i >= 0; --i) {
163 const uint64_t work = MakeUInt64(dividend[i], remainder);
164 remainder = static_cast<uint32_t>(work % divisor);
165 quotient[i] = static_cast<uint32_t>(work / divisor);
166 }
167 low_ = MakeUInt64(quotient[0], quotient[1]);
168 high_ = MakeUInt64(quotient[2], quotient[3]);
169 return *this;
170 }
171
172 // Returns high 64bit of 128bit product.
MultiplyHigh(uint64_t u,uint64_t v)173 uint64_t UInt128::MultiplyHigh(uint64_t u, uint64_t v) {
174 const uint64_t u_low = LowUInt32(u);
175 const uint64_t u_high = HighUInt32(u);
176 const uint64_t v_low = LowUInt32(v);
177 const uint64_t v_high = HighUInt32(v);
178 const uint64_t partial_product = u_high * v_low + HighUInt32(u_low * v_low);
179 return u_high * v_high + HighUInt32(partial_product) +
180 HighUInt32(u_low * v_high + LowUInt32(partial_product));
181 }
182
CountDigits(uint64_t x)183 static int CountDigits(uint64_t x) {
184 int number_of_digits = 0;
185 for (uint64_t power_of_ten = 1; x >= power_of_ten; power_of_ten *= 10) {
186 ++number_of_digits;
187 if (power_of_ten >= std::numeric_limits<uint64_t>::max() / 10)
188 break;
189 }
190 return number_of_digits;
191 }
192
ScaleDown(uint64_t x,int n)193 static uint64_t ScaleDown(uint64_t x, int n) {
194 DCHECK_GE(n, 0);
195 while (n > 0 && x) {
196 x /= 10;
197 --n;
198 }
199 return x;
200 }
201
ScaleUp(uint64_t x,int n)202 static uint64_t ScaleUp(uint64_t x, int n) {
203 DCHECK_GE(n, 0);
204 DCHECK_LE(n, kPrecision);
205
206 uint64_t y = 1;
207 uint64_t z = 10;
208 for (;;) {
209 if (n & 1)
210 y = y * z;
211
212 n >>= 1;
213 if (!n)
214 return x * y;
215
216 z = z * z;
217 }
218 }
219
220 } // namespace
221
EncodedData(Sign sign,FormatClass format_class)222 Decimal::EncodedData::EncodedData(Sign sign, FormatClass format_class)
223 : coefficient_(0), exponent_(0), format_class_(format_class), sign_(sign) {}
224
EncodedData(Sign sign,int exponent,uint64_t coefficient)225 Decimal::EncodedData::EncodedData(Sign sign, int exponent, uint64_t coefficient)
226 : format_class_(coefficient ? kClassNormal : kClassZero), sign_(sign) {
227 if (exponent >= kExponentMin && exponent <= kExponentMax) {
228 while (coefficient > kMaxCoefficient) {
229 coefficient /= 10;
230 ++exponent;
231 }
232 }
233
234 if (exponent > kExponentMax) {
235 coefficient_ = 0;
236 exponent_ = 0;
237 format_class_ = kClassInfinity;
238 return;
239 }
240
241 if (exponent < kExponentMin) {
242 coefficient_ = 0;
243 exponent_ = 0;
244 format_class_ = kClassZero;
245 return;
246 }
247
248 coefficient_ = coefficient;
249 exponent_ = static_cast<int16_t>(exponent);
250 }
251
operator ==(const EncodedData & another) const252 bool Decimal::EncodedData::operator==(const EncodedData& another) const {
253 return sign_ == another.sign_ && format_class_ == another.format_class_ &&
254 exponent_ == another.exponent_ && coefficient_ == another.coefficient_;
255 }
256
Decimal(int32_t i32)257 Decimal::Decimal(int32_t i32)
258 : data_(i32 < 0 ? kNegative : kPositive,
259 0,
260 i32 < 0 ? static_cast<uint64_t>(-static_cast<int64_t>(i32))
261 : static_cast<uint64_t>(i32)) {}
262
Decimal(Sign sign,int exponent,uint64_t coefficient)263 Decimal::Decimal(Sign sign, int exponent, uint64_t coefficient)
264 : data_(sign, exponent, coefficient) {}
265
Decimal(const EncodedData & data)266 Decimal::Decimal(const EncodedData& data) : data_(data) {}
267
268 Decimal::Decimal(const Decimal& other) = default;
269
270 Decimal& Decimal::operator=(const Decimal& other) = default;
271
operator +=(const Decimal & other)272 Decimal& Decimal::operator+=(const Decimal& other) {
273 data_ = (*this + other).data_;
274 return *this;
275 }
276
operator -=(const Decimal & other)277 Decimal& Decimal::operator-=(const Decimal& other) {
278 data_ = (*this - other).data_;
279 return *this;
280 }
281
operator *=(const Decimal & other)282 Decimal& Decimal::operator*=(const Decimal& other) {
283 data_ = (*this * other).data_;
284 return *this;
285 }
286
operator /=(const Decimal & other)287 Decimal& Decimal::operator/=(const Decimal& other) {
288 data_ = (*this / other).data_;
289 return *this;
290 }
291
operator -() const292 Decimal Decimal::operator-() const {
293 if (IsNaN())
294 return *this;
295
296 Decimal result(*this);
297 result.data_.SetSign(InvertSign(data_.GetSign()));
298 return result;
299 }
300
operator +(const Decimal & rhs) const301 Decimal Decimal::operator+(const Decimal& rhs) const {
302 const Decimal& lhs = *this;
303 const Sign lhs_sign = lhs.GetSign();
304 const Sign rhs_sign = rhs.GetSign();
305
306 SpecialValueHandler handler(lhs, rhs);
307 switch (handler.Handle()) {
308 case SpecialValueHandler::kBothFinite:
309 break;
310
311 case SpecialValueHandler::kBothInfinity:
312 return lhs_sign == rhs_sign ? lhs : Nan();
313
314 case SpecialValueHandler::kEitherNaN:
315 return handler.Value();
316
317 case SpecialValueHandler::kLHSIsInfinity:
318 return lhs;
319
320 case SpecialValueHandler::kRHSIsInfinity:
321 return rhs;
322 }
323
324 const AlignedOperands aligned_operands = AlignOperands(lhs, rhs);
325
326 const uint64_t result =
327 lhs_sign == rhs_sign
328 ? aligned_operands.lhs_coefficient + aligned_operands.rhs_coefficient
329 : aligned_operands.lhs_coefficient - aligned_operands.rhs_coefficient;
330
331 if (lhs_sign == kNegative && rhs_sign == kPositive && !result)
332 return Decimal(kPositive, aligned_operands.exponent, 0);
333
334 return static_cast<int64_t>(result) >= 0
335 ? Decimal(lhs_sign, aligned_operands.exponent, result)
336 : Decimal(InvertSign(lhs_sign), aligned_operands.exponent,
337 -static_cast<int64_t>(result));
338 }
339
operator -(const Decimal & rhs) const340 Decimal Decimal::operator-(const Decimal& rhs) const {
341 const Decimal& lhs = *this;
342 const Sign lhs_sign = lhs.GetSign();
343 const Sign rhs_sign = rhs.GetSign();
344
345 SpecialValueHandler handler(lhs, rhs);
346 switch (handler.Handle()) {
347 case SpecialValueHandler::kBothFinite:
348 break;
349
350 case SpecialValueHandler::kBothInfinity:
351 return lhs_sign == rhs_sign ? Nan() : lhs;
352
353 case SpecialValueHandler::kEitherNaN:
354 return handler.Value();
355
356 case SpecialValueHandler::kLHSIsInfinity:
357 return lhs;
358
359 case SpecialValueHandler::kRHSIsInfinity:
360 return Infinity(InvertSign(rhs_sign));
361 }
362
363 const AlignedOperands aligned_operands = AlignOperands(lhs, rhs);
364
365 const uint64_t result =
366 lhs_sign == rhs_sign
367 ? aligned_operands.lhs_coefficient - aligned_operands.rhs_coefficient
368 : aligned_operands.lhs_coefficient + aligned_operands.rhs_coefficient;
369
370 if (lhs_sign == kNegative && rhs_sign == kNegative && !result)
371 return Decimal(kPositive, aligned_operands.exponent, 0);
372
373 return static_cast<int64_t>(result) >= 0
374 ? Decimal(lhs_sign, aligned_operands.exponent, result)
375 : Decimal(InvertSign(lhs_sign), aligned_operands.exponent,
376 -static_cast<int64_t>(result));
377 }
378
operator *(const Decimal & rhs) const379 Decimal Decimal::operator*(const Decimal& rhs) const {
380 const Decimal& lhs = *this;
381 const Sign lhs_sign = lhs.GetSign();
382 const Sign rhs_sign = rhs.GetSign();
383 const Sign result_sign = lhs_sign == rhs_sign ? kPositive : kNegative;
384
385 SpecialValueHandler handler(lhs, rhs);
386 switch (handler.Handle()) {
387 case SpecialValueHandler::kBothFinite: {
388 const uint64_t lhs_coefficient = lhs.data_.Coefficient();
389 const uint64_t rhs_coefficient = rhs.data_.Coefficient();
390 int result_exponent = lhs.Exponent() + rhs.Exponent();
391 UInt128 work(UInt128::Multiply(lhs_coefficient, rhs_coefficient));
392 while (work.High()) {
393 work /= 10;
394 ++result_exponent;
395 }
396 return Decimal(result_sign, result_exponent, work.Low());
397 }
398
399 case SpecialValueHandler::kBothInfinity:
400 return Infinity(result_sign);
401
402 case SpecialValueHandler::kEitherNaN:
403 return handler.Value();
404
405 case SpecialValueHandler::kLHSIsInfinity:
406 return rhs.IsZero() ? Nan() : Infinity(result_sign);
407
408 case SpecialValueHandler::kRHSIsInfinity:
409 return lhs.IsZero() ? Nan() : Infinity(result_sign);
410 }
411
412 NOTREACHED();
413 return Nan();
414 }
415
operator /(const Decimal & rhs) const416 Decimal Decimal::operator/(const Decimal& rhs) const {
417 const Decimal& lhs = *this;
418 const Sign lhs_sign = lhs.GetSign();
419 const Sign rhs_sign = rhs.GetSign();
420 const Sign result_sign = lhs_sign == rhs_sign ? kPositive : kNegative;
421
422 SpecialValueHandler handler(lhs, rhs);
423 switch (handler.Handle()) {
424 case SpecialValueHandler::kBothFinite:
425 break;
426
427 case SpecialValueHandler::kBothInfinity:
428 return Nan();
429
430 case SpecialValueHandler::kEitherNaN:
431 return handler.Value();
432
433 case SpecialValueHandler::kLHSIsInfinity:
434 return Infinity(result_sign);
435
436 case SpecialValueHandler::kRHSIsInfinity:
437 return Zero(result_sign);
438 }
439
440 DCHECK(lhs.IsFinite());
441 DCHECK(rhs.IsFinite());
442
443 if (rhs.IsZero())
444 return lhs.IsZero() ? Nan() : Infinity(result_sign);
445
446 int result_exponent = lhs.Exponent() - rhs.Exponent();
447
448 if (lhs.IsZero())
449 return Decimal(result_sign, result_exponent, 0);
450
451 uint64_t remainder = lhs.data_.Coefficient();
452 const uint64_t divisor = rhs.data_.Coefficient();
453 uint64_t result = 0;
454 for (;;) {
455 while (remainder < divisor && result < kMaxCoefficient / 10) {
456 remainder *= 10;
457 result *= 10;
458 --result_exponent;
459 }
460 if (remainder < divisor)
461 break;
462 uint64_t quotient = remainder / divisor;
463 if (result > kMaxCoefficient - quotient)
464 break;
465 result += quotient;
466 remainder %= divisor;
467 if (!remainder)
468 break;
469 }
470
471 if (remainder > divisor / 2)
472 ++result;
473
474 return Decimal(result_sign, result_exponent, result);
475 }
476
operator ==(const Decimal & rhs) const477 bool Decimal::operator==(const Decimal& rhs) const {
478 return data_ == rhs.data_ || CompareTo(rhs).IsZero();
479 }
480
operator !=(const Decimal & rhs) const481 bool Decimal::operator!=(const Decimal& rhs) const {
482 if (data_ == rhs.data_)
483 return false;
484 const Decimal result = CompareTo(rhs);
485 if (result.IsNaN())
486 return false;
487 return !result.IsZero();
488 }
489
operator <(const Decimal & rhs) const490 bool Decimal::operator<(const Decimal& rhs) const {
491 const Decimal result = CompareTo(rhs);
492 if (result.IsNaN())
493 return false;
494 return !result.IsZero() && result.IsNegative();
495 }
496
operator <=(const Decimal & rhs) const497 bool Decimal::operator<=(const Decimal& rhs) const {
498 if (data_ == rhs.data_)
499 return true;
500 const Decimal result = CompareTo(rhs);
501 if (result.IsNaN())
502 return false;
503 return result.IsZero() || result.IsNegative();
504 }
505
operator >(const Decimal & rhs) const506 bool Decimal::operator>(const Decimal& rhs) const {
507 const Decimal result = CompareTo(rhs);
508 if (result.IsNaN())
509 return false;
510 return !result.IsZero() && result.IsPositive();
511 }
512
operator >=(const Decimal & rhs) const513 bool Decimal::operator>=(const Decimal& rhs) const {
514 if (data_ == rhs.data_)
515 return true;
516 const Decimal result = CompareTo(rhs);
517 if (result.IsNaN())
518 return false;
519 return result.IsZero() || !result.IsNegative();
520 }
521
Abs() const522 Decimal Decimal::Abs() const {
523 Decimal result(*this);
524 result.data_.SetSign(kPositive);
525 return result;
526 }
527
AlignOperands(const Decimal & lhs,const Decimal & rhs)528 Decimal::AlignedOperands Decimal::AlignOperands(const Decimal& lhs,
529 const Decimal& rhs) {
530 DCHECK(lhs.IsFinite());
531 DCHECK(rhs.IsFinite());
532
533 const int lhs_exponent = lhs.Exponent();
534 const int rhs_exponent = rhs.Exponent();
535 int exponent = std::min(lhs_exponent, rhs_exponent);
536 uint64_t lhs_coefficient = lhs.data_.Coefficient();
537 uint64_t rhs_coefficient = rhs.data_.Coefficient();
538
539 if (lhs_exponent > rhs_exponent) {
540 const int number_of_lhs_digits = CountDigits(lhs_coefficient);
541 if (number_of_lhs_digits) {
542 const int lhs_shift_amount = lhs_exponent - rhs_exponent;
543 const int overflow = number_of_lhs_digits + lhs_shift_amount - kPrecision;
544 if (overflow <= 0) {
545 lhs_coefficient = ScaleUp(lhs_coefficient, lhs_shift_amount);
546 } else {
547 lhs_coefficient = ScaleUp(lhs_coefficient, lhs_shift_amount - overflow);
548 rhs_coefficient = ScaleDown(rhs_coefficient, overflow);
549 exponent += overflow;
550 }
551 }
552
553 } else if (lhs_exponent < rhs_exponent) {
554 const int number_of_rhs_digits = CountDigits(rhs_coefficient);
555 if (number_of_rhs_digits) {
556 const int rhs_shift_amount = rhs_exponent - lhs_exponent;
557 const int overflow = number_of_rhs_digits + rhs_shift_amount - kPrecision;
558 if (overflow <= 0) {
559 rhs_coefficient = ScaleUp(rhs_coefficient, rhs_shift_amount);
560 } else {
561 rhs_coefficient = ScaleUp(rhs_coefficient, rhs_shift_amount - overflow);
562 lhs_coefficient = ScaleDown(lhs_coefficient, overflow);
563 exponent += overflow;
564 }
565 }
566 }
567
568 AlignedOperands aligned_operands;
569 aligned_operands.exponent = exponent;
570 aligned_operands.lhs_coefficient = lhs_coefficient;
571 aligned_operands.rhs_coefficient = rhs_coefficient;
572 return aligned_operands;
573 }
574
IsMultiplePowersOfTen(uint64_t coefficient,int n)575 static bool IsMultiplePowersOfTen(uint64_t coefficient, int n) {
576 return !coefficient || !(coefficient % ScaleUp(1, n));
577 }
578
579 // Round toward positive infinity.
Ceil() const580 Decimal Decimal::Ceil() const {
581 if (IsSpecial())
582 return *this;
583
584 if (Exponent() >= 0)
585 return *this;
586
587 uint64_t result = data_.Coefficient();
588 const int number_of_digits = CountDigits(result);
589 const int number_of_drop_digits = -Exponent();
590 if (number_of_digits <= number_of_drop_digits)
591 return IsPositive() ? Decimal(1) : Zero(kPositive);
592
593 result = ScaleDown(result, number_of_drop_digits);
594 if (IsPositive() &&
595 !IsMultiplePowersOfTen(data_.Coefficient(), number_of_drop_digits))
596 ++result;
597 return Decimal(GetSign(), 0, result);
598 }
599
CompareTo(const Decimal & rhs) const600 Decimal Decimal::CompareTo(const Decimal& rhs) const {
601 const Decimal result(*this - rhs);
602 switch (result.data_.GetFormatClass()) {
603 case EncodedData::kClassInfinity:
604 return result.IsNegative() ? Decimal(-1) : Decimal(1);
605
606 case EncodedData::kClassNaN:
607 case EncodedData::kClassNormal:
608 return result;
609
610 case EncodedData::kClassZero:
611 return Zero(kPositive);
612
613 default:
614 NOTREACHED();
615 return Nan();
616 }
617 }
618
619 // Round toward negative infinity.
Floor() const620 Decimal Decimal::Floor() const {
621 if (IsSpecial())
622 return *this;
623
624 if (Exponent() >= 0)
625 return *this;
626
627 uint64_t result = data_.Coefficient();
628 const int number_of_digits = CountDigits(result);
629 const int number_of_drop_digits = -Exponent();
630 if (number_of_digits < number_of_drop_digits)
631 return IsPositive() ? Zero(kPositive) : Decimal(-1);
632
633 result = ScaleDown(result, number_of_drop_digits);
634 if (IsNegative() &&
635 !IsMultiplePowersOfTen(data_.Coefficient(), number_of_drop_digits))
636 ++result;
637 return Decimal(GetSign(), 0, result);
638 }
639
FromDouble(double double_value)640 Decimal Decimal::FromDouble(double double_value) {
641 if (std::isfinite(double_value))
642 return FromString(String::NumberToStringECMAScript(double_value));
643
644 if (std::isinf(double_value))
645 return Infinity(double_value < 0 ? kNegative : kPositive);
646
647 return Nan();
648 }
649
FromString(const String & str)650 Decimal Decimal::FromString(const String& str) {
651 int exponent = 0;
652 Sign exponent_sign = kPositive;
653 int number_of_digits = 0;
654 int number_of_digits_after_dot = 0;
655 int number_of_extra_digits = 0;
656 Sign sign = kPositive;
657
658 enum {
659 kStateDigit,
660 kStateDot,
661 kStateDotDigit,
662 kStateE,
663 kStateEDigit,
664 kStateESign,
665 kStateSign,
666 kStateStart,
667 kStateZero,
668 } state = kStateStart;
669
670 #define HandleCharAndBreak(expected, nextState) \
671 if (ch == expected) { \
672 state = nextState; \
673 break; \
674 }
675
676 #define HandleTwoCharsAndBreak(expected1, expected2, nextState) \
677 if (ch == expected1 || ch == expected2) { \
678 state = nextState; \
679 break; \
680 }
681
682 uint64_t accumulator = 0;
683 for (unsigned index = 0; index < str.length(); ++index) {
684 const int ch = str[index];
685 switch (state) {
686 case kStateDigit:
687 if (ch >= '0' && ch <= '9') {
688 if (number_of_digits < kPrecision) {
689 ++number_of_digits;
690 accumulator *= 10;
691 accumulator += ch - '0';
692 } else {
693 ++number_of_extra_digits;
694 }
695 break;
696 }
697
698 HandleCharAndBreak('.', kStateDot);
699 HandleTwoCharsAndBreak('E', 'e', kStateE);
700 return Nan();
701
702 case kStateDot:
703 case kStateDotDigit:
704 if (ch >= '0' && ch <= '9') {
705 if (number_of_digits < kPrecision) {
706 ++number_of_digits;
707 ++number_of_digits_after_dot;
708 accumulator *= 10;
709 accumulator += ch - '0';
710 }
711 state = kStateDotDigit;
712 break;
713 }
714
715 HandleTwoCharsAndBreak('E', 'e', kStateE);
716 return Nan();
717
718 case kStateE:
719 if (ch == '+') {
720 exponent_sign = kPositive;
721 state = kStateESign;
722 break;
723 }
724
725 if (ch == '-') {
726 exponent_sign = kNegative;
727 state = kStateESign;
728 break;
729 }
730
731 if (ch >= '0' && ch <= '9') {
732 exponent = ch - '0';
733 state = kStateEDigit;
734 break;
735 }
736
737 return Nan();
738
739 case kStateEDigit:
740 if (ch >= '0' && ch <= '9') {
741 exponent *= 10;
742 exponent += ch - '0';
743 if (exponent > kExponentMax + kPrecision) {
744 if (accumulator)
745 return exponent_sign == kNegative ? Zero(kPositive)
746 : Infinity(sign);
747 return Zero(sign);
748 }
749 state = kStateEDigit;
750 break;
751 }
752
753 return Nan();
754
755 case kStateESign:
756 if (ch >= '0' && ch <= '9') {
757 exponent = ch - '0';
758 state = kStateEDigit;
759 break;
760 }
761
762 return Nan();
763
764 case kStateSign:
765 if (ch >= '1' && ch <= '9') {
766 accumulator = ch - '0';
767 number_of_digits = 1;
768 state = kStateDigit;
769 break;
770 }
771
772 HandleCharAndBreak('0', kStateZero);
773 HandleCharAndBreak('.', kStateDot);
774 return Nan();
775
776 case kStateStart:
777 if (ch >= '1' && ch <= '9') {
778 accumulator = ch - '0';
779 number_of_digits = 1;
780 state = kStateDigit;
781 break;
782 }
783
784 if (ch == '-') {
785 sign = kNegative;
786 state = kStateSign;
787 break;
788 }
789
790 if (ch == '+') {
791 sign = kPositive;
792 state = kStateSign;
793 break;
794 }
795
796 HandleCharAndBreak('0', kStateZero);
797 HandleCharAndBreak('.', kStateDot);
798 return Nan();
799
800 case kStateZero:
801 if (ch == '0')
802 break;
803
804 if (ch >= '1' && ch <= '9') {
805 accumulator = ch - '0';
806 number_of_digits = 1;
807 state = kStateDigit;
808 break;
809 }
810
811 HandleCharAndBreak('.', kStateDot);
812 HandleTwoCharsAndBreak('E', 'e', kStateE);
813 return Nan();
814
815 default:
816 NOTREACHED();
817 return Nan();
818 }
819 }
820
821 if (state == kStateZero)
822 return Zero(sign);
823
824 if (state == kStateDigit || state == kStateEDigit ||
825 state == kStateDotDigit) {
826 int result_exponent = exponent * (exponent_sign == kNegative ? -1 : 1) -
827 number_of_digits_after_dot + number_of_extra_digits;
828 if (result_exponent < kExponentMin)
829 return Zero(kPositive);
830
831 const int overflow = result_exponent - kExponentMax + 1;
832 if (overflow > 0) {
833 if (overflow + number_of_digits - number_of_digits_after_dot > kPrecision)
834 return Infinity(sign);
835 accumulator = ScaleUp(accumulator, overflow);
836 result_exponent -= overflow;
837 }
838
839 return Decimal(sign, result_exponent, accumulator);
840 }
841
842 return Nan();
843 }
844
Infinity(const Sign sign)845 Decimal Decimal::Infinity(const Sign sign) {
846 return Decimal(EncodedData(sign, EncodedData::kClassInfinity));
847 }
848
Nan()849 Decimal Decimal::Nan() {
850 return Decimal(EncodedData(kPositive, EncodedData::kClassNaN));
851 }
852
Remainder(const Decimal & rhs) const853 Decimal Decimal::Remainder(const Decimal& rhs) const {
854 const Decimal quotient = *this / rhs;
855 return quotient.IsSpecial()
856 ? quotient
857 : *this - (quotient.IsNegative() ? quotient.Ceil()
858 : quotient.Floor()) *
859 rhs;
860 }
861
Round() const862 Decimal Decimal::Round() const {
863 if (IsSpecial())
864 return *this;
865
866 if (Exponent() >= 0)
867 return *this;
868
869 uint64_t result = data_.Coefficient();
870 const int number_of_digits = CountDigits(result);
871 const int number_of_drop_digits = -Exponent();
872 if (number_of_digits < number_of_drop_digits)
873 return Zero(kPositive);
874
875 result = ScaleDown(result, number_of_drop_digits - 1);
876 if (result % 10 >= 5)
877 result += 10;
878 result /= 10;
879 return Decimal(GetSign(), 0, result);
880 }
881
ToDouble() const882 double Decimal::ToDouble() const {
883 if (IsFinite()) {
884 bool valid;
885 const double double_value = ToString().ToDouble(&valid);
886 return valid ? double_value : std::numeric_limits<double>::quiet_NaN();
887 }
888
889 if (IsInfinity())
890 return IsNegative() ? -std::numeric_limits<double>::infinity()
891 : std::numeric_limits<double>::infinity();
892
893 return std::numeric_limits<double>::quiet_NaN();
894 }
895
ToString() const896 String Decimal::ToString() const {
897 switch (data_.GetFormatClass()) {
898 case EncodedData::kClassInfinity:
899 return GetSign() ? "-Infinity" : "Infinity";
900
901 case EncodedData::kClassNaN:
902 return "NaN";
903
904 case EncodedData::kClassNormal:
905 case EncodedData::kClassZero:
906 break;
907
908 default:
909 NOTREACHED();
910 return "";
911 }
912
913 StringBuilder builder;
914 if (GetSign())
915 builder.Append('-');
916
917 int original_exponent = Exponent();
918 uint64_t coefficient = data_.Coefficient();
919
920 if (original_exponent < 0) {
921 const int kMaxDigits = DBL_DIG;
922 uint64_t last_digit = 0;
923 while (CountDigits(coefficient) > kMaxDigits) {
924 last_digit = coefficient % 10;
925 coefficient /= 10;
926 ++original_exponent;
927 }
928
929 if (last_digit >= 5)
930 ++coefficient;
931
932 while (original_exponent < 0 && coefficient && !(coefficient % 10)) {
933 coefficient /= 10;
934 ++original_exponent;
935 }
936 }
937
938 const String digits = String::Number(coefficient);
939 int coefficient_length = static_cast<int>(digits.length());
940 const int adjusted_exponent = original_exponent + coefficient_length - 1;
941 if (original_exponent <= 0 && adjusted_exponent >= -6) {
942 if (!original_exponent) {
943 builder.Append(digits);
944 return builder.ToString();
945 }
946
947 if (adjusted_exponent >= 0) {
948 for (int i = 0; i < coefficient_length; ++i) {
949 builder.Append(digits[i]);
950 if (i == adjusted_exponent)
951 builder.Append('.');
952 }
953 return builder.ToString();
954 }
955
956 builder.Append("0.");
957 for (int i = adjusted_exponent + 1; i < 0; ++i)
958 builder.Append('0');
959
960 builder.Append(digits);
961
962 } else {
963 builder.Append(digits[0]);
964 while (coefficient_length >= 2 && digits[coefficient_length - 1] == '0')
965 --coefficient_length;
966 if (coefficient_length >= 2) {
967 builder.Append('.');
968 for (int i = 1; i < coefficient_length; ++i)
969 builder.Append(digits[i]);
970 }
971
972 if (adjusted_exponent) {
973 builder.Append(adjusted_exponent < 0 ? "e" : "e+");
974 builder.AppendNumber(adjusted_exponent);
975 }
976 }
977 return builder.ToString();
978 }
979
Zero(Sign sign)980 Decimal Decimal::Zero(Sign sign) {
981 return Decimal(EncodedData(sign, EncodedData::kClassZero));
982 }
983
operator <<(std::ostream & ostream,const Decimal & decimal)984 std::ostream& operator<<(std::ostream& ostream, const Decimal& decimal) {
985 Decimal::EncodedData data = decimal.Value();
986 return ostream << "encode(" << String::Number(data.Coefficient()).Ascii()
987 << ", " << String::Number(data.Exponent()).Ascii() << ", "
988 << (data.GetSign() == Decimal::kNegative ? "Negative"
989 : "Positive")
990 << ")=" << decimal.ToString().Ascii();
991 }
992
993 } // namespace blink
994