|
17 | 17 |
|
18 | 18 | eps = 1E-05
|
19 | 19 | NAN = float('nan')
|
| 20 | +NNAN = float('-nan') |
20 | 21 | INF = float('inf')
|
21 | 22 | NINF = float('-inf')
|
22 | 23 | FLOAT_MAX = sys.float_info.max
|
|
37 | 38 | test_file = os.path.join(test_dir, 'mathdata', 'cmath_testcases.txt')
|
38 | 39 |
|
39 | 40 |
|
| 41 | +def is_signed_nan(x, x0): |
| 42 | + """Check if x is a NaN with the same sign as x0.""" |
| 43 | + return math.isnan(x) and math.copysign(1, x) == math.copysign(1, x0) |
| 44 | + |
| 45 | + |
40 | 46 | def to_ulps(x):
|
41 | 47 | """Convert a non-NaN float x to an integer, in such a way that
|
42 | 48 | adjacent floats are converted to adjacent integers. Then
|
@@ -253,9 +259,10 @@ def ftest(self, name, got, expected, ulp_tol=5, abs_tol=0.0):
|
253 | 259 | non-finite floats, exact equality is demanded. Also, nan==nan
|
254 | 260 | in this function.
|
255 | 261 | """
|
256 |
| - failure = result_check(expected, got, ulp_tol, abs_tol) |
257 |
| - if failure is not None: |
258 |
| - self.fail("{}: {}".format(name, failure)) |
| 262 | + with self.subTest(name): |
| 263 | + failure = result_check(expected, got, ulp_tol, abs_tol) |
| 264 | + if failure is not None: |
| 265 | + self.fail(failure) |
259 | 266 |
|
260 | 267 | def testConstants(self):
|
261 | 268 | # Ref: Abramowitz & Stegun (Dover, 1965)
|
@@ -623,6 +630,101 @@ def testFmod(self):
|
623 | 630 | self.assertEqual(math.fmod(0.0, NINF), 0.0)
|
624 | 631 | self.assertRaises(ValueError, math.fmod, INF, INF)
|
625 | 632 |
|
| 633 | + def test_fmax(self): |
| 634 | + self.assertRaises(TypeError, math.fmax) |
| 635 | + self.assertRaises(TypeError, math.fmax, 'x', 'y') |
| 636 | + |
| 637 | + self.assertEqual(math.fmax(0., 0.), 0.) |
| 638 | + self.assertEqual(math.fmax(0., -0.), 0.) |
| 639 | + self.assertEqual(math.fmax(-0., 0.), 0.) |
| 640 | + |
| 641 | + self.assertEqual(math.fmax(1., 0.), 1.) |
| 642 | + self.assertEqual(math.fmax(0., 1.), 1.) |
| 643 | + self.assertEqual(math.fmax(1., -0.), 1.) |
| 644 | + self.assertEqual(math.fmax(-0., 1.), 1.) |
| 645 | + |
| 646 | + self.assertEqual(math.fmax(-1., 0.), 0.) |
| 647 | + self.assertEqual(math.fmax(0., -1.), 0.) |
| 648 | + self.assertEqual(math.fmax(-1., -0.), -0.) |
| 649 | + self.assertEqual(math.fmax(-0., -1.), -0.) |
| 650 | + |
| 651 | + for x in [NINF, -1., -0., 0., 1., INF]: |
| 652 | + self.assertFalse(math.isnan(x)) |
| 653 | + |
| 654 | + with self.subTest("math.fmax(INF, x)", x=x): |
| 655 | + self.assertEqual(math.fmax(INF, x), INF) |
| 656 | + with self.subTest("math.fmax(x, INF)", x=x): |
| 657 | + self.assertEqual(math.fmax(x, INF), INF) |
| 658 | + |
| 659 | + with self.subTest("math.fmax(NINF, x)", x=x): |
| 660 | + self.assertEqual(math.fmax(NINF, x), x) |
| 661 | + with self.subTest("math.fmax(x, NINF)", x=x): |
| 662 | + self.assertEqual(math.fmax(x, NINF), x) |
| 663 | + |
| 664 | + @requires_IEEE_754 |
| 665 | + def test_fmax_nans(self): |
| 666 | + # When exactly one operand is NaN, the other is returned. |
| 667 | + for x in [NINF, -1., -0., 0., 1., INF]: |
| 668 | + with self.subTest(x=x): |
| 669 | + self.assertFalse(math.isnan(math.fmax(NAN, x))) |
| 670 | + self.assertFalse(math.isnan(math.fmax(x, NAN))) |
| 671 | + self.assertFalse(math.isnan(math.fmax(NNAN, x))) |
| 672 | + self.assertFalse(math.isnan(math.fmax(x, NNAN))) |
| 673 | + # When operands are NaNs with identical sign, return this signed NaN. |
| 674 | + self.assertTrue(is_signed_nan(math.fmax(NAN, NAN), 1)) |
| 675 | + self.assertTrue(is_signed_nan(math.fmax(NNAN, NNAN), -1)) |
| 676 | + # When operands are NaNs of different signs, return the positive NaN. |
| 677 | + self.assertTrue(is_signed_nan(math.fmax(NAN, NNAN), 1)) |
| 678 | + self.assertTrue(is_signed_nan(math.fmax(NNAN, NAN), 1)) |
| 679 | + |
| 680 | + def test_fmin(self): |
| 681 | + self.assertRaises(TypeError, math.fmin) |
| 682 | + self.assertRaises(TypeError, math.fmin, 'x', 'y') |
| 683 | + |
| 684 | + self.assertEqual(math.fmin(0., 0.), 0.) |
| 685 | + self.assertEqual(math.fmin(0., -0.), -0.) |
| 686 | + self.assertEqual(math.fmin(-0., 0.), -0.) |
| 687 | + |
| 688 | + self.assertEqual(math.fmin(1., 0.), 0.) |
| 689 | + self.assertEqual(math.fmin(0., 1.), 0.) |
| 690 | + self.assertEqual(math.fmin(1., -0.), -0.) |
| 691 | + self.assertEqual(math.fmin(-0., 1.), -0.) |
| 692 | + |
| 693 | + self.assertEqual(math.fmin(-1., 0.), -1.) |
| 694 | + self.assertEqual(math.fmin(0., -1.), -1.) |
| 695 | + self.assertEqual(math.fmin(-1., -0.), -1.) |
| 696 | + self.assertEqual(math.fmin(-0., -1.), -1.) |
| 697 | + |
| 698 | + for x in [NINF, -1., -0., 0., 1., INF]: |
| 699 | + self.assertFalse(math.isnan(x)) |
| 700 | + |
| 701 | + with self.subTest("math.fmin(INF, x)", x=x): |
| 702 | + self.assertEqual(math.fmin(INF, x), x) |
| 703 | + with self.subTest("math.fmin(x, INF)", x=x): |
| 704 | + self.assertEqual(math.fmin(x, INF), x) |
| 705 | + |
| 706 | + with self.subTest("math.fmin(NINF, x)", x=x): |
| 707 | + self.assertEqual(math.fmin(NINF, x), NINF) |
| 708 | + with self.subTest("math.fmin(x, NINF)", x=x): |
| 709 | + self.assertEqual(math.fmin(x, NINF), NINF) |
| 710 | + |
| 711 | + @requires_IEEE_754 |
| 712 | + def test_fmin_nans(self): |
| 713 | + # When exactly one operand is NaN, the other is returned. |
| 714 | + for x in [NINF, -1., -0., 0., 1., INF]: |
| 715 | + with self.subTest(x=x): |
| 716 | + self.assertFalse(math.isnan(x)) |
| 717 | + self.assertFalse(math.isnan(math.fmin(NAN, x))) |
| 718 | + self.assertFalse(math.isnan(math.fmin(x, NAN))) |
| 719 | + self.assertFalse(math.isnan(math.fmin(NNAN, x))) |
| 720 | + self.assertFalse(math.isnan(math.fmin(x, NNAN))) |
| 721 | + # When operands are NaNs with identical sign, return this signed NaN. |
| 722 | + self.assertTrue(is_signed_nan(math.fmin(NAN, NAN), 1)) |
| 723 | + self.assertTrue(is_signed_nan(math.fmin(NNAN, NNAN), -1)) |
| 724 | + # When operands are NaNs of different signs, return the negative NaN. |
| 725 | + self.assertTrue(is_signed_nan(math.fmin(NAN, NNAN), -1)) |
| 726 | + self.assertTrue(is_signed_nan(math.fmin(NNAN, NAN), -1)) |
| 727 | + |
626 | 728 | def testFrexp(self):
|
627 | 729 | self.assertRaises(TypeError, math.frexp)
|
628 | 730 |
|
|
0 commit comments