WeightedLowess
A C++ library for LOWESS with various weighting schemes
Loading...
Searching...
No Matches
SortBy.hpp
Go to the documentation of this file.
1#ifndef WEIGHTEDLOWESS_SORTBY_HPP
2#define WEIGHTEDLOWESS_SORTBY_HPP
3
4#include <algorithm>
5#include <numeric>
6#include <vector>
7#include <cstdint>
8#include <type_traits>
9#include <initializer_list>
10#include <cstddef>
11
12#include "sanisizer/sanisizer.hpp"
13
14#include "utils.hpp"
15
21namespace WeightedLowess {
22
32class SortBy {
33private:
34 std::vector<std::size_t> my_permutation;
35 bool my_sorted = true;
36
37public:
43 template<typename Sortable_>
44 SortBy(const std::size_t num_points, const Sortable_* x) {
45 set(num_points, x);
46 }
47
52 SortBy() = default;
53
59 template<typename Sortable_>
60 void set(const std::size_t num_points, const Sortable_* x) {
61 if (num_points) {
62 my_sorted = std::is_sorted(x, x + num_points);
63 if (!my_sorted) {
64 sanisizer::resize(my_permutation, num_points);
65 std::iota(my_permutation.begin(), my_permutation.end(), static_cast<std::size_t>(0));
66 std::sort(my_permutation.begin(), my_permutation.end(), [&](std::size_t left, std::size_t right) -> bool { return x[left] < x[right]; });
67 }
68 }
69 }
70
71private:
72 template<typename AllData_, typename Used_>
73 void permute_raw(AllData_& data, Used_* work) const {
74 if (my_sorted) {
75 return;
76 }
77
78 const auto num_points = my_permutation.size();
79 std::fill_n(work, num_points, 0);
80
81 // Reordering values in place.
82 for (decltype(internal::I(num_points)) i = 0; i < num_points; ++i) {
83 if (work[i]) {
84 continue;
85 }
86 work[i] = 1;
87
88 std::size_t current = i, replacement = my_permutation[i];
89 while (replacement != i) {
90 if constexpr(std::is_pointer<AllData_>::value) {
91 std::swap(data[current], data[replacement]);
92 } else {
93 for (auto d : data) {
94 std::swap(d[current], d[replacement]);
95 }
96 }
97 current = replacement;
98 work[replacement] = 1;
99 replacement = my_permutation[replacement];
100 }
101 }
102 }
103
104public:
113 template<typename Data_, typename Used_>
114 void permute(Data_* data, Used_* work) const {
115 permute_raw(data, work);
116 }
117
126 template<typename Data_, typename Used_>
127 void permute(std::initializer_list<Data_> data, Used_* work) const {
128 permute_raw(data, work);
129 }
130
139 template<typename DataPointers_, typename Used_>
140 void permute(DataPointers_ data, Used_* work) const {
141 permute_raw(data, work);
142 }
143
152 template<typename Data_, typename Used_>
153 void permute(Data_* data, std::vector<Used_>& work) const {
154 const auto num_points = my_permutation.size();
155 sanisizer::resize(work, num_points);
156 permute(data, work.data());
157 }
158
167 template<typename Data_, typename Used_>
168 void permute(std::initializer_list<Data_> data, std::vector<Used_>& work) const {
169 const auto num_points = my_permutation.size();
170 sanisizer::resize(work, num_points);
171 permute(data, work.data());
172 }
173
182 template<typename DataPointers_, typename Used_>
183 void permute(DataPointers_ data, std::vector<Used_>& work) const {
184 const auto num_points = my_permutation.size();
185 sanisizer::resize(work, num_points);
186 permute(data, work.data());
187 }
188
189private:
190 template<typename AllData_, typename Used_>
191 void unpermute_raw(AllData_& data, Used_* work) const {
192 if (my_sorted) {
193 return;
194 }
195
196 const auto num_points = my_permutation.size();
197 std::fill_n(work, num_points, 0);
198
199 for (decltype(internal::I(num_points)) i = 0; i < num_points; ++i) {
200 if (work[i]) {
201 continue;
202 }
203 work[i] = 1;
204
205 auto replacement = my_permutation[i];
206 while (replacement != i) {
207 if constexpr(std::is_pointer<AllData_>::value) {
208 std::swap(data[i], data[replacement]);
209 } else {
210 for (auto d : data) {
211 std::swap(d[i], d[replacement]);
212 }
213 }
214 work[replacement] = 1;
215 replacement = my_permutation[replacement];
216 }
217 }
218 }
219
220public:
228 template<typename Data_, typename Used_>
229 void unpermute(Data_* data, Used_* work) const {
230 unpermute_raw(data, work);
231 }
232
240 template<typename Data_, typename Used_>
241 void unpermute(std::initializer_list<Data_*> data, Used_* work) const {
242 unpermute_raw(data, work);
243 }
244
252 template<typename DataPointers_, typename Used_>
253 void unpermute(DataPointers_ data, Used_* work) const {
254 unpermute_raw(data, work);
255 }
256
264 template<typename Data_, typename Used_>
265 void unpermute(Data_* data, std::vector<Used_>& work) const {
266 const auto num_points = my_permutation.size();
267 sanisizer::resize(work, num_points);
268 unpermute(data, work.data());
269 }
270
278 template<typename Data_, typename Used_>
279 void unpermute(std::initializer_list<Data_*> data, std::vector<Used_>& work) const {
280 const auto num_points = my_permutation.size();
281 sanisizer::resize(work, num_points);
282 unpermute(data, work.data());
283 }
284
292 template<typename DataPointers_, typename Used_>
293 void unpermute(DataPointers_ data, std::vector<Used_>& work) const {
294 const auto num_points = my_permutation.size();
295 sanisizer::resize(work, num_points);
296 unpermute(data, work.data());
297 }
298};
299
300}
301
302#endif
Utility class for sorting on a covariate.
Definition SortBy.hpp:32
void unpermute(Data_ *data, std::vector< Used_ > &work) const
Definition SortBy.hpp:265
void unpermute(Data_ *data, Used_ *work) const
Definition SortBy.hpp:229
void unpermute(std::initializer_list< Data_ * > data, std::vector< Used_ > &work) const
Definition SortBy.hpp:279
void unpermute(DataPointers_ data, Used_ *work) const
Definition SortBy.hpp:253
void permute(std::initializer_list< Data_ > data, std::vector< Used_ > &work) const
Definition SortBy.hpp:168
void permute(std::initializer_list< Data_ > data, Used_ *work) const
Definition SortBy.hpp:127
void unpermute(std::initializer_list< Data_ * > data, Used_ *work) const
Definition SortBy.hpp:241
void permute(Data_ *data, std::vector< Used_ > &work) const
Definition SortBy.hpp:153
void permute(DataPointers_ data, std::vector< Used_ > &work) const
Definition SortBy.hpp:183
void set(const std::size_t num_points, const Sortable_ *x)
Definition SortBy.hpp:60
void permute(DataPointers_ data, Used_ *work) const
Definition SortBy.hpp:140
void permute(Data_ *data, Used_ *work) const
Definition SortBy.hpp:114
void unpermute(DataPointers_ data, std::vector< Used_ > &work) const
Definition SortBy.hpp:293
SortBy(const std::size_t num_points, const Sortable_ *x)
Definition SortBy.hpp:44
Namespace for LOWESS functions.
Definition compute.hpp:18