2
0
mirror of https://github.com/boostorg/python.git synced 2026-01-19 16:32:16 +00:00

Compare commits

...

196 Commits

Author SHA1 Message Date
Stefan Seefeld
7d3df3d3a7 Merge branch 'develop' 2017-03-28 12:57:32 -04:00
Stefan Seefeld
df16e3e55e Fix typo. 2017-03-28 12:54:05 -04:00
Stefan Seefeld
ae747521b0 Merge branch 'develop' 2017-03-24 15:53:30 -04:00
Stefan Seefeld
3066c73c09 Fix Windows builds. 2017-03-24 15:39:13 -04:00
Stefan Seefeld
edd890bd2b More dllexport fixes 2017-03-24 15:39:13 -04:00
Stefan Seefeld
352792c90a Add more export symbols. 2017-03-16 20:14:39 -04:00
Stefan Seefeld
47faef65ee Fix documentation links. 2017-03-16 11:35:26 -04:00
Rene Rivera
5e4b44e0af Don't build numpy if there's no python version to target. 2017-03-06 10:39:01 -06:00
Rene Rivera
5121fc11f9 Don't build numpy if there's no python version to target. 2017-03-06 10:30:41 -06:00
Rene Rivera
07b1489f3b BPL builds targets need to always be defined. 2017-03-05 15:17:26 -06:00
Rene Rivera
471e6181b2 BPL builds targets need to always be defined. 2017-03-05 15:16:36 -06:00
Rene Rivera
44ea0562b2 Fix no pynumpy target when no numpy configured. 2017-03-05 09:00:27 -06:00
Rene Rivera
60fba03e99 Fix libs from referencing BPL when there is no python configured. 2017-03-05 09:00:10 -06:00
Rene Rivera
398e7f02b8 Fix no pynumpy target when no numpy configured. 2017-03-05 08:56:57 -06:00
Rene Rivera
1e315242ce Fix libs from referencing BPL when there is no python configured. 2017-03-03 22:28:22 -06:00
al3xst
77ee91d5c5 Updated python library reference url
Due to changes on the python website, the url to the pickle library reference page was invalid.
2017-03-03 18:29:05 -05:00
Stefan Seefeld
e3c9dd78aa Merge branch 'develop' 2017-03-03 18:07:49 -05:00
Rene Rivera
e670de2795 Fix empty numpy lib name caused by missing parens for lib name map. 2017-03-02 21:55:49 -06:00
Rene Rivera
367b793ac9 Merge branch 'develop' of https://github.com/boostorg/python.git into develop 2017-03-01 10:15:47 -06:00
Rene Rivera
8c170d9193 Fix building of multiple BPL libs even when the configured python does
not match.
2017-03-01 10:15:37 -06:00
SPKorhonen
bd7b8ecba5 Fix for missing export symbols, issue #98 (#110)
Fix for missing export symbols in shared library of boost::python::numpy
2017-02-15 11:53:28 -05:00
Jürgen Hunold
0224f54ae0 Switch^Cisibility support to BOOST_SYMBOL_EXPORT. Refs #2114 2017-02-13 10:43:23 -05:00
Stefan Seefeld
d14b8cf411 Fix library dependency with Python 3. 2017-01-03 21:17:51 -05:00
Tadeu Manoel
4e0b96faa8 Fix conversion of PyUnicodeObject to wstring (#93) 2016-12-14 07:58:07 -05:00
Tadeu Manoel
7178a70176 Fix a problem where test_builtin_converters.py is not being run (#94)
This was happening because the module docstring was not the first statement.
2016-12-14 07:54:37 -05:00
Stefan Seefeld
aaf9022770 Merge branch 'develop' 2016-11-02 14:12:45 -04:00
Vladimir Prus
36bbdde2fe Use Boost-global python tagging. 2016-10-28 11:56:15 +03:00
Stefan Seefeld
1df6d84b80 Fix Python 3 incompatibility. 2016-10-27 08:37:25 -04:00
Stefan Seefeld
e968329174 Clean up examples. 2016-10-23 21:34:16 -04:00
Stefan Seefeld
07c8cbe652 Adjust to Boost.Build changes. 2016-10-23 21:27:31 -04:00
Stefan Seefeld
163e469bc4 Minor fixes. 2016-10-19 11:25:48 -04:00
Stefan Seefeld
ac39d2ed69 Fix doc build. 2016-10-19 07:34:34 -04:00
Stefan Seefeld
264f6ae4b9 Work around a sphinx bug. 2016-10-18 21:14:47 -04:00
Stefan Seefeld
84c96447e2 Add NumPy support to the BB-based build logic. 2016-10-18 16:32:05 -04:00
Stefan Seefeld
dc8d68d3fc Fix id clash in hierarchical tocs. 2016-10-16 20:30:15 -04:00
Stefan Seefeld
91512a971d More doc fine-tuning. 2016-10-10 14:22:57 -04:00
Rene Rivera
88ea1f9626 Fix syntax error caused by merging. 2016-10-10 12:22:25 -05:00
Rene Rivera
731ba745ca Add, and update, documentation build targets. 2016-10-10 12:22:10 -05:00
Stefan Seefeld
080eb55be6 Fine-tune documentation formatting. 2016-10-10 12:02:28 -04:00
Rene Rivera
a3d8223b5d Fix syntax error caused by merging. 2016-10-09 11:04:38 -05:00
Stefan Seefeld
b9431cd326 Remove obsolete tests from build logic. 2016-10-09 09:19:20 -04:00
Stefan Seefeld
2ccf54f091 Minor doc touch-ups. 2016-10-09 00:02:39 -04:00
Stefan Seefeld
4ce4821111 Remove obsolete tests. 2016-10-08 15:29:56 -04:00
Rene Rivera
69ddfcae17 Add, and update, documentation build targets. 2016-10-08 15:16:38 -04:00
Stefan Seefeld
3ace4a0015 Adjust NumPy code to work with new directory / namespace structure. 2016-10-08 13:34:17 -04:00
Stefan Seefeld
cbb3851488 Merge NumPy extension from https://github.com/ndarray/Boost.NumPy/. 2016-10-07 20:03:12 -04:00
Stefan Seefeld
127cc20a1d Install documentation for development branch separately. 2016-10-07 18:17:43 -04:00
Stefan Seefeld
482219f20a Remove a bunch of obsolete files. 2016-09-29 23:18:00 -04:00
Wei-Ming Yang
061050c006 Fix a mistake in str::count() 2016-09-29 08:09:30 -04:00
Wei-Ming Yang
03adaee6d2 Implement str::endswith() 2016-09-29 08:08:46 -04:00
WKarel
bc2f77a3db Assert refcount before decrement (#64)
Assert reference count before decrementing it.
2016-09-29 07:48:46 -04:00
vmurashev
aaf0d220ae tests for python3 - get rid of 'from past.builtins import long' 2016-09-28 22:44:46 -04:00
vmurashev
bb6f52dc35 test/exec.cpp - register builtin module before call 'Py_Initialize' 2016-09-28 22:44:46 -04:00
Stefan Seefeld
d422058fb4 Adjust BB logic to shared_ptr test changes. 2016-09-28 16:59:44 -04:00
Stefan Seefeld
a60ab14b91 Fix doc upload. 2016-09-28 13:37:15 -04:00
Stefan Seefeld
e0ee734161 Update credentials to upload generated docs. 2016-09-28 08:31:12 -04:00
Stefan Seefeld
444c948abe Fix doc upload. 2016-09-27 20:13:38 -04:00
Stefan Seefeld
97e4b34a15 Add support for std::shared_ptr. 2016-09-27 13:53:37 -04:00
Stefan Seefeld
5029273ca8 Use std::unique_ptr instead of std::auto_ptr 2016-09-22 20:30:33 -04:00
Jim Bosch
26aaa5b62e Merge pull request #51 from willyd/vscompat
Visual Studio compatibility fixes
2015-11-21 18:36:38 -05:00
Guillaume Dumont
f753f4bc30 Visual Studio compatibility fixes
Static linking fix
2015-09-16 10:18:23 -04:00
Jim Bosch
9e53eb2c23 Fix some confusing magic numbers in docs for stride (#50).
Documentation here needs a bigger cleanup than I can give it
right now, but this at least removes the ambiguity as to whether
"4" means the shape or sizeof(int).
2015-09-09 23:55:28 -04:00
Jim Bosch
6c2e3fb487 Update README and convert it to Markdown. 2015-09-09 23:48:55 -04:00
Jim Bosch
fcbba59630 Enable tests in CMake build and fix relative path problems.
As reported in #46, tests were not being built with CMake due
to a typo.  But they were also broken, because the relative path
to the dynamic library used in the link commands for the test
Python modules wasn't appropriate for running the tests from
the source directory.  Instead, we now copy the Python test
scripts to the build directory and run them there.
2015-09-09 23:27:40 -04:00
Jim Bosch
61a399e80a Remove const from rvalue returns (#42).
I'd originally thought this was a useful way to prevent no-op
assignments to rvalues, but compilers now check for that
without using const, and it was probably only non-standard
compiler behavior that ever made it useful.
2015-09-09 22:38:50 -04:00
Jim Bosch
a0e849ed91 Switch from int to Py_intptr_t for shape/stride returns. 2015-01-18 10:00:42 -05:00
Christoph Lassner
4dbb2784ee Removed unnecessary defaults. 2015-01-17 14:06:22 -05:00
Christoph Lassner
4d9ab505b0 Updated build system behaviour and comments for the --with-boost option. 2015-01-17 14:06:00 -05:00
Jim Bosch
3494381c01 Resolve dtype equivalence issue in MSVC 2014-11-23 12:39:57 -05:00
Christoph Lassner
bc13c4c600 Fixed unsigned long test error. 2014-11-23 12:39:57 -05:00
Christoph Lassner
73b8350e53 Switch SCons to use SConsChecks submodule for Windows support 2014-11-23 12:39:52 -05:00
Jim Bosch
c509a3ab01 Merge pull request #39 from termoshtt/cmake_python3
(with minor modification from Jim Bosch)
2014-11-23 12:05:52 -05:00
Toshiki Teramura
4c2070f39f Revise example/wrap.cpp for python3 2014-11-23 12:03:58 -05:00
Toshiki Teramura
e2c23fd5f9 Append python version detector
Slight modifications from Jim Bosch for more standard language in
build system language.
2014-11-23 12:03:15 -05:00
Jim Bosch
7ff5465e7d Merge pull request #36 from ChrislS/master
SCons change to build a static lib for Windows
2014-09-25 20:19:38 -04:00
Christoph Lassner
e747cc9422 * SCons change to build a static lib for Windows. 2014-09-25 18:25:05 +02:00
Jim Bosch
b46ccc4f51 Merge pull request #35 from karlssonper/master
Examples and tests optional to build in CMake
2014-08-26 14:12:02 -04:00
per
be72aab254 Examples and tests are now optional to build. The default behavior is the same as before where both are built. 2014-08-18 11:28:53 +02:00
Jim Bosch
5035f6e801 Merge pull request #34 from karlssonper/master
added the NPY_FLOAT16 dtype
2014-08-04 15:10:44 -06:00
Per
0b549aee88 added the NPY_FLOAT16 dtype 2014-08-04 16:38:02 +02:00
Jim Bosch
bf73da1bce Merge pull request #31 from nbecker/master
SCons build system updates to support Python 3
2014-06-02 21:52:21 -04:00
Neal D. Becker
ca8ce585b7 Use equivalent, but doesn't seem to help 2014-06-02 09:40:28 -04:00
Neal D. Becker
81551cf6b6 port to py3 2014-06-02 09:40:00 -04:00
Jim Bosch
e3bf3c6f51 Merge pull request #29 from coroa/master
cmake: switch from using deprecated linklibraries to target_linklibraries
2013-10-10 15:46:08 -07:00
Jonas Hoersch
c8798676f6 cmake: switch from using deprecated linklibraries to target_linklibraries
the total information duplication actually decreases and it
facilitates reusing CMake instructions from outer projects.
2013-10-06 20:03:51 +02:00
Jim Bosch
c9974daec2 Avoid Python 3 compile warnings in NumPy initialization 2013-08-24 18:08:01 -04:00
Jim Bosch
b46dfd9064 Qualify calls to template member functions in invoke_matching.
This is necessary to avoid a bug in which a template struct from another
namespace can be confused with the member function by the parser
(see gcc bug 55576; it's apparently a defect in the C++98 standard).
2013-03-19 11:38:08 -04:00
Jim Bosch
956606ef0c Update README to mention CMake build system. 2013-03-15 23:08:40 -04:00
Philip Miller
0b59058fa2 Add cmake build system, fix examples for Windows compatibility. 2013-03-15 23:08:16 -04:00
Jim Bosch
2a41c80c58 Fix embedding issues with statically-compiled Python, at least on Linux. Use LINKFLAGS instead of LDFLAGS (see also #23; patch from Luc Bourhis) 2013-03-07 09:41:10 -05:00
Jim Bosch
42a57978ee Merge pull request #17 from awishnick/master
Added astype to ndarray
2013-01-18 13:46:42 -08:00
Aaron Wishnick
4b99e6b83f Add astype to ndarray. 2013-01-11 15:16:29 -05:00
Jim Bosch
49b536fbd3 replace non-constant array sizes with scoped_array 2012-12-10 23:32:08 -05:00
Jim Bosch
2e47285fb5 Add license file and license header to source files. 2012-09-26 00:33:10 -04:00
Jim Bosch
45b588b85a Merge pull request #12 from barnabyrobson/patch-1
Update SConscript to print the correct message when Boost.Python config test cannot be run.
2012-09-25 20:14:19 -07:00
barnabyrobson
cce7dfcf17 Update SConscript
Fixing copy and pasted comment to say correct thing when program built against Boost.Python can not run.
2012-09-22 20:13:20 -07:00
Jim Bosch
2f7742ffec add more permissive equivalence test for dtypes, start using it in tests 2012-09-18 23:13:29 -04:00
Ilya Kolpakov
46b959cceb ufunc tests now ensure that return value is the same object as the 'output' (if it is provided) argument being the same object as the ufunc return value 2012-09-04 12:10:55 +02:00
Ilya Kolpakov
ca3526c76a ufunc test now uses assert_array_almost_equal instead of bitwise(?) comparison 2012-09-04 11:30:58 +02:00
Jim Bosch
4ec94c676b Add example (wrap.py) to demonstrate how to wrap simple functions that operate on C arrays into functions that operate on NumPy arrays (#6). 2012-05-13 17:51:48 -04:00
Jim Bosch
a35cbd1af1 Switch to use RPATH in test and example builds (#5). 2012-05-13 17:50:15 -04:00
Jim Bosch
28a9fab278 Overhauled how builtin dtype objects are accessed for better consistency, added converters for array scalars. 2012-05-13 13:03:10 -04:00
Jim Bosch
ab2225bcbd Remove unused special handling for bool dtype. 2012-05-12 12:15:32 -04:00
Jim Bosch
dbe4903887 fix LoadableModule suffix on darwin 2012-04-29 12:55:57 -04:00
Jim Bosch
405f99cd3c Fix bug in boost/numpy.hpp install location 2012-04-28 15:47:48 -04:00
Jim Bosch
313dcbb628 added as_matrix call policy 2012-04-21 16:46:28 -04:00
Jim Bosch
dca44829a6 untabify python test files 2012-04-21 16:34:01 -04:00
Jim Bosch
46f6382fe4 Change how external environment variables are propagated to SCons to allow it to find executables in $PATH. 2012-04-21 15:14:29 -04:00
Jim Bosch
99e6194620 more SCons refactoring 2012-04-21 00:50:53 -04:00
Jim Bosch
4c2850cbfd Make CheckLibs available to ndarray SConstruct file. 2012-04-19 23:28:41 -04:00
Jim Bosch
029eb385ed Prepend Boost paths rather than append them; puts explicit paths at a higher priority than paths pulled from distutils (patch from Neal Becker). 2012-04-17 23:03:58 -04:00
Jim Bosch
77b89341d0 Added support for specifying installation directories for headers and libraries separately (modified patch from Neal Becker).
Signed-off-by: Jim Bosch <jbosch@astro.princeton.edu>
2012-04-17 22:53:06 -04:00
Jim Bosch
588027252b Remove unnecessary shared_ptr in class_ for ufuncs (from Neal Becker).
Signed-off-by: Jim Bosch <jbosch@astro.princeton.edu>
2012-04-17 22:01:39 -04:00
Jim Bosch
d61d41a786 allow CCFLAGS to be passed on command line or through construction variable; default is now '-O2 -g' 2012-04-17 10:00:36 -04:00
Jim Bosch
1d3a535e53 switch to using LoadableModule instead of SharedLibrary for test Python modules 2012-04-16 23:58:34 -04:00
Jim Bosch
65dc91f3da add bang lines to Python unit test scripts 2012-04-16 23:50:46 -04:00
Jim Bosch
782ca7bf20 add custom rpath option to SCons builds 2012-04-16 23:43:57 -04:00
Jim Bosch
1a5a3e1701 modifications to SCons build system to be friendlier to ndarray 2012-04-16 00:53:38 -04:00
Jim Bosch
00c61f4767 fix GitHub URL in readme 2012-04-11 20:18:38 -04:00
Jim Bosch
c20af50ae3 added README file 2012-04-11 20:17:18 -04:00
Jim Bosch
38e68fa2ae overhauled scons scripts 2012-03-18 18:57:14 -04:00
Jim Bosch
35a62fea52 added .gitignore 2012-03-18 17:09:13 -04:00
Jim Bosch
b219376e24 fixed header order in gaussian example; Python.h should always come before system headers 2012-03-18 17:05:22 -04:00
Jim Bosch
1e66e33201 removed ublas dependency from gaussian example 2011-11-08 03:45:31 +00:00
Stefan Seefeld
8f909d55ac Refine style. 2011-10-31 22:56:38 +00:00
Stefan Seefeld
05c21bcae1 Refine style. 2011-10-31 22:55:22 +00:00
Stefan Seefeld
0cb3bd7aa5 Add navigation bar. 2011-10-30 22:25:34 +00:00
Stefan Seefeld
7a84a00673 build new 'gaussian.cpp' extension. 2011-10-30 20:54:20 +00:00
Jim Bosch
9d7dfd8449 added gaussian example, updated scons build 2011-10-30 14:43:53 +00:00
Stefan Seefeld
2a8823f745 Fix formatting issues in the Reference Manual. 2011-10-29 20:39:37 +00:00
Stefan Seefeld
beaa4b0e4d Remove implementation details from documentation. 2011-10-29 18:20:25 +00:00
Stefan Seefeld
55c3b0569e Restructure documentation sources to build with sphinx. 2011-10-27 14:12:14 +00:00
Ankit Daftery
2aca81bca9 Added temporary directory for Reference documentation 2011-08-31 12:35:56 +00:00
Jim Bosch
32d2135462 boost/numpy - enabled new unit tests in old SCons build system 2011-08-25 23:32:43 +00:00
Ankit Daftery
7064cf3186 Added tutorial for ufunc 2011-08-17 18:26:20 +00:00
Ankit Daftery
777e16e1d0 Added example for ufunc 2011-08-17 18:25:44 +00:00
Ankit Daftery
715e5cbc31 Added non-unit strides example 2011-08-14 06:49:08 +00:00
Ankit Daftery
67b5b07976 Added non-unit strides example 2011-08-14 06:48:46 +00:00
Ankit Daftery
7b088c9df2 Removed todo 2011-08-13 13:55:03 +00:00
Ankit Daftery
3dda62f8b8 Added tutorial for fromdata, i.e. copy free data access 2011-08-12 09:26:55 +00:00
Ankit Daftery
c33460c265 Made a few modifications 2011-08-12 09:26:22 +00:00
Ankit Daftery
4c12b004ec Added example for data access using pointers 2011-08-12 05:16:20 +00:00
Ankit Daftery
5bed132ff8 Added a line for zeros 2011-08-08 17:05:09 +00:00
Ankit Daftery
3ffcf3335a Added working custom dtype example 2011-08-06 21:13:13 +00:00
Ankit Daftery
c314274a56 Added working custom dtype exampel 2011-08-06 21:12:42 +00:00
Ankit Daftery
437373456f Added example for custom dtype 2011-08-05 17:04:29 +00:00
Ankit Daftery
7add755ae0 Added tutorial for dtype 2011-08-05 09:06:19 +00:00
Ankit Daftery
79182d7189 Added ndarray.rst 2011-08-04 17:47:09 +00:00
Ankit Daftery
36e9e38373 Tutorial for ndarrays 2011-08-04 17:45:00 +00:00
Ankit Daftery
45e52301e9 Added from_data implementation, zeros(..) examples 2011-08-04 17:39:04 +00:00
Ankit Daftery
37a73f344b Modified Jamfile 2011-08-03 20:07:40 +00:00
Ankit Daftery
bbd9aad6e9 New examples 2011-08-03 20:07:20 +00:00
Stefan Seefeld
8fa1f9db9e Add support for ReST docs. 2011-07-19 04:32:25 +00:00
Stefan Seefeld
9c56469358 Add example(s) 2011-07-05 14:20:57 +00:00
Stefan Seefeld
196c9e653f Fix indexing tests. 2011-07-03 20:36:55 +00:00
Stefan Seefeld
c572b4db73 Rename (and move) boost.python.numpy to boost.numpy. 2011-07-03 16:42:15 +00:00
Stefan Seefeld
b2519a25a9 Rename (and move) boost.python.numpy to boost.numpy. 2011-07-03 16:40:30 +00:00
Ankit Daftery
2979e4b062 Added index array and boolean tests 2011-06-30 02:50:40 +00:00
Stefan Seefeld
88dd5330d0 Tidy indexing tests. 2011-06-27 14:07:54 +00:00
Ankit Daftery
fa51b58cd6 Added test for slices with steps. Auto-detection of step not implemented yet 2011-06-27 04:09:12 +00:00
Ankit Daftery
419b6ec973 Added tests for indexing 2011-06-24 12:58:57 +00:00
Ankit Daftery
085f574d6e Added more tests for ndarray 2011-06-20 17:18:43 +00:00
Stefan Seefeld
69d9f34f3e Fix ndarray tests. 2011-06-19 20:16:06 +00:00
Stefan Seefeld
36ee7d23f9 Fix ndarray tests. 2011-06-19 20:08:48 +00:00
Ankit Daftery
b269b4b124 Adding test for ndarray.Fails as of now. 2011-06-19 19:38:51 +00:00
Ankit Daftery
20b68f2a2f Added build rule for shapes 2011-06-14 03:36:59 +00:00
Ankit Daftery
2794a9bd15 Test to check the shape of the ndarray 2011-06-14 03:32:10 +00:00
Stefan Seefeld
0a76801936 Move build system improvements 2011-05-30 20:39:43 +00:00
Stefan Seefeld
daf466a697 Work on numpy configuration 2011-05-30 01:18:16 +00:00
Ankit Daftery
718cfd468e First build of numpy.jam module to check for the location of the numpy build directory 2011-05-29 18:39:06 +00:00
Ankit Daftery
3796825523 Updated to include the numpy.jam module 2011-05-29 18:34:21 +00:00
Ankit Daftery
6904a166f7 Updated to include the numpy.jam module 2011-05-29 18:33:56 +00:00
Ankit Daftery
39b9047190 New addition to support boost.build 2011-05-28 12:53:03 +00:00
Ankit Daftery
930167e961 New addition to support boost.build 2011-05-28 12:52:29 +00:00
Ankit Daftery
64b2c1697b Patch to fix scons issue 2011-05-28 12:47:37 +00:00
Ankit Daftery
f0345b2521 New addition to support boost.build 2011-05-28 12:45:52 +00:00
Jim Bosch
77ec571511 Boost.Python.Numpy - moved convenience header one directory lower 2011-02-16 00:24:22 +00:00
Jim Bosch
70c7fbd1d8 Boost.Python.Numpy - removing malfunctioning variant build directories 2011-01-17 20:01:48 +00:00
Jim Bosch
91a1119070 Boost.Python.Numpy - cleaning up build system 2011-01-15 23:00:43 +00:00
Jim Bosch
a300f7cdd0 boost.python.numpy - updates to build system, added some svn:ignores 2011-01-07 23:39:45 +00:00
Jim Bosch
65db10061f numpy - (build system) fixed setting lib output path in tests 2011-01-06 19:37:28 +00:00
Jim Bosch
3d7f523384 numpy - added missing doxygen builder 2011-01-06 19:30:58 +00:00
Jim Bosch
252c3aa695 numpy - updates to site_scons, header documentation 2011-01-04 19:19:20 +00:00
Jim Bosch
584df88fb2 boost.python.numpy - switched to simpler syntax for invoke_matching_array 2010-10-06 22:40:41 +00:00
Jim Bosch
ba1416fff0 boost.python.numpy - moved dtype::invoke_matching_template into separate header, added similar code for invocation based on dimensionality 2010-10-06 19:05:20 +00:00
Jim Bosch
42ca807c82 boost.python.numpy - fixed missing bool instantiation for dtype::get_builtin 2010-10-06 00:31:09 +00:00
Jim Bosch
b988e8c45f boost.python.numpy - adding missing symbols, fixed constness in dtype 2010-07-25 00:18:18 +00:00
Jim Bosch
c7db44f617 boost.python.numpy - added ndarray::reshape 2010-06-29 07:55:33 +00:00
Jim Bosch
f3aecdf2f4 boost.python.numpy - added dtype template invoker 2010-06-24 22:20:55 +00:00
Jim Bosch
40bd0326f3 boost.python numpy - build system separates debug and standard builds 2010-06-08 01:44:59 +00:00
Jim Bosch
99d3a54ad5 boost.python numpy support - improvements to build system 2010-05-18 06:59:41 +00:00
Jim Bosch
c3d186e0bf boost python numpy extensions - updated source files to reflect previous header move 2010-05-15 03:44:45 +00:00
Jim Bosch
e0fa8ec619 numpy python extensions - moved main header file inside subdirectory 2010-05-14 23:43:38 +00:00
Jim Bosch
e2b2ebe862 numpy python extension - added basic SCons build system, started on unit tests 2010-05-14 22:47:14 +00:00
Jim Bosch
eef2eef7dd initial sandbox import for numpy utilities in boost.python 2010-03-08 21:50:13 +00:00
Jim Bosch
189915bc8b folder for new numpy project: improved boost.python bindings for numpy 2010-03-08 20:12:06 +00:00
268 changed files with 7661 additions and 10332 deletions

View File

@@ -5,11 +5,19 @@ SOURCE_BRANCH="master"
TARGET_BRANCH="gh-pages"
# Pull requests and commits to other branches shouldn't try to deploy, just build to verify
if [ "$TRAVIS_PULL_REQUEST" != "false" ] || [ "$TRAVIS_BRANCH" != master -a "$TRAVIS_BRANCH" != develop ]; then
if [ "$TRAVIS_PULL_REQUEST" != "false" ] || \
[ "$TRAVIS_BRANCH" != master -a \
"$TRAVIS_BRANCH" != develop -a \
"$TRAVIS_BRANCH" != travis ]; then
echo "No docs to upload."
exit 0
fi
if [ -z "$GH_TOKEN" ]; then
echo "Error: GH_TOKEN is undefined"
exit 1
fi
# Save some useful information
REPO=`git config remote.origin.url`
SHA=`git rev-parse --verify HEAD`
@@ -20,19 +28,30 @@ SHA=`git rev-parse --verify HEAD`
cd bin.SCons
git init
git config user.name "Travis CI"
git config user.email "$COMMIT_AUTHOR_EMAIL"
git config user.email "travis-ci"
# Make sure 'GH_TOKEN' is set (as 'secure' variable) in .travis.yml
git remote add upstream "https://$GH_TOKEN@github.com/boostorg/python.git"
git fetch upstream
git reset upstream/gh-pages
# Prepare version.
if [ "$TRAVIS_BRANCH" = develop -o "$TRAVIS_BRANCH" = travis ]; then
mkdir -p develop/doc/
cp ../index.html develop/
cp ../doc/index.html develop/doc/
cp -a doc/html develop/doc/
git add develop/index.html
git add develop/doc/index.html
git add -A develop/doc/html
else
cp ../index.html .
cp ../doc/index.html doc/
git add index.html
git add doc/index.html
git add -A doc/html
fi
# Commit the new version.
cp ../index.html .
cp ../doc/index.html doc/
git add index.html
git add doc/index.html
git add -A doc/html
git commit -m "Deploy to GitHub Pages: ${SHA}"
# Now that we're all set up, we can push.

4
.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
bin.SCons
*.pyc
*~
\#*\#

View File

@@ -11,23 +11,28 @@ dist: trusty
language: cpp
env:
global:
- secure: BRNUkxN3p8f+uYKWC3Hr0VPqZA0PxbWr1DJlcI4hbiZtzKhMCWjDmd9UW9CzzexqeOxpd+9s0G87qvOur+wMSVxugDxtTesZrh1czXHeSVxgQrYD783XJtQJ9aYypbChkiboRD6Xpmbq7itwMuHBJMFtCuDxMynpU1jWwkyTf2Y=
matrix:
include:
- compiler: gcc
env: CXX=g++ PYTHON=python CXXFLAGS=-std=c++98
- compiler: gcc
env: CXX=g++ PYTHON=python CXXFLAGS=-std=c++11
- compiler: gcc
env: CXX=g++ PYTHON=python3 CXXFLAGS=-std=c++98
- compiler: gcc
env: CXX=g++ PYTHON=python3 CXXFLAGS=-std=c++11
- compiler: clang
env: CXX=clang++ PYTHON=python3 CXXFLAGS=-std=c++98
- compiler: clang
env: CXX=clang++ PYTHON=python3 CXXFLAGS=-std=c++11
- env: PYTHON=python DOC=1
global:
- secure: mqoxglbUN/At/r8O7nLVccGldnB1jvhLHNyYjfCXrdOD0GNX+TY2TS1+kIEv9Deg/P6X/QvrBa/ZzbDNryn3mDXBfOSy400ebSIUHHP3HtGHJShOGDyXedY3hZ/dqmxdV3p9hIxv4lcx1HPyC96s4wpiR0S9F1JBzD6scIabezM=
- compiler: gcc
env: CXX=g++ PYTHON=python CXXFLAGS=-std=c++98
- compiler: gcc
env: CXX=g++ PYTHON=python CXXFLAGS=-std=c++11
- compiler: gcc
env: CXX=g++ PYTHON=python3 CXXFLAGS=-std=c++98
- compiler: gcc
env: CXX=g++ PYTHON=python3 CXXFLAGS=-std=c++11
- compiler: clang
# 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 OPTIONS=--no-numpy
- env: PYTHON=python DOC=1
addons:
apt:
@@ -38,28 +43,57 @@ 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
- python-docutils
cache:
directories:
- $HOME/Boost
before_install:
# The Trusty image has several Python versions pre-installed compiled with
# 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
# The Trusty image has several Python versions pre-installed compiled with
# 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")
install:
# Install our own version of Boost (the subset we need) as the system version is
# too old (for C++11 support).
- rm -rf $HOME/Boost
- |
set -e
if [ ! -d $HOME/Boost ]; then
echo "rebuilding Boost prerequisites"
wget https://sourceforge.net/projects/boost/files/boost/1.61.0/boost_1_61_0.tar.gz/download
tar xf download
pushd boost_1_61_0
./bootstrap.sh
./b2 tools/bcp
mkdir -p $HOME/Boost
dist/bin/bcp python tools/boostbook tools/quickbook $HOME/Boost &> /dev/null
popd
fi
before_script:
- scons --version
script:
- scons config --python=$PYTHON
- scons config --python=$PYTHON --boost-include=$HOME/Boost $OPTIONS
- if [ "$DOC" ]; then scons doc; else scons && scons test; fi
after_success:
# Upload docs only when building upstream.
- if [ "$DOC" -a "$TRAVIS_REPO_SLUG" = "boostorg/python" -a "$TRAVIS_PULL_REQUEST" = "false" ]; then .ci/upload_docs.sh; fi
- |
if [ "$DOC" -a \
"$TRAVIS_REPO_SLUG" = "boostorg/python" -a \
"$TRAVIS_PULL_REQUEST" = "false" ]; then
export GH_TOKEN
.ci/upload_docs.sh
fi

23
LICENSE_1_0.txt Normal file
View File

@@ -0,0 +1,23 @@
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

View File

@@ -17,6 +17,8 @@ Welcome to Boost.Python, a C++ library which enables seamless interoperability b
See the [Boost.Python](http://boostorg.github.io/python) documentation for details.
**Hint :** Check out the [development version](http://boostorg.github.io/python/develop) of the documentation to see work in progress.
# Building ![Build Status](https://travis-ci.org/boostorg/python.svg?branch=develop)
While Boost.Python is part of the Boost C++ Libraries super-project, and thus can be compiled as part of Boost, it can also be compiled and installed stand-alone, i.e. against a pre-installed Boost package.
@@ -65,4 +67,4 @@ Run
```
scons doc
```
to build the documentation.
to build the documentation.

View File

@@ -1,34 +0,0 @@
# -*- python -*-
Import("env")
env.Append(CPPPATH = "#/include",CPPDEFINES = ["BOOST_ALL_NO_LIB=1"])
env.AppendUnique(CPPDEFINES = ["${LINK_DYNAMIC and 'BOOST_PYTHON_DYN_LINK=1' or []}"])
for variant in env["variant"]:
env["current_variant"] = variant
env.SetProperty(profile = False)
if variant == "release":
env.SetProperty(optimize = "speed", debug = False)
elif variant == "debug":
env.SetProperty(optimize = "no", debug = True)
elif variant == "profile":
env.SetProperty(optimize = "speed", profile = True, debug = True)
for linking in env["link"]:
env["linking"] = linking
if linking == "dynamic":
env["LINK_DYNAMIC"] = True
else:
env["LINK_DYNAMIC"] = False
for threading in env["threading"]:
env["current_threading"] = threading
env.SetProperty(threading = threading)
variant_dir=env.subst("$BOOST_CURRENT_VARIANT_DIR")
env.SConscript("src/SConscript", variant_dir=variant_dir + '/src',
exports = { "env" : env.Clone(BOOST_LIB = 'python') })
if GetOption("test"):
test_env = env.Clone(BOOST_LIB = 'python', BOOST_TEST = True)
test_env.BoostUseLib('python')
env.SConscript("test/SConscript", variant_dir=variant_dir + '/test',
exports = { "env" : test_env })

View File

@@ -39,8 +39,9 @@ arch = ARGUMENTS.get('arch', platform.machine())
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_vars['ENV'] = os.environ #{'PATH': os.environ['PATH'], 'TMP' : os.environ['TMP']}
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 +69,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

@@ -69,13 +69,15 @@ install:
# pip will build them from source using the MSVC compiler matching the
# target Python version and architecture
- easy_install scons
- easy_install sphinx
- pip install numpy
#- "%CMD_IN_ENV% pip install -r dev-requirements.txt"
build_script:
# Build the compiled extension
#- "%CMD_IN_ENV% python setup.py build"
- scons config arch=%ARCH% --boost-include=%BOOST_PREFIX%
- scons arch=%ARCH%
- scons arch=%ARCH% --verbose
test_script:
# Run the project tests

View File

@@ -6,6 +6,7 @@ import os ;
import indirect ;
import modules ;
import feature ;
import property ;
import python ;
@@ -30,52 +31,26 @@ else
;
}
rule find-py3-version
{
local versions = [ feature.values python ] ;
local py3ver ;
for local v in $(versions)
{
if $(v) >= 3.0
{
py3ver = $(v) ;
}
}
return $(py3ver) ;
}
py3-version = [ find-py3-version ] ;
py2-version = [ py-version 2 ] ;
py3-version = [ py-version 3 ] ;
project boost/python
: source-location ../src
: requirements
-<tag>@$(BOOST_JAMROOT_MODULE)%$(BOOST_JAMROOT_MODULE).tag
<tag>@$(__name__).tag
;
rule tag ( name : type ? : property-set )
{
local result = $(name) ;
if $(type) in STATIC_LIB SHARED_LIB IMPORT_LIB
{
if $(name) = boost_python && $(PYTHON_ID)
{
result = $(result)-$(PYTHON_ID) ;
}
}
# forward to the boost tagging rule
return [ indirect.call $(BOOST_JAMROOT_MODULE)%$(BOOST_JAMROOT_MODULE).tag
$(result) : $(type) : $(property-set) ] ;
}
rule cond ( test ? : yes * : no * ) { if $(test) { return $(yes) ; } else { return $(no) ; } }
rule unless ( test ? : yes * : no * ) { if ! $(test) { return $(yes) ; } else { return $(no) ; } }
local rule eq ( a : b ) { if $(a) = $(b) { return 1 ; } }
rule lib_boost_python ( is-py3 ? )
lib_boost_python(2) = boost_python ;
lib_boost_python(3) = boost_python3 ;
lib_boost_python($(py2-version)) = $(lib_boost_python(2)) ;
lib_boost_python($(py3-version)) = $(lib_boost_python(3)) ;
rule lib_boost_python ( version )
{
lib [ cond $(is-py3) : boost_python3 : boost_python ]
lib $(lib_boost_python($(version)))
: # sources
numeric.cpp
list.cpp
@@ -131,21 +106,83 @@ rule lib_boost_python ( is-py3 ? )
<dependency>config-warning
<python-debugging>on:<define>BOOST_DEBUG_PYTHON
[ cond $(is-py3) : <python>$(py3-version) ]
<python>$(version)
-<tag>@$(BOOST_JAMROOT_MODULE)%$(BOOST_JAMROOT_MODULE).tag
<tag>@$(BOOST_JAMROOT_MODULE)%$(BOOST_JAMROOT_MODULE).python-tag
<conditional>@python.require-py
: # default build
<link>shared
: # usage requirements
<link>static:<define>BOOST_PYTHON_STATIC_LIB
<python-debugging>on:<define>BOOST_DEBUG_PYTHON
;
}
lib_boost_python ;
boost-install boost_python ;
lib_boost_numpy(2) = boost_numpy ;
lib_boost_numpy(3) = boost_numpy3 ;
if $(py3-version)
lib_boost_numpy($(py2-version)) = $(lib_boost_numpy(2)) ;
lib_boost_numpy($(py3-version)) = $(lib_boost_numpy(3)) ;
rule lib_boost_numpy ( version )
{
lib_boost_python yes ;
boost-install boost_python3 ;
numpy-include = [ python.numpy-include ] ;
lib $(lib_boost_numpy($(version)))
: # sources
numpy/dtype.cpp
numpy/matrix.cpp
numpy/ndarray.cpp
numpy/numpy.cpp
numpy/scalars.cpp
numpy/ufunc.cpp
: # requirements
<link>static:<define>BOOST_NUMPY_STATIC_LIB
<define>BOOST_NUMPY_SOURCE
[ cond [ python.numpy ] : <library>/python//python_for_extensions ]
[ unless [ python.numpy ] : <build>no ]
<include>$(numpy-include)
<library>$(lib_boost_python($(version)))
<python-debugging>on:<define>BOOST_DEBUG_PYTHON
<python>$(version)
-<tag>@$(BOOST_JAMROOT_MODULE)%$(BOOST_JAMROOT_MODULE).tag
<tag>@$(BOOST_JAMROOT_MODULE)%$(BOOST_JAMROOT_MODULE).python-tag
<conditional>@python.require-py
: # default build
<link>shared
: # usage requirements
<link>static:<define>BOOST_NUMPY_STATIC_LIB
<python-debugging>on:<define>BOOST_DEBUG_PYTHON
;
}
libraries = ;
for local N in 2 3
{
if $(py$(N)-version)
{
lib_boost_python $(py$(N)-version) ;
libraries += $(lib_boost_python($(py$(N)-version))) ;
}
else
{
alias $(lib_boost_python($(N))) ;
}
if $(py$(N)-version) && [ python.numpy ]
{
lib_boost_numpy $(py$(N)-version) ;
libraries += $(lib_boost_numpy($(py$(N)-version))) ;
}
else
{
alias $(lib_boost_numpy($(N))) ;
}
}
boost-install $(libraries) ;

Binary file not shown.

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

@@ -4,10 +4,14 @@
# 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)
import boostbook ;
import quickbook ;
import docutils ;
import os ;
path-constant here : . ;
path-constant images : html/images ;
project python/doc
: requirements
-<xsl:param>boost.defaults=Boost
@@ -17,9 +21,16 @@ project python/doc
<format>html:<xsl:param>chunk.section.depth=1
;
import boostbook ;
import quickbook ;
import docutils ;
make numpy : numpy/index.rst : @sphinx-build ;
if [ os.name ] = NT
{
actions sphinx-build { chdir "$(>:D)" && make clean && make html}
}
else
{
actions sphinx-build { make -C "$(>:D)" clean html}
}
boostbook python : python.qbk
: <format>html:<name>$(here)/html
@@ -47,3 +58,9 @@ html article : article.rst
: <location>html
<docutils-html>"--link-stylesheet --traceback --trim-footnote-reference-space --footnote-references=superscript --stylesheet=rst.css"
;
###############################################################################
alias boostdoc ;
explicit boostdoc ;
alias boostrelease : python tutorial reference numpy article ;
explicit boostrelease ;

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/')

133
doc/numpy/Makefile Normal file
View File

@@ -0,0 +1,133 @@
# Makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
PAPER =
BUILDDIR = _build
HTMLDIR = ../html/numpy
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest
all: html
help:
@echo "Please use \`make <target>' where <target> is one of"
@echo " html to make standalone HTML files"
@echo " dirhtml to make HTML files named index.html in directories"
@echo " singlehtml to make a single large HTML file"
@echo " pickle to make pickle files"
@echo " json to make JSON files"
@echo " htmlhelp to make HTML files and a HTML help project"
@echo " qthelp to make HTML files and a qthelp project"
@echo " devhelp to make HTML files and a Devhelp project"
@echo " epub to make an epub"
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@echo " latexpdf to make LaTeX files and run them through pdflatex"
@echo " text to make text files"
@echo " man to make manual pages"
@echo " changes to make an overview of all changed/added/deprecated items"
@echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
clean:
-rm -rf $(BUILDDIR)/*
html:
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(HTMLDIR)
@echo
@echo "Build finished. The HTML pages are in $(HTMLDIR)."
dirhtml:
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
singlehtml:
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
@echo
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
pickle:
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
@echo
@echo "Build finished; now you can process the pickle files."
json:
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
@echo
@echo "Build finished; now you can process the JSON files."
htmlhelp:
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
@echo
@echo "Build finished; now you can run HTML Help Workshop with the" \
".hhp project file in $(BUILDDIR)/htmlhelp."
qthelp:
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
@echo
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/BoostNumPy.qhcp"
@echo "To view the help file:"
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/BoostNumPy.qhc"
devhelp:
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
@echo
@echo "Build finished."
@echo "To view the help file:"
@echo "# mkdir -p $$HOME/.local/share/devhelp/BoostNumPy"
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/BoostNumPy"
@echo "# devhelp"
epub:
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
@echo
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
latex:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
@echo "Run \`make' in that directory to run these through (pdf)latex" \
"(use \`make latexpdf' here to do that automatically)."
latexpdf:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through pdflatex..."
make -C $(BUILDDIR)/latex all-pdf
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
text:
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
@echo
@echo "Build finished. The text files are in $(BUILDDIR)/text."
man:
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
@echo
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
changes:
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
@echo
@echo "The overview file is in $(BUILDDIR)/changes."
linkcheck:
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
@echo
@echo "Link check complete; look for any errors in the above output " \
"or in $(BUILDDIR)/linkcheck/output.txt."
doctest:
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
@echo "Testing of doctests in the sources finished, look at the " \
"results in $(BUILDDIR)/doctest/output.txt."

716
doc/numpy/_static/boost.css Normal file
View File

@@ -0,0 +1,716 @@
/*=============================================================================
Copyright (c) 2004 Joel de Guzman
http://spirit.sourceforge.net/
Copyright 2013 Niall Douglas additions for colors and alignment.
Copyright 2013 Paul A. Bristow additions for more colors and alignments.
Distributed under the Boost Software License, Version 1.0. (See accompany-
ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/
/*=============================================================================
Body defaults
=============================================================================*/
body
{
margin: 1em;
font-family: sans-serif;
}
/*=============================================================================
Paragraphs
=============================================================================*/
p
{
text-align: left;
font-size: 10pt;
line-height: 1.15;
}
/*=============================================================================
Program listings
=============================================================================*/
/* Code on paragraphs */
p tt.computeroutput
{
font-size: 9pt;
}
pre.synopsis
{
font-size: 9pt;
margin: 1pc 4% 0pc 4%;
padding: 0.5pc 0.5pc 0.5pc 0.5pc;
}
.programlisting,
.screen
{
font-size: 9pt;
display: block;
margin: 1pc 4% 0pc 4%;
padding: 0.5pc 0.5pc 0.5pc 0.5pc;
}
/* Program listings in tables don't get borders */
td .programlisting,
td .screen
{
margin: 0pc 0pc 0pc 0pc;
padding: 0pc 0pc 0pc 0pc;
}
/*=============================================================================
Headings
=============================================================================*/
h1, h2, h3, h4, h5, h6
{
text-align: left;
margin: 1em 0em 0.5em 0em;
font-weight: bold;
}
h1 { font-size: 140%; }
h2 { font-weight: bold; font-size: 140%; }
h3 { font-weight: bold; font-size: 130%; }
h4 { font-weight: bold; font-size: 120%; }
h5 { font-weight: normal; font-style: italic; font-size: 110%; }
h6 { font-weight: normal; font-style: italic; font-size: 100%; }
/* Top page titles */
title,
h1.title,
h2.title
h3.title,
h4.title,
h5.title,
h6.title,
.refentrytitle
{
font-weight: bold;
margin-bottom: 1pc;
}
h1.title { font-size: 140% }
h2.title { font-size: 140% }
h3.title { font-size: 130% }
h4.title { font-size: 120% }
h5.title { font-size: 110% }
h6.title { font-size: 100% }
.section h1
{
margin: 0em 0em 0.5em 0em;
font-size: 140%;
}
.section h2 { font-size: 140% }
.section h3 { font-size: 130% }
.section h4 { font-size: 120% }
.section h5 { font-size: 110% }
.section h6 { font-size: 100% }
/* Code on titles */
h1 tt.computeroutput { font-size: 140% }
h2 tt.computeroutput { font-size: 140% }
h3 tt.computeroutput { font-size: 130% }
h4 tt.computeroutput { font-size: 130% }
h5 tt.computeroutput { font-size: 130% }
h6 tt.computeroutput { font-size: 130% }
/*=============================================================================
Author
=============================================================================*/
h3.author
{
font-size: 100%
}
/*=============================================================================
Lists
=============================================================================*/
li
{
font-size: 10pt;
line-height: 1.3;
}
/* Unordered lists */
ul
{
text-align: left;
}
/* Ordered lists */
ol
{
text-align: left;
}
/*=============================================================================
Links
=============================================================================*/
a
{
text-decoration: none; /* no underline */
}
a:hover
{
text-decoration: underline;
}
/*=============================================================================
Spirit style navigation
=============================================================================*/
.spirit-nav
{
text-align: right;
}
.spirit-nav a
{
color: white;
padding-left: 0.5em;
}
.spirit-nav img
{
border-width: 0px;
}
/*=============================================================================
Copyright footer
=============================================================================*/
.copyright-footer
{
text-align: right;
font-size: 70%;
}
.copyright-footer p
{
text-align: right;
font-size: 80%;
}
/*=============================================================================
Table of contents
=============================================================================*/
div.toc
{
margin: 1pc 4% 0pc 4%;
padding: 0.1pc 1pc 0.1pc 1pc;
font-size: 80%;
line-height: 1.15;
}
.boost-toc
{
float: right;
padding: 0.5pc;
}
/* Code on toc */
.toc .computeroutput { font-size: 120% }
/* No margin on nested menus */
.toc dl dl { margin: 0; }
/*=============================================================================
Tables
=============================================================================*/
.table-title,
div.table p.title
{
margin-left: 4%;
padding-right: 0.5em;
padding-left: 0.5em;
}
.informaltable table,
.table table
{
width: 92%;
margin-left: 4%;
margin-right: 4%;
}
div.informaltable table,
div.table table
{
padding: 4px;
}
/* Table Cells */
div.informaltable table tr td,
div.table table tr td
{
padding: 0.5em;
text-align: left;
font-size: 9pt;
}
div.informaltable table tr th,
div.table table tr th
{
padding: 0.5em 0.5em 0.5em 0.5em;
border: 1pt solid white;
font-size: 80%;
}
table.simplelist
{
width: auto !important;
margin: 0em !important;
padding: 0em !important;
border: none !important;
}
table.simplelist td
{
margin: 0em !important;
padding: 0em !important;
text-align: left !important;
font-size: 9pt !important;
border: none !important;
}
/*=============================================================================
Suppress margins in tables
=============================================================================*/
table th > *:first-child,
table td > *:first-child
{
margin-top: 0;
}
table th > *:last-child,
table td > *:last-child
{
margin-bottom: 0;
}
/*=============================================================================
Blurbs
=============================================================================*/
div.note,
div.tip,
div.important,
div.caution,
div.warning,
p.blurb
{
font-size: 9pt; /* A little bit smaller than the main text */
line-height: 1.2;
display: block;
margin: 1pc 4% 0pc 4%;
padding: 0.5pc 0.5pc 0.5pc 0.5pc;
}
p.blurb img
{
padding: 1pt;
}
/*=============================================================================
Variable Lists
=============================================================================*/
div.variablelist
{
margin: 1em 0;
}
/* Make the terms in definition lists bold */
div.variablelist dl dt,
span.term
{
font-weight: bold;
font-size: 10pt;
}
div.variablelist table tbody tr td
{
text-align: left;
vertical-align: top;
padding: 0em 2em 0em 0em;
font-size: 10pt;
margin: 0em 0em 0.5em 0em;
line-height: 1;
}
div.variablelist dl dt
{
margin-bottom: 0.2em;
}
div.variablelist dl dd
{
margin: 0em 0em 0.5em 2em;
font-size: 10pt;
}
div.variablelist table tbody tr td p,
div.variablelist dl dd p
{
margin: 0em 0em 0.5em 0em;
line-height: 1;
}
/*=============================================================================
Misc
=============================================================================*/
/* Title of books and articles in bibliographies */
span.title
{
font-style: italic;
}
span.underline
{
text-decoration: underline;
}
span.strikethrough
{
text-decoration: line-through;
}
/* Copyright, Legal Notice */
div div.legalnotice p
{
text-align: left
}
/*=============================================================================
Colors
=============================================================================*/
@media screen
{
body {
background-color: #FFFFFF;
color: #000000;
}
/* Syntax Highlighting */
.keyword { color: #0000AA; }
.identifier { color: #000000; }
.special { color: #707070; }
.preprocessor { color: #402080; }
.char { color: teal; }
.comment { color: #800000; }
.string { color: teal; }
.number { color: teal; }
.white_bkd { background-color: #FFFFFF; }
.dk_grey_bkd { background-color: #999999; }
/* Links */
a, a .keyword, a .identifier, a .special, a .preprocessor
a .char, a .comment, a .string, a .number
{
color: #005a9c;
}
a:visited, a:visited .keyword, a:visited .identifier,
a:visited .special, a:visited .preprocessor a:visited .char,
a:visited .comment, a:visited .string, a:visited .number
{
color: #9c5a9c;
}
h1 a, h2 a, h3 a, h4 a, h5 a, h6 a,
h1 a:hover, h2 a:hover, h3 a:hover, h4 a:hover, h5 a:hover, h6 a:hover,
h1 a:visited, h2 a:visited, h3 a:visited, h4 a:visited, h5 a:visited, h6 a:visited
{
text-decoration: none; /* no underline */
color: #000000;
}
/* Copyright, Legal Notice */
.copyright
{
color: #666666;
font-size: small;
}
div div.legalnotice p
{
color: #666666;
}
/* Program listing */
pre.synopsis
{
border: 1px solid #DCDCDC;
}
.programlisting,
.screen
{
border: 1px solid #DCDCDC;
}
td .programlisting,
td .screen
{
border: 0px solid #DCDCDC;
}
/* Blurbs */
div.note,
div.tip,
div.important,
div.caution,
div.warning,
p.blurb
{
border: 1px solid #DCDCDC;
}
/* Table of contents */
div.toc
{
border: 1px solid #DCDCDC;
}
/* Tables */
div.informaltable table tr td,
div.table table tr td
{
border: 1px solid #DCDCDC;
}
div.informaltable table tr th,
div.table table tr th
{
background-color: #F0F0F0;
border: 1px solid #DCDCDC;
}
.copyright-footer
{
color: #8F8F8F;
}
/* Misc */
span.highlight
{
color: #00A000;
}
}
@media print
{
/* Links */
a
{
color: black;
}
a:visited
{
color: black;
}
.spirit-nav
{
display: none;
}
/* Program listing */
pre.synopsis
{
border: 1px solid gray;
}
.programlisting,
.screen
{
border: 1px solid gray;
}
td .programlisting,
td .screen
{
border: 0px solid #DCDCDC;
}
/* Table of contents */
div.toc
{
border: 1px solid gray;
}
.informaltable table,
.table table
{
border: 1px solid gray;
border-collapse: collapse;
}
/* Tables */
div.informaltable table tr td,
div.table table tr td
{
border: 1px solid gray;
}
div.informaltable table tr th,
div.table table tr th
{
border: 1px solid gray;
}
table.simplelist tr td
{
border: none !important;
}
/* Misc */
span.highlight
{
font-weight: bold;
}
}
/*=============================================================================
Images
=============================================================================*/
span.inlinemediaobject img
{
vertical-align: middle;
}
/*==============================================================================
Super and Subscript: style so that line spacing isn't effected, see
http://www.adobe.com/cfusion/communityengine/index.cfm?event=showdetails&productId=1&postId=5341
==============================================================================*/
sup,
sub {
height: 0;
line-height: 1;
vertical-align: baseline;
position: relative;
}
/* For internet explorer: */
* html sup,
* html sub {
vertical-align: bottom;
}
sup {
bottom: 1ex;
}
sub {
top: .5ex;
}
/*==============================================================================
Indexes: pretty much the same as the TOC.
==============================================================================*/
.index
{
font-size: 80%;
padding-top: 0px;
padding-bottom: 0px;
margin-top: 0px;
margin-bottom: 0px;
margin-left: 0px;
}
.index ul
{
padding-left: 3em;
}
.index p
{
padding: 2px;
margin: 2px;
}
.index-entry-level-0
{
font-weight: bold;
}
.index em
{
font-weight: bold;
}
/*==============================================================================
Alignment and coloring use 'role' feature, available from Quickbook 1.6 up.
Added from Niall Douglas for role color and alignment.
http://article.gmane.org/gmane.comp.lib.boost.devel/243318
*/
/* Add text alignment (see http://www.w3schools.com/cssref/pr_text_text-align.asp) */
span.aligncenter
{
display: inline-block; width: 100%; text-align: center;
}
span.alignright
{
display: inline-block; width: 100%; text-align: right;
}
/* alignleft is the default. */
span.alignleft
{
display: inline-block; width: 100%; text-align: left;
}
/* alignjustify stretches the word spacing so that each line has equal width
within a chosen fraction of page width (here arbitrarily 20%).
*Not* useful inside table items as the column width remains the total string width.
Nor very useful, except to temporarily restrict the width.
*/
span.alignjustify
{
display: inline-block; width: 20%; text-align: justify;
}
/* Text colors.
Names at http://www.w3.org/TR/2002/WD-css3-color-20020219/ 4.3. X11 color keywords.
Quickbook Usage: [role red Some red text]
*/
span.red { inline-block; color: red; }
span.green { color: green; }
span.lime { color: #00FF00; }
span.blue { color: blue; }
span.navy { color: navy; }
span.yellow { color: yellow; }
span.magenta { color: magenta; }
span.indigo { color: #4B0082; }
span.cyan { color: cyan; }
span.purple { color: purple; }
span.gold { color: gold; }
span.silver { color: silver; } /* lighter gray */
span.gray { color: #808080; } /* light gray */

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 358 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 336 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 334 B

View File

@@ -0,0 +1,38 @@
@import url(boost.css);
.header h1 a
{
color: #00507f;
font-size: 200%;
font-style: italic;
}
.header h3 { margin: 1px;}
#contents
{
/* border-bottom: solid thin black;*/
}
.highlight
{
border: 1px solid #dcdcdc;
background-color: inherit;
padding: 0 1em;
margin: 0 5em;
}
#searchbox
{
float: right;
width: auto;
margin: 0 2em;
}
.admonition-title { font-weight: bold;}
.toctree-wrapper
{
border: 1px solid #dcdcdc;
padding: 1em;
margin: 0 2em;
}
.toctree-wrapper .caption,
.toctree-wrapper .topic-title { font-weight: bold;}

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 370 B

View File

@@ -0,0 +1,120 @@
{%- macro navbar() %}
<div class="navbar" style="text-align:right;">
{#%- if parents|count > 0 %#}
{#{ parents[1].title }#}
{%- if prev %}
<a class="prev" title="{{ prev.title|striptags|e }}" href="{{ prev.link|e }}"><img src="{{ pathto('_static/prev.png', 1) }}" alt="prev"/></a>
{%- endif %}
{%- if parents %}
<a class="up" title="{{ parents[-1].title|striptags|e }}" href="{{ parents[-1].link|e }}"><img src="{{ pathto('_static/up.png', 1) }}" alt="up"/></a>
{%- endif %}
{%- if next %}
<a class="next" title="{{ next.title|striptags|e }}" href="{{ next.link|e }}"><img src="{{ pathto('_static/next.png', 1) }}" alt="next"/></a>
{%- endif %}
{#%- endif %#}
</div>
{%- endmacro %}
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
{{ metatags }}
{%- if builder != 'htmlhelp' %}
{%- set titlesuffix = docstitle|e %}
{%- set titlesuffix = " - " + titlesuffix %}
{%- endif %}
<title>{{ title|striptags }}{{ titlesuffix }}</title>
{%- if builder == 'web' %}
<link rel="stylesheet" href="{{ pathto('index') }}?do=stylesheet{%
if in_admin_panel %}&admin=yes{% endif %}" type="text/css" />
{%- for link, type, title in page_links %}
<link rel="alternate" type="{{ type|e(true) }}" title="{{ title|e(true) }}" href="{{ link|e(true) }}" />
{%- endfor %}
{%- else %}
<link rel="stylesheet" href="{{ pathto('_static/pygments.css', 1) }}" type="text/css" />
<link rel="stylesheet" href="{{ pathto('_static/style.css', 1) }}" type="text/css" />
{%- endif %}
{%- if builder != 'htmlhelp' %}
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '{{ pathto("", 1) }}',
VERSION: '{{ release|e }}',
COLLAPSE_MODINDEX: false,
FILE_SUFFIX: '{{ file_suffix }}'
};
</script>
{%- for scriptfile in script_files %}
<script type="text/javascript" src="{{ pathto(scriptfile, 1) }}"></script>
{%- endfor %}
{%- if use_opensearch %}
<link rel="search" type="application/opensearchdescription+xml"
title="{% trans docstitle=docstitle|e %}Search within {{ docstitle }}{% endtrans %}"
href="{{ pathto('_static/opensearch.xml', 1) }}"/>
{%- endif %}
{%- if favicon %}
<link rel="shortcut icon" href="{{ pathto('_static/' + favicon, 1) }}"/>
{%- endif %}
{%- endif %}
{%- block linktags %}
{%- if hasdoc('about') %}
<link rel="author" title="{{ _('About these documents') }}" href="{{ pathto('about') }}" />
{%- endif %}
<link rel="index" title="{{ _('Index') }}" href="{{ pathto('genindex') }}" />
<link rel="search" title="{{ _('Search') }}" href="{{ pathto('search') }}" />
{%- if hasdoc('copyright') %}
<link rel="copyright" title="{{ _('Copyright') }}" href="{{ pathto('copyright') }}" />
{%- endif %}
<link rel="top" title="{{ docstitle|e }}" href="{{ pathto('index') }}" />
{%- if parents %}
<link rel="up" title="{{ parents[-1].title|striptags }}" href="{{ parents[-1].link|e }}" />
{%- endif %}
{%- if next %}
<link rel="next" title="{{ next.title|striptags }}" href="{{ next.link|e }}" />
{%- endif %}
{%- if prev %}
<link rel="prev" title="{{ prev.title|striptags }}" href="{{ prev.link|e }}" />
{%- endif %}
{%- endblock %}
{%- block extrahead %} {% endblock %}
</head>
<body>
<div class="header">
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
"header">
<tr>
<td valign="top" width="300">
<h3><a href="{{ pathto('index') }}"><img
alt="C++ Boost" src="{{ pathto('_static/' + logo, 1) }}" border="0"></a></h3>
</td>
<td >
<h1 align="center"><a href="{{ pathto('index') }}">(NumPy)</a></h1>
<!-- <h2 align="center">CallPolicies Concept</h2>-->
</td>
<td>
{%- if pagename != "search" %}
<div id="searchbox" style="display: none">
<form class="search" action="{{ pathto('search') }}" method="get">
<input type="text" name="q" size="18" />
<input type="submit" value="{{ _('Search') }}" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
{%- endif %}
</td>
</tr>
</table>
</div>
<hr/>
<div class="content">
{%- block top_navbar %}{{ navbar() }}{% endblock %}
{% block body %} {% endblock %}
{%- block bottom_navbar %}{{ navbar() }}{% endblock %}
</div>
</body>
</html>

219
doc/numpy/conf.py Normal file
View File

@@ -0,0 +1,219 @@
# -*- coding: utf-8 -*-
#
# 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.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
import sys, os
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#sys.path.insert(0, os.path.abspath('.'))
# -- General configuration -----------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = []
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The suffix of source filenames.
source_suffix = '.rst'
# The encoding of source files.
#source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = u'Boost.Python NumPy extension'
copyright = u'2011, Stefan Seefeld'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = '1.0'
# The full version, including alpha/beta/rc tags.
release = '1.0'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = ['_build']
# The reST default role (used for this markup: `text`) to use for all documents.
#default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'default'
highlight_language = 'c++'
# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []
# -- Options for HTML output ---------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
html_theme = 'default'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = []
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
#html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
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
# pixels large.
#html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}
# If false, no module index is generated.
#html_domain_indices = True
# If false, no index is generated.
html_use_index = True
# If true, the index is split into individual pages for each letter.
#html_split_index = False
# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
#html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = None
# Output file base name for HTML help builder.
htmlhelp_basename = 'BoostPythonNumPydoc'
html_add_permalinks = False
# -- Options for LaTeX output --------------------------------------------------
# The paper size ('letter' or 'a4').
#latex_paper_size = 'letter'
# The font size ('10pt', '11pt' or '12pt').
#latex_font_size = '10pt'
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents = [
('index', 'BoostPythonNumPy.tex', u'Boost.Python NumPy Documentation',
u'Stefan Seefeld', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False
# If true, show page references after internal links.
#latex_show_pagerefs = False
# If true, show URL addresses after external links.
#latex_show_urls = False
# Additional stuff for the LaTeX preamble.
#latex_preamble = ''
# Documents to append as an appendix to all manuals.
#latex_appendices = []
# If false, no module index is generated.
#latex_domain_indices = True
# -- Options for manual page output --------------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
('index', 'boostnumpy', u'Boost.Python NumPy Documentation',
[u'Stefan Seefeld'], 1)
]

14
doc/numpy/index.rst Normal file
View File

@@ -0,0 +1,14 @@
.. 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 the documentation of the Boost.Python NumPy extension!
=================================================================
.. toctree::
:maxdepth: 2
Tutorial <tutorial/index>
Reference <reference/index>

171
doc/numpy/make.bat Normal file
View File

@@ -0,0 +1,171 @@
@ECHO OFF
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set BUILDDIR=_build
set HTMLDIR=../html/numpy
set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
if NOT "%PAPER%" == "" (
set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
)
if "%1" == "" goto help
if "%1" == "help" (
:help
echo.Please use `make ^<target^>` where ^<target^> is one of
echo. html to make standalone HTML files
echo. dirhtml to make HTML files named index.html in directories
echo. singlehtml to make a single large HTML file
echo. pickle to make pickle files
echo. json to make JSON files
echo. htmlhelp to make HTML files and a HTML help project
echo. qthelp to make HTML files and a qthelp project
echo. devhelp to make HTML files and a Devhelp project
echo. epub to make an epub
echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
echo. text to make text files
echo. man to make manual pages
echo. changes to make an overview over all changed/added/deprecated items
echo. linkcheck to check all external links for integrity
echo. doctest to run all doctests embedded in the documentation if enabled
goto end
)
if "%1" == "clean" (
for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
del /q /s %BUILDDIR%\*
goto end
)
if "%1" == "html" (
%SPHINXBUILD% -b html %ALLSPHINXOPTS% %HTMLDIR%
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %HTMLDIR%.
goto end
)
if "%1" == "dirhtml" (
%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
goto end
)
if "%1" == "singlehtml" (
%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
goto end
)
if "%1" == "pickle" (
%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can process the pickle files.
goto end
)
if "%1" == "json" (
%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can process the JSON files.
goto end
)
if "%1" == "htmlhelp" (
%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can run HTML Help Workshop with the ^
.hhp project file in %BUILDDIR%/htmlhelp.
goto end
)
if "%1" == "qthelp" (
%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can run "qcollectiongenerator" with the ^
.qhcp project file in %BUILDDIR%/qthelp, like this:
echo.^> qcollectiongenerator %BUILDDIR%\qthelp\BoostNumPy.qhcp
echo.To view the help file:
echo.^> assistant -collectionFile %BUILDDIR%\qthelp\BoostNumPy.ghc
goto end
)
if "%1" == "devhelp" (
%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished.
goto end
)
if "%1" == "epub" (
%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The epub file is in %BUILDDIR%/epub.
goto end
)
if "%1" == "latex" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
if errorlevel 1 exit /b 1
echo.
echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
goto end
)
if "%1" == "text" (
%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The text files are in %BUILDDIR%/text.
goto end
)
if "%1" == "man" (
%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The manual pages are in %BUILDDIR%/man.
goto end
)
if "%1" == "changes" (
%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
if errorlevel 1 exit /b 1
echo.
echo.The overview file is in %BUILDDIR%/changes.
goto end
)
if "%1" == "linkcheck" (
%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
if errorlevel 1 exit /b 1
echo.
echo.Link check complete; look for any errors in the above output ^
or in %BUILDDIR%/linkcheck/output.txt.
goto end
)
if "%1" == "doctest" (
%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
if errorlevel 1 exit /b 1
echo.
echo.Testing of doctests in the sources finished, look at the ^
results in %BUILDDIR%/doctest/output.txt.
goto end
)
:end

View File

@@ -0,0 +1,110 @@
binary_ufunc
============
.. contents :: Table of Contents
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/python/numpy/ufunc.hpp>`` contains the ``binary_ufunc`` structure definitions
synopsis
--------
::
namespace boost
{
namespace python
{
namespace numpy
{
template <typename TBinaryFunctor,
typename TArgument1=typename TBinaryFunctor::first_argument_type,
typename TArgument2=typename TBinaryFunctor::second_argument_type,
typename TResult=typename TBinaryFunctor::result_type>
struct binary_ufunc
{
static object call(TBinaryFunctor & self,
object const & input1,
object const & input2,
object const & output);
static object make();
};
}
}
}
constructors
------------
::
struct example_binary_ufunc
{
typedef any_valid first_argument_type;
typedef any_valid second_argument_type;
typedef any_valid result_type;
};
:Requirements: The ``any_valid`` type must be defined using typedef as a valid C++ type in order to use the struct methods correctly
:Note: The struct must be exposed as a Python class, and an instance of the class must be created to use the ``call`` method corresponding to the ``__call__`` attribute of the Python object
accessors
---------
::
template <typename TBinaryFunctor,
typename TArgument1=typename TBinaryFunctor::first_argument_type,
typename TArgument2=typename TBinaryFunctor::second_argument_type,
typename TResult=typename TBinaryFunctor::result_type>
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
:Effects: Passes a Python object to the underlying C++ functor after broadcasting its arguments
::
template <typename TBinaryFunctor,
typename TArgument1=typename TBinaryFunctor::first_argument_type,
typename TArgument2=typename TBinaryFunctor::second_argument_type,
typename TResult=typename TBinaryFunctor::result_type>
static object make();
:Requires: Typenames ``TBinaryFunctor`` and optionally ``TArgument1`` and ``TArgument2`` for argument type and ``TResult`` for result type
:Returns: A Python function object to call the overloaded () operator in the struct (in typical usage)
Example(s)
----------
::
namespace p = boost::python;
namespace np = boost::python::numpy;
struct BinarySquare
{
typedef double first_argument_type;
typedef double second_argument_type;
typedef double result_type;
double operator()(double a,double b) const { return (a*a + b*b) ; }
};
p::object ud = p::class_<BinarySquare, boost::shared_ptr<BinarySquare> >("BinarySquare").def("__call__", np::binary_ufunc<BinarySquare>::make());
p::object inst = ud();
result_array = inst.attr("__call__")(demo_array,demo_array) ;
std::cout << "Square of list with binary ufunc is " << p::extract <char const * > (p::str(result_array)) << std::endl ;

View File

@@ -0,0 +1,92 @@
dtype
=====
.. contents :: Table of Contents
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/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
--------
::
namespace boost
{
namespace python
{
namespace numpy
{
class dtype : public object
{
static python::detail::new_reference convert(object::object_cref arg, bool align);
public:
// Convert an arbitrary Python object to a data-type descriptor object.
template <typename T>
explicit dtype(T arg, bool align=false);
// Get the built-in numpy dtype associated with the given scalar template type.
template <typename T> static dtype get_builtin();
// Return the size of the data type in bytes.
int get_itemsize() const;
};
}
}
}
constructors
------------
::
template <typename T>
explicit dtype(T arg, bool align=false)
:Requirements: ``T`` must be either :
* a built-in C++ typename convertible to object
* a valid python object or convertible to object
:Effects: Constructs an object from the supplied python object / convertible
to object / builtin C++ data type
:Throws: Nothing
::
template <typename T> static dtype get_builtin();
:Requirements: The typename supplied, ``T`` must be a builtin C++ type also supported by numpy
:Returns: Numpy dtype corresponding to builtin C++ type
accessors
---------
::
int get_itemsize() const;
:Returns: the size of the data type in bytes.
Example(s)
----------
::
namespace p = boost::python;
namespace np = boost::python::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

@@ -0,0 +1,12 @@
Boost.Python NumPy extension Reference
======================================
.. toctree::
:maxdepth: 2
dtype
ndarray
unary_ufunc
binary_ufunc
multi_iter

View File

@@ -0,0 +1,94 @@
multi_iter
==========
.. contents :: Table of Contents
A ``multi_iter`` is a Python object, intended to be used as an iterator It should generally only be used in loops.
``<boost/python/numpy/ufunc.hpp>`` contains the class definitions for ``multi_iter``
synopsis
--------
::
namespace boost
{
namespace python
{
namespace numpy
{
class multi_iter : public object
{
public:
void next();
bool not_done() const;
char * get_data(int n) const;
int const get_nd() const;
Py_intptr_t const * get_shape() const;
Py_intptr_t const shape(int n) const;
};
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
------------
::
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
accessors
---------
::
void next();
:Effects: Increments the iterator
::
bool not_done() const;
:Returns: boolean value indicating whether the iterator is at its end
::
char * get_data(int n) const;
:Returns: a pointer to the element of the nth broadcasted array.
::
int const get_nd() const;
:Returns: the number of dimensions of the broadcasted array expression
::
Py_intptr_t const * get_shape() const;
:Returns: the shape of the broadcasted array expression as an array of integers.
::
Py_intptr_t const shape(int n) const;
:Returns: the shape of the broadcasted array expression in the nth dimension.

View File

@@ -0,0 +1,382 @@
ndarray
=======
.. contents :: Table of Contents
A `ndarray`_ is an N-dimensional array which contains items of the same type and size, where N is the number of dimensions and is specified in the form of a ``shape`` tuple. Optionally, the numpy ``dtype`` for the objects contained may also be specified.
.. _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/python/numpy/ndarray.hpp>`` contains the structures and methods necessary to move raw data between C++ and Python and create ndarrays from the data
synopsis
--------
::
namespace boost
{
namespace python
{
namespace numpy
{
class ndarray : public object
{
public:
enum bitflag
{
NONE=0x0, C_CONTIGUOUS=0x1, F_CONTIGUOUS=0x2, V_CONTIGUOUS=0x1|0x2,
ALIGNED=0x4, WRITEABLE=0x8, BEHAVED=0x4|0x8,
CARRAY_RO=0x1|0x4, CARRAY=0x1|0x4|0x8, CARRAY_MIS=0x1|0x8,
FARRAY_RO=0x2|0x4, FARRAY=0x2|0x4|0x8, FARRAY_MIS=0x2|0x8,
UPDATE_ALL=0x1|0x2|0x4, VARRAY=0x1|0x2|0x8, ALL=0x1|0x2|0x4|0x8
};
ndarray view(dtype const & dt) const;
ndarray astype(dtype const & dt) const;
ndarray copy() const;
int const shape(int n) const;
int const strides(int n) const;
char * get_data() const;
dtype get_dtype() const;
python::object get_base() const;
void set_base(object const & base);
Py_intptr_t const * get_shape() const;
Py_intptr_t const * get_strides() const;
int const get_nd() const;
bitflag const get_flags() const;
ndarray transpose() const;
ndarray squeeze() const;
ndarray reshape(tuple const & shape) const;
object scalarize() const;
};
ndarray zeros(tuple const & shape, dtype const & dt);
ndarray zeros(int nd, Py_intptr_t 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(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, object const & owner);
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);
}
constructors
------------
::
ndarray view(dtype const & dt) const;
:Returns: new ndarray with old ndarray data cast as supplied dtype
::
ndarray astype(dtype const & dt) const;
:Returns: new ndarray with old ndarray data converted to supplied dtype
::
ndarray copy() const;
:Returns: Copy of calling ndarray object
::
ndarray transpose() const;
:Returns: An ndarray with the rows and columns interchanged
::
ndarray squeeze() const;
:Returns: An ndarray with all unit-shaped dimensions removed
::
ndarray reshape(tuple const & shape) const;
:Requirements: The new ``shape`` of the ndarray must be supplied as a tuple
:Returns: An ndarray with the same data but reshaped to the ``shape`` supplied
::
object scalarize() const;
:Returns: A scalar if the ndarray has only one element, otherwise it returns the entire array
::
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 :
* the ``shape`` or the size of all dimensions, as a tuple
* the ``dtype`` of the data
* the ``nd`` size for a square shaped ndarray
* the ``shape`` Py_intptr_t
:Returns: A new ndarray with the given shape and data type, with data initialized to zero.
::
ndarray empty(tuple const & shape, dtype const & dt);
ndarray empty(int nd, Py_intptr_t const * shape, dtype const & dt);
:Requirements: The following parameters must be supplied :
* the ``shape`` or the size of all dimensions, as a tuple
* the ``dtype`` of the data
* the ``shape`` Py_intptr_t
:Returns: A new ndarray with the given shape and data type, with data left uninitialized.
::
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
::
template <typename Container>
inline ndarray from_data(void * data,dtype const & dt,Container shape,Container strides,python::object const & owner)
:Requirements: The following parameters must be supplied :
* the ``data`` which is a generic C++ data container
* the dtype ``dt`` of the data
* the ``shape`` of the ndarray as Python object
* the ``strides`` of each dimension of the array as a Python object
* the ``owner`` of the data, in case it is not the ndarray itself
:Returns: ndarray with attributes and data supplied
:Note: The ``Container`` typename must be one that is convertible to a std::vector or python object type
::
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 :
* the ``obj`` Python object to convert to ndarray
* the dtype ``dt`` of the data
* minimum number of dimensions ``nd_min`` of the ndarray as Python object
* maximum number of dimensions ``nd_max`` of the ndarray as Python object
* optional ``flags`` bitflags
:Returns: ndarray constructed with dimensions and data supplied as parameters
::
inline ndarray from_object(object const & obj, dtype const & dt, int nd, ndarray::bitflag flags=ndarray::NONE);
:Requirements: The following parameters must be supplied :
* the ``obj`` Python object to convert to ndarray
* the dtype ``dt`` of the data
* number of dimensions ``nd`` of the ndarray as Python object
* optional ``flags`` bitflags
:Returns: ndarray with dimensions ``nd`` x ``nd`` and suplied parameters
::
inline ndarray from_object(object const & obj, dtype const & dt, ndarray::bitflag flags=ndarray::NONE)
:Requirements: The following parameters must be supplied :
* the ``obj`` Python object to convert to ndarray
* the dtype ``dt`` of the data
* optional ``flags`` bitflags
:Returns: Supplied Python object as ndarray
::
ndarray from_object(object const & obj, int nd_min, int nd_max, ndarray::bitflag flags=ndarray::NONE);
:Requirements: The following parameters must be supplied :
* the ``obj`` Python object to convert to ndarray
* minimum number of dimensions ``nd_min`` of the ndarray as Python object
* maximum number of dimensions ``nd_max`` of the ndarray as Python object
* optional ``flags`` bitflags
:Returns: ndarray with supplied dimension limits and parameters
:Note: dtype need not be supplied here
::
inline ndarray from_object(object const & obj, int nd, ndarray::bitflag flags=ndarray::NONE);
:Requirements: The following parameters must be supplied :
* the ``obj`` Python object to convert to ndarray
* the dtype ``dt`` of the data
* number of dimensions ``nd`` of the ndarray as Python object
* optional ``flags`` bitflags
:Returns: ndarray of ``nd`` x ``nd`` dimensions constructed from the supplied object
::
inline ndarray from_object(object const & obj, ndarray::bitflag flags=ndarray::NONE)
:Requirements: The following parameters must be supplied :
* the ``obj`` Python object to convert to ndarray
* optional ``flags`` bitflags
:Returns: ndarray of same dimensions and dtype as supplied Python object
accessors
---------
::
int const shape(int n) const;
:Returns: The size of the n-th dimension of the ndarray
::
int const strides(int n) const;
:Returns: The stride of the nth dimension.
::
char * get_data() const;
:Returns: Array's raw data pointer as a char
:Note: This returns char so stride math works properly on it.User will have to reinterpret_cast it.
::
dtype get_dtype() const;
:Returns: Array's data-type descriptor object (dtype)
::
object get_base() const;
:Returns: Object that owns the array's data, or None if the array owns its own data.
::
void set_base(object const & base);
:Returns: Set the object that owns the array's data. Exercise caution while using this
::
Py_intptr_t const * get_shape() const;
:Returns: Shape of the array as an array of integers
::
Py_intptr_t const * get_strides() const;
:Returns: Stride of the array as an array of integers
::
int const get_nd() const;
:Returns: Number of array dimensions
::
bitflag const get_flags() const;
:Returns: Array flags
::
inline ndarray::bitflag operator|(ndarray::bitflag a, ndarray::bitflag b)
:Returns: bitflag logically OR-ed as (a | b)
::
inline ndarray::bitflag operator&(ndarray::bitflag a, ndarray::bitflag b)
:Returns: bitflag logically AND-ed as (a & b)
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) ;
p::list l ;
np::ndarray example_list = np::array (l) ;
np::dtype dt = np::dtype::get_builtin<int>();
np::ndarray example_list1 = np::array (l,dt);
int data[] = {1,2,3,4} ;
p::tuple shape = p::make_tuple(4) ;
p::tuple stride = p::make_tuple(4) ;
p::object own ;
np::ndarray data_ex = np::from_data(data,dt,shape,stride,own);
uint8_t mul_data[][4] = {{1,2,3,4},{5,6,7,8},{1,3,5,7}};
shape = p::make_tuple(3,2) ;
stride = p::make_tuple(4,2) ;
np::dtype dt1 = np::dtype::get_builtin<uint8_t>();
np::ndarray mul_data_ex = np::from_data(mul_data,dt1, p::make_tuple(3,4),p::make_tuple(4,1),p::object());
mul_data_ex = np::from_data(mul_data,dt1, shape,stride,p::object());

View File

@@ -0,0 +1,103 @@
unary_ufunc
===========
.. contents :: Table of Contents
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/python/numpy/ufunc.hpp>`` contains the ``unary_ufunc`` structure definitions
synopsis
--------
::
namespace boost
{
namespace python
{
namespace numpy
{
template <typename TUnaryFunctor,
typename TArgument=typename TUnaryFunctor::argument_type,
typename TResult=typename TUnaryFunctor::result_type>
struct unary_ufunc
{
static object call(TUnaryFunctor & self,
object const & input,
object const & output) ;
static object make();
};
}
}
}
constructors
------------
::
struct example_unary_ufunc
{
typedef any_valid_type argument_type;
typedef any_valid_type result_type;
};
:Requirements: The ``any_valid`` type must be defined using typedef as a valid C++ type in order to use the struct methods correctly
:Note: The struct must be exposed as a Python class, and an instance of the class must be created to use the ``call`` method corresponding to the ``__call__`` attribute of the Python object
accessors
---------
::
template <typename TUnaryFunctor,
typename TArgument=typename TUnaryFunctor::argument_type,
typename TResult=typename TUnaryFunctor::result_type>
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
:Effects: Passes a Python object to the underlying C++ functor after broadcasting its arguments
::
template <typename TUnaryFunctor,
typename TArgument=typename TUnaryFunctor::argument_type,
typename TResult=typename TUnaryFunctor::result_type>
static object make();
:Requires: Typenames ``TUnaryFunctor`` and optionally ``TArgument`` for argument type and ``TResult`` for result type
:Returns: A Python function object to call the overloaded () operator in the struct (in typical usage)
Example(s)
----------
::
namespace p = boost::python;
namespace np = boost::python::numpy;
struct UnarySquare
{
typedef double argument_type;
typedef double result_type;
double operator()(double r) const { return r * r;}
};
p::object ud = p::class_<UnarySquare, boost::shared_ptr<UnarySquare> >("UnarySquare").def("__call__", np::unary_ufunc<UnarySquare>::make());
p::object inst = ud();
std::cout << "Square of unary scalar 1.0 is " << p::extract <char const * > (p::str(inst.attr("__call__")(1.0))) << std::endl ;

149
doc/numpy/rst.css Normal file
View File

@@ -0,0 +1,149 @@
@import url("doc/src/boostbook.css");
@import url("doc/src/docutils.css");
/* Copyright David Abrahams 2006. 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)
*/
dl.docutils dt {
font-weight: bold }
img.boost-logo {
border: none;
vertical-align: middle
}
pre.literal-block span.concept {
font-style: italic;
}
.nav {
display: inline;
list-style-type: none;
}
.prevpage {
padding-top: -5px;
text-align: left;
float: left;
}
.nextpage {
padding-top: -20px;
text-align: right;
float: right;
}
div.small {
font-size: smaller }
h2 a {
font-size: 90%;
}
h3 a {
font-size: 80%;
}
h4 a {
font-size: 70%;
}
h5 a {
font-size: 60%;
}
dl,table
{
text-align: left;
font-size: 10pt;
line-height: 1.15;
}
/*=============================================================================
Tables
=============================================================================*/
/* The only clue docutils gives us that tables are logically tables,
and not, e.g., footnotes, is that they have border="1". Therefore
we're keying off of that. We used to manually patch docutils to
add a "table" class to all logical tables, but that proved much too
fragile.
*/
table[border="1"]
{
width: 92%;
margin-left: 4%;
margin-right: 4%;
}
table[border="1"]
{
padding: 4px;
}
/* Table Cells */
table[border="1"] tr td
{
padding: 0.5em;
text-align: left;
font-size: 9pt;
}
table[border="1"] tr th
{
padding: 0.5em 0.5em 0.5em 0.5em;
border: 1pt solid white;
font-size: 80%;
}
@media screen
{
/* Tables */
table[border="1"] tr td
{
border: 1px solid #DCDCDC;
}
table[border="1"] tr th
{
background-color: #F0F0F0;
border: 1px solid #DCDCDC;
}
pre,
.screen
{
border: 1px solid #DCDCDC;
}
td pre
td .screen
{
border: 0px
}
.sidebar pre
{
border: 0px
}
}
pre,
.screen
{
font-size: 9pt;
display: block;
margin: 1pc 4% 0pc 4%;
padding: 0.5pc 0.5pc 0.5pc 0.5pc;
}
/* Program listings in tables don't get borders */
td pre,
td .screen
{
margin: 0pc 0pc 0pc 0pc;
padding: 0pc 0pc 0pc 0pc;
}

View File

@@ -0,0 +1,54 @@
How to use dtypes
=================
Here is a brief tutorial to show how to create ndarrays with built-in python data types, and extract the types and values of member variables
Like before, first get the necessary headers, setup the namespaces and initialize the Python runtime and numpy module::
#include <boost/python/numpy.hpp>
#include <iostream>
namespace p = boost::python;
namespace np = boost::python::numpy;
int main(int argc, char **argv)
{
Py_Initialize();
np::initialize();
Next, we create the shape and dtype. We use the get_builtin method to get the numpy dtype corresponding to the builtin C++ dtype
Here, we will create a 3x3 array passing a tuple with (3,3) for the size, and double as the data type ::
p::tuple shape = p::make_tuple(3, 3);
np::dtype dtype = np::dtype::get_builtin<double>();
np::ndarray a = np::zeros(shape, dtype);
Finally, we can print the array using the extract method in the python namespace.
Here, we first convert the variable into a string, and then extract it as a C++ character array from the python string using the <char const \* > template ::
std::cout << "Original array:\n" << p::extract<char const *>(p::str(a)) << std::endl;
We can also print the dtypes of the data members of the ndarray by using the get_dtype method for the ndarray ::
std::cout << "Datatype is:\n" << p::extract<char const *>(p::str(a.get_dtype())) << std::endl ;
We can also create custom dtypes and build ndarrays with the custom dtypes
We use the dtype constructor to create a custom dtype. This constructor takes a list as an argument.
The list should contain one or more tuples of the format (variable name, variable type)
So first create a tuple with a variable name and its dtype, double, to create a custom dtype ::
p::tuple for_custom_dtype = p::make_tuple("ha",dtype) ;
Next, create a list, and add this tuple to the list. Then use the list to create the custom dtype ::
p::list list_for_dtype ;
list_for_dtype.append(for_custom_dtype) ;
np::dtype custom_dtype = np::dtype(list_for_dtype) ;
We are now ready to create an ndarray with dimensions specified by \*shape\* and of custom dtpye ::
np::ndarray new_array = np::zeros(shape,custom_dtype);
}

View File

@@ -0,0 +1,56 @@
How to access data using raw pointers
=====================================
One of the advantages of the ndarray wrapper is that the same data can be used in both Python and C++ and changes can be made to reflect at both ends.
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/python/numpy.hpp>
#include <iostream>
namespace p = boost::python;
namespace np = boost::python::numpy;
int main(int argc, char **argv)
{
Py_Initialize();
np::initialize();
Create an array in C++ , and pass the pointer to it to the from_data method to create an ndarray::
int arr[] = {1,2,3,4,5};
np::ndarray py_array = np::from_data(arr, np::dtype::get_builtin<int>(),
p::make_tuple(5),
p::make_tuple(sizeof(int)),
p::object());
Print the source C++ array, as well as the ndarray, to check if they are the same::
std::cout << "C++ array :" << std::endl;
for (int j=0;j<4;j++)
{
std::cout << arr[j] << ' ';
}
std::cout << std::endl
<< "Python ndarray :" << p::extract<char const *>(p::str(py_array)) << std::endl;
Now, change an element in the Python ndarray, and check if the value changed correspondingly in the source C++ array::
py_array[1] = 5 ;
std::cout << "Is the change reflected in the C++ array used to create the ndarray ? " << std::endl;
for (int j = 0; j < 5; j++)
{
std::cout << arr[j] << ' ';
}
Next, change an element of the source C++ array and see if it is reflected in the Python ndarray::
arr[2] = 8;
std::cout << std::endl
<< "Is the change reflected in the Python ndarray ?" << std::endl
<< p::extract<char const *>(p::str(py_array)) << std::endl;
}
As we can see, the changes are reflected across the ends. This happens because the from_data method passes the C++ array by reference to create the ndarray, and thus uses the same locations for storing data.

View File

@@ -0,0 +1,12 @@
Boost.Python NumPy extension Tutorial
=====================================
.. toctree::
:maxdepth: 2
simple
dtype
ndarray
ufunc
fromdata

View File

@@ -0,0 +1,99 @@
Creating ndarrays
=================
The Boost.Numpy library exposes quite a few methods to create ndarrays. ndarrays can be created in a variety of ways, include empty arrays and zero filled arrays.
ndarrays can also be created from arbitrary python sequences as well as from data and dtypes.
This tutorial will introduce you to some of the ways in which you can create ndarrays. The methods covered here include creating ndarrays from arbitrary Python sequences, as well as from C++ containers, using both unit and non-unit strides
First, as before, initialise the necessary namepaces and runtimes ::
#include <boost/python/numpy.hpp>
#include <iostream>
namespace p = boost::python;
namespace np = boost::python::numpy;
int main(int argc, char **argv)
{
Py_Initialize();
np::initialize();
Let's now create an ndarray from a simple tuple. We first create a tuple object, and then pass it to the array method, to generate the necessary tuple ::
p::object tu = p::make_tuple('a','b','c');
np::ndarray example_tuple = np::array(tu);
Let's now try the same with a list. We create an empty list, add an element using the append method, and as before, call the array method ::
p::list l;
l.append('a');
np::ndarray example_list = np::array (l);
Optionally, we can also specify a dtype for the array ::
np::dtype dt = np::dtype::get_builtin<int>();
np::ndarray example_list1 = np::array (l,dt);
We can also create an array by supplying data arrays and a few other parameters.
First,create an integer array ::
int data[] = {1,2,3,4,5};
Create a shape, and strides, needed by the function ::
p::tuple shape = p::make_tuple(5);
p::tuple stride = p::make_tuple(sizeof(int));
Here, shape is (4,) , and the stride is `sizeof(int)``.
A stride is the number of bytes that must be traveled to get to the next desired element while constructing the ndarray.
The function also needs an owner, to keep track of the data array passed. Passing none is dangerous ::
p::object own;
The from_data function takes the data array, datatype,shape,stride and owner as arguments and returns an ndarray ::
np::ndarray data_ex1 = np::from_data(data,dt, shape,stride,own);
Now let's print the ndarray we created ::
std::cout << "Single dimensional array ::" << std::endl
<< p::extract<char const *>(p::str(data_ex)) << std::endl;
Let's make it a little more interesting. Lets make an 3x2 ndarray from a multi-dimensional array using non-unit strides
First lets create a 3x4 array of 8-bit integers ::
uint8_t mul_data[][4] = {{1,2,3,4},{5,6,7,8},{1,3,5,7}};
Now let's create an array of 3x2 elements, picking the first and third elements from each row . For that, the shape will be 3x2.
The strides will be 4x2 i.e. 4 bytes to go to the next desired row, and 2 bytes to go to the next desired column ::
shape = p::make_tuple(3,2);
stride = p::make_tuple(sizeof(uint8_t)*2,sizeof(uint8_t));
Get the numpy dtype for the built-in 8-bit integer data type ::
np::dtype dt1 = np::dtype::get_builtin<uint8_t>();
Now lets first create and print out the ndarray as is.
Notice how we can pass the shape and strides in the function directly, as well as the owner. The last part can be done because we don't have any use to
manipulate the "owner" object ::
np::ndarray mul_data_ex = np::from_data(mul_data, dt1,
p::make_tuple(3,4),
p::make_tuple(4,1),
p::object());
std::cout << "Original multi dimensional array :: " << std::endl
<< p::extract<char const *>(p::str(mul_data_ex)) << std::endl;
Now create the new ndarray using the shape and strides and print out the array we created using non-unit strides ::
mul_data_ex = np::from_data(mul_data, dt1, shape, stride, p::object());
std::cout << "Selective multidimensional array :: "<<std::endl
<< p::extract<char const *>(p::str(mul_data_ex)) << std::endl ;
}
.. note:: The from_data method will throw ``error_already_set`` if the number of elements dictated by the shape and the corresponding strides don't match.

View File

@@ -0,0 +1,41 @@
A simple tutorial on Arrays
===========================
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/python/numpy.hpp>
#include <iostream>
namespace p = boost::python;
namespace np = boost::python::numpy;
Initialise the Python runtime, and the numpy module. Failure to call these results in segmentation errors::
int main(int argc, char **argv)
{
Py_Initialize();
np::initialize();
Zero filled n-dimensional arrays can be created using the shape and data-type of the array as a parameter. Here, the shape is 3x3 and the datatype is the built-in float type::
p::tuple shape = p::make_tuple(3, 3);
np::dtype dtype = np::dtype::get_builtin<float>();
np::ndarray a = np::zeros(shape, dtype);
You can also create an empty array like this ::
np::ndarray b = np::empty(shape,dtype);
Print the original and reshaped array. The array a which is a list is first converted to a string, and each value in the list is extracted using extract< >::
std::cout << "Original array:\n" << p::extract<char const *>(p::str(a)) << std::endl;
// Reshape the array into a 1D array
a = a.reshape(p::make_tuple(9));
// Print it again.
std::cout << "Reshaped array:\n" << p::extract<char const *>(p::str(a)) << std::endl;
}

View File

@@ -0,0 +1,120 @@
Ufuncs
======
Ufuncs or universal functions operate on ndarrays element by element, and support array broadcasting, type casting, and other features.
Lets try and see how we can use the binary and unary ufunc methods
After the neccessary includes ::
#include <boost/python/numpy.hpp>
#include <iostream>
namespace p = boost::python;
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 ::
struct UnarySquare
{
typedef double argument_type;
typedef double result_type;
double operator()(double r) const { return r * r;}
};
struct BinarySquare
{
typedef double first_argument_type;
typedef double second_argument_type;
typedef double result_type;
double operator()(double a,double b) const { return (a*a + b*b) ; }
};
Initialise the Python runtime and the numpy module ::
int main(int argc, char **argv)
{
Py_Initialize();
np::initialize();
Now expose the struct UnarySquare to Python as a class, and let ud be the class object. ::
p::object ud = p::class_<UnarySquare, boost::shared_ptr<UnarySquare> >("UnarySquare");
ud.def("__call__", np::unary_ufunc<UnarySquare>::make());
Let inst be an instance of the class ud ::
p::object inst = ud();
Use the "__call__" method to call the overloaded () operator and print the value ::
std::cout << "Square of unary scalar 1.0 is " << p::extract<char const *>(p::str(inst.attr("__call__")(1.0))) << std::endl;
Create an array in C++ ::
int arr[] = {1,2,3,4} ;
..and use it to create the ndarray in Python ::
np::ndarray demo_array = np::from_data(arr, np::dtype::get_builtin<int>(),
p::make_tuple(4),
p::make_tuple(4),
p::object());
Print out the demo array ::
std::cout << "Demo array is " << p::extract<char const *>(p::str(demo_array)) << std::endl;
Call the "__call__" method to perform the operation and assign the value to result_array ::
p::object result_array = inst.attr("__call__")(demo_array);
Print the resultant array ::
std::cout << "Square of demo array is " << p::extract<char const *>(p::str(result_array)) << std::endl;
Lets try the same with a list ::
p::list li;
li.append(3);
li.append(7);
Print out the demo list ::
std::cout << "Demo list is " << p::extract<char const *>(p::str(li)) << std::endl;
Call the ufunc for the list ::
result_array = inst.attr("__call__")(li);
And print the list out ::
std::cout << "Square of demo list is " << p::extract<char const *>(p::str(result_array)) << std::endl;
Now lets try Binary ufuncs. Again, expose the struct BinarySquare to Python as a class, and let ud be the class object ::
ud = p::class_<BinarySquare, boost::shared_ptr<BinarySquare> >("BinarySquare");
ud.def("__call__", np::binary_ufunc<BinarySquare>::make());
And initialise ud ::
inst = ud();
Print the two input lists ::
std::cout << "The two input list for binary ufunc are " << std::endl
<< p::extract<char const *>(p::str(demo_array)) << std::endl
<< p::extract<char const *>(p::str(demo_array)) << std::endl;
Call the binary ufunc taking demo_array as both inputs ::
result_array = inst.attr("__call__")(demo_array,demo_array);
And print the output ::
std::cout << "Square of list with binary ufunc is " << p::extract<char const *>(p::str(result_array)) << std::endl;
}

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 Extension Documentation]
[endsect]

View File

@@ -38,7 +38,7 @@ The `indexing_suite` class is the base class for the management of C++ container
[[__iter__(self)]
[This method is called when an iterator is required for a container. This method should return a new iterator object that can iterate over all the objects in the container. For mappings, it should iterate over the keys of the container, and should also be made available as the method iterkeys().
Iterator objects also need to implement this method; they are required to return themselves. For more information on iterator objects, see [@http://www.python.org/doc/current/lib/typeiter.html Iterator Types] in the [@http://www.python.org/doc/current/lib/lib.html Python Library Reference].]]
Iterator objects also need to implement this method; they are required to return themselves. For more information on iterator objects, see [@https://docs.python.org/3/library/stdtypes.html#iterator-types Iterator Types] in the [@https://docs.python.org/3/library/index.html Python Library Reference].]]
[[__contains__(self, item)]
[Called to implement membership test operators. Should return true if item is in self, false otherwise. For mapping objects, this should consider the keys of the mapping rather than the values or the key-item pairs.]]

View File

@@ -4,7 +4,7 @@ Pickle is a Python module for object serialization, also known as persistence, m
It is often necessary to save and restore the contents of an object to a file. One approach to this problem is to write a pair of functions that read and write data from a file in a special format. A powerful alternative approach is to use Python's pickle module. Exploiting Python's ability for introspection, the pickle module recursively converts nearly arbitrary Python objects into a stream of bytes that can be written to a file.
The Boost Python Library supports the pickle module through the interface as described in detail in the [@http://www.python.org/doc/current/lib/module-pickle.html Python Library Reference for pickle]. This interface involves the special methods `__getinitargs__`, `__getstate__` and `__setstate__` as described in the following. Note that `Boost.Python` is also fully compatible with Python's cPickle module.
The Boost Python Library supports the pickle module through the interface as described in detail in the [@https://docs.python.org/2/library/pickle.html Python Library Reference for pickle]. This interface involves the special methods `__getinitargs__`, `__getstate__` and `__setstate__` as described in the following. Note that `Boost.Python` is also fully compatible with Python's cPickle module.
[endsect]
[section The Pickle Interface]
At the user level, the Boost.Python pickle interface involves three special methods:

View File

@@ -1,43 +1,35 @@
# Copyright David Abrahams 2006. 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)
# 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)
# Specify the path to the Boost project. If you move this project,
# adjust this path to refer to the Boost root directory.
use-project boost
: ../../.. ;
import python ;
# Set up the project-wide requirements that everything uses the
# boost_python library from the project whose global ID is
# /boost/python.
project
: requirements <library>/boost/python//boost_python
<implicit-dependency>/boost//headers
: usage-requirements <implicit-dependency>/boost//headers
;
# Declare the three extension modules. You can specify multiple
# source files after the colon separated by spaces.
python-extension getting_started1 : getting_started1.cpp ;
python-extension getting_started2 : getting_started2.cpp ;
python-extension std_pair_ext : std_pair.cpp ;
# A little "rule" (function) to clean up the syntax of declaring tests
# of these extension modules.
local rule run-test ( test-name : sources + )
if ! [ python.configured ]
{
import testing ;
testing.make-test run-pyd : $(sources) : : $(test-name) ;
ECHO "warning: no Python configured in user-config.jam" ;
ECHO "warning: will use default configuration" ;
using python ;
}
# Declare test targets
run-test test1 : getting_started1 test_getting_started1.py ;
run-test test2 : getting_started2 test_getting_started2.py ;
run-test test3 : std_pair_ext test_std_pair.py ;
# Adjust the following if Boost.Python isn't installed in a default location
lib boost_python ;
# A target that runs all the tests
alias test : test1 test2 test3 ;
project
: requirements
# <include>/path/to/boost/python
<library>boost_python
;
# Only run tests when explicitly requested
explicit test test1 test2 test3 ;
rule run-test ( test-name : sources + )
{
import testing ;
testing.make-test run-pyd : $(sources) : : $(test-name) ;
}
build-project quickstart ;
build-project tutorial ;
if [ python.numpy ]
{
build-project numpy ;
}

View File

@@ -1,16 +0,0 @@
.. Copyright David Abrahams 2006. 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)
To get started with the Boost Python Library, use the examples
getting_started1.cpp and getting_started2.cpp. Invoking
bjam --toolset=your-toolset test
in this directory will build and run the examples. See
http://www.boost.org/more/getting_started.html for details about the
--toolset= option.
If you move this example from its place in the Boost development tree
you'll need to edit the two lines indicated in Jamroot and
boost-build.jam.

11
example/README.md Normal file
View File

@@ -0,0 +1,11 @@
![logo](https://raw.githubusercontent.com/boostorg/python/develop/doc/images/bpl.png)
# Examples
This directory contains various examples using Boost.Python.
You may compile these using the `bjam` command either in this directory
or in any of the subdirectories.
You may need to adjust the paths in the Jamroot file if Boost.Python
is not installed in a default location.
See http://boostorg.github.io/python/doc/html/building/no_install_quickstart.html
for details.

View File

@@ -1,7 +0,0 @@
# Copyright David Abrahams 2006. 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)
# Edit this path to point at the tools/build/src subdirectory of your
# Boost installation. Absolute paths work, too.
boost-build ../../../tools/build/src ;

View File

@@ -1,25 +0,0 @@
// Copyright Ralf W. Grosse-Kunstleve 2002-2004. 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/python/module.hpp>
#include <boost/python/def.hpp>
#include <string>
namespace { // Avoid cluttering the global namespace.
// A couple of simple C++ functions that we want to expose to Python.
std::string greet() { return "hello, world"; }
int square(int number) { return number * number; }
}
namespace python = boost::python;
// Python requires an exported function called init<module-name> in every
// extension module. This is where we build the module contents.
BOOST_PYTHON_MODULE(getting_started1)
{
// Add regular functions to the module.
python::def("greet", greet);
python::def("square", square);
}

View File

@@ -1,41 +0,0 @@
// Copyright Ralf W. Grosse-Kunstleve 2002-2004. 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/python/class.hpp>
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
#include <iostream>
#include <string>
namespace { // Avoid cluttering the global namespace.
// A friendly class.
class hello
{
public:
hello(const std::string& country) { this->country = country; }
std::string greet() const { return "Hello from " + country; }
private:
std::string country;
};
// A function taking a hello object as an argument.
std::string invite(const hello& w) {
return w.greet() + "! Please come soon!";
}
}
BOOST_PYTHON_MODULE(getting_started2)
{
using namespace boost::python;
class_<hello>("hello", init<std::string>())
// Add a regular member function.
.def("greet", &hello::greet)
// Add invite() as a member of hello!
.def("invite", invite)
;
// Also add invite() as a regular function to the module.
def("invite", invite);
}

29
example/numpy/Jamfile Normal file
View File

@@ -0,0 +1,29 @@
# 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)
import python ;
# Adjust the following if Boost.Python isn't installed in a default location
lib boost_numpy
:
: <search>/usr/local/Boost/lib
<include>/usr/local/Boost/include
;
project numpy
: requirements
<include>/usr/local/Boost/include
<library>boost_numpy
<location>.
;
exe simple : simple.cpp boost_numpy /python//python ;
exe dtype : dtype.cpp boost_numpy /python//python ;
exe ndarray : ndarray.cpp /python//python ;
exe fromdata : fromdata.cpp /python//python ;
exe ufunc : ufunc.cpp /python//python ;
exe wrap : wrap.cpp /python//python ;
python-extension gaussian : gaussian.cpp ;

View File

@@ -0,0 +1,37 @@
# Copyright Jim Bosch 2010-2012.
# 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)
import numpy
import gaussian
mu = numpy.zeros(2, dtype=float)
sigma = numpy.identity(2, dtype=float)
sigma[0, 1] = 0.15
sigma[1, 0] = 0.15
g = gaussian.bivariate_gaussian(mu, sigma)
r = numpy.linspace(-40, 40, 1001)
x, y = numpy.meshgrid(r, r)
z = g(x, y)
s = z.sum() * (r[1] - r[0])**2
print "sum (should be ~ 1):", s
xc = (z * x).sum() / z.sum()
print "x centroid (should be ~ %f): %f" % (mu[0], xc)
yc = (z * y).sum() / z.sum()
print "y centroid (should be ~ %f): %f" % (mu[1], yc)
xx = (z * (x - xc)**2).sum() / z.sum()
print "xx moment (should be ~ %f): %f" % (sigma[0,0], xx)
yy = (z * (y - yc)**2).sum() / z.sum()
print "yy moment (should be ~ %f): %f" % (sigma[1,1], yy)
xy = 0.5 * (z * (x - xc) * (y - yc)).sum() / z.sum()
print "xy moment (should be ~ %f): %f" % (sigma[0,1], xy)

49
example/numpy/dtype.cpp Normal file
View File

@@ -0,0 +1,49 @@
// Copyright Ankit Daftery 2011-2012.
// 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)
/**
* @brief An example to show how to create ndarrays with built-in python data types, and extract
* the types and values of member variables
*
* @todo Add an example to show type conversion.
* Add an example to show use of user-defined types
*
*/
#include <boost/python/numpy.hpp>
#include <iostream>
namespace p = boost::python;
namespace np = boost::python::numpy;
int main(int argc, char **argv)
{
// Initialize the Python runtime.
Py_Initialize();
// Initialize NumPy
np::initialize();
// Create a 3x3 shape...
p::tuple shape = p::make_tuple(3, 3);
// ...as well as a type for C++ double
np::dtype dtype = np::dtype::get_builtin<double>();
// Construct an array with the above shape and type
np::ndarray a = np::zeros(shape, dtype);
// Print the array
std::cout << "Original array:\n" << p::extract<char const *>(p::str(a)) << std::endl;
// Print the datatype of the elements
std::cout << "Datatype is:\n" << p::extract<char const *>(p::str(a.get_dtype())) << std::endl ;
// Using user defined dtypes to create dtype and an array of the custom dtype
// First create a tuple with a variable name and its dtype, double, to create a custom dtype
p::tuple for_custom_dtype = p::make_tuple("ha",dtype) ;
// The list needs to be created, because the constructor to create the custom dtype
// takes a list of (variable,variable_type) as an argument
p::list list_for_dtype ;
list_for_dtype.append(for_custom_dtype) ;
// Create the custom dtype
np::dtype custom_dtype = np::dtype(list_for_dtype) ;
// Create an ndarray with the custom dtype
np::ndarray new_array = np::zeros(shape,custom_dtype);
}

View File

@@ -0,0 +1,48 @@
// Copyright Ankit Daftery 2011-2012.
// 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)
/**
* @brief An example to show how to access data using raw pointers. This shows that you can use and
* manipulate data in either Python or C++ and have the changes reflected in both.
*/
#include <boost/python/numpy.hpp>
#include <iostream>
namespace p = boost::python;
namespace np = boost::python::numpy;
int main(int argc, char **argv)
{
// Initialize the Python runtime.
Py_Initialize();
// Initialize NumPy
np::initialize();
// Create an array in C++
int arr[] = {1,2,3,4} ;
// Create the ndarray in Python
np::ndarray py_array = np::from_data(arr, np::dtype::get_builtin<int>() , p::make_tuple(4), p::make_tuple(4), p::object());
// Print the ndarray that we just created, and the source C++ array
std::cout << "C++ array :" << std::endl ;
for (int j=0;j<4;j++)
{
std::cout << arr[j] << ' ' ;
}
std::cout << std::endl << "Python ndarray :" << p::extract<char const *>(p::str(py_array)) << std::endl;
// Change an element in the python ndarray
py_array[1] = 5 ;
// And see if the C++ container is changed or not
std::cout << "Is the change reflected in the C++ array used to create the ndarray ? " << std::endl ;
for (int j = 0;j<4 ; j++)
{
std::cout << arr[j] << ' ' ;
}
// Conversely, change it in C++
arr[2] = 8 ;
// And see if the changes are reflected in the Python ndarray
std::cout << std::endl << "Is the change reflected in the Python ndarray ?" << std::endl << p::extract<char const *>(p::str(py_array)) << std::endl;
}

315
example/numpy/gaussian.cpp Normal file
View File

@@ -0,0 +1,315 @@
// Copyright Jim Bosch 2010-2012.
// 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/python/numpy.hpp>
#include <cmath>
#include <memory>
#ifndef M_PI
#include <boost/math/constants/constants.hpp>
const double M_PI = boost::math::constants::pi<double>();
#endif
namespace bp = boost::python;
namespace bn = boost::python::numpy;
/**
* A 2x2 matrix class, purely for demonstration purposes.
*
* Instead of wrapping this class with Boost.Python, we'll convert it to/from numpy.ndarray.
*/
class matrix2 {
public:
double & operator()(int i, int j) {
return _data[i*2 + j];
}
double const & operator()(int i, int j) const {
return _data[i*2 + j];
}
double const * data() const { return _data; }
private:
double _data[4];
};
/**
* A 2-element vector class, purely for demonstration purposes.
*
* Instead of wrapping this class with Boost.Python, we'll convert it to/from numpy.ndarray.
*/
class vector2 {
public:
double & operator[](int i) {
return _data[i];
}
double const & operator[](int i) const {
return _data[i];
}
double const * data() const { return _data; }
vector2 operator+(vector2 const & other) const {
vector2 r;
r[0] = _data[0] + other[0];
r[1] = _data[1] + other[1];
return r;
}
vector2 operator-(vector2 const & other) const {
vector2 r;
r[0] = _data[0] - other[0];
r[1] = _data[1] - other[1];
return r;
}
private:
double _data[2];
};
/**
* Matrix-vector multiplication.
*/
vector2 operator*(matrix2 const & m, vector2 const & v) {
vector2 r;
r[0] = m(0, 0) * v[0] + m(0, 1) * v[1];
r[1] = m(1, 0) * v[0] + m(1, 1) * v[1];
return r;
}
/**
* Vector inner product.
*/
double dot(vector2 const & v1, vector2 const & v2) {
return v1[0] * v2[0] + v1[1] * v2[1];
}
/**
* This class represents a simple 2-d Gaussian (Normal) distribution, defined by a
* mean vector 'mu' and a covariance matrix 'sigma'.
*/
class bivariate_gaussian {
public:
vector2 const & get_mu() const { return _mu; }
matrix2 const & get_sigma() const { return _sigma; }
/**
* Evaluate the density of the distribution at a point defined by a two-element vector.
*/
double operator()(vector2 const & p) const {
vector2 u = _cholesky * (p - _mu);
return 0.5 * _cholesky(0, 0) * _cholesky(1, 1) * std::exp(-0.5 * dot(u, u)) / M_PI;
}
/**
* Evaluate the density of the distribution at an (x, y) point.
*/
double operator()(double x, double y) const {
vector2 p;
p[0] = x;
p[1] = y;
return operator()(p);
}
/**
* Construct from a mean vector and covariance matrix.
*/
bivariate_gaussian(vector2 const & mu, matrix2 const & sigma)
: _mu(mu), _sigma(sigma), _cholesky(compute_inverse_cholesky(sigma))
{}
private:
/**
* This evaluates the inverse of the Cholesky factorization of a 2x2 matrix;
* it's just a shortcut in evaluating the density.
*/
static matrix2 compute_inverse_cholesky(matrix2 const & m) {
matrix2 l;
// First do cholesky factorization: l l^t = m
l(0, 0) = std::sqrt(m(0, 0));
l(0, 1) = m(0, 1) / l(0, 0);
l(1, 1) = std::sqrt(m(1, 1) - l(0,1) * l(0,1));
// Now do forward-substitution (in-place) to invert:
l(0, 0) = 1.0 / l(0, 0);
l(1, 0) = l(0, 1) = -l(0, 1) / l(1, 1);
l(1, 1) = 1.0 / l(1, 1);
return l;
}
vector2 _mu;
matrix2 _sigma;
matrix2 _cholesky;
};
/*
* We have a two options for wrapping get_mu and get_sigma into NumPy-returning Python methods:
* - we could deep-copy the data, making totally new NumPy arrays;
* - we could make NumPy arrays that point into the existing memory.
* The latter is often preferable, especially if the arrays are large, but it's dangerous unless
* the reference counting is correct: the returned NumPy array needs to hold a reference that
* keeps the memory it points to from being deallocated as long as it is alive. This is what the
* "owner" argument to from_data does - the NumPy array holds a reference to the owner, keeping it
* from being destroyed.
*
* Note that this mechanism isn't completely safe for data members that can have their internal
* storage reallocated. A std::vector, for instance, can be invalidated when it is resized,
* so holding a Python reference to a C++ class that holds a std::vector may not be a guarantee
* that the memory in the std::vector will remain valid.
*/
/**
* These two functions are custom wrappers for get_mu and get_sigma, providing the shallow-copy
* conversion with reference counting described above.
*
* It's also worth noting that these return NumPy arrays that cannot be modified in Python;
* the const overloads of vector::data() and matrix::data() return const references,
* and passing a const pointer to from_data causes NumPy's 'writeable' flag to be set to false.
*/
static bn::ndarray py_get_mu(bp::object const & self) {
vector2 const & mu = bp::extract<bivariate_gaussian const &>(self)().get_mu();
return bn::from_data(
mu.data(),
bn::dtype::get_builtin<double>(),
bp::make_tuple(2),
bp::make_tuple(sizeof(double)),
self
);
}
static bn::ndarray py_get_sigma(bp::object const & self) {
matrix2 const & sigma = bp::extract<bivariate_gaussian const &>(self)().get_sigma();
return bn::from_data(
sigma.data(),
bn::dtype::get_builtin<double>(),
bp::make_tuple(2, 2),
bp::make_tuple(2 * sizeof(double), sizeof(double)),
self
);
}
/**
* To allow the constructor to work, we need to define some from-Python converters from NumPy arrays
* to the matrix/vector types. The rvalue-from-python functionality is not well-documented in Boost.Python
* itself; you can learn more from boost/python/converter/rvalue_from_python_data.hpp.
*/
/**
* We start with two functions that just copy a NumPy array into matrix/vector objects. These will be used
* in the templated converted below. The first just uses the operator[] overloads provided by
* bp::object.
*/
static void copy_ndarray_to_mv2(bn::ndarray const & array, vector2 & vec) {
vec[0] = bp::extract<double>(array[0]);
vec[1] = bp::extract<double>(array[1]);
}
/**
* Here, we'll take the alternate approach of using the strides to access the array's memory directly.
* This can be much faster for large arrays.
*/
static void copy_ndarray_to_mv2(bn::ndarray const & array, matrix2 & mat) {
// Unfortunately, get_strides() can't be inlined, so it's best to call it once up-front.
Py_intptr_t const * strides = array.get_strides();
for (int i = 0; i < 2; ++i) {
for (int j = 0; j < 2; ++j) {
mat(i, j) = *reinterpret_cast<double const *>(array.get_data() + i * strides[0] + j * strides[1]);
}
}
}
/**
* Here's the actual converter. Because we've separated the differences into the above functions,
* we can write a single template class that works for both matrix2 and vector2.
*/
template <typename T, int N>
struct mv2_from_python {
/**
* Register the converter.
*/
mv2_from_python() {
bp::converter::registry::push_back(
&convertible,
&construct,
bp::type_id< T >()
);
}
/**
* Test to see if we can convert this to the desired type; if not return zero.
* If we can convert, returned pointer can be used by construct().
*/
static void * convertible(PyObject * p) {
try {
bp::object obj(bp::handle<>(bp::borrowed(p)));
std::auto_ptr<bn::ndarray> array(
new bn::ndarray(
bn::from_object(obj, bn::dtype::get_builtin<double>(), N, N, bn::ndarray::V_CONTIGUOUS)
)
);
if (array->shape(0) != 2) return 0;
if (N == 2 && array->shape(1) != 2) return 0;
return array.release();
} catch (bp::error_already_set & err) {
bp::handle_exception();
return 0;
}
}
/**
* Finish the conversion by initializing the C++ object into memory prepared by Boost.Python.
*/
static void construct(PyObject * obj, bp::converter::rvalue_from_python_stage1_data * data) {
// Extract the array we passed out of the convertible() member function.
std::auto_ptr<bn::ndarray> array(reinterpret_cast<bn::ndarray*>(data->convertible));
// Find the memory block Boost.Python has prepared for the result.
typedef bp::converter::rvalue_from_python_storage<T> storage_t;
storage_t * storage = reinterpret_cast<storage_t*>(data);
// Use placement new to initialize the result.
T * m_or_v = new (storage->storage.bytes) T();
// Fill the result with the values from the NumPy array.
copy_ndarray_to_mv2(*array, *m_or_v);
// Finish up.
data->convertible = storage->storage.bytes;
}
};
BOOST_PYTHON_MODULE(gaussian) {
bn::initialize();
// Register the from-python converters
mv2_from_python< vector2, 1 >();
mv2_from_python< matrix2, 2 >();
typedef double (bivariate_gaussian::*call_vector)(vector2 const &) const;
bp::class_<bivariate_gaussian>("bivariate_gaussian", bp::init<bivariate_gaussian const &>())
// Declare the constructor (wouldn't work without the from-python converters).
.def(bp::init< vector2 const &, matrix2 const & >())
// Use our custom reference-counting getters
.add_property("mu", &py_get_mu)
.add_property("sigma", &py_get_sigma)
// First overload accepts a two-element array argument
.def("__call__", (call_vector)&bivariate_gaussian::operator())
// This overload works like a binary NumPy universal function: you can pass
// in scalars or arrays, and the C++ function will automatically be called
// on each element of an array argument.
.def("__call__", bn::binary_ufunc<bivariate_gaussian,double,double,double>::make())
;
}

71
example/numpy/ndarray.cpp Normal file
View File

@@ -0,0 +1,71 @@
// Copyright Ankit Daftery 2011-2012.
// 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)
/**
* @brief An example to show how to create ndarrays using arbitrary Python sequences.
*
* The Python sequence could be any object whose __array__ method returns an array, or any
* (nested) sequence. This example also shows how to create arrays using both unit and
* non-unit strides.
*/
#include <boost/python/numpy.hpp>
#include <iostream>
namespace p = boost::python;
namespace np = boost::python::numpy;
#if _MSC_VER
using boost::uint8_t;
#endif
int main(int argc, char **argv)
{
// Initialize the Python runtime.
Py_Initialize();
// Initialize NumPy
np::initialize();
// Create an ndarray from a simple tuple
p::object tu = p::make_tuple('a','b','c') ;
np::ndarray example_tuple = np::array (tu) ;
// and from a list
p::list l ;
np::ndarray example_list = np::array (l) ;
// Optionally, you can also specify a dtype
np::dtype dt = np::dtype::get_builtin<int>();
np::ndarray example_list1 = np::array (l,dt);
// You can also create an array by supplying data.First,create an integer array
int data[] = {1,2,3,4} ;
// Create a shape, and strides, needed by the function
p::tuple shape = p::make_tuple(4) ;
p::tuple stride = p::make_tuple(4) ;
// The function also needs an owner, to keep track of the data array passed. Passing none is dangerous
p::object own ;
// The from_data function takes the data array, datatype,shape,stride and owner as arguments
// and returns an ndarray
np::ndarray data_ex = np::from_data(data,dt,shape,stride,own);
// Print the ndarray we created
std::cout << "Single dimensional array ::" << std::endl << p::extract < char const * > (p::str(data_ex)) << std::endl ;
// Now lets make an 3x2 ndarray from a multi-dimensional array using non-unit strides
// First lets create a 3x4 array of 8-bit integers
uint8_t mul_data[][4] = {{1,2,3,4},{5,6,7,8},{1,3,5,7}};
// Now let's create an array of 3x2 elements, picking the first and third elements from each row
// For that, the shape will be 3x2
shape = p::make_tuple(3,2) ;
// The strides will be 4x2 i.e. 4 bytes to go to the next desired row, and 2 bytes to go to the next desired column
stride = p::make_tuple(4,2) ;
// Get the numpy dtype for the built-in 8-bit integer data type
np::dtype dt1 = np::dtype::get_builtin<uint8_t>();
// First lets create and print out the ndarray as is
np::ndarray mul_data_ex = np::from_data(mul_data,dt1, p::make_tuple(3,4),p::make_tuple(4,1),p::object());
std::cout << "Original multi dimensional array :: " << std::endl << p::extract < char const * > (p::str(mul_data_ex)) << std::endl ;
// Now create the new ndarray using the shape and strides
mul_data_ex = np::from_data(mul_data,dt1, shape,stride,p::object());
// Print out the array we created using non-unit strides
std::cout << "Selective multidimensional array :: "<<std::endl << p::extract < char const * > (p::str(mul_data_ex)) << std::endl ;
}

32
example/numpy/simple.cpp Normal file
View File

@@ -0,0 +1,32 @@
// Copyright 2011 Stefan Seefeld.
// 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/python/numpy.hpp>
#include <iostream>
namespace p = boost::python;
namespace np = boost::python::numpy;
int main(int argc, char **argv)
{
// Initialize the Python runtime.
Py_Initialize();
// Initialize NumPy
np::initialize();
// Create a 3x3 shape...
p::tuple shape = p::make_tuple(3, 3);
// ...as well as a type for C++ float
np::dtype dtype = np::dtype::get_builtin<float>();
// Construct an array with the above shape and type
np::ndarray a = np::zeros(shape, dtype);
// Construct an empty array with the above shape and dtype as well
np::ndarray b = np::empty(shape,dtype);
// Print the array
std::cout << "Original array:\n" << p::extract<char const *>(p::str(a)) << std::endl;
// Reshape the array into a 1D array
a = a.reshape(p::make_tuple(9));
// Print it again.
std::cout << "Reshaped array:\n" << p::extract<char const *>(p::str(a)) << std::endl;
}

86
example/numpy/ufunc.cpp Normal file
View File

@@ -0,0 +1,86 @@
// Copyright Ankit Daftery 2011-2012.
// 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)
/**
* @brief An example to demonstrate use of universal functions or ufuncs
*
*
* @todo Calling the overloaded () operator is in a roundabout manner, find a simpler way
* None of the methods like np::add, np::multiply etc are supported as yet
*/
#include <boost/python/numpy.hpp>
#include <iostream>
namespace p = boost::python;
namespace np = boost::python::numpy;
// Create the structs necessary to implement the ufuncs
// The typedefs *must* be made
struct UnarySquare
{
typedef double argument_type;
typedef double result_type;
double operator()(double r) const { return r * r;}
};
struct BinarySquare
{
typedef double first_argument_type;
typedef double second_argument_type;
typedef double result_type;
double operator()(double a,double b) const { return (a*a + b*b) ; }
};
int main(int argc, char **argv)
{
// Initialize the Python runtime.
Py_Initialize();
// Initialize NumPy
np::initialize();
// Expose the struct UnarySquare to Python as a class, and let ud be the class object
p::object ud = p::class_<UnarySquare, boost::shared_ptr<UnarySquare> >("UnarySquare")
.def("__call__", np::unary_ufunc<UnarySquare>::make());
// Let inst be an instance of the class ud
p::object inst = ud();
// Use the "__call__" method to call the overloaded () operator and print the value
std::cout << "Square of unary scalar 1.0 is " << p::extract <char const * > (p::str(inst.attr("__call__")(1.0))) << std::endl ;
// Create an array in C++
int arr[] = {1,2,3,4} ;
// ..and use it to create the ndarray in Python
np::ndarray demo_array = np::from_data(arr, np::dtype::get_builtin<int>() , p::make_tuple(4), p::make_tuple(4), p::object());
// Print out the demo array
std::cout << "Demo array is " << p::extract <char const * > (p::str(demo_array)) << std::endl ;
// Call the "__call__" method to perform the operation and assign the value to result_array
p::object result_array = inst.attr("__call__")(demo_array) ;
// Print the resultant array
std::cout << "Square of demo array is " << p::extract <char const * > (p::str(result_array)) << std::endl ;
// Lets try the same with a list
p::list li ;
li.append(3);
li.append(7);
// Print out the demo list
std::cout << "Demo list is " << p::extract <char const * > (p::str(li)) << std::endl ;
// Call the ufunc for the list
result_array = inst.attr("__call__")(li) ;
// And print the list out
std::cout << "Square of demo list is " << p::extract <char const * > (p::str(result_array)) << std::endl ;
// Now lets try Binary ufuncs
// Expose the struct BinarySquare to Python as a class, and let ud be the class object
ud = p::class_<BinarySquare, boost::shared_ptr<BinarySquare> >("BinarySquare")
.def("__call__", np::binary_ufunc<BinarySquare>::make());
// Again initialise inst as an instance of the class ud
inst = ud();
// Print the two input listsPrint the two input lists
std::cout << "The two input list for binary ufunc are " << std::endl << p::extract <char const * > (p::str(demo_array)) << std::endl << p::extract <char const * > (p::str(demo_array)) << std::endl ;
// Call the binary ufunc taking demo_array as both inputs
result_array = inst.attr("__call__")(demo_array,demo_array) ;
std::cout << "Square of list with binary ufunc is " << p::extract <char const * > (p::str(result_array)) << std::endl ;
}

135
example/numpy/wrap.cpp Normal file
View File

@@ -0,0 +1,135 @@
// Copyright Jim Bosch 2011-2012.
// 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)
/**
* A simple example showing how to wrap a couple of C++ functions that
* operate on 2-d arrays into Python functions that take NumPy arrays
* as arguments.
*
* If you find have a lot of such functions to wrap, you may want to
* create a C++ array type (or use one of the many existing C++ array
* libraries) that maps well to NumPy arrays and create Boost.Python
* converters. There's more work up front than the approach here,
* but much less boilerplate per function. See the "Gaussian" example
* included with Boost.NumPy for an example of custom converters, or
* take a look at the "ndarray" project on GitHub for a more complete,
* high-level solution.
*
* Note that we're using embedded Python here only to make a convenient
* self-contained example; you could just as easily put the wrappers
* in a regular C++-compiled module and imported them in regular
* Python. Again, see the Gaussian demo for an example.
*/
#include <boost/python/numpy.hpp>
#include <boost/scoped_array.hpp>
#include <iostream>
namespace p = boost::python;
namespace np = boost::python::numpy;
// This is roughly the most efficient way to write a C/C++ function that operates
// on a 2-d NumPy array - operate directly on the array by incrementing a pointer
// with the strides.
void fill1(double * array, int rows, int cols, int row_stride, int col_stride) {
double * row_iter = array;
double n = 0.0; // just a counter we'll fill the array with.
for (int i = 0; i < rows; ++i, row_iter += row_stride) {
double * col_iter = row_iter;
for (int j = 0; j < cols; ++j, col_iter += col_stride) {
*col_iter = ++n;
}
}
}
// Here's a simple wrapper function for fill1. It requires that the passed
// NumPy array be exactly what we're looking for - no conversion from nested
// sequences or arrays with other data types, because we want to modify it
// in-place.
void wrap_fill1(np::ndarray const & array) {
if (array.get_dtype() != np::dtype::get_builtin<double>()) {
PyErr_SetString(PyExc_TypeError, "Incorrect array data type");
p::throw_error_already_set();
}
if (array.get_nd() != 2) {
PyErr_SetString(PyExc_TypeError, "Incorrect number of dimensions");
p::throw_error_already_set();
}
fill1(reinterpret_cast<double*>(array.get_data()),
array.shape(0), array.shape(1),
array.strides(0) / sizeof(double), array.strides(1) / sizeof(double));
}
// Another fill function that takes a double**. This is less efficient, because
// it's not the native NumPy data layout, but it's common enough in C/C++ that
// it's worth its own example. This time we don't pass the strides, and instead
// in wrap_fill2 we'll require the C_CONTIGUOUS bitflag, which guarantees that
// the column stride is 1 and the row stride is the number of columns. That
// restricts the arrays that can be passed to fill2 (it won't work on most
// subarray views or transposes, for instance).
void fill2(double ** array, int rows, int cols) {
double n = 0.0; // just a counter we'll fill the array with.
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < cols; ++j) {
array[i][j] = ++n;
}
}
}
// Here's the wrapper for fill2; it's a little more complicated because we need
// to check the flags and create the array of pointers.
void wrap_fill2(np::ndarray const & array) {
if (array.get_dtype() != np::dtype::get_builtin<double>()) {
PyErr_SetString(PyExc_TypeError, "Incorrect array data type");
p::throw_error_already_set();
}
if (array.get_nd() != 2) {
PyErr_SetString(PyExc_TypeError, "Incorrect number of dimensions");
p::throw_error_already_set();
}
if (!(array.get_flags() & np::ndarray::C_CONTIGUOUS)) {
PyErr_SetString(PyExc_TypeError, "Array must be row-major contiguous");
p::throw_error_already_set();
}
double * iter = reinterpret_cast<double*>(array.get_data());
int rows = array.shape(0);
int cols = array.shape(1);
boost::scoped_array<double*> ptrs(new double*[rows]);
for (int i = 0; i < rows; ++i, iter += cols) {
ptrs[i] = iter;
}
fill2(ptrs.get(), array.shape(0), array.shape(1));
}
BOOST_PYTHON_MODULE(example) {
np::initialize(); // have to put this in any module that uses Boost.NumPy
p::def("fill1", wrap_fill1);
p::def("fill2", wrap_fill2);
}
int main(int argc, char **argv)
{
// This line makes our module available to the embedded Python intepreter.
# if PY_VERSION_HEX >= 0x03000000
PyImport_AppendInittab("example", &PyInit_example);
# else
PyImport_AppendInittab("example", &initexample);
# endif
// Initialize the Python runtime.
Py_Initialize();
PyRun_SimpleString(
"import example\n"
"import numpy\n"
"z1 = numpy.zeros((5,6), dtype=float)\n"
"z2 = numpy.zeros((4,3), dtype=float)\n"
"example.fill1(z1)\n"
"example.fill2(z2)\n"
"print z1\n"
"print z2\n"
);
Py_Finalize();
}

Binary file not shown.

View File

@@ -1,23 +1,15 @@
# Copyright David Abrahams 2006. 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)
# 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)
# Specify the path to the Boost project. If you move this project,
# adjust the path to refer to the Boost root directory.
use-project boost
: ../../../.. ;
# Set up the project-wide requirements that everything uses the
# boost_python library defined in the project whose global ID is
# /boost/python.
project boost-python-quickstart
: requirements <library>/boost/python//boost_python
<implicit-dependency>/boost//headers
: usage-requirements <implicit-dependency>/boost//headers
;
# Make the definition of the python-extension rule available
import python ;
import testing ;
project quickstart
: requirements
<location>.
;
# Declare a Python extension called hello.
python-extension extending : extending.cpp ;
@@ -25,8 +17,6 @@ python-extension extending : extending.cpp ;
# Declare an executable called embedding that embeds Python
exe embedding : embedding.cpp /python//python ;
import testing ;
# Declare a test of the extension module
testing.make-test run-pyd : extending test_extending.py : : test_ext ;

View File

@@ -1,7 +0,0 @@
# Copyright David Abrahams 2006. 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)
# Edit this path to point at the tools/build/src subdirectory of your
# Boost installation. Absolute paths work, too.
boost-build ../../../../tools/build/src ;

View File

@@ -1,6 +1,7 @@
#! /usr/bin/env python
# Copyright Stefan Seefeld 2006. 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)
print 'Hello World !'
print('Hello World !')
number = 42

View File

@@ -1,3 +1,4 @@
#! /usr/bin/env python
# Copyright Ralf W. Grosse-Kunstleve 2006. 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)

View File

@@ -1,49 +0,0 @@
// Copyright Ralf W. Grosse-Kunstleve 2002-2004. 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/python/module.hpp>
#include <boost/python/def.hpp>
#include <boost/python/tuple.hpp>
#include <boost/python/to_python_converter.hpp>
namespace { // Avoid cluttering the global namespace.
// Converts a std::pair instance to a Python tuple.
template <typename T1, typename T2>
struct std_pair_to_tuple
{
static PyObject* convert(std::pair<T1, T2> const& p)
{
return boost::python::incref(
boost::python::make_tuple(p.first, p.second).ptr());
}
static PyTypeObject const *get_pytype () {return &PyTuple_Type; }
};
// Helper for convenience.
template <typename T1, typename T2>
struct std_pair_to_python_converter
{
std_pair_to_python_converter()
{
boost::python::to_python_converter<
std::pair<T1, T2>,
std_pair_to_tuple<T1, T2>,
true //std_pair_to_tuple has get_pytype
>();
}
};
// Example function returning a std::pair.
std::pair<int, int>
foo() { return std::pair<int, int>(3, 5); }
} // namespace anonymous
BOOST_PYTHON_MODULE(std_pair_ext)
{
using namespace boost::python;
std_pair_to_python_converter<int, int>();
def("foo", foo);
}

View File

@@ -1,21 +0,0 @@
# Copyright Ralf W. Grosse-Kunstleve 2006. 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)
r'''>>> import getting_started1
>>> print getting_started1.greet()
hello, world
>>> number = 11
>>> print number, '*', number, '=', getting_started1.square(number)
11 * 11 = 121
'''
def run(args = None):
if args is not None:
import sys
sys.argv = args
import doctest, test_getting_started1
return doctest.testmod(test_getting_started1)
if __name__ == '__main__':
import sys
sys.exit(run()[0])

View File

@@ -1,34 +0,0 @@
# Copyright Ralf W. Grosse-Kunstleve 2006. 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)
r'''>>> from getting_started2 import *
>>> hi = hello('California')
>>> hi.greet()
'Hello from California'
>>> invite(hi)
'Hello from California! Please come soon!'
>>> hi.invite()
'Hello from California! Please come soon!'
>>> class wordy(hello):
... def greet(self):
... return hello.greet(self) + ', where the weather is fine'
...
>>> hi2 = wordy('Florida')
>>> hi2.greet()
'Hello from Florida, where the weather is fine'
>>> invite(hi2)
'Hello from Florida! Please come soon!'
'''
def run(args = None):
if args is not None:
import sys
sys.argv = args
import doctest, test_getting_started2
return doctest.testmod(test_getting_started2)
if __name__ == '__main__':
import sys
sys.exit(run()[0])

View File

@@ -1,6 +0,0 @@
# Copyright Ralf W. Grosse-Kunstleve 2006. 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)
import std_pair_ext
assert std_pair_ext.foo() == (3, 5)
print "OK"

19
example/tutorial/Jamfile Normal file
View File

@@ -0,0 +1,19 @@
# 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)
import python ;
project tutorial
: requirements
<location>.
;
python-extension hello_ext : hello.cpp ;
run-test hello : hello_ext hello.py ;
alias test : hello ;
explicit test ;

View File

@@ -1,51 +0,0 @@
# Copyright David Abrahams 2006. 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)
import python ;
if ! [ python.configured ]
{
ECHO "notice: no Python configured in user-config.jam" ;
ECHO "notice: will use default configuration" ;
using python ;
}
# Specify the path to the Boost project. If you move this project,
# adjust this path to refer to the Boost root directory.
use-project boost
: ../../../.. ;
# Set up the project-wide requirements that everything uses the
# boost_python library from the project whose global ID is
# /boost/python.
project
: requirements <library>/boost/python//boost_python
<implicit-dependency>/boost//headers
: usage-requirements <implicit-dependency>/boost//headers
;
# Declare the three extension modules. You can specify multiple
# source files after the colon separated by spaces.
python-extension hello_ext : hello.cpp ;
# Put the extension and Boost.Python DLL in the current directory, so
# that running script by hand works.
install convenient_copy
: hello_ext
: <install-dependencies>on <install-type>SHARED_LIB <install-type>PYTHON_EXTENSION
<location>.
;
# A little "rule" (function) to clean up the syntax of declaring tests
# of these extension modules.
local rule run-test ( test-name : sources + )
{
import testing ;
testing.make-test run-pyd : $(sources) : : $(test-name) ;
}
# Declare test targets
run-test hello : hello_ext hello.py ;

View File

@@ -1,7 +1,8 @@
#! /usr/bin/env python
# Copyright Joel de Guzman 2002-2007. 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)
# Hello World Example from the tutorial
import hello_ext
print hello_ext.greet()
print(hello_ext.greet())

View File

@@ -9,8 +9,11 @@
namespace boost { namespace python { namespace converter {
BOOST_PYTHON_DECL PyObject* checked_downcast_impl(PyObject*, PyTypeObject*);
BOOST_PYTHON_DECL inline
PyObject* checked_downcast_impl(PyObject *obj, PyTypeObject *type)
{
return (PyType_IsSubtype(Py_TYPE(obj), type) ? obj : NULL);
}
// Used as a base class for specializations which need to provide
// Python type checking capability.
template <class Object, PyTypeObject* pytype>

View File

@@ -1,19 +1,21 @@
// Copyright David Abrahams 2002.
// 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 REGISTERED_DWA2002710_HPP
# define REGISTERED_DWA2002710_HPP
# include <boost/python/type_id.hpp>
# include <boost/python/converter/registry.hpp>
# include <boost/python/converter/registrations.hpp>
# include <boost/type_traits/transform_traits.hpp>
# include <boost/type_traits/cv_traits.hpp>
# include <boost/type_traits/is_void.hpp>
# include <boost/detail/workaround.hpp>
# include <boost/python/type_id.hpp>
# include <boost/type.hpp>
#ifndef boost_python_converter_registered_hpp_
#define boost_python_converter_registered_hpp_
#include <boost/python/type_id.hpp>
#include <boost/python/converter/registry.hpp>
#include <boost/python/converter/registrations.hpp>
#include <boost/type_traits/transform_traits.hpp>
#include <boost/type_traits/cv_traits.hpp>
#include <boost/type_traits/is_void.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/type.hpp>
#include <memory>
#if defined(BOOST_PYTHON_TRACE_REGISTRY) \
|| defined(BOOST_PYTHON_CONVERTER_REGISTRY_APPLE_MACH_WORKAROUND)
# include <iostream>
@@ -75,7 +77,16 @@ namespace detail
{
registry::lookup_shared_ptr(type_id<shared_ptr<T> >());
}
#if __cplusplus >= 201103L
template <class T>
inline void
register_shared_ptr0(std::shared_ptr<T>*)
{
registry::lookup_shared_ptr(type_id<std::shared_ptr<T> >());
}
#endif
template <class T>
inline void
register_shared_ptr1(T const volatile*)
@@ -112,4 +123,4 @@ namespace detail
}}} // namespace boost::python::converter
#endif // REGISTERED_DWA2002710_HPP
#endif

View File

@@ -1,63 +1,65 @@
// Copyright David Abrahams 2002.
// 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 SHARED_PTR_FROM_PYTHON_DWA20021130_HPP
# define SHARED_PTR_FROM_PYTHON_DWA20021130_HPP
# include <boost/python/handle.hpp>
# include <boost/python/converter/shared_ptr_deleter.hpp>
# include <boost/python/converter/from_python.hpp>
# include <boost/python/converter/rvalue_from_python_data.hpp>
# include <boost/python/converter/registered.hpp>
#ifndef boost_python_converter_shared_ptr_from_python_hpp_
#define boost_python_converter_shared_ptr_from_python_hpp_
#include <boost/python/handle.hpp>
#include <boost/python/converter/shared_ptr_deleter.hpp>
#include <boost/python/converter/from_python.hpp>
#include <boost/python/converter/rvalue_from_python_data.hpp>
#include <boost/python/converter/registered.hpp>
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
# include <boost/python/converter/pytype_function.hpp>
#endif
# include <boost/shared_ptr.hpp>
#include <boost/shared_ptr.hpp>
#include <memory>
namespace boost { namespace python { namespace converter {
template <class T>
template <class T, template <typename> class SP>
struct shared_ptr_from_python
{
shared_ptr_from_python()
{
converter::registry::insert(&convertible, &construct, type_id<shared_ptr<T> >()
shared_ptr_from_python()
{
converter::registry::insert(&convertible, &construct, type_id<SP<T> >()
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
, &converter::expected_from_python_type_direct<T>::get_pytype
, &converter::expected_from_python_type_direct<T>::get_pytype
#endif
);
}
);
}
private:
static void* convertible(PyObject* p)
{
if (p == Py_None)
return p;
static void* convertible(PyObject* p)
{
if (p == Py_None)
return p;
return converter::get_lvalue_from_python(p, registered<T>::converters);
}
return converter::get_lvalue_from_python(p, registered<T>::converters);
}
static void construct(PyObject* source, rvalue_from_python_stage1_data* data)
static void construct(PyObject* source, rvalue_from_python_stage1_data* data)
{
void* const storage = ((converter::rvalue_from_python_storage<SP<T> >*)data)->storage.bytes;
// Deal with the "None" case.
if (data->convertible == source)
new (storage) SP<T>();
else
{
void* const storage = ((converter::rvalue_from_python_storage<shared_ptr<T> >*)data)->storage.bytes;
// Deal with the "None" case.
if (data->convertible == source)
new (storage) shared_ptr<T>();
else
{
boost::shared_ptr<void> hold_convertible_ref_count(
(void*)0, shared_ptr_deleter(handle<>(borrowed(source))) );
// use aliasing constructor
new (storage) shared_ptr<T>(
hold_convertible_ref_count,
static_cast<T*>(data->convertible));
}
data->convertible = storage;
SP<void> hold_convertible_ref_count(
(void*)0, shared_ptr_deleter(handle<>(borrowed(source))) );
// use aliasing constructor
new (storage) SP<T>(hold_convertible_ref_count,
static_cast<T*>(data->convertible));
}
data->convertible = storage;
}
};
}}} // namespace boost::python::converter
#endif // SHARED_PTR_FROM_PYTHON_DWA20021130_HPP
#endif

View File

@@ -1,14 +1,16 @@
// Copyright David Abrahams 2003.
// 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 SHARED_PTR_TO_PYTHON_DWA2003224_HPP
# define SHARED_PTR_TO_PYTHON_DWA2003224_HPP
# include <boost/python/refcount.hpp>
# include <boost/python/converter/shared_ptr_deleter.hpp>
# include <boost/shared_ptr.hpp>
# include <boost/get_pointer.hpp>
#ifndef boost_python_converter_shared_ptr_to_python_hpp_
#define boost_python_converter_shared_ptr_to_python_hpp_
#include <boost/python/refcount.hpp>
#include <boost/python/converter/shared_ptr_deleter.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/get_pointer.hpp>
namespace boost { namespace python { namespace converter {
@@ -23,6 +25,19 @@ PyObject* shared_ptr_to_python(shared_ptr<T> const& x)
return converter::registered<shared_ptr<T> const&>::converters.to_python(&x);
}
#if __cplusplus >= 201103L
template <class T>
PyObject* shared_ptr_to_python(std::shared_ptr<T> const& x)
{
if (!x)
return python::detail::none();
else if (shared_ptr_deleter* d = std::get_deleter<shared_ptr_deleter>(x))
return incref(get_pointer(d->owner));
else
return converter::registered<std::shared_ptr<T> const&>::converters.to_python(&x);
}
#endif
}}} // namespace boost::python::converter
#endif // SHARED_PTR_TO_PYTHON_DWA2003224_HPP
#endif

View File

@@ -64,31 +64,18 @@
#endif
#if defined(BOOST_PYTHON_DYNAMIC_LIB)
# if !defined(_WIN32) && !defined(__CYGWIN__) \
&& !defined(BOOST_PYTHON_USE_GCC_SYMBOL_VISIBILITY) \
&& BOOST_WORKAROUND(__GNUC__, >= 3) && (__GNUC_MINOR__ >=5 || __GNUC__ > 3)
# define BOOST_PYTHON_USE_GCC_SYMBOL_VISIBILITY 1
# endif
# if BOOST_PYTHON_USE_GCC_SYMBOL_VISIBILITY
# if defined(BOOST_SYMBOL_EXPORT)
# if defined(BOOST_PYTHON_SOURCE)
# define BOOST_PYTHON_DECL __attribute__ ((__visibility__("default")))
# define BOOST_PYTHON_DECL BOOST_SYMBOL_EXPORT
# define BOOST_PYTHON_DECL_FORWARD BOOST_SYMBOL_FORWARD_EXPORT
# define BOOST_PYTHON_DECL_EXCEPTION BOOST_EXCEPTION_EXPORT
# define BOOST_PYTHON_BUILD_DLL
# else
# define BOOST_PYTHON_DECL
# endif
# define BOOST_PYTHON_DECL_FORWARD
# define BOOST_PYTHON_DECL_EXCEPTION __attribute__ ((__visibility__("default")))
# elif (defined(_WIN32) || defined(__CYGWIN__))
# if defined(BOOST_PYTHON_SOURCE)
# define BOOST_PYTHON_DECL __declspec(dllexport)
# define BOOST_PYTHON_BUILD_DLL
# else
# define BOOST_PYTHON_DECL __declspec(dllimport)
# define BOOST_PYTHON_DECL BOOST_SYMBOL_IMPORT
# define BOOST_PYTHON_DECL_FORWARD BOOST_SYMBOL_FORWARD_IMPORT
# define BOOST_PYTHON_DECL_EXCEPTION BOOST_EXCEPTION_IMPORT
# endif
# endif
#endif
#ifndef BOOST_PYTHON_DECL
@@ -96,11 +83,11 @@
#endif
#ifndef BOOST_PYTHON_DECL_FORWARD
# define BOOST_PYTHON_DECL_FORWARD BOOST_PYTHON_DECL
# define BOOST_PYTHON_DECL_FORWARD
#endif
#ifndef BOOST_PYTHON_DECL_EXCEPTION
# define BOOST_PYTHON_DECL_EXCEPTION BOOST_PYTHON_DECL
# define BOOST_PYTHON_DECL_EXCEPTION
#endif
#if BOOST_WORKAROUND(__DECCXX_VER, BOOST_TESTED_AT(60590042))

View File

@@ -11,7 +11,7 @@
namespace boost { namespace python { namespace detail {
struct BOOST_PYTHON_DECL_FORWARD exception_handler;
struct exception_handler;
typedef function2<bool, exception_handler const&, function0<void> const&> handler_function;

View File

@@ -1,17 +1,23 @@
// Copyright David Abrahams 2003.
// 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 IS_SHARED_PTR_DWA2003224_HPP
# define IS_SHARED_PTR_DWA2003224_HPP
# include <boost/python/detail/is_xxx.hpp>
# include <boost/shared_ptr.hpp>
#ifndef boost_python_detail_is_shared_ptr_hpp_
#define boost_python_detail_is_shared_ptr_hpp_
#include <boost/python/detail/is_xxx.hpp>
#include <boost/shared_ptr.hpp>
namespace boost { namespace python { namespace detail {
BOOST_PYTHON_IS_XXX_DEF(shared_ptr, shared_ptr, 1)
#if __cplusplus >= 201103L
template <typename T>
struct is_shared_ptr<std::shared_ptr<T> > : std::true_type {};
#endif
}}} // namespace boost::python::detail
#endif // IS_SHARED_PTR_DWA2003224_HPP
#endif

View File

@@ -1,17 +1,28 @@
// Copyright David Abrahams 2003.
// 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 VALUE_IS_SHARED_PTR_DWA2003224_HPP
# define VALUE_IS_SHARED_PTR_DWA2003224_HPP
# include <boost/python/detail/value_is_xxx.hpp>
# include <boost/shared_ptr.hpp>
#ifndef boost_python_detail_value_is_shared_ptr_hpp_
#define boost_python_detail_value_is_shared_ptr_hpp_
#include <boost/python/detail/value_is_xxx.hpp>
#include <boost/python/detail/is_shared_ptr.hpp>
namespace boost { namespace python { namespace detail {
BOOST_PYTHON_VALUE_IS_XXX_DEF(shared_ptr, shared_ptr, 1)
template <class X_>
struct value_is_shared_ptr
{
static bool const value = is_shared_ptr<typename remove_cv<
typename remove_reference<X_>
::type>
::type>
::value;
typedef mpl::bool_<value> type;
};
}}} // namespace boost::python::detail
#endif // VALUE_IS_SHARED_PTR_DWA2003224_HPP

2
include/boost/python/detail/wrapper_base.hpp Executable file → Normal file
View File

@@ -14,7 +14,7 @@ class override;
namespace detail
{
class BOOST_PYTHON_DECL_FORWARD wrapper_base;
class wrapper_base;
namespace wrapper_base_ // ADL disabler
{

View File

@@ -14,7 +14,7 @@
namespace boost { namespace python {
struct BOOST_PYTHON_DECL_EXCEPTION error_already_set
struct BOOST_PYTHON_DECL error_already_set
{
virtual ~error_already_set();
};

View File

@@ -45,8 +45,13 @@ namespace detail
template <class U>
void dispatch(U* x, mpl::true_) const
{
std::auto_ptr<U> owner(x);
dispatch(owner, mpl::false_());
#if __cplusplus < 201103L
std::auto_ptr<U> owner(x);
dispatch(owner, mpl::false_());
#else
std::unique_ptr<U> owner(x);
dispatch(std::move(owner), mpl::false_());
#endif
}
template <class Ptr>
@@ -58,7 +63,11 @@ namespace detail
void* memory = holder::allocate(this->m_self, offsetof(instance_t, storage), sizeof(holder));
try {
#if __cplusplus < 201103L
(new (memory) holder(x))->install(this->m_self);
#else
(new (memory) holder(std::move(x)))->install(this->m_self);
#endif
}
catch(...) {
holder::deallocate(this->m_self, memory);

View File

@@ -0,0 +1,34 @@
// 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_python_numpy_hpp_
#define boost_python_numpy_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>
#include <boost/python/numpy/config.hpp>
namespace boost { namespace python { namespace numpy {
/**
* @brief Initialize the Numpy C-API
*
* This must be called before using anything in boost.numpy;
* It should probably be the first line inside BOOST_PYTHON_MODULE.
*
* @internal This just calls the Numpy C-API functions "import_array()"
* and "import_ufunc()", and then calls
* dtype::register_scalar_converters().
*/
BOOST_NUMPY_DECL void initialize(bool register_scalar_converters=true);
}}} // namespace boost::python::numpy
#endif

View File

@@ -0,0 +1,78 @@
// (C) Copyright Samuli-Petrus Korhonen 2017.
// 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)
//
// The author gratefully acknowleges the support of NMR Solutions, Inc., in
// producing this work.
// Revision History:
// 15 Feb 17 Initial version
#ifndef CONFIG_NUMPY20170215_H_
# define CONFIG_NUMPY20170215_H_
# include <boost/config.hpp>
/*****************************************************************************
*
* Set up dll import/export options:
*
****************************************************************************/
// backwards compatibility:
#ifdef BOOST_NUMPY_STATIC_LIB
# define BOOST_NUMPY_STATIC_LINK
# elif !defined(BOOST_NUMPY_DYNAMIC_LIB)
# define BOOST_NUMPY_DYNAMIC_LIB
#endif
#if defined(BOOST_NUMPY_DYNAMIC_LIB)
# if defined(BOOST_SYMBOL_EXPORT)
# if defined(BOOST_NUMPY_SOURCE)
# define BOOST_NUMPY_DECL BOOST_SYMBOL_EXPORT
# define BOOST_NUMPY_DECL_FORWARD BOOST_SYMBOL_FORWARD_EXPORT
# define BOOST_NUMPY_DECL_EXCEPTION BOOST_EXCEPTION_EXPORT
# define BOOST_NUMPY_BUILD_DLL
# else
# define BOOST_NUMPY_DECL BOOST_SYMBOL_IMPORT
# define BOOST_NUMPY_DECL_FORWARD BOOST_SYMBOL_FORWARD_IMPORT
# define BOOST_NUMPY_DECL_EXCEPTION BOOST_EXCEPTION_IMPORT
# endif
# endif
#endif
#ifndef BOOST_NUMPY_DECL
# define BOOST_NUMPY_DECL
#endif
#ifndef BOOST_NUMPY_DECL_FORWARD
# define BOOST_NUMPY_DECL_FORWARD
#endif
#ifndef BOOST_NUMPY_DECL_EXCEPTION
# define BOOST_NUMPY_DECL_EXCEPTION
#endif
// enable automatic library variant selection ------------------------------//
#if !defined(BOOST_NUMPY_SOURCE) && !defined(BOOST_ALL_NO_LIB) && !defined(BOOST_NUMPY_NO_LIB)
//
// Set the name of our library, this will get undef'ed by auto_link.hpp
// once it's done with it:
//
#define BOOST_LIB_NAME boost_numpy
//
// If we're importing code from a dll, then tell auto_link.hpp about it:
//
#ifdef BOOST_NUMPY_DYNAMIC_LIB
# define BOOST_DYN_LINK
#endif
//
// And include the header that does the work:
//
#include <boost/config/auto_link.hpp>
#endif // auto-linking disabled
#endif // CONFIG_NUMPY20170215_H_

View File

@@ -0,0 +1,118 @@
// 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_python_numpy_dtype_hpp_
#define boost_python_numpy_dtype_hpp_
/**
* @file boost/python/numpy/dtype.hpp
* @brief Object manager for Python's numpy.dtype class.
*/
#include <boost/python.hpp>
#include <boost/python/numpy/numpy_object_mgr_traits.hpp>
#include <boost/python/numpy/config.hpp>
#include <boost/mpl/for_each.hpp>
#include <boost/type_traits/add_pointer.hpp>
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 BOOST_NUMPY_DECL 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) : object(convert(arg, align)) {}
/**
* @brief Get the built-in numpy dtype associated with the given scalar template type.
*
* This is perhaps the most useful part of the numpy API: it returns the dtype object
* corresponding to a built-in C++ type. This should work for any integer or floating point
* type supported by numpy, and will also work for std::complex if
* sizeof(std::complex<T>) == 2*sizeof(T).
*
* It can also be useful for users to add explicit specializations for POD structs
* that return field-based dtypes.
*/
template <typename T> static dtype get_builtin();
/// @brief Return the size of the data type in bytes.
int get_itemsize() const;
/**
* @brief Compare two dtypes for equivalence.
*
* This is more permissive than equality tests. For instance, if long and int are the same
* size, the dtypes corresponding to each will be equivalent, but not equal.
*/
friend BOOST_NUMPY_DECL bool equivalent(dtype const & a, dtype const & b);
/**
* @brief Register from-Python converters for NumPy's built-in array scalar types.
*
* This is usually called automatically by initialize(), and shouldn't be called twice
* (doing so just adds unused converters to the Boost.Python registry).
*/
static void register_scalar_converters();
BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS(dtype, object);
};
BOOST_NUMPY_DECL bool equivalent(dtype const & a, dtype const & b);
namespace detail
{
template <int bits, bool isUnsigned> dtype get_int_dtype();
template <int bits> dtype get_float_dtype();
template <int bits> dtype get_complex_dtype();
template <typename T, bool isInt=boost::is_integral<T>::value>
struct builtin_dtype;
template <typename T>
struct builtin_dtype<T,true> {
static dtype get() { return get_int_dtype< 8*sizeof(T), boost::is_unsigned<T>::value >(); }
};
template <>
struct builtin_dtype<bool,true> {
static dtype get();
};
template <typename T>
struct builtin_dtype<T,false> {
static dtype get() { return get_float_dtype< 8*sizeof(T) >(); }
};
template <typename T>
struct builtin_dtype< std::complex<T>, false > {
static dtype get() { return get_complex_dtype< 16*sizeof(T) >(); }
};
} // namespace detail
template <typename T>
inline dtype dtype::get_builtin() { return detail::builtin_dtype<T>::get(); }
} // namespace boost::python::numpy
namespace converter {
NUMPY_OBJECT_MANAGER_TRAITS(numpy::dtype);
}}} // namespace boost::python::converter
#endif

View File

@@ -0,0 +1,35 @@
// 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_python_numpy_internal_hpp_
#define boost_python_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_PYTHON_NUMPY_INTERNAL
#define NO_IMPORT_ARRAY
#define NO_IMPORT_UFUNC
#else
#ifndef BOOST_PYTHON_NUMPY_INTERNAL_MAIN
ERROR_internal_hpp_is_for_internal_use_only
#endif
#endif
#define PY_ARRAY_UNIQUE_SYMBOL BOOST_NUMPY_ARRAY_API
#define PY_UFUNC_UNIQUE_SYMBOL BOOST_UFUNC_ARRAY_API
#include <numpy/arrayobject.h>
#include <numpy/ufuncobject.h>
#include <boost/python/numpy.hpp>
#define NUMPY_OBJECT_MANAGER_TRAITS_IMPL(pytype,manager) \
PyTypeObject const * object_manager_traits<manager>::get_pytype() { return &pytype; }
#endif

View File

@@ -0,0 +1,186 @@
// 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_python_numpy_invoke_matching_hpp_
#define boost_python_numpy_invoke_matching_hpp_
/**
* @brief Template invocation based on dtype matching.
*/
#include <boost/python/numpy/dtype.hpp>
#include <boost/python/numpy/ndarray.hpp>
#include <boost/mpl/integral_c.hpp>
namespace boost { namespace python { namespace numpy {
namespace detail
{
struct BOOST_NUMPY_DECL add_pointer_meta
{
template <typename T>
struct apply
{
typedef typename boost::add_pointer<T>::type type;
};
};
struct BOOST_NUMPY_DECL dtype_template_match_found {};
struct BOOST_NUMPY_DECL nd_template_match_found {};
template <typename Function>
struct dtype_template_invoker
{
template <typename T>
void operator()(T *) const
{
if (dtype::get_builtin<T>() == m_dtype)
{
m_func.Function::template apply<T>();
throw dtype_template_match_found();
}
}
dtype_template_invoker(dtype const & dtype_, Function func)
: m_dtype(dtype_), m_func(func) {}
private:
dtype const & m_dtype;
Function m_func;
};
template <typename Function>
struct dtype_template_invoker< boost::reference_wrapper<Function> >
{
template <typename T>
void operator()(T *) const
{
if (dtype::get_builtin<T>() == m_dtype)
{
m_func.Function::template apply<T>();
throw dtype_template_match_found();
}
}
dtype_template_invoker(dtype const & dtype_, Function & func)
: m_dtype(dtype_), m_func(func) {}
private:
dtype const & m_dtype;
Function & m_func;
};
template <typename Function>
struct nd_template_invoker
{
template <int N>
void operator()(boost::mpl::integral_c<int,N> *) const
{
if (m_nd == N)
{
m_func.Function::template apply<N>();
throw nd_template_match_found();
}
}
nd_template_invoker(int nd, Function func) : m_nd(nd), m_func(func) {}
private:
int m_nd;
Function m_func;
};
template <typename Function>
struct nd_template_invoker< boost::reference_wrapper<Function> >
{
template <int N>
void operator()(boost::mpl::integral_c<int,N> *) const
{
if (m_nd == N)
{
m_func.Function::template apply<N>();
throw nd_template_match_found();
}
}
nd_template_invoker(int nd, Function & func) : m_nd(nd), m_func(func) {}
private:
int m_nd;
Function & m_func;
};
} // namespace boost::python::numpy::detail
template <typename Sequence, typename Function>
void invoke_matching_nd(int nd, Function f)
{
detail::nd_template_invoker<Function> invoker(nd, f);
try { boost::mpl::for_each< Sequence, detail::add_pointer_meta >(invoker);}
catch (detail::nd_template_match_found &) { return;}
PyErr_SetString(PyExc_TypeError, "number of dimensions not found in template list.");
python::throw_error_already_set();
}
template <typename Sequence, typename Function>
void invoke_matching_dtype(dtype const & dtype_, Function f)
{
detail::dtype_template_invoker<Function> invoker(dtype_, f);
try { boost::mpl::for_each< Sequence, detail::add_pointer_meta >(invoker);}
catch (detail::dtype_template_match_found &) { return;}
PyErr_SetString(PyExc_TypeError, "dtype not found in template list.");
python::throw_error_already_set();
}
namespace detail
{
template <typename T, typename Function>
struct array_template_invoker_wrapper_2
{
template <int N>
void apply() const { m_func.Function::template apply<T,N>();}
array_template_invoker_wrapper_2(Function & func) : m_func(func) {}
private:
Function & m_func;
};
template <typename DimSequence, typename Function>
struct array_template_invoker_wrapper_1
{
template <typename T>
void apply() const { invoke_matching_nd<DimSequence>(m_nd, array_template_invoker_wrapper_2<T,Function>(m_func));}
array_template_invoker_wrapper_1(int nd, Function & func) : m_nd(nd), m_func(func) {}
private:
int m_nd;
Function & m_func;
};
template <typename DimSequence, typename Function>
struct array_template_invoker_wrapper_1< DimSequence, boost::reference_wrapper<Function> >
: public array_template_invoker_wrapper_1< DimSequence, Function >
{
array_template_invoker_wrapper_1(int nd, Function & func)
: array_template_invoker_wrapper_1< DimSequence, Function >(nd, func) {}
};
} // namespace boost::python::numpy::detail
template <typename TypeSequence, typename DimSequence, typename Function>
void invoke_matching_array(ndarray const & array_, Function f)
{
detail::array_template_invoker_wrapper_1<DimSequence,Function> wrapper(array_.get_nd(), f);
invoke_matching_dtype<TypeSequence>(array_.get_dtype(), wrapper);
}
}}} // namespace boost::python::numpy
#endif

View File

@@ -0,0 +1,84 @@
// 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_python_numpy_matrix_hpp_
#define boost_python_numpy_matrix_hpp_
/**
* @brief Object manager for numpy.matrix.
*/
#include <boost/python.hpp>
#include <boost/python/numpy/numpy_object_mgr_traits.hpp>
#include <boost/python/numpy/ndarray.hpp>
#include <boost/python/numpy/config.hpp>
namespace boost { namespace python { namespace numpy {
/**
* @brief A boost.python "object manager" (subclass of object) for numpy.matrix.
*
* @internal numpy.matrix is defined in Python, so object_manager_traits<matrix>::get_pytype()
* is implemented by importing numpy and getting the "matrix" attribute of the module.
* We then just hope that doesn't get destroyed while we need it, because if we put
* a dynamic python object in a static-allocated boost::python::object or handle<>,
* bad things happen when Python shuts down. I think this solution is safe, but I'd
* love to get that confirmed.
*/
class BOOST_NUMPY_DECL matrix : public ndarray
{
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(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(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;
/// \brief Copy the scalar (deep for all non-object fields).
matrix copy() const;
/// \brief Transpose the matrix.
matrix transpose() const;
};
/**
* @brief CallPolicies that causes a function that returns a numpy.ndarray to
* return a numpy.matrix instead.
*/
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::python::numpy
namespace converter
{
NUMPY_OBJECT_MANAGER_TRAITS(numpy::matrix);
}}} // namespace boost::python::converter
#endif

View File

@@ -0,0 +1,313 @@
// 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_python_numpy_ndarray_hpp_
#define boost_python_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/python/numpy/numpy_object_mgr_traits.hpp>
#include <boost/python/numpy/dtype.hpp>
#include <boost/python/numpy/config.hpp>
#include <vector>
namespace boost { namespace python { namespace numpy {
/**
* @brief A boost.python "object manager" (subclass of object) for numpy.ndarray.
*
* @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 BOOST_NUMPY_DECL ndarray : public object
{
/**
* @brief An internal struct that's byte-compatible with PyArrayObject.
*
* This is just a hack to allow inline access to this stuff while hiding numpy/arrayobject.h
* from the user.
*/
struct array_struct
{
PyObject_HEAD
char * data;
int nd;
Py_intptr_t * shape;
Py_intptr_t * strides;
PyObject * base;
PyObject * descr;
int flags;
PyObject * weakreflist;
};
/// @brief Return the held Python object as an array_struct.
array_struct * get_struct() const { return reinterpret_cast<array_struct*>(this->ptr()); }
public:
/**
* @brief Enum to represent (some) of Numpy's internal flags.
*
* These don't match the actual Numpy flag values; we can't get those without including
* numpy/arrayobject.h or copying them directly. That's very unfortunate.
*
* @todo I'm torn about whether this should be an enum. It's very convenient to not
* make these simple integer values for overloading purposes, but the need to
* define every possible combination and custom bitwise operators is ugly.
*/
enum bitflag
{
NONE=0x0, C_CONTIGUOUS=0x1, F_CONTIGUOUS=0x2, V_CONTIGUOUS=0x1|0x2,
ALIGNED=0x4, WRITEABLE=0x8, BEHAVED=0x4|0x8,
CARRAY_RO=0x1|0x4, CARRAY=0x1|0x4|0x8, CARRAY_MIS=0x1|0x8,
FARRAY_RO=0x2|0x4, FARRAY=0x2|0x4|0x8, FARRAY_MIS=0x2|0x8,
UPDATE_ALL=0x1|0x2|0x4, VARRAY=0x1|0x2|0x8, ALL=0x1|0x2|0x4|0x8
};
BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS(ndarray, object);
/// @brief Return a view of the scalar with the given dtype.
ndarray view(dtype const & dt) const;
/// @brief Copy the array, cast to a specified type.
ndarray astype(dtype const & dt) const;
/// @brief Copy the scalar (deep for all non-object fields).
ndarray copy() const;
/// @brief Return the size of the nth dimension.
Py_intptr_t shape(int n) const { return get_shape()[n]; }
/// @brief Return the stride of the nth dimension.
Py_intptr_t strides(int n) const { return get_strides()[n]; }
/**
* @brief Return the array's raw data pointer.
*
* This returns char so stride math works properly on it. It's pretty much
* expected that the user will have to reinterpret_cast it.
*/
char * get_data() const { return get_struct()->data; }
/// @brief Return the array's data-type descriptor object.
dtype get_dtype() const;
/// @brief Return the object that owns the array's data, or None if the array owns its own data.
object get_base() const;
/// @brief Set the object that owns the array's data. Use with care.
void set_base(object const & base);
/// @brief Return the shape of the array as an array of integers (length == get_nd()).
Py_intptr_t const * get_shape() const { return get_struct()->shape; }
/// @brief Return the stride of the array as an array of integers (length == get_nd()).
Py_intptr_t const * get_strides() const { return get_struct()->strides; }
/// @brief Return the number of array dimensions.
int get_nd() const { return get_struct()->nd; }
/// @brief Return the array flags.
bitflag get_flags() const;
/// @brief Reverse the dimensions of the array.
ndarray transpose() const;
/// @brief Eliminate any unit-sized dimensions.
ndarray squeeze() const;
/// @brief Equivalent to self.reshape(*shape) in Python.
ndarray reshape(python::tuple const & shape) const;
/**
* @brief If the array contains only a single element, return it as an array scalar; otherwise return
* the array.
*
* @internal This is simply a call to PyArray_Return();
*/
object scalarize() const;
};
/**
* @brief Construct a new array with the given shape and data type, with data initialized to zero.
*/
BOOST_NUMPY_DECL ndarray zeros(python::tuple const & shape, dtype const & dt);
BOOST_NUMPY_DECL ndarray zeros(int nd, Py_intptr_t const * shape, dtype const & dt);
/**
* @brief Construct a new array with the given shape and data type, with data left uninitialized.
*/
BOOST_NUMPY_DECL ndarray empty(python::tuple const & shape, dtype const & dt);
BOOST_NUMPY_DECL ndarray empty(int nd, Py_intptr_t const * shape, dtype const & dt);
/**
* @brief Construct a new array from an arbitrary Python sequence.
*
* @todo This does't seem to handle ndarray subtypes the same way that "numpy.array" does in Python.
*/
BOOST_NUMPY_DECL ndarray array(object const & obj);
BOOST_NUMPY_DECL ndarray array(object const & obj, dtype const & dt);
namespace detail
{
BOOST_NUMPY_DECL ndarray from_data_impl(void * data,
dtype const & dt,
std::vector<Py_intptr_t> const & shape,
std::vector<Py_intptr_t> const & strides,
object const & owner,
bool writeable);
template <typename Container>
ndarray from_data_impl(void * data,
dtype const & dt,
Container shape,
Container strides,
object const & owner,
bool writeable,
typename boost::enable_if< boost::is_integral<typename Container::value_type> >::type * enabled = NULL)
{
std::vector<Py_intptr_t> shape_(shape.begin(),shape.end());
std::vector<Py_intptr_t> strides_(strides.begin(), strides.end());
return from_data_impl(data, dt, shape_, strides_, owner, writeable);
}
BOOST_NUMPY_DECL ndarray from_data_impl(void * data,
dtype const & dt,
object const & shape,
object const & strides,
object const & owner,
bool writeable);
} // namespace boost::python::numpy::detail
/**
* @brief Construct a new ndarray object from a raw pointer.
*
* @param[in] data Raw pointer to the first element of the array.
* @param[in] dt Data type descriptor. Often retrieved with dtype::get_builtin().
* @param[in] shape Shape of the array as STL container of integers; must have begin() and end().
* @param[in] strides Shape of the array as STL container of integers; must have begin() and end().
* @param[in] owner An arbitray Python object that owns that data pointer. The array object will
* keep a reference to the object, and decrement it's reference count when the
* array goes out of scope. Pass None at your own peril.
*
* @todo Should probably take ranges of iterators rather than actual container objects.
*/
template <typename Container>
inline ndarray from_data(void * data,
dtype const & dt,
Container shape,
Container strides,
python::object const & owner)
{
return numpy::detail::from_data_impl(data, dt, shape, strides, owner, true);
}
/**
* @brief Construct a new ndarray object from a raw pointer.
*
* @param[in] data Raw pointer to the first element of the array.
* @param[in] dt Data type descriptor. Often retrieved with dtype::get_builtin().
* @param[in] shape Shape of the array as STL container of integers; must have begin() and end().
* @param[in] strides Shape of the array as STL container of integers; must have begin() and end().
* @param[in] owner An arbitray Python object that owns that data pointer. The array object will
* keep a reference to the object, and decrement it's reference count when the
* array goes out of scope. Pass None at your own peril.
*
* This overload takes a const void pointer and sets the "writeable" flag of the array to false.
*
* @todo Should probably take ranges of iterators rather than actual container objects.
*/
template <typename Container>
inline ndarray from_data(void const * data,
dtype const & dt,
Container shape,
Container strides,
python::object const & owner)
{
return numpy::detail::from_data_impl(const_cast<void*>(data), dt, shape, strides, owner, false);
}
/**
* @brief Transform an arbitrary object into a numpy array with the given requirements.
*
* @param[in] obj An arbitrary python object to convert. Arrays that meet the requirements
* will be passed through directly.
* @param[in] dt Data type descriptor. Often retrieved with dtype::get_builtin().
* @param[in] nd_min Minimum number of dimensions.
* @param[in] nd_max Maximum number of dimensions.
* @param[in] flags Bitwise OR of flags specifying additional requirements.
*/
BOOST_NUMPY_DECL ndarray from_object(object const & obj,
dtype const & dt,
int nd_min,
int nd_max,
ndarray::bitflag flags=ndarray::NONE);
BOOST_NUMPY_DECL 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);
}
BOOST_NUMPY_DECL inline ndarray from_object(object const & obj,
dtype const & dt,
ndarray::bitflag flags=ndarray::NONE)
{
return from_object(obj, dt, 0, 0, flags);
}
BOOST_NUMPY_DECL ndarray from_object(object const & obj,
int nd_min,
int nd_max,
ndarray::bitflag flags=ndarray::NONE);
BOOST_NUMPY_DECL inline ndarray from_object(object const & obj,
int nd,
ndarray::bitflag flags=ndarray::NONE)
{
return from_object(obj, nd, nd, flags);
}
BOOST_NUMPY_DECL inline ndarray from_object(object const & obj,
ndarray::bitflag flags=ndarray::NONE)
{
return from_object(obj, 0, 0, flags);
}
BOOST_NUMPY_DECL inline ndarray::bitflag operator|(ndarray::bitflag a,
ndarray::bitflag b)
{
return ndarray::bitflag(int(a) | int(b));
}
BOOST_NUMPY_DECL inline ndarray::bitflag operator&(ndarray::bitflag a,
ndarray::bitflag b)
{
return ndarray::bitflag(int(a) & int(b));
}
} // namespace boost::python::numpy
namespace converter
{
NUMPY_OBJECT_MANAGER_TRAITS(numpy::ndarray);
}}} // namespace boost::python::converter
#endif

View File

@@ -0,0 +1,38 @@
// 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_python_numpy_numpy_object_mgr_traits_hpp_
#define boost_python_numpy_numpy_object_mgr_traits_hpp_
#include <boost/python/numpy/config.hpp>
/**
* @brief Macro that specializes object_manager_traits by requiring a
* source-file implementation of get_pytype().
*/
#define NUMPY_OBJECT_MANAGER_TRAITS(manager) \
template <> \
struct BOOST_NUMPY_DECL object_manager_traits<manager> \
{ \
BOOST_STATIC_CONSTANT(bool, is_specialized = true); \
static inline python::detail::new_reference adopt(PyObject* x) \
{ \
return python::detail::new_reference(python::pytype_check((PyTypeObject*)get_pytype(), x)); \
} \
static bool check(PyObject* x) \
{ \
return ::PyObject_IsInstance(x, (PyObject*)get_pytype()); \
} \
static manager* checked_downcast(PyObject* x) \
{ \
return python::downcast<manager>((checked_downcast_impl)(x, (PyTypeObject*)get_pytype())); \
} \
static PyTypeObject const * get_pytype(); \
}
#endif

View File

@@ -0,0 +1,58 @@
// 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_python_numpy_scalars_hpp_
#define boost_python_numpy_scalars_hpp_
/**
* @brief Object managers for array scalars (currently only numpy.void is implemented).
*/
#include <boost/python.hpp>
#include <boost/python/numpy/numpy_object_mgr_traits.hpp>
#include <boost/python/numpy/dtype.hpp>
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 BOOST_NUMPY_DECL void_ : public object
{
static python::detail::new_reference convert(object_cref arg, bool align);
public:
/**
* @brief Construct a new array scalar with the given size and void dtype.
*
* Data is initialized to zero. One can create a standalone scalar object
* with a certain dtype "dt" with:
* @code
* void_ scalar = void_(dt.get_itemsize()).view(dt);
* @endcode
*/
explicit void_(Py_ssize_t size);
BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS(void_, object);
/// @brief Return a view of the scalar with the given dtype.
void_ view(dtype const & dt) const;
/// @brief Copy the scalar (deep for all non-object fields).
void_ copy() const;
};
} // namespace boost::python::numpy
namespace converter
{
NUMPY_OBJECT_MANAGER_TRAITS(numpy::void_);
}}} // namespace boost::python::converter
#endif

View File

@@ -0,0 +1,206 @@
// 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_python_numpy_ufunc_hpp_
#define boost_python_numpy_ufunc_hpp_
/**
* @brief Utilities to create ufunc-like broadcasting functions out of C++ functors.
*/
#include <boost/python.hpp>
#include <boost/python/numpy/numpy_object_mgr_traits.hpp>
#include <boost/python/numpy/dtype.hpp>
#include <boost/python/numpy/ndarray.hpp>
#include <boost/python/numpy/config.hpp>
namespace boost { namespace python { namespace numpy {
/**
* @brief A boost.python "object manager" (subclass of object) for PyArray_MultiIter.
*
* multi_iter is a Python object, but a very low-level one. It should generally only be used
* in loops of the form:
* @code
* while (iter.not_done()) {
* ...
* iter.next();
* }
* @endcode
*
* @todo I can't tell if this type is exposed in Python anywhere; if it is, we should use that name.
* It's more dangerous than most object managers, however - maybe it actually belongs in
* a detail namespace?
*/
class BOOST_NUMPY_DECL multi_iter : public object
{
public:
BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS(multi_iter, object);
/// @brief Increment the iterator.
void next();
/// @brief Check if the iterator is at its end.
bool not_done() const;
/// @brief Return a pointer to the element of the nth broadcasted array.
char * get_data(int n) const;
/// @brief Return the number of dimensions of the broadcasted array expression.
int get_nd() const;
/// @brief Return the shape of the broadcasted array expression as an array of integers.
Py_intptr_t const * get_shape() const;
/// @brief Return the shape of the broadcasted array expression in the nth dimension.
Py_intptr_t shape(int n) const;
};
/// @brief Construct a multi_iter over a single sequence or scalar object.
BOOST_NUMPY_DECL multi_iter make_multi_iter(object const & a1);
/// @brief Construct a multi_iter by broadcasting two objects.
BOOST_NUMPY_DECL multi_iter make_multi_iter(object const & a1, object const & a2);
/// @brief Construct a multi_iter by broadcasting three objects.
BOOST_NUMPY_DECL 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
* Python object.
*
* Typical usage looks like this:
* @code
* struct TimesPI
* {
* typedef double argument_type;
* typedef double result_type;
* double operator()(double input) const { return input * M_PI; }
* };
*
* BOOST_PYTHON_MODULE(example)
* {
* class_< TimesPI >("TimesPI")
* .def("__call__", unary_ufunc<TimesPI>::make());
* }
* @endcode
*
*/
template <typename TUnaryFunctor,
typename TArgument=typename TUnaryFunctor::argument_type,
typename TResult=typename TUnaryFunctor::result_type>
struct unary_ufunc
{
/**
* @brief A C++ function with object arguments that broadcasts its arguments before
* passing them to the underlying C++ functor.
*/
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 != 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);
while (iter.not_done())
{
TArgument * argument = reinterpret_cast<TArgument*>(iter.get_data(0));
TResult * result = reinterpret_cast<TResult*>(iter.get_data(1));
*result = self(*argument);
iter.next();
}
return out_array.scalarize();
}
/**
* @brief Construct a boost.python function object from call() with reasonable keyword names.
*
* Users will often want to specify their own keyword names with the same signature, but this
* is a convenient shortcut.
*/
static object make()
{
return make_function(call, default_call_policies(), (arg("input"), arg("output")=object()));
}
};
/**
* @brief Helps wrap a C++ functor taking a pair of scalar arguments as a broadcasting ufunc-like
* Python object.
*
* Typical usage looks like this:
* @code
* struct CosSum
* {
* typedef double first_argument_type;
* typedef double second_argument_type;
* typedef double result_type;
* double operator()(double input1, double input2) const { return std::cos(input1 + input2); }
* };
*
* BOOST_PYTHON_MODULE(example)
* {
* class_< CosSum >("CosSum")
* .def("__call__", binary_ufunc<CosSum>::make());
* }
* @endcode
*
*/
template <typename TBinaryFunctor,
typename TArgument1=typename TBinaryFunctor::first_argument_type,
typename TArgument2=typename TBinaryFunctor::second_argument_type,
typename TResult=typename TBinaryFunctor::result_type>
struct binary_ufunc
{
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>();
dtype out_dtype = dtype::get_builtin<TResult>();
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 != 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);
while (iter.not_done())
{
TArgument1 * argument1 = reinterpret_cast<TArgument1*>(iter.get_data(0));
TArgument2 * argument2 = reinterpret_cast<TArgument2*>(iter.get_data(1));
TResult * result = reinterpret_cast<TResult*>(iter.get_data(2));
*result = self(*argument1, *argument2);
iter.next();
}
return out_array.scalarize();
}
static object make()
{
return make_function(call, default_call_policies(),
(arg("input1"), arg("input2"), arg("output")=object()));
}
};
} // namespace boost::python::numpy
namespace converter
{
NUMPY_OBJECT_MANAGER_TRAITS(numpy::multi_iter);
}}} // namespace boost::python::converter
#endif

View File

@@ -1,43 +1,46 @@
// Copyright David Abrahams 2004. 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 CLASS_METADATA_DWA2004719_HPP
# define CLASS_METADATA_DWA2004719_HPP
# include <boost/python/converter/shared_ptr_from_python.hpp>
// Copyright David Abrahams 2004.
// 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/python/object/inheritance.hpp>
# include <boost/python/object/class_wrapper.hpp>
# include <boost/python/object/make_instance.hpp>
# include <boost/python/object/value_holder.hpp>
# include <boost/python/object/pointer_holder.hpp>
# include <boost/python/object/make_ptr_instance.hpp>
#ifndef boost_python_object_class_metadata_hpp_
#define boost_python_object_class_metadata_hpp_
# include <boost/python/detail/force_instantiate.hpp>
# include <boost/python/detail/not_specified.hpp>
#include <boost/python/converter/shared_ptr_from_python.hpp>
#include <boost/python/object/inheritance.hpp>
#include <boost/python/object/class_wrapper.hpp>
#include <boost/python/object/make_instance.hpp>
#include <boost/python/object/value_holder.hpp>
#include <boost/python/object/pointer_holder.hpp>
#include <boost/python/object/make_ptr_instance.hpp>
# include <boost/python/has_back_reference.hpp>
# include <boost/python/bases.hpp>
#include <boost/python/detail/force_instantiate.hpp>
#include <boost/python/detail/not_specified.hpp>
# include <boost/type_traits/add_pointer.hpp>
# include <boost/type_traits/is_convertible.hpp>
# include <boost/type_traits/is_polymorphic.hpp>
#include <boost/python/has_back_reference.hpp>
#include <boost/python/bases.hpp>
# include <boost/mpl/if.hpp>
# include <boost/mpl/eval_if.hpp>
# include <boost/mpl/bool.hpp>
# include <boost/mpl/or.hpp>
# include <boost/mpl/identity.hpp>
# include <boost/mpl/for_each.hpp>
# include <boost/mpl/placeholders.hpp>
# include <boost/mpl/single_view.hpp>
#include <boost/type_traits/add_pointer.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/type_traits/is_polymorphic.hpp>
# include <boost/mpl/assert.hpp>
# include <boost/type_traits/is_same.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/or.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/mpl/for_each.hpp>
#include <boost/mpl/placeholders.hpp>
#include <boost/mpl/single_view.hpp>
# include <boost/type_traits/is_convertible.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/type_traits/is_same.hpp>
# include <boost/noncopyable.hpp>
# include <boost/detail/workaround.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/noncopyable.hpp>
#include <boost/detail/workaround.hpp>
namespace boost { namespace python { namespace objects {
@@ -80,18 +83,22 @@ struct register_base_of
// Preamble of register_class. Also used for callback classes, which
// need some registration of their own.
//
template <class T, class Bases>
inline void register_shared_ptr_from_python_and_casts(T*, Bases)
{
// Constructor performs registration
python::detail::force_instantiate(converter::shared_ptr_from_python<T>());
// Constructor performs registration
python::detail::force_instantiate(converter::shared_ptr_from_python<T, boost::shared_ptr>());
#if __cplusplus >= 201103L
python::detail::force_instantiate(converter::shared_ptr_from_python<T, std::shared_ptr>());
#endif
//
// register all up/downcasts here. We're using the alternate
// interface to mpl::for_each to avoid an MSVC 6 bug.
//
register_dynamic_id<T>();
mpl::for_each(register_base_of<T>(), (Bases*)0, (add_pointer<mpl::_>*)0);
//
// register all up/downcasts here. We're using the alternate
// interface to mpl::for_each to avoid an MSVC 6 bug.
//
register_dynamic_id<T>();
mpl::for_each(register_base_of<T>(), (Bases*)0, (add_pointer<mpl::_>*)0);
}
//
@@ -220,8 +227,7 @@ struct class_metadata
template <class T2, class Callback>
inline static void register_aux2(T2*, Callback)
{
objects::register_shared_ptr_from_python_and_casts((T2*)0, bases());
objects::register_shared_ptr_from_python_and_casts((T2*)0, bases());
class_metadata::maybe_register_callback_class((T2*)0, Callback());
class_metadata::maybe_register_class_to_python((T2*)0, is_noncopyable());
@@ -282,9 +288,8 @@ struct class_metadata
template <class T2>
inline static void maybe_register_callback_class(T2*, mpl::true_)
{
objects::register_shared_ptr_from_python_and_casts(
objects::register_shared_ptr_from_python_and_casts(
(wrapped*)0, mpl::single_view<T2>());
// explicit qualification of type_id makes msvc6 happy
objects::copy_class_object(python::type_id<T2>(), python::type_id<wrapped>());
}
@@ -292,4 +297,4 @@ struct class_metadata
}}} // namespace boost::python::object
#endif // CLASS_METADATA_DWA2004719_HPP
#endif

View File

@@ -11,7 +11,7 @@
namespace boost { namespace python
{
struct BOOST_PYTHON_DECL_FORWARD instance_holder;
struct instance_holder;
}} // namespace boost::python
namespace boost { namespace python { namespace objects {

View File

@@ -21,7 +21,11 @@ struct make_ptr_instance
template <class Arg>
static inline Holder* construct(void* storage, PyObject*, Arg& x)
{
return new (storage) Holder(x);
#if __cplusplus < 201103L
return new (storage) Holder(x);
#else
return new (storage) Holder(std::move(x));
#endif
}
template <class Ptr>

View File

@@ -107,13 +107,21 @@ struct pointer_holder_back_reference : instance_holder
template <class Pointer, class Value>
inline pointer_holder<Pointer,Value>::pointer_holder(Pointer p)
#if __cplusplus < 201103L
: m_p(p)
#else
: m_p(std::move(p))
#endif
{
}
template <class Pointer, class Value>
inline pointer_holder_back_reference<Pointer,Value>::pointer_holder_back_reference(Pointer p)
#if __cplusplus < 201103L
: m_p(p)
#else
: m_p(std::move(p))
#endif
{
}

View File

@@ -135,7 +135,11 @@ struct py_function
{}
py_function(py_function const& rhs)
: m_impl(rhs.m_impl)
#if __cplusplus < 201103L
: m_impl(rhs.m_impl)
#else
: m_impl(std::move(rhs.m_impl))
#endif
{}
PyObject* operator()(PyObject* args, PyObject* kw) const
@@ -164,7 +168,11 @@ struct py_function
}
private:
#if __cplusplus < 201103L
mutable std::auto_ptr<py_function_impl_base> m_impl;
#else
mutable std::unique_ptr<py_function_impl_base> m_impl;
#endif
};
}}} // namespace boost::python::objects

View File

@@ -422,6 +422,7 @@ inline api::object_base& api::object_base::operator=(api::object_base const& rhs
inline api::object_base::~object_base()
{
assert( Py_REFCNT(m_ptr) > 0 );
Py_DECREF(m_ptr);
}

View File

@@ -27,12 +27,14 @@ inline T* xincref(T* p)
template <class T>
inline void decref(T* p)
{
assert( Py_REFCNT(python::upcast<PyObject>(p)) > 0 );
Py_DECREF(python::upcast<PyObject>(p));
}
template <class T>
inline void xdecref(T* p)
{
assert( !p || Py_REFCNT(python::upcast<PyObject>(p)) > 0 );
Py_XDECREF(python::upcast<PyObject>(p));
}

Some files were not shown because too many files have changed in this diff Show More