📄 matrix_sparse.hpp
字号:
}
BOOST_UBLAS_INLINE
array_type &data () {
return data_;
}
// Resizing
private:
BOOST_UBLAS_INLINE
size_type restrict_capacity (size_type non_zeros) const {
// Guarding against overflow - thanks to Alexei Novakov for the hint.
// non_zeros = (std::min) (non_zeros, size1_ * size2_);
if (size1_ > 0 && non_zeros / size1_ >= size2_)
non_zeros = size1_ * size2_;
return non_zeros;
}
public:
BOOST_UBLAS_INLINE
void resize (size_type size1, size_type size2, bool preserve = true) {
// FIXME preserve unimplemented
BOOST_UBLAS_CHECK (!preserve, internal_logic ());
size1_ = size1;
size2_ = size2;
data ().clear ();
}
// Reserving
BOOST_UBLAS_INLINE
void reserve (size_type non_zeros, bool preserve = true) {
detail::map_reserve (data (), restrict_capacity (non_zeros));
}
// Element support
BOOST_UBLAS_INLINE
pointer find_element (size_type i, size_type j) {
return const_cast<pointer> (const_cast<const self_type&>(*this).find_element (i, j));
}
BOOST_UBLAS_INLINE
const_pointer find_element (size_type i, size_type j) const {
const size_type element = layout_type::element (i, size1_, j, size2_);
const_subiterator_type it (data ().find (element));
if (it == data ().end ())
return 0;
BOOST_UBLAS_CHECK ((*it).first == element, internal_logic ()); // broken map
return &(*it).second;
}
// Element access
BOOST_UBLAS_INLINE
const_reference operator () (size_type i, size_type j) const {
const size_type element = layout_type::element (i, size1_, j, size2_);
const_subiterator_type it (data ().find (element));
if (it == data ().end ())
return zero_;
BOOST_UBLAS_CHECK ((*it).first == element, internal_logic ()); // broken map
return (*it).second;
}
BOOST_UBLAS_INLINE
reference operator () (size_type i, size_type j) {
#ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE
const size_type element = layout_type::element (i, size1_, j, size2_);
std::pair<subiterator_type, bool> ii (data ().insert (typename array_type::value_type (element, value_type/*zero*/())));
BOOST_UBLAS_CHECK ((ii.first)->first == element, internal_logic ()); // broken map
return (ii.first)->second;
#else
return reference (*this, i, j);
#endif
}
// Element assingment
BOOST_UBLAS_INLINE
true_reference insert_element (size_type i, size_type j, const_reference t) {
BOOST_UBLAS_CHECK (!find_element (i, j), bad_index ()); // duplicate element
const size_type element = layout_type::element (i, size1_, j, size2_);
std::pair<subiterator_type, bool> ii (data ().insert (typename array_type::value_type (element, t)));
BOOST_UBLAS_CHECK ((ii.first)->first == element, internal_logic ()); // broken map
if (!ii.second) // existing element
(ii.first)->second = t;
return (ii.first)->second;
}
BOOST_UBLAS_INLINE
void erase_element (size_type i, size_type j) {
subiterator_type it = data ().find (layout_type::element (i, size1_, j, size2_));
if (it == data ().end ())
return;
data ().erase (it);
}
// Zeroing
BOOST_UBLAS_INLINE
void clear () {
data ().clear ();
}
// Assignment
BOOST_UBLAS_INLINE
mapped_matrix &operator = (const mapped_matrix &m) {
if (this != &m) {
size1_ = m.size1_;
size2_ = m.size2_;
data () = m.data ();
}
return *this;
}
template<class C> // Container assignment without temporary
BOOST_UBLAS_INLINE
mapped_matrix &operator = (const matrix_container<C> &m) {
resize (m ().size1 (), m ().size2 (), false);
assign (m);
return *this;
}
BOOST_UBLAS_INLINE
mapped_matrix &assign_temporary (mapped_matrix &m) {
swap (m);
return *this;
}
template<class AE>
BOOST_UBLAS_INLINE
mapped_matrix &operator = (const matrix_expression<AE> &ae) {
self_type temporary (ae, detail::map_capacity (data ()));
return assign_temporary (temporary);
}
template<class AE>
BOOST_UBLAS_INLINE
mapped_matrix &assign (const matrix_expression<AE> &ae) {
matrix_assign<scalar_assign> (*this, ae);
return *this;
}
template<class AE>
BOOST_UBLAS_INLINE
mapped_matrix& operator += (const matrix_expression<AE> &ae) {
self_type temporary (*this + ae, detail::map_capacity (data ()));
return assign_temporary (temporary);
}
template<class C> // Container assignment without temporary
BOOST_UBLAS_INLINE
mapped_matrix &operator += (const matrix_container<C> &m) {
plus_assign (m);
return *this;
}
template<class AE>
BOOST_UBLAS_INLINE
mapped_matrix &plus_assign (const matrix_expression<AE> &ae) {
matrix_assign<scalar_plus_assign> (*this, ae);
return *this;
}
template<class AE>
BOOST_UBLAS_INLINE
mapped_matrix& operator -= (const matrix_expression<AE> &ae) {
self_type temporary (*this - ae, detail::map_capacity (data ()));
return assign_temporary (temporary);
}
template<class C> // Container assignment without temporary
BOOST_UBLAS_INLINE
mapped_matrix &operator -= (const matrix_container<C> &m) {
minus_assign (m);
return *this;
}
template<class AE>
BOOST_UBLAS_INLINE
mapped_matrix &minus_assign (const matrix_expression<AE> &ae) {
matrix_assign<scalar_minus_assign> (*this, ae);
return *this;
}
template<class AT>
BOOST_UBLAS_INLINE
mapped_matrix& operator *= (const AT &at) {
matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
return *this;
}
template<class AT>
BOOST_UBLAS_INLINE
mapped_matrix& operator /= (const AT &at) {
matrix_assign_scalar<scalar_divides_assign> (*this, at);
return *this;
}
// Swapping
BOOST_UBLAS_INLINE
void swap (mapped_matrix &m) {
if (this != &m) {
std::swap (size1_, m.size1_);
std::swap (size2_, m.size2_);
data ().swap (m.data ());
}
}
BOOST_UBLAS_INLINE
friend void swap (mapped_matrix &m1, mapped_matrix &m2) {
m1.swap (m2);
}
// Iterator types
private:
// Use storage iterator
typedef typename A::const_iterator const_subiterator_type;
typedef typename A::iterator subiterator_type;
BOOST_UBLAS_INLINE
true_reference at_element (size_type i, size_type j) {
const size_type element = layout_type::element (i, size1_, j, size2_);
subiterator_type it (data ().find (element));
BOOST_UBLAS_CHECK (it != data ().end(), bad_index ());
BOOST_UBLAS_CHECK ((*it).first == element, internal_logic ()); // broken map
return it->second;
}
public:
class const_iterator1;
class iterator1;
class const_iterator2;
class iterator2;
typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
typedef reverse_iterator_base1<iterator1> reverse_iterator1;
typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
typedef reverse_iterator_base2<iterator2> reverse_iterator2;
// Element lookup
// BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
const_iterator1 find1 (int rank, size_type i, size_type j, int direction = 1) const {
const_subiterator_type it (data ().lower_bound (layout_type::address (i, size1_, j, size2_)));
const_subiterator_type it_end (data ().end ());
size_type index1 = size_type (-1);
size_type index2 = size_type (-1);
while (rank == 1 && it != it_end) {
index1 = layout_type::index1 ((*it).first, size1_, size2_);
index2 = layout_type::index2 ((*it).first, size1_, size2_);
if (direction > 0) {
if ((index1 >= i && index2 == j) || (i >= size1_))
break;
++ i;
} else /* if (direction < 0) */ {
if ((index1 <= i && index2 == j) || (i == 0))
break;
-- i;
}
it = data ().lower_bound (layout_type::address (i, size1_, j, size2_));
}
if (rank == 1 && index2 != j) {
if (direction > 0)
i = size1_;
else /* if (direction < 0) */
i = 0;
rank = 0;
}
return const_iterator1 (*this, rank, i, j, it);
}
// BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
iterator1 find1 (int rank, size_type i, size_type j, int direction = 1) {
subiterator_type it (data ().lower_bound (layout_type::address (i, size1_, j, size2_)));
subiterator_type it_end (data ().end ());
size_type index1 = size_type (-1);
size_type index2 = size_type (-1);
while (rank == 1 && it != it_end) {
index1 = layout_type::index1 ((*it).first, size1_, size2_);
index2 = layout_type::index2 ((*it).first, size1_, size2_);
if (direction > 0) {
if ((index1 >= i && index2 == j) || (i >= size1_))
break;
++ i;
} else /* if (direction < 0) */ {
if ((index1 <= i && index2 == j) || (i == 0))
break;
-- i;
}
it = data ().lower_bound (layout_type::address (i, size1_, j, size2_));
}
if (rank == 1 && index2 != j) {
if (direction > 0)
i = size1_;
else /* if (direction < 0) */
i = 0;
rank = 0;
}
return iterator1 (*this, rank, i, j, it);
}
// BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
const_iterator2 find2 (int rank, size_type i, size_type j, int direction = 1) const {
const_subiterator_type it (data ().lower_bound (layout_type::address (i, size1_, j, size2_)));
const_subiterator_type it_end (data ().end ());
size_type index1 = size_type (-1);
size_type index2 = size_type (-1);
while (rank == 1 && it != it_end) {
index1 = layout_type::index1 ((*it).first, size1_, size2_);
index2 = layout_type::index2 ((*it).first, size1_, size2_);
if (direction > 0) {
if ((index2 >= j && index1 == i) || (j >= size2_))
break;
++ j;
} else /* if (direction < 0) */ {
if ((index2 <= j && index1 == i) || (j == 0))
break;
-- j;
}
it = data ().lower_bound (layout_type::address (i, size1_, j, size2_));
}
if (rank == 1 && index1 != i) {
if (direction > 0)
j = size2_;
else /* if (direction < 0) */
j = 0;
rank = 0;
}
return const_iterator2 (*this, rank, i, j, it);
}
// BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
iterator2 find2 (int rank, size_type i, size_type j, int direction = 1) {
subiterator_type it (data ().lower_bound (layout_type::address (i, size1_, j, size2_)));
subiterator_type it_end (data ().end ());
size_type index1 = size_type (-1);
size_type index2 = size_type (-1);
while (rank == 1 && it != it_end) {
index1 = layout_type::index1 ((*it).first, size1_, size2_);
index2 = layout_type::index2 ((*it).first, size1_, size2_);
if (direction > 0) {
if ((index2 >= j && index1 == i) || (j >= size2_))
break;
++ j;
} else /* if (direction < 0) */ {
if ((index2 <= j && index1 == i) || (j == 0))
break;
-- j;
}
it = data ().lower_bound (layout_type::address (i, size1_, j, size2_));
}
if (rank == 1 && index1 != i) {
if (direction > 0)
j = size2_;
else /* if (direction < 0) */
j = 0;
rank = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -