]> git.saurik.com Git - apple/icu.git/blob - icuSources/i18n/visibledigits.cpp
ICU-62107.0.1.tar.gz
[apple/icu.git] / icuSources / i18n / visibledigits.cpp
1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /*
4 * Copyright (C) 2016, International Business Machines
5 * Corporation and others. All Rights Reserved.
6 *
7 * file name: visibledigits.cpp
8 */
9
10 #include <math.h>
11
12 #include "unicode/utypes.h"
13
14 #if !UCONFIG_NO_FORMATTING
15
16 #include "cstring.h"
17 #include "decNumber.h"
18 #include "digitlst.h"
19 #include "uassert.h"
20 #include "visibledigits.h"
21
22 static const int32_t kNegative = 1;
23 static const int32_t kInfinite = 2;
24 static const int32_t kNaN = 4;
25
26 U_NAMESPACE_BEGIN
27
28 void VisibleDigits::setNegative() {
29 fFlags |= kNegative;
30 }
31
32 void VisibleDigits::setNaN() {
33 fFlags |= kNaN;
34 }
35
36 void VisibleDigits::setInfinite() {
37 fFlags |= kInfinite;
38 }
39
40 void VisibleDigits::clear() {
41 fInterval.clear();
42 fDigits.clear();
43 fExponent = 0;
44 fFlags = 0;
45 fAbsIntValue = 0LL;
46 fAbsIntValueSet = FALSE;
47 fAbsDoubleValue = 0.0;
48 fAbsDoubleValueSet = FALSE;
49 }
50
51 UBool VisibleDigits::isNegative() const {
52 return (fFlags & kNegative);
53 }
54
55 UBool VisibleDigits::isNaN() const {
56 return (fFlags & kNaN);
57 }
58
59 UBool VisibleDigits::isInfinite() const {
60 return (fFlags & kInfinite);
61 }
62
63 int32_t VisibleDigits::getDigitByExponent(int32_t digitPos) const {
64 if (digitPos < fExponent || digitPos >= fExponent + fDigits.length()) {
65 return 0;
66 }
67 const char *ptr = fDigits.data();
68 return ptr[digitPos - fExponent];
69 }
70
71 UBool VisibleDigits::isOverMaxDigits() const {
72 return (fExponent + fDigits.length() > fInterval.getMostSignificantExclusive());
73 }
74
75 UBool VisibleDigits::isNaNOrInfinity() const {
76 return (fFlags & (kInfinite | kNaN)) != 0;
77 }
78
79 UBool VisibleDigits::formatFullPrecision() const { // Apple
80 return fFormatFullPrecision;
81 }
82 void VisibleDigits::setFormatFullPrecision(UBool formatFullPrecision) { // Apple
83 fFormatFullPrecision = formatFullPrecision;
84 }
85
86 double VisibleDigits::computeAbsDoubleValue() const {
87 // Take care of NaN and infinity
88 if (isNaN()) {
89 return uprv_getNaN();
90 }
91 if (isInfinite()) {
92 return uprv_getInfinity();
93 }
94
95 // stack allocate a decNumber to hold MAX_DBL_DIGITS+3 significant digits
96 struct {
97 decNumber decNum;
98 char digits[MAX_DBL_DIGITS+3];
99 } decNumberWithStorage;
100 decNumber *numberPtr = &decNumberWithStorage.decNum;
101
102 int32_t mostSig = fInterval.getMostSignificantExclusive();
103 int32_t mostSigNonZero = fExponent + fDigits.length();
104 int32_t end = mostSig > mostSigNonZero ? mostSigNonZero : mostSig;
105 int32_t leastSig = fInterval.getLeastSignificantInclusive();
106 int32_t start = leastSig > fExponent ? leastSig : fExponent;
107 if (end <= start) {
108 return 0.0;
109 }
110 if (start < end - (MAX_DBL_DIGITS+3)) {
111 start = end - (MAX_DBL_DIGITS+3);
112 }
113 uint8_t *pos = numberPtr->lsu;
114 const char *src = &(fDigits.data()[start - fExponent]);
115 for (int32_t i = start; i < end; ++i) {
116 *pos++ = (uint8_t) (*src++);
117 }
118 numberPtr->exponent = start;
119 numberPtr->bits = 0;
120 numberPtr->digits = end - start;
121 char str[MAX_DBL_DIGITS+18];
122 uprv_decNumberToString(numberPtr, str);
123 U_ASSERT(uprv_strlen(str) < MAX_DBL_DIGITS+18);
124 char *unused = NULL;
125 return DigitList::decimalStrToDouble(str, &unused);
126 }
127
128 void VisibleDigits::getFixedDecimal(
129 double &source, int64_t &intValue, int64_t &f, int64_t &t, int32_t &v, UBool &hasIntValue) const {
130 source = 0.0;
131 intValue = 0;
132 f = 0;
133 t = 0;
134 v = 0;
135 hasIntValue = FALSE;
136 if (isNaNOrInfinity()) {
137 return;
138 }
139
140 // source
141 if (fAbsDoubleValueSet) {
142 source = fAbsDoubleValue;
143 } else {
144 source = computeAbsDoubleValue();
145 }
146
147 // visible decimal digits
148 v = fInterval.getFracDigitCount();
149
150 // intValue
151
152 // If we initialized from an int64 just use that instead of
153 // calculating
154 if (fAbsIntValueSet) {
155 intValue = fAbsIntValue;
156 } else {
157 int32_t startPos = fInterval.getMostSignificantExclusive();
158 if (startPos > 18) {
159 startPos = 18;
160 }
161 // process the integer digits
162 for (int32_t i = startPos - 1; i >= 0; --i) {
163 intValue = intValue * 10LL + getDigitByExponent(i);
164 }
165 if (intValue == 0LL && startPos > 0) {
166 intValue = 100000000000000000LL;
167 }
168 }
169
170 // f (decimal digits)
171 // skip over any leading 0's in fraction digits.
172 int32_t idx = -1;
173 for (; idx >= -v && getDigitByExponent(idx) == 0; --idx)
174 ;
175
176 // Only process up to first 18 non zero fraction digits for decimalDigits
177 // since that is all we can fit into an int64.
178 for (int32_t i = idx; i >= -v && i > idx - 18; --i) {
179 f = f * 10LL + getDigitByExponent(i);
180 }
181
182 // If we have no decimal digits, we don't have an integer value
183 hasIntValue = (f == 0LL);
184
185 // t (decimal digits without trailing zeros)
186 t = f;
187 while (t > 0 && t % 10LL == 0) {
188 t /= 10;
189 }
190 }
191
192 U_NAMESPACE_END
193 #endif /* #if !UCONFIG_NO_FORMATTING */