v2 / vlib / math / bits / bits.v
632 lines · 565 sloc · 18.97 KB · 0832a68bd714695d292aef2ca9b08d16b9a86516
Raw
1// Copyright (c) 2019-2024 Alexander Medvednikov. All rights reserved.
2// Use of this source code is governed by an MIT license
3// that can be found in the LICENSE file.
4module bits
5
6// See http://supertech.csail.mit.edu/papers/debruijn.pdf
7const de_bruijn32 = u32(0x077CB531)
8const de_bruijn32tab = [u8(0), 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, 31, 27, 13,
9 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9]!
10const de_bruijn64 = u64(0x03f79d71b4ca8b09)
11const de_bruijn64tab = [u8(0), 1, 56, 2, 57, 49, 28, 3, 61, 58, 42, 50, 38, 29, 17, 4, 62, 47,
12 59, 36, 45, 43, 51, 22, 53, 39, 33, 30, 24, 18, 12, 5, 63, 55, 48, 27, 60, 41, 37, 16, 46,
13 35, 44, 21, 52, 32, 23, 11, 54, 26, 40, 15, 34, 20, 31, 10, 25, 14, 19, 9, 13, 8, 7, 6]!
14
15const m0 = u64(0x5555555555555555) // 01010101 ...
16
17const m1 = u64(0x3333333333333333) // 00110011 ...
18
19const m2 = u64(0x0f0f0f0f0f0f0f0f) // 00001111 ...
20
21const m3 = u64(0x00ff00ff00ff00ff) // etc.
22
23const m4 = u64(0x0000ffff0000ffff)
24
25// --- LeadingZeros ---
26// leading_zeros_8 returns the number of leading zero bits in x; the result is 8 for x == 0.
27@[inline]
28pub fn leading_zeros_8(x u8) int {
29 return leading_zeros_8_default(x)
30}
31
32@[inline]
33fn leading_zeros_8_default(x u8) int {
34 return 8 - len_8(x)
35}
36
37// leading_zeros_16 returns the number of leading zero bits in x; the result is 16 for x == 0.
38@[inline]
39pub fn leading_zeros_16(x u16) int {
40 return leading_zeros_16_default(x)
41}
42
43@[inline]
44fn leading_zeros_16_default(x u16) int {
45 return 16 - len_16(x)
46}
47
48// leading_zeros_32 returns the number of leading zero bits in x; the result is 32 for x == 0.
49@[inline]
50pub fn leading_zeros_32(x u32) int {
51 return leading_zeros_32_default(x)
52}
53
54@[inline]
55fn leading_zeros_32_default(x u32) int {
56 return 32 - len_32(x)
57}
58
59// leading_zeros_64 returns the number of leading zero bits in x; the result is 64 for x == 0.
60@[inline]
61pub fn leading_zeros_64(x u64) int {
62 return leading_zeros_64_default(x)
63}
64
65@[inline]
66fn leading_zeros_64_default(x u64) int {
67 return 64 - len_64(x)
68}
69
70// --- TrailingZeros ---
71// trailing_zeros_8 returns the number of trailing zero bits in x; the result is 8 for x == 0.
72@[inline]
73pub fn trailing_zeros_8(x u8) int {
74 return trailing_zeros_8_default(x)
75}
76
77@[direct_array_access; inline]
78fn trailing_zeros_8_default(x u8) int {
79 return int(ntz_8_tab[x])
80}
81
82// trailing_zeros_16 returns the number of trailing zero bits in x; the result is 16 for x == 0.
83@[inline]
84pub fn trailing_zeros_16(x u16) int {
85 return trailing_zeros_16_default(x)
86}
87
88@[direct_array_access; ignore_overflow; inline]
89fn trailing_zeros_16_default(x u16) int {
90 if x == 0 {
91 return 16
92 }
93 // see comment in trailing_zeros_64
94 return int(de_bruijn32tab[u32(x & -x) * de_bruijn32 >> (32 - 5)])
95}
96
97// trailing_zeros_32 returns the number of trailing zero bits in x; the result is 32 for x == 0.
98@[inline]
99pub fn trailing_zeros_32(x u32) int {
100 return trailing_zeros_32_default(x)
101}
102
103@[direct_array_access; ignore_overflow; inline]
104fn trailing_zeros_32_default(x u32) int {
105 if x == 0 {
106 return 32
107 }
108 // see comment in trailing_zeros_64
109 return int(de_bruijn32tab[(x & -x) * de_bruijn32 >> (32 - 5)])
110}
111
112// trailing_zeros_64 returns the number of trailing zero bits in x; the result is 64 for x == 0.
113@[inline]
114pub fn trailing_zeros_64(x u64) int {
115 return trailing_zeros_64_default(x)
116}
117
118@[direct_array_access; ignore_overflow; inline]
119fn trailing_zeros_64_default(x u64) int {
120 if x == 0 {
121 return 64
122 }
123 // If popcount is fast, replace code below with return popcount(^x & (x - 1)).
124 //
125 // x & -x leaves only the right-most bit set in the word. Let k be the
126 // index of that bit. Since only a single bit is set, the value is two
127 // to the power of k. Multiplying by a power of two is equivalent to
128 // left shifting, in this case by k bits. The de Bruijn (64 bit) constant
129 // is such that all six bit, consecutive substrings are distinct.
130 // Therefore, if we have a left shifted version of this constant we can
131 // find by how many bits it was shifted by looking at which six bit
132 // substring ended up at the top of the word.
133 // (Knuth, volume 4, section 7.3.1)
134 return int(de_bruijn64tab[int((x & -x) * de_bruijn64 >> (64 - 6))])
135}
136
137// --- OnesCount ---
138// ones_count_8 returns the number of one bits ("population count") in x.
139@[inline]
140pub fn ones_count_8(x u8) int {
141 return ones_count_8_default(x)
142}
143
144@[direct_array_access; inline]
145fn ones_count_8_default(x u8) int {
146 return int(pop_8_tab[x])
147}
148
149// ones_count_16 returns the number of one bits ("population count") in x.
150@[inline]
151pub fn ones_count_16(x u16) int {
152 return ones_count_16_default(x)
153}
154
155@[direct_array_access; inline]
156fn ones_count_16_default(x u16) int {
157 return int(pop_8_tab[x >> 8] + pop_8_tab[x & u16(0xff)])
158}
159
160// ones_count_32 returns the number of one bits ("population count") in x.
161@[inline]
162pub fn ones_count_32(x u32) int {
163 return ones_count_32_default(x)
164}
165
166@[direct_array_access; inline]
167fn ones_count_32_default(x u32) int {
168 return int(pop_8_tab[x >> 24] + pop_8_tab[(x >> 16) & 0xff] + pop_8_tab[(x >> 8) & 0xff] +
169 pop_8_tab[x & u32(0xff)])
170}
171
172// ones_count_64 returns the number of one bits ("population count") in x.
173@[inline]
174pub fn ones_count_64(x u64) int {
175 return ones_count_64_default(x)
176}
177
178fn ones_count_64_default(x u64) int {
179 // Implementation: Parallel summing of adjacent bits.
180 // See "Hacker's Delight", Chap. 5: Counting Bits.
181 // The following pattern shows the general approach:
182 //
183 // x = x>>1&(m0&m) + x&(m0&m)
184 // x = x>>2&(m1&m) + x&(m1&m)
185 // x = x>>4&(m2&m) + x&(m2&m)
186 // x = x>>8&(m3&m) + x&(m3&m)
187 // x = x>>16&(m4&m) + x&(m4&m)
188 // x = x>>32&(m5&m) + x&(m5&m)
189 // return int(x)
190 //
191 // Masking (& operations) can be left away when there's no
192 // danger that a field's sum will carry over into the next
193 // field: Since the result cannot be > 64, 8 bits is enough
194 // and we can ignore the masks for the shifts by 8 and up.
195 // Per "Hacker's Delight", the first line can be simplified
196 // more, but it saves at best one instruction, so we leave
197 // it alone for clarity.
198 mut y := ((x >> u64(1)) & (m0 & max_u64)) + (x & (m0 & max_u64))
199 y = ((y >> u64(2)) & (m1 & max_u64)) + (y & (m1 & max_u64))
200 y = ((y >> 4) + y) & (m2 & max_u64)
201 y += y >> 8
202 y += y >> 16
203 y += y >> 32
204 return int(y) & ((1 << 7) - 1)
205}
206
207const n8 = u8(8)
208const n16 = u16(16)
209const n32 = u32(32)
210const n64 = u64(64)
211
212// --- RotateLeft ---
213// rotate_left_8 returns the value of x rotated left by (k mod 8) bits.
214// To rotate x right by k bits, call rotate_left_8(x, -k).
215//
216// This function's execution time does not depend on the inputs.
217@[inline]
218pub fn rotate_left_8(x u8, k int) u8 {
219 s := u8(k) & (n8 - u8(1))
220 return (x << s) | (x >> (n8 - s))
221}
222
223// rotate_left_16 returns the value of x rotated left by (k mod 16) bits.
224// To rotate x right by k bits, call rotate_left_16(x, -k).
225//
226// This function's execution time does not depend on the inputs.
227@[inline]
228pub fn rotate_left_16(x u16, k int) u16 {
229 s := u16(k) & (n16 - u16(1))
230 return (x << s) | (x >> (n16 - s))
231}
232
233// rotate_left_32 returns the value of x rotated left by (k mod 32) bits.
234// To rotate x right by k bits, call rotate_left_32(x, -k).
235//
236// This function's execution time does not depend on the inputs.
237@[inline]
238pub fn rotate_left_32(x u32, k int) u32 {
239 s := u32(k) & (n32 - u32(1))
240 return (x << s) | (x >> (n32 - s))
241}
242
243// rotate_left_64 returns the value of x rotated left by (k mod 64) bits.
244// To rotate x right by k bits, call rotate_left_64(x, -k).
245//
246// This function's execution time does not depend on the inputs.
247@[inline]
248pub fn rotate_left_64(x u64, k int) u64 {
249 s := u64(k) & (n64 - u64(1))
250 return (x << s) | (x >> (n64 - s))
251}
252
253// --- Reverse ---
254// reverse_8 returns the value of x with its bits in reversed order.
255@[direct_array_access; inline]
256pub fn reverse_8(x u8) u8 {
257 return rev_8_tab[x]
258}
259
260// reverse_16 returns the value of x with its bits in reversed order.
261@[direct_array_access; inline]
262pub fn reverse_16(x u16) u16 {
263 return u16(rev_8_tab[x >> 8]) | (u16(rev_8_tab[x & u16(0xff)]) << 8)
264}
265
266// reverse_32 returns the value of x with its bits in reversed order.
267@[inline]
268pub fn reverse_32(x u32) u32 {
269 mut y := (((x >> u32(1)) & (m0 & max_u32)) | ((x & (m0 & max_u32)) << 1))
270 y = (((y >> u32(2)) & (m1 & max_u32)) | ((y & (m1 & max_u32)) << u32(2)))
271 y = (((y >> u32(4)) & (m2 & max_u32)) | ((y & (m2 & max_u32)) << u32(4)))
272 return reverse_bytes_32(u32(y))
273}
274
275// reverse_64 returns the value of x with its bits in reversed order.
276@[inline]
277pub fn reverse_64(x u64) u64 {
278 mut y := (((x >> u64(1)) & (m0 & max_u64)) | ((x & (m0 & max_u64)) << 1))
279 y = (((y >> u64(2)) & (m1 & max_u64)) | ((y & (m1 & max_u64)) << 2))
280 y = (((y >> u64(4)) & (m2 & max_u64)) | ((y & (m2 & max_u64)) << 4))
281 return reverse_bytes_64(y)
282}
283
284// --- ReverseBytes ---
285// reverse_bytes_16 returns the value of x with its bytes in reversed order.
286//
287// This function's execution time does not depend on the inputs.
288@[inline]
289pub fn reverse_bytes_16(x u16) u16 {
290 return (x >> 8) | (x << 8)
291}
292
293// reverse_bytes_32 returns the value of x with its bytes in reversed order.
294//
295// This function's execution time does not depend on the inputs.
296@[inline]
297pub fn reverse_bytes_32(x u32) u32 {
298 y := (((x >> u32(8)) & (m3 & max_u32)) | ((x & (m3 & max_u32)) << u32(8)))
299 return u32((y >> 16) | (y << 16))
300}
301
302// reverse_bytes_64 returns the value of x with its bytes in reversed order.
303//
304// This function's execution time does not depend on the inputs.
305@[inline]
306pub fn reverse_bytes_64(x u64) u64 {
307 mut y := (((x >> u64(8)) & (m3 & max_u64)) | ((x & (m3 & max_u64)) << u64(8)))
308 y = (((y >> u64(16)) & (m4 & max_u64)) | ((y & (m4 & max_u64)) << u64(16)))
309 return (y >> 32) | (y << 32)
310}
311
312// --- Len ---
313// len_8 returns the minimum number of bits required to represent x; the result is 0 for x == 0.
314@[direct_array_access]
315pub fn len_8(x u8) int {
316 return int(len_8_tab[x])
317}
318
319// len_16 returns the minimum number of bits required to represent x; the result is 0 for x == 0.
320@[direct_array_access; ignore_overflow]
321pub fn len_16(x u16) int {
322 mut y := x
323 mut n := 0
324 if y >= 1 << 8 {
325 y >>= 8
326 n = 8
327 }
328 return n + int(len_8_tab[int(y)])
329}
330
331// len_32 returns the minimum number of bits required to represent x; the result is 0 for x == 0.
332@[direct_array_access; ignore_overflow]
333pub fn len_32(x u32) int {
334 mut y := x
335 mut n := 0
336 if y >= (1 << 16) {
337 y >>= 16
338 n = 16
339 }
340 if y >= (1 << 8) {
341 y >>= 8
342 n += 8
343 }
344 return n + int(len_8_tab[int(y)])
345}
346
347// len_64 returns the minimum number of bits required to represent x; the result is 0 for x == 0.
348@[direct_array_access]
349pub fn len_64(x u64) int {
350 mut y := x
351 mut n := 0
352 if y >= u64(1) << u64(32) {
353 y >>= 32
354 n = 32
355 }
356 if y >= u64(1) << u64(16) {
357 y >>= 16
358 n += 16
359 }
360 if y >= u64(1) << u64(8) {
361 y >>= 8
362 n += 8
363 }
364 return n + int(len_8_tab[int(y)])
365}
366
367// --- Add with carry ---
368// Add returns the sum with carry of x, y and carry: sum = x + y + carry.
369// The carry input must be 0 or 1; otherwise the behavior is undefined.
370// The carryOut output is guaranteed to be 0 or 1.
371// add_32 returns the sum with carry of x, y and carry: sum = x + y + carry.
372// The carry input must be 0 or 1; otherwise the behavior is undefined.
373// The carryOut output is guaranteed to be 0 or 1.
374// This function's execution time does not depend on the inputs.
375@[ignore_overflow]
376pub fn add_32(x u32, y u32, carry u32) (u32, u32) {
377 sum64 := u64(x) + u64(y) + u64(carry)
378 sum := u32(sum64)
379 carry_out := u32(sum64 >> 32)
380 return sum, carry_out
381}
382
383// add_64 returns the sum with carry of x, y and carry: sum = x + y + carry.
384// The carry input must be 0 or 1; otherwise the behavior is undefined.
385// The carryOut output is guaranteed to be 0 or 1.
386// This function's execution time does not depend on the inputs.
387@[ignore_overflow]
388pub fn add_64(x u64, y u64, carry u64) (u64, u64) {
389 sum := x + y + carry
390 // The sum will overflow if both top bits are set (x & y) or if one of them
391 // is (x | y), and a carry from the lower place happened. If such a carry
392 // happens, the top bit will be 1 + 0 + 1 = 0 (&^ sum).
393 carry_out := ((x & y) | ((x | y) & ~sum)) >> 63
394 return sum, carry_out
395}
396
397// --- Subtract with borrow ---
398// Sub returns the difference of x, y and borrow: diff = x - y - borrow.
399// The borrow input must be 0 or 1; otherwise the behavior is undefined.
400// The borrowOut output is guaranteed to be 0 or 1.
401// sub_32 returns the difference of x, y and borrow, diff = x - y - borrow.
402// The borrow input must be 0 or 1; otherwise the behavior is undefined.
403// The borrowOut output is guaranteed to be 0 or 1.
404// This function's execution time does not depend on the inputs.
405@[ignore_overflow]
406pub fn sub_32(x u32, y u32, borrow u32) (u32, u32) {
407 diff := x - y - borrow
408 // The difference will underflow if the top bit of x is not set and the top
409 // bit of y is set (^x & y) or if they are the same (^(x ^ y)) and a borrow
410 // from the lower place happens. If that borrow happens, the result will be
411 // 1 - 1 - 1 = 0 - 0 - 1 = 1 (& diff).
412 borrow_out := ((~x & y) | (~(x ^ y) & diff)) >> 31
413 return diff, borrow_out
414}
415
416// sub_64 returns the difference of x, y and borrow: diff = x - y - borrow.
417// The borrow input must be 0 or 1; otherwise the behavior is undefined.
418// The borrowOut output is guaranteed to be 0 or 1.
419// This function's execution time does not depend on the inputs.
420@[ignore_overflow]
421pub fn sub_64(x u64, y u64, borrow u64) (u64, u64) {
422 diff := x - y - borrow
423 // See Sub32 for the bit logic.
424 borrow_out := ((~x & y) | (~(x ^ y) & diff)) >> 63
425 return diff, borrow_out
426}
427
428// --- Full-width multiply ---
429
430@[markused]
431pub const two32 = u64(0x100000000)
432const mask32 = two32 - 1
433const overflow_error = 'Overflow Error'
434const divide_error = 'Divide Error'
435
436// mul_32 returns the 64-bit product of x and y: (hi, lo) = x * y
437// with the product bits' upper half returned in hi and the lower
438// half returned in lo.
439//
440// This function's execution time does not depend on the inputs.
441@[inline]
442pub fn mul_32(x u32, y u32) (u32, u32) {
443 return mul_32_default(x, y)
444}
445
446@[inline]
447fn mul_32_default(x u32, y u32) (u32, u32) {
448 tmp := u64(x) * u64(y)
449 hi := u32(tmp >> 32)
450 lo := u32(tmp)
451 return hi, lo
452}
453
454// mul_64 returns the 128-bit product of x and y: (hi, lo) = x * y
455// with the product bits' upper half returned in hi and the lower
456// half returned in lo.
457//
458// This function's execution time does not depend on the inputs.
459@[inline]
460pub fn mul_64(x u64, y u64) (u64, u64) {
461 return mul_64_default(x, y)
462}
463
464fn mul_64_default(x u64, y u64) (u64, u64) {
465 x0 := x & mask32
466 x1 := x >> 32
467 y0 := y & mask32
468 y1 := y >> 32
469 w0 := x0 * y0
470 t := x1 * y0 + (w0 >> 32)
471 mut w1 := t & mask32
472 w2 := t >> 32
473 w1 += x0 * y1
474 hi := x1 * y1 + w2 + (w1 >> 32)
475 lo := x * y
476 return hi, lo
477}
478
479// mul_add_32 returns the 64-bit result of x * y + z: (hi, lo) = x * y + z
480// with the result bits' upper half returned in hi and the lower
481// half returned in lo.
482@[inline]
483pub fn mul_add_32(x u32, y u32, z u32) (u32, u32) {
484 return mul_add_32_default(x, y, z)
485}
486
487@[inline]
488fn mul_add_32_default(x u32, y u32, z u32) (u32, u32) {
489 tmp := u64(x) * u64(y) + u64(z)
490 hi := u32(tmp >> 32)
491 lo := u32(tmp)
492 return hi, lo
493}
494
495// mul_add_64 returns the 128-bit result of x * y + z: (hi, lo) = x * y + z
496// with the result bits' upper half returned in hi and the lower
497// half returned in lo.
498@[inline]
499pub fn mul_add_64(x u64, y u64, z u64) (u64, u64) {
500 return mul_add_64_default(x, y, z)
501}
502
503@[inline]
504fn mul_add_64_default(x u64, y u64, z u64) (u64, u64) {
505 h, l := mul_64(x, y)
506 lo := l + z
507 hi := h + u64(lo < l)
508 return hi, lo
509}
510
511// --- Full-width divide ---
512// div_32 returns the quotient and remainder of (hi, lo) divided by y:
513// quo = (hi, lo)/y, rem = (hi, lo)%y with the dividend bits' upper
514// half in parameter hi and the lower half in parameter lo.
515// div_32 panics for y == 0 (division by zero) or y <= hi (quotient overflow).
516@[inline]
517pub fn div_32(hi u32, lo u32, y u32) (u32, u32) {
518 return div_32_default(hi, lo, y)
519}
520
521fn div_32_default(hi u32, lo u32, y u32) (u32, u32) {
522 if y != 0 && y <= hi {
523 panic(overflow_error)
524 }
525 z := (u64(hi) << 32) | u64(lo)
526 quo := u32(z / u64(y))
527 rem := u32(z % u64(y))
528 return quo, rem
529}
530
531// div_64 returns the quotient and remainder of (hi, lo) divided by y:
532// quo = (hi, lo)/y, rem = (hi, lo)%y with the dividend bits' upper
533// half in parameter hi and the lower half in parameter lo.
534// div_64 panics for y == 0 (division by zero) or y <= hi (quotient overflow).
535@[inline]
536pub fn div_64(hi u64, lo u64, y1 u64) (u64, u64) {
537 return div_64_default(hi, lo, y1)
538}
539
540fn div_64_default(hi u64, lo u64, y1 u64) (u64, u64) {
541 mut y := y1
542 if y == 0 {
543 panic(overflow_error)
544 }
545 if y <= hi {
546 panic(overflow_error)
547 }
548 s := u32(leading_zeros_64(y))
549 y <<= s
550 yn1 := y >> 32
551 yn0 := y & mask32
552 ss1 := (hi << s)
553 xxx := 64 - s
554 mut ss2 := lo >> xxx
555 if xxx == 64 {
556 // in Go, shifting right a u64 number, 64 times produces 0 *always*.
557 // See https://go.dev/ref/spec
558 // > The shift operators implement arithmetic shifts if the left operand
559 // > is a signed integer and logical shifts if it is an unsigned integer.
560 // > There is no upper limit on the shift count.
561 // > Shifts behave as if the left operand is shifted n times by 1 for a shift count of n.
562 // > As a result, x << 1 is the same as x*2 and x >> 1 is the same as x/2
563 // > but truncated towards negative infinity.
564 //
565 // In V, that is currently left to whatever C is doing, which is apparently a NOP.
566 // This function was a direct port of https://cs.opensource.google/go/go/+/refs/tags/go1.17.6:src/math/bits/bits.go;l=512,
567 // so we have to use the Go behaviour.
568 // TODO: reconsider whether we need to adopt it for our shift ops, or just use function wrappers that do it.
569 ss2 = 0
570 }
571 un32 := ss1 | ss2
572 un10 := lo << s
573 un1 := un10 >> 32
574 un0 := un10 & mask32
575 mut q1 := un32 / yn1
576 mut rhat := un32 - (q1 * yn1)
577 for q1 >= two32 || (q1 * yn0) > ((two32 * rhat) + un1) {
578 q1--
579 rhat += yn1
580 if rhat >= two32 {
581 break
582 }
583 }
584 un21 := (un32 * two32) + (un1 - (q1 * y))
585 mut q0 := un21 / yn1
586 rhat = un21 - q0 * yn1
587 for q0 >= two32 || (q0 * yn0) > ((two32 * rhat) + un0) {
588 q0--
589 rhat += yn1
590 if rhat >= two32 {
591 break
592 }
593 }
594 qq := ((q1 * two32) + q0)
595 rr := ((un21 * two32) + un0 - (q0 * y)) >> s
596 return qq, rr
597}
598
599// rem_32 returns the remainder of (hi, lo) divided by y. Rem32 panics
600// for y == 0 (division by zero) but, unlike Div32, it doesn't panic
601// on a quotient overflow.
602pub fn rem_32(hi u32, lo u32, y u32) u32 {
603 return u32(((u64(hi) << 32) | u64(lo)) % u64(y))
604}
605
606// rem_64 returns the remainder of (hi, lo) divided by y. Rem64 panics
607// for y == 0 (division by zero) but, unlike div_64, it doesn't panic
608// on a quotient overflow.
609pub fn rem_64(hi u64, lo u64, y u64) u64 {
610 // We scale down hi so that hi < y, then use div_64 to compute the
611 // rem with the guarantee that it won't panic on quotient overflow.
612 // Given that
613 // hi ≡ hi%y (mod y)
614 // we have
615 // hi<<64 + lo ≡ (hi%y)<<64 + lo (mod y)
616 _, rem := div_64(hi % y, lo, y)
617 return rem
618}
619
620// normalize returns a normal number y and exponent exp
621// satisfying x == y × 2**exp. It assumes x is finite and non-zero.
622pub fn normalize(x f64) (f64, int) {
623 smallest_normal := 2.2250738585072014e-308 // 2**-1022
624 if (if x > 0.0 {
625 x
626 } else {
627 -x
628 }) < smallest_normal {
629 return x * (u64(1) << u64(52)), -52
630 }
631 return x, 0
632}
633