📄 compressed2d.hpp
字号:
if (indices.empty())
return utilities::maybe<size_t> (0, false);
// &v[i] isn't liked by all libs -> &v[0]+i circumvents complaints
const size_t *first = &indices[0] + starts[major],
*last = &indices[0] + slot_ends[major];
if (first == last)
return utilities::maybe<size_t> (first - &indices[0], false);
const size_t *index = std::lower_bound(first, last, minor);
return utilities::maybe<size_t> (index - &indices[0], index != last && *index == minor);
}
template <typename Elt, typename Parameters, typename Updater>
inline void compressed2D_inserter<Elt, Parameters, Updater>::update(size_type row, size_type col, value_type val)
{
using std::copy_backward;
Updater updater;
compressed2D_indexer indexer;
size_pair mm = indexer.major_minor_c(matrix, row, col);
size_type major, minor;
boost::tie(major, minor) = mm;
utilities::maybe<size_type> pos = matrix_offset(mm);
// Check if already in matrix and update it
if (pos)
updater (elements[pos], val);
else {
size_type& my_end = slot_ends[major];
// Check if place in matrix to insert there
if (my_end != starts[major+1]) {
copy_backward(&elements[0] + pos.value(), &elements[0] + my_end, &elements[0] + (my_end+1));
copy_backward(&indices[0] + pos.value(), &indices[0] + my_end, &indices[0] + (my_end+1));
elements[pos] = updater.init(val); indices[pos] = minor;
my_end++;
matrix.my_nnz++; // new entry
} else {
typename map_type::iterator it = spare.find(mm);
// If not in map insert it, otherwise update the value
if (it == spare.end()) {
spare.insert(std::make_pair(mm, updater.init(val)));
matrix.my_nnz++; // new entry
} else
updater(it->second, val);
}
}
// std::cout << "inserter update: " << matrix.my_nnz << " non-zero elements, new value is " << elements[pos] << "\n";
}
template <typename Elt, typename Parameters, typename Updater>
void compressed2D_inserter<Elt, Parameters, Updater>::final_place()
{
using std::swap;
size_type dim1 = matrix.dim1();
std::vector<size_type> new_starts(dim1 + 1);
new_starts[0] = 0;
typename map_type::iterator it = spare.begin();
for (size_type i = 0; i < dim1; i++) {
size_type entries = slot_ends[i] - starts[i];
while (it != spare.end() && it->first.first == i)
entries++, it++;
new_starts[i+1] = new_starts[i] + entries;
}
size_type new_total = new_starts[dim1], old_total = starts[dim1];
if (new_total > old_total) {
elements.resize(new_total);
indices.resize(new_total); }
operations::shift_blocks(dim1, starts, new_starts, slot_ends, elements);
operations::shift_blocks(dim1, starts, new_starts, slot_ends, indices);
if (new_total < old_total) {
elements.resize(new_total);
indices.resize(new_total); }
for (size_type i = 0; i < dim1; i++)
slot_ends[i] = new_starts[i] + slot_ends[i] - starts[i];
swap(starts, new_starts);
}
template <typename Elt, typename Parameters, typename Updater>
void compressed2D_inserter<Elt, Parameters, Updater>::insert_spare()
{
using std::copy_backward;
for (typename map_type::iterator it = spare.begin(); it != spare.end(); ++it) {
size_pair mm = it->first;
size_type major = mm.first, minor = mm.second;
utilities::maybe<size_type> pos = matrix_offset(mm);
size_type& my_end = slot_ends[major];
// &v[i] see above
copy_backward(&elements[0] + pos.value(), &elements[0] + my_end, &elements[0] + (my_end+1));
copy_backward(&indices[0] + pos.value(), &indices[0] + my_end, &indices[0] + (my_end+1));
elements[pos] = it->second; indices[pos] = minor;
my_end++;
}
}
// ================
// Free functions
// ================
template <typename Value, typename Parameters>
typename compressed2D<Value, Parameters>::size_type
inline num_rows(const compressed2D<Value, Parameters>& matrix)
{
return matrix.num_rows();
}
template <typename Value, typename Parameters>
typename compressed2D<Value, Parameters>::size_type
inline num_cols(const compressed2D<Value, Parameters>& matrix)
{
return matrix.num_cols();
}
template <typename Value, typename Parameters>
typename compressed2D<Value, Parameters>::size_type
inline size(const compressed2D<Value, Parameters>& matrix)
{
return matrix.num_cols() * matrix.num_rows();
}
// ================
// Range generators
// ================
namespace traits
{
// VC 8.0 finds ambiguity with mtl::tag::morton_dense (I wonder why, especially here)
using mtl::compressed2D;
// ===========
// For cursors
// ===========
template <class Elt, class Parameters>
struct range_generator<glas::tag::nz, compressed2D<Elt, Parameters> >
: detail::all_offsets_range_generator<compressed2D<Elt, Parameters>,
compressed_el_cursor<Elt, Parameters>,
complexity_classes::linear_cached>
{};
// Cursor over all rows
// Supported if row major matrix
template <typename Elt, typename Parameters>
struct range_generator<glas::tag::row, compressed2D<Elt, Parameters> >
: boost::mpl::if_<
boost::is_same<typename Parameters::orientation, row_major>
, detail::all_rows_range_generator<compressed2D<Elt, Parameters>, complexity_classes::linear_cached>
, range_generator<tag::unsupported, compressed2D<Elt, Parameters> >
>::type {};
template <class Elt, class Parameters>
struct range_generator<glas::tag::nz,
detail::sub_matrix_cursor<compressed2D<Elt, Parameters>, glas::tag::row, 2> >
{
typedef detail::sub_matrix_cursor<compressed2D<Elt, Parameters>, glas::tag::row, 2> cursor_type;
typedef complexity_classes::linear_cached complexity;
typedef compressed_minor_cursor<Elt, Parameters> type;
static int const level = 1;
type begin(cursor_type const& cursor) const
{
return type(cursor.ref, cursor.key, cursor.ref.begin_col());
}
type end(cursor_type const& cursor) const
{
return type(cursor.ref, cursor.key, cursor.ref.end_col());
}
};
// Cursor over all columns
// Supported if column major matrix
template <typename Elt, typename Parameters>
struct range_generator<glas::tag::col, compressed2D<Elt, Parameters> >
: boost::mpl::if_<
boost::is_same<typename Parameters::orientation, col_major>
, detail::all_cols_range_generator<compressed2D<Elt, Parameters>, complexity_classes::linear_cached>
, range_generator<tag::unsupported, compressed2D<Elt, Parameters> >
>::type {};
template <class Elt, class Parameters>
struct range_generator<glas::tag::nz,
detail::sub_matrix_cursor<compressed2D<Elt, Parameters>, glas::tag::col, 2> >
{
typedef detail::sub_matrix_cursor<compressed2D<Elt, Parameters>, glas::tag::col, 2> cursor_type;
typedef complexity_classes::linear_cached complexity;
typedef compressed_minor_cursor<Elt, Parameters> type;
static int const level = 1;
type begin(cursor_type const& cursor) const
{
return type(cursor.ref, cursor.ref.begin_row(), cursor.key);
}
type end(cursor_type const& cursor) const
{
return type(cursor.ref, cursor.ref.end_row(), cursor.key);
}
};
// Cursor over all rows or columns, depending which one is major
template <typename Elt, typename Parameters>
struct range_generator<glas::tag::major, compressed2D<Elt, Parameters> >
: boost::mpl::if_<
boost::is_same<typename Parameters::orientation, row_major>
, range_generator<glas::tag::row, compressed2D<Elt, Parameters> >
, range_generator<glas::tag::col, compressed2D<Elt, Parameters> >
>::type {};
// =============
// For iterators
// =============
template <class Elt, class Parameters>
struct range_generator<tag::const_iter::nz,
detail::sub_matrix_cursor<compressed2D<Elt, Parameters>, glas::tag::row, 2> >
{
typedef compressed2D<Elt, Parameters> matrix_type;
typedef typename matrix_type::size_type size_type;
typedef typename matrix_type::value_type value_type;
typedef detail::sub_matrix_cursor<matrix_type, glas::tag::row, 2> cursor;
typedef complexity_classes::linear_cached complexity;
static int const level = 1;
typedef const value_type* type;
type begin(cursor const& c)
{
const matrix_type& matrix= c.ref;
size_type offset= matrix.indexer(matrix, c.key, matrix.begin_col());
return &matrix.data[0] + offset;
}
// returned pointer can pass the end and must only be used for comparison
type end(cursor const& c)
{
const matrix_type& matrix= c.ref;
size_type offset= matrix.indexer(matrix, c.key, matrix.end_col());
return &matrix.data[0] + offset;
}
};
template <class Elt, class Parameters>
struct range_generator<tag::const_iter::nz,
detail::sub_matrix_cursor<compressed2D<Elt, Parameters>, glas::tag::col, 2> >
{
typedef compressed2D<Elt, Parameters> matrix_type;
typedef typename matrix_type::size_type size_type;
typedef typename matrix_type::value_type value_type;
typedef detail::sub_matrix_cursor<matrix_type, glas::tag::col, 2> cursor;
typedef complexity_classes::linear_cached complexity;
static int const level = 1;
typedef const value_type* type;
type begin(cursor const& c)
{
const matrix_type& matrix= c.ref;
size_type offset= matrix.indexer(matrix, matrix.begin_row(), c.key);
return &matrix.data[0] + offset;
}
// returned pointer can pass the end and must only be used for comparison
type end(cursor const& c)
{
const matrix_type& matrix= c.ref;
size_type offset= matrix.indexer(matrix, matrix.end_row(), c.key);
return &matrix.data[0] + offset;
}
};
} // namespace traits
} // namespace mtl
#endif // MTL_COMPRESSED2D_INCLUDE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -