📄 compressed2d.hpp
字号:
// Software License for MTL// // Copyright (c) 2007 The Trustees of Indiana University. All rights reserved.// Authors: Peter Gottschling and Andrew Lumsdaine// // This file is part of the Matrix Template Library// // See also license.mtl.txt in the distribution.
#ifndef MTL_COMPRESSED2D_INCLUDE
#define MTL_COMPRESSED2D_INCLUDE
#include <algorithm>
#include <vector>
#include <map>
#include <boost/tuple/tuple.hpp>
#include <boost/type_traits.hpp>
#include <boost/mpl/if.hpp>
#include <boost/numeric/mtl/mtl_fwd.hpp>
#include <boost/numeric/mtl/utility/common_include.hpp>
#include <boost/numeric/mtl/utility/maybe.hpp>
#include <boost/numeric/mtl/detail/base_cursor.hpp>
#include <boost/numeric/mtl/operation/update.hpp>
#include <boost/numeric/mtl/operation/shift_block.hpp>
#include <boost/numeric/mtl/matrix/mat_expr.hpp>
#include <boost/numeric/mtl/matrix/element_matrix.hpp>
#include <boost/numeric/mtl/matrix/element_array.hpp>
#include <boost/numeric/mtl/operation/compute_factors.hpp>
namespace mtl {
// using std::size_t;
// using std::vector;
// using utilities::maybe;
// Forward declarations
// template <typename Elt, typename Parameters> class compressed2D;
// template <typename Elt, typename Parameters, typename Updater> class compressed2D_inserter;
template <typename Value, typename Parameters>
typename compressed2D<Value, Parameters>::size_type
inline num_rows(const compressed2D<Value, Parameters>& matrix);
template <typename Value, typename Parameters>
typename compressed2D<Value, Parameters>::size_type
inline num_cols(const compressed2D<Value, Parameters>& matrix);
template <typename Value, typename Parameters>
typename compressed2D<Value, Parameters>::size_type
inline size(const compressed2D<Value, Parameters>& matrix);
struct compressed_key
{
typedef std::size_t size_t;
typedef compressed_key self;
template <typename Elt, typename Parameters>
explicit compressed_key(compressed2D<Elt, Parameters> const& matrix, size_t offset) : offset(offset)
{
std::size_t my_major= matrix.indexer.find_major(matrix, offset);
major= my_major;
}
template <typename Elt, typename Parameters>
explicit compressed_key(compressed2D<Elt, Parameters> const& matrix, size_t r, size_t c)
{
offset= matrix.indexer(matrix, r, c);
major= matrix.indexer.major_minor_c(matrix, r, c).first;
}
compressed_key(compressed_key const& other)
{
offset= other.offset; major= other.major;
}
self& operator= (self const& other)
{
offset= other.offset; major= other.major;
return *this;
}
bool operator== (compressed_key const& other)
{
//if (offset == other.offset && major != other.major)
// std::cout << offset << " " << other.offset << " " << major << " " << other.major << '\n';
MTL_DEBUG_THROW_IF(offset == other.offset && major != other.major,
logic_error("equal offsets imply equal major"));
return offset == other.offset;
}
bool operator!= (compressed_key const& other)
{
return !(*this == other);
}
size_t major;
size_t offset;
};
// Cursor over every element
template <typename Elt, typename Parameters>
struct compressed_el_cursor
: public compressed_key
{
typedef Elt value_type;
typedef compressed_key base;
typedef compressed_el_cursor self;
typedef std::size_t size_t;
explicit compressed_el_cursor(compressed2D<Elt, Parameters> const& matrix, size_t r, size_t c)
: base(matrix, r, c), matrix(matrix)
{}
explicit compressed_el_cursor(compressed2D<Elt, Parameters> const& matrix, size_t offset)
: base(matrix, offset), matrix(matrix)
{}
compressed_el_cursor(const compressed_el_cursor<Elt, Parameters>& other)
: base(other), matrix(other.matrix)
{}
self& operator= (self const& other)
{
base::operator=(other);
return *this;
}
self& operator++ ()
{
++offset;
MTL_DEBUG_THROW_IF(matrix.starts[major+1] < offset, runtime_error("Inconsistent incrementation!"));
while (major < matrix.starts.size()-1 && matrix.starts[major+1] == offset)
++major;
return *this;
}
base& operator* ()
{
return *this;
}
compressed2D<Elt, Parameters> const& matrix;
};
// Cursor over every element
template <typename Elt, typename Parameters>
struct compressed_minor_cursor
: public compressed_key
{
typedef Elt value_type;
typedef compressed_key base;
typedef compressed_minor_cursor self;
typedef std::size_t size_t;
explicit compressed_minor_cursor(mtl::compressed2D<Elt, Parameters> const& matrix, size_t r, size_t c)
: base(matrix, r, c), matrix(matrix)
{}
explicit compressed_minor_cursor(mtl::compressed2D<Elt, Parameters> const& matrix, size_t offset)
: base(matrix, offset), matrix(matrix)
{}
compressed_minor_cursor(self const& other) : base(other), matrix(other.matrix) {}
self& operator= (self const& other)
{
base::operator=(other);
return *this;
}
self& operator++ ()
{
++offset;
return *this;
}
base& operator* ()
{
return *this;
}
mtl::compressed2D<Elt, Parameters> const& matrix;
};
// Indexing for compressed matrices
struct compressed2D_indexer
{
typedef std::size_t size_t;
typedef size_t size_type;
typedef std::pair<size_type, size_type> size_pair;
private:
// helpers for public functions
template <class Matrix>
utilities::maybe<size_t> offset(const Matrix& ma, size_t major, size_t minor) const
{
typedef utilities::maybe<size_t> result_type;
assert(ma.starts[major] <= ma.starts[major+1]); // Check sortedness
assert(ma.starts[major+1] <= ma.my_nnz); // Check bounds of indices
// Now we are save to use past-end addresses as iterators
// Empty matrices are special cases
if (ma.indices.empty())
return result_type(0, false);
const size_t *first = &ma.indices[0] + ma.starts[major],
*last = &ma.indices[0] + ma.starts[major+1];
// if empty row (or column) return start of next one
if (first == last)
return result_type(first - &ma.indices[0], false);
const size_t *index = std::lower_bound(first, last, minor);
return result_type(index - &ma.indices[0], index != last && *index == minor);
}
public:
// Returns major and minor index in C style (starting with 0)
template <class Matrix>
size_pair major_minor_c(const Matrix& ma, size_t row, size_t col) const
{
using std::make_pair;
// convert into c indices
typename Matrix::index_type my_index;
size_t my_row= index::change_from(my_index, row),
my_col= index::change_from(my_index, col);
return make_pair(ma.major_(my_row, my_col), ma.minor_(my_row, my_col));
}
// Returns the offset if found
// If not found it returns the position where it would be inserted
template <class Matrix>
utilities::maybe<size_t> operator() (const Matrix& ma, size_t row, size_t col) const
{
size_t major, minor;
boost::tie(major, minor) = major_minor_c(ma, row, col);
return offset(ma, major, minor);
}
// Same as above if internal representation is already known
template <class Matrix>
utilities::maybe<size_t> operator() (const Matrix& ma, size_pair major_minor) const
{
return offset(ma, major_minor.first, major_minor.second);
}
// For a given offset the minor can be accessed directly, the major dim has to be searched
// Returned in internal (c) representation
template <class Matrix>
size_t find_major(const Matrix& ma, size_t offset) const
{
MTL_DEBUG_THROW_IF(ma.starts.empty(), logic_error("Major vector can't be empty"));
size_t my_major= std::upper_bound(ma.starts.begin(), ma.starts.end(), offset) - ma.starts.begin();
return --my_major;
}
template <class Matrix>
size_t minor_from_offset(const Matrix& ma, size_t offset) const
{
typedef typename Matrix::index_type my_index;
return index::change_to(my_index(), ma.indices[offset]);
}
}; // compressed2D_indexer
// Compressed 2D matrix type
// For now no external data
template <typename Elt, typename Parameters = matrix::parameters<> >
class compressed2D
: public detail::base_matrix<Elt, Parameters>,
public detail::const_crtp_base_matrix< compressed2D<Elt, Parameters>, Elt, std::size_t >,
public detail::crtp_matrix_assign< compressed2D<Elt, Parameters>, Elt, std::size_t >,
public matrix::mat_expr< compressed2D<Elt, Parameters> >
{
typedef std::size_t size_t;
typedef detail::base_matrix<Elt, Parameters> super;
typedef compressed2D self;
typedef matrix::mat_expr< compressed2D<Elt, Parameters> > expr_base;
typedef detail::crtp_matrix_assign< self, Elt, std::size_t > assign_base;
public:
typedef Parameters parameters;
typedef typename Parameters::orientation orientation;
typedef typename Parameters::index index_type;
typedef typename Parameters::dimensions dimensions;
typedef Elt value_type;
typedef compressed_key key_type;
// return type of operator() const
typedef value_type const_access_type;
// typedef const_pointer_type key_type;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -