diff --git a/pkg/util/assert/assert.go b/pkg/util/assert/assert.go index 89338b462..19cf6e062 100644 --- a/pkg/util/assert/assert.go +++ b/pkg/util/assert/assert.go @@ -77,3 +77,33 @@ func asInt64(x any) (int64, bool) { return 0, false } + +// True errors if condition is false. +func True(t *testing.T, condition bool, msg ...any) { + if condition { + return + } + + t.Errorf("condition is false") + + if len(msg) != 0 { + t.Errorf(msg[0].(string), msg[1:]...) + } + + t.FailNow() +} + +// False errors if condition is true. +func False(t *testing.T, condition bool, msg ...any) { + if !condition { + return + } + + t.Errorf("condition is true") + + if len(msg) != 0 { + t.Errorf(msg[0].(string), msg[1:]...) + } + + t.FailNow() +} diff --git a/pkg/util/field/gf251/element.go b/pkg/util/field/gf251/element.go index 263913782..7f4ff21e4 100644 --- a/pkg/util/field/gf251/element.go +++ b/pkg/util/field/gf251/element.go @@ -28,7 +28,8 @@ type Element [1]uint32 // defined as an array to prevent mistaken use of arithme const ( r = 1 << 32 // register size modulus = 251 - rSq = 69 // r² (mod m) + rModM = 123 + rSqModM = 69 // r² (mod m) negModulusInvModR = 1711142349 // -modulus⁻¹ (mod r), used for Montgomery reduction nbBytes = 2 ) @@ -71,7 +72,7 @@ func montgomeryReduce(x uint64) Element { // AddUint32 x + y func (x Element) AddUint32(y uint32) Element { - return x.Add(NewElement(y)) + return x.Add(New(y)) } // ToUint32 returns the numerical (non-Montgomery) @@ -85,9 +86,9 @@ func (x Element) Mul(y Element) Element { return montgomeryReduce(uint64(x[0]) * uint64(y[0])) } -// NewElement returns an element of the field f corresponding to the natural number x. -func NewElement(x uint32) Element { - return Element{uint32(uint64(x) << 32 % modulus)} +// New returns an element of the field f corresponding to the natural number x. +func New(x uint32) Element { + return Element{x}.Mul(Element{rSqModM}) } // Cmp compares the numerical values of x and y. @@ -121,7 +122,7 @@ func (x Element) Inverse() Element { var c Element // Since x actually contains x.R, we have to multiply the result by R² to get x⁻¹R⁻¹R² = x⁻¹R. - b := Element{rSq} + b := Element{rSqModM} for (u != 1) && (v != 1) { for u%2 == 0 { @@ -179,5 +180,13 @@ func (x Element) AddBytes(b []byte) Element { for i := range nbBytes { v |= uint32(b[i]) << ((nbBytes - 1 - i) * 8) } - return x.Add(NewElement(v)) + return x.Add(New(v)) +} + +func (x Element) IsZero() bool { + return x[0] == 0 +} + +func (x Element) IsOne() bool { + return x[0] == rModM } diff --git a/pkg/util/field/gf251/element_test.go b/pkg/util/field/gf251/element_test.go index bb9242ada..be01f350e 100644 --- a/pkg/util/field/gf251/element_test.go +++ b/pkg/util/field/gf251/element_test.go @@ -38,8 +38,8 @@ func TestMul(t *testing.T) { Lsh(&i, 32). Mod(&i, &m) - x := NewElement(a) - y := NewElement(b) + x := New(a) + y := New(b) x = x.Mul(y) @@ -60,7 +60,7 @@ func TestInverse(t *testing.T) { Lsh(&i, 32). // Montgomery form Mod(&i, &m) - x := NewElement(a) + x := New(a) x = x.Inverse() assert.Equal(t, i.Uint64(), x[0], "inverse of %d", a) @@ -74,7 +74,7 @@ func TestHalve(t *testing.T) { for range 1000000 { a := rand.Uint32N(modulus) - x := NewElement(a) + x := New(a) x = x.Half() i.SetUint64(uint64(x[0])).Add(&i, &i).Mod(&i, &m) // (a/2) as computed, multiplied by 2 @@ -98,8 +98,8 @@ func TestSub(t *testing.T) { Lsh(&i, 32). Mod(&i, &m) - x := NewElement(a) - y := NewElement(b) + x := New(a) + y := New(b) x = x.Sub(y) @@ -112,7 +112,7 @@ func TestMontgomery(t *testing.T) { i := big.NewInt(1 << 32) i.Mod(i, m) - x := NewElement(1) + x := New(1) assert.Equal(t, i.Uint64(), x[0]) x = montgomeryReduce(uint64(x[0])) @@ -128,9 +128,24 @@ func TestByteConversion(t *testing.T) { // bytes to element x := Element{}.AddBytes(expectedB) - assert.Equal(t, NewElement(a), x) + assert.Equal(t, New(a), x) // element to bytes assert.Equal(t, expectedB, x.Bytes()) } } + +func TestZeroOne(t *testing.T) { + zero := New(0) + one := New(1) + + assert.True(t, zero.IsZero()) + assert.False(t, one.IsZero()) + assert.False(t, zero.IsOne()) + assert.True(t, one.IsOne()) + + assert.Equal(t, zero, zero.Add(zero)) + assert.Equal(t, one, zero.Add(one)) + assert.Equal(t, one, one.Mul(one)) + assert.Equal(t, zero, one.Mul(zero)) +} diff --git a/pkg/util/field/gf8209/element.go b/pkg/util/field/gf8209/element.go index b12e9c498..85c1f8105 100644 --- a/pkg/util/field/gf8209/element.go +++ b/pkg/util/field/gf8209/element.go @@ -28,7 +28,8 @@ type Element [1]uint32 // defined as an array to prevent mistaken use of arithme const ( r = 1 << 32 // register size modulus = 8209 - rSq = 150 // r² (mod m) + rModM = 2078 + rSqModM = 150 // r² (mod m) negModulusInvModR = 1667968783 // -modulus⁻¹ (mod r), used for Montgomery reduction nbBytes = 2 ) @@ -71,7 +72,7 @@ func montgomeryReduce(x uint64) Element { // AddUint32 x + y func (x Element) AddUint32(y uint32) Element { - return x.Add(NewElement(y)) + return x.Add(New(y)) } // ToUint32 returns the numerical (non-Montgomery) @@ -85,9 +86,9 @@ func (x Element) Mul(y Element) Element { return montgomeryReduce(uint64(x[0]) * uint64(y[0])) } -// NewElement returns an element of the field f corresponding to the natural number x. -func NewElement(x uint32) Element { - return Element{uint32(uint64(x) << 32 % modulus)} +// New returns an element of the field f corresponding to the natural number x. +func New(x uint32) Element { + return Element{x}.Mul(Element{rSqModM}) } // Cmp compares the numerical values of x and y. @@ -121,7 +122,7 @@ func (x Element) Inverse() Element { var c Element // Since x actually contains x.R, we have to multiply the result by R² to get x⁻¹R⁻¹R² = x⁻¹R. - b := Element{rSq} + b := Element{rSqModM} for (u != 1) && (v != 1) { for u%2 == 0 { @@ -179,5 +180,13 @@ func (x Element) AddBytes(b []byte) Element { for i := range nbBytes { v |= uint32(b[i]) << ((nbBytes - 1 - i) * 8) } - return x.Add(NewElement(v)) + return x.Add(New(v)) +} + +func (x Element) IsZero() bool { + return x[0] == 0 +} + +func (x Element) IsOne() bool { + return x[0] == rModM } diff --git a/pkg/util/field/gf8209/element_test.go b/pkg/util/field/gf8209/element_test.go index 53b9ece65..3c362780a 100644 --- a/pkg/util/field/gf8209/element_test.go +++ b/pkg/util/field/gf8209/element_test.go @@ -38,8 +38,8 @@ func TestMul(t *testing.T) { Lsh(&i, 32). Mod(&i, &m) - x := NewElement(a) - y := NewElement(b) + x := New(a) + y := New(b) x = x.Mul(y) @@ -60,7 +60,7 @@ func TestInverse(t *testing.T) { Lsh(&i, 32). // Montgomery form Mod(&i, &m) - x := NewElement(a) + x := New(a) x = x.Inverse() assert.Equal(t, i.Uint64(), x[0], "inverse of %d", a) @@ -74,7 +74,7 @@ func TestHalve(t *testing.T) { for range 1000000 { a := rand.Uint32N(modulus) - x := NewElement(a) + x := New(a) x = x.Half() i.SetUint64(uint64(x[0])).Add(&i, &i).Mod(&i, &m) // (a/2) as computed, multiplied by 2 @@ -98,8 +98,8 @@ func TestSub(t *testing.T) { Lsh(&i, 32). Mod(&i, &m) - x := NewElement(a) - y := NewElement(b) + x := New(a) + y := New(b) x = x.Sub(y) @@ -112,7 +112,7 @@ func TestMontgomery(t *testing.T) { i := big.NewInt(1 << 32) i.Mod(i, m) - x := NewElement(1) + x := New(1) assert.Equal(t, i.Uint64(), x[0]) x = montgomeryReduce(uint64(x[0])) @@ -128,9 +128,24 @@ func TestByteConversion(t *testing.T) { // bytes to element x := Element{}.AddBytes(expectedB) - assert.Equal(t, NewElement(a), x) + assert.Equal(t, New(a), x) // element to bytes assert.Equal(t, expectedB, x.Bytes()) } } + +func TestZeroOne(t *testing.T) { + zero := New(0) + one := New(1) + + assert.True(t, zero.IsZero()) + assert.False(t, one.IsZero()) + assert.False(t, zero.IsOne()) + assert.True(t, one.IsOne()) + + assert.Equal(t, zero, zero.Add(zero)) + assert.Equal(t, one, zero.Add(one)) + assert.Equal(t, one, one.Mul(one)) + assert.Equal(t, zero, one.Mul(zero)) +} diff --git a/pkg/util/field/interface.go b/pkg/util/field/interface.go index 97020c65c..5b22f0c5b 100644 --- a/pkg/util/field/interface.go +++ b/pkg/util/field/interface.go @@ -17,4 +17,6 @@ type Element[Operand any] interface { AddBytes([]byte) Operand // AddBytes adds Element to the given big-endian value, with a strict length requirement. fmt.Stringer Text(base int) string // Text returns the numerical value of x in the given base. + IsZero() bool + IsOne() bool } diff --git a/pkg/util/field/interface_test.go b/pkg/util/field/interface_test.go new file mode 100644 index 000000000..8fd8e99ac --- /dev/null +++ b/pkg/util/field/interface_test.go @@ -0,0 +1,12 @@ +package field + +import ( + bls12_377 "github.com/consensys/go-corset/pkg/util/field/bls12-377" + "github.com/consensys/go-corset/pkg/util/field/koalabear" +) + +func init() { + // make sure the interface is adhered to. + _ = Element[koalabear.Element](koalabear.Element{}) + _ = Element[bls12_377.Element](bls12_377.Element{}) +} diff --git a/pkg/util/field/internal/generator/main.go b/pkg/util/field/internal/generator/main.go index 147a217f7..774b14fad 100644 --- a/pkg/util/field/internal/generator/main.go +++ b/pkg/util/field/internal/generator/main.go @@ -63,7 +63,8 @@ type fieldSpecs struct { type fieldConfig struct { fieldSpecs - RSq uint32 + RSqModM uint32 + RModM uint32 NegModulusInvModR uint32 } @@ -83,11 +84,13 @@ func (f fieldSpecs) config() (*fieldConfig, error) { var x big.Int - x.Mod(r, m). - Mul(&x, &x). + x.Mod(r, m) + specs.RModM = uint32(x.Uint64()) + + x.Mul(&x, &x). Mod(&x, m) - specs.RSq = uint32(x.Uint64()) + specs.RSqModM = uint32(x.Uint64()) x.ModInverse(m, r) specs.NegModulusInvModR = uint32(R - x.Uint64()) diff --git a/pkg/util/field/internal/generator/templates/element.go.tmpl b/pkg/util/field/internal/generator/templates/element.go.tmpl index 7960c0b35..81cb02d1c 100644 --- a/pkg/util/field/internal/generator/templates/element.go.tmpl +++ b/pkg/util/field/internal/generator/templates/element.go.tmpl @@ -14,7 +14,8 @@ type Element [1]uint32 // defined as an array to prevent mistaken use of arithme const ( r = 1 << 32 // register size modulus = {{ .Modulus }} - rSq = {{ .RSq }} // r² (mod m) + rModM = {{ .RModM }} + rSqModM = {{ .RSqModM }} // r² (mod m) negModulusInvModR = {{ .NegModulusInvModR }} // -modulus⁻¹ (mod r), used for Montgomery reduction nbBytes = {{ $nbBytes }} ) @@ -57,7 +58,7 @@ func montgomeryReduce(x uint64) Element { // AddUint32 x + y func (x Element) AddUint32(y uint32) Element { - return x.Add(NewElement(y)) + return x.Add(New(y)) } // ToUint32 returns the numerical (non-Montgomery) @@ -71,9 +72,9 @@ func (x Element) Mul(y Element) Element { return montgomeryReduce(uint64(x[0]) * uint64(y[0])) } -// NewElement returns an element of the field f corresponding to the natural number x. -func NewElement(x uint32) Element { - return Element{uint32(uint64(x) << 32 % modulus)} +// New returns an element of the field f corresponding to the natural number x. +func New(x uint32) Element { + return Element{x}.Mul(Element{rSqModM}) } // Cmp compares the numerical values of x and y. @@ -107,7 +108,7 @@ func (x Element) Inverse() Element { var c Element // Since x actually contains x.R, we have to multiply the result by R² to get x⁻¹R⁻¹R² = x⁻¹R. - b := Element{rSq} + b := Element{rSqModM} for (u != 1) && (v != 1) { for u%2 == 0 { @@ -167,5 +168,13 @@ func (x Element) AddBytes(b []byte) Element { for i := range nbBytes { v |= uint32(b[i]) << ((nbBytes - 1 - i)*8) } - return x.Add(NewElement(v)) + return x.Add(New(v)) +} + +func (x Element) IsZero() bool { + return x[0] == 0 +} + +func (x Element) IsOne() bool { + return x[0] == rModM } diff --git a/pkg/util/field/internal/generator/templates/element.test.go.tmpl b/pkg/util/field/internal/generator/templates/element.test.go.tmpl index 7c78d469a..4160f588e 100644 --- a/pkg/util/field/internal/generator/templates/element.test.go.tmpl +++ b/pkg/util/field/internal/generator/templates/element.test.go.tmpl @@ -20,8 +20,8 @@ func TestMul(t *testing.T) { Lsh(&i, 32). Mod(&i, &m) - x := NewElement(a) - y := NewElement(b) + x := New(a) + y := New(b) x = x.Mul(y) @@ -42,7 +42,7 @@ func TestInverse(t *testing.T) { Lsh(&i, 32). // Montgomery form Mod(&i, &m) - x := NewElement(a) + x := New(a) x = x.Inverse() assert.Equal(t, i.Uint64(), x[0], "inverse of %d", a) @@ -56,7 +56,7 @@ func TestHalve(t *testing.T) { for range 1000000 { a := rand.Uint32N(modulus) - x := NewElement(a) + x := New(a) x = x.Half() i.SetUint64(uint64(x[0])).Add(&i, &i).Mod(&i, &m) // (a/2) as computed, multiplied by 2 @@ -80,8 +80,8 @@ func TestSub(t *testing.T) { Lsh(&i, 32). Mod(&i, &m) - x := NewElement(a) - y := NewElement(b) + x := New(a) + y := New(b) x = x.Sub(y) @@ -94,7 +94,7 @@ func TestMontgomery(t *testing.T) { i := big.NewInt(1 << 32) i.Mod(i, m) - x := NewElement(1) + x := New(1) assert.Equal(t, i.Uint64(), x[0]) x = montgomeryReduce(uint64(x[0])) @@ -110,9 +110,24 @@ func TestByteConversion(t *testing.T) { // bytes to element x := Element{}.AddBytes(expectedB) - assert.Equal(t, NewElement(a), x) + assert.Equal(t, New(a), x) // element to bytes assert.Equal(t, expectedB, x.Bytes()) } } + +func TestZeroOne(t *testing.T) { + zero := New(0) + one := New(1) + + assert.True(t, zero.IsZero()) + assert.False(t, one.IsZero()) + assert.False(t, zero.IsOne()) + assert.True(t, one.IsOne()) + + assert.Equal(t, zero, zero.Add(zero)) + assert.Equal(t, one, zero.Add(one)) + assert.Equal(t, one, one.Mul(one)) + assert.Equal(t, zero, one.Mul(zero)) +} diff --git a/pkg/util/field/koalabear/element.go b/pkg/util/field/koalabear/element.go index cd9da146d..17d77e982 100644 --- a/pkg/util/field/koalabear/element.go +++ b/pkg/util/field/koalabear/element.go @@ -28,7 +28,8 @@ type Element [1]uint32 // defined as an array to prevent mistaken use of arithme const ( r = 1 << 32 // register size modulus = 2130706433 - rSq = 402124772 // r² (mod m) + rModM = 33554430 + rSqModM = 402124772 // r² (mod m) negModulusInvModR = 2130706431 // -modulus⁻¹ (mod r), used for Montgomery reduction nbBytes = 4 ) @@ -71,7 +72,7 @@ func montgomeryReduce(x uint64) Element { // AddUint32 x + y func (x Element) AddUint32(y uint32) Element { - return x.Add(NewElement(y)) + return x.Add(New(y)) } // ToUint32 returns the numerical (non-Montgomery) @@ -85,9 +86,9 @@ func (x Element) Mul(y Element) Element { return montgomeryReduce(uint64(x[0]) * uint64(y[0])) } -// NewElement returns an element of the field f corresponding to the natural number x. -func NewElement(x uint32) Element { - return Element{uint32(uint64(x) << 32 % modulus)} +// New returns an element of the field f corresponding to the natural number x. +func New(x uint32) Element { + return Element{x}.Mul(Element{rSqModM}) } // Cmp compares the numerical values of x and y. @@ -121,7 +122,7 @@ func (x Element) Inverse() Element { var c Element // Since x actually contains x.R, we have to multiply the result by R² to get x⁻¹R⁻¹R² = x⁻¹R. - b := Element{rSq} + b := Element{rSqModM} for (u != 1) && (v != 1) { for u%2 == 0 { @@ -179,5 +180,13 @@ func (x Element) AddBytes(b []byte) Element { for i := range nbBytes { v |= uint32(b[i]) << ((nbBytes - 1 - i) * 8) } - return x.Add(NewElement(v)) + return x.Add(New(v)) +} + +func (x Element) IsZero() bool { + return x[0] == 0 +} + +func (x Element) IsOne() bool { + return x[0] == rModM } diff --git a/pkg/util/field/koalabear/element_test.go b/pkg/util/field/koalabear/element_test.go index f75a206f4..d20ffd93e 100644 --- a/pkg/util/field/koalabear/element_test.go +++ b/pkg/util/field/koalabear/element_test.go @@ -38,8 +38,8 @@ func TestMul(t *testing.T) { Lsh(&i, 32). Mod(&i, &m) - x := NewElement(a) - y := NewElement(b) + x := New(a) + y := New(b) x = x.Mul(y) @@ -60,7 +60,7 @@ func TestInverse(t *testing.T) { Lsh(&i, 32). // Montgomery form Mod(&i, &m) - x := NewElement(a) + x := New(a) x = x.Inverse() assert.Equal(t, i.Uint64(), x[0], "inverse of %d", a) @@ -74,7 +74,7 @@ func TestHalve(t *testing.T) { for range 1000000 { a := rand.Uint32N(modulus) - x := NewElement(a) + x := New(a) x = x.Half() i.SetUint64(uint64(x[0])).Add(&i, &i).Mod(&i, &m) // (a/2) as computed, multiplied by 2 @@ -98,8 +98,8 @@ func TestSub(t *testing.T) { Lsh(&i, 32). Mod(&i, &m) - x := NewElement(a) - y := NewElement(b) + x := New(a) + y := New(b) x = x.Sub(y) @@ -112,7 +112,7 @@ func TestMontgomery(t *testing.T) { i := big.NewInt(1 << 32) i.Mod(i, m) - x := NewElement(1) + x := New(1) assert.Equal(t, i.Uint64(), x[0]) x = montgomeryReduce(uint64(x[0])) @@ -128,9 +128,24 @@ func TestByteConversion(t *testing.T) { // bytes to element x := Element{}.AddBytes(expectedB) - assert.Equal(t, NewElement(a), x) + assert.Equal(t, New(a), x) // element to bytes assert.Equal(t, expectedB, x.Bytes()) } } + +func TestZeroOne(t *testing.T) { + zero := New(0) + one := New(1) + + assert.True(t, zero.IsZero()) + assert.False(t, one.IsZero()) + assert.False(t, zero.IsOne()) + assert.True(t, one.IsOne()) + + assert.Equal(t, zero, zero.Add(zero)) + assert.Equal(t, one, zero.Add(one)) + assert.Equal(t, one, one.Mul(one)) + assert.Equal(t, zero, one.Mul(zero)) +} diff --git a/pkg/util/field/mersenne31/element.go b/pkg/util/field/mersenne31/element.go index 38eccd6d2..71de72322 100644 --- a/pkg/util/field/mersenne31/element.go +++ b/pkg/util/field/mersenne31/element.go @@ -28,7 +28,8 @@ type Element [1]uint32 // defined as an array to prevent mistaken use of arithme const ( r = 1 << 32 // register size modulus = 2147483647 - rSq = 4 // r² (mod m) + rModM = 2 + rSqModM = 4 // r² (mod m) negModulusInvModR = 2147483649 // -modulus⁻¹ (mod r), used for Montgomery reduction nbBytes = 4 ) @@ -71,7 +72,7 @@ func montgomeryReduce(x uint64) Element { // AddUint32 x + y func (x Element) AddUint32(y uint32) Element { - return x.Add(NewElement(y)) + return x.Add(New(y)) } // ToUint32 returns the numerical (non-Montgomery) @@ -85,9 +86,9 @@ func (x Element) Mul(y Element) Element { return montgomeryReduce(uint64(x[0]) * uint64(y[0])) } -// NewElement returns an element of the field f corresponding to the natural number x. -func NewElement(x uint32) Element { - return Element{uint32(uint64(x) << 32 % modulus)} +// New returns an element of the field f corresponding to the natural number x. +func New(x uint32) Element { + return Element{x}.Mul(Element{rSqModM}) } // Cmp compares the numerical values of x and y. @@ -121,7 +122,7 @@ func (x Element) Inverse() Element { var c Element // Since x actually contains x.R, we have to multiply the result by R² to get x⁻¹R⁻¹R² = x⁻¹R. - b := Element{rSq} + b := Element{rSqModM} for (u != 1) && (v != 1) { for u%2 == 0 { @@ -179,5 +180,13 @@ func (x Element) AddBytes(b []byte) Element { for i := range nbBytes { v |= uint32(b[i]) << ((nbBytes - 1 - i) * 8) } - return x.Add(NewElement(v)) + return x.Add(New(v)) +} + +func (x Element) IsZero() bool { + return x[0] == 0 +} + +func (x Element) IsOne() bool { + return x[0] == rModM } diff --git a/pkg/util/field/mersenne31/element_test.go b/pkg/util/field/mersenne31/element_test.go index 79f585541..e978b3f3f 100644 --- a/pkg/util/field/mersenne31/element_test.go +++ b/pkg/util/field/mersenne31/element_test.go @@ -38,8 +38,8 @@ func TestMul(t *testing.T) { Lsh(&i, 32). Mod(&i, &m) - x := NewElement(a) - y := NewElement(b) + x := New(a) + y := New(b) x = x.Mul(y) @@ -60,7 +60,7 @@ func TestInverse(t *testing.T) { Lsh(&i, 32). // Montgomery form Mod(&i, &m) - x := NewElement(a) + x := New(a) x = x.Inverse() assert.Equal(t, i.Uint64(), x[0], "inverse of %d", a) @@ -74,7 +74,7 @@ func TestHalve(t *testing.T) { for range 1000000 { a := rand.Uint32N(modulus) - x := NewElement(a) + x := New(a) x = x.Half() i.SetUint64(uint64(x[0])).Add(&i, &i).Mod(&i, &m) // (a/2) as computed, multiplied by 2 @@ -98,8 +98,8 @@ func TestSub(t *testing.T) { Lsh(&i, 32). Mod(&i, &m) - x := NewElement(a) - y := NewElement(b) + x := New(a) + y := New(b) x = x.Sub(y) @@ -112,7 +112,7 @@ func TestMontgomery(t *testing.T) { i := big.NewInt(1 << 32) i.Mod(i, m) - x := NewElement(1) + x := New(1) assert.Equal(t, i.Uint64(), x[0]) x = montgomeryReduce(uint64(x[0])) @@ -128,9 +128,24 @@ func TestByteConversion(t *testing.T) { // bytes to element x := Element{}.AddBytes(expectedB) - assert.Equal(t, NewElement(a), x) + assert.Equal(t, New(a), x) // element to bytes assert.Equal(t, expectedB, x.Bytes()) } } + +func TestZeroOne(t *testing.T) { + zero := New(0) + one := New(1) + + assert.True(t, zero.IsZero()) + assert.False(t, one.IsZero()) + assert.False(t, zero.IsOne()) + assert.True(t, one.IsOne()) + + assert.Equal(t, zero, zero.Add(zero)) + assert.Equal(t, one, zero.Add(one)) + assert.Equal(t, one, one.Mul(one)) + assert.Equal(t, zero, one.Mul(zero)) +}