gh-135853: add `math.fmax` and `math.fmin` by picnixz · Pull Request #135888 · python/cpython · GitHub
Skip to content
Merged
26 changes: 26 additions & 0 deletions Doc/library/math.rst
2 changes: 1 addition & 1 deletion Doc/whatsnew/3.15.rst
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ math
* Add :func:`math.isnormal` and :func:`math.issubnormal` functions.
(Contributed by Sergey B Kirpichev in :gh:`132908`.)

* Add :func:`math.signbit` function.
* Add :func:`math.fmax`, :func:`math.fmin` and :func:`math.signbit` functions.
(Contributed by Bénédikt Tran in :gh:`135853`.)


Expand Down
87 changes: 87 additions & 0 deletions Lib/test/test_math.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

eps = 1E-05
NAN = float('nan')
NNAN = float('-nan')
INF = float('inf')
NINF = float('-inf')
FLOAT_MAX = sys.float_info.max
Expand Down Expand Up @@ -636,6 +637,92 @@ def testFmod(self):
self.assertEqual(math.fmod(0.0, NINF), 0.0)
self.assertRaises(ValueError, math.fmod, INF, INF)

def test_fmax(self):
self.assertRaises(TypeError, math.fmax)
self.assertRaises(TypeError, math.fmax, 'x', 'y')

self.assertEqual(math.fmax(0., 0.), 0.)
self.assertEqual(math.fmax(1., 2.), 2.)
self.assertEqual(math.fmax(2., 1.), 2.)

self.assertEqual(math.fmax(+1., +0.), 1.)
self.assertEqual(math.fmax(+0., +1.), 1.)
self.assertEqual(math.fmax(+1., -0.), 1.)
self.assertEqual(math.fmax(-0., +1.), 1.)

self.assertEqual(math.fmax(-1., +0.), 0.)
self.assertEqual(math.fmax(+0., -1.), 0.)
self.assertEqual(math.fmax(-1., -0.), 0.)
self.assertEqual(math.fmax(-0., -1.), 0.)

for x in [NINF, -1., -0., 0., 1., INF]:
self.assertFalse(math.isnan(x))

with self.subTest(x=x, is_negative=math.copysign(1, x) < 0):
self.assertEqual(math.fmax(INF, x), INF)
self.assertEqual(math.fmax(x, INF), INF)
self.assertEqual(math.fmax(NINF, x), x)
self.assertEqual(math.fmax(x, NINF), x)

@requires_IEEE_754
Comment thread
vstinner marked this conversation as resolved.
def test_fmax_nans(self):
# When exactly one operand is NaN, the other is returned.
for x in [NINF, -1., -0., 0., 1., INF]:
with self.subTest(x=x, is_negative=math.copysign(1, x) < 0):
self.assertFalse(math.isnan(math.fmax(NAN, x)))
self.assertFalse(math.isnan(math.fmax(x, NAN)))
self.assertFalse(math.isnan(math.fmax(NNAN, x)))
self.assertFalse(math.isnan(math.fmax(x, NNAN)))
# When both operands are NaNs, fmax() returns NaN (see C11, F.10.9.2)
# whose sign is implementation-defined (see C11, F.10.0.3).
self.assertTrue(math.isnan(math.fmax(NAN, NAN)))
self.assertTrue(math.isnan(math.fmax(NNAN, NNAN)))
self.assertTrue(math.isnan(math.fmax(NAN, NNAN)))
self.assertTrue(math.isnan(math.fmax(NNAN, NAN)))

def test_fmin(self):
self.assertRaises(TypeError, math.fmin)
self.assertRaises(TypeError, math.fmin, 'x', 'y')

self.assertEqual(math.fmin(0., 0.), 0.)
self.assertEqual(math.fmin(1., 2.), 1.)
self.assertEqual(math.fmin(2., 1.), 1.)

self.assertEqual(math.fmin(+1., +0.), 0.)
self.assertEqual(math.fmin(+0., +1.), 0.)
self.assertEqual(math.fmin(+1., -0.), 0.)
self.assertEqual(math.fmin(-0., +1.), 0.)

self.assertEqual(math.fmin(-1., +0.), -1.)
self.assertEqual(math.fmin(+0., -1.), -1.)
self.assertEqual(math.fmin(-1., -0.), -1.)
self.assertEqual(math.fmin(-0., -1.), -1.)

for x in [NINF, -1., -0., 0., 1., INF]:
self.assertFalse(math.isnan(x))

with self.subTest(x=x, is_negative=math.copysign(1, x) < 0):
self.assertEqual(math.fmin(INF, x), x)
self.assertEqual(math.fmin(x, INF), x)
self.assertEqual(math.fmin(NINF, x), NINF)
self.assertEqual(math.fmin(x, NINF), NINF)

@requires_IEEE_754
def test_fmin_nans(self):
# When exactly one operand is NaN, the other is returned.
for x in [NINF, -1., -0., 0., 1., INF]:
with self.subTest(x=x, is_negative=math.copysign(1, x) < 0):
self.assertFalse(math.isnan(math.fmin(NAN, x)))
self.assertFalse(math.isnan(math.fmin(x, NAN)))
self.assertFalse(math.isnan(math.fmin(NNAN, x)))
self.assertFalse(math.isnan(math.fmin(x, NNAN)))
# When both operands are NaNs, fmin() returns NaN (see C11, F.10.9.3)
# whose sign is implementation-defined (see C11, F.10.0.3).
self.assertTrue(math.isnan(math.fmin(NAN, NAN)))
self.assertTrue(math.isnan(math.fmin(NNAN, NNAN)))
self.assertTrue(math.isnan(math.fmin(NAN, NNAN)))
self.assertTrue(math.isnan(math.fmin(NNAN, NAN)))

def testFrexp(self):
self.assertRaises(TypeError, math.frexp)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Add :func:`math.fmax` and :func:`math.fmin` to get the larger and smaller of
two floating-point values. Patch by Bénédikt Tran.
108 changes: 107 additions & 1 deletion Modules/clinic/mathmodule.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

36 changes: 36 additions & 0 deletions Modules/mathmodule.c
Loading