summaryrefslogtreecommitdiff
path: root/doc/swig
diff options
context:
space:
mode:
Diffstat (limited to 'doc/swig')
-rw-r--r--doc/swig/Makefile36
-rw-r--r--doc/swig/README130
-rw-r--r--doc/swig/doc/Makefile51
-rw-r--r--doc/swig/doc/numpy_swig.html1244
-rw-r--r--doc/swig/doc/numpy_swig.pdfbin0 -> 168839 bytes
-rw-r--r--doc/swig/doc/numpy_swig.txt950
-rw-r--r--doc/swig/doc/testing.html482
-rw-r--r--doc/swig/doc/testing.pdfbin0 -> 72439 bytes
-rw-r--r--doc/swig/doc/testing.txt173
-rw-r--r--doc/swig/numpy.i1634
-rw-r--r--doc/swig/pyfragments.swg174
-rw-r--r--doc/swig/test/Array.i107
-rw-r--r--doc/swig/test/Array1.cxx131
-rw-r--r--doc/swig/test/Array1.h55
-rw-r--r--doc/swig/test/Array2.cxx168
-rw-r--r--doc/swig/test/Array2.h63
-rw-r--r--doc/swig/test/Farray.cxx122
-rw-r--r--doc/swig/test/Farray.h56
-rw-r--r--doc/swig/test/Farray.i73
-rw-r--r--doc/swig/test/Fortran.cxx24
-rw-r--r--doc/swig/test/Fortran.h21
-rw-r--r--doc/swig/test/Fortran.i36
-rw-r--r--doc/swig/test/Makefile34
-rw-r--r--doc/swig/test/Matrix.cxx112
-rw-r--r--doc/swig/test/Matrix.h52
-rw-r--r--doc/swig/test/Matrix.i45
-rw-r--r--doc/swig/test/Tensor.cxx131
-rw-r--r--doc/swig/test/Tensor.h52
-rw-r--r--doc/swig/test/Tensor.i49
-rw-r--r--doc/swig/test/Vector.cxx100
-rw-r--r--doc/swig/test/Vector.h58
-rw-r--r--doc/swig/test/Vector.i47
-rwxr-xr-xdoc/swig/test/setup.py66
-rwxr-xr-xdoc/swig/test/testArray.py283
-rwxr-xr-xdoc/swig/test/testFarray.py158
-rw-r--r--doc/swig/test/testFortran.py169
-rwxr-xr-xdoc/swig/test/testMatrix.py361
-rwxr-xr-xdoc/swig/test/testTensor.py401
-rwxr-xr-xdoc/swig/test/testVector.py380
39 files changed, 8228 insertions, 0 deletions
diff --git a/doc/swig/Makefile b/doc/swig/Makefile
new file mode 100644
index 000000000..b64492f45
--- /dev/null
+++ b/doc/swig/Makefile
@@ -0,0 +1,36 @@
+# List all of the subdirectories here for recursive make
+SUBDIRS = test doc
+
+# Default target
+.PHONY : default
+default:
+ @echo "There is no default make target for this Makefile"
+ @echo "Valid make targets are:"
+ @echo " test - Compile and run tests of numpy.i"
+ @echo " doc - Generate numpy.i documentation"
+ @echo " all - make test + doc"
+ @echo " clean - Remove generated files recursively"
+
+# Target all
+.PHONY : all
+all: $(SUBDIRS)
+
+# Target test
+.PHONY : test
+test:
+ cd $@ && make $@
+
+# Target doc
+.PHONY : doc
+doc:
+ cd $@ && make
+
+# Target clean
+.PHONY : clean
+clean:
+ @for dir in $(SUBDIRS); do \
+ echo ; \
+ echo Running \'make clean\' in $$dir; \
+ cd $$dir && make clean && cd ..; \
+ done; \
+ echo
diff --git a/doc/swig/README b/doc/swig/README
new file mode 100644
index 000000000..d557b305f
--- /dev/null
+++ b/doc/swig/README
@@ -0,0 +1,130 @@
+Notes for the numpy/doc/swig directory
+======================================
+
+This set of files is for developing and testing file numpy.i, which is
+intended to be a set of typemaps for helping SWIG interface between C
+and C++ code that uses C arrays and the python module NumPy. It is
+ultimately hoped that numpy.i will be included as part of the SWIG
+distribution.
+
+Documentation
+-------------
+Documentation for how to use numpy.i is in the doc directory. The
+primary source file here is numpy_swig.txt, a restructured text file
+that documents how to use numpy.i. The Makefile in doc allows for the
+conversion of numpy_swig.txt to HTML (if you have docutils installed)
+and to PDF (if you have docutils and latex/pdftex installed). This
+should not be necessary, however, as numpy_swig.html and
+numpy_swig.pdf are stored in the repository.
+
+The same is true for a file called doc/testing.txt, which describes
+the testing system used here.
+
+If you have the prerequisites installed and wish to build the HTML and
+PDF documentation, this can be achieved by calling::
+
+ $ make doc
+
+from the shell.
+
+Testing
+-------
+The tests are a good example of what we are trying to do with numpy.i.
+The files related to testing are are in the test subdirectory::
+
+ Vector.h
+ Vector.cxx
+ Vector.i
+ testVector.py
+
+ Matrix.h
+ Matrix.cxx
+ Matrix.i
+ testMatrix.py
+
+ Tensor.h
+ Tensor.cxx
+ Tensor.i
+ testTensor.py
+
+The header files contain prototypes for functions that illustrate the
+wrapping issues we wish to address. Right now, this consists of
+functions with argument signatures of the following forms. Vector.h::
+
+ (type IN_ARRAY1[ANY])
+ (type* IN_ARRAY1, int DIM1)
+ (int DIM1, type* IN_ARRAY1)
+
+ (type INPLACE_ARRAY1[ANY])
+ (type* INPLACE_ARRAY1, int DIM1)
+ (int DIM1, type* INPLACE_ARRAY1)
+
+ (type ARGOUT_ARRAY1[ANY])
+ (type* ARGOUT_ARRAY1, int DIM1)
+ (int DIM1, type* ARGOUT_ARRAY1)
+
+Matrix.h::
+
+ (type IN_ARRAY2[ANY][ANY])
+ (type* IN_ARRAY2, int DIM1, int DIM2)
+ (int DIM1, int DIM2, type* IN_ARRAY2)
+
+ (type INPLACE_ARRAY2[ANY][ANY])
+ (type* INPLACE_ARRAY2, int DIM1, int DIM2)
+ (int DIM1, int DIM2, type* INPLACE_ARRAY2)
+
+ (type ARGOUT_ARRAY2[ANY][ANY])
+
+Tensor.h::
+
+ (type IN_ARRAY3[ANY][ANY][ANY])
+ (type* IN_ARRAY3, int DIM1, int DIM2, int DIM3)
+ (int DIM1, int DIM2, int DIM3, type* IN_ARRAY3)
+
+ (type INPLACE_ARRAY3[ANY][ANY][ANY])
+ (type* INPLACE_ARRAY3, int DIM1, int DIM2, int DIM3)
+ (int DIM1, int DIM2, int DIM3, type* INPLACE_ARRAY3)
+
+ (type ARGOUT_ARRAY3[ANY][ANY][ANY])
+
+These function signatures take a pointer to an array of type "type",
+whose length is specified by the integer(s) DIM1 (and DIM2, and DIM3).
+
+The objective for the IN_ARRAY signatures is for SWIG to generate
+python wrappers that take a container that constitutes a valid
+argument to the numpy array constructor, and can be used to build an
+array of type "type". Currently, types "signed char", "unsigned
+char", "short", "unsigned short", "int", "unsigned int", "long",
+"unsigned long", "long long", "unsigned long long", "float", and
+"double" are supported and tested.
+
+The objective for the INPLACE_ARRAY signatures is for SWIG to generate
+python wrappers that accept a numpy array of any of the above-listed
+types.
+
+The source files Vector.cxx, Matrix.cxx and Tensor.cxx contain the
+actual implementations of the functions described in Vector.h,
+Matrix.h and Tensor.h. The python scripts testVector.py,
+testMatrix.py and testTensor.py test the resulting python wrappers
+using the unittest module.
+
+The SWIG interface files Vector.i, Matrix.i and Tensor.i are used to
+generate the wrapper code. The SWIG_FILE_WITH_INIT macro allows
+numpy.i to be used with multiple python modules. If it is specified,
+then the %init block found in Vector.i, Matrix.i and Tensor.i are
+required. The other things done in Vector.i, Matrix.i and Tensor.i
+are the inclusion of the appropriate header file and numpy.i file, and
+the "%apply" directives to force the functions to use the typemaps.
+
+The setup.py script is a standard python distutils script. It defines
+_Vector, _Matrix and _Tensor extension modules and Vector, Matrix and
+Tensor python modules. The Makefile automates everything, setting up
+the dependencies, calling swig to generate the wrappers, and calling
+setup.py to compile the wrapper code and generate the shared objects.
+Targets "all" (default), "test", "doc" and "clean" are supported. The
+"doc" target creates HTML documentation (with make target "html"), and
+PDF documentation (with make targets "tex" and "pdf").
+
+To build and run the test code, simply execute from the shell::
+
+ $ make test
diff --git a/doc/swig/doc/Makefile b/doc/swig/doc/Makefile
new file mode 100644
index 000000000..9223f0481
--- /dev/null
+++ b/doc/swig/doc/Makefile
@@ -0,0 +1,51 @@
+# ReStructured Text
+RST2HTML = rst2html.py
+RST2LATEX = rst2latex.py
+RFLAGS = --generator --time
+HTML_FLAGS = --no-xml-declaration
+LATEX_FLAGS =
+LATEX = pdflatex
+
+# Web pages that need to be made
+WEB_PAGES = numpy_swig.html testing.html
+
+# LaTeX files that need to be made
+LATEX_FILES = numpy_swig.tex testing.tex
+
+# PDF files that need to be made
+PDF_FILES = numpy_swig.pdf testing.pdf
+
+# Default target: documentation
+.PHONY : doc
+doc: html pdf
+
+# HTML target
+.PHONY : html
+html: $(WEB_PAGES)
+
+# Rule: %.txt -> %.html
+%.html: %.txt
+ $(RST2HTML) $(RFLAGS) $(HTML_FLAGS) $< $@
+
+# LaTeX target
+.PHONY : tex
+tex: $(LATEX_FILES)
+
+# Rule: %.txt -> %.tex
+%.tex: %.txt
+ $(RST2LATEX) $(RFLAGS) $(LATEX_FLAGS) $< $@
+
+# PDF target
+.PHONY : pdf
+pdf: $(PDF_FILES)
+
+# Rule: %.tex -> %.pdf
+%.pdf: %.tex
+ $(LATEX) $<
+ $(LATEX) $<
+
+# Clean target
+.PHONY : clean
+clean:
+ $(RM) $(LATEX_FILES)
+ $(RM) *.pyc *.aux *.dvi *.log *.out *~
diff --git a/doc/swig/doc/numpy_swig.html b/doc/swig/doc/numpy_swig.html
new file mode 100644
index 000000000..ed127f330
--- /dev/null
+++ b/doc/swig/doc/numpy_swig.html
@@ -0,0 +1,1244 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
+<title>numpy.i: a SWIG Interface File for NumPy</title>
+<meta name="author" content="Bill Spotz" />
+<meta name="date" content="1 December, 2007" />
+<style type="text/css">
+
+/*
+:Author: David Goodger
+:Contact: goodger@users.sourceforge.net
+:Date: $Date: 2005-12-18 01:56:14 +0100 (Sun, 18 Dec 2005) $
+:Revision: $Revision: 4224 $
+:Copyright: This stylesheet has been placed in the public domain.
+
+Default cascading style sheet for the HTML output of Docutils.
+
+See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
+customize this style sheet.
+*/
+
+/* used to remove borders from tables and images */
+.borderless, table.borderless td, table.borderless th {
+ border: 0 }
+
+table.borderless td, table.borderless th {
+ /* Override padding for "table.docutils td" with "! important".
+ The right padding separates the table cells. */
+ padding: 0 0.5em 0 0 ! important }
+
+.first {
+ /* Override more specific margin styles with "! important". */
+ margin-top: 0 ! important }
+
+.last, .with-subtitle {
+ margin-bottom: 0 ! important }
+
+.hidden {
+ display: none }
+
+a.toc-backref {
+ text-decoration: none ;
+ color: black }
+
+blockquote.epigraph {
+ margin: 2em 5em ; }
+
+dl.docutils dd {
+ margin-bottom: 0.5em }
+
+/* Uncomment (and remove this text!) to get bold-faced definition list terms
+dl.docutils dt {
+ font-weight: bold }
+*/
+
+div.abstract {
+ margin: 2em 5em }
+
+div.abstract p.topic-title {
+ font-weight: bold ;
+ text-align: center }
+
+div.admonition, div.attention, div.caution, div.danger, div.error,
+div.hint, div.important, div.note, div.tip, div.warning {
+ margin: 2em ;
+ border: medium outset ;
+ padding: 1em }
+
+div.admonition p.admonition-title, div.hint p.admonition-title,
+div.important p.admonition-title, div.note p.admonition-title,
+div.tip p.admonition-title {
+ font-weight: bold ;
+ font-family: sans-serif }
+
+div.attention p.admonition-title, div.caution p.admonition-title,
+div.danger p.admonition-title, div.error p.admonition-title,
+div.warning p.admonition-title {
+ color: red ;
+ font-weight: bold ;
+ font-family: sans-serif }
+
+/* Uncomment (and remove this text!) to get reduced vertical space in
+ compound paragraphs.
+div.compound .compound-first, div.compound .compound-middle {
+ margin-bottom: 0.5em }
+
+div.compound .compound-last, div.compound .compound-middle {
+ margin-top: 0.5em }
+*/
+
+div.dedication {
+ margin: 2em 5em ;
+ text-align: center ;
+ font-style: italic }
+
+div.dedication p.topic-title {
+ font-weight: bold ;
+ font-style: normal }
+
+div.figure {
+ margin-left: 2em ;
+ margin-right: 2em }
+
+div.footer, div.header {
+ clear: both;
+ font-size: smaller }
+
+div.line-block {
+ display: block ;
+ margin-top: 1em ;
+ margin-bottom: 1em }
+
+div.line-block div.line-block {
+ margin-top: 0 ;
+ margin-bottom: 0 ;
+ margin-left: 1.5em }
+
+div.sidebar {
+ margin-left: 1em ;
+ border: medium outset ;
+ padding: 1em ;
+ background-color: #ffffee ;
+ width: 40% ;
+ float: right ;
+ clear: right }
+
+div.sidebar p.rubric {
+ font-family: sans-serif ;
+ font-size: medium }
+
+div.system-messages {
+ margin: 5em }
+
+div.system-messages h1 {
+ color: red }
+
+div.system-message {
+ border: medium outset ;
+ padding: 1em }
+
+div.system-message p.system-message-title {
+ color: red ;
+ font-weight: bold }
+
+div.topic {
+ margin: 2em }
+
+h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
+h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
+ margin-top: 0.4em }
+
+h1.title {
+ text-align: center }
+
+h2.subtitle {
+ text-align: center }
+
+hr.docutils {
+ width: 75% }
+
+img.align-left {
+ clear: left }
+
+img.align-right {
+ clear: right }
+
+ol.simple, ul.simple {
+ margin-bottom: 1em }
+
+ol.arabic {
+ list-style: decimal }
+
+ol.loweralpha {
+ list-style: lower-alpha }
+
+ol.upperalpha {
+ list-style: upper-alpha }
+
+ol.lowerroman {
+ list-style: lower-roman }
+
+ol.upperroman {
+ list-style: upper-roman }
+
+p.attribution {
+ text-align: right ;
+ margin-left: 50% }
+
+p.caption {
+ font-style: italic }
+
+p.credits {
+ font-style: italic ;
+ font-size: smaller }
+
+p.label {
+ white-space: nowrap }
+
+p.rubric {
+ font-weight: bold ;
+ font-size: larger ;
+ color: maroon ;
+ text-align: center }
+
+p.sidebar-title {
+ font-family: sans-serif ;
+ font-weight: bold ;
+ font-size: larger }
+
+p.sidebar-subtitle {
+ font-family: sans-serif ;
+ font-weight: bold }
+
+p.topic-title {
+ font-weight: bold }
+
+pre.address {
+ margin-bottom: 0 ;
+ margin-top: 0 ;
+ font-family: serif ;
+ font-size: 100% }
+
+pre.literal-block, pre.doctest-block {
+ margin-left: 2em ;
+ margin-right: 2em ;
+ background-color: #eeeeee }
+
+span.classifier {
+ font-family: sans-serif ;
+ font-style: oblique }
+
+span.classifier-delimiter {
+ font-family: sans-serif ;
+ font-weight: bold }
+
+span.interpreted {
+ font-family: sans-serif }
+
+span.option {
+ white-space: nowrap }
+
+span.pre {
+ white-space: pre }
+
+span.problematic {
+ color: red }
+
+span.section-subtitle {
+ /* font-size relative to parent (h1..h6 element) */
+ font-size: 80% }
+
+table.citation {
+ border-left: solid 1px gray;
+ margin-left: 1px }
+
+table.docinfo {
+ margin: 2em 4em }
+
+table.docutils {
+ margin-top: 0.5em ;
+ margin-bottom: 0.5em }
+
+table.footnote {
+ border-left: solid 1px black;
+ margin-left: 1px }
+
+table.docutils td, table.docutils th,
+table.docinfo td, table.docinfo th {
+ padding-left: 0.5em ;
+ padding-right: 0.5em ;
+ vertical-align: top }
+
+table.docutils th.field-name, table.docinfo th.docinfo-name {
+ font-weight: bold ;
+ text-align: left ;
+ white-space: nowrap ;
+ padding-left: 0 }
+
+h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
+h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
+ font-size: 100% }
+
+tt.docutils {
+ background-color: #eeeeee }
+
+ul.auto-toc {
+ list-style-type: none }
+
+</style>
+</head>
+<body>
+<div class="document" id="numpy-i-a-swig-interface-file-for-numpy">
+<h1 class="title">numpy.i: a SWIG Interface File for NumPy</h1>
+<table class="docinfo" frame="void" rules="none">
+<col class="docinfo-name" />
+<col class="docinfo-content" />
+<tbody valign="top">
+<tr><th class="docinfo-name">Author:</th>
+<td>Bill Spotz</td></tr>
+<tr class="field"><th class="docinfo-name">Institution:</th><td class="field-body">Sandia National Laboratories</td>
+</tr>
+<tr><th class="docinfo-name">Date:</th>
+<td>1 December, 2007</td></tr>
+</tbody>
+</table>
+<div class="contents topic">
+<p class="topic-title first"><a id="contents" name="contents">Contents</a></p>
+<ul class="simple">
+<li><a class="reference" href="#introduction" id="id1" name="id1">Introduction</a></li>
+<li><a class="reference" href="#using-numpy-i" id="id2" name="id2">Using numpy.i</a></li>
+<li><a class="reference" href="#available-typemaps" id="id3" name="id3">Available Typemaps</a><ul>
+<li><a class="reference" href="#input-arrays" id="id4" name="id4">Input Arrays</a></li>
+<li><a class="reference" href="#in-place-arrays" id="id5" name="id5">In-Place Arrays</a></li>
+<li><a class="reference" href="#argout-arrays" id="id6" name="id6">Argout Arrays</a></li>
+<li><a class="reference" href="#argoutview-arrays" id="id7" name="id7">Argoutview Arrays</a></li>
+<li><a class="reference" href="#output-arrays" id="id8" name="id8">Output Arrays</a></li>
+<li><a class="reference" href="#other-common-types-bool" id="id9" name="id9">Other Common Types: bool</a></li>
+<li><a class="reference" href="#other-common-types-complex" id="id10" name="id10">Other Common Types: complex</a></li>
+</ul>
+</li>
+<li><a class="reference" href="#numpy-array-scalars-and-swig" id="id11" name="id11">NumPy Array Scalars and SWIG</a><ul>
+<li><a class="reference" href="#why-is-there-a-second-file" id="id12" name="id12">Why is There a Second File?</a></li>
+</ul>
+</li>
+<li><a class="reference" href="#helper-functions" id="id13" name="id13">Helper Functions</a><ul>
+<li><a class="reference" href="#macros" id="id14" name="id14">Macros</a></li>
+<li><a class="reference" href="#routines" id="id15" name="id15">Routines</a></li>
+</ul>
+</li>
+<li><a class="reference" href="#beyond-the-provided-typemaps" id="id16" name="id16">Beyond the Provided Typemaps</a><ul>
+<li><a class="reference" href="#a-common-example" id="id17" name="id17">A Common Example</a></li>
+<li><a class="reference" href="#other-situations" id="id18" name="id18">Other Situations</a></li>
+<li><a class="reference" href="#a-final-note" id="id19" name="id19">A Final Note</a></li>
+</ul>
+</li>
+<li><a class="reference" href="#summary" id="id20" name="id20">Summary</a></li>
+<li><a class="reference" href="#acknowledgements" id="id21" name="id21">Acknowledgements</a></li>
+</ul>
+</div>
+<div class="section">
+<h1><a class="toc-backref" href="#id1" id="introduction" name="introduction">Introduction</a></h1>
+<p>The Simple Wrapper and Interface Generator (or <a class="reference" href="http://www.swig.org">SWIG</a>) is a powerful tool for generating wrapper
+code for interfacing to a wide variety of scripting languages.
+<a class="reference" href="http://www.swig.org">SWIG</a> can parse header files, and using only the code prototypes,
+create an interface to the target language. But <a class="reference" href="http://www.swig.org">SWIG</a> is not
+omnipotent. For example, it cannot know from the prototype:</p>
+<pre class="literal-block">
+double rms(double* seq, int n);
+</pre>
+<p>what exactly <tt class="docutils literal"><span class="pre">seq</span></tt> is. Is it a single value to be altered in-place?
+Is it an array, and if so what is its length? Is it input-only?
+Output-only? Input-output? <a class="reference" href="http://www.swig.org">SWIG</a> cannot determine these details,
+and does not attempt to do so.</p>
+<p>If we designed <tt class="docutils literal"><span class="pre">rms</span></tt>, we probably made it a routine that takes an
+input-only array of length <tt class="docutils literal"><span class="pre">n</span></tt> of <tt class="docutils literal"><span class="pre">double</span></tt> values called <tt class="docutils literal"><span class="pre">seq</span></tt>
+and returns the root mean square. The default behavior of <a class="reference" href="http://www.swig.org">SWIG</a>,
+however, will be to create a wrapper function that compiles, but is
+nearly impossible to use from the scripting language in the way the C
+routine was intended.</p>
+<p>For <a class="reference" href="http://www.python.org">python</a>, the preferred way of handling
+contiguous (or technically, <em>strided</em>) blocks of homogeneous data is
+with the module <a class="reference" href="http://numpy.scipy.org">NumPy</a>, which provides full
+object-oriented access to multidimensial arrays of data. Therefore,
+the most logical <a class="reference" href="http://www.python.org">python</a> interface for the <tt class="docutils literal"><span class="pre">rms</span></tt> function would be
+(including doc string):</p>
+<pre class="literal-block">
+def rms(seq):
+ &quot;&quot;&quot;
+ rms: return the root mean square of a sequence
+ rms(numpy.ndarray) -&gt; double
+ rms(list) -&gt; double
+ rms(tuple) -&gt; double
+ &quot;&quot;&quot;
+</pre>
+<p>where <tt class="docutils literal"><span class="pre">seq</span></tt> would be a <a class="reference" href="http://numpy.scipy.org">NumPy</a> array of <tt class="docutils literal"><span class="pre">double</span></tt> values, and its
+length <tt class="docutils literal"><span class="pre">n</span></tt> would be extracted from <tt class="docutils literal"><span class="pre">seq</span></tt> internally before being
+passed to the C routine. Even better, since <a class="reference" href="http://numpy.scipy.org">NumPy</a> supports
+construction of arrays from arbitrary <a class="reference" href="http://www.python.org">python</a> sequences, <tt class="docutils literal"><span class="pre">seq</span></tt>
+itself could be a nearly arbitrary sequence (so long as each element
+can be converted to a <tt class="docutils literal"><span class="pre">double</span></tt>) and the wrapper code would
+internally convert it to a <a class="reference" href="http://numpy.scipy.org">NumPy</a> array before extracting its data
+and length.</p>
+<p><a class="reference" href="http://www.swig.org">SWIG</a> allows these types of conversions to be defined via a
+mechanism called typemaps. This document provides information on how
+to use <tt class="docutils literal"><span class="pre">numpy.i</span></tt>, a <a class="reference" href="http://www.swig.org">SWIG</a> interface file that defines a series of
+typemaps intended to make the type of array-related conversions
+described above relatively simple to implement. For example, suppose
+that the <tt class="docutils literal"><span class="pre">rms</span></tt> function prototype defined above was in a header file
+named <tt class="docutils literal"><span class="pre">rms.h</span></tt>. To obtain the <a class="reference" href="http://www.python.org">python</a> interface discussed above,
+your <a class="reference" href="http://www.swig.org">SWIG</a> interface file would need the following:</p>
+<pre class="literal-block">
+%{
+#define SWIG_FILE_WITH_INIT
+#include &quot;rms.h&quot;
+%}
+
+%include &quot;numpy.i&quot;
+
+%init %{
+import_array();
+%}
+
+%apply (double* IN_ARRAY1, int DIM1) {(double* seq, int n)};
+%include &quot;rms.h&quot;
+</pre>
+<p>Typemaps are keyed off a list of one or more function arguments,
+either by type or by type and name. We will refer to such lists as
+<em>signatures</em>. One of the many typemaps defined by <tt class="docutils literal"><span class="pre">numpy.i</span></tt> is used
+above and has the signature <tt class="docutils literal"><span class="pre">(double*</span> <span class="pre">IN_ARRAY1,</span> <span class="pre">int</span> <span class="pre">DIM1)</span></tt>. The
+argument names are intended to suggest that the <tt class="docutils literal"><span class="pre">double*</span></tt> argument
+is an input array of one dimension and that the <tt class="docutils literal"><span class="pre">int</span></tt> represents
+that dimension. This is precisely the pattern in the <tt class="docutils literal"><span class="pre">rms</span></tt>
+prototype.</p>
+<p>Most likely, no actual prototypes to be wrapped will have the argument
+names <tt class="docutils literal"><span class="pre">IN_ARRAY1</span></tt> and <tt class="docutils literal"><span class="pre">DIM1</span></tt>. We use the <tt class="docutils literal"><span class="pre">%apply</span></tt> directive to
+apply the typemap for one-dimensional input arrays of type <tt class="docutils literal"><span class="pre">double</span></tt>
+to the actual prototype used by <tt class="docutils literal"><span class="pre">rms</span></tt>. Using <tt class="docutils literal"><span class="pre">numpy.i</span></tt>
+effectively, therefore, requires knowing what typemaps are available
+and what they do.</p>
+<p>A <a class="reference" href="http://www.swig.org">SWIG</a> interface file that includes the <a class="reference" href="http://www.swig.org">SWIG</a> directives given
+above will produce wrapper code that looks something like:</p>
+<pre class="literal-block">
+ 1 PyObject *_wrap_rms(PyObject *args) {
+ 2 PyObject *resultobj = 0;
+ 3 double *arg1 = (double *) 0 ;
+ 4 int arg2 ;
+ 5 double result;
+ 6 PyArrayObject *array1 = NULL ;
+ 7 int is_new_object1 = 0 ;
+ 8 PyObject * obj0 = 0 ;
+ 9
+10 if (!PyArg_ParseTuple(args,(char *)&quot;O:rms&quot;,&amp;obj0)) SWIG_fail;
+11 {
+12 array1 = obj_to_array_contiguous_allow_conversion(
+13 obj0, NPY_DOUBLE, &amp;is_new_object1);
+14 npy_intp size[1] = {
+15 -1
+16 };
+17 if (!array1 || !require_dimensions(array1, 1) ||
+18 !require_size(array1, size, 1)) SWIG_fail;
+19 arg1 = (double*) array1-&gt;data;
+20 arg2 = (int) array1-&gt;dimensions[0];
+21 }
+22 result = (double)rms(arg1,arg2);
+23 resultobj = SWIG_From_double((double)(result));
+24 {
+25 if (is_new_object1 &amp;&amp; array1) Py_DECREF(array1);
+26 }
+27 return resultobj;
+28 fail:
+29 {
+30 if (is_new_object1 &amp;&amp; array1) Py_DECREF(array1);
+31 }
+32 return NULL;
+33 }
+</pre>
+<p>The typemaps from <tt class="docutils literal"><span class="pre">numpy.i</span></tt> are responsible for the following lines
+of code: 12--20, 25 and 30. Line 10 parses the input to the <tt class="docutils literal"><span class="pre">rms</span></tt>
+function. From the format string <tt class="docutils literal"><span class="pre">&quot;O:rms&quot;</span></tt>, we can see that the
+argument list is expected to be a single <a class="reference" href="http://www.python.org">python</a> object (specified
+by the <tt class="docutils literal"><span class="pre">O</span></tt> before the colon) and whose pointer is stored in
+<tt class="docutils literal"><span class="pre">obj0</span></tt>. A number of functions, supplied by <tt class="docutils literal"><span class="pre">numpy.i</span></tt>, are called
+to make and check the (possible) conversion from a generic <a class="reference" href="http://www.python.org">python</a>
+object to a <a class="reference" href="http://numpy.scipy.org">NumPy</a> array. These functions are explained in the
+section <a class="reference" href="#helper-functions">Helper Functions</a>, but hopefully their names are
+self-explanatory. At line 12 we use <tt class="docutils literal"><span class="pre">obj0</span></tt> to construct a <a class="reference" href="http://numpy.scipy.org">NumPy</a>
+array. At line 17, we check the validity of the result: that it is
+non-null and that it has a single dimension of arbitrary length. Once
+these states are verified, we extract the data buffer and length in
+lines 19 and 20 so that we can call the underlying C function at line
+22. Line 25 performs memory management for the case where we have
+created a new array that is no longer needed.</p>
+<p>This code has a significant amount of error handling. Note the
+<tt class="docutils literal"><span class="pre">SWIG_fail</span></tt> is a macro for <tt class="docutils literal"><span class="pre">goto</span> <span class="pre">fail</span></tt>, refering to the label at
+line 28. If the user provides the wrong number of arguments, this
+will be caught at line 10. If construction of the <a class="reference" href="http://numpy.scipy.org">NumPy</a> array
+fails or produces an array with the wrong number of dimensions, these
+errors are caught at line 17. And finally, if an error is detected,
+memory is still managed correctly at line 30.</p>
+<p>Note that if the C function signature was in a different order:</p>
+<pre class="literal-block">
+double rms(int n, double* seq);
+</pre>
+<p>that <a class="reference" href="http://www.swig.org">SWIG</a> would not match the typemap signature given above with
+the argument list for <tt class="docutils literal"><span class="pre">rms</span></tt>. Fortunately, <tt class="docutils literal"><span class="pre">numpy.i</span></tt> has a set of
+typemaps with the data pointer given last:</p>
+<pre class="literal-block">
+%apply (int DIM1, double* IN_ARRAY1) {(int n, double* seq)};
+</pre>
+<p>This simply has the effect of switching the definitions of <tt class="docutils literal"><span class="pre">arg1</span></tt>
+and <tt class="docutils literal"><span class="pre">arg2</span></tt> in lines 3 and 4 of the generated code above, and their
+assignments in lines 19 and 20.</p>
+</div>
+<div class="section">
+<h1><a class="toc-backref" href="#id2" id="using-numpy-i" name="using-numpy-i">Using numpy.i</a></h1>
+<p>The <tt class="docutils literal"><span class="pre">numpy.i</span></tt> file is currently located in the <tt class="docutils literal"><span class="pre">numpy/docs/swig</span></tt>
+sub-directory under the <tt class="docutils literal"><span class="pre">numpy</span></tt> installation directory. Typically,
+you will want to copy it to the directory where you are developing
+your wrappers. If it is ever adopted by <a class="reference" href="http://www.swig.org">SWIG</a> developers, then it
+will be installed in a standard place where <a class="reference" href="http://www.swig.org">SWIG</a> can find it.</p>
+<p>A simple module that only uses a single <a class="reference" href="http://www.swig.org">SWIG</a> interface file should
+include the following:</p>
+<pre class="literal-block">
+%{
+#define SWIG_FILE_WITH_INIT
+%}
+%include &quot;numpy.i&quot;
+%init %{
+import_array();
+%}
+</pre>
+<p>Within a compiled <a class="reference" href="http://www.python.org">python</a> module, <tt class="docutils literal"><span class="pre">import_array()</span></tt> should only get
+called once. This could be in a C/C++ file that you have written and
+is linked to the module. If this is the case, then none of your
+interface files should <tt class="docutils literal"><span class="pre">#define</span> <span class="pre">SWIG_FILE_WITH_INIT</span></tt> or call
+<tt class="docutils literal"><span class="pre">import_array()</span></tt>. Or, this initialization call could be in a
+wrapper file generated by <a class="reference" href="http://www.swig.org">SWIG</a> from an interface file that has the
+<tt class="docutils literal"><span class="pre">%init</span></tt> block as above. If this is the case, and you have more than
+one <a class="reference" href="http://www.swig.org">SWIG</a> interface file, then only one interface file should
+<tt class="docutils literal"><span class="pre">#define</span> <span class="pre">SWIG_FILE_WITH_INIT</span></tt> and call <tt class="docutils literal"><span class="pre">import_array()</span></tt>.</p>
+</div>
+<div class="section">
+<h1><a class="toc-backref" href="#id3" id="available-typemaps" name="available-typemaps">Available Typemaps</a></h1>
+<p>The typemap directives provided by <tt class="docutils literal"><span class="pre">numpy.i</span></tt> for arrays of different
+data types, say <tt class="docutils literal"><span class="pre">double</span></tt> and <tt class="docutils literal"><span class="pre">int</span></tt>, and dimensions of different
+types, say <tt class="docutils literal"><span class="pre">int</span></tt> or <tt class="docutils literal"><span class="pre">long</span></tt>, are identical to one another except
+for the C and <a class="reference" href="http://numpy.scipy.org">NumPy</a> type specifications. The typemaps are
+therefore implemented (typically behind the scenes) via a macro:</p>
+<pre class="literal-block">
+%numpy_typemaps(DATA_TYPE, DATA_TYPECODE, DIM_TYPE)
+</pre>
+<p>that can be invoked for appropriate <tt class="docutils literal"><span class="pre">(DATA_TYPE,</span> <span class="pre">DATA_TYPECODE,</span>
+<span class="pre">DIM_TYPE)</span></tt> triplets. For example:</p>
+<pre class="literal-block">
+%numpy_typemaps(double, NPY_DOUBLE, int)
+%numpy_typemaps(int, NPY_INT , int)
+</pre>
+<p>The <tt class="docutils literal"><span class="pre">numpy.i</span></tt> interface file uses the <tt class="docutils literal"><span class="pre">%numpy_typemaps</span></tt> macro to
+implement typemaps for the following C data types and <tt class="docutils literal"><span class="pre">int</span></tt>
+dimension types:</p>
+<blockquote>
+<ul class="simple">
+<li><tt class="docutils literal"><span class="pre">signed</span> <span class="pre">char</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">unsigned</span> <span class="pre">char</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">short</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">unsigned</span> <span class="pre">short</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">int</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">unsigned</span> <span class="pre">int</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">long</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">unsigned</span> <span class="pre">long</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">long</span> <span class="pre">long</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">unsigned</span> <span class="pre">long</span> <span class="pre">long</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">float</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">double</span></tt></li>
+</ul>
+</blockquote>
+<p>In the following descriptions, we reference a generic <tt class="docutils literal"><span class="pre">DATA_TYPE</span></tt>, which
+could be any of the C data types listed above, and <tt class="docutils literal"><span class="pre">DIM_TYPE</span></tt> which
+should be one of the many types of integers.</p>
+<p>The typemap signatures are largely differentiated on the name given to
+the buffer pointer. Names with <tt class="docutils literal"><span class="pre">FARRAY</span></tt> are for FORTRAN-ordered
+arrays, and names with <tt class="docutils literal"><span class="pre">ARRAY</span></tt> are for C-ordered (or 1D arrays).</p>
+<div class="section">
+<h2><a class="toc-backref" href="#id4" id="input-arrays" name="input-arrays">Input Arrays</a></h2>
+<p>Input arrays are defined as arrays of data that are passed into a
+routine but are not altered in-place or returned to the user. The
+<a class="reference" href="http://www.python.org">python</a> input array is therefore allowed to be almost any <a class="reference" href="http://www.python.org">python</a>
+sequence (such as a list) that can be converted to the requested type
+of array. The input array signatures are</p>
+<p>1D:</p>
+<blockquote>
+<ul class="simple">
+<li><tt class="docutils literal"><span class="pre">(</span> <span class="pre">DATA_TYPE</span> <span class="pre">IN_ARRAY1[ANY]</span> <span class="pre">)</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">(</span> <span class="pre">DATA_TYPE*</span> <span class="pre">IN_ARRAY1,</span> <span class="pre">int</span> <span class="pre">DIM1</span> <span class="pre">)</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">(</span> <span class="pre">int</span> <span class="pre">DIM1,</span> <span class="pre">DATA_TYPE*</span> <span class="pre">IN_ARRAY1</span> <span class="pre">)</span></tt></li>
+</ul>
+</blockquote>
+<p>2D:</p>
+<blockquote>
+<ul class="simple">
+<li><tt class="docutils literal"><span class="pre">(</span> <span class="pre">DATA_TYPE</span> <span class="pre">IN_ARRAY2[ANY][ANY]</span> <span class="pre">)</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">(</span> <span class="pre">DATA_TYPE*</span> <span class="pre">IN_ARRAY2,</span> <span class="pre">int</span> <span class="pre">DIM1,</span> <span class="pre">int</span> <span class="pre">DIM2</span> <span class="pre">)</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">(</span> <span class="pre">int</span> <span class="pre">DIM1,</span> <span class="pre">int</span> <span class="pre">DIM2,</span> <span class="pre">DATA_TYPE*</span> <span class="pre">IN_ARRAY2</span> <span class="pre">)</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">(</span> <span class="pre">DATA_TYPE*</span> <span class="pre">IN_FARRAY2,</span> <span class="pre">int</span> <span class="pre">DIM1,</span> <span class="pre">int</span> <span class="pre">DIM2</span> <span class="pre">)</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">(</span> <span class="pre">int</span> <span class="pre">DIM1,</span> <span class="pre">int</span> <span class="pre">DIM2,</span> <span class="pre">DATA_TYPE*</span> <span class="pre">IN_FARRAY2</span> <span class="pre">)</span></tt></li>
+</ul>
+</blockquote>
+<p>3D:</p>
+<blockquote>
+<ul class="simple">
+<li><tt class="docutils literal"><span class="pre">(</span> <span class="pre">DATA_TYPE</span> <span class="pre">IN_ARRAY3[ANY][ANY][ANY]</span> <span class="pre">)</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">(</span> <span class="pre">DATA_TYPE*</span> <span class="pre">IN_ARRAY3,</span> <span class="pre">int</span> <span class="pre">DIM1,</span> <span class="pre">int</span> <span class="pre">DIM2,</span> <span class="pre">int</span> <span class="pre">DIM3</span> <span class="pre">)</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">(</span> <span class="pre">int</span> <span class="pre">DIM1,</span> <span class="pre">int</span> <span class="pre">DIM2,</span> <span class="pre">int</span> <span class="pre">DIM3,</span> <span class="pre">DATA_TYPE*</span> <span class="pre">IN_ARRAY3</span> <span class="pre">)</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">(</span> <span class="pre">DATA_TYPE*</span> <span class="pre">IN_FARRAY3,</span> <span class="pre">int</span> <span class="pre">DIM1,</span> <span class="pre">int</span> <span class="pre">DIM2,</span> <span class="pre">int</span> <span class="pre">DIM3</span> <span class="pre">)</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">(</span> <span class="pre">int</span> <span class="pre">DIM1,</span> <span class="pre">int</span> <span class="pre">DIM2,</span> <span class="pre">int</span> <span class="pre">DIM3,</span> <span class="pre">DATA_TYPE*</span> <span class="pre">IN_FARRAY3</span> <span class="pre">)</span></tt></li>
+</ul>
+</blockquote>
+<p>The first signature listed, <tt class="docutils literal"><span class="pre">(</span> <span class="pre">DATA_TYPE</span> <span class="pre">IN_ARRAY[ANY]</span> <span class="pre">)</span></tt> is for
+one-dimensional arrays with hard-coded dimensions. Likewise,
+<tt class="docutils literal"><span class="pre">(</span> <span class="pre">DATA_TYPE</span> <span class="pre">IN_ARRAY2[ANY][ANY]</span> <span class="pre">)</span></tt> is for two-dimensional arrays
+with hard-coded dimensions, and similarly for three-dimensional.</p>
+</div>
+<div class="section">
+<h2><a class="toc-backref" href="#id5" id="in-place-arrays" name="in-place-arrays">In-Place Arrays</a></h2>
+<p>In-place arrays are defined as arrays that are modified in-place. The
+input values may or may not be used, but the values at the time the
+function returns are significant. The provided <a class="reference" href="http://www.python.org">python</a> argument
+must therefore be a <a class="reference" href="http://numpy.scipy.org">NumPy</a> array of the required type. The in-place
+signatures are</p>
+<p>1D:</p>
+<blockquote>
+<ul class="simple">
+<li><tt class="docutils literal"><span class="pre">(</span> <span class="pre">DATA_TYPE</span> <span class="pre">INPLACE_ARRAY1[ANY]</span> <span class="pre">)</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">(</span> <span class="pre">DATA_TYPE*</span> <span class="pre">INPLACE_ARRAY1,</span> <span class="pre">int</span> <span class="pre">DIM1</span> <span class="pre">)</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">(</span> <span class="pre">int</span> <span class="pre">DIM1,</span> <span class="pre">DATA_TYPE*</span> <span class="pre">INPLACE_ARRAY1</span> <span class="pre">)</span></tt></li>
+</ul>
+</blockquote>
+<p>2D:</p>
+<blockquote>
+<ul class="simple">
+<li><tt class="docutils literal"><span class="pre">(</span> <span class="pre">DATA_TYPE</span> <span class="pre">INPLACE_ARRAY2[ANY][ANY]</span> <span class="pre">)</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">(</span> <span class="pre">DATA_TYPE*</span> <span class="pre">INPLACE_ARRAY2,</span> <span class="pre">int</span> <span class="pre">DIM1,</span> <span class="pre">int</span> <span class="pre">DIM2</span> <span class="pre">)</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">(</span> <span class="pre">int</span> <span class="pre">DIM1,</span> <span class="pre">int</span> <span class="pre">DIM2,</span> <span class="pre">DATA_TYPE*</span> <span class="pre">INPLACE_ARRAY2</span> <span class="pre">)</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">(</span> <span class="pre">DATA_TYPE*</span> <span class="pre">INPLACE_FARRAY2,</span> <span class="pre">int</span> <span class="pre">DIM1,</span> <span class="pre">int</span> <span class="pre">DIM2</span> <span class="pre">)</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">(</span> <span class="pre">int</span> <span class="pre">DIM1,</span> <span class="pre">int</span> <span class="pre">DIM2,</span> <span class="pre">DATA_TYPE*</span> <span class="pre">INPLACE_FARRAY2</span> <span class="pre">)</span></tt></li>
+</ul>
+</blockquote>
+<p>3D:</p>
+<blockquote>
+<ul class="simple">
+<li><tt class="docutils literal"><span class="pre">(</span> <span class="pre">DATA_TYPE</span> <span class="pre">INPLACE_ARRAY3[ANY][ANY][ANY]</span> <span class="pre">)</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">(</span> <span class="pre">DATA_TYPE*</span> <span class="pre">INPLACE_ARRAY3,</span> <span class="pre">int</span> <span class="pre">DIM1,</span> <span class="pre">int</span> <span class="pre">DIM2,</span> <span class="pre">int</span> <span class="pre">DIM3</span> <span class="pre">)</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">(</span> <span class="pre">int</span> <span class="pre">DIM1,</span> <span class="pre">int</span> <span class="pre">DIM2,</span> <span class="pre">int</span> <span class="pre">DIM3,</span> <span class="pre">DATA_TYPE*</span> <span class="pre">INPLACE_ARRAY3</span> <span class="pre">)</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">(</span> <span class="pre">DATA_TYPE*</span> <span class="pre">INPLACE_FARRAY3,</span> <span class="pre">int</span> <span class="pre">DIM1,</span> <span class="pre">int</span> <span class="pre">DIM2,</span> <span class="pre">int</span> <span class="pre">DIM3</span> <span class="pre">)</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">(</span> <span class="pre">int</span> <span class="pre">DIM1,</span> <span class="pre">int</span> <span class="pre">DIM2,</span> <span class="pre">int</span> <span class="pre">DIM3,</span> <span class="pre">DATA_TYPE*</span> <span class="pre">INPLACE_FARRAY3</span> <span class="pre">)</span></tt></li>
+</ul>
+</blockquote>
+<p>These typemaps now check to make sure that the <tt class="docutils literal"><span class="pre">INPLACE_ARRAY</span></tt>
+arguments use native byte ordering. If not, an exception is raised.</p>
+</div>
+<div class="section">
+<h2><a class="toc-backref" href="#id6" id="argout-arrays" name="argout-arrays">Argout Arrays</a></h2>
+<p>Argout arrays are arrays that appear in the input arguments in C, but
+are in fact output arrays. This pattern occurs often when there is
+more than one output variable and the single return argument is
+therefore not sufficient. In <a class="reference" href="http://www.python.org">python</a>, the convential way to return
+multiple arguments is to pack them into a sequence (tuple, list, etc.)
+and return the sequence. This is what the argout typemaps do. If a
+wrapped function that uses these argout typemaps has more than one
+return argument, they are packed into a tuple or list, depending on
+the version of <a class="reference" href="http://www.python.org">python</a>. The <a class="reference" href="http://www.python.org">python</a> user does not pass these
+arrays in, they simply get returned. For the case where a dimension
+is specified, the python user must provide that dimension as an
+argument. The argout signatures are</p>
+<p>1D:</p>
+<blockquote>
+<ul class="simple">
+<li><tt class="docutils literal"><span class="pre">(</span> <span class="pre">DATA_TYPE</span> <span class="pre">ARGOUT_ARRAY1[ANY]</span> <span class="pre">)</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">(</span> <span class="pre">DATA_TYPE*</span> <span class="pre">ARGOUT_ARRAY1,</span> <span class="pre">int</span> <span class="pre">DIM1</span> <span class="pre">)</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">(</span> <span class="pre">int</span> <span class="pre">DIM1,</span> <span class="pre">DATA_TYPE*</span> <span class="pre">ARGOUT_ARRAY1</span> <span class="pre">)</span></tt></li>
+</ul>
+</blockquote>
+<p>2D:</p>
+<blockquote>
+<ul class="simple">
+<li><tt class="docutils literal"><span class="pre">(</span> <span class="pre">DATA_TYPE</span> <span class="pre">ARGOUT_ARRAY2[ANY][ANY]</span> <span class="pre">)</span></tt></li>
+</ul>
+</blockquote>
+<p>3D:</p>
+<blockquote>
+<ul class="simple">
+<li><tt class="docutils literal"><span class="pre">(</span> <span class="pre">DATA_TYPE</span> <span class="pre">ARGOUT_ARRAY3[ANY][ANY][ANY]</span> <span class="pre">)</span></tt></li>
+</ul>
+</blockquote>
+<p>These are typically used in situations where in C/C++, you would
+allocate a(n) array(s) on the heap, and call the function to fill the
+array(s) values. In <a class="reference" href="http://www.python.org">python</a>, the arrays are allocated for you and
+returned as new array objects.</p>
+<p>Note that we support <tt class="docutils literal"><span class="pre">DATA_TYPE*</span></tt> argout typemaps in 1D, but not 2D
+or 3D. This is because of a quirk with the <a class="reference" href="http://www.swig.org">SWIG</a> typemap syntax and
+cannot be avoided. Note that for these types of 1D typemaps, the
+<a class="reference" href="http://www.python.org">python</a> function will take a single argument representing <tt class="docutils literal"><span class="pre">DIM1</span></tt>.</p>
+</div>
+<div class="section">
+<h2><a class="toc-backref" href="#id7" id="argoutview-arrays" name="argoutview-arrays">Argoutview Arrays</a></h2>
+<p>Argoutview arrays are for when your C code provides you with a view of
+its internal data and does not require any memory to be allocated by
+the user. This can be dangerous. There is almost no way to guarantee
+that the internal data from the C code will remain in existence for
+the entire lifetime of the <a class="reference" href="http://numpy.scipy.org">NumPy</a> array that encapsulates it. If
+the user destroys the object that provides the view of the data before
+destroying the <a class="reference" href="http://numpy.scipy.org">NumPy</a> array, then using that array my result in bad
+memory references or segmentation faults. Nevertheless, there are
+situations, working with large data sets, where you simply have no
+other choice.</p>
+<p>The C code to be wrapped for argoutview arrays are characterized by
+pointers: pointers to the dimensions and double pointers to the data,
+so that these values can be passed back to the user. The argoutview
+typemap signatures are therefore</p>
+<p>1D:</p>
+<blockquote>
+<ul class="simple">
+<li><tt class="docutils literal"><span class="pre">(</span> <span class="pre">DATA_TYPE**</span> <span class="pre">ARGOUTVIEW_ARRAY1,</span> <span class="pre">DIM_TYPE*</span> <span class="pre">DIM1</span> <span class="pre">)</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">(</span> <span class="pre">DIM_TYPE*</span> <span class="pre">DIM1,</span> <span class="pre">DATA_TYPE**</span> <span class="pre">ARGOUTVIEW_ARRAY1</span> <span class="pre">)</span></tt></li>
+</ul>
+</blockquote>
+<p>2D:</p>
+<blockquote>
+<ul class="simple">
+<li><tt class="docutils literal"><span class="pre">(</span> <span class="pre">DATA_TYPE**</span> <span class="pre">ARGOUTVIEW_ARRAY2,</span> <span class="pre">DIM_TYPE*</span> <span class="pre">DIM1,</span> <span class="pre">DIM_TYPE*</span> <span class="pre">DIM2</span> <span class="pre">)</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">(</span> <span class="pre">DIM_TYPE*</span> <span class="pre">DIM1,</span> <span class="pre">DIM_TYPE*</span> <span class="pre">DIM2,</span> <span class="pre">DATA_TYPE**</span> <span class="pre">ARGOUTVIEW_ARRAY2</span> <span class="pre">)</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">(</span> <span class="pre">DATA_TYPE**</span> <span class="pre">ARGOUTVIEW_FARRAY2,</span> <span class="pre">DIM_TYPE*</span> <span class="pre">DIM1,</span> <span class="pre">DIM_TYPE*</span> <span class="pre">DIM2</span> <span class="pre">)</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">(</span> <span class="pre">DIM_TYPE*</span> <span class="pre">DIM1,</span> <span class="pre">DIM_TYPE*</span> <span class="pre">DIM2,</span> <span class="pre">DATA_TYPE**</span> <span class="pre">ARGOUTVIEW_FARRAY2</span> <span class="pre">)</span></tt></li>
+</ul>
+</blockquote>
+<p>3D:</p>
+<blockquote>
+<ul class="simple">
+<li><tt class="docutils literal"><span class="pre">(</span> <span class="pre">DATA_TYPE**</span> <span class="pre">ARGOUTVIEW_ARRAY3,</span> <span class="pre">DIM_TYPE*</span> <span class="pre">DIM1,</span> <span class="pre">DIM_TYPE*</span> <span class="pre">DIM2,</span> <span class="pre">DIM_TYPE*</span> <span class="pre">DIM3)</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">(</span> <span class="pre">DIM_TYPE*</span> <span class="pre">DIM1,</span> <span class="pre">DIM_TYPE*</span> <span class="pre">DIM2,</span> <span class="pre">DIM_TYPE*</span> <span class="pre">DIM3,</span> <span class="pre">DATA_TYPE**</span> <span class="pre">ARGOUTVIEW_ARRAY3)</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">(</span> <span class="pre">DATA_TYPE**</span> <span class="pre">ARGOUTVIEW_FARRAY3,</span> <span class="pre">DIM_TYPE*</span> <span class="pre">DIM1,</span> <span class="pre">DIM_TYPE*</span> <span class="pre">DIM2,</span> <span class="pre">DIM_TYPE*</span> <span class="pre">DIM3)</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">(</span> <span class="pre">DIM_TYPE*</span> <span class="pre">DIM1,</span> <span class="pre">DIM_TYPE*</span> <span class="pre">DIM2,</span> <span class="pre">DIM_TYPE*</span> <span class="pre">DIM3,</span> <span class="pre">DATA_TYPE**</span> <span class="pre">ARGOUTVIEW_FARRAY3)</span></tt></li>
+</ul>
+</blockquote>
+<p>Note that arrays with hard-coded dimensions are not supported. These
+cannot follow the double pointer signatures of these typemaps.</p>
+</div>
+<div class="section">
+<h2><a class="toc-backref" href="#id8" id="output-arrays" name="output-arrays">Output Arrays</a></h2>
+<p>The <tt class="docutils literal"><span class="pre">numpy.i</span></tt> interface file does not support typemaps for output
+arrays, for several reasons. First, C/C++ return arguments are
+limited to a single value. This prevents obtaining dimension
+information in a general way. Second, arrays with hard-coded lengths
+are not permitted as return arguments. In other words:</p>
+<pre class="literal-block">
+double[3] newVector(double x, double y, double z);
+</pre>
+<p>is not legal C/C++ syntax. Therefore, we cannot provide typemaps of
+the form:</p>
+<pre class="literal-block">
+%typemap(out) (TYPE[ANY]);
+</pre>
+<p>If you run into a situation where a function or method is returning a
+pointer to an array, your best bet is to write your own version of the
+function to be wrapped, either with <tt class="docutils literal"><span class="pre">%extend</span></tt> for the case of class
+methods or <tt class="docutils literal"><span class="pre">%ignore</span></tt> and <tt class="docutils literal"><span class="pre">%rename</span></tt> for the case of functions.</p>
+</div>
+<div class="section">
+<h2><a class="toc-backref" href="#id9" id="other-common-types-bool" name="other-common-types-bool">Other Common Types: bool</a></h2>
+<p>Note that C++ type <tt class="docutils literal"><span class="pre">bool</span></tt> is not supported in the list in the
+<a class="reference" href="#available-typemaps">Available Typemaps</a> section. NumPy bools are a single byte, while
+the C++ <tt class="docutils literal"><span class="pre">bool</span></tt> is four bytes (at least on my system). Therefore:</p>
+<pre class="literal-block">
+%numpy_typemaps(bool, NPY_BOOL, int)
+</pre>
+<p>will result in typemaps that will produce code that reference
+improper data lengths. You can implement the following macro
+expansion:</p>
+<pre class="literal-block">
+%numpy_typemaps(bool, NPY_UINT, int)
+</pre>
+<p>to fix the data length problem, and <a class="reference" href="#input-arrays">Input Arrays</a> will work fine,
+but <a class="reference" href="#in-place-arrays">In-Place Arrays</a> might fail type-checking.</p>
+</div>
+<div class="section">
+<h2><a class="toc-backref" href="#id10" id="other-common-types-complex" name="other-common-types-complex">Other Common Types: complex</a></h2>
+<p>Typemap conversions for complex floating-point types is also not
+supported automatically. This is because <a class="reference" href="http://www.python.org">python</a> and <a class="reference" href="http://numpy.scipy.org">NumPy</a> are
+written in C, which does not have native complex types. Both
+<a class="reference" href="http://www.python.org">python</a> and <a class="reference" href="http://numpy.scipy.org">NumPy</a> implement their own (essentially equivalent)
+<tt class="docutils literal"><span class="pre">struct</span></tt> definitions for complex variables:</p>
+<pre class="literal-block">
+/* Python */
+typedef struct {double real; double imag;} Py_complex;
+
+/* NumPy */
+typedef struct {float real, imag;} npy_cfloat;
+typedef struct {double real, imag;} npy_cdouble;
+</pre>
+<p>We could have implemented:</p>
+<pre class="literal-block">
+%numpy_typemaps(Py_complex , NPY_CDOUBLE, int)
+%numpy_typemaps(npy_cfloat , NPY_CFLOAT , int)
+%numpy_typemaps(npy_cdouble, NPY_CDOUBLE, int)
+</pre>
+<p>which would have provided automatic type conversions for arrays of
+type <tt class="docutils literal"><span class="pre">Py_complex</span></tt>, <tt class="docutils literal"><span class="pre">npy_cfloat</span></tt> and <tt class="docutils literal"><span class="pre">npy_cdouble</span></tt>. However, it
+seemed unlikely that there would be any independent (non-<a class="reference" href="http://www.python.org">python</a>,
+non-<a class="reference" href="http://numpy.scipy.org">NumPy</a>) application code that people would be using <a class="reference" href="http://www.swig.org">SWIG</a> to
+generate a <a class="reference" href="http://www.python.org">python</a> interface to, that also used these definitions
+for complex types. More likely, these application codes will define
+their own complex types, or in the case of C++, use <tt class="docutils literal"><span class="pre">std::complex</span></tt>.
+Assuming these data structures are compatible with <a class="reference" href="http://www.python.org">python</a> and
+<a class="reference" href="http://numpy.scipy.org">NumPy</a> complex types, <tt class="docutils literal"><span class="pre">%numpy_typemap</span></tt> expansions as above (with
+the user's complex type substituted for the first argument) should
+work.</p>
+</div>
+</div>
+<div class="section">
+<h1><a class="toc-backref" href="#id11" id="numpy-array-scalars-and-swig" name="numpy-array-scalars-and-swig">NumPy Array Scalars and SWIG</a></h1>
+<p><a class="reference" href="http://www.swig.org">SWIG</a> has sophisticated type checking for numerical types. For
+example, if your C/C++ routine expects an integer as input, the code
+generated by <a class="reference" href="http://www.swig.org">SWIG</a> will check for both <a class="reference" href="http://www.python.org">python</a> integers and
+<a class="reference" href="http://www.python.org">python</a> long integers, and raise an overflow error if the provided
+<a class="reference" href="http://www.python.org">python</a> integer is too big to cast down to a C integer. With the
+introduction of <a class="reference" href="http://numpy.scipy.org">NumPy</a> scalar arrays into your <a class="reference" href="http://www.python.org">python</a> code, you
+might conceivably extract an integer from a <a class="reference" href="http://numpy.scipy.org">NumPy</a> array and attempt
+to pass this to a <a class="reference" href="http://www.swig.org">SWIG</a>-wrapped C/C++ function that expects an
+<tt class="docutils literal"><span class="pre">int</span></tt>, but the <a class="reference" href="http://www.swig.org">SWIG</a> type checking will not recognize the <a class="reference" href="http://numpy.scipy.org">NumPy</a>
+array scalar as an integer. (Often, this does in fact work -- it
+depends on whether <a class="reference" href="http://numpy.scipy.org">NumPy</a> recognizes the integer type you are using
+as inheriting from the <a class="reference" href="http://www.python.org">python</a> integer type on the platform you are
+using. Sometimes, this means that code that works on a 32-bit machine
+will fail on a 64-bit machine.)</p>
+<p>If you get a <a class="reference" href="http://www.python.org">python</a> error that looks like the following:</p>
+<pre class="literal-block">
+TypeError: in method 'MyClass_MyMethod', argument 2 of type 'int'
+</pre>
+<p>and the argument you are passing is an integer extracted from a
+<a class="reference" href="http://numpy.scipy.org">NumPy</a> array, then you have stumbled upon this problem. The
+solution is to modify the <a class="reference" href="http://www.swig.org">SWIG</a> type conversion system to accept
+<a class="reference" href="http://numpy.scipy.org">Numpy</a> array scalars in addition to the standard integer types.
+Fortunately, this capabilitiy has been provided for you. Simply copy
+the file:</p>
+<pre class="literal-block">
+pyfragments.swg
+</pre>
+<p>to the working build directory for you project, and this problem will
+be fixed. It is suggested that you do this anyway, as it only
+increases the capabilities of your <a class="reference" href="http://www.python.org">python</a> interface.</p>
+<div class="section">
+<h2><a class="toc-backref" href="#id12" id="why-is-there-a-second-file" name="why-is-there-a-second-file">Why is There a Second File?</a></h2>
+<p>The <a class="reference" href="http://www.swig.org">SWIG</a> type checking and conversion system is a complicated
+combination of C macros, <a class="reference" href="http://www.swig.org">SWIG</a> macros, <a class="reference" href="http://www.swig.org">SWIG</a> typemaps and <a class="reference" href="http://www.swig.org">SWIG</a>
+fragments. Fragments are a way to conditionally insert code into your
+wrapper file if it is needed, and not insert it if not needed. If
+multiple typemaps require the same fragment, the fragment only gets
+inserted into your wrapper code once.</p>
+<p>There is a fragment for converting a <a class="reference" href="http://www.python.org">python</a> integer to a C
+<tt class="docutils literal"><span class="pre">long</span></tt>. There is a different fragment that converts a <a class="reference" href="http://www.python.org">python</a>
+integer to a C <tt class="docutils literal"><span class="pre">int</span></tt>, that calls the rountine defined in the
+<tt class="docutils literal"><span class="pre">long</span></tt> fragment. We can make the changes we want here by changing
+the definition for the <tt class="docutils literal"><span class="pre">long</span></tt> fragment. <a class="reference" href="http://www.swig.org">SWIG</a> determines the
+active definition for a fragment using a &quot;first come, first served&quot;
+system. That is, we need to define the fragment for <tt class="docutils literal"><span class="pre">long</span></tt>
+conversions prior to <a class="reference" href="http://www.swig.org">SWIG</a> doing it internally. <a class="reference" href="http://www.swig.org">SWIG</a> allows us
+to do this by putting our fragment definitions in the file
+<tt class="docutils literal"><span class="pre">pyfragments.swg</span></tt>. If we were to put the new fragment definitions
+in <tt class="docutils literal"><span class="pre">numpy.i</span></tt>, they would be ignored.</p>
+</div>
+</div>
+<div class="section">
+<h1><a class="toc-backref" href="#id13" id="helper-functions" name="helper-functions">Helper Functions</a></h1>
+<p>The <tt class="docutils literal"><span class="pre">numpy.i</span></tt> file containes several macros and routines that it
+uses internally to build its typemaps. However, these functions may
+be useful elsewhere in your interface file. These macros and routines
+are implemented as fragments, which are described briefly in the
+previous section. If you try to use one or more of the following
+macros or functions, but your compiler complains that it does not
+recognize the symbol, then you need to force these fragments to appear
+in your code using:</p>
+<pre class="literal-block">
+%fragment(&quot;NumPy_Fragments&quot;);
+</pre>
+<p>in your <a class="reference" href="http://www.swig.org">SWIG</a> interface file.</p>
+<div class="section">
+<h2><a class="toc-backref" href="#id14" id="macros" name="macros">Macros</a></h2>
+<blockquote>
+<dl class="docutils">
+<dt><strong>is_array(a)</strong></dt>
+<dd>Evaluates as true if <tt class="docutils literal"><span class="pre">a</span></tt> is non-<tt class="docutils literal"><span class="pre">NULL</span></tt> and can be cast to a
+<tt class="docutils literal"><span class="pre">PyArrayObject*</span></tt>.</dd>
+<dt><strong>array_type(a)</strong></dt>
+<dd>Evaluates to the integer data type code of <tt class="docutils literal"><span class="pre">a</span></tt>, assuming <tt class="docutils literal"><span class="pre">a</span></tt> can
+be cast to a <tt class="docutils literal"><span class="pre">PyArrayObject*</span></tt>.</dd>
+<dt><strong>array_numdims(a)</strong></dt>
+<dd>Evaluates to the integer number of dimensions of <tt class="docutils literal"><span class="pre">a</span></tt>, assuming
+<tt class="docutils literal"><span class="pre">a</span></tt> can be cast to a <tt class="docutils literal"><span class="pre">PyArrayObject*</span></tt>.</dd>
+<dt><strong>array_dimensions(a)</strong></dt>
+<dd>Evaluates to an array of type <tt class="docutils literal"><span class="pre">npy_intp</span></tt> and length
+<tt class="docutils literal"><span class="pre">array_numdims(a)</span></tt>, giving the lengths of all of the dimensions
+of <tt class="docutils literal"><span class="pre">a</span></tt>, assuming <tt class="docutils literal"><span class="pre">a</span></tt> can be cast to a <tt class="docutils literal"><span class="pre">PyArrayObject*</span></tt>.</dd>
+<dt><strong>array_size(a,i)</strong></dt>
+<dd>Evaluates to the <tt class="docutils literal"><span class="pre">i</span></tt>-th dimension size of <tt class="docutils literal"><span class="pre">a</span></tt>, assuming <tt class="docutils literal"><span class="pre">a</span></tt>
+can be cast to a <tt class="docutils literal"><span class="pre">PyArrayObject*</span></tt>.</dd>
+<dt><strong>array_data(a)</strong></dt>
+<dd>Evaluates to a pointer of type <tt class="docutils literal"><span class="pre">void*</span></tt> that points to the data
+buffer of <tt class="docutils literal"><span class="pre">a</span></tt>, assuming <tt class="docutils literal"><span class="pre">a</span></tt> can be cast to a <tt class="docutils literal"><span class="pre">PyArrayObject*</span></tt>.</dd>
+<dt><strong>array_is_contiguous(a)</strong></dt>
+<dd>Evaluates as true if <tt class="docutils literal"><span class="pre">a</span></tt> is a contiguous array. Equivalent to
+<tt class="docutils literal"><span class="pre">(PyArray_ISCONTIGUOUS(a))</span></tt>.</dd>
+<dt><strong>array_is_native(a)</strong></dt>
+<dd>Evaluates as true if the data buffer of <tt class="docutils literal"><span class="pre">a</span></tt> uses native byte
+order. Equivalent to <tt class="docutils literal"><span class="pre">(PyArray_ISNOTSWAPPED(a))</span></tt>.</dd>
+<dt><strong>array_is_fortran(a)</strong></dt>
+<dd>Evaluates as true if <tt class="docutils literal"><span class="pre">a</span></tt> is FORTRAN ordered.</dd>
+</dl>
+</blockquote>
+</div>
+<div class="section">
+<h2><a class="toc-backref" href="#id15" id="routines" name="routines">Routines</a></h2>
+<blockquote>
+<p><strong>pytype_string()</strong></p>
+<blockquote>
+<p>Return type: <tt class="docutils literal"><span class="pre">char*</span></tt></p>
+<p>Arguments:</p>
+<ul class="simple">
+<li><tt class="docutils literal"><span class="pre">PyObject*</span> <span class="pre">py_obj</span></tt>, a general <a class="reference" href="http://www.python.org">python</a> object.</li>
+</ul>
+<p>Return a string describing the type of <tt class="docutils literal"><span class="pre">py_obj</span></tt>.</p>
+</blockquote>
+<p><strong>typecode_string()</strong></p>
+<blockquote>
+<p>Return type: <tt class="docutils literal"><span class="pre">char*</span></tt></p>
+<p>Arguments:</p>
+<ul class="simple">
+<li><tt class="docutils literal"><span class="pre">int</span> <span class="pre">typecode</span></tt>, a <a class="reference" href="http://numpy.scipy.org">NumPy</a> integer typecode.</li>
+</ul>
+<p>Return a string describing the type corresponding to the <a class="reference" href="http://numpy.scipy.org">NumPy</a>
+<tt class="docutils literal"><span class="pre">typecode</span></tt>.</p>
+</blockquote>
+<p><strong>type_match()</strong></p>
+<blockquote>
+<p>Return type: <tt class="docutils literal"><span class="pre">int</span></tt></p>
+<p>Arguments:</p>
+<ul class="simple">
+<li><tt class="docutils literal"><span class="pre">int</span> <span class="pre">actual_type</span></tt>, the <a class="reference" href="http://numpy.scipy.org">NumPy</a> typecode of a <a class="reference" href="http://numpy.scipy.org">NumPy</a> array.</li>
+<li><tt class="docutils literal"><span class="pre">int</span> <span class="pre">desired_type</span></tt>, the desired <a class="reference" href="http://numpy.scipy.org">NumPy</a> typecode.</li>
+</ul>
+<p>Make sure that <tt class="docutils literal"><span class="pre">actual_type</span></tt> is compatible with
+<tt class="docutils literal"><span class="pre">desired_type</span></tt>. For example, this allows character and
+byte types, or int and long types, to match. This is now
+equivalent to <tt class="docutils literal"><span class="pre">PyArray_EquivTypenums()</span></tt>.</p>
+</blockquote>
+<p><strong>obj_to_array_no_conversion()</strong></p>
+<blockquote>
+<p>Return type: <tt class="docutils literal"><span class="pre">PyArrayObject*</span></tt></p>
+<p>Arguments:</p>
+<ul class="simple">
+<li><tt class="docutils literal"><span class="pre">PyObject*</span> <span class="pre">input</span></tt>, a general <a class="reference" href="http://www.python.org">python</a> object.</li>
+<li><tt class="docutils literal"><span class="pre">int</span> <span class="pre">typecode</span></tt>, the desired <a class="reference" href="http://numpy.scipy.org">NumPy</a> typecode.</li>
+</ul>
+<p>Cast <tt class="docutils literal"><span class="pre">input</span></tt> to a <tt class="docutils literal"><span class="pre">PyArrayObject*</span></tt> if legal, and ensure that
+it is of type <tt class="docutils literal"><span class="pre">typecode</span></tt>. If <tt class="docutils literal"><span class="pre">input</span></tt> cannot be cast, or the
+<tt class="docutils literal"><span class="pre">typecode</span></tt> is wrong, set a <a class="reference" href="http://www.python.org">python</a> error and return <tt class="docutils literal"><span class="pre">NULL</span></tt>.</p>
+</blockquote>
+<p><strong>obj_to_array_allow_conversion()</strong></p>
+<blockquote>
+<p>Return type: <tt class="docutils literal"><span class="pre">PyArrayObject*</span></tt></p>
+<p>Arguments:</p>
+<ul class="simple">
+<li><tt class="docutils literal"><span class="pre">PyObject*</span> <span class="pre">input</span></tt>, a general <a class="reference" href="http://www.python.org">python</a> object.</li>
+<li><tt class="docutils literal"><span class="pre">int</span> <span class="pre">typecode</span></tt>, the desired <a class="reference" href="http://numpy.scipy.org">NumPy</a> typecode of the resulting
+array.</li>
+<li><tt class="docutils literal"><span class="pre">int*</span> <span class="pre">is_new_object</span></tt>, returns a value of 0 if no conversion
+performed, else 1.</li>
+</ul>
+<p>Convert <tt class="docutils literal"><span class="pre">input</span></tt> to a <a class="reference" href="http://numpy.scipy.org">NumPy</a> array with the given <tt class="docutils literal"><span class="pre">typecode</span></tt>.
+On success, return a valid <tt class="docutils literal"><span class="pre">PyArrayObject*</span></tt> with the correct
+type. On failure, the <a class="reference" href="http://www.python.org">python</a> error string will be set and the
+routine returns <tt class="docutils literal"><span class="pre">NULL</span></tt>.</p>
+</blockquote>
+<p><strong>make_contiguous()</strong></p>
+<blockquote>
+<p>Return type: <tt class="docutils literal"><span class="pre">PyArrayObject*</span></tt></p>
+<p>Arguments:</p>
+<ul class="simple">
+<li><tt class="docutils literal"><span class="pre">PyArrayObject*</span> <span class="pre">ary</span></tt>, a <a class="reference" href="http://numpy.scipy.org">NumPy</a> array.</li>
+<li><tt class="docutils literal"><span class="pre">int*</span> <span class="pre">is_new_object</span></tt>, returns a value of 0 if no conversion
+performed, else 1.</li>
+<li><tt class="docutils literal"><span class="pre">int</span> <span class="pre">min_dims</span></tt>, minimum allowable dimensions.</li>
+<li><tt class="docutils literal"><span class="pre">int</span> <span class="pre">max_dims</span></tt>, maximum allowable dimensions.</li>
+</ul>
+<p>Check to see if <tt class="docutils literal"><span class="pre">ary</span></tt> is contiguous. If so, return the input
+pointer and flag it as not a new object. If it is not contiguous,
+create a new <tt class="docutils literal"><span class="pre">PyArrayObject*</span></tt> using the original data, flag it
+as a new object and return the pointer.</p>
+</blockquote>
+<p><strong>obj_to_array_contiguous_allow_conversion()</strong></p>
+<blockquote>
+<p>Return type: <tt class="docutils literal"><span class="pre">PyArrayObject*</span></tt></p>
+<p>Arguments:</p>
+<ul class="simple">
+<li><tt class="docutils literal"><span class="pre">PyObject*</span> <span class="pre">input</span></tt>, a general <a class="reference" href="http://www.python.org">python</a> object.</li>
+<li><tt class="docutils literal"><span class="pre">int</span> <span class="pre">typecode</span></tt>, the desired <a class="reference" href="http://numpy.scipy.org">NumPy</a> typecode of the resulting
+array.</li>
+<li><tt class="docutils literal"><span class="pre">int*</span> <span class="pre">is_new_object</span></tt>, returns a value of 0 if no conversion
+performed, else 1.</li>
+</ul>
+<p>Convert <tt class="docutils literal"><span class="pre">input</span></tt> to a contiguous <tt class="docutils literal"><span class="pre">PyArrayObject*</span></tt> of the
+specified type. If the input object is not a contiguous
+<tt class="docutils literal"><span class="pre">PyArrayObject*</span></tt>, a new one will be created and the new object
+flag will be set.</p>
+</blockquote>
+<p><strong>require_contiguous()</strong></p>
+<blockquote>
+<p>Return type: <tt class="docutils literal"><span class="pre">int</span></tt></p>
+<p>Arguments:</p>
+<ul class="simple">
+<li><tt class="docutils literal"><span class="pre">PyArrayObject*</span> <span class="pre">ary</span></tt>, a <a class="reference" href="http://numpy.scipy.org">NumPy</a> array.</li>
+</ul>
+<p>Test whether <tt class="docutils literal"><span class="pre">ary</span></tt> is contiguous. If so, return 1. Otherwise,
+set a <a class="reference" href="http://www.python.org">python</a> error and return 0.</p>
+</blockquote>
+<p><strong>require_native()</strong></p>
+<blockquote>
+<p>Return type: <tt class="docutils literal"><span class="pre">int</span></tt></p>
+<p>Arguments:</p>
+<ul class="simple">
+<li><tt class="docutils literal"><span class="pre">PyArray_Object*</span> <span class="pre">ary</span></tt>, a <a class="reference" href="http://numpy.scipy.org">NumPy</a> array.</li>
+</ul>
+<p>Require that <tt class="docutils literal"><span class="pre">ary</span></tt> is not byte-swapped. If the array is not
+byte-swapped, return 1. Otherwise, set a <a class="reference" href="http://www.python.org">python</a> error and
+return 0.</p>
+</blockquote>
+<p><strong>require_dimensions()</strong></p>
+<blockquote>
+<p>Return type: <tt class="docutils literal"><span class="pre">int</span></tt></p>
+<p>Arguments:</p>
+<ul class="simple">
+<li><tt class="docutils literal"><span class="pre">PyArrayObject*</span> <span class="pre">ary</span></tt>, a <a class="reference" href="http://numpy.scipy.org">NumPy</a> array.</li>
+<li><tt class="docutils literal"><span class="pre">int</span> <span class="pre">exact_dimensions</span></tt>, the desired number of dimensions.</li>
+</ul>
+<p>Require <tt class="docutils literal"><span class="pre">ary</span></tt> to have a specified number of dimensions. If the
+array has the specified number of dimensions, return 1.
+Otherwise, set a <a class="reference" href="http://www.python.org">python</a> error and return 0.</p>
+</blockquote>
+<p><strong>require_dimensions_n()</strong></p>
+<blockquote>
+<p>Return type: <tt class="docutils literal"><span class="pre">int</span></tt></p>
+<p>Arguments:</p>
+<ul class="simple">
+<li><tt class="docutils literal"><span class="pre">PyArrayObject*</span> <span class="pre">ary</span></tt>, a <a class="reference" href="http://numpy.scipy.org">NumPy</a> array.</li>
+<li><tt class="docutils literal"><span class="pre">int*</span> <span class="pre">exact_dimensions</span></tt>, an array of integers representing
+acceptable numbers of dimensions.</li>
+<li><tt class="docutils literal"><span class="pre">int</span> <span class="pre">n</span></tt>, the length of <tt class="docutils literal"><span class="pre">exact_dimensions</span></tt>.</li>
+</ul>
+<p>Require <tt class="docutils literal"><span class="pre">ary</span></tt> to have one of a list of specified number of
+dimensions. If the array has one of the specified number of
+dimensions, return 1. Otherwise, set the <a class="reference" href="http://www.python.org">python</a> error string
+and return 0.</p>
+</blockquote>
+<p><strong>require_size()</strong></p>
+<blockquote>
+<p>Return type: <tt class="docutils literal"><span class="pre">int</span></tt></p>
+<p>Arguments:</p>
+<ul class="simple">
+<li><tt class="docutils literal"><span class="pre">PyArrayObject*</span> <span class="pre">ary</span></tt>, a <a class="reference" href="http://numpy.scipy.org">NumPy</a> array.</li>
+<li><tt class="docutils literal"><span class="pre">npy_int*</span> <span class="pre">size</span></tt>, an array representing the desired lengths of
+each dimension.</li>
+<li><tt class="docutils literal"><span class="pre">int</span> <span class="pre">n</span></tt>, the length of <tt class="docutils literal"><span class="pre">size</span></tt>.</li>
+</ul>
+<p>Require <tt class="docutils literal"><span class="pre">ary</span></tt> to have a specified shape. If the array has the
+specified shape, return 1. Otherwise, set the <a class="reference" href="http://www.python.org">python</a> error
+string and return 0.</p>
+</blockquote>
+<p><strong>require_fortran()</strong></p>
+<blockquote>
+<p>Return type: <tt class="docutils literal"><span class="pre">int</span></tt></p>
+<p>Arguments:</p>
+<ul class="simple">
+<li><tt class="docutils literal"><span class="pre">PyArrayObject*</span> <span class="pre">ary</span></tt>, a <a class="reference" href="http://numpy.scipy.org">NumPy</a> array.</li>
+</ul>
+<p>Require the given <tt class="docutils literal"><span class="pre">PyArrayObject</span></tt> to to be FORTRAN ordered. If
+the the <tt class="docutils literal"><span class="pre">PyArrayObject</span></tt> is already FORTRAN ordered, do nothing.
+Else, set the FORTRAN ordering flag and recompute the strides.</p>
+</blockquote>
+</blockquote>
+</div>
+</div>
+<div class="section">
+<h1><a class="toc-backref" href="#id16" id="beyond-the-provided-typemaps" name="beyond-the-provided-typemaps">Beyond the Provided Typemaps</a></h1>
+<p>There are many C or C++ array/<a class="reference" href="http://numpy.scipy.org">NumPy</a> array situations not covered by
+a simple <tt class="docutils literal"><span class="pre">%include</span> <span class="pre">&quot;numpy.i&quot;</span></tt> and subsequent <tt class="docutils literal"><span class="pre">%apply</span></tt> directives.</p>
+<div class="section">
+<h2><a class="toc-backref" href="#id17" id="a-common-example" name="a-common-example">A Common Example</a></h2>
+<p>Consider a reasonable prototype for a dot product function:</p>
+<pre class="literal-block">
+double dot(int len, double* vec1, double* vec2);
+</pre>
+<p>The <a class="reference" href="http://www.python.org">python</a> interface that we want is:</p>
+<pre class="literal-block">
+def dot(vec1, vec2):
+ &quot;&quot;&quot;
+ dot(PyObject,PyObject) -&gt; double
+ &quot;&quot;&quot;
+</pre>
+<p>The problem here is that there is one dimension argument and two array
+arguments, and our typemaps are set up for dimensions that apply to a
+single array (in fact, <a class="reference" href="http://www.swig.org">SWIG</a> does not provide a mechanism for
+associating <tt class="docutils literal"><span class="pre">len</span></tt> with <tt class="docutils literal"><span class="pre">vec2</span></tt> that takes two <a class="reference" href="http://www.python.org">python</a> input
+arguments). The recommended solution is the following:</p>
+<pre class="literal-block">
+%apply (int DIM1, double* IN_ARRAY1) {(int len1, double* vec1),
+ (int len2, double* vec2)}
+%rename (dot) my_dot;
+%exception my_dot {
+ $action
+ if (PyErr_Occurred()) SWIG_fail;
+}
+%inline %{
+double my_dot(int len1, double* vec1, int len2, double* vec2) {
+ if (len1 != len2) {
+ PyErr_Format(PyExc_ValueError,
+ &quot;Arrays of lengths (%d,%d) given&quot;,
+ len1, len2);
+ return 0.0;
+ }
+ return dot(len1, vec1, vec2);
+}
+%}
+</pre>
+<p>If the header file that contains the prototype for <tt class="docutils literal"><span class="pre">double</span> <span class="pre">dot()</span></tt>
+also contains other prototypes that you want to wrap, so that you need
+to <tt class="docutils literal"><span class="pre">%include</span></tt> this header file, then you will also need a <tt class="docutils literal"><span class="pre">%ignore</span>
+<span class="pre">dot;</span></tt> directive, placed after the <tt class="docutils literal"><span class="pre">%rename</span></tt> and before the
+<tt class="docutils literal"><span class="pre">%include</span></tt> directives. Or, if the function in question is a class
+method, you will want to use <tt class="docutils literal"><span class="pre">%extend</span></tt> rather than <tt class="docutils literal"><span class="pre">%inline</span></tt> in
+addition to <tt class="docutils literal"><span class="pre">%ignore</span></tt>.</p>
+<p><strong>A note on error handling:</strong> Note that <tt class="docutils literal"><span class="pre">my_dot</span></tt> returns a
+<tt class="docutils literal"><span class="pre">double</span></tt> but that it can also raise a <a class="reference" href="http://www.python.org">python</a> error. The
+resulting wrapper function will return a <a class="reference" href="http://www.python.org">python</a> float
+representation of 0.0 when the vector lengths do not match. Since
+this is not <tt class="docutils literal"><span class="pre">NULL</span></tt>, the <a class="reference" href="http://www.python.org">python</a> interpreter will not know to check
+for an error. For this reason, we add the <tt class="docutils literal"><span class="pre">%exception</span></tt> directive
+above for <tt class="docutils literal"><span class="pre">my_dot</span></tt> to get the behavior we want (note that
+<tt class="docutils literal"><span class="pre">$action</span></tt> is a macro that gets expanded to a valid call to
+<tt class="docutils literal"><span class="pre">my_dot</span></tt>). In general, you will probably want to write a <a class="reference" href="http://www.swig.org">SWIG</a>
+macro to perform this task.</p>
+</div>
+<div class="section">
+<h2><a class="toc-backref" href="#id18" id="other-situations" name="other-situations">Other Situations</a></h2>
+<p>There are other wrapping situations in which <tt class="docutils literal"><span class="pre">numpy.i</span></tt> may be
+helpful when you encounter them.</p>
+<blockquote>
+<ul>
+<li><p class="first">In some situations, it is possible that you could use the
+<tt class="docutils literal"><span class="pre">%numpy_templates</span></tt> macro to implement typemaps for your own
+types. See the <a class="reference" href="#other-common-types-bool">Other Common Types: bool</a> or <a class="reference" href="#other-common-types-complex">Other Common
+Types: complex</a> sections for examples. Another situation is if
+your dimensions are of a type other than <tt class="docutils literal"><span class="pre">int</span></tt> (say <tt class="docutils literal"><span class="pre">long</span></tt> for
+example):</p>
+<pre class="literal-block">
+%numpy_typemaps(double, NPY_DOUBLE, long)
+</pre>
+</li>
+<li><p class="first">You can use the code in <tt class="docutils literal"><span class="pre">numpy.i</span></tt> to write your own typemaps.
+For example, if you had a four-dimensional array as a function
+argument, you could cut-and-paste the appropriate
+three-dimensional typemaps into your interface file. The
+modifications for the fourth dimension would be trivial.</p>
+</li>
+<li><p class="first">Sometimes, the best approach is to use the <tt class="docutils literal"><span class="pre">%extend</span></tt> directive
+to define new methods for your classes (or overload existing ones)
+that take a <tt class="docutils literal"><span class="pre">PyObject*</span></tt> (that either is or can be converted to a
+<tt class="docutils literal"><span class="pre">PyArrayObject*</span></tt>) instead of a pointer to a buffer. In this
+case, the helper routines in <tt class="docutils literal"><span class="pre">numpy.i</span></tt> can be very useful.</p>
+</li>
+<li><p class="first">Writing typemaps can be a bit nonintuitive. If you have specific
+questions about writing <a class="reference" href="http://www.swig.org">SWIG</a> typemaps for <a class="reference" href="http://numpy.scipy.org">NumPy</a>, the
+developers of <tt class="docutils literal"><span class="pre">numpy.i</span></tt> do monitor the
+<a class="reference" href="mailto:Numpy-discussion&#64;scipy.org">Numpy-discussion</a> and
+<a class="reference" href="mailto:Swig-user&#64;lists.sourceforge.net">Swig-user</a> mail lists.</p>
+</li>
+</ul>
+</blockquote>
+</div>
+<div class="section">
+<h2><a class="toc-backref" href="#id19" id="a-final-note" name="a-final-note">A Final Note</a></h2>
+<p>When you use the <tt class="docutils literal"><span class="pre">%apply</span></tt> directive, as is usually necessary to use
+<tt class="docutils literal"><span class="pre">numpy.i</span></tt>, it will remain in effect until you tell <a class="reference" href="http://www.swig.org">SWIG</a> that it
+shouldn't be. If the arguments to the functions or methods that you
+are wrapping have common names, such as <tt class="docutils literal"><span class="pre">length</span></tt> or <tt class="docutils literal"><span class="pre">vector</span></tt>,
+these typemaps may get applied in situations you do not expect or
+want. Therefore, it is always a good idea to add a <tt class="docutils literal"><span class="pre">%clear</span></tt>
+directive after you are done with a specific typemap:</p>
+<pre class="literal-block">
+%apply (double* IN_ARRAY1, int DIM1) {(double* vector, int length)}
+%include &quot;my_header.h&quot;
+%clear (double* vector, int length);
+</pre>
+<p>In general, you should target these typemap signatures specifically
+where you want them, and then clear them after you are done.</p>
+</div>
+</div>
+<div class="section">
+<h1><a class="toc-backref" href="#id20" id="summary" name="summary">Summary</a></h1>
+<p>Out of the box, <tt class="docutils literal"><span class="pre">numpy.i</span></tt> provides typemaps that support conversion
+between <a class="reference" href="http://numpy.scipy.org">NumPy</a> arrays and C arrays:</p>
+<blockquote>
+<ul class="simple">
+<li>That can be one of 12 different scalar types: <tt class="docutils literal"><span class="pre">signed</span> <span class="pre">char</span></tt>,
+<tt class="docutils literal"><span class="pre">unsigned</span> <span class="pre">char</span></tt>, <tt class="docutils literal"><span class="pre">short</span></tt>, <tt class="docutils literal"><span class="pre">unsigned</span> <span class="pre">short</span></tt>, <tt class="docutils literal"><span class="pre">int</span></tt>,
+<tt class="docutils literal"><span class="pre">unsigned</span> <span class="pre">int</span></tt>, <tt class="docutils literal"><span class="pre">long</span></tt>, <tt class="docutils literal"><span class="pre">unsigned</span> <span class="pre">long</span></tt>, <tt class="docutils literal"><span class="pre">long</span> <span class="pre">long</span></tt>,
+<tt class="docutils literal"><span class="pre">unsigned</span> <span class="pre">long</span> <span class="pre">long</span></tt>, <tt class="docutils literal"><span class="pre">float</span></tt> and <tt class="docutils literal"><span class="pre">double</span></tt>.</li>
+<li>That support 41 different argument signatures for each data type,
+including:<ul>
+<li>One-dimensional, two-dimensional and three-dimensional arrays.</li>
+<li>Input-only, in-place, argout and argoutview behavior.</li>
+<li>Hard-coded dimensions, data-buffer-then-dimensions
+specification, and dimensions-then-data-buffer specification.</li>
+<li>Both C-ordering (&quot;last dimension fastest&quot;) or FORTRAN-ordering
+(&quot;first dimension fastest&quot;) support for 2D and 3D arrays.</li>
+</ul>
+</li>
+</ul>
+</blockquote>
+<p>The <tt class="docutils literal"><span class="pre">numpy.i</span></tt> interface file also provides additional tools for
+wrapper developers, including:</p>
+<blockquote>
+<ul class="simple">
+<li>A <a class="reference" href="http://www.swig.org">SWIG</a> macro (<tt class="docutils literal"><span class="pre">%numpy_typemaps</span></tt>) with three arguments for
+implementing the 41 argument signatures for the user's choice of
+(1) C data type, (2) <a class="reference" href="http://numpy.scipy.org">NumPy</a> data type (assuming they match), and
+(3) dimension type.</li>
+<li>Nine C macros and 13 C functions that can be used to write
+specialized typemaps, extensions, or inlined functions that handle
+cases not covered by the provided typemaps.</li>
+</ul>
+</blockquote>
+</div>
+<div class="section">
+<h1><a class="toc-backref" href="#id21" id="acknowledgements" name="acknowledgements">Acknowledgements</a></h1>
+<p>Many people have worked to glue <a class="reference" href="http://www.swig.org">SWIG</a> and <a class="reference" href="http://numpy.scipy.org">NumPy</a> together (as well
+as <a class="reference" href="http://www.swig.org">SWIG</a> and the predecessors of <a class="reference" href="http://numpy.scipy.org">NumPy</a>, Numeric and numarray).
+The effort to standardize this work into <tt class="docutils literal"><span class="pre">numpy.i</span></tt> began at the 2005
+<a class="reference" href="http://scipy.org">SciPy</a> Conference with a conversation between
+Fernando Perez and myself. Fernando collected helper functions and
+typemaps from Eric Jones, Michael Hunter, Anna Omelchenko and Michael
+Sanner. Sebastian Hasse and Georg Holzmann have also provided
+additional error checking and use cases. The work of these
+contributors has made this end result possible.</p>
+</div>
+</div>
+<div class="footer">
+<hr class="footer" />
+Generated on: 2007-12-01 18:17 UTC.
+Generated by <a class="reference" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source.
+
+</div>
+</body>
+</html>
diff --git a/doc/swig/doc/numpy_swig.pdf b/doc/swig/doc/numpy_swig.pdf
new file mode 100644
index 000000000..1d4642cf7
--- /dev/null
+++ b/doc/swig/doc/numpy_swig.pdf
Binary files differ
diff --git a/doc/swig/doc/numpy_swig.txt b/doc/swig/doc/numpy_swig.txt
new file mode 100644
index 000000000..bfde018bf
--- /dev/null
+++ b/doc/swig/doc/numpy_swig.txt
@@ -0,0 +1,950 @@
+==========================================
+ numpy.i: a SWIG Interface File for NumPy
+==========================================
+
+:Author: Bill Spotz
+:Institution: Sandia National Laboratories
+:Date: 1 December, 2007
+
+.. contents::
+
+Introduction
+============
+
+The Simple Wrapper and Interface Generator (or `SWIG
+<http://www.swig.org>`_) is a powerful tool for generating wrapper
+code for interfacing to a wide variety of scripting languages.
+`SWIG`_ can parse header files, and using only the code prototypes,
+create an interface to the target language. But `SWIG`_ is not
+omnipotent. For example, it cannot know from the prototype::
+
+ double rms(double* seq, int n);
+
+what exactly ``seq`` is. Is it a single value to be altered in-place?
+Is it an array, and if so what is its length? Is it input-only?
+Output-only? Input-output? `SWIG`_ cannot determine these details,
+and does not attempt to do so.
+
+If we designed ``rms``, we probably made it a routine that takes an
+input-only array of length ``n`` of ``double`` values called ``seq``
+and returns the root mean square. The default behavior of `SWIG`_,
+however, will be to create a wrapper function that compiles, but is
+nearly impossible to use from the scripting language in the way the C
+routine was intended.
+
+For `python <http://www.python.org>`_, the preferred way of handling
+contiguous (or technically, *strided*) blocks of homogeneous data is
+with the module `NumPy <http://numpy.scipy.org>`_, which provides full
+object-oriented access to multidimensial arrays of data. Therefore,
+the most logical `python`_ interface for the ``rms`` function would be
+(including doc string)::
+
+ def rms(seq):
+ """
+ rms: return the root mean square of a sequence
+ rms(numpy.ndarray) -> double
+ rms(list) -> double
+ rms(tuple) -> double
+ """
+
+where ``seq`` would be a `NumPy`_ array of ``double`` values, and its
+length ``n`` would be extracted from ``seq`` internally before being
+passed to the C routine. Even better, since `NumPy`_ supports
+construction of arrays from arbitrary `python`_ sequences, ``seq``
+itself could be a nearly arbitrary sequence (so long as each element
+can be converted to a ``double``) and the wrapper code would
+internally convert it to a `NumPy`_ array before extracting its data
+and length.
+
+`SWIG`_ allows these types of conversions to be defined via a
+mechanism called typemaps. This document provides information on how
+to use ``numpy.i``, a `SWIG`_ interface file that defines a series of
+typemaps intended to make the type of array-related conversions
+described above relatively simple to implement. For example, suppose
+that the ``rms`` function prototype defined above was in a header file
+named ``rms.h``. To obtain the `python`_ interface discussed above,
+your `SWIG`_ interface file would need the following::
+
+ %{
+ #define SWIG_FILE_WITH_INIT
+ #include "rms.h"
+ %}
+
+ %include "numpy.i"
+
+ %init %{
+ import_array();
+ %}
+
+ %apply (double* IN_ARRAY1, int DIM1) {(double* seq, int n)};
+ %include "rms.h"
+
+Typemaps are keyed off a list of one or more function arguments,
+either by type or by type and name. We will refer to such lists as
+*signatures*. One of the many typemaps defined by ``numpy.i`` is used
+above and has the signature ``(double* IN_ARRAY1, int DIM1)``. The
+argument names are intended to suggest that the ``double*`` argument
+is an input array of one dimension and that the ``int`` represents
+that dimension. This is precisely the pattern in the ``rms``
+prototype.
+
+Most likely, no actual prototypes to be wrapped will have the argument
+names ``IN_ARRAY1`` and ``DIM1``. We use the ``%apply`` directive to
+apply the typemap for one-dimensional input arrays of type ``double``
+to the actual prototype used by ``rms``. Using ``numpy.i``
+effectively, therefore, requires knowing what typemaps are available
+and what they do.
+
+A `SWIG`_ interface file that includes the `SWIG`_ directives given
+above will produce wrapper code that looks something like::
+
+ 1 PyObject *_wrap_rms(PyObject *args) {
+ 2 PyObject *resultobj = 0;
+ 3 double *arg1 = (double *) 0 ;
+ 4 int arg2 ;
+ 5 double result;
+ 6 PyArrayObject *array1 = NULL ;
+ 7 int is_new_object1 = 0 ;
+ 8 PyObject * obj0 = 0 ;
+ 9
+ 10 if (!PyArg_ParseTuple(args,(char *)"O:rms",&obj0)) SWIG_fail;
+ 11 {
+ 12 array1 = obj_to_array_contiguous_allow_conversion(
+ 13 obj0, NPY_DOUBLE, &is_new_object1);
+ 14 npy_intp size[1] = {
+ 15 -1
+ 16 };
+ 17 if (!array1 || !require_dimensions(array1, 1) ||
+ 18 !require_size(array1, size, 1)) SWIG_fail;
+ 19 arg1 = (double*) array1->data;
+ 20 arg2 = (int) array1->dimensions[0];
+ 21 }
+ 22 result = (double)rms(arg1,arg2);
+ 23 resultobj = SWIG_From_double((double)(result));
+ 24 {
+ 25 if (is_new_object1 && array1) Py_DECREF(array1);
+ 26 }
+ 27 return resultobj;
+ 28 fail:
+ 29 {
+ 30 if (is_new_object1 && array1) Py_DECREF(array1);
+ 31 }
+ 32 return NULL;
+ 33 }
+
+The typemaps from ``numpy.i`` are responsible for the following lines
+of code: 12--20, 25 and 30. Line 10 parses the input to the ``rms``
+function. From the format string ``"O:rms"``, we can see that the
+argument list is expected to be a single `python`_ object (specified
+by the ``O`` before the colon) and whose pointer is stored in
+``obj0``. A number of functions, supplied by ``numpy.i``, are called
+to make and check the (possible) conversion from a generic `python`_
+object to a `NumPy`_ array. These functions are explained in the
+section `Helper Functions`_, but hopefully their names are
+self-explanatory. At line 12 we use ``obj0`` to construct a `NumPy`_
+array. At line 17, we check the validity of the result: that it is
+non-null and that it has a single dimension of arbitrary length. Once
+these states are verified, we extract the data buffer and length in
+lines 19 and 20 so that we can call the underlying C function at line
+22. Line 25 performs memory management for the case where we have
+created a new array that is no longer needed.
+
+This code has a significant amount of error handling. Note the
+``SWIG_fail`` is a macro for ``goto fail``, refering to the label at
+line 28. If the user provides the wrong number of arguments, this
+will be caught at line 10. If construction of the `NumPy`_ array
+fails or produces an array with the wrong number of dimensions, these
+errors are caught at line 17. And finally, if an error is detected,
+memory is still managed correctly at line 30.
+
+Note that if the C function signature was in a different order::
+
+ double rms(int n, double* seq);
+
+that `SWIG`_ would not match the typemap signature given above with
+the argument list for ``rms``. Fortunately, ``numpy.i`` has a set of
+typemaps with the data pointer given last::
+
+ %apply (int DIM1, double* IN_ARRAY1) {(int n, double* seq)};
+
+This simply has the effect of switching the definitions of ``arg1``
+and ``arg2`` in lines 3 and 4 of the generated code above, and their
+assignments in lines 19 and 20.
+
+Using numpy.i
+=============
+
+The ``numpy.i`` file is currently located in the ``numpy/docs/swig``
+sub-directory under the ``numpy`` installation directory. Typically,
+you will want to copy it to the directory where you are developing
+your wrappers. If it is ever adopted by `SWIG`_ developers, then it
+will be installed in a standard place where `SWIG`_ can find it.
+
+A simple module that only uses a single `SWIG`_ interface file should
+include the following::
+
+ %{
+ #define SWIG_FILE_WITH_INIT
+ %}
+ %include "numpy.i"
+ %init %{
+ import_array();
+ %}
+
+Within a compiled `python`_ module, ``import_array()`` should only get
+called once. This could be in a C/C++ file that you have written and
+is linked to the module. If this is the case, then none of your
+interface files should ``#define SWIG_FILE_WITH_INIT`` or call
+``import_array()``. Or, this initialization call could be in a
+wrapper file generated by `SWIG`_ from an interface file that has the
+``%init`` block as above. If this is the case, and you have more than
+one `SWIG`_ interface file, then only one interface file should
+``#define SWIG_FILE_WITH_INIT`` and call ``import_array()``.
+
+Available Typemaps
+==================
+
+The typemap directives provided by ``numpy.i`` for arrays of different
+data types, say ``double`` and ``int``, and dimensions of different
+types, say ``int`` or ``long``, are identical to one another except
+for the C and `NumPy`_ type specifications. The typemaps are
+therefore implemented (typically behind the scenes) via a macro::
+
+ %numpy_typemaps(DATA_TYPE, DATA_TYPECODE, DIM_TYPE)
+
+that can be invoked for appropriate ``(DATA_TYPE, DATA_TYPECODE,
+DIM_TYPE)`` triplets. For example::
+
+ %numpy_typemaps(double, NPY_DOUBLE, int)
+ %numpy_typemaps(int, NPY_INT , int)
+
+The ``numpy.i`` interface file uses the ``%numpy_typemaps`` macro to
+implement typemaps for the following C data types and ``int``
+dimension types:
+
+ * ``signed char``
+ * ``unsigned char``
+ * ``short``
+ * ``unsigned short``
+ * ``int``
+ * ``unsigned int``
+ * ``long``
+ * ``unsigned long``
+ * ``long long``
+ * ``unsigned long long``
+ * ``float``
+ * ``double``
+
+In the following descriptions, we reference a generic ``DATA_TYPE``, which
+could be any of the C data types listed above, and ``DIM_TYPE`` which
+should be one of the many types of integers.
+
+The typemap signatures are largely differentiated on the name given to
+the buffer pointer. Names with ``FARRAY`` are for FORTRAN-ordered
+arrays, and names with ``ARRAY`` are for C-ordered (or 1D arrays).
+
+Input Arrays
+------------
+
+Input arrays are defined as arrays of data that are passed into a
+routine but are not altered in-place or returned to the user. The
+`python`_ input array is therefore allowed to be almost any `python`_
+sequence (such as a list) that can be converted to the requested type
+of array. The input array signatures are
+
+1D:
+
+ * ``( DATA_TYPE IN_ARRAY1[ANY] )``
+ * ``( DATA_TYPE* IN_ARRAY1, int DIM1 )``
+ * ``( int DIM1, DATA_TYPE* IN_ARRAY1 )``
+
+2D:
+
+ * ``( DATA_TYPE IN_ARRAY2[ANY][ANY] )``
+ * ``( DATA_TYPE* IN_ARRAY2, int DIM1, int DIM2 )``
+ * ``( int DIM1, int DIM2, DATA_TYPE* IN_ARRAY2 )``
+ * ``( DATA_TYPE* IN_FARRAY2, int DIM1, int DIM2 )``
+ * ``( int DIM1, int DIM2, DATA_TYPE* IN_FARRAY2 )``
+
+3D:
+
+ * ``( DATA_TYPE IN_ARRAY3[ANY][ANY][ANY] )``
+ * ``( DATA_TYPE* IN_ARRAY3, int DIM1, int DIM2, int DIM3 )``
+ * ``( int DIM1, int DIM2, int DIM3, DATA_TYPE* IN_ARRAY3 )``
+ * ``( DATA_TYPE* IN_FARRAY3, int DIM1, int DIM2, int DIM3 )``
+ * ``( int DIM1, int DIM2, int DIM3, DATA_TYPE* IN_FARRAY3 )``
+
+The first signature listed, ``( DATA_TYPE IN_ARRAY[ANY] )`` is for
+one-dimensional arrays with hard-coded dimensions. Likewise,
+``( DATA_TYPE IN_ARRAY2[ANY][ANY] )`` is for two-dimensional arrays
+with hard-coded dimensions, and similarly for three-dimensional.
+
+In-Place Arrays
+---------------
+
+In-place arrays are defined as arrays that are modified in-place. The
+input values may or may not be used, but the values at the time the
+function returns are significant. The provided `python`_ argument
+must therefore be a `NumPy`_ array of the required type. The in-place
+signatures are
+
+1D:
+
+ * ``( DATA_TYPE INPLACE_ARRAY1[ANY] )``
+ * ``( DATA_TYPE* INPLACE_ARRAY1, int DIM1 )``
+ * ``( int DIM1, DATA_TYPE* INPLACE_ARRAY1 )``
+
+2D:
+
+ * ``( DATA_TYPE INPLACE_ARRAY2[ANY][ANY] )``
+ * ``( DATA_TYPE* INPLACE_ARRAY2, int DIM1, int DIM2 )``
+ * ``( int DIM1, int DIM2, DATA_TYPE* INPLACE_ARRAY2 )``
+ * ``( DATA_TYPE* INPLACE_FARRAY2, int DIM1, int DIM2 )``
+ * ``( int DIM1, int DIM2, DATA_TYPE* INPLACE_FARRAY2 )``
+
+3D:
+
+ * ``( DATA_TYPE INPLACE_ARRAY3[ANY][ANY][ANY] )``
+ * ``( DATA_TYPE* INPLACE_ARRAY3, int DIM1, int DIM2, int DIM3 )``
+ * ``( int DIM1, int DIM2, int DIM3, DATA_TYPE* INPLACE_ARRAY3 )``
+ * ``( DATA_TYPE* INPLACE_FARRAY3, int DIM1, int DIM2, int DIM3 )``
+ * ``( int DIM1, int DIM2, int DIM3, DATA_TYPE* INPLACE_FARRAY3 )``
+
+These typemaps now check to make sure that the ``INPLACE_ARRAY``
+arguments use native byte ordering. If not, an exception is raised.
+
+Argout Arrays
+-------------
+
+Argout arrays are arrays that appear in the input arguments in C, but
+are in fact output arrays. This pattern occurs often when there is
+more than one output variable and the single return argument is
+therefore not sufficient. In `python`_, the convential way to return
+multiple arguments is to pack them into a sequence (tuple, list, etc.)
+and return the sequence. This is what the argout typemaps do. If a
+wrapped function that uses these argout typemaps has more than one
+return argument, they are packed into a tuple or list, depending on
+the version of `python`_. The `python`_ user does not pass these
+arrays in, they simply get returned. For the case where a dimension
+is specified, the python user must provide that dimension as an
+argument. The argout signatures are
+
+1D:
+
+ * ``( DATA_TYPE ARGOUT_ARRAY1[ANY] )``
+ * ``( DATA_TYPE* ARGOUT_ARRAY1, int DIM1 )``
+ * ``( int DIM1, DATA_TYPE* ARGOUT_ARRAY1 )``
+
+2D:
+
+ * ``( DATA_TYPE ARGOUT_ARRAY2[ANY][ANY] )``
+
+3D:
+
+ * ``( DATA_TYPE ARGOUT_ARRAY3[ANY][ANY][ANY] )``
+
+These are typically used in situations where in C/C++, you would
+allocate a(n) array(s) on the heap, and call the function to fill the
+array(s) values. In `python`_, the arrays are allocated for you and
+returned as new array objects.
+
+Note that we support ``DATA_TYPE*`` argout typemaps in 1D, but not 2D
+or 3D. This is because of a quirk with the `SWIG`_ typemap syntax and
+cannot be avoided. Note that for these types of 1D typemaps, the
+`python`_ function will take a single argument representing ``DIM1``.
+
+Argoutview Arrays
+-----------------
+
+Argoutview arrays are for when your C code provides you with a view of
+its internal data and does not require any memory to be allocated by
+the user. This can be dangerous. There is almost no way to guarantee
+that the internal data from the C code will remain in existence for
+the entire lifetime of the `NumPy`_ array that encapsulates it. If
+the user destroys the object that provides the view of the data before
+destroying the `NumPy`_ array, then using that array my result in bad
+memory references or segmentation faults. Nevertheless, there are
+situations, working with large data sets, where you simply have no
+other choice.
+
+The C code to be wrapped for argoutview arrays are characterized by
+pointers: pointers to the dimensions and double pointers to the data,
+so that these values can be passed back to the user. The argoutview
+typemap signatures are therefore
+
+1D:
+
+ * ``( DATA_TYPE** ARGOUTVIEW_ARRAY1, DIM_TYPE* DIM1 )``
+ * ``( DIM_TYPE* DIM1, DATA_TYPE** ARGOUTVIEW_ARRAY1 )``
+
+2D:
+
+ * ``( DATA_TYPE** ARGOUTVIEW_ARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2 )``
+ * ``( DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_ARRAY2 )``
+ * ``( DATA_TYPE** ARGOUTVIEW_FARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2 )``
+ * ``( DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_FARRAY2 )``
+
+3D:
+
+ * ``( DATA_TYPE** ARGOUTVIEW_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3)``
+ * ``( DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_ARRAY3)``
+ * ``( DATA_TYPE** ARGOUTVIEW_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3)``
+ * ``( DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_FARRAY3)``
+
+Note that arrays with hard-coded dimensions are not supported. These
+cannot follow the double pointer signatures of these typemaps.
+
+Output Arrays
+-------------
+
+The ``numpy.i`` interface file does not support typemaps for output
+arrays, for several reasons. First, C/C++ return arguments are
+limited to a single value. This prevents obtaining dimension
+information in a general way. Second, arrays with hard-coded lengths
+are not permitted as return arguments. In other words::
+
+ double[3] newVector(double x, double y, double z);
+
+is not legal C/C++ syntax. Therefore, we cannot provide typemaps of
+the form::
+
+ %typemap(out) (TYPE[ANY]);
+
+If you run into a situation where a function or method is returning a
+pointer to an array, your best bet is to write your own version of the
+function to be wrapped, either with ``%extend`` for the case of class
+methods or ``%ignore`` and ``%rename`` for the case of functions.
+
+Other Common Types: bool
+------------------------
+
+Note that C++ type ``bool`` is not supported in the list in the
+`Available Typemaps`_ section. NumPy bools are a single byte, while
+the C++ ``bool`` is four bytes (at least on my system). Therefore::
+
+ %numpy_typemaps(bool, NPY_BOOL, int)
+
+will result in typemaps that will produce code that reference
+improper data lengths. You can implement the following macro
+expansion::
+
+ %numpy_typemaps(bool, NPY_UINT, int)
+
+to fix the data length problem, and `Input Arrays`_ will work fine,
+but `In-Place Arrays`_ might fail type-checking.
+
+Other Common Types: complex
+---------------------------
+
+Typemap conversions for complex floating-point types is also not
+supported automatically. This is because `python`_ and `NumPy`_ are
+written in C, which does not have native complex types. Both
+`python`_ and `NumPy`_ implement their own (essentially equivalent)
+``struct`` definitions for complex variables::
+
+ /* Python */
+ typedef struct {double real; double imag;} Py_complex;
+
+ /* NumPy */
+ typedef struct {float real, imag;} npy_cfloat;
+ typedef struct {double real, imag;} npy_cdouble;
+
+We could have implemented::
+
+ %numpy_typemaps(Py_complex , NPY_CDOUBLE, int)
+ %numpy_typemaps(npy_cfloat , NPY_CFLOAT , int)
+ %numpy_typemaps(npy_cdouble, NPY_CDOUBLE, int)
+
+which would have provided automatic type conversions for arrays of
+type ``Py_complex``, ``npy_cfloat`` and ``npy_cdouble``. However, it
+seemed unlikely that there would be any independent (non-`python`_,
+non-`NumPy`_) application code that people would be using `SWIG`_ to
+generate a `python`_ interface to, that also used these definitions
+for complex types. More likely, these application codes will define
+their own complex types, or in the case of C++, use ``std::complex``.
+Assuming these data structures are compatible with `python`_ and
+`NumPy`_ complex types, ``%numpy_typemap`` expansions as above (with
+the user's complex type substituted for the first argument) should
+work.
+
+NumPy Array Scalars and SWIG
+============================
+
+`SWIG`_ has sophisticated type checking for numerical types. For
+example, if your C/C++ routine expects an integer as input, the code
+generated by `SWIG`_ will check for both `python`_ integers and
+`python`_ long integers, and raise an overflow error if the provided
+`python`_ integer is too big to cast down to a C integer. With the
+introduction of `NumPy`_ scalar arrays into your `python`_ code, you
+might conceivably extract an integer from a `NumPy`_ array and attempt
+to pass this to a `SWIG`_-wrapped C/C++ function that expects an
+``int``, but the `SWIG`_ type checking will not recognize the `NumPy`_
+array scalar as an integer. (Often, this does in fact work -- it
+depends on whether `NumPy`_ recognizes the integer type you are using
+as inheriting from the `python`_ integer type on the platform you are
+using. Sometimes, this means that code that works on a 32-bit machine
+will fail on a 64-bit machine.)
+
+If you get a `python`_ error that looks like the following::
+
+ TypeError: in method 'MyClass_MyMethod', argument 2 of type 'int'
+
+and the argument you are passing is an integer extracted from a
+`NumPy`_ array, then you have stumbled upon this problem. The
+solution is to modify the `SWIG`_ type conversion system to accept
+`Numpy`_ array scalars in addition to the standard integer types.
+Fortunately, this capabilitiy has been provided for you. Simply copy
+the file::
+
+ pyfragments.swg
+
+to the working build directory for you project, and this problem will
+be fixed. It is suggested that you do this anyway, as it only
+increases the capabilities of your `python`_ interface.
+
+Why is There a Second File?
+---------------------------
+
+The `SWIG`_ type checking and conversion system is a complicated
+combination of C macros, `SWIG`_ macros, `SWIG`_ typemaps and `SWIG`_
+fragments. Fragments are a way to conditionally insert code into your
+wrapper file if it is needed, and not insert it if not needed. If
+multiple typemaps require the same fragment, the fragment only gets
+inserted into your wrapper code once.
+
+There is a fragment for converting a `python`_ integer to a C
+``long``. There is a different fragment that converts a `python`_
+integer to a C ``int``, that calls the rountine defined in the
+``long`` fragment. We can make the changes we want here by changing
+the definition for the ``long`` fragment. `SWIG`_ determines the
+active definition for a fragment using a "first come, first served"
+system. That is, we need to define the fragment for ``long``
+conversions prior to `SWIG`_ doing it internally. `SWIG`_ allows us
+to do this by putting our fragment definitions in the file
+``pyfragments.swg``. If we were to put the new fragment definitions
+in ``numpy.i``, they would be ignored.
+
+Helper Functions
+================
+
+The ``numpy.i`` file containes several macros and routines that it
+uses internally to build its typemaps. However, these functions may
+be useful elsewhere in your interface file. These macros and routines
+are implemented as fragments, which are described briefly in the
+previous section. If you try to use one or more of the following
+macros or functions, but your compiler complains that it does not
+recognize the symbol, then you need to force these fragments to appear
+in your code using::
+
+ %fragment("NumPy_Fragments");
+
+in your `SWIG`_ interface file.
+
+Macros
+------
+
+ **is_array(a)**
+ Evaluates as true if ``a`` is non-``NULL`` and can be cast to a
+ ``PyArrayObject*``.
+
+ **array_type(a)**
+ Evaluates to the integer data type code of ``a``, assuming ``a`` can
+ be cast to a ``PyArrayObject*``.
+
+ **array_numdims(a)**
+ Evaluates to the integer number of dimensions of ``a``, assuming
+ ``a`` can be cast to a ``PyArrayObject*``.
+
+ **array_dimensions(a)**
+ Evaluates to an array of type ``npy_intp`` and length
+ ``array_numdims(a)``, giving the lengths of all of the dimensions
+ of ``a``, assuming ``a`` can be cast to a ``PyArrayObject*``.
+
+ **array_size(a,i)**
+ Evaluates to the ``i``-th dimension size of ``a``, assuming ``a``
+ can be cast to a ``PyArrayObject*``.
+
+ **array_data(a)**
+ Evaluates to a pointer of type ``void*`` that points to the data
+ buffer of ``a``, assuming ``a`` can be cast to a ``PyArrayObject*``.
+
+ **array_is_contiguous(a)**
+ Evaluates as true if ``a`` is a contiguous array. Equivalent to
+ ``(PyArray_ISCONTIGUOUS(a))``.
+
+ **array_is_native(a)**
+ Evaluates as true if the data buffer of ``a`` uses native byte
+ order. Equivalent to ``(PyArray_ISNOTSWAPPED(a))``.
+
+ **array_is_fortran(a)**
+ Evaluates as true if ``a`` is FORTRAN ordered.
+
+Routines
+--------
+
+ **pytype_string()**
+
+ Return type: ``char*``
+
+ Arguments:
+
+ * ``PyObject* py_obj``, a general `python`_ object.
+
+ Return a string describing the type of ``py_obj``.
+
+
+ **typecode_string()**
+
+ Return type: ``char*``
+
+ Arguments:
+
+ * ``int typecode``, a `NumPy`_ integer typecode.
+
+ Return a string describing the type corresponding to the `NumPy`_
+ ``typecode``.
+
+ **type_match()**
+
+ Return type: ``int``
+
+ Arguments:
+
+ * ``int actual_type``, the `NumPy`_ typecode of a `NumPy`_ array.
+
+ * ``int desired_type``, the desired `NumPy`_ typecode.
+
+ Make sure that ``actual_type`` is compatible with
+ ``desired_type``. For example, this allows character and
+ byte types, or int and long types, to match. This is now
+ equivalent to ``PyArray_EquivTypenums()``.
+
+
+ **obj_to_array_no_conversion()**
+
+ Return type: ``PyArrayObject*``
+
+ Arguments:
+
+ * ``PyObject* input``, a general `python`_ object.
+
+ * ``int typecode``, the desired `NumPy`_ typecode.
+
+ Cast ``input`` to a ``PyArrayObject*`` if legal, and ensure that
+ it is of type ``typecode``. If ``input`` cannot be cast, or the
+ ``typecode`` is wrong, set a `python`_ error and return ``NULL``.
+
+
+ **obj_to_array_allow_conversion()**
+
+ Return type: ``PyArrayObject*``
+
+ Arguments:
+
+ * ``PyObject* input``, a general `python`_ object.
+
+ * ``int typecode``, the desired `NumPy`_ typecode of the resulting
+ array.
+
+ * ``int* is_new_object``, returns a value of 0 if no conversion
+ performed, else 1.
+
+ Convert ``input`` to a `NumPy`_ array with the given ``typecode``.
+ On success, return a valid ``PyArrayObject*`` with the correct
+ type. On failure, the `python`_ error string will be set and the
+ routine returns ``NULL``.
+
+
+ **make_contiguous()**
+
+ Return type: ``PyArrayObject*``
+
+ Arguments:
+
+ * ``PyArrayObject* ary``, a `NumPy`_ array.
+
+ * ``int* is_new_object``, returns a value of 0 if no conversion
+ performed, else 1.
+
+ * ``int min_dims``, minimum allowable dimensions.
+
+ * ``int max_dims``, maximum allowable dimensions.
+
+ Check to see if ``ary`` is contiguous. If so, return the input
+ pointer and flag it as not a new object. If it is not contiguous,
+ create a new ``PyArrayObject*`` using the original data, flag it
+ as a new object and return the pointer.
+
+
+ **obj_to_array_contiguous_allow_conversion()**
+
+ Return type: ``PyArrayObject*``
+
+ Arguments:
+
+ * ``PyObject* input``, a general `python`_ object.
+
+ * ``int typecode``, the desired `NumPy`_ typecode of the resulting
+ array.
+
+ * ``int* is_new_object``, returns a value of 0 if no conversion
+ performed, else 1.
+
+ Convert ``input`` to a contiguous ``PyArrayObject*`` of the
+ specified type. If the input object is not a contiguous
+ ``PyArrayObject*``, a new one will be created and the new object
+ flag will be set.
+
+
+ **require_contiguous()**
+
+ Return type: ``int``
+
+ Arguments:
+
+ * ``PyArrayObject* ary``, a `NumPy`_ array.
+
+ Test whether ``ary`` is contiguous. If so, return 1. Otherwise,
+ set a `python`_ error and return 0.
+
+
+ **require_native()**
+
+ Return type: ``int``
+
+ Arguments:
+
+ * ``PyArray_Object* ary``, a `NumPy`_ array.
+
+ Require that ``ary`` is not byte-swapped. If the array is not
+ byte-swapped, return 1. Otherwise, set a `python`_ error and
+ return 0.
+
+ **require_dimensions()**
+
+ Return type: ``int``
+
+ Arguments:
+
+ * ``PyArrayObject* ary``, a `NumPy`_ array.
+
+ * ``int exact_dimensions``, the desired number of dimensions.
+
+ Require ``ary`` to have a specified number of dimensions. If the
+ array has the specified number of dimensions, return 1.
+ Otherwise, set a `python`_ error and return 0.
+
+
+ **require_dimensions_n()**
+
+ Return type: ``int``
+
+ Arguments:
+
+ * ``PyArrayObject* ary``, a `NumPy`_ array.
+
+ * ``int* exact_dimensions``, an array of integers representing
+ acceptable numbers of dimensions.
+
+ * ``int n``, the length of ``exact_dimensions``.
+
+ Require ``ary`` to have one of a list of specified number of
+ dimensions. If the array has one of the specified number of
+ dimensions, return 1. Otherwise, set the `python`_ error string
+ and return 0.
+
+
+ **require_size()**
+
+ Return type: ``int``
+
+ Arguments:
+
+ * ``PyArrayObject* ary``, a `NumPy`_ array.
+
+ * ``npy_int* size``, an array representing the desired lengths of
+ each dimension.
+
+ * ``int n``, the length of ``size``.
+
+ Require ``ary`` to have a specified shape. If the array has the
+ specified shape, return 1. Otherwise, set the `python`_ error
+ string and return 0.
+
+
+ **require_fortran()**
+
+ Return type: ``int``
+
+ Arguments:
+
+ * ``PyArrayObject* ary``, a `NumPy`_ array.
+
+ Require the given ``PyArrayObject`` to to be FORTRAN ordered. If
+ the the ``PyArrayObject`` is already FORTRAN ordered, do nothing.
+ Else, set the FORTRAN ordering flag and recompute the strides.
+
+
+Beyond the Provided Typemaps
+============================
+
+There are many C or C++ array/`NumPy`_ array situations not covered by
+a simple ``%include "numpy.i"`` and subsequent ``%apply`` directives.
+
+A Common Example
+----------------
+
+Consider a reasonable prototype for a dot product function::
+
+ double dot(int len, double* vec1, double* vec2);
+
+The `python`_ interface that we want is::
+
+ def dot(vec1, vec2):
+ """
+ dot(PyObject,PyObject) -> double
+ """
+
+The problem here is that there is one dimension argument and two array
+arguments, and our typemaps are set up for dimensions that apply to a
+single array (in fact, `SWIG`_ does not provide a mechanism for
+associating ``len`` with ``vec2`` that takes two `python`_ input
+arguments). The recommended solution is the following::
+
+ %apply (int DIM1, double* IN_ARRAY1) {(int len1, double* vec1),
+ (int len2, double* vec2)}
+ %rename (dot) my_dot;
+ %exception my_dot {
+ $action
+ if (PyErr_Occurred()) SWIG_fail;
+ }
+ %inline %{
+ double my_dot(int len1, double* vec1, int len2, double* vec2) {
+ if (len1 != len2) {
+ PyErr_Format(PyExc_ValueError,
+ "Arrays of lengths (%d,%d) given",
+ len1, len2);
+ return 0.0;
+ }
+ return dot(len1, vec1, vec2);
+ }
+ %}
+
+If the header file that contains the prototype for ``double dot()``
+also contains other prototypes that you want to wrap, so that you need
+to ``%include`` this header file, then you will also need a ``%ignore
+dot;`` directive, placed after the ``%rename`` and before the
+``%include`` directives. Or, if the function in question is a class
+method, you will want to use ``%extend`` rather than ``%inline`` in
+addition to ``%ignore``.
+
+**A note on error handling:** Note that ``my_dot`` returns a
+``double`` but that it can also raise a `python`_ error. The
+resulting wrapper function will return a `python`_ float
+representation of 0.0 when the vector lengths do not match. Since
+this is not ``NULL``, the `python`_ interpreter will not know to check
+for an error. For this reason, we add the ``%exception`` directive
+above for ``my_dot`` to get the behavior we want (note that
+``$action`` is a macro that gets expanded to a valid call to
+``my_dot``). In general, you will probably want to write a `SWIG`_
+macro to perform this task.
+
+Other Situations
+----------------
+
+There are other wrapping situations in which ``numpy.i`` may be
+helpful when you encounter them.
+
+ * In some situations, it is possible that you could use the
+ ``%numpy_templates`` macro to implement typemaps for your own
+ types. See the `Other Common Types: bool`_ or `Other Common
+ Types: complex`_ sections for examples. Another situation is if
+ your dimensions are of a type other than ``int`` (say ``long`` for
+ example)::
+
+ %numpy_typemaps(double, NPY_DOUBLE, long)
+
+ * You can use the code in ``numpy.i`` to write your own typemaps.
+ For example, if you had a four-dimensional array as a function
+ argument, you could cut-and-paste the appropriate
+ three-dimensional typemaps into your interface file. The
+ modifications for the fourth dimension would be trivial.
+
+ * Sometimes, the best approach is to use the ``%extend`` directive
+ to define new methods for your classes (or overload existing ones)
+ that take a ``PyObject*`` (that either is or can be converted to a
+ ``PyArrayObject*``) instead of a pointer to a buffer. In this
+ case, the helper routines in ``numpy.i`` can be very useful.
+
+ * Writing typemaps can be a bit nonintuitive. If you have specific
+ questions about writing `SWIG`_ typemaps for `NumPy`_, the
+ developers of ``numpy.i`` do monitor the
+ `Numpy-discussion <mailto:Numpy-discussion@scipy.org>`_ and
+ `Swig-user <mailto:Swig-user@lists.sourceforge.net>`_ mail lists.
+
+A Final Note
+------------
+
+When you use the ``%apply`` directive, as is usually necessary to use
+``numpy.i``, it will remain in effect until you tell `SWIG`_ that it
+shouldn't be. If the arguments to the functions or methods that you
+are wrapping have common names, such as ``length`` or ``vector``,
+these typemaps may get applied in situations you do not expect or
+want. Therefore, it is always a good idea to add a ``%clear``
+directive after you are done with a specific typemap::
+
+ %apply (double* IN_ARRAY1, int DIM1) {(double* vector, int length)}
+ %include "my_header.h"
+ %clear (double* vector, int length);
+
+In general, you should target these typemap signatures specifically
+where you want them, and then clear them after you are done.
+
+Summary
+=======
+
+Out of the box, ``numpy.i`` provides typemaps that support conversion
+between `NumPy`_ arrays and C arrays:
+
+ * That can be one of 12 different scalar types: ``signed char``,
+ ``unsigned char``, ``short``, ``unsigned short``, ``int``,
+ ``unsigned int``, ``long``, ``unsigned long``, ``long long``,
+ ``unsigned long long``, ``float`` and ``double``.
+
+ * That support 41 different argument signatures for each data type,
+ including:
+
+ + One-dimensional, two-dimensional and three-dimensional arrays.
+
+ + Input-only, in-place, argout and argoutview behavior.
+
+ + Hard-coded dimensions, data-buffer-then-dimensions
+ specification, and dimensions-then-data-buffer specification.
+
+ + Both C-ordering ("last dimension fastest") or FORTRAN-ordering
+ ("first dimension fastest") support for 2D and 3D arrays.
+
+The ``numpy.i`` interface file also provides additional tools for
+wrapper developers, including:
+
+ * A `SWIG`_ macro (``%numpy_typemaps``) with three arguments for
+ implementing the 41 argument signatures for the user's choice of
+ (1) C data type, (2) `NumPy`_ data type (assuming they match), and
+ (3) dimension type.
+
+ * Nine C macros and 13 C functions that can be used to write
+ specialized typemaps, extensions, or inlined functions that handle
+ cases not covered by the provided typemaps.
+
+Acknowledgements
+================
+
+Many people have worked to glue `SWIG`_ and `NumPy`_ together (as well
+as `SWIG`_ and the predecessors of `NumPy`_, Numeric and numarray).
+The effort to standardize this work into ``numpy.i`` began at the 2005
+`SciPy <http://scipy.org>`_ Conference with a conversation between
+Fernando Perez and myself. Fernando collected helper functions and
+typemaps from Eric Jones, Michael Hunter, Anna Omelchenko and Michael
+Sanner. Sebastian Hasse and Georg Holzmann have also provided
+additional error checking and use cases. The work of these
+contributors has made this end result possible.
diff --git a/doc/swig/doc/testing.html b/doc/swig/doc/testing.html
new file mode 100644
index 000000000..3622550df
--- /dev/null
+++ b/doc/swig/doc/testing.html
@@ -0,0 +1,482 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
+<title>Testing the numpy.i Typemaps</title>
+<meta name="author" content="Bill Spotz" />
+<meta name="date" content="6 April, 2007" />
+<style type="text/css">
+
+/*
+:Author: David Goodger
+:Contact: goodger@users.sourceforge.net
+:Date: $Date: 2005-12-18 01:56:14 +0100 (Sun, 18 Dec 2005) $
+:Revision: $Revision: 4224 $
+:Copyright: This stylesheet has been placed in the public domain.
+
+Default cascading style sheet for the HTML output of Docutils.
+
+See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
+customize this style sheet.
+*/
+
+/* used to remove borders from tables and images */
+.borderless, table.borderless td, table.borderless th {
+ border: 0 }
+
+table.borderless td, table.borderless th {
+ /* Override padding for "table.docutils td" with "! important".
+ The right padding separates the table cells. */
+ padding: 0 0.5em 0 0 ! important }
+
+.first {
+ /* Override more specific margin styles with "! important". */
+ margin-top: 0 ! important }
+
+.last, .with-subtitle {
+ margin-bottom: 0 ! important }
+
+.hidden {
+ display: none }
+
+a.toc-backref {
+ text-decoration: none ;
+ color: black }
+
+blockquote.epigraph {
+ margin: 2em 5em ; }
+
+dl.docutils dd {
+ margin-bottom: 0.5em }
+
+/* Uncomment (and remove this text!) to get bold-faced definition list terms
+dl.docutils dt {
+ font-weight: bold }
+*/
+
+div.abstract {
+ margin: 2em 5em }
+
+div.abstract p.topic-title {
+ font-weight: bold ;
+ text-align: center }
+
+div.admonition, div.attention, div.caution, div.danger, div.error,
+div.hint, div.important, div.note, div.tip, div.warning {
+ margin: 2em ;
+ border: medium outset ;
+ padding: 1em }
+
+div.admonition p.admonition-title, div.hint p.admonition-title,
+div.important p.admonition-title, div.note p.admonition-title,
+div.tip p.admonition-title {
+ font-weight: bold ;
+ font-family: sans-serif }
+
+div.attention p.admonition-title, div.caution p.admonition-title,
+div.danger p.admonition-title, div.error p.admonition-title,
+div.warning p.admonition-title {
+ color: red ;
+ font-weight: bold ;
+ font-family: sans-serif }
+
+/* Uncomment (and remove this text!) to get reduced vertical space in
+ compound paragraphs.
+div.compound .compound-first, div.compound .compound-middle {
+ margin-bottom: 0.5em }
+
+div.compound .compound-last, div.compound .compound-middle {
+ margin-top: 0.5em }
+*/
+
+div.dedication {
+ margin: 2em 5em ;
+ text-align: center ;
+ font-style: italic }
+
+div.dedication p.topic-title {
+ font-weight: bold ;
+ font-style: normal }
+
+div.figure {
+ margin-left: 2em ;
+ margin-right: 2em }
+
+div.footer, div.header {
+ clear: both;
+ font-size: smaller }
+
+div.line-block {
+ display: block ;
+ margin-top: 1em ;
+ margin-bottom: 1em }
+
+div.line-block div.line-block {
+ margin-top: 0 ;
+ margin-bottom: 0 ;
+ margin-left: 1.5em }
+
+div.sidebar {
+ margin-left: 1em ;
+ border: medium outset ;
+ padding: 1em ;
+ background-color: #ffffee ;
+ width: 40% ;
+ float: right ;
+ clear: right }
+
+div.sidebar p.rubric {
+ font-family: sans-serif ;
+ font-size: medium }
+
+div.system-messages {
+ margin: 5em }
+
+div.system-messages h1 {
+ color: red }
+
+div.system-message {
+ border: medium outset ;
+ padding: 1em }
+
+div.system-message p.system-message-title {
+ color: red ;
+ font-weight: bold }
+
+div.topic {
+ margin: 2em }
+
+h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
+h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
+ margin-top: 0.4em }
+
+h1.title {
+ text-align: center }
+
+h2.subtitle {
+ text-align: center }
+
+hr.docutils {
+ width: 75% }
+
+img.align-left {
+ clear: left }
+
+img.align-right {
+ clear: right }
+
+ol.simple, ul.simple {
+ margin-bottom: 1em }
+
+ol.arabic {
+ list-style: decimal }
+
+ol.loweralpha {
+ list-style: lower-alpha }
+
+ol.upperalpha {
+ list-style: upper-alpha }
+
+ol.lowerroman {
+ list-style: lower-roman }
+
+ol.upperroman {
+ list-style: upper-roman }
+
+p.attribution {
+ text-align: right ;
+ margin-left: 50% }
+
+p.caption {
+ font-style: italic }
+
+p.credits {
+ font-style: italic ;
+ font-size: smaller }
+
+p.label {
+ white-space: nowrap }
+
+p.rubric {
+ font-weight: bold ;
+ font-size: larger ;
+ color: maroon ;
+ text-align: center }
+
+p.sidebar-title {
+ font-family: sans-serif ;
+ font-weight: bold ;
+ font-size: larger }
+
+p.sidebar-subtitle {
+ font-family: sans-serif ;
+ font-weight: bold }
+
+p.topic-title {
+ font-weight: bold }
+
+pre.address {
+ margin-bottom: 0 ;
+ margin-top: 0 ;
+ font-family: serif ;
+ font-size: 100% }
+
+pre.literal-block, pre.doctest-block {
+ margin-left: 2em ;
+ margin-right: 2em ;
+ background-color: #eeeeee }
+
+span.classifier {
+ font-family: sans-serif ;
+ font-style: oblique }
+
+span.classifier-delimiter {
+ font-family: sans-serif ;
+ font-weight: bold }
+
+span.interpreted {
+ font-family: sans-serif }
+
+span.option {
+ white-space: nowrap }
+
+span.pre {
+ white-space: pre }
+
+span.problematic {
+ color: red }
+
+span.section-subtitle {
+ /* font-size relative to parent (h1..h6 element) */
+ font-size: 80% }
+
+table.citation {
+ border-left: solid 1px gray;
+ margin-left: 1px }
+
+table.docinfo {
+ margin: 2em 4em }
+
+table.docutils {
+ margin-top: 0.5em ;
+ margin-bottom: 0.5em }
+
+table.footnote {
+ border-left: solid 1px black;
+ margin-left: 1px }
+
+table.docutils td, table.docutils th,
+table.docinfo td, table.docinfo th {
+ padding-left: 0.5em ;
+ padding-right: 0.5em ;
+ vertical-align: top }
+
+table.docutils th.field-name, table.docinfo th.docinfo-name {
+ font-weight: bold ;
+ text-align: left ;
+ white-space: nowrap ;
+ padding-left: 0 }
+
+h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
+h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
+ font-size: 100% }
+
+tt.docutils {
+ background-color: #eeeeee }
+
+ul.auto-toc {
+ list-style-type: none }
+
+</style>
+</head>
+<body>
+<div class="document" id="testing-the-numpy-i-typemaps">
+<h1 class="title">Testing the numpy.i Typemaps</h1>
+<table class="docinfo" frame="void" rules="none">
+<col class="docinfo-name" />
+<col class="docinfo-content" />
+<tbody valign="top">
+<tr><th class="docinfo-name">Author:</th>
+<td>Bill Spotz</td></tr>
+<tr class="field"><th class="docinfo-name">Institution:</th><td class="field-body">Sandia National Laboratories</td>
+</tr>
+<tr><th class="docinfo-name">Date:</th>
+<td>6 April, 2007</td></tr>
+</tbody>
+</table>
+<div class="contents topic">
+<p class="topic-title first"><a id="contents" name="contents">Contents</a></p>
+<ul class="simple">
+<li><a class="reference" href="#introduction" id="id1" name="id1">Introduction</a></li>
+<li><a class="reference" href="#testing-organization" id="id2" name="id2">Testing Organization</a></li>
+<li><a class="reference" href="#testing-header-files" id="id3" name="id3">Testing Header Files</a></li>
+<li><a class="reference" href="#testing-source-files" id="id4" name="id4">Testing Source Files</a></li>
+<li><a class="reference" href="#testing-swig-interface-files" id="id5" name="id5">Testing SWIG Interface Files</a></li>
+<li><a class="reference" href="#testing-python-scripts" id="id6" name="id6">Testing Python Scripts</a></li>
+</ul>
+</div>
+<div class="section">
+<h1><a class="toc-backref" href="#id1" id="introduction" name="introduction">Introduction</a></h1>
+<p>Writing tests for the <tt class="docutils literal"><span class="pre">numpy.i</span></tt> <a class="reference" href="http://www.swig.org">SWIG</a>
+interface file is a combinatorial headache. At present, 12 different
+data types are supported, each with 23 different argument signatures,
+for a total of 276 typemaps supported &quot;out of the box&quot;. Each of these
+typemaps, in turn, might require several unit tests in order to verify
+expected behavior for both proper and improper inputs. Currently,
+this results in 1,020 individual unit tests that are performed when
+<tt class="docutils literal"><span class="pre">make</span> <span class="pre">test</span></tt> is run in the <tt class="docutils literal"><span class="pre">numpy/docs/swig</span></tt> subdirectory.</p>
+<p>To facilitate this many similar unit tests, some high-level
+programming techniques are employed, including C and <a class="reference" href="http://www.swig.org">SWIG</a> macros,
+as well as <a class="reference" href="http://www.python.org">python</a> inheritance. The
+purpose of this document is to describe the testing infrastructure
+employed to verify that the <tt class="docutils literal"><span class="pre">numpy.i</span></tt> typemaps are working as
+expected.</p>
+</div>
+<div class="section">
+<h1><a class="toc-backref" href="#id2" id="testing-organization" name="testing-organization">Testing Organization</a></h1>
+<p>There are three indepedent testing frameworks supported, for one-,
+two-, and three-dimensional arrays respectively. For one-dimensional
+arrays, there are two C++ files, a header and a source, named:</p>
+<pre class="literal-block">
+Vector.h
+Vector.cxx
+</pre>
+<p>that contain prototypes and code for a variety of functions that have
+one-dimensional arrays as function arguments. The file:</p>
+<pre class="literal-block">
+Vector.i
+</pre>
+<p>is a <a class="reference" href="http://www.swig.org">SWIG</a> interface file that defines a python module <tt class="docutils literal"><span class="pre">Vector</span></tt>
+that wraps the functions in <tt class="docutils literal"><span class="pre">Vector.h</span></tt> while utilizing the typemaps
+in <tt class="docutils literal"><span class="pre">numpy.i</span></tt> to correctly handle the C arrays.</p>
+<p>The <tt class="docutils literal"><span class="pre">Makefile</span></tt> calls <tt class="docutils literal"><span class="pre">swig</span></tt> to generate <tt class="docutils literal"><span class="pre">Vector.py</span></tt> and
+<tt class="docutils literal"><span class="pre">Vector_wrap.cxx</span></tt>, and also executes the <tt class="docutils literal"><span class="pre">setup.py</span></tt> script that
+compiles <tt class="docutils literal"><span class="pre">Vector_wrap.cxx</span></tt> and links together the extension module
+<tt class="docutils literal"><span class="pre">_Vector.so</span></tt> or <tt class="docutils literal"><span class="pre">_Vector.dylib</span></tt>, depending on the platform. This
+extension module and the proxy file <tt class="docutils literal"><span class="pre">Vector.py</span></tt> are both placed in a
+subdirectory under the <tt class="docutils literal"><span class="pre">build</span></tt> directory.</p>
+<p>The actual testing takes place with a <a class="reference" href="http://www.python.org">python</a> script named:</p>
+<pre class="literal-block">
+testVector.py
+</pre>
+<p>that uses the standard <a class="reference" href="http://www.python.org">python</a> library module <tt class="docutils literal"><span class="pre">unittest</span></tt>, which
+performs several tests of each function defined in <tt class="docutils literal"><span class="pre">Vector.h</span></tt> for
+each data type supported.</p>
+<p>Two-dimensional arrays are tested in exactly the same manner. The
+above description applies, but with <tt class="docutils literal"><span class="pre">Matrix</span></tt> substituted for
+<tt class="docutils literal"><span class="pre">Vector</span></tt>. For three-dimensional tests, substitute <tt class="docutils literal"><span class="pre">Tensor</span></tt> for
+<tt class="docutils literal"><span class="pre">Vector</span></tt>. For the descriptions that follow, we will reference the
+<tt class="docutils literal"><span class="pre">Vector</span></tt> tests, but the same information applies to <tt class="docutils literal"><span class="pre">Matrix</span></tt> and
+<tt class="docutils literal"><span class="pre">Tensor</span></tt> tests.</p>
+<p>The command <tt class="docutils literal"><span class="pre">make</span> <span class="pre">test</span></tt> will ensure that all of the test software is
+built and then run all three test scripts.</p>
+</div>
+<div class="section">
+<h1><a class="toc-backref" href="#id3" id="testing-header-files" name="testing-header-files">Testing Header Files</a></h1>
+<p><tt class="docutils literal"><span class="pre">Vector.h</span></tt> is a C++ header file that defines a C macro called
+<tt class="docutils literal"><span class="pre">TEST_FUNC_PROTOS</span></tt> that takes two arguments: <tt class="docutils literal"><span class="pre">TYPE</span></tt>, which is a
+data type name such as <tt class="docutils literal"><span class="pre">unsigned</span> <span class="pre">int</span></tt>; and <tt class="docutils literal"><span class="pre">SNAME</span></tt>, which is a
+short name for the same data type with no spaces, e.g. <tt class="docutils literal"><span class="pre">uint</span></tt>. This
+macro defines several function prototypes that have the prefix
+<tt class="docutils literal"><span class="pre">SNAME</span></tt> and have at least one argument that is an array of type
+<tt class="docutils literal"><span class="pre">TYPE</span></tt>. Those functions that have return arguments return a
+<tt class="docutils literal"><span class="pre">TYPE</span></tt> value.</p>
+<p><tt class="docutils literal"><span class="pre">TEST_FUNC_PROTOS</span></tt> is then implemented for all of the data types
+supported by <tt class="docutils literal"><span class="pre">numpy.i</span></tt>:</p>
+<blockquote>
+<ul class="simple">
+<li><tt class="docutils literal"><span class="pre">signed</span> <span class="pre">char</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">unsigned</span> <span class="pre">char</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">short</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">unsigned</span> <span class="pre">short</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">int</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">unsigned</span> <span class="pre">int</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">long</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">unsigned</span> <span class="pre">long</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">long</span> <span class="pre">long</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">unsigned</span> <span class="pre">long</span> <span class="pre">long</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">float</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">double</span></tt></li>
+</ul>
+</blockquote>
+</div>
+<div class="section">
+<h1><a class="toc-backref" href="#id4" id="testing-source-files" name="testing-source-files">Testing Source Files</a></h1>
+<p><tt class="docutils literal"><span class="pre">Vector.cxx</span></tt> is a C++ source file that implements compilable code
+for each of the function prototypes specified in <tt class="docutils literal"><span class="pre">Vector.h</span></tt>. It
+defines a C macro <tt class="docutils literal"><span class="pre">TEST_FUNCS</span></tt> that has the same arguments and works
+in the same way as <tt class="docutils literal"><span class="pre">TEST_FUNC_PROTOS</span></tt> does in <tt class="docutils literal"><span class="pre">Vector.h</span></tt>.
+<tt class="docutils literal"><span class="pre">TEST_FUNCS</span></tt> is implemented for each of the 12 data types as above.</p>
+</div>
+<div class="section">
+<h1><a class="toc-backref" href="#id5" id="testing-swig-interface-files" name="testing-swig-interface-files">Testing SWIG Interface Files</a></h1>
+<p><tt class="docutils literal"><span class="pre">Vector.i</span></tt> is a <a class="reference" href="http://www.swig.org">SWIG</a> interface file that defines python module
+<tt class="docutils literal"><span class="pre">Vector</span></tt>. It follows the conventions for using <tt class="docutils literal"><span class="pre">numpy.i</span></tt> as
+described in the <a class="reference" href="numpy_swig.html">numpy.i documentation</a>. It
+defines a <a class="reference" href="http://www.swig.org">SWIG</a> macro <tt class="docutils literal"><span class="pre">%apply_numpy_typemaps</span></tt> that has a single
+argument <tt class="docutils literal"><span class="pre">TYPE</span></tt>. It uses the <a class="reference" href="http://www.swig.org">SWIG</a> directive <tt class="docutils literal"><span class="pre">%apply</span></tt> as
+described in the <a class="reference" href="numpy_swig.html">numpy.i documentation</a> to apply the provided
+typemaps to the argument signatures found in <tt class="docutils literal"><span class="pre">Vector.h</span></tt>. This macro
+is then implemented for all of the data types supported by
+<tt class="docutils literal"><span class="pre">numpy.i</span></tt>. It then does a <tt class="docutils literal"><span class="pre">%include</span> <span class="pre">&quot;Vector.h&quot;</span></tt> to wrap all of
+the function prototypes in <tt class="docutils literal"><span class="pre">Vector.h</span></tt> using the typemaps in
+<tt class="docutils literal"><span class="pre">numpy.i</span></tt>.</p>
+</div>
+<div class="section">
+<h1><a class="toc-backref" href="#id6" id="testing-python-scripts" name="testing-python-scripts">Testing Python Scripts</a></h1>
+<p>After <tt class="docutils literal"><span class="pre">make</span></tt> is used to build the testing extension modules,
+<tt class="docutils literal"><span class="pre">testVector.py</span></tt> can be run to execute the tests. As with other
+scripts that use <tt class="docutils literal"><span class="pre">unittest</span></tt> to facilitate unit testing,
+<tt class="docutils literal"><span class="pre">testVector.py</span></tt> defines a class that inherits from
+<tt class="docutils literal"><span class="pre">unittest.TestCase</span></tt>:</p>
+<pre class="literal-block">
+class VectorTestCase(unittest.TestCase):
+</pre>
+<p>However, this class is not run directly. Rather, it serves as a base
+class to several other python classes, each one specific to a
+particular data type. The <tt class="docutils literal"><span class="pre">VectorTestCase</span></tt> class stores two strings
+for typing information:</p>
+<blockquote>
+<dl class="docutils">
+<dt><strong>self.typeStr</strong></dt>
+<dd>A string that matches one of the <tt class="docutils literal"><span class="pre">SNAME</span></tt> prefixes used in
+<tt class="docutils literal"><span class="pre">Vector.h</span></tt> and <tt class="docutils literal"><span class="pre">Vector.cxx</span></tt>. For example, <tt class="docutils literal"><span class="pre">&quot;double&quot;</span></tt>.</dd>
+<dt><strong>self.typeCode</strong></dt>
+<dd>A short (typically single-character) string that represents a
+data type in numpy and corresponds to <tt class="docutils literal"><span class="pre">self.typeStr</span></tt>. For
+example, if <tt class="docutils literal"><span class="pre">self.typeStr</span></tt> is <tt class="docutils literal"><span class="pre">&quot;double&quot;</span></tt>, then
+<tt class="docutils literal"><span class="pre">self.typeCode</span></tt> should be <tt class="docutils literal"><span class="pre">&quot;d&quot;</span></tt>.</dd>
+</dl>
+</blockquote>
+<p>Each test defined by the <tt class="docutils literal"><span class="pre">VectorTestCase</span></tt> class extracts the python
+function it is trying to test by accessing the <tt class="docutils literal"><span class="pre">Vector</span></tt> module's
+dictionary:</p>
+<pre class="literal-block">
+length = Vector.__dict__[self.typeStr + &quot;Length&quot;]
+</pre>
+<p>In the case of double precision tests, this will return the python
+function <tt class="docutils literal"><span class="pre">Vector.doubleLength</span></tt>.</p>
+<p>We then define a new test case class for each supported data type with
+a short definition such as:</p>
+<pre class="literal-block">
+class doubleTestCase(VectorTestCase):
+ def __init__(self, methodName=&quot;runTest&quot;):
+ VectorTestCase.__init__(self, methodName)
+ self.typeStr = &quot;double&quot;
+ self.typeCode = &quot;d&quot;
+</pre>
+<p>Each of these 12 classes is collected into a <tt class="docutils literal"><span class="pre">unittest.TestSuite</span></tt>,
+which is then executed. Errors and failures are summed together and
+returned as the exit argument. Any non-zero result indicates that at
+least one test did not pass.</p>
+</div>
+</div>
+<div class="footer">
+<hr class="footer" />
+Generated on: 2007-04-06 21:21 UTC.
+Generated by <a class="reference" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source.
+
+</div>
+</body>
+</html>
diff --git a/doc/swig/doc/testing.pdf b/doc/swig/doc/testing.pdf
new file mode 100644
index 000000000..9ffcf7575
--- /dev/null
+++ b/doc/swig/doc/testing.pdf
Binary files differ
diff --git a/doc/swig/doc/testing.txt b/doc/swig/doc/testing.txt
new file mode 100644
index 000000000..bfd5218e8
--- /dev/null
+++ b/doc/swig/doc/testing.txt
@@ -0,0 +1,173 @@
+============================
+Testing the numpy.i Typemaps
+============================
+
+:Author: Bill Spotz
+:Institution: Sandia National Laboratories
+:Date: 6 April, 2007
+
+.. contents::
+
+Introduction
+============
+
+Writing tests for the ``numpy.i`` `SWIG <http://www.swig.org>`_
+interface file is a combinatorial headache. At present, 12 different
+data types are supported, each with 23 different argument signatures,
+for a total of 276 typemaps supported "out of the box". Each of these
+typemaps, in turn, might require several unit tests in order to verify
+expected behavior for both proper and improper inputs. Currently,
+this results in 1,020 individual unit tests that are performed when
+``make test`` is run in the ``numpy/docs/swig`` subdirectory.
+
+To facilitate this many similar unit tests, some high-level
+programming techniques are employed, including C and `SWIG`_ macros,
+as well as `python <http://www.python.org>`_ inheritance. The
+purpose of this document is to describe the testing infrastructure
+employed to verify that the ``numpy.i`` typemaps are working as
+expected.
+
+Testing Organization
+====================
+
+There are three indepedent testing frameworks supported, for one-,
+two-, and three-dimensional arrays respectively. For one-dimensional
+arrays, there are two C++ files, a header and a source, named::
+
+ Vector.h
+ Vector.cxx
+
+that contain prototypes and code for a variety of functions that have
+one-dimensional arrays as function arguments. The file::
+
+ Vector.i
+
+is a `SWIG`_ interface file that defines a python module ``Vector``
+that wraps the functions in ``Vector.h`` while utilizing the typemaps
+in ``numpy.i`` to correctly handle the C arrays.
+
+The ``Makefile`` calls ``swig`` to generate ``Vector.py`` and
+``Vector_wrap.cxx``, and also executes the ``setup.py`` script that
+compiles ``Vector_wrap.cxx`` and links together the extension module
+``_Vector.so`` or ``_Vector.dylib``, depending on the platform. This
+extension module and the proxy file ``Vector.py`` are both placed in a
+subdirectory under the ``build`` directory.
+
+The actual testing takes place with a `python`_ script named::
+
+ testVector.py
+
+that uses the standard `python`_ library module ``unittest``, which
+performs several tests of each function defined in ``Vector.h`` for
+each data type supported.
+
+Two-dimensional arrays are tested in exactly the same manner. The
+above description applies, but with ``Matrix`` substituted for
+``Vector``. For three-dimensional tests, substitute ``Tensor`` for
+``Vector``. For the descriptions that follow, we will reference the
+``Vector`` tests, but the same information applies to ``Matrix`` and
+``Tensor`` tests.
+
+The command ``make test`` will ensure that all of the test software is
+built and then run all three test scripts.
+
+Testing Header Files
+====================
+
+``Vector.h`` is a C++ header file that defines a C macro called
+``TEST_FUNC_PROTOS`` that takes two arguments: ``TYPE``, which is a
+data type name such as ``unsigned int``; and ``SNAME``, which is a
+short name for the same data type with no spaces, e.g. ``uint``. This
+macro defines several function prototypes that have the prefix
+``SNAME`` and have at least one argument that is an array of type
+``TYPE``. Those functions that have return arguments return a
+``TYPE`` value.
+
+``TEST_FUNC_PROTOS`` is then implemented for all of the data types
+supported by ``numpy.i``:
+
+ * ``signed char``
+ * ``unsigned char``
+ * ``short``
+ * ``unsigned short``
+ * ``int``
+ * ``unsigned int``
+ * ``long``
+ * ``unsigned long``
+ * ``long long``
+ * ``unsigned long long``
+ * ``float``
+ * ``double``
+
+Testing Source Files
+====================
+
+``Vector.cxx`` is a C++ source file that implements compilable code
+for each of the function prototypes specified in ``Vector.h``. It
+defines a C macro ``TEST_FUNCS`` that has the same arguments and works
+in the same way as ``TEST_FUNC_PROTOS`` does in ``Vector.h``.
+``TEST_FUNCS`` is implemented for each of the 12 data types as above.
+
+Testing SWIG Interface Files
+============================
+
+``Vector.i`` is a `SWIG`_ interface file that defines python module
+``Vector``. It follows the conventions for using ``numpy.i`` as
+described in the `numpy.i documentation <numpy_swig.html>`_. It
+defines a `SWIG`_ macro ``%apply_numpy_typemaps`` that has a single
+argument ``TYPE``. It uses the `SWIG`_ directive ``%apply`` as
+described in the `numpy.i documentation`_ to apply the provided
+typemaps to the argument signatures found in ``Vector.h``. This macro
+is then implemented for all of the data types supported by
+``numpy.i``. It then does a ``%include "Vector.h"`` to wrap all of
+the function prototypes in ``Vector.h`` using the typemaps in
+``numpy.i``.
+
+Testing Python Scripts
+======================
+
+After ``make`` is used to build the testing extension modules,
+``testVector.py`` can be run to execute the tests. As with other
+scripts that use ``unittest`` to facilitate unit testing,
+``testVector.py`` defines a class that inherits from
+``unittest.TestCase``::
+
+ class VectorTestCase(unittest.TestCase):
+
+However, this class is not run directly. Rather, it serves as a base
+class to several other python classes, each one specific to a
+particular data type. The ``VectorTestCase`` class stores two strings
+for typing information:
+
+ **self.typeStr**
+ A string that matches one of the ``SNAME`` prefixes used in
+ ``Vector.h`` and ``Vector.cxx``. For example, ``"double"``.
+
+ **self.typeCode**
+ A short (typically single-character) string that represents a
+ data type in numpy and corresponds to ``self.typeStr``. For
+ example, if ``self.typeStr`` is ``"double"``, then
+ ``self.typeCode`` should be ``"d"``.
+
+Each test defined by the ``VectorTestCase`` class extracts the python
+function it is trying to test by accessing the ``Vector`` module's
+dictionary::
+
+ length = Vector.__dict__[self.typeStr + "Length"]
+
+In the case of double precision tests, this will return the python
+function ``Vector.doubleLength``.
+
+We then define a new test case class for each supported data type with
+a short definition such as::
+
+ class doubleTestCase(VectorTestCase):
+ def __init__(self, methodName="runTest"):
+ VectorTestCase.__init__(self, methodName)
+ self.typeStr = "double"
+ self.typeCode = "d"
+
+Each of these 12 classes is collected into a ``unittest.TestSuite``,
+which is then executed. Errors and failures are summed together and
+returned as the exit argument. Any non-zero result indicates that at
+least one test did not pass.
diff --git a/doc/swig/numpy.i b/doc/swig/numpy.i
new file mode 100644
index 000000000..72fc4f9c4
--- /dev/null
+++ b/doc/swig/numpy.i
@@ -0,0 +1,1634 @@
+/* -*- C -*- (not really, but good for syntax highlighting) */
+#ifdef SWIGPYTHON
+
+%{
+#ifndef SWIG_FILE_WITH_INIT
+# define NO_IMPORT_ARRAY
+#endif
+#include "stdio.h"
+#include <numpy/arrayobject.h>
+%}
+
+/**********************************************************************/
+
+%fragment("NumPy_Backward_Compatibility", "header")
+{
+/* Support older NumPy data type names
+*/
+%#if NDARRAY_VERSION < 0x01000000
+%#define NPY_BOOL PyArray_BOOL
+%#define NPY_BYTE PyArray_BYTE
+%#define NPY_UBYTE PyArray_UBYTE
+%#define NPY_SHORT PyArray_SHORT
+%#define NPY_USHORT PyArray_USHORT
+%#define NPY_INT PyArray_INT
+%#define NPY_UINT PyArray_UINT
+%#define NPY_LONG PyArray_LONG
+%#define NPY_ULONG PyArray_ULONG
+%#define NPY_LONGLONG PyArray_LONGLONG
+%#define NPY_ULONGLONG PyArray_ULONGLONG
+%#define NPY_FLOAT PyArray_FLOAT
+%#define NPY_DOUBLE PyArray_DOUBLE
+%#define NPY_LONGDOUBLE PyArray_LONGDOUBLE
+%#define NPY_CFLOAT PyArray_CFLOAT
+%#define NPY_CDOUBLE PyArray_CDOUBLE
+%#define NPY_CLONGDOUBLE PyArray_CLONGDOUBLE
+%#define NPY_OBJECT PyArray_OBJECT
+%#define NPY_STRING PyArray_STRING
+%#define NPY_UNICODE PyArray_UNICODE
+%#define NPY_VOID PyArray_VOID
+%#define NPY_NTYPES PyArray_NTYPES
+%#define NPY_NOTYPE PyArray_NOTYPE
+%#define NPY_CHAR PyArray_CHAR
+%#define NPY_USERDEF PyArray_USERDEF
+%#define npy_intp intp
+
+%#define NPY_MAX_BYTE MAX_BYTE
+%#define NPY_MIN_BYTE MIN_BYTE
+%#define NPY_MAX_UBYTE MAX_UBYTE
+%#define NPY_MAX_SHORT MAX_SHORT
+%#define NPY_MIN_SHORT MIN_SHORT
+%#define NPY_MAX_USHORT MAX_USHORT
+%#define NPY_MAX_INT MAX_INT
+%#define NPY_MIN_INT MIN_INT
+%#define NPY_MAX_UINT MAX_UINT
+%#define NPY_MAX_LONG MAX_LONG
+%#define NPY_MIN_LONG MIN_LONG
+%#define NPY_MAX_ULONG MAX_ULONG
+%#define NPY_MAX_LONGLONG MAX_LONGLONG
+%#define NPY_MIN_LONGLONG MIN_LONGLONG
+%#define NPY_MAX_ULONGLONG MAX_ULONGLONG
+%#define NPY_MAX_INTP MAX_INTP
+%#define NPY_MIN_INTP MIN_INTP
+
+%#define NPY_FARRAY FARRAY
+%#define NPY_F_CONTIGUOUS F_CONTIGUOUS
+%#endif
+}
+
+/**********************************************************************/
+
+/* The following code originally appeared in
+ * enthought/kiva/agg/src/numeric.i written by Eric Jones. It was
+ * translated from C++ to C by John Hunter. Bill Spotz has modified
+ * it to fix some minor bugs, upgrade from Numeric to numpy (all
+ * versions), add some comments and functionality, and convert from
+ * direct code insertion to SWIG fragments.
+ */
+
+%fragment("NumPy_Macros", "header")
+{
+/* Macros to extract array attributes.
+ */
+%#define is_array(a) ((a) && PyArray_Check((PyArrayObject *)a))
+%#define array_type(a) (int)(PyArray_TYPE(a))
+%#define array_numdims(a) (((PyArrayObject *)a)->nd)
+%#define array_dimensions(a) (((PyArrayObject *)a)->dimensions)
+%#define array_size(a,i) (((PyArrayObject *)a)->dimensions[i])
+%#define array_data(a) (((PyArrayObject *)a)->data)
+%#define array_is_contiguous(a) (PyArray_ISCONTIGUOUS(a))
+%#define array_is_native(a) (PyArray_ISNOTSWAPPED(a))
+%#define array_is_fortran(a) (PyArray_ISFORTRAN(a))
+}
+
+/**********************************************************************/
+
+%fragment("NumPy_Utilities", "header")
+{
+ /* Given a PyObject, return a string describing its type.
+ */
+ char* pytype_string(PyObject* py_obj) {
+ if (py_obj == NULL ) return "C NULL value";
+ if (py_obj == Py_None ) return "Python None" ;
+ if (PyCallable_Check(py_obj)) return "callable" ;
+ if (PyString_Check( py_obj)) return "string" ;
+ if (PyInt_Check( py_obj)) return "int" ;
+ if (PyFloat_Check( py_obj)) return "float" ;
+ if (PyDict_Check( py_obj)) return "dict" ;
+ if (PyList_Check( py_obj)) return "list" ;
+ if (PyTuple_Check( py_obj)) return "tuple" ;
+ if (PyFile_Check( py_obj)) return "file" ;
+ if (PyModule_Check( py_obj)) return "module" ;
+ if (PyInstance_Check(py_obj)) return "instance" ;
+
+ return "unkown type";
+ }
+
+ /* Given a NumPy typecode, return a string describing the type.
+ */
+ char* typecode_string(int typecode) {
+ static char* type_names[25] = {"bool", "byte", "unsigned byte",
+ "short", "unsigned short", "int",
+ "unsigned int", "long", "unsigned long",
+ "long long", "unsigned long long",
+ "float", "double", "long double",
+ "complex float", "complex double",
+ "complex long double", "object",
+ "string", "unicode", "void", "ntypes",
+ "notype", "char", "unknown"};
+ return typecode < 24 ? type_names[typecode] : type_names[24];
+ }
+
+ /* Make sure input has correct numpy type. Allow character and byte
+ * to match. Also allow int and long to match. This is deprecated.
+ * You should use PyArray_EquivTypenums() instead.
+ */
+ int type_match(int actual_type, int desired_type) {
+ return PyArray_EquivTypenums(actual_type, desired_type);
+ }
+}
+
+/**********************************************************************/
+
+%fragment("NumPy_Object_to_Array", "header",
+ fragment="NumPy_Backward_Compatibility",
+ fragment="NumPy_Macros",
+ fragment="NumPy_Utilities")
+{
+ /* Given a PyObject pointer, cast it to a PyArrayObject pointer if
+ * legal. If not, set the python error string appropriately and
+ * return NULL.
+ */
+ PyArrayObject* obj_to_array_no_conversion(PyObject* input, int typecode)
+ {
+ PyArrayObject* ary = NULL;
+ if (is_array(input) && (typecode == NPY_NOTYPE ||
+ PyArray_EquivTypenums(array_type(input), typecode)))
+ {
+ ary = (PyArrayObject*) input;
+ }
+ else if is_array(input)
+ {
+ char* desired_type = typecode_string(typecode);
+ char* actual_type = typecode_string(array_type(input));
+ PyErr_Format(PyExc_TypeError,
+ "Array of type '%s' required. Array of type '%s' given",
+ desired_type, actual_type);
+ ary = NULL;
+ }
+ else
+ {
+ char * desired_type = typecode_string(typecode);
+ char * actual_type = pytype_string(input);
+ PyErr_Format(PyExc_TypeError,
+ "Array of type '%s' required. A '%s' was given",
+ desired_type, actual_type);
+ ary = NULL;
+ }
+ return ary;
+ }
+
+ /* Convert the given PyObject to a NumPy array with the given
+ * typecode. On success, return a valid PyArrayObject* with the
+ * correct type. On failure, the python error string will be set and
+ * the routine returns NULL.
+ */
+ PyArrayObject* obj_to_array_allow_conversion(PyObject* input, int typecode,
+ int* is_new_object)
+ {
+ PyArrayObject* ary = NULL;
+ PyObject* py_obj;
+ if (is_array(input) && (typecode == NPY_NOTYPE ||
+ PyArray_EquivTypenums(array_type(input),typecode)))
+ {
+ ary = (PyArrayObject*) input;
+ *is_new_object = 0;
+ }
+ else
+ {
+ py_obj = PyArray_FROMANY(input, typecode, 0, 0, NPY_DEFAULT);
+ /* If NULL, PyArray_FromObject will have set python error value.*/
+ ary = (PyArrayObject*) py_obj;
+ *is_new_object = 1;
+ }
+ return ary;
+ }
+
+ /* Given a PyArrayObject, check to see if it is contiguous. If so,
+ * return the input pointer and flag it as not a new object. If it is
+ * not contiguous, create a new PyArrayObject using the original data,
+ * flag it as a new object and return the pointer.
+ */
+ PyArrayObject* make_contiguous(PyArrayObject* ary, int* is_new_object,
+ int min_dims, int max_dims)
+ {
+ PyArrayObject* result;
+ if (array_is_contiguous(ary))
+ {
+ result = ary;
+ *is_new_object = 0;
+ }
+ else
+ {
+ result = (PyArrayObject*) PyArray_ContiguousFromObject((PyObject*)ary,
+ array_type(ary),
+ min_dims,
+ max_dims);
+ *is_new_object = 1;
+ }
+ return result;
+ }
+
+ /* Given a PyArrayObject, check to see if it is Fortran-contiguous.
+ * If so, return the input pointer, but do not flag it as not a new
+ * object. If it is not Fortran-contiguous, create a new
+ * PyArrayObject using the original data, flag it as a new object
+ * and return the pointer.
+ */
+ PyArrayObject* make_fortran(PyArrayObject* ary, int* is_new_object,
+ int min_dims, int max_dims)
+ {
+ PyArrayObject* result;
+ if (array_is_fortran(ary))
+ {
+ result = ary;
+ *is_new_object = 0;
+ }
+ else
+ {
+ Py_INCREF(ary->descr);
+ result = (PyArrayObject*) PyArray_FromArray(ary, ary->descr, NPY_FORTRAN);
+ *is_new_object = 1;
+ }
+ return result;
+ }
+
+ /* Convert a given PyObject to a contiguous PyArrayObject of the
+ * specified type. If the input object is not a contiguous
+ * PyArrayObject, a new one will be created and the new object flag
+ * will be set.
+ */
+ PyArrayObject* obj_to_array_contiguous_allow_conversion(PyObject* input,
+ int typecode,
+ int* is_new_object)
+ {
+ int is_new1 = 0;
+ int is_new2 = 0;
+ PyArrayObject* ary2;
+ PyArrayObject* ary1 = obj_to_array_allow_conversion(input, typecode,
+ &is_new1);
+ if (ary1)
+ {
+ ary2 = make_contiguous(ary1, &is_new2, 0, 0);
+ if ( is_new1 && is_new2)
+ {
+ Py_DECREF(ary1);
+ }
+ ary1 = ary2;
+ }
+ *is_new_object = is_new1 || is_new2;
+ return ary1;
+ }
+
+ /* Convert a given PyObject to a Fortran-ordered PyArrayObject of the
+ * specified type. If the input object is not a Fortran-ordered
+ * PyArrayObject, a new one will be created and the new object flag
+ * will be set.
+ */
+ PyArrayObject* obj_to_array_fortran_allow_conversion(PyObject* input,
+ int typecode,
+ int* is_new_object)
+ {
+ int is_new1 = 0;
+ int is_new2 = 0;
+ PyArrayObject* ary2;
+ PyArrayObject* ary1 = obj_to_array_allow_conversion(input, typecode,
+ &is_new1);
+ if (ary1)
+ {
+ ary2 = make_fortran(ary1, &is_new2, 0, 0);
+ if (is_new1 && is_new2)
+ {
+ Py_DECREF(ary1);
+ }
+ ary1 = ary2;
+ }
+ *is_new_object = is_new1 || is_new2;
+ return ary1;
+ }
+
+} /* end fragment */
+
+
+/**********************************************************************/
+
+%fragment("NumPy_Array_Requirements", "header",
+ fragment="NumPy_Backward_Compatibility",
+ fragment="NumPy_Macros")
+{
+ /* Test whether a python object is contiguous. If array is
+ * contiguous, return 1. Otherwise, set the python error string and
+ * return 0.
+ */
+ int require_contiguous(PyArrayObject* ary)
+ {
+ int contiguous = 1;
+ if (!array_is_contiguous(ary))
+ {
+ PyErr_SetString(PyExc_TypeError,
+ "Array must be contiguous. A non-contiguous array was given");
+ contiguous = 0;
+ }
+ return contiguous;
+ }
+
+ /* Require that a numpy array is not byte-swapped. If the array is
+ * not byte-swapped, return 1. Otherwise, set the python error string
+ * and return 0.
+ */
+ int require_native(PyArrayObject* ary)
+ {
+ int native = 1;
+ if (!array_is_native(ary))
+ {
+ PyErr_SetString(PyExc_TypeError,
+ "Array must have native byteorder. "
+ "A byte-swapped array was given");
+ native = 0;
+ }
+ return native;
+ }
+
+ /* Require the given PyArrayObject to have a specified number of
+ * dimensions. If the array has the specified number of dimensions,
+ * return 1. Otherwise, set the python error string and return 0.
+ */
+ int require_dimensions(PyArrayObject* ary, int exact_dimensions)
+ {
+ int success = 1;
+ if (array_numdims(ary) != exact_dimensions)
+ {
+ PyErr_Format(PyExc_TypeError,
+ "Array must have %d dimensions. Given array has %d dimensions",
+ exact_dimensions, array_numdims(ary));
+ success = 0;
+ }
+ return success;
+ }
+
+ /* Require the given PyArrayObject to have one of a list of specified
+ * number of dimensions. If the array has one of the specified number
+ * of dimensions, return 1. Otherwise, set the python error string
+ * and return 0.
+ */
+ int require_dimensions_n(PyArrayObject* ary, int* exact_dimensions, int n)
+ {
+ int success = 0;
+ int i;
+ char dims_str[255] = "";
+ char s[255];
+ for (i = 0; i < n && !success; i++)
+ {
+ if (array_numdims(ary) == exact_dimensions[i])
+ {
+ success = 1;
+ }
+ }
+ if (!success)
+ {
+ for (i = 0; i < n-1; i++)
+ {
+ sprintf(s, "%d, ", exact_dimensions[i]);
+ strcat(dims_str,s);
+ }
+ sprintf(s, " or %d", exact_dimensions[n-1]);
+ strcat(dims_str,s);
+ PyErr_Format(PyExc_TypeError,
+ "Array must have %s dimensions. Given array has %d dimensions",
+ dims_str, array_numdims(ary));
+ }
+ return success;
+ }
+
+ /* Require the given PyArrayObject to have a specified shape. If the
+ * array has the specified shape, return 1. Otherwise, set the python
+ * error string and return 0.
+ */
+ int require_size(PyArrayObject* ary, npy_intp* size, int n)
+ {
+ int i;
+ int success = 1;
+ int len;
+ char desired_dims[255] = "[";
+ char s[255];
+ char actual_dims[255] = "[";
+ for(i=0; i < n;i++)
+ {
+ if (size[i] != -1 && size[i] != array_size(ary,i))
+ {
+ success = 0;
+ }
+ }
+ if (!success)
+ {
+ for (i = 0; i < n; i++)
+ {
+ if (size[i] == -1)
+ {
+ sprintf(s, "*,");
+ }
+ else
+ {
+ sprintf(s, "%ld,", (long int)size[i]);
+ }
+ strcat(desired_dims,s);
+ }
+ len = strlen(desired_dims);
+ desired_dims[len-1] = ']';
+ for (i = 0; i < n; i++)
+ {
+ sprintf(s, "%ld,", (long int)array_size(ary,i));
+ strcat(actual_dims,s);
+ }
+ len = strlen(actual_dims);
+ actual_dims[len-1] = ']';
+ PyErr_Format(PyExc_TypeError,
+ "Array must have shape of %s. Given array has shape of %s",
+ desired_dims, actual_dims);
+ }
+ return success;
+ }
+
+ /* Require the given PyArrayObject to to be FORTRAN ordered. If the
+ * the PyArrayObject is already FORTRAN ordered, do nothing. Else,
+ * set the FORTRAN ordering flag and recompute the strides.
+ */
+ int require_fortran(PyArrayObject* ary)
+ {
+ int success = 1;
+ int nd = array_numdims(ary);
+ int i;
+ if (array_is_fortran(ary)) return success;
+ /* Set the FORTRAN ordered flag */
+ ary->flags = NPY_FARRAY;
+ /* Recompute the strides */
+ ary->strides[0] = ary->strides[nd-1];
+ for (i=1; i < nd; ++i)
+ ary->strides[i] = ary->strides[i-1] * array_size(ary,i-1);
+ return success;
+ }
+}
+
+/* Combine all NumPy fragments into one for convenience */
+%fragment("NumPy_Fragments", "header",
+ fragment="NumPy_Backward_Compatibility",
+ fragment="NumPy_Macros",
+ fragment="NumPy_Utilities",
+ fragment="NumPy_Object_to_Array",
+ fragment="NumPy_Array_Requirements") { }
+
+/* End John Hunter translation (with modifications by Bill Spotz)
+ */
+
+/* %numpy_typemaps() macro
+ *
+ * This macro defines a family of 41 typemaps that allow C arguments
+ * of the form
+ *
+ * (DATA_TYPE IN_ARRAY1[ANY])
+ * (DATA_TYPE* IN_ARRAY1, DIM_TYPE DIM1)
+ * (DIM_TYPE DIM1, DATA_TYPE* IN_ARRAY1)
+ *
+ * (DATA_TYPE IN_ARRAY2[ANY][ANY])
+ * (DATA_TYPE* IN_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2)
+ * (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_ARRAY2)
+ * (DATA_TYPE* IN_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2)
+ * (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_FARRAY2)
+ *
+ * (DATA_TYPE IN_ARRAY3[ANY][ANY][ANY])
+ * (DATA_TYPE* IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3)
+ * (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_ARRAY3)
+ * (DATA_TYPE* IN_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3)
+ * (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_FARRAY3)
+ *
+ * (DATA_TYPE INPLACE_ARRAY1[ANY])
+ * (DATA_TYPE* INPLACE_ARRAY1, DIM_TYPE DIM1)
+ * (DIM_TYPE DIM1, DATA_TYPE* INPLACE_ARRAY1)
+ *
+ * (DATA_TYPE INPLACE_ARRAY2[ANY][ANY])
+ * (DATA_TYPE* INPLACE_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2)
+ * (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_ARRAY2)
+ * (DATA_TYPE* INPLACE_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2)
+ * (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_FARRAY2)
+ *
+ * (DATA_TYPE INPLACE_ARRAY3[ANY][ANY][ANY])
+ * (DATA_TYPE* INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3)
+ * (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_ARRAY3)
+ * (DATA_TYPE* INPLACE_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3)
+ * (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_FARRAY3)
+ *
+ * (DATA_TYPE ARGOUT_ARRAY1[ANY])
+ * (DATA_TYPE* ARGOUT_ARRAY1, DIM_TYPE DIM1)
+ * (DIM_TYPE DIM1, DATA_TYPE* ARGOUT_ARRAY1)
+ *
+ * (DATA_TYPE ARGOUT_ARRAY2[ANY][ANY])
+ *
+ * (DATA_TYPE ARGOUT_ARRAY3[ANY][ANY][ANY])
+ *
+ * (DATA_TYPE** ARGOUTVIEW_ARRAY1, DIM_TYPE* DIM1)
+ * (DIM_TYPE* DIM1, DATA_TYPE** ARGOUTVIEW_ARRAY1)
+ *
+ * (DATA_TYPE** ARGOUTVIEW_ARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2)
+ * (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_ARRAY2)
+ * (DATA_TYPE** ARGOUTVIEW_FARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2)
+ * (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_FARRAY2)
+ *
+ * (DATA_TYPE** ARGOUTVIEW_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3)
+ * (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_ARRAY3)
+ * (DATA_TYPE** ARGOUTVIEW_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3)
+ * (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_FARRAY3)
+ *
+ * where "DATA_TYPE" is any type supported by the NumPy module, and
+ * "DIM_TYPE" is any int-like type suitable for specifying dimensions.
+ * The difference between "ARRAY" typemaps and "FARRAY" typemaps is
+ * that the "FARRAY" typemaps expect FORTRAN ordering of
+ * multidimensional arrays. In python, the dimensions will not need
+ * to be specified (except for the "DATA_TYPE* ARGOUT_ARRAY1"
+ * typemaps). The IN_ARRAYs can be a numpy array or any sequence that
+ * can be converted to a numpy array of the specified type. The
+ * INPLACE_ARRAYs must be numpy arrays of the appropriate type. The
+ * ARGOUT_ARRAYs will be returned as new numpy arrays of the
+ * appropriate type.
+ *
+ * These typemaps can be applied to existing functions using the
+ * %apply directive. For example:
+ *
+ * %apply (double* IN_ARRAY1, int DIM1) {(double* series, int length)};
+ * double prod(double* series, int length);
+ *
+ * %apply (int DIM1, int DIM2, double* INPLACE_ARRAY2)
+ * {(int rows, int cols, double* matrix )};
+ * void floor(int rows, int cols, double* matrix, double f);
+ *
+ * %apply (double IN_ARRAY3[ANY][ANY][ANY])
+ * {(double tensor[2][2][2] )};
+ * %apply (double ARGOUT_ARRAY3[ANY][ANY][ANY])
+ * {(double low[2][2][2] )};
+ * %apply (double ARGOUT_ARRAY3[ANY][ANY][ANY])
+ * {(double upp[2][2][2] )};
+ * void luSplit(double tensor[2][2][2],
+ * double low[2][2][2],
+ * double upp[2][2][2] );
+ *
+ * or directly with
+ *
+ * double prod(double* IN_ARRAY1, int DIM1);
+ *
+ * void floor(int DIM1, int DIM2, double* INPLACE_ARRAY2, double f);
+ *
+ * void luSplit(double IN_ARRAY3[ANY][ANY][ANY],
+ * double ARGOUT_ARRAY3[ANY][ANY][ANY],
+ * double ARGOUT_ARRAY3[ANY][ANY][ANY]);
+ */
+
+%define %numpy_typemaps(DATA_TYPE, DATA_TYPECODE, DIM_TYPE)
+
+/************************/
+/* Input Array Typemaps */
+/************************/
+
+/* Typemap suite for (DATA_TYPE IN_ARRAY1[ANY])
+ */
+%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY,
+ fragment="NumPy_Macros")
+ (DATA_TYPE IN_ARRAY1[ANY])
+{
+ $1 = is_array($input) || PySequence_Check($input);
+}
+%typemap(in,
+ fragment="NumPy_Fragments")
+ (DATA_TYPE IN_ARRAY1[ANY])
+ (PyArrayObject* array=NULL, int is_new_object=0)
+{
+ npy_intp size[1] = { $1_dim0 };
+ array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE,
+ &is_new_object);
+ if (!array || !require_dimensions(array, 1) ||
+ !require_size(array, size, 1)) SWIG_fail;
+ $1 = ($1_ltype) array_data(array);
+}
+%typemap(freearg)
+ (DATA_TYPE IN_ARRAY1[ANY])
+{
+ if (is_new_object$argnum && array$argnum)
+ { Py_DECREF(array$argnum); }
+}
+
+/* Typemap suite for (DATA_TYPE* IN_ARRAY1, DIM_TYPE DIM1)
+ */
+%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY,
+ fragment="NumPy_Macros")
+ (DATA_TYPE* IN_ARRAY1, DIM_TYPE DIM1)
+{
+ $1 = is_array($input) || PySequence_Check($input);
+}
+%typemap(in,
+ fragment="NumPy_Fragments")
+ (DATA_TYPE* IN_ARRAY1, DIM_TYPE DIM1)
+ (PyArrayObject* array=NULL, int is_new_object=0)
+{
+ npy_intp size[1] = { -1 };
+ array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE,
+ &is_new_object);
+ if (!array || !require_dimensions(array, 1) ||
+ !require_size(array, size, 1)) SWIG_fail;
+ $1 = (DATA_TYPE*) array_data(array);
+ $2 = (DIM_TYPE) array_size(array,0);
+}
+%typemap(freearg)
+ (DATA_TYPE* IN_ARRAY1, DIM_TYPE DIM1)
+{
+ if (is_new_object$argnum && array$argnum)
+ { Py_DECREF(array$argnum); }
+}
+
+/* Typemap suite for (DIM_TYPE DIM1, DATA_TYPE* IN_ARRAY1)
+ */
+%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY,
+ fragment="NumPy_Macros")
+ (DIM_TYPE DIM1, DATA_TYPE* IN_ARRAY1)
+{
+ $1 = is_array($input) || PySequence_Check($input);
+}
+%typemap(in,
+ fragment="NumPy_Fragments")
+ (DIM_TYPE DIM1, DATA_TYPE* IN_ARRAY1)
+ (PyArrayObject* array=NULL, int is_new_object=0)
+{
+ npy_intp size[1] = {-1};
+ array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE,
+ &is_new_object);
+ if (!array || !require_dimensions(array, 1) ||
+ !require_size(array, size, 1)) SWIG_fail;
+ $1 = (DIM_TYPE) array_size(array,0);
+ $2 = (DATA_TYPE*) array_data(array);
+}
+%typemap(freearg)
+ (DIM_TYPE DIM1, DATA_TYPE* IN_ARRAY1)
+{
+ if (is_new_object$argnum && array$argnum)
+ { Py_DECREF(array$argnum); }
+}
+
+/* Typemap suite for (DATA_TYPE IN_ARRAY2[ANY][ANY])
+ */
+%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY,
+ fragment="NumPy_Macros")
+ (DATA_TYPE IN_ARRAY2[ANY][ANY])
+{
+ $1 = is_array($input) || PySequence_Check($input);
+}
+%typemap(in,
+ fragment="NumPy_Fragments")
+ (DATA_TYPE IN_ARRAY2[ANY][ANY])
+ (PyArrayObject* array=NULL, int is_new_object=0)
+{
+ npy_intp size[2] = { $1_dim0, $1_dim1 };
+ array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE,
+ &is_new_object);
+ if (!array || !require_dimensions(array, 2) ||
+ !require_size(array, size, 2)) SWIG_fail;
+ $1 = ($1_ltype) array_data(array);
+}
+%typemap(freearg)
+ (DATA_TYPE IN_ARRAY2[ANY][ANY])
+{
+ if (is_new_object$argnum && array$argnum)
+ { Py_DECREF(array$argnum); }
+}
+
+/* Typemap suite for (DATA_TYPE* IN_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2)
+ */
+%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY,
+ fragment="NumPy_Macros")
+ (DATA_TYPE* IN_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2)
+{
+ $1 = is_array($input) || PySequence_Check($input);
+}
+%typemap(in,
+ fragment="NumPy_Fragments")
+ (DATA_TYPE* IN_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2)
+ (PyArrayObject* array=NULL, int is_new_object=0)
+{
+ npy_intp size[2] = { -1, -1 };
+ array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE,
+ &is_new_object);
+ if (!array || !require_dimensions(array, 2) ||
+ !require_size(array, size, 2)) SWIG_fail;
+ $1 = (DATA_TYPE*) array_data(array);
+ $2 = (DIM_TYPE) array_size(array,0);
+ $3 = (DIM_TYPE) array_size(array,1);
+}
+%typemap(freearg)
+ (DATA_TYPE* IN_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2)
+{
+ if (is_new_object$argnum && array$argnum)
+ { Py_DECREF(array$argnum); }
+}
+
+/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_ARRAY2)
+ */
+%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY,
+ fragment="NumPy_Macros")
+ (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_ARRAY2)
+{
+ $1 = is_array($input) || PySequence_Check($input);
+}
+%typemap(in,
+ fragment="NumPy_Fragments")
+ (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_ARRAY2)
+ (PyArrayObject* array=NULL, int is_new_object=0)
+{
+ npy_intp size[2] = { -1, -1 };
+ array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE,
+ &is_new_object);
+ if (!array || !require_dimensions(array, 2) ||
+ !require_size(array, size, 2)) SWIG_fail;
+ $1 = (DIM_TYPE) array_size(array,0);
+ $2 = (DIM_TYPE) array_size(array,1);
+ $3 = (DATA_TYPE*) array_data(array);
+}
+%typemap(freearg)
+ (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_ARRAY2)
+{
+ if (is_new_object$argnum && array$argnum)
+ { Py_DECREF(array$argnum); }
+}
+
+/* Typemap suite for (DATA_TYPE* IN_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2)
+ */
+%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY,
+ fragment="NumPy_Macros")
+ (DATA_TYPE* IN_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2)
+{
+ $1 = is_array($input) || PySequence_Check($input);
+}
+%typemap(in,
+ fragment="NumPy_Fragments")
+ (DATA_TYPE* IN_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2)
+ (PyArrayObject* array=NULL, int is_new_object=0)
+{
+ npy_intp size[2] = { -1, -1 };
+ array = obj_to_array_fortran_allow_conversion($input, DATA_TYPECODE,
+ &is_new_object);
+ if (!array || !require_dimensions(array, 2) ||
+ !require_size(array, size, 2) || !require_fortran(array)) SWIG_fail;
+ $1 = (DATA_TYPE*) array_data(array);
+ $2 = (DIM_TYPE) array_size(array,0);
+ $3 = (DIM_TYPE) array_size(array,1);
+}
+%typemap(freearg)
+ (DATA_TYPE* IN_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2)
+{
+ if (is_new_object$argnum && array$argnum)
+ { Py_DECREF(array$argnum); }
+}
+
+/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_FARRAY2)
+ */
+%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY,
+ fragment="NumPy_Macros")
+ (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_FARRAY2)
+{
+ $1 = is_array($input) || PySequence_Check($input);
+}
+%typemap(in,
+ fragment="NumPy_Fragments")
+ (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_FARRAY2)
+ (PyArrayObject* array=NULL, int is_new_object=0)
+{
+ npy_intp size[2] = { -1, -1 };
+ array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE,
+ &is_new_object);
+ if (!array || !require_dimensions(array, 2) ||
+ !require_size(array, size, 2) || !require_fortran(array)) SWIG_fail;
+ $1 = (DIM_TYPE) array_size(array,0);
+ $2 = (DIM_TYPE) array_size(array,1);
+ $3 = (DATA_TYPE*) array_data(array);
+}
+%typemap(freearg)
+ (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_FARRAY2)
+{
+ if (is_new_object$argnum && array$argnum)
+ { Py_DECREF(array$argnum); }
+}
+
+/* Typemap suite for (DATA_TYPE IN_ARRAY3[ANY][ANY][ANY])
+ */
+%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY,
+ fragment="NumPy_Macros")
+ (DATA_TYPE IN_ARRAY3[ANY][ANY][ANY])
+{
+ $1 = is_array($input) || PySequence_Check($input);
+}
+%typemap(in,
+ fragment="NumPy_Fragments")
+ (DATA_TYPE IN_ARRAY3[ANY][ANY][ANY])
+ (PyArrayObject* array=NULL, int is_new_object=0)
+{
+ npy_intp size[3] = { $1_dim0, $1_dim1, $1_dim2 };
+ array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE,
+ &is_new_object);
+ if (!array || !require_dimensions(array, 3) ||
+ !require_size(array, size, 3)) SWIG_fail;
+ $1 = ($1_ltype) array_data(array);
+}
+%typemap(freearg)
+ (DATA_TYPE IN_ARRAY3[ANY][ANY][ANY])
+{
+ if (is_new_object$argnum && array$argnum)
+ { Py_DECREF(array$argnum); }
+}
+
+/* Typemap suite for (DATA_TYPE* IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2,
+ * DIM_TYPE DIM3)
+ */
+%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY,
+ fragment="NumPy_Macros")
+ (DATA_TYPE* IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3)
+{
+ $1 = is_array($input) || PySequence_Check($input);
+}
+%typemap(in,
+ fragment="NumPy_Fragments")
+ (DATA_TYPE* IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3)
+ (PyArrayObject* array=NULL, int is_new_object=0)
+{
+ npy_intp size[3] = { -1, -1, -1 };
+ array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE,
+ &is_new_object);
+ if (!array || !require_dimensions(array, 3) ||
+ !require_size(array, size, 3)) SWIG_fail;
+ $1 = (DATA_TYPE*) array_data(array);
+ $2 = (DIM_TYPE) array_size(array,0);
+ $3 = (DIM_TYPE) array_size(array,1);
+ $4 = (DIM_TYPE) array_size(array,2);
+}
+%typemap(freearg)
+ (DATA_TYPE* IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3)
+{
+ if (is_new_object$argnum && array$argnum)
+ { Py_DECREF(array$argnum); }
+}
+
+/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3,
+ * DATA_TYPE* IN_ARRAY3)
+ */
+%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY,
+ fragment="NumPy_Macros")
+ (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_ARRAY3)
+{
+ $1 = is_array($input) || PySequence_Check($input);
+}
+%typemap(in,
+ fragment="NumPy_Fragments")
+ (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_ARRAY3)
+ (PyArrayObject* array=NULL, int is_new_object=0)
+{
+ npy_intp size[3] = { -1, -1, -1 };
+ array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE,
+ &is_new_object);
+ if (!array || !require_dimensions(array, 3) ||
+ !require_size(array, size, 3)) SWIG_fail;
+ $1 = (DIM_TYPE) array_size(array,0);
+ $2 = (DIM_TYPE) array_size(array,1);
+ $3 = (DIM_TYPE) array_size(array,2);
+ $4 = (DATA_TYPE*) array_data(array);
+}
+%typemap(freearg)
+ (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_ARRAY3)
+{
+ if (is_new_object$argnum && array$argnum)
+ { Py_DECREF(array$argnum); }
+}
+
+/* Typemap suite for (DATA_TYPE* IN_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2,
+ * DIM_TYPE DIM3)
+ */
+%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY,
+ fragment="NumPy_Macros")
+ (DATA_TYPE* IN_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3)
+{
+ $1 = is_array($input) || PySequence_Check($input);
+}
+%typemap(in,
+ fragment="NumPy_Fragments")
+ (DATA_TYPE* IN_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3)
+ (PyArrayObject* array=NULL, int is_new_object=0)
+{
+ npy_intp size[3] = { -1, -1, -1 };
+ array = obj_to_array_fortran_allow_conversion($input, DATA_TYPECODE,
+ &is_new_object);
+ if (!array || !require_dimensions(array, 3) ||
+ !require_size(array, size, 3) | !require_fortran(array)) SWIG_fail;
+ $1 = (DATA_TYPE*) array_data(array);
+ $2 = (DIM_TYPE) array_size(array,0);
+ $3 = (DIM_TYPE) array_size(array,1);
+ $4 = (DIM_TYPE) array_size(array,2);
+}
+%typemap(freearg)
+ (DATA_TYPE* IN_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3)
+{
+ if (is_new_object$argnum && array$argnum)
+ { Py_DECREF(array$argnum); }
+}
+
+/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3,
+ * DATA_TYPE* IN_FARRAY3)
+ */
+%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY,
+ fragment="NumPy_Macros")
+ (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_FARRAY3)
+{
+ $1 = is_array($input) || PySequence_Check($input);
+}
+%typemap(in,
+ fragment="NumPy_Fragments")
+ (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_FARRAY3)
+ (PyArrayObject* array=NULL, int is_new_object=0)
+{
+ npy_intp size[3] = { -1, -1, -1 };
+ array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE,
+ &is_new_object);
+ if (!array || !require_dimensions(array, 3) ||
+ !require_size(array, size, 3) || !require_fortran(array)) SWIG_fail;
+ $1 = (DIM_TYPE) array_size(array,0);
+ $2 = (DIM_TYPE) array_size(array,1);
+ $3 = (DIM_TYPE) array_size(array,2);
+ $4 = (DATA_TYPE*) array_data(array);
+}
+%typemap(freearg)
+ (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_FARRAY3)
+{
+ if (is_new_object$argnum && array$argnum)
+ { Py_DECREF(array$argnum); }
+}
+
+/***************************/
+/* In-Place Array Typemaps */
+/***************************/
+
+/* Typemap suite for (DATA_TYPE INPLACE_ARRAY1[ANY])
+ */
+%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY,
+ fragment="NumPy_Macros")
+ (DATA_TYPE INPLACE_ARRAY1[ANY])
+{
+ $1 = is_array($input) && PyArray_EquivTypenums(array_type($input),
+ DATA_TYPECODE);
+}
+%typemap(in,
+ fragment="NumPy_Fragments")
+ (DATA_TYPE INPLACE_ARRAY1[ANY])
+ (PyArrayObject* array=NULL)
+{
+ npy_intp size[1] = { $1_dim0 };
+ array = obj_to_array_no_conversion($input, DATA_TYPECODE);
+ if (!array || !require_dimensions(array,1) || !require_size(array, size, 1) ||
+ !require_contiguous(array) || !require_native(array)) SWIG_fail;
+ $1 = ($1_ltype) array_data(array);
+}
+
+/* Typemap suite for (DATA_TYPE* INPLACE_ARRAY1, DIM_TYPE DIM1)
+ */
+%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY,
+ fragment="NumPy_Macros")
+ (DATA_TYPE* INPLACE_ARRAY1, DIM_TYPE DIM1)
+{
+ $1 = is_array($input) && PyArray_EquivTypenums(array_type($input),
+ DATA_TYPECODE);
+}
+%typemap(in,
+ fragment="NumPy_Fragments")
+ (DATA_TYPE* INPLACE_ARRAY1, DIM_TYPE DIM1)
+ (PyArrayObject* array=NULL, int i=1)
+{
+ array = obj_to_array_no_conversion($input, DATA_TYPECODE);
+ if (!array || !require_dimensions(array,1) || !require_contiguous(array)
+ || !require_native(array)) SWIG_fail;
+ $1 = (DATA_TYPE*) array_data(array);
+ $2 = 1;
+ for (i=0; i < array_numdims(array); ++i) $2 *= array_size(array,i);
+}
+
+/* Typemap suite for (DIM_TYPE DIM1, DATA_TYPE* INPLACE_ARRAY1)
+ */
+%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY,
+ fragment="NumPy_Macros")
+ (DIM_TYPE DIM1, DATA_TYPE* INPLACE_ARRAY1)
+{
+ $1 = is_array($input) && PyArray_EquivTypenums(array_type($input),
+ DATA_TYPECODE);
+}
+%typemap(in,
+ fragment="NumPy_Fragments")
+ (DIM_TYPE DIM1, DATA_TYPE* INPLACE_ARRAY1)
+ (PyArrayObject* array=NULL, int i=0)
+{
+ array = obj_to_array_no_conversion($input, DATA_TYPECODE);
+ if (!array || !require_dimensions(array,1) || !require_contiguous(array)
+ || !require_native(array)) SWIG_fail;
+ $1 = 1;
+ for (i=0; i < array_numdims(array); ++i) $1 *= array_size(array,i);
+ $2 = (DATA_TYPE*) array_data(array);
+}
+
+/* Typemap suite for (DATA_TYPE INPLACE_ARRAY2[ANY][ANY])
+ */
+%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY,
+ fragment="NumPy_Macros")
+ (DATA_TYPE INPLACE_ARRAY2[ANY][ANY])
+{
+ $1 = is_array($input) && PyArray_EquivTypenums(array_type($input),
+ DATA_TYPECODE);
+}
+%typemap(in,
+ fragment="NumPy_Fragments")
+ (DATA_TYPE INPLACE_ARRAY2[ANY][ANY])
+ (PyArrayObject* array=NULL)
+{
+ npy_intp size[2] = { $1_dim0, $1_dim1 };
+ array = obj_to_array_no_conversion($input, DATA_TYPECODE);
+ if (!array || !require_dimensions(array,2) || !require_size(array, size, 2) ||
+ !require_contiguous(array) || !require_native(array)) SWIG_fail;
+ $1 = ($1_ltype) array_data(array);
+}
+
+/* Typemap suite for (DATA_TYPE* INPLACE_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2)
+ */
+%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY,
+ fragment="NumPy_Macros")
+ (DATA_TYPE* INPLACE_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2)
+{
+ $1 = is_array($input) && PyArray_EquivTypenums(array_type($input),
+ DATA_TYPECODE);
+}
+%typemap(in,
+ fragment="NumPy_Fragments")
+ (DATA_TYPE* INPLACE_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2)
+ (PyArrayObject* array=NULL)
+{
+ array = obj_to_array_no_conversion($input, DATA_TYPECODE);
+ if (!array || !require_dimensions(array,2) || !require_contiguous(array)
+ || !require_native(array)) SWIG_fail;
+ $1 = (DATA_TYPE*) array_data(array);
+ $2 = (DIM_TYPE) array_size(array,0);
+ $3 = (DIM_TYPE) array_size(array,1);
+}
+
+/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_ARRAY2)
+ */
+%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY,
+ fragment="NumPy_Macros")
+ (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_ARRAY2)
+{
+ $1 = is_array($input) && PyArray_EquivTypenums(array_type($input),
+ DATA_TYPECODE);
+}
+%typemap(in,
+ fragment="NumPy_Fragments")
+ (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_ARRAY2)
+ (PyArrayObject* array=NULL)
+{
+ array = obj_to_array_no_conversion($input, DATA_TYPECODE);
+ if (!array || !require_dimensions(array,2) || !require_contiguous(array) ||
+ !require_native(array)) SWIG_fail;
+ $1 = (DIM_TYPE) array_size(array,0);
+ $2 = (DIM_TYPE) array_size(array,1);
+ $3 = (DATA_TYPE*) array_data(array);
+}
+
+/* Typemap suite for (DATA_TYPE* INPLACE_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2)
+ */
+%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY,
+ fragment="NumPy_Macros")
+ (DATA_TYPE* INPLACE_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2)
+{
+ $1 = is_array($input) && PyArray_EquivTypenums(array_type($input),
+ DATA_TYPECODE);
+}
+%typemap(in,
+ fragment="NumPy_Fragments")
+ (DATA_TYPE* INPLACE_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2)
+ (PyArrayObject* array=NULL)
+{
+ array = obj_to_array_no_conversion($input, DATA_TYPECODE);
+ if (!array || !require_dimensions(array,2) || !require_contiguous(array)
+ || !require_native(array) || !require_fortran(array)) SWIG_fail;
+ $1 = (DATA_TYPE*) array_data(array);
+ $2 = (DIM_TYPE) array_size(array,0);
+ $3 = (DIM_TYPE) array_size(array,1);
+}
+
+/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_FARRAY2)
+ */
+%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY,
+ fragment="NumPy_Macros")
+ (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_FARRAY2)
+{
+ $1 = is_array($input) && PyArray_EquivTypenums(array_type($input),
+ DATA_TYPECODE);
+}
+%typemap(in,
+ fragment="NumPy_Fragments")
+ (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_FARRAY2)
+ (PyArrayObject* array=NULL)
+{
+ array = obj_to_array_no_conversion($input, DATA_TYPECODE);
+ if (!array || !require_dimensions(array,2) || !require_contiguous(array) ||
+ !require_native(array) || !require_fortran(array)) SWIG_fail;
+ $1 = (DIM_TYPE) array_size(array,0);
+ $2 = (DIM_TYPE) array_size(array,1);
+ $3 = (DATA_TYPE*) array_data(array);
+}
+
+/* Typemap suite for (DATA_TYPE INPLACE_ARRAY3[ANY][ANY][ANY])
+ */
+%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY,
+ fragment="NumPy_Macros")
+ (DATA_TYPE INPLACE_ARRAY3[ANY][ANY][ANY])
+{
+ $1 = is_array($input) && PyArray_EquivTypenums(array_type($input),
+ DATA_TYPECODE);
+}
+%typemap(in,
+ fragment="NumPy_Fragments")
+ (DATA_TYPE INPLACE_ARRAY3[ANY][ANY][ANY])
+ (PyArrayObject* array=NULL)
+{
+ npy_intp size[3] = { $1_dim0, $1_dim1, $1_dim2 };
+ array = obj_to_array_no_conversion($input, DATA_TYPECODE);
+ if (!array || !require_dimensions(array,3) || !require_size(array, size, 3) ||
+ !require_contiguous(array) || !require_native(array)) SWIG_fail;
+ $1 = ($1_ltype) array_data(array);
+}
+
+/* Typemap suite for (DATA_TYPE* INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2,
+ * DIM_TYPE DIM3)
+ */
+%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY,
+ fragment="NumPy_Macros")
+ (DATA_TYPE* INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3)
+{
+ $1 = is_array($input) && PyArray_EquivTypenums(array_type($input),
+ DATA_TYPECODE);
+}
+%typemap(in,
+ fragment="NumPy_Fragments")
+ (DATA_TYPE* INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3)
+ (PyArrayObject* array=NULL)
+{
+ array = obj_to_array_no_conversion($input, DATA_TYPECODE);
+ if (!array || !require_dimensions(array,3) || !require_contiguous(array) ||
+ !require_native(array)) SWIG_fail;
+ $1 = (DATA_TYPE*) array_data(array);
+ $2 = (DIM_TYPE) array_size(array,0);
+ $3 = (DIM_TYPE) array_size(array,1);
+ $4 = (DIM_TYPE) array_size(array,2);
+}
+
+/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3,
+ * DATA_TYPE* INPLACE_ARRAY3)
+ */
+%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY,
+ fragment="NumPy_Macros")
+ (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_ARRAY3)
+{
+ $1 = is_array($input) && PyArray_EquivTypenums(array_type($input),
+ DATA_TYPECODE);
+}
+%typemap(in,
+ fragment="NumPy_Fragments")
+ (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_ARRAY3)
+ (PyArrayObject* array=NULL)
+{
+ array = obj_to_array_no_conversion($input, DATA_TYPECODE);
+ if (!array || !require_dimensions(array,3) || !require_contiguous(array)
+ || !require_native(array)) SWIG_fail;
+ $1 = (DIM_TYPE) array_size(array,0);
+ $2 = (DIM_TYPE) array_size(array,1);
+ $3 = (DIM_TYPE) array_size(array,2);
+ $4 = (DATA_TYPE*) array_data(array);
+}
+
+/* Typemap suite for (DATA_TYPE* INPLACE_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2,
+ * DIM_TYPE DIM3)
+ */
+%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY,
+ fragment="NumPy_Macros")
+ (DATA_TYPE* INPLACE_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3)
+{
+ $1 = is_array($input) && PyArray_EquivTypenums(array_type($input),
+ DATA_TYPECODE);
+}
+%typemap(in,
+ fragment="NumPy_Fragments")
+ (DATA_TYPE* INPLACE_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3)
+ (PyArrayObject* array=NULL)
+{
+ array = obj_to_array_no_conversion($input, DATA_TYPECODE);
+ if (!array || !require_dimensions(array,3) || !require_contiguous(array) ||
+ !require_native(array) || !require_fortran(array)) SWIG_fail;
+ $1 = (DATA_TYPE*) array_data(array);
+ $2 = (DIM_TYPE) array_size(array,0);
+ $3 = (DIM_TYPE) array_size(array,1);
+ $4 = (DIM_TYPE) array_size(array,2);
+}
+
+/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3,
+ * DATA_TYPE* INPLACE_FARRAY3)
+ */
+%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY,
+ fragment="NumPy_Macros")
+ (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_FARRAY3)
+{
+ $1 = is_array($input) && PyArray_EquivTypenums(array_type($input),
+ DATA_TYPECODE);
+}
+%typemap(in,
+ fragment="NumPy_Fragments")
+ (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_FARRAY3)
+ (PyArrayObject* array=NULL)
+{
+ array = obj_to_array_no_conversion($input, DATA_TYPECODE);
+ if (!array || !require_dimensions(array,3) || !require_contiguous(array)
+ || !require_native(array) || !require_fortran(array)) SWIG_fail;
+ $1 = (DIM_TYPE) array_size(array,0);
+ $2 = (DIM_TYPE) array_size(array,1);
+ $3 = (DIM_TYPE) array_size(array,2);
+ $4 = (DATA_TYPE*) array_data(array);
+}
+
+/*************************/
+/* Argout Array Typemaps */
+/*************************/
+
+/* Typemap suite for (DATA_TYPE ARGOUT_ARRAY1[ANY])
+ */
+%typemap(in,numinputs=0,
+ fragment="NumPy_Backward_Compatibility,NumPy_Macros")
+ (DATA_TYPE ARGOUT_ARRAY1[ANY])
+ (PyObject * array = NULL)
+{
+ npy_intp dims[1] = { $1_dim0 };
+ array = PyArray_SimpleNew(1, dims, DATA_TYPECODE);
+ if (!array) SWIG_fail;
+ $1 = ($1_ltype) array_data(array);
+}
+%typemap(argout)
+ (DATA_TYPE ARGOUT_ARRAY1[ANY])
+{
+ $result = SWIG_Python_AppendOutput($result,array$argnum);
+}
+
+/* Typemap suite for (DATA_TYPE* ARGOUT_ARRAY1, DIM_TYPE DIM1)
+ */
+%typemap(in,numinputs=1,
+ fragment="NumPy_Fragments")
+ (DATA_TYPE* ARGOUT_ARRAY1, DIM_TYPE DIM1)
+ (PyObject * array = NULL)
+{
+ npy_intp dims[1];
+ if (!PyInt_Check($input))
+ {
+ char* typestring = pytype_string($input);
+ PyErr_Format(PyExc_TypeError,
+ "Int dimension expected. '%s' given.",
+ typestring);
+ SWIG_fail;
+ }
+ $2 = (DIM_TYPE) PyInt_AsLong($input);
+ dims[0] = (npy_intp) $2;
+ array = PyArray_SimpleNew(1, dims, DATA_TYPECODE);
+ if (!array) SWIG_fail;
+ $1 = (DATA_TYPE*) array_data(array);
+}
+%typemap(argout)
+ (DATA_TYPE* ARGOUT_ARRAY1, DIM_TYPE DIM1)
+{
+ $result = SWIG_Python_AppendOutput($result,array$argnum);
+}
+
+/* Typemap suite for (DIM_TYPE DIM1, DATA_TYPE* ARGOUT_ARRAY1)
+ */
+%typemap(in,numinputs=1,
+ fragment="NumPy_Fragments")
+ (DIM_TYPE DIM1, DATA_TYPE* ARGOUT_ARRAY1)
+ (PyObject * array = NULL)
+{
+ npy_intp dims[1];
+ if (!PyInt_Check($input))
+ {
+ char* typestring = pytype_string($input);
+ PyErr_Format(PyExc_TypeError,
+ "Int dimension expected. '%s' given.",
+ typestring);
+ SWIG_fail;
+ }
+ $1 = (DIM_TYPE) PyInt_AsLong($input);
+ dims[0] = (npy_intp) $1;
+ array = PyArray_SimpleNew(1, dims, DATA_TYPECODE);
+ if (!array) SWIG_fail;
+ $2 = (DATA_TYPE*) array_data(array);
+}
+%typemap(argout)
+ (DIM_TYPE DIM1, DATA_TYPE* ARGOUT_ARRAY1)
+{
+ $result = SWIG_Python_AppendOutput($result,array$argnum);
+}
+
+/* Typemap suite for (DATA_TYPE ARGOUT_ARRAY2[ANY][ANY])
+ */
+%typemap(in,numinputs=0,
+ fragment="NumPy_Backward_Compatibility,NumPy_Macros")
+ (DATA_TYPE ARGOUT_ARRAY2[ANY][ANY])
+ (PyObject * array = NULL)
+{
+ npy_intp dims[2] = { $1_dim0, $1_dim1 };
+ array = PyArray_SimpleNew(2, dims, DATA_TYPECODE);
+ if (!array) SWIG_fail;
+ $1 = ($1_ltype) array_data(array);
+}
+%typemap(argout)
+ (DATA_TYPE ARGOUT_ARRAY2[ANY][ANY])
+{
+ $result = SWIG_Python_AppendOutput($result,array$argnum);
+}
+
+/* Typemap suite for (DATA_TYPE ARGOUT_ARRAY3[ANY][ANY][ANY])
+ */
+%typemap(in,numinputs=0,
+ fragment="NumPy_Backward_Compatibility,NumPy_Macros")
+ (DATA_TYPE ARGOUT_ARRAY3[ANY][ANY][ANY])
+ (PyObject * array = NULL)
+{
+ npy_intp dims[3] = { $1_dim0, $1_dim1, $1_dim2 };
+ array = PyArray_SimpleNew(3, dims, DATA_TYPECODE);
+ if (!array) SWIG_fail;
+ $1 = ($1_ltype) array_data(array);
+}
+%typemap(argout)
+ (DATA_TYPE ARGOUT_ARRAY3[ANY][ANY][ANY])
+{
+ $result = SWIG_Python_AppendOutput($result,array$argnum);
+}
+
+/*****************************/
+/* Argoutview Array Typemaps */
+/*****************************/
+
+/* Typemap suite for (DATA_TYPE** ARGOUTVIEW_ARRAY1, DIM_TYPE* DIM1)
+ */
+%typemap(in,numinputs=0)
+ (DATA_TYPE** ARGOUTVIEW_ARRAY1, DIM_TYPE* DIM1 )
+ (DATA_TYPE* data_temp , DIM_TYPE dim_temp)
+{
+ $1 = &data_temp;
+ $2 = &dim_temp;
+}
+%typemap(argout,
+ fragment="NumPy_Backward_Compatibility")
+ (DATA_TYPE** ARGOUTVIEW_ARRAY1, DIM_TYPE* DIM1)
+{
+ npy_intp dims[1] = { *$2 };
+ PyObject * array = PyArray_SimpleNewFromData(1, dims, DATA_TYPECODE, (void*)(*$1));
+ if (!array) SWIG_fail;
+ $result = SWIG_Python_AppendOutput($result,array);
+}
+
+/* Typemap suite for (DIM_TYPE* DIM1, DATA_TYPE** ARGOUTVIEW_ARRAY1)
+ */
+%typemap(in,numinputs=0)
+ (DIM_TYPE* DIM1 , DATA_TYPE** ARGOUTVIEW_ARRAY1)
+ (DIM_TYPE dim_temp, DATA_TYPE* data_temp )
+{
+ $1 = &dim_temp;
+ $2 = &data_temp;
+}
+%typemap(argout,
+ fragment="NumPy_Backward_Compatibility")
+ (DIM_TYPE* DIM1, DATA_TYPE** ARGOUTVIEW_ARRAY1)
+{
+ npy_intp dims[1] = { *$1 };
+ PyObject * array = PyArray_SimpleNewFromData(1, dims, DATA_TYPECODE, (void*)(*$2));
+ if (!array) SWIG_fail;
+ $result = SWIG_Python_AppendOutput($result,array);
+}
+
+/* Typemap suite for (DATA_TYPE** ARGOUTVIEW_ARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2)
+ */
+%typemap(in,numinputs=0)
+ (DATA_TYPE** ARGOUTVIEW_ARRAY2, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 )
+ (DATA_TYPE* data_temp , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp)
+{
+ $1 = &data_temp;
+ $2 = &dim1_temp;
+ $3 = &dim2_temp;
+}
+%typemap(argout,
+ fragment="NumPy_Backward_Compatibility")
+ (DATA_TYPE** ARGOUTVIEW_ARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2)
+{
+ npy_intp dims[2] = { *$2, *$3 };
+ PyObject * array = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$1));
+ if (!array) SWIG_fail;
+ $result = SWIG_Python_AppendOutput($result,array);
+}
+
+/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_ARRAY2)
+ */
+%typemap(in,numinputs=0)
+ (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DATA_TYPE** ARGOUTVIEW_ARRAY2)
+ (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DATA_TYPE* data_temp )
+{
+ $1 = &dim1_temp;
+ $2 = &dim2_temp;
+ $3 = &data_temp;
+}
+%typemap(argout,
+ fragment="NumPy_Backward_Compatibility")
+ (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_ARRAY2)
+{
+ npy_intp dims[2] = { *$1, *$2 };
+ PyObject * array = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$3));
+ if (!array) SWIG_fail;
+ $result = SWIG_Python_AppendOutput($result,array);
+}
+
+/* Typemap suite for (DATA_TYPE** ARGOUTVIEW_FARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2)
+ */
+%typemap(in,numinputs=0)
+ (DATA_TYPE** ARGOUTVIEW_FARRAY2, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 )
+ (DATA_TYPE* data_temp , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp)
+{
+ $1 = &data_temp;
+ $2 = &dim1_temp;
+ $3 = &dim2_temp;
+}
+%typemap(argout,
+ fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements")
+ (DATA_TYPE** ARGOUTVIEW_FARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2)
+{
+ npy_intp dims[2] = { *$2, *$3 };
+ PyObject * obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$1));
+ PyArrayObject * array = (PyArrayObject*) obj;
+ if (!array || !require_fortran(array)) SWIG_fail;
+ $result = SWIG_Python_AppendOutput($result,obj);
+}
+
+/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_FARRAY2)
+ */
+%typemap(in,numinputs=0)
+ (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DATA_TYPE** ARGOUTVIEW_FARRAY2)
+ (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DATA_TYPE* data_temp )
+{
+ $1 = &dim1_temp;
+ $2 = &dim2_temp;
+ $3 = &data_temp;
+}
+%typemap(argout,
+ fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements")
+ (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_FARRAY2)
+{
+ npy_intp dims[2] = { *$1, *$2 };
+ PyObject * obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$3));
+ PyArrayObject * array = (PyArrayObject*) obj;
+ if (!array || !require_fortran(array)) SWIG_fail;
+ $result = SWIG_Python_AppendOutput($result,obj);
+}
+
+/* Typemap suite for (DATA_TYPE** ARGOUTVIEW_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2,
+ DIM_TYPE* DIM3)
+ */
+%typemap(in,numinputs=0)
+ (DATA_TYPE** ARGOUTVIEW_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3)
+ (DATA_TYPE* data_temp, DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp)
+{
+ $1 = &data_temp;
+ $2 = &dim1_temp;
+ $3 = &dim2_temp;
+ $4 = &dim3_temp;
+}
+%typemap(argout,
+ fragment="NumPy_Backward_Compatibility")
+ (DATA_TYPE** ARGOUTVIEW_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3)
+{
+ npy_intp dims[3] = { *$2, *$3, *$4 };
+ PyObject * array = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$1));
+ if (!array) SWIG_fail;
+ $result = SWIG_Python_AppendOutput($result,array);
+}
+
+/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3,
+ DATA_TYPE** ARGOUTVIEW_ARRAY3)
+ */
+%typemap(in,numinputs=0)
+ (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_ARRAY3)
+ (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DATA_TYPE* data_temp)
+{
+ $1 = &dim1_temp;
+ $2 = &dim2_temp;
+ $3 = &dim3_temp;
+ $4 = &data_temp;
+}
+%typemap(argout,
+ fragment="NumPy_Backward_Compatibility")
+ (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_ARRAY3)
+{
+ npy_intp dims[3] = { *$1, *$2, *$3 };
+ PyObject * array = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$3));
+ if (!array) SWIG_fail;
+ $result = SWIG_Python_AppendOutput($result,array);
+}
+
+/* Typemap suite for (DATA_TYPE** ARGOUTVIEW_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2,
+ DIM_TYPE* DIM3)
+ */
+%typemap(in,numinputs=0)
+ (DATA_TYPE** ARGOUTVIEW_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3)
+ (DATA_TYPE* data_temp, DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp)
+{
+ $1 = &data_temp;
+ $2 = &dim1_temp;
+ $3 = &dim2_temp;
+ $4 = &dim3_temp;
+}
+%typemap(argout,
+ fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements")
+ (DATA_TYPE** ARGOUTVIEW_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3)
+{
+ npy_intp dims[3] = { *$2, *$3, *$4 };
+ PyObject * obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$1));
+ PyArrayObject * array = (PyArrayObject*) obj;
+ if (!array || require_fortran(array)) SWIG_fail;
+ $result = SWIG_Python_AppendOutput($result,obj);
+}
+
+/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3,
+ DATA_TYPE** ARGOUTVIEW_FARRAY3)
+ */
+%typemap(in,numinputs=0)
+ (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_FARRAY3)
+ (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DATA_TYPE* data_temp)
+{
+ $1 = &dim1_temp;
+ $2 = &dim2_temp;
+ $3 = &dim3_temp;
+ $4 = &data_temp;
+}
+%typemap(argout,
+ fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements")
+ (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_FARRAY3)
+{
+ npy_intp dims[3] = { *$1, *$2, *$3 };
+ PyObject * obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$3));
+ PyArrayObject * array = (PyArrayObject*) obj;
+ if (!array || require_fortran(array)) SWIG_fail;
+ $result = SWIG_Python_AppendOutput($result,obj);
+}
+
+%enddef /* %numpy_typemaps() macro */
+/* *************************************************************** */
+
+/* Concrete instances of the %numpy_typemaps() macro: Each invocation
+ * below applies all of the typemaps above to the specified data type.
+ */
+%numpy_typemaps(signed char , NPY_BYTE , int)
+%numpy_typemaps(unsigned char , NPY_UBYTE , int)
+%numpy_typemaps(short , NPY_SHORT , int)
+%numpy_typemaps(unsigned short , NPY_USHORT , int)
+%numpy_typemaps(int , NPY_INT , int)
+%numpy_typemaps(unsigned int , NPY_UINT , int)
+%numpy_typemaps(long , NPY_LONG , int)
+%numpy_typemaps(unsigned long , NPY_ULONG , int)
+%numpy_typemaps(long long , NPY_LONGLONG , int)
+%numpy_typemaps(unsigned long long, NPY_ULONGLONG, int)
+%numpy_typemaps(float , NPY_FLOAT , int)
+%numpy_typemaps(double , NPY_DOUBLE , int)
+
+/* ***************************************************************
+ * The follow macro expansion does not work, because C++ bool is 4
+ * bytes and NPY_BOOL is 1 byte
+ *
+ * %numpy_typemaps(bool, NPY_BOOL, int)
+ */
+
+/* ***************************************************************
+ * On my Mac, I get the following warning for this macro expansion:
+ * 'swig/python detected a memory leak of type 'long double *', no destructor found.'
+ *
+ * %numpy_typemaps(long double, NPY_LONGDOUBLE, int)
+ */
+
+/* ***************************************************************
+ * Swig complains about a syntax error for the following macro
+ * expansions:
+ *
+ * %numpy_typemaps(complex float, NPY_CFLOAT , int)
+ *
+ * %numpy_typemaps(complex double, NPY_CDOUBLE, int)
+ *
+ * %numpy_typemaps(complex long double, NPY_CLONGDOUBLE, int)
+ */
+
+#endif /* SWIGPYTHON */
diff --git a/doc/swig/pyfragments.swg b/doc/swig/pyfragments.swg
new file mode 100644
index 000000000..0deaa61e1
--- /dev/null
+++ b/doc/swig/pyfragments.swg
@@ -0,0 +1,174 @@
+/*-*- C -*-*/
+
+/**********************************************************************/
+
+/* For numpy versions prior to 1.0, the names of certain data types
+ * are different than in later versions. This fragment provides macro
+ * substitutions that allow us to support old and new versions of
+ * numpy.
+ */
+
+%fragment("NumPy_Backward_Compatibility", "header")
+{
+/* Support older NumPy data type names
+ */
+%#if NDARRAY_VERSION < 0x01000000
+%#define NPY_BOOL PyArray_BOOL
+%#define NPY_BYTE PyArray_BYTE
+%#define NPY_UBYTE PyArray_UBYTE
+%#define NPY_SHORT PyArray_SHORT
+%#define NPY_USHORT PyArray_USHORT
+%#define NPY_INT PyArray_INT
+%#define NPY_UINT PyArray_UINT
+%#define NPY_LONG PyArray_LONG
+%#define NPY_ULONG PyArray_ULONG
+%#define NPY_LONGLONG PyArray_LONGLONG
+%#define NPY_ULONGLONG PyArray_ULONGLONG
+%#define NPY_FLOAT PyArray_FLOAT
+%#define NPY_DOUBLE PyArray_DOUBLE
+%#define NPY_LONGDOUBLE PyArray_LONGDOUBLE
+%#define NPY_CFLOAT PyArray_CFLOAT
+%#define NPY_CDOUBLE PyArray_CDOUBLE
+%#define NPY_CLONGDOUBLE PyArray_CLONGDOUBLE
+%#define NPY_OBJECT PyArray_OBJECT
+%#define NPY_STRING PyArray_STRING
+%#define NPY_UNICODE PyArray_UNICODE
+%#define NPY_VOID PyArray_VOID
+%#define NPY_NTYPES PyArray_NTYPES
+%#define NPY_NOTYPE PyArray_NOTYPE
+%#define NPY_CHAR PyArray_CHAR
+%#define NPY_USERDEF PyArray_USERDEF
+%#define npy_intp intp
+
+%#define NPY_MAX_BYTE MAX_BYTE
+%#define NPY_MIN_BYTE MIN_BYTE
+%#define NPY_MAX_UBYTE MAX_UBYTE
+%#define NPY_MAX_SHORT MAX_SHORT
+%#define NPY_MIN_SHORT MIN_SHORT
+%#define NPY_MAX_USHORT MAX_USHORT
+%#define NPY_MAX_INT MAX_INT
+%#define NPY_MIN_INT MIN_INT
+%#define NPY_MAX_UINT MAX_UINT
+%#define NPY_MAX_LONG MAX_LONG
+%#define NPY_MIN_LONG MIN_LONG
+%#define NPY_MAX_ULONG MAX_ULONG
+%#define NPY_MAX_LONGLONG MAX_LONGLONG
+%#define NPY_MIN_LONGLONG MIN_LONGLONG
+%#define NPY_MAX_ULONGLONG MAX_ULONGLONG
+%#define NPY_MAX_INTP MAX_INTP
+%#define NPY_MIN_INTP MIN_INTP
+
+%#define NPY_FARRAY FARRAY
+%#define NPY_F_CONTIGUOUS F_CONTIGUOUS
+%#endif
+}
+
+/**********************************************************************/
+
+/* Override the SWIG_AsVal_frag(long) fragment so that it also checks
+ * for numpy scalar array types. The code through the %#endif is
+ * essentially cut-and-paste from pyprimtype.swg
+ */
+
+%fragment(SWIG_AsVal_frag(long), "header",
+ fragment="SWIG_CanCastAsInteger",
+ fragment="NumPy_Backward_Compatibility")
+{
+ SWIGINTERN int
+ SWIG_AsVal_dec(long)(PyObject * obj, long * val)
+ {
+ static PyArray_Descr * longDescr = PyArray_DescrNewFromType(NPY_LONG);
+ if (PyInt_Check(obj)) {
+ if (val) *val = PyInt_AsLong(obj);
+ return SWIG_OK;
+ } else if (PyLong_Check(obj)) {
+ long v = PyLong_AsLong(obj);
+ if (!PyErr_Occurred()) {
+ if (val) *val = v;
+ return SWIG_OK;
+ } else {
+ PyErr_Clear();
+ }
+ }
+%#ifdef SWIG_PYTHON_CAST_MODE
+ {
+ int dispatch = 0;
+ long v = PyInt_AsLong(obj);
+ if (!PyErr_Occurred()) {
+ if (val) *val = v;
+ return SWIG_AddCast(SWIG_OK);
+ } else {
+ PyErr_Clear();
+ }
+ if (!dispatch) {
+ double d;
+ int res = SWIG_AddCast(SWIG_AsVal(double)(obj,&d));
+ if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, LONG_MIN, LONG_MAX)) {
+ if (val) *val = (long)(d);
+ return res;
+ }
+ }
+ }
+%#endif
+ if (!PyArray_IsScalar(obj,Integer)) return SWIG_TypeError;
+ PyArray_CastScalarToCtype(obj, (void*)val, longDescr);
+ return SWIG_OK;
+ }
+}
+
+
+/* Override the SWIG_AsVal_frag(unsigned long) fragment so that it
+ * also checks for numpy scalar array types. The code through the
+ * %#endif is essentially cut-and-paste from pyprimtype.swg
+ */
+
+%fragment(SWIG_AsVal_frag(unsigned long),"header",
+ fragment="SWIG_CanCastAsInteger",
+ fragment="NumPy_Backward_Compatibility")
+{
+ SWIGINTERN int
+ SWIG_AsVal_dec(unsigned long)(PyObject *obj, unsigned long *val)
+ {
+ static PyArray_Descr * ulongDescr = PyArray_DescrNewFromType(NPY_ULONG);
+ if (PyInt_Check(obj)) {
+ long v = PyInt_AsLong(obj);
+ if (v >= 0) {
+ if (val) *val = v;
+ return SWIG_OK;
+ } else {
+ return SWIG_OverflowError;
+ }
+ } else if (PyLong_Check(obj)) {
+ unsigned long v = PyLong_AsUnsignedLong(obj);
+ if (!PyErr_Occurred()) {
+ if (val) *val = v;
+ return SWIG_OK;
+ } else {
+ PyErr_Clear();
+ }
+ }
+%#ifdef SWIG_PYTHON_CAST_MODE
+ {
+ int dispatch = 0;
+ unsigned long v = PyLong_AsUnsignedLong(obj);
+ if (!PyErr_Occurred()) {
+ if (val) *val = v;
+ return SWIG_AddCast(SWIG_OK);
+ } else {
+ PyErr_Clear();
+ }
+ if (!dispatch) {
+ double d;
+ int res = SWIG_AddCast(SWIG_AsVal(double)(obj,&d));
+ if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, 0, ULONG_MAX)) {
+ if (val) *val = (unsigned long)(d);
+ return res;
+ }
+ }
+ }
+%#endif
+ if (!PyArray_IsScalar(obj,Integer)) return SWIG_TypeError;
+ PyArray_CastScalarToCtype(obj, (void*)val, ulongDescr);
+ return SWIG_OK;
+ }
+}
diff --git a/doc/swig/test/Array.i b/doc/swig/test/Array.i
new file mode 100644
index 000000000..d56dd2d1c
--- /dev/null
+++ b/doc/swig/test/Array.i
@@ -0,0 +1,107 @@
+// -*- c++ -*-
+
+%module Array
+
+%{
+#define SWIG_FILE_WITH_INIT
+#include "Array1.h"
+#include "Array2.h"
+%}
+
+// Get the NumPy typemaps
+%include "../numpy.i"
+
+ // Get the STL typemaps
+%include "stl.i"
+
+// Handle standard exceptions
+%include "exception.i"
+%exception
+{
+ try
+ {
+ $action
+ }
+ catch (const std::invalid_argument& e)
+ {
+ SWIG_exception(SWIG_ValueError, e.what());
+ }
+ catch (const std::out_of_range& e)
+ {
+ SWIG_exception(SWIG_IndexError, e.what());
+ }
+}
+%init %{
+ import_array();
+%}
+
+// Global ignores
+%ignore *::operator=;
+%ignore *::operator[];
+
+// Apply the 1D NumPy typemaps
+%apply (int DIM1 , long* INPLACE_ARRAY1)
+ {(int length, long* data )};
+%apply (long** ARGOUTVIEW_ARRAY1, int* DIM1 )
+ {(long** data , int* length)};
+
+// Apply the 2D NumPy typemaps
+%apply (int DIM1 , int DIM2 , long* INPLACE_ARRAY2)
+ {(int nrows, int ncols, long* data )};
+%apply (int* DIM1 , int* DIM2 , long** ARGOUTVIEW_ARRAY2)
+ {(int* nrows, int* ncols, long** data )};
+// Note: the %apply for INPLACE_ARRAY2 above gets successfully applied
+// to the constructor Array2(int nrows, int ncols, long* data), but
+// does not get applied to the method Array2::resize(int nrows, int
+// ncols, long* data). I have no idea why. For this reason the test
+// for Apply2.resize(numpy.ndarray) in testArray.py is commented out.
+
+// Array1 support
+%include "Array1.h"
+%extend Array1
+{
+ void __setitem__(int i, long v)
+ {
+ self->operator[](i) = v;
+ }
+
+ long __getitem__(int i)
+ {
+ return self->operator[](i);
+ }
+
+ int __len__()
+ {
+ return self->length();
+ }
+
+ std::string __str__()
+ {
+ return self->asString();
+ }
+}
+
+// Array2 support
+%include "Array2.h"
+%extend Array2
+{
+ void __setitem__(int i, Array1 & v)
+ {
+ self->operator[](i) = v;
+ }
+
+ Array1 & __getitem__(int i)
+ {
+ return self->operator[](i);
+ }
+
+ int __len__()
+ {
+ return self->nrows() * self->ncols();
+ }
+
+ std::string __str__()
+ {
+ return self->asString();
+ }
+}
diff --git a/doc/swig/test/Array1.cxx b/doc/swig/test/Array1.cxx
new file mode 100644
index 000000000..0c09e02f9
--- /dev/null
+++ b/doc/swig/test/Array1.cxx
@@ -0,0 +1,131 @@
+#include "Array1.h"
+#include <iostream>
+#include <sstream>
+
+// Default/length/array constructor
+Array1::Array1(int length, long* data) :
+ _ownData(false), _length(0), _buffer(0)
+{
+ resize(length, data);
+}
+
+// Copy constructor
+Array1::Array1(const Array1 & source) :
+ _length(source._length)
+{
+ allocateMemory();
+ *this = source;
+}
+
+// Destructor
+Array1::~Array1()
+{
+ deallocateMemory();
+}
+
+// Assignment operator
+Array1 & Array1::operator=(const Array1 & source)
+{
+ int len = _length < source._length ? _length : source._length;
+ for (int i=0; i < len; ++i)
+ {
+ (*this)[i] = source[i];
+ }
+ return *this;
+}
+
+// Equals operator
+bool Array1::operator==(const Array1 & other) const
+{
+ if (_length != other._length) return false;
+ for (int i=0; i < _length; ++i)
+ {
+ if ((*this)[i] != other[i]) return false;
+ }
+ return true;
+}
+
+// Length accessor
+int Array1::length() const
+{
+ return _length;
+}
+
+// Resize array
+void Array1::resize(int length, long* data)
+{
+ if (length < 0) throw std::invalid_argument("Array1 length less than 0");
+ if (length == _length) return;
+ deallocateMemory();
+ _length = length;
+ if (!data)
+ {
+ allocateMemory();
+ }
+ else
+ {
+ _ownData = false;
+ _buffer = data;
+ }
+}
+
+// Set item accessor
+long & Array1::operator[](int i)
+{
+ if (i < 0 || i >= _length) throw std::out_of_range("Array1 index out of range");
+ return _buffer[i];
+}
+
+// Get item accessor
+const long & Array1::operator[](int i) const
+{
+ if (i < 0 || i >= _length) throw std::out_of_range("Array1 index out of range");
+ return _buffer[i];
+}
+
+// String output
+std::string Array1::asString() const
+{
+ std::stringstream result;
+ result << "[";
+ for (int i=0; i < _length; ++i)
+ {
+ result << " " << _buffer[i];
+ if (i < _length-1) result << ",";
+ }
+ result << " ]";
+ return result.str();
+}
+
+// Get view
+void Array1::view(long** data, int* length) const
+{
+ *data = _buffer;
+ *length = _length;
+}
+
+// Private methods
+ void Array1::allocateMemory()
+ {
+ if (_length == 0)
+ {
+ _ownData = false;
+ _buffer = 0;
+ }
+ else
+ {
+ _ownData = true;
+ _buffer = new long[_length];
+ }
+ }
+
+ void Array1::deallocateMemory()
+ {
+ if (_ownData && _length && _buffer)
+ {
+ delete [] _buffer;
+ }
+ _ownData = false;
+ _length = 0;
+ _buffer = 0;
+ }
diff --git a/doc/swig/test/Array1.h b/doc/swig/test/Array1.h
new file mode 100644
index 000000000..754c248fc
--- /dev/null
+++ b/doc/swig/test/Array1.h
@@ -0,0 +1,55 @@
+#ifndef ARRAY1_H
+#define ARRAY1_H
+
+#include <stdexcept>
+#include <string>
+
+class Array1
+{
+public:
+
+ // Default/length/array constructor
+ Array1(int length = 0, long* data = 0);
+
+ // Copy constructor
+ Array1(const Array1 & source);
+
+ // Destructor
+ ~Array1();
+
+ // Assignment operator
+ Array1 & operator=(const Array1 & source);
+
+ // Equals operator
+ bool operator==(const Array1 & other) const;
+
+ // Length accessor
+ int length() const;
+
+ // Resize array
+ void resize(int length, long* data = 0);
+
+ // Set item accessor
+ long & operator[](int i);
+
+ // Get item accessor
+ const long & operator[](int i) const;
+
+ // String output
+ std::string asString() const;
+
+ // Get view
+ void view(long** data, int* length) const;
+
+private:
+ // Members
+ bool _ownData;
+ int _length;
+ long * _buffer;
+
+ // Methods
+ void allocateMemory();
+ void deallocateMemory();
+};
+
+#endif
diff --git a/doc/swig/test/Array2.cxx b/doc/swig/test/Array2.cxx
new file mode 100644
index 000000000..e3558f786
--- /dev/null
+++ b/doc/swig/test/Array2.cxx
@@ -0,0 +1,168 @@
+#include "Array2.h"
+#include <sstream>
+
+// Default constructor
+Array2::Array2() :
+ _ownData(false), _nrows(0), _ncols(), _buffer(0), _rows(0)
+{ }
+
+// Size/array constructor
+Array2::Array2(int nrows, int ncols, long* data) :
+ _ownData(false), _nrows(0), _ncols(), _buffer(0), _rows(0)
+{
+ resize(nrows, ncols, data);
+}
+
+// Copy constructor
+Array2::Array2(const Array2 & source) :
+ _nrows(source._nrows), _ncols(source._ncols)
+{
+ _ownData = true;
+ allocateMemory();
+ *this = source;
+}
+
+// Destructor
+Array2::~Array2()
+{
+ deallocateMemory();
+}
+
+// Assignment operator
+Array2 & Array2::operator=(const Array2 & source)
+{
+ int nrows = _nrows < source._nrows ? _nrows : source._nrows;
+ int ncols = _ncols < source._ncols ? _ncols : source._ncols;
+ for (int i=0; i < nrows; ++i)
+ {
+ for (int j=0; j < ncols; ++j)
+ {
+ (*this)[i][j] = source[i][j];
+ }
+ }
+ return *this;
+}
+
+// Equals operator
+bool Array2::operator==(const Array2 & other) const
+{
+ if (_nrows != other._nrows) return false;
+ if (_ncols != other._ncols) return false;
+ for (int i=0; i < _nrows; ++i)
+ {
+ for (int j=0; j < _ncols; ++j)
+ {
+ if ((*this)[i][j] != other[i][j]) return false;
+ }
+ }
+ return true;
+}
+
+// Length accessors
+int Array2::nrows() const
+{
+ return _nrows;
+}
+
+int Array2::ncols() const
+{
+ return _ncols;
+}
+
+// Resize array
+void Array2::resize(int nrows, int ncols, long* data)
+{
+ if (nrows < 0) throw std::invalid_argument("Array2 nrows less than 0");
+ if (ncols < 0) throw std::invalid_argument("Array2 ncols less than 0");
+ if (nrows == _nrows && ncols == _ncols) return;
+ deallocateMemory();
+ _nrows = nrows;
+ _ncols = ncols;
+ if (!data)
+ {
+ allocateMemory();
+ }
+ else
+ {
+ _ownData = false;
+ _buffer = data;
+ allocateRows();
+ }
+}
+
+// Set item accessor
+Array1 & Array2::operator[](int i)
+{
+ if (i < 0 || i > _nrows) throw std::out_of_range("Array2 row index out of range");
+ return _rows[i];
+}
+
+// Get item accessor
+const Array1 & Array2::operator[](int i) const
+{
+ if (i < 0 || i > _nrows) throw std::out_of_range("Array2 row index out of range");
+ return _rows[i];
+}
+
+// String output
+std::string Array2::asString() const
+{
+ std::stringstream result;
+ result << "[ ";
+ for (int i=0; i < _nrows; ++i)
+ {
+ if (i > 0) result << " ";
+ result << (*this)[i].asString();
+ if (i < _nrows-1) result << "," << std::endl;
+ }
+ result << " ]" << std::endl;
+ return result.str();
+}
+
+// Get view
+void Array2::view(int* nrows, int* ncols, long** data) const
+{
+ *nrows = _nrows;
+ *ncols = _ncols;
+ *data = _buffer;
+}
+
+// Private methods
+void Array2::allocateMemory()
+{
+ if (_nrows * _ncols == 0)
+ {
+ _ownData = false;
+ _buffer = 0;
+ _rows = 0;
+ }
+ else
+ {
+ _ownData = true;
+ _buffer = new long[_nrows*_ncols];
+ allocateRows();
+ }
+}
+
+void Array2::allocateRows()
+{
+ _rows = new Array1[_nrows];
+ for (int i=0; i < _nrows; ++i)
+ {
+ _rows[i].resize(_ncols, &_buffer[i*_ncols]);
+ }
+}
+
+void Array2::deallocateMemory()
+{
+ if (_ownData && _nrows*_ncols && _buffer)
+ {
+ delete [] _rows;
+ delete [] _buffer;
+ }
+ _ownData = false;
+ _nrows = 0;
+ _ncols = 0;
+ _buffer = 0;
+ _rows = 0;
+}
diff --git a/doc/swig/test/Array2.h b/doc/swig/test/Array2.h
new file mode 100644
index 000000000..a6e5bfc30
--- /dev/null
+++ b/doc/swig/test/Array2.h
@@ -0,0 +1,63 @@
+#ifndef ARRAY2_H
+#define ARRAY2_H
+
+#include "Array1.h"
+#include <stdexcept>
+#include <string>
+
+class Array2
+{
+public:
+
+ // Default constructor
+ Array2();
+
+ // Size/array constructor
+ Array2(int nrows, int ncols, long* data=0);
+
+ // Copy constructor
+ Array2(const Array2 & source);
+
+ // Destructor
+ ~Array2();
+
+ // Assignment operator
+ Array2 & operator=(const Array2 & source);
+
+ // Equals operator
+ bool operator==(const Array2 & other) const;
+
+ // Length accessors
+ int nrows() const;
+ int ncols() const;
+
+ // Resize array
+ void resize(int ncols, int nrows, long* data=0);
+
+ // Set item accessor
+ Array1 & operator[](int i);
+
+ // Get item accessor
+ const Array1 & operator[](int i) const;
+
+ // String output
+ std::string asString() const;
+
+ // Get view
+ void view(int* nrows, int* ncols, long** data) const;
+
+private:
+ // Members
+ bool _ownData;
+ int _nrows;
+ int _ncols;
+ long * _buffer;
+ Array1 * _rows;
+
+ // Methods
+ void allocateMemory();
+ void allocateRows();
+ void deallocateMemory();
+};
+
+#endif
diff --git a/doc/swig/test/Farray.cxx b/doc/swig/test/Farray.cxx
new file mode 100644
index 000000000..3983c333b
--- /dev/null
+++ b/doc/swig/test/Farray.cxx
@@ -0,0 +1,122 @@
+#include "Farray.h"
+#include <sstream>
+
+// Size constructor
+Farray::Farray(int nrows, int ncols) :
+ _nrows(nrows), _ncols(ncols), _buffer(0)
+{
+ allocateMemory();
+}
+
+// Copy constructor
+Farray::Farray(const Farray & source) :
+ _nrows(source._nrows), _ncols(source._ncols)
+{
+ allocateMemory();
+ *this = source;
+}
+
+// Destructor
+Farray::~Farray()
+{
+ delete [] _buffer;
+}
+
+// Assignment operator
+Farray & Farray::operator=(const Farray & source)
+{
+ int nrows = _nrows < source._nrows ? _nrows : source._nrows;
+ int ncols = _ncols < source._ncols ? _ncols : source._ncols;
+ for (int i=0; i < nrows; ++i)
+ {
+ for (int j=0; j < ncols; ++j)
+ {
+ (*this)(i,j) = source(i,j);
+ }
+ }
+ return *this;
+}
+
+// Equals operator
+bool Farray::operator==(const Farray & other) const
+{
+ if (_nrows != other._nrows) return false;
+ if (_ncols != other._ncols) return false;
+ for (int i=0; i < _nrows; ++i)
+ {
+ for (int j=0; j < _ncols; ++j)
+ {
+ if ((*this)(i,j) != other(i,j)) return false;
+ }
+ }
+ return true;
+}
+
+// Length accessors
+int Farray::nrows() const
+{
+ return _nrows;
+}
+
+int Farray::ncols() const
+{
+ return _ncols;
+}
+
+// Set item accessor
+long & Farray::operator()(int i, int j)
+{
+ if (i < 0 || i > _nrows) throw std::out_of_range("Farray row index out of range");
+ if (j < 0 || j > _ncols) throw std::out_of_range("Farray col index out of range");
+ return _buffer[offset(i,j)];
+}
+
+// Get item accessor
+const long & Farray::operator()(int i, int j) const
+{
+ if (i < 0 || i > _nrows) throw std::out_of_range("Farray row index out of range");
+ if (j < 0 || j > _ncols) throw std::out_of_range("Farray col index out of range");
+ return _buffer[offset(i,j)];
+}
+
+// String output
+std::string Farray::asString() const
+{
+ std::stringstream result;
+ result << "[ ";
+ for (int i=0; i < _nrows; ++i)
+ {
+ if (i > 0) result << " ";
+ result << "[";
+ for (int j=0; j < _ncols; ++j)
+ {
+ result << " " << (*this)(i,j);
+ if (j < _ncols-1) result << ",";
+ }
+ result << " ]";
+ if (i < _nrows-1) result << "," << std::endl;
+ }
+ result << " ]" << std::endl;
+ return result.str();
+}
+
+// Get view
+void Farray::view(int* nrows, int* ncols, long** data) const
+{
+ *nrows = _nrows;
+ *ncols = _ncols;
+ *data = _buffer;
+}
+
+// Private methods
+void Farray::allocateMemory()
+{
+ if (_nrows <= 0) throw std::invalid_argument("Farray nrows <= 0");
+ if (_ncols <= 0) throw std::invalid_argument("Farray ncols <= 0");
+ _buffer = new long[_nrows*_ncols];
+}
+
+inline int Farray::offset(int i, int j) const
+{
+ return i + j * _nrows;
+}
diff --git a/doc/swig/test/Farray.h b/doc/swig/test/Farray.h
new file mode 100644
index 000000000..4199a287c
--- /dev/null
+++ b/doc/swig/test/Farray.h
@@ -0,0 +1,56 @@
+#ifndef FARRAY_H
+#define FARRAY_H
+
+#include <stdexcept>
+#include <string>
+
+class Farray
+{
+public:
+
+ // Size constructor
+ Farray(int nrows, int ncols);
+
+ // Copy constructor
+ Farray(const Farray & source);
+
+ // Destructor
+ ~Farray();
+
+ // Assignment operator
+ Farray & operator=(const Farray & source);
+
+ // Equals operator
+ bool operator==(const Farray & other) const;
+
+ // Length accessors
+ int nrows() const;
+ int ncols() const;
+
+ // Set item accessor
+ long & operator()(int i, int j);
+
+ // Get item accessor
+ const long & operator()(int i, int j) const;
+
+ // String output
+ std::string asString() const;
+
+ // Get view
+ void view(int* nrows, int* ncols, long** data) const;
+
+private:
+ // Members
+ int _nrows;
+ int _ncols;
+ long * _buffer;
+
+ // Default constructor: not implemented
+ Farray();
+
+ // Methods
+ void allocateMemory();
+ int offset(int i, int j) const;
+};
+
+#endif
diff --git a/doc/swig/test/Farray.i b/doc/swig/test/Farray.i
new file mode 100644
index 000000000..25f6cd025
--- /dev/null
+++ b/doc/swig/test/Farray.i
@@ -0,0 +1,73 @@
+// -*- c++ -*-
+
+%module Farray
+
+%{
+#define SWIG_FILE_WITH_INIT
+#include "Farray.h"
+%}
+
+// Get the NumPy typemaps
+%include "../numpy.i"
+
+ // Get the STL typemaps
+%include "stl.i"
+
+// Handle standard exceptions
+%include "exception.i"
+%exception
+{
+ try
+ {
+ $action
+ }
+ catch (const std::invalid_argument& e)
+ {
+ SWIG_exception(SWIG_ValueError, e.what());
+ }
+ catch (const std::out_of_range& e)
+ {
+ SWIG_exception(SWIG_IndexError, e.what());
+ }
+}
+%init %{
+ import_array();
+%}
+
+// Global ignores
+%ignore *::operator=;
+%ignore *::operator();
+
+// Apply the 2D NumPy typemaps
+%apply (int* DIM1 , int* DIM2 , long** ARGOUTVIEW_FARRAY2)
+ {(int* nrows, int* ncols, long** data )};
+
+// Farray support
+%include "Farray.h"
+%extend Farray
+{
+ PyObject * __setitem__(PyObject* index, long v)
+ {
+ int i, j;
+ if (!PyArg_ParseTuple(index, "ii:Farray___setitem__",&i,&j)) return NULL;
+ self->operator()(i,j) = v;
+ return Py_BuildValue("");
+ }
+
+ PyObject * __getitem__(PyObject * index)
+ {
+ int i, j;
+ if (!PyArg_ParseTuple(index, "ii:Farray___getitem__",&i,&j)) return NULL;
+ return SWIG_From_long(self->operator()(i,j));
+ }
+
+ int __len__()
+ {
+ return self->nrows() * self->ncols();
+ }
+
+ std::string __str__()
+ {
+ return self->asString();
+ }
+}
diff --git a/doc/swig/test/Fortran.cxx b/doc/swig/test/Fortran.cxx
new file mode 100644
index 000000000..475d21ddc
--- /dev/null
+++ b/doc/swig/test/Fortran.cxx
@@ -0,0 +1,24 @@
+#include <stdlib.h>
+#include <math.h>
+#include <iostream>
+#include "Fortran.h"
+
+#define TEST_FUNCS(TYPE, SNAME) \
+\
+TYPE SNAME ## SecondElement(TYPE * matrix, int rows, int cols) { \
+ TYPE result = matrix[1]; \
+ return result; \
+} \
+
+TEST_FUNCS(signed char , schar )
+TEST_FUNCS(unsigned char , uchar )
+TEST_FUNCS(short , short )
+TEST_FUNCS(unsigned short , ushort )
+TEST_FUNCS(int , int )
+TEST_FUNCS(unsigned int , uint )
+TEST_FUNCS(long , long )
+TEST_FUNCS(unsigned long , ulong )
+TEST_FUNCS(long long , longLong )
+TEST_FUNCS(unsigned long long, ulongLong)
+TEST_FUNCS(float , float )
+TEST_FUNCS(double , double )
diff --git a/doc/swig/test/Fortran.h b/doc/swig/test/Fortran.h
new file mode 100644
index 000000000..c243bb50f
--- /dev/null
+++ b/doc/swig/test/Fortran.h
@@ -0,0 +1,21 @@
+#ifndef FORTRAN_H
+#define FORTRAN_H
+
+#define TEST_FUNC_PROTOS(TYPE, SNAME) \
+\
+TYPE SNAME ## SecondElement( TYPE * matrix, int rows, int cols); \
+
+TEST_FUNC_PROTOS(signed char , schar )
+TEST_FUNC_PROTOS(unsigned char , uchar )
+TEST_FUNC_PROTOS(short , short )
+TEST_FUNC_PROTOS(unsigned short , ushort )
+TEST_FUNC_PROTOS(int , int )
+TEST_FUNC_PROTOS(unsigned int , uint )
+TEST_FUNC_PROTOS(long , long )
+TEST_FUNC_PROTOS(unsigned long , ulong )
+TEST_FUNC_PROTOS(long long , longLong )
+TEST_FUNC_PROTOS(unsigned long long, ulongLong)
+TEST_FUNC_PROTOS(float , float )
+TEST_FUNC_PROTOS(double , double )
+
+#endif
diff --git a/doc/swig/test/Fortran.i b/doc/swig/test/Fortran.i
new file mode 100644
index 000000000..131790dd6
--- /dev/null
+++ b/doc/swig/test/Fortran.i
@@ -0,0 +1,36 @@
+// -*- c++ -*-
+%module Fortran
+
+%{
+#define SWIG_FILE_WITH_INIT
+#include "Fortran.h"
+%}
+
+// Get the NumPy typemaps
+%include "../numpy.i"
+
+%init %{
+ import_array();
+%}
+
+%define %apply_numpy_typemaps(TYPE)
+
+%apply (TYPE* IN_FARRAY2, int DIM1, int DIM2) {(TYPE* matrix, int rows, int cols)};
+
+%enddef /* %apply_numpy_typemaps() macro */
+
+%apply_numpy_typemaps(signed char )
+%apply_numpy_typemaps(unsigned char )
+%apply_numpy_typemaps(short )
+%apply_numpy_typemaps(unsigned short )
+%apply_numpy_typemaps(int )
+%apply_numpy_typemaps(unsigned int )
+%apply_numpy_typemaps(long )
+%apply_numpy_typemaps(unsigned long )
+%apply_numpy_typemaps(long long )
+%apply_numpy_typemaps(unsigned long long)
+%apply_numpy_typemaps(float )
+%apply_numpy_typemaps(double )
+
+// Include the header file to be wrapped
+%include "Fortran.h"
diff --git a/doc/swig/test/Makefile b/doc/swig/test/Makefile
new file mode 100644
index 000000000..5360b1ced
--- /dev/null
+++ b/doc/swig/test/Makefile
@@ -0,0 +1,34 @@
+# SWIG
+INTERFACES = Array.i Farray.i Vector.i Matrix.i Tensor.i Fortran.i
+WRAPPERS = $(INTERFACES:.i=_wrap.cxx)
+PROXIES = $(INTERFACES:.i=.py )
+
+# Default target: build the tests
+.PHONY : all
+all: $(WRAPPERS) Array1.cxx Array1.h Farray.cxx Farray.h Vector.cxx Vector.h \
+ Matrix.cxx Matrix.h Tensor.cxx Tensor.h Fortran.h Fortran.cxx
+ ./setup.py build_ext -i
+
+# Test target: run the tests
+.PHONY : test
+test: all
+ python testVector.py
+ python testMatrix.py
+ python testTensor.py
+ python testArray.py
+ python testFarray.py
+ python testFortran.py
+
+# Rule: %.i -> %_wrap.cxx
+%_wrap.cxx: %.i %.h ../numpy.i
+ swig -c++ -python $<
+%_wrap.cxx: %.i %1.h %2.h ../numpy.i
+ swig -c++ -python $<
+
+# Clean target
+.PHONY : clean
+clean:
+ $(RM) -r build
+ $(RM) *.so
+ $(RM) $(WRAPPERS)
+ $(RM) $(PROXIES)
diff --git a/doc/swig/test/Matrix.cxx b/doc/swig/test/Matrix.cxx
new file mode 100644
index 000000000..b953d7017
--- /dev/null
+++ b/doc/swig/test/Matrix.cxx
@@ -0,0 +1,112 @@
+#include <stdlib.h>
+#include <math.h>
+#include <iostream>
+#include "Matrix.h"
+
+// The following macro defines a family of functions that work with 2D
+// arrays with the forms
+//
+// TYPE SNAMEDet( TYPE matrix[2][2]);
+// TYPE SNAMEMax( TYPE * matrix, int rows, int cols);
+// TYPE SNAMEMin( int rows, int cols, TYPE * matrix);
+// void SNAMEScale( TYPE matrix[3][3]);
+// void SNAMEFloor( TYPE * array, int rows, int cols, TYPE floor);
+// void SNAMECeil( int rows, int cols, TYPE * array, TYPE ceil);
+// void SNAMELUSplit(TYPE in[3][3], TYPE lower[3][3], TYPE upper[3][3]);
+//
+// for any specified type TYPE (for example: short, unsigned int, long
+// long, etc.) with given short name SNAME (for example: short, uint,
+// longLong, etc.). The macro is then expanded for the given
+// TYPE/SNAME pairs. The resulting functions are for testing numpy
+// interfaces, respectively, for:
+//
+// * 2D input arrays, hard-coded length
+// * 2D input arrays
+// * 2D input arrays, data last
+// * 2D in-place arrays, hard-coded lengths
+// * 2D in-place arrays
+// * 2D in-place arrays, data last
+// * 2D argout arrays, hard-coded length
+//
+#define TEST_FUNCS(TYPE, SNAME) \
+\
+TYPE SNAME ## Det(TYPE matrix[2][2]) { \
+ return matrix[0][0]*matrix[1][1] - matrix[0][1]*matrix[1][0]; \
+} \
+\
+TYPE SNAME ## Max(TYPE * matrix, int rows, int cols) { \
+ int i, j, index; \
+ TYPE result = matrix[0]; \
+ for (j=0; j<cols; ++j) { \
+ for (i=0; i<rows; ++i) { \
+ index = j*rows + i; \
+ if (matrix[index] > result) result = matrix[index]; \
+ } \
+ } \
+ return result; \
+} \
+\
+TYPE SNAME ## Min(int rows, int cols, TYPE * matrix) { \
+ int i, j, index; \
+ TYPE result = matrix[0]; \
+ for (j=0; j<cols; ++j) { \
+ for (i=0; i<rows; ++i) { \
+ index = j*rows + i; \
+ if (matrix[index] < result) result = matrix[index]; \
+ } \
+ } \
+ return result; \
+} \
+\
+void SNAME ## Scale(TYPE array[3][3], TYPE val) { \
+ for (int i=0; i<3; ++i) \
+ for (int j=0; j<3; ++j) \
+ array[i][j] *= val; \
+} \
+\
+void SNAME ## Floor(TYPE * array, int rows, int cols, TYPE floor) { \
+ int i, j, index; \
+ for (j=0; j<cols; ++j) { \
+ for (i=0; i<rows; ++i) { \
+ index = j*rows + i; \
+ if (array[index] < floor) array[index] = floor; \
+ } \
+ } \
+} \
+\
+void SNAME ## Ceil(int rows, int cols, TYPE * array, TYPE ceil) { \
+ int i, j, index; \
+ for (j=0; j<cols; ++j) { \
+ for (i=0; i<rows; ++i) { \
+ index = j*rows + i; \
+ if (array[index] > ceil) array[index] = ceil; \
+ } \
+ } \
+} \
+\
+void SNAME ## LUSplit(TYPE matrix[3][3], TYPE lower[3][3], TYPE upper[3][3]) { \
+ for (int i=0; i<3; ++i) { \
+ for (int j=0; j<3; ++j) { \
+ if (i >= j) { \
+ lower[i][j] = matrix[i][j]; \
+ upper[i][j] = 0; \
+ } else { \
+ lower[i][j] = 0; \
+ upper[i][j] = matrix[i][j]; \
+ } \
+ } \
+ } \
+}
+
+TEST_FUNCS(signed char , schar )
+TEST_FUNCS(unsigned char , uchar )
+TEST_FUNCS(short , short )
+TEST_FUNCS(unsigned short , ushort )
+TEST_FUNCS(int , int )
+TEST_FUNCS(unsigned int , uint )
+TEST_FUNCS(long , long )
+TEST_FUNCS(unsigned long , ulong )
+TEST_FUNCS(long long , longLong )
+TEST_FUNCS(unsigned long long, ulongLong)
+TEST_FUNCS(float , float )
+TEST_FUNCS(double , double )
diff --git a/doc/swig/test/Matrix.h b/doc/swig/test/Matrix.h
new file mode 100644
index 000000000..f37836cc4
--- /dev/null
+++ b/doc/swig/test/Matrix.h
@@ -0,0 +1,52 @@
+#ifndef MATRIX_H
+#define MATRIX_H
+
+// The following macro defines the prototypes for a family of
+// functions that work with 2D arrays with the forms
+//
+// TYPE SNAMEDet( TYPE matrix[2][2]);
+// TYPE SNAMEMax( TYPE * matrix, int rows, int cols);
+// TYPE SNAMEMin( int rows, int cols, TYPE * matrix);
+// void SNAMEScale( TYPE array[3][3]);
+// void SNAMEFloor( TYPE * array, int rows, int cols, TYPE floor);
+// void SNAMECeil( int rows, int cols, TYPE * array, TYPE ceil );
+// void SNAMELUSplit(TYPE in[3][3], TYPE lower[3][3], TYPE upper[3][3]);
+//
+// for any specified type TYPE (for example: short, unsigned int, long
+// long, etc.) with given short name SNAME (for example: short, uint,
+// longLong, etc.). The macro is then expanded for the given
+// TYPE/SNAME pairs. The resulting functions are for testing numpy
+// interfaces, respectively, for:
+//
+// * 2D input arrays, hard-coded lengths
+// * 2D input arrays
+// * 2D input arrays, data last
+// * 2D in-place arrays, hard-coded lengths
+// * 2D in-place arrays
+// * 2D in-place arrays, data last
+// * 2D argout arrays, hard-coded length
+//
+#define TEST_FUNC_PROTOS(TYPE, SNAME) \
+\
+TYPE SNAME ## Det( TYPE matrix[2][2]); \
+TYPE SNAME ## Max( TYPE * matrix, int rows, int cols); \
+TYPE SNAME ## Min( int rows, int cols, TYPE * matrix); \
+void SNAME ## Scale( TYPE array[3][3], TYPE val); \
+void SNAME ## Floor( TYPE * array, int rows, int cols, TYPE floor); \
+void SNAME ## Ceil( int rows, int cols, TYPE * array, TYPE ceil ); \
+void SNAME ## LUSplit(TYPE matrix[3][3], TYPE lower[3][3], TYPE upper[3][3]);
+
+TEST_FUNC_PROTOS(signed char , schar )
+TEST_FUNC_PROTOS(unsigned char , uchar )
+TEST_FUNC_PROTOS(short , short )
+TEST_FUNC_PROTOS(unsigned short , ushort )
+TEST_FUNC_PROTOS(int , int )
+TEST_FUNC_PROTOS(unsigned int , uint )
+TEST_FUNC_PROTOS(long , long )
+TEST_FUNC_PROTOS(unsigned long , ulong )
+TEST_FUNC_PROTOS(long long , longLong )
+TEST_FUNC_PROTOS(unsigned long long, ulongLong)
+TEST_FUNC_PROTOS(float , float )
+TEST_FUNC_PROTOS(double , double )
+
+#endif
diff --git a/doc/swig/test/Matrix.i b/doc/swig/test/Matrix.i
new file mode 100644
index 000000000..e721397a0
--- /dev/null
+++ b/doc/swig/test/Matrix.i
@@ -0,0 +1,45 @@
+// -*- c++ -*-
+%module Matrix
+
+%{
+#define SWIG_FILE_WITH_INIT
+#include "Matrix.h"
+%}
+
+// Get the NumPy typemaps
+%include "../numpy.i"
+
+%init %{
+ import_array();
+%}
+
+%define %apply_numpy_typemaps(TYPE)
+
+%apply (TYPE IN_ARRAY2[ANY][ANY]) {(TYPE matrix[ANY][ANY])};
+%apply (TYPE* IN_ARRAY2, int DIM1, int DIM2) {(TYPE* matrix, int rows, int cols)};
+%apply (int DIM1, int DIM2, TYPE* IN_ARRAY2) {(int rows, int cols, TYPE* matrix)};
+
+%apply (TYPE INPLACE_ARRAY2[ANY][ANY]) {(TYPE array[3][3])};
+%apply (TYPE* INPLACE_ARRAY2, int DIM1, int DIM2) {(TYPE* array, int rows, int cols)};
+%apply (int DIM1, int DIM2, TYPE* INPLACE_ARRAY2) {(int rows, int cols, TYPE* array)};
+
+%apply (TYPE ARGOUT_ARRAY2[ANY][ANY]) {(TYPE lower[3][3])};
+%apply (TYPE ARGOUT_ARRAY2[ANY][ANY]) {(TYPE upper[3][3])};
+
+%enddef /* %apply_numpy_typemaps() macro */
+
+%apply_numpy_typemaps(signed char )
+%apply_numpy_typemaps(unsigned char )
+%apply_numpy_typemaps(short )
+%apply_numpy_typemaps(unsigned short )
+%apply_numpy_typemaps(int )
+%apply_numpy_typemaps(unsigned int )
+%apply_numpy_typemaps(long )
+%apply_numpy_typemaps(unsigned long )
+%apply_numpy_typemaps(long long )
+%apply_numpy_typemaps(unsigned long long)
+%apply_numpy_typemaps(float )
+%apply_numpy_typemaps(double )
+
+// Include the header file to be wrapped
+%include "Matrix.h"
diff --git a/doc/swig/test/Tensor.cxx b/doc/swig/test/Tensor.cxx
new file mode 100644
index 000000000..dce595291
--- /dev/null
+++ b/doc/swig/test/Tensor.cxx
@@ -0,0 +1,131 @@
+#include <stdlib.h>
+#include <math.h>
+#include <iostream>
+#include "Tensor.h"
+
+// The following macro defines a family of functions that work with 3D
+// arrays with the forms
+//
+// TYPE SNAMENorm( TYPE tensor[2][2][2]);
+// TYPE SNAMEMax( TYPE * tensor, int rows, int cols, int num);
+// TYPE SNAMEMin( int rows, int cols, int num, TYPE * tensor);
+// void SNAMEScale( TYPE tensor[3][3][3]);
+// void SNAMEFloor( TYPE * array, int rows, int cols, int num, TYPE floor);
+// void SNAMECeil( int rows, int cols, int num, TYPE * array, TYPE ceil);
+// void SNAMELUSplit(TYPE in[2][2][2], TYPE lower[2][2][2], TYPE upper[2][2][2]);
+//
+// for any specified type TYPE (for example: short, unsigned int, long
+// long, etc.) with given short name SNAME (for example: short, uint,
+// longLong, etc.). The macro is then expanded for the given
+// TYPE/SNAME pairs. The resulting functions are for testing numpy
+// interfaces, respectively, for:
+//
+// * 3D input arrays, hard-coded length
+// * 3D input arrays
+// * 3D input arrays, data last
+// * 3D in-place arrays, hard-coded lengths
+// * 3D in-place arrays
+// * 3D in-place arrays, data last
+// * 3D argout arrays, hard-coded length
+//
+#define TEST_FUNCS(TYPE, SNAME) \
+\
+TYPE SNAME ## Norm(TYPE tensor[2][2][2]) { \
+ double result = 0; \
+ for (int k=0; k<2; ++k) \
+ for (int j=0; j<2; ++j) \
+ for (int i=0; i<2; ++i) \
+ result += tensor[i][j][k] * tensor[i][j][k]; \
+ return (TYPE)sqrt(result/8); \
+} \
+\
+TYPE SNAME ## Max(TYPE * tensor, int rows, int cols, int num) { \
+ int i, j, k, index; \
+ TYPE result = tensor[0]; \
+ for (k=0; k<num; ++k) { \
+ for (j=0; j<cols; ++j) { \
+ for (i=0; i<rows; ++i) { \
+ index = k*rows*cols + j*rows + i; \
+ if (tensor[index] > result) result = tensor[index]; \
+ } \
+ } \
+ } \
+ return result; \
+} \
+\
+TYPE SNAME ## Min(int rows, int cols, int num, TYPE * tensor) { \
+ int i, j, k, index; \
+ TYPE result = tensor[0]; \
+ for (k=0; k<num; ++k) { \
+ for (j=0; j<cols; ++j) { \
+ for (i=0; i<rows; ++i) { \
+ index = k*rows*cols + j*rows + i; \
+ if (tensor[index] < result) result = tensor[index]; \
+ } \
+ } \
+ } \
+ return result; \
+} \
+\
+void SNAME ## Scale(TYPE array[3][3][3], TYPE val) { \
+ for (int i=0; i<3; ++i) \
+ for (int j=0; j<3; ++j) \
+ for (int k=0; k<3; ++k) \
+ array[i][j][k] *= val; \
+} \
+\
+void SNAME ## Floor(TYPE * array, int rows, int cols, int num, TYPE floor) { \
+ int i, j, k, index; \
+ for (k=0; k<num; ++k) { \
+ for (j=0; j<cols; ++j) { \
+ for (i=0; i<rows; ++i) { \
+ index = k*cols*rows + j*rows + i; \
+ if (array[index] < floor) array[index] = floor; \
+ } \
+ } \
+ } \
+} \
+\
+void SNAME ## Ceil(int rows, int cols, int num, TYPE * array, TYPE ceil) { \
+ int i, j, k, index; \
+ for (k=0; k<num; ++k) { \
+ for (j=0; j<cols; ++j) { \
+ for (i=0; i<rows; ++i) { \
+ index = j*rows + i; \
+ if (array[index] > ceil) array[index] = ceil; \
+ } \
+ } \
+ } \
+} \
+\
+void SNAME ## LUSplit(TYPE tensor[2][2][2], TYPE lower[2][2][2], \
+ TYPE upper[2][2][2]) { \
+ int sum; \
+ for (int k=0; k<2; ++k) { \
+ for (int j=0; j<2; ++j) { \
+ for (int i=0; i<2; ++i) { \
+ sum = i + j + k; \
+ if (sum < 2) { \
+ lower[i][j][k] = tensor[i][j][k]; \
+ upper[i][j][k] = 0; \
+ } else { \
+ upper[i][j][k] = tensor[i][j][k]; \
+ lower[i][j][k] = 0; \
+ } \
+ } \
+ } \
+ } \
+}
+
+TEST_FUNCS(signed char , schar )
+TEST_FUNCS(unsigned char , uchar )
+TEST_FUNCS(short , short )
+TEST_FUNCS(unsigned short , ushort )
+TEST_FUNCS(int , int )
+TEST_FUNCS(unsigned int , uint )
+TEST_FUNCS(long , long )
+TEST_FUNCS(unsigned long , ulong )
+TEST_FUNCS(long long , longLong )
+TEST_FUNCS(unsigned long long, ulongLong)
+TEST_FUNCS(float , float )
+TEST_FUNCS(double , double )
diff --git a/doc/swig/test/Tensor.h b/doc/swig/test/Tensor.h
new file mode 100644
index 000000000..d60eb2d2e
--- /dev/null
+++ b/doc/swig/test/Tensor.h
@@ -0,0 +1,52 @@
+#ifndef TENSOR_H
+#define TENSOR_H
+
+// The following macro defines the prototypes for a family of
+// functions that work with 3D arrays with the forms
+//
+// TYPE SNAMENorm( TYPE tensor[2][2][2]);
+// TYPE SNAMEMax( TYPE * tensor, int rows, int cols, int num);
+// TYPE SNAMEMin( int rows, int cols, int num, TYPE * tensor);
+// void SNAMEScale( TYPE array[3][3][3]);
+// void SNAMEFloor( TYPE * array, int rows, int cols, int num, TYPE floor);
+// void SNAMECeil( int rows, int cols, int num, TYPE * array, TYPE ceil );
+// void SNAMELUSplit(TYPE in[3][3][3], TYPE lower[3][3][3], TYPE upper[3][3][3]);
+//
+// for any specified type TYPE (for example: short, unsigned int, long
+// long, etc.) with given short name SNAME (for example: short, uint,
+// longLong, etc.). The macro is then expanded for the given
+// TYPE/SNAME pairs. The resulting functions are for testing numpy
+// interfaces, respectively, for:
+//
+// * 3D input arrays, hard-coded lengths
+// * 3D input arrays
+// * 3D input arrays, data last
+// * 3D in-place arrays, hard-coded lengths
+// * 3D in-place arrays
+// * 3D in-place arrays, data last
+// * 3D argout arrays, hard-coded length
+//
+#define TEST_FUNC_PROTOS(TYPE, SNAME) \
+\
+TYPE SNAME ## Norm( TYPE tensor[2][2][2]); \
+TYPE SNAME ## Max( TYPE * tensor, int rows, int cols, int num); \
+TYPE SNAME ## Min( int rows, int cols, int num, TYPE * tensor); \
+void SNAME ## Scale( TYPE array[3][3][3], TYPE val); \
+void SNAME ## Floor( TYPE * array, int rows, int cols, int num, TYPE floor); \
+void SNAME ## Ceil( int rows, int cols, int num, TYPE * array, TYPE ceil ); \
+void SNAME ## LUSplit(TYPE tensor[2][2][2], TYPE lower[2][2][2], TYPE upper[2][2][2]);
+
+TEST_FUNC_PROTOS(signed char , schar )
+TEST_FUNC_PROTOS(unsigned char , uchar )
+TEST_FUNC_PROTOS(short , short )
+TEST_FUNC_PROTOS(unsigned short , ushort )
+TEST_FUNC_PROTOS(int , int )
+TEST_FUNC_PROTOS(unsigned int , uint )
+TEST_FUNC_PROTOS(long , long )
+TEST_FUNC_PROTOS(unsigned long , ulong )
+TEST_FUNC_PROTOS(long long , longLong )
+TEST_FUNC_PROTOS(unsigned long long, ulongLong)
+TEST_FUNC_PROTOS(float , float )
+TEST_FUNC_PROTOS(double , double )
+
+#endif
diff --git a/doc/swig/test/Tensor.i b/doc/swig/test/Tensor.i
new file mode 100644
index 000000000..a1198dc9e
--- /dev/null
+++ b/doc/swig/test/Tensor.i
@@ -0,0 +1,49 @@
+// -*- c++ -*-
+%module Tensor
+
+%{
+#define SWIG_FILE_WITH_INIT
+#include "Tensor.h"
+%}
+
+// Get the NumPy typemaps
+%include "../numpy.i"
+
+%init %{
+ import_array();
+%}
+
+%define %apply_numpy_typemaps(TYPE)
+
+%apply (TYPE IN_ARRAY3[ANY][ANY][ANY]) {(TYPE tensor[ANY][ANY][ANY])};
+%apply (TYPE* IN_ARRAY3, int DIM1, int DIM2, int DIM3)
+ {(TYPE* tensor, int rows, int cols, int num)};
+%apply (int DIM1, int DIM2, int DIM3, TYPE* IN_ARRAY3)
+ {(int rows, int cols, int num, TYPE* tensor)};
+
+%apply (TYPE INPLACE_ARRAY3[ANY][ANY][ANY]) {(TYPE array[3][3][3])};
+%apply (TYPE* INPLACE_ARRAY3, int DIM1, int DIM2, int DIM3)
+ {(TYPE* array, int rows, int cols, int num)};
+%apply (int DIM1, int DIM2, int DIM3, TYPE* INPLACE_ARRAY3)
+ {(int rows, int cols, int num, TYPE* array)};
+
+%apply (TYPE ARGOUT_ARRAY3[ANY][ANY][ANY]) {(TYPE lower[2][2][2])};
+%apply (TYPE ARGOUT_ARRAY3[ANY][ANY][ANY]) {(TYPE upper[2][2][2])};
+
+%enddef /* %apply_numpy_typemaps() macro */
+
+%apply_numpy_typemaps(signed char )
+%apply_numpy_typemaps(unsigned char )
+%apply_numpy_typemaps(short )
+%apply_numpy_typemaps(unsigned short )
+%apply_numpy_typemaps(int )
+%apply_numpy_typemaps(unsigned int )
+%apply_numpy_typemaps(long )
+%apply_numpy_typemaps(unsigned long )
+%apply_numpy_typemaps(long long )
+%apply_numpy_typemaps(unsigned long long)
+%apply_numpy_typemaps(float )
+%apply_numpy_typemaps(double )
+
+// Include the header file to be wrapped
+%include "Tensor.h"
diff --git a/doc/swig/test/Vector.cxx b/doc/swig/test/Vector.cxx
new file mode 100644
index 000000000..2c90404da
--- /dev/null
+++ b/doc/swig/test/Vector.cxx
@@ -0,0 +1,100 @@
+#include <stdlib.h>
+#include <math.h>
+#include <iostream>
+#include "Vector.h"
+
+// The following macro defines a family of functions that work with 1D
+// arrays with the forms
+//
+// TYPE SNAMELength( TYPE vector[3]);
+// TYPE SNAMEProd( TYPE * series, int size);
+// TYPE SNAMESum( int size, TYPE * series);
+// void SNAMEReverse(TYPE array[3]);
+// void SNAMEOnes( TYPE * array, int size);
+// void SNAMEZeros( int size, TYPE * array);
+// void SNAMEEOSplit(TYPE vector[3], TYPE even[3], odd[3]);
+// void SNAMETwos( TYPE * twoVec, int size);
+// void SNAMEThrees( int size, TYPE * threeVec);
+//
+// for any specified type TYPE (for example: short, unsigned int, long
+// long, etc.) with given short name SNAME (for example: short, uint,
+// longLong, etc.). The macro is then expanded for the given
+// TYPE/SNAME pairs. The resulting functions are for testing numpy
+// interfaces, respectively, for:
+//
+// * 1D input arrays, hard-coded length
+// * 1D input arrays
+// * 1D input arrays, data last
+// * 1D in-place arrays, hard-coded length
+// * 1D in-place arrays
+// * 1D in-place arrays, data last
+// * 1D argout arrays, hard-coded length
+// * 1D argout arrays
+// * 1D argout arrays, data last
+//
+#define TEST_FUNCS(TYPE, SNAME) \
+\
+TYPE SNAME ## Length(TYPE vector[3]) { \
+ double result = 0; \
+ for (int i=0; i<3; ++i) result += vector[i]*vector[i]; \
+ return (TYPE)sqrt(result); \
+} \
+\
+TYPE SNAME ## Prod(TYPE * series, int size) { \
+ TYPE result = 1; \
+ for (int i=0; i<size; ++i) result *= series[i]; \
+ return result; \
+} \
+\
+TYPE SNAME ## Sum(int size, TYPE * series) { \
+ TYPE result = 0; \
+ for (int i=0; i<size; ++i) result += series[i]; \
+ return result; \
+} \
+\
+void SNAME ## Reverse(TYPE array[3]) { \
+ TYPE temp = array[0]; \
+ array[0] = array[2]; \
+ array[2] = temp; \
+} \
+\
+void SNAME ## Ones(TYPE * array, int size) { \
+ for (int i=0; i<size; ++i) array[i] = 1; \
+} \
+\
+void SNAME ## Zeros(int size, TYPE * array) { \
+ for (int i=0; i<size; ++i) array[i] = 0; \
+} \
+\
+void SNAME ## EOSplit(TYPE vector[3], TYPE even[3], TYPE odd[3]) { \
+ for (int i=0; i<3; ++i) { \
+ if (i % 2 == 0) { \
+ even[i] = vector[i]; \
+ odd[ i] = 0; \
+ } else { \
+ even[i] = 0; \
+ odd[ i] = vector[i]; \
+ } \
+ } \
+} \
+\
+void SNAME ## Twos(TYPE* twoVec, int size) { \
+ for (int i=0; i<size; ++i) twoVec[i] = 2; \
+} \
+\
+void SNAME ## Threes(int size, TYPE* threeVec) { \
+ for (int i=0; i<size; ++i) threeVec[i] = 3; \
+}
+
+TEST_FUNCS(signed char , schar )
+TEST_FUNCS(unsigned char , uchar )
+TEST_FUNCS(short , short )
+TEST_FUNCS(unsigned short , ushort )
+TEST_FUNCS(int , int )
+TEST_FUNCS(unsigned int , uint )
+TEST_FUNCS(long , long )
+TEST_FUNCS(unsigned long , ulong )
+TEST_FUNCS(long long , longLong )
+TEST_FUNCS(unsigned long long, ulongLong)
+TEST_FUNCS(float , float )
+TEST_FUNCS(double , double )
diff --git a/doc/swig/test/Vector.h b/doc/swig/test/Vector.h
new file mode 100644
index 000000000..01da361c6
--- /dev/null
+++ b/doc/swig/test/Vector.h
@@ -0,0 +1,58 @@
+#ifndef VECTOR_H
+#define VECTOR_H
+
+// The following macro defines the prototypes for a family of
+// functions that work with 1D arrays with the forms
+//
+// TYPE SNAMELength( TYPE vector[3]);
+// TYPE SNAMEProd( TYPE * series, int size);
+// TYPE SNAMESum( int size, TYPE * series);
+// void SNAMEReverse(TYPE array[3]);
+// void SNAMEOnes( TYPE * array, int size);
+// void SNAMEZeros( int size, TYPE * array);
+// void SNAMEEOSplit(TYPE vector[3], TYPE even[3], TYPE odd[3]);
+// void SNAMETwos( TYPE * twoVec, int size);
+// void SNAMEThrees( int size, TYPE * threeVec);
+//
+// for any specified type TYPE (for example: short, unsigned int, long
+// long, etc.) with given short name SNAME (for example: short, uint,
+// longLong, etc.). The macro is then expanded for the given
+// TYPE/SNAME pairs. The resulting functions are for testing numpy
+// interfaces, respectively, for:
+//
+// * 1D input arrays, hard-coded length
+// * 1D input arrays
+// * 1D input arrays, data last
+// * 1D in-place arrays, hard-coded length
+// * 1D in-place arrays
+// * 1D in-place arrays, data last
+// * 1D argout arrays, hard-coded length
+// * 1D argout arrays
+// * 1D argout arrays, data last
+//
+#define TEST_FUNC_PROTOS(TYPE, SNAME) \
+\
+TYPE SNAME ## Length( TYPE vector[3]); \
+TYPE SNAME ## Prod( TYPE * series, int size); \
+TYPE SNAME ## Sum( int size, TYPE * series); \
+void SNAME ## Reverse(TYPE array[3]); \
+void SNAME ## Ones( TYPE * array, int size); \
+void SNAME ## Zeros( int size, TYPE * array); \
+void SNAME ## EOSplit(TYPE vector[3], TYPE even[3], TYPE odd[3]); \
+void SNAME ## Twos( TYPE * twoVec, int size); \
+void SNAME ## Threes( int size, TYPE * threeVec); \
+
+TEST_FUNC_PROTOS(signed char , schar )
+TEST_FUNC_PROTOS(unsigned char , uchar )
+TEST_FUNC_PROTOS(short , short )
+TEST_FUNC_PROTOS(unsigned short , ushort )
+TEST_FUNC_PROTOS(int , int )
+TEST_FUNC_PROTOS(unsigned int , uint )
+TEST_FUNC_PROTOS(long , long )
+TEST_FUNC_PROTOS(unsigned long , ulong )
+TEST_FUNC_PROTOS(long long , longLong )
+TEST_FUNC_PROTOS(unsigned long long, ulongLong)
+TEST_FUNC_PROTOS(float , float )
+TEST_FUNC_PROTOS(double , double )
+
+#endif
diff --git a/doc/swig/test/Vector.i b/doc/swig/test/Vector.i
new file mode 100644
index 000000000..e86f21c37
--- /dev/null
+++ b/doc/swig/test/Vector.i
@@ -0,0 +1,47 @@
+// -*- c++ -*-
+%module Vector
+
+%{
+#define SWIG_FILE_WITH_INIT
+#include "Vector.h"
+%}
+
+// Get the NumPy typemaps
+%include "../numpy.i"
+
+%init %{
+ import_array();
+%}
+
+%define %apply_numpy_typemaps(TYPE)
+
+%apply (TYPE IN_ARRAY1[ANY]) {(TYPE vector[3])};
+%apply (TYPE* IN_ARRAY1, int DIM1) {(TYPE* series, int size)};
+%apply (int DIM1, TYPE* IN_ARRAY1) {(int size, TYPE* series)};
+
+%apply (TYPE INPLACE_ARRAY1[ANY]) {(TYPE array[3])};
+%apply (TYPE* INPLACE_ARRAY1, int DIM1) {(TYPE* array, int size)};
+%apply (int DIM1, TYPE* INPLACE_ARRAY1) {(int size, TYPE* array)};
+
+%apply (TYPE ARGOUT_ARRAY1[ANY]) {(TYPE even[3])};
+%apply (TYPE ARGOUT_ARRAY1[ANY]) {(TYPE odd[ 3])};
+%apply (TYPE* ARGOUT_ARRAY1, int DIM1) {(TYPE* twoVec, int size)};
+%apply (int DIM1, TYPE* ARGOUT_ARRAY1) {(int size, TYPE* threeVec)};
+
+%enddef /* %apply_numpy_typemaps() macro */
+
+%apply_numpy_typemaps(signed char )
+%apply_numpy_typemaps(unsigned char )
+%apply_numpy_typemaps(short )
+%apply_numpy_typemaps(unsigned short )
+%apply_numpy_typemaps(int )
+%apply_numpy_typemaps(unsigned int )
+%apply_numpy_typemaps(long )
+%apply_numpy_typemaps(unsigned long )
+%apply_numpy_typemaps(long long )
+%apply_numpy_typemaps(unsigned long long)
+%apply_numpy_typemaps(float )
+%apply_numpy_typemaps(double )
+
+// Include the header file to be wrapped
+%include "Vector.h"
diff --git a/doc/swig/test/setup.py b/doc/swig/test/setup.py
new file mode 100755
index 000000000..fadf8b5cd
--- /dev/null
+++ b/doc/swig/test/setup.py
@@ -0,0 +1,66 @@
+#! /usr/bin/env python
+
+# System imports
+from distutils.core import *
+from distutils import sysconfig
+
+# Third-party modules - we depend on numpy for everything
+import numpy
+
+# Obtain the numpy include directory. This logic works across numpy versions.
+try:
+ numpy_include = numpy.get_include()
+except AttributeError:
+ numpy_include = numpy.get_numpy_include()
+
+# Array extension module
+_Array = Extension("_Array",
+ ["Array_wrap.cxx",
+ "Array1.cxx",
+ "Array2.cxx"],
+ include_dirs = [numpy_include],
+ )
+
+# Farray extension module
+_Farray = Extension("_Farray",
+ ["Farray_wrap.cxx",
+ "Farray.cxx"],
+ include_dirs = [numpy_include],
+ )
+
+# _Vector extension module
+_Vector = Extension("_Vector",
+ ["Vector_wrap.cxx",
+ "Vector.cxx"],
+ include_dirs = [numpy_include],
+ )
+
+# _Matrix extension module
+_Matrix = Extension("_Matrix",
+ ["Matrix_wrap.cxx",
+ "Matrix.cxx"],
+ include_dirs = [numpy_include],
+ )
+
+# _Tensor extension module
+_Tensor = Extension("_Tensor",
+ ["Tensor_wrap.cxx",
+ "Tensor.cxx"],
+ include_dirs = [numpy_include],
+ )
+
+_Fortran = Extension("_Fortran",
+ ["Fortran_wrap.cxx",
+ "Fortran.cxx"],
+ include_dirs = [numpy_include],
+ )
+
+# NumyTypemapTests setup
+setup(name = "NumpyTypemapTests",
+ description = "Functions that work on arrays",
+ author = "Bill Spotz",
+ py_modules = ["Array", "Farray", "Vector", "Matrix", "Tensor",
+ "Fortran"],
+ ext_modules = [_Array , _Farray , _Vector , _Matrix , _Tensor,
+ _Fortran]
+ )
diff --git a/doc/swig/test/testArray.py b/doc/swig/test/testArray.py
new file mode 100755
index 000000000..ba83d14d9
--- /dev/null
+++ b/doc/swig/test/testArray.py
@@ -0,0 +1,283 @@
+#! /usr/bin/env python
+
+# System imports
+from distutils.util import get_platform
+import os
+import sys
+import unittest
+
+# Import NumPy
+import numpy as np
+major, minor = [ int(d) for d in np.__version__.split(".")[:2] ]
+if major == 0:
+ BadListError = TypeError
+else:
+ BadListError = ValueError
+
+import Array
+
+######################################################################
+
+class Array1TestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.length = 5
+ self.array1 = Array.Array1(self.length)
+
+ def testConstructor0(self):
+ "Test Array1 default constructor"
+ a = Array.Array1()
+ self.failUnless(isinstance(a, Array.Array1))
+ self.failUnless(len(a) == 0)
+
+ def testConstructor1(self):
+ "Test Array1 length constructor"
+ self.failUnless(isinstance(self.array1, Array.Array1))
+
+ def testConstructor2(self):
+ "Test Array1 array constructor"
+ na = np.arange(self.length)
+ aa = Array.Array1(na)
+ self.failUnless(isinstance(aa, Array.Array1))
+
+ def testConstructor3(self):
+ "Test Array1 copy constructor"
+ for i in range(self.array1.length()): self.array1[i] = i
+ arrayCopy = Array.Array1(self.array1)
+ self.failUnless(arrayCopy == self.array1)
+
+ def testConstructorBad(self):
+ "Test Array1 length constructor, negative"
+ self.assertRaises(ValueError, Array.Array1, -4)
+
+ def testLength(self):
+ "Test Array1 length method"
+ self.failUnless(self.array1.length() == self.length)
+
+ def testLen(self):
+ "Test Array1 __len__ method"
+ self.failUnless(len(self.array1) == self.length)
+
+ def testResize0(self):
+ "Test Array1 resize method, length"
+ newLen = 2 * self.length
+ self.array1.resize(newLen)
+ self.failUnless(len(self.array1) == newLen)
+
+ def testResize1(self):
+ "Test Array1 resize method, array"
+ a = np.zeros((2*self.length,), dtype='l')
+ self.array1.resize(a)
+ self.failUnless(len(self.array1) == len(a))
+
+ def testResizeBad(self):
+ "Test Array1 resize method, negative length"
+ self.assertRaises(ValueError, self.array1.resize, -5)
+
+ def testSetGet(self):
+ "Test Array1 __setitem__, __getitem__ methods"
+ n = self.length
+ for i in range(n):
+ self.array1[i] = i*i
+ for i in range(n):
+ self.failUnless(self.array1[i] == i*i)
+
+ def testSetBad1(self):
+ "Test Array1 __setitem__ method, negative index"
+ self.assertRaises(IndexError, self.array1.__setitem__, -1, 0)
+
+ def testSetBad2(self):
+ "Test Array1 __setitem__ method, out-of-range index"
+ self.assertRaises(IndexError, self.array1.__setitem__, self.length+1, 0)
+
+ def testGetBad1(self):
+ "Test Array1 __getitem__ method, negative index"
+ self.assertRaises(IndexError, self.array1.__getitem__, -1)
+
+ def testGetBad2(self):
+ "Test Array1 __getitem__ method, out-of-range index"
+ self.assertRaises(IndexError, self.array1.__getitem__, self.length+1)
+
+ def testAsString(self):
+ "Test Array1 asString method"
+ for i in range(self.array1.length()): self.array1[i] = i+1
+ self.failUnless(self.array1.asString() == "[ 1, 2, 3, 4, 5 ]")
+
+ def testStr(self):
+ "Test Array1 __str__ method"
+ for i in range(self.array1.length()): self.array1[i] = i-2
+ self.failUnless(str(self.array1) == "[ -2, -1, 0, 1, 2 ]")
+
+ def testView(self):
+ "Test Array1 view method"
+ for i in range(self.array1.length()): self.array1[i] = i+1
+ a = self.array1.view()
+ self.failUnless(isinstance(a, np.ndarray))
+ self.failUnless(len(a) == self.length)
+ self.failUnless((a == [1,2,3,4,5]).all())
+
+######################################################################
+
+class Array2TestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.nrows = 5
+ self.ncols = 4
+ self.array2 = Array.Array2(self.nrows, self.ncols)
+
+ def testConstructor0(self):
+ "Test Array2 default constructor"
+ a = Array.Array2()
+ self.failUnless(isinstance(a, Array.Array2))
+ self.failUnless(len(a) == 0)
+
+ def testConstructor1(self):
+ "Test Array2 nrows, ncols constructor"
+ self.failUnless(isinstance(self.array2, Array.Array2))
+
+ def testConstructor2(self):
+ "Test Array2 array constructor"
+ na = np.zeros((3,4), dtype="l")
+ aa = Array.Array2(na)
+ self.failUnless(isinstance(aa, Array.Array2))
+
+ def testConstructor3(self):
+ "Test Array2 copy constructor"
+ for i in range(self.nrows):
+ for j in range(self.ncols):
+ self.array2[i][j] = i * j
+ arrayCopy = Array.Array2(self.array2)
+ self.failUnless(arrayCopy == self.array2)
+
+ def testConstructorBad1(self):
+ "Test Array2 nrows, ncols constructor, negative nrows"
+ self.assertRaises(ValueError, Array.Array2, -4, 4)
+
+ def testConstructorBad2(self):
+ "Test Array2 nrows, ncols constructor, negative ncols"
+ self.assertRaises(ValueError, Array.Array2, 4, -4)
+
+ def testNrows(self):
+ "Test Array2 nrows method"
+ self.failUnless(self.array2.nrows() == self.nrows)
+
+ def testNcols(self):
+ "Test Array2 ncols method"
+ self.failUnless(self.array2.ncols() == self.ncols)
+
+ def testLen(self):
+ "Test Array2 __len__ method"
+ self.failUnless(len(self.array2) == self.nrows*self.ncols)
+
+ def testResize0(self):
+ "Test Array2 resize method, size"
+ newRows = 2 * self.nrows
+ newCols = 2 * self.ncols
+ self.array2.resize(newRows, newCols)
+ self.failUnless(len(self.array2) == newRows * newCols)
+
+ #def testResize1(self):
+ # "Test Array2 resize method, array"
+ # a = np.zeros((2*self.nrows, 2*self.ncols), dtype='l')
+ # self.array2.resize(a)
+ # self.failUnless(len(self.array2) == len(a))
+
+ def testResizeBad1(self):
+ "Test Array2 resize method, negative nrows"
+ self.assertRaises(ValueError, self.array2.resize, -5, 5)
+
+ def testResizeBad2(self):
+ "Test Array2 resize method, negative ncols"
+ self.assertRaises(ValueError, self.array2.resize, 5, -5)
+
+ def testSetGet1(self):
+ "Test Array2 __setitem__, __getitem__ methods"
+ m = self.nrows
+ n = self.ncols
+ array1 = [ ]
+ a = np.arange(n, dtype="l")
+ for i in range(m):
+ array1.append(Array.Array1(i*a))
+ for i in range(m):
+ self.array2[i] = array1[i]
+ for i in range(m):
+ self.failUnless(self.array2[i] == array1[i])
+
+ def testSetGet2(self):
+ "Test Array2 chained __setitem__, __getitem__ methods"
+ m = self.nrows
+ n = self.ncols
+ for i in range(m):
+ for j in range(n):
+ self.array2[i][j] = i*j
+ for i in range(m):
+ for j in range(n):
+ self.failUnless(self.array2[i][j] == i*j)
+
+ def testSetBad1(self):
+ "Test Array2 __setitem__ method, negative index"
+ a = Array.Array1(self.ncols)
+ self.assertRaises(IndexError, self.array2.__setitem__, -1, a)
+
+ def testSetBad2(self):
+ "Test Array2 __setitem__ method, out-of-range index"
+ a = Array.Array1(self.ncols)
+ self.assertRaises(IndexError, self.array2.__setitem__, self.nrows+1, a)
+
+ def testGetBad1(self):
+ "Test Array2 __getitem__ method, negative index"
+ self.assertRaises(IndexError, self.array2.__getitem__, -1)
+
+ def testGetBad2(self):
+ "Test Array2 __getitem__ method, out-of-range index"
+ self.assertRaises(IndexError, self.array2.__getitem__, self.nrows+1)
+
+ def testAsString(self):
+ "Test Array2 asString method"
+ result = """\
+[ [ 0, 1, 2, 3 ],
+ [ 1, 2, 3, 4 ],
+ [ 2, 3, 4, 5 ],
+ [ 3, 4, 5, 6 ],
+ [ 4, 5, 6, 7 ] ]
+"""
+ for i in range(self.nrows):
+ for j in range(self.ncols):
+ self.array2[i][j] = i+j
+ self.failUnless(self.array2.asString() == result)
+
+ def testStr(self):
+ "Test Array2 __str__ method"
+ result = """\
+[ [ 0, -1, -2, -3 ],
+ [ 1, 0, -1, -2 ],
+ [ 2, 1, 0, -1 ],
+ [ 3, 2, 1, 0 ],
+ [ 4, 3, 2, 1 ] ]
+"""
+ for i in range(self.nrows):
+ for j in range(self.ncols):
+ self.array2[i][j] = i-j
+ self.failUnless(str(self.array2) == result)
+
+ def testView(self):
+ "Test Array2 view method"
+ a = self.array2.view()
+ self.failUnless(isinstance(a, np.ndarray))
+ self.failUnless(len(a) == self.nrows)
+
+######################################################################
+
+if __name__ == "__main__":
+
+ # Build the test suite
+ suite = unittest.TestSuite()
+ suite.addTest(unittest.makeSuite(Array1TestCase))
+ suite.addTest(unittest.makeSuite(Array2TestCase))
+
+ # Execute the test suite
+ print "Testing Classes of Module Array"
+ print "NumPy version", np.__version__
+ print
+ result = unittest.TextTestRunner(verbosity=2).run(suite)
+ sys.exit(len(result.errors) + len(result.failures))
diff --git a/doc/swig/test/testFarray.py b/doc/swig/test/testFarray.py
new file mode 100755
index 000000000..614e149bd
--- /dev/null
+++ b/doc/swig/test/testFarray.py
@@ -0,0 +1,158 @@
+#! /usr/bin/env python
+
+# System imports
+from distutils.util import get_platform
+import os
+import sys
+import unittest
+
+# Import NumPy
+import numpy as np
+major, minor = [ int(d) for d in np.__version__.split(".")[:2] ]
+if major == 0: BadListError = TypeError
+else: BadListError = ValueError
+
+# Add the distutils-generated build directory to the python search path and then
+# import the extension module
+libDir = "lib.%s-%s" % (get_platform(), sys.version[:3])
+sys.path.insert(0,os.path.join("build", libDir))
+import Farray
+
+######################################################################
+
+class FarrayTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.nrows = 5
+ self.ncols = 4
+ self.array = Farray.Farray(self.nrows, self.ncols)
+
+ def testConstructor1(self):
+ "Test Farray size constructor"
+ self.failUnless(isinstance(self.array, Farray.Farray))
+
+ def testConstructor2(self):
+ "Test Farray copy constructor"
+ for i in range(self.nrows):
+ for j in range(self.ncols):
+ self.array[i,j] = i + j
+ arrayCopy = Farray.Farray(self.array)
+ self.failUnless(arrayCopy == self.array)
+
+ def testConstructorBad1(self):
+ "Test Farray size constructor, negative nrows"
+ self.assertRaises(ValueError, Farray.Farray, -4, 4)
+
+ def testConstructorBad2(self):
+ "Test Farray size constructor, negative ncols"
+ self.assertRaises(ValueError, Farray.Farray, 4, -4)
+
+ def testNrows(self):
+ "Test Farray nrows method"
+ self.failUnless(self.array.nrows() == self.nrows)
+
+ def testNcols(self):
+ "Test Farray ncols method"
+ self.failUnless(self.array.ncols() == self.ncols)
+
+ def testLen(self):
+ "Test Farray __len__ method"
+ self.failUnless(len(self.array) == self.nrows*self.ncols)
+
+ def testSetGet(self):
+ "Test Farray __setitem__, __getitem__ methods"
+ m = self.nrows
+ n = self.ncols
+ for i in range(m):
+ for j in range(n):
+ self.array[i,j] = i*j
+ for i in range(m):
+ for j in range(n):
+ self.failUnless(self.array[i,j] == i*j)
+
+ def testSetBad1(self):
+ "Test Farray __setitem__ method, negative row"
+ self.assertRaises(IndexError, self.array.__setitem__, (-1, 3), 0)
+
+ def testSetBad2(self):
+ "Test Farray __setitem__ method, negative col"
+ self.assertRaises(IndexError, self.array.__setitem__, (1, -3), 0)
+
+ def testSetBad3(self):
+ "Test Farray __setitem__ method, out-of-range row"
+ self.assertRaises(IndexError, self.array.__setitem__, (self.nrows+1, 0), 0)
+
+ def testSetBad4(self):
+ "Test Farray __setitem__ method, out-of-range col"
+ self.assertRaises(IndexError, self.array.__setitem__, (0, self.ncols+1), 0)
+
+ def testGetBad1(self):
+ "Test Farray __getitem__ method, negative row"
+ self.assertRaises(IndexError, self.array.__getitem__, (-1, 3))
+
+ def testGetBad2(self):
+ "Test Farray __getitem__ method, negative col"
+ self.assertRaises(IndexError, self.array.__getitem__, (1, -3))
+
+ def testGetBad3(self):
+ "Test Farray __getitem__ method, out-of-range row"
+ self.assertRaises(IndexError, self.array.__getitem__, (self.nrows+1, 0))
+
+ def testGetBad4(self):
+ "Test Farray __getitem__ method, out-of-range col"
+ self.assertRaises(IndexError, self.array.__getitem__, (0, self.ncols+1))
+
+ def testAsString(self):
+ "Test Farray asString method"
+ result = """\
+[ [ 0, 1, 2, 3 ],
+ [ 1, 2, 3, 4 ],
+ [ 2, 3, 4, 5 ],
+ [ 3, 4, 5, 6 ],
+ [ 4, 5, 6, 7 ] ]
+"""
+ for i in range(self.nrows):
+ for j in range(self.ncols):
+ self.array[i,j] = i+j
+ self.failUnless(self.array.asString() == result)
+
+ def testStr(self):
+ "Test Farray __str__ method"
+ result = """\
+[ [ 0, -1, -2, -3 ],
+ [ 1, 0, -1, -2 ],
+ [ 2, 1, 0, -1 ],
+ [ 3, 2, 1, 0 ],
+ [ 4, 3, 2, 1 ] ]
+"""
+ for i in range(self.nrows):
+ for j in range(self.ncols):
+ self.array[i,j] = i-j
+ self.failUnless(str(self.array) == result)
+
+ def testView(self):
+ "Test Farray view method"
+ for i in range(self.nrows):
+ for j in range(self.ncols):
+ self.array[i,j] = i+j
+ a = self.array.view()
+ self.failUnless(isinstance(a, np.ndarray))
+ self.failUnless(a.flags.f_contiguous)
+ for i in range(self.nrows):
+ for j in range(self.ncols):
+ self.failUnless(a[i,j] == i+j)
+
+######################################################################
+
+if __name__ == "__main__":
+
+ # Build the test suite
+ suite = unittest.TestSuite()
+ suite.addTest(unittest.makeSuite(FarrayTestCase))
+
+ # Execute the test suite
+ print "Testing Classes of Module Farray"
+ print "NumPy version", np.__version__
+ print
+ result = unittest.TextTestRunner(verbosity=2).run(suite)
+ sys.exit(len(result.errors) + len(result.failures))
diff --git a/doc/swig/test/testFortran.py b/doc/swig/test/testFortran.py
new file mode 100644
index 000000000..d2c382869
--- /dev/null
+++ b/doc/swig/test/testFortran.py
@@ -0,0 +1,169 @@
+#! /usr/bin/env python
+
+# System imports
+from distutils.util import get_platform
+import os
+import sys
+import unittest
+
+# Import NumPy
+import numpy as np
+major, minor = [ int(d) for d in np.__version__.split(".")[:2] ]
+if major == 0: BadListError = TypeError
+else: BadListError = ValueError
+
+import Fortran
+
+######################################################################
+
+class FortranTestCase(unittest.TestCase):
+
+ def __init__(self, methodName="runTests"):
+ unittest.TestCase.__init__(self, methodName)
+ self.typeStr = "double"
+ self.typeCode = "d"
+
+ # Test (type* IN_FARRAY2, int DIM1, int DIM2) typemap
+ def testSecondElementContiguous(self):
+ "Test luSplit function with a Fortran-array"
+ print >>sys.stderr, self.typeStr, "... ",
+ second = Fortran.__dict__[self.typeStr + "SecondElement"]
+ matrix = np.arange(9).reshape(3, 3).astype(self.typeCode)
+ self.assertEquals(second(matrix), 3)
+
+ def testSecondElementFortran(self):
+ "Test luSplit function with a Fortran-array"
+ print >>sys.stderr, self.typeStr, "... ",
+ second = Fortran.__dict__[self.typeStr + "SecondElement"]
+ matrix = np.asfortranarray(np.arange(9).reshape(3, 3),
+ self.typeCode)
+ self.assertEquals(second(matrix), 3)
+
+ def testSecondElementObject(self):
+ "Test luSplit function with a Fortran-array"
+ print >>sys.stderr, self.typeStr, "... ",
+ second = Fortran.__dict__[self.typeStr + "SecondElement"]
+ matrix = np.asfortranarray([[0,1,2],[3,4,5],[6,7,8]], self.typeCode)
+ self.assertEquals(second(matrix), 3)
+
+######################################################################
+
+class scharTestCase(FortranTestCase):
+ def __init__(self, methodName="runTest"):
+ FortranTestCase.__init__(self, methodName)
+ self.typeStr = "schar"
+ self.typeCode = "b"
+
+######################################################################
+
+class ucharTestCase(FortranTestCase):
+ def __init__(self, methodName="runTest"):
+ FortranTestCase.__init__(self, methodName)
+ self.typeStr = "uchar"
+ self.typeCode = "B"
+
+######################################################################
+
+class shortTestCase(FortranTestCase):
+ def __init__(self, methodName="runTest"):
+ FortranTestCase.__init__(self, methodName)
+ self.typeStr = "short"
+ self.typeCode = "h"
+
+######################################################################
+
+class ushortTestCase(FortranTestCase):
+ def __init__(self, methodName="runTest"):
+ FortranTestCase.__init__(self, methodName)
+ self.typeStr = "ushort"
+ self.typeCode = "H"
+
+######################################################################
+
+class intTestCase(FortranTestCase):
+ def __init__(self, methodName="runTest"):
+ FortranTestCase.__init__(self, methodName)
+ self.typeStr = "int"
+ self.typeCode = "i"
+
+######################################################################
+
+class uintTestCase(FortranTestCase):
+ def __init__(self, methodName="runTest"):
+ FortranTestCase.__init__(self, methodName)
+ self.typeStr = "uint"
+ self.typeCode = "I"
+
+######################################################################
+
+class longTestCase(FortranTestCase):
+ def __init__(self, methodName="runTest"):
+ FortranTestCase.__init__(self, methodName)
+ self.typeStr = "long"
+ self.typeCode = "l"
+
+######################################################################
+
+class ulongTestCase(FortranTestCase):
+ def __init__(self, methodName="runTest"):
+ FortranTestCase.__init__(self, methodName)
+ self.typeStr = "ulong"
+ self.typeCode = "L"
+
+######################################################################
+
+class longLongTestCase(FortranTestCase):
+ def __init__(self, methodName="runTest"):
+ FortranTestCase.__init__(self, methodName)
+ self.typeStr = "longLong"
+ self.typeCode = "q"
+
+######################################################################
+
+class ulongLongTestCase(FortranTestCase):
+ def __init__(self, methodName="runTest"):
+ FortranTestCase.__init__(self, methodName)
+ self.typeStr = "ulongLong"
+ self.typeCode = "Q"
+
+######################################################################
+
+class floatTestCase(FortranTestCase):
+ def __init__(self, methodName="runTest"):
+ FortranTestCase.__init__(self, methodName)
+ self.typeStr = "float"
+ self.typeCode = "f"
+
+######################################################################
+
+class doubleTestCase(FortranTestCase):
+ def __init__(self, methodName="runTest"):
+ FortranTestCase.__init__(self, methodName)
+ self.typeStr = "double"
+ self.typeCode = "d"
+
+######################################################################
+
+if __name__ == "__main__":
+
+ # Build the test suite
+ suite = unittest.TestSuite()
+ suite.addTest(unittest.makeSuite( scharTestCase))
+ suite.addTest(unittest.makeSuite( ucharTestCase))
+ suite.addTest(unittest.makeSuite( shortTestCase))
+ suite.addTest(unittest.makeSuite( ushortTestCase))
+ suite.addTest(unittest.makeSuite( intTestCase))
+ suite.addTest(unittest.makeSuite( uintTestCase))
+ suite.addTest(unittest.makeSuite( longTestCase))
+ suite.addTest(unittest.makeSuite( ulongTestCase))
+ suite.addTest(unittest.makeSuite( longLongTestCase))
+ suite.addTest(unittest.makeSuite(ulongLongTestCase))
+ suite.addTest(unittest.makeSuite( floatTestCase))
+ suite.addTest(unittest.makeSuite( doubleTestCase))
+
+ # Execute the test suite
+ print "Testing 2D Functions of Module Matrix"
+ print "NumPy version", np.__version__
+ print
+ result = unittest.TextTestRunner(verbosity=2).run(suite)
+ sys.exit(len(result.errors) + len(result.failures))
diff --git a/doc/swig/test/testMatrix.py b/doc/swig/test/testMatrix.py
new file mode 100755
index 000000000..12061702d
--- /dev/null
+++ b/doc/swig/test/testMatrix.py
@@ -0,0 +1,361 @@
+#! /usr/bin/env python
+
+# System imports
+from distutils.util import get_platform
+import os
+import sys
+import unittest
+
+# Import NumPy
+import numpy as np
+major, minor = [ int(d) for d in np.__version__.split(".")[:2] ]
+if major == 0: BadListError = TypeError
+else: BadListError = ValueError
+
+import Matrix
+
+######################################################################
+
+class MatrixTestCase(unittest.TestCase):
+
+ def __init__(self, methodName="runTests"):
+ unittest.TestCase.__init__(self, methodName)
+ self.typeStr = "double"
+ self.typeCode = "d"
+
+ # Test (type IN_ARRAY2[ANY][ANY]) typemap
+ def testDet(self):
+ "Test det function"
+ print >>sys.stderr, self.typeStr, "... ",
+ det = Matrix.__dict__[self.typeStr + "Det"]
+ matrix = [[8,7],[6,9]]
+ self.assertEquals(det(matrix), 30)
+
+ # Test (type IN_ARRAY2[ANY][ANY]) typemap
+ def testDetBadList(self):
+ "Test det function with bad list"
+ print >>sys.stderr, self.typeStr, "... ",
+ det = Matrix.__dict__[self.typeStr + "Det"]
+ matrix = [[8,7], ["e", "pi"]]
+ self.assertRaises(BadListError, det, matrix)
+
+ # Test (type IN_ARRAY2[ANY][ANY]) typemap
+ def testDetWrongDim(self):
+ "Test det function with wrong dimensions"
+ print >>sys.stderr, self.typeStr, "... ",
+ det = Matrix.__dict__[self.typeStr + "Det"]
+ matrix = [8,7]
+ self.assertRaises(TypeError, det, matrix)
+
+ # Test (type IN_ARRAY2[ANY][ANY]) typemap
+ def testDetWrongSize(self):
+ "Test det function with wrong size"
+ print >>sys.stderr, self.typeStr, "... ",
+ det = Matrix.__dict__[self.typeStr + "Det"]
+ matrix = [[8,7,6], [5,4,3], [2,1,0]]
+ self.assertRaises(TypeError, det, matrix)
+
+ # Test (type IN_ARRAY2[ANY][ANY]) typemap
+ def testDetNonContainer(self):
+ "Test det function with non-container"
+ print >>sys.stderr, self.typeStr, "... ",
+ det = Matrix.__dict__[self.typeStr + "Det"]
+ self.assertRaises(TypeError, det, None)
+
+ # Test (type* IN_ARRAY2, int DIM1, int DIM2) typemap
+ def testMax(self):
+ "Test max function"
+ print >>sys.stderr, self.typeStr, "... ",
+ max = Matrix.__dict__[self.typeStr + "Max"]
+ matrix = [[6,5,4],[3,2,1]]
+ self.assertEquals(max(matrix), 6)
+
+ # Test (type* IN_ARRAY2, int DIM1, int DIM2) typemap
+ def testMaxBadList(self):
+ "Test max function with bad list"
+ print >>sys.stderr, self.typeStr, "... ",
+ max = Matrix.__dict__[self.typeStr + "Max"]
+ matrix = [[6,"five",4], ["three", 2, "one"]]
+ self.assertRaises(BadListError, max, matrix)
+
+ # Test (type* IN_ARRAY2, int DIM1, int DIM2) typemap
+ def testMaxNonContainer(self):
+ "Test max function with non-container"
+ print >>sys.stderr, self.typeStr, "... ",
+ max = Matrix.__dict__[self.typeStr + "Max"]
+ self.assertRaises(TypeError, max, None)
+
+ # Test (type* IN_ARRAY2, int DIM1, int DIM2) typemap
+ def testMaxWrongDim(self):
+ "Test max function with wrong dimensions"
+ print >>sys.stderr, self.typeStr, "... ",
+ max = Matrix.__dict__[self.typeStr + "Max"]
+ self.assertRaises(TypeError, max, [0, 1, 2, 3])
+
+ # Test (int DIM1, int DIM2, type* IN_ARRAY2) typemap
+ def testMin(self):
+ "Test min function"
+ print >>sys.stderr, self.typeStr, "... ",
+ min = Matrix.__dict__[self.typeStr + "Min"]
+ matrix = [[9,8],[7,6],[5,4]]
+ self.assertEquals(min(matrix), 4)
+
+ # Test (int DIM1, int DIM2, type* IN_ARRAY2) typemap
+ def testMinBadList(self):
+ "Test min function with bad list"
+ print >>sys.stderr, self.typeStr, "... ",
+ min = Matrix.__dict__[self.typeStr + "Min"]
+ matrix = [["nine","eight"], ["seven","six"]]
+ self.assertRaises(BadListError, min, matrix)
+
+ # Test (int DIM1, int DIM2, type* IN_ARRAY2) typemap
+ def testMinWrongDim(self):
+ "Test min function with wrong dimensions"
+ print >>sys.stderr, self.typeStr, "... ",
+ min = Matrix.__dict__[self.typeStr + "Min"]
+ self.assertRaises(TypeError, min, [1,3,5,7,9])
+
+ # Test (int DIM1, int DIM2, type* IN_ARRAY2) typemap
+ def testMinNonContainer(self):
+ "Test min function with non-container"
+ print >>sys.stderr, self.typeStr, "... ",
+ min = Matrix.__dict__[self.typeStr + "Min"]
+ self.assertRaises(TypeError, min, False)
+
+ # Test (type INPLACE_ARRAY2[ANY][ANY]) typemap
+ def testScale(self):
+ "Test scale function"
+ print >>sys.stderr, self.typeStr, "... ",
+ scale = Matrix.__dict__[self.typeStr + "Scale"]
+ matrix = np.array([[1,2,3],[2,1,2],[3,2,1]],self.typeCode)
+ scale(matrix,4)
+ self.assertEquals((matrix == [[4,8,12],[8,4,8],[12,8,4]]).all(), True)
+
+ # Test (type INPLACE_ARRAY2[ANY][ANY]) typemap
+ def testScaleWrongDim(self):
+ "Test scale function with wrong dimensions"
+ print >>sys.stderr, self.typeStr, "... ",
+ scale = Matrix.__dict__[self.typeStr + "Scale"]
+ matrix = np.array([1,2,2,1],self.typeCode)
+ self.assertRaises(TypeError, scale, matrix)
+
+ # Test (type INPLACE_ARRAY2[ANY][ANY]) typemap
+ def testScaleWrongSize(self):
+ "Test scale function with wrong size"
+ print >>sys.stderr, self.typeStr, "... ",
+ scale = Matrix.__dict__[self.typeStr + "Scale"]
+ matrix = np.array([[1,2],[2,1]],self.typeCode)
+ self.assertRaises(TypeError, scale, matrix)
+
+ # Test (type INPLACE_ARRAY2[ANY][ANY]) typemap
+ def testScaleWrongType(self):
+ "Test scale function with wrong type"
+ print >>sys.stderr, self.typeStr, "... ",
+ scale = Matrix.__dict__[self.typeStr + "Scale"]
+ matrix = np.array([[1,2,3],[2,1,2],[3,2,1]],'c')
+ self.assertRaises(TypeError, scale, matrix)
+
+ # Test (type INPLACE_ARRAY2[ANY][ANY]) typemap
+ def testScaleNonArray(self):
+ "Test scale function with non-array"
+ print >>sys.stderr, self.typeStr, "... ",
+ scale = Matrix.__dict__[self.typeStr + "Scale"]
+ matrix = [[1,2,3],[2,1,2],[3,2,1]]
+ self.assertRaises(TypeError, scale, matrix)
+
+ # Test (type* INPLACE_ARRAY2, int DIM1, int DIM2) typemap
+ def testFloor(self):
+ "Test floor function"
+ print >>sys.stderr, self.typeStr, "... ",
+ floor = Matrix.__dict__[self.typeStr + "Floor"]
+ matrix = np.array([[6,7],[8,9]],self.typeCode)
+ floor(matrix,7)
+ np.testing.assert_array_equal(matrix, np.array([[7,7],[8,9]]))
+
+ # Test (type* INPLACE_ARRAY2, int DIM1, int DIM2) typemap
+ def testFloorWrongDim(self):
+ "Test floor function with wrong dimensions"
+ print >>sys.stderr, self.typeStr, "... ",
+ floor = Matrix.__dict__[self.typeStr + "Floor"]
+ matrix = np.array([6,7,8,9],self.typeCode)
+ self.assertRaises(TypeError, floor, matrix)
+
+ # Test (type* INPLACE_ARRAY2, int DIM1, int DIM2) typemap
+ def testFloorWrongType(self):
+ "Test floor function with wrong type"
+ print >>sys.stderr, self.typeStr, "... ",
+ floor = Matrix.__dict__[self.typeStr + "Floor"]
+ matrix = np.array([[6,7], [8,9]],'c')
+ self.assertRaises(TypeError, floor, matrix)
+
+ # Test (type* INPLACE_ARRAY2, int DIM1, int DIM2) typemap
+ def testFloorNonArray(self):
+ "Test floor function with non-array"
+ print >>sys.stderr, self.typeStr, "... ",
+ floor = Matrix.__dict__[self.typeStr + "Floor"]
+ matrix = [[6,7], [8,9]]
+ self.assertRaises(TypeError, floor, matrix)
+
+ # Test (int DIM1, int DIM2, type* INPLACE_ARRAY2) typemap
+ def testCeil(self):
+ "Test ceil function"
+ print >>sys.stderr, self.typeStr, "... ",
+ ceil = Matrix.__dict__[self.typeStr + "Ceil"]
+ matrix = np.array([[1,2],[3,4]],self.typeCode)
+ ceil(matrix,3)
+ np.testing.assert_array_equal(matrix, np.array([[1,2],[3,3]]))
+
+ # Test (int DIM1, int DIM2, type* INPLACE_ARRAY2) typemap
+ def testCeilWrongDim(self):
+ "Test ceil function with wrong dimensions"
+ print >>sys.stderr, self.typeStr, "... ",
+ ceil = Matrix.__dict__[self.typeStr + "Ceil"]
+ matrix = np.array([1,2,3,4],self.typeCode)
+ self.assertRaises(TypeError, ceil, matrix)
+
+ # Test (int DIM1, int DIM2, type* INPLACE_ARRAY2) typemap
+ def testCeilWrongType(self):
+ "Test ceil function with wrong dimensions"
+ print >>sys.stderr, self.typeStr, "... ",
+ ceil = Matrix.__dict__[self.typeStr + "Ceil"]
+ matrix = np.array([[1,2], [3,4]],'c')
+ self.assertRaises(TypeError, ceil, matrix)
+
+ # Test (int DIM1, int DIM2, type* INPLACE_ARRAY2) typemap
+ def testCeilNonArray(self):
+ "Test ceil function with non-array"
+ print >>sys.stderr, self.typeStr, "... ",
+ ceil = Matrix.__dict__[self.typeStr + "Ceil"]
+ matrix = [[1,2], [3,4]]
+ self.assertRaises(TypeError, ceil, matrix)
+
+ # Test (type ARGOUT_ARRAY2[ANY][ANY]) typemap
+ def testLUSplit(self):
+ "Test luSplit function"
+ print >>sys.stderr, self.typeStr, "... ",
+ luSplit = Matrix.__dict__[self.typeStr + "LUSplit"]
+ lower, upper = luSplit([[1,2,3],[4,5,6],[7,8,9]])
+ self.assertEquals((lower == [[1,0,0],[4,5,0],[7,8,9]]).all(), True)
+ self.assertEquals((upper == [[0,2,3],[0,0,6],[0,0,0]]).all(), True)
+
+######################################################################
+
+class scharTestCase(MatrixTestCase):
+ def __init__(self, methodName="runTest"):
+ MatrixTestCase.__init__(self, methodName)
+ self.typeStr = "schar"
+ self.typeCode = "b"
+
+######################################################################
+
+class ucharTestCase(MatrixTestCase):
+ def __init__(self, methodName="runTest"):
+ MatrixTestCase.__init__(self, methodName)
+ self.typeStr = "uchar"
+ self.typeCode = "B"
+
+######################################################################
+
+class shortTestCase(MatrixTestCase):
+ def __init__(self, methodName="runTest"):
+ MatrixTestCase.__init__(self, methodName)
+ self.typeStr = "short"
+ self.typeCode = "h"
+
+######################################################################
+
+class ushortTestCase(MatrixTestCase):
+ def __init__(self, methodName="runTest"):
+ MatrixTestCase.__init__(self, methodName)
+ self.typeStr = "ushort"
+ self.typeCode = "H"
+
+######################################################################
+
+class intTestCase(MatrixTestCase):
+ def __init__(self, methodName="runTest"):
+ MatrixTestCase.__init__(self, methodName)
+ self.typeStr = "int"
+ self.typeCode = "i"
+
+######################################################################
+
+class uintTestCase(MatrixTestCase):
+ def __init__(self, methodName="runTest"):
+ MatrixTestCase.__init__(self, methodName)
+ self.typeStr = "uint"
+ self.typeCode = "I"
+
+######################################################################
+
+class longTestCase(MatrixTestCase):
+ def __init__(self, methodName="runTest"):
+ MatrixTestCase.__init__(self, methodName)
+ self.typeStr = "long"
+ self.typeCode = "l"
+
+######################################################################
+
+class ulongTestCase(MatrixTestCase):
+ def __init__(self, methodName="runTest"):
+ MatrixTestCase.__init__(self, methodName)
+ self.typeStr = "ulong"
+ self.typeCode = "L"
+
+######################################################################
+
+class longLongTestCase(MatrixTestCase):
+ def __init__(self, methodName="runTest"):
+ MatrixTestCase.__init__(self, methodName)
+ self.typeStr = "longLong"
+ self.typeCode = "q"
+
+######################################################################
+
+class ulongLongTestCase(MatrixTestCase):
+ def __init__(self, methodName="runTest"):
+ MatrixTestCase.__init__(self, methodName)
+ self.typeStr = "ulongLong"
+ self.typeCode = "Q"
+
+######################################################################
+
+class floatTestCase(MatrixTestCase):
+ def __init__(self, methodName="runTest"):
+ MatrixTestCase.__init__(self, methodName)
+ self.typeStr = "float"
+ self.typeCode = "f"
+
+######################################################################
+
+class doubleTestCase(MatrixTestCase):
+ def __init__(self, methodName="runTest"):
+ MatrixTestCase.__init__(self, methodName)
+ self.typeStr = "double"
+ self.typeCode = "d"
+
+######################################################################
+
+if __name__ == "__main__":
+
+ # Build the test suite
+ suite = unittest.TestSuite()
+ suite.addTest(unittest.makeSuite( scharTestCase))
+ suite.addTest(unittest.makeSuite( ucharTestCase))
+ suite.addTest(unittest.makeSuite( shortTestCase))
+ suite.addTest(unittest.makeSuite( ushortTestCase))
+ suite.addTest(unittest.makeSuite( intTestCase))
+ suite.addTest(unittest.makeSuite( uintTestCase))
+ suite.addTest(unittest.makeSuite( longTestCase))
+ suite.addTest(unittest.makeSuite( ulongTestCase))
+ suite.addTest(unittest.makeSuite( longLongTestCase))
+ suite.addTest(unittest.makeSuite(ulongLongTestCase))
+ suite.addTest(unittest.makeSuite( floatTestCase))
+ suite.addTest(unittest.makeSuite( doubleTestCase))
+
+ # Execute the test suite
+ print "Testing 2D Functions of Module Matrix"
+ print "NumPy version", np.__version__
+ print
+ result = unittest.TextTestRunner(verbosity=2).run(suite)
+ sys.exit(len(result.errors) + len(result.failures))
diff --git a/doc/swig/test/testTensor.py b/doc/swig/test/testTensor.py
new file mode 100755
index 000000000..3d0ce097e
--- /dev/null
+++ b/doc/swig/test/testTensor.py
@@ -0,0 +1,401 @@
+#! /usr/bin/env python
+
+# System imports
+from distutils.util import get_platform
+from math import sqrt
+import os
+import sys
+import unittest
+
+# Import NumPy
+import numpy as np
+major, minor = [ int(d) for d in np.__version__.split(".")[:2] ]
+if major == 0: BadListError = TypeError
+else: BadListError = ValueError
+
+import Tensor
+
+######################################################################
+
+class TensorTestCase(unittest.TestCase):
+
+ def __init__(self, methodName="runTests"):
+ unittest.TestCase.__init__(self, methodName)
+ self.typeStr = "double"
+ self.typeCode = "d"
+ self.result = sqrt(28.0/8)
+
+ # Test (type IN_ARRAY3[ANY][ANY][ANY]) typemap
+ def testNorm(self):
+ "Test norm function"
+ print >>sys.stderr, self.typeStr, "... ",
+ norm = Tensor.__dict__[self.typeStr + "Norm"]
+ tensor = [[[0,1], [2,3]],
+ [[3,2], [1,0]]]
+ if isinstance(self.result, int):
+ self.assertEquals(norm(tensor), self.result)
+ else:
+ self.assertAlmostEqual(norm(tensor), self.result, 6)
+
+ # Test (type IN_ARRAY3[ANY][ANY][ANY]) typemap
+ def testNormBadList(self):
+ "Test norm function with bad list"
+ print >>sys.stderr, self.typeStr, "... ",
+ norm = Tensor.__dict__[self.typeStr + "Norm"]
+ tensor = [[[0,"one"],[2,3]],
+ [[3,"two"],[1,0]]]
+ self.assertRaises(BadListError, norm, tensor)
+
+ # Test (type IN_ARRAY3[ANY][ANY][ANY]) typemap
+ def testNormWrongDim(self):
+ "Test norm function with wrong dimensions"
+ print >>sys.stderr, self.typeStr, "... ",
+ norm = Tensor.__dict__[self.typeStr + "Norm"]
+ tensor = [[0,1,2,3],
+ [3,2,1,0]]
+ self.assertRaises(TypeError, norm, tensor)
+
+ # Test (type IN_ARRAY3[ANY][ANY][ANY]) typemap
+ def testNormWrongSize(self):
+ "Test norm function with wrong size"
+ print >>sys.stderr, self.typeStr, "... ",
+ norm = Tensor.__dict__[self.typeStr + "Norm"]
+ tensor = [[[0,1,0], [2,3,2]],
+ [[3,2,3], [1,0,1]]]
+ self.assertRaises(TypeError, norm, tensor)
+
+ # Test (type IN_ARRAY3[ANY][ANY][ANY]) typemap
+ def testNormNonContainer(self):
+ "Test norm function with non-container"
+ print >>sys.stderr, self.typeStr, "... ",
+ norm = Tensor.__dict__[self.typeStr + "Norm"]
+ self.assertRaises(TypeError, norm, None)
+
+ # Test (type* IN_ARRAY3, int DIM1, int DIM2, int DIM3) typemap
+ def testMax(self):
+ "Test max function"
+ print >>sys.stderr, self.typeStr, "... ",
+ max = Tensor.__dict__[self.typeStr + "Max"]
+ tensor = [[[1,2], [3,4]],
+ [[5,6], [7,8]]]
+ self.assertEquals(max(tensor), 8)
+
+ # Test (type* IN_ARRAY3, int DIM1, int DIM2, int DIM3) typemap
+ def testMaxBadList(self):
+ "Test max function with bad list"
+ print >>sys.stderr, self.typeStr, "... ",
+ max = Tensor.__dict__[self.typeStr + "Max"]
+ tensor = [[[1,"two"], [3,4]],
+ [[5,"six"], [7,8]]]
+ self.assertRaises(BadListError, max, tensor)
+
+ # Test (type* IN_ARRAY3, int DIM1, int DIM2, int DIM3) typemap
+ def testMaxNonContainer(self):
+ "Test max function with non-container"
+ print >>sys.stderr, self.typeStr, "... ",
+ max = Tensor.__dict__[self.typeStr + "Max"]
+ self.assertRaises(TypeError, max, None)
+
+ # Test (type* IN_ARRAY3, int DIM1, int DIM2, int DIM3) typemap
+ def testMaxWrongDim(self):
+ "Test max function with wrong dimensions"
+ print >>sys.stderr, self.typeStr, "... ",
+ max = Tensor.__dict__[self.typeStr + "Max"]
+ self.assertRaises(TypeError, max, [0, -1, 2, -3])
+
+ # Test (int DIM1, int DIM2, int DIM3, type* IN_ARRAY3) typemap
+ def testMin(self):
+ "Test min function"
+ print >>sys.stderr, self.typeStr, "... ",
+ min = Tensor.__dict__[self.typeStr + "Min"]
+ tensor = [[[9,8], [7,6]],
+ [[5,4], [3,2]]]
+ self.assertEquals(min(tensor), 2)
+
+ # Test (int DIM1, int DIM2, int DIM3, type* IN_ARRAY3) typemap
+ def testMinBadList(self):
+ "Test min function with bad list"
+ print >>sys.stderr, self.typeStr, "... ",
+ min = Tensor.__dict__[self.typeStr + "Min"]
+ tensor = [[["nine",8], [7,6]],
+ [["five",4], [3,2]]]
+ self.assertRaises(BadListError, min, tensor)
+
+ # Test (int DIM1, int DIM2, int DIM3, type* IN_ARRAY3) typemap
+ def testMinNonContainer(self):
+ "Test min function with non-container"
+ print >>sys.stderr, self.typeStr, "... ",
+ min = Tensor.__dict__[self.typeStr + "Min"]
+ self.assertRaises(TypeError, min, True)
+
+ # Test (int DIM1, int DIM2, int DIM3, type* IN_ARRAY3) typemap
+ def testMinWrongDim(self):
+ "Test min function with wrong dimensions"
+ print >>sys.stderr, self.typeStr, "... ",
+ min = Tensor.__dict__[self.typeStr + "Min"]
+ self.assertRaises(TypeError, min, [[1,3],[5,7]])
+
+ # Test (type INPLACE_ARRAY3[ANY][ANY][ANY]) typemap
+ def testScale(self):
+ "Test scale function"
+ print >>sys.stderr, self.typeStr, "... ",
+ scale = Tensor.__dict__[self.typeStr + "Scale"]
+ tensor = np.array([[[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]]],self.typeCode)
+ scale(tensor,4)
+ self.assertEquals((tensor == [[[4,0,4], [0,4,0], [4,0,4]],
+ [[0,4,0], [4,0,4], [0,4,0]],
+ [[4,0,4], [0,4,0], [4,0,4]]]).all(), True)
+
+ # Test (type INPLACE_ARRAY3[ANY][ANY][ANY]) typemap
+ def testScaleWrongType(self):
+ "Test scale function with wrong type"
+ print >>sys.stderr, self.typeStr, "... ",
+ scale = Tensor.__dict__[self.typeStr + "Scale"]
+ tensor = np.array([[[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]]],'c')
+ self.assertRaises(TypeError, scale, tensor)
+
+ # Test (type INPLACE_ARRAY3[ANY][ANY][ANY]) typemap
+ def testScaleWrongDim(self):
+ "Test scale function with wrong dimensions"
+ print >>sys.stderr, self.typeStr, "... ",
+ scale = Tensor.__dict__[self.typeStr + "Scale"]
+ tensor = np.array([[1,0,1], [0,1,0], [1,0,1],
+ [0,1,0], [1,0,1], [0,1,0]],self.typeCode)
+ self.assertRaises(TypeError, scale, tensor)
+
+ # Test (type INPLACE_ARRAY3[ANY][ANY][ANY]) typemap
+ def testScaleWrongSize(self):
+ "Test scale function with wrong size"
+ print >>sys.stderr, self.typeStr, "... ",
+ scale = Tensor.__dict__[self.typeStr + "Scale"]
+ tensor = np.array([[[1,0], [0,1], [1,0]],
+ [[0,1], [1,0], [0,1]],
+ [[1,0], [0,1], [1,0]]],self.typeCode)
+ self.assertRaises(TypeError, scale, tensor)
+
+ # Test (type INPLACE_ARRAY3[ANY][ANY][ANY]) typemap
+ def testScaleNonArray(self):
+ "Test scale function with non-array"
+ print >>sys.stderr, self.typeStr, "... ",
+ scale = Tensor.__dict__[self.typeStr + "Scale"]
+ self.assertRaises(TypeError, scale, True)
+
+ # Test (type* INPLACE_ARRAY3, int DIM1, int DIM2, int DIM3) typemap
+ def testFloor(self):
+ "Test floor function"
+ print >>sys.stderr, self.typeStr, "... ",
+ floor = Tensor.__dict__[self.typeStr + "Floor"]
+ tensor = np.array([[[1,2], [3,4]],
+ [[5,6], [7,8]]],self.typeCode)
+ floor(tensor,4)
+ np.testing.assert_array_equal(tensor, np.array([[[4,4], [4,4]],
+ [[5,6], [7,8]]]))
+
+ # Test (type* INPLACE_ARRAY3, int DIM1, int DIM2, int DIM3) typemap
+ def testFloorWrongType(self):
+ "Test floor function with wrong type"
+ print >>sys.stderr, self.typeStr, "... ",
+ floor = Tensor.__dict__[self.typeStr + "Floor"]
+ tensor = np.array([[[1,2], [3,4]],
+ [[5,6], [7,8]]],'c')
+ self.assertRaises(TypeError, floor, tensor)
+
+ # Test (type* INPLACE_ARRAY3, int DIM1, int DIM2, int DIM3) typemap
+ def testFloorWrongDim(self):
+ "Test floor function with wrong type"
+ print >>sys.stderr, self.typeStr, "... ",
+ floor = Tensor.__dict__[self.typeStr + "Floor"]
+ tensor = np.array([[1,2], [3,4], [5,6], [7,8]],self.typeCode)
+ self.assertRaises(TypeError, floor, tensor)
+
+ # Test (type* INPLACE_ARRAY3, int DIM1, int DIM2, int DIM3) typemap
+ def testFloorNonArray(self):
+ "Test floor function with non-array"
+ print >>sys.stderr, self.typeStr, "... ",
+ floor = Tensor.__dict__[self.typeStr + "Floor"]
+ self.assertRaises(TypeError, floor, object)
+
+ # Test (int DIM1, int DIM2, int DIM3, type* INPLACE_ARRAY3) typemap
+ def testCeil(self):
+ "Test ceil function"
+ print >>sys.stderr, self.typeStr, "... ",
+ ceil = Tensor.__dict__[self.typeStr + "Ceil"]
+ tensor = np.array([[[9,8], [7,6]],
+ [[5,4], [3,2]]],self.typeCode)
+ ceil(tensor,5)
+ np.testing.assert_array_equal(tensor, np.array([[[5,5], [5,5]],
+ [[5,4], [3,2]]]))
+
+ # Test (int DIM1, int DIM2, int DIM3, type* INPLACE_ARRAY3) typemap
+ def testCeilWrongType(self):
+ "Test ceil function with wrong type"
+ print >>sys.stderr, self.typeStr, "... ",
+ ceil = Tensor.__dict__[self.typeStr + "Ceil"]
+ tensor = np.array([[[9,8], [7,6]],
+ [[5,4], [3,2]]],'c')
+ self.assertRaises(TypeError, ceil, tensor)
+
+ # Test (int DIM1, int DIM2, int DIM3, type* INPLACE_ARRAY3) typemap
+ def testCeilWrongDim(self):
+ "Test ceil function with wrong dimensions"
+ print >>sys.stderr, self.typeStr, "... ",
+ ceil = Tensor.__dict__[self.typeStr + "Ceil"]
+ tensor = np.array([[9,8], [7,6], [5,4], [3,2]], self.typeCode)
+ self.assertRaises(TypeError, ceil, tensor)
+
+ # Test (int DIM1, int DIM2, int DIM3, type* INPLACE_ARRAY3) typemap
+ def testCeilNonArray(self):
+ "Test ceil function with non-array"
+ print >>sys.stderr, self.typeStr, "... ",
+ ceil = Tensor.__dict__[self.typeStr + "Ceil"]
+ tensor = [[[9,8], [7,6]],
+ [[5,4], [3,2]]]
+ self.assertRaises(TypeError, ceil, tensor)
+
+ # Test (type ARGOUT_ARRAY3[ANY][ANY][ANY]) typemap
+ def testLUSplit(self):
+ "Test luSplit function"
+ print >>sys.stderr, self.typeStr, "... ",
+ luSplit = Tensor.__dict__[self.typeStr + "LUSplit"]
+ lower, upper = luSplit([[[1,1], [1,1]],
+ [[1,1], [1,1]]])
+ self.assertEquals((lower == [[[1,1], [1,0]],
+ [[1,0], [0,0]]]).all(), True)
+ self.assertEquals((upper == [[[0,0], [0,1]],
+ [[0,1], [1,1]]]).all(), True)
+
+######################################################################
+
+class scharTestCase(TensorTestCase):
+ def __init__(self, methodName="runTest"):
+ TensorTestCase.__init__(self, methodName)
+ self.typeStr = "schar"
+ self.typeCode = "b"
+ self.result = int(self.result)
+
+######################################################################
+
+class ucharTestCase(TensorTestCase):
+ def __init__(self, methodName="runTest"):
+ TensorTestCase.__init__(self, methodName)
+ self.typeStr = "uchar"
+ self.typeCode = "B"
+ self.result = int(self.result)
+
+######################################################################
+
+class shortTestCase(TensorTestCase):
+ def __init__(self, methodName="runTest"):
+ TensorTestCase.__init__(self, methodName)
+ self.typeStr = "short"
+ self.typeCode = "h"
+ self.result = int(self.result)
+
+######################################################################
+
+class ushortTestCase(TensorTestCase):
+ def __init__(self, methodName="runTest"):
+ TensorTestCase.__init__(self, methodName)
+ self.typeStr = "ushort"
+ self.typeCode = "H"
+ self.result = int(self.result)
+
+######################################################################
+
+class intTestCase(TensorTestCase):
+ def __init__(self, methodName="runTest"):
+ TensorTestCase.__init__(self, methodName)
+ self.typeStr = "int"
+ self.typeCode = "i"
+ self.result = int(self.result)
+
+######################################################################
+
+class uintTestCase(TensorTestCase):
+ def __init__(self, methodName="runTest"):
+ TensorTestCase.__init__(self, methodName)
+ self.typeStr = "uint"
+ self.typeCode = "I"
+ self.result = int(self.result)
+
+######################################################################
+
+class longTestCase(TensorTestCase):
+ def __init__(self, methodName="runTest"):
+ TensorTestCase.__init__(self, methodName)
+ self.typeStr = "long"
+ self.typeCode = "l"
+ self.result = int(self.result)
+
+######################################################################
+
+class ulongTestCase(TensorTestCase):
+ def __init__(self, methodName="runTest"):
+ TensorTestCase.__init__(self, methodName)
+ self.typeStr = "ulong"
+ self.typeCode = "L"
+ self.result = int(self.result)
+
+######################################################################
+
+class longLongTestCase(TensorTestCase):
+ def __init__(self, methodName="runTest"):
+ TensorTestCase.__init__(self, methodName)
+ self.typeStr = "longLong"
+ self.typeCode = "q"
+ self.result = int(self.result)
+
+######################################################################
+
+class ulongLongTestCase(TensorTestCase):
+ def __init__(self, methodName="runTest"):
+ TensorTestCase.__init__(self, methodName)
+ self.typeStr = "ulongLong"
+ self.typeCode = "Q"
+ self.result = int(self.result)
+
+######################################################################
+
+class floatTestCase(TensorTestCase):
+ def __init__(self, methodName="runTest"):
+ TensorTestCase.__init__(self, methodName)
+ self.typeStr = "float"
+ self.typeCode = "f"
+
+######################################################################
+
+class doubleTestCase(TensorTestCase):
+ def __init__(self, methodName="runTest"):
+ TensorTestCase.__init__(self, methodName)
+ self.typeStr = "double"
+ self.typeCode = "d"
+
+######################################################################
+
+if __name__ == "__main__":
+
+ # Build the test suite
+ suite = unittest.TestSuite()
+ suite.addTest(unittest.makeSuite( scharTestCase))
+ suite.addTest(unittest.makeSuite( ucharTestCase))
+ suite.addTest(unittest.makeSuite( shortTestCase))
+ suite.addTest(unittest.makeSuite( ushortTestCase))
+ suite.addTest(unittest.makeSuite( intTestCase))
+ suite.addTest(unittest.makeSuite( uintTestCase))
+ suite.addTest(unittest.makeSuite( longTestCase))
+ suite.addTest(unittest.makeSuite( ulongTestCase))
+ suite.addTest(unittest.makeSuite( longLongTestCase))
+ suite.addTest(unittest.makeSuite(ulongLongTestCase))
+ suite.addTest(unittest.makeSuite( floatTestCase))
+ suite.addTest(unittest.makeSuite( doubleTestCase))
+
+ # Execute the test suite
+ print "Testing 3D Functions of Module Tensor"
+ print "NumPy version", np.__version__
+ print
+ result = unittest.TextTestRunner(verbosity=2).run(suite)
+ sys.exit(len(result.errors) + len(result.failures))
diff --git a/doc/swig/test/testVector.py b/doc/swig/test/testVector.py
new file mode 100755
index 000000000..2ee918389
--- /dev/null
+++ b/doc/swig/test/testVector.py
@@ -0,0 +1,380 @@
+#! /usr/bin/env python
+
+# System imports
+from distutils.util import get_platform
+import os
+import sys
+import unittest
+
+# Import NumPy
+import numpy as np
+major, minor = [ int(d) for d in np.__version__.split(".")[:2] ]
+if major == 0: BadListError = TypeError
+else: BadListError = ValueError
+
+import Vector
+
+######################################################################
+
+class VectorTestCase(unittest.TestCase):
+
+ def __init__(self, methodName="runTest"):
+ unittest.TestCase.__init__(self, methodName)
+ self.typeStr = "double"
+ self.typeCode = "d"
+
+ # Test the (type IN_ARRAY1[ANY]) typemap
+ def testLength(self):
+ "Test length function"
+ print >>sys.stderr, self.typeStr, "... ",
+ length = Vector.__dict__[self.typeStr + "Length"]
+ self.assertEquals(length([5, 12, 0]), 13)
+
+ # Test the (type IN_ARRAY1[ANY]) typemap
+ def testLengthBadList(self):
+ "Test length function with bad list"
+ print >>sys.stderr, self.typeStr, "... ",
+ length = Vector.__dict__[self.typeStr + "Length"]
+ self.assertRaises(BadListError, length, [5, "twelve", 0])
+
+ # Test the (type IN_ARRAY1[ANY]) typemap
+ def testLengthWrongSize(self):
+ "Test length function with wrong size"
+ print >>sys.stderr, self.typeStr, "... ",
+ length = Vector.__dict__[self.typeStr + "Length"]
+ self.assertRaises(TypeError, length, [5, 12])
+
+ # Test the (type IN_ARRAY1[ANY]) typemap
+ def testLengthWrongDim(self):
+ "Test length function with wrong dimensions"
+ print >>sys.stderr, self.typeStr, "... ",
+ length = Vector.__dict__[self.typeStr + "Length"]
+ self.assertRaises(TypeError, length, [[1,2], [3,4]])
+
+ # Test the (type IN_ARRAY1[ANY]) typemap
+ def testLengthNonContainer(self):
+ "Test length function with non-container"
+ print >>sys.stderr, self.typeStr, "... ",
+ length = Vector.__dict__[self.typeStr + "Length"]
+ self.assertRaises(TypeError, length, None)
+
+ # Test the (type* IN_ARRAY1, int DIM1) typemap
+ def testProd(self):
+ "Test prod function"
+ print >>sys.stderr, self.typeStr, "... ",
+ prod = Vector.__dict__[self.typeStr + "Prod"]
+ self.assertEquals(prod([1,2,3,4]), 24)
+
+ # Test the (type* IN_ARRAY1, int DIM1) typemap
+ def testProdBadList(self):
+ "Test prod function with bad list"
+ print >>sys.stderr, self.typeStr, "... ",
+ prod = Vector.__dict__[self.typeStr + "Prod"]
+ self.assertRaises(BadListError, prod, [[1,"two"], ["e","pi"]])
+
+ # Test the (type* IN_ARRAY1, int DIM1) typemap
+ def testProdWrongDim(self):
+ "Test prod function with wrong dimensions"
+ print >>sys.stderr, self.typeStr, "... ",
+ prod = Vector.__dict__[self.typeStr + "Prod"]
+ self.assertRaises(TypeError, prod, [[1,2], [8,9]])
+
+ # Test the (type* IN_ARRAY1, int DIM1) typemap
+ def testProdNonContainer(self):
+ "Test prod function with non-container"
+ print >>sys.stderr, self.typeStr, "... ",
+ prod = Vector.__dict__[self.typeStr + "Prod"]
+ self.assertRaises(TypeError, prod, None)
+
+ # Test the (int DIM1, type* IN_ARRAY1) typemap
+ def testSum(self):
+ "Test sum function"
+ print >>sys.stderr, self.typeStr, "... ",
+ sum = Vector.__dict__[self.typeStr + "Sum"]
+ self.assertEquals(sum([5,6,7,8]), 26)
+
+ # Test the (int DIM1, type* IN_ARRAY1) typemap
+ def testSumBadList(self):
+ "Test sum function with bad list"
+ print >>sys.stderr, self.typeStr, "... ",
+ sum = Vector.__dict__[self.typeStr + "Sum"]
+ self.assertRaises(BadListError, sum, [3,4, 5, "pi"])
+
+ # Test the (int DIM1, type* IN_ARRAY1) typemap
+ def testSumWrongDim(self):
+ "Test sum function with wrong dimensions"
+ print >>sys.stderr, self.typeStr, "... ",
+ sum = Vector.__dict__[self.typeStr + "Sum"]
+ self.assertRaises(TypeError, sum, [[3,4], [5,6]])
+
+ # Test the (int DIM1, type* IN_ARRAY1) typemap
+ def testSumNonContainer(self):
+ "Test sum function with non-container"
+ print >>sys.stderr, self.typeStr, "... ",
+ sum = Vector.__dict__[self.typeStr + "Sum"]
+ self.assertRaises(TypeError, sum, True)
+
+ # Test the (type INPLACE_ARRAY1[ANY]) typemap
+ def testReverse(self):
+ "Test reverse function"
+ print >>sys.stderr, self.typeStr, "... ",
+ reverse = Vector.__dict__[self.typeStr + "Reverse"]
+ vector = np.array([1,2,4],self.typeCode)
+ reverse(vector)
+ self.assertEquals((vector == [4,2,1]).all(), True)
+
+ # Test the (type INPLACE_ARRAY1[ANY]) typemap
+ def testReverseWrongDim(self):
+ "Test reverse function with wrong dimensions"
+ print >>sys.stderr, self.typeStr, "... ",
+ reverse = Vector.__dict__[self.typeStr + "Reverse"]
+ vector = np.array([[1,2], [3,4]],self.typeCode)
+ self.assertRaises(TypeError, reverse, vector)
+
+ # Test the (type INPLACE_ARRAY1[ANY]) typemap
+ def testReverseWrongSize(self):
+ "Test reverse function with wrong size"
+ print >>sys.stderr, self.typeStr, "... ",
+ reverse = Vector.__dict__[self.typeStr + "Reverse"]
+ vector = np.array([9,8,7,6,5,4],self.typeCode)
+ self.assertRaises(TypeError, reverse, vector)
+
+ # Test the (type INPLACE_ARRAY1[ANY]) typemap
+ def testReverseWrongType(self):
+ "Test reverse function with wrong type"
+ print >>sys.stderr, self.typeStr, "... ",
+ reverse = Vector.__dict__[self.typeStr + "Reverse"]
+ vector = np.array([1,2,4],'c')
+ self.assertRaises(TypeError, reverse, vector)
+
+ # Test the (type INPLACE_ARRAY1[ANY]) typemap
+ def testReverseNonArray(self):
+ "Test reverse function with non-array"
+ print >>sys.stderr, self.typeStr, "... ",
+ reverse = Vector.__dict__[self.typeStr + "Reverse"]
+ self.assertRaises(TypeError, reverse, [2,4,6])
+
+ # Test the (type* INPLACE_ARRAY1, int DIM1) typemap
+ def testOnes(self):
+ "Test ones function"
+ print >>sys.stderr, self.typeStr, "... ",
+ ones = Vector.__dict__[self.typeStr + "Ones"]
+ vector = np.zeros(5,self.typeCode)
+ ones(vector)
+ np.testing.assert_array_equal(vector, np.array([1,1,1,1,1]))
+
+ # Test the (type* INPLACE_ARRAY1, int DIM1) typemap
+ def testOnesWrongDim(self):
+ "Test ones function with wrong dimensions"
+ print >>sys.stderr, self.typeStr, "... ",
+ ones = Vector.__dict__[self.typeStr + "Ones"]
+ vector = np.zeros((5,5),self.typeCode)
+ self.assertRaises(TypeError, ones, vector)
+
+ # Test the (type* INPLACE_ARRAY1, int DIM1) typemap
+ def testOnesWrongType(self):
+ "Test ones function with wrong type"
+ print >>sys.stderr, self.typeStr, "... ",
+ ones = Vector.__dict__[self.typeStr + "Ones"]
+ vector = np.zeros((5,5),'c')
+ self.assertRaises(TypeError, ones, vector)
+
+ # Test the (type* INPLACE_ARRAY1, int DIM1) typemap
+ def testOnesNonArray(self):
+ "Test ones function with non-array"
+ print >>sys.stderr, self.typeStr, "... ",
+ ones = Vector.__dict__[self.typeStr + "Ones"]
+ self.assertRaises(TypeError, ones, [2,4,6,8])
+
+ # Test the (int DIM1, type* INPLACE_ARRAY1) typemap
+ def testZeros(self):
+ "Test zeros function"
+ print >>sys.stderr, self.typeStr, "... ",
+ zeros = Vector.__dict__[self.typeStr + "Zeros"]
+ vector = np.ones(5,self.typeCode)
+ zeros(vector)
+ np.testing.assert_array_equal(vector, np.array([0,0,0,0,0]))
+
+ # Test the (int DIM1, type* INPLACE_ARRAY1) typemap
+ def testZerosWrongDim(self):
+ "Test zeros function with wrong dimensions"
+ print >>sys.stderr, self.typeStr, "... ",
+ zeros = Vector.__dict__[self.typeStr + "Zeros"]
+ vector = np.ones((5,5),self.typeCode)
+ self.assertRaises(TypeError, zeros, vector)
+
+ # Test the (int DIM1, type* INPLACE_ARRAY1) typemap
+ def testZerosWrongType(self):
+ "Test zeros function with wrong type"
+ print >>sys.stderr, self.typeStr, "... ",
+ zeros = Vector.__dict__[self.typeStr + "Zeros"]
+ vector = np.ones(6,'c')
+ self.assertRaises(TypeError, zeros, vector)
+
+ # Test the (int DIM1, type* INPLACE_ARRAY1) typemap
+ def testZerosNonArray(self):
+ "Test zeros function with non-array"
+ print >>sys.stderr, self.typeStr, "... ",
+ zeros = Vector.__dict__[self.typeStr + "Zeros"]
+ self.assertRaises(TypeError, zeros, [1,3,5,7,9])
+
+ # Test the (type ARGOUT_ARRAY1[ANY]) typemap
+ def testEOSplit(self):
+ "Test eoSplit function"
+ print >>sys.stderr, self.typeStr, "... ",
+ eoSplit = Vector.__dict__[self.typeStr + "EOSplit"]
+ even, odd = eoSplit([1,2,3])
+ self.assertEquals((even == [1,0,3]).all(), True)
+ self.assertEquals((odd == [0,2,0]).all(), True)
+
+ # Test the (type* ARGOUT_ARRAY1, int DIM1) typemap
+ def testTwos(self):
+ "Test twos function"
+ print >>sys.stderr, self.typeStr, "... ",
+ twos = Vector.__dict__[self.typeStr + "Twos"]
+ vector = twos(5)
+ self.assertEquals((vector == [2,2,2,2,2]).all(), True)
+
+ # Test the (type* ARGOUT_ARRAY1, int DIM1) typemap
+ def testTwosNonInt(self):
+ "Test twos function with non-integer dimension"
+ print >>sys.stderr, self.typeStr, "... ",
+ twos = Vector.__dict__[self.typeStr + "Twos"]
+ self.assertRaises(TypeError, twos, 5.0)
+
+ # Test the (int DIM1, type* ARGOUT_ARRAY1) typemap
+ def testThrees(self):
+ "Test threes function"
+ print >>sys.stderr, self.typeStr, "... ",
+ threes = Vector.__dict__[self.typeStr + "Threes"]
+ vector = threes(6)
+ self.assertEquals((vector == [3,3,3,3,3,3]).all(), True)
+
+ # Test the (type* ARGOUT_ARRAY1, int DIM1) typemap
+ def testThreesNonInt(self):
+ "Test threes function with non-integer dimension"
+ print >>sys.stderr, self.typeStr, "... ",
+ threes = Vector.__dict__[self.typeStr + "Threes"]
+ self.assertRaises(TypeError, threes, "threes")
+
+######################################################################
+
+class scharTestCase(VectorTestCase):
+ def __init__(self, methodName="runTest"):
+ VectorTestCase.__init__(self, methodName)
+ self.typeStr = "schar"
+ self.typeCode = "b"
+
+######################################################################
+
+class ucharTestCase(VectorTestCase):
+ def __init__(self, methodName="runTest"):
+ VectorTestCase.__init__(self, methodName)
+ self.typeStr = "uchar"
+ self.typeCode = "B"
+
+######################################################################
+
+class shortTestCase(VectorTestCase):
+ def __init__(self, methodName="runTest"):
+ VectorTestCase.__init__(self, methodName)
+ self.typeStr = "short"
+ self.typeCode = "h"
+
+######################################################################
+
+class ushortTestCase(VectorTestCase):
+ def __init__(self, methodName="runTest"):
+ VectorTestCase.__init__(self, methodName)
+ self.typeStr = "ushort"
+ self.typeCode = "H"
+
+######################################################################
+
+class intTestCase(VectorTestCase):
+ def __init__(self, methodName="runTest"):
+ VectorTestCase.__init__(self, methodName)
+ self.typeStr = "int"
+ self.typeCode = "i"
+
+######################################################################
+
+class uintTestCase(VectorTestCase):
+ def __init__(self, methodName="runTest"):
+ VectorTestCase.__init__(self, methodName)
+ self.typeStr = "uint"
+ self.typeCode = "I"
+
+######################################################################
+
+class longTestCase(VectorTestCase):
+ def __init__(self, methodName="runTest"):
+ VectorTestCase.__init__(self, methodName)
+ self.typeStr = "long"
+ self.typeCode = "l"
+
+######################################################################
+
+class ulongTestCase(VectorTestCase):
+ def __init__(self, methodName="runTest"):
+ VectorTestCase.__init__(self, methodName)
+ self.typeStr = "ulong"
+ self.typeCode = "L"
+
+######################################################################
+
+class longLongTestCase(VectorTestCase):
+ def __init__(self, methodName="runTest"):
+ VectorTestCase.__init__(self, methodName)
+ self.typeStr = "longLong"
+ self.typeCode = "q"
+
+######################################################################
+
+class ulongLongTestCase(VectorTestCase):
+ def __init__(self, methodName="runTest"):
+ VectorTestCase.__init__(self, methodName)
+ self.typeStr = "ulongLong"
+ self.typeCode = "Q"
+
+######################################################################
+
+class floatTestCase(VectorTestCase):
+ def __init__(self, methodName="runTest"):
+ VectorTestCase.__init__(self, methodName)
+ self.typeStr = "float"
+ self.typeCode = "f"
+
+######################################################################
+
+class doubleTestCase(VectorTestCase):
+ def __init__(self, methodName="runTest"):
+ VectorTestCase.__init__(self, methodName)
+ self.typeStr = "double"
+ self.typeCode = "d"
+
+######################################################################
+
+if __name__ == "__main__":
+
+ # Build the test suite
+ suite = unittest.TestSuite()
+ suite.addTest(unittest.makeSuite( scharTestCase))
+ suite.addTest(unittest.makeSuite( ucharTestCase))
+ suite.addTest(unittest.makeSuite( shortTestCase))
+ suite.addTest(unittest.makeSuite( ushortTestCase))
+ suite.addTest(unittest.makeSuite( intTestCase))
+ suite.addTest(unittest.makeSuite( uintTestCase))
+ suite.addTest(unittest.makeSuite( longTestCase))
+ suite.addTest(unittest.makeSuite( ulongTestCase))
+ suite.addTest(unittest.makeSuite( longLongTestCase))
+ suite.addTest(unittest.makeSuite(ulongLongTestCase))
+ suite.addTest(unittest.makeSuite( floatTestCase))
+ suite.addTest(unittest.makeSuite( doubleTestCase))
+
+ # Execute the test suite
+ print "Testing 1D Functions of Module Vector"
+ print "NumPy version", np.__version__
+ print
+ result = unittest.TextTestRunner(verbosity=2).run(suite)
+ sys.exit(len(result.errors) + len(result.failures))