From 4ec03a2d9b1c88a657829af7dc193fcb73d419bb Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 16 Apr 2025 13:45:50 +0100 Subject: [PATCH] Fix `strconv.parse_float` related procedures caused by a shifting problem --- core/strconv/decimal/decimal.odin | 3 +- core/strconv/generic_float.odin | 55 +++++++++++++------------------ 2 files changed, 24 insertions(+), 34 deletions(-) diff --git a/core/strconv/decimal/decimal.odin b/core/strconv/decimal/decimal.odin index 06503d01a..cb9285083 100644 --- a/core/strconv/decimal/decimal.odin +++ b/core/strconv/decimal/decimal.odin @@ -399,7 +399,7 @@ shift_left :: proc(a: ^Decimal, k: uint) #no_bounds_check { a.decimal_point += delta - a.count = clamp(a.count, 0, len(a.digits)) + a.count = clamp(a.count+delta, 0, len(a.digits)) trim(a) } /* @@ -562,4 +562,3 @@ rounded_integer :: proc(a: ^Decimal) -> u64 { } return n } - diff --git a/core/strconv/generic_float.odin b/core/strconv/generic_float.odin index b049f0fe1..b126dc3b6 100644 --- a/core/strconv/generic_float.odin +++ b/core/strconv/generic_float.odin @@ -339,45 +339,37 @@ Converts a decimal number to its floating-point representation with the given fo - b: The bits representing the floating-point number - overflow: A boolean indicating whether an overflow occurred during conversion */ -@(private) decimal_to_float_bits :: proc(d: ^decimal.Decimal, info: ^Float_Info) -> (b: u64, overflow: bool) { - end :: proc "contextless" (d: ^decimal.Decimal, mant: u64, exp: int, info: ^Float_Info) -> (bits: u64) { + overflow_end :: proc "contextless" (d: ^decimal.Decimal, info: ^Float_Info) -> (u64, bool) { + mant: u64 = 0 + exp: int = 1< (bits: u64, overflow: bool) { bits = mant & (u64(1)< bool { - mant^ = 0 - exp^ = 1< 310 { - set_overflow(&mant, &exp, info) - b = end(d, mant, exp, info) - return + return overflow_end(d, info) } else if d.decimal_point < -330 { - mant = 0 - exp = info.bias - b = end(d, mant, exp, info) - return + return end(d, 0, info.bias, info, false) } @(static, rodata) power_table := [?]int{1, 3, 6, 9, 13, 16, 19, 23, 26} - exp = 0 + + exp := 0 for d.decimal_point > 0 { n := 27 if d.decimal_point >= len(power_table) else power_table[d.decimal_point] decimal.shift(d, -n) @@ -392,35 +384,34 @@ decimal_to_float_bits :: proc(d: ^decimal.Decimal, info: ^Float_Info) -> (b: u64 // go from [0.5, 1) to [1, 2) exp -= 1 + // Min rep exp is 1+bias if exp < info.bias + 1 { n := info.bias + 1 - exp - decimal.shift(d, n) + decimal.shift(d, -n) exp += n } if (exp-info.bias) >= (1<>= 1 exp += 1 if (exp-info.bias) >= (1<