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