From 266a2cb469ce63cfab6fadd5bcfe5f3e0d51d72f Mon Sep 17 00:00:00 2001 From: leohhhn Date: Tue, 27 Feb 2024 22:43:46 +0100 Subject: [PATCH 01/20] port over overflow --- gnovm/stdlibs/overflow/overflow.gno | 131 +++++++++ gnovm/stdlibs/overflow/overflow_impl.gno | 360 +++++++++++++++++++++++ gnovm/stdlibs/overflow/overflow_test.gno | 119 ++++++++ 3 files changed, 610 insertions(+) create mode 100644 gnovm/stdlibs/overflow/overflow.gno create mode 100644 gnovm/stdlibs/overflow/overflow_impl.gno create mode 100644 gnovm/stdlibs/overflow/overflow_test.gno diff --git a/gnovm/stdlibs/overflow/overflow.gno b/gnovm/stdlibs/overflow/overflow.gno new file mode 100644 index 00000000000..b476ea5776e --- /dev/null +++ b/gnovm/stdlibs/overflow/overflow.gno @@ -0,0 +1,131 @@ +/* +Package overflow offers overflow-checked integer arithmetic operations +for int, int32, and int64. Each of the operations returns a +result,bool combination. This was prompted by the need to know when +to flow into higher precision types from the math.big library. + +For instance, assuing a 64 bit machine: + +10 + 20 -> 30 +int(math.MaxInt64) + 1 -> -9223372036854775808 + +whereas + +overflow.Add(10,20) -> (30, true) +overflow.Add(math.MaxInt64,1) -> (0, false) + +Add, Sub, Mul, Div are for int. Add64, Add32, etc. are specifically sized. + +If anybody wishes an unsigned version, submit a pull request for code +and new tests. +*/ +package overflow + +//go:generate ./overflow_template.sh + +import "math" + +func _is64Bit() bool { + maxU32 := uint(math.MaxUint32) + return ((maxU32 << 1) >> 1) == maxU32 +} + +/********** PARTIAL TEST COVERAGE FROM HERE DOWN ************* + +The only way that I could see to do this is a combination of +my normal 64 bit system and a GopherJS running on Node. My +understanding is that its ints are 32 bit. + +So, FEEL FREE to carefully review the code visually. + +*************************************************************/ + +// Unspecified size, i.e. normal signed int + +// Add sums two ints, returning the result and a boolean status. +func Add(a, b int) (int, bool) { + if _is64Bit() { + r64, ok := Add64(int64(a), int64(b)) + return int(r64), ok + } + r32, ok := Add32(int32(a), int32(b)) + return int(r32), ok +} + +// Sub returns the difference of two ints and a boolean status. +func Sub(a, b int) (int, bool) { + if _is64Bit() { + r64, ok := Sub64(int64(a), int64(b)) + return int(r64), ok + } + r32, ok := Sub32(int32(a), int32(b)) + return int(r32), ok +} + +// Mul returns the product of two ints and a boolean status. +func Mul(a, b int) (int, bool) { + if _is64Bit() { + r64, ok := Mul64(int64(a), int64(b)) + return int(r64), ok + } + r32, ok := Mul32(int32(a), int32(b)) + return int(r32), ok +} + +// Div returns the quotient of two ints and a boolean status +func Div(a, b int) (int, bool) { + if _is64Bit() { + r64, ok := Div64(int64(a), int64(b)) + return int(r64), ok + } + r32, ok := Div32(int32(a), int32(b)) + return int(r32), ok +} + +// Quotient returns the quotient, remainder and status of two ints +func Quotient(a, b int) (int, int, bool) { + if _is64Bit() { + q64, r64, ok := Quotient64(int64(a), int64(b)) + return int(q64), int(r64), ok + } + q32, r32, ok := Quotient32(int32(a), int32(b)) + return int(q32), int(r32), ok +} + +/************* Panic versions for int ****************/ + +// Addp returns the sum of two ints, panicking on overflow +func Addp(a, b int) int { + r, ok := Add(a, b) + if !ok { + panic("addition overflow") + } + return r +} + +// Subp returns the difference of two ints, panicking on overflow. +func Subp(a, b int) int { + r, ok := Sub(a, b) + if !ok { + panic("subtraction overflow") + } + return r +} + +// Mulp returns the product of two ints, panicking on overflow. +func Mulp(a, b int) int { + r, ok := Mul(a, b) + if !ok { + panic("multiplication overflow") + } + return r +} + +// Divp returns the quotient of two ints, panicking on overflow. +func Divp(a, b int) int { + r, ok := Div(a, b) + if !ok { + panic("division failure") + } + return r +} diff --git a/gnovm/stdlibs/overflow/overflow_impl.gno b/gnovm/stdlibs/overflow/overflow_impl.gno new file mode 100644 index 00000000000..a9a90c43835 --- /dev/null +++ b/gnovm/stdlibs/overflow/overflow_impl.gno @@ -0,0 +1,360 @@ +package overflow + +// This is generated code, created by overflow_template.sh executed +// by "go generate" + +// Add8 performs + operation on two int8 operands +// returning a result and status +func Add8(a, b int8) (int8, bool) { + c := a + b + if (c > a) == (b > 0) { + return c, true + } + return c, false +} + +// Add8p is the unchecked panicing version of Add8 +func Add8p(a, b int8) int8 { + r, ok := Add8(a, b) + if !ok { + panic("addition overflow") + } + return r +} + +// Sub8 performs - operation on two int8 operands +// returning a result and status +func Sub8(a, b int8) (int8, bool) { + c := a - b + if (c < a) == (b > 0) { + return c, true + } + return c, false +} + +// Sub8p is the unchecked panicing version of Sub8 +func Sub8p(a, b int8) int8 { + r, ok := Sub8(a, b) + if !ok { + panic("subtraction overflow") + } + return r +} + +// Mul8 performs * operation on two int8 operands +// returning a result and status +func Mul8(a, b int8) (int8, bool) { + if a == 0 || b == 0 { + return 0, true + } + c := a * b + if (c < 0) == ((a < 0) != (b < 0)) { + if c/b == a { + return c, true + } + } + return c, false +} + +// Mul8p is the unchecked panicing version of Mul8 +func Mul8p(a, b int8) int8 { + r, ok := Mul8(a, b) + if !ok { + panic("multiplication overflow") + } + return r +} + +// Div8 performs / operation on two int8 operands +// returning a result and status +func Div8(a, b int8) (int8, bool) { + q, _, ok := Quotient8(a, b) + return q, ok +} + +// Div8p is the unchecked panicing version of Div8 +func Div8p(a, b int8) int8 { + r, ok := Div8(a, b) + if !ok { + panic("division failure") + } + return r +} + +// Quotient8 performs + operation on two int8 operands +// returning a quotient, a remainder and status +func Quotient8(a, b int8) (int8, int8, bool) { + if b == 0 { + return 0, 0, false + } + c := a / b + status := (c < 0) == ((a < 0) != (b < 0)) + return c, a % b, status +} + +// Add16 performs + operation on two int16 operands +// returning a result and status +func Add16(a, b int16) (int16, bool) { + c := a + b + if (c > a) == (b > 0) { + return c, true + } + return c, false +} + +// Add16p is the unchecked panicing version of Add16 +func Add16p(a, b int16) int16 { + r, ok := Add16(a, b) + if !ok { + panic("addition overflow") + } + return r +} + +// Sub16 performs - operation on two int16 operands +// returning a result and status +func Sub16(a, b int16) (int16, bool) { + c := a - b + if (c < a) == (b > 0) { + return c, true + } + return c, false +} + +// Sub16p is the unchecked panicing version of Sub16 +func Sub16p(a, b int16) int16 { + r, ok := Sub16(a, b) + if !ok { + panic("subtraction overflow") + } + return r +} + +// Mul16 performs * operation on two int16 operands +// returning a result and status +func Mul16(a, b int16) (int16, bool) { + if a == 0 || b == 0 { + return 0, true + } + c := a * b + if (c < 0) == ((a < 0) != (b < 0)) { + if c/b == a { + return c, true + } + } + return c, false +} + +// Mul16p is the unchecked panicing version of Mul16 +func Mul16p(a, b int16) int16 { + r, ok := Mul16(a, b) + if !ok { + panic("multiplication overflow") + } + return r +} + +// Div16 performs / operation on two int16 operands +// returning a result and status +func Div16(a, b int16) (int16, bool) { + q, _, ok := Quotient16(a, b) + return q, ok +} + +// Div16p is the unchecked panicing version of Div16 +func Div16p(a, b int16) int16 { + r, ok := Div16(a, b) + if !ok { + panic("division failure") + } + return r +} + +// Quotient16 performs + operation on two int16 operands +// returning a quotient, a remainder and status +func Quotient16(a, b int16) (int16, int16, bool) { + if b == 0 { + return 0, 0, false + } + c := a / b + status := (c < 0) == ((a < 0) != (b < 0)) + return c, a % b, status +} + +// Add32 performs + operation on two int32 operands +// returning a result and status +func Add32(a, b int32) (int32, bool) { + c := a + b + if (c > a) == (b > 0) { + return c, true + } + return c, false +} + +// Add32p is the unchecked panicing version of Add32 +func Add32p(a, b int32) int32 { + r, ok := Add32(a, b) + if !ok { + panic("addition overflow") + } + return r +} + +// Sub32 performs - operation on two int32 operands +// returning a result and status +func Sub32(a, b int32) (int32, bool) { + c := a - b + if (c < a) == (b > 0) { + return c, true + } + return c, false +} + +// Sub32p is the unchecked panicing version of Sub32 +func Sub32p(a, b int32) int32 { + r, ok := Sub32(a, b) + if !ok { + panic("subtraction overflow") + } + return r +} + +// Mul32 performs * operation on two int32 operands +// returning a result and status +func Mul32(a, b int32) (int32, bool) { + if a == 0 || b == 0 { + return 0, true + } + c := a * b + if (c < 0) == ((a < 0) != (b < 0)) { + if c/b == a { + return c, true + } + } + return c, false +} + +// Mul32p is the unchecked panicing version of Mul32 +func Mul32p(a, b int32) int32 { + r, ok := Mul32(a, b) + if !ok { + panic("multiplication overflow") + } + return r +} + +// Div32 performs / operation on two int32 operands +// returning a result and status +func Div32(a, b int32) (int32, bool) { + q, _, ok := Quotient32(a, b) + return q, ok +} + +// Div32p is the unchecked panicing version of Div32 +func Div32p(a, b int32) int32 { + r, ok := Div32(a, b) + if !ok { + panic("division failure") + } + return r +} + +// Quotient32 performs + operation on two int32 operands +// returning a quotient, a remainder and status +func Quotient32(a, b int32) (int32, int32, bool) { + if b == 0 { + return 0, 0, false + } + c := a / b + status := (c < 0) == ((a < 0) != (b < 0)) + return c, a % b, status +} + +// Add64 performs + operation on two int64 operands +// returning a result and status +func Add64(a, b int64) (int64, bool) { + c := a + b + if (c > a) == (b > 0) { + return c, true + } + return c, false +} + +// Add64p is the unchecked panicing version of Add64 +func Add64p(a, b int64) int64 { + r, ok := Add64(a, b) + if !ok { + panic("addition overflow") + } + return r +} + +// Sub64 performs - operation on two int64 operands +// returning a result and status +func Sub64(a, b int64) (int64, bool) { + c := a - b + if (c < a) == (b > 0) { + return c, true + } + return c, false +} + +// Sub64p is the unchecked panicing version of Sub64 +func Sub64p(a, b int64) int64 { + r, ok := Sub64(a, b) + if !ok { + panic("subtraction overflow") + } + return r +} + +// Mul64 performs * operation on two int64 operands +// returning a result and status +func Mul64(a, b int64) (int64, bool) { + if a == 0 || b == 0 { + return 0, true + } + c := a * b + if (c < 0) == ((a < 0) != (b < 0)) { + if c/b == a { + return c, true + } + } + return c, false +} + +// Mul64p is the unchecked panicing version of Mul64 +func Mul64p(a, b int64) int64 { + r, ok := Mul64(a, b) + if !ok { + panic("multiplication overflow") + } + return r +} + +// Div64 performs / operation on two int64 operands +// returning a result and status +func Div64(a, b int64) (int64, bool) { + q, _, ok := Quotient64(a, b) + return q, ok +} + +// Div64p is the unchecked panicing version of Div64 +func Div64p(a, b int64) int64 { + r, ok := Div64(a, b) + if !ok { + panic("division failure") + } + return r +} + +// Quotient64 performs + operation on two int64 operands +// returning a quotient, a remainder and status +func Quotient64(a, b int64) (int64, int64, bool) { + if b == 0 { + return 0, 0, false + } + c := a / b + status := (c < 0) == ((a < 0) != (b < 0)) + return c, a % b, status +} diff --git a/gnovm/stdlibs/overflow/overflow_test.gno b/gnovm/stdlibs/overflow/overflow_test.gno new file mode 100644 index 00000000000..419191d3697 --- /dev/null +++ b/gnovm/stdlibs/overflow/overflow_test.gno @@ -0,0 +1,119 @@ +package overflow + +import ( + "math" + "testing" +) +import "fmt" + +// sample all possibilities of 8 bit numbers +// by checking against 64 bit numbers + +func TestAlgorithms(t *testing.T) { + + errors := 0 + + for a64 := int64(math.MinInt8); a64 <= int64(math.MaxInt8); a64++ { + + for b64 := int64(math.MinInt8); b64 <= int64(math.MaxInt8) && errors < 10; b64++ { + + a8 := int8(a64) + b8 := int8(b64) + + if int64(a8) != a64 || int64(b8) != b64 { + t.Fatal("LOGIC FAILURE IN TEST") + } + + // ADDITION + { + r64 := a64 + b64 + + // now the verification + result, ok := Add8(a8, b8) + if ok && int64(result) != r64 { + t.Errorf("failed to fail on %v + %v = %v instead of %v\n", + a8, b8, result, r64) + errors++ + } + if !ok && int64(result) == r64 { + t.Fail() + errors++ + } + } + + // SUBTRACTION + { + r64 := a64 - b64 + + // now the verification + result, ok := Sub8(a8, b8) + if ok && int64(result) != r64 { + t.Errorf("failed to fail on %v - %v = %v instead of %v\n", + a8, b8, result, r64) + } + if !ok && int64(result) == r64 { + t.Fail() + errors++ + } + } + + // MULTIPLICATION + { + r64 := a64 * b64 + + // now the verification + result, ok := Mul8(a8, b8) + if ok && int64(result) != r64 { + t.Errorf("failed to fail on %v * %v = %v instead of %v\n", + a8, b8, result, r64) + errors++ + } + if !ok && int64(result) == r64 { + t.Fail() + errors++ + } + } + + // DIVISION + if b8 != 0 { + r64 := a64 / b64 + + // now the verification + result, _, ok := Quotient8(a8, b8) + if ok && int64(result) != r64 { + t.Errorf("failed to fail on %v / %v = %v instead of %v\n", + a8, b8, result, r64) + errors++ + } + if !ok && result != 0 && int64(result) == r64 { + t.Fail() + errors++ + } + } + } + } + +} + +func TestQuotient(t *testing.T) { + q, r, ok := Quotient(100, 3) + if r != 1 || q != 33 || !ok { + t.Errorf("expected 100/3 => 33, r=1") + } + if _, _, ok = Quotient(1, 0); ok { + t.Error("unexpected lack of failure") + } +} + +//func TestAdditionInt(t *testing.T) { +// fmt.Printf("\nminint8 = %v\n", math.MinInt8) +// fmt.Printf("maxint8 = %v\n\n", math.MaxInt8) +// fmt.Printf("maxint32 = %v\n", math.MaxInt32) +// fmt.Printf("minint32 = %v\n\n", math.MinInt32) +// fmt.Printf("maxint64 = %v\n", math.MaxInt64) +// fmt.Printf("minint64 = %v\n\n", math.MinInt64) +//} + +func Test64(t *testing.T) { + fmt.Println("64bit:", _is64Bit()) +} From b9ca46a304ac388e731f75a98d76586f5abb6d7a Mon Sep 17 00:00:00 2001 From: leohhhn Date: Tue, 27 Feb 2024 23:23:41 +0100 Subject: [PATCH 02/20] make fmt --- gnovm/stdlibs/overflow/overflow_test.gno | 3 --- 1 file changed, 3 deletions(-) diff --git a/gnovm/stdlibs/overflow/overflow_test.gno b/gnovm/stdlibs/overflow/overflow_test.gno index 419191d3697..c57be9d0a6a 100644 --- a/gnovm/stdlibs/overflow/overflow_test.gno +++ b/gnovm/stdlibs/overflow/overflow_test.gno @@ -10,11 +10,9 @@ import "fmt" // by checking against 64 bit numbers func TestAlgorithms(t *testing.T) { - errors := 0 for a64 := int64(math.MinInt8); a64 <= int64(math.MaxInt8); a64++ { - for b64 := int64(math.MinInt8); b64 <= int64(math.MaxInt8) && errors < 10; b64++ { a8 := int8(a64) @@ -92,7 +90,6 @@ func TestAlgorithms(t *testing.T) { } } } - } func TestQuotient(t *testing.T) { From 6b1e9f0b3c17c4c0b47bf9bc8832570bd30bba27 Mon Sep 17 00:00:00 2001 From: leohhhn Date: Tue, 27 Feb 2024 23:25:48 +0100 Subject: [PATCH 03/20] move overflow to math/overflow --- gnovm/stdlibs/{overflow => math}/overflow.gno | 2 +- gnovm/stdlibs/{overflow => math}/overflow_impl.gno | 2 +- gnovm/stdlibs/{overflow => math}/overflow_test.gno | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) rename gnovm/stdlibs/{overflow => math}/overflow.gno (99%) rename gnovm/stdlibs/{overflow => math}/overflow_impl.gno (99%) rename gnovm/stdlibs/{overflow => math}/overflow_test.gno (99%) diff --git a/gnovm/stdlibs/overflow/overflow.gno b/gnovm/stdlibs/math/overflow.gno similarity index 99% rename from gnovm/stdlibs/overflow/overflow.gno rename to gnovm/stdlibs/math/overflow.gno index b476ea5776e..cbda1ccd0ae 100644 --- a/gnovm/stdlibs/overflow/overflow.gno +++ b/gnovm/stdlibs/math/overflow.gno @@ -19,7 +19,7 @@ Add, Sub, Mul, Div are for int. Add64, Add32, etc. are specifically sized. If anybody wishes an unsigned version, submit a pull request for code and new tests. */ -package overflow +package math //go:generate ./overflow_template.sh diff --git a/gnovm/stdlibs/overflow/overflow_impl.gno b/gnovm/stdlibs/math/overflow_impl.gno similarity index 99% rename from gnovm/stdlibs/overflow/overflow_impl.gno rename to gnovm/stdlibs/math/overflow_impl.gno index a9a90c43835..2402ed004a0 100644 --- a/gnovm/stdlibs/overflow/overflow_impl.gno +++ b/gnovm/stdlibs/math/overflow_impl.gno @@ -1,4 +1,4 @@ -package overflow +package math // This is generated code, created by overflow_template.sh executed // by "go generate" diff --git a/gnovm/stdlibs/overflow/overflow_test.gno b/gnovm/stdlibs/math/overflow_test.gno similarity index 99% rename from gnovm/stdlibs/overflow/overflow_test.gno rename to gnovm/stdlibs/math/overflow_test.gno index c57be9d0a6a..69a3fccf98b 100644 --- a/gnovm/stdlibs/overflow/overflow_test.gno +++ b/gnovm/stdlibs/math/overflow_test.gno @@ -1,4 +1,4 @@ -package overflow +package math import ( "math" From f734acb658efda68c0ea627ed11210f2e39804c2 Mon Sep 17 00:00:00 2001 From: leohhhn Date: Tue, 27 Feb 2024 23:31:49 +0100 Subject: [PATCH 04/20] fix tests? --- gnovm/stdlibs/math/overflow.gno | 4 +--- gnovm/stdlibs/math/overflow_test.gno | 16 +--------------- 2 files changed, 2 insertions(+), 18 deletions(-) diff --git a/gnovm/stdlibs/math/overflow.gno b/gnovm/stdlibs/math/overflow.gno index cbda1ccd0ae..5d2c3ca1d1b 100644 --- a/gnovm/stdlibs/math/overflow.gno +++ b/gnovm/stdlibs/math/overflow.gno @@ -23,10 +23,8 @@ package math //go:generate ./overflow_template.sh -import "math" - func _is64Bit() bool { - maxU32 := uint(math.MaxUint32) + maxU32 := uint(MaxUint32) return ((maxU32 << 1) >> 1) == maxU32 } diff --git a/gnovm/stdlibs/math/overflow_test.gno b/gnovm/stdlibs/math/overflow_test.gno index 69a3fccf98b..727ade5ec48 100644 --- a/gnovm/stdlibs/math/overflow_test.gno +++ b/gnovm/stdlibs/math/overflow_test.gno @@ -1,10 +1,9 @@ -package math +package math_test import ( "math" "testing" ) -import "fmt" // sample all possibilities of 8 bit numbers // by checking against 64 bit numbers @@ -101,16 +100,3 @@ func TestQuotient(t *testing.T) { t.Error("unexpected lack of failure") } } - -//func TestAdditionInt(t *testing.T) { -// fmt.Printf("\nminint8 = %v\n", math.MinInt8) -// fmt.Printf("maxint8 = %v\n\n", math.MaxInt8) -// fmt.Printf("maxint32 = %v\n", math.MaxInt32) -// fmt.Printf("minint32 = %v\n\n", math.MinInt32) -// fmt.Printf("maxint64 = %v\n", math.MaxInt64) -// fmt.Printf("minint64 = %v\n\n", math.MinInt64) -//} - -func Test64(t *testing.T) { - fmt.Println("64bit:", _is64Bit()) -} From 9e15e6a05ebfccfe4cb00f72b7d0b65cf83f3e81 Mon Sep 17 00:00:00 2001 From: leohhhn Date: Tue, 27 Feb 2024 23:52:09 +0100 Subject: [PATCH 05/20] port from examples/ --- gnovm/stdlibs/math/overflow.gno | 129 ----------- .../overflow.gno} | 214 +++++++++++++++--- .../math/{ => overflow}/overflow_test.gno | 8 +- 3 files changed, 181 insertions(+), 170 deletions(-) delete mode 100644 gnovm/stdlibs/math/overflow.gno rename gnovm/stdlibs/math/{overflow_impl.gno => overflow/overflow.gno} (51%) rename gnovm/stdlibs/math/{ => overflow}/overflow_test.gno (93%) diff --git a/gnovm/stdlibs/math/overflow.gno b/gnovm/stdlibs/math/overflow.gno deleted file mode 100644 index 5d2c3ca1d1b..00000000000 --- a/gnovm/stdlibs/math/overflow.gno +++ /dev/null @@ -1,129 +0,0 @@ -/* -Package overflow offers overflow-checked integer arithmetic operations -for int, int32, and int64. Each of the operations returns a -result,bool combination. This was prompted by the need to know when -to flow into higher precision types from the math.big library. - -For instance, assuing a 64 bit machine: - -10 + 20 -> 30 -int(math.MaxInt64) + 1 -> -9223372036854775808 - -whereas - -overflow.Add(10,20) -> (30, true) -overflow.Add(math.MaxInt64,1) -> (0, false) - -Add, Sub, Mul, Div are for int. Add64, Add32, etc. are specifically sized. - -If anybody wishes an unsigned version, submit a pull request for code -and new tests. -*/ -package math - -//go:generate ./overflow_template.sh - -func _is64Bit() bool { - maxU32 := uint(MaxUint32) - return ((maxU32 << 1) >> 1) == maxU32 -} - -/********** PARTIAL TEST COVERAGE FROM HERE DOWN ************* - -The only way that I could see to do this is a combination of -my normal 64 bit system and a GopherJS running on Node. My -understanding is that its ints are 32 bit. - -So, FEEL FREE to carefully review the code visually. - -*************************************************************/ - -// Unspecified size, i.e. normal signed int - -// Add sums two ints, returning the result and a boolean status. -func Add(a, b int) (int, bool) { - if _is64Bit() { - r64, ok := Add64(int64(a), int64(b)) - return int(r64), ok - } - r32, ok := Add32(int32(a), int32(b)) - return int(r32), ok -} - -// Sub returns the difference of two ints and a boolean status. -func Sub(a, b int) (int, bool) { - if _is64Bit() { - r64, ok := Sub64(int64(a), int64(b)) - return int(r64), ok - } - r32, ok := Sub32(int32(a), int32(b)) - return int(r32), ok -} - -// Mul returns the product of two ints and a boolean status. -func Mul(a, b int) (int, bool) { - if _is64Bit() { - r64, ok := Mul64(int64(a), int64(b)) - return int(r64), ok - } - r32, ok := Mul32(int32(a), int32(b)) - return int(r32), ok -} - -// Div returns the quotient of two ints and a boolean status -func Div(a, b int) (int, bool) { - if _is64Bit() { - r64, ok := Div64(int64(a), int64(b)) - return int(r64), ok - } - r32, ok := Div32(int32(a), int32(b)) - return int(r32), ok -} - -// Quotient returns the quotient, remainder and status of two ints -func Quotient(a, b int) (int, int, bool) { - if _is64Bit() { - q64, r64, ok := Quotient64(int64(a), int64(b)) - return int(q64), int(r64), ok - } - q32, r32, ok := Quotient32(int32(a), int32(b)) - return int(q32), int(r32), ok -} - -/************* Panic versions for int ****************/ - -// Addp returns the sum of two ints, panicking on overflow -func Addp(a, b int) int { - r, ok := Add(a, b) - if !ok { - panic("addition overflow") - } - return r -} - -// Subp returns the difference of two ints, panicking on overflow. -func Subp(a, b int) int { - r, ok := Sub(a, b) - if !ok { - panic("subtraction overflow") - } - return r -} - -// Mulp returns the product of two ints, panicking on overflow. -func Mulp(a, b int) int { - r, ok := Mul(a, b) - if !ok { - panic("multiplication overflow") - } - return r -} - -// Divp returns the quotient of two ints, panicking on overflow. -func Divp(a, b int) int { - r, ok := Div(a, b) - if !ok { - panic("division failure") - } - return r -} diff --git a/gnovm/stdlibs/math/overflow_impl.gno b/gnovm/stdlibs/math/overflow/overflow.gno similarity index 51% rename from gnovm/stdlibs/math/overflow_impl.gno rename to gnovm/stdlibs/math/overflow/overflow.gno index 2402ed004a0..dde2c764dec 100644 --- a/gnovm/stdlibs/math/overflow_impl.gno +++ b/gnovm/stdlibs/math/overflow/overflow.gno @@ -1,5 +1,141 @@ -package math +// This is modified from https://github.com/JohnCGriffin/overflow (MIT). +// NOTE: there was a bug with the original Quotient* functions, and +// testing method. These have been fixed here, and tests ported to +// tests/files/maths_int*.go respectively. +// Note: copied over from p/demo/maths & deprecated over there. +package overflow +import "math" + +/* +Package overflow offers overflow-checked integer arithmetic operations +for int, int32, and int64. Each of the operations returns a +result,bool combination. This was prompted by the need to know when +to flow into higher precision types from the math.big library. + +For instance, assuing a 64 bit machine: + +10 + 20 -> 30 +int(math.MaxInt64) + 1 -> -9223372036854775808 + +whereas + +overflow.Add(10,20) -> (30, true) +overflow.Add(math.MaxInt64,1) -> (0, false) + +Add, Sub, Mul, Div are for int. Add64, Add32, etc. are specifically sized. + +If anybody wishes an unsigned version, submit a pull request for code +and new tests. */ + +//go:generate ./overflow_template.sh + +func _is64Bit() bool { + maxU32 := uint(math.MaxUint32) + return ((maxU32 << 1) >> 1) == maxU32 +} + +/********** PARTIAL TEST COVERAGE FROM HERE DOWN ************* + +The only way that I could see to do this is a combination of +my normal 64 bit system and a GopherJS running on Node. My +understanding is that its ints are 32 bit. + +So, FEEL FREE to carefully review the code visually. + +*************************************************************/ + +// Unspecified size, i.e. normal signed int + +// Add sums two ints, returning the result and a boolean status. +func Add(a, b int) (int, bool) { + if _is64Bit() { + r64, ok := Add64(int64(a), int64(b)) + return int(r64), ok + } + r32, ok := Add32(int32(a), int32(b)) + return int(r32), ok +} + +// Sub returns the difference of two ints and a boolean status. +func Sub(a, b int) (int, bool) { + if _is64Bit() { + r64, ok := Sub64(int64(a), int64(b)) + return int(r64), ok + } + r32, ok := Sub32(int32(a), int32(b)) + return int(r32), ok +} + +// Mul returns the product of two ints and a boolean status. +func Mul(a, b int) (int, bool) { + if _is64Bit() { + r64, ok := Mul64(int64(a), int64(b)) + return int(r64), ok + } + r32, ok := Mul32(int32(a), int32(b)) + return int(r32), ok +} + +// Div returns the quotient of two ints and a boolean status +func Div(a, b int) (int, bool) { + if _is64Bit() { + r64, ok := Div64(int64(a), int64(b)) + return int(r64), ok + } + r32, ok := Div32(int32(a), int32(b)) + return int(r32), ok +} + +// Quo returns the quotient, remainder and status of two ints +func Quo(a, b int) (int, int, bool) { + if _is64Bit() { + q64, r64, ok := Quo64(int64(a), int64(b)) + return int(q64), int(r64), ok + } + q32, r32, ok := Quo32(int32(a), int32(b)) + return int(q32), int(r32), ok +} + +/************* Panic versions for int ****************/ + +// Addp returns the sum of two ints, panicking on overflow +func Addp(a, b int) int { + r, ok := Add(a, b) + if !ok { + panic("addition overflow") + } + return r +} + +// Subp returns the difference of two ints, panicking on overflow. +func Subp(a, b int) int { + r, ok := Sub(a, b) + if !ok { + panic("subtraction overflow") + } + return r +} + +// Mulp returns the product of two ints, panicking on overflow. +func Mulp(a, b int) int { + r, ok := Mul(a, b) + if !ok { + panic("multiplication overflow") + } + return r +} + +// Divp returns the quotient of two ints, panicking on overflow. +func Divp(a, b int) int { + r, ok := Div(a, b) + if !ok { + panic("division failure") + } + return r +} + +//---------------------------------------- // This is generated code, created by overflow_template.sh executed // by "go generate" @@ -13,7 +149,7 @@ func Add8(a, b int8) (int8, bool) { return c, false } -// Add8p is the unchecked panicing version of Add8 +// Add8p is the unchecked panicking version of Add8 func Add8p(a, b int8) int8 { r, ok := Add8(a, b) if !ok { @@ -32,7 +168,7 @@ func Sub8(a, b int8) (int8, bool) { return c, false } -// Sub8p is the unchecked panicing version of Sub8 +// Sub8p is the unchecked panicking version of Sub8 func Sub8p(a, b int8) int8 { r, ok := Sub8(a, b) if !ok { @@ -56,7 +192,7 @@ func Mul8(a, b int8) (int8, bool) { return c, false } -// Mul8p is the unchecked panicing version of Mul8 +// Mul8p is the unchecked panicking version of Mul8 func Mul8p(a, b int8) int8 { r, ok := Mul8(a, b) if !ok { @@ -68,11 +204,11 @@ func Mul8p(a, b int8) int8 { // Div8 performs / operation on two int8 operands // returning a result and status func Div8(a, b int8) (int8, bool) { - q, _, ok := Quotient8(a, b) + q, _, ok := Quo8(a, b) return q, ok } -// Div8p is the unchecked panicing version of Div8 +// Div8p is the unchecked panicking version of Div8 func Div8p(a, b int8) int8 { r, ok := Div8(a, b) if !ok { @@ -81,15 +217,16 @@ func Div8p(a, b int8) int8 { return r } -// Quotient8 performs + operation on two int8 operands +// Quo8 performs + operation on two int8 operands // returning a quotient, a remainder and status -func Quotient8(a, b int8) (int8, int8, bool) { +func Quo8(a, b int8) (int8, int8, bool) { if b == 0 { return 0, 0, false + } else if b == -1 && a == math.MinInt8 { + return 0, 0, false } c := a / b - status := (c < 0) == ((a < 0) != (b < 0)) - return c, a % b, status + return c, a % b, true } // Add16 performs + operation on two int16 operands @@ -102,7 +239,7 @@ func Add16(a, b int16) (int16, bool) { return c, false } -// Add16p is the unchecked panicing version of Add16 +// Add16p is the unchecked panicking version of Add16 func Add16p(a, b int16) int16 { r, ok := Add16(a, b) if !ok { @@ -121,7 +258,7 @@ func Sub16(a, b int16) (int16, bool) { return c, false } -// Sub16p is the unchecked panicing version of Sub16 +// Sub16p is the unchecked panicking version of Sub16 func Sub16p(a, b int16) int16 { r, ok := Sub16(a, b) if !ok { @@ -145,7 +282,7 @@ func Mul16(a, b int16) (int16, bool) { return c, false } -// Mul16p is the unchecked panicing version of Mul16 +// Mul16p is the unchecked panicking version of Mul16 func Mul16p(a, b int16) int16 { r, ok := Mul16(a, b) if !ok { @@ -157,11 +294,11 @@ func Mul16p(a, b int16) int16 { // Div16 performs / operation on two int16 operands // returning a result and status func Div16(a, b int16) (int16, bool) { - q, _, ok := Quotient16(a, b) + q, _, ok := Quo16(a, b) return q, ok } -// Div16p is the unchecked panicing version of Div16 +// Div16p is the unchecked panicking version of Div16 func Div16p(a, b int16) int16 { r, ok := Div16(a, b) if !ok { @@ -170,15 +307,16 @@ func Div16p(a, b int16) int16 { return r } -// Quotient16 performs + operation on two int16 operands +// Quo16 performs + operation on two int16 operands // returning a quotient, a remainder and status -func Quotient16(a, b int16) (int16, int16, bool) { +func Quo16(a, b int16) (int16, int16, bool) { if b == 0 { return 0, 0, false + } else if b == -1 && a == math.MinInt16 { + return 0, 0, false } c := a / b - status := (c < 0) == ((a < 0) != (b < 0)) - return c, a % b, status + return c, a % b, true } // Add32 performs + operation on two int32 operands @@ -191,7 +329,7 @@ func Add32(a, b int32) (int32, bool) { return c, false } -// Add32p is the unchecked panicing version of Add32 +// Add32p is the unchecked panicking version of Add32 func Add32p(a, b int32) int32 { r, ok := Add32(a, b) if !ok { @@ -210,7 +348,7 @@ func Sub32(a, b int32) (int32, bool) { return c, false } -// Sub32p is the unchecked panicing version of Sub32 +// Sub32p is the unchecked panicking version of Sub32 func Sub32p(a, b int32) int32 { r, ok := Sub32(a, b) if !ok { @@ -234,7 +372,7 @@ func Mul32(a, b int32) (int32, bool) { return c, false } -// Mul32p is the unchecked panicing version of Mul32 +// Mul32p is the unchecked panicking version of Mul32 func Mul32p(a, b int32) int32 { r, ok := Mul32(a, b) if !ok { @@ -246,11 +384,11 @@ func Mul32p(a, b int32) int32 { // Div32 performs / operation on two int32 operands // returning a result and status func Div32(a, b int32) (int32, bool) { - q, _, ok := Quotient32(a, b) + q, _, ok := Quo32(a, b) return q, ok } -// Div32p is the unchecked panicing version of Div32 +// Div32p is the unchecked panicking version of Div32 func Div32p(a, b int32) int32 { r, ok := Div32(a, b) if !ok { @@ -259,15 +397,16 @@ func Div32p(a, b int32) int32 { return r } -// Quotient32 performs + operation on two int32 operands +// Quo32 performs + operation on two int32 operands // returning a quotient, a remainder and status -func Quotient32(a, b int32) (int32, int32, bool) { +func Quo32(a, b int32) (int32, int32, bool) { if b == 0 { return 0, 0, false + } else if b == -1 && a == math.MinInt32 { + return 0, 0, false } c := a / b - status := (c < 0) == ((a < 0) != (b < 0)) - return c, a % b, status + return c, a % b, true } // Add64 performs + operation on two int64 operands @@ -280,7 +419,7 @@ func Add64(a, b int64) (int64, bool) { return c, false } -// Add64p is the unchecked panicing version of Add64 +// Add64p is the unchecked panicking version of Add64 func Add64p(a, b int64) int64 { r, ok := Add64(a, b) if !ok { @@ -299,7 +438,7 @@ func Sub64(a, b int64) (int64, bool) { return c, false } -// Sub64p is the unchecked panicing version of Sub64 +// Sub64p is the unchecked panicking version of Sub64 func Sub64p(a, b int64) int64 { r, ok := Sub64(a, b) if !ok { @@ -323,7 +462,7 @@ func Mul64(a, b int64) (int64, bool) { return c, false } -// Mul64p is the unchecked panicing version of Mul64 +// Mul64p is the unchecked panicking version of Mul64 func Mul64p(a, b int64) int64 { r, ok := Mul64(a, b) if !ok { @@ -335,11 +474,11 @@ func Mul64p(a, b int64) int64 { // Div64 performs / operation on two int64 operands // returning a result and status func Div64(a, b int64) (int64, bool) { - q, _, ok := Quotient64(a, b) + q, _, ok := Quo64(a, b) return q, ok } -// Div64p is the unchecked panicing version of Div64 +// Div64p is the unchecked panicking version of Div64 func Div64p(a, b int64) int64 { r, ok := Div64(a, b) if !ok { @@ -348,13 +487,14 @@ func Div64p(a, b int64) int64 { return r } -// Quotient64 performs + operation on two int64 operands +// Quo64 performs + operation on two int64 operands // returning a quotient, a remainder and status -func Quotient64(a, b int64) (int64, int64, bool) { +func Quo64(a, b int64) (int64, int64, bool) { if b == 0 { return 0, 0, false + } else if b == -1 && a == math.MinInt64 { + return 0, 0, false } c := a / b - status := (c < 0) == ((a < 0) != (b < 0)) - return c, a % b, status + return c, a % b, true } diff --git a/gnovm/stdlibs/math/overflow_test.gno b/gnovm/stdlibs/math/overflow/overflow_test.gno similarity index 93% rename from gnovm/stdlibs/math/overflow_test.gno rename to gnovm/stdlibs/math/overflow/overflow_test.gno index 727ade5ec48..6c3e584a2d6 100644 --- a/gnovm/stdlibs/math/overflow_test.gno +++ b/gnovm/stdlibs/math/overflow/overflow_test.gno @@ -1,4 +1,4 @@ -package math_test +package overflow import ( "math" @@ -76,7 +76,7 @@ func TestAlgorithms(t *testing.T) { r64 := a64 / b64 // now the verification - result, _, ok := Quotient8(a8, b8) + result, _, ok := Quo8(a8, b8) if ok && int64(result) != r64 { t.Errorf("failed to fail on %v / %v = %v instead of %v\n", a8, b8, result, r64) @@ -92,11 +92,11 @@ func TestAlgorithms(t *testing.T) { } func TestQuotient(t *testing.T) { - q, r, ok := Quotient(100, 3) + q, r, ok := Quo(100, 3) if r != 1 || q != 33 || !ok { t.Errorf("expected 100/3 => 33, r=1") } - if _, _, ok = Quotient(1, 0); ok { + if _, _, ok = Quo(1, 0); ok { t.Error("unexpected lack of failure") } } From ad63184f2c6baa18555a00fdd887315454581ad3 Mon Sep 17 00:00:00 2001 From: leohhhn Date: Tue, 27 Feb 2024 23:52:43 +0100 Subject: [PATCH 06/20] remove examples/.../maths/overflow.gno --- examples/gno.land/p/demo/maths/overflow.gno | 498 -------------------- 1 file changed, 498 deletions(-) delete mode 100644 examples/gno.land/p/demo/maths/overflow.gno diff --git a/examples/gno.land/p/demo/maths/overflow.gno b/examples/gno.land/p/demo/maths/overflow.gno deleted file mode 100644 index f88f8014da2..00000000000 --- a/examples/gno.land/p/demo/maths/overflow.gno +++ /dev/null @@ -1,498 +0,0 @@ -// This is modified from https://github.com/JohnCGriffin/overflow (MIT). -// NOTE: there was a bug with the original Quotient* functions, and -// testing method. These have been fixed here, and tests ported to -// tests/files/maths_int*.go respectively. -// TODO: make PR upstream. -package maths - -/* -Package overflow offers overflow-checked integer arithmetic operations -for int, int32, and int64. Each of the operations returns a -result,bool combination. This was prompted by the need to know when -to flow into higher precision types from the math.big library. - -For instance, assuing a 64 bit machine: - -10 + 20 -> 30 -int(math.MaxInt64) + 1 -> -9223372036854775808 - -whereas - -overflow.Add(10,20) -> (30, true) -overflow.Add(math.MaxInt64,1) -> (0, false) - -Add, Sub, Mul, Div are for int. Add64, Add32, etc. are specifically sized. - -If anybody wishes an unsigned version, submit a pull request for code -and new tests. */ - -//go:generate ./overflow_template.sh - -func _is64Bit() bool { - maxU32 := uint(MaxUint32) - return ((maxU32 << 1) >> 1) == maxU32 -} - -/********** PARTIAL TEST COVERAGE FROM HERE DOWN ************* - -The only way that I could see to do this is a combination of -my normal 64 bit system and a GopherJS running on Node. My -understanding is that its ints are 32 bit. - -So, FEEL FREE to carefully review the code visually. - -*************************************************************/ - -// Unspecified size, i.e. normal signed int - -// Add sums two ints, returning the result and a boolean status. -func Add(a, b int) (int, bool) { - if _is64Bit() { - r64, ok := Add64(int64(a), int64(b)) - return int(r64), ok - } - r32, ok := Add32(int32(a), int32(b)) - return int(r32), ok -} - -// Sub returns the difference of two ints and a boolean status. -func Sub(a, b int) (int, bool) { - if _is64Bit() { - r64, ok := Sub64(int64(a), int64(b)) - return int(r64), ok - } - r32, ok := Sub32(int32(a), int32(b)) - return int(r32), ok -} - -// Mul returns the product of two ints and a boolean status. -func Mul(a, b int) (int, bool) { - if _is64Bit() { - r64, ok := Mul64(int64(a), int64(b)) - return int(r64), ok - } - r32, ok := Mul32(int32(a), int32(b)) - return int(r32), ok -} - -// Div returns the quotient of two ints and a boolean status -func Div(a, b int) (int, bool) { - if _is64Bit() { - r64, ok := Div64(int64(a), int64(b)) - return int(r64), ok - } - r32, ok := Div32(int32(a), int32(b)) - return int(r32), ok -} - -// Quo returns the quotient, remainder and status of two ints -func Quo(a, b int) (int, int, bool) { - if _is64Bit() { - q64, r64, ok := Quo64(int64(a), int64(b)) - return int(q64), int(r64), ok - } - q32, r32, ok := Quo32(int32(a), int32(b)) - return int(q32), int(r32), ok -} - -/************* Panic versions for int ****************/ - -// Addp returns the sum of two ints, panicking on overflow -func Addp(a, b int) int { - r, ok := Add(a, b) - if !ok { - panic("addition overflow") - } - return r -} - -// Subp returns the difference of two ints, panicking on overflow. -func Subp(a, b int) int { - r, ok := Sub(a, b) - if !ok { - panic("subtraction overflow") - } - return r -} - -// Mulp returns the product of two ints, panicking on overflow. -func Mulp(a, b int) int { - r, ok := Mul(a, b) - if !ok { - panic("multiplication overflow") - } - return r -} - -// Divp returns the quotient of two ints, panicking on overflow. -func Divp(a, b int) int { - r, ok := Div(a, b) - if !ok { - panic("division failure") - } - return r -} - -//---------------------------------------- -// This is generated code, created by overflow_template.sh executed -// by "go generate" - -// Add8 performs + operation on two int8 operands -// returning a result and status -func Add8(a, b int8) (int8, bool) { - c := a + b - if (c > a) == (b > 0) { - return c, true - } - return c, false -} - -// Add8p is the unchecked panicking version of Add8 -func Add8p(a, b int8) int8 { - r, ok := Add8(a, b) - if !ok { - panic("addition overflow") - } - return r -} - -// Sub8 performs - operation on two int8 operands -// returning a result and status -func Sub8(a, b int8) (int8, bool) { - c := a - b - if (c < a) == (b > 0) { - return c, true - } - return c, false -} - -// Sub8p is the unchecked panicking version of Sub8 -func Sub8p(a, b int8) int8 { - r, ok := Sub8(a, b) - if !ok { - panic("subtraction overflow") - } - return r -} - -// Mul8 performs * operation on two int8 operands -// returning a result and status -func Mul8(a, b int8) (int8, bool) { - if a == 0 || b == 0 { - return 0, true - } - c := a * b - if (c < 0) == ((a < 0) != (b < 0)) { - if c/b == a { - return c, true - } - } - return c, false -} - -// Mul8p is the unchecked panicking version of Mul8 -func Mul8p(a, b int8) int8 { - r, ok := Mul8(a, b) - if !ok { - panic("multiplication overflow") - } - return r -} - -// Div8 performs / operation on two int8 operands -// returning a result and status -func Div8(a, b int8) (int8, bool) { - q, _, ok := Quo8(a, b) - return q, ok -} - -// Div8p is the unchecked panicking version of Div8 -func Div8p(a, b int8) int8 { - r, ok := Div8(a, b) - if !ok { - panic("division failure") - } - return r -} - -// Quo8 performs + operation on two int8 operands -// returning a quotient, a remainder and status -func Quo8(a, b int8) (int8, int8, bool) { - if b == 0 { - return 0, 0, false - } else if b == -1 && a == MinInt8 { - return 0, 0, false - } - c := a / b - return c, a % b, true -} - -// Add16 performs + operation on two int16 operands -// returning a result and status -func Add16(a, b int16) (int16, bool) { - c := a + b - if (c > a) == (b > 0) { - return c, true - } - return c, false -} - -// Add16p is the unchecked panicking version of Add16 -func Add16p(a, b int16) int16 { - r, ok := Add16(a, b) - if !ok { - panic("addition overflow") - } - return r -} - -// Sub16 performs - operation on two int16 operands -// returning a result and status -func Sub16(a, b int16) (int16, bool) { - c := a - b - if (c < a) == (b > 0) { - return c, true - } - return c, false -} - -// Sub16p is the unchecked panicking version of Sub16 -func Sub16p(a, b int16) int16 { - r, ok := Sub16(a, b) - if !ok { - panic("subtraction overflow") - } - return r -} - -// Mul16 performs * operation on two int16 operands -// returning a result and status -func Mul16(a, b int16) (int16, bool) { - if a == 0 || b == 0 { - return 0, true - } - c := a * b - if (c < 0) == ((a < 0) != (b < 0)) { - if c/b == a { - return c, true - } - } - return c, false -} - -// Mul16p is the unchecked panicking version of Mul16 -func Mul16p(a, b int16) int16 { - r, ok := Mul16(a, b) - if !ok { - panic("multiplication overflow") - } - return r -} - -// Div16 performs / operation on two int16 operands -// returning a result and status -func Div16(a, b int16) (int16, bool) { - q, _, ok := Quo16(a, b) - return q, ok -} - -// Div16p is the unchecked panicking version of Div16 -func Div16p(a, b int16) int16 { - r, ok := Div16(a, b) - if !ok { - panic("division failure") - } - return r -} - -// Quo16 performs + operation on two int16 operands -// returning a quotient, a remainder and status -func Quo16(a, b int16) (int16, int16, bool) { - if b == 0 { - return 0, 0, false - } else if b == -1 && a == MinInt16 { - return 0, 0, false - } - c := a / b - return c, a % b, true -} - -// Add32 performs + operation on two int32 operands -// returning a result and status -func Add32(a, b int32) (int32, bool) { - c := a + b - if (c > a) == (b > 0) { - return c, true - } - return c, false -} - -// Add32p is the unchecked panicking version of Add32 -func Add32p(a, b int32) int32 { - r, ok := Add32(a, b) - if !ok { - panic("addition overflow") - } - return r -} - -// Sub32 performs - operation on two int32 operands -// returning a result and status -func Sub32(a, b int32) (int32, bool) { - c := a - b - if (c < a) == (b > 0) { - return c, true - } - return c, false -} - -// Sub32p is the unchecked panicking version of Sub32 -func Sub32p(a, b int32) int32 { - r, ok := Sub32(a, b) - if !ok { - panic("subtraction overflow") - } - return r -} - -// Mul32 performs * operation on two int32 operands -// returning a result and status -func Mul32(a, b int32) (int32, bool) { - if a == 0 || b == 0 { - return 0, true - } - c := a * b - if (c < 0) == ((a < 0) != (b < 0)) { - if c/b == a { - return c, true - } - } - return c, false -} - -// Mul32p is the unchecked panicking version of Mul32 -func Mul32p(a, b int32) int32 { - r, ok := Mul32(a, b) - if !ok { - panic("multiplication overflow") - } - return r -} - -// Div32 performs / operation on two int32 operands -// returning a result and status -func Div32(a, b int32) (int32, bool) { - q, _, ok := Quo32(a, b) - return q, ok -} - -// Div32p is the unchecked panicking version of Div32 -func Div32p(a, b int32) int32 { - r, ok := Div32(a, b) - if !ok { - panic("division failure") - } - return r -} - -// Quo32 performs + operation on two int32 operands -// returning a quotient, a remainder and status -func Quo32(a, b int32) (int32, int32, bool) { - if b == 0 { - return 0, 0, false - } else if b == -1 && a == MinInt32 { - return 0, 0, false - } - c := a / b - return c, a % b, true -} - -// Add64 performs + operation on two int64 operands -// returning a result and status -func Add64(a, b int64) (int64, bool) { - c := a + b - if (c > a) == (b > 0) { - return c, true - } - return c, false -} - -// Add64p is the unchecked panicking version of Add64 -func Add64p(a, b int64) int64 { - r, ok := Add64(a, b) - if !ok { - panic("addition overflow") - } - return r -} - -// Sub64 performs - operation on two int64 operands -// returning a result and status -func Sub64(a, b int64) (int64, bool) { - c := a - b - if (c < a) == (b > 0) { - return c, true - } - return c, false -} - -// Sub64p is the unchecked panicking version of Sub64 -func Sub64p(a, b int64) int64 { - r, ok := Sub64(a, b) - if !ok { - panic("subtraction overflow") - } - return r -} - -// Mul64 performs * operation on two int64 operands -// returning a result and status -func Mul64(a, b int64) (int64, bool) { - if a == 0 || b == 0 { - return 0, true - } - c := a * b - if (c < 0) == ((a < 0) != (b < 0)) { - if c/b == a { - return c, true - } - } - return c, false -} - -// Mul64p is the unchecked panicking version of Mul64 -func Mul64p(a, b int64) int64 { - r, ok := Mul64(a, b) - if !ok { - panic("multiplication overflow") - } - return r -} - -// Div64 performs / operation on two int64 operands -// returning a result and status -func Div64(a, b int64) (int64, bool) { - q, _, ok := Quo64(a, b) - return q, ok -} - -// Div64p is the unchecked panicking version of Div64 -func Div64p(a, b int64) int64 { - r, ok := Div64(a, b) - if !ok { - panic("division failure") - } - return r -} - -// Quo64 performs + operation on two int64 operands -// returning a quotient, a remainder and status -func Quo64(a, b int64) (int64, int64, bool) { - if b == 0 { - return 0, 0, false - } else if b == -1 && a == MinInt64 { - return 0, 0, false - } - c := a / b - return c, a % b, true -} From 9574b6cc9d950a5809106bf5ab2cc2b930937a87 Mon Sep 17 00:00:00 2001 From: leohhhn Date: Sun, 31 Mar 2024 15:57:28 +0900 Subject: [PATCH 07/20] update comment --- gnovm/stdlibs/math/overflow/overflow.gno | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gnovm/stdlibs/math/overflow/overflow.gno b/gnovm/stdlibs/math/overflow/overflow.gno index dde2c764dec..2757e6c3c14 100644 --- a/gnovm/stdlibs/math/overflow/overflow.gno +++ b/gnovm/stdlibs/math/overflow/overflow.gno @@ -2,7 +2,7 @@ // NOTE: there was a bug with the original Quotient* functions, and // testing method. These have been fixed here, and tests ported to // tests/files/maths_int*.go respectively. -// Note: copied over from p/demo/maths & deprecated over there. +// Note: moved over from p/demo/maths. package overflow import "math" From 251e522851eeea1ed1e235f67e66b0d4b8c1056a Mon Sep 17 00:00:00 2001 From: leohhhn Date: Sun, 31 Mar 2024 16:08:40 +0900 Subject: [PATCH 08/20] add remainder check --- gnovm/stdlibs/math/overflow/overflow_test.gno | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/gnovm/stdlibs/math/overflow/overflow_test.gno b/gnovm/stdlibs/math/overflow/overflow_test.gno index 6c3e584a2d6..cba1a25cf42 100644 --- a/gnovm/stdlibs/math/overflow/overflow_test.gno +++ b/gnovm/stdlibs/math/overflow/overflow_test.gno @@ -74,16 +74,18 @@ func TestAlgorithms(t *testing.T) { // DIVISION if b8 != 0 { r64 := a64 / b64 + rem64 := a64 % b64 // now the verification - result, _, ok := Quo8(a8, b8) + result, rem, ok := Quo8(a8, b8) if ok && int64(result) != r64 { t.Errorf("failed to fail on %v / %v = %v instead of %v\n", a8, b8, result, r64) errors++ } - if !ok && result != 0 && int64(result) == r64 { - t.Fail() + if ok && int64(rem) != rem64 { + t.Errorf("failed to fail on %v %% %v = %v instead of %v\n", + a8, b8, rem, rem64) errors++ } } From d8fd1f58bd95f4a02b4cc55c82f675fcbe22e4a9 Mon Sep 17 00:00:00 2001 From: leohhhn Date: Tue, 23 Apr 2024 17:22:55 +0200 Subject: [PATCH 09/20] move comment --- gnovm/stdlibs/math/overflow/overflow.gno | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/gnovm/stdlibs/math/overflow/overflow.gno b/gnovm/stdlibs/math/overflow/overflow.gno index 2757e6c3c14..9bdeff0720f 100644 --- a/gnovm/stdlibs/math/overflow/overflow.gno +++ b/gnovm/stdlibs/math/overflow/overflow.gno @@ -3,9 +3,6 @@ // testing method. These have been fixed here, and tests ported to // tests/files/maths_int*.go respectively. // Note: moved over from p/demo/maths. -package overflow - -import "math" /* Package overflow offers overflow-checked integer arithmetic operations @@ -26,7 +23,11 @@ overflow.Add(math.MaxInt64,1) -> (0, false) Add, Sub, Mul, Div are for int. Add64, Add32, etc. are specifically sized. If anybody wishes an unsigned version, submit a pull request for code -and new tests. */ +and new tests. +*/ +package overflow + +import "math" //go:generate ./overflow_template.sh From 88e37eedc10a56674681c765653edf7061d13ac8 Mon Sep 17 00:00:00 2001 From: leohhhn Date: Tue, 23 Apr 2024 17:34:35 +0200 Subject: [PATCH 10/20] replace import in tests --- gnovm/tests/files/maths_int8.gno | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/gnovm/tests/files/maths_int8.gno b/gnovm/tests/files/maths_int8.gno index 40e7a2a62e0..66d59e9fc31 100644 --- a/gnovm/tests/files/maths_int8.gno +++ b/gnovm/tests/files/maths_int8.gno @@ -1,14 +1,12 @@ package main -import ( - "gno.land/p/demo/maths" -) +import "math" func main() { ctr := int64(0) - for a64 := int64(maths.MinInt8); a64 <= int64(maths.MaxInt8); a64++ { - for b64 := int64(maths.MinInt8); b64 <= int64(maths.MaxInt8); b64++ { + for a64 := int64(math.MinInt8); a64 <= int64(math.MaxInt8); a64++ { + for b64 := int64(math.MinInt8); b64 <= int64(math.MaxInt8); b64++ { a8 := int8(a64) b8 := int8(b64) if int64(a8) != a64 || int64(b8) != b64 { @@ -21,8 +19,8 @@ func main() { r64 := a64 + b64 // now the verification - result, ok := maths.Add8(a8, b8) - if int64(maths.MinInt8) <= r64 && r64 <= int64(maths.MaxInt8) { + result, ok := math.Add8(a8, b8) + if int64(math.MinInt8) <= r64 && r64 <= int64(math.MaxInt8) { if !ok || int64(result) != r64 { println("add", a8, b8, result, r64) panic("incorrect result for non-overflow") @@ -39,8 +37,8 @@ func main() { r64 := a64 - b64 // now the verification - result, ok := maths.Sub8(a8, b8) - if int64(maths.MinInt8) <= r64 && r64 <= int64(maths.MaxInt8) { + result, ok := math.Sub8(a8, b8) + if int64(math.MinInt8) <= r64 && r64 <= int64(math.MaxInt8) { if !ok || int64(result) != r64 { println("sub", a8, b8, result, r64) panic("incorrect result for non-overflow") @@ -57,8 +55,8 @@ func main() { r64 := a64 * b64 // now the verification - result, ok := maths.Mul8(a8, b8) - if int64(maths.MinInt8) <= r64 && r64 <= int64(maths.MaxInt8) { + result, ok := math.Mul8(a8, b8) + if int64(math.MinInt8) <= r64 && r64 <= int64(math.MaxInt8) { if !ok || int64(result) != r64 { println("mul", a8, b8, result, r64) panic("incorrect result for non-overflow") @@ -75,8 +73,8 @@ func main() { r64 := a64 / b64 // now the verification - result, _, ok := maths.Quo8(a8, b8) - if int64(maths.MinInt8) <= r64 && r64 <= int64(maths.MaxInt8) { + result, _, ok := math.Quo8(a8, b8) + if int64(math.MinInt8) <= r64 && r64 <= int64(math.MaxInt8) { if !ok || int64(result) != r64 { panic("incorrect result for non-overflow") } From e91eb87679c9217646d79a84ba7576eb5230e64d Mon Sep 17 00:00:00 2001 From: leohhhn Date: Tue, 23 Apr 2024 17:41:26 +0200 Subject: [PATCH 11/20] fix --- gnovm/tests/files/maths_int8.gno | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/gnovm/tests/files/maths_int8.gno b/gnovm/tests/files/maths_int8.gno index 66d59e9fc31..2e7a48969fb 100644 --- a/gnovm/tests/files/maths_int8.gno +++ b/gnovm/tests/files/maths_int8.gno @@ -1,6 +1,9 @@ package main -import "math" +import ( + "math" + "math/overflow" +) func main() { ctr := int64(0) @@ -19,7 +22,7 @@ func main() { r64 := a64 + b64 // now the verification - result, ok := math.Add8(a8, b8) + result, ok := overflow.Add8(a8, b8) if int64(math.MinInt8) <= r64 && r64 <= int64(math.MaxInt8) { if !ok || int64(result) != r64 { println("add", a8, b8, result, r64) @@ -37,7 +40,7 @@ func main() { r64 := a64 - b64 // now the verification - result, ok := math.Sub8(a8, b8) + result, ok := overflow.Sub8(a8, b8) if int64(math.MinInt8) <= r64 && r64 <= int64(math.MaxInt8) { if !ok || int64(result) != r64 { println("sub", a8, b8, result, r64) @@ -55,7 +58,7 @@ func main() { r64 := a64 * b64 // now the verification - result, ok := math.Mul8(a8, b8) + result, ok := overflow.Mul8(a8, b8) if int64(math.MinInt8) <= r64 && r64 <= int64(math.MaxInt8) { if !ok || int64(result) != r64 { println("mul", a8, b8, result, r64) @@ -73,7 +76,7 @@ func main() { r64 := a64 / b64 // now the verification - result, _, ok := math.Quo8(a8, b8) + result, _, ok := overflow.Quo8(a8, b8) if int64(math.MinInt8) <= r64 && r64 <= int64(math.MaxInt8) { if !ok || int64(result) != r64 { panic("incorrect result for non-overflow") From 61b0cca4b25bc76f1bdb60cd5cbbf77ae29400ee Mon Sep 17 00:00:00 2001 From: leohhhn Date: Tue, 23 Apr 2024 18:33:47 +0200 Subject: [PATCH 12/20] add values to gonative --- gnovm/tests/files/maths_int16_long.gno | 23 ++++++++++++----------- gnovm/tests/imports.go | 8 ++++++++ 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/gnovm/tests/files/maths_int16_long.gno b/gnovm/tests/files/maths_int16_long.gno index efaf0ea9346..7655c94b278 100644 --- a/gnovm/tests/files/maths_int16_long.gno +++ b/gnovm/tests/files/maths_int16_long.gno @@ -1,14 +1,15 @@ package main import ( - "gno.land/p/demo/maths" + "math" + "math/overflow" ) func main() { ctr := int64(0) - for a64 := int64(maths.MinInt16); a64 <= int64(maths.MaxInt16); a64++ { - for b64 := int64(maths.MinInt16); b64 <= int64(maths.MaxInt16); b64++ { + for a64 := int64(math.MinInt16); a64 <= int64(math.MaxInt16); a64++ { + for b64 := int64(math.MinInt16); b64 <= int64(math.MaxInt16); b64++ { a16 := int16(a64) b16 := int16(b64) if int64(a16) != a64 || int64(b16) != b64 { @@ -21,8 +22,8 @@ func main() { r64 := a64 + b64 // now the verification - result, ok := maths.Add16(a16, b16) - if int64(maths.MinInt16) <= r64 && r64 <= int64(maths.MaxInt16) { + result, ok := overflow.Add16(a16, b16) + if int64(math.MinInt16) <= r64 && r64 <= int64(math.MaxInt16) { if !ok || int64(result) != r64 { println("add", a16, b16, result, r64) panic("incorrect result for non-overflow") @@ -40,8 +41,8 @@ func main() { r64 := a64 - b64 // now the verification - result, ok := maths.Sub16(a16, b16) - if int64(maths.MinInt16) <= r64 && r64 <= int64(maths.MaxInt16) { + result, ok := overflow.Sub16(a16, b16) + if int64(math.MinInt16) <= r64 && r64 <= int64(math.MaxInt16) { if !ok || int64(result) != r64 { println("sub", a16, b16, result, r64) panic("incorrect result for non-overflow") @@ -59,8 +60,8 @@ func main() { r64 := a64 * b64 // now the verification - result, ok := maths.Mul16(a16, b16) - if int64(maths.MinInt16) <= r64 && r64 <= int64(maths.MaxInt16) { + result, ok := overflow.Mul16(a16, b16) + if int64(math.MinInt16) <= r64 && r64 <= int64(math.MaxInt16) { if !ok || int64(result) != r64 { println("mul", a16, b16, result, r64) panic("incorrect result for non-overflow") @@ -78,8 +79,8 @@ func main() { r64 := a64 / b64 // now the verification - result, _, ok := maths.Quo16(a16, b16) - if int64(maths.MinInt16) <= r64 && r64 <= int64(maths.MaxInt16) { + result, _, ok := overflow.Quo16(a16, b16) + if int64(math.MinInt16) <= r64 && r64 <= int64(math.MaxInt16) { if !ok || int64(result) != r64 { println("quo", a16, b16, result, r64) panic("incorrect result for non-overflow") diff --git a/gnovm/tests/imports.go b/gnovm/tests/imports.go index 9c48b4132cf..ab760d6a8ef 100644 --- a/gnovm/tests/imports.go +++ b/gnovm/tests/imports.go @@ -254,6 +254,14 @@ func TestStore(rootDir, filesPath string, stdin io.Reader, stdout, stderr io.Wri pkg.DefineGoNativeValue("Pi", math.Pi) pkg.DefineGoNativeValue("MaxFloat32", math.MaxFloat32) pkg.DefineGoNativeValue("MaxFloat64", math.MaxFloat64) + pkg.DefineGoNativeValue("MaxUint32", math.MaxUint32) + pkg.DefineGoNativeValue("MinInt8", math.MinInt8) + pkg.DefineGoNativeValue("MinInt16", math.MinInt16) + pkg.DefineGoNativeValue("MinInt32", math.MinInt32) + pkg.DefineGoNativeValue("MinInt64", math.MinInt64) + pkg.DefineGoNativeValue("MaxInt16", math.MaxInt16) + pkg.DefineGoNativeValue("MaxInt32", math.MaxInt32) + pkg.DefineGoNativeValue("MaxInt64", math.MaxInt64) return pkg, pkg.NewPackage() case "math/rand": // XXX only expose for tests. From b3b3daadf958aea1f101bebfac9d8625f3f4500a Mon Sep 17 00:00:00 2001 From: leohhhn Date: Tue, 23 Apr 2024 18:34:57 +0200 Subject: [PATCH 13/20] add val --- gnovm/tests/imports.go | 1 + 1 file changed, 1 insertion(+) diff --git a/gnovm/tests/imports.go b/gnovm/tests/imports.go index ab760d6a8ef..b05886f76ff 100644 --- a/gnovm/tests/imports.go +++ b/gnovm/tests/imports.go @@ -259,6 +259,7 @@ func TestStore(rootDir, filesPath string, stdin io.Reader, stdout, stderr io.Wri pkg.DefineGoNativeValue("MinInt16", math.MinInt16) pkg.DefineGoNativeValue("MinInt32", math.MinInt32) pkg.DefineGoNativeValue("MinInt64", math.MinInt64) + pkg.DefineGoNativeValue("MaxInt8", math.MaxInt8) pkg.DefineGoNativeValue("MaxInt16", math.MaxInt16) pkg.DefineGoNativeValue("MaxInt32", math.MaxInt32) pkg.DefineGoNativeValue("MaxInt64", math.MaxInt64) From c557c4ed772939157c1b5fe963cd9e84042f9e5e Mon Sep 17 00:00:00 2001 From: leohhhn Date: Tue, 23 Apr 2024 19:03:07 +0200 Subject: [PATCH 14/20] rename maths to rat --- examples/gno.land/p/demo/groups/gno.mod | 2 +- examples/gno.land/p/demo/groups/vote_set.gno | 6 +++--- examples/gno.land/p/demo/maths/gno.mod | 1 - examples/gno.land/p/demo/rat/gno.mod | 1 + examples/gno.land/p/demo/{maths => rat}/maths.gno | 2 +- examples/gno.land/p/demo/{maths => rat}/rat.gno | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) delete mode 100644 examples/gno.land/p/demo/maths/gno.mod create mode 100644 examples/gno.land/p/demo/rat/gno.mod rename examples/gno.land/p/demo/{maths => rat}/maths.gno (96%) rename examples/gno.land/p/demo/{maths => rat}/rat.gno (98%) diff --git a/examples/gno.land/p/demo/groups/gno.mod b/examples/gno.land/p/demo/groups/gno.mod index 0e9f7cf2a7c..f0749e3f411 100644 --- a/examples/gno.land/p/demo/groups/gno.mod +++ b/examples/gno.land/p/demo/groups/gno.mod @@ -1,6 +1,6 @@ module gno.land/p/demo/groups require ( - gno.land/p/demo/maths v0.0.0-latest + gno.land/p/demo/rat v0.0.0-latest gno.land/r/demo/boards v0.0.0-latest ) diff --git a/examples/gno.land/p/demo/groups/vote_set.gno b/examples/gno.land/p/demo/groups/vote_set.gno index 22b29045d91..f66fb0fc8d8 100644 --- a/examples/gno.land/p/demo/groups/vote_set.gno +++ b/examples/gno.land/p/demo/groups/vote_set.gno @@ -4,7 +4,7 @@ import ( "std" "time" - "gno.land/p/demo/maths" + "gno.land/p/demo/rat" ) //---------------------------------------- @@ -71,8 +71,8 @@ func (vlist *VoteList) CountVotes(target string) int { // Committee type Committee struct { - Quorum maths.Rat - Threshold maths.Rat + Quorum rat.Rat + Threshold rat.Rat Addresses std.AddressSet } diff --git a/examples/gno.land/p/demo/maths/gno.mod b/examples/gno.land/p/demo/maths/gno.mod deleted file mode 100644 index d320b653702..00000000000 --- a/examples/gno.land/p/demo/maths/gno.mod +++ /dev/null @@ -1 +0,0 @@ -module gno.land/p/demo/maths diff --git a/examples/gno.land/p/demo/rat/gno.mod b/examples/gno.land/p/demo/rat/gno.mod new file mode 100644 index 00000000000..9ee0e4c16c5 --- /dev/null +++ b/examples/gno.land/p/demo/rat/gno.mod @@ -0,0 +1 @@ +module gno.land/p/demo/rat \ No newline at end of file diff --git a/examples/gno.land/p/demo/maths/maths.gno b/examples/gno.land/p/demo/rat/maths.gno similarity index 96% rename from examples/gno.land/p/demo/maths/maths.gno rename to examples/gno.land/p/demo/rat/maths.gno index 0b3ce3c30e5..115e3cad5d8 100644 --- a/examples/gno.land/p/demo/maths/maths.gno +++ b/examples/gno.land/p/demo/rat/maths.gno @@ -1,4 +1,4 @@ -package maths +package rat const ( intSize = 32 << (^uint(0) >> 63) // 32 or 64 diff --git a/examples/gno.land/p/demo/maths/rat.gno b/examples/gno.land/p/demo/rat/rat.gno similarity index 98% rename from examples/gno.land/p/demo/maths/rat.gno rename to examples/gno.land/p/demo/rat/rat.gno index a7520fb016e..ea53343c490 100644 --- a/examples/gno.land/p/demo/maths/rat.gno +++ b/examples/gno.land/p/demo/rat/rat.gno @@ -1,4 +1,4 @@ -package maths +package rat //---------------------------------------- // Rat fractions From 84aaa51b9d2e3c3749b34af42e21efccdad66bb9 Mon Sep 17 00:00:00 2001 From: leohhhn Date: Tue, 23 Apr 2024 19:04:12 +0200 Subject: [PATCH 15/20] remove math_int8.gno --- gnovm/tests/files/maths_int8.gno | 96 -------------------------------- 1 file changed, 96 deletions(-) delete mode 100644 gnovm/tests/files/maths_int8.gno diff --git a/gnovm/tests/files/maths_int8.gno b/gnovm/tests/files/maths_int8.gno deleted file mode 100644 index 2e7a48969fb..00000000000 --- a/gnovm/tests/files/maths_int8.gno +++ /dev/null @@ -1,96 +0,0 @@ -package main - -import ( - "math" - "math/overflow" -) - -func main() { - ctr := int64(0) - - for a64 := int64(math.MinInt8); a64 <= int64(math.MaxInt8); a64++ { - for b64 := int64(math.MinInt8); b64 <= int64(math.MaxInt8); b64++ { - a8 := int8(a64) - b8 := int8(b64) - if int64(a8) != a64 || int64(b8) != b64 { - panic("LOGIC FAILURE IN TEST") - } - ctr++ - - // ADDITION - { - r64 := a64 + b64 - - // now the verification - result, ok := overflow.Add8(a8, b8) - if int64(math.MinInt8) <= r64 && r64 <= int64(math.MaxInt8) { - if !ok || int64(result) != r64 { - println("add", a8, b8, result, r64) - panic("incorrect result for non-overflow") - } - } else { - if ok { - panic("incorrect ok result") - } - } - } - - // SUBTRACTION - { - r64 := a64 - b64 - - // now the verification - result, ok := overflow.Sub8(a8, b8) - if int64(math.MinInt8) <= r64 && r64 <= int64(math.MaxInt8) { - if !ok || int64(result) != r64 { - println("sub", a8, b8, result, r64) - panic("incorrect result for non-overflow") - } - } else { - if ok { - panic("incorrect ok result") - } - } - } - - // MULTIPLICATION - { - r64 := a64 * b64 - - // now the verification - result, ok := overflow.Mul8(a8, b8) - if int64(math.MinInt8) <= r64 && r64 <= int64(math.MaxInt8) { - if !ok || int64(result) != r64 { - println("mul", a8, b8, result, r64) - panic("incorrect result for non-overflow") - } - } else { - if ok { - panic("incorrect ok result") - } - } - } - - // DIVISION - if b8 != 0 { - r64 := a64 / b64 - - // now the verification - result, _, ok := overflow.Quo8(a8, b8) - if int64(math.MinInt8) <= r64 && r64 <= int64(math.MaxInt8) { - if !ok || int64(result) != r64 { - panic("incorrect result for non-overflow") - } - } else { - if ok { - panic("incorrect ok result") - } - } - } - } - } - println("done", ctr) -} - -// Output: -// done 65536 From 0c65261e15d9eba9f802ea885b116a9301e5a4b7 Mon Sep 17 00:00:00 2001 From: leohhhn Date: Tue, 23 Apr 2024 19:06:18 +0200 Subject: [PATCH 16/20] move long test to overflow_test --- gnovm/stdlibs/math/overflow/overflow_test.gno | 97 +++++++++++++++++ gnovm/tests/files/maths_int16_long.gno | 101 ------------------ 2 files changed, 97 insertions(+), 101 deletions(-) delete mode 100644 gnovm/tests/files/maths_int16_long.gno diff --git a/gnovm/stdlibs/math/overflow/overflow_test.gno b/gnovm/stdlibs/math/overflow/overflow_test.gno index cba1a25cf42..5d1e5a3a22a 100644 --- a/gnovm/stdlibs/math/overflow/overflow_test.gno +++ b/gnovm/stdlibs/math/overflow/overflow_test.gno @@ -1,6 +1,7 @@ package overflow import ( + "github.com/gnolang/overflow" "math" "testing" ) @@ -102,3 +103,99 @@ func TestQuotient(t *testing.T) { t.Error("unexpected lack of failure") } } + +func TestLong(t *testing.T) { + if testing.Short() { + t.Skip() + } + + ctr := int64(0) + + for a64 := int64(math.MinInt16); a64 <= int64(math.MaxInt16); a64++ { + for b64 := int64(math.MinInt16); b64 <= int64(math.MaxInt16); b64++ { + a16 := int16(a64) + b16 := int16(b64) + if int64(a16) != a64 || int64(b16) != b64 { + panic("LOGIC FAILURE IN TEST") + } + ctr++ + + // ADDITION + { + r64 := a64 + b64 + + // now the verification + result, ok := overflow.Add16(a16, b16) + if int64(math.MinInt16) <= r64 && r64 <= int64(math.MaxInt16) { + if !ok || int64(result) != r64 { + println("add", a16, b16, result, r64) + panic("incorrect result for non-overflow") + } + } else { + if ok { + println("add", a16, b16, result, r64) + panic("incorrect ok result") + } + } + } + + // SUBTRACTION + { + r64 := a64 - b64 + + // now the verification + result, ok := overflow.Sub16(a16, b16) + if int64(math.MinInt16) <= r64 && r64 <= int64(math.MaxInt16) { + if !ok || int64(result) != r64 { + println("sub", a16, b16, result, r64) + panic("incorrect result for non-overflow") + } + } else { + if ok { + println("sub", a16, b16, result, r64) + panic("incorrect ok result") + } + } + } + + // MULTIPLICATION + { + r64 := a64 * b64 + + // now the verification + result, ok := overflow.Mul16(a16, b16) + if int64(math.MinInt16) <= r64 && r64 <= int64(math.MaxInt16) { + if !ok || int64(result) != r64 { + println("mul", a16, b16, result, r64) + panic("incorrect result for non-overflow") + } + } else { + if ok { + println("mul", a16, b16, result, r64) + panic("incorrect ok result") + } + } + } + + // DIVISION + if b16 != 0 { + r64 := a64 / b64 + + // now the verification + result, _, ok := overflow.Quo16(a16, b16) + if int64(math.MinInt16) <= r64 && r64 <= int64(math.MaxInt16) { + if !ok || int64(result) != r64 { + println("quo", a16, b16, result, r64) + panic("incorrect result for non-overflow") + } + } else { + if ok { + println("quo", a16, b16, result, r64) + panic("incorrect ok result") + } + } + } + } + } + println("done", ctr) +} diff --git a/gnovm/tests/files/maths_int16_long.gno b/gnovm/tests/files/maths_int16_long.gno deleted file mode 100644 index 7655c94b278..00000000000 --- a/gnovm/tests/files/maths_int16_long.gno +++ /dev/null @@ -1,101 +0,0 @@ -package main - -import ( - "math" - "math/overflow" -) - -func main() { - ctr := int64(0) - - for a64 := int64(math.MinInt16); a64 <= int64(math.MaxInt16); a64++ { - for b64 := int64(math.MinInt16); b64 <= int64(math.MaxInt16); b64++ { - a16 := int16(a64) - b16 := int16(b64) - if int64(a16) != a64 || int64(b16) != b64 { - panic("LOGIC FAILURE IN TEST") - } - ctr++ - - // ADDITION - { - r64 := a64 + b64 - - // now the verification - result, ok := overflow.Add16(a16, b16) - if int64(math.MinInt16) <= r64 && r64 <= int64(math.MaxInt16) { - if !ok || int64(result) != r64 { - println("add", a16, b16, result, r64) - panic("incorrect result for non-overflow") - } - } else { - if ok { - println("add", a16, b16, result, r64) - panic("incorrect ok result") - } - } - } - - // SUBTRACTION - { - r64 := a64 - b64 - - // now the verification - result, ok := overflow.Sub16(a16, b16) - if int64(math.MinInt16) <= r64 && r64 <= int64(math.MaxInt16) { - if !ok || int64(result) != r64 { - println("sub", a16, b16, result, r64) - panic("incorrect result for non-overflow") - } - } else { - if ok { - println("sub", a16, b16, result, r64) - panic("incorrect ok result") - } - } - } - - // MULTIPLICATION - { - r64 := a64 * b64 - - // now the verification - result, ok := overflow.Mul16(a16, b16) - if int64(math.MinInt16) <= r64 && r64 <= int64(math.MaxInt16) { - if !ok || int64(result) != r64 { - println("mul", a16, b16, result, r64) - panic("incorrect result for non-overflow") - } - } else { - if ok { - println("mul", a16, b16, result, r64) - panic("incorrect ok result") - } - } - } - - // DIVISION - if b16 != 0 { - r64 := a64 / b64 - - // now the verification - result, _, ok := overflow.Quo16(a16, b16) - if int64(math.MinInt16) <= r64 && r64 <= int64(math.MaxInt16) { - if !ok || int64(result) != r64 { - println("quo", a16, b16, result, r64) - panic("incorrect result for non-overflow") - } - } else { - if ok { - println("quo", a16, b16, result, r64) - panic("incorrect ok result") - } - } - } - } - } - println("done", ctr) -} - -// Output: -// done XXXXXX From 94997d8e935fa3ab8bb8b8803c0756b90a14308f Mon Sep 17 00:00:00 2001 From: leohhhn Date: Tue, 23 Apr 2024 19:10:22 +0200 Subject: [PATCH 17/20] fmt, lint, fix test --- gnovm/stdlibs/math/overflow/overflow_test.gno | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/gnovm/stdlibs/math/overflow/overflow_test.gno b/gnovm/stdlibs/math/overflow/overflow_test.gno index 5d1e5a3a22a..b7881aec480 100644 --- a/gnovm/stdlibs/math/overflow/overflow_test.gno +++ b/gnovm/stdlibs/math/overflow/overflow_test.gno @@ -1,7 +1,6 @@ package overflow import ( - "github.com/gnolang/overflow" "math" "testing" ) @@ -125,7 +124,7 @@ func TestLong(t *testing.T) { r64 := a64 + b64 // now the verification - result, ok := overflow.Add16(a16, b16) + result, ok := Add16(a16, b16) if int64(math.MinInt16) <= r64 && r64 <= int64(math.MaxInt16) { if !ok || int64(result) != r64 { println("add", a16, b16, result, r64) @@ -144,7 +143,7 @@ func TestLong(t *testing.T) { r64 := a64 - b64 // now the verification - result, ok := overflow.Sub16(a16, b16) + result, ok := Sub16(a16, b16) if int64(math.MinInt16) <= r64 && r64 <= int64(math.MaxInt16) { if !ok || int64(result) != r64 { println("sub", a16, b16, result, r64) @@ -163,7 +162,7 @@ func TestLong(t *testing.T) { r64 := a64 * b64 // now the verification - result, ok := overflow.Mul16(a16, b16) + result, ok := Mul16(a16, b16) if int64(math.MinInt16) <= r64 && r64 <= int64(math.MaxInt16) { if !ok || int64(result) != r64 { println("mul", a16, b16, result, r64) @@ -182,7 +181,7 @@ func TestLong(t *testing.T) { r64 := a64 / b64 // now the verification - result, _, ok := overflow.Quo16(a16, b16) + result, _, ok := Quo16(a16, b16) if int64(math.MinInt16) <= r64 && r64 <= int64(math.MaxInt16) { if !ok || int64(result) != r64 { println("quo", a16, b16, result, r64) From 1c6c543c992d2b6f0844de2499f37463f65695b0 Mon Sep 17 00:00:00 2001 From: leohhhn Date: Tue, 23 Apr 2024 19:15:52 +0200 Subject: [PATCH 18/20] tidy rat --- examples/gno.land/p/demo/rat/gno.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/gno.land/p/demo/rat/gno.mod b/examples/gno.land/p/demo/rat/gno.mod index 9ee0e4c16c5..c20136fe9bb 100644 --- a/examples/gno.land/p/demo/rat/gno.mod +++ b/examples/gno.land/p/demo/rat/gno.mod @@ -1 +1 @@ -module gno.land/p/demo/rat \ No newline at end of file +module gno.land/p/demo/rat From 15e23cd9aa282fecfa03b5769bdfb1499b172de1 Mon Sep 17 00:00:00 2001 From: Leon Hudak <33522493+leohhhn@users.noreply.github.com> Date: Wed, 24 Apr 2024 18:37:02 +0200 Subject: [PATCH 19/20] Update gnovm/tests/imports.go Co-authored-by: Hariom Verma --- gnovm/tests/imports.go | 1 + 1 file changed, 1 insertion(+) diff --git a/gnovm/tests/imports.go b/gnovm/tests/imports.go index b05886f76ff..b9b6f12728c 100644 --- a/gnovm/tests/imports.go +++ b/gnovm/tests/imports.go @@ -255,6 +255,7 @@ func TestStore(rootDir, filesPath string, stdin io.Reader, stdout, stderr io.Wri pkg.DefineGoNativeValue("MaxFloat32", math.MaxFloat32) pkg.DefineGoNativeValue("MaxFloat64", math.MaxFloat64) pkg.DefineGoNativeValue("MaxUint32", math.MaxUint32) + pkg.DefineGoNativeValue("MaxUint64", math.MaxUint64) pkg.DefineGoNativeValue("MinInt8", math.MinInt8) pkg.DefineGoNativeValue("MinInt16", math.MinInt16) pkg.DefineGoNativeValue("MinInt32", math.MinInt32) From 5f4ce07fe0dbbb8d2878a3dbb9cf0a29bf4cf423 Mon Sep 17 00:00:00 2001 From: Hariom Verma Date: Wed, 24 Apr 2024 22:29:12 +0530 Subject: [PATCH 20/20] Update gnovm/tests/imports.go --- gnovm/tests/imports.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gnovm/tests/imports.go b/gnovm/tests/imports.go index b9b6f12728c..389c6717780 100644 --- a/gnovm/tests/imports.go +++ b/gnovm/tests/imports.go @@ -255,7 +255,7 @@ func TestStore(rootDir, filesPath string, stdin io.Reader, stdout, stderr io.Wri pkg.DefineGoNativeValue("MaxFloat32", math.MaxFloat32) pkg.DefineGoNativeValue("MaxFloat64", math.MaxFloat64) pkg.DefineGoNativeValue("MaxUint32", math.MaxUint32) - pkg.DefineGoNativeValue("MaxUint64", math.MaxUint64) + pkg.DefineGoNativeValue("MaxUint64", uint64(math.MaxUint64)) pkg.DefineGoNativeValue("MinInt8", math.MinInt8) pkg.DefineGoNativeValue("MinInt16", math.MinInt16) pkg.DefineGoNativeValue("MinInt32", math.MinInt32)