More C++11ification. 1. Replace HashMap and HashSet with std::unordered_map and std::unordered_set respectively. 2. Extract the pair hasher into a struct pair_hash. 3. Delete collections_port.h 4. Convert explicit iterator based loops to auto based loops where sensible. Change-Id: Ib88bcd13a7463d18435639d3b771abaa52080efb
diff --git a/CMakeLists.txt b/CMakeLists.txt index c78dc41..54e5e3a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt
@@ -440,10 +440,6 @@ # they are used when checking for compiler features. set(CMAKE_REQUIRED_FLAGS ${CMAKE_CXX_FLAGS}) -# Set the Ceres option for C++11. -# TODO(alex): Remove when #defines are removed from source & config.h -list(APPEND CERES_COMPILE_OPTIONS CERES_STD_UNORDERED_MAP) - if (TBB) find_package(TBB QUIET) if (TBB_FOUND)
diff --git a/cmake/config.h.in b/cmake/config.h.in index 76b853c..d031651 100644 --- a/cmake/config.h.in +++ b/cmake/config.h.in
@@ -73,13 +73,6 @@ @CERES_HAVE_PTHREAD@ @CERES_HAVE_RWLOCK@ -// Which version of unordered map was used when Ceres was compiled. Exactly -// one of these will be defined for any given build. -@CERES_STD_UNORDERED_MAP@ -@CERES_STD_UNORDERED_MAP_IN_TR1_NAMESPACE@ -@CERES_TR1_UNORDERED_MAP@ -@CERES_NO_UNORDERED_MAP@ - // If defined, the memory header is in <tr1/memory>, otherwise <memory>. @CERES_TR1_MEMORY_HEADER@
diff --git a/internal/ceres/block_random_access_diagonal_matrix.h b/internal/ceres/block_random_access_diagonal_matrix.h index 07ffc9d..2a8340b 100644 --- a/internal/ceres/block_random_access_diagonal_matrix.h +++ b/internal/ceres/block_random_access_diagonal_matrix.h
@@ -36,7 +36,6 @@ #include <utility> #include "ceres/mutex.h" #include "ceres/block_random_access_matrix.h" -#include "ceres/collections_port.h" #include "ceres/triplet_sparse_matrix.h" #include "ceres/integral_types.h" #include "ceres/internal/macros.h"
diff --git a/internal/ceres/block_random_access_sparse_matrix.cc b/internal/ceres/block_random_access_sparse_matrix.cc index 5432ec1..540a8b9 100644 --- a/internal/ceres/block_random_access_sparse_matrix.cc +++ b/internal/ceres/block_random_access_sparse_matrix.cc
@@ -69,11 +69,9 @@ // object for looking into the values array of the // TripletSparseMatrix. int num_nonzeros = 0; - for (set<pair<int, int> >::const_iterator it = block_pairs.begin(); - it != block_pairs.end(); - ++it) { - const int row_block_size = blocks_[it->first]; - const int col_block_size = blocks_[it->second]; + for (const auto& block_pair : block_pairs) { + const int row_block_size = blocks_[block_pair.first]; + const int col_block_size = blocks_[block_pair.second]; num_nonzeros += row_block_size * col_block_size; } @@ -88,24 +86,19 @@ double* values = tsm_->mutable_values(); int pos = 0; - for (set<pair<int, int> >::const_iterator it = block_pairs.begin(); - it != block_pairs.end(); - ++it) { - const int row_block_size = blocks_[it->first]; - const int col_block_size = blocks_[it->second]; - cell_values_.push_back(make_pair(make_pair(it->first, it->second), - values + pos)); - layout_[IntPairToLong(it->first, it->second)] = + for (const auto& block_pair : block_pairs) { + const int row_block_size = blocks_[block_pair.first]; + const int col_block_size = blocks_[block_pair.second]; + cell_values_.push_back(make_pair(block_pair, values + pos)); + layout_[IntPairToLong(block_pair.first, block_pair.second)] = new CellInfo(values + pos); pos += row_block_size * col_block_size; } // Fill the sparsity pattern of the underlying matrix. - for (set<pair<int, int> >::const_iterator it = block_pairs.begin(); - it != block_pairs.end(); - ++it) { - const int row_block_id = it->first; - const int col_block_id = it->second; + for (const auto& block_pair : block_pairs) { + const int row_block_id = block_pair.first; + const int col_block_id = block_pair.second; const int row_block_size = blocks_[row_block_id]; const int col_block_size = blocks_[col_block_id]; int pos = @@ -125,10 +118,8 @@ // Assume that the user does not hold any locks on any cell blocks // when they are calling SetZero. BlockRandomAccessSparseMatrix::~BlockRandomAccessSparseMatrix() { - for (LayoutType::iterator it = layout_.begin(); - it != layout_.end(); - ++it) { - delete it->second; + for (const auto& entry : layout_) { + delete entry.second; } } @@ -163,19 +154,17 @@ void BlockRandomAccessSparseMatrix::SymmetricRightMultiply(const double* x, double* y) const { - vector< pair<pair<int, int>, double*> >::const_iterator it = - cell_values_.begin(); - for (; it != cell_values_.end(); ++it) { - const int row = it->first.first; + for (const auto& cell_position_and_data : cell_values_) { + const int row = cell_position_and_data.first.first; const int row_block_size = blocks_[row]; const int row_block_pos = block_positions_[row]; - const int col = it->first.second; + const int col = cell_position_and_data.first.second; const int col_block_size = blocks_[col]; const int col_block_pos = block_positions_[col]; MatrixVectorMultiply<Eigen::Dynamic, Eigen::Dynamic, 1>( - it->second, row_block_size, col_block_size, + cell_position_and_data.second, row_block_size, col_block_size, x + col_block_pos, y + row_block_pos); @@ -185,7 +174,7 @@ // triangular multiply also. if (row != col) { MatrixTransposeVectorMultiply<Eigen::Dynamic, Eigen::Dynamic, 1>( - it->second, row_block_size, col_block_size, + cell_position_and_data.second, row_block_size, col_block_size, x + row_block_pos, y + col_block_pos); }
diff --git a/internal/ceres/block_random_access_sparse_matrix.h b/internal/ceres/block_random_access_sparse_matrix.h index 2b3c7fd..e79667b 100644 --- a/internal/ceres/block_random_access_sparse_matrix.h +++ b/internal/ceres/block_random_access_sparse_matrix.h
@@ -32,11 +32,11 @@ #define CERES_INTERNAL_BLOCK_RANDOM_ACCESS_SPARSE_MATRIX_H_ #include <set> +#include <unordered_map> #include <vector> #include <utility> #include "ceres/mutex.h" #include "ceres/block_random_access_matrix.h" -#include "ceres/collections_port.h" #include "ceres/triplet_sparse_matrix.h" #include "ceres/integral_types.h" #include "ceres/internal/macros.h" @@ -109,7 +109,7 @@ // A mapping from <row_block_id, col_block_id> to the position in // the values array of tsm_ where the block is stored. - typedef HashMap<long int, CellInfo* > LayoutType; + typedef std::unordered_map<long int, CellInfo* > LayoutType; LayoutType layout_; // In order traversal of contents of the matrix. This allows us to
diff --git a/internal/ceres/block_random_access_sparse_matrix_test.cc b/internal/ceres/block_random_access_sparse_matrix_test.cc index e4d82d0..688b09d 100644 --- a/internal/ceres/block_random_access_sparse_matrix_test.cc +++ b/internal/ceres/block_random_access_sparse_matrix_test.cc
@@ -68,11 +68,9 @@ EXPECT_EQ(m.num_rows(), num_rows); EXPECT_EQ(m.num_cols(), num_rows); - for (set<pair<int, int> >::const_iterator it = block_pairs.begin(); - it != block_pairs.end(); - ++it) { - const int row_block_id = it->first; - const int col_block_id = it->second; + for (const auto& block_pair : block_pairs) { + const int row_block_id = block_pair.first; + const int col_block_id = block_pair.second; int row; int col; int row_stride;
diff --git a/internal/ceres/canonical_views_clustering.cc b/internal/ceres/canonical_views_clustering.cc index b3e9c22..ca8dff5 100644 --- a/internal/ceres/canonical_views_clustering.cc +++ b/internal/ceres/canonical_views_clustering.cc
@@ -31,7 +31,9 @@ #include "ceres/canonical_views_clustering.h" -#include "ceres/collections_port.h" +#include <unordered_set> +#include <unordered_map> + #include "ceres/graph.h" #include "ceres/internal/macros.h" #include "ceres/map_util.h" @@ -42,8 +44,8 @@ using std::vector; -typedef HashMap<int, int> IntMap; -typedef HashSet<int> IntSet; +typedef std::unordered_map<int, int> IntMap; +typedef std::unordered_set<int> IntSet; class CanonicalViewsClustering { public: @@ -76,7 +78,7 @@ // center). IntMap view_to_canonical_view_; // Maps a view to its similarity to its current cluster center. - HashMap<int, double> view_to_canonical_view_similarity_; + std::unordered_map<int, double> view_to_canonical_view_similarity_; CERES_DISALLOW_COPY_AND_ASSIGN(CanonicalViewsClustering); }; @@ -111,14 +113,12 @@ int best_view = 0; // TODO(sameeragarwal): Make this loop multi-threaded. - for (IntSet::const_iterator view = valid_views.begin(); - view != valid_views.end(); - ++view) { + for (const auto& view : valid_views) { const double difference = - ComputeClusteringQualityDifference(*view, *centers); + ComputeClusteringQualityDifference(view, *centers); if (difference > best_difference) { best_difference = difference; - best_view = *view; + best_view = view; } } @@ -144,11 +144,9 @@ void CanonicalViewsClustering::FindValidViews( IntSet* valid_views) const { const IntSet& views = graph_->vertices(); - for (IntSet::const_iterator view = views.begin(); - view != views.end(); - ++view) { - if (graph_->VertexWeight(*view) != WeightedGraph<int>::InvalidWeight()) { - valid_views->insert(*view); + for (const auto& view : views) { + if (graph_->VertexWeight(view) != WeightedGraph<int>::InvalidWeight()) { + valid_views->insert(view); } } } @@ -166,12 +164,10 @@ // was added to the list of canonical views and its nearest // neighbors became members of its cluster. const IntSet& neighbors = graph_->Neighbors(candidate); - for (IntSet::const_iterator neighbor = neighbors.begin(); - neighbor != neighbors.end(); - ++neighbor) { + for (const auto& neighbor : neighbors) { const double old_similarity = - FindWithDefault(view_to_canonical_view_similarity_, *neighbor, 0.0); - const double new_similarity = graph_->EdgeWeight(*neighbor, candidate); + FindWithDefault(view_to_canonical_view_similarity_, neighbor, 0.0); + const double new_similarity = graph_->EdgeWeight(neighbor, candidate); if (new_similarity > old_similarity) { difference += new_similarity - old_similarity; } @@ -193,16 +189,14 @@ void CanonicalViewsClustering::UpdateCanonicalViewAssignments( const int canonical_view) { const IntSet& neighbors = graph_->Neighbors(canonical_view); - for (IntSet::const_iterator neighbor = neighbors.begin(); - neighbor != neighbors.end(); - ++neighbor) { + for (const auto& neighbor : neighbors) { const double old_similarity = - FindWithDefault(view_to_canonical_view_similarity_, *neighbor, 0.0); + FindWithDefault(view_to_canonical_view_similarity_, neighbor, 0.0); const double new_similarity = - graph_->EdgeWeight(*neighbor, canonical_view); + graph_->EdgeWeight(neighbor, canonical_view); if (new_similarity > old_similarity) { - view_to_canonical_view_[*neighbor] = canonical_view; - view_to_canonical_view_similarity_[*neighbor] = new_similarity; + view_to_canonical_view_[neighbor] = canonical_view; + view_to_canonical_view_similarity_[neighbor] = new_similarity; } } } @@ -222,17 +216,14 @@ static const int kInvalidClusterId = -1; const IntSet& views = graph_->vertices(); - for (IntSet::const_iterator view = views.begin(); - view != views.end(); - ++view) { - IntMap::const_iterator it = - view_to_canonical_view_.find(*view); + for (const auto& view : views) { + auto it = view_to_canonical_view_.find(view); int cluster_id = kInvalidClusterId; if (it != view_to_canonical_view_.end()) { cluster_id = FindOrDie(center_to_cluster_id, it->second); } - InsertOrDie(membership, *view, cluster_id); + InsertOrDie(membership, view, cluster_id); } }
diff --git a/internal/ceres/canonical_views_clustering.h b/internal/ceres/canonical_views_clustering.h index 0847f48..6514827 100644 --- a/internal/ceres/canonical_views_clustering.h +++ b/internal/ceres/canonical_views_clustering.h
@@ -41,9 +41,9 @@ #ifndef CERES_INTERNAL_CANONICAL_VIEWS_CLUSTERING_H_ #define CERES_INTERNAL_CANONICAL_VIEWS_CLUSTERING_H_ +#include <unordered_map> #include <vector> -#include "ceres/collections_port.h" #include "ceres/graph.h" namespace ceres { @@ -98,7 +98,7 @@ const CanonicalViewsClusteringOptions& options, const WeightedGraph<int>& graph, std::vector<int>* centers, - HashMap<int, int>* membership); + std::unordered_map<int, int>* membership); struct CanonicalViewsClusteringOptions { CanonicalViewsClusteringOptions()
diff --git a/internal/ceres/canonical_views_clustering_test.cc b/internal/ceres/canonical_views_clustering_test.cc index 0c15fc7..a8db293 100644 --- a/internal/ceres/canonical_views_clustering_test.cc +++ b/internal/ceres/canonical_views_clustering_test.cc
@@ -31,7 +31,7 @@ #include "ceres/canonical_views_clustering.h" -#include "ceres/collections_port.h" +#include <unordered_map> #include "ceres/graph.h" #include "gtest/gtest.h" @@ -74,7 +74,7 @@ CanonicalViewsClusteringOptions options_; std::vector<int> centers_; - HashMap<int, int> membership_; + std::unordered_map<int, int> membership_; }; TEST_F(CanonicalViewsTest, ComputeCanonicalViewsTest) {
diff --git a/internal/ceres/collections_port.h b/internal/ceres/collections_port.h deleted file mode 100644 index e699a66..0000000 --- a/internal/ceres/collections_port.h +++ /dev/null
@@ -1,196 +0,0 @@ -// Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2015 Google Inc. All rights reserved. -// http://ceres-solver.org/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// * Neither the name of Google Inc. nor the names of its contributors may be -// used to endorse or promote products derived from this software without -// specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// -// Author: keir@google.com (Keir Mierle) -// -// Portable HashMap and HashSet, and a specialized overload for hashing pairs. - -#ifndef CERES_INTERNAL_COLLECTIONS_PORT_H_ -#define CERES_INTERNAL_COLLECTIONS_PORT_H_ - -#include "ceres/internal/port.h" - -#if defined(CERES_NO_UNORDERED_MAP) -# include <map> -# include <set> -#endif - -#if defined(CERES_TR1_UNORDERED_MAP) -# include <tr1/unordered_map> -# include <tr1/unordered_set> -# define CERES_HASH_NAMESPACE_START namespace std { namespace tr1 { -# define CERES_HASH_NAMESPACE_END } } -#endif - -#if defined(CERES_STD_UNORDERED_MAP) -# include <unordered_map> -# include <unordered_set> -# define CERES_HASH_NAMESPACE_START namespace std { -# define CERES_HASH_NAMESPACE_END } -#endif - -#if defined(CERES_STD_UNORDERED_MAP_IN_TR1_NAMESPACE) -# include <unordered_map> -# include <unordered_set> -# define CERES_HASH_NAMESPACE_START namespace std { namespace tr1 { -# define CERES_HASH_NAMESPACE_END } } -#endif - -#if !defined(CERES_NO_UNORDERED_MAP) && !defined(CERES_TR1_UNORDERED_MAP) && \ - !defined(CERES_STD_UNORDERED_MAP) && !defined(CERES_STD_UNORDERED_MAP_IN_TR1_NAMESPACE) // NOLINT -# error One of: CERES_NO_UNORDERED_MAP, CERES_TR1_UNORDERED_MAP,\ - CERES_STD_UNORDERED_MAP, CERES_STD_UNORDERED_MAP_IN_TR1_NAMESPACE must be defined! // NOLINT -#endif - -#include <utility> -#include "ceres/integral_types.h" - -// Some systems don't have access to unordered_map/unordered_set. In -// that case, substitute the hash map/set with normal map/set. The -// price to pay is slower speed for some operations. -#if defined(CERES_NO_UNORDERED_MAP) - -namespace ceres { -namespace internal { - -template<typename K, typename V> -struct HashMap : map<K, V> {}; - -template<typename K> -struct HashSet : set<K> {}; - -} // namespace internal -} // namespace ceres - -#else - -namespace ceres { -namespace internal { - -#if defined(CERES_TR1_UNORDERED_MAP) || \ - defined(CERES_STD_UNORDERED_MAP_IN_TR1_NAMESPACE) -template<typename K, typename V> -struct HashMap : std::tr1::unordered_map<K, V> {}; -template<typename K> -struct HashSet : std::tr1::unordered_set<K> {}; -#endif - -#if defined(CERES_STD_UNORDERED_MAP) -template<typename K, typename V> -struct HashMap : std::unordered_map<K, V> {}; -template<typename K> -struct HashSet : std::unordered_set<K> {}; -#endif - -#if defined(_WIN32) && !defined(__MINGW64__) && !defined(__MINGW32__) -#define GG_LONGLONG(x) x##I64 -#define GG_ULONGLONG(x) x##UI64 -#else -#define GG_LONGLONG(x) x##LL -#define GG_ULONGLONG(x) x##ULL -#endif - -// The hash function is due to Bob Jenkins (see -// http://burtleburtle.net/bob/hash/index.html). Each mix takes 36 instructions, -// in 18 cycles if you're lucky. On x86 architectures, this requires 45 -// instructions in 27 cycles, if you're lucky. -// -// 32bit version -inline void hash_mix(uint32& a, uint32& b, uint32& c) { - a -= b; a -= c; a ^= (c>>13); - b -= c; b -= a; b ^= (a<<8); - c -= a; c -= b; c ^= (b>>13); - a -= b; a -= c; a ^= (c>>12); - b -= c; b -= a; b ^= (a<<16); - c -= a; c -= b; c ^= (b>>5); - a -= b; a -= c; a ^= (c>>3); - b -= c; b -= a; b ^= (a<<10); - c -= a; c -= b; c ^= (b>>15); -} - -// 64bit version -inline void hash_mix(uint64& a, uint64& b, uint64& c) { - a -= b; a -= c; a ^= (c>>43); - b -= c; b -= a; b ^= (a<<9); - c -= a; c -= b; c ^= (b>>8); - a -= b; a -= c; a ^= (c>>38); - b -= c; b -= a; b ^= (a<<23); - c -= a; c -= b; c ^= (b>>5); - a -= b; a -= c; a ^= (c>>35); - b -= c; b -= a; b ^= (a<<49); - c -= a; c -= b; c ^= (b>>11); -} - -inline uint32 Hash32NumWithSeed(uint32 num, uint32 c) { - // The golden ratio; an arbitrary value. - uint32 b = 0x9e3779b9UL; - hash_mix(num, b, c); - return c; -} - -inline uint64 Hash64NumWithSeed(uint64 num, uint64 c) { - // More of the golden ratio. - uint64 b = GG_ULONGLONG(0xe08c1d668b756f82); - hash_mix(num, b, c); - return c; -} - -} // namespace internal -} // namespace ceres - -// Since on some platforms this is a doubly-nested namespace (std::tr1) and -// others it is not, the entire namespace line must be in a macro. -CERES_HASH_NAMESPACE_START - -// The outrageously annoying specializations below are for portability reasons. -// In short, it's not possible to have two overloads of hash<pair<T1, T2> - -// Hasher for STL pairs. Requires hashers for both members to be defined. -template<typename T> -struct hash<pair<T, T> > { - size_t operator()(const pair<T, T>& p) const { - size_t h1 = hash<T>()(p.first); - size_t h2 = hash<T>()(p.second); - // The decision below is at compile time - return (sizeof(h1) <= sizeof(ceres::internal::uint32)) ? - ceres::internal::Hash32NumWithSeed(h1, h2) : - ceres::internal::Hash64NumWithSeed(h1, h2); - } - // Less than operator for MSVC. - bool operator()(const pair<T, T>& a, - const pair<T, T>& b) const { - return a < b; - } - static const size_t bucket_size = 4; // These are required by MSVC - static const size_t min_buckets = 8; // 4 and 8 are defaults. -}; - -CERES_HASH_NAMESPACE_END - -#endif // CERES_NO_UNORDERED_MAP -#endif // CERES_INTERNAL_COLLECTIONS_PORT_H_
diff --git a/internal/ceres/coordinate_descent_minimizer.cc b/internal/ceres/coordinate_descent_minimizer.cc index a334dde..e5569d4 100644 --- a/internal/ceres/coordinate_descent_minimizer.cc +++ b/internal/ceres/coordinate_descent_minimizer.cc
@@ -80,18 +80,15 @@ // offsets for parallel access. map<ParameterBlock*, int> parameter_block_index; map<int, set<double*> > group_to_elements = ordering.group_to_elements(); - for (map<int, set<double*> >::const_iterator it = group_to_elements.begin(); - it != group_to_elements.end(); - ++it) { - for (set<double*>::const_iterator ptr_it = it->second.begin(); - ptr_it != it->second.end(); - ++ptr_it) { - parameter_blocks_.push_back(parameter_map.find(*ptr_it)->second); + for (const auto& g_t_e : group_to_elements) { + const auto& elements = g_t_e.second; + for (double* parameter_block: elements) { + parameter_blocks_.push_back(parameter_map.find(parameter_block)->second); parameter_block_index[parameter_blocks_.back()] = parameter_blocks_.size() - 1; } independent_set_offsets_.push_back( - independent_set_offsets_.back() + it->second.size()); + independent_set_offsets_.back() + elements.size()); } // The ordering does not have to contain all parameter blocks, so @@ -114,8 +111,7 @@ const int num_parameter_blocks = residual_block->NumParameterBlocks(); for (int j = 0; j < num_parameter_blocks; ++j) { ParameterBlock* parameter_block = residual_block->parameter_blocks()[j]; - const map<ParameterBlock*, int>::const_iterator it = - parameter_block_index.find(parameter_block); + const auto it = parameter_block_index.find(parameter_block); if (it != parameter_block_index.end()) { residual_blocks_[it->second].push_back(residual_block); } @@ -267,13 +263,12 @@ ordering.group_to_elements(); // Verify that each group is an independent set - map<int, set<double*> >::const_iterator it = group_to_elements.begin(); - for (; it != group_to_elements.end(); ++it) { - if (!program.IsParameterBlockSetIndependent(it->second)) { + for (const auto& g_t_e : group_to_elements) { + if (!program.IsParameterBlockSetIndependent(g_t_e.second)) { *message = StringPrintf("The user-provided " "parameter_blocks_for_inner_iterations does not " - "form an independent set. Group Id: %d", it->first); + "form an independent set. Group Id: %d", g_t_e.first); return false; } }
diff --git a/internal/ceres/covariance_impl.cc b/internal/ceres/covariance_impl.cc index c52866b..484c94f 100644 --- a/internal/ceres/covariance_impl.cc +++ b/internal/ceres/covariance_impl.cc
@@ -38,6 +38,7 @@ #include <cstdlib> #include <numeric> #include <sstream> +#include <unordered_set> #include <utility> #include <vector> @@ -45,7 +46,6 @@ #include "Eigen/SparseQR" #include "Eigen/SVD" -#include "ceres/collections_port.h" #include "ceres/compressed_col_sparse_matrix_utils.h" #include "ceres/compressed_row_sparse_matrix.h" #include "ceres/covariance.h" @@ -412,7 +412,7 @@ vector<double*> all_parameter_blocks; problem->GetParameterBlocks(&all_parameter_blocks); const ProblemImpl::ParameterMap& parameter_map = problem->parameter_map(); - HashSet<ParameterBlock*> parameter_blocks_in_use; + std::unordered_set<ParameterBlock*> parameter_blocks_in_use; vector<ResidualBlock*> residual_blocks; problem->GetResidualBlocks(&residual_blocks); @@ -511,13 +511,10 @@ // rows of the covariance matrix in order. int i = 0; // index into covariance_blocks. int cursor = 0; // index into the covariance matrix. - for (map<const double*, int>::const_iterator it = - parameter_block_to_row_index_.begin(); - it != parameter_block_to_row_index_.end(); - ++it) { - const double* row_block = it->first; + for (const auto& entry : parameter_block_to_row_index_) { + const double* row_block = entry.first; const int row_block_size = problem->ParameterBlockLocalSize(row_block); - int row_begin = it->second; + int row_begin = entry.second; // Iterate over the covariance blocks contained in this row block // and count the number of columns in this row block.
diff --git a/internal/ceres/covariance_test.cc b/internal/ceres/covariance_test.cc index 92a7626..96c962a 100644 --- a/internal/ceres/covariance_test.cc +++ b/internal/ceres/covariance_test.cc
@@ -564,9 +564,8 @@ } int dof = 0; // degrees of freedom = sum of LocalSize()s - for (BoundsMap::const_iterator iter = column_bounds.begin(); - iter != column_bounds.end(); ++iter) { - dof = std::max(dof, iter->second.second); + for (const auto& bound : column_bounds) { + dof = std::max(dof, bound.second.second); } ConstMatrixRef expected(expected_covariance, dof, dof); double diff_norm = (expected.block(row_begin,
diff --git a/internal/ceres/graph.h b/internal/ceres/graph.h index b96b672..25bb141 100644 --- a/internal/ceres/graph.h +++ b/internal/ceres/graph.h
@@ -32,11 +32,12 @@ #define CERES_INTERNAL_GRAPH_H_ #include <limits> +#include <unordered_set> +#include <unordered_map> #include <utility> #include "ceres/integral_types.h" #include "ceres/map_util.h" -#include "ceres/collections_port.h" -#include "ceres/internal/macros.h" +#include "ceres/pair_hash.h" #include "ceres/types.h" #include "glog/logging.h" @@ -53,7 +54,7 @@ // Add a vertex. void AddVertex(const Vertex& vertex) { if (vertices_.insert(vertex).second) { - edges_[vertex] = HashSet<Vertex>(); + edges_[vertex] = std::unordered_set<Vertex>(); } } @@ -63,10 +64,9 @@ } vertices_.erase(vertex); - const HashSet<Vertex>& sinks = edges_[vertex]; - for (typename HashSet<Vertex>::const_iterator it = sinks.begin(); - it != sinks.end(); ++it) { - edges_[*it].erase(vertex); + const std::unordered_set<Vertex>& sinks = edges_[vertex]; + for (const Vertex& s : sinks) { + edges_[s].erase(vertex); } edges_.erase(vertex); @@ -90,19 +90,17 @@ // Calling Neighbors on a vertex not in the graph will result in // undefined behaviour. - const HashSet<Vertex>& Neighbors(const Vertex& vertex) const { + const std::unordered_set<Vertex>& Neighbors(const Vertex& vertex) const { return FindOrDie(edges_, vertex); } - const HashSet<Vertex>& vertices() const { + const std::unordered_set<Vertex>& vertices() const { return vertices_; } private: - HashSet<Vertex> vertices_; - HashMap<Vertex, HashSet<Vertex> > edges_; - - CERES_DISALLOW_COPY_AND_ASSIGN(Graph); + std::unordered_set<Vertex> vertices_; + std::unordered_map<Vertex, std::unordered_set<Vertex> > edges_; }; // A weighted undirected graph templated over the vertex ids. Vertex @@ -117,7 +115,7 @@ void AddVertex(const Vertex& vertex, double weight) { if (vertices_.find(vertex) == vertices_.end()) { vertices_.insert(vertex); - edges_[vertex] = HashSet<Vertex>(); + edges_[vertex] = std::unordered_set<Vertex>(); } vertex_weights_[vertex] = weight; } @@ -135,15 +133,14 @@ vertices_.erase(vertex); vertex_weights_.erase(vertex); - const HashSet<Vertex>& sinks = edges_[vertex]; - for (typename HashSet<Vertex>::const_iterator it = sinks.begin(); - it != sinks.end(); ++it) { - if (vertex < *it) { - edge_weights_.erase(std::make_pair(vertex, *it)); + const std::unordered_set<Vertex>& sinks = edges_[vertex]; + for (const Vertex& s : sinks) { + if (vertex < s) { + edge_weights_.erase(std::make_pair(vertex, s)); } else { - edge_weights_.erase(std::make_pair(*it, vertex)); + edge_weights_.erase(std::make_pair(s, vertex)); } - edges_[*it].erase(vertex); + edges_[s].erase(vertex); } edges_.erase(vertex); @@ -198,11 +195,11 @@ // Calling Neighbors on a vertex not in the graph will result in // undefined behaviour. - const HashSet<Vertex>& Neighbors(const Vertex& vertex) const { + const std::unordered_set<Vertex>& Neighbors(const Vertex& vertex) const { return FindOrDie(edges_, vertex); } - const HashSet<Vertex>& vertices() const { + const std::unordered_set<Vertex>& vertices() const { return vertices_; } @@ -211,12 +208,11 @@ } private: - HashSet<Vertex> vertices_; - HashMap<Vertex, double> vertex_weights_; - HashMap<Vertex, HashSet<Vertex> > edges_; - HashMap<std::pair<Vertex, Vertex>, double> edge_weights_; - - CERES_DISALLOW_COPY_AND_ASSIGN(WeightedGraph); + std::unordered_set<Vertex> vertices_; + std::unordered_map<Vertex, double> vertex_weights_; + std::unordered_map<Vertex, std::unordered_set<Vertex>> edges_; + std::unordered_map<std::pair<Vertex, Vertex>, double, pair_hash> + edge_weights_; }; } // namespace internal
diff --git a/internal/ceres/graph_algorithms.h b/internal/ceres/graph_algorithms.h index d1d3f52..08837cf 100644 --- a/internal/ceres/graph_algorithms.h +++ b/internal/ceres/graph_algorithms.h
@@ -34,9 +34,10 @@ #define CERES_INTERNAL_GRAPH_ALGORITHMS_H_ #include <algorithm> +#include <unordered_map> +#include <unordered_set> #include <vector> #include <utility> -#include "ceres/collections_port.h" #include "ceres/graph.h" #include "ceres/wall_time.h" #include "glog/logging.h" @@ -96,7 +97,7 @@ template <typename Vertex> int IndependentSetOrdering(const Graph<Vertex>& graph, std::vector<Vertex>* ordering) { - const HashSet<Vertex>& vertices = graph.vertices(); + const std::unordered_set<Vertex>& vertices = graph.vertices(); const int num_vertices = vertices.size(); CHECK_NOTNULL(ordering); @@ -109,34 +110,29 @@ const char kBlack = 2; // Mark all vertices white. - HashMap<Vertex, char> vertex_color; + std::unordered_map<Vertex, char> vertex_color; std::vector<Vertex> vertex_queue; - for (typename HashSet<Vertex>::const_iterator it = vertices.begin(); - it != vertices.end(); - ++it) { - vertex_color[*it] = kWhite; - vertex_queue.push_back(*it); + for (const Vertex& vertex : vertices) { + vertex_color[vertex] = kWhite; + vertex_queue.push_back(vertex); } - - std::sort(vertex_queue.begin(), vertex_queue.end(), + std::sort(vertex_queue.begin(), + vertex_queue.end(), VertexTotalOrdering<Vertex>(graph)); // Iterate over vertex_queue. Pick the first white vertex, add it // to the independent set. Mark it black and its neighbors grey. - for (int i = 0; i < vertex_queue.size(); ++i) { - const Vertex& vertex = vertex_queue[i]; + for (const Vertex& vertex : vertex_queue) { if (vertex_color[vertex] != kWhite) { continue; } ordering->push_back(vertex); vertex_color[vertex] = kBlack; - const HashSet<Vertex>& neighbors = graph.Neighbors(vertex); - for (typename HashSet<Vertex>::const_iterator it = neighbors.begin(); - it != neighbors.end(); - ++it) { - vertex_color[*it] = kGrey; + const std::unordered_set<Vertex>& neighbors = graph.Neighbors(vertex); + for (const Vertex& neighbor : neighbors) { + vertex_color[neighbor] = kGrey; } } @@ -145,10 +141,7 @@ // Iterate over the vertices and add all the grey vertices to the // ordering. At this stage there should only be black or grey // vertices in the graph. - for (typename std::vector<Vertex>::const_iterator it = vertex_queue.begin(); - it != vertex_queue.end(); - ++it) { - const Vertex vertex = *it; + for (const Vertex& vertex : vertex_queue) { DCHECK(vertex_color[vertex] != kWhite); if (vertex_color[vertex] != kBlack) { ordering->push_back(vertex); @@ -173,7 +166,7 @@ int StableIndependentSetOrdering(const Graph<Vertex>& graph, std::vector<Vertex>* ordering) { CHECK_NOTNULL(ordering); - const HashSet<Vertex>& vertices = graph.vertices(); + const std::unordered_set<Vertex>& vertices = graph.vertices(); const int num_vertices = vertices.size(); CHECK_EQ(vertices.size(), ordering->size()); @@ -188,11 +181,9 @@ VertexDegreeLessThan<Vertex>(graph)); // Mark all vertices white. - HashMap<Vertex, char> vertex_color; - for (typename HashSet<Vertex>::const_iterator it = vertices.begin(); - it != vertices.end(); - ++it) { - vertex_color[*it] = kWhite; + std::unordered_map<Vertex, char> vertex_color; + for (const Vertex& vertex : vertices) { + vertex_color[vertex] = kWhite; } ordering->clear(); @@ -207,11 +198,9 @@ ordering->push_back(vertex); vertex_color[vertex] = kBlack; - const HashSet<Vertex>& neighbors = graph.Neighbors(vertex); - for (typename HashSet<Vertex>::const_iterator it = neighbors.begin(); - it != neighbors.end(); - ++it) { - vertex_color[*it] = kGrey; + const std::unordered_set<Vertex>& neighbors = graph.Neighbors(vertex); + for (const Vertex& neighbor : neighbors) { + vertex_color[neighbor] = kGrey; } } @@ -220,10 +209,7 @@ // Iterate over the vertices and add all the grey vertices to the // ordering. At this stage there should only be black or grey // vertices in the graph. - for (typename std::vector<Vertex>::const_iterator it = vertex_queue.begin(); - it != vertex_queue.end(); - ++it) { - const Vertex vertex = *it; + for (const Vertex& vertex : vertex_queue) { DCHECK(vertex_color[vertex] != kWhite); if (vertex_color[vertex] != kBlack) { ordering->push_back(vertex); @@ -242,8 +228,8 @@ // is what gives this data structure its efficiency. template <typename Vertex> Vertex FindConnectedComponent(const Vertex& vertex, - HashMap<Vertex, Vertex>* union_find) { - typename HashMap<Vertex, Vertex>::iterator it = union_find->find(vertex); + std::unordered_map<Vertex, Vertex>* union_find) { + auto it = union_find->find(vertex); DCHECK(it != union_find->end()); if (it->second != vertex) { it->second = FindConnectedComponent(it->second, union_find); @@ -279,25 +265,19 @@ // Disjoint-set to keep track of the connected components in the // maximum spanning tree. - HashMap<Vertex, Vertex> disjoint_set; + std::unordered_map<Vertex, Vertex> disjoint_set; // Sort of the edges in the graph in decreasing order of their // weight. Also add the vertices of the graph to the Maximum // Spanning Tree graph and set each vertex to be its own connected // component in the disjoint_set structure. - const HashSet<Vertex>& vertices = graph.vertices(); - for (typename HashSet<Vertex>::const_iterator it = vertices.begin(); - it != vertices.end(); - ++it) { - const Vertex vertex1 = *it; + const std::unordered_set<Vertex>& vertices = graph.vertices(); + for (const Vertex& vertex1 : vertices) { forest->AddVertex(vertex1, graph.VertexWeight(vertex1)); disjoint_set[vertex1] = vertex1; - const HashSet<Vertex>& neighbors = graph.Neighbors(vertex1); - for (typename HashSet<Vertex>::const_iterator it2 = neighbors.begin(); - it2 != neighbors.end(); - ++it2) { - const Vertex vertex2 = *it2; + const std::unordered_set<Vertex>& neighbors = graph.Neighbors(vertex1); + for (const Vertex& vertex2 : neighbors) { if (vertex1 >= vertex2) { continue; }
diff --git a/internal/ceres/graph_algorithms_test.cc b/internal/ceres/graph_algorithms_test.cc index 1071488..160ece1 100644 --- a/internal/ceres/graph_algorithms_test.cc +++ b/internal/ceres/graph_algorithms_test.cc
@@ -31,8 +31,8 @@ #include "ceres/graph_algorithms.h" #include <algorithm> +#include <unordered_set> #include "gtest/gtest.h" -#include "ceres/collections_port.h" #include "ceres/graph.h" #include "ceres/internal/port.h" #include "ceres/internal/scoped_ptr.h" @@ -112,7 +112,7 @@ scoped_ptr<WeightedGraph<int> > forest(Degree2MaximumSpanningForest(graph)); - const HashSet<int>& vertices = forest->vertices(); + const std::unordered_set<int>& vertices = forest->vertices(); EXPECT_EQ(vertices.size(), 2); EXPECT_EQ(forest->VertexWeight(0), 1.0); EXPECT_EQ(forest->VertexWeight(1), 2.0); @@ -134,35 +134,35 @@ graph.AddEdge(0, 4, 4.0); scoped_ptr<WeightedGraph<int> > forest(Degree2MaximumSpanningForest(graph)); - const HashSet<int>& vertices = forest->vertices(); + const std::unordered_set<int>& vertices = forest->vertices(); EXPECT_EQ(vertices.size(), 5); { - const HashSet<int>& neighbors = forest->Neighbors(0); + const std::unordered_set<int>& neighbors = forest->Neighbors(0); EXPECT_EQ(neighbors.size(), 2); EXPECT_TRUE(neighbors.find(4) != neighbors.end()); EXPECT_TRUE(neighbors.find(3) != neighbors.end()); } { - const HashSet<int>& neighbors = forest->Neighbors(3); + const std::unordered_set<int>& neighbors = forest->Neighbors(3); EXPECT_EQ(neighbors.size(), 1); EXPECT_TRUE(neighbors.find(0) != neighbors.end()); } { - const HashSet<int>& neighbors = forest->Neighbors(4); + const std::unordered_set<int>& neighbors = forest->Neighbors(4); EXPECT_EQ(neighbors.size(), 1); EXPECT_TRUE(neighbors.find(0) != neighbors.end()); } { - const HashSet<int>& neighbors = forest->Neighbors(1); + const std::unordered_set<int>& neighbors = forest->Neighbors(1); EXPECT_EQ(neighbors.size(), 0); } { - const HashSet<int>& neighbors = forest->Neighbors(2); + const std::unordered_set<int>& neighbors = forest->Neighbors(2); EXPECT_EQ(neighbors.size(), 0); } }
diff --git a/internal/ceres/graph_test.cc b/internal/ceres/graph_test.cc index e9d4e1c..0907f86 100644 --- a/internal/ceres/graph_test.cc +++ b/internal/ceres/graph_test.cc
@@ -30,8 +30,8 @@ #include "ceres/graph.h" +#include <unordered_set> #include "gtest/gtest.h" -#include "ceres/collections_port.h" #include "ceres/internal/scoped_ptr.h" namespace ceres { @@ -48,7 +48,7 @@ graph.AddVertex(1); graph.AddEdge(0, 1); - const HashSet<int>& vertices = graph.vertices(); + const std::unordered_set<int>& vertices = graph.vertices(); EXPECT_EQ(vertices.size(), 2); EXPECT_EQ(graph.Neighbors(0).size(), 1); EXPECT_EQ(graph.Neighbors(1).size(), 1); @@ -60,7 +60,7 @@ graph.AddVertex(1); graph.AddEdge(0, 1); - const HashSet<int>& vertices = graph.vertices(); + const std::unordered_set<int>& vertices = graph.vertices(); EXPECT_EQ(vertices.size(), 2); @@ -93,7 +93,7 @@ graph.AddVertex(1, 2.0); graph.AddEdge(0, 1, 0.5); - const HashSet<int>& vertices = graph.vertices(); + const std::unordered_set<int>& vertices = graph.vertices(); EXPECT_EQ(vertices.size(), 2); EXPECT_EQ(graph.VertexWeight(0), 1.0); EXPECT_EQ(graph.VertexWeight(1), 2.0); @@ -109,7 +109,7 @@ graph.AddVertex(1, 2.0); graph.AddEdge(0, 1, 0.5); - const HashSet<int>& vertices = graph.vertices(); + const std::unordered_set<int>& vertices = graph.vertices(); EXPECT_EQ(vertices.size(), 2);
diff --git a/internal/ceres/low_rank_inverse_hessian.cc b/internal/ceres/low_rank_inverse_hessian.cc index 1c6c992..f3953c4 100644 --- a/internal/ceres/low_rank_inverse_hessian.cc +++ b/internal/ceres/low_rank_inverse_hessian.cc
@@ -175,12 +175,10 @@ << "approximation."; } - for (list<int>::const_iterator it = indices_.begin(); - it != indices_.end(); - ++it) { - const double beta = delta_gradient_history_.col(*it).dot(search_direction) / - delta_x_dot_delta_gradient_(*it); - search_direction += delta_x_history_.col(*it) * (alpha(*it) - beta); + for (const int i : indices_) { + const double beta = delta_gradient_history_.col(i).dot(search_direction) / + delta_x_dot_delta_gradient_(i); + search_direction += delta_x_history_.col(i) * (alpha(i) - beta); } }
diff --git a/internal/ceres/ordered_groups_test.cc b/internal/ceres/ordered_groups_test.cc index 4510686..8cf4324 100644 --- a/internal/ceres/ordered_groups_test.cc +++ b/internal/ceres/ordered_groups_test.cc
@@ -33,7 +33,6 @@ #include <cstddef> #include <vector> #include "gtest/gtest.h" -#include "ceres/collections_port.h" namespace ceres { namespace internal {
diff --git a/internal/ceres/pair_hash.h b/internal/ceres/pair_hash.h new file mode 100644 index 0000000..7fb32cf --- /dev/null +++ b/internal/ceres/pair_hash.h
@@ -0,0 +1,112 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2018 Google Inc. All rights reserved. +// http://ceres-solver.org/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) +// +// A hasher for std::pair<T, T>. + +#ifndef CERES_INTERNAL_PAIR_HASH_H_ +#define CERES_INTERNAL_PAIR_HASH_H_ + +#include "ceres/internal/port.h" +#include <utility> +#include "ceres/integral_types.h" + +namespace ceres { +namespace internal { + +#if defined(_WIN32) && !defined(__MINGW64__) && !defined(__MINGW32__) +#define GG_LONGLONG(x) x##I64 +#define GG_ULONGLONG(x) x##UI64 +#else +#define GG_LONGLONG(x) x##LL +#define GG_ULONGLONG(x) x##ULL +#endif + +// The hash function is due to Bob Jenkins (see +// http://burtleburtle.net/bob/hash/index.html). Each mix takes 36 instructions, +// in 18 cycles if you're lucky. On x86 architectures, this requires 45 +// instructions in 27 cycles, if you're lucky. +// +// 32bit version +inline void hash_mix(uint32& a, uint32& b, uint32& c) { + a -= b; a -= c; a ^= (c>>13); + b -= c; b -= a; b ^= (a<<8); + c -= a; c -= b; c ^= (b>>13); + a -= b; a -= c; a ^= (c>>12); + b -= c; b -= a; b ^= (a<<16); + c -= a; c -= b; c ^= (b>>5); + a -= b; a -= c; a ^= (c>>3); + b -= c; b -= a; b ^= (a<<10); + c -= a; c -= b; c ^= (b>>15); +} + +// 64bit version +inline void hash_mix(uint64& a, uint64& b, uint64& c) { + a -= b; a -= c; a ^= (c>>43); + b -= c; b -= a; b ^= (a<<9); + c -= a; c -= b; c ^= (b>>8); + a -= b; a -= c; a ^= (c>>38); + b -= c; b -= a; b ^= (a<<23); + c -= a; c -= b; c ^= (b>>5); + a -= b; a -= c; a ^= (c>>35); + b -= c; b -= a; b ^= (a<<49); + c -= a; c -= b; c ^= (b>>11); +} + +inline uint32 Hash32NumWithSeed(uint32 num, uint32 c) { + // The golden ratio; an arbitrary value. + uint32 b = 0x9e3779b9UL; + hash_mix(num, b, c); + return c; +} + +inline uint64 Hash64NumWithSeed(uint64 num, uint64 c) { + // More of the golden ratio. + uint64 b = GG_ULONGLONG(0xe08c1d668b756f82); + hash_mix(num, b, c); + return c; +} + +// Hasher for STL pairs. Requires hashers for both members to be defined. +struct pair_hash { + public: + template <typename T> + std::size_t operator()(const std::pair<T, T>& p) const { + const std::size_t h1 = std::hash<T>()(p.first); + const std::size_t h2 = std::hash<T>()(p.second); + // The decision below is at compile time + return (sizeof(h1) <= sizeof(uint32)) ? Hash32NumWithSeed(h1, h2) + : Hash64NumWithSeed(h1, h2); + } +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_PAIR_HASH_H_
diff --git a/internal/ceres/parameter_block.h b/internal/ceres/parameter_block.h index 8e21553..a41d9d1 100644 --- a/internal/ceres/parameter_block.h +++ b/internal/ceres/parameter_block.h
@@ -35,8 +35,8 @@ #include <cstdlib> #include <limits> #include <string> +#include <unordered_set> #include "ceres/array_utils.h" -#include "ceres/collections_port.h" #include "ceres/integral_types.h" #include "ceres/internal/eigen.h" #include "ceres/internal/port.h" @@ -71,7 +71,7 @@ // when it is small, but transitions to a hash set when it has more elements. // // For now, use a hash set. - typedef HashSet<ResidualBlock*> ResidualBlockSet; + typedef std::unordered_set<ResidualBlock*> ResidualBlockSet; // Create a parameter block with the user state, size, and index specified. // The size is the size of the parameter block and the index is the position
diff --git a/internal/ceres/parameter_block_ordering.cc b/internal/ceres/parameter_block_ordering.cc index efba339..649ce14 100644 --- a/internal/ceres/parameter_block_ordering.cc +++ b/internal/ceres/parameter_block_ordering.cc
@@ -30,6 +30,7 @@ #include "ceres/parameter_block_ordering.h" +#include <unordered_set> #include "ceres/graph.h" #include "ceres/graph_algorithms.h" #include "ceres/internal/scoped_ptr.h" @@ -55,7 +56,7 @@ event_logger.AddEvent("CreateHessianGraph"); const vector<ParameterBlock*>& parameter_blocks = program.parameter_blocks(); - const HashSet<ParameterBlock*>& vertices = graph->vertices(); + const std::unordered_set<ParameterBlock*>& vertices = graph->vertices(); for (int i = 0; i < parameter_blocks.size(); ++i) { if (vertices.count(parameter_blocks[i]) > 0) { ordering->push_back(parameter_blocks[i]); @@ -162,10 +163,8 @@ const map<int, set<double*> >& group_to_elements = ordering->group_to_elements(); - for (map<int, set<double*> >::const_iterator it = group_to_elements.begin(); - it != group_to_elements.end(); - ++it) { - group_sizes->push_back(it->second.size()); + for (const auto& g_t_e : group_to_elements) { + group_sizes->push_back(g_t_e.second.size()); } }
diff --git a/internal/ceres/parameter_block_ordering_test.cc b/internal/ceres/parameter_block_ordering_test.cc index c98cdb5..41babff 100644 --- a/internal/ceres/parameter_block_ordering_test.cc +++ b/internal/ceres/parameter_block_ordering_test.cc
@@ -31,9 +31,9 @@ #include "ceres/parameter_block_ordering.h" #include <cstddef> +#include <unordered_set> #include <vector> #include "gtest/gtest.h" -#include "ceres/collections_port.h" #include "ceres/graph.h" #include "ceres/problem_impl.h" #include "ceres/program.h" @@ -48,7 +48,7 @@ using std::vector; typedef Graph<ParameterBlock*> HessianGraph; -typedef HashSet<ParameterBlock*> VertexSet; +typedef std::unordered_set<ParameterBlock*> VertexSet; template <int M, int N1 = 0, int N2 = 0, int N3 = 0> class DummyCostFunction: public SizedCostFunction<M, N1, N2, N3> {
diff --git a/internal/ceres/problem_impl.cc b/internal/ceres/problem_impl.cc index 3ed0efd..1f3c55b 100644 --- a/internal/ceres/problem_impl.cc +++ b/internal/ceres/problem_impl.cc
@@ -63,7 +63,6 @@ using std::map; using std::string; using std::vector; -typedef std::map<double*, internal::ParameterBlock*> ParameterMap; namespace { // Returns true if two regions of memory, a and b, with sizes size_a and size_b @@ -90,7 +89,7 @@ template <typename KeyType> void DecrementValueOrDeleteKey(const KeyType key, std::map<KeyType, int>* container) { - typename std::map<KeyType, int>::iterator it = container->find(key); + auto it = container->find(key); if (it->second == 1) { delete key; container->erase(it); @@ -936,10 +935,9 @@ void ProblemImpl::GetParameterBlocks(vector<double*>* parameter_blocks) const { CHECK_NOTNULL(parameter_blocks); parameter_blocks->resize(0); - for (ParameterMap::const_iterator it = parameter_block_map_.begin(); - it != parameter_block_map_.end(); - ++it) { - parameter_blocks->push_back(it->first); + parameter_blocks->reserve(parameter_block_map_.size()); + for (const auto& entry : parameter_block_map_) { + parameter_blocks->push_back(entry.first); } }
diff --git a/internal/ceres/problem_impl.h b/internal/ceres/problem_impl.h index 03e61d2..4c24e3b 100644 --- a/internal/ceres/problem_impl.h +++ b/internal/ceres/problem_impl.h
@@ -40,9 +40,9 @@ #define CERES_PUBLIC_PROBLEM_IMPL_H_ #include <map> +#include <unordered_set> #include <vector> -#include "ceres/collections_port.h" #include "ceres/context_impl.h" #include "ceres/internal/macros.h" #include "ceres/internal/port.h" @@ -65,7 +65,7 @@ class ProblemImpl { public: typedef std::map<double*, ParameterBlock*> ParameterMap; - typedef HashSet<ResidualBlock*> ResidualBlockSet; + typedef std::unordered_set<ResidualBlock*> ResidualBlockSet; typedef std::map<CostFunction*, int> CostFunctionRefCount; typedef std::map<LossFunction*, int> LossFunctionRefCount; @@ -203,7 +203,7 @@ ContextImpl* context_impl_; // The mapping from user pointers to parameter blocks. - std::map<double*, ParameterBlock*> parameter_block_map_; + ParameterMap parameter_block_map_; // Iff enable_fast_removal is enabled, contains the current residual blocks. ResidualBlockSet residual_block_set_;
diff --git a/internal/ceres/program.cc b/internal/ceres/program.cc index 8e97f07..f6cd138 100644 --- a/internal/ceres/program.cc +++ b/internal/ceres/program.cc
@@ -373,11 +373,10 @@ // blocks in the same residual block are part of // parameter_block_ptrs as that would violate the assumption that it // is an independent set in the Hessian matrix. - for (vector<ResidualBlock*>::const_iterator it = residual_blocks_.begin(); - it != residual_blocks_.end(); - ++it) { - ParameterBlock* const* parameter_blocks = (*it)->parameter_blocks(); - const int num_parameter_blocks = (*it)->NumParameterBlocks(); + for (const ResidualBlock* residual_block : residual_blocks_) { + ParameterBlock* const* parameter_blocks = + residual_block->parameter_blocks(); + const int num_parameter_blocks = residual_block->NumParameterBlocks(); int count = 0; for (int i = 0; i < num_parameter_blocks; ++i) { count += independent_set.count(
diff --git a/internal/ceres/reorder_program.cc b/internal/ceres/reorder_program.cc index a7c3710..94a35bd 100644 --- a/internal/ceres/reorder_program.cc +++ b/internal/ceres/reorder_program.cc
@@ -234,23 +234,18 @@ parameter_blocks->clear(); const map<int, set<double*> >& groups = ordering.group_to_elements(); - for (map<int, set<double*> >::const_iterator group_it = groups.begin(); - group_it != groups.end(); - ++group_it) { - const set<double*>& group = group_it->second; - for (set<double*>::const_iterator parameter_block_ptr_it = group.begin(); - parameter_block_ptr_it != group.end(); - ++parameter_block_ptr_it) { - ProblemImpl::ParameterMap::const_iterator parameter_block_it = - parameter_map.find(*parameter_block_ptr_it); - if (parameter_block_it == parameter_map.end()) { + for (const auto& p : groups) { + const set<double*>& group = p.second; + for (double* parameter_block_ptr : group) { + auto it = parameter_map.find(parameter_block_ptr); + if (it == parameter_map.end()) { *error = StringPrintf("User specified ordering contains a pointer " "to a double that is not a parameter block in " "the problem. The invalid double is in group: %d", - group_it->first); + p.first); return false; } - parameter_blocks->push_back(parameter_block_it->second); + parameter_blocks->push_back(it->second); } } return true;
diff --git a/internal/ceres/schur_jacobi_preconditioner.cc b/internal/ceres/schur_jacobi_preconditioner.cc index d7f6fe9..13e6463 100644 --- a/internal/ceres/schur_jacobi_preconditioner.cc +++ b/internal/ceres/schur_jacobi_preconditioner.cc
@@ -34,7 +34,6 @@ #include <vector> #include "ceres/block_random_access_diagonal_matrix.h" #include "ceres/block_sparse_matrix.h" -#include "ceres/collections_port.h" #include "ceres/internal/scoped_ptr.h" #include "ceres/linear_solver.h" #include "ceres/schur_eliminator.h"
diff --git a/internal/ceres/schur_jacobi_preconditioner.h b/internal/ceres/schur_jacobi_preconditioner.h index 5398f3f..fb7753b 100644 --- a/internal/ceres/schur_jacobi_preconditioner.h +++ b/internal/ceres/schur_jacobi_preconditioner.h
@@ -41,7 +41,6 @@ #include <set> #include <vector> #include <utility> -#include "ceres/collections_port.h" #include "ceres/internal/macros.h" #include "ceres/internal/scoped_ptr.h" #include "ceres/preconditioner.h"
diff --git a/internal/ceres/single_linkage_clustering.cc b/internal/ceres/single_linkage_clustering.cc index 9e9342a..2d3213a 100644 --- a/internal/ceres/single_linkage_clustering.cc +++ b/internal/ceres/single_linkage_clustering.cc
@@ -30,8 +30,9 @@ #include "ceres/single_linkage_clustering.h" +#include <unordered_set> +#include <unordered_map> #include "ceres/graph.h" -#include "ceres/collections_port.h" #include "ceres/graph_algorithms.h" namespace ceres { @@ -40,27 +41,18 @@ int ComputeSingleLinkageClustering( const SingleLinkageClusteringOptions& options, const WeightedGraph<int>& graph, - HashMap<int, int>* membership) { + std::unordered_map<int, int>* membership) { CHECK_NOTNULL(membership)->clear(); // Initially each vertex is in its own cluster. - const HashSet<int>& vertices = graph.vertices(); - for (HashSet<int>::const_iterator it = vertices.begin(); - it != vertices.end(); - ++it) { - (*membership)[*it] = *it; + const std::unordered_set<int>& vertices = graph.vertices(); + for (const int v : vertices) { + (*membership)[v] = v; } - for (HashSet<int>::const_iterator it1 = vertices.begin(); - it1 != vertices.end(); - ++it1) { - const int vertex1 = *it1; - const HashSet<int>& neighbors = graph.Neighbors(vertex1); - for (HashSet<int>::const_iterator it2 = neighbors.begin(); - it2 != neighbors.end(); - ++it2) { - const int vertex2 = *it2; - + for (const int vertex1 : vertices) { + const std::unordered_set<int>& neighbors = graph.Neighbors(vertex1); + for (const int vertex2 : neighbors) { // Since the graph is undirected, only pay attention to one side // of the edge and ignore weak edges. if ((vertex1 > vertex2) || @@ -87,11 +79,9 @@ // Make sure that every vertex is connected directly to the vertex // identifying the cluster. int num_clusters = 0; - for (HashMap<int, int>::iterator it = membership->begin(); - it != membership->end(); - ++it) { - it->second = FindConnectedComponent(it->first, membership); - if (it->first == it->second) { + for (auto& m : *membership) { + m.second = FindConnectedComponent(m.first, membership); + if (m.first == m.second) { ++num_clusters; } }
diff --git a/internal/ceres/single_linkage_clustering.h b/internal/ceres/single_linkage_clustering.h index 8d1f02b..374125b 100644 --- a/internal/ceres/single_linkage_clustering.h +++ b/internal/ceres/single_linkage_clustering.h
@@ -31,7 +31,7 @@ #ifndef CERES_INTERNAL_SINGLE_LINKAGE_CLUSTERING_H_ #define CERES_INTERNAL_SINGLE_LINKAGE_CLUSTERING_H_ -#include "ceres/collections_port.h" +#include <unordered_map> #include "ceres/graph.h" namespace ceres { @@ -60,7 +60,7 @@ int ComputeSingleLinkageClustering( const SingleLinkageClusteringOptions& options, const WeightedGraph<int>& graph, - HashMap<int, int>* membership); + std::unordered_map<int, int>* membership); } // namespace internal } // namespace ceres
diff --git a/internal/ceres/single_linkage_clustering_test.cc b/internal/ceres/single_linkage_clustering_test.cc index ca1a661..281c281 100644 --- a/internal/ceres/single_linkage_clustering_test.cc +++ b/internal/ceres/single_linkage_clustering_test.cc
@@ -30,7 +30,7 @@ #include "ceres/single_linkage_clustering.h" -#include "ceres/collections_port.h" +#include <unordered_map> #include "ceres/graph.h" #include "gtest/gtest.h" @@ -52,7 +52,7 @@ graph.AddEdge(4, 5, 1.0); SingleLinkageClusteringOptions options; - HashMap<int, int> membership; + std::unordered_map<int, int> membership; ComputeSingleLinkageClustering(options, graph, &membership); EXPECT_EQ(membership.size(), kNumVertices); @@ -81,7 +81,7 @@ graph.AddEdge(4, 5, 0.5); SingleLinkageClusteringOptions options; - HashMap<int, int> membership; + std::unordered_map<int, int> membership; ComputeSingleLinkageClustering(options, graph, &membership); EXPECT_EQ(membership.size(), kNumVertices); @@ -111,7 +111,7 @@ graph.AddEdge(4, 5, 1.0); SingleLinkageClusteringOptions options; - HashMap<int, int> membership; + std::unordered_map<int, int> membership; ComputeSingleLinkageClustering(options, graph, &membership); EXPECT_EQ(membership.size(), kNumVertices);
diff --git a/internal/ceres/visibility.cc b/internal/ceres/visibility.cc index cb962a6..a446b6b 100644 --- a/internal/ceres/visibility.cc +++ b/internal/ceres/visibility.cc
@@ -35,10 +35,11 @@ #include <algorithm> #include <set> #include <vector> +#include <unordered_map> #include <utility> #include "ceres/block_structure.h" -#include "ceres/collections_port.h" #include "ceres/graph.h" +#include "ceres/pair_hash.h" #include "glog/logging.h" namespace ceres { @@ -98,22 +99,17 @@ vector<set<int> > inverse_visibility(num_points); for (int i = 0; i < visibility.size(); i++) { const set<int>& visibility_set = visibility[i]; - for (set<int>::const_iterator it = visibility_set.begin(); - it != visibility_set.end(); - ++it) { - inverse_visibility[*it].insert(i); + for (const int v : visibility_set) { + inverse_visibility[v].insert(i); } } // Map from camera pairs to number of points visible to both cameras // in the pair. - HashMap<pair<int, int>, int > camera_pairs; + std::unordered_map<pair<int, int>, int, pair_hash> camera_pairs; // Count the number of points visible to each camera/f_block pair. - for (vector<set<int> >::const_iterator it = inverse_visibility.begin(); - it != inverse_visibility.end(); - ++it) { - const set<int>& inverse_visibility_set = *it; + for (const auto& inverse_visibility_set : inverse_visibility) { for (set<int>::const_iterator camera1 = inverse_visibility_set.begin(); camera1 != inverse_visibility_set.end(); ++camera1) { @@ -136,14 +132,11 @@ } // Add an edge for each camera pair. - for (HashMap<pair<int, int>, int>::const_iterator it = camera_pairs.begin(); - it != camera_pairs.end(); - ++it) { - const int camera1 = it->first.first; - const int camera2 = it->first.second; - CHECK_NE(camera1, camera2); - - const int count = it->second; + for (const auto& camera_pair_count : camera_pairs) { + const int camera1 = camera_pair_count.first.first; + const int camera2 = camera_pair_count.first.second; + const int count = camera_pair_count.second; + DCHECK_NE(camera1, camera2); // Static cast necessary for Windows. const double weight = static_cast<double>(count) / (sqrt(static_cast<double>(
diff --git a/internal/ceres/visibility_based_preconditioner.cc b/internal/ceres/visibility_based_preconditioner.cc index 24563ae..31d2cc3 100644 --- a/internal/ceres/visibility_based_preconditioner.cc +++ b/internal/ceres/visibility_based_preconditioner.cc
@@ -40,7 +40,6 @@ #include "ceres/block_random_access_sparse_matrix.h" #include "ceres/block_sparse_matrix.h" #include "ceres/canonical_views_clustering.h" -#include "ceres/collections_port.h" #include "ceres/graph.h" #include "ceres/graph_algorithms.h" #include "ceres/internal/scoped_ptr.h" @@ -177,7 +176,7 @@ scoped_ptr<WeightedGraph<int> > schur_complement_graph( CHECK_NOTNULL(CreateSchurComplementGraph(visibility))); - HashMap<int, int> membership; + std::unordered_map<int, int> membership; if (options_.visibility_clustering_type == CANONICAL_VIEWS) { vector<int> centers; @@ -382,11 +381,9 @@ // matrix. Scaling these off-diagonal entries by 1/2 forces this // matrix to be positive definite. void VisibilityBasedPreconditioner::ScaleOffDiagonalCells() { - for (set<pair<int, int> >::const_iterator it = block_pairs_.begin(); - it != block_pairs_.end(); - ++it) { - const int block1 = it->first; - const int block2 = it->second; + for (const auto& block_pair : block_pairs_) { + const int block1 = block_pair.first; + const int block2 = block_pair.second; if (!IsBlockPairOffDiagonal(block1, block2)) { continue; } @@ -464,23 +461,17 @@ // each vertex. void VisibilityBasedPreconditioner::ForestToClusterPairs( const WeightedGraph<int>& forest, - HashSet<pair<int, int> >* cluster_pairs) const { + std::unordered_set<pair<int, int>, pair_hash >* cluster_pairs) const { CHECK_NOTNULL(cluster_pairs)->clear(); - const HashSet<int>& vertices = forest.vertices(); + const std::unordered_set<int>& vertices = forest.vertices(); CHECK_EQ(vertices.size(), num_clusters_); // Add all the cluster pairs corresponding to the edges in the // forest. - for (HashSet<int>::const_iterator it1 = vertices.begin(); - it1 != vertices.end(); - ++it1) { - const int cluster1 = *it1; + for (const int cluster1 : vertices) { cluster_pairs->insert(make_pair(cluster1, cluster1)); - const HashSet<int>& neighbors = forest.Neighbors(cluster1); - for (HashSet<int>::const_iterator it2 = neighbors.begin(); - it2 != neighbors.end(); - ++it2) { - const int cluster2 = *it2; + const std::unordered_set<int>& neighbors = forest.Neighbors(cluster1); + for (const int cluster2 : neighbors) { if (cluster1 < cluster2) { cluster_pairs->insert(make_pair(cluster1, cluster2)); } @@ -538,7 +529,7 @@ return cluster_graph; } -// Canonical views clustering returns a HashMap from vertices to +// Canonical views clustering returns a std::unordered_map from vertices to // cluster ids. Convert this into a flat array for quick lookup. It is // possible that some of the vertices may not be associated with any // cluster. In that case, randomly assign them to one of the clusters. @@ -547,20 +538,18 @@ // the membership_map, we also map the cluster ids to a contiguous set // of integers so that the cluster ids are in [0, num_clusters_). void VisibilityBasedPreconditioner::FlattenMembershipMap( - const HashMap<int, int>& membership_map, + const std::unordered_map<int, int>& membership_map, vector<int>* membership_vector) const { CHECK_NOTNULL(membership_vector)->resize(0); membership_vector->resize(num_blocks_, -1); - HashMap<int, int> cluster_id_to_index; + std::unordered_map<int, int> cluster_id_to_index; // Iterate over the cluster membership map and update the // cluster_membership_ vector assigning arbitrary cluster ids to // the few cameras that have not been clustered. - for (HashMap<int, int>::const_iterator it = membership_map.begin(); - it != membership_map.end(); - ++it) { - const int camera_id = it->first; - int cluster_id = it->second; + for (const auto& m : membership_map) { + const int camera_id = m.first; + int cluster_id = m.second; // If the view was not clustered, randomly assign it to one of the // clusters. This preserves the mathematical correctness of the
diff --git a/internal/ceres/visibility_based_preconditioner.h b/internal/ceres/visibility_based_preconditioner.h index 40ce2c7..1c831d0 100644 --- a/internal/ceres/visibility_based_preconditioner.h +++ b/internal/ceres/visibility_based_preconditioner.h
@@ -49,13 +49,15 @@ #define CERES_INTERNAL_VISIBILITY_BASED_PRECONDITIONER_H_ #include <set> +#include <unordered_map> +#include <unordered_set> #include <utility> #include <vector> -#include "ceres/collections_port.h" #include "ceres/graph.h" #include "ceres/internal/macros.h" #include "ceres/internal/scoped_ptr.h" #include "ceres/linear_solver.h" +#include "ceres/pair_hash.h" #include "ceres/preconditioner.h" #include "ceres/sparse_cholesky.h" @@ -150,7 +152,7 @@ void ScaleOffDiagonalCells(); void ClusterCameras(const std::vector<std::set<int> >& visibility); - void FlattenMembershipMap(const HashMap<int, int>& membership_map, + void FlattenMembershipMap(const std::unordered_map<int, int>& membership_map, std::vector<int>* membership_vector) const; void ComputeClusterVisibility( const std::vector<std::set<int> >& visibility, @@ -158,7 +160,7 @@ WeightedGraph<int>* CreateClusterGraph( const std::vector<std::set<int> >& visibility) const; void ForestToClusterPairs(const WeightedGraph<int>& forest, - HashSet<std::pair<int, int> >* cluster_pairs) const; + std::unordered_set<std::pair<int, int>, pair_hash>* cluster_pairs) const; void ComputeBlockPairsInPreconditioner(const CompressedRowBlockStructure& bs); bool IsBlockPairInPreconditioner(int block1, int block2) const; bool IsBlockPairOffDiagonal(int block1, int block2) const; @@ -182,7 +184,7 @@ // Set of cluster pairs (including self pairs (i,i)) in the // preconditioner. - HashSet<std::pair<int, int> > cluster_pairs_; + std::unordered_set<std::pair<int, int>, pair_hash> cluster_pairs_; scoped_ptr<SchurEliminatorBase> eliminator_; // Preconditioner matrix.
diff --git a/internal/ceres/visibility_based_preconditioner_test.cc b/internal/ceres/visibility_based_preconditioner_test.cc index d2f13bc..2227116 100644 --- a/internal/ceres/visibility_based_preconditioner_test.cc +++ b/internal/ceres/visibility_based_preconditioner_test.cc
@@ -35,15 +35,14 @@ #include "ceres/block_random_access_sparse_matrix.h" #include "ceres/block_sparse_matrix.h" #include "ceres/casts.h" -#include "ceres/collections_port.h" #include "ceres/file.h" #include "ceres/internal/eigen.h" #include "ceres/internal/scoped_ptr.h" #include "ceres/linear_least_squares_problems.h" #include "ceres/schur_eliminator.h" #include "ceres/stringprintf.h" -#include "ceres/types.h" #include "ceres/test_util.h" +#include "ceres/types.h" #include "glog/logging.h" #include "gtest/gtest.h" @@ -110,11 +109,11 @@ // schur_complement_.get(), rhs.data()); // } - // AssertionResult IsSparsityStructureValid() { // preconditioner_->InitStorage(*A_->block_structure()); -// const HashSet<pair<int, int> >& cluster_pairs = get_cluster_pairs(); -// const vector<int>& cluster_membership = get_cluster_membership(); +// const std::unordered_set<pair<int, int>, pair_hash>& cluster_pairs = +// get_cluster_pairs(); const vector<int>& cluster_membership = +// get_cluster_membership(); // for (int i = 0; i < num_camera_blocks_; ++i) { // for (int j = i; j < num_camera_blocks_; ++j) { @@ -137,8 +136,8 @@ // AssertionResult PreconditionerValuesMatch() { // preconditioner_->Update(*A_, D_.get()); -// const HashSet<pair<int, int> >& cluster_pairs = get_cluster_pairs(); -// const BlockRandomAccessSparseMatrix* m = get_m(); +// const std::unordered_set<pair<int, int>, pair_hash>& cluster_pairs = +// get_cluster_pairs(); const BlockRandomAccessSparseMatrix* m = get_m(); // Matrix preconditioner_matrix; // m->matrix()->ToDenseMatrix(&preconditioner_matrix); // ConstMatrixRef full_schur_complement(schur_complement_->values(), @@ -205,11 +204,12 @@ // return &preconditioner_->block_pairs_; // } -// const HashSet<pair<int, int> >& get_cluster_pairs() { +// const std::unordered_set<pair<int, int>, pair_hash>& get_cluster_pairs() { // return preconditioner_->cluster_pairs_; // } -// HashSet<pair<int, int> >* get_mutable_cluster_pairs() { +// std::unordered_set<pair<int, int>, pair_hash>* get_mutable_cluster_pairs() +// { // return &preconditioner_->cluster_pairs_; // } @@ -253,8 +253,8 @@ // *get_mutable_num_clusters() = 1; -// HashSet<pair<int, int> >& cluster_pairs = *get_mutable_cluster_pairs(); -// cluster_pairs.clear(); +// std::unordered_set<pair<int, int>, pair_hash>& cluster_pairs = +// *get_mutable_cluster_pairs(); cluster_pairs.clear(); // cluster_pairs.insert(make_pair(0, 0)); // EXPECT_TRUE(IsSparsityStructureValid()); @@ -284,8 +284,6 @@ // } // } - - // TEST_F(VisibilityBasedPreconditionerTest, ClusterJacobi) { // options_.type = CLUSTER_JACOBI; // preconditioner_.reset( @@ -301,9 +299,9 @@ // } // *get_mutable_num_clusters() = kNumClusters; -// HashSet<pair<int, int> >& cluster_pairs = *get_mutable_cluster_pairs(); -// cluster_pairs.clear(); -// for (int i = 0; i < kNumClusters; ++i) { +// std::unordered_set<pair<int, int>, pair_hash>& cluster_pairs = +// *get_mutable_cluster_pairs(); cluster_pairs.clear(); for (int i = 0; i < +// kNumClusters; ++i) { // cluster_pairs.insert(make_pair(i, i)); // } @@ -311,7 +309,6 @@ // EXPECT_TRUE(PreconditionerValuesMatch()); // } - // TEST_F(VisibilityBasedPreconditionerTest, ClusterTridiagonal) { // options_.type = CLUSTER_TRIDIAGONAL; // preconditioner_.reset( @@ -327,9 +324,9 @@ // *get_mutable_num_clusters() = kNumClusters; // // Spanning forest has structure 0-1 2 -// HashSet<pair<int, int> >& cluster_pairs = *get_mutable_cluster_pairs(); -// cluster_pairs.clear(); -// for (int i = 0; i < kNumClusters; ++i) { +// std::unordered_set<pair<int, int>, pair_hash>& cluster_pairs = +// *get_mutable_cluster_pairs(); cluster_pairs.clear(); for (int i = 0; i < +// kNumClusters; ++i) { // cluster_pairs.insert(make_pair(i, i)); // } // cluster_pairs.insert(make_pair(0, 1));