mfbt/decimal/Decimal.cpp

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:2319a4a7fb2f
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 #include <algorithm>
35 #include <float.h>
36
37 using namespace moz_decimal_utils;
38
39 namespace WebCore {
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(0x16345785D89FFFF); // 999999999999999999 == 18 9's
48
49 // This class handles Decimal special values.
50 class SpecialValueHandler {
51 WTF_MAKE_NONCOPYABLE(SpecialValueHandler);
52 public:
53 enum HandleResult {
54 BothFinite,
55 BothInfinity,
56 EitherNaN,
57 LHSIsInfinity,
58 RHSIsInfinity,
59 };
60
61 SpecialValueHandler(const Decimal& lhs, const Decimal& rhs);
62 HandleResult handle();
63 Decimal value() const;
64
65 private:
66 enum Result {
67 ResultIsLHS,
68 ResultIsRHS,
69 ResultIsUnknown,
70 };
71
72 const Decimal& m_lhs;
73 const Decimal& m_rhs;
74 Result m_result;
75 };
76
77 SpecialValueHandler::SpecialValueHandler(const Decimal& lhs, const Decimal& rhs)
78 : m_lhs(lhs), m_rhs(rhs), m_result(ResultIsUnknown)
79 {
80 }
81
82 SpecialValueHandler::HandleResult SpecialValueHandler::handle()
83 {
84 if (m_lhs.isFinite() && m_rhs.isFinite())
85 return BothFinite;
86
87 const Decimal::EncodedData::FormatClass lhsClass = m_lhs.value().formatClass();
88 const Decimal::EncodedData::FormatClass rhsClass = m_rhs.value().formatClass();
89 if (lhsClass == Decimal::EncodedData::ClassNaN) {
90 m_result = ResultIsLHS;
91 return EitherNaN;
92 }
93
94 if (rhsClass == Decimal::EncodedData::ClassNaN) {
95 m_result = ResultIsRHS;
96 return EitherNaN;
97 }
98
99 if (lhsClass == Decimal::EncodedData::ClassInfinity)
100 return rhsClass == Decimal::EncodedData::ClassInfinity ? BothInfinity : LHSIsInfinity;
101
102 if (rhsClass == Decimal::EncodedData::ClassInfinity)
103 return RHSIsInfinity;
104
105 ASSERT_NOT_REACHED();
106 return BothFinite;
107 }
108
109 Decimal SpecialValueHandler::value() const
110 {
111 switch (m_result) {
112 case ResultIsLHS:
113 return m_lhs;
114 case ResultIsRHS:
115 return m_rhs;
116 case ResultIsUnknown:
117 default:
118 ASSERT_NOT_REACHED();
119 return m_lhs;
120 }
121 }
122
123 // This class is used for 128 bit unsigned integer arithmetic.
124 class UInt128 {
125 public:
126 UInt128(uint64_t low, uint64_t high)
127 : m_high(high), m_low(low)
128 {
129 }
130
131 UInt128& operator/=(uint32_t);
132
133 uint64_t high() const { return m_high; }
134 uint64_t low() const { return m_low; }
135
136 static UInt128 multiply(uint64_t u, uint64_t v) { return UInt128(u * v, multiplyHigh(u, v)); }
137
138 private:
139 static uint32_t highUInt32(uint64_t x) { return static_cast<uint32_t>(x >> 32); }
140 static uint32_t lowUInt32(uint64_t x) { return static_cast<uint32_t>(x & ((static_cast<uint64_t>(1) << 32) - 1)); }
141 bool isZero() const { return !m_low && !m_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
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.
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
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
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
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
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
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
269 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
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
282 Decimal::Decimal(Sign sign, int exponent, uint64_t coefficient)
283 : m_data(sign, coefficient ? exponent : 0, coefficient)
284 {
285 }
286
287 Decimal::Decimal(const EncodedData& data)
288 : m_data(data)
289 {
290 }
291
292 Decimal::Decimal(const Decimal& other)
293 : m_data(other.m_data)
294 {
295 }
296
297 Decimal& Decimal::operator=(const Decimal& other)
298 {
299 m_data = other.m_data;
300 return *this;
301 }
302
303 Decimal& Decimal::operator+=(const Decimal& other)
304 {
305 m_data = (*this + other).m_data;
306 return *this;
307 }
308
309 Decimal& Decimal::operator-=(const Decimal& other)
310 {
311 m_data = (*this - other).m_data;
312 return *this;
313 }
314
315 Decimal& Decimal::operator*=(const Decimal& other)
316 {
317 m_data = (*this * other).m_data;
318 return *this;
319 }
320
321 Decimal& Decimal::operator/=(const Decimal& other)
322 {
323 m_data = (*this / other).m_data;
324 return *this;
325 }
326
327 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
337 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
375 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
413 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
451 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 while (result < MaxCoefficient / 100) {
491 while (remainder < divisor) {
492 remainder *= 10;
493 result *= 10;
494 --resultExponent;
495 }
496 result += remainder / divisor;
497 remainder %= divisor;
498 if (!remainder)
499 break;
500 }
501
502 if (remainder > divisor / 2)
503 ++result;
504
505 return Decimal(resultSign, resultExponent, result);
506 }
507
508 bool Decimal::operator==(const Decimal& rhs) const
509 {
510 if (isNaN() || rhs.isNaN())
511 return false;
512 return m_data == rhs.m_data || compareTo(rhs).isZero();
513 }
514
515 bool Decimal::operator!=(const Decimal& rhs) const
516 {
517 if (isNaN() || rhs.isNaN())
518 return true;
519 if (m_data == rhs.m_data)
520 return false;
521 const Decimal result = compareTo(rhs);
522 if (result.isNaN())
523 return false;
524 return !result.isZero();
525 }
526
527 bool Decimal::operator<(const Decimal& rhs) const
528 {
529 const Decimal result = compareTo(rhs);
530 if (result.isNaN())
531 return false;
532 return !result.isZero() && result.isNegative();
533 }
534
535 bool Decimal::operator<=(const Decimal& rhs) const
536 {
537 if (isNaN() || rhs.isNaN())
538 return false;
539 if (m_data == rhs.m_data)
540 return true;
541 const Decimal result = compareTo(rhs);
542 if (result.isNaN())
543 return false;
544 return result.isZero() || result.isNegative();
545 }
546
547 bool Decimal::operator>(const Decimal& rhs) const
548 {
549 const Decimal result = compareTo(rhs);
550 if (result.isNaN())
551 return false;
552 return !result.isZero() && result.isPositive();
553 }
554
555 bool Decimal::operator>=(const Decimal& rhs) const
556 {
557 if (isNaN() || rhs.isNaN())
558 return false;
559 if (m_data == rhs.m_data)
560 return true;
561 const Decimal result = compareTo(rhs);
562 if (result.isNaN())
563 return false;
564 return result.isZero() || !result.isNegative();
565 }
566
567 Decimal Decimal::abs() const
568 {
569 Decimal result(*this);
570 result.m_data.setSign(Positive);
571 return result;
572 }
573
574 Decimal::AlignedOperands Decimal::alignOperands(const Decimal& lhs, const Decimal& rhs)
575 {
576 ASSERT(lhs.isFinite());
577 ASSERT(rhs.isFinite());
578
579 const int lhsExponent = lhs.exponent();
580 const int rhsExponent = rhs.exponent();
581 int exponent = std::min(lhsExponent, rhsExponent);
582 uint64_t lhsCoefficient = lhs.m_data.coefficient();
583 uint64_t rhsCoefficient = rhs.m_data.coefficient();
584
585 if (lhsExponent > rhsExponent) {
586 const int numberOfLHSDigits = countDigits(lhsCoefficient);
587 if (numberOfLHSDigits) {
588 const int lhsShiftAmount = lhsExponent - rhsExponent;
589 const int overflow = numberOfLHSDigits + lhsShiftAmount - Precision;
590 if (overflow <= 0)
591 lhsCoefficient = scaleUp(lhsCoefficient, lhsShiftAmount);
592 else {
593 lhsCoefficient = scaleUp(lhsCoefficient, lhsShiftAmount - overflow);
594 rhsCoefficient = scaleDown(rhsCoefficient, overflow);
595 exponent += overflow;
596 }
597 }
598
599 } else if (lhsExponent < rhsExponent) {
600 const int numberOfRHSDigits = countDigits(rhsCoefficient);
601 if (numberOfRHSDigits) {
602 const int rhsShiftAmount = rhsExponent - lhsExponent;
603 const int overflow = numberOfRHSDigits + rhsShiftAmount - Precision;
604 if (overflow <= 0)
605 rhsCoefficient = scaleUp(rhsCoefficient, rhsShiftAmount);
606 else {
607 rhsCoefficient = scaleUp(rhsCoefficient, rhsShiftAmount - overflow);
608 lhsCoefficient = scaleDown(lhsCoefficient, overflow);
609 exponent += overflow;
610 }
611 }
612 }
613
614 AlignedOperands alignedOperands;
615 alignedOperands.exponent = exponent;
616 alignedOperands.lhsCoefficient = lhsCoefficient;
617 alignedOperands.rhsCoefficient = rhsCoefficient;
618 return alignedOperands;
619 }
620
621 // Round toward positive infinity.
622 // Note: Mac ports defines ceil(x) as wtf_ceil(x), so we can't use name "ceil" here.
623 Decimal Decimal::ceiling() const
624 {
625 if (isSpecial())
626 return *this;
627
628 if (exponent() >= 0)
629 return *this;
630
631 uint64_t coefficient = m_data.coefficient();
632 const int numberOfDigits = countDigits(coefficient);
633 const int numberOfDropDigits = -exponent();
634 if (numberOfDigits < numberOfDropDigits)
635 return isPositive() ? Decimal(1) : zero(Positive);
636
637 uint64_t result = scaleDown(coefficient, numberOfDropDigits);
638 uint64_t droppedDigits = coefficient - scaleUp(result, numberOfDropDigits);
639 if (droppedDigits && isPositive())
640 result += 1;
641 return Decimal(sign(), 0, result);
642 }
643
644 Decimal Decimal::compareTo(const Decimal& rhs) const
645 {
646 const Decimal result(*this - rhs);
647 switch (result.m_data.formatClass()) {
648 case EncodedData::ClassInfinity:
649 return result.isNegative() ? Decimal(-1) : Decimal(1);
650
651 case EncodedData::ClassNaN:
652 case EncodedData::ClassNormal:
653 return result;
654
655 case EncodedData::ClassZero:
656 return zero(Positive);
657
658 default:
659 ASSERT_NOT_REACHED();
660 return nan();
661 }
662 }
663
664 // Round toward negative infinity.
665 Decimal Decimal::floor() const
666 {
667 if (isSpecial())
668 return *this;
669
670 if (exponent() >= 0)
671 return *this;
672
673 uint64_t coefficient = m_data.coefficient();
674 const int numberOfDigits = countDigits(coefficient);
675 const int numberOfDropDigits = -exponent();
676 if (numberOfDigits < numberOfDropDigits)
677 return isPositive() ? zero(Positive) : Decimal(-1);
678
679 uint64_t result = scaleDown(coefficient, numberOfDropDigits);
680 uint64_t droppedDigits = coefficient - scaleUp(result, numberOfDropDigits);
681 if (droppedDigits && isNegative()) {
682 result += 1;
683 }
684 return Decimal(sign(), 0, result);
685 }
686
687 Decimal Decimal::fromDouble(double doubleValue)
688 {
689 if (std::isfinite(doubleValue))
690 return fromString(mozToString(doubleValue));
691
692 if (std::isinf(doubleValue))
693 return infinity(doubleValue < 0 ? Negative : Positive);
694
695 return nan();
696 }
697
698 Decimal Decimal::fromString(const String& str)
699 {
700 int exponent = 0;
701 Sign exponentSign = Positive;
702 int numberOfDigits = 0;
703 int numberOfDigitsAfterDot = 0;
704 int numberOfExtraDigits = 0;
705 Sign sign = Positive;
706
707 enum {
708 StateDigit,
709 StateDot,
710 StateDotDigit,
711 StateE,
712 StateEDigit,
713 StateESign,
714 StateSign,
715 StateStart,
716 StateZero,
717 } state = StateStart;
718
719 #define HandleCharAndBreak(expected, nextState) \
720 if (ch == expected) { \
721 state = nextState; \
722 break; \
723 }
724
725 #define HandleTwoCharsAndBreak(expected1, expected2, nextState) \
726 if (ch == expected1 || ch == expected2) { \
727 state = nextState; \
728 break; \
729 }
730
731 uint64_t accumulator = 0;
732 for (unsigned index = 0; index < str.length(); ++index) {
733 const int ch = str[index];
734 switch (state) {
735 case StateDigit:
736 if (ch >= '0' && ch <= '9') {
737 if (numberOfDigits < Precision) {
738 ++numberOfDigits;
739 accumulator *= 10;
740 accumulator += ch - '0';
741 } else
742 ++numberOfExtraDigits;
743 break;
744 }
745
746 HandleCharAndBreak('.', StateDot);
747 HandleTwoCharsAndBreak('E', 'e', StateE);
748 return nan();
749
750 case StateDot:
751 if (ch >= '0' && ch <= '9') {
752 if (numberOfDigits < Precision) {
753 ++numberOfDigits;
754 ++numberOfDigitsAfterDot;
755 accumulator *= 10;
756 accumulator += ch - '0';
757 }
758 state = StateDotDigit;
759 break;
760 }
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
899 Decimal Decimal::infinity(const Sign sign)
900 {
901 return Decimal(EncodedData(sign, EncodedData::ClassInfinity));
902 }
903
904 Decimal Decimal::nan()
905 {
906 return Decimal(EncodedData(Positive, EncodedData::ClassNaN));
907 }
908
909 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
915 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 // We're implementing round-half-away-from-zero, so we only need the one
930 // (the most significant) fractional digit:
931 result = scaleDown(result, numberOfDropDigits - 1);
932 if (result % 10 >= 5)
933 result += 10;
934 result /= 10;
935 return Decimal(sign(), 0, result);
936 }
937
938 double Decimal::toDouble() const
939 {
940 if (isFinite()) {
941 bool valid;
942 const double doubleValue = mozToDouble(toString(), &valid);
943 return valid ? doubleValue : std::numeric_limits<double>::quiet_NaN();
944 }
945
946 if (isInfinity())
947 return isNegative() ? -std::numeric_limits<double>::infinity() : std::numeric_limits<double>::infinity();
948
949 return std::numeric_limits<double>::quiet_NaN();
950 }
951
952 String Decimal::toString() const
953 {
954 switch (m_data.formatClass()) {
955 case EncodedData::ClassInfinity:
956 return sign() ? "-Infinity" : "Infinity";
957
958 case EncodedData::ClassNaN:
959 return "NaN";
960
961 case EncodedData::ClassNormal:
962 case EncodedData::ClassZero:
963 break;
964
965 default:
966 ASSERT_NOT_REACHED();
967 return "";
968 }
969
970 StringBuilder builder;
971 if (sign())
972 builder.append('-');
973
974 int originalExponent = exponent();
975 uint64_t coefficient = m_data.coefficient();
976
977 if (originalExponent < 0) {
978 const int maxDigits = DBL_DIG;
979 uint64_t lastDigit = 0;
980 while (countDigits(coefficient) > maxDigits) {
981 lastDigit = coefficient % 10;
982 coefficient /= 10;
983 ++originalExponent;
984 }
985
986 if (lastDigit >= 5)
987 ++coefficient;
988
989 while (originalExponent < 0 && coefficient && !(coefficient % 10)) {
990 coefficient /= 10;
991 ++originalExponent;
992 }
993 }
994
995 const String digits = mozToString(coefficient);
996 int coefficientLength = static_cast<int>(digits.length());
997 const int adjustedExponent = originalExponent + coefficientLength - 1;
998 if (originalExponent <= 0 && adjustedExponent >= -6) {
999 if (!originalExponent) {
1000 builder.append(digits);
1001 return builder.toString();
1002 }
1003
1004 if (adjustedExponent >= 0) {
1005 for (int i = 0; i < coefficientLength; ++i) {
1006 builder.append(digits[i]);
1007 if (i == adjustedExponent)
1008 builder.append('.');
1009 }
1010 return builder.toString();
1011 }
1012
1013 builder.appendLiteral("0.");
1014 for (int i = adjustedExponent + 1; i < 0; ++i)
1015 builder.append('0');
1016
1017 builder.append(digits);
1018
1019 } else {
1020 builder.append(digits[0]);
1021 while (coefficientLength >= 2 && digits[coefficientLength - 1] == '0')
1022 --coefficientLength;
1023 if (coefficientLength >= 2) {
1024 builder.append('.');
1025 for (int i = 1; i < coefficientLength; ++i)
1026 builder.append(digits[i]);
1027 }
1028
1029 if (adjustedExponent) {
1030 builder.append(adjustedExponent < 0 ? "e" : "e+");
1031 builder.appendNumber(adjustedExponent);
1032 }
1033 }
1034 return builder.toString();
1035 }
1036
1037 bool Decimal::toString(char* strBuf, size_t bufLength) const
1038 {
1039 ASSERT(bufLength > 0);
1040 String str = toString();
1041 size_t length = str.copy(strBuf, bufLength);
1042 if (length < bufLength) {
1043 strBuf[length] = '\0';
1044 return true;
1045 }
1046 strBuf[bufLength - 1] = '\0';
1047 return false;
1048 }
1049
1050 Decimal Decimal::zero(Sign sign)
1051 {
1052 return Decimal(EncodedData(sign, EncodedData::ClassZero));
1053 }
1054
1055 } // namespace WebCore
1056

mercurial