Skip to content

Commit 9d14505

Browse files
committed
gh-132908: add math.normal/subnormal() functions
1 parent ecd0373 commit 9d14505

File tree

6 files changed

+153
-2
lines changed

6 files changed

+153
-2
lines changed

Doc/library/math.rst

Lines changed: 19 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 floating-point number
57+
:func:`issubnormal(x) <issubnormal>` Check if *x* is a subnormal floating-point 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`
@@ -374,6 +376,23 @@ Floating point manipulation functions
374376
.. versionadded:: 3.2
375377

376378

379+
.. function:: isnormal(x)
380+
381+
Return ``True`` if *x* is a normal floating-point number, i.e. a finite
382+
nonzero number, that is not a subnormal. Return ``False`` otherwise.
383+
384+
.. versionadded:: next
385+
386+
387+
.. function:: issubnormal(x)
388+
389+
Return ``True`` if *x* is a subnormal floating-point number, i.e. 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+
377396
.. function:: isinf(x)
378397

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

Doc/whatsnew/3.14.rst

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -950,7 +950,10 @@ math
950950
----
951951

952952
* Added more detailed error messages for domain errors in the module.
953-
(Contributed by by Charlie Zhao and Sergey B Kirpichev in :gh:`101410`.)
953+
(Contributed by Charlie Zhao and Sergey B Kirpichev in :gh:`101410`.)
954+
955+
* Add :func:`math.isnormal` and :func:`math.issubnormal` function.
956+
(Contributed by Sergey B Kirpichev in :gh:`132908`.)
954957

955958

956959
mimetypes

Lib/test/test_math.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1967,6 +1967,28 @@ def testIsfinite(self):
19671967
self.assertFalse(math.isfinite(float("inf")))
19681968
self.assertFalse(math.isfinite(float("-inf")))
19691969

1970+
def testIsnormal(self):
1971+
self.assertTrue(math.isnormal(1.25))
1972+
self.assertTrue(math.isnormal(-1.0))
1973+
self.assertFalse(math.isnormal(0.0))
1974+
self.assertFalse(math.isnormal(-0.0))
1975+
self.assertFalse(math.isnormal(INF))
1976+
self.assertFalse(math.isnormal(NINF))
1977+
self.assertFalse(math.isnormal(NAN))
1978+
self.assertFalse(math.isnormal(FLOAT_MIN/2))
1979+
self.assertFalse(math.isnormal(-FLOAT_MIN/2))
1980+
1981+
def testIsnormal(self):
1982+
self.assertFalse(math.issubnormal(1.25))
1983+
self.assertFalse(math.issubnormal(-1.0))
1984+
self.assertFalse(math.issubnormal(0.0))
1985+
self.assertFalse(math.issubnormal(-0.0))
1986+
self.assertFalse(math.issubnormal(INF))
1987+
self.assertFalse(math.issubnormal(NINF))
1988+
self.assertFalse(math.issubnormal(NAN))
1989+
self.assertTrue(math.issubnormal(FLOAT_MIN/2))
1990+
self.assertTrue(math.issubnormal(-FLOAT_MIN/2))
1991+
19701992
def testIsnan(self):
19711993
self.assertTrue(math.isnan(float("nan")))
19721994
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` function. 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: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3098,6 +3098,41 @@ math_isfinite_impl(PyObject *module, double x)
30983098
return PyBool_FromLong((long)isfinite(x));
30993099
}
31003100

3101+
/*[clinic input]
3102+
math.isnormal
3103+
3104+
x: double
3105+
/
3106+
3107+
Return True if x is normal, and False otherwise.
3108+
[clinic start generated code]*/
3109+
3110+
static PyObject *
3111+
math_isnormal_impl(PyObject *module, double x)
3112+
/*[clinic end generated code: output=c7b302b5b89c3541 input=fdaa00c58aa7bc17]*/
3113+
{
3114+
return PyBool_FromLong((long)isnormal(x));
3115+
}
3116+
3117+
/*[clinic input]
3118+
math.issubnormal
3119+
3120+
x: double
3121+
/
3122+
3123+
Return True if x is subnormal, and False otherwise.
3124+
[clinic start generated code]*/
3125+
3126+
static PyObject *
3127+
math_issubnormal_impl(PyObject *module, double x)
3128+
/*[clinic end generated code: output=4e76ac98ddcae761 input=9a20aba7107d0d95]*/
3129+
{
3130+
#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 202311L
3131+
return PyBool_FromLong((long)issubnormal(x));
3132+
#else
3133+
return PyBool_FromLong((long)(isfinite(x) && x && !isnormal(x)));
3134+
#endif
3135+
}
31013136

31023137
/*[clinic input]
31033138
math.isnan
@@ -4126,6 +4161,8 @@ static PyMethodDef math_methods[] = {
41264161
MATH_HYPOT_METHODDEF
41274162
MATH_ISCLOSE_METHODDEF
41284163
MATH_ISFINITE_METHODDEF
4164+
MATH_ISNORMAL_METHODDEF
4165+
MATH_ISSUBNORMAL_METHODDEF
41294166
MATH_ISINF_METHODDEF
41304167
MATH_ISNAN_METHODDEF
41314168
MATH_ISQRT_METHODDEF

0 commit comments

Comments
 (0)