[Python-Dev] [Very Long (11K)] Numeric PEPs, first public posts
Moshe Zadka
moshez@zadka.site.co.il
Fri, 16 Mar 2001 15:18:43 +0200
After the brouhaha at IPC9, it was decided that while PEP-0228 should stay
as a possible goal, there should be more concrete PEPs suggesting specific
changes in Python numerical model, with implementation suggestions and
migration paths fleshed out. So, there are four new PEPs now, all proposing
changes to Python's numeric model. There are some connections between them,
but each is supposed to be accepted or rejected according to its own merits.
To facilitate discussion, I'm including copies of the PEPs concerned
(for reference purposes, these are PEPs 0237-0240, and the latest public
version is always in the Python CVS under non-dist/peps/ . A reasonably
up to date version is linked from http://python.sourceforge.net)
Please direct all future discussion to python-numerics@lists.sourceforge.net
This list has been especially set-up to discuss those subjects.
PEP: 237
Title: Unifying Long Integers and Integers
Version: $Revision: 1.2 $
Author: pep@zadka.site.co.il (Moshe Zadka)
Status: Draft
Type: Standards Track
Created: 11-Mar-2001
Python-Version: 2.2
Post-History:
Abstract
Python has both integers (machine word size integral) types, and
long integers (unbounded integral) types. When integers
operations overflow the machine registers, they raise an error.
This PEP proposes to do away with the distinction, and unify the
types from the perspective of both the Python interpreter and the
C API.
Rationale
Having the machine word size exposed to the language hinders
portability. For examples Python source files and .pyc's are not
portable because of this. Many programs find a need to deal with
larger numbers after the fact, and changing the algorithms later
is not only bothersome, but hinders performance in the normal
case.
Literals
A trailing 'L' at the end of an integer literal will stop having
any meaning, and will be eventually phased out. This will be done
using warnings when encountering such literals. The warning will
be off by default in Python 2.2, on for 12 months, which will
probably mean Python 2.3 and 2.4, and then will no longer be
supported.
Builtin Functions
The function long() will call the function int(), issuing a
warning. The warning will be off in 2.2, and on for two revisions
before removing the function. A FAQ will be added to explain that
a solutions for old modules are:
long=int
at the top of the module, or:
import __builtin__
__builtin__.long=int
In site.py.
C API
All PyLong_As* will call PyInt_As*. If PyInt_As* does not exist,
it will be added. Similarly for PyLong_From*. A similar path of
warnings as for the Python builtins will be followed.
Overflows
When an arithmetic operation on two numbers whose internal
representation is as machine-level integers returns something
whose internal representation is a bignum, a warning which is
turned off by default will be issued. This is only a debugging
aid, and has no guaranteed semantics.
Implementation
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.
Jython Issues
Jython will have a PyInt interface which is implemented by both
from PyFixNum and PyBigNum.
Open Issues
What to do about sys.maxint?
What to do about PyInt_AS_LONG failures?
What do do about %u, %o, %x formatting operators?
How to warn about << not cutting integers?
Should the overflow warning be on a portable maximum size?
Will unification of types and classes help with a more straightforward
implementations?
Copyright
This document has been placed in the public domain.
PEP: 238
Title: Non-integer Division
Version: $Revision: 1.1 $
Author: pep@zadka.site.co.il (Moshe Zadka)
Status: Draft
Type: Standards Track
Created: 11-Mar-2001
Python-Version: 2.2
Post-History:
Abstract
Dividing integers currently returns the floor of the quantities.
This behavior is known as integer division, and is similar to what
C and FORTRAN do. This has the useful property that all
operations on integers return integers, but it does tend to put a
hump in the learning curve when new programmers are surprised that
1/2 == 0
This proposal shows a way to change this while keeping backward
compatibility issues in mind.
Rationale
The behavior of integer division is a major stumbling block found
in user testing of Python. This manages to trip up new
programmers regularly and even causes the experienced programmer
to make the occasional mistake. The workarounds, like explicitly
coercing one of the operands to float or use a non-integer
literal, are very non-intuitive and lower the readability of the
program.
// Operator
A `//' operator which will be introduced, which will call the
nb_intdivide or __intdiv__ slots. This operator will be
implemented in all the Python numeric types, and will have the
semantics of
a // b == floor(a/b)
Except that the type of a//b will be the type a and b will be
coerced into. Specifically, if a and b are of the same type, a//b
will be of that type too.
Changing the Semantics of the / Operator
The nb_divide slot on integers (and long integers, if these are a
separate type, but see PEP 237[1]) will issue a warning when given
integers a and b such that
a % b != 0
The warning will be off by default in the 2.2 release, and on by
default for in the next Python release, and will stay in effect
for 24 months. The next Python release after 24 months, it will
implement
(a/b) * b = a (more or less)
The type of a/b will be either a float or a rational, depending on
other PEPs[2, 3].
__future__
A special opcode, FUTURE_DIV will be added that does the
equivalent of:
if type(a) in (types.IntType, types.LongType):
if type(b) in (types.IntType, types.LongType):
if a % b != 0:
return float(a)/b
return a/b
(or rational(a)/b, depending on whether 0.5 is rational or float).
If "from __future__ import non_integer_division" is present in the
module, until the IntType nb_divide is changed, the "/" operator
is compiled to FUTURE_DIV.
Open Issues
Should the // operator be renamed to "div"?
References
[1] PEP 237, Unifying Long Integers and Integers, Zadka,
http://python.sourceforge.net/peps/pep-0237.html
[2] PEP 239, Adding a Rational Type to Python, Zadka,
http://python.sourceforge.net/peps/pep-0239.html
[3] PEP 240, Adding a Rational Literal to Python, Zadka,
http://python.sourceforge.net/peps/pep-0240.html
Copyright
This document has been placed in the public domain.
PEP: 239
Title: Adding a Rational Type to Python
Version: $Revision: 1.1 $
Author: pep@zadka.site.co.il (Moshe Zadka)
Status: Draft
Type: Standards Track
Created: 11-Mar-2001
Python-Version: 2.2
Post-History:
Abstract
Python has no numeric type with the semantics of an unboundedly
precise rational number. This proposal explains the semantics of
such a type, and suggests builtin functions and literals to
support such a type. This PEP suggests no literals for rational
numbers; that is left for another PEP[1].
Rationale
While sometimes slower and more memory intensive (in general,
unboundedly so) rational arithmetic captures more closely the
mathematical ideal of numbers, and tends to have behavior which is
less surprising to newbies. Though many Python implementations of
rational numbers have been written, none of these exist in the
core, or are documented in any way. This has made them much less
accessible to people who are less Python-savvy.
RationalType
There will be a new numeric type added called RationalType. Its
unary operators will do the obvious thing. Binary operators will
coerce integers and long integers to rationals, and rationals to
floats and complexes.
The following attributes will be supported: .numerator and
.denominator. The language definition will not define these other
then that:
r.denominator * r == r.numerator
In particular, no guarantees are made regarding the GCD or the
sign of the denominator, even though in the proposed
implementation, the GCD is always 1 and the denominator is always
positive.
The method r.trim(max_denominator) will return the closest
rational s to r such that abs(s.denominator) <= max_denominator.
The rational() Builtin
This function will have the signature rational(n, d=1). n and d
must both be integers, long integers or rationals. A guarantee is
made that
rational(n, d) * d == n
References
[1] PEP 240, Adding a Rational Literal to Python, Zadka,
http://python.sourceforge.net/peps/pep-0240.html
Copyright
This document has been placed in the public domain.
PEP: 240
Title: Adding a Rational Literal to Python
Version: $Revision: 1.1 $
Author: pep@zadka.site.co.il (Moshe Zadka)
Status: Draft
Type: Standards Track
Created: 11-Mar-2001
Python-Version: 2.2
Post-History:
Abstract
A different PEP[1] suggests adding a builtin rational type to
Python. This PEP suggests changing the ddd.ddd float literal to a
rational in Python, and modifying non-integer division to return
it.
Rationale
Rational numbers are useful, and are much harder to use without
literals. Making the "obvious" non-integer type one with more
predictable semantics will surprise new programmers less then
using floating point numbers.
Proposal
Literals conforming to the regular expression '\d*.\d*' will be
rational numbers.
Backwards Compatibility
The only backwards compatible issue is the type of literals
mentioned above. The following migration is suggested:
1. "from __future__ import rational_literals" will cause all such
literals to be treated as rational numbers.
2. Python 2.2 will have a warning, turned off by default, about
such literals in the absence of a __future__ statement. The
warning message will contain information about the __future__
statement, and indicate that to get floating point literals,
they should be suffixed with "e0".
3. Python 2.3 will have the warning turned on by default. This
warning will stay in place for 24 months, at which time the
literals will be rationals and the warning will be removed.
References
[1] PEP 239, Adding a Rational Type to Python, Zadka,
http://python.sourceforge.net/peps/pep-0239.html
Copyright
This document has been placed in the public domain.