math.big: add .bytes() and .bytes_trimmed() methods, `big.from_int(1024).bytes_trimmed() == [byte(0x00), 0x04]`

pull/10863/head
Delyan Angelov 2021-07-19 16:42:37 +03:00
parent 9127e202d5
commit 732d8101e0
No known key found for this signature in database
GPG Key ID: 66886C0F12D595ED
2 changed files with 56 additions and 0 deletions

View File

@ -282,3 +282,37 @@ pub fn factorial(nn Number) Number {
pub fn fact(n int) Number {
return factorial(from_int(n))
}
// bytes returns an array of the bytes for the number `n`,
// in little endian format, where .bytes()[0] is the least
// significant byte. The result is NOT trimmed, and will contain 0s, even
// after the significant bytes.
// This method is faster than .bytes_trimmed(), but may be less convenient.
// Example: assert big.from_int(1).bytes()[0] == byte(0x01)
// Example: assert big.from_int(1024).bytes()[1] == byte(0x04)
// Example: assert big.from_int(1048576).bytes()[2] == byte(0x10)
pub fn (n &Number) bytes() []byte {
mut res := []byte{len: 128, init: 0}
unsafe { C.memcpy(res.data, n, 128) }
return res
}
// bytes_trimmed returns an array of the bytes for the number `n`,
// in little endian format, where .bytes_trimmed()[0] is the least
// significant byte. The result is trimmed, so that *the last* byte
// of the result is also the the last meaningfull byte, != 0 .
// Example: assert big.from_int(1).bytes_trimmed() == [byte(0x01)]
// Example: assert big.from_int(1024).bytes_trimmed() == [byte(0x00), 0x04]
// Example: assert big.from_int(1048576).bytes_trimmed() == [byte(0x00), 0x00, 0x10]
pub fn (n &Number) bytes_trimmed() []byte {
mut res := []byte{len: 128, init: 0}
unsafe { C.memcpy(res.data, n, 128) }
mut non_zero_idx := 127
for ; non_zero_idx >= 0; non_zero_idx-- {
if res[non_zero_idx] != 0 {
break
}
}
res.trim(non_zero_idx + 1)
return res
}

View File

@ -126,3 +126,25 @@ fn test_factorial() {
f100 := big.factorial(big.from_u64(100))
assert f100.hexstr() == '1b30964ec395dc24069528d54bbda40d16e966ef9a70eb21b5b2943a321cdf10391745570cca9420c6ecb3b72ed2ee8b02ea2735c61a000000000000000000000000'
}
fn trimbytes(n int, x []byte) []byte {
mut res := x.clone()
res.trim(n)
return res
}
fn test_bytes() {
assert big.from_int(0).bytes().len == 128
assert big.from_hex_string('e'.repeat(100)).bytes().len == 128
assert trimbytes(3, big.from_int(1).bytes()) == [byte(0x01), 0x00, 0x00]
assert trimbytes(3, big.from_int(1024).bytes()) == [byte(0x00), 0x04, 0x00]
assert trimbytes(3, big.from_int(1048576).bytes()) == [byte(0x00), 0x00, 0x10]
}
fn test_bytes_trimmed() {
assert big.from_int(0).bytes_trimmed().len == 0
assert big.from_hex_string('AB'.repeat(50)).bytes_trimmed().len == 50
assert big.from_int(1).bytes_trimmed() == [byte(0x01)]
assert big.from_int(1024).bytes_trimmed() == [byte(0x00), 0x04]
assert big.from_int(1048576).bytes_trimmed() == [byte(0x00), 0x00, 0x10]
}