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