From af8e5696f05b8c241f6b7c08daad1479d1d19d62 Mon Sep 17 00:00:00 2001 From: Vadim Pisarevsky Date: Tue, 27 Mar 2012 14:43:24 +0000 Subject: [PATCH] fixed a few compile problems in SparseMat code; fixed iteration over an empty sparse matrix (ticket #1587) --- modules/core/include/opencv2/core/mat.hpp | 10 ++- modules/core/src/matrix.cpp | 22 ++++++ modules/core/test/test_operations.cpp | 89 +++++++++++++++++++++++ 3 files changed, 118 insertions(+), 3 deletions(-) diff --git a/modules/core/include/opencv2/core/mat.hpp b/modules/core/include/opencv2/core/mat.hpp index ee3a3af211..427952d6d6 100644 --- a/modules/core/include/opencv2/core/mat.hpp +++ b/modules/core/include/opencv2/core/mat.hpp @@ -2294,7 +2294,7 @@ inline SparseMatConstIterator::SparseMatConstIterator(const SparseMatConstIterat } static inline bool operator == (const SparseMatConstIterator& it1, const SparseMatConstIterator& it2) -{ return it1.m == it2.m && it1.hashidx == it2.hashidx && it1.ptr == it2.ptr; } +{ return it1.m == it2.m && it1.ptr == it2.ptr; } static inline bool operator != (const SparseMatConstIterator& it1, const SparseMatConstIterator& it2) { return !(it1 == it2); } @@ -2527,7 +2527,9 @@ SparseMatConstIterator_<_Tp>::SparseMatConstIterator_(const SparseMatConstIterat template inline SparseMatConstIterator_<_Tp>& SparseMatConstIterator_<_Tp>::operator = (const SparseMatConstIterator_<_Tp>& it) -{ return ((SparseMatConstIterator&)*this = it); } +{ return reinterpret_cast&> + (*reinterpret_cast(this) = + reinterpret_cast(it)); } template inline const _Tp& SparseMatConstIterator_<_Tp>::operator *() const @@ -2564,7 +2566,9 @@ SparseMatIterator_<_Tp>::SparseMatIterator_(const SparseMatIterator_<_Tp>& it) template inline SparseMatIterator_<_Tp>& SparseMatIterator_<_Tp>::operator = (const SparseMatIterator_<_Tp>& it) -{ return ((SparseMatIterator&)*this = it); } +{ return reinterpret_cast&> + (*reinterpret_cast(this) = + reinterpret_cast(it)); } template inline _Tp& SparseMatIterator_<_Tp>::operator *() const diff --git a/modules/core/src/matrix.cpp b/modules/core/src/matrix.cpp index c38ff2bd24..ff9714ada4 100644 --- a/modules/core/src/matrix.cpp +++ b/modules/core/src/matrix.cpp @@ -3506,6 +3506,28 @@ SparseMat::operator CvSparseMat*() const return m; } +uchar* SparseMat::ptr(int i0, bool createMissing, size_t* hashval) +{ + CV_Assert( hdr && hdr->dims == 1 ); + size_t h = hashval ? *hashval : hash(i0); + size_t hidx = h & (hdr->hashtab.size() - 1), nidx = hdr->hashtab[hidx]; + uchar* pool = &hdr->pool[0]; + while( nidx != 0 ) + { + Node* elem = (Node*)(pool + nidx); + if( elem->hashval == h && elem->idx[0] == i0 ) + return &value(elem); + nidx = elem->next; + } + + if( createMissing ) + { + int idx[] = { i0 }; + return newNode( idx, h ); + } + return 0; +} + uchar* SparseMat::ptr(int i0, int i1, bool createMissing, size_t* hashval) { CV_Assert( hdr && hdr->dims == 2 ); diff --git a/modules/core/test/test_operations.cpp b/modules/core/test/test_operations.cpp index 6e7968fb02..8528fc3d1d 100644 --- a/modules/core/test/test_operations.cpp +++ b/modules/core/test/test_operations.cpp @@ -885,3 +885,92 @@ void CV_OperationsTest::run( int /* start_from */) } TEST(Core_Array, expressions) { CV_OperationsTest test; test.safe_run(); } + +class CV_SparseMatTest : public cvtest::BaseTest +{ +public: + CV_SparseMatTest() {} + ~CV_SparseMatTest() {} +protected: + void run(int) + { + try + { + RNG& rng = theRNG(); + const int MAX_DIM=3; + int sizes[MAX_DIM], idx[MAX_DIM]; + for( int iter = 0; iter < 100; iter++ ) + { + ts->printf(cvtest::TS::LOG, "."); + ts->update_context(this, iter, true); + int k, dims = rng.uniform(1, MAX_DIM+1), p = 1; + for( k = 0; k < dims; k++ ) + { + sizes[k] = rng.uniform(1, 30); + p *= sizes[k]; + } + int j, nz = rng.uniform(0, (p+2)/2), nz0 = 0; + SparseMat_ v(dims,sizes); + + CV_Assert( (int)v.nzcount() == 0 ); + + SparseMatIterator_ it = v.begin(); + SparseMatIterator_ it_end = v.end(); + + for( k = 0; it != it_end; ++it, ++k ) + ; + CV_Assert( k == 0 ); + + int sum0 = 0, sum = 0; + for( j = 0; j < nz; j++ ) + { + int val = rng.uniform(1, 100); + for( k = 0; k < dims; k++ ) + idx[k] = rng.uniform(0, sizes[k]); + if( dims == 1 ) + { + CV_Assert( v.ref(idx[0]) == v(idx[0]) ); + } + else if( dims == 2 ) + { + CV_Assert( v.ref(idx[0], idx[1]) == v(idx[0], idx[1]) ); + } + else if( dims == 3 ) + { + CV_Assert( v.ref(idx[0], idx[1], idx[2]) == v(idx[0], idx[1], idx[2]) ); + } + CV_Assert( v.ref(idx) == v(idx) ); + v.ref(idx) += val; + if( v(idx) == val ) + nz0++; + sum0 += val; + } + + CV_Assert( (int)v.nzcount() == nz0 ); + + it = v.begin(); + it_end = v.end(); + + for( k = 0; it != it_end; ++it, ++k ) + sum += *it; + CV_Assert( k == nz0 && sum == sum0 ); + + v.clear(); + CV_Assert( (int)v.nzcount() == 0 ); + + it = v.begin(); + it_end = v.end(); + + for( k = 0; it != it_end; ++it, ++k ) + ; + CV_Assert( k == 0 ); + } + } + catch(...) + { + ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH); + } + } +}; + +TEST(Core_SparseMat, iterations) { CV_SparseMatTest test; test.safe_run(); }