[PYTHON MATRIX-SIG] Type Coercion

Konrad HINSEN hinsenk@ere.umontreal.ca
Wed, 7 Feb 1996 16:36:58 -0500


   Python has only one floating point type, call this a PyFloat.
   Internally, these numbers store their data using C doubles.  However,
   the standard C interface to PyFloats allows them to be extracted into
   either a C float or a C double (PyArg_ParseTuple), so its not clear
   that a PyFloat should really be considered either a float or a double.

The association of PyFloats with C floats exists only in the C
interface, presumably to facilitate interfacing to existing C code. No
part of the standard language makes use of it, and to an average
Python user PyFloat are definitely C doubles.

   Three things can happen:

   1) Return an array of floats (possible undesired loss of precision)
   2) Return an array of doubles (possible undesired gain of precision)
   3) Raise an exception (very annoying to the user)

The potential problems in 1) and 2) are also very annoying to the
user!

   This particular problem could be eliminated by having a_float[0]
   return a 0d array of floats with a single element.  Perhaps this is
   worth considering.

I don't see any serious problem with that. Most Python code will work
just as well with an array of rank 0 as with a scalar. Only code that
does explicit type checks will have to take care of the
difference. And explicit conversion would always be possible using the
standard conversion functions.

   Personally I would prefer to use method 1, combined with the major
   change to the existing system that scalars are returned as 0d arrays,
   not as python scalars.

Personally I see this as the least desirable option, my preference
being in the order 3) 2) 1). My argument is again the principle
of least surprise: if something unexpected is going to happen,
I prefer it to be
1) an exception
2) a loss in efficiency
3) a loss in accuracy.
in that order.


Let me propose another solution, fully knowing that Guido might
throw a 16-ton weight at me:

Suppose we modify the Python float object by adding a flag "single
precision". This flag would be set if either
1) A constant is created that can be represented in a C float
   (such as 0.5).
2) A constant is created with a special suffix like 'S'
   (to be used for low-precision constants with no exact
   binary representation, such as 0.1, if precision doesn't
   matter).
3) When a PyFloat is generated as a rank-0 float array.
4) Possibly as the result of an explicit conversion to a
   "low precision scalar", if that turns out to be useful.

The default behaviour of PyFloats would not change at all, and so
there are no compatibility problems. Any result of a scalar operation
would not have the flag set, of course. There is also no significant
speed penalty, since only the creation of a constant becomes more
involved, and that happens at compile time. The only price to pay
would be an increase in the size of a float object.

The only place where the new flag would matter is in coercion to an
array object. It should take care of most the problems of method 2),
which after all is the most common coercion convention in programming
languages. Unwanted promotion to double can still occur in situations
such as
   2.*pi*array([1.,2.,3.], Float(32)),
because 2.*pi would be "non-degradable" even if pi was, because
it is the result of a scalar operation. But such standard cases
can be handled by something like
  twopi = short_float(2.*pi),
where short_float() is the conversion function mentioned above.

To help pinning down unwanted coercion to double, one could further
offer some option that raises an exception for such operations. This
would have the status of a debugging aid rather than a language
feature and could, for example, be activated by a command line switch.

-------------------------------------------------------------------------------
Konrad Hinsen                     | E-Mail: hinsenk@ere.umontreal.ca
Departement de chimie             | Tel.: +1-514-343-6111 ext. 3953
Universite de Montreal            | Fax:  +1-514-343-7586
C.P. 6128, succ. Centre-Ville     | Deutsch/Esperanto/English/Nederlands/
Montreal (QC) H3C 3J7             | Francais (phase experimentale)
-------------------------------------------------------------------------------

=================
MATRIX-SIG  - SIG on Matrix Math for Python

send messages to: matrix-sig@python.org
administrivia to: matrix-sig-request@python.org
=================