Skip to content

Commit

Permalink
fix: allow constant values of infininitesimal non-zero floating points (
Browse files Browse the repository at this point in the history
#1185)

Added a unit test and an integration test trying to reproduce #1150 

Avoid unhandled errors.

- [x] Added new tests, or not needed, or not feasible
- [x] Provided an example (e.g. screenshot) to aid review or the PR is
self-explanatory
- [x] Updated the official documentation or not needed
- [x] No breaking changes were made, or a `BREAKING CHANGE: xxx` message
was included in the description
- [x] Added references to related issues and PRs
- [x] Provided any useful hints for running manual tests
- [x] Added new benchmarks to [generated
graphs](https://gnoland.github.io/benchmarks), if any. More info
[here](https://github.com/gnolang/gno/blob/master/.benchmarks/README.md).

---------

Signed-off-by: Antonio Navarro Perez <antnavper@gmail.com>
Co-authored-by: Morgan Bazalgette <morgan@morganbaz.com>
  • Loading branch information
ajnavarro and thehowl authored Oct 21, 2023
1 parent f6d500a commit 5cf3c71
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 9 deletions.
21 changes: 12 additions & 9 deletions gnovm/pkg/gnolang/values_conversions.go
Original file line number Diff line number Diff line change
Expand Up @@ -1240,23 +1240,26 @@ 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)
return
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)
Expand Down
25 changes: 25 additions & 0 deletions gnovm/pkg/gnolang/values_conversions_test.go
Original file line number Diff line number Diff line change
@@ -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())
}
13 changes: 13 additions & 0 deletions gnovm/tests/files/float6.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package main

const (
SmallestNonzeroFloat64 = 0x1p-1022 * 0x1p-52 // 4.9406564584124654417656879286822137236505980e-324
DividedByTwo = SmallestNonzeroFloat64 / 2
)

func main() {
println(DividedByTwo)
}

// Output:
// 0
15 changes: 15 additions & 0 deletions gnovm/tests/files/float7.gno
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 5cf3c71

Please sign in to comment.