From d6e2405bc20d44b8bd1a895fa3a28dd7513c5364 Mon Sep 17 00:00:00 2001 From: Lee ByeongJun Date: Mon, 2 Sep 2024 14:13:01 +0900 Subject: [PATCH 1/7] update condition --- .../gno.land/p/demo/int256/conversion.gno | 3 +- .../p/demo/int256/conversion_test.gno | 63 +++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/examples/gno.land/p/demo/int256/conversion.gno b/examples/gno.land/p/demo/int256/conversion.gno index ee6e7560f15..bcc342857d1 100644 --- a/examples/gno.land/p/demo/int256/conversion.gno +++ b/examples/gno.land/p/demo/int256/conversion.gno @@ -79,8 +79,9 @@ func (z *Int) ToString() string { } t := z.abs.Dec() - if z.neg { + if z.neg && !z.abs.IsZero() { return "-" + t } + return t } diff --git a/examples/gno.land/p/demo/int256/conversion_test.gno b/examples/gno.land/p/demo/int256/conversion_test.gno index da54c226669..b085a77a15a 100644 --- a/examples/gno.land/p/demo/int256/conversion_test.gno +++ b/examples/gno.land/p/demo/int256/conversion_test.gno @@ -169,3 +169,66 @@ func TestSetUint256(t *testing.T) { } } } + +func TestToString(t *testing.T) { + tests := []struct { + name string + setup func() *Int + expected string + }{ + { + name: "Zero from subtraction", + setup: func() *Int { + minusThree := MustFromDecimal("-3") + three := MustFromDecimal("3") + return Zero().Add(minusThree, three) + }, + expected: "0", + }, + { + name: "Zero from right shift", + setup: func() *Int { + return Zero().Rsh(One(), 1234) + }, + expected: "0", + }, + { + name: "Positive number", + setup: func() *Int { + return MustFromDecimal("42") + }, + expected: "42", + }, + { + name: "Negative number", + setup: func() *Int { + return MustFromDecimal("-42") + }, + expected: "-42", + }, + { + name: "Large positive number", + setup: func() *Int { + return MustFromDecimal("115792089237316195423570985008687907853269984665640564039457584007913129639935") + }, + expected: "115792089237316195423570985008687907853269984665640564039457584007913129639935", + }, + { + name: "Large negative number", + setup: func() *Int { + return MustFromDecimal("-115792089237316195423570985008687907853269984665640564039457584007913129639935") + }, + expected: "-115792089237316195423570985008687907853269984665640564039457584007913129639935", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + z := tt.setup() + result := z.ToString() + if result != tt.expected { + t.Errorf("ToString() = %s, want %s", result, tt.expected) + } + }) + } +} From 4fe293a7688f5f62f20b05d37df02bc92e3d8a44 Mon Sep 17 00:00:00 2001 From: Lee ByeongJun Date: Mon, 2 Sep 2024 14:56:50 +0900 Subject: [PATCH 2/7] fix add function --- .../gno.land/p/demo/int256/arithmetic.gno | 48 ++++++++++++++----- .../p/demo/int256/arithmetic_test.gno | 3 +- 2 files changed, 39 insertions(+), 12 deletions(-) diff --git a/examples/gno.land/p/demo/int256/arithmetic.gno b/examples/gno.land/p/demo/int256/arithmetic.gno index ce05426f585..55ad33189bf 100644 --- a/examples/gno.land/p/demo/int256/arithmetic.gno +++ b/examples/gno.land/p/demo/int256/arithmetic.gno @@ -5,26 +5,52 @@ import "gno.land/p/demo/uint256" func (z *Int) Add(x, y *Int) *Int { z.initiateAbs() - neg := x.neg - if x.neg == y.neg { - // x + y == x + y - // (-x) + (-y) == -(x + y) - z.abs = z.abs.Add(x.abs, y.abs) + // If both numbers have the same sign, add their absolute values + z.abs.Add(x.abs, y.abs) + z.neg = x.neg } else { - // x + (-y) == x - y == -(y - x) - // (-x) + y == y - x == -(x - y) + // If signs are different, subtract the smaller absolute value from the larger if x.abs.Cmp(y.abs) >= 0 { - z.abs = z.abs.Sub(x.abs, y.abs) + z.abs.Sub(x.abs, y.abs) + z.neg = x.neg } else { - neg = !neg - z.abs = z.abs.Sub(y.abs, x.abs) + z.abs.Sub(y.abs, x.abs) + z.neg = y.neg } } - z.neg = neg // 0 has no sign + + // Ensure zero is always positive + if z.abs.IsZero() { + z.neg = false + } + return z } +// func (z *Int) Add(x, y *Int) *Int { +// z.initiateAbs() + +// neg := x.neg + +// if x.neg == y.neg { +// // x + y == x + y +// // (-x) + (-y) == -(x + y) +// z.abs = z.abs.Add(x.abs, y.abs) +// } else { +// // x + (-y) == x - y == -(y - x) +// // (-x) + y == y - x == -(x - y) +// if x.abs.Cmp(y.abs) >= 0 { +// z.abs = z.abs.Sub(x.abs, y.abs) +// } else { +// neg = !neg +// z.abs = z.abs.Sub(y.abs, x.abs) +// } +// } +// z.neg = neg // 0 has no sign +// return z +// } + // AddUint256 set z to the sum x + y, where y is a uint256, and returns z func (z *Int) AddUint256(x *Int, y *uint256.Uint) *Int { if x.neg { diff --git a/examples/gno.land/p/demo/int256/arithmetic_test.gno b/examples/gno.land/p/demo/int256/arithmetic_test.gno index c4aeb18e3c5..28311f9ac05 100644 --- a/examples/gno.land/p/demo/int256/arithmetic_test.gno +++ b/examples/gno.land/p/demo/int256/arithmetic_test.gno @@ -15,8 +15,9 @@ func TestAdd(t *testing.T) { {"1", "1", "2"}, {"1", "2", "3"}, // NEGATIVE - {"-1", "1", "-0"}, // TODO: remove negative sign for 0 ?? + {"-1", "1", "0"}, {"1", "-1", "0"}, + {"3", "-3", "0"}, {"-1", "-1", "-2"}, {"-1", "-2", "-3"}, {"-1", "3", "2"}, From b9d8bde4bfd300a71da5a4edb2cdeea3b00e3d26 Mon Sep 17 00:00:00 2001 From: Lee ByeongJun Date: Mon, 2 Sep 2024 14:59:21 +0900 Subject: [PATCH 3/7] remove comment --- .../gno.land/p/demo/int256/arithmetic.gno | 23 ------------------- 1 file changed, 23 deletions(-) diff --git a/examples/gno.land/p/demo/int256/arithmetic.gno b/examples/gno.land/p/demo/int256/arithmetic.gno index 55ad33189bf..2535976a957 100644 --- a/examples/gno.land/p/demo/int256/arithmetic.gno +++ b/examples/gno.land/p/demo/int256/arithmetic.gno @@ -28,29 +28,6 @@ func (z *Int) Add(x, y *Int) *Int { return z } -// func (z *Int) Add(x, y *Int) *Int { -// z.initiateAbs() - -// neg := x.neg - -// if x.neg == y.neg { -// // x + y == x + y -// // (-x) + (-y) == -(x + y) -// z.abs = z.abs.Add(x.abs, y.abs) -// } else { -// // x + (-y) == x - y == -(y - x) -// // (-x) + y == y - x == -(x - y) -// if x.abs.Cmp(y.abs) >= 0 { -// z.abs = z.abs.Sub(x.abs, y.abs) -// } else { -// neg = !neg -// z.abs = z.abs.Sub(y.abs, x.abs) -// } -// } -// z.neg = neg // 0 has no sign -// return z -// } - // AddUint256 set z to the sum x + y, where y is a uint256, and returns z func (z *Int) AddUint256(x *Int, y *uint256.Uint) *Int { if x.neg { From 85759026488bb342b7432d857c0c0bd1fb55a0b9 Mon Sep 17 00:00:00 2001 From: Lee ByeongJun Date: Mon, 2 Sep 2024 15:12:18 +0900 Subject: [PATCH 4/7] div, sub. mul --- .../gno.land/p/demo/int256/arithmetic.gno | 42 +++++++---- .../p/demo/int256/arithmetic_test.gno | 75 +++++++++---------- 2 files changed, 64 insertions(+), 53 deletions(-) diff --git a/examples/gno.land/p/demo/int256/arithmetic.gno b/examples/gno.land/p/demo/int256/arithmetic.gno index 2535976a957..99e9c659b22 100644 --- a/examples/gno.land/p/demo/int256/arithmetic.gno +++ b/examples/gno.land/p/demo/int256/arithmetic.gno @@ -69,22 +69,27 @@ func AddDeltaOverflow(z, x *uint256.Uint, y *Int) bool { func (z *Int) Sub(x, y *Int) *Int { z.initiateAbs() - neg := x.neg if x.neg != y.neg { - // x - (-y) == x + y - // (-x) - y == -(x + y) - z.abs = z.abs.Add(x.abs, y.abs) + // If sign are different, add the absolute values + z.abs.Add(x.abs, y.abs) + z.neg = x.neg } else { - // x - y == x - y == -(y - x) - // (-x) - (-y) == y - x == -(x - y) + // If signs are the same, subtract the smaller absolute value from the larger if x.abs.Cmp(y.abs) >= 0 { z.abs = z.abs.Sub(x.abs, y.abs) + z.neg = x.neg } else { - neg = !neg - z.abs = z.abs.Sub(y.abs, x.abs) + // neg = !neg + // z.abs = z.abs.Sub(y.abs, x.abs) + z.abs.Sub(y.abs, x.abs) + z.neg = !x.neg } } - z.neg = neg // 0 has no sign + + // Ensure zero is always positive + if z.abs.IsZero() { + z.neg = false + } return z } @@ -110,7 +115,7 @@ func (z *Int) Mul(x, y *Int) *Int { z.initiateAbs() z.abs = z.abs.Mul(x.abs, y.abs) - z.neg = x.neg != y.neg // 0 has no sign + z.neg = x.neg != y.neg && !z.abs.IsZero() // 0 has no sign return z } @@ -129,12 +134,19 @@ func (z *Int) MulUint256(x *Int, y *uint256.Uint) *Int { func (z *Int) Div(x, y *Int) *Int { z.initiateAbs() - z.abs.Div(x.abs, y.abs) - if x.neg == y.neg { - z.neg = false - } else { - z.neg = true + if y.abs.IsZero() { + panic("division by zero") } + + z.abs.Div(x.abs, y.abs) + z.neg = (x.neg != y.neg) && !z.abs.IsZero() // 0 has no sign + + // z.abs.Div(x.abs, y.abs) + // if x.neg == y.neg { + // z.neg = false + // } else { + // z.neg = true + // } return z } diff --git a/examples/gno.land/p/demo/int256/arithmetic_test.gno b/examples/gno.land/p/demo/int256/arithmetic_test.gno index 28311f9ac05..4cfa306890a 100644 --- a/examples/gno.land/p/demo/int256/arithmetic_test.gno +++ b/examples/gno.land/p/demo/int256/arithmetic_test.gno @@ -189,10 +189,10 @@ func TestSub(t *testing.T) { {"1", "1", "0"}, {"-1", "1", "-2"}, {"1", "-1", "2"}, - {"-1", "-1", "-0"}, - {"-115792089237316195423570985008687907853269984665640564039457584007913129639935", "-115792089237316195423570985008687907853269984665640564039457584007913129639935", "-0"}, + {"-1", "-1", "0"}, + {"-115792089237316195423570985008687907853269984665640564039457584007913129639935", "-115792089237316195423570985008687907853269984665640564039457584007913129639935", "0"}, {"-115792089237316195423570985008687907853269984665640564039457584007913129639935", "0", "-115792089237316195423570985008687907853269984665640564039457584007913129639935"}, - {x: "-115792089237316195423570985008687907853269984665640564039457584007913129639935", y: "1", want: "-0"}, + {x: "-115792089237316195423570985008687907853269984665640564039457584007913129639935", y: "1", want: "0"}, } for _, tc := range tests { @@ -352,46 +352,45 @@ func TestMulUint256(t *testing.T) { func TestDiv(t *testing.T) { tests := []struct { - x, y, want string + x, y, expected string }{ + {"1", "1", "1"}, {"0", "1", "0"}, - {"0", "-1", "-0"}, - {"10", "0", "0"}, - {"10", "1", "10"}, - {"10", "-1", "-10"}, - {"-10", "0", "-0"}, - {"-10", "1", "-10"}, - {"-10", "-1", "10"}, - {"10", "-3", "-3"}, - {"10", "3", "3"}, + {"-1", "1", "-1"}, + {"1", "-1", "-1"}, + {"-1", "-1", "1"}, + {"-6", "3", "-2"}, + {"10", "-2", "-5"}, + {"-10", "3", "-3"}, + {"7", "3", "2"}, + {"-7", "3", "-2"}, + {"115792089237316195423570985008687907853269984665640564039457584007913129639935", "2", "57896044618658097711785492504343953926634992332820282019728792003956564819967"}, // Max uint256 / 2 } - for _, tc := range tests { - x, err := FromDecimal(tc.x) - if err != nil { - t.Error(err) - continue - } - - y, err := FromDecimal(tc.y) - if err != nil { - t.Error(err) - continue - } - - want, err := FromDecimal(tc.want) - if err != nil { - t.Error(err) - continue - } - - got := New() - got.Div(x, y) - - if got.Neq(want) { - t.Errorf("Div(%s, %s) = %v, want %v", tc.x, tc.y, got.ToString(), want.ToString()) - } + for _, tt := range tests { + t.Run(tt.x+"/"+tt.y, func(t *testing.T) { + x := MustFromDecimal(tt.x) + y := MustFromDecimal(tt.y) + result := Zero().Div(x, y) + if result.ToString() != tt.expected { + t.Errorf("Div(%s, %s) = %s, want %s", tt.x, tt.y, result.ToString(), tt.expected) + } + if result.abs.IsZero() && result.neg { + t.Errorf("Div(%s, %s) resulted in negative zero", tt.x, tt.y) + } + }) } + + t.Run("Division by zero", func(t *testing.T) { + defer func() { + if r := recover(); r == nil { + t.Errorf("Div(1, 0) did not panic") + } + }() + x := MustFromDecimal("1") + y := MustFromDecimal("0") + Zero().Div(x, y) + }) } func TestDivUint256(t *testing.T) { From 009bf4a34d209aa48b9e6b66e1f430d9a14658eb Mon Sep 17 00:00:00 2001 From: Lee ByeongJun Date: Mon, 2 Sep 2024 15:20:21 +0900 Subject: [PATCH 5/7] fix --- examples/gno.land/p/demo/int256/arithmetic.gno | 8 -------- 1 file changed, 8 deletions(-) diff --git a/examples/gno.land/p/demo/int256/arithmetic.gno b/examples/gno.land/p/demo/int256/arithmetic.gno index 99e9c659b22..d44b37b8537 100644 --- a/examples/gno.land/p/demo/int256/arithmetic.gno +++ b/examples/gno.land/p/demo/int256/arithmetic.gno @@ -79,8 +79,6 @@ func (z *Int) Sub(x, y *Int) *Int { z.abs = z.abs.Sub(x.abs, y.abs) z.neg = x.neg } else { - // neg = !neg - // z.abs = z.abs.Sub(y.abs, x.abs) z.abs.Sub(y.abs, x.abs) z.neg = !x.neg } @@ -141,12 +139,6 @@ func (z *Int) Div(x, y *Int) *Int { z.abs.Div(x.abs, y.abs) z.neg = (x.neg != y.neg) && !z.abs.IsZero() // 0 has no sign - // z.abs.Div(x.abs, y.abs) - // if x.neg == y.neg { - // z.neg = false - // } else { - // z.neg = true - // } return z } From 36e1f46c28489335fb79cbd2c0a2d9413b0d7694 Mon Sep 17 00:00:00 2001 From: Lee ByeongJun Date: Thu, 5 Sep 2024 12:26:50 +0900 Subject: [PATCH 6/7] fix --- examples/gno.land/p/demo/int256/conversion.gno | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/gno.land/p/demo/int256/conversion.gno b/examples/gno.land/p/demo/int256/conversion.gno index bcc342857d1..9e264e7e46b 100644 --- a/examples/gno.land/p/demo/int256/conversion.gno +++ b/examples/gno.land/p/demo/int256/conversion.gno @@ -79,7 +79,7 @@ func (z *Int) ToString() string { } t := z.abs.Dec() - if z.neg && !z.abs.IsZero() { + if z.neg { return "-" + t } From 4e84f641f04c224a421aa5c0f85494b21ad2cb36 Mon Sep 17 00:00:00 2001 From: Lee ByeongJun Date: Fri, 13 Sep 2024 11:05:56 +0900 Subject: [PATCH 7/7] apply suggestions --- .../gno.land/p/demo/int256/arithmetic.gno | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/examples/gno.land/p/demo/int256/arithmetic.gno b/examples/gno.land/p/demo/int256/arithmetic.gno index d44b37b8537..8926fe1d6de 100644 --- a/examples/gno.land/p/demo/int256/arithmetic.gno +++ b/examples/gno.land/p/demo/int256/arithmetic.gno @@ -10,21 +10,18 @@ func (z *Int) Add(x, y *Int) *Int { z.abs.Add(x.abs, y.abs) z.neg = x.neg } else { - // If signs are different, subtract the smaller absolute value from the larger - if x.abs.Cmp(y.abs) >= 0 { + switch x.abs.Cmp(y.abs) { + case 1: // x > y z.abs.Sub(x.abs, y.abs) z.neg = x.neg - } else { + case -1: // x < y z.abs.Sub(y.abs, x.abs) z.neg = y.neg + case 0: // x == y + z.abs = uint256.NewUint(0) } } - // Ensure zero is always positive - if z.abs.IsZero() { - z.neg = false - } - return z } @@ -74,13 +71,15 @@ func (z *Int) Sub(x, y *Int) *Int { z.abs.Add(x.abs, y.abs) z.neg = x.neg } else { - // If signs are the same, subtract the smaller absolute value from the larger - if x.abs.Cmp(y.abs) >= 0 { - z.abs = z.abs.Sub(x.abs, y.abs) + switch x.abs.Cmp(y.abs) { + case 1: // x > y + z.abs.Sub(x.abs, y.abs) z.neg = x.neg - } else { + case -1: // x < y z.abs.Sub(y.abs, x.abs) z.neg = !x.neg + case 0: // x == y + z.abs = uint256.NewUint(0) } }