Let us adjust the powers instead.

This commit is contained in:
Daniel Lemire 2020-11-19 18:15:42 -05:00
parent 1afba556e3
commit d521ddf7f7
3 changed files with 13 additions and 48 deletions

View File

@ -60,36 +60,6 @@ namespace {
fastfloat_really_inline int power(int q) noexcept { fastfloat_really_inline int power(int q) noexcept {
return (((152170 + 65536) * q) >> 16) + 63; return (((152170 + 65536) * q) >> 16) + 63;
} }
// Checks whether w is divisible by 5**-q. If it returns true, then
// w is definitively divisible by 5**-q.
inline bool is_divisible(int64_t q, uint64_t w) noexcept {
if((q>=-18) || (q<-27)) { return false; }
int64_t pos_q = -q;
// For each pair, first entry is the multiplicative inverse of 5**-q
// and the second one is the largest quotient.
//
// This could be more efficient by using...
// Faster remainder by direct computation: Applications to compilers and software libraries
// Software: Practice and Experience 49 (6), 2019.
// but the following is simple enough.
constexpr static uint64_t table[10][2] = {
{0xc1773b91fac10669,0x49c977}, // inverse of 5**18
{0x26b172506559ce15,0xec1e4}, // inverse of 5**19
{0xd489e3a9addec2d1,0x2f394}, // inverse of 5**20
{0x90e860bb892c8d5d,0x971d}, // inverse of 5**21
{0x502e79bf1b6f4f79,0x1e39}, // inverse of 5**22
{0xdcd618596be30fe5,0x60b}, // inverse of 5**23
{0x2c2ad1ab7bfa3661,0x135}, // inverse of 5**24
{0x8d55d224bfed7ad,0x3d}, // inverse of 5**25
{0x1c445d3a8cc9189,0xc}, // inverse of 5**26
{0xcd27412a54f5b6b5,0x2}, // inverse of 5**27
};
uint64_t inverse = table[pos_q-18][0];
uint64_t threshold = table[pos_q-18][1];
uint64_t product = w * inverse;
if(product > threshold) { return false; }
return true;
}
} // namespace } // namespace
@ -131,14 +101,9 @@ adjusted_mantissa compute_float(int64_t q, uint64_t w) noexcept {
// In some very rare cases, this could happen, in which case we might need a more accurate // In some very rare cases, this could happen, in which case we might need a more accurate
// computation that what we can provide cheaply. This is very, very unlikely. // computation that what we can provide cheaply. This is very, very unlikely.
// //
// There is still a chance to recover. If w is divisible by 5**-q,
if(!is_divisible(q,w)) {
answer.power2 = -1; // This (a negative value) indicates an error condition. answer.power2 = -1; // This (a negative value) indicates an error condition.
return answer; return answer;
} }
product.low += 1;
product.high += 1;
}
// The "compute_product_approximation" function can be slightly slower than a branchless approach: // The "compute_product_approximation" function can be slightly slower than a branchless approach:
// value128 product = compute_product(q, w); // value128 product = compute_product(q, w);
// but in practice, we can win big with the compute_product_approximation if its additional branch // but in practice, we can win big with the compute_product_approximation if its additional branch

View File

@ -347,16 +347,16 @@ const uint64_t power_of_five_128[]= {
0xa2425ff75e14fc31,0xa1258379a94d028d, 0xa2425ff75e14fc31,0xa1258379a94d028d,
0xcad2f7f5359a3b3e,0x96ee45813a04330, 0xcad2f7f5359a3b3e,0x96ee45813a04330,
0xfd87b5f28300ca0d,0x8bca9d6e188853fc, 0xfd87b5f28300ca0d,0x8bca9d6e188853fc,
0x9e74d1b791e07e48,0x775ea264cf55347d, 0x9e74d1b791e07e48,0x775ea264cf55347e,
0xc612062576589dda,0x95364afe032a819d, 0xc612062576589dda,0x95364afe032a819e,
0xf79687aed3eec551,0x3a83ddbd83f52204, 0xf79687aed3eec551,0x3a83ddbd83f52205,
0x9abe14cd44753b52,0xc4926a9672793542, 0x9abe14cd44753b52,0xc4926a9672793543,
0xc16d9a0095928a27,0x75b7053c0f178293, 0xc16d9a0095928a27,0x75b7053c0f178294,
0xf1c90080baf72cb1,0x5324c68b12dd6338, 0xf1c90080baf72cb1,0x5324c68b12dd6339,
0x971da05074da7bee,0xd3f6fc16ebca5e03, 0x971da05074da7bee,0xd3f6fc16ebca5e04,
0xbce5086492111aea,0x88f4bb1ca6bcf584, 0xbce5086492111aea,0x88f4bb1ca6bcf585,
0xec1e4a7db69561a5,0x2b31e9e3d06c32e5, 0xec1e4a7db69561a5,0x2b31e9e3d06c32e6,
0x9392ee8e921d5d07,0x3aff322e62439fcf, 0x9392ee8e921d5d07,0x3aff322e62439fd0,
0xb877aa3236a4b449,0x9befeb9fad487c3, 0xb877aa3236a4b449,0x9befeb9fad487c3,
0xe69594bec44de15b,0x4c2ebe687989a9b4, 0xe69594bec44de15b,0x4c2ebe687989a9b4,
0x901d7cf73ab0acd9,0xf9d37014bf60a11, 0x901d7cf73ab0acd9,0xf9d37014bf60a11,

View File

@ -8,7 +8,7 @@ for q in range(-342,0):
z = 0 z = 0
while( (1<<z) < power5) : while( (1<<z) < power5) :
z += 1 z += 1
if(q >= -17): if(q >= -27):
b = z + 127 b = z + 127
c = 2 ** b // power5 + 1 c = 2 ** b // power5 + 1
format(c) format(c)