gh-132908: Add math.isnormal/issubnormal() functions (GH132935)
This commit is contained in:
parent
128195e12e
commit
5f61cde80a
@ -53,6 +53,8 @@ noted otherwise, all return values are floats.
|
||||
:func:`frexp(x) <frexp>` Mantissa and exponent of *x*
|
||||
:func:`isclose(a, b, rel_tol, abs_tol) <isclose>` Check if the values *a* and *b* are close to each other
|
||||
:func:`isfinite(x) <isfinite>` Check if *x* is neither an infinity nor a NaN
|
||||
:func:`isnormal(x) <isnormal>` Check if *x* is a normal number
|
||||
:func:`issubnormal(x) <issubnormal>` Check if *x* is a subnormal number
|
||||
:func:`isinf(x) <isinf>` Check if *x* is a positive or negative infinity
|
||||
: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`
|
||||
@ -373,6 +375,24 @@ Floating point manipulation functions
|
||||
.. versionadded:: 3.2
|
||||
|
||||
|
||||
.. function:: isnormal(x)
|
||||
|
||||
Return ``True`` if *x* is a normal number, that is a finite
|
||||
nonzero number that is not a subnormal (see :func:`issubnormal`).
|
||||
Return ``False`` otherwise.
|
||||
|
||||
.. versionadded:: next
|
||||
|
||||
|
||||
.. function:: issubnormal(x)
|
||||
|
||||
Return ``True`` if *x* is a subnormal number, that is a finite
|
||||
nonzero number with a magnitude smaller than the smallest positive normal
|
||||
number, see :data:`sys.float_info.min`. Return ``False`` otherwise.
|
||||
|
||||
.. versionadded:: next
|
||||
|
||||
|
||||
.. function:: isinf(x)
|
||||
|
||||
Return ``True`` if *x* is a positive or negative infinity, and
|
||||
|
@ -1454,7 +1454,7 @@ math
|
||||
----
|
||||
|
||||
* Added more detailed error messages for domain errors in the module.
|
||||
(Contributed by by Charlie Zhao and Sergey B Kirpichev in :gh:`101410`.)
|
||||
(Contributed by Charlie Zhao and Sergey B Kirpichev in :gh:`101410`.)
|
||||
|
||||
|
||||
mimetypes
|
||||
|
@ -105,6 +105,13 @@ difflib
|
||||
(Contributed by Jiahao Li in :gh:`134580`.)
|
||||
|
||||
|
||||
math
|
||||
----
|
||||
|
||||
* Add :func:`math.isnormal` and :func:`math.issubnormal` functions.
|
||||
(Contributed by Sergey B Kirpichev in :gh:`132908`.)
|
||||
|
||||
|
||||
shelve
|
||||
------
|
||||
|
||||
|
@ -1973,6 +1973,28 @@ class MathTests(unittest.TestCase):
|
||||
self.assertFalse(math.isfinite(float("inf")))
|
||||
self.assertFalse(math.isfinite(float("-inf")))
|
||||
|
||||
def testIsnormal(self):
|
||||
self.assertTrue(math.isnormal(1.25))
|
||||
self.assertTrue(math.isnormal(-1.0))
|
||||
self.assertFalse(math.isnormal(0.0))
|
||||
self.assertFalse(math.isnormal(-0.0))
|
||||
self.assertFalse(math.isnormal(INF))
|
||||
self.assertFalse(math.isnormal(NINF))
|
||||
self.assertFalse(math.isnormal(NAN))
|
||||
self.assertFalse(math.isnormal(FLOAT_MIN/2))
|
||||
self.assertFalse(math.isnormal(-FLOAT_MIN/2))
|
||||
|
||||
def testIssubnormal(self):
|
||||
self.assertFalse(math.issubnormal(1.25))
|
||||
self.assertFalse(math.issubnormal(-1.0))
|
||||
self.assertFalse(math.issubnormal(0.0))
|
||||
self.assertFalse(math.issubnormal(-0.0))
|
||||
self.assertFalse(math.issubnormal(INF))
|
||||
self.assertFalse(math.issubnormal(NINF))
|
||||
self.assertFalse(math.issubnormal(NAN))
|
||||
self.assertTrue(math.issubnormal(FLOAT_MIN/2))
|
||||
self.assertTrue(math.issubnormal(-FLOAT_MIN/2))
|
||||
|
||||
def testIsnan(self):
|
||||
self.assertTrue(math.isnan(float("nan")))
|
||||
self.assertTrue(math.isnan(float("-nan")))
|
||||
|
@ -0,0 +1,2 @@
|
||||
Add :func:`math.isnormal` and :func:`math.issubnormal` functions. Patch by
|
||||
Sergey B Kirpichev.
|
70
Modules/clinic/mathmodule.c.h
generated
70
Modules/clinic/mathmodule.c.h
generated
@ -628,6 +628,74 @@ exit:
|
||||
return return_value;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(math_isnormal__doc__,
|
||||
"isnormal($module, x, /)\n"
|
||||
"--\n"
|
||||
"\n"
|
||||
"Return True if x is normal, and False otherwise.");
|
||||
|
||||
#define MATH_ISNORMAL_METHODDEF \
|
||||
{"isnormal", (PyCFunction)math_isnormal, METH_O, math_isnormal__doc__},
|
||||
|
||||
static PyObject *
|
||||
math_isnormal_impl(PyObject *module, double x);
|
||||
|
||||
static PyObject *
|
||||
math_isnormal(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_isnormal_impl(module, x);
|
||||
|
||||
exit:
|
||||
return return_value;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(math_issubnormal__doc__,
|
||||
"issubnormal($module, x, /)\n"
|
||||
"--\n"
|
||||
"\n"
|
||||
"Return True if x is subnormal, and False otherwise.");
|
||||
|
||||
#define MATH_ISSUBNORMAL_METHODDEF \
|
||||
{"issubnormal", (PyCFunction)math_issubnormal, METH_O, math_issubnormal__doc__},
|
||||
|
||||
static PyObject *
|
||||
math_issubnormal_impl(PyObject *module, double x);
|
||||
|
||||
static PyObject *
|
||||
math_issubnormal(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_issubnormal_impl(module, x);
|
||||
|
||||
exit:
|
||||
return return_value;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(math_isnan__doc__,
|
||||
"isnan($module, x, /)\n"
|
||||
"--\n"
|
||||
@ -1110,4 +1178,4 @@ math_ulp(PyObject *module, PyObject *arg)
|
||||
exit:
|
||||
return return_value;
|
||||
}
|
||||
/*[clinic end generated code: output=77e7b8c161c39843 input=a9049054013a1b77]*/
|
||||
/*[clinic end generated code: output=44bba3a0a052a364 input=a9049054013a1b77]*/
|
||||
|
@ -3118,6 +3118,44 @@ math_isfinite_impl(PyObject *module, double x)
|
||||
}
|
||||
|
||||
|
||||
/*[clinic input]
|
||||
math.isnormal
|
||||
|
||||
x: double
|
||||
/
|
||||
|
||||
Return True if x is normal, and False otherwise.
|
||||
[clinic start generated code]*/
|
||||
|
||||
static PyObject *
|
||||
math_isnormal_impl(PyObject *module, double x)
|
||||
/*[clinic end generated code: output=c7b302b5b89c3541 input=fdaa00c58aa7bc17]*/
|
||||
{
|
||||
return PyBool_FromLong(isnormal(x));
|
||||
}
|
||||
|
||||
|
||||
/*[clinic input]
|
||||
math.issubnormal
|
||||
|
||||
x: double
|
||||
/
|
||||
|
||||
Return True if x is subnormal, and False otherwise.
|
||||
[clinic start generated code]*/
|
||||
|
||||
static PyObject *
|
||||
math_issubnormal_impl(PyObject *module, double x)
|
||||
/*[clinic end generated code: output=4e76ac98ddcae761 input=9a20aba7107d0d95]*/
|
||||
{
|
||||
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L
|
||||
return PyBool_FromLong(issubnormal(x));
|
||||
#else
|
||||
return PyBool_FromLong(isfinite(x) && x && !isnormal(x));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*[clinic input]
|
||||
math.isnan
|
||||
|
||||
@ -4145,6 +4183,8 @@ static PyMethodDef math_methods[] = {
|
||||
MATH_HYPOT_METHODDEF
|
||||
MATH_ISCLOSE_METHODDEF
|
||||
MATH_ISFINITE_METHODDEF
|
||||
MATH_ISNORMAL_METHODDEF
|
||||
MATH_ISSUBNORMAL_METHODDEF
|
||||
MATH_ISINF_METHODDEF
|
||||
MATH_ISNAN_METHODDEF
|
||||
MATH_ISQRT_METHODDEF
|
||||
|
Loading…
x
Reference in New Issue
Block a user