Skip to content

Commit e486b12

Browse files
committed
Allow 1 ULP of error in GDA tests
In the GDA arithmetic specification, exp, ln, log10 and power operations may be up to 1 ulp (unit in last place) in error.
1 parent 88212e6 commit e486b12

1 file changed

Lines changed: 38 additions & 8 deletions

File tree

dectest/test.go

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"os"
77
"reflect"
88
"strconv"
9+
"strings"
910
"testing"
1011

1112
"github.com/ericlagergren/decimal"
@@ -277,15 +278,15 @@ got : %v
277278
func check(t *testing.T, z, r *decimal.Big, c *Case, flags decimal.Condition) {
278279
helper(t)()
279280
if !equal(z, r) {
280-
str := fmt.Sprintf(`%s
281-
wanted: %q (%s:%d)
282-
got : %q (%s:%d)
283-
`,
281+
s := []string{
284282
c.ShortString(10000),
285-
r, flags, -r.Scale(),
286-
z, z.Context.Conditions, -z.Scale(),
287-
)
288-
t.Log(str)
283+
fmt.Sprintf("wanted: %q (%s:%d)", r, flags, -r.Scale()),
284+
fmt.Sprintf("got : %q (%s:%d)", z, z.Context.Conditions, -z.Scale()),
285+
}
286+
if allow1ULPError[c.Op] && equalWithin1ULP(z, r) {
287+
s = append(s, "passed within 1 ULP")
288+
}
289+
t.Log(strings.Join(s, "\n"), "\n")
289290
}
290291
}
291292

@@ -321,6 +322,35 @@ func equal(x, y *decimal.Big) bool {
321322
return cmp && scl && prec
322323
}
323324

325+
func equalWithin1ULP(x, y *decimal.Big) bool {
326+
if !x.IsFinite() || !y.IsFinite() {
327+
return false
328+
}
329+
formX, negX, coeffX, expX := x.Decompose(make([]byte, 2<<3))
330+
formY, negY, coeffY, expY := y.Decompose(make([]byte, 2<<3))
331+
if formX != formY || negX != negY || expX != expY {
332+
return false
333+
}
334+
l := len(coeffX)
335+
if len(coeffY) != l {
336+
return false
337+
}
338+
for i := 0; i < l-1; i++ {
339+
if coeffX[i] != coeffY[i] {
340+
return false
341+
}
342+
}
343+
d := coeffX[l-1] - coeffY[l-1]
344+
return d == 0x01 || d == 0xff
345+
}
346+
347+
var allow1ULPError = map[Op]bool{
348+
Exp: true,
349+
Ln: true,
350+
Log10: true,
351+
Power: true,
352+
}
353+
324354
// helper returns testing.T.Helper, if it exists.
325355
func helper(v interface{}) func() {
326356
if fn, ok := v.(interface {

0 commit comments

Comments
 (0)