aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoralandonovan <adonovan@google.com>2020-10-06 17:39:52 -0400
committerGitHub <noreply@github.com>2020-10-06 17:39:52 -0400
commit227f4aabceb5ac8b1bfeb1e8cc1badee996704f4 (patch)
treeb0907eacbdc92ee864a051ea1d76a46e195b282c
parent88a10930eb75e9ec92aea441058f24a11184bb2f (diff)
downloadstarlark-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.go3
-rw-r--r--starlark/testdata/float.star8
-rw-r--r--starlark/value.go8
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) {