Move CompactifyArray to array_utils. 1. Rename it to MapValuesToContiguousRange. 2. Improve implementation to just use a vector. Change-Id: I2a5e73e3a6fb81694c6f452a00d60df16c0149e6
diff --git a/internal/ceres/array_utils.cc b/internal/ceres/array_utils.cc index 3eea042..205ddaf 100644 --- a/internal/ceres/array_utils.cc +++ b/internal/ceres/array_utils.cc
@@ -30,10 +30,11 @@ #include "ceres/array_utils.h" +#include <algorithm> #include <cmath> #include <cstddef> #include <string> - +#include <vector> #include "ceres/fpclassify.h" #include "ceres/stringprintf.h" @@ -94,5 +95,19 @@ } } +void MapValuesToContiguousRange(const int size, int* array) { + std::vector<int> unique_values(array, array + size); + std::sort(unique_values.begin(), unique_values.end()); + unique_values.erase(std::unique(unique_values.begin(), + unique_values.end()), + unique_values.end()); + + for (int i = 0; i < size; ++i) { + array[i] = std::lower_bound(unique_values.begin(), + unique_values.end(), + array[i]) - unique_values.begin(); + } +} + } // namespace internal } // namespace ceres
diff --git a/internal/ceres/array_utils.h b/internal/ceres/array_utils.h index 34fda6f..55e68a8 100644 --- a/internal/ceres/array_utils.h +++ b/internal/ceres/array_utils.h
@@ -67,6 +67,14 @@ extern const double kImpossibleValue; +// array contains a list of (possibly repeating) non-negative +// integers. Let us assume that we have constructed another array `p` +// by sorting and uniquing the entries of array. +// +// MapValuesToContiguousRange replaces each entry in "array" with its +// position in `p`. +void MapValuesToContiguousRange(int size, int* array); + } // namespace internal } // namespace ceres
diff --git a/internal/ceres/array_utils_test.cc b/internal/ceres/array_utils_test.cc index 96e625d..203a301 100644 --- a/internal/ceres/array_utils_test.cc +++ b/internal/ceres/array_utils_test.cc
@@ -32,6 +32,7 @@ #include <limits> #include <cmath> +#include <vector> #include "gtest/gtest.h" namespace ceres { @@ -71,5 +72,51 @@ EXPECT_EQ(FindInvalidValue(3, x), 0); } +TEST(MapValuesToContiguousRange, ContiguousEntries) { + vector<int> array; + array.push_back(0); + array.push_back(1); + vector<int> expected = array; + MapValuesToContiguousRange(array.size(), &array[0]); + EXPECT_EQ(array, expected); + array.clear(); + + array.push_back(1); + array.push_back(0); + expected = array; + MapValuesToContiguousRange(array.size(), &array[0]); + EXPECT_EQ(array, expected); +} + +TEST(MapValuesToContiguousRange, NonContiguousEntries) { + vector<int> array; + array.push_back(0); + array.push_back(2); + vector<int> expected; + expected.push_back(0); + expected.push_back(1); + MapValuesToContiguousRange(array.size(), &array[0]); + EXPECT_EQ(array, expected); +} + +TEST(MapValuesToContiguousRange, NonContiguousRepeatingEntries) { + vector<int> array; + array.push_back(3); + array.push_back(1); + array.push_back(0); + array.push_back(0); + array.push_back(0); + array.push_back(5); + vector<int> expected; + expected.push_back(2); + expected.push_back(1); + expected.push_back(0); + expected.push_back(0); + expected.push_back(0); + expected.push_back(3); + MapValuesToContiguousRange(array.size(), &array[0]); + EXPECT_EQ(array, expected); +} + } // namespace internal } // namespace ceres
diff --git a/internal/ceres/solver_impl.cc b/internal/ceres/solver_impl.cc index 2bf6cd2..fbcaf6b 100644 --- a/internal/ceres/solver_impl.cc +++ b/internal/ceres/solver_impl.cc
@@ -34,6 +34,7 @@ #include <iostream> // NOLINT #include <numeric> #include <string> +#include "ceres/array_utils.h" #include "ceres/coordinate_descent_minimizer.h" #include "ceres/cxsparse.h" #include "ceres/evaluator.h" @@ -1707,7 +1708,7 @@ // Renumber the entries of constraints to be contiguous integers // as camd requires that the group ids be in the range [0, // parameter_blocks.size() - 1]. - SolverImpl::CompactifyArray(&constraints); + MapValuesToContiguousRange(constraints.size(), &constraints[0]); // Set the offsets and index for CreateJacobianSparsityTranspose. program->SetParameterOffsetsAndIndex(); @@ -1832,20 +1833,5 @@ return true; } -void SolverImpl::CompactifyArray(vector<int>* array_ptr) { - vector<int>& array = *array_ptr; - const set<int> unique_group_ids(array.begin(), array.end()); - map<int, int> group_id_map; - for (set<int>::const_iterator it = unique_group_ids.begin(); - it != unique_group_ids.end(); - ++it) { - InsertOrDie(&group_id_map, *it, group_id_map.size()); - } - - for (int i = 0; i < array.size(); ++i) { - array[i] = group_id_map[array[i]]; - } -} - } // namespace internal } // namespace ceres
diff --git a/internal/ceres/solver_impl.h b/internal/ceres/solver_impl.h index 631add5..0085898 100644 --- a/internal/ceres/solver_impl.h +++ b/internal/ceres/solver_impl.h
@@ -213,13 +213,6 @@ ParameterBlockOrdering* parameter_block_ordering, Program* program, string* message); - - // array contains a list of (possibly repeating) non-negative - // integers. Let us assume that we have constructed another array - // `p` by sorting and uniqueing the entries of array. - // CompactifyArray replaces each entry in "array" with its position - // in `p`. - static void CompactifyArray(vector<int>* array); }; } // namespace internal
diff --git a/internal/ceres/solver_impl_test.cc b/internal/ceres/solver_impl_test.cc index c2f8c22..1f15628 100644 --- a/internal/ceres/solver_impl_test.cc +++ b/internal/ceres/solver_impl_test.cc
@@ -1038,53 +1038,6 @@ EXPECT_EQ((expected_dense_jacobian - actual_dense_jacobian).norm(), 0.0); } -TEST(CompactifyArray, ContiguousEntries) { - vector<int> array; - array.push_back(0); - array.push_back(1); - vector<int> expected = array; - SolverImpl::CompactifyArray(&array); - EXPECT_EQ(array, expected); - array.clear(); - - array.push_back(1); - array.push_back(0); - expected = array; - SolverImpl::CompactifyArray(&array); - EXPECT_EQ(array, expected); -} - -TEST(CompactifyArray, NonContiguousEntries) { - vector<int> array; - array.push_back(0); - array.push_back(2); - vector<int> expected; - expected.push_back(0); - expected.push_back(1); - SolverImpl::CompactifyArray(&array); - EXPECT_EQ(array, expected); -} - -TEST(CompactifyArray, NonContiguousRepeatingEntries) { - vector<int> array; - array.push_back(3); - array.push_back(1); - array.push_back(0); - array.push_back(0); - array.push_back(0); - array.push_back(5); - vector<int> expected; - expected.push_back(2); - expected.push_back(1); - expected.push_back(0); - expected.push_back(0); - expected.push_back(0); - expected.push_back(3); - - SolverImpl::CompactifyArray(&array); - EXPECT_EQ(array, expected); -} - TEST(SolverImpl, ProblemHasNanParameterBlocks) { Problem problem; double x[2];