On Wednesday 21 January 2009 10:22:36 Neal Becker wrote:
> > [http://mail.python.org/pipermail/cplusplus-sig/2008-October/013825.html
>
> Thanks for reminding me about this!
>
> Do you have a current version of the code?  I grabbed the files from the
> above message, but I see some additional subsequent messages with more
> patches.

That is the latest publicly posted code. Since then, there is just one minor 
patch (attached) which enables use of row-major (c-contiguous) arrays.

This does *not* work with strided arrays which would be a fair bit of effort 
to support. Further, you will have to work with the numpy iterator interface, 
which, while well-designed, is a great illustration of the effort required to 
support OO programming in an non-OO language, and is pretty tedious to map to 
the ublas storage iterator interface. If you do implement it, I would very 
much like to take a look at it.

Regards,
Ravi

--- numpyregister.hpp.old	2009-01-21 11:15:50.000000000 -0500
+++ numpyregister.hpp	2008-10-08 11:35:24.000000000 -0400
@@ -174,6 +174,7 @@
   static void execute() {}
 };
 
+// Structure to hold flags for creating arrays referencing existing data.
 template <typename T> struct orientation_t;
 template <> struct orientation_t< boost::numeric::ublas::row_major_tag >
 {
@@ -184,6 +185,17 @@
   BOOST_STATIC_CONSTANT( npy_intp, value = NPY_FARRAY );
 };
 
+// Structure to hold flags for creating arrays with new data.
+template <typename T> struct orientation_flag_t;
+template <> struct orientation_flag_t< boost::numeric::ublas::row_major_tag >
+{
+  BOOST_STATIC_CONSTANT( npy_intp, value = 0 );
+};
+template <> struct orientation_flag_t< boost::numeric::ublas::column_major_tag >
+{
+  BOOST_STATIC_CONSTANT( npy_intp, value = 1 );
+};
+
 template <bool copy, typename matrix_t>
 struct pyarray_from_matrix_impl;
 
@@ -215,7 +227,7 @@
   typedef typename matrix_t::value_type data_t;
   typedef typename boost::mpl::at<numpy_typemap, data_t>::type typenum_t;
   BOOST_STATIC_CONSTANT( npy_intp,
-                         orient = orientation_t<typename matrix_t::
+                         orient = orientation_flag_t<typename matrix_t::
                            orientation_category>::value );
 
   static PyObject* convert( const matrix_t &in )
@@ -223,7 +235,7 @@
     // Create a new numpy array from existing data.
     npy_intp dims[2]; dims[0] = in.size1(); dims[1] = in.size2();
     // Must use PyArray_New because PyArray_SimpleNew does not support column major
-    // arrays. However, because of a numpy bug, c-contiguous arrays do not work now.
+    // arrays.
     PyObject *obj = PyArray_New( &PyArray_Type, 2, dims, typenum_t::value, NULL,
                                  NULL, 0, orient, NULL );
     std::copy( in.data().begin(), in.data().end(),
@@ -235,7 +247,7 @@
 template <typename T>
 struct ublas_vector_from_numpy
 {
-  typedef numpy_storage_array<T> array_storage_t;
+  typedef numpy_storage_array<T, storage_demux<T, one_dimension_tag> > array_storage_t;
   typedef boost::numeric::ublas::vector<T, array_storage_t > array_t;
   typedef boost::python::converter::rvalue_from_python_storage<array_t> storage_t;
   typedef typename boost::mpl::at<numpy_typemap, T>::type typenum_t;
@@ -271,17 +283,80 @@
   }
 };
 
+template <typename T> bool check_storage_validity( PyObject * );
+template<> inline bool check_storage_validity<
+  boost::numeric::ublas::row_major>( PyObject *obj )
+{
+  // Non-contiguous arrays are always considered C order
+  return !PyArray_ISFORTRAN( obj );
+}
+template<> inline bool check_storage_validity<
+  boost::numeric::ublas::column_major>( PyObject *obj )
+{
+  return PyArray_ISFORTRAN( obj );
+}
+
+template <typename T, typename storage_order>
+struct ublas_matrix_from_numpy
+{
+  typedef numpy_storage_array<T, storage_demux<T, storage_order> > array_storage_t;
+  typedef boost::numeric::ublas::matrix<T, storage_order, array_storage_t > array_t;
+  typedef boost::python::converter::rvalue_from_python_storage<array_t> storage_t;
+  typedef typename boost::mpl::at<numpy_typemap, T>::type typenum_t;
+
+  static void* convertible( PyObject *obj )
+  {
+    // Check for numpy array and correct data type
+    if ( !PyArray_Check( obj )
+         || ( PyArray_TYPE( obj ) != typenum_t::value )
+         || ( PyArray_NDIM( obj ) != 2 )
+         || !check_storage_validity<storage_order>( obj )
+      )
+      return 0;
+    return obj;
+  }
+
+  static void construct( PyObject *obj,
+                         boost::python::converter::rvalue_from_python_stage1_data* data )
+  {
+    storage_t *the_storage = reinterpret_cast<storage_t*>( data );
+    void *memory_chunk = the_storage->storage.bytes;
+    array_storage_t dd( obj );
+    array_t *v = new ( memory_chunk ) array_t( PyArray_DIMS( obj )[0]
+                                               , PyArray_DIMS( obj )[1]
+                                               , dd );
+    data->convertible = memory_chunk;
+  }
+
+  static void register_from_python_converter()
+  {
+    boost::python::converter::registry::push_back(
+      &ublas_matrix_from_numpy<T, storage_order>::convertible,
+      &ublas_matrix_from_numpy<T, storage_order>::construct,
+      boost::python::type_id<array_t>()
+      );
+  }
+};
+
 template <typename map_iter>
 struct register_ublas_from_python_converter_impl
 {
   typedef typename boost::mpl::deref<map_iter>::type pair_t;
   typedef typename pair_t::first data_t;
-  typedef ublas_vector_from_numpy<data_t> converter_t;
+  typedef ublas_vector_from_numpy<data_t> vector_converter_t;
+  typedef ublas_matrix_from_numpy<data_t,
+                                  boost::numeric::ublas::row_major
+                                  > row_major_matrix_converter_t;
+  typedef ublas_matrix_from_numpy<data_t,
+                                  boost::numeric::ublas::column_major
+                                  > column_major_matrix_converter_t;
   typedef typename boost::mpl::next<map_iter>::type next_iter;
 
   static void execute()
   {
-    converter_t::register_from_python_converter();
+    vector_converter_t::register_from_python_converter();
+    row_major_matrix_converter_t::register_from_python_converter();
+    column_major_matrix_converter_t::register_from_python_converter();
     register_ublas_from_python_converter_impl<next_iter>::execute();
   }
 };
_______________________________________________
Numpy-discussion mailing list
Numpy-discussion@scipy.org
http://projects.scipy.org/mailman/listinfo/numpy-discussion

Reply via email to