Skip to content

Commit

Permalink
lang/funcs: use big.Float for floor/ceil
Browse files Browse the repository at this point in the history
This avoids the loss of precision from converting to float64.
  • Loading branch information
jbardin committed Jul 6, 2021
1 parent 47a7961 commit 924d9fc
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 12 deletions.
38 changes: 26 additions & 12 deletions cty/function/stdlib/number.go
Original file line number Diff line number Diff line change
Expand Up @@ -371,14 +371,21 @@ var CeilFunc = function.New(&function.Spec{
},
Type: function.StaticReturnType(cty.Number),
Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
var val float64
if err := gocty.FromCtyValue(args[0], &val); err != nil {
return cty.UnknownVal(cty.String), err
f := args[0].AsBigFloat()

if f.IsInf() {
return cty.NumberVal(f), nil
}
if math.IsInf(val, 0) {
return cty.NumberFloatVal(val), nil

i, acc := f.Int(nil)
switch acc {
case big.Exact, big.Above:
// Done.
case big.Below:
i.Add(i, big.NewInt(1))
}
return cty.NumberIntVal(int64(math.Ceil(val))), nil

return cty.NumberVal(f.SetInt(i)), nil
},
})

Expand All @@ -393,14 +400,21 @@ var FloorFunc = function.New(&function.Spec{
},
Type: function.StaticReturnType(cty.Number),
Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
var val float64
if err := gocty.FromCtyValue(args[0], &val); err != nil {
return cty.UnknownVal(cty.String), err
f := args[0].AsBigFloat()

if f.IsInf() {
return cty.NumberVal(f), nil
}
if math.IsInf(val, 0) {
return cty.NumberFloatVal(val), nil

i, acc := f.Int(nil)
switch acc {
case big.Exact, big.Below:
// Done.
case big.Above:
i.Sub(i, big.NewInt(1))
}
return cty.NumberIntVal(int64(math.Floor(val))), nil

return cty.NumberVal(f.SetInt(i)), nil
},
})

Expand Down
20 changes: 20 additions & 0 deletions cty/function/stdlib/number_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -817,6 +817,16 @@ func TestCeil(t *testing.T) {
cty.NumberFloatVal(math.Inf(-1)),
false,
},
{
cty.MustParseNumberVal("99999999999999999999999999999999999999999999999999998.123"),
cty.MustParseNumberVal("99999999999999999999999999999999999999999999999999999"),
false,
},
{
cty.MustParseNumberVal("-99999999999999999999999999999999999999999999999999998.123"),
cty.MustParseNumberVal("-99999999999999999999999999999999999999999999999999998"),
false,
},
}

for _, test := range tests {
Expand Down Expand Up @@ -865,6 +875,16 @@ func TestFloor(t *testing.T) {
cty.NumberFloatVal(math.Inf(-1)),
false,
},
{
cty.MustParseNumberVal("99999999999999999999999999999999999999999999999999999.123"),
cty.MustParseNumberVal("99999999999999999999999999999999999999999999999999999"),
false,
},
{
cty.MustParseNumberVal("-99999999999999999999999999999999999999999999999999998.123"),
cty.MustParseNumberVal("-99999999999999999999999999999999999999999999999999999"),
false,
},
}

for _, test := range tests {
Expand Down

0 comments on commit 924d9fc

Please sign in to comment.