github.com/rsc/go@v0.0.0-20150416155037-e040fd465409/src/math/big/float_test.go (about) 1 // Copyright 2014 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 "fmt" 9 "math" 10 "strconv" 11 "strings" 12 "testing" 13 ) 14 15 // Verify that ErrNaN implements the error interface. 16 var _ error = ErrNaN{} 17 18 func (x *Float) uint64() uint64 { 19 u, acc := x.Uint64() 20 if acc != Exact { 21 panic(fmt.Sprintf("%s is not a uint64", x.Format('g', 10))) 22 } 23 return u 24 } 25 26 func (x *Float) int64() int64 { 27 i, acc := x.Int64() 28 if acc != Exact { 29 panic(fmt.Sprintf("%s is not an int64", x.Format('g', 10))) 30 } 31 return i 32 } 33 34 func TestFloatZeroValue(t *testing.T) { 35 // zero (uninitialized) value is a ready-to-use 0.0 36 var x Float 37 if s := x.Format('f', 1); s != "0.0" { 38 t.Errorf("zero value = %s; want 0.0", s) 39 } 40 41 // zero value has precision 0 42 if prec := x.Prec(); prec != 0 { 43 t.Errorf("prec = %d; want 0", prec) 44 } 45 46 // zero value can be used in any and all positions of binary operations 47 make := func(x int) *Float { 48 var f Float 49 if x != 0 { 50 f.SetInt64(int64(x)) 51 } 52 // x == 0 translates into the zero value 53 return &f 54 } 55 for _, test := range []struct { 56 z, x, y, want int 57 opname rune 58 op func(z, x, y *Float) *Float 59 }{ 60 {0, 0, 0, 0, '+', (*Float).Add}, 61 {0, 1, 2, 3, '+', (*Float).Add}, 62 {1, 2, 0, 2, '+', (*Float).Add}, 63 {2, 0, 1, 1, '+', (*Float).Add}, 64 65 {0, 0, 0, 0, '-', (*Float).Sub}, 66 {0, 1, 2, -1, '-', (*Float).Sub}, 67 {1, 2, 0, 2, '-', (*Float).Sub}, 68 {2, 0, 1, -1, '-', (*Float).Sub}, 69 70 {0, 0, 0, 0, '*', (*Float).Mul}, 71 {0, 1, 2, 2, '*', (*Float).Mul}, 72 {1, 2, 0, 0, '*', (*Float).Mul}, 73 {2, 0, 1, 0, '*', (*Float).Mul}, 74 75 // {0, 0, 0, 0, '/', (*Float).Quo}, // panics 76 {0, 2, 1, 2, '/', (*Float).Quo}, 77 {1, 2, 0, 0, '/', (*Float).Quo}, // = +Inf 78 {2, 0, 1, 0, '/', (*Float).Quo}, 79 } { 80 z := make(test.z) 81 test.op(z, make(test.x), make(test.y)) 82 got := 0 83 if !z.IsInf() { 84 got = int(z.int64()) 85 } 86 if got != test.want { 87 t.Errorf("%d %c %d = %d; want %d", test.x, test.opname, test.y, got, test.want) 88 } 89 } 90 91 // TODO(gri) test how precision is set for zero value results 92 } 93 94 func makeFloat(s string) *Float { 95 var x Float 96 97 switch s { 98 case "0": 99 return &x 100 case "-0": 101 return x.Neg(&x) 102 case "Inf", "+Inf": 103 return x.SetInf(false) 104 case "-Inf": 105 return x.SetInf(true) 106 } 107 108 x.SetPrec(1000) 109 if _, ok := x.SetString(s); !ok { 110 panic(fmt.Sprintf("%q is not a valid float", s)) 111 } 112 return &x 113 } 114 115 func TestFloatSetPrec(t *testing.T) { 116 for _, test := range []struct { 117 x string 118 prec uint 119 want string 120 acc Accuracy 121 }{ 122 // prec 0 123 {"0", 0, "0", Exact}, 124 {"-0", 0, "-0", Exact}, 125 {"-Inf", 0, "-Inf", Exact}, 126 {"+Inf", 0, "+Inf", Exact}, 127 {"123", 0, "0", Below}, 128 {"-123", 0, "-0", Above}, 129 130 // prec at upper limit 131 {"0", MaxPrec, "0", Exact}, 132 {"-0", MaxPrec, "-0", Exact}, 133 {"-Inf", MaxPrec, "-Inf", Exact}, 134 {"+Inf", MaxPrec, "+Inf", Exact}, 135 136 // just a few regular cases - general rounding is tested elsewhere 137 {"1.5", 1, "2", Above}, 138 {"-1.5", 1, "-2", Below}, 139 {"123", 1e6, "123", Exact}, 140 {"-123", 1e6, "-123", Exact}, 141 } { 142 x := makeFloat(test.x).SetPrec(test.prec) 143 prec := test.prec 144 if prec > MaxPrec { 145 prec = MaxPrec 146 } 147 if got := x.Prec(); got != prec { 148 t.Errorf("%s.SetPrec(%d).Prec() == %d; want %d", test.x, test.prec, got, prec) 149 } 150 if got, acc := x.String(), x.Acc(); got != test.want || acc != test.acc { 151 t.Errorf("%s.SetPrec(%d) = %s (%s); want %s (%s)", test.x, test.prec, got, acc, test.want, test.acc) 152 } 153 } 154 } 155 156 func TestFloatMinPrec(t *testing.T) { 157 const max = 100 158 for _, test := range []struct { 159 x string 160 want uint 161 }{ 162 {"0", 0}, 163 {"-0", 0}, 164 {"+Inf", 0}, 165 {"-Inf", 0}, 166 {"1", 1}, 167 {"2", 1}, 168 {"3", 2}, 169 {"0x8001", 16}, 170 {"0x8001p-1000", 16}, 171 {"0x8001p+1000", 16}, 172 {"0.1", max}, 173 } { 174 x := makeFloat(test.x).SetPrec(max) 175 if got := x.MinPrec(); got != test.want { 176 t.Errorf("%s.MinPrec() = %d; want %d", test.x, got, test.want) 177 } 178 } 179 } 180 181 func TestFloatSign(t *testing.T) { 182 for _, test := range []struct { 183 x string 184 s int 185 }{ 186 {"-Inf", -1}, 187 {"-1", -1}, 188 {"-0", 0}, 189 {"+0", 0}, 190 {"+1", +1}, 191 {"+Inf", +1}, 192 } { 193 x := makeFloat(test.x) 194 s := x.Sign() 195 if s != test.s { 196 t.Errorf("%s.Sign() = %d; want %d", test.x, s, test.s) 197 } 198 } 199 } 200 201 // alike(x, y) is like x.Cmp(y) == 0 but also considers the sign of 0 (0 != -0). 202 func alike(x, y *Float) bool { 203 return x.Cmp(y) == 0 && x.Signbit() == y.Signbit() 204 } 205 206 func TestFloatMantExp(t *testing.T) { 207 for _, test := range []struct { 208 x string 209 mant string 210 exp int 211 }{ 212 {"0", "0", 0}, 213 {"+0", "0", 0}, 214 {"-0", "-0", 0}, 215 {"Inf", "+Inf", 0}, 216 {"+Inf", "+Inf", 0}, 217 {"-Inf", "-Inf", 0}, 218 {"1.5", "0.75", 1}, 219 {"1.024e3", "0.5", 11}, 220 {"-0.125", "-0.5", -2}, 221 } { 222 x := makeFloat(test.x) 223 mant := makeFloat(test.mant) 224 m := new(Float) 225 e := x.MantExp(m) 226 if !alike(m, mant) || e != test.exp { 227 t.Errorf("%s.MantExp() = %s, %d; want %s, %d", test.x, m.Format('g', 10), e, test.mant, test.exp) 228 } 229 } 230 } 231 232 func TestFloatMantExpAliasing(t *testing.T) { 233 x := makeFloat("0.5p10") 234 if e := x.MantExp(x); e != 10 { 235 t.Fatalf("Float.MantExp aliasing error: got %d; want 10", e) 236 } 237 if want := makeFloat("0.5"); !alike(x, want) { 238 t.Fatalf("Float.MantExp aliasing error: got %s; want %s", x.Format('g', 10), want.Format('g', 10)) 239 } 240 } 241 242 func TestFloatSetMantExp(t *testing.T) { 243 for _, test := range []struct { 244 frac string 245 exp int 246 z string 247 }{ 248 {"0", 0, "0"}, 249 {"+0", 0, "0"}, 250 {"-0", 0, "-0"}, 251 {"Inf", 1234, "+Inf"}, 252 {"+Inf", -1234, "+Inf"}, 253 {"-Inf", -1234, "-Inf"}, 254 {"0", MinExp, "0"}, 255 {"0.25", MinExp, "+0"}, // exponent underflow 256 {"-0.25", MinExp, "-0"}, // exponent underflow 257 {"1", MaxExp, "+Inf"}, // exponent overflow 258 {"2", MaxExp - 1, "+Inf"}, // exponent overflow 259 {"0.75", 1, "1.5"}, 260 {"0.5", 11, "1024"}, 261 {"-0.5", -2, "-0.125"}, 262 {"32", 5, "1024"}, 263 {"1024", -10, "1"}, 264 } { 265 frac := makeFloat(test.frac) 266 want := makeFloat(test.z) 267 var z Float 268 z.SetMantExp(frac, test.exp) 269 if !alike(&z, want) { 270 t.Errorf("SetMantExp(%s, %d) = %s; want %s", test.frac, test.exp, z.Format('g', 10), test.z) 271 } 272 // test inverse property 273 mant := new(Float) 274 if z.SetMantExp(mant, want.MantExp(mant)).Cmp(want) != 0 { 275 t.Errorf("Inverse property not satisfied: got %s; want %s", z.Format('g', 10), test.z) 276 } 277 } 278 } 279 280 func TestFloatPredicates(t *testing.T) { 281 for _, test := range []struct { 282 x string 283 sign int 284 signbit, inf bool 285 }{ 286 {x: "-Inf", sign: -1, signbit: true, inf: true}, 287 {x: "-1", sign: -1, signbit: true}, 288 {x: "-0", signbit: true}, 289 {x: "0"}, 290 {x: "1", sign: 1}, 291 {x: "+Inf", sign: 1, inf: true}, 292 } { 293 x := makeFloat(test.x) 294 if got := x.Signbit(); got != test.signbit { 295 t.Errorf("(%s).Signbit() = %v; want %v", test.x, got, test.signbit) 296 } 297 if got := x.Sign(); got != test.sign { 298 t.Errorf("(%s).Sign() = %d; want %d", test.x, got, test.sign) 299 } 300 if got := x.IsInf(); got != test.inf { 301 t.Errorf("(%s).IsInf() = %v; want %v", test.x, got, test.inf) 302 } 303 } 304 } 305 306 func TestFloatIsInt(t *testing.T) { 307 for _, test := range []string{ 308 "0 int", 309 "-0 int", 310 "1 int", 311 "-1 int", 312 "0.5", 313 "1.23", 314 "1.23e1", 315 "1.23e2 int", 316 "0.000000001e+8", 317 "0.000000001e+9 int", 318 "1.2345e200 int", 319 "Inf", 320 "+Inf", 321 "-Inf", 322 } { 323 s := strings.TrimSuffix(test, " int") 324 want := s != test 325 if got := makeFloat(s).IsInt(); got != want { 326 t.Errorf("%s.IsInt() == %t", s, got) 327 } 328 } 329 } 330 331 func fromBinary(s string) int64 { 332 x, err := strconv.ParseInt(s, 2, 64) 333 if err != nil { 334 panic(err) 335 } 336 return x 337 } 338 339 func toBinary(x int64) string { 340 return strconv.FormatInt(x, 2) 341 } 342 343 func testFloatRound(t *testing.T, x, r int64, prec uint, mode RoundingMode) { 344 // verify test data 345 var ok bool 346 switch mode { 347 case ToNearestEven, ToNearestAway: 348 ok = true // nothing to do for now 349 case ToZero: 350 if x < 0 { 351 ok = r >= x 352 } else { 353 ok = r <= x 354 } 355 case AwayFromZero: 356 if x < 0 { 357 ok = r <= x 358 } else { 359 ok = r >= x 360 } 361 case ToNegativeInf: 362 ok = r <= x 363 case ToPositiveInf: 364 ok = r >= x 365 default: 366 panic("unreachable") 367 } 368 if !ok { 369 t.Fatalf("incorrect test data for prec = %d, %s: x = %s, r = %s", prec, mode, toBinary(x), toBinary(r)) 370 } 371 372 // compute expected accuracy 373 a := Exact 374 switch { 375 case r < x: 376 a = Below 377 case r > x: 378 a = Above 379 } 380 381 // round 382 f := new(Float).SetMode(mode).SetInt64(x).SetPrec(prec) 383 384 // check result 385 r1 := f.int64() 386 p1 := f.Prec() 387 a1 := f.Acc() 388 if r1 != r || p1 != prec || a1 != a { 389 t.Errorf("round %s (%d bits, %s) incorrect: got %s (%d bits, %s); want %s (%d bits, %s)", 390 toBinary(x), prec, mode, 391 toBinary(r1), p1, a1, 392 toBinary(r), prec, a) 393 return 394 } 395 396 // g and f should be the same 397 // (rounding by SetPrec after SetInt64 using default precision 398 // should be the same as rounding by SetInt64 after setting the 399 // precision) 400 g := new(Float).SetMode(mode).SetPrec(prec).SetInt64(x) 401 if !alike(g, f) { 402 t.Errorf("round %s (%d bits, %s) not symmetric: got %s and %s; want %s", 403 toBinary(x), prec, mode, 404 toBinary(g.int64()), 405 toBinary(r1), 406 toBinary(r), 407 ) 408 return 409 } 410 411 // h and f should be the same 412 // (repeated rounding should be idempotent) 413 h := new(Float).SetMode(mode).SetPrec(prec).Set(f) 414 if !alike(h, f) { 415 t.Errorf("round %s (%d bits, %s) not idempotent: got %s and %s; want %s", 416 toBinary(x), prec, mode, 417 toBinary(h.int64()), 418 toBinary(r1), 419 toBinary(r), 420 ) 421 return 422 } 423 } 424 425 // TestFloatRound tests basic rounding. 426 func TestFloatRound(t *testing.T) { 427 for _, test := range []struct { 428 prec uint 429 x, zero, neven, naway, away string // input, results rounded to prec bits 430 }{ 431 {5, "1000", "1000", "1000", "1000", "1000"}, 432 {5, "1001", "1001", "1001", "1001", "1001"}, 433 {5, "1010", "1010", "1010", "1010", "1010"}, 434 {5, "1011", "1011", "1011", "1011", "1011"}, 435 {5, "1100", "1100", "1100", "1100", "1100"}, 436 {5, "1101", "1101", "1101", "1101", "1101"}, 437 {5, "1110", "1110", "1110", "1110", "1110"}, 438 {5, "1111", "1111", "1111", "1111", "1111"}, 439 440 {4, "1000", "1000", "1000", "1000", "1000"}, 441 {4, "1001", "1001", "1001", "1001", "1001"}, 442 {4, "1010", "1010", "1010", "1010", "1010"}, 443 {4, "1011", "1011", "1011", "1011", "1011"}, 444 {4, "1100", "1100", "1100", "1100", "1100"}, 445 {4, "1101", "1101", "1101", "1101", "1101"}, 446 {4, "1110", "1110", "1110", "1110", "1110"}, 447 {4, "1111", "1111", "1111", "1111", "1111"}, 448 449 {3, "1000", "1000", "1000", "1000", "1000"}, 450 {3, "1001", "1000", "1000", "1010", "1010"}, 451 {3, "1010", "1010", "1010", "1010", "1010"}, 452 {3, "1011", "1010", "1100", "1100", "1100"}, 453 {3, "1100", "1100", "1100", "1100", "1100"}, 454 {3, "1101", "1100", "1100", "1110", "1110"}, 455 {3, "1110", "1110", "1110", "1110", "1110"}, 456 {3, "1111", "1110", "10000", "10000", "10000"}, 457 458 {3, "1000001", "1000000", "1000000", "1000000", "1010000"}, 459 {3, "1001001", "1000000", "1010000", "1010000", "1010000"}, 460 {3, "1010001", "1010000", "1010000", "1010000", "1100000"}, 461 {3, "1011001", "1010000", "1100000", "1100000", "1100000"}, 462 {3, "1100001", "1100000", "1100000", "1100000", "1110000"}, 463 {3, "1101001", "1100000", "1110000", "1110000", "1110000"}, 464 {3, "1110001", "1110000", "1110000", "1110000", "10000000"}, 465 {3, "1111001", "1110000", "10000000", "10000000", "10000000"}, 466 467 {2, "1000", "1000", "1000", "1000", "1000"}, 468 {2, "1001", "1000", "1000", "1000", "1100"}, 469 {2, "1010", "1000", "1000", "1100", "1100"}, 470 {2, "1011", "1000", "1100", "1100", "1100"}, 471 {2, "1100", "1100", "1100", "1100", "1100"}, 472 {2, "1101", "1100", "1100", "1100", "10000"}, 473 {2, "1110", "1100", "10000", "10000", "10000"}, 474 {2, "1111", "1100", "10000", "10000", "10000"}, 475 476 {2, "1000001", "1000000", "1000000", "1000000", "1100000"}, 477 {2, "1001001", "1000000", "1000000", "1000000", "1100000"}, 478 {2, "1010001", "1000000", "1100000", "1100000", "1100000"}, 479 {2, "1011001", "1000000", "1100000", "1100000", "1100000"}, 480 {2, "1100001", "1100000", "1100000", "1100000", "10000000"}, 481 {2, "1101001", "1100000", "1100000", "1100000", "10000000"}, 482 {2, "1110001", "1100000", "10000000", "10000000", "10000000"}, 483 {2, "1111001", "1100000", "10000000", "10000000", "10000000"}, 484 485 {1, "1000", "1000", "1000", "1000", "1000"}, 486 {1, "1001", "1000", "1000", "1000", "10000"}, 487 {1, "1010", "1000", "1000", "1000", "10000"}, 488 {1, "1011", "1000", "1000", "1000", "10000"}, 489 {1, "1100", "1000", "10000", "10000", "10000"}, 490 {1, "1101", "1000", "10000", "10000", "10000"}, 491 {1, "1110", "1000", "10000", "10000", "10000"}, 492 {1, "1111", "1000", "10000", "10000", "10000"}, 493 494 {1, "1000001", "1000000", "1000000", "1000000", "10000000"}, 495 {1, "1001001", "1000000", "1000000", "1000000", "10000000"}, 496 {1, "1010001", "1000000", "1000000", "1000000", "10000000"}, 497 {1, "1011001", "1000000", "1000000", "1000000", "10000000"}, 498 {1, "1100001", "1000000", "10000000", "10000000", "10000000"}, 499 {1, "1101001", "1000000", "10000000", "10000000", "10000000"}, 500 {1, "1110001", "1000000", "10000000", "10000000", "10000000"}, 501 {1, "1111001", "1000000", "10000000", "10000000", "10000000"}, 502 } { 503 x := fromBinary(test.x) 504 z := fromBinary(test.zero) 505 e := fromBinary(test.neven) 506 n := fromBinary(test.naway) 507 a := fromBinary(test.away) 508 prec := test.prec 509 510 testFloatRound(t, x, z, prec, ToZero) 511 testFloatRound(t, x, e, prec, ToNearestEven) 512 testFloatRound(t, x, n, prec, ToNearestAway) 513 testFloatRound(t, x, a, prec, AwayFromZero) 514 515 testFloatRound(t, x, z, prec, ToNegativeInf) 516 testFloatRound(t, x, a, prec, ToPositiveInf) 517 518 testFloatRound(t, -x, -a, prec, ToNegativeInf) 519 testFloatRound(t, -x, -z, prec, ToPositiveInf) 520 } 521 } 522 523 // TestFloatRound24 tests that rounding a float64 to 24 bits 524 // matches IEEE-754 rounding to nearest when converting a 525 // float64 to a float32 (excluding denormal numbers). 526 func TestFloatRound24(t *testing.T) { 527 const x0 = 1<<26 - 0x10 // 11...110000 (26 bits) 528 for d := 0; d <= 0x10; d++ { 529 x := float64(x0 + d) 530 f := new(Float).SetPrec(24).SetFloat64(x) 531 got, _ := f.Float32() 532 want := float32(x) 533 if got != want { 534 t.Errorf("Round(%g, 24) = %g; want %g", x, got, want) 535 } 536 } 537 } 538 539 func TestFloatSetUint64(t *testing.T) { 540 for _, want := range []uint64{ 541 0, 542 1, 543 2, 544 10, 545 100, 546 1<<32 - 1, 547 1 << 32, 548 1<<64 - 1, 549 } { 550 var f Float 551 f.SetUint64(want) 552 if got := f.uint64(); got != want { 553 t.Errorf("got %#x (%s); want %#x", got, f.Format('p', 0), want) 554 } 555 } 556 557 // test basic rounding behavior (exhaustive rounding testing is done elsewhere) 558 const x uint64 = 0x8765432187654321 // 64 bits needed 559 for prec := uint(1); prec <= 64; prec++ { 560 f := new(Float).SetPrec(prec).SetMode(ToZero).SetUint64(x) 561 got := f.uint64() 562 want := x &^ (1<<(64-prec) - 1) // cut off (round to zero) low 64-prec bits 563 if got != want { 564 t.Errorf("got %#x (%s); want %#x", got, f.Format('p', 0), want) 565 } 566 } 567 } 568 569 func TestFloatSetInt64(t *testing.T) { 570 for _, want := range []int64{ 571 0, 572 1, 573 2, 574 10, 575 100, 576 1<<32 - 1, 577 1 << 32, 578 1<<63 - 1, 579 } { 580 for i := range [2]int{} { 581 if i&1 != 0 { 582 want = -want 583 } 584 var f Float 585 f.SetInt64(want) 586 if got := f.int64(); got != want { 587 t.Errorf("got %#x (%s); want %#x", got, f.Format('p', 0), want) 588 } 589 } 590 } 591 592 // test basic rounding behavior (exhaustive rounding testing is done elsewhere) 593 const x int64 = 0x7654321076543210 // 63 bits needed 594 for prec := uint(1); prec <= 63; prec++ { 595 f := new(Float).SetPrec(prec).SetMode(ToZero).SetInt64(x) 596 got := f.int64() 597 want := x &^ (1<<(63-prec) - 1) // cut off (round to zero) low 63-prec bits 598 if got != want { 599 t.Errorf("got %#x (%s); want %#x", got, f.Format('p', 0), want) 600 } 601 } 602 } 603 604 func TestFloatSetFloat64(t *testing.T) { 605 for _, want := range []float64{ 606 0, 607 1, 608 2, 609 12345, 610 1e10, 611 1e100, 612 3.14159265e10, 613 2.718281828e-123, 614 1.0 / 3, 615 math.MaxFloat32, 616 math.MaxFloat64, 617 math.SmallestNonzeroFloat32, 618 math.SmallestNonzeroFloat64, 619 math.Inf(-1), 620 math.Inf(0), 621 -math.Inf(1), 622 } { 623 for i := range [2]int{} { 624 if i&1 != 0 { 625 want = -want 626 } 627 var f Float 628 f.SetFloat64(want) 629 if got, acc := f.Float64(); got != want || acc != Exact { 630 t.Errorf("got %g (%s, %s); want %g (Exact)", got, f.Format('p', 0), acc, want) 631 } 632 } 633 } 634 635 // test basic rounding behavior (exhaustive rounding testing is done elsewhere) 636 const x uint64 = 0x8765432143218 // 53 bits needed 637 for prec := uint(1); prec <= 52; prec++ { 638 f := new(Float).SetPrec(prec).SetMode(ToZero).SetFloat64(float64(x)) 639 got, _ := f.Float64() 640 want := float64(x &^ (1<<(52-prec) - 1)) // cut off (round to zero) low 53-prec bits 641 if got != want { 642 t.Errorf("got %g (%s); want %g", got, f.Format('p', 0), want) 643 } 644 } 645 646 // test NaN 647 defer func() { 648 if p, ok := recover().(ErrNaN); !ok { 649 t.Errorf("got %v; want ErrNaN panic", p) 650 } 651 }() 652 var f Float 653 f.SetFloat64(math.NaN()) 654 // should not reach here 655 t.Errorf("got %s; want ErrNaN panic", f.Format('p', 0)) 656 } 657 658 func TestFloatSetInt(t *testing.T) { 659 for _, want := range []string{ 660 "0", 661 "1", 662 "-1", 663 "1234567890", 664 "123456789012345678901234567890", 665 "123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890", 666 } { 667 var x Int 668 _, ok := x.SetString(want, 0) 669 if !ok { 670 t.Errorf("invalid integer %s", want) 671 continue 672 } 673 n := x.BitLen() 674 675 var f Float 676 f.SetInt(&x) 677 678 // check precision 679 if n < 64 { 680 n = 64 681 } 682 if prec := f.Prec(); prec != uint(n) { 683 t.Errorf("got prec = %d; want %d", prec, n) 684 } 685 686 // check value 687 got := f.Format('g', 100) 688 if got != want { 689 t.Errorf("got %s (%s); want %s", got, f.Format('p', 0), want) 690 } 691 } 692 693 // TODO(gri) test basic rounding behavior 694 } 695 696 func TestFloatSetRat(t *testing.T) { 697 for _, want := range []string{ 698 "0", 699 "1", 700 "-1", 701 "1234567890", 702 "123456789012345678901234567890", 703 "123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890", 704 "1.2", 705 "3.14159265", 706 // TODO(gri) expand 707 } { 708 var x Rat 709 _, ok := x.SetString(want) 710 if !ok { 711 t.Errorf("invalid fraction %s", want) 712 continue 713 } 714 n := max(x.Num().BitLen(), x.Denom().BitLen()) 715 716 var f1, f2 Float 717 f2.SetPrec(1000) 718 f1.SetRat(&x) 719 f2.SetRat(&x) 720 721 // check precision when set automatically 722 if n < 64 { 723 n = 64 724 } 725 if prec := f1.Prec(); prec != uint(n) { 726 t.Errorf("got prec = %d; want %d", prec, n) 727 } 728 729 got := f2.Format('g', 100) 730 if got != want { 731 t.Errorf("got %s (%s); want %s", got, f2.Format('p', 0), want) 732 } 733 } 734 } 735 736 func TestFloatSetInf(t *testing.T) { 737 var f Float 738 for _, test := range []struct { 739 signbit bool 740 prec uint 741 want string 742 }{ 743 {false, 0, "+Inf"}, 744 {true, 0, "-Inf"}, 745 {false, 10, "+Inf"}, 746 {true, 30, "-Inf"}, 747 } { 748 x := f.SetPrec(test.prec).SetInf(test.signbit) 749 if got := x.String(); got != test.want || x.Prec() != test.prec { 750 t.Errorf("SetInf(%v) = %s (prec = %d); want %s (prec = %d)", test.signbit, got, x.Prec(), test.want, test.prec) 751 } 752 } 753 } 754 755 func TestFloatUint64(t *testing.T) { 756 for _, test := range []struct { 757 x string 758 out uint64 759 acc Accuracy 760 }{ 761 {"-Inf", 0, Above}, 762 {"-1", 0, Above}, 763 {"-1e-1000", 0, Above}, 764 {"-0", 0, Exact}, 765 {"0", 0, Exact}, 766 {"1e-1000", 0, Below}, 767 {"1", 1, Exact}, 768 {"1.000000000000000000001", 1, Below}, 769 {"12345.0", 12345, Exact}, 770 {"12345.000000000000000000001", 12345, Below}, 771 {"18446744073709551615", 18446744073709551615, Exact}, 772 {"18446744073709551615.000000000000000000001", math.MaxUint64, Below}, 773 {"18446744073709551616", math.MaxUint64, Below}, 774 {"1e10000", math.MaxUint64, Below}, 775 {"+Inf", math.MaxUint64, Below}, 776 } { 777 x := makeFloat(test.x) 778 out, acc := x.Uint64() 779 if out != test.out || acc != test.acc { 780 t.Errorf("%s: got %d (%s); want %d (%s)", test.x, out, acc, test.out, test.acc) 781 } 782 } 783 } 784 785 func TestFloatInt64(t *testing.T) { 786 for _, test := range []struct { 787 x string 788 out int64 789 acc Accuracy 790 }{ 791 {"-Inf", math.MinInt64, Above}, 792 {"-1e10000", math.MinInt64, Above}, 793 {"-9223372036854775809", math.MinInt64, Above}, 794 {"-9223372036854775808.000000000000000000001", math.MinInt64, Above}, 795 {"-9223372036854775808", -9223372036854775808, Exact}, 796 {"-9223372036854775807.000000000000000000001", -9223372036854775807, Above}, 797 {"-9223372036854775807", -9223372036854775807, Exact}, 798 {"-12345.000000000000000000001", -12345, Above}, 799 {"-12345.0", -12345, Exact}, 800 {"-1.000000000000000000001", -1, Above}, 801 {"-1.5", -1, Above}, 802 {"-1", -1, Exact}, 803 {"-1e-1000", 0, Above}, 804 {"0", 0, Exact}, 805 {"1e-1000", 0, Below}, 806 {"1", 1, Exact}, 807 {"1.000000000000000000001", 1, Below}, 808 {"1.5", 1, Below}, 809 {"12345.0", 12345, Exact}, 810 {"12345.000000000000000000001", 12345, Below}, 811 {"9223372036854775807", 9223372036854775807, Exact}, 812 {"9223372036854775807.000000000000000000001", math.MaxInt64, Below}, 813 {"9223372036854775808", math.MaxInt64, Below}, 814 {"1e10000", math.MaxInt64, Below}, 815 {"+Inf", math.MaxInt64, Below}, 816 } { 817 x := makeFloat(test.x) 818 out, acc := x.Int64() 819 if out != test.out || acc != test.acc { 820 t.Errorf("%s: got %d (%s); want %d (%s)", test.x, out, acc, test.out, test.acc) 821 } 822 } 823 } 824 825 func TestFloatFloat32(t *testing.T) { 826 for _, test := range []struct { 827 x string 828 out float32 829 acc Accuracy 830 }{ 831 {"-Inf", float32(math.Inf(-1)), Exact}, 832 {"-0x1.ffffff0p2147483646", float32(-math.Inf(+1)), Below}, // overflow in rounding 833 {"-1e10000", float32(math.Inf(-1)), Below}, // overflow 834 {"-0x1p128", float32(math.Inf(-1)), Below}, // overflow 835 {"-0x1.ffffff0p127", float32(-math.Inf(+1)), Below}, // overflow 836 {"-0x1.fffffe8p127", -math.MaxFloat32, Above}, 837 {"-0x1.fffffe0p127", -math.MaxFloat32, Exact}, 838 {"-12345.000000000000000000001", -12345, Above}, 839 {"-12345.0", -12345, Exact}, 840 {"-1.000000000000000000001", -1, Above}, 841 {"-1", -1, Exact}, 842 {"-0x0.000002p-126", -math.SmallestNonzeroFloat32, Exact}, 843 {"-0x0.000002p-127", -0, Above}, // underflow 844 {"-1e-1000", -0, Above}, // underflow 845 {"0", 0, Exact}, 846 {"1e-1000", 0, Below}, // underflow 847 {"0x0.000002p-127", 0, Below}, // underflow 848 {"0x0.000002p-126", math.SmallestNonzeroFloat32, Exact}, 849 {"1", 1, Exact}, 850 {"1.000000000000000000001", 1, Below}, 851 {"12345.0", 12345, Exact}, 852 {"12345.000000000000000000001", 12345, Below}, 853 {"0x1.fffffe0p127", math.MaxFloat32, Exact}, 854 {"0x1.fffffe8p127", math.MaxFloat32, Below}, 855 {"0x1.ffffff0p127", float32(math.Inf(+1)), Above}, // overflow 856 {"0x1p128", float32(math.Inf(+1)), Above}, // overflow 857 {"1e10000", float32(math.Inf(+1)), Above}, // overflow 858 {"0x1.ffffff0p2147483646", float32(math.Inf(+1)), Above}, // overflow in rounding 859 {"+Inf", float32(math.Inf(+1)), Exact}, 860 } { 861 // conversion should match strconv where syntax is agreeable 862 if f, err := strconv.ParseFloat(test.x, 32); err == nil && float32(f) != test.out { 863 t.Errorf("%s: got %g; want %g (incorrect test data)", test.x, f, test.out) 864 } 865 866 x := makeFloat(test.x) 867 out, acc := x.Float32() 868 if out != test.out || acc != test.acc { 869 t.Errorf("%s: got %g (%#x, %s); want %g (%#x, %s)", test.x, out, math.Float32bits(out), acc, test.out, math.Float32bits(test.out), test.acc) 870 } 871 872 // test that x.SetFloat64(float64(f)).Float32() == f 873 var x2 Float 874 out2, acc2 := x2.SetFloat64(float64(out)).Float32() 875 if out2 != out || acc2 != Exact { 876 t.Errorf("idempotency test: got %g (%s); want %g (Exact)", out2, acc2, out) 877 } 878 } 879 } 880 881 func TestFloatFloat64(t *testing.T) { 882 const smallestNormalFloat64 = 2.2250738585072014e-308 // 1p-1022 883 for _, test := range []struct { 884 x string 885 out float64 886 acc Accuracy 887 }{ 888 {"-Inf", math.Inf(-1), Exact}, 889 {"-0x1.fffffffffffff8p2147483646", -math.Inf(+1), Below}, // overflow in rounding 890 {"-1e10000", math.Inf(-1), Below}, // overflow 891 {"-0x1p1024", math.Inf(-1), Below}, // overflow 892 {"-0x1.fffffffffffff8p1023", -math.Inf(+1), Below}, // overflow 893 {"-0x1.fffffffffffff4p1023", -math.MaxFloat64, Above}, 894 {"-0x1.fffffffffffff0p1023", -math.MaxFloat64, Exact}, 895 {"-12345.000000000000000000001", -12345, Above}, 896 {"-12345.0", -12345, Exact}, 897 {"-1.000000000000000000001", -1, Above}, 898 {"-1", -1, Exact}, 899 {"-0x0.0000000000001p-1022", -math.SmallestNonzeroFloat64, Exact}, 900 {"-0x0.0000000000001p-1023", -0, Above}, // underflow 901 {"-1e-1000", -0, Above}, // underflow 902 {"0", 0, Exact}, 903 {"1e-1000", 0, Below}, // underflow 904 {"0x0.0000000000001p-1023", 0, Below}, // underflow 905 {"0x0.0000000000001p-1022", math.SmallestNonzeroFloat64, Exact}, 906 {"1", 1, Exact}, 907 {"1.000000000000000000001", 1, Below}, 908 {"12345.0", 12345, Exact}, 909 {"12345.000000000000000000001", 12345, Below}, 910 {"0x1.fffffffffffff0p1023", math.MaxFloat64, Exact}, 911 {"0x1.fffffffffffff4p1023", math.MaxFloat64, Below}, 912 {"0x1.fffffffffffff8p1023", math.Inf(+1), Above}, // overflow 913 {"0x1p1024", math.Inf(+1), Above}, // overflow 914 {"1e10000", math.Inf(+1), Above}, // overflow 915 {"0x1.fffffffffffff8p2147483646", math.Inf(+1), Above}, // overflow in rounding 916 {"+Inf", math.Inf(+1), Exact}, 917 918 // selected denormalized values that were handled incorrectly in the past 919 {"0x.fffffffffffffp-1022", smallestNormalFloat64 - math.SmallestNonzeroFloat64, Exact}, 920 {"4503599627370495p-1074", smallestNormalFloat64 - math.SmallestNonzeroFloat64, Exact}, 921 922 // http://www.exploringbinary.com/php-hangs-on-numeric-value-2-2250738585072011e-308/ 923 {"2.2250738585072011e-308", 2.225073858507201e-308, Below}, 924 // http://www.exploringbinary.com/java-hangs-when-converting-2-2250738585072012e-308/ 925 {"2.2250738585072012e-308", 2.2250738585072014e-308, Above}, 926 } { 927 // conversion should match strconv where syntax is agreeable 928 if f, err := strconv.ParseFloat(test.x, 64); err == nil && f != test.out { 929 t.Errorf("%s: got %g; want %g (incorrect test data)", test.x, f, test.out) 930 } 931 932 x := makeFloat(test.x) 933 out, acc := x.Float64() 934 if out != test.out || acc != test.acc { 935 t.Errorf("%s: got %g (%#x, %s); want %g (%#x, %s)", test.x, out, math.Float64bits(out), acc, test.out, math.Float64bits(test.out), test.acc) 936 } 937 938 // test that x.SetFloat64(f).Float64() == f 939 var x2 Float 940 out2, acc2 := x2.SetFloat64(out).Float64() 941 if out2 != out || acc2 != Exact { 942 t.Errorf("idempotency test: got %g (%s); want %g (Exact)", out2, acc2, out) 943 } 944 } 945 } 946 947 func TestFloatInt(t *testing.T) { 948 for _, test := range []struct { 949 x string 950 want string 951 acc Accuracy 952 }{ 953 {"0", "0", Exact}, 954 {"+0", "0", Exact}, 955 {"-0", "0", Exact}, 956 {"Inf", "nil", Below}, 957 {"+Inf", "nil", Below}, 958 {"-Inf", "nil", Above}, 959 {"1", "1", Exact}, 960 {"-1", "-1", Exact}, 961 {"1.23", "1", Below}, 962 {"-1.23", "-1", Above}, 963 {"123e-2", "1", Below}, 964 {"123e-3", "0", Below}, 965 {"123e-4", "0", Below}, 966 {"1e-1000", "0", Below}, 967 {"-1e-1000", "0", Above}, 968 {"1e+10", "10000000000", Exact}, 969 {"1e+100", "10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", Exact}, 970 } { 971 x := makeFloat(test.x) 972 res, acc := x.Int(nil) 973 got := "nil" 974 if res != nil { 975 got = res.String() 976 } 977 if got != test.want || acc != test.acc { 978 t.Errorf("%s: got %s (%s); want %s (%s)", test.x, got, acc, test.want, test.acc) 979 } 980 } 981 982 // check that supplied *Int is used 983 for _, f := range []string{"0", "1", "-1", "1234"} { 984 x := makeFloat(f) 985 i := new(Int) 986 if res, _ := x.Int(i); res != i { 987 t.Errorf("(%s).Int is not using supplied *Int", f) 988 } 989 } 990 } 991 992 func TestFloatRat(t *testing.T) { 993 for _, test := range []struct { 994 x, want string 995 acc Accuracy 996 }{ 997 {"0", "0/1", Exact}, 998 {"+0", "0/1", Exact}, 999 {"-0", "0/1", Exact}, 1000 {"Inf", "nil", Below}, 1001 {"+Inf", "nil", Below}, 1002 {"-Inf", "nil", Above}, 1003 {"1", "1/1", Exact}, 1004 {"-1", "-1/1", Exact}, 1005 {"1.25", "5/4", Exact}, 1006 {"-1.25", "-5/4", Exact}, 1007 {"1e10", "10000000000/1", Exact}, 1008 {"1p10", "1024/1", Exact}, 1009 {"-1p-10", "-1/1024", Exact}, 1010 {"3.14159265", "7244019449799623199/2305843009213693952", Exact}, 1011 } { 1012 x := makeFloat(test.x).SetPrec(64) 1013 res, acc := x.Rat(nil) 1014 got := "nil" 1015 if res != nil { 1016 got = res.String() 1017 } 1018 if got != test.want { 1019 t.Errorf("%s: got %s; want %s", test.x, got, test.want) 1020 continue 1021 } 1022 if acc != test.acc { 1023 t.Errorf("%s: got %s; want %s", test.x, acc, test.acc) 1024 continue 1025 } 1026 1027 // inverse conversion 1028 if res != nil { 1029 got := new(Float).SetPrec(64).SetRat(res) 1030 if got.Cmp(x) != 0 { 1031 t.Errorf("%s: got %s; want %s", test.x, got, x) 1032 } 1033 } 1034 } 1035 1036 // check that supplied *Rat is used 1037 for _, f := range []string{"0", "1", "-1", "1234"} { 1038 x := makeFloat(f) 1039 r := new(Rat) 1040 if res, _ := x.Rat(r); res != r { 1041 t.Errorf("(%s).Rat is not using supplied *Rat", f) 1042 } 1043 } 1044 } 1045 1046 func TestFloatAbs(t *testing.T) { 1047 for _, test := range []string{ 1048 "0", 1049 "1", 1050 "1234", 1051 "1.23e-2", 1052 "1e-1000", 1053 "1e1000", 1054 "Inf", 1055 } { 1056 p := makeFloat(test) 1057 a := new(Float).Abs(p) 1058 if !alike(a, p) { 1059 t.Errorf("%s: got %s; want %s", test, a.Format('g', 10), test) 1060 } 1061 1062 n := makeFloat("-" + test) 1063 a.Abs(n) 1064 if !alike(a, p) { 1065 t.Errorf("-%s: got %s; want %s", test, a.Format('g', 10), test) 1066 } 1067 } 1068 } 1069 1070 func TestFloatNeg(t *testing.T) { 1071 for _, test := range []string{ 1072 "0", 1073 "1", 1074 "1234", 1075 "1.23e-2", 1076 "1e-1000", 1077 "1e1000", 1078 "Inf", 1079 } { 1080 p1 := makeFloat(test) 1081 n1 := makeFloat("-" + test) 1082 n2 := new(Float).Neg(p1) 1083 p2 := new(Float).Neg(n2) 1084 if !alike(n2, n1) { 1085 t.Errorf("%s: got %s; want %s", test, n2.Format('g', 10), n1.Format('g', 10)) 1086 } 1087 if !alike(p2, p1) { 1088 t.Errorf("%s: got %s; want %s", test, p2.Format('g', 10), p1.Format('g', 10)) 1089 } 1090 } 1091 } 1092 1093 func TestFloatInc(t *testing.T) { 1094 const n = 10 1095 for _, prec := range precList { 1096 if 1<<prec < n { 1097 continue // prec must be large enough to hold all numbers from 0 to n 1098 } 1099 var x, one Float 1100 x.SetPrec(prec) 1101 one.SetInt64(1) 1102 for i := 0; i < n; i++ { 1103 x.Add(&x, &one) 1104 } 1105 if x.Cmp(new(Float).SetInt64(n)) != 0 { 1106 t.Errorf("prec = %d: got %s; want %d", prec, &x, n) 1107 } 1108 } 1109 } 1110 1111 // Selected precisions with which to run various tests. 1112 var precList = [...]uint{1, 2, 5, 8, 10, 16, 23, 24, 32, 50, 53, 64, 100, 128, 500, 511, 512, 513, 1000, 10000} 1113 1114 // Selected bits with which to run various tests. 1115 // Each entry is a list of bits representing a floating-point number (see fromBits). 1116 var bitsList = [...]Bits{ 1117 {}, // = 0 1118 {0}, // = 1 1119 {1}, // = 2 1120 {-1}, // = 1/2 1121 {10}, // = 2**10 == 1024 1122 {-10}, // = 2**-10 == 1/1024 1123 {100, 10, 1}, // = 2**100 + 2**10 + 2**1 1124 {0, -1, -2, -10}, 1125 // TODO(gri) add more test cases 1126 } 1127 1128 // TestFloatAdd tests Float.Add/Sub by comparing the result of a "manual" 1129 // addition/subtraction of arguments represented by Bits values with the 1130 // respective Float addition/subtraction for a variety of precisions 1131 // and rounding modes. 1132 func TestFloatAdd(t *testing.T) { 1133 for _, xbits := range bitsList { 1134 for _, ybits := range bitsList { 1135 // exact values 1136 x := xbits.Float() 1137 y := ybits.Float() 1138 zbits := xbits.add(ybits) 1139 z := zbits.Float() 1140 1141 for i, mode := range [...]RoundingMode{ToZero, ToNearestEven, AwayFromZero} { 1142 for _, prec := range precList { 1143 got := new(Float).SetPrec(prec).SetMode(mode) 1144 got.Add(x, y) 1145 want := zbits.round(prec, mode) 1146 if got.Cmp(want) != 0 { 1147 t.Errorf("i = %d, prec = %d, %s:\n\t %s %v\n\t+ %s %v\n\t= %s\n\twant %s", 1148 i, prec, mode, x, xbits, y, ybits, got, want) 1149 } 1150 1151 got.Sub(z, x) 1152 want = ybits.round(prec, mode) 1153 if got.Cmp(want) != 0 { 1154 t.Errorf("i = %d, prec = %d, %s:\n\t %s %v\n\t- %s %v\n\t= %s\n\twant %s", 1155 i, prec, mode, z, zbits, x, xbits, got, want) 1156 } 1157 } 1158 } 1159 } 1160 } 1161 } 1162 1163 // TestFloatAdd32 tests that Float.Add/Sub of numbers with 1164 // 24bit mantissa behaves like float32 addition/subtraction 1165 // (excluding denormal numbers). 1166 func TestFloatAdd32(t *testing.T) { 1167 // chose base such that we cross the mantissa precision limit 1168 const base = 1<<26 - 0x10 // 11...110000 (26 bits) 1169 for d := 0; d <= 0x10; d++ { 1170 for i := range [2]int{} { 1171 x0, y0 := float64(base), float64(d) 1172 if i&1 != 0 { 1173 x0, y0 = y0, x0 1174 } 1175 1176 x := NewFloat(x0) 1177 y := NewFloat(y0) 1178 z := new(Float).SetPrec(24) 1179 1180 z.Add(x, y) 1181 got, acc := z.Float32() 1182 want := float32(y0) + float32(x0) 1183 if got != want || acc != Exact { 1184 t.Errorf("d = %d: %g + %g = %g (%s); want %g (Exact)", d, x0, y0, got, acc, want) 1185 } 1186 1187 z.Sub(z, y) 1188 got, acc = z.Float32() 1189 want = float32(want) - float32(y0) 1190 if got != want || acc != Exact { 1191 t.Errorf("d = %d: %g - %g = %g (%s); want %g (Exact)", d, x0+y0, y0, got, acc, want) 1192 } 1193 } 1194 } 1195 } 1196 1197 // TestFloatAdd64 tests that Float.Add/Sub of numbers with 1198 // 53bit mantissa behaves like float64 addition/subtraction. 1199 func TestFloatAdd64(t *testing.T) { 1200 // chose base such that we cross the mantissa precision limit 1201 const base = 1<<55 - 0x10 // 11...110000 (55 bits) 1202 for d := 0; d <= 0x10; d++ { 1203 for i := range [2]int{} { 1204 x0, y0 := float64(base), float64(d) 1205 if i&1 != 0 { 1206 x0, y0 = y0, x0 1207 } 1208 1209 x := NewFloat(x0) 1210 y := NewFloat(y0) 1211 z := new(Float).SetPrec(53) 1212 1213 z.Add(x, y) 1214 got, acc := z.Float64() 1215 want := x0 + y0 1216 if got != want || acc != Exact { 1217 t.Errorf("d = %d: %g + %g = %g (%s); want %g (Exact)", d, x0, y0, got, acc, want) 1218 } 1219 1220 z.Sub(z, y) 1221 got, acc = z.Float64() 1222 want -= y0 1223 if got != want || acc != Exact { 1224 t.Errorf("d = %d: %g - %g = %g (%s); want %g (Exact)", d, x0+y0, y0, got, acc, want) 1225 } 1226 } 1227 } 1228 } 1229 1230 // TestFloatMul tests Float.Mul/Quo by comparing the result of a "manual" 1231 // multiplication/division of arguments represented by Bits values with the 1232 // respective Float multiplication/division for a variety of precisions 1233 // and rounding modes. 1234 func TestFloatMul(t *testing.T) { 1235 for _, xbits := range bitsList { 1236 for _, ybits := range bitsList { 1237 // exact values 1238 x := xbits.Float() 1239 y := ybits.Float() 1240 zbits := xbits.mul(ybits) 1241 z := zbits.Float() 1242 1243 for i, mode := range [...]RoundingMode{ToZero, ToNearestEven, AwayFromZero} { 1244 for _, prec := range precList { 1245 got := new(Float).SetPrec(prec).SetMode(mode) 1246 got.Mul(x, y) 1247 want := zbits.round(prec, mode) 1248 if got.Cmp(want) != 0 { 1249 t.Errorf("i = %d, prec = %d, %s:\n\t %s %v\n\t* %s %v\n\t= %s\n\twant %s", 1250 i, prec, mode, x, xbits, y, ybits, got, want) 1251 } 1252 1253 if x.Sign() == 0 { 1254 continue // ignore div-0 case (not invertable) 1255 } 1256 got.Quo(z, x) 1257 want = ybits.round(prec, mode) 1258 if got.Cmp(want) != 0 { 1259 t.Errorf("i = %d, prec = %d, %s:\n\t %s %v\n\t/ %s %v\n\t= %s\n\twant %s", 1260 i, prec, mode, z, zbits, x, xbits, got, want) 1261 } 1262 } 1263 } 1264 } 1265 } 1266 } 1267 1268 // TestFloatMul64 tests that Float.Mul/Quo of numbers with 1269 // 53bit mantissa behaves like float64 multiplication/division. 1270 func TestFloatMul64(t *testing.T) { 1271 for _, test := range []struct { 1272 x, y float64 1273 }{ 1274 {0, 0}, 1275 {0, 1}, 1276 {1, 1}, 1277 {1, 1.5}, 1278 {1.234, 0.5678}, 1279 {2.718281828, 3.14159265358979}, 1280 {2.718281828e10, 3.14159265358979e-32}, 1281 {1.0 / 3, 1e200}, 1282 } { 1283 for i := range [8]int{} { 1284 x0, y0 := test.x, test.y 1285 if i&1 != 0 { 1286 x0 = -x0 1287 } 1288 if i&2 != 0 { 1289 y0 = -y0 1290 } 1291 if i&4 != 0 { 1292 x0, y0 = y0, x0 1293 } 1294 1295 x := NewFloat(x0) 1296 y := NewFloat(y0) 1297 z := new(Float).SetPrec(53) 1298 1299 z.Mul(x, y) 1300 got, _ := z.Float64() 1301 want := x0 * y0 1302 if got != want { 1303 t.Errorf("%g * %g = %g; want %g", x0, y0, got, want) 1304 } 1305 1306 if y0 == 0 { 1307 continue // avoid division-by-zero 1308 } 1309 z.Quo(z, y) 1310 got, _ = z.Float64() 1311 want /= y0 1312 if got != want { 1313 t.Errorf("%g / %g = %g; want %g", x0*y0, y0, got, want) 1314 } 1315 } 1316 } 1317 } 1318 1319 func TestIssue6866(t *testing.T) { 1320 for _, prec := range precList { 1321 two := new(Float).SetPrec(prec).SetInt64(2) 1322 one := new(Float).SetPrec(prec).SetInt64(1) 1323 three := new(Float).SetPrec(prec).SetInt64(3) 1324 msix := new(Float).SetPrec(prec).SetInt64(-6) 1325 psix := new(Float).SetPrec(prec).SetInt64(+6) 1326 1327 p := new(Float).SetPrec(prec) 1328 z1 := new(Float).SetPrec(prec) 1329 z2 := new(Float).SetPrec(prec) 1330 1331 // z1 = 2 + 1.0/3*-6 1332 p.Quo(one, three) 1333 p.Mul(p, msix) 1334 z1.Add(two, p) 1335 1336 // z2 = 2 - 1.0/3*+6 1337 p.Quo(one, three) 1338 p.Mul(p, psix) 1339 z2.Sub(two, p) 1340 1341 if z1.Cmp(z2) != 0 { 1342 t.Fatalf("prec %d: got z1 = %s != z2 = %s; want z1 == z2\n", prec, z1, z2) 1343 } 1344 if z1.Sign() != 0 { 1345 t.Errorf("prec %d: got z1 = %s; want 0", prec, z1) 1346 } 1347 if z2.Sign() != 0 { 1348 t.Errorf("prec %d: got z2 = %s; want 0", prec, z2) 1349 } 1350 } 1351 } 1352 1353 func TestFloatQuo(t *testing.T) { 1354 // TODO(gri) make the test vary these precisions 1355 preci := 200 // precision of integer part 1356 precf := 20 // precision of fractional part 1357 1358 for i := 0; i < 8; i++ { 1359 // compute accurate (not rounded) result z 1360 bits := Bits{preci - 1} 1361 if i&3 != 0 { 1362 bits = append(bits, 0) 1363 } 1364 if i&2 != 0 { 1365 bits = append(bits, -1) 1366 } 1367 if i&1 != 0 { 1368 bits = append(bits, -precf) 1369 } 1370 z := bits.Float() 1371 1372 // compute accurate x as z*y 1373 y := NewFloat(3.14159265358979323e123) 1374 1375 x := new(Float).SetPrec(z.Prec() + y.Prec()).SetMode(ToZero) 1376 x.Mul(z, y) 1377 1378 // leave for debugging 1379 // fmt.Printf("x = %s\ny = %s\nz = %s\n", x, y, z) 1380 1381 if got := x.Acc(); got != Exact { 1382 t.Errorf("got acc = %s; want exact", got) 1383 } 1384 1385 // round accurate z for a variety of precisions and 1386 // modes and compare against result of x / y. 1387 for _, mode := range [...]RoundingMode{ToZero, ToNearestEven, AwayFromZero} { 1388 for d := -5; d < 5; d++ { 1389 prec := uint(preci + d) 1390 got := new(Float).SetPrec(prec).SetMode(mode).Quo(x, y) 1391 want := bits.round(prec, mode) 1392 if got.Cmp(want) != 0 { 1393 t.Errorf("i = %d, prec = %d, %s:\n\t %s\n\t/ %s\n\t= %s\n\twant %s", 1394 i, prec, mode, x, y, got, want) 1395 } 1396 } 1397 } 1398 } 1399 } 1400 1401 // TestFloatQuoSmoke tests all divisions x/y for values x, y in the range [-n, +n]; 1402 // it serves as a smoke test for basic correctness of division. 1403 func TestFloatQuoSmoke(t *testing.T) { 1404 n := 1000 1405 if testing.Short() { 1406 n = 10 1407 } 1408 1409 const dprec = 3 // max. precision variation 1410 const prec = 10 + dprec // enough bits to hold n precisely 1411 for x := -n; x <= n; x++ { 1412 for y := -n; y < n; y++ { 1413 if y == 0 { 1414 continue 1415 } 1416 1417 a := float64(x) 1418 b := float64(y) 1419 c := a / b 1420 1421 // vary operand precision (only ok as long as a, b can be represented correctly) 1422 for ad := -dprec; ad <= dprec; ad++ { 1423 for bd := -dprec; bd <= dprec; bd++ { 1424 A := new(Float).SetPrec(uint(prec + ad)).SetFloat64(a) 1425 B := new(Float).SetPrec(uint(prec + bd)).SetFloat64(b) 1426 C := new(Float).SetPrec(53).Quo(A, B) // C has float64 mantissa width 1427 1428 cc, acc := C.Float64() 1429 if cc != c { 1430 t.Errorf("%g/%g = %s; want %.5g\n", a, b, C.Format('g', 5), c) 1431 continue 1432 } 1433 if acc != Exact { 1434 t.Errorf("%g/%g got %s result; want exact result", a, b, acc) 1435 } 1436 } 1437 } 1438 } 1439 } 1440 } 1441 1442 // TestFloatArithmeticSpecialValues tests that Float operations produce the 1443 // correct results for combinations of zero (±0), finite (±1 and ±2.71828), 1444 // and infinite (±Inf) operands. 1445 func TestFloatArithmeticSpecialValues(t *testing.T) { 1446 zero := 0.0 1447 args := []float64{math.Inf(-1), -2.71828, -1, -zero, zero, 1, 2.71828, math.Inf(1)} 1448 xx := new(Float) 1449 yy := new(Float) 1450 got := new(Float) 1451 want := new(Float) 1452 for i := 0; i < 4; i++ { 1453 for _, x := range args { 1454 xx.SetFloat64(x) 1455 // check conversion is correct 1456 // (no need to do this for y, since we see exactly the 1457 // same values there) 1458 if got, acc := xx.Float64(); got != x || acc != Exact { 1459 t.Errorf("Float(%g) == %g (%s)", x, got, acc) 1460 } 1461 for _, y := range args { 1462 yy.SetFloat64(y) 1463 var ( 1464 op string 1465 z float64 1466 f func(z, x, y *Float) *Float 1467 ) 1468 switch i { 1469 case 0: 1470 op = "+" 1471 z = x + y 1472 f = (*Float).Add 1473 case 1: 1474 op = "-" 1475 z = x - y 1476 f = (*Float).Sub 1477 case 2: 1478 op = "*" 1479 z = x * y 1480 f = (*Float).Mul 1481 case 3: 1482 op = "/" 1483 z = x / y 1484 f = (*Float).Quo 1485 default: 1486 panic("unreachable") 1487 } 1488 var errnan bool // set if execution of f panicked with ErrNaN 1489 // protect execution of f 1490 func() { 1491 defer func() { 1492 if p := recover(); p != nil { 1493 _ = p.(ErrNaN) // re-panic if not ErrNaN 1494 errnan = true 1495 } 1496 }() 1497 f(got, xx, yy) 1498 }() 1499 if math.IsNaN(z) { 1500 if !errnan { 1501 t.Errorf("%5g %s %5g = %5s; want ErrNaN panic", x, op, y, got) 1502 } 1503 continue 1504 } 1505 if errnan { 1506 t.Errorf("%5g %s %5g panicked with ErrNan; want %5s", x, op, y, want) 1507 continue 1508 } 1509 want.SetFloat64(z) 1510 if !alike(got, want) { 1511 t.Errorf("%5g %s %5g = %5s; want %5s", x, op, y, got, want) 1512 } 1513 } 1514 } 1515 } 1516 } 1517 1518 func TestFloatArithmeticOverflow(t *testing.T) { 1519 for _, test := range []struct { 1520 prec uint 1521 mode RoundingMode 1522 op byte 1523 x, y, want string 1524 acc Accuracy 1525 }{ 1526 {4, ToNearestEven, '+', "0", "0", "0", Exact}, // smoke test 1527 {4, ToNearestEven, '+', "0x.8p0", "0x.8p0", "0x.8p1", Exact}, // smoke test 1528 1529 {4, ToNearestEven, '+', "0", "0x.8p2147483647", "0x.8p2147483647", Exact}, 1530 {4, ToNearestEven, '+', "0x.8p2147483500", "0x.8p2147483647", "0x.8p2147483647", Below}, // rounded to zero 1531 {4, ToNearestEven, '+', "0x.8p2147483647", "0x.8p2147483647", "+Inf", Above}, // exponent overflow in + 1532 {4, ToNearestEven, '+', "-0x.8p2147483647", "-0x.8p2147483647", "-Inf", Below}, // exponent overflow in + 1533 {4, ToNearestEven, '-', "-0x.8p2147483647", "0x.8p2147483647", "-Inf", Below}, // exponent overflow in - 1534 1535 {4, ToZero, '+', "0x.fp2147483647", "0x.8p2147483643", "0x.fp2147483647", Below}, // rounded to zero 1536 {4, ToNearestEven, '+', "0x.fp2147483647", "0x.8p2147483643", "+Inf", Above}, // exponent overflow in rounding 1537 {4, AwayFromZero, '+', "0x.fp2147483647", "0x.8p2147483643", "+Inf", Above}, // exponent overflow in rounding 1538 1539 {4, AwayFromZero, '-', "-0x.fp2147483647", "0x.8p2147483644", "-Inf", Below}, // exponent overflow in rounding 1540 {4, ToNearestEven, '-', "-0x.fp2147483647", "0x.8p2147483643", "-Inf", Below}, // exponent overflow in rounding 1541 {4, ToZero, '-', "-0x.fp2147483647", "0x.8p2147483643", "-0x.fp2147483647", Above}, // rounded to zero 1542 1543 {4, ToNearestEven, '+', "0", "0x.8p-2147483648", "0x.8p-2147483648", Exact}, 1544 {4, ToNearestEven, '+', "0x.8p-2147483648", "0x.8p-2147483648", "0x.8p-2147483647", Exact}, 1545 1546 {4, ToNearestEven, '*', "1", "0x.8p2147483647", "0x.8p2147483647", Exact}, 1547 {4, ToNearestEven, '*', "2", "0x.8p2147483647", "+Inf", Above}, // exponent overflow in * 1548 {4, ToNearestEven, '*', "-2", "0x.8p2147483647", "-Inf", Below}, // exponent overflow in * 1549 1550 {4, ToNearestEven, '/', "0.5", "0x.8p2147483647", "0x.8p-2147483646", Exact}, 1551 {4, ToNearestEven, '/', "0x.8p0", "0x.8p2147483647", "0x.8p-2147483646", Exact}, 1552 {4, ToNearestEven, '/', "0x.8p-1", "0x.8p2147483647", "0x.8p-2147483647", Exact}, 1553 {4, ToNearestEven, '/', "0x.8p-2", "0x.8p2147483647", "0x.8p-2147483648", Exact}, 1554 {4, ToNearestEven, '/', "0x.8p-3", "0x.8p2147483647", "0", Below}, // exponent underflow in / 1555 } { 1556 x := makeFloat(test.x) 1557 y := makeFloat(test.y) 1558 z := new(Float).SetPrec(test.prec).SetMode(test.mode) 1559 switch test.op { 1560 case '+': 1561 z.Add(x, y) 1562 case '-': 1563 z.Sub(x, y) 1564 case '*': 1565 z.Mul(x, y) 1566 case '/': 1567 z.Quo(x, y) 1568 default: 1569 panic("unreachable") 1570 } 1571 if got := z.Format('p', 0); got != test.want || z.Acc() != test.acc { 1572 t.Errorf( 1573 "prec = %d (%s): %s %c %s = %s (%s); want %s (%s)", 1574 test.prec, test.mode, x.Format('p', 0), test.op, y.Format('p', 0), got, z.Acc(), test.want, test.acc, 1575 ) 1576 } 1577 } 1578 } 1579 1580 // TODO(gri) Add tests that check correctness in the presence of aliasing. 1581 1582 // For rounding modes ToNegativeInf and ToPositiveInf, rounding is affected 1583 // by the sign of the value to be rounded. Test that rounding happens after 1584 // the sign of a result has been set. 1585 // This test uses specific values that are known to fail if rounding is 1586 // "factored" out before setting the result sign. 1587 func TestFloatArithmeticRounding(t *testing.T) { 1588 for _, test := range []struct { 1589 mode RoundingMode 1590 prec uint 1591 x, y, want int64 1592 op byte 1593 }{ 1594 {ToZero, 3, -0x8, -0x1, -0x8, '+'}, 1595 {AwayFromZero, 3, -0x8, -0x1, -0xa, '+'}, 1596 {ToNegativeInf, 3, -0x8, -0x1, -0xa, '+'}, 1597 1598 {ToZero, 3, -0x8, 0x1, -0x8, '-'}, 1599 {AwayFromZero, 3, -0x8, 0x1, -0xa, '-'}, 1600 {ToNegativeInf, 3, -0x8, 0x1, -0xa, '-'}, 1601 1602 {ToZero, 3, -0x9, 0x1, -0x8, '*'}, 1603 {AwayFromZero, 3, -0x9, 0x1, -0xa, '*'}, 1604 {ToNegativeInf, 3, -0x9, 0x1, -0xa, '*'}, 1605 1606 {ToZero, 3, -0x9, 0x1, -0x8, '/'}, 1607 {AwayFromZero, 3, -0x9, 0x1, -0xa, '/'}, 1608 {ToNegativeInf, 3, -0x9, 0x1, -0xa, '/'}, 1609 } { 1610 var x, y, z Float 1611 x.SetInt64(test.x) 1612 y.SetInt64(test.y) 1613 z.SetPrec(test.prec).SetMode(test.mode) 1614 switch test.op { 1615 case '+': 1616 z.Add(&x, &y) 1617 case '-': 1618 z.Sub(&x, &y) 1619 case '*': 1620 z.Mul(&x, &y) 1621 case '/': 1622 z.Quo(&x, &y) 1623 default: 1624 panic("unreachable") 1625 } 1626 if got, acc := z.Int64(); got != test.want || acc != Exact { 1627 t.Errorf("%s, %d bits: %d %c %d = %d (%s); want %d (Exact)", 1628 test.mode, test.prec, test.x, test.op, test.y, got, acc, test.want, 1629 ) 1630 } 1631 } 1632 } 1633 1634 // TestFloatCmpSpecialValues tests that Cmp produces the correct results for 1635 // combinations of zero (±0), finite (±1 and ±2.71828), and infinite (±Inf) 1636 // operands. 1637 func TestFloatCmpSpecialValues(t *testing.T) { 1638 zero := 0.0 1639 args := []float64{math.Inf(-1), -2.71828, -1, -zero, zero, 1, 2.71828, math.Inf(1)} 1640 xx := new(Float) 1641 yy := new(Float) 1642 for i := 0; i < 4; i++ { 1643 for _, x := range args { 1644 xx.SetFloat64(x) 1645 // check conversion is correct 1646 // (no need to do this for y, since we see exactly the 1647 // same values there) 1648 if got, acc := xx.Float64(); got != x || acc != Exact { 1649 t.Errorf("Float(%g) == %g (%s)", x, got, acc) 1650 } 1651 for _, y := range args { 1652 yy.SetFloat64(y) 1653 got := xx.Cmp(yy) 1654 want := 0 1655 switch { 1656 case x < y: 1657 want = -1 1658 case x > y: 1659 want = +1 1660 } 1661 if got != want { 1662 t.Errorf("(%g).Cmp(%g) = %s; want %s", x, y, got, want) 1663 } 1664 } 1665 } 1666 } 1667 }