1 // Copyright (C) 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 double VisibleDigits::computeAbsDoubleValue() const { 80 // Take care of NaN and infinity 81 if (isNaN()) { 82 return uprv_getNaN(); 83 } 84 if (isInfinite()) { 85 return uprv_getInfinity(); 86 } 87 88 // stack allocate a decNumber to hold MAX_DBL_DIGITS+3 significant digits 89 struct { 90 decNumber decNum; 91 char digits[MAX_DBL_DIGITS+3]; 92 } decNumberWithStorage; 93 decNumber *numberPtr = &decNumberWithStorage.decNum; 94 95 int32_t mostSig = fInterval.getMostSignificantExclusive(); 96 int32_t mostSigNonZero = fExponent + fDigits.length(); 97 int32_t end = mostSig > mostSigNonZero ? mostSigNonZero : mostSig; 98 int32_t leastSig = fInterval.getLeastSignificantInclusive(); 99 int32_t start = leastSig > fExponent ? leastSig : fExponent; 100 if (end <= start) { 101 return 0.0; 102 } 103 if (start < end - (MAX_DBL_DIGITS+3)) { 104 start = end - (MAX_DBL_DIGITS+3); 105 } 106 uint8_t *pos = numberPtr->lsu; 107 const char *src = &(fDigits.data()[start - fExponent]); 108 for (int32_t i = start; i < end; ++i) { 109 *pos++ = (uint8_t) (*src++); 110 } 111 numberPtr->exponent = start; 112 numberPtr->bits = 0; 113 numberPtr->digits = end - start; 114 char str[MAX_DBL_DIGITS+18]; 115 uprv_decNumberToString(numberPtr, str); 116 U_ASSERT(uprv_strlen(str) < MAX_DBL_DIGITS+18); 117 char *unused = NULL; 118 return DigitList::decimalStrToDouble(str, &unused); 119 } 120 121 void VisibleDigits::getFixedDecimal( 122 double &source, int64_t &intValue, int64_t &f, int64_t &t, int32_t &v, UBool &hasIntValue) const { 123 source = 0.0; 124 intValue = 0; 125 f = 0; 126 t = 0; 127 v = 0; 128 hasIntValue = FALSE; 129 if (isNaNOrInfinity()) { 130 return; 131 } 132 133 // source 134 if (fAbsDoubleValueSet) { 135 source = fAbsDoubleValue; 136 } else { 137 source = computeAbsDoubleValue(); 138 } 139 140 // visible decimal digits 141 v = fInterval.getFracDigitCount(); 142 143 // intValue 144 145 // If we initialized from an int64 just use that instead of 146 // calculating 147 if (fAbsIntValueSet) { 148 intValue = fAbsIntValue; 149 } else { 150 int32_t startPos = fInterval.getMostSignificantExclusive(); 151 if (startPos > 18) { 152 startPos = 18; 153 } 154 // process the integer digits 155 for (int32_t i = startPos - 1; i >= 0; --i) { 156 intValue = intValue * 10LL + getDigitByExponent(i); 157 } 158 if (intValue == 0LL && startPos > 0) { 159 intValue = 100000000000000000LL; 160 } 161 } 162 163 // f (decimal digits) 164 // skip over any leading 0's in fraction digits. 165 int32_t idx = -1; 166 for (; idx >= -v && getDigitByExponent(idx) == 0; --idx) 167 ; 168 169 // Only process up to first 18 non zero fraction digits for decimalDigits 170 // since that is all we can fit into an int64. 171 for (int32_t i = idx; i >= -v && i > idx - 18; --i) { 172 f = f * 10LL + getDigitByExponent(i); 173 } 174 175 // If we have no decimal digits, we don't have an integer value 176 hasIntValue = (f == 0LL); 177 178 // t (decimal digits without trailing zeros) 179 t = f; 180 while (t > 0 && t % 10LL == 0) { 181 t /= 10; 182 } 183 } 184 185 U_NAMESPACE_END 186 #endif /* #if !UCONFIG_NO_FORMATTING */ 187