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