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