diff --git a/vlib/strconv/atof.c.v b/vlib/strconv/atof.c.v index bf72737080b5f3..6d6c5235acfb9e 100644 --- a/vlib/strconv/atof.c.v +++ b/vlib/strconv/atof.c.v @@ -289,7 +289,7 @@ fn converter(mut pn PrepNumber) u64 { s0 = q0 pn.exponent++ } - // C.printf("mantissa before normalization: %08x%08x%08x binexp: %d \n", s2,s1,s0,binexp) + // C.printf(c"mantissa before normalization: %08x%08x%08x binexp: %d \n", s2,s1,s0,binexp) // normalization, the 28 bit in s2 must the leftest one in the variable if s2 != 0 || s1 != 0 || s0 != 0 { for (s2 & mask28) == 0 { @@ -333,20 +333,20 @@ fn converter(mut pn PrepNumber) u64 { s0=0x0 */ - // C.printf("mantissa before rounding: %08x%08x%08x binexp: %d \n", s2,s1,s0,binexp) + // C.printf(c"mantissa before rounding: %08x%08x%08x binexp: %d \n", s2,s1,s0,binexp) // s1 => 0xFFFFFFxx only F are rapresented nbit := 7 check_round_bit := u32(1) << u32(nbit) check_round_mask := u32(0xFFFFFFFF) << u32(nbit) if (s1 & check_round_bit) != 0 { - // C.printf("need round!! cehck mask: %08x\n", s1 & ~check_round_mask ) + // C.printf(c"need round!! check mask: %08x\n", s1 & ~check_round_mask ) if (s1 & ~check_round_mask) != 0 { - // C.printf("Add 1!\n") + // C.printf(c"Add 1!\n") s2, s1, s0 = add96(s2, s1, s0, 0, check_round_bit, 0) } else { - // C.printf("All 0!\n") + // C.printf(c"All 0!\n") if (s1 & (check_round_bit << u32(1))) != 0 { - // C.printf("Add 1 form -1 bit control!\n") + // C.printf(c"Add 1 form -1 bit control!\n") s2, s1, s0 = add96(s2, s1, s0, 0, check_round_bit, 0) } } @@ -354,17 +354,18 @@ fn converter(mut pn PrepNumber) u64 { s0 = u32(0) // recheck normalization if s2 & (mask28 << u32(1)) != 0 { - // C.printf("Renormalize!!") + // C.printf(c"Renormalize!!\n") q2, q1, q0 = lsr96(s2, s1, s0) - binexp-- + binexp++ + // dump(binexp) s2 = q2 s1 = q1 s0 = q0 } } // tmp := ( u64(s2 & ~mask28) << 24) | ((u64(s1) + u64(128)) >> 8) - // C.printf("mantissa after rounding : %08x%08x%08x binexp: %d \n", s2,s1,s0,binexp) - // C.printf("Tmp result: %016x\n",tmp) + // C.printf(c"mantissa after rounding : %08x %08x %08x binexp: %d \n", s2,s1,s0,binexp) + // C.printf(c"Tmp result: %016x\n",tmp) // end rounding // offset the binary exponent IEEE 754 binexp += 1023 diff --git a/vlib/strconv/converter_test.v b/vlib/strconv/converter_test.v new file mode 100644 index 00000000000000..1a1651126bfecd --- /dev/null +++ b/vlib/strconv/converter_test.v @@ -0,0 +1,30 @@ +module main + +fn test_issue_16448() { + float_prec := 1.9999999999999999 + 0.0000000000000000005 + assert float_prec > 1.99 + assert float_prec < 2.01 +} + +// Testing all the numbers between -100E6..100E6 takes over a minute with clang on i3 +// while for just -1E5..1E5, it takes less than a second. +// const r = i64(100_000_001) +// const r = i64(17_000_001) +const r = i64(100_001) + +fn test_renormalisation_inside_converter() { + for i in -r .. r { + s := '${i}.9999999999999999999' + fs := s.f64() + ifs := i64(fs) + if i % 10000 == 0 { + eprintln('>>> s: ${s:30s} | fs: ${fs:20.6f} | ifs: ${ifs:20}') + } + if i < 0 && ifs != i - 1 { + panic('invalid negative f64 value, i: ${i} | s: ${s} | fs: ${fs} | ifs: ${ifs}') + } + if i > 0 && ifs != i + 1 { + panic('invalid positive f64 value, i: ${i} | s: ${s} | fs: ${fs} | ifs: ${ifs}') + } + } +}