The operations on arrays that were mentioned in the previous section (element-wise addition, multiplication, etc.) all share some features -- they all follow similar rules for broadcasting, coercion and ``element-wise operation''. Just as standard addition is available in Python through the add function in the operator module, array operations are available through callable objects as well. Thus, the following objects are available in the numarray module:
add () | subtract () | multiply (*) | divide () |
remainder (%) | power (**) | arccos | arccosh |
arcsin | arcsinh | arctan | arctanh |
cos | cosh | tan | tanh |
log10 | sin | sinh | sqrt |
absolute (abs) | fabs | floor | ceil |
fmod | exp | log | conjugate |
maximum | minimum | ||
greater () | greater_equal () | equal () | |
less () | less_equal () | not_equal () | |
logical_or | logical_xor | logical_not | logical_and |
bitwise_or () | bitwise_xor (^) | bitwise_not (~) | bitwise_and (&) |
rshift () | lshift () |
All of these ufuncs can be used as functions. For example, to use add, which is a binary ufunc (i.e. it takes two arguments), one can do either of:
>>> a = arange(10) >>> print add(a,a) [ 0 2 4 6 8 10 12 14 16 18] >>> print a + a [ 0 2 4 6 8 10 12 14 16 18]
+
operator on arrays performs exactly the same thing
as the add ufunc when operated on arrays. For a unary ufunc such as
sin, one can do, e.g.:
>>> a = arange(10) >>> print sin(a) [ 0. 0.84147096 0.90929741 0.14112 -0.7568025 -0.95892429 -0.27941549 0.65698659 0.98935825 0.41211849]
sin(0)=0
, sin(1)=0.84147098
, etc.).
There are three additional features of ufuncs which make them different from standard Python functions. They can operate on any Python sequence in addition to arrays; they can take an ``output'' argument; they have methods which are themselves callable with arrays and sequences. Each of these will be described in turn.
Ufuncs can operate on any Python sequence. Ufuncs have so far been described as callable objects which take either one or two arrays as arguments (depending on whether they are unary or binary). In fact, any Python sequence which can be the input to the array constructor can be used. The return value from ufuncs is always an array. Thus:
>>> add([1,2,3,4], (1,2,3,4)) array([2, 4, 6, 8])
In many computations with large sets of numbers, arrays are often used only once. For example, a computation on a large set of numbers could involve the following step
dataset = dataset * 1.20
dataset = multiply(dataset, 1.20)
multiply(dataset, 1.20, dataset)
dataset = dataset * 1.20
) and the ``small and fast'' version
above will yield different results in at least one case:
\>>> a=arange(5,type=Int32) >>> print a[::-1]*1.7 [ 6.8 5.1 3.4 1.7 0. ] >>> multiply(a[::-1],1.7,a) >>> print a [6 5 3 1 0] >>> a *= 1.7 >>> print a [0 1 3 5 6]
The output array does not need to be the same variable as the input array. In numarray, in contrast to Numeric, the output array may have any type (automatic conversion is performed on the output).
a, axis=0) |
>>> a = array([1,2,3,4]) >>> print add.reduce(a) # with Python's reduce, same as reduce(add, a) 10
>>> b = array([[1,2,3,4],[6,7,8,9]]) >>> print b [[1 2 3 4] [6 7 8 9]] >>> print add.reduce(b) [ 7 9 11 13]
>>> print b [[1 2 3 4] [6 7 8 9]] >>> print add.reduce(b, axis=1) [10 30]
a) |
>>> a = arange(10) >>> print a [0 1 2 3 4 5 6 7 8 9] >>> print add.accumulate(a) [ 0 1 3 6 10 15 21 28 36 45] # 0, 0+1, 0+1+2, 0+1+2+3, ... 0+...+9 >>> print add.reduce(a) # same as add.accumulate(a)[-1] w/o side effects on a 45
a, b) |
>>> print a [0 1 2 3 4] >>> print b [0 1 2 3] >>> print add.outer(a,b) [[0 1 2 3] [1 2 3 4] [2 3 4 5] [3 4 5 6] [4 5 6 7]] >>> print multiply.outer(b,a) [[ 0 0 0 0 0] [ 0 1 2 3 4] [ 0 2 4 6 8] [ 0 3 6 9 12]] >>> print power.outer(a,b) [[ 1 0 0 0] [ 1 1 1 1] [ 1 2 4 8] [ 1 3 9 27] [ 1 4 16 64]]
) |
Except when the output argument is used as described above, ufuncs always return new arrays which do not share any data with the input arrays.