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. 4 5 package big 6 7 import ( 8 "bytes" 9 "encoding/gob" 10 "encoding/json" 11 "encoding/xml" 12 "math" 13 "testing" 14 ) 15 16 func TestZeroRat(t *testing.T) { 17 var x, y, z Rat 18 y.SetFrac64(0, 42) 19 20 if x.Cmp(&y) != 0 { 21 t.Errorf("x and y should be both equal and zero") 22 } 23 24 if s := x.String(); s != "0/1" { 25 t.Errorf("got x = %s, want 0/1", s) 26 } 27 28 if s := x.RatString(); s != "0" { 29 t.Errorf("got x = %s, want 0", s) 30 } 31 32 z.Add(&x, &y) 33 if s := z.RatString(); s != "0" { 34 t.Errorf("got x+y = %s, want 0", s) 35 } 36 37 z.Sub(&x, &y) 38 if s := z.RatString(); s != "0" { 39 t.Errorf("got x-y = %s, want 0", s) 40 } 41 42 z.Mul(&x, &y) 43 if s := z.RatString(); s != "0" { 44 t.Errorf("got x*y = %s, want 0", s) 45 } 46 47 // check for division by zero 48 defer func() { 49 if s := recover(); s == nil || s.(string) != "division by zero" { 50 panic(s) 51 } 52 }() 53 z.Quo(&x, &y) 54 } 55 56 func TestRatSign(t *testing.T) { 57 zero := NewRat(0, 1) 58 for _, a := range setStringTests { 59 x, ok := new(Rat).SetString(a.in) 60 if !ok { 61 continue 62 } 63 s := x.Sign() 64 e := x.Cmp(zero) 65 if s != e { 66 t.Errorf("got %d; want %d for z = %v", s, e, &x) 67 } 68 } 69 } 70 71 var ratCmpTests = []struct { 72 rat1, rat2 string 73 out int 74 }{ 75 {"0", "0/1", 0}, 76 {"1/1", "1", 0}, 77 {"-1", "-2/2", 0}, 78 {"1", "0", 1}, 79 {"0/1", "1/1", -1}, 80 {"-5/1434770811533343057144", "-5/1434770811533343057145", -1}, 81 {"49832350382626108453/8964749413", "49832350382626108454/8964749413", -1}, 82 {"-37414950961700930/7204075375675961", "37414950961700930/7204075375675961", -1}, 83 {"37414950961700930/7204075375675961", "74829901923401860/14408150751351922", 0}, 84 } 85 86 func TestRatCmp(t *testing.T) { 87 for i, test := range ratCmpTests { 88 x, _ := new(Rat).SetString(test.rat1) 89 y, _ := new(Rat).SetString(test.rat2) 90 91 out := x.Cmp(y) 92 if out != test.out { 93 t.Errorf("#%d got out = %v; want %v", i, out, test.out) 94 } 95 } 96 } 97 98 func TestIsInt(t *testing.T) { 99 one := NewInt(1) 100 for _, a := range setStringTests { 101 x, ok := new(Rat).SetString(a.in) 102 if !ok { 103 continue 104 } 105 i := x.IsInt() 106 e := x.Denom().Cmp(one) == 0 107 if i != e { 108 t.Errorf("got IsInt(%v) == %v; want %v", x, i, e) 109 } 110 } 111 } 112 113 func TestRatAbs(t *testing.T) { 114 zero := new(Rat) 115 for _, a := range setStringTests { 116 x, ok := new(Rat).SetString(a.in) 117 if !ok { 118 continue 119 } 120 e := new(Rat).Set(x) 121 if e.Cmp(zero) < 0 { 122 e.Sub(zero, e) 123 } 124 z := new(Rat).Abs(x) 125 if z.Cmp(e) != 0 { 126 t.Errorf("got Abs(%v) = %v; want %v", x, z, e) 127 } 128 } 129 } 130 131 func TestRatNeg(t *testing.T) { 132 zero := new(Rat) 133 for _, a := range setStringTests { 134 x, ok := new(Rat).SetString(a.in) 135 if !ok { 136 continue 137 } 138 e := new(Rat).Sub(zero, x) 139 z := new(Rat).Neg(x) 140 if z.Cmp(e) != 0 { 141 t.Errorf("got Neg(%v) = %v; want %v", x, z, e) 142 } 143 } 144 } 145 146 func TestRatInv(t *testing.T) { 147 zero := new(Rat) 148 for _, a := range setStringTests { 149 x, ok := new(Rat).SetString(a.in) 150 if !ok { 151 continue 152 } 153 if x.Cmp(zero) == 0 { 154 continue // avoid division by zero 155 } 156 e := new(Rat).SetFrac(x.Denom(), x.Num()) 157 z := new(Rat).Inv(x) 158 if z.Cmp(e) != 0 { 159 t.Errorf("got Inv(%v) = %v; want %v", x, z, e) 160 } 161 } 162 } 163 164 type ratBinFun func(z, x, y *Rat) *Rat 165 type ratBinArg struct { 166 x, y, z string 167 } 168 169 func testRatBin(t *testing.T, i int, name string, f ratBinFun, a ratBinArg) { 170 x, _ := new(Rat).SetString(a.x) 171 y, _ := new(Rat).SetString(a.y) 172 z, _ := new(Rat).SetString(a.z) 173 out := f(new(Rat), x, y) 174 175 if out.Cmp(z) != 0 { 176 t.Errorf("%s #%d got %s want %s", name, i, out, z) 177 } 178 } 179 180 var ratBinTests = []struct { 181 x, y string 182 sum, prod string 183 }{ 184 {"0", "0", "0", "0"}, 185 {"0", "1", "1", "0"}, 186 {"-1", "0", "-1", "0"}, 187 {"-1", "1", "0", "-1"}, 188 {"1", "1", "2", "1"}, 189 {"1/2", "1/2", "1", "1/4"}, 190 {"1/4", "1/3", "7/12", "1/12"}, 191 {"2/5", "-14/3", "-64/15", "-28/15"}, 192 {"4707/49292519774798173060", "-3367/70976135186689855734", "84058377121001851123459/1749296273614329067191168098769082663020", "-1760941/388732505247628681598037355282018369560"}, 193 {"-61204110018146728334/3", "-31052192278051565633/2", "-215564796870448153567/6", "950260896245257153059642991192710872711/3"}, 194 {"-854857841473707320655/4237645934602118692642972629634714039", "-18/31750379913563777419", "-27/133467566250814981", "15387441146526731771790/134546868362786310073779084329032722548987800600710485341"}, 195 {"618575745270541348005638912139/19198433543745179392300736", "-19948846211000086/637313996471", "27674141753240653/30123979153216", "-6169936206128396568797607742807090270137721977/6117715203873571641674006593837351328"}, 196 {"-3/26206484091896184128", "5/2848423294177090248", "15310893822118706237/9330894968229805033368778458685147968", "-5/24882386581946146755650075889827061248"}, 197 {"26946729/330400702820", "41563965/225583428284", "1238218672302860271/4658307703098666660055", "224002580204097/14906584649915733312176"}, 198 {"-8259900599013409474/7", "-84829337473700364773/56707961321161574960", "-468402123685491748914621885145127724451/396955729248131024720", "350340947706464153265156004876107029701/198477864624065512360"}, 199 {"575775209696864/1320203974639986246357", "29/712593081308", "410331716733912717985762465/940768218243776489278275419794956", "808/45524274987585732633"}, 200 {"1786597389946320496771/2066653520653241", "6269770/1992362624741777", "3559549865190272133656109052308126637/4117523232840525481453983149257", "8967230/3296219033"}, 201 {"-36459180403360509753/32150500941194292113930", "9381566963714/9633539", "301622077145533298008420642898530153/309723104686531919656937098270", "-3784609207827/3426986245"}, 202 } 203 204 func TestRatBin(t *testing.T) { 205 for i, test := range ratBinTests { 206 arg := ratBinArg{test.x, test.y, test.sum} 207 testRatBin(t, i, "Add", (*Rat).Add, arg) 208 209 arg = ratBinArg{test.y, test.x, test.sum} 210 testRatBin(t, i, "Add symmetric", (*Rat).Add, arg) 211 212 arg = ratBinArg{test.sum, test.x, test.y} 213 testRatBin(t, i, "Sub", (*Rat).Sub, arg) 214 215 arg = ratBinArg{test.sum, test.y, test.x} 216 testRatBin(t, i, "Sub symmetric", (*Rat).Sub, arg) 217 218 arg = ratBinArg{test.x, test.y, test.prod} 219 testRatBin(t, i, "Mul", (*Rat).Mul, arg) 220 221 arg = ratBinArg{test.y, test.x, test.prod} 222 testRatBin(t, i, "Mul symmetric", (*Rat).Mul, arg) 223 224 if test.x != "0" { 225 arg = ratBinArg{test.prod, test.x, test.y} 226 testRatBin(t, i, "Quo", (*Rat).Quo, arg) 227 } 228 229 if test.y != "0" { 230 arg = ratBinArg{test.prod, test.y, test.x} 231 testRatBin(t, i, "Quo symmetric", (*Rat).Quo, arg) 232 } 233 } 234 } 235 236 func TestIssue820(t *testing.T) { 237 x := NewRat(3, 1) 238 y := NewRat(2, 1) 239 z := y.Quo(x, y) 240 q := NewRat(3, 2) 241 if z.Cmp(q) != 0 { 242 t.Errorf("got %s want %s", z, q) 243 } 244 245 y = NewRat(3, 1) 246 x = NewRat(2, 1) 247 z = y.Quo(x, y) 248 q = NewRat(2, 3) 249 if z.Cmp(q) != 0 { 250 t.Errorf("got %s want %s", z, q) 251 } 252 253 x = NewRat(3, 1) 254 z = x.Quo(x, x) 255 q = NewRat(3, 3) 256 if z.Cmp(q) != 0 { 257 t.Errorf("got %s want %s", z, q) 258 } 259 } 260 261 var setFrac64Tests = []struct { 262 a, b int64 263 out string 264 }{ 265 {0, 1, "0"}, 266 {0, -1, "0"}, 267 {1, 1, "1"}, 268 {-1, 1, "-1"}, 269 {1, -1, "-1"}, 270 {-1, -1, "1"}, 271 {-9223372036854775808, -9223372036854775808, "1"}, 272 } 273 274 func TestRatSetFrac64Rat(t *testing.T) { 275 for i, test := range setFrac64Tests { 276 x := new(Rat).SetFrac64(test.a, test.b) 277 if x.RatString() != test.out { 278 t.Errorf("#%d got %s want %s", i, x.RatString(), test.out) 279 } 280 } 281 } 282 283 func TestRatGobEncoding(t *testing.T) { 284 var medium bytes.Buffer 285 enc := gob.NewEncoder(&medium) 286 dec := gob.NewDecoder(&medium) 287 for _, test := range encodingTests { 288 medium.Reset() // empty buffer for each test case (in case of failures) 289 var tx Rat 290 tx.SetString(test + ".14159265") 291 if err := enc.Encode(&tx); err != nil { 292 t.Errorf("encoding of %s failed: %s", &tx, err) 293 } 294 var rx Rat 295 if err := dec.Decode(&rx); err != nil { 296 t.Errorf("decoding of %s failed: %s", &tx, err) 297 } 298 if rx.Cmp(&tx) != 0 { 299 t.Errorf("transmission of %s failed: got %s want %s", &tx, &rx, &tx) 300 } 301 } 302 } 303 304 // Sending a nil Rat pointer (inside a slice) on a round trip through gob should yield a zero. 305 // TODO: top-level nils. 306 func TestGobEncodingNilRatInSlice(t *testing.T) { 307 buf := new(bytes.Buffer) 308 enc := gob.NewEncoder(buf) 309 dec := gob.NewDecoder(buf) 310 311 var in = make([]*Rat, 1) 312 err := enc.Encode(&in) 313 if err != nil { 314 t.Errorf("gob encode failed: %q", err) 315 } 316 var out []*Rat 317 err = dec.Decode(&out) 318 if err != nil { 319 t.Fatalf("gob decode failed: %q", err) 320 } 321 if len(out) != 1 { 322 t.Fatalf("wrong len; want 1 got %d", len(out)) 323 } 324 var zero Rat 325 if out[0].Cmp(&zero) != 0 { 326 t.Errorf("transmission of (*Int)(nill) failed: got %s want 0", out) 327 } 328 } 329 330 var ratNums = []string{ 331 "-141592653589793238462643383279502884197169399375105820974944592307816406286", 332 "-1415926535897932384626433832795028841971", 333 "-141592653589793", 334 "-1", 335 "0", 336 "1", 337 "141592653589793", 338 "1415926535897932384626433832795028841971", 339 "141592653589793238462643383279502884197169399375105820974944592307816406286", 340 } 341 342 var ratDenoms = []string{ 343 "1", 344 "718281828459045", 345 "7182818284590452353602874713526624977572", 346 "718281828459045235360287471352662497757247093699959574966967627724076630353", 347 } 348 349 func TestRatJSONEncoding(t *testing.T) { 350 for _, num := range ratNums { 351 for _, denom := range ratDenoms { 352 var tx Rat 353 tx.SetString(num + "/" + denom) 354 b, err := json.Marshal(&tx) 355 if err != nil { 356 t.Errorf("marshaling of %s failed: %s", &tx, err) 357 continue 358 } 359 var rx Rat 360 if err := json.Unmarshal(b, &rx); err != nil { 361 t.Errorf("unmarshaling of %s failed: %s", &tx, err) 362 continue 363 } 364 if rx.Cmp(&tx) != 0 { 365 t.Errorf("JSON encoding of %s failed: got %s want %s", &tx, &rx, &tx) 366 } 367 } 368 } 369 } 370 371 func TestRatXMLEncoding(t *testing.T) { 372 for _, num := range ratNums { 373 for _, denom := range ratDenoms { 374 var tx Rat 375 tx.SetString(num + "/" + denom) 376 b, err := xml.Marshal(&tx) 377 if err != nil { 378 t.Errorf("marshaling of %s failed: %s", &tx, err) 379 continue 380 } 381 var rx Rat 382 if err := xml.Unmarshal(b, &rx); err != nil { 383 t.Errorf("unmarshaling of %s failed: %s", &tx, err) 384 continue 385 } 386 if rx.Cmp(&tx) != 0 { 387 t.Errorf("XML encoding of %s failed: got %s want %s", &tx, &rx, &tx) 388 } 389 } 390 } 391 } 392 393 func TestIssue2379(t *testing.T) { 394 // 1) no aliasing 395 q := NewRat(3, 2) 396 x := new(Rat) 397 x.SetFrac(NewInt(3), NewInt(2)) 398 if x.Cmp(q) != 0 { 399 t.Errorf("1) got %s want %s", x, q) 400 } 401 402 // 2) aliasing of numerator 403 x = NewRat(2, 3) 404 x.SetFrac(NewInt(3), x.Num()) 405 if x.Cmp(q) != 0 { 406 t.Errorf("2) got %s want %s", x, q) 407 } 408 409 // 3) aliasing of denominator 410 x = NewRat(2, 3) 411 x.SetFrac(x.Denom(), NewInt(2)) 412 if x.Cmp(q) != 0 { 413 t.Errorf("3) got %s want %s", x, q) 414 } 415 416 // 4) aliasing of numerator and denominator 417 x = NewRat(2, 3) 418 x.SetFrac(x.Denom(), x.Num()) 419 if x.Cmp(q) != 0 { 420 t.Errorf("4) got %s want %s", x, q) 421 } 422 423 // 5) numerator and denominator are the same 424 q = NewRat(1, 1) 425 x = new(Rat) 426 n := NewInt(7) 427 x.SetFrac(n, n) 428 if x.Cmp(q) != 0 { 429 t.Errorf("5) got %s want %s", x, q) 430 } 431 } 432 433 func TestIssue3521(t *testing.T) { 434 a := new(Int) 435 b := new(Int) 436 a.SetString("64375784358435883458348587", 0) 437 b.SetString("4789759874531", 0) 438 439 // 0) a raw zero value has 1 as denominator 440 zero := new(Rat) 441 one := NewInt(1) 442 if zero.Denom().Cmp(one) != 0 { 443 t.Errorf("0) got %s want %s", zero.Denom(), one) 444 } 445 446 // 1a) a zero value remains zero independent of denominator 447 x := new(Rat) 448 x.Denom().Set(new(Int).Neg(b)) 449 if x.Cmp(zero) != 0 { 450 t.Errorf("1a) got %s want %s", x, zero) 451 } 452 453 // 1b) a zero value may have a denominator != 0 and != 1 454 x.Num().Set(a) 455 qab := new(Rat).SetFrac(a, b) 456 if x.Cmp(qab) != 0 { 457 t.Errorf("1b) got %s want %s", x, qab) 458 } 459 460 // 2a) an integral value becomes a fraction depending on denominator 461 x.SetFrac64(10, 2) 462 x.Denom().SetInt64(3) 463 q53 := NewRat(5, 3) 464 if x.Cmp(q53) != 0 { 465 t.Errorf("2a) got %s want %s", x, q53) 466 } 467 468 // 2b) an integral value becomes a fraction depending on denominator 469 x = NewRat(10, 2) 470 x.Denom().SetInt64(3) 471 if x.Cmp(q53) != 0 { 472 t.Errorf("2b) got %s want %s", x, q53) 473 } 474 475 // 3) changing the numerator/denominator of a Rat changes the Rat 476 x.SetFrac(a, b) 477 a = x.Num() 478 b = x.Denom() 479 a.SetInt64(5) 480 b.SetInt64(3) 481 if x.Cmp(q53) != 0 { 482 t.Errorf("3) got %s want %s", x, q53) 483 } 484 } 485 486 func TestFloat32Distribution(t *testing.T) { 487 // Generate a distribution of (sign, mantissa, exp) values 488 // broader than the float32 range, and check Rat.Float32() 489 // always picks the closest float32 approximation. 490 var add = []int64{ 491 0, 492 1, 493 3, 494 5, 495 7, 496 9, 497 11, 498 } 499 var winc, einc = uint64(1), 1 // soak test (~1.5s on x86-64) 500 if testing.Short() { 501 winc, einc = 5, 15 // quick test (~60ms on x86-64) 502 } 503 504 for _, sign := range "+-" { 505 for _, a := range add { 506 for wid := uint64(0); wid < 30; wid += winc { 507 b := 1<<wid + a 508 if sign == '-' { 509 b = -b 510 } 511 for exp := -150; exp < 150; exp += einc { 512 num, den := NewInt(b), NewInt(1) 513 if exp > 0 { 514 num.Lsh(num, uint(exp)) 515 } else { 516 den.Lsh(den, uint(-exp)) 517 } 518 r := new(Rat).SetFrac(num, den) 519 f, _ := r.Float32() 520 521 if !checkIsBestApprox32(t, f, r) { 522 // Append context information. 523 t.Errorf("(input was mantissa %#x, exp %d; f = %g (%b); f ~ %g; r = %v)", 524 b, exp, f, f, math.Ldexp(float64(b), exp), r) 525 } 526 527 checkNonLossyRoundtrip32(t, f) 528 } 529 } 530 } 531 } 532 } 533 534 func TestFloat64Distribution(t *testing.T) { 535 // Generate a distribution of (sign, mantissa, exp) values 536 // broader than the float64 range, and check Rat.Float64() 537 // always picks the closest float64 approximation. 538 var add = []int64{ 539 0, 540 1, 541 3, 542 5, 543 7, 544 9, 545 11, 546 } 547 var winc, einc = uint64(1), 1 // soak test (~75s on x86-64) 548 if testing.Short() { 549 winc, einc = 10, 500 // quick test (~12ms on x86-64) 550 } 551 552 for _, sign := range "+-" { 553 for _, a := range add { 554 for wid := uint64(0); wid < 60; wid += winc { 555 b := 1<<wid + a 556 if sign == '-' { 557 b = -b 558 } 559 for exp := -1100; exp < 1100; exp += einc { 560 num, den := NewInt(b), NewInt(1) 561 if exp > 0 { 562 num.Lsh(num, uint(exp)) 563 } else { 564 den.Lsh(den, uint(-exp)) 565 } 566 r := new(Rat).SetFrac(num, den) 567 f, _ := r.Float64() 568 569 if !checkIsBestApprox64(t, f, r) { 570 // Append context information. 571 t.Errorf("(input was mantissa %#x, exp %d; f = %g (%b); f ~ %g; r = %v)", 572 b, exp, f, f, math.Ldexp(float64(b), exp), r) 573 } 574 575 checkNonLossyRoundtrip64(t, f) 576 } 577 } 578 } 579 } 580 } 581 582 // TestSetFloat64NonFinite checks that SetFloat64 of a non-finite value 583 // returns nil. 584 func TestSetFloat64NonFinite(t *testing.T) { 585 for _, f := range []float64{math.NaN(), math.Inf(+1), math.Inf(-1)} { 586 var r Rat 587 if r2 := r.SetFloat64(f); r2 != nil { 588 t.Errorf("SetFloat64(%g) was %v, want nil", f, r2) 589 } 590 } 591 } 592 593 // checkNonLossyRoundtrip32 checks that a float->Rat->float roundtrip is 594 // non-lossy for finite f. 595 func checkNonLossyRoundtrip32(t *testing.T, f float32) { 596 if !isFinite(float64(f)) { 597 return 598 } 599 r := new(Rat).SetFloat64(float64(f)) 600 if r == nil { 601 t.Errorf("Rat.SetFloat64(float64(%g) (%b)) == nil", f, f) 602 return 603 } 604 f2, exact := r.Float32() 605 if f != f2 || !exact { 606 t.Errorf("Rat.SetFloat64(float64(%g)).Float32() = %g (%b), %v, want %g (%b), %v; delta = %b", 607 f, f2, f2, exact, f, f, true, f2-f) 608 } 609 } 610 611 // checkNonLossyRoundtrip64 checks that a float->Rat->float roundtrip is 612 // non-lossy for finite f. 613 func checkNonLossyRoundtrip64(t *testing.T, f float64) { 614 if !isFinite(f) { 615 return 616 } 617 r := new(Rat).SetFloat64(f) 618 if r == nil { 619 t.Errorf("Rat.SetFloat64(%g (%b)) == nil", f, f) 620 return 621 } 622 f2, exact := r.Float64() 623 if f != f2 || !exact { 624 t.Errorf("Rat.SetFloat64(%g).Float64() = %g (%b), %v, want %g (%b), %v; delta = %b", 625 f, f2, f2, exact, f, f, true, f2-f) 626 } 627 } 628 629 // delta returns the absolute difference between r and f. 630 func delta(r *Rat, f float64) *Rat { 631 d := new(Rat).Sub(r, new(Rat).SetFloat64(f)) 632 return d.Abs(d) 633 } 634 635 // checkIsBestApprox32 checks that f is the best possible float32 636 // approximation of r. 637 // Returns true on success. 638 func checkIsBestApprox32(t *testing.T, f float32, r *Rat) bool { 639 if math.Abs(float64(f)) >= math.MaxFloat32 { 640 // Cannot check +Inf, -Inf, nor the float next to them (MaxFloat32). 641 // But we have tests for these special cases. 642 return true 643 } 644 645 // r must be strictly between f0 and f1, the floats bracketing f. 646 f0 := math.Nextafter32(f, float32(math.Inf(-1))) 647 f1 := math.Nextafter32(f, float32(math.Inf(+1))) 648 649 // For f to be correct, r must be closer to f than to f0 or f1. 650 df := delta(r, float64(f)) 651 df0 := delta(r, float64(f0)) 652 df1 := delta(r, float64(f1)) 653 if df.Cmp(df0) > 0 { 654 t.Errorf("Rat(%v).Float32() = %g (%b), but previous float32 %g (%b) is closer", r, f, f, f0, f0) 655 return false 656 } 657 if df.Cmp(df1) > 0 { 658 t.Errorf("Rat(%v).Float32() = %g (%b), but next float32 %g (%b) is closer", r, f, f, f1, f1) 659 return false 660 } 661 if df.Cmp(df0) == 0 && !isEven32(f) { 662 t.Errorf("Rat(%v).Float32() = %g (%b); halfway should have rounded to %g (%b) instead", r, f, f, f0, f0) 663 return false 664 } 665 if df.Cmp(df1) == 0 && !isEven32(f) { 666 t.Errorf("Rat(%v).Float32() = %g (%b); halfway should have rounded to %g (%b) instead", r, f, f, f1, f1) 667 return false 668 } 669 return true 670 } 671 672 // checkIsBestApprox64 checks that f is the best possible float64 673 // approximation of r. 674 // Returns true on success. 675 func checkIsBestApprox64(t *testing.T, f float64, r *Rat) bool { 676 if math.Abs(f) >= math.MaxFloat64 { 677 // Cannot check +Inf, -Inf, nor the float next to them (MaxFloat64). 678 // But we have tests for these special cases. 679 return true 680 } 681 682 // r must be strictly between f0 and f1, the floats bracketing f. 683 f0 := math.Nextafter(f, math.Inf(-1)) 684 f1 := math.Nextafter(f, math.Inf(+1)) 685 686 // For f to be correct, r must be closer to f than to f0 or f1. 687 df := delta(r, f) 688 df0 := delta(r, f0) 689 df1 := delta(r, f1) 690 if df.Cmp(df0) > 0 { 691 t.Errorf("Rat(%v).Float64() = %g (%b), but previous float64 %g (%b) is closer", r, f, f, f0, f0) 692 return false 693 } 694 if df.Cmp(df1) > 0 { 695 t.Errorf("Rat(%v).Float64() = %g (%b), but next float64 %g (%b) is closer", r, f, f, f1, f1) 696 return false 697 } 698 if df.Cmp(df0) == 0 && !isEven64(f) { 699 t.Errorf("Rat(%v).Float64() = %g (%b); halfway should have rounded to %g (%b) instead", r, f, f, f0, f0) 700 return false 701 } 702 if df.Cmp(df1) == 0 && !isEven64(f) { 703 t.Errorf("Rat(%v).Float64() = %g (%b); halfway should have rounded to %g (%b) instead", r, f, f, f1, f1) 704 return false 705 } 706 return true 707 } 708 709 func isEven32(f float32) bool { return math.Float32bits(f)&1 == 0 } 710 func isEven64(f float64) bool { return math.Float64bits(f)&1 == 0 } 711 712 func TestIsFinite(t *testing.T) { 713 finites := []float64{ 714 1.0 / 3, 715 4891559871276714924261e+222, 716 math.MaxFloat64, 717 math.SmallestNonzeroFloat64, 718 -math.MaxFloat64, 719 -math.SmallestNonzeroFloat64, 720 } 721 for _, f := range finites { 722 if !isFinite(f) { 723 t.Errorf("!IsFinite(%g (%b))", f, f) 724 } 725 } 726 nonfinites := []float64{ 727 math.NaN(), 728 math.Inf(-1), 729 math.Inf(+1), 730 } 731 for _, f := range nonfinites { 732 if isFinite(f) { 733 t.Errorf("IsFinite(%g, (%b))", f, f) 734 } 735 } 736 } 737