diff --git a/peps/pep-0791.rst b/peps/pep-0791.rst index 9b1dd749a85..e9b1726fe75 100644 --- a/peps/pep-0791.rst +++ b/peps/pep-0791.rst @@ -16,27 +16,27 @@ Abstract ======== This PEP proposes a new module for number-theoretical, combinatorial and other -functions defined for integer arguments, like -:external+py3.14:func:`math.gcd` or :external+py3.14:func:`math.isqrt`. +functions defined for integer arguments, like :external+py3.14:func:`math.gcd` +or :external+py3.14:func:`math.isqrt`. Motivation ========== -The :external+py3.14:mod:`math` documentation says: "This module provides access -to the mathematical functions defined by the C standard." But, -over time the module was populated with functions that aren't related to -the C standard or floating-point arithmetics. Now it's much harder to describe +The :external+py3.14:mod:`math` documentation says: "This module provides +access to the mathematical functions defined by the C standard." But, over +time the module was populated with functions that aren't related to the C +standard or floating-point arithmetics. Now it's much harder to describe module scope, content and interfaces (returned values or accepted arguments). -For example, the :external+py3.14:mod:`math` module documentation says: "Except -when explicitly noted otherwise, all return values are floats." This is no -longer true: *None* of the functions listed in the `Number-theoretic -functions `_ -subsection of the documentation return a float, but the -documentation doesn't say so. In the documentation for the proposed ``intmath`` module the sentence "All -return values are integers." would be accurate. In a similar way we -can simplify the description of the accepted arguments for functions in both the +For example, the following statement from the documentation: "Except when +explicitly noted otherwise, all return values are floats." This is no longer +true: *None* of the functions listed in the `Number-theoretic functions +`_ +subsection of the documentation return a float, but the documentation doesn't +say so. In the documentation for the proposed ``intmath`` module the sentence +"All return values are integers" would be accurate. In a similar way we can +simplify the description of the accepted arguments for functions in both the new module and in :external+py3.14:mod:`math`. Now it's a lot harder to satisfy people's expectations about the module @@ -45,12 +45,13 @@ return an exact answer? Many languages, Python packages (like :pypi:`scipy`) or pocket calculators have functions with same or similar name, that return a floating-point value, which is only an approximation in this example. -Apparently, the :external+py3.14:mod:`math` module can't serve as a catch-all place -for mathematical functions since we also have the :external+py3.14:mod:`cmath` and -:external+py3.14:mod:`statistics` modules. Let's do the same for integer-related -functions. It provides shared context, which reduces verbosity in the -documentation and conceptual load. It also aids discoverability through -grouping related functions and makes IDE suggestions more helpful. +Apparently, the :external+py3.14:mod:`math` module can't serve as a catch-all +place for mathematical functions since we also have the +:external+py3.14:mod:`cmath` and :external+py3.14:mod:`statistics` modules. +Let's do the same for integer-related functions. It provides shared context, +which reduces verbosity in the documentation and conceptual load. It also aids +discoverability through grouping related functions and makes IDE suggestions +more helpful. Currently the :external+py3.14:mod:`math` module code in the CPython is around 4200LOC, from which the new module code is roughly 1/3 (1300LOC). This is @@ -62,61 +63,67 @@ And this situation tends to get worse. When the module split `was first proposed `_, there were only two integer-related functions: -:external+py3.14:func:`~math.factorial` (accepting also :class:`float`'s, like other -functions in the module) and :external+py3.14:func:`~math.gcd` (moved from the -::external+py3.14:mod:`fractions` module). Then +:external+py3.14:func:`~math.factorial` (accepting also :class:`float`'s, like +other functions in the module) and :external+py3.14:func:`~math.gcd` (moved +from the :external+py3.14:mod:`fractions` module). Then :external+py3.14:func:`~math.isqrt`, :external+py3.14:func:`~math.comb` and :external+py3.14:func:`~math.perm` were added, and addition of the new module was `proposed second time `_, so all new functions would go directly to it, without littering the -:external+py3.14:mod:`math` namespace. -Now there are six functions and :external+py3.14:func:`~math.factorial` doesn't accept -:class:`float`'s anymore. +:external+py3.14:mod:`math` namespace. Now there are six functions and +:external+py3.14:func:`~math.factorial` doesn't accept :class:`float`\ s +anymore. Some possible additions, among those proposed in the initial discussion thread -and issue -`python/cpython#81313 `_ are: +and issue `python/cpython#81313 +`_ are: * ``c_div()`` and ``n_div()`` --- for integer division with rounding towards positive infinity (ceiling divide) and to the nearest integer, see `relevant discussion thread `_. This is reinvented - several times in the stdlib, e.g. in the :mod:`datetime` and the + several times in the stdlib, e.g. in :mod:`datetime` and :mod:`fractions`. -* ``gcdext()`` --- to solve linear `Diophantine equation `_ in two variables (the +* ``gcdext()`` --- to solve linear `Diophantine equation + `_ in two variables (the :external+py3.14:class:`int` implementation actually includes an extended Euclidean algorithm) -* ``isqrt_rem()`` --- to return both an integer square root and a remainder (which is non-zero only if - the integer isn't a perfect square) -* ``ilog()`` --- integer logarithm, :external+py3.14:func:`math.log` - has special handling for integer arguments. It's unique (with respect to other module - functions) and not documented so far, see issue - `python/cpython#120950 `_. -* ``fibonacci()`` --- `Fibonacci sequence `_. +* ``isqrt_rem()`` --- to return both an integer square root and a remainder + (which is non-zero only if the integer isn't a perfect square) + +* ``ilog()`` --- integer logarithm, :external+py3.14:func:`math.log` has + special handling for integer arguments. It's unique (with respect to other + module functions) and not documented so far, see issue `python/cpython#120950 + `_. +* ``fibonacci()`` --- `Fibonacci sequence + `_. Rationale ========= Why not fix the :external+py3.14:mod:`math` module documentation instead? -Sure, we can be much more vague in the module preamble (i.e. roughly say -that "the :external+py3.14:mod:`math` module contains some mathematical -functions"), we can accurately describe input/output for each function -and it's behavior (e.g. whether the :external+py3.14:func:`~math.factorial` -output is exact or not, like e.g. the `scipy.special.factorial `_, per default). - -But the major issue is that the current module mixes different, almost non-interlaced -application domains. Adding more documentation will just highlight this and -make the issue worse for end users (more text to read/skip). And it will not -fix issue with discoverability (to know in which module to find a function, and -that it can be found at all, you need to look at all the functions in the -module), nor with tab-completion. +Sure, we can be much more vague in the module preamble (i.e. roughly say that +"the :external+py3.14:mod:`math` module contains some mathematical functions"), +we can accurately describe input/output for each function and its behavior +(e.g. whether the :external+py3.14:func:`~math.factorial` output is exact or +not, like the `scipy.special.factorial +`_, +per default). + +But the major issue is that the current module mixes different, almost +non-interlaced application domains. Adding more documentation will just +highlight this and make the issue worse for end users (more text to read/skip). +And it will not fix the issue with discoverability (to know in which module to find +a function, and that it can be found at all, you need to look at all the +functions in the module), nor with tab-completion. Specification ============= The PEP proposes moving the following integer-related functions to a new -module, called ``intmath``: +module, called ``intmath`` (see `Open Issues`_ for alternatives for +it's name): * :external+py3.14:func:`~math.comb` * :external+py3.14:func:`~math.factorial` @@ -163,8 +170,8 @@ How to Teach This ================= The new module will be a place for functions, that 1) accept -:external+py3.14:class:`int`-like arguments and also return integers, and 2) are -also in the field of arbitrary-precision integer arithmetic, i.e. have no +:external+py3.14:class:`int`-like arguments and also return integers, and 2) +are also in the field of arbitrary-precision integer arithmetic, i.e. have no dependency on the platform floating-point format or behaviour and/or on the platform math library (``libm``). @@ -183,20 +190,6 @@ Reference Implementation Rejected ideas ============== -Module name ------------ - -`Polling showed `_ ``intmath`` as most -popular candidate with ``imath`` as a second winner. - -Other proposed names include ``ntheory`` (like SymPy's submodule), -``integermath``, ``zmath``, ``dmath`` and ``imaths``. - -As a variant, the new module can be added as a submodule of the -:external+py3.14:mod:`math`: ``integer`` (most preferred), ``discrete`` -or ``ntheory``. - - isqrt() renaming --------------------------------------------- @@ -207,16 +200,30 @@ is ultimately a different function: it is the floor of the square root. It would be confusing to give it the same name (under a different module). +Open Issues +=========== + +`Polling showed `_ ``intmath`` as most +popular candidate with ``imath`` as a second winner. + +Other proposed names include ``ntheory`` (like SymPy's submodule), +``integermath``, ``zmath``, ``dmath`` and ``imaths``. + +As a variant, the new module can be added as a submodule of the +:external+py3.14:mod:`math`: ``integer`` (most preferred), ``discrete`` or +``ntheory`` (author preference). + + Acknowledgements ================ -Thanks to Tim Peters for reviving the idea of splitting the :external+py3.14:mod:`math` -module. Thanks to Neil Girdhar for substantial improvements of -the initial draft. +Thanks to Tim Peters for reviving the idea of splitting the +:external+py3.14:mod:`math` module. Thanks to Neil Girdhar for substantial +improvements of the initial draft. Copyright ========= -This document is placed in the public domain or under the -CC0-1.0-Universal license, whichever is more permissive. +This document is placed in the public domain or under the CC0-1.0-Universal +license, whichever is more permissive.