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