From 7f7b888a5d3d5e718f94a24b32e7681974ac33aa Mon Sep 17 00:00:00 2001 From: Omar Sy Date: Fri, 20 Dec 2024 23:06:15 +0100 Subject: [PATCH] feat: use softfloat as is it --- gno.land/pkg/sdk/vm/convert.go | 5 +- gnovm/pkg/gnolang/frame.go | 5 +- gnovm/pkg/gnolang/gonative.go | 19 +- .../gnolang/internal/softfloat/softfloat.go | 45 +++ gnovm/pkg/gnolang/op_binary.go | 41 +-- gnovm/pkg/gnolang/op_inc_dec.go | 9 +- gnovm/pkg/gnolang/op_unary.go | 5 +- gnovm/pkg/gnolang/softfloat.go | 338 ------------------ gnovm/pkg/gnolang/values.go | 20 +- gnovm/pkg/gnolang/values_conversions.go | 215 +++++------ gnovm/pkg/gnolang/values_conversions_test.go | 3 +- gnovm/pkg/gnolang/values_string.go | 9 +- 12 files changed, 216 insertions(+), 498 deletions(-) delete mode 100644 gnovm/pkg/gnolang/softfloat.go diff --git a/gno.land/pkg/sdk/vm/convert.go b/gno.land/pkg/sdk/vm/convert.go index 89fc3e0973d..dbaabcfbc4b 100644 --- a/gno.land/pkg/sdk/vm/convert.go +++ b/gno.land/pkg/sdk/vm/convert.go @@ -3,6 +3,7 @@ package vm import ( "encoding/base64" "fmt" + "math" "strconv" "strings" @@ -143,11 +144,11 @@ func convertArgToGno(arg string, argT gno.Type) (tv gno.TypedValue) { return case gno.Float32Type: value := convertFloat(arg, 32) - tv.SetFloat32(gno.ConvertToSoftFloat32(value)) + tv.SetFloat32(math.Float32bits(float32(value))) return case gno.Float64Type: value := convertFloat(arg, 64) - tv.SetFloat64(gno.ConvertToSoftFloat64(value)) + tv.SetFloat64(math.Float64bits(value)) return default: panic(fmt.Sprintf("unexpected primitive type %s", bt.String())) diff --git a/gnovm/pkg/gnolang/frame.go b/gnovm/pkg/gnolang/frame.go index 2ac1027eb32..60f19979b7a 100644 --- a/gnovm/pkg/gnolang/frame.go +++ b/gnovm/pkg/gnolang/frame.go @@ -2,6 +2,7 @@ package gnolang import ( "fmt" + "math" "strings" ) @@ -207,9 +208,9 @@ func toConstExpTrace(cte *ConstExpr) string { case Uint64Type: return fmt.Sprintf("%d", tv.GetUint64()) case Float32Type: - return fmt.Sprintf("%v", tv.GetFloat32()) + return fmt.Sprintf("%v", math.Float32frombits(tv.GetFloat32())) case Float64Type: - return fmt.Sprintf("%v", tv.GetFloat64()) + return fmt.Sprintf("%v", math.Float64frombits(tv.GetFloat64())) } } diff --git a/gnovm/pkg/gnolang/gonative.go b/gnovm/pkg/gnolang/gonative.go index e77c7f99474..85fc8b70051 100644 --- a/gnovm/pkg/gnolang/gonative.go +++ b/gnovm/pkg/gnolang/gonative.go @@ -2,7 +2,10 @@ package gnolang import ( "fmt" + "math" "reflect" + + "github.com/gnolang/gno/gnovm/pkg/gnolang/internal/softfloat" ) // NOTE @@ -329,9 +332,9 @@ func go2GnoValue(alloc *Allocator, rv reflect.Value) (tv TypedValue) { case reflect.Uint64: tv.SetUint64(rv.Uint()) case reflect.Float32: - tv.SetFloat32(ConvertToSoftFloat32(rv.Float())) + tv.SetFloat32(softfloat.F64to32(math.Float64bits(rv.Float()))) case reflect.Float64: - tv.SetFloat64(ConvertToSoftFloat64(rv.Float())) + tv.SetFloat64(math.Float64bits(rv.Float())) case reflect.Array: tv.V = alloc.NewNative(rv) case reflect.Slice: @@ -428,11 +431,11 @@ func go2GnoValueUpdate(alloc *Allocator, rlm *Realm, lvl int, tv *TypedValue, rv } case Float32Kind: if lvl != 0 { - tv.SetFloat32(ConvertToSoftFloat32(rv.Float())) + tv.SetFloat32(softfloat.F64to32(math.Float64bits(rv.Float()))) } case Float64Kind: if lvl != 0 { - tv.SetFloat64(ConvertToSoftFloat64(rv.Float())) + tv.SetFloat64(math.Float64bits(rv.Float())) } case BigintKind: panic("not yet implemented") @@ -644,9 +647,9 @@ func go2GnoValue2(alloc *Allocator, store Store, rv reflect.Value, recursive boo case reflect.Uint64: tv.SetUint64(rv.Uint()) case reflect.Float32: - tv.SetFloat32(ConvertToSoftFloat32(rv.Float())) + tv.SetFloat32(softfloat.F64to32(math.Float64bits(rv.Float()))) case reflect.Float64: - tv.SetFloat64(ConvertToSoftFloat64(rv.Float())) + tv.SetFloat64(math.Float64bits(rv.Float())) case reflect.Array: rvl := rv.Len() if rv.Type().Elem().Kind() == reflect.Uint8 { @@ -1049,9 +1052,9 @@ func gno2GoValue(tv *TypedValue, rv reflect.Value) (ret reflect.Value) { case Uint64Type: rv.SetUint(tv.GetUint64()) case Float32Type: - rv.SetFloat(tv.GetFloat32().Float64()) + rv.SetFloat(math.Float64frombits(softfloat.F32to64(tv.GetFloat32()))) case Float64Type: - rv.SetFloat(tv.GetFloat64().Float64()) + rv.SetFloat(math.Float64frombits(tv.GetFloat64())) default: panic(fmt.Sprintf( "unexpected type %s", diff --git a/gnovm/pkg/gnolang/internal/softfloat/softfloat.go b/gnovm/pkg/gnolang/internal/softfloat/softfloat.go index 73f7fa79be0..30f66dff620 100644 --- a/gnovm/pkg/gnolang/internal/softfloat/softfloat.go +++ b/gnovm/pkg/gnolang/internal/softfloat/softfloat.go @@ -19,6 +19,12 @@ package softfloat //go:generate sh copy.sh +const ( + mask = 0x7FF + shift = 64 - 11 - 1 + bias = 1023 +) + func Fadd64(f, g uint64) uint64 { return fadd64(f, g) } func Fsub64(f, g uint64) uint64 { return fsub64(f, g) } func Fmul64(f, g uint64) uint64 { return fmul64(f, g) } @@ -87,3 +93,42 @@ func Fuint64to64(x uint64) uint64 { return fuint64to64(x) } func Funpack32(f uint32) (sign, mant uint32, exp int, inf, nan bool) { return funpack32(f) } func Funpack64(f uint64) (sign, mant uint64, exp int, inf, nan bool) { return funpack64(f) } + +// Trunc + +func Ftrunc64(f uint64) uint64 { return trunc(f) } +func Ftrunc32(f uint32) uint32 { return f64to32(trunc(f32to64(f))) } + +func trunc(x uint64) uint64 { + cmp, _ := Fcmp64(x, Fintto64(0)) + if _, _, _, isInf, IsNaN := Funpack64(x); cmp == 0 || isInf || IsNaN { + return x + } + + d, _ := modf(x) + return d +} + +func modf(u uint64) (it uint64, frac uint64) { + if Flt64(u, fint64to64(1)) { + switch { + case Flt64(u, fint64to64(0)): + it, frac = modf(Fneg64(u)) + return -it, -frac + case feq64(u, fint64to64(0)): + return u, u // Return -0, -0 when f == -0 + } + return 0, u + } + + it = u + e := uint(it>>shift)&mask - bias + + // Keep the top 12+e bits, the integer part; clear the rest. + if e < 64-12 { + it &^= 1<<(64-12-e) - 1 + } + + frac = fsub64(u, it) + return +} diff --git a/gnovm/pkg/gnolang/op_binary.go b/gnovm/pkg/gnolang/op_binary.go index e99a5505058..60f5a41293e 100644 --- a/gnovm/pkg/gnolang/op_binary.go +++ b/gnovm/pkg/gnolang/op_binary.go @@ -6,6 +6,7 @@ import ( "math/big" "github.com/cockroachdb/apd/v3" + "github.com/gnolang/gno/gnovm/pkg/gnolang/internal/softfloat" ) // ---------------------------------------- @@ -391,9 +392,9 @@ func isEql(store Store, lv, rv *TypedValue) bool { case Uint64Kind: return (lv.GetUint64() == rv.GetUint64()) case Float32Kind: - return lv.GetFloat32().Eq(rv.GetFloat32()) + return softfloat.Feq32(lv.GetFloat32(), rv.GetFloat32()) case Float64Kind: - return lv.GetFloat64().Eq(rv.GetFloat64()) + return softfloat.Feq64(lv.GetFloat64(), rv.GetFloat64()) case BigintKind: lb := lv.V.(BigintValue).V rb := rv.V.(BigintValue).V @@ -532,9 +533,9 @@ func isLss(lv, rv *TypedValue) bool { case Uint64Kind: return (lv.GetUint64() < rv.GetUint64()) case Float32Kind: - return lv.GetFloat32().Lt(rv.GetFloat32()) + return softfloat.Flt32(lv.GetFloat32(), rv.GetFloat32()) case Float64Kind: - return lv.GetFloat64().Lt(rv.GetFloat64()) + return softfloat.Flt64(lv.GetFloat64(), rv.GetFloat64()) case BigintKind: lb := lv.V.(BigintValue).V rb := rv.V.(BigintValue).V @@ -576,9 +577,9 @@ func isLeq(lv, rv *TypedValue) bool { case Uint64Kind: return (lv.GetUint64() <= rv.GetUint64()) case Float32Kind: - return lv.GetFloat32().Le(rv.GetFloat32()) + return softfloat.Fle32(lv.GetFloat32(), rv.GetFloat32()) case Float64Kind: - return lv.GetFloat64().Le(rv.GetFloat64()) + return softfloat.Fle64(lv.GetFloat64(), rv.GetFloat64()) case BigintKind: lb := lv.V.(BigintValue).V rb := rv.V.(BigintValue).V @@ -620,9 +621,9 @@ func isGtr(lv, rv *TypedValue) bool { case Uint64Kind: return (lv.GetUint64() > rv.GetUint64()) case Float32Kind: - return lv.GetFloat32().Gt(rv.GetFloat32()) + return softfloat.Fgt32(lv.GetFloat32(), rv.GetFloat32()) case Float64Kind: - return lv.GetFloat64().Gt(rv.GetFloat64()) + return softfloat.Fgt64(lv.GetFloat64(), rv.GetFloat64()) case BigintKind: lb := lv.V.(BigintValue).V rb := rv.V.(BigintValue).V @@ -664,9 +665,9 @@ func isGeq(lv, rv *TypedValue) bool { case Uint64Kind: return (lv.GetUint64() >= rv.GetUint64()) case Float32Kind: - return lv.GetFloat32().Ge(rv.GetFloat32()) + return softfloat.Fge32(lv.GetFloat32(), rv.GetFloat32()) case Float64Kind: - return lv.GetFloat64().Ge(rv.GetFloat64()) + return softfloat.Fge64(lv.GetFloat64(), rv.GetFloat64()) case BigintKind: lb := lv.V.(BigintValue).V rb := rv.V.(BigintValue).V @@ -714,10 +715,10 @@ func addAssign(alloc *Allocator, lv, rv *TypedValue) { lv.SetUint64(lv.GetUint64() + rv.GetUint64()) case Float32Type: // NOTE: gno doesn't fuse *+. - lv.SetFloat32(lv.GetFloat32().Add(rv.GetFloat32())) + lv.SetFloat32(softfloat.Fadd32(lv.GetFloat32(), rv.GetFloat32())) case Float64Type: // NOTE: gno doesn't fuse *+. - lv.SetFloat64(lv.GetFloat64().Add(rv.GetFloat64())) + lv.SetFloat64(softfloat.Fadd64(lv.GetFloat64(), rv.GetFloat64())) case BigintType, UntypedBigintType: lb := lv.GetBigInt() lb = big.NewInt(0).Add(lb, rv.GetBigInt()) @@ -770,10 +771,10 @@ func subAssign(lv, rv *TypedValue) { lv.SetUint64(lv.GetUint64() - rv.GetUint64()) case Float32Type: // NOTE: gno doesn't fuse *+. - lv.SetFloat32(lv.GetFloat32().Sub(rv.GetFloat32())) + lv.SetFloat32(softfloat.Fsub32(lv.GetFloat32(), rv.GetFloat32())) case Float64Type: // NOTE: gno doesn't fuse *+. - lv.SetFloat64(lv.GetFloat64().Sub(rv.GetFloat64())) + lv.SetFloat64(softfloat.Fsub64(lv.GetFloat64(), rv.GetFloat64())) case BigintType, UntypedBigintType: lb := lv.GetBigInt() lb = big.NewInt(0).Sub(lb, rv.GetBigInt()) @@ -826,10 +827,10 @@ func mulAssign(lv, rv *TypedValue) { lv.SetUint64(lv.GetUint64() * rv.GetUint64()) case Float32Type: // NOTE: gno doesn't fuse *+. - lv.SetFloat32(lv.GetFloat32().Mul(rv.GetFloat32())) + lv.SetFloat32(softfloat.Fmul32(lv.GetFloat32(), rv.GetFloat32())) case Float64Type: // NOTE: gno doesn't fuse *+. - lv.SetFloat64(lv.GetFloat64().Mul(rv.GetFloat64())) + lv.SetFloat64(softfloat.Fmul64(lv.GetFloat64(), rv.GetFloat64())) case BigintType, UntypedBigintType: lb := lv.GetBigInt() lb = big.NewInt(0).Mul(lb, rv.GetBigInt()) @@ -917,16 +918,16 @@ func quoAssign(lv, rv *TypedValue) *Exception { lv.SetUint64(lv.GetUint64() / rv.GetUint64()) case Float32Type: // NOTE: gno doesn't fuse *+. - if rv.GetFloat32().Eq(0) { + if softfloat.Feq32(rv.GetFloat32(), softfloat.Fintto32(0)) { return expt } - lv.SetFloat32(lv.GetFloat32().Div(rv.GetFloat32())) + lv.SetFloat32(softfloat.Fdiv32(lv.GetFloat32(), rv.GetFloat32())) case Float64Type: // NOTE: gno doesn't fuse *+. - if rv.GetFloat64().Eq(0) { + if softfloat.Feq64(rv.GetFloat64(), softfloat.Fintto64(0)) { return expt } - lv.SetFloat64(lv.GetFloat64().Div(rv.GetFloat64())) + lv.SetFloat64(softfloat.Fdiv64(lv.GetFloat64(), rv.GetFloat64())) case BigintType, UntypedBigintType: if rv.GetBigInt().Sign() == 0 { return expt diff --git a/gnovm/pkg/gnolang/op_inc_dec.go b/gnovm/pkg/gnolang/op_inc_dec.go index 98583a57976..708aae821ac 100644 --- a/gnovm/pkg/gnolang/op_inc_dec.go +++ b/gnovm/pkg/gnolang/op_inc_dec.go @@ -5,6 +5,7 @@ import ( "math/big" "github.com/cockroachdb/apd/v3" + "github.com/gnolang/gno/gnovm/pkg/gnolang/internal/softfloat" ) func (m *Machine) doOpInc() { @@ -54,9 +55,9 @@ func (m *Machine) doOpInc() { case Uint64Type: lv.SetUint64(lv.GetUint64() + 1) case Float32Type: - lv.SetFloat32(lv.GetFloat32().Add(1)) + lv.SetFloat32(softfloat.Fadd32(lv.GetFloat32(), softfloat.Fintto32(1))) case Float64Type: - lv.SetFloat64(lv.GetFloat64().Add(1)) + lv.SetFloat64(softfloat.Fadd64(lv.GetFloat64(), softfloat.Fintto64(1))) case BigintType, UntypedBigintType: lb := lv.GetBigInt() lb = big.NewInt(0).Add(lb, big.NewInt(1)) @@ -124,9 +125,9 @@ func (m *Machine) doOpDec() { case Uint64Type: lv.SetUint64(lv.GetUint64() - 1) case Float32Type: - lv.SetFloat32(lv.GetFloat32().Sub(1)) + lv.SetFloat32(softfloat.Fsub32(lv.GetFloat32(), softfloat.Fintto32(1))) case Float64Type: - lv.SetFloat64(lv.GetFloat64().Sub(1)) + lv.SetFloat64(softfloat.Fsub64(lv.GetFloat64(), softfloat.Fintto64(1))) case BigintType, UntypedBigintType: lb := lv.GetBigInt() lb = big.NewInt(0).Sub(lb, big.NewInt(1)) diff --git a/gnovm/pkg/gnolang/op_unary.go b/gnovm/pkg/gnolang/op_unary.go index 99ecb98d792..469c80b8dac 100644 --- a/gnovm/pkg/gnolang/op_unary.go +++ b/gnovm/pkg/gnolang/op_unary.go @@ -5,6 +5,7 @@ import ( "math/big" "github.com/cockroachdb/apd/v3" + "github.com/gnolang/gno/gnovm/pkg/gnolang/internal/softfloat" ) func (m *Machine) doOpUpos() { @@ -46,9 +47,9 @@ func (m *Machine) doOpUneg() { case Uint64Type: xv.SetUint64(-xv.GetUint64()) case Float32Type: - xv.SetFloat32(xv.GetFloat32().Neg()) + xv.SetFloat32(softfloat.Fneg32(xv.GetFloat32())) case Float64Type: - xv.SetFloat64(xv.GetFloat64().Neg()) + xv.SetFloat64(softfloat.Fneg64(xv.GetFloat64())) case UntypedBigintType, BigintType: bv := xv.V.(BigintValue) xv.V = BigintValue{V: new(big.Int).Neg(bv.V)} diff --git a/gnovm/pkg/gnolang/softfloat.go b/gnovm/pkg/gnolang/softfloat.go deleted file mode 100644 index 342ce493e8a..00000000000 --- a/gnovm/pkg/gnolang/softfloat.go +++ /dev/null @@ -1,338 +0,0 @@ -package gnolang - -import ( - "fmt" - "math" - - "github.com/gnolang/gno/gnovm/pkg/gnolang/internal/softfloat" -) - -const ( - mask = 0x7FF - shift = 64 - 11 - 1 - bias = 1023 -) - -type ( - SoftFloat64 uint64 - SoftFloat32 uint32 -) - -func Trunc(x SoftFloat64) SoftFloat64 { - cmp, _ := softfloat.Fcmp64(uint64(x), softfloat.Fintto64(0)) - if _, _, _, isInf, IsNaN := softfloat.Funpack64(uint64(x)); cmp == 0 || isInf || IsNaN { - return x - } - - d, _ := Modf(x) - return d -} - -func Modf(u SoftFloat64) (it SoftFloat64, frac SoftFloat64) { - if u.Lt(1) { - switch { - case u.Lt(0): - it, frac = Modf(u.Neg()) - return -it, -frac - case u.Eq(0): - return u, u // Return -0, -0 when f == -0 - } - return 0, u - } - - it = u - e := uint(it>>shift)&mask - bias - - // Keep the top 12+e bits, the integer part; clear the rest. - if e < 64-12 { - it &^= 1<<(64-12-e) - 1 - } - - frac = u.Sub(it) - return -} - -func ConvertToSoftFloat64(n any) SoftFloat64 { - switch n := n.(type) { - case SoftFloat64: - return n - case SoftFloat32: - return SoftFloat64(softfloat.F32to64(uint32(n))) - case int: - return SoftFloat64(softfloat.Fintto64(int64(n))) - case int32: - return SoftFloat64(softfloat.Fint32to64(n)) - case int8: - return SoftFloat64(softfloat.Fint32to64(int32(n))) - case int16: - return SoftFloat64(softfloat.Fint32to64(int32(n))) - case int64: - return SoftFloat64(softfloat.Fint64to64(n)) - case uint: - return SoftFloat64(softfloat.Fuint64to64(uint64(n))) - case uint16: - return SoftFloat64(softfloat.Fuint64to64(uint64(n))) - case uint32: - return SoftFloat64(softfloat.Fuint64to64(uint64(n))) - case uint8: - return SoftFloat64(softfloat.Fuint64to64(uint64(n))) - case uint64: - return SoftFloat64(softfloat.Fuint64to64(n)) - case float32: - return SoftFloat32(math.Float32bits(n)).SoftFloat64() - case float64: - return SoftFloat64(math.Float64bits(n)) - default: - panic(fmt.Sprintf("unsupported type: %T", n)) - } -} - -func ConvertToSoftFloat32(n any) SoftFloat32 { - switch n := n.(type) { - case SoftFloat64: - return SoftFloat32(softfloat.F64to32(uint64(n))) - case SoftFloat32: - return n - case int: - return SoftFloat32(softfloat.Fintto32(int64(n))) - case int32: - return SoftFloat32(softfloat.Fint32to32(n)) - case int8: - return SoftFloat32(softfloat.Fint32to32(int32(n))) - case int16: - return SoftFloat32(softfloat.Fint32to32(int32(n))) - case int64: - return SoftFloat32(softfloat.Fint64to32(n)) - case uint: - return SoftFloat32(softfloat.Fuint64to32(uint64(n))) - case uint16: - return SoftFloat32(softfloat.Fuint64to32(uint64(n))) - case uint32: - return SoftFloat32(softfloat.Fuint64to32(uint64(n))) - case uint8: - return SoftFloat32(softfloat.Fuint64to32(uint64(n))) - case uint64: - return SoftFloat32(softfloat.Fuint64to32(n)) - case float32: - return SoftFloat32(math.Float32bits(n)) - case float64: - return SoftFloat64(math.Float64bits(n)).SoftFloat32() - default: - panic(fmt.Sprintf("unsupported type: %T", n)) - } -} - -// SoftFloat64 - -func (f SoftFloat64) String() string { - return fmt.Sprintf("%v", math.Float64frombits(uint64(f))) -} - -func (f SoftFloat64) Float64() float64 { - return math.Float64frombits(uint64(f)) -} - -func (f SoftFloat64) Float32() float32 { - return float32(math.Float64frombits(uint64(f))) -} - -func (f SoftFloat64) SoftFloat32() SoftFloat32 { - return SoftFloat32(softfloat.F64to32(uint64(f))) -} - -func (f SoftFloat64) Int() int { - n, _ := softfloat.F64toint(uint64(f)) - return int(n) -} - -func (f SoftFloat64) Int64() int64 { - return softfloat.F64toint64(uint64(f)) -} - -func (f SoftFloat64) Int32() int32 { - return softfloat.F64toint32(uint64(f)) -} - -func (f SoftFloat64) Int16() int16 { - return int16(softfloat.F64toint32(uint64(f))) -} - -func (f SoftFloat64) Int8() int8 { - return int8(softfloat.F64toint32(uint64(f))) -} - -func (f SoftFloat64) Uint() uint { - return uint(softfloat.F64touint64(uint64(f))) -} - -func (f SoftFloat64) Uint64() uint64 { - return softfloat.F64touint64(uint64(f)) -} - -func (f SoftFloat64) Uint32() uint32 { - return uint32(softfloat.F64touint64(uint64(f))) -} - -func (f SoftFloat64) Uint16() uint16 { - return uint16(softfloat.F64touint64(uint64(f))) -} - -func (f SoftFloat64) Uint8() uint8 { - return uint8(softfloat.F64touint64(uint64(f))) -} - -func (f SoftFloat64) Add(g any) SoftFloat64 { - return SoftFloat64(softfloat.Fadd64(uint64(f), uint64(ConvertToSoftFloat64(g)))) -} - -func (f SoftFloat64) Sub(g any) SoftFloat64 { - return SoftFloat64(softfloat.Fsub64(uint64(f), uint64(ConvertToSoftFloat64(g)))) -} - -func (f SoftFloat64) Mul(g any) SoftFloat64 { - return SoftFloat64(softfloat.Fmul64(uint64(f), uint64(ConvertToSoftFloat64(g)))) -} - -func (f SoftFloat64) Div(g any) SoftFloat64 { - return SoftFloat64(softfloat.Fdiv64(uint64(f), uint64(ConvertToSoftFloat64(g)))) -} - -func (f SoftFloat64) Neg() SoftFloat64 { - return SoftFloat64(softfloat.Fneg64(uint64(f))) -} - -func (f SoftFloat64) Trunc() SoftFloat64 { - return Trunc(f) -} - -// == -func (f SoftFloat64) Eq(g any) bool { - return softfloat.Feq64(uint64(f), uint64(ConvertToSoftFloat64(g))) -} - -// > -func (f SoftFloat64) Gt(g any) bool { - return softfloat.Fgt64(uint64(f), uint64(ConvertToSoftFloat64(g))) -} - -// >= -func (f SoftFloat64) Ge(g any) bool { - return softfloat.Fge64(uint64(f), uint64(ConvertToSoftFloat64(g))) -} - -// < -func (f SoftFloat64) Lt(g any) bool { - return softfloat.Flt64(uint64(f), uint64(ConvertToSoftFloat64(g))) -} - -// <= -func (f SoftFloat64) Le(g any) bool { - return softfloat.Fle64(uint64(f), uint64(ConvertToSoftFloat64(g))) -} - -// SoftFloat32 - -func (f SoftFloat32) Float32() float32 { - return math.Float32frombits(uint32(f)) -} - -func (f SoftFloat32) Float64() float64 { - return math.Float64frombits(softfloat.F32to64(uint32(f))) -} - -func (f SoftFloat32) SoftFloat64() SoftFloat64 { - return SoftFloat64(softfloat.F32to64(uint32(f))) -} - -func (f SoftFloat32) Int() int { - return int(softfloat.F32toint64(uint32(f))) -} - -func (f SoftFloat32) Int64() int64 { - return softfloat.F32toint64(uint32(f)) -} - -func (f SoftFloat32) Int32() int32 { - return softfloat.F32toint32(uint32(f)) -} - -func (f SoftFloat32) Int16() int16 { - return int16(softfloat.F32toint32(uint32(f))) -} - -func (f SoftFloat32) Int8() int8 { - return int8(softfloat.F32toint32(uint32(f))) -} - -func (f SoftFloat32) Uint() uint { - return uint(softfloat.F32touint64(uint32(f))) -} - -func (f SoftFloat32) Uint64() uint64 { - return softfloat.F32touint64(uint32(f)) -} - -func (f SoftFloat32) Uint32() uint32 { - return uint32(softfloat.F32touint64(uint32(f))) -} - -func (f SoftFloat32) Uint16() uint16 { - return uint16(softfloat.F32touint64(uint32(f))) -} - -func (f SoftFloat32) Uint8() uint8 { - return uint8(softfloat.F32touint64(uint32(f))) -} - -func (f SoftFloat32) Add(g any) SoftFloat32 { - return SoftFloat32(softfloat.Fadd32(uint32(f), uint32(ConvertToSoftFloat32(g)))) -} - -func (f SoftFloat32) Sub(g any) SoftFloat32 { - return SoftFloat32(softfloat.Fsub32(uint32(f), uint32(ConvertToSoftFloat32(g)))) -} - -func (f SoftFloat32) Mul(g any) SoftFloat32 { - return SoftFloat32(softfloat.Fmul32(uint32(f), uint32(ConvertToSoftFloat32(g)))) -} - -func (f SoftFloat32) Div(g any) SoftFloat32 { - return SoftFloat32(softfloat.Fdiv32(uint32(f), uint32(ConvertToSoftFloat32(g)))) -} - -func (f SoftFloat32) Neg() SoftFloat32 { - return SoftFloat32(softfloat.Fneg32(uint32(f))) -} - -func (f SoftFloat32) Trunc() SoftFloat32 { - return SoftFloat32(softfloat.F64to32(uint64(Trunc(SoftFloat64(softfloat.F32to64(uint32(f))))))) -} - -// == -func (f SoftFloat32) Eq(g any) bool { - return softfloat.Feq32(uint32(f), uint32(ConvertToSoftFloat32(g))) -} - -// > -func (f SoftFloat32) Gt(g any) bool { - return softfloat.Fgt32(uint32(f), uint32(ConvertToSoftFloat32(g))) -} - -// >= -func (f SoftFloat32) Ge(g any) bool { - return softfloat.Fge32(uint32(f), uint32(ConvertToSoftFloat32(g))) -} - -// < -func (f SoftFloat32) Lt(g any) bool { - return softfloat.Flt32(uint32(f), uint32(ConvertToSoftFloat32(g))) -} - -// <= -func (f SoftFloat32) Le(g any) bool { - return softfloat.Fle32(uint32(f), uint32(ConvertToSoftFloat32(g))) -} - -func (f SoftFloat32) String() string { - return fmt.Sprintf("%v", math.Float32frombits(uint32(f))) -} diff --git a/gnovm/pkg/gnolang/values.go b/gnovm/pkg/gnolang/values.go index 84e2882b519..da887764c8e 100644 --- a/gnovm/pkg/gnolang/values.go +++ b/gnovm/pkg/gnolang/values.go @@ -1122,13 +1122,13 @@ func (tv *TypedValue) PrimitiveBytes() (data []byte) { data = make([]byte, 4) u32 := tv.GetFloat32() binary.LittleEndian.PutUint32( - data, uint32(u32)) + data, u32) return data case Float64Type: data = make([]byte, 8) u64 := tv.GetFloat64() binary.LittleEndian.PutUint64( - data, uint64(u64)) + data, u64) return data case BigintType: return tv.V.(BigintValue).V.Bytes() @@ -1449,7 +1449,7 @@ func (tv *TypedValue) GetUint64() uint64 { return *(*uint64)(unsafe.Pointer(&tv.N)) } -func (tv *TypedValue) SetFloat32(n SoftFloat32) { +func (tv *TypedValue) SetFloat32(n uint32) { if debug { if tv.T.Kind() != Float32Kind || isNative(tv.T) { panic(fmt.Sprintf( @@ -1457,10 +1457,10 @@ func (tv *TypedValue) SetFloat32(n SoftFloat32) { tv.T.String())) } } - *(*SoftFloat32)(unsafe.Pointer(&tv.N)) = n + *(*uint32)(unsafe.Pointer(&tv.N)) = n } -func (tv *TypedValue) GetFloat32() SoftFloat32 { +func (tv *TypedValue) GetFloat32() uint32 { if debug { if tv.T != nil && tv.T.Kind() != Float32Kind { panic(fmt.Sprintf( @@ -1468,10 +1468,10 @@ func (tv *TypedValue) GetFloat32() SoftFloat32 { tv.T.String())) } } - return *(*SoftFloat32)(unsafe.Pointer(&tv.N)) + return *(*uint32)(unsafe.Pointer(&tv.N)) } -func (tv *TypedValue) SetFloat64(n SoftFloat64) { +func (tv *TypedValue) SetFloat64(n uint64) { if debug { if tv.T.Kind() != Float64Kind || isNative(tv.T) { panic(fmt.Sprintf( @@ -1479,10 +1479,10 @@ func (tv *TypedValue) SetFloat64(n SoftFloat64) { tv.T.String())) } } - *(*SoftFloat64)(unsafe.Pointer(&tv.N)) = n + *(*uint64)(unsafe.Pointer(&tv.N)) = n } -func (tv *TypedValue) GetFloat64() SoftFloat64 { +func (tv *TypedValue) GetFloat64() uint64 { if debug { if tv.T != nil && tv.T.Kind() != Float64Kind { panic(fmt.Sprintf( @@ -1490,7 +1490,7 @@ func (tv *TypedValue) GetFloat64() SoftFloat64 { tv.T.String())) } } - return *(*SoftFloat64)(unsafe.Pointer(&tv.N)) + return *(*uint64)(unsafe.Pointer(&tv.N)) } func (tv *TypedValue) GetBigInt() *big.Int { diff --git a/gnovm/pkg/gnolang/values_conversions.go b/gnovm/pkg/gnolang/values_conversions.go index 09963185b58..e1c9378fe67 100644 --- a/gnovm/pkg/gnolang/values_conversions.go +++ b/gnovm/pkg/gnolang/values_conversions.go @@ -8,6 +8,7 @@ import ( "strconv" "github.com/cockroachdb/apd/v3" + "github.com/gnolang/gno/gnovm/pkg/gnolang/internal/softfloat" ) // t cannot be nil or untyped or DataByteType. @@ -163,11 +164,11 @@ GNO_CASE: tv.T = t tv.SetUint64(x) case Float32Kind: - x := ConvertToSoftFloat32(tv.GetInt()) + x := softfloat.Fintto32(int64(tv.GetInt())) tv.T = t tv.SetFloat32(x) case Float64Kind: - x := ConvertToSoftFloat64(tv.GetInt()) + x := softfloat.Fintto64(int64(tv.GetInt())) tv.T = t tv.SetFloat64(x) case StringKind: @@ -233,11 +234,11 @@ GNO_CASE: tv.T = t tv.SetUint64(x) case Float32Kind: - x := ConvertToSoftFloat32(tv.GetInt8()) + x := softfloat.Fint32to32(int32(tv.GetInt8())) tv.T = t tv.SetFloat32(x) case Float64Kind: - x := ConvertToSoftFloat64(tv.GetInt8()) + x := softfloat.Fint32to64(int32(tv.GetInt8())) tv.T = t tv.SetFloat64(x) case StringKind: @@ -304,11 +305,11 @@ GNO_CASE: tv.T = t tv.SetUint64(x) case Float32Kind: - x := ConvertToSoftFloat32(tv.GetInt16()) + x := softfloat.Fint32to32(int32(tv.GetInt16())) tv.T = t tv.SetFloat32(x) case Float64Kind: - x := ConvertToSoftFloat64(tv.GetInt16()) + x := softfloat.Fint32to64(int32(tv.GetInt16())) tv.T = t tv.SetFloat64(x) case StringKind: @@ -379,11 +380,11 @@ GNO_CASE: tv.T = t tv.SetUint64(x) case Float32Kind: - x := ConvertToSoftFloat32(tv.GetInt32()) + x := softfloat.Fint32to32(tv.GetInt32()) tv.T = t tv.SetFloat32(x) case Float64Kind: - x := ConvertToSoftFloat64(tv.GetInt32()) + x := softfloat.Fint32to64(tv.GetInt32()) tv.T = t tv.SetFloat64(x) case StringKind: @@ -456,11 +457,11 @@ GNO_CASE: tv.T = t tv.SetUint64(x) case Float32Kind: - x := ConvertToSoftFloat32(tv.GetInt64()) + x := softfloat.Fint64to32(tv.GetInt64()) tv.T = t tv.SetFloat32(x) case Float64Kind: - x := ConvertToSoftFloat64(tv.GetInt64()) + x := softfloat.Fint64to64(tv.GetInt64()) tv.T = t tv.SetFloat64(x) case StringKind: @@ -533,11 +534,11 @@ GNO_CASE: tv.T = t tv.SetUint64(x) case Float32Kind: - x := ConvertToSoftFloat32(tv.GetUint()) + x := softfloat.Fuint64to32(uint64(tv.GetUint())) tv.T = t tv.SetFloat32(x) case Float64Kind: - x := ConvertToSoftFloat64(tv.GetUint()) + x := softfloat.Fuint64to64(uint64(tv.GetUint())) tv.T = t tv.SetFloat64(x) case StringKind: @@ -602,11 +603,11 @@ GNO_CASE: tv.T = t tv.SetUint64(x) case Float32Kind: - x := ConvertToSoftFloat32(tv.GetUint8()) + x := softfloat.Fuint64to32(uint64(tv.GetUint8())) tv.T = t tv.SetFloat32(x) case Float64Kind: - x := ConvertToSoftFloat64(tv.GetUint8()) + x := softfloat.Fuint64to64(uint64(tv.GetUint8())) tv.T = t tv.SetFloat64(x) case StringKind: @@ -673,11 +674,11 @@ GNO_CASE: tv.T = t tv.SetUint64(x) case Float32Kind: - x := ConvertToSoftFloat32(tv.GetUint16()) + x := softfloat.Fuint64to32(uint64(tv.GetUint16())) tv.T = t tv.SetFloat32(x) case Float64Kind: - x := ConvertToSoftFloat64(tv.GetUint16()) + x := softfloat.Fuint64to64(uint64(tv.GetUint16())) tv.T = t tv.SetFloat64(x) case StringKind: @@ -746,11 +747,11 @@ GNO_CASE: tv.T = t tv.SetUint64(x) case Float32Kind: - x := ConvertToSoftFloat32(tv.GetUint32()) + x := softfloat.Fuint64to32(uint64(tv.GetUint32())) tv.T = t tv.SetFloat32(x) case Float64Kind: - x := ConvertToSoftFloat64(tv.GetUint32()) + x := softfloat.Fuint64to64(uint64(tv.GetUint32())) tv.T = t tv.SetFloat64(x) case StringKind: @@ -825,11 +826,11 @@ GNO_CASE: tv.T = t tv.SetUint64(x) case Float32Kind: - x := ConvertToSoftFloat32(tv.GetUint64()) + x := softfloat.Fuint64to32(tv.GetUint64()) tv.T = t tv.SetFloat32(x) case Float64Kind: - x := ConvertToSoftFloat64(tv.GetUint64()) + x := softfloat.Fuint64to64(tv.GetUint64()) tv.T = t tv.SetFloat64(x) case StringKind: @@ -847,147 +848,147 @@ GNO_CASE: switch k { case IntKind: validate(Float32Kind, IntKind, func() bool { - trunc := tv.GetFloat32().Trunc() + trunc := softfloat.Ftrunc32(tv.GetFloat32()) - if !trunc.Eq(tv.GetFloat32()) { + if !softfloat.Feq32(trunc, tv.GetFloat32()) { return false } - truncInt64 := trunc.Int64() + truncInt64 := softfloat.F32toint64(trunc) return truncInt64 >= math.MinInt && truncInt64 <= math.MaxInt }) - x := tv.GetFloat32().Int() + x := int(softfloat.F32toint64(tv.GetFloat32())) tv.T = t tv.SetInt(x) case Int8Kind: validate(Float32Kind, Int8Kind, func() bool { - trunc := tv.GetFloat32().Trunc() + trunc := softfloat.Ftrunc32(tv.GetFloat32()) - if !trunc.Eq(tv.GetFloat32()) { + if !softfloat.Feq32(trunc, tv.GetFloat32()) { return false } - truncInt64 := trunc.Int64() + truncInt64 := softfloat.F32toint64(trunc) return truncInt64 >= math.MinInt8 && truncInt64 <= math.MaxInt8 }) - x := tv.GetFloat32().Int8() + x := int8(softfloat.F32toint32(tv.GetFloat32())) tv.T = t tv.SetInt8(x) case Int16Kind: validate(Float32Kind, Int16Kind, func() bool { - trunc := tv.GetFloat32().Trunc() + trunc := softfloat.Ftrunc32(tv.GetFloat32()) - if !trunc.Eq(tv.GetFloat32()) { + if !softfloat.Feq32(trunc, tv.GetFloat32()) { return false } - truncInt64 := trunc.Int64() + truncInt64 := softfloat.F32toint64(trunc) return truncInt64 >= math.MinInt16 && truncInt64 <= math.MaxInt16 }) - x := tv.GetFloat32().Int16() + x := int16(softfloat.F32toint32(tv.GetFloat32())) tv.T = t tv.SetInt16(x) case Int32Kind: validate(Float32Kind, Int32Kind, func() bool { - trunc := tv.GetFloat32().Trunc() + trunc := softfloat.Ftrunc32(tv.GetFloat32()) - if !trunc.Eq(tv.GetFloat32()) { + if !softfloat.Feq32(trunc, tv.GetFloat32()) { return false } - truncInt64 := trunc.Int64() + truncInt64 := softfloat.F32toint64(trunc) return truncInt64 >= math.MinInt32 && truncInt64 <= math.MaxInt32 }) - x := tv.GetFloat32().Int32() + x := softfloat.F32toint32(tv.GetFloat32()) tv.T = t tv.SetInt32(x) case Int64Kind: validate(Float32Kind, Int64Kind, func() bool { - trunc := tv.GetFloat32().Trunc() + trunc := softfloat.Ftrunc32(tv.GetFloat32()) - return tv.GetFloat32().Eq(trunc) + return softfloat.Feq32(trunc, tv.GetFloat32()) }) - x := tv.GetFloat32().Int64() + x := softfloat.F32toint64(tv.GetFloat32()) tv.T = t tv.SetInt64(x) case UintKind: validate(Float32Kind, UintKind, func() bool { - trunc := tv.GetFloat32().Trunc() + trunc := softfloat.Ftrunc32(tv.GetFloat32()) - if !trunc.Eq(tv.GetFloat32()) { + if !softfloat.Feq32(trunc, tv.GetFloat32()) { return false } - truncUint64 := trunc.Uint64() + truncUint64 := softfloat.F32touint64(trunc) return truncUint64 >= 0 && truncUint64 <= math.MaxUint }) - x := tv.GetFloat32().Uint() + x := uint(softfloat.F32touint64(tv.GetFloat32())) tv.T = t tv.SetUint(x) case Uint8Kind: validate(Float32Kind, Uint8Kind, func() bool { - trunc := tv.GetFloat32().Trunc() + trunc := softfloat.Ftrunc32(tv.GetFloat32()) - if !trunc.Eq(tv.GetFloat32()) { + if !softfloat.Feq32(trunc, tv.GetFloat32()) { return false } - truncUint64 := trunc.Uint64() + truncUint64 := softfloat.F32touint64(trunc) return truncUint64 >= 0 && truncUint64 <= math.MaxUint8 }) - x := tv.GetFloat32().Uint8() + x := uint8(softfloat.F32touint64(tv.GetFloat32())) tv.T = t tv.SetUint8(x) case Uint16Kind: validate(Float32Kind, Uint16Kind, func() bool { - trunc := tv.GetFloat32().Trunc() + trunc := softfloat.Ftrunc32(tv.GetFloat32()) - if !trunc.Eq(tv.GetFloat32()) { + if !softfloat.Feq32(trunc, tv.GetFloat32()) { return false } - truncUint64 := trunc.Uint64() + truncUint64 := softfloat.F32touint64(trunc) return truncUint64 >= 0 && truncUint64 <= math.MaxUint16 }) - x := tv.GetFloat32().Uint16() + x := uint16(softfloat.F32touint64(tv.GetFloat32())) tv.T = t tv.SetUint16(x) case Uint32Kind: validate(Float32Kind, Uint32Kind, func() bool { - trunc := tv.GetFloat32().Trunc() + trunc := softfloat.Ftrunc32(tv.GetFloat32()) - if !trunc.Eq(tv.GetFloat32()) { + if !softfloat.Feq32(trunc, tv.GetFloat32()) { return false } - truncUint64 := trunc.Uint64() + truncUint64 := softfloat.F32touint64(trunc) return truncUint64 >= 0 && truncUint64 <= math.MaxUint32 }) - x := tv.GetFloat32().Uint32() + x := uint32(softfloat.F32touint64(tv.GetFloat32())) tv.T = t tv.SetUint32(x) case Uint64Kind: validate(Float32Kind, Uint64Kind, func() bool { - trunc := tv.GetFloat32().Trunc() + trunc := softfloat.Ftrunc32(tv.GetFloat32()) - if !trunc.Eq(tv.GetFloat32()) { + if !softfloat.Feq32(trunc, tv.GetFloat32()) { return false } - truncUint64 := trunc.Uint64() + truncUint64 := softfloat.F32touint64(trunc) return truncUint64 >= 0 && truncUint64 <= math.MaxUint }) - x := tv.GetFloat32().Uint64() + x := softfloat.F32touint64(tv.GetFloat32()) tv.T = t tv.SetUint64(x) case Float32Kind: @@ -995,7 +996,7 @@ GNO_CASE: tv.T = t tv.SetFloat32(x) case Float64Kind: - x := tv.GetFloat32().SoftFloat64() /// ??? + x := softfloat.F32to64(tv.GetFloat32()) tv.T = t tv.SetFloat64(x) default: @@ -1007,156 +1008,156 @@ GNO_CASE: switch k { case IntKind: validate(Float64Kind, IntKind, func() bool { - trunc := tv.GetFloat64().Trunc() + trunc := softfloat.Ftrunc64(tv.GetFloat64()) - if !trunc.Eq(tv.GetFloat64()) { + if !softfloat.Feq64(trunc, tv.GetFloat64()) { return false } - truncInt64 := trunc.Int64() + truncInt64 := softfloat.F64toint64(trunc) return truncInt64 >= math.MinInt && truncInt64 <= math.MaxInt }) - x := tv.GetFloat64().Int() + xp, _ := softfloat.F64toint(tv.GetFloat64()) + x := int(xp) tv.T = t tv.SetInt(x) case Int8Kind: validate(Float64Kind, Int8Kind, func() bool { - trunc := tv.GetFloat64().Trunc() + trunc := softfloat.Ftrunc64(tv.GetFloat64()) - if !trunc.Eq(tv.GetFloat64()) { + if !softfloat.Feq64(trunc, tv.GetFloat64()) { return false } - truncInt64 := trunc.Int64() + truncInt64 := softfloat.F64toint64(trunc) return truncInt64 >= math.MinInt8 && truncInt64 <= math.MaxInt8 }) - x := tv.GetFloat64().Int8() + x := int8(softfloat.F64toint32(tv.GetFloat64())) tv.T = t tv.SetInt8(x) case Int16Kind: validate(Float64Kind, Int16Kind, func() bool { - trunc := tv.GetFloat64().Trunc() + trunc := softfloat.Ftrunc64(tv.GetFloat64()) - if !trunc.Eq(tv.GetFloat64()) { + if !softfloat.Feq64(trunc, tv.GetFloat64()) { return false } - truncInt64 := trunc.Int64() + truncInt64 := softfloat.F64toint64(trunc) return truncInt64 >= math.MinInt16 && truncInt64 <= math.MaxInt16 }) - x := tv.GetFloat64().Int16() + x := int16(softfloat.F64toint32(tv.GetFloat64())) tv.T = t tv.SetInt16(x) case Int32Kind: validate(Float64Kind, Int32Kind, func() bool { - trunc := tv.GetFloat64().Trunc() + trunc := softfloat.Ftrunc64(tv.GetFloat64()) - if !trunc.Eq(tv.GetFloat64()) { + if !softfloat.Feq64(trunc, tv.GetFloat64()) { return false } - truncInt64 := trunc.Int64() + truncInt64 := softfloat.F64toint64(trunc) return truncInt64 >= math.MinInt32 && truncInt64 <= math.MaxInt32 }) - x := tv.GetFloat64().Int32() + x := softfloat.F64toint32(tv.GetFloat64()) tv.T = t tv.SetInt32(x) case Int64Kind: validate(Float64Kind, Int64Kind, func() bool { - trunc := tv.GetFloat64().Trunc() + trunc := softfloat.Ftrunc64(tv.GetFloat64()) - return tv.GetFloat64().Eq(trunc) + return softfloat.Feq64(trunc, tv.GetFloat64()) }) - x := tv.GetFloat64().Int64() + x := softfloat.F64toint64(tv.GetFloat64()) tv.T = t tv.SetInt64(x) case UintKind: validate(Float64Kind, UintKind, func() bool { - trunc := tv.GetFloat64().Trunc() + trunc := softfloat.Ftrunc64(tv.GetFloat64()) - if !trunc.Eq(tv.GetFloat64()) { + if !softfloat.Feq64(trunc, tv.GetFloat64()) { return false } - truncUint64 := trunc.Uint64() + truncUint64 := softfloat.F64touint64(trunc) return truncUint64 >= 0 && truncUint64 <= math.MaxUint }) - x := tv.GetFloat64().Uint() + x := uint(softfloat.F64touint64(tv.GetFloat64())) tv.T = t tv.SetUint(x) case Uint8Kind: validate(Float64Kind, Uint8Kind, func() bool { - trunc := tv.GetFloat64().Trunc() + trunc := softfloat.Ftrunc64(tv.GetFloat64()) - if !trunc.Eq(tv.GetFloat64()) { + if !softfloat.Feq64(trunc, tv.GetFloat64()) { return false } - truncUint64 := trunc.Uint64() + truncUint64 := softfloat.F64touint64(trunc) return truncUint64 >= 0 && truncUint64 <= math.MaxUint8 }) - x := tv.GetFloat64().Uint8() + x := uint8(softfloat.F64touint64(tv.GetFloat64())) tv.T = t tv.SetUint8(x) case Uint16Kind: validate(Float64Kind, Uint16Kind, func() bool { - trunc := tv.GetFloat64().Trunc() + trunc := softfloat.Ftrunc64(tv.GetFloat64()) - if !trunc.Eq(tv.GetFloat64()) { + if !softfloat.Feq64(trunc, tv.GetFloat64()) { return false } - truncUint64 := trunc.Uint64() + truncUint64 := softfloat.F64touint64(trunc) return truncUint64 >= 0 && truncUint64 <= math.MaxUint16 }) - x := tv.GetFloat64().Uint16() + x := uint16(softfloat.F64touint64(tv.GetFloat64())) tv.T = t tv.SetUint16(x) case Uint32Kind: validate(Float64Kind, Uint32Kind, func() bool { - trunc := tv.GetFloat64().Trunc() - - if !trunc.Eq(tv.GetFloat64()) { + trunc := softfloat.Ftrunc64(tv.GetFloat64()) + if !softfloat.Feq64(trunc, tv.GetFloat64()) { return false } - truncUint64 := trunc.Uint64() + truncUint64 := softfloat.F64touint64(trunc) return truncUint64 >= 0 && truncUint64 <= math.MaxUint32 }) - x := tv.GetFloat64().Uint32() + x := uint32(softfloat.F64touint64(tv.GetFloat64())) tv.T = t tv.SetUint32(x) case Uint64Kind: validate(Float64Kind, Uint64Kind, func() bool { - trunc := tv.GetFloat64().Trunc() + trunc := softfloat.Ftrunc64(tv.GetFloat64()) - if !trunc.Eq(tv.GetFloat64()) { + if !softfloat.Feq64(tv.GetFloat64(), trunc) { return false } - truncUint64 := trunc.Uint64() + truncUint64 := softfloat.F64touint64(trunc) return truncUint64 >= 0 && truncUint64 <= math.MaxUint64 }) - x := tv.GetFloat64().Uint64() + x := softfloat.F64touint64(tv.GetFloat64()) tv.T = t tv.SetUint64(x) case Float32Kind: validate(Float64Kind, Float32Kind, func() bool { - return tv.GetFloat64().Le(SoftFloat64(math.Float64bits(float64(math.MaxFloat32)))) + return softfloat.Fle64(tv.GetFloat64(), math.Float64bits(float64(math.MaxFloat32))) }) - x := tv.GetFloat64().SoftFloat32() + x := softfloat.F64to32(tv.GetFloat64()) tv.T = t tv.SetFloat32(x) case Float64Kind: @@ -1480,7 +1481,7 @@ func ConvertUntypedBigintTo(dst *TypedValue, bv BigintValue, t Type) { if f32 == 0 && (acc == big.Below || acc == big.Above) { panic("bigint underflows float32 (too close to zero)") } - dst.SetFloat32(SoftFloat32(math.Float32bits(f32))) + dst.SetFloat32(math.Float32bits(f32)) return // done case Float64Kind: dst.T = t @@ -1494,7 +1495,7 @@ func ConvertUntypedBigintTo(dst *TypedValue, bv BigintValue, t Type) { if f64 == 0 && (acc == big.Below || acc == big.Above) { panic("bigint underflows float64 (too close to zero)") } - dst.SetFloat64(SoftFloat64(math.Float64bits(f64))) + dst.SetFloat64(math.Float64bits(f64)) return // done case BigdecKind: dst.T = t @@ -1609,7 +1610,7 @@ func ConvertUntypedBigdecTo(dst *TypedValue, bv BigdecValue, t Type) { dst.T = Float64Type dst.V = nil f, _ := bd.Float64() - dst.SetFloat64(SoftFloat64(math.Float64bits(f))) + dst.SetFloat64(math.Float64bits(f)) return case IntKind, Int8Kind, Int16Kind, Int32Kind, Int64Kind: fallthrough @@ -1635,7 +1636,7 @@ func ConvertUntypedBigdecTo(dst *TypedValue, bv BigdecValue, t Type) { if math.IsInf(float64(f32), 0) { panic("cannot convert untyped bigdec to float32 -- too close to +-Inf") } - dst.SetFloat32(SoftFloat32(math.Float32bits(f32))) + dst.SetFloat32(math.Float32bits(f32)) return case Float64Kind: dst.T = t @@ -1647,7 +1648,7 @@ func ConvertUntypedBigdecTo(dst *TypedValue, bv BigdecValue, t Type) { if math.IsInf(f64, 0) { panic("cannot convert untyped bigdec to float64 -- too close to +-Inf") } - dst.SetFloat64(SoftFloat64(math.Float64bits(f64))) + dst.SetFloat64(math.Float64bits(f64)) return default: panic(fmt.Sprintf( diff --git a/gnovm/pkg/gnolang/values_conversions_test.go b/gnovm/pkg/gnolang/values_conversions_test.go index 2899fabda3d..5538e973bdc 100644 --- a/gnovm/pkg/gnolang/values_conversions_test.go +++ b/gnovm/pkg/gnolang/values_conversions_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/cockroachdb/apd/v3" + "github.com/gnolang/gno/gnovm/pkg/gnolang/internal/softfloat" "github.com/stretchr/testify/require" ) @@ -24,7 +25,7 @@ func TestConvertUntypedBigdecToFloat(t *testing.T) { ConvertUntypedBigdecTo(dst, bd, typ) - require.Equal(t, ConvertToSoftFloat64(0), dst.GetFloat64()) + require.True(t, softfloat.Feq64(dst.GetFloat64(), 0)) } func TestBitShiftingOverflow(t *testing.T) { diff --git a/gnovm/pkg/gnolang/values_string.go b/gnovm/pkg/gnolang/values_string.go index a414f440e4e..fdf0c8f55de 100644 --- a/gnovm/pkg/gnolang/values_string.go +++ b/gnovm/pkg/gnolang/values_string.go @@ -2,6 +2,7 @@ package gnolang import ( "fmt" + "math" "reflect" "strconv" "strings" @@ -339,9 +340,9 @@ func (tv *TypedValue) ProtectedSprint(seen *seenValues, considerDeclaredType boo case Uint64Type: return fmt.Sprintf("%d", tv.GetUint64()) case Float32Type: - return fmt.Sprintf("%v", tv.GetFloat32()) + return fmt.Sprintf("%v", math.Float32frombits(tv.GetFloat32())) case Float64Type: - return fmt.Sprintf("%v", tv.GetFloat64()) + return fmt.Sprintf("%v", math.Float64frombits(tv.GetFloat64())) case UntypedBigintType, BigintType: return tv.V.(BigintValue).V.String() case UntypedBigdecType, BigdecType: @@ -447,9 +448,9 @@ func (tv TypedValue) ProtectedString(seen *seenValues) string { case Uint64Type: vs = fmt.Sprintf("%d", tv.GetUint64()) case Float32Type: - vs = fmt.Sprintf("%v", tv.GetFloat32()) + vs = fmt.Sprintf("%v", math.Float32frombits(tv.GetFloat32())) case Float64Type: - vs = fmt.Sprintf("%v", tv.GetFloat64()) + vs = fmt.Sprintf("%v", math.Float64frombits(tv.GetFloat64())) // Complex types that require recusion protection. default: vs = nilStr