📄 dense2d.hpp
字号:
}; // dense2D
// ================
// Free functions
// ================
template <typename Value, typename Parameters>
typename dense2D<Value, Parameters>::size_type
inline num_rows(const dense2D<Value, Parameters>& matrix)
{
return matrix.num_rows();
}
template <typename Value, typename Parameters>
typename dense2D<Value, Parameters>::size_type
inline num_cols(const dense2D<Value, Parameters>& matrix)
{
return matrix.num_cols();
}
template <typename Value, typename Parameters>
typename dense2D<Value, Parameters>::size_type
inline size(const dense2D<Value, Parameters>& matrix)
{
return matrix.num_cols() * matrix.num_rows();
}
namespace traits
{
// VC 8.0 finds ambiguity with mtl::tag::morton_dense (I wonder why, especially here)
using mtl::dense2D;
// ================
// Range generators
// For cursors
// ================
template <typename Value, typename Parameters>
struct range_generator<glas::tag::all, dense2D<Value, Parameters> >
: detail::dense_element_range_generator<dense2D<Value, Parameters>,
dense_el_cursor<Value>, complexity_classes::linear_cached>
{};
template <typename Value, typename Parameters>
struct range_generator<glas::tag::nz, dense2D<Value, Parameters> >
: detail::dense_element_range_generator<dense2D<Value, Parameters>,
dense_el_cursor<Value>, complexity_classes::linear_cached>
{};
namespace detail
{
// complexity of dense row cursor depends on storage scheme
// if orientation is row_major then complexity is cached_linear, otherwise linear
template <typename Orientation> struct dense2D_rc {};
template<> struct dense2D_rc<row_major>
{
typedef complexity_classes::linear_cached type;
};
template<> struct dense2D_rc<col_major>
{
typedef complexity_classes::linear type;
};
// Complexity of column cursor is of course opposite
template <typename Orientation> struct dense2D_cc
: dense2D_rc<typename transposed_orientation<Orientation>::type>
{};
}
template <typename Value, typename Parameters>
struct range_generator<glas::tag::row, dense2D<Value, Parameters> >
: detail::all_rows_range_generator<dense2D<Value, Parameters>,
typename detail::dense2D_rc<typename Parameters::orientation>::type>
{};
// For a cursor pointing to some row give the range of elements in this row
template <typename Value, typename Parameters>
struct range_generator<glas::tag::nz,
detail::sub_matrix_cursor<dense2D<Value, Parameters>, glas::tag::row, 2> >
{
typedef dense2D<Value, Parameters> matrix;
typedef typename matrix::size_type size_type;
typedef detail::sub_matrix_cursor<matrix, glas::tag::row, 2> cursor;
// linear for col_major and linear_cached for row_major
typedef typename detail::dense2D_rc<typename Parameters::orientation>::type complexity;
static int const level = 1;
typedef typename boost::mpl::if_<
boost::is_same<typename Parameters::orientation, row_major>
, dense_el_cursor<Value>
, strided_dense_el_cursor<Value>
>::type type;
private:
type dispatch(cursor const& c, size_type col, row_major)
{
return type(c.ref, c.key, col);
}
type dispatch(cursor const& c, size_type col, col_major)
{
return type(c.ref, c.key, col, c.ref.ldim);
}
public:
type begin(cursor const& c)
{
return dispatch(c, c.ref.begin_col(), typename matrix::orientation());
}
type end(cursor const& c)
{
return dispatch(c, c.ref.end_col(), typename matrix::orientation());
}
};
template <typename Value, typename Parameters>
struct range_generator<glas::tag::all,
detail::sub_matrix_cursor<dense2D<Value, Parameters>, glas::tag::row, 2> >
: range_generator<glas::tag::nz,
detail::sub_matrix_cursor<dense2D<Value, Parameters>, glas::tag::row, 2> >
{};
template <typename Value, typename Parameters>
struct range_generator<glas::tag::col, dense2D<Value, Parameters> >
: detail::all_cols_range_generator<dense2D<Value, Parameters>,
typename detail::dense2D_cc<typename Parameters::orientation>::type>
{};
// For a cursor pointing to some row give the range of elements in this row
template <typename Value, typename Parameters>
struct range_generator<glas::tag::nz,
detail::sub_matrix_cursor<dense2D<Value, Parameters>, glas::tag::col, 2> >
{
typedef dense2D<Value, Parameters> matrix;
typedef typename matrix::size_type size_type;
typedef detail::sub_matrix_cursor<matrix, glas::tag::col, 2> cursor;
typedef typename detail::dense2D_cc<typename Parameters::orientation>::type complexity;
static int const level = 1;
typedef typename boost::mpl::if_<
boost::is_same<typename Parameters::orientation, col_major>
, dense_el_cursor<Value>
, strided_dense_el_cursor<Value>
>::type type;
private:
type dispatch(cursor const& c, size_type row, col_major)
{
return type(c.ref, row, c.key);
}
type dispatch(cursor const& c, size_type row, row_major)
{
return type(c.ref, row, c.key, c.ref.ldim);
}
public:
type begin(cursor const& c)
{
return dispatch(c, c.ref.begin_row(), typename matrix::orientation());
}
type end(cursor const& c)
{
return dispatch(c, c.ref.end_row(), typename matrix::orientation());
}
};
template <typename Value, typename Parameters>
struct range_generator<glas::tag::all,
detail::sub_matrix_cursor<dense2D<Value, Parameters>, glas::tag::col, 2> >
: public range_generator<glas::tag::nz,
detail::sub_matrix_cursor<dense2D<Value, Parameters>, glas::tag::col, 2> >
{};
// =============
// For iterators
// =============
namespace detail {
// Traversal along major dimension first and then along minor
template <typename OuterTag, typename Orientation>
struct major_traversal
{
static const bool value= false;
};
template <> struct major_traversal<glas::tag::row, row_major>
{
static const bool value= true;
};
template <> struct major_traversal<glas::tag::col, col_major>
{
static const bool value= true;
};
template <typename OuterTag, typename Matrix, bool is_const>
struct dense2D_iterator_range_generator
{
typedef Matrix matrix_type;
typedef typename matrix_type::size_type size_type;
typedef typename matrix_type::value_type value_type;
typedef typename matrix_type::parameters parameters;
typedef detail::sub_matrix_cursor<matrix_type, OuterTag, 2> cursor;
// if traverse first along major dimension then memory access is contiguous (otherwise strided)
typedef typename boost::mpl::if_<
major_traversal<OuterTag, typename parameters::orientation>
, complexity_classes::linear_cached
, complexity_classes::linear
>::type complexity;
static int const level = 1;
// if traverse first along major dimension use pointer otherwise strided iterator
typedef typename boost::mpl::if_<
major_traversal<OuterTag, typename parameters::orientation>
, typename boost::mpl::if_c<
is_const
, const value_type*
, value_type*
>::type
, typename boost::mpl::if_c<
is_const
, strided_dense_el_const_iterator<value_type>
, strided_dense_el_iterator<value_type>
>::type
>::type type;
private:
// if traverse first along major dim. then return address as pointer
type dispatch(cursor const& c, size_type row, size_type col, complexity_classes::linear_cached)
{
// cast const away (is dirty and should be improved later (cursors must distinct constness))
matrix_type& ref= const_cast<matrix_type&>(c.ref);
return &ref[row][col];
}
// otherwise strided
type dispatch(cursor const& c, size_type row, size_type col, complexity_classes::linear)
{
// cast const away (is dirty and should be improved later (cursors must distinct constness))
matrix_type& ref= const_cast<matrix_type&>(c.ref);
return type(ref, row, col, ref.ldim);
}
type begin_dispatch(cursor const& c, glas::tag::row)
{
return dispatch(c, c.key, c.ref.begin_col(), complexity());
}
type end_dispatch(cursor const& c, glas::tag::row)
{
return dispatch(c, c.key, c.ref.end_col(), complexity());
}
type begin_dispatch(cursor const& c, glas::tag::col)
{
return dispatch(c, c.ref.begin_row(), c.key, complexity());
}
type end_dispatch(cursor const& c, glas::tag::col)
{
return dispatch(c, c.ref.end_row(), c.key, complexity());
}
public:
type begin(cursor const& c)
{
return begin_dispatch(c, OuterTag());
}
type end(cursor const& c)
{
return end_dispatch(c, OuterTag());
}
};
} // namespace detail
template <typename Value, typename Parameters, typename OuterTag>
struct range_generator<tag::iter::nz,
detail::sub_matrix_cursor<dense2D<Value, Parameters>, OuterTag, 2> >
: public detail::dense2D_iterator_range_generator<OuterTag, dense2D<Value, Parameters>, false>
{};
template <typename Value, typename Parameters, typename OuterTag>
struct range_generator<tag::iter::all,
detail::sub_matrix_cursor<dense2D<Value, Parameters>, OuterTag, 2> >
: public detail::dense2D_iterator_range_generator<OuterTag, dense2D<Value, Parameters>, false>
{};
template <typename Value, typename Parameters, typename OuterTag>
struct range_generator<tag::const_iter::nz,
detail::sub_matrix_cursor<dense2D<Value, Parameters>, OuterTag, 2> >
: public detail::dense2D_iterator_range_generator<OuterTag, dense2D<Value, Parameters>, true>
{};
template <typename Value, typename Parameters, typename OuterTag>
struct range_generator<tag::const_iter::all,
detail::sub_matrix_cursor<dense2D<Value, Parameters>, OuterTag, 2> >
: public detail::dense2D_iterator_range_generator<OuterTag, dense2D<Value, Parameters>, true>
{};
} // namespace traits
// ==========
// Sub matrix
// ==========
template <typename Value, typename Parameters>
struct sub_matrix_t<dense2D<Value, Parameters> >
{
typedef dense2D<Value, Parameters> matrix_type;
typedef matrix_type sub_matrix_type;
typedef matrix_type const const_sub_matrix_type;
typedef typename matrix_type::size_type size_type;
sub_matrix_type operator()(matrix_type& matrix, size_type begin_r, size_type end_r, size_type begin_c, size_type end_c)
{
matrix.check_ranges(begin_r, end_r, begin_c, end_c);
sub_matrix_type tmp(matrix);
// Sub-matrix doesn't own the memory (and must not free at the end)
tmp.extern_memory= true;
// tmp.ldim= matrix.ldim; // or in copy constructor ?
// Treat empty sub-matrices specially
if(end_r <= begin_r || end_c <= begin_c)
tmp.set_ranges(0, 0);
else {
// Leading dimension doesn't change
tmp.data += matrix.indexer(matrix, begin_r, begin_c); // Takes care of indexing
tmp.set_ranges(end_r - begin_r, end_c - begin_c);
}
return tmp;
}
const_sub_matrix_type
operator()(matrix_type const& matrix, size_type begin_r, size_type end_r, size_type begin_c, size_type end_c)
{
// To minimize code duplication, we use the non-const version
sub_matrix_type tmp((*this)(const_cast<matrix_type&>(matrix), begin_r, end_r, begin_c, end_c));
return tmp;
}
};
} // namespace mtl
#endif // MTL_DENSE2D_INCLUDE
/*
Limitations:
- with compile-time constant dimension, submatrices are not supported (would violate self-similarity)
- Element cursor doesn't work for sub-matrices (not contiguous)
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -