Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(107)

Side by Side Diff: source/i18n/digitlst.cpp

Issue 1621843002: ICU 56 update step 1 (Closed) Base URL: https://chromium.googlesource.com/chromium/deps/icu.git@561
Patch Set: Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « source/i18n/digitlst.h ('k') | source/i18n/dtfmtsym.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « source/i18n/digitlst.h ('k') | source/i18n/dtfmtsym.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698