strtodtest.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. // Tencent is pleased to support the open source community by making RapidJSON available.
  2. //
  3. // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
  4. //
  5. // Licensed under the MIT License (the "License"); you may not use this file except
  6. // in compliance with the License. You may obtain a copy of the License at
  7. //
  8. // http://opensource.org/licenses/MIT
  9. //
  10. // Unless required by applicable law or agreed to in writing, software distributed
  11. // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
  12. // CONDITIONS OF ANY KIND, either express or implied. See the License for the
  13. // specific language governing permissions and limitations under the License.
  14. #include "unittest.h"
  15. #include "rapidjson/internal/strtod.h"
  16. #ifdef __clang__
  17. RAPIDJSON_DIAG_PUSH
  18. RAPIDJSON_DIAG_OFF(unreachable-code)
  19. #endif
  20. #define BIGINTEGER_LITERAL(s) BigInteger(s, sizeof(s) - 1)
  21. using namespace rapidjson::internal;
  22. TEST(Strtod, CheckApproximationCase) {
  23. static const int kSignificandSize = 52;
  24. static const int kExponentBias = 0x3FF;
  25. static const uint64_t kExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000);
  26. static const uint64_t kSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF);
  27. static const uint64_t kHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000);
  28. // http://www.exploringbinary.com/using-integers-to-check-a-floating-point-approximation/
  29. // Let b = 0x1.465a72e467d88p-149
  30. // = 5741268244528520 x 2^-201
  31. union {
  32. double d;
  33. uint64_t u;
  34. }u;
  35. u.u = 0x465a72e467d88 | ((static_cast<uint64_t>(-149 + kExponentBias)) << kSignificandSize);
  36. const double b = u.d;
  37. const uint64_t bInt = (u.u & kSignificandMask) | kHiddenBit;
  38. const int bExp = static_cast<int>(((u.u & kExponentMask) >> kSignificandSize) - kExponentBias - kSignificandSize);
  39. EXPECT_DOUBLE_EQ(1.7864e-45, b);
  40. EXPECT_EQ(RAPIDJSON_UINT64_C2(0x001465a7, 0x2e467d88), bInt);
  41. EXPECT_EQ(-201, bExp);
  42. // Let d = 17864 x 10-49
  43. const char dInt[] = "17864";
  44. const int dExp = -49;
  45. // Let h = 2^(bExp-1)
  46. const int hExp = bExp - 1;
  47. EXPECT_EQ(-202, hExp);
  48. int dS_Exp2 = 0;
  49. int dS_Exp5 = 0;
  50. int bS_Exp2 = 0;
  51. int bS_Exp5 = 0;
  52. int hS_Exp2 = 0;
  53. int hS_Exp5 = 0;
  54. // Adjust for decimal exponent
  55. if (dExp >= 0) {
  56. dS_Exp2 += dExp;
  57. dS_Exp5 += dExp;
  58. }
  59. else {
  60. bS_Exp2 -= dExp;
  61. bS_Exp5 -= dExp;
  62. hS_Exp2 -= dExp;
  63. hS_Exp5 -= dExp;
  64. }
  65. // Adjust for binary exponent
  66. if (bExp >= 0)
  67. bS_Exp2 += bExp;
  68. else {
  69. dS_Exp2 -= bExp;
  70. hS_Exp2 -= bExp;
  71. }
  72. // Adjust for half ulp exponent
  73. if (hExp >= 0)
  74. hS_Exp2 += hExp;
  75. else {
  76. dS_Exp2 -= hExp;
  77. bS_Exp2 -= hExp;
  78. }
  79. // Remove common power of two factor from all three scaled values
  80. int common_Exp2 = std::min(dS_Exp2, std::min(bS_Exp2, hS_Exp2));
  81. dS_Exp2 -= common_Exp2;
  82. bS_Exp2 -= common_Exp2;
  83. hS_Exp2 -= common_Exp2;
  84. EXPECT_EQ(153, dS_Exp2);
  85. EXPECT_EQ(0, dS_Exp5);
  86. EXPECT_EQ(1, bS_Exp2);
  87. EXPECT_EQ(49, bS_Exp5);
  88. EXPECT_EQ(0, hS_Exp2);
  89. EXPECT_EQ(49, hS_Exp5);
  90. BigInteger dS = BIGINTEGER_LITERAL(dInt);
  91. dS.MultiplyPow5(static_cast<unsigned>(dS_Exp5)) <<= static_cast<size_t>(dS_Exp2);
  92. BigInteger bS(bInt);
  93. bS.MultiplyPow5(static_cast<unsigned>(bS_Exp5)) <<= static_cast<size_t>(bS_Exp2);
  94. BigInteger hS(1);
  95. hS.MultiplyPow5(static_cast<unsigned>(hS_Exp5)) <<= static_cast<size_t>(hS_Exp2);
  96. EXPECT_TRUE(BIGINTEGER_LITERAL("203970822259994138521801764465966248930731085529088") == dS);
  97. EXPECT_TRUE(BIGINTEGER_LITERAL("203970822259994122305215569213032722473144531250000") == bS);
  98. EXPECT_TRUE(BIGINTEGER_LITERAL("17763568394002504646778106689453125") == hS);
  99. EXPECT_EQ(1, dS.Compare(bS));
  100. BigInteger delta(0);
  101. EXPECT_FALSE(dS.Difference(bS, &delta));
  102. EXPECT_TRUE(BIGINTEGER_LITERAL("16216586195252933526457586554279088") == delta);
  103. EXPECT_TRUE(bS.Difference(dS, &delta));
  104. EXPECT_TRUE(BIGINTEGER_LITERAL("16216586195252933526457586554279088") == delta);
  105. EXPECT_EQ(-1, delta.Compare(hS));
  106. }
  107. #ifdef __clang__
  108. RAPIDJSON_DIAG_POP
  109. #endif