Wayverb
compile_time.h
1 #pragma once
2 
3 #include <tuple>
4 #include <algorithm>
5 
6 namespace {
7 // std::ostream& operator<<(std::ostream& os, const index& i) {
8 // return os << "[" << i.x << ", " << i.y << ", " << i.z << "]";
9 //}
10 
11 template <typename T>
12 struct locator final {
13  T x, y, z;
14 };
15 
16 template <typename T>
17 constexpr auto to_tuple(const locator<T>& a) {
18  return std::tie(a.x, a.y, a.z);
19 }
20 
21 template <typename T>
22 constexpr bool operator==(const locator<T>& a, const locator<T>& b) {
23  return to_tuple(a) == to_tuple(b);
24 }
25 
26 template <typename T>
27 constexpr bool operator!=(const locator<T>& a, const locator<T>& b) {
28  return !(a == b);
29 }
30 
31 constexpr size_t triangle(size_t i) { return (i * (i + 1)) / 2; }
32 
33 static_assert(triangle(0) == 0, "triangle");
34 static_assert(triangle(1) == 1, "triangle");
35 static_assert(triangle(2) == 3, "triangle");
36 static_assert(triangle(3) == 6, "triangle");
37 static_assert(triangle(4) == 10, "triangle");
38 static_assert(triangle(5) == 15, "triangle");
39 
40 constexpr size_t tetrahedron(size_t i) { return (i * (i + 1) * (i + 2)) / 6; }
41 
42 static_assert(tetrahedron(0) == 0, "tetrahdedron");
43 static_assert(tetrahedron(1) == 1, "tetrahdedron");
44 static_assert(tetrahedron(2) == 4, "tetrahdedron");
45 static_assert(tetrahedron(3) == 10, "tetrahdedron");
46 static_assert(tetrahedron(4) == 20, "tetrahdedron");
47 static_assert(tetrahedron(5) == 35, "tetrahdedron");
48 
49 constexpr locator<size_t> to_locator(size_t ind) {
50  auto x = 0u;
51  for (auto i = 1u;; ++i) {
52  auto tri = triangle(i);
53  if (ind < tri) {
54  x = i - 1;
55  break;
56  }
57  ind -= tri;
58  }
59 
60  auto y = 0u;
61  for (auto i = 1u;; ++i) {
62  if (ind < i) {
63  y = i - 1;
64  break;
65  }
66  ind -= i;
67  }
68 
69  auto z = ind;
70 
71  return locator<size_t>{x, y, z};
72 }
73 
74 static_assert(to_locator(0) == locator<size_t>{0, 0, 0}, "to_locator");
75 
76 static_assert(to_locator(1) == locator<size_t>{1, 0, 0}, "to_locator");
77 static_assert(to_locator(2) == locator<size_t>{1, 1, 0}, "to_locator");
78 static_assert(to_locator(3) == locator<size_t>{1, 1, 1}, "to_locator");
79 
80 static_assert(to_locator(4) == locator<size_t>{2, 0, 0}, "to_locator");
81 static_assert(to_locator(5) == locator<size_t>{2, 1, 0}, "to_locator");
82 static_assert(to_locator(6) == locator<size_t>{2, 1, 1}, "to_locator");
83 static_assert(to_locator(7) == locator<size_t>{2, 2, 0}, "to_locator");
84 static_assert(to_locator(8) == locator<size_t>{2, 2, 1}, "to_locator");
85 static_assert(to_locator(9) == locator<size_t>{2, 2, 2}, "to_locator");
86 
87 static_assert(to_locator(10) == locator<size_t>{3, 0, 0}, "to_locator");
88 static_assert(to_locator(11) == locator<size_t>{3, 1, 0}, "to_locator");
89 static_assert(to_locator(12) == locator<size_t>{3, 1, 1}, "to_locator");
90 static_assert(to_locator(13) == locator<size_t>{3, 2, 0}, "to_locator");
91 static_assert(to_locator(14) == locator<size_t>{3, 2, 1}, "to_locator");
92 static_assert(to_locator(15) == locator<size_t>{3, 2, 2}, "to_locator");
93 static_assert(to_locator(16) == locator<size_t>{3, 3, 0}, "to_locator");
94 static_assert(to_locator(17) == locator<size_t>{3, 3, 1}, "to_locator");
95 static_assert(to_locator(18) == locator<size_t>{3, 3, 2}, "to_locator");
96 static_assert(to_locator(19) == locator<size_t>{3, 3, 3}, "to_locator");
97 
98 constexpr size_t abs(int i) { return std::max(i, -i); }
99 
100 template <typename T>
101 constexpr void swap(T& a, T& b) {
102  T t = a;
103  a = b;
104  b = t;
105 }
106 
107 constexpr locator<size_t> fold_locator(const locator<int>& i) {
108  size_t x = abs(i.x);
109  size_t y = abs(i.y);
110  size_t z = abs(i.z);
111  size_t plane = x + 1;
112  if (plane <= y) {
113  swap(x, y);
114  }
115  if (plane <= z) {
116  swap(x, z);
117  }
118  if (y < z) {
119  swap(y, z);
120  }
121  return locator<size_t>{x, y, z};
122 }
123 
124 static_assert(fold_locator(locator<int>{0, 0, 0}) == locator<size_t>{0, 0, 0},
125  "fold_locator");
126 
127 static_assert(fold_locator(locator<int>{1, 0, 0}) == locator<size_t>{1, 0, 0},
128  "fold_locator");
129 static_assert(fold_locator(locator<int>{-1, 0, 0}) == locator<size_t>{1, 0, 0},
130  "fold_locator");
131 static_assert(fold_locator(locator<int>{0, 1, 0}) == locator<size_t>{1, 0, 0},
132  "fold_locator");
133 static_assert(fold_locator(locator<int>{0, -1, 0}) == locator<size_t>{1, 0, 0},
134  "fold_locator");
135 static_assert(fold_locator(locator<int>{0, 0, 1}) == locator<size_t>{1, 0, 0},
136  "fold_locator");
137 static_assert(fold_locator(locator<int>{0, 0, -1}) == locator<size_t>{1, 0, 0},
138  "fold_locator");
139 
140 static_assert(fold_locator(locator<int>{4, 0, 3}) == locator<size_t>{4, 3, 0},
141  "fold_locator");
142 static_assert(fold_locator(locator<int>{-4, 0, 3}) == locator<size_t>{4, 3, 0},
143  "fold_locator");
144 
145 constexpr size_t to_index(const locator<size_t>& l) {
146  return tetrahedron(l.x) + triangle(l.y) + l.z;
147 }
148 
149 static_assert(0 == to_index(locator<size_t>{0, 0, 0}), "to_locator");
150 
151 static_assert(1 == to_index(locator<size_t>{1, 0, 0}), "to_locator");
152 static_assert(2 == to_index(locator<size_t>{1, 1, 0}), "to_locator");
153 static_assert(3 == to_index(locator<size_t>{1, 1, 1}), "to_locator");
154 
155 static_assert(4 == to_index(locator<size_t>{2, 0, 0}), "to_locator");
156 static_assert(5 == to_index(locator<size_t>{2, 1, 0}), "to_locator");
157 static_assert(6 == to_index(locator<size_t>{2, 1, 1}), "to_locator");
158 static_assert(7 == to_index(locator<size_t>{2, 2, 0}), "to_locator");
159 static_assert(8 == to_index(locator<size_t>{2, 2, 1}), "to_locator");
160 static_assert(9 == to_index(locator<size_t>{2, 2, 2}), "to_locator");
161 
162 static_assert(10 == to_index(locator<size_t>{3, 0, 0}), "to_locator");
163 static_assert(11 == to_index(locator<size_t>{3, 1, 0}), "to_locator");
164 static_assert(12 == to_index(locator<size_t>{3, 1, 1}), "to_locator");
165 static_assert(13 == to_index(locator<size_t>{3, 2, 0}), "to_locator");
166 static_assert(14 == to_index(locator<size_t>{3, 2, 1}), "to_locator");
167 static_assert(15 == to_index(locator<size_t>{3, 2, 2}), "to_locator");
168 static_assert(16 == to_index(locator<size_t>{3, 3, 0}), "to_locator");
169 static_assert(17 == to_index(locator<size_t>{3, 3, 1}), "to_locator");
170 static_assert(18 == to_index(locator<size_t>{3, 3, 2}), "to_locator");
171 static_assert(19 == to_index(locator<size_t>{3, 3, 3}), "to_locator");
172 
173 } // namespace