Permalink
Cannot retrieve contributors at this time
339 lines (250 sloc)
13.5 KB
| PEP: 237 | |
| Title: Unifying Long Integers and Integers | |
| Version: $Revision$ | |
| Last-Modified: $Date$ | |
| Author: Moshe Zadka, Guido van Rossum | |
| Status: Final | |
| Type: Standards Track | |
| Content-Type: text/x-rst | |
| Created: 11-Mar-2001 | |
| Python-Version: 2.2 | |
| Post-History: 16-Mar-2001, 14-Aug-2001, 23-Aug-2001 | |
| Abstract | |
| ======== | |
| Python currently distinguishes between two kinds of integers (ints): regular | |
| or short ints, limited by the size of a C long (typically 32 or 64 bits), and | |
| long ints, which are limited only by available memory. When operations on | |
| short ints yield results that don't fit in a C long, they raise an error. | |
| There are some other distinctions too. This PEP proposes to do away with most | |
| of the differences in semantics, unifying the two types from the perspective | |
| of the Python user. | |
| Rationale | |
| ========= | |
| Many programs find a need to deal with larger numbers after the fact, and | |
| changing the algorithms later is bothersome. It can hinder performance in the | |
| normal case, when all arithmetic is performed using long ints whether or not | |
| they are needed. | |
| Having the machine word size exposed to the language hinders portability. For | |
| examples Python source files and .pyc's are not portable between 32-bit and | |
| 64-bit machines because of this. | |
| There is also the general desire to hide unnecessary details from the Python | |
| user when they are irrelevant for most applications. An example is memory | |
| allocation, which is explicit in C but automatic in Python, giving us the | |
| convenience of unlimited sizes on strings, lists, etc. It makes sense to | |
| extend this convenience to numbers. | |
| It will give new Python programmers (whether they are new to programming in | |
| general or not) one less thing to learn before they can start using the | |
| language. | |
| Implementation | |
| ============== | |
| Initially, two alternative implementations were proposed (one by each author): | |
| 1. The ``PyInt`` type's slot for a C long will be turned into a:: | |
| union { | |
| long i; | |
| struct { | |
| unsigned long length; | |
| digit digits[1]; | |
| } bignum; | |
| }; | |
| Only the ``n-1`` lower bits of the ``long`` have any meaning; the top bit | |
| is always set. This distinguishes the ``union``. All ``PyInt`` functions | |
| will check this bit before deciding which types of operations to use. | |
| 2. The existing short and long int types remain, but operations return | |
| a long int instead of raising ``OverflowError`` when a result cannot be | |
| represented as a short int. A new type, ``integer``, may be introduced | |
| that is an abstract base type of which both the ``int`` and ``long`` | |
| implementation types are subclassed. This is useful so that programs can | |
| check integer-ness with a single test:: | |
| if isinstance(i, integer): ... | |
| After some consideration, the second implementation plan was selected, since | |
| it is far easier to implement, is backwards compatible at the C API level, and | |
| in addition can be implemented partially as a transitional measure. | |
| Incompatibilities | |
| ================= | |
| The following operations have (usually subtly) different semantics for short | |
| and for long integers, and one or the other will have to be changed somehow. | |
| This is intended to be an exhaustive list. If you know of any other operation | |
| that differ in outcome depending on whether a short or a long int with the same | |
| value is passed, please write the second author. | |
| - Currently, all arithmetic operators on short ints except ``<<`` raise | |
| ``OverflowError`` if the result cannot be represented as a short int. This | |
| will be changed to return a long int instead. The following operators can | |
| currently raise ``OverflowError``: ``x+y``, ``x-y``, ``x*y``, ``x**y``, | |
| ``divmod(x, y)``, ``x/y``, ``x%y``, and ``-x``. (The last four can only | |
| overflow when the value ``-sys.maxint-1`` is involved.) | |
| - Currently, ``x<<n`` can lose bits for short ints. This will be changed to | |
| return a long int containing all the shifted-out bits, if returning a short | |
| int would lose bits (where changing sign is considered a special case of | |
| losing bits). | |
| - Currently, hex and oct literals for short ints may specify negative values; | |
| for example ``0xffffffff == -1`` on a 32-bit machine. This will be changed | |
| to equal ``0xffffffffL`` (``2**32-1``). | |
| - Currently, the ``%u``, ``%x``, ``%X`` and ``%o`` string formatting operators | |
| and the ``hex()`` and ``oct()`` built-in functions behave differently for | |
| negative numbers: negative short ints are formatted as unsigned C long, | |
| while negative long ints are formatted with a minus sign. This will be | |
| changed to use the long int semantics in all cases (but without the trailing | |
| *L* that currently distinguishes the output of ``hex()`` and ``oct()`` for | |
| long ints). Note that this means that ``%u`` becomes an alias for ``%d``. | |
| It will eventually be removed. | |
| - Currently, ``repr()`` of a long int returns a string ending in *L* while | |
| ``repr()`` of a short int doesn't. The *L* will be dropped; but not before | |
| Python 3.0. | |
| - Currently, an operation with long operands will never return a short int. | |
| This *may* change, since it allows some optimization. (No changes have been | |
| made in this area yet, and none are planned.) | |
| - The expression ``type(x).__name__`` depends on whether *x* is a short or a | |
| long int. Since implementation alternative 2 is chosen, this difference | |
| will remain. (In Python 3.0, we *may* be able to deploy a trick to hide the | |
| difference, because it *is* annoying to reveal the difference to user code, | |
| and more so as the difference between the two types is less visible.) | |
| - Long and short ints are handled different by the ``marshal`` module, and by | |
| the ``pickle`` and ``cPickle`` modules. This difference will remain (at | |
| least until Python 3.0). | |
| - Short ints with small values (typically between -1 and 99 inclusive) are | |
| *interned* -- whenever a result has such a value, an existing short int with | |
| the same value is returned. This is not done for long ints with the same | |
| values. This difference will remain. (Since there is no guarantee of this | |
| interning, it is debatable whether this is a semantic difference -- but code | |
| may exist that uses ``is`` for comparisons of short ints and happens to work | |
| because of this interning. Such code may fail if used with long ints.) | |
| Literals | |
| ======== | |
| A trailing *L* at the end of an integer literal will stop having any | |
| meaning, and will be eventually become illegal. The compiler will choose the | |
| appropriate type solely based on the value. (Until Python 3.0, it will force | |
| the literal to be a long; but literals without a trailing *L* may also be | |
| long, if they are not representable as short ints.) | |
| Built-in Functions | |
| ================== | |
| The function ``int()`` will return a short or a long int depending on the | |
| argument value. In Python 3.0, the function ``long()`` will call the function | |
| ``int()``; before then, it will continue to force the result to be a long int, | |
| but otherwise work the same way as ``int()``. The built-in name ``long`` will | |
| remain in the language to represent the long implementation type (unless it is | |
| completely eradicated in Python 3.0), but using the ``int()`` function is | |
| still recommended, since it will automatically return a long when needed. | |
| C API | |
| ===== | |
| The C API remains unchanged; C code will still need to be aware of the | |
| difference between short and long ints. (The Python 3.0 C API will probably | |
| be completely incompatible.) | |
| The ``PyArg_Parse*()`` APIs already accept long ints, as long as they are | |
| within the range representable by C ints or longs, so that functions taking C | |
| int or long argument won't have to worry about dealing with Python longs. | |
| Transition | |
| ========== | |
| There are three major phases to the transition: | |
| 1. Short int operations that currently raise ``OverflowError`` return a long | |
| int value instead. This is the only change in this phase. Literals will | |
| still distinguish between short and long ints. The other semantic | |
| differences listed above (including the behavior of ``<<``) will remain. | |
| Because this phase only changes situations that currently raise | |
| ``OverflowError``, it is assumed that this won't break existing code. | |
| (Code that depends on this exception would have to be too convoluted to be | |
| concerned about it.) For those concerned about extreme backwards | |
| compatibility, a command line option (or a call to the warnings module) | |
| will allow a warning or an error to be issued at this point, but this is | |
| off by default. | |
| 2. The remaining semantic differences are addressed. In all cases the long | |
| int semantics will prevail. Since this will introduce backwards | |
| incompatibilities which will break some old code, this phase may require a | |
| future statement and/or warnings, and a prolonged transition phase. The | |
| trailing *L* will continue to be used for longs as input and by | |
| ``repr()``. | |
| A. Warnings are enabled about operations that will change their numeric | |
| outcome in stage 2B, in particular ``hex()`` and ``oct()``, ``%u``, | |
| ``%x``, ``%X`` and ``%o``, ``hex`` and ``oct`` literals in the | |
| (inclusive) range ``[sys.maxint+1, sys.maxint*2+1]``, and left shifts | |
| losing bits. | |
| B. The new semantic for these operations are implemented. Operations that | |
| give different results than before will *not* issue a warning. | |
| 3. The trailing *L* is dropped from ``repr()``, and made illegal on input. | |
| (If possible, the ``long`` type completely disappears.) The trailing *L* | |
| is also dropped from ``hex()`` and ``oct()``. | |
| Phase 1 will be implemented in Python 2.2. | |
| Phase 2 will be implemented gradually, with 2A in Python 2.3 and 2B in | |
| Python 2.4. | |
| Phase 3 will be implemented in Python 3.0 (at least two years after Python 2.4 | |
| is released). | |
| OverflowWarning | |
| =============== | |
| Here are the rules that guide warnings generated in situations that currently | |
| raise ``OverflowError``. This applies to transition phase 1. Historical | |
| note: despite that phase 1 was completed in Python 2.2, and phase 2A in Python | |
| 2.3, nobody noticed that OverflowWarning was still generated in Python 2.3. | |
| It was finally disabled in Python 2.4. The Python builtin | |
| ``OverflowWarning``, and the corresponding C API ``PyExc_OverflowWarning``, | |
| are no longer generated or used in Python 2.4, but will remain for the | |
| (unlikely) case of user code until Python 2.5. | |
| - A new warning category is introduced, ``OverflowWarning``. This is a | |
| built-in name. | |
| - If an int result overflows, an ``OverflowWarning`` warning is issued, with a | |
| message argument indicating the operation, e.g. "integer addition". This | |
| may or may not cause a warning message to be displayed on ``sys.stderr``, or | |
| may cause an exception to be raised, all under control of the ``-W`` command | |
| line and the warnings module. | |
| - The ``OverflowWarning`` warning is ignored by default. | |
| - The ``OverflowWarning`` warning can be controlled like all warnings, via the | |
| ``-W`` command line option or via the ``warnings.filterwarnings()`` call. | |
| For example:: | |
| python -Wdefault::OverflowWarning | |
| cause the ``OverflowWarning`` to be displayed the first time it occurs at a | |
| particular source line, and:: | |
| python -Werror::OverflowWarning | |
| cause the ``OverflowWarning`` to be turned into an exception whenever it | |
| happens. The following code enables the warning from inside the program:: | |
| import warnings | |
| warnings.filterwarnings("default", "", OverflowWarning) | |
| See the python ``man`` page for the ``-W`` option and the ``warnings`` | |
| module documentation for ``filterwarnings()``. | |
| - If the ``OverflowWarning`` warning is turned into an error, | |
| ``OverflowError`` is substituted. This is needed for backwards | |
| compatibility. | |
| - Unless the warning is turned into an exceptions, the result of the operation | |
| (e.g., ``x+y``) is recomputed after converting the arguments to long ints. | |
| Example | |
| ======= | |
| If you pass a long int to a C function or built-in operation that takes an | |
| integer, it will be treated the same as a short int as long as the value fits | |
| (by virtue of how ``PyArg_ParseTuple()`` is implemented). If the long value | |
| doesn't fit, it will still raise an ``OverflowError``. For example:: | |
| def fact(n): | |
| if n <= 1: | |
| return 1 | |
| return n*fact(n-1) | |
| A = "ABCDEFGHIJKLMNOPQ" | |
| n = input("Gimme an int: ") | |
| print A[fact(n)%17] | |
| For ``n >= 13``, this currently raises ``OverflowError`` (unless the user | |
| enters a trailing *L* as part of their input), even though the calculated | |
| index would always be in ``range(17)``. With the new approach this code will | |
| do the right thing: the index will be calculated as a long int, but its value | |
| will be in range. | |
| Resolved Issues | |
| =============== | |
| These issues, previously open, have been resolved. | |
| - ``hex()`` and ``oct()`` applied to longs will continue to produce a trailing | |
| *L* until Python 3000. The original text above wasn't clear about this, | |
| but since it didn't happen in Python 2.4 it was thought better to leave it | |
| alone. BDFL pronouncement here: | |
| https://mail.python.org/pipermail/python-dev/2006-June/065918.html | |
| - What to do about ``sys.maxint``? Leave it in, since it is still relevant | |
| whenever the distinction between short and long ints is still relevant (e.g. | |
| when inspecting the type of a value). | |
| - Should we remove ``%u`` completely? Remove it. | |
| - Should we warn about ``<<`` not truncating integers? Yes. | |
| - Should the overflow warning be on a portable maximum size? No. | |
| Implementation | |
| ============== | |
| The implementation work for the Python 2.x line is completed; phase 1 was | |
| released with Python 2.2, phase 2A with Python 2.3, and phase 2B will be | |
| released with Python 2.4 (and is already in CVS). | |
| Copyright | |
| ========= | |
| This document has been placed in the public domain. | |
| .. | |
| Local Variables: | |
| mode: indented-text | |
| indent-tabs-mode: nil | |
| End: |