21 #ifndef THUNDEREGG_FACE_H
22 #define THUNDEREGG_FACE_H
29 #include <ThunderEgg/tpl/json.hpp>
40 template<
int D,
int M>
52 static constexpr
size_t twopow(
size_t N) {
return 0b1 << N; }
57 static constexpr
size_t factorial(
size_t N) {
return N == 0 ? 1 : N * factorial(N - 1); }
62 static constexpr
size_t choose(
size_t N,
size_t K)
64 return factorial(N) / (factorial(K) * factorial(N - K));
67 static constexpr
size_t sum(
int N)
69 return N == -1 ? 0 : (twopow(D - N) * choose(D, N) + sum(N - 1));
73 static constexpr
int dimensionality = M;
77 static constexpr
size_t number_of = twopow(D - M) * choose(D, M);
79 static constexpr
size_t sum_of_faces = M <= 0 ? 0 : sum(M - 1);
85 explicit Face(
unsigned char value)
88 static_assert(D <= 3 && D >= 0,
"Only up to 3 dimensions supported");
89 static_assert(M >= 0 && M < D,
"Invalid M value");
97 static_assert(D <= 3 && D >= 0,
"Only up to 3 dimensions supported");
98 static_assert(M >= 0 && M < D,
"Invalid M value");
116 static auto west() ->
typename std::enable_if<D <= 3 && M == D - 1 && N == N,
Face<D, M>>::type
124 static auto east() ->
typename std::enable_if<D <= 3 && M == D - 1 && N == N,
Face<D, M>>::type
133 typename std::enable_if<D <= 3 && D >= 2 && M == D - 1 && N == N,
Face<D, M>>::type
142 typename std::enable_if<D <= 3 && D >= 2 && M == D - 1 && N == N,
Face<D, M>>::type
151 typename std::enable_if<D <= 3 && D >= 3 && M == D - 1 && N == N,
Face<D, M>>::type
160 typename std::enable_if<D <= 3 && D >= 3 && M == D - 1 && N == N,
Face<D, M>>::type
169 static auto sw() ->
typename std::enable_if<D == 2 && M == 0 && N == N, Face<D, M>>::type
177 static auto se() ->
typename std::enable_if<D == 2 && M == 0 && N == N, Face<D, M>>::type
179 return Face<D, M>(0b01);
185 static auto nw() ->
typename std::enable_if<D == 2 && M == 0 && N == N, Face<D, M>>::type
187 return Face<D, M>(0b10);
193 static auto ne() ->
typename std::enable_if<D == 2 && M == 0 && N == N, Face<D, M>>::type
195 return Face<D, M>(0b11);
202 static auto bsw() ->
typename std::enable_if<D == 3 && M == 0 && N == N, Face<D, M>>::type
204 return Face<D, M>(0b000);
210 static auto bse() ->
typename std::enable_if<D == 3 && M == 0 && N == N, Face<D, M>>::type
212 return Face<D, M>(0b001);
218 static auto bnw() ->
typename std::enable_if<D == 3 && M == 0 && N == N, Face<D, M>>::type
220 return Face<D, M>(0b010);
226 static auto bne() ->
typename std::enable_if<D == 3 && M == 0 && N == N, Face<D, M>>::type
228 return Face<D, M>(0b011);
234 static auto tsw() ->
typename std::enable_if<D == 3 && M == 0 && N == N, Face<D, M>>::type
236 return Face<D, M>(0b100);
242 static auto tse() ->
typename std::enable_if<D == 3 && M == 0 && N == N, Face<D, M>>::type
244 return Face<D, M>(0b101);
250 static auto tnw() ->
typename std::enable_if<D == 3 && M == 0 && N == N, Face<D, M>>::type
252 return Face<D, M>(0b110);
258 static auto tne() ->
typename std::enable_if<D == 3 && M == 0 && N == N, Face<D, M>>::type
260 return Face<D, M>(0b111);
267 static auto bs() ->
typename std::enable_if<D == 3 && M == 1 && N == N, Face<D, M>>::type
275 static auto bn() ->
typename std::enable_if<D == 3 && M == 1 && N == N, Face<D, M>>::type
283 static auto ts() ->
typename std::enable_if<D == 3 && M == 1 && N == N, Face<D, M>>::type
291 static auto tn() ->
typename std::enable_if<D == 3 && M == 1 && N == N, Face<D, M>>::type
299 static auto bw() ->
typename std::enable_if<D == 3 && M == 1 && N == N, Face<D, M>>::type
307 static auto be() ->
typename std::enable_if<D == 3 && M == 1 && N == N, Face<D, M>>::type
315 static auto tw() ->
typename std::enable_if<D == 3 && M == 1 && N == N, Face<D, M>>::type
323 static auto te() ->
typename std::enable_if<D == 3 && M == 1 && N == N, Face<D, M>>::type
331 static auto sw() ->
typename std::enable_if<D == 3 && M == 1 && N == N, Face<D, M>>::type
339 static auto se() ->
typename std::enable_if<D == 3 && M == 1 && N == N, Face<D, M>>::type
347 static auto nw() ->
typename std::enable_if<D == 3 && M == 1 && N == N, Face<D, M>>::type
355 static auto ne() ->
typename std::enable_if<D == 3 && M == 1 && N == N, Face<D, M>>::type
459 typename std::enable_if<D <= 3 && D >= 1 && M == D - 1 && N == N,
size_t>::type
469 typename std::enable_if<D <= 3 && D >= 1 && M == D - 1 && N == N,
bool>::type
471 return !(value & 0b1);
479 typename std::enable_if<D <= 3 && D >= 1 && M == D - 1 && N == N,
bool>::type
498 std::array<
Face<D, D - 1>, D - M> sides;
499 if constexpr (D > 1 && M == 0) {
500 for (
size_t i = 0; i < D; i++) {
502 if ((1 << i) & value) {
505 sides[i] =
Face<D, D - 1>(side);
507 }
else if constexpr (D == 3 && M == 1) {
508 size_t not_axis = value >> 2;
509 size_t curr_index = 0;
510 for (
unsigned char i = 0; i < D; i++) {
512 unsigned char bit = (value & (0b1 << curr_index)) >> curr_index;
513 sides[curr_index] =
Face<D, D - 1>((i << 1) ^ bit);
518 sides[0] =
Face<D, D - 1>(value);
569 return Side<D>((axis << 1) + 1);
585 to_json(tpl::nlohmann::json& j,
const Side<1>& s);
587 to_json(tpl::nlohmann::json& j,
const Side<2>& s);
589 to_json(tpl::nlohmann::json& j,
const Side<3>& s);
591 from_json(
const tpl::nlohmann::json& j, Side<1>& s);
593 from_json(
const tpl::nlohmann::json& j, Side<2>& s);
595 from_json(
const tpl::nlohmann::json& j, Side<3>& s);
607 operator<<(std::ostream& os,
const Side<1>& s);
619 operator<<(std::ostream& os,
const Side<2>& s);
631 operator<<(std::ostream& os,
const Side<3>& s);
650 to_json(tpl::nlohmann::json& j,
const Edge& o);
652 from_json(
const tpl::nlohmann::json& j,
Edge& o);
686 to_json(tpl::nlohmann::json& j,
const Corner<2>& o);
688 to_json(tpl::nlohmann::json& j,
const Corner<3>& o);
690 from_json(
const tpl::nlohmann::json& j,
Corner<2>& o);
692 from_json(
const tpl::nlohmann::json& j,
Corner<3>& o);