746 lines
49 KiB
HTML
746 lines
49 KiB
HTML
|
|
|||
|
<!DOCTYPE html>
|
|||
|
<html lang="en">
|
|||
|
<head>
|
|||
|
<meta charset="utf-8">
|
|||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|||
|
<meta name="color-scheme" content="light dark">
|
|||
|
<title>PEP 209 – Multi-dimensional Arrays | peps.python.org</title>
|
|||
|
<link rel="shortcut icon" href="../_static/py.png">
|
|||
|
<link rel="canonical" href="https://peps.python.org/pep-0209/">
|
|||
|
<link rel="stylesheet" href="../_static/style.css" type="text/css">
|
|||
|
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
|
|||
|
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
|
|||
|
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
|
|||
|
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
|
|||
|
<meta property="og:title" content='PEP 209 – Multi-dimensional Arrays | peps.python.org'>
|
|||
|
<meta property="og:description" content="This PEP proposes a redesign and re-implementation of the multi-dimensional array module, Numeric, to make it easier to add new features and functionality to the module. Aspects of Numeric 2 that will receive special attention are efficient access to a...">
|
|||
|
<meta property="og:type" content="website">
|
|||
|
<meta property="og:url" content="https://peps.python.org/pep-0209/">
|
|||
|
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
|
|||
|
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
|
|||
|
<meta property="og:image:alt" content="Python PEPs">
|
|||
|
<meta property="og:image:width" content="200">
|
|||
|
<meta property="og:image:height" content="200">
|
|||
|
<meta name="description" content="This PEP proposes a redesign and re-implementation of the multi-dimensional array module, Numeric, to make it easier to add new features and functionality to the module. Aspects of Numeric 2 that will receive special attention are efficient access to a...">
|
|||
|
<meta name="theme-color" content="#3776ab">
|
|||
|
</head>
|
|||
|
<body>
|
|||
|
|
|||
|
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
|
|||
|
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
|
|||
|
<title>Following system colour scheme</title>
|
|||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
|
|||
|
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|||
|
<circle cx="12" cy="12" r="9"></circle>
|
|||
|
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
|
|||
|
</svg>
|
|||
|
</symbol>
|
|||
|
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
|
|||
|
<title>Selected dark colour scheme</title>
|
|||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
|
|||
|
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|||
|
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
|
|||
|
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
|
|||
|
</svg>
|
|||
|
</symbol>
|
|||
|
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
|
|||
|
<title>Selected light colour scheme</title>
|
|||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
|
|||
|
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|||
|
<circle cx="12" cy="12" r="5"></circle>
|
|||
|
<line x1="12" y1="1" x2="12" y2="3"></line>
|
|||
|
<line x1="12" y1="21" x2="12" y2="23"></line>
|
|||
|
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
|
|||
|
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
|
|||
|
<line x1="1" y1="12" x2="3" y2="12"></line>
|
|||
|
<line x1="21" y1="12" x2="23" y2="12"></line>
|
|||
|
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
|
|||
|
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
|
|||
|
</svg>
|
|||
|
</symbol>
|
|||
|
</svg>
|
|||
|
<script>
|
|||
|
|
|||
|
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
|
|||
|
</script>
|
|||
|
<section id="pep-page-section">
|
|||
|
<header>
|
|||
|
<h1>Python Enhancement Proposals</h1>
|
|||
|
<ul class="breadcrumbs">
|
|||
|
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> » </li>
|
|||
|
<li><a href="../pep-0000/">PEP Index</a> » </li>
|
|||
|
<li>PEP 209</li>
|
|||
|
</ul>
|
|||
|
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
|
|||
|
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
|
|||
|
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
|
|||
|
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
|
|||
|
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
|
|||
|
</button>
|
|||
|
</header>
|
|||
|
<article>
|
|||
|
<section id="pep-content">
|
|||
|
<h1 class="page-title">PEP 209 – Multi-dimensional Arrays</h1>
|
|||
|
<dl class="rfc2822 field-list simple">
|
|||
|
<dt class="field-odd">Author<span class="colon">:</span></dt>
|
|||
|
<dd class="field-odd">Paul Barrett <barrett at stsci.edu>, Travis Oliphant <oliphant at ee.byu.edu></dd>
|
|||
|
<dt class="field-even">Status<span class="colon">:</span></dt>
|
|||
|
<dd class="field-even"><abbr title="Removed from consideration by sponsor or authors">Withdrawn</abbr></dd>
|
|||
|
<dt class="field-odd">Type<span class="colon">:</span></dt>
|
|||
|
<dd class="field-odd"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd>
|
|||
|
<dt class="field-even">Created<span class="colon">:</span></dt>
|
|||
|
<dd class="field-even">03-Jan-2001</dd>
|
|||
|
<dt class="field-odd">Python-Version<span class="colon">:</span></dt>
|
|||
|
<dd class="field-odd">2.2</dd>
|
|||
|
<dt class="field-even">Post-History<span class="colon">:</span></dt>
|
|||
|
<dd class="field-even"><p></p></dd>
|
|||
|
</dl>
|
|||
|
<hr class="docutils" />
|
|||
|
<section id="contents">
|
|||
|
<details><summary>Table of Contents</summary><ul class="simple">
|
|||
|
<li><a class="reference internal" href="#abstract">Abstract</a></li>
|
|||
|
<li><a class="reference internal" href="#motivation">Motivation</a></li>
|
|||
|
<li><a class="reference internal" href="#proposal">Proposal</a></li>
|
|||
|
<li><a class="reference internal" href="#design-and-implementation">Design and Implementation</a></li>
|
|||
|
<li><a class="reference internal" href="#open-issues">Open Issues</a></li>
|
|||
|
<li><a class="reference internal" href="#implementation-steps">Implementation Steps</a></li>
|
|||
|
<li><a class="reference internal" href="#incompatibilities">Incompatibilities</a></li>
|
|||
|
<li><a class="reference internal" href="#appendices">Appendices</a></li>
|
|||
|
<li><a class="reference internal" href="#copyright">Copyright</a></li>
|
|||
|
<li><a class="reference internal" href="#related-peps">Related PEPs</a></li>
|
|||
|
<li><a class="reference internal" href="#references">References</a></li>
|
|||
|
</ul>
|
|||
|
</details></section>
|
|||
|
<div class="pep-banner sticky-banner deprecated withdrawn admonition important">
|
|||
|
<p class="admonition-title">Important</p>
|
|||
|
<p>This PEP has been withdrawn.</p>
|
|||
|
<p class="close-button">×</p>
|
|||
|
<p></p>
|
|||
|
</div>
|
|||
|
<section id="abstract">
|
|||
|
<h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2>
|
|||
|
<p>This PEP proposes a redesign and re-implementation of the
|
|||
|
multi-dimensional array module, Numeric, to make it easier to add
|
|||
|
new features and functionality to the module. Aspects of Numeric 2
|
|||
|
that will receive special attention are efficient access to arrays
|
|||
|
exceeding a gigabyte in size and composed of inhomogeneous data
|
|||
|
structures or records. The proposed design uses four Python
|
|||
|
classes: ArrayType, UFunc, Array, and ArrayView; and a low-level
|
|||
|
C-extension module, _ufunc, to handle the array operations
|
|||
|
efficiently. In addition, each array type has its own C-extension
|
|||
|
module which defines the coercion rules, operations, and methods
|
|||
|
for that type. This design enables new types, features, and
|
|||
|
functionality to be added in a modular fashion. The new version
|
|||
|
will introduce some incompatibilities with the current Numeric.</p>
|
|||
|
</section>
|
|||
|
<section id="motivation">
|
|||
|
<h2><a class="toc-backref" href="#motivation" role="doc-backlink">Motivation</a></h2>
|
|||
|
<p>Multi-dimensional arrays are commonly used to store and manipulate
|
|||
|
data in science, engineering, and computing. Python currently has
|
|||
|
an extension module, named Numeric (henceforth called Numeric 1),
|
|||
|
which provides a satisfactory set of functionality for users
|
|||
|
manipulating homogeneous arrays of data of moderate size (of order
|
|||
|
10 MB). For access to larger arrays (of order 100 MB or more) of
|
|||
|
possibly inhomogeneous data, the implementation of Numeric 1 is
|
|||
|
inefficient and cumbersome. In the future, requests by the
|
|||
|
Numerical Python community for additional functionality is also
|
|||
|
likely as PEPs 211: Adding New Linear Operators to Python, and
|
|||
|
225: Elementwise/Objectwise Operators illustrate.</p>
|
|||
|
</section>
|
|||
|
<section id="proposal">
|
|||
|
<h2><a class="toc-backref" href="#proposal" role="doc-backlink">Proposal</a></h2>
|
|||
|
<p>This proposal recommends a re-design and re-implementation of
|
|||
|
Numeric 1, henceforth called Numeric 2, which will enable new
|
|||
|
types, features, and functionality to be added in an easy and
|
|||
|
modular manner. The initial design of Numeric 2 should focus on
|
|||
|
providing a generic framework for manipulating arrays of various
|
|||
|
types and should enable a straightforward mechanism for adding new
|
|||
|
array types and UFuncs. Functional methods that are more specific
|
|||
|
to various disciplines can then be layered on top of this core.
|
|||
|
This new module will still be called Numeric and most of the
|
|||
|
behavior found in Numeric 1 will be preserved.</p>
|
|||
|
<p>The proposed design uses four Python classes: ArrayType, UFunc,
|
|||
|
Array, and ArrayView; and a low-level C-extension module to handle
|
|||
|
the array operations efficiently. In addition, each array type
|
|||
|
has its own C-extension module which defines the coercion rules,
|
|||
|
operations, and methods for that type. At a later date, when core
|
|||
|
functionality is stable, some Python classes can be converted to
|
|||
|
C-extension types.</p>
|
|||
|
<p>Some planned features are:</p>
|
|||
|
<ol class="arabic">
|
|||
|
<li>Improved memory usage<p>This feature is particularly important when handling large arrays
|
|||
|
and can produce significant improvements in performance as well as
|
|||
|
memory usage. We have identified several areas where memory usage
|
|||
|
can be improved:</p>
|
|||
|
<ol class="loweralpha">
|
|||
|
<li>Use a local coercion model<p>Instead of using Python’s global coercion model which creates
|
|||
|
temporary arrays, Numeric 2, like Numeric 1, will implement a
|
|||
|
local coercion model as described in <a class="pep reference internal" href="../pep-0208/" title="PEP 208 – Reworking the Coercion Model">PEP 208</a> which defers the
|
|||
|
responsibility of coercion to the operator. By using internal
|
|||
|
buffers, a coercion operation can be done for each array
|
|||
|
(including output arrays), if necessary, at the time of the
|
|||
|
operation. Benchmarks <a class="footnote-reference brackets" href="#id2" id="id1">[1]</a> have shown that performance is at
|
|||
|
most degraded only slightly and is improved in cases where the
|
|||
|
internal buffers are less than the L2 cache size and the
|
|||
|
processor is under load. To avoid array coercion altogether,
|
|||
|
C functions having arguments of mixed type are allowed in
|
|||
|
Numeric 2.</p>
|
|||
|
</li>
|
|||
|
<li>Avoid creation of temporary arrays<p>In complex array expressions (i.e. having more than one
|
|||
|
operation), each operation will create a temporary array which
|
|||
|
will be used and then deleted by the succeeding operation. A
|
|||
|
better approach would be to identify these temporary arrays
|
|||
|
and reuse their data buffers when possible, namely when the
|
|||
|
array shape and type are the same as the temporary array being
|
|||
|
created. This can be done by checking the temporary array’s
|
|||
|
reference count. If it is 1, then it will be deleted once the
|
|||
|
operation is done and is a candidate for reuse.</p>
|
|||
|
</li>
|
|||
|
<li>Optional use of memory-mapped files<p>Numeric users sometimes need to access data from very large
|
|||
|
files or to handle data that is greater than the available
|
|||
|
memory. Memory-mapped arrays provide a mechanism to do this
|
|||
|
by storing the data on disk while making it appear to be in
|
|||
|
memory. Memory- mapped arrays should improve access to all
|
|||
|
files by eliminating one of two copy steps during a file
|
|||
|
access. Numeric should be able to access in-memory and
|
|||
|
memory-mapped arrays transparently.</p>
|
|||
|
</li>
|
|||
|
<li>Record access<p>In some fields of science, data is stored in files as binary
|
|||
|
records. For example, in astronomy, photon data is stored as a
|
|||
|
1 dimensional list of photons in order of arrival time. These
|
|||
|
records or C-like structures contain information about the
|
|||
|
detected photon, such as its arrival time, its position on the
|
|||
|
detector, and its energy. Each field may be of a different
|
|||
|
type, such as char, int, or float. Such arrays introduce new
|
|||
|
issues that must be dealt with, in particular byte alignment
|
|||
|
or byte swapping may need to be performed for the numeric
|
|||
|
values to be properly accessed (though byte swapping is also
|
|||
|
an issue for memory mapped data). Numeric 2 is designed to
|
|||
|
automatically handle alignment and representational issues
|
|||
|
when data is accessed or operated on. There are two
|
|||
|
approaches to implementing records; as either a derived array
|
|||
|
class or a special array type, depending on your point-of-view.
|
|||
|
We defer this discussion to the Open Issues section.</p>
|
|||
|
</li>
|
|||
|
</ol>
|
|||
|
</li>
|
|||
|
<li>Additional array types<p>Numeric 1 has 11 defined types: char, ubyte, sbyte, short, int,
|
|||
|
long, float, double, cfloat, cdouble, and object. There are no
|
|||
|
ushort, uint, or ulong types, nor are there more complex types
|
|||
|
such as a bit type which is of use to some fields of science and
|
|||
|
possibly for implementing masked-arrays. The design of Numeric 1
|
|||
|
makes the addition of these and other types a difficult and
|
|||
|
error-prone process. To enable the easy addition (and deletion)
|
|||
|
of new array types such as a bit type described below, a re-design
|
|||
|
of Numeric is necessary.</p>
|
|||
|
<ol class="loweralpha">
|
|||
|
<li>Bit type<p>The result of a rich comparison between arrays is an array of
|
|||
|
boolean values. The result can be stored in an array of type
|
|||
|
char, but this is an unnecessary waste of memory. A better
|
|||
|
implementation would use a bit or boolean type, compressing
|
|||
|
the array size by a factor of eight. This is currently being
|
|||
|
implemented for Numeric 1 (by Travis Oliphant) and should be
|
|||
|
included in Numeric 2.</p>
|
|||
|
</li>
|
|||
|
</ol>
|
|||
|
</li>
|
|||
|
<li>Enhanced array indexing syntax<p>The extended slicing syntax was added to Python to provide greater
|
|||
|
flexibility when manipulating Numeric arrays by allowing
|
|||
|
step-sizes greater than 1. This syntax works well as a shorthand
|
|||
|
for a list of regularly spaced indices. For those situations
|
|||
|
where a list of irregularly spaced indices are needed, an enhanced
|
|||
|
array indexing syntax would allow 1-D arrays to be arguments.</p>
|
|||
|
</li>
|
|||
|
<li>Rich comparisons<p>The implementation of <a class="pep reference internal" href="../pep-0207/" title="PEP 207 – Rich Comparisons">PEP 207</a>: Rich Comparisons in Python 2.1
|
|||
|
provides additional flexibility when manipulating arrays. We
|
|||
|
intend to implement this feature in Numeric 2.</p>
|
|||
|
</li>
|
|||
|
<li>Array broadcasting rules<p>When an operation between a scalar and an array is done, the
|
|||
|
implied behavior is to create a new array having the same shape as
|
|||
|
the array operand containing the scalar value. This is called
|
|||
|
array broadcasting. It also works with arrays of lesser rank,
|
|||
|
such as vectors. This implicit behavior is implemented in Numeric
|
|||
|
1 and will also be implemented in Numeric 2.</p>
|
|||
|
</li>
|
|||
|
</ol>
|
|||
|
</section>
|
|||
|
<section id="design-and-implementation">
|
|||
|
<h2><a class="toc-backref" href="#design-and-implementation" role="doc-backlink">Design and Implementation</a></h2>
|
|||
|
<p>The design of Numeric 2 has four primary classes:</p>
|
|||
|
<ol class="arabic">
|
|||
|
<li>ArrayType:<p>This is a simple class that describes the fundamental properties
|
|||
|
of an array-type, e.g. its name, its size in bytes, its coercion
|
|||
|
relations with respect to other types, etc., e.g.</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">Int32</span> <span class="o">=</span> <span class="n">ArrayType</span><span class="p">(</span><span class="s1">'Int32'</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="s1">'doc-string'</span><span class="p">)</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>Its relation to the other types is defined when the C-extension
|
|||
|
module for that type is imported. The corresponding Python code
|
|||
|
is:</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">Int32</span><span class="o">.</span><span class="n">astype</span><span class="p">[</span><span class="n">Real64</span><span class="p">]</span> <span class="o">=</span> <span class="n">Real64</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>This says that the Real64 array-type has higher priority than the
|
|||
|
Int32 array-type.</p>
|
|||
|
<p>The following attributes and methods are proposed for the core
|
|||
|
implementation. Additional attributes can be added on an
|
|||
|
individual basis, e.g. .bitsize or .bitstrides for the bit type.</p>
|
|||
|
<p>Attributes:</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">.</span><span class="n">name</span><span class="p">:</span> <span class="n">e</span><span class="o">.</span><span class="n">g</span><span class="o">.</span> <span class="s2">"Int32"</span><span class="p">,</span> <span class="s2">"Float64"</span><span class="p">,</span> <span class="n">etc</span><span class="o">.</span>
|
|||
|
<span class="o">.</span><span class="n">typecode</span><span class="p">:</span> <span class="n">e</span><span class="o">.</span><span class="n">g</span><span class="o">.</span> <span class="s1">'i'</span><span class="p">,</span> <span class="s1">'f'</span><span class="p">,</span> <span class="n">etc</span><span class="o">.</span>
|
|||
|
<span class="p">(</span><span class="k">for</span> <span class="n">backward</span> <span class="n">compatibility</span><span class="p">)</span>
|
|||
|
<span class="o">.</span><span class="n">size</span> <span class="p">(</span><span class="ow">in</span> <span class="nb">bytes</span><span class="p">):</span> <span class="n">e</span><span class="o">.</span><span class="n">g</span><span class="o">.</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="n">etc</span><span class="o">.</span>
|
|||
|
<span class="o">.</span><span class="n">array_rules</span> <span class="p">(</span><span class="n">mapping</span><span class="p">):</span> <span class="n">rules</span> <span class="n">between</span> <span class="n">array</span> <span class="n">types</span>
|
|||
|
<span class="o">.</span><span class="n">pyobj_rules</span> <span class="p">(</span><span class="n">mapping</span><span class="p">):</span> <span class="n">rules</span> <span class="n">between</span> <span class="n">array</span> <span class="ow">and</span> <span class="n">python</span> <span class="n">types</span>
|
|||
|
<span class="o">.</span><span class="n">doc</span><span class="p">:</span> <span class="n">documentation</span> <span class="n">string</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>Methods:</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="fm">__init__</span><span class="p">():</span> <span class="n">initialization</span>
|
|||
|
<span class="fm">__del__</span><span class="p">():</span> <span class="n">destruction</span>
|
|||
|
<span class="fm">__repr__</span><span class="p">():</span> <span class="n">representation</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>C-API: This still needs to be fleshed-out.</p>
|
|||
|
</li>
|
|||
|
<li>UFunc:<p>This class is the heart of Numeric 2. Its design is similar to
|
|||
|
that of ArrayType in that the UFunc creates a singleton callable
|
|||
|
object whose attributes are name, total and input number of
|
|||
|
arguments, a document string, and an empty CFunc dictionary; e.g.</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">add</span> <span class="o">=</span> <span class="n">UFunc</span><span class="p">(</span><span class="s1">'add'</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="s1">'doc-string'</span><span class="p">)</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>When defined the add instance has no C functions associated with
|
|||
|
it and therefore can do no work. The CFunc dictionary is
|
|||
|
populated or registered later when the C-extension module for an
|
|||
|
array-type is imported. The arguments of the register method are:
|
|||
|
function name, function descriptor, and the CUFunc object. The
|
|||
|
corresponding Python code is</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">add</span><span class="o">.</span><span class="n">register</span><span class="p">(</span><span class="s1">'add'</span><span class="p">,</span> <span class="p">(</span><span class="n">Int32</span><span class="p">,</span> <span class="n">Int32</span><span class="p">,</span> <span class="n">Int32</span><span class="p">),</span> <span class="n">cfunc</span><span class="o">-</span><span class="n">add</span><span class="p">)</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>In the initialization function of an array type module, e.g.
|
|||
|
Int32, there are two C API functions: one to initialize the
|
|||
|
coercion rules and the other to register the CFunc objects.</p>
|
|||
|
<p>When an operation is applied to some arrays, the <code class="docutils literal notranslate"><span class="pre">__call__</span></code> method
|
|||
|
is invoked. It gets the type of each array (if the output array
|
|||
|
is not given, it is created from the coercion rules) and checks
|
|||
|
the CFunc dictionary for a key that matches the argument types.
|
|||
|
If it exists the operation is performed immediately, otherwise the
|
|||
|
coercion rules are used to search for a related operation and set
|
|||
|
of conversion functions. The <code class="docutils literal notranslate"><span class="pre">__call__</span></code> method then invokes a
|
|||
|
compute method written in C to iterate over slices of each array,
|
|||
|
namely:</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">_ufunc</span><span class="o">.</span><span class="n">compute</span><span class="p">(</span><span class="nb">slice</span><span class="p">,</span> <span class="n">data</span><span class="p">,</span> <span class="n">func</span><span class="p">,</span> <span class="n">swap</span><span class="p">,</span> <span class="n">conv</span><span class="p">)</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>The ‘func’ argument is a CFuncObject, while the ‘swap’ and ‘conv’
|
|||
|
arguments are lists of CFuncObjects for those arrays needing pre- or
|
|||
|
post-processing, otherwise None is used. The data argument is
|
|||
|
a list of buffer objects, and the slice argument gives the number
|
|||
|
of iterations for each dimension along with the buffer offset and
|
|||
|
step size for each array and each dimension.</p>
|
|||
|
<p>We have predefined several UFuncs for use by the <code class="docutils literal notranslate"><span class="pre">__call__</span></code> method:
|
|||
|
cast, swap, getobj, and setobj. The cast and swap functions do
|
|||
|
coercion and byte-swapping, respectively and the getobj and setobj
|
|||
|
functions do coercion between Numeric arrays and Python sequences.</p>
|
|||
|
<p>The following attributes and methods are proposed for the core
|
|||
|
implementation.</p>
|
|||
|
<p>Attributes:</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">.</span><span class="n">name</span><span class="p">:</span> <span class="n">e</span><span class="o">.</span><span class="n">g</span><span class="o">.</span> <span class="s2">"add"</span><span class="p">,</span> <span class="s2">"subtract"</span><span class="p">,</span> <span class="n">etc</span><span class="o">.</span>
|
|||
|
<span class="o">.</span><span class="n">nargs</span><span class="p">:</span> <span class="n">number</span> <span class="n">of</span> <span class="n">total</span> <span class="n">arguments</span>
|
|||
|
<span class="o">.</span><span class="n">iargs</span><span class="p">:</span> <span class="n">number</span> <span class="n">of</span> <span class="nb">input</span> <span class="n">arguments</span>
|
|||
|
<span class="o">.</span><span class="n">cfuncs</span> <span class="p">(</span><span class="n">mapping</span><span class="p">):</span> <span class="n">the</span> <span class="nb">set</span> <span class="n">C</span> <span class="n">functions</span>
|
|||
|
<span class="o">.</span><span class="n">doc</span><span class="p">:</span> <span class="n">documentation</span> <span class="n">string</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>Methods:</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="fm">__init__</span><span class="p">():</span> <span class="n">initialization</span>
|
|||
|
<span class="fm">__del__</span><span class="p">():</span> <span class="n">destruction</span>
|
|||
|
<span class="fm">__repr__</span><span class="p">():</span> <span class="n">representation</span>
|
|||
|
<span class="fm">__call__</span><span class="p">():</span> <span class="n">look</span><span class="o">-</span><span class="n">up</span> <span class="ow">and</span> <span class="n">dispatch</span> <span class="n">method</span>
|
|||
|
<span class="n">initrule</span><span class="p">():</span> <span class="n">initialize</span> <span class="n">coercion</span> <span class="n">rule</span>
|
|||
|
<span class="n">uninitrule</span><span class="p">():</span> <span class="n">uninitialize</span> <span class="n">coercion</span> <span class="n">rule</span>
|
|||
|
<span class="n">register</span><span class="p">():</span> <span class="n">register</span> <span class="n">a</span> <span class="n">CUFunc</span>
|
|||
|
<span class="n">unregister</span><span class="p">():</span> <span class="n">unregister</span> <span class="n">a</span> <span class="n">CUFunc</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>C-API: This still needs to be fleshed-out.</p>
|
|||
|
</li>
|
|||
|
<li>Array:<p>This class contains information about the array, such as shape,
|
|||
|
type, endian-ness of the data, etc.. Its operators, ‘+’, ‘-‘,
|
|||
|
etc. just invoke the corresponding UFunc function, e.g.</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="fm">__add__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
|
|||
|
<span class="k">return</span> <span class="n">ufunc</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">)</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>The following attributes, methods, and functions are proposed for
|
|||
|
the core implementation.</p>
|
|||
|
<p>Attributes:</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">.</span><span class="n">shape</span><span class="p">:</span> <span class="n">shape</span> <span class="n">of</span> <span class="n">the</span> <span class="n">array</span>
|
|||
|
<span class="o">.</span><span class="n">format</span><span class="p">:</span> <span class="nb">type</span> <span class="n">of</span> <span class="n">the</span> <span class="n">array</span>
|
|||
|
<span class="o">.</span><span class="n">real</span> <span class="p">(</span><span class="n">only</span> <span class="nb">complex</span><span class="p">):</span> <span class="n">real</span> <span class="n">part</span> <span class="n">of</span> <span class="n">a</span> <span class="nb">complex</span> <span class="n">array</span>
|
|||
|
<span class="o">.</span><span class="n">imag</span> <span class="p">(</span><span class="n">only</span> <span class="nb">complex</span><span class="p">):</span> <span class="n">imaginary</span> <span class="n">part</span> <span class="n">of</span> <span class="n">a</span> <span class="nb">complex</span> <span class="n">array</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>Methods:</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="fm">__init__</span><span class="p">():</span> <span class="n">initialization</span>
|
|||
|
<span class="fm">__del__</span><span class="p">():</span> <span class="n">destruction</span>
|
|||
|
<span class="n">__repr_</span><span class="p">():</span> <span class="n">representation</span>
|
|||
|
<span class="fm">__str__</span><span class="p">():</span> <span class="n">pretty</span> <span class="n">representation</span>
|
|||
|
<span class="n">__cmp__</span><span class="p">():</span> <span class="n">rich</span> <span class="n">comparison</span>
|
|||
|
<span class="fm">__len__</span><span class="p">():</span>
|
|||
|
<span class="fm">__getitem__</span><span class="p">():</span>
|
|||
|
<span class="fm">__setitem__</span><span class="p">():</span>
|
|||
|
<span class="n">__getslice__</span><span class="p">():</span>
|
|||
|
<span class="n">__setslice__</span><span class="p">():</span>
|
|||
|
<span class="n">numeric</span> <span class="n">methods</span><span class="p">:</span>
|
|||
|
<span class="n">copy</span><span class="p">():</span> <span class="n">copy</span> <span class="n">of</span> <span class="n">array</span>
|
|||
|
<span class="n">aslist</span><span class="p">():</span> <span class="n">create</span> <span class="nb">list</span> <span class="kn">from</span> <span class="nn">array</span>
|
|||
|
<span class="n">asstring</span><span class="p">():</span> <span class="n">create</span> <span class="n">string</span> <span class="kn">from</span> <span class="nn">array</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>Functions:</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">fromlist</span><span class="p">():</span> <span class="n">create</span> <span class="n">array</span> <span class="kn">from</span> <span class="nn">sequence</span>
|
|||
|
<span class="n">fromstring</span><span class="p">():</span> <span class="n">create</span> <span class="n">array</span> <span class="kn">from</span> <span class="nn">string</span>
|
|||
|
<span class="n">array</span><span class="p">():</span> <span class="n">create</span> <span class="n">array</span> <span class="k">with</span> <span class="n">shape</span> <span class="ow">and</span> <span class="n">value</span>
|
|||
|
<span class="n">concat</span><span class="p">():</span> <span class="n">concatenate</span> <span class="n">two</span> <span class="n">arrays</span>
|
|||
|
<span class="n">resize</span><span class="p">():</span> <span class="n">resize</span> <span class="n">array</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>C-API: This still needs to be fleshed-out.</p>
|
|||
|
</li>
|
|||
|
<li>ArrayView<p>This class is similar to the Array class except that the reshape
|
|||
|
and flat methods will raise exceptions, since non-contiguous
|
|||
|
arrays cannot be reshaped or flattened using just pointer and
|
|||
|
step-size information.</p>
|
|||
|
<p>C-API: This still needs to be fleshed-out.</p>
|
|||
|
</li>
|
|||
|
<li>C-extension modules:<p>Numeric2 will have several C-extension modules.</p>
|
|||
|
<ol class="loweralpha">
|
|||
|
<li>_ufunc:<p>The primary module of this set is the _ufuncmodule.c. The
|
|||
|
intention of this module is to do the bare minimum,
|
|||
|
i.e. iterate over arrays using a specified C function. The
|
|||
|
interface of these functions is the same as Numeric 1, i.e.</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">int</span> <span class="p">(</span><span class="o">*</span><span class="n">CFunc</span><span class="p">)(</span><span class="n">char</span> <span class="o">*</span><span class="n">data</span><span class="p">,</span> <span class="nb">int</span> <span class="o">*</span><span class="n">steps</span><span class="p">,</span> <span class="nb">int</span> <span class="n">repeat</span><span class="p">,</span> <span class="n">void</span> <span class="o">*</span><span class="n">func</span><span class="p">);</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>and their functionality is expected to be the same, i.e. they
|
|||
|
iterate over the inner-most dimension.</p>
|
|||
|
<p>The following attributes and methods are proposed for the core
|
|||
|
implementation.</p>
|
|||
|
<p>Attributes:</p>
|
|||
|
<p>Methods:</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">compute</span><span class="p">():</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>C-API: This still needs to be fleshed-out.</p>
|
|||
|
</li>
|
|||
|
<li>_int32, _real64, etc.:<p>There will also be C-extension modules for each array type,
|
|||
|
e.g. _int32module.c, _real64module.c, etc. As mentioned
|
|||
|
previously, when these modules are imported by the UFunc
|
|||
|
module, they will automatically register their functions and
|
|||
|
coercion rules. New or improved versions of these modules can
|
|||
|
be easily implemented and used without affecting the rest of
|
|||
|
Numeric 2.</p>
|
|||
|
</li>
|
|||
|
</ol>
|
|||
|
</li>
|
|||
|
</ol>
|
|||
|
</section>
|
|||
|
<section id="open-issues">
|
|||
|
<h2><a class="toc-backref" href="#open-issues" role="doc-backlink">Open Issues</a></h2>
|
|||
|
<ol class="arabic">
|
|||
|
<li>Does slicing syntax default to copy or view behavior?<p>The default behavior of Python is to return a copy of a sub-list
|
|||
|
or tuple when slicing syntax is used, whereas Numeric 1 returns a
|
|||
|
view into the array. The choice made for Numeric 1 is apparently
|
|||
|
for reasons of performance: the developers wish to avoid the
|
|||
|
penalty of allocating and copying the data buffer during each
|
|||
|
array operation and feel that the need for a deep copy of an array
|
|||
|
to be rare. Yet, some have argued that Numeric’s slice notation
|
|||
|
should also have copy behavior to be consistent with Python lists.
|
|||
|
In this case the performance penalty associated with copy behavior
|
|||
|
can be minimized by implementing copy-on-write. This scheme has
|
|||
|
both arrays sharing one data buffer (as in view behavior) until
|
|||
|
either array is assigned new data at which point a copy of the
|
|||
|
data buffer is made. View behavior would then be implemented by
|
|||
|
an ArrayView class, whose behavior be similar to Numeric 1 arrays,
|
|||
|
i.e. .shape is not settable for non-contiguous arrays. The use of
|
|||
|
an ArrayView class also makes explicit what type of data the array
|
|||
|
contains.</p>
|
|||
|
</li>
|
|||
|
<li>Does item syntax default to copy or view behavior?<p>A similar question arises with the item syntax. For example, if
|
|||
|
<code class="docutils literal notranslate"><span class="pre">a</span> <span class="pre">=</span> <span class="pre">[[0,1,2],</span> <span class="pre">[3,4,5]]</span></code> and <code class="docutils literal notranslate"><span class="pre">b</span> <span class="pre">=</span> <span class="pre">a[0]</span></code>, then changing <code class="docutils literal notranslate"><span class="pre">b[0]</span></code> also changes
|
|||
|
<code class="docutils literal notranslate"><span class="pre">a[0][0]</span></code>, because <code class="docutils literal notranslate"><span class="pre">a[0]</span></code> is a reference or view of the first row of a.
|
|||
|
Therefore, if c is a 2-d array, it would appear that <code class="docutils literal notranslate"><span class="pre">c[i]</span></code>
|
|||
|
should return a 1-d array which is a view into, instead of a copy
|
|||
|
of, c for consistency. Yet, <code class="docutils literal notranslate"><span class="pre">c[i]</span></code> can be considered just a
|
|||
|
shorthand for <code class="docutils literal notranslate"><span class="pre">c[i,:]</span></code> which would imply copy behavior assuming
|
|||
|
slicing syntax returns a copy. Should Numeric 2 behave the same
|
|||
|
way as lists and return a view or should it return a copy.</p>
|
|||
|
</li>
|
|||
|
<li>How is scalar coercion implemented?<p>Python has fewer numeric types than Numeric which can cause
|
|||
|
coercion problems. For example, when multiplying a Python scalar
|
|||
|
of type float and a Numeric array of type float, the Numeric array
|
|||
|
is converted to a double, since the Python float type is actually
|
|||
|
a double. This is often not the desired behavior, since the
|
|||
|
Numeric array will be doubled in size which is likely to be
|
|||
|
annoying, particularly for very large arrays. We prefer that the
|
|||
|
array type trumps the python type for the same type class, namely
|
|||
|
integer, float, and complex. Therefore, an operation between a
|
|||
|
Python integer and an Int16 (short) array will return an Int16
|
|||
|
array. Whereas an operation between a Python float and an Int16
|
|||
|
array would return a Float64 (double) array. Operations between
|
|||
|
two arrays use normal coercion rules.</p>
|
|||
|
</li>
|
|||
|
<li>How is integer division handled?<p>In a future version of Python, the behavior of integer division
|
|||
|
will change. The operands will be converted to floats, so the
|
|||
|
result will be a float. If we implement the proposed scalar
|
|||
|
coercion rules where arrays have precedence over Python scalars,
|
|||
|
then dividing an array by an integer will return an integer array
|
|||
|
and will not be consistent with a future version of Python which
|
|||
|
would return an array of type double. Scientific programmers are
|
|||
|
familiar with the distinction between integer and float-point
|
|||
|
division, so should Numeric 2 continue with this behavior?</p>
|
|||
|
</li>
|
|||
|
<li>How should records be implemented?<p>There are two approaches to implementing records depending on your
|
|||
|
point-of-view. The first is two divide arrays into separate
|
|||
|
classes depending on the behavior of their types. For example,
|
|||
|
numeric arrays are one class, strings a second, and records a
|
|||
|
third, because the range and type of operations of each class
|
|||
|
differ. As such, a record array is not a new type, but a
|
|||
|
mechanism for a more flexible form of array. To easily access and
|
|||
|
manipulate such complex data, the class is comprised of numeric
|
|||
|
arrays having different byte offsets into the data buffer. For
|
|||
|
example, one might have a table consisting of an array of Int16,
|
|||
|
Real32 values. Two numeric arrays, one with an offset of 0 bytes
|
|||
|
and a stride of 6 bytes to be interpreted as Int16, and one with an
|
|||
|
offset of 2 bytes and a stride of 6 bytes to be interpreted as
|
|||
|
Real32 would represent the record array. Both numeric arrays
|
|||
|
would refer to the same data buffer, but have different offset and
|
|||
|
stride attributes, and a different numeric type.</p>
|
|||
|
<p>The second approach is to consider a record as one of many array
|
|||
|
types, albeit with fewer, and possibly different, array operations
|
|||
|
than for numeric arrays. This approach considers an array type to
|
|||
|
be a mapping of a fixed-length string. The mapping can either be
|
|||
|
simple, like integer and floating-point numbers, or complex, like
|
|||
|
a complex number, a byte string, and a C-structure. The record
|
|||
|
type effectively merges the struct and Numeric modules into a
|
|||
|
multi-dimensional struct array. This approach implies certain
|
|||
|
changes to the array interface. For example, the ‘typecode’
|
|||
|
keyword argument should probably be changed to the more
|
|||
|
descriptive ‘format’ keyword.</p>
|
|||
|
<ol class="loweralpha">
|
|||
|
<li>How are record semantics defined and implemented?<p>Which ever implementation approach is taken for records, the
|
|||
|
syntax and semantics of how they are to be accessed and
|
|||
|
manipulated must be decided, if one wishes to have access to
|
|||
|
sub-fields of records. In this case, the record type can
|
|||
|
essentially be considered an inhomogeneous list, like a tuple
|
|||
|
returned by the unpack method of the struct module; and a 1-d
|
|||
|
array of records may be interpreted as a 2-d array with the
|
|||
|
second dimension being the index into the list of fields.
|
|||
|
This enhanced array semantics makes access to an array of one
|
|||
|
or more of the fields easy and straightforward. It also
|
|||
|
allows a user to do array operations on a field in a natural
|
|||
|
and intuitive way. If we assume that records are implemented
|
|||
|
as an array type, then last dimension defaults to 0 and can
|
|||
|
therefore be neglected for arrays comprised of simple types,
|
|||
|
like numeric.</p>
|
|||
|
</li>
|
|||
|
</ol>
|
|||
|
</li>
|
|||
|
<li>How are masked-arrays implemented?<p>Masked-arrays in Numeric 1 are implemented as a separate array
|
|||
|
class. With the ability to add new array types to Numeric 2, it
|
|||
|
is possible that masked-arrays in Numeric 2 could be implemented
|
|||
|
as a new array type instead of an array class.</p>
|
|||
|
</li>
|
|||
|
<li>How are numerical errors handled (IEEE floating-point errors in
|
|||
|
particular)?<p>It is not clear to the proposers (Paul Barrett and Travis
|
|||
|
Oliphant) what is the best or preferred way of handling errors.
|
|||
|
Since most of the C functions that do the operation, iterate over
|
|||
|
the inner-most (last) dimension of the array. This dimension
|
|||
|
could contain a thousand or more items having one or more errors
|
|||
|
of differing type, such as divide-by-zero, underflow, and
|
|||
|
overflow. Additionally, keeping track of these errors may come at
|
|||
|
the expense of performance. Therefore, we suggest several
|
|||
|
options:</p>
|
|||
|
<ol class="loweralpha simple">
|
|||
|
<li>Print a message of the most severe error, leaving it to
|
|||
|
the user to locate the errors.</li>
|
|||
|
<li>Print a message of all errors that occurred and the number
|
|||
|
of occurrences, leaving it to the user to locate the errors.</li>
|
|||
|
<li>Print a message of all errors that occurred and a list of
|
|||
|
where they occurred.</li>
|
|||
|
<li>Or use a hybrid approach, printing only the most severe
|
|||
|
error, yet keeping track of what and where the errors
|
|||
|
occurred. This would allow the user to locate the errors
|
|||
|
while keeping the error message brief.</li>
|
|||
|
</ol>
|
|||
|
</li>
|
|||
|
<li>What features are needed to ease the integration of FORTRAN
|
|||
|
libraries and code?</li>
|
|||
|
</ol>
|
|||
|
<p>It would be a good idea at this stage to consider how to ease the
|
|||
|
integration of FORTRAN libraries and user code in Numeric 2.</p>
|
|||
|
</section>
|
|||
|
<section id="implementation-steps">
|
|||
|
<h2><a class="toc-backref" href="#implementation-steps" role="doc-backlink">Implementation Steps</a></h2>
|
|||
|
<ol class="arabic">
|
|||
|
<li>Implement basic UFunc capability<ol class="loweralpha">
|
|||
|
<li>Minimal Array class:<p>Necessary class attributes and methods, e.g. .shape, .data,
|
|||
|
.type, etc.</p>
|
|||
|
</li>
|
|||
|
<li>Minimal ArrayType class:<p>Int32, Real64, Complex64, Char, Object</p>
|
|||
|
</li>
|
|||
|
<li>Minimal UFunc class:<p>UFunc instantiation, CFunction registration, UFunc call for
|
|||
|
1-D arrays including the rules for doing alignment,
|
|||
|
byte-swapping, and coercion.</p>
|
|||
|
</li>
|
|||
|
<li>Minimal C-extension module:<p>_UFunc, which does the innermost array loop in C.</p>
|
|||
|
<p>This step implements whatever is needed to do: ‘c = add(a, b)’
|
|||
|
where a, b, and c are 1-D arrays. It teaches us how to add
|
|||
|
new UFuncs, to coerce the arrays, to pass the necessary
|
|||
|
information to a C iterator method and to do the actually
|
|||
|
computation.</p>
|
|||
|
</li>
|
|||
|
</ol>
|
|||
|
</li>
|
|||
|
<li>Continue enhancing the UFunc iterator and Array class<ol class="loweralpha simple">
|
|||
|
<li>Implement some access methods for the Array class:
|
|||
|
print, repr, getitem, setitem, etc.</li>
|
|||
|
<li>Implement multidimensional arrays</li>
|
|||
|
<li>Implement some of basic Array methods using UFuncs:
|
|||
|
+, -, *, /, etc.</li>
|
|||
|
<li>Enable UFuncs to use Python sequences.</li>
|
|||
|
</ol>
|
|||
|
</li>
|
|||
|
<li>Complete the standard UFunc and Array class behavior<ol class="loweralpha simple">
|
|||
|
<li>Implement getslice and setslice behavior</li>
|
|||
|
<li>Work on Array broadcasting rules</li>
|
|||
|
<li>Implement Record type</li>
|
|||
|
</ol>
|
|||
|
</li>
|
|||
|
<li>Add additional functionality<ol class="loweralpha simple">
|
|||
|
<li>Add more UFuncs</li>
|
|||
|
<li>Implement buffer or mmap access</li>
|
|||
|
</ol>
|
|||
|
</li>
|
|||
|
</ol>
|
|||
|
</section>
|
|||
|
<section id="incompatibilities">
|
|||
|
<h2><a class="toc-backref" href="#incompatibilities" role="doc-backlink">Incompatibilities</a></h2>
|
|||
|
<p>The following is a list of incompatibilities in behavior between
|
|||
|
Numeric 1 and Numeric 2.</p>
|
|||
|
<ol class="arabic">
|
|||
|
<li>Scalar coercion rules<p>Numeric 1 has single set of coercion rules for array and Python
|
|||
|
numeric types. This can cause unexpected and annoying problems
|
|||
|
during the calculation of an array expression. Numeric 2 intends
|
|||
|
to overcome these problems by having two sets of coercion rules:
|
|||
|
one for arrays and Python numeric types, and another just for
|
|||
|
arrays.</p>
|
|||
|
</li>
|
|||
|
<li>No savespace attribute<p>The savespace attribute in Numeric 1 makes arrays with this
|
|||
|
attribute set take precedence over those that do not have it set.
|
|||
|
Numeric 2 will not have such an attribute and therefore normal
|
|||
|
array coercion rules will be in effect.</p>
|
|||
|
</li>
|
|||
|
<li>Slicing syntax returns a copy<p>The slicing syntax in Numeric 1 returns a view into the original
|
|||
|
array. The slicing behavior for Numeric 2 will be a copy. You
|
|||
|
should use the ArrayView class to get a view into an array.</p>
|
|||
|
</li>
|
|||
|
<li>Boolean comparisons return a boolean array<p>A comparison between arrays in Numeric 1 results in a Boolean
|
|||
|
scalar, because of current limitations in Python. The advent of
|
|||
|
Rich Comparisons in Python 2.1 will allow an array of Booleans to
|
|||
|
be returned.</p>
|
|||
|
</li>
|
|||
|
<li>Type characters are deprecated<p>Numeric 2 will have an ArrayType class composed of Type instances,
|
|||
|
for example Int8, Int16, Int32, and Int for signed integers. The
|
|||
|
typecode scheme in Numeric 1 will be available for backward
|
|||
|
compatibility, but will be deprecated.</p>
|
|||
|
</li>
|
|||
|
</ol>
|
|||
|
</section>
|
|||
|
<section id="appendices">
|
|||
|
<h2><a class="toc-backref" href="#appendices" role="doc-backlink">Appendices</a></h2>
|
|||
|
<ol class="upperalpha">
|
|||
|
<li>Implicit sub-arrays iteration<p>A computer animation is composed of a number of 2-D images or
|
|||
|
frames of identical shape. By stacking these images into a single
|
|||
|
block of memory, a 3-D array is created. Yet the operations to be
|
|||
|
performed are not meant for the entire 3-D array, but on the set
|
|||
|
of 2-D sub-arrays. In most array languages, each frame has to be
|
|||
|
extracted, operated on, and then reinserted into the output array
|
|||
|
using a for-like loop. The J language allows the programmer to
|
|||
|
perform such operations implicitly by having a rank for the frame
|
|||
|
and array. By default these ranks will be the same during the
|
|||
|
creation of the array. It was the intention of the Numeric 1
|
|||
|
developers to implement this feature, since it is based on the
|
|||
|
language J. The Numeric 1 code has the required variables for
|
|||
|
implementing this behavior, but was never implemented. We intend
|
|||
|
to implement implicit sub-array iteration in Numeric 2, if the
|
|||
|
array broadcasting rules found in Numeric 1 do not fully support
|
|||
|
this behavior.</p>
|
|||
|
</li>
|
|||
|
</ol>
|
|||
|
</section>
|
|||
|
<section id="copyright">
|
|||
|
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
|
|||
|
<p>This document is placed in the public domain.</p>
|
|||
|
</section>
|
|||
|
<section id="related-peps">
|
|||
|
<h2><a class="toc-backref" href="#related-peps" role="doc-backlink">Related PEPs</a></h2>
|
|||
|
<ul class="simple">
|
|||
|
<li><a class="pep reference internal" href="../pep-0207/" title="PEP 207 – Rich Comparisons">PEP 207</a>: Rich Comparisons
|
|||
|
by Guido van Rossum and David Ascher</li>
|
|||
|
<li><a class="pep reference internal" href="../pep-0208/" title="PEP 208 – Reworking the Coercion Model">PEP 208</a>: Reworking the Coercion Model
|
|||
|
by Neil Schemenauer and Marc-Andre’ Lemburg</li>
|
|||
|
<li><a class="pep reference internal" href="../pep-0211/" title="PEP 211 – Adding A New Outer Product Operator">PEP 211</a>: Adding New Linear Algebra Operators to Python
|
|||
|
by Greg Wilson</li>
|
|||
|
<li><a class="pep reference internal" href="../pep-0225/" title="PEP 225 – Elementwise/Objectwise Operators">PEP 225</a>: Elementwise/Objectwise Operators
|
|||
|
by Huaiyu Zhu</li>
|
|||
|
<li><a class="pep reference internal" href="../pep-0228/" title="PEP 228 – Reworking Python’s Numeric Model">PEP 228</a>: Reworking Python’s Numeric Model
|
|||
|
by Moshe Zadka</li>
|
|||
|
</ul>
|
|||
|
</section>
|
|||
|
<section id="references">
|
|||
|
<h2><a class="toc-backref" href="#references" role="doc-backlink">References</a></h2>
|
|||
|
<aside class="footnote-list brackets">
|
|||
|
<aside class="footnote brackets" id="id2" role="doc-footnote">
|
|||
|
<dt class="label" id="id2">[<a href="#id1">1</a>]</dt>
|
|||
|
<dd><ol class="upperalpha simple" start="16">
|
|||
|
<li>Greenfield 2000. private communication.</li>
|
|||
|
</ol>
|
|||
|
</aside>
|
|||
|
</aside>
|
|||
|
</section>
|
|||
|
</section>
|
|||
|
<hr class="docutils" />
|
|||
|
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0209.rst">https://github.com/python/peps/blob/main/peps/pep-0209.rst</a></p>
|
|||
|
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0209.rst">2024-04-14 13:35:25 GMT</a></p>
|
|||
|
|
|||
|
</article>
|
|||
|
<nav id="pep-sidebar">
|
|||
|
<h2>Contents</h2>
|
|||
|
<ul>
|
|||
|
<li><a class="reference internal" href="#abstract">Abstract</a></li>
|
|||
|
<li><a class="reference internal" href="#motivation">Motivation</a></li>
|
|||
|
<li><a class="reference internal" href="#proposal">Proposal</a></li>
|
|||
|
<li><a class="reference internal" href="#design-and-implementation">Design and Implementation</a></li>
|
|||
|
<li><a class="reference internal" href="#open-issues">Open Issues</a></li>
|
|||
|
<li><a class="reference internal" href="#implementation-steps">Implementation Steps</a></li>
|
|||
|
<li><a class="reference internal" href="#incompatibilities">Incompatibilities</a></li>
|
|||
|
<li><a class="reference internal" href="#appendices">Appendices</a></li>
|
|||
|
<li><a class="reference internal" href="#copyright">Copyright</a></li>
|
|||
|
<li><a class="reference internal" href="#related-peps">Related PEPs</a></li>
|
|||
|
<li><a class="reference internal" href="#references">References</a></li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<br>
|
|||
|
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0209.rst">Page Source (GitHub)</a>
|
|||
|
</nav>
|
|||
|
</section>
|
|||
|
<script src="../_static/colour_scheme.js"></script>
|
|||
|
<script src="../_static/wrap_tables.js"></script>
|
|||
|
<script src="../_static/sticky_banner.js"></script>
|
|||
|
</body>
|
|||
|
</html>
|