2
0
mirror of https://github.com/boostorg/python.git synced 2026-01-28 07:22:31 +00:00

Adjust NumPy code to work with new directory / namespace structure.

This commit is contained in:
Stefan Seefeld
2016-10-07 20:15:54 -04:00
parent cbb3851488
commit 3ace4a0015
53 changed files with 1200 additions and 485 deletions

View File

@@ -26,9 +26,11 @@ matrix:
- compiler: gcc
env: CXX=g++ PYTHON=python3 CXXFLAGS=-std=c++11
- compiler: clang
env: CXX=clang++ PYTHON=python3 CXXFLAGS=-std=c++98
# clang generates an 'illegal instruction' error in the NumPy check.
# Perhaps we need to upgrade clang to a newer version ?
env: CXX=clang++ PYTHON=python3 CXXFLAGS=-std=c++98 OPTIONS=--no-numpy
- compiler: clang
env: CXX=clang++ PYTHON=python3 CXXFLAGS=-std=c++11
env: CXX=clang++ PYTHON=python3 CXXFLAGS=-std=c++11 OPTIONS=--no-numpy
- env: PYTHON=python DOC=1
@@ -41,8 +43,10 @@ addons:
- gcc-4.8
- g++-4.8
- clang
- python-dev python-pip
- python-numpy
- python-sphinx
- python3-dev
- python3-numpy
- libboost-all-dev
- xsltproc
- docbook-xsl
@@ -58,7 +62,6 @@ before_install:
# conflicting UCS2 and UCS4 unicode. Modify the PATH to skip the TravisCI python.
# See https://github.com/travis-ci/travis-ci/issues/4948 for details.
- export PATH=$(echo $PATH | tr ':' "\n" | sed '/\/opt\/python/d' | tr "\n" ":" | sed "s|::|:|g")
- sudo pip install future
install:
# Install our own version of Boost (the subset we need) as the system version is
@@ -82,7 +85,7 @@ before_script:
- scons --version
script:
- scons config --python=$PYTHON --boost-include=$HOME/Boost
- scons config --python=$PYTHON --boost-include=$HOME/Boost $OPTIONS
- if [ "$DOC" ]; then scons doc; else scons && scons test; fi
after_success:

View File

@@ -40,7 +40,7 @@ env_vars = {}
if 'CXX' in os.environ: env_vars['CXX'] = os.environ['CXX']
if 'CXXFLAGS' in os.environ: env_vars['CXXFLAGS'] = os.environ['CXXFLAGS'].split()
env = Environment(toolpath=['config/tools'],
tools=['default', 'libs', 'tests', 'doc'],
tools=['default', 'libs', 'tests', 'doc', 'sphinx4scons'],
variables=vars,
TARGET_ARCH=arch,
**env_vars)
@@ -68,7 +68,7 @@ config_log = '{}/config.log'.format(build_dir)
SConsignFile('{}/.sconsign'.format(build_dir))
#env.Decider('MD5-timestamp')
env.Decider('timestamp-newer')
checks = config.get_checks()
checks = config.get_checks(env)
if 'config' in COMMAND_LINE_TARGETS:
conf=env.Configure(custom_tests=checks, log_file=config_log, conf_dir=build_dir)
if False in (getattr(conf, c)() for c in checks):

View File

@@ -13,11 +13,14 @@ import platform
from . import ui
from . import cxx
from . import python
from . import numpy
from . import boost
def add_options(vars):
ui.add_option('-V', '--verbose', dest='verbose', action='store_true', help='verbose mode: print full commands.')
ui.add_option('--no-numpy', dest='numpy', action='store_false', help='do not attempt to build NumPy bindings.')
python.add_options(vars)
numpy.add_options(vars)
boost.add_options(vars)
vars.Add('CXX')
@@ -29,8 +32,10 @@ def add_options(vars):
vars.Add('PYTHON')
vars.Add('PYTHONLIBS')
vars.Add('prefix')
vars.Add('boostbook_prefix',
vars.Add('CXX11'))
vars.Add('boostbook_prefix')
vars.Add('CXX11')
vars.Add('NUMPY')
vars.Add('NUMPY_CPPPATH', converter=lambda v:v.split())
ui.add_variable(vars, ("arch", "target architeture", platform.machine()))
ui.add_variable(vars, ("toolchain", "toolchain to use", 'gcc'))
@@ -42,10 +47,14 @@ def add_options(vars):
ui.add_variable(vars, PathVariable("prefix", "Install prefix", "/usr/local", PathVariable.PathAccept))
def get_checks():
def get_checks(env):
checks = OrderedDict()
checks['cxx'] = cxx.check
checks['python'] = python.check
if env.GetOption('numpy') is not False:
checks['numpy'] = numpy.check
else:
env['NUMPY'] = False
checks['boost'] = boost.check
return checks

86
config/numpy.py Normal file
View File

@@ -0,0 +1,86 @@
#
# Copyright (c) 2016 Stefan Seefeld
# All rights reserved.
#
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
from . import ui
from contextlib import contextmanager
@contextmanager
def saved(context):
save_cpppath = context.env.get('CPPPATH', [])
save_libs = context.env.get('LIBS', [])
yield context
context.env.Replace(LIBS=save_libs)
context.env.Replace(CPPPATH=save_cpppath)
def add_options(vars):
pass
def check(context):
numpy_source_file = r"""
// If defined, enforces linking againg PythonXXd.lib, which
// is usually not included in Python environments.
#undef _DEBUG
#include "Python.h"
#include "numpy/arrayobject.h"
#if PY_VERSION_HEX >= 0x03000000
void *initialize() { import_array();}
#else
void initialize() { import_array();}
#endif
int main()
{
int result = 0;
Py_Initialize();
initialize();
if (PyErr_Occurred())
{
result = 1;
}
else
{
npy_intp dims = 2;
PyObject * a = PyArray_SimpleNew(1, &dims, NPY_INT);
if (!a) result = 1;
Py_DECREF(a);
}
Py_Finalize();
return result;
}
"""
import platform
import subprocess
import re, os
def check_python(cmd):
try:
return True, subprocess.check_output([python, '-c', cmd]).strip()
except subprocess.CalledProcessError as e:
return False, e
context.Message('Checking for NumPy...')
with saved(context):
python = context.env['PYTHON']
result, numpy_incpath = check_python('import numpy; print(numpy.get_include())')
if result:
context.env.AppendUnique(CPPPATH=numpy_incpath)
context.env.AppendUnique(LIBS=context.env['PYTHONLIBS'])
result, output = context.TryRun(numpy_source_file,'.cpp')
if not result:
context.Result(0)
return False
context.env['NUMPY'] = True
context.env['NUMPY_CPPPATH'] = numpy_incpath
context.Result(1)
return True

View File

@@ -58,6 +58,10 @@ def BoostRST(env, target, source, resources=[]):
'rst2html --link-stylesheet --traceback --trim-footnote-reference-space --footnote-references=superscript --stylesheet=rst.css $SOURCE $TARGET')
def BoostSphinx(env, target, source):
env.Sphinx(target, source)
def exists(env):
return True
@@ -68,3 +72,4 @@ def generate(env):
env.AddMethod(BoostBook)
env.AddMethod(BoostHTML)
env.AddMethod(BoostRST)
env.AddMethod(BoostSphinx)

View File

@@ -0,0 +1,592 @@
"""SCons.Tool.spinx4scons
Tool-specific initialization for the Sphinx document build system.
There normally shouldn't be any need to import this module directly.
It will usually be imported through the generic SCons.Tool.Tool()
selection method.
It should be placed in e.g. ~/site_scons/site_tools/sphinx4scons/
directory. Then it may be loaded by placing
sphinx = Tool('sphinx4scons')
sphinx(env)
in your SConstruct file.
For further details, please see the SCons documentation on how to
install and enable custom tools.
"""
#
# This package is provided under the Expat license
#
# Copyright (c) 2012 Orlando Wingbrant
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
__author__ = "Orlando Wingbrant"
__email__ = "orlando@widesite.org"
__url__ = "https://bitbucket.org/wingbrant/sphinx4scons"
__license__ = "Expat license"
import SCons.Action
import SCons.Builder
import SCons.Defaults
import SCons.Util
import SCons.Node.FS
import os
from sphinx.util.matching import patfilter, compile_matchers
from sphinx.util.osutil import make_filename
class ToolSphinxWarning(SCons.Warnings.Warning):
pass
class SphinxBuilderNotFound(ToolSphinxWarning):
pass
SCons.Warnings.enableWarningClass(ToolSphinxWarning)
def exists(env):
return _detect(env)
def _detect(env):
"""Try to detect the sphinx-build script."""
try:
return env['SPHINXBUILD']
except KeyError:
pass
sphinx = env.WhereIs('sphinx-build')
if sphinx:
return sphinx
raise SCons.Errors.StopError(
SphinxBuilderNotFound,
"Could not detect sphinx-build script")
return None
def generate(env):
"""Add Builders and construction variables to the Environment."""
env['SPHINXBUILD'] = _detect(env)
sphinx = _create_sphinx_builder(env)
env.SetDefault(
# Additional command-line flags
SPHINXFLAGS = '',
# Tag definitions, each entry will appear on the command line preceded by -t
SPHINXTAGS = [],
# Directory for doctrees
SPHINXDOCTREE = '',
# Path to sphinx configuration file
SPHINXCONFIG = '',
# Config file override settings, each entry will be preceded by -D
SPHINXSETTINGS = {},
# Default sphinx builder,
SPHINXBUILDER = 'html',
# Sphinx command
SPHINXCOM = "$SPHINXBUILD $_SPHINXOPTIONS ${SOURCE.attributes.root} ${TARGET.attributes.root}",
# Alternate console output when building sphinx documents
SPHINXCOMSTR = ""
)
try:
env.AddMethod(Sphinx, "Sphinx")
except AttributeError:
# Looks like we use a pre-0.98 version of SCons...
from SCons.Script.SConscript import SConsEnvironment
SConsEnvironment.Sphinx = Sphinx
def Sphinx(env, target, source, **kw):
"""A pseudo-builder wrapper for the sphinx builder."""
builder = env['BUILDERS']['Sphinx4Scons']
env_kw = env.Override(kw)
options = _get_sphinxoptions(env_kw, target, source)
output = builder(env, target, source, _SPHINXOPTIONS=options, **kw)
return output
def _get_sphinxoptions(env, target, source):
"""Concatenates all the options for the sphinx command line."""
options = []
builder = _get_sphinxbuilder(env)
options.append("-b %s" % env.subst(builder, target=target, source=source))
flags = env.get('options', env.get('SPHINXFLAGS', ''))
options.append(env.subst(flags, target=target, source=source))
tags = env.get('tags', env.get('SPHINXTAGS', None))
if tags is not None:
if not SCons.SCons.Util.is_List(tags):
tags = [tags]
for tag in tags:
if tag != '':
tag = env.subst(tag, target=target, source=source)
options.append("-t %s" % tag)
settings = env.get('settings', env.get('SPHINXSETTINGS', None))
if settings is not None:
if not SCons.SCons.Util.is_Dict(settings):
raise TypeError('SPHINXSETTINGS and/or settings argument must be a dictionary')
for key, value in settings.iteritems():
if value != '':
value = env.subst(value, target=target, source=source)
options.append('-D "%s=%s"' % (key, value))
doctree = env.get('doctree', env.get("SPHINXDOCTREE", None))
if isinstance(doctree, SCons.Node.FS.Dir):
options.append("-d %s" % doctree.get_abspath())
elif doctree is not None and doctree != '':
doctree = env.subst(doctree, target=target, source=source)
options.append("-d %s" % env.Dir(doctree).get_abspath())
config = _get_sphinxconfig_path(env, None)
if config is not None and config != '':
config = env.subst(config, target=target, source=source)
options.append("-c %s" % env.Dir(config).File('conf.py').rfile().dir.get_abspath())
return " ".join(options)
def _create_sphinx_builder(env):
try:
sphinx = env['BUILDERS']['Sphinx4Scons']
except KeyError:
fs = SCons.Node.FS.get_default_fs()
sphinx_com = SCons.Action.Action('$SPHINXCOM', '$SPHINXCOMSTR')
sphinx = SCons.Builder.Builder(action=sphinx_com,
emitter=sphinx_emitter,
target_factory=fs.Dir,
source_factory=fs.Dir
)
env['BUILDERS']['Sphinx4Scons'] = sphinx
return sphinx
def sphinx_emitter(target, source, env):
target[0].must_be_same(SCons.Node.FS.Dir)
targetnode = target[0]
source[0].must_be_same(SCons.Node.FS.Dir)
srcnode = source[0]
configdir = _get_sphinxconfig_path(env, None)
if not configdir:
confignode = srcnode
else:
confignode = env.Dir(configdir)
srcinfo = SourceInfo(srcnode, confignode, env)
targets, sources = _get_emissions(env, target, srcinfo)
env.Clean(targets, target[0])
return targets, sources
def sphinx_path(os_path):
"""Create sphinx-style path from os-style path."""
return os_path.replace(os.sep, "/")
def os_path(sphinx_path):
"""Create os-style path from sphinx-style path."""
return sphinx_path.replace("/", os.sep)
class SourceInfo(object):
"""
Data container for all different kinds of source files used in
a sphinx project.
"""
def __init__(self, srcnode, confignode, env):
self.confignode = confignode
self.config = self._get_config(self.confignode, env)
self.templates = self._get_templates(self.confignode, self.config)
self.statics = self._get_statics(self.confignode, self.config)
self.srcnode = srcnode
self.sources = self._get_sources(self.srcnode, self.config)
self.srcroot = srcnode
if not srcnode.duplicate:
self.srcroot = srcnode.srcnode().rdir()
def _get_config(self, confignode, env):
config = {}
execfile(confignode.File('conf.py').rfile().get_abspath(), config)
return config
def _get_templates(self, confignode, config):
"""Returns template files defined in the project."""
templates = []
for path in config.get('templates_path', []):
# Check if path is dir or file.
# We can't use FS.Entry since that will create nodes, and
# these nodes don't know about the source tree and will
# get disambiguated to files even if they are directories in the
# source tree.
p = confignode.File('conf.py').rfile().dir.srcnode().get_abspath()
p = os.path.join(p, os_path(path))
if os.path.isfile(p):
templates.append(confignode.File(path))
elif os.path.isdir(p):
node = confignode.Dir(path)
for root, dirs, files in os.walk(p):
mydir = node.Dir(os.path.relpath(root, p))
templates += [mydir.File(f) for f in files]
return templates
def _get_statics(self, confignode, config):
"""Returns static files, filtered through exclude_patterns."""
statics = []
matchers = compile_matchers(config.get('exclude_patterns', []))
for path in config.get('html_static_path', []):
# Check _get_templates() why we use this construction.
p = confignode.File('conf.py').rfile().dir.srcnode().get_abspath()
p = os.path.join(p, os_path(path))
if os.path.isfile(p):
statics.append(confignode.File(path))
elif os.path.isdir(p):
node = confignode.Dir(path)
for root, dirs, files in os.walk(p):
relpath = os.path.relpath(root, p)
for entry in [d for d in dirs if
self._anymatch(matchers,
sphinx_path(os.path.join(relpath, d)))]:
dirs.remove(entry)
statics += [node.File(os_path(f)) for f in
self._exclude(matchers,
[sphinx_path(os.path.join(relpath, name))
for name in files])]
return statics
def _get_sources(self, srcnode, config):
"""Returns all source files in the project filtered through exclude_patterns."""
suffix = config.get('source_suffix', '.rst')
matchers = compile_matchers(config.get('exclude_patterns', []))
srcfiles = []
scannode = srcnode.srcnode().rdir()
for root, dirs, files in os.walk(scannode.get_abspath()):
relpath = os.path.relpath(root, scannode.get_abspath())
for entry in [d for d in dirs if
self._anymatch(matchers,
sphinx_path(os.path.join(relpath, d)))]:
dirs.remove(entry)
srcfiles += [srcnode.File(os_path(f)) for f in
self._exclude(matchers,
[sphinx_path(os.path.join(relpath, name))
for name in files if name.endswith(suffix)])]
return srcfiles
def _exclude(self, matchers, items):
result = items
for matcher in matchers:
result = filter(lambda x: not matcher(x), result)
return result
def _anymatch(self, matchers, item):
for matcher in matchers:
if matcher(item):
return True
return False
def _get_sphinxconfig_path(env, default):
path = env.get('config', env.get('SPHINXCONFIG', None))
if path is None or path == '':
path = default
return path
def _get_emissions(env, target, srcinfo):
targets = []
sources = []
builder = _get_sphinxbuilder(env)
if builder == 'changes':
targets, sources = _get_changes_emissions(env, target, srcinfo)
if builder == 'devhelp':
targets, sources = _get_help_emissions(env, target, srcinfo,
['.devhelp.gz'])
elif builder == 'dirhtml':
targets, sources = _get_dirhtml_emissions(env, target, srcinfo)
elif builder == 'doctest':
targets, sources = _get_doctest_emissions(env, target, srcinfo)
elif builder == 'epub':
targets, sources = _get_epub_emissions(env, target, srcinfo)
elif builder == 'html':
targets, sources = _get_serialize_emissions(env, target, srcinfo)
elif builder == 'htmlhelp':
targets, sources = _get_help_emissions(env, target, srcinfo,
['.hhp'], 'htmlhelp_basename')
elif builder == 'gettext':
targets, sources = _get_gettext_emissions(env, target, srcinfo)
elif builder == 'json':
targets, sources = _get_serialize_emissions(env, target, srcinfo,
'.fjson',
['globalcontext.json',
'searchindex.json',
'self.environment.pickle'])
elif builder == 'latex':
targets, sources = _get_latex_emissions(env, target, srcinfo)
elif builder == 'linkcheck':
targets, sources = _get_linkcheck_emissions(env, target, srcinfo)
elif builder == 'man':
targets, sources = _get_man_emissions(env, target, srcinfo)
elif builder == 'pickle':
targets, sources = _get_serialize_emissions(env, target, srcinfo,
'.fpickle',
['globalcontext.pickle',
'searchindex.pickle',
'environment.pickle'])
elif builder == 'qthelp':
targets, sources = _get_help_emissions(env, target, srcinfo,
['.qhp', '.qhcp'])
elif builder == 'singlehtml':
targets, sources = _get_singlehtml_emissions(env, target, srcinfo)
elif builder == 'texinfo':
targets, sources = _get_texinfo_emissions(env, target, srcinfo)
elif builder == 'text':
targets, sources = _get_text_emissions(env, target, srcinfo)
sources.append(srcinfo.confignode.File('conf.py'))
for s in sources:
s.attributes.root = srcinfo.srcroot
for t in targets:
t.attributes.root = target[0]
return targets, sources
def _get_sphinxbuilder(env):
builder = env.get('builder', env["SPHINXBUILDER"])
if builder is None or builder == '':
raise SCons.Errors.UserError(("Missing construction variable " +
"SPHINXBUILDER or variable is empty."))
return builder
def _get_changes_emissions(env, target, srcinfo):
sources = []
sources.extend(srcinfo.sources)
targets = [target[0].File("changes.html")]
return targets, sources
def _get_dirhtml_emissions(env, target, srcinfo):
suffix = srcinfo.config.get('html_file_suffix', ".html")
def get_outfilename(pagename):
pagename = os.path.splitext(pagename)[0]
#Special treatment of files named "index". Don't create directory.
if pagename == 'index' or pagename.endswith(os.sep + 'index'):
outfilename = pagename + suffix
else:
outfilename = os.path.join(pagename, 'index' + suffix)
return outfilename
sources = []
sources.extend(srcinfo.sources)
sources.extend(srcinfo.templates)
sources.extend(srcinfo.statics)
targets = []
for s in srcinfo.sources:
t = os.path.relpath(str(s), str(srcinfo.srcroot))
targets.append(target[0].File(get_outfilename(t)))
for key in srcinfo.config.get('html_additional_pages', {}):
t = target[0].File(get_outfilename(key))
targets.append(t)
return targets, sources
def _get_doctest_emissions(env, target, srcinfo):
sources = []
sources.extend(srcinfo.sources)
targets = [target[0].File("output.txt")]
return targets, sources
def _get_epub_emissions(env, target, srcinfo):
epubPreFiles = srcinfo.config.get('epub_pre_files', [])
epubPostFiles = srcinfo.config.get('epub_post_files', [])
epubCover = srcinfo.config.get('epub_cover', (None, None))
sources = []
sources.extend(srcinfo.sources)
sources.extend([srcinfo.srcroot.File(os_path(f[0])) for f in epubPreFiles])
sources.extend([srcinfo.srcroot.File(os_path(f[0])) for f in epubPostFiles])
if not (epubCover[0] is None or epubCover[0] == ''):
sources.append(srcinfo.srcroot.File(os_path(epubCover[0])))
if not (epubCover[1] is None or epubCover[1] == ''):
sources.append(srcinfo.srcroot.File(os_path(epubCover[1])))
t = srcinfo.config.get('epub_basename',
srcinfo.config.get('project',
'Python'))
targets = [target[0].File("%s.epub" % make_filename(t))]
return targets, sources
def _get_gettext_emissions(env, target, srcinfo):
sources = []
sources.extend(srcinfo.sources)
targets = [os.path.relpath(str(s), str(srcinfo.srcroot)) for s in sources]
targets = [os.path.splitext(t)[0] for t in targets]
targets = set([t.split(os.sep)[0] for t in targets])
targets = [target[0].File(t + ".pot") for t in targets]
return targets, sources
def _get_help_emissions(env, target, srcinfo, suffixes, basenameConfigKey='project'):
basename = make_filename(
srcinfo.config.get(basenameConfigKey, srcinfo.config['project']))
sources = []
sources.extend(srcinfo.sources)
sources.extend(srcinfo.templates)
sources.extend(srcinfo.statics)
targets = [target[0].File(basename + s) for s in suffixes]
return targets, sources
def _get_latex_emissions(env, target, srcinfo):
sources = []
sources.extend(srcinfo.sources)
targets = map(lambda x: target[0].File(os_path(x[1])),
srcinfo.config.get('latex_documents'))
return targets, sources
def _get_linkcheck_emissions(env, target, srcinfo):
sources = []
sources.extend(srcinfo.sources)
targets = [target[0].File("output.txt")]
return targets, sources
def _get_man_emissions(env, target, srcinfo):
sources = []
sources.extend(srcinfo.sources)
targets = map(lambda x: target[0].File(os_path("%s.%s" % (x[1], x[4]))),
srcinfo.config.get('man_pages'))
return targets, sources
def _get_serialize_emissions(env, target, srcinfo, suffix=None, extrafiles=[]):
if suffix is None:
suffix = srcinfo.config.get('html_file_suffix', '.html')
sources = []
sources.extend(srcinfo.sources)
sources.extend(srcinfo.templates)
sources.extend(srcinfo.statics)
targets = []
for s in srcinfo.sources:
t = os.path.splitext(str(s))[0] + suffix
t = os.path.relpath(t, str(srcinfo.srcroot))
targets.append(t)
for key in srcinfo.config.get('html_additional_pages', {}):
targets.append(os_path("%s%s" % (key, suffix)))
targets.extend(extrafiles)
targets = [target[0].File(t) for t in targets]
return targets, sources
def _get_singlehtml_emissions(env, target, srcinfo):
suffix = srcinfo.config.get('html_file_suffix', ".html")
sources = []
sources.extend(srcinfo.sources)
sources.extend(srcinfo.templates)
sources.extend(srcinfo.statics)
t = os.path.relpath(srcinfo.config['master_doc'] + suffix,
str(srcinfo.srcroot))
targets = [target[0].File(t)]
return targets, sources
def _get_texinfo_emissions(env, target, srcinfo):
suffix = srcinfo.config.get('source_suffix', '.rst')
sources = []
sources.extend(srcinfo.sources)
sources.extend(map(lambda x: source[0].File(os_path(x + suffix)),
srcinfo.config.get('texinfo_appendices', [])))
targets = map(lambda x: target[0].File(os_path("%s.texi" % x[1])),
srcinfo.config.get('texinfo_documents'))
return targets, sources
def _get_text_emissions(env, target, srcinfo):
sources = []
sources.extend(srcinfo.sources)
targets = []
for s in sources:
t = os.path.relpath(str(s), str(srcinfo.srcroot))
t = os.path.splitext(t)[0] + ".txt"
targets.append(target[0].File(t))
return targets, sources

View File

@@ -47,3 +47,6 @@ env.BoostHTML('html/reference/', 'reference.dbk',
'--stringparam', 'boost.graphics.root', '../images/'])
env.BoostRST('html/article.html', 'article.rst', resources=['rst.css'])
if env['NUMPY']:
env.BoostSphinx('html/numpy', 'numpy/')

BIN
doc/numpy/_static/bpl.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View File

@@ -86,12 +86,12 @@
"header">
<tr>
<td valign="top" width="300">
<h3><a href="{{ pathto('index') }}"><img height="86" width="277"
<h3><a href="{{ pathto('index') }}"><img
alt="C++ Boost" src="{{ pathto('_static/' + logo, 1) }}" border="0"></a></h3>
</td>
<td valign="top">
<h1 align="center"><a href="{{ pathto('index') }}">Boost.NumPy</a></h1>
<!-- <h1 align="center"><a href="{{ pathto('index') }}">Boost.NumPy</a></h1>-->
<!-- <h2 align="center">CallPolicies Concept</h2>-->
</td>
<td>

View File

@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
#
# Boost.NumPy documentation build configuration file, created by
# Boost.Python NumPy documentation build configuration file, created by
# sphinx-quickstart on Thu Oct 27 09:04:58 2011.
#
# This file is execfile()d with the current directory set to its containing dir.
@@ -40,7 +40,7 @@ source_suffix = '.rst'
master_doc = 'index'
# General information about the project.
project = u'Boost.NumPy'
project = u'Boost.Python NumPy extension'
copyright = u'2011, Stefan Seefeld'
# The version info for the project you're documenting, acts as replacement for
@@ -112,7 +112,7 @@ html_theme = 'default'
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
html_logo = '_static/boost.png'
html_logo = 'static/bpl.png'
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
@@ -122,7 +122,7 @@ html_logo = '_static/boost.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']
html_static_path = ['static']
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
@@ -166,7 +166,7 @@ html_use_index = True
#html_file_suffix = None
# Output file base name for HTML help builder.
htmlhelp_basename = 'BoostNumPydoc'
htmlhelp_basename = 'BoostPythonNumPydoc'
html_add_permalinks = False
@@ -181,7 +181,7 @@ html_add_permalinks = False
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents = [
('index', 'BoostNumPy.tex', u'Boost.NumPy Documentation',
('index', 'BoostPythonNumPy.tex', u'Boost.Python NumPy Documentation',
u'Stefan Seefeld', 'manual'),
]
@@ -214,6 +214,6 @@ latex_documents = [
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
('index', 'boostnumpy', u'Boost.NumPy Documentation',
('index', 'boostnumpy', u'Boost.Python NumPy Documentation',
[u'Stefan Seefeld'], 1)
]

View File

@@ -1,10 +1,10 @@
.. Boost.NumPy documentation master file, created by
.. Boost.Python NumPy extension documentation master file, created by
sphinx-quickstart on Thu Oct 27 09:04:58 2011.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Welcome to Boost.NumPy's documentation!
=======================================
Welcome to the documentation of the Boost.Python NumPy extension!
=================================================================
Contents:
@@ -13,5 +13,4 @@ Contents:
Tutorial <tutorial/index>
Reference <reference/index>
cmakeBuild.rst

View File

@@ -5,7 +5,7 @@ binary_ufunc
A ``binary_ufunc`` is a struct used as an intermediate step to broadcast two arguments so that a C++ function can be converted to a ufunc like function
``<boost/numpy/ufunc.hpp>`` contains the ``binary_ufunc`` structure definitions
``<boost/python/numpy/ufunc.hpp>`` contains the ``binary_ufunc`` structure definitions
synopsis
@@ -15,6 +15,8 @@ synopsis
namespace boost
{
namespace python
{
namespace numpy
{
@@ -26,16 +28,17 @@ synopsis
struct binary_ufunc
{
static python::object call(TBinaryFunctor & self,
python::object const & input1,
python::object const & input2,
python::object const & output);
static object call(TBinaryFunctor & self,
object const & input1,
object const & input2,
object const & output);
static python::object make();
static object make();
};
}
}
}
constructors
@@ -63,9 +66,9 @@ accessors
typename TArgument1=typename TBinaryFunctor::first_argument_type,
typename TArgument2=typename TBinaryFunctor::second_argument_type,
typename TResult=typename TBinaryFunctor::result_type>
static python::object call(TBinaryFunctor & self,
python::object const & input,
python::object const & output);
static object call(TBinaryFunctor & self,
object const & input,
object const & output);
:Requires: Typenames ``TBinaryFunctor`` and optionally ``TArgument1`` and ``TArgument2`` for argument type and ``TResult`` for result type
@@ -77,7 +80,7 @@ accessors
typename TArgument1=typename TBinaryFunctor::first_argument_type,
typename TArgument2=typename TBinaryFunctor::second_argument_type,
typename TResult=typename TBinaryFunctor::result_type>
static python::object make();
static object make();
:Requires: Typenames ``TBinaryFunctor`` and optionally ``TArgument1`` and ``TArgument2`` for argument type and ``TResult`` for result type
@@ -87,6 +90,8 @@ Example(s)
----------
::
namespace p = boost::python;
namespace np = boost::python::numpy;
struct BinarySquare
{

View File

@@ -7,7 +7,7 @@ A `dtype`_ is an object describing the type of the elements of an ndarray
.. _dtype: http://docs.scipy.org/doc/numpy/reference/arrays.dtypes.html#data-type-objects-dtype
``<boost/numpy/dtype.hpp>`` contains the method calls necessary to generate a python object equivalent to a numpy.dtype from builtin C++ objects, as well as to create custom dtypes from user defined types
``<boost/python/numpy/dtype.hpp>`` contains the method calls necessary to generate a python object equivalent to a numpy.dtype from builtin C++ objects, as well as to create custom dtypes from user defined types
synopsis
@@ -17,12 +17,14 @@ synopsis
namespace boost
{
namespace python
{
namespace numpy
{
class dtype : public python::object
class dtype : public object
{
static python::detail::new_reference convert(python::object::object_cref arg, bool align);
static python::detail::new_reference convert(object::object_cref arg, bool align);
public:
// Convert an arbitrary Python object to a data-type descriptor object.
@@ -37,6 +39,8 @@ synopsis
};
}
}
}
constructors
------------
@@ -78,8 +82,9 @@ Example(s)
----------
::
namespace p = boost::python;
namespace np = boost::python::numpy;
namespace np = boost::numpy;
np::dtype dtype = np::dtype::get_builtin<double>();
p::tuple for_custom_dtype = p::make_tuple("ha",dtype);
np::dtype custom_dtype = np::dtype(list_for_dtype);

View File

@@ -1,5 +1,5 @@
Boost.NumPy Reference
=====================
Boost.Python NumPy extension Reference
======================================
Contents:

View File

@@ -5,7 +5,7 @@ multi_iter
A ``multi_iter`` is a Python object, intended to be used as an iterator It should generally only be used in loops.
``<boost/numpy/ufunc.hpp>`` contains the class definitions for ``multi_iter``
``<boost/python/numpy/ufunc.hpp>`` contains the class definitions for ``multi_iter``
synopsis
@@ -15,10 +15,12 @@ synopsis
namespace boost
{
namespace python
{
namespace numpy
{
class multi_iter : public python::object
class multi_iter : public object
{
public:
void next();
@@ -30,12 +32,13 @@ synopsis
};
multi_iter make_multi_iter(python::object const & a1);
multi_iter make_multi_iter(python::object const & a1, python::object const & a2);
multi_iter make_multi_iter(python::object const & a1, python::object const & a2, python::object const & a3);
multi_iter make_multi_iter(object const & a1);
multi_iter make_multi_iter(object const & a1, object const & a2);
multi_iter make_multi_iter(object const & a1, object const & a2, object const & a3);
}
}
}
constructors
@@ -43,9 +46,9 @@ constructors
::
multi_iter make_multi_iter(python::object const & a1);
multi_iter make_multi_iter(python::object const & a1, python::object const & a2);
multi_iter make_multi_iter(python::object const & a1, python::object const & a2, python::object const & a3);
multi_iter make_multi_iter(object const & a1);
multi_iter make_multi_iter(object const & a1, object const & a2);
multi_iter make_multi_iter(object const & a1, object const & a2, object const & a3);
:Returns: A Python iterator object broadcasting over one, two or three sequences as supplied

View File

@@ -8,7 +8,7 @@ A `ndarray`_ is an N-dimensional array which contains items of the same type and
.. _ndarray: http://docs.scipy.org/doc/numpy/reference/arrays.ndarray.html
.. _dtype: http://docs.scipy.org/doc/numpy/reference/arrays.dtypes.html#data-type-objects-dtype
``<boost/numpy/ndarray.hpp>`` contains the structures and methods necessary to move raw data between C++ and Python and create ndarrays from the data
``<boost/python/numpy/ndarray.hpp>`` contains the structures and methods necessary to move raw data between C++ and Python and create ndarrays from the data
@@ -19,10 +19,12 @@ synopsis
namespace boost
{
namespace python
{
namespace numpy
{
class ndarray : public python::object
class ndarray : public object
{
public:
@@ -53,30 +55,30 @@ synopsis
ndarray transpose() const;
ndarray squeeze() const;
ndarray reshape(python::tuple const & shape) const;
python::object scalarize() const;
ndarray reshape(tuple const & shape) const;
object scalarize() const;
};
ndarray zeros(python::tuple const & shape, dtype const & dt);
ndarray zeros(tuple const & shape, dtype const & dt);
ndarray zeros(int nd, Py_intptr_t const * shape, dtype const & dt);
ndarray empty(python::tuple const & shape, dtype const & dt);
ndarray empty(tuple const & shape, dtype const & dt);
ndarray empty(int nd, Py_intptr_t const * shape, dtype const & dt);
ndarray array(python::object const & obj);
ndarray array(python::object const & obj, dtype const & dt);
ndarray array(object const & obj);
ndarray array(object const & obj, dtype const & dt);
template <typename Container>
ndarray from_data(void * data,dtype const & dt,Container shape,Container strides,python::object const & owner);
template <typename Container>
ndarray from_data(void const * data, dtype const & dt, Container shape, Container strides, python::object const & owner);
ndarray from_data(void const * data, dtype const & dt, Container shape, Container strides, object const & owner);
ndarray from_object(python::object const & obj, dtype const & dt,int nd_min, int nd_max, ndarray::bitflag flags=ndarray::NONE);
ndarray from_object(python::object const & obj, dtype const & dt,int nd, ndarray::bitflag flags=ndarray::NONE);
ndarray from_object(python::object const & obj, dtype const & dt, ndarray::bitflag flags=ndarray::NONE);
ndarray from_object(python::object const & obj, int nd_min, int nd_max,ndarray::bitflag flags=ndarray::NONE);
ndarray from_object(python::object const & obj, int nd, ndarray::bitflag flags=ndarray::NONE);
ndarray from_object(python::object const & obj, ndarray::bitflag flags=ndarray::NONE)
ndarray from_object(object const & obj, dtype const & dt,int nd_min, int nd_max, ndarray::bitflag flags=ndarray::NONE);
ndarray from_object(object const & obj, dtype const & dt,int nd, ndarray::bitflag flags=ndarray::NONE);
ndarray from_object(object const & obj, dtype const & dt, ndarray::bitflag flags=ndarray::NONE);
ndarray from_object(object const & obj, int nd_min, int nd_max,ndarray::bitflag flags=ndarray::NONE);
ndarray from_object(object const & obj, int nd, ndarray::bitflag flags=ndarray::NONE);
ndarray from_object(object const & obj, ndarray::bitflag flags=ndarray::NONE)
ndarray::bitflag operator|(ndarray::bitflag a, ndarray::bitflag b) ;
ndarray::bitflag operator&(ndarray::bitflag a, ndarray::bitflag b);
@@ -119,7 +121,7 @@ constructors
::
ndarray reshape(python::tuple const & shape) const;
ndarray reshape(tuple const & shape) const;
:Requirements: The new ``shape`` of the ndarray must be supplied as a tuple
@@ -128,13 +130,13 @@ constructors
::
python::object scalarize() const;
object scalarize() const;
:Returns: A scalar if the ndarray has only one element, otherwise it returns the entire array
::
ndarray zeros(python::tuple const & shape, dtype const & dt);
ndarray zeros(tuple const & shape, dtype const & dt);
ndarray zeros(int nd, Py_intptr_t const * shape, dtype const & dt);
:Requirements: The following parameters must be supplied as required :
@@ -148,7 +150,7 @@ constructors
::
ndarray empty(python::tuple const & shape, dtype const & dt);
ndarray empty(tuple const & shape, dtype const & dt);
ndarray empty(int nd, Py_intptr_t const * shape, dtype const & dt);
@@ -162,8 +164,8 @@ constructors
::
ndarray array(python::object const & obj);
ndarray array(python::object const & obj, dtype const & dt);
ndarray array(object const & obj);
ndarray array(object const & obj, dtype const & dt);
:Returns: A new ndarray from an arbitrary Python sequence, with dtype of each element specified optionally
@@ -186,7 +188,7 @@ constructors
::
ndarray from_object(python::object const & obj, dtype const & dt,int nd_min, int nd_max, ndarray::bitflag flags=ndarray::NONE);
ndarray from_object(object const & obj, dtype const & dt,int nd_min, int nd_max, ndarray::bitflag flags=ndarray::NONE);
:Requirements: The following parameters must be supplied :
@@ -200,7 +202,7 @@ constructors
::
inline ndarray from_object(python::object const & obj, dtype const & dt, int nd, ndarray::bitflag flags=ndarray::NONE);
inline ndarray from_object(object const & obj, dtype const & dt, int nd, ndarray::bitflag flags=ndarray::NONE);
:Requirements: The following parameters must be supplied :
@@ -213,7 +215,7 @@ constructors
::
inline ndarray from_object(python::object const & obj, dtype const & dt, ndarray::bitflag flags=ndarray::NONE)
inline ndarray from_object(object const & obj, dtype const & dt, ndarray::bitflag flags=ndarray::NONE)
:Requirements: The following parameters must be supplied :
@@ -225,7 +227,7 @@ constructors
::
ndarray from_object(python::object const & obj, int nd_min, int nd_max, ndarray::bitflag flags=ndarray::NONE);
ndarray from_object(object const & obj, int nd_min, int nd_max, ndarray::bitflag flags=ndarray::NONE);
:Requirements: The following parameters must be supplied :
@@ -240,7 +242,7 @@ constructors
::
inline ndarray from_object(python::object const & obj, int nd, ndarray::bitflag flags=ndarray::NONE);
inline ndarray from_object(object const & obj, int nd, ndarray::bitflag flags=ndarray::NONE);
:Requirements: The following parameters must be supplied :
@@ -253,7 +255,7 @@ constructors
::
inline ndarray from_object(python::object const & obj, ndarray::bitflag flags=ndarray::NONE)
inline ndarray from_object(object const & obj, ndarray::bitflag flags=ndarray::NONE)
:Requirements: The following parameters must be supplied :
@@ -295,7 +297,7 @@ accessors
::
python::object get_base() const;
object get_base() const;
:Returns: Object that owns the array's data, or None if the array owns its own data.
@@ -351,6 +353,8 @@ Example(s)
----------
::
namespace p = boost::python;
namespace np = boost::python::numpy;
p::object tu = p::make_tuple('a','b','c') ;
np::ndarray example_tuple = np::array (tu) ;

View File

@@ -5,7 +5,7 @@ unary_ufunc
A ``unary_ufunc`` is a struct used as an intermediate step to broadcast a single argument so that a C++ function can be converted to a ufunc like function
``<boost/numpy/ufunc.hpp>`` contains the ``unary_ufunc`` structure definitions
``<boost/python/numpy/ufunc.hpp>`` contains the ``unary_ufunc`` structure definitions
synopsis
@@ -15,6 +15,8 @@ synopsis
namespace boost
{
namespace python
{
namespace numpy
{
@@ -24,15 +26,16 @@ synopsis
struct unary_ufunc
{
static python::object call(TUnaryFunctor & self,
python::object const & input,
python::object const & output) ;
static object call(TUnaryFunctor & self,
object const & input,
object const & output) ;
static python::object make();
static object make();
};
}
}
}
constructors
@@ -58,9 +61,9 @@ accessors
template <typename TUnaryFunctor,
typename TArgument=typename TUnaryFunctor::argument_type,
typename TResult=typename TUnaryFunctor::result_type>
static python::object call(TUnaryFunctor & self,
python::object const & input,
python::object const & output);
static object call(TUnaryFunctor & self,
object const & input,
object const & output);
:Requires: Typenames ``TUnaryFunctor`` and optionally ``TArgument`` for argument type and ``TResult`` for result type
@@ -71,7 +74,7 @@ accessors
template <typename TUnaryFunctor,
typename TArgument=typename TUnaryFunctor::argument_type,
typename TResult=typename TUnaryFunctor::result_type>
static python::object make();
static object make();
:Requires: Typenames ``TUnaryFunctor`` and optionally ``TArgument`` for argument type and ``TResult`` for result type
@@ -83,6 +86,8 @@ Example(s)
----------
::
namespace p = boost::python;
namespace np = boost::python::numpy;
struct UnarySquare
{

View File

@@ -5,11 +5,11 @@ Here is a brief tutorial to show how to create ndarrays with built-in python dat
Like before, first get the necessary headers, setup the namespaces and initialize the Python runtime and numpy module::
#include <boost/numpy.hpp>
#include <boost/python/numpy.hpp>
#include <iostream>
namespace p = boost::python;
namespace np = boost::numpy;
namespace np = boost::python::numpy;
int main(int argc, char **argv)
{

View File

@@ -6,11 +6,11 @@ The from_data method makes this possible.
Like before, first get the necessary headers, setup the namespaces and initialize the Python runtime and numpy module::
#include <boost/numpy.hpp>
#include <boost/python/numpy.hpp>
#include <iostream>
namespace p = boost::python;
namespace np = boost::numpy;
namespace np = boost::python::numpy;
int main(int argc, char **argv)
{

View File

@@ -1,5 +1,5 @@
Boost.NumPy Tutorial
====================
Boost.Python NumPy extension Tutorial
=====================================
Contents:

View File

@@ -8,11 +8,11 @@ This tutorial will introduce you to some of the ways in which you can create nda
First, as before, initialise the necessary namepaces and runtimes ::
#include <boost/numpy.hpp>
#include <boost/python/numpy.hpp>
#include <iostream>
namespace p = boost::python;
namespace np = boost::numpy;
namespace np = boost::python::numpy;
int main(int argc, char **argv)
{

View File

@@ -5,11 +5,11 @@ Let's start with a simple tutorial to create and modify arrays.
Get the necessary headers for numpy components and set up necessary namespaces::
#include <boost/numpy.hpp>
#include <boost/python/numpy.hpp>
#include <iostream>
namespace p = boost::python;
namespace np = boost::numpy;
namespace np = boost::python::numpy;
Initialise the Python runtime, and the numpy module. Failure to call these results in segmentation errors::

View File

@@ -7,11 +7,11 @@ Lets try and see how we can use the binary and unary ufunc methods
After the neccessary includes ::
#include <boost/numpy.hpp>
#include <boost/python/numpy.hpp>
#include <iostream>
namespace p = boost::python;
namespace np = boost::numpy;
namespace np = boost::python::numpy;
Now we create the structs necessary to implement the ufuncs. The typedefs *must* be made as the ufunc generators take these typedefs as inputs and return an error otherwise ::

View File

@@ -50,6 +50,7 @@ The development of these features was funded in part by grants to `Boost Consult
* [link glossary Glossary]
* [link support Support Resources]
* [link faq Frequently Asked Questions (FAQs)]
* [@numpy/index.html NumPy]
[endsect]

View File

@@ -1,24 +1,20 @@
// Copyright Jim Bosch 2010-2012.
// Copyright Stefan Seefeld 2016.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_NUMPY_HPP_INCLUDED
#define BOOST_NUMPY_HPP_INCLUDED
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
/**
* @file boost/numpy.hpp
* @brief Main public header file for boost.numpy.
*/
#ifndef boost_python_numpy_hpp_
#define boost_python_numpy_hpp_
#include <boost/numpy/dtype.hpp>
#include <boost/numpy/ndarray.hpp>
#include <boost/numpy/scalars.hpp>
#include <boost/numpy/matrix.hpp>
#include <boost/numpy/ufunc.hpp>
#include <boost/numpy/invoke_matching.hpp>
#include <boost/python/numpy/dtype.hpp>
#include <boost/python/numpy/ndarray.hpp>
#include <boost/python/numpy/scalars.hpp>
#include <boost/python/numpy/matrix.hpp>
#include <boost/python/numpy/ufunc.hpp>
#include <boost/python/numpy/invoke_matching.hpp>
namespace boost {
namespace numpy {
namespace boost { namespace python { namespace numpy {
/**
* @brief Initialize the Numpy C-API
@@ -32,7 +28,6 @@ namespace numpy {
*/
void initialize(bool register_scalar_converters=true);
} // namespace boost::numpy
} // namespace boost
}}} // namespace boost::python::numpy
#endif // !BOOST_NUMPY_HPP_INCLUDED
#endif

View File

@@ -1,35 +1,37 @@
// Copyright Jim Bosch 2010-2012.
// Copyright Stefan Seefeld 2016.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_NUMPY_DTYPE_HPP_INCLUDED
#define BOOST_NUMPY_DTYPE_HPP_INCLUDED
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef boost_python_numpy_dtype_hpp_
#define boost_python_numpy_dtype_hpp_
/**
* @file boost/numpy/dtype.hpp
* @file boost/python/numpy/dtype.hpp
* @brief Object manager for Python's numpy.dtype class.
*/
#include <boost/python.hpp>
#include <boost/numpy/numpy_object_mgr_traits.hpp>
#include <boost/python/numpy/numpy_object_mgr_traits.hpp>
#include <boost/mpl/for_each.hpp>
#include <boost/type_traits/add_pointer.hpp>
namespace boost { namespace numpy {
namespace boost { namespace python { namespace numpy {
/**
* @brief A boost.python "object manager" (subclass of object) for numpy.dtype.
*
* @todo This could have a lot more interesting accessors.
*/
class dtype : public python::object {
static python::detail::new_reference convert(python::object::object_cref arg, bool align);
class dtype : public object {
static python::detail::new_reference convert(object::object_cref arg, bool align);
public:
/// @brief Convert an arbitrary Python object to a data-type descriptor object.
template <typename T>
explicit dtype(T arg, bool align=false) : python::object(convert(arg, align)) {}
explicit dtype(T arg, bool align=false) : object(convert(arg, align)) {}
/**
* @brief Get the built-in numpy dtype associated with the given scalar template type.
@@ -63,7 +65,7 @@ public:
*/
static void register_scalar_converters();
BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS(dtype, python::object);
BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS(dtype, object);
};
@@ -106,10 +108,10 @@ struct builtin_dtype< std::complex<T>, false > {
template <typename T>
inline dtype dtype::get_builtin() { return detail::builtin_dtype<T>::get(); }
}} // namespace boost::numpy
} // namespace boost::python::numpy
namespace boost { namespace python { namespace converter {
namespace converter {
NUMPY_OBJECT_MANAGER_TRAITS(numpy::dtype);
}}} // namespace boost::python::converter
#endif // !BOOST_NUMPY_DTYPE_HPP_INCLUDED
#endif

View File

@@ -1,23 +1,25 @@
// Copyright Jim Bosch 2010-2012.
// Copyright Stefan Seefeld 2016.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_NUMPY_INTERNAL_HPP_INCLUDED
#define BOOST_NUMPY_INTERNAL_HPP_INCLUDED
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef boost_python_numpy_internal_hpp_
#define boost_python_numpy_internal_hpp_
/**
* @file boost/numpy/internal.hpp
* @file boost/python/numpy/internal.hpp
* @brief Internal header file to include the Numpy C-API headers.
*
* This should only be included by source files in the boost.numpy library itself.
*/
#include <boost/python.hpp>
#ifdef BOOST_NUMPY_INTERNAL
#ifdef BOOST_PYTHON_NUMPY_INTERNAL
#define NO_IMPORT_ARRAY
#define NO_IMPORT_UFUNC
#else
#ifndef BOOST_NUMPY_INTERNAL_MAIN
#ifndef BOOST_PYTHON_NUMPY_INTERNAL_MAIN
ERROR_internal_hpp_is_for_internal_use_only
#endif
#endif
@@ -25,9 +27,9 @@ ERROR_internal_hpp_is_for_internal_use_only
#define PY_UFUNC_UNIQUE_SYMBOL BOOST_UFUNC_ARRAY_API
#include <numpy/arrayobject.h>
#include <numpy/ufuncobject.h>
#include <boost/numpy.hpp>
#include <boost/python/numpy.hpp>
#define NUMPY_OBJECT_MANAGER_TRAITS_IMPL(pytype,manager) \
PyTypeObject const * object_manager_traits<manager>::get_pytype() { return &pytype; }
#endif // !BOOST_NUMPY_INTERNAL_HPP_INCLUDED
#endif

View File

@@ -1,24 +1,21 @@
// Copyright Jim Bosch 2010-2012.
// Copyright Stefan Seefeld 2016.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_NUMPY_INVOKE_MATCHING_HPP_INCLUDED
#define BOOST_NUMPY_INVOKE_MATCHING_HPP_INCLUDED
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef boost_python_numpy_invoke_matching_hpp_
#define boost_python_numpy_invoke_matching_hpp_
/**
* @file boost/numpy/invoke_matching.hpp
* @brief Template invocation based on dtype matching.
*/
#include <boost/numpy/dtype.hpp>
#include <boost/numpy/ndarray.hpp>
#include <boost/python/numpy/dtype.hpp>
#include <boost/python/numpy/ndarray.hpp>
#include <boost/mpl/integral_c.hpp>
namespace boost
{
namespace numpy
{
namespace boost { namespace python { namespace numpy {
namespace detail
{
@@ -119,7 +116,7 @@ private:
Function & m_func;
};
} // namespace boost::numpy::detail
} // namespace boost::python::numpy::detail
template <typename Sequence, typename Function>
void invoke_matching_nd(int nd, Function f)
@@ -175,7 +172,7 @@ struct array_template_invoker_wrapper_1< DimSequence, boost::reference_wrapper<F
: array_template_invoker_wrapper_1< DimSequence, Function >(nd, func) {}
};
} // namespace boost::numpy::detail
} // namespace boost::python::numpy::detail
template <typename TypeSequence, typename DimSequence, typename Function>
void invoke_matching_array(ndarray const & array_, Function f)
@@ -184,7 +181,6 @@ void invoke_matching_array(ndarray const & array_, Function f)
invoke_matching_dtype<TypeSequence>(array_.get_dtype(), wrapper);
}
} // namespace boost::numpy
} // namespace boost
}}} // namespace boost::python::numpy
#endif // !BOOST_NUMPY_INVOKE_MATCHING_HPP_INCLUDED
#endif

View File

@@ -1,23 +1,21 @@
// Copyright Jim Bosch 2010-2012.
// Copyright Stefan Seefeld 2016.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_NUMPY_MATRIX_HPP_INCLUDED
#define BOOST_NUMPY_MATRIX_HPP_INCLUDED
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef boost_python_numpy_matrix_hpp_
#define boost_python_numpy_matrix_hpp_
/**
* @file boost/numpy/matrix.hpp
* @brief Object manager for numpy.matrix.
*/
#include <boost/python.hpp>
#include <boost/numpy/numpy_object_mgr_traits.hpp>
#include <boost/numpy/ndarray.hpp>
#include <boost/python/numpy/numpy_object_mgr_traits.hpp>
#include <boost/python/numpy/ndarray.hpp>
namespace boost
{
namespace numpy
{
namespace boost { namespace python { namespace numpy {
/**
* @brief A boost.python "object manager" (subclass of object) for numpy.matrix.
@@ -31,19 +29,19 @@ namespace numpy
*/
class matrix : public ndarray
{
static python::object construct(object_cref obj, dtype const & dt, bool copy);
static python::object construct(object_cref obj, bool copy);
static object construct(object_cref obj, dtype const & dt, bool copy);
static object construct(object_cref obj, bool copy);
public:
BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS(matrix, ndarray);
/// @brief Equivalent to "numpy.matrix(obj,dt,copy)" in Python.
explicit matrix(python::object const & obj, dtype const & dt, bool copy=true)
: ndarray(python::extract<ndarray>(construct(obj, dt, copy))) {}
explicit matrix(object const & obj, dtype const & dt, bool copy=true)
: ndarray(extract<ndarray>(construct(obj, dt, copy))) {}
/// @brief Equivalent to "numpy.matrix(obj,copy=copy)" in Python.
explicit matrix(python::object const & obj, bool copy=true)
: ndarray(python::extract<ndarray>(construct(obj, copy))) {}
explicit matrix(object const & obj, bool copy=true)
: ndarray(extract<ndarray>(construct(obj, copy))) {}
/// \brief Return a view of the matrix with the given dtype.
matrix view(dtype const & dt) const;
@@ -60,26 +58,25 @@ public:
* @brief CallPolicies that causes a function that returns a numpy.ndarray to
* return a numpy.matrix instead.
*/
template <typename Base = python::default_call_policies>
struct as_matrix : Base {
static PyObject * postcall(PyObject *, PyObject * result) {
python::object a = python::object(python::handle<>(result));
numpy::matrix m(a, false);
Py_INCREF(m.ptr());
return m.ptr();
}
template <typename Base = default_call_policies>
struct as_matrix : Base
{
static PyObject * postcall(PyObject *, PyObject * result)
{
object a = object(handle<>(result));
numpy::matrix m(a, false);
Py_INCREF(m.ptr());
return m.ptr();
}
};
} // namespace boost::numpy
namespace python
{
} // namespace boost::python::numpy
namespace converter
{
NUMPY_OBJECT_MANAGER_TRAITS(numpy::matrix);
} // namespace boost::python::converter
} // namespace boost::python
} // namespace boost
}}} // namespace boost::python::converter
#endif // !BOOST_NUMPY_MATRIX_HPP_INCLUDED
#endif

View File

@@ -1,27 +1,24 @@
// Copyright Jim Bosch 2010-2012.
// Copyright Stefan Seefeld 2016.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_NUMPY_NDARRAY_HPP_INCLUDED
#define BOOST_NUMPY_NDARRAY_HPP_INCLUDED
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef boost_python_numpy_ndarray_hpp_
#define boost_python_numpy_ndarray_hpp_
/**
* @file boost/numpy/ndarray.hpp
* @brief Object manager and various utilities for numpy.ndarray.
*/
#include <boost/python.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <boost/numpy/numpy_object_mgr_traits.hpp>
#include <boost/numpy/dtype.hpp>
#include <boost/python/numpy/numpy_object_mgr_traits.hpp>
#include <boost/python/numpy/dtype.hpp>
#include <vector>
namespace boost
{
namespace numpy
{
namespace boost { namespace python { namespace numpy {
/**
* @brief A boost.python "object manager" (subclass of object) for numpy.ndarray.
@@ -29,7 +26,7 @@ namespace numpy
* @todo This could have a lot more functionality (like boost::python::numeric::array).
* Right now all that exists is what was needed to move raw data between C++ and Python.
*/
class ndarray : public python::object
class ndarray : public object
{
/**
@@ -104,7 +101,7 @@ public:
dtype get_dtype() const;
/// @brief Return the object that owns the array's data, or None if the array owns its own data.
python::object get_base() const;
object get_base() const;
/// @brief Set the object that owns the array's data. Use with care.
void set_base(object const & base);
@@ -136,7 +133,7 @@ public:
*
* @internal This is simply a call to PyArray_Return();
*/
python::object scalarize() const;
object scalarize() const;
};
/**
@@ -156,8 +153,8 @@ ndarray empty(int nd, Py_intptr_t const * shape, dtype const & dt);
*
* @todo This does't seem to handle ndarray subtypes the same way that "numpy.array" does in Python.
*/
ndarray array(python::object const & obj);
ndarray array(python::object const & obj, dtype const & dt);
ndarray array(object const & obj);
ndarray array(object const & obj, dtype const & dt);
namespace detail
{
@@ -166,7 +163,7 @@ ndarray from_data_impl(void * data,
dtype const & dt,
std::vector<Py_intptr_t> const & shape,
std::vector<Py_intptr_t> const & strides,
python::object const & owner,
object const & owner,
bool writeable);
template <typename Container>
@@ -174,7 +171,7 @@ ndarray from_data_impl(void * data,
dtype const & dt,
Container shape,
Container strides,
python::object const & owner,
object const & owner,
bool writeable,
typename boost::enable_if< boost::is_integral<typename Container::value_type> >::type * enabled = NULL)
{
@@ -185,12 +182,12 @@ ndarray from_data_impl(void * data,
ndarray from_data_impl(void * data,
dtype const & dt,
python::object const & shape,
python::object const & strides,
python::object const & owner,
object const & shape,
object const & strides,
object const & owner,
bool writeable);
} // namespace boost::numpy::detail
} // namespace boost::python::numpy::detail
/**
* @brief Construct a new ndarray object from a raw pointer.
@@ -250,29 +247,29 @@ inline ndarray from_data(void const * data,
* @param[in] nd_max Maximum number of dimensions.
* @param[in] flags Bitwise OR of flags specifying additional requirements.
*/
ndarray from_object(python::object const & obj, dtype const & dt,
ndarray from_object(object const & obj, dtype const & dt,
int nd_min, int nd_max, ndarray::bitflag flags=ndarray::NONE);
inline ndarray from_object(python::object const & obj, dtype const & dt,
inline ndarray from_object(object const & obj, dtype const & dt,
int nd, ndarray::bitflag flags=ndarray::NONE)
{
return from_object(obj, dt, nd, nd, flags);
}
inline ndarray from_object(python::object const & obj, dtype const & dt, ndarray::bitflag flags=ndarray::NONE)
inline ndarray from_object(object const & obj, dtype const & dt, ndarray::bitflag flags=ndarray::NONE)
{
return from_object(obj, dt, 0, 0, flags);
}
ndarray from_object(python::object const & obj, int nd_min, int nd_max,
ndarray from_object(object const & obj, int nd_min, int nd_max,
ndarray::bitflag flags=ndarray::NONE);
inline ndarray from_object(python::object const & obj, int nd, ndarray::bitflag flags=ndarray::NONE)
inline ndarray from_object(object const & obj, int nd, ndarray::bitflag flags=ndarray::NONE)
{
return from_object(obj, nd, nd, flags);
}
inline ndarray from_object(python::object const & obj, ndarray::bitflag flags=ndarray::NONE)
inline ndarray from_object(object const & obj, ndarray::bitflag flags=ndarray::NONE)
{
return from_object(obj, 0, 0, flags);
}
@@ -287,17 +284,13 @@ inline ndarray::bitflag operator&(ndarray::bitflag a, ndarray::bitflag b)
return ndarray::bitflag(int(a) & int(b));
}
} // namespace boost::numpy
} // namespace boost::python::numpy
namespace python
{
namespace converter
{
NUMPY_OBJECT_MANAGER_TRAITS(numpy::ndarray);
} // namespace boost::python::converter
} // namespace boost::python
} // namespace boost
}}} // namespace boost::python::converter
#endif // !BOOST_NUMPY_NDARRAY_HPP_INCLUDED
#endif

View File

@@ -1,12 +1,13 @@
// Copyright Jim Bosch 2010-2012.
// Copyright Stefan Seefeld 2016.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_NUMPY_NUMPY_OBJECT_MGR_TRAITS_HPP_INCLUDED
#define BOOST_NUMPY_NUMPY_OBJECT_MGR_TRAITS_HPP_INCLUDED
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef boost_python_numpy_numpy_object_mgr_traits_hpp_
#define boost_python_numpy_numpy_object_mgr_traits_hpp_
/**
* @file boost/numpy/numpy_object_mgr_traits.hpp
* @brief Macro that specializes object_manager_traits by requiring a
* source-file implementation of get_pytype().
*/
@@ -31,5 +32,5 @@ struct object_manager_traits<manager> \
static PyTypeObject const * get_pytype(); \
}
#endif // !BOOST_NUMPY_NUMPY_OBJECT_MGR_TRAITS_HPP_INCLUDED
#endif

View File

@@ -1,30 +1,28 @@
// Copyright Jim Bosch 2010-2012.
// Copyright Stefan Seefeld 2016.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_NUMPY_SCALARS_HPP_INCLUDED
#define BOOST_NUMPY_SCALARS_HPP_INCLUDED
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef boost_python_numpy_scalars_hpp_
#define boost_python_numpy_scalars_hpp_
/**
* @file boost/numpy/scalars.hpp
* @brief Object managers for array scalars (currently only numpy.void is implemented).
*/
#include <boost/python.hpp>
#include <boost/numpy/numpy_object_mgr_traits.hpp>
#include <boost/numpy/dtype.hpp>
#include <boost/python/numpy/numpy_object_mgr_traits.hpp>
#include <boost/python/numpy/dtype.hpp>
namespace boost
{
namespace numpy
{
namespace boost { namespace python { namespace numpy {
/**
* @brief A boost.python "object manager" (subclass of object) for numpy.void.
*
* @todo This could have a lot more functionality.
*/
class void_ : public python::object
class void_ : public object
{
static python::detail::new_reference convert(object_cref arg, bool align);
public:
@@ -50,15 +48,11 @@ public:
};
} // namespace boost::numpy
} // namespace boost::python::numpy
namespace python
{
namespace converter
{
NUMPY_OBJECT_MANAGER_TRAITS(numpy::void_);
} // namespace boost::python::converter
} // namespace boost::python
} // namespace boost
}}} // namespace boost::python::converter
#endif // !BOOST_NUMPY_SCALARS_HPP_INCLUDED
#endif

View File

@@ -1,24 +1,22 @@
// Copyright Jim Bosch 2010-2012.
// Copyright Stefan Seefeld 2016.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_NUMPY_UFUNC_HPP_INCLUDED
#define BOOST_NUMPY_UFUNC_HPP_INCLUDED
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef boost_python_numpy_ufunc_hpp_
#define boost_python_numpy_ufunc_hpp_
/**
* @file boost/numpy/ufunc.hpp
* @brief Utilities to create ufunc-like broadcasting functions out of C++ functors.
*/
#include <boost/python.hpp>
#include <boost/numpy/numpy_object_mgr_traits.hpp>
#include <boost/numpy/dtype.hpp>
#include <boost/numpy/ndarray.hpp>
#include <boost/python/numpy/numpy_object_mgr_traits.hpp>
#include <boost/python/numpy/dtype.hpp>
#include <boost/python/numpy/ndarray.hpp>
namespace boost
{
namespace numpy
{
namespace boost { namespace python { namespace numpy {
/**
* @brief A boost.python "object manager" (subclass of object) for PyArray_MultiIter.
@@ -36,11 +34,11 @@ namespace numpy
* It's more dangerous than most object managers, however - maybe it actually belongs in
* a detail namespace?
*/
class multi_iter : public python::object
class multi_iter : public object
{
public:
BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS(multi_iter, python::object);
BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS(multi_iter, object);
/// @brief Increment the iterator.
void next();
@@ -63,13 +61,13 @@ public:
};
/// @brief Construct a multi_iter over a single sequence or scalar object.
multi_iter make_multi_iter(python::object const & a1);
multi_iter make_multi_iter(object const & a1);
/// @brief Construct a multi_iter by broadcasting two objects.
multi_iter make_multi_iter(python::object const & a1, python::object const & a2);
multi_iter make_multi_iter(object const & a1, object const & a2);
/// @brief Construct a multi_iter by broadcasting three objects.
multi_iter make_multi_iter(python::object const & a1, python::object const & a2, python::object const & a3);
multi_iter make_multi_iter(object const & a1, object const & a2, object const & a3);
/**
* @brief Helps wrap a C++ functor taking a single scalar argument as a broadcasting ufunc-like
@@ -102,12 +100,12 @@ struct unary_ufunc
* @brief A C++ function with object arguments that broadcasts its arguments before
* passing them to the underlying C++ functor.
*/
static python::object call(TUnaryFunctor & self, python::object const & input, python::object const & output)
static object call(TUnaryFunctor & self, object const & input, object const & output)
{
dtype in_dtype = dtype::get_builtin<TArgument>();
dtype out_dtype = dtype::get_builtin<TResult>();
ndarray in_array = from_object(input, in_dtype, ndarray::ALIGNED);
ndarray out_array = (output != python::object()) ?
ndarray out_array = (output != object()) ?
from_object(output, out_dtype, ndarray::ALIGNED | ndarray::WRITEABLE)
: zeros(in_array.get_nd(), in_array.get_shape(), out_dtype);
multi_iter iter = make_multi_iter(in_array, out_array);
@@ -127,10 +125,9 @@ struct unary_ufunc
* Users will often want to specify their own keyword names with the same signature, but this
* is a convenient shortcut.
*/
static python::object make()
static object make()
{
namespace p = python;
return p::make_function(call, p::default_call_policies(), (p::arg("input"), p::arg("output")=p::object()));
return make_function(call, default_call_policies(), (arg("input"), arg("output")=object()));
}
};
@@ -163,9 +160,9 @@ template <typename TBinaryFunctor,
struct binary_ufunc
{
static python::object
call(TBinaryFunctor & self, python::object const & input1, python::object const & input2,
python::object const & output)
static object
call(TBinaryFunctor & self, object const & input1, object const & input2,
object const & output)
{
dtype in1_dtype = dtype::get_builtin<TArgument1>();
dtype in2_dtype = dtype::get_builtin<TArgument2>();
@@ -173,7 +170,7 @@ struct binary_ufunc
ndarray in1_array = from_object(input1, in1_dtype, ndarray::ALIGNED);
ndarray in2_array = from_object(input2, in2_dtype, ndarray::ALIGNED);
multi_iter iter = make_multi_iter(in1_array, in2_array);
ndarray out_array = (output != python::object())
ndarray out_array = (output != object())
? from_object(output, out_dtype, ndarray::ALIGNED | ndarray::WRITEABLE)
: zeros(iter.get_nd(), iter.get_shape(), out_dtype);
iter = make_multi_iter(in1_array, in2_array, out_array);
@@ -188,26 +185,21 @@ struct binary_ufunc
return out_array.scalarize();
}
static python::object make()
static object make()
{
namespace p = python;
return p::make_function(call, p::default_call_policies(),
(p::arg("input1"), p::arg("input2"), p::arg("output")=p::object()));
return make_function(call, default_call_policies(),
(arg("input1"), arg("input2"), arg("output")=object()));
}
};
} // namespace boost::numpy
} // namespace boost::python::numpy
namespace python
{
namespace converter
{
NUMPY_OBJECT_MANAGER_TRAITS(numpy::multi_iter);
} // namespace boost::python::converter
} // namespace boost::python
} // namespace boost
}}} // namespace boost::python::converter
#endif // !BOOST_NUMPY_UFUNC_HPP_INCLUDED
#endif

View File

@@ -42,3 +42,13 @@ env.BoostLibrary(
'import.cpp',
'exec.cpp',
'object/function_doc_signature.cpp'])
if env['NUMPY']:
env.BoostLibrary(
'numpy',
['numpy/dtype.cpp',
'numpy/matrix.cpp',
'numpy/ndarray.cpp',
'numpy/numpy.cpp',
'numpy/scalars.cpp',
'numpy/ufunc.cpp'])

View File

@@ -1,12 +1,14 @@
// Copyright Jim Bosch 2010-2012.
// Copyright Stefan Seefeld 2016.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifdef _MSC_VER
#include <boost/cstdint.hpp>
#endif
#define BOOST_NUMPY_INTERNAL
#include <boost/numpy/internal.hpp>
#define BOOST_PYTHON_NUMPY_INTERNAL
#include <boost/python/numpy/internal.hpp>
#define DTYPE_FROM_CODE(code) \
dtype(python::detail::new_reference(reinterpret_cast<PyObject*>(PyArray_DescrFromType(code))))
@@ -35,10 +37,9 @@
namespace boost { namespace python { namespace converter {
NUMPY_OBJECT_MANAGER_TRAITS_IMPL(PyArrayDescr_Type, numpy::dtype)
}}} // namespace boost::python::converter
namespace boost { namespace numpy {
} // namespace boost::python::converter
namespace numpy {
namespace detail {
dtype builtin_dtype<bool,true>::get() { return DTYPE_FROM_CODE(NPY_BOOL); }
@@ -75,14 +76,18 @@ template dtype get_complex_dtype< 2 * NPY_BITSOF_LONGDOUBLE >();
} // namespace detail
python::detail::new_reference dtype::convert(python::object const & arg, bool align) {
python::detail::new_reference dtype::convert(object const & arg, bool align)
{
PyArray_Descr* obj=NULL;
if (align) {
if (align)
{
if (PyArray_DescrAlignConverter(arg.ptr(), &obj) < 0)
python::throw_error_already_set();
} else {
throw_error_already_set();
}
else
{
if (PyArray_DescrConverter(arg.ptr(), &obj) < 0)
python::throw_error_already_set();
throw_error_already_set();
}
return python::detail::new_reference(reinterpret_cast<PyObject*>(obj));
}
@@ -118,58 +123,68 @@ bool equivalent(dtype const & a, dtype const & b) {
#endif
}
namespace {
namespace
{
namespace pyconv = boost::python::converter;
template <typename T>
class array_scalar_converter {
class array_scalar_converter
{
public:
static PyTypeObject const * get_pytype() {
// This implementation depends on the fact that get_builtin returns pointers to objects
// NumPy has declared statically, and that the typeobj member also refers to a static
// object. That means we don't need to do any reference counting.
// In fact, I'm somewhat concerned that increasing the reference count of any of these
// might cause leaks, because I don't think Boost.Python ever decrements it, but it's
// probably a moot point if everything is actually static.
return reinterpret_cast<PyArray_Descr*>(dtype::get_builtin<T>().ptr())->typeobj;
static PyTypeObject const * get_pytype()
{
// This implementation depends on the fact that get_builtin returns pointers to objects
// NumPy has declared statically, and that the typeobj member also refers to a static
// object. That means we don't need to do any reference counting.
// In fact, I'm somewhat concerned that increasing the reference count of any of these
// might cause leaks, because I don't think Boost.Python ever decrements it, but it's
// probably a moot point if everything is actually static.
return reinterpret_cast<PyArray_Descr*>(dtype::get_builtin<T>().ptr())->typeobj;
}
static void * convertible(PyObject * obj) {
if (obj->ob_type == get_pytype()) {
return obj;
} else {
dtype dt(python::detail::borrowed_reference(obj->ob_type));
if (equivalent(dt, dtype::get_builtin<T>())) {
return obj;
}
}
static void * convertible(PyObject * obj)
{
if (obj->ob_type == get_pytype())
{
return obj;
}
else
{
dtype dt(python::detail::borrowed_reference(obj->ob_type));
if (equivalent(dt, dtype::get_builtin<T>()))
{
return obj;
}
}
return 0;
}
static void convert(PyObject * obj, pyconv::rvalue_from_python_stage1_data* data) {
void * storage = reinterpret_cast<pyconv::rvalue_from_python_storage<T>*>(data)->storage.bytes;
// We assume std::complex is a "standard layout" here and elsewhere; not guaranteed by
// C++03 standard, but true in every known implementation (and guaranteed by C++11).
PyArray_ScalarAsCtype(obj, reinterpret_cast<T*>(storage));
data->convertible = storage;
static void convert(PyObject * obj, pyconv::rvalue_from_python_stage1_data* data)
{
void * storage = reinterpret_cast<pyconv::rvalue_from_python_storage<T>*>(data)->storage.bytes;
// We assume std::complex is a "standard layout" here and elsewhere; not guaranteed by
// C++03 standard, but true in every known implementation (and guaranteed by C++11).
PyArray_ScalarAsCtype(obj, reinterpret_cast<T*>(storage));
data->convertible = storage;
}
static void declare() {
pyconv::registry::push_back(
&convertible, &convert, python::type_id<T>()
static void declare()
{
pyconv::registry::push_back(&convertible, &convert, python::type_id<T>()
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
, &get_pytype
, &get_pytype
#endif
);
);
}
};
} // anonymous
void dtype::register_scalar_converters() {
void dtype::register_scalar_converters()
{
array_scalar_converter<bool>::declare();
array_scalar_converter<npy_uint8>::declare();
array_scalar_converter<npy_int8>::declare();
@@ -196,5 +211,4 @@ void dtype::register_scalar_converters() {
#endif
}
} // namespace boost::numpy
} // namespace boost
}}} // namespace boost::python::numpy

View File

@@ -1,28 +1,25 @@
// Copyright Jim Bosch 2010-2012.
// Copyright Stefan Seefeld 2016.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#define BOOST_NUMPY_INTERNAL
#include <boost/numpy/internal.hpp>
#include <boost/numpy/matrix.hpp>
#define BOOST_PYTHON_NUMPY_INTERNAL
#include <boost/python/numpy/internal.hpp>
#include <boost/python/numpy/matrix.hpp>
namespace boost
namespace boost { namespace python { namespace numpy
{
namespace numpy
{
namespace detail
{
inline python::object get_matrix_type()
inline object get_matrix_type()
{
python::object module = python::import("numpy");
object module = import("numpy");
return module.attr("matrix");
}
} // namespace boost::numpy::detail
} // namespace boost::numpy
} // namespace boost::python::numpy::detail
} // namespace boost::python::numpy
namespace python
{
namespace converter
{
@@ -32,17 +29,16 @@ PyTypeObject const * object_manager_traits<numpy::matrix>::get_pytype()
}
} // namespace boost::python::converter
} // namespace boost::python
namespace numpy
{
python::object matrix::construct(python::object const & obj, dtype const & dt, bool copy)
object matrix::construct(object const & obj, dtype const & dt, bool copy)
{
return numpy::detail::get_matrix_type()(obj, dt, copy);
}
python::object matrix::construct(python::object const & obj, bool copy)
object matrix::construct(object const & obj, bool copy)
{
return numpy::detail::get_matrix_type()(obj, object(), copy);
}
@@ -61,8 +57,7 @@ matrix matrix::copy() const
matrix matrix::transpose() const
{
return matrix(python::extract<matrix>(ndarray::transpose()));
return matrix(extract<matrix>(ndarray::transpose()));
}
} // namespace boost::numpy
} // namespace boost
}}} // namespace boost::python::numpy

View File

@@ -1,21 +1,18 @@
// Copyright Jim Bosch 2010-2012.
// Copyright Stefan Seefeld 2016.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#define BOOST_NUMPY_INTERNAL
#include <boost/numpy/internal.hpp>
#define BOOST_PYTHON_NUMPY_INTERNAL
#include <boost/python/numpy/internal.hpp>
#include <boost/scoped_array.hpp>
namespace boost
{
namespace python
{
namespace boost { namespace python {
namespace converter
{
NUMPY_OBJECT_MANAGER_TRAITS_IMPL(PyArray_Type, numpy::ndarray)
} // namespace boost::python::converter
} // namespace boost::python
namespace numpy
{
@@ -277,5 +274,4 @@ ndarray from_object(python::object const & obj, int nd_min, int nd_max, ndarray:
NULL)));
}
}
}
}}} // namespace boost::python::numpy

View File

@@ -1,24 +1,24 @@
// Copyright Jim Bosch 2010-2012.
// Copyright Stefan Seefeld 2016.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#define BOOST_NUMPY_INTERNAL_MAIN
#include <boost/numpy/internal.hpp>
#include <boost/numpy/dtype.hpp>
#define BOOST_PYTHON_NUMPY_INTERNAL_MAIN
#include <boost/python/numpy/internal.hpp>
#include <boost/python/numpy/dtype.hpp>
namespace boost
{
namespace numpy
{
namespace boost { namespace python { namespace numpy {
#if PY_MAJOR_VERSION == 2
static void wrap_import_array() {
import_array();
static void wrap_import_array()
{
import_array();
}
#else
static void * wrap_import_array() {
import_array();
static void * wrap_import_array()
{
import_array();
}
#endif
@@ -30,5 +30,4 @@ void initialize(bool register_scalar_converters)
dtype::register_scalar_converters();
}
}
}
}}} // namespace boost::python::numpy

View File

@@ -1,20 +1,17 @@
// Copyright Jim Bosch 2010-2012.
// Copyright Stefan Seefeld 2016.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#define BOOST_NUMPY_INTERNAL
#include <boost/numpy/internal.hpp>
#define BOOST_PYTHON_NUMPY_INTERNAL
#include <boost/python/numpy/internal.hpp>
namespace boost
{
namespace python
{
namespace boost { namespace python {
namespace converter
{
NUMPY_OBJECT_MANAGER_TRAITS_IMPL(PyVoidArrType_Type, numpy::void_)
} // namespace boost::python::converter
} // namespace boost::python
namespace numpy
{
@@ -36,5 +33,4 @@ void_ void_::copy() const
(PyObject_CallMethod(this->ptr(), const_cast<char*>("copy"), const_cast<char*>(""))));
}
}
}
}}} // namespace boost::python::numpy

View File

@@ -1,36 +1,33 @@
// Copyright Jim Bosch 2010-2012.
// Copyright Stefan Seefeld 2016.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#define BOOST_NUMPY_INTERNAL
#include <boost/numpy/internal.hpp>
#include <boost/numpy/ufunc.hpp>
#define BOOST_PYTHON_NUMPY_INTERNAL
#include <boost/python/numpy/internal.hpp>
#include <boost/python/numpy/ufunc.hpp>
namespace boost
{
namespace python
{
namespace boost { namespace python {
namespace converter
{
NUMPY_OBJECT_MANAGER_TRAITS_IMPL(PyArrayMultiIter_Type, numpy::multi_iter)
} // namespace boost::python::converter
} // namespace boost::python
namespace numpy
{
multi_iter make_multi_iter(python::object const & a1)
multi_iter make_multi_iter(object const & a1)
{
return multi_iter(python::detail::new_reference(PyArray_MultiIterNew(1, a1.ptr())));
}
multi_iter make_multi_iter(python::object const & a1, python::object const & a2)
multi_iter make_multi_iter(object const & a1, object const & a2)
{
return multi_iter(python::detail::new_reference(PyArray_MultiIterNew(2, a1.ptr(), a2.ptr())));
}
multi_iter make_multi_iter(python::object const & a1, python::object const & a2, python::object const & a3)
multi_iter make_multi_iter(object const & a1, object const & a2, object const & a3)
{
return multi_iter(python::detail::new_reference(PyArray_MultiIterNew(3, a1.ptr(), a2.ptr(), a3.ptr())));
}
@@ -65,5 +62,4 @@ Py_intptr_t multi_iter::shape(int n) const
return reinterpret_cast<PyArrayMultiIterObject*>(ptr())->dimensions[n];
}
}
}
}}} // namespace boost::python::numpy

View File

@@ -47,7 +47,6 @@ for test in [('injected',),
('minimal',),
('args',),
('raw_ctor',),
('numpy',None, ['printer.py', 'numeric_tests.py', 'numarray_tests.py']),
('exception_translator',),
('test_enum', ['enum_ext']),
('test_cltree', ['cltree']),
@@ -80,7 +79,7 @@ for test in [('injected',),
('extract',),
('crossmod_opaque', ['crossmod_opaque_a', 'crossmod_opaque_b']),
('opaque',),
('voidptr',),
# ('voidptr',),
('pickle1',),
('pickle2',),
('pickle3',),
@@ -145,5 +144,17 @@ if platform.system() == 'Windows':
tests+=env.BPLTest('calling_conventions')
tests+=env.BPLTest('calling_conventions_mf')
if env['NUMPY']:
numpy_env = env.Clone()
numpy_env.BoostUseLib('numpy')
for test in [('numpy/dtype',),
('numpy/ufunc',),
('numpy/templates',),
('numpy/ndarray',),
('numpy/indexing',),
('numpy/shapes',),]:
tests+=numpy_env.BPLTest(*test)
env.BoostTestSummary(tests)
AlwaysBuild(tests)

View File

@@ -1,20 +1,21 @@
// Copyright Jim Bosch & Ankit Daftery 2010-2012.
// Copyright Stefan Seefeld 2016.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/numpy.hpp>
#include <boost/python/numpy.hpp>
#include <boost/cstdint.hpp>
namespace p = boost::python;
namespace np = boost::numpy;
namespace np = boost::python::numpy;
template <typename T>
np::dtype accept(T) {
return np::dtype::get_builtin<T>();
}
BOOST_PYTHON_MODULE(dtype_mod)
BOOST_PYTHON_MODULE(dtype_ext)
{
np::initialize();
// wrap dtype equivalence test, since it isn't available in Python API.

View File

@@ -5,21 +5,21 @@
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
import dtype_mod
import dtype_ext
import unittest
import numpy
class DtypeTestCase(unittest.TestCase):
def assertEquivalent(self, a, b):
return self.assert_(dtype_mod.equivalent(a, b), "%r is not equivalent to %r")
return self.assert_(dtype_ext.equivalent(a, b), "%r is not equivalent to %r")
def testIntegers(self):
for bits in (8, 16, 32, 64):
s = getattr(numpy, "int%d" % bits)
u = getattr(numpy, "uint%d" % bits)
fs = getattr(dtype_mod, "accept_int%d" % bits)
fu = getattr(dtype_mod, "accept_uint%d" % bits)
fs = getattr(dtype_ext, "accept_int%d" % bits)
fu = getattr(dtype_ext, "accept_uint%d" % bits)
self.assertEquivalent(fs(s(1)), numpy.dtype(s))
self.assertEquivalent(fu(u(1)), numpy.dtype(u))
# these should just use the regular Boost.Python converters
@@ -31,7 +31,7 @@ class DtypeTestCase(unittest.TestCase):
self.assertEquivalent(fu(long(1)), numpy.dtype(u))
for name in ("bool_", "byte", "ubyte", "short", "ushort", "intc", "uintc"):
t = getattr(numpy, name)
ft = getattr(dtype_mod, "accept_%s" % name)
ft = getattr(dtype_ext, "accept_%s" % name)
self.assertEquivalent(ft(t(1)), numpy.dtype(t))
# these should just use the regular Boost.Python converters
self.assertEquivalent(ft(True), numpy.dtype(t))
@@ -43,17 +43,17 @@ class DtypeTestCase(unittest.TestCase):
def testFloats(self):
f = numpy.float32
c = numpy.complex64
self.assertEquivalent(dtype_mod.accept_float32(f(numpy.pi)), numpy.dtype(f))
self.assertEquivalent(dtype_mod.accept_complex64(c(1+2j)), numpy.dtype(c))
self.assertEquivalent(dtype_ext.accept_float32(f(numpy.pi)), numpy.dtype(f))
self.assertEquivalent(dtype_ext.accept_complex64(c(1+2j)), numpy.dtype(c))
f = numpy.float64
c = numpy.complex128
self.assertEquivalent(dtype_mod.accept_float64(f(numpy.pi)), numpy.dtype(f))
self.assertEquivalent(dtype_mod.accept_complex128(c(1+2j)), numpy.dtype(c))
if hasattr(numpy, "longdouble") and hasattr(dtype_mod, "accept_longdouble"):
self.assertEquivalent(dtype_ext.accept_float64(f(numpy.pi)), numpy.dtype(f))
self.assertEquivalent(dtype_ext.accept_complex128(c(1+2j)), numpy.dtype(c))
if hasattr(numpy, "longdouble") and hasattr(dtype_ext, "accept_longdouble"):
f = numpy.longdouble
c = numpy.clongdouble
self.assertEquivalent(dtype_mod.accept_longdouble(f(numpy.pi)), numpy.dtype(f))
self.assertEquivalent(dtype_mod.accept_clongdouble(c(1+2j)), numpy.dtype(c))
self.assertEquivalent(dtype_ext.accept_longdouble(f(numpy.pi)), numpy.dtype(f))
self.assertEquivalent(dtype_ext.accept_clongdouble(c(1+2j)), numpy.dtype(c))
if __name__=="__main__":

View File

@@ -1,13 +1,14 @@
// Copyright Jim Bosch & Ankit Daftery 2010-2012.
// Copyright Stefan Seefeld 2016.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/numpy.hpp>
#include <boost/python/numpy.hpp>
#include <boost/python/slice.hpp>
namespace p = boost::python;
namespace np = boost::numpy;
namespace np = boost::python::numpy;
p::object single(np::ndarray ndarr, int i) { return ndarr[i];}
p::object slice(np::ndarray ndarr, p::slice sl) { return ndarr[sl];}
@@ -15,7 +16,7 @@ p::object indexarray(np::ndarray ndarr, np::ndarray d1) { return ndarr[d1];}
p::object indexarray_2d(np::ndarray ndarr, np::ndarray d1,np::ndarray d2) { return ndarr[p::make_tuple(d1,d2)];}
p::object indexslice(np::ndarray ndarr, np::ndarray d1, p::slice sl) { return ndarr[p::make_tuple(d1, sl)];}
BOOST_PYTHON_MODULE(indexing_mod)
BOOST_PYTHON_MODULE(indexing_ext)
{
np::initialize();
p::def("single", single);

View File

@@ -7,49 +7,49 @@
import unittest
import numpy
import indexing_mod
import indexing_ext
class TestIndexing(unittest.TestCase):
def testSingle(self):
x = numpy.arange(0,10)
for i in range(0,10):
numpy.testing.assert_equal(indexing_mod.single(x,i), i)
numpy.testing.assert_equal(indexing_ext.single(x,i), i)
for i in range(-10,0):
numpy.testing.assert_equal(indexing_mod.single(x,i),10+i)
numpy.testing.assert_equal(indexing_ext.single(x,i),10+i)
def testSlice(self):
x = numpy.arange(0,10)
sl = slice(3,8)
b = [3,4,5,6,7]
numpy.testing.assert_equal(indexing_mod.slice(x,sl), b)
numpy.testing.assert_equal(indexing_ext.slice(x,sl), b)
def testStepSlice(self):
x = numpy.arange(0,10)
sl = slice(3,8,2)
b = [3,5,7]
numpy.testing.assert_equal(indexing_mod.slice(x,sl), b)
numpy.testing.assert_equal(indexing_ext.slice(x,sl), b)
def testIndex(self):
x = numpy.arange(0,10)
chk = numpy.array([3,4,5,6])
numpy.testing.assert_equal(indexing_mod.indexarray(x,chk),chk)
numpy.testing.assert_equal(indexing_ext.indexarray(x,chk),chk)
chk = numpy.array([[0,1],[2,3]])
numpy.testing.assert_equal(indexing_mod.indexarray(x,chk),chk)
numpy.testing.assert_equal(indexing_ext.indexarray(x,chk),chk)
x = numpy.arange(9).reshape(3,3)
y = numpy.array([0,1])
z = numpy.array([0,2])
chk = numpy.array([0,5])
numpy.testing.assert_equal(indexing_mod.indexarray(x,y,z),chk)
numpy.testing.assert_equal(indexing_ext.indexarray(x,y,z),chk)
x = numpy.arange(0,10)
b = x>4
chk = numpy.array([5,6,7,8,9])
numpy.testing.assert_equal(indexing_mod.indexarray(x,b),chk)
numpy.testing.assert_equal(indexing_ext.indexarray(x,b),chk)
x = numpy.arange(9).reshape(3,3)
b = numpy.array([0,2])
sl = slice(0,3)
chk = numpy.array([[0,1,2],[6,7,8]])
numpy.testing.assert_equal(indexing_mod.indexslice(x,b,sl),chk)
numpy.testing.assert_equal(indexing_ext.indexslice(x,b,sl),chk)
if __name__=="__main__":
unittest.main()

View File

@@ -1,19 +1,20 @@
// Copyright Jim Bosch & Ankit Daftery 2010-2012.
// Copyright Stefan Seefeld 2016.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/numpy.hpp>
#include <boost/python/numpy.hpp>
namespace p = boost::python;
namespace np = boost::numpy;
namespace np = boost::python::numpy;
np::ndarray zeros(p::tuple shape, np::dtype dt) { return np::zeros(shape, dt);}
np::ndarray array2(p::object obj, np::dtype dt) { return np::array(obj,dt);}
np::ndarray array1(p::object obj) { return np::array(obj);}
np::ndarray empty1(p::tuple shape, np::dtype dt) { return np::empty(shape,dt);}
np::ndarray c_empty(p::tuple shape, np::dtype dt)
np::ndarray c_empty(p::tuple shape, np::dtype dt)
{
// convert 'shape' to a C array so we can test the corresponding
// version of the constructor
@@ -30,7 +31,7 @@ np::ndarray transpose(np::ndarray arr) { return arr.transpose();}
np::ndarray squeeze(np::ndarray arr) { return arr.squeeze();}
np::ndarray reshape(np::ndarray arr,p::tuple tup) { return arr.reshape(tup);}
BOOST_PYTHON_MODULE(ndarray_mod)
BOOST_PYTHON_MODULE(ndarray_ext)
{
np::initialize();
p::def("zeros", zeros);

View File

@@ -5,7 +5,7 @@
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
import ndarray_mod
import ndarray_ext
import unittest
import numpy
@@ -16,7 +16,7 @@ class TestNdarray(unittest.TestCase):
v = numpy.zeros(60, dtype=dtp)
dt = numpy.dtype(dtp)
for shape in ((60,),(6,10),(4,3,5),(2,2,3,5)):
a1 = ndarray_mod.zeros(shape,dt)
a1 = ndarray_ext.zeros(shape,dt)
a2 = v.reshape(a1.shape)
self.assertEqual(shape,a1.shape)
self.assert_((a1 == a2).all())
@@ -25,7 +25,7 @@ class TestNdarray(unittest.TestCase):
for dtp in (numpy.int16, numpy.int32, numpy.float32, numpy.complex128):
dt = numpy.dtype(dtp)
shape = (6, 10)
a1 = ndarray_mod.zeros_matrix(shape, dt)
a1 = ndarray_ext.zeros_matrix(shape, dt)
a2 = numpy.matrix(numpy.zeros(shape, dtype=dtp))
self.assertEqual(shape,a1.shape)
self.assert_((a1 == a2).all())
@@ -36,8 +36,8 @@ class TestNdarray(unittest.TestCase):
for dtp in (numpy.int16, numpy.int32, numpy.float32, numpy.complex128):
v = numpy.array(a, dtype=dtp)
dt = numpy.dtype(dtp)
a1 = ndarray_mod.array(a)
a2 = ndarray_mod.array(a,dt)
a1 = ndarray_ext.array(a)
a2 = ndarray_ext.array(a,dt)
self.assert_((a1 == v).all())
self.assert_((a2 == v).all())
for shape in ((60,),(6,10),(4,3,5),(2,2,3,5)):
@@ -50,8 +50,8 @@ class TestNdarray(unittest.TestCase):
for dtp in (numpy.int16, numpy.int32, numpy.float32, numpy.complex128):
dt = numpy.dtype(dtp)
for shape in ((60,),(6,10),(4,3,5),(2,2,3,5)):
a1 = ndarray_mod.empty(shape,dt)
a2 = ndarray_mod.c_empty(shape,dt)
a1 = ndarray_ext.empty(shape,dt)
a2 = ndarray_ext.c_empty(shape,dt)
self.assertEqual(shape,a1.shape)
self.assertEqual(shape,a2.shape)
@@ -61,18 +61,18 @@ class TestNdarray(unittest.TestCase):
for shape in ((6,10),(4,3,5),(2,2,3,5)):
a1 = numpy.empty(shape,dt)
a2 = a1.transpose()
a1 = ndarray_mod.transpose(a1)
a1 = ndarray_ext.transpose(a1)
self.assertEqual(a1.shape,a2.shape)
def testSqueeze(self):
a1 = numpy.array([[[3,4,5]]])
a2 = a1.squeeze()
a1 = ndarray_mod.squeeze(a1)
a1 = ndarray_ext.squeeze(a1)
self.assertEqual(a1.shape,a2.shape)
def testReshape(self):
a1 = numpy.empty((2,2))
a2 = ndarray_mod.reshape(a1,(1,4))
a2 = ndarray_ext.reshape(a1,(1,4))
self.assertEqual(a2.shape,(1,4))
if __name__=="__main__":

View File

@@ -1,12 +1,13 @@
// Copyright Jim Bosch & Ankit Daftery 2010-2012.
// Copyright Stefan Seefeld 2016.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/numpy.hpp>
#include <boost/python/numpy.hpp>
namespace p = boost::python;
namespace np = boost::numpy;
namespace np = boost::python::numpy;
np::ndarray reshape(np::ndarray old_array, p::tuple shape)
{
@@ -14,7 +15,7 @@ np::ndarray reshape(np::ndarray old_array, p::tuple shape)
return local_shape;
}
BOOST_PYTHON_MODULE(shapes_mod)
BOOST_PYTHON_MODULE(shapes_ext)
{
np::initialize();
p::def("reshape", reshape);

View File

@@ -5,7 +5,7 @@
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
import shapes_mod
import shapes_ext
import unittest
import numpy
@@ -14,7 +14,7 @@ class TestShapes(unittest.TestCase):
def testShapes(self):
a1 = numpy.array([(0,1),(2,3)])
a1_shape = (1,4)
a1 = shapes_mod.reshape(a1,a1_shape)
a1 = shapes_ext.reshape(a1,a1_shape)
self.assertEqual(a1_shape,a1.shape)
if __name__=="__main__":

View File

@@ -1,16 +1,17 @@
// Copyright Jim Bosch & Ankit Daftery 2010-2012.
// Copyright Stefan Seefeld 2016.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/numpy.hpp>
#include <boost/python/numpy.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/vector_c.hpp>
namespace p = boost::python;
namespace np = boost::numpy;
namespace np = boost::python::numpy;
struct ArrayFiller
struct ArrayFiller
{
typedef boost::mpl::vector< short, int, float, std::complex<double> > TypeSequence;
@@ -19,14 +20,14 @@ struct ArrayFiller
explicit ArrayFiller(np::ndarray const & arg) : argument(arg) {}
template <typename T, int N>
void apply() const
void apply() const
{
if (N == 1)
if (N == 1)
{
char * p = argument.get_data();
int stride = argument.strides(0);
int size = argument.shape(0);
for (int n = 0; n != size; ++n, p += stride)
for (int n = 0; n != size; ++n, p += stride)
*reinterpret_cast<T*>(p) = static_cast<T>(n);
}
else
@@ -37,7 +38,7 @@ struct ArrayFiller
int rows = argument.shape(0);
int cols = argument.shape(1);
int i = 0;
for (int n = 0; n != rows; ++n, row_p += row_stride)
for (int n = 0; n != rows; ++n, row_p += row_stride)
{
char * col_p = row_p;
for (int m = 0; m != cols; ++i, ++m, col_p += col_stride)
@@ -49,13 +50,13 @@ struct ArrayFiller
np::ndarray argument;
};
void fill(np::ndarray const & arg)
void fill(np::ndarray const & arg)
{
ArrayFiller filler(arg);
np::invoke_matching_array<ArrayFiller::TypeSequence, ArrayFiller::DimSequence >(arg, filler);
}
BOOST_PYTHON_MODULE(templates_mod)
BOOST_PYTHON_MODULE(templates_ext)
{
np::initialize();
p::def("fill", fill);

View File

@@ -5,7 +5,7 @@
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
import templates_mod
import templates_ext
import unittest
import numpy
@@ -17,12 +17,12 @@ class TestTemplates(unittest.TestCase):
for shape in ((12,), (4, 3), (2, 6)):
a1 = numpy.zeros(shape, dtype=dtype)
a2 = v.reshape(a1.shape)
templates_mod.fill(a1)
templates_ext.fill(a1)
self.assert_((a1 == a2).all())
a1 = numpy.zeros((12,), dtype=numpy.float64)
self.assertRaises(TypeError, templates_mod.fill, a1)
self.assertRaises(TypeError, templates_ext.fill, a1)
a1 = numpy.zeros((12,2,3), dtype=numpy.float32)
self.assertRaises(TypeError, templates_mod.fill, a1)
self.assertRaises(TypeError, templates_ext.fill, a1)
if __name__=="__main__":
unittest.main()

View File

@@ -1,14 +1,15 @@
// Copyright Jim Bosch & Ankit Daftery 2010-2012.
// Copyright Stefan Seefeld 2016.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/numpy.hpp>
#include <boost/python/numpy.hpp>
namespace p = boost::python;
namespace np = boost::numpy;
namespace np = boost::python::numpy;
struct UnaryCallable
struct UnaryCallable
{
typedef double argument_type;
typedef double result_type;
@@ -16,7 +17,7 @@ struct UnaryCallable
double operator()(double r) const { return r * 2;}
};
struct BinaryCallable
struct BinaryCallable
{
typedef double first_argument_type;
typedef double second_argument_type;
@@ -25,7 +26,7 @@ struct BinaryCallable
double operator()(double a, double b) const { return a * 2 + b * 3;}
};
BOOST_PYTHON_MODULE(ufunc_mod)
BOOST_PYTHON_MODULE(ufunc_ext)
{
np::initialize();
p::class_<UnaryCallable>("UnaryCallable")

View File

@@ -5,7 +5,7 @@
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
import ufunc_mod
import ufunc_ext
import unittest
import numpy
from numpy.testing.utils import assert_array_almost_equal
@@ -13,12 +13,12 @@ from numpy.testing.utils import assert_array_almost_equal
class TestUnary(unittest.TestCase):
def testScalar(self):
f = ufunc_mod.UnaryCallable()
f = ufunc_ext.UnaryCallable()
assert_array_almost_equal(f(1.0), 2.0)
assert_array_almost_equal(f(3.0), 6.0)
def testArray(self):
f = ufunc_mod.UnaryCallable()
f = ufunc_ext.UnaryCallable()
a = numpy.arange(5, dtype=float)
b = f(a)
assert_array_almost_equal(b, a*2.0)
@@ -28,7 +28,7 @@ class TestUnary(unittest.TestCase):
assert_array_almost_equal(d, a*2.0)
def testList(self):
f = ufunc_mod.UnaryCallable()
f = ufunc_ext.UnaryCallable()
a = range(5)
b = f(a)
assert_array_almost_equal(b/2.0, a)
@@ -36,12 +36,12 @@ class TestUnary(unittest.TestCase):
class TestBinary(unittest.TestCase):
def testScalar(self):
f = ufunc_mod.BinaryCallable()
f = ufunc_ext.BinaryCallable()
assert_array_almost_equal(f(1.0, 3.0), 11.0)
assert_array_almost_equal(f(3.0, 2.0), 12.0)
def testArray(self):
f = ufunc_mod.BinaryCallable()
f = ufunc_ext.BinaryCallable()
a = numpy.random.randn(5)
b = numpy.random.randn(5)
assert_array_almost_equal(f(a,b), (a*2+b*3))