Permalink
Cannot retrieve contributors at this time
237 lines (176 sloc)
8.27 KB
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
peps/pep-0242.txt
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| PEP: 242 | |
| Title: Numeric Kinds | |
| Author: Paul F. Dubois <paul@pfdubois.com> | |
| Status: Rejected | |
| Type: Standards Track | |
| Content-Type: text/x-rst | |
| Created: 17-Mar-2001 | |
| Python-Version: 2.2 | |
| Post-History: 17-Apr-2001 | |
| Abstract | |
| ======== | |
| This proposal gives the user optional control over the precision | |
| and range of numeric computations so that a computation can be | |
| written once and run anywhere with at least the desired precision | |
| and range. It is backward compatible with existing code. The | |
| meaning of decimal literals is clarified. | |
| Rationale | |
| ========= | |
| Currently it is impossible in every language except Fortran 90 to | |
| write a program in a portable way that uses floating point and | |
| gets roughly the same answer regardless of platform -- or refuses | |
| to compile if that is not possible. Python currently has only one | |
| floating point type, equal to a C double in the C implementation. | |
| No type exists corresponding to single or quad floats. It would | |
| complicate the language to try to introduce such types directly | |
| and their subsequent use would not be portable. This proposal is | |
| similar to the Fortran 90 "kind" solution, adapted to the Python | |
| environment. With this facility an entire calculation can be | |
| switched from one level of precision to another by changing a | |
| single line. If the desired precision does not exist on a | |
| particular machine, the program will fail rather than get the | |
| wrong answer. Since coding in this style would involve an early | |
| call to the routine that will fail, this is the next best thing to | |
| not compiling. | |
| Supported Kinds of Ints and Floats | |
| ================================== | |
| Complex numbers are treated separately below, since Python can be | |
| built without them. | |
| Each Python compiler may define as many "kinds" of integer and | |
| floating point numbers as it likes, except that it must support at | |
| least two kinds of integer corresponding to the existing int and | |
| long, and must support at least one kind of floating point number, | |
| equivalent to the present float. | |
| The range and precision of these required kinds are processor | |
| dependent, as at present, except for the "long integer" kind, | |
| which can hold an arbitrary integer. | |
| The built-in functions ``int()``, ``long()``, and ``float()`` convert inputs | |
| to these default kinds as they do at present. (Note that a | |
| Unicode string is actually a different "kind" of string and that a | |
| sufficiently knowledgeable person might be able to expand this PEP | |
| to cover that case.) | |
| Within each type (integer, floating) the compiler supports a | |
| linearly-ordered set of kinds, with the ordering determined by the | |
| ability to hold numbers of an increased range and/or precision. | |
| Kind Objects | |
| ============ | |
| Two new standard functions are defined in a module named "kinds". | |
| They return callable objects called kind objects. Each int or | |
| floating kind object f has the signature ``result = f(x)``, and each | |
| complex kind object has the signature ``result = f(x, y=0.)``. | |
| ``int_kind(n)`` | |
| For an integer argument ``n >= 1``, return a callable object whose | |
| result is an integer kind that will hold an integer number in | |
| the open interval (``-10**n``, ``10**n``). The kind object accepts | |
| arguments that are integers including longs. If ``n == 0``, | |
| returns the kind object corresponding to the Python literal 0. | |
| ``float_kind(nd, n)`` | |
| For ``nd >= 0`` and ``n >= 1``, return a callable object whose result | |
| is a floating point kind that will hold a floating-point | |
| number with at least nd digits of precision and a base-10 | |
| exponent in the closed interval ``[-n, n]``. The kind object | |
| accepts arguments that are integer or float. | |
| If nd and n are both zero, returns the kind object | |
| corresponding to the Python literal 0.0. | |
| The compiler will return a kind object corresponding to the least | |
| of its available set of kinds for that type that has the desired | |
| properties. If no kind with the desired qualities exists in a | |
| given implementation an ``OverflowError`` exception is thrown. A kind | |
| function converts its argument to the target kind, but if the | |
| result does not fit in the target kind's range, an ``OverflowError`` | |
| exception is thrown. | |
| Besides their callable behavior, kind objects have attributes | |
| giving the traits of the kind in question. | |
| 1. ``name`` is the name of the kind. The standard kinds are called | |
| int, long, double. | |
| 2. ``typecode`` is a single-letter string that would be appropriate | |
| for use with ``Numeric`` or module ``array`` to form an array of this | |
| kind. The standard types' typecodes are 'i', 'O', 'd' | |
| respectively. | |
| 3. Integer kinds have these additional attributes: ``MAX``, equal to | |
| the maximum permissible integer of this kind, or ``None`` for the | |
| long kind. ``MIN``, equal to the most negative permissible integer | |
| of this kind, or ``None`` for the long kind. | |
| 4. Float kinds have these additional attributes whose properties | |
| are equal to the corresponding value for the corresponding C | |
| type in the standard header file "float.h". ``MAX``, ``MIN``, ``DIG``, | |
| ``MANT_DIG``, ``EPSILON``, ``MAX_EXP``, ``MAX_10_EXP``, ``MIN_EXP``, | |
| ``MIN_10_EXP``, ``RADIX``, ``ROUNDS`` | |
| (== ``FLT_RADIX``, ``FLT_ROUNDS`` in float.h). These | |
| values are of type integer except for ``MAX``, ``MIN``, and ``EPSILON``, | |
| which are of the Python floating type to which the kind | |
| corresponds. | |
| Attributes of Module kinds | |
| ========================== | |
| ``int_kinds`` is a list of the available integer kinds, sorted from lowest | |
| to highest kind. By definition, ``int_kinds[-1]`` is the long kind. | |
| ``float_kinds`` is a list of the available floating point kinds, sorted | |
| from lowest to highest kind. | |
| ``default_int_kind`` is the kind object corresponding to the Python | |
| literal 0 | |
| ``default_long_kind`` is the kind object corresponding to the Python | |
| literal 0L | |
| ``default_float_kind`` is the kind object corresponding to the Python | |
| literal 0.0 | |
| Complex Numbers | |
| =============== | |
| If supported, complex numbers have real and imaginary parts that | |
| are floating-point numbers with the same kind. A Python compiler | |
| must support a complex analog of each floating point kind it | |
| supports, if it supports complex numbers at all. | |
| If complex numbers are supported, the following are available in | |
| module kinds: | |
| ``complex_kind(nd, n)`` | |
| Return a callable object whose result is a complex kind that | |
| will hold a complex number each of whose components (.real, | |
| .imag) is of kind ``float_kind(nd, n)``. The kind object will | |
| accept one argument that is of any integer, real, or complex | |
| kind, or two arguments, each integer or real. | |
| ``complex_kinds`` is a list of the available complex kinds, sorted | |
| from lowest to highest kind. | |
| ``default_complex_kind`` is the kind object corresponding to the | |
| Python literal 0.0j. The name of this kind | |
| is doublecomplex, and its typecode is 'D'. | |
| Complex kind objects have these addition attributes: | |
| ``floatkind`` is the kind object of the corresponding float type. | |
| Examples | |
| ======== | |
| In module myprecision.py:: | |
| import kinds | |
| tinyint = kinds.int_kind(1) | |
| single = kinds.float_kind(6, 90) | |
| double = kinds.float_kind(15, 300) | |
| csingle = kinds.complex_kind(6, 90) | |
| In the rest of my code:: | |
| from myprecision import tinyint, single, double, csingle | |
| n = tinyint(3) | |
| x = double(1.e20) | |
| z = 1.2 | |
| # builtin float gets you the default float kind, properties unknown | |
| w = x * float(x) | |
| # but in the following case we know w has kind "double". | |
| w = x * double(z) | |
| u = csingle(x + z * 1.0j) | |
| u2 = csingle(x+z, 1.0) | |
| Note how that entire code can then be changed to a higher | |
| precision by changing the arguments in myprecision.py. | |
| Comment: note that you aren't promised that single != double; but | |
| you are promised that ``double(1.e20)`` will hold a number with 15 | |
| decimal digits of precision and a range up to ``10**300`` or that the | |
| ``float_kind`` call will fail. | |
| Open Issues | |
| =========== | |
| No open issues have been raised at this time. | |
| Rejection | |
| ========= | |
| This PEP has been closed by the author. The kinds module will not | |
| be added to the standard library. | |
| There was no opposition to the proposal but only mild interest in | |
| using it, not enough to justify adding the module to the standard | |
| library. Instead, it will be made available as a separate | |
| distribution item at the Numerical Python site. At the next | |
| release of Numerical Python, it will no longer be a part of the | |
| Numeric distribution. | |
| Copyright | |
| ========= | |
| This document has been placed in the public domain. |