1// © 2017 and later: Unicode, Inc. and others.
2// License & terms of use: http://www.unicode.org/copyright.html
3
4#include "unicode/utypes.h"
5
6#if !UCONFIG_NO_FORMATTING
7
8#include <cstdlib>
9#include <cmath>
10#include <limits>
11#include <stdlib.h>
12
13#include "unicode/plurrule.h"
14#include "cmemory.h"
15#include "number_decnum.h"
16#include "putilimp.h"
17#include "number_decimalquantity.h"
18#include "number_roundingutils.h"
19#include "double-conversion.h"
20#include "charstr.h"
21#include "number_utils.h"
22#include "uassert.h"
23
24using namespace icu;
25using namespace icu::number;
26using namespace icu::number::impl;
27
28using icu::double_conversion::DoubleToStringConverter;
29using icu::double_conversion::StringToDoubleConverter;
30
31namespace {
32
33int8_t NEGATIVE_FLAG = 1;
34int8_t INFINITY_FLAG = 2;
35int8_t NAN_FLAG = 4;
36
37/** Helper function for safe subtraction (no overflow). */
38inline int32_t safeSubtract(int32_t a, int32_t b) {
39 // Note: In C++, signed integer subtraction is undefined behavior.
40 int32_t diff = static_cast<int32_t>(static_cast<uint32_t>(a) - static_cast<uint32_t>(b));
41 if (b < 0 && diff < a) { return INT32_MAX; }
42 if (b > 0 && diff > a) { return INT32_MIN; }
43 return diff;
44}
45
46static double DOUBLE_MULTIPLIERS[] = {
47 1e0,
48 1e1,
49 1e2,
50 1e3,
51 1e4,
52 1e5,
53 1e6,
54 1e7,
55 1e8,
56 1e9,
57 1e10,
58 1e11,
59 1e12,
60 1e13,
61 1e14,
62 1e15,
63 1e16,
64 1e17,
65 1e18,
66 1e19,
67 1e20,
68 1e21};
69
70} // namespace
71
72icu::IFixedDecimal::~IFixedDecimal() = default;
73
74DecimalQuantity::DecimalQuantity() {
75 setBcdToZero();
76 flags = 0;
77}
78
79DecimalQuantity::~DecimalQuantity() {
80 if (usingBytes) {
81 uprv_free(fBCD.bcdBytes.ptr);
82 fBCD.bcdBytes.ptr = nullptr;
83 usingBytes = false;
84 }
85}
86
87DecimalQuantity::DecimalQuantity(const DecimalQuantity &other) {
88 *this = other;
89}
90
91DecimalQuantity::DecimalQuantity(DecimalQuantity&& src) U_NOEXCEPT {
92 *this = std::move(src);
93}
94
95DecimalQuantity &DecimalQuantity::operator=(const DecimalQuantity &other) {
96 if (this == &other) {
97 return *this;
98 }
99 copyBcdFrom(other);
100 copyFieldsFrom(other);
101 return *this;
102}
103
104DecimalQuantity& DecimalQuantity::operator=(DecimalQuantity&& src) U_NOEXCEPT {
105 if (this == &src) {
106 return *this;
107 }
108 moveBcdFrom(src);
109 copyFieldsFrom(src);
110 return *this;
111}
112
113void DecimalQuantity::copyFieldsFrom(const DecimalQuantity& other) {
114 bogus = other.bogus;
115 lReqPos = other.lReqPos;
116 rReqPos = other.rReqPos;
117 scale = other.scale;
118 precision = other.precision;
119 flags = other.flags;
120 origDouble = other.origDouble;
121 origDelta = other.origDelta;
122 isApproximate = other.isApproximate;
123}
124
125void DecimalQuantity::clear() {
126 lReqPos = 0;
127 rReqPos = 0;
128 flags = 0;
129 setBcdToZero(); // sets scale, precision, hasDouble, origDouble, origDelta, and BCD data
130}
131
132void DecimalQuantity::setMinInteger(int32_t minInt) {
133 // Validation should happen outside of DecimalQuantity, e.g., in the Precision class.
134 U_ASSERT(minInt >= 0);
135
136 // Special behavior: do not set minInt to be less than what is already set.
137 // This is so significant digits rounding can set the integer length.
138 if (minInt < lReqPos) {
139 minInt = lReqPos;
140 }
141
142 // Save values into internal state
143 lReqPos = minInt;
144}
145
146void DecimalQuantity::setMinFraction(int32_t minFrac) {
147 // Validation should happen outside of DecimalQuantity, e.g., in the Precision class.
148 U_ASSERT(minFrac >= 0);
149
150 // Save values into internal state
151 // Negation is safe for minFrac/maxFrac because -Integer.MAX_VALUE > Integer.MIN_VALUE
152 rReqPos = -minFrac;
153}
154
155void DecimalQuantity::applyMaxInteger(int32_t maxInt) {
156 // Validation should happen outside of DecimalQuantity, e.g., in the Precision class.
157 U_ASSERT(maxInt >= 0);
158
159 if (precision == 0) {
160 return;
161 }
162
163 if (maxInt <= scale) {
164 setBcdToZero();
165 return;
166 }
167
168 int32_t magnitude = getMagnitude();
169 if (maxInt <= magnitude) {
170 popFromLeft(magnitude - maxInt + 1);
171 compact();
172 }
173}
174
175uint64_t DecimalQuantity::getPositionFingerprint() const {
176 uint64_t fingerprint = 0;
177 fingerprint ^= (lReqPos << 16);
178 fingerprint ^= (static_cast<uint64_t>(rReqPos) << 32);
179 return fingerprint;
180}
181
182void DecimalQuantity::roundToIncrement(double roundingIncrement, RoundingMode roundingMode,
183 UErrorCode& status) {
184 // Do not call this method with an increment having only a 1 or a 5 digit!
185 // Use a more efficient call to either roundToMagnitude() or roundToNickel().
186 // Check a few popular rounding increments; a more thorough check is in Java.
187 U_ASSERT(roundingIncrement != 0.01);
188 U_ASSERT(roundingIncrement != 0.05);
189 U_ASSERT(roundingIncrement != 0.1);
190 U_ASSERT(roundingIncrement != 0.5);
191 U_ASSERT(roundingIncrement != 1);
192 U_ASSERT(roundingIncrement != 5);
193
194 DecNum incrementDN;
195 incrementDN.setTo(roundingIncrement, status);
196 if (U_FAILURE(status)) { return; }
197
198 // Divide this DecimalQuantity by the increment, round, then multiply back.
199 divideBy(incrementDN, status);
200 if (U_FAILURE(status)) { return; }
201 roundToMagnitude(0, roundingMode, status);
202 if (U_FAILURE(status)) { return; }
203 multiplyBy(incrementDN, status);
204 if (U_FAILURE(status)) { return; }
205}
206
207void DecimalQuantity::multiplyBy(const DecNum& multiplicand, UErrorCode& status) {
208 if (isZeroish()) {
209 return;
210 }
211 // Convert to DecNum, multiply, and convert back.
212 DecNum decnum;
213 toDecNum(decnum, status);
214 if (U_FAILURE(status)) { return; }
215 decnum.multiplyBy(multiplicand, status);
216 if (U_FAILURE(status)) { return; }
217 setToDecNum(decnum, status);
218}
219
220void DecimalQuantity::divideBy(const DecNum& divisor, UErrorCode& status) {
221 if (isZeroish()) {
222 return;
223 }
224 // Convert to DecNum, multiply, and convert back.
225 DecNum decnum;
226 toDecNum(decnum, status);
227 if (U_FAILURE(status)) { return; }
228 decnum.divideBy(divisor, status);
229 if (U_FAILURE(status)) { return; }
230 setToDecNum(decnum, status);
231}
232
233void DecimalQuantity::negate() {
234 flags ^= NEGATIVE_FLAG;
235}
236
237int32_t DecimalQuantity::getMagnitude() const {
238 U_ASSERT(precision != 0);
239 return scale + precision - 1;
240}
241
242bool DecimalQuantity::adjustMagnitude(int32_t delta) {
243 if (precision != 0) {
244 // i.e., scale += delta; origDelta += delta
245 bool overflow = uprv_add32_overflow(scale, delta, &scale);
246 overflow = uprv_add32_overflow(origDelta, delta, &origDelta) || overflow;
247 // Make sure that precision + scale won't overflow, either
248 int32_t dummy;
249 overflow = overflow || uprv_add32_overflow(scale, precision, &dummy);
250 return overflow;
251 }
252 return false;
253}
254
255double DecimalQuantity::getPluralOperand(PluralOperand operand) const {
256 // If this assertion fails, you need to call roundToInfinity() or some other rounding method.
257 // See the comment at the top of this file explaining the "isApproximate" field.
258 U_ASSERT(!isApproximate);
259
260 switch (operand) {
261 case PLURAL_OPERAND_I:
262 // Invert the negative sign if necessary
263 return static_cast<double>(isNegative() ? -toLong(true) : toLong(true));
264 case PLURAL_OPERAND_F:
265 return static_cast<double>(toFractionLong(true));
266 case PLURAL_OPERAND_T:
267 return static_cast<double>(toFractionLong(false));
268 case PLURAL_OPERAND_V:
269 return fractionCount();
270 case PLURAL_OPERAND_W:
271 return fractionCountWithoutTrailingZeros();
272 default:
273 return std::abs(toDouble());
274 }
275}
276
277bool DecimalQuantity::hasIntegerValue() const {
278 return scale >= 0;
279}
280
281int32_t DecimalQuantity::getUpperDisplayMagnitude() const {
282 // If this assertion fails, you need to call roundToInfinity() or some other rounding method.
283 // See the comment in the header file explaining the "isApproximate" field.
284 U_ASSERT(!isApproximate);
285
286 int32_t magnitude = scale + precision;
287 int32_t result = (lReqPos > magnitude) ? lReqPos : magnitude;
288 return result - 1;
289}
290
291int32_t DecimalQuantity::getLowerDisplayMagnitude() const {
292 // If this assertion fails, you need to call roundToInfinity() or some other rounding method.
293 // See the comment in the header file explaining the "isApproximate" field.
294 U_ASSERT(!isApproximate);
295
296 int32_t magnitude = scale;
297 int32_t result = (rReqPos < magnitude) ? rReqPos : magnitude;
298 return result;
299}
300
301int8_t DecimalQuantity::getDigit(int32_t magnitude) const {
302 // If this assertion fails, you need to call roundToInfinity() or some other rounding method.
303 // See the comment at the top of this file explaining the "isApproximate" field.
304 U_ASSERT(!isApproximate);
305
306 return getDigitPos(magnitude - scale);
307}
308
309int32_t DecimalQuantity::fractionCount() const {
310 return -getLowerDisplayMagnitude();
311}
312
313int32_t DecimalQuantity::fractionCountWithoutTrailingZeros() const {
314 return -scale > 0 ? -scale : 0; // max(-scale, 0)
315}
316
317bool DecimalQuantity::isNegative() const {
318 return (flags & NEGATIVE_FLAG) != 0;
319}
320
321Signum DecimalQuantity::signum() const {
322 if (isNegative()) {
323 return SIGNUM_NEG;
324 } else if (isZeroish() && !isInfinite()) {
325 return SIGNUM_ZERO;
326 } else {
327 return SIGNUM_POS;
328 }
329}
330
331bool DecimalQuantity::isInfinite() const {
332 return (flags & INFINITY_FLAG) != 0;
333}
334
335bool DecimalQuantity::isNaN() const {
336 return (flags & NAN_FLAG) != 0;
337}
338
339bool DecimalQuantity::isZeroish() const {
340 return precision == 0;
341}
342
343DecimalQuantity &DecimalQuantity::setToInt(int32_t n) {
344 setBcdToZero();
345 flags = 0;
346 if (n == INT32_MIN) {
347 flags |= NEGATIVE_FLAG;
348 // leave as INT32_MIN; handled below in _setToInt()
349 } else if (n < 0) {
350 flags |= NEGATIVE_FLAG;
351 n = -n;
352 }
353 if (n != 0) {
354 _setToInt(n);
355 compact();
356 }
357 return *this;
358}
359
360void DecimalQuantity::_setToInt(int32_t n) {
361 if (n == INT32_MIN) {
362 readLongToBcd(-static_cast<int64_t>(n));
363 } else {
364 readIntToBcd(n);
365 }
366}
367
368DecimalQuantity &DecimalQuantity::setToLong(int64_t n) {
369 setBcdToZero();
370 flags = 0;
371 if (n < 0 && n > INT64_MIN) {
372 flags |= NEGATIVE_FLAG;
373 n = -n;
374 }
375 if (n != 0) {
376 _setToLong(n);
377 compact();
378 }
379 return *this;
380}
381
382void DecimalQuantity::_setToLong(int64_t n) {
383 if (n == INT64_MIN) {
384 DecNum decnum;
385 UErrorCode localStatus = U_ZERO_ERROR;
386 decnum.setTo("9.223372036854775808E+18", localStatus);
387 if (U_FAILURE(localStatus)) { return; } // unexpected
388 flags |= NEGATIVE_FLAG;
389 readDecNumberToBcd(decnum);
390 } else if (n <= INT32_MAX) {
391 readIntToBcd(static_cast<int32_t>(n));
392 } else {
393 readLongToBcd(n);
394 }
395}
396
397DecimalQuantity &DecimalQuantity::setToDouble(double n) {
398 setBcdToZero();
399 flags = 0;
400 // signbit() from <math.h> handles +0.0 vs -0.0
401 if (std::signbit(n)) {
402 flags |= NEGATIVE_FLAG;
403 n = -n;
404 }
405 if (std::isnan(n) != 0) {
406 flags |= NAN_FLAG;
407 } else if (std::isfinite(n) == 0) {
408 flags |= INFINITY_FLAG;
409 } else if (n != 0) {
410 _setToDoubleFast(n);
411 compact();
412 }
413 return *this;
414}
415
416void DecimalQuantity::_setToDoubleFast(double n) {
417 isApproximate = true;
418 origDouble = n;
419 origDelta = 0;
420
421 // Make sure the double is an IEEE 754 double. If not, fall back to the slow path right now.
422 // TODO: Make a fast path for other types of doubles.
423 if (!std::numeric_limits<double>::is_iec559) {
424 convertToAccurateDouble();
425 // Turn off the approximate double flag, since the value is now exact.
426 isApproximate = false;
427 origDouble = 0.0;
428 return;
429 }
430
431 // To get the bits from the double, use memcpy, which takes care of endianness.
432 uint64_t ieeeBits;
433 uprv_memcpy(&ieeeBits, &n, sizeof(n));
434 int32_t exponent = static_cast<int32_t>((ieeeBits & 0x7ff0000000000000L) >> 52) - 0x3ff;
435
436 // Not all integers can be represented exactly for exponent > 52
437 if (exponent <= 52 && static_cast<int64_t>(n) == n) {
438 _setToLong(static_cast<int64_t>(n));
439 return;
440 }
441
442 // 3.3219... is log2(10)
443 auto fracLength = static_cast<int32_t> ((52 - exponent) / 3.32192809489);
444 if (fracLength >= 0) {
445 int32_t i = fracLength;
446 // 1e22 is the largest exact double.
447 for (; i >= 22; i -= 22) n *= 1e22;
448 n *= DOUBLE_MULTIPLIERS[i];
449 } else {
450 int32_t i = fracLength;
451 // 1e22 is the largest exact double.
452 for (; i <= -22; i += 22) n /= 1e22;
453 n /= DOUBLE_MULTIPLIERS[-i];
454 }
455 auto result = static_cast<int64_t>(std::round(n));
456 if (result != 0) {
457 _setToLong(result);
458 scale -= fracLength;
459 }
460}
461
462void DecimalQuantity::convertToAccurateDouble() {
463 U_ASSERT(origDouble != 0);
464 int32_t delta = origDelta;
465
466 // Call the slow oracle function (Double.toString in Java, DoubleToAscii in C++).
467 char buffer[DoubleToStringConverter::kBase10MaximalLength + 1];
468 bool sign; // unused; always positive
469 int32_t length;
470 int32_t point;
471 DoubleToStringConverter::DoubleToAscii(
472 origDouble,
473 DoubleToStringConverter::DtoaMode::SHORTEST,
474 0,
475 buffer,
476 sizeof(buffer),
477 &sign,
478 &length,
479 &point
480 );
481
482 setBcdToZero();
483 readDoubleConversionToBcd(buffer, length, point);
484 scale += delta;
485 explicitExactDouble = true;
486}
487
488DecimalQuantity &DecimalQuantity::setToDecNumber(StringPiece n, UErrorCode& status) {
489 setBcdToZero();
490 flags = 0;
491
492 // Compute the decNumber representation
493 DecNum decnum;
494 decnum.setTo(n, status);
495
496 _setToDecNum(decnum, status);
497 return *this;
498}
499
500DecimalQuantity& DecimalQuantity::setToDecNum(const DecNum& decnum, UErrorCode& status) {
501 setBcdToZero();
502 flags = 0;
503
504 _setToDecNum(decnum, status);
505 return *this;
506}
507
508void DecimalQuantity::_setToDecNum(const DecNum& decnum, UErrorCode& status) {
509 if (U_FAILURE(status)) { return; }
510 if (decnum.isNegative()) {
511 flags |= NEGATIVE_FLAG;
512 }
513 if (!decnum.isZero()) {
514 readDecNumberToBcd(decnum);
515 compact();
516 }
517}
518
519int64_t DecimalQuantity::toLong(bool truncateIfOverflow) const {
520 // NOTE: Call sites should be guarded by fitsInLong(), like this:
521 // if (dq.fitsInLong()) { /* use dq.toLong() */ } else { /* use some fallback */ }
522 // Fallback behavior upon truncateIfOverflow is to truncate at 17 digits.
523 uint64_t result = 0L;
524 int32_t upperMagnitude = scale + precision - 1;
525 if (truncateIfOverflow) {
526 upperMagnitude = std::min(upperMagnitude, 17);
527 }
528 for (int32_t magnitude = upperMagnitude; magnitude >= 0; magnitude--) {
529 result = result * 10 + getDigitPos(magnitude - scale);
530 }
531 if (isNegative()) {
532 return static_cast<int64_t>(0LL - result); // i.e., -result
533 }
534 return static_cast<int64_t>(result);
535}
536
537uint64_t DecimalQuantity::toFractionLong(bool includeTrailingZeros) const {
538 uint64_t result = 0L;
539 int32_t magnitude = -1;
540 int32_t lowerMagnitude = scale;
541 if (includeTrailingZeros) {
542 lowerMagnitude = std::min(lowerMagnitude, rReqPos);
543 }
544 for (; magnitude >= lowerMagnitude && result <= 1e18L; magnitude--) {
545 result = result * 10 + getDigitPos(magnitude - scale);
546 }
547 // Remove trailing zeros; this can happen during integer overflow cases.
548 if (!includeTrailingZeros) {
549 while (result > 0 && (result % 10) == 0) {
550 result /= 10;
551 }
552 }
553 return result;
554}
555
556bool DecimalQuantity::fitsInLong(bool ignoreFraction) const {
557 if (isInfinite() || isNaN()) {
558 return false;
559 }
560 if (isZeroish()) {
561 return true;
562 }
563 if (scale < 0 && !ignoreFraction) {
564 return false;
565 }
566 int magnitude = getMagnitude();
567 if (magnitude < 18) {
568 return true;
569 }
570 if (magnitude > 18) {
571 return false;
572 }
573 // Hard case: the magnitude is 10^18.
574 // The largest int64 is: 9,223,372,036,854,775,807
575 for (int p = 0; p < precision; p++) {
576 int8_t digit = getDigit(18 - p);
577 static int8_t INT64_BCD[] = { 9, 2, 2, 3, 3, 7, 2, 0, 3, 6, 8, 5, 4, 7, 7, 5, 8, 0, 8 };
578 if (digit < INT64_BCD[p]) {
579 return true;
580 } else if (digit > INT64_BCD[p]) {
581 return false;
582 }
583 }
584 // Exactly equal to max long plus one.
585 return isNegative();
586}
587
588double DecimalQuantity::toDouble() const {
589 // If this assertion fails, you need to call roundToInfinity() or some other rounding method.
590 // See the comment in the header file explaining the "isApproximate" field.
591 U_ASSERT(!isApproximate);
592
593 if (isNaN()) {
594 return NAN;
595 } else if (isInfinite()) {
596 return isNegative() ? -INFINITY : INFINITY;
597 }
598
599 // We are processing well-formed input, so we don't need any special options to StringToDoubleConverter.
600 StringToDoubleConverter converter(0, 0, 0, "", "");
601 UnicodeString numberString = this->toScientificString();
602 int32_t count;
603 return converter.StringToDouble(
604 reinterpret_cast<const uint16_t*>(numberString.getBuffer()),
605 numberString.length(),
606 &count);
607}
608
609void DecimalQuantity::toDecNum(DecNum& output, UErrorCode& status) const {
610 // Special handling for zero
611 if (precision == 0) {
612 output.setTo("0", status);
613 }
614
615 // Use the BCD constructor. We need to do a little bit of work to convert, though.
616 // The decNumber constructor expects most-significant first, but we store least-significant first.
617 MaybeStackArray<uint8_t, 20> ubcd(precision);
618 for (int32_t m = 0; m < precision; m++) {
619 ubcd[precision - m - 1] = static_cast<uint8_t>(getDigitPos(m));
620 }
621 output.setTo(ubcd.getAlias(), precision, scale, isNegative(), status);
622}
623
624void DecimalQuantity::truncate() {
625 if (scale < 0) {
626 shiftRight(-scale);
627 scale = 0;
628 compact();
629 }
630}
631
632void DecimalQuantity::roundToNickel(int32_t magnitude, RoundingMode roundingMode, UErrorCode& status) {
633 roundToMagnitude(magnitude, roundingMode, true, status);
634}
635
636void DecimalQuantity::roundToMagnitude(int32_t magnitude, RoundingMode roundingMode, UErrorCode& status) {
637 roundToMagnitude(magnitude, roundingMode, false, status);
638}
639
640void DecimalQuantity::roundToMagnitude(int32_t magnitude, RoundingMode roundingMode, bool nickel, UErrorCode& status) {
641 // The position in the BCD at which rounding will be performed; digits to the right of position
642 // will be rounded away.
643 int position = safeSubtract(magnitude, scale);
644
645 // "trailing" = least significant digit to the left of rounding
646 int8_t trailingDigit = getDigitPos(position);
647
648 if (position <= 0 && !isApproximate && (!nickel || trailingDigit == 0 || trailingDigit == 5)) {
649 // All digits are to the left of the rounding magnitude.
650 } else if (precision == 0) {
651 // No rounding for zero.
652 } else {
653 // Perform rounding logic.
654 // "leading" = most significant digit to the right of rounding
655 int8_t leadingDigit = getDigitPos(safeSubtract(position, 1));
656
657 // Compute which section of the number we are in.
658 // EDGE means we are at the bottom or top edge, like 1.000 or 1.999 (used by doubles)
659 // LOWER means we are between the bottom edge and the midpoint, like 1.391
660 // MIDPOINT means we are exactly in the middle, like 1.500
661 // UPPER means we are between the midpoint and the top edge, like 1.916
662 roundingutils::Section section;
663 if (!isApproximate) {
664 if (nickel && trailingDigit != 2 && trailingDigit != 7) {
665 // Nickel rounding, and not at .02x or .07x
666 if (trailingDigit < 2) {
667 // .00, .01 => down to .00
668 section = roundingutils::SECTION_LOWER;
669 } else if (trailingDigit < 5) {
670 // .03, .04 => up to .05
671 section = roundingutils::SECTION_UPPER;
672 } else if (trailingDigit < 7) {
673 // .05, .06 => down to .05
674 section = roundingutils::SECTION_LOWER;
675 } else {
676 // .08, .09 => up to .10
677 section = roundingutils::SECTION_UPPER;
678 }
679 } else if (leadingDigit < 5) {
680 // Includes nickel rounding .020-.024 and .070-.074
681 section = roundingutils::SECTION_LOWER;
682 } else if (leadingDigit > 5) {
683 // Includes nickel rounding .026-.029 and .076-.079
684 section = roundingutils::SECTION_UPPER;
685 } else {
686 // Includes nickel rounding .025 and .075
687 section = roundingutils::SECTION_MIDPOINT;
688 for (int p = safeSubtract(position, 2); p >= 0; p--) {
689 if (getDigitPos(p) != 0) {
690 section = roundingutils::SECTION_UPPER;
691 break;
692 }
693 }
694 }
695 } else {
696 int32_t p = safeSubtract(position, 2);
697 int32_t minP = uprv_max(0, precision - 14);
698 if (leadingDigit == 0 && (!nickel || trailingDigit == 0 || trailingDigit == 5)) {
699 section = roundingutils::SECTION_LOWER_EDGE;
700 for (; p >= minP; p--) {
701 if (getDigitPos(p) != 0) {
702 section = roundingutils::SECTION_LOWER;
703 break;
704 }
705 }
706 } else if (leadingDigit == 4 && (!nickel || trailingDigit == 2 || trailingDigit == 7)) {
707 section = roundingutils::SECTION_MIDPOINT;
708 for (; p >= minP; p--) {
709 if (getDigitPos(p) != 9) {
710 section = roundingutils::SECTION_LOWER;
711 break;
712 }
713 }
714 } else if (leadingDigit == 5 && (!nickel || trailingDigit == 2 || trailingDigit == 7)) {
715 section = roundingutils::SECTION_MIDPOINT;
716 for (; p >= minP; p--) {
717 if (getDigitPos(p) != 0) {
718 section = roundingutils::SECTION_UPPER;
719 break;
720 }
721 }
722 } else if (leadingDigit == 9 && (!nickel || trailingDigit == 4 || trailingDigit == 9)) {
723 section = roundingutils::SECTION_UPPER_EDGE;
724 for (; p >= minP; p--) {
725 if (getDigitPos(p) != 9) {
726 section = roundingutils::SECTION_UPPER;
727 break;
728 }
729 }
730 } else if (nickel && trailingDigit != 2 && trailingDigit != 7) {
731 // Nickel rounding, and not at .02x or .07x
732 if (trailingDigit < 2) {
733 // .00, .01 => down to .00
734 section = roundingutils::SECTION_LOWER;
735 } else if (trailingDigit < 5) {
736 // .03, .04 => up to .05
737 section = roundingutils::SECTION_UPPER;
738 } else if (trailingDigit < 7) {
739 // .05, .06 => down to .05
740 section = roundingutils::SECTION_LOWER;
741 } else {
742 // .08, .09 => up to .10
743 section = roundingutils::SECTION_UPPER;
744 }
745 } else if (leadingDigit < 5) {
746 // Includes nickel rounding .020-.024 and .070-.074
747 section = roundingutils::SECTION_LOWER;
748 } else {
749 // Includes nickel rounding .026-.029 and .076-.079
750 section = roundingutils::SECTION_UPPER;
751 }
752
753 bool roundsAtMidpoint = roundingutils::roundsAtMidpoint(roundingMode);
754 if (safeSubtract(position, 1) < precision - 14 ||
755 (roundsAtMidpoint && section == roundingutils::SECTION_MIDPOINT) ||
756 (!roundsAtMidpoint && section < 0 /* i.e. at upper or lower edge */)) {
757 // Oops! This means that we have to get the exact representation of the double,
758 // because the zone of uncertainty is along the rounding boundary.
759 convertToAccurateDouble();
760 roundToMagnitude(magnitude, roundingMode, nickel, status); // start over
761 return;
762 }
763
764 // Turn off the approximate double flag, since the value is now confirmed to be exact.
765 isApproximate = false;
766 origDouble = 0.0;
767 origDelta = 0;
768
769 if (position <= 0 && (!nickel || trailingDigit == 0 || trailingDigit == 5)) {
770 // All digits are to the left of the rounding magnitude.
771 return;
772 }
773
774 // Good to continue rounding.
775 if (section == -1) { section = roundingutils::SECTION_LOWER; }
776 if (section == -2) { section = roundingutils::SECTION_UPPER; }
777 }
778
779 // Nickel rounding "half even" goes to the nearest whole (away from the 5).
780 bool isEven = nickel
781 ? (trailingDigit < 2 || trailingDigit > 7
782 || (trailingDigit == 2 && section != roundingutils::SECTION_UPPER)
783 || (trailingDigit == 7 && section == roundingutils::SECTION_UPPER))
784 : (trailingDigit % 2) == 0;
785
786 bool roundDown = roundingutils::getRoundingDirection(isEven,
787 isNegative(),
788 section,
789 roundingMode,
790 status);
791 if (U_FAILURE(status)) {
792 return;
793 }
794
795 // Perform truncation
796 if (position >= precision) {
797 setBcdToZero();
798 scale = magnitude;
799 } else {
800 shiftRight(position);
801 }
802
803 if (nickel) {
804 if (trailingDigit < 5 && roundDown) {
805 setDigitPos(0, 0);
806 compact();
807 return;
808 } else if (trailingDigit >= 5 && !roundDown) {
809 setDigitPos(0, 9);
810 trailingDigit = 9;
811 // do not return: use the bubbling logic below
812 } else {
813 setDigitPos(0, 5);
814 // compact not necessary: digit at position 0 is nonzero
815 return;
816 }
817 }
818
819 // Bubble the result to the higher digits
820 if (!roundDown) {
821 if (trailingDigit == 9) {
822 int bubblePos = 0;
823 // Note: in the long implementation, the most digits BCD can have at this point is
824 // 15, so bubblePos <= 15 and getDigitPos(bubblePos) is safe.
825 for (; getDigitPos(bubblePos) == 9; bubblePos++) {}
826 shiftRight(bubblePos); // shift off the trailing 9s
827 }
828 int8_t digit0 = getDigitPos(0);
829 U_ASSERT(digit0 != 9);
830 setDigitPos(0, static_cast<int8_t>(digit0 + 1));
831 precision += 1; // in case an extra digit got added
832 }
833
834 compact();
835 }
836}
837
838void DecimalQuantity::roundToInfinity() {
839 if (isApproximate) {
840 convertToAccurateDouble();
841 }
842}
843
844void DecimalQuantity::appendDigit(int8_t value, int32_t leadingZeros, bool appendAsInteger) {
845 U_ASSERT(leadingZeros >= 0);
846
847 // Zero requires special handling to maintain the invariant that the least-significant digit
848 // in the BCD is nonzero.
849 if (value == 0) {
850 if (appendAsInteger && precision != 0) {
851 scale += leadingZeros + 1;
852 }
853 return;
854 }
855
856 // Deal with trailing zeros
857 if (scale > 0) {
858 leadingZeros += scale;
859 if (appendAsInteger) {
860 scale = 0;
861 }
862 }
863
864 // Append digit
865 shiftLeft(leadingZeros + 1);
866 setDigitPos(0, value);
867
868 // Fix scale if in integer mode
869 if (appendAsInteger) {
870 scale += leadingZeros + 1;
871 }
872}
873
874UnicodeString DecimalQuantity::toPlainString() const {
875 U_ASSERT(!isApproximate);
876 UnicodeString sb;
877 if (isNegative()) {
878 sb.append(u'-');
879 }
880 if (precision == 0 || getMagnitude() < 0) {
881 sb.append(u'0');
882 }
883 for (int m = getUpperDisplayMagnitude(); m >= getLowerDisplayMagnitude(); m--) {
884 if (m == -1) { sb.append(u'.'); }
885 sb.append(getDigit(m) + u'0');
886 }
887 return sb;
888}
889
890UnicodeString DecimalQuantity::toScientificString() const {
891 U_ASSERT(!isApproximate);
892 UnicodeString result;
893 if (isNegative()) {
894 result.append(u'-');
895 }
896 if (precision == 0) {
897 result.append(u"0E+0", -1);
898 return result;
899 }
900 int32_t upperPos = precision - 1;
901 int32_t lowerPos = 0;
902 int32_t p = upperPos;
903 result.append(u'0' + getDigitPos(p));
904 if ((--p) >= lowerPos) {
905 result.append(u'.');
906 for (; p >= lowerPos; p--) {
907 result.append(u'0' + getDigitPos(p));
908 }
909 }
910 result.append(u'E');
911 int32_t _scale = upperPos + scale;
912 if (_scale == INT32_MIN) {
913 result.append({u"-2147483648", -1});
914 return result;
915 } else if (_scale < 0) {
916 _scale *= -1;
917 result.append(u'-');
918 } else {
919 result.append(u'+');
920 }
921 if (_scale == 0) {
922 result.append(u'0');
923 }
924 int32_t insertIndex = result.length();
925 while (_scale > 0) {
926 std::div_t res = std::div(_scale, 10);
927 result.insert(insertIndex, u'0' + res.rem);
928 _scale = res.quot;
929 }
930 return result;
931}
932
933////////////////////////////////////////////////////
934/// End of DecimalQuantity_AbstractBCD.java ///
935/// Start of DecimalQuantity_DualStorageBCD.java ///
936////////////////////////////////////////////////////
937
938int8_t DecimalQuantity::getDigitPos(int32_t position) const {
939 if (usingBytes) {
940 if (position < 0 || position >= precision) { return 0; }
941 return fBCD.bcdBytes.ptr[position];
942 } else {
943 if (position < 0 || position >= 16) { return 0; }
944 return (int8_t) ((fBCD.bcdLong >> (position * 4)) & 0xf);
945 }
946}
947
948void DecimalQuantity::setDigitPos(int32_t position, int8_t value) {
949 U_ASSERT(position >= 0);
950 if (usingBytes) {
951 ensureCapacity(position + 1);
952 fBCD.bcdBytes.ptr[position] = value;
953 } else if (position >= 16) {
954 switchStorage();
955 ensureCapacity(position + 1);
956 fBCD.bcdBytes.ptr[position] = value;
957 } else {
958 int shift = position * 4;
959 fBCD.bcdLong = (fBCD.bcdLong & ~(0xfL << shift)) | ((long) value << shift);
960 }
961}
962
963void DecimalQuantity::shiftLeft(int32_t numDigits) {
964 if (!usingBytes && precision + numDigits > 16) {
965 switchStorage();
966 }
967 if (usingBytes) {
968 ensureCapacity(precision + numDigits);
969 int i = precision + numDigits - 1;
970 for (; i >= numDigits; i--) {
971 fBCD.bcdBytes.ptr[i] = fBCD.bcdBytes.ptr[i - numDigits];
972 }
973 for (; i >= 0; i--) {
974 fBCD.bcdBytes.ptr[i] = 0;
975 }
976 } else {
977 fBCD.bcdLong <<= (numDigits * 4);
978 }
979 scale -= numDigits;
980 precision += numDigits;
981}
982
983void DecimalQuantity::shiftRight(int32_t numDigits) {
984 if (usingBytes) {
985 int i = 0;
986 for (; i < precision - numDigits; i++) {
987 fBCD.bcdBytes.ptr[i] = fBCD.bcdBytes.ptr[i + numDigits];
988 }
989 for (; i < precision; i++) {
990 fBCD.bcdBytes.ptr[i] = 0;
991 }
992 } else {
993 fBCD.bcdLong >>= (numDigits * 4);
994 }
995 scale += numDigits;
996 precision -= numDigits;
997}
998
999void DecimalQuantity::popFromLeft(int32_t numDigits) {
1000 U_ASSERT(numDigits <= precision);
1001 if (usingBytes) {
1002 int i = precision - 1;
1003 for (; i >= precision - numDigits; i--) {
1004 fBCD.bcdBytes.ptr[i] = 0;
1005 }
1006 } else {
1007 fBCD.bcdLong &= (static_cast<uint64_t>(1) << ((precision - numDigits) * 4)) - 1;
1008 }
1009 precision -= numDigits;
1010}
1011
1012void DecimalQuantity::setBcdToZero() {
1013 if (usingBytes) {
1014 uprv_free(fBCD.bcdBytes.ptr);
1015 fBCD.bcdBytes.ptr = nullptr;
1016 usingBytes = false;
1017 }
1018 fBCD.bcdLong = 0L;
1019 scale = 0;
1020 precision = 0;
1021 isApproximate = false;
1022 origDouble = 0;
1023 origDelta = 0;
1024}
1025
1026void DecimalQuantity::readIntToBcd(int32_t n) {
1027 U_ASSERT(n != 0);
1028 // ints always fit inside the long implementation.
1029 uint64_t result = 0L;
1030 int i = 16;
1031 for (; n != 0; n /= 10, i--) {
1032 result = (result >> 4) + ((static_cast<uint64_t>(n) % 10) << 60);
1033 }
1034 U_ASSERT(!usingBytes);
1035 fBCD.bcdLong = result >> (i * 4);
1036 scale = 0;
1037 precision = 16 - i;
1038}
1039
1040void DecimalQuantity::readLongToBcd(int64_t n) {
1041 U_ASSERT(n != 0);
1042 if (n >= 10000000000000000L) {
1043 ensureCapacity();
1044 int i = 0;
1045 for (; n != 0L; n /= 10L, i++) {
1046 fBCD.bcdBytes.ptr[i] = static_cast<int8_t>(n % 10);
1047 }
1048 U_ASSERT(usingBytes);
1049 scale = 0;
1050 precision = i;
1051 } else {
1052 uint64_t result = 0L;
1053 int i = 16;
1054 for (; n != 0L; n /= 10L, i--) {
1055 result = (result >> 4) + ((n % 10) << 60);
1056 }
1057 U_ASSERT(i >= 0);
1058 U_ASSERT(!usingBytes);
1059 fBCD.bcdLong = result >> (i * 4);
1060 scale = 0;
1061 precision = 16 - i;
1062 }
1063}
1064
1065void DecimalQuantity::readDecNumberToBcd(const DecNum& decnum) {
1066 const decNumber* dn = decnum.getRawDecNumber();
1067 if (dn->digits > 16) {
1068 ensureCapacity(dn->digits);
1069 for (int32_t i = 0; i < dn->digits; i++) {
1070 fBCD.bcdBytes.ptr[i] = dn->lsu[i];
1071 }
1072 } else {
1073 uint64_t result = 0L;
1074 for (int32_t i = 0; i < dn->digits; i++) {
1075 result |= static_cast<uint64_t>(dn->lsu[i]) << (4 * i);
1076 }
1077 fBCD.bcdLong = result;
1078 }
1079 scale = dn->exponent;
1080 precision = dn->digits;
1081}
1082
1083void DecimalQuantity::readDoubleConversionToBcd(
1084 const char* buffer, int32_t length, int32_t point) {
1085 // NOTE: Despite the fact that double-conversion's API is called
1086 // "DoubleToAscii", they actually use '0' (as opposed to u8'0').
1087 if (length > 16) {
1088 ensureCapacity(length);
1089 for (int32_t i = 0; i < length; i++) {
1090 fBCD.bcdBytes.ptr[i] = buffer[length-i-1] - '0';
1091 }
1092 } else {
1093 uint64_t result = 0L;
1094 for (int32_t i = 0; i < length; i++) {
1095 result |= static_cast<uint64_t>(buffer[length-i-1] - '0') << (4 * i);
1096 }
1097 fBCD.bcdLong = result;
1098 }
1099 scale = point - length;
1100 precision = length;
1101}
1102
1103void DecimalQuantity::compact() {
1104 if (usingBytes) {
1105 int32_t delta = 0;
1106 for (; delta < precision && fBCD.bcdBytes.ptr[delta] == 0; delta++);
1107 if (delta == precision) {
1108 // Number is zero
1109 setBcdToZero();
1110 return;
1111 } else {
1112 // Remove trailing zeros
1113 shiftRight(delta);
1114 }
1115
1116 // Compute precision
1117 int32_t leading = precision - 1;
1118 for (; leading >= 0 && fBCD.bcdBytes.ptr[leading] == 0; leading--);
1119 precision = leading + 1;
1120
1121 // Switch storage mechanism if possible
1122 if (precision <= 16) {
1123 switchStorage();
1124 }
1125
1126 } else {
1127 if (fBCD.bcdLong == 0L) {
1128 // Number is zero
1129 setBcdToZero();
1130 return;
1131 }
1132
1133 // Compact the number (remove trailing zeros)
1134 // TODO: Use a more efficient algorithm here and below. There is a logarithmic one.
1135 int32_t delta = 0;
1136 for (; delta < precision && getDigitPos(delta) == 0; delta++);
1137 fBCD.bcdLong >>= delta * 4;
1138 scale += delta;
1139
1140 // Compute precision
1141 int32_t leading = precision - 1;
1142 for (; leading >= 0 && getDigitPos(leading) == 0; leading--);
1143 precision = leading + 1;
1144 }
1145}
1146
1147void DecimalQuantity::ensureCapacity() {
1148 ensureCapacity(40);
1149}
1150
1151void DecimalQuantity::ensureCapacity(int32_t capacity) {
1152 if (capacity == 0) { return; }
1153 int32_t oldCapacity = usingBytes ? fBCD.bcdBytes.len : 0;
1154 if (!usingBytes) {
1155 // TODO: There is nothing being done to check for memory allocation failures.
1156 // TODO: Consider indexing by nybbles instead of bytes in C++, so that we can
1157 // make these arrays half the size.
1158 fBCD.bcdBytes.ptr = static_cast<int8_t*>(uprv_malloc(capacity * sizeof(int8_t)));
1159 fBCD.bcdBytes.len = capacity;
1160 // Initialize the byte array to zeros (this is done automatically in Java)
1161 uprv_memset(fBCD.bcdBytes.ptr, 0, capacity * sizeof(int8_t));
1162 } else if (oldCapacity < capacity) {
1163 auto bcd1 = static_cast<int8_t*>(uprv_malloc(capacity * 2 * sizeof(int8_t)));
1164 uprv_memcpy(bcd1, fBCD.bcdBytes.ptr, oldCapacity * sizeof(int8_t));
1165 // Initialize the rest of the byte array to zeros (this is done automatically in Java)
1166 uprv_memset(bcd1 + oldCapacity, 0, (capacity - oldCapacity) * sizeof(int8_t));
1167 uprv_free(fBCD.bcdBytes.ptr);
1168 fBCD.bcdBytes.ptr = bcd1;
1169 fBCD.bcdBytes.len = capacity * 2;
1170 }
1171 usingBytes = true;
1172}
1173
1174void DecimalQuantity::switchStorage() {
1175 if (usingBytes) {
1176 // Change from bytes to long
1177 uint64_t bcdLong = 0L;
1178 for (int i = precision - 1; i >= 0; i--) {
1179 bcdLong <<= 4;
1180 bcdLong |= fBCD.bcdBytes.ptr[i];
1181 }
1182 uprv_free(fBCD.bcdBytes.ptr);
1183 fBCD.bcdBytes.ptr = nullptr;
1184 fBCD.bcdLong = bcdLong;
1185 usingBytes = false;
1186 } else {
1187 // Change from long to bytes
1188 // Copy the long into a local variable since it will get munged when we allocate the bytes
1189 uint64_t bcdLong = fBCD.bcdLong;
1190 ensureCapacity();
1191 for (int i = 0; i < precision; i++) {
1192 fBCD.bcdBytes.ptr[i] = static_cast<int8_t>(bcdLong & 0xf);
1193 bcdLong >>= 4;
1194 }
1195 U_ASSERT(usingBytes);
1196 }
1197}
1198
1199void DecimalQuantity::copyBcdFrom(const DecimalQuantity &other) {
1200 setBcdToZero();
1201 if (other.usingBytes) {
1202 ensureCapacity(other.precision);
1203 uprv_memcpy(fBCD.bcdBytes.ptr, other.fBCD.bcdBytes.ptr, other.precision * sizeof(int8_t));
1204 } else {
1205 fBCD.bcdLong = other.fBCD.bcdLong;
1206 }
1207}
1208
1209void DecimalQuantity::moveBcdFrom(DecimalQuantity &other) {
1210 setBcdToZero();
1211 if (other.usingBytes) {
1212 usingBytes = true;
1213 fBCD.bcdBytes.ptr = other.fBCD.bcdBytes.ptr;
1214 fBCD.bcdBytes.len = other.fBCD.bcdBytes.len;
1215 // Take ownership away from the old instance:
1216 other.fBCD.bcdBytes.ptr = nullptr;
1217 other.usingBytes = false;
1218 } else {
1219 fBCD.bcdLong = other.fBCD.bcdLong;
1220 }
1221}
1222
1223const char16_t* DecimalQuantity::checkHealth() const {
1224 if (usingBytes) {
1225 if (precision == 0) { return u"Zero precision but we are in byte mode"; }
1226 int32_t capacity = fBCD.bcdBytes.len;
1227 if (precision > capacity) { return u"Precision exceeds length of byte array"; }
1228 if (getDigitPos(precision - 1) == 0) { return u"Most significant digit is zero in byte mode"; }
1229 if (getDigitPos(0) == 0) { return u"Least significant digit is zero in long mode"; }
1230 for (int i = 0; i < precision; i++) {
1231 if (getDigitPos(i) >= 10) { return u"Digit exceeding 10 in byte array"; }
1232 if (getDigitPos(i) < 0) { return u"Digit below 0 in byte array"; }
1233 }
1234 for (int i = precision; i < capacity; i++) {
1235 if (getDigitPos(i) != 0) { return u"Nonzero digits outside of range in byte array"; }
1236 }
1237 } else {
1238 if (precision == 0 && fBCD.bcdLong != 0) {
1239 return u"Value in bcdLong even though precision is zero";
1240 }
1241 if (precision > 16) { return u"Precision exceeds length of long"; }
1242 if (precision != 0 && getDigitPos(precision - 1) == 0) {
1243 return u"Most significant digit is zero in long mode";
1244 }
1245 if (precision != 0 && getDigitPos(0) == 0) {
1246 return u"Least significant digit is zero in long mode";
1247 }
1248 for (int i = 0; i < precision; i++) {
1249 if (getDigitPos(i) >= 10) { return u"Digit exceeding 10 in long"; }
1250 if (getDigitPos(i) < 0) { return u"Digit below 0 in long (?!)"; }
1251 }
1252 for (int i = precision; i < 16; i++) {
1253 if (getDigitPos(i) != 0) { return u"Nonzero digits outside of range in long"; }
1254 }
1255 }
1256
1257 // No error
1258 return nullptr;
1259}
1260
1261bool DecimalQuantity::operator==(const DecimalQuantity& other) const {
1262 bool basicEquals =
1263 scale == other.scale
1264 && precision == other.precision
1265 && flags == other.flags
1266 && lReqPos == other.lReqPos
1267 && rReqPos == other.rReqPos
1268 && isApproximate == other.isApproximate;
1269 if (!basicEquals) {
1270 return false;
1271 }
1272
1273 if (precision == 0) {
1274 return true;
1275 } else if (isApproximate) {
1276 return origDouble == other.origDouble && origDelta == other.origDelta;
1277 } else {
1278 for (int m = getUpperDisplayMagnitude(); m >= getLowerDisplayMagnitude(); m--) {
1279 if (getDigit(m) != other.getDigit(m)) {
1280 return false;
1281 }
1282 }
1283 return true;
1284 }
1285}
1286
1287UnicodeString DecimalQuantity::toString() const {
1288 MaybeStackArray<char, 30> digits(precision + 1);
1289 for (int32_t i = 0; i < precision; i++) {
1290 digits[i] = getDigitPos(precision - i - 1) + '0';
1291 }
1292 digits[precision] = 0; // terminate buffer
1293 char buffer8[100];
1294 snprintf(
1295 buffer8,
1296 sizeof(buffer8),
1297 "<DecimalQuantity %d:%d %s %s%s%s%d>",
1298 lReqPos,
1299 rReqPos,
1300 (usingBytes ? "bytes" : "long"),
1301 (isNegative() ? "-" : ""),
1302 (precision == 0 ? "0" : digits.getAlias()),
1303 "E",
1304 scale);
1305 return UnicodeString(buffer8, -1, US_INV);
1306}
1307
1308#endif /* #if !UCONFIG_NO_FORMATTING */
1309