|
| 1 | +PEP: 791 |
| 2 | +Title: imath --- module for integer-specific mathematics functions |
| 3 | +Author: Sergey B Kirpichev <skirpichev@gmail.com> |
| 4 | +Sponsor: Victor Stinner <vstinner@python.org> |
| 5 | +Discussions-To: Pending |
| 6 | +Status: Draft |
| 7 | +Type: Standards Track |
| 8 | +Created: 12-May-2025 |
| 9 | +Python-Version: 3.15 |
| 10 | +Post-History: `12-Jul-2018 <https://mail.python.org/archives/list/python-ideas@python.org/thread/YYJ5YJBJNCVXQWK5K3WSVNMPUSV56LOR/>`__, |
| 11 | + 02-Jun-2019, |
| 12 | + `09-May-2025 <https://discuss.python.org/t/91337>`__, |
| 13 | + |
| 14 | + |
| 15 | +Abstract |
| 16 | +======== |
| 17 | + |
| 18 | +This PEP proposes a new module for number-theoretical, combinatorial and other |
| 19 | +functions defined for integer arguments, like |
| 20 | +:external+py3.14:func:`math.gcd` or :external+py3.14:func:`math.isqrt`. |
| 21 | + |
| 22 | + |
| 23 | +Motivation |
| 24 | +========== |
| 25 | + |
| 26 | +The :external+py3.14:mod:`math` documentation says: "This module provides access |
| 27 | +to the mathematical functions defined by the C standard." But, |
| 28 | +over time the module was populated with functions that aren't related to |
| 29 | +the C standard or floating-point arithmetics. Now it's much harder to describe |
| 30 | +module scope, content and interfaces (returned values or accepted arguments). |
| 31 | + |
| 32 | +For example, the :external+py3.14:mod:`math` module documentation says: "Except |
| 33 | +when explicitly noted otherwise, all return values are floats." This is no |
| 34 | +longer true: *None* of the functions listed in the `Number-theoretic |
| 35 | +functions <https://docs.python.org/3.14/library/math.html#number-theoretic-functions>`_ |
| 36 | +subsection of the documentation return a float, but the |
| 37 | +documentation doesn't say so. In the documentation for the proposed ``imath`` module the sentence "All |
| 38 | +return values are integers." would be accurate. In a similar way we |
| 39 | +can simplify the description of the accepted arguments for functions in both the |
| 40 | +:external+py3.14:mod:`math` and the new module. |
| 41 | + |
| 42 | +Apparently, the :external+py3.14:mod:`math` module can't serve as a catch-all place |
| 43 | +for mathematical functions since we also have the :external+py3.14:mod:`cmath` and |
| 44 | +:external+py3.14:mod:`statistics` modules. Let's do the same for integer-related |
| 45 | +functions. It provides shared context, which reduces verbosity in the |
| 46 | +documentation and conceptual load. It also aids discoverability through |
| 47 | +grouping related functions and makes IDE suggestions more helpful. |
| 48 | + |
| 49 | +Currently the :external+py3.14:mod:`math` module code in the CPython is around |
| 50 | +4200LOC, from which the new module code is roughly 1/3 (1300LOC). This is |
| 51 | +comparable with the :external+py3.14:mod:`cmath` (1340LOC), which is *not* a |
| 52 | +simple wrapper to the ``libm``, as most functions in the |
| 53 | +:external+py3.14:mod:`math` module. |
| 54 | + |
| 55 | + |
| 56 | +Specification |
| 57 | +============= |
| 58 | + |
| 59 | +The PEP proposes moving the following integer-related functions to a new |
| 60 | +module, called ``imath``: |
| 61 | + |
| 62 | +* :external+py3.14:func:`~math.comb` |
| 63 | +* :external+py3.14:func:`~math.factorial` |
| 64 | +* :external+py3.14:func:`~math.gcd` |
| 65 | +* :external+py3.14:func:`~math.isqrt` |
| 66 | +* :external+py3.14:func:`~math.lcm` |
| 67 | +* :external+py3.14:func:`~math.perm` |
| 68 | + |
| 69 | +Their aliases in :external+py3.14:mod:`math` will be :term:`soft deprecated`. |
| 70 | + |
| 71 | +Module functions will accept integers and objects that implement the |
| 72 | +:external+py3.14:meth:`~object.__index__` method, which is used to convert the |
| 73 | +object to an integer number. Suitable functions must be computed exactly, |
| 74 | +given sufficient time and memory. |
| 75 | + |
| 76 | +Possible extensions for the new module and its scope are discussed in the |
| 77 | +`Open Issues <Open Issues_>`_ section. New functions are not part of this |
| 78 | +proposal. |
| 79 | + |
| 80 | + |
| 81 | +Backwards Compatibility |
| 82 | +======================= |
| 83 | + |
| 84 | +As aliases in :external+py3.14:mod:`math` will be kept for an indefinite time |
| 85 | +(their use would be discouraged), there are no anticipated code breaks. |
| 86 | + |
| 87 | + |
| 88 | +How to Teach This |
| 89 | +================= |
| 90 | + |
| 91 | +The new module will be a place for functions, that 1) accept |
| 92 | +:external+py3.14:class:`int`-like arguments and also return integers, and 2) are |
| 93 | +also in the field of arbitrary-precision integer arithmetic, i.e. have no |
| 94 | +dependency on the platform floating-point format or behaviour and/or on the |
| 95 | +platform math library (``libm``). |
| 96 | + |
| 97 | +For users it would be natural first to look on the |
| 98 | +:external+py3.14:class:`int`'s methods, which cover most basic use-cases (e.g. |
| 99 | +:external+py3.14:meth:`int.bit_length` method), than to some dedicated place in |
| 100 | +the stdlib. |
| 101 | + |
| 102 | + |
| 103 | +Reference Implementation |
| 104 | +======================== |
| 105 | + |
| 106 | +`python/cpython#133909 <https://github.com/python/cpython/pull/133909>`_ |
| 107 | + |
| 108 | + |
| 109 | +Open Issues |
| 110 | +=========== |
| 111 | + |
| 112 | +Module name |
| 113 | +----------- |
| 114 | + |
| 115 | +The chosen name seems consistent with one existing domain-specific mathematical module: |
| 116 | +:external+py3.14:mod:`cmath` (for complex numbers). |
| 117 | + |
| 118 | +We note the `Imath |
| 119 | +<https://github.com/AcademySoftwareFoundation/Imath>`_ C++ library includes |
| 120 | +Python bindings with the same name. There is also an :pypi:`imath` project on |
| 121 | +PyPI, but only with two releases, with the most recent one four years ago. Its |
| 122 | +repository is no longer accessible. |
| 123 | + |
| 124 | +`Polling showed <https://discuss.python.org/t/91337/35>`_ ``intmath`` as another |
| 125 | +popular name. The argument made was that the normal mathematical spelling of |
| 126 | +the imaginary unit is ``i``, which makes ``imath`` ambiguous. It also has no conflict |
| 127 | +with any PyPI module. On the other hand, ``intmath`` may be confused with |
| 128 | +interval math or numerical integration. |
| 129 | + |
| 130 | +Other proposed names include ``ntheory`` (like SymPy's submodule), |
| 131 | +``integermath`` and ``imaths``. |
| 132 | + |
| 133 | + |
| 134 | +Module scope and possible extensions |
| 135 | +------------------------------------ |
| 136 | + |
| 137 | +Unless we can just provide bindings to some well supported mathematical library |
| 138 | +like the GMP, the module scope should be limited. For example, no primality |
| 139 | +testing and factorization, as production-quality implementatons will require a |
| 140 | +decent mathematical background from contributors and belongs rather to |
| 141 | +specialized libraries. |
| 142 | + |
| 143 | +Some possible additions, among those proposed in the initial discussion thread |
| 144 | +(see also issue |
| 145 | +`python/cpython#81313 <https://github.com/python/cpython/issues/81313>`_): |
| 146 | + |
| 147 | +* ``ceil_div()`` --- for integer ceiling divide, see |
| 148 | + `relevant discussion thread <https://discuss.python.org/t/91269>`_. |
| 149 | +* ``gcdext()`` --- to solve linear `Diophantine equation <https://en.wikipedia.org/wiki/Diophantine_equation>`_ in two variables (the |
| 150 | + :external+py3.14:class:`int` implementation actually includes an extended |
| 151 | + Euclidean algorithm) |
| 152 | +* ``isqrt_rem()`` --- to return both an integer square root and a remainder (which is non-zero only if |
| 153 | + the integer isn't a perfect square) |
| 154 | +* ``ilog()`` --- integer logarithm, :external+py3.14:func:`math.log` |
| 155 | + has special handling for integer arguments. It's unique (with respect to other module |
| 156 | + functions) and not documented so far, see issue |
| 157 | + `python/cpython#120950 <https://github.com/python/cpython/issues/120950>`_. |
| 158 | +* ``fibonacci()`` --- `Fibonacci sequence <https://en.wikipedia.org/wiki/Fibonacci_sequence>`_. |
| 159 | + |
| 160 | + |
| 161 | +Rejected ideas |
| 162 | +============== |
| 163 | + |
| 164 | +There was a brief discussion about exposing :external+py3.14:func:`math.isqrt` |
| 165 | +as ``imath.sqrt`` in the same way that :external+py3.14:func:`cmath.sqrt` is |
| 166 | +the complex version of :external+py3.14:func:`math.sqrt`. However, ``isqrt`` |
| 167 | +is ultimately a different function: it is the floor of the square root. It |
| 168 | +would be confusing to give it the same name (under a different module). |
| 169 | + |
| 170 | + |
| 171 | +Acknowledgements |
| 172 | +================ |
| 173 | + |
| 174 | +Thanks to Tim Peters for reviving the idea of splitting the :external+py3.14:mod:`math` |
| 175 | +module. Thanks to Neil Girdhar for substantial improvements of |
| 176 | +the initial draft. |
| 177 | + |
| 178 | + |
| 179 | +Copyright |
| 180 | +========= |
| 181 | + |
| 182 | +This document is placed in the public domain or under the |
| 183 | +CC0-1.0-Universal license, whichever is more permissive. |
0 commit comments