[PEP draft 2] Adding new math operators

Tim Hochberg tim.hochberg at ieee.org
Wed Aug 9 17:24:37 EDT 2000


hzhu at localhost.localdomain (Huaiyu Zhu) writes:

> On 09 Aug 2000 20:54:19 +0200, Konrad Hinsen <hinsen at cnrs-orleans.fr> wrote:
> >hzhu at localhost.localdomain (Huaiyu Zhu) writes:
> >
> >> The more I think about this approach, the more uncertainties it presents. 
> >> It
> >
> >What uncertainties? In the variety that I have described, It's
> >basically NumPy and MatPy, much as they are today, with a more
> >efficient interconversion.
> 
> It's uncertainty about the "more efficient interconversion".  Try
> 
> def E(self): 
> 
> and give it a few test examples including numbers, arrays and matrices.
> 
> If you mean adding .E to numbers in the core, then that's a big change,
> certainly not as they are today.  It does require a design that specifies
> all the effects, like what I listed: 2==(2).E?  2 is (2).E?  And many more.
> I haven't seen any complete description of this kind, but I'm not saying it
> can't be done. If someone describes it then the uncertainties go away.

I'm out of love with the ~+ notation, so I'd like to see more serious
discussion of the .E notation. However, there hasn't been a formal or
even an informal attempt at describing how it would work, particularly
at the edges. I'm going to put a very informal description below in
the hope that it'll help the discussion along.

0) NumPy / MatPy arrays perform elementwise / matrixwise operations
   when acted on with (*,+, etc.).

1) a.E / e.A return a NumPy / MatPy array. (*)

2) c * d, works when the types (MatPy / NumPy) match. If they do not
          match, an exception is raised.

2a) If either c or d is a scalar (python float/int/complex or rank 0 array),
    it is converted to the type of the other operand without complaint.

3a) If c or d is a convertable python type (e.g., a tuple) it is
    converted without complaint. This is necessary for NumPy 
    compatability.(**)

(*) The other option, shadow classes, seems to lead to a much more
    complex setup. 

(**) I suppose MatPy could do this differently if it wanted, all that
     is required is that, for example, E + (1,2,3) work when E is a 
     NumPy array.

That's it for rules right now. I'm sure these have some problems, but
perhaps they can be built into something more useful. The viability of
this approach probably depends on how much, in practice, elementwise
and matrixwise computations are mixed. In my experience, not much, but
that's just me.

There has been some critisism of this approach on the basis that
inside a function one doesn't know what types are passed in. I think
this is a smaller problem than it has been presented as. If the
function in question is not a small, throwaway function, then it is
both useful and easy to check or coerce the arguments at the top of
the function. For example:

def frobulate(A, B, C):
   A, B, C = A.E, B.E, C.E # I like working elementwise.
   # ....

or better still:

def fribbinate(A, B, C):
   A, B, C = asarray(A, Float), asarray(B, Float), asarray(C, Float)
   #....

The second option, which I commonly use, also protects against
inadvertent integer matrices and also allows the user of the function
to use lists or tuples as inputs which can often be useful:

D = fribbinate(A, B, [1,5,7])

In addition, the additional operator approach only help here if the
sense of the operators is the same for both MatPy and NumPy. Which
means that, in effect, ~X would be matrixeise for both packages. I
admit to having lost track of this thread for a while, but last I
heard the wish was for ~X to be elementwise within MatPy.

-tim



More information about the Python-list mailing list