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