15.7 Universal Functions (ufuncs)
Numeric supplies
named functions with the same semantics as Python's
arithmetic, comparison, and bitwise operators. Similar semantics
(element-wise operation, broadcasting, coercion) are also available
with other mathematical functions, both binary and unary, that
Numeric supplies. For example,
Numeric supplies typical mathematical functions
similar to those supplied by built-in module math,
such as sin, cos,
log, and exp.
These functions are objects of type ufunc (which
stands for universal function) and share several traits in addition
to those they have in common with array operators. Every
ufunc instance u is
callable, is applicable to sequences as well as to arrays, and lets
you specify an optional output argument.
If u is binary (i.e., if
u accepts two operand arguments),
u also has four callable attributes, named
u.accumulate,
u.outer,
u.reduce, and
u.reduceat. The
ufunc objects supplied by
Numeric apply only to arrays with numeric type
codes (i.e., not to arrays with type code 'O' or
'c').
Any ufunc u applies to
sequences, not just to arrays. When you start with a list
L, it's faster to call
u directly on L
rather than to convert L to an array.
u's return value is an
array a; you can perform further
computation, if any, on a, and then, if
you need a list result, you can convert the resulting array to a list
by calling its method tolist. For example, say you
must compute the logarithm of each item of a list and return another
list. On my system, with N set to
2222 and using python
-O, a list comprehension such as:
def logsupto(N):
return [math.log(x) for x in range(2,N)]
takes about 5.6 milliseconds. Using Python's
built-in map:
def logsupto(N):
return map(math.log, range(2,N))
takes around half the time, 2.8 milliseconds. Using
Numeric's
ufunc named log:
def logsupto(N):
return Numeric.log(range(2,N)).tolist( )
reduces the time to about 2.0 milliseconds. Taking some care to
exploit the output argument to the
log ufunc:
def logsupto(N):
temp = Numeric.arange(2, N, typecode=Numeric.Float)
Numeric.log(temp, temp)
return temp.tolist( )
further reduces the time, down to just 0.9 milliseconds. The ability
to accelerate such simple but massive computations (here by about 6
times) with so little effort is a good part of the attraction of
Numeric, and particularly of
Numeric's
ufunc objects.
15.7.1 The Optional output Argument
Any ufunc u accepts an
optional last argument output that
specifies an output array. If supplied,
output must be an array or array slice of
the right shape and type for
u's results (i.e., no
coercion, no broadcasting). u stores
results in output and does not create a
new array. output can be the same as an
input array argument a of
u. Indeed,
output is normally specified in order to
substitute common idioms such as
a=u(a,b)
with faster equivalents such as
u(a,b,a).
However, output cannot share data with
a without being
a (i.e., output
can't be a different view of some or all of
a's data). If you pass
such a disallowed output argument,
Numeric is normally unable to diagnose your error
and raise an exception, so instead you get wrong results.
Whether you pass the optional output
argument or not, a ufunc
u returns its results as the
function's return value. When you do not pass
output, u
stores the results it returns in a new array
object, so you normally bind
u's return value to some
reference in order to be able to access
u's results later. When
you pass the output argument,
u stores the results in
output, so you need not bind
u's return value. You can
later access u's results
as the new contents of the array object passed as
output.
15.7.2 Callable Attributes
Every
binary ufunc u supplies
four attributes that are also callable objects.
Returns an array r with the same shape and
type code as a. Each element of
r is the accumulation of elements of
a along the given
axis with the function or operator
underlying u. For example:
print add.accumulate(range(10))
# prints: [0 1 3 6 10 15 21 28 36 45] Since add's underlying operator
is +, and a is sequence
0,1,2,...,9, r is
0,0+1,0+1+2,...,0+1+...+8+9. In other words,
r[0] is
a[0],
r[1] is
r[0]
+
a[1],
r[2] is
r[1]
+
a[2], and so on (i.e.,
each
r[i]
is
r[i-1]
+
a[i]).
Returns an array r whose shape tuple is
a.shape+b.shape.
For each tuple ta indexing
a and tb
indexing b,
a[ta],
operated (with the function or operator underlying
u) with
b[tb],
is put in
r[ta+tb]
(the + here indicates tuple concatenation). The
overall operation is known in mathematics as the outer product when
u is multiply. For
example:
a = Numeric.arange(3, 5)
b = Numeric.arange(1, 6)
c = Numeric.multiply.outer(a, b)
print a.shape, b.shape, c.shape # prints: (2,) (5,) (2,5)
print c # prints: [[3 6 9 12 15]
# [4 8 12 16 20]] c.shape is
(2,5), the concatenation of the shape tuples of
operands a and
b. Each i row
of c is the whole of
b multiplied by the corresponding
i element of a.
Returns an array r with the same type code
as a and rank one less than
a's rank. Each element of
r is the reduction of the elements of
a, along the given
axis, with the function or operator
underlying u. The functionality of
u.reduce is therefore
close to that of Python's built-in
reduce function, covered in Chapter 8. For example, since
0+1+2+...+9 is 45,
add.reduce(range(10)) is 45.
This is just like, when using built-in reduce and
import operator,
reduce(operator.add,range(10)) is also
45.
Returns an array r with the same type code
as a and the same shape as
indices. Each element of
r is the reduction, with the function or
operator underlying u, of elements of
a starting from the corresponding item of
indices up to the next one excluded (up to
the end, for the last one). For example:
print add.reduceat(range(10),(2,6,8)) # prints: [14 13 17] Here, r's elements are
the partial sums 2+3+4+5, 6+7,
and 8+9.
15.7.3 ufunc Objects Supplied by Numeric
Numeric supplies several ufunc
objects, as listed in Table 15-4.
Table 15-4. ufunc objects supplied by Numeric
absolute
|
Behaves like the abs built-in function
|
add
|
Behaves like the + operator
|
arccos
|
Behaves like the acos function in
math and cmath
|
arccosh
|
Behaves like the acosh function in
cmath
|
arcsin
|
Behaves like the asin function in
math and cmath
|
arcsinh
|
Behaves like the asinh function in
cmath
|
arctan
|
Behaves like the atan function in
math and cmath
|
arctanh
|
Behaves like the atanh function in
cmath
|
bitwise_and
|
Behaves like the & operator
|
bitwise_not
|
Behaves like the ~ operator
|
bitwise_or
|
Behaves like the | operator
|
bitwise_xor
|
Behaves like the ^ operator
|
ceil
|
Behaves like the ceil function in
math
|
conjugate
|
Computes the complex conjugate of each element (unary)
|
cos
|
Behaves like the cos function in
math and cmath
|
cosh
|
Behaves like the cosh function in
cmath
|
divide
|
Behaves like the / operator
|
equal
|
Behaves like the = = operator
|
exp
|
Behaves like the exp function in
math and cmath
|
fabs
|
Behaves like the fabs function in
math
|
floor
|
Behaves like the floor function in
math
|
fmod
|
Behaves like the fmod function in
math
|
greater
|
Behaves like the > operator
|
greater_equal
|
Behaves like the /= operator
|
less
|
Behaves like the < operator
|
less_equal
|
Behaves like the <= operator
|
log
|
Behaves like the log function in
math and cmath
|
log10
|
Behaves like the log10 function in
math and cmath
|
logical_and
|
Behaves like the & operator; always returns an
array containing 0s and 1s, the
truth values of the operands' elements
|
logical_not
|
Returns an array of 0s and 1s,
logical negations of the operand's elements
|
logical_or
|
Behaves like the | operator; always returns an
array containing 0s and 1s, the
truth values of the operands' elements
|
logical_xor
|
Behaves like the ^ operator; always returns an
array containing 0s and 1s, the
truth values of the operands' elements
|
maximum
|
Returns element-wise the larger of the two elements being operated on
|
minimum
|
Returns element-wise the smaller of the two elements being operated on
|
multiply
|
Behaves like the * operator
|
not_equal
|
Behaves like the != operator
|
power
|
Behaves like the ** operator
|
remainder
|
Behaves like the % operator
|
sin
|
Behaves like the sin function in
math and cmath
|
sinh
|
Behaves like the sinh function in
cmath
|
sqrt
|
Behaves like the sqrt function in
math and cmath
|
subtract
|
Behaves like the - operator
|
tan
|
Behaves like the tan function in
math and cmath
|
tanh
|
Behaves like the tanh function in
cmath
|
Here's how you might use the
maximum ufunc to get a numeric
ramp that goes down and then back up again:
print Numeric.maximum(range(1,20),range(20,1,-1))
# prints: [20 19 18 17 16 15 14 13 12 11 11 12 13 14 15 16 17 18 19]
15.7.4 Shorthand for Commonly Used ufunc Methods
Numeric defines function synonyms for some
commonly used methods of ufunc objects, as listed
in Table 15-5.
Table 15-5. Synonyms for ufunc methods
alltrue
|
logical_and.reduce
|
cumproduct
|
multiply.accumulate
|
cumsum
|
add.accumulate
|
product
|
multiply.reduce
|
sometrue
|
logical_or.reduce
|
sum
|
add.reduce
|
|