|
Boost.Numeric.Bindings.Traits |
The Traits Library provides the mappings from the interfaces of various vector and matrix C++ libraries to the storage layout format required by the original API's of different external numeric libraries.
These mappings are implemented by means of traits classes and their specialisations. One advantage of this approach is that the traits idiom is non-intrusive: no changes or additions to vector and matrix classes are needed. Another advantage is the extensibility since traits classes can be specialised for many different vector or matrix libraries. Furthermore, the traits idiom is a compile-time mechanism and thus adds no run-time overhead.
ublas::vector<>
, ublas::c_vector<>
and vector proxies -- in ublas_vector.hpp
ublas::matrix_row<>
and ublas::matrix_column<>
-- in ublas_matrix.hpp
std::valarray<>
-- in std_valarray.hpp
std::vector<>
-- in std_vector.hpp
boost::array<>
-- in boost_array.hpp
c_array.hpp
tnt.hpp
ublas::matrix<>
, ublas::c_matrix<>
and matrix proxies -- in ublas_matrix.hpp
ublas::symmetric_matrix<>
and ublas::symmetric_adaptor<>
-- in ublas_symmetric.hpp
ublas::hermitian_matrix<>
and ublas::hermitian_adaptor<>
-- in ublas_hermitian.hpp
ublas::vector<>
and ublas::c_vector<>
(matrices with one column and one row) -- in ublas_vector2.hpp
tnt.hpp
ublas::compressed_matrix<>
and ublas::coordinate_matrix<>
-- in ublas_sparse.hpp
boost/numeric/bindings/traits
.
If you are using any of these vector or matrix classes, this is in fact all you need to know about traits classes and their specialisations.
Example. Simple initialisation and dot product of vectors
v
(represented by std::vector<>
) and
w
(represented by
`plain' C array) using ATLAS bindings:
#include <iostream> #include <boost/numeric/bindings/traits/std_vector.hpp> #include <boost/numeric/bindings/traits/c_array.hpp> #include <boost/numeric/bindings/atlas/cblas1.hpp> namespace atlas = boost::numeric::bindings::atlas; int main() { std::vectorv(10); double w[10]; atlas::set (0.1, v); // v = [ 0.1 0.1 ... 0.1 ]^T atlas::set (0.2, w); // w = [ 0.2 0.2 ... 0.2 ]^T std::cout << atlas::dot (v, w) << std::endl; }
vector_traits<>
class.
This class was designed taking into account requirements of the
interfaces of BLAS levels 1 and 2 functions.
vector_traits<>
is defined in the header boost/numeric/bindings/traits/vector_traits.hpp
.
Specialisations are defined in:
Header | Vector class(es) |
---|---|
boost_array.hpp | boost::array<>
|
c_array.hpp | C array: T[N]
|
std_valarray.hpp | std::valarray<>
|
std_vector.hpp | std::vector<>
|
tnt.hpp | TNT::Array1D<> , TNT::Fortran_Array1D<>
|
ublas_matrix.hpp |
ublas::matrix_row<> , ublas::matrix_column<>
|
ublas_vector.hpp |
ublas::vector<> , ublas::c_vector<> , ublas::vector_range<> , ublas::vector_slice<>
|
All headers are in boost/numeric/bindings/traits/
.
Value type | value_type | The type of the objects contained in the vector |
Pointer type | pointer | Data type used to point to any entry of the vector in memory |
Name | Expression | Semantics |
---|---|---|
Beginning of storage | storage(v) | Returns a
pointer to the beginning of the storage of vector v
|
Size of vector | size(v) | Returns the size of
vector v
|
Stride | stride(v) | Returns the distance
between pointers pointing to consecutive entries in v
|
vector_traits<>
is implemented in three steps
(see vector_traits.hpp
):
default_vector_traits<>
,
vector_detail_traits<>
,
vector_traits<>
.
default_vector_traits<>
defines
default functionality:
template <typename V, typename T = typename V::value_type> struct default_vector_traits { typedef T value_type; typedef typename detail::generate_const<V,T>::type* pointer; static pointer storage (V& v) { return v.begin(); } static std::ptrdiff_t size (V& v) { return v.size(); } static std::ptrdiff_t stride (V& v) { return 1; } };
Metafunction generate_const<>
`copies'
const
, if present, from V
to T
,
that is, if vector type V
is non-const
,
pointer
will be T*
, and if V
is
const
, pointer
will be T const*
.
As can be seen from the implementation of function storage()
,
the assumption is that V
provides function
begin()
and that V::iterator
(or V::const_iterator
, if V
is const
) is pointer, as
e.g. uBLAS storage classes (unbounded_array<>
,
bounded_array<>
and array_adaptor<>
)
and boost::array<>
.
Also, it is assumed that V
provides function size()
and that stride is 1. If this is not the case with your vector class, you must write
specialisation.
2. Class vector_detail_traits<>
was
introduced having the writing of specialisations in mind.
It has two template parameters: VIdentifier
and VType
.
VIdentifier
is used to identify the (written) implementation
and VType
is the actual type for which the
specialisation is needed in the code which uses traits
-- VIdentifier
is always non-const
(e.g. ublas::vector<>
), while VType
can be const
(e.g. ublas::vector<>
or
ublas::vector<> const
).
Generic/default implementation is:
template <typename VIdentifier, typename VType> struct vector_detail_traits : default_vector_traits<VType> {};
3. Class vector_traits<>
is derived from
vector_detail_traits<>
. It deduces
VIdentifier
from its template parameter VType
by removing const
, if present:
template <typename VType> struct vector_traits : vector_detail_traits<typename boost::remove_const<VType>::type, VType> {};
Specialisations. Class
vector_detail_traits<>
can be specialised if
default implementation is not appropriate for particular vector type.
All specialisations must provide types defined in subsection 1.3.3 and static
member functions defined in subsection 1.3.4.
Example. Specialisation for
built-in C array (see c_array.hpp
):
template <typename T, std::size_t N, typename VType> struct vector_detail_traits<T[N],VType> { typedef T value_type; typedef typename detail::generate_const<VType,T>::type* pointer; static pointer storage (VType& a) { return a; } static std::ptrdiff_t size (VType&) { return N; } static std::ptrdiff_t stride (VType&) { return 1; } };
Example. Specialisation for std::vector<>
(see std_vector.hpp
):
template <typename T, typename Alloc, typename VType> struct vector_traits<std::vector<T, Alloc>, VType> : default_vector_traits<V,T> { typedef typename default_vector_traits<VType,T>::pointer pointer; static pointer storage (VType& v) { return &v.front(); } };Type
value_type
and functions
size()
and stride()
are inherited from
default_vector_traits<>
.
matrix_traits<>
class.
This class was designed taking into account requirements of the
interfaces of BLAS (levels 2 and 3) and LAPACK functions.
matrix_traits<>
is defined in header boost/numeric/bindings/traits/matrix_traits.hpp
.
Specialisations are defined in:
Header | Matrix classes |
---|---|
tnt.hpp | TNT::Array2D<> , TNT::Fortran_Array2D<>
|
ublas_hermitian.hpp | ublas::hermitian_matrix<> , ublas::hermitian_adaptor<>
|
ublas_matrix.hpp
| ublas::matrix<> , ublas::c_matrix<> , ublas::matrix_range<> , ublas::matrix_slice<>
|
ublas_symmetric.hpp | ublas::symmetric_matrix<> , ublas::symmetric_adaptor<>
|
ublas_vector2.hpp
| ublas::vector<> (as n-by-1 matrix), ublas::c_vector<> (as 1-by-n matrix)
|
All headers are in boost/numeric/bindings/traits/
.
Value type | value_type | The type of the objects contained in the matrix |
Pointer type | pointer | Data type used to point to any entry of the matrix in memory |
Matrix structure | matrix_structure | Describes the pattern of nonzero and zero elements and the storage layout [1] |
Ordering type | ordering_type | Row or column major [2] |
Upper/lower type | uplo_type | For triangular, symmetric and hermitian matrices: indicates whether upper or lower triangular part is referenced or stored [3] |
[1] matrix_structure
is a tag which can be:
general_t
symmetric_t
symmetric_packed_t
hermitian_t
hermitian_packed_t
unknown_structure_t
[2] ordering_type
can be:
row_major_t
column_major_t
[3] Upper/lower tag must be defined only for triangular (full and packed),
symmetric (full and packed) and hermitian (full and packed) matrices. For packed types
it indicates whether upper or lower triangular part is stored, and for
full matrices it denotes part that is referenced.
uplo_type
can be:
upper_t
lower_t
Name | Expression | Semantics |
---|---|---|
Beginning of storage | storage(m) | Returns a pointer to the
beginning of the storage of matrix m
|
Number of rows | num_rows(m) | Returns the number of rows of matrix m
|
Number of columns | num_columns(m) | Returns the number of
columns matrix m
|
Leading dimension | leading_dimension(m) | Returns the distance between pointers to the first element in consecutive rows/columns in case of row-major/column-major matrices [1] |
[1] Not needed for all matrix types (e.g. not needed for triangular, symmetric and hermitian packed matrices).
matrix_traits<>
is
similar to the vector_traits<>
's implementation
(subsection 1.3.5); only, first step is omitted because
there is no reasonable default -- different matrix libraries provide
different interfaces (for example, functions that return number of
rows and columns are named num_rows()
, num_columns()
in uBLAS, dim1()
, dim2()
in TNT,
and nrows()
, ncols()
in MTL).
Definitions in matrix_traits.hpp
are:
template <typename MIdentifier, typename MType> struct matrix_detail_traits {}; template <typename MType> struct matrix_traits : matrix_detail_traits<typename boost::remove_const::type, MType> {};
Specialisations of matrix_detail_traits<>
must provide
types defined in subsection 1.4.3 and static member functions defined
in subsection 1.4.4.
Example. Specialisation of matrix_detail_traits<>
for ublas::matrix<>
(see ublas_matrix.hpp
):
template <typename T, typename F, typename ArrT, typename MType> struct matrix_detail_traits<boost::numeric::ublas::matrix<T,F,ArrT>, Mtype> { typedef general_t matrix_structure; typedef typename detail::ublas_ordering<typename F::orientation_category>::type ordering_type; typedef T value_type; typedef typename detail::generate_const<MType,T>::type* pointer; static pointer storage (MType& m) { typedef typename detail::generate_const<MType,ArrT>::type array_type; return vector_traits<array_type>::storage (m.data()); } static std::ptrdiff_t num_rows (MType& m) { return m.size1(); } static std::ptrdiff_t num_columns (MType& m) { return m.size2(); } static std::ptrdiff_t leading_dimension (MType& m) { return F::size2 (m.size1(), m.size2()); } static std::ptrdiff_t stride1 (MType& m) { return F::one1 (m.size1(), m.size2()); } static std::ptrdiff_t stride2 (MType& m) { return F::one2 (m.size1(), m.size2()); } };Notes:
[1] As ublas::matrix<>
is general matrix,
uplo_type
is not defined.
[2] Metafunction detail::ublas_ordering<>
(defined
in detail/ublas_ordering.hpp
)
maps orientation_category
, as defined in uBLAS, to corresponding ordering type.
[3] Note that the storage()
function uses
vector_traits::storage<>()
.
[4] This specialisation also defines functions stride1()
and
stride2()
because they are needed in specialisations of
vector_traits<>
for ublas::matrix_row<>
and ublas::matrix_column<>
.
Example. Specialisation of matrix_detail_traits<>
for ublas::symmetric_matrix<>
(see ublas_symmetric.hpp
):
template <typename T, typename F1, typename F2, typename A, typename MType> struct matrix_detail_traits<boost::numeric::ublas::symmetric_matrix<T, F1, F2, A>, Mtype> { typedef symmetric_packed_t matrix_structure; typedef typename detail::ublas_ordering<typename F2::orientation_category>::type ordering_type; typedef typename detail::ublas_uplo<typename F1::packed_category>::type uplo_type; typedef T value_type; typedef typename detail::generate_const<MType,T>::type* pointer; static pointer storage (MType& sm) { typedef typename detail::generate_const<MType,A>::type array_type ; return vector_traits<array_type>::storage (sm.data()); } static std::ptrdiff_t num_rows (MType& sm) { return sm.size1(); } static std::ptrdiff_t num_columns (MType& sm) { return sm.size2(); } };This specialisation defines
uplo_type
, but
leading_dimension()
makes no sense for packed matrix
storage types.
sparse_matrix_traits<>
class.
sparse_matrix_traits<>
is defined in header boost/numeric/bindings/traits/sparse_traits.hpp
.
Specialisations are defined in:
Header | Matrix classes |
---|---|
ublas_sparse.hpp | ublas::compressed_matrix<> , ublas::coordinate_matrix<>
|
All headers are in boost/numeric/bindings/traits/
.
Value type | value_type | The type of the objects contained in the matrix |
Value pointer type | value_pointer | Data type used to point to (nonzero) matrix elements |
Index pointer type | index_pointer | Data type used to point to row and column indices |
Matrix structure | matrix_structure | Describes the pattern of nonzero and zero elements and the storage layout [1] |
Ordering type | ordering_type | Row or column major [2] |
Storage format | storage_format | Data structure used to store the matrix [3] |
[1] matrix_structure
is a tag which can be:
general_t
[2] ordering_type
can be:
row_major_t
column_major_t
[3] storage_format
can be:
compressed_t
coordinate_t
BOOST_STATIC_CONSTANT (std::size_t, index_base);
Name | Expression | Semantics |
---|---|---|
Major index | index1_storage(m) |
Depends on storage_format and ordering_type [1]
|
Minor index | index2_storage(m) |
Depends on storage_format and ordering_type [2]
|
Element storage | storage(m) | Returns a pointer to the beginning of the storage of matrix entries [3] |
Number of rows | num_rows(m) | Returns the number of rows of matrix m
|
Number of columns | num_columns(m) | Returns the number of
columns matrix m
|
Number of entries | num_nonzeros(m) | Returns the number of matrix entries [3] |
[1] Returned value is a pointer to the beginning of:
the array of column start locations | for compressed column format; | |||
the array of row start locations | for compressed row format; | |||
the array of column indices | for column major coordinate format; | |||
the array of row indices | for row major coordinate format. |
[2] Returned value is a pointer to the beginning of:
the array of row indices | for compressed column format; | |||
the array of column indices | for compressed row format; | |||
the array of row indices | for column major coordinate format; | |||
the array of column indices | for row major coordinate format. |
[3] All nonzeros are entries, but an entry may be numerically zero.
sparse_matrix_traits<>
is
similar to the matrix_traits<>
's implementation
(subsection 1.4.5).
Specialisations of sparse_matrix_detail_traits<>
must provide
types defined in subsection 1.5.3,
static constants defined in subsection 1.5.4
and static member functions defined in subsection 1.5.5.
There are also free functions available to obtain storage layout information:
vector_traits.hpp
:
Expression | Semantics |
---|---|
vector_storage(v) | Returns a
pointer to the beginning of the storage of vector v
|
vector_size(v) | Returns the size of
vector v
|
vector_stride(v) | Returns the distance
between pointers pointing to consecutive entries in v
|
matrix_traits.hpp
:
Expression | Semantics |
---|---|
matrix_storage(m) | Returns a pointer to the
beginning of the storage of matrix m
|
matrix_num_rows(m) | Returns the number of rows of matrix m
|
matrix_num_columns(m) | Returns the number of
columns matrix m
|
leading_dimension(m) | Returns the leading
dimension of matrix m
|
The syntax of these is slightly simpler than that of the traits class; e.g. instead of
traits::vector_traits<some_vector_type const>::storage (v)one can write
traits::vector_storage (v)
Although these free functions generally rely
on the traits classes, they can also implement an alternative strategy
on compilers that are unable to handle the traits idiom (see
vector_raw.hpp
and matrix_raw.hpp
).
To facilitate generic bindings for libraries of which the API is defined in Fortran, the Traits Library provides a multi-platform mapping between C and Fortran calling conventions: some Fortran compilers add a trailing underscore to all defined symbols, some generate symbols in uppercase only.
When including the traits/fortran.h
header, one of following
symbols will be defined:
BIND_FORTRAN_LOWERCASE_UNDERSCORE
BIND_FORTRAN_LOWERCASE
FORTRAN_ID
macro:
#if defined(BIND_FORTRAN_LOWERCASE_UNDERSCORE) #define FORTRAN_ID( id ) id##_ #elif defined(BIND_FORTRAN_LOWERCASE) #define FORTRAN_ID( id ) id #endif
Here's more information on how to call Fortran routines from C and C++.
See type.h for mapping of Fortran types to C.
See type.hpp for mapping of Fortran types to C++
See value_traits.hpp for value_type inside complex types.