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