github.com/rsc/tmp@v0.0.0-20240517235954-6deaab19748b/bootstrap/internal/gc/big/float_test.go (about) 1 // Do not edit. Bootstrap copy of /Users/rsc/g/go/src/cmd/internal/gc/big/float_test.go 2 3 // Copyright 2014 The Go Authors. All rights reserved. 4 // Use of this source code is governed by a BSD-style 5 // license that can be found in the LICENSE file. 6 7 package big 8 9 import ( 10 "fmt" 11 "math" 12 "strconv" 13 "strings" 14 "testing" 15 ) 16 17 func (x *Float) uint64() uint64 { 18 u, acc := x.Uint64() 19 if acc != Exact { 20 panic(fmt.Sprintf("%s is not a uint64", x.Format('g', 10))) 21 } 22 return u 23 } 24 25 func (x *Float) int64() int64 { 26 i, acc := x.Int64() 27 if acc != Exact { 28 panic(fmt.Sprintf("%s is not an int64", x.Format('g', 10))) 29 } 30 return i 31 } 32 33 func TestFloatZeroValue(t *testing.T) { 34 // zero (uninitialized) value is a ready-to-use 0.0 35 var x Float 36 if s := x.Format('f', 1); s != "0.0" { 37 t.Errorf("zero value = %s; want 0.0", s) 38 } 39 40 // zero value has precision 0 41 if prec := x.Prec(); prec != 0 { 42 t.Errorf("prec = %d; want 0", prec) 43 } 44 45 // zero value can be used in any and all positions of binary operations 46 make := func(x int) *Float { 47 var f Float 48 if x != 0 { 49 f.SetInt64(int64(x)) 50 } 51 // x == 0 translates into the zero value 52 return &f 53 } 54 for _, test := range []struct { 55 z, x, y, want int 56 opname rune 57 op func(z, x, y *Float) *Float 58 }{ 59 {0, 0, 0, 0, '+', (*Float).Add}, 60 {0, 1, 2, 3, '+', (*Float).Add}, 61 {1, 2, 0, 2, '+', (*Float).Add}, 62 {2, 0, 1, 1, '+', (*Float).Add}, 63 64 {0, 0, 0, 0, '-', (*Float).Sub}, 65 {0, 1, 2, -1, '-', (*Float).Sub}, 66 {1, 2, 0, 2, '-', (*Float).Sub}, 67 {2, 0, 1, -1, '-', (*Float).Sub}, 68 69 {0, 0, 0, 0, '*', (*Float).Mul}, 70 {0, 1, 2, 2, '*', (*Float).Mul}, 71 {1, 2, 0, 0, '*', (*Float).Mul}, 72 {2, 0, 1, 0, '*', (*Float).Mul}, 73 74 // {0, 0, 0, 0, '/', (*Float).Quo}, // panics 75 {0, 2, 1, 2, '/', (*Float).Quo}, 76 {1, 2, 0, 0, '/', (*Float).Quo}, // = +Inf 77 {2, 0, 1, 0, '/', (*Float).Quo}, 78 } { 79 z := make(test.z) 80 test.op(z, make(test.x), make(test.y)) 81 got := 0 82 if !z.IsInf() { 83 got = int(z.int64()) 84 } 85 if got != test.want { 86 t.Errorf("%d %c %d = %d; want %d", test.x, test.opname, test.y, got, test.want) 87 } 88 } 89 90 // TODO(gri) test how precision is set for zero value results 91 } 92 93 func makeFloat(s string) *Float { 94 var x Float 95 96 switch s { 97 case "0": 98 return &x 99 case "-0": 100 return x.Neg(&x) 101 case "Inf", "+Inf": 102 return x.SetInf(false) 103 case "-Inf": 104 return x.SetInf(true) 105 } 106 107 x.SetPrec(1000) 108 if _, ok := x.SetString(s); !ok { 109 panic(fmt.Sprintf("%q is not a valid float", s)) 110 } 111 return &x 112 } 113 114 func TestFloatSetPrec(t *testing.T) { 115 for _, test := range []struct { 116 x string 117 prec uint 118 want string 119 acc Accuracy 120 }{ 121 // prec 0 122 {"0", 0, "0", Exact}, 123 {"-0", 0, "-0", Exact}, 124 {"-Inf", 0, "-Inf", Exact}, 125 {"+Inf", 0, "+Inf", Exact}, 126 {"123", 0, "0", Below}, 127 {"-123", 0, "-0", Above}, 128 129 // prec at upper limit 130 {"0", MaxPrec, "0", Exact}, 131 {"-0", MaxPrec, "-0", Exact}, 132 {"-Inf", MaxPrec, "-Inf", Exact}, 133 {"+Inf", MaxPrec, "+Inf", Exact}, 134 135 // just a few regular cases - general rounding is tested elsewhere 136 {"1.5", 1, "2", Above}, 137 {"-1.5", 1, "-2", Below}, 138 {"123", 1e6, "123", Exact}, 139 {"-123", 1e6, "-123", Exact}, 140 } { 141 x := makeFloat(test.x).SetPrec(test.prec) 142 prec := test.prec 143 if prec > MaxPrec { 144 prec = MaxPrec 145 } 146 if got := x.Prec(); got != prec { 147 t.Errorf("%s.SetPrec(%d).Prec() == %d; want %d", test.x, test.prec, got, prec) 148 } 149 if got, acc := x.String(), x.Acc(); got != test.want || acc != test.acc { 150 t.Errorf("%s.SetPrec(%d) = %s (%s); want %s (%s)", test.x, test.prec, got, acc, test.want, test.acc) 151 } 152 } 153 } 154 155 func TestFloatMinPrec(t *testing.T) { 156 const max = 100 157 for _, test := range []struct { 158 x string 159 want uint 160 }{ 161 {"0", 0}, 162 {"-0", 0}, 163 {"+Inf", 0}, 164 {"-Inf", 0}, 165 {"1", 1}, 166 {"2", 1}, 167 {"3", 2}, 168 {"0x8001", 16}, 169 {"0x8001p-1000", 16}, 170 {"0x8001p+1000", 16}, 171 {"0.1", max}, 172 } { 173 x := makeFloat(test.x).SetPrec(max) 174 if got := x.MinPrec(); got != test.want { 175 t.Errorf("%s.MinPrec() = %d; want %d", test.x, got, test.want) 176 } 177 } 178 } 179 180 func TestFloatSign(t *testing.T) { 181 for _, test := range []struct { 182 x string 183 s int 184 }{ 185 {"-Inf", -1}, 186 {"-1", -1}, 187 {"-0", 0}, 188 {"+0", 0}, 189 {"+1", +1}, 190 {"+Inf", +1}, 191 } { 192 x := makeFloat(test.x) 193 s := x.Sign() 194 if s != test.s { 195 t.Errorf("%s.Sign() = %d; want %d", test.x, s, test.s) 196 } 197 } 198 } 199 200 // alike(x, y) is like x.Cmp(y) == 0 but also considers the sign of 0 (0 != -0). 201 func alike(x, y *Float) bool { 202 return x.Cmp(y) == 0 && x.Signbit() == y.Signbit() 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.Format('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.Format('g', 10), want.Format('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.Format('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.Format('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.Format('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.Format('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.Format('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.Format('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.Format('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.Format('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.Format('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.Format('g', 100) 687 if got != want { 688 t.Errorf("got %s (%s); want %s", got, f.Format('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.Format('g', 100) 729 if got != want { 730 t.Errorf("got %s (%s); want %s", got, f2.Format('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 {"-Inf", float32(math.Inf(-1)), Exact}, 831 {"-0x1.ffffff0p2147483646", float32(-math.Inf(+1)), Below}, // overflow in rounding 832 {"-1e10000", float32(math.Inf(-1)), Below}, // overflow 833 {"-0x1p128", float32(math.Inf(-1)), Below}, // overflow 834 {"-0x1.ffffff0p127", float32(-math.Inf(+1)), Below}, // overflow 835 {"-0x1.fffffe8p127", -math.MaxFloat32, Above}, 836 {"-0x1.fffffe0p127", -math.MaxFloat32, Exact}, 837 {"-12345.000000000000000000001", -12345, Above}, 838 {"-12345.0", -12345, Exact}, 839 {"-1.000000000000000000001", -1, Above}, 840 {"-1", -1, Exact}, 841 {"-0x0.000002p-126", -math.SmallestNonzeroFloat32, Exact}, 842 {"-0x0.000002p-127", -0, Above}, // underflow 843 {"-1e-1000", -0, Above}, // underflow 844 {"0", 0, Exact}, 845 {"1e-1000", 0, Below}, // underflow 846 {"0x0.000002p-127", 0, Below}, // underflow 847 {"0x0.000002p-126", math.SmallestNonzeroFloat32, Exact}, 848 {"1", 1, Exact}, 849 {"1.000000000000000000001", 1, Below}, 850 {"12345.0", 12345, Exact}, 851 {"12345.000000000000000000001", 12345, Below}, 852 {"0x1.fffffe0p127", math.MaxFloat32, Exact}, 853 {"0x1.fffffe8p127", math.MaxFloat32, Below}, 854 {"0x1.ffffff0p127", float32(math.Inf(+1)), Above}, // overflow 855 {"0x1p128", float32(math.Inf(+1)), Above}, // overflow 856 {"1e10000", float32(math.Inf(+1)), Above}, // overflow 857 {"0x1.ffffff0p2147483646", float32(math.Inf(+1)), Above}, // overflow in rounding 858 {"+Inf", float32(math.Inf(+1)), Exact}, 859 } { 860 // conversion should match strconv where syntax is agreeable 861 if f, err := strconv.ParseFloat(test.x, 32); err == nil && float32(f) != test.out { 862 t.Errorf("%s: got %g; want %g (incorrect test data)", test.x, f, test.out) 863 } 864 865 x := makeFloat(test.x) 866 out, acc := x.Float32() 867 if out != test.out || acc != test.acc { 868 t.Errorf("%s: got %g (%#x, %s); want %g (%#x, %s)", test.x, out, math.Float32bits(out), acc, test.out, math.Float32bits(test.out), test.acc) 869 } 870 871 // test that x.SetFloat64(float64(f)).Float32() == f 872 var x2 Float 873 out2, acc2 := x2.SetFloat64(float64(out)).Float32() 874 if out2 != out || acc2 != Exact { 875 t.Errorf("idempotency test: got %g (%s); want %g (Exact)", out2, acc2, out) 876 } 877 } 878 } 879 880 func TestFloatFloat64(t *testing.T) { 881 const smallestNormalFloat64 = 2.2250738585072014e-308 // 1p-1022 882 for _, test := range []struct { 883 x string 884 out float64 885 acc Accuracy 886 }{ 887 {"-Inf", math.Inf(-1), Exact}, 888 {"-0x1.fffffffffffff8p2147483646", -math.Inf(+1), Below}, // overflow in rounding 889 {"-1e10000", math.Inf(-1), Below}, // overflow 890 {"-0x1p1024", math.Inf(-1), Below}, // overflow 891 {"-0x1.fffffffffffff8p1023", -math.Inf(+1), Below}, // overflow 892 {"-0x1.fffffffffffff4p1023", -math.MaxFloat64, Above}, 893 {"-0x1.fffffffffffff0p1023", -math.MaxFloat64, Exact}, 894 {"-12345.000000000000000000001", -12345, Above}, 895 {"-12345.0", -12345, Exact}, 896 {"-1.000000000000000000001", -1, Above}, 897 {"-1", -1, Exact}, 898 {"-0x0.0000000000001p-1022", -math.SmallestNonzeroFloat64, Exact}, 899 {"-0x0.0000000000001p-1023", -0, Above}, // underflow 900 {"-1e-1000", -0, Above}, // underflow 901 {"0", 0, Exact}, 902 {"1e-1000", 0, Below}, // underflow 903 {"0x0.0000000000001p-1023", 0, Below}, // underflow 904 {"0x0.0000000000001p-1022", math.SmallestNonzeroFloat64, Exact}, 905 {"1", 1, Exact}, 906 {"1.000000000000000000001", 1, Below}, 907 {"12345.0", 12345, Exact}, 908 {"12345.000000000000000000001", 12345, Below}, 909 {"0x1.fffffffffffff0p1023", math.MaxFloat64, Exact}, 910 {"0x1.fffffffffffff4p1023", math.MaxFloat64, Below}, 911 {"0x1.fffffffffffff8p1023", math.Inf(+1), Above}, // overflow 912 {"0x1p1024", math.Inf(+1), Above}, // overflow 913 {"1e10000", math.Inf(+1), Above}, // overflow 914 {"0x1.fffffffffffff8p2147483646", math.Inf(+1), Above}, // overflow in rounding 915 {"+Inf", math.Inf(+1), Exact}, 916 917 // selected denormalized values that were handled incorrectly in the past 918 {"0x.fffffffffffffp-1022", smallestNormalFloat64 - math.SmallestNonzeroFloat64, Exact}, 919 {"4503599627370495p-1074", smallestNormalFloat64 - math.SmallestNonzeroFloat64, Exact}, 920 921 // http://www.exploringbinary.com/php-hangs-on-numeric-value-2-2250738585072011e-308/ 922 {"2.2250738585072011e-308", 2.225073858507201e-308, Below}, 923 // http://www.exploringbinary.com/java-hangs-when-converting-2-2250738585072012e-308/ 924 {"2.2250738585072012e-308", 2.2250738585072014e-308, Above}, 925 } { 926 // conversion should match strconv where syntax is agreeable 927 if f, err := strconv.ParseFloat(test.x, 64); err == nil && f != test.out { 928 t.Errorf("%s: got %g; want %g (incorrect test data)", test.x, f, test.out) 929 } 930 931 x := makeFloat(test.x) 932 out, acc := x.Float64() 933 if out != test.out || acc != test.acc { 934 t.Errorf("%s: got %g (%#x, %s); want %g (%#x, %s)", test.x, out, math.Float64bits(out), acc, test.out, math.Float64bits(test.out), test.acc) 935 } 936 937 // test that x.SetFloat64(f).Float64() == f 938 var x2 Float 939 out2, acc2 := x2.SetFloat64(out).Float64() 940 if out2 != out || acc2 != Exact { 941 t.Errorf("idempotency test: got %g (%s); want %g (Exact)", out2, acc2, out) 942 } 943 } 944 } 945 946 func TestFloatInt(t *testing.T) { 947 for _, test := range []struct { 948 x string 949 want string 950 acc Accuracy 951 }{ 952 {"0", "0", Exact}, 953 {"+0", "0", Exact}, 954 {"-0", "0", Exact}, 955 {"Inf", "nil", Below}, 956 {"+Inf", "nil", Below}, 957 {"-Inf", "nil", Above}, 958 {"1", "1", Exact}, 959 {"-1", "-1", Exact}, 960 {"1.23", "1", Below}, 961 {"-1.23", "-1", Above}, 962 {"123e-2", "1", Below}, 963 {"123e-3", "0", Below}, 964 {"123e-4", "0", Below}, 965 {"1e-1000", "0", Below}, 966 {"-1e-1000", "0", Above}, 967 {"1e+10", "10000000000", Exact}, 968 {"1e+100", "10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", Exact}, 969 } { 970 x := makeFloat(test.x) 971 res, acc := x.Int(nil) 972 got := "nil" 973 if res != nil { 974 got = res.String() 975 } 976 if got != test.want || acc != test.acc { 977 t.Errorf("%s: got %s (%s); want %s (%s)", test.x, got, acc, test.want, test.acc) 978 } 979 } 980 981 // check that supplied *Int is used 982 for _, f := range []string{"0", "1", "-1", "1234"} { 983 x := makeFloat(f) 984 i := new(Int) 985 if res, _ := x.Int(i); res != i { 986 t.Errorf("(%s).Int is not using supplied *Int", f) 987 } 988 } 989 } 990 991 func TestFloatRat(t *testing.T) { 992 for _, test := range []struct { 993 x, want string 994 acc Accuracy 995 }{ 996 {"0", "0/1", Exact}, 997 {"+0", "0/1", Exact}, 998 {"-0", "0/1", Exact}, 999 {"Inf", "nil", Below}, 1000 {"+Inf", "nil", Below}, 1001 {"-Inf", "nil", Above}, 1002 {"1", "1/1", Exact}, 1003 {"-1", "-1/1", Exact}, 1004 {"1.25", "5/4", Exact}, 1005 {"-1.25", "-5/4", Exact}, 1006 {"1e10", "10000000000/1", Exact}, 1007 {"1p10", "1024/1", Exact}, 1008 {"-1p-10", "-1/1024", Exact}, 1009 {"3.14159265", "7244019449799623199/2305843009213693952", Exact}, 1010 } { 1011 x := makeFloat(test.x).SetPrec(64) 1012 res, acc := x.Rat(nil) 1013 got := "nil" 1014 if res != nil { 1015 got = res.String() 1016 } 1017 if got != test.want { 1018 t.Errorf("%s: got %s; want %s", test.x, got, test.want) 1019 continue 1020 } 1021 if acc != test.acc { 1022 t.Errorf("%s: got %s; want %s", test.x, acc, test.acc) 1023 continue 1024 } 1025 1026 // inverse conversion 1027 if res != nil { 1028 got := new(Float).SetPrec(64).SetRat(res) 1029 if got.Cmp(x) != 0 { 1030 t.Errorf("%s: got %s; want %s", test.x, got, x) 1031 } 1032 } 1033 } 1034 1035 // check that supplied *Rat is used 1036 for _, f := range []string{"0", "1", "-1", "1234"} { 1037 x := makeFloat(f) 1038 r := new(Rat) 1039 if res, _ := x.Rat(r); res != r { 1040 t.Errorf("(%s).Rat is not using supplied *Rat", f) 1041 } 1042 } 1043 } 1044 1045 func TestFloatAbs(t *testing.T) { 1046 for _, test := range []string{ 1047 "0", 1048 "1", 1049 "1234", 1050 "1.23e-2", 1051 "1e-1000", 1052 "1e1000", 1053 "Inf", 1054 } { 1055 p := makeFloat(test) 1056 a := new(Float).Abs(p) 1057 if !alike(a, p) { 1058 t.Errorf("%s: got %s; want %s", test, a.Format('g', 10), test) 1059 } 1060 1061 n := makeFloat("-" + test) 1062 a.Abs(n) 1063 if !alike(a, p) { 1064 t.Errorf("-%s: got %s; want %s", test, a.Format('g', 10), test) 1065 } 1066 } 1067 } 1068 1069 func TestFloatNeg(t *testing.T) { 1070 for _, test := range []string{ 1071 "0", 1072 "1", 1073 "1234", 1074 "1.23e-2", 1075 "1e-1000", 1076 "1e1000", 1077 "Inf", 1078 } { 1079 p1 := makeFloat(test) 1080 n1 := makeFloat("-" + test) 1081 n2 := new(Float).Neg(p1) 1082 p2 := new(Float).Neg(n2) 1083 if !alike(n2, n1) { 1084 t.Errorf("%s: got %s; want %s", test, n2.Format('g', 10), n1.Format('g', 10)) 1085 } 1086 if !alike(p2, p1) { 1087 t.Errorf("%s: got %s; want %s", test, p2.Format('g', 10), p1.Format('g', 10)) 1088 } 1089 } 1090 } 1091 1092 func TestFloatInc(t *testing.T) { 1093 const n = 10 1094 for _, prec := range precList { 1095 if 1<<prec < n { 1096 continue // prec must be large enough to hold all numbers from 0 to n 1097 } 1098 var x, one Float 1099 x.SetPrec(prec) 1100 one.SetInt64(1) 1101 for i := 0; i < n; i++ { 1102 x.Add(&x, &one) 1103 } 1104 if x.Cmp(new(Float).SetInt64(n)) != 0 { 1105 t.Errorf("prec = %d: got %s; want %d", prec, &x, n) 1106 } 1107 } 1108 } 1109 1110 // Selected precisions with which to run various tests. 1111 var precList = [...]uint{1, 2, 5, 8, 10, 16, 23, 24, 32, 50, 53, 64, 100, 128, 500, 511, 512, 513, 1000, 10000} 1112 1113 // Selected bits with which to run various tests. 1114 // Each entry is a list of bits representing a floating-point number (see fromBits). 1115 var bitsList = [...]Bits{ 1116 {}, // = 0 1117 {0}, // = 1 1118 {1}, // = 2 1119 {-1}, // = 1/2 1120 {10}, // = 2**10 == 1024 1121 {-10}, // = 2**-10 == 1/1024 1122 {100, 10, 1}, // = 2**100 + 2**10 + 2**1 1123 {0, -1, -2, -10}, 1124 // TODO(gri) add more test cases 1125 } 1126 1127 // TestFloatAdd tests Float.Add/Sub by comparing the result of a "manual" 1128 // addition/subtraction of arguments represented by Bits values with the 1129 // respective Float addition/subtraction for a variety of precisions 1130 // and rounding modes. 1131 func TestFloatAdd(t *testing.T) { 1132 for _, xbits := range bitsList { 1133 for _, ybits := range bitsList { 1134 // exact values 1135 x := xbits.Float() 1136 y := ybits.Float() 1137 zbits := xbits.add(ybits) 1138 z := zbits.Float() 1139 1140 for i, mode := range [...]RoundingMode{ToZero, ToNearestEven, AwayFromZero} { 1141 for _, prec := range precList { 1142 got := new(Float).SetPrec(prec).SetMode(mode) 1143 got.Add(x, y) 1144 want := zbits.round(prec, mode) 1145 if got.Cmp(want) != 0 { 1146 t.Errorf("i = %d, prec = %d, %s:\n\t %s %v\n\t+ %s %v\n\t= %s\n\twant %s", 1147 i, prec, mode, x, xbits, y, ybits, got, want) 1148 } 1149 1150 got.Sub(z, x) 1151 want = ybits.round(prec, mode) 1152 if got.Cmp(want) != 0 { 1153 t.Errorf("i = %d, prec = %d, %s:\n\t %s %v\n\t- %s %v\n\t= %s\n\twant %s", 1154 i, prec, mode, z, zbits, x, xbits, got, want) 1155 } 1156 } 1157 } 1158 } 1159 } 1160 } 1161 1162 // TestFloatAdd32 tests that Float.Add/Sub of numbers with 1163 // 24bit mantissa behaves like float32 addition/subtraction 1164 // (excluding denormal numbers). 1165 func TestFloatAdd32(t *testing.T) { 1166 // chose base such that we cross the mantissa precision limit 1167 const base = 1<<26 - 0x10 // 11...110000 (26 bits) 1168 for d := 0; d <= 0x10; d++ { 1169 for i := range [2]int{} { 1170 x0, y0 := float64(base), float64(d) 1171 if i&1 != 0 { 1172 x0, y0 = y0, x0 1173 } 1174 1175 x := NewFloat(x0) 1176 y := NewFloat(y0) 1177 z := new(Float).SetPrec(24) 1178 1179 z.Add(x, y) 1180 got, acc := z.Float32() 1181 want := float32(y0) + float32(x0) 1182 if got != want || acc != Exact { 1183 t.Errorf("d = %d: %g + %g = %g (%s); want %g (Exact)", d, x0, y0, got, acc, want) 1184 } 1185 1186 z.Sub(z, y) 1187 got, acc = z.Float32() 1188 want = float32(want) - float32(y0) 1189 if got != want || acc != Exact { 1190 t.Errorf("d = %d: %g - %g = %g (%s); want %g (Exact)", d, x0+y0, y0, got, acc, want) 1191 } 1192 } 1193 } 1194 } 1195 1196 // TestFloatAdd64 tests that Float.Add/Sub of numbers with 1197 // 53bit mantissa behaves like float64 addition/subtraction. 1198 func TestFloatAdd64(t *testing.T) { 1199 // chose base such that we cross the mantissa precision limit 1200 const base = 1<<55 - 0x10 // 11...110000 (55 bits) 1201 for d := 0; d <= 0x10; d++ { 1202 for i := range [2]int{} { 1203 x0, y0 := float64(base), float64(d) 1204 if i&1 != 0 { 1205 x0, y0 = y0, x0 1206 } 1207 1208 x := NewFloat(x0) 1209 y := NewFloat(y0) 1210 z := new(Float).SetPrec(53) 1211 1212 z.Add(x, y) 1213 got, acc := z.Float64() 1214 want := x0 + y0 1215 if got != want || acc != Exact { 1216 t.Errorf("d = %d: %g + %g = %g (%s); want %g (Exact)", d, x0, y0, got, acc, want) 1217 } 1218 1219 z.Sub(z, y) 1220 got, acc = z.Float64() 1221 want -= y0 1222 if got != want || acc != Exact { 1223 t.Errorf("d = %d: %g - %g = %g (%s); want %g (Exact)", d, x0+y0, y0, got, acc, want) 1224 } 1225 } 1226 } 1227 } 1228 1229 // TestFloatMul tests Float.Mul/Quo by comparing the result of a "manual" 1230 // multiplication/division of arguments represented by Bits values with the 1231 // respective Float multiplication/division for a variety of precisions 1232 // and rounding modes. 1233 func TestFloatMul(t *testing.T) { 1234 for _, xbits := range bitsList { 1235 for _, ybits := range bitsList { 1236 // exact values 1237 x := xbits.Float() 1238 y := ybits.Float() 1239 zbits := xbits.mul(ybits) 1240 z := zbits.Float() 1241 1242 for i, mode := range [...]RoundingMode{ToZero, ToNearestEven, AwayFromZero} { 1243 for _, prec := range precList { 1244 got := new(Float).SetPrec(prec).SetMode(mode) 1245 got.Mul(x, y) 1246 want := zbits.round(prec, mode) 1247 if got.Cmp(want) != 0 { 1248 t.Errorf("i = %d, prec = %d, %s:\n\t %s %v\n\t* %s %v\n\t= %s\n\twant %s", 1249 i, prec, mode, x, xbits, y, ybits, got, want) 1250 } 1251 1252 if x.Sign() == 0 { 1253 continue // ignore div-0 case (not invertable) 1254 } 1255 got.Quo(z, x) 1256 want = ybits.round(prec, mode) 1257 if got.Cmp(want) != 0 { 1258 t.Errorf("i = %d, prec = %d, %s:\n\t %s %v\n\t/ %s %v\n\t= %s\n\twant %s", 1259 i, prec, mode, z, zbits, x, xbits, got, want) 1260 } 1261 } 1262 } 1263 } 1264 } 1265 } 1266 1267 // TestFloatMul64 tests that Float.Mul/Quo of numbers with 1268 // 53bit mantissa behaves like float64 multiplication/division. 1269 func TestFloatMul64(t *testing.T) { 1270 for _, test := range []struct { 1271 x, y float64 1272 }{ 1273 {0, 0}, 1274 {0, 1}, 1275 {1, 1}, 1276 {1, 1.5}, 1277 {1.234, 0.5678}, 1278 {2.718281828, 3.14159265358979}, 1279 {2.718281828e10, 3.14159265358979e-32}, 1280 {1.0 / 3, 1e200}, 1281 } { 1282 for i := range [8]int{} { 1283 x0, y0 := test.x, test.y 1284 if i&1 != 0 { 1285 x0 = -x0 1286 } 1287 if i&2 != 0 { 1288 y0 = -y0 1289 } 1290 if i&4 != 0 { 1291 x0, y0 = y0, x0 1292 } 1293 1294 x := NewFloat(x0) 1295 y := NewFloat(y0) 1296 z := new(Float).SetPrec(53) 1297 1298 z.Mul(x, y) 1299 got, _ := z.Float64() 1300 want := x0 * y0 1301 if got != want { 1302 t.Errorf("%g * %g = %g; want %g", x0, y0, got, want) 1303 } 1304 1305 if y0 == 0 { 1306 continue // avoid division-by-zero 1307 } 1308 z.Quo(z, y) 1309 got, _ = z.Float64() 1310 want /= y0 1311 if got != want { 1312 t.Errorf("%g / %g = %g; want %g", x0*y0, y0, got, want) 1313 } 1314 } 1315 } 1316 } 1317 1318 func TestIssue6866(t *testing.T) { 1319 for _, prec := range precList { 1320 two := new(Float).SetPrec(prec).SetInt64(2) 1321 one := new(Float).SetPrec(prec).SetInt64(1) 1322 three := new(Float).SetPrec(prec).SetInt64(3) 1323 msix := new(Float).SetPrec(prec).SetInt64(-6) 1324 psix := new(Float).SetPrec(prec).SetInt64(+6) 1325 1326 p := new(Float).SetPrec(prec) 1327 z1 := new(Float).SetPrec(prec) 1328 z2 := new(Float).SetPrec(prec) 1329 1330 // z1 = 2 + 1.0/3*-6 1331 p.Quo(one, three) 1332 p.Mul(p, msix) 1333 z1.Add(two, p) 1334 1335 // z2 = 2 - 1.0/3*+6 1336 p.Quo(one, three) 1337 p.Mul(p, psix) 1338 z2.Sub(two, p) 1339 1340 if z1.Cmp(z2) != 0 { 1341 t.Fatalf("prec %d: got z1 = %s != z2 = %s; want z1 == z2\n", prec, z1, z2) 1342 } 1343 if z1.Sign() != 0 { 1344 t.Errorf("prec %d: got z1 = %s; want 0", prec, z1) 1345 } 1346 if z2.Sign() != 0 { 1347 t.Errorf("prec %d: got z2 = %s; want 0", prec, z2) 1348 } 1349 } 1350 } 1351 1352 func TestFloatQuo(t *testing.T) { 1353 // TODO(gri) make the test vary these precisions 1354 preci := 200 // precision of integer part 1355 precf := 20 // precision of fractional part 1356 1357 for i := 0; i < 8; i++ { 1358 // compute accurate (not rounded) result z 1359 bits := Bits{preci - 1} 1360 if i&3 != 0 { 1361 bits = append(bits, 0) 1362 } 1363 if i&2 != 0 { 1364 bits = append(bits, -1) 1365 } 1366 if i&1 != 0 { 1367 bits = append(bits, -precf) 1368 } 1369 z := bits.Float() 1370 1371 // compute accurate x as z*y 1372 y := NewFloat(3.14159265358979323e123) 1373 1374 x := new(Float).SetPrec(z.Prec() + y.Prec()).SetMode(ToZero) 1375 x.Mul(z, y) 1376 1377 // leave for debugging 1378 // fmt.Printf("x = %s\ny = %s\nz = %s\n", x, y, z) 1379 1380 if got := x.Acc(); got != Exact { 1381 t.Errorf("got acc = %s; want exact", got) 1382 } 1383 1384 // round accurate z for a variety of precisions and 1385 // modes and compare against result of x / y. 1386 for _, mode := range [...]RoundingMode{ToZero, ToNearestEven, AwayFromZero} { 1387 for d := -5; d < 5; d++ { 1388 prec := uint(preci + d) 1389 got := new(Float).SetPrec(prec).SetMode(mode).Quo(x, y) 1390 want := bits.round(prec, mode) 1391 if got.Cmp(want) != 0 { 1392 t.Errorf("i = %d, prec = %d, %s:\n\t %s\n\t/ %s\n\t= %s\n\twant %s", 1393 i, prec, mode, x, y, got, want) 1394 } 1395 } 1396 } 1397 } 1398 } 1399 1400 // TestFloatQuoSmoke tests all divisions x/y for values x, y in the range [-n, +n]; 1401 // it serves as a smoke test for basic correctness of division. 1402 func TestFloatQuoSmoke(t *testing.T) { 1403 n := 1000 1404 if testing.Short() { 1405 n = 10 1406 } 1407 1408 const dprec = 3 // max. precision variation 1409 const prec = 10 + dprec // enough bits to hold n precisely 1410 for x := -n; x <= n; x++ { 1411 for y := -n; y < n; y++ { 1412 if y == 0 { 1413 continue 1414 } 1415 1416 a := float64(x) 1417 b := float64(y) 1418 c := a / b 1419 1420 // vary operand precision (only ok as long as a, b can be represented correctly) 1421 for ad := -dprec; ad <= dprec; ad++ { 1422 for bd := -dprec; bd <= dprec; bd++ { 1423 A := new(Float).SetPrec(uint(prec + ad)).SetFloat64(a) 1424 B := new(Float).SetPrec(uint(prec + bd)).SetFloat64(b) 1425 C := new(Float).SetPrec(53).Quo(A, B) // C has float64 mantissa width 1426 1427 cc, acc := C.Float64() 1428 if cc != c { 1429 t.Errorf("%g/%g = %s; want %.5g\n", a, b, C.Format('g', 5), c) 1430 continue 1431 } 1432 if acc != Exact { 1433 t.Errorf("%g/%g got %s result; want exact result", a, b, acc) 1434 } 1435 } 1436 } 1437 } 1438 } 1439 } 1440 1441 // TestFloatArithmeticSpecialValues tests that Float operations produce the 1442 // correct results for combinations of zero (±0), finite (±1 and ±2.71828), 1443 // and infinite (±Inf) operands. 1444 func TestFloatArithmeticSpecialValues(t *testing.T) { 1445 zero := 0.0 1446 args := []float64{math.Inf(-1), -2.71828, -1, -zero, zero, 1, 2.71828, math.Inf(1)} 1447 xx := new(Float) 1448 yy := new(Float) 1449 got := new(Float) 1450 want := new(Float) 1451 for i := 0; i < 4; i++ { 1452 for _, x := range args { 1453 xx.SetFloat64(x) 1454 // check conversion is correct 1455 // (no need to do this for y, since we see exactly the 1456 // same values there) 1457 if got, acc := xx.Float64(); got != x || acc != Exact { 1458 t.Errorf("Float(%g) == %g (%s)", x, got, acc) 1459 } 1460 for _, y := range args { 1461 yy.SetFloat64(y) 1462 var ( 1463 op string 1464 z float64 1465 f func(z, x, y *Float) *Float 1466 ) 1467 switch i { 1468 case 0: 1469 op = "+" 1470 z = x + y 1471 f = (*Float).Add 1472 case 1: 1473 op = "-" 1474 z = x - y 1475 f = (*Float).Sub 1476 case 2: 1477 op = "*" 1478 z = x * y 1479 f = (*Float).Mul 1480 case 3: 1481 op = "/" 1482 z = x / y 1483 f = (*Float).Quo 1484 default: 1485 panic("unreachable") 1486 } 1487 var errnan bool // set if execution of f panicked with ErrNaN 1488 // protect execution of f 1489 func() { 1490 defer func() { 1491 if p := recover(); p != nil { 1492 _ = p.(ErrNaN) // re-panic if not ErrNaN 1493 errnan = true 1494 } 1495 }() 1496 f(got, xx, yy) 1497 }() 1498 if math.IsNaN(z) { 1499 if !errnan { 1500 t.Errorf("%5g %s %5g = %5s; want ErrNaN panic", x, op, y, got) 1501 } 1502 continue 1503 } 1504 if errnan { 1505 t.Errorf("%5g %s %5g panicked with ErrNan; want %5s", x, op, y, want) 1506 continue 1507 } 1508 want.SetFloat64(z) 1509 if !alike(got, want) { 1510 t.Errorf("%5g %s %5g = %5s; want %5s", x, op, y, got, want) 1511 } 1512 } 1513 } 1514 } 1515 } 1516 1517 func TestFloatArithmeticOverflow(t *testing.T) { 1518 for _, test := range []struct { 1519 prec uint 1520 mode RoundingMode 1521 op byte 1522 x, y, want string 1523 acc Accuracy 1524 }{ 1525 {4, ToNearestEven, '+', "0", "0", "0", Exact}, // smoke test 1526 {4, ToNearestEven, '+', "0x.8p0", "0x.8p0", "0x.8p1", Exact}, // smoke test 1527 1528 {4, ToNearestEven, '+', "0", "0x.8p2147483647", "0x.8p2147483647", Exact}, 1529 {4, ToNearestEven, '+', "0x.8p2147483500", "0x.8p2147483647", "0x.8p2147483647", Below}, // rounded to zero 1530 {4, ToNearestEven, '+', "0x.8p2147483647", "0x.8p2147483647", "+Inf", Above}, // exponent overflow in + 1531 {4, ToNearestEven, '+', "-0x.8p2147483647", "-0x.8p2147483647", "-Inf", Below}, // exponent overflow in + 1532 {4, ToNearestEven, '-', "-0x.8p2147483647", "0x.8p2147483647", "-Inf", Below}, // exponent overflow in - 1533 1534 {4, ToZero, '+', "0x.fp2147483647", "0x.8p2147483643", "0x.fp2147483647", Below}, // rounded to zero 1535 {4, ToNearestEven, '+', "0x.fp2147483647", "0x.8p2147483643", "+Inf", Above}, // exponent overflow in rounding 1536 {4, AwayFromZero, '+', "0x.fp2147483647", "0x.8p2147483643", "+Inf", Above}, // exponent overflow in rounding 1537 1538 {4, AwayFromZero, '-', "-0x.fp2147483647", "0x.8p2147483644", "-Inf", Below}, // exponent overflow in rounding 1539 {4, ToNearestEven, '-', "-0x.fp2147483647", "0x.8p2147483643", "-Inf", Below}, // exponent overflow in rounding 1540 {4, ToZero, '-', "-0x.fp2147483647", "0x.8p2147483643", "-0x.fp2147483647", Above}, // rounded to zero 1541 1542 {4, ToNearestEven, '+', "0", "0x.8p-2147483648", "0x.8p-2147483648", Exact}, 1543 {4, ToNearestEven, '+', "0x.8p-2147483648", "0x.8p-2147483648", "0x.8p-2147483647", Exact}, 1544 1545 {4, ToNearestEven, '*', "1", "0x.8p2147483647", "0x.8p2147483647", Exact}, 1546 {4, ToNearestEven, '*', "2", "0x.8p2147483647", "+Inf", Above}, // exponent overflow in * 1547 {4, ToNearestEven, '*', "-2", "0x.8p2147483647", "-Inf", Below}, // exponent overflow in * 1548 1549 {4, ToNearestEven, '/', "0.5", "0x.8p2147483647", "0x.8p-2147483646", Exact}, 1550 {4, ToNearestEven, '/', "0x.8p0", "0x.8p2147483647", "0x.8p-2147483646", Exact}, 1551 {4, ToNearestEven, '/', "0x.8p-1", "0x.8p2147483647", "0x.8p-2147483647", Exact}, 1552 {4, ToNearestEven, '/', "0x.8p-2", "0x.8p2147483647", "0x.8p-2147483648", Exact}, 1553 {4, ToNearestEven, '/', "0x.8p-3", "0x.8p2147483647", "0", Below}, // exponent underflow in / 1554 } { 1555 x := makeFloat(test.x) 1556 y := makeFloat(test.y) 1557 z := new(Float).SetPrec(test.prec).SetMode(test.mode) 1558 switch test.op { 1559 case '+': 1560 z.Add(x, y) 1561 case '-': 1562 z.Sub(x, y) 1563 case '*': 1564 z.Mul(x, y) 1565 case '/': 1566 z.Quo(x, y) 1567 default: 1568 panic("unreachable") 1569 } 1570 if got := z.Format('p', 0); got != test.want || z.Acc() != test.acc { 1571 t.Errorf( 1572 "prec = %d (%s): %s %c %s = %s (%s); want %s (%s)", 1573 test.prec, test.mode, x.Format('p', 0), test.op, y.Format('p', 0), got, z.Acc(), test.want, test.acc, 1574 ) 1575 } 1576 } 1577 } 1578 1579 // TODO(gri) Add tests that check correctness in the presence of aliasing. 1580 1581 // For rounding modes ToNegativeInf and ToPositiveInf, rounding is affected 1582 // by the sign of the value to be rounded. Test that rounding happens after 1583 // the sign of a result has been set. 1584 // This test uses specific values that are known to fail if rounding is 1585 // "factored" out before setting the result sign. 1586 func TestFloatArithmeticRounding(t *testing.T) { 1587 for _, test := range []struct { 1588 mode RoundingMode 1589 prec uint 1590 x, y, want int64 1591 op byte 1592 }{ 1593 {ToZero, 3, -0x8, -0x1, -0x8, '+'}, 1594 {AwayFromZero, 3, -0x8, -0x1, -0xa, '+'}, 1595 {ToNegativeInf, 3, -0x8, -0x1, -0xa, '+'}, 1596 1597 {ToZero, 3, -0x8, 0x1, -0x8, '-'}, 1598 {AwayFromZero, 3, -0x8, 0x1, -0xa, '-'}, 1599 {ToNegativeInf, 3, -0x8, 0x1, -0xa, '-'}, 1600 1601 {ToZero, 3, -0x9, 0x1, -0x8, '*'}, 1602 {AwayFromZero, 3, -0x9, 0x1, -0xa, '*'}, 1603 {ToNegativeInf, 3, -0x9, 0x1, -0xa, '*'}, 1604 1605 {ToZero, 3, -0x9, 0x1, -0x8, '/'}, 1606 {AwayFromZero, 3, -0x9, 0x1, -0xa, '/'}, 1607 {ToNegativeInf, 3, -0x9, 0x1, -0xa, '/'}, 1608 } { 1609 var x, y, z Float 1610 x.SetInt64(test.x) 1611 y.SetInt64(test.y) 1612 z.SetPrec(test.prec).SetMode(test.mode) 1613 switch test.op { 1614 case '+': 1615 z.Add(&x, &y) 1616 case '-': 1617 z.Sub(&x, &y) 1618 case '*': 1619 z.Mul(&x, &y) 1620 case '/': 1621 z.Quo(&x, &y) 1622 default: 1623 panic("unreachable") 1624 } 1625 if got, acc := z.Int64(); got != test.want || acc != Exact { 1626 t.Errorf("%s, %d bits: %d %c %d = %d (%s); want %d (Exact)", 1627 test.mode, test.prec, test.x, test.op, test.y, got, acc, test.want, 1628 ) 1629 } 1630 } 1631 } 1632 1633 // TestFloatCmpSpecialValues tests that Cmp produces the correct results for 1634 // combinations of zero (±0), finite (±1 and ±2.71828), and infinite (±Inf) 1635 // operands. 1636 func TestFloatCmpSpecialValues(t *testing.T) { 1637 zero := 0.0 1638 args := []float64{math.Inf(-1), -2.71828, -1, -zero, zero, 1, 2.71828, math.Inf(1)} 1639 xx := new(Float) 1640 yy := new(Float) 1641 for i := 0; i < 4; i++ { 1642 for _, x := range args { 1643 xx.SetFloat64(x) 1644 // check conversion is correct 1645 // (no need to do this for y, since we see exactly the 1646 // same values there) 1647 if got, acc := xx.Float64(); got != x || acc != Exact { 1648 t.Errorf("Float(%g) == %g (%s)", x, got, acc) 1649 } 1650 for _, y := range args { 1651 yy.SetFloat64(y) 1652 got := xx.Cmp(yy) 1653 want := 0 1654 switch { 1655 case x < y: 1656 want = -1 1657 case x > y: 1658 want = +1 1659 } 1660 if got != want { 1661 t.Errorf("(%g).Cmp(%g) = %s; want %s", x, y, got, want) 1662 } 1663 } 1664 } 1665 } 1666 }