strconv: vfmt everything

pull/10508/head
Delyan Angelov 2021-06-18 17:59:56 +03:00
parent 5dff8dc097
commit de384f1cc8
No known key found for this signature in database
GPG Key ID: 66886C0F12D595ED
17 changed files with 1544 additions and 1252 deletions

View File

@ -43,7 +43,6 @@ const (
'vlib/', 'vlib/',
] ]
vfmt_known_failing_exceptions = arrays.merge(verify_known_failing_exceptions, [ vfmt_known_failing_exceptions = arrays.merge(verify_known_failing_exceptions, [
'vlib/strconv/' /* prevent conflicts, till the new pure V string interpolation is merged */,
'vlib/term/ui/input.v' /* comment after a struct embed is removed */, 'vlib/term/ui/input.v' /* comment after a struct embed is removed */,
'vlib/regex/regex_test.v' /* contains meaningfull formatting of the test case data */, 'vlib/regex/regex_test.v' /* contains meaningfull formatting of the test case data */,
'vlib/readline/readline_test.v' /* vfmt eats `{ Readline }` from `import readline { Readline }` */, 'vlib/readline/readline_test.v' /* vfmt eats `{ Readline }` from `import readline { Readline }` */,

View File

@ -414,7 +414,6 @@ Public functions
// atof64 return a f64 from a string doing a parsing operation // atof64 return a f64 from a string doing a parsing operation
pub fn atof64(s string) f64 { pub fn atof64(s string) f64 {
mut pn := PrepNumber{} mut pn := PrepNumber{}
mut res_parsing := 0 mut res_parsing := 0
mut res := Float64u{} mut res := Float64u{}

View File

@ -1,4 +1,5 @@
import strconv import strconv
/********************************************************************** /**********************************************************************
* *
* String to float Test * String to float Test
@ -18,7 +19,7 @@ fn test_atof() {
-0.004, -0.004,
0.0, 0.0,
-0.0, -0.0,
31234567890123 31234567890123,
] ]
// strings // strings
@ -37,7 +38,6 @@ fn test_atof() {
// slow atof // slow atof
assert strconv.atof64(src_num_str[c]).strlong() == x.strlong() assert strconv.atof64(src_num_str[c]).strlong() == x.strlong()
// quick atof // quick atof
mut s1 := (strconv.atof_quick(src_num_str[c]).str()) mut s1 := (strconv.atof_quick(src_num_str[c]).str())
mut s2 := (x.str()) mut s2 := (x.str())
@ -71,5 +71,5 @@ fn test_atof() {
// double_minus_zero // double_minus_zero
f1 = -0.0 f1 = -0.0
assert *ptr == u64(0x8000000000000000) assert *ptr == u64(0x8000000000000000)
println("DONE!") println('DONE!')
} }

File diff suppressed because one or more lines are too long

View File

@ -69,15 +69,15 @@ pub fn common_parse_uint2(s string, _base int, _bit_size int) (u64, int) {
return u64(0), -1 return u64(0), -1
} }
if bit_size == 0 { if bit_size == 0 {
bit_size = int_size bit_size = strconv.int_size
} else if bit_size < 0 || bit_size > 64 { } else if bit_size < 0 || bit_size > 64 {
// return error('parse_uint: bitsize error $s - $bit_size') // return error('parse_uint: bitsize error $s - $bit_size')
return u64(0), -2 return u64(0), -2
} }
// Cutoff is the smallest number such that cutoff*base > maxUint64. // Cutoff is the smallest number such that cutoff*base > maxUint64.
// Use compile-time constants for common cases. // Use compile-time constants for common cases.
cutoff := max_u64 / u64(base) + u64(1) cutoff := strconv.max_u64 / u64(base) + u64(1)
max_val := if bit_size == 64 { max_u64 } else { (u64(1) << u64(bit_size)) - u64(1) } max_val := if bit_size == 64 { strconv.max_u64 } else { (u64(1) << u64(bit_size)) - u64(1) }
mut n := u64(0) mut n := u64(0)
for i in start_index .. s.len { for i in start_index .. s.len {
c := s[i] c := s[i]
@ -144,7 +144,7 @@ pub fn common_parse_int(_s string, base int, _bit_size int, error_on_non_digit b
return i64(0) return i64(0)
} }
if bit_size == 0 { if bit_size == 0 {
bit_size = int_size bit_size = strconv.int_size
} }
// TODO: check should u64(bit_size-1) be size of int (32)? // TODO: check should u64(bit_size-1) be size of int (32)?
cutoff := u64(1) << u64(bit_size - 1) cutoff := u64(1) << u64(bit_size - 1)
@ -156,11 +156,7 @@ pub fn common_parse_int(_s string, base int, _bit_size int, error_on_non_digit b
// return error('parse_int: range error $s0') // return error('parse_int: range error $s0')
return -i64(cutoff) return -i64(cutoff)
} }
return if neg { return if neg { -i64(un) } else { i64(un) }
-i64(un)
} else {
i64(un)
}
} }
// parse_int interprets a string s in the given base (0, 2 to 36) and // parse_int interprets a string s in the given base (0, 2 to 36) and
@ -184,9 +180,8 @@ pub fn atoi(s string) ?int {
if s == '' { if s == '' {
return error('strconv.atoi: parsing "$s": invalid syntax ') return error('strconv.atoi: parsing "$s": invalid syntax ')
} }
if (int_size == 32 && (0 < s.len && if (strconv.int_size == 32 && (0 < s.len && s.len < 10))
s.len < 10)) || || (strconv.int_size == 64 && (0 < s.len && s.len < 19)) {
(int_size == 64 && (0 < s.len && s.len < 19)) {
// Fast path for small integers that fit int type. // Fast path for small integers that fit int type.
mut start_idx := 0 mut start_idx := 0
if s[0] == `-` || s[0] == `+` { if s[0] == `-` || s[0] == `+` {
@ -205,11 +200,7 @@ pub fn atoi(s string) ?int {
} }
n = n * 10 + int(ch) n = n * 10 + int(ch)
} }
return if s[0] == `-` { return if s[0] == `-` { -n } else { n }
-n
} else {
n
}
} }
// Slow path for invalid, big, or underscored integers. // Slow path for invalid, big, or underscored integers.
int64 := parse_int(s, 10, 0) int64 := parse_int(s, 10, 0)
@ -233,8 +224,8 @@ fn underscore_ok(s string) bool {
} }
// Optional base prefix. // Optional base prefix.
mut hex := false mut hex := false
if s.len - i >= 2 && s[i] == `0` && if s.len - i >= 2 && s[i] == `0` && (byte_to_lower(s[i + 1]) == `b`
(byte_to_lower(s[i + 1]) == `b` || byte_to_lower(s[i + 1]) == `o` || byte_to_lower(s[i + 1]) == `x`) { || byte_to_lower(s[i + 1]) == `o` || byte_to_lower(s[i + 1]) == `x`) {
saw = `0` // base prefix counts as a digit for "underscore as digit separator" saw = `0` // base prefix counts as a digit for "underscore as digit separator"
hex = byte_to_lower(s[i + 1]) == `x` hex = byte_to_lower(s[i + 1]) == `x`
i += 2 i += 2
@ -242,8 +233,8 @@ fn underscore_ok(s string) bool {
// Number proper. // Number proper.
for ; i < s.len; i++ { for ; i < s.len; i++ {
// Digits are always okay. // Digits are always okay.
if (`0` <= s[i] && s[i] <= `9`) || if (`0` <= s[i] && s[i] <= `9`) || (hex && `a` <= byte_to_lower(s[i])
(hex && `a` <= byte_to_lower(s[i]) && byte_to_lower(s[i]) <= `f`) { && byte_to_lower(s[i]) <= `f`) {
saw = `0` saw = `0`
continue continue
} }

View File

@ -1,4 +1,5 @@
module strconv module strconv
/*============================================================================= /*=============================================================================
f32 to string f32 to string
@ -78,8 +79,8 @@ pub fn (d Dec32) get_string_32(neg bool, i_n_digit int, i_pad_digit int) string
if n_digit < out_len { if n_digit < out_len {
// println("orig: ${out_len_original}") // println("orig: ${out_len_original}")
out += ten_pow_table_32[out_len - n_digit - 1] * 5 // round to up out += strconv.ten_pow_table_32[out_len - n_digit - 1] * 5 // round to up
out /= ten_pow_table_32[out_len - n_digit] out /= strconv.ten_pow_table_32[out_len - n_digit]
out_len = n_digit out_len = n_digit
} }
@ -96,7 +97,7 @@ pub fn (d Dec32) get_string_32(neg bool, i_n_digit int, i_pad_digit int) string
if i_n_digit == 0 { if i_n_digit == 0 {
unsafe { unsafe {
buf[i] = 0 buf[i] = 0
return tos(byteptr(&buf[0]), i) return tos(&byte(&buf[0]), i)
} }
} }
@ -140,17 +141,17 @@ pub fn (d Dec32) get_string_32(neg bool, i_n_digit int, i_pad_digit int) string
buf[i] = 0 buf[i] = 0
return unsafe { return unsafe {
tos(byteptr(&buf[0]), i) tos(&byte(&buf[0]), i)
} }
} }
fn f32_to_decimal_exact_int(i_mant u32, exp u32) (Dec32, bool) { fn f32_to_decimal_exact_int(i_mant u32, exp u32) (Dec32, bool) {
mut d := Dec32{} mut d := Dec32{}
e := exp - bias32 e := exp - strconv.bias32
if e > mantbits32 { if e > strconv.mantbits32 {
return d, false return d, false
} }
shift := mantbits32 - e shift := strconv.mantbits32 - e
mant := i_mant | 0x0080_0000 // implicit 1 mant := i_mant | 0x0080_0000 // implicit 1
// mant := i_mant | (1 << mantbits32) // implicit 1 // mant := i_mant | (1 << mantbits32) // implicit 1
d.m = mant >> shift d.m = mant >> shift
@ -170,11 +171,11 @@ fn f32_to_decimal(mant u32, exp u32) Dec32 {
if exp == 0 { if exp == 0 {
// We subtract 2 so that the bounds computation has // We subtract 2 so that the bounds computation has
// 2 additional bits. // 2 additional bits.
e2 = 1 - bias32 - int(mantbits32) - 2 e2 = 1 - strconv.bias32 - int(strconv.mantbits32) - 2
m2 = mant m2 = mant
} else { } else {
e2 = int(exp) - bias32 - int(mantbits32) - 2 e2 = int(exp) - strconv.bias32 - int(strconv.mantbits32) - 2
m2 = (u32(1) << mantbits32) | mant m2 = (u32(1) << strconv.mantbits32) | mant
} }
even := (m2 & 1) == 0 even := (m2 & 1) == 0
accept_bounds := even accept_bounds := even
@ -306,7 +307,10 @@ fn f32_to_decimal(mant u32, exp u32) Dec32 {
out = vr + bool_to_u32(vr == vm || last_removed_digit >= 5) out = vr + bool_to_u32(vr == vm || last_removed_digit >= 5)
} }
return Dec32{m: out e: e10 + removed} return Dec32{
m: out
e: e10 + removed
}
} }
//============================================================================= //=============================================================================
@ -319,14 +323,14 @@ pub fn f32_to_str(f f32, n_digit int) string {
u1.f = f u1.f = f
u := unsafe { u1.u } u := unsafe { u1.u }
neg := (u >> (mantbits32 + expbits32)) != 0 neg := (u >> (strconv.mantbits32 + strconv.expbits32)) != 0
mant := u & ((u32(1) << mantbits32) - u32(1)) mant := u & ((u32(1) << strconv.mantbits32) - u32(1))
exp := (u >> mantbits32) & ((u32(1) << expbits32) - u32(1)) exp := (u >> strconv.mantbits32) & ((u32(1) << strconv.expbits32) - u32(1))
// println("${neg} ${mant} e ${exp-bias32}") // println("${neg} ${mant} e ${exp-bias32}")
// Exit early for easy cases. // Exit early for easy cases.
if (exp == maxexp32) || (exp == 0 && mant == 0) { if (exp == strconv.maxexp32) || (exp == 0 && mant == 0) {
return get_string_special(neg, exp == 0, mant == 0) return get_string_special(neg, exp == 0, mant == 0)
} }
@ -346,14 +350,14 @@ pub fn f32_to_str_pad(f f32, n_digit int) string {
u1.f = f u1.f = f
u := unsafe { u1.u } u := unsafe { u1.u }
neg := (u >> (mantbits32 + expbits32)) != 0 neg := (u >> (strconv.mantbits32 + strconv.expbits32)) != 0
mant := u & ((u32(1) << mantbits32) - u32(1)) mant := u & ((u32(1) << strconv.mantbits32) - u32(1))
exp := (u >> mantbits32) & ((u32(1) << expbits32) - u32(1)) exp := (u >> strconv.mantbits32) & ((u32(1) << strconv.expbits32) - u32(1))
// println("${neg} ${mant} e ${exp-bias32}") // println("${neg} ${mant} e ${exp-bias32}")
// Exit early for easy cases. // Exit early for easy cases.
if (exp == maxexp32) || (exp == 0 && mant == 0) { if (exp == strconv.maxexp32) || (exp == 0 && mant == 0) {
return get_string_special(neg, exp == 0, mant == 0) return get_string_special(neg, exp == 0, mant == 0)
} }

View File

@ -1,4 +1,5 @@
module strconv module strconv
/*============================================================================= /*=============================================================================
f64 to string f64 to string
@ -86,10 +87,10 @@ fn (d Dec64) get_string_64(neg bool, i_n_digit int, i_pad_digit int) string {
// rounding last used digit // rounding last used digit
if n_digit < out_len { if n_digit < out_len {
// println("out:[$out]") // println("out:[$out]")
out += ten_pow_table_64[out_len - n_digit - 1] * 5 // round to up out += strconv.ten_pow_table_64[out_len - n_digit - 1] * 5 // round to up
out /= ten_pow_table_64[out_len - n_digit] out /= strconv.ten_pow_table_64[out_len - n_digit]
// println("out1:[$out] ${d.m / ten_pow_table_64[out_len - n_digit ]}") // println("out1:[$out] ${d.m / ten_pow_table_64[out_len - n_digit ]}")
if d.m / ten_pow_table_64[out_len - n_digit] < out { if d.m / strconv.ten_pow_table_64[out_len - n_digit] < out {
d_exp++ d_exp++
n_digit++ n_digit++
} }
@ -113,7 +114,7 @@ fn (d Dec64) get_string_64(neg bool, i_n_digit int, i_pad_digit int) string {
if i_n_digit == 0 { if i_n_digit == 0 {
unsafe { unsafe {
buf[i] = 0 buf[i] = 0
return tos(byteptr(&buf[0]), i) return tos(&byte(&buf[0]), i)
} }
} }
@ -163,17 +164,17 @@ fn (d Dec64) get_string_64(neg bool, i_n_digit int, i_pad_digit int) string {
buf[i] = 0 buf[i] = 0
return unsafe { return unsafe {
tos(byteptr(&buf[0]), i) tos(&byte(&buf[0]), i)
} }
} }
fn f64_to_decimal_exact_int(i_mant u64, exp u64) (Dec64, bool) { fn f64_to_decimal_exact_int(i_mant u64, exp u64) (Dec64, bool) {
mut d := Dec64{} mut d := Dec64{}
e := exp - bias64 e := exp - strconv.bias64
if e > mantbits64 { if e > strconv.mantbits64 {
return d, false return d, false
} }
shift := mantbits64 - e shift := strconv.mantbits64 - e
mant := i_mant | u64(0x0010_0000_0000_0000) // implicit 1 mant := i_mant | u64(0x0010_0000_0000_0000) // implicit 1
// mant := i_mant | (1 << mantbits64) // implicit 1 // mant := i_mant | (1 << mantbits64) // implicit 1
d.m = mant >> shift d.m = mant >> shift
@ -194,11 +195,11 @@ fn f64_to_decimal(mant u64, exp u64) Dec64 {
if exp == 0 { if exp == 0 {
// We subtract 2 so that the bounds computation has // We subtract 2 so that the bounds computation has
// 2 additional bits. // 2 additional bits.
e2 = 1 - bias64 - int(mantbits64) - 2 e2 = 1 - strconv.bias64 - int(strconv.mantbits64) - 2
m2 = mant m2 = mant
} else { } else {
e2 = int(exp) - bias64 - int(mantbits64) - 2 e2 = int(exp) - strconv.bias64 - int(strconv.mantbits64) - 2
m2 = (u64(1) << mantbits64) | mant m2 = (u64(1) << strconv.mantbits64) | mant
} }
even := (m2 & 1) == 0 even := (m2 & 1) == 0
accept_bounds := even accept_bounds := even
@ -237,7 +238,8 @@ fn f64_to_decimal(mant u64, exp u64) Dec64 {
// Same as min(e2 + (^mm & 1), pow5Factor64(mm)) >= q // Same as min(e2 + (^mm & 1), pow5Factor64(mm)) >= q
// <=> e2 + (^mm & 1) >= q && pow5Factor64(mm) >= q // <=> e2 + (^mm & 1) >= q && pow5Factor64(mm) >= q
// <=> true && pow5Factor64(mm) >= q, since e2 >= q. // <=> true && pow5Factor64(mm) >= q, since e2 >= q.
vm_is_trailing_zeros = multiple_of_power_of_five_64(mv - 1 - mm_shift, q) vm_is_trailing_zeros = multiple_of_power_of_five_64(mv - 1 - mm_shift,
q)
} else if multiple_of_power_of_five_64(mv + 2, q) { } else if multiple_of_power_of_five_64(mv + 2, q) {
vp-- vp--
} }
@ -355,7 +357,10 @@ fn f64_to_decimal(mant u64, exp u64) Dec64 {
out = vr + bool_to_u64(vr == vm || round_up) out = vr + bool_to_u64(vr == vm || round_up)
} }
return Dec64{m: out, e: e10 + removed} return Dec64{
m: out
e: e10 + removed
}
} }
//============================================================================= //=============================================================================
@ -368,13 +373,13 @@ pub fn f64_to_str(f f64, n_digit int) string {
u1.f = f u1.f = f
u := unsafe { u1.u } u := unsafe { u1.u }
neg := (u >> (mantbits64 + expbits64)) != 0 neg := (u >> (strconv.mantbits64 + strconv.expbits64)) != 0
mant := u & ((u64(1) << mantbits64) - u64(1)) mant := u & ((u64(1) << strconv.mantbits64) - u64(1))
exp := (u >> mantbits64) & ((u64(1) << expbits64) - u64(1)) exp := (u >> strconv.mantbits64) & ((u64(1) << strconv.expbits64) - u64(1))
// println("s:${neg} mant:${mant} exp:${exp} float:${f} byte:${u1.u:016lx}") // println("s:${neg} mant:${mant} exp:${exp} float:${f} byte:${u1.u:016lx}")
// Exit early for easy cases. // Exit early for easy cases.
if (exp == maxexp64) || (exp == 0 && mant == 0) { if (exp == strconv.maxexp64) || (exp == 0 && mant == 0) {
return get_string_special(neg, exp == 0, mant == 0) return get_string_special(neg, exp == 0, mant == 0)
} }
@ -393,13 +398,13 @@ pub fn f64_to_str_pad(f f64, n_digit int) string {
u1.f = f u1.f = f
u := unsafe { u1.u } u := unsafe { u1.u }
neg := (u >> (mantbits64 + expbits64)) != 0 neg := (u >> (strconv.mantbits64 + strconv.expbits64)) != 0
mant := u & ((u64(1) << mantbits64) - u64(1)) mant := u & ((u64(1) << strconv.mantbits64) - u64(1))
exp := (u >> mantbits64) & ((u64(1) << expbits64) - u64(1)) exp := (u >> strconv.mantbits64) & ((u64(1) << strconv.expbits64) - u64(1))
// println("s:${neg} mant:${mant} exp:${exp} float:${f} byte:${u1.u:016lx}") // println("s:${neg} mant:${mant} exp:${exp} float:${f} byte:${u1.u:016lx}")
// Exit early for easy cases. // Exit early for easy cases.
if (exp == maxexp64) || (exp == 0 && mant == 0) { if (exp == strconv.maxexp64) || (exp == 0 && mant == 0) {
return get_string_special(neg, exp == 0, mant == 0) return get_string_special(neg, exp == 0, mant == 0)
} }

View File

@ -1,7 +1,6 @@
module strconv module strconv
/* /*
printf/sprintf V implementation printf/sprintf V implementation
Copyright (c) 2020 Dario Deledda. All rights reserved. Copyright (c) 2020 Dario Deledda. All rights reserved.
@ -9,9 +8,7 @@ Use of this source code is governed by an MIT license
that can be found in the LICENSE file. that can be found in the LICENSE file.
This file contains the printf/sprintf functions This file contains the printf/sprintf functions
*/ */
import strings import strings
pub enum Align_text { pub enum Align_text {
@ -21,9 +18,7 @@ pub enum Align_text {
} }
/* /*
Float conversion utility Float conversion utility
*/ */
const ( const (
// rounding value // rounding value
@ -81,9 +76,7 @@ const(
// max float 1.797693134862315708145274237317043567981e+308 // max float 1.797693134862315708145274237317043567981e+308
/* /*
Single format functions Single format functions
*/ */
pub struct BF_param { pub struct BF_param {
pub mut: pub mut:

View File

@ -6,6 +6,7 @@ that can be found in the LICENSE file.
This file contains string interpolation V functions This file contains string interpolation V functions
=============================================================================*/ =============================================================================*/
module strconv module strconv
import strings import strings
// strings.Builder version of format_str // strings.Builder version of format_str
@ -103,10 +104,14 @@ pub fn format_dec_sb(d u64, p BF_param, mut res strings.Builder) {
// calculate the digit_pairs start index // calculate the digit_pairs start index
d_i = (n - (n1 * 100)) << 1 d_i = (n - (n1 * 100)) << 1
n = n1 n = n1
unsafe{ buf[i] = digit_pairs.str[d_i] } unsafe {
buf[i] = strconv.digit_pairs.str[d_i]
}
i-- i--
d_i++ d_i++
unsafe{ buf[i] = digit_pairs.str[d_i] } unsafe {
buf[i] = strconv.digit_pairs.str[d_i]
}
i-- i--
} }
i++ i++
@ -115,7 +120,6 @@ pub fn format_dec_sb(d u64, p BF_param, mut res strings.Builder) {
i++ i++
} }
unsafe { res.write_ptr(&buf[i], n_char) } unsafe { res.write_ptr(&buf[i], n_char) }
} else { } else {
// we have a zero no need of more code! // we have a zero no need of more code!
res.write_b(`0`) res.write_b(`0`)
@ -130,10 +134,7 @@ pub fn format_dec_sb(d u64, p BF_param, mut res strings.Builder) {
return return
} }
[direct_array_access; manualfree]
[manualfree]
[direct_array_access]
pub fn f64_to_str_lnd1(f f64, dec_digit int) string { pub fn f64_to_str_lnd1(f f64, dec_digit int) string {
unsafe { unsafe {
// we add the rounding value // we add the rounding value
@ -162,8 +163,7 @@ pub fn f64_to_str_lnd1(f f64, dec_digit int) string {
} else if c == `+` { } else if c == `+` {
sgn = 1 sgn = 1
i++ i++
} } else if c >= `0` && c <= `9` {
else if c >= `0` && c <= `9` {
b[i1] = c b[i1] = c
i1++ i1++
i++ i++
@ -179,7 +179,7 @@ pub fn f64_to_str_lnd1(f f64, dec_digit int) string {
break break
} else { } else {
s.free() s.free()
return "[Float conversion error!!]" return '[Float conversion error!!]'
} }
} }
b[i1] = 0 b[i1] = 0
@ -293,7 +293,6 @@ pub fn f64_to_str_lnd1(f f64, dec_digit int) string {
res.free() res.free()
return tmp_res return tmp_res
} }
} }
} }
@ -301,7 +300,7 @@ pub fn f64_to_str_lnd1(f f64, dec_digit int) string {
[manualfree] [manualfree]
pub fn format_fl(f f64, p BF_param) string { pub fn format_fl(f f64, p BF_param) string {
unsafe { unsafe {
mut s := "" mut s := ''
// mut fs := "1.2343" // mut fs := "1.2343"
mut fs := f64_to_str_lnd1(if f >= 0.0 { f } else { -f }, p.len1) mut fs := f64_to_str_lnd1(if f >= 0.0 { f } else { -f }, p.len1)
// println("Dario") // println("Dario")
@ -338,7 +337,7 @@ pub fn format_fl(f f64, p BF_param) string {
if p.positive { if p.positive {
if p.sign_flag { if p.sign_flag {
tmp := s tmp := s
s = "+" + fs s = '+' + fs
tmp.free() tmp.free()
} else { } else {
tmp := s tmp := s
@ -347,7 +346,7 @@ pub fn format_fl(f f64, p BF_param) string {
} }
} else { } else {
tmp := s tmp := s
s = "-" + fs s = '-' + fs
tmp.free() tmp.free()
} }
} }
@ -366,7 +365,6 @@ pub fn format_fl(f f64, p BF_param) string {
} }
} }
s.free() s.free()
fs.free() fs.free()
tmp_res := res.str() tmp_res := res.str()
@ -378,7 +376,7 @@ pub fn format_fl(f f64, p BF_param) string {
[manualfree] [manualfree]
pub fn format_es(f f64, p BF_param) string { pub fn format_es(f f64, p BF_param) string {
unsafe { unsafe {
mut s := "" mut s := ''
mut fs := f64_to_str_pad(if f > 0 { f } else { -f }, p.len1) mut fs := f64_to_str_pad(if f > 0 { f } else { -f }, p.len1)
if p.rm_tail_zero { if p.rm_tail_zero {
fs = remove_tail_zeros(fs) fs = remove_tail_zeros(fs)
@ -403,7 +401,7 @@ pub fn format_es(f f64, p BF_param) string {
if p.positive { if p.positive {
if p.sign_flag { if p.sign_flag {
tmp := s tmp := s
s = "+" + fs s = '+' + fs
tmp.free() tmp.free()
} else { } else {
tmp := s tmp := s
@ -412,7 +410,7 @@ pub fn format_es(f f64, p BF_param) string {
} }
} else { } else {
tmp := s tmp := s
s = "-" + fs s = '-' + fs
tmp.free() tmp.free()
} }
} }

View File

@ -1,21 +1,21 @@
import strconv import strconv
fn test_format() { fn test_format() {
mut temp_s := "" mut temp_s := ''
mut tmp_str:= "" mut tmp_str := ''
a0 := u32(10) a0 := u32(10)
b0 := 200 b0 := 200
c0 := byte(12) c0 := byte(12)
s0 := "ciAo" s0 := 'ciAo'
ch0 := `B` ch0 := `B`
f0 := 0.312345 f0 := 0.312345
f1 := 200000.0 f1 := 200000.0
f2 := -1234.300e6 f2 := -1234.300e6
f3 := 1234.300e-6 f3 := 1234.300e-6
sc0 := "ciao: [%-08u] %d %hhd [%8s] [%08X] [%-20.4f] [%-20.4f] [%c]" sc0 := 'ciao: [%-08u] %d %hhd [%8s] [%08X] [%-20.4f] [%-20.4f] [%c]'
temp_s = strconv.v_sprintf(sc0, a0, b0, c0, s0, b0, f0, f1, ch0) temp_s = strconv.v_sprintf(sc0, a0, b0, c0, s0, b0, f0, f1, ch0)
tmp_str = "ciao: [10 ] 200 12 [ ciAo] [000000C8] [0.3123 ] [200000.0000 ] [B]" tmp_str = 'ciao: [10 ] 200 12 [ ciAo] [000000C8] [0.3123 ] [200000.0000 ] [B]'
// C.printf(sc0.str,a0 ,b0 ,c0 ,s0.str ,b0 ,f0, f1, ch0) // C.printf(sc0.str,a0 ,b0 ,c0 ,s0.str ,b0 ,f0, f1, ch0)
// println("\n$temp_s") // println("\n$temp_s")
assert tmp_str == temp_s assert tmp_str == temp_s
@ -24,9 +24,9 @@ fn test_format(){
b := i16(13) b := i16(13)
c := 14 c := 14
d := i64(15) d := i64(15)
sc1 := "==>%hhd %hd %d %ld" sc1 := '==>%hhd %hd %d %ld'
temp_s = strconv.v_sprintf(sc1, a, b, c, d) temp_s = strconv.v_sprintf(sc1, a, b, c, d)
tmp_str = "==>12 13 14 15" tmp_str = '==>12 13 14 15'
// C.printf(sc1.str, a ,b ,c, d) // C.printf(sc1.str, a ,b ,c, d)
// println("\n$temp_s") // println("\n$temp_s")
assert tmp_str == temp_s assert tmp_str == temp_s
@ -35,69 +35,69 @@ fn test_format(){
b1 := i16(0xffff) b1 := i16(0xffff)
c1 := u32(0xffff_ffff) c1 := u32(0xffff_ffff)
d1 := u64(-1) d1 := u64(-1)
sc2 := "%hhu %hu %u %lu" sc2 := '%hhu %hu %u %lu'
temp_s = strconv.v_sprintf(sc2, a1, b1, c1, d1) temp_s = strconv.v_sprintf(sc2, a1, b1, c1, d1)
tmp_str = "255 65535 4294967295 18446744073709551615" tmp_str = '255 65535 4294967295 18446744073709551615'
// C.printf(sc2.str, a1 ,b1 ,c1, d1) // C.printf(sc2.str, a1 ,b1 ,c1, d1)
// println("\n$temp_s") // println("\n$temp_s")
assert tmp_str == temp_s assert tmp_str == temp_s
sc3 := "%hhx %hx %x %lx" sc3 := '%hhx %hx %x %lx'
temp_s = strconv.v_sprintf(sc3, a1, b1, c1, d1) temp_s = strconv.v_sprintf(sc3, a1, b1, c1, d1)
tmp_str = "ff ffff ffffffff ffffffffffffffff" tmp_str = 'ff ffff ffffffff ffffffffffffffff'
// C.printf(sc3.str, a1 ,b1 ,c1, d1) // C.printf(sc3.str, a1 ,b1 ,c1, d1)
// println("\n$temp_s") // println("\n$temp_s")
assert tmp_str == temp_s assert tmp_str == temp_s
sc4 := "[%-20.3e] [%20.3e] [%-020.3e] [%-020.3E] [%-020.3e] [%-020.3e]" sc4 := '[%-20.3e] [%20.3e] [%-020.3e] [%-020.3E] [%-020.3e] [%-020.3e]'
temp_s = strconv.v_sprintf(sc4, f0, f1, f1, f1, f2, f3) temp_s = strconv.v_sprintf(sc4, f0, f1, f1, f1, f2, f3)
tmp_str = "[3.123e-01 ] [ 2.000e+05] [2.000e+05 ] [2.000E+05 ] [-1.234e+09 ] [1.234e-03 ]" tmp_str = '[3.123e-01 ] [ 2.000e+05] [2.000e+05 ] [2.000E+05 ] [-1.234e+09 ] [1.234e-03 ]'
// C.printf(sc4.str, f0, f1, f1, f1, f2, f3) // C.printf(sc4.str, f0, f1, f1, f1, f2, f3)
// println("\n$temp_s") // println("\n$temp_s")
assert tmp_str == temp_s assert tmp_str == temp_s
sc5 := "[%.3f] [%0.3f] [%0.3F] [%0.3f] [%0.3F]" sc5 := '[%.3f] [%0.3f] [%0.3F] [%0.3f] [%0.3F]'
temp_s = strconv.v_sprintf(sc5, f0, f1, f1, f2, f3) temp_s = strconv.v_sprintf(sc5, f0, f1, f1, f2, f3)
tmp_str = "[0.312] [200000.000] [200000.000] [-1234300000.000] [0.001]" tmp_str = '[0.312] [200000.000] [200000.000] [-1234300000.000] [0.001]'
// C.printf(sc5.str, f0, f1, f1, f2, f3, f3) // C.printf(sc5.str, f0, f1, f1, f2, f3, f3)
// println("\n$temp_s") // println("\n$temp_s")
assert tmp_str == temp_s assert tmp_str == temp_s
ml := 3 ml := 3
sc6 := "%.*s [%05hhX]" sc6 := '%.*s [%05hhX]'
temp_s = strconv.v_sprintf(sc6, ml, s0, a) temp_s = strconv.v_sprintf(sc6, ml, s0, a)
tmp_str = "ciA [0000C]" tmp_str = 'ciA [0000C]'
// C.printf(sc6.str, ml, s0.str, a) // C.printf(sc6.str, ml, s0.str, a)
// println("\n$temp_s") // println("\n$temp_s")
assert tmp_str == temp_s assert tmp_str == temp_s
a2 := 125 a2 := 125
sc7 := "[%9x] [%9X] [%-9x] [%-9X] [%09x] [%09X]" sc7 := '[%9x] [%9X] [%-9x] [%-9X] [%09x] [%09X]'
temp_s = strconv.v_sprintf(sc7, a2, a2, a2, a2, a2, a2) temp_s = strconv.v_sprintf(sc7, a2, a2, a2, a2, a2, a2)
tmp_str = "[ 7d] [ 7D] [7d ] [7D ] [00000007d] [00000007D]" tmp_str = '[ 7d] [ 7D] [7d ] [7D ] [00000007d] [00000007D]'
// C.printf(sc7.str, a2, a2, a2, a2, a2, a2) // C.printf(sc7.str, a2, a2, a2, a2, a2, a2)
// println("\n$temp_s") // println("\n$temp_s")
assert tmp_str == temp_s assert tmp_str == temp_s
g_test := [ g_test := [
"[ -1e-07][ -1E-07]|", '[ -1e-07][ -1E-07]|',
"[ -1e-06][ -1E-06]|", '[ -1e-06][ -1E-06]|',
"[ -1e-05][ -1E-05]|", '[ -1e-05][ -1E-05]|',
"[ -0.0001][ -0.0001]|", '[ -0.0001][ -0.0001]|',
"[ -0.001][ -0.001]|", '[ -0.001][ -0.001]|',
"[ -0.01][ -0.01]|", '[ -0.01][ -0.01]|',
"[ -0.1][ -0.1]|", '[ -0.1][ -0.1]|',
"[ -1][ -1]|", '[ -1][ -1]|',
"[ -10][ -10]|", '[ -10][ -10]|',
"[ -100][ -100]|", '[ -100][ -100]|',
"[ -1000][ -1000]|", '[ -1000][ -1000]|',
"[ -10000][ -10000]|" '[ -10000][ -10000]|',
] ]
mut ft := -1e-7 mut ft := -1e-7
mut x := 0 mut x := 0
mut cnt := 0 mut cnt := 0
sc8 := "[%20g][%20G]|" sc8 := '[%20g][%20G]|'
for x < 12 { for x < 12 {
temp_s = strconv.v_sprintf(sc8, ft, ft) temp_s = strconv.v_sprintf(sc8, ft, ft)
// C.printf(sc8.str, ft, ft) // C.printf(sc8.str, ft, ft)

View File

@ -1,7 +1,6 @@
module strconv module strconv
/* /*
f32/f64 ftoa functions f32/f64 ftoa functions
Copyright (c) 2019-2021 Dario Deledda. All rights reserved. Copyright (c) 2019-2021 Dario Deledda. All rights reserved.
@ -17,7 +16,6 @@ Pages 270282 https://doi.org/10.1145/3192366.3192369
inspired by the Go version here: inspired by the Go version here:
https://github.com/cespare/ryu/tree/ba56a33f39e3bbbfa409095d0f9ae168a595feea https://github.com/cespare/ryu/tree/ba56a33f39e3bbbfa409095d0f9ae168a595feea
*/ */
[inline] [inline]

View File

@ -22,7 +22,7 @@ pub fn format_int(n i64, radix int) string {
mut res := '' mut res := ''
for n_copy != 0 { for n_copy != 0 {
tmp_0 := res tmp_0 := res
tmp_1 := base_digits[n_copy % radix].ascii_str() tmp_1 := strconv.base_digits[n_copy % radix].ascii_str()
res = tmp_1 + res res = tmp_1 + res
tmp_0.free() tmp_0.free()
tmp_1.free() tmp_1.free()
@ -49,7 +49,7 @@ pub fn format_uint(n u64, radix int) string {
uradix := u64(radix) uradix := u64(radix)
for n_copy != 0 { for n_copy != 0 {
tmp_0 := res tmp_0 := res
tmp_1 := base_digits[n_copy % uradix].ascii_str() tmp_1 := strconv.base_digits[n_copy % uradix].ascii_str()
res = tmp_1 + res res = tmp_1 + res
tmp_0.free() tmp_0.free()
tmp_1.free() tmp_1.free()

View File

@ -32,8 +32,7 @@ fn test_format_uint() {
assert strconv.format_int(255, 8) == '377' assert strconv.format_int(255, 8) == '377'
assert strconv.format_int(255, 10) == '255' assert strconv.format_int(255, 10) == '255'
assert strconv.format_int(255, 16) == 'ff' assert strconv.format_int(255, 16) == 'ff'
assert strconv.format_uint(18446744073709551615, 2) == assert strconv.format_uint(18446744073709551615, 2) == '1111111111111111111111111111111111111111111111111111111111111111'
'1111111111111111111111111111111111111111111111111111111111111111'
assert strconv.format_uint(18446744073709551615, 16) == 'ffffffffffffffff' assert strconv.format_uint(18446744073709551615, 16) == 'ffffffffffffffff'
assert strconv.parse_int('baobab', 36, 64) == 683058467 assert strconv.parse_int('baobab', 36, 64) == 683058467
assert strconv.format_uint(683058467, 36) == 'baobab' assert strconv.format_uint(683058467, 36) == 'baobab'

View File

@ -29,29 +29,87 @@ powers_of_10 = [
] ]
pow5_split_32 = [ pow5_split_32 = [
u64(1152921504606846976), u64(1441151880758558720), u64(1801439850948198400), u64(2251799813685248000), u64(1152921504606846976),
u64(1407374883553280000), u64(1759218604441600000), u64(2199023255552000000), u64(1374389534720000000), u64(1441151880758558720),
u64(1717986918400000000), u64(2147483648000000000), u64(1342177280000000000), u64(1677721600000000000), u64(1801439850948198400),
u64(2097152000000000000), u64(1310720000000000000), u64(1638400000000000000), u64(2048000000000000000), u64(2251799813685248000),
u64(1280000000000000000), u64(1600000000000000000), u64(2000000000000000000), u64(1250000000000000000), u64(1407374883553280000),
u64(1562500000000000000), u64(1953125000000000000), u64(1220703125000000000), u64(1525878906250000000), u64(1759218604441600000),
u64(1907348632812500000), u64(1192092895507812500), u64(1490116119384765625), u64(1862645149230957031), u64(2199023255552000000),
u64(1164153218269348144), u64(1455191522836685180), u64(1818989403545856475), u64(2273736754432320594), u64(1374389534720000000),
u64(1421085471520200371), u64(1776356839400250464), u64(2220446049250313080), u64(1387778780781445675), u64(1717986918400000000),
u64(1734723475976807094), u64(2168404344971008868), u64(1355252715606880542), u64(1694065894508600678), u64(2147483648000000000),
u64(2117582368135750847), u64(1323488980084844279), u64(1654361225106055349), u64(2067951531382569187), u64(1342177280000000000),
u64(1292469707114105741), u64(1615587133892632177), u64(2019483917365790221) u64(1677721600000000000),
u64(2097152000000000000),
u64(1310720000000000000),
u64(1638400000000000000),
u64(2048000000000000000),
u64(1280000000000000000),
u64(1600000000000000000),
u64(2000000000000000000),
u64(1250000000000000000),
u64(1562500000000000000),
u64(1953125000000000000),
u64(1220703125000000000),
u64(1525878906250000000),
u64(1907348632812500000),
u64(1192092895507812500),
u64(1490116119384765625),
u64(1862645149230957031),
u64(1164153218269348144),
u64(1455191522836685180),
u64(1818989403545856475),
u64(2273736754432320594),
u64(1421085471520200371),
u64(1776356839400250464),
u64(2220446049250313080),
u64(1387778780781445675),
u64(1734723475976807094),
u64(2168404344971008868),
u64(1355252715606880542),
u64(1694065894508600678),
u64(2117582368135750847),
u64(1323488980084844279),
u64(1654361225106055349),
u64(2067951531382569187),
u64(1292469707114105741),
u64(1615587133892632177),
u64(2019483917365790221),
] ]
pow5_inv_split_32 = [ pow5_inv_split_32 = [
u64(576460752303423489), u64(461168601842738791), u64(368934881474191033), u64(295147905179352826), u64(576460752303423489),
u64(472236648286964522), u64(377789318629571618), u64(302231454903657294), u64(483570327845851670), u64(461168601842738791),
u64(386856262276681336), u64(309485009821345069), u64(495176015714152110), u64(396140812571321688), u64(368934881474191033),
u64(316912650057057351), u64(507060240091291761), u64(405648192073033409), u64(324518553658426727), u64(295147905179352826),
u64(519229685853482763), u64(415383748682786211), u64(332306998946228969), u64(531691198313966350), u64(472236648286964522),
u64(425352958651173080), u64(340282366920938464), u64(544451787073501542), u64(435561429658801234), u64(377789318629571618),
u64(348449143727040987), u64(557518629963265579), u64(446014903970612463), u64(356811923176489971), u64(302231454903657294),
u64(570899077082383953), u64(456719261665907162), u64(365375409332725730) u64(483570327845851670),
u64(386856262276681336),
u64(309485009821345069),
u64(495176015714152110),
u64(396140812571321688),
u64(316912650057057351),
u64(507060240091291761),
u64(405648192073033409),
u64(324518553658426727),
u64(519229685853482763),
u64(415383748682786211),
u64(332306998946228969),
u64(531691198313966350),
u64(425352958651173080),
u64(340282366920938464),
u64(544451787073501542),
u64(435561429658801234),
u64(348449143727040987),
u64(557518629963265579),
u64(446014903970612463),
u64(356811923176489971),
u64(570899077082383953),
u64(456719261665907162),
u64(365375409332725730),
] ]
pow5_split_64 = [ pow5_split_64 = [
@ -380,7 +438,7 @@ pow5_split_64 =[
Uint128{u64(0xd070b763396297bf), u64(0x0194bd136316c046)}, Uint128{u64(0xd070b763396297bf), u64(0x0194bd136316c046)},
Uint128{u64(0x848ce53c07bb3daf), u64(0x01f9ec583bdc7058)}, Uint128{u64(0x848ce53c07bb3daf), u64(0x01f9ec583bdc7058)},
Uint128{u64(0x52d80f4584d5068d), u64(0x013c33b72569c637)}, Uint128{u64(0x52d80f4584d5068d), u64(0x013c33b72569c637)},
Uint128{u64(0x278e1316e60a4831), u64(0x018b40a4eec437c5)} Uint128{u64(0x278e1316e60a4831), u64(0x018b40a4eec437c5)},
] ]
pow5_inv_split_64 = [ pow5_inv_split_64 = [
@ -675,6 +733,6 @@ pow5_inv_split_64 = [
Uint128{u64(0xdd3b8d9fe50c2bb1), u64(0x026fb3398a0dab15)}, Uint128{u64(0xdd3b8d9fe50c2bb1), u64(0x026fb3398a0dab15)},
Uint128{u64(0x952c15cca1ad12b5), u64(0x03e5eb8f434911bc)}, Uint128{u64(0x952c15cca1ad12b5), u64(0x03e5eb8f434911bc)},
Uint128{u64(0x775677d6e7bda891), u64(0x031e560c35d40e30)}, Uint128{u64(0x775677d6e7bda891), u64(0x031e560c35d40e30)},
Uint128{u64(0xc5dec645863153a7), u64(0x027eab3cf7dcd826)} Uint128{u64(0xc5dec645863153a7), u64(0x027eab3cf7dcd826)},
] ]
) )

View File

@ -1,7 +1,6 @@
module strconv module strconv
/* /*
f32/f64 to string utilities f32/f64 to string utilities
Copyright (c) 2019-2021 Dario Deledda. All rights reserved. Copyright (c) 2019-2021 Dario Deledda. All rights reserved.
@ -17,17 +16,13 @@ Pages 270282 https://doi.org/10.1145/3192366.3192369
inspired by the Go version here: inspired by the Go version here:
https://github.com/cespare/ryu/tree/ba56a33f39e3bbbfa409095d0f9ae168a595feea https://github.com/cespare/ryu/tree/ba56a33f39e3bbbfa409095d0f9ae168a595feea
*/ */
import math.bits import math.bits
// import math // import math
/* /*
General Utilities General Utilities
*/ */
fn assert1(t bool, msg string) { fn assert1(t bool, msg string) {
if !t { if !t {
@ -61,25 +56,23 @@ fn bool_to_u64(b bool) u64 {
fn get_string_special(neg bool, expZero bool, mantZero bool) string { fn get_string_special(neg bool, expZero bool, mantZero bool) string {
if !mantZero { if !mantZero {
return "nan" return 'nan'
} }
if !expZero { if !expZero {
if neg { if neg {
return "-inf" return '-inf'
} else { } else {
return "+inf" return '+inf'
} }
} }
if neg { if neg {
return "-0e+00" return '-0e+00'
} }
return "0e+00" return '0e+00'
} }
/* /*
32 bit functions 32 bit functions
*/ */
// decimal_len_32 return the number of decimal digits of the input // decimal_len_32 return the number of decimal digits of the input
[deprecated] [deprecated]
@ -87,16 +80,25 @@ pub fn decimal_len_32(u u32) int {
// Function precondition: u is not a 10-digit number. // Function precondition: u is not a 10-digit number.
// (9 digits are sufficient for round-tripping.) // (9 digits are sufficient for round-tripping.)
// This benchmarked faster than the log2 approach used for u64. // This benchmarked faster than the log2 approach used for u64.
assert1(u < 1000000000, "too big") assert1(u < 1000000000, 'too big')
if u >= 100000000 { return 9 } if u >= 100000000 {
else if u >= 10000000 { return 8 } return 9
else if u >= 1000000 { return 7 } } else if u >= 10000000 {
else if u >= 100000 { return 6 } return 8
else if u >= 10000 { return 5 } } else if u >= 1000000 {
else if u >= 1000 { return 4 } return 7
else if u >= 100 { return 3 } } else if u >= 100000 {
else if u >= 10 { return 2 } return 6
} else if u >= 10000 {
return 5
} else if u >= 1000 {
return 4
} else if u >= 100 {
return 3
} else if u >= 10 {
return 2
}
return 1 return 1
} }
@ -106,7 +108,7 @@ fn mul_shift_32(m u32, mul u64, ishift int) u32 {
hi, lo := bits.mul_64(u64(m), mul) hi, lo := bits.mul_64(u64(m), mul)
shifted_sum := (lo >> u64(ishift)) + (hi << u64(64 - ishift)) shifted_sum := (lo >> u64(ishift)) + (hi << u64(64 - ishift))
assert1(shifted_sum <= 2147483647, "shiftedSum <= math.max_u32") assert1(shifted_sum <= 2147483647, 'shiftedSum <= math.max_u32')
return u32(shifted_sum) return u32(shifted_sum)
} }
@ -120,7 +122,7 @@ fn mul_pow5_div_pow2(m u32, i u32, j int) u32 {
fn pow5_factor_32(i_v u32) u32 { fn pow5_factor_32(i_v u32) u32 {
mut v := i_v mut v := i_v
for n := u32(0); ; n++ { for n := u32(0); true; n++ {
q := v / 5 q := v / 5
r := v % 5 r := v % 5
if r != 0 { if r != 0 {
@ -145,8 +147,8 @@ fn multiple_of_power_of_two_32(v u32, p u32) bool {
fn log10_pow2(e int) u32 { fn log10_pow2(e int) u32 {
// The first value this approximation fails for is 2^1651 // The first value this approximation fails for is 2^1651
// which is just greater than 10^297. // which is just greater than 10^297.
assert1(e >= 0, "e >= 0") assert1(e >= 0, 'e >= 0')
assert1(e <= 1650, "e <= 1650") assert1(e <= 1650, 'e <= 1650')
return (u32(e) * 78913) >> 18 return (u32(e) * 78913) >> 18
} }
@ -154,8 +156,8 @@ fn log10_pow2(e int) u32 {
fn log10_pow5(e int) u32 { fn log10_pow5(e int) u32 {
// The first value this approximation fails for is 5^2621 // The first value this approximation fails for is 5^2621
// which is just greater than 10^1832. // which is just greater than 10^1832.
assert1(e >= 0, "e >= 0") assert1(e >= 0, 'e >= 0')
assert1(e <= 2620, "e <= 2620") assert1(e <= 2620, 'e <= 2620')
return (u32(e) * 732923) >> 20 return (u32(e) * 732923) >> 20
} }
@ -164,18 +166,17 @@ fn pow5_bits(e int) int {
// This approximation works up to the point that the multiplication // This approximation works up to the point that the multiplication
// overflows at e = 3529. If the multiplication were done in 64 bits, // overflows at e = 3529. If the multiplication were done in 64 bits,
// it would fail at 5^4004 which is just greater than 2^9297. // it would fail at 5^4004 which is just greater than 2^9297.
assert1(e >= 0, "e >= 0") assert1(e >= 0, 'e >= 0')
assert1(e <= 3528, "e <= 3528") assert1(e <= 3528, 'e <= 3528')
return int(((u32(e) * 1217359) >> 19) + 1) return int(((u32(e) * 1217359) >> 19) + 1)
} }
/* /*
64 bit functions 64 bit functions
*/ */
[deprecated]
// decimal_len_64 return the number of decimal digits of the input // decimal_len_64 return the number of decimal digits of the input
[deprecated]
pub fn decimal_len_64(u u64) int { pub fn decimal_len_64(u u64) int {
// http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10 // http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10
log2 := 64 - bits.leading_zeros_64(u) - 1 log2 := 64 - bits.leading_zeros_64(u) - 1
@ -190,14 +191,17 @@ fn shift_right_128(v Uint128, shift int) u64 {
// (It is in the range [2, 59].) // (It is in the range [2, 59].)
// Check this here in case a future change requires larger shift // Check this here in case a future change requires larger shift
// values. In this case this function needs to be adjusted. // values. In this case this function needs to be adjusted.
assert1(shift < 64, "shift < 64") assert1(shift < 64, 'shift < 64')
return (v.hi << u64(64 - shift)) | (v.lo >> u32(shift)) return (v.hi << u64(64 - shift)) | (v.lo >> u32(shift))
} }
fn mul_shift_64(m u64, mul Uint128, shift int) u64 { fn mul_shift_64(m u64, mul Uint128, shift int) u64 {
hihi, hilo := bits.mul_64(m, mul.hi) hihi, hilo := bits.mul_64(m, mul.hi)
lohi, _ := bits.mul_64(m, mul.lo) lohi, _ := bits.mul_64(m, mul.lo)
mut sum := Uint128{lo: lohi + hilo,hi: hihi} mut sum := Uint128{
lo: lohi + hilo
hi: hihi
}
if sum.lo < lohi { if sum.lo < lohi {
sum.hi++ // overflow sum.hi++ // overflow
} }
@ -206,7 +210,7 @@ fn mul_shift_64(m u64, mul Uint128, shift int) u64 {
fn pow5_factor_64(v_i u64) u32 { fn pow5_factor_64(v_i u64) u32 {
mut v := v_i mut v := v_i
for n := u32(0); ; n++ { for n := u32(0); true; n++ {
q := v / 5 q := v / 5
r := v % 5 r := v % 5
if r != 0 { if r != 0 {
@ -226,9 +230,7 @@ fn multiple_of_power_of_two_64(v u64, p u32) bool {
} }
/* /*
f64 to string with string format f64 to string with string format
*/ */
// TODO: Investigate precision issues // TODO: Investigate precision issues
@ -265,7 +267,6 @@ pub fn f64_to_str_l_no_dot(f f64) string {
return res return res
} }
// f64_to_str_l return a string with the f64 converted in a string in decimal notation // f64_to_str_l return a string with the f64 converted in a string in decimal notation
[manualfree] [manualfree]
pub fn fxx_to_str_l_parse(s string) string { pub fn fxx_to_str_l_parse(s string) string {
@ -291,8 +292,7 @@ pub fn fxx_to_str_l_parse(s string) string {
} else if c == `+` { } else if c == `+` {
sgn = 1 sgn = 1
i++ i++
} } else if c >= `0` && c <= `9` {
else if c >= `0` && c <= `9` {
b[i1] = c b[i1] = c
i1++ i1++
i++ i++
@ -307,7 +307,7 @@ pub fn fxx_to_str_l_parse(s string) string {
i++ i++
break break
} else { } else {
return "Float conversion error!!" return 'Float conversion error!!'
} }
} }
b[i1] = 0 b[i1] = 0
@ -415,8 +415,7 @@ pub fn fxx_to_str_l_parse_no_dot(s string) string {
} else if c == `+` { } else if c == `+` {
sgn = 1 sgn = 1
i++ i++
} } else if c >= `0` && c <= `9` {
else if c >= `0` && c <= `9` {
b[i1] = c b[i1] = c
i1++ i1++
i++ i++
@ -431,7 +430,7 @@ pub fn fxx_to_str_l_parse_no_dot(s string) string {
i++ i++
break break
} else { } else {
return "Float conversion error!!" return 'Float conversion error!!'
} }
} }
b[i1] = 0 b[i1] = 0

View File

@ -6,6 +6,7 @@ that can be found in the LICENSE file.
This file contains string interpolation V functions This file contains string interpolation V functions
=============================================================================*/ =============================================================================*/
module strconv module strconv
import strings import strings
enum Char_parse_state { enum Char_parse_state {
@ -15,11 +16,9 @@ enum Char_parse_state {
pad_ch pad_ch
len_set_start len_set_start
len_set_in len_set_in
check_type check_type
check_float check_float
check_float_in check_float_in
reset_params reset_params
} }
@ -83,7 +82,7 @@ pub fn v_sprintf(str string, pt ... voidptr) string{
// pointer, manage it here // pointer, manage it here
if ch == `p` && status == .field_char { if ch == `p` && status == .field_char {
v_sprintf_panic(p_index, pt.len) v_sprintf_panic(p_index, pt.len)
res.write_string("0x") res.write_string('0x')
res.write_string(ptr_str(unsafe { pt[p_index] })) res.write_string(ptr_str(unsafe { pt[p_index] }))
status = .reset_params status = .reset_params
p_index++ p_index++
@ -114,7 +113,7 @@ pub fn v_sprintf(str string, pt ... voidptr) string{
} }
i++ i++
continue continue
} else if ch == `'` { } else if ch == `\'` {
i++ i++
continue continue
} else if ch == `.` && fc_ch1 >= `1` && fc_ch1 <= `9` { } else if ch == `.` && fc_ch1 >= `1` && fc_ch1 <= `9` {
@ -195,7 +194,6 @@ pub fn v_sprintf(str string, pt ... voidptr) string{
} }
if status == .check_type { if status == .check_type {
if ch == `l` { if ch == `l` {
if ch1 == `0` { if ch1 == `0` {
ch1 = `l` ch1 = `l`
@ -206,8 +204,7 @@ pub fn v_sprintf(str string, pt ... voidptr) string{
i++ i++
continue continue
} }
} } else if ch == `h` {
else if ch == `h` {
if ch1 == `0` { if ch1 == `0` {
ch1 = `h` ch1 = `h`
i++ i++
@ -218,7 +215,6 @@ pub fn v_sprintf(str string, pt ... voidptr) string{
continue continue
} }
} }
// signed integer // signed integer
else if ch in [`d`, `i`] { else if ch in [`d`, `i`] {
mut d1 := u64(0) mut d1 := u64(0)
@ -269,9 +265,15 @@ pub fn v_sprintf(str string, pt ... voidptr) string{
positive = if x >= 0 { true } else { false } positive = if x >= 0 { true } else { false }
d1 = if positive { u64(x) } else { u64(-x) } d1 = if positive { u64(x) } else { u64(-x) }
} }
} }
res.write_string(format_dec_old(d1,{pad_ch: pad_ch, len0: len0, len1: 0, positive: positive, sign_flag: sign, allign: allign})) res.write_string(format_dec_old(d1,
pad_ch: pad_ch
len0: len0
len1: 0
positive: positive
sign_flag: sign
allign: allign
))
status = .reset_params status = .reset_params
p_index++ p_index++
i++ i++
@ -279,7 +281,6 @@ pub fn v_sprintf(str string, pt ... voidptr) string{
ch2 = `0` ch2 = `0`
continue continue
} }
// unsigned integer // unsigned integer
else if ch == `u` { else if ch == `u` {
mut d1 := u64(0) mut d1 := u64(0)
@ -314,17 +315,23 @@ pub fn v_sprintf(str string, pt ... voidptr) string{
} }
} }
res.write_string(format_dec_old(d1,{pad_ch: pad_ch, len0: len0, len1: 0, positive: positive, sign_flag: sign, allign: allign})) res.write_string(format_dec_old(d1,
pad_ch: pad_ch
len0: len0
len1: 0
positive: positive
sign_flag: sign
allign: allign
))
status = .reset_params status = .reset_params
p_index++ p_index++
i++ i++
continue continue
} }
// hex // hex
else if ch in [`x`, `X`] { else if ch in [`x`, `X`] {
v_sprintf_panic(p_index, pt.len) v_sprintf_panic(p_index, pt.len)
mut s := "" mut s := ''
match ch1 { match ch1 {
// h for 16 bit int // h for 16 bit int
// hh fot 8 bit int // hh fot 8 bit int
@ -363,7 +370,14 @@ pub fn v_sprintf(str string, pt ... voidptr) string{
s = s.to_upper() s = s.to_upper()
} }
res.write_string(format_str(s,{pad_ch: pad_ch, len0: len0, len1: 0, positive: true, sign_flag: false, allign: allign})) res.write_string(format_str(s,
pad_ch: pad_ch
len0: len0
len1: 0
positive: true
sign_flag: false
allign: allign
))
status = .reset_params status = .reset_params
p_index++ p_index++
i++ i++
@ -376,38 +390,66 @@ pub fn v_sprintf(str string, pt ... voidptr) string{
x := unsafe { *(&f64(pt[p_index])) } x := unsafe { *(&f64(pt[p_index])) }
positive := x >= f64(0.0) positive := x >= f64(0.0)
len1 = if len1 >= 0 { len1 } else { def_len1 } len1 = if len1 >= 0 { len1 } else { def_len1 }
s := format_fl_old(f64(x), {pad_ch: pad_ch, len0: len0, len1: len1, positive: positive, sign_flag: sign, allign: allign}) s := format_fl_old(f64(x),
pad_ch: pad_ch
len0: len0
len1: len1
positive: positive
sign_flag: sign
allign: allign
)
res.write_string(if ch == `F` { s.to_upper() } else { s }) res.write_string(if ch == `F` { s.to_upper() } else { s })
status = .reset_params status = .reset_params
p_index++ p_index++
i++ i++
continue continue
} } else if ch in [`e`, `E`] {
else if ch in [`e`, `E`] {
v_sprintf_panic(p_index, pt.len) v_sprintf_panic(p_index, pt.len)
x := unsafe { *(&f64(pt[p_index])) } x := unsafe { *(&f64(pt[p_index])) }
positive := x >= f64(0.0) positive := x >= f64(0.0)
len1 = if len1 >= 0 { len1 } else { def_len1 } len1 = if len1 >= 0 { len1 } else { def_len1 }
s := format_es_old(f64(x), {pad_ch: pad_ch, len0: len0, len1: len1, positive: positive, sign_flag: sign, allign: allign}) s := format_es_old(f64(x),
pad_ch: pad_ch
len0: len0
len1: len1
positive: positive
sign_flag: sign
allign: allign
)
res.write_string(if ch == `E` { s.to_upper() } else { s }) res.write_string(if ch == `E` { s.to_upper() } else { s })
status = .reset_params status = .reset_params
p_index++ p_index++
i++ i++
continue continue
} } else if ch in [`g`, `G`] {
else if ch in [`g`, `G`] {
v_sprintf_panic(p_index, pt.len) v_sprintf_panic(p_index, pt.len)
x := unsafe { *(&f64(pt[p_index])) } x := unsafe { *(&f64(pt[p_index])) }
positive := x >= f64(0.0) positive := x >= f64(0.0)
mut s := "" mut s := ''
tx := fabs(x) tx := fabs(x)
if tx < 999_999.0 && tx >= 0.00001 { if tx < 999_999.0 && tx >= 0.00001 {
// println("Here g format_fl [$tx]") // println("Here g format_fl [$tx]")
len1 = if len1 >= 0 { len1 + 1 } else { def_len1 } len1 = if len1 >= 0 { len1 + 1 } else { def_len1 }
s = format_fl_old(x, {pad_ch: pad_ch, len0: len0, len1: len1, positive: positive, sign_flag: sign, allign: allign, rm_tail_zero: true}) s = format_fl_old(x,
pad_ch: pad_ch
len0: len0
len1: len1
positive: positive
sign_flag: sign
allign: allign
rm_tail_zero: true
)
} else { } else {
len1 = if len1 >= 0 { len1 + 1 } else { def_len1 } len1 = if len1 >= 0 { len1 + 1 } else { def_len1 }
s = format_es_old(x, {pad_ch: pad_ch, len0: len0, len1: len1, positive: positive, sign_flag: sign, allign: allign, rm_tail_zero: true}) s = format_es_old(x,
pad_ch: pad_ch
len0: len0
len1: len1
positive: positive
sign_flag: sign
allign: allign
rm_tail_zero: true
)
} }
res.write_string(if ch == `G` { s.to_upper() } else { s }) res.write_string(if ch == `G` { s.to_upper() } else { s })
status = .reset_params status = .reset_params
@ -415,13 +457,19 @@ pub fn v_sprintf(str string, pt ... voidptr) string{
i++ i++
continue continue
} }
// string // string
else if ch == `s` { else if ch == `s` {
v_sprintf_panic(p_index, pt.len) v_sprintf_panic(p_index, pt.len)
s1 := unsafe { *(&string(pt[p_index])) } s1 := unsafe { *(&string(pt[p_index])) }
pad_ch = ` ` pad_ch = ` `
res.write_string(format_str(s1, {pad_ch: pad_ch, len0: len0, len1: 0, positive: true, sign_flag: false, allign: allign})) res.write_string(format_str(s1,
pad_ch: pad_ch
len0: len0
len1: 0
positive: true
sign_flag: false
allign: allign
))
status = .reset_params status = .reset_params
p_index++ p_index++
i++ i++
@ -435,7 +483,7 @@ pub fn v_sprintf(str string, pt ... voidptr) string{
} }
if p_index != pt.len { if p_index != pt.len {
panic('${p_index} % conversion specifiers, but given ${pt.len} args') panic('$p_index % conversion specifiers, but given $pt.len args')
} }
return res.str() return res.str()
@ -444,7 +492,7 @@ pub fn v_sprintf(str string, pt ... voidptr) string{
[inline] [inline]
fn v_sprintf_panic(idx int, len int) { fn v_sprintf_panic(idx int, len int) {
if idx >= len { if idx >= len {
panic('${idx+1} % conversion specifiers, but given only ${len} args') panic('${idx + 1} % conversion specifiers, but given only $len args')
} }
} }
@ -459,7 +507,7 @@ fn fabs(x f64) f64 {
[manualfree] [manualfree]
pub fn format_fl_old(f f64, p BF_param) string { pub fn format_fl_old(f f64, p BF_param) string {
unsafe { unsafe {
mut s := "" mut s := ''
// mut fs := "1.2343" // mut fs := "1.2343"
mut fs := f64_to_str_lnd1(if f >= 0.0 { f } else { -f }, p.len1) mut fs := f64_to_str_lnd1(if f >= 0.0 { f } else { -f }, p.len1)
// println("Dario") // println("Dario")
@ -496,7 +544,7 @@ pub fn format_fl_old(f f64, p BF_param) string {
if p.positive { if p.positive {
if p.sign_flag { if p.sign_flag {
tmp := s tmp := s
s = "+" + fs s = '+' + fs
tmp.free() tmp.free()
} else { } else {
tmp := s tmp := s
@ -505,7 +553,7 @@ pub fn format_fl_old(f f64, p BF_param) string {
} }
} else { } else {
tmp := s tmp := s
s = "-" + fs s = '-' + fs
tmp.free() tmp.free()
} }
} }
@ -524,7 +572,6 @@ pub fn format_fl_old(f f64, p BF_param) string {
} }
} }
s.free() s.free()
fs.free() fs.free()
tmp_res := res.str() tmp_res := res.str()
@ -536,7 +583,7 @@ pub fn format_fl_old(f f64, p BF_param) string {
[manualfree] [manualfree]
pub fn format_es_old(f f64, p BF_param) string { pub fn format_es_old(f f64, p BF_param) string {
unsafe { unsafe {
mut s := "" mut s := ''
mut fs := f64_to_str_pad(if f > 0 { f } else { -f }, p.len1) mut fs := f64_to_str_pad(if f > 0 { f } else { -f }, p.len1)
if p.rm_tail_zero { if p.rm_tail_zero {
fs = remove_tail_zeros_old(fs) fs = remove_tail_zeros_old(fs)
@ -561,7 +608,7 @@ pub fn format_es_old(f f64, p BF_param) string {
if p.positive { if p.positive {
if p.sign_flag { if p.sign_flag {
tmp := s tmp := s
s = "+" + fs s = '+' + fs
tmp.free() tmp.free()
} else { } else {
tmp := s tmp := s
@ -570,7 +617,7 @@ pub fn format_es_old(f f64, p BF_param) string {
} }
} else { } else {
tmp := s tmp := s
s = "-" + fs s = '-' + fs
tmp.free() tmp.free()
} }
} }
@ -606,8 +653,7 @@ pub fn remove_tail_zeros_old(s string) string {
if ch == `.` { if ch == `.` {
in_decimal = true in_decimal = true
dot_pos = i dot_pos = i
} } else if in_decimal {
else if in_decimal {
if ch == `0` && prev_ch != `0` { if ch == `0` && prev_ch != `0` {
last_zero_start = i last_zero_start = i
} else if ch >= `1` && ch <= `9` { } else if ch >= `1` && ch <= `9` {
@ -620,7 +666,7 @@ pub fn remove_tail_zeros_old(s string) string {
i++ i++
} }
mut tmp := "" mut tmp := ''
if last_zero_start > 0 { if last_zero_start > 0 {
if last_zero_start == dot_pos + 1 { if last_zero_start == dot_pos + 1 {
tmp = s[..dot_pos] + s[i..] tmp = s[..dot_pos] + s[i..]
@ -638,7 +684,7 @@ pub fn remove_tail_zeros_old(s string) string {
// max int64 9223372036854775807 // max int64 9223372036854775807
pub fn format_dec_old(d u64, p BF_param) string { pub fn format_dec_old(d u64, p BF_param) string {
mut s := "" mut s := ''
mut res := strings.new_builder(20) mut res := strings.new_builder(20)
mut sign_len_diff := 0 mut sign_len_diff := 0
if p.pad_ch == `0` { if p.pad_ch == `0` {
@ -655,12 +701,12 @@ pub fn format_dec_old(d u64, p BF_param) string {
} else { } else {
if p.positive { if p.positive {
if p.sign_flag { if p.sign_flag {
s = "+" + d.str() s = '+' + d.str()
} else { } else {
s = d.str() s = d.str()
} }
} else { } else {
s = "-" + d.str() s = '-' + d.str()
} }
} }
dif := p.len0 - s.len + sign_len_diff dif := p.len0 - s.len + sign_len_diff