The C++ Vector and Matrix Types

PyUblas defines Ublas-compatible C++ types, namely numpy_vector and numpy_matrix. These are defined in pyublas/numpy.hpp.

Introduction

numpy_vector is derived from Ublas’s vector and may be used in the same places as the latter, in the same ways. There is only one difference:

numpy_vector will not copy your data unless you ask it to.

numpy_vector internally uses Numpy arrays to store data. Unlike the native Ublas vector<T>, numpy_vector has reference or “handle” semantics: Copy-constructing and assigning only makes a new reference to the existing vector’s data. Unlike native Ublas, it will not make a copy. Consider this example:

numpy_vector<double> a(5);
std::fill(a.begin(), a.end(), 17);

numpy_vector<double> b(a); // only references a's data
b[2] = 0;

std::cout << a[2] << std::endl; // prints "0".

If you want the data to be copied, you must say so explicitly:

numpy_vector<double> c(a.size());
c.assign(a); // actually copies a's data
c[2] = 17;

std::cout << a[2] << std::endl; // still prints "0".
std::cout << c[2] << std::endl; // prints "17".

If you follow these simple rules, it’s easy to write code that works the same for both ublas::vector and numpy_vector. (Note that here, as in the rest of this documentation, the same discussion applies without change to numpy_matrix as well.)

Warning

The assign method does not resize its target to the size of its operand–this is something you have to do by hand if you use the above recipe.

You should be aware of another difference: Indexed access to numpy_vector is much slower than iterator access. Iterators achieve the same speed as “regular” Ublas, while indexed access adds some extra instructions to find the real start of the array in the presence of negative slices. As is true of much of the rest of C++:

Note

Use iterators whenever possible.

Also see Gaah! Why is this garbage so slow?

Reference Documentation

#include <pyublas/numpy.hpp>

numpy_array

template <class ValueType>, in namespace pyublas.

Only members that are not already part of the Boost.Ublas “Storage” Concept are shown.

Public type definitions:

typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef ValueType value_type;
typedef const ValueType &const_reference;
typedef ValueType &reference;
typedef const ValueType *const_pointer;
typedef ValueType *pointer;
constructor numpy_array()
explicit_constructor numpy_array(size_type n)
constructor numpy_array(size_type n, const value_type &v)
constructor numpy_array(int ndim, const npy_intp *dims)
constructor numpy_array(const boost::python::handle<> &obj)

Construct a new numpy_array. If you use the empty constructor, the array is in an invalid state until numpy_array::resize() is called. Calling any other member function will result in undefined behavior.

size_type numpy_array::ndim()

A const member function.

const npy_intp *numpy_array::dims()

A const member function.

const npy_intp *numpy_array::strides()

A const member function.

npy_intp numpy_array::itemsize()

A const member function.

bool numpy_array::writable()

A const member function.

void numpy_array::reshape(int ndim, const npy_intp *dims, NPY_ORDER order=NPY_CORDER)
value_type *numpy_array::data()
const value_type *numpy_array::data()

A const member function.

boost::python::handle<> numpy_array::handle()

Return a handle to the underlying Numpy array object. If the array is unitialized, the function may return a handle to None.

A const member function.

numpy_vector

template <class ValueType>, in namespace pyublas.

constructor numpy_vector()
constructor numpy_vector(const numpy_array<ValueType> &s)
constructor numpy_vector(int ndim, const npy_intp *dims)
explicit_constructor numpy_vector(typename super::size_type size)
constructor numpy_vector(size_type size, const value_type &init)
constructor numpy_vector(const numpy_vector &v)
constructor numpy_vector(const boost::numeric::ublas::vector_expression<AE> &ae)
constructor numpy_vector(int ndim, const npy_intp *dims, const boost::numeric::ublas::vector_expression<AE> &ae)

Construct a new numpy_vector instance.

The (ndim, dims) constructor form can be used to specify the Python-side shape of the array at construction time. This is extended by the (ndim, dims, ae) form, which allows to specify the vector expression from which the vector is initialized, along with its Python-side shape. Both the initializer and the Python-side shape are assumed to yield identical vector sizes.

Observe that PyObject handles are implicitly convertible to numpy_array, so that you can invoke the constructor simply by feeding it a boost::python::handle.

If you use the empty constructor, the vector is in an invalid state until numpy_vector::resize() is called. In this state, calling numpy_vector::is_valid(), numpy_vector::size() and numpy_vector::resize() is allowed. Calling any other member function results in undefined behavior.

size_type numpy_vector::ndim()

Return the number of dimensions of this array.

A const member function.

const npy_intp *numpy_vector::dims()

Return an array of numpy_vector::ndim() entries, each of which is the size of the array along one dimension. in elements.

A const member function.

const npy_intp *numpy_vector::strides()

Return an array of numpy_vector::ndim() entries, each of which is the stride along one dimension, in bytes. Divide by numpy_vector::itemsize() to convert this to element-wise strides.

A const member function.

npy_intp numpy_vector::itemsize()

Return the size (in bytes) of each element of the array.

A const member function.

bool numpy_vector::writable()

A const member function.

ValueType &numpy_vector::sub(npy_intp i)
ValueType &numpy_vector::sub(npy_intp i, npy_intp j)
ValueType &numpy_vector::sub(npy_intp i, npy_intp j, npy_intp k)
ValueType &numpy_vector::sub(npy_intp i, npy_intp j, npy_intp k, npy_intp l)

Return the element at the index (i), (i,j), (i,j,k), (i,j,k,l). It is up to you to ensure that the array has the same number of dimensions, otherwise the results are undefined.

Also available as const member functions.

void numpy_vector::reshape(int ndim, const npy_intp *dims, NPY_ORDER order=NPY_CORDER)

Same operation as numpy.reshape().

boost::numeric::ublas::vector_slice<numpy_vector> numpy_vector::as_strided()

Return a view of the array that seems contiguous, by only looking at every numpy_vector::min_stride()‘th element.

Also available as a const member function.

boost::vector<ValueType> &numpy_vector::as_ublas()

Downcast this instance to the underlying boost::numeric::ublas::vector<ValueType>.

Also available as a const member function.

boost::python::handle<> numpy_vector::to_python()

Return a Boost.Python handle (which is essentially an auto-refcounting PyObject *) to the underlying Numpy array. If the matrix is empty, the function may return a handle to None.

A const member function.

numpy_strided_vector

template <class ValueType>, in namespace pyublas.

If you use this type as a argument type in a function called from Python, the converted vector will respect non-contiguous slices automatically. See What about slices?

Inherits from boost::numeric::ublas::vector_slice.

Warning

Ublas only provides single-dimensional strides. Multi-dimensional numpy slices (such as zeros((5,5))[:3,:3]) can easily become too complex to be represented using these slices. In this case, the from-Python conversion fails with a ValueError.

constructor numpy_strided_vector(const numpy_array<ValueType> &s)
constructor numpy_strided_vector(const numpy_strided_vector &v)
constructor numpy_strided_vector(numpy_vector<ValueType> &v, boost::numeric::ublas::slice const &s)
constructor numpy_strided_vector(const boost::numeric::ublas::vector_expression<AE> &ae)

Observe that PyObject handles are implicitly convertible to numpy_array, so that you can invoke the constructor simply by feeding it a boost::python::handle.

size_type numpy_strided_vector::ndim()

Return the number of dimensions of this array.

A const member function.

const npy_intp *numpy_strided_vector::dims()

Return an array of numpy_strided_vector::ndim() entries, each of which is the size of the array along one dimension. in elements.

A const member function.

const npy_intp *numpy_strided_vector::strides()

Return an array of numpy_strided_vector::ndim() entries, each of which is the stride along one dimension, in bytes. Divide by numpy_strided_vector::itemsize() to convert this to element-wise strides.

A const member function.

npy_intp numpy_strided_vector::min_stride()

The smallest stride used in the underlying array, in bytes. Divide by numpy_strided_vector::itemsize() to convert this to element-wise strides.

A const member function.

npy_intp numpy_strided_vector::itemsize()

Return the size (in bytes) of each element of the array.

A const member function.

bool numpy_strided_vector::writable()

A const member function.

ValueType &numpy_strided_vector::sub(npy_intp i)
ValueType &numpy_strided_vector::sub(npy_intp i, npy_intp j)
ValueType &numpy_strided_vector::sub(npy_intp i, npy_intp j, npy_intp k)
ValueType &numpy_strided_vector::sub(npy_intp i, npy_intp j, npy_intp k, npy_intp l)

Return the element at the index (i), (i,j), (i,j,k), (i,j,k,l). It is up to you to ensure that the array has the same number of dimensions, otherwise the results are undefined.

Also available as const member functions.

boost::numeric::ublas::vector_slice<numpy_vector<ValueType> > &numpy_vector::as_ublas()

Downcast this instance to the underlying boost::numeric::ublas::vector<ValueType>.

Also available as a const member function.

boost::python::handle<> numpy_vector::to_python()

Return a Boost.Python handle (which is essentially an auto-refcounting PyObject *) to the underlying Numpy array. If the matrix is empty, the function may return a handle to None.

A const member function.

numpy_matrix

template <class ValueType, class Orientation=boost::numeric::ublas::row_major>, in namespace pyublas.

constructor numpy_matrix()
constructor numpy_matrix(size_type size1, size_type size2)
constructor numpy_matrix(size_type size1, size_type size2, const value_type &init)
constructor numpy_matrix(size_type size1, size_type size2, const array_type &data)
constructor numpy_matrix(const typename super::array_type &data)
constructor numpy_matrix(const numpy_matrix &m)
constructor numpy_matrix(const boost::numeric::ublas::matrix_expression<AE> &ae)

Observe that PyObject handles are implicitly convertible to numpy_array, so that you can invoke the constructor simply by feeding it a boost::python::handle.

If you use the empty constructor, the matrix is in an invalid state until numpy_matrix::resize() is called. Calling any other member function will result in undefined behavior.

boost::matrix<ValueType, Orientation> &numpy_matrix::as_ublas()

Also available as a const member function.

boost::python::handle<> numpy_matrix::to_python()

Return a handle to the underlying Numpy array object. If the matrix is empty, the function may return a handle to None.

A const member function.

invalid_ok

template <class Contained>, in namespace pyublas.

Contained can be numpy_vector or numpy_matrix. If arguments of this type are converted from Python, they will also accept the value None. In that case, the resulting Contained will be invalid if None is passed in. See Can I pass None for an argument that gets converted to numpy_vector?

Contained &invalid_ok::operator*()

Return a reference to the Contained array.

Contained *invalid_ok::operator->()

Return a pointer to the Contained array.

Interacting with Boost.Bindings

PyUblas contains special code to support interacting with the Boost.Bindings library.

If you want to activate this support, define the macro PYUBLAS_HAVE_BOOST_BINDINGS before including pyublas/numpy.hpp.

Boost.Bindings works seamlessly with numpy_vector. For numpy_matrix, you need to explicitly downcast it to the ublas::matrix type. You may do so by simply calling the as_ublas() method.