\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
two 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.


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


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

\begin{funcdesc}{array}{sequence=None, type=None, shape=None, 
      copy=1, savespace=0, typecode=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).  The optional argument \code{type}, if omitted,
   as in the example above, Python tries to find the best data type which can
   represent all the elements. Another optional argument is
   the shape to use for the array.
   
   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}
\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}
Another approach is to directly access the type object from the numeric types
module:
\begin{verbatim}
import numerictypes
a = array([10], type = numerictypes.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. An alternative is to use the \function{array} creator 
function with existing arrays as arguments:
\begin{verbatim}
>>> print a
[0 1 2 3 4 5 6 6 7]
>>> b = array([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}


\paragraph*{For Advanced Users} 
The \index{numarray!constructor}\class{\numarray} constructor takes a data
argument, an optional type, and an optional shape argument. If the data
argument is a sequence, then array creates a new object of type
\class{\numarray}, and fills the array with the elements of the data object.
The shape of the array is determined by the size and nesting arrangement of the
elements of data.



\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,))
1
\end{verbatim}
   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}



\clearpage
\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}


\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}

Mathematically, if operands \code{a, b} have ranks \code{m} and \code{n} 
respectively and \code{m <= n}, then the following codition must be true:
\begin{verbatim}
a.shape = b.shape[-m:]
\end{verbatim}
So, 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,)
\end{verbatim}
But not these:
\begin{verbatim}
(3, 2, 4) and (2, 3, 4)
(3, 2, 4) and (3, 4)
(4,) and (0,)
\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}


\section{Getting and Setting array values}
\label{sec:get-set-array-values}

Just like other Python sequences, array contents are manipulated with the
\code{[]} notation. For rank-1 arrays, there are no differences between list
and array notations:
\begin{verbatim}
>>> a = arange(10)
>>> print a[0]                          # get first element
0
>>> print a[1:5]                        # get second through fifth elements
[1 2 3 4]
>>> print a[-1]                         # get last element
9
>>> print a[:-1]                        # get all but last element
[0 1 2 3 4 5 6 7 8]
\end{verbatim}
If an array is multidimensional (of rank > 1), then specifying a single 
integer index will return an array of
dimension one less than the original array.

\begin{verbatim}
>>> a = arange(9, shape=(3,3))
>>> print a
[[0 1 2]
 [3 4 5]
 [6 7 8]]
>>> print a[0]                          # get first row, not first element!
[0 1 2]
>>> print a[1]                          # get second row
[3 4 5]
\end{verbatim}
To get to individual elements in a rank-2 array, one specifies both indices
separated by commas:
\begin{verbatim}
>>> print a[0,0]                        # get element at first row, first column
0
>>> print a[0,1]                        # get element at first row, second column
1
>>> print a[1,0]                        # get element at second row, first column
3
>>> print a[2,-1]                       # get element at third row, last column
8
\end{verbatim}
Of course, the \code{[]} notation can be used to set values as well:
\begin{verbatim}
>>> a[0,0] = 123
>>> print a
[[123   1   2]
 [  3   4   5]
 [  6   7   8]]
\end{verbatim}
Note that when referring to rows, the right hand side of the equal sign needs
to be a sequence which ``fits'' in the referred array subset, as described 
by the broadcast rule (in the code sample below, a 3-element row):
\begin{verbatim}
>>> a[1] = [10,11,12] ; print a
[[123   1   2]
 [ 10  11  12]
 [  6   7   8]]
>>> a[2] = 99 ; print a
[[123   1   2]
 [ 10  11  12]
 [ 99  99  99]]
\end{verbatim}

Note also that when assigning floating point values to integer arrays that
the values are silently truncated:
\begin{verbatim}
>>> a[1] = 93.999432
[[123   1   2]
 [ 93  93  93]
 [ 99  99  99]]
\end{verbatim}

\section{Slicing Arrays}
\label{sec:slicing-arrays}

The standard rules of Python slicing apply to arrays, on a per-dimension basis.
Assuming a 3x3 array:
\begin{verbatim}
>>> a = reshape(arange(9),(3,3))
>>> print a
[[0 1 2]
 [3 4 5]
 [6 7 8]]
\end{verbatim}
The plain \code{[:]} operator slices from beginning to end:
\begin{verbatim}
>>> print a[:,:]
[[0 1 2]
 [3 4 5]
 [6 7 8]]
\end{verbatim}
In other words, \code{[:]} with no arguments is the same as \code{[:]} for
lists --- it can be read ``all indices along this axis''.  (Actually, there is
an important distinction; see below.) So, to get the second row along the
second dimension:
\begin{verbatim}
>>> print a[:,1]
[1 4 7]
\end{verbatim}
Note that what was a ``column'' vector is now a ``row'' vector ­ any ``integer
slice'' (as in the 1 in the example above) results in a returned array with
rank one less than the input array.  There is one important distinction between
slicing arrays and slicing standard Python sequence objects. A slice of a
\class{list} is a new copy of that subset of the \class{list}; a slice of an
array is just a view into the data of the first array.  To force a copy, you
can use the \function{copy} method. For example:
\begin{verbatim}
>>> a = arange (20)
>>> b = a[3:8]
>>> c = a[3:8].copy()
>>> a[5] = -99
>>> print b
[  3   4 -99   6   7]
>>> print c
[3 4 5 6 7]
\end{verbatim}
If one does not specify as many slices as there are dimensions in an array,
then the remaining slices are assumed to be ``all''. If \var{A} is a rank-3
array, then
\begin{verbatim}
A[1] == A[1,:] == A[1,:,:]
\end{verbatim}
An additional slice notation for arrays which does not exist for Python
lists (before Python 2.3), i. e. the optional third argument, meaning 
the ``step size'', also called \index{stride}stride or increment. Its 
default value is 1, meaning return every element in the specified range.  
Alternate values allow one to skip some of the elements in the slice:
\begin{verbatim}
>>> a = arange(12)
>>> print a
[ 0  1  2  3  4  5  6  7  8  9 10 11]
>>> print a[::2]                        # return every *other* element
[ 0  2  4  6  8 10]
\end{verbatim}
\index{stride!Negative}Negative strides are allowed as long as the starting
index is greater than the stopping index:
\begin{verbatim}
>>> a = reshape(arange(9),(3,3))                                                                                          Array Basics
>>> print a
[[0 1 2]
 [3 4 5]
 [6 7 8]]
>>> print a[:, 0]
[0 3 6]
>>> print a[0:3, 0]
[0 3 6]
>>> print a[2::-1, 0]
[6 3 0]
\end{verbatim}
If a negative stride is specified and the starting or stopping indices are
omitted, they default to ``end of axis'' and ``beginning of axis''
respectively.  Thus, the following two statements are equivalent for the array
given:
\begin{verbatim}
>>> print a[2::-1, 0]
[6 3 0]
>>> print a[::-1, 0]
[6 3 0]
>>> print a[::-1]                       # this reverses only the first axis
[[6 7 8]
 [3 4 5]
 [0 1 2]]
>>> print a[::-1,::-1]                  # this reverses both axes
[[8 7 6]
 [5 4 3]
 [2 1 0]]
\end{verbatim}
One final way of slicing arrays is with the keyword \samp{...} This keyword is
somewhat complicated. It stands for ``however many `:' I need depending on the
rank of the object I'm indexing, so that the indices I \emph{do} specify are at
the end of the index list as opposed to the usual beginning''.

So, if one has a rank-3 array \var{A}, then \code{A[...,0]} is the same thing
as \code{A[:,:,0]}, but if \var{B} is rank-4, then \code{B[...,0]} is the same
thing as: \code{B[:,:,:,0]}. Only one \samp{...} is expanded in an index
expression, so if one has a rank-5 array \var{C}, then \code{C[...,0,...]} is
the same thing as \code{C[:,:,:,0,:]}.

Note that the result of assigning a slice of an array to an overlapping slice
of the same array is undefined:

\begin{verbatim}
>>> a[1:,1:] = a[:2, :2]           # don't do this!  undefined 
\end{verbatim}

\section{Index Arrays}
\label{sec:index-arrays}

Arrays used as subscripts have special meanings which implicitly invoke the
functions \function{put} (page \pageref{func:put}), \function{take} (page
\pageref{func:take}), or \function{compress} (page \pageref{func:compress}). If
the array is of \class{Bool} type, then the indexing will be treated as the
equivalent of the compress function. If the array is of an integer type, then a
\function{take} or \function{put} operation is implied. We will generalize the
existing take and put as follows: If \var{ind1}, \var{ind2}, ...  \var{indN}
are index arrays (arrays of integers whose values indicate the index into
another array), then \code{x[ind1, ind2]} forms a new array with the same shape
as \var{ind1}, \var{ind2} (they all must be broadcastable to the same shape)
and values such: \samp{result[i,j,k] = x[ind1[i,j,k], ind2[i,j,k]]} In this
example, \var{ind1}, \var{ind2} are index arrays with 3 dimensions (but they
could have an arbitrary number of dimensions).  To illustrate with some
specific examples:
\begin{verbatim}
>>> # simple index array example
>>> x = 2*arange(10)
>>> ind = array([3,6,2,4,4])
>>> x[ind]
array([ 6, 12,  4,  8,  8])
>>> # index a 2-d array
>>> x = arange(12)
>>> x.setshape((3,4))
>>> x
array([[ 0,  1,  2,  3],
  [ 4,  5,  6,  7],
  [ 8,  9, 10, 11]])
>>> ind1 = array([2,1])
>>> ind2 = array([0,2])
>>> x[ind1, ind2]
array([8, 6])
>>> # multidimensional index arrays
>>> ind1 = array([[2,2],[1,0]])
>>> ind2 = array([[2,1],[0,1]])
>>> x[ind1, ind2]
array([[10,  9],
  [ 4,  1]])
>>> # Mindblowing combination of multidimensional index arrays with
>>> # partial indexing. Strap on your seatbelts.
>>> x[ind1]
array([[[ 8,  9, 10, 11],
  [ 8,  9, 10, 11]],
  [[ 4,  5,  6,  7],
   [ 0,  1,  2,  3]]])
\end{verbatim}
Note that in this last example, each index in the single index array
(\var{ind1}) is treated as though \var{x} were given only one index. For each
of these ``single'' indices, a 1-d array is returned, thus the combination of
the 2 dimensions in the index array combined with the leftover dimension in the
array being indexed produces a 3 dimensional array.

When using constants for some of the index positions, then the result uses that
constant for all values. Slices and strides (at least initially) will not be
permitted in the same subscript as index arrays. So
\begin{verbatim}
>>> x[ind1, 2]
array([[10, 10],
  [ 6,  2]])
\end{verbatim}
would be legal, but
\begin{verbatim}
>>> x[ind1, 1:3]
Traceback (most recent call last):
[...]
    raise IndexError("Cannot mix arrays and slices as indices")
IndexError: Cannot mix arrays and slices as indices
\end{verbatim}
would not be.  Similarly for assignment:
\begin{verbatim}
x[ind1, ind2, ind3] = values
\end{verbatim}
will form a new array such that:
\begin{verbatim}
x[ind1[i,j,k], ind2[i,j,k], ind3[i,j,k]] = values[i,j,k]
\end{verbatim}

The index arrays and the value array must be broadcast consistently. (As an
example: \code{ind1.setshape((5,4))}, \code{ind2.setshape((5,))},
\code{ind3.setshape((1,4))}, and \code{values.setshape((1,))}.)
\begin{verbatim}
# Index put example, using broadcasting and illustrating that Python
# integer sequences work as indices also.
>>> x = zeros((10,10))
>>> x[[2,5,6],array([0,1,9,3])[:,NewAxis]] = 111
>>> x
array([[  0,   0,   0,   0,   0,   0,   0,   0,   0,   0],
  [  0,   0,   0,   0,   0,   0,   0,   0,   0,   0],
  [111, 111,   0, 111,   0,   0,   0,   0,   0, 111],
  [  0,   0,   0,   0,   0,   0,   0,   0,   0,   0],
  [  0,   0,   0,   0,   0,   0,   0,   0,   0,   0],
  [111, 111,   0, 111,   0,   0,   0,   0,   0, 111],
  [111, 111,   0, 111,   0,   0,   0,   0,   0, 111],
  [  0,   0,   0,   0,   0,   0,   0,   0,   0,   0],
  [  0,   0,   0,   0,   0,   0,   0,   0,   0,   0],
  [  0,   0,   0,   0,   0,   0,   0,   0,   0,   0]])
\end{verbatim}
If indices are repeated, the last value encountered will be stored. When index
values are out of range they will be clipped to the appropriate range. That is
to say, an index that is too large will be taken to refer to the last element,
and a negative index will be interpreted as zero (future versions will
interpret negative indices in the usual Python style, counting backwards from
the end). Use of the equivalent \index{take}\function{take} and
\index{put}\function{put} functions will allow other interpretations of the
indices (raise exceptions for out of bounds indices, allow negative indices to
work backwards as they do when used individually, or for indices to wrap
around). The same behavior applies for functions such as choose and where.
\begin{verbatim}
>>> x = 2*arange(10)
>>> x[[0, 5, 100, 5, -2]] = [1000, 1005, 1100, 2005, 3005]
>>> x
array([3005,    2,    4,    6,    8, 2005,   12,   14,   16, 1100])
\end{verbatim}


\section{Exception Handling}
\label{sec:exception-handling}

We desired better control over exception handling than currently exists in
Numeric. This has traditionally been a problem area (see the numerous posts in
\ulink{comp.lang.python}{news:comp.lang.python} regarding floating point
exceptions, especially those by Tim Peters). Numeric raises an exception for
integer computations that result in a divide by zero or multiplications that
result in overflows. The exception is raised after that operation has completed
on all the array elements. No exceptions are raised for floating point errors
(divide by zero, overflow, underflow, and invalid results), the compiler and
processor are left to their default behavior (which is usually to return Infs
and NaNs as values).

The approach for numarray is to provide customizable error handling behavior.
It should be possible to specify three different behaviors for each of the four
error types independently. These are:
\begin{itemize}
\item Ignore the error.
\item Print a warning.
\item Raise a Python exception.
\end{itemize}
The current implementation does that and has been tested successfully on
Windows, Solaris, Redhat and Tru64.  The implementation uses the floating point
processor ``sticky status flags'' to detect errors. One can set the error mode
by calling the error object's setMode method. For example:
\begin{verbatim}
>>> numarray.Error.setMode(all="warn") # the default mode
>>> numarray.Error.setMode(dividebyzero="raise", underflow="ignore", invalid="warn")
\end{verbatim}

The Error object can also be used in a stacking manner, by using the \function{pushMode}
and \function{popMode} methods rather than \function{setMode}.  For example:
\begin{verbatim}
>>> numarray.Error.getMode()
_NumErrorMode(overflow='warn', underflow='warn', dividebyzero='warn', invalid='warn')
>>> numarray.Error.pushMode(all="raise") # get really picky...
>>> numarray.Error.getMode()
_NumErrorMode(overflow='raise', underflow='raise', dividebyzero='raise', invalid='raise')
>>> numarray.Error.popMode()  # pop and return the ``new'' mode
_NumErrorMode(overflow='raise', underflow='raise', dividebyzero='raise', invalid='raise')
>>> numarray.Error.getMode()  # verify the original mode is back
_NumErrorMode(overflow='warn', underflow='warn', dividebyzero='warn', invalid='warn')
\end{verbatim}



Integer exception modes work the same way. Although integer computations do not
affect the floating point status flag directly, our code checks the denominator
of 0 in divisions (in much the same way Numeric does) and then performs a
floating point divide by zero to set the status flag (overflows are handled
similarly). So even integer exceptions use the floating point status flags
indirectly.


%% 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:
