8000 gh-135853: add `math.fmax` and `math.fmin` by picnixz · Pull Request #135888 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

gh-135853: add math.fmax and math.fmin #135888

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
Prev Previous commit
Next Next commit
address review
  • Loading branch information
picnixz committed Jun 24, 2025
commit afb0a9195b51a8e8cc0427a20fe61396c1742c97
8 changes: 4 additions & 4 deletions Doc/library/math.rst
Original file line number Diff line number Diff line change
Expand Up @@ -253,8 +253,8 @@ Floating point arithmetic

Get the larger of two floating-point values, treating NaNs as missing data.

If *x* and *y* are NaNs of same sign *s*, return ``copysign(nan, s)``.
If *x* and *y* are NaNs of different sign, return ``copysign(nan, 1)``.
When both operands are NaNs, return ``nan`` (the sign of the result is
implementation-defined).

.. versionadded:: next

Expand All @@ -263,8 +263,8 @@ Floating point arithmetic

Get the smaller of two floating-point values, treating NaNs as missing data.

If *x* and *y* are NaNs of same sign *s*, return ``copysign(nan, s)``.
If *x* and *y* are NaNs of different sign, return ``copysign(nan, -1)``.
When both operands are NaNs, return ``nan`` (the sign of the result is
implementation-defined).

.. versionadded:: next

Expand Down
27 changes: 10 additions & 17 deletions Lib/test/test_math.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,6 @@
test_file = os.path.join(test_dir, 'mathdata', 'cmath_testcases.txt')


def is_signed_nan(x, x0):
"""Check if x is a NaN with the same sign as x0."""
return math.isnan(x) and math.copysign(1, x) == math.copysign(1, x0)


def to_ulps(x):
"""Convert a non-NaN float x to an integer, in such a way that
adjacent floats are converted to adjacent integers. Then
Expand Down Expand Up @@ -670,12 +665,11 @@ def test_fmax_nans(self):
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 operands are NaNs with identical sign, return this signed NaN.
self.assertTrue(is_signed_nan(math.fmax(NAN, NAN), 1))
self.assertTrue(is_signed_nan(math.fmax(NNAN, NNAN), -1))
# When operands are NaNs of different signs, return the positive NaN.
self.assertTrue(is_signed_nan(math.fmax(NAN, NNAN), 1))
self.assertTrue(is_signed_nan(math.fmax(NNAN, NAN), 1))
# When both operands are NaNs, fmax() returns NaN (see C11, F.10.9.2).
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)
Expand Down Expand Up @@ -718,12 +712,11 @@ def test_fmin_nans(self):
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 operands are NaNs with identical sign, return this signed NaN.
self.assertTrue(is_signed_nan(math.fmin(NAN, NAN), 1))
self.assertTrue(is_signed_nan(math.fmin(NNAN, NNAN), -1))
# When operands are NaNs of different signs, return the negative NaN.
self.assertTrue(is_signed_nan(math.fmin(NAN, NNAN), -1))
self.assertTrue(is_signed_nan(math.fmin(NNAN, NAN), -1))
# When both operands are NaNs, fmax() returns NaN (see C11, F.10.9.2).
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
12 changes: 1 addition & 11 deletions Modules/mathmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -1222,17 +1222,12 @@ math.fmax -> double
/

Returns the larger of two floating-point arguments.

[clinic start generated code]*/

static double
math_fmax_impl(PyObject *module, double x, double y)
/*[clinic end generated code: output=00692358d312fee2 input=0dcf618bb27f98c7]*/
/*[clinic end generated code: output=00692358d312fee2 input=e64ab9f40a60f4f1]*/
{
if (isnan(x) && isnan(y)) {
double s = copysign(1, x);
return s == copysign(1, y) ? copysign(NAN, s) : NAN;
}
return fmax(x, y);
}

Expand All @@ -1250,11 +1245,6 @@ static double
math_fmin_impl(PyObject *module, double x, double y)
/*[clinic end generated code: output=3d5b7826bd292dd9 input=f7b5c91de01d766f]*/
{
if (isnan(x) && isnan(y)) {
double s = copysign(1, x);
// return ±NAN if both are ±NAN and -NAN otherwise.
return copysign(NAN, s == copysign(1, y) ? s : -1);
}
return fmin(x, y);
}

Expand Down
Loading
0