C++ Boost

Boost.Numeric.Bindings.Traits



Back to Bindings Library Synopsis

Contents

  1. Generic Storage Layout Information
    1. Rationale
    2. Using Traits Classes
    3. Vector Traits
      1. Description
      2. Definition
      3. Associated Types
      4. Expression Semantics
      5. Implementation
    4. Matrix Traits
      1. Description
      2. Definition
      3. Associated Types
      4. Expression Semantics
      5. Implementation
    5. Sparse Matrix Traits
      1. Description
      2. Definition
      3. Associated Types
      4. Static Constants
      5. Expression Semantics
      6. Implementation
    6. Free functions
  2. Calling Conventions
  3. Type Mapping

1. Generic Storage Layout Information

1.1 Rationale

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.

1.2 Using Traits Classes

To use particular vector or matrix class in bindings to some external library, proper traits specialisation must be included. Specialisations for following vector and matrix classes are currently available: All mentioned files are in the directory 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::vector v(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; 
  }

1.3 Vector Traits

1.3.1.Description

Generic bindings functions which manipulate vectors are written in terms of types (subsection 1.3.3) and static functions (subsection 1.3.4) defined in the vector_traits<> class. This class was designed taking into account requirements of the interfaces of BLAS levels 1 and 2 functions.

1.3.2.Definition

Generic class vector_traits<> is defined in the header boost/numeric/bindings/traits/vector_traits.hpp.

Specialisations are defined in:

HeaderVector 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/.

1.3.3 Associated Types

Value typevalue_typeThe type of the objects contained in the vector
Pointer typepointerData type used to point to any entry of the vector in memory

1.3.4 Expression Semantics

NameExpressionSemantics
Beginning of storagestorage(v)Returns a pointer to the beginning of the storage of vector v
Size of vectorsize(v)Returns the size of vector v
Stridestride(v)Returns the distance between pointers pointing to consecutive entries in v

1.3.5 Implementation

Class vector_traits<> is implemented in three steps (see vector_traits.hpp):
  1. definition of class default_vector_traits<>,
  2. definition of class vector_detail_traits<>,
  3. definition of class vector_traits<>.
1. Class 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<>.

1.4 Matrix Traits

1.4.1 Description

Generic bindings functions which manipulate matrices are written in terms of types (subsection 1.4.3) and static functions (subsection 1.4.4) defined in the matrix_traits<> class. This class was designed taking into account requirements of the interfaces of BLAS (levels 2 and 3) and LAPACK functions.

1.4.2 Definition

Generic class matrix_traits<> is defined in header boost/numeric/bindings/traits/matrix_traits.hpp.

Specialisations are defined in:

HeaderMatrix 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/.

1.4.3 Associated Types

Value typevalue_typeThe type of the objects contained in the matrix
Pointer typepointerData type used to point to any entry of the matrix in memory
Matrix structurematrix_structureDescribes the pattern of nonzero and zero elements and the storage layout [1]
Ordering typeordering_typeRow or column major [2]
Upper/lower typeuplo_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:

[2] ordering_type can be:

[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:

1.4.4 Expression Semantics

NameExpressionSemantics
Beginning of storagestorage(m)Returns a pointer to the beginning of the storage of matrix m
Number of rowsnum_rows(m)Returns the number of rows of matrix m
Number of columnsnum_columns(m)Returns the number of columns matrix m
Leading dimensionleading_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).

1.4.5 Implementation

Implementation of 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.

1.5 Sparse Matrix Traits

1.5.1 Description

Generic bindings functions which manipulate sparse matrices are written in terms of types (subsection 1.5.3), static constants (subsection 1.5.4) and static functions (subsection 1.5.5) defined in the sparse_matrix_traits<> class.

1.5.2 Definition

Generic class sparse_matrix_traits<> is defined in header boost/numeric/bindings/traits/sparse_traits.hpp.

Specialisations are defined in:

HeaderMatrix classes
ublas_sparse.hpp ublas::compressed_matrix<>, ublas::coordinate_matrix<>

All headers are in boost/numeric/bindings/traits/.

1.5.3 Associated Types

Value typevalue_typeThe type of the objects contained in the matrix
Value pointer typevalue_pointerData type used to point to (nonzero) matrix elements
Index pointer typeindex_pointerData type used to point to row and column indices
Matrix structurematrix_structureDescribes the pattern of nonzero and zero elements and the storage layout [1]
Ordering typeordering_typeRow or column major [2]
Storage formatstorage_formatData structure used to store the matrix [3]

[1] matrix_structure is a tag which can be:

[2] ordering_type can be:

[3] storage_format can be:

1.5.4 Static Constants

BOOST_STATIC_CONSTANT (std::size_t, index_base);

1.5.5 Expression Semantics

NameExpressionSemantics
Major indexindex1_storage(m) Depends on storage_format and ordering_type [1]
Minor indexindex2_storage(m) Depends on storage_format and ordering_type [2]
Element storagestorage(m)Returns a pointer to the beginning of the storage of matrix entries [3]
Number of rowsnum_rows(m)Returns the number of rows of matrix m
Number of columnsnum_columns(m)Returns the number of columns matrix m
Number of entriesnum_nonzeros(m)Returns the number of matrix entries [3]

[1] Returned value is a pointer to the beginning of:

the array of column start locationsfor compressed column format;
the array of row start locationsfor compressed row format;
the array of column indicesfor column major coordinate format;
the array of row indicesfor row major coordinate format.

[2] Returned value is a pointer to the beginning of:

the array of row indicesfor compressed column format;
the array of column indicesfor compressed row format;
the array of row indicesfor column major coordinate format;
the array of column indicesfor row major coordinate format.

[3] All nonzeros are entries, but an entry may be numerically zero.

1.5.6 Implementation

Implementation of 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.

1.6 Free functions

There are also free functions available to obtain storage layout information:

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).

2. Calling conventions

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:

Function names are generated using the 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++.

3. Type mapping

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.