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 bool isZero = (isZeroish() && !isInfinite());
323 bool isNeg = isNegative();
324 if (isZero && isNeg) {
325 return SIGNUM_NEG_ZERO;
326 } else if (isZero) {
327 return SIGNUM_POS_ZERO;
328 } else if (isNeg) {
329 return SIGNUM_NEG;
330 } else {
331 return SIGNUM_POS;
332 }
333}
334
335bool DecimalQuantity::isInfinite() const {
336 return (flags & INFINITY_FLAG) != 0;
337}
338
339bool DecimalQuantity::isNaN() const {
340 return (flags & NAN_FLAG) != 0;
341}
342
343bool DecimalQuantity::isZeroish() const {
344 return precision == 0;
345}
346
347DecimalQuantity &DecimalQuantity::setToInt(int32_t n) {
348 setBcdToZero();
349 flags = 0;
350 if (n == INT32_MIN) {
351 flags |= NEGATIVE_FLAG;
352 // leave as INT32_MIN; handled below in _setToInt()
353 } else if (n < 0) {
354 flags |= NEGATIVE_FLAG;
355 n = -n;
356 }
357 if (n != 0) {
358 _setToInt(n);
359 compact();
360 }
361 return *this;
362}
363
364void DecimalQuantity::_setToInt(int32_t n) {
365 if (n == INT32_MIN) {
366 readLongToBcd(-static_cast<int64_t>(n));
367 } else {
368 readIntToBcd(n);
369 }
370}
371
372DecimalQuantity &DecimalQuantity::setToLong(int64_t n) {
373 setBcdToZero();
374 flags = 0;
375 if (n < 0 && n > INT64_MIN) {
376 flags |= NEGATIVE_FLAG;
377 n = -n;
378 }
379 if (n != 0) {
380 _setToLong(n);
381 compact();
382 }
383 return *this;
384}
385
386void DecimalQuantity::_setToLong(int64_t n) {
387 if (n == INT64_MIN) {
388 DecNum decnum;
389 UErrorCode localStatus = U_ZERO_ERROR;
390 decnum.setTo("9.223372036854775808E+18", localStatus);
391 if (U_FAILURE(localStatus)) { return; } // unexpected
392 flags |= NEGATIVE_FLAG;
393 readDecNumberToBcd(decnum);
394 } else if (n <= INT32_MAX) {
395 readIntToBcd(static_cast<int32_t>(n));
396 } else {
397 readLongToBcd(n);
398 }
399}
400
401DecimalQuantity &DecimalQuantity::setToDouble(double n) {
402 setBcdToZero();
403 flags = 0;
404 // signbit() from <math.h> handles +0.0 vs -0.0
405 if (std::signbit(n)) {
406 flags |= NEGATIVE_FLAG;
407 n = -n;
408 }
409 if (std::isnan(n) != 0) {
410 flags |= NAN_FLAG;
411 } else if (std::isfinite(n) == 0) {
412 flags |= INFINITY_FLAG;
413 } else if (n != 0) {
414 _setToDoubleFast(n);
415 compact();
416 }
417 return *this;
418}
419
420void DecimalQuantity::_setToDoubleFast(double n) {
421 isApproximate = true;
422 origDouble = n;
423 origDelta = 0;
424
425 // Make sure the double is an IEEE 754 double. If not, fall back to the slow path right now.
426 // TODO: Make a fast path for other types of doubles.
427 if (!std::numeric_limits<double>::is_iec559) {
428 convertToAccurateDouble();
429 // Turn off the approximate double flag, since the value is now exact.
430 isApproximate = false;
431 origDouble = 0.0;
432 return;
433 }
434
435 // To get the bits from the double, use memcpy, which takes care of endianness.
436 uint64_t ieeeBits;
437 uprv_memcpy(&ieeeBits, &n, sizeof(n));
438 int32_t exponent = static_cast<int32_t>((ieeeBits & 0x7ff0000000000000L) >> 52) - 0x3ff;
439
440 // Not all integers can be represented exactly for exponent > 52
441 if (exponent <= 52 && static_cast<int64_t>(n) == n) {
442 _setToLong(static_cast<int64_t>(n));
443 return;
444 }
445
446 // 3.3219... is log2(10)
447 auto fracLength = static_cast<int32_t> ((52 - exponent) / 3.32192809489);
448 if (fracLength >= 0) {
449 int32_t i = fracLength;
450 // 1e22 is the largest exact double.
451 for (; i >= 22; i -= 22) n *= 1e22;
452 n *= DOUBLE_MULTIPLIERS[i];
453 } else {
454 int32_t i = fracLength;
455 // 1e22 is the largest exact double.
456 for (; i <= -22; i += 22) n /= 1e22;
457 n /= DOUBLE_MULTIPLIERS[-i];
458 }
459 auto result = static_cast<int64_t>(uprv_round(n));
460 if (result != 0) {
461 _setToLong(result);
462 scale -= fracLength;
463 }
464}
465
466void DecimalQuantity::convertToAccurateDouble() {
467 U_ASSERT(origDouble != 0);
468 int32_t delta = origDelta;
469
470 // Call the slow oracle function (Double.toString in Java, DoubleToAscii in C++).
471 char buffer[DoubleToStringConverter::kBase10MaximalLength + 1];
472 bool sign; // unused; always positive
473 int32_t length;
474 int32_t point;
475 DoubleToStringConverter::DoubleToAscii(
476 origDouble,
477 DoubleToStringConverter::DtoaMode::SHORTEST,
478 0,
479 buffer,
480 sizeof(buffer),
481 &sign,
482 &length,
483 &point
484 );
485
486 setBcdToZero();
487 readDoubleConversionToBcd(buffer, length, point);
488 scale += delta;
489 explicitExactDouble = true;
490}
491
492DecimalQuantity &DecimalQuantity::setToDecNumber(StringPiece n, UErrorCode& status) {
493 setBcdToZero();
494 flags = 0;
495
496 // Compute the decNumber representation
497 DecNum decnum;
498 decnum.setTo(n, status);
499
500 _setToDecNum(decnum, status);
501 return *this;
502}
503
504DecimalQuantity& DecimalQuantity::setToDecNum(const DecNum& decnum, UErrorCode& status) {
505 setBcdToZero();
506 flags = 0;
507
508 _setToDecNum(decnum, status);
509 return *this;
510}
511
512void DecimalQuantity::_setToDecNum(const DecNum& decnum, UErrorCode& status) {
513 if (U_FAILURE(status)) { return; }
514 if (decnum.isNegative()) {
515 flags |= NEGATIVE_FLAG;
516 }
517 if (!decnum.isZero()) {
518 readDecNumberToBcd(decnum);
519 compact();
520 }
521}
522
523int64_t DecimalQuantity::toLong(bool truncateIfOverflow) const {
524 // NOTE: Call sites should be guarded by fitsInLong(), like this:
525 // if (dq.fitsInLong()) { /* use dq.toLong() */ } else { /* use some fallback */ }
526 // Fallback behavior upon truncateIfOverflow is to truncate at 17 digits.
527 uint64_t result = 0L;
528 int32_t upperMagnitude = scale + precision - 1;
529 if (truncateIfOverflow) {
530 upperMagnitude = std::min(upperMagnitude, 17);
531 }
532 for (int32_t magnitude = upperMagnitude; magnitude >= 0; magnitude--) {
533 result = result * 10 + getDigitPos(magnitude - scale);
534 }
535 if (isNegative()) {
536 return static_cast<int64_t>(0LL - result); // i.e., -result
537 }
538 return static_cast<int64_t>(result);
539}
540
541uint64_t DecimalQuantity::toFractionLong(bool includeTrailingZeros) const {
542 uint64_t result = 0L;
543 int32_t magnitude = -1;
544 int32_t lowerMagnitude = scale;
545 if (includeTrailingZeros) {
546 lowerMagnitude = std::min(lowerMagnitude, rReqPos);
547 }
548 for (; magnitude >= lowerMagnitude && result <= 1e18L; magnitude--) {
549 result = result * 10 + getDigitPos(magnitude - scale);
550 }
551 // Remove trailing zeros; this can happen during integer overflow cases.
552 if (!includeTrailingZeros) {
553 while (result > 0 && (result % 10) == 0) {
554 result /= 10;
555 }
556 }
557 return result;
558}
559
560bool DecimalQuantity::fitsInLong(bool ignoreFraction) const {
561 if (isInfinite() || isNaN()) {
562 return false;
563 }
564 if (isZeroish()) {
565 return true;
566 }
567 if (scale < 0 && !ignoreFraction) {
568 return false;
569 }
570 int magnitude = getMagnitude();
571 if (magnitude < 18) {
572 return true;
573 }
574 if (magnitude > 18) {
575 return false;
576 }
577 // Hard case: the magnitude is 10^18.
578 // The largest int64 is: 9,223,372,036,854,775,807
579 for (int p = 0; p < precision; p++) {
580 int8_t digit = getDigit(18 - p);
581 static int8_t INT64_BCD[] = { 9, 2, 2, 3, 3, 7, 2, 0, 3, 6, 8, 5, 4, 7, 7, 5, 8, 0, 8 };
582 if (digit < INT64_BCD[p]) {
583 return true;
584 } else if (digit > INT64_BCD[p]) {
585 return false;
586 }
587 }
588 // Exactly equal to max long plus one.
589 return isNegative();
590}
591
592double DecimalQuantity::toDouble() const {
593 // If this assertion fails, you need to call roundToInfinity() or some other rounding method.
594 // See the comment in the header file explaining the "isApproximate" field.
595 U_ASSERT(!isApproximate);
596
597 if (isNaN()) {
598 return NAN;
599 } else if (isInfinite()) {
600 return isNegative() ? -INFINITY : INFINITY;
601 }
602
603 // We are processing well-formed input, so we don't need any special options to StringToDoubleConverter.
604 StringToDoubleConverter converter(0, 0, 0, "", "");
605 UnicodeString numberString = this->toScientificString();
606 int32_t count;
607 return converter.StringToDouble(
608 reinterpret_cast<const uint16_t*>(numberString.getBuffer()),
609 numberString.length(),
610 &count);
611}
612
613void DecimalQuantity::toDecNum(DecNum& output, UErrorCode& status) const {
614 // Special handling for zero
615 if (precision == 0) {
616 output.setTo("0", status);
617 }
618
619 // Use the BCD constructor. We need to do a little bit of work to convert, though.
620 // The decNumber constructor expects most-significant first, but we store least-significant first.
621 MaybeStackArray<uint8_t, 20> ubcd(precision);
622 for (int32_t m = 0; m < precision; m++) {
623 ubcd[precision - m - 1] = static_cast<uint8_t>(getDigitPos(m));
624 }
625 output.setTo(ubcd.getAlias(), precision, scale, isNegative(), status);
626}
627
628void DecimalQuantity::truncate() {
629 if (scale < 0) {
630 shiftRight(-scale);
631 scale = 0;
632 compact();
633 }
634}
635
636void DecimalQuantity::roundToNickel(int32_t magnitude, RoundingMode roundingMode, UErrorCode& status) {
637 roundToMagnitude(magnitude, roundingMode, true, status);
638}
639
640void DecimalQuantity::roundToMagnitude(int32_t magnitude, RoundingMode roundingMode, UErrorCode& status) {
641 roundToMagnitude(magnitude, roundingMode, false, status);
642}
643
644void DecimalQuantity::roundToMagnitude(int32_t magnitude, RoundingMode roundingMode, bool nickel, UErrorCode& status) {
645 // The position in the BCD at which rounding will be performed; digits to the right of position
646 // will be rounded away.
647 int position = safeSubtract(magnitude, scale);
648
649 // "trailing" = least significant digit to the left of rounding
650 int8_t trailingDigit = getDigitPos(position);
651
652 if (position <= 0 && !isApproximate && (!nickel || trailingDigit == 0 || trailingDigit == 5)) {
653 // All digits are to the left of the rounding magnitude.
654 } else if (precision == 0) {
655 // No rounding for zero.
656 } else {
657 // Perform rounding logic.
658 // "leading" = most significant digit to the right of rounding
659 int8_t leadingDigit = getDigitPos(safeSubtract(position, 1));
660
661 // Compute which section of the number we are in.
662 // EDGE means we are at the bottom or top edge, like 1.000 or 1.999 (used by doubles)
663 // LOWER means we are between the bottom edge and the midpoint, like 1.391
664 // MIDPOINT means we are exactly in the middle, like 1.500
665 // UPPER means we are between the midpoint and the top edge, like 1.916
666 roundingutils::Section section;
667 if (!isApproximate) {
668 if (nickel && trailingDigit != 2 && trailingDigit != 7) {
669 // Nickel rounding, and not at .02x or .07x
670 if (trailingDigit < 2) {
671 // .00, .01 => down to .00
672 section = roundingutils::SECTION_LOWER;
673 } else if (trailingDigit < 5) {
674 // .03, .04 => up to .05
675 section = roundingutils::SECTION_UPPER;
676 } else if (trailingDigit < 7) {
677 // .05, .06 => down to .05
678 section = roundingutils::SECTION_LOWER;
679 } else {
680 // .08, .09 => up to .10
681 section = roundingutils::SECTION_UPPER;
682 }
683 } else if (leadingDigit < 5) {
684 // Includes nickel rounding .020-.024 and .070-.074
685 section = roundingutils::SECTION_LOWER;
686 } else if (leadingDigit > 5) {
687 // Includes nickel rounding .026-.029 and .076-.079
688 section = roundingutils::SECTION_UPPER;
689 } else {
690 // Includes nickel rounding .025 and .075
691 section = roundingutils::SECTION_MIDPOINT;
692 for (int p = safeSubtract(position, 2); p >= 0; p--) {
693 if (getDigitPos(p) != 0) {
694 section = roundingutils::SECTION_UPPER;
695 break;
696 }
697 }
698 }
699 } else {
700 int32_t p = safeSubtract(position, 2);
701 int32_t minP = uprv_max(0, precision - 14);
702 if (leadingDigit == 0 && (!nickel || trailingDigit == 0 || trailingDigit == 5)) {
703 section = roundingutils::SECTION_LOWER_EDGE;
704 for (; p >= minP; p--) {
705 if (getDigitPos(p) != 0) {
706 section = roundingutils::SECTION_LOWER;
707 break;
708 }
709 }
710 } else if (leadingDigit == 4 && (!nickel || trailingDigit == 2 || trailingDigit == 7)) {
711 section = roundingutils::SECTION_MIDPOINT;
712 for (; p >= minP; p--) {
713 if (getDigitPos(p) != 9) {
714 section = roundingutils::SECTION_LOWER;
715 break;
716 }
717 }
718 } else if (leadingDigit == 5 && (!nickel || trailingDigit == 2 || trailingDigit == 7)) {
719 section = roundingutils::SECTION_MIDPOINT;
720 for (; p >= minP; p--) {
721 if (getDigitPos(p) != 0) {
722 section = roundingutils::SECTION_UPPER;
723 break;
724 }
725 }
726 } else if (leadingDigit == 9 && (!nickel || trailingDigit == 4 || trailingDigit == 9)) {
727 section = roundingutils::SECTION_UPPER_EDGE;
728 for (; p >= minP; p--) {
729 if (getDigitPos(p) != 9) {
730 section = roundingutils::SECTION_UPPER;
731 break;
732 }
733 }
734 } else if (nickel && trailingDigit != 2 && trailingDigit != 7) {
735 // Nickel rounding, and not at .02x or .07x
736 if (trailingDigit < 2) {
737 // .00, .01 => down to .00
738 section = roundingutils::SECTION_LOWER;
739 } else if (trailingDigit < 5) {
740 // .03, .04 => up to .05
741 section = roundingutils::SECTION_UPPER;
742 } else if (trailingDigit < 7) {
743 // .05, .06 => down to .05
744 section = roundingutils::SECTION_LOWER;
745 } else {
746 // .08, .09 => up to .10
747 section = roundingutils::SECTION_UPPER;
748 }
749 } else if (leadingDigit < 5) {
750 // Includes nickel rounding .020-.024 and .070-.074
751 section = roundingutils::SECTION_LOWER;
752 } else {
753 // Includes nickel rounding .026-.029 and .076-.079
754 section = roundingutils::SECTION_UPPER;
755 }
756
757 bool roundsAtMidpoint = roundingutils::roundsAtMidpoint(roundingMode);
758 if (safeSubtract(position, 1) < precision - 14 ||
759 (roundsAtMidpoint && section == roundingutils::SECTION_MIDPOINT) ||
760 (!roundsAtMidpoint && section < 0 /* i.e. at upper or lower edge */)) {
761 // Oops! This means that we have to get the exact representation of the double,
762 // because the zone of uncertainty is along the rounding boundary.
763 convertToAccurateDouble();
764 roundToMagnitude(magnitude, roundingMode, nickel, status); // start over
765 return;
766 }
767
768 // Turn off the approximate double flag, since the value is now confirmed to be exact.
769 isApproximate = false;
770 origDouble = 0.0;
771 origDelta = 0;
772
773 if (position <= 0 && (!nickel || trailingDigit == 0 || trailingDigit == 5)) {
774 // All digits are to the left of the rounding magnitude.
775 return;
776 }
777
778 // Good to continue rounding.
779 if (section == -1) { section = roundingutils::SECTION_LOWER; }
780 if (section == -2) { section = roundingutils::SECTION_UPPER; }
781 }
782
783 // Nickel rounding "half even" goes to the nearest whole (away from the 5).
784 bool isEven = nickel
785 ? (trailingDigit < 2 || trailingDigit > 7
786 || (trailingDigit == 2 && section != roundingutils::SECTION_UPPER)
787 || (trailingDigit == 7 && section == roundingutils::SECTION_UPPER))
788 : (trailingDigit % 2) == 0;
789
790 bool roundDown = roundingutils::getRoundingDirection(isEven,
791 isNegative(),
792 section,
793 roundingMode,
794 status);
795 if (U_FAILURE(status)) {
796 return;
797 }
798
799 // Perform truncation
800 if (position >= precision) {
801 setBcdToZero();
802 scale = magnitude;
803 } else {
804 shiftRight(position);
805 }
806
807 if (nickel) {
808 if (trailingDigit < 5 && roundDown) {
809 setDigitPos(0, 0);
810 compact();
811 return;
812 } else if (trailingDigit >= 5 && !roundDown) {
813 setDigitPos(0, 9);
814 trailingDigit = 9;
815 // do not return: use the bubbling logic below
816 } else {
817 setDigitPos(0, 5);
818 // compact not necessary: digit at position 0 is nonzero
819 return;
820 }
821 }
822
823 // Bubble the result to the higher digits
824 if (!roundDown) {
825 if (trailingDigit == 9) {
826 int bubblePos = 0;
827 // Note: in the long implementation, the most digits BCD can have at this point is
828 // 15, so bubblePos <= 15 and getDigitPos(bubblePos) is safe.
829 for (; getDigitPos(bubblePos) == 9; bubblePos++) {}
830 shiftRight(bubblePos); // shift off the trailing 9s
831 }
832 int8_t digit0 = getDigitPos(0);
833 U_ASSERT(digit0 != 9);
834 setDigitPos(0, static_cast<int8_t>(digit0 + 1));
835 precision += 1; // in case an extra digit got added
836 }
837
838 compact();
839 }
840}
841
842void DecimalQuantity::roundToInfinity() {
843 if (isApproximate) {
844 convertToAccurateDouble();
845 }
846}
847
848void DecimalQuantity::appendDigit(int8_t value, int32_t leadingZeros, bool appendAsInteger) {
849 U_ASSERT(leadingZeros >= 0);
850
851 // Zero requires special handling to maintain the invariant that the least-significant digit
852 // in the BCD is nonzero.
853 if (value == 0) {
854 if (appendAsInteger && precision != 0) {
855 scale += leadingZeros + 1;
856 }
857 return;
858 }
859
860 // Deal with trailing zeros
861 if (scale > 0) {
862 leadingZeros += scale;
863 if (appendAsInteger) {
864 scale = 0;
865 }
866 }
867
868 // Append digit
869 shiftLeft(leadingZeros + 1);
870 setDigitPos(0, value);
871
872 // Fix scale if in integer mode
873 if (appendAsInteger) {
874 scale += leadingZeros + 1;
875 }
876}
877
878UnicodeString DecimalQuantity::toPlainString() const {
879 U_ASSERT(!isApproximate);
880 UnicodeString sb;
881 if (isNegative()) {
882 sb.append(u'-');
883 }
884 if (precision == 0 || getMagnitude() < 0) {
885 sb.append(u'0');
886 }
887 for (int m = getUpperDisplayMagnitude(); m >= getLowerDisplayMagnitude(); m--) {
888 if (m == -1) { sb.append(u'.'); }
889 sb.append(getDigit(m) + u'0');
890 }
891 return sb;
892}
893
894UnicodeString DecimalQuantity::toScientificString() const {
895 U_ASSERT(!isApproximate);
896 UnicodeString result;
897 if (isNegative()) {
898 result.append(u'-');
899 }
900 if (precision == 0) {
901 result.append(u"0E+0", -1);
902 return result;
903 }
904 int32_t upperPos = precision - 1;
905 int32_t lowerPos = 0;
906 int32_t p = upperPos;
907 result.append(u'0' + getDigitPos(p));
908 if ((--p) >= lowerPos) {
909 result.append(u'.');
910 for (; p >= lowerPos; p--) {
911 result.append(u'0' + getDigitPos(p));
912 }
913 }
914 result.append(u'E');
915 int32_t _scale = upperPos + scale;
916 if (_scale == INT32_MIN) {
917 result.append({u"-2147483648", -1});
918 return result;
919 } else if (_scale < 0) {
920 _scale *= -1;
921 result.append(u'-');
922 } else {
923 result.append(u'+');
924 }
925 if (_scale == 0) {
926 result.append(u'0');
927 }
928 int32_t insertIndex = result.length();
929 while (_scale > 0) {
930 std::div_t res = std::div(_scale, 10);
931 result.insert(insertIndex, u'0' + res.rem);
932 _scale = res.quot;
933 }
934 return result;
935}
936
937////////////////////////////////////////////////////
938/// End of DecimalQuantity_AbstractBCD.java ///
939/// Start of DecimalQuantity_DualStorageBCD.java ///
940////////////////////////////////////////////////////
941
942int8_t DecimalQuantity::getDigitPos(int32_t position) const {
943 if (usingBytes) {
944 if (position < 0 || position >= precision) { return 0; }
945 return fBCD.bcdBytes.ptr[position];
946 } else {
947 if (position < 0 || position >= 16) { return 0; }
948 return (int8_t) ((fBCD.bcdLong >> (position * 4)) & 0xf);
949 }
950}
951
952void DecimalQuantity::setDigitPos(int32_t position, int8_t value) {
953 U_ASSERT(position >= 0);
954 if (usingBytes) {
955 ensureCapacity(position + 1);
956 fBCD.bcdBytes.ptr[position] = value;
957 } else if (position >= 16) {
958 switchStorage();
959 ensureCapacity(position + 1);
960 fBCD.bcdBytes.ptr[position] = value;
961 } else {
962 int shift = position * 4;
963 fBCD.bcdLong = (fBCD.bcdLong & ~(0xfL << shift)) | ((long) value << shift);
964 }
965}
966
967void DecimalQuantity::shiftLeft(int32_t numDigits) {
968 if (!usingBytes && precision + numDigits > 16) {
969 switchStorage();
970 }
971 if (usingBytes) {
972 ensureCapacity(precision + numDigits);
973 int i = precision + numDigits - 1;
974 for (; i >= numDigits; i--) {
975 fBCD.bcdBytes.ptr[i] = fBCD.bcdBytes.ptr[i - numDigits];
976 }
977 for (; i >= 0; i--) {
978 fBCD.bcdBytes.ptr[i] = 0;
979 }
980 } else {
981 fBCD.bcdLong <<= (numDigits * 4);
982 }
983 scale -= numDigits;
984 precision += numDigits;
985}
986
987void DecimalQuantity::shiftRight(int32_t numDigits) {
988 if (usingBytes) {
989 int i = 0;
990 for (; i < precision - numDigits; i++) {
991 fBCD.bcdBytes.ptr[i] = fBCD.bcdBytes.ptr[i + numDigits];
992 }
993 for (; i < precision; i++) {
994 fBCD.bcdBytes.ptr[i] = 0;
995 }
996 } else {
997 fBCD.bcdLong >>= (numDigits * 4);
998 }
999 scale += numDigits;
1000 precision -= numDigits;
1001}
1002
1003void DecimalQuantity::popFromLeft(int32_t numDigits) {
1004 U_ASSERT(numDigits <= precision);
1005 if (usingBytes) {
1006 int i = precision - 1;
1007 for (; i >= precision - numDigits; i--) {
1008 fBCD.bcdBytes.ptr[i] = 0;
1009 }
1010 } else {
1011 fBCD.bcdLong &= (static_cast<uint64_t>(1) << ((precision - numDigits) * 4)) - 1;
1012 }
1013 precision -= numDigits;
1014}
1015
1016void DecimalQuantity::setBcdToZero() {
1017 if (usingBytes) {
1018 uprv_free(fBCD.bcdBytes.ptr);
1019 fBCD.bcdBytes.ptr = nullptr;
1020 usingBytes = false;
1021 }
1022 fBCD.bcdLong = 0L;
1023 scale = 0;
1024 precision = 0;
1025 isApproximate = false;
1026 origDouble = 0;
1027 origDelta = 0;
1028}
1029
1030void DecimalQuantity::readIntToBcd(int32_t n) {
1031 U_ASSERT(n != 0);
1032 // ints always fit inside the long implementation.
1033 uint64_t result = 0L;
1034 int i = 16;
1035 for (; n != 0; n /= 10, i--) {
1036 result = (result >> 4) + ((static_cast<uint64_t>(n) % 10) << 60);
1037 }
1038 U_ASSERT(!usingBytes);
1039 fBCD.bcdLong = result >> (i * 4);
1040 scale = 0;
1041 precision = 16 - i;
1042}
1043
1044void DecimalQuantity::readLongToBcd(int64_t n) {
1045 U_ASSERT(n != 0);
1046 if (n >= 10000000000000000L) {
1047 ensureCapacity();
1048 int i = 0;
1049 for (; n != 0L; n /= 10L, i++) {
1050 fBCD.bcdBytes.ptr[i] = static_cast<int8_t>(n % 10);
1051 }
1052 U_ASSERT(usingBytes);
1053 scale = 0;
1054 precision = i;
1055 } else {
1056 uint64_t result = 0L;
1057 int i = 16;
1058 for (; n != 0L; n /= 10L, i--) {
1059 result = (result >> 4) + ((n % 10) << 60);
1060 }
1061 U_ASSERT(i >= 0);
1062 U_ASSERT(!usingBytes);
1063 fBCD.bcdLong = result >> (i * 4);
1064 scale = 0;
1065 precision = 16 - i;
1066 }
1067}
1068
1069void DecimalQuantity::readDecNumberToBcd(const DecNum& decnum) {
1070 const decNumber* dn = decnum.getRawDecNumber();
1071 if (dn->digits > 16) {
1072 ensureCapacity(dn->digits);
1073 for (int32_t i = 0; i < dn->digits; i++) {
1074 fBCD.bcdBytes.ptr[i] = dn->lsu[i];
1075 }
1076 } else {
1077 uint64_t result = 0L;
1078 for (int32_t i = 0; i < dn->digits; i++) {
1079 result |= static_cast<uint64_t>(dn->lsu[i]) << (4 * i);
1080 }
1081 fBCD.bcdLong = result;
1082 }
1083 scale = dn->exponent;
1084 precision = dn->digits;
1085}
1086
1087void DecimalQuantity::readDoubleConversionToBcd(
1088 const char* buffer, int32_t length, int32_t point) {
1089 // NOTE: Despite the fact that double-conversion's API is called
1090 // "DoubleToAscii", they actually use '0' (as opposed to u8'0').
1091 if (length > 16) {
1092 ensureCapacity(length);
1093 for (int32_t i = 0; i < length; i++) {
1094 fBCD.bcdBytes.ptr[i] = buffer[length-i-1] - '0';
1095 }
1096 } else {
1097 uint64_t result = 0L;
1098 for (int32_t i = 0; i < length; i++) {
1099 result |= static_cast<uint64_t>(buffer[length-i-1] - '0') << (4 * i);
1100 }
1101 fBCD.bcdLong = result;
1102 }
1103 scale = point - length;
1104 precision = length;
1105}
1106
1107void DecimalQuantity::compact() {
1108 if (usingBytes) {
1109 int32_t delta = 0;
1110 for (; delta < precision && fBCD.bcdBytes.ptr[delta] == 0; delta++);
1111 if (delta == precision) {
1112 // Number is zero
1113 setBcdToZero();
1114 return;
1115 } else {
1116 // Remove trailing zeros
1117 shiftRight(delta);
1118 }
1119
1120 // Compute precision
1121 int32_t leading = precision - 1;
1122 for (; leading >= 0 && fBCD.bcdBytes.ptr[leading] == 0; leading--);
1123 precision = leading + 1;
1124
1125 // Switch storage mechanism if possible
1126 if (precision <= 16) {
1127 switchStorage();
1128 }
1129
1130 } else {
1131 if (fBCD.bcdLong == 0L) {
1132 // Number is zero
1133 setBcdToZero();
1134 return;
1135 }
1136
1137 // Compact the number (remove trailing zeros)
1138 // TODO: Use a more efficient algorithm here and below. There is a logarithmic one.
1139 int32_t delta = 0;
1140 for (; delta < precision && getDigitPos(delta) == 0; delta++);
1141 fBCD.bcdLong >>= delta * 4;
1142 scale += delta;
1143
1144 // Compute precision
1145 int32_t leading = precision - 1;
1146 for (; leading >= 0 && getDigitPos(leading) == 0; leading--);
1147 precision = leading + 1;
1148 }
1149}
1150
1151void DecimalQuantity::ensureCapacity() {
1152 ensureCapacity(40);
1153}
1154
1155void DecimalQuantity::ensureCapacity(int32_t capacity) {
1156 if (capacity == 0) { return; }
1157 int32_t oldCapacity = usingBytes ? fBCD.bcdBytes.len : 0;
1158 if (!usingBytes) {
1159 // TODO: There is nothing being done to check for memory allocation failures.
1160 // TODO: Consider indexing by nybbles instead of bytes in C++, so that we can
1161 // make these arrays half the size.
1162 fBCD.bcdBytes.ptr = static_cast<int8_t*>(uprv_malloc(capacity * sizeof(int8_t)));
1163 fBCD.bcdBytes.len = capacity;
1164 // Initialize the byte array to zeros (this is done automatically in Java)
1165 uprv_memset(fBCD.bcdBytes.ptr, 0, capacity * sizeof(int8_t));
1166 } else if (oldCapacity < capacity) {
1167 auto bcd1 = static_cast<int8_t*>(uprv_malloc(capacity * 2 * sizeof(int8_t)));
1168 uprv_memcpy(bcd1, fBCD.bcdBytes.ptr, oldCapacity * sizeof(int8_t));
1169 // Initialize the rest of the byte array to zeros (this is done automatically in Java)
1170 uprv_memset(bcd1 + oldCapacity, 0, (capacity - oldCapacity) * sizeof(int8_t));
1171 uprv_free(fBCD.bcdBytes.ptr);
1172 fBCD.bcdBytes.ptr = bcd1;
1173 fBCD.bcdBytes.len = capacity * 2;
1174 }
1175 usingBytes = true;
1176}
1177
1178void DecimalQuantity::switchStorage() {
1179 if (usingBytes) {
1180 // Change from bytes to long
1181 uint64_t bcdLong = 0L;
1182 for (int i = precision - 1; i >= 0; i--) {
1183 bcdLong <<= 4;
1184 bcdLong |= fBCD.bcdBytes.ptr[i];
1185 }
1186 uprv_free(fBCD.bcdBytes.ptr);
1187 fBCD.bcdBytes.ptr = nullptr;
1188 fBCD.bcdLong = bcdLong;
1189 usingBytes = false;
1190 } else {
1191 // Change from long to bytes
1192 // Copy the long into a local variable since it will get munged when we allocate the bytes
1193 uint64_t bcdLong = fBCD.bcdLong;
1194 ensureCapacity();
1195 for (int i = 0; i < precision; i++) {
1196 fBCD.bcdBytes.ptr[i] = static_cast<int8_t>(bcdLong & 0xf);
1197 bcdLong >>= 4;
1198 }
1199 U_ASSERT(usingBytes);
1200 }
1201}
1202
1203void DecimalQuantity::copyBcdFrom(const DecimalQuantity &other) {
1204 setBcdToZero();
1205 if (other.usingBytes) {
1206 ensureCapacity(other.precision);
1207 uprv_memcpy(fBCD.bcdBytes.ptr, other.fBCD.bcdBytes.ptr, other.precision * sizeof(int8_t));
1208 } else {
1209 fBCD.bcdLong = other.fBCD.bcdLong;
1210 }
1211}
1212
1213void DecimalQuantity::moveBcdFrom(DecimalQuantity &other) {
1214 setBcdToZero();
1215 if (other.usingBytes) {
1216 usingBytes = true;
1217 fBCD.bcdBytes.ptr = other.fBCD.bcdBytes.ptr;
1218 fBCD.bcdBytes.len = other.fBCD.bcdBytes.len;
1219 // Take ownership away from the old instance:
1220 other.fBCD.bcdBytes.ptr = nullptr;
1221 other.usingBytes = false;
1222 } else {
1223 fBCD.bcdLong = other.fBCD.bcdLong;
1224 }
1225}
1226
1227const char16_t* DecimalQuantity::checkHealth() const {
1228 if (usingBytes) {
1229 if (precision == 0) { return u"Zero precision but we are in byte mode"; }
1230 int32_t capacity = fBCD.bcdBytes.len;
1231 if (precision > capacity) { return u"Precision exceeds length of byte array"; }
1232 if (getDigitPos(precision - 1) == 0) { return u"Most significant digit is zero in byte mode"; }
1233 if (getDigitPos(0) == 0) { return u"Least significant digit is zero in long mode"; }
1234 for (int i = 0; i < precision; i++) {
1235 if (getDigitPos(i) >= 10) { return u"Digit exceeding 10 in byte array"; }
1236 if (getDigitPos(i) < 0) { return u"Digit below 0 in byte array"; }
1237 }
1238 for (int i = precision; i < capacity; i++) {
1239 if (getDigitPos(i) != 0) { return u"Nonzero digits outside of range in byte array"; }
1240 }
1241 } else {
1242 if (precision == 0 && fBCD.bcdLong != 0) {
1243 return u"Value in bcdLong even though precision is zero";
1244 }
1245 if (precision > 16) { return u"Precision exceeds length of long"; }
1246 if (precision != 0 && getDigitPos(precision - 1) == 0) {
1247 return u"Most significant digit is zero in long mode";
1248 }
1249 if (precision != 0 && getDigitPos(0) == 0) {
1250 return u"Least significant digit is zero in long mode";
1251 }
1252 for (int i = 0; i < precision; i++) {
1253 if (getDigitPos(i) >= 10) { return u"Digit exceeding 10 in long"; }
1254 if (getDigitPos(i) < 0) { return u"Digit below 0 in long (?!)"; }
1255 }
1256 for (int i = precision; i < 16; i++) {
1257 if (getDigitPos(i) != 0) { return u"Nonzero digits outside of range in long"; }
1258 }
1259 }
1260
1261 // No error
1262 return nullptr;
1263}
1264
1265bool DecimalQuantity::operator==(const DecimalQuantity& other) const {
1266 bool basicEquals =
1267 scale == other.scale
1268 && precision == other.precision
1269 && flags == other.flags
1270 && lReqPos == other.lReqPos
1271 && rReqPos == other.rReqPos
1272 && isApproximate == other.isApproximate;
1273 if (!basicEquals) {
1274 return false;
1275 }
1276
1277 if (precision == 0) {
1278 return true;
1279 } else if (isApproximate) {
1280 return origDouble == other.origDouble && origDelta == other.origDelta;
1281 } else {
1282 for (int m = getUpperDisplayMagnitude(); m >= getLowerDisplayMagnitude(); m--) {
1283 if (getDigit(m) != other.getDigit(m)) {
1284 return false;
1285 }
1286 }
1287 return true;
1288 }
1289}
1290
1291UnicodeString DecimalQuantity::toString() const {
1292 MaybeStackArray<char, 30> digits(precision + 1);
1293 for (int32_t i = 0; i < precision; i++) {
1294 digits[i] = getDigitPos(precision - i - 1) + '0';
1295 }
1296 digits[precision] = 0; // terminate buffer
1297 char buffer8[100];
1298 snprintf(
1299 buffer8,
1300 sizeof(buffer8),
1301 "<DecimalQuantity %d:%d %s %s%s%s%d>",
1302 lReqPos,
1303 rReqPos,
1304 (usingBytes ? "bytes" : "long"),
1305 (isNegative() ? "-" : ""),
1306 (precision == 0 ? "0" : digits.getAlias()),
1307 "E",
1308 scale);
1309 return UnicodeString(buffer8, -1, US_INV);
1310}
1311
1312#endif /* #if !UCONFIG_NO_FORMATTING */
1313