\chapter{Array Basics}
\label{cha:array-basics}

\begin{quote} 
   This chapter introduces some of the basic functions which will be used
   throughout the text.
\end{quote}

\section{Basics}
\label{sec:arraybasics:basics}

Before we explore the world of image manipulation as a case-study in array
manipulation, we should first define a few terms which we'll use over and
over again. Discussions of arrays and matrices and vectors can get confusing
due to differences in nomenclature. Here is a brief definition of the terms
used in this tutorial, and more or less consistently in the error messages of
\numarray{}.

The Python objects under discussion are formally called ``\NUMARRAY{}'' (or
even more correctly ``\numarray{}'') objects (N-dimensional arrays), but
informally we'll just call them ``array objects'' or just ``arrays''. These are
different from the array objects defined in the standard Python \module{array}
module (which is an older module designed for processing one-dimensional data
such as sound files).

These array objects hold their data in a fixed length, homogeneous (but not
necessarily contiguous) block of elements, i.e.\ their elements all have the
same C type (such as a 64-bit floating-point number). This is quite different
from most Python container objects, which are variable length heterogeneous
collections.

Any given array object has a \index{rank}rank, which is the number of
``dimensions'' or ``axes'' it has. For example, a point in 3D space \code{[1,
   2, 1]} is an array of rank 1 --- it has one dimension. That dimension has a
length of 3.  As another example, the array
\begin{verbatim}
1.0 0.0 0.0
0.0 1.0 2.0
\end{verbatim}
is an array of rank 2 (it is 2-dimensional). The first dimension has a length
of 2, the second dimension has a length of 3. Because the word ``dimension''
has many different meanings to different folks, in general the word ``axis''
will be used instead. Axes are numbered just like Python list indices: they
start at 0, and can also be counted from the end, so that \code{axis=-1} is the
last axis of an array, \code{axis=-2} is the penultimate axis, etc.  

There are there important and potentially unintuitive behaviors of
\module{numarray} arrays which take some getting used to. The first is that by
default, operations on arrays are performed elementwise.\footnote{This is
common to IDL behavior but contrary to Matlab behavior.}  This means that when
adding two arrays, the resulting array has as elements the pairwise sums of the
two operand arrays.  This is true for all operations, including multiplication.
Thus, array multiplication using the * operator will default to elementwise
multiplication, not matrix multiplication as used in linear algebra. Many
people will want to use arrays as linear algebra-type matrices (including their
\index{rank}rank-1 versions, vectors). For those users, the matrixmultiply
function will be useful.

The second behavior which will catch many users by surprise is that
certain operations, such as slicing, return arrays which are simply different
views of the same data; that is, they will in fact share their data. This will
be discussed at length in examples later.  Now that these definitions and 
warnings are laid out, let's see what we can do with these arrays.

The third behavior which may catch Matlab or Fortran users unaware is the use
of row-major data storage as is done in C.  So while a Fortran array might 
be indexed a[x,y],  numarray is indexed a[y,x].

\newpage
\section{Creating arrays from scratch}
\label{sec:creating-arrays-from}


\subsection{array() and types}
\label{sec:array-types}

\begin{funcdesc}{array}{sequence=None, typecode=None, copy=1, savespace=0,
    type=None, shape=None}
   There are many ways to create arrays. The most basic one is the use of the
   \function{array} function:
\begin{verbatim}
>>> a = array([1.2, 3.5, -1])
\end{verbatim}
   to make sure this worked, do:
\begin{verbatim}
>>> print a
[ 1.2  3.5 -1. ]
\end{verbatim}
   The \function{array} function takes several arguments --- the first one is
   the values, which can be a Python sequence object (such as a list or a
   tuple).  If the optional argument \code{type} is omitted, numarray tries to
   find the best data type which can represent all the elements. 
   
   Since the elements we gave our example were two floats and one integer, it
   chose \class{Float64} as the type of the resulting array. One can specify
   unequivocally the \code{type} of the elements --- this is especially 
   useful when, for example, one wants an array contains floats even
   though all of its input elements are integers:
\begin{verbatim}
>>> x,y,z = 1,2,3
>>> a = array([x,y,z])                  # integers are enough for 1, 2 and 3
>>> print a
[1 2 3]
>>> a = array([x,y,z], type=Float32)    # not the default type
>>> print a
[ 1.  2.  3.]
\end{verbatim}
    Another optional argument is the \code{shape} to use for the array.  When
    passed a \class{NumArray} instance, by default \function{array} will make
    an independent, aligned, contiguous, non-byteswapped copy.  If also passed
    a shape or different type, the resulting ``copy'' will be reshaped or
    cast as the new type.
\end{funcdesc}

\begin{funcdesc}{asarray}{seq, type=None, typecode=None}
   This function converts scalars, lists and tuples to a \class{numarray}, when
   possible. It passes \class{numarray}s through, making copies only to
   convert types.  In any other case a \class{TypeError} is raised.
\end{funcdesc}

\begin{funcdesc}{inputarray}{seq, type=None, typecode=None}
  This is an obosolete alias for \function{asarray}.
\end{funcdesc}


\paragraph*{Important Tip} \label{sec:important-tips} 
Pop Quiz: What will be the type of the array below:
\begin{verbatim}
>>> mystery = array([1, 2.0, -3j])
\end{verbatim}
Hint: -3j is an imaginary number. \\
Answer: Complex64
         
A very common mistake is to call \function{array} with a set of numbers as
arguments, as in \code{array(1, 2, 3, 4, 5)}. This doesn't produce the expected
result if at least two numbers are used, because the first argument to
\function{array} must be the entire data for the array --- thus, in most cases,
a sequence of numbers. The correct way to write the preceding invocation is
most likely \code{array([1, 2, 3, 4, 5])}.

Possible values for the type \index{type argument}argument to the
\function{array} creator function (and indeed to any function which accepts a
so-called type for arrays) are:
\begin{enumerate}
\item Elements that can have values true or false: \index{Bool}\class{Bool}.
\item Unsigned numeric types: \index{UInt8}\class{UInt8},
  \index{UInt16}\class{UInt16}, \index{UInt32}\class{UInt32}, and
  \index{UInt64}\class{UInt64}\footnote[1]{UInt64 is unsupported on Windows}.
\item Signed numeric types: 
   \begin{itemize}
   \item Signed integer choices: \index{Int8}\class{Int8},
      \index{Int16}\class{Int16}, \index{Int32}\class{Int32}, \index{Int64}\class{Int64}.
   \item Floating point choices: \index{Float32}\class{Float32},
      \index{Float64}\class{Float64}.
   \end{itemize}
\item Complex number types: \index{Complex32}\class{Complex32},
   \index{Complex64}\class{Complex64}.
\end{enumerate}

To specify a type, e.g. \class{UInt8}, etc, the easiest method is just to
specify it as a string:
\begin{verbatim}
a = array([10], type = 'UInt8')
\end{verbatim}

The various means for specifying types are defined in table
\ref{tab:type-specifiers}, with each item in a row being equivalent.  The
\emph{preferred} methods are in the first 3 columns: numarray type object, type
string, or type code.  The last two columns were added for backwards
compatabililty with Numeric and are not recommended for new code.  Numarray
type object and string names denote the size of the type in bits.  The numarray
type code names denote the size of the type in bytes.  The type objects must be
imported from or referenced via the numerictypes module.  All type strings and
type codes are specified using ordinary Python strings, and hence don't require
an import.  Complex type names denote the size of one component, real or
imaginary, in bits/bytes, but the letter code is the total size of the 
whole number ('c8' and 'c16').

\begin{table}[h]
  \centering
  \caption{Type specifiers}
  \label{tab:type-specifiers}
  \begin{tabular}{|l|l|l|l|l|}
    \hline
    Numarray Type&Numarray String&Numarray Code&Numeric String&Numeric Code\\
    \hline
    Int8&'Int8'&'i1'&'Byte'&'1'\\
    \hline
    UInt8&'UInt8'&'u1'&'UByte'& \\
    \hline
    Int16&'Int16'&'i2'&'Short'&'s'\\
    \hline
    UInt16&'UInt16'&'u2'&'UShort'& \\
    \hline
    Int32&'Int32'&'i4'&'Int'&'i'\\
    \hline
    UInt32&'UInt32'&'u4'&'UInt'&'u'\\
    \hline
    Int64&'Int64'&'i8'& & \\
    \hline
    UInt64\footnotemark[1]&'UInt64'&'u8'& & \\
    \hline
    Float32&'Float32'&'f4'&'Float'&'f'\\
    \hline
    Float64&'Float64'&'f8'&'Double'&'d'\\
    \hline
    Complex32&'Complex32'&'c8'& &'F'\\
    \hline
    Complex64&'Complex64'&'c16'&'Complex'&'D'\\
    \hline
    Bool&'Bool'& & & \\
    \hline
  \end{tabular}
\end{table}

\subsection{Multidimensional Arrays}
\label{sec:multi-dim-arrays}

The following example shows one way of creating \index{multidimensional
   arrays}multidimensional arrays:
\begin{verbatim}
>>> ma = array([[1,2,3],[4,5,6]])
>>> print ma
[[1 2 3]
 [4 5 6]]
\end{verbatim}
The first argument to \function{array} in the code above is a single
\class{list} containing two lists, each containing three elements. If we wanted
floats instead, we could specify, as discussed in the previous section, the
optional type we wished:
\begin{verbatim}
>>> ma_floats = array([[1,2,3],[4,5,6]], type=Float32)
>>> print ma_floats
[[ 1.  2.  3.]
 [ 4.  5.  6.]]
\end{verbatim}
This array allows us to introduce the notion of \index{shape}``shape''. The
shape of an array is the set of numbers which define its dimensions. The shape
of the array \var{ma} defined above is 2 by 3. More precisely, all arrays have
an attribute which is a tuple of integers giving the shape. The
\index{getshape}\method{getshape} method returns this tuple.  In general, one
can directly use the \member{shape} attribute (but only for Python 2.2 and
later) to get or set its value. Since it isn't supported for earlier versions
of Python, subsequent examples will use \method{getshape} and
\index{setshape}\method{setshape} only. So, in this case:
\begin{verbatim}
>>> print ma.shape                      # works only with Python 2.2 or later
>>> print ma.getshape()                 # works with all Python versions
(2, 3)
\end{verbatim}
Using the earlier definitions, this is a shape of \index{rank}rank 2, where the
first axis has length 2, and the second axis has length 3. The rank of an array
\code{A} is always equal to \code{len(A.getshape())}.  Note that shape is an
attribute and \method{getshape} is a method of array objects. They are the
first of several that we will see throughout this tutorial. If you're not used
to object-oriented programming, you can think of attributes as ``features'' or
``qualities'' of individual arrays, and methods are functions that operate on
individual arrays.  The relation between an array and its shape is similar to
the relation between a person and their hair color. In Python, it's called an
object/attribute relation.

\begin{funcdesc}{reshape}{a, shape}
   What if one wants to change the dimensions of an array? For now, let us
   consider changing the shape of an array without making it ``grow''. Say, for
   example, we want to make the 2x3 array defined above (\var{ma}) an array of
   rank 1:
\begin{verbatim}
>>> flattened_ma = reshape(ma, (6,))
>>> print flattened_ma
[1 2 3 4 5 6]
\end{verbatim}
   One can change the shape of arrays to any shape as long as the product of
   all the lengths of all the axes is kept constant (in other words, as long as
   the number of elements in the array doesn't change):
\begin{verbatim}
>>> a = array([1,2,3,4,5,6,7,8])
>>> print a
[1 2 3 4 5 6 7 8]
>>> b = reshape(a, (2,4))               # 2*4 == 8
>>> print b
[[1 2 3 4]
 [5 6 7 8]]
>>> c = reshape(b, (4,2))               # 4*2 == 8
>>> print c
[[1 2]
 [3 4]
 [5 6]
 [7 8]]
\end{verbatim}
   The function \function{reshape} expects an array/sequence as its 
   first argument, and a shape as its second argument.
   The shape has to be a sequence of integers (a \class{list} or a
   \class{tuple}).  There is also a \method{setshape}
   method, which changes the shape of an array in-place (see below).
   
   One nice feature of shape tuples is that one entry in the shape tuple is
   allowed to be -1. The -1 will be automatically replaced by whatever number
   is needed to build a shape which does not change the size of the array.
   Thus:
\begin{verbatim}
>>> a = reshape(array(range(25)), (5,-1))
>>> print a, a.getshape()
[[ 0  1  2  3  4]
 [ 5  6  7  8  9]
 [10 11 12 13 14]
 [15 16 17 18 19]
 [20 21 22 23 24]] (5, 5)
\end{verbatim}
   The \member{shape} of an array is a modifiable attribute of the array, but
   it is an internal attribute. You can change the shape of an array by calling
   the \method{setshape} method (or by assigning a \class{tuple} to the shape
   attribute, in Python 2.2 and later), which assigns a new shape to the array:
\begin{verbatim}
>>> a = array([1,2,3,4,5,6,7,8,9,10])
>>> a.getshape()
(10,)
>>> a.setshape((2,5))
>>> a.shape = (2,5)                     # for Python 2.2 and later
>>> print a
[[ 1  2  3  4  5]
 [ 6  7  8  9 10]]
>>> a.setshape((10,1))                  # second axis has length 1
>>> print a
[[ 1]
 [ 2]
 [ 3]
 [ 4]
 [ 5]
 [ 6]
 [ 7]
 [ 8]
 [ 9]
 [10]]
>>> a.setshape((5,-1))                  # note the -1 trick described above
>>> print a
[[ 1  2]
 [ 3  4]
 [ 5  6]
 [ 7  8]
 [ 9 10]]
\end{verbatim}
   As in the rest of Python, violating rules (such as the one about which
   shapes are allowed) results in exceptions:
\begin{verbatim}
>>> a.setshape((6,-1))
Traceback (innermost last):
  File "<stdin>", line 1, in ?
ValueError: New shape is not consistent with the old shape
\end{verbatim}
\end{funcdesc}


\paragraph*{For Advanced Users: Printing arrays}

\begin{quote}
   Sections denoted ``For Advanced Users'' indicates 
   function aspects which may not be needed for a first introduction of
   \numarray{}, but is mentioned for the sake of completeness.
\end{quote}

The default \index{printing arrays}printing routine provided by the
\module{\numarray} module prints arrays as follows:
\begin{enumerate}
\item The last axis is always printed left to right.
\item The next-to-last axis is printed top to bottom.
\end{enumerate}
The remaining axes are printed top to bottom with increasing numbers of
separators.

This explains why rank-1 arrays are printed from left to right, rank-2 arrays
have the first dimension going down the screen and the second dimension going
from left to right, etc.

If you want to change the shape of an array so that it has more elements than
it started with (i.e. grow it), then you have several options: One solution is
to use the \index{concatenate}\function{concatenate} function discussed later.
\begin{verbatim}
>>> print a
[0 1 2 3 4 5 6 6 7]
>>> print concatenate([[a],[a]])
>>> print b
[[0 1 2 3 4 5 6 7]
 [0 1 2 3 4 5 6 7]]
>>> print b.getshape()
(2, 8)
\end{verbatim}


\begin{funcdesc}{resize}{array, shape}
   A final possibility is the \function{resize} function, which takes a
   \var{base} array as its first argument and the desired \var{shape} as the
   second argument.  Unlike \function{reshape}, the shape argument to
   \function{resize} can be a smaller or larger shape than the input
   array. Smaller shapes will result in arrays with the data at the
   ``beginning'' of the input array, and larger shapes result in arrays with
   data containing as many replications of the input array as are needed to
   fill the shape. For example, starting with a simple array
\begin{verbatim}
>>> base = array([0,1])
\end{verbatim}
   one can quickly build a large array with replicated data:
\begin{verbatim}
>>> big = resize(base, (9,9))
>>> print big
[[0 1 0 1 0 1 0 1 0]
 [1 0 1 0 1 0 1 0 1]
 [0 1 0 1 0 1 0 1 0]
 [1 0 1 0 1 0 1 0 1]
 [0 1 0 1 0 1 0 1 0]
 [1 0 1 0 1 0 1 0 1]
 [0 1 0 1 0 1 0 1 0]
 [1 0 1 0 1 0 1 0 1]
 [0 1 0 1 0 1 0 1 0]]
\end{verbatim}
\end{funcdesc}

\newpage
\section{Creating arrays with values specified ``on-the-fly''}
\label{sec:creating-arrays-on-the-fly}

\begin{funcdesc}{zeros}{shape, type}
\end{funcdesc}
\begin{funcdesc}{ones}{shape, type}
   Often, one needs to manipulate arrays filled with numbers which aren't
   available beforehand. The \module{\numarray} module provides a few functions
   which create arrays from scratch: \function{zeros} and \function{ones}
   simply create arrays of a given \var{shape} filled with zeros and ones
   respectively:
\begin{verbatim}
>>> z = zeros((3,3))
>>> print z
[[0 0 0]
 [0 0 0]
 [0 0 0]]
>>> o = ones([2,3])
>>> print o
[[1 1 1]
 [1 1 1]]
\end{verbatim}
   Note that the first argument is a shape --- it needs to be a \class{tuple} or
   a \class{list} of integers. Also note that the default type for the
   returned arrays is \class{Int}, which you can override, e. g.: 
\begin{verbatim}
>>> o = ones((2,3), Float32)
>>> print o
[[ 1.  1.  1.]
 [ 1.  1.  1.]]
\end{verbatim}
\end{funcdesc}


\begin{funcdesc}{arrayrange}{a1, a2=None, stride=1, type=None, shape=None}
\end{funcdesc}
\begin{funcdesc}{arange}{a1, a2=None, stride=1, type=None, shape=None}
   The \function{arange} function is similar to the \function{range} function
   in Python, except that it returns an \class{array} as opposed to a
   \class{list}.
   \function{arange} and \function{arrayrange} are equivalent.
\begin{verbatim}
>>> r = arange(10)
>>> print r
[0 1 2 3 4 5 6 7 8 9]
\end{verbatim}
   Combining the \function{arange} with the \function{reshape} function, we can
   get:
\begin{verbatim}
>>> big = reshape(arange(100),(10,10))
>>> print big
[[ 0  1  2  3  4  5  6  7  8  9]
 [10 11 12 13 14 15 16 17 18 19]
 [20 21 22 23 24 25 26 27 28 29]
 [30 31 32 33 34 35 36 37 38 39]
 [40 41 42 43 44 45 46 47 48 49]
 [50 51 52 53 54 55 56 57 58 59]
 [60 61 62 63 64 65 66 67 68 69]
 [70 71 72 73 74 75 76 77 78 79]
 [80 81 82 83 84 85 86 87 88 89]
 [90 91 92 93 94 95 96 97 98 99]]
\end{verbatim}
   One can set the \code{a1}, \code{a2}, and \code{stride} arguments, which 
   allows for more varied ranges:
\begin{verbatim}
>>> print arange(10,-10,-2)
[10  8  6  4  2  0  -2  -4  -6  -8]
\end{verbatim}
   An important feature of arange is that it can be used with non-integer
   starting points and strides:
\begin{verbatim}
>>> print arange(5.0)
[ 0. 1. 2. 3. 4.]
>>> print arange(0, 1, .2)
[ 0.   0.2  0.4  0.6  0.8]
\end{verbatim}
   If you want to create an array with just one value, repeated over and over,
   you can use the * operator applied to lists
\begin{verbatim}
>>> a = array([[3]*5]*5)
>>> print a
[[3 3 3 3 3]
 [3 3 3 3 3]
 [3 3 3 3 3]
 [3 3 3 3 3]
 [3 3 3 3 3]]
\end{verbatim}
   but that is relatively slow, since the duplication is done on Python lists.
   A quicker way would be to start with 0's and add 3:
\begin{verbatim}
         >>> a = zeros([5,5]) + 3
         >>> print a
         [[3 3 3 3 3]
          [3 3 3 3 3]
          [3 3 3 3 3]
          [3 3 3 3 3]
          [3 3 3 3 3]]
\end{verbatim}
   The optional \code{type} argument forces the type of the resulting array,
   which is otherwise the ``highest'' of the \code{a1}, \code{a2}, and 
   \code{stride} arguments.  The \code{a1} argument defaults to 0 if not 
   specified. Note that if the specified \code{type} is
   is ``lower'' than what \function{arange} would
   normally use, the array is the result of a precision-losing cast (a
   round-down, as that used in the \method{astype} method for arrays.)
\end{funcdesc}


\subsection{Creating an array from a function}
\label{sec:creating-array-from-function}

\begin{funcdesc}{fromfunction}{object, shape} 
   Finally, one may want to create an array whose elements are the result
   of a function evaluation. This is done using the \function{fromfunction}
   function, which takes two arguments, a \var{shape} and a callable
   \var{object} (usually a function).  For example:
\begin{verbatim}
>>> def dist(x,y):
...   return (x-5)**2+(y-5)**2          # distance from (5,5) squared
...
>>> m = fromfunction(dist, (10,10))
>>> print m
[[50 41 34 29 26 25 26 29 34 41]
 [41 32 25 20 17 16 17 20 25 32]
 [34 25 18 13 10  9 10 13 18 25]
 [29 20 13  8  5  4  5  8 13 20]
 [26 17 10  5  2  1  2  5 10 17]
 [25 16  9  4  1  0  1  4  9 16]
 [26 17 10  5  2  1  2  5 10 17]
 [29 20 13  8  5  4  5  8 13 20]
 [34 25 18 13 10  9 10 13 18 25]
 [41 32 25 20 17 16 17 20 25 32]]
>>> m = fromfunction(lambda i,j,k: 100*(i+1)+10*(j+1)+(k+1), (4,2,3))
>>> print m
[[[111 112 113]
  [121 122 123]]
 [[211 212 213]
  [221 222 223]]
 [[311 312 313]
  [321 322 323]]
 [[411 412 413]
  [421 422 423]]]
\end{verbatim}
   These examples show that \function{fromfunction}
   creates an array of the shape specified by its second argument, and with the
   contents corresponding to the value of the function argument (the first
   argument) evaluated at the indices of the array. Thus the value of
   \code{m[3, 4]} in the first example above is the value of dist when
   \code{x=3} and \code{y=4}.  Similarly for the lambda function in the second
   example, but with a rank-3 array.  The implementation of
   \function{fromfunction} consists of:
\begin{verbatim}
def fromfunction(function, dimensions):
    return apply(function, tuple(indices(dimensions)))
\end{verbatim}
   which means that the function \function{function} is called with arguments
   given by the sequence \code{indices(dimensions)}. As described in the
   definition of indices, this consists of arrays of indices which will be of
   rank one less than that specified by dimensions. This means that the
   function argument must accept the same number of arguments as there are
   dimensions in \var{dimensions}, and that each argument will be an array of
   the same shape as that specified by dimensions.  Furthermore, the array
   which is passed as the first argument corresponds to the indices of each
   element in the resulting array along the first axis, that which is passed as
   the second argument corresponds to the indices of each element in the
   resulting array along the second axis, etc. A consequence of this is that
   the function which is used with \function{fromfunction} will work as
   expected only if it performs a separable computation on its arguments, and
   expects its arguments to be indices along each axis. Thus, no logical
   operation on the arguments can be performed, or any non-shape preserving
   operation. Thus, the following will not work as expected:
\begin{verbatim}
>>> def buggy(test):
...     if test > 4: return 1
...     else: return 0
...
>>> print fromfunction(buggy,(10,))
Traceback (most recent call last):
...
RuntimeError: An array doesn't make sense as a truth value.  Use any(a) or
all(a).
\end{verbatim}
The reason \function{buggy()} failed is that indices((10,)) results in an array
passed as \var{test}.  The result of comparing \var{test} with 4 is also an
array which has no unambiguous meaning as a truth value.

Here is how to do it properly. We add a print statement to the
   function for clarity:
\begin{verbatim}
>>> def notbuggy(test):                 # only works in Python 2.1 & later
...     print test
...     return where(test>4,1,0)
...
>>> fromfunction(notbuggy,(10,))
[0 1 2 3 4 5 6 7 8 9]
array([0, 0, 0, 0, 0, 1, 1, 1, 1, 1])
\end{verbatim}
   We leave it as an excercise for the reader to figure out why the ``buggy''
   example gave the result 1.
\end{funcdesc}


\begin{funcdesc}{identity}{size}
   The \function{identity} function takes a single integer argument and returns
   a square identity array (in the ``matrix'' sense) of that \var{size} of
   integers:
\begin{verbatim}
      >>> print identity(5)
      [[1 0 0 0 0]
       [0 1 0 0 0]
       [0 0 1 0 0]
       [0 0 0 1 0]
       [0 0 0 0 1]]
\end{verbatim}
\end{funcdesc}



\newpage
\section{Coercion and Casting}
\label{sec:coercion-casting}

We've mentioned the types of arrays, and how to create arrays with the right
type.  But what happens when arrays with different types interact?  For 
some operations, the behavior of \numarray{} is significantly different 
from Numeric.

\subsection{Automatic Coercions and Binary Operations}
\label{sec:automatic-coercion-binary-casting}

In \numarray{} (in contrast to Numeric), there is now a distinction between how
coercion is treated in two basic cases: array/scalar operations and array/array
operations. In the array/array case, the coercion rules are nearly identical to
those of Numeric, the only difference being combining signed and unsigned
integers of the same size.  The array/array result types are enumerated in
table \ref{tab:array-array-result-types}.
\begin{table}[h]
\footnotesize
\centering
\caption{Array/Array Result Types}
\label{tab:array-array-result-types}
\begin{tabular}{|l|l|l|l|l|l|l|l|l|l|l|l|l|l|}
\hline
 &Bool&Int8&UInt8&Int16&UInt16&Int32&UInt32&Int64&UInt64&Float32&Float64&Complex32&Complex64\\
\hline
Bool&Int8&Int8&UInt8&Int16&UInt16&Int32&UInt32&Int64&UInt64&Float32&Float64&Complex32&Complex64\\
\hline
Int8& &Int8&Int16&Int16&Int32&Int32&Int64&Int64&Int64&Float32&Float64&Complex32&Complex64\\
\hline
UInt8& & &UInt8&Int16&UInt16&Int32&UInt32&Int64&UInt64&Float32&Float64&Complex32&Complex64\\
\hline
Int16& & & &Int16&Int32&Int32&Int64&Int64&Int64&Float32&Float64&Complex32&Complex64\\
\hline
UInt16& & & & &UInt16&Int32&UInt32&Int64&UInt64&Float32&Float64&Complex32&Complex64\\
\hline
Int32& & & & & &Int32&Int64&Int64&Int64&Float32&Float64&Complex32&Complex64\\
\hline
UInt32& & & & & & &UInt32&Int64&UInt64&Float32&Float64&Complex32&Complex64\\
\hline
Int64& & & & & & & &Int64&Int64&Float64&Float64&Complex64&Complex64\\
\hline
UInt64& & & & & & & & &UInt64&Float64&Float64&Complex64&Complex64\\
\hline
Float32& & & & & & & & & &Float32&Float64&Complex32&Complex64\\
\hline
Float64& & & & & & & & & & &Float64&Complex64&Complex64\\
\hline
Complex32& & & & & & & & & & & &Complex32&Complex64\\
\hline
Complex64& & & & & & & & & & & & &Complex64\\
\hline
\end{tabular}
\end{table}

Scalars, however, are treated differently. If the scalar is of the same
``kind'' as the array (for example, the array and scalar are both integer
types) then the output is the type of the array, even if it is of a normally
``lower'' type than the scalar.  Adding an \class{Int16} array with an integer
scalar results in an \class{Int16} array, not an \class{Int32} array as is the
case in Numeric.  Likewise adding a \class{Float32} array to a float scalar
results in a \class{Float32} array rather than a \class{Float64} array as is
the case with Numeric.  Adding an \class{Int16} array and a float scalar will
result in a \class{Float64} array, however, since the scalar is of a higher
kind than the array.  Finally, when scalars and arrays are operated on
together, the scalar is converted to a rank-0 array first.  Thus, adding a
``small'' integer to a ``large'' floating point array is equivalent to first
casting the integer ``up'' to the type of the array.
\begin{verbatim}
>>> print (array ((1, 2, 3), type=Int16) * 2).type()
numarray type: Int16
>>> arange(0, 1.0, .1) + 12
array([ 12. , 12.1, 12.2, 12.3, 12.4, 12.5, 12.6, 12.7, 12.8, 12.9]
\end{verbatim}

The results of array/scalar operations are enumerated in table
\ref{tab:Array-Scalar-Result-Types}.  Entries marked with " are identical to
their neighbors on the same row.
\begin{table}[h]
\footnotesize
\centering
\caption{Array/Scalar Result Types}
\label{tab:Array-Scalar-Result-Types}
\begin{tabular}{|l|l|l|l|l|l|l|l|l|l|l|l|l|l|}
\hline
 &Bool&Int8&UInt8&Int16&UInt16&Int32&UInt32&Int64&UInt64&Float32&Float64&Complex32&Complex64\\
\hline
int&Int32&Int8&UInt8&Int16&UInt16&Int32&UInt32&Int64&UInt64&Float32&Float64&Complex32&Complex64\\
\hline
long&Int32&Int8&UInt8&Int16&UInt16&Int32&UInt32&Int64&UInt64&Float32&Float64&Complex32&Complex64\\
\hline
float&Float64&"&"&"&"&"&"&"&Float64&Float32&Float64&Complex32&Complex64\\
\hline
complex&Complex64&"&"&"&"&"&"&"&"&"&"&"&Complex64\\
\hline
\end{tabular}
\end{table}

\footnotetext[10]{Float64}
\footnotetext[20]{Complex64}

\subsection{The type value table}
\label{sec:type-value-table}

The type identifiers (\class{Float32}, etc.) are \class{NumericType} instances.
The mapping between type and the equivalent C variable is machine dependent.
The correspondences between types and C variables for 32-bit architectures are
shown in Table \ref{tab:type-identifiers}.

\begin{table}[h]
   \centering
   \caption{Type identifier table on a x86 computer.}
   \label{tab:type-identifiers}
   \begin{tabular}{ccl}
      \# of bytes & \# of bits      & Identifier \\
           1      &       8         &   Bool \\
           1      &       8         &   Int8 \\
           1      &       8         &   UInt8 \\
           2      &       16        &   Int16 \\
           2      &       16        &   UInt16 \\
           4      &       32        &   Int32 \\
           4      &       32        &   UInt32 \\
           8      &       64        &   Int64 \\
           8      &       64        &   UInt64 \\
           4      &       32        &   Float32 \\
           8      &       64        &   Float64 \\
           8      &       64        &   Complex32 \\
           16     &      128        &   Complex64 
   \end{tabular}
\end{table}

\subsection{Long: the platform relative type}
The type identifier \class{Long} is aliased to either \class{Int32} or
\class{Int64}, depending on the machine architecture where numarray is
installed.  On 32-bit platforms, \class{Long} is defined as \class{Int32}.  On
64-bit (LP64) platforms, \class{Long} is defined as \class{Int64}. \class{Long}
is used as the default integer type for arrays and for index values, such as
those returned by \function{nonzero}.  

\subsection{Deliberate casts (potentially down)}
\label{sec:deliberate-casts}

\begin{methoddesc}{astype}{type}
   You may also force \module{numarray} to cast any number array to another
   number array.  For example, to take an array of any numeric type
   (\class{IntX} or \class{FloatX} or \class{ComplexX} or \class{UIntX}) and
   convert it to a 64-bit float, one can do:
\begin{verbatim}
>>> floatarray = otherarray.astype(Float64)
\end{verbatim}
   The \var{type} can be any of the number types, ``larger'' or ``smaller''. If
   it is larger, this is a cast-up. If it is smaller, the standard casting
   rules of the underlying language (C) are used, which means that truncation
   or integer wrap-around can occur:
\begin{verbatim}
>>> print x
[   0.     0.4    0.8    1.2  300.6]
>>> print x.astype(Int32)
[  0   0   0   1 300]
>>> print x.astype(Int8)      # wrap-around
[ 0  0  0  1 44]
\end{verbatim}
   If the \var{type} used with \method{astype} is the original array's type,
   then a copy of the original array is returned.
\end{methoddesc}


\newpage
\section{Operating on Arrays}
\label{sec:operating-arrays}

\subsection{Simple operations}
\label{sec:simple-operations}

If you have a keen eye, you have noticed that some of the previous examples did
something new: they added a number to an array. Indeed, most Python operations
applicable to numbers are directly applicable to arrays:
\begin{verbatim}
>>> print a
[1 2 3]
>>> print a * 3
[3 6 9]
>>> print a + 3
[4 5 6]
\end{verbatim}
Note that the mathematical operators behave differently depending on the types
of their operands. When one of the operands is an array and the other a
number, the number is added to all the elements of the array, and the resulting
array is returned. This is called \index{broadcasting}\var{broadcasting}. 
This also occurs for unary mathematical operations such as sine and the 
negative sign:
\begin{verbatim}
>>> print sin(a)
[ 0.84147096 0.90929741 0.14112 ]
>>> print -a
[-1 -2 -3]
\end{verbatim}
When both elements are arrays of the same shape, then a new array is created,
where each element is the operation result of the corresponding elements in 
the original arrays:
\begin{verbatim}
>>> print a + a
[2 4 6]
\end{verbatim}
If the operands of operations such as addition, are arrays having the same
rank but different dimensions, then an exception is generated:
\begin{verbatim}
>>> a = array([1,2,3])
>>> b = array([4,5,6,7])                # note this has four elements
>>> print a + b
Traceback (innermost last):
  File "<stdin>", line 1, in ?
ValueError: Arrays have incompatible shapes
\end{verbatim}
This is because there is no reasonable way for numarray to interpret addition
of a \code{(3,)} shaped array and a \code{(4,)} shaped array.

Note what happens when adding arrays with different rank:
\begin{verbatim}
>>> print a
[1 2 3]
>>> print b
[[ 4  8 12]
 [ 5  9 13]
 [ 6 10 14]
 [ 7 11 15]]
>>> print a + b
[[ 5 10 15]
 [ 6 11 16]
 [ 7 12 17]
 [ 8 13 18]]
\end{verbatim}
This is another form of \index{broadcasting}broadcasting. To understand this,
one needs to look carefully at the shapes of \code{a} and \code{b}:
\begin{verbatim}
>>> a.getshape()
(3,)
>>> b.getshape()
(4,3)
\end{verbatim}
Note that the last axis of \code{a} is the same length as that of \code{b}
(i.e.\ compare the last elements in their shape tuples).  Because \code{a}'s
and \code{b}'s last dimensions both have length 3, those two dimensions were
``matched'', and a new dimension was created and automatically ``assumed'' for
array \code{a}. The data already in \code{a} were ``replicated'' as many 
times as needed (4, in this case) to make the shapes of the two operand 
arrays conform. This
replication (\index{broadcasting}broadcasting) occurs when arrays are operands
to binary operations and their shapes differ, based on the following algorithm:
\begin{itemize}
\item starting from the last axis, the axis lengths (dimensions) of the
   operands are compared,
\item if both arrays have axis lengths greater than 1, but the lengths differ,
   an exception is raised,
\item if one array has an axis length greater than 1, then the other array's
   axis is ``stretched'' to match the length of the first axis; if the other
   array's axis is not present (i.e., if the other array has smaller rank),
   then a new axis of the same length is created.
\end{itemize}

Operands with the following shapes will work:
\begin{verbatim}
(3, 2, 4) and (3, 2, 4)
(3, 2, 4) and (2, 4)
(3, 2, 4) and (4,)
(2, 1, 2) and (2, 2)
\end{verbatim}

But not these:
\begin{verbatim}
(3, 2, 4) and (2, 3, 4)
(3, 2, 4) and (3, 4)
(4,) and (0,)
(2, 1, 2) and (0, 2)
\end{verbatim}

This algorithm is complex to describe, but intuitive in practice.


\subsection{In-place operations}
\label{sec:inplace-operations}

Beginning with Python 2.0, Python supports the in-place operators
\index{+=}\code{+=}, \index{+=}\code{-=}, \index{*=}\code{*=}, and
\index{/=}\code{/=}. \Numarray{} supports these operations, but you need to be
careful. The right-hand side should be of the same type. Some violation of this
is possible, but in general contortions may be necessary for using the smaller
``kinds'' of types.
\begin{verbatim}
>>> x = array ([1, 2, 3], type=Int16)
>>> x += 3.5
>>> print x
[4 5 6]
\end{verbatim}


%% Local Variables:
%% mode: LaTeX
%% mode: auto-fill
%% fill-column: 79
%% indent-tabs-mode: nil
%% ispell-dictionary: "american"
%% reftex-fref-is-default: nil
%% TeX-auto-save: t
%% TeX-command-default: "pdfeLaTeX"
%% TeX-master: "numarray"
%% TeX-parse-self: t
%% End:
