2014-04-11 Marc Glisse <marc.glisse@inria.fr>
[official-gcc.git] / libgo / go / math / big / rat_test.go
blob0d432637ba19764d65d7ef4f138d72bd652c1c84
1 // Copyright 2010 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 package big
7 import (
8 "bytes"
9 "encoding/gob"
10 "fmt"
11 "math"
12 "strconv"
13 "strings"
14 "testing"
17 func TestZeroRat(t *testing.T) {
18 var x, y, z Rat
19 y.SetFrac64(0, 42)
21 if x.Cmp(&y) != 0 {
22 t.Errorf("x and y should be both equal and zero")
25 if s := x.String(); s != "0/1" {
26 t.Errorf("got x = %s, want 0/1", s)
29 if s := x.RatString(); s != "0" {
30 t.Errorf("got x = %s, want 0", s)
33 z.Add(&x, &y)
34 if s := z.RatString(); s != "0" {
35 t.Errorf("got x+y = %s, want 0", s)
38 z.Sub(&x, &y)
39 if s := z.RatString(); s != "0" {
40 t.Errorf("got x-y = %s, want 0", s)
43 z.Mul(&x, &y)
44 if s := z.RatString(); s != "0" {
45 t.Errorf("got x*y = %s, want 0", s)
48 // check for division by zero
49 defer func() {
50 if s := recover(); s == nil || s.(string) != "division by zero" {
51 panic(s)
53 }()
54 z.Quo(&x, &y)
57 var setStringTests = []struct {
58 in, out string
59 ok bool
61 {"0", "0", true},
62 {"-0", "0", true},
63 {"1", "1", true},
64 {"-1", "-1", true},
65 {"1.", "1", true},
66 {"1e0", "1", true},
67 {"1.e1", "10", true},
68 {in: "1e", ok: false},
69 {in: "1.e", ok: false},
70 {in: "1e+14e-5", ok: false},
71 {in: "1e4.5", ok: false},
72 {in: "r", ok: false},
73 {in: "a/b", ok: false},
74 {in: "a.b", ok: false},
75 {"-0.1", "-1/10", true},
76 {"-.1", "-1/10", true},
77 {"2/4", "1/2", true},
78 {".25", "1/4", true},
79 {"-1/5", "-1/5", true},
80 {"8129567.7690E14", "812956776900000000000", true},
81 {"78189e+4", "781890000", true},
82 {"553019.8935e+8", "55301989350000", true},
83 {"98765432109876543210987654321e-10", "98765432109876543210987654321/10000000000", true},
84 {"9877861857500000E-7", "3951144743/4", true},
85 {"2169378.417e-3", "2169378417/1000000", true},
86 {"884243222337379604041632732738665534", "884243222337379604041632732738665534", true},
87 {"53/70893980658822810696", "53/70893980658822810696", true},
88 {"106/141787961317645621392", "53/70893980658822810696", true},
89 {"204211327800791583.81095", "4084226556015831676219/20000", true},
92 func TestRatSetString(t *testing.T) {
93 for i, test := range setStringTests {
94 x, ok := new(Rat).SetString(test.in)
96 if ok {
97 if !test.ok {
98 t.Errorf("#%d SetString(%q) expected failure", i, test.in)
99 } else if x.RatString() != test.out {
100 t.Errorf("#%d SetString(%q) got %s want %s", i, test.in, x.RatString(), test.out)
102 } else if x != nil {
103 t.Errorf("#%d SetString(%q) got %p want nil", i, test.in, x)
108 func TestRatScan(t *testing.T) {
109 var buf bytes.Buffer
110 for i, test := range setStringTests {
111 x := new(Rat)
112 buf.Reset()
113 buf.WriteString(test.in)
115 _, err := fmt.Fscanf(&buf, "%v", x)
116 if err == nil != test.ok {
117 if test.ok {
118 t.Errorf("#%d error: %s", i, err)
119 } else {
120 t.Errorf("#%d expected error", i)
122 continue
124 if err == nil && x.RatString() != test.out {
125 t.Errorf("#%d got %s want %s", i, x.RatString(), test.out)
130 var floatStringTests = []struct {
131 in string
132 prec int
133 out string
135 {"0", 0, "0"},
136 {"0", 4, "0.0000"},
137 {"1", 0, "1"},
138 {"1", 2, "1.00"},
139 {"-1", 0, "-1"},
140 {".25", 2, "0.25"},
141 {".25", 1, "0.3"},
142 {".25", 3, "0.250"},
143 {"-1/3", 3, "-0.333"},
144 {"-2/3", 4, "-0.6667"},
145 {"0.96", 1, "1.0"},
146 {"0.999", 2, "1.00"},
147 {"0.9", 0, "1"},
148 {".25", -1, "0"},
149 {".55", -1, "1"},
152 func TestFloatString(t *testing.T) {
153 for i, test := range floatStringTests {
154 x, _ := new(Rat).SetString(test.in)
156 if x.FloatString(test.prec) != test.out {
157 t.Errorf("#%d got %s want %s", i, x.FloatString(test.prec), test.out)
162 func TestRatSign(t *testing.T) {
163 zero := NewRat(0, 1)
164 for _, a := range setStringTests {
165 x, ok := new(Rat).SetString(a.in)
166 if !ok {
167 continue
169 s := x.Sign()
170 e := x.Cmp(zero)
171 if s != e {
172 t.Errorf("got %d; want %d for z = %v", s, e, &x)
177 var ratCmpTests = []struct {
178 rat1, rat2 string
179 out int
181 {"0", "0/1", 0},
182 {"1/1", "1", 0},
183 {"-1", "-2/2", 0},
184 {"1", "0", 1},
185 {"0/1", "1/1", -1},
186 {"-5/1434770811533343057144", "-5/1434770811533343057145", -1},
187 {"49832350382626108453/8964749413", "49832350382626108454/8964749413", -1},
188 {"-37414950961700930/7204075375675961", "37414950961700930/7204075375675961", -1},
189 {"37414950961700930/7204075375675961", "74829901923401860/14408150751351922", 0},
192 func TestRatCmp(t *testing.T) {
193 for i, test := range ratCmpTests {
194 x, _ := new(Rat).SetString(test.rat1)
195 y, _ := new(Rat).SetString(test.rat2)
197 out := x.Cmp(y)
198 if out != test.out {
199 t.Errorf("#%d got out = %v; want %v", i, out, test.out)
204 func TestIsInt(t *testing.T) {
205 one := NewInt(1)
206 for _, a := range setStringTests {
207 x, ok := new(Rat).SetString(a.in)
208 if !ok {
209 continue
211 i := x.IsInt()
212 e := x.Denom().Cmp(one) == 0
213 if i != e {
214 t.Errorf("got IsInt(%v) == %v; want %v", x, i, e)
219 func TestRatAbs(t *testing.T) {
220 zero := new(Rat)
221 for _, a := range setStringTests {
222 x, ok := new(Rat).SetString(a.in)
223 if !ok {
224 continue
226 e := new(Rat).Set(x)
227 if e.Cmp(zero) < 0 {
228 e.Sub(zero, e)
230 z := new(Rat).Abs(x)
231 if z.Cmp(e) != 0 {
232 t.Errorf("got Abs(%v) = %v; want %v", x, z, e)
237 func TestRatNeg(t *testing.T) {
238 zero := new(Rat)
239 for _, a := range setStringTests {
240 x, ok := new(Rat).SetString(a.in)
241 if !ok {
242 continue
244 e := new(Rat).Sub(zero, x)
245 z := new(Rat).Neg(x)
246 if z.Cmp(e) != 0 {
247 t.Errorf("got Neg(%v) = %v; want %v", x, z, e)
252 func TestRatInv(t *testing.T) {
253 zero := new(Rat)
254 for _, a := range setStringTests {
255 x, ok := new(Rat).SetString(a.in)
256 if !ok {
257 continue
259 if x.Cmp(zero) == 0 {
260 continue // avoid division by zero
262 e := new(Rat).SetFrac(x.Denom(), x.Num())
263 z := new(Rat).Inv(x)
264 if z.Cmp(e) != 0 {
265 t.Errorf("got Inv(%v) = %v; want %v", x, z, e)
270 type ratBinFun func(z, x, y *Rat) *Rat
271 type ratBinArg struct {
272 x, y, z string
275 func testRatBin(t *testing.T, i int, name string, f ratBinFun, a ratBinArg) {
276 x, _ := new(Rat).SetString(a.x)
277 y, _ := new(Rat).SetString(a.y)
278 z, _ := new(Rat).SetString(a.z)
279 out := f(new(Rat), x, y)
281 if out.Cmp(z) != 0 {
282 t.Errorf("%s #%d got %s want %s", name, i, out, z)
286 var ratBinTests = []struct {
287 x, y string
288 sum, prod string
290 {"0", "0", "0", "0"},
291 {"0", "1", "1", "0"},
292 {"-1", "0", "-1", "0"},
293 {"-1", "1", "0", "-1"},
294 {"1", "1", "2", "1"},
295 {"1/2", "1/2", "1", "1/4"},
296 {"1/4", "1/3", "7/12", "1/12"},
297 {"2/5", "-14/3", "-64/15", "-28/15"},
298 {"4707/49292519774798173060", "-3367/70976135186689855734", "84058377121001851123459/1749296273614329067191168098769082663020", "-1760941/388732505247628681598037355282018369560"},
299 {"-61204110018146728334/3", "-31052192278051565633/2", "-215564796870448153567/6", "950260896245257153059642991192710872711/3"},
300 {"-854857841473707320655/4237645934602118692642972629634714039", "-18/31750379913563777419", "-27/133467566250814981", "15387441146526731771790/134546868362786310073779084329032722548987800600710485341"},
301 {"618575745270541348005638912139/19198433543745179392300736", "-19948846211000086/637313996471", "27674141753240653/30123979153216", "-6169936206128396568797607742807090270137721977/6117715203873571641674006593837351328"},
302 {"-3/26206484091896184128", "5/2848423294177090248", "15310893822118706237/9330894968229805033368778458685147968", "-5/24882386581946146755650075889827061248"},
303 {"26946729/330400702820", "41563965/225583428284", "1238218672302860271/4658307703098666660055", "224002580204097/14906584649915733312176"},
304 {"-8259900599013409474/7", "-84829337473700364773/56707961321161574960", "-468402123685491748914621885145127724451/396955729248131024720", "350340947706464153265156004876107029701/198477864624065512360"},
305 {"575775209696864/1320203974639986246357", "29/712593081308", "410331716733912717985762465/940768218243776489278275419794956", "808/45524274987585732633"},
306 {"1786597389946320496771/2066653520653241", "6269770/1992362624741777", "3559549865190272133656109052308126637/4117523232840525481453983149257", "8967230/3296219033"},
307 {"-36459180403360509753/32150500941194292113930", "9381566963714/9633539", "301622077145533298008420642898530153/309723104686531919656937098270", "-3784609207827/3426986245"},
310 func TestRatBin(t *testing.T) {
311 for i, test := range ratBinTests {
312 arg := ratBinArg{test.x, test.y, test.sum}
313 testRatBin(t, i, "Add", (*Rat).Add, arg)
315 arg = ratBinArg{test.y, test.x, test.sum}
316 testRatBin(t, i, "Add symmetric", (*Rat).Add, arg)
318 arg = ratBinArg{test.sum, test.x, test.y}
319 testRatBin(t, i, "Sub", (*Rat).Sub, arg)
321 arg = ratBinArg{test.sum, test.y, test.x}
322 testRatBin(t, i, "Sub symmetric", (*Rat).Sub, arg)
324 arg = ratBinArg{test.x, test.y, test.prod}
325 testRatBin(t, i, "Mul", (*Rat).Mul, arg)
327 arg = ratBinArg{test.y, test.x, test.prod}
328 testRatBin(t, i, "Mul symmetric", (*Rat).Mul, arg)
330 if test.x != "0" {
331 arg = ratBinArg{test.prod, test.x, test.y}
332 testRatBin(t, i, "Quo", (*Rat).Quo, arg)
335 if test.y != "0" {
336 arg = ratBinArg{test.prod, test.y, test.x}
337 testRatBin(t, i, "Quo symmetric", (*Rat).Quo, arg)
342 func TestIssue820(t *testing.T) {
343 x := NewRat(3, 1)
344 y := NewRat(2, 1)
345 z := y.Quo(x, y)
346 q := NewRat(3, 2)
347 if z.Cmp(q) != 0 {
348 t.Errorf("got %s want %s", z, q)
351 y = NewRat(3, 1)
352 x = NewRat(2, 1)
353 z = y.Quo(x, y)
354 q = NewRat(2, 3)
355 if z.Cmp(q) != 0 {
356 t.Errorf("got %s want %s", z, q)
359 x = NewRat(3, 1)
360 z = x.Quo(x, x)
361 q = NewRat(3, 3)
362 if z.Cmp(q) != 0 {
363 t.Errorf("got %s want %s", z, q)
367 var setFrac64Tests = []struct {
368 a, b int64
369 out string
371 {0, 1, "0"},
372 {0, -1, "0"},
373 {1, 1, "1"},
374 {-1, 1, "-1"},
375 {1, -1, "-1"},
376 {-1, -1, "1"},
377 {-9223372036854775808, -9223372036854775808, "1"},
380 func TestRatSetFrac64Rat(t *testing.T) {
381 for i, test := range setFrac64Tests {
382 x := new(Rat).SetFrac64(test.a, test.b)
383 if x.RatString() != test.out {
384 t.Errorf("#%d got %s want %s", i, x.RatString(), test.out)
389 func TestRatGobEncoding(t *testing.T) {
390 var medium bytes.Buffer
391 enc := gob.NewEncoder(&medium)
392 dec := gob.NewDecoder(&medium)
393 for _, test := range encodingTests {
394 medium.Reset() // empty buffer for each test case (in case of failures)
395 var tx Rat
396 tx.SetString(test + ".14159265")
397 if err := enc.Encode(&tx); err != nil {
398 t.Errorf("encoding of %s failed: %s", &tx, err)
400 var rx Rat
401 if err := dec.Decode(&rx); err != nil {
402 t.Errorf("decoding of %s failed: %s", &tx, err)
404 if rx.Cmp(&tx) != 0 {
405 t.Errorf("transmission of %s failed: got %s want %s", &tx, &rx, &tx)
410 // Sending a nil Rat pointer (inside a slice) on a round trip through gob should yield a zero.
411 // TODO: top-level nils.
412 func TestGobEncodingNilRatInSlice(t *testing.T) {
413 buf := new(bytes.Buffer)
414 enc := gob.NewEncoder(buf)
415 dec := gob.NewDecoder(buf)
417 var in = make([]*Rat, 1)
418 err := enc.Encode(&in)
419 if err != nil {
420 t.Errorf("gob encode failed: %q", err)
422 var out []*Rat
423 err = dec.Decode(&out)
424 if err != nil {
425 t.Fatalf("gob decode failed: %q", err)
427 if len(out) != 1 {
428 t.Fatalf("wrong len; want 1 got %d", len(out))
430 var zero Rat
431 if out[0].Cmp(&zero) != 0 {
432 t.Errorf("transmission of (*Int)(nill) failed: got %s want 0", out)
436 func TestIssue2379(t *testing.T) {
437 // 1) no aliasing
438 q := NewRat(3, 2)
439 x := new(Rat)
440 x.SetFrac(NewInt(3), NewInt(2))
441 if x.Cmp(q) != 0 {
442 t.Errorf("1) got %s want %s", x, q)
445 // 2) aliasing of numerator
446 x = NewRat(2, 3)
447 x.SetFrac(NewInt(3), x.Num())
448 if x.Cmp(q) != 0 {
449 t.Errorf("2) got %s want %s", x, q)
452 // 3) aliasing of denominator
453 x = NewRat(2, 3)
454 x.SetFrac(x.Denom(), NewInt(2))
455 if x.Cmp(q) != 0 {
456 t.Errorf("3) got %s want %s", x, q)
459 // 4) aliasing of numerator and denominator
460 x = NewRat(2, 3)
461 x.SetFrac(x.Denom(), x.Num())
462 if x.Cmp(q) != 0 {
463 t.Errorf("4) got %s want %s", x, q)
466 // 5) numerator and denominator are the same
467 q = NewRat(1, 1)
468 x = new(Rat)
469 n := NewInt(7)
470 x.SetFrac(n, n)
471 if x.Cmp(q) != 0 {
472 t.Errorf("5) got %s want %s", x, q)
476 func TestIssue3521(t *testing.T) {
477 a := new(Int)
478 b := new(Int)
479 a.SetString("64375784358435883458348587", 0)
480 b.SetString("4789759874531", 0)
482 // 0) a raw zero value has 1 as denominator
483 zero := new(Rat)
484 one := NewInt(1)
485 if zero.Denom().Cmp(one) != 0 {
486 t.Errorf("0) got %s want %s", zero.Denom(), one)
489 // 1a) a zero value remains zero independent of denominator
490 x := new(Rat)
491 x.Denom().Set(new(Int).Neg(b))
492 if x.Cmp(zero) != 0 {
493 t.Errorf("1a) got %s want %s", x, zero)
496 // 1b) a zero value may have a denominator != 0 and != 1
497 x.Num().Set(a)
498 qab := new(Rat).SetFrac(a, b)
499 if x.Cmp(qab) != 0 {
500 t.Errorf("1b) got %s want %s", x, qab)
503 // 2a) an integral value becomes a fraction depending on denominator
504 x.SetFrac64(10, 2)
505 x.Denom().SetInt64(3)
506 q53 := NewRat(5, 3)
507 if x.Cmp(q53) != 0 {
508 t.Errorf("2a) got %s want %s", x, q53)
511 // 2b) an integral value becomes a fraction depending on denominator
512 x = NewRat(10, 2)
513 x.Denom().SetInt64(3)
514 if x.Cmp(q53) != 0 {
515 t.Errorf("2b) got %s want %s", x, q53)
518 // 3) changing the numerator/denominator of a Rat changes the Rat
519 x.SetFrac(a, b)
520 a = x.Num()
521 b = x.Denom()
522 a.SetInt64(5)
523 b.SetInt64(3)
524 if x.Cmp(q53) != 0 {
525 t.Errorf("3) got %s want %s", x, q53)
529 // Test inputs to Rat.SetString. The prefix "long:" causes the test
530 // to be skipped in --test.short mode. (The threshold is about 500us.)
531 var float64inputs = []string{
532 // Constants plundered from strconv/testfp.txt.
534 // Table 1: Stress Inputs for Conversion to 53-bit Binary, < 1/2 ULP
535 "5e+125",
536 "69e+267",
537 "999e-026",
538 "7861e-034",
539 "75569e-254",
540 "928609e-261",
541 "9210917e+080",
542 "84863171e+114",
543 "653777767e+273",
544 "5232604057e-298",
545 "27235667517e-109",
546 "653532977297e-123",
547 "3142213164987e-294",
548 "46202199371337e-072",
549 "231010996856685e-073",
550 "9324754620109615e+212",
551 "78459735791271921e+049",
552 "272104041512242479e+200",
553 "6802601037806061975e+198",
554 "20505426358836677347e-221",
555 "836168422905420598437e-234",
556 "4891559871276714924261e+222",
558 // Table 2: Stress Inputs for Conversion to 53-bit Binary, > 1/2 ULP
559 "9e-265",
560 "85e-037",
561 "623e+100",
562 "3571e+263",
563 "81661e+153",
564 "920657e-023",
565 "4603285e-024",
566 "87575437e-309",
567 "245540327e+122",
568 "6138508175e+120",
569 "83356057653e+193",
570 "619534293513e+124",
571 "2335141086879e+218",
572 "36167929443327e-159",
573 "609610927149051e-255",
574 "3743626360493413e-165",
575 "94080055902682397e-242",
576 "899810892172646163e+283",
577 "7120190517612959703e+120",
578 "25188282901709339043e-252",
579 "308984926168550152811e-052",
580 "6372891218502368041059e+064",
582 // Table 14: Stress Inputs for Conversion to 24-bit Binary, <1/2 ULP
583 "5e-20",
584 "67e+14",
585 "985e+15",
586 "7693e-42",
587 "55895e-16",
588 "996622e-44",
589 "7038531e-32",
590 "60419369e-46",
591 "702990899e-20",
592 "6930161142e-48",
593 "25933168707e+13",
594 "596428896559e+20",
596 // Table 15: Stress Inputs for Conversion to 24-bit Binary, >1/2 ULP
597 "3e-23",
598 "57e+18",
599 "789e-35",
600 "2539e-18",
601 "76173e+28",
602 "887745e-11",
603 "5382571e-37",
604 "82381273e-35",
605 "750486563e-38",
606 "3752432815e-39",
607 "75224575729e-45",
608 "459926601011e+15",
610 // Constants plundered from strconv/atof_test.go.
612 "0",
613 "1",
614 "+1",
615 "1e23",
616 "1E23",
617 "100000000000000000000000",
618 "1e-100",
619 "123456700",
620 "99999999999999974834176",
621 "100000000000000000000001",
622 "100000000000000008388608",
623 "100000000000000016777215",
624 "100000000000000016777216",
625 "-1",
626 "-0.1",
627 "-0", // NB: exception made for this input
628 "1e-20",
629 "625e-3",
631 // largest float64
632 "1.7976931348623157e308",
633 "-1.7976931348623157e308",
634 // next float64 - too large
635 "1.7976931348623159e308",
636 "-1.7976931348623159e308",
637 // the border is ...158079
638 // borderline - okay
639 "1.7976931348623158e308",
640 "-1.7976931348623158e308",
641 // borderline - too large
642 "1.797693134862315808e308",
643 "-1.797693134862315808e308",
645 // a little too large
646 "1e308",
647 "2e308",
648 "1e309",
650 // way too large
651 "1e310",
652 "-1e310",
653 "1e400",
654 "-1e400",
655 "long:1e400000",
656 "long:-1e400000",
658 // denormalized
659 "1e-305",
660 "1e-306",
661 "1e-307",
662 "1e-308",
663 "1e-309",
664 "1e-310",
665 "1e-322",
666 // smallest denormal
667 "5e-324",
668 "4e-324",
669 "3e-324",
670 // too small
671 "2e-324",
672 // way too small
673 "1e-350",
674 "long:1e-400000",
675 // way too small, negative
676 "-1e-350",
677 "long:-1e-400000",
679 // try to overflow exponent
680 // [Disabled: too slow and memory-hungry with rationals.]
681 // "1e-4294967296",
682 // "1e+4294967296",
683 // "1e-18446744073709551616",
684 // "1e+18446744073709551616",
686 // http://www.exploringbinary.com/java-hangs-when-converting-2-2250738585072012e-308/
687 "2.2250738585072012e-308",
688 // http://www.exploringbinary.com/php-hangs-on-numeric-value-2-2250738585072011e-308/
690 "2.2250738585072011e-308",
692 // A very large number (initially wrongly parsed by the fast algorithm).
693 "4.630813248087435e+307",
695 // A different kind of very large number.
696 "22.222222222222222",
697 "long:2." + strings.Repeat("2", 4000) + "e+1",
699 // Exactly halfway between 1 and math.Nextafter(1, 2).
700 // Round to even (down).
701 "1.00000000000000011102230246251565404236316680908203125",
702 // Slightly lower; still round down.
703 "1.00000000000000011102230246251565404236316680908203124",
704 // Slightly higher; round up.
705 "1.00000000000000011102230246251565404236316680908203126",
706 // Slightly higher, but you have to read all the way to the end.
707 "long:1.00000000000000011102230246251565404236316680908203125" + strings.Repeat("0", 10000) + "1",
709 // Smallest denormal, 2^(-1022-52)
710 "4.940656458412465441765687928682213723651e-324",
711 // Half of smallest denormal, 2^(-1022-53)
712 "2.470328229206232720882843964341106861825e-324",
713 // A little more than the exact half of smallest denormal
714 // 2^-1075 + 2^-1100. (Rounds to 1p-1074.)
715 "2.470328302827751011111470718709768633275e-324",
716 // The exact halfway between smallest normal and largest denormal:
717 // 2^-1022 - 2^-1075. (Rounds to 2^-1022.)
718 "2.225073858507201136057409796709131975935e-308",
720 "1152921504606846975", // 1<<60 - 1
721 "-1152921504606846975", // -(1<<60 - 1)
722 "1152921504606846977", // 1<<60 + 1
723 "-1152921504606846977", // -(1<<60 + 1)
725 "1/3",
728 func TestFloat64SpecialCases(t *testing.T) {
729 for _, input := range float64inputs {
730 if strings.HasPrefix(input, "long:") {
731 if testing.Short() {
732 continue
734 input = input[len("long:"):]
737 r, ok := new(Rat).SetString(input)
738 if !ok {
739 t.Errorf("Rat.SetString(%q) failed", input)
740 continue
742 f, exact := r.Float64()
744 // 1. Check string -> Rat -> float64 conversions are
745 // consistent with strconv.ParseFloat.
746 // Skip this check if the input uses "a/b" rational syntax.
747 if !strings.Contains(input, "/") {
748 e, _ := strconv.ParseFloat(input, 64)
750 // Careful: negative Rats too small for
751 // float64 become -0, but Rat obviously cannot
752 // preserve the sign from SetString("-0").
753 switch {
754 case math.Float64bits(e) == math.Float64bits(f):
755 // Ok: bitwise equal.
756 case f == 0 && r.Num().BitLen() == 0:
757 // Ok: Rat(0) is equivalent to both +/- float64(0).
758 default:
759 t.Errorf("strconv.ParseFloat(%q) = %g (%b), want %g (%b); delta = %g", input, e, e, f, f, f-e)
763 if !isFinite(f) {
764 continue
767 // 2. Check f is best approximation to r.
768 if !checkIsBestApprox(t, f, r) {
769 // Append context information.
770 t.Errorf("(input was %q)", input)
773 // 3. Check f->R->f roundtrip is non-lossy.
774 checkNonLossyRoundtrip(t, f)
776 // 4. Check exactness using slow algorithm.
777 if wasExact := new(Rat).SetFloat64(f).Cmp(r) == 0; wasExact != exact {
778 t.Errorf("Rat.SetString(%q).Float64().exact = %t, want %t", input, exact, wasExact)
783 func TestFloat64Distribution(t *testing.T) {
784 // Generate a distribution of (sign, mantissa, exp) values
785 // broader than the float64 range, and check Rat.Float64()
786 // always picks the closest float64 approximation.
787 var add = []int64{
796 var winc, einc = uint64(1), int(1) // soak test (~75s on x86-64)
797 if testing.Short() {
798 winc, einc = 10, 500 // quick test (~12ms on x86-64)
801 for _, sign := range "+-" {
802 for _, a := range add {
803 for wid := uint64(0); wid < 60; wid += winc {
804 b := int64(1<<wid + a)
805 if sign == '-' {
806 b = -b
808 for exp := -1100; exp < 1100; exp += einc {
809 num, den := NewInt(b), NewInt(1)
810 if exp > 0 {
811 num.Lsh(num, uint(exp))
812 } else {
813 den.Lsh(den, uint(-exp))
815 r := new(Rat).SetFrac(num, den)
816 f, _ := r.Float64()
818 if !checkIsBestApprox(t, f, r) {
819 // Append context information.
820 t.Errorf("(input was mantissa %#x, exp %d; f = %g (%b); f ~ %g; r = %v)",
821 b, exp, f, f, math.Ldexp(float64(b), exp), r)
824 checkNonLossyRoundtrip(t, f)
831 // TestFloat64NonFinite checks that SetFloat64 of a non-finite value
832 // returns nil.
833 func TestSetFloat64NonFinite(t *testing.T) {
834 for _, f := range []float64{math.NaN(), math.Inf(+1), math.Inf(-1)} {
835 var r Rat
836 if r2 := r.SetFloat64(f); r2 != nil {
837 t.Errorf("SetFloat64(%g) was %v, want nil", f, r2)
842 // checkNonLossyRoundtrip checks that a float->Rat->float roundtrip is
843 // non-lossy for finite f.
844 func checkNonLossyRoundtrip(t *testing.T, f float64) {
845 if !isFinite(f) {
846 return
848 r := new(Rat).SetFloat64(f)
849 if r == nil {
850 t.Errorf("Rat.SetFloat64(%g (%b)) == nil", f, f)
851 return
853 f2, exact := r.Float64()
854 if f != f2 || !exact {
855 t.Errorf("Rat.SetFloat64(%g).Float64() = %g (%b), %v, want %g (%b), %v; delta = %b",
856 f, f2, f2, exact, f, f, true, f2-f)
860 // delta returns the absolute difference between r and f.
861 func delta(r *Rat, f float64) *Rat {
862 d := new(Rat).Sub(r, new(Rat).SetFloat64(f))
863 return d.Abs(d)
866 // checkIsBestApprox checks that f is the best possible float64
867 // approximation of r.
868 // Returns true on success.
869 func checkIsBestApprox(t *testing.T, f float64, r *Rat) bool {
870 if math.Abs(f) >= math.MaxFloat64 {
871 // Cannot check +Inf, -Inf, nor the float next to them (MaxFloat64).
872 // But we have tests for these special cases.
873 return true
876 // r must be strictly between f0 and f1, the floats bracketing f.
877 f0 := math.Nextafter(f, math.Inf(-1))
878 f1 := math.Nextafter(f, math.Inf(+1))
880 // For f to be correct, r must be closer to f than to f0 or f1.
881 df := delta(r, f)
882 df0 := delta(r, f0)
883 df1 := delta(r, f1)
884 if df.Cmp(df0) > 0 {
885 t.Errorf("Rat(%v).Float64() = %g (%b), but previous float64 %g (%b) is closer", r, f, f, f0, f0)
886 return false
888 if df.Cmp(df1) > 0 {
889 t.Errorf("Rat(%v).Float64() = %g (%b), but next float64 %g (%b) is closer", r, f, f, f1, f1)
890 return false
892 if df.Cmp(df0) == 0 && !isEven(f) {
893 t.Errorf("Rat(%v).Float64() = %g (%b); halfway should have rounded to %g (%b) instead", r, f, f, f0, f0)
894 return false
896 if df.Cmp(df1) == 0 && !isEven(f) {
897 t.Errorf("Rat(%v).Float64() = %g (%b); halfway should have rounded to %g (%b) instead", r, f, f, f1, f1)
898 return false
900 return true
903 func isEven(f float64) bool { return math.Float64bits(f)&1 == 0 }
905 func TestIsFinite(t *testing.T) {
906 finites := []float64{
907 1.0 / 3,
908 4891559871276714924261e+222,
909 math.MaxFloat64,
910 math.SmallestNonzeroFloat64,
911 -math.MaxFloat64,
912 -math.SmallestNonzeroFloat64,
914 for _, f := range finites {
915 if !isFinite(f) {
916 t.Errorf("!IsFinite(%g (%b))", f, f)
919 nonfinites := []float64{
920 math.NaN(),
921 math.Inf(-1),
922 math.Inf(+1),
924 for _, f := range nonfinites {
925 if isFinite(f) {
926 t.Errorf("IsFinite(%g, (%b))", f, f)