[Numpy-discussion] Numpy and PEP 343

Tim Hochberg tim.hochberg at cox.net
Fri Mar 3 13:36:01 CST 2006

David M. Cooke wrote:

>Tim Hochberg <tim.hochberg at cox.net> writes:
>>That makes sense. One thought I had with respect to the various numpy
>>functions (sin, cos, pow, etc) was to just have the bytecodes:
>>call_unary_function, function_id, store_in, source
>>call_binary_function, function_id, store_in, source1, source2
>>call_trinary_function, function_id, store_in, source1, source2, source3
>>Then just store pointers to the functions in relevant tables. In it's
>>most straightforward form, you'd need 6 character chunks of bytecode
>>instead of four.  However, if that turns out to slow everything else
>>down I think it could be packed down to 4 again. The function_ids
>>could probably be packed into the opcode (as long as we stay below 200
>>or so functions, which is probably safe), the other way to pack things
>>down is to require that one of the sources for trinary functions is
>>always a certain register (say register-0). That requires a bit more
>>cleverness at the compiler level, but is probably feasible.
>That's along the lines I'm thinking of. It seems to me that if
>evaluating the function requires a function call (and not an inlined
>machine instruction like the basic ops), then we may as well dispatch
>like this (plus, it's easier :). This could also allow for user
Hmm. If we are going to allow user extensions, we should think about 
this now. I was thinking of just putting all of the functions in a big 
table and doing a lookup based on bytecode. I'm not sure how this should 
work if we are allowing user extensions though.

>Binary and trinary (how many of those do we have??)
I'm sure there are more that I'm not thinking of, but the main function 
that I am concerned with is  arctan2. For trinary, the main one is which.

> could
>maybe be handled by storing the extra arguments in a separate array.
If there really are only a few functions, we could give them their own 
opcodes. That means binary function still fit in 4 characters without a 
problem.  That is:

OP_ATAN2 R0, R1, R2

would compute:
   R0[:] = arctan2(R1, R2)

Trinary could be defined as using their input as one of the arguments. 
This would sometimes require an extra copy and some cleverness in the 
compiler, but I think it would be reasonable. Thus


would compute:
   R0[:] = which(R0, R1, R2)

since the first argument of 'which' is often thrown away anyway, for 
instance 'which (a < 1, b, c)', the extra copy could often be avoided if 
we're smart. This might be a bad idea if there turns out to be several 
more trinary functions that I'm not thinking of or if there are 
quaternary functions we want to support. (I can't think of any though).

>I'm going to look at adding more smarts to the compiler, too. Got a
>couple books on them :-)
Do you have any recomendations?

>Different data types could be handled by separate input arrays, and a
>conversion opcode ('int2float', say).
That'd be cool. At some point I want to handle complex, but I'm going to 
wait till the main issues with floats shake themselves out.


More information about the Numpy-discussion mailing list