github.com/q45/go@v0.0.0-20151101211701-a4fb8c13db3f/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 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 // normals 847 {"0x.ffffffp-126", math.Float32frombits(0x00800000), Above}, // rounded up to smallest normal 848 {"1p-126", math.Float32frombits(0x00800000), Exact}, // smallest normal 849 {"0x1.fffffep-126", math.Float32frombits(0x00ffffff), Exact}, 850 {"0x1.ffffffp-126", math.Float32frombits(0x01000000), Above}, // rounded up 851 {"1", 1, Exact}, 852 {"1.000000000000000000001", 1, Below}, 853 {"12345.0", 12345, Exact}, 854 {"12345.000000000000000000001", 12345, Below}, 855 {"0x1.fffffe0p127", math.MaxFloat32, Exact}, 856 {"0x1.fffffe8p127", math.MaxFloat32, Below}, 857 858 // overflow 859 {"0x1.ffffff0p127", float32(math.Inf(+1)), Above}, 860 {"0x1p128", float32(math.Inf(+1)), Above}, 861 {"1e10000", float32(math.Inf(+1)), Above}, 862 {"0x1.ffffff0p2147483646", float32(math.Inf(+1)), Above}, // overflow in rounding 863 864 // inf 865 {"Inf", float32(math.Inf(+1)), Exact}, 866 } { 867 for i := 0; i < 2; i++ { 868 // test both signs 869 tx, tout, tacc := test.x, test.out, test.acc 870 if i != 0 { 871 tx = "-" + tx 872 tout = -tout 873 tacc = -tacc 874 } 875 876 // conversion should match strconv where syntax is agreeable 877 if f, err := strconv.ParseFloat(tx, 32); err == nil && !alike32(float32(f), tout) { 878 t.Errorf("%s: got %g; want %g (incorrect test data)", tx, f, tout) 879 } 880 881 x := makeFloat(tx) 882 out, acc := x.Float32() 883 if !alike32(out, tout) || acc != tacc { 884 t.Errorf("%s: got %g (%#x, %s); want %g (%#x, %s)", tx, out, math.Float32bits(out), acc, test.out, math.Float32bits(test.out), tacc) 885 } 886 887 // test that x.SetFloat64(float64(f)).Float32() == f 888 var x2 Float 889 out2, acc2 := x2.SetFloat64(float64(out)).Float32() 890 if !alike32(out2, out) || acc2 != Exact { 891 t.Errorf("idempotency test: got %g (%s); want %g (Exact)", out2, acc2, out) 892 } 893 } 894 } 895 } 896 897 func TestFloatFloat64(t *testing.T) { 898 const smallestNormalFloat64 = 2.2250738585072014e-308 // 1p-1022 899 for _, test := range []struct { 900 x string 901 out float64 902 acc Accuracy 903 }{ 904 {"0", 0, Exact}, 905 906 // underflow 907 {"1e-1000", 0, Below}, 908 {"0x0.0000000000001p-1023", 0, Below}, 909 {"0x0.00000000000008p-1022", 0, Below}, 910 911 // denormals 912 {"0x0.0000000000000cp-1022", math.SmallestNonzeroFloat64, Above}, // rounded up to smallest denormal 913 {"0x0.0000000000001p-1022", math.SmallestNonzeroFloat64, Exact}, // smallest denormal 914 {"0x.8p-1073", math.SmallestNonzeroFloat64, Exact}, 915 {"1p-1074", math.SmallestNonzeroFloat64, Exact}, 916 {"0x.fffffffffffffp-1022", math.Float64frombits(0x000fffffffffffff), Exact}, // largest denormal 917 918 // normals 919 {"0x.fffffffffffff8p-1022", math.Float64frombits(0x0010000000000000), Above}, // rounded up to smallest normal 920 {"1p-1022", math.Float64frombits(0x0010000000000000), Exact}, // smallest normal 921 {"1", 1, Exact}, 922 {"1.000000000000000000001", 1, Below}, 923 {"12345.0", 12345, Exact}, 924 {"12345.000000000000000000001", 12345, Below}, 925 {"0x1.fffffffffffff0p1023", math.MaxFloat64, Exact}, 926 {"0x1.fffffffffffff4p1023", math.MaxFloat64, Below}, 927 928 // overflow 929 {"0x1.fffffffffffff8p1023", math.Inf(+1), Above}, 930 {"0x1p1024", math.Inf(+1), Above}, 931 {"1e10000", math.Inf(+1), Above}, 932 {"0x1.fffffffffffff8p2147483646", math.Inf(+1), Above}, // overflow in rounding 933 {"Inf", math.Inf(+1), Exact}, 934 935 // selected denormalized values that were handled incorrectly in the past 936 {"0x.fffffffffffffp-1022", smallestNormalFloat64 - math.SmallestNonzeroFloat64, Exact}, 937 {"4503599627370495p-1074", smallestNormalFloat64 - math.SmallestNonzeroFloat64, Exact}, 938 939 // http://www.exploringbinary.com/php-hangs-on-numeric-value-2-2250738585072011e-308/ 940 {"2.2250738585072011e-308", 2.225073858507201e-308, Below}, 941 // http://www.exploringbinary.com/java-hangs-when-converting-2-2250738585072012e-308/ 942 {"2.2250738585072012e-308", 2.2250738585072014e-308, Above}, 943 } { 944 for i := 0; i < 2; i++ { 945 // test both signs 946 tx, tout, tacc := test.x, test.out, test.acc 947 if i != 0 { 948 tx = "-" + tx 949 tout = -tout 950 tacc = -tacc 951 } 952 953 // conversion should match strconv where syntax is agreeable 954 if f, err := strconv.ParseFloat(tx, 64); err == nil && !alike64(f, tout) { 955 t.Errorf("%s: got %g; want %g (incorrect test data)", tx, f, tout) 956 } 957 958 x := makeFloat(tx) 959 out, acc := x.Float64() 960 if !alike64(out, tout) || acc != tacc { 961 t.Errorf("%s: got %g (%#x, %s); want %g (%#x, %s)", tx, out, math.Float64bits(out), acc, test.out, math.Float64bits(test.out), tacc) 962 } 963 964 // test that x.SetFloat64(f).Float64() == f 965 var x2 Float 966 out2, acc2 := x2.SetFloat64(out).Float64() 967 if !alike64(out2, out) || acc2 != Exact { 968 t.Errorf("idempotency test: got %g (%s); want %g (Exact)", out2, acc2, out) 969 } 970 } 971 } 972 } 973 974 func TestFloatInt(t *testing.T) { 975 for _, test := range []struct { 976 x string 977 want string 978 acc Accuracy 979 }{ 980 {"0", "0", Exact}, 981 {"+0", "0", Exact}, 982 {"-0", "0", Exact}, 983 {"Inf", "nil", Below}, 984 {"+Inf", "nil", Below}, 985 {"-Inf", "nil", Above}, 986 {"1", "1", Exact}, 987 {"-1", "-1", Exact}, 988 {"1.23", "1", Below}, 989 {"-1.23", "-1", Above}, 990 {"123e-2", "1", Below}, 991 {"123e-3", "0", Below}, 992 {"123e-4", "0", Below}, 993 {"1e-1000", "0", Below}, 994 {"-1e-1000", "0", Above}, 995 {"1e+10", "10000000000", Exact}, 996 {"1e+100", "10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", Exact}, 997 } { 998 x := makeFloat(test.x) 999 res, acc := x.Int(nil) 1000 got := "nil" 1001 if res != nil { 1002 got = res.String() 1003 } 1004 if got != test.want || acc != test.acc { 1005 t.Errorf("%s: got %s (%s); want %s (%s)", test.x, got, acc, test.want, test.acc) 1006 } 1007 } 1008 1009 // check that supplied *Int is used 1010 for _, f := range []string{"0", "1", "-1", "1234"} { 1011 x := makeFloat(f) 1012 i := new(Int) 1013 if res, _ := x.Int(i); res != i { 1014 t.Errorf("(%s).Int is not using supplied *Int", f) 1015 } 1016 } 1017 } 1018 1019 func TestFloatRat(t *testing.T) { 1020 for _, test := range []struct { 1021 x, want string 1022 acc Accuracy 1023 }{ 1024 {"0", "0/1", Exact}, 1025 {"+0", "0/1", Exact}, 1026 {"-0", "0/1", Exact}, 1027 {"Inf", "nil", Below}, 1028 {"+Inf", "nil", Below}, 1029 {"-Inf", "nil", Above}, 1030 {"1", "1/1", Exact}, 1031 {"-1", "-1/1", Exact}, 1032 {"1.25", "5/4", Exact}, 1033 {"-1.25", "-5/4", Exact}, 1034 {"1e10", "10000000000/1", Exact}, 1035 {"1p10", "1024/1", Exact}, 1036 {"-1p-10", "-1/1024", Exact}, 1037 {"3.14159265", "7244019449799623199/2305843009213693952", Exact}, 1038 } { 1039 x := makeFloat(test.x).SetPrec(64) 1040 res, acc := x.Rat(nil) 1041 got := "nil" 1042 if res != nil { 1043 got = res.String() 1044 } 1045 if got != test.want { 1046 t.Errorf("%s: got %s; want %s", test.x, got, test.want) 1047 continue 1048 } 1049 if acc != test.acc { 1050 t.Errorf("%s: got %s; want %s", test.x, acc, test.acc) 1051 continue 1052 } 1053 1054 // inverse conversion 1055 if res != nil { 1056 got := new(Float).SetPrec(64).SetRat(res) 1057 if got.Cmp(x) != 0 { 1058 t.Errorf("%s: got %s; want %s", test.x, got, x) 1059 } 1060 } 1061 } 1062 1063 // check that supplied *Rat is used 1064 for _, f := range []string{"0", "1", "-1", "1234"} { 1065 x := makeFloat(f) 1066 r := new(Rat) 1067 if res, _ := x.Rat(r); res != r { 1068 t.Errorf("(%s).Rat is not using supplied *Rat", f) 1069 } 1070 } 1071 } 1072 1073 func TestFloatAbs(t *testing.T) { 1074 for _, test := range []string{ 1075 "0", 1076 "1", 1077 "1234", 1078 "1.23e-2", 1079 "1e-1000", 1080 "1e1000", 1081 "Inf", 1082 } { 1083 p := makeFloat(test) 1084 a := new(Float).Abs(p) 1085 if !alike(a, p) { 1086 t.Errorf("%s: got %s; want %s", test, a.Text('g', 10), test) 1087 } 1088 1089 n := makeFloat("-" + test) 1090 a.Abs(n) 1091 if !alike(a, p) { 1092 t.Errorf("-%s: got %s; want %s", test, a.Text('g', 10), test) 1093 } 1094 } 1095 } 1096 1097 func TestFloatNeg(t *testing.T) { 1098 for _, test := range []string{ 1099 "0", 1100 "1", 1101 "1234", 1102 "1.23e-2", 1103 "1e-1000", 1104 "1e1000", 1105 "Inf", 1106 } { 1107 p1 := makeFloat(test) 1108 n1 := makeFloat("-" + test) 1109 n2 := new(Float).Neg(p1) 1110 p2 := new(Float).Neg(n2) 1111 if !alike(n2, n1) { 1112 t.Errorf("%s: got %s; want %s", test, n2.Text('g', 10), n1.Text('g', 10)) 1113 } 1114 if !alike(p2, p1) { 1115 t.Errorf("%s: got %s; want %s", test, p2.Text('g', 10), p1.Text('g', 10)) 1116 } 1117 } 1118 } 1119 1120 func TestFloatInc(t *testing.T) { 1121 const n = 10 1122 for _, prec := range precList { 1123 if 1<<prec < n { 1124 continue // prec must be large enough to hold all numbers from 0 to n 1125 } 1126 var x, one Float 1127 x.SetPrec(prec) 1128 one.SetInt64(1) 1129 for i := 0; i < n; i++ { 1130 x.Add(&x, &one) 1131 } 1132 if x.Cmp(new(Float).SetInt64(n)) != 0 { 1133 t.Errorf("prec = %d: got %s; want %d", prec, &x, n) 1134 } 1135 } 1136 } 1137 1138 // Selected precisions with which to run various tests. 1139 var precList = [...]uint{1, 2, 5, 8, 10, 16, 23, 24, 32, 50, 53, 64, 100, 128, 500, 511, 512, 513, 1000, 10000} 1140 1141 // Selected bits with which to run various tests. 1142 // Each entry is a list of bits representing a floating-point number (see fromBits). 1143 var bitsList = [...]Bits{ 1144 {}, // = 0 1145 {0}, // = 1 1146 {1}, // = 2 1147 {-1}, // = 1/2 1148 {10}, // = 2**10 == 1024 1149 {-10}, // = 2**-10 == 1/1024 1150 {100, 10, 1}, // = 2**100 + 2**10 + 2**1 1151 {0, -1, -2, -10}, 1152 // TODO(gri) add more test cases 1153 } 1154 1155 // TestFloatAdd tests Float.Add/Sub by comparing the result of a "manual" 1156 // addition/subtraction of arguments represented by Bits values with the 1157 // respective Float addition/subtraction for a variety of precisions 1158 // and rounding modes. 1159 func TestFloatAdd(t *testing.T) { 1160 for _, xbits := range bitsList { 1161 for _, ybits := range bitsList { 1162 // exact values 1163 x := xbits.Float() 1164 y := ybits.Float() 1165 zbits := xbits.add(ybits) 1166 z := zbits.Float() 1167 1168 for i, mode := range [...]RoundingMode{ToZero, ToNearestEven, AwayFromZero} { 1169 for _, prec := range precList { 1170 got := new(Float).SetPrec(prec).SetMode(mode) 1171 got.Add(x, y) 1172 want := zbits.round(prec, mode) 1173 if got.Cmp(want) != 0 { 1174 t.Errorf("i = %d, prec = %d, %s:\n\t %s %v\n\t+ %s %v\n\t= %s\n\twant %s", 1175 i, prec, mode, x, xbits, y, ybits, got, want) 1176 } 1177 1178 got.Sub(z, x) 1179 want = ybits.round(prec, mode) 1180 if got.Cmp(want) != 0 { 1181 t.Errorf("i = %d, prec = %d, %s:\n\t %s %v\n\t- %s %v\n\t= %s\n\twant %s", 1182 i, prec, mode, z, zbits, x, xbits, got, want) 1183 } 1184 } 1185 } 1186 } 1187 } 1188 } 1189 1190 // TestFloatAdd32 tests that Float.Add/Sub of numbers with 1191 // 24bit mantissa behaves like float32 addition/subtraction 1192 // (excluding denormal numbers). 1193 func TestFloatAdd32(t *testing.T) { 1194 // chose base such that we cross the mantissa precision limit 1195 const base = 1<<26 - 0x10 // 11...110000 (26 bits) 1196 for d := 0; d <= 0x10; d++ { 1197 for i := range [2]int{} { 1198 x0, y0 := float64(base), float64(d) 1199 if i&1 != 0 { 1200 x0, y0 = y0, x0 1201 } 1202 1203 x := NewFloat(x0) 1204 y := NewFloat(y0) 1205 z := new(Float).SetPrec(24) 1206 1207 z.Add(x, y) 1208 got, acc := z.Float32() 1209 want := float32(y0) + float32(x0) 1210 if got != want || acc != Exact { 1211 t.Errorf("d = %d: %g + %g = %g (%s); want %g (Exact)", d, x0, y0, got, acc, want) 1212 } 1213 1214 z.Sub(z, y) 1215 got, acc = z.Float32() 1216 want = float32(want) - float32(y0) 1217 if got != want || acc != Exact { 1218 t.Errorf("d = %d: %g - %g = %g (%s); want %g (Exact)", d, x0+y0, y0, got, acc, want) 1219 } 1220 } 1221 } 1222 } 1223 1224 // TestFloatAdd64 tests that Float.Add/Sub of numbers with 1225 // 53bit mantissa behaves like float64 addition/subtraction. 1226 func TestFloatAdd64(t *testing.T) { 1227 // chose base such that we cross the mantissa precision limit 1228 const base = 1<<55 - 0x10 // 11...110000 (55 bits) 1229 for d := 0; d <= 0x10; d++ { 1230 for i := range [2]int{} { 1231 x0, y0 := float64(base), float64(d) 1232 if i&1 != 0 { 1233 x0, y0 = y0, x0 1234 } 1235 1236 x := NewFloat(x0) 1237 y := NewFloat(y0) 1238 z := new(Float).SetPrec(53) 1239 1240 z.Add(x, y) 1241 got, acc := z.Float64() 1242 want := x0 + y0 1243 if got != want || acc != Exact { 1244 t.Errorf("d = %d: %g + %g = %g (%s); want %g (Exact)", d, x0, y0, got, acc, want) 1245 } 1246 1247 z.Sub(z, y) 1248 got, acc = z.Float64() 1249 want -= y0 1250 if got != want || acc != Exact { 1251 t.Errorf("d = %d: %g - %g = %g (%s); want %g (Exact)", d, x0+y0, y0, got, acc, want) 1252 } 1253 } 1254 } 1255 } 1256 1257 // TestFloatMul tests Float.Mul/Quo by comparing the result of a "manual" 1258 // multiplication/division of arguments represented by Bits values with the 1259 // respective Float multiplication/division for a variety of precisions 1260 // and rounding modes. 1261 func TestFloatMul(t *testing.T) { 1262 for _, xbits := range bitsList { 1263 for _, ybits := range bitsList { 1264 // exact values 1265 x := xbits.Float() 1266 y := ybits.Float() 1267 zbits := xbits.mul(ybits) 1268 z := zbits.Float() 1269 1270 for i, mode := range [...]RoundingMode{ToZero, ToNearestEven, AwayFromZero} { 1271 for _, prec := range precList { 1272 got := new(Float).SetPrec(prec).SetMode(mode) 1273 got.Mul(x, y) 1274 want := zbits.round(prec, mode) 1275 if got.Cmp(want) != 0 { 1276 t.Errorf("i = %d, prec = %d, %s:\n\t %s %v\n\t* %s %v\n\t= %s\n\twant %s", 1277 i, prec, mode, x, xbits, y, ybits, got, want) 1278 } 1279 1280 if x.Sign() == 0 { 1281 continue // ignore div-0 case (not invertable) 1282 } 1283 got.Quo(z, x) 1284 want = ybits.round(prec, mode) 1285 if got.Cmp(want) != 0 { 1286 t.Errorf("i = %d, prec = %d, %s:\n\t %s %v\n\t/ %s %v\n\t= %s\n\twant %s", 1287 i, prec, mode, z, zbits, x, xbits, got, want) 1288 } 1289 } 1290 } 1291 } 1292 } 1293 } 1294 1295 // TestFloatMul64 tests that Float.Mul/Quo of numbers with 1296 // 53bit mantissa behaves like float64 multiplication/division. 1297 func TestFloatMul64(t *testing.T) { 1298 for _, test := range []struct { 1299 x, y float64 1300 }{ 1301 {0, 0}, 1302 {0, 1}, 1303 {1, 1}, 1304 {1, 1.5}, 1305 {1.234, 0.5678}, 1306 {2.718281828, 3.14159265358979}, 1307 {2.718281828e10, 3.14159265358979e-32}, 1308 {1.0 / 3, 1e200}, 1309 } { 1310 for i := range [8]int{} { 1311 x0, y0 := test.x, test.y 1312 if i&1 != 0 { 1313 x0 = -x0 1314 } 1315 if i&2 != 0 { 1316 y0 = -y0 1317 } 1318 if i&4 != 0 { 1319 x0, y0 = y0, x0 1320 } 1321 1322 x := NewFloat(x0) 1323 y := NewFloat(y0) 1324 z := new(Float).SetPrec(53) 1325 1326 z.Mul(x, y) 1327 got, _ := z.Float64() 1328 want := x0 * y0 1329 if got != want { 1330 t.Errorf("%g * %g = %g; want %g", x0, y0, got, want) 1331 } 1332 1333 if y0 == 0 { 1334 continue // avoid division-by-zero 1335 } 1336 z.Quo(z, y) 1337 got, _ = z.Float64() 1338 want /= y0 1339 if got != want { 1340 t.Errorf("%g / %g = %g; want %g", x0*y0, y0, got, want) 1341 } 1342 } 1343 } 1344 } 1345 1346 func TestIssue6866(t *testing.T) { 1347 for _, prec := range precList { 1348 two := new(Float).SetPrec(prec).SetInt64(2) 1349 one := new(Float).SetPrec(prec).SetInt64(1) 1350 three := new(Float).SetPrec(prec).SetInt64(3) 1351 msix := new(Float).SetPrec(prec).SetInt64(-6) 1352 psix := new(Float).SetPrec(prec).SetInt64(+6) 1353 1354 p := new(Float).SetPrec(prec) 1355 z1 := new(Float).SetPrec(prec) 1356 z2 := new(Float).SetPrec(prec) 1357 1358 // z1 = 2 + 1.0/3*-6 1359 p.Quo(one, three) 1360 p.Mul(p, msix) 1361 z1.Add(two, p) 1362 1363 // z2 = 2 - 1.0/3*+6 1364 p.Quo(one, three) 1365 p.Mul(p, psix) 1366 z2.Sub(two, p) 1367 1368 if z1.Cmp(z2) != 0 { 1369 t.Fatalf("prec %d: got z1 = %s != z2 = %s; want z1 == z2\n", prec, z1, z2) 1370 } 1371 if z1.Sign() != 0 { 1372 t.Errorf("prec %d: got z1 = %s; want 0", prec, z1) 1373 } 1374 if z2.Sign() != 0 { 1375 t.Errorf("prec %d: got z2 = %s; want 0", prec, z2) 1376 } 1377 } 1378 } 1379 1380 func TestFloatQuo(t *testing.T) { 1381 // TODO(gri) make the test vary these precisions 1382 preci := 200 // precision of integer part 1383 precf := 20 // precision of fractional part 1384 1385 for i := 0; i < 8; i++ { 1386 // compute accurate (not rounded) result z 1387 bits := Bits{preci - 1} 1388 if i&3 != 0 { 1389 bits = append(bits, 0) 1390 } 1391 if i&2 != 0 { 1392 bits = append(bits, -1) 1393 } 1394 if i&1 != 0 { 1395 bits = append(bits, -precf) 1396 } 1397 z := bits.Float() 1398 1399 // compute accurate x as z*y 1400 y := NewFloat(3.14159265358979323e123) 1401 1402 x := new(Float).SetPrec(z.Prec() + y.Prec()).SetMode(ToZero) 1403 x.Mul(z, y) 1404 1405 // leave for debugging 1406 // fmt.Printf("x = %s\ny = %s\nz = %s\n", x, y, z) 1407 1408 if got := x.Acc(); got != Exact { 1409 t.Errorf("got acc = %s; want exact", got) 1410 } 1411 1412 // round accurate z for a variety of precisions and 1413 // modes and compare against result of x / y. 1414 for _, mode := range [...]RoundingMode{ToZero, ToNearestEven, AwayFromZero} { 1415 for d := -5; d < 5; d++ { 1416 prec := uint(preci + d) 1417 got := new(Float).SetPrec(prec).SetMode(mode).Quo(x, y) 1418 want := bits.round(prec, mode) 1419 if got.Cmp(want) != 0 { 1420 t.Errorf("i = %d, prec = %d, %s:\n\t %s\n\t/ %s\n\t= %s\n\twant %s", 1421 i, prec, mode, x, y, got, want) 1422 } 1423 } 1424 } 1425 } 1426 } 1427 1428 // TestFloatQuoSmoke tests all divisions x/y for values x, y in the range [-n, +n]; 1429 // it serves as a smoke test for basic correctness of division. 1430 func TestFloatQuoSmoke(t *testing.T) { 1431 n := 1000 1432 if testing.Short() { 1433 n = 10 1434 } 1435 1436 const dprec = 3 // max. precision variation 1437 const prec = 10 + dprec // enough bits to hold n precisely 1438 for x := -n; x <= n; x++ { 1439 for y := -n; y < n; y++ { 1440 if y == 0 { 1441 continue 1442 } 1443 1444 a := float64(x) 1445 b := float64(y) 1446 c := a / b 1447 1448 // vary operand precision (only ok as long as a, b can be represented correctly) 1449 for ad := -dprec; ad <= dprec; ad++ { 1450 for bd := -dprec; bd <= dprec; bd++ { 1451 A := new(Float).SetPrec(uint(prec + ad)).SetFloat64(a) 1452 B := new(Float).SetPrec(uint(prec + bd)).SetFloat64(b) 1453 C := new(Float).SetPrec(53).Quo(A, B) // C has float64 mantissa width 1454 1455 cc, acc := C.Float64() 1456 if cc != c { 1457 t.Errorf("%g/%g = %s; want %.5g\n", a, b, C.Text('g', 5), c) 1458 continue 1459 } 1460 if acc != Exact { 1461 t.Errorf("%g/%g got %s result; want exact result", a, b, acc) 1462 } 1463 } 1464 } 1465 } 1466 } 1467 } 1468 1469 // TestFloatArithmeticSpecialValues tests that Float operations produce the 1470 // correct results for combinations of zero (±0), finite (±1 and ±2.71828), 1471 // and infinite (±Inf) operands. 1472 func TestFloatArithmeticSpecialValues(t *testing.T) { 1473 zero := 0.0 1474 args := []float64{math.Inf(-1), -2.71828, -1, -zero, zero, 1, 2.71828, math.Inf(1)} 1475 xx := new(Float) 1476 yy := new(Float) 1477 got := new(Float) 1478 want := new(Float) 1479 for i := 0; i < 4; i++ { 1480 for _, x := range args { 1481 xx.SetFloat64(x) 1482 // check conversion is correct 1483 // (no need to do this for y, since we see exactly the 1484 // same values there) 1485 if got, acc := xx.Float64(); got != x || acc != Exact { 1486 t.Errorf("Float(%g) == %g (%s)", x, got, acc) 1487 } 1488 for _, y := range args { 1489 yy.SetFloat64(y) 1490 var ( 1491 op string 1492 z float64 1493 f func(z, x, y *Float) *Float 1494 ) 1495 switch i { 1496 case 0: 1497 op = "+" 1498 z = x + y 1499 f = (*Float).Add 1500 case 1: 1501 op = "-" 1502 z = x - y 1503 f = (*Float).Sub 1504 case 2: 1505 op = "*" 1506 z = x * y 1507 f = (*Float).Mul 1508 case 3: 1509 op = "/" 1510 z = x / y 1511 f = (*Float).Quo 1512 default: 1513 panic("unreachable") 1514 } 1515 var errnan bool // set if execution of f panicked with ErrNaN 1516 // protect execution of f 1517 func() { 1518 defer func() { 1519 if p := recover(); p != nil { 1520 _ = p.(ErrNaN) // re-panic if not ErrNaN 1521 errnan = true 1522 } 1523 }() 1524 f(got, xx, yy) 1525 }() 1526 if math.IsNaN(z) { 1527 if !errnan { 1528 t.Errorf("%5g %s %5g = %5s; want ErrNaN panic", x, op, y, got) 1529 } 1530 continue 1531 } 1532 if errnan { 1533 t.Errorf("%5g %s %5g panicked with ErrNan; want %5s", x, op, y, want) 1534 continue 1535 } 1536 want.SetFloat64(z) 1537 if !alike(got, want) { 1538 t.Errorf("%5g %s %5g = %5s; want %5s", x, op, y, got, want) 1539 } 1540 } 1541 } 1542 } 1543 } 1544 1545 func TestFloatArithmeticOverflow(t *testing.T) { 1546 for _, test := range []struct { 1547 prec uint 1548 mode RoundingMode 1549 op byte 1550 x, y, want string 1551 acc Accuracy 1552 }{ 1553 {4, ToNearestEven, '+', "0", "0", "0", Exact}, // smoke test 1554 {4, ToNearestEven, '+', "0x.8p+0", "0x.8p+0", "0x.8p+1", Exact}, // smoke test 1555 1556 {4, ToNearestEven, '+', "0", "0x.8p2147483647", "0x.8p+2147483647", Exact}, 1557 {4, ToNearestEven, '+', "0x.8p2147483500", "0x.8p2147483647", "0x.8p+2147483647", Below}, // rounded to zero 1558 {4, ToNearestEven, '+', "0x.8p2147483647", "0x.8p2147483647", "+Inf", Above}, // exponent overflow in + 1559 {4, ToNearestEven, '+', "-0x.8p2147483647", "-0x.8p2147483647", "-Inf", Below}, // exponent overflow in + 1560 {4, ToNearestEven, '-', "-0x.8p2147483647", "0x.8p2147483647", "-Inf", Below}, // exponent overflow in - 1561 1562 {4, ToZero, '+', "0x.fp2147483647", "0x.8p2147483643", "0x.fp+2147483647", Below}, // rounded to zero 1563 {4, ToNearestEven, '+', "0x.fp2147483647", "0x.8p2147483643", "+Inf", Above}, // exponent overflow in rounding 1564 {4, AwayFromZero, '+', "0x.fp2147483647", "0x.8p2147483643", "+Inf", Above}, // exponent overflow in rounding 1565 1566 {4, AwayFromZero, '-', "-0x.fp2147483647", "0x.8p2147483644", "-Inf", Below}, // exponent overflow in rounding 1567 {4, ToNearestEven, '-', "-0x.fp2147483647", "0x.8p2147483643", "-Inf", Below}, // exponent overflow in rounding 1568 {4, ToZero, '-', "-0x.fp2147483647", "0x.8p2147483643", "-0x.fp+2147483647", Above}, // rounded to zero 1569 1570 {4, ToNearestEven, '+', "0", "0x.8p-2147483648", "0x.8p-2147483648", Exact}, 1571 {4, ToNearestEven, '+', "0x.8p-2147483648", "0x.8p-2147483648", "0x.8p-2147483647", Exact}, 1572 1573 {4, ToNearestEven, '*', "1", "0x.8p2147483647", "0x.8p+2147483647", Exact}, 1574 {4, ToNearestEven, '*', "2", "0x.8p2147483647", "+Inf", Above}, // exponent overflow in * 1575 {4, ToNearestEven, '*', "-2", "0x.8p2147483647", "-Inf", Below}, // exponent overflow in * 1576 1577 {4, ToNearestEven, '/', "0.5", "0x.8p2147483647", "0x.8p-2147483646", Exact}, 1578 {4, ToNearestEven, '/', "0x.8p+0", "0x.8p2147483647", "0x.8p-2147483646", Exact}, 1579 {4, ToNearestEven, '/', "0x.8p-1", "0x.8p2147483647", "0x.8p-2147483647", Exact}, 1580 {4, ToNearestEven, '/', "0x.8p-2", "0x.8p2147483647", "0x.8p-2147483648", Exact}, 1581 {4, ToNearestEven, '/', "0x.8p-3", "0x.8p2147483647", "0", Below}, // exponent underflow in / 1582 } { 1583 x := makeFloat(test.x) 1584 y := makeFloat(test.y) 1585 z := new(Float).SetPrec(test.prec).SetMode(test.mode) 1586 switch test.op { 1587 case '+': 1588 z.Add(x, y) 1589 case '-': 1590 z.Sub(x, y) 1591 case '*': 1592 z.Mul(x, y) 1593 case '/': 1594 z.Quo(x, y) 1595 default: 1596 panic("unreachable") 1597 } 1598 if got := z.Text('p', 0); got != test.want || z.Acc() != test.acc { 1599 t.Errorf( 1600 "prec = %d (%s): %s %c %s = %s (%s); want %s (%s)", 1601 test.prec, test.mode, x.Text('p', 0), test.op, y.Text('p', 0), got, z.Acc(), test.want, test.acc, 1602 ) 1603 } 1604 } 1605 } 1606 1607 // TODO(gri) Add tests that check correctness in the presence of aliasing. 1608 1609 // For rounding modes ToNegativeInf and ToPositiveInf, rounding is affected 1610 // by the sign of the value to be rounded. Test that rounding happens after 1611 // the sign of a result has been set. 1612 // This test uses specific values that are known to fail if rounding is 1613 // "factored" out before setting the result sign. 1614 func TestFloatArithmeticRounding(t *testing.T) { 1615 for _, test := range []struct { 1616 mode RoundingMode 1617 prec uint 1618 x, y, want int64 1619 op byte 1620 }{ 1621 {ToZero, 3, -0x8, -0x1, -0x8, '+'}, 1622 {AwayFromZero, 3, -0x8, -0x1, -0xa, '+'}, 1623 {ToNegativeInf, 3, -0x8, -0x1, -0xa, '+'}, 1624 1625 {ToZero, 3, -0x8, 0x1, -0x8, '-'}, 1626 {AwayFromZero, 3, -0x8, 0x1, -0xa, '-'}, 1627 {ToNegativeInf, 3, -0x8, 0x1, -0xa, '-'}, 1628 1629 {ToZero, 3, -0x9, 0x1, -0x8, '*'}, 1630 {AwayFromZero, 3, -0x9, 0x1, -0xa, '*'}, 1631 {ToNegativeInf, 3, -0x9, 0x1, -0xa, '*'}, 1632 1633 {ToZero, 3, -0x9, 0x1, -0x8, '/'}, 1634 {AwayFromZero, 3, -0x9, 0x1, -0xa, '/'}, 1635 {ToNegativeInf, 3, -0x9, 0x1, -0xa, '/'}, 1636 } { 1637 var x, y, z Float 1638 x.SetInt64(test.x) 1639 y.SetInt64(test.y) 1640 z.SetPrec(test.prec).SetMode(test.mode) 1641 switch test.op { 1642 case '+': 1643 z.Add(&x, &y) 1644 case '-': 1645 z.Sub(&x, &y) 1646 case '*': 1647 z.Mul(&x, &y) 1648 case '/': 1649 z.Quo(&x, &y) 1650 default: 1651 panic("unreachable") 1652 } 1653 if got, acc := z.Int64(); got != test.want || acc != Exact { 1654 t.Errorf("%s, %d bits: %d %c %d = %d (%s); want %d (Exact)", 1655 test.mode, test.prec, test.x, test.op, test.y, got, acc, test.want, 1656 ) 1657 } 1658 } 1659 } 1660 1661 // TestFloatCmpSpecialValues tests that Cmp produces the correct results for 1662 // combinations of zero (±0), finite (±1 and ±2.71828), and infinite (±Inf) 1663 // operands. 1664 func TestFloatCmpSpecialValues(t *testing.T) { 1665 zero := 0.0 1666 args := []float64{math.Inf(-1), -2.71828, -1, -zero, zero, 1, 2.71828, math.Inf(1)} 1667 xx := new(Float) 1668 yy := new(Float) 1669 for i := 0; i < 4; i++ { 1670 for _, x := range args { 1671 xx.SetFloat64(x) 1672 // check conversion is correct 1673 // (no need to do this for y, since we see exactly the 1674 // same values there) 1675 if got, acc := xx.Float64(); got != x || acc != Exact { 1676 t.Errorf("Float(%g) == %g (%s)", x, got, acc) 1677 } 1678 for _, y := range args { 1679 yy.SetFloat64(y) 1680 got := xx.Cmp(yy) 1681 want := 0 1682 switch { 1683 case x < y: 1684 want = -1 1685 case x > y: 1686 want = +1 1687 } 1688 if got != want { 1689 t.Errorf("(%g).Cmp(%g) = %v; want %v", x, y, got, want) 1690 } 1691 } 1692 } 1693 } 1694 }