lin
Classes
Traits

Set of template metaprogramming constructs to examine compile time information about tensor types. More...

Classes

struct  lin::internal::_elem< C >
 Provides a tensor type's element type. More...
 
struct  lin::internal::_eval< C, typename >
 Provides a specific tensor type's evaluation type. More...
 
struct  lin::internal::_dims< C >
 Provides a specific tensor type's compile time dimensions. More...
 
struct  lin::internal::traits< C >
 Collection of compile time information about a specific tensor class. More...
 
struct  lin::internal::has_traits< C >
 Tests if a type has traits. More...
 
struct  lin::internal::has_fixed_rows< C >
 Tests if a tensor type has a fixed row count. More...
 
struct  lin::internal::has_fixed_cols< C >
 Tests if a tensor type has a fixed column count. More...
 
struct  lin::internal::has_fixed_dimensions< C >
 Tests if a tensor type has fixed dimensions. More...
 
struct  lin::internal::has_strictly_bounded_rows< C >
 Tests is a tensor type has a strictly bounded row count. More...
 
struct  lin::internal::has_strictly_bounded_cols< C >
 Tests if a tensor type has a strictly bounded column count. More...
 
struct  lin::internal::has_strictly_bounded_dimensions< C >
 Tests if a tensor type has strictly bounded dimensions. More...
 
struct  lin::internal::has_bounded_rows< C >
 Tests if a tensor type has a bounded row count. More...
 
struct  lin::internal::has_bounded_cols< C >
 Tests if a tensor type has a bounded column count. More...
 
struct  lin::internal::has_bounded_dimensions< C >
 Tests if a tensor type has bounded dimensions. More...
 
struct  lin::internal::has_valid_traits< C >
 Tests if a tensor type's traits are valid. More...
 
struct  lin::internal::is_tall< C >
 Tests if a tensor type is "tall". More...
 
struct  lin::internal::is_short< C >
 Tests if a tensor type is "short". More...
 
struct  lin::internal::is_square< C >
 Tests if a tensor type is "square". More...
 
struct  lin::internal::have_same_elements< Cs >
 Tests if a set of tensor types all have the same element type. More...
 
struct  lin::internal::have_floating_point_elements< Cs >
 Tests if a set of tensor types all have floating point elements. More...
 
struct  lin::internal::have_integral_elements< Cs >
 Tests if a set of tensor types all have integral elements. More...
 
struct  lin::internal::have_same_rows< Cs >
 Tests if a set of tensor types all have the same row traits. More...
 
struct  lin::internal::have_same_cols< Cs >
 Tests if a set of tensor types all have the same column traits. More...
 
struct  lin::internal::have_same_dimensions< Cs >
 Tests if a set of tensor types all have the same dimensions. More...
 
struct  lin::internal::have_same_traits< Cs >
 Tests if a set of tensor types all have the same traits. More...
 
struct  lin::internal::is_row_vector< C >
 Tests if a tensor type is a row vector. More...
 
struct  lin::internal::is_col_vector< C >
 Tests if a tensor type is a column vector. More...
 
struct  lin::internal::is_vector< C >
 Tests if a tensor type is a vector. More...
 
struct  lin::internal::vector_traits< C >
 Collection of compile time information describing a tensor type which is deemed a vector. More...
 
struct  lin::internal::have_same_vector_dimensions< Cs >
 Tests if a set of vector types all have the same dimensions. More...
 
struct  lin::internal::have_same_vector_traits< Cs >
 Tests if a set of vector types all have the same vector traits. More...
 
struct  lin::internal::is_matrix< C >
 Tests if a tensor type is a matrix. More...
 

Detailed Description

Set of template metaprogramming constructs to examine compile time information about tensor types.

Overview

The traits module serves two main purposes:

  1. Provide a mechanism for the leaves of the lin inheritance tree communicate their compile time traits to their parents classes.
  2. Give a set of structs to help query properties about these traits.

All of this allows incredibly flexible implementations of tensor operators. They can, for example, detect at compile time whether or not a given operation "makes sense" with two arbitrary tensor types.

Providing Traits Information

Every type in lin has traits information associated with it (see internal::traits). All leaves of the lin inheritance tree must provide traits information by define a template specialization for internal::_elem and internal::_dims.

For example, the Vector class specifies it's traits like so:

namespace lin {
template <typename T, size_t N, size_t MN = N>
class Vector : ... { ... };
namespace internal {
template <typename T, size_t N, size_t MN>
struct _elem<Vector<T, N, MN>> {
typedef T type;
};
template <typename T, size_t N, size_t MN>
struct _dims<Vector<T, N, MN>> {
static constexpr size_t rows = N;
static constexpr size_t cols = 1;
static constexpr size_t max_rows = MN;
static constexpr size_t max_cols = 1;
};
} // namespace internal
} // namespace lin

Those struct defintions along with internal::_eval (which we won't get into here) are then used by internal::traits to complete each types trait's set.

Using Traits Information

As previously mentioned, the template metaprogramming constructs provided by the traits module are commonly used in std::enable_if guards for tensor operations.

As an example, consider tyring to enable a tensor element wise addition operator when appropriate. Logically, this requires two things of the input types to be true:

  1. The tensor elements types must be able to add together.
  2. The tensor's should have the same dimensions traits.

As such, we would define an enable if guard similiar to the following:

namespace lin {
namespace internal {
template <typename T, typename U>
using add_expr = decltype(std::declval<T &>() + std::declval<U &>());
template <class C, class D>
struct can_add
: conjunction<is_dectected<add_expr, _elem_t<C>, _elem_t<D>>, have_same_dimensions<C, D>> { };
template <class C, class D, std::enable_if_t<can_add<C, D>::value, size_t> = 0>
constexpr auto operator+(Stream<C> const &, Stream<D> const &) { ... }
} // namespace internal
} // namespace lin

This can be extended to matrix factorizations and more complex operations. See the list of structs above for more ideas!