mirror of
https://github.com/vlang/v.git
synced 2025-09-13 14:32:26 +03:00
math.big: restore and refactor str() and integer_from_string() (#25154)
Some checks are pending
Graphics CI / gg-regressions (push) Waiting to run
vlib modules CI / build-module-docs (push) Waiting to run
Shy and PV CI / v-compiles-puzzle-vibes (push) Waiting to run
Sanitized CI / sanitize-undefined-clang (push) Waiting to run
Sanitized CI / sanitize-undefined-gcc (push) Waiting to run
Sanitized CI / tests-sanitize-address-clang (push) Waiting to run
Sanitized CI / sanitize-address-msvc (push) Waiting to run
Sanitized CI / sanitize-address-gcc (push) Waiting to run
Sanitized CI / sanitize-memory-clang (push) Waiting to run
sdl CI / v-compiles-sdl-examples (push) Waiting to run
Time CI / time-windows (push) Waiting to run
Time CI / time-linux (push) Waiting to run
Time CI / time-macos (push) Waiting to run
toml CI / toml-module-pass-external-test-suites (push) Waiting to run
Tools CI / tools-windows (msvc) (push) Waiting to run
Tools CI / tools-windows (tcc) (push) Waiting to run
Tools CI / tools-linux (clang) (push) Waiting to run
Tools CI / tools-linux (gcc) (push) Waiting to run
Tools CI / tools-linux (tcc) (push) Waiting to run
Tools CI / tools-macos (clang) (push) Waiting to run
Tools CI / tools-windows (gcc) (push) Waiting to run
Tools CI / tools-docker-ubuntu-musl (push) Waiting to run
vab CI / vab-compiles-v-examples (push) Waiting to run
vab CI / v-compiles-os-android (push) Waiting to run
Some checks are pending
Graphics CI / gg-regressions (push) Waiting to run
vlib modules CI / build-module-docs (push) Waiting to run
Shy and PV CI / v-compiles-puzzle-vibes (push) Waiting to run
Sanitized CI / sanitize-undefined-clang (push) Waiting to run
Sanitized CI / sanitize-undefined-gcc (push) Waiting to run
Sanitized CI / tests-sanitize-address-clang (push) Waiting to run
Sanitized CI / sanitize-address-msvc (push) Waiting to run
Sanitized CI / sanitize-address-gcc (push) Waiting to run
Sanitized CI / sanitize-memory-clang (push) Waiting to run
sdl CI / v-compiles-sdl-examples (push) Waiting to run
Time CI / time-windows (push) Waiting to run
Time CI / time-linux (push) Waiting to run
Time CI / time-macos (push) Waiting to run
toml CI / toml-module-pass-external-test-suites (push) Waiting to run
Tools CI / tools-windows (msvc) (push) Waiting to run
Tools CI / tools-windows (tcc) (push) Waiting to run
Tools CI / tools-linux (clang) (push) Waiting to run
Tools CI / tools-linux (gcc) (push) Waiting to run
Tools CI / tools-linux (tcc) (push) Waiting to run
Tools CI / tools-macos (clang) (push) Waiting to run
Tools CI / tools-windows (gcc) (push) Waiting to run
Tools CI / tools-docker-ubuntu-musl (push) Waiting to run
vab CI / vab-compiles-v-examples (push) Waiting to run
vab CI / v-compiles-os-android (push) Waiting to run
This commit is contained in:
parent
752eb5cf8c
commit
d8d125b056
1 changed files with 66 additions and 21 deletions
|
@ -1,8 +1,19 @@
|
||||||
module big
|
module big
|
||||||
|
|
||||||
|
import math
|
||||||
import math.bits
|
import math.bits
|
||||||
|
import strings
|
||||||
|
|
||||||
const digit_array = '0123456789abcdefghijklmnopqrstuvwxyz'.bytes()
|
const digit_array = '0123456789abcdefghijklmnopqrstuvwxyz'.bytes()
|
||||||
|
// vfmt off
|
||||||
|
const radix_options = {
|
||||||
|
2: 59, 3: 37, 4: 29, 5: 25, 6: 23, 7: 21, 8: 19, 9: 18, 10: 18,
|
||||||
|
11: 17, 12: 16, 13: 16, 14: 15, 15: 15, 16: 14, 17: 14, 18: 14,
|
||||||
|
19: 14, 20: 13, 21: 13, 22: 13, 23: 13, 24: 13, 25: 12, 26: 12,
|
||||||
|
27: 12, 28: 12, 29: 12, 30: 12, 31: 12, 32: 11, 33: 11, 34: 11,
|
||||||
|
35: 11, 36: 11
|
||||||
|
}
|
||||||
|
// vfmt on
|
||||||
pub const digit_bits = 60 // 60bits
|
pub const digit_bits = 60 // 60bits
|
||||||
const max_digit = (u64(1) << digit_bits) - u64(1)
|
const max_digit = (u64(1) << digit_bits) - u64(1)
|
||||||
// big.Integer
|
// big.Integer
|
||||||
|
@ -240,13 +251,17 @@ fn integer_from_regular_string(characters string, radix u32) Integer {
|
||||||
|
|
||||||
mut result := zero_int
|
mut result := zero_int
|
||||||
radix_int := integer_from_u32(radix)
|
radix_int := integer_from_u32(radix)
|
||||||
|
pow := radix_options[int(radix)]
|
||||||
for index := start_index; index < characters.len; index++ {
|
radix_pow := radix_int.pow(u32(pow))
|
||||||
digit := characters[index]
|
for i := start_index; i < characters.len; i += pow {
|
||||||
value := digit_array.index(digit)
|
end := math.min(i + pow, characters.len)
|
||||||
|
num_str := characters[i..end]
|
||||||
result *= radix_int
|
if num_str.len == pow {
|
||||||
result += integer_from_int(value)
|
result *= radix_pow
|
||||||
|
} else {
|
||||||
|
result *= radix_int.pow(u32(num_str.len))
|
||||||
|
}
|
||||||
|
result += integer_from_u64(regular_string_to_radix(num_str, radix))
|
||||||
}
|
}
|
||||||
|
|
||||||
return Integer{
|
return Integer{
|
||||||
|
@ -255,6 +270,15 @@ fn integer_from_regular_string(characters string, radix u32) Integer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn regular_string_to_radix(characters string, radix u32) u64 {
|
||||||
|
mut result := u64(0)
|
||||||
|
|
||||||
|
for c in characters {
|
||||||
|
result = result * radix + u64(digit_array.index(c))
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
// abs returns the absolute value of the integer `a`.
|
// abs returns the absolute value of the integer `a`.
|
||||||
pub fn (a Integer) abs() Integer {
|
pub fn (a Integer) abs() Integer {
|
||||||
return if a.signum == 0 {
|
return if a.signum == 0 {
|
||||||
|
@ -822,37 +846,58 @@ pub fn (integer Integer) radix_str(radix u32) string {
|
||||||
if integer.signum == 0 || radix == 0 {
|
if integer.signum == 0 || radix == 0 {
|
||||||
return '0'
|
return '0'
|
||||||
}
|
}
|
||||||
return integer.general_radix_str(radix)
|
return integer.general_radix_str(int(radix))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (integer Integer) general_radix_str(radix u32) string {
|
fn (integer Integer) general_radix_str(radix int) string {
|
||||||
$if debug {
|
$if debug {
|
||||||
assert radix != 0
|
assert radix != 0
|
||||||
}
|
}
|
||||||
divisor := integer_from_u32(radix)
|
divisor := integer_from_int(radix).pow(u32(radix_options[radix]))
|
||||||
|
|
||||||
mut current := integer.abs()
|
mut current := integer.abs()
|
||||||
mut new_current := zero_int
|
|
||||||
mut digit := zero_int
|
mut digit := zero_int
|
||||||
mut rune_array := []rune{cap: current.digits.len * 4}
|
mut sb := strings.new_builder(integer.digits.len * radix_options[radix]) // XXX
|
||||||
|
mut st := []string{cap: integer.digits.len * radix_options[radix]}
|
||||||
for current.signum > 0 {
|
for current.signum > 0 {
|
||||||
new_current, digit = current.div_mod_internal(divisor)
|
current, digit = current.div_mod_internal(divisor)
|
||||||
rune_array << digit_array[digit.int()]
|
st << general_str(current, digit, radix)
|
||||||
unsafe { digit.free() }
|
|
||||||
unsafe { current.free() }
|
|
||||||
current = new_current
|
|
||||||
}
|
}
|
||||||
if integer.signum == -1 {
|
if integer.signum == -1 {
|
||||||
rune_array << `-`
|
sb.write_string('-')
|
||||||
}
|
}
|
||||||
|
for st.len > 0 {
|
||||||
|
sb.write_string(st.pop())
|
||||||
|
}
|
||||||
|
return sb.str()
|
||||||
|
}
|
||||||
|
|
||||||
rune_array.reverse_in_place()
|
fn general_str(quotient Integer, remainder Integer, radix int) string {
|
||||||
return rune_array.string()
|
if quotient.signum == 0 && remainder.signum == 0 {
|
||||||
|
return '0'
|
||||||
|
}
|
||||||
|
divisor := integer_from_int(radix)
|
||||||
|
|
||||||
|
mut current := remainder.abs()
|
||||||
|
mut digit := zero_int
|
||||||
|
mut sb := strings.new_builder(radix_options[radix])
|
||||||
|
mut st := []u8{cap: radix_options[radix]}
|
||||||
|
for current.signum > 0 {
|
||||||
|
current, digit = current.div_mod_internal(divisor)
|
||||||
|
st << digit_array[digit.int()]
|
||||||
|
}
|
||||||
|
if quotient.signum > 0 {
|
||||||
|
sb.write_string(strings.repeat(48, radix_options[radix] - st.len))
|
||||||
|
}
|
||||||
|
for st.len > 0 {
|
||||||
|
sb.write_u8(st.pop())
|
||||||
|
}
|
||||||
|
return sb.str()
|
||||||
}
|
}
|
||||||
|
|
||||||
// str returns the decimal string representation of the integer `a`.
|
// str returns the decimal string representation of the integer `a`.
|
||||||
pub fn (integer Integer) str() string {
|
pub fn (integer Integer) str() string {
|
||||||
return integer.radix_str(10)
|
return integer.radix_str(u32(10))
|
||||||
}
|
}
|
||||||
|
|
||||||
// int returns the integer value of the integer `a`.
|
// int returns the integer value of the integer `a`.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue