### 16.5. Universal Functions (ufuncs)

Numeric supplies named functions with the same semantics as Python's arithmetic, comparison, and bitwise operators, and mathematical functions like those supplied by built-in modules math and cmath (covered in "The math and cmath Modules" on page 365), 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 (element-wise operation, broadcasting, coercion). Every ufunc instance u is callable, is applicable to sequences as well as to arrays, and accepts 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 typecodes (i.e., not to arrays with typecode 'O' or 'c') and Python sequences of numbers.

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; if you need a list result, convert the resulting array to a list at the end by calling method tolist. For example, say you must compute the logarithm of each item of a list and return another list. On my laptop, with N set to 2222, a list comprehension such as:

```def logsupto(N):
return [math.log(x) for x in range(2,N)]
```

takes about 5.2 milliseconds. Using Python's built-in map:

```def logsupto(N):
return map(math.log, range(2,N))
```

is faster, about 3.7 milliseconds. Using Numeric's ufunc named log:

```def logsupto(N):
return Numeric.log(Numeric.arange(2,N)).tolist( )
```

reduces the time to about 2.1 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, output=temp)
return temp.tolist( )
```

further reduces the time, down to just 2 milliseconds. The ability to accelerate such simple but massive computations (here by almost three times) with so little effort is a good part of the attraction of Numeric, and particularly of Numeric's ufunc objects. Do take care not to carelessly code something like:

```def logsupto(N):
return Numeric.log(range(2,N)).tolist( )
```

which, on my laptop, takes about 18 milliseconds; clearly, the conversions from list to array and from integer to float may dominate actual computations in a case like this one.

#### 16.5.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 (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 may 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.

#### 16.5.2. Callable Attributes

Every binary ufunc u supplies four attributes that are also callable objects.

 accumulate u.accumulate(a,axis=0) Returns an array r with the same shape and typecode 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 the 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 (r[i] is r[i-1] + a[i] for each i>0). outer u.outer(a,b) 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), which is the concatenation of the shape tuples of operands a and b. Each ith row of c is the whole of b multiplied by the corresponding ith element of a. reduce u.reduce(a,axis=0) Returns an array r with the same typecode as a and a 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 "reduce". For example, since 0+1+2+...+9 is 45, add.reduce(range(10)) is 45. With built-in reduce and import operator, reduce(operator.add,range(10)) is also 45, just like the simpler and faster expression sum(range(10)). reduceat u.reduceat(a,indices) Returns an array r with the same typecode 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 Numeric.add.reduceat(range(10),(2,6,8)) # emits: [14 13 17] ``` Here, r's elements are the partial sums 2+3+4+5, 6+7, and 8+9.

#### 16.5.3. ufunc Objects Supplied by Numeric

Numeric supplies several ufunc objects, as listed in Table 16-3.

##### Table 16-3. ufunc objects supplied by Numeric

ufunc

Behavior

absolute

Like the abs built-in function

Like the + operator

arccos

Like the acos function in math and cmath

arccosh

Like the acosh function in cmath

arcsin

Like the asin function in math and cmath

arcsinh

Like the asinh function in cmath

arctan

Like the atan function in math and cmath

arctanh

Like the atanh function in cmath

bitwise_and

Like the & operator

bitwise_not

Like the ~ operator

bitwise_or

Like the | operator

bitwise_xor

Like the ^ operator

ceil

Like the ceil function in math

conjugate

Complex conjugate of each element (unary)

cos

Like the cos function in math and cmath

cosh

Like the cosh function in cmath

divide

Like the / operator (but with result inf for division by zero)

divide_safe

Like the / operator (raises an exception for division by zero)

equal

Like the == operator

exp

Like the exp function in math and cmath

fabs

Like the fabs function in math

floor

Like the floor function in math

fmod

Like the fmod function in math

greater

Like the > operator

greater_equal

Like the >= operator

less

Like the < operator

less_equal

Like the <= operator

log

Like the log function in math and cmath

log10

Like the log10 function in math and cmath

logical_and

Like the & operator; returns array of 0s and 1s

logical_not

Like the ~ operator; returns array of 0s and 1s

logical_or

Like the | operator; returns array of 0s and 1s

logical_xor

Like the ^ operator; returns array of 0s and 1s

maximum

Element-wise, the larger of the two elements being operated on

minimum

Element-wise, the smaller of the two elements being operated on

multiply

Like the * operator

not_equal

Like the != operator

power

Like the ** operator

remainder

Like the % operator

sin

Like the sin function in math and cmath

sinh

Like the sinh function in cmath

sqrt

Like the sqrt function in math and cmath

subtract

Like the - operator

tan

Like the tan function in math and cmath

tanh

Like the tanh function in cmath

Here's how you can use ufunc to get a "ramp" of numbers, decreasing then increasing:

```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]
```

#### 16.5.4. Shorthand for Commonly Used ufunc Methods

Numeric defines function synonyms for some commonly used methods of ufunc objects, as listed in Table 16-4.

##### Table 16-4. Synonyms for ufunc methods

Synonym

Stands for

alltrue

logical_and.reduce

cumproduct

multiply.accumulate

cumsum