1
2
3
4
5 package strconv
6
7 import "math/bits"
8
9
10
11 type uint128 struct {
12 Hi uint64
13 Lo uint64
14 }
15
16
17 func umul128(x, y uint64) uint128 {
18 hi, lo := bits.Mul64(x, y)
19 return uint128{hi, lo}
20 }
21
22
23 func umul192(x uint64, y uint128) (hi, mid, lo uint64) {
24 mid1, lo := bits.Mul64(x, y.Lo)
25 hi, mid2 := bits.Mul64(x, y.Hi)
26 mid, carry := bits.Add64(mid1, mid2, 0)
27 return hi + carry, mid, lo
28 }
29
30
31
32
33 func pow10(e int) (mant uint128, exp int, ok bool) {
34 if e < pow10Min || e > pow10Max {
35 return
36 }
37 return pow10Tab[e-pow10Min], 1 + mulLog2_10(e), true
38 }
39
40
41
42
43
44
45 func mulLog10_2(x int) int {
46
47 return (x * 78913) >> 18
48 }
49
50
51
52
53
54
55 func mulLog2_10(x int) int {
56
57 return (x * 108853) >> 15
58 }
59
60 func bool2uint(b bool) uint {
61 if b {
62 return 1
63 }
64 return 0
65 }
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96 func divisiblePow5(x uint64, p int) bool {
97 return 1 <= p && p <= 22 && x*div5Tab[p-1][0] <= div5Tab[p-1][1]
98 }
99
100 const maxUint64 = 1<<64 - 1
101
102
103 var div5Tab = [22][2]uint64{
104 {0xcccccccccccccccd, maxUint64 / 5},
105 {0x8f5c28f5c28f5c29, maxUint64 / 5 / 5},
106 {0x1cac083126e978d5, maxUint64 / 5 / 5 / 5},
107 {0xd288ce703afb7e91, maxUint64 / 5 / 5 / 5 / 5},
108 {0x5d4e8fb00bcbe61d, maxUint64 / 5 / 5 / 5 / 5 / 5},
109 {0x790fb65668c26139, maxUint64 / 5 / 5 / 5 / 5 / 5 / 5},
110 {0xe5032477ae8d46a5, maxUint64 / 5 / 5 / 5 / 5 / 5 / 5 / 5},
111 {0xc767074b22e90e21, maxUint64 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5},
112 {0x8e47ce423a2e9c6d, maxUint64 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5},
113 {0x4fa7f60d3ed61f49, maxUint64 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5},
114 {0x0fee64690c913975, maxUint64 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5},
115 {0x3662e0e1cf503eb1, maxUint64 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5},
116 {0xa47a2cf9f6433fbd, maxUint64 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5},
117 {0x54186f653140a659, maxUint64 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5},
118 {0x7738164770402145, maxUint64 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5},
119 {0xe4a4d1417cd9a041, maxUint64 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5},
120 {0xc75429d9e5c5200d, maxUint64 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5},
121 {0xc1773b91fac10669, maxUint64 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5},
122 {0x26b172506559ce15, maxUint64 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5},
123 {0xd489e3a9addec2d1, maxUint64 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5},
124 {0x90e860bb892c8d5d, maxUint64 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5},
125 {0x502e79bf1b6f4f79, maxUint64 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5 / 5},
126 }
127
128
129
130
131
132
133
134
135
136 func trimZeros(x uint64) (uint64, int) {
137 const (
138 div1e8m = 0xc767074b22e90e21
139 div1e8le = maxUint64 / 100000000
140
141 div1e4m = 0xd288ce703afb7e91
142 div1e4le = maxUint64 / 10000
143
144 div1e2m = 0x8f5c28f5c28f5c29
145 div1e2le = maxUint64 / 100
146
147 div1e1m = 0xcccccccccccccccd
148 div1e1le = maxUint64 / 10
149 )
150
151
152
153
154 var assert [1]struct{}
155 _ = assert[(div1e8m*5*5*5*5*5*5*5*5)%(1<<64)-1]
156 _ = assert[(div1e4m*5*5*5*5)%(1<<64)-1]
157 _ = assert[(div1e2m*5*5)%(1<<64)-1]
158 _ = assert[(div1e1m*5)%(1<<64)-1]
159
160
161 p := 0
162 for d := bits.RotateLeft64(x*div1e8m, -8); d <= div1e8le; d = bits.RotateLeft64(x*div1e8m, -8) {
163 x = d
164 p += 8
165 }
166 if d := bits.RotateLeft64(x*div1e4m, -4); d <= div1e4le {
167 x = d
168 p += 4
169 }
170 if d := bits.RotateLeft64(x*div1e2m, -2); d <= div1e2le {
171 x = d
172 p += 2
173 }
174 if d := bits.RotateLeft64(x*div1e1m, -1); d <= div1e1le {
175 x = d
176 p += 1
177 }
178 return x, p
179 }
180
View as plain text