From 725fc987a9ae0683322249eb7afd0688d5a4f46e Mon Sep 17 00:00:00 2001 From: Sergey B Kirpichev Date: Sun, 31 May 2026 10:29:44 +0300 Subject: [PATCH] [3.13] Correct frexp() docs for zero and non-finite numbers (GH-149753) 0.5 <= abs(m) < 1 is only true for finite nonzero numbers (cherry picked from commit 5b5ffce05c211a5b0b74cd95eeb4c463614ee136) Co-authored-by: Sergey B Kirpichev --- Doc/library/math.rst | 10 ++++++---- Modules/clinic/mathmodule.c.h | 7 ++++--- Modules/mathmodule.c | 7 ++++--- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/Doc/library/math.rst b/Doc/library/math.rst index 46d61388f794827..ebf0ea3901bb6db 100644 --- a/Doc/library/math.rst +++ b/Doc/library/math.rst @@ -321,10 +321,12 @@ Floating point manipulation functions .. function:: frexp(x) - Return the mantissa and exponent of *x* as the pair ``(m, e)``. *m* is a float - and *e* is an integer such that ``x == m * 2**e`` exactly. If *x* is zero, - returns ``(0.0, 0)``, otherwise ``0.5 <= abs(m) < 1``. This is used to "pick - apart" the internal representation of a float in a portable way. + Return the mantissa and exponent of *x* as the pair ``(m, e)``. + If *x* is a finite nonzero number, then *m* is a float with + ``0.5 <= abs(m) < 1.0`` and an integer *e* is such that + ``x == m * 2**e`` exactly. Else, return ``(x, 0)``. + This is used to "pick apart" the internal representation of + a float in a portable way. Note that :func:`frexp` has a different call/return pattern than its C equivalents: it takes a single argument and return a pair of diff --git a/Modules/clinic/mathmodule.c.h b/Modules/clinic/mathmodule.c.h index 7af5fcccb2d14af..473efd8ef05a18a 100644 --- a/Modules/clinic/mathmodule.c.h +++ b/Modules/clinic/mathmodule.c.h @@ -76,8 +76,9 @@ PyDoc_STRVAR(math_frexp__doc__, "\n" "Return the mantissa and exponent of x, as pair (m, e).\n" "\n" -"m is a float and e is an int, such that x = m * 2.**e.\n" -"If x is 0, m and e are both 0. Else 0.5 <= abs(m) < 1.0."); +"If x is a finite nonzero number, then m is a float with\n" +"0.5 <= abs(m) < 1.0 and an integer e is such that\n" +"x == m * 2**e exactly. Else, return (x, 0)."); #define MATH_FREXP_METHODDEF \ {"frexp", (PyCFunction)math_frexp, METH_O, math_frexp__doc__}, @@ -1009,4 +1010,4 @@ math_ulp(PyObject *module, PyObject *arg) exit: return return_value; } -/*[clinic end generated code: output=ef101d15f144ab44 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=9ed980dea18198be input=a9049054013a1b77]*/ diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c index 66ad6d4c4de0c5a..e0a1db0fea8d88e 100644 --- a/Modules/mathmodule.c +++ b/Modules/mathmodule.c @@ -2095,13 +2095,14 @@ math.frexp Return the mantissa and exponent of x, as pair (m, e). -m is a float and e is an int, such that x = m * 2.**e. -If x is 0, m and e are both 0. Else 0.5 <= abs(m) < 1.0. +If x is a finite nonzero number, then m is a float with +0.5 <= abs(m) < 1.0 and an integer e is such that +x == m * 2**e exactly. Else, return (x, 0). [clinic start generated code]*/ static PyObject * math_frexp_impl(PyObject *module, double x) -/*[clinic end generated code: output=03e30d252a15ad4a input=96251c9e208bc6e9]*/ +/*[clinic end generated code: output=03e30d252a15ad4a input=215cf8ea28a0959b]*/ { int i; /* deal with special cases directly, to sidestep platform