math.big: make big.from_string take a decimal, add big.from_hex_string

pull/7467/head
Delyan Angelov 2020-12-22 09:44:59 +02:00
parent b47daad40d
commit 93c0f503a2
3 changed files with 38 additions and 12 deletions

View File

@ -60,6 +60,7 @@ const (
'vlib/cli/', 'vlib/cli/',
'vlib/flag/', 'vlib/flag/',
'vlib/gg/gg.v', 'vlib/gg/gg.v',
'vlib/math/big/',
'vlib/os/', 'vlib/os/',
'vlib/semver/', 'vlib/semver/',
'vlib/strings/', 'vlib/strings/',

View File

@ -75,26 +75,28 @@ fn C.bignum_isqrt(a &Number, b &Number)
// copy src number to dst number // copy src number to dst number
fn C.bignum_assign(dst &Number, src &Number) fn C.bignum_assign(dst &Number, src &Number)
// ////////////////////////////////////////////////////////// // new returns a bignum, initialized to 0
// conversion actions to/from big numbers:
pub fn new() Number { pub fn new() Number {
return Number{} return Number{}
} }
// conversion actions to/from big numbers:
// from_int converts an ordinary int number `i` to big.Number
pub fn from_int(i int) Number { pub fn from_int(i int) Number {
n := Number{} n := Number{}
C.bignum_from_int(&n, i) C.bignum_from_int(&n, i)
return n return n
} }
// from_u64 converts an ordinary u64 number `u` to big.Number
pub fn from_u64(u u64) Number { pub fn from_u64(u u64) Number {
n := Number{} n := Number{}
C.bignum_from_int(&n, u) C.bignum_from_int(&n, u)
return n return n
} }
// Converts a hex string to big.Number. // from_hex_string converts a hex string to big.Number
pub fn from_string(input string) Number { pub fn from_hex_string(input string) Number {
mut s := input.trim_prefix('0x') mut s := input.trim_prefix('0x')
if s.len == 0 { if s.len == 0 {
s = '0' s = '0'
@ -106,6 +108,17 @@ pub fn from_string(input string) Number {
return n return n
} }
// from_string converts a decimal string to big.Number
pub fn from_string(input string) Number {
mut n := from_int(0)
for _, c in input {
d := from_int(int(c - `0`))
n = (n * ten) + d
}
return n
}
// .int() converts (a small) big.Number `n` to an ordinary integer.
pub fn (n Number) int() int { pub fn (n Number) int() int {
r := C.bignum_to_int(&n) r := C.bignum_to_int(&n)
return r return r
@ -115,7 +128,7 @@ const (
ten = from_int(10) ten = from_int(10)
) )
// Decimal representation for the big unsigned integer number n. // .str returns a decimal representation of the big unsigned integer number n.
pub fn (n Number) str() string { pub fn (n Number) str() string {
if n.is_zero() { if n.is_zero() {
return '0' return '0'
@ -131,10 +144,11 @@ pub fn (n Number) str() string {
return digits.reverse().bytestr() return digits.reverse().bytestr()
} }
// .hexstr returns a hexadecimal representation of the bignum `n`
pub fn (n Number) hexstr() string { pub fn (n Number) hexstr() string {
mut buf := [8192]byte{} mut buf := [8192]byte{}
// NB: C.bignum_to_string(), returns the HEXADECIMAL representation of the bignum n
C.bignum_to_string(&n, buf, 8192) C.bignum_to_string(&n, buf, 8192)
// NB: bignum_to_string , returns the HEXADECIMAL representation of the bignum n
s := tos_clone(buf) s := tos_clone(buf)
if s.len == 0 { if s.len == 0 {
return '0' return '0'

View File

@ -78,13 +78,24 @@ fn test_mod() {
} }
fn test_from_str() { fn test_from_str() {
assert big.from_string('').hexstr() == '0' assert big.from_string('9870123').str() == '9870123'
assert big.from_string('1').hexstr() == '1' assert big.from_string('').str() == '0'
assert big.from_string('0').hexstr() == '0' assert big.from_string('0').str() == '0'
assert big.from_string('0x123').hexstr() == '123' assert big.from_string('1').str() == '1'
for i := 1; i < 307; i += 61 {
input := '9'.repeat(i)
out := big.from_string(input).str()
// eprintln('>> i: $i input: $input.str()')
// eprintln('>> i: $i out: $out.str()')
assert input == out
}
}
fn test_from_hex_str() {
assert big.from_hex_string('0x123').hexstr() == '123'
for i in 1 .. 33 { for i in 1 .. 33 {
input := 'e'.repeat(i) input := 'e'.repeat(i)
out := big.from_string(input).hexstr() out := big.from_hex_string(input).hexstr()
assert input == out assert input == out
} }
assert big.from_string('0').hexstr() == '0' assert big.from_string('0').hexstr() == '0'
@ -98,7 +109,7 @@ fn test_str() {
assert big.from_u64(4398046511104).str() == '4398046511104' assert big.from_u64(4398046511104).str() == '4398046511104'
assert big.from_int(4294967295).str() == '18446744073709551615' assert big.from_int(4294967295).str() == '18446744073709551615'
assert big.from_int(-1).str() == '18446744073709551615' assert big.from_int(-1).str() == '18446744073709551615'
assert big.from_string('e'.repeat(80)).str() == assert big.from_hex_string('e'.repeat(80)).str() ==
'1993587900192849410235353592424915306962524220866209251950572167300738410728597846688097947807470' '1993587900192849410235353592424915306962524220866209251950572167300738410728597846688097947807470'
} }