diff --git a/gnovm/pkg/gnolang/values_conversions.go b/gnovm/pkg/gnolang/values_conversions.go index 9fc2ce4a567..cc7c0de9f09 100644 --- a/gnovm/pkg/gnolang/values_conversions.go +++ b/gnovm/pkg/gnolang/values_conversions.go @@ -1240,12 +1240,14 @@ func ConvertUntypedBigdecTo(dst *TypedValue, bv BigdecValue, t Type) { case Float32Kind: dst.T = t dst.V = nil - f64, _ := bd.Float64() + f64, err := bd.Float64() + if err != nil { + panic(fmt.Errorf("cannot convert untyped bigdec to float64: %w", err)) + } + bf := big.NewFloat(f64) - f32, acc := bf.Float32() - if f32 == 0 && (acc == big.Below || acc == big.Above) { - panic("cannot convert untyped bigdec to float32 -- too close to zero") - } else if math.IsInf(float64(f32), 0) { + f32, _ := bf.Float32() + if math.IsInf(float64(f32), 0) { panic("cannot convert untyped bigdec to float32 -- too close to +-Inf") } dst.SetFloat32(f32) @@ -1253,10 +1255,11 @@ func ConvertUntypedBigdecTo(dst *TypedValue, bv BigdecValue, t Type) { case Float64Kind: dst.T = t dst.V = nil - f64, _ := bd.Float64() - if f64 == 0 && !bd.IsZero() { - panic("cannot convert untyped bigdec to float64 -- too close to zero") - } else if math.IsInf(f64, 0) { + f64, err := bd.Float64() + if err != nil { + panic(fmt.Errorf("cannot convert untyped bigdec to float64: %w", err)) + } + if math.IsInf(f64, 0) { panic("cannot convert untyped bigdec to float64 -- too close to +-Inf") } dst.SetFloat64(f64) diff --git a/gnovm/pkg/gnolang/values_conversions_test.go b/gnovm/pkg/gnolang/values_conversions_test.go new file mode 100644 index 00000000000..b9ac9e68d68 --- /dev/null +++ b/gnovm/pkg/gnolang/values_conversions_test.go @@ -0,0 +1,25 @@ +package gnolang + +import ( + "math" + "testing" + + "github.com/cockroachdb/apd" + "github.com/stretchr/testify/require" +) + +func TestConvertUntypedBigdecToFloat(t *testing.T) { + dst := &TypedValue{} + + dec, err := apd.New(-math.MaxInt64, -4).SetFloat64(math.SmallestNonzeroFloat64 / 2) + require.NoError(t, err) + bd := BigdecValue{ + V: dec, + } + + typ := Float64Type + + ConvertUntypedBigdecTo(dst, bd, typ) + + require.Equal(t, float64(0), dst.GetFloat64()) +} diff --git a/gnovm/tests/files/float6.gno b/gnovm/tests/files/float6.gno new file mode 100644 index 00000000000..680b9461975 --- /dev/null +++ b/gnovm/tests/files/float6.gno @@ -0,0 +1,13 @@ +package main + +const ( + SmallestNonzeroFloat64 = 0x1p-1022 * 0x1p-52 // 4.9406564584124654417656879286822137236505980e-324 + DividedByTwo = SmallestNonzeroFloat64 / 2 +) + +func main() { + println(DividedByTwo) +} + +// Output: +// 0 diff --git a/gnovm/tests/files/float7.gno b/gnovm/tests/files/float7.gno new file mode 100644 index 00000000000..f519a963523 --- /dev/null +++ b/gnovm/tests/files/float7.gno @@ -0,0 +1,15 @@ +package main + +const ( + SmallestNonzeroFloat32 = 0x1p-126 * 0x1p-23 // 1.401298464324817070923729583289916131280e-45 + DividedByTwo = SmallestNonzeroFloat32 / 2 +) + +func main() { + var i float32 + i = DividedByTwo + println(i) +} + +// Output: +// 0