TMB Documentation  v1.9.11
radix.hpp
1 #ifndef HAVE_RADIX_HPP
2 #define HAVE_RADIX_HPP
3 // Autogenerated - do not edit by hand !
4 #include <algorithm>
5 #include <vector>
6 
8 namespace radix {
9 
15 template <class T, class I>
16 struct radix {
18  const std::vector<T>& x;
20  std::vector<T> x_sort;
22  std::vector<I> x_order;
24  static const int radix_width = 8;
26  static const int total_width = sizeof(T) * 8;
28  static const int num_keys = (1 << radix_width);
30  static const int mask = num_keys - 1;
31  size_t key(T x, int k) { return (x >> k) & mask; }
32 
33  radix(const std::vector<T>& x) : x(x) {
34  static_assert(T(-1) > T(0), "Value type must be unsigned");
35  static_assert(total_width % radix_width == 0,
36  "Value width must be a multiple of radix width");
37  }
38  template <bool get_order>
39  void run_sort() {
40  T bitwise_min = ~0, bitwise_max = 0;
41  for (size_t i = 0; i < x.size(); i++) {
42  bitwise_min &= x[i];
43  bitwise_max |= x[i];
44  }
45 
46  x_sort = x;
47  x_order.resize(x.size() * get_order);
48  for (size_t i = 0; i < x_order.size(); i++) x_order[i] = i;
49 
50  std::vector<size_t> count(num_keys);
51  std::vector<size_t> pos(num_keys);
52 
53  std::vector<I> y_order(x.size() * get_order);
54  std::vector<T> y_sort(x.size());
55  for (size_t k = 0; k < total_width; k += radix_width) {
56  if (key(bitwise_min, k) == key(bitwise_max, k)) continue;
57 
58  std::fill(count.begin(), count.end(), 0);
59  for (size_t i = 0; i < x.size(); i++) {
60  count[key(x[i], k)]++;
61  }
62 
63  std::fill(pos.begin(), pos.end(), 0);
64  for (size_t i = 1; i < pos.size(); i++) {
65  pos[i] = pos[i - 1] + count[i - 1];
66  }
67  for (size_t i = 0; i < x.size(); i++) {
68  T x_sort_i = x_sort[i];
69  size_t& j = pos[key(x_sort_i, k)];
70 
71  y_sort[j] = x_sort_i;
72  if (get_order) y_order[j] = x_order[i];
73  j++;
74  }
75  std::swap(x_sort, y_sort);
76  std::swap(x_order, y_order);
77  }
78  }
79  std::vector<T> sort() {
80  run_sort<false>();
81  return x_sort;
82  }
83  std::vector<I> order() {
84  run_sort<true>();
85  return x_order;
86  }
87  std::vector<I> first_occurance() {
88  run_sort<true>();
89  std::vector<I> ans(x_order.size());
90  for (size_t i = 0; i < ans.size(); i++) ans[i] = i;
91  for (size_t i = 1; i < x_sort.size(); i++) {
92  if (x_sort[i - 1] == x_sort[i]) {
93  ans[x_order[i]] = ans[x_order[i - 1]];
94  }
95  }
96  return ans;
97  }
98 };
99 
100 template <class I, class T>
101 std::vector<I> order(const std::vector<T>& x) {
102  return radix<T, I>(x).order();
103 }
104 
107 template <class I, class T>
108 std::vector<I> first_occurance(const std::vector<T>& x) {
109  return radix<T, I>(x).first_occurance();
110 }
111 
115 template <class I, class T>
116 std::vector<I> factor(const std::vector<T>& x) {
117  std::vector<I> y = first_occurance<I>(x);
118  std::vector<I> tab(y.size());
119  for (size_t i = 0, k = 0; i < y.size(); i++) {
120  if (y[i] == i)
121  tab[i] = k++;
122  else
123  tab[i] = tab[y[i]];
124  }
125  return tab;
126 }
127 
128 } // namespace radix
129 #endif // HAVE_RADIX_HPP
Radix based sorting and first_occurance.
Definition: radix.hpp:8
std::vector< T > x_sort
Output: sort(x)
Definition: radix.hpp:20
const std::vector< T > & x
Reference to the input vector.
Definition: radix.hpp:18
Simple radix sort implementation.
Definition: radix.hpp:16
std::vector< I > factor(const std::vector< T > &x)
Replace each element in a vector by an integer code such that x[i] == x[j] implies f[i] == f[j] ...
Definition: radix.hpp:116
std::vector< I > first_occurance(const std::vector< T > &x)
For each element of a vector find the index of its first occurance from the left. ...
Definition: radix.hpp:108
std::vector< I > x_order
Output: order(x) permutation.
Definition: radix.hpp:22
License: GPL v2