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