diff --git a/doc/v2/numeric.html b/doc/v2/numeric.html
index 0817f5ef..ea04d5aa 100644
--- a/doc/v2/numeric.html
+++ b/doc/v2/numeric.html
@@ -1,105 +1,105 @@
-
+
-
-
-
-
+
+
+
+
- Boost.Python - <boost/python/numeric.hpp>
-
+ Boost.Python - <boost/python/numeric.hpp>
+
-
-
-
-
-
-
+
+
+
+
+
+
-
-
+
+
- Header <boost/python/numeric.hpp>
-
-
-
-
+ Header <boost/python/numeric.hpp>
+
+
+
+
- Contents
+ Contents
-
- Introduction
+
+ Introduction
- Classes
+ Classes
-
-
- Class array
+
+
+ Class array
-
-
- Class array
- synopsis
+
+
+ Class array
+ synopsis
- Class array
- observer functions
+ Class array
+ observer functions
- Class array
- static functions
-
-
-
-
+ Class array static
+ functions
+
+
+
+
- Example(s)
-
-
+ Example(s)
+
+
- Introduction
+ Introduction
- Exposes a TypeWrapper for the Python
- array
- type.
+ Exposes a TypeWrapper for the Python
+ array
+ type.
- Classes
+ Classes
- Class array
+ Class array
- Provides access to the array types of Numerical Python 's Numeric and NumArray modules. With
- the exception of the functions documented below , the semantics of the constructors and
- member functions defined below can be fully understood by reading the TypeWrapper concept
- definition. Since array is publicly derived from object , the public object
- interface applies to array instances as well.
+ Provides access to the array types of Numerical Python 's Numeric and NumArray modules. With
+ the exception of the functions documented below , the semantics of the constructors and
+ member functions defined below can be fully understood by reading the
+ TypeWrapper concept
+ definition. Since array is publicly derived from
+ object , the public
+ object interface applies to array instances as well.
- The default behavior is to use
- numarray.NDArray as the associated Python type if the
- numarray module is installed in the default location.
- Otherwise it falls back to use Numeric.ArrayType. If neither
- extension module is installed, conversions to arguments of type
- numeric::array will cause overload resolution to reject the
- overload, and other attempted uses of numeric::array will raise an appropriate Python exception.
- The associated Python type can be set manually using the set_module_and_type (...) static
- function.
+ The default behavior is
+ to use numarray.NDArray as the associated Python type if the
+ numarray module is installed in the default location.
+ Otherwise it falls back to use Numeric.ArrayType. If neither
+ extension module is installed, overloads of wrapped C++ functions with
+ numeric::array parameters will never be matched, and other
+ attempted uses of numeric::array will raise an appropriate Python exception. The
+ associated Python type can be set manually using the set_module_and_type (...) static
+ function.
- Class array
- synopsis
-
+ Class
+ array synopsis
+
namespace boost { namespace python { namespace numeric
{
class array : public object
@@ -110,7 +110,7 @@ namespace boost { namespace python { namespace numeric
object astype(Type const& type_);
template <class Type>
- object new_(Type const& type_) const;
+ array new_(Type const& type_) const;
template <class Sequence>
void resize(Sequence const& x);
@@ -136,14 +136,14 @@ namespace boost { namespace python { namespace numeric
void tofile(File const& f) const;
object factory();
- template <class Buffer>
- object factory(Buffer const&);
- template <class Buffer, class Type>
- object factory(Buffer const&, Type const&);
- template <class Buffer, class Type, class Shape>
- object factory(Buffer const&, Type const&, Shape const&, bool copy = true, bool savespace = false);
- template <class Buffer, class Type, class Shape>
- object factory(Buffer const&, Type const&, Shape const&, bool copy, bool savespace, char typecode);
+ template <class Sequence>
+ object factory(Sequence const&);
+ template <class Sequence, class Typecode>
+ object factory(Sequence const&, Typecode const&, bool copy = true, bool savespace = false);
+ template <class Sequence, class Typecode, class Type>
+ object factory(Sequence const&, Typecode const&, bool copy, bool savespace, Type const&);
+ template <class Sequence, class Typecode, class Type, class Shape>
+ object factory(Sequence const&, Typecode const&, bool copy, bool savespace, Type const&, Shape const&);
template <class T1>
explicit array(T1 const& x1);
@@ -155,6 +155,7 @@ namespace boost { namespace python { namespace numeric
static void set_module_and_type();
static void set_module_and_type(char const* package_path = 0, char const* type_name = 0);
+ static void get_module_name();
object argmax(long axis=-1);
@@ -203,54 +204,60 @@ namespace boost { namespace python { namespace numeric
}}}
- Class array observer
- functions
-
+ Class
+ array observer functions
+
object factory();
-template <class Buffer>
-object factory(Buffer const&);
-template <class Buffer, class Type>
-object factory(Buffer const&, Type const&);
-template <class Buffer, class Type, class Shape>
-object factory(Buffer const&, Type const&, Shape const&, bool copy = true, bool savespace = false);
-template <class Buffer, class Type, class Shape>
-object factory(Buffer const&, Type const&, Shape const&, bool copy, bool savespace, char typecode);
-
- These functions map to the underlying array type's array()
- function family. They are not called "array" because of the
- C++ limitation that you can't define a member function with the same name
- as its enclosing class.
-
+template <class Sequence>
+object factory(Sequence const&);
+template <class Sequence, class Typecode>
+object factory(Sequence const&, Typecode const&, bool copy = true, bool savespace = false);
+template <class Sequence, class Typecode, class Type>
+object factory(Sequence const&, Typecode const&, bool copy, bool savespace, Type const&);
+template <class Sequence, class Typecode, class Type, class Shape>
+object factory(Sequence const&, Typecode const&, bool copy, bool savespace, Type const&, Shape const&);
+ These functions map to the underlying array type's array()
+function family. They are not called "array" because of the C++
+limitation that you can't define a member function with the same name as its
+enclosing class.
+
template <class Type>
-object new_(Type const&) const;
-
- This function maps to the underlying array type's new()
- function. It is not called "new" because that is a keyword
- in C++.
+array new_(Type const&) const;
+ This function maps to the underlying array type's new()
+function. It is not called "new" because that is a keyword in
+C++.
- Class array static
- functions
-
+ Class
+ array static functions
+
static void set_module_and_type(char const* package_path, char const* type_name);
static void set_module_and_type();
-
- Requires: package_path and
- type_name, if supplied, is an ntbs .
+
+ Requires: package_path and
+ type_name, if supplied, is an ntbs .
- Effects: The first form sets the package path of the module
- which supplies the type named by type_name to
- package_path. The second form restores the default search behavior . The associated Python
- type will be searched for only the first time it is needed, and
- thereafter the first time it is needed after an invocation of
- set_module_and_type.
-
+ Effects: The first form sets the package path of the module
+ that supplies the type named by type_name to
+ package_path. The second form restores the default search behavior . The associated Python type
+ will be searched for only the first time it is needed, and thereafter the
+ first time it is needed after an invocation of
+ set_module_and_type.
+
+
+static std::string get_module_name()
+
- Example
-
+
+ Effects: Returns the name of the module containing the class
+ that will be held by new numeric::array instances.
+
+
+ Example
+
#include <boost/python/numeric.hpp>
#include <boost/python/tuple.hpp>
@@ -261,10 +268,9 @@ void set_first_element(numeric::array& y, double value)
}
- Revised 03 October, 2002
+ Revised 07 October, 2006
- © Copyright Dave Abrahams 2002.
-
+ © Copyright Dave
+ Abrahams 2002-2006.
+
-
diff --git a/include/boost/python/numeric.hpp b/include/boost/python/numeric.hpp
index 14aa7d6d..3868154b 100644
--- a/include/boost/python/numeric.hpp
+++ b/include/boost/python/numeric.hpp
@@ -17,6 +17,8 @@
namespace boost { namespace python { namespace numeric {
+struct array;
+
namespace aux
{
struct BOOST_PYTHON_DECL array_base : object
@@ -36,18 +38,19 @@ namespace aux
void info() const;
bool is_c_array() const;
bool isbyteswapped() const;
- object new_(object type) const;
+ array new_(object type) const;
void sort();
object trace(long offset = 0, long axis1 = 0, long axis2 = 1) const;
object type() const;
char typecode() const;
-
- object factory(object const& buffer=object()
- , object const& type=object()
- , object const& shape=object()
- , bool copy = true
- , bool savespace = false
- , object typecode = object());
+
+ object factory(
+ object const& sequence = object()
+ , object const& typecode = object()
+ , bool copy = true
+ , bool savespace = false
+ , object type = object()
+ , object shape = object());
object getflat() const;
long getrank() const;
@@ -106,7 +109,7 @@ class array : public aux::array_base
}
template
- object new_(Type const& type_) const
+ array new_(Type const& type_) const
{
return base::new_(object(type_));
}
@@ -162,43 +165,48 @@ class array : public aux::array_base
return base::factory();
}
- template
- object factory(Buffer const& buffer)
+ template
+ object factory(Sequence const& sequence)
{
- return base::factory(object(buffer));
+ return base::factory(object(sequence));
}
- template
+ template
object factory(
- Buffer const& buffer
- , Type const& type_)
+ Sequence const& sequence
+ , Typecode const& typecode_
+ , bool copy = true
+ , bool savespace = false
+ )
{
- return base::factory(object(buffer), object(type_));
+ return base::factory(object(sequence), object(typecode_), copy, savespace);
}
- template
+ template
object factory(
- Buffer const& buffer
- , Type const& type_
- , Shape const& shape
- , bool copy = true
- , bool savespace = false)
+ Sequence const& sequence
+ , Typecode const& typecode_
+ , bool copy
+ , bool savespace
+ , Type const& type
+ )
{
- return base::factory(object(buffer), object(type_), object(shape), copy, savespace);
+ return base::factory(object(sequence), object(typecode_), copy, savespace, object(type));
}
- template
+ template
object factory(
- Buffer const& buffer
- , Type const& type_
- , Shape const& shape
- , bool copy
- , bool savespace
- , char typecode)
+ Sequence const& sequence
+ , Typecode const& typecode_
+ , bool copy
+ , bool savespace
+ , Type const& type
+ , Shape const& shape
+ )
{
- return base::factory(object(buffer), object(type_), object(shape), copy, savespace, object(typecode));
+ return base::factory(object(sequence), object(typecode_), copy, savespace, object(type), object(shape));
}
-
+
# define BOOST_PYTHON_ENUM_AS_OBJECT(z, n, x) object(BOOST_PP_CAT(x,n))
# define BOOST_PP_LOCAL_MACRO(n) \
template \
@@ -210,6 +218,7 @@ class array : public aux::array_base
# undef BOOST_PYTHON_AS_OBJECT
static BOOST_PYTHON_DECL void set_module_and_type(char const* package_name = 0, char const* type_attribute_name = 0);
+ static BOOST_PYTHON_DECL std::string get_module_name();
public: // implementation detail -- for internal use only
BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS(array, base);
diff --git a/src/numeric.cpp b/src/numeric.cpp
index 3e64e141..35c469c5 100644
--- a/src/numeric.cpp
+++ b/src/numeric.cpp
@@ -90,7 +90,12 @@ void array::set_module_and_type(char const* package_name, char const* type_attri
module_name = package_name ? package_name : "" ;
type_name = type_attribute_name ? type_attribute_name : "" ;
}
-
+
+std::string array::get_module_name()
+{
+ load(false);
+ return module_name;
+}
namespace aux
{
@@ -173,9 +178,9 @@ namespace aux
return extract(attr("isbyteswapped")());
}
- object array_base::new_(object type) const
+ array array_base::new_(object type) const
{
- return attr("new")(type);
+ return extract(attr("new")(type))();
}
void array_base::sort()
@@ -197,15 +202,17 @@ namespace aux
{
return extract(attr("typecode")());
}
-
- object array_base::factory(object const& buffer
- , object const& type
- , object const& shape
+
+ object array_base::factory(
+ object const& sequence
+ , object const& typecode
, bool copy
, bool savespace
- , object typecode)
+ , object type
+ , object shape
+ )
{
- return attr("factory")(buffer, type, shape, copy, savespace, typecode);
+ return attr("factory")(sequence, typecode, copy, savespace, type, shape);
}
object array_base::getflat() const
diff --git a/test/numpy.cpp b/test/numpy.cpp
index deb9667b..962a6a8c 100644
--- a/test/numpy.cpp
+++ b/test/numpy.cpp
@@ -7,6 +7,7 @@
#include
#include
#include
+#include
using namespace boost::python;
@@ -39,19 +40,28 @@ void info(numeric::array const& z)
z.info();
}
+namespace
+{
+ object handle_error()
+ {
+ PyObject* type, *value, *traceback;
+ PyErr_Fetch(&type, &value, &traceback);
+ handle<> ty(type), v(value), tr(traceback);
+ return object("exception");
+ str format("exception type: %sn");
+ format += "exception value: %sn";
+ format += "traceback:n%s" ;
+ object ret = format % boost::python::make_tuple(ty, v, tr);
+ return ret;
+ }
+}
#define CHECK(expr) \
{ \
object result; \
try { result = object(expr); } \
catch(error_already_set) \
{ \
- PyObject* type, *value, *traceback; \
- PyErr_Fetch(&type, &value, &traceback); \
- handle<> ty(type), v(value), tr(traceback); \
- str format("exception type: %s\n"); \
- format += "exception value: %s\n"; \
- format += "traceback:\n%s" ; \
- result = format % boost::python::make_tuple(ty, v, tr); \
+ result = handle_error(); \
} \
check(result); \
}
@@ -73,7 +83,7 @@ void exercise(numeric::array& y, object check)
// the results of corresponding python operations.
void exercise_numarray(numeric::array& y, object check)
{
- CHECK(y.astype());
+ CHECK(str(y));
CHECK(y.argmax());
CHECK(y.argmax(0));
@@ -89,7 +99,7 @@ void exercise_numarray(numeric::array& y, object check)
CHECK(y.diagonal());
CHECK(y.diagonal(1));
- CHECK(y.diagonal(0, 1));
+ CHECK(y.diagonal(0, 0));
CHECK(y.diagonal(0, 1, 0));
CHECK(y.is_c_array());
@@ -97,19 +107,22 @@ void exercise_numarray(numeric::array& y, object check)
CHECK(y.trace());
CHECK(y.trace(1));
- CHECK(y.trace(0, 1));
+ CHECK(y.trace(0, 0));
CHECK(y.trace(0, 1, 0));
- CHECK(y.new_('D'));
+ CHECK(y.new_("D").getshape());
+ CHECK(y.new_("D").type());
y.sort();
CHECK(y);
CHECK(y.type());
CHECK(y.factory(make_tuple(1.2, 3.4)));
- CHECK(y.factory(make_tuple(1.2, 3.4), "Double"));
- CHECK(y.factory(make_tuple(1.2, 3.4), "Double", make_tuple(1,2,1)));
- CHECK(y.factory(make_tuple(1.2, 3.4), "Double", make_tuple(2,1,1), false));
- CHECK(y.factory(make_tuple(1.2, 3.4), "Double", make_tuple(2), true, true));
+ CHECK(y.factory(make_tuple(1.2, 3.4), "f8"));
+ CHECK(y.factory(make_tuple(1.2, 3.4), "f8", true));
+ CHECK(y.factory(make_tuple(1.2, 3.4), "f8", true, false));
+ CHECK(y.factory(make_tuple(1.2, 3.4), "f8", true, false, object()));
+ CHECK (y.factory(make_tuple(1.2, 3.4), "f8", true, false, object(), make_tuple(1,2,1)));
+
}
BOOST_PYTHON_MODULE(numpy_ext)
@@ -119,6 +132,7 @@ BOOST_PYTHON_MODULE(numpy_ext)
def("exercise", exercise);
def("exercise_numarray", exercise_numarray);
def("set_module_and_type", &numeric::array::set_module_and_type);
+ def("get_module_name", &numeric::array::get_module_name);
def("info", info);
}
diff --git a/test/numpy.py b/test/numpy.py
index 6f186c59..f4fbcdf3 100644
--- a/test/numpy.py
+++ b/test/numpy.py
@@ -8,6 +8,9 @@
# tests based on the availability of Numeric and numarray, the corresponding
# test functions are simply deleted below if necessary.
+# So we can coerce portably across Python versions
+bool = type(1 == 1)
+
def numeric_tests():
'''
>>> from numpy_ext import *
@@ -55,8 +58,8 @@ def _numarray_tests():
>>> check = p.check
>>> exercise_numarray(x, p)
- >>> check(y.astype());
-
+ >>> check(str(y))
+
>>> check(y.argmax());
>>> check(y.argmax(0));
@@ -68,30 +71,35 @@ def _numarray_tests():
>>> y.byteswap();
>>> check(y);
-
+
>>> check(y.diagonal());
>>> check(y.diagonal(1));
- >>> check(y.diagonal(0, 1));
+ >>> check(y.diagonal(0, 0));
>>> check(y.diagonal(0, 1, 0));
>>> check(y.is_c_array());
- >>> check(y.isbyteswapped());
+
+ # coerce because numarray still returns an int and the C++ interface forces
+ # the return type to bool
+ >>> check( bool(y.isbyteswapped()) );
>>> check(y.trace());
>>> check(y.trace(1));
- >>> check(y.trace(0, 1));
+ >>> check(y.trace(0, 0));
>>> check(y.trace(0, 1, 0));
- >>> check(y.new('D'));
+ >>> check(y.new('D').getshape());
+ >>> check(y.new('D').type());
>>> y.sort();
>>> check(y);
>>> check(y.type());
>>> check(y.factory((1.2, 3.4)));
- >>> check(y.factory((1.2, 3.4), "Double"));
- >>> check(y.factory((1.2, 3.4), "Double", (1,2,1)));
- >>> check(y.factory((1.2, 3.4), "Double", (2,1,1), false));
- >>> check(y.factory((1.2, 3.4), "Double", (2,), true, true));
+ >>> check(y.factory((1.2, 3.4), "f8"))
+ >>> check(y.factory((1.2, 3.4), "f8", true))
+ >>> check(y.factory((1.2, 3.4), "f8", true, false))
+ >>> check(y.factory((1.2, 3.4), "f8", true, false, None))
+ >>> check(y.factory((1.2, 3.4), "f8", true, false, None, (1,2,1)))
>>> p.results
[]
@@ -105,12 +113,12 @@ class _printer(object):
def __init__(self):
self.results = [];
def __call__(self, *stuff):
- self.results += [ str(x) for x in stuff ]
+ for x in stuff:
+ self.results.append(str(x))
def check(self, x):
- if self.results[0] == str(x):
- del self.results[0]
- else:
- print ' Expected:\n %s\n but got:\n %s' % (x, self.results[0])
+ if self.results[0] != str(x):
+ print ' Expected:\n %s\n but the C++ interface gave:\n %s' % (x, self.results[0])
+ del self.results[0]
def _run(args = None):
import sys
@@ -150,21 +158,29 @@ def _run(args = None):
failures = 0
+ find = doctest.DocTestFinder().find
+ run = doctest.DocTestRunner().run
+
#
# Run tests 4 different ways if both modules are installed, just
# to show that set_module_and_type() is working properly
#
# run all the tests with default module search
- print 'testing default extension module'
- failures += doctest.testmod(sys.modules.get(__name__))[0]
+ print 'testing default extension module:', \
+ numpy_ext.get_module_name() or '[numeric support not installed]'
+ for test in find(numeric_tests):
+ failures += run(test)[0]
+
# test against Numeric if installed
if has_numeric:
print 'testing Numeric module explicitly'
numpy_ext.set_module_and_type('Numeric', 'ArrayType')
- failures += doctest.testmod(sys.modules.get(__name__))[0]
-
+
+ for test in find(numeric_tests):
+ failures += run(test)[0]
+
global __test__
if has_numarray:
# Add the _numarray_tests to the list of things to test in
@@ -173,13 +189,18 @@ def _run(args = None):
'numeric_tests': numeric_tests }
print 'testing numarray module explicitly'
numpy_ext.set_module_and_type('numarray', 'NDArray')
- failures += doctest.testmod(sys.modules.get(__name__))[0]
+
+ for test in find(numeric_tests) + find(_numarray_tests):
+ failures += run(test)[0]
del __test__
# see that we can go back to the default
- print 'testing default module again'
numpy_ext.set_module_and_type('', '')
- failures += doctest.testmod(sys.modules.get(__name__))[0]
+ print 'testing default module again:', \
+ numpy_ext.get_module_name() or '[numeric support not installed]'
+
+ for test in find(numeric_tests):
+ failures += run(test)[0]
return failures