Source file
src/math/big/float_test.go
1
2
3
4
5 package big
6
7 import (
8 "flag"
9 "fmt"
10 "math"
11 "strconv"
12 "strings"
13 "testing"
14 )
15
16
17 var _ error = ErrNaN{}
18
19 func (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
27 func (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
35 func TestFloatZeroValue(t *testing.T) {
36
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
43 if prec := x.Prec(); prec != 0 {
44 t.Errorf("prec = %d; want 0", prec)
45 }
46
47
48 make := func(x int) *Float {
49 var f Float
50 if x != 0 {
51 f.SetInt64(int64(x))
52 }
53
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
77 {0, 2, 1, 2, '/', (*Float).Quo},
78 {1, 2, 0, 0, '/', (*Float).Quo},
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
93 }
94
95 func 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
103 func TestFloatSetPrec(t *testing.T) {
104 for _, test := range []struct {
105 x string
106 prec uint
107 want string
108 acc Accuracy
109 }{
110
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
119 {"0", MaxPrec, "0", Exact},
120 {"-0", MaxPrec, "-0", Exact},
121 {"-Inf", MaxPrec, "-Inf", Exact},
122 {"+Inf", MaxPrec, "+Inf", Exact},
123
124
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
144 func 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
169 func 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
190 func alike(x, y *Float) bool {
191 return x.Cmp(y) == 0 && x.Signbit() == y.Signbit()
192 }
193
194 func alike32(x, y float32) bool {
195
196 return x == y && math.Signbit(float64(x)) == math.Signbit(float64(y))
197
198 }
199
200 func alike64(x, y float64) bool {
201
202 return x == y && math.Signbit(x) == math.Signbit(y)
203
204 }
205
206 func 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
232 func 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
242 func 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"},
256 {"-0.25", MinExp, "-0"},
257 {"1", MaxExp, "+Inf"},
258 {"2", MaxExp - 1, "+Inf"},
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
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
280 func 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
306 func 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
331 func 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
339 func toBinary(x int64) string {
340 return strconv.FormatInt(x, 2)
341 }
342
343 func testFloatRound(t *testing.T, x, r int64, prec uint, mode RoundingMode) {
344
345 var ok bool
346 switch mode {
347 case ToNearestEven, ToNearestAway:
348 ok = true
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
373 a := Exact
374 switch {
375 case r < x:
376 a = Below
377 case r > x:
378 a = Above
379 }
380
381
382 f := new(Float).SetMode(mode).SetInt64(x).SetPrec(prec)
383
384
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
397
398
399
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
412
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
426 func TestFloatRound(t *testing.T) {
427 for _, test := range []struct {
428 prec uint
429 x, zero, neven, naway, away string
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
524
525
526 func TestFloatRound24(t *testing.T) {
527 const x0 = 1<<26 - 0x10
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
539 func 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
558 const x uint64 = 0x8765432187654321
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)
563 if got != want {
564 t.Errorf("got %#x (%s); want %#x", got, f.Text('p', 0), want)
565 }
566 }
567 }
568
569 func 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
593 const x int64 = 0x7654321076543210
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)
598 if got != want {
599 t.Errorf("got %#x (%s); want %#x", got, f.Text('p', 0), want)
600 }
601 }
602 }
603
604 func 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
636 const x uint64 = 0x8765432143218
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))
641 if got != want {
642 t.Errorf("got %g (%s); want %g", got, f.Text('p', 0), want)
643 }
644 }
645
646
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
655 t.Errorf("got %s; want ErrNaN panic", f.Text('p', 0))
656 }
657
658 func 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
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
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
694 }
695
696 func 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
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
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
736 func 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
755 func 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
785 func 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
825 func 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
834 {"1e-1000", 0, Below},
835 {"0x0.000002p-127", 0, Below},
836 {"0x.0000010p-126", 0, Below},
837
838
839 {"1.401298464e-45", math.SmallestNonzeroFloat32, Above},
840 {"0x.ffffff8p-149", math.SmallestNonzeroFloat32, Above},
841 {"0x.0000018p-126", math.SmallestNonzeroFloat32, Above},
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},
846
847
848 {"0x0.0000001p-126", math.Float32frombits(0x00000000), Below},
849 {"0x0.0000008p-126", math.Float32frombits(0x00000000), Below},
850 {"0x0.0000010p-126", math.Float32frombits(0x00000000), Below},
851 {"0x0.0000011p-126", math.Float32frombits(0x00000001), Above},
852 {"0x0.0000018p-126", math.Float32frombits(0x00000001), Above},
853
854 {"0x1.0000000p-149", math.Float32frombits(0x00000001), Exact},
855 {"0x0.0000020p-126", math.Float32frombits(0x00000001), Exact},
856 {"0x0.fffffe0p-126", math.Float32frombits(0x007fffff), Exact},
857 {"0x1.0000000p-126", math.Float32frombits(0x00800000), Exact},
858
859 {"0x0.8p-149", math.Float32frombits(0x000000000), Below},
860 {"0x0.9p-149", math.Float32frombits(0x000000001), Above},
861 {"0x0.ap-149", math.Float32frombits(0x000000001), Above},
862 {"0x0.bp-149", math.Float32frombits(0x000000001), Above},
863 {"0x0.cp-149", math.Float32frombits(0x000000001), Above},
864
865 {"0x1.0p-149", math.Float32frombits(0x000000001), Exact},
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},
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},
877
878 {"0x4.0p-149", math.Float32frombits(0x000000004), Exact},
879 {"0x4.8p-149", math.Float32frombits(0x000000004), Below},
880 {"0x4.9p-149", math.Float32frombits(0x000000005), Above},
881
882
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
888 {"0x.ffffffp-126", math.Float32frombits(0x00800000), Above},
889 {"1p-126", math.Float32frombits(0x00800000), Exact},
890 {"0x1.fffffep-126", math.Float32frombits(0x00ffffff), Exact},
891 {"0x1.ffffffp-126", math.Float32frombits(0x01000000), Above},
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
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},
904
905
906 {"Inf", float32(math.Inf(+1)), Exact},
907 } {
908 for i := 0; i < 2; i++ {
909
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
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
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
938 func TestFloatFloat64(t *testing.T) {
939 const smallestNormalFloat64 = 2.2250738585072014e-308
940 for _, test := range []struct {
941 x string
942 out float64
943 acc Accuracy
944 }{
945 {"0", 0, Exact},
946
947
948 {"1e-1000", 0, Below},
949 {"0x0.0000000000001p-1023", 0, Below},
950 {"0x0.00000000000008p-1022", 0, Below},
951
952
953 {"0x0.0000000000000cp-1022", math.SmallestNonzeroFloat64, Above},
954 {"0x0.00000000000010p-1022", math.SmallestNonzeroFloat64, Exact},
955 {"0x.8p-1073", math.SmallestNonzeroFloat64, Exact},
956 {"1p-1074", math.SmallestNonzeroFloat64, Exact},
957 {"0x.fffffffffffffp-1022", math.Float64frombits(0x000fffffffffffff), Exact},
958
959
960 {"0x0.00000000000001p-1022", math.Float64frombits(0x00000000000000000), Below},
961 {"0x0.00000000000004p-1022", math.Float64frombits(0x00000000000000000), Below},
962 {"0x0.00000000000008p-1022", math.Float64frombits(0x00000000000000000), Below},
963 {"0x0.00000000000009p-1022", math.Float64frombits(0x00000000000000001), Above},
964 {"0x0.0000000000000ap-1022", math.Float64frombits(0x00000000000000001), Above},
965
966 {"0x0.8p-1074", math.Float64frombits(0x00000000000000000), Below},
967 {"0x0.9p-1074", math.Float64frombits(0x00000000000000001), Above},
968 {"0x0.ap-1074", math.Float64frombits(0x00000000000000001), Above},
969 {"0x0.bp-1074", math.Float64frombits(0x00000000000000001), Above},
970 {"0x0.cp-1074", math.Float64frombits(0x00000000000000001), Above},
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},
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},
984
985 {"0x4.0p-1074", math.Float64frombits(0x00000000000000004), Exact},
986 {"0x4.8p-1074", math.Float64frombits(0x00000000000000004), Below},
987 {"0x4.9p-1074", math.Float64frombits(0x00000000000000005), Above},
988
989
990 {"0x.fffffffffffff8p-1022", math.Float64frombits(0x0010000000000000), Above},
991 {"1p-1022", math.Float64frombits(0x0010000000000000), Exact},
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
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},
1004 {"Inf", math.Inf(+1), Exact},
1005
1006
1007 {"0x.fffffffffffffp-1022", smallestNormalFloat64 - math.SmallestNonzeroFloat64, Exact},
1008 {"4503599627370495p-1074", smallestNormalFloat64 - math.SmallestNonzeroFloat64, Exact},
1009
1010
1011 {"2.2250738585072011e-308", 2.225073858507201e-308, Below},
1012
1013 {"2.2250738585072012e-308", 2.2250738585072014e-308, Above},
1014 } {
1015 for i := 0; i < 2; i++ {
1016
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
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
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
1045 func 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
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
1090 func 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
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
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
1144 func 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
1168 func 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
1191 func TestFloatInc(t *testing.T) {
1192 const n = 10
1193 for _, prec := range precList {
1194 if 1<<prec < n {
1195 continue
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
1210 var precList = [...]uint{1, 2, 5, 8, 10, 16, 23, 24, 32, 50, 53, 64, 100, 128, 500, 511, 512, 513, 1000, 10000}
1211
1212
1213
1214 var bitsList = [...]Bits{
1215 {},
1216 {0},
1217 {1},
1218 {-1},
1219 {10},
1220 {-10},
1221 {100, 10, 1},
1222 {0, -1, -2, -10},
1223
1224 }
1225
1226
1227
1228
1229
1230 func TestFloatAdd(t *testing.T) {
1231 for _, xbits := range bitsList {
1232 for _, ybits := range bitsList {
1233
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
1262
1263
1264 func 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
1287
1288
1289 func TestFloatAdd32(t *testing.T) {
1290
1291 const base = 1<<26 - 0x10
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
1321
1322 func TestFloatAdd64(t *testing.T) {
1323
1324 const base = 1<<55 - 0x10
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
1353 func 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
1382
1383
1384
1385 func TestFloatMul(t *testing.T) {
1386 for _, xbits := range bitsList {
1387 for _, ybits := range bitsList {
1388
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
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
1420
1421 func 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
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
1470 func 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
1483 p.Quo(one, three)
1484 p.Mul(p, msix)
1485 z1.Add(two, p)
1486
1487
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
1504 func TestFloatQuo(t *testing.T) {
1505
1506 preci := 200
1507 precf := 20
1508
1509 for i := 0; i < 8; i++ {
1510
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
1524 y := NewFloat(3.14159265358979323e123)
1525
1526 x := new(Float).SetPrec(z.Prec() + y.Prec()).SetMode(ToZero)
1527 x.Mul(z, y)
1528
1529
1530
1531
1532 if got := x.Acc(); got != Exact {
1533 t.Errorf("got acc = %s; want exact", got)
1534 }
1535
1536
1537
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
1552 var long = flag.Bool("long", false, "run very long tests")
1553
1554
1555
1556 func TestFloatQuoSmoke(t *testing.T) {
1557 n := 10
1558 if *long {
1559 n = 1000
1560 }
1561
1562 const dprec = 3
1563 const prec = 10 + dprec
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
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)
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
1596
1597
1598 func 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
1609
1610
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
1642
1643 func() {
1644 defer func() {
1645 if p := recover(); p != nil {
1646 _ = p.(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
1671 func 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},
1680 {4, ToNearestEven, '+', "0x.8p+0", "0x.8p+0", "0x.8p+1", Exact},
1681
1682 {4, ToNearestEven, '+', "0", "0x.8p2147483647", "0x.8p+2147483647", Exact},
1683 {4, ToNearestEven, '+', "0x.8p2147483500", "0x.8p2147483647", "0x.8p+2147483647", Below},
1684 {4, ToNearestEven, '+', "0x.8p2147483647", "0x.8p2147483647", "+Inf", Above},
1685 {4, ToNearestEven, '+', "-0x.8p2147483647", "-0x.8p2147483647", "-Inf", Below},
1686 {4, ToNearestEven, '-', "-0x.8p2147483647", "0x.8p2147483647", "-Inf", Below},
1687
1688 {4, ToZero, '+', "0x.fp2147483647", "0x.8p2147483643", "0x.fp+2147483647", Below},
1689 {4, ToNearestEven, '+', "0x.fp2147483647", "0x.8p2147483643", "+Inf", Above},
1690 {4, AwayFromZero, '+', "0x.fp2147483647", "0x.8p2147483643", "+Inf", Above},
1691
1692 {4, AwayFromZero, '-', "-0x.fp2147483647", "0x.8p2147483644", "-Inf", Below},
1693 {4, ToNearestEven, '-', "-0x.fp2147483647", "0x.8p2147483643", "-Inf", Below},
1694 {4, ToZero, '-', "-0x.fp2147483647", "0x.8p2147483643", "-0x.fp+2147483647", Above},
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},
1701 {4, ToNearestEven, '*', "-2", "0x.8p2147483647", "-Inf", Below},
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},
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
1734
1735
1736
1737
1738
1739
1740 func 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
1788
1789
1790 func 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
1799
1800
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
1822 func 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
1841 func 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
View as plain text