if x.form == finite && y.form == finite {
// x + y (common case)
+
+ // Below we set z.neg = x.neg, and when z aliases y this will
+ // change the y operand's sign. This is fine, because if an
+ // operand aliases the receiver it'll be overwritten, but we still
+ // want the original x.neg and y.neg values when we evaluate
+ // x.neg != y.neg, so we need to save y.neg before setting z.neg.
+ yneg := y.neg
+
z.neg = x.neg
- if x.neg == y.neg {
+ if x.neg == yneg {
// x + y == x + y
// (-x) + (-y) == -(x + y)
z.uadd(x, y)
if x.form == finite && y.form == finite {
// x - y (common case)
+ yneg := y.neg
z.neg = x.neg
- if x.neg != y.neg {
+ if x.neg != yneg {
// x - (-y) == x + y
// (-x) - y == -(x + y)
z.uadd(x, y)
}
}
+func TestIssue20490(t *testing.T) {
+ var tests = []struct {
+ a, b float64
+ }{
+ {4, 1},
+ {-4, 1},
+ {4, -1},
+ {-4, -1},
+ }
+
+ for _, test := range tests {
+ a, b := NewFloat(test.a), NewFloat(test.b)
+ diff := new(Float).Sub(a, b)
+ b.Sub(a, b)
+ if b.Cmp(diff) != 0 {
+ t.Errorf("got %g - %g = %g; want %g\n", a, NewFloat(test.b), b, diff)
+ }
+
+ b = NewFloat(test.b)
+ sum := new(Float).Add(a, b)
+ b.Add(a, b)
+ if b.Cmp(sum) != 0 {
+ t.Errorf("got %g + %g = %g; want %g\n", a, NewFloat(test.b), b, sum)
+ }
+
+ }
+}
+
// TestFloatMul tests Float.Mul/Quo by comparing the result of a "manual"
// multiplication/division of arguments represented by Bits values with the
// respective Float multiplication/division for a variety of precisions