Home | History | Annotate | Download | only in unittest
      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 
     15 #include "unittest.h"
     16 
     17 #include "rapidjson/internal/strtod.h"
     18 
     19 #define BIGINTEGER_LITERAL(s) BigInteger(s, sizeof(s) - 1)
     20 
     21 using namespace rapidjson::internal;
     22 
     23 TEST(Strtod, CheckApproximationCase) {
     24     static const int kSignificandSize = 52;
     25     static const int kExponentBias = 0x3FF;
     26     static const uint64_t kExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000);
     27     static const uint64_t kSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF);
     28     static const uint64_t kHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000);
     29 
     30     // http://www.exploringbinary.com/using-integers-to-check-a-floating-point-approximation/
     31     // Let b = 0x1.465a72e467d88p-149
     32     //       = 5741268244528520 x 2^-201
     33     union {
     34         double d;
     35         uint64_t u;
     36     }u;
     37     u.u = 0x465a72e467d88 | ((static_cast<uint64_t>(-149 + kExponentBias)) << kSignificandSize);
     38     const double b = u.d;
     39     const uint64_t bInt = (u.u & kSignificandMask) | kHiddenBit;
     40     const int bExp = ((u.u & kExponentMask) >> kSignificandSize) - kExponentBias - kSignificandSize;
     41     EXPECT_DOUBLE_EQ(1.7864e-45, b);
     42     EXPECT_EQ(RAPIDJSON_UINT64_C2(0x001465a7, 0x2e467d88), bInt);
     43     EXPECT_EQ(-201, bExp);
     44 
     45     // Let d = 17864 x 10-49
     46     const char dInt[] = "17864";
     47     const int dExp = -49;
     48 
     49     // Let h = 2^(bExp-1)
     50     const int hExp = bExp - 1;
     51     EXPECT_EQ(-202, hExp);
     52 
     53     int dS_Exp2 = 0;
     54     int dS_Exp5 = 0;
     55     int bS_Exp2 = 0;
     56     int bS_Exp5 = 0;
     57     int hS_Exp2 = 0;
     58     int hS_Exp5 = 0;
     59 
     60     // Adjust for decimal exponent
     61     if (dExp >= 0) {
     62         dS_Exp2 += dExp;
     63         dS_Exp5 += dExp;
     64     }
     65     else {
     66         bS_Exp2 -= dExp;
     67         bS_Exp5 -= dExp;
     68         hS_Exp2 -= dExp;
     69         hS_Exp5 -= dExp;
     70     }
     71 
     72     // Adjust for binary exponent
     73     if (bExp >= 0)
     74         bS_Exp2 += bExp;
     75     else {
     76         dS_Exp2 -= bExp;
     77         hS_Exp2 -= bExp;
     78     }
     79 
     80     // Adjust for half ulp exponent
     81     if (hExp >= 0)
     82         hS_Exp2 += hExp;
     83     else {
     84         dS_Exp2 -= hExp;
     85         bS_Exp2 -= hExp;
     86     }
     87 
     88     // Remove common power of two factor from all three scaled values
     89     int common_Exp2 = std::min(dS_Exp2, std::min(bS_Exp2, hS_Exp2));
     90     dS_Exp2 -= common_Exp2;
     91     bS_Exp2 -= common_Exp2;
     92     hS_Exp2 -= common_Exp2;
     93 
     94     EXPECT_EQ(153, dS_Exp2);
     95     EXPECT_EQ(0, dS_Exp5);
     96     EXPECT_EQ(1, bS_Exp2);
     97     EXPECT_EQ(49, bS_Exp5);
     98     EXPECT_EQ(0, hS_Exp2);
     99     EXPECT_EQ(49, hS_Exp5);
    100 
    101     BigInteger dS = BIGINTEGER_LITERAL(dInt);
    102     dS.MultiplyPow5(dS_Exp5) <<= dS_Exp2;
    103 
    104     BigInteger bS(bInt);
    105     bS.MultiplyPow5(bS_Exp5) <<= bS_Exp2;
    106 
    107     BigInteger hS(1);
    108     hS.MultiplyPow5(hS_Exp5) <<= hS_Exp2;
    109 
    110     EXPECT_TRUE(BIGINTEGER_LITERAL("203970822259994138521801764465966248930731085529088") == dS);
    111     EXPECT_TRUE(BIGINTEGER_LITERAL("203970822259994122305215569213032722473144531250000") == bS);
    112     EXPECT_TRUE(BIGINTEGER_LITERAL("17763568394002504646778106689453125") == hS);
    113 
    114     EXPECT_EQ(1, dS.Compare(bS));
    115 
    116     BigInteger delta(0);
    117     EXPECT_FALSE(dS.Difference(bS, &delta));
    118     EXPECT_TRUE(BIGINTEGER_LITERAL("16216586195252933526457586554279088") == delta);
    119     EXPECT_TRUE(bS.Difference(dS, &delta));
    120     EXPECT_TRUE(BIGINTEGER_LITERAL("16216586195252933526457586554279088") == delta);
    121 
    122     EXPECT_EQ(-1, delta.Compare(hS));
    123 }
    124