diff options
author | alandonovan <adonovan@google.com> | 2020-10-06 17:39:52 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-10-06 17:39:52 -0400 |
commit | 227f4aabceb5ac8b1bfeb1e8cc1badee996704f4 (patch) | |
tree | b0907eacbdc92ee864a051ea1d76a46e195b282c | |
parent | 88a10930eb75e9ec92aea441058f24a11184bb2f (diff) | |
download | starlark-go-227f4aabceb5ac8b1bfeb1e8cc1badee996704f4.tar.gz |
starlark: fix float % float bug (#308)
We had a test, but the test was wrong.
Fixes issue #307
-rw-r--r-- | starlark/eval.go | 3 | ||||
-rw-r--r-- | starlark/testdata/float.star | 8 | ||||
-rw-r--r-- | starlark/value.go | 8 |
3 files changed, 12 insertions, 7 deletions
diff --git a/starlark/eval.go b/starlark/eval.go index f52bb85..c17b8b7 100644 --- a/starlark/eval.go +++ b/starlark/eval.go @@ -9,7 +9,6 @@ import ( "io" "io/ioutil" "log" - "math" "math/big" "sort" "strings" @@ -886,7 +885,7 @@ func Binary(op syntax.Token, x, y Value) (Value, error) { if y == 0.0 { return nil, fmt.Errorf("float modulo by zero") } - return Float(math.Mod(float64(x), float64(y))), nil + return x.Mod(y), nil case Int: if y.Sign() == 0 { return nil, fmt.Errorf("float modulo by zero") diff --git a/starlark/testdata/float.star b/starlark/testdata/float.star index b54c35e..4d7a269 100644 --- a/starlark/testdata/float.star +++ b/starlark/testdata/float.star @@ -80,12 +80,12 @@ assert.fails(lambda: 1 // 0.0, "floored division by zero") # remainder assert.eq(100.0 % 8.0, 4.0) -assert.eq(100.0 % -8.0, 4.0) -assert.eq(-100.0 % 8.0, -4.0) +assert.eq(100.0 % -8.0, -4.0) +assert.eq(-100.0 % 8.0, 4.0) assert.eq(-100.0 % -8.0, -4.0) assert.eq(98.0 % 8.0, 2.0) -assert.eq(98.0 % -8.0, 2.0) -assert.eq(-98.0 % 8.0, -2.0) +assert.eq(98.0 % -8.0, -6.0) +assert.eq(-98.0 % 8.0, 6.0) assert.eq(-98.0 % -8.0, -2.0) assert.eq(2.5 % 2.0, 0.5) assert.eq(2.5 % 2, 0.5) diff --git a/starlark/value.go b/starlark/value.go index 267465f..eb0e84e 100644 --- a/starlark/value.go +++ b/starlark/value.go @@ -440,7 +440,13 @@ func AsFloat(x Value) (f float64, ok bool) { return 0, false } -func (x Float) Mod(y Float) Float { return Float(math.Mod(float64(x), float64(y))) } +func (x Float) Mod(y Float) Float { + z := Float(math.Mod(float64(x), float64(y))) + if (x < 0) != (y < 0) && z != 0 { + z += y + } + return z +} // Unary implements the operations +float and -float. func (f Float) Unary(op syntax.Token) (Value, error) { |