summaryrefslogtreecommitdiff
path: root/numpy
diff options
context:
space:
mode:
Diffstat (limited to 'numpy')
-rw-r--r--numpy/doc/swig/doc/numpy_swig.html122
-rw-r--r--numpy/doc/swig/doc/numpy_swig.pdfbin163324 -> 166822 bytes
-rw-r--r--numpy/doc/swig/doc/numpy_swig.txt61
-rw-r--r--numpy/doc/swig/doc/testing.pdfbin72687 -> 72439 bytes
-rw-r--r--numpy/doc/swig/numpy.i272
-rw-r--r--numpy/doc/swig/test/Array.i107
-rw-r--r--numpy/doc/swig/test/Array1.cxx131
-rw-r--r--numpy/doc/swig/test/Array1.h55
-rw-r--r--numpy/doc/swig/test/Array2.cxx168
-rw-r--r--numpy/doc/swig/test/Array2.h63
-rw-r--r--numpy/doc/swig/test/Makefile8
-rwxr-xr-xnumpy/doc/swig/test/setup.py12
-rwxr-xr-xnumpy/doc/swig/test/testArray.py285
13 files changed, 1137 insertions, 147 deletions
diff --git a/numpy/doc/swig/doc/numpy_swig.html b/numpy/doc/swig/doc/numpy_swig.html
index 7da4f57fc..93a576001 100644
--- a/numpy/doc/swig/doc/numpy_swig.html
+++ b/numpy/doc/swig/doc/numpy_swig.html
@@ -5,7 +5,7 @@
<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="22 November, 2007" />
+<meta name="date" content="29 November, 2007" />
<style type="text/css">
/*
@@ -302,7 +302,7 @@ ul.auto-toc {
<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>22 November, 2007</td></tr>
+<td>29 November, 2007</td></tr>
</tbody>
</table>
<div class="contents topic">
@@ -314,28 +314,29 @@ ul.auto-toc {
<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="#output-arrays" id="id7" name="id7">Output Arrays</a></li>
-<li><a class="reference" href="#other-common-types-bool" id="id8" name="id8">Other Common Types: bool</a></li>
-<li><a class="reference" href="#other-common-types-complex" id="id9" name="id9">Other Common Types: complex</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="id10" name="id10">NumPy Array Scalars and SWIG</a><ul>
-<li><a class="reference" href="#why-is-there-a-second-file" id="id11" name="id11">Why is There a Second File?</a></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="id12" name="id12">Helper Functions</a><ul>
-<li><a class="reference" href="#macros" id="id13" name="id13">Macros</a></li>
-<li><a class="reference" href="#routines" id="id14" name="id14">Routines</a></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="id15" name="id15">Beyond the Provided Typemaps</a><ul>
-<li><a class="reference" href="#a-common-example" id="id16" name="id16">A Common Example</a></li>
-<li><a class="reference" href="#other-situations" id="id17" name="id17">Other Situations</a></li>
-<li><a class="reference" href="#a-final-note" id="id18" name="id18">A Final Note</a></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="id19" name="id19">Summary</a></li>
-<li><a class="reference" href="#acknowledgements" id="id20" name="id20">Acknowledgements</a></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">
@@ -636,7 +637,37 @@ 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="output-arrays" name="output-arrays">Output Arrays</a></h2>
+<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>
+<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>
+<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_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>
+</ul>
+</blockquote>
+<p>Note that arrays with hard-coded dimensions are not supported. Thes
+have to be allocated ahead of time, which defeats the purpose of the
+typemap.</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
@@ -656,7 +687,7 @@ function to be wrapped, either with <tt class="docutils literal"><span class="pr
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="#id8" id="other-common-types-bool" name="other-common-types-bool">Other Common Types: bool</a></h2>
+<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>
@@ -673,7 +704,7 @@ expansion:</p>
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="#id9" id="other-common-types-complex" name="other-common-types-complex">Other Common Types: complex</a></h2>
+<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
@@ -707,7 +738,7 @@ work.</p>
</div>
</div>
<div class="section">
-<h1><a class="toc-backref" href="#id10" id="numpy-array-scalars-and-swig" name="numpy-array-scalars-and-swig">NumPy Array Scalars and SWIG</a></h1>
+<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
@@ -720,7 +751,7 @@ to pass this to a <a class="reference" href="http://www.swig.org">SWIG</a>-wrapp
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. Often, this means that code that works on a 32-bit machine
+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">
@@ -730,7 +761,7 @@ TypeError: in method 'MyClass_MyMethod', argument 2 of type 'int'
<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 to you. Simply copy
+Fortunately, this capabilitiy has been provided for you. Simply copy
the file:</p>
<pre class="literal-block">
pyfragments.swg
@@ -739,7 +770,7 @@ pyfragments.swg
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="#id11" id="why-is-there-a-second-file" name="why-is-there-a-second-file">Why is There a Second File?</a></h2>
+<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
@@ -760,12 +791,21 @@ in <tt class="docutils literal"><span class="pre">numpy.i</span></tt>, they woul
</div>
</div>
<div class="section">
-<h1><a class="toc-backref" href="#id12" id="helper-functions" name="helper-functions">Helper Functions</a></h1>
+<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.</p>
+be useful elsewhere in your interface file. These macros and routines
+are implemented as fragments, as 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="#id13" id="macros" name="macros">Macros</a></h2>
+<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>
@@ -797,7 +837,7 @@ order. Equivalent to <tt class="docutils literal"><span class="pre">(PyArray_IS
</blockquote>
</div>
<div class="section">
-<h2><a class="toc-backref" href="#id14" id="routines" name="routines">Routines</a></h2>
+<h2><a class="toc-backref" href="#id15" id="routines" name="routines">Routines</a></h2>
<blockquote>
<p><strong>pytype_string()</strong></p>
<blockquote>
@@ -957,11 +997,11 @@ string and return 0.</p>
</div>
</div>
<div class="section">
-<h1><a class="toc-backref" href="#id15" id="beyond-the-provided-typemaps" name="beyond-the-provided-typemaps">Beyond the Provided Typemaps</a></h1>
+<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="#id16" id="a-common-example" name="a-common-example">A Common Example</a></h2>
+<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);
@@ -1017,7 +1057,7 @@ above for <tt class="docutils literal"><span class="pre">my_dot</span></tt> to g
macro to perform this task.</p>
</div>
<div class="section">
-<h2><a class="toc-backref" href="#id17" id="other-situations" name="other-situations">Other Situations</a></h2>
+<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>
@@ -1054,7 +1094,7 @@ developers of <tt class="docutils literal"><span class="pre">numpy.i</span></tt>
</blockquote>
</div>
<div class="section">
-<h2><a class="toc-backref" href="#id18" id="a-final-note" name="a-final-note">A Final Note</a></h2>
+<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
@@ -1072,7 +1112,7 @@ where you want them, and then clear them after you are done.</p>
</div>
</div>
<div class="section">
-<h1><a class="toc-backref" href="#id19" id="summary" name="summary">Summary</a></h1>
+<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>
@@ -1081,10 +1121,10 @@ between <a class="reference" href="http://numpy.scipy.org">NumPy</a> arrays and
<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 23 different argument signatures for each data type,
+<li>That support 29 different argument signatures for each data type,
including:<ul>
<li>One-dimensional, two-dimensional and three-dimensional arrays.</li>
-<li>Input-only, in-place, and argout behavior.</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>
</ul>
@@ -1096,31 +1136,31 @@ 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 23 argument signatures for the user's choice of
+implementing the 29 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>Seven C macros and eleven C functions that can be used to write
+<li>Eight C macros and twelve 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="#id20" id="acknowledgements" name="acknowledgements">Acknowledgements</a></h1>
+<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 has also provided additional error checking
-and use cases. The work of these contributors has made this end
-result possible.</p>
+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-11-22 18:34 UTC.
+Generated on: 2007-11-29 19:48 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>
diff --git a/numpy/doc/swig/doc/numpy_swig.pdf b/numpy/doc/swig/doc/numpy_swig.pdf
index 81da6aa93..7797c00b3 100644
--- a/numpy/doc/swig/doc/numpy_swig.pdf
+++ b/numpy/doc/swig/doc/numpy_swig.pdf
Binary files differ
diff --git a/numpy/doc/swig/doc/numpy_swig.txt b/numpy/doc/swig/doc/numpy_swig.txt
index 84c583029..fd140ead3 100644
--- a/numpy/doc/swig/doc/numpy_swig.txt
+++ b/numpy/doc/swig/doc/numpy_swig.txt
@@ -4,7 +4,7 @@
:Author: Bill Spotz
:Institution: Sandia National Laboratories
-:Date: 22 November, 2007
+:Date: 29 November, 2007
.. contents::
@@ -314,6 +314,36 @@ or 3D. This 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
+
+ * ``( 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_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3)``
+ * ``( DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_ARRAY3)``
+
+Note that arrays with hard-coded dimensions are not supported. Thes
+have to be allocated ahead of time, which defeats the purpose of the
+typemap.
+
Output Arrays
-------------
@@ -402,7 +432,7 @@ to pass this to a `SWIG`_-wrapped C/C++ function that expects an
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. Often, this means that code that works on a 32-bit machine
+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::
@@ -413,7 +443,7 @@ 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 to you. Simply copy
+Fortunately, this capabilitiy has been provided for you. Simply copy
the file::
pyfragments.swg
@@ -449,7 +479,16 @@ 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.
+be useful elsewhere in your interface file. These macros and routines
+are implemented as fragments, as 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
------
@@ -806,12 +845,12 @@ between `NumPy`_ arrays and C arrays:
``unsigned int``, ``long``, ``unsigned long``, ``long long``,
``unsigned long long``, ``float`` and ``double``.
- * That support 23 different argument signatures for each data type,
+ * That support 29 different argument signatures for each data type,
including:
+ One-dimensional, two-dimensional and three-dimensional arrays.
- + Input-only, in-place, and argout behavior.
+ + Input-only, in-place, argout and argoutview behavior.
+ Hard-coded dimensions, data-buffer-then-dimensions
specification, and dimensions-then-data-buffer specification.
@@ -820,11 +859,11 @@ The ``numpy.i`` interface file also provides additional tools for
wrapper developers, including:
* A `SWIG`_ macro (``%numpy_typemaps``) with three arguments for
- implementing the 23 argument signatures for the user's choice of
+ implementing the 29 argument signatures for the user's choice of
(1) C data type, (2) `NumPy`_ data type (assuming they match), and
(3) dimension type.
- * Seven C macros and eleven C functions that can be used to write
+ * Eight C macros and twelve C functions that can be used to write
specialized typemaps, extensions, or inlined functions that handle
cases not covered by the provided typemaps.
@@ -837,6 +876,6 @@ 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 has also provided additional error checking
-and use cases. The work of these contributors has made this end
-result possible.
+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/numpy/doc/swig/doc/testing.pdf b/numpy/doc/swig/doc/testing.pdf
index 7029c75fc..9ffcf7575 100644
--- a/numpy/doc/swig/doc/testing.pdf
+++ b/numpy/doc/swig/doc/testing.pdf
Binary files differ
diff --git a/numpy/doc/swig/numpy.i b/numpy/doc/swig/numpy.i
index 626067d79..fc918f1ed 100644
--- a/numpy/doc/swig/numpy.i
+++ b/numpy/doc/swig/numpy.i
@@ -9,14 +9,6 @@
#include <numpy/arrayobject.h>
%}
-/* 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 slightly 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_Backward_Compatibility", "header")
@@ -73,6 +65,14 @@
/**********************************************************************/
+/* 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.
@@ -406,7 +406,7 @@
/* %numpy_typemaps() macro
*
- * This macro defines a family of 23 typemaps that allow C arguments
+ * This macro defines a family of 29 typemaps that allow C arguments
* of the form
*
* (DATA_TYPE IN_ARRAY1[ANY])
@@ -441,95 +441,53 @@
*
* (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_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3)
+ * (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_ARRAY3)
+ *
* where "DATA_TYPE" is any type supported by the NumPy module, and
* "DIM_TYPE" is any int-like type suitable for specifying dimensions.
* 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 numpy
- * arrays of the appropriate type.
+ * 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:
- *
- * %apply (double IN_ARRAY1[ANY]) {(double vector[ANY])};
- * double length(double vector[3]);
+ * %apply directive. For example:
*
* %apply (double* IN_ARRAY1, int DIM1) {(double* series, int length)};
* double prod(double* series, int length);
*
- * %apply (int DIM1, double* IN_ARRAY1) {(int length, double* series)}
- * double sum(int length, double* series)
- *
- * %apply (double IN_ARRAY2[ANY][ANY]) {(double matrix[2][2])};
- * double det(double matrix[2][2]);
- *
- * %apply (double* IN_ARRAY2, int DIM1, int DIM2) {(double* matrix, int rows, int cols)};
- * double max(double* matrix, int rows, int cols);
- *
- * %apply (int DIM1, int DIM2, double* IN_ARRAY2) {(int rows, int cols, double* matrix)}
- * double min(int length, double* series)
- *
- * %apply (double INPLACE_ARRAY1[ANY]) {(double vector[3])};
- * void reverse(double vector[3]);
- *
- * %apply (double* INPLACE_ARRAY1, int DIM1) {(double* series, int length)};
- * void ones(double* series, int length);
- *
- * %apply (int DIM1, double* INPLACE_ARRAY1) {(int length, double* series)}
- * double zeros(int length, double* series)
+ * %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 INPLACE_ARRAY2[ANY][ANY]) {(double matrix[3][3])};
- * void scale(double matrix[3][3]);
- *
- * %apply (double* INPLACE_ARRAY2, int DIM1, int DIM2) {(double* matrix, int rows, int cols)};
- * void floor(double* matrix, int rows, int cols);
- *
- * %apply (int DIM1, int DIM2, double* INPLACE_ARRAY2) {(int rows, int cols, double* matrix)};
- * void ceil(int rows, int cols, double* matrix);
- *
- * %apply (double IN_ARRAY1[ANY] ) {(double vector[ANY])};
- * %apply (double ARGOUT_ARRAY1[ANY]) {(double even[ 3])};
- * %apply (double ARGOUT_ARRAY1[ANY]) {(double odd[ 3])};
- * void eoSplit(double vector[3], double even[3], double odd[3]);
- *
- * %apply (double* ARGOUT_ARRAY1, int DIM1) {(double* twoVec, int size)};
- * void twos(double* twoVec, int size);
- *
- * %apply (int DIM1, double* ARGOUT_ARRAY1) {(int size, double* threeVec)};
- * void threes(int size, double* threeVec);
- *
- * %apply (double IN_ARRAY2[ANY][ANY]) {(double matrix[2][2])};
- * %apply (double ARGOUT_ARRAY2[ANY][ANY]) {(double upper[ 3][3])};
- * %apply (double ARGOUT_ARRAY2[ANY][ANY]) {(double lower[ 3][3])};
- * void luSplit(double matrix[3][3], double upper[3][3], double lower[3][3]);
+ * %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 length(double IN_ARRAY1[ANY]);
* double prod(double* IN_ARRAY1, int DIM1);
- * double sum( int DIM1, double* IN_ARRAY1)
- *
- * double det(double IN_ARRAY2[ANY][ANY]);
- * double max(double* IN_ARRAY2, int DIM1, int DIM2);
- * double min(int DIM1, int DIM2, double* IN_ARRAY2)
- *
- * void reverse(double INPLACE_ARRAY1[ANY]);
- * void ones( double* INPLACE_ARRAY1, int DIM1);
- * void zeros(int DIM1, double* INPLACE_ARRAY1)
*
- * void scale(double INPLACE_ARRAY2[ANY][ANY]);
- * void floor(double* INPLACE_ARRAY2, int DIM1, int DIM2, double floor);
- * void ceil( int DIM1, int DIM2, double* INPLACE_ARRAY2, double ceil );
+ * void floor(int DIM1, int DIM2, double* INPLACE_ARRAY2, double f);
*
- * void eoSplit(double IN_ARRAY1[ANY], double ARGOUT_ARRAY1[ANY],
- * double ARGOUT_ARRAY1[ANY]);
- * void twos(double* ARGOUT_ARRAY1, int DIM1)
- * void threes(int DIM1, double* ARGOUT_ARRAY1)
- *
- * void luSplit(double IN_ARRAY2[ANY][ANY], double ARGOUT_ARRAY2[ANY][ANY],
- * double ARGOUT_ARRAY2[ANY][ANY]);
+ * 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)
@@ -1107,8 +1065,140 @@
$result = SWIG_Python_AppendOutput($result,array$argnum);
}
-%enddef /* %numpy_typemaps() macro */
+/*****************************/
+/* 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)
+ (PyObject* array = NULL)
+{
+ npy_intp dims[1] = { *$2 };
+ 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)
+ (PyObject* array = NULL)
+{
+ npy_intp dims[1] = { *$1 };
+ 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)
+ (PyObject* array = NULL)
+{
+ npy_intp dims[2] = { *$2, *$3 };
+ 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)
+ (PyObject* array = NULL)
+{
+ npy_intp dims[2] = { *$1, *$2 };
+ 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_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)
+ (PyObject* array = NULL)
+{
+ npy_intp dims[3] = { *$2, *$3, *$4 };
+ 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)
+ (PyObject* array = NULL)
+{
+ npy_intp dims[3] = { *$1, *$2, *$3 };
+ array = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$3));
+ if (!array) SWIG_fail;
+ $result = SWIG_Python_AppendOutput($result,array);
+}
+
+%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.
@@ -1129,26 +1219,26 @@
/* ***************************************************************
* 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)
+ *
+ * %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)
+ *
+ * %numpy_typemaps(long double, NPY_LONGDOUBLE, int)
*/
/* ***************************************************************
- * Swig complains about a syntax error for the following macros
+ * 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)
+ *
+ * %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/numpy/doc/swig/test/Array.i b/numpy/doc/swig/test/Array.i
new file mode 100644
index 000000000..d56dd2d1c
--- /dev/null
+++ b/numpy/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/numpy/doc/swig/test/Array1.cxx b/numpy/doc/swig/test/Array1.cxx
new file mode 100644
index 000000000..0c09e02f9
--- /dev/null
+++ b/numpy/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/numpy/doc/swig/test/Array1.h b/numpy/doc/swig/test/Array1.h
new file mode 100644
index 000000000..754c248fc
--- /dev/null
+++ b/numpy/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/numpy/doc/swig/test/Array2.cxx b/numpy/doc/swig/test/Array2.cxx
new file mode 100644
index 000000000..e3558f786
--- /dev/null
+++ b/numpy/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/numpy/doc/swig/test/Array2.h b/numpy/doc/swig/test/Array2.h
new file mode 100644
index 000000000..a6e5bfc30
--- /dev/null
+++ b/numpy/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/numpy/doc/swig/test/Makefile b/numpy/doc/swig/test/Makefile
index e6768b52c..b980cce78 100644
--- a/numpy/doc/swig/test/Makefile
+++ b/numpy/doc/swig/test/Makefile
@@ -1,11 +1,12 @@
# SWIG
-INTERFACES = Vector.i Matrix.i Tensor.i
+INTERFACES = Array.i Vector.i Matrix.i Tensor.i
WRAPPERS = $(INTERFACES:.i=_wrap.cxx)
PROXIES = $(INTERFACES:.i=.py )
# Default target: build the tests
.PHONY : all
-all: $(WRAPPERS) Vector.cxx Vector.h Matrix.cxx Matrix.h Tensor.cxx Tensor.h
+all: $(WRAPPERS) Array1.cxx Array1.h Vector.cxx Vector.h Matrix.cxx Matrix.h \
+ Tensor.cxx Tensor.h
./setup.py build
# Test target: run the tests
@@ -14,10 +15,13 @@ test: all
python testVector.py
python testMatrix.py
python testTensor.py
+ python testArray.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
diff --git a/numpy/doc/swig/test/setup.py b/numpy/doc/swig/test/setup.py
index 4e6826cc1..948b8ec7e 100755
--- a/numpy/doc/swig/test/setup.py
+++ b/numpy/doc/swig/test/setup.py
@@ -13,6 +13,14 @@ try:
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],
+ )
+
# _Vector extension module
_Vector = Extension("_Vector",
["Vector_wrap.cxx",
@@ -38,6 +46,6 @@ _Tensor = Extension("_Tensor",
setup(name = "NumpyTypemapTests",
description = "Functions that work on arrays",
author = "Bill Spotz",
- py_modules = ["Vector", "Matrix", "Tensor"],
- ext_modules = [_Vector , _Matrix , _Tensor ]
+ py_modules = ["Array", "Vector", "Matrix", "Tensor"],
+ ext_modules = [_Array , _Vector , _Matrix , _Tensor ]
)
diff --git a/numpy/doc/swig/test/testArray.py b/numpy/doc/swig/test/testArray.py
new file mode 100755
index 000000000..a22692465
--- /dev/null
+++ b/numpy/doc/swig/test/testArray.py
@@ -0,0 +1,285 @@
+#! /usr/bin/env python
+
+# System imports
+from distutils.util import get_platform
+import os
+import sys
+import unittest
+
+# Import NumPy
+import numpy as N
+major, minor = [ int(d) for d in N.__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 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 = N.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 = N.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, N.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 = N.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 = N.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 = N.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, N.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", N.__version__
+ print
+ result = unittest.TextTestRunner(verbosity=2).run(suite)
+ sys.exit(len(result.errors) + len(result.failures))