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:
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:
which 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, ...".