1// Copyright 2014 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package big
6
7import (
8	"flag"
9	"fmt"
10	"math"
11	"strconv"
12	"strings"
13	"testing"
14)
15
16// Verify that ErrNaN implements the error interface.
17var _ error = ErrNaN{}
18
19func (x *Float) uint64() uint64 {
20	u, acc := x.Uint64()
21	if acc != Exact {
22		panic(fmt.Sprintf("%s is not a uint64", x.Text('g', 10)))
23	}
24	return u
25}
26
27func (x *Float) int64() int64 {
28	i, acc := x.Int64()
29	if acc != Exact {
30		panic(fmt.Sprintf("%s is not an int64", x.Text('g', 10)))
31	}
32	return i
33}
34
35func TestFloatZeroValue(t *testing.T) {
36	// zero (uninitialized) value is a ready-to-use 0.0
37	var x Float
38	if s := x.Text('f', 1); s != "0.0" {
39		t.Errorf("zero value = %s; want 0.0", s)
40	}
41
42	// zero value has precision 0
43	if prec := x.Prec(); prec != 0 {
44		t.Errorf("prec = %d; want 0", prec)
45	}
46
47	// zero value can be used in any and all positions of binary operations
48	make := func(x int) *Float {
49		var f Float
50		if x != 0 {
51			f.SetInt64(int64(x))
52		}
53		// x == 0 translates into the zero value
54		return &f
55	}
56	for _, test := range []struct {
57		z, x, y, want int
58		opname        rune
59		op            func(z, x, y *Float) *Float
60	}{
61		{0, 0, 0, 0, '+', (*Float).Add},
62		{0, 1, 2, 3, '+', (*Float).Add},
63		{1, 2, 0, 2, '+', (*Float).Add},
64		{2, 0, 1, 1, '+', (*Float).Add},
65
66		{0, 0, 0, 0, '-', (*Float).Sub},
67		{0, 1, 2, -1, '-', (*Float).Sub},
68		{1, 2, 0, 2, '-', (*Float).Sub},
69		{2, 0, 1, -1, '-', (*Float).Sub},
70
71		{0, 0, 0, 0, '*', (*Float).Mul},
72		{0, 1, 2, 2, '*', (*Float).Mul},
73		{1, 2, 0, 0, '*', (*Float).Mul},
74		{2, 0, 1, 0, '*', (*Float).Mul},
75
76		// {0, 0, 0, 0, '/', (*Float).Quo}, // panics
77		{0, 2, 1, 2, '/', (*Float).Quo},
78		{1, 2, 0, 0, '/', (*Float).Quo}, // = +Inf
79		{2, 0, 1, 0, '/', (*Float).Quo},
80	} {
81		z := make(test.z)
82		test.op(z, make(test.x), make(test.y))
83		got := 0
84		if !z.IsInf() {
85			got = int(z.int64())
86		}
87		if got != test.want {
88			t.Errorf("%d %c %d = %d; want %d", test.x, test.opname, test.y, got, test.want)
89		}
90	}
91
92	// TODO(gri) test how precision is set for zero value results
93}
94
95func makeFloat(s string) *Float {
96	x, _, err := ParseFloat(s, 0, 1000, ToNearestEven)
97	if err != nil {
98		panic(err)
99	}
100	return x
101}
102
103func TestFloatSetPrec(t *testing.T) {
104	for _, test := range []struct {
105		x    string
106		prec uint
107		want string
108		acc  Accuracy
109	}{
110		// prec 0
111		{"0", 0, "0", Exact},
112		{"-0", 0, "-0", Exact},
113		{"-Inf", 0, "-Inf", Exact},
114		{"+Inf", 0, "+Inf", Exact},
115		{"123", 0, "0", Below},
116		{"-123", 0, "-0", Above},
117
118		// prec at upper limit
119		{"0", MaxPrec, "0", Exact},
120		{"-0", MaxPrec, "-0", Exact},
121		{"-Inf", MaxPrec, "-Inf", Exact},
122		{"+Inf", MaxPrec, "+Inf", Exact},
123
124		// just a few regular cases - general rounding is tested elsewhere
125		{"1.5", 1, "2", Above},
126		{"-1.5", 1, "-2", Below},
127		{"123", 1e6, "123", Exact},
128		{"-123", 1e6, "-123", Exact},
129	} {
130		x := makeFloat(test.x).SetPrec(test.prec)
131		prec := test.prec
132		if prec > MaxPrec {
133			prec = MaxPrec
134		}
135		if got := x.Prec(); got != prec {
136			t.Errorf("%s.SetPrec(%d).Prec() == %d; want %d", test.x, test.prec, got, prec)
137		}
138		if got, acc := x.String(), x.Acc(); got != test.want || acc != test.acc {
139			t.Errorf("%s.SetPrec(%d) = %s (%s); want %s (%s)", test.x, test.prec, got, acc, test.want, test.acc)
140		}
141	}
142}
143
144func TestFloatMinPrec(t *testing.T) {
145	const max = 100
146	for _, test := range []struct {
147		x    string
148		want uint
149	}{
150		{"0", 0},
151		{"-0", 0},
152		{"+Inf", 0},
153		{"-Inf", 0},
154		{"1", 1},
155		{"2", 1},
156		{"3", 2},
157		{"0x8001", 16},
158		{"0x8001p-1000", 16},
159		{"0x8001p+1000", 16},
160		{"0.1", max},
161	} {
162		x := makeFloat(test.x).SetPrec(max)
163		if got := x.MinPrec(); got != test.want {
164			t.Errorf("%s.MinPrec() = %d; want %d", test.x, got, test.want)
165		}
166	}
167}
168
169func TestFloatSign(t *testing.T) {
170	for _, test := range []struct {
171		x string
172		s int
173	}{
174		{"-Inf", -1},
175		{"-1", -1},
176		{"-0", 0},
177		{"+0", 0},
178		{"+1", +1},
179		{"+Inf", +1},
180	} {
181		x := makeFloat(test.x)
182		s := x.Sign()
183		if s != test.s {
184			t.Errorf("%s.Sign() = %d; want %d", test.x, s, test.s)
185		}
186	}
187}
188
189// alike(x, y) is like x.Cmp(y) == 0 but also considers the sign of 0 (0 != -0).
190func alike(x, y *Float) bool {
191	return x.Cmp(y) == 0 && x.Signbit() == y.Signbit()
192}
193
194func alike32(x, y float32) bool {
195	// we can ignore NaNs
196	return x == y && math.Signbit(float64(x)) == math.Signbit(float64(y))
197}
198
199func alike64(x, y float64) bool {
200	// we can ignore NaNs
201	return x == y && math.Signbit(x) == math.Signbit(y)
202}
203
204func TestFloatMantExp(t *testing.T) {
205	for _, test := range []struct {
206		x    string
207		mant string
208		exp  int
209	}{
210		{"0", "0", 0},
211		{"+0", "0", 0},
212		{"-0", "-0", 0},
213		{"Inf", "+Inf", 0},
214		{"+Inf", "+Inf", 0},
215		{"-Inf", "-Inf", 0},
216		{"1.5", "0.75", 1},
217		{"1.024e3", "0.5", 11},
218		{"-0.125", "-0.5", -2},
219	} {
220		x := makeFloat(test.x)
221		mant := makeFloat(test.mant)
222		m := new(Float)
223		e := x.MantExp(m)
224		if !alike(m, mant) || e != test.exp {
225			t.Errorf("%s.MantExp() = %s, %d; want %s, %d", test.x, m.Text('g', 10), e, test.mant, test.exp)
226		}
227	}
228}
229
230func TestFloatMantExpAliasing(t *testing.T) {
231	x := makeFloat("0.5p10")
232	if e := x.MantExp(x); e != 10 {
233		t.Fatalf("Float.MantExp aliasing error: got %d; want 10", e)
234	}
235	if want := makeFloat("0.5"); !alike(x, want) {
236		t.Fatalf("Float.MantExp aliasing error: got %s; want %s", x.Text('g', 10), want.Text('g', 10))
237	}
238}
239
240func TestFloatSetMantExp(t *testing.T) {
241	for _, test := range []struct {
242		frac string
243		exp  int
244		z    string
245	}{
246		{"0", 0, "0"},
247		{"+0", 0, "0"},
248		{"-0", 0, "-0"},
249		{"Inf", 1234, "+Inf"},
250		{"+Inf", -1234, "+Inf"},
251		{"-Inf", -1234, "-Inf"},
252		{"0", MinExp, "0"},
253		{"0.25", MinExp, "+0"},    // exponent underflow
254		{"-0.25", MinExp, "-0"},   // exponent underflow
255		{"1", MaxExp, "+Inf"},     // exponent overflow
256		{"2", MaxExp - 1, "+Inf"}, // exponent overflow
257		{"0.75", 1, "1.5"},
258		{"0.5", 11, "1024"},
259		{"-0.5", -2, "-0.125"},
260		{"32", 5, "1024"},
261		{"1024", -10, "1"},
262	} {
263		frac := makeFloat(test.frac)
264		want := makeFloat(test.z)
265		var z Float
266		z.SetMantExp(frac, test.exp)
267		if !alike(&z, want) {
268			t.Errorf("SetMantExp(%s, %d) = %s; want %s", test.frac, test.exp, z.Text('g', 10), test.z)
269		}
270		// test inverse property
271		mant := new(Float)
272		if z.SetMantExp(mant, want.MantExp(mant)).Cmp(want) != 0 {
273			t.Errorf("Inverse property not satisfied: got %s; want %s", z.Text('g', 10), test.z)
274		}
275	}
276}
277
278func TestFloatPredicates(t *testing.T) {
279	for _, test := range []struct {
280		x            string
281		sign         int
282		signbit, inf bool
283	}{
284		{x: "-Inf", sign: -1, signbit: true, inf: true},
285		{x: "-1", sign: -1, signbit: true},
286		{x: "-0", signbit: true},
287		{x: "0"},
288		{x: "1", sign: 1},
289		{x: "+Inf", sign: 1, inf: true},
290	} {
291		x := makeFloat(test.x)
292		if got := x.Signbit(); got != test.signbit {
293			t.Errorf("(%s).Signbit() = %v; want %v", test.x, got, test.signbit)
294		}
295		if got := x.Sign(); got != test.sign {
296			t.Errorf("(%s).Sign() = %d; want %d", test.x, got, test.sign)
297		}
298		if got := x.IsInf(); got != test.inf {
299			t.Errorf("(%s).IsInf() = %v; want %v", test.x, got, test.inf)
300		}
301	}
302}
303
304func TestFloatIsInt(t *testing.T) {
305	for _, test := range []string{
306		"0 int",
307		"-0 int",
308		"1 int",
309		"-1 int",
310		"0.5",
311		"1.23",
312		"1.23e1",
313		"1.23e2 int",
314		"0.000000001e+8",
315		"0.000000001e+9 int",
316		"1.2345e200 int",
317		"Inf",
318		"+Inf",
319		"-Inf",
320	} {
321		s := strings.TrimSuffix(test, " int")
322		want := s != test
323		if got := makeFloat(s).IsInt(); got != want {
324			t.Errorf("%s.IsInt() == %t", s, got)
325		}
326	}
327}
328
329func fromBinary(s string) int64 {
330	x, err := strconv.ParseInt(s, 2, 64)
331	if err != nil {
332		panic(err)
333	}
334	return x
335}
336
337func toBinary(x int64) string {
338	return strconv.FormatInt(x, 2)
339}
340
341func testFloatRound(t *testing.T, x, r int64, prec uint, mode RoundingMode) {
342	// verify test data
343	var ok bool
344	switch mode {
345	case ToNearestEven, ToNearestAway:
346		ok = true // nothing to do for now
347	case ToZero:
348		if x < 0 {
349			ok = r >= x
350		} else {
351			ok = r <= x
352		}
353	case AwayFromZero:
354		if x < 0 {
355			ok = r <= x
356		} else {
357			ok = r >= x
358		}
359	case ToNegativeInf:
360		ok = r <= x
361	case ToPositiveInf:
362		ok = r >= x
363	default:
364		panic("unreachable")
365	}
366	if !ok {
367		t.Fatalf("incorrect test data for prec = %d, %s: x = %s, r = %s", prec, mode, toBinary(x), toBinary(r))
368	}
369
370	// compute expected accuracy
371	a := Exact
372	switch {
373	case r < x:
374		a = Below
375	case r > x:
376		a = Above
377	}
378
379	// round
380	f := new(Float).SetMode(mode).SetInt64(x).SetPrec(prec)
381
382	// check result
383	r1 := f.int64()
384	p1 := f.Prec()
385	a1 := f.Acc()
386	if r1 != r || p1 != prec || a1 != a {
387		t.Errorf("round %s (%d bits, %s) incorrect: got %s (%d bits, %s); want %s (%d bits, %s)",
388			toBinary(x), prec, mode,
389			toBinary(r1), p1, a1,
390			toBinary(r), prec, a)
391		return
392	}
393
394	// g and f should be the same
395	// (rounding by SetPrec after SetInt64 using default precision
396	// should be the same as rounding by SetInt64 after setting the
397	// precision)
398	g := new(Float).SetMode(mode).SetPrec(prec).SetInt64(x)
399	if !alike(g, f) {
400		t.Errorf("round %s (%d bits, %s) not symmetric: got %s and %s; want %s",
401			toBinary(x), prec, mode,
402			toBinary(g.int64()),
403			toBinary(r1),
404			toBinary(r),
405		)
406		return
407	}
408
409	// h and f should be the same
410	// (repeated rounding should be idempotent)
411	h := new(Float).SetMode(mode).SetPrec(prec).Set(f)
412	if !alike(h, f) {
413		t.Errorf("round %s (%d bits, %s) not idempotent: got %s and %s; want %s",
414			toBinary(x), prec, mode,
415			toBinary(h.int64()),
416			toBinary(r1),
417			toBinary(r),
418		)
419		return
420	}
421}
422
423// TestFloatRound tests basic rounding.
424func TestFloatRound(t *testing.T) {
425	for _, test := range []struct {
426		prec                        uint
427		x, zero, neven, naway, away string // input, results rounded to prec bits
428	}{
429		{5, "1000", "1000", "1000", "1000", "1000"},
430		{5, "1001", "1001", "1001", "1001", "1001"},
431		{5, "1010", "1010", "1010", "1010", "1010"},
432		{5, "1011", "1011", "1011", "1011", "1011"},
433		{5, "1100", "1100", "1100", "1100", "1100"},
434		{5, "1101", "1101", "1101", "1101", "1101"},
435		{5, "1110", "1110", "1110", "1110", "1110"},
436		{5, "1111", "1111", "1111", "1111", "1111"},
437
438		{4, "1000", "1000", "1000", "1000", "1000"},
439		{4, "1001", "1001", "1001", "1001", "1001"},
440		{4, "1010", "1010", "1010", "1010", "1010"},
441		{4, "1011", "1011", "1011", "1011", "1011"},
442		{4, "1100", "1100", "1100", "1100", "1100"},
443		{4, "1101", "1101", "1101", "1101", "1101"},
444		{4, "1110", "1110", "1110", "1110", "1110"},
445		{4, "1111", "1111", "1111", "1111", "1111"},
446
447		{3, "1000", "1000", "1000", "1000", "1000"},
448		{3, "1001", "1000", "1000", "1010", "1010"},
449		{3, "1010", "1010", "1010", "1010", "1010"},
450		{3, "1011", "1010", "1100", "1100", "1100"},
451		{3, "1100", "1100", "1100", "1100", "1100"},
452		{3, "1101", "1100", "1100", "1110", "1110"},
453		{3, "1110", "1110", "1110", "1110", "1110"},
454		{3, "1111", "1110", "10000", "10000", "10000"},
455
456		{3, "1000001", "1000000", "1000000", "1000000", "1010000"},
457		{3, "1001001", "1000000", "1010000", "1010000", "1010000"},
458		{3, "1010001", "1010000", "1010000", "1010000", "1100000"},
459		{3, "1011001", "1010000", "1100000", "1100000", "1100000"},
460		{3, "1100001", "1100000", "1100000", "1100000", "1110000"},
461		{3, "1101001", "1100000", "1110000", "1110000", "1110000"},
462		{3, "1110001", "1110000", "1110000", "1110000", "10000000"},
463		{3, "1111001", "1110000", "10000000", "10000000", "10000000"},
464
465		{2, "1000", "1000", "1000", "1000", "1000"},
466		{2, "1001", "1000", "1000", "1000", "1100"},
467		{2, "1010", "1000", "1000", "1100", "1100"},
468		{2, "1011", "1000", "1100", "1100", "1100"},
469		{2, "1100", "1100", "1100", "1100", "1100"},
470		{2, "1101", "1100", "1100", "1100", "10000"},
471		{2, "1110", "1100", "10000", "10000", "10000"},
472		{2, "1111", "1100", "10000", "10000", "10000"},
473
474		{2, "1000001", "1000000", "1000000", "1000000", "1100000"},
475		{2, "1001001", "1000000", "1000000", "1000000", "1100000"},
476		{2, "1010001", "1000000", "1100000", "1100000", "1100000"},
477		{2, "1011001", "1000000", "1100000", "1100000", "1100000"},
478		{2, "1100001", "1100000", "1100000", "1100000", "10000000"},
479		{2, "1101001", "1100000", "1100000", "1100000", "10000000"},
480		{2, "1110001", "1100000", "10000000", "10000000", "10000000"},
481		{2, "1111001", "1100000", "10000000", "10000000", "10000000"},
482
483		{1, "1000", "1000", "1000", "1000", "1000"},
484		{1, "1001", "1000", "1000", "1000", "10000"},
485		{1, "1010", "1000", "1000", "1000", "10000"},
486		{1, "1011", "1000", "1000", "1000", "10000"},
487		{1, "1100", "1000", "10000", "10000", "10000"},
488		{1, "1101", "1000", "10000", "10000", "10000"},
489		{1, "1110", "1000", "10000", "10000", "10000"},
490		{1, "1111", "1000", "10000", "10000", "10000"},
491
492		{1, "1000001", "1000000", "1000000", "1000000", "10000000"},
493		{1, "1001001", "1000000", "1000000", "1000000", "10000000"},
494		{1, "1010001", "1000000", "1000000", "1000000", "10000000"},
495		{1, "1011001", "1000000", "1000000", "1000000", "10000000"},
496		{1, "1100001", "1000000", "10000000", "10000000", "10000000"},
497		{1, "1101001", "1000000", "10000000", "10000000", "10000000"},
498		{1, "1110001", "1000000", "10000000", "10000000", "10000000"},
499		{1, "1111001", "1000000", "10000000", "10000000", "10000000"},
500	} {
501		x := fromBinary(test.x)
502		z := fromBinary(test.zero)
503		e := fromBinary(test.neven)
504		n := fromBinary(test.naway)
505		a := fromBinary(test.away)
506		prec := test.prec
507
508		testFloatRound(t, x, z, prec, ToZero)
509		testFloatRound(t, x, e, prec, ToNearestEven)
510		testFloatRound(t, x, n, prec, ToNearestAway)
511		testFloatRound(t, x, a, prec, AwayFromZero)
512
513		testFloatRound(t, x, z, prec, ToNegativeInf)
514		testFloatRound(t, x, a, prec, ToPositiveInf)
515
516		testFloatRound(t, -x, -a, prec, ToNegativeInf)
517		testFloatRound(t, -x, -z, prec, ToPositiveInf)
518	}
519}
520
521// TestFloatRound24 tests that rounding a float64 to 24 bits
522// matches IEEE 754 rounding to nearest when converting a
523// float64 to a float32 (excluding denormal numbers).
524func TestFloatRound24(t *testing.T) {
525	const x0 = 1<<26 - 0x10 // 11...110000 (26 bits)
526	for d := 0; d <= 0x10; d++ {
527		x := float64(x0 + d)
528		f := new(Float).SetPrec(24).SetFloat64(x)
529		got, _ := f.Float32()
530		want := float32(x)
531		if got != want {
532			t.Errorf("Round(%g, 24) = %g; want %g", x, got, want)
533		}
534	}
535}
536
537func TestFloatSetUint64(t *testing.T) {
538	for _, want := range []uint64{
539		0,
540		1,
541		2,
542		10,
543		100,
544		1<<32 - 1,
545		1 << 32,
546		1<<64 - 1,
547	} {
548		var f Float
549		f.SetUint64(want)
550		if got := f.uint64(); got != want {
551			t.Errorf("got %#x (%s); want %#x", got, f.Text('p', 0), want)
552		}
553	}
554
555	// test basic rounding behavior (exhaustive rounding testing is done elsewhere)
556	const x uint64 = 0x8765432187654321 // 64 bits needed
557	for prec := uint(1); prec <= 64; prec++ {
558		f := new(Float).SetPrec(prec).SetMode(ToZero).SetUint64(x)
559		got := f.uint64()
560		want := x &^ (1<<(64-prec) - 1) // cut off (round to zero) low 64-prec bits
561		if got != want {
562			t.Errorf("got %#x (%s); want %#x", got, f.Text('p', 0), want)
563		}
564	}
565}
566
567func TestFloatSetInt64(t *testing.T) {
568	for _, want := range []int64{
569		0,
570		1,
571		2,
572		10,
573		100,
574		1<<32 - 1,
575		1 << 32,
576		1<<63 - 1,
577	} {
578		for i := range [2]int{} {
579			if i&1 != 0 {
580				want = -want
581			}
582			var f Float
583			f.SetInt64(want)
584			if got := f.int64(); got != want {
585				t.Errorf("got %#x (%s); want %#x", got, f.Text('p', 0), want)
586			}
587		}
588	}
589
590	// test basic rounding behavior (exhaustive rounding testing is done elsewhere)
591	const x int64 = 0x7654321076543210 // 63 bits needed
592	for prec := uint(1); prec <= 63; prec++ {
593		f := new(Float).SetPrec(prec).SetMode(ToZero).SetInt64(x)
594		got := f.int64()
595		want := x &^ (1<<(63-prec) - 1) // cut off (round to zero) low 63-prec bits
596		if got != want {
597			t.Errorf("got %#x (%s); want %#x", got, f.Text('p', 0), want)
598		}
599	}
600}
601
602func TestFloatSetFloat64(t *testing.T) {
603	for _, want := range []float64{
604		0,
605		1,
606		2,
607		12345,
608		1e10,
609		1e100,
610		3.14159265e10,
611		2.718281828e-123,
612		1.0 / 3,
613		math.MaxFloat32,
614		math.MaxFloat64,
615		math.SmallestNonzeroFloat32,
616		math.SmallestNonzeroFloat64,
617		math.Inf(-1),
618		math.Inf(0),
619		-math.Inf(1),
620	} {
621		for i := range [2]int{} {
622			if i&1 != 0 {
623				want = -want
624			}
625			var f Float
626			f.SetFloat64(want)
627			if got, acc := f.Float64(); got != want || acc != Exact {
628				t.Errorf("got %g (%s, %s); want %g (Exact)", got, f.Text('p', 0), acc, want)
629			}
630		}
631	}
632
633	// test basic rounding behavior (exhaustive rounding testing is done elsewhere)
634	const x uint64 = 0x8765432143218 // 53 bits needed
635	for prec := uint(1); prec <= 52; prec++ {
636		f := new(Float).SetPrec(prec).SetMode(ToZero).SetFloat64(float64(x))
637		got, _ := f.Float64()
638		want := float64(x &^ (1<<(52-prec) - 1)) // cut off (round to zero) low 53-prec bits
639		if got != want {
640			t.Errorf("got %g (%s); want %g", got, f.Text('p', 0), want)
641		}
642	}
643
644	// test NaN
645	defer func() {
646		if p, ok := recover().(ErrNaN); !ok {
647			t.Errorf("got %v; want ErrNaN panic", p)
648		}
649	}()
650	var f Float
651	f.SetFloat64(math.NaN())
652	// should not reach here
653	t.Errorf("got %s; want ErrNaN panic", f.Text('p', 0))
654}
655
656func TestFloatSetInt(t *testing.T) {
657	for _, want := range []string{
658		"0",
659		"1",
660		"-1",
661		"1234567890",
662		"123456789012345678901234567890",
663		"123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890",
664	} {
665		var x Int
666		_, ok := x.SetString(want, 0)
667		if !ok {
668			t.Errorf("invalid integer %s", want)
669			continue
670		}
671		n := x.BitLen()
672
673		var f Float
674		f.SetInt(&x)
675
676		// check precision
677		if n < 64 {
678			n = 64
679		}
680		if prec := f.Prec(); prec != uint(n) {
681			t.Errorf("got prec = %d; want %d", prec, n)
682		}
683
684		// check value
685		got := f.Text('g', 100)
686		if got != want {
687			t.Errorf("got %s (%s); want %s", got, f.Text('p', 0), want)
688		}
689	}
690
691	// TODO(gri) test basic rounding behavior
692}
693
694func TestFloatSetRat(t *testing.T) {
695	for _, want := range []string{
696		"0",
697		"1",
698		"-1",
699		"1234567890",
700		"123456789012345678901234567890",
701		"123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890",
702		"1.2",
703		"3.14159265",
704		// TODO(gri) expand
705	} {
706		var x Rat
707		_, ok := x.SetString(want)
708		if !ok {
709			t.Errorf("invalid fraction %s", want)
710			continue
711		}
712		n := max(x.Num().BitLen(), x.Denom().BitLen())
713
714		var f1, f2 Float
715		f2.SetPrec(1000)
716		f1.SetRat(&x)
717		f2.SetRat(&x)
718
719		// check precision when set automatically
720		if n < 64 {
721			n = 64
722		}
723		if prec := f1.Prec(); prec != uint(n) {
724			t.Errorf("got prec = %d; want %d", prec, n)
725		}
726
727		got := f2.Text('g', 100)
728		if got != want {
729			t.Errorf("got %s (%s); want %s", got, f2.Text('p', 0), want)
730		}
731	}
732}
733
734func TestFloatSetInf(t *testing.T) {
735	var f Float
736	for _, test := range []struct {
737		signbit bool
738		prec    uint
739		want    string
740	}{
741		{false, 0, "+Inf"},
742		{true, 0, "-Inf"},
743		{false, 10, "+Inf"},
744		{true, 30, "-Inf"},
745	} {
746		x := f.SetPrec(test.prec).SetInf(test.signbit)
747		if got := x.String(); got != test.want || x.Prec() != test.prec {
748			t.Errorf("SetInf(%v) = %s (prec = %d); want %s (prec = %d)", test.signbit, got, x.Prec(), test.want, test.prec)
749		}
750	}
751}
752
753func TestFloatUint64(t *testing.T) {
754	for _, test := range []struct {
755		x   string
756		out uint64
757		acc Accuracy
758	}{
759		{"-Inf", 0, Above},
760		{"-1", 0, Above},
761		{"-1e-1000", 0, Above},
762		{"-0", 0, Exact},
763		{"0", 0, Exact},
764		{"1e-1000", 0, Below},
765		{"1", 1, Exact},
766		{"1.000000000000000000001", 1, Below},
767		{"12345.0", 12345, Exact},
768		{"12345.000000000000000000001", 12345, Below},
769		{"18446744073709551615", 18446744073709551615, Exact},
770		{"18446744073709551615.000000000000000000001", math.MaxUint64, Below},
771		{"18446744073709551616", math.MaxUint64, Below},
772		{"1e10000", math.MaxUint64, Below},
773		{"+Inf", math.MaxUint64, Below},
774	} {
775		x := makeFloat(test.x)
776		out, acc := x.Uint64()
777		if out != test.out || acc != test.acc {
778			t.Errorf("%s: got %d (%s); want %d (%s)", test.x, out, acc, test.out, test.acc)
779		}
780	}
781}
782
783func TestFloatInt64(t *testing.T) {
784	for _, test := range []struct {
785		x   string
786		out int64
787		acc Accuracy
788	}{
789		{"-Inf", math.MinInt64, Above},
790		{"-1e10000", math.MinInt64, Above},
791		{"-9223372036854775809", math.MinInt64, Above},
792		{"-9223372036854775808.000000000000000000001", math.MinInt64, Above},
793		{"-9223372036854775808", -9223372036854775808, Exact},
794		{"-9223372036854775807.000000000000000000001", -9223372036854775807, Above},
795		{"-9223372036854775807", -9223372036854775807, Exact},
796		{"-12345.000000000000000000001", -12345, Above},
797		{"-12345.0", -12345, Exact},
798		{"-1.000000000000000000001", -1, Above},
799		{"-1.5", -1, Above},
800		{"-1", -1, Exact},
801		{"-1e-1000", 0, Above},
802		{"0", 0, Exact},
803		{"1e-1000", 0, Below},
804		{"1", 1, Exact},
805		{"1.000000000000000000001", 1, Below},
806		{"1.5", 1, Below},
807		{"12345.0", 12345, Exact},
808		{"12345.000000000000000000001", 12345, Below},
809		{"9223372036854775807", 9223372036854775807, Exact},
810		{"9223372036854775807.000000000000000000001", math.MaxInt64, Below},
811		{"9223372036854775808", math.MaxInt64, Below},
812		{"1e10000", math.MaxInt64, Below},
813		{"+Inf", math.MaxInt64, Below},
814	} {
815		x := makeFloat(test.x)
816		out, acc := x.Int64()
817		if out != test.out || acc != test.acc {
818			t.Errorf("%s: got %d (%s); want %d (%s)", test.x, out, acc, test.out, test.acc)
819		}
820	}
821}
822
823func TestFloatFloat32(t *testing.T) {
824	for _, test := range []struct {
825		x   string
826		out float32
827		acc Accuracy
828	}{
829		{"0", 0, Exact},
830
831		// underflow to zero
832		{"1e-1000", 0, Below},
833		{"0x0.000002p-127", 0, Below},
834		{"0x.0000010p-126", 0, Below},
835
836		// denormals
837		{"1.401298464e-45", math.SmallestNonzeroFloat32, Above}, // rounded up to smallest denormal
838		{"0x.ffffff8p-149", math.SmallestNonzeroFloat32, Above}, // rounded up to smallest denormal
839		{"0x.0000018p-126", math.SmallestNonzeroFloat32, Above}, // rounded up to smallest denormal
840		{"0x.0000020p-126", math.SmallestNonzeroFloat32, Exact},
841		{"0x.8p-148", math.SmallestNonzeroFloat32, Exact},
842		{"1p-149", math.SmallestNonzeroFloat32, Exact},
843		{"0x.fffffep-126", math.Float32frombits(0x7fffff), Exact}, // largest denormal
844
845		// special denormal cases (see issues 14553, 14651)
846		{"0x0.0000001p-126", math.Float32frombits(0x00000000), Below}, // underflow to zero
847		{"0x0.0000008p-126", math.Float32frombits(0x00000000), Below}, // underflow to zero
848		{"0x0.0000010p-126", math.Float32frombits(0x00000000), Below}, // rounded down to even
849		{"0x0.0000011p-126", math.Float32frombits(0x00000001), Above}, // rounded up to smallest denormal
850		{"0x0.0000018p-126", math.Float32frombits(0x00000001), Above}, // rounded up to smallest denormal
851
852		{"0x1.0000000p-149", math.Float32frombits(0x00000001), Exact}, // smallest denormal
853		{"0x0.0000020p-126", math.Float32frombits(0x00000001), Exact}, // smallest denormal
854		{"0x0.fffffe0p-126", math.Float32frombits(0x007fffff), Exact}, // largest denormal
855		{"0x1.0000000p-126", math.Float32frombits(0x00800000), Exact}, // smallest normal
856
857		{"0x0.8p-149", math.Float32frombits(0x000000000), Below}, // rounded down to even
858		{"0x0.9p-149", math.Float32frombits(0x000000001), Above}, // rounded up to smallest denormal
859		{"0x0.ap-149", math.Float32frombits(0x000000001), Above}, // rounded up to smallest denormal
860		{"0x0.bp-149", math.Float32frombits(0x000000001), Above}, // rounded up to smallest denormal
861		{"0x0.cp-149", math.Float32frombits(0x000000001), Above}, // rounded up to smallest denormal
862
863		{"0x1.0p-149", math.Float32frombits(0x000000001), Exact}, // smallest denormal
864		{"0x1.7p-149", math.Float32frombits(0x000000001), Below},
865		{"0x1.8p-149", math.Float32frombits(0x000000002), Above},
866		{"0x1.9p-149", math.Float32frombits(0x000000002), Above},
867
868		{"0x2.0p-149", math.Float32frombits(0x000000002), Exact},
869		{"0x2.8p-149", math.Float32frombits(0x000000002), Below}, // rounded down to even
870		{"0x2.9p-149", math.Float32frombits(0x000000003), Above},
871
872		{"0x3.0p-149", math.Float32frombits(0x000000003), Exact},
873		{"0x3.7p-149", math.Float32frombits(0x000000003), Below},
874		{"0x3.8p-149", math.Float32frombits(0x000000004), Above}, // rounded up to even
875
876		{"0x4.0p-149", math.Float32frombits(0x000000004), Exact},
877		{"0x4.8p-149", math.Float32frombits(0x000000004), Below}, // rounded down to even
878		{"0x4.9p-149", math.Float32frombits(0x000000005), Above},
879
880		// specific case from issue 14553
881		{"0x7.7p-149", math.Float32frombits(0x000000007), Below},
882		{"0x7.8p-149", math.Float32frombits(0x000000008), Above},
883		{"0x7.9p-149", math.Float32frombits(0x000000008), Above},
884
885		// normals
886		{"0x.ffffffp-126", math.Float32frombits(0x00800000), Above}, // rounded up to smallest normal
887		{"1p-126", math.Float32frombits(0x00800000), Exact},         // smallest normal
888		{"0x1.fffffep-126", math.Float32frombits(0x00ffffff), Exact},
889		{"0x1.ffffffp-126", math.Float32frombits(0x01000000), Above}, // rounded up
890		{"1", 1, Exact},
891		{"1.000000000000000000001", 1, Below},
892		{"12345.0", 12345, Exact},
893		{"12345.000000000000000000001", 12345, Below},
894		{"0x1.fffffe0p127", math.MaxFloat32, Exact},
895		{"0x1.fffffe8p127", math.MaxFloat32, Below},
896
897		// overflow
898		{"0x1.ffffff0p127", float32(math.Inf(+1)), Above},
899		{"0x1p128", float32(math.Inf(+1)), Above},
900		{"1e10000", float32(math.Inf(+1)), Above},
901		{"0x1.ffffff0p2147483646", float32(math.Inf(+1)), Above}, // overflow in rounding
902
903		// inf
904		{"Inf", float32(math.Inf(+1)), Exact},
905	} {
906		for i := 0; i < 2; i++ {
907			// test both signs
908			tx, tout, tacc := test.x, test.out, test.acc
909			if i != 0 {
910				tx = "-" + tx
911				tout = -tout
912				tacc = -tacc
913			}
914
915			// conversion should match strconv where syntax is agreeable
916			if f, err := strconv.ParseFloat(tx, 32); err == nil && !alike32(float32(f), tout) {
917				t.Errorf("%s: got %g; want %g (incorrect test data)", tx, f, tout)
918			}
919
920			x := makeFloat(tx)
921			out, acc := x.Float32()
922			if !alike32(out, tout) || acc != tacc {
923				t.Errorf("%s: got %g (%#08x, %s); want %g (%#08x, %s)", tx, out, math.Float32bits(out), acc, test.out, math.Float32bits(test.out), tacc)
924			}
925
926			// test that x.SetFloat64(float64(f)).Float32() == f
927			var x2 Float
928			out2, acc2 := x2.SetFloat64(float64(out)).Float32()
929			if !alike32(out2, out) || acc2 != Exact {
930				t.Errorf("idempotency test: got %g (%s); want %g (Exact)", out2, acc2, out)
931			}
932		}
933	}
934}
935
936func TestFloatFloat64(t *testing.T) {
937	const smallestNormalFloat64 = 2.2250738585072014e-308 // 1p-1022
938	for _, test := range []struct {
939		x   string
940		out float64
941		acc Accuracy
942	}{
943		{"0", 0, Exact},
944
945		// underflow to zero
946		{"1e-1000", 0, Below},
947		{"0x0.0000000000001p-1023", 0, Below},
948		{"0x0.00000000000008p-1022", 0, Below},
949
950		// denormals
951		{"0x0.0000000000000cp-1022", math.SmallestNonzeroFloat64, Above}, // rounded up to smallest denormal
952		{"0x0.00000000000010p-1022", math.SmallestNonzeroFloat64, Exact}, // smallest denormal
953		{"0x.8p-1073", math.SmallestNonzeroFloat64, Exact},
954		{"1p-1074", math.SmallestNonzeroFloat64, Exact},
955		{"0x.fffffffffffffp-1022", math.Float64frombits(0x000fffffffffffff), Exact}, // largest denormal
956
957		// special denormal cases (see issues 14553, 14651)
958		{"0x0.00000000000001p-1022", math.Float64frombits(0x00000000000000000), Below}, // underflow to zero
959		{"0x0.00000000000004p-1022", math.Float64frombits(0x00000000000000000), Below}, // underflow to zero
960		{"0x0.00000000000008p-1022", math.Float64frombits(0x00000000000000000), Below}, // rounded down to even
961		{"0x0.00000000000009p-1022", math.Float64frombits(0x00000000000000001), Above}, // rounded up to smallest denormal
962		{"0x0.0000000000000ap-1022", math.Float64frombits(0x00000000000000001), Above}, // rounded up to smallest denormal
963
964		{"0x0.8p-1074", math.Float64frombits(0x00000000000000000), Below}, // rounded down to even
965		{"0x0.9p-1074", math.Float64frombits(0x00000000000000001), Above}, // rounded up to smallest denormal
966		{"0x0.ap-1074", math.Float64frombits(0x00000000000000001), Above}, // rounded up to smallest denormal
967		{"0x0.bp-1074", math.Float64frombits(0x00000000000000001), Above}, // rounded up to smallest denormal
968		{"0x0.cp-1074", math.Float64frombits(0x00000000000000001), Above}, // rounded up to smallest denormal
969
970		{"0x1.0p-1074", math.Float64frombits(0x00000000000000001), Exact},
971		{"0x1.7p-1074", math.Float64frombits(0x00000000000000001), Below},
972		{"0x1.8p-1074", math.Float64frombits(0x00000000000000002), Above},
973		{"0x1.9p-1074", math.Float64frombits(0x00000000000000002), Above},
974
975		{"0x2.0p-1074", math.Float64frombits(0x00000000000000002), Exact},
976		{"0x2.8p-1074", math.Float64frombits(0x00000000000000002), Below}, // rounded down to even
977		{"0x2.9p-1074", math.Float64frombits(0x00000000000000003), Above},
978
979		{"0x3.0p-1074", math.Float64frombits(0x00000000000000003), Exact},
980		{"0x3.7p-1074", math.Float64frombits(0x00000000000000003), Below},
981		{"0x3.8p-1074", math.Float64frombits(0x00000000000000004), Above}, // rounded up to even
982
983		{"0x4.0p-1074", math.Float64frombits(0x00000000000000004), Exact},
984		{"0x4.8p-1074", math.Float64frombits(0x00000000000000004), Below}, // rounded down to even
985		{"0x4.9p-1074", math.Float64frombits(0x00000000000000005), Above},
986
987		// normals
988		{"0x.fffffffffffff8p-1022", math.Float64frombits(0x0010000000000000), Above}, // rounded up to smallest normal
989		{"1p-1022", math.Float64frombits(0x0010000000000000), Exact},                 // smallest normal
990		{"1", 1, Exact},
991		{"1.000000000000000000001", 1, Below},
992		{"12345.0", 12345, Exact},
993		{"12345.000000000000000000001", 12345, Below},
994		{"0x1.fffffffffffff0p1023", math.MaxFloat64, Exact},
995		{"0x1.fffffffffffff4p1023", math.MaxFloat64, Below},
996
997		// overflow
998		{"0x1.fffffffffffff8p1023", math.Inf(+1), Above},
999		{"0x1p1024", math.Inf(+1), Above},
1000		{"1e10000", math.Inf(+1), Above},
1001		{"0x1.fffffffffffff8p2147483646", math.Inf(+1), Above}, // overflow in rounding
1002		{"Inf", math.Inf(+1), Exact},
1003
1004		// selected denormalized values that were handled incorrectly in the past
1005		{"0x.fffffffffffffp-1022", smallestNormalFloat64 - math.SmallestNonzeroFloat64, Exact},
1006		{"4503599627370495p-1074", smallestNormalFloat64 - math.SmallestNonzeroFloat64, Exact},
1007
1008		// https://www.exploringbinary.com/php-hangs-on-numeric-value-2-2250738585072011e-308/
1009		{"2.2250738585072011e-308", 2.225073858507201e-308, Below},
1010		// https://www.exploringbinary.com/java-hangs-when-converting-2-2250738585072012e-308/
1011		{"2.2250738585072012e-308", 2.2250738585072014e-308, Above},
1012	} {
1013		for i := 0; i < 2; i++ {
1014			// test both signs
1015			tx, tout, tacc := test.x, test.out, test.acc
1016			if i != 0 {
1017				tx = "-" + tx
1018				tout = -tout
1019				tacc = -tacc
1020			}
1021
1022			// conversion should match strconv where syntax is agreeable
1023			if f, err := strconv.ParseFloat(tx, 64); err == nil && !alike64(f, tout) {
1024				t.Errorf("%s: got %g; want %g (incorrect test data)", tx, f, tout)
1025			}
1026
1027			x := makeFloat(tx)
1028			out, acc := x.Float64()
1029			if !alike64(out, tout) || acc != tacc {
1030				t.Errorf("%s: got %g (%#016x, %s); want %g (%#016x, %s)", tx, out, math.Float64bits(out), acc, test.out, math.Float64bits(test.out), tacc)
1031			}
1032
1033			// test that x.SetFloat64(f).Float64() == f
1034			var x2 Float
1035			out2, acc2 := x2.SetFloat64(out).Float64()
1036			if !alike64(out2, out) || acc2 != Exact {
1037				t.Errorf("idempotency test: got %g (%s); want %g (Exact)", out2, acc2, out)
1038			}
1039		}
1040	}
1041}
1042
1043func TestFloatInt(t *testing.T) {
1044	for _, test := range []struct {
1045		x    string
1046		want string
1047		acc  Accuracy
1048	}{
1049		{"0", "0", Exact},
1050		{"+0", "0", Exact},
1051		{"-0", "0", Exact},
1052		{"Inf", "nil", Below},
1053		{"+Inf", "nil", Below},
1054		{"-Inf", "nil", Above},
1055		{"1", "1", Exact},
1056		{"-1", "-1", Exact},
1057		{"1.23", "1", Below},
1058		{"-1.23", "-1", Above},
1059		{"123e-2", "1", Below},
1060		{"123e-3", "0", Below},
1061		{"123e-4", "0", Below},
1062		{"1e-1000", "0", Below},
1063		{"-1e-1000", "0", Above},
1064		{"1e+10", "10000000000", Exact},
1065		{"1e+100", "10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", Exact},
1066	} {
1067		x := makeFloat(test.x)
1068		res, acc := x.Int(nil)
1069		got := "nil"
1070		if res != nil {
1071			got = res.String()
1072		}
1073		if got != test.want || acc != test.acc {
1074			t.Errorf("%s: got %s (%s); want %s (%s)", test.x, got, acc, test.want, test.acc)
1075		}
1076	}
1077
1078	// check that supplied *Int is used
1079	for _, f := range []string{"0", "1", "-1", "1234"} {
1080		x := makeFloat(f)
1081		i := new(Int)
1082		if res, _ := x.Int(i); res != i {
1083			t.Errorf("(%s).Int is not using supplied *Int", f)
1084		}
1085	}
1086}
1087
1088func TestFloatRat(t *testing.T) {
1089	for _, test := range []struct {
1090		x, want string
1091		acc     Accuracy
1092	}{
1093		{"0", "0/1", Exact},
1094		{"+0", "0/1", Exact},
1095		{"-0", "0/1", Exact},
1096		{"Inf", "nil", Below},
1097		{"+Inf", "nil", Below},
1098		{"-Inf", "nil", Above},
1099		{"1", "1/1", Exact},
1100		{"-1", "-1/1", Exact},
1101		{"1.25", "5/4", Exact},
1102		{"-1.25", "-5/4", Exact},
1103		{"1e10", "10000000000/1", Exact},
1104		{"1p10", "1024/1", Exact},
1105		{"-1p-10", "-1/1024", Exact},
1106		{"3.14159265", "7244019449799623199/2305843009213693952", Exact},
1107	} {
1108		x := makeFloat(test.x).SetPrec(64)
1109		res, acc := x.Rat(nil)
1110		got := "nil"
1111		if res != nil {
1112			got = res.String()
1113		}
1114		if got != test.want {
1115			t.Errorf("%s: got %s; want %s", test.x, got, test.want)
1116			continue
1117		}
1118		if acc != test.acc {
1119			t.Errorf("%s: got %s; want %s", test.x, acc, test.acc)
1120			continue
1121		}
1122
1123		// inverse conversion
1124		if res != nil {
1125			got := new(Float).SetPrec(64).SetRat(res)
1126			if got.Cmp(x) != 0 {
1127				t.Errorf("%s: got %s; want %s", test.x, got, x)
1128			}
1129		}
1130	}
1131
1132	// check that supplied *Rat is used
1133	for _, f := range []string{"0", "1", "-1", "1234"} {
1134		x := makeFloat(f)
1135		r := new(Rat)
1136		if res, _ := x.Rat(r); res != r {
1137			t.Errorf("(%s).Rat is not using supplied *Rat", f)
1138		}
1139	}
1140}
1141
1142func TestFloatAbs(t *testing.T) {
1143	for _, test := range []string{
1144		"0",
1145		"1",
1146		"1234",
1147		"1.23e-2",
1148		"1e-1000",
1149		"1e1000",
1150		"Inf",
1151	} {
1152		p := makeFloat(test)
1153		a := new(Float).Abs(p)
1154		if !alike(a, p) {
1155			t.Errorf("%s: got %s; want %s", test, a.Text('g', 10), test)
1156		}
1157
1158		n := makeFloat("-" + test)
1159		a.Abs(n)
1160		if !alike(a, p) {
1161			t.Errorf("-%s: got %s; want %s", test, a.Text('g', 10), test)
1162		}
1163	}
1164}
1165
1166func TestFloatNeg(t *testing.T) {
1167	for _, test := range []string{
1168		"0",
1169		"1",
1170		"1234",
1171		"1.23e-2",
1172		"1e-1000",
1173		"1e1000",
1174		"Inf",
1175	} {
1176		p1 := makeFloat(test)
1177		n1 := makeFloat("-" + test)
1178		n2 := new(Float).Neg(p1)
1179		p2 := new(Float).Neg(n2)
1180		if !alike(n2, n1) {
1181			t.Errorf("%s: got %s; want %s", test, n2.Text('g', 10), n1.Text('g', 10))
1182		}
1183		if !alike(p2, p1) {
1184			t.Errorf("%s: got %s; want %s", test, p2.Text('g', 10), p1.Text('g', 10))
1185		}
1186	}
1187}
1188
1189func TestFloatInc(t *testing.T) {
1190	const n = 10
1191	for _, prec := range precList {
1192		if 1<<prec < n {
1193			continue // prec must be large enough to hold all numbers from 0 to n
1194		}
1195		var x, one Float
1196		x.SetPrec(prec)
1197		one.SetInt64(1)
1198		for i := 0; i < n; i++ {
1199			x.Add(&x, &one)
1200		}
1201		if x.Cmp(new(Float).SetInt64(n)) != 0 {
1202			t.Errorf("prec = %d: got %s; want %d", prec, &x, n)
1203		}
1204	}
1205}
1206
1207// Selected precisions with which to run various tests.
1208var precList = [...]uint{1, 2, 5, 8, 10, 16, 23, 24, 32, 50, 53, 64, 100, 128, 500, 511, 512, 513, 1000, 10000}
1209
1210// Selected bits with which to run various tests.
1211// Each entry is a list of bits representing a floating-point number (see fromBits).
1212var bitsList = [...]Bits{
1213	{},           // = 0
1214	{0},          // = 1
1215	{1},          // = 2
1216	{-1},         // = 1/2
1217	{10},         // = 2**10 == 1024
1218	{-10},        // = 2**-10 == 1/1024
1219	{100, 10, 1}, // = 2**100 + 2**10 + 2**1
1220	{0, -1, -2, -10},
1221	// TODO(gri) add more test cases
1222}
1223
1224// TestFloatAdd tests Float.Add/Sub by comparing the result of a "manual"
1225// addition/subtraction of arguments represented by Bits values with the
1226// respective Float addition/subtraction for a variety of precisions
1227// and rounding modes.
1228func TestFloatAdd(t *testing.T) {
1229	for _, xbits := range bitsList {
1230		for _, ybits := range bitsList {
1231			// exact values
1232			x := xbits.Float()
1233			y := ybits.Float()
1234			zbits := xbits.add(ybits)
1235			z := zbits.Float()
1236
1237			for i, mode := range [...]RoundingMode{ToZero, ToNearestEven, AwayFromZero} {
1238				for _, prec := range precList {
1239					got := new(Float).SetPrec(prec).SetMode(mode)
1240					got.Add(x, y)
1241					want := zbits.round(prec, mode)
1242					if got.Cmp(want) != 0 {
1243						t.Errorf("i = %d, prec = %d, %s:\n\t     %s %v\n\t+    %s %v\n\t=    %s\n\twant %s",
1244							i, prec, mode, x, xbits, y, ybits, got, want)
1245					}
1246
1247					got.Sub(z, x)
1248					want = ybits.round(prec, mode)
1249					if got.Cmp(want) != 0 {
1250						t.Errorf("i = %d, prec = %d, %s:\n\t     %s %v\n\t-    %s %v\n\t=    %s\n\twant %s",
1251							i, prec, mode, z, zbits, x, xbits, got, want)
1252					}
1253				}
1254			}
1255		}
1256	}
1257}
1258
1259// TestFloatAddRoundZero tests Float.Add/Sub rounding when the result is exactly zero.
1260// x + (-x) or x - x for non-zero x should be +0 in all cases except when
1261// the rounding mode is ToNegativeInf in which case it should be -0.
1262func TestFloatAddRoundZero(t *testing.T) {
1263	for _, mode := range [...]RoundingMode{ToNearestEven, ToNearestAway, ToZero, AwayFromZero, ToPositiveInf, ToNegativeInf} {
1264		x := NewFloat(5.0)
1265		y := new(Float).Neg(x)
1266		want := NewFloat(0.0)
1267		if mode == ToNegativeInf {
1268			want.Neg(want)
1269		}
1270		got := new(Float).SetMode(mode)
1271		got.Add(x, y)
1272		if got.Cmp(want) != 0 || got.neg != (mode == ToNegativeInf) {
1273			t.Errorf("%s:\n\t     %v\n\t+    %v\n\t=    %v\n\twant %v",
1274				mode, x, y, got, want)
1275		}
1276		got.Sub(x, x)
1277		if got.Cmp(want) != 0 || got.neg != (mode == ToNegativeInf) {
1278			t.Errorf("%v:\n\t     %v\n\t-    %v\n\t=    %v\n\twant %v",
1279				mode, x, x, got, want)
1280		}
1281	}
1282}
1283
1284// TestFloatAdd32 tests that Float.Add/Sub of numbers with
1285// 24bit mantissa behaves like float32 addition/subtraction
1286// (excluding denormal numbers).
1287func TestFloatAdd32(t *testing.T) {
1288	// chose base such that we cross the mantissa precision limit
1289	const base = 1<<26 - 0x10 // 11...110000 (26 bits)
1290	for d := 0; d <= 0x10; d++ {
1291		for i := range [2]int{} {
1292			x0, y0 := float64(base), float64(d)
1293			if i&1 != 0 {
1294				x0, y0 = y0, x0
1295			}
1296
1297			x := NewFloat(x0)
1298			y := NewFloat(y0)
1299			z := new(Float).SetPrec(24)
1300
1301			z.Add(x, y)
1302			got, acc := z.Float32()
1303			want := float32(y0) + float32(x0)
1304			if got != want || acc != Exact {
1305				t.Errorf("d = %d: %g + %g = %g (%s); want %g (Exact)", d, x0, y0, got, acc, want)
1306			}
1307
1308			z.Sub(z, y)
1309			got, acc = z.Float32()
1310			want = float32(want) - float32(y0)
1311			if got != want || acc != Exact {
1312				t.Errorf("d = %d: %g - %g = %g (%s); want %g (Exact)", d, x0+y0, y0, got, acc, want)
1313			}
1314		}
1315	}
1316}
1317
1318// TestFloatAdd64 tests that Float.Add/Sub of numbers with
1319// 53bit mantissa behaves like float64 addition/subtraction.
1320func TestFloatAdd64(t *testing.T) {
1321	// chose base such that we cross the mantissa precision limit
1322	const base = 1<<55 - 0x10 // 11...110000 (55 bits)
1323	for d := 0; d <= 0x10; d++ {
1324		for i := range [2]int{} {
1325			x0, y0 := float64(base), float64(d)
1326			if i&1 != 0 {
1327				x0, y0 = y0, x0
1328			}
1329
1330			x := NewFloat(x0)
1331			y := NewFloat(y0)
1332			z := new(Float).SetPrec(53)
1333
1334			z.Add(x, y)
1335			got, acc := z.Float64()
1336			want := x0 + y0
1337			if got != want || acc != Exact {
1338				t.Errorf("d = %d: %g + %g = %g (%s); want %g (Exact)", d, x0, y0, got, acc, want)
1339			}
1340
1341			z.Sub(z, y)
1342			got, acc = z.Float64()
1343			want -= y0
1344			if got != want || acc != Exact {
1345				t.Errorf("d = %d: %g - %g = %g (%s); want %g (Exact)", d, x0+y0, y0, got, acc, want)
1346			}
1347		}
1348	}
1349}
1350
1351func TestIssue20490(t *testing.T) {
1352	var tests = []struct {
1353		a, b float64
1354	}{
1355		{4, 1},
1356		{-4, 1},
1357		{4, -1},
1358		{-4, -1},
1359	}
1360
1361	for _, test := range tests {
1362		a, b := NewFloat(test.a), NewFloat(test.b)
1363		diff := new(Float).Sub(a, b)
1364		b.Sub(a, b)
1365		if b.Cmp(diff) != 0 {
1366			t.Errorf("got %g - %g = %g; want %g\n", a, NewFloat(test.b), b, diff)
1367		}
1368
1369		b = NewFloat(test.b)
1370		sum := new(Float).Add(a, b)
1371		b.Add(a, b)
1372		if b.Cmp(sum) != 0 {
1373			t.Errorf("got %g + %g = %g; want %g\n", a, NewFloat(test.b), b, sum)
1374		}
1375
1376	}
1377}
1378
1379// TestFloatMul tests Float.Mul/Quo by comparing the result of a "manual"
1380// multiplication/division of arguments represented by Bits values with the
1381// respective Float multiplication/division for a variety of precisions
1382// and rounding modes.
1383func TestFloatMul(t *testing.T) {
1384	for _, xbits := range bitsList {
1385		for _, ybits := range bitsList {
1386			// exact values
1387			x := xbits.Float()
1388			y := ybits.Float()
1389			zbits := xbits.mul(ybits)
1390			z := zbits.Float()
1391
1392			for i, mode := range [...]RoundingMode{ToZero, ToNearestEven, AwayFromZero} {
1393				for _, prec := range precList {
1394					got := new(Float).SetPrec(prec).SetMode(mode)
1395					got.Mul(x, y)
1396					want := zbits.round(prec, mode)
1397					if got.Cmp(want) != 0 {
1398						t.Errorf("i = %d, prec = %d, %s:\n\t     %v %v\n\t*    %v %v\n\t=    %v\n\twant %v",
1399							i, prec, mode, x, xbits, y, ybits, got, want)
1400					}
1401
1402					if x.Sign() == 0 {
1403						continue // ignore div-0 case (not invertable)
1404					}
1405					got.Quo(z, x)
1406					want = ybits.round(prec, mode)
1407					if got.Cmp(want) != 0 {
1408						t.Errorf("i = %d, prec = %d, %s:\n\t     %v %v\n\t/    %v %v\n\t=    %v\n\twant %v",
1409							i, prec, mode, z, zbits, x, xbits, got, want)
1410					}
1411				}
1412			}
1413		}
1414	}
1415}
1416
1417// TestFloatMul64 tests that Float.Mul/Quo of numbers with
1418// 53bit mantissa behaves like float64 multiplication/division.
1419func TestFloatMul64(t *testing.T) {
1420	for _, test := range []struct {
1421		x, y float64
1422	}{
1423		{0, 0},
1424		{0, 1},
1425		{1, 1},
1426		{1, 1.5},
1427		{1.234, 0.5678},
1428		{2.718281828, 3.14159265358979},
1429		{2.718281828e10, 3.14159265358979e-32},
1430		{1.0 / 3, 1e200},
1431	} {
1432		for i := range [8]int{} {
1433			x0, y0 := test.x, test.y
1434			if i&1 != 0 {
1435				x0 = -x0
1436			}
1437			if i&2 != 0 {
1438				y0 = -y0
1439			}
1440			if i&4 != 0 {
1441				x0, y0 = y0, x0
1442			}
1443
1444			x := NewFloat(x0)
1445			y := NewFloat(y0)
1446			z := new(Float).SetPrec(53)
1447
1448			z.Mul(x, y)
1449			got, _ := z.Float64()
1450			want := x0 * y0
1451			if got != want {
1452				t.Errorf("%g * %g = %g; want %g", x0, y0, got, want)
1453			}
1454
1455			if y0 == 0 {
1456				continue // avoid division-by-zero
1457			}
1458			z.Quo(z, y)
1459			got, _ = z.Float64()
1460			want /= y0
1461			if got != want {
1462				t.Errorf("%g / %g = %g; want %g", x0*y0, y0, got, want)
1463			}
1464		}
1465	}
1466}
1467
1468func TestIssue6866(t *testing.T) {
1469	for _, prec := range precList {
1470		two := new(Float).SetPrec(prec).SetInt64(2)
1471		one := new(Float).SetPrec(prec).SetInt64(1)
1472		three := new(Float).SetPrec(prec).SetInt64(3)
1473		msix := new(Float).SetPrec(prec).SetInt64(-6)
1474		psix := new(Float).SetPrec(prec).SetInt64(+6)
1475
1476		p := new(Float).SetPrec(prec)
1477		z1 := new(Float).SetPrec(prec)
1478		z2 := new(Float).SetPrec(prec)
1479
1480		// z1 = 2 + 1.0/3*-6
1481		p.Quo(one, three)
1482		p.Mul(p, msix)
1483		z1.Add(two, p)
1484
1485		// z2 = 2 - 1.0/3*+6
1486		p.Quo(one, three)
1487		p.Mul(p, psix)
1488		z2.Sub(two, p)
1489
1490		if z1.Cmp(z2) != 0 {
1491			t.Fatalf("prec %d: got z1 = %v != z2 = %v; want z1 == z2\n", prec, z1, z2)
1492		}
1493		if z1.Sign() != 0 {
1494			t.Errorf("prec %d: got z1 = %v; want 0", prec, z1)
1495		}
1496		if z2.Sign() != 0 {
1497			t.Errorf("prec %d: got z2 = %v; want 0", prec, z2)
1498		}
1499	}
1500}
1501
1502func TestFloatQuo(t *testing.T) {
1503	// TODO(gri) make the test vary these precisions
1504	preci := 200 // precision of integer part
1505	precf := 20  // precision of fractional part
1506
1507	for i := 0; i < 8; i++ {
1508		// compute accurate (not rounded) result z
1509		bits := Bits{preci - 1}
1510		if i&3 != 0 {
1511			bits = append(bits, 0)
1512		}
1513		if i&2 != 0 {
1514			bits = append(bits, -1)
1515		}
1516		if i&1 != 0 {
1517			bits = append(bits, -precf)
1518		}
1519		z := bits.Float()
1520
1521		// compute accurate x as z*y
1522		y := NewFloat(3.14159265358979323e123)
1523
1524		x := new(Float).SetPrec(z.Prec() + y.Prec()).SetMode(ToZero)
1525		x.Mul(z, y)
1526
1527		// leave for debugging
1528		// fmt.Printf("x = %s\ny = %s\nz = %s\n", x, y, z)
1529
1530		if got := x.Acc(); got != Exact {
1531			t.Errorf("got acc = %s; want exact", got)
1532		}
1533
1534		// round accurate z for a variety of precisions and
1535		// modes and compare against result of x / y.
1536		for _, mode := range [...]RoundingMode{ToZero, ToNearestEven, AwayFromZero} {
1537			for d := -5; d < 5; d++ {
1538				prec := uint(preci + d)
1539				got := new(Float).SetPrec(prec).SetMode(mode).Quo(x, y)
1540				want := bits.round(prec, mode)
1541				if got.Cmp(want) != 0 {
1542					t.Errorf("i = %d, prec = %d, %s:\n\t     %s\n\t/    %s\n\t=    %s\n\twant %s",
1543						i, prec, mode, x, y, got, want)
1544				}
1545			}
1546		}
1547	}
1548}
1549
1550var long = flag.Bool("long", false, "run very long tests")
1551
1552// TestFloatQuoSmoke tests all divisions x/y for values x, y in the range [-n, +n];
1553// it serves as a smoke test for basic correctness of division.
1554func TestFloatQuoSmoke(t *testing.T) {
1555	n := 10
1556	if *long {
1557		n = 1000
1558	}
1559
1560	const dprec = 3         // max. precision variation
1561	const prec = 10 + dprec // enough bits to hold n precisely
1562	for x := -n; x <= n; x++ {
1563		for y := -n; y < n; y++ {
1564			if y == 0 {
1565				continue
1566			}
1567
1568			a := float64(x)
1569			b := float64(y)
1570			c := a / b
1571
1572			// vary operand precision (only ok as long as a, b can be represented correctly)
1573			for ad := -dprec; ad <= dprec; ad++ {
1574				for bd := -dprec; bd <= dprec; bd++ {
1575					A := new(Float).SetPrec(uint(prec + ad)).SetFloat64(a)
1576					B := new(Float).SetPrec(uint(prec + bd)).SetFloat64(b)
1577					C := new(Float).SetPrec(53).Quo(A, B) // C has float64 mantissa width
1578
1579					cc, acc := C.Float64()
1580					if cc != c {
1581						t.Errorf("%g/%g = %s; want %.5g\n", a, b, C.Text('g', 5), c)
1582						continue
1583					}
1584					if acc != Exact {
1585						t.Errorf("%g/%g got %s result; want exact result", a, b, acc)
1586					}
1587				}
1588			}
1589		}
1590	}
1591}
1592
1593// TestFloatArithmeticSpecialValues tests that Float operations produce the
1594// correct results for combinations of zero (±0), finite (±1 and ±2.71828),
1595// and infinite (±Inf) operands.
1596func TestFloatArithmeticSpecialValues(t *testing.T) {
1597	zero := 0.0
1598	args := []float64{math.Inf(-1), -2.71828, -1, -zero, zero, 1, 2.71828, math.Inf(1)}
1599	xx := new(Float)
1600	yy := new(Float)
1601	got := new(Float)
1602	want := new(Float)
1603	for i := 0; i < 4; i++ {
1604		for _, x := range args {
1605			xx.SetFloat64(x)
1606			// check conversion is correct
1607			// (no need to do this for y, since we see exactly the
1608			// same values there)
1609			if got, acc := xx.Float64(); got != x || acc != Exact {
1610				t.Errorf("Float(%g) == %g (%s)", x, got, acc)
1611			}
1612			for _, y := range args {
1613				yy.SetFloat64(y)
1614				var (
1615					op string
1616					z  float64
1617					f  func(z, x, y *Float) *Float
1618				)
1619				switch i {
1620				case 0:
1621					op = "+"
1622					z = x + y
1623					f = (*Float).Add
1624				case 1:
1625					op = "-"
1626					z = x - y
1627					f = (*Float).Sub
1628				case 2:
1629					op = "*"
1630					z = x * y
1631					f = (*Float).Mul
1632				case 3:
1633					op = "/"
1634					z = x / y
1635					f = (*Float).Quo
1636				default:
1637					panic("unreachable")
1638				}
1639				var errnan bool // set if execution of f panicked with ErrNaN
1640				// protect execution of f
1641				func() {
1642					defer func() {
1643						if p := recover(); p != nil {
1644							_ = p.(ErrNaN) // re-panic if not ErrNaN
1645							errnan = true
1646						}
1647					}()
1648					f(got, xx, yy)
1649				}()
1650				if math.IsNaN(z) {
1651					if !errnan {
1652						t.Errorf("%5g %s %5g = %5s; want ErrNaN panic", x, op, y, got)
1653					}
1654					continue
1655				}
1656				if errnan {
1657					t.Errorf("%5g %s %5g panicked with ErrNan; want %5s", x, op, y, want)
1658					continue
1659				}
1660				want.SetFloat64(z)
1661				if !alike(got, want) {
1662					t.Errorf("%5g %s %5g = %5s; want %5s", x, op, y, got, want)
1663				}
1664			}
1665		}
1666	}
1667}
1668
1669func TestFloatArithmeticOverflow(t *testing.T) {
1670	for _, test := range []struct {
1671		prec       uint
1672		mode       RoundingMode
1673		op         byte
1674		x, y, want string
1675		acc        Accuracy
1676	}{
1677		{4, ToNearestEven, '+', "0", "0", "0", Exact},                   // smoke test
1678		{4, ToNearestEven, '+', "0x.8p+0", "0x.8p+0", "0x.8p+1", Exact}, // smoke test
1679
1680		{4, ToNearestEven, '+', "0", "0x.8p2147483647", "0x.8p+2147483647", Exact},
1681		{4, ToNearestEven, '+', "0x.8p2147483500", "0x.8p2147483647", "0x.8p+2147483647", Below}, // rounded to zero
1682		{4, ToNearestEven, '+', "0x.8p2147483647", "0x.8p2147483647", "+Inf", Above},             // exponent overflow in +
1683		{4, ToNearestEven, '+', "-0x.8p2147483647", "-0x.8p2147483647", "-Inf", Below},           // exponent overflow in +
1684		{4, ToNearestEven, '-', "-0x.8p2147483647", "0x.8p2147483647", "-Inf", Below},            // exponent overflow in -
1685
1686		{4, ToZero, '+', "0x.fp2147483647", "0x.8p2147483643", "0x.fp+2147483647", Below}, // rounded to zero
1687		{4, ToNearestEven, '+', "0x.fp2147483647", "0x.8p2147483643", "+Inf", Above},      // exponent overflow in rounding
1688		{4, AwayFromZero, '+', "0x.fp2147483647", "0x.8p2147483643", "+Inf", Above},       // exponent overflow in rounding
1689
1690		{4, AwayFromZero, '-', "-0x.fp2147483647", "0x.8p2147483644", "-Inf", Below},        // exponent overflow in rounding
1691		{4, ToNearestEven, '-', "-0x.fp2147483647", "0x.8p2147483643", "-Inf", Below},       // exponent overflow in rounding
1692		{4, ToZero, '-', "-0x.fp2147483647", "0x.8p2147483643", "-0x.fp+2147483647", Above}, // rounded to zero
1693
1694		{4, ToNearestEven, '+', "0", "0x.8p-2147483648", "0x.8p-2147483648", Exact},
1695		{4, ToNearestEven, '+', "0x.8p-2147483648", "0x.8p-2147483648", "0x.8p-2147483647", Exact},
1696
1697		{4, ToNearestEven, '*', "1", "0x.8p2147483647", "0x.8p+2147483647", Exact},
1698		{4, ToNearestEven, '*', "2", "0x.8p2147483647", "+Inf", Above},  // exponent overflow in *
1699		{4, ToNearestEven, '*', "-2", "0x.8p2147483647", "-Inf", Below}, // exponent overflow in *
1700
1701		{4, ToNearestEven, '/', "0.5", "0x.8p2147483647", "0x.8p-2147483646", Exact},
1702		{4, ToNearestEven, '/', "0x.8p+0", "0x.8p2147483647", "0x.8p-2147483646", Exact},
1703		{4, ToNearestEven, '/', "0x.8p-1", "0x.8p2147483647", "0x.8p-2147483647", Exact},
1704		{4, ToNearestEven, '/', "0x.8p-2", "0x.8p2147483647", "0x.8p-2147483648", Exact},
1705		{4, ToNearestEven, '/', "0x.8p-3", "0x.8p2147483647", "0", Below}, // exponent underflow in /
1706	} {
1707		x := makeFloat(test.x)
1708		y := makeFloat(test.y)
1709		z := new(Float).SetPrec(test.prec).SetMode(test.mode)
1710		switch test.op {
1711		case '+':
1712			z.Add(x, y)
1713		case '-':
1714			z.Sub(x, y)
1715		case '*':
1716			z.Mul(x, y)
1717		case '/':
1718			z.Quo(x, y)
1719		default:
1720			panic("unreachable")
1721		}
1722		if got := z.Text('p', 0); got != test.want || z.Acc() != test.acc {
1723			t.Errorf(
1724				"prec = %d (%s): %s %c %s = %s (%s); want %s (%s)",
1725				test.prec, test.mode, x.Text('p', 0), test.op, y.Text('p', 0), got, z.Acc(), test.want, test.acc,
1726			)
1727		}
1728	}
1729}
1730
1731// TODO(gri) Add tests that check correctness in the presence of aliasing.
1732
1733// For rounding modes ToNegativeInf and ToPositiveInf, rounding is affected
1734// by the sign of the value to be rounded. Test that rounding happens after
1735// the sign of a result has been set.
1736// This test uses specific values that are known to fail if rounding is
1737// "factored" out before setting the result sign.
1738func TestFloatArithmeticRounding(t *testing.T) {
1739	for _, test := range []struct {
1740		mode       RoundingMode
1741		prec       uint
1742		x, y, want int64
1743		op         byte
1744	}{
1745		{ToZero, 3, -0x8, -0x1, -0x8, '+'},
1746		{AwayFromZero, 3, -0x8, -0x1, -0xa, '+'},
1747		{ToNegativeInf, 3, -0x8, -0x1, -0xa, '+'},
1748
1749		{ToZero, 3, -0x8, 0x1, -0x8, '-'},
1750		{AwayFromZero, 3, -0x8, 0x1, -0xa, '-'},
1751		{ToNegativeInf, 3, -0x8, 0x1, -0xa, '-'},
1752
1753		{ToZero, 3, -0x9, 0x1, -0x8, '*'},
1754		{AwayFromZero, 3, -0x9, 0x1, -0xa, '*'},
1755		{ToNegativeInf, 3, -0x9, 0x1, -0xa, '*'},
1756
1757		{ToZero, 3, -0x9, 0x1, -0x8, '/'},
1758		{AwayFromZero, 3, -0x9, 0x1, -0xa, '/'},
1759		{ToNegativeInf, 3, -0x9, 0x1, -0xa, '/'},
1760	} {
1761		var x, y, z Float
1762		x.SetInt64(test.x)
1763		y.SetInt64(test.y)
1764		z.SetPrec(test.prec).SetMode(test.mode)
1765		switch test.op {
1766		case '+':
1767			z.Add(&x, &y)
1768		case '-':
1769			z.Sub(&x, &y)
1770		case '*':
1771			z.Mul(&x, &y)
1772		case '/':
1773			z.Quo(&x, &y)
1774		default:
1775			panic("unreachable")
1776		}
1777		if got, acc := z.Int64(); got != test.want || acc != Exact {
1778			t.Errorf("%s, %d bits: %d %c %d = %d (%s); want %d (Exact)",
1779				test.mode, test.prec, test.x, test.op, test.y, got, acc, test.want,
1780			)
1781		}
1782	}
1783}
1784
1785// TestFloatCmpSpecialValues tests that Cmp produces the correct results for
1786// combinations of zero (±0), finite (±1 and ±2.71828), and infinite (±Inf)
1787// operands.
1788func TestFloatCmpSpecialValues(t *testing.T) {
1789	zero := 0.0
1790	args := []float64{math.Inf(-1), -2.71828, -1, -zero, zero, 1, 2.71828, math.Inf(1)}
1791	xx := new(Float)
1792	yy := new(Float)
1793	for i := 0; i < 4; i++ {
1794		for _, x := range args {
1795			xx.SetFloat64(x)
1796			// check conversion is correct
1797			// (no need to do this for y, since we see exactly the
1798			// same values there)
1799			if got, acc := xx.Float64(); got != x || acc != Exact {
1800				t.Errorf("Float(%g) == %g (%s)", x, got, acc)
1801			}
1802			for _, y := range args {
1803				yy.SetFloat64(y)
1804				got := xx.Cmp(yy)
1805				want := 0
1806				switch {
1807				case x < y:
1808					want = -1
1809				case x > y:
1810					want = +1
1811				}
1812				if got != want {
1813					t.Errorf("(%g).Cmp(%g) = %v; want %v", x, y, got, want)
1814				}
1815			}
1816		}
1817	}
1818}
1819
1820func BenchmarkFloatAdd(b *testing.B) {
1821	x := new(Float)
1822	y := new(Float)
1823	z := new(Float)
1824
1825	for _, prec := range []uint{10, 1e2, 1e3, 1e4, 1e5} {
1826		x.SetPrec(prec).SetRat(NewRat(1, 3))
1827		y.SetPrec(prec).SetRat(NewRat(1, 6))
1828		z.SetPrec(prec)
1829
1830		b.Run(fmt.Sprintf("%v", prec), func(b *testing.B) {
1831			b.ReportAllocs()
1832			for i := 0; i < b.N; i++ {
1833				z.Add(x, y)
1834			}
1835		})
1836	}
1837}
1838
1839func BenchmarkFloatSub(b *testing.B) {
1840	x := new(Float)
1841	y := new(Float)
1842	z := new(Float)
1843
1844	for _, prec := range []uint{10, 1e2, 1e3, 1e4, 1e5} {
1845		x.SetPrec(prec).SetRat(NewRat(1, 3))
1846		y.SetPrec(prec).SetRat(NewRat(1, 6))
1847		z.SetPrec(prec)
1848
1849		b.Run(fmt.Sprintf("%v", prec), func(b *testing.B) {
1850			b.ReportAllocs()
1851			for i := 0; i < b.N; i++ {
1852				z.Sub(x, y)
1853			}
1854		})
1855	}
1856}
1857