v / vlib / strconv / utilities.v
259 lines · 234 sloc · 5.01 KB · d9a3a3aa0aa397c22e6f5440c5a7fb2292c104c9
Raw
1module strconv
2
3import math.bits
4
5// general utilities
6
7// General Utilities
8@[if debug_strconv ?]
9fn assert1(t bool, msg string) {
10 if !t {
11 panic(msg)
12 }
13}
14
15@[inline]
16fn bool_to_int(b bool) int {
17 if b {
18 return 1
19 }
20 return 0
21}
22
23@[inline]
24fn bool_to_u32(b bool) u32 {
25 if b {
26 return u32(1)
27 }
28 return u32(0)
29}
30
31@[inline]
32fn bool_to_u64(b bool) u64 {
33 if b {
34 return u64(1)
35 }
36 return u64(0)
37}
38
39fn get_string_special(neg bool, expZero bool, mantZero bool) string {
40 if !mantZero {
41 return 'nan'
42 }
43 if !expZero {
44 if neg {
45 return '-inf'
46 } else {
47 return '+inf'
48 }
49 }
50 if neg {
51 return '-0e+00'
52 }
53 return '0e+00'
54}
55
56/*
5732 bit functions
58*/
59
60fn mul_shift_32(m u32, mul u64, ishift int) u32 {
61 // QTODO
62 // assert ishift > 32
63
64 hi, lo := bits.mul_64(u64(m), mul)
65 shifted_sum := (lo >> u64(ishift)) + (hi << u64(64 - ishift))
66 assert1(shifted_sum <= 2147483647, 'shiftedSum <= math.max_u32')
67 return u32(shifted_sum)
68}
69
70@[direct_array_access; inline]
71fn mul_pow5_invdiv_pow2(m u32, q u32, j int) u32 {
72 assert1(q < pow5_inv_split_32.len, 'q < pow5_inv_split_32.len')
73 return mul_shift_32(m, pow5_inv_split_32[q], j)
74}
75
76@[direct_array_access; inline]
77fn mul_pow5_div_pow2(m u32, i u32, j int) u32 {
78 assert1(i < pow5_split_32.len, 'i < pow5_split_32.len')
79 return mul_shift_32(m, pow5_split_32[i], j)
80}
81
82fn pow5_factor_32(i_v u32) u32 {
83 mut v := i_v
84 for n := u32(0); true; n++ {
85 q := v / 5
86 r := v % 5
87 if r != 0 {
88 return n
89 }
90 v = q
91 }
92 return v
93}
94
95// multiple_of_power_of_five_32 reports whether v is divisible by 5^p.
96fn multiple_of_power_of_five_32(v u32, p u32) bool {
97 return pow5_factor_32(v) >= p
98}
99
100// multiple_of_power_of_two_32 reports whether v is divisible by 2^p.
101fn multiple_of_power_of_two_32(v u32, p u32) bool {
102 return u32(bits.trailing_zeros_32(v)) >= p
103}
104
105// log10_pow2 returns floor(log_10(2^e)).
106fn log10_pow2(e int) u32 {
107 // The first value this approximation fails for is 2^1651
108 // which is just greater than 10^297.
109 assert1(e >= 0, 'e >= 0')
110 assert1(e <= 1650, 'e <= 1650')
111 return (u32(e) * 78913) >> 18
112}
113
114// log10_pow5 returns floor(log_10(5^e)).
115fn log10_pow5(e int) u32 {
116 // The first value this approximation fails for is 5^2621
117 // which is just greater than 10^1832.
118 assert1(e >= 0, 'e >= 0')
119 assert1(e <= 2620, 'e <= 2620')
120 return (u32(e) * 732923) >> 20
121}
122
123// pow5_bits returns ceil(log_2(5^e)), or else 1 if e==0.
124fn pow5_bits(e int) int {
125 // This approximation works up to the point that the multiplication
126 // overflows at e = 3529. If the multiplication were done in 64 bits,
127 // it would fail at 5^4004 which is just greater than 2^9297.
128 assert1(e >= 0, 'e >= 0')
129 assert1(e <= 3528, 'e <= 3528')
130 return int(((u32(e) * 1217359) >> 19) + 1)
131}
132
133/*
13464 bit functions
135*/
136
137fn shift_right_128(v Uint128, shift int) u64 {
138 // The shift value is always modulo 64.
139 // In the current implementation of the 64-bit version
140 // of Ryu, the shift value is always < 64.
141 // (It is in the range [2, 59].)
142 // Check this here in case a future change requires larger shift
143 // values. In this case this function needs to be adjusted.
144 assert1(shift < 64, 'shift < 64')
145 return (v.hi << u64(64 - shift)) | (v.lo >> u32(shift))
146}
147
148fn mul_shift_64(m u64, mul Uint128, shift int) u64 {
149 hihi, hilo := bits.mul_64(m, mul.hi)
150 lohi, _ := bits.mul_64(m, mul.lo)
151 mut sum := Uint128{
152 lo: lohi + hilo
153 hi: hihi
154 }
155 if sum.lo < lohi {
156 sum.hi++ // overflow
157 }
158 return shift_right_128(sum, shift - 64)
159}
160
161fn pow5_factor_64(v_i u64) u32 {
162 mut v := v_i
163 for n := u32(0); true; n++ {
164 q := v / 5
165 r := v % 5
166 if r != 0 {
167 return n
168 }
169 v = q
170 }
171 return u32(0)
172}
173
174fn multiple_of_power_of_five_64(v u64, p u32) bool {
175 return pow5_factor_64(v) >= p
176}
177
178fn multiple_of_power_of_two_64(v u64, p u32) bool {
179 return u32(bits.trailing_zeros_64(v)) >= p
180}
181
182// dec_digits return the number of decimal digit of an u64
183pub fn dec_digits(n u64) int {
184 if n <= 9_999_999_999 { // 1-10
185 if n <= 99_999 { // 5
186 if n <= 99 { // 2
187 if n <= 9 { // 1
188 return 1
189 } else {
190 return 2
191 }
192 } else {
193 if n <= 999 { // 3
194 return 3
195 } else {
196 if n <= 9999 { // 4
197 return 4
198 } else {
199 return 5
200 }
201 }
202 }
203 } else {
204 if n <= 9_999_999 { // 7
205 if n <= 999_999 { // 6
206 return 6
207 } else {
208 return 7
209 }
210 } else {
211 if n <= 99_999_999 { // 8
212 return 8
213 } else {
214 if n <= 999_999_999 { // 9
215 return 9
216 }
217 return 10
218 }
219 }
220 }
221 } else {
222 if n <= 999_999_999_999_999 { // 5
223 if n <= 999_999_999_999 { // 2
224 if n <= 99_999_999_999 { // 1
225 return 11
226 } else {
227 return 12
228 }
229 } else {
230 if n <= 9_999_999_999_999 { // 3
231 return 13
232 } else {
233 if n <= 99_999_999_999_999 { // 4
234 return 14
235 } else {
236 return 15
237 }
238 }
239 }
240 } else {
241 if n <= 99_999_999_999_999_999 { // 7
242 if n <= 9_999_999_999_999_999 { // 6
243 return 16
244 } else {
245 return 17
246 }
247 } else {
248 if n <= 999_999_999_999_999_999 { // 8
249 return 18
250 } else {
251 if n <= 9_999_999_999_999_999_999 { // 9
252 return 19
253 }
254 return 20
255 }
256 }
257 }
258 }
259}
260