# [Numpy-svn] r5959 - in numpy-docs/trunk: . source source/_static source/_templates source/reference source/reference/figures source/user

numpy-svn@scip... numpy-svn@scip...
Sun Oct 26 12:59:38 CDT 2008

Author: ptvirtan
Date: 2008-10-26 12:57:55 -0500 (Sun, 26 Oct 2008)
New Revision: 5959

Added:
numpy-docs/trunk/Makefile
numpy-docs/trunk/README.txt
numpy-docs/trunk/postprocess.py
numpy-docs/trunk/source/
numpy-docs/trunk/source/_static/
numpy-docs/trunk/source/_static/scipy.css
numpy-docs/trunk/source/_templates/
numpy-docs/trunk/source/_templates/indexcontent.html
numpy-docs/trunk/source/_templates/indexsidebar.html
numpy-docs/trunk/source/_templates/layout.html
numpy-docs/trunk/source/about.rst
numpy-docs/trunk/source/bugs.rst
numpy-docs/trunk/source/conf.py
numpy-docs/trunk/source/contents.rst
numpy-docs/trunk/source/glossary.rst
numpy-docs/trunk/source/license.rst
numpy-docs/trunk/source/reference/
numpy-docs/trunk/source/reference/arrays.classes.rst
numpy-docs/trunk/source/reference/arrays.dtypes.rst
numpy-docs/trunk/source/reference/arrays.indexing.rst
numpy-docs/trunk/source/reference/arrays.interface.rst
numpy-docs/trunk/source/reference/arrays.ndarray.rst
numpy-docs/trunk/source/reference/arrays.rst
numpy-docs/trunk/source/reference/arrays.scalars.rst
numpy-docs/trunk/source/reference/c-api.array.rst
numpy-docs/trunk/source/reference/c-api.config.rst
numpy-docs/trunk/source/reference/c-api.dtype.rst
numpy-docs/trunk/source/reference/c-api.rst
numpy-docs/trunk/source/reference/c-api.types-and-structures.rst
numpy-docs/trunk/source/reference/c-api.ufunc.rst
numpy-docs/trunk/source/reference/distutils.rst
numpy-docs/trunk/source/reference/figures/
numpy-docs/trunk/source/reference/figures/dtype-hierarchy.dia
numpy-docs/trunk/source/reference/figures/dtype-hierarchy.pdf
numpy-docs/trunk/source/reference/figures/dtype-hierarchy.png
numpy-docs/trunk/source/reference/figures/threefundamental.fig
numpy-docs/trunk/source/reference/figures/threefundamental.pdf
numpy-docs/trunk/source/reference/figures/threefundamental.png
numpy-docs/trunk/source/reference/index.rst
numpy-docs/trunk/source/reference/internals.code-explanations.rst
numpy-docs/trunk/source/reference/internals.rst
numpy-docs/trunk/source/reference/routines.array-creation.rst
numpy-docs/trunk/source/reference/routines.array-manipulation.rst
numpy-docs/trunk/source/reference/routines.bitwise.rst
numpy-docs/trunk/source/reference/routines.ctypeslib.rst
numpy-docs/trunk/source/reference/routines.dtype.rst
numpy-docs/trunk/source/reference/routines.dual.rst
numpy-docs/trunk/source/reference/routines.emath.rst
numpy-docs/trunk/source/reference/routines.err.rst
numpy-docs/trunk/source/reference/routines.fft.rst
numpy-docs/trunk/source/reference/routines.financial.rst
numpy-docs/trunk/source/reference/routines.functional.rst
numpy-docs/trunk/source/reference/routines.help.rst
numpy-docs/trunk/source/reference/routines.indexing.rst
numpy-docs/trunk/source/reference/routines.io.rst
numpy-docs/trunk/source/reference/routines.linalg.rst
numpy-docs/trunk/source/reference/routines.logic.rst
numpy-docs/trunk/source/reference/routines.ma.rst
numpy-docs/trunk/source/reference/routines.math.rst
numpy-docs/trunk/source/reference/routines.matlib.rst
numpy-docs/trunk/source/reference/routines.numarray.rst
numpy-docs/trunk/source/reference/routines.oldnumeric.rst
numpy-docs/trunk/source/reference/routines.other.rst
numpy-docs/trunk/source/reference/routines.poly.rst
numpy-docs/trunk/source/reference/routines.random.rst
numpy-docs/trunk/source/reference/routines.rst
numpy-docs/trunk/source/reference/routines.set.rst
numpy-docs/trunk/source/reference/routines.sort.rst
numpy-docs/trunk/source/reference/routines.statistics.rst
numpy-docs/trunk/source/reference/routines.window.rst
numpy-docs/trunk/source/reference/ufuncs.rst
numpy-docs/trunk/source/scipyshiny_small.png
numpy-docs/trunk/source/user/
numpy-docs/trunk/source/user/basics.broadcasting.rst
numpy-docs/trunk/source/user/basics.creation.rst
numpy-docs/trunk/source/user/basics.indexing.rst
numpy-docs/trunk/source/user/basics.rec.rst
numpy-docs/trunk/source/user/basics.rst
numpy-docs/trunk/source/user/basics.subclassing.rst
numpy-docs/trunk/source/user/basics.types.rst
numpy-docs/trunk/source/user/c-info.beyond-basics.rst
numpy-docs/trunk/source/user/c-info.how-to-extend.rst
numpy-docs/trunk/source/user/c-info.python-as-glue.rst
numpy-docs/trunk/source/user/c-info.rst
numpy-docs/trunk/source/user/howtofind.rst
numpy-docs/trunk/source/user/index.rst
numpy-docs/trunk/source/user/misc.rst
numpy-docs/trunk/source/user/performance.rst
numpy-docs/trunk/summarize.py
Log:
Import initial version of Numpy documentation

Added: numpy-docs/trunk/Makefile
===================================================================
--- numpy-docs/trunk/Makefile	2008-10-26 17:50:36 UTC (rev 5958)
+++ numpy-docs/trunk/Makefile	2008-10-26 17:57:55 UTC (rev 5959)
@@ -0,0 +1,98 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS    =
+SPHINXBUILD   = LANG=C sphinx-build
+PAPER         =
+
+# Internal variables.
+PAPEROPT_a4     = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS   = -d build/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source + +.PHONY: help clean html web pickle htmlhelp latex changes linkcheck + +help: + @echo "Please use \make <target>' where <target> is one of" + @echo " dist to make a distribution-ready tree" + @echo " html to make standalone HTML files" + @echo " pickle to make pickle files (usable by e.g. sphinx-web)" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " changes to make an overview over all changed/added/deprecated items" + @echo " linkcheck to check all external links for integrity" + +clean: + -rm -rf build/* source/reference/generated + +dist: html + test -d build/latex || make latex + make -C build/latex all-pdf + -rm -rf build/dist + cp -r build/html build/dist + perl -pi -e 's#^\s*(<li><a href=".*?">NumPy.*?Manual.*?&raquo;</li>)#<li><a href="/">Numpy and Scipy Documentation</a> &raquo;</li>#;' build/dist/*.html build/dist/*/*.html build/dist/*/*/*.html + cd build/html && zip -9r ../dist/numpy-html.zip . + cp build/latex/*.pdf build/dist + cd build/dist && tar czf ../dist.tar.gz * + +generate: build/generate-stamp +build/generate-stamp:$(wildcard source/reference/*.rst) ext
+	mkdir -p build
+	./ext/autosummary_generate.py source/reference/*.rst \
+		-p dump.xml -o source/reference/generated
+	touch build/generate-stamp
+
+ext:
+	svn co http://sphinx.googlecode.com/svn/contrib/trunk/numpyext ext
+
+html: generate
+	mkdir -p build/html build/doctrees
+	$(SPHINXBUILD) -b html$(ALLSPHINXOPTS) build/html
+	python postprocess.py html build/html/*.html
+	@echo
+	@echo "Build finished. The HTML pages are in build/html."
+
+pickle: generate
+	mkdir -p build/pickle build/doctrees
+	$(SPHINXBUILD) -b pickle$(ALLSPHINXOPTS) build/pickle
+	@echo
+	@echo "Build finished; now you can process the pickle files or run"
+	@echo "  sphinx-web build/pickle"
+	@echo "to start the sphinx-web server."
+
+web: pickle
+
+htmlhelp: generate
+	mkdir -p build/htmlhelp build/doctrees
+	$(SPHINXBUILD) -b htmlhelp$(ALLSPHINXOPTS) build/htmlhelp
+	@echo
+	@echo "Build finished; now you can run HTML Help Workshop with the" \
+	      ".hhp project file in build/htmlhelp."
+
+latex: generate
+	mkdir -p build/latex build/doctrees
+	$(SPHINXBUILD) -b latex$(ALLSPHINXOPTS) build/latex
+	python postprocess.py tex build/latex/*.tex
+	@echo
+	@echo "Build finished; the LaTeX files are in build/latex."
+	@echo "Run \make all-pdf' or \make all-ps' in that directory to" \
+	      "run these through (pdf)latex."
+
+coverage: build
+	mkdir -p build/coverage build/doctrees
+	$(SPHINXBUILD) -b coverage$(ALLSPHINXOPTS) build/coverage
+	@echo "Coverage finished; see c.txt and python.txt in build/coverage"
+
+changes: generate
+	mkdir -p build/changes build/doctrees
+	$(SPHINXBUILD) -b changes$(ALLSPHINXOPTS) build/changes
+	@echo
+	@echo "The overview file is in build/changes."
+
+linkcheck: generate
+	mkdir -p build/linkcheck build/doctrees
+	$(SPHINXBUILD) -b linkcheck$(ALLSPHINXOPTS) build/linkcheck
+	@echo
+	@echo "Link check complete; look for any errors in the above output " \
+	      "or in build/linkcheck/output.txt."

Property changes on: numpy-docs/trunk/Makefile
___________________________________________________________________
Name: svn:eol-style
+ native

Added: numpy-docs/trunk/README.txt
===================================================================
--- numpy-docs/trunk/README.txt	2008-10-26 17:50:36 UTC (rev 5958)
+++ numpy-docs/trunk/README.txt	2008-10-26 17:57:55 UTC (rev 5959)
@@ -0,0 +1,40 @@
+NumPy Reference Guide
+=====================
+
+Instructions
+------------
+1. Optionally download an XML dump of the newest docstrings from the doc wiki
+   at /pydocweb/dump and save it as dump.xml.
+2. Run make html or make dist
+
+You can also run summarize.py to see which parts of the Numpy
+namespace are documented.
+
+
+TODO
+----
+
+* Numberless [*] footnotes cause LaTeX errors.
+
+* See also sections are still somehow broken even if some work.
+  The problem is that Sphinx searches like this::
+
+      'name'
+      'active_module.name'
+      'active_module.active_class.name'.
+
+  Whereas, we would like to have this:
+
+      'name'
+      'active_module.name'
+      'parent_of_active_module.name'
+      'parent_of_parent_of_active_module.name'
+      ...
+      'numpy.name'
+
+  We can get one step upwards by always using 'numpy' as the active module.
+  It seems difficult to beat Sphinx to do what we want.
+  Do we need to change our docstring standard slightly, ie. allow only
+  leaving the 'numpy.' prefix away?
+
+* Link resolution doesn't work as intended... eg. doc.ufunc_

Property changes on: numpy-docs/trunk/README.txt
___________________________________________________________________
Name: svn:eol-style
+ native

Added: numpy-docs/trunk/postprocess.py
===================================================================
--- numpy-docs/trunk/postprocess.py	2008-10-26 17:50:36 UTC (rev 5958)
+++ numpy-docs/trunk/postprocess.py	2008-10-26 17:57:55 UTC (rev 5959)
@@ -0,0 +1,59 @@
+#!/usr/bin/env python
+"""
+%prog MODE FILES...
+
+Post-processes HTML and Latex files output by Sphinx.
+MODE is either 'html' or 'tex'.
+
+"""
+import re, optparse
+
+def main():
+    p = optparse.OptionParser(__doc__)
+    options, args = p.parse_args()
+
+    if len(args) < 1:
+        p.error('no mode given')
+
+    mode = args.pop(0)
+
+    if mode not in ('html', 'tex'):
+        p.error('unknown mode %s' % mode)
+
+    for fn in args:
+        f = open(fn, 'r')
+        try:
+            if mode == 'html':
+                lines = process_html(fn, f.readlines())
+            elif mode == 'tex':
+                lines = process_tex(f.readlines())
+        finally:
+            f.close()
+
+        f = open(fn, 'w')
+        f.write("".join(lines))
+        f.close()
+
+def process_html(fn, lines):
+    return lines
+
+def process_tex(lines):
+    """
+    Remove unnecessary section titles from the LaTeX file.
+
+    """
+    new_lines = []
+    for line in lines:
+        if (line.startswith(r'\section{numpy.')
+            or line.startswith(r'\subsection{numpy.')
+            or line.startswith(r'\subsubsection{numpy.')
+            or line.startswith(r'\paragraph{numpy.')
+            or line.startswith(r'\subparagraph{numpy.')
+            ):
+            pass # skip!
+        else:
+            new_lines.append(line)
+    return new_lines
+
+if __name__ == "__main__":
+    main()

Property changes on: numpy-docs/trunk/postprocess.py
___________________________________________________________________
Name: svn:executable
+

Added: numpy-docs/trunk/source/_static/scipy.css
===================================================================
--- numpy-docs/trunk/source/_static/scipy.css	2008-10-26 17:50:36 UTC (rev 5958)
+++ numpy-docs/trunk/source/_static/scipy.css	2008-10-26 17:57:55 UTC (rev 5959)
@@ -0,0 +1,155 @@
+@import "default.css";
+
+/**
+ * Spacing fixes
+ */
+
+div.body p, div.body dd, div.body li {
+  line-height: 125%;
+}
+
+ul.simple {
+    margin-top: 0;
+    margin-bottom: 0;
+    padding-top: 0;
+    padding-bottom: 0;
+}
+
+/* spacing around blockquoted fields in parameters/attributes/returns */
+td.field-body > blockquote {
+    margin-top: 0.1em;
+    margin-bottom: 0.5em;
+}
+
+/* spacing around example code */
+div.highlight > pre {
+    padding: 2px 5px 2px 5px;
+}
+
+/* spacing in see also definition lists */
+dl.last > dd {
+    margin-top: 1px;
+    margin-bottom: 5px;
+    margin-left: 30px;
+}
+
+/**
+ * Hide dummy toctrees
+ */
+
+ul {
+  padding-top: 0;
+  padding-bottom: 0;
+  margin-top: 0;
+  margin-bottom: 0;
+}
+ul li {
+  padding-top: 0;
+  padding-bottom: 0;
+  margin-top: 0;
+  margin-bottom: 0;
+}
+ul li a.reference {
+  padding-top: 0;
+  padding-bottom: 0;
+  margin-top: 0;
+  margin-bottom: 0;
+}
+
+/**
+ * Make high-level subsections easier to distinguish from top-level ones
+ */
+div.body h3 {
+  background-color: transparent;
+}
+
+div.body h4 {
+  border: none;
+  background-color: transparent;
+}
+
+/**
+ * Scipy colors
+ */
+
+body {
+  background-color: rgb(100,135,220);
+}
+
+div.document {
+  background-color: rgb(230,230,230);
+}
+
+div.sphinxsidebar {
+  background-color: rgb(230,230,230);
+}
+
+div.related {
+  background-color: rgb(100,135,220);
+}
+
+div.sphinxsidebar h3 {
+  color: rgb(0,102,204);
+}
+
+div.sphinxsidebar h3 a {
+  color: rgb(0,102,204);
+}
+
+div.sphinxsidebar h4 {
+  color: rgb(0,82,194);
+}
+
+div.sphinxsidebar p {
+  color: black;
+}
+
+div.sphinxsidebar a {
+  color: #355f7c;
+}
+
+div.sphinxsidebar ul.want-points {
+  list-style: disc;
+}
+
+.field-list th {
+  color: rgb(0,102,204);
+}
+
+/**
+ * Extra admonitions
+ */
+
+div.tip {
+  background-color: #ffffe4;
+  border: 1px solid #ee6;
+}
+
+/*
+div.admonition-example {
+    background-color: #e4ffe4;
+    border: 1px solid #ccc;
+}*/
+
+
+/**
+ * Styling for field lists
+ */
+
+table.field-list th {
+  border-left: 1px solid #aaa !important;
+  padding-left: 5px;
+}
+
+table.field-list {
+  border-collapse: separate;
+  border-spacing: 10px;
+}
+
+/**
+ * Styling for footnotes
+ */
+
+table.footnote td, table.footnote th {
+  border: none;
+}

Added: numpy-docs/trunk/source/_templates/indexcontent.html
===================================================================
--- numpy-docs/trunk/source/_templates/indexcontent.html	2008-10-26 17:50:36 UTC (rev 5958)
+++ numpy-docs/trunk/source/_templates/indexcontent.html	2008-10-26 17:57:55 UTC (rev 5959)
@@ -0,0 +1,55 @@
+{% extends "defindex.html" %}
+{% block tables %}
+  <p><strong>Parts of the documentation:</strong></p>
+  <table class="contentstable" align="center"><tr>
+    <td width="50%">
+      <p class="biglink"><a class="biglink" href="{{ pathto("user/index") }}">Numpy User Guide</a><br/>
+         <span class="linkdescr">start here</span></p>
+      <p class="biglink"><a class="biglink" href="{{ pathto("reference/index") }}">Numpy Reference</a><br/>
+         <span class="linkdescr">reference documentation</span></p>
+    </td></tr>
+  </table>
+
+  <p><strong>Indices and tables:</strong></p>
+  <table class="contentstable" align="center"><tr>
+    <td width="50%">
+      <p class="biglink"><a class="biglink" href="{{ pathto("modindex") }}">Module Index</a><br/>
+         <span class="linkdescr">quick access to all modules</span></p>
+      <p class="biglink"><a class="biglink" href="{{ pathto("genindex") }}">General Index</a><br/>
+         <span class="linkdescr">all functions, classes, terms</span></p>
+      <p class="biglink"><a class="biglink" href="{{ pathto("glossary") }}">Glossary</a><br/>
+         <span class="linkdescr">the most important terms explained</span></p>
+    </td><td width="50%">
+      <p class="biglink"><a class="biglink" href="{{ pathto("search") }}">Search page</a><br/>
+         <span class="linkdescr">search this documentation</span></p>
+      <p class="biglink"><a class="biglink" href="{{ pathto("contents") }}">Complete Table of Contents</a><br/>
+         <span class="linkdescr">lists all sections and subsections</span></p>
+    </td></tr>
+  </table>
+
+  <p><strong>Meta information:</strong></p>
+  <table class="contentstable" align="center"><tr>
+    <td width="50%">
+      <p class="biglink"><a class="biglink" href="{{ pathto("bugs") }}">Reporting bugs</a></p>
+      <p class="biglink"><a class="biglink" href="{{ pathto("about") }}">About NumPy</a></p>
+    </td><td width="50%">
+      <p class="biglink"><a class="biglink" href="{{ pathto("license") }}">License of Numpy</a></p>
+    </td></tr>
+  </table>
+
+  <h2>Acknowledgements</h2>
+  <p>
+    Large parts of this manual originate from Travis E. Oliphant's book
+    <a href="http://www.tramy.us/">"Guide to Numpy"</a> (which generously entered
+    Public Domain in August 2008). The reference documentation for many of
+    the functions are written by numerous contributors and developers of
+    Numpy, both prior to and during the
+    <a href="http://scipy.org/Developer_Zone/DocMarathon2008">Numpy Documentation Marathon</a>.
+  </p>
+  <p>
+    The Documentation Marathon is still ongoing. Please help us write
+    better documentation for Numpy by joining it! Instructions on how to
+    join and what to do can be found
+    <a href="http://scipy.org/Developer_Zone/DocMarathon2008">on the scipy.org website</a>.
+  </p>
+{% endblock %}

Added: numpy-docs/trunk/source/_templates/indexsidebar.html
===================================================================
--- numpy-docs/trunk/source/_templates/indexsidebar.html	2008-10-26 17:50:36 UTC (rev 5958)
+++ numpy-docs/trunk/source/_templates/indexsidebar.html	2008-10-26 17:57:55 UTC (rev 5959)
@@ -0,0 +1,5 @@
+            <h3>Resources</h3>
+            <ul>
+              <li><a href="http://scipy.org/">Scipy.org website</a></li>
+              <li>&nbsp;</li>
+            </ul>

Added: numpy-docs/trunk/source/_templates/layout.html
===================================================================
--- numpy-docs/trunk/source/_templates/layout.html	2008-10-26 17:50:36 UTC (rev 5958)
+++ numpy-docs/trunk/source/_templates/layout.html	2008-10-26 17:57:55 UTC (rev 5959)
@@ -0,0 +1,4 @@
+{% extends "!layout.html" %}
+{% block rootrellink %}
+<li><a href="{{ pathto('index') }}">{{ shorttitle }}</a>{{ reldelim1 }}</li>
+{% endblock %}

Added: numpy-docs/trunk/source/about.rst
===================================================================
--- numpy-docs/trunk/source/about.rst	2008-10-26 17:50:36 UTC (rev 5958)
+++ numpy-docs/trunk/source/about.rst	2008-10-26 17:57:55 UTC (rev 5959)
@@ -0,0 +1,66 @@
+About NumPy
+===========
+
+NumPy <http://www.scipy.org/NumpPy/>__ is the fundamental package
+needed for scientific computing with Python. This package contains:
+
+- a powerful N-dimensional :ref:array object <arrays>
+- sophisticated :ref:(broadcasting) functions <ufuncs>
+- basic :ref:linear algebra functions <routines.linalg>
+- basic :ref:Fourier transforms <routines.fft>
+- sophisticated :ref:random number capabilities <routines.random>
+- tools for integrating Fortran code
+- tools for integrating C/C++ code
+
+Besides its obvious scientific uses, *NumPy* can also be used as an
+efficient multi-dimensional container of generic data. Arbitrary
+data-types can be defined. This allows *NumPy* to seamlessly and
+speedily integrate with a wide-variety of databases.
+
+NumPy is a successor for two earlier scientific Python libraries:
+NumPy derives from the old *Numeric* code base and can be used
+as a replacement for *Numeric*.  It also adds the features introduced
+by *Numarray* and can also be used to replace *Numarray*.
+
+NumPy community
+---------------
+
+Numpy is a distributed, volunteer open-source project. *You* can help
+us make it better; if you believe something should be improved either
+in functionality or in documentation, don't hesitate to contact us --- or
+even better, contact us and participate in fixing the problem.
+
+Our main means of communication are:
+
+- scipy.org website <http://scipy.org/>__
+
+- Mailing lists <http://scipy.org/Mailing_Lists>__
+
+- Numpy Trac <http://projects.scipy.org/scipy/numpy>__ (bug "tickets" go here)
+
+More information about the development of Numpy can be found at
+http://scipy.org/Developer_Zone
+
+If you want to fix issues in this documentation, the easiest way
+is to participate in our ongoing documentation marathon
+<http://scipy.org/Developer_Zone/DocMarathon2008>__.
+
+
+About this documentation
+========================
+
+Conventions
+-----------
+
+Names of classes, objects, constants, etc. are given in **boldface** font.
+Often they are also links to a more detailed documentation of the
+referred object.
+
+This manual contains many examples of use, usually prefixed with the
+Python prompt >>> (which is not a part of the example code). The
+examples assume that you have first entered::
+
+>>> import numpy as np
+
+before running the examples.
+

Added: numpy-docs/trunk/source/bugs.rst
===================================================================
--- numpy-docs/trunk/source/bugs.rst	2008-10-26 17:50:36 UTC (rev 5958)
+++ numpy-docs/trunk/source/bugs.rst	2008-10-26 17:57:55 UTC (rev 5959)
@@ -0,0 +1,23 @@
+**************
+Reporting bugs
+**************
+
+File bug reports or feature requests, and make contributions
+(e.g. code patches), by submitting a "ticket" on the Trac pages:
+
+- Numpy Trac: http://scipy.org/scipy/numpy
+
+Because of spam abuse, you must create an account on our Trac in order
+to submit a ticket, then click on the "New Ticket" tab that only
+appears when you have logged in. Please give as much information as
+you can in the ticket. It is extremely useful if you can supply a
+small self-contained code snippet that reproduces the problem. Also
+specify the component, the version you are referring to and the
+milestone.
+
+Report bugs to the appropriate Trac instance (there is one for NumPy
+and a different one for SciPy). There are also read-only mailing lists
+for tracking the status of your bug ticket.
+
+More information can be found on the http://scipy.org/Developer_Zone
+website.

Added: numpy-docs/trunk/source/conf.py
===================================================================
--- numpy-docs/trunk/source/conf.py	2008-10-26 17:50:36 UTC (rev 5958)
+++ numpy-docs/trunk/source/conf.py	2008-10-26 17:57:55 UTC (rev 5959)
@@ -0,0 +1,229 @@
+# -*- coding: utf-8 -*-
+
+import sys, os
+
+# If your extensions are in another directory, add it here. If the directory
+# is relative to the documentation root, use os.path.abspath to make it
+# absolute, like shown here.
+sys.path.append(os.path.abspath('../ext'))
+
+# Check Sphinx version
+import sphinx
+if sphinx.__version__ < "0.5":
+    raise RuntimeError("Sphinx 0.5.dev or newer required")
+
+
+# -----------------------------------------------------------------------------
+# General configuration
+# -----------------------------------------------------------------------------
+
+# Add any Sphinx extension module names here, as strings. They can be extensions
+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+extensions = ['sphinx.ext.autodoc', 'sphinx.ext.pngmath', 'numpydoc',
+              'phantom_import', 'autosummary', 'sphinx.ext.intersphinx',
+              'sphinx.ext.coverage']
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The master toctree document.
+#master_doc = 'index'
+
+# General substitutions.
+project = 'NumPy'
+copyright = '2008, The Scipy community'
+
+# The default replacements for |version| and |release|, also used in various
+# other places throughout the built documents.
+#
+# The short X.Y version.
+version = '1.2'
+# The full version, including alpha/beta/rc tags.
+release = '1.2.dev'
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+today_fmt = '%B %d, %Y'
+
+# List of documents that shouldn't be included in the build.
+#unused_docs = []
+
+# The reST default role (used for this markup: text) to use for all documents.
+default_role = "autolink"
+
+# List of directories, relative to source directories, that shouldn't be searched
+# for source files.
+exclude_dirs = []
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+add_function_parentheses = False
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+
+# -----------------------------------------------------------------------------
+# HTML output
+# -----------------------------------------------------------------------------
+
+# The style sheet to use for HTML and HTML Help pages. A file of that name
+# must exist either in Sphinx' static/ path, or in one of the custom paths
+# given in html_static_path.
+html_style = 'scipy.css'
+
+# The name for this set of Sphinx documents.  If None, it defaults to
+# "<project> v<release> documentation".
+html_title = "%s v%s Manual (DRAFT)" % (project, version)
+
+# The name of an image file (within the static path) to place at the top of
+# the sidebar.
+html_logo = 'scipyshiny_small.png'
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+html_sidebars = {
+    'index': 'indexsidebar.html'
+}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+html_additional_pages = {
+    'index': 'indexcontent.html',
+}
+
+# If false, no module index is generated.
+html_use_modindex = True
+
+# If true, the reST sources are included in the HTML build as _sources/<name>.
+#html_copy_source = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it.  The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# If nonempty, this is the file name suffix for HTML files (e.g. ".html").
+#html_file_suffix = '.html'
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'NumPydoc'
+
+# Pngmath should try to align formulas properly
+pngmath_use_preview = True
+
+
+# -----------------------------------------------------------------------------
+# LaTeX output
+# -----------------------------------------------------------------------------
+
+# The paper size ('letter' or 'a4').
+#latex_paper_size = 'letter'
+
+# The font size ('10pt', '11pt' or '12pt').
+#latex_font_size = '10pt'
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, document class [howto/manual]).
+_stdauthor = 'Written by the NumPy community'
+latex_documents = [
+  ('reference/index', 'numpy-ref.tex', 'NumPy Reference',
+   _stdauthor, 'manual'),
+  ('user/index', 'numpy-user.tex', 'NumPy User Guide',
+   _stdauthor, 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# Additional stuff for the LaTeX preamble.
+latex_preamble = r'''
+\usepackage{amsmath}
+
+% In the parameters section, place a newline after the Parameters
+% header
+\usepackage{expdlist}
+\let\latexdescription=\description
+\def\description{\latexdescription{}{} \breaklabel}
+
+% Make Examples/etc section headers smaller and more compact
+\makeatletter
+\titleformat{\paragraph}{\normalsize\py@HeaderFamily}%
+            {\py@TitleColor}{0em}{\py@TitleColor}{\py@NormalColor}
+\titlespacing*{\paragraph}{0pt}{1ex}{0pt}
+\makeatother
+
+% Fix footer/header
+\renewcommand{\chaptermark}[1]{\markboth{\MakeUppercase{\thechapter.\ #1}}{}}
+\renewcommand{\sectionmark}[1]{\markright{\MakeUppercase{\thesection.\ #1}}}
+'''
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+latex_use_modindex = False
+
+
+# -----------------------------------------------------------------------------
+# Intersphinx configuration
+# -----------------------------------------------------------------------------
+intersphinx_mapping = {'http://docs.python.org/dev': None}
+
+
+# -----------------------------------------------------------------------------
+# Numpy extensions
+# -----------------------------------------------------------------------------
+
+# If we want to do a phantom import from an XML file for all autodocs
+phantom_import_file = 'dump.xml'
+
+# Edit links
+#numpydoc_edit_link = 'Edit </pydocweb/doc/%(full_name)s/>__'
+
+# -----------------------------------------------------------------------------
+# Coverage checker
+# -----------------------------------------------------------------------------
+coverage_ignore_modules = r"""
+    """.split()
+coverage_ignore_functions = r"""
+    test(|_) (some|all)true bitwise_not cumproduct pkgload + generic\. + """.split() +coverage_ignore_classes = r""" + """.split() + +coverage_c_path = [] +coverage_c_regexes = {} +coverage_ignore_c_items = {} + + Added: numpy-docs/trunk/source/contents.rst =================================================================== --- numpy-docs/trunk/source/contents.rst 2008-10-26 17:50:36 UTC (rev 5958) +++ numpy-docs/trunk/source/contents.rst 2008-10-26 17:57:55 UTC (rev 5959) @@ -0,0 +1,12 @@ +##################### +Numpy manual contents +##################### + +.. toctree:: + + user/index + reference/index + about + bugs + license + glossary Added: numpy-docs/trunk/source/glossary.rst =================================================================== --- numpy-docs/trunk/source/glossary.rst 2008-10-26 17:50:36 UTC (rev 5958) +++ numpy-docs/trunk/source/glossary.rst 2008-10-26 17:57:55 UTC (rev 5959) @@ -0,0 +1,14 @@ +******** +Glossary +******** + +.. toctree:: + +.. glossary:: + + .. automodule:: numpy.doc.glossary + +Jargon +------ + +.. automodule:: numpy.doc.jargon Added: numpy-docs/trunk/source/license.rst =================================================================== --- numpy-docs/trunk/source/license.rst 2008-10-26 17:50:36 UTC (rev 5958) +++ numpy-docs/trunk/source/license.rst 2008-10-26 17:57:55 UTC (rev 5959) @@ -0,0 +1,35 @@ +************* +Numpy License +************* + +Copyright (c) 2005, NumPy Developers + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + +* Neither the name of the NumPy Developers nor the names of any + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Added: numpy-docs/trunk/source/reference/arrays.classes.rst =================================================================== --- numpy-docs/trunk/source/reference/arrays.classes.rst 2008-10-26 17:50:36 UTC (rev 5958) +++ numpy-docs/trunk/source/reference/arrays.classes.rst 2008-10-26 17:57:55 UTC (rev 5959) @@ -0,0 +1,414 @@ +######################### +Standard array subclasses +######################### + +.. currentmodule:: numpy + +The :class:ndarray in NumPy is a "new-style" Python +built-in-type. Therefore, it can be inherited from (in Python or in C) +if desired. Therefore, it can form a foundation for many useful +classes. Often whether to sub-class the array object or to simply use +the core array component as an internal part of a new class is a +difficult decision, and can be simply a matter of choice. NumPy has +several tools for simplifying how your new object interacts with other +array objects, and so the choice may not be significant in the +end. One way to simplify the question is by asking yourself if the +object you are interested can be replaced as a single array or does it +really require two or more arrays at its core. + +Note that :func:asarray always returns the base-class ndarray. If +you are confident that your use of the array object can handle any +subclass of an ndarray, then :func:asanyarray can be used to allow +subclasses to propagate more cleanly through your subroutine. In +principal a subclass could redefine any aspect of the array and +therefore, under strict guidelines, :func:asanyarray would rarely be +useful. However, most subclasses of the arrayobject will not +redefine certain aspects of the array object such as the buffer +interface, or the attributes of the array. One of important example, +however, of why your subroutine may not be able to handle an arbitrary +subclass of an array is that matrices redefine the "*" operator to be +matrix-multiplication, rather than element-by-element multiplication. + + +Special attributes and methods +============================== + +.. seealso:: :ref:Subclassing ndarray <basics.subclassing> + +Numpy provides several hooks that subclasses of :class:ndarray can +customize: + +.. function:: __array_finalize__(self) + + This method is called whenever the system internally allocates a + new array from *obj*, where *obj* is a subclass (subtype) of the + :class:ndarray. It can be used to change attributes of *self* after + construction (so as to ensure a 2-d matrix for example), or to + update meta-information from the "parent." Subclasses inherit a + default implementation of this method that does nothing. + +.. function:: __array_wrap__(array) + + This method should return an instance of the subclass from the + :class:ndarray object passed in. For example, this is called + after every :ref:ufunc <ufuncs.output-type> for the object with + the highest array priority. The ufunc-computed array object is + passed in and whatever is returned is passed to the + user. Subclasses inherit a default implementation of this method. + +.. data:: __array_priority__ + + The value of this attribute is used to determine what type of + object to return in situations where there is more than one + possibility for the Python type of the returned object. Subclasses + inherit a default value of 1.0 for this attribute. + +.. function:: __array__([dtype]) + + If a class having the :obj:__array__ method is used as the output + object of an :ref:ufunc <ufuncs.output-type>, results will be + written to the object returned by :obj:__array__. + +Matrix objects +============== + +.. index:: + single: matrix + +:class:matrix objects inherit from the ndarray and therefore, they +have the same attributes and methods of ndarrays. There are six +important differences of matrix objects, however that may lead to +unexpected results when you use matrices but expect them to act like +arrays: + +1. Matrix objects can be created using a string notation to allow Matlab- + style syntax where spaces separate columns and semicolons (';') + separate rows. + +2. Matrix objects are always two-dimensional. This has far-reaching + implications, in that m.ravel() is still two-dimensional (with a 1 in + the first dimension) and item selection returns two-dimensional + objects so that sequence behavior is fundamentally different than + arrays. + +3. Matrix objects over-ride multiplication to be + matrix-multiplication. **Make sure you understand this for + functions that you may want to receive matrices. Especially in + light of the fact that asanyarray(m) returns a matrix when m is a + matrix.** + +4. Matrix objects over-ride power to be matrix raised to a power. The + same warning about using power inside a function that uses + asanyarray(...) to get an array object holds for this fact. + +5. The default __array_priority\__ of matrix objects is 10.0, and + therefore mixed operations with ndarrays always produce matrices. + +6. Matrices have special attributes which make calculations easier. These + are + + .. autosummary:: + :toctree: generated/ + + matrix.T + matrix.H + matrix.I + matrix.A + +.. warning:: + + Matrix objects over-ride multiplication, '*', and power, '**', to be + matrix-multiplication and matrix power, respectively. If your + subroutine can accept sub-classes and you do not convert to base-class + arrays, then you must use the ufuncs multiply and power to be sure + that you are performing the correct operation for all inputs. + +The matrix class is a Python subclass of the ndarray and can be used +as a reference for how to construct your own subclass of the ndarray. +Matrices can be created from other matrices, strings, and anything +else that can be converted to an ndarray . The name "mat "is an +alias for "matrix "in NumPy. + +.. autosummary:: + :toctree: generated/ + + matrix + asmatrix + bmat + +Example 1: Matrix creation from a string + +>>> a=mat('1 2 3; 4 5 3') +>>> print (a*a.T).I +[[ 0.2924 -0.1345] + [-0.1345 0.0819]] + +Example 2: Matrix creation from nested sequence + +>>> mat([[1,5,10],[1.0,3,4j]]) +matrix([[ 1.+0.j, 5.+0.j, 10.+0.j], + [ 1.+0.j, 3.+0.j, 0.+4.j]]) + +Example 3: Matrix creation from an array + +>>> mat(random.rand(3,3)).T +matrix([[ 0.7699, 0.7922, 0.3294], + [ 0.2792, 0.0101, 0.9219], + [ 0.3398, 0.7571, 0.8197]]) + +Memory-mapped file arrays +========================= + +.. index:: + single: memory maps + +.. currentmodule:: numpy + +Memory-mapped files are useful for reading and/or modifying small +segments of a large file with regular layout, without reading the +entire file into memory. A simple subclass of the ndarray uses a +memory-mapped file for the data buffer of the array. For small files, +the over-head of reading the entire file into memory is typically not +significant, however for large files using memory mapping can save +considerable resources. + +Memory-mapped-file arrays have one additional method (besides those +they inherit from the ndarray): :meth:.flush() <memmap.flush> which +must be called manually by the user to ensure that any changes to the +array actually get written to disk. + +.. note:: + + Memory-mapped arrays use the the Python memory-map object which (prior + to Python 2.5) does not allow files to be larger than a certain size + depending on the platform. This size is always < 2GB even on 64-bit + systems. + +.. autosummary:: + :toctree: generated/ + + memmap + memmap.flush + +Example: + +>>> a = memmap('newfile.dat', dtype=float, mode='w+', shape=1000) +>>> a[10] = 10.0 +>>> a[30] = 30.0 +>>> del a +>>> b = fromfile('newfile.dat', dtype=float) +>>> print b[10], b[30] +10.0 30.0 +>>> a = memmap('newfile.dat', dtype=float) +>>> print a[10], a[30] +10.0 30.0 + + +Character arrays (:mod:numpy.char) +==================================== + +.. seealso:: :ref:routines.array-creation.char + +.. index:: + single: character arrays + +These are enhanced arrays of either :class:string type or +:class:unicode_ type. These arrays inherit from the +:class:ndarray, but specially-define the operations +, *, +and % on a (broadcasting) element-by-element basis. These +operations are not available on the standard :class:ndarray of +character type. In addition, the :class:chararray has all of the +standard :class:string <str> (and :class:unicode) methods, +executing them on an element-by-element basis. Perhaps the easiest way +to create a chararray is to use :meth:self.view(chararray) +<ndarray.view> where *self* is an ndarray of string or unicode +data-type. However, a chararray can also be created using the +:meth:numpy.chararray constructor, or via the +:func:numpy.char.array function: + +.. autosummary:: + :toctree: generated/ + + chararray + core.defchararray.array + +Another difference with the standard ndarray of string data-type is +that the chararray inherits the feature introduced by Numarray that +white-space at the end of any element in the array will be ignored on +item retrieval and comparison operations. + + +.. _arrays.classes.rec: + +Record arrays (:mod:numpy.rec) +================================ + +.. seealso:: :ref:routines.array-creation.rec, :ref:routines.dtype, + :ref:arrays.dtypes. + +Numpy provides the :class:recarray class which allows accessing the +fields of a record/structured array as attributes, and a corresponding +scalar data type object :class:record. + +.. currentmodule:: numpy + +.. autosummary:: + :toctree: generated/ + + recarray + record + +Masked arrays (:mod:numpy.ma) +=============================== + +.. seealso:: :ref:routines.ma + +.. XXX: masked array documentation should be improved + +.. currentmodule:: numpy + +.. index:: + single: masked arrays + +.. autosummary:: + :toctree: generated/ + + ma.masked_array + +.. automodule:: numpy.ma + + +Standard container class +======================== + +.. currentmodule:: numpy + +For backward compatibility and as a standard "container "class, the +UserArray from Numeric has been brought over to NumPy and named +:class:numpy.lib.user_array.container The container class is a +Python class whose self.array attribute is an ndarray. Multiple +inheritance is probably easier with numpy.lib.user_array.container +than with the ndarray itself and so it is included by default. It is +not documented here beyond mentioning its existence because you are +encouraged to use the ndarray class directly if you can. + +.. autosummary:: + :toctree: generated/ + + numpy.lib.user_array.container + +.. index:: + single: user_array + single: container class + + +Array Iterators +=============== + +.. currentmodule:: numpy + +.. index:: + single: array iterator + +Iterators are a powerful concept for array processing. Essentially, +iterators implement a generalized for-loop. If *myiter* is an iterator +object, then the Python code:: + + for val in myiter: + ... + some code involving val + ... + +calls val = myiter.next() repeatedly until :exc:StopIteration is +raised by the iterator. There are several ways to iterate over an +array that may be useful: default iteration, flat iteration, and +:math:N-dimensional enumeration. + + +Default iteration +----------------- + +The default iterator of an ndarray object is the default Python +iterator of a sequence type. Thus, when the array object itself is +used as an iterator. The default behavior is equivalent to:: + + for i in arr.shape[0]: + val = arr[i] + +This default iterator selects a sub-array of dimension :math:N-1 from the array. This can be a useful construct for defining recursive +algorithms. To loop over the entire array requires :math:N for-loops. + +>>> a = arange(24).reshape(3,2,4)+10 +>>> for val in a: +... print 'item:', val +item: [[10 11 12 13] + [14 15 16 17]] +item: [[18 19 20 21] + [22 23 24 25]] +item: [[26 27 28 29] + [30 31 32 33]] + + +Flat iteration +-------------- + +.. autosummary:: + :toctree: generated/ + + ndarray.flat + +As mentioned previously, the flat attribute of ndarray objects returns +an iterator that will cycle over the entire array in C-style +contiguous order. + +>>> for i, val in enumerate(a.flat): +... if i%5 == 0: print i, val +0 10 +5 15 +10 20 +15 25 +20 30 + +Here, I've used the built-in enumerate iterator to return the iterator +index as well as the value. + + +N-dimensional enumeration +------------------------- + +.. autosummary:: + :toctree: generated/ + + ndenumerate + +Sometimes it may be useful to get the N-dimensional index while +iterating. The ndenumerate iterator can achieve this. + +>>> for i, val in ndenumerate(a): +... if sum(i)%5 == 0: print i, val +(0, 0, 0) 10 +(1, 1, 3) 25 +(2, 0, 3) 29 +(2, 1, 2) 32 + + +Iterator for broadcasting +------------------------- + +.. autosummary:: + :toctree: generated/ + + broadcast + +The general concept of broadcasting is also available from Python +using the :class:broadcast iterator. This object takes :math:N +objects as inputs and returns an iterator that returns tuples +providing each of the input sequence elements in the broadcasted +result. + +>>> for val in broadcast([[1,0],[2,3]],[0,1]): +... print val +(1, 0) +(0, 1) +(2, 0) +(3, 1) Added: numpy-docs/trunk/source/reference/arrays.dtypes.rst =================================================================== --- numpy-docs/trunk/source/reference/arrays.dtypes.rst 2008-10-26 17:50:36 UTC (rev 5958) +++ numpy-docs/trunk/source/reference/arrays.dtypes.rst 2008-10-26 17:57:55 UTC (rev 5959) @@ -0,0 +1,513 @@ +.. currentmodule:: numpy + +.. _arrays.dtypes: + +********************************** +Data type objects (:class:dtype) +********************************** + +A data type object (an instance of :class:numpy.dtype class) +describes how the bytes in the fixed-size block of memory +corresponding to an array item should be interpreted. It describes the +following aspects of the data: + +1. Type of the data (integer, float, Python object, etc.) +2. Size of the data (how many bytes is in *e.g.* the integer) +3. Byte order of the data (:term:little-endian or :term:big-endian) +4. If the data type is a :term:record, an aggregate of other + data types, (*e.g.*, describing an array item consisting of + an integer and a float), + + 1. what are the names of the ":term:fields <field>" of the record, + by which they can be :ref:accessed <arrays.indexing.rec>, + 2. what is the data-type of each :term:field, and + 3. which part of the memory block each field takes. + +5. If the data is a sub-array, what is its shape and data type. + +.. index:: + pair: dtype; scalar + +To describe the type of scalar data, there are several :ref:built-in +scalar types <arrays.scalars.built-in> in Numpy for various precision +of integers, floating-point numbers, *etc*. An item extracted from an +array, *e.g.*, by indexing, will be a Python object whose type is the +scalar type associated with the data type of the array. + +Note that the scalar types are not :class:dtype objects, even though +they can be used in place of one whenever a data type specification is +needed in Numpy. + +.. index:: + pair: dtype; field + pair: dtype; record + +Record data types are formed by creating a data type whose +:term:fields contain other data types. Each field has a name by +which it can be :ref:accessed <arrays.indexing.rec>. The parent data +type should be of sufficient size to contain all its fields; the +parent can for example be based on the :class:void type which allows +an arbitrary item size. Record data types may also contain other record +types and fixed-size sub-array data types in their fields. + +.. index:: + pair: dtype; sub-array + +Finally, a data type can describe items that are themselves arrays of +items of another data type. These sub-arrays must, however, be of a +fixed size. If an array is created using a data-type describing a +sub-array, the dimensions of the sub-array are appended to the shape +of the array when the array is created. Sub-arrays in a field of a +record behave differently, see :ref:arrays.indexing.rec. + +.. admonition:: Example + + A simple data type containing a 32-bit big-endian integer: + (see :ref:arrays.dtypes.constructing for details on construction) + + >>> dt = np.dtype('>i4') + >>> dt.byteorder + '>' + >>> dt.itemsize + 4 + >>> dt.name + 'int32' + >>> dt.type is np.int32 + True + + The corresponding array scalar type is :class:int32. + +.. admonition:: Example + + A record data type containing a 16-character string (in field 'name') + and a sub-array of two 64-bit floating-point number (in field 'grades'): + + >>> dt = np.dtype([('name', np.str_, 16), ('grades', np.float64, (2,))]) + >>> dt['name'] + dtype('|S16') + >>> dt['grades'] + dtype(('float64',(2,))) + + Items of an array of this data type are wrapped in an :ref:array + scalar <arrays.scalars> type that also has two fields: + + >>> x = np.array([('Sarah', (8.0, 7.0)), ('John', (6.0, 7.0))], dtype=dt) + >>> x[1] + ('John', [6.0, 7.0]) + >>> x[1]['grades'] + array([ 6., 7.]) + >>> type(x[1]) + <type 'numpy.void'> + >>> type(x[1]['grades']) + <type 'numpy.ndarray'> + +.. _arrays.dtypes.constructing: + +Specifying and constructing data types +====================================== + +Whenever a data-type is required in a NumPy function or method, either +a :class:dtype object or something that can be converted to one can +be supplied. Such conversions are done by the :class:dtype +constructor: + +.. autosummary:: + :toctree: generated/ + + dtype + +What can be converted to a data-type object is described below: + +:class:dtype object + + .. index:: + triple: dtype; construction; from dtype + + Used as-is. + +:const:None + + .. index:: + triple: dtype; construction; from None + + The default data type: :class:float_. + +.. index:: + triple: dtype; construction; from type + +Array-scalar types + + The 21 built-in :ref:array scalar type objects + <arrays.scalars.built-in> all convert to an associated data-type object. + This is true for their sub-classes as well. + + Note that not all data-type information can be supplied with a + type-object: for example, :term:flexible data-types have + a default *itemsize* of 0, and require an explicitly given size + to be useful. + + .. admonition:: Example + + >>> dt = np.dtype(np.int32) # 32-bit integer + >>> dt = np.dtype(np.complex128) # 128-bit complex floating-point number + +Generic types + + The generic hierarchical type objects convert to corresponding + type objects according to the associations: + + ===================================================== =============== + :class:number, :class:inexact, :class:floating :class:float + :class:complexfloating :class:cfloat + :class:integer, :class:signedinteger :class:int\_ + :class:unsignedinteger :class:uint + :class:character :class:string + :class:generic, :class:flexible :class:void + ===================================================== =============== + +Built-in Python types + + Several python types are equivalent to a corresponding + array scalar when used to generate a :class:dtype object: + + ================ =============== + :class:int :class:int\_ + :class:bool :class:bool\_ + :class:float :class:float\_ + :class:complex :class:cfloat + :class:str :class:string + :class:unicode :class:unicode\_ + :class:buffer :class:void + (all others) :class:object_ + ================ =============== + + .. admonition:: Example + + >>> dt = np.dtype(float) # Python-compatible floating-point number + >>> dt = np.dtype(int) # Python-compatible integer + >>> dt = np.dtype(object) # Python object + +Types with .dtype + + Any type object with a dtype attribute: The attribute will be + accessed and used directly. The attribute must return something + that is convertible into a dtype object. + +.. index:: + triple: dtype; construction; from string + +Several kinds of strings can be converted. Recognized strings can be +prepended with '>' (:term:big-endian), '<' +(:term:little-endian), or '=' (hardware-native, the default), to +specify the byte order. + +One-character strings + + Each built-in data-type has a character code + (the updated Numeric typecodes), that uniquely identifies it. + + .. admonition:: Example + + >>> dt = np.dtype('b') # byte, native byte order + >>> dt = np.dtype('>H') # big-endian unsigned short + >>> dt = np.dtype('<f') # little-endian single-precision float + >>> dt = np.dtype('d') # double-precision floating-point number + +Array-protocol type strings (see :ref:arrays.interface) + + The first character specifies the kind of data and the remaining + characters specify how many bytes of data. The supported kinds are + + ================ ======================== + 'b' Boolean + 'i' (signed) integer + 'u' unsigned integer + 'f' floating-point + 'c' complex-floating point + 'S', 'a' string + 'U' unicode + 'V' anything (:class:void) + ================ ======================== + + .. admonition:: Example + + >>> dt = np.dtype('i4') # 32-bit signed integer + >>> dt = np.dtype('f8') # 64-bit floating-point number + >>> dt = np.dtype('c16') # 128-bit complex floating-point number + >>> dt = np.dtype('a25') # 25-character string + +String with comma-separated fields + + Numarray introduced a short-hand notation for specifying the format + of a record as a comma-separated string of basic formats. + + A basic format in this context is an optional shape specifier + followed by an array-protocol type string. Parenthesis are required + on the shape if it is greater than 1-d. NumPy allows a modification + on the format in that any string that can uniquely identify the + type can be used to specify the data-type in a field. + The generated data-type fields are named 'f0', 'f2', ..., + 'f<N-1>' where N (>1) is the number of comma-separated basic + formats in the string. If the optional shape specifier is provided, + then the data-type for the corresponding field describes a sub-array. + + .. admonition:: Example + + - field named f0 containing a 32-bit integer + - field named f1 containing a 2 x 3 sub-array + of 64-bit floating-point numbers + - field named f2 containing a 32-bit floating-point number + + >>> dt = np.dtype("i4, (2,3)f8, f4") + + - field named f0 containing a 3-character string + - field named f1 containing a sub-array of shape (3,) + containing 64-bit unsigned integers + - field named f2 containing a 3 x 4 sub-array + containing 10-character strings + + >>> dt = np.dtype("a3, 3u8, (3,4)a10") + +Type strings + + Any string in :obj:numpy.sctypeDict.keys(): + + .. admonition:: Example + + >>> dt = np.dtype('uint32') # 32-bit unsigned integer + >>> dt = np.dtype('Float64') # 64-bit floating-point number + +.. index:: + triple: dtype; construction; from tuple + +(flexible_dtype, itemsize) + + The first argument must be an object that is converted to a + flexible data-type object (one whose element size is 0), the + second argument is an integer providing the desired itemsize. + + .. admonition:: Example + + >>> dt = np.dtype((void, 10)) # 10-byte wide data block + >>> dt = np.dtype((str, 35)) # 35-character string + >>> dt = np.dtype(('U', 10)) # 10-character unicode string + +(fixed_dtype, shape) + + .. index:: + pair: dtype; sub-array + + The first argument is any object that can be converted into a + fixed-size data-type object. The second argument is the desired + shape of this type. If the shape parameter is 1, then the + data-type object is equivalent to fixed dtype. If *shape* is a + tuple, then the new dtype defines a sub-array of the given shape. + + .. admonition:: Example + + >>> dt = np.dtype((np.int32, (2,2))) # 2 x 2 integer sub-array + >>> dt = np.dtype(('S10', 1)) # 10-character string + >>> dt = np.dtype(('i4, (2,3)f8, f4', (2,3))) # 2 x 3 record sub-array + +(base_dtype, new_dtype) + + Both arguments must be convertible to data-type objects in this + case. The *base_dtype* is the data-type object that the new + data-type builds on. This is how you could assign named fields to + any built-in data-type object. + + .. admonition:: Example + + 32-bit integer, whose first two bytes are interpreted as an integer + via field real, and the following two bytes via field imag. + + >>> dt = np.dtype((np.int32, {'real': (np.int16, 0), 'imag': (np.int16, 2)}) + + 32-bit integer, which is interpreted as consisting of a sub-array + of shape (4,) containing 8-bit integers: + + >>> dt = np.dtype((np.int32, (np.int8, 4))) + + 32-bit integer, containing fields r, g, b, a that + interpret the 4 bytes in the integer as four unsigned integers: + + >>> dt = np.dtype(('i4', [('r','u1'),('g','u1'),('b','u1'),('a','u1')])) + +.. note:: XXX: does the second-to-last example above make sense? + +.. index:: + triple: dtype; construction; from list + +[(field_name, field_dtype, field_shape), ...] + + *obj* should be a list of fields where each field is described by a + tuple of length 2 or 3. (Equivalent to the descr item in the + :obj:__array_interface__ attribute.) + + The first element, *field_name*, is the field name (if this is + '' then a standard field name, 'f#', is assigned). The + field name may also be a 2-tuple of strings where the first string + is either a "title" (which may be any string or unicode string) or + meta-data for the field which can be any object, and the second + string is the "name" which must be a valid Python identifier. + + The second element, *field_dtype*, can be anything that can be + interpreted as a data-type. + + The optional third element *field_shape* contains the shape if this + field represents an array of the data-type in the second + element. Note that a 3-tuple with a third argument equal to 1 is + equivalent to a 2-tuple. + + This style does not accept *align* in the :class:dtype + constructor as it is assumed that all of the memory is accounted + for by the array interface description. + + .. admonition:: Example + + Data-type with fields big (big-endian 32-bit integer) and + little (little-endian 32-bit integer): + + >>> dt = np.dtype([('big', '>i4'), ('little', '<i4')]) + + Data-type with fields R, G, B, A, each being an + unsigned 8-bit integer: + + >>> dt = np.dtype([('R','u1'), ('G','u1'), ('B','u1'), ('A','u1')]) + +.. index:: + triple: dtype; construction; from dict + +{'names': ..., 'formats': ..., 'offsets': ..., 'titles': ...} + + This style has two required and two optional keys. The *names* + and *formats* keys are required. Their respective values are + equal-length lists with the field names and the field formats. + The field names must be strings and the field formats can be any + object accepted by :class:dtype constructor. + + The optional keys in the dictionary are *offsets* and *titles* and + their values must each be lists of the same length as the *names* + and *formats* lists. The *offsets* value is a list of byte offsets + (integers) for each field, while the *titles* value is a list of + titles for each field (:const:None can be used if no title is + desired for that field). The *titles* can be any :class:string + or :class:unicode object and will add another entry to the + fields dictionary keyed by the title and referencing the same + field tuple which will contain the title as an additional tuple + member. + + .. admonition:: Example + + Data type with fields r, g, b, a, each being + a 8-bit unsigned integer: + + >>> dt = np.dtype({'names': ['r','g','b','a'], + ... 'formats': [uint8, uint8, uint8, uint8]}) + + Data type with fields r and b (with the given titles), + both being 8-bit unsigned integers, the first at byte position + 0 from the start of the field and the second at position 2: + + >>> dt = np.dtype({'names': ['r','b'], 'formats': ['u1', 'u1'], + ... 'offsets': [0, 2], + ... 'titles': ['Red pixel', 'Blue pixel']}) + + +{'field1': ..., 'field2': ..., ...} + + This style allows passing in the :attr:fields <dtype.fields> + attribute of a data-type object. + + *obj* should contain string or unicode keys that refer to + (data-type, offset) or (data-type, offset, title) tuples. + + .. admonition:: Example + + Data type containing field col1 (10-character string at + byte position 0), col2 (32-bit float at byte position 10), + and col3 (integers at byte position 14): + + >>> dt = np.dtype({'col1': ('S10', 0), 'col2': (float32, 10), 'col3': (int, 14)}) + + +:class:dtype +============== + +Numpy data type descriptions are instances of the :class:dtype class. + +Attributes +---------- + +The type of the data is described by the following :class:dtype attributes: + +.. autosummary:: + :toctree: generated/ + + dtype.type + dtype.kind + dtype.char + dtype.num + dtype.str + +Size of the data is in turn described by: + +.. autosummary:: + :toctree: generated/ + + dtype.name + dtype.itemsize + +Endianness of this data: + +.. autosummary:: + :toctree: generated/ + + dtype.byteorder + +Information about sub-data-types in a :term:record: + +.. autosummary:: + :toctree: generated/ + + dtype.fields + dtype.names + +For data types that describe sub-arrays: + +.. autosummary:: + :toctree: generated/ + + dtype.subdtype + dtype.shape + +Attributes providing additional information: + +.. autosummary:: + :toctree: generated/ + + dtype.hasobject + dtype.flags + dtype.isbuiltin + dtype.isnative + dtype.descr + dtype.alignment + + +Methods +------- + +Data types have the following method for changing the byte order: + +.. autosummary:: + :toctree: generated/ + + dtype.newbyteorder + +The following methods implement the pickle protocol: + +.. autosummary:: + :toctree: generated/ + + dtype.__reduce__ + dtype.__setstate__ Added: numpy-docs/trunk/source/reference/arrays.indexing.rst =================================================================== --- numpy-docs/trunk/source/reference/arrays.indexing.rst 2008-10-26 17:50:36 UTC (rev 5958) +++ numpy-docs/trunk/source/reference/arrays.indexing.rst 2008-10-26 17:57:55 UTC (rev 5959) @@ -0,0 +1,375 @@ +.. _arrays.indexing: + +Indexing +======== + +.. sectionauthor:: adapted from "Guide to Numpy" by Travis E. Oliphant + +.. currentmodule:: numpy + +.. index:: indexing, slicing + +:class:ndarrays <ndarray> can be indexed using the standard Python +x[obj] syntax, where *x* is the array and *obj* the selection. +There are three kinds of indexing available: record access, basic +slicing, advanced indexing. Which one occurs depends on *obj*. + +.. note:: + + In Python, x[(exp1, exp2, ..., expN)] is equivalent to + x[exp1, exp2, ..., expN]; the latter is just syntactic sugar + for the former. + + +Basic Slicing +------------- + +Basic slicing extends Python's basic concept of slicing to N +dimensions. Basic slicing occurs when *obj* is a :class:slice object +(constructed by start:stop:step notation inside of brackets), an +integer, or a tuple of slice objects and integers. :const:Ellipsis +and :const:newaxis objects can be interspersed with these as +well. In order to remain backward compatible with a common usage in +Numeric, basic slicing is also initiated if the selection object is +any sequence (such as a :class:list) containing :class:slice +objects, the :const:Ellipsis object, or the :const:newaxis object, +but no integer arrays or other embedded sequences. + +.. index:: + triple: ndarray; special methods; getslice + triple: ndarray; special methods; setslice + single: ellipsis + single: newaxis + +The simplest case of indexing with *N* integers returns an :ref:array +scalar <arrays.scalars> representing the corresponding item. As in +Python, all indices are zero-based: for the *i*-th index :math:n_i, +the valid range is :math:0 \le n_i < d_i where :math:d_i is the +*i*-th element of the shape of the array. Negative indices are +interpreted as counting from the end of the array (*i.e.*, if *i < 0*, +it means :math:n_i + i). + + +All arrays generated by basic slicing are always :term:views <view> +of the original array. + +The standard rules of sequence slicing apply to basic slicing on a +per-dimension basis (including using a step index). Some useful +concepts to remember include: + +- The basic slice syntax is i:j:k where *i* is the starting index, + *j* is the stopping index, and *k* is the step (:math:k\neq0). + This selects the *m* elements (in the corresponding dimension) with + index values *i*, *i + k*, ..., *i + (m - 1) k* where + :math:m = q + (r\neq0) and *q* and *r* are the quotient and remainder + obtained by dividing *j - i* by *k*: *j - i = q k + r*, so that + *i + (m - 1) k < j*. + + .. admonition:: Example + + >>> x = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) + >>> x[1:7:2] + array([1, 3, 5]) + +- Negative *i* and *j* are interpreted as *n + i* and *n + j* where + *n* is the number of elements in the corresponding dimension. + Negative *k* makes stepping go towards smaller indices. + + .. admonition:: Example + + >>> x[-2:10] + array([8, 9]) + >>> x[-3:3:-1] + array([7, 6, 5, 4]) + +- Assume *n* is the number of elements in the dimension being + sliced. Then, if *i* is not given it defaults to 0 for *k > 0* and + *n* for *k < 0* . If *j* is not given it defaults to *n* for *k > 0* + and -1 for *k < 0* . If *k* is not given it defaults to 1. Note that + :: is the same as : and means select all indices along this + axis. + + .. admonition:: Example + + >>> x[5:] + array([5, 6, 7, 8, 9]) + +- If the number of objects in the selection tuple is less than + *N* , then : is assumed for any subsequent dimensions. + + .. admonition:: Example + + >>> x = np.array([[[1],[2],[3]], [[4],[5],[6]]]) + >>> x.shape + (2, 3, 1) + >>> x[1:2] + array([[[4], + [5], + [6]]]) + +- :const:Ellipsis expand to the number of : objects needed to + make a selection tuple of the same length as x.ndim. Only the + first ellipsis is expanded, any others are interpreted as :. + + .. admonition:: Example + + >>> x[...,0] + array([[1, 2, 3], + [4, 5, 6]]) + +- Each :const:newaxis object in the selection tuple serves to expand + the dimensions of the resulting selection by one unit-length + dimension. The added dimension is the position of the :const:newaxis + object in the selection tuple. + + .. admonition:: Example + + >>> x[:,np.newaxis,:,:].shape + (2, 1, 3, 1) + +- An integer, *i*, returns the same values as i:i+1 + **except** the dimensionality of the returned object is reduced by + 1. In particular, a selection tuple with the *p*-th + element an integer (and all other entries :) returns the + corresponding sub-array with dimension *N - 1*. If *N = 1* + then the returned object is an array scalar. These objects are + explained in :ref:arrays.scalars. + +- If the selection tuple has all entries : except the + *p*-th entry which is a slice object i:j:k, + then the returned array has dimension *N* formed by + concatenating the sub-arrays returned by integer indexing of + elements *i*, *i+k*, ..., *i + (m - 1) k < j*, + +- Basic slicing with more than one non-: entry in the slicing + tuple, acts like repeated application of slicing using a single + non-: entry, where the non-: entries are successively taken + (with all other non-: entries replaced by :). Thus, + x[ind1,...,ind2,:] acts like x[ind1][...,ind2,:] under basic + slicing. + + .. warning:: The above is **not** true for advanced slicing. + +- You may use slicing to set values in the array, but (unlike lists) you + can never grow the array. The size of the value to be set in + x[obj] = value must be (broadcastable) to the same shape as + x[obj]. + +.. index:: + pair: ndarray; view + +.. note:: + + Remember that a slicing tuple can always be constructed as *obj* + and used in the x[obj] notation. Slice objects can be used in + the construction in place of the [start:stop:step] + notation. For example, x[1:10:5,::-1] can also be implemented + as obj = (slice(1,10,5), slice(None,None,-1)); x[obj] . This + can be useful for constructing generic code that works on arrays + of arbitrary dimension. + +.. data:: newaxis + + The :const:newaxis object can be used in the basic slicing syntax + discussed above. :const:None can also be used instead of + :const:newaxis. + + +Advanced indexing +----------------- + +Advanced indexing is triggered when the selection object, *obj*, is a +non-tuple sequence object, an :class:ndarray (of data type integer or bool), +or a tuple with at least one sequence object or ndarray (of data type +integer or bool). There are two types of advanced indexing: integer +and Boolean. + +Advanced indexing always returns a *copy* of the data (contrast with +basic slicing that returns a :term:view). + +Integer +^^^^^^^ + +Integer indexing allows selection of arbitrary items in the array +based on their *N*-dimensional index. This kind of selection occurs +when advanced indexing is triggered and the selection object is not +an array of data type bool. For the discussion below, when the +selection object is not a tuple, it will be referred to as if it had +been promoted to a 1-tuple, which will be called the selection +tuple. The rules of advanced integer-style indexing are: + +- If the length of the selection tuple is larger than *N* an error is raised. + +- All sequences and scalars in the selection tuple are converted to + :class:intp indexing arrays. + +- All selection tuple objects must be convertible to :class:intp + arrays, :class:slice objects, or the :const:Ellipsis object. + +- The first :const:Ellipsis object will be expanded, and any other + :const:Ellipsis objects will be treated as full slice (:) + objects. The expanded :const:Ellipsis object is replaced with as + many full slice (:) objects as needed to make the length of the + selection tuple :math:N. + +- If the selection tuple is smaller than *N*, then as many : + objects as needed are added to the end of the selection tuple so + that the modified selection tuple has length *N*. + +- All the integer indexing arrays must be :ref:broadcastable + <arrays.broadcasting.broadcastable> to the same shape. + +- The shape of the output (or the needed shape of the object to be used + for setting) is the broadcasted shape. + +- After expanding any ellipses and filling out any missing : + objects in the selection tuple, then let :math:N_t be the number + of indexing arrays, and let :math:N_s = N - N_t be the number of + slice objects. Note that :math:N_t > 0 (or we wouldn't be doing + advanced integer indexing). + +- If :math:N_s = 0 then the *M*-dimensional result is constructed by + varying the index tuple (i_1, ..., i_M) over the range + of the result shape and for each value of the index tuple + (ind_1, ..., ind_M):: + + result[i_1, ..., i_M] == x[ind_1[i_1, ..., i_M], ind_2[i_1, ..., i_M], + ..., ind_N[i_1, ..., i_M]] + + .. admonition:: Example + + Suppose the shape of the broadcasted indexing arrays is 3-dimensional + and *N* is 2. Then the result is found by letting *i, j, k* run over + the shape found by broadcasting ind_1 and ind_2, and each + *i, j, k* yields:: + + result[i,j,k] = x[ind_1[i,j,k], ind_2[i,j,k]] + +- If :math:N_s > 0, then partial indexing is done. This can be + somewhat mind-boggling to understand, but if you think in terms of + the shapes of the arrays involved, it can be easier to grasp what + happens. In simple cases (*i.e.* one indexing array and *N - 1* slice + objects) it does exactly what you would expect (concatenation of + repeated application of basic slicing). The rule for partial + indexing is that the shape of the result (or the interpreted shape + of the object to be used in setting) is the shape of *x* with the + indexed subspace replaced with the broadcasted indexing subspace. If + the index subspaces are right next to each other, then the + broadcasted indexing space directly replaces all of the indexed + subspaces in *x*. If the indexing subspaces are separated (by slice + objects), then the broadcasted indexing space is first, followed by + the sliced subspace of *x*. + + .. admonition:: Example + + Suppose x.shape is (10,20,30) and ind is a (2,3,4)-shaped + indexing :class:intp array, then result = x[...,ind,:] has + shape (10,2,3,4,30) because the (20,)-shaped subspace has been + replaced with a (2,3,4)-shaped broadcasted indexing subspace. If + we let *i, j, k* loop over the (2,3,4)-shaped subspace then + result[...,i,j,k,:] = x[...,ind[i,j,k],:]. This example + produces the same result as :meth:x.take(ind, axis=-2) <ndarray.take>. + + .. admonition:: Example + + Now let x.shape be (10,20,30,40,50) and suppose ind_1 + and ind_2 are broadcastable to the shape (2,3,4). Then + x[:,ind_1,ind_2] has shape (10,2,3,4,40,50) because the + (20,30)-shaped subspace from X has been replaced with the + (2,3,4) subspace from the indices. However, + x[:,ind_1,:,ind_2] has shape (2,3,4,10,30,50) because there + is no unambiguous place to drop in the indexing subspace, thus + it is tacked-on to the beginning. It is always possible to use + :meth:.transpose() <ndarray.transpose> to move the subspace + anywhere desired. (Note that this example cannot be replicated + using :func:take.) + + +Boolean +^^^^^^^ + +This advanced indexing occurs when obj is an array object of Boolean +type (such as may be returned from comparison operators). It is always +equivalent to (but faster than) x[obj.nonzero()] where, as +described above, :meth:obj.nonzero() <ndarray.nonzero> returns a +tuple (of length :attr:obj.ndim <ndarray.ndim>) of integer index +arrays showing the :const:True elements of *obj*. + +The special case when obj.ndim == x.ndim is worth mentioning. In +this case x[obj] returns a 1-dimensional array filled with the +elements of *x* corresponding to the :const:True values of *obj*. +The search order will be C-style (last index varies the fastest). If +*obj* has :const:True values at entries that are outside of the +bounds of *x*, then an index error will be raised. + +You can also use Boolean arrays as element of the selection tuple. In +such instances, they will always be interpreted as :meth:nonzero(obj) +<ndarray.nonzero> and the equivalent integer indexing will be +done. + +.. warning:: + + The definition of advanced indexing means that x[(1,2,3),] is + fundamentally different than x[(1,2,3)]. The latter is + equivalent to x[1,2,3] which will trigger basic selection while + the former will trigger advanced indexing. Be sure to understand + why this is occurs. + + Also recognize that x[[1,2,3]] will trigger advanced indexing, + whereas x[[1,2,slice(None)]] will trigger basic slicing. + +.. note:: + + XXX: this section may need some tuning... + Also the above warning needs explanation as the last part is at odds + with the definition of basic indexing. + + +.. _arrays.indexing.rec: + +Record Access +------------- + +.. seealso:: :ref:arrays.dtypes, :ref:arrays.scalars + +If the :class:ndarray object is a record array, *i.e.* its data type +is a :term:record data type, the :term:fields <field> of the array +can be accessed by indexing the array with strings, dictionary-like. + +Indexing x['field-name'] returns a new :term:view to the array, +which is of the same shape as *x* (except when the field is a +sub-array) but of data type x.dtype['field-name'] and contains +only the part of the data in the specified field. Also record array +scalars can be "indexed" this way. + +If the accessed field is a sub-array, the dimensions of the sub-array +are appended to the shape of the result. + +.. admonition:: Example + + >>> x = np.zeros((2,2), dtype=[('a', np.int32), ('b', np.float64, (3,3))]) + >>> x['a'].shape + (2, 2) + >>> x['a'].dtype + dtype('int32') + >>> x['b'].shape + (2, 2, 3, 3) + >>> x['b'].dtype + dtype('float64') + + +Flat Iterator indexing +---------------------- + +:attr:x.flat <ndarray.flat> returns an iterator that will iterate +over the entire array (in C-contiguous style with the last index +varying the fastest). This iterator object can also be indexed using +basic slicing or advanced indexing as long as the selection object is +not a tuple. This should be clear from the fact that :attr:x.flat +<ndarray.flat> is a 1-dimensional view. It can be used for integer +indexing with 1-dimensional C-style-flat indices. The shape of any +returned array is therefore the shape of the integer indexing object. + +.. index:: + single: indexing + single: ndarray Added: numpy-docs/trunk/source/reference/arrays.interface.rst =================================================================== --- numpy-docs/trunk/source/reference/arrays.interface.rst 2008-10-26 17:50:36 UTC (rev 5958) +++ numpy-docs/trunk/source/reference/arrays.interface.rst 2008-10-26 17:57:55 UTC (rev 5959) @@ -0,0 +1,210 @@ +.. index:: + pair: array; interface + pair: array; protocol + +.. _arrays.interface: + +******************* +The Array Interface +******************* + +:version: 3 + +The array interface (sometimes called array protocol) was created in +2005 as a means for array-like Python objects to re-use each other's +data buffers intelligently whenever possible. The homogeneous +N-dimensional array interface is a default mechanism for objects to +share N-dimensional array memory and information. The interface +consists of a Python-side and a C-side using two attributes. Objects +wishing to be considered an N-dimensional array in application code +should support at least one of these attributes. Objects wishing to +support an N-dimensional array in application code should look for at +least one of these attributes and use the information provided +appropriately. + +This interface describes homogeneous arrays in the sense that each +item of the array has the same "type". This type can be very simple +or it can be a quite arbitrary and complicated C-like structure. + +There are two ways to use the interface: A Python side and a C-side. +Both are separate attributes. + +.. note:: + + An alternative to the array interface; + :cfunc:The Revised Buffer Protocol <PyObject_GetBuffer>, :pep:3118 + is introduced in Python 2.6. + +Python side +=========== + +This approach to the interface consists of the object having an +:data:__array_interface__ attribute. + +.. data:: __array_interface__ + + A dictionary of items (3 required and 5 optional). The optional + keys in the dictionary have implied defaults if they are not + provided. + + The keys are: + + **shape** (required) + + Tuple whose elements are the array size in each dimension. Each + entry is an integer (a Python int or long). Note that these + integers could be larger than the platform "int" or "long" + could hold (a Python int is a C long). It is up to the code + using this attribute to handle this appropriately; either by + raising an error when overflow is possible, or by using + :cdata:Py_LONG_LONG as the C type for the shapes. + + **typestr** (required) + + A string providing the basic type of the homogenous array The + basic string format consists of 3 parts: a character describing + the byteorder of the data (<: little-endian, >: + big-endian, |: not-relevant), a character code giving the + basic type of the array, and an integer providing the number of + bytes the type uses. + + The basic type character codes are: + + ===== ================================================================ + t Bit field (following integer gives the number of + bits in the bit field). + b Boolean (integer type where all values are only True or False) + i Integer + u Unsigned integer + f Floating point + c Complex floating point + O Object (i.e. the memory contains a pointer to :ctype:PyObject) + S String (fixed-length sequence of char) + U Unicode (fixed-length sequence of :ctype:Py_UNICODE) + V Other (void \* -- each item is a fixed-size chunk of memory) + ===== ================================================================ + + **descr** (optional) + + A list of tuples providing a more detailed description of the + memory layout for each item in the homogeneous array. Each + tuple in the list has two or three elements. Normally, this + attribute would be used when *typestr* is V[0-9]+, but this is + not a requirement. The only requirement is that the number of + bytes represented in the *typestr* key is the same as the total + number of bytes represented here. The idea is to support + descriptions of C-like structs (records) that make up array + elements. The elements of each tuple in the list are + + 1. A string providing a name associated with this portion of + the record. This could also be a tuple of ('full name', + 'basic_name') where basic name would be a valid Python + variable name representing the full name of the field. + + 2. Either a basic-type description string as in *typestr* or + another list (for nested records) + + 3. An optional shape tuple providing how many times this part + of the record should be repeated. No repeats are assumed + if this is not given. Very complicated structures can be + described using this generic interface. Notice, however, + that each element of the array is still of the same + data-type. Some examples of using this interface are given + below. + + **Default**: [('', typestr)] + + **data** (optional) + + A 2-tuple whose first argument is an integer (a long integer + if necessary) that points to the data-area storing the array + contents. This pointer must point to the first element of + data (in other words any offset is always ignored in this + case). The second entry in the tuple is a read-only flag (true + means the data area is read-only). + + This attribute can also be an object exposing the + :cfunc:buffer interface <PyObject_AsCharBuffer> which + will be used to share the data. If this key is not present (or + returns :class:None), then memory sharing will be done + through the buffer interface of the object itself. In this + case, the offset key can be used to indicate the start of the + buffer. A reference to the object exposing the array interface + must be stored by the new object if the memory area is to be + secured. + + **Default**: :const:None + + **strides** (optional) + + Either :const:None to indicate a C-style contiguous array or + a Tuple of strides which provides the number of bytes needed + to jump to the next array element in the corresponding + dimension. Each entry must be an integer (a Python + :const:int or :const:long). As with shape, the values may + be larger than can be represented by a C "int" or "long"; the + calling code should handle this appropiately, either by + raising an error, or by using :ctype:Py_LONG_LONG in C. The + default is :const:None which implies a C-style contiguous + memory buffer. In this model, the last dimension of the array + varies the fastest. For example, the default strides tuple + for an object whose array entries are 8 bytes long and whose + shape is (10,20,30) would be (4800, 240, 8) + + **Default**: :const:None (C-style contiguous) + + **mask** (optional) + + :const:None or an object exposing the array interface. All + elements of the mask array should be interpreted only as true + or not true indicating which elements of this array are valid. + The shape of this object should be "broadcastable" + <arrays.broadcasting.broadcastable> to the shape of the + original array. + + **Default**: :const:None (All array values are valid) + + **offset** (optional) + + An integer offset into the array data region. This can only be + used when data is :const:None or returns a :class:buffer + object. + + **Default**: 0. + + **version** (required) + + An integer showing the version of the interface (i.e. 3 for + this version). Be careful not to use this to invalidate + objects exposing future versions of the interface. + + +C-struct access +=============== + +This approach to the array interface allows for faster access to an +array using only one attribute lookup and a well-defined C-structure. + +.. cvar:: __array_struct__ + + A :ctype:PyCObject whose :cdata:voidptr member contains a + pointer to a filled :ctype:PyArrayInterface structure. Memory + for the structure is dynamically created and the :ctype:PyCObject + is also created with an appropriate destructor so the retriever of + this attribute simply has to apply :cfunc:Py_DECREF() to the + object returned by this attribute when it is finished. Also, + either the data needs to be copied out, or a reference to the + object exposing this attribute must be held to ensure the data is + not freed. Objects exposing the :obj:__array_struct__ interface + must also not reallocate their memory if other objects are + referencing them. + +.. admonition:: New since June 16, 2006: + + In the past most implementations used the "desc" member of the + :ctype:PyCObject itself (do not confuse this with the "descr" member of + the :ctype:PyArrayInterface structure above --- they are two separate + things) to hold the pointer to the object exposing the interface. + This is now an explicit part of the interface. Be sure to own a + reference to the object when the :ctype:PyCObject is created using + :ctype:PyCObject_FromVoidPtrAndDesc. Added: numpy-docs/trunk/source/reference/arrays.ndarray.rst =================================================================== --- numpy-docs/trunk/source/reference/arrays.ndarray.rst 2008-10-26 17:50:36 UTC (rev 5958) +++ numpy-docs/trunk/source/reference/arrays.ndarray.rst 2008-10-26 17:57:55 UTC (rev 5959) @@ -0,0 +1,529 @@ +.. _arrays.ndarray: + +****************************************** +The N-dimensional array (:class:ndarray) +****************************************** + +.. currentmodule:: numpy + +An :class:ndarray is a (usually fixed-size) multidimensional +container of items of the same type and size. The number of dimensions +and items in an array is defined by its :attr:shape <ndarray.shape>, +which is a :class:tuple of *N* integers that specify the sizes of +each dimension. The type of items in the array is specified by a +separate :ref:data-type object (dtype) <arrays.dtypes>, one of which +is associated with each ndarray. + +As with other container objects in Python, the contents of a +:class:ndarray can be accessed and modified by :ref:indexing or +slicing <arrays.indexing> the array (using for example *N* integers), +and via the methods and attributes of the :class:ndarray. + +.. index:: view, base + +Different :class:ndarrays <ndarray> can share the same data, so that +changes made in one :class:ndarray may be visible in another. That +is, an ndarray can be a *"view"* to another ndarray, and the data it +is referring to is taken care of by the *"base"* ndarray. ndarrays can +also be views to memory owned by Python :class:strings <str> or +objects implementing the :class:buffer or :ref:array +<arrays.interface> interfaces. + + +.. admonition:: Example + + A 2-dimensional array of size 2 x 3, composed of 4-byte integer elements: + + >>> x = np.array([[1, 2, 3], [4, 5, 6]], np.int32) + >>> type(x) + <type 'numpy.ndarray'> + >>> x.shape + (2, 3) + >>> x.dtype + dtype('int32') + + The array can be indexed using a Python container-like syntax: + + >>> x[1,2] + 6 + + For example :ref:slicing <arrays.indexing> can produce views of the array: + + >>> y = x[:,1] + >>> y[0] = 9 + >>> x + array([[1, 9, 3], + [4, 5, 6]]) + + +Constructing arrays +=================== + +New arrays can be constructed using the routines detailed in +:ref:routines.array-creation, and also by using the low-level +:class:ndarray constructor: + +.. autosummary:: + :toctree: generated/ + + ndarray + +.. _arrays.ndarray.indexing: + + +Indexing arrays +=============== + +Arrays can be indexed using an extended Python slicing syntax, +array[selection]. Similar syntax is also used for accessing +fields in a :ref:record array <arrays.dtypes>. + +.. seealso:: :ref:Array Indexing <arrays.indexing>. + +Internal memory layout of an ndarray +==================================== + +An instance of class :class:ndarray consists of a contiguous +one-dimensional segment of computer memory (owned by the array, or by +some other object), combined with an indexing scheme that maps *N* +integers into the location of an item in the block. The ranges in +which the indices can vary is specified by the :obj:shape +<ndarray.shape> of the array. How many bytes each item takes and how +the bytes are interpreted is defined by the :ref:data-type object +<arrays.dtypes> associated with the array. + +.. index:: C-order, Fortran-order, row-major, column-major, stride, offset + +A segment of memory is inherently 1-dimensional, and there are many +different schemes of arranging the items of an *N*-dimensional array to +a 1-dimensional block. Numpy is flexible, and :class:ndarray objects +can accommodate any *strided indexing scheme*. In a strided scheme, +the N-dimensional index :math:(n_0, n_1, ..., n_{N-1}) corresponds +to the offset (in bytes) + +.. math:: n_{\mathrm{offset}} = \sum_{k=0}^{N-1} s_k n_k + +from the beginning of the memory block associated with the +array. Here, :math:s_k are integers which specify the :obj:strides +<ndarray.strides> of the array. The :term:column-major order (used +for example in the Fortran language and in *Matlab*) and +:term:row-major order (used in C) are special cases of the strided +scheme, and correspond to the strides: + +.. math:: + + s_k^{\mathrm{column}} = \prod_{j=0}^{k-1} d_j , \quad s_k^{\mathrm{row}} = \prod_{j=k+1}^{N-1} d_j . + +.. index:: single-segment, contiguous, non-contiguous + +Both the C and Fortran orders are :term:contiguous, *i.e.* +:term:single-segment, memory layouts, in which every part of the +memory block can be accessed by some combination of the indices. + +Data in new :class:ndarrays <ndarray> is in the :term:row-major +(C) order, unless otherwise specified, but for example :ref:basic +array slicing <arrays.indexing> often produces :term:views <view> +in a different scheme. + +.. seealso: :ref:Indexing <arrays.ndarray.indexing>_ + +.. note:: + + Several algorithms in NumPy work on arbitrarily strided arrays. + However, some algorithms require single-segment arrays. When an + irregularly strided array is passed in to such algorithms, a copy + is automatically made. + + +Array attributes +================ + +Array attributes reflect information that is intrinsic to the array +itself. Generally, accessing an array through its attributes allows +you to get and sometimes set intrinsic properties of the array without +creating a new array. The exposed attributes are the core parts of an +array and only some of them can be reset meaningfully without creating +a new array. Information on each attribute is given below. + +Memory layout +------------- + +The following attributes contain information about the memory layout +of the array: + +.. autosummary:: + :toctree: generated/ + + ndarray.flags + ndarray.shape + ndarray.strides + ndarray.ndim + ndarray.data + ndarray.size + ndarray.itemsize + ndarray.nbytes + ndarray.base + +.. note:: XXX: update and check these docstrings. + +Data type +--------- + +.. seealso:: :ref:Data type objects <arrays.dtypes> + +The data type object associated with the array can be found in the +:attr:dtype <ndarray.dtype> attribute: + +.. autosummary:: + :toctree: generated/ + + ndarray.dtype + +.. note:: XXX: update the dtype attribute docstring: setting etc. + +Other attributes +---------------- + +.. autosummary:: + :toctree: generated/ + + ndarray.T + ndarray.real + ndarray.imag + ndarray.flat + ndarray.ctypes + __array_priority__ + + +.. _arrays.ndarray.array-interface: + +Array interface +--------------- + +.. seealso:: :ref:arrays.interface. + +========================== =================================== +:obj:__array_interface__ Python-side of the array interface +:obj:__array_struct__ C-side of the array interface +========================== =================================== + +:mod:ctypes foreign function interface +---------------------------------------- + +.. autosummary:: + :toctree: generated/ + + ndarray.ctypes + +.. note:: XXX: update and check these docstrings. + +Array methods +============= + +An :class:ndarray object has many methods which operate on or with +the array in some fashion, typically returning an array result. These +methods are explained below. + +For the following methods there are also corresponding functions in +:mod:numpy: :func:all, :func:any, :func:argmax, +:func:argmin, :func:argsort, :func:choose, :func:clip, +:func:compress, :func:copy, :func:cumprod, :func:cumsum, +:func:diagonal, :func:imag, :func:max <amax>, :func:mean, +:func:min <amin>, :func:nonzero, :func:prod, :func:ptp, :func:put, +:func:ravel, :func:real, :func:repeat, :func:reshape, +:func:round <around>, :func:searchsorted, :func:sort, :func:squeeze, +:func:std, :func:sum, :func:swapaxes, :func:take, +:func:trace, :func:transpose, :func:var. + +Array conversion +---------------- + +.. autosummary:: + :toctree: generated/ + + ndarray.item + ndarray.tolist + ndarray.itemset + ndarray.tostring + ndarray.tofile + ndarray.dump + ndarray.dumps + ndarray.astype + ndarray.byteswap + ndarray.copy + ndarray.view + ndarray.getfield + ndarray.setflags + ndarray.fill + +.. note:: XXX: update and check these docstrings. + +Shape manipulation +------------------ + +For reshape, resize, and transpose, the single tuple argument may be +replaced with n integers which will be interpreted as an n-tuple. + +.. autosummary:: + :toctree: generated/ + + ndarray.reshape + ndarray.resize + ndarray.transpose + ndarray.swapaxes + ndarray.flatten + ndarray.ravel + ndarray.squeeze + +Item selection and manipulation +------------------------------- + +For array methods that take an *axis* keyword, it defaults to +:const:None. If axis is *None*, then the array is treated as a 1-D +array. Any other value for *axis* represents the dimension along which +the operation should proceed. + +.. autosummary:: + :toctree: generated/ + + ndarray.take + ndarray.put + ndarray.repeat + ndarray.choose + ndarray.sort + ndarray.argsort + ndarray.searchsorted + ndarray.nonzero + ndarray.compress + ndarray.diagonal + +Calculation +----------- + +.. index:: axis + +Many of these methods take an argument named *axis*. In such cases, + +- If *axis* is *None* (the default), the array is treated as a 1-D + array and the operation is performed over the entire array. This + behavior is also the default if self is a 0-dimensional array or + array scalar. + +- If *axis* is an integer, then the operation is done over the given axis + (for each 1-D subarray that can be created along the given axis). + +The parameter *dtype* specifies the data type over which a reduction +operation (like summing) should take place. The default reduce data +type is the same as the data type of *self*. To avoid overflow, it can +be useful to perform the reduction using a larger data type. + +For several methods, an optional *out* argument can also be provided +and the result will be placed into the output array given. The *out* +argument must be an :class:ndarray and have the same number of +elements. It can have a different data type in which case casting will +be performed. + + +.. autosummary:: + :toctree: generated/ + + ndarray.argmax + ndarray.min + ndarray.argmin + ndarray.ptp + ndarray.clip + ndarray.conj + ndarray.round + ndarray.trace + ndarray.sum + ndarray.cumsum + ndarray.mean + ndarray.var + ndarray.std + ndarray.prod + ndarray.cumprod + ndarray.all + ndarray.any + +Arithmetic and comparison operations +==================================== + +.. note:: XXX: write all attributes explicitly here instead of relying on + the auto\* stuff? + +.. index:: comparison, arithmetic, operation, operator + +Arithmetic and comparison operations on :class:ndarrays <ndarray> +are defined as element-wise operations, and generally yield +:class:ndarray objects as results. + +Each of the arithmetic operations (+, -, *, /, //, +%, divmod(), ** or pow(), <<, >>, &, +^, |, ~) and the comparisons (==, <, >, +<=, >=, !=) is equivalent to the corresponding +:term:universal function (or :term:ufunc for short) in Numpy. For +more information, see the section on :ref:Universal Functions +<ufuncs>. + +Comparison operators: + +.. autosummary:: + :toctree: generated/ + + ndarray.__lt__ + ndarray.__le__ + ndarray.__gt__ + ndarray.__ge__ + ndarray.__eq__ + ndarray.__ne__ + +Truth value of an array (:func:bool()): + +.. autosummary:: + :toctree: generated/ + + ndarray.__nonzero__ + +.. note:: + + Truth-value testing of an array invokes + :meth:ndarray.__nonzero__, which raises an error if the number of + elements in the the array is larger than 1, because the truth value + of such arrays is ambiguous. Use :meth:.any() <ndarray.any> and + :meth:.all() <ndarray.all> instead to be clear about what is meant in + such cases. (If the number of elements is 0, the array evaluates to + False.) + + +Unary operations: + +.. autosummary:: + :toctree: generated/ + + ndarray.__neg__ + ndarray.__pos__ + ndarray.__abs__ + ndarray.__invert__ + +Arithmetic: + +.. autosummary:: + :toctree: generated/ + + ndarray.__add__ + ndarray.__sub__ + ndarray.__mul__ + ndarray.__div__ + ndarray.__truediv__ + ndarray.__floordiv__ + ndarray.__mod__ + ndarray.__divmod__ + ndarray.__pow__ + ndarray.__lshift__ + ndarray.__rshift__ + ndarray.__and__ + ndarray.__or__ + ndarray.__xor__ + +.. note:: + + - Any third argument to :func:pow() is silently ignored, + as the underlying :func:ufunc <power> only takes two arguments. + + - The three division operators are all defined; :obj:div is active + by default, :obj:truediv is active when + :obj:__future__ division is in effect. + + - Because :class:ndarray is a built-in type (written in C), the + __r{op}__ special methods are not directly defined. + + - The functions called to implement many arithmetic special methods + for arrays can be modified using :func:set_numeric_ops. + +Arithmetic, in-place: + +.. autosummary:: + :toctree: generated/ + + ndarray.__iadd__ + ndarray.__isub__ + ndarray.__imul__ + ndarray.__idiv__ + ndarray.__itruediv__ + ndarray.__ifloordiv__ + ndarray.__imod__ + ndarray.__ipow__ + ndarray.__ilshift__ + ndarray.__irshift__ + ndarray.__iand__ + ndarray.__ior__ + ndarray.__ixor__ + +.. warning:: + + In place operations will perform the calculation using the + precision decided by the data type of the two operands, but will + silently downcast the result (if necessary) so it can fit back into + the array. Therefore, for mixed precision calculations, A {op}= + B can be different than A = A {op} B. For example, suppose + a = ones((3,3)). Then, a += 3j is different than a = a + + 3j: While they both perform the same computation, a += 3 + casts the result to fit back in a, whereas a = a + 3j + re-binds the name a to the result. + + +Special methods +=============== + +For standard library functions: + +.. autosummary:: + :toctree: generated/ + + ndarray.__copy__ + ndarray.__deepcopy__ + ndarray.__reduce__ + ndarray.__setstate__ + +Basic customization: + +.. autosummary:: + :toctree: generated/ + + ndarray.__new__ + ndarray.__array__ + ndarray.__array_wrap__ + +Container customization: (see :ref:Indexing <arrays.indexing>) + +.. autosummary:: + :toctree: generated/ + + ndarray.__len__ + ndarray.__getitem__ + ndarray.__setitem__ + ndarray.__getslice__ + ndarray.__setslice__ + ndarray.__contains__ + +Conversion; the operations :func:complex(), :func:int(), +:func:long(), :func:float(), :func:oct(), and +:func:hex(). They work only on arrays that have one element in them +and return the appropriate scalar. + +.. autosummary:: + :toctree: generated/ + + ndarray.__int__ + ndarray.__long__ + ndarray.__float__ + ndarray.__oct__ + ndarray.__hex__ + +String representations: + +.. autosummary:: + :toctree: generated/ + + ndarray.__str__ + ndarray.__repr__ Added: numpy-docs/trunk/source/reference/arrays.rst =================================================================== --- numpy-docs/trunk/source/reference/arrays.rst 2008-10-26 17:50:36 UTC (rev 5958) +++ numpy-docs/trunk/source/reference/arrays.rst 2008-10-26 17:57:55 UTC (rev 5959) @@ -0,0 +1,46 @@ +.. _arrays: + +************* +Array objects +************* + +.. currentmodule:: numpy + +NumPy provides an N-dimensional array type, the :ref:ndarray +<arrays.ndarray>, which describes a collection of "items" of the same +type. The items can be :ref:indexed <arrays.indexing> using for +example N integers. + +All ndarrays are :term:homogenous: every item takes up the same size +block of memory, and all blocks are interpreted in exactly the same +way. How each item in the array is to be interpreted is specified by a +separate :ref:data-type object <arrays.dtypes>, one of which is associated +with every array. In addition to basic types (integers, floats, +*etc.*), the data type objects can also represent data structures. + +An item extracted from an array, *e.g.*, by indexing, is represented +by a Python object whose type is one of the :ref:array scalar types +<arrays.scalars> built in Numpy. The array scalars allow easy manipulation +of also more complicated arrangements of data. + +.. figure:: figures/threefundamental.png + + **Figure** + Conceptual diagram showing the relationship between the three + fundamental objects used to describe the data in an array: 1) the + ndarray itself, 2) the data-type object that describes the layout + of a single fixed-size element of the array, 3) the array-scalar + Python object that is returned when a single element of the array + is accessed. + + + +.. toctree:: + :maxdepth: 2 + + arrays.ndarray + arrays.scalars + arrays.dtypes + arrays.indexing + arrays.classes + arrays.interface Added: numpy-docs/trunk/source/reference/arrays.scalars.rst =================================================================== --- numpy-docs/trunk/source/reference/arrays.scalars.rst 2008-10-26 17:50:36 UTC (rev 5958) +++ numpy-docs/trunk/source/reference/arrays.scalars.rst 2008-10-26 17:57:55 UTC (rev 5959) @@ -0,0 +1,288 @@ +.. _arrays.scalars: + +******* +Scalars +******* + +.. currentmodule:: numpy + +Python defines only one type of a particular data class (there is only +one integer type, one floating-point type, etc.). This can be +convenient in applications that don't need to be concerned with all +the ways data can be represented in a computer. For scientific +computing, however, more control is often needed. + +In NumPy, there are 21 new fundamental Python types to describe +different types of scalars. These type descriptors are mostly based on +the types available in the C language that CPython is written in, with +several additional types compatible with Python's types. + +Array scalars have the same attributes and methods as :class:ndarrays +<ndarray>. [#]_ This allows one to treat items of an array partly on +the same footing as arrays, smoothing out rough edges that result when +mixing scalar and array operations. + +Array scalars live in a hierarchy (see the Figure below) of data +types. They can be detected using the hierarchy: For example, +isinstance(val, np.generic) will return :const:True if *val* is +an array scalar object. Alternatively, what kind of array scalar is +present can be determined using other members of the data type +hierarchy. Thus, for example isinstance(val, np.complexfloating) +will return :const:True if *val* is a complex valued type, while +:const:isinstance(val, np.flexible) will return true if *val* is one +of the flexible itemsize array types (:class:string, +:class:unicode, :class:void). + +.. figure:: figures/dtype-hierarchy.png + + **Figure:** Hierarchy of type objects representing the array data + types. Not shown are the two integer types :class:intp and + :class:uintp which just point to the integer type that holds a + pointer for the platform. All the number types can be obtained + using bit-width names as well. + +.. [#] However, array scalars are immutable, so that none of the array + scalar attributes are settable. + +.. _arrays.scalars.character-codes: + +.. _arrays.scalars.built-in: + +Built-in scalar types +===================== + +The built-in scalar types are shown below. Along with their (mostly) +C-derived names, the integer, float, and complex data-types are also +available using a bit-width convention so that an array of the right +size can always be ensured (e.g. :class:int8, :class:float64, +:class:complex128). Two aliases (:class:intp and :class:uintp) +pointing to the integer type that is sufficiently large to hold a C pointer +are also provided. The C-like names are associated with character codes, +which are shown in the table. Use of the character codes, however, +is discouraged. + +Five of the scalar types are essentially equivalent to fundamental +Python types and therefore inherit from them as well as from the +generic array scalar type: + +==================== ==================== +Array scalar type Related Python type +==================== ==================== +:class:int_ :class:IntType +:class:float_ :class:FloatType +:class:complex_ :class:ComplexType +:class:str_ :class:StringType +:class:unicode_ :class:UnicodeType +==================== ==================== + +The :class:bool_ data type is very similar to the Python +:class:BooleanType but does not inherit from it because Python's +:class:BooleanType does not allow itself to be inherited from, and +on the C-level the size of the actual bool data is not the same as a +Python Boolean scalar. + +.. warning:: + + The :class:bool_ type is not a subclass of the :class:int_ type + (the :class:bool_ is not even a number type). This is different + than Python's default implementation of :class:bool as a + sub-class of int. + + +.. tip:: The default data type in Numpy is :class:float_. + +In the tables below, platform? means that the type may not +available on all platforms. Compatibility with different C or Python +types is indicated: two types are compatible if their data is of the +same size and interpreted in the same way. + +Booleans: + +=================== ============================= =============== +Type Remarks Character code +=================== ============================= =============== +:class:bool_ compatible: Python bool '?' +:class:bool8 8 bits +=================== ============================= =============== + +Integers: + +=================== ============================= =============== +:class:byte compatible: C char 'b' +:class:short compatible: C short 'h' +:class:intc compatible: C int 'i' +:class:int_ compatible: Python int 'l' +:class:longlong compatible: C long long 'q' +:class:intp large enough to fit a pointer 'p' +:class:int8 8 bits +:class:int16 16 bits +:class:int32 32 bits +:class:int64 64 bits +=================== ============================= =============== + +Unsigned integers: + +=================== ============================= =============== +:class:ubyte compatible: C unsigned char 'B' +:class:ushort compatible: C unsigned short 'H' +:class:uintc compatible: C unsigned int 'I' +:class:uint compatible: Python int 'L' +:class:ulonglong compatible: C long long 'Q' +:class:uintp large enough to fit a pointer 'P' +:class:uint8 8 bits +:class:uint16 16 bits +:class:uint32 32 bits +:class:uint64 64 bits +=================== ============================= =============== + +Floating-point numbers: + +=================== ============================= =============== +:class:single compatible: C float 'f' +:class:double compatible: C double +:class:float_ compatible: Python float 'd' +:class:longfloat compatible: C long float 'g' +:class:float32 32 bits +:class:float64 64 bits +:class:float96 92 bits, platform? +:class:float128 128 bits, platform? +=================== ============================= =============== + +Complex floating-point numbers: + +=================== ============================= =============== +:class:csingle 'F' +:class:complex_ compatible: Python complex 'D' +:class:clongfloat 'G' +:class:complex64 two 32-bit floats +:class:complex128 two 64-bit floats +:class:complex192 two 96-bit floats, + platform? +:class:complex256 two 128-bit floats, + platform? +=================== ============================= =============== + +Any Python object: + +=================== ============================= =============== +:class:object_ any Python object 'O' +=================== ============================= =============== + +.. note:: + + The data actually stored in :term:object arrays <object array> + (*i.e.* arrays having dtype :class:object_) are references to + Python objects, not the objects themselves. Hence, object arrays + behave more like usual Python :class:lists <list>, in the sense + that their contents need not be of the same Python type. + + The object type is also special because an array containing + :class:object_ items does not return an :class:object_ object + on item access, but instead returns the actual object that + the array item refers to. + +The following data types are :term:flexible. They have no predefined +size: the data they describe can be of different length in different +arrays. (In the character codes # is an integer denoting how many +elements the data type consists of.) + +=================== ============================= ======== +:class:str_ compatible: Python str 'S#' +:class:unicode_ compatible: Python unicode 'U#' +:class:void 'V#' +=================== ============================= ======== + + +.. warning:: + + Numeric Compatibility: If you used old typecode characters in your + Numeric code (which was never recommended), you will need to change + some of them to the new characters. In particular, the needed + changes are c -> S1, b -> B, 1 -> b, s -> h, w -> + H, and u -> I. These changes make the type character + convention more consistent with other Python modules such as the + :mod:struct module. + + +.. note:: XXX: what to put in the type docstrings, and where to put them? + +Attributes +========== + +The array scalar objects have an :obj:array priority +<__array_priority__> of :cdata:NPY_SCALAR_PRIORITY +(-1,000,000.0). They also do not (yet) have a :attr:ctypes <ndarray.ctypes> +attribute. Otherwise, they share the same attributes as arrays: + +.. autosummary:: + :toctree: generated/ + + generic.flags + generic.shape + generic.strides + generic.ndim + generic.data + generic.size + generic.itemsize + generic.base + generic.dtype + generic.real + generic.imag + generic.flat + generic.T + generic.__array_interface__ + generic.__array_struct__ + generic.__array_priority__ + generic.__array_wrap__ + +.. note:: XXX: import the documentation into the docstrings? + +Indexing +======== +.. seealso:: :ref:arrays.indexing, :ref:arrays.dtypes + +Array scalars can be indexed like 0-dimensional arrays: if *x* is an +array scalar, + +- x[()] returns a 0-dimensional :class:ndarray +- x['field-name'] returns the array scalar in the field *field-name*. + (*x* can have fields, for example, when it corresponds to a record data type.) + +Methods +======= + +Array scalars have exactly the same methods as arrays. The default +behavior of these methods is to internally convert the scalar to an +equivalent 0-dimensional array and to call the corresponding array +method. In addition, math operations on array scalars are defined so +that the same hardware flags are set and used to interpret the results +as for :ref:ufunc <ufuncs>, so that the error state used for ufuncs +also carries over to the math on array scalars. + +The exceptions to the above rules are given below: + +.. autosummary:: + :toctree: generated/ + + generic + generic.__array__ + generic.__array_wrap__ + generic.__squeeze__ + generic.byteswap + generic.__reduce__ + generic.__setstate__ + generic.setflags + +.. note:: XXX: import the documentation into the docstrings? + +Defining new types +================== + +There are two ways to effectively define a new array scalar type +(apart from composing record :ref:dtypes <arrays.dtypes> from the built-in +scalar types): One way is to simply subclass the :class:ndarray and +overwrite the methods of interest. This will work to a degree, but +internally certain behaviors are fixed by the data type of the array. +To fully customize the data type of an array you need to define a new +data-type, and register it with NumPy. Such new types can only be +defined in C, using the :ref:Numpy C-API <c-api>. Added: numpy-docs/trunk/source/reference/c-api.array.rst =================================================================== --- numpy-docs/trunk/source/reference/c-api.array.rst 2008-10-26 17:50:36 UTC (rev 5958) +++ numpy-docs/trunk/source/reference/c-api.array.rst 2008-10-26 17:57:55 UTC (rev 5959) @@ -0,0 +1,2635 @@ +Array API +========= + +.. sectionauthor:: Travis E. Oliphant + +| The test of a first-rate intelligence is the ability to hold two +| opposed ideas in the mind at the same time, and still retain the +| ability to function. +| --- *F. Scott Fitzgerald* + +| For a successful technology, reality must take precedence over public +| relations, for Nature cannot be fooled. +| --- *Richard P. Feynman* + +.. index:: + pair: ndarray; C-API + pair: C-API; array + + +Array structure and data access +------------------------------- + +These macros all access the :ctype:PyArrayObject structure members. The input +argument, obj, can be any :ctype:PyObject * that is directly interpretable +as a :ctype:PyArrayObject * (any instance of the :cdata:PyArray_Type and its +sub-types). + +.. cfunction:: void *PyArray_DATA(PyObject *obj) + +.. cfunction:: char *PyArray_BYTES(PyObject *obj) + + These two macros are similar and obtain the pointer to the + data-buffer for the array. The first macro can (and should be) + assigned to a particular pointer where the second is for generic + processing. If you have not guaranteed a contiguous and/or aligned + array then be sure you understand how to access the data in the + array to avoid memory and/or alignment problems. + +.. cfunction:: npy_intp *PyArray_DIMS(PyObject *arr) + +.. cfunction:: npy_intp *PyArray_STRIDES(PyObject* arr) + +.. cfunction:: npy_intp PyArray_DIM(PyObject* arr, int n) + + Return the shape in the *n* :math:^{\textrm{th}} dimension. + +.. cfunction:: npy_intp PyArray_STRIDE(PyObject* arr, int n) + + Return the stride in the *n* :math:^{\textrm{th}} dimension. + +.. cfunction:: PyObject *PyArray_BASE(PyObject* arr) + +.. cfunction:: PyArray_Descr *PyArray_DESCR(PyObject* arr) + +.. cfunction:: int PyArray_FLAGS(PyObject* arr) + +.. cfunction:: int PyArray_ITEMSIZE(PyObject* arr) + + Return the itemsize for the elements of this array. + +.. cfunction:: int PyArray_TYPE(PyObject* arr) + + Return the (builtin) typenumber for the elements of this array. + +.. cfunction:: PyObject *PyArray_GETITEM(PyObject* arr, void* itemptr) + + Get a Python object from the ndarray, *arr*, at the location + pointed to by itemptr. Return NULL on failure. + +.. cfunction:: int PyArray_SETITEM(PyObject* arr, void* itemptr, PyObject* obj) + + Convert obj and place it in the ndarray, *arr*, at the place + pointed to by itemptr. Return -1 if an error occurs or 0 on + success. + +.. cfunction:: npy_intp PyArray_SIZE(PyObject* arr) + + Returns the total size (in number of elements) of the array. + +.. cfunction:: npy_intp PyArray_Size(PyObject* obj) + + Returns 0 if *obj* is not a sub-class of bigndarray. Otherwise, + returns the total number of elements in the array. Safer version + of :cfunc:PyArray_SIZE (*obj*). + +.. cfunction:: npy_intp PyArray_NBYTES(PyObject* arr) + + Returns the total number of bytes consumed by the array. + + +Data access +^^^^^^^^^^^ + +These functions and macros provide easy access to elements of the +ndarray from C. These work for all arrays. You may need to take care +when accessing the data in the array, however, if it is not in machine +byte-order, misaligned, or not writeable. In other words, be sure to +respect the state of the flags unless you know what you are doing, or +have previously guaranteed an array that is writeable, aligned, and in +machine byte-order using :cfunc:PyArray_FromAny. If you wish to handle all +types of arrays, the copyswap function for each type is useful for +handling misbehaved arrays. Some platforms (e.g. Solaris) do not like +misaligned data and will crash if you de-reference a misaligned +pointer. Other platforms (e.g. x86 Linux) will just work more slowly +with misaligned data. + +.. cfunction:: void* PyArray_GetPtr(PyArrayObject* aobj, npy_intp* ind) + + Return a pointer to the data of the ndarray, *aobj*, at the + N-dimensional index given by the c-array, *ind*, (which must be + at least *aobj* ->nd in size). You may want to typecast the + returned pointer to the data type of the ndarray. + +.. cfunction:: void* PyArray_GETPTR1(PyObject* obj, <npy_intp> i) + +.. cfunction:: void* PyArray_GETPTR2(PyObject* obj, <npy_intp> i, <npy_intp> j) + +.. cfunction:: void* PyArray_GETPTR3(PyObject* obj, <npy_intp> i, <npy_intp> j, <npy_intp> k) + +.. cfunction:: void* PyArray_GETPTR4(PyObject* obj, <npy_intp> i, <npy_intp> j, <npy_intp> k, <npy_intp> l) + + Quick, inline access to the element at the given coordinates in + the ndarray, *obj*, which must have respectively 1, 2, 3, or 4 + dimensions (this is not checked). The corresponding *i*, *j*, + *k*, and *l* coordinates can be any integer but will be + interpreted as npy_intp. You may want to typecast the + returned pointer to the data type of the ndarray. + + +Creating arrays +--------------- + + +From scratch +^^^^^^^^^^^^ + +.. cfunction:: PyObject* PyArray_NewFromDescr(PyTypeObject* subtype, PyArray_Descr* descr, int nd, npy_intp* dims, npy_intp* strides, void* data, int flags, PyObject* obj) + + This is the main array creation function. Most new arrays are + created with this flexible function. The returned object is an + object of Python-type *subtype*, which must be a subtype of + :cdata:PyArray_Type. The array has *nd* dimensions, described by + *dims*. The data-type descriptor of the new array is *descr*. If + *subtype* is not :cdata:&PyArray_Type (*e.g.* a Python subclass of + the ndarray), then *obj* is the object to pass to the + :obj:__array_finalize__ method of the subclass. If *data* is + NULL, then new memory will be allocated and *flags* can be + non-zero to indicate a Fortran-style contiguous array. If *data* + is not NULL, then it is assumed to point to the memory to be + used for the array and the *flags* argument is used as the new + flags for the array (except the state of :cdata:NPY_OWNDATA and + :cdata:UPDATEIFCOPY flags of the new array will be reset). In + addition, if *data* is non-NULL, then *strides* can also be + provided. If *strides* is NULL, then the array strides are + computed as C-style contiguous (default) or Fortran-style + contiguous (*flags* is nonzero for *data* = NULL or *flags* & + :cdata:NPY_F_CONTIGUOUS is nonzero non-NULL *data*). Any provided + *dims* and *strides* are copied into newly allocated dimension and + strides arrays for the new array object. + +.. cfunction:: PyObject* PyArray_New(PyTypeObject* subtype, int nd, npy_intp* dims, int type_num, npy_intp* strides, void* data, int itemsize, int flags, PyObject* obj) + + This is similar to :cfunc:PyArray_DescrNew (...) except you + specify the data-type descriptor with *type_num* and *itemsize*, + where *type_num* corresponds to a builtin (or user-defined) + type. If the type always has the same number of bytes, then + itemsize is ignored. Otherwise, itemsize specifies the particular + size of this array. + + + +.. warning:: + + If data is passed to :cfunc:PyArray_NewFromDescr or :cfunc:PyArray_New, + this memory must not be deallocated until the new array is + deleted. If this data came from another Python object, this can + be accomplished using :cfunc:Py_INCREF on that object and setting the + base member of the new array to point to that object. If strides + are passed in they must be consistent with the dimensions, the + itemsize, and the data of the array. + +.. cfunction:: PyObject* PyArray_SimpleNew(int nd, npy_intp* dims, int typenum) + + Create a new unitialized array of type, *typenum*, whose size in + each of *nd* dimensions is given by the integer array, *dims*. + This function cannot be used to create a flexible-type array (no + itemsize given). + +.. cfunction:: PyObject* PyArray_SimpleNewFromData(int nd, npy_intp* dims, int typenum, void* data) + + Create an array wrapper around *data* pointed to by the given + pointer. The array flags will have a default that the data area is + well-behaved and C-style contiguous. The shape of the array is + given by the *dims* c-array of length *nd*. The data-type of the + array is indicated by *typenum*. + +.. cfunction:: PyObject* PyArray_SimpleNewFromDescr(int nd, npy_intp* dims, PyArray_Descr* descr) + + Create a new array with the provided data-type descriptor, *descr* + , of the shape deteremined by *nd* and *dims*. + +.. cfunction:: PyArray_FILLWBYTE(PyObject* obj, int val) + + Fill the array pointed to by *obj* ---which must be a (subclass + of) bigndarray---with the contents of *val* (evaluated as a byte). + +.. cfunction:: PyObject* PyArray_Zeros(int nd, npy_intp* dims, PyArray_Descr* dtype, int fortran) + + Construct a new *nd* -dimensional array with shape given by *dims* + and data type given by *dtype*. If *fortran* is non-zero, then a + Fortran-order array is created, otherwise a C-order array is + created. Fill the memory with zeros (or the 0 object if *dtype* + corresponds to :ctype:PyArray_OBJECT ). + +.. cfunction:: PyObject* PyArray_ZEROS(int nd, npy_intp* dims, int type_num, int fortran) + + Macro form of :cfunc:PyArray_Zeros which takes a type-number instead + of a data-type object. + +.. cfunction:: PyObject* PyArray_Empty(int nd, npy_intp* dims, PyArray_Descr* dtype, int fortran) + + Construct a new *nd* -dimensional array with shape given by *dims* + and data type given by *dtype*. If *fortran* is non-zero, then a + Fortran-order array is created, otherwise a C-order array is + created. The array is uninitialized unless the data type + corresponds to :ctype:PyArray_OBJECT in which case the array is + filled with :cdata:Py_None. + +.. cfunction:: PyObject* PyArray_EMPTY(int nd, npy_intp* dims, int typenum, int fortran) + + Macro form of :cfunc:PyArray_Empty which takes a type-number, + *typenum*, instead of a data-type object. + +.. cfunction:: PyObject* PyArray_Arange(double start, double stop, double step, int typenum) + + Construct a new 1-dimensional array of data-type, *typenum*, that + ranges from *start* to *stop* (exclusive) in increments of *step* + . Equivalent to **arange** (*start*, *stop*, *step*, dtype). + +.. cfunction:: PyObject* PyArray_ArangeObj(PyObject* start, PyObject* stop, PyObject* step, PyArray_Descr* descr) + + Construct a new 1-dimensional array of data-type determined by + descr, that ranges from start to stop (exclusive) in + increments of step. Equivalent to arange( start, + stop, step, typenum ). + + +From other objects +^^^^^^^^^^^^^^^^^^ + +.. cfunction:: PyObject* PyArray_FromAny(PyObject* op, PyArray_Descr* dtype, int min_depth, int max_depth, int requirements, PyObject* context) + + This is the main function used to obtain an array from any nested + sequence, or object that exposes the array interface, op. The + parameters allow specification of the required *type*, the + minimum (*min_depth*) and maximum (*max_depth*) number of + dimensions acceptable, and other *requirements* for the array. The + *dtype* argument needs to be a :ctype:PyArray_Descr structure + indicating the desired data-type (including required + byteorder). The *dtype* argument may be NULL, indicating that any + data-type (and byteorder) is acceptable. If you want to use + NULL for the *dtype* and ensure the array is notswapped then + use :cfunc:PyArray_CheckFromAny. A value of 0 for either of the + depth parameters causes the parameter to be ignored. Any of the + following array flags can be added (*e.g.* using \|) to get the + *requirements* argument. If your code can handle general (*e.g.* + strided, byte-swapped, or unaligned arrays) then *requirements* + may be 0. Also, if *op* is not already an array (or does not + expose the array interface), then a new array will be created (and + filled from *op* using the sequence protocol). The new array will + have :cdata:NPY_DEFAULT as its flags member. The *context* argument + is passed to the :obj:__array__ method of *op* and is only used if + the array is constructed that way. + + .. cvar:: NPY_C_CONTIGUOUS + + Make sure the returned array is C-style contiguous + + .. cvar:: NPY_F_CONTIGUOUS + + Make sure the returned array is Fortran-style contiguous. + + .. cvar:: NPY_ALIGNED + + Make sure the returned array is aligned on proper boundaries for its + data type. An aligned array has the data pointer and every strides + factor as a multiple of the alignment factor for the data-type- + descriptor. + + .. cvar:: NPY_WRITEABLE + + Make sure the returned array can be written to. + + .. cvar:: NPY_ENSURECOPY + + Make sure a copy is made of *op*. If this flag is not + present, data is not copied if it can be avoided. + + .. cvar:: NPY_ENSUREARRAY + + Make sure the result is a base-class ndarray or bigndarray. By + default, if *op* is an instance of a subclass of the + bigndarray, an instance of that same subclass is returned. If + this flag is set, an ndarray object will be returned instead. + + .. cvar:: NPY_FORCECAST + + Force a cast to the output type even if it cannot be done + safely. Without this flag, a data cast will occur only if it + can be done safely, otherwise an error is reaised. + + .. cvar:: NPY_UPDATEIFCOPY + + If *op* is already an array, but does not satisfy the + requirements, then a copy is made (which will satisfy the + requirements). If this flag is present and a copy (of an + object that is already an array) must be made, then the + corresponding :cdata:NPY_UPDATEIFCOPY flag is set in the returned + copy and *op* is made to be read-only. When the returned copy + is deleted (presumably after your calculations are complete), + its contents will be copied back into *op* and the *op* array + will be made writeable again. If *op* is not writeable to + begin with, then an error is raised. If *op* is not already an + array, then this flag has no effect. + + .. cvar:: NPY_BEHAVED + + :cdata:NPY_ALIGNED \| :cdata:NPY_WRITEABLE + + .. cvar:: NPY_CARRAY + + :cdata:NPY_C_CONTIGUOUS \| :cdata:NPY_BEHAVED + + .. cvar:: NPY_CARRAY_RO + + :cdata:NPY_C_CONTIGUOUS \| :cdata:NPY_ALIGNED + + .. cvar:: NPY_FARRAY + + :cdata:NPY_F_CONTIGUOUS \| :cdata:NPY_BEHAVED + + .. cvar:: NPY_FARRAY_RO + + :cdata:NPY_F_CONTIGUOUS \| :cdata:NPY_ALIGNED + + .. cvar:: NPY_DEFAULT + + :cdata:NPY_CARRAY + + .. cvar:: NPY_IN_ARRAY + + :cdata:NPY_CONTIGUOUS \| :cdata:NPY_ALIGNED + + .. cvar:: NPY_IN_FARRAY + + :cdata:NPY_F_CONTIGUOUS \| :cdata:NPY_ALIGNED + + .. cvar:: NPY_INOUT_ARRAY + + :cdata:NPY_C_CONTIGUOUS \| :cdata:NPY_WRITEABLE \| + :cdata:NPY_ALIGNED + + .. cvar:: NPY_INOUT_FARRAY + + :cdata:NPY_F_CONTIGUOUS \| :cdata:NPY_WRITEABLE \| + :cdata:NPY_ALIGNED + + .. cvar:: NPY_OUT_ARRAY + + :cdata:NPY_C_CONTIGUOUS \| :cdata:NPY_WRITEABLE \| + :cdata:NPY_ALIGNED \| :cdata:NPY_UPDATEIFCOPY + + .. cvar:: NPY_OUT_FARRAY + + :cdata:NPY_F_CONTIGUOUS \| :cdata:NPY_WRITEABLE \| + :cdata:NPY_ALIGNED \| :cdata:UPDATEIFCOPY + + +.. cfunction:: PyObject* PyArray_CheckFromAny(PyObject* op, PyArray_Descr* dtype, int min_depth, int max_depth, int requirements, PyObject* context) + + Nearly identical to :cfunc:PyArray_FromAny (...) except + *requirements* can contain :cdata:NPY_NOTSWAPPED (over-riding the + specification in *dtype*) and :cdata:NPY_ELEMENTSTRIDES which + indicates that the array should be aligned in the sense that the + strides are multiples of the element size. + +.. cvar:: NPY_NOTSWAPPED + + Make sure the returned array has a data-type descriptor that is in + machine byte-order, over-riding any specification in the *dtype* + argument. Normally, the byte-order requirement is determined by + the *dtype* argument. If this flag is set and the dtype argument + does not indicate a machine byte-order descriptor (or is NULL and + the object is already an array with a data-type descriptor that is + not in machine byte- order), then a new data-type descriptor is + created and used with its byte-order field set to native. + +.. cvar:: NPY_BEHAVED_NS + + :cdata:NPY_ALIGNED \| :cdata:NPY_WRITEABLE \| :cdata:NPY_NOTSWAPPED + +.. cvar:: NPY_ELEMENTSTRIDES + + Make sure the returned array has strides that are multiples of the + element size. + +.. cfunction:: PyObject* PyArray_FromArray(PyArrayObject* op, PyArray_Descr* newtype, int requirements) + + Special case of :cfunc:PyArray_FromAny for when *op* is already an + array but it needs to be of a specific *newtype* (including + byte-order) or has certain *requirements*. + +.. cfunction:: PyObject* PyArray_FromStructInterface(PyObject* op) + + Returns an ndarray object from a Python object that exposes the + :obj:__array_struct__ method and follows the array interface + protocol. If the object does not contain this method then a + borrowed reference to :cdata:Py_NotImplemented is returned. + +.. cfunction:: PyObject* PyArray_FromInterface(PyObject* op) + + Returns an ndarray object from a Python object that exposes the + :obj:__array_shape__ and :obj:__array_typestr__ + methods following + the array interface protocol. If the object does not contain one + of these method then a borrowed reference to :cdata:Py_NotImplemented + is returned. + +.. cfunction:: PyObject* PyArray_FromArrayAttr(PyObject* op, PyArray_Descr* dtype, PyObject* context) + + Return an ndarray object from a Python object that exposes the + :obj:__array__ method. The :obj:__array__ method can take 0, 1, or 2 + arguments ([dtype, context]) where *context* is used to pass + information about where the :obj:__array__ method is being called + from (currently only used in ufuncs). + +.. cfunction:: PyObject* PyArray_ContiguousFromAny(PyObject* op, int typenum, int min_depth, int max_depth) + + This function returns a (C-style) contiguous and behaved function + array from any nested sequence or array interface exporting + object, *op*, of (non-flexible) type given by the enumerated + *typenum*, of minimum depth *min_depth*, and of maximum depth + *max_depth*. Equivalent to a call to :cfunc:PyArray_FromAny with + requirements set to :cdata:NPY_DEFAULT and the type_num member of the + type argument set to *typenum*. + +.. cfunction:: PyObject *PyArray_FromObject(PyObject *op, int typenum, int min_depth, int max_depth) + + Return an aligned and in native-byteorder array from any nested + sequence or array-interface exporting object, op, of a type given by + the enumerated typenum. The minimum number of dimensions the array can + have is given by min_depth while the maximum is max_depth. This is + equivalent to a call to :cfunc:PyArray_FromAny with requirements set to + BEHAVED. + +.. cfunction:: PyObject* PyArray_EnsureArray(PyObject* op) + + This function **steals a reference** to op and makes sure that + op is a base-class ndarray. It special cases array scalars, + but otherwise calls :cfunc:PyArray_FromAny ( op, NULL, 0, 0, + :cdata:NPY_ENSUREARRAY). + +.. cfunction:: PyObject* PyArray_FromString(char* string, npy_intp slen, PyArray_Descr* dtype, npy_intp num, char* sep) + + Construct a one-dimensional ndarray of a single type from a binary + or (ASCII) text string of length slen. The data-type of + the array to-be-created is given by dtype. If num is -1, then + **copy** the entire string and return an appropriately sized + array, otherwise, num is the number of items to **copy** from + the string. If sep is NULL (or ""), then interpret the string + as bytes of binary data, otherwise convert the sub-strings + separated by sep to items of data-type dtype. Some + data-types may not be readable in text mode and an error will be + raised if that occurs. All errors return NULL. + +.. cfunction:: PyObject* PyArray_FromFile(FILE* fp, PyArray_Descr* dtype, npy_intp num, char* sep) + + Construct a one-dimensional ndarray of a single type from a binary + or text file. The open file pointer is fp, the data-type of + the array to be created is given by dtype. This must match + the data in the file. If num is -1, then read until the end of + the file and return an appropriately sized array, otherwise, + num is the number of items to read. If sep is NULL (or + ""), then read from the file in binary mode, otherwise read from + the file in text mode with sep providing the item + separator. Some array types cannot be read in text mode in which + case an error is raised. + +.. cfunction:: PyObject* PyArray_FromBuffer(PyObject* buf, PyArray_Descr* dtype, npy_intp count, npy_intp offset) + + Construct a one-dimensional ndarray of a single type from an + object, buf, that exports the (single-segment) buffer protocol + (or has an attribute __buffer\__ that returns an object that + exports the buffer protocol). A writeable buffer will be tried + first followed by a read- only buffer. The :cdata:NPY_WRITEABLE + flag of the returned array will reflect which one was + successful. The data is assumed to start at offset bytes from + the start of the memory location for the object. The type of the + data in the buffer will be interpreted depending on the data- type + descriptor, dtype. If count is negative then it will be + determined from the size of the buffer and the requested itemsize, + otherwise, count represents how many elements should be + converted from the buffer. + +.. cfunction:: int PyArray_CopyInto(PyArrayObject* dest, PyArrayObject* src) + + Copy from the source array, src, into the destination array, + dest, performing a data-type conversion if necessary. If an + error occurs return -1 (otherwise 0). The shape of src must be + broadcastable to the shape of dest. The data areas of dest + and src must not overlap. + +.. cfunction:: int PyArray_MoveInto(PyArrayObject* dest, PyArrayObject* src) + + Move data from the source array, src, into the destination + array, dest, performing a data-type conversion if + necessary. If an error occurs return -1 (otherwise 0). The shape + of src must be broadcastable to the shape of dest. The + data areas of dest and src may overlap. + +.. cfunction:: PyArrayObject* PyArray_GETCONTIGUOUS(PyObject* op) + + If op is already (C-style) contiguous and well-behaved then + just return a reference, otherwise return a (contiguous and + well-behaved) copy of the array. The parameter op must be a + (sub-class of an) ndarray and no checking for that is done. + +.. cfunction:: PyObject* PyArray_FROM_O(PyObject* obj) + + Convert obj to an ndarray. The argument can be any nested + sequence or object that exports the array interface. This is a + macro form of :cfunc:PyArray_FromAny using NULL, 0, 0, 0 for the + other arguments. Your code must be able to handle any data-type + descriptor and any combination of data-flags to use this macro. + +.. cfunction:: PyObject* PyArray_FROM_OF(PyObject* obj, int requirements) + + Similar to :cfunc:PyArray_FROM_O except it can take an argument + of *requirements* indicating properties the resulting array must + have. Available requirements that can be enforced are + :cdata:NPY_CONTIGUOUS, :cdata:NPY_F_CONTIGUOUS, + :cdata:NPY_ALIGNED, :cdata:NPY_WRITEABLE, + :cdata:NPY_NOTSWAPPED, :cdata:NPY_ENSURECOPY, + :cdata:NPY_UPDATEIFCOPY, :cdata:NPY_FORCECAST, and + :cdata:NPY_ENSUREARRAY. Standard combinations of flags can also + be used: + +.. cfunction:: PyObject* PyArray_FROM_OT(PyObject* obj, int typenum) + + Similar to :cfunc:PyArray_FROM_O except it can take an argument of + *typenum* specifying the type-number the returned array. + +.. cfunction:: PyObject* PyArray_FROM_OTF(PyObject* obj, int typenum, int requirements) + + Combination of :cfunc:PyArray_FROM_OF and :cfunc:PyArray_FROM_OT + allowing both a *typenum* and a *flags* argument to be provided.. + +.. cfunction:: PyObject* PyArray_FROMANY(PyObject* obj, int typenum, int min, int max, int requirements) + + Similar to :cfunc:PyArray_FromAny except the data-type is + specified using a typenumber. :cfunc:PyArray_DescrFromType + (*typenum*) is passed directly to :cfunc:PyArray_FromAny. This + macro also adds :cdata:NPY_DEFAULT to requirements if + :cdata:NPY_ENSURECOPY is passed in as requirements. + +.. cfunction:: PyObject *PyArray_CheckAxis(PyObject* obj, int* axis, int requirements) + + Encapsulate the functionality of functions and methods that take + the axis= keyword and work properly with None as the axis + argument. The input array is obj, while *axis is a + converted integer (so that >=MAXDIMS is the None value), and + requirements gives the needed properties of obj. The + output is a converted version of the input so that requirements + are met and if needed a flattening has occurred. On output + negative values of *axis are converted and the new value is + checked to ensure consistency with the shape of obj. + + +Dealing with types +------------------ + + +General check of Python Type +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. cfunction:: PyArray_Check(op) + + Evaluates true if *op* is a Python object whose type is a sub-type + of :cdata:PyArray_Type. + +.. cfunction:: PyArray_CheckExact(op) + + Evaluates true if *op* is a Python object with type + :cdata:PyArray_Type. + +.. cfunction:: PyArray_HasArrayInterface(op, out) + + If op implements any part of the array interface, then out + will contain a new reference to the newly created ndarray using + the interface or out will contain NULL if an error during + conversion occurs. Otherwise, out will contain a borrowed + reference to :cdata:Py_NotImplemented and no error condition is set. + +.. cfunction:: PyArray_HasArrayInterfaceType(op, type, context, out) + + If op implements any part of the array interface, then out + will contain a new reference to the newly created ndarray using + the interface or out will contain NULL if an error during + conversion occurs. Otherwise, out will contain a borrowed + reference to Py_NotImplemented and no error condition is set. + This version allows setting of the type and context in the part of + the array interface that looks for the :obj:__array__ attribute. + +.. cfunction:: PyArray_IsZeroDim(op) + + Evaluates true if *op* is an instance of (a subclass of) + :cdata:PyArray_Type and has 0 dimensions. + +.. cfunction:: PyArray_IsScalar(op, cls) + + Evaluates true if *op* is an instance of :cdata:Py{cls}ArrType_Type. + +.. cfunction:: PyArray_CheckScalar(op) + + Evaluates true if *op* is either an array scalar (an instance of a + sub-type of :cdata:PyGenericArr_Type ), or an instance of (a + sub-class of) :cdata:PyArray_Type whose dimensionality is 0. + +.. cfunction:: PyArray_IsPythonScalar(op) + + Evaluates true if *op* is a builtin Python "scalar" object (int, + float, complex, str, unicode, long, bool). + +.. cfunction:: PyArray_IsAnyScalar(op) + + Evaluates true if *op* is either a Python scalar or an array + scalar (an instance of a sub- type of :cdata:PyGenericArr_Type ). + + +Data-type checking +^^^^^^^^^^^^^^^^^^ + +For the typenum macros, the argument is an integer representing an +enumerated array data type. For the array type checking macros the +argument must be a :ctype:PyObject * that can be directly interpreted as a +:ctype:PyArrayObject *. + +.. cfunction:: PyTypeNum_ISUNSIGNED(num) + +.. cfunction:: PyDataType_ISUNSIGNED(descr) + +.. cfunction:: PyArray_ISUNSIGNED(obj) + + Type represents an unsigned integer. + +.. cfunction:: PyTypeNum_ISSIGNED(num) + +.. cfunction:: PyDataType_ISSIGNED(descr) + +.. cfunction:: PyArray_ISSIGNED(obj) + + Type represents a signed integer. + +.. cfunction:: PyTypeNum_ISINTEGER(num) + +.. cfunction:: PyDataType_ISINTEGER(descr) + +.. cfunction:: PyArray_ISINTEGER(obj) + + Type represents any integer. + +.. cfunction:: PyTypeNum_ISFLOAT(num) + +.. cfunction:: PyDataType_ISFLOAT(descr) + +.. cfunction:: PyArray_ISFLOAT(obj) + + Type represents any floating point number. + +.. cfunction:: PyTypeNum_ISCOMPLEX(num) + +.. cfunction:: PyDataType_ISCOMPLEX(descr) + +.. cfunction:: PyArray_ISCOMPLEX(obj) + + Type represents any complex floating point number. + +.. cfunction:: PyTypeNum_ISNUMBER(num) + +.. cfunction:: PyDataType_ISNUMBER(descr) + +.. cfunction:: PyArray_ISNUMBER(obj) + + Type represents any integer, floating point, or complex floating point + number. + +.. cfunction:: PyTypeNum_ISSTRING(num) + +.. cfunction:: PyDataType_ISSTRING(descr) + +.. cfunction:: PyArray_ISSTRING(obj) + + Type represents a string data type. + +.. cfunction:: PyTypeNum_ISPYTHON(num) + +.. cfunction:: PyDataType_ISPYTHON(descr) + +.. cfunction:: PyArray_ISPYTHON(obj) + + Type represents an enumerated type corresponding to one of the + standard Python scalar (bool, int, float, or complex). + +.. cfunction:: PyTypeNum_ISFLEXIBLE(num) + +.. cfunction:: PyDataType_ISFLEXIBLE(descr) + +.. cfunction:: PyArray_ISFLEXIBLE(obj) + + Type represents one of the flexible array types ( :cdata:NPY_STRING, + :cdata:NPY_UNICODE, or :cdata:NPY_VOID ). + +.. cfunction:: PyTypeNum_ISUSERDEF(num) + +.. cfunction:: PyDataType_ISUSERDEF(descr) + +.. cfunction:: PyArray_ISUSERDEF(obj) + + Type represents a user-defined type. + +.. cfunction:: PyTypeNum_ISEXTENDED(num) + +.. cfunction:: PyDataType_ISEXTENDED(descr) + +.. cfunction:: PyArray_ISEXTENDED(obj) + + Type is either flexible or user-defined. + +.. cfunction:: PyTypeNum_ISOBJECT(num) + +.. cfunction:: PyDataType_ISOBJECT(descr) + +.. cfunction:: PyArray_ISOBJECT(obj) + + Type represents object data type. + +.. cfunction:: PyTypeNum_ISBOOL(num) + +.. cfunction:: PyDataType_ISBOOL(descr) + +.. cfunction:: PyArray_ISBOOL(obj) + + Type represents Boolean data type. + +.. cfunction:: PyDataType_HASFIELDS(descr) + +.. cfunction:: PyArray_HASFIELDS(obj) + + Type has fields associated with it. + +.. cfunction:: PyArray_ISNOTSWAPPED(m) + + Evaluates true if the data area of the ndarray *m* is in machine + byte-order according to the array's data-type descriptor. + +.. cfunction:: PyArray_ISBYTESWAPPED(m) + + Evaluates true if the data area of the ndarray *m* is **not** in + machine byte-order according to the array's data-type descriptor. + +.. cfunction:: Bool PyArray_EquivTypes(PyArray_Descr* type1, PyArray_Descr* type2) + + Return :cdata:NPY_TRUE if *type1* and *type2* actually represent + equivalent types for this platform (the fortran member of each + type is ignored). For example, on 32-bit platforms, + :cdata:NPY_LONG and :cdata:NPY_INT are equivalent. Otherwise + return :cdata:NPY_FALSE. + +.. cfunction:: Bool PyArray_EquivArrTypes(PyArrayObject* a1, PyArrayObject * a2) + + Return :cdata:NPY_TRUE if *a1* and *a2* are arrays with equivalent + types for this platform. + +.. cfunction:: Bool PyArray_EquivTypenums(int typenum1, int typenum2) + + Special case of :cfunc:PyArray_EquivTypes (...) that does not accept + flexible data types but may be easier to call. + +.. cfunction:: int PyArray_EquivByteorders({byteorder} b1, {byteorder} b2) + + True if byteorder characters ( :cdata:NPY_LITTLE, + :cdata:NPY_BIG, :cdata:NPY_NATIVE, :cdata:NPY_IGNORE ) are + either equal or equivalent as to their specification of a native + byte order. Thus, on a little-endian machine :cdata:NPY_LITTLE + and :cdata:NPY_NATIVE are equivalent where they are not + equivalent on a big-endian machine. + + +Converting data types +^^^^^^^^^^^^^^^^^^^^^ + +.. cfunction:: PyObject* PyArray_Cast(PyArrayObject* arr, int typenum) + + Mainly for backwards compatibility to the Numeric C-API and for + simple casts to non-flexible types. Return a new array object with + the elements of *arr* cast to the data-type *typenum* which must + be one of the enumerated types and not a flexible type. + +.. cfunction:: PyObject* PyArray_CastToType(PyArrayObject* arr, PyArray_Descr* type, int fortran) + + Return a new array of the *type* specified, casting the elements + of *arr* as appropriate. The fortran argument specifies the + ordering of the output array. + +.. cfunction:: int PyArray_CastTo(PyArrayObject* out, PyArrayObject* in) + + Cast the elements of the array *in* into the array *out*. The + output array should be writeable, have an integer-multiple of the + number of elements in the input array (more than one copy can be + placed in out), and have a data type that is one of the builtin + types. Returns 0 on success and -1 if an error occurs. + +.. cfunction:: PyArray_VectorUnaryFunc* PyArray_GetCastFunc(PyArray_Descr* from, int totype) + + Return the low-level casting function to cast from the given + descriptor to the builtin type number. If no casting function + exists return NULL and set an error. Using this function + instead of direct access to *from* ->f->cast will allow support of + any user-defined casting functions added to a descriptors casting + dictionary. + +.. cfunction:: int PyArray_CanCastSafely(int fromtype, int totype) + + Returns non-zero if an array of data type *fromtype* can be cast + to an array of data type *totype* without losing information. An + exception is that 64-bit integers are allowed to be cast to 64-bit + floating point values even though this can lose precision on large + integers so as not to proliferate the use of long doubles without + explict requests. Flexible array types are not checked according + to their lengths with this function. + +.. cfunction:: int PyArray_CanCastTo(PyArray_Descr* fromtype, PyArray_Descr* totype) + + Returns non-zero if an array of data type *fromtype* (which can + include flexible types) can be cast safely to an array of data + type *totype* (which can include flexible types). This is + basically a wrapper around :cfunc:PyArray_CanCastSafely with + additional support for size checking if *fromtype* and *totype* + are :cdata:NPY_STRING or :cdata:NPY_UNICODE. + +.. cfunction:: int PyArray_ObjectType(PyObject* op, int mintype) + + This function is useful for determining a common type that two or + more arrays can be converted to. It only works for non-flexible + array types as no itemsize information is passed. The *mintype* + argument represents the minimum type acceptable, and *op* + represents the object that will be converted to an array. The + return value is the enumerated typenumber that represents the + data-type that *op* should have. + +.. cfunction:: void PyArray_ArrayType(PyObject* op, PyArray_Descr* mintype, PyArray_Descr* outtype) + + This function works similarly to :cfunc:PyArray_ObjectType (...) + except it handles flexible arrays. The *mintype* argument can have + an itemsize member and the *outtype* argument will have an + itemsize member at least as big but perhaps bigger depending on + the object *op*. + +.. cfunction:: PyArrayObject** PyArray_ConvertToCommonType(PyObject* op, int* n) + + Convert a sequence of Python objects contained in *op* to an array + of ndarrays each having the same data type. The type is selected + based on the typenumber (larger type number is chosen over a + smaller one) ignoring objects that are only scalars. The length of + the sequence is returned in *n*, and an *n* -length array of + :ctype:PyArrayObject pointers is the return value (or NULL if an + error occurs). The returned array must be freed by the caller of + this routine (using :cfunc:PyDataMem_FREE ) and all the array objects + in it DECREF 'd or a memory-leak will occur. The example + template-code below shows a typically usage: + + .. code-block:: c + + mps = PyArray_ConvertToCommonType(obj, &n); + if (mps==NULL) return NULL; + {code} + <before return> + for (i=0; i<n; i++) Py_DECREF(mps[i]); + PyDataMem_FREE(mps); + {return} + +.. cfunction:: char* PyArray_Zero(PyArrayObject* arr) + + A pointer to newly created memory of size *arr* ->itemsize that + holds the representation of 0 for that type. The returned pointer, + *ret*, **must be freed** using :cfunc:PyDataMem_FREE (ret) when it is + not needed anymore. + +.. cfunction:: char* PyArray_One(PyArrayObject* arr) + + A pointer to newly created memory of size *arr* ->itemsize that + holds the representation of 1 for that type. The returned pointer, + *ret*, **must be freed** using :cfunc:PyDataMem_FREE (ret) when it + is not needed anymore. + +.. cfunction:: int PyArray_ValidType(int typenum) + + Returns :cdata:NPY_TRUE if *typenum* represents a valid type-number + (builtin or user-defined or character code). Otherwise, this + function returns :cdata:NPY_FALSE. + + +New data types +^^^^^^^^^^^^^^ + +.. cfunction:: void PyArray_InitArrFuncs(PyArray_ArrFuncs* f) + + Initialize all function pointers and members to NULL. + +.. cfunction:: int PyArray_RegisterDataType(PyArray_Descr* dtype) + + Register a data-type as a new user-defined data type for + arrays. The type must have most of its entries filled in. This is + not always checked and errors can produce segfaults. In + particular, the typeobj member of the dtype structure must be + filled with a Python type that has a fixed-size element-size that + corresponds to the elsize member of *dtype*. Also the f + member must have the required functions: nonzero, copyswap, + copyswapn, getitem, setitem, and cast (some of the cast functions + may be NULL if no support is desired). To avoid confusion, you + should choose a unique character typecode but this is not enforced + and not relied on internally. + + A user-defined type number is returned that uniquely identifies + the type. A pointer to the new structure can then be obtained from + :cfunc:PyArray_DescrFromType using the returned type number. A -1 is + returned if an error occurs. If this *dtype* has already been + registered (checked only by the address of the pointer), then + return the previously-assigned type-number. + +.. cfunction:: int PyArray_RegisterCastFunc(PyArray_Descr* descr, int totype, PyArray_VectorUnaryFunc* castfunc) + + Register a low-level casting function, *castfunc*, to convert + from the data-type, *descr*, to the given data-type number, + *totype*. Any old casting function is over-written. A 0 is + returned on success or a -1 on failure. + +.. cfunction:: int PyArray_RegisterCanCast(PyArray_Descr* descr, int totype, PyArray_SCALARKIND scalar) + + Register the data-type number, *totype*, as castable from + data-type object, *descr*, of the given *scalar* kind. Use + *scalar* = :cdata:NPY_NOSCALAR to register that an array of data-type + *descr* can be cast safely to a data-type whose type_number is + *totype*. + + +Special functions for PyArray_OBJECT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. cfunction:: int PyArray_INCREF(PyArrayObject* op) + + Used for an array, *op*, that contains any Python objects. It + increments the reference count of every object in the array + according to the data-type of *op*. A -1 is returned if an error + occurs, otherwise 0 is returned. + +.. cfunction:: void PyArray_Item_INCREF(char* ptr, PyArray_Descr* dtype) + + A function to INCREF all the objects at the location *ptr* + according to the data-type *dtype*. If *ptr* is the start of a + record with an object at any offset, then this will (recursively) + increment the reference count of all object-like items in the + record. + +.. cfunction:: int PyArray_XDECREF(PyArrayObject* op) + + Used for an array, *op*, that contains any Python objects. It + decrements the reference count of every object in the array + according to the data-type of *op*. Normal return value is 0. A + -1 is returned if an error occurs. + +.. cfunction:: void PyArray_Item_XDECREF(char* ptr, PyArray_Descr* dtype) + + A function to XDECREF all the object-like items at the loacation + *ptr* as recorded in the data-type, *dtype*. This works + recursively so that if dtype itself has fields with data-types + that contain object-like items, all the object-like fields will be + XDECREF 'd. + +.. cfunction:: void PyArray_FillObjectArray(PyArrayObject* arr, PyObject* obj) + + Fill a newly created array with a single value obj at all + locations in the structure with object data-types. No checking is + performed but *arr* must be of data-type :ctype:PyArray_OBJECT and be + single-segment and uninitialized (no previous objects in + position). Use :cfunc:PyArray_DECREF (*arr*) if you need to + decrement all the items in the object array prior to calling this + function. + + +Array flags +----------- + + +Basic Array Flags +^^^^^^^^^^^^^^^^^ + +An ndarray can have a data segment that is not a simple contiguous +chunk of well-behaved memory you can manipulate. It may not be aligned +with word boundaries (very important on some platforms). It might have +its data in a different byte-order than the machine recognizes. It +might not be writeable. It might be in Fortan-contiguous order. The +array flags are used to indicate what can be said about data +associated with an array. + +.. cvar:: NPY_C_CONTIGUOUS + + The data area is in C-style contiguous order (last index varies the + fastest). + +.. cvar:: NPY_F_CONTIGUOUS + + The data area is in Fortran-style contiguous order (first index varies + the fastest). + +.. cvar:: NPY_OWNDATA + + The data area is owned by this array. + +.. cvar:: NPY_ALIGNED + + The data area is aligned appropriately (for all strides). + +.. cvar:: NPY_WRITEABLE + + The data area can be written to. + + Notice that the above 3 flags are are defined so that a new, well- + behaved array has these flags defined as true. + +.. cvar:: NPY_UPDATEIFCOPY + + The data area represents a (well-behaved) copy whose information + should be transferred back to the original when this array is deleted. + + +Combinations of array flags +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. cvar:: NPY_BEHAVED + + :cdata:NPY_ALIGNED \| :cdata:NPY_WRITEABLE + +.. cvar:: NPY_CARRAY + + :cdata:NPY_C_CONTIGUOUS \| :cdata:NPY_BEHAVED + +.. cvar:: NPY_CARRAY_RO + + :cdata:NPY_C_CONTIGUOUS \| :cdata:NPY_ALIGNED + +.. cvar:: NPY_FARRAY + + :cdata:NPY_F_CONTIGUOUS \| :cdata:NPY_BEHAVED + +.. cvar:: NPY_FARRAY_RO + + :cdata:NPY_F_CONTIGUOUS \| :cdata:NPY_ALIGNED + +.. cvar:: NPY_DEFAULT + + :cdata:NPY_CARRAY + +.. cvar:: NPY_UPDATE_ALL + + :cdata:NPY_C_CONTIGUOUS \| :cdata:NPY_F_CONTIGUOUS \| :cdata:NPY_ALIGNED + + +Flag-like constants +^^^^^^^^^^^^^^^^^^^ + +These constants are used in :cfunc:PyArray_FromAny (and its macro forms) to +specify desired properties of the new array. + +.. cvar:: NPY_FORCECAST + + Cast to the desired type, even if it can't be done without losing + information. + +.. cvar:: NPY_ENSURECOPY + + Make sure the resulting array is a copy of the original. + +.. cvar:: NPY_ENSUREARRAY + + Make sure the resulting object is an actual ndarray (or bigndarray), + and not a sub-class. + +.. cvar:: NPY_NOTSWAPPED + + Only used in :cfunc:PyArray_CheckFromAny to over-ride the byteorder + of the data-type object passed in. + +.. cvar:: NPY_BEHAVED_NS + + :cdata:NPY_ALIGNED \| :cdata:NPY_WRITEABLE \| :cdata:NPY_NOTSWAPPED + + +Flag checking +^^^^^^^^^^^^^ + +For all of these macros *arr* must be an instance of a (subclass of) +:cdata:PyArray_Type, but no checking is done. + +.. cfunction:: PyArray_CHKFLAGS(arr, flags) + + The first parameter, arr, must be an ndarray or subclass. The + parameter, *flags*, should be an integer consisting of bitwise + combinations of the possible flags an array can have: + :cdata:NPY_C_CONTIGUOUS, :cdata:NPY_F_CONTIGUOUS, + :cdata:NPY_OWNDATA, :cdata:NPY_ALIGNED, + :cdata:NPY_WRITEABLE, :cdata:NPY_UPDATEIFCOPY. + +.. cfunction:: PyArray_ISCONTIGUOUS(arr) + + Evaluates true if *arr* is C-style contiguous. + +.. cfunction:: PyArray_ISFORTRAN(arr) + + Evaluates true if *arr* is Fortran-style contiguous. + +.. cfunction:: PyArray_ISWRITEABLE(arr) + + Evaluates true if the data area of *arr* can be written to + +.. cfunction:: PyArray_ISALIGNED(arr) + + Evaluates true if the data area of *arr* is properly aligned on + the machine. + +.. cfunction:: PyArray_ISBEHAVED(arr) + + Evalutes true if the data area of *arr* is aligned and writeable + and in machine byte-order according to its descriptor. + +.. cfunction:: PyArray_ISBEHAVED_RO(arr) + + Evaluates true if the data area of *arr* is aligned and in machine + byte-order. + +.. cfunction:: PyArray_ISCARRAY(arr) + + Evaluates true if the data area of *arr* is C-style contiguous, + and :cfunc:PyArray_ISBEHAVED (*arr*) is true. + +.. cfunction:: PyArray_ISFARRAY(arr) + + Evaluates true if the data area of *arr* is Fortran-style + contiguous and :cfunc:PyArray_ISBEHAVED (*arr*) is true. + +.. cfunction:: PyArray_ISCARRAY_RO(arr) + + Evaluates true if the data area of *arr* is C-style contiguous, + aligned, and in machine byte-order. + +.. cfunction:: PyArray_ISFARRAY_RO(arr) + + Evaluates true if the data area of *arr* is Fortran-style + contiguous, aligned, and in machine byte-order **.** + +.. cfunction:: PyArray_ISONESEGMENT(arr) + + Evaluates true if the data area of *arr* consists of a single + (C-style or Fortran-style) contiguous segment. + +.. cfunction:: void PyArray_UpdateFlags(PyArrayObject* arr, int flagmask) + + The :cdata:NPY_C_CONTIGUOUS, :cdata:NPY_ALIGNED, and + :cdata:NPY_F_CONTIGUOUS array flags can be "calculated" from the + array object itself. This routine updates one or more of these + flags of *arr* as specified in *flagmask* by performing the + required calculation. + + +.. warning:: + + It is important to keep the flags updated (using + :cfunc:PyArray_UpdateFlags can help) whenever a manipulation with an + array is performed that might cause them to change. Later + calculations in NumPy that rely on the state of these flags do not + repeat the calculation to update them. + + +Array method alternative API +---------------------------- + + +Conversion +^^^^^^^^^^ + +.. cfunction:: PyObject* PyArray_GetField(PyArrayObject* self, PyArray_Descr* dtype, int offset) + + Equivalent to :meth:ndarray.getfield (*self*, *dtype*, *offset*). Return + a new array of the given *dtype* using the data in the current + array at a specified *offset* in bytes. The *offset* plus the + itemsize of the new array type must be less than *self* + ->descr->elsize or an error is raised. The same shape and strides + as the original array are used. Therefore, this function has the + effect of returning a field from a record array. But, it can also + be used to select specific bytes or groups of bytes from any array + type. + +.. cfunction:: int PyArray_SetField(PyArrayObject* self, PyArray_Descr* dtype, int offset, PyObject* val) + + Equivalent to :meth:ndarray.setfield (*self*, *val*, *dtype*, *offset* + ). Set the field starting at *offset* in bytes and of the given + *dtype* to *val*. The *offset* plus *dtype* ->elsize must be less + than *self* ->descr->elsize or an error is raised. Otherwise, the + *val* argument is converted to an array and copied into the field + pointed to. If necessary, the elements of *val* are repeated to + fill the destination array, But, the number of elements in the + destination must be an integer multiple of the number of elements + in *val*. + +.. cfunction:: PyObject* PyArray_Byteswap(PyArrayObject* self, Bool inplace) + + Equivalent to :meth:ndarray.byteswap (*self*, *inplace*). Return an array + whose data area is byteswapped. If *inplace* is non-zero, then do + the byteswap inplace and return a reference to self. Otherwise, + create a byteswapped copy and leave self unchanged. + +.. cfunction:: PyObject* PyArray_NewCopy(PyArrayObject* old, NPY_ORDER order) + + Equivalent to :meth:ndarray.copy (*self*, *fortran*). Make a copy of the + *old* array. The returned array is always aligned and writeable + with data interpreted the same as the old array. If *order* is + :cdata:NPY_CORDER, then a C-style contiguous array is returned. If + *order* is :cdata:NPY_FORTRANORDER, then a Fortran-style contiguous + array is returned. If *order is* :cdata:NPY_ANYORDER, then the array + returned is Fortran-style contiguous only if the old one is; + otherwise, it is C-style contiguous. + +.. cfunction:: PyObject* PyArray_ToList(PyArrayObject* self) + + Equivalent to :meth:ndarray.tolist (*self*). Return a nested Python list + from *self*. + +.. cfunction:: PyObject* PyArray_ToString(PyArrayObject* self, NPY_ORDER order) + + Equivalent to :meth:ndarray.tostring (*self*, *order*). Return the bytes + of this array in a Python string. + +.. cfunction:: PyObject* PyArray_ToFile(PyArrayObject* self, FILE* fp, char* sep, char* format) + + Write the contents of *self* to the file pointer *fp* in C-style + contiguous fashion. Write the data as binary bytes if *sep* is the + string ""or NULL. Otherwise, write the contents of *self* as + text using the *sep* string as the item separator. Each item will + be printed to the file. If the *format* string is not NULL or + "", then it is a Python print statement format string showing how + the items are to be written. + +.. cfunction:: int PyArray_Dump(PyObject* self, PyObject* file, int protocol) + + Pickle the object in *self* to the given *file* (either a string + or a Python file object). If *file* is a Python string it is + considered to be the name of a file which is then opened in binary + mode. The given *protocol* is used (if *protocol* is negative, or + the highest available is used). This is a simple wrapper around + cPickle.dump(*self*, *file*, *protocol*). + +.. cfunction:: PyObject* PyArray_Dumps(PyObject* self, int protocol) + + Pickle the object in *self* to a Python string and return it. Use + the Pickle *protocol* provided (or the highest available if + *protocol* is negative). + +.. cfunction:: int PyArray_FillWithScalar(PyArrayObject* arr, PyObject* obj) + + Fill the array, *arr*, with the given scalar object, *obj*. The + object is first converted to the data type of *arr*, and then + copied into every location. A -1 is returned if an error occurs, + otherwise 0 is returned. + +.. cfunction:: PyObject* PyArray_View(PyArrayObject* self, PyArray_Descr* dtype) + + Equivalent to :meth:ndarray.view (*self*, *dtype*). Return a new view of + the array *self* as possibly a different data-type, *dtype*. If + *dtype* is NULL, then the returned array will have the same + data type as *self*. The new data-type must be consistent with + the size of *self*. Either the itemsizes must be identical, or + *self* must be single-segment and the total number of bytes must + be the same. In the latter case the dimensions of the returned + array will be altered in the last (or first for Fortran-style + contiguous arrays) dimension. The data area of the returned array + and self is exactly the same. + + +Shape Manipulation +^^^^^^^^^^^^^^^^^^ + +.. cfunction:: PyObject* PyArray_Newshape(PyArrayObject* self, PyArray_Dims* newshape) + + Result will be a new array (pointing to the same memory location + as *self* if possible), but having a shape given by *newshape* + . If the new shape is not compatible with the strides of *self*, + then a copy of the array with the new specified shape will be + returned. + +.. cfunction:: PyObject* PyArray_Reshape(PyArrayObject* self, PyObject* shape) + + Equivalent to :meth:ndarray.reshape (*self*, *shape*) where *shape* is a + sequence. Converts *shape* to a :ctype:PyArray_Dims structure and + calls :cfunc:PyArray_Newshape internally. + +.. cfunction:: PyObject* PyArray_Squeeze(PyArrayObject* self) + + Equivalent to :meth:ndarray.squeeze (*self*). Return a new view of *self* + with all of the dimensions of length 1 removed from the shape. + +.. warning:: + + matrix objects are always 2-dimensional. Therefore, + :cfunc:PyArray_Squeeze has no effect on arrays of matrix sub-class. + +.. cfunction:: PyObject* PyArray_SwapAxes(PyArrayObject* self, int a1, int a2) + + Equivalent to :meth:ndarray.swapaxes (*self*, *a1*, *a2*). The returned + array is a new view of the data in *self* with the given axes, + *a1* and *a2*, swapped. + +.. cfunction:: PyObject* PyArray_Resize(PyArrayObject* self, PyArray_Dims* newshape, int refcheck, NPY_ORDER fortran) + + Equivalent to :meth:ndarray.resize (*self*, *newshape*, refcheck + = *refcheck*, order= fortran ). This function only works on + single-segment arrays. It changes the shape of *self* inplace and + will reallocate the memory for *self* if *newshape* has a + different total number of elements then the old shape. If + reallocation is necessary, then *self* must own its data, have + *self* - >base==NULL, have *self* - >weakrefs==NULL, and + (unless refcheck is 0) not be referenced by any other array. A + reference to the new array is returned. The fortran argument can + be :cdata:NPY_ANYORDER, :cdata:NPY_CORDER, or + :cdata:NPY_FORTRANORDER. This argument is used if the number of + dimension is (or is being resized to be) greater than 2. It + currently has no effect. Eventually it could be used to determine + how the resize operation should view the data when constructing a + differently-dimensioned array. + +.. cfunction:: PyObject* PyArray_Transpose(PyArrayObject* self, PyArray_Dims* permute) + + Equivalent to :meth:ndarray.transpose (*self*, *permute*). Permute the + axes of the ndarray object *self* according to the data structure + *permute* and return the result. If *permute* is NULL, then + the resulting array has its axes reversed. For example if *self* + has shape :math:10\times20\times30, and *permute* .ptr is + (0,2,1) the shape of the result is :math:10\times30\times20. If + *permute* is NULL, the shape of the result is + :math:30\times20\times10. + +.. cfunction:: PyObject* PyArray_Flatten(PyArrayObject* self, NPY_ORDER order) + + Equivalent to :meth:ndarray.flatten (*self*, *order*). Return a 1-d copy + of the array. If *order* is :cdata:NPY_FORTRANORDER the elements are + scanned out in Fortran order (first-dimension varies the + fastest). If *order* is :cdata:NPY_CORDER, the elements of self + are scanned in C-order (last dimension varies the fastest). If + *order* :cdata:NPY_ANYORDER, then the result of + :cfunc:PyArray_ISFORTRAN (*self*) is used to determine which order + to flatten. + +.. cfunction:: PyObject* PyArray_Ravel(PyArrayObject* self, NPY_ORDER order) + + Equivalent to *self*.ravel(*order*). Same basic functionality + as :cfunc:PyArray_Flatten (*self*, *order*) except if *order* is 0 + and *self* is C-style contiguous, the shape is altered but no copy + is performed. + + +Item selection and manipulation +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. cfunction:: PyObject* PyArray_TakeFrom(PyArrayObject* self, PyObject* indices, int axis, PyArrayObject* ret, NPY_CLIPMODE clipmode) + + Equivalent to :meth:ndarray.take (*self*, *indices*, *axis*, *ret*, + *clipmode*) except *axis* =None in Python is obtained by setting + *axis* = :cdata:NPY_MAXDIMS in C. Extract the items from self + indicated by the integer-valued *indices* along the given *axis.* + The clipmode argument can be :cdata:NPY_RAISE, :cdata:NPY_WRAP, or + :cdata:NPY_CLIP to indicate what to do with out-of-bound indices. The + *ret* argument can specify an output array rather than having one + created internally. + +.. cfunction:: PyObject* PyArray_PutTo(PyArrayObject* self, PyObject* values, PyObject* indices, NPY_CLIPMODE clipmode) + + Equivalent to *self*.put(*values*, *indices*, *clipmode* + ). Put *values* into *self* at the corresponding (flattened) + *indices*. If *values* is too small it will be repeated as + necessary. + +.. cfunction:: PyObject* PyArray_PutMask(PyArrayObject* self, PyObject* values, PyObject* mask) + + Place the *values* in *self* wherever corresponding positions + (using a flattened context) in *mask* are true. The *mask* and + *self* arrays must have the same total number of elements. If + *values* is too small, it will be repeated as necessary. + +.. cfunction:: PyObject* PyArray_Repeat(PyArrayObject* self, PyObject* op, int axis) + + Equivalent to :meth:ndarray.repeat (*self*, *op*, *axis*). Copy the + elements of *self*, *op* times along the given *axis*. Either + *op* is a scalar integer or a sequence of length *self* + ->dimensions[ *axis* ] indicating how many times to repeat each + item along the axis. + +.. cfunction:: PyObject* PyArray_Choose(PyArrayObject* self, PyObject* op, PyArrayObject* ret, NPY_CLIPMODE clipmode) + + Equivalent to :meth:ndarray.choose (*self*, *op*, *ret*, *clipmode*). + Create a new array by selecting elements from the sequence of + arrays in *op* based on the integer values in *self*. The arrays + must all be broadcastable to the same shape and the entries in + *self* should be between 0 and len(*op*). The output is placed + in *ret* unless it is NULL in which case a new output is + created. The *clipmode* argument determines behavior for when + entries in *self* are not between 0 and len(*op*). + + .. cvar:: NPY_RAISE + + raise a ValueError; + + .. cvar:: NPY_WRAP + + wrap values < 0 by adding len(*op*) and values >=len(*op*) + by subtracting len(*op*) until they are in range; + + .. cvar:: NPY_CLIP + + all values are clipped to the region [0, len(*op*) ). + + +.. cfunction:: PyObject* PyArray_Sort(PyArrayObject* self, int axis) + + Equivalent to :meth:ndarray.sort (*self*, *axis*). Return an array with + the items of *self* sorted along *axis*. + +.. cfunction:: PyObject* PyArray_ArgSort(PyArrayObject* self, int axis) + + Equivalent to :meth:ndarray.argsort (*self*, *axis*). Return an array of + indices such that selection of these indices along the given + axis would return a sorted version of *self*. If *self* + ->descr is a data-type with fields defined, then + self->descr->names is used to determine the sort order. A + comparison where the first field is equal will use the second + field and so on. To alter the sort order of a record array, create + a new data-type with a different order of names and construct a + view of the array with that new data-type. + +.. cfunction:: PyObject* PyArray_LexSort(PyObject* sort_keys, int axis) + + Given a sequence of arrays (*sort_keys*) of the same shape, + return an array of indices (similar to :cfunc:PyArray_ArgSort (...)) + that would sort the arrays lexicographically. A lexicographic sort + specifies that when two keys are found to be equal, the order is + based on comparison of subsequent keys. A merge sort (which leaves + equal entries unmoved) is required to be defined for the + types. The sort is accomplished by sorting the indices first using + the first *sort_key* and then using the second *sort_key* and so + forth. This is equivalent to the lexsort(*sort_keys*, *axis*) + Python command. Because of the way the merge-sort works, be sure + to understand the order the *sort_keys* must be in (reversed from + the order you would use when comparing two elements). + + If these arrays are all collected in a record array, then + :cfunc:PyArray_Sort (...) can also be used to sort the array + directly. + +.. cfunction:: PyObject* PyArray_SearchSorted(PyArrayObject* self, PyObject* values) + + Equivalent to :meth:ndarray.searchsorted (*self*, *values*). Assuming + *self* is a 1-d array in ascending order representing bin + boundaries then the output is an array the same shape as *values* + of bin numbers, giving the bin into which each item in *values* + would be placed. No checking is done on whether or not self is in + ascending order. + +.. cfunction:: PyObject* PyArray_Diagonal(PyArrayObject* self, int offset, int axis1, int axis2) + + Equivalent to :meth:ndarray.diagonal (*self*, *offset*, *axis1*, *axis2* + ). Return the *offset* diagonals of the 2-d arrays defined by + *axis1* and *axis2*. + +.. cfunction:: PyObject* PyArray_Nonzero(PyArrayObject* self) + + Equivalent to :meth:ndarray.nonzero (*self*). Returns a tuple of index + arrays that select elements of *self* that are nonzero. If (nd= + :cfunc:PyArray_NDIM ( self ))==1, then a single index array is + returned. The index arrays have data type :cdata:NPY_INTP. If a + tuple is returned (nd :math:\neq 1), then its length is nd. + +.. cfunction:: PyObject* PyArray_Compress(PyArrayObject* self, PyObject* condition, int axis, PyArrayObject* out) + + Equivalent to :meth:ndarray.compress (*self*, *condition*, *axis* + ). Return the elements along *axis* corresponding to elements of + *condition* that are true. + + +Calculation +^^^^^^^^^^^ + +.. tip:: + + Pass in :cdata:NPY_MAXDIMS for axis in order to achieve the same + effect that is obtained by passing in *axis* = :const:None in Python + (treating the array as a 1-d array). + +.. cfunction:: PyObject* PyArray_ArgMax(PyArrayObject* self, int axis) + + Equivalent to :meth:ndarray.argmax (*self*, *axis*). Return the index of + the largest element of *self* along *axis*. + +.. cfunction:: PyObject* PyArray_ArgMin(PyArrayObject* self, int axis) + + Equivalent to :meth:ndarray.argmin (*self*, *axis*). Return the index of + the smallest element of *self* along *axis*. + +.. cfunction:: PyObject* PyArray_Max(PyArrayObject* self, int axis, PyArrayObject* out) + + Equivalent to :meth:ndarray.max (*self*, *axis*). Return the largest + element of *self* along the given *axis*. + +.. cfunction:: PyObject* PyArray_Min(PyArrayObject* self, int axis, PyArrayObject* out) + + Equivalent to :meth:ndarray.min (*self*, *axis*). Return the smallest + element of *self* along the given *axis*. + +.. cfunction:: PyObject* PyArray_Ptp(PyArrayObject* self, int axis, PyArrayObject* out) + + Equivalent to :meth:ndarray.ptp (*self*, *axis*). Return the difference + between the largest element of *self* along *axis* and the + smallest element of *self* along *axis*. + + + +.. note:: + + The rtype argument specifies the data-type the reduction should + take place over. This is important if the data-type of the array + is not "large" enough to handle the output. By default, all + integer data-types are made at least as large as :cdata:NPY_LONG + for the "add" and "multiply" ufuncs (which form the basis for + mean, sum, cumsum, prod, and cumprod functions). + +.. cfunction:: PyObject* PyArray_Mean(PyArrayObject* self, int axis, int rtype, PyArrayObject* out) + + Equivalent to :meth:ndarray.mean (*self*, *axis*, *rtype*). Returns the + mean of the elements along the given *axis*, using the enumerated + type *rtype* as the data type to sum in. Default sum behavior is + obtained using :cdata:PyArray_NOTYPE for *rtype*. + +.. cfunction:: PyObject* PyArray_Trace(PyArrayObject* self, int offset, int axis1, int axis2, int rtype, PyArrayObject* out) + + Equivalent to :meth:ndarray.trace (*self*, *offset*, *axis1*, *axis2*, + *rtype*). Return the sum (using *rtype* as the data type of + summation) over the *offset* diagonal elements of the 2-d arrays + defined by *axis1* and *axis2* variables. A positive offset + chooses diagonals above the main diagonal. A negative offset + selects diagonals below the main diagonal. + +.. cfunction:: PyObject* PyArray_Clip(PyArrayObject* self, PyObject* min, PyObject* max) + + Equivalent to :meth:ndarray.clip (*self*, *min*, *max*). Clip an array, + *self*, so that values larger than *max* are fixed to *max* and + values less than *min* are fixed to *min*. + +.. cfunction:: PyObject* PyArray_Conjugate(PyArrayObject* self) + + Equivalent to :meth:ndarray.conjugate (*self*). + Return the complex conjugate of *self*. If *self* is not of + complex data type, then return *self* with an reference. + +.. cfunction:: PyObject* PyArray_Round(PyArrayObject* self, int decimals, PyArrayObject* out) + + Equivalent to :meth:ndarray.round (*self*, *decimals*, *out*). Returns + the array with elements rounded to the nearest decimal place. The + decimal place is defined as the :math:10^{-\textrm{decimals}} + digit so that negative *decimals* cause rounding to the nearest 10's, 100's, etc. If out is NULL, then the output array is created, otherwise the output is placed in *out* which must be the correct size and type. + +.. cfunction:: PyObject* PyArray_Std(PyArrayObject* self, int axis, int rtype, PyArrayObject* out) + + Equivalent to :meth:ndarray.std (*self*, *axis*, *rtype*). Return the + standard deviation using data along *axis* converted to data type + *rtype*. + +.. cfunction:: PyObject* PyArray_Sum(PyArrayObject* self, int axis, int rtype, PyArrayObject* out) + + Equivalent to :meth:ndarray.sum (*self*, *axis*, *rtype*). Return 1-d + vector sums of elements in *self* along *axis*. Perform the sum + after converting data to data type *rtype*. + +.. cfunction:: PyObject* PyArray_CumSum(PyArrayObject* self, int axis, int rtype, PyArrayObject* out) + + Equivalent to :meth:ndarray.cumsum (*self*, *axis*, *rtype*). Return + cumulative 1-d sums of elements in *self* along *axis*. Perform + the sum after converting data to data type *rtype*. + +.. cfunction:: PyObject* PyArray_Prod(PyArrayObject* self, int axis, int rtype, PyArrayObject* out) + + Equivalent to :meth:ndarray.prod (*self*, *axis*, *rtype*). Return 1-d + products of elements in *self* along *axis*. Perform the product + after converting data to data type *rtype*. + +.. cfunction:: PyObject* PyArray_CumProd(PyArrayObject* self, int axis, int rtype, PyArrayObject* out) + + Equivalent to :meth:ndarray.cumprod (*self*, *axis*, *rtype*). Return + 1-d cumulative products of elements in self along axis. + Perform the product after converting data to data type rtype. + +.. cfunction:: PyObject* PyArray_All(PyArrayObject* self, int axis, PyArrayObject* out) + + Equivalent to :meth:ndarray.all (*self*, *axis*). Return an array with + True elements for every 1-d sub-array of self defined by + axis in which all the elements are True. + +.. cfunction:: PyObject* PyArray_Any(PyArrayObject* self, int axis, PyArrayObject* out) + + Equivalent to :meth:ndarray.any (*self*, *axis*). Return an array with + True elements for every 1-d sub-array of *self* defined by *axis* + in which any of the elements are True. + +Functions +--------- + + +Array Functions +^^^^^^^^^^^^^^^ + +.. cfunction:: int PyArray_AsCArray(PyObject** op, void* ptr, npy_intp* dims, int nd, int typenum, int itemsize) + + Sometimes it is useful to access a multidimensional array as a + C-style multi-dimensional array so that algorithms can be + implemented using C's a[i][j][k] syntax. This routine returns a + pointer, *ptr*, that simulates this kind of C-style array, for + 1-, 2-, and 3-d ndarrays. + + :param op: + + The address to any Python object. This Python object will be replaced + with an equivalent well-behaved, C-style contiguous, ndarray of the + given data type specifice by the last two arguments. Be sure that + stealing a reference in this way to the input object is justified. + + :param ptr: + + The address to a (ctype* for 1-d, ctype** for 2-d or ctype*** for 3-d) + variable where ctype is the equivalent C-type for the data type. On + return, *ptr* will be addressable as a 1-d, 2-d, or 3-d array. + + :param dims: + + An output array that contains the shape of the array object. This + array gives boundaries on any looping that will take place. + + :param nd: + + The dimensionality of the array (1, 2, or 3). + + :param typenum: + + The expected data type of the array. + + :param itemsize: + + This argument is only needed when *typenum* represents a + flexible array. Otherwise it should be 0. + +.. note:: + + The simulation of a C-style array is not complete for 2-d and 3-d + arrays. For example, the simulated arrays of pointers cannot be passed + to subroutines expecting specific, statically-defined 2-d and 3-d + arrays. To pass to functions requiring those kind of inputs, you must + statically define the required array and copy data. + +.. cfunction:: int PyArray_Free(PyObject* op, void* ptr) + + Must be called with the same objects and memory locations returned + from :cfunc:PyArray_AsCArray (...). This function cleans up memory + that otherwise would get leaked. + +.. cfunction:: PyObject* PyArray_Concatenate(PyObject* obj, int axis) + + Join the sequence of objects in *obj* together along *axis* into a + single array. If the dimensions or types are not compatible an + error is raised. + +.. cfunction:: PyObject* PyArray_InnerProduct(PyObject* obj1, PyObject* obj2) + + Compute a product-sum over the last dimensions of *obj1* and + *obj2*. Neither array is conjugated. + +.. cfunction:: PyObject* PyArray_MatrixProduct(PyObject* obj1, PyObject* obj) + + Compute a product-sum over the last dimension of *obj1* and the + second-to-last dimension of *obj2*. For 2-d arrays this is a + matrix-product. Neither array is conjugated. + +.. cfunction:: PyObject* PyArray_CopyAndTranspose(PyObject \* op) + + A specialized copy and transpose function that works only for 2-d + arrays. The returned array is a transposed copy of *op*. + +.. cfunction:: PyObject* PyArray_Correlate(PyObject* op1, PyObject* op2, int mode) + + Compute the 1-d correlation of the 1-d arrays *op1* and *op2* + . The correlation is computed at each output point by multiplying + *op1* by a shifted version of *op2* and summing the result. As a + result of the shift, needed values outside of the defined range of + *op1* and *op2* are interpreted as zero. The mode determines how + many shifts to return: 0 - return only shifts that did not need to + assume zero- values; 1 - return an object that is the same size as + *op1*, 2 - return all possible shifts (any overlap at all is + accepted). + +.. cfunction:: PyObject* PyArray_Where(PyObject* condition, PyObject* x, PyObject* y) + + If both x and y are NULL, then return + :cfunc:PyArray_Nonzero (*condition*). Otherwise, both *x* and *y* + must be given and the object returned is shaped like *condition* + and has elements of *x* and *y* where *condition* is respectively + True or False. + + +Other functions +^^^^^^^^^^^^^^^ + +.. cfunction:: Bool PyArray_CheckStrides(int elsize, int nd, npy_intp numbytes, npy_intp* dims, npy_intp* newstrides) + + Determine if *newstrides* is a strides array consistent with the + memory of an *nd* -dimensional array with shape dims and + element-size, *elsize*. The *newstrides* array is checked to see + if jumping by the provided number of bytes in each direction will + ever mean jumping more than *numbytes* which is the assumed size + of the available memory segment. If *numbytes* is 0, then an + equivalent *numbytes* is computed assuming *nd*, *dims*, and + *elsize* refer to a single-segment array. Return :cdata:NPY_TRUE if + *newstrides* is acceptable, otherwise return :cdata:NPY_FALSE. + +.. cfunction:: npy_intp PyArray_MultiplyList(npy_intp* seq, int n) + +.. cfunction:: int PyArray_MultiplyIntList(int* seq, int n) + + Both of these routines multiply an *n* -length array, *seq*, of + integers and return the result. No overflow checking is performed. + +.. cfunction:: int PyArray_CompareLists(npy_intp* l1, npy_intp* l2, int n) + + Given two *n* -length arrays of integers, *l1*, and *l2*, return + 1 if the lists are identical; otherwise, return 0. + + +Array Iterators +--------------- + +An array iterator is a simple way to access the elements of an +N-dimensional array quickly and efficiently. Section 2 +<#sec-array-iterator>__ provides more description and examples of +this useful approach to looping over an array. + +.. cfunction:: PyObject* PyArray_IterNew(PyObject* arr) + + Return an array iterator object from the array, *arr*. This is + equivalent to *arr*. **flat**. The array iterator object makes + it easy to loop over an N-dimensional non-contiguous array in + C-style contiguous fashion. + +.. cfunction:: PyObject* PyArray_IterAllButAxis(PyObject* arr, int \*axis) + + Return an array iterator that will iterate over all axes but the + one provided in *\*axis*. The returned iterator cannot be used + with :cfunc:PyArray_ITER_GOTO1D. This iterator could be used to + write something similar to what ufuncs do wherein the loop over + the largest axis is done by a separate sub-routine. If *\*axis* is + negative then *\*axis* will be set to the axis having the smallest + stride and that axis will be used. + +.. cfunction:: PyObject *PyArray_BroadcastToShape(PyObject* arr, npy_intp *dimensions, int nd) + + Return an array iterator that is broadcast to iterate as an array + of the shape provided by *dimensions* and *nd*. + +.. cfunction:: int PyArrayIter_Check(PyObject* op) + + Evaluates true if *op* is an array iterator (or instance of a + subclass of the array iterator type). + +.. cfunction:: void PyArray_ITER_RESET(PyObject* iterator) + + Reset an *iterator* to the beginning of the array. + +.. cfunction:: void PyArray_ITER_NEXT(PyObject* iterator) + + Incremement the index and the dataptr members of the *iterator* to + point to the next element of the array. If the array is not + (C-style) contiguous, also increment the N-dimensional coordinates + array. + +.. cfunction:: void *PyArray_ITER_DATA(PyObject* iterator) + + A pointer to the current element of the array. + +.. cfunction:: void PyArray_ITER_GOTO(PyObject* iterator, npy_intp* destination) + + Set the *iterator* index, dataptr, and coordinates members to the + location in the array indicated by the N-dimensional c-array, + *destination*, which must have size at least *iterator* + ->nd_m1+1. + +.. cfunction:: PyArray_ITER_GOTO1D(PyObject* iterator, npy_intp index) + + Set the *iterator* index and dataptr to the location in the array + indicated by the integer *index* which points to an element in the + C-styled flattened array. + +.. cfunction:: int PyArray_ITER_NOTDONE(PyObject* iterator) + + Evaluates TRUE as long as the iterator has not looped through all of + the elements, otherwise it evaluates FALSE. + + +Broadcasting (multi-iterators) +------------------------------ + +.. cfunction:: PyObject* PyArray_MultiIterNew(int num, ...) + + A simplified interface to broadcasting. This function takes the + number of arrays to broadcast and then *num* extra ( :ctype:PyObject * + ) arguments. These arguments are converted to arrays and iterators + are created. :cfunc:PyArray_Broadcast is then called on the resulting + multi-iterator object. The resulting, broadcasted mult-iterator + object is then returned. A broadcasted operation can then be + performed using a single loop and using :cfunc:PyArray_MultiIter_NEXT + (..) + +.. cfunction:: void PyArray_MultiIter_RESET(PyObject* multi) + + Reset all the iterators to the beginning in a multi-iterator + object, *multi*. + +.. cfunction:: void PyArray_MultiIter_NEXT(PyObject* multi) + + Advance each iterator in a multi-iterator object, *multi*, to its + next (broadcasted) element. + +.. cfunction:: void *PyArray_MultiIter_DATA(PyObject* multi, int i) + + Return the data-pointer of the *i* :math:^{\textrm{th}} iterator + in a multi-iterator object. + +.. cfunction:: void PyArray_MultiIter_NEXTi(PyObject* multi, int i) + + Advance the pointer of only the *i* :math:^{\textrm{th}} iterator. + +.. cfunction:: void PyArray_MultiIter_GOTO(PyObject* multi, npy_intp* destination) + + Advance each iterator in a multi-iterator object, *multi*, to the + given :math:N -dimensional *destination* where :math:N is the + number of dimensions in the broadcasted array. + +.. cfunction:: void PyArray_MultiIter_GOTO1D(PyObject* multi, npy_intp index) + + Advance each iterator in a multi-iterator object, *multi*, to the + corresponding location of the *index* into the flattened + broadcasted array. + +.. cfunction:: int PyArray_MultiIter_NOTDONE(PyObject* multi) + + Evaluates TRUE as long as the multi-iterator has not looped + through all of the elements (of the broadcasted result), otherwise + it evaluates FALSE. + +.. cfunction:: int PyArray_Broadcast(PyArrayMultiIterObject* mit) + + This function encapsulates the broadcasting rules. The *mit* + container should already contain iterators for all the arrays that + need to be broadcast. On return, these iterators will be adjusted + so that iteration over each simultaneously will accomplish the + broadcasting. A negative number is returned if an error occurs. + +.. cfunction:: int PyArray_RemoveSmallest(PyArrayMultiIterObject* mit) + + This function takes a multi-iterator object that has been + previously "broadcasted," finds the dimension with the smallest + "sum of strides" in the broadcasted result and adapts all the + iterators so as not to iterate over that dimension (by effectively + making them of length-1 in that dimension). The corresponding + dimension is returned unless *mit* ->nd is 0, then -1 is + returned. This function is useful for constructing ufunc-like + routines that broadcast their inputs correctly and then call a + strided 1-d version of the routine as the inner-loop. This 1-d + version is usually optimized for speed and for this reason the + loop should be performed over the axis that won't require large + stride jumps. + + +Array Scalars +------------- + +.. cfunction:: PyObject* PyArray_Return(PyArrayObject* arr) + + This function checks to see if *arr* is a 0-dimensional array and, + if so, returns the appropriate array scalar. It should be used + whenever 0-dimensional arrays could be returned to Python. + +.. cfunction:: PyObject* PyArray_Scalar(void* data, PyArray_Descr* dtype, PyObject* itemsize) + + Return an array scalar object of the given enumerated *typenum* + and *itemsize* by **copying** from memory pointed to by *data* + . If *swap* is nonzero then this function will byteswap the data + if appropriate to the data-type because array scalars are always + in correct machine-byte order. + +.. cfunction:: PyObject* PyArray_ToScalar(void* data, PyArrayObject* arr) + + Return an array scalar object of the type and itemsize indicated + by the array object *arr* copied from the memory pointed to by + *data* and swapping if the data in *arr* is not in machine + byte-order. + +.. cfunction:: PyObject* PyArray_FromScalar(PyObject* scalar, PyArray_Descr* outcode) + + Return a 0-dimensional array of type determined by *outcode* from + *scalar* which should be an array-scalar object. If *outcode* is + NULL, then the type is determined from *scalar*. + +.. cfunction:: void PyArray_ScalarAsCtype(PyObject* scalar, void* ctypeptr) + + Return in *ctypeptr* a pointer to the actual value in an array + scalar. There is no error checking so *scalar* must be an + array-scalar object, and ctypeptr must have enough space to hold + the correct type. For flexible-sized types, a pointer to the data + is copied into the memory of *ctypeptr*, for all other types, the + actual data is copied into the address pointed to by *ctypeptr*. + +.. cfunction:: void PyArray_CastScalarToCtype(PyObject* scalar, void* ctypeptr, PyArray_Descr* outcode) + + Return the data (cast to the data type indicated by *outcode*) + from the array-scalar, *scalar*, into the memory pointed to by + *ctypeptr* (which must be large enough to handle the incoming + memory). + +.. cfunction:: PyObject* PyArray_TypeObjectFromType(int type) + + Returns a scalar type-object from a type-number, *type* + . Equivalent to :cfunc:PyArray_DescrFromType (*type*)->typeobj + except for reference counting and error-checking. Returns a new + reference to the typeobject on success or NULL on failure. + +.. cfunction:: NPY_SCALARKIND PyArray_ScalarKind(int typenum, PyArrayObject** arr) + + Return the kind of scalar represented by *typenum* and the array + in *\*arr* (if *arr* is not NULL ). The array is assumed to be + rank-0 and only used if *typenum* represents a signed integer. If + *arr* is not NULL and the first element is negative then + :cdata:NPY_INTNEG_SCALAR is returned, otherwise + :cdata:NPY_INTPOS_SCALAR is returned. The possible return values + are :cdata:NPY_{kind}_SCALAR where {kind} can be **INTPOS**, + **INTNEG**, **FLOAT**, **COMPLEX**, **BOOL**, or **OBJECT**. + :cdata:NPY_NOSCALAR is also an enumerated value + :ctype:NPY_SCALARKIND variables can take on. + +.. cfunction:: int PyArray_CanCoerceScalar(char thistype, char neededtype, NPY_SCALARKIND scalar) + + Implements the rules for scalar coercion. Scalars are only + silently coerced from thistype to neededtype if this function + returns nonzero. If scalar is :cdata:NPY_NOSCALAR, then this + function is equivalent to :cfunc:PyArray_CanCastSafely. The rule is + that scalars of the same KIND can be coerced into arrays of the + same KIND. This rule means that high-precision scalars will never + cause low-precision arrays of the same KIND to be upcast. + + +Data-type descriptors +--------------------- + + + +.. warning:: + + Data-type objects must be reference counted so be aware of the + action on the data-type reference of different C-API calls. The + standard rule is that when a data-type object is returned it is a + new reference. Functions that take :ctype:PyArray_Descr * objects and + return arrays steal references to the data-type their inputs + unless otherwise noted. Therefore, you must own a reference to any + data-type object used as input to such a function. + +.. cfunction:: int PyArrayDescr_Check(PyObject* obj) + + Evaluates as true if *obj* is a data-type object ( :ctype:PyArray_Descr * ). + +.. cfunction:: PyArray_Descr* PyArray_DescrNew(PyArray_Descr* obj) + + Return a new data-type object copied from *obj* (the fields + reference is just updated so that the new object points to the + same fields dictionary if any). + +.. cfunction:: PyArray_Descr* PyArray_DescrNewFromType(int typenum) + + Create a new data-type object from the built-in (or + user-registered) data-type indicated by *typenum*. All builtin + types should not have any of their fields changed. This creates a + new copy of the :ctype:PyArray_Descr structure so that you can fill + it in as appropriate. This function is especially needed for + flexible data-types which need to have a new elsize member in + order to be meaningful in array construction. + +.. cfunction:: PyArray_Descr* PyArray_DescrNewByteorder(PyArray_Descr* obj, char newendian) + + Create a new data-type object with the byteorder set according to + *newendian*. All referenced data-type objects (in subdescr and + fields members of the data-type object) are also changed + (recursively). If a byteorder of :cdata:NPY_IGNORE is encountered it + is left alone. If newendian is :cdata:NPY_SWAP, then all byte-orders + are swapped. Other valid newendian values are :cdata:NPY_NATIVE, + :cdata:NPY_LITTLE, and :cdata:NPY_BIG which all cause the returned + data-typed descriptor (and all it's + referenced data-type descriptors) to have the corresponding byte- + order. + +.. cfunction:: PyArray_Descr* PyArray_DescrFromObject(PyObject* op, PyArray_Descr* mintype) + + Determine an appropriate data-type object from the object *op* + (which should be a "nested" sequence object) and the minimum + data-type descriptor mintype (which can be NULL ). Similar in + behavior to array(*op*).dtype. Don't confuse this function with + :cfunc:PyArray_DescrConverter. This function essentially looks at + all the objects in the (nested) sequence and determines the + data-type from the elements it finds. + +.. cfunction:: PyArray_Descr* PyArray_DescrFromScalar(PyObject* scalar) + + Return a data-type object from an array-scalar object. No checking + is done to be sure that *scalar* is an array scalar. If no + suitable data-type can be determined, then a data-type of + :cdata:NPY_OBJECT is returned by default. + +.. cfunction:: PyArray_Descr* PyArray_DescrFromType(int typenum) + + Returns a data-type object corresponding to *typenum*. The + *typenum* can be one of the enumerated types, a character code for + one of the enumerated types, or a user-defined type. + +.. cfunction:: int PyArray_DescrConverter(PyObject* obj, PyArray_Descr** dtype) + + Convert any compatible Python object, *obj*, to a data-type object + in *dtype*. A large number of Python objects can be converted to + data-type objects. See :ref:arrays.dtypes for a complete + description. This version of the converter converts None objects + to a :cdata:NPY_DEFAULT_TYPE data-type object. This function can + be used with the "O&" character code in :cfunc:PyArg_ParseTuple + processing. + +.. cfunction:: int PyArray_DescrConverter2(PyObject* obj, PyArray_Descr** dtype) + + Convert any compatible Python object, *obj*, to a data-type + object in *dtype*. This version of the converter converts None + objects so that the returned data-type is NULL. This function + can also be used with the "O&" character in PyArg_ParseTuple + processing. + +.. cfunction:: int Pyarray_DescrAlignConverter(PyObject* obj, PyArray_Descr** dtype) + + Like :cfunc:PyArray_DescrConverter except it aligns C-struct-like + objects on word-boundaries as the compiler would. + +.. cfunction:: int Pyarray_DescrAlignConverter2(PyObject* obj, PyArray_Descr** dtype) + + Like :cfunc:PyArray_DescrConverter2 except it aligns C-struct-like + objects on word-boundaries as the compiler would. + +.. cfunction:: PyObject *PyArray_FieldNames(PyObject* dict) + + Take the fields dictionary, *dict*, such as the one attached to a + data-type object and construct an ordered-list of field names such + as is stored in the names field of the :ctype:PyArray_Descr object. + + +Conversion Utilities +-------------------- + + +For use with :cfunc:PyArg_ParseTuple +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +All of these functions can be used in :cfunc:PyArg_ParseTuple (...) with +the "O&" format specifier to automatically convert any Python object +to the required C-object. All of these functions return +:cdata:NPY_SUCCEED if successful and :cdata:NPY_FAIL if not. The first +argument to all of these function is a Python object. The second +argument is the **address** of the C-type to convert the Python object +to. + + +.. warning:: + + Be sure to understand what steps you should take to manage the + memory when using these conversion functions. These functions can + require freeing memory, and/or altering the reference counts of + specific objects based on your use. + +.. cfunction:: int PyArray_Converter(PyObject* obj, PyObject** address) + + Convert any Python object to a :ctype:PyArrayObject. If + :cfunc:PyArray_Check (*obj*) is TRUE then its reference count is + incremented and a reference placed in *address*. If *obj* is not + an array, then convert it to an array using :cfunc:PyArray_FromAny + . No matter what is returned, you must DECREF the object returned + by this routine in *address* when you are done with it. + +.. cfunction:: int PyArray_OutputConverter(PyObject* obj, PyArrayObject** address) + + This is a default converter for output arrays given to + functions. If *obj* is :cdata:Py_None or NULL, then *\*address* + will be NULL but the call will succeed. If :cfunc:PyArray_Check ( + *obj*) is TRUE then it is returned in *\*address* without + incrementing its reference count. + +.. cfunction:: int PyArray_IntpConverter(PyObject* obj, PyArray_Dims* seq) + + Convert any Python sequence, *obj*, smaller than :cdata:NPY_MAXDIMS + to a C-array of :ctype:npy_intp. The Python object could also be a + single number. The *seq* variable is a pointer to a structure with + members ptr and len. On successful return, *seq* ->ptr contains a + pointer to memory that must be freed to avoid a memory leak. The + restriction on memory size allows this converter to be + conveniently used for sequences intended to be interpreted as + array shapes. + +.. cfunction:: int PyArray_BufferConverter(PyObject* obj, PyArray_Chunk* buf) + + Convert any Python object, *obj*, with a (single-segment) buffer + interface to a variable with members that detail the object's use + of its chunk of memory. The *buf* variable is a pointer to a + structure with base, ptr, len, and flags members. The + :ctype:PyArray_Chunk structure is binary compatibile with the + Python's buffer object (through its len member on 32-bit platforms + and its ptr member on 64-bit platforms or in Python 2.5). On + return, the base member is set to *obj* (or its base if *obj* is + already a buffer object pointing to another object). If you need + to hold on to the memory be sure to INCREF the base member. The + chunk of memory is pointed to by *buf* ->ptr member and has length + *buf* ->len. The flags member of *buf* is :cdata:NPY_BEHAVED_RO with + the :cdata:NPY_WRITEABLE flag set if *obj* has a writeable buffer + interface. + +.. cfunction:: int PyArray_AxisConverter(PyObject \* obj, int* axis) + + Convert a Python object, *obj*, representing an axis argument to + the proper value for passing to the functions that take an integer + axis. Specifically, if *obj* is None, *axis* is set to + :cdata:NPY_MAXDIMS which is interpreted correctly by the C-API + functions that take axis arguments. + +.. cfunction:: int PyArray_BoolConverter(PyObject* obj, Bool* value) + + Convert any Python object, *obj*, to :cdata:NPY_TRUE or + :cdata:NPY_FALSE, and place the result in *value*. + +.. cfunction:: int PyArray_ByteorderConverter(PyObject* obj, char* endian) + + Convert Python strings into the corresponding byte-order + character: + '>', '<', 's', '=', or '\|'. + +.. cfunction:: int PyArray_SortkindConverter(PyObject* obj, NPY_SORTKIND* sort) + + Convert Python strings into one of :cdata:NPY_QUICKSORT (starts + with 'q' or 'Q') , :cdata:NPY_HEAPSORT (starts with 'h' or 'H'), + or :cdata:NPY_MERGESORT (starts with 'm' or 'M'). + +.. cfunction:: int PyArray_SearchsideConverter(PyObject* obj, NPY_SEARCHSIDE* side) + + Convert Python strings into one of :cdata:NPY_SEARCHLEFT (starts with 'l' + or 'L'), or :cdata:NPY_SEARCHRIGHT (starts with 'r' or 'R'). + +Other conversions +^^^^^^^^^^^^^^^^^ + +.. cfunction:: int PyArray_PyIntAsInt(PyObject* op) + + Convert all kinds of Python objects (including arrays and array + scalars) to a standard integer. On error, -1 is returned and an + exception set. You may find useful the macro: + + .. code-block:: c + + #define error_converting(x) (((x) == -1) && PyErr_Occurred() + +.. cfunction:: npy_intp PyArray_PyIntAsIntp(PyObject* op) + + Convert all kinds of Python objects (including arrays and array + scalars) to a (platform-pointer-sized) integer. On error, -1 is + returned and an exception set. + +.. cfunction:: int PyArray_IntpFromSequence(PyObject* seq, npy_intp* vals, int maxvals) + + Convert any Python sequence (or single Python number) passed in as + *seq* to (up to) *maxvals* pointer-sized integers and place them + in the *vals* array. The sequence can be smaller then *maxvals* as + the number of converted objects is returned. + +.. cfunction:: int PyArray_TypestrConvert(int itemsize, int gentype) + + Convert typestring characters (with *itemsize*) to basic + enumerated data types. The typestring character corresponding to + signed and unsigned integers, floating point numbers, and + complex-floating point numbers are recognized and converted. Other + values of gentype are returned. This function can be used to + convert, for example, the string'f4' to :cdata:NPY_FLOAT32. + + +Miscellaneous +------------- + + +Importing the API +^^^^^^^^^^^^^^^^^ + +In order to make use of the C-API from another extension module, the +import_array () command must be used. If the extension module is +self-contained in a single .c file, then that is all that needs to be +done. If, however, the extension module involves multiple files where +the C-API is needed then some additional steps must be taken. + +.. cfunction:: void import_array(void) + + This function must be called in the initialization section of a + module that will make use of the C-API. It imports the module + where the function-pointer table is stored and points the correct + variable to it. + +.. cmacro:: PY_ARRAY_UNIQUE_SYMBOL + +.. cmacro:: NO_IMPORT_ARRAY + + Using these #defines you can use the C-API in multiple files for a + single extension module. In each file you must define + :cmacro:PY_ARRAY_UNIQUE_SYMBOL to some name that will hold the + C-API (*e.g.* myextension_ARRAY_API). This must be done **before** + including the numpy/arrayobject.h file. In the module + intialization routine you call import_array (). In addition, + in the files that do not have the module initialization + sub_routine define :cmacro:NO_IMPORT_ARRAY prior to including + numpy/arrayobject.h. + + Suppose I have two files coolmodule.c and coolhelper.c which need + to be compiled and linked into a single extension module. Suppose + coolmodule.c contains the required initcool module initialization + function (with the import_array() function called). Then, + coolmodule.c would have at the top: + + .. code-block:: c + + #define PY_ARRAY_UNIQUE_SYMBOL cool_ARRAY_API + #include numpy/arrayobject.h + + On the other hand, coolhelper.c would contain at the top: + + .. code-block:: c + + #define PY_ARRAY_UNIQUE_SYMBOL cool_ARRAY_API + #define NO_IMPORT_ARRAY + #include numpy/arrayobject.h + +.. cfunction:: unsigned int PyArray_GetNDArrayCVersion(void) + + This just returns the value :cdata:NPY_VERSION. Because it is in the + C-API, however, comparing the output of this function from the + value defined in the current header gives a way to test if the + C-API has changed thus requiring a re-compilation of extension + modules that use the C-API. + + +Internal Flexibility +^^^^^^^^^^^^^^^^^^^^ + +.. cfunction:: int PyArray_SetNumericOps(PyObject* dict) + + NumPy stores an internal table of Python callable objects that are + used to implement arithmetic operations for arrays as well as + certain array calculation methods. This function allows the user + to replace any or all of these Python objects with their own + versions. The keys of the dictionary, *dict*, are the named + functions to replace and the paired value is the Python callable + object to use. Care should be taken that the function used to + replace an internal array operation does not itself call back to + that internal array operation (unless you have designed the + function to handle that), or an unchecked infinite recursion can + result (possibly causing program crash). The key names that + represent operations that can be replaced are: + + **add**, **subtract**, **multiply**, **divide**, + **remainder**, **power**, **square**, **reciprocal**, + **ones_like**, **sqrt**, **negative**, **absolute**, + **invert**, **left_shift**, **right_shift**, + **bitwise_and**, **bitwise_xor**, **bitwise_or**, + **less**, **less_equal**, **equal**, **not_equal**, + **greater**, **greater_equal**, **floor_divide**, + **true_divide**, **logical_or**, **logical_and**, + **floor**, **ceil**, **maximum**, **minimum**, **rint**. + + + These functions are included here because they are used at least once + in the array object's methods. The function returns -1 (without + setting a Python Error) if one of the objects being assigned is not + callable. + +.. cfunction:: PyObject* PyArray_GetNumericOps(void) + + Return a Python dictionary containing the callable Python objects + stored in the the internal arithmetic operation table. The keys of + this dictionary are given in the explanation for :cfunc:PyArray_SetNumericOps. + +.. cfunction:: void PyArray_SetStringFunction(PyObject* op, int repr) + + This function allows you to alter the tp_str and tp_repr methods + of the array object to any Python function. Thus you can alter + what happens for all arrays when str(arr) or repr(arr) is called + from Python. The function to be called is passed in as *op*. If + *repr* is non-zero, then this function will be called in response + to repr(arr), otherwise the function will be called in response to + str(arr). No check on whether or not *op* is callable is + performed. The callable passed in to *op* should expect an array + argument and should return a string to be printed. + + +Memory management +^^^^^^^^^^^^^^^^^ + +.. cfunction:: char* PyDataMem_NEW(size_t nbytes) + +.. cfunction:: PyDataMem_FREE(char* ptr) + +.. cfunction:: char* PyDataMem_RENEW(void * ptr, size_t newbytes) + + Macros to allocate, free, and reallocate memory. These macros are used + internally to create arrays. + +.. cfunction:: npy_intp* PyDimMem_NEW(nd) + +.. cfunction:: PyDimMem_FREE(npy_intp* ptr) + +.. cfunction:: npy_intp* PyDimMem_RENEW(npy_intp* ptr, npy_intp newnd) + + Macros to allocate, free, and reallocate dimension and strides memory. + +.. cfunction:: PyArray_malloc(nbytes) + +.. cfunction:: PyArray_free(ptr) + +.. cfunction:: PyArray_realloc(ptr, nbytes) + + These macros use different memory allocators, depending on the + constant :cdata:NPY_USE_PYMEM. The system malloc is used when + :cdata:NPY_USE_PYMEM is 0, if :cdata:NPY_USE_PYMEM is 1, then + the Python memory allocator is used. + + +Threading support +^^^^^^^^^^^^^^^^^ + +These macros are only meaningful if :cdata:NPY_ALLOW_THREADS +evaluates True during compilation of the extension module. Otherwise, +these macros are equivalent to whitespace. Python uses a single Global +Interpreter Lock (GIL) for each Python process so that only a single +thread may excecute at a time (even on multi-cpu machines). When +calling out to a compiled function that may take time to compute (and +does not have side-effects for other threads like updated global +variables), the GIL should be released so that other Python threads +can run while the time-consuming calculations are performed. This can +be accomplished using two groups of macros. Typically, if one macro in +a group is used in a code block, all of them must be used in the same +code block. Currently, :cdata:NPY_ALLOW_THREADS is defined to the +python-defined :cdata:WITH_THREADS constant unless the environment +variable :cdata:NPY_NOSMP is set in which case +:cdata:NPY_ALLOW_THREADS is defined to be 0. + +Group 1 +""""""" + + This group is used to call code that may take some time but does not + use any Python C-API calls. Thus, the GIL should be released during + its calculation. + + .. cmacro:: NPY_BEGIN_ALLOW_THREADS + + Equivalent to :cmacro:Py_BEGIN_ALLOW_THREADS except it uses + :cdata:NPY_ALLOW_THREADS to determine if the macro if + replaced with white-space or not. + + .. cmacro:: NPY_END_ALLOW_THREADS + + Equivalent to :cmacro:Py_END_ALLOW_THREADS except it uses + :cdata:NPY_ALLOW_THREADS to determine if the macro if + replaced with white-space or not. + + .. cmacro:: NPY_BEGIN_THREADS_DEF + + Place in the variable declaration area. This macro sets up the + variable needed for storing the Python state. + + .. cmacro:: NPY_BEGIN_THREADS + + Place right before code that does not need the Python + interpreter (no Python C-API calls). This macro saves the + Python state and releases the GIL. + + .. cmacro:: NPY_END_THREADS + + Place right after code that does not need the Python + interpreter. This macro acquires the GIL and restores the + Python state from the saved variable. + + .. cfunction:: NPY_BEGIN_THREADS_DESCR(PyArray_Descr *dtype) + + Useful to release the GIL only if *dtype* does not contain + arbitrary Python objects which may need the Python interpreter + during execution of the loop. Equivalent to + + .. cfunction:: NPY_END_THREADS_DESCR(PyArray_Descr *dtype) + + Useful to regain the GIL in situations where it was released + using the BEGIN form of this macro. + +Group 2 +""""""" + + This group is used to re-acquire the Python GIL after it has been + released. For example, suppose the GIL has been released (using the + previous calls), and then some path in the code (perhaps in a + different subroutine) requires use of the Python C-API, then these + macros are useful to acquire the GIL. These macros accomplish + essentially a reverse of the previous three (acquire the LOCK saving + what state it had) and then re-release it with the saved state. + + .. cmacro:: NPY_ALLOW_C_API_DEF + + Place in the variable declaration area to set up the necessary + variable. + + .. cmacro:: NPY_ALLOW_C_API + + Place before code that needs to call the Python C-API (when it is + known that the GIL has already been released). + + .. cmacro:: NPY_DISABLE_C_API + + Place after code that needs to call the Python C-API (to re-release + the GIL). + +.. tip:: + + Never use semicolons after the threading support macros. + + +Priority +^^^^^^^^ + +.. cvar:: NPY_PRIOIRTY + + Default priority for arrays. + +.. cvar:: NPY_SUBTYPE_PRIORITY + + Default subtype priority. + +.. cvar:: NPY_SCALAR_PRIORITY + + Default scalar priority (very small) + +.. cfunction:: double PyArray_GetPriority(PyObject* obj, double def) + + Return the :obj:__array_priority__ attribute (converted to a + double) of *obj* or *def* if no attribute of that name + exists. Fast returns that avoid the attribute lookup are provided + for objects of type :cdata:PyArray_Type. + + +Default buffers +^^^^^^^^^^^^^^^ + +.. cvar:: NPY_BUFSIZE + + Default size of the user-settable internal buffers. + +.. cvar:: NPY_MIN_BUFSIZE + + Smallest size of user-settable internal buffers. + +.. cvar:: NPY_MAX_BUFSIZE + + Largest size allowed for the user-settable buffers. + + +Other constants +^^^^^^^^^^^^^^^ + +.. cvar:: NPY_NUM_FLOATTYPE + + The number of floating-point types + +.. cvar:: NPY_MAXDIMS + + The maximum number of dimensions allowed in arrays. + +.. cvar:: NPY_VERSION + + The current version of the ndarray object (check to see if this + variable is defined to guarantee the numpy/arrayobject.h header is + being used). + +.. cvar:: NPY_FALSE + + Defined as 0 for use with Bool. + +.. cvar:: NPY_TRUE + + Defined as 1 for use with Bool. + +.. cvar:: NPY_FAIL + + The return value of failed converter functions which are called using + the "O&" syntax in :cfunc:PyArg_ParseTuple-like functions. + +.. cvar:: NPY_SUCCEED + + The return value of successful converter functions which are called + using the "O&" syntax in :cfunc:PyArg_ParseTuple-like functions. + + +Miscellaneous Macros +^^^^^^^^^^^^^^^^^^^^ + +.. cfunction:: PyArray_SAMESHAPE(a1, a2) + + Evaluates as True if arrays *a1* and *a2* have the same shape. + +.. cfunction:: PyArray_MAX(a,b) + + Returns the maximum of *a* and *b*. If (*a*) or (*b*) are + expressions they are evaluated twice. + +.. cfunction:: PyArray_MIN(a,b) + + Returns the minimum of *a* and *b*. If (*a*) or (*b*) are + expressions they are evaluated twice. + +.. cfunction:: PyArray_CLT(a,b) + +.. cfunction:: PyArray_CGT(a,b) + +.. cfunction:: PyArray_CLE(a,b) + +.. cfunction:: PyArray_CGE(a,b) + +.. cfunction:: PyArray_CEQ(a,b) + +.. cfunction:: PyArray_CNE(a,b) + + Implements the complex comparisons between two complex numbers + (structures with a real and imag member) using NumPy's definition + of the ordering which is lexicographic: comparing the real parts + first and then the complex parts if the real parts are equal. + +.. cfunction:: PyArray_REFCOUNT(PyObject* op) + + Returns the reference count of any Python object. + +.. cfunction:: PyArray_XDECREF_ERR(PyObject \*obj) + + DECREF's an array object which may have the :cdata:NPY_UPDATEIFCOPY + flag set without causing the contents to be copied back into the + original array. Resets the :cdata:NPY_WRITEABLE flag on the base + object. This is useful for recovering from an error condition when + :cdata:NPY_UPDATEIFCOPY is used. + + +Enumerated Types +^^^^^^^^^^^^^^^^ + +.. ctype:: NPY_SORTKIND + + A special variable-type which can take on the values :cdata:NPY_{KIND} + where {KIND} is + + **QUICKSORT**, **HEAPSORT**, **MERGESORT** + + .. cvar:: NPY_NSORTS + + Defined to be the number of sorts. + +.. ctype:: NPY_SCALARKIND + + A special variable type indicating the number of "kinds" of + scalars distinguished in determining scalar-coercion rules. This + variable can take on the values :cdata:NPY_{KIND} where {KIND} can be + + **NOSCALAR**, **BOOL_SCALAR**, **INTPOS_SCALAR**, + **INTNEG_SCALAR**, **FLOAT_SCALAR**, **COMPLEX_SCALAR**, + **OBJECT_SCALAR** + + + .. cvar:: NPY_NSCALARKINDS + + Defined to be the number of scalar kinds + (not including :cdata:NPY_NOSCALAR). + +.. ctype:: NPY_ORDER + + A variable type indicating the order that an array should be + interpreted in. The value of a variable of this type can be + :cdata:NPY_{ORDER} where {ORDER} is + + **ANYORDER**, **CORDER**, **FORTRANORDER** + +.. ctype:: NPY_CLIPMODE + + A variable type indicating the kind of clipping that should be + applied in certain functions. The value of a variable of this type + can be :cdata:NPY_{MODE} where {MODE} is + + **CLIP**, **WRAP**, **RAISE** + +.. index:: + pair: ndarray; C-API Added: numpy-docs/trunk/source/reference/c-api.config.rst =================================================================== --- numpy-docs/trunk/source/reference/c-api.config.rst 2008-10-26 17:50:36 UTC (rev 5958) +++ numpy-docs/trunk/source/reference/c-api.config.rst 2008-10-26 17:57:55 UTC (rev 5959) @@ -0,0 +1,110 @@ +Configuration defines +===================== + +.. sectionauthor:: Travis E. Oliphant + +When NumPy is built, a configuration file is constructed and placed as +config.h in the NumPy include directory. This configuration file +ensures that specific macros are defined and defines other macros +based on whether or not your system has certain features. It is +included by the arrayobject.h file. + + +Guaranteed to be defined +------------------------ + +The :cdata:SIZEOF_{CTYPE} constants are defined so that sizeof +information is available to the pre-processor. + +.. cvar:: CHAR_BIT + + The number of bits of a char. The char is the unit of all sizeof + definitions + +.. cvar:: SIZEOF_SHORT + + sizeof(short) + +.. cvar:: SIZEOF_INT + + sizeof(int) + +.. cvar:: SIZEOF_LONG + + sizeof(long) + +.. cvar:: SIZEOF_LONG_LONG + + sizeof(longlong) where longlong is defined appropriately on the + platform (A macro defines **SIZEOF_LONGLONG** as well.) + +.. cvar:: SIZEOF_PY_LONG_LONG + + +.. cvar:: SIZEOF_FLOAT + + sizeof(float) + +.. cvar:: SIZEOF_DOUBLE + + sizeof(double) + +.. cvar:: SIZEOF_LONG_DOUBLE + + sizeof(longdouble) (A macro defines **SIZEOF_LONGDOUBLE** as well.) + +.. cvar:: SIZEOF_PY_INTPTR_T + + Size of a pointer on this platform (sizeof(void \*)) (A macro defines + SIZEOF_INTP as well.) + + +Possible defines +---------------- + +These defines will cause the compilation to ignore compatibility code +that is placed in NumPy and use the system code instead. If they are +not defined, then the system does not have that capability. + +.. cvar:: HAVE_LONGDOUBLE_FUNCS + + System has C99 long double math functions. + +.. cvar:: HAVE_FLOAT_FUNCS + + System has C99 float math functions. + +.. cvar:: HAVE_INVERSE_HYPERBOLIC + + System has inverse hyperbolic functions: asinh, acosh, and atanh. + +.. cvar:: HAVE_INVERSE_HYPERBOLIC_FLOAT + + System has C99 float extensions to inverse hyperbolic functions: + asinhf, acoshf, atanhf + +.. cvar:: HAVE_INVERSE_HYPERBOLIC_LONGDOUBLE + + System has C99 long double extensions to inverse hyperbolic functions: + asinhl, acoshl, atanhl. + +.. cvar:: HAVE_ISNAN + + System has an isnan function. + +.. cvar:: HAVE_ISINF + + System has an isinf function. + +.. cvar:: HAVE_LOG1P + + System has the log1p function: :math:\log\left(x+1\right). + +.. cvar:: HAVE_EXPM1 + + System has the expm1 function: :math:\exp\left(x\right)-1. + +.. cvar:: HAVE_RINT + + System has the rint function. + Added: numpy-docs/trunk/source/reference/c-api.dtype.rst =================================================================== --- numpy-docs/trunk/source/reference/c-api.dtype.rst 2008-10-26 17:50:36 UTC (rev 5958) +++ numpy-docs/trunk/source/reference/c-api.dtype.rst 2008-10-26 17:57:55 UTC (rev 5959) @@ -0,0 +1,218 @@ +Data Type API +============= + +.. sectionauthor:: Travis E. Oliphant + +The standard array can have 21 different data types (and has some +support for adding your own types). These data types all have an +enumerated type, an enumerated type-character, and a corresponding +array scalar Python type object (placed in a hierarchy). There are +also standard C typedefs to make it easier to manipulate elements of +the given data type. For the numeric types, there are also bit-width +equivalent C typedefs and named typenumbers that make it easier to +select the precision desired. + +.. warning:: + + The names for the types in c code follows c naming conventions + more closely. The Python names for these types follow Python + conventions. Thus, :cdata:NPY_FLOAT picks up a 32-bit float in + C, but :class:numpy.float_ in Python corresponds to a 64-bit + double. The bit-width names can be used in both Python and C for + clarity. + + +Enumerated Types +---------------- + +There is a list of enumerated types defined providing the basic 21 +data types plus some useful generic names. Whenever the code requires +a type number, one of these enumerated types is requested. The types +are all called :cdata:NPY_{NAME} where {NAME} can be + + **BOOL**, **BYTE**, **UBYTE**, **SHORT**, **USHORT**, **INT**, + **UINT**, **LONG**, **ULONG**, **LONGLONG**, **ULONGLONG**, + **FLOAT**, **DOUBLE**, **LONGDOUBLE**, **CFLOAT**, **CDOUBLE**, + **CLONGDOUBLE**, **OBJECT**, **STRING**, **UNICODE**, **VOID** + + **NTYPES**, **NOTYPE**, **USERDEF**, **DEFAULT_TYPE** + +The various character codes indicating certain types are also part of +an enumerated list. References to type characters (should they be +needed at all) should always use these enumerations. The form of them +is :cdata:NPY_{NAME}LTR where {NAME} can be + + **BOOL**, **BYTE**, **UBYTE**, **SHORT**, **USHORT**, **INT**, + **UINT**, **LONG**, **ULONG**, **LONGLONG**, **ULONGLONG**, + **FLOAT**, **DOUBLE**, **LONGDOUBLE**, **CFLOAT**, **CDOUBLE**, + **CLONGDOUBLE**, **OBJECT**, **STRING**, **VOID** + + **INTP**, **UINTP** + + **GENBOOL**, **SIGNED**, **UNSIGNED**, **FLOATING**, **COMPLEX** + +The latter group of {NAME}s corresponds to letters used in the array +interface typestring specification. + + +Defines +------- + +Max and min values for integers +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. cvar:: NPY_MAX_INT{bits} + +.. cvar:: NPY_MAX_UINT{bits} + +.. cvar:: NPY_MIN_INT{bits} + + These are defined for {bits} = 8, 16, 32, 64, 128, and 256 and provide + the maximum (minimum) value of the corresponding (unsigned) integer + type. Note: the actual integer type may not be available on all + platforms (i.e. 128-bit and 256-bit integers are rare). + +.. cvar:: NPY_MIN_{type} + + This is defined for {type} = **BYTE**, **SHORT**, **INT**, + **LONG**, **LONGLONG**, **INTP** + +.. cvar:: NPY_MAX_{type} + + This is defined for all defined for {type} = **BYTE**, **UBYTE**, + **SHORT**, **USHORT**, **INT**, **UINT**, **LONG**, **ULONG**, + **LONGLONG**, **ULONGLONG**, **INTP**, **UINTP** + + +Number of bits in data types +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +All :cdata:NPY_SIZEOF_{CTYPE} constants have corresponding +:cdata:NPY_BITSOF_{CTYPE} constants defined. The :cdata:NPY_BITSOF_{CTYPE} +constants provide the number of bits in the data type. Specifically, +the available {CTYPE}s are + + **BOOL**, **CHAR**, **SHORT**, **INT**, **LONG**, + **LONGLONG**, **FLOAT**, **DOUBLE**, **LONGDOUBLE** + + +Bit-width references to enumerated typenums +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +All of the numeric data types (integer, floating point, and complex) +have constants that are defined to be a specific enumerated type +number. Exactly which enumerated type a bit-width type refers to is +platform dependent. In particular, the constants available are +:cdata:PyArray_{NAME}{BITS} where {NAME} is **INT**, **UINT**, +**FLOAT**, **COMPLEX** and {BITS} can be 8, 16, 32, 64, 80, 96, 128, +160, 192, 256, and 512. Obviously not all bit-widths are available on +all platforms for all the kinds of numeric types. Commonly 8-, 16-, +32-, 64-bit integers; 32-, 64-bit floats; and 64-, 128-bit complex +types are available. + + +Integer that can hold a pointer +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The constants **PyArray_INTP** and **PyArray_UINTP** refer to an +enumerated integer type that is large enough to hold a pointer on the +platform. Index arrays should always be converted to **PyArray_INTP** +, because the dimension of the array is of type npy_intp. + + +C-type names +------------ + +There are standard variable types for each of the numeric data types +and the bool data type. Some of these are already available in the +C-specification. You can create variables in extension code with these +types. + + +Boolean +^^^^^^^ + +.. ctype:: npy_bool + + unsigned char; The constants :cdata:NPY_FALSE and + :cdata:NPY_TRUE are also defined. + + +(Un)Signed Integer +^^^^^^^^^^^^^^^^^^ + +Unsigned versions of the integers can be defined by pre-pending a 'u' +to the front of the integer name. + +.. ctype:: npy_(u)byte + + (unsigned) char + +.. ctype:: npy_(u)short + + (unsigned) short + +.. ctype:: npy_(u)int + + (unsigned) int + +.. ctype:: npy_(u)long + + (unsigned) long int + +.. ctype:: npy_(u)longlong + + (unsigned long long int) + +.. ctype:: npy_(u)intp + + (unsigned) Py_intptr_t (an integer that is the size of a pointer on + the platform). + + +(Complex) Floating point +^^^^^^^^^^^^^^^^^^^^^^^^ + +.. ctype:: npy_(c)float + + float + +.. ctype:: npy_(c)double + + double + +.. ctype:: npy_(c)longdouble + + long double + +complex types are structures with **.real** and **.imag** members (in +that order). + + +Bit-width names +^^^^^^^^^^^^^^^ + +There are also typedefs for signed integers, unsigned integers, +floating point, and complex floating point types of specific bit- +widths. The available type names are + + :ctype:npy_int{bits}, :ctype:npy_uint{bits}, :ctype:npy_float{bits}, + and :ctype:npy_complex{bits} + +where {bits} is the number of bits in the type and can be **8**, +**16**, **32**, **64**, 128, and 256 for integer types; 16, **32** +, **64**, 80, 96, 128, and 256 for floating-point types; and 32, +**64**, **128**, 160, 192, and 512 for complex-valued types. Which +bit-widths are available is platform dependent. The bolded bit-widths +are usually available on all platforms. + + +Printf Formatting +----------------- + +For help in printing, the following strings are defined as the correct +format specifier in printf and related commands. + + :cdata:NPY_LONGLONG_FMT, :cdata:NPY_ULONGLONG_FMT, + :cdata:NPY_INTP_FMT, :cdata:NPY_UINTP_FMT, + :cdata:NPY_LONGDOUBLE_FMT Added: numpy-docs/trunk/source/reference/c-api.rst =================================================================== --- numpy-docs/trunk/source/reference/c-api.rst 2008-10-26 17:50:36 UTC (rev 5958) +++ numpy-docs/trunk/source/reference/c-api.rst 2008-10-26 17:57:55 UTC (rev 5959) @@ -0,0 +1,47 @@ +.. _c-api: + +########### +Numpy C-API +########### + +.. sectionauthor:: Travis E. Oliphant + +| Beware of the man who won't be bothered with details. +| --- *William Feather, Sr.* + +| The truth is out there. +| --- *Chris Carter, The X Files* + + +NumPy provides a C-API to enable users to extend the system and get +access to the array object for use in other routines. The best way to +truly understand the C-API is to read the source code. If you are +unfamiliar with (C) source code, however, this can be a daunting +experience at first. Be assured that the task becomes easier with +practice, and you may be surprised at how simple the C-code can be to +understand. Even if you don't think you can write C-code from scratch, +it is much easier to understand and modify already-written source code +then create it *de novo*. + +Python extensions are especially straightforward to understand because +they all have a very similar structure. Admittedly, NumPy is not a +trivial extension to Python, and may take a little more snooping to +grasp. This is especially true because of the code-generation +techniques, which simplify maintenance of very similar code, but can +make the code a little less readable to beginners. Still, with a +little persistence, the code can be opened to your understanding. It +is my hope, that this guide to the C-API can assist in the process of +becoming familiar with the compiled-level work that can be done with +NumPy in order to squeeze that last bit of necessary speed out of your +code. + +.. currentmodule:: numpy-c-api + +.. toctree:: + :maxdepth: 2 + + c-api.types-and-structures + c-api.config + c-api.dtype + c-api.array + c-api.ufunc Added: numpy-docs/trunk/source/reference/c-api.types-and-structures.rst =================================================================== --- numpy-docs/trunk/source/reference/c-api.types-and-structures.rst 2008-10-26 17:50:36 UTC (rev 5958) +++ numpy-docs/trunk/source/reference/c-api.types-and-structures.rst 2008-10-26 17:57:55 UTC (rev 5959) @@ -0,0 +1,1173 @@ +***************************** +Python Types and C-Structures +***************************** + +.. sectionauthor:: Travis E. Oliphant + +Several new types are defined in the C-code. Most of these are +accessible from Python, but a few are not exposed due to their limited +use. Every new Python type has an associated :ctype:PyObject * with an +internal structure that includes a pointer to a "method table" that +defines how the new object behaves in Python. When you receive a +Python object into C code, you always get a pointer to a +:ctype:PyObject structure. Because a :ctype:PyObject structure is +very generic and defines only :cmacro:PyObject_HEAD, by itself it +is not very interesting. However, different objects contain more +details after the :cmacro:PyObject_HEAD (but you have to cast to the +correct type to access them --- or use accessor functions or macros). + + +New Python Types Defined +======================== + +Python types are the functional equivalent in C of classes in Python. +By constructing a new Python type you make available a new object for +Python. The ndarray object is an example of a new type defined in C. +New types are defined in C by two basic steps: + +1. creating a C-structure (usually named :ctype:Py{Name}Object) that is + binary- compatible with the :ctype:PyObject structure itself but holds + the additional information needed for that particular object; + +2. populating the :ctype:PyTypeObject table (pointed to by the ob_type + member of the :ctype:PyObject structure) with pointers to functions + that implement the desired behavior for the type. + +Instead of special method names which define behavior for Python +classes, there are "function tables" which point to functions that +implement the desired results. Since Python 2.2, the PyTypeObject +itself has become dynamic which allows C types that can be "sub-typed +"from other C-types in C, and sub-classed in Python. The children +types inherit the attributes and methods from their parent(s). + +There are two major new types: the ndarray ( :cdata:PyArray_Type ) +and the ufunc ( :cdata:PyUFunc_Type ). Additional types play a +supportive role: the :cdata:PyArrayIter_Type, the +:cdata:PyArrayMultiIter_Type, and the :cdata:PyArrayDescr_Type +. The :cdata:PyArrayIter_Type is the type for a flat iterator for an +ndarray (the object that is returned when getting the flat +attribute). The :cdata:PyArrayMultiIter_Type is the type of the +object returned when calling broadcast (). It handles iteration +and broadcasting over a collection of nested sequences. Also, the +:cdata:PyArrayDescr_Type is the data-type-descriptor type whose +instances describe the data. Finally, there are 21 new scalar-array +types which are new Python scalars corresponding to each of the +fundamental data types available for arrays. An additional 10 other +types are place holders that allow the array scalars to fit into a +hierarchy of actual Python types. + + +PyArray_Type +------------ + +.. cvar:: PyArray_Type + + The Python type of the ndarray is :cdata:PyArray_Type. In C, every + ndarray is a pointer to a :ctype:PyArrayObject structure. The ob_type + member of this structure contains a pointer to the :cdata:PyArray_Type + typeobject. + +.. ctype:: PyArrayObject + + The :ctype:PyArrayObject C-structure contains all of the required + information for an array. All instances of an ndarray (and its + subclasses) will have this structure. For future compatibility, + these structure members should normally be accessed using the + provided macros. If you need a shorter name, then you can make use + of :ctype:NPY_AO which is defined to be equivalent to + :ctype:PyArrayObject. + + .. code-block:: c + + typedef struct PyArrayObject { + PyObject_HEAD + char *data; + int nd; + npy_intp *dimensions; + npy_intp *strides; + PyObject *base; + PyArray_Descr *descr; + int flags; + PyObject *weakreflist; + } PyArrayObject; + +.. cmacro:: PyArrayObject.PyObject_HEAD + + This is needed by all Python objects. It consists of (at least) + a reference count member ( ob_refcnt ) and a pointer to the + typeobject ( ob_type ). (Other elements may also be present + if Python was compiled with special options see + Include/object.h in the Python source tree for more + information). The ob_type member points to a Python type + object. + +.. cmember:: char *PyArrayObject.data + + A pointer to the first element of the array. This pointer can + (and normally should) be recast to the data type of the array. + +.. cmember:: int PyArrayObject.nd + + An integer providing the number of dimensions for this + array. When nd is 0, the array is sometimes called a rank-0 + array. Such arrays have undefined dimensions and strides and + cannot be accessed. :cdata:NPY_MAXDIMS is the largest number of + dimensions for any array. + +.. cmember:: npy_intp PyArrayObject.dimensions + + An array of integers providing the shape in each dimension as + long as nd :math:\geq 1. The integer is always large enough + to hold a pointer on the platform, so the dimension size is + only limited by memory. + +.. cmember:: npy_intp *PyArrayObject.strides + + An array of integers providing for each dimension the number of + bytes that must be skipped to get to the next element in that + dimension. + +.. cmember:: PyObject *PyArrayObject.base + + This member is used to hold a pointer to another Python object + that is related to this array. There are two use cases: 1) If + this array does not own its own memory, then base points to the + Python object that owns it (perhaps another array object), 2) + If this array has the :cdata:NPY_UPDATEIFCOPY flag set, then this + array is a working copy of a "misbehaved" array. As soon as + this array is deleted, the array pointed to by base will be + updated with the contents of this array. + +.. cmember:: PyArray_Descr *PyArrayObject.descr + + A pointer to a data-type descriptor object (see below). The + data-type descriptor object is an instance of a new built-in + type which allows a generic description of memory. There is a + descriptor structure for each data type supported. This + descriptor structure contains useful information about the type + as well as a pointer to a table of function pointers to + implement specific functionality. + +.. cmember:: int PyArrayObject.flags + + Flags indicating how the memory pointed to by data is to be + interpreted. Possible flags are :cdata:NPY_C_CONTIGUOUS, + :cdata:NPY_F_CONTIGUOUS, :cdata:NPY_OWNDATA, :cdata:NPY_ALIGNED, + :cdata:NPY_WRITEABLE, and :cdata:NPY_UPDATEIFCOPY. + +.. cmember:: PyObject *PyArrayObject.weakreflist + + This member allows array objects to have weak references (using the + weakref module). + + +PyArrayDescr_Type +----------------- + +.. cvar:: PyArrayDescr_Type + + The :cdata:PyArrayDescr_Type is the built-in type of the + data-type-descriptor objects used to describe how the bytes comprising + the array are to be interpreted. There are 21 statically-defined + :ctype:PyArray_Descr objects for the built-in data-types. While these + participate in reference counting, their reference count should never + reach zero. There is also a dynamic table of user-defined + :ctype:PyArray_Descr objects that is also maintained. Once a + data-type-descriptor object is "registered" it should never be + deallocated either. The function :cfunc:PyArray_DescrFromType (...) can + be used to retrieve a :ctype:PyArray_Descr object from an enumerated + type-number (either built-in or user- defined). + +.. ctype:: PyArray_Descr + + The format of the :ctype:PyArray_Descr structure that lies at the + heart of the :cdata:PyArrayDescr_Type is + + .. code-block:: c + + typedef struct { + PyObject_HEAD + PyTypeObject *typeobj; + char kind; + char type; + char byteorder; + char hasobject; + int type_num; + int elsize; + int alignment; + PyArray_ArrayDescr *subarray; + PyObject *fields; + PyArray_ArrFuncs *f; + } PyArray_Descr; + +.. cmember:: PyTypeObject *PyArray_Descr.typeobj + + Pointer to a typeobject that is the corresponding Python type for + the elements of this array. For the builtin types, this points to + the corresponding array scalar. For user-defined types, this + should point to a user-defined typeobject. This typeobject can + either inherit from array scalars or not. If it does not inherit + from array scalars, then the :cdata:NPY_USE_GETITEM and + :cdata:NPY_USE_SETITEM flags should be set in the hasobject flag. + +.. cmember:: char PyArray_Descr.kind + + A character code indicating the kind of array (using the array + interface typestring notation). A 'b' represents Boolean, a 'i' + represents signed integer, a 'u' represents unsigned integer, 'f' + represents floating point, 'c' represents complex floating point, 'S' + represents 8-bit character string, 'U' represents 32-bit/character + unicode string, and 'V' repesents arbitrary. + +.. cmember:: char PyArray_Descr.type + + A traditional character code indicating the data type. + +.. cmember:: char PyArray_Descr.byteorder + + A character indicating the byte-order: '>' (big-endian), '<' (little- + endian), '=' (native), '\|' (irrelevant, ignore). All builtin data- + types have byteorder '='. + +.. cmember:: char PyArray_Descr.hasobject + + A data-type bit-flag that determines if the data-type exhibits object- + array like behavior. Each bit in this member is a flag which are named + as: + + .. cvar:: NPY_ITEM_REFCOUNT + + .. cvar:: NPY_ITEM_HASOBJECT + + Indicates that items of this data-type must be reference + counted (using :cfunc:Py_INCREF and :cfunc:Py_DECREF ). + + .. cvar:: NPY_ITEM_LISTPICKLE + + Indicates arrays of this data-type must be converted to a list + before pickling. + + .. cvar:: NPY_ITEM_IS_POINTER + + Indicates the item is a pointer to some other data-type + + .. cvar:: NPY_NEEDS_INIT + + Indicates memory for this data-type must be initialized (set + to 0) on creation. + + .. cvar:: NPY_NEEDS_PYAPI + + Indicates this data-type requires the Python C-API during + access (so don't give up the GIL if array access is going to + be needed). + + .. cvar:: NPY_USE_GETITEM + + On array access use the f->getitem function pointer + instead of the standard conversion to an array scalar. Must + use if you don't define an array scalar to go along with + the data-type. + + .. cvar:: NPY_USE_SETITEM + + When creating a 0-d array from an array scalar use + f->setitem instead of the standard copy from an array + scalar. Must use if you don't define an array scalar to go + along with the data-type. + + .. cvar:: NPY_FROM_FIELDS + + The bits that are inherited for the parent data-type if these + bits are set in any field of the data-type. Currently ( + :cdata:NPY_NEEDS_INIT \| :cdata:NPY_LIST_PICKLE \| + :cdata:NPY_ITEM_REFCOUNT \| :cdata:NPY_NEEDS_PYAPI ). + + .. cvar:: NPY_OBJECT_DTYPE_FLAGS + + Bits set for the object data-type: ( :cdata:NPY_LIST_PICKLE + \| :cdata:NPY_USE_GETITEM \| :cdata:NPY_ITEM_IS_POINTER \| + :cdata:NPY_REFCOUNT \| :cdata:NPY_NEEDS_INIT \| + :cdata:NPY_NEEDS_PYAPI). + + .. cfunction:: PyDataType_FLAGCHK(PyArray_Descr *dtype, int flags) + + Return true if all the given flags are set for the data-type + object. + + .. cfunction:: PyDataType_REFCHK(PyArray_Descr *dtype) + + Equivalent to :cfunc:PyDataType_FLAGCHK (*dtype*, + :cdata:NPY_ITEM_REFCOUNT). + +.. cmember:: int PyArray_Descr.type_num + + A number that uniquely identifies the data type. For new data-types, + this number is assigned when the data-type is registered. + +.. cmember:: int PyArray_Descr.elsize + + For data types that are always the same size (such as long), this + holds the size of the data type. For flexible data types where + different arrays can have a different elementsize, this should be + 0. + +.. cmember:: int PyArray_Descr.alignment + + A number providing alignment information for this data type. + Specifically, it shows how far from the start of a 2-element + structure (whose first element is a char ), the compiler + places an item of this type: offsetof(struct {char c; type v;}, + v) + +.. cmember:: PyArray_ArrayDescr *PyArray_Descr.subarray + + If this is non- NULL, then this data-type descriptor is a + C-style contiguous array of another data-type descriptor. In + other-words, each element that this descriptor describes is + actually an array of some other base descriptor. This is most + useful as the data-type descriptor for a field in another + data-type descriptor. The fields member should be NULL if this + is non- NULL (the fields member of the base descriptor can be + non- NULL however). The :ctype:PyArray_ArrayDescr structure is + defined using + + .. code-block:: c + + typedef struct { + PyArray_Descr *base; + PyObject *shape; + } PyArray_ArrayDescr; + + The elements of this structure are: + + .. cmember:: PyArray_Descr *PyArray_ArrayDescr.base + + The data-type-descriptor object of the base-type. + + .. cmember:: PyObject *PyArray_ArrayDescr.shape + + The shape (always C-style contiguous) of the sub-array as a Python + tuple. + + +.. cmember:: PyObject *PyArray_Descr.fields + + If this is non-NULL, then this data-type-descriptor has fields + described by a Python dictionary whose keys are names (and also + titles if given) and whose values are tuples that describe the + fields. Recall that a data-type-descriptor always describes a + fixed-length set of bytes. A field is a named sub-region of that + total, fixed-length collection. A field is described by a tuple + composed of another data- type-descriptor and a byte + offset. Optionally, the tuple may contain a title which is + normally a Python string. These tuples are placed in this + dictionary keyed by name (and also title if given). + +.. cmember:: PyArray_ArrFuncs *PyArray_Descr.f + + A pointer to a structure containing functions that the type needs + to implement internal features. These functions are not the same + thing as the universal functions (ufuncs) described later. Their + signatures can vary arbitrarily. + +.. ctype:: PyArray_ArrFuncs + + Functions implementing internal features. Not all of these + function pointers must be defined for a given type. The required + members are nonzero, copyswap, copyswapn, setitem, + getitem, and cast. These are assumed to be non- NULL + and NULL entries will cause a program crash. The other + functions may be NULL which will just mean reduced + functionality for that data-type. (Also, the nonzero function will + be filled in with a default function if it is NULL when you + register a user-defined data-type). + + .. code-block:: c + + typedef struct { + PyArray_VectorUnaryFunc *cast[PyArray_NTYPES]; + PyArray_GetItemFunc *getitem; + PyArray_SetItemFunc *setitem; + PyArray_CopySwapNFunc *copyswapn; + PyArray_CopySwapFunc *copyswap; + PyArray_CompareFunc *compare; + PyArray_ArgFunc *argmax; + PyArray_DotFunc *dotfunc; + PyArray_ScanFunc *scanfunc; + PyArray_FromStrFunc *fromstr; + PyArray_NonzeroFunc *nonzero; + PyArray_FillFunc *fill; + PyArray_FillWithScalarFunc *fillwithscalar; + PyArray_SortFunc *sort[PyArray_NSORTS]; + PyArray_ArgSortFunc *argsort[PyArray_NSORTS]; + PyObject *castdict; + PyArray_ScalarKindFunc *scalarkind; + int **cancastscalarkindto; + int *cancastto; + int listpickle + } PyArray_ArrFuncs; + + The concept of a behaved segment is used in the description of the + function pointers. A behaved segment is one that is aligned and in + native machine byte-order for the data-type. The nonzero, + copyswap, copyswapn, getitem, and setitem + functions can (and must) deal with mis-behaved arrays. The other + functions require behaved memory segments. + + .. cmember:: void cast(void *from, void *to, npy_intp n, void *fromarr, void *toarr) + + An array of function pointers to cast from the current type to + all of the other builtin types. Each function casts a + contiguous, aligned, and notswapped buffer pointed at by + *from* to a contiguous, aligned, and notswapped buffer pointed + at by *to* The number of items to cast is given by *n*, and + the arguments *fromarr* and *toarr* are interpreted as + PyArrayObjects for flexible arrays to get itemsize + information. + + .. cmember:: PyObject *getitem(void *data, void *arr) + + A pointer to a function that returns a standard Python object + from a single element of the array object *arr* pointed to by + *data*. This function must be able to deal with "misbehaved + "(misaligned and/or swapped) arrays correctly. + + .. cmember:: int setitem(PyObject *item, void *data, void *arr) + + A pointer to a function that sets the Python object *item* + into the array, *arr*, at the position pointed to by *data* + . This function deals with "misbehaved" arrays. If successful, + a zero is returned, otherwise, a negative one is returned (and + a Python error set). + + .. cmember:: void copyswapn(void *dest, npy_intp dstride, void *src, npy_intp sstride, npy_intp n, int swap, void *arr) + + .. cmember:: void copyswap(void *dest, void *src, int swap, void *arr) + + These members are both pointers to functions to copy data from + *src* to *dest* and *swap* if indicated. The value of arr is + only used for flexible ( :cdata:NPY_STRING, :cdata:NPY_UNICODE, + and :cdata:NPY_VOID ) arrays (and is obtained from + arr->descr->elsize ). The second function copies a single + value, while the first loops over n values with the provided + strides. These functions can deal with misbehaved *src* + data. If *src* is NULL then no copy is performed. If *swap* is + 0, then no byteswapping occurs. It is assumed that *dest* and + *src* do not overlap. If they overlap, then use memmove + (...) first followed by copyswap(n) with NULL valued + src. + + .. cmember:: int compare(const void* d1, const void* d2, void* arr) + + A pointer to a function that compares two elements of the + array, arr, pointed to by d1 and d2. This + function requires behaved arrays. The return value is 1 if * + d1 > * d2, 0 if * d1 == * d2, and -1 if * + d1 < * d2. The array object arr is used to retrieve + itemsize and field information for flexible arrays. + + .. cmember:: int argmax(void* data, npy_intp n, npy_intp* max_ind, void* arr) + + A pointer to a function that retrieves the index of the + largest of n elements in arr beginning at the element + pointed to by data. This function requires that the + memory segment be contiguous and behaved. The return value is + always 0. The index of the largest element is returned in + max_ind. + + .. cmember:: void dotfunc(void* ip1, npy_intp is1, void* ip2, npy_intp is2, void* op, npy_intp n, void* arr) + + A pointer to a function that multiplies two n -length + sequences together, adds them, and places the result in + element pointed to by op of arr. The start of the two + sequences are pointed to by ip1 and ip2. To get to + the next element in each sequence requires a jump of is1 + and is2 *bytes*, respectively. This function requires + behaved (though not necessarily contiguous) memory. + + .. cmember:: int scanfunc(FILE* fd, void* ip , void* sep , void* arr) + + A pointer to a function that scans (scanf style) one element + of the corresponding type from the file descriptor fd into + the array memory pointed to by ip. The array is assumed + to be behaved. If sep is not NULL, then a separator string + is also scanned from the file before returning. The last + argument arr is the array to be scanned into. A 0 is + returned if the scan is successful. A negative number + indicates something went wrong: -1 means the end of file was + reached before the separator string could be scanned, -4 means + that the end of file was reached before the element could be + scanned, and -3 means that the element could not be + interpreted from the format string. Requires a behaved array. + + .. cmember:: int fromstr(char* str, void* ip, char** endptr, void* arr) + + A pointer to a function that converts the string pointed to by + str to one element of the corresponding type and places it + in the memory location pointed to by ip. After the + conversion is completed, *endptr points to the rest of the + string. The last argument arr is the array into which ip + points (needed for variable-size data- types). Returns 0 on + success or -1 on failure. Requires a behaved array. + + .. cmember:: Bool nonzero(void* data, void* arr) + + A pointer to a function that returns TRUE if the item of + arr pointed to by data is nonzero. This function can + deal with misbehaved arrays. + + .. cmember:: void fill(void* data, npy_intp length, void* arr) + + A pointer to a function that fills a contiguous array of given + length with data. The first two elements of the array must + already be filled- in. From these two values, a delta will be + computed and the values from item 3 to the end will be + computed by repeatedly adding this computed delta. The data + buffer must be well-behaved. + + .. cmember:: void fillwithscalar(void* buffer, npy_intp length, void* value, void* arr) + + A pointer to a function that fills a contiguous buffer of + the given length with a single scalar value whose + address is given. The final argument is the array which is + needed to get the itemsize for variable-length arrays. + + .. cmember:: int sort(void* start, npy_intp length, void* arr) + + An array of function pointers to a particular sorting + algorithms. A particular sorting algorithm is obtained using a + key (so far :cdata:PyArray_QUICKSORT, :dataPyArray_HEAPSORT, and + :cdata:PyArray_MERGESORT are defined). These sorts are done + in-place assuming contiguous and aligned data. + + .. cmember:: int argsort(void* start, npy_intp* result, npy_intp length, void \*arr) + + An array of function pointers to sorting algorithms for this + data type. The same sorting algorithms as for sort are + available. The indices producing the sort are returned in + result (which must be initialized with indices 0 to length-1 + inclusive). + + .. cmember:: PyObject *castdict + + Either NULL or a dictionary containing low-level casting + functions for user- defined data-types. Each function is + wrapped in a :ctype:PyCObject * and keyed by the data-type number. + + .. cmember:: PyArray_SCALARKIND scalarkind(PyArrayObject* arr) + + A function to determine how scalars of this type should be + interpreted. The argument is NULL or a 0-dimensional array + containing the data (if that is needed to determine the kind + of scalar). The return value must be of type + :ctype:PyArray_SCALARKIND. + + .. cmember:: int **cancastscalarkindto + + Either NULL or an array of :ctype:PyArray_NSCALARKINDS + pointers. These pointers should each be either NULL or a + pointer to an array of integers (terminated by + :cdata:PyArray_NOTYPE) indicating data-types that a scalar of + this data-type of the specified kind can be cast to safely + (this usually means without losing precision). + + .. cmember:: int *cancastto + + Either NULL or an array of integers (terminated by + :cdata:PyArray_NOTYPE ) indicated data-types that this data-type + can be cast to safely (this usually means without losing + precision). + + .. cmember:: int listpickle + + Unused. + +The :cdata:PyArray_Type typeobject implements many of the features of +Python objects including the tp_as_number, tp_as_sequence, +tp_as_mapping, and tp_as_buffer interfaces. The rich comparison +(tp_richcompare) is also used along with new-style attribute lookup +for methods (tp_methods) and properties (tp_getset). The +:cdata:PyArray_Type can also be sub-typed. + +.. tip:: + + The tp_as_number methods use a generic approach to call whatever + function has been registered for handling the operation. The + function PyNumeric_SetOps(..) can be used to register functions to + handle particular mathematical operations (for all arrays). When + the umath module is imported, it sets the numeric operations for + all arrays to the corresponding ufuncs. The tp_str and tp_repr + methods can also be altered using PyString_SetStringFunction(...). + + +PyUFunc_Type +------------ + +.. cvar:: PyUFunc_Type + + The ufunc object is implemented by creation of the + :cdata:PyUFunc_Type. It is a very simple type that implements only + basic getattribute behavior, printing behavior, and has call + behavior which allows these objects to act like functions. The + basic idea behind the ufunc is to hold a reference to fast + 1-dimensional (vector) loops for each data type that supports the + operation. These one-dimensional loops all have the same signature + and are the key to creating a new ufunc. They are called by the + generic looping code as appropriate to implement the N-dimensional + function. There are also some generic 1-d loops defined for + floating and complexfloating arrays that allow you to define a + ufunc using a single scalar function (*e.g.* atanh). + + +.. ctype:: PyUFuncObject + + The core of the ufunc is the :ctype:PyUFuncObject which contains all + the information needed to call the underlying C-code loops that + perform the actual work. It has the following structure: + + .. code-block:: c + + typedef struct { + PyObject_HEAD + int nin; + int nout; + int nargs; + int identity; + PyUFuncGenericFunction *functions; + void **data; + int ntypes; + int check_return; + char *name; + char *types; + char *doc; + void *ptr; + PyObject *obj; + PyObject *userloops; + } PyUFuncObject; + + .. cmacro:: PyUFuncObject.PyObject_HEAD + + required for all Python objects. + + .. cmember:: int PyUFuncObject.nin + + The number of input arguments. + + .. cmember:: int PyUFuncObject.nout + + The number of output arguments. + + .. cmember:: int PyUFuncObject.nargs + + The total number of arguments (*nin* + *nout*). This must be + less than :cdata:NPY_MAXARGS. + + .. cmember:: int PyUFuncObject.identity + + Either :cdata:PyUFunc_One, :cdata:PyUFunc_Zero, or :cdata:PyUFunc_None + to indicate the identity for this operation. It is only used + for a reduce-like call on an empty array. + + .. cmember:: void PyUFuncObject.functions(char** args, npy_intp* dims, npy_intp* steps, void* extradata) + + An array of function pointers --- one for each data type + supported by the ufunc. This is the vector loop that is called + to implement the underlying function *dims* [0] times. The + first argument, *args*, is an array of *nargs* pointers to + behaved memory. Pointers to the data for the input arguments + are first, followed by the pointers to the data for the output + arguments. How many bytes must be skipped to get to the next + element in the sequence is specified by the corresponding entry + in the *steps* array. The last argument allows the loop to + receive extra information. This is commonly used so that a + single, generic vector loop can be used for multiple + functions. In this case, the actual scalar function to call is + passed in as *extradata*. The size of this function pointer + array is ntypes. + + .. cmember:: void **PyUFuncObject.data + + Extra data to be passed to the 1-d vector loops or NULL if + no extra-data is needed. This C-array must be the same size ( + *i.e.* ntypes) as the functions array. NULL is used if + extra_data is not needed. Several C-API calls for UFuncs are + just 1-d vector loops that make use of this extra data to + receive a pointer to the actual function to call. + + .. cmember:: int PyUFuncObject.ntypes + + The number of supported data types for the ufunc. This number + specifies how many different 1-d loops (of the builtin data types) are + available. + + .. cmember:: int PyUFuncObject.check_return + + Obsolete and unused. However, it is set by the corresponding entry in + the main ufunc creation routine: :cfunc:PyUFunc_FromFuncAndData (...). + + .. cmember:: char *PyUFuncObject.name + + A string name for the ufunc. This is used dynamically to build + the __doc\__ attribute of ufuncs. + + .. cmember:: char *PyUFuncObject.types + + An array of *nargs* :math:\times *ntypes* 8-bit type_numbers + which contains the type signature for the function for each of + the supported (builtin) data types. For each of the *ntypes* + functions, the corresponding set of type numbers in this array + shows how the *args* argument should be interpreted in the 1-d + vector loop. These type numbers do not have to be the same type + and mixed-type ufuncs are supported. + + .. cmember:: char *PyUFuncObject.doc + + Documentation for the ufunc. Should not contain the function + signature as this is generated dynamically when __doc\__ is + retrieved. + + .. cmember:: void *PyUFuncObject.ptr + + Any dynamically allocated memory. Currently, this is used for dynamic + ufuncs created from a python function to store room for the types, + data, and name members. + + .. cmember:: PyObject *PyUFuncObject.obj + + For ufuncs dynamically created from python functions, this member + holds a reference to the underlying Python function. + + .. cmember:: PyObject *PyUFuncObject.userloops + + A dictionary of user-defined 1-d vector loops (stored as CObject ptrs) + for user-defined types. A loop may be registered by the user for any + user-defined type. It is retrieved by type number. User defined type + numbers are always larger than :cdata:NPY_USERDEF. + + +PyArrayIter_Type +---------------- + +.. cvar:: PyArrayIter_Type + + This is an iterator object that makes it easy to loop over an N-dimensional + array. It is the object returned from the flat attribute of an + ndarray. It is also used extensively throughout the implementation + internals to loop over an N-dimensional array. The tp_as_mapping + interface is implemented so that the iterator object can be indexed + (using 1-d indexing), and a few methods are implemented through the + tp_methods table. This object implements the next method and can be + used anywhere an iterator can be used in Python. + +.. ctype:: PyArrayIterObject + + The C-structure corresponding to an object of :cdata:PyArrayIter_Type is + the :ctype:PyArrayIterObject. The :ctype:PyArrayIterObject is used to keep + track of a pointer into an N-dimensional array. It contains associated + information used to quickly march through the array. The pointer can + be adjusted in three basic ways: 1) advance to the "next" position in + the array in a C-style contiguous fashion, 2) advance to an arbitrary + N-dimensional coordinate in the array, and 3) advance to an arbitrary + one-dimensional index into the array. The members of the + :ctype:PyArrayIterObject structure are used in these + calculations. Iterator objects keep their own dimension and strides + information about an array. This can be adjusted as needed for + "broadcasting," or to loop over only specific dimensions. + + .. code-block:: c + + typedef struct { + PyObject_HEAD + int nd_m1; + npy_intp index; + npy_intp size; + npy_intp coordinates[NPY_MAXDIMS]; + npy_intp dims_m1[NPY_MAXDIMS]; + npy_intp strides[NPY_MAXDIMS]; + npy_intp backstrides[NPY_MAXDIMS]; + npy_intp factors[NPY_MAXDIMS]; + PyArrayObject *ao; + char *dataptr; + Bool contiguous; + } PyArrayIterObject; + + .. cmember:: int PyArrayIterObject.nd_m1 + + :math:N-1 where :math:N is the number of dimensions in the + underlying array. + + .. cmember:: npy_intp PyArrayIterObject.index + + The current 1-d index into the array. + + .. cmember:: npy_intp PyArrayIterObject.size + + The total size of the underlying array. + + .. cmember:: npy_intp *PyArrayIterObject.coordinates + + An :math:N -dimensional index into the array. + + .. cmember:: npy_intp *PyArrayIterObject.dims_m1 + + The size of the array minus 1 in each dimension. + + .. cmember:: npy_intp *PyArrayIterObject.strides + + The strides of the array. How many bytes needed to jump to the next + element in each dimension. + + .. cmember:: npy_intp *PyArrayIterObject.backstrides + + How many bytes needed to jump from the end of a dimension back + to its beginning. Note that *backstrides* [k]= *strides* [k]*d + *ims_m1* [k], but it is stored here as an optimization. + + .. cmember:: npy_intp *PyArrayIterObject.factors + + This array is used in computing an N-d index from a 1-d index. It + contains needed products of the dimensions. + + .. cmember:: PyArrayObject *PyArrayIterObject.ao + + A pointer to the underlying ndarray this iterator was created to + represent. + + .. cmember:: char *PyArrayIterObject.dataptr + + This member points to an element in the ndarray indicated by the + index. + + .. cmember:: Bool PyArrayIterObject.contiguous + + This flag is true if the underlying array is + :cdata:NPY_C_CONTIGUOUS. It is used to simplify calculations when + possible. + + +How to use an array iterator on a C-level is explained more fully in +later sections. Typically, you do not need to concern yourself with +the internal structure of the iterator object, and merely interact +with it through the use of the macros :cfunc:PyArray_ITER_NEXT (it), +:cfunc:PyArray_ITER_GOTO (it, dest), or :cfunc:PyArray_ITER_GOTO1D (it, +index). All of these macros require the argument *it* to be a +:ctype:PyArrayIterObject *. + + +PyArrayMultiIter_Type +--------------------- + +.. cvar:: PyArrayMultiIter_Type + + This type provides an iterator that encapsulates the concept of + broadcasting. It allows :math:N arrays to be broadcast together + so that the loop progresses in C-style contiguous fashion over the + broadcasted array. The corresponding C-structure is the + :ctype:PyArrayMultiIterObject whose memory layout must begin any + object, *obj*, passed in to the :cfunc:PyArray_Broadcast (obj) + function. Broadcasting is performed by adjusting array iterators so + that each iterator represents the broadcasted shape and size, but + has its strides adjusted so that the correct element from the array + is used at each iteration. + + +.. ctype:: PyArrayMultiIterObject + + .. code-block:: c + + typedef struct { + PyObject_HEAD + int numiter; + npy_intp size; + npy_intp index; + int nd; + npy_intp dimensions[NPY_MAXDIMS]; + PyArrayIterObject *iters[NPY_MAXDIMS]; + } PyArrayMultiIterObject; + + .. cmacro:: PyArrayMultiIterObject.PyObject_HEAD + + Needed at the start of every Python object (holds reference count and + type identification). + + .. cmember:: int PyArrayMultiIterObject.numiter + + The number of arrays that need to be broadcast to the same shape. + + .. cmember:: npy_intp PyArrayMultiIterObject.size + + The total broadcasted size. + + .. cmember:: npy_intp PyArrayMultiIterObject.index + + The current (1-d) index into the broadcasted result. + + .. cmember:: int PyArrayMultiIterObject.nd + + The number of dimensions in the broadcasted result. + + .. cmember:: npy_intp *PyArrayMultiIterObject.dimensions + + The shape of the broadcasted result (only nd slots are used). + + .. cmember:: PyArrayIterObject **PyArrayMultiIterObject.iters + + An array of iterator objects that holds the iterators for the arrays + to be broadcast together. On return, the iterators are adjusted for + broadcasting. + + +PyArrayFlags_Type +----------------- + +.. cvar:: PyArrayFlags_Type + + When the flags attribute is retrieved from Python, a special + builtin object of this type is constructed. This special type makes + it easier to work with the different flags by accessing them as + attributes or by accessing them as if the object were a dictionary + with the flag names as entries. + + +ScalarArrayTypes +---------------- + +There is a Python type for each of the different built-in data types +that can be present in the array Most of these are simple wrappers +around the corresponding data type in C. The C-names for these types +are :cdata:Py{TYPE}ArrType_Type where {TYPE} can be + + **Bool**, **Byte**, **Short**, **Int**, **Long**, **LongLong**, + **UByte**, **UShort**, **UInt**, **ULong**, **ULongLong**, + **Float**, **Double**, **LongDouble**, **CFloat**, **CDouble**, + **CLongDouble**, **String**, **Unicode**, **Void**, and + **Object**. + +These type names are part of the C-API and can therefore be created in +extension C-code. There is also a :cdata:PyIntpArrType_Type and a +:cdata:PyUIntpArrType_Type that are simple substitutes for one of the +integer types that can hold a pointer on the platform. The structure +of these scalar objects is not exposed to C-code. The function +:cfunc:PyArray_ScalarAsCtype (..) can be used to extract the C-type value +from the array scalar and the function :cfunc:PyArray_Scalar (...) can be +used to construct an array scalar from a C-value. + + +Other C-Structures +================== + +A few new C-structures were found to be useful in the development of +NumPy. These C-structures are used in at least one C-API call and are +therefore documented here. The main reason these structures were +defined is to make it easy to use the Python ParseTuple C-API to +convert from Python objects to a useful C-Object. + + +PyArray_Dims +------------ + +.. ctype:: PyArray_Dims + + This structure is very useful when shape and/or strides information is + supposed to be interpreted. The structure is: + + .. code-block:: c + + typedef struct { + npy_intp *ptr; + int len; + } PyArray_Dims; + + The members of this structure are + + .. cmember:: npy_intp *PyArray_Dims.ptr + + A pointer to a list of (:ctype:npy_intp) integers which usually + represent array shape or array strides. + + .. cmember:: int PyArray_Dims.len + + The length of the list of integers. It is assumed safe to + access *ptr* [0] to *ptr* [len-1]. + + +PyArray_Chunk +------------- + +.. ctype:: PyArray_Chunk + + This is equivalent to the buffer object structure in Python up to + the ptr member. On 32-bit platforms (*i.e.* if :cdata:NPY_SIZEOF_INT + == :cdata:NPY_SIZEOF_INTP ) or in Python 2.5, the len member also + matches an equivalent member of the buffer object. It is useful to + represent a generic single- segment chunk of memory. + + .. code-block:: c + + typedef struct { + PyObject_HEAD + PyObject *base; + void *ptr; + npy_intp len; + int flags; + } PyArray_Chunk; + + The members are + + .. cmacro:: PyArray_Chunk.PyObject_HEAD + + Necessary for all Python objects. Included here so that the + :ctype:PyArray_Chunk structure matches that of the buffer object + (at least to the len member). + + .. cmember:: PyObject *PyArray_Chunk.base + + The Python object this chunk of memory comes from. Needed so that + memory can be accounted for properly. + + .. cmember:: void *PyArray_Chunk.ptr + + A pointer to the start of the single-segment chunk of memory. + + .. cmember:: npy_intp PyArray_Chunk.len + + The length of the segment in bytes. + + .. cmember:: int PyArray_Chunk.flags + + Any data flags (*e.g.* :cdata:NPY_WRITEABLE ) that should be used + to interpret the memory. + + +PyArrayInterface +---------------- + +.. seealso:: :ref:arrays.interface + +.. ctype:: PyArrayInterface + + The :ctype:PyArrayInterface structure is defined so that NumPy and + other extension modules can use the rapid array interface + protocol. The :obj:__array_struct__ method of an object that + supports the rapid array interface protocol should return a + :ctype:PyCObject that contains a pointer to a :ctype:PyArrayInterface + structure with the relevant details of the array. After the new + array is created, the attribute should be DECREF'd which will + free the :ctype:PyArrayInterface structure. Remember to INCREF the + object (whose :obj:__array_struct__ attribute was retrieved) and + point the base member of the new :ctype:PyArrayObject to this same + object. In this way the memory for the array will be managed + correctly. + + .. code-block:: c + + typedef struct { + int two; + int nd; + char typekind; + int itemsize; + int flags; + npy_intp *shape; + npy_intp *strides; + void *data; + PyObject *descr; + } PyArrayInterface; + + .. cmember:: int PyArrayInterface.two + + the integer 2 as a sanity check. + + .. cmember:: int PyArrayInterface.nd + + the number of dimensions in the array. + + .. cmember:: char PyArrayInterface.typekind + + A character indicating what kind of array is present according to the + typestring convention with 't' -> bitfield, 'b' -> Boolean, 'i' -> + signed integer, 'u' -> unsigned integer, 'f' -> floating point, 'c' -> + complex floating point, 'O' -> object, 'S' -> string, 'U' -> unicode, + 'V' -> void. + + .. cmember:: int PyArrayInterface.itemsize + + The number of bytes each item in the array requires. + + .. cmember:: int PyArrayInterface.flags + + Any of the bits :cdata:NPY_C_CONTIGUOUS (1), + :cdata:NPY_F_CONTIGUOUS (2), :cdata:NPY_ALIGNED (0x100), + :cdata:NPY_NOTSWAPPED (0x200), or :cdata:NPY_WRITEABLE + (0x400) to indicate something about the data. The + :cdata:NPY_ALIGNED, :cdata:NPY_C_CONTIGUOUS, and + :cdata:NPY_F_CONTIGUOUS flags can actually be determined from + the other parameters. The flag :cdata:NPY_ARR_HAS_DESCR + (0x800) can also be set to indicate to objects consuming the + version 3 array interface that the descr member of the + structure is present (it will be ignored by objects consuming + version 2 of the array interface). + + .. cmember:: npy_intp *PyArrayInterface.shape + + An array containing the size of the array in each dimension. + + .. cmember:: npy_intp *PyArrayInterface.strides + + An array containing the number of bytes to jump to get to the next + element in each dimension. + + .. cmember:: void *PyArrayInterface.data + + A pointer *to* the first element of the array. + + .. cmember:: PyObject *PyArrayInterface.descr + + A Python object describing the data-type in more detail (same + as the *descr* key in :obj:__array_interface__). This can be + NULL if *typekind* and *itemsize* provide enough + information. This field is also ignored unless + :cdata:ARR_HAS_DESCR flag is on in *flags*. + + +Internally used structures +-------------------------- + +Internally, the code uses some additional Python objects primarily for +memory management. These types are not accessible directly from +Python, and are not exposed to the C-API. They are included here only +for completeness and assistance in understanding the code. + + +.. ctype:: PyUFuncLoopObject + + A loose wrapper for a C-structure that contains the information + needed for looping. This is useful if you are trying to understand + the ufunc looping code. The :ctype:PyUFuncLoopObject is the associated + C-structure. It is defined in the ufuncobject.h header. + +.. ctype:: PyUFuncReduceObject + + A loose wrapper for the C-structure that contains the information + needed for reduce-like methods of ufuncs. This is useful if you are + trying to understand the reduce, accumulate, and reduce-at + code. The :ctype:PyUFuncReduceObject is the associated C-structure. It + is defined in the ufuncobject.h header. + +.. ctype:: PyUFunc_Loop1d + + A simple linked-list of C-structures containing the information needed + to define a 1-d loop for a ufunc for every defined signature of a + user-defined data-type. + +.. cvar:: PyArrayMapIter_Type + + Advanced indexing is handled with this Python type. It is simply a + loose wrapper around the C-structure containing the variables + needed for advanced array indexing. The associated C-structure, + :ctype:PyArrayMapIterObject, is useful if you are trying to + understand the advanced-index mapping code. It is defined in the + arrayobject.h header. This type is not exposed to Python and + could be replaced with a C-structure. As a Python type it takes + advantage of reference- counted memory management. + Added: numpy-docs/trunk/source/reference/c-api.ufunc.rst =================================================================== --- numpy-docs/trunk/source/reference/c-api.ufunc.rst 2008-10-26 17:50:36 UTC (rev 5958) +++ numpy-docs/trunk/source/reference/c-api.ufunc.rst 2008-10-26 17:57:55 UTC (rev 5959) @@ -0,0 +1,335 @@ +UFunc API +========= + +.. sectionauthor:: Travis E. Oliphant + +.. index:: + pair: ufunc; C-API + + +Constants +--------- + +.. cvar:: UFUNC_ERR_{HANDLER} + + {HANDLER} can be **IGNORE**, **WARN**, **RAISE**, or **CALL** + +.. cvar:: UFUNC_{THING}_{ERR} + + {THING} can be **MASK**, **SHIFT**, or **FPE**, and {ERR} can + be **DIVIDEBYZERO**, **OVERFLOW**, **UNDERFLOW**, and **INVALID**. + +.. cvar:: PyUFunc_{VALUE} + + {VALUE} can be **One** (1), **Zero** (0), or **None** (-1) + + +Macros +------ + +.. cmacro:: NPY_LOOP_BEGIN_THREADS + + Used in universal function code to only release the Python GIL if + loop->obj is not true (*i.e.* this is not an OBJECT array + loop). Requires use of :cmacro:NPY_BEGIN_THREADS_DEF in variable + declaration area. + +.. cmacro:: NPY_LOOP_END_THREADS + + Used in universal function code to re-acquire the Python GIL if it + was released (because loop->obj was not true). + +.. cfunction:: UFUNC_CHECK_ERROR(loop) + + A macro used internally to check for errors and goto fail if + found. This macro requires a fail label in the current code + block. The *loop* variable must have at least members (obj, + errormask, and errorobj). If *loop* ->obj is nonzero, then + :cfunc:PyErr_Occurred () is called (meaning the GIL must be held). If + *loop* ->obj is zero, then if *loop* ->errormask is nonzero, + :cfunc:PyUFunc_checkfperr is called with arguments *loop* ->errormask + and *loop* ->errobj. If the result of this check of the IEEE + floating point registers is true then the code redirects to the + fail label which must be defined. + +.. cfunction:: UFUNC_CHECK_STATUS(ret) + + A macro that expands to platform-dependent code. The *ret* + variable can can be any integer. The :cdata:UFUNC_FPE_{ERR} bits are + set in *ret* according to the status of the corresponding error + flags of the floating point processor. + + +Functions +--------- + +.. cfunction:: PyObject* PyUFunc_FromFuncAndData(PyUFuncGenericFunction* func, void** data, char* types, int ntypes, int nin, int nout, int identity, char* name, char* doc, int check_return) + + Create a new broadcasting universal function from required variables. + Each ufunc builds around the notion of an element-by-element + operation. Each ufunc object contains pointers to 1-d loops + implementing the basic functionality for each supported type. + + :param nin: + + The number of inputs to this operation. + + :param nout: + + The number of outputs + + :param ntypes: + + How many different data-type "signatures" the ufunc has implemented. + + :param func: + + Must to an array of length *ntypes* containing + :ctype:PyUFuncGenericFunction items. These items are pointers to + functions that acutally implement the underlying + (element-by-element) function :math:N times. T + + :param types: + + Must be of length (*nin* + *nout*) \* *ntypes*, and it + contains the data-types (built-in only) that the corresponding + function in the *func* array can deal with. + + :param data: + + Should be NULL or a pointer to an array of size *ntypes* + . This array may contain arbitrary extra-data to be passed to + the corresponding 1-d loop function in the func array. + + :param name: + + The name for the ufunc. + + :param doc: + + Allows passing in a documentation string to be stored with the + ufunc. The documentation string should not contain the name + of the function or the calling signature as that will be + dynamically determined from the object and available when + accessing the **__doc__** attribute of the ufunc. + + :param check_return: + + Unused and present for backwards compatibility of the C-API. A + corresponding *check_return* integer does exist in the ufunc + structure and it does get set with this value when the ufunc + object is created. + +.. cfunction:: int PyUFunc_RegisterLoopForType(PyUFuncObject* ufunc, int usertype, PyUFuncGenericFunction function, int* arg_types, void* data) + + This function allows the user to register a 1-d loop with an + already- created ufunc to be used whenever the ufunc is called + with any of its input arguments as the user-defined + data-type. This is needed in order to make ufuncs work with + built-in data-types. The data-type must have been previously + registered with the numpy system. The loop is passed in as + *function*. This loop can take arbitrary data which should be + passed in as *data*. The data-types the loop requires are passed + in as *arg_types* which must be a pointer to memory at least as + large as ufunc->nargs. + +.. cfunction:: int PyUFunc_ReplaceLoopBySignature(PyUFuncObject* ufunc, PyUFuncGenericFunction newfunc, int* signature, PyUFuncGenericFunction* oldfunc) + + Replace a 1-d loop matching the given *signature* in the + already-created *ufunc* with the new 1-d loop newfunc. Return the + old 1-d loop function in *oldfunc*. Return 0 on success and -1 on + failure. This function works only with built-in types (use + :cfunc:PyUFunc_RegisterLoopForType for user-defined types). A + signature is an array of data-type numbers indicating the inputs + followed by the outputs assumed by the 1-d loop. + +.. cfunction:: int PyUFunc_GenericFunction(PyUFuncObject* self, PyObject* args, PyArrayObject** mps) + + A generic ufunc call. The ufunc is passed in as *self*, the + arguments to the ufunc as *args*. The *mps* argument is an array + of :ctype:PyArrayObject pointers containing the converted input + arguments as well as the ufunc outputs on return. The user is + responsible for managing this array and receives a new reference + for each array in *mps*. The total number of arrays in *mps* is + given by *self* ->nin + *self* ->nout. + +.. cfunction:: int PyUFunc_checkfperr(int errmask, PyObject* errobj) + + A simple interface to the IEEE error-flag checking support. The + *errmask* argument is a mask of :cdata:UFUNC_MASK_{ERR} bitmasks + indicating which errors to check for (and how to check for + them). The *errobj* must be a Python tuple with two elements: a + string containing the name which will be used in any communication + of error and either a callable Python object (call-back function) + or :cdata:Py_None. The callable object will only be used if + :cdata:UFUNC_ERR_CALL is set as the desired error checking + method. This routine manages the GIL and is safe to call even + after releasing the GIL. If an error in the IEEE-compatibile + hardware is determined a -1 is returned, otherwise a 0 is + returned. + +.. cfunction:: void PyUFunc_clearfperr() + + Clear the IEEE error flags. + +.. cfunction:: void PyUFunc_GetPyValues(char* name, int* bufsize, int* errmask, PyObject** errobj) + + Get the Python values used for ufunc processing from the + thread-local storage area unless the defaults have been set in + which case the name lookup is bypassed. The name is placed as a + string in the first element of *\*errobj*. The second element is + the looked-up function to call on error callback. The value of the + looked-up buffer-size to use is passed into *bufsize*, and the + value of the error mask is placed into *errmask*. + + +Generic functions +----------------- + +At the core of every ufunc is a collection of type-specific functions +that defines the basic functionality for each of the supported types. +These functions must evaluate the underlying function :math:N\geq1 +times. Extra-data may be passed in that may be used during the +calculation. This feature allows some general functions to be used as +these basic looping functions. The general function has all the code +needed to point variables to the right place and set up a function +call. The general function assumes that the actual function to call is +passed in as the extra data and calls it with the correct values. All +of these functions are suitable for placing directly in the array of +functions stored in the functions member of the PyUFuncObject +structure. + +.. cfunction:: void PyUFunc_f_f_As_d_d(char** args, npy_intp* dimensions, npy_intp* steps, void* func) + +.. cfunction:: void PyUFunc_d_d(char** args, npy_intp* dimensions, npy_intp* steps, void* func) + +.. cfunction:: void PyUFunc_f_f(char** args, npy_intp* dimensions, npy_intp* steps, void* func) + +.. cfunction:: void PyUFunc_g_g(char** args, npy_intp* dimensions, npy_intp* steps, void* func) + +.. cfunction:: void PyUFunc_F_F_As_D_D(char** args, npy_intp* dimensions, npy_intp* steps, void* func) + +.. cfunction:: void PyUFunc_F_F(char** args, npy_intp* dimensions, npy_intp* steps, void* func) + +.. cfunction:: void PyUFunc_D_D(char** args, npy_intp* dimensions, npy_intp* steps, void* func) + +.. cfunction:: void PyUFunc_G_G(char** args, npy_intp* dimensions, npy_intp* steps, void* func) + + Type specific, core 1-d functions for ufuncs where each + calculation is obtained by calling a function taking one input + argument and returning one output. This function is passed in + func. The letters correspond to dtypechar's of the supported + data types ( f - float, d - double, g - long double, + F - cfloat, D - cdouble, G - clongdouble). The + argument *func* must support the same signature. The _As_X_X + variants assume ndarray's of one data type but cast the values to + use an underlying function that takes a different data type. Thus, + :cfunc:PyUFunc_f_f_As_d_d uses ndarrays of data type :cdata:NPY_FLOAT + but calls out to a C-function that takes double and returns + double. + +.. cfunction:: void PyUFunc_ff_f_As_dd_d(char** args, npy_intp* dimensions, npy_intp* steps, void* func) + +.. cfunction:: void PyUFunc_ff_f(char** args, npy_intp* dimensions, npy_intp* steps, void* func) + +.. cfunction:: void PyUFunc_dd_d(char** args, npy_intp* dimensions, npy_intp* steps, void* func) + +.. cfunction:: void PyUFunc_gg_g(char** args, npy_intp* dimensions, npy_intp* steps, void* func) + +.. cfunction:: void PyUFunc_FF_F_As_DD_D(char** args, npy_intp* dimensions, npy_intp* steps, void* func) + +.. cfunction:: void PyUFunc_DD_D(char** args, npy_intp* dimensions, npy_intp* steps, void* func) + +.. cfunction:: void PyUFunc_FF_F(char** args, npy_intp* dimensions, npy_intp* steps, void* func) + +.. cfunction:: void PyUFunc_GG_G(char** args, npy_intp* dimensions, npy_intp* steps, void* func) + + Type specific, core 1-d functions for ufuncs where each + calculation is obtained by calling a function taking two input + arguments and returning one output. The underlying function to + call is passed in as *func*. The letters correspond to + dtypechar's of the specific data type supported by the + general-purpose function. The argument func must support the + corresponding signature. The _As_XX_X variants assume ndarrays + of one data type but cast the values at each iteration of the loop + to use the underlying function that takes a different data type. + +.. cfunction:: void PyUFunc_O_O(char** args, npy_intp* dimensions, npy_intp* steps, void* func) + +.. cfunction:: void PyUFunc_OO_O(char** args, npy_intp* dimensions, npy_intp* steps, void* func) + + One-input, one-output, and two-input, one-output core 1-d functions + for the :cdata:NPY_OBJECT data type. These functions handle reference count + issues and return early on error. The actual function to call is *func* + and it must accept calls with the signature (PyObject*)(PyObject*) + for :cfunc:PyUFunc_O_O or (PyObject*)(PyObject *, PyObject *) + for :cfunc:PyUFunc_OO_O. + +.. cfunction:: void PyUFunc_O_O_method(char** args, npy_intp* dimensions, npy_intp* steps, void* func) + + This general purpose 1-d core function assumes that *func* is a string + representing a method of the input object. For each + iteration of the loop, the Python obejct is extracted from the array + and its *func* method is called returning the result to the output array. + +.. cfunction:: void PyUFunc_OO_O_method(char** args, npy_intp* dimensions, npy_intp* steps, void* func) + + This general purpose 1-d core function assumes that *func* is a + string representing a method of the input object that takes one + argument. The first argument in *args* is the method whose function is + called, the second argument in *args* is the argument passed to the + function. The output of the function is stored in the third entry + of *args*. + +.. cfunction:: void PyUFunc_On_Om(char** args, npy_intp* dimensions, npy_intp* steps, void* func) + + This is the 1-d core function used by the dynamic ufuncs created + by umath.frompyfunc(function, nin, nout). In this case *func* is a + pointer to a :ctype:PyUFunc_PyFuncData structure which has definition + + .. ctype:: PyUFunc_PyFuncData + + .. code-block:: c + + typedef struct { + int nin; + int nout; + PyObject *callable; + } PyUFunc_PyFuncData; + + At each iteration of the loop, the *nin* input objects are exctracted + from their object arrays and placed into an argument tuple, the Python + *callable* is called with the input arguments, and the nout + outputs are placed into their object arrays. + + +Importing the API +----------------- + +.. cvar:: PY_UFUNC_UNIQUE_SYMBOL + +.. cvar:: NO_IMPORT_UFUNC + +.. cfunction:: void import_ufunc(void) + + These are the constants and functions for accessing the ufunc + C-API from extension modules in precisely the same way as the + array C-API can be accessed. The import_ufunc () function must + always be called (in the initialization subroutine of the + extension module). If your extension module is in one file then + that is all that is required. The other two constants are useful + if your extension module makes use of multiple files. In that + case, define :cdata:PY_UFUNC_UNIQUE_SYMBOL to something unique to + your code and then in source files that do not contain the module + initialization function but still need access to the UFUNC API, + define :cdata:PY_UFUNC_UNIQUE_SYMBOL to the same name used previously + and also define :cdata:NO_IMPORT_UFUNC. + + The C-API is actually an array of function pointers. This array is + created (and pointed to by a global variable) by import_ufunc. The + global variable is either statically defined or allowed to be seen + by other files depending on the state of + :cdata:Py_UFUNC_UNIQUE_SYMBOL and :cdata:NO_IMPORT_UFUNC. + +.. index:: + pair: ufunc; C-API Added: numpy-docs/trunk/source/reference/distutils.rst =================================================================== --- numpy-docs/trunk/source/reference/distutils.rst 2008-10-26 17:50:36 UTC (rev 5958) +++ numpy-docs/trunk/source/reference/distutils.rst 2008-10-26 17:57:55 UTC (rev 5959) @@ -0,0 +1,413 @@ +********************************** +Packaging (:mod:numpy.distutils) +********************************** + +.. module:: numpy.distutils + +NumPy provides enhanced distutils functionality to make it easier to +build and install sub-packages, auto-generate code, and extension +modules that use Fortran-compiled libraries. To use features of numpy +distutils, use the :func:setup <core.setup> command from +:mod:numpy.distutils.core. A useful :class:Configuration +<misc_util.Configuration> class is also provided in +:mod:numpy.distutils.misc_util that can make it easier to construct +keyword arguments to pass to the setup function (by passing the +dictionary obtained from the todict() method of the class). More +information is available in the NumPy Distutils Users Guide in +<site-packages>/numpy/doc/DISTUTILS.txt. + +.. index:: + single: distutils + + +Modules in :mod:numpy.distutils +================================= + +misc_util +--------- + +.. module:: numpy.distutils.misc_util + +.. autosummary:: + :toctree: generated/ + + Configuration + get_numpy_include_dirs + get_numarray_include_dirs + dict_append + appendpath + allpath + dot_join + generate_config_py + get_cmd + terminal_has_colors + red_text + green_text + yellow_text + blue_text + cyan_text + cyg2win32 + all_strings + has_f_sources + has_cxx_sources + filter_sources + get_dependencies + is_local_src_dir + get_ext_source_files + get_script_files + + +.. class:: Configuration(package_name=None, parent_name=None, top_path=None, package_path=None, **attrs) + + Construct a configuration instance for the given package name. If + *parent_name* is not :const:None, then construct the package as a + sub-package of the *parent_name* package. If *top_path* and + *package_path* are :const:None then they are assumed equal to + the path of the file this instance was created in. The setup.py + files in the numpy distribution are good examples of how to use + the :class:Configuration instance. + + .. method:: todict() + + Return a dictionary compatible with the keyword arguments of distutils + setup function. Thus, this method may be used as + setup(\**config.todict()). + + .. method:: get_distribution() + + Return the distutils distribution object for self. + + .. method:: get_subpackage(subpackage_name, subpackage_path=None) + + Return a Configuration instance for the sub-package given. If + subpackage_path is None then the path is assumed to be the local path + plus the subpackage_name. If a setup.py file is not found in the + subpackage_path, then a default configuration is used. + + .. method:: add_subpackage(subpackage_name, subpackage_path=None) + + Add a sub-package to the current Configuration instance. This is + useful in a setup.py script for adding sub-packages to a package. The + sub-package is contained in subpackage_path / subpackage_name and this + directory may contain a setup.py script or else a default setup + (suitable for Python-code-only subpackages) is assumed. If the + subpackage_path is None, then it is assumed to be located in the local + path / subpackage_name. + + .. method:: self.add_data_files(*files) + + Add files to the list of data_files to be included with the package. + The form of each element of the files sequence is very flexible + allowing many combinations of where to get the files from the package + and where they should ultimately be installed on the system. The most + basic usage is for an element of the files argument sequence to be a + simple filename. This will cause that file from the local path to be + installed to the installation path of the self.name package (package + path). The file argument can also be a relative path in which case the + entire relative path will be installed into the package directory. + Finally, the file can be an absolute path name in which case the file + will be found at the absolute path name but installed to the package + path. + + This basic behavior can be augmented by passing a 2-tuple in as the + file argument. The first element of the tuple should specify the + relative path (under the package install directory) where the + remaining sequence of files should be installed to (it has nothing to + do with the file-names in the source distribution). The second element + of the tuple is the sequence of files that should be installed. The + files in this sequence can be filenames, relative paths, or absolute + paths. For absolute paths the file will be installed in the top-level + package installation directory (regardless of the first argument). + Filenames and relative path names will be installed in the package + install directory under the path name given as the first element of + the tuple. An example may clarify:: + + self.add_data_files('foo.dat', + ('fun', ['gun.dat', 'nun/pun.dat', '/tmp/sun.dat']), + 'bar/cat.dat', + '/full/path/to/can.dat') + + will install these data files to:: + + <package install directory>/ + foo.dat + fun/ + gun.dat + nun/ + pun.dat + sun.dat + bar/ + car.dat + can.dat + + where <package install directory> is the package (or sub-package) + directory such as '/usr/lib/python2.4/site-packages/mypackage' ('C: \\Python2.4 \\Lib \\site-packages \\mypackage') or '/usr/lib/python2.4/site- + packages/mypackage/mysubpackage' ('C: \\Python2.4 \\Lib \\site-packages \\mypackage \\mysubpackage'). + + + An additional feature is that the path to a data-file can actually be + a function that takes no arguments and returns the actual path(s) to + the data-files. This is useful when the data files are generated while + building the package. + + .. method:: add_data_dir(data_path) + + Recursively add files under data_path to the list of data_files to be + installed (and distributed). The data_path can be either a relative + path-name, or an absolute path-name, or a 2-tuple where the first + argument shows where in the install directory the data directory + should be installed to. For example suppose the source directory + contains fun/foo.dat and fun/bar/car.dat:: + + self.add_data_dir('fun') + self.add_data_dir(('sun', 'fun')) + self.add_data_dir(('gun', '/full/path/to/fun')) + + Will install data-files to the locations:: + + <package install directory>/ + fun/ + foo.dat + bar/ + car.dat + sun/ + foo.dat + bar/ + car.dat + gun/ + foo.dat + car.dat + + .. method:: add_include_dirs(*paths) + + Add the given sequence of paths to the beginning of the include_dirs + list. This list will be visible to all extension modules of the + current package. + + .. method:: add_headers(*files) + + Add the given sequence of files to the beginning of the headers list. + By default, headers will be installed under <python- + include>/<self.name.replace('.','/')>/ directory. If an item of files + is a tuple, then its first argument specifies the actual installation + location relative to the <python-include> path. + + .. method:: add_extension(name, sources, **kw) + + Create and add an Extension instance to the ext_modules list. The + first argument defines the name of the extension module that will be + installed under the self.name package. The second argument is a list + of sources. This method also takes the following optional keyword + arguments that are passed on to the Extension constructor: + include_dirs, define_macros, undef_macros, library_dirs, libraries, + runtime_library_dirs, extra_objects, swig_opts, depends, language, + f2py_options, module_dirs, and extra_info. + + The self.paths(...) method is applied to all lists that may contain + paths. The extra_info is a dictionary or a list of dictionaries whose + content will be appended to the keyword arguments. The depends list + contains paths to files or directories that the sources of the + extension module depend on. If any path in the depends list is newer + than the extension module, then the module will be rebuilt. + + The list of sources may contain functions (called source generators) + which must take an extension instance and a build directory as inputs + and return a source file or list of source files or None. If None is + returned then no sources are generated. If the Extension instance has + no sources after processing all source generators, then no extension + module is built. + + .. method:: add_library(name, sources, **build_info) + + Add a library to the list of libraries. Allowed keyword arguments are + depends, macros, include_dirs, extra_compiler_args, and f2py_options. + The name is the name of the library to be built and sources is a list + of sources (or source generating functions) to add to the library. + + .. method:: add_scripts(*files) + + Add the sequence of files to the beginning of the scripts list. + Scripts will be installed under the <prefix>/bin/ directory. + + .. method:: paths(*paths) + + Applies glob.glob(...) to each path in the sequence (if needed) and + pre-pends the local_path if needed. Because this is called on all + source lists, this allows wildcard characters to be specified in lists + of sources for extension modules and libraries and scripts and allows + path-names be relative to the source directory. + + .. method:: get_config_cmd() + + Returns the numpy.distutils config command instance. + + .. method:: get_build_temp_dir() + + Return a path to a temporary directory where temporary files should be + placed. + + .. method:: have_f77c() + + True if a Fortran 77 compiler is available (because a simple Fortran + 77 code was able to be compiled successfully). + + .. method:: have_f90c() + + True if a Fortran 90 compiler is available (because a simple Fortran + 90 code was able to be compiled successfully) + + .. method:: get_version() + + Return a version string of the current package or None if the version + information could not be detected. This method scans files named + __version__.py, <packagename>_version.py, version.py, and + __svn_version__.py for string variables version, __version\__, and + <packagename>_version, until a version number is found. + + .. method:: make_svn_version_py() + + Appends a data function to the data_files list that will generate + __svn_version__.py file to the current package directory. This file + will be removed from the source directory when Python exits (so that + it can be re-generated next time the package is built). This is + intended for working with source directories that are in an SVN + repository. + + .. method:: make_config_py() + + Generate a package __config__.py file containing system information + used during the building of the package. This file is installed to the + package installation directory. + + .. method:: get_info(*names) + + Return information (from system_info.get_info) for all of the names in + the argument list in a single dictionary. + + +Other modules +------------- + +.. currentmodule:: numpy.distutils + +.. autosummary:: + :toctree: generated/ + + system_info.get_info + system_info.get_standard_file + cpuinfo.cpu + log.set_verbosity + exec_command + + +Conversion of .src files +============================ + +NumPy distutils supports automatic conversion of source files named +<somefile>.src. This facility can be used to maintain very similar +code blocks requiring only simple changes between blocks. During the +build phase of setup, if a template file named <somefile>.src is +encountered, a new file named <somefile> is constructed from the +template and placed in the build directory to be used instead. Two +forms of template conversion are supported. The first form occurs for +files named named <file>.ext.src where ext is a recognized Fortran +extension (f, f90, f95, f77, for, ftn, pyf). The second form is used +for all other cases. + +.. index:: + single: code generation + +Fortran files +------------- + +This template converter will replicate all **function** and +**subroutine** blocks in the file with names that contain '<...>' +according to the rules in '<...>'. The number of comma-separated words +in '<...>' determines the number of times the block is repeated. What +these words are indicates what that repeat rule, '<...>', should be +replaced with in each block. All of the repeat rules in a block must +contain the same number of comma-separated words indicating the number +of times that block should be repeated. If the word in the repeat rule +needs a comma, leftarrow, or rightarrow, then prepend it with a +backslash ' \'. If a word in the repeat rule matches ' \\<index>' then +it will be replaced with the <index>-th word in the same repeat +specification. There are two forms for the repeat rule: named and +short. + + +Named repeat rule +^^^^^^^^^^^^^^^^^ + +A named repeat rule is useful when the same set of repeats must be +used several times in a block. It is specified using <rule1=item1, +item2, item3,..., itemN>, where N is the number of times the block +should be repeated. On each repeat of the block, the entire +expression, '<...>' will be replaced first with item1, and then with +item2, and so forth until N repeats are accomplished. Once a named +repeat specification has been introduced, the same repeat rule may be +used **in the current block** by referring only to the name +(i.e. <rule1>. + + +Short repeat rule +^^^^^^^^^^^^^^^^^ + +A short repeat rule looks like <item1, item2, item3, ..., itemN>. The +rule specifies that the entire expression, '<...>' should be replaced +first with item1, and then with item2, and so forth until N repeats +are accomplished. + + +Pre-defined names +^^^^^^^^^^^^^^^^^ + +The following predefined named repeat rules are available: + +- <prefix=s,d,c,z> + +- <_c=s,d,c,z> + +- <_t=real, double precision, complex, double complex> + +- <ftype=real, double precision, complex, double complex> + +- <ctype=float, double, complex_float, complex_double> + +- <ftypereal=float, double precision, \\0, \\1> + +- <ctypereal=float, double, \\0, \\1> + + +Other files +----------- + +Non-Fortran files use a separate syntax for defining template blocks +that should be repeated using a variable expansion similar to the +named repeat rules of the Fortran-specific repeats. The template rules +for these files are: + +1. "/\**begin repeat "on a line by itself marks the beginning of + a segment that should be repeated. + +2. Named variable expansions are defined using #name=item1, item2, item3, + ..., itemN# and placed on successive lines. These variables are + replaced in each repeat block with corresponding word. All named + variables in the same repeat block must define the same number of + words. + +3. In specifying the repeat rule for a named variable, item*N is short- + hand for item, item, ..., item repeated N times. In addition, + parenthesis in combination with \*N can be used for grouping several + items that should be repeated. Thus, #name=(item1, item2)*4# is + equivalent to #name=item1, item2, item1, item2, item1, item2, item1, + item2# + +4. "\*/ "on a line by itself marks the end of the the variable expansion + naming. The next line is the first line that will be repeated using + the named rules. + +5. Inside the block to be repeated, the variables that should be expanded + are specified as @name@. + +6. "/\**end repeat**/ "on a line by itself marks the previous line + as the last line of the block to be repeated. Added: numpy-docs/trunk/source/reference/figures/dtype-hierarchy.dia =================================================================== (Binary files differ) Property changes on: numpy-docs/trunk/source/reference/figures/dtype-hierarchy.dia ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: numpy-docs/trunk/source/reference/figures/dtype-hierarchy.pdf =================================================================== (Binary files differ) Property changes on: numpy-docs/trunk/source/reference/figures/dtype-hierarchy.pdf ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: numpy-docs/trunk/source/reference/figures/dtype-hierarchy.png =================================================================== (Binary files differ) Property changes on: numpy-docs/trunk/source/reference/figures/dtype-hierarchy.png ___________________________________________________________________ Name: svn:mime-type + image/png Added: numpy-docs/trunk/source/reference/figures/threefundamental.fig =================================================================== --- numpy-docs/trunk/source/reference/figures/threefundamental.fig 2008-10-26 17:50:36 UTC (rev 5958) +++ numpy-docs/trunk/source/reference/figures/threefundamental.fig 2008-10-26 17:57:55 UTC (rev 5959) @@ -0,0 +1,57 @@ +#FIG 3.2 +Landscape +Center +Inches +Letter +100.00 +Single +-2 +1200 2 +6 1950 2850 4350 3450 +2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 1950 2850 4350 2850 4350 3450 1950 3450 1950 2850 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 2550 2850 2550 3450 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 3150 2850 3150 3450 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 3750 2850 3750 3450 +-6 +2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 5100 2850 7500 2850 7500 3450 5100 3450 5100 2850 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 5700 2850 5700 3450 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 6300 2850 6300 3450 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 6900 2850 6900 3450 +2 4 0 1 0 7 50 -1 -1 0.000 0 0 7 0 0 5 + 7800 3600 7800 2700 525 2700 525 3600 7800 3600 +2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 675 2850 1725 2850 1725 3450 675 3450 675 2850 +2 2 0 4 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 5700 2850 6300 2850 6300 3450 5700 3450 5700 2850 +2 2 0 4 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 5700 1725 6300 1725 6300 2325 5700 2325 5700 1725 +2 4 0 1 0 7 50 -1 -1 0.000 0 0 7 0 0 5 + 6450 2475 6450 1275 5550 1275 5550 2475 6450 2475 +2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 5700 1350 6300 1350 6300 1575 5700 1575 5700 1350 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 3 + 2 1 1.00 60.00 120.00 + 900 2850 900 1875 1575 1875 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 + 2 1 1.00 60.00 120.00 + 3375 1800 5550 1800 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 + 2 1 1.00 60.00 120.00 + 6000 2850 6000 2325 +2 4 0 1 0 7 50 -1 -1 0.000 0 0 7 0 0 5 + 3375 2100 3375 1575 1575 1575 1575 2100 3375 2100 +4 0 0 50 -1 18 14 0.0000 4 165 720 825 3225 header\001 +4 0 0 50 -1 2 40 0.0000 4 105 450 4500 3225 ...\001 +4 0 0 50 -1 18 14 0.0000 4 210 810 3600 3900 ndarray\001 +4 0 0 50 -1 18 14 0.0000 4 165 630 6600 2175 scalar\001 +4 0 0 50 -1 18 14 0.0000 4 165 540 6600 1950 array\001 +4 0 0 50 -1 16 12 0.0000 4 135 420 5775 1500 head\001 +4 0 0 50 -1 18 14 0.0000 4 210 975 1950 1875 data-type\001 Added: numpy-docs/trunk/source/reference/figures/threefundamental.pdf =================================================================== (Binary files differ) Property changes on: numpy-docs/trunk/source/reference/figures/threefundamental.pdf ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: numpy-docs/trunk/source/reference/figures/threefundamental.png =================================================================== (Binary files differ) Property changes on: numpy-docs/trunk/source/reference/figures/threefundamental.png ___________________________________________________________________ Name: svn:mime-type + image/png Added: numpy-docs/trunk/source/reference/index.rst =================================================================== --- numpy-docs/trunk/source/reference/index.rst 2008-10-26 17:50:36 UTC (rev 5958) +++ numpy-docs/trunk/source/reference/index.rst 2008-10-26 17:57:55 UTC (rev 5959) @@ -0,0 +1,43 @@ +.. _reference: + +############### +NumPy Reference +############### + +:Release: |version| +:Date: |today| + +.. module:: numpy + +This reference manual details functions, modules, and objects +included in Numpy, describing what they are and what they do. +For learning how to use NumPy, see also :ref:user. + + +.. toctree:: + :maxdepth: 2 + + arrays + ufuncs + routines + ctypes + distutils + c-api + internals + + +Acknowledgements +================ + +Large parts of this manual originate from Travis E. Oliphant's book +Guide to Numpy <http://www.tramy.us/>__ (which generously entered +Public Domain in August 2008). The reference documentation for many of +the functions are written by numerous contributors and developers of +Numpy, both prior to and during the +Numpy Documentation Marathon <http://scipy.org/Developer_Zone/DocMarathon2008>__. + +The Documentation Marathon is still ongoing. Please help us write +better documentation for Numpy by joining it! Instructions on how to +join and what to do can be found +on the scipy.org website <http://scipy.org/Developer_Zone/DocMarathon2008>__ + Added: numpy-docs/trunk/source/reference/internals.code-explanations.rst =================================================================== --- numpy-docs/trunk/source/reference/internals.code-explanations.rst 2008-10-26 17:50:36 UTC (rev 5958) +++ numpy-docs/trunk/source/reference/internals.code-explanations.rst 2008-10-26 17:57:55 UTC (rev 5959) @@ -0,0 +1,665 @@ +.. currentmodule:: numpy + +************************* +Numpy C Code Explanations +************************* + + Fanaticism consists of redoubling your efforts when you have forgotten + your aim. + --- *George Santayana* + + An authority is a person who can tell you more about something than + you really care to know. + --- *Unknown* + +This Chapter attempts to explain the logic behind some of the new +pieces of code. The purpose behind these explanations is to enable +somebody to be able to understand the ideas behind the implementation +somewhat more easily than just staring at the code. Perhaps in this +way, the algorithms can be improved on, borrowed from, and/or +optimized. + + +Memory model +============ + +.. index:: + pair: ndarray; memory model + +One fundamental aspect of the ndarray is that an array is seen as a +"chunk" of memory starting at some location. The interpretation of +this memory depends on the stride information. For each dimension in +an :math:N -dimensional array, an integer (stride) dictates how many +bytes must be skipped to get to the next element in that dimension. +Unless you have a single-segment array, this stride information must +be consulted when traversing through an array. It is not difficult to +write code that accepts strides, you just have to use (char \*) +pointers because strides are in units of bytes. Keep in mind also that +strides do not have to be unit-multiples of the element size. Also, +remember that if the number of dimensions of the array is 0 (sometimes +called a rank-0 array), then the strides and dimensions variables are +NULL. + +Besides the structural information contained in the strides and +dimensions members of the :ctype:PyArrayObject, the flags contain important +information about how the data may be accessed. In particular, the +:cdata:NPY_ALIGNED flag is set when the memory is on a suitable boundary +according to the data-type array. Even if you have a contiguous chunk +of memory, you cannot just assume it is safe to dereference a data- +type-specific pointer to an element. Only if the :cdata:NPY_ALIGNED flag is +set is this a safe operation (on some platforms it will work but on +others, like Solaris, it will cause a bus error). The :cdata:NPY_WRITEABLE +should also be ensured if you plan on writing to the memory area of +the array. It is also possible to obtain a pointer to an unwriteable +memory area. Sometimes, writing to the memory area when the +:cdata:NPY_WRITEABLE flag is not set will just be rude. Other times it can +cause program crashes ( *e.g.* a data-area that is a read-only +memory-mapped file). + + +Data-type encapsulation +======================= + +.. index:: + single: dtype + +The data-type is an important abstraction of the ndarray. Operations +will look to the data-type to provide the key functionality that is +needed to operate on the array. This functionality is provided in the +list of function pointers pointed to by the 'f' member of the +:ctype:PyArray_Descr structure. In this way, the number of data-types can be +extended simply by providing a :ctype:PyArray_Descr structure with suitable +function pointers in the 'f' member. For built-in types there are some +optimizations that by-pass this mechanism, but the point of the data- +type abstraction is to allow new data-types to be added. + +One of the built-in data-types, the void data-type allows for +arbitrary records containing 1 or more fields as elements of the +array. A field is simply another data-type object along with an offset +into the current record. In order to support arbitrarily nested +fields, several recursive implementations of data-type access are +implemented for the void type. A common idiom is to cycle through the +elements of the dictionary and perform a specific operation based on +the data-type object stored at the given offset. These offsets can be +arbitrary numbers. Therefore, the possibility of encountering mis- +aligned data must be recognized and taken into account if necessary. + + +N-D Iterators +============= + +.. index:: + single: array iterator + +A very common operation in much of NumPy code is the need to iterate +over all the elements of a general, strided, N-dimensional array. This +operation of a general-purpose N-dimensional loop is abstracted in the +notion of an iterator object. To write an N-dimensional loop, you only +have to create an iterator object from an ndarray, work with the +dataptr member of the iterator object structure and call the macro +:cfunc:PyArray_ITER_NEXT (it) on the iterator object to move to the next +element. The "next" element is always in C-contiguous order. The macro +works by first special casing the C-contiguous, 1-d, and 2-d cases +which work very simply. + +For the general case, the iteration works by keeping track of a list +of coordinate counters in the iterator object. At each iteration, the +last coordinate counter is increased (starting from 0). If this +counter is smaller then one less than the size of the array in that +dimension (a pre-computed and stored value), then the counter is +increased and the dataptr member is increased by the strides in that +dimension and the macro ends. If the end of a dimension is reached, +the counter for the last dimension is reset to zero and the dataptr is +moved back to the beginning of that dimension by subtracting the +strides value times one less than the number of elements in that +dimension (this is also pre-computed and stored in the backstrides +member of the iterator object). In this case, the macro does not end, +but a local dimension counter is decremented so that the next-to-last +dimension replaces the role that the last dimension played and the +previously-described tests are executed again on the next-to-last +dimension. In this way, the dataptr is adjusted appropriately for +arbitrary striding. + +The coordinates member of the :ctype:PyArrayIterObject structure maintains +the current N-d counter unless the underlying array is C-contiguous in +which case the coordinate counting is by-passed. The index member of +the :ctype:PyArrayIterObject keeps track of the current flat index of the +iterator. It is updated by the :cfunc:PyArray_ITER_NEXT macro. + + +Broadcasting +============ + +.. index:: + single: broadcasting + +In Numeric, broadcasting was implemented in several lines of code +buried deep in ufuncobject.c. In NumPy, the notion of broadcasting has +been abstracted so that it can be performed in multiple places. +Broadcasting is handled by the function :cfunc:PyArray_Broadcast. This +function requires a :ctype:PyArrayMultiIterObject (or something that is a +binary equivalent) to be passed in. The :ctype:PyArrayMultiIterObject keeps +track of the broadcasted number of dimensions and size in each +dimension along with the total size of the broadcasted result. It also +keeps track of the number of arrays being broadcast and a pointer to +an iterator for each of the arrays being broadcasted. + +The :cfunc:PyArray_Broadcast function takes the iterators that have already +been defined and uses them to determine the broadcast shape in each +dimension (to create the iterators at the same time that broadcasting +occurs then use the :cfunc:PyMultiIter_New function). Then, the iterators are +adjusted so that each iterator thinks it is iterating over an array +with the broadcasted size. This is done by adjusting the iterators +number of dimensions, and the shape in each dimension. This works +because the iterator strides are also adjusted. Broadcasting only +adjusts (or adds) length-1 dimensions. For these dimensions, the +strides variable is simply set to 0 so that the data-pointer for the +iterator over that array doesn't move as the broadcasting operation +operates over the extended dimension. + +Broadcasting was always implemented in Numeric using 0-valued strides +for the extended dimensions. It is done in exactly the same way in +NumPy. The big difference is that now the array of strides is kept +track of in a :ctype:PyArrayIterObject, the iterators involved in a +broadcasted result are kept track of in a :ctype:PyArrayMultiIterObject, +and the :cfunc:PyArray_BroadCast call implements the broad-casting rules. + + +Array Scalars +============= + +.. index:: + single: array scalars + +The array scalars offer a hierarchy of Python types that allow a one- +to-one correspondence between the data-type stored in an array and the +Python-type that is returned when an element is extracted from the +array. An exception to this rule was made with object arrays. Object +arrays are heterogeneous collections of arbitrary Python objects. When +you select an item from an object array, you get back the original +Python object (and not an object array scalar which does exist but is +rarely used for practical purposes). + +The array scalars also offer the same methods and attributes as arrays +with the intent that the same code can be used to support arbitrary +dimensions (including 0-dimensions). The array scalars are read-only +(immutable) with the exception of the void scalar which can also be +written to so that record-array field setting works more naturally +(a[0]['f1'] = value ). + + +Advanced ("Fancy") Indexing +============================= + +.. index:: + single: indexing + +The implementation of advanced indexing represents some of the most +difficult code to write and explain. In fact, there are two +implementations of advanced indexing. The first works only with 1-d +arrays and is implemented to handle expressions involving a.flat[obj]. +The second is general-purpose that works for arrays of "arbitrary +dimension" (up to a fixed maximum). The one-dimensional indexing +approaches were implemented in a rather straightforward fashion, and +so it is the general-purpose indexing code that will be the focus of +this section. + +There is a multi-layer approach to indexing because the indexing code +can at times return an array scalar and at other times return an +array. The functions with "_nice" appended to their name do this +special handling while the function without the _nice appendage always +return an array (perhaps a 0-dimensional array). Some special-case +optimizations (the index being an integer scalar, and the index being +a tuple with as many dimensions as the array) are handled in +array_subscript_nice function which is what Python calls when +presented with the code "a[obj]." These optimizations allow fast +single-integer indexing, and also ensure that a 0-dimensional array is +not created only to be discarded as the array scalar is returned +instead. This provides significant speed-up for code that is selecting +many scalars out of an array (such as in a loop). However, it is still +not faster than simply using a list to store standard Python scalars, +because that is optimized by the Python interpreter itself. + +After these optimizations, the array_subscript function itself is +called. This function first checks for field selection which occurs +when a string is passed as the indexing object. Then, 0-d arrays are +given special-case consideration. Finally, the code determines whether +or not advanced, or fancy, indexing needs to be performed. If fancy +indexing is not needed, then standard view-based indexing is performed +using code borrowed from Numeric which parses the indexing object and +returns the offset into the data-buffer and the dimensions necessary +to create a new view of the array. The strides are also changed by +multiplying each stride by the step-size requested along the +corresponding dimension. + + +Fancy-indexing check +-------------------- + +The fancy_indexing_check routine determines whether or not to use +standard view-based indexing or new copy-based indexing. If the +indexing object is a tuple, then view-based indexing is assumed by +default. Only if the tuple contains an array object or a sequence +object is fancy-indexing assumed. If the indexing object is an array, +then fancy indexing is automatically assumed. If the indexing object +is any other kind of sequence, then fancy-indexing is assumed by +default. This is over-ridden to simple indexing if the sequence +contains any slice, newaxis, or Ellipsis objects, and no arrays or +additional sequences are also contained in the sequence. The purpose +of this is to allow the construction of "slicing" sequences which is a +common technique for building up code that works in arbitrary numbers +of dimensions. + + +Fancy-indexing implementation +----------------------------- + +The concept of indexing was also abstracted using the idea of an +iterator. If fancy indexing is performed, then a :ctype:PyArrayMapIterObject +is created. This internal object is not exposed to Python. It is +created in order to handle the fancy-indexing at a high-level. Both +get and set fancy-indexing operations are implemented using this +object. Fancy indexing is abstracted into three separate operations: +(1) creating the :ctype:PyArrayMapIterObject from the indexing object, (2) +binding the :ctype:PyArrayMapIterObject to the array being indexed, and (3) +getting (or setting) the items determined by the indexing object. +There is an optimization implemented so that the :ctype:PyArrayIterObject +(which has it's own less complicated fancy-indexing) is used for +indexing when possible. + + +Creating the mapping object +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The first step is to convert the indexing objects into a standard form +where iterators are created for all of the index array inputs and all +Boolean arrays are converted to equivalent integer index arrays (as if +nonzero(arr) had been called). Finally, all integer arrays are +replaced with the integer 0 in the indexing object and all of the +index-array iterators are "broadcast" to the same shape. + + +Binding the mapping object +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +When the mapping object is created it does not know which array it +will be used with so once the index iterators are constructed during +mapping-object creation, the next step is to associate these iterators +with a particular ndarray. This process interprets any ellipsis and +slice objects so that the index arrays are associated with the +appropriate axis (the axis indicated by the iteraxis entry +corresponding to the iterator for the integer index array). This +information is then used to check the indices to be sure they are +within range of the shape of the array being indexed. The presence of +ellipsis and/or slice objects implies a sub-space iteration that is +accomplished by extracting a sub-space view of the array (using the +index object resulting from replacing all the integer index arrays +with 0) and storing the information about where this sub-space starts +in the mapping object. This is used later during mapping-object +iteration to select the correct elements from the underlying array. + + +Getting (or Setting) +^^^^^^^^^^^^^^^^^^^^ + +After the mapping object is successfully bound to a particular array, +the mapping object contains the shape of the resulting item as well as +iterator objects that will walk through the currently-bound array and +either get or set its elements as needed. The walk is implemented +using the :cfunc:PyArray_MapIterNext function. This function sets the +coordinates of an iterator object into the current array to be the +next coordinate location indicated by all of the indexing-object +iterators while adjusting, if necessary, for the presence of a sub- +space. The result of this function is that the dataptr member of the +mapping object structure is pointed to the next position in the array +that needs to be copied out or set to some value. + +When advanced indexing is used to extract an array, an iterator for +the new array is constructed and advanced in phase with the mapping +object iterator. When advanced indexing is used to place values in an +array, a special "broadcasted" iterator is constructed from the object +being placed into the array so that it will only work if the values +used for setting have a shape that is "broadcastable" to the shape +implied by the indexing object. + + +Universal Functions +=================== + +.. index:: + single: ufunc + +Universal functions are callable objects that take :math:N inputs +and produce :math:M outputs by wrapping basic 1-d loops that work +element-by-element into full easy-to use functions that seamlessly +implement broadcasting, type-checking and buffered coercion, and +output-argument handling. New universal functions are normally created +in C, although there is a mechanism for creating ufuncs from Python +functions (:func:frompyfunc). The user must supply a 1-d loop that +implements the basic function taking the input scalar values and +placing the resulting scalars into the appropriate output slots as +explaine n implementation. + + +Setup +----- + +Every ufunc calculation involves some overhead related to setting up +the calculation. The practical significance of this overhead is that +even though the actual calculation of the ufunc is very fast, you will +be able to write array and type-specific code that will work faster +for small arrays than the ufunc. In particular, using ufuncs to +perform many calculations on 0-d arrays will be slower than other +Python-based solutions (the silently-imported scalarmath module exists +precisely to give array scalars the look-and-feel of ufunc-based +calculations with significantly reduced overhead). + +When a ufunc is called, many things must be done. The information +collected from these setup operations is stored in a loop-object. This +loop object is a C-structure (that could become a Python object but is +not initialized as such because it is only used internally). This loop +object has the layout needed to be used with PyArray_Broadcast so that +the broadcasting can be handled in the same way as it is handled in +other sections of code. + +The first thing done is to look-up in the thread-specific global +dictionary the current values for the buffer-size, the error mask, and +the associated error object. The state of the error mask controls what +happens when an error-condiction is found. It should be noted that +checking of the hardware error flags is only performed after each 1-d +loop is executed. This means that if the input and output arrays are +contiguous and of the correct type so that a single 1-d loop is +performed, then the flags may not be checked until all elements of the +array have been calcluated. Looking up these values in a thread- +specific dictionary takes time which is easily ignored for all but +very small arrays. + +After checking, the thread-specific global variables, the inputs are +evaluated to determine how the ufunc should proceed and the input and +output arrays are constructed if necessary. Any inputs which are not +arrays are converted to arrays (using context if necessary). Which of +the inputs are scalars (and therefore converted to 0-d arrays) is +noted. + +Next, an appropriate 1-d loop is selected from the 1-d loops available +to the ufunc based on the input array types. This 1-d loop is selected +by trying to match the signature of the data-types of the inputs +against the available signatures. The signatures corresponding to +built-in types are stored in the types member of the ufunc structure. +The signatures corresponding to user-defined types are stored in a +linked-list of function-information with the head element stored as a +CObject in the userloops dictionary keyed by the data-type number +(the first user-defined type in the argument list is used as the key). +The signatures are searched until a signature is found to which the +input arrays can all be cast safely (ignoring any scalar arguments +which are not allowed to determine the type of the result). The +implication of this search procedure is that "lesser types" should be +placed below "larger types" when the signatures are stored. If no 1-d +loop is found, then an error is reported. Otherwise, the argument_list +is updated with the stored signature --- in case casting is necessary +and to fix the output types assumed by the 1-d loop. + +If the ufunc has 2 inputs and 1 output and the second input is an +Object array then a special-case check is performed so that +NotImplemented is returned if the second input is not an ndarray, has +the __array_priority\__ attribute, and has an __r{op}\__ special +method. In this way, Python is signaled to give the other object a +chance to complete the operation instead of using generic object-array +calculations. This allows (for example) sparse matrices to override +the multiplication operator 1-d loop. + +For input arrays that are smaller than the specified buffer size, +copies are made of all non-contiguous, mis-aligned, or out-of- +byteorder arrays to ensure that for small arrays, a single-loop is +used. Then, array iterators are created for all the input arrays and +the resulting collection of iterators is broadcast to a single shape. + +The output arguments (if any) are then processed and any missing +return arrays are constructed. If any provided output array doesn't +have the correct type (or is mis-aligned) and is smaller than the +buffer size, then a new output array is constructed with the special +UPDATEIFCOPY flag set so that when it is DECREF'd on completion of the +function, it's contents will be copied back into the output array. +Iterators for the output arguments are then processed. + +Finally, the decision is made about how to execute the looping +mechanism to ensure that all elements of the input arrays are combined +to produce the output arrays of the correct type. The options for loop +execution are one-loop (for contiguous, aligned, and correct data- +type), strided-loop (for non-contiguous but still aligned and correct +data-type), and a buffered loop (for mis-aligned or incorrect data- +type situations). Depending on which execution method is called for, +the loop is then setup and computed. + + +Function call +------------- + +This section describes how the basic universal function computation +loop is setup and executed for each of the three different kinds of +execution possibilities. If :cdata:NPY_ALLOW_THREADS is defined during +compilation, then the Python Global Interpreter Lock (GIL) is released +prior to calling all of these loops (as long as they don't involve +object arrays). It is re-acquired if necessary to handle error +conditions. The hardware error flags are checked only after the 1-d +loop is calcluated. + + +One Loop +^^^^^^^^ + +This is the simplest case of all. The ufunc is executed by calling the +underlying 1-d loop exactly once. This is possible only when we have +aligned data of the correct type (including byte-order) for both input +and output and all arrays have uniform strides (either contiguous, +0-d, or 1-d). In this case, the 1-d computational loop is called once +to compute the calculation for the entire array. Note that the +hardware error flags are only checked after the entire calculation is +complete. + + +Strided Loop +^^^^^^^^^^^^ + +When the input and output arrays are aligned and of the correct type, +but the striding is not uniform (non-contiguous and 2-d or larger), +then a second looping structure is employed for the calculation. This +approach converts all of the iterators for the input and output +arguments to iterate over all but the largest dimension. The inner +loop is then handled by the underlying 1-d computational loop. The +outer loop is a standard iterator loop on the converted iterators. The +hardware error flags are checked after each 1-d loop is completed. + + +Buffered Loop +^^^^^^^^^^^^^ + +This is the code that handles the situation whenever the input and/or +output arrays are either misaligned or of the wrong data-type +(including being byte-swapped) from what the underlying 1-d loop +expects. The arrays are also assumed to be non-contiguous. The code +works very much like the strided loop except for the inner 1-d loop is +modified so that pre-processing is performed on the inputs and post- +processing is performed on the outputs in bufsize chunks (where +bufsize is a user-settable parameter). The underlying 1-d +computational loop is called on data that is copied over (if it needs +to be). The setup code and the loop code is considerably more +complicated in this case because it has to handle: + +- memory allocation of the temporary buffers + +- deciding whether or not to use buffers on the input and output data + (mis-aligned and/or wrong data-type) + +- copying and possibly casting data for any inputs or outputs for which + buffers are necessary. + +- special-casing Object arrays so that reference counts are properly + handled when copies and/or casts are necessary. + +- breaking up the inner 1-d loop into bufsize chunks (with a possible + remainder). + +Again, the hardware error flags are checked at the end of each 1-d +loop. + + +Final output manipulation +------------------------- + +Ufuncs allow other array-like classes to be passed seamlessly through +the interface in that inputs of a particular class will induce the +outputs to be of that same class. The mechanism by which this works is +the following. If any of the inputs are not ndarrays and define the +:obj:__array_wrap__ method, then the class with the largest +:obj:__array_priority__ attribute determines the type of all the +outputs (with the exception of any output arrays passed in). The +:obj:__array_wrap__ method of the input array will be called with the +ndarray being returned from the ufunc as it's input. There are two +calling styles of the :obj:__array_wrap__ function supported. The first +takes the ndarray as the first argument and a tuple of "context" as +the second argument. The context is (ufunc, arguments, output argument +number). This is the first call tried. If a TypeError occurs, then the +function is called with just the ndarray as the first argument. + + +Methods +------- + +Their are three methods of ufuncs that require calculation similar to +the general-purpose ufuncs. These are reduce, accumulate, and +reduceat. Each of these methods requires a setup command followed by a +loop. There are four loop styles possible for the methods +corresponding to no-elements, one-element, strided-loop, and buffered- +loop. These are the same basic loop styles as implemented for the +general purpose function call except for the no-element and one- +element cases which are special-cases occurring when the input array +objects have 0 and 1 elements respectively. + + +Setup +^^^^^ + +The setup function for all three methods is construct_reduce. +This function creates a reducing loop object and fills it with +parameters needed to complete the loop. All of the methods only work +on ufuncs that take 2-inputs and return 1 output. Therefore, the +underlying 1-d loop is selected assuming a signature of [ otype, +otype, otype ] where otype is the requested reduction +data-type. The buffer size and error handling is then retrieved from +(per-thread) global storage. For small arrays that are mis-aligned or +have incorrect data-type, a copy is made so that the un-buffered +section of code is used. Then, the looping strategy is selected. If +there is 1 element or 0 elements in the array, then a simple looping +method is selected. If the array is not mis-aligned and has the +correct data-type, then strided looping is selected. Otherwise, +buffered looping must be performed. Looping parameters are then +established, and the return array is constructed. The output array is +of a different shape depending on whether the method is reduce, +accumulate, or reduceat. If an output array is already provided, then +it's shape is checked. If the output array is not C-contiguous, +aligned, and of the correct data type, then a temporary copy is made +with the UPDATEIFCOPY flag set. In this way, the methods will be able +to work with a well-behaved output array but the result will be copied +back into the true output array when the method computation is +complete. Finally, iterators are set up to loop over the correct axis +(depending on the value of axis provided to the method) and the setup +routine returns to the actual computation routine. + + +Reduce +^^^^^^ + +.. index:: + triple: ufunc; methods; reduce + +All of the ufunc methods use the same underlying 1-d computational +loops with input and output arguments adjusted so that the appropriate +reduction takes place. For example, the key to the functioning of +reduce is that the 1-d loop is called with the output and the second +input pointing to the same position in memory and both having a step- +size of 0. The first input is pointing to the input array with a step- +size given by the appropriate stride for the selected axis. In this +way, the operation performed is + +.. math:: + :nowrap: + + \begin{align*} + o & = & i[0] \\ + o & = & i[k]\textrm{<op>}o\quad k=1\ldots N + \end{align*} + +where :math:N+1 is the number of elements in the input, :math:i, +:math:o is the output, and :math:i[k] is the +:math:k^{\textrm{th}} element of :math:i along the selected axis. +This basic operations is repeated for arrays with greater than 1 +dimension so that the reduction takes place for every 1-d sub-array +along the selected axis. An iterator with the selected dimension +removed handles this looping. + +For buffered loops, care must be taken to copy and cast data before +the loop function is called because the underlying loop expects +aligned data of the correct data-type (including byte-order). The +buffered loop must handle this copying and casting prior to calling +the loop function on chunks no greater than the user-specified +bufsize. + + +Accumulate +^^^^^^^^^^ + +.. index:: + triple: ufunc; methods; accumulate + +The accumulate function is very similar to the reduce function in that +the output and the second input both point to the output. The +difference is that the second input points to memory one stride behind +the current output pointer. Thus, the operation performed is + +.. math:: + :nowrap: + + \begin{align*} + o[0] & = & i[0] \\ + o[k] & = & i[k]\textrm{<op>}o[k-1]\quad k=1\ldots N. + \end{align*} + +The output has the same shape as the input and each 1-d loop operates +over :math:N elements when the shape in the selected axis is :math:N+1. Again, buffered loops take care to copy and cast the data before +calling the underlying 1-d computational loop. + + +Reduceat +^^^^^^^^ + +.. index:: + triple: ufunc; methods; reduceat + single: ufunc + +The reduceat function is a generalization of both the reduce and +accumulate functions. It implements a reduce over ranges of the input +array specified by indices. The extra indices argument is checked to +be sure that every input is not too large for the input array along +the selected dimension before the loop calculations take place. The +loop implementation is handled using code that is very similar to the +reduce code repeated as many times as there are elements in the +indices input. In particular: the first input pointer passed to the +underlying 1-d computational loop points to the input array at the +correct location indicated by the index array. In addition, the output +pointer and the second input pointer passed to the underlying 1-d loop +point to the same position in memory. The size of the 1-d +computational loop is fixed to be the difference between the current +index and the next index (when the current index is the last index, +then the next index is assumed to be the length of the array along the +selected dimension). In this way, the 1-d loop will implement a reduce +over the specified indices. + +Mis-aligned or a loop data-type that does not match the input and/or +output data-type is handled using buffered code where-in data is +copied to a temporary buffer and cast to the correct data-type if +necessary prior to calling the underlying 1-d function. The temporary +buffers are created in (element) sizes no bigger than the user +settable buffer-size value. Thus, the loop must be flexible enough to +call the underlying 1-d computational loop enough times to complete +the total calculation in chunks no bigger than the buffer-size. Added: numpy-docs/trunk/source/reference/internals.rst =================================================================== --- numpy-docs/trunk/source/reference/internals.rst 2008-10-26 17:50:36 UTC (rev 5958) +++ numpy-docs/trunk/source/reference/internals.rst 2008-10-26 17:57:55 UTC (rev 5959) @@ -0,0 +1,9 @@ +*************** +Numpy internals +*************** + +.. toctree:: + + internals.code-explanations + +.. automodule:: numpy.doc.internals Added: numpy-docs/trunk/source/reference/routines.array-creation.rst =================================================================== --- numpy-docs/trunk/source/reference/routines.array-creation.rst 2008-10-26 17:50:36 UTC (rev 5958) +++ numpy-docs/trunk/source/reference/routines.array-creation.rst 2008-10-26 17:57:55 UTC (rev 5959) @@ -0,0 +1,98 @@ +.. _routines.array-creation: + +Array creation routines +======================= + +.. seealso:: :ref:Array creation <arrays.creation> + +.. currentmodule:: numpy + +Ones and zeros +-------------- +.. autosummary:: + :toctree: generated/ + + empty + empty_like + eye + identity + ones + ones_like + zeros + zeros_like + +From existing data +------------------ +.. autosummary:: + :toctree: generated/ + + array + asarray + asanyarray + ascontiguousarray + asmatrix + copy + frombuffer + fromfile + fromfunction + fromiter + loadtxt + +.. _routines.array-creation.rec: + +Creating record arrays (:mod:numpy.rec) +----------------------------------------- + +.. note:: :mod:numpy.rec is the preferred alias for :mod:numpy.core.records. + +.. autosummary:: + :toctree: generated/ + + core.records.array + core.records.fromarrays + core.records.fromrecords + core.records.fromstring + core.records.fromfile + +.. _routines.array-creation.char: + +Creating character arrays (:mod:numpy.char) +--------------------------------------------- + +.. note:: :mod:numpy.char is the preferred alias for :mod:numpy.core.defchararray. + +.. autosummary:: + :toctree: generated/ + + core.defchararray.array + +Numerical ranges +---------------- +.. autosummary:: + :toctree: generated/ + + arange + linspace + logspace + meshgrid + mgrid + +Building matrices +----------------- +.. autosummary:: + :toctree: generated/ + + diag + diagflat + tri + tril + triu + vander + +The Matrix class +---------------- +.. autosummary:: + :toctree: generated/ + + mat + bmat Added: numpy-docs/trunk/source/reference/routines.array-manipulation.rst =================================================================== --- numpy-docs/trunk/source/reference/routines.array-manipulation.rst 2008-10-26 17:50:36 UTC (rev 5958) +++ numpy-docs/trunk/source/reference/routines.array-manipulation.rst 2008-10-26 17:57:55 UTC (rev 5959) @@ -0,0 +1,108 @@ +Array manipulation routines +*************************** + +.. currentmodule:: numpy + +.. toctree:: + +Changing array shape +==================== +.. autosummary:: + :toctree: generated/ + + + reshape + ravel + ndarray.flat + ndarray.flatten + +Transpose-like operations +========================= +.. autosummary:: + :toctree: generated/ + + + rollaxis + swapaxes + ndarray.T + transpose + +Changing number of dimensions +============================= +.. autosummary:: + :toctree: generated/ + + + atleast_1d + atleast_2d + atleast_3d + broadcast + broadcast_arrays + expand_dims + squeeze + +Changing kind of array +====================== +.. autosummary:: + :toctree: generated/ + + asarray + asanyarray + asmatrix + asfarray + asfortranarray + asscalar + require + +Joining arrays +============== +.. autosummary:: + :toctree: generated/ + + append + column_stack + concatenate + dstack + hstack + vstack + +Splitting arrays +================ +.. autosummary:: + :toctree: generated/ + + array_split + dsplit + hsplit + split + vsplit + +Tiling arrays +============= +.. autosummary:: + :toctree: generated/ + + tile + repeat + +Adding and removing elements +============================ +.. autosummary:: + :toctree: generated/ + + delete + insert + resize + trim_zeros + unique + +Rearranging elements +==================== +.. autosummary:: + :toctree: generated/ + + fliplr + flipud + reshape + roll + rot90 Added: numpy-docs/trunk/source/reference/routines.bitwise.rst =================================================================== --- numpy-docs/trunk/source/reference/routines.bitwise.rst 2008-10-26 17:50:36 UTC (rev 5958) +++ numpy-docs/trunk/source/reference/routines.bitwise.rst 2008-10-26 17:57:55 UTC (rev 5959) @@ -0,0 +1,31 @@ +Binary operations +***************** + +.. currentmodule:: numpy + +Elementwise bit operations +-------------------------- +.. autosummary:: + :toctree: generated/ + + bitwise_and + bitwise_or + bitwise_xor + invert + left_shift + right_shift + +Bit packing +----------- +.. autosummary:: + :toctree: generated/ + + packbits + unpackbits + +Output formatting +----------------- +.. autosummary:: + :toctree: generated/ + + binary_repr Added: numpy-docs/trunk/source/reference/routines.ctypeslib.rst =================================================================== --- numpy-docs/trunk/source/reference/routines.ctypeslib.rst 2008-10-26 17:50:36 UTC (rev 5958) +++ numpy-docs/trunk/source/reference/routines.ctypeslib.rst 2008-10-26 17:57:55 UTC (rev 5959) @@ -0,0 +1,11 @@ +*********************************************************** +C-Types Foreign Function Interface (:mod:numpy.ctypeslib) +*********************************************************** + +.. currentmodule:: numpy.ctypeslib + +.. autofunction:: as_array +.. autofunction:: as_ctypes +.. autofunction:: ctypes_load_library +.. autofunction:: load_library +.. autofunction:: ndpointer Added: numpy-docs/trunk/source/reference/routines.dtype.rst =================================================================== --- numpy-docs/trunk/source/reference/routines.dtype.rst 2008-10-26 17:50:36 UTC (rev 5958) +++ numpy-docs/trunk/source/reference/routines.dtype.rst 2008-10-26 17:57:55 UTC (rev 5959) @@ -0,0 +1,52 @@ +.. _routines.dtype: + +Data type routines +================== + +.. currentmodule:: numpy + +.. autosummary:: + :toctree: generated/ + + can_cast + common_type + obj2sctype + +Creating data types +------------------- + +.. autosummary:: + :toctree: generated/ + + + dtype + format_parser + +Data type information +--------------------- +.. autosummary:: + :toctree: generated/ + + finfo + iinfo + MachAr + +Data type testing +----------------- +.. autosummary:: + :toctree: generated/ + + issctype + issubdtype + issubsctype + issubclass_ + find_common_type + +Miscellaneous +------------- +.. autosummary:: + :toctree: generated/ + + typename + sctype2char + mintypecode Added: numpy-docs/trunk/source/reference/routines.dual.rst =================================================================== --- numpy-docs/trunk/source/reference/routines.dual.rst 2008-10-26 17:50:36 UTC (rev 5958) +++ numpy-docs/trunk/source/reference/routines.dual.rst 2008-10-26 17:57:55 UTC (rev 5959) @@ -0,0 +1,48 @@ +Optionally Scipy-accelerated routines (:mod:numpy.dual) +********************************************************* + +.. automodule:: numpy.dual + +Linear algebra +-------------- + +.. currentmodule:: numpy.linalg + +.. autosummary:: + + cholesky + det + eig + eigh + eigvals + eigvalsh + inv + lstsq + norm + pinv + solve + svd + +FFT +--- + +.. currentmodule:: numpy.fft + +.. autosummary:: + + fft + fft2 + fftn + ifft + ifft2 + ifftn + +Other +----- + +.. currentmodule:: numpy + +.. autosummary:: + + i0 + Added: numpy-docs/trunk/source/reference/routines.emath.rst =================================================================== --- numpy-docs/trunk/source/reference/routines.emath.rst 2008-10-26 17:50:36 UTC (rev 5958) +++ numpy-docs/trunk/source/reference/routines.emath.rst 2008-10-26 17:57:55 UTC (rev 5959) @@ -0,0 +1,10 @@ +Mathematical functions with automatic domain (:mod:numpy.emath) +*********************************************************************** + +.. currentmodule:: numpy + +.. note:: :mod:numpy.emath is a preferred alias for :mod:numpy.lib.scimath, + available after :mod:numpy is imported. + +.. automodule:: numpy.lib.scimath + :members: Added: numpy-docs/trunk/source/reference/routines.err.rst =================================================================== --- numpy-docs/trunk/source/reference/routines.err.rst 2008-10-26 17:50:36 UTC (rev 5958) +++ numpy-docs/trunk/source/reference/routines.err.rst 2008-10-26 17:57:55 UTC (rev 5959) @@ -0,0 +1,25 @@ +Floating point error handling +***************************** + +.. currentmodule:: numpy + +Setting and getting error handling +---------------------------------- + +.. autosummary:: + :toctree: generated/ + + seterr + geterr + seterrcall + geterrcall + errstate + +Internal functions +------------------ + +.. autosummary:: + :toctree: generated/ + + seterrobj + geterrobj Added: numpy-docs/trunk/source/reference/routines.fft.rst =================================================================== --- numpy-docs/trunk/source/reference/routines.fft.rst 2008-10-26 17:50:36 UTC (rev 5958) +++ numpy-docs/trunk/source/reference/routines.fft.rst 2008-10-26 17:57:55 UTC (rev 5959) @@ -0,0 +1,59 @@ +.. _routines.fft: + +Fourier transforms (:mod:numpy.fft) +************************************* + +.. currentmodule:: numpy.fft + +1-dimensional +------------- +.. autosummary:: + :toctree: generated/ + + fft + ifft + +2-dimensional +------------- +.. autosummary:: + :toctree: generated/ + + fft2 + ifft2 + +N-dimensional +------------- +.. autosummary:: + :toctree: generated/ + + fftn + ifftn + +Hermite symmetric +----------------- +.. autosummary:: + :toctree: generated/ + + hfft + ihfft + +Real-valued +----------- +.. autosummary:: + :toctree: generated/ + + rfft + irfft + rfft2 + irfft2 + rfftn + irfftn + +Helper routines +--------------- +.. autosummary:: + :toctree: generated/ + + fftfreq + fftshift + ifftshift Added: numpy-docs/trunk/source/reference/routines.financial.rst =================================================================== --- numpy-docs/trunk/source/reference/routines.financial.rst 2008-10-26 17:50:36 UTC (rev 5958) +++ numpy-docs/trunk/source/reference/routines.financial.rst 2008-10-26 17:57:55 UTC (rev 5959) @@ -0,0 +1,21 @@ +Financial functions +******************* + +.. currentmodule:: numpy + +Simple financial functions +-------------------------- + +.. autosummary:: + :toctree: generated/ + + fv + pv + npv + pmt + ppmt + ipmt + irr + mirr + nper + rate Added: numpy-docs/trunk/source/reference/routines.functional.rst =================================================================== --- numpy-docs/trunk/source/reference/routines.functional.rst 2008-10-26 17:50:36 UTC (rev 5958) +++ numpy-docs/trunk/source/reference/routines.functional.rst 2008-10-26 17:57:55 UTC (rev 5959) @@ -0,0 +1,13 @@ +Functional programming +********************** + +.. currentmodule:: numpy + +.. autosummary:: + :toctree: generated/ + + apply_along_axis + apply_over_axes + vectorize + frompyfunc + piecewise Added: numpy-docs/trunk/source/reference/routines.help.rst =================================================================== --- numpy-docs/trunk/source/reference/routines.help.rst 2008-10-26 17:50:36 UTC (rev 5958) +++ numpy-docs/trunk/source/reference/routines.help.rst 2008-10-26 17:57:55 UTC (rev 5959) @@ -0,0 +1,24 @@ +.. _routines.help: + +Numpy-specific help functions +============================= + +.. currentmodule:: numpy + +Finding help +------------ + +.. autosummary:: + :toctree: generated/ + + lookfor + + +Reading help +------------ + +.. autosummary:: + :toctree: generated/ + + info + source Added: numpy-docs/trunk/source/reference/routines.indexing.rst =================================================================== --- numpy-docs/trunk/source/reference/routines.indexing.rst 2008-10-26 17:50:36 UTC (rev 5958) +++ numpy-docs/trunk/source/reference/routines.indexing.rst 2008-10-26 17:57:55 UTC (rev 5959) @@ -0,0 +1,53 @@ +.. _routines.indexing: + +Indexing routines +================= + +.. seealso:: :ref:Indexing <arrays.indexing> + +.. currentmodule:: numpy + +Generating index arrays +----------------------- +.. autosummary:: + :toctree: generated/ + + c_ + r_ + s_ + nonzero + where + indices + ix_ + ogrid + unravel_index + +Indexing-like operations +------------------------ +.. autosummary:: + :toctree: generated/ + + take + choose + compress + diag + diagonal + select + +Inserting data into arrays +-------------------------- +.. autosummary:: + :toctree: generated/ + + place + put + putmask + +Iterating over arrays +--------------------- +.. autosummary:: + :toctree: generated/ + + ndenumerate + ndindex + flatiter Added: numpy-docs/trunk/source/reference/routines.io.rst =================================================================== --- numpy-docs/trunk/source/reference/routines.io.rst 2008-10-26 17:50:36 UTC (rev 5958) +++ numpy-docs/trunk/source/reference/routines.io.rst 2008-10-26 17:57:55 UTC (rev 5959) @@ -0,0 +1,64 @@ +Input and output +**************** + +.. currentmodule:: numpy + +NPZ files +--------- +.. autosummary:: + :toctree: generated/ + + load + save + savez + +Text files +---------- +.. autosummary:: + :toctree: generated/ + + loadtxt + savetxt + fromregex + fromstring + ndarray.tofile + ndarray.tolist + +String formatting +----------------- +.. autosummary:: + :toctree: generated/ + + array_repr + array_str + +Memory mapping files +-------------------- +.. autosummary:: + :toctree: generated/ + + memmap + +Text formatting options +----------------------- +.. autosummary:: + :toctree: generated/ + + set_printoptions + get_printoptions + set_string_function + +Base-n representations +---------------------- +.. autosummary:: + :toctree: generated/ + + binary_repr + base_repr + +Data sources +------------ +.. autosummary:: + :toctree: generated/ + + DataSource Added: numpy-docs/trunk/source/reference/routines.linalg.rst =================================================================== --- numpy-docs/trunk/source/reference/routines.linalg.rst 2008-10-26 17:50:36 UTC (rev 5958) +++ numpy-docs/trunk/source/reference/routines.linalg.rst 2008-10-26 17:57:55 UTC (rev 5959) @@ -0,0 +1,67 @@ +.. _routines.linalg: + +Linear algebra (:mod:numpy.linalg) +************************************ + +.. currentmodule:: numpy + +Matrix and vector products +-------------------------- +.. autosummary:: + :toctree: generated/ + + dot + vdot + inner + outer + tensordot + linalg.matrix_power + kron + +Decompositions +-------------- +.. autosummary:: + :toctree: generated/ + + linalg.cholesky + linalg.qr + linalg.svd + +Matrix eigenvalues +------------------ +.. autosummary:: + :toctree: generated/ + + linalg.eig + linalg.eigh + linalg.eigvals + linalg.eigvalsh + +Norms and other numbers +----------------------- +.. autosummary:: + :toctree: generated/ + + linalg.norm + linalg.cond + linalg.det + trace + +Solving equations and inverting matrices +---------------------------------------- +.. autosummary:: + :toctree: generated/ + + linalg.solve + linalg.tensorsolve + linalg.lstsq + linalg.inv + linalg.pinv + linalg.tensorinv + +Exceptions +---------- +.. autosummary:: + :toctree: generated/ + + linalg.LinAlgError Added: numpy-docs/trunk/source/reference/routines.logic.rst =================================================================== --- numpy-docs/trunk/source/reference/routines.logic.rst 2008-10-26 17:50:36 UTC (rev 5958) +++ numpy-docs/trunk/source/reference/routines.logic.rst 2008-10-26 17:57:55 UTC (rev 5959) @@ -0,0 +1,64 @@ +Logic functions +*************** + +.. currentmodule:: numpy + +Truth value testing +------------------- +.. autosummary:: + :toctree: generated/ + + all + any + +Array contents +-------------- +.. autosummary:: + :toctree: generated/ + + isfinite + isinf + isnan + isneginf + isposinf + +Array type testing +------------------ +.. autosummary:: + :toctree: generated/ + + iscomplex + iscomplexobj + isfortran + isreal + isrealobj + isscalar + +Logical operations +------------------ +.. autosummary:: + :toctree: generated/ + + logical_and + logical_or + logical_not + logical_xor + +Comparison +---------- +.. autosummary:: + :toctree: generated/ + + allclose + array_equal + array_equiv + +.. autosummary:: + :toctree: generated/ + + greater + greater_equal + less + less_equal + equal + not_equal Added: numpy-docs/trunk/source/reference/routines.ma.rst =================================================================== --- numpy-docs/trunk/source/reference/routines.ma.rst 2008-10-26 17:50:36 UTC (rev 5958) +++ numpy-docs/trunk/source/reference/routines.ma.rst 2008-10-26 17:57:55 UTC (rev 5959) @@ -0,0 +1,52 @@ +.. _routines.ma: + +Masked array operations +*********************** + +.. currentmodule:: numpy + +Creation +-------- + +.. autosummary:: + :toctree: generated/ + + ma.masked_array + +Converting to ndarray +--------------------- + +.. autosummary:: + :toctree: generated/ + + ma.filled + ma.common_fill_value + ma.default_fill_value + ma.masked_array.get_fill_value + ma.maximum_fill_value + ma.minimum_fill_value + +Inspecting the array +-------------------- + +.. autosummary:: + :toctree: generated/ + + ma.getmask + ma.getmaskarray + ma.getdata + ma.count_masked + +Modifying the mask +------------------ + +.. autosummary:: + :toctree: generated/ + + ma.make_mask + ma.mask_cols + ma.mask_or + ma.mask_rowcols + ma.mask_rows + ma.harden_mask + ma.ids Added: numpy-docs/trunk/source/reference/routines.math.rst =================================================================== --- numpy-docs/trunk/source/reference/routines.math.rst 2008-10-26 17:50:36 UTC (rev 5958) +++ numpy-docs/trunk/source/reference/routines.math.rst 2008-10-26 17:57:55 UTC (rev 5959) @@ -0,0 +1,143 @@ +Mathematical functions +********************** + +.. currentmodule:: numpy + +Trigonometric functions +----------------------- +.. autosummary:: + :toctree: generated/ + + sin + cos + tan + arcsin + arccos + arctan + hypot + arctan2 + degrees + radians + unwrap + +Hyperbolic functions +-------------------- +.. autosummary:: + :toctree: generated/ + + sinh + cosh + tanh + arcsinh + arccosh + arctanh + +Rounding +-------- +.. autosummary:: + :toctree: generated/ + + around + round_ + rint + fix + floor + ceil + +Sums, products, differences +--------------------------- +.. autosummary:: + :toctree: generated/ + + prod + sum + nansum + cumprod + cumsum + diff + ediff1d + gradient + cross + trapz + +Exponents and logarithms +------------------------ +.. autosummary:: + :toctree: generated/ + + exp + expm1 + log + log10 + log2 + log1p + +Other special functions +----------------------- +.. autosummary:: + :toctree: generated/ + + i0 + sinc + +Floating point routines +----------------------- +.. autosummary:: + :toctree: generated/ + + signbit + frexp + ldexp + +Arithmetic operations +--------------------- +.. autosummary:: + :toctree: generated/ + + add + reciprocal + negative + multiply + divide + power + subtract + true_divide + floor_divide + + fmod + mod + modf + remainder + +Handling complex numbers +------------------------ +.. autosummary:: + :toctree: generated/ + + angle + real + imag + conj + + +Miscellaneous +------------- +.. autosummary:: + :toctree: generated/ + + convolve + clip + + sqrt + square + + absolute + fabs + sign + maximum + minimum + + nan_to_num + real_if_close + + interp Added: numpy-docs/trunk/source/reference/routines.matlib.rst =================================================================== --- numpy-docs/trunk/source/reference/routines.matlib.rst 2008-10-26 17:50:36 UTC (rev 5958) +++ numpy-docs/trunk/source/reference/routines.matlib.rst 2008-10-26 17:57:55 UTC (rev 5959) @@ -0,0 +1,11 @@ +Matrix library (:mod:numpy.matlib) +************************************ + +.. currentmodule:: numpy + +This module contains all functions in the :mod:numpy namespace, with +the following replacement functions that return :class:matrices +<matrix> instead of :class:ndarrays <ndarray>. + +.. automodule:: numpy.matlib + :members: Added: numpy-docs/trunk/source/reference/routines.numarray.rst =================================================================== --- numpy-docs/trunk/source/reference/routines.numarray.rst 2008-10-26 17:50:36 UTC (rev 5958) +++ numpy-docs/trunk/source/reference/routines.numarray.rst 2008-10-26 17:57:55 UTC (rev 5959) @@ -0,0 +1,6 @@ +********************************************** +Numarray compatibility (:mod:numpy.numarray) +********************************************** + +.. automodule:: numpy.numarray + :members: Added: numpy-docs/trunk/source/reference/routines.oldnumeric.rst =================================================================== --- numpy-docs/trunk/source/reference/routines.oldnumeric.rst 2008-10-26 17:50:36 UTC (rev 5958) +++ numpy-docs/trunk/source/reference/routines.oldnumeric.rst 2008-10-26 17:57:55 UTC (rev 5959) @@ -0,0 +1,8 @@ +*************************************************** +Old Numeric compatibility (:mod:numpy.oldnumeric) +*************************************************** + +.. currentmodule:: numpy + +.. automodule:: numpy.oldnumeric + :members: Added: numpy-docs/trunk/source/reference/routines.other.rst =================================================================== --- numpy-docs/trunk/source/reference/routines.other.rst 2008-10-26 17:50:36 UTC (rev 5958) +++ numpy-docs/trunk/source/reference/routines.other.rst 2008-10-26 17:57:55 UTC (rev 5959) @@ -0,0 +1,24 @@ +Miscellaneous routines +********************** + +.. toctree:: + +.. currentmodule:: numpy + +Buffer objects +-------------- +.. autosummary:: + :toctree: generated/ + + getbuffer + newbuffer + +Performance tuning +------------------ +.. autosummary:: + :toctree: generated/ + + alterdot + restoredot + setbufsize + getbufsize Added: numpy-docs/trunk/source/reference/routines.poly.rst =================================================================== --- numpy-docs/trunk/source/reference/routines.poly.rst 2008-10-26 17:50:36 UTC (rev 5958) +++ numpy-docs/trunk/source/reference/routines.poly.rst 2008-10-26 17:57:55 UTC (rev 5959) @@ -0,0 +1,46 @@ +Polynomials +*********** + +.. currentmodule:: numpy + +Basics +------ +.. autosummary:: + :toctree: generated/ + + poly1d + polyval + poly + roots + +Fitting +------- +.. autosummary:: + :toctree: generated/ + + polyfit + +Calculus +-------- +.. autosummary:: + :toctree: generated/ + + polyder + polyint + +Arithmetic +---------- +.. autosummary:: + :toctree: generated/ + + polyadd + polydiv + polymul + polysub + +Warnings +-------- +.. autosummary:: + :toctree: generated/ + + RankWarning Added: numpy-docs/trunk/source/reference/routines.random.rst =================================================================== --- numpy-docs/trunk/source/reference/routines.random.rst 2008-10-26 17:50:36 UTC (rev 5958) +++ numpy-docs/trunk/source/reference/routines.random.rst 2008-10-26 17:57:55 UTC (rev 5959) @@ -0,0 +1,77 @@ +.. _routines.random: + +Random sampling (:mod:numpy.random) +************************************* + +.. currentmodule:: numpy.random + +Simple random data +================== +.. autosummary:: + :toctree: generated/ + + rand + randn + randint + random_integers + random_sample + bytes + +Permutations +============ +.. autosummary:: + :toctree: generated/ + + shuffle + permutation + +Distributions +============= +.. autosummary:: + :toctree: generated/ + + beta + binomial + chisquare + mtrand.dirichlet + exponential + f + gamma + geometric + gumbel + hypergeometric + laplace + logistic + lognormal + logseries + multinomial + multivariate_normal + negative_binomial + noncentral_chisquare + noncentral_f + normal + pareto + poisson + power + rayleigh + standard_cauchy + standard_exponential + standard_gamma + standard_normal + standard_t + triangular + uniform + vonmises + wald + weibull + zipf + +Random generator +================ +.. autosummary:: + :toctree: generated/ + + mtrand.RandomState + seed + get_state + set_state Added: numpy-docs/trunk/source/reference/routines.rst =================================================================== --- numpy-docs/trunk/source/reference/routines.rst 2008-10-26 17:50:36 UTC (rev 5958) +++ numpy-docs/trunk/source/reference/routines.rst 2008-10-26 17:57:55 UTC (rev 5959) @@ -0,0 +1,35 @@ +******** +Routines +******** + +.. toctree:: + :maxdepth: 2 + + routines.array-creation + routines.array-manipulation + routines.indexing + routines.dtype + routines.io + routines.fft + routines.linalg + routines.random + routines.sort + routines.logic + routines.bitwise + routines.statistics + routines.math + routines.functional + routines.poly + routines.financial + routines.set + routines.window + routines.err + routines.ma + routines.help + routines.other + routines.emath + routines.matlib + routines.dual + routines.numarray + routines.oldnumeric + routines.ctypeslib Added: numpy-docs/trunk/source/reference/routines.set.rst =================================================================== --- numpy-docs/trunk/source/reference/routines.set.rst 2008-10-26 17:50:36 UTC (rev 5958) +++ numpy-docs/trunk/source/reference/routines.set.rst 2008-10-26 17:57:55 UTC (rev 5959) @@ -0,0 +1,23 @@ +Set routines +============ + +.. currentmodule:: numpy + +Making proper sets +------------------ +.. autosummary:: + :toctree: generated/ + + unique1d + +Boolean operations +------------------ +.. autosummary:: + :toctree: generated/ + + intersect1d + intersect1d_nu + setdiff1d + setmember1d + setxor1d + union1d Added: numpy-docs/trunk/source/reference/routines.sort.rst =================================================================== --- numpy-docs/trunk/source/reference/routines.sort.rst 2008-10-26 17:50:36 UTC (rev 5958) +++ numpy-docs/trunk/source/reference/routines.sort.rst 2008-10-26 17:57:55 UTC (rev 5959) @@ -0,0 +1,32 @@ +Sorting and searching +===================== + +.. currentmodule:: numpy + +Sorting +------- +.. autosummary:: + :toctree: generated/ + + sort + lexsort + argsort + ndarray.sort + msort + sort_complex + +Searching +--------- +.. autosummary:: + :toctree: generated/ + + argmax + nanargmax + argmin + nanargmin + argwhere + nonzero + flatnonzero + where + searchsorted + extract Added: numpy-docs/trunk/source/reference/routines.statistics.rst =================================================================== --- numpy-docs/trunk/source/reference/routines.statistics.rst 2008-10-26 17:50:36 UTC (rev 5958) +++ numpy-docs/trunk/source/reference/routines.statistics.rst 2008-10-26 17:57:55 UTC (rev 5959) @@ -0,0 +1,51 @@ +Statistics +========== + +.. currentmodule:: numpy + + +Extremal values +--------------- + +.. autosummary:: + :toctree: generated/ + + amin + amax + nanmax + nanmin + ptp + +Averages and variances +---------------------- + +.. autosummary:: + :toctree: generated/ + + average + mean + median + std + var + +Correlating +----------- + +.. autosummary:: + :toctree: generated/ + + corrcoef + correlate + cov + +Histograms +---------- + +.. autosummary:: + :toctree: generated/ + + histogram + histogram2d + histogramdd + bincount + digitize Added: numpy-docs/trunk/source/reference/routines.window.rst =================================================================== --- numpy-docs/trunk/source/reference/routines.window.rst 2008-10-26 17:50:36 UTC (rev 5958) +++ numpy-docs/trunk/source/reference/routines.window.rst 2008-10-26 17:57:55 UTC (rev 5959) @@ -0,0 +1,16 @@ +Window functions +================ + +.. currentmodule:: numpy + +Various windows +--------------- + +.. autosummary:: + :toctree: generated/ + + bartlett + blackman + hamming + hanning + kaiser Added: numpy-docs/trunk/source/reference/ufuncs.rst =================================================================== --- numpy-docs/trunk/source/reference/ufuncs.rst 2008-10-26 17:50:36 UTC (rev 5958) +++ numpy-docs/trunk/source/reference/ufuncs.rst 2008-10-26 17:57:55 UTC (rev 5959) @@ -0,0 +1,551 @@ +.. sectionauthor:: adapted from "Guide to Numpy" by Travis E. Oliphant + +.. _ufuncs: + +************************************ +Universal functions (:class:ufunc) +************************************ + +.. note: XXX: section might need to be made more reference-guideish... + +.. currentmodule:: numpy + +.. index: ufunc, universal function, arithmetic, operation + +A universal function (or :term:ufunc for short) is a function that +operates on :class:ndarrays <ndarray> in an element-by-element fashion, +supporting :ref:array broadcasting <ufuncs.broadcasting>, :ref:type +casting <ufuncs.casting>, and several other standard features. That +is, a ufunc is a ":term:vectorized" wrapper for a function that +takes a fixed number of scalar inputs and produces a fixed number of +scalar outputs. + +In Numpy, universal functions are instances of the +:class:numpy.ufunc class. Many of the built-in functions are +implemented in compiled C code, but :class:ufunc instances can also +be produced using the :func:frompyfunc factory function. + + +.. _ufuncs.broadcasting: + +Broadcasting +============ + +.. index:: broadcasting + +Each universal function takes array inputs and produces array outputs +by performing the core function element-wise on the inputs. Standard +broadcasting rules are applied so that inputs not sharing exactly the +same shapes can still be usefully operated on. Broadcasting can be +understood by four rules: + +1. All input arrays with :attr:ndim <ndarray.ndim> smaller than the + input array of largest :attr:ndim <ndarray.ndim> have 1's + prepended to their shapes. + +2. The size in each dimension of the output shape is the maximum of all + the input shapes in that dimension. + +3. An input can be used in the calculation if it's shape in a particular + dimension either matches the output shape or has value exactly 1. + +4. If an input has a dimension size of 1 in its shape, the first data + entry in that dimension will be used for all calculations along + that dimension. In other words, the stepping machinery of the + :term:ufunc will simply not step along that dimension when + otherwise needed (the :term:stride will be 0 for that dimension). + +Broadcasting is used throughout NumPy to decide how to handle non +equally-shaped arrays; for example all arithmetic operators (+, +-, *, ...) between :class:ndarrays <ndarray> broadcast the +arrays before operation. + +.. _arrays.broadcasting.broadcastable: + +.. index:: broadcastable + +A set of arrays is called ":term:broadcastable" to the same shape if +the above rules produce a valid result, *i.e.*, one of the following +is true: + +1. The arrays all have exactly the same shape. + +2. The arrays all have the same number of dimensions and the length of + each dimensions is either a common length or 1. + +3. The arrays that have too few dimensions can have their shapes prepended + with a dimension of length 1 to satisfy property 2. + +.. admonition:: Example + + If a.shape is (5,1), b.shape is (1,6), c.shape is (6,) + and d.shape is () so that d is a scalar, then *a*, *b*, *c*, + and *d* are all broadcastable to dimension (5,6); and + + - *a* acts like a (5,6) array where a[:,0] is broadcast to the other + columns, + + - *b* acts like a (5,6) array where b[0,:] is broadcast + to the other rows, + + - *c* acts like a (1,6) array and therefore like a (5,6) array + where c[:] is broadcast to every row, and finally, + + - *d* acts like a (5,6) array where the single value is repeated. + + +.. _ufuncs.output-type: + +Output type determination +========================= + +The output of the ufunc (and its methods) is not necessarily an +:class:ndarray, if all input arguments are not :class:ndarrays <ndarray>. + +All output arrays will be passed to the :obj:__array_wrap__ +method of the input (besides :class:ndarrays <ndarray>, and scalars) +that defines it **and** has the highest :obj:__array_priority__ of +any other input to the universal function. The default +:obj:__array_priority__ of the ndarray is 0.0, and the default +:obj:__array_priority__ of a subtype is 1.0. Matrices have +:obj:__array_priority__ equal to 10.0. + +The ufuncs can also all take output arguments. The output will be cast +if necessary to the provided output array. If a class with an +:obj:__array__ method is used for the output, results will be +written to the object returned by :obj:__array__. Then, if the class +also has an :obj:__array_wrap__ method, the returned +:class:ndarray result will be passed to that method just before +passing control back to the caller. + +Use of internal buffers +======================= + +.. index:: buffers + +Internally, buffers are used for misaligned data, swapped data, and +data that has to be converted from one data type to another. The size +of the internal buffers is settable on a per-thread basis. There can +be up to :math:2 (n_{\mathrm{inputs}} + n_{\mathrm{outputs}}) +buffers of the specified size created to handle the data from all the +inputs and outputs of a ufunc. The default size of the buffer is +10,000 elements. Whenever buffer-based calculation would be needed, +but all input arrays are smaller than the buffer size, those +misbehaved or incorrect typed arrays will be copied before the +calculation proceeds. Adjusting the size of the buffer may therefore +alter the speed at which ufunc calculations of various sorts are +completed. A simple interface for setting this variable is accessible +using the function + +.. autosummary:: + :toctree: generated/ + + setbufsize + + +Error handling +============== + +.. index:: error handling + +Universal functions can trip special floating point status registers +in your hardware (such as divide-by-zero). If available on your +platform, these registers will be regularly checked during +calculation. Error handling is controlled on a per-thread basis, +and can be configured using the functions + +.. autosummary:: + :toctree: generated/ + + seterr + seterrcall + +.. _ufuncs.casting: + +Casting Rules +============= + +.. index:: + pair: ufunc; casting rules + +At the core of every ufunc is a one-dimensional strided loop that +implements the actual function for a specific type combination. When a +ufunc is created, it is given a static list of inner loops and a +corresponding list of type signatures over which the ufunc operates. +The ufunc machinery uses this list to determine which inner loop to +use for a particular case. You can inspect the :attr:.types +<ufunc.types> attribute for a particular ufunc to see which type +combinations have a defined inner loop and which output type they +produce (:ref:character codes <arrays.scalars.character-codes> are used in +that output for brevity). + +Casting must be done on one or more of the inputs whenever the ufunc +does not have a core loop implementation for the input types provided. +If an implementation for the input types cannot be found, then the +algorithm searches for an implementation with a type signature to +which all of the inputs can be cast "safely." The first one it finds +in its internal list of loops is selected and performed with types +cast. Recall that internal copies during ufuncs (even for casting) are +limited to the size of an internal buffer which is user settable. + +.. note:: + + Universal functions in NumPy are flexible enough to have mixed type + signatures. Thus, for example, a universal function could be defined + that works with floating point and integer values. See :func:ldexp + for an example. + +By the above description, the casting rules are essentially +implemented by the question of when a data type can be cast "safely" +to another data type. The answer to this question can be determined in +Python with a function call: :func:can_cast(fromtype, totype) +<can_cast>. Figure shows the results of this call for my 32-bit +system on the 21 internally supported types. You can generate this +table for your system with code shown in that Figure. + +.. admonition:: Figure + + Code segment showing the can cast safely table for a 32-bit system. + + >>> def print_table(ntypes): + ... print 'X', + ... for char in ntypes: print char, + ... print + ... for row in ntypes: + ... print row, + ... for col in ntypes: + ... print int(np.can_cast(row, col)), + ... print + >>> print_table(np.typecodes['All']) + X ? b h i l q p B H I L Q P f d g F D G S U V O + ? 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + b 0 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 + h 0 0 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 + i 0 0 0 1 1 1 1 0 0 0 0 0 0 0 1 1 0 1 1 1 1 1 1 + l 0 0 0 1 1 1 1 0 0 0 0 0 0 0 1 1 0 1 1 1 1 1 1 + q 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 1 0 1 1 1 1 1 1 + p 0 0 0 1 1 1 1 0 0 0 0 0 0 0 1 1 0 1 1 1 1 1 1 + B 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + H 0 0 0 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + I 0 0 0 0 0 1 0 0 0 1 1 1 1 0 1 1 0 1 1 1 1 1 1 + L 0 0 0 0 0 1 0 0 0 1 1 1 1 0 1 1 0 1 1 1 1 1 1 + Q 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 1 1 1 1 1 1 + P 0 0 0 0 0 1 0 0 0 1 1 1 1 0 1 1 0 1 1 1 1 1 1 + f 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 + d 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 1 1 1 1 1 + g 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 1 1 1 + F 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 + D 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 + G 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 + S 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 + U 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 + V 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 + O 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 + +You should note that, while included in the table for completeness, +the 'S', 'U', and 'V' types cannot be operated on by ufuncs. Also, +note that on a 64-bit system the integer types may have different +sizes resulting in a slightly altered table. + +Mixed scalar-array operations use a different set of casting rules +that ensure that a scalar cannot upcast an array unless the scalar is +of a fundamentally different kind of data (*i.e.* under a different +hierachy in the data type hierarchy) than the array. This rule +enables you to use scalar constants in your code (which as Python +types are interpreted accordingly in ufuncs) without worrying about +whether the precision of the scalar constant will cause upcasting on +your large (small precision) array. + + +:class:ufunc +============== + +Optional keyword arguments +-------------------------- + +All ufuncs take optional keyword arguments. These represent rather +advanced usage and will likely not be used by most users. + +.. index:: + pair: ufunc; keyword arguments + +*sig* + + Either a data-type, a tuple of data-types, or a special signature + string indicating the input and output types of a ufunc. This argument + allows you to specify a specific signature for a the 1-d loop to use + in the underlying calculation. If the loop specified does not exist + for the ufunc, then a TypeError is raised. Normally a suitable loop is + found automatically by comparing the input types with what is + available and searching for a loop with data-types to which all inputs + can be cast safely. This key-word argument lets you by-pass that + search and choose a loop you want. A list of available signatures is + available in the **types** attribute of the ufunc object. + +*extobj* + + a list of length 1, 2, or 3 specifying the ufunc buffer-size, the + error mode integer, and the error call-back function. Normally, these + values are looked-up in a thread-specific dictionary. Passing them + here bypasses that look-up and uses the low-level specification + provided for the error-mode. This may be useful as an optimization for + calculations requiring lots of ufuncs on small arrays in a loop. + + +Attributes +---------- + +There are some informational attributes that universal functions +possess. None of the attributes can be set. + +.. index:: + pair: ufunc; attributes + + +============ ================================================================= +**__doc__** A docstring for each ufunc. The first part of the docstring is + dynamically generated from the number of outputs, the name, and + the number of inputs. The second part of the doc string is + provided at creation time and stored with the ufunc. + +**__name__** The name of the ufunc. +============ ================================================================= + +.. autosummary:: + :toctree: generated/ + + ufunc.nin + ufunc.nout + ufunc.nargs + ufunc.ntypes + ufunc.types + ufunc.identity + +Methods +------- + +All ufuncs have 4 methods. However, these methods only make sense on +ufuncs that take two input arguments and return one output argument. +Attempting to call these methods on other ufuncs will cause a +:exc:ValueError . The reduce-like methods all take an *axis* keyword +and a *dtype* keyword, and the arrays must all have dimension >= +1. The *axis* keyword specifies which axis of the array the reduction +will take place over and may be negative, but must be an integer. The +*dtype* keyword allows you to manage a very common problem that arises +when naively using {op}.reduce <ufunc.reduce>. Sometimes you may +have an array of a certain data type and wish to add up all of its +elements, but the result does not fit into the data type of the +array. This commonly happens if you have an array of single-byte +integers. The *dtype* keyword allows you to alter the data type that the +reduction takes place over (and therefore the type of the +output). Thus, you can ensure that the output is a data type with +large-enough precision to handle your output. The responsibility of +altering the reduce type is mostly up to you. There is one exception: +if no *dtype* is given for a reduction on the "add" or "multiply" +operations, then if the input type is an integer (or boolean) data- +type and smaller than the size of the :class:int_ data type, it will +be internally upcast to the :class:int_ (or :class:uint) data +type. + +.. index:: + pair: ufunc; methods + +.. autosummary:: + :toctree: generated/ + + ufunc.reduce + ufunc.accumulate + ufunc.reduceat + ufunc.outer + + +.. warning:: + + A reduce-like operation on an array with a data type that has + range "too small "to handle the result will silently wrap. You + should use dtype to increase the data type over which reduction + takes place. + + +Available ufuncs +================ + +There are currently more than 60 universal functions defined in +:mod:numpy on one or more types, covering a wide variety of +operations. Some of these ufuncs are called automatically on arrays +when the relevant infix notation is used (*e.g.* :func:add(a, b) <add> +is called internally when a + b is written and *a* or *b* is an +:class:ndarray). Nonetheless, you may still want to use the ufunc +call in order to use the optional output argument(s) to place the +output(s) in an object (or in objects) of your choice. + +Recall that each ufunc operates element-by-element. Therefore, each +ufunc will be described as if acting on a set of scalar inputs to +return a set of scalar outputs. + +.. note:: + + The ufunc still returns its output(s) even if you use the optional + output argument(s). + +Math operations +--------------- + +.. autosummary:: + + add + subtract + multiply + divide + true_divide + floor_divide + negative + power + remainder + mod + fmod + absolute + rint + sign + conj + exp + log + expm1 + log1p + log10 + sqrt + square + reciprocal + ones_like + +.. tip:: + + The optional output arguments can be used to help you save memory + for large calculations. If your arrays are large, complicated + expressions can take longer than absolutely necessary due to the + creation and (later) destruction of temporary calculation + spaces. For example, the expression G=a*b+c is equivalent to + t1=A*B; G=T1+C; del t1. It will be more quickly executed as + G=A*B; add(G,C,G) which is the same as G=A*B; G+=C. + + +Trigonometric functions +----------------------- +All trigonometric functions use radians when an angle is called for. +The ratio of degrees to radians is :math:180^{\circ}/\pi. + +.. autosummary:: + + sin + cos + tan + arcsin + arccos + arctan + arctan2 + hypot + sinh + cosh + tanh + arcsinh + arccosh + arctanh + +Bit-twiddling functions +----------------------- + +These function all need integer arguments and they maniuplate the bit- +pattern of those arguments. + +.. autosummary:: + + bitwise_and + bitwise_or + bitwise_xor + invert + left_shift + right_shift + +Comparison functions +-------------------- + +.. autosummary:: + + greater + greater_equal + less + less_equal + not_equal + equal + +.. warning:: + + Do not use the Python keywords and and or to combine + logical array expressions. These keywords will test the truth + value of the entire array (not element-by-element as you might + expect). Use the bitwise operators: & and \| instead. + +.. autosummary:: + + logical_and + logical_or + logical_xor + logical_not + +.. warning:: + + The Bitwise operators (& and \|) are the proper way to combine + element-by-element array comparisons. Be sure to understand the + operator precedence: (a>2) & (a<5) is the proper syntax because a>2 & + a<5 will result in an error due to the fact that 2 & a is evaluated + first. + +.. autosummary:: + + maximum + +.. tip:: + + The Python function max() will find the maximum over a one-dimensional + array, but it will do so using a slower sequence interface. The reduce + method of the maximum ufunc is much faster. Also, the max() method + will not give answers you might expect for arrays with greater than + one dimension. The reduce method of minimum also allows you to compute + a total minimum over an array. + +.. autosummary:: + + minimum + +.. warning:: + + the behavior of maximum(a,b) is than that of max(a,b). As a ufunc, + maximum(a,b) performs an element-by-element comparison of a and b and + chooses each element of the result according to which element in the + two arrays is larger. In contrast, max(a,b) treats the objects a and b + as a whole, looks at the (total) truth value of a>b and uses it to + return either a or b (as a whole). A similar difference exists between + minimum(a,b) and min(a,b). + + +Floating functions +------------------ + +Recall that all of these functions work element-by-element over an +array, returning an array output. The description details only a +single operation. + +.. autosummary:: + + isreal + iscomplex + isfinite + isinf + isnan + signbit + modf + ldexp + frexp + fmod + floor + ceil Added: numpy-docs/trunk/source/scipyshiny_small.png =================================================================== (Binary files differ) Property changes on: numpy-docs/trunk/source/scipyshiny_small.png ___________________________________________________________________ Name: svn:mime-type + image/png Added: numpy-docs/trunk/source/user/basics.broadcasting.rst =================================================================== --- numpy-docs/trunk/source/user/basics.broadcasting.rst 2008-10-26 17:50:36 UTC (rev 5958) +++ numpy-docs/trunk/source/user/basics.broadcasting.rst 2008-10-26 17:57:55 UTC (rev 5959) @@ -0,0 +1,7 @@ +************ +Broadcasting +************ + +.. seealso:: :class:numpy.broadcast + +.. automodule:: numpy.doc.broadcasting Added: numpy-docs/trunk/source/user/basics.creation.rst =================================================================== --- numpy-docs/trunk/source/user/basics.creation.rst 2008-10-26 17:50:36 UTC (rev 5958) +++ numpy-docs/trunk/source/user/basics.creation.rst 2008-10-26 17:57:55 UTC (rev 5959) @@ -0,0 +1,9 @@ +.. _arrays.creation: + +************** +Array creation +************** + +.. seealso:: :ref:Array creation routines <routines.array-creation> + +.. automodule:: numpy.doc.creation Added: numpy-docs/trunk/source/user/basics.indexing.rst =================================================================== --- numpy-docs/trunk/source/user/basics.indexing.rst 2008-10-26 17:50:36 UTC (rev 5958) +++ numpy-docs/trunk/source/user/basics.indexing.rst 2008-10-26 17:57:55 UTC (rev 5959) @@ -0,0 +1,16 @@ +.. _basics.indexing: + +******** +Indexing +******** + +.. seealso:: :ref:Indexing routines <routines.indexing> + +.. note:: + + XXX: Combine numpy.doc.indexing with material + section 2.2 Basic indexing? + Or incorporate the material directly here? + + +.. automodule:: numpy.doc.indexing Added: numpy-docs/trunk/source/user/basics.rec.rst =================================================================== --- numpy-docs/trunk/source/user/basics.rec.rst 2008-10-26 17:50:36 UTC (rev 5958) +++ numpy-docs/trunk/source/user/basics.rec.rst 2008-10-26 17:57:55 UTC (rev 5959) @@ -0,0 +1,5 @@ +*************************************** +Structured arrays (aka "Record arrays") +*************************************** + +.. automodule:: numpy.doc.structured_arrays Added: numpy-docs/trunk/source/user/basics.rst =================================================================== --- numpy-docs/trunk/source/user/basics.rst 2008-10-26 17:50:36 UTC (rev 5958) +++ numpy-docs/trunk/source/user/basics.rst 2008-10-26 17:57:55 UTC (rev 5959) @@ -0,0 +1,17 @@ +************ +Numpy basics +************ + +.. note:: + + XXX: there is overlap between this text extracted from numpy.doc + and "Guide to Numpy" chapter 2. Needs combining? + +.. toctree:: + + basics.types + basics.creation + basics.indexing + basics.broadcasting + basics.rec + basics.subclassing Added: numpy-docs/trunk/source/user/basics.subclassing.rst =================================================================== --- numpy-docs/trunk/source/user/basics.subclassing.rst 2008-10-26 17:50:36 UTC (rev 5958) +++ numpy-docs/trunk/source/user/basics.subclassing.rst 2008-10-26 17:57:55 UTC (rev 5959) @@ -0,0 +1,7 @@ +.. _basics.subclassing: + +******************* +Subclassing ndarray +******************* + +.. automodule:: numpy.doc.subclassing Added: numpy-docs/trunk/source/user/basics.types.rst =================================================================== --- numpy-docs/trunk/source/user/basics.types.rst 2008-10-26 17:50:36 UTC (rev 5958) +++ numpy-docs/trunk/source/user/basics.types.rst 2008-10-26 17:57:55 UTC (rev 5959) @@ -0,0 +1,14 @@ +********** +Data types +********** + +.. seealso:: :ref:Data type objects <arrays.dtypes> + +.. note:: + + XXX: Combine numpy.doc.indexing with material from + "Guide to Numpy" (section 2.1 Data-Type descriptors)? + Or incorporate the material directly here? + + +.. automodule:: numpy.doc.basics Added: numpy-docs/trunk/source/user/c-info.beyond-basics.rst =================================================================== --- numpy-docs/trunk/source/user/c-info.beyond-basics.rst 2008-10-26 17:50:36 UTC (rev 5958) +++ numpy-docs/trunk/source/user/c-info.beyond-basics.rst 2008-10-26 17:57:55 UTC (rev 5959) @@ -0,0 +1,734 @@ +***************** +Beyond the Basics +***************** + +| The voyage of discovery is not in seeking new landscapes but in having +| new eyes. +| --- *Marcel Proust* + +| Discovery is seeing what everyone else has seen and thinking what no +| one else has thought. +| --- *Albert Szent-Gyorgi* + + +Iterating over elements in the array +==================================== + +.. _sec:array_iterator: + +Basic Iteration +--------------- + +One common algorithmic requirement is to be able to walk over all +elements in a multidimensional array. The array iterator object makes +this easy to do in a generic way that works for arrays of any +dimension. Naturally, if you know the number of dimensions you will be +using, then you can always write nested for loops to accomplish the +iteration. If, however, you want to write code that works with any +number of dimensions, then you can make use of the array iterator. An +array iterator object is returned when accessing the .flat attribute +of an array. + +.. index:: + single: array iterator + +Basic usage is to call :cfunc:PyArray_IterNew ( array ) where array +is an ndarray object (or one of its sub-classes). The returned object +is an array-iterator object (the same object returned by the .flat +attribute of the ndarray). This object is usually cast to +PyArrayIterObject* so that its members can be accessed. The only +members that are needed are iter->size which contains the total +size of the array, iter->index, which contains the current 1-d +index into the array, and iter->dataptr which is a pointer to the +data for the current element of the array. Sometimes it is also +useful to access iter->ao which is a pointer to the underlying +ndarray object. + +After processing data at the current element of the array, the next +element of the array can be obtained using the macro +:cfunc:PyArray_ITER_NEXT ( iter ). The iteration always proceeds in a +C-style contiguous fashion (last index varying the fastest). The +:cfunc:PyArray_ITER_GOTO ( iter, destination ) can be used to +jump to a particular point in the array, where destination is an +array of npy_intp data-type with space to handle at least the number +of dimensions in the underlying array. Occasionally it is useful to +use :cfunc:PyArray_ITER_GOTO1D ( iter, index ) which will jump +to the 1-d index given by the value of index. The most common +usage, however, is given in the following example. + +.. code-block:: c + + PyObject *obj; /* assumed to be some ndarray object */ + PyArrayIterObject *iter; + ... + iter = (PyArrayIterObject *)PyArray_IterNew(obj); + if (iter == NULL) goto fail; /* Assume fail has clean-up code */ + while (iter->index < iter->size) { + /* do something with the data at it->dataptr */ + PyArray_ITER_NEXT(it); + } + ... + +You can also use :cfunc:PyArrayIter_Check ( obj ) to ensure you have +an iterator object and :cfunc:PyArray_ITER_RESET ( iter ) to reset an +iterator object back to the beginning of the array. + +It should be emphasized at this point that you may not need the array +iterator if your array is already contiguous (using an array iterator +will work but will be slower than the fastest code you could write). +The major purpose of array iterators is to encapsulate iteration over +N-dimensional arrays with arbitrary strides. They are used in many, +many places in the NumPy source code itself. If you already know your +array is contiguous (Fortran or C), then simply adding the element- +size to a running pointer variable will step you through the array +very efficiently. In other words, code like this will probably be +faster for you in the contiguous case (assuming doubles). + +.. code-block:: c + + npy_intp size; + double *dptr; /* could make this any variable type */ + size = PyArray_SIZE(obj); + dptr = PyArray_DATA(obj); + while(size--) { + /* do something with the data at dptr */ + dptr++; + } + + +Iterating over all but one axis +------------------------------- + +A common algorithm is to loop over all elements of an array and +perform some function with each element by issuing a function call. As +function calls can be time consuming, one way to speed up this kind of +algorithm is to write the function so it takes a vector of data and +then write the iteration so the function call is performed for an +entire dimension of data at a time. This increases the amount of work +done per function call, thereby reducing the function-call over-head +to a small(er) fraction of the total time. Even if the interior of the +loop is performed without a function call it can be advantageous to +perform the inner loop over the dimension with the highest number of +elements to take advantage of speed enhancements available on micro- +processors that use pipelining to enhance fundmental operations. + +The :cfunc:PyArray_IterAllButAxis ( array, &dim ) constructs an +iterator object that is modified so that it will not iterate over the +dimension indicated by dim. The only restriction on this iterator +object, is that the :cfunc:PyArray_Iter_GOTO1D ( it, ind ) macro +cannot be used (thus flat indexing won't work either if you pass this +object back to Python --- so you shouldn't do this). Note that the +returned object from this routine is still usually cast to +PyArrayIterObject \*. All that's been done is to modify the strides +and dimensions of the returned iterator to simulate iterating over +array[...,0,...] where 0 is placed on the +:math:\textrm{dim}^{\textrm{th}} dimension. If dim is negative, then +the dimension with the largest axis is found and used. + + +Iterating over multiple arrays +------------------------------ + +Very often, it is desireable to iterate over several arrays at the +same time. The universal functions are an example of this kind of +behavior. If all you want to do is iterate over arrays with the same +shape, then simply creating several iterator objects is the standard +procedure. For example, the following code iterates over two arrays +assumed to be the same shape and size (actually obj1 just has to have +at least as many total elements as does obj2): + +.. code-block:: c + + /* It is already assumed that obj1 and obj2 + are ndarrays of the same shape and size. + */ + iter1 = (PyArrayIterObject *)PyArray_IterNew(obj1); + if (iter1 == NULL) goto fail; + iter2 = (PyArrayIterObject *)PyArray_IterNew(obj2); + if (iter2 == NULL) goto fail; /* assume iter1 is DECREF'd at fail */ + while (iter2->index < iter2->size) { + /* process with iter1->dataptr and iter2->dataptr */ + PyArray_ITER_NEXT(iter1); + PyArray_ITER_NEXT(iter2); + } + + +Broadcasting over multiple arrays +--------------------------------- + +.. index:: + single: broadcasting + +When multiple arrays are involved in an operation, you may want to use the same +broadcasting rules that the math operations ( *i.e.* the ufuncs) use. This can +be done easily using the :ctype:PyArrayMultiIterObject. This is the object +returned from the Python command numpy.broadcast and it is almost as easy to +use from C. The function :cfunc:PyArray_MultiIterNew ( n, ... ) is +used (with n input objects in place of ... ). The input objects can be +arrays or anything that can be converted into an array. A pointer to a +PyArrayMultiIterObject is returned. Broadcasting has already been accomplished +which adjusts the iterators so that all that needs to be done to advance to the +next element in each array is for PyArray_ITER_NEXT to be called for each of +the inputs. This incrementing is automatically performed by +:cfunc:PyArray_MultiIter_NEXT ( obj ) macro (which can handle a +multiterator obj as either a :ctype:PyArrayMultiObject * or a +:ctype:PyObject *). The data from input number i is available using +:cfunc:PyArray_MultiIter_DATA ( obj, i ) and the total (broadcasted) +size as :cfunc:PyArray_MultiIter_SIZE ( obj). An example of using this +feature follows. + +.. code-block:: c + + mobj = PyArray_MultiIterNew(2, obj1, obj2); + size = PyArray_MultiIter_SIZE(obj); + while(size--) { + ptr1 = PyArray_MultiIter_DATA(mobj, 0); + ptr2 = PyArray_MultiIter_DATA(mobj, 1); + /* code using contents of ptr1 and ptr2 */ + PyArray_MultiIter_NEXT(mobj); + } + +The function :cfunc:PyArray_RemoveLargest ( multi ) can be used to +take a multi-iterator object and adjust all the iterators so that +iteration does not take place over the largest dimension (it makes +that dimension of size 1). The code being looped over that makes use +of the pointers will very-likely also need the strides data for each +of the iterators. This information is stored in +multi->iters[i]->strides. + +.. index:: + single: array iterator + +There are several examples of using the multi-iterator in the NumPy +source code as it makes N-dimensional broadcasting-code very simple to +write. Browse the source for more examples. + +.. _sec:Creating-a-new: + +Creating a new universal function +================================= + +.. index:: + pair: ufunc; adding new + +The umath module is a computer-generated C-module that creates many +ufuncs. It provides a great many examples of how to create a universal +function. Creating your own ufunc that will make use of the ufunc +machinery is not difficult either. Suppose you have a function that +you want to operate element-by-element over its inputs. By creating a +new ufunc you will obtain a function that handles + +- broadcasting + +- N-dimensional looping + +- automatic type-conversions with minimal memory usage + +- optional output arrays + +It is not difficult to create your own ufunc. All that is required is +a 1-d loop for each data-type you want to support. Each 1-d loop must +have a specific signature, and only ufuncs for fixed-size data-types +can be used. The function call used to create a new ufunc to work on +built-in data-types is given below. A different mechanism is used to +register ufuncs for user-defined data-types. + +.. cfunction:: PyObject *PyUFunc_FromFuncAndData( PyUFuncGenericFunction* func, void** data, char* types, int ntypes, int nin, int nout, int identity, char* name, char* doc, int check_return) + + *func* + + A pointer to an array of 1-d functions to use. This array must be at + least ntypes long. Each entry in the array must be a PyUFuncGenericFunction function. This function has the following signature. An example of a + valid 1d loop function is also given. + + .. cfunction:: void loop1d(char** args, npy_intp* dimensions, npy_intp* steps, void* data) + + *args* + + An array of pointers to the actual data for the input and output + arrays. The input arguments are given first followed by the output + arguments. + + *dimensions* + + A pointer to the size of the dimension over which this function is + looping. + + *steps* + + A pointer to the number of bytes to jump to get to the + next element in this dimension for each of the input and + output arguments. + + *data* + + Arbitrary data (extra arguments, function names, *etc.* ) + that can be stored with the ufunc and will be passed in + when it is called. + + .. code-block:: c + + static void + double_add(char *args, npy_intp *dimensions, npy_intp *steps, void *extra) + { + npy_intp i; + npy_intp is1=steps[0], is2=steps[1]; + npy_intp os=steps[2], n=dimensions[0]; + char *i1=args[0], *i2=args[1], *op=args[2]; + for (i=0; i<n; i++) { + *((double *)op) = *((double *)i1) + \ + *((double *)i2); + i1 += is1; i2 += is2; op += os; + } + } + + *data* + + An array of data. There should be ntypes entries (or NULL) --- one for + every loop function defined for this ufunc. This data will be passed + in to the 1-d loop. One common use of this data variable is to pass in + an actual function to call to compute the result when a generic 1-d + loop (e.g. :cfunc:PyUFunc_d_d) is being used. + + *types* + + An array of type-number signatures (type char ). This + array should be of size (nin+nout)*ntypes and contain the + data-types for the corresponding 1-d loop. The inputs should + be first followed by the outputs. For example, suppose I have + a ufunc that supports 1 integer and 1 double 1-d loop + (length-2 func and data arrays) that takes 2 inputs and + returns 1 output that is always a complex double, then the + types array would be + + + The bit-width names can also be used (e.g. :cdata:NPY_INT32, + :cdata:NPY_COMPLEX128 ) if desired. + + *ntypes* + + The number of data-types supported. This is equal to the number of 1-d + loops provided. + + *nin* + + The number of input arguments. + + *nout* + + The number of output arguments. + + *identity* + + Either :cdata:PyUFunc_One, :cdata:PyUFunc_Zero, :cdata:PyUFunc_None. + This specifies what should be returned when an empty array is + passed to the reduce method of the ufunc. + + *name* + + A NULL -terminated string providing the name of this ufunc + (should be the Python name it will be called). + + *doc* + + A documentation string for this ufunc (will be used in generating the + response to {ufunc_name}.__doc__). Do not include the function + signature or the name as this is generated automatically. + + *check_return* + + Not presently used, but this integer value does get set in the + structure-member of similar name. + + .. index:: + pair: ufunc; adding new + + The returned ufunc object is a callable Python object. It should be + placed in a (module) dictionary under the same name as was used in the + name argument to the ufunc-creation routine. The following example is + adapted from the umath module + + .. code-block:: c + + static PyUFuncGenericFunction atan2_functions[]=\ + {PyUFunc_ff_f, PyUFunc_dd_d, + PyUFunc_gg_g, PyUFunc_OO_O_method}; + static void* atan2_data[]=\ + {(void *)atan2f,(void *) atan2, + (void *)atan2l,(void *)"arctan2"}; + static char atan2_signatures[]=\ + {NPY_FLOAT, NPY_FLOAT, NPY_FLOAT, + NPY_DOUBLE, NPY_DOUBLE, + NPY_DOUBLE, NPY_LONGDOUBLE, + NPY_LONGDOUBLE, NPY_LONGDOUBLE + NPY_OBJECT, NPY_OBJECT, + NPY_OBJECT}; + ... + /* in the module initialization code */ + PyObject *f, *dict, *module; + ... + dict = PyModule_GetDict(module); + ... + f = PyUFunc_FromFuncAndData(atan2_functions, + atan2_data, atan2_signatures, 4, 2, 1, + PyUFunc_None, "arctan2", + "a safe and correct arctan(x1/x2)", 0); + PyDict_SetItemString(dict, "arctan2", f); + Py_DECREF(f); + ... + + +User-defined data-types +======================= + +NumPy comes with 21 builtin data-types. While this covers a large +majority of possible use cases, it is conceivable that a user may have +a need for an additional data-type. There is some support for adding +an additional data-type into the NumPy system. This additional data- +type will behave much like a regular data-type except ufuncs must have +1-d loops registered to handle it separately. Also checking for +whether or not other data-types can be cast "safely" to and from this +new type or not will always return "can cast" unless you also register +which types your new data-type can be cast to and from. Adding +data-types is one of the less well-tested areas for NumPy 1.0, so +there may be bugs remaining in the approach. Only add a new data-type +if you can't do what you want to do using the OBJECT or VOID +data-types that are already available. As an example of what I +consider a useful application of the ability to add data-types is the +possibility of adding a data-type of arbitrary precision floats to +NumPy. + +.. index:: + pair: dtype; adding new + + +Adding the new data-type +------------------------ + +To begin to make use of the new data-type, you need to first define a +new Python type to hold the scalars of your new data-type. It should +be acceptable to inherit from one of the array scalars if your new +type has a binary compatible layout. This will allow your new data +type to have the methods and attributes of array scalars. New data- +types must have a fixed memory size (if you want to define a data-type +that needs a flexible representation, like a variable-precision +number, then use a pointer to the object as the data-type). The memory +layout of the object structure for the new Python type must be +PyObject_HEAD followed by the fixed-size memory needed for the data- +type. For example, a suitable structure for the new Python type is: + +.. code-block:: c + + typedef struct { + PyObject_HEAD; + some_data_type obval; + /* the name can be whatever you want */ + } PySomeDataTypeObject; + +After you have defined a new Python type object, you must then define +a new :ctype:PyArray_Descr structure whose typeobject member will contain a +pointer to the data-type you've just defined. In addition, the +required functions in the ".f" member must be defined: nonzero, +copyswap, copyswapn, setitem, getitem, and cast. The more functions in +the ".f" member you define, however, the more useful the new data-type +will be. It is very important to intialize unused functions to NULL. +This can be achieved using :cfunc:PyArray_InitArrFuncs (f). + +Once a new :ctype:PyArray_Descr structure is created and filled with the +needed information and useful functions you call +:cfunc:PyArray_RegisterDataType (new_descr). The return value from this +call is an integer providing you with a unique type_number that +specifies your data-type. This type number should be stored and made +available by your module so that other modules can use it to recognize +your data-type (the other mechanism for finding a user-defined +data-type number is to search based on the name of the type-object +associated with the data-type using :cfunc:PyArray_TypeNumFromName ). + + +Registering a casting function +------------------------------ + +You may want to allow builtin (and other user-defined) data-types to +be cast automatically to your data-type. In order to make this +possible, you must register a casting function with the data-type you +want to be able to cast from. This requires writing low-level casting +functions for each conversion you want to support and then registering +these functions with the data-type descriptor. A low-level casting +function has the signature. + +.. cfunction:: void castfunc( void* from, void* to, npy_intp n, void* fromarr, void* toarr) + + Cast n elements from one type to another. The data to + cast from is in a contiguous, correctly-swapped and aligned chunk + of memory pointed to by from. The buffer to cast to is also + contiguous, correctly-swapped and aligned. The fromarr and toarr + arguments should only be used for flexible-element-sized arrays + (string, unicode, void). + +An example castfunc is: + +.. code-block:: c + + static void + double_to_float(double *from, float* to, npy_intp n, + void* ig1, void* ig2); + while (n--) { + (*to++) = (double) *(from++); + } + +This could then be registered to convert doubles to floats using the +code: + +.. code-block:: c + + doub = PyArray_DescrFromType(NPY_DOUBLE); + PyArray_RegisterCastFunc(doub, NPY_FLOAT, + (PyArray_VectorUnaryFunc *)double_to_float); + Py_DECREF(doub); + + +Registering coercion rules +-------------------------- + +By default, all user-defined data-types are not presumed to be safely +castable to any builtin data-types. In addition builtin data-types are +not presumed to be safely castable to user-defined data-types. This +situation limits the ability of user-defined data-types to participate +in the coercion system used by ufuncs and other times when automatic +coercion takes place in NumPy. This can be changed by registering +data-types as safely castable from a particlar data-type object. The +function :cfunc:PyArray_RegisterCanCast (from_descr, totype_number, +scalarkind) should be used to specify that the data-type object +from_descr can be cast to the data-type with type number +totype_number. If you are not trying to alter scalar coercion rules, +then use :cdata:PyArray_NOSCALAR for the scalarkind argument. + +If you want to allow your new data-type to also be able to share in +the scalar coercion rules, then you need to specify the scalarkind +function in the data-type object's ".f" member to return the kind of +scalar the new data-type should be seen as (the value of the scalar is +available to that function). Then, you can register data-types that +can be cast to separately for each scalar kind that may be returned +from your user-defined data-type. If you don't register scalar +coercion handling, then all of your user-defined data-types will be +seen as :cdata:PyArray_NOSCALAR. + + +Registering a ufunc loop +------------------------ + +You may also want to register low-level ufunc loops for your data-type +so that an ndarray of your data-type can have math applied to it +seamlessly. Registering a new loop with exactly the same arg_types +signature, silently replaces any previously registered loops for that +data-type. + +Before you can register a 1-d loop for a ufunc, the ufunc must be +previously created. Then you call :cfunc:PyUFunc_RegisterLoopForType +(...) with the information needed for the loop. The return value of +this function is 0 if the process was successful and -1 with +an error condition set if it was not successful. + +.. cfunction:: int PyUFunc_RegisterLoopForType( PyUFuncObject* ufunc, int usertype, PyUFuncGenericFunction function, int* arg_types, void* data) + + *ufunc* + + The ufunc to attach this loop to. + + *usertype* + + The user-defined type this loop should be indexed under. This number + must be a user-defined type or an error occurs. + + *function* + + The ufunc inner 1-d loop. This function must have the signature as + explained in Section 3 <#sec-creating-a-new>__ . + + *arg_types* + + (optional) If given, this should contain an array of integers of at + least size ufunc.nargs containing the data-types expected by the loop + function. The data will be copied into a NumPy-managed structure so + the memory for this argument should be deleted after calling this + function. If this is NULL, then it will be assumed that all data-types + are of type usertype. + + *data* + + (optional) Specify any optional data needed by the function which will + be passed when the function is called. + + .. index:: + pair: dtype; adding new + + +Subtyping the ndarray in C +========================== + +One of the lesser-used features that has been lurking in Python since +2.2 is the ability to sub-class types in C. This facility is one of +the important reasons for basing NumPy off of the Numeric code-base +which was already in C. A sub-type in C allows much more flexibility +with regards to memory management. Sub-typing in C is not difficult +even if you have only a rudimentary understanding of how to create new +types for Python. While it is easiest to sub-type from a single parent +type, sub-typing from multiple parent types is also possible. Multiple +inheritence in C is generally less useful than it is in Python because +a restriction on Python sub-types is that they have a binary +compatible memory layout. Perhaps for this reason, it is somewhat +easier to sub-type from a single parent type. + +.. index:: + pair: ndarray; subtyping + +All C-structures corresponding to Python objects must begin with +:cmacro:PyObject_HEAD (or :cmacro:PyObject_VAR_HEAD). In the same +way, any sub-type must have a C-structure that begins with exactly the +same memory layout as the parent type (or all of the parent types in +the case of multiple-inheritance). The reason for this is that Python +may attempt to access a member of the sub-type structure as if it had +the parent structure ( *i.e.* it will cast a given pointer to a +pointer to the parent structure and then dereference one of it's +members). If the memory layouts are not compatible, then this attempt +will cause unpredictable behavior (eventually leading to a memory +violation and program crash). + +One of the elements in :cmacro:PyObject_HEAD is a pointer to a +type-object structure. A new Python type is created by creating a new +type-object structure and populating it with functions and pointers to +describe the desired behavior of the type. Typically, a new +C-structure is also created to contain the instance-specific +information needed for each object of the type as well. For example, +:cdata:&PyArray_Type is a pointer to the type-object table for the ndarray +while a :ctype:PyArrayObject * variable is a pointer to a particular instance +of an ndarray (one of the members of the ndarray structure is, in +turn, a pointer to the type- object table :cdata:&PyArray_Type). Finally +:cfunc:PyType_Ready (<pointer_to_type_object>) must be called for +every new Python type. + + +Creating sub-types +------------------ + +To create a sub-type, a similar proceedure must be followed except +only behaviors that are different require new entries in the type- +object structure. All other entires can be NULL and will be filled in +by :cfunc:PyType_Ready with appropriate functions from the parent +type(s). In particular, to create a sub-type in C follow these steps: + +1. If needed create a new C-structure to handle each instance of your + type. A typical C-structure would be: + + .. code-block:: c + + typedef _new_struct { + PyArrayObject base; + /* new things here */ + } NewArrayObject; + + Notice that the full PyArrayObject is used as the first entry in order + to ensure that the binary layout of instances of the new type is + identical to the PyArrayObject. + +2. Fill in a new Python type-object structure with pointers to new + functions that will over-ride the default behavior while leaving any + function that should remain the same unfilled (or NULL). The tp_name + element should be different. + +3. Fill in the tp_base member of the new type-object structure with a + pointer to the (main) parent type object. For multiple-inheritance, + also fill in the tp_bases member with a tuple containing all of the + parent objects in the order they should be used to define inheritance. + Remember, all parent-types must have the same C-structure for multiple + inheritance to work properly. + +4. Call :cfunc:PyType_Ready (<pointer_to_new_type>). If this function + returns a negative number, a failure occurred and the type is not + initialized. Otherwise, the type is ready to be used. It is + generally important to place a reference to the new type into the + module dictionary so it can be accessed from Python. + +More information on creating sub-types in C can be learned by reading +PEP 253 (available at http://www.python.org/dev/peps/pep-0253). + + +Specific features of ndarray sub-typing +--------------------------------------- + +Some special methods and attributes are used by arrays in order to +facilitate the interoperation of sub-types with the base ndarray type. + +.. note:: XXX: some of the documentation below needs to be moved to the + reference guide. + + +The __array_finalize\__ method +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. attribute:: ndarray.__array_finalize__ + + Several array-creation functions of the ndarray allow + specification of a particular sub-type to be created. This allows + sub-types to be handled seamlessly in many routines. When a + sub-type is created in such a fashion, however, neither the + __new_\_ method nor the __init\__ method gets called. Instead, the + sub-type is allocated and the appropriate instance-structure + members are filled in. Finally, the :obj:__array_finalize__ + attribute is looked-up in the object dictionary. If it is present + and not None, then it can be either a CObject containing a pointer + to a :cfunc:PyArray_FinalizeFunc or it can be a method taking a + single argument (which could be None). + + If the :obj:__array_finalize__ attribute is a CObject, then the pointer + must be a pointer to a function with the signature: + + .. code-block:: c + + (int) (PyArrayObject *, PyObject *) + + The first argument is the newly created sub-type. The second argument + (if not NULL) is the "parent" array (if the array was created using + slicing or some other operation where a clearly-distinguishable parent + is present). This routine can do anything it wants to. It should + return a -1 on error and 0 otherwise. + + If the :obj:__array_finalize__ attribute is not None nor a CObject, + then it must be a Python method that takes the parent array as an + argument (which could be None if there is no parent), and returns + nothing. Errors in this method will be caught and handled. + + +The __array_priority\__ attribute +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. attribute:: ndarray.__array_priority__ + + This attribute allows simple but flexible determination of which sub- + type should be considered "primary" when an operation involving two or + more sub-types arises. In operations where different sub-types are + being used, the sub-type with the largest :obj:__array_priority__ + attribute will determine the sub-type of the output(s). If two sub- + types have the same :obj:__array_priority__ then the sub-type of the + first argument determines the output. The default + :obj:__array_priority__ attribute returns a value of 0.0 for the base + ndarray type and 1.0 for a sub-type. This attribute can also be + defined by objects that are not sub-types of the ndarray and can be + used to determine which :obj:__array_wrap__ method should be called for + the return output. + +The __array_wrap\__ method +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. attribute:: ndarray.__array_wrap__ + + Any class or type can define this method which should take an ndarray + argument and return an instance of the type. It can be seen as the + opposite of the :obj:__array__ method. This method is used by the + ufuncs (and other NumPy functions) to allow other objects to pass + through. For Python >2.4, it can also be used to write a decorator + that converts a function that works only with ndarrays to one that + works with any type with :obj:__array__ and :obj:__array_wrap__ methods. + +.. index:: + pair: ndarray; subtyping Added: numpy-docs/trunk/source/user/c-info.how-to-extend.rst =================================================================== --- numpy-docs/trunk/source/user/c-info.how-to-extend.rst 2008-10-26 17:50:36 UTC (rev 5958) +++ numpy-docs/trunk/source/user/c-info.how-to-extend.rst 2008-10-26 17:57:55 UTC (rev 5959) @@ -0,0 +1,641 @@ +******************* +How to extend NumPy +******************* + +| That which is static and repetitive is boring. That which is dynamic +| and random is confusing. In between lies art. +| --- *John A. Locke* + +| Science is a differential equation. Religion is a boundary condition. +| --- *Alan Turing* + + +.. _sec:Writing-an-extension: + +Writing an extension module +=========================== + +While the ndarray object is designed to allow rapid computation in +Python, it is also designed to be general-purpose and satisfy a wide- +variety of computational needs. As a result, if absolute speed is +essential, there is no replacement for a well-crafted, compiled loop +specific to your application and hardware. This is one of the reasons +that numpy includes f2py so that an easy-to-use mechanisms for linking +(simple) C/C++ and (arbitrary) Fortran code directly into Python are +available. You are encouraged to use and improve this mechanism. The +purpose of this section is not to document this tool but to document +the more basic steps to writing an extension module that this tool +depends on. + +.. index:: + single: extension module + +When an extension module is written, compiled, and installed to +somewhere in the Python path (sys.path), the code can then be imported +into Python as if it were a standard python file. It will contain +objects and methods that have been defined and compiled in C code. The +basic steps for doing this in Python are well-documented and you can +find more information in the documentation for Python itself available +online at www.python.org <http://www.python.org>_ . + +In addition to the Python C-API, there is a full and rich C-API for +NumPy allowing sophisticated manipulations on a C-level. However, for +most applications, only a few API calls will typically be used. If all +you need to do is extract a pointer to memory along with some shape +information to pass to another calculation routine, then you will use +very different calls, then if you are trying to create a new array- +like type or add a new data type for ndarrays. This chapter documents +the API calls and macros that are most commonly used. + + +Required subroutine +=================== + +There is exactly one function that must be defined in your C-code in +order for Python to use it as an extension module. The function must +be called init{name} where {name} is the name of the module from +Python. This function must be declared so that it is visible to code +outside of the routine. Besides adding the methods and constants you +desire, this subroutine must also contain calls to import_array() +and/or import_ufunc() depending on which C-API is needed. Forgetting +to place these commands will show itself as an ugly segmentation fault +(crash) as soon as any C-API subroutine is actually called. It is +actually possible to have multiple init{name} functions in a single +file in which case multiple modules will be defined by that file. +However, there are some tricks to get that to work correctly and it is +not covered here. + +A minimal init{name} method looks like: + +.. code-block:: c + + PyMODINIT_FUNC + init{name}(void) + { + (void)Py_InitModule({name}, mymethods); + import_array(); + } + +The mymethods must be an array (usually statically declared) of +PyMethodDef structures which contain method names, actual C-functions, +a variable indicating whether the method uses keyword arguments or +not, and docstrings. These are explained in the next section. If you +want to add constants to the module, then you store the returned value +from Py_InitModule which is a module object. The most general way to +add itmes to the module is to get the module dictionary using +PyModule_GetDict(module). With the module dictionary, you can add +whatever you like to the module manually. An easier way to add objects +to the module is to use one of three additional Python C-API calls +that do not require a separate extraction of the module dictionary. +These are documented in the Python documentation, but repeated here +for convenience: + +.. cfunction:: int PyModule_AddObject(PyObject* module, char* name, PyObject* value) + +.. cfunction:: int PyModule_AddIntConstant(PyObject* module, char* name, long value) + +.. cfunction:: int PyModule_AddStringConstant(PyObject* module, char* name, char* value) + + All three of these functions require the *module* object (the + return value of Py_InitModule). The *name* is a string that + labels the value in the module. Depending on which function is + called, the *value* argument is either a general object + (:cfunc:PyModule_AddObject steals a reference to it), an integer + constant, or a string constant. + + +Defining functions +================== + +The second argument passed in to the Py_InitModule function is a +structure that makes it easy to to define functions in the module. In +the example given above, the mymethods structure would have been +defined earlier in the file (usually right before the init{name} +subroutine) to: + +.. code-block:: c + + static PyMethodDef mymethods[] = { + { nokeywordfunc,nokeyword_cfunc, + METH_VARARGS, + Doc string}, + { keywordfunc, keyword_cfunc, + METH_VARARGS|METH_KEYWORDS, + Doc string}, + {NULL, NULL, 0, NULL} /* Sentinel */ + } + +Each entry in the mymethods array is a :ctype:PyMethodDef structure +containing 1) the Python name, 2) the C-function that implements the +function, 3) flags indicating whether or not keywords are accepted for +this function, and 4) The docstring for the function. Any number of +functions may be defined for a single module by adding more entries to +this table. The last entry must be all NULL as shown to act as a +sentinel. Python looks for this entry to know that all of the +functions for the module have been defined. + +The last thing that must be done to finish the extension module is to +actually write the code that performs the desired functions. There are +two kinds of functions: those that don't accept keyword arguments, and +those that do. + + +Functions without keyword arguments +----------------------------------- + +Functions that don't accept keyword arguments should be written as: + +.. code-block:: c + + static PyObject* + nokeyword_cfunc (PyObject *dummy, PyObject *args) + { + /* convert Python arguments */ + /* do function */ + /* return something */ + } + +The dummy argument is not used in this context and can be safely +ignored. The *args* argument contains all of the arguments passed in +to the function as a tuple. You can do anything you want at this +point, but usually the easiest way to manage the input arguments is to +call :cfunc:PyArg_ParseTuple (args, format_string, +addresses_to_C_variables...) or :cfunc:PyArg_UnpackTuple (tuple, "name" , +min, max, ...). A good description of how to use the first function is +contained in the Python C-API reference manual under section 5.5 +(Parsing arguments and building values). You should pay particular +attention to the "O&" format which uses converter functions to go +between the Python object and the C object. All of the other format +functions can be (mostly) thought of as special cases of this general +rule. There are several converter functions defined in the NumPy C-API +that may be of use. In particular, the :cfunc:PyArray_DescrConverter +function is very useful to support arbitrary data-type specification. +This function transforms any valid data-type Python object into a +:ctype:PyArray_Descr * object. Remember to pass in the address of the +C-variables that should be filled in. + +There are lots of examples of how to use :cfunc:PyArg_ParseTuple +throughout the NumPy source code. The standard usage is like this: + +.. code-block:: c + + PyObject *input; + PyArray_Descr *dtype; + if (!PyArg_ParseTuple(args, "OO&", &input, + PyArray_DescrConverter, + &dtype)) return NULL; + +It is important to keep in mind that you get a *borrowed* reference to +the object when using the "O" format string. However, the converter +functions usually require some form of memory handling. In this +example, if the conversion is successful, *dtype* will hold a new +reference to a :ctype:PyArray_Descr * object, while *input* will hold a +borrowed reference. Therefore, if this conversion were mixed with +another conversion (say to an integer) and the data-type conversion +was successful but the integer conversion failed, then you would need +to release the reference count to the data-type object before +returning. A typical way to do this is to set *dtype* to NULL +before calling :cfunc:PyArg_ParseTuple and then use :cfunc:Py_XDECREF +on *dtype* before returning. + +After the input arguments are processed, the code that actually does +the work is written (likely calling other functions as needed). The +final step of the C-function is to return something. If an error is +encountered then NULL should be returned (making sure an error has +actually been set). If nothing should be returned then increment +:cdata:Py_None and return it. If a single object should be returned then +it is returned (ensuring that you own a reference to it first). If +multiple objects should be returned then you need to return a tuple. +The :cfunc:Py_BuildValue (format_string, c_variables...) function makes +it easy to build tuples of Python objects from C variables. Pay +special attention to the difference between 'N' and 'O' in the format +string or you can easily create memory leaks. The 'O' format string +increments the reference count of the :ctype:PyObject * C-variable it +corresponds to, while the 'N' format string steals a reference to the +corresponding :ctype:PyObject * C-variable. You should use 'N' if you ave +already created a reference for the object and just want to give that +reference to the tuple. You should use 'O' if you only have a borrowed +reference to an object and need to create one to provide for the +tuple. + + +Functions with keyword arguments +-------------------------------- + +These functions are very similar to functions without keyword +arguments. The only difference is that the function signature is: + +.. code-block:: c + + static PyObject* + keyword_cfunc (PyObject *dummy, PyObject *args, PyObject *kwds) + { + ... + } + +The kwds argument holds a Python dictionary whose keys are the names +of the keyword arguments and whose values are the corresponding +keyword-argument values. This dictionary can be processed however you +see fit. The easiest way to handle it, however, is to replace the +:cfunc:PyArg_ParseTuple (args, format_string, addresses...) function with +a call to :cfunc:PyArg_ParseTupleAndKeywords (args, kwds, format_string, +char \*kwlist[], addresses...). The kwlist parameter to this function +is a NULL -terminated array of strings providing the expected +keyword arguments. There should be one string for each entry in the +format_string. Using this function will raise a TypeError if invalid +keyword arguments are passed in. + +For more help on this function please see section 1.8 (Keyword +Paramters for Extension Functions) of the Extending and Embedding +tutorial in the Python documentation. + + +Reference counting +------------------ + +The biggest difficulty when writing extension modules is reference +counting. It is an important reason for the popularity of f2py, weave, +pyrex, ctypes, etc.... If you mis-handle reference counts you can get +problems from memory-leaks to segmentation faults. The only strategy I +know of to handle reference counts correctly is blood, sweat, and +tears. First, you force it into your head that every Python variable +has a reference count. Then, you understand exactly what each function +does to the reference count of your objects, so that you can properly +use DECREF and INCREF when you need them. Reference counting can +really test the amount of patience and diligence you have towards your +programming craft. Despite the grim depiction, most cases of reference +counting are quite straightforward with the most common difficulty +being not using DECREF on objects before exiting early from a routine +due to some error. In second place, is the common error of not owning +the reference on an object that is passed to a function or macro that +is going to steal the reference ( *e.g.* :cfunc:PyTuple_SET_ITEM, and +most functions that take :ctype:PyArray_Descr objects). + +.. index:: + single: reference counting + +Typically you get a new reference to a variable when it is created or +is the return value of some function (there are some prominent +exceptions, however --- such as getting an item out of a tuple or a +dictionary). When you own the reference, you are responsible to make +sure that :cfunc:Py_DECREF (var) is called when the variable is no +longer necessary (and no other function has "stolen" its +reference). Also, if you are passing a Python object to a function +that will "steal" the reference, then you need to make sure you own it +(or use :cfunc:Py_INCREF to get your own reference). You will also +encounter the notion of borrowing a reference. A function that borrows +a reference does not alter the reference count of the object and does +not expect to "hold on "to the reference. It's just going to use the +object temporarily. When you use :cfunc:PyArg_ParseTuple or +:cfunc:PyArg_UnpackTuple you receive a borrowed reference to the +objects in the tuple and should not alter their reference count inside +your function. With practice, you can learn to get reference counting +right, but it can be frustrating at first. + +One common source of reference-count errors is the :cfunc:Py_BuildValue +function. Pay careful attention to the difference between the 'N' +format character and the 'O' format character. If you create a new +object in your subroutine (such as an output array), and you are +passing it back in a tuple of return values, then you should most- +likely use the 'N' format character in :cfunc:Py_BuildValue. The 'O' +character will increase the reference count by one. This will leave +the caller with two reference counts for a brand-new array. When the +variable is deleted and the reference count decremented by one, there +will still be that extra reference count, and the array will never be +deallocated. You will have a reference-counting induced memory leak. +Using the 'N' character will avoid this situation as it will return to +the caller an object (inside the tuple) with a single reference count. + +.. index:: + single: reference counting + + + + +Dealing with array objects +========================== + +Most extension modules for NumPy will need to access the memory for an +ndarray object (or one of it's sub-classes). The easiest way to do +this doesn't require you to know much about the internals of NumPy. +The method is to + +1. Ensure you are dealing with a well-behaved array (aligned, in machine + byte-order and single-segment) of the correct type and number of + dimensions. + + 1. By converting it from some Python object using + :cfunc:PyArray_FromAny or a macro built on it. + + 2. By constructing a new ndarray of your desired shape and type + using :cfunc:PyArray_NewFromDescr or a simpler macro or function + based on it. + + +2. Get the shape of the array and a pointer to its actual data. + +3. Pass the data and shape information on to a subroutine or other + section of code that actually performs the computation. + +4. If you are writing the algorithm, then I recommend that you use the + stride information contained in the array to access the elements of + the array (the :cfunc:PyArray_GETPTR macros make this painless). Then, + you can relax your requirements so as not to force a single-segment + array and the data-copying that might result. + +Each of these sub-topics is covered in the following sub-sections. + + +Converting an arbitrary sequence object +--------------------------------------- + +The main routine for obtaining an array from any Python object that +can be converted to an array is :cfunc:PyArray_FromAny. This +function is very flexible with many input arguments. Several macros +make it easier to use the basic function. :cfunc:PyArray_FROM_OTF is +arguably the most useful of these macros for the most common uses. It +allows you to convert an arbitrary Python object to an array of a +specific builtin data-type ( *e.g.* float), while specifying a +particular set of requirements ( *e.g.* contiguous, aligned, and +writeable). The syntax is + +.. cfunction:: PyObject *PyArray_FROM_OTF(PyObject* obj, int typenum, int requirements) + + Return an ndarray from any Python object, *obj*, that can be + converted to an array. The number of dimensions in the returned + array is determined by the object. The desired data-type of the + returned array is provided in *typenum* which should be one of the + enumerated types. The *requirements* for the returned array can be + any combination of standard array flags. Each of these arguments + is explained in more detail below. You receive a new reference to + the array on success. On failure, NULL is returned and an + exception is set. + + *obj* + + The object can be any Python object convertable to an ndarray. + If the object is already (a subclass of) the ndarray that + satisfies the requirements then a new reference is returned. + Otherwise, a new array is constructed. The contents of *obj* + are copied to the new array unless the array interface is used + so that data does not have to be copied. Objects that can be + converted to an array include: 1) any nested sequence object, + 2) any object exposing the array interface, 3) any object with + an :obj:__array__ method (which should return an ndarray), + and 4) any scalar object (becomes a zero-dimensional + array). Sub-classes of the ndarray that otherwise fit the + requirements will be passed through. If you want to ensure + a base-class ndarray, then use :cdata:NPY_ENSUREARRAY in the + requirements flag. A copy is made only if necessary. If you + want to guarantee a copy, then pass in :cdata:NPY_ENSURECOPY + to the requirements flag. + + *typenum* + + One of the enumerated types or :cdata:NPY_NOTYPE if the data-type + should be determined from the object itself. The C-based names + can be used: + + :cdata:NPY_BOOL, :cdata:NPY_BYTE, :cdata:NPY_UBYTE, + :cdata:NPY_SHORT, :cdata:NPY_USHORT, :cdata:NPY_INT, + :cdata:NPY_UINT, :cdata:NPY_LONG, :cdata:NPY_ULONG, + :cdata:NPY_LONGLONG, :cdata:NPY_ULONGLONG, :cdata:NPY_DOUBLE, + :cdata:NPY_LONGDOUBLE, :cdata:NPY_CFLOAT, :cdata:NPY_CDOUBLE, + :cdata:NPY_CLONGDOUBLE, :cdata:NPY_OBJECT. + + Alternatively, the bit-width names can be used as supported on the + platform. For example: + + :cdata:NPY_INT8, :cdata:NPY_INT16, :cdata:NPY_INT32, + :cdata:NPY_INT64, :cdata:NPY_UINT8, + :cdata:NPY_UINT16, :cdata:NPY_UINT32, + :cdata:NPY_UINT64, :cdata:NPY_FLOAT32, + :cdata:NPY_FLOAT64, :cdata:NPY_COMPLEX64, + :cdata:NPY_COMPLEX128. + + The object will be converted to the desired type only if it + can be done without losing precision. Otherwise NULL will + be returned and an error raised. Use :cdata:NPY_FORCECAST in the + requirements flag to override this behavior. + + *requirements* + + The memory model for an ndarray admits arbitrary strides in + each dimension to advance to the next element of the array. + Often, however, you need to interface with code that expects a + C-contiguous or a Fortran-contiguous memory layout. In + addition, an ndarray can be misaligned (the address of an + element is not at an integral multiple of the size of the + element) which can cause your program to crash (or at least + work more slowly) if you try and dereference a pointer into + the array data. Both of these problems can be solved by + converting the Python object into an array that is more + "well-behaved" for your specific usage. + + The requirements flag allows specification of what kind of array is + acceptable. If the object passed in does not satisfy this requirements + then a copy is made so that thre returned object will satisfy the + requirements. these ndarray can use a very generic pointer to memory. + This flag allows specification of the desired properties of the + returned array object. All of the flags are explained in the detailed + API chapter. The flags most commonly needed are :cdata:NPY_IN_ARRAY, + :cdata:NPY_OUT_ARRAY, and :cdata:NPY_INOUT_ARRAY: + + .. cvar:: NPY_IN_ARRAY + + Equivalent to :cdata:NPY_CONTIGUOUS \| + :cdata:NPY_ALIGNED. This combination of flags is useful + for arrays that must be in C-contiguous order and aligned. + These kinds of arrays are usually input arrays for some + algorithm. + + .. cvar:: NPY_OUT_ARRAY + + Equivalent to :cdata:NPY_CONTIGUOUS \| + :cdata:NPY_ALIGNED \| :cdata:NPY_WRITEABLE. This + combination of flags is useful to specify an array that is + in C-contiguous order, is aligned, and can be written to + as well. Such an array is usually returned as output + (although normally such output arrays are created from + scratch). + + .. cvar:: NPY_INOUT_ARRAY + + Equivalent to :cdata:NPY_CONTIGUOUS \| + :cdata:NPY_ALIGNED \| :cdata:NPY_WRITEABLE \| + :cdata:NPY_UPDATEIFCOPY. This combination of flags is + useful to specify an array that will be used for both + input and output. If a copy is needed, then when the + temporary is deleted (by your use of :cfunc:Py_DECREF at + the end of the interface routine), the temporary array + will be copied back into the original array passed in. Use + of the :cdata:UPDATEIFCOPY flag requires that the input + object is already an array (because other objects cannot + be automatically updated in this fashion). If an error + occurs use :cfunc:PyArray_DECREF_ERR (obj) on an array + with the :cdata:NPY_UPDATEIFCOPY flag set. This will + delete the array without causing the contents to be copied + back into the original array. + + + Other useful flags that can be OR'd as additional requirements are: + + .. cvar:: NPY_FORCECAST + + Cast to the desired type, even if it can't be done without losing + information. + + .. cvar:: NPY_ENSURECOPY + + Make sure the resulting array is a copy of the original. + + .. cvar:: NPY_ENSUREARRAY + + Make sure the resulting object is an actual ndarray and not a sub- + class. + +.. note:: + + Whether or not an array is byte-swapped is determined by the + data-type of the array. Native byte-order arrays are always + requested by :cfunc:PyArray_FROM_OTF and so there is no need for + a :cdata:NPY_NOTSWAPPED flag in the requirements argument. There + is also no way to get a byte-swapped array from this routine. + + +Creating a brand-new ndarray +---------------------------- + +Quite often new arrays must be created from within extension-module +code. Perhaps an output array is needed and you don't want the caller +to have to supply it. Perhaps only a temporary array is needed to hold +an intermediate calculation. Whatever the need there are simple ways +to get an ndarray object of whatever data-type is needed. The most +general function for doing this is :cfunc:PyArray_NewFromDescr. All array +creation functions go through this heavily re-used code. Because of +its flexibility, it can be somewhat confusing to use. As a result, +simpler forms exist that are easier to use. + +.. cfunction:: PyObject *PyArray_SimpleNew(int nd, npy_intp* dims, int typenum) + + This function allocates new memory and places it in an ndarray + with *nd* dimensions whose shape is determined by the array of + at least *nd* items pointed to by *dims*. The memory for the + array is uninitialized (unless typenum is :cdata:PyArray_OBJECT in + which case each element in the array is set to NULL). The + *typenum* argument allows specification of any of the builtin + data-types such as :cdata:PyArray_FLOAT or :cdata:PyArray_LONG. The + memory for the array can be set to zero if desired using + :cfunc:PyArray_FILLWBYTE (return_object, 0). + +.. cfunction:: PyObject *PyArray_SimpleNewFromData( int nd, npy_intp* dims, int typenum, void* data) + + Sometimes, you want to wrap memory allocated elsewhere into an + ndarray object for downstream use. This routine makes it + straightforward to do that. The first three arguments are the same + as in :cfunc:PyArray_SimpleNew, the final argument is a pointer to a + block of contiguous memory that the ndarray should use as it's + data-buffer which will be interpreted in C-style contiguous + fashion. A new reference to an ndarray is returned, but the + ndarray will not own its data. When this ndarray is deallocated, + the pointer will not be freed. + + You should ensure that the provided memory is not freed while the + returned array is in existence. The easiest way to handle this is + if data comes from another reference-counted Python object. The + reference count on this object should be increased after the + pointer is passed in, and the base member of the returned ndarray + should point to the Python object that owns the data. Then, when + the ndarray is deallocated, the base-member will be DECREF'd + appropriately. If you want the memory to be freed as soon as the + ndarray is deallocated then simply set the OWNDATA flag on the + returned ndarray. + + +Getting at ndarray memory and accessing elements of the ndarray +--------------------------------------------------------------- + +If obj is an ndarray (:ctype:PyArrayObject *), then the data-area of the +ndarray is pointed to by the void* pointer :cfunc:PyArray_DATA (obj) or +the char* pointer :cfunc:PyArray_BYTES (obj). Remember that (in general) +this data-area may not be aligned according to the data-type, it may +represent byte-swapped data, and/or it may not be writeable. If the +data area is aligned and in native byte-order, then how to get at a +specific element of the array is determined only by the array of +npy_intp variables, :cfunc:PyArray_STRIDES (obj). In particular, this +c-array of integers shows how many **bytes** must be added to the +current element pointer to get to the next element in each dimension. +For arrays less than 4-dimensions there are :cfunc:PyArray_GETPTR{k} +(obj, ...) macros where {k} is the integer 1, 2, 3, or 4 that make +using the array strides easier. The arguments .... represent {k} non- +negative integer indices into the array. For example, suppose E is +a 3-dimensional ndarray. A (void*) pointer to the element E[i,j,k] +is obtained as :cfunc:PyArray_GETPTR3 (E, i, j, k). + +As explained previously, C-style contiguous arrays and Fortran-style +contiguous arrays have particular striding patterns. Two array flags +(:cdata:NPY_C_CONTIGUOUS and :cdataNPY_F_CONTIGUOUS) indicate +whether or not the striding pattern of a particular array matches the +C-style contiguous or Fortran-style contiguous or neither. Whether or +not the striding pattern matches a standard C or Fortran one can be +tested Using :cfunc:PyArray_ISCONTIGUOUS (obj) and +:cfunc:PyArray_ISFORTRAN (obj) respectively. Most third-party +libraries expect contiguous arrays. But, often it is not difficult to +support general-purpose striding. I encourage you to use the striding +information in your own code whenever possible, and reserve +single-segment requirements for wrapping third-party code. Using the +striding information provided with the ndarray rather than requiring a +contiguous striding reduces copying that otherwise must be made. + + +Example +======= + +.. index:: + single: extension module + +The following example shows how you might write a wrapper that accepts +two input arguments (that will be converted to an array) and an output +argument (that must be an array). The function returns None and +updates the output array. + +.. code-block:: c + + static PyObject * + example_wrapper(PyObject *dummy, PyObject *args) + { + PyObject *arg1=NULL, *arg2=NULL, *out=NULL; + PyObject *arr1=NULL, *arr2=NULL, *oarr=NULL; + + if (!PyArg_ParseTuple(args, OOO&, &arg1, *arg2, + &PyArrayType, *out)) return NULL; + + arr1 = PyArray_FROM_OTF(arg1, NPY_DOUBLE, NPY_IN_ARRAY); + if (arr1 == NULL) return NULL; + arr2 = PyArray_FROM_OTF(arg2, NPY_DOUBLE, NPY_IN_ARRAY); + if (arr2 == NULL) goto fail; + oarr = PyArray_FROM_OTF(out, NPY_DOUBLE, NPY_INOUT_ARRAY); + if (oarr == NULL) goto fail; + + /* code that makes use of arguments */ + /* You will probably need at least + nd = PyArray_NDIM(<..>) -- number of dimensions + dims = PyArray_DIMS(<..>) -- npy_intp array of length nd + showing length in each dim. + dptr = (double *)PyArray_DATA(<..>) -- pointer to data. + + If an error occurs goto fail. + */ + + Py_DECREF(arr1); + Py_DECREF(arr2); + Py_DECREF(oarr); + Py_INCREF(Py_None); + return Py_None; + + fail: + Py_XDECREF(arr1); + Py_XDECREF(arr2); + PyArray_XDECREF_ERR(oarr); + return NULL; + } Added: numpy-docs/trunk/source/user/c-info.python-as-glue.rst =================================================================== --- numpy-docs/trunk/source/user/c-info.python-as-glue.rst 2008-10-26 17:50:36 UTC (rev 5958) +++ numpy-docs/trunk/source/user/c-info.python-as-glue.rst 2008-10-26 17:57:55 UTC (rev 5959) @@ -0,0 +1,1523 @@ +******************** +Using Python as glue +******************** + +| There is no conversation more boring than the one where everybody +| agrees. +| --- *Michel de Montaigne* + +| Duct tape is like the force. It has a light side, and a dark side, and +| it holds the universe together. +| --- *Carl Zwanzig* + +Many people like to say that Python is a fantastic glue language. +Hopefully, this Chapter will convince you that this is true. The first +adopters of Python for science were typically people who used it to +glue together large applicaton codes running on super-computers. Not +only was it much nicer to code in Python than in a shell script or +Perl, in addition, the ability to easily extend Python made it +relatively easy to create new classes and types specifically adapted +to the problems being solved. From the interactions of these early +contributors, Numeric emerged as an array-like object that could be +used to pass data between these applications. + +As Numeric has matured and developed into NumPy, people have been able +to write more code directly in NumPy. Often this code is fast-enough +for production use, but there are still times that there is a need to +access compiled code. Either to get that last bit of efficiency out of +the algorithm or to make it easier to access widely-available codes +written in C/C++ or Fortran. + +This chapter will review many of the tools that are available for the +purpose of accessing code written in other compiled languages. There +are many resources available for learning to call other compiled +libraries from Python and the purpose of this Chapter is not to make +you an expert. The main goal is to make you aware of some of the +possibilities so that you will know what to "Google" in order to learn more. + +The http://www.scipy.org website also contains a great deal of useful +information about many of these tools. For example, there is a nice +description of using several of the tools explained in this chapter at +http://www.scipy.org/PerformancePython. This link provides several +ways to solve the same problem showing how to use and connect with +compiled code to get the best performance. In the process you can get +a taste for several of the approaches that will be discussed in this +chapter. + + +Calling other compiled libraries from Python +============================================ + +While Python is a great language and a pleasure to code in, its +dynamic nature results in overhead that can cause some code ( *i.e.* +raw computations inside of for loops) to be up 10-100 times slower +than equivalent code written in a static compiled language. In +addition, it can cause memory usage to be larger than necessary as +temporary arrays are created and destroyed during computation. For +many types of computing needs the extra slow-down and memory +consumption can often not be spared (at least for time- or memory- +critical portions of your code). Therefore one of the most common +needs is to call out from Python code to a fast, machine-code routine +(e.g. compiled using C/C++ or Fortran). The fact that this is +relatively easy to do is a big reason why Python is such an excellent +high-level language for scientific and engineering programming. + +Their are two basic approaches to calling compiled code: writing an +extension module that is then imported to Python using the import +command, or calling a shared-library subroutine directly from Python +using the ctypes module (included in the standard distribution with +Python 2.5). The first method is the most common (but with the +inclusion of ctypes into Python 2.5 this status may change). + +.. warning:: + + Calling C-code from Python can result in Python crashes if you are not + careful. None of the approaches in this chapter are immune. You have + to know something about the way data is handled by both NumPy and by + the third-party library being used. + + +Hand-generated wrappers +======================= + +Extension modules were discussed in Chapter 1 +<#sec-writing-an-extension>__ . The most basic way to interface with +compiled code is to write an extension module and construct a module +method that calls the compiled code. For improved readability, your +method should take advantage of the PyArg_ParseTuple call to convert +between Python objects and C data-types. For standard C data-types +there is probably already a built-in converter. For others you may +need to write your own converter and use the "O&" format string which +allows you to specify a function that will be used to perform the +conversion from the Python object to whatever C-structures are needed. + +Once the conversions to the appropriate C-structures and C data-types +have been performed, the next step in the wrapper is to call the +underlying function. This is straightforward if the underlying +function is in C or C++. However, in order to call Fortran code you +must be familiar with how Fortran subroutines are called from C/C++ +using your compiler and platform. This can vary somewhat platforms and +compilers (which is another reason f2py makes life much simpler for +interfacing Fortran code) but generally involves underscore mangling +of the name and the fact that all variables are passed by reference +(i.e. all arguments are pointers). + +The advantage of the hand-generated wrapper is that you have complete +control over how the C-library gets used and called which can lead to +a lean and tight interface with minimal over-head. The disadvantage is +that you have to write, debug, and maintain C-code, although most of +it can be adapted using the time-honored technique of +"cutting-pasting-and-modifying" from other extension modules. Because, +the procedure of calling out to additional C-code is fairly +regimented, code-generation procedures have been developed to make +this process easier. One of these code- generation techniques is +distributed with NumPy and allows easy integration with Fortran and +(simple) C code. This package, f2py, will be covered briefly in the +next session. + + +f2py +==== + +F2py allows you to automatically construct an extension module that +interfaces to routines in Fortran 77/90/95 code. It has the ability to +parse Fortran 77/90/95 code and automatically generate Python +signatures for the subroutines it encounters, or you can guide how the +subroutine interfaces with Python by constructing an interface- +defintion-file (or modifying the f2py-produced one). + +.. index:: + single: f2py + +Creating source for a basic extension module +-------------------------------------------- + +Probably the easiest way to introduce f2py is to offer a simple +example. Here is one of the subroutines contained in a file named +:file:add.f: + +.. code-block:: none + + C + SUBROUTINE ZADD(A,B,C,N) + C + DOUBLE COMPLEX A(*) + DOUBLE COMPLEX B(*) + DOUBLE COMPLEX C(*) + INTEGER N + DO 20 J = 1, N + C(J) = A(J)+B(J) + 20 CONTINUE + END + +This routine simply adds the elements in two contiguous arrays and +places the result in a third. The memory for all three arrays must be +provided by the calling routine. A very basic interface to this +routine can be automatically generated by f2py:: + + f2py -m add add.f + +You should be able to run this command assuming your search-path is +set-up properly. This command will produce an extension module named +addmodule.c in the current directory. This extension module can now be +compiled and used from Python just like any other extension module. + + +Creating a compiled extension module +------------------------------------ + +You can also get f2py to compile add.f and also compile its produced +extension module leaving only a shared-library extension file that can +be imported from Python:: + + f2py -c -m add add.f + +This command leaves a file named add.{ext} in the current directory +(where {ext} is the appropriate extension for a python extension +module on your platform --- so, pyd, *etc.* ). This module may then be +imported from Python. It will contain a method for each subroutin in +add (zadd, cadd, dadd, sadd). The docstring of each method contains +information about how the module method may be called: + + >>> import add + >>> print add.zadd.__doc__ + zadd - Function signature: + zadd(a,b,c,n) + Required arguments: + a : input rank-1 array('D') with bounds (*) + b : input rank-1 array('D') with bounds (*) + c : input rank-1 array('D') with bounds (*) + n : input int + + +Improving the basic interface +----------------------------- + +The default interface is a very literal translation of the fortran +code into Python. The Fortran array arguments must now be NumPy arrays +and the integer argument should be an integer. The interface will +attempt to convert all arguments to their required types (and shapes) +and issue an error if unsuccessful. However, because it knows nothing +about the semantics of the arguments (such that C is an output and n +should really match the array sizes), it is possible to abuse this +function in ways that can cause Python to crash. For example: + + >>> add.zadd([1,2,3],[1,2],[3,4],1000) + +will cause a program crash on most systems. Under the covers, the +lists are being converted to proper arrays but then the underlying add +loop is told to cycle way beyond the borders of the allocated memory. + +In order to improve the interface, directives should be provided. This +is accomplished by constructing an interface definition file. It is +usually best to start from the interface file that f2py can produce +(where it gets its default behavior from). To get f2py to generate the +interface file use the -h option:: + + f2py -h add.pyf -m add add.f + +This command leaves the file add.pyf in the current directory. The +section of this file corresponding to zadd is: + +.. code-block:: none + + subroutine zadd(a,b,c,n) ! in :add:add.f + double complex dimension(*) :: a + double complex dimension(*) :: b + double complex dimension(*) :: c + integer :: n + end subroutine zadd + +By placing intent directives and checking code, the interface can be +cleaned up quite a bit until the Python module method is both easier +to use and more robust. + +.. code-block:: none + + subroutine zadd(a,b,c,n) ! in :add:add.f + double complex dimension(n) :: a + double complex dimension(n) :: b + double complex intent(out),dimension(n) :: c + integer intent(hide),depend(a) :: n=len(a) + end subroutine zadd + +The intent directive, intent(out) is used to tell f2py that c is +an output variable and should be created by the interface before being +passed to the underlying code. The intent(hide) directive tells f2py +to not allow the user to specify the variable, n, but instead to +get it from the size of a. The depend( a ) directive is +necessary to tell f2py that the value of n depends on the input a (so +that it won't try to create the variable n until the variable a is +created). + +The new interface has docstring: + + >>> print add.zadd.__doc__ + zadd - Function signature: + c = zadd(a,b) + Required arguments: + a : input rank-1 array('D') with bounds (n) + b : input rank-1 array('D') with bounds (n) + Return objects: + c : rank-1 array('D') with bounds (n) + +Now, the function can be called in a much more robust way: + + >>> add.zadd([1,2,3],[4,5,6]) + array([ 5.+0.j, 7.+0.j, 9.+0.j]) + +Notice the automatic conversion to the correct format that occurred. + + +Inserting directives in Fortran source +-------------------------------------- + +The nice interface can also be generated automatically by placing the +variable directives as special comments in the original fortran code. +Thus, if I modify the source code to contain: + +.. code-block:: none + + C + SUBROUTINE ZADD(A,B,C,N) + C + CF2PY INTENT(OUT) :: C + CF2PY INTENT(HIDE) :: N + CF2PY DOUBLE COMPLEX :: A(N) + CF2PY DOUBLE COMPLEX :: B(N) + CF2PY DOUBLE COMPLEX :: C(N) + DOUBLE COMPLEX A(*) + DOUBLE COMPLEX B(*) + DOUBLE COMPLEX C(*) + INTEGER N + DO 20 J = 1, N + C(J) = A(J) + B(J) + 20 CONTINUE + END + +Then, I can compile the extension module using:: + + f2py -c -m add add.f + +The resulting signature for the function add.zadd is exactly the same +one that was created previously. If the original source code had +contained A(N) instead of A(\*) and so forth with B and C, then I +could obtain (nearly) the same interface simply by placing the +INTENT(OUT) :: C comment line in the source code. The only difference +is that N would be an optional input that would default to the length +of A. + + +A filtering example +------------------- + +For comparison with the other methods to be discussed. Here is another +example of a function that filters a two-dimensional array of double +precision floating-point numbers using a fixed averaging filter. The +advantage of using Fortran to index into multi-dimensional arrays +should be clear from this example. + +.. code-block:: none + + SUBROUTINE DFILTER2D(A,B,M,N) + C + DOUBLE PRECISION A(M,N) + DOUBLE PRECISION B(M,N) + INTEGER N, M + CF2PY INTENT(OUT) :: B + CF2PY INTENT(HIDE) :: N + CF2PY INTENT(HIDE) :: M + DO 20 I = 2,M-1 + DO 40 J=2,N-1 + B(I,J) = A(I,J) + +           (A(I-1,J)+A(I+1,J) +
+         $A(I,J-1)+A(I,J+1) )*0.5D0 + +$           (A(I-1,J-1) + A(I-1,J+1) +
+         \$            A(I+1,J-1) + A(I+1,J+1))*0.25D0
+     40      CONTINUE
+     20   CONTINUE
+          END
+
+This code can be compiled and linked into an extension module named
+filter using::
+
+    f2py -c -m filter filter.f
+
+This will produce an extension module named filter.so in the current
+directory with a method named dfilter2d that returns a filtered
+version of the input.
+
+
+Calling f2py from Python
+------------------------
+
+The f2py program is written in Python and can be run from inside your
+module. This provides a facility that is somewhat similar to the use
+of weave.ext_tools described below. An example of the final interface
+executed using Python code is:
+
+.. code-block:: python
+
+    import numpy.f2py as f2py
+    fid = open('add.f')
+    source = fid.read()
+    fid.close()
+    f2py.compile(source, modulename='add')
+    import add
+
+The source string can be any valid Fortran code. If you want to save
+the extension-module source code then a suitable file-name can be
+provided by the source_fn keyword to the compile function.
+
+
+Automatic extension module generation
+-------------------------------------
+
+If you want to distribute your f2py extension module, then you only
+need to include the .pyf file and the Fortran code. The distutils
+extensions in NumPy allow you to define an extension module entirely
+in terms of this interface file. A valid setup.py file allowing
+distribution of the add.f module (as part of the package f2py_examples
+so that it would be loaded as f2py_examples.add) is:
+
+.. code-block:: python
+
+    def configuration(parent_package='', top_path=None)
+        from numpy.distutils.misc_util import Configuration
+        config = Configuration('f2py_examples',parent_package, top_path)
+        config.add_extension('add', sources=['add.pyf','add.f'])
+        return config
+
+    if __name__ == '__main__':
+        from numpy.distutils.core import setup
+        setup(**configuration(top_path='').todict())
+
+Installation of the new package is easy using::
+
+    python setup.py install
+
+assuming you have the proper permissions to write to the main site-
+packages directory for the version of Python you are using. For the
+resulting package to work, you need to create a file named __init__.py
+(in the same directory as add.pyf). Notice the extension module is
+defined entirely in terms of the "add.pyf" and "add.f" files. The
+conversion of the .pyf file to a .c file is handled by numpy.disutils.
+
+
+Conclusion
+----------
+
+The interface definition file (.pyf) is how you can fine-tune the
+interface between Python and Fortran. There is decent documentation
+for f2py found in the numpy/f2py/docs directory where-ever NumPy is
+installed on your system (usually under site-packages). There is also
+more information on using f2py (including how to use it to wrap C
+codes) at http://www.scipy.org/Cookbook under the "Using NumPy with
+Other Languages" heading.
+
+The f2py method of linking compiled code is currently the most
+sophisticated and integrated approach. It allows clean separation of
+Python with compiled code while still allowing for separate
+distribution of the extension module. The only draw-back is that it
+requires the existence of a Fortran compiler in order for a user to
+install the code. However, with the existence of the free-compilers
+g77, gfortran, and g95, as well as high-quality commerical compilers,
+this restriction is not particularly onerous. In my opinion, Fortran
+is still the easiest way to write fast and clear code for scientific
+computing. It handles complex numbers, and multi-dimensional indexing
+in the most straightforward way. Be aware, however, that some Fortran
+compilers will not be able to optimize code as well as good hand-
+written C-code.
+
+.. index::
+   single: f2py
+
+
+weave
+=====
+
+Weave is a scipy package that can be used to automate the process of
+extending Python with C/C++ code. It can be used to speed up
+evaluation of an array expression that would otherwise create
+temporary variables, to directly "inline" C/C++ code into Python, or
+to create a fully-named extension module.  You must either install
+scipy or get the weave package separately and install it using the
+standard python setup.py install. You must also have a C/C++-compiler
+installed and useable by Python distutils in order to use weave.
+
+.. index::
+   single: weave
+
+Somewhat dated, but still useful documentation for weave can be found
+at the link http://www.scipy/Weave. There are also many examples found
+in the examples directory which is installed under the weave directory
+in the place where weave is installed on your system.
+
+
+Speed up code involving arrays (also see scipy.numexpr)
+-------------------------------------------------------
+
+This is the easiest way to use weave and requires minimal changes to
+your Python code. It involves placing quotes around the expression of
+interest and calling weave.blitz. Weave will parse the code and
+generate C++ code using Blitz C++ arrays. It will then compile the
+code and catalog the shared library so that the next time this exact
+string is asked for (and the array types are the same), the already-
+compiled shared library will be loaded and used. Because Blitz makes
+extensive use of C++ templating, it can take a long time to compile
+the first time. After that, however, the code should evaluate more
+quickly than the equivalent NumPy expression. This is especially true
+if your array sizes are large and the expression would require NumPy
+to create several temporaries. Only expressions involving basic
+arithmetic operations and basic array slicing can be converted to
+Blitz C++ code.
+
+For example, consider the expression::
+
+    d = 4*a + 5*a*b + 6*b*c
+
+where a, b, and c are all arrays of the same type and shape. When the
+data-type is double-precision and the size is 1000x1000, this
+expression takes about 0.5 seconds to compute on an 1.1Ghz AMD Athlon
+machine. When this expression is executed instead using blitz:
+
+.. code-block:: python
+
+    d = empty(a.shape, 'd'); weave.blitz(expr)
+
+execution time is only about 0.20 seconds (about 0.14 seconds spent in
+weave and the rest in allocating space for d). Thus, we've sped up the
+code by a factor of 2 using only a simnple command (weave.blitz). Your
+mileage may vary, but factors of 2-8 speed-ups are possible with this
+very simple technique.
+
+If you are interested in using weave in this way, then you should also
+look at scipy.numexpr which is another similar way to speed up
+expressions by eliminating the need for temporary variables. Using
+numexpr does not require a C/C++ compiler.
+
+
+Inline C-code
+-------------
+
+Probably the most widely-used method of employing weave is to
+"in-line" C/C++ code into Python in order to speed up a time-critical
+section of Python code. In this method of using weave, you define a
+string containing useful C-code and then pass it to the function
+**weave.inline** ( code_string, variables ), where
+code_string is a string of valid C/C++ code and variables is a list of
+variables that should be passed in from Python. The C/C++ code should
+refer to the variables with the same names as they are defined with in
+Python. If weave.line should return anything the the special value
+return_val should be set to whatever object should be returned. The
+following example shows how to use weave on basic Python objects:
+
+.. code-block:: python
+
+    code = r"""
+    int i;
+    py::tuple results(2);
+    for (i=0; i<a.length(); i++) {
+         a[i] = i;
+    }
+    results[0] = 3.0;
+    results[1] = 4.0;
+    return_val = results;
+    """
+    a = [None]*10
+    res = weave.inline(code,['a'])
+
+The C++ code shown in the code string uses the name 'a' to refer to
+the Python list that is passed in. Because the Python List is a
+mutable type, the elements of the list itself are modified by the C++
+code. A set of C++ classes are used to access Python objects using
+simple syntax.
+
+The main advantage of using C-code, however, is to speed up processing
+on an array of data. Accessing a NumPy array in C++ code using weave,
+depends on what kind of type converter is chosen in going from NumPy
+arrays to C++ code. The default converter creates 5 variables for the
+C-code for every NumPy array passed in to weave.inline. The following
+table shows these variables which can all be used in the C++ code. The
+table assumes that myvar is the name of the array in Python with
+data-type {dtype} (i.e.  float64, float32, int8, etc.)
+
+===========  ==============  =========================================
+Variable     Type            Contents
+===========  ==============  =========================================
+myvar        {dtype}*        Pointer to the first element of the array
+Nmyvar       npy_intp*       A pointer to the dimensions array
+Smyvar       npy_intp*       A pointer to the strides array
+Dmyvar       int             The number of dimensions
+myvar_array  PyArrayObject*  The entire structure for the array
+===========  ==============  =========================================
+
+The in-lined code can contain references to any of these variables as
+well as to the standard macros MYVAR1(i), MYVAR2(i,j), MYVAR3(i,j,k),
+and MYVAR4(i,j,k,l). These name-based macros (they are the Python name
+capitalized followed by the number of dimensions needed) will de-
+reference the memory for the array at the given location with no error
+checking (be-sure to use the correct macro and ensure the array is
+aligned and in correct byte-swap order in order to get useful
+results). The following code shows how you might use these variables
+and macros to code a loop in C that computes a simple 2-d weighted
+averaging filter.
+
+.. code-block:: c++
+
+    int i,j;
+    for(i=1;i<Na[0]-1;i++) {
+       for(j=1;j<Na[1]-1;j++) {
+           B2(i,j) = A2(i,j) + (A2(i-1,j) +
+                     A2(i+1,j)+A2(i,j-1)
+                     + A2(i,j+1))*0.5
+                     + (A2(i-1,j-1)
+                     + A2(i-1,j+1)
+                     + A2(i+1,j-1)
+                     + A2(i+1,j+1))*0.25
+       }
+    }
+
+The above code doesn't have any error checking and so could fail with
+a Python crash if, a had the wrong number of dimensions, or b
+did not have the same shape as a. However, it could be placed
+inside a standard Python function with the necessary error checking to
+produce a robust but fast subroutine.
+
+One final note about weave.inline: if you have additional code you
+want to include in the final extension module such as supporting
+function calls, include statments, etc. you can pass this code in as a
+string using the keyword support_code: weave.inline(code, variables,
+support_code=support). If you need the extension module to link
+against an additional library then you can also pass in
+distutils-style keyword arguments such as library_dirs, libraries,
+and/or runtime_library_dirs which point to the appropriate libraries
+and directories.
+
+Simplify creation of an extension module
+----------------------------------------
+
+The inline function creates one extension module for each function to-
+be inlined. It also generates a lot of intermediate code that is
+duplicated for each extension module. If you have several related
+codes to execute in C, it would be better to make them all separate
+functions in a single extension module with multiple functions. You
+can also use the tools weave provides to produce this larger extension
+module. In fact, the weave.inline function just uses these more
+general tools to do its work.
+
+The approach is to:
+
+1. construct a extension module object using
+   ext_tools.ext_module(module_name);
+
+2. create function objects using ext_tools.ext_function(func_name,
+   code, variables);
+
+3. (optional) add support code to the function using the
+   .customize.add_support_code( support_code ) method of the
+   function object;
+
+4. add the functions to the extension module object using the
+   .add_function(func) method;
+
+5. when all the functions are added, compile the extension with its
+   .compile() method.
+
+Several examples are available in the examples directory where weave
+is installed on your system. Look particularly at ramp2.py,
+increment_example.py and fibonacii.py
+
+
+Conclusion
+----------
+
+Weave is a useful tool for quickly routines in C/C++ and linking them
+into Python. It's caching-mechanism allows for on-the-fly compilation
+which makes it particularly attractive for in-house code. Because of
+the requirement that the user have a C++-compiler, it can be difficult
+(but not impossible) to distribute a package that uses weave to other
+users who don't have a compiler installed. Of course, weave could be
+used to construct an extension module which is then distributed in the
+normal way *(* using a setup.py file). While you can use weave to
+build larger extension modules with many methods, creating methods
+with a variable- number of arguments is not possible. Thus, for a more
+sophisticated module, you will still probably want a Python-layer that
+calls the weave-produced extension.
+
+.. index::
+   single: weave
+
+
+Pyrex
+=====
+
+Pyrex is a way to write C-extension modules using Python-like syntax.
+It is an interesting way to generate extension modules that is growing
+in popularity, particularly among people who have rusty or non-
+existent C-skills. It does require the user to write the "interface"
+code and so is more time-consuming than SWIG or f2py if you are trying
+to interface to a large library of code. However, if you are writing
+an extension module that will include quite a bit of your own
+algorithmic code, as well, then Pyrex is a good match. A big weakness
+perhaps is the inability to easily and quickly access the elements of
+a multidimensional array.
+
+.. index::
+   single: pyrex
+
+Notice that Pyrex is an extension-module generator only. Unlike weave
+or f2py, it includes no automatic facility for compiling and linking
+the extension module (which must be done in the usual fashion). It
+does provide a modified distutils class called build_ext which lets
+you build an extension module from a .pyx source. Thus, you could
+write in a setup.py file:
+
+.. code-block:: python
+
+    from Pyrex.Distutils import build_ext
+    from distutils.extension import Extension
+    from distutils.core import setup
+
+    import numpy
+    py_ext = Extension('mine', ['mine.pyx'],
+             include_dirs=[numpy.get_include()])
+
+    setup(name='mine', description='Nothing',
+          ext_modules=[pyx_ext],
+          cmdclass = {'build_ext':build_ext})
+
+Adding the NumPy include directory is, of course, only necessary if
+you are using NumPy arrays in the extension module (which is what I
+assume you are using Pyrex for). The distutils extensions in NumPy
+also include support for automatically producing the extension-module
+and linking it from a .pyx file. It works so that if the user does
+not have Pyrex installed, then it looks for a file with the same
+file-name but a .c extension which it then uses instead of trying
+to produce the .c file again.
+
+Pyrex does not natively understand NumPy arrays. However, it is not
+difficult to include information that lets Pyrex deal with them
+usefully. In fact, the numpy.random.mtrand module was written using
+Pyrex so an example of Pyrex usage is already included in the NumPy
+source distribution. That experience led to the creation of a standard
+c_numpy.pxd file that you can use to simplify interacting with NumPy
+array objects in a Pyrex-written extension. The file may not be
+complete (it wasn't at the time of this writing). If you have
+additions you'd like to contribute, please send them. The file is
+located in the .../site-packages/numpy/doc/pyrex directory where you
+have Python installed. There is also an example in that directory of
+using Pyrex to construct a simple extension module. It shows that
+Pyrex looks a lot like Python but also contains some new syntax that
+is necessary in order to get C-like speed.
+
+If you just use Pyrex to compile a standard Python module, then you
+will get a C-extension module that runs either as fast or, possibly,
+more slowly than the equivalent Python module. Speed increases are
+possible only when you use cdef to statically define C variables and
+use a special construct to create for loops:
+
+.. code-block:: none
+
+    cdef int i
+    for i from start <= i < stop
+
+Let's look at two examples we've seen before to see how they might be
+implemented using Pyrex. These examples were compiled into extension
+modules using Pyrex-0.9.3.1.
+
+
+Pyrex-add
+---------
+
+Here is part of a Pyrex-file I named add.pyx which implements the add
+functions we previously implemented using f2py:
+
+.. code-block:: none
+
+    cimport c_numpy
+    from c_numpy cimport import_array, ndarray, npy_intp, npy_cdouble, \
+         npy_cfloat, NPY_DOUBLE, NPY_CDOUBLE, NPY_FLOAT, \
+         NPY_CFLOAT
+
+    #We need to initialize NumPy
+    import_array()
+
+    def zadd(object ao, object bo):
+        cdef ndarray c, a, b
+        cdef npy_intp i
+        a = c_numpy.PyArray_ContiguousFromAny(ao,
+                      NPY_CDOUBLE, 1, 1)
+        b = c_numpy.PyArray_ContiguousFromAny(bo,
+                      NPY_CDOUBLE, 1, 1)
+        c = c_numpy.PyArray_SimpleNew(a.nd, a.dimensions,
+                     a.descr.type_num)
+        for i from 0 <= i < a.dimensions[0]:
+            (<npy_cdouble *>c.data)[i].real = \
+                 (<npy_cdouble *>a.data)[i].real + \
+                 (<npy_cdouble *>b.data)[i].real
+            (<npy_cdouble *>c.data)[i].imag = \
+                 (<npy_cdouble *>a.data)[i].imag + \
+                 (<npy_cdouble *>b.data)[i].imag
+        return c
+
+This module shows use of the cimport statement to load the
+definitions from the c_numpy.pxd file. As shown, both versions of the
+import statement are supported. It also shows use of the NumPy C-API
+to construct NumPy arrays from arbitrary input objects. The array c is
+created using PyArray_SimpleNew. Then the c-array is filled by
+addition. Casting to a particiular data-type is accomplished using
+<cast \*>. Pointers are de-referenced with bracket notation and
+members of structures are accessed using '.' notation even if the
+object is techinically a pointer to a structure. The use of the
+special for loop construct ensures that the underlying code will have
+a similar C-loop so the addition calculation will proceed quickly.
+Notice that we have not checked for NULL after calling to the C-API
+--- a cardinal sin when writing C-code. For routines that return
+Python objects, Pyrex inserts the checks for NULL into the C-code for
+you and returns with failure if need be. There is also a way to get
+Pyrex to automatically check for exceptions when you call functions
+that don't return Python objects. See the documentation of Pyrex for
+details.
+
+
+Pyrex-filter
+------------
+
+The two-dimensional example we created using weave is a bit uglierto
+implement in Pyrex because two-dimensional indexing using Pyrex is not
+as simple. But, it is straightforward (and possibly faster because of
+pre-computed indices). Here is the Pyrex-file I named image.pyx.
+
+.. code-block:: none
+
+    cimport c_numpy
+    from c_numpy cimport import_array, ndarray, npy_intp,\
+         NPY_DOUBLE, NPY_CDOUBLE, \
+         NPY_FLOAT, NPY_CFLOAT, NPY_ALIGNED \
+
+    #We need to initialize NumPy
+    import_array()
+    def filter(object ao):
+        cdef ndarray a, b
+        cdef npy_intp i, j, M, N, oS
+        cdef npy_intp r,rm1,rp1,c,cm1,cp1
+        cdef double value
+        # Require an ALIGNED array
+        # (but not necessarily contiguous)
+        #  We will use strides to access the elements.
+        a = c_numpy.PyArray_FROMANY(ao, NPY_DOUBLE, \
+                    2, 2, NPY_ALIGNED)
+        b = c_numpy.PyArray_SimpleNew(a.nd,a.dimensions, \
+                                      a.descr.type_num)
+        M = a.dimensions[0]
+        N = a.dimensions[1]
+        S0 = a.strides[0]
+        S1 = a.strides[1]
+        for i from 1 <= i < M-1:
+            r = i*S0
+            rm1 = r-S0
+            rp1 = r+S0
+            oS = i*N
+            for j from 1 <= j < N-1:
+                c = j*S1
+                cm1 = c-S1
+                cp1 = c+S1
+                (<double *>b.data)[oS+j] = \
+                   (<double *>(a.data+r+c))[0] + \
+                   ((<double *>(a.data+rm1+c))[0] + \
+                    (<double *>(a.data+rp1+c))[0] + \
+                    (<double *>(a.data+r+cm1))[0] + \
+                    (<double *>(a.data+r+cp1))[0])*0.5 + \
+                   ((<double *>(a.data+rm1+cm1))[0] + \
+                    (<double *>(a.data+rp1+cm1))[0] + \
+                    (<double *>(a.data+rp1+cp1))[0] + \
+                    (<double *>(a.data+rm1+cp1))[0])*0.25
+        return b
+
+This 2-d averaging filter runs quickly because the loop is in C and
+the pointer computations are done only as needed. However, it is not
+particularly easy to understand what is happening. A 2-d image, in
+, can be filtered using this code very quickly using:
+
+.. code-block:: python
+
+    import image
+    out = image.filter(in)
+
+
+Conclusion
+----------
+
+There are several disadvantages of using Pyrex:
+
+1. The syntax for Pyrex can get a bit bulky, and it can be confusing at
+   first to understand what kind of objects you are getting and how to
+   interface them with C-like constructs.
+
+2. Inappropriate Pyrex syntax or incorrect calls to C-code or type-
+   mismatches can result in failures such as
+
+    1. Pyrex failing to generate the extension module source code,
+
+    2. Compiler failure while generating the extension module binary due to
+       incorrect C syntax,
+
+    3. Python failure when trying to use the module.
+
+
+3. It is easy to lose a clean separation between Python and C which makes
+   re-using your C-code for other non-Python-related projects more
+   difficult.
+
+4. Multi-dimensional arrays are "bulky" to index (appropriate macros
+   may be able to fix this).
+
+5. The C-code generated by Prex is hard to read and modify (and typically
+   compiles with annoying but harmless warnings).
+
+Writing a good Pyrex extension module still takes a bit of effort
+because not only does it require (a little) familiarity with C, but
+also with Pyrex's brand of Python-mixed-with C. One big advantage of
+Pyrex-generated extension modules is that they are easy to distribute
+using distutils. In summary, Pyrex is a very capable tool for either
+gluing C-code or generating an extension module quickly and should not
+be over-looked. It is especially useful for people that can't or won't
+write C-code or Fortran code. But, if you are already able to write
+simple subroutines in C or Fortran, then I would use one of the other
+approaches such as f2py (for Fortran), ctypes (for C shared-
+libraries), or weave (for inline C-code).
+
+.. index::
+   single: pyrex
+
+
+
+
+ctypes
+======
+
+Ctypes is a python extension module (downloaded separately for Python
+<2.5 and included with Python 2.5) that allows you to call an
+arbitrary function in a shared library directly from Python. This
+approach allows you to interface with C-code directly from Python.
+This opens up an enormous number of libraries for use from Python. The
+drawback, however, is that coding mistakes can lead to ugly program
+crashes very easily (just as can happen in C) because there is little
+type or bounds checking done on the parameters. This is especially
+true when array data is passed in as a pointer to a raw memory
+location. The responsibility is then on you that the subroutine will
+not access memory outside the actual array area. But, if you don't
+mind living a little dangerously ctypes can be an effective tool for
+quickly taking advantage of a large shared library (or writing
+extended functionality in your own shared library).
+
+.. index::
+   single: ctypes
+
+Because the ctypes approach exposes a raw interface to the compiled
+code it is not always tolerant of user mistakes. Robust use of the
+ctypes module typically involves an additional layer of Python code in
+order to check the data types and array bounds of objects passed to
+the underlying subroutine. This additional layer of checking (not to
+mention the conversion from ctypes objects to C-data-types that ctypes
+itself performs), will make the interface slower than a hand-written
+extension-module interface. However, this overhead should be neglible
+if the C-routine being called is doing any significant amount of work.
+If you are a great Python programmer with weak C-skills, ctypes is an
+easy way to write a useful interface to a (shared) library of compiled
+code.
+
+To use c-types you must
+
+1. Have a shared library.
+
+2. Load the shared library.
+
+3. Convert the python objects to ctypes-understood arguments.
+
+4. Call the function from the library with the ctypes arguments.
+
+
+Having a shared library
+-----------------------
+
+There are several requirements for a shared library that can be used
+with c-types that are platform specific. This guide assumes you have
+some familiarity with making a shared library on your system (or
+simply have a shared library available to you). Items to remember are:
+
+- A shared library must be compiled in a special way ( *e.g.* using
+  the -shared flag with gcc).
+
+- On some platforms (*e.g.* Windows) , a shared library requires a
+  .def file that specifies the functions to be exported. For example a
+  mylib.def file might contain.
+
+  ::
+
+      LIBRARY mylib.dll
+      EXPORTS
+      cool_function1
+      cool_function2
+
+  Alternatively, you may be able to use the storage-class specifier
+  __declspec(dllexport) in the C-definition of the function to avoid the
+  need for this .def file.
+
+There is no standard way in Python distutils to create a standard
+shared library (an extension module is a "special" shared library
+Python understands) in a cross-platform manner. Thus, a big
+disadvantage of ctypes at the time of writing this book is that it is
+difficult to distribute in a cross-platform manner a Python extension
+that uses c-types and includes your own code which should be compiled
+as a shared library on the users system.
+
+
+Loading the shared library
+--------------------------
+
+A simple, but robust way to load the shared library is to get the
+absolute path name and load it using the cdll object of ctypes.:
+
+.. code-block:: python
+
+    lib = ctypes.cdll[<full_path_name>]
+
+However, on Windows accessing an attribute of the cdll method will
+load the first DLL by that name found in the current directory or on
+the PATH. Loading the absolute path name requires a little finesse for
+cross-platform work since the extension of shared libraries varies.
+There is a ctypes.util.find_library utility available that can
+simplify the process of finding the library to load but it is not
+foolproof. Complicating matters, different platforms have different
+default extensions used by shared libraries (e.g. .dll -- Windows, .so
+-- Linux, .dylib -- Mac OS X). This must also be taken into account if
+you are using c-types to wrap code that needs to work on several
+platforms.
+
+NumPy provides a convenience function called
+:func:ctypeslib.load_library (name, path). This function takes the name
+of the shared library (including any prefix like 'lib' but excluding
+the extension) and a path where the shared library can be located. It
+returns a ctypes library object or raises an OSError if the library
+cannot be found or raises an ImportError if the ctypes module is not
+available. (Windows users: the ctypes library object loaded using
+:func:load_library is always loaded assuming cdecl calling convention.
+See the ctypes documentation under ctypes.windll and/or ctypes.oledll
+for ways to load libraries under other calling conventions).
+
+The functions in the shared library are available as attributes of the
+ctypes library object (returned from :func:ctypeslib.load_library) or
+as items using lib['func_name'] syntax. The latter method for
+retrieving a function name is particularly useful if the function name
+contains characters that are not allowable in Python variable names.
+
+
+Converting arguments
+--------------------
+
+Python ints/longs, strings, and unicode objects are automatically
+converted as needed to equivalent c-types arguments The None object is
+also converted automatically to a NULL pointer. All other Python
+objects must be converted to ctypes-specific types. There are two ways
+around this restriction that allow c-types to integrate with other
+objects.
+
+1. Don't set the argtypes attribute of the function object and define an
+   :obj:_as_parameter_ method for the object you want to pass in. The
+   :obj:_as_parameter_ method must return a Python int which will be passed
+   directly to the function.
+
+2. Set the argtypes attribute to a list whose entries contain objects
+   with a classmethod named from_param that knows how to convert your
+   object to an object that ctypes can understand (an int/long, string,
+   unicode, or object with the :obj:_as_parameter_ attribute).
+
+NumPy uses both methods with a preference for the second method
+because it can be safer. The ctypes attribute of the ndarray returns
+an object that has an _as_parameter\_ attribute which returns an
+integer representing the address of the ndarray to which it is
+associated. As a result, one can pass this ctypes attribute object
+directly to a function expecting a pointer to the data in your
+ndarray. The caller must be sure that the ndarray object is of the
+correct type, shape, and has the correct flags set or risk nasty
+crashes if the data-pointer to inappropriate arrays are passsed in.
+
+To implement the second method, NumPy provides the class-factory
+function :func:ndpointer in the :mod:ctypeslib module. This
+class-factory function produces an appropriate class that can be
+placed in an argtypes attribute entry of a ctypes function. The class
+will contain a from_param method which ctypes will use to convert any
+ndarray passed in to the function to a ctypes-recognized object. In
+the process, the conversion will perform checking on any properties of
+the ndarray that were specified by the user in the call to :func:ndpointer.
+Aspects of the ndarray that can be checked include the data-type, the
+number-of-dimensions, the shape, and/or the state of the flags on any
+array passed. The return value of the from_param method is the ctypes
+attribute of the array which (because it contains the _as_parameter\_
+attribute pointing to the array data area) can be used by ctypes
+directly.
+
+The ctypes attribute of an ndarray is also endowed with additional
+attributes that may be convenient when passing additional information
+about the array into a ctypes function. The attributes **data**,
+**shape**, and **strides** can provide c-types compatible types
+corresponding to the data-area, the shape, and the strides of the
+array. The data attribute reutrns a c_void_p representing a
+pointer to the data area. The shape and strides attributes each return
+an array of ctypes integers (or None representing a NULL pointer, if a
+0-d array). The base ctype of the array is a ctype integer of the same
+size as a pointer on the platform. There are also methods
+data_as({ctype}), shape_as(<base ctype>), and strides_as(<base
+ctype>). These return the data as a ctype object of your choice and
+the shape/strides arrays using an underlying base type of your choice.
+For convenience, the **ctypeslib** module also contains **c_intp** as
+a ctypes integer data-type whose size is the same as the size of
+c_void_p on the platform (it's value is None if ctypes is not
+installed).
+
+
+Calling the function
+--------------------
+
+The function is accessed as an attribute of or an item from the loaded
+shared-library. Thus, if "./mylib.so" has a function named
+"cool_function1" , I could access this function either as:
+
+.. code-block:: python
+
+    lib = numpy.ctypeslib.load_library('mylib','.')
+    func1 = lib.cool_function1 # or equivalently
+    func1 = lib['cool_function1']
+
+In ctypes, the return-value of a function is set to be 'int' by
+default. This behavior can be changed by setting the restype attribute
+of the function. Use None for the restype if the function has no
+return value ('void'):
+
+.. code-block:: python
+
+    func1.restype = None
+
+As previously discussed, you can also set the argtypes attribute of
+the function in order to have ctypes check the types of the input
+arguments when the function is called. Use the :func:ndpointer factory
+function to generate a ready-made class for data-type, shape, and
+flags checking on your new function. The :func:ndpointer function has the
+signature
+
+.. function:: ndpointer(dtype=None, ndim=None, shape=None, flags=None)
+
+    Keyword arguments with the value None are not checked.
+    Specifying a keyword enforces checking of that aspect of the
+    ndarray on conversion to a ctypes-compatible object. The dtype
+    keyword can be any object understood as a data-type object. The
+    ndim keyword should be an integer, and the shape keyword should be
+    an integer or a sequence of integers. The flags keyword specifies
+    the minimal flags that are required on any array passed in. This
+    can be specified as a string of comma separated requirements, an
+    integer indicating the requirement bits OR'd together, or a flags
+    object returned from the flags attribute of an array with the
+    necessary requirements.
+
+Using an ndpointer class in the argtypes method can make it
+significantly safer to call a C-function using ctypes and the data-
+area of an ndarray. You may still want to wrap the function in an
+additional Python wrapper to make it user-friendly (hiding some
+obvious arguments and making some arguments output arguments). In this
+process, the **requires** function in NumPy may be useful to return the right kind of array from
+a given input.
+
+
+Complete example
+----------------
+
+In this example, I will show how the addition function and the filter
+function implemented previously using the other approaches can be
+implemented using ctypes. First, the C-code which implements the
+algorithms contains the functions zadd, dadd, sadd, cadd, and
+dfilter2d. The zadd function is:
+
+.. code-block:: c
+
+    /* Add arrays of contiguous data */
+    typedef struct {double real; double imag;} cdouble;
+    typedef struct {float real; float imag;} cfloat;
+    void zadd(cdouble *a, cdouble *b, cdouble *c, long n)
+    {
+        while (n--) {
+            c->real = a->real + b->real;
+            c->imag = a->imag + b->imag;
+            a++; b++; c++;
+        }
+    }
+
+with similar code for cadd, dadd, and sadd that handles complex float,
+double, and float data-types, respectively:
+
+.. code-block:: c
+
+    void cadd(cfloat *a, cfloat *b, cfloat *c, long n)
+    {
+            while (n--) {
+                    c->real = a->real + b->real;
+                    c->imag = a->imag + b->imag;
+                    a++; b++; c++;
+            }
+    }
+    void dadd(double *a, double *b, double *c, long n)
+    {
+            while (n--) {
+                    *c++ = *a++ + *b++;
+            }
+    }
+    void sadd(float *a, float *b, float *c, long n)
+    {
+            while (n--) {
+                    *c++ = *a++ + *b++;
+            }
+    }
+
+The code.c file also contains the function dfilter2d:
+
+.. code-block:: c
+
+    /* Assumes b is contiguous and
+       a has strides that are multiples of sizeof(double)
+    */
+    void
+    dfilter2d(double *a, double *b, int *astrides, int *dims)
+    {
+        int i, j, M, N, S0, S1;
+        int r, c, rm1, rp1, cp1, cm1;
+
+        M = dims[0]; N = dims[1];
+        S0 = astrides[0]/sizeof(double);
+        S1=astrides[1]/sizeof(double);
+        for (i=1; i<M-1; i++) {
+            r = i*S0; rp1 = r+S0; rm1 = r-S0;
+            for (j=1; j<N-1; j++) {
+                c = j*S1; cp1 = j+S1; cm1 = j-S1;
+                b[i*N+j] = a[r+c] +                 \
+                    (a[rp1+c] + a[rm1+c] +          \
+                     a[r+cp1] + a[r+cm1])*0.5 +     \
+                    (a[rp1+cp1] + a[rp1+cm1] +      \
+                     a[rm1+cp1] + a[rm1+cp1])*0.25;
+            }
+        }
+    }
+
+A possible advantage this code has over the Fortran-equivalent code is
+that it takes arbitrarily strided (i.e. non-contiguous arrays) and may
+also run faster depending on the optimization capability of your
+compiler. But, it is a obviously more complicated than the simple code
+in filter.f. This code must be compiled into a shared library. On my
+Linux system this is accomplished using::
+
+    gcc -o code.so -shared code.c
+
+Which creates a shared_library named code.so in the current directory.
+On Windows don't forget to either add __declspec(dllexport) in front
+of void on the line preceeding each function definition, or write a
+code.def file that lists the names of the functions to be exported.
+
+A suitable Python interface to this shared library should be
+constructed. To do this create a file named interface.py with the
+following lines at the top:
+
+.. code-block:: python
+
+    __all__ = ['add', 'filter2d']
+
+    import numpy as N
+    import os
+
+    _path = os.path.dirname('__file__')
+    lib = N.ctypeslib.load_library('code', _path)
+    _typedict = {'zadd' : complex, 'sadd' : N.single,
+                 'cadd' : N.csingle, 'dadd' : float}
+    for name in _typedict.keys():
+        val = getattr(lib, name)
+        val.restype = None
+        _type = _typedict[name]
+        val.argtypes = [N.ctypeslib.ndpointer(_type,
+                          flags='aligned, contiguous'),
+                        N.ctypeslib.ndpointer(_type,
+                          flags='aligned, contiguous'),
+                        N.ctypeslib.ndpointer(_type,
+                          flags='aligned, contiguous,'\
+                                'writeable'),
+                        N.ctypeslib.c_intp]
+
+This code loads the shared library named code.{ext} located in the
+same path as this file. It then adds a return type of void to the
+functions contained in the library. It also adds argument checking to
+the functions in the library so that ndarrays can be passed as the
+first three arguments along with an integer (large enough to hold a
+pointer on the platform) as the fourth argument.
+
+Setting up the filtering function is similar and allows the filtering
+function to be called with ndarray arguments as the first two
+arguments and with pointers to integers (large enough to handle the
+strides and shape of an ndarray) as the last two arguments.:
+
+.. code-block:: python
+
+    lib.dfilter2d.restype=None
+    lib.dfilter2d.argtypes = [N.ctypeslib.ndpointer(float, ndim=2,
+                                           flags='aligned'),
+                              N.ctypeslib.ndpointer(float, ndim=2,
+                                     flags='aligned, contiguous,'\
+                                           'writeable'),
+                              ctypes.POINTER(N.ctypeslib.c_intp),
+                              ctypes.POINTER(N.ctypeslib.c_intp)]
+
+Next, define a simple selection function that chooses which addition
+function to call in the shared library based on the data-type:
+
+.. code-block:: python
+
+    def select(dtype):
+        if dtype.char in ['?bBhHf']:
+            return lib.sadd, single
+        elif dtype.char in ['F']:
+            return lib.cadd, csingle
+        elif dtype.char in ['DG']:
+            return lib.zadd, complex
+        else:
+            return lib.dadd, float
+        return func, ntype
+
+Finally, the two functions to be exported by the interface can be
+written simply as:
+
+.. code-block:: python
+
+    def add(a, b):
+        requires = ['CONTIGUOUS', 'ALIGNED']
+        a = N.asanyarray(a)
+        func, dtype = select(a.dtype)
+        a = N.require(a, dtype, requires)
+        b = N.require(b, dtype, requires)
+        c = N.empty_like(a)
+        func(a,b,c,a.size)
+        return c
+
+and:
+
+.. code-block:: python
+
+    def filter2d(a):
+        a = N.require(a, float, ['ALIGNED'])
+        b = N.zeros_like(a)
+        lib.dfilter2d(a, b, a.ctypes.strides, a.ctypes.shape)
+        return b
+
+
+Conclusion
+----------
+
+.. index::
+   single: ctypes
+
+Using ctypes is a powerful way to connect Python with arbitrary
+C-code. It's advantages for extending Python include
+
+- clean separation of C-code from Python code
+
+    - no need to learn a new syntax except Python and C
+
+    - allows re-use of C-code
+
+    - functionality in shared libraries written for other purposes can be
+      obtained with a simple Python wrapper and search for the library.
+
+
+- easy integration with NumPy through the ctypes attribute
+
+- full argument checking with the ndpointer class factory
+
+It's disadvantages include
+
+- It is difficult to distribute an extension module made using ctypes
+  because of a lack of support for building shared libraries in
+  distutils (but I suspect this will change in time).
+
+- You must have shared-libraries of your code (no static libraries).
+
+- Very little support for C++ code and it's different library-calling
+  conventions. You will probably need a C-wrapper around C++ code to use
+  with ctypes (or just use Boost.Python instead).
+
+Because of the difficulty in distributing an extension module made
+using ctypes, f2py is still the easiest way to extend Python for
+package creation. However, ctypes is a close second and will probably
+be growing in popularity now that it is part of the Python
+distribution. This should bring more features to ctypes that should
+eliminate the difficulty in extending Python and distributing the
+extension using ctypes.
+
+
+Additional tools you may find useful
+====================================
+
+These tools have been found useful by others using Python and so are
+included here. They are discussed separately because I see them as
+either older ways to do things more modernly handled by f2py, weave,
+Pyrex, or ctypes (SWIG, PyFort, PyInline) or because I don't know much
+about them (SIP, Boost, Instant). I have not added links to these
+methods because my experience is that you can find the most relevant
+link faster using Google or some other search engine, and any links
+provided here would be quickly dated. Do not assume that just because
+it is included in this list, I don't think the package deserves your
+attention. I'm including information about these packages because many
+people have found them useful and I'd like to give you as many options
+as possible for tackling the problem of easily integrating your code.
+
+
+SWIG
+----
+
+.. index::
+   single: swig
+
+Simplified Wrapper and Interface Generator (SWIG) is an old and fairly
+stable method for wrapping C/C++-libraries to a large variety of other
+languages. It does not specifically understand NumPy arrays but can be
+made useable with NumPy through the use of typemaps. There are some
+sample typemaps in the numpy/doc/swig directory under numpy.i along
+with an example module that makes use of them. SWIG excels at wrapping
+large C/C++ libraries because it can (almost) parse their headers and
+auto-produce an interface. Technically, you need to generate a .i
+file that defines the interface. Often, however, this .i file can
+be parts of the header itself. The interface usually needs a bit of
+tweaking to be very useful. This ability to parse C/C++ headers and
+auto-generate the interface still makes SWIG a useful approach to
+adding functionalilty from C/C++ into Python, despite the other
+methods that have emerged that are more targeted to Python. SWIG can
+actually target extensions for several languages, but the typemaps
+usually have to be language-specific. Nonetheless, with modifications
+to the Python-specific typemaps, SWIG can be used to interface a
+library with other languages such as Perl, Tcl, and Ruby.
+
+My experience with SWIG has been generally positive in that it is
+relatively easy to use and quite powerful. I used to use it quite
+often before becoming more proficient at writing C-extensions.
+However, I struggled writing custom interfaces with SWIG because it
+must be done using the concept of typemaps which are not Python
+specific and are written in a C-like syntax. Therefore, I tend to
+prefer other gluing strategies and would only attempt to use SWIG to
+wrap a very-large C/C++ library. Nonetheless, there are others who use
+SWIG quite happily.
+
+
+SIP
+---
+
+.. index::
+   single: SIP
+
+SIP is another tool for wrapping C/C++ libraries that is Python
+specific and appears to have very good support for C++. Riverbank
+Computing developed SIP in order to create Python bindings to the QT
+library. An interface file must be written to generate the binding,
+but the interface file looks a lot like a C/C++ header file. While SIP
+is not a full C++ parser, it understands quite a bit of C++ syntax as
+well as its own special directives that allow modification of how the
+Python binding is accomplished. It also allows the user to define
+mappings between Python types and C/C++ structrues and classes.
+
+
+Boost Python
+------------
+
+.. index::
+   single: Boost.Python
+
+Boost is a repository of C++ libraries and Boost.Python is one of
+those libraries which provides a concise interface for binding C++
+classes and functions to Python. The amazing part of the Boost.Python
+approach is that it works entirely in pure C++ without introducing a
+new syntax. Many users of C++ report that Boost.Python makes it
+possible to combine the best of both worlds in a seamless fashion. I
+have not used Boost.Python because I am not a big user of C++ and
+using Boost to wrap simple C-subroutines is usually over-kill. It's
+primary purpose is to make C++ classes available in Python. So, if you
+have a set of C++ classes that need to be integrated cleanly into
+Python, consider learning about and using Boost.Python.
+
+
+Instant
+-------
+
+.. index::
+   single: Instant
+
+This is a relatively new package (called pyinstant at sourceforge)
+that builds on top of SWIG to make it easy to inline C and C++ code in
+Python very much like weave. However, Instant builds extension modules
+on the fly with specific module names and specific method names. In
+this repsect it is more more like f2py in its behavior. The extension
+modules are built on-the fly (as long as the SWIG is installed). They
+can then be imported. Here is an example of using Instant with NumPy
+arrays (adapted from the test2 included in the Instant distribution):
+
+.. code-block:: python
+
+    code="""
+    PyObject* add(PyObject* a_, PyObject* b_){
+      /*
+      various checks
+      */
+      PyArrayObject* a=(PyArrayObject*) a_;
+      PyArrayObject* b=(PyArrayObject*) b_;
+      int n = a->dimensions[0];
+      int dims[1];
+      dims[0] = n;
+      PyArrayObject* ret;
+      ret = (PyArrayObject*) PyArray_FromDims(1, dims, NPY_DOUBLE);
+      int i;
+      char *aj=a->data;
+      char *bj=b->data;
+      double *retj = (double *)ret->data;
+      for (i=0; i < n; i++) {
+        *retj++ = *((double *)aj) + *((double *)bj);
+        aj += a->strides[0];
+        bj += b->strides[0];
+      }
+    return (PyObject *)ret;
+    }
+    """
+    import Instant, numpy
+    ext = Instant.Instant()
+    ext.create_extension(code=s, headers=["numpy/arrayobject.h"],
+                         include_dirs=[numpy.get_include()],
+                         init_code='import_array();', module="test2b_ext")
+    import test2b_ext
+    a = numpy.arange(1000)
+    b = numpy.arange(1000)
+    d = test2b_ext.add(a,b)
+
+Except perhaps for the dependence on SWIG, Instant is a
+straightforward utility for writing extension modules.
+
+
+PyInline
+--------
+
+This is a much older module that allows automatic building of
+extension modules so that C-code can be included with Python code.
+It's latest release (version 0.03) was in 2001, and it appears that it
+is not being updated.
+
+
+PyFort
+------
+
+PyFort is a nice tool for wrapping Fortran and Fortran-like C-code
+into Python with support for Numeric arrays. It was written by Paul
+Dubois, a distinguished computer scientist and the very first
+maintainer of Numeric (now retired). It is worth mentioning in the
+hopes that somebody will update PyFort to work with NumPy arrays as
+well which now support either Fortran or C-style contiguous arrays.

Added: numpy-docs/trunk/source/user/c-info.rst
===================================================================
--- numpy-docs/trunk/source/user/c-info.rst	2008-10-26 17:50:36 UTC (rev 5958)
+++ numpy-docs/trunk/source/user/c-info.rst	2008-10-26 17:57:55 UTC (rev 5959)
@@ -0,0 +1,9 @@
+#################
+Using Numpy C-API
+#################
+
+.. toctree::
+
+   c-info.how-to-extend
+   c-info.python-as-glue
+   c-info.beyond-basics

Added: numpy-docs/trunk/source/user/howtofind.rst
===================================================================
--- numpy-docs/trunk/source/user/howtofind.rst	2008-10-26 17:50:36 UTC (rev 5958)
+++ numpy-docs/trunk/source/user/howtofind.rst	2008-10-26 17:57:55 UTC (rev 5959)
@@ -0,0 +1,9 @@
+*************************
+How to find documentation
+*************************
+
+.. seealso:: :ref:Numpy-specific help functions <routines.help>
+
+.. note:: XXX: this part is not yet written.
+
+.. automodule:: numpy.doc.howtofind

Added: numpy-docs/trunk/source/user/index.rst
===================================================================
--- numpy-docs/trunk/source/user/index.rst	2008-10-26 17:50:36 UTC (rev 5958)
+++ numpy-docs/trunk/source/user/index.rst	2008-10-26 17:57:55 UTC (rev 5959)
@@ -0,0 +1,27 @@
+.. _user:
+
+################
+Numpy User Guide
+################
+
+This guide explains how to make use of different features
+of Numpy. For a detailed documentation about different functions
+and classes, see :ref:reference.
+
+.. warning::
+
+   This "User Guide" is still very much work in progress; the material
+   is not organized, and many aspects of Numpy are not covered.
+
+   More documentation for Numpy can be found on the
+   scipy.org <http://www.scipy.org/Documentation>__ website.
+
+.. toctree::
+   :maxdepth: 2
+
+   howtofind
+   basics
+   performance
+   misc
+   c-info
+

Added: numpy-docs/trunk/source/user/misc.rst
===================================================================
--- numpy-docs/trunk/source/user/misc.rst	2008-10-26 17:50:36 UTC (rev 5958)
+++ numpy-docs/trunk/source/user/misc.rst	2008-10-26 17:57:55 UTC (rev 5959)
@@ -0,0 +1,9 @@
+*************
+Miscellaneous
+*************
+
+.. note:: XXX: This section is not yet written.
+
+.. automodule:: numpy.doc.misc
+
+.. automodule:: numpy.doc.methods_vs_functions

Added: numpy-docs/trunk/source/user/performance.rst
===================================================================
--- numpy-docs/trunk/source/user/performance.rst	2008-10-26 17:50:36 UTC (rev 5958)
+++ numpy-docs/trunk/source/user/performance.rst	2008-10-26 17:57:55 UTC (rev 5959)
@@ -0,0 +1,7 @@
+***********
+Performance
+***********
+
+.. note:: XXX: This section is not yet written.
+
+.. automodule:: numpy.doc.performance

Added: numpy-docs/trunk/summarize.py
===================================================================
--- numpy-docs/trunk/summarize.py	2008-10-26 17:50:36 UTC (rev 5958)
+++ numpy-docs/trunk/summarize.py	2008-10-26 17:57:55 UTC (rev 5959)
@@ -0,0 +1,167 @@
+#!/usr/bin/env python
+"""
+summarize.py
+
+Show a summary about which Numpy functions are documented and which are not.
+
+"""
+
+import os, glob, re, sys, inspect, optparse
+sys.path.append(os.path.join(os.path.dirname(__file__), 'ext'))
+from ext.phantom_import import import_phantom_module
+
+from ext.autosummary_generate import get_documented
+
+CUR_DIR = os.path.dirname(__file__)
+SOURCE_DIR = os.path.join(CUR_DIR, 'source', 'reference')
+
+SKIP_LIST = """
+# --- aliases:
+alltrue sometrue bitwise_not cumproduct
+row_stack column_stack product rank
+
+# -- skipped:
+core lib f2py dual doc emath ma rec char distutils oldnumeric numarray
+testing version matlib
+
+add_docstring add_newdoc add_newdocs fastCopyAndTranspose pkgload
+conjugate disp
+
+int0 object0 unicode0 uint0 string_ string0 void0
+
+flagsobj
+
+setup setupscons PackageLoader
+
+lib.scimath.arccos lib.scimath.arcsin lib.scimath.arccosh lib.scimath.arcsinh
+lib.scimath.arctanh lib.scimath.log lib.scimath.log2 lib.scimath.log10
+lib.scimath.logn lib.scimath.power lib.scimath.sqrt
+
+# --- numpy.random:
+random random.info random.mtrand random.ranf random.sample random.random
+
+# --- numpy.fft:
+fft fft.Tester fft.bench fft.fftpack fft.fftpack_lite fft.helper
+fft.refft fft.refft2 fft.refftn fft.irefft fft.irefft2 fft.irefftn
+fft.info fft.test
+
+# --- numpy.linalg:
+linalg linalg.Tester
+linalg.bench linalg.info linalg.lapack_lite linalg.linalg linalg.test
+
+# --- numpy.ctypeslib:
+ctypeslib ctypeslib.test
+
+""".split()
+
+def main():
+    p = optparse.OptionParser(__doc__)
+    options, args = p.parse_args()
+
+    if len(args) != 0:
+        p.error('Wrong number of arguments')
+
+    # prepare
+    fn = os.path.join(CUR_DIR, 'dump.xml')
+    if os.path.isfile(fn):
+        import_phantom_module(fn)
+
+    # check
+    documented, undocumented = check_numpy()
+
+    # report
+    in_sections = {}
+    for name, locations in documented.iteritems():
+        for (filename, section, keyword, toctree) in locations:
+            in_sections.setdefault((filename, section, keyword), []).append(name)
+
+    print "Documented"
+    print "==========\n"
+
+    last_filename = None
+    for (filename, section, keyword), names in sorted(in_sections.items()):
+        if filename != last_filename:
+            print "--- %s\n" % filename
+        last_filename = filename
+        print " ** ", section
+        print format_in_columns(sorted(names))
+        print "\n"
+
+    print ""
+    print "Undocumented"
+    print "============\n"
+    print format_in_columns(sorted(undocumented.keys()))
+
+def check_numpy():
+    documented = get_documented(glob.glob(SOURCE_DIR + '/*.rst'))
+    undocumented = {}
+
+    import numpy, numpy.fft, numpy.linalg, numpy.random
+    for mod in [numpy, numpy.fft, numpy.linalg, numpy.random,
+                numpy.ctypeslib, numpy.emath, numpy.ma]:
+        undocumented.update(get_undocumented(documented, mod, skip=SKIP_LIST))
+
+    for d in (documented, undocumented):
+        for k in d.keys():
+            if k.startswith('numpy.'):
+                d[k[6:]] = d[k]
+                del d[k]
+
+    return documented, undocumented
+
+def get_undocumented(documented, module, module_name=None, skip=[]):
+    """
+    Find out which items in Numpy are not documented.
+
+    Returns
+    -------
+    undocumented : dict of bool
+        Dictionary containing True for each documented item name
+        and False for each undocumented one.
+
+    """
+    undocumented = {}
+
+    if module_name is None:
+        module_name = module.__name__
+
+    for name in dir(module):
+        obj = getattr(module, name)
+        if name.startswith('_'): continue
+
+        full_name = '.'.join([module_name, name])
+
+        if full_name in skip: continue
+        if full_name.startswith('numpy.') and full_name[6:] in skip: continue
+        if not (inspect.ismodule(obj) or callable(obj) or inspect.isclass(obj)):
+            continue
+
+        if full_name not in documented:
+            undocumented[full_name] = True
+
+    return undocumented
+
+def format_in_columns(lst):
+    """
+    Format a list containing strings to a string containing the items
+    in columns.
+    """
+    lst = map(str, lst)
+    col_len = max(map(len, lst)) + 2
+    ncols = 80//col_len
+    if ncols == 0:
+        ncols = 1
+
+    if len(lst) % ncols == 0:
+        nrows = len(lst)//ncols
+    else:
+        nrows = 1 + len(lst)//ncols
+
+    fmt = ' %%-%ds ' % (col_len-2)
+
+    lines = []
+    for n in range(nrows):
+        lines.append("".join([fmt % x for x in lst[n::nrows]]))
+    return "\n".join(lines)
+
+if __name__ == "__main__": main()

Property changes on: numpy-docs/trunk/summarize.py
___________________________________________________________________
Name: svn:executable
+

`

More information about the Numpy-svn mailing list