Maxim Integrated / Mbed OS MAXREFDES155#

Dependencies:   MaximInterface

Committer:
IanBenzMaxim
Date:
Fri Feb 24 11:23:12 2017 -0600
Revision:
0:33d4e66780c0
Initial commit.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
IanBenzMaxim 0:33d4e66780c0 1 // Tencent is pleased to support the open source community by making RapidJSON available.
IanBenzMaxim 0:33d4e66780c0 2 //
IanBenzMaxim 0:33d4e66780c0 3 // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
IanBenzMaxim 0:33d4e66780c0 4 //
IanBenzMaxim 0:33d4e66780c0 5 // Licensed under the MIT License (the "License"); you may not use this file except
IanBenzMaxim 0:33d4e66780c0 6 // in compliance with the License. You may obtain a copy of the License at
IanBenzMaxim 0:33d4e66780c0 7 //
IanBenzMaxim 0:33d4e66780c0 8 // http://opensource.org/licenses/MIT
IanBenzMaxim 0:33d4e66780c0 9 //
IanBenzMaxim 0:33d4e66780c0 10 // Unless required by applicable law or agreed to in writing, software distributed
IanBenzMaxim 0:33d4e66780c0 11 // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
IanBenzMaxim 0:33d4e66780c0 12 // CONDITIONS OF ANY KIND, either express or implied. See the License for the
IanBenzMaxim 0:33d4e66780c0 13 // specific language governing permissions and limitations under the License.
IanBenzMaxim 0:33d4e66780c0 14
IanBenzMaxim 0:33d4e66780c0 15 #ifndef RAPIDJSON_STRTOD_
IanBenzMaxim 0:33d4e66780c0 16 #define RAPIDJSON_STRTOD_
IanBenzMaxim 0:33d4e66780c0 17
IanBenzMaxim 0:33d4e66780c0 18 #include "ieee754.h"
IanBenzMaxim 0:33d4e66780c0 19 #include "biginteger.h"
IanBenzMaxim 0:33d4e66780c0 20 #include "diyfp.h"
IanBenzMaxim 0:33d4e66780c0 21 #include "pow10.h"
IanBenzMaxim 0:33d4e66780c0 22
IanBenzMaxim 0:33d4e66780c0 23 RAPIDJSON_NAMESPACE_BEGIN
IanBenzMaxim 0:33d4e66780c0 24 namespace internal {
IanBenzMaxim 0:33d4e66780c0 25
IanBenzMaxim 0:33d4e66780c0 26 inline double FastPath(double significand, int exp) {
IanBenzMaxim 0:33d4e66780c0 27 if (exp < -308)
IanBenzMaxim 0:33d4e66780c0 28 return 0.0;
IanBenzMaxim 0:33d4e66780c0 29 else if (exp >= 0)
IanBenzMaxim 0:33d4e66780c0 30 return significand * internal::Pow10(exp);
IanBenzMaxim 0:33d4e66780c0 31 else
IanBenzMaxim 0:33d4e66780c0 32 return significand / internal::Pow10(-exp);
IanBenzMaxim 0:33d4e66780c0 33 }
IanBenzMaxim 0:33d4e66780c0 34
IanBenzMaxim 0:33d4e66780c0 35 inline double StrtodNormalPrecision(double d, int p) {
IanBenzMaxim 0:33d4e66780c0 36 if (p < -308) {
IanBenzMaxim 0:33d4e66780c0 37 // Prevent expSum < -308, making Pow10(p) = 0
IanBenzMaxim 0:33d4e66780c0 38 d = FastPath(d, -308);
IanBenzMaxim 0:33d4e66780c0 39 d = FastPath(d, p + 308);
IanBenzMaxim 0:33d4e66780c0 40 }
IanBenzMaxim 0:33d4e66780c0 41 else
IanBenzMaxim 0:33d4e66780c0 42 d = FastPath(d, p);
IanBenzMaxim 0:33d4e66780c0 43 return d;
IanBenzMaxim 0:33d4e66780c0 44 }
IanBenzMaxim 0:33d4e66780c0 45
IanBenzMaxim 0:33d4e66780c0 46 template <typename T>
IanBenzMaxim 0:33d4e66780c0 47 inline T Min3(T a, T b, T c) {
IanBenzMaxim 0:33d4e66780c0 48 T m = a;
IanBenzMaxim 0:33d4e66780c0 49 if (m > b) m = b;
IanBenzMaxim 0:33d4e66780c0 50 if (m > c) m = c;
IanBenzMaxim 0:33d4e66780c0 51 return m;
IanBenzMaxim 0:33d4e66780c0 52 }
IanBenzMaxim 0:33d4e66780c0 53
IanBenzMaxim 0:33d4e66780c0 54 inline int CheckWithinHalfULP(double b, const BigInteger& d, int dExp) {
IanBenzMaxim 0:33d4e66780c0 55 const Double db(b);
IanBenzMaxim 0:33d4e66780c0 56 const uint64_t bInt = db.IntegerSignificand();
IanBenzMaxim 0:33d4e66780c0 57 const int bExp = db.IntegerExponent();
IanBenzMaxim 0:33d4e66780c0 58 const int hExp = bExp - 1;
IanBenzMaxim 0:33d4e66780c0 59
IanBenzMaxim 0:33d4e66780c0 60 int dS_Exp2 = 0, dS_Exp5 = 0, bS_Exp2 = 0, bS_Exp5 = 0, hS_Exp2 = 0, hS_Exp5 = 0;
IanBenzMaxim 0:33d4e66780c0 61
IanBenzMaxim 0:33d4e66780c0 62 // Adjust for decimal exponent
IanBenzMaxim 0:33d4e66780c0 63 if (dExp >= 0) {
IanBenzMaxim 0:33d4e66780c0 64 dS_Exp2 += dExp;
IanBenzMaxim 0:33d4e66780c0 65 dS_Exp5 += dExp;
IanBenzMaxim 0:33d4e66780c0 66 }
IanBenzMaxim 0:33d4e66780c0 67 else {
IanBenzMaxim 0:33d4e66780c0 68 bS_Exp2 -= dExp;
IanBenzMaxim 0:33d4e66780c0 69 bS_Exp5 -= dExp;
IanBenzMaxim 0:33d4e66780c0 70 hS_Exp2 -= dExp;
IanBenzMaxim 0:33d4e66780c0 71 hS_Exp5 -= dExp;
IanBenzMaxim 0:33d4e66780c0 72 }
IanBenzMaxim 0:33d4e66780c0 73
IanBenzMaxim 0:33d4e66780c0 74 // Adjust for binary exponent
IanBenzMaxim 0:33d4e66780c0 75 if (bExp >= 0)
IanBenzMaxim 0:33d4e66780c0 76 bS_Exp2 += bExp;
IanBenzMaxim 0:33d4e66780c0 77 else {
IanBenzMaxim 0:33d4e66780c0 78 dS_Exp2 -= bExp;
IanBenzMaxim 0:33d4e66780c0 79 hS_Exp2 -= bExp;
IanBenzMaxim 0:33d4e66780c0 80 }
IanBenzMaxim 0:33d4e66780c0 81
IanBenzMaxim 0:33d4e66780c0 82 // Adjust for half ulp exponent
IanBenzMaxim 0:33d4e66780c0 83 if (hExp >= 0)
IanBenzMaxim 0:33d4e66780c0 84 hS_Exp2 += hExp;
IanBenzMaxim 0:33d4e66780c0 85 else {
IanBenzMaxim 0:33d4e66780c0 86 dS_Exp2 -= hExp;
IanBenzMaxim 0:33d4e66780c0 87 bS_Exp2 -= hExp;
IanBenzMaxim 0:33d4e66780c0 88 }
IanBenzMaxim 0:33d4e66780c0 89
IanBenzMaxim 0:33d4e66780c0 90 // Remove common power of two factor from all three scaled values
IanBenzMaxim 0:33d4e66780c0 91 int common_Exp2 = Min3(dS_Exp2, bS_Exp2, hS_Exp2);
IanBenzMaxim 0:33d4e66780c0 92 dS_Exp2 -= common_Exp2;
IanBenzMaxim 0:33d4e66780c0 93 bS_Exp2 -= common_Exp2;
IanBenzMaxim 0:33d4e66780c0 94 hS_Exp2 -= common_Exp2;
IanBenzMaxim 0:33d4e66780c0 95
IanBenzMaxim 0:33d4e66780c0 96 BigInteger dS = d;
IanBenzMaxim 0:33d4e66780c0 97 dS.MultiplyPow5(static_cast<unsigned>(dS_Exp5)) <<= static_cast<unsigned>(dS_Exp2);
IanBenzMaxim 0:33d4e66780c0 98
IanBenzMaxim 0:33d4e66780c0 99 BigInteger bS(bInt);
IanBenzMaxim 0:33d4e66780c0 100 bS.MultiplyPow5(static_cast<unsigned>(bS_Exp5)) <<= static_cast<unsigned>(bS_Exp2);
IanBenzMaxim 0:33d4e66780c0 101
IanBenzMaxim 0:33d4e66780c0 102 BigInteger hS(1);
IanBenzMaxim 0:33d4e66780c0 103 hS.MultiplyPow5(static_cast<unsigned>(hS_Exp5)) <<= static_cast<unsigned>(hS_Exp2);
IanBenzMaxim 0:33d4e66780c0 104
IanBenzMaxim 0:33d4e66780c0 105 BigInteger delta(0);
IanBenzMaxim 0:33d4e66780c0 106 dS.Difference(bS, &delta);
IanBenzMaxim 0:33d4e66780c0 107
IanBenzMaxim 0:33d4e66780c0 108 return delta.Compare(hS);
IanBenzMaxim 0:33d4e66780c0 109 }
IanBenzMaxim 0:33d4e66780c0 110
IanBenzMaxim 0:33d4e66780c0 111 inline bool StrtodFast(double d, int p, double* result) {
IanBenzMaxim 0:33d4e66780c0 112 // Use fast path for string-to-double conversion if possible
IanBenzMaxim 0:33d4e66780c0 113 // see http://www.exploringbinary.com/fast-path-decimal-to-floating-point-conversion/
IanBenzMaxim 0:33d4e66780c0 114 if (p > 22 && p < 22 + 16) {
IanBenzMaxim 0:33d4e66780c0 115 // Fast Path Cases In Disguise
IanBenzMaxim 0:33d4e66780c0 116 d *= internal::Pow10(p - 22);
IanBenzMaxim 0:33d4e66780c0 117 p = 22;
IanBenzMaxim 0:33d4e66780c0 118 }
IanBenzMaxim 0:33d4e66780c0 119
IanBenzMaxim 0:33d4e66780c0 120 if (p >= -22 && p <= 22 && d <= 9007199254740991.0) { // 2^53 - 1
IanBenzMaxim 0:33d4e66780c0 121 *result = FastPath(d, p);
IanBenzMaxim 0:33d4e66780c0 122 return true;
IanBenzMaxim 0:33d4e66780c0 123 }
IanBenzMaxim 0:33d4e66780c0 124 else
IanBenzMaxim 0:33d4e66780c0 125 return false;
IanBenzMaxim 0:33d4e66780c0 126 }
IanBenzMaxim 0:33d4e66780c0 127
IanBenzMaxim 0:33d4e66780c0 128 // Compute an approximation and see if it is within 1/2 ULP
IanBenzMaxim 0:33d4e66780c0 129 inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosition, int exp, double* result) {
IanBenzMaxim 0:33d4e66780c0 130 uint64_t significand = 0;
IanBenzMaxim 0:33d4e66780c0 131 size_t i = 0; // 2^64 - 1 = 18446744073709551615, 1844674407370955161 = 0x1999999999999999
IanBenzMaxim 0:33d4e66780c0 132 for (; i < length; i++) {
IanBenzMaxim 0:33d4e66780c0 133 if (significand > RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) ||
IanBenzMaxim 0:33d4e66780c0 134 (significand == RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) && decimals[i] > '5'))
IanBenzMaxim 0:33d4e66780c0 135 break;
IanBenzMaxim 0:33d4e66780c0 136 significand = significand * 10u + static_cast<unsigned>(decimals[i] - '0');
IanBenzMaxim 0:33d4e66780c0 137 }
IanBenzMaxim 0:33d4e66780c0 138
IanBenzMaxim 0:33d4e66780c0 139 if (i < length && decimals[i] >= '5') // Rounding
IanBenzMaxim 0:33d4e66780c0 140 significand++;
IanBenzMaxim 0:33d4e66780c0 141
IanBenzMaxim 0:33d4e66780c0 142 size_t remaining = length - i;
IanBenzMaxim 0:33d4e66780c0 143 const unsigned kUlpShift = 3;
IanBenzMaxim 0:33d4e66780c0 144 const unsigned kUlp = 1 << kUlpShift;
IanBenzMaxim 0:33d4e66780c0 145 int64_t error = (remaining == 0) ? 0 : kUlp / 2;
IanBenzMaxim 0:33d4e66780c0 146
IanBenzMaxim 0:33d4e66780c0 147 DiyFp v(significand, 0);
IanBenzMaxim 0:33d4e66780c0 148 v = v.Normalize();
IanBenzMaxim 0:33d4e66780c0 149 error <<= -v.e;
IanBenzMaxim 0:33d4e66780c0 150
IanBenzMaxim 0:33d4e66780c0 151 const int dExp = static_cast<int>(decimalPosition) - static_cast<int>(i) + exp;
IanBenzMaxim 0:33d4e66780c0 152
IanBenzMaxim 0:33d4e66780c0 153 int actualExp;
IanBenzMaxim 0:33d4e66780c0 154 DiyFp cachedPower = GetCachedPower10(dExp, &actualExp);
IanBenzMaxim 0:33d4e66780c0 155 if (actualExp != dExp) {
IanBenzMaxim 0:33d4e66780c0 156 static const DiyFp kPow10[] = {
IanBenzMaxim 0:33d4e66780c0 157 DiyFp(RAPIDJSON_UINT64_C2(0xa0000000, 00000000), -60), // 10^1
IanBenzMaxim 0:33d4e66780c0 158 DiyFp(RAPIDJSON_UINT64_C2(0xc8000000, 00000000), -57), // 10^2
IanBenzMaxim 0:33d4e66780c0 159 DiyFp(RAPIDJSON_UINT64_C2(0xfa000000, 00000000), -54), // 10^3
IanBenzMaxim 0:33d4e66780c0 160 DiyFp(RAPIDJSON_UINT64_C2(0x9c400000, 00000000), -50), // 10^4
IanBenzMaxim 0:33d4e66780c0 161 DiyFp(RAPIDJSON_UINT64_C2(0xc3500000, 00000000), -47), // 10^5
IanBenzMaxim 0:33d4e66780c0 162 DiyFp(RAPIDJSON_UINT64_C2(0xf4240000, 00000000), -44), // 10^6
IanBenzMaxim 0:33d4e66780c0 163 DiyFp(RAPIDJSON_UINT64_C2(0x98968000, 00000000), -40) // 10^7
IanBenzMaxim 0:33d4e66780c0 164 };
IanBenzMaxim 0:33d4e66780c0 165 int adjustment = dExp - actualExp - 1;
IanBenzMaxim 0:33d4e66780c0 166 RAPIDJSON_ASSERT(adjustment >= 0 && adjustment < 7);
IanBenzMaxim 0:33d4e66780c0 167 v = v * kPow10[adjustment];
IanBenzMaxim 0:33d4e66780c0 168 if (length + static_cast<unsigned>(adjustment)> 19u) // has more digits than decimal digits in 64-bit
IanBenzMaxim 0:33d4e66780c0 169 error += kUlp / 2;
IanBenzMaxim 0:33d4e66780c0 170 }
IanBenzMaxim 0:33d4e66780c0 171
IanBenzMaxim 0:33d4e66780c0 172 v = v * cachedPower;
IanBenzMaxim 0:33d4e66780c0 173
IanBenzMaxim 0:33d4e66780c0 174 error += kUlp + (error == 0 ? 0 : 1);
IanBenzMaxim 0:33d4e66780c0 175
IanBenzMaxim 0:33d4e66780c0 176 const int oldExp = v.e;
IanBenzMaxim 0:33d4e66780c0 177 v = v.Normalize();
IanBenzMaxim 0:33d4e66780c0 178 error <<= oldExp - v.e;
IanBenzMaxim 0:33d4e66780c0 179
IanBenzMaxim 0:33d4e66780c0 180 const unsigned effectiveSignificandSize = Double::EffectiveSignificandSize(64 + v.e);
IanBenzMaxim 0:33d4e66780c0 181 unsigned precisionSize = 64 - effectiveSignificandSize;
IanBenzMaxim 0:33d4e66780c0 182 if (precisionSize + kUlpShift >= 64) {
IanBenzMaxim 0:33d4e66780c0 183 unsigned scaleExp = (precisionSize + kUlpShift) - 63;
IanBenzMaxim 0:33d4e66780c0 184 v.f >>= scaleExp;
IanBenzMaxim 0:33d4e66780c0 185 v.e += scaleExp;
IanBenzMaxim 0:33d4e66780c0 186 error = (error >> scaleExp) + 1 + static_cast<int>(kUlp);
IanBenzMaxim 0:33d4e66780c0 187 precisionSize -= scaleExp;
IanBenzMaxim 0:33d4e66780c0 188 }
IanBenzMaxim 0:33d4e66780c0 189
IanBenzMaxim 0:33d4e66780c0 190 DiyFp rounded(v.f >> precisionSize, v.e + static_cast<int>(precisionSize));
IanBenzMaxim 0:33d4e66780c0 191 const uint64_t precisionBits = (v.f & ((uint64_t(1) << precisionSize) - 1)) * kUlp;
IanBenzMaxim 0:33d4e66780c0 192 const uint64_t halfWay = (uint64_t(1) << (precisionSize - 1)) * kUlp;
IanBenzMaxim 0:33d4e66780c0 193 if (precisionBits >= halfWay + static_cast<unsigned>(error)) {
IanBenzMaxim 0:33d4e66780c0 194 rounded.f++;
IanBenzMaxim 0:33d4e66780c0 195 if (rounded.f & (DiyFp::kDpHiddenBit << 1)) { // rounding overflows mantissa (issue #340)
IanBenzMaxim 0:33d4e66780c0 196 rounded.f >>= 1;
IanBenzMaxim 0:33d4e66780c0 197 rounded.e++;
IanBenzMaxim 0:33d4e66780c0 198 }
IanBenzMaxim 0:33d4e66780c0 199 }
IanBenzMaxim 0:33d4e66780c0 200
IanBenzMaxim 0:33d4e66780c0 201 *result = rounded.ToDouble();
IanBenzMaxim 0:33d4e66780c0 202
IanBenzMaxim 0:33d4e66780c0 203 return halfWay - static_cast<unsigned>(error) >= precisionBits || precisionBits >= halfWay + static_cast<unsigned>(error);
IanBenzMaxim 0:33d4e66780c0 204 }
IanBenzMaxim 0:33d4e66780c0 205
IanBenzMaxim 0:33d4e66780c0 206 inline double StrtodBigInteger(double approx, const char* decimals, size_t length, size_t decimalPosition, int exp) {
IanBenzMaxim 0:33d4e66780c0 207 const BigInteger dInt(decimals, length);
IanBenzMaxim 0:33d4e66780c0 208 const int dExp = static_cast<int>(decimalPosition) - static_cast<int>(length) + exp;
IanBenzMaxim 0:33d4e66780c0 209 Double a(approx);
IanBenzMaxim 0:33d4e66780c0 210 int cmp = CheckWithinHalfULP(a.Value(), dInt, dExp);
IanBenzMaxim 0:33d4e66780c0 211 if (cmp < 0)
IanBenzMaxim 0:33d4e66780c0 212 return a.Value(); // within half ULP
IanBenzMaxim 0:33d4e66780c0 213 else if (cmp == 0) {
IanBenzMaxim 0:33d4e66780c0 214 // Round towards even
IanBenzMaxim 0:33d4e66780c0 215 if (a.Significand() & 1)
IanBenzMaxim 0:33d4e66780c0 216 return a.NextPositiveDouble();
IanBenzMaxim 0:33d4e66780c0 217 else
IanBenzMaxim 0:33d4e66780c0 218 return a.Value();
IanBenzMaxim 0:33d4e66780c0 219 }
IanBenzMaxim 0:33d4e66780c0 220 else // adjustment
IanBenzMaxim 0:33d4e66780c0 221 return a.NextPositiveDouble();
IanBenzMaxim 0:33d4e66780c0 222 }
IanBenzMaxim 0:33d4e66780c0 223
IanBenzMaxim 0:33d4e66780c0 224 inline double StrtodFullPrecision(double d, int p, const char* decimals, size_t length, size_t decimalPosition, int exp) {
IanBenzMaxim 0:33d4e66780c0 225 RAPIDJSON_ASSERT(d >= 0.0);
IanBenzMaxim 0:33d4e66780c0 226 RAPIDJSON_ASSERT(length >= 1);
IanBenzMaxim 0:33d4e66780c0 227
IanBenzMaxim 0:33d4e66780c0 228 double result;
IanBenzMaxim 0:33d4e66780c0 229 if (StrtodFast(d, p, &result))
IanBenzMaxim 0:33d4e66780c0 230 return result;
IanBenzMaxim 0:33d4e66780c0 231
IanBenzMaxim 0:33d4e66780c0 232 // Trim leading zeros
IanBenzMaxim 0:33d4e66780c0 233 while (*decimals == '0' && length > 1) {
IanBenzMaxim 0:33d4e66780c0 234 length--;
IanBenzMaxim 0:33d4e66780c0 235 decimals++;
IanBenzMaxim 0:33d4e66780c0 236 decimalPosition--;
IanBenzMaxim 0:33d4e66780c0 237 }
IanBenzMaxim 0:33d4e66780c0 238
IanBenzMaxim 0:33d4e66780c0 239 // Trim trailing zeros
IanBenzMaxim 0:33d4e66780c0 240 while (decimals[length - 1] == '0' && length > 1) {
IanBenzMaxim 0:33d4e66780c0 241 length--;
IanBenzMaxim 0:33d4e66780c0 242 decimalPosition--;
IanBenzMaxim 0:33d4e66780c0 243 exp++;
IanBenzMaxim 0:33d4e66780c0 244 }
IanBenzMaxim 0:33d4e66780c0 245
IanBenzMaxim 0:33d4e66780c0 246 // Trim right-most digits
IanBenzMaxim 0:33d4e66780c0 247 const int kMaxDecimalDigit = 780;
IanBenzMaxim 0:33d4e66780c0 248 if (static_cast<int>(length) > kMaxDecimalDigit) {
IanBenzMaxim 0:33d4e66780c0 249 int delta = (static_cast<int>(length) - kMaxDecimalDigit);
IanBenzMaxim 0:33d4e66780c0 250 exp += delta;
IanBenzMaxim 0:33d4e66780c0 251 decimalPosition -= static_cast<unsigned>(delta);
IanBenzMaxim 0:33d4e66780c0 252 length = kMaxDecimalDigit;
IanBenzMaxim 0:33d4e66780c0 253 }
IanBenzMaxim 0:33d4e66780c0 254
IanBenzMaxim 0:33d4e66780c0 255 // If too small, underflow to zero
IanBenzMaxim 0:33d4e66780c0 256 if (int(length) + exp < -324)
IanBenzMaxim 0:33d4e66780c0 257 return 0.0;
IanBenzMaxim 0:33d4e66780c0 258
IanBenzMaxim 0:33d4e66780c0 259 if (StrtodDiyFp(decimals, length, decimalPosition, exp, &result))
IanBenzMaxim 0:33d4e66780c0 260 return result;
IanBenzMaxim 0:33d4e66780c0 261
IanBenzMaxim 0:33d4e66780c0 262 // Use approximation from StrtodDiyFp and make adjustment with BigInteger comparison
IanBenzMaxim 0:33d4e66780c0 263 return StrtodBigInteger(result, decimals, length, decimalPosition, exp);
IanBenzMaxim 0:33d4e66780c0 264 }
IanBenzMaxim 0:33d4e66780c0 265
IanBenzMaxim 0:33d4e66780c0 266 } // namespace internal
IanBenzMaxim 0:33d4e66780c0 267 RAPIDJSON_NAMESPACE_END
IanBenzMaxim 0:33d4e66780c0 268
IanBenzMaxim 0:33d4e66780c0 269 #endif // RAPIDJSON_STRTOD_