• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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