| | |
| | |
| | |
| |
|
| | package strconv |
| |
|
| | import "math/bits" |
| |
|
| | |
| | |
| | type uint128 struct { |
| | Hi uint64 |
| | Lo uint64 |
| | } |
| |
|
| | |
| | func umul128(x, y uint64) uint128 { |
| | hi, lo := bits.Mul64(x, y) |
| | return uint128{hi, lo} |
| | } |
| |
|
| | |
| | func umul192(x uint64, y uint128) (hi, mid, lo uint64) { |
| | mid1, lo := bits.Mul64(x, y.Lo) |
| | hi, mid2 := bits.Mul64(x, y.Hi) |
| | mid, carry := bits.Add64(mid1, mid2, 0) |
| | return hi + carry, mid, lo |
| | } |
| |
|
| | |
| | |
| | |
| | func pow10(e int) (mant uint128, exp int, ok bool) { |
| | if e < pow10Min || e > pow10Max { |
| | return |
| | } |
| | return pow10Tab[e-pow10Min], 1 + mulLog2_10(e), true |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | func mulLog10_2(x int) int { |
| | |
| | return (x * 78913) >> 18 |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | func mulLog2_10(x int) int { |
| | |
| | return (x * 108853) >> 15 |
| | } |
| |
|
| | func bool2uint(b bool) uint { |
| | if b { |
| | return 1 |
| | } |
| | return 0 |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | |
| | |
| | |
| | func divisiblePow5(x uint64, p int) bool { |
| | return 1 <= p && p <= 22 && x*div5Tab[p-1][0] <= div5Tab[p-1][1] |
| | } |
| |
|
| | const maxUint64 = 1<<64 - 1 |
| |
|
| | |
| | var div5Tab = [22][2]uint64{ |
| | {0xcccccccccccccccd, maxUint64 / 5}, |
| | {0x8f5c28f5c28f5c29, maxUint64 / 5 / 5}, |
| | {0x1cac083126e978d5, maxUint64 / 5 / 5 / 5}, |
| | {0xd288ce703afb7e91, maxUint64 / 5 / 5 / 5 / 5}, |
| | {0x5d4e8fb00bcbe61d, maxUint64 / 5 / 5 / 5 / 5 / 5}, |
| | {0x790fb65668c26139, maxUint64 / 5 / 5 / 5 / 5 / 5 / 5}, |
| | {0xe5032477ae8d46a5, maxUint64 / 5 / 5 / 5 / 5 / 5 / 5 / 5}, |
| | {0xc767074b22e90e21, maxUint64 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5}, |
| | {0x8e47ce423a2e9c6d, maxUint64 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5}, |
| | {0x4fa7f60d3ed61f49, maxUint64 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5}, |
| | {0x0fee64690c913975, maxUint64 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5}, |
| | {0x3662e0e1cf503eb1, maxUint64 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5}, |
| | {0xa47a2cf9f6433fbd, maxUint64 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5}, |
| | {0x54186f653140a659, maxUint64 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5}, |
| | {0x7738164770402145, maxUint64 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5}, |
| | {0xe4a4d1417cd9a041, maxUint64 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5}, |
| | {0xc75429d9e5c5200d, maxUint64 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5}, |
| | {0xc1773b91fac10669, maxUint64 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5}, |
| | {0x26b172506559ce15, maxUint64 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5}, |
| | {0xd489e3a9addec2d1, maxUint64 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5}, |
| | {0x90e860bb892c8d5d, maxUint64 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5}, |
| | {0x502e79bf1b6f4f79, maxUint64 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5}, |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | func trimZeros(x uint64) (uint64, int) { |
| | const ( |
| | div1e8m = 0xc767074b22e90e21 |
| | div1e8le = maxUint64 / 100000000 |
| |
|
| | div1e4m = 0xd288ce703afb7e91 |
| | div1e4le = maxUint64 / 10000 |
| |
|
| | div1e2m = 0x8f5c28f5c28f5c29 |
| | div1e2le = maxUint64 / 100 |
| |
|
| | div1e1m = 0xcccccccccccccccd |
| | div1e1le = maxUint64 / 10 |
| | ) |
| |
|
| | |
| | |
| | |
| | var assert [1]struct{} |
| | _ = assert[(div1e8m*5*5*5*5*5*5*5*5)%(1<<64)-1] |
| | _ = assert[(div1e4m*5*5*5*5)%(1<<64)-1] |
| | _ = assert[(div1e2m*5*5)%(1<<64)-1] |
| | _ = assert[(div1e1m*5)%(1<<64)-1] |
| |
|
| | |
| | p := 0 |
| | for d := bits.RotateLeft64(x*div1e8m, -8); d <= div1e8le; d = bits.RotateLeft64(x*div1e8m, -8) { |
| | x = d |
| | p += 8 |
| | } |
| | if d := bits.RotateLeft64(x*div1e4m, -4); d <= div1e4le { |
| | x = d |
| | p += 4 |
| | } |
| | if d := bits.RotateLeft64(x*div1e2m, -2); d <= div1e2le { |
| | x = d |
| | p += 2 |
| | } |
| | if d := bits.RotateLeft64(x*div1e1m, -1); d <= div1e1le { |
| | x = d |
| | p += 1 |
| | } |
| | return x, p |
| | } |
| |
|