mirror of
https://github.com/python/cpython.git
synced 2025-07-07 19:35:27 +00:00
gh-135853: add math.signbit
(#135877)
This commit is contained in:
parent
ff7b5d44a0
commit
42ccac2d7f
6 changed files with 81 additions and 3 deletions
|
@ -59,6 +59,7 @@ noted otherwise, all return values are floats.
|
||||||
:func:`isnan(x) <isnan>` Check if *x* is a NaN (not a number)
|
:func:`isnan(x) <isnan>` Check if *x* is a NaN (not a number)
|
||||||
:func:`ldexp(x, i) <ldexp>` ``x * (2**i)``, inverse of function :func:`frexp`
|
:func:`ldexp(x, i) <ldexp>` ``x * (2**i)``, inverse of function :func:`frexp`
|
||||||
:func:`nextafter(x, y, steps) <nextafter>` Floating-point value *steps* steps after *x* towards *y*
|
:func:`nextafter(x, y, steps) <nextafter>` Floating-point value *steps* steps after *x* towards *y*
|
||||||
|
:func:`signbit(x) <signbit>` Check if *x* is a negative number
|
||||||
:func:`ulp(x) <ulp>` Value of the least significant bit of *x*
|
:func:`ulp(x) <ulp>` Value of the least significant bit of *x*
|
||||||
|
|
||||||
**Power, exponential and logarithmic functions**
|
**Power, exponential and logarithmic functions**
|
||||||
|
@ -431,6 +432,15 @@ Floating point manipulation functions
|
||||||
Added the *steps* argument.
|
Added the *steps* argument.
|
||||||
|
|
||||||
|
|
||||||
|
.. function:: signbit(x)
|
||||||
|
|
||||||
|
Return ``True`` if the sign of *x* is negative and ``False`` otherwise.
|
||||||
|
|
||||||
|
This is useful to detect the sign bit of zeroes, infinities and NaNs.
|
||||||
|
|
||||||
|
.. versionadded:: next
|
||||||
|
|
||||||
|
|
||||||
.. function:: ulp(x)
|
.. function:: ulp(x)
|
||||||
|
|
||||||
Return the value of the least significant bit of the float *x*:
|
Return the value of the least significant bit of the float *x*:
|
||||||
|
|
|
@ -115,6 +115,9 @@ math
|
||||||
* Add :func:`math.isnormal` and :func:`math.issubnormal` functions.
|
* Add :func:`math.isnormal` and :func:`math.issubnormal` functions.
|
||||||
(Contributed by Sergey B Kirpichev in :gh:`132908`.)
|
(Contributed by Sergey B Kirpichev in :gh:`132908`.)
|
||||||
|
|
||||||
|
* Add :func:`math.signbit` function.
|
||||||
|
(Contributed by Bénédikt Tran in :gh:`135853`.)
|
||||||
|
|
||||||
|
|
||||||
os.path
|
os.path
|
||||||
-------
|
-------
|
||||||
|
|
|
@ -475,6 +475,19 @@ class MathTests(unittest.TestCase):
|
||||||
# similarly, copysign(2., NAN) could be 2. or -2.
|
# similarly, copysign(2., NAN) could be 2. or -2.
|
||||||
self.assertEqual(abs(math.copysign(2., NAN)), 2.)
|
self.assertEqual(abs(math.copysign(2., NAN)), 2.)
|
||||||
|
|
||||||
|
def test_signbit(self):
|
||||||
|
self.assertRaises(TypeError, math.signbit)
|
||||||
|
self.assertRaises(TypeError, math.signbit, '1.0')
|
||||||
|
|
||||||
|
# C11, §7.12.3.6 requires signbit() to return a nonzero value
|
||||||
|
# if and only if the sign of its argument value is negative,
|
||||||
|
# but in practice, we are only interested in a boolean value.
|
||||||
|
self.assertIsInstance(math.signbit(1.0), bool)
|
||||||
|
|
||||||
|
for arg in [0., 1., INF, NAN]:
|
||||||
|
self.assertFalse(math.signbit(arg))
|
||||||
|
self.assertTrue(math.signbit(-arg))
|
||||||
|
|
||||||
def testCos(self):
|
def testCos(self):
|
||||||
self.assertRaises(TypeError, math.cos)
|
self.assertRaises(TypeError, math.cos)
|
||||||
self.ftest('cos(-pi/2)', math.cos(-math.pi/2), 0, abs_tol=math.ulp(1))
|
self.ftest('cos(-pi/2)', math.cos(-math.pi/2), 0, abs_tol=math.ulp(1))
|
||||||
|
@ -1387,7 +1400,6 @@ class MathTests(unittest.TestCase):
|
||||||
args = ((-5, -5, 10), (1.5, 4611686018427387904, 2305843009213693952))
|
args = ((-5, -5, 10), (1.5, 4611686018427387904, 2305843009213693952))
|
||||||
self.assertEqual(sumprod(*args), 0.0)
|
self.assertEqual(sumprod(*args), 0.0)
|
||||||
|
|
||||||
|
|
||||||
@requires_IEEE_754
|
@requires_IEEE_754
|
||||||
@unittest.skipIf(HAVE_DOUBLE_ROUNDING,
|
@unittest.skipIf(HAVE_DOUBLE_ROUNDING,
|
||||||
"sumprod() accuracy not guaranteed on machines with double rounding")
|
"sumprod() accuracy not guaranteed on machines with double rounding")
|
||||||
|
@ -2486,7 +2498,6 @@ class MathTests(unittest.TestCase):
|
||||||
with self.assertRaises(ValueError):
|
with self.assertRaises(ValueError):
|
||||||
math.nextafter(1.0, INF, steps=-1)
|
math.nextafter(1.0, INF, steps=-1)
|
||||||
|
|
||||||
|
|
||||||
@requires_IEEE_754
|
@requires_IEEE_754
|
||||||
def test_ulp(self):
|
def test_ulp(self):
|
||||||
self.assertEqual(math.ulp(1.0), sys.float_info.epsilon)
|
self.assertEqual(math.ulp(1.0), sys.float_info.epsilon)
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
:mod:`math`: expose C99 :func:`~math.signbit` function to determine whether
|
||||||
|
the sign bit of a floating-point value is set. Patch by Bénédikt Tran.
|
36
Modules/clinic/mathmodule.c.h
generated
36
Modules/clinic/mathmodule.c.h
generated
|
@ -84,6 +84,40 @@ PyDoc_STRVAR(math_floor__doc__,
|
||||||
#define MATH_FLOOR_METHODDEF \
|
#define MATH_FLOOR_METHODDEF \
|
||||||
{"floor", (PyCFunction)math_floor, METH_O, math_floor__doc__},
|
{"floor", (PyCFunction)math_floor, METH_O, math_floor__doc__},
|
||||||
|
|
||||||
|
PyDoc_STRVAR(math_signbit__doc__,
|
||||||
|
"signbit($module, x, /)\n"
|
||||||
|
"--\n"
|
||||||
|
"\n"
|
||||||
|
"Return True if the sign of x is negative and False otherwise.");
|
||||||
|
|
||||||
|
#define MATH_SIGNBIT_METHODDEF \
|
||||||
|
{"signbit", (PyCFunction)math_signbit, METH_O, math_signbit__doc__},
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
math_signbit_impl(PyObject *module, double x);
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
math_signbit(PyObject *module, PyObject *arg)
|
||||||
|
{
|
||||||
|
PyObject *return_value = NULL;
|
||||||
|
double x;
|
||||||
|
|
||||||
|
if (PyFloat_CheckExact(arg)) {
|
||||||
|
x = PyFloat_AS_DOUBLE(arg);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x = PyFloat_AsDouble(arg);
|
||||||
|
if (x == -1.0 && PyErr_Occurred()) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return_value = math_signbit_impl(module, x);
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
PyDoc_STRVAR(math_fsum__doc__,
|
PyDoc_STRVAR(math_fsum__doc__,
|
||||||
"fsum($module, seq, /)\n"
|
"fsum($module, seq, /)\n"
|
||||||
"--\n"
|
"--\n"
|
||||||
|
@ -1178,4 +1212,4 @@ math_ulp(PyObject *module, PyObject *arg)
|
||||||
exit:
|
exit:
|
||||||
return return_value;
|
return return_value;
|
||||||
}
|
}
|
||||||
/*[clinic end generated code: output=44bba3a0a052a364 input=a9049054013a1b77]*/
|
/*[clinic end generated code: output=4e3fa94d026f027b input=a9049054013a1b77]*/
|
||||||
|
|
|
@ -1233,6 +1233,23 @@ FUNC2(remainder, m_remainder,
|
||||||
"Return x - n*y where n*y is the closest integer multiple of y.\n"
|
"Return x - n*y where n*y is the closest integer multiple of y.\n"
|
||||||
"In the case where x is exactly halfway between two multiples of\n"
|
"In the case where x is exactly halfway between two multiples of\n"
|
||||||
"y, the nearest even value of n is used. The result is always exact.")
|
"y, the nearest even value of n is used. The result is always exact.")
|
||||||
|
|
||||||
|
/*[clinic input]
|
||||||
|
math.signbit
|
||||||
|
|
||||||
|
x: double
|
||||||
|
/
|
||||||
|
|
||||||
|
Return True if the sign of x is negative and False otherwise.
|
||||||
|
[clinic start generated code]*/
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
math_signbit_impl(PyObject *module, double x)
|
||||||
|
/*[clinic end generated code: output=20c5f20156a9b871 input=3d3493fbcb5bdb3e]*/
|
||||||
|
{
|
||||||
|
return PyBool_FromLong(signbit(x));
|
||||||
|
}
|
||||||
|
|
||||||
FUNC1D(sin, sin, 0,
|
FUNC1D(sin, sin, 0,
|
||||||
"sin($module, x, /)\n--\n\n"
|
"sin($module, x, /)\n--\n\n"
|
||||||
"Return the sine of x (measured in radians).",
|
"Return the sine of x (measured in radians).",
|
||||||
|
@ -4199,6 +4216,7 @@ static PyMethodDef math_methods[] = {
|
||||||
MATH_POW_METHODDEF
|
MATH_POW_METHODDEF
|
||||||
MATH_RADIANS_METHODDEF
|
MATH_RADIANS_METHODDEF
|
||||||
{"remainder", _PyCFunction_CAST(math_remainder), METH_FASTCALL, math_remainder_doc},
|
{"remainder", _PyCFunction_CAST(math_remainder), METH_FASTCALL, math_remainder_doc},
|
||||||
|
MATH_SIGNBIT_METHODDEF
|
||||||
{"sin", math_sin, METH_O, math_sin_doc},
|
{"sin", math_sin, METH_O, math_sin_doc},
|
||||||
{"sinh", math_sinh, METH_O, math_sinh_doc},
|
{"sinh", math_sinh, METH_O, math_sinh_doc},
|
||||||
{"sqrt", math_sqrt, METH_O, math_sqrt_doc},
|
{"sqrt", math_sqrt, METH_O, math_sqrt_doc},
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue