diff --git a/scalar.go b/scalar.go index ac080a9..d9cd49b 100644 --- a/scalar.go +++ b/scalar.go @@ -40,9 +40,12 @@ func NewScalar() *Scalar { return &Scalar{} } -// MultiplyAdd sets s = x * y + z mod l, and returns s. DEPRECATED. Use the individual Add and Multiply methods instead. +// MultiplyAdd sets s = x * y + z mod l, and returns s. It is equivalent to +// using Multiply and then Add. func (s *Scalar) MultiplyAdd(x, y, z *Scalar) *Scalar { - return s.Multiply(x, y).Add(s, z) + // Make a copy of z in case it aliases s. + zCopy := new(Scalar).Set(z) + return s.Multiply(x, y).Add(s, zCopy) } // Add sets s = x + y mod l, and returns s. diff --git a/scalar_alias_test.go b/scalar_alias_test.go index 4766202..ef384bf 100644 --- a/scalar_alias_test.go +++ b/scalar_alias_test.go @@ -75,6 +75,9 @@ func TestScalarAliasing(t *testing.T) { "Negate": func(v, x Scalar) bool { return checkAliasingOneArg((*Scalar).Negate, v, x) }, + "Invert": func(v, x Scalar) bool { + return checkAliasingOneArg((*Scalar).Invert, v, x) + }, "Multiply": func(v, x, y Scalar) bool { return checkAliasingTwoArgs((*Scalar).Multiply, v, x, y) }, @@ -84,6 +87,21 @@ func TestScalarAliasing(t *testing.T) { "Subtract": func(v, x, y Scalar) bool { return checkAliasingTwoArgs((*Scalar).Subtract, v, x, y) }, + "MultiplyAdd1": func(v, x, y, fixed Scalar) bool { + return checkAliasingTwoArgs(func(v, x, y *Scalar) *Scalar { + return v.MultiplyAdd(&fixed, x, y) + }, v, x, y) + }, + "MultiplyAdd2": func(v, x, y, fixed Scalar) bool { + return checkAliasingTwoArgs(func(v, x, y *Scalar) *Scalar { + return v.MultiplyAdd(x, &fixed, y) + }, v, x, y) + }, + "MultiplyAdd3": func(v, x, y, fixed Scalar) bool { + return checkAliasingTwoArgs(func(v, x, y *Scalar) *Scalar { + return v.MultiplyAdd(x, y, &fixed) + }, v, x, y) + }, } { err := quick.Check(f, &quick.Config{MaxCountScale: 1 << 5}) if err != nil {