Tatooine
index_order.h
Go to the documentation of this file.
1#ifndef TATOOINE_INDEX_ORDER_H
2#define TATOOINE_INDEX_ORDER_H
3//==============================================================================
4#include <tatooine/concepts.h>
6#include <tatooine/utility.h>
7
8#include <array>
9#include <boost/range/adaptor/reversed.hpp>
10#include <numeric>
11#include <vector>
12//==============================================================================
13namespace tatooine {
14//==============================================================================
17struct x_fastest {
18 template <std::forward_iterator Iterator>
19 static constexpr auto plain_index(Iterator resolution_it,
20 integral auto const... is) {
21 using int_t = typename std::iterator_traits<Iterator>::value_type;
22 auto multiplier = int_t(1);
23 auto idx = int_t(0);
24 auto it = [&](int_t const i) {
25 idx += i * multiplier;
26 multiplier *= *(resolution_it++);
27 };
28 for_each(it, static_cast<int_t>(is)...);
29 return idx;
30 }
31 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
32 template <std::forward_iterator Iterator>
33 static constexpr auto plain_index(Iterator resolution_it,
34 integral_range auto const& is) {
35 using int_t = typename std::iterator_traits<Iterator>::value_type;
36 auto multiplier = int_t(1);
37 auto idx = int_t(0);
38 for (auto const i : is) {
39 idx += static_cast<int_t>(i) * multiplier;
40 multiplier *= *(resolution_it++);
41 }
42 return idx;
43 }
44 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
45 static constexpr auto plain_index(integral_range auto const& resolution,
46 integral auto const... is) {
47 return plain_index(begin(resolution), is...);
48 }
49 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
50 static constexpr auto plain_index(integral_range auto const& resolution,
51 integral_range auto const& indices) {
52 assert(resolution.size() == indices.size());
53 return plain_index(begin(resolution), indices);
54 }
55 //----------------------------------------------------------------------------
56 template <integral_range Resolution>
57 static auto multi_index(Resolution const& resolution,
58 integral auto plain_index) {
59 using int_t = std::ranges::range_value_t<Resolution>;
60 auto is = std::vector<int_t>(resolution.size());
61 auto multiplier = std::accumulate(std::ranges::begin(resolution), std::ranges::prev(end(resolution)),
62 int_t(1), std::multiplies<int_t>{});
63
64 auto resolution_it = std::ranges::prev(end(resolution), 2);
65 for (std::size_t j = 0; j < resolution.size(); ++j, --resolution_it) {
66 auto i = resolution.size() - 1 - j;
67 is[i] = plain_index / multiplier;
68 plain_index -= is[i] * multiplier;
69 if (resolution_it >= begin(resolution)) {
70 multiplier /= *resolution_it;
71 }
72 }
73 return is;
74 }
75};
76//==============================================================================
79struct x_slowest {
80 private:
81 static constexpr auto internal_plain_index(
82 std::forward_iterator auto resolution_it, range auto const& is)
83 -> std::size_t {
84 auto multiplier = std::size_t(1);
85 auto idx = std::size_t(0);
86
87 for (auto i : is | boost::adaptors::reversed) {
88 idx += i * multiplier;
89 multiplier *= *(resolution_it--);
90 }
91 return idx;
92 }
93 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
94 static constexpr auto internal_plain_index(range auto const& resolution,
95 integral auto const... p_is)
96 -> std::size_t {
97 std::array is{p_is...};
98
99 std::size_t multiplier = 1;
100 std::size_t idx = 0;
101
102 for (std::size_t i = 0; i < size(is); ++i) {
103 idx += is[is.size() - 1 - i] * multiplier;
104 // idx += is[i] * multiplier;
105 multiplier *= resolution[is.size() - 1 - i];
106 }
107 return idx;
108 }
109
110 public:
111 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
112 static constexpr auto plain_index(range auto const& resolution,
113 integral auto const... is) -> std::size_t {
114 assert(sizeof...(is) == resolution.size());
115 return internal_plain_index(resolution, is...);
116 }
117 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
118 static auto plain_index(range auto const& resolution, range auto const& is)
119 -> std::size_t {
120 assert(is.size() == resolution.size());
121 return internal_plain_index(prev(end(resolution)), is);
122 }
123 //----------------------------------------------------------------------------
124 static auto multi_index(range auto const& resolution, std::size_t plain_index) {
125 auto is = std::vector<std::size_t> (resolution.size());
126 std::size_t multiplier = 1;
127
128 auto resolution_it = prev(end(resolution));
129 auto is_it = prev(end(is));
130 for (; resolution_it != begin(resolution); --resolution_it, --is_it) {
131 *is_it = plain_index * multiplier;
132 plain_index -= *is_it;
133 multiplier *= *resolution_it;
134 }
135 return is;
136 }
137};
138template <typename T>
139concept index_order = std::same_as<T, x_fastest> || std::same_as<T, x_slowest>;
140//==============================================================================
141} // namespace tatooine
142//==============================================================================
143#endif
Definition: index_order.h:139
Definition: concepts.h:91
Definition: concepts.h:21
Definition: concepts.h:84
Definition: algorithm.h:6
auto begin(Range &&range)
Definition: iterator_facade.h:318
auto end(Range &&range)
Definition: iterator_facade.h:322
auto size(vec< ValueType, N > const &v)
Definition: vec.h:148
constexpr void for_each(F &&f, Ts &&... ts)
Definition: utility.h:39
auto prev(Iter iter)
Definition: iterator_facade.h:343
Definition: index_order.h:17
static auto multi_index(Resolution const &resolution, integral auto plain_index)
Definition: index_order.h:57
static constexpr auto plain_index(integral_range auto const &resolution, integral_range auto const &indices)
Definition: index_order.h:50
static constexpr auto plain_index(Iterator resolution_it, integral auto const ... is)
Definition: index_order.h:19
static constexpr auto plain_index(Iterator resolution_it, integral_range auto const &is)
Definition: index_order.h:33
static constexpr auto plain_index(integral_range auto const &resolution, integral auto const ... is)
Definition: index_order.h:45
Definition: index_order.h:79
static auto multi_index(range auto const &resolution, std::size_t plain_index)
Definition: index_order.h:124
static constexpr auto internal_plain_index(std::forward_iterator auto resolution_it, range auto const &is) -> std::size_t
Definition: index_order.h:81
static constexpr auto plain_index(range auto const &resolution, integral auto const ... is) -> std::size_t
Definition: index_order.h:112
static auto plain_index(range auto const &resolution, range auto const &is) -> std::size_t
Definition: index_order.h:118
static constexpr auto internal_plain_index(range auto const &resolution, integral auto const ... p_is) -> std::size_t
Definition: index_order.h:94