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