Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r63299 - in sandbox/numpy: boost/python/numpy libs/python/numpy/test
From: talljimbo_at_[hidden]
Date: 2010-06-24 18:20:56


Author: jbosch
Date: 2010-06-24 18:20:55 EDT (Thu, 24 Jun 2010)
New Revision: 63299
URL: http://svn.boost.org/trac/boost/changeset/63299

Log:
boost.python.numpy - added dtype template invoker
Added:
   sandbox/numpy/libs/python/numpy/test/templates.py
      - copied, changed from r63094, /sandbox/numpy/libs/python/numpy/test/ufunc.py
   sandbox/numpy/libs/python/numpy/test/templates_mod.cpp
      - copied, changed from r63094, /sandbox/numpy/libs/python/numpy/test/ufunc_mod.cpp
Text files modified:
   sandbox/numpy/boost/python/numpy/dtype.hpp | 52 ++++++++++++++++++++++++++++++++++++++++
   sandbox/numpy/libs/python/numpy/test/SConscript | 12 ++++++---
   sandbox/numpy/libs/python/numpy/test/templates.py | 52 +++++++--------------------------------
   sandbox/numpy/libs/python/numpy/test/templates_mod.cpp | 39 ++++++++++++++++-------------
   4 files changed, 91 insertions(+), 64 deletions(-)

Modified: sandbox/numpy/boost/python/numpy/dtype.hpp
==============================================================================
--- sandbox/numpy/boost/python/numpy/dtype.hpp (original)
+++ sandbox/numpy/boost/python/numpy/dtype.hpp 2010-06-24 18:20:55 EDT (Thu, 24 Jun 2010)
@@ -9,6 +9,9 @@
 #include <boost/python.hpp>
 #include <boost/python/numpy/numpy_object_mgr_traits.hpp>
 
+#include <boost/mpl/for_each.hpp>
+#include <boost/type_traits/add_pointer.hpp>
+
 namespace boost { namespace python {
 namespace numpy {
 
@@ -43,8 +46,57 @@
 
     BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS(dtype, object);
 
+ template <typename Sequence, typename Function>
+ void invoke_matching_template(Function f);
+
+};
+
+namespace detail {
+
+struct add_pointer_meta {
+
+ template <typename T>
+ struct apply {
+ typedef typename boost::add_pointer<T>::type type;
+ };
+
 };
 
+struct dtype_template_match_found {};
+
+template <typename Function>
+struct dtype_template_invoker {
+
+ template <typename T>
+ void operator()(T * x) const {
+ if (dtype::get_builtin<T>() == m_dtype) {
+ m_func.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;
+};
+
+} // namespace boost::python::numpy::detail
+
+template <typename Sequence, typename Function>
+void dtype::invoke_matching_template(Function f) {
+ detail::dtype_template_invoker<Function> invoker(*this, f);
+ try {
+ boost::mpl::for_each< Sequence, detail::add_pointer_meta >(invoker);
+ } catch (detail::dtype_template_match_found &) {
+ return;
+ }
+ PyErr_SetString(PyExc_TypeError, "numpy.dtype not found in template list.");
+ throw_error_already_set();
+}
+
 } // namespace boost::python::numpy
 
 namespace converter {

Modified: sandbox/numpy/libs/python/numpy/test/SConscript
==============================================================================
--- sandbox/numpy/libs/python/numpy/test/SConscript (original)
+++ sandbox/numpy/libs/python/numpy/test/SConscript 2010-06-24 18:20:55 EDT (Thu, 24 Jun 2010)
@@ -1,8 +1,12 @@
 Import("bp_numpy_env")
 
-ufunc_mod = bp_numpy_env.SharedLibrary("ufunc_mod", "ufunc_mod.cpp", SHLIBPREFIX="",
- LIBS="boost_python_numpy")
-ufunc_test = bp_numpy_env.PythonUnitTest("ufunc.py", ufunc_mod)
+test = []
+
+for name in ("ufunc", "templates"):
+ mod = bp_numpy_env.SharedLibrary("%s_mod" % name, "%s_mod.cpp" % name, SHLIBPREFIX="",
+ LIBS="boost_python_numpy")
+ test.extend(
+ bp_numpy_env.PythonUnitTest("%s.py" % name, mod)
+ )
 
-test = ufunc_test
 Return("test")

Copied: sandbox/numpy/libs/python/numpy/test/templates.py (from r63094, /sandbox/numpy/libs/python/numpy/test/ufunc.py)
==============================================================================
--- /sandbox/numpy/libs/python/numpy/test/ufunc.py (original)
+++ sandbox/numpy/libs/python/numpy/test/templates.py 2010-06-24 18:20:55 EDT (Thu, 24 Jun 2010)
@@ -1,49 +1,17 @@
-import ufunc_mod
+import templates_mod
 import unittest
 import numpy
 
-class TestUnary(unittest.TestCase):
+class TestTemplates(unittest.TestCase):
 
- def testScalar(self):
- f = ufunc_mod.UnaryCallable()
- self.assertEqual(f(1.0), 2.0)
- self.assertEqual(f(3.0), 6.0)
-
- def testArray(self):
- f = ufunc_mod.UnaryCallable()
- a = numpy.arange(5, dtype=float)
- b = f(a)
- self.assert_((b == a*2.0).all())
- c = numpy.zeros(5, dtype=float)
- d = f(a,output=c)
- self.assert_((c == a*2.0).all())
- self.assert_((d == a*2.0).all())
-
- def testList(self):
- f = ufunc_mod.UnaryCallable()
- a = range(5)
- b = f(a)
- self.assert_((b/2.0 == a).all())
-
-class TestBinary(unittest.TestCase):
-
- def testScalar(self):
- f = ufunc_mod.BinaryCallable()
- self.assertEqual(f(1.0, 3.0), 11.0)
- self.assertEqual(f(3.0, 2.0), 12.0)
-
- def testArray(self):
- f = ufunc_mod.BinaryCallable()
- a = numpy.random.randn(5)
- b = numpy.random.randn(5)
- self.assert_((f(a,b) == (a*2+b*3)).all())
- c = numpy.zeros(5, dtype=float)
- d = f(a,b,output=c)
- self.assert_((c == a*2 + b*3).all())
- self.assert_((d == a*2 + b*3).all())
- self.assert_((f(a, 2.0) == a*2 + 6.0).all())
- self.assert_((f(1.0, b) == 2.0 + b*3).all())
-
+ def testTemplates(self):
+ for dtype in (numpy.int16, numpy.int32, numpy.float32, numpy.complex128):
+ a1 = numpy.zeros((12,), dtype=dtype)
+ a2 = numpy.arange(12, dtype=dtype)
+ templates_mod.fill(a1)
+ self.assert_((a1 == a2).all())
+ a1 = numpy.zeros((12,), dtype=numpy.float64)
+ self.assertRaises(TypeError, templates_mod.fill, a1)
 
 if __name__=="__main__":
     unittest.main()

Copied: sandbox/numpy/libs/python/numpy/test/templates_mod.cpp (from r63094, /sandbox/numpy/libs/python/numpy/test/ufunc_mod.cpp)
==============================================================================
--- /sandbox/numpy/libs/python/numpy/test/ufunc_mod.cpp (original)
+++ sandbox/numpy/libs/python/numpy/test/templates_mod.cpp 2010-06-24 18:20:55 EDT (Thu, 24 Jun 2010)
@@ -1,31 +1,34 @@
 #include <boost/python/numpy/numpy.hpp>
+#include <boost/mpl/vector.hpp>
 
 namespace bp = boost::python;
 
-struct UnaryCallable {
+struct ArrayFiller {
 
- typedef double argument_type;
- typedef double result_type;
+ typedef boost::mpl::vector< short, int, float, std::complex<double> > Sequence;
 
- double operator()(double r) const { return r * 2; }
+ template <typename T>
+ void apply() const {
+ char * p = argument.get_data();
+ int stride = argument.strides(0);
+ int size = argument.shape(0);
+ for (int n = 0; n != size; ++n, p += stride) {
+ *reinterpret_cast<T*>(p) = static_cast<T>(n);
+ }
+ }
 
-};
-
-struct BinaryCallable {
-
- typedef double first_argument_type;
- typedef double second_argument_type;
- typedef double result_type;
+ bp::numpy::ndarray argument;
 
- double operator()(double a, double b) const { return a * 2 + b * 3; }
+ explicit ArrayFiller(bp::numpy::ndarray const & arg) : argument(arg) {}
 
 };
 
-BOOST_PYTHON_MODULE(ufunc_mod) {
- bp::numpy::initialize();
- bp::class_< UnaryCallable, boost::shared_ptr<UnaryCallable> >("UnaryCallable")
- .def("__call__", bp::numpy::unary_ufunc<UnaryCallable>::make());
- bp::class_< BinaryCallable, boost::shared_ptr<BinaryCallable> >("BinaryCallable")
- .def("__call__", bp::numpy::binary_ufunc<BinaryCallable>::make());
+void fill(bp::numpy::ndarray const & arg) {
+ ArrayFiller filler(arg);
+ arg.get_dtype().invoke_matching_template< ArrayFiller::Sequence >(filler);
+}
 
+BOOST_PYTHON_MODULE(templates_mod) {
+ bp::numpy::initialize();
+ bp::def("fill", &fill);
 }


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk