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