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