Line | Branch | Exec | Source |
---|---|---|---|
1 | // This file is part of INSTINCT, the INS Toolkit for Integrated | ||
2 | // Navigation Concepts and Training by the Institute of Navigation of | ||
3 | // the University of Stuttgart, Germany. | ||
4 | // | ||
5 | // This Source Code Form is subject to the terms of the Mozilla Public | ||
6 | // License, v. 2.0. If a copy of the MPL was not distributed with this | ||
7 | // file, You can obtain one at https://mozilla.org/MPL/2.0/. | ||
8 | |||
9 | /// @file Sort.hpp | ||
10 | /// @brief Sorting algorithms | ||
11 | /// @author T. Topp (topp@ins.uni-stuttgart.de) | ||
12 | /// @date 2023-09-15 | ||
13 | |||
14 | #pragma once | ||
15 | |||
16 | #include <vector> | ||
17 | #include <algorithm> | ||
18 | #include <numeric> | ||
19 | #include "util/Eigen.hpp" | ||
20 | |||
21 | namespace NAV | ||
22 | { | ||
23 | |||
24 | /// @brief Gives the permutation to sort the std::vector | ||
25 | /// @param vec Vector to get the sorting permutation for | ||
26 | /// @param compare Comparison operator | ||
27 | /// @return Permutation vector | ||
28 | /// @note Taken from https://stackoverflow.com/a/17074810 | ||
29 | template<typename T, typename Compare> | ||
30 | 1 | std::vector<size_t> sort_permutation(const std::vector<T>& vec, Compare compare) | |
31 | { | ||
32 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | std::vector<size_t> p(vec.size()); |
33 | 1 | std::iota(p.begin(), p.end(), 0); // NOLINT(boost-use-ranges,modernize-use-ranges) // ranges::iota is C++23 and not supported yet | |
34 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
11 | std::ranges::sort(p, [&](size_t i, size_t j) { return compare(vec[i], vec[j]); }); |
35 | 1 | return p; | |
36 | ✗ | } | |
37 | |||
38 | /// @brief Gives the permutation to sort the vector | ||
39 | /// @param vec Vector to get the sorting permutation for | ||
40 | /// @param compare Comparison operator | ||
41 | /// @return Permutation vector | ||
42 | /// @note Taken from https://stackoverflow.com/a/17074810, adapted for Eigen | ||
43 | template<typename Derived, typename Compare> | ||
44 | 1 | std::vector<size_t> sort_permutation(const Eigen::MatrixBase<Derived>& vec, Compare compare) | |
45 | { | ||
46 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | std::vector<size_t> p(static_cast<size_t>(vec.rows())); |
47 | 1 | std::iota(p.begin(), p.end(), 0); // NOLINT(boost-use-ranges,modernize-use-ranges) // ranges::iota is C++23 and not supported yet | |
48 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
11 | std::ranges::sort(p, [&](size_t i, size_t j) { return compare(vec(static_cast<Eigen::Index>(i)), vec(static_cast<Eigen::Index>(j))); }); |
49 | 1 | return p; | |
50 | ✗ | } | |
51 | |||
52 | /// @brief Sort a std::vector with a permutation | ||
53 | /// @param vec Vector to sort | ||
54 | /// @param p Permutation to sort by | ||
55 | /// @return Sorted vector | ||
56 | /// @note Taken from https://stackoverflow.com/a/17074810 | ||
57 | template<typename T> | ||
58 | 2 | std::vector<T> apply_permutation(const std::vector<T>& vec, const std::vector<size_t>& p) | |
59 | { | ||
60 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | std::vector<T> sorted_vec(vec.size()); |
61 | 2 | std::transform(p.begin(), p.end(), sorted_vec.begin(), | |
62 | 10 | [&](size_t i) { return vec[i]; }); | |
63 | 2 | return sorted_vec; | |
64 | } | ||
65 | |||
66 | /// @brief Sort a vector with a permutation | ||
67 | /// @param vec Vector to sort | ||
68 | /// @param p Permutation to sort by | ||
69 | /// @return Sorted vector | ||
70 | /// @note Taken from https://stackoverflow.com/a/17074810, adapted for Eigen | ||
71 | template<typename Scalar, int Size> | ||
72 | 1 | Eigen::Vector<Scalar, Size> apply_permutation(const Eigen::Vector<Scalar, Size>& vec, const std::vector<size_t>& p) | |
73 | { | ||
74 | 1 | Eigen::Vector<Scalar, Size> sorted = vec; | |
75 |
1/2✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | std::transform(p.begin(), p.end(), sorted.begin(), |
76 | 5 | [&](size_t i) { return vec(static_cast<Eigen::Index>(i)); }); | |
77 | 1 | return sorted; | |
78 | ✗ | } | |
79 | |||
80 | /// @brief Sort a matrix row-wise with a permutation | ||
81 | /// @param m Matrix to sort | ||
82 | /// @param p Permutation to sort by | ||
83 | /// @return Sorted matrix | ||
84 | /// @note Taken from https://stackoverflow.com/a/17074810, adapted for Eigen | ||
85 | template<typename Derived> | ||
86 | 1 | typename Derived::PlainObject apply_permutation_rowwise(const Eigen::MatrixBase<Derived>& m, const std::vector<size_t>& p) | |
87 | { | ||
88 | 1 | typename Derived::PlainObject sorted = m; | |
89 |
3/6✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
|
1 | std::transform(p.begin(), p.end(), sorted.rowwise().begin(), |
90 | 5 | [&](size_t i) { return m.row(static_cast<Eigen::Index>(i)); }); | |
91 | 1 | return sorted; | |
92 | ✗ | } | |
93 | |||
94 | /// @brief Sort a matrix col-wise with a permutation | ||
95 | /// @param m Matrix to sort | ||
96 | /// @param p Permutation to sort by | ||
97 | /// @return Sorted matrix | ||
98 | /// @note Taken from https://stackoverflow.com/a/17074810, adapted for Eigen | ||
99 | template<typename Derived> | ||
100 | 1 | typename Derived::PlainObject apply_permutation_colwise(const Eigen::MatrixBase<Derived>& m, const std::vector<size_t>& p) | |
101 | { | ||
102 | 1 | typename Derived::PlainObject sorted = m; | |
103 |
3/6✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
|
1 | std::transform(p.begin(), p.end(), sorted.colwise().begin(), |
104 | 5 | [&](size_t i) { return m.col(static_cast<Eigen::Index>(i)); }); | |
105 | 1 | return sorted; | |
106 | ✗ | } | |
107 | |||
108 | /// @brief Sort a std::vector with a permutation | ||
109 | /// @param vec Vector to sort | ||
110 | /// @param p Permutation to sort by | ||
111 | template<typename T> | ||
112 | 2 | void apply_permutation_in_place(std::vector<T>& vec, const std::vector<size_t>& p) | |
113 | { | ||
114 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | std::vector<bool> done(p.size()); |
115 |
2/2✓ Branch 1 taken 10 times.
✓ Branch 2 taken 2 times.
|
12 | for (size_t i = 0; i < p.size(); ++i) |
116 | { | ||
117 |
3/4✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8 times.
✓ Branch 5 taken 2 times.
|
10 | if (done[i]) |
118 | { | ||
119 | 8 | continue; | |
120 | } | ||
121 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | done[i] = true; |
122 | 2 | size_t prev_j = i; | |
123 | 2 | size_t j = p[i]; | |
124 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2 times.
|
10 | while (i != j) |
125 | { | ||
126 | 8 | std::swap(vec[prev_j], vec[j]); | |
127 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | done[j] = true; |
128 | 8 | prev_j = j; | |
129 | 8 | j = p[j]; | |
130 | } | ||
131 | } | ||
132 | 2 | } | |
133 | |||
134 | /// @brief Sort a vector with a permutation | ||
135 | /// @param vec Vector to sort | ||
136 | /// @param p Permutation to sort by | ||
137 | /// @note Taken from https://stackoverflow.com/a/17074810 | ||
138 | template<typename Scalar, int Size> | ||
139 | 1 | void apply_permutation_in_place(Eigen::Vector<Scalar, Size>& vec, const std::vector<size_t>& p) | |
140 | { | ||
141 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | std::vector<bool> done(p.size()); |
142 |
2/2✓ Branch 1 taken 5 times.
✓ Branch 2 taken 1 times.
|
6 | for (size_t i = 0; i < p.size(); ++i) |
143 | { | ||
144 |
3/4✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 1 times.
|
5 | if (done[i]) |
145 | { | ||
146 | 4 | continue; | |
147 | } | ||
148 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | done[i] = true; |
149 | 1 | size_t prev_j = i; | |
150 | 1 | size_t j = p[i]; | |
151 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
|
5 | while (i != j) |
152 | { | ||
153 |
2/4✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
|
4 | std::swap(vec(static_cast<Eigen::Index>(prev_j)), vec(static_cast<Eigen::Index>(j))); |
154 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | done[j] = true; |
155 | 4 | prev_j = j; | |
156 | 4 | j = p[j]; | |
157 | } | ||
158 | } | ||
159 | 1 | } | |
160 | |||
161 | /// @brief Sort a matrix row-wise with a permutation | ||
162 | /// @param m Matrix to sort | ||
163 | /// @param p Permutation to sort by | ||
164 | /// @note Taken from https://stackoverflow.com/a/17074810 | ||
165 | template<typename Scalar, int Rows, int Cols> | ||
166 | 1 | void apply_permutation_rowwise_in_place(Eigen::Matrix<Scalar, Rows, Cols>& m, const std::vector<size_t>& p) | |
167 | { | ||
168 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | std::vector<bool> done(p.size()); |
169 |
2/2✓ Branch 1 taken 5 times.
✓ Branch 2 taken 1 times.
|
6 | for (size_t i = 0; i < p.size(); ++i) |
170 | { | ||
171 |
3/4✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 1 times.
|
5 | if (done[i]) |
172 | { | ||
173 | 4 | continue; | |
174 | } | ||
175 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | done[i] = true; |
176 | 1 | size_t prev_j = i; | |
177 | 1 | size_t j = p[i]; | |
178 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
|
5 | while (i != j) |
179 | { | ||
180 |
3/6✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 8 not taken.
|
4 | m.row(static_cast<Eigen::Index>(prev_j)).swap(m.row(static_cast<Eigen::Index>(j))); |
181 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | done[j] = true; |
182 | 4 | prev_j = j; | |
183 | 4 | j = p[j]; | |
184 | } | ||
185 | } | ||
186 | 1 | } | |
187 | |||
188 | /// @brief Sort a matrix col-wise with a permutation | ||
189 | /// @param m Matrix to sort | ||
190 | /// @param p Permutation to sort by | ||
191 | /// @note Taken from https://stackoverflow.com/a/17074810 | ||
192 | template<typename Scalar, int Rows, int Cols> | ||
193 | 1 | void apply_permutation_colwise_in_place(Eigen::Matrix<Scalar, Rows, Cols>& m, const std::vector<size_t>& p) | |
194 | { | ||
195 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | std::vector<bool> done(p.size()); |
196 |
2/2✓ Branch 1 taken 5 times.
✓ Branch 2 taken 1 times.
|
6 | for (size_t i = 0; i < p.size(); ++i) |
197 | { | ||
198 |
3/4✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 1 times.
|
5 | if (done[i]) |
199 | { | ||
200 | 4 | continue; | |
201 | } | ||
202 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | done[i] = true; |
203 | 1 | size_t prev_j = i; | |
204 | 1 | size_t j = p[i]; | |
205 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
|
5 | while (i != j) |
206 | { | ||
207 |
3/6✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 8 not taken.
|
4 | m.col(static_cast<Eigen::Index>(prev_j)).swap(m.col(static_cast<Eigen::Index>(j))); |
208 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | done[j] = true; |
209 | 4 | prev_j = j; | |
210 | 4 | j = p[j]; | |
211 | } | ||
212 | } | ||
213 | 1 | } | |
214 | |||
215 | } // namespace NAV | ||
216 |