From d60a55d30b4430120a39c3fa5a70f5e9eaa2ec47 Mon Sep 17 00:00:00 2001 From: penguindark <57967770+penguindark@users.noreply.github.com> Date: Tue, 11 May 2021 07:09:17 +0200 Subject: [PATCH] strconv: float functions cleaning and speed optimization (#10076) --- vlib/strconv/f32_str.v | 52 ++++++++++------------------ vlib/strconv/f64_str.v | 78 +++++++++++++++++------------------------- 2 files changed, 51 insertions(+), 79 deletions(-) diff --git a/vlib/strconv/f32_str.v b/vlib/strconv/f32_str.v index 4afbdfac77..290887d2fa 100644 --- a/vlib/strconv/f32_str.v +++ b/vlib/strconv/f32_str.v @@ -1,6 +1,5 @@ module strconv - -/* +/*============================================================================= f32 to string @@ -18,8 +17,7 @@ Pages 270–282 https://doi.org/10.1145/3192366.3192369 inspired by the Go version here: https://github.com/cespare/ryu/tree/ba56a33f39e3bbbfa409095d0f9ae168a595feea -*/ - +=============================================================================*/ // pow of ten table used by n_digit reduction const( @@ -39,11 +37,9 @@ const( ] ) -/* - - Conversion Functions - -*/ +//============================================================================= +// Conversion Functions +//============================================================================= const( mantbits32 = u32(23) expbits32 = u32(8) @@ -53,11 +49,13 @@ const( // max 46 char // -3.40282346638528859811704183484516925440e+38 +[direct_array_access] pub fn (d Dec32) get_string_32(neg bool, i_n_digit int, i_pad_digit int) string { n_digit := i_n_digit + 1 pad_digit := i_pad_digit + 1 mut out := d.m - mut out_len := decimal_len_32(out) + //mut out_len := decimal_len_32(out) + mut out_len := dec_digits(out) out_len_original := out_len mut fw_zeros := 0 @@ -119,15 +117,6 @@ pub fn (d Dec32) get_string_32(neg bool, i_n_digit int, i_pad_digit int) string fw_zeros-- } - /* - x=0 - for x>(mantbits32+expbits32)) != 0 - mant := u & ((u32(1)<> mantbits32) & ((u32(1)<> (mantbits32 + expbits32)) != 0 + mant := u & ((u32(1) << mantbits32) - u32(1)) + exp := (u >> mantbits32) & ((u32(1) << expbits32) - u32(1)) //println("${neg} ${mant} e ${exp-bias32}") @@ -360,9 +346,9 @@ pub fn f32_to_str_pad(f f32, n_digit int) string { u1.f = f u := unsafe {u1.u} - neg := (u>>(mantbits32+expbits32)) != 0 - mant := u & ((u32(1)<> mantbits32) & ((u32(1)<> (mantbits32 + expbits32)) != 0 + mant := u & ((u32(1) << mantbits32) - u32(1)) + exp := (u >> mantbits32) & ((u32(1) << expbits32) - u32(1)) //println("${neg} ${mant} e ${exp-bias32}") diff --git a/vlib/strconv/f64_str.v b/vlib/strconv/f64_str.v index 7a6b73e43a..8f9ae8e999 100644 --- a/vlib/strconv/f64_str.v +++ b/vlib/strconv/f64_str.v @@ -1,8 +1,7 @@ module strconv +/*============================================================================= -/* - -f32 to string +f64 to string Copyright (c) 2019-2021 Dario Deledda. All rights reserved. Use of this source code is governed by an MIT license @@ -18,7 +17,7 @@ Pages 270–282 https://doi.org/10.1145/3192366.3192369 inspired by the Go version here: https://github.com/cespare/ryu/tree/ba56a33f39e3bbbfa409095d0f9ae168a595feea -*/ +=============================================================================*/ // pow of ten table used by n_digit reduction const( @@ -46,11 +45,9 @@ const( ] ) -/* - -Conversion Functions - -*/ +//============================================================================= +// Conversion Functions +//============================================================================= const( mantbits64 = u32(52) expbits64 = u32(11) @@ -58,12 +55,14 @@ const( maxexp64 = 2047 ) +[direct_array_access] fn (d Dec64) get_string_64(neg bool, i_n_digit int, i_pad_digit int) string { - mut n_digit := i_n_digit + 1 + mut n_digit := i_n_digit + 1 pad_digit := i_pad_digit + 1 mut out := d.m mut d_exp := d.e - mut out_len := decimal_len_64(out) + // mut out_len := decimal_len_64(out) + mut out_len := dec_digits(out) out_len_original := out_len mut fw_zeros := 0 @@ -75,7 +74,7 @@ fn (d Dec64) get_string_64(neg bool, i_n_digit int, i_pad_digit int) string { mut i := 0 if neg { - buf[i]=`-` + buf[i] = `-` i++ } @@ -88,9 +87,9 @@ fn (d Dec64) get_string_64(neg bool, i_n_digit int, i_pad_digit int) string { if n_digit < out_len { //println("out:[$out]") out += ten_pow_table_64[out_len - n_digit - 1] * 5 // round to up - out /= ten_pow_table_64[out_len - n_digit ] + out /= 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 / ten_pow_table_64[out_len - n_digit] < out { d_exp++ n_digit++ } @@ -103,8 +102,8 @@ fn (d Dec64) get_string_64(neg bool, i_n_digit int, i_pad_digit int) string { y := i + out_len mut x := 0 - for x < (out_len-disp-1) { - buf[y - x] = `0` + byte(out%10) + for x < (out_len - disp - 1) { + buf[y - x] = `0` + byte(out % 10) out /= 10 i++ x++ @@ -114,7 +113,7 @@ fn (d Dec64) get_string_64(neg bool, i_n_digit int, i_pad_digit int) string { if i_n_digit == 0 { unsafe { buf[i]=0 - return tos(byteptr(&buf[0]), i) + return tos(byteptr(&buf[0]), i) } } @@ -125,7 +124,7 @@ fn (d Dec64) get_string_64(neg bool, i_n_digit int, i_pad_digit int) string { } if y-x >= 0 { - buf[y - x] = `0` + byte(out%10) + buf[y - x] = `0` + byte(out % 10) i++ } @@ -135,15 +134,6 @@ fn (d Dec64) get_string_64(neg bool, i_n_digit int, i_pad_digit int) string { fw_zeros-- } - /* - x=0 - for x= q // <=> e2 + (^mm & 1) >= q && pow5Factor64(mm) >= q // <=> true && pow5Factor64(mm) >= q, since e2 >= 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) { + 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) { vp-- } } @@ -302,7 +284,7 @@ fn f64_to_decimal(mant u64, exp u64) Dec64 { // General case, which happens rarely (~0.7%). for { vp_div_10 := vp / 10 - vm_div_10 := vm / 10 + vm_div_10 := vm / 10 if vp_div_10 <= vm_div_10 { break } @@ -376,15 +358,19 @@ fn f64_to_decimal(mant u64, exp u64) Dec64 { return Dec64{m: out, e: e10 + removed} } +//============================================================================= +// String Functions +//============================================================================= + // f64_to_str return a string in scientific notation with max n_digit after the dot pub fn f64_to_str(f f64, n_digit int) string { mut u1 := Uf64{} u1.f = f u := unsafe {u1.u} - neg := (u>>(mantbits64+expbits64)) != 0 - mant := u & ((u64(1)<> mantbits64) & ((u64(1)<> (mantbits64 + expbits64)) != 0 + mant := u & ((u64(1) << mantbits64) - u64(1)) + exp := (u >> mantbits64) & ((u64(1) << expbits64) - u64(1)) //println("s:${neg} mant:${mant} exp:${exp} float:${f} byte:${u1.u:016lx}") // Exit early for easy cases. @@ -407,9 +393,9 @@ pub fn f64_to_str_pad(f f64, n_digit int) string { u1.f = f u := unsafe {u1.u} - neg := (u>>(mantbits64+expbits64)) != 0 - mant := u & ((u64(1)<> mantbits64) & ((u64(1)<> (mantbits64 + expbits64)) != 0 + mant := u & ((u64(1) << mantbits64) - u64(1)) + exp := (u >> mantbits64) & ((u64(1) << expbits64) - u64(1)) //println("s:${neg} mant:${mant} exp:${exp} float:${f} byte:${u1.u:016lx}") // Exit early for easy cases.