stellarlib 0.1.0
Loading...
Searching...
No Matches
matrix.hpp
1/* clang-format off */
2
3/*
4 stellarlib
5 Copyright (C) 2025-2026 Domán Zana
6
7 This software is provided 'as-is', without any express or implied
8 warranty. In no event will the authors be held liable for any damages
9 arising from the use of this software.
10
11 Permission is granted to anyone to use this software for any purpose,
12 including commercial applications, and to alter it and redistribute it
13 freely, subject to the following restrictions:
14
15 1. The origin of this software must not be misrepresented; you must not
16 claim that you wrote the original software. If you use this software
17 in a product, an acknowledgment in the product documentation would be
18 appreciated but is not required.
19 2. Altered source versions must be plainly marked as such, and must not be
20 misrepresented as being the original software.
21 3. This notice may not be removed or altered from any source distribution.
22*/
23
24#ifndef STELLARLIB_LIN_MATRIX_HPP
25#define STELLARLIB_LIN_MATRIX_HPP
26
27#include <array>
28#include <cstddef>
29#include <format>
30#include <memory>
31#include <ostream>
32#include <ranges>
33#include <sstream>
34#include <type_traits>
35#include <utility>
36
37namespace stellarlib::lin::internal
38{
39template <typename T, std::size_t M, std::size_t N>
40requires (std::is_arithmetic_v<T> && static_cast<bool>(M * N))
41class matrix final : public std::array<T, M * N>
42{
43public:
44 [[nodiscard]]
45 constexpr matrix() noexcept = default;
46
47 template <typename U>
48 [[nodiscard]]
49 explicit constexpr matrix(const U elem) noexcept
50 requires (std::is_convertible_v<U, T> && M == N)
51 {
52 for (const auto i : std::views::iota(std::size_t{}, M * N)) {
53 std::array<T, M * N>::operator[](i) = i % (N + 1) ? 0 : static_cast<T>(elem);
54 }
55 }
56
57 template <typename ...Args>
58 [[nodiscard]]
59 explicit constexpr matrix(Args &&...args) noexcept
60 requires ((std::is_convertible_v<Args, T> && ...) && sizeof...(Args) == M * N)
61 : std::array<T, M * N>{static_cast<T>(std::forward<Args>(args))...}
62 {}
63
64 [[nodiscard]]
65 explicit constexpr matrix(const std::array<T, M * N> &elems) noexcept
66 : std::array<T, M * N>{elems}
67 {}
68
69 template <typename U>
70 [[nodiscard]]
71 explicit constexpr matrix(const std::array<U, M * N> &elems) noexcept
72 {
73 for (const auto [lhs, rhs] : std::views::zip(*this, elems)) {
74 lhs = rhs;
75 }
76 }
77
78 [[nodiscard]]
79 explicit constexpr matrix(const matrix<T, N, M> &other) noexcept
80 requires (M == 1 || N == 1)
81 : std::array<T, M * N>{other}
82 {}
83
84 template <typename U>
85 [[nodiscard]]
86 explicit constexpr matrix(const matrix<U, N, M> &other) noexcept
87 requires (M == 1 || N == 1)
88 {
89 for (const auto [lhs, rhs] : std::views::zip(*this, other)) {
90 lhs = rhs;
91 }
92 }
93
94 [[nodiscard]]
95 constexpr matrix(const matrix &) noexcept = default;
96
97 [[nodiscard]]
98 constexpr matrix(matrix &&) noexcept = default;
99
100 template <typename Arg>
101 constexpr auto operator=(Arg &&arg) noexcept
102 -> auto &
103 {
104 std::destroy_at(this);
105 std::construct_at(this, std::forward<Arg>(arg));
106 return *this;
107 }
108
109 constexpr auto operator=(const matrix &) noexcept
110 -> matrix & = default;
111
112 constexpr auto operator=(matrix &&) noexcept
113 -> matrix & = default;
114
115 constexpr ~matrix() noexcept = default;
116
117 template <typename U>
118 [[nodiscard]]
119 explicit constexpr operator U() noexcept
120 requires (std::is_convertible_v<T, U> && M * N == 1)
121 {
122 return std::array<T, M * N>::front();
123 }
124
125#define STELLARLIB_LIN_MATRIX_ACCESSOR_SINGLE_IMPL(expr, i)\
126 [[nodiscard]]\
127 constexpr auto expr() const noexcept\
128 {\
129 return elem<i>();\
130 }\
131\
132 [[nodiscard]]\
133 constexpr auto expr() noexcept\
134 -> auto &\
135 {\
136 return elem<i>();\
137 }
138
139#define STELLARLIB_LIN_MATRIX_ACCESSOR_DOUBLE_IMPL(expr1, expr2, i)\
140 STELLARLIB_LIN_MATRIX_ACCESSOR_SINGLE_IMPL(expr1, i);\
141 STELLARLIB_LIN_MATRIX_ACCESSOR_SINGLE_IMPL(expr2, i);
142
143#define STELLARLIB_LIN_MATRIX_SWIZZLE_SINGLE_IMPL(expr, ...)\
144 [[nodiscard]]\
145 constexpr auto expr() const noexcept\
146 {\
147 return swizzle<__VA_ARGS__>();\
148 }
149
150#define STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(expr1, expr2, ...)\
151 STELLARLIB_LIN_MATRIX_SWIZZLE_SINGLE_IMPL(expr1, __VA_ARGS__);\
152 STELLARLIB_LIN_MATRIX_SWIZZLE_SINGLE_IMPL(expr2, __VA_ARGS__);
153
154 STELLARLIB_LIN_MATRIX_ACCESSOR_DOUBLE_IMPL(x, r, 0);
155 STELLARLIB_LIN_MATRIX_ACCESSOR_DOUBLE_IMPL(y, g, 1);
156 STELLARLIB_LIN_MATRIX_ACCESSOR_DOUBLE_IMPL(z, b, 2);
157 STELLARLIB_LIN_MATRIX_ACCESSOR_DOUBLE_IMPL(w, a, 3);
158
159 [[nodiscard]]
160 constexpr auto operator[](const std::size_t n) const noexcept
161 requires (M == 1 || N == 1)
162 {
163 return std::array<T, M * N>::operator[](n);
164 }
165
166 [[nodiscard]]
167 constexpr auto operator[](const std::size_t n) noexcept
168 -> auto &
169 requires (M == 1 || N == 1)
170 {
171 return std::array<T, M * N>::operator[](n);
172 }
173
174 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xx, rr, 0, 0);
175 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xy, rg, 0, 1);
176 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xz, rb, 0, 2);
177 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xw, ra, 0, 3);
178 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yx, gr, 1, 0);
179 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yy, gg, 1, 1);
180 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yz, gb, 1, 2);
181 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yw, ga, 1, 3);
182 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zx, br, 2, 0);
183 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zy, bg, 2, 1);
184 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zz, bb, 2, 2);
185 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zw, ba, 2, 3);
186 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wx, ar, 3, 0);
187 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wy, ag, 3, 1);
188 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wz, ab, 3, 2);
189 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(ww, aa, 3, 3);
190 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xxx, rrr, 0, 0, 0);
191 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xxy, rrg, 0, 0, 1);
192 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xxz, rrb, 0, 0, 2);
193 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xxw, rra, 0, 0, 3);
194 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xyx, rgr, 0, 1, 0);
195 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xyy, rgg, 0, 1, 1);
196 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xyz, rgb, 0, 1, 2);
197 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xyw, rga, 0, 1, 3);
198 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xzx, rbr, 0, 2, 0);
199 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xzy, rbg, 0, 2, 1);
200 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xzz, rbb, 0, 2, 2);
201 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xzw, rba, 0, 2, 3);
202 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xwx, rar, 0, 3, 0);
203 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xwy, rag, 0, 3, 1);
204 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xwz, rab, 0, 3, 2);
205 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xww, raa, 0, 3, 3);
206 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yxx, grr, 1, 0, 0);
207 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yxy, grg, 1, 0, 1);
208 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yxz, grb, 1, 0, 2);
209 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yxw, gra, 1, 0, 3);
210 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yyx, ggr, 1, 1, 0);
211 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yyy, ggg, 1, 1, 1);
212 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yyz, ggb, 1, 1, 2);
213 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yyw, gga, 1, 1, 3);
214 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yzx, gbr, 1, 2, 0);
215 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yzy, gbg, 1, 2, 1);
216 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yzz, gbb, 1, 2, 2);
217 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yzw, gba, 1, 2, 3);
218 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(ywx, gar, 1, 3, 0);
219 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(ywy, gag, 1, 3, 1);
220 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(ywz, gab, 1, 3, 2);
221 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yww, gaa, 1, 3, 3);
222 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zxx, brr, 2, 0, 0);
223 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zxy, brg, 2, 0, 1);
224 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zxz, brb, 2, 0, 2);
225 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zxw, bra, 2, 0, 3);
226 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zyx, bgr, 2, 1, 0);
227 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zyy, bgg, 2, 1, 1);
228 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zyz, bgb, 2, 1, 2);
229 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zyw, bga, 2, 1, 3);
230 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zzx, bbr, 2, 2, 0);
231 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zzy, bbg, 2, 2, 1);
232 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zzz, bbb, 2, 2, 2);
233 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zzw, bba, 2, 2, 3);
234 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zwx, bar, 2, 3, 0);
235 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zwy, bag, 2, 3, 1);
236 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zwz, bab, 2, 3, 2);
237 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zww, baa, 2, 3, 3);
238 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wxx, arr, 3, 0, 0);
239 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wxy, arg, 3, 0, 1);
240 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wxz, arb, 3, 0, 2);
241 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wxw, ara, 3, 0, 3);
242 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wyx, agr, 3, 1, 0);
243 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wyy, agg, 3, 1, 1);
244 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wyz, agb, 3, 1, 2);
245 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wyw, aga, 3, 1, 3);
246 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wzx, abr, 3, 2, 0);
247 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wzy, abg, 3, 2, 1);
248 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wzz, abb, 3, 2, 2);
249 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wzw, aba, 3, 2, 3);
250 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wwx, aar, 3, 3, 0);
251 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wwy, aag, 3, 3, 1);
252 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wwz, aab, 3, 3, 2);
253 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(www, aaa, 3, 3, 3);
254 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xxxx, rrrr, 0, 0, 0, 0);
255 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xxxy, rrrg, 0, 0, 0, 1);
256 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xxxz, rrrb, 0, 0, 0, 2);
257 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xxxw, rrra, 0, 0, 0, 3);
258 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xxyx, rrgr, 0, 0, 1, 0);
259 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xxyy, rrgg, 0, 0, 1, 1);
260 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xxyz, rrgb, 0, 0, 1, 2);
261 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xxyw, rrga, 0, 0, 1, 3);
262 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xxzx, rrbr, 0, 0, 2, 0);
263 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xxzy, rrbg, 0, 0, 2, 1);
264 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xxzz, rrbb, 0, 0, 2, 2);
265 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xxzw, rrba, 0, 0, 2, 3);
266 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xxwx, rrar, 0, 0, 3, 0);
267 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xxwy, rrag, 0, 0, 3, 1);
268 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xxwz, rrab, 0, 0, 3, 2);
269 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xxww, rraa, 0, 0, 3, 3);
270 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xyxx, rgrr, 0, 1, 0, 0);
271 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xyxy, rgrg, 0, 1, 0, 1);
272 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xyxz, rgrb, 0, 1, 0, 2);
273 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xyxw, rgra, 0, 1, 0, 3);
274 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xyyx, rggr, 0, 1, 1, 0);
275 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xyyy, rggg, 0, 1, 1, 1);
276 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xyyz, rggb, 0, 1, 1, 2);
277 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xyyw, rgga, 0, 1, 1, 3);
278 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xyzx, rgbr, 0, 1, 2, 0);
279 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xyzy, rgbg, 0, 1, 2, 1);
280 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xyzz, rgbb, 0, 1, 2, 2);
281 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xyzw, rgba, 0, 1, 2, 3);
282 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xywx, rgar, 0, 1, 3, 0);
283 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xywy, rgag, 0, 1, 3, 1);
284 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xywz, rgab, 0, 1, 3, 2);
285 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xyww, rgaa, 0, 1, 3, 3);
286 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xzxx, rbrr, 0, 2, 0, 0);
287 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xzxy, rbrg, 0, 2, 0, 1);
288 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xzxz, rbrb, 0, 2, 0, 2);
289 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xzxw, rbra, 0, 2, 0, 3);
290 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xzyx, rbgr, 0, 2, 1, 0);
291 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xzyy, rbgg, 0, 2, 1, 1);
292 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xzyz, rbgb, 0, 2, 1, 2);
293 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xzyw, rbga, 0, 2, 1, 3);
294 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xzzx, rbbr, 0, 2, 2, 0);
295 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xzzy, rbbg, 0, 2, 2, 1);
296 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xzzz, rbbb, 0, 2, 2, 2);
297 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xzzw, rbba, 0, 2, 2, 3);
298 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xzwx, rbar, 0, 2, 3, 0);
299 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xzwy, rbag, 0, 2, 3, 1);
300 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xzwz, rbab, 0, 2, 3, 2);
301 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xzww, rbaa, 0, 2, 3, 3);
302 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xwxx, rarr, 0, 3, 0, 0);
303 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xwxy, rarg, 0, 3, 0, 1);
304 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xwxz, rarb, 0, 3, 0, 2);
305 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xwxw, rara, 0, 3, 0, 3);
306 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xwyx, ragr, 0, 3, 1, 0);
307 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xwyy, ragg, 0, 3, 1, 1);
308 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xwyz, ragb, 0, 3, 1, 2);
309 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xwyw, raga, 0, 3, 1, 3);
310 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xwzx, rabr, 0, 3, 2, 0);
311 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xwzy, rabg, 0, 3, 2, 1);
312 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xwzz, rabb, 0, 3, 2, 2);
313 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xwzw, raba, 0, 3, 2, 3);
314 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xwwx, raar, 0, 3, 3, 0);
315 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xwwy, raag, 0, 3, 3, 1);
316 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xwwz, raab, 0, 3, 3, 2);
317 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(xwww, raaa, 0, 3, 3, 3);
318 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yxxx, grrr, 1, 0, 0, 0);
319 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yxxy, grrg, 1, 0, 0, 1);
320 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yxxz, grrb, 1, 0, 0, 2);
321 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yxxw, grra, 1, 0, 0, 3);
322 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yxyx, grgr, 1, 0, 1, 0);
323 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yxyy, grgg, 1, 0, 1, 1);
324 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yxyz, grgb, 1, 0, 1, 2);
325 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yxyw, grga, 1, 0, 1, 3);
326 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yxzx, grbr, 1, 0, 2, 0);
327 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yxzy, grbg, 1, 0, 2, 1);
328 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yxzz, grbb, 1, 0, 2, 2);
329 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yxzw, grba, 1, 0, 2, 3);
330 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yxwx, grar, 1, 0, 3, 0);
331 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yxwy, grag, 1, 0, 3, 1);
332 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yxwz, grab, 1, 0, 3, 2);
333 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yxww, graa, 1, 0, 3, 3);
334 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yyxx, ggrr, 1, 1, 0, 0);
335 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yyxy, ggrg, 1, 1, 0, 1);
336 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yyxz, ggrb, 1, 1, 0, 2);
337 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yyxw, ggra, 1, 1, 0, 3);
338 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yyyx, gggr, 1, 1, 1, 0);
339 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yyyy, gggg, 1, 1, 1, 1);
340 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yyyz, gggb, 1, 1, 1, 2);
341 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yyyw, ggga, 1, 1, 1, 3);
342 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yyzx, ggbr, 1, 1, 2, 0);
343 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yyzy, ggbg, 1, 1, 2, 1);
344 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yyzz, ggbb, 1, 1, 2, 2);
345 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yyzw, ggba, 1, 1, 2, 3);
346 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yywx, ggar, 1, 1, 3, 0);
347 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yywy, ggag, 1, 1, 3, 1);
348 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yywz, ggab, 1, 1, 3, 2);
349 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yyww, ggaa, 1, 1, 3, 3);
350 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yzxx, gbrr, 1, 2, 0, 0);
351 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yzxy, gbrg, 1, 2, 0, 1);
352 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yzxz, gbrb, 1, 2, 0, 2);
353 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yzxw, gbra, 1, 2, 0, 3);
354 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yzyx, gbgr, 1, 2, 1, 0);
355 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yzyy, gbgg, 1, 2, 1, 1);
356 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yzyz, gbgb, 1, 2, 1, 2);
357 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yzyw, gbga, 1, 2, 1, 3);
358 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yzzx, gbbr, 1, 2, 2, 0);
359 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yzzy, gbbg, 1, 2, 2, 1);
360 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yzzz, gbbb, 1, 2, 2, 2);
361 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yzzw, gbba, 1, 2, 2, 3);
362 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yzwx, gbar, 1, 2, 3, 0);
363 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yzwy, gbag, 1, 2, 3, 1);
364 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yzwz, gbab, 1, 2, 3, 2);
365 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(yzww, gbaa, 1, 2, 3, 3);
366 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(ywxx, garr, 1, 3, 0, 0);
367 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(ywxy, garg, 1, 3, 0, 1);
368 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(ywxz, garb, 1, 3, 0, 2);
369 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(ywxw, gara, 1, 3, 0, 3);
370 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(ywyx, gagr, 1, 3, 1, 0);
371 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(ywyy, gagg, 1, 3, 1, 1);
372 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(ywyz, gagb, 1, 3, 1, 2);
373 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(ywyw, gaga, 1, 3, 1, 3);
374 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(ywzx, gabr, 1, 3, 2, 0);
375 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(ywzy, gabg, 1, 3, 2, 1);
376 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(ywzz, gabb, 1, 3, 2, 2);
377 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(ywzw, gaba, 1, 3, 2, 3);
378 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(ywwx, gaar, 1, 3, 3, 0);
379 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(ywwy, gaag, 1, 3, 3, 1);
380 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(ywwz, gaab, 1, 3, 3, 2);
381 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(ywww, gaaa, 1, 3, 3, 3);
382 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zxxx, brrr, 2, 0, 0, 0);
383 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zxxy, brrg, 2, 0, 0, 1);
384 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zxxz, brrb, 2, 0, 0, 2);
385 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zxxw, brra, 2, 0, 0, 3);
386 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zxyx, brgr, 2, 0, 1, 0);
387 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zxyy, brgg, 2, 0, 1, 1);
388 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zxyz, brgb, 2, 0, 1, 2);
389 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zxyw, brga, 2, 0, 1, 3);
390 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zxzx, brbr, 2, 0, 2, 0);
391 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zxzy, brbg, 2, 0, 2, 1);
392 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zxzz, brbb, 2, 0, 2, 2);
393 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zxzw, brba, 2, 0, 2, 3);
394 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zxwx, brar, 2, 0, 3, 0);
395 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zxwy, brag, 2, 0, 3, 1);
396 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zxwz, brab, 2, 0, 3, 2);
397 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zxww, braa, 2, 0, 3, 3);
398 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zyxx, bgrr, 2, 1, 0, 0);
399 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zyxy, bgrg, 2, 1, 0, 1);
400 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zyxz, bgrb, 2, 1, 0, 2);
401 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zyxw, bgra, 2, 1, 0, 3);
402 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zyyx, bggr, 2, 1, 1, 0);
403 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zyyy, bggg, 2, 1, 1, 1);
404 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zyyz, bggb, 2, 1, 1, 2);
405 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zyyw, bgga, 2, 1, 1, 3);
406 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zyzx, bgbr, 2, 1, 2, 0);
407 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zyzy, bgbg, 2, 1, 2, 1);
408 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zyzz, bgbb, 2, 1, 2, 2);
409 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zyzw, bgba, 2, 1, 2, 3);
410 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zywx, bgar, 2, 1, 3, 0);
411 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zywy, bgag, 2, 1, 3, 1);
412 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zywz, bgab, 2, 1, 3, 2);
413 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zyww, bgaa, 2, 1, 3, 3);
414 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zzxx, bbrr, 2, 2, 0, 0);
415 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zzxy, bbrg, 2, 2, 0, 1);
416 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zzxz, bbrb, 2, 2, 0, 2);
417 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zzxw, bbra, 2, 2, 0, 3);
418 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zzyx, bbgr, 2, 2, 1, 0);
419 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zzyy, bbgg, 2, 2, 1, 1);
420 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zzyz, bbgb, 2, 2, 1, 2);
421 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zzyw, bbga, 2, 2, 1, 3);
422 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zzzx, bbbr, 2, 2, 2, 0);
423 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zzzy, bbbg, 2, 2, 2, 1);
424 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zzzz, bbbb, 2, 2, 2, 2);
425 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zzzw, bbba, 2, 2, 2, 3);
426 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zzwx, bbar, 2, 2, 3, 0);
427 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zzwy, bbag, 2, 2, 3, 1);
428 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zzwz, bbab, 2, 2, 3, 2);
429 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zzww, bbaa, 2, 2, 3, 3);
430 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zwxx, barr, 2, 3, 0, 0);
431 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zwxy, barg, 2, 3, 0, 1);
432 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zwxz, barb, 2, 3, 0, 2);
433 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zwxw, bara, 2, 3, 0, 3);
434 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zwyx, bagr, 2, 3, 1, 0);
435 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zwyy, bagg, 2, 3, 1, 1);
436 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zwyz, bagb, 2, 3, 1, 2);
437 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zwyw, baga, 2, 3, 1, 3);
438 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zwzx, babr, 2, 3, 2, 0);
439 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zwzy, babg, 2, 3, 2, 1);
440 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zwzz, babb, 2, 3, 2, 2);
441 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zwzw, baba, 2, 3, 2, 3);
442 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zwwx, baar, 2, 3, 3, 0);
443 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zwwy, baag, 2, 3, 3, 1);
444 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zwwz, baab, 2, 3, 3, 2);
445 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(zwww, baaa, 2, 3, 3, 3);
446 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wxxx, arrr, 3, 0, 0, 0);
447 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wxxy, arrg, 3, 0, 0, 1);
448 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wxxz, arrb, 3, 0, 0, 2);
449 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wxxw, arra, 3, 0, 0, 3);
450 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wxyx, argr, 3, 0, 1, 0);
451 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wxyy, argg, 3, 0, 1, 1);
452 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wxyz, argb, 3, 0, 1, 2);
453 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wxyw, arga, 3, 0, 1, 3);
454 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wxzx, arbr, 3, 0, 2, 0);
455 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wxzy, arbg, 3, 0, 2, 1);
456 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wxzz, arbb, 3, 0, 2, 2);
457 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wxzw, arba, 3, 0, 2, 3);
458 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wxwx, arar, 3, 0, 3, 0);
459 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wxwy, arag, 3, 0, 3, 1);
460 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wxwz, arab, 3, 0, 3, 2);
461 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wxww, araa, 3, 0, 3, 3);
462 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wyxx, agrr, 3, 1, 0, 0);
463 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wyxy, agrg, 3, 1, 0, 1);
464 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wyxz, agrb, 3, 1, 0, 2);
465 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wyxw, agra, 3, 1, 0, 3);
466 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wyyx, aggr, 3, 1, 1, 0);
467 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wyyy, aggg, 3, 1, 1, 1);
468 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wyyz, aggb, 3, 1, 1, 2);
469 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wyyw, agga, 3, 1, 1, 3);
470 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wyzx, agbr, 3, 1, 2, 0);
471 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wyzy, agbg, 3, 1, 2, 1);
472 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wyzz, agbb, 3, 1, 2, 2);
473 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wyzw, agba, 3, 1, 2, 3);
474 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wywx, agar, 3, 1, 3, 0);
475 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wywy, agag, 3, 1, 3, 1);
476 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wywz, agab, 3, 1, 3, 2);
477 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wyww, agaa, 3, 1, 3, 3);
478 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wzxx, abrr, 3, 2, 0, 0);
479 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wzxy, abrg, 3, 2, 0, 1);
480 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wzxz, abrb, 3, 2, 0, 2);
481 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wzxw, abra, 3, 2, 0, 3);
482 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wzyx, abgr, 3, 2, 1, 0);
483 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wzyy, abgg, 3, 2, 1, 1);
484 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wzyz, abgb, 3, 2, 1, 2);
485 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wzyw, abga, 3, 2, 1, 3);
486 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wzzx, abbr, 3, 2, 2, 0);
487 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wzzy, abbg, 3, 2, 2, 1);
488 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wzzz, abbb, 3, 2, 2, 2);
489 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wzzw, abba, 3, 2, 2, 3);
490 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wzwx, abar, 3, 2, 3, 0);
491 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wzwy, abag, 3, 2, 3, 1);
492 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wzwz, abab, 3, 2, 3, 2);
493 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wzww, abaa, 3, 2, 3, 3);
494 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wwxx, aarr, 3, 3, 0, 0);
495 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wwxy, aarg, 3, 3, 0, 1);
496 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wwxz, aarb, 3, 3, 0, 2);
497 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wwxw, aara, 3, 3, 0, 3);
498 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wwyx, aagr, 3, 3, 1, 0);
499 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wwyy, aagg, 3, 3, 1, 1);
500 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wwyz, aagb, 3, 3, 1, 2);
501 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wwyw, aaga, 3, 3, 1, 3);
502 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wwzx, aabr, 3, 3, 2, 0);
503 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wwzy, aabg, 3, 3, 2, 1);
504 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wwzz, aabb, 3, 3, 2, 2);
505 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wwzw, aaba, 3, 3, 2, 3);
506 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wwwx, aaar, 3, 3, 3, 0);
507 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wwwy, aaag, 3, 3, 3, 1);
508 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wwwz, aaab, 3, 3, 3, 2);
509 STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL(wwww, aaaa, 3, 3, 3, 3);
510
511 [[nodiscard]]
512 constexpr auto operator[](const std::size_t m) const noexcept
513 -> const auto &
514 requires (M != 1 && N != 1)
515 {
516 using row [[gnu::may_alias]] = matrix<T, 1, N>;
517 return *reinterpret_cast<const row *>(std::addressof(std::array<T, M * N>::operator[](m * N)));
518 }
519
520 [[nodiscard]]
521 constexpr auto operator[](const std::size_t m) noexcept
522 -> auto &
523 requires (M != 1 && N != 1)
524 {
525 using row [[gnu::may_alias]] = matrix<T, 1, N>;
526 return *reinterpret_cast<row *>(std::addressof(std::array<T, M * N>::operator[](m * N)));
527 }
528
529private:
530 template <std::size_t I>
531 [[nodiscard]]
532 constexpr auto elem() const noexcept
533 requires ((M == 1 || N == 1) && I < M * N)
534 {
535 return std::array<T, M * N>::operator[](I);
536 }
537
538 template <std::size_t I>
539 [[nodiscard]]
540 constexpr auto elem() noexcept
541 -> auto &
542 requires ((M == 1 || N == 1) && I < M * N)
543 {
544 return std::array<T, M * N>::operator[](I);
545 }
546
547 template <std::size_t ...I>
548 [[nodiscard]]
549 constexpr auto swizzle() const noexcept
550 {
551 return matrix<T, 1, sizeof...(I)>{elem<I>()...};
552 }
553};
554
555#define STELLARLIB_LIN_MATRIX_PREFIX_POSTFIX_OPERATOR_IMPL(op)\
556template <typename T, std::size_t M, std::size_t N>\
557constexpr auto operator op (matrix<T, M, N> &self) noexcept\
558 -> auto &\
559{\
560 for (auto &elem : self) {\
561 op elem;\
562 }\
563\
564 return self;\
565}\
566\
567template <typename T, std::size_t M, std::size_t N>\
568constexpr auto operator op (matrix<T, M, N> &self, int) noexcept\
569 -> matrix<T, M, N>\
570{\
571 const auto res{self};\
572 op self;\
573 return res;\
574}
575
576#define STELLARLIB_LIN_MATRIX_UNARY_OPERATOR_IMPL(op)\
577template <typename T, std::size_t M, std::size_t N>\
578[[nodiscard]]\
579constexpr auto operator op (const matrix<T, M, N> &self) noexcept\
580 -> matrix<T, M, N>\
581{\
582 matrix<T, M, N> res;\
583\
584 for (const auto [res, elem] : std::views::zip(res, self)) {\
585 res = static_cast<T>(op elem);\
586 }\
587\
588 return res;\
589}
590
591#define STELLARLIB_LIN_MATRIX_BINARY_OPERATOR_IMPL(op)\
592template <typename T, std::size_t M, std::size_t N, typename U>\
593constexpr auto operator op##= (matrix<T, M, N> &lhs, const U rhs) noexcept\
594 -> auto &\
595 requires (std::is_arithmetic_v<U>)\
596{\
597 for (auto &lhs : lhs) {\
598 lhs op##= rhs;\
599 }\
600\
601 return lhs;\
602}\
603\
604template <typename T, std::size_t M, std::size_t N, typename U>\
605[[nodiscard]]\
606constexpr auto operator op (const matrix<T, M, N> &lhs, const U rhs) noexcept\
607 -> matrix<std::common_type_t<T, U>, M, N>\
608 requires (std::is_arithmetic_v<U>)\
609{\
610 auto res{lhs};\
611 res op##= rhs;\
612 return res;\
613}\
614\
615template <typename T, typename U, std::size_t M, std::size_t N>\
616[[nodiscard]]\
617constexpr auto operator op (const T lhs, const matrix<U, M, N> &rhs) noexcept\
618 -> matrix<std::common_type_t<T, U>, M, N>\
619 requires (std::is_arithmetic_v<T>)\
620{\
621 matrix<std::common_type_t<T, U>, M, N> res;\
622\
623 for (const auto [res, rhs] : std::views::zip(res, rhs)) {\
624 res = static_cast<std::common_type_t<T, U>>(lhs op rhs);\
625 }\
626\
627 return res;\
628}\
629\
630template <typename T, std::size_t M1, std::size_t N1, typename U, std::size_t M2, std::size_t N2>\
631constexpr auto operator op##= (matrix<T, M1, N1> &lhs, const matrix<U, M2, N2> &rhs) noexcept\
632 -> auto &\
633 requires ((M1 == 1 || N1 == 1) && (M2 == 1 || N2 == 1) && M1 * N1 == M2 * N2 || M1 == M2 && N1 == N2)\
634{\
635 for (const auto [lhs, rhs] : std::views::zip(lhs, rhs)) {\
636 lhs op##= rhs;\
637 }\
638\
639 return lhs;\
640}\
641\
642template <typename T, std::size_t M1, std::size_t N1, typename U, std::size_t M2, std::size_t N2>\
643[[nodiscard]]\
644constexpr auto operator op (const matrix<T, M1, N1> &lhs, const matrix<U, M2, N2> &rhs) noexcept\
645 -> matrix<std::common_type_t<T, U>, M1, N1>\
646 requires ((M1 == 1 || N1 == 1) && (M2 == 1 || N2 == 1) && M1 * N1 == M2 * N2 || M1 == M2 && N1 == N2)\
647{\
648 auto res{lhs};\
649 res op##= rhs;\
650 return res;\
651}
652
653#define STELLARLIB_LIN_MATRIX_BOOLEAN_OPERATOR_IMPL(op)\
654template <typename T, std::size_t M, std::size_t N, typename U>\
655[[nodiscard]]\
656constexpr auto operator op (const matrix<T, M, N> &lhs, const U rhs) noexcept\
657 -> matrix<bool, M, N>\
658 requires (std::is_arithmetic_v<U>)\
659{\
660 matrix<bool, M, N> res;\
661\
662 for (const auto [res, lhs] : std::views::zip(res, lhs)) {\
663 res = lhs op rhs;\
664 }\
665\
666 return res;\
667}\
668\
669template <typename T, typename U, std::size_t M, std::size_t N>\
670[[nodiscard]]\
671constexpr auto operator op (const T lhs, const matrix<U, M, N> &rhs) noexcept\
672 -> matrix<bool, M, N>\
673 requires (std::is_arithmetic_v<T>)\
674{\
675 matrix<bool, M, N> res;\
676\
677 for (const auto [res, rhs] : std::views::zip(res, rhs)) {\
678 res = lhs op rhs;\
679 }\
680\
681 return res;\
682}\
683\
684template <typename T, std::size_t M1, std::size_t N1, typename U, std::size_t M2, std::size_t N2>\
685[[nodiscard]]\
686constexpr auto operator op (const matrix<T, M1, N1> &lhs, const matrix<U, M2, N2> &rhs) noexcept\
687 -> matrix<bool, M1, N1>\
688 requires ((M1 == 1 || N1 == 1) && (M2 == 1 || N2 == 1) && M1 * N1 == M2 * N2 || M1 == M2 && N1 == N2)\
689{\
690 matrix<bool, M1, N1> res;\
691\
692 for (const auto [res, lhs, rhs] : std::views::zip(res, lhs, rhs)) {\
693 res = lhs op rhs;\
694 }\
695\
696 return res;\
697}
698
699STELLARLIB_LIN_MATRIX_PREFIX_POSTFIX_OPERATOR_IMPL(++);
700STELLARLIB_LIN_MATRIX_PREFIX_POSTFIX_OPERATOR_IMPL(--);
701
702template <typename T, std::size_t M, std::size_t N>
703[[nodiscard]]
704constexpr auto operator+(const matrix<T, M, N> &self) noexcept
705{
706 return self;
707}
708
709STELLARLIB_LIN_MATRIX_UNARY_OPERATOR_IMPL(-);
710STELLARLIB_LIN_MATRIX_UNARY_OPERATOR_IMPL(!);
711STELLARLIB_LIN_MATRIX_UNARY_OPERATOR_IMPL(~);
712STELLARLIB_LIN_MATRIX_BINARY_OPERATOR_IMPL(*);
713STELLARLIB_LIN_MATRIX_BINARY_OPERATOR_IMPL(/);
714STELLARLIB_LIN_MATRIX_BINARY_OPERATOR_IMPL(%);
715STELLARLIB_LIN_MATRIX_BINARY_OPERATOR_IMPL(+);
716STELLARLIB_LIN_MATRIX_BINARY_OPERATOR_IMPL(-);
717STELLARLIB_LIN_MATRIX_BINARY_OPERATOR_IMPL(<<);
718STELLARLIB_LIN_MATRIX_BINARY_OPERATOR_IMPL(>>);
719STELLARLIB_LIN_MATRIX_BOOLEAN_OPERATOR_IMPL(<);
720STELLARLIB_LIN_MATRIX_BOOLEAN_OPERATOR_IMPL(<=);
721STELLARLIB_LIN_MATRIX_BOOLEAN_OPERATOR_IMPL(>);
722STELLARLIB_LIN_MATRIX_BOOLEAN_OPERATOR_IMPL(>=);
723STELLARLIB_LIN_MATRIX_BOOLEAN_OPERATOR_IMPL(==);
724STELLARLIB_LIN_MATRIX_BOOLEAN_OPERATOR_IMPL(!=);
725STELLARLIB_LIN_MATRIX_BINARY_OPERATOR_IMPL(&);
726STELLARLIB_LIN_MATRIX_BINARY_OPERATOR_IMPL(^);
727STELLARLIB_LIN_MATRIX_BINARY_OPERATOR_IMPL(|);
728STELLARLIB_LIN_MATRIX_BOOLEAN_OPERATOR_IMPL(&&);
729STELLARLIB_LIN_MATRIX_BOOLEAN_OPERATOR_IMPL(||);
730
731template <typename T, std::size_t M, std::size_t N>
732constexpr auto operator<<(std::ostream &os, const matrix<T, M, N> &self)
733 -> auto &
734 requires (M == 1 || N == 1)
735{
736 os << '[' << self.front();
737
738 for (const auto elem : std::ranges::subrange{self.begin() + 1, self.end()}) {
739 os << ", " << elem;
740 }
741
742 os << ']';
743 return os;
744}
745
746template <typename T, std::size_t M, std::size_t N>
747constexpr auto operator<<(std::ostream &os, const matrix<T, M, N> &self)
748 -> auto &
749{
750 os << '[' << self[0];
751
752 for (const auto m : std::views::iota(std::size_t{1}, M)) {
753 os << ", " << self[m];
754 }
755
756 os << ']';
757 return os;
758}
759}
760
761template <typename T, std::size_t M, std::size_t N>
762struct std::formatter<stellarlib::lin::internal::matrix<T, M, N>> final
763{
764 [[nodiscard]]
765 constexpr auto parse(const std::format_parse_context &ctx) const noexcept
766 {
767 return ctx.begin();
768 }
769
770 [[nodiscard]]
771 constexpr auto format(const stellarlib::lin::internal::matrix<T, M, N> &matrix, std::format_context &ctx) const
772 {
773 std::ostringstream out{};
774 out << matrix;
775 return std::format_to(ctx.out(), "{}", out.view());
776 }
777};
778
779#undef STELLARLIB_LIN_MATRIX_BOOLEAN_OPERATOR_IMPL
780#undef STELLARLIB_LIN_MATRIX_BINARY_OPERATOR_IMPL
781#undef STELLARLIB_LIN_MATRIX_UNARY_OPERATOR_IMPL
782#undef STELLARLIB_LIN_MATRIX_PREFIX_POSTFIX_OPERATOR_IMPL
783#undef STELLARLIB_LIN_MATRIX_SWIZZLE_DOUBLE_IMPL
784#undef STELLARLIB_LIN_MATRIX_SWIZZLE_SINGLE_IMPL
785#undef STELLARLIB_LIN_MATRIX_ACCESSOR_DOUBLE_IMPL
786#undef STELLARLIB_LIN_MATRIX_ACCESSOR_SINGLE_IMPL
787
788#endif
internal::matrix< T, M, N > matrix
Generic M*N matrix with per-component operations.
Definition lin.hpp:48