Opened 8 years ago
Last modified 8 years ago
#10127 new Bugs
coordinate_matrix sort() fails on to std::swap
| Reported by: | anonymous | Owned by: | Gunter |
|---|---|---|---|
| Milestone: | Boost 1.58.0 | Component: | uBLAS |
| Version: | Boost 1.54.0 | Severity: | Showstopper |
| Keywords: | c++11, swap, sort, matrix, reference | Cc: |
Description
Orginally posted here:
http://stackoverflow.com/questions/24228772/c11-compatibility-of-sparse-matrix-implementations
The following program does not compile with gcc 4.8 or clang 3.4 when --std=c++11 is set:
#include <boost/numeric/ublas/io.hpp>
#include <boost/numeric/ublas/matrix_sparse.hpp>
using namespace boost::numeric::ublas;
int main(int argc, char** argv) {
coordinate_matrix<int> m1(100, 100, 100);
for (int i = 0; i < 100; i++)
m1.insert_element(i,i,i);
compressed_matrix<int> m2(m1, 100);
}
We can solve the issue by providing a swap() routine:
#include <boost/numeric/ublas/io.hpp>
#include <boost/numeric/ublas/matrix_sparse.hpp>
using namespace boost::numeric::ublas;
namespace std {
template<class M>
inline
void swap (boost::numeric::ublas::index_triple<M> i1, boost::numeric::ublas::index_triple<M> i2) {
i1.swap (i2);
}
}
int main(int argc, char** argv) {
coordinate_matrix<int> m1(100, 100, 100);
for (int i = 0; i < 100; i++)
m1.insert_element(i,i,i);
compressed_matrix<int> m2(m1, 100);
}
I am not an expert C++ template programmer, so I am unable to decide what is the cause here, but the C++ reference on std::sort explicitly mentions a swap() method.
Change History (6)
comment:1 by , 8 years ago
comment:2 by , 8 years ago
This also affects version 1.55.0 sparse vectors, which breaks the LU substitution.
For example, the following code produces incorrect output. It should swap the 2nd and 3rd elements, producing
1.000000, 3.000000, 2.000000
but instead it produces
1.000000, 3.000000, 3.000000
It is fixed by uncommenting the #define BOOST_UBLAS_NO_ELEMENT_PROXIES
//#define BOOST_UBLAS_NO_ELEMENT_PROXIES
#include <boost/numeric/ublas/vector_sparse.hpp>
#include <boost/numeric/ublas/lu.hpp>
using namespace boost::numeric::ublas;
int main()
{
mapped_vector<float> y;
y(0) = 1.0f;
y(1) = 2.0f;
y(2) = 3.0f;
LOG("Initial vector is: " << y);
permutation_matrix<std::size_t> perm(y.size());
perm(0) = 0;
perm(1) = 2;
perm(2) = 2;
swap_rows(perm, y);
LOG("Swapped vector is: " << y);
}
comment:3 by , 8 years ago
| Component: | None → uBLAS |
|---|---|
| Owner: | set to |
comment:4 by , 8 years ago
Hi, any chance to get this ticket solved in the next release ? version 1.57 doesn't seem to offer a fix for this issue, as far as I know.
comment:5 by , 8 years ago
| Milestone: | To Be Determined → Boost 1.58.0 |
|---|---|
| Severity: | Problem → Showstopper |
I think this bug represents a fundamental break in core functionality, so I am raising the severity. I believe this should be fixed with priority.
comment:6 by , 8 years ago
| Keywords: | c++11 swap sort matrix reference added |
|---|

Test case can be minimized to:
#include <boost/numeric/ublas/matrix_sparse.hpp> int main() { boost::numeric::ublas::coordinate_matrix<int> m1(1, 1, 1); m1.insert_element(0, 0, 0); }The problem seems to be that when BOOST_UBLAS_STRICT_MATRIX_SPARSE is defined, coordinate_matrix and its iterator types use a proxy class as their reference type:
#ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE typedef T &reference; #else typedef sparse_matrix_element<self_type> reference; #endifwhich violates the C++ standard's requirement that the reference type for forward iterators is a true reference. C++11 [forward.iterators]/1 states: "A class or pointer type X satisfies the requirements of a forward iterator if ... if X is a mutable iterator, reference is a reference to T; if X is a const iterator, reference is a reference to const T, ...".