LeviLamina
Loading...
Searching...
No Matches
Field.h
1#pragma once
2
3#include <array>
4#include <cmath>
5#include <concepts>
6#include <cstddef>
7
8#include "ll/api/base/Macro.h"
9
10#include "mc/math/vector/base/CommutativeGroup.h"
11
12namespace ll::math {
13struct FieldTag {};
14
15template <typename T>
16concept IsField = std::is_base_of_v<FieldTag, T>;
17
18template <typename T, typename... Components>
19struct LL_EBO Field : CommutativeGroup<T, Components...>, FieldTag {
20public:
21 using first_type = typename CommutativeGroup<T, Components...>::first_type;
22
23 [[nodiscard]] constexpr std::array<T, Field::size() * 2> getNeighbors() const noexcept {
24 std::array<T, Field::size() * 2> res;
25 size_t i = 0;
26 Field::forEachComponent([&]<typename axis_type, size_t axis> {
27 ll::meta::unroll<2>([&]<size_t iter> {
28 T tmp = *(static_cast<T const*>(this));
29 tmp.template get<axis_type, axis>() += static_cast<axis_type>(iter * 2 - 1);
30 res[i] = tmp;
31 i++;
32 });
33 });
34 return res;
35 }
36
37 constexpr T& operator*=(T const& b) noexcept {
38 Field::forEachComponent([&]<typename axis_type, size_t iter> {
39 static_cast<T*>(this)->template get<axis_type, iter>() *= b.template get<axis_type, iter>();
40 });
41 return static_cast<T&>(*(static_cast<T*>(this)));
42 }
43
44 constexpr T& operator/=(T const& b) noexcept {
45 Field::forEachComponent([&]<typename axis_type, size_t iter> {
46 static_cast<T*>(this)->template get<axis_type, iter>() /= b.template get<axis_type, iter>();
47 });
48 return static_cast<T&>(*(static_cast<T*>(this)));
49 }
50
51 [[nodiscard]] constexpr T operator*(T const& b) const noexcept {
52 T tmp = *(static_cast<T const*>(this));
53 tmp *= b;
54 return tmp;
55 }
56
57 [[nodiscard]] constexpr T operator/(T const& b) const noexcept {
58 T tmp = *(static_cast<T const*>(this));
59 tmp /= b;
60 return tmp;
61 }
62
63 template <std::convertible_to<first_type> V>
64 constexpr T& operator*=(V const& b) noexcept {
65 Field::forEachComponent([&]<typename axis_type, size_t iter> {
66 static_cast<T*>(this)->template get<first_type, iter>() *= static_cast<first_type>(b);
67 });
68 return static_cast<T&>(*(static_cast<T*>(this)));
69 }
70
71 template <std::convertible_to<first_type> V>
72 constexpr T& operator/=(V const& b) noexcept {
73 Field::forEachComponent([&]<typename axis_type, size_t iter> {
74 static_cast<T*>(this)->template get<first_type, iter>() /= static_cast<first_type>(b);
75 });
76 return static_cast<T&>(*(static_cast<T*>(this)));
77 }
78
79 template <std::convertible_to<first_type> V>
80 [[nodiscard]] constexpr T operator*(V const& b) const noexcept {
81 T tmp = *(static_cast<T const*>(this));
82 tmp *= static_cast<first_type>(b);
83 return tmp;
84 }
85
86 template <std::convertible_to<first_type> V>
87 [[nodiscard]] constexpr T operator/(V const& b) const noexcept {
88 T tmp = *(static_cast<T const*>(this));
89 tmp /= static_cast<first_type>(b);
90 return tmp;
91 }
92
93 [[nodiscard]] constexpr T mul(T const& b) const noexcept { return *(static_cast<T const*>(this)) * b; }
94
95 [[nodiscard]] constexpr T div(T const& b) const noexcept { return *(static_cast<T const*>(this)) / b; }
96
97 template <std::convertible_to<first_type> V>
98 [[nodiscard]] constexpr T mul(V const& b) const noexcept {
99 return *(static_cast<T const*>(this)) * static_cast<first_type>(b);
100 }
101
102 template <std::convertible_to<first_type> V>
103 [[nodiscard]] constexpr T div(V const& b) const noexcept {
104 return *(static_cast<T const*>(this)) / static_cast<first_type>(b);
105 }
106
107 [[nodiscard]] constexpr double dot(T const& b) const noexcept {
108 double res = 0.0;
109 Field::forEachComponent([&]<typename axis_type, size_t iter> {
110 res += (double)(static_cast<T const*>(this)->template get<axis_type, iter>())
111 * b.template get<axis_type, iter>();
112 });
113 return res;
114 }
115
116 template <std::convertible_to<first_type> V>
117 [[nodiscard]] constexpr double dot(V const& b) const noexcept {
118 double res = 0.0;
119 Field::forEachComponent([&]<typename axis_type, size_t iter> {
120 res += (double)(static_cast<T const*>(this)->template get<axis_type, iter>()) * static_cast<first_type>(b);
121 });
122 return res;
123 }
124
125 [[nodiscard]] constexpr double lengthSqr() const noexcept { return dot(*(static_cast<T const*>(this))); }
126
127 [[nodiscard]] constexpr double length() const noexcept { return sqrt(static_cast<double>(lengthSqr())); }
128
129 [[nodiscard]] constexpr double distanceTo(T const& b) const noexcept {
130 return (*(static_cast<T const*>(this)) - b).length();
131 }
132
133 [[nodiscard]] constexpr double distanceToSqr(T const& b) const noexcept {
134 return (*(static_cast<T const*>(this)) - b).lengthSqr();
135 }
136
137 [[nodiscard]] constexpr bool operator<(T const& b) const noexcept { return lengthSqr() < b.lengthSqr(); }
138
139 [[nodiscard]] constexpr bool operator>(T const& b) const noexcept { return lengthSqr() > b.lengthSqr(); }
140
141 [[nodiscard]] constexpr bool operator<=(T const& b) const noexcept { return lengthSqr() <= b.lengthSqr(); }
142
143 [[nodiscard]] constexpr bool operator>=(T const& b) const noexcept { return lengthSqr() >= b.lengthSqr(); }
144
145 [[nodiscard]] constexpr class boolN<sizeof...(Components)> lt(T const& b) const noexcept
146 requires(sizeof...(Components) >= 2 && sizeof...(Components) <= 4)
147 {
148 boolN<sizeof...(Components)> res = true;
149 Field::forEachComponent([&]<typename axis_type, size_t iter> {
150 res.template get<bool, iter>() =
151 (static_cast<T const*>(this)->template get<axis_type, iter>() < b.template get<axis_type, iter>());
152 });
153 return res;
154 }
155
156 [[nodiscard]] constexpr class boolN<sizeof...(Components)> le(T const& b) const noexcept
157 requires(sizeof...(Components) >= 2 && sizeof...(Components) <= 4)
158 {
159 boolN<sizeof...(Components)> res = true;
160 Field::forEachComponent([&]<typename axis_type, size_t iter> {
161 res.template get<bool, iter>() =
162 (static_cast<T const*>(this)->template get<axis_type, iter>() <= b.template get<axis_type, iter>());
163 });
164 return res;
165 }
166
167 [[nodiscard]] constexpr class boolN<sizeof...(Components)> gt(T const& b) const noexcept
168 requires(sizeof...(Components) >= 2 && sizeof...(Components) <= 4)
169 {
170 boolN<sizeof...(Components)> res = true;
171 Field::forEachComponent([&]<typename axis_type, size_t iter> {
172 res.template get<bool, iter>() =
173 (static_cast<T const*>(this)->template get<axis_type, iter>() > b.template get<axis_type, iter>());
174 });
175 return res;
176 }
177
178 [[nodiscard]] constexpr class boolN<sizeof...(Components)> ge(T const& b) const noexcept
179 requires(sizeof...(Components) >= 2 && sizeof...(Components) <= 4)
180 {
181 boolN<sizeof...(Components)> res = true;
182 Field::forEachComponent([&]<typename axis_type, size_t iter> {
183 res.template get<bool, iter>() =
184 (static_cast<T const*>(this)->template get<axis_type, iter>() >= b.template get<axis_type, iter>());
185 });
186 return res;
187 }
188};
189
190template <IsField T, std::convertible_to<typename T::first_type> V>
191[[nodiscard]] constexpr auto operator*(V const& v, T const& t) noexcept {
192 return T{static_cast<typename T::first_type>(v)} * t;
193}
194
195template <IsField T, std::convertible_to<typename T::first_type> V>
196[[nodiscard]] constexpr auto operator/(V const& v, T const& t) noexcept {
197 return T{static_cast<typename T::first_type>(v)} / t;
198}
199
200#define LL_VEC_GEN_BASIC_MATH_FUNC_FLOAT(TYPE, NAME) \
201 template <TYPE T> \
202 [[nodiscard]] constexpr T NAME(T const& x) noexcept { \
203 T tmp; \
204 T::forEachComponent([&]<typename axis_type, size_t iter> { \
205 tmp.template get<axis_type, iter>() = \
206 static_cast<axis_type>(std::NAME(x.template get<axis_type, iter>())); \
207 }); \
208 return tmp; \
209 }
210LL_VEC_GEN_BASIC_MATH_FUNC_FLOAT(IsField, abs)
211} // namespace ll::math
Definition boolN.h:10
Definition Field.h:16
Definition CommutativeGroup.h:17
Definition Field.h:13
Definition Field.h:19