2020-02-03 05:00:36 +01:00
|
|
|
// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved.
|
2019-09-17 21:03:54 +02:00
|
|
|
// Use of this source code is governed by an MIT license
|
|
|
|
// that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
module rand
|
|
|
|
|
2020-04-26 11:56:27 +02:00
|
|
|
import math.bits
|
|
|
|
import encoding.binary
|
2019-09-17 21:03:54 +02:00
|
|
|
|
2019-09-23 22:17:06 +02:00
|
|
|
pub fn int_u64(max u64) ?u64 {
|
2020-02-09 09:25:27 +01:00
|
|
|
bitlen := bits.len_64(max)
|
2019-09-17 21:03:54 +02:00
|
|
|
if bitlen == 0 {
|
|
|
|
return u64(0)
|
|
|
|
}
|
|
|
|
k := (bitlen + 7) / 8
|
|
|
|
mut b := u64(bitlen % 8)
|
|
|
|
if b == u64(0) {
|
|
|
|
b = u64(8)
|
|
|
|
}
|
|
|
|
mut n := u64(0)
|
|
|
|
for {
|
2020-08-29 01:58:03 +02:00
|
|
|
mut bytes := read(k)?
|
2019-09-17 21:03:54 +02:00
|
|
|
bytes[0] &= byte(int(u64(1)<<b) - 1)
|
|
|
|
x := bytes_to_u64(bytes)
|
|
|
|
n = x[0]
|
2019-09-18 15:12:16 +02:00
|
|
|
// NOTE: maybe until we have bigint could do it another way?
|
|
|
|
// if x.len > 1 {
|
|
|
|
// n = u64(u32(x[1])<<u32(32)) | n
|
|
|
|
// }
|
2019-09-17 21:03:54 +02:00
|
|
|
if n < max {
|
|
|
|
return n
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return n
|
|
|
|
}
|
|
|
|
|
2019-09-23 22:17:06 +02:00
|
|
|
fn bytes_to_u64(b []byte) []u64 {
|
2019-09-18 15:12:16 +02:00
|
|
|
ws := 64/8
|
2020-06-27 21:46:04 +02:00
|
|
|
mut z := []u64{len:((b.len + ws - 1) / ws)}
|
2019-09-17 21:03:54 +02:00
|
|
|
mut i := b.len
|
2019-09-18 15:12:16 +02:00
|
|
|
for k := 0; i >= ws; k++ {
|
2020-02-02 02:50:46 +01:00
|
|
|
z[k] = binary.big_endian_u64(b[i-ws..i])
|
2019-09-18 15:12:16 +02:00
|
|
|
i -= ws
|
2019-09-17 21:03:54 +02:00
|
|
|
}
|
|
|
|
if i > 0 {
|
|
|
|
mut d := u64(0)
|
|
|
|
for s := u64(0); i > 0; s += u64(8) {
|
2020-01-23 22:49:13 +01:00
|
|
|
d |= u64(b[i-1]) << s
|
2019-09-17 21:03:54 +02:00
|
|
|
i--
|
|
|
|
}
|
|
|
|
z[z.len-1] = d
|
|
|
|
}
|
|
|
|
return z
|
|
|
|
}
|