OLD | NEW |
1 /* | 1 /* |
2 ********************************************************************** | 2 ********************************************************************** |
3 * Copyright (C) 1997-2014, International Business Machines | 3 * Copyright (C) 1997-2015, International Business Machines |
4 * Corporation and others. All Rights Reserved. | 4 * Corporation and others. All Rights Reserved. |
5 ********************************************************************** | 5 ********************************************************************** |
6 * | 6 * |
7 * File DIGITLST.CPP | 7 * File DIGITLST.CPP |
8 * | 8 * |
9 * Modification History: | 9 * Modification History: |
10 * | 10 * |
11 * Date Name Description | 11 * Date Name Description |
12 * 03/21/97 clhuang Converted from java. | 12 * 03/21/97 clhuang Converted from java. |
13 * 03/21/97 clhuang Implemented with new APIs. | 13 * 03/21/97 clhuang Implemented with new APIs. |
(...skipping 13 matching lines...) Expand all Loading... |
27 #include "digitlst.h" | 27 #include "digitlst.h" |
28 | 28 |
29 #if !UCONFIG_NO_FORMATTING | 29 #if !UCONFIG_NO_FORMATTING |
30 #include "unicode/putil.h" | 30 #include "unicode/putil.h" |
31 #include "charstr.h" | 31 #include "charstr.h" |
32 #include "cmemory.h" | 32 #include "cmemory.h" |
33 #include "cstring.h" | 33 #include "cstring.h" |
34 #include "mutex.h" | 34 #include "mutex.h" |
35 #include "putilimp.h" | 35 #include "putilimp.h" |
36 #include "uassert.h" | 36 #include "uassert.h" |
| 37 #include "digitinterval.h" |
37 #include <stdlib.h> | 38 #include <stdlib.h> |
38 #include <limits.h> | 39 #include <limits.h> |
39 #include <string.h> | 40 #include <string.h> |
40 #include <stdio.h> | 41 #include <stdio.h> |
41 #include <limits> | 42 #include <limits> |
42 | 43 |
43 // *************************************************************************** | 44 // *************************************************************************** |
44 // class DigitList | 45 // class DigitList |
45 // A wrapper onto decNumber. | 46 // A wrapper onto decNumber. |
46 // Used to be standalone. | 47 // Used to be standalone. |
(...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
389 fDecNumber->digits++; | 390 fDecNumber->digits++; |
390 // DigitList emulation - appending doesn't change the magnitude of e
xisting | 391 // DigitList emulation - appending doesn't change the magnitude of e
xisting |
391 // digits. With decNumber's decimal being aft
er the | 392 // digits. With decNumber's decimal being aft
er the |
392 // least signficant digit, we need to adjust t
he exponent. | 393 // least signficant digit, we need to adjust t
he exponent. |
393 fDecNumber->exponent--; | 394 fDecNumber->exponent--; |
394 } | 395 } |
395 } | 396 } |
396 internalClear(); | 397 internalClear(); |
397 } | 398 } |
398 | 399 |
| 400 char DigitList::getStrtodDecimalSeparator() { |
| 401 // TODO: maybe use andy's pthread once. |
| 402 static char gDecimal = 0; |
| 403 char result; |
| 404 { |
| 405 Mutex mutex; |
| 406 result = gDecimal;; |
| 407 if (result == 0) { |
| 408 // We need to know the decimal separator character that will be used
with strtod(). |
| 409 // Depends on the C runtime global locale. |
| 410 // Most commonly is '.' |
| 411 // TODO: caching could fail if the global locale is changed on the f
ly. |
| 412 char rep[MAX_DIGITS]; |
| 413 sprintf(rep, "%+1.1f", 1.0); |
| 414 result = rep[2]; |
| 415 gDecimal = result;; |
| 416 } |
| 417 } |
| 418 return result; |
| 419 } |
| 420 |
399 // ------------------------------------- | 421 // ------------------------------------- |
400 | 422 |
401 /** | 423 /** |
402 * Currently, getDouble() depends on strtod() to do its conversion. | 424 * Currently, getDouble() depends on strtod() to do its conversion. |
403 * | 425 * |
404 * WARNING!! | 426 * WARNING!! |
405 * This is an extremely costly function. ~1/2 of the conversion time | 427 * This is an extremely costly function. ~1/2 of the conversion time |
406 * can be linked to this function. | 428 * can be linked to this function. |
407 */ | 429 */ |
408 double | 430 double |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
485 | 507 |
486 // ------------------------------------- | 508 // ------------------------------------- |
487 | 509 |
488 /** | 510 /** |
489 * convert this number to an int32_t. Round if there is a fractional part. | 511 * convert this number to an int32_t. Round if there is a fractional part. |
490 * Return zero if the number cannot be represented. | 512 * Return zero if the number cannot be represented. |
491 */ | 513 */ |
492 int32_t DigitList::getLong() /*const*/ | 514 int32_t DigitList::getLong() /*const*/ |
493 { | 515 { |
494 int32_t result = 0; | 516 int32_t result = 0; |
495 if (fDecNumber->digits + fDecNumber->exponent > 10) { | 517 if (getUpperExponent() > 10) { |
496 // Overflow, absolute value too big. | 518 // Overflow, absolute value too big. |
497 return result; | 519 return result; |
498 } | 520 } |
499 if (fDecNumber->exponent != 0) { | 521 if (fDecNumber->exponent != 0) { |
500 // Force to an integer, with zero exponent, rounding if necessary. | 522 // Force to an integer, with zero exponent, rounding if necessary. |
501 // (decNumberToInt32 will only work if the exponent is exactly zero.) | 523 // (decNumberToInt32 will only work if the exponent is exactly zero.) |
502 DigitList copy(*this); | 524 DigitList copy(*this); |
503 DigitList zero; | 525 DigitList zero; |
504 uprv_decNumberQuantize(copy.fDecNumber, copy.fDecNumber, zero.fDecNumber
, &fContext); | 526 uprv_decNumberQuantize(copy.fDecNumber, copy.fDecNumber, zero.fDecNumber
, &fContext); |
505 result = uprv_decNumberToInt32(copy.fDecNumber, &fContext); | 527 result = uprv_decNumberToInt32(copy.fDecNumber, &fContext); |
506 } else { | 528 } else { |
507 result = uprv_decNumberToInt32(fDecNumber, &fContext); | 529 result = uprv_decNumberToInt32(fDecNumber, &fContext); |
508 } | 530 } |
509 return result; | 531 return result; |
510 } | 532 } |
511 | 533 |
512 | 534 |
513 /** | 535 /** |
514 * convert this number to an int64_t. Truncate if there is a fractional part. | 536 * convert this number to an int64_t. Truncate if there is a fractional part. |
515 * Return zero if the number cannot be represented. | 537 * Return zero if the number cannot be represented. |
516 */ | 538 */ |
517 int64_t DigitList::getInt64() /*const*/ { | 539 int64_t DigitList::getInt64() /*const*/ { |
518 if(fHave==kInt64) { | 540 if(fHave==kInt64) { |
519 return fUnion.fInt64; | 541 return fUnion.fInt64; |
520 } | 542 } |
521 // Truncate if non-integer. | 543 // Truncate if non-integer. |
522 // Return 0 if out of range. | 544 // Return 0 if out of range. |
523 // Range of in64_t is -9223372036854775808 to 9223372036854775807 (19 digit
s) | 545 // Range of in64_t is -9223372036854775808 to 9223372036854775807 (19 digit
s) |
524 // | 546 // |
525 if (fDecNumber->digits + fDecNumber->exponent > 19) { | 547 if (getUpperExponent() > 19) { |
526 // Overflow, absolute value too big. | 548 // Overflow, absolute value too big. |
527 return 0; | 549 return 0; |
528 } | 550 } |
529 | 551 |
530 // The number of integer digits may differ from the number of digits stored | 552 // The number of integer digits may differ from the number of digits stored |
531 // in the decimal number. | 553 // in the decimal number. |
532 // for 12.345 numIntDigits = 2, number->digits = 5 | 554 // for 12.345 numIntDigits = 2, number->digits = 5 |
533 // for 12E4 numIntDigits = 6, number->digits = 2 | 555 // for 12E4 numIntDigits = 6, number->digits = 2 |
534 // The conversion ignores the fraction digits in the first case, | 556 // The conversion ignores the fraction digits in the first case, |
535 // and fakes up extra zero digits in the second. | 557 // and fakes up extra zero digits in the second. |
536 // TODO: It would be faster to store a table of powers of ten to multiply b
y | 558 // TODO: It would be faster to store a table of powers of ten to multiply b
y |
537 // instead of looping over zero digits, multiplying each time. | 559 // instead of looping over zero digits, multiplying each time. |
538 | 560 |
539 int32_t numIntDigits = fDecNumber->digits + fDecNumber->exponent; | 561 int32_t numIntDigits = getUpperExponent(); |
540 uint64_t value = 0; | 562 uint64_t value = 0; |
541 for (int32_t i = 0; i < numIntDigits; i++) { | 563 for (int32_t i = 0; i < numIntDigits; i++) { |
542 // Loop is iterating over digits starting with the most significant. | 564 // Loop is iterating over digits starting with the most significant. |
543 // Numbers are stored with the least significant digit at index zero. | 565 // Numbers are stored with the least significant digit at index zero. |
544 int32_t digitIndex = fDecNumber->digits - i - 1; | 566 int32_t digitIndex = fDecNumber->digits - i - 1; |
545 int32_t v = (digitIndex >= 0) ? fDecNumber->lsu[digitIndex] : 0; | 567 int32_t v = (digitIndex >= 0) ? fDecNumber->lsu[digitIndex] : 0; |
546 value = value * (uint64_t)10 + (uint64_t)v; | 568 value = value * (uint64_t)10 + (uint64_t)v; |
547 } | 569 } |
548 | 570 |
549 if (decNumberIsNegative(fDecNumber)) { | 571 if (decNumberIsNegative(fDecNumber)) { |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
604 uprv_decNumberTrim(this->fDecNumber); | 626 uprv_decNumberTrim(this->fDecNumber); |
605 if (fDecNumber->exponent < 0) { | 627 if (fDecNumber->exponent < 0) { |
606 // Number contains fraction digits. | 628 // Number contains fraction digits. |
607 return FALSE; | 629 return FALSE; |
608 } | 630 } |
609 if (decNumberIsZero(this->fDecNumber) && !ignoreNegativeZero && | 631 if (decNumberIsZero(this->fDecNumber) && !ignoreNegativeZero && |
610 (fDecNumber->bits & DECNEG) != 0) { | 632 (fDecNumber->bits & DECNEG) != 0) { |
611 // Negative Zero, not ingored. Cannot represent as a long. | 633 // Negative Zero, not ingored. Cannot represent as a long. |
612 return FALSE; | 634 return FALSE; |
613 } | 635 } |
614 if (fDecNumber->digits + fDecNumber->exponent < 10) { | 636 if (getUpperExponent() < 10) { |
615 // The number is 9 or fewer digits. | 637 // The number is 9 or fewer digits. |
616 // The max and min int32 are 10 digts, so this number fits. | 638 // The max and min int32 are 10 digts, so this number fits. |
617 // This is the common case. | 639 // This is the common case. |
618 return TRUE; | 640 return TRUE; |
619 } | 641 } |
620 | 642 |
621 // TODO: Should cache these constants; construction is relatively costly. | 643 // TODO: Should cache these constants; construction is relatively costly. |
622 // But not of huge consequence; they're only needed for 10 digit ints
. | 644 // But not of huge consequence; they're only needed for 10 digit ints
. |
623 UErrorCode status = U_ZERO_ERROR; | 645 UErrorCode status = U_ZERO_ERROR; |
624 DigitList min32; min32.set("-2147483648", status); | 646 DigitList min32; min32.set("-2147483648", status); |
(...skipping 26 matching lines...) Expand all Loading... |
651 uprv_decNumberTrim(this->fDecNumber); | 673 uprv_decNumberTrim(this->fDecNumber); |
652 if (fDecNumber->exponent < 0) { | 674 if (fDecNumber->exponent < 0) { |
653 // Number contains fraction digits. | 675 // Number contains fraction digits. |
654 return FALSE; | 676 return FALSE; |
655 } | 677 } |
656 if (decNumberIsZero(this->fDecNumber) && !ignoreNegativeZero && | 678 if (decNumberIsZero(this->fDecNumber) && !ignoreNegativeZero && |
657 (fDecNumber->bits & DECNEG) != 0) { | 679 (fDecNumber->bits & DECNEG) != 0) { |
658 // Negative Zero, not ingored. Cannot represent as a long. | 680 // Negative Zero, not ingored. Cannot represent as a long. |
659 return FALSE; | 681 return FALSE; |
660 } | 682 } |
661 if (fDecNumber->digits + fDecNumber->exponent < 19) { | 683 if (getUpperExponent() < 19) { |
662 // The number is 18 or fewer digits. | 684 // The number is 18 or fewer digits. |
663 // The max and min int64 are 19 digts, so this number fits. | 685 // The max and min int64 are 19 digts, so this number fits. |
664 // This is the common case. | 686 // This is the common case. |
665 return TRUE; | 687 return TRUE; |
666 } | 688 } |
667 | 689 |
668 // TODO: Should cache these constants; construction is relatively costly. | 690 // TODO: Should cache these constants; construction is relatively costly. |
669 // But not of huge consequence; they're only needed for 19 digit ints
. | 691 // But not of huge consequence; they're only needed for 19 digit ints
. |
670 UErrorCode status = U_ZERO_ERROR; | 692 UErrorCode status = U_ZERO_ERROR; |
671 DigitList min64; min64.set("-9223372036854775808", status); | 693 DigitList min64; min64.set("-9223372036854775808", status); |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
825 // ------------------------------------- | 847 // ------------------------------------- |
826 | 848 |
827 /* | 849 /* |
828 * Multiply | 850 * Multiply |
829 * The number will be expanded if need be to retain full precision. | 851 * The number will be expanded if need be to retain full precision. |
830 * In practice, for formatting, multiply is by 10, 100 or 1000, so more dig
its | 852 * In practice, for formatting, multiply is by 10, 100 or 1000, so more dig
its |
831 * will not be required for this use. | 853 * will not be required for this use. |
832 */ | 854 */ |
833 void | 855 void |
834 DigitList::mult(const DigitList &other, UErrorCode &status) { | 856 DigitList::mult(const DigitList &other, UErrorCode &status) { |
| 857 if (U_FAILURE(status)) { |
| 858 return; |
| 859 } |
835 fContext.status = 0; | 860 fContext.status = 0; |
836 int32_t requiredDigits = this->digits() + other.digits(); | 861 int32_t requiredDigits = this->digits() + other.digits(); |
837 if (requiredDigits > fContext.digits) { | 862 if (requiredDigits > fContext.digits) { |
838 reduce(); // Remove any trailing zeros | 863 reduce(); // Remove any trailing zeros |
839 int32_t requiredDigits = this->digits() + other.digits(); | 864 int32_t requiredDigits = this->digits() + other.digits(); |
840 ensureCapacity(requiredDigits, status); | 865 ensureCapacity(requiredDigits, status); |
841 } | 866 } |
842 uprv_decNumberMultiply(fDecNumber, fDecNumber, other.fDecNumber, &fContext); | 867 uprv_decNumberMultiply(fDecNumber, fDecNumber, other.fDecNumber, &fContext); |
843 internalClear(); | 868 internalClear(); |
844 } | 869 } |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
895 // ------------------------------------- | 920 // ------------------------------------- |
896 | 921 |
897 /** | 922 /** |
898 * Round the representation to the given number of digits. | 923 * Round the representation to the given number of digits. |
899 * @param maximumDigits The maximum number of digits to be shown. | 924 * @param maximumDigits The maximum number of digits to be shown. |
900 * Upon return, count will be less than or equal to maximumDigits. | 925 * Upon return, count will be less than or equal to maximumDigits. |
901 */ | 926 */ |
902 void | 927 void |
903 DigitList::round(int32_t maximumDigits) | 928 DigitList::round(int32_t maximumDigits) |
904 { | 929 { |
| 930 reduce(); |
| 931 if (maximumDigits >= fDecNumber->digits) { |
| 932 return; |
| 933 } |
905 int32_t savedDigits = fContext.digits; | 934 int32_t savedDigits = fContext.digits; |
906 fContext.digits = maximumDigits; | 935 fContext.digits = maximumDigits; |
907 uprv_decNumberPlus(fDecNumber, fDecNumber, &fContext); | 936 uprv_decNumberPlus(fDecNumber, fDecNumber, &fContext); |
908 fContext.digits = savedDigits; | 937 fContext.digits = savedDigits; |
909 uprv_decNumberTrim(fDecNumber); | 938 uprv_decNumberTrim(fDecNumber); |
| 939 reduce(); |
910 internalClear(); | 940 internalClear(); |
911 } | 941 } |
912 | 942 |
913 | 943 |
914 void | 944 void |
915 DigitList::roundFixedPoint(int32_t maximumFractionDigits) { | 945 DigitList::roundFixedPoint(int32_t maximumFractionDigits) { |
916 trim(); // Remove trailing zeros. | 946 reduce(); // Remove trailing zeros. |
917 if (fDecNumber->exponent >= -maximumFractionDigits) { | 947 if (fDecNumber->exponent >= -maximumFractionDigits) { |
918 return; | 948 return; |
919 } | 949 } |
920 decNumber scale; // Dummy decimal number, but with the desired number of | 950 decNumber scale; // Dummy decimal number, but with the desired number of |
921 uprv_decNumberZero(&scale); // fraction digits. | 951 uprv_decNumberZero(&scale); // fraction digits. |
922 scale.exponent = -maximumFractionDigits; | 952 scale.exponent = -maximumFractionDigits; |
923 scale.lsu[0] = 1; | 953 scale.lsu[0] = 1; |
924 | 954 |
925 uprv_decNumberQuantize(fDecNumber, fDecNumber, &scale, &fContext); | 955 uprv_decNumberQuantize(fDecNumber, fDecNumber, &scale, &fContext); |
926 trim(); | 956 reduce(); |
927 internalClear(); | 957 internalClear(); |
928 } | 958 } |
929 | 959 |
930 // ------------------------------------- | 960 // ------------------------------------- |
931 | 961 |
932 void | 962 void |
933 DigitList::toIntegralValue() { | 963 DigitList::toIntegralValue() { |
934 uprv_decNumberToIntegralValue(fDecNumber, fDecNumber, &fContext); | 964 uprv_decNumberToIntegralValue(fDecNumber, fDecNumber, &fContext); |
935 } | 965 } |
936 | 966 |
937 | 967 |
938 // ------------------------------------- | 968 // ------------------------------------- |
939 UBool | 969 UBool |
940 DigitList::isZero() const | 970 DigitList::isZero() const |
941 { | 971 { |
942 return decNumberIsZero(fDecNumber); | 972 return decNumberIsZero(fDecNumber); |
943 } | 973 } |
944 | 974 |
| 975 // ------------------------------------- |
| 976 int32_t |
| 977 DigitList::getUpperExponent() const { |
| 978 return fDecNumber->digits + fDecNumber->exponent; |
| 979 } |
| 980 |
| 981 DigitInterval & |
| 982 DigitList::getSmallestInterval(DigitInterval &result) const { |
| 983 result.setLeastSignificantInclusive(fDecNumber->exponent); |
| 984 result.setMostSignificantExclusive(getUpperExponent()); |
| 985 return result; |
| 986 } |
| 987 |
| 988 uint8_t |
| 989 DigitList::getDigitByExponent(int32_t exponent) const { |
| 990 int32_t idx = exponent - fDecNumber->exponent; |
| 991 if (idx < 0 || idx >= fDecNumber->digits) { |
| 992 return 0; |
| 993 } |
| 994 return fDecNumber->lsu[idx]; |
| 995 } |
| 996 |
| 997 void |
| 998 DigitList::appendDigitsTo(CharString &str, UErrorCode &status) const { |
| 999 str.append((const char *) fDecNumber->lsu, fDecNumber->digits, status); |
| 1000 } |
| 1001 |
| 1002 void |
| 1003 DigitList::roundAtExponent(int32_t exponent, int32_t maxSigDigits) { |
| 1004 reduce(); |
| 1005 if (maxSigDigits < fDecNumber->digits) { |
| 1006 int32_t minExponent = getUpperExponent() - maxSigDigits; |
| 1007 if (exponent < minExponent) { |
| 1008 exponent = minExponent; |
| 1009 } |
| 1010 } |
| 1011 if (exponent <= fDecNumber->exponent) { |
| 1012 return; |
| 1013 } |
| 1014 int32_t digits = getUpperExponent() - exponent; |
| 1015 if (digits > 0) { |
| 1016 round(digits); |
| 1017 } else { |
| 1018 roundFixedPoint(-exponent); |
| 1019 } |
| 1020 } |
| 1021 |
| 1022 void |
| 1023 DigitList::quantize(const DigitList &quantity, UErrorCode &status) { |
| 1024 if (U_FAILURE(status)) { |
| 1025 return; |
| 1026 } |
| 1027 div(quantity, status); |
| 1028 roundAtExponent(0); |
| 1029 mult(quantity, status); |
| 1030 reduce(); |
| 1031 } |
| 1032 |
| 1033 int32_t |
| 1034 DigitList::getScientificExponent( |
| 1035 int32_t minIntDigitCount, int32_t exponentMultiplier) const { |
| 1036 // The exponent for zero is always zero. |
| 1037 if (isZero()) { |
| 1038 return 0; |
| 1039 } |
| 1040 int32_t intDigitCount = getUpperExponent(); |
| 1041 int32_t exponent; |
| 1042 if (intDigitCount >= minIntDigitCount) { |
| 1043 int32_t maxAdjustment = intDigitCount - minIntDigitCount; |
| 1044 exponent = (maxAdjustment / exponentMultiplier) * exponentMultiplier; |
| 1045 } else { |
| 1046 int32_t minAdjustment = minIntDigitCount - intDigitCount; |
| 1047 exponent = ((minAdjustment + exponentMultiplier - 1) / exponentMultiplie
r) * -exponentMultiplier; |
| 1048 } |
| 1049 return exponent; |
| 1050 } |
| 1051 |
| 1052 int32_t |
| 1053 DigitList::toScientific( |
| 1054 int32_t minIntDigitCount, int32_t exponentMultiplier) { |
| 1055 int32_t exponent = getScientificExponent( |
| 1056 minIntDigitCount, exponentMultiplier); |
| 1057 shiftDecimalRight(-exponent); |
| 1058 return exponent; |
| 1059 } |
| 1060 |
| 1061 void |
| 1062 DigitList::shiftDecimalRight(int32_t n) { |
| 1063 fDecNumber->exponent += n; |
| 1064 internalClear(); |
| 1065 } |
| 1066 |
945 U_NAMESPACE_END | 1067 U_NAMESPACE_END |
946 #endif // #if !UCONFIG_NO_FORMATTING | 1068 #endif // #if !UCONFIG_NO_FORMATTING |
947 | 1069 |
948 //eof | 1070 //eof |
OLD | NEW |