Skip to content

Commit 5f61cde

Browse files
authored
gh-132908: Add math.isnormal/issubnormal() functions (GH132935)
1 parent 128195e commit 5f61cde

File tree

7 files changed

+161
-2
lines changed

7 files changed

+161
-2
lines changed

Doc/library/math.rst

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ noted otherwise, all return values are floats.
5353
:func:`frexp(x) <frexp>` Mantissa and exponent of *x*
5454
:func:`isclose(a, b, rel_tol, abs_tol) <isclose>` Check if the values *a* and *b* are close to each other
5555
:func:`isfinite(x) <isfinite>` Check if *x* is neither an infinity nor a NaN
56+
:func:`isnormal(x) <isnormal>` Check if *x* is a normal number
57+
:func:`issubnormal(x) <issubnormal>` Check if *x* is a subnormal number
5658
:func:`isinf(x) <isinf>` Check if *x* is a positive or negative infinity
5759
:func:`isnan(x) <isnan>` Check if *x* is a NaN (not a number)
5860
:func:`ldexp(x, i) <ldexp>` ``x * (2**i)``, inverse of function :func:`frexp`
@@ -373,6 +375,24 @@ Floating point manipulation functions
373375
.. versionadded:: 3.2
374376

375377

378+
.. function:: isnormal(x)
379+
380+
Return ``True`` if *x* is a normal number, that is a finite
381+
nonzero number that is not a subnormal (see :func:`issubnormal`).
382+
Return ``False`` otherwise.
383+
384+
.. versionadded:: next
385+
386+
387+
.. function:: issubnormal(x)
388+
389+
Return ``True`` if *x* is a subnormal number, that is a finite
390+
nonzero number with a magnitude smaller than the smallest positive normal
391+
number, see :data:`sys.float_info.min`. Return ``False`` otherwise.
392+
393+
.. versionadded:: next
394+
395+
376396
.. function:: isinf(x)
377397

378398
Return ``True`` if *x* is a positive or negative infinity, and

Doc/whatsnew/3.14.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1454,7 +1454,7 @@ math
14541454
----
14551455

14561456
* Added more detailed error messages for domain errors in the module.
1457-
(Contributed by by Charlie Zhao and Sergey B Kirpichev in :gh:`101410`.)
1457+
(Contributed by Charlie Zhao and Sergey B Kirpichev in :gh:`101410`.)
14581458

14591459

14601460
mimetypes

Doc/whatsnew/3.15.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,13 @@ difflib
105105
(Contributed by Jiahao Li in :gh:`134580`.)
106106

107107

108+
math
109+
----
110+
111+
* Add :func:`math.isnormal` and :func:`math.issubnormal` functions.
112+
(Contributed by Sergey B Kirpichev in :gh:`132908`.)
113+
114+
108115
shelve
109116
------
110117

Lib/test/test_math.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1973,6 +1973,28 @@ def testIsfinite(self):
19731973
self.assertFalse(math.isfinite(float("inf")))
19741974
self.assertFalse(math.isfinite(float("-inf")))
19751975

1976+
def testIsnormal(self):
1977+
self.assertTrue(math.isnormal(1.25))
1978+
self.assertTrue(math.isnormal(-1.0))
1979+
self.assertFalse(math.isnormal(0.0))
1980+
self.assertFalse(math.isnormal(-0.0))
1981+
self.assertFalse(math.isnormal(INF))
1982+
self.assertFalse(math.isnormal(NINF))
1983+
self.assertFalse(math.isnormal(NAN))
1984+
self.assertFalse(math.isnormal(FLOAT_MIN/2))
1985+
self.assertFalse(math.isnormal(-FLOAT_MIN/2))
1986+
1987+
def testIssubnormal(self):
1988+
self.assertFalse(math.issubnormal(1.25))
1989+
self.assertFalse(math.issubnormal(-1.0))
1990+
self.assertFalse(math.issubnormal(0.0))
1991+
self.assertFalse(math.issubnormal(-0.0))
1992+
self.assertFalse(math.issubnormal(INF))
1993+
self.assertFalse(math.issubnormal(NINF))
1994+
self.assertFalse(math.issubnormal(NAN))
1995+
self.assertTrue(math.issubnormal(FLOAT_MIN/2))
1996+
self.assertTrue(math.issubnormal(-FLOAT_MIN/2))
1997+
19761998
def testIsnan(self):
19771999
self.assertTrue(math.isnan(float("nan")))
19782000
self.assertTrue(math.isnan(float("-nan")))
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Add :func:`math.isnormal` and :func:`math.issubnormal` functions. Patch by
2+
Sergey B Kirpichev.

Modules/clinic/mathmodule.c.h

Lines changed: 69 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Modules/mathmodule.c

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3118,6 +3118,44 @@ math_isfinite_impl(PyObject *module, double x)
31183118
}
31193119

31203120

3121+
/*[clinic input]
3122+
math.isnormal
3123+
3124+
x: double
3125+
/
3126+
3127+
Return True if x is normal, and False otherwise.
3128+
[clinic start generated code]*/
3129+
3130+
static PyObject *
3131+
math_isnormal_impl(PyObject *module, double x)
3132+
/*[clinic end generated code: output=c7b302b5b89c3541 input=fdaa00c58aa7bc17]*/
3133+
{
3134+
return PyBool_FromLong(isnormal(x));
3135+
}
3136+
3137+
3138+
/*[clinic input]
3139+
math.issubnormal
3140+
3141+
x: double
3142+
/
3143+
3144+
Return True if x is subnormal, and False otherwise.
3145+
[clinic start generated code]*/
3146+
3147+
static PyObject *
3148+
math_issubnormal_impl(PyObject *module, double x)
3149+
/*[clinic end generated code: output=4e76ac98ddcae761 input=9a20aba7107d0d95]*/
3150+
{
3151+
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L
3152+
return PyBool_FromLong(issubnormal(x));
3153+
#else
3154+
return PyBool_FromLong(isfinite(x) && x && !isnormal(x));
3155+
#endif
3156+
}
3157+
3158+
31213159
/*[clinic input]
31223160
math.isnan
31233161
@@ -4145,6 +4183,8 @@ static PyMethodDef math_methods[] = {
41454183
MATH_HYPOT_METHODDEF
41464184
MATH_ISCLOSE_METHODDEF
41474185
MATH_ISFINITE_METHODDEF
4186+
MATH_ISNORMAL_METHODDEF
4187+
MATH_ISSUBNORMAL_METHODDEF
41484188
MATH_ISINF_METHODDEF
41494189
MATH_ISNAN_METHODDEF
41504190
MATH_ISQRT_METHODDEF

0 commit comments

Comments
 (0)