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