TerraForge3D  2.3.1
3D Terrain And Landscape Generator

◆ get_cached_power_for_binary_exponent()

cached_power nlohmann::detail::dtoa_impl::get_cached_power_for_binary_exponent ( int  e)
inline

For a normalized diyfp w = f * 2^e, this function returns a (normalized) cached power-of-ten c = f_c * 2^e_c, such that the exponent of the product w * c satisfies (Definition 3.2 from [1])

 alpha <= e_c + e + q <= gamma.

Definition at line 15837 of file json.hpp.

15838{
15839 // Now
15840 //
15841 // alpha <= e_c + e + q <= gamma (1)
15842 // ==> f_c * 2^alpha <= c * 2^e * 2^q
15843 //
15844 // and since the c's are normalized, 2^(q-1) <= f_c,
15845 //
15846 // ==> 2^(q - 1 + alpha) <= c * 2^(e + q)
15847 // ==> 2^(alpha - e - 1) <= c
15848 //
15849 // If c were an exact power of ten, i.e. c = 10^k, one may determine k as
15850 //
15851 // k = ceil( log_10( 2^(alpha - e - 1) ) )
15852 // = ceil( (alpha - e - 1) * log_10(2) )
15853 //
15854 // From the paper:
15855 // "In theory the result of the procedure could be wrong since c is rounded,
15856 // and the computation itself is approximated [...]. In practice, however,
15857 // this simple function is sufficient."
15858 //
15859 // For IEEE double precision floating-point numbers converted into
15860 // normalized diyfp's w = f * 2^e, with q = 64,
15861 //
15862 // e >= -1022 (min IEEE exponent)
15863 // -52 (p - 1)
15864 // -52 (p - 1, possibly normalize denormal IEEE numbers)
15865 // -11 (normalize the diyfp)
15866 // = -1137
15867 //
15868 // and
15869 //
15870 // e <= +1023 (max IEEE exponent)
15871 // -52 (p - 1)
15872 // -11 (normalize the diyfp)
15873 // = 960
15874 //
15875 // This binary exponent range [-1137,960] results in a decimal exponent
15876 // range [-307,324]. One does not need to store a cached power for each
15877 // k in this range. For each such k it suffices to find a cached power
15878 // such that the exponent of the product lies in [alpha,gamma].
15879 // This implies that the difference of the decimal exponents of adjacent
15880 // table entries must be less than or equal to
15881 //
15882 // floor( (gamma - alpha) * log_10(2) ) = 8.
15883 //
15884 // (A smaller distance gamma-alpha would require a larger table.)
15885 // NB:
15886 // Actually this function returns c, such that -60 <= e_c + e + 64 <= -34.
15887 constexpr int kCachedPowersMinDecExp = -300;
15888 constexpr int kCachedPowersDecStep = 8;
15889 static constexpr std::array<cached_power, 79> kCachedPowers =
15890 {
15891 {
15892 { 0xAB70FE17C79AC6CA, -1060, -300 },
15893 { 0xFF77B1FCBEBCDC4F, -1034, -292 },
15894 { 0xBE5691EF416BD60C, -1007, -284 },
15895 { 0x8DD01FAD907FFC3C, -980, -276 },
15896 { 0xD3515C2831559A83, -954, -268 },
15897 { 0x9D71AC8FADA6C9B5, -927, -260 },
15898 { 0xEA9C227723EE8BCB, -901, -252 },
15899 { 0xAECC49914078536D, -874, -244 },
15900 { 0x823C12795DB6CE57, -847, -236 },
15901 { 0xC21094364DFB5637, -821, -228 },
15902 { 0x9096EA6F3848984F, -794, -220 },
15903 { 0xD77485CB25823AC7, -768, -212 },
15904 { 0xA086CFCD97BF97F4, -741, -204 },
15905 { 0xEF340A98172AACE5, -715, -196 },
15906 { 0xB23867FB2A35B28E, -688, -188 },
15907 { 0x84C8D4DFD2C63F3B, -661, -180 },
15908 { 0xC5DD44271AD3CDBA, -635, -172 },
15909 { 0x936B9FCEBB25C996, -608, -164 },
15910 { 0xDBAC6C247D62A584, -582, -156 },
15911 { 0xA3AB66580D5FDAF6, -555, -148 },
15912 { 0xF3E2F893DEC3F126, -529, -140 },
15913 { 0xB5B5ADA8AAFF80B8, -502, -132 },
15914 { 0x87625F056C7C4A8B, -475, -124 },
15915 { 0xC9BCFF6034C13053, -449, -116 },
15916 { 0x964E858C91BA2655, -422, -108 },
15917 { 0xDFF9772470297EBD, -396, -100 },
15918 { 0xA6DFBD9FB8E5B88F, -369, -92 },
15919 { 0xF8A95FCF88747D94, -343, -84 },
15920 { 0xB94470938FA89BCF, -316, -76 },
15921 { 0x8A08F0F8BF0F156B, -289, -68 },
15922 { 0xCDB02555653131B6, -263, -60 },
15923 { 0x993FE2C6D07B7FAC, -236, -52 },
15924 { 0xE45C10C42A2B3B06, -210, -44 },
15925 { 0xAA242499697392D3, -183, -36 },
15926 { 0xFD87B5F28300CA0E, -157, -28 },
15927 { 0xBCE5086492111AEB, -130, -20 },
15928 { 0x8CBCCC096F5088CC, -103, -12 },
15929 { 0xD1B71758E219652C, -77, -4 },
15930 { 0x9C40000000000000, -50, 4 },
15931 { 0xE8D4A51000000000, -24, 12 },
15932 { 0xAD78EBC5AC620000, 3, 20 },
15933 { 0x813F3978F8940984, 30, 28 },
15934 { 0xC097CE7BC90715B3, 56, 36 },
15935 { 0x8F7E32CE7BEA5C70, 83, 44 },
15936 { 0xD5D238A4ABE98068, 109, 52 },
15937 { 0x9F4F2726179A2245, 136, 60 },
15938 { 0xED63A231D4C4FB27, 162, 68 },
15939 { 0xB0DE65388CC8ADA8, 189, 76 },
15940 { 0x83C7088E1AAB65DB, 216, 84 },
15941 { 0xC45D1DF942711D9A, 242, 92 },
15942 { 0x924D692CA61BE758, 269, 100 },
15943 { 0xDA01EE641A708DEA, 295, 108 },
15944 { 0xA26DA3999AEF774A, 322, 116 },
15945 { 0xF209787BB47D6B85, 348, 124 },
15946 { 0xB454E4A179DD1877, 375, 132 },
15947 { 0x865B86925B9BC5C2, 402, 140 },
15948 { 0xC83553C5C8965D3D, 428, 148 },
15949 { 0x952AB45CFA97A0B3, 455, 156 },
15950 { 0xDE469FBD99A05FE3, 481, 164 },
15951 { 0xA59BC234DB398C25, 508, 172 },
15952 { 0xF6C69A72A3989F5C, 534, 180 },
15953 { 0xB7DCBF5354E9BECE, 561, 188 },
15954 { 0x88FCF317F22241E2, 588, 196 },
15955 { 0xCC20CE9BD35C78A5, 614, 204 },
15956 { 0x98165AF37B2153DF, 641, 212 },
15957 { 0xE2A0B5DC971F303A, 667, 220 },
15958 { 0xA8D9D1535CE3B396, 694, 228 },
15959 { 0xFB9B7CD9A4A7443C, 720, 236 },
15960 { 0xBB764C4CA7A44410, 747, 244 },
15961 { 0x8BAB8EEFB6409C1A, 774, 252 },
15962 { 0xD01FEF10A657842C, 800, 260 },
15963 { 0x9B10A4E5E9913129, 827, 268 },
15964 { 0xE7109BFBA19C0C9D, 853, 276 },
15965 { 0xAC2820D9623BF429, 880, 284 },
15966 { 0x80444B5E7AA7CF85, 907, 292 },
15967 { 0xBF21E44003ACDD2D, 933, 300 },
15968 { 0x8E679C2F5E44FF8F, 960, 308 },
15969 { 0xD433179D9C8CB841, 986, 316 },
15970 { 0x9E19DB92B4E31BA9, 1013, 324 },
15971 }
15972 };
15973 // This computation gives exactly the same results for k as
15974 // k = ceil((kAlpha - e - 1) * 0.30102999566398114)
15975 // for |e| <= 1500, but doesn't require floating-point operations.
15976 // NB: log_10(2) ~= 78913 / 2^18
15977 JSON_ASSERT(e >= -1500);
15978 JSON_ASSERT(e <= 1500);
15979 const int f = kAlpha - e - 1;
15980 const int k = (f * 78913) / (1 << 18) + static_cast<int>(f > 0);
15981 const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep;
15982 JSON_ASSERT(index >= 0);
15983 JSON_ASSERT(static_cast<std::size_t>(index) < kCachedPowers.size());
15984 const cached_power cached = kCachedPowers[static_cast<std::size_t>(index)];
15985 JSON_ASSERT(kAlpha <= cached.e + e + 64);
15986 JSON_ASSERT(kGamma >= cached.e + e + 64);
15987 return cached;
15988}