# CachedPowers is ported from the C++ "double-conversions" library. # The following is their license: # Copyright 2006-2008 the V8 project authors. All rights reserved. # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. @[Deprecated] module Float::Printer::CachedPowers record Power, significand : UInt64, binary_exp : Int16, decimal_exp : Int16 # The minimal and maximal target exponent define the range of w's binary # exponent, where 'w' is the result of multiplying the input by a cached power # of ten. # # A different range might be chosen on a different platform, to optimize digit # generation, but a smaller range requires more powers of ten to be cached. MIN_TARGET_EXP = -60 MAX_TARGET_EXP = -32 CACHED_POWER_OFFSET = 348 # -1 * the first decimal_exp # Not all powers of ten are cached. The decimal exponent of two neighboring # cached numbers will differ by `CACHED_EXP_STEP` CACHED_EXP_STEP = 8 MIN_CACHED_EXP = -348 MAX_CACHED_EXP = 340 D_1_LOG2_10 = 0.30102999566398114 # 1 / lg(10) PowCache = [ {0xfa8fd5a0081c0288_u64, -1220_i16, -348_i16}, {0xbaaee17fa23ebf76_u64, -1193_i16, -340_i16}, {0x8b16fb203055ac76_u64, -1166_i16, -332_i16}, {0xcf42894a5dce35ea_u64, -1140_i16, -324_i16}, {0x9a6bb0aa55653b2d_u64, -1113_i16, -316_i16}, {0xe61acf033d1a45df_u64, -1087_i16, -308_i16}, {0xab70fe17c79ac6ca_u64, -1060_i16, -300_i16}, {0xff77b1fcbebcdc4f_u64, -1034_i16, -292_i16}, {0xbe5691ef416bd60c_u64, -1007_i16, -284_i16}, {0x8dd01fad907ffc3c_u64, -980_i16, -276_i16}, {0xd3515c2831559a83_u64, -954_i16, -268_i16}, {0x9d71ac8fada6c9b5_u64, -927_i16, -260_i16}, {0xea9c227723ee8bcb_u64, -901_i16, -252_i16}, {0xaecc49914078536d_u64, -874_i16, -244_i16}, {0x823c12795db6ce57_u64, -847_i16, -236_i16}, {0xc21094364dfb5637_u64, -821_i16, -228_i16}, {0x9096ea6f3848984f_u64, -794_i16, -220_i16}, {0xd77485cb25823ac7_u64, -768_i16, -212_i16}, {0xa086cfcd97bf97f4_u64, -741_i16, -204_i16}, {0xef340a98172aace5_u64, -715_i16, -196_i16}, {0xb23867fb2a35b28e_u64, -688_i16, -188_i16}, {0x84c8d4dfd2c63f3b_u64, -661_i16, -180_i16}, {0xc5dd44271ad3cdba_u64, -635_i16, -172_i16}, {0x936b9fcebb25c996_u64, -608_i16, -164_i16}, {0xdbac6c247d62a584_u64, -582_i16, -156_i16}, {0xa3ab66580d5fdaf6_u64, -555_i16, -148_i16}, {0xf3e2f893dec3f126_u64, -529_i16, -140_i16}, {0xb5b5ada8aaff80b8_u64, -502_i16, -132_i16}, {0x87625f056c7c4a8b_u64, -475_i16, -124_i16}, {0xc9bcff6034c13053_u64, -449_i16, -116_i16}, {0x964e858c91ba2655_u64, -422_i16, -108_i16}, {0xdff9772470297ebd_u64, -396_i16, -100_i16}, {0xa6dfbd9fb8e5b88f_u64, -369_i16, -92_i16}, {0xf8a95fcf88747d94_u64, -343_i16, -84_i16}, {0xb94470938fa89bcf_u64, -316_i16, -76_i16}, {0x8a08f0f8bf0f156b_u64, -289_i16, -68_i16}, {0xcdb02555653131b6_u64, -263_i16, -60_i16}, {0x993fe2c6d07b7fac_u64, -236_i16, -52_i16}, {0xe45c10c42a2b3b06_u64, -210_i16, -44_i16}, {0xaa242499697392d3_u64, -183_i16, -36_i16}, {0xfd87b5f28300ca0e_u64, -157_i16, -28_i16}, {0xbce5086492111aeb_u64, -130_i16, -20_i16}, {0x8cbccc096f5088cc_u64, -103_i16, -12_i16}, {0xd1b71758e219652c_u64, -77_i16, -4_i16}, {0x9c40000000000000_u64, -50_i16, 4_i16}, {0xe8d4a51000000000_u64, -24_i16, 12_i16}, {0xad78ebc5ac620000_u64, 3_i16, 20_i16}, {0x813f3978f8940984_u64, 30_i16, 28_i16}, {0xc097ce7bc90715b3_u64, 56_i16, 36_i16}, {0x8f7e32ce7bea5c70_u64, 83_i16, 44_i16}, {0xd5d238a4abe98068_u64, 109_i16, 52_i16}, {0x9f4f2726179a2245_u64, 136_i16, 60_i16}, {0xed63a231d4c4fb27_u64, 162_i16, 68_i16}, {0xb0de65388cc8ada8_u64, 189_i16, 76_i16}, {0x83c7088e1aab65db_u64, 216_i16, 84_i16}, {0xc45d1df942711d9a_u64, 242_i16, 92_i16}, {0x924d692ca61be758_u64, 269_i16, 100_i16}, {0xda01ee641a708dea_u64, 295_i16, 108_i16}, {0xa26da3999aef774a_u64, 322_i16, 116_i16}, {0xf209787bb47d6b85_u64, 348_i16, 124_i16}, {0xb454e4a179dd1877_u64, 375_i16, 132_i16}, {0x865b86925b9bc5c2_u64, 402_i16, 140_i16}, {0xc83553c5c8965d3d_u64, 428_i16, 148_i16}, {0x952ab45cfa97a0b3_u64, 455_i16, 156_i16}, {0xde469fbd99a05fe3_u64, 481_i16, 164_i16}, {0xa59bc234db398c25_u64, 508_i16, 172_i16}, {0xf6c69a72a3989f5c_u64, 534_i16, 180_i16}, {0xb7dcbf5354e9bece_u64, 561_i16, 188_i16}, {0x88fcf317f22241e2_u64, 588_i16, 196_i16}, {0xcc20ce9bd35c78a5_u64, 614_i16, 204_i16}, {0x98165af37b2153df_u64, 641_i16, 212_i16}, {0xe2a0b5dc971f303a_u64, 667_i16, 220_i16}, {0xa8d9d1535ce3b396_u64, 694_i16, 228_i16}, {0xfb9b7cd9a4a7443c_u64, 720_i16, 236_i16}, {0xbb764c4ca7a44410_u64, 747_i16, 244_i16}, {0x8bab8eefb6409c1a_u64, 774_i16, 252_i16}, {0xd01fef10a657842c_u64, 800_i16, 260_i16}, {0x9b10a4e5e9913129_u64, 827_i16, 268_i16}, {0xe7109bfba19c0c9d_u64, 853_i16, 276_i16}, {0xac2820d9623bf429_u64, 880_i16, 284_i16}, {0x80444b5e7aa7cf85_u64, 907_i16, 292_i16}, {0xbf21e44003acdd2d_u64, 933_i16, 300_i16}, {0x8e679c2f5e44ff8f_u64, 960_i16, 308_i16}, {0xd433179d9c8cb841_u64, 986_i16, 316_i16}, {0x9e19db92b4e31ba9_u64, 1013_i16, 324_i16}, {0xeb96bf6ebadf77d9_u64, 1039_i16, 332_i16}, {0xaf87023b9bf0ee6b_u64, 1066_i16, 340_i16}, ].map { |t| Power.new t[0], t[1], t[2] } Pow10Cache = {0, 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000} def self.largest_pow10(n, n_bits) : {Int32, Int32} # 1233/4096 is approximately 1/lg(10). # We increment to skip over the first entry in the powers cache. guess = ((n_bits + 1) * 1233 >> 12) + 1 # We don't have any guarantees that 2^number_bits <= number. guess -= 1 if n < Pow10Cache[guess] return Pow10Cache[guess], guess end # Returns a cached power-of-ten with a binary exponent in the range # around *exp* (boundaries included). def self.get_cached_power_for_binary_exponent(exp) : {DiyFP, Int32} min_exp = MIN_TARGET_EXP - (exp + DiyFP::SIGNIFICAND_SIZE) k = ((min_exp + DiyFP::SIGNIFICAND_SIZE - 1) * D_1_LOG2_10).ceil index = ((CACHED_POWER_OFFSET + k.to_i - 1) // CACHED_EXP_STEP) + 1 pow = PowCache[index] return DiyFP.new(pow.significand, pow.binary_exp), pow.decimal_exp.to_i end end