## Universal Functions for arrays

NumPy provides a wealth of mathematical functions that operate on then ndarray object. From algebraic functions such as addition and multiplication to trigonometric functions such as sin, and cos. Each universal function (ufunc) is an instance of a general class so that function behavior is the same. All ufuncs perform element-by-element operations over an array or a set of arrays (for multi-input functions). The ufuncs themselves and their methods are documented in Part 9.

One important aspect of ufunc behavior that should be introduced early, however, is the idea of broadcasting. Broadcasting is used in several places throughout NumPy and is therefore worth early exposure. To understand the idea of broadcasting, you first have to be conscious of the fact that all ufuncs are always element-by-element operations. In other words, suppose we have a ufunc with two inputs and one output (e.g. addition) and the inputs are both arrays of shape 4 x 6 x 5. Then, the output is going to be 4 x 6 x 5, and will be the result of applying the underlying function (e.g. +) to each pair of inputs to produce the output at the corresponding N-dimensional location.

Broadcasting allows ufuncs to deal in a meaningful way with inputs that do not have exactly the same shape. In particular, the first rule of broadcasting is that if all input arrays do not have the same number of dimensions, then a "1" will be repeatedly pre-pended to the shapes of the smaller arrays until all the arrays have the same number of dimensions. The second rule of broadcasting ensures that arrays with a size of 1 along a particular dimension act as if they had the size of the array with the largest shape along that dimension. The value of the array element is assumed to be the same along that dimension for the "broadcasted" array. After application of the broadcasting rules, the sizes of all arrays must match.

While a little tedious to explain, the broadcasting rules are easy to pick up by looking at a couple of examples. Suppose there is a ufunc with two inputs, A and B. Now supposed that A has shape 4 x 6 x 5 while B has shape 4 x 6 x 1. The ufunc will proceed to compute the 4 x 6 x 5 output as if B had been 4 x 6 x 5 by assuming that B[...,k] = B[..., 0] for k = 1, 2, 3, 4.

Another example illustrates the idea of adding 1's to the beginning of the array shape-tuple. Suppose A is the same as above, but B is a length 5 array. Because of the first rule, B will be interpreted as a 1 x 1 x 5 array, and then because of the second rule B will be interpreted as a 4 x 6 x 5 array by repeating the elements of B in the obvious way.

The most common alteration needed is to route-around the automatic pre-pending of 1's to the shape of the array. If it is desired, to add 1's to the end of the array shape, then dimensions can always be added using the newaxis name in NumPy: B[..., newaxis, newaxis] returns an array with 2 additional 1's appended to the shape of B.

One important aspect of broadcasting is the calculation of functions on regularly spaced grids. For example, suppose it is desired to show a portion of the multiplication table by computing the function a * b on a grid with a running from 6 to 9 and b running from 12 to 16. The following code illustrates how this could be done using ufuncs and broadcasting.

0 0