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