25 static_assert(D == 2 || D == 3,
"Only 2D or 3D rotation-matrices are supported");
29 constexpr matrix& operator=(
matrix const&)
noexcept =
default;
30 constexpr matrix& operator=(
matrix&&)
noexcept =
default;
32 constexpr matrix()
noexcept
34 hilet a = f32x4::broadcast(1.0f);
42 _col0(col0), _col1(col1), _col2(col2), _col3(col3)
49 _col0(
static_cast<f32x4>(col0)),
50 _col1(
static_cast<f32x4>(col1)),
51 _col2(
static_cast<f32x4>(col2)),
52 _col3{0.0f, 0.0f, 0.0f, 1.0f}
68 _col0(c0r0, c0r1, c0r2, 0.0f), _col1(c1r0, c1r1, c1r2, 0.0f), _col2(c2r0, c2r1, c2r2, 0.0f), _col3(0.0f, 0.0f, 0.0f, 1.0f)
91 _col0(c0r0, c0r1, c0r2, c0r3), _col1(c1r0, c1r1, c1r2, c1r3), _col2(c2r0, c2r1, c2r2, c2r3), _col3(c3r0, c3r1, c3r2, c3r3)
98 _col0(get<0>(other)), _col1(get<1>(other)), _col2(get<2>(other)), _col3(get<3>(other))
118 return {_col0, _col1, _col2, _col3};
130 [[nodiscard]]
constexpr static matrix
134 [[nodiscard]]
friend constexpr f32x4 const& get(
matrix const& rhs)
noexcept
136 if constexpr (I == 0) {
138 }
else if constexpr (I == 1) {
140 }
else if constexpr (I == 2) {
142 }
else if constexpr (I == 3) {
150 [[nodiscard]]
friend constexpr f32x4& get(matrix& rhs)
noexcept
152 if constexpr (I == 0) {
154 }
else if constexpr (I == 1) {
156 }
else if constexpr (I == 2) {
158 }
else if constexpr (I == 3) {
165 [[nodiscard]]
constexpr bool holds_invariant() const noexcept
170 [[nodiscard]]
constexpr auto operator*(f32x4
const& rhs)
const noexcept
172 return f32x4{_col0 * rhs.xxxx() + _col1 * rhs.yyyy() + _col2 * rhs.zzzz() + _col3 * rhs.wwww()};
180 [[nodiscard]]
constexpr float operator*(
float const& rhs)
const noexcept
183 auto abs_scale = hypot<D>(_col0 * f32x4::broadcast(rhs));
196 return {*
this * get<0>(rhs), *
this * get<1>(rhs), *
this * get<2>(rhs), *
this * get<3>(rhs)};
200 [[nodiscard]]
constexpr auto operator*(
vector<E> const& rhs)
const noexcept
204 _col0 *
static_cast<f32x4>(rhs).xxxx() + _col1 *
static_cast<f32x4>(rhs).yyyy() +
205 _col2 *
static_cast<f32x4>(rhs).zzzz()};
209 [[nodiscard]]
constexpr auto operator*(extent<E>
const& rhs)
const noexcept
213 _col0 *
static_cast<f32x4
>(rhs).xxxx() + _col1 *
static_cast<f32x4
>(rhs).yyyy() +
214 _col2 *
static_cast<f32x4
>(rhs).zzzz()};
218 [[nodiscard]]
constexpr auto operator*(point<E>
const& rhs)
const noexcept
222 _col0 *
static_cast<f32x4
>(rhs).xxxx() + _col1 *
static_cast<f32x4
>(rhs).yyyy() +
223 _col2 *
static_cast<f32x4
>(rhs).zzzz() + _col3 *
static_cast<f32x4
>(rhs).wwww()};
226 [[nodiscard]]
constexpr rectangle operator*(aarectangle
const& rhs)
const noexcept
232 [[nodiscard]]
constexpr rectangle operator*(rectangle
const& rhs)
const noexcept
234 return rectangle{*
this * rhs.origin, *
this * rhs.right, *
this * rhs.up};
237 [[nodiscard]]
constexpr quad operator*(quad
const& rhs)
const noexcept
239 return quad{*
this * rhs.p0, *
this * rhs.p1, *
this * rhs.p2, *
this * rhs.p3};
242 [[nodiscard]]
constexpr circle operator*(circle
const& rhs)
const noexcept
244 return circle{*
this * midpoint(rhs), *
this * rhs.radius()};
247 [[nodiscard]]
constexpr line_segment operator*(line_segment
const& rhs)
const noexcept
249 return line_segment{*
this * rhs.origin(), *
this * rhs.direction()};
260 _col0 *
static_cast<f32x4>(rhs).xxxx() + _col1 *
static_cast<f32x4>(rhs).yyyy() +
261 _col2 *
static_cast<f32x4>(rhs).zzzz() + _col3};
271 return matrix{*
this * get<0>(rhs), *
this * get<1>(rhs), *
this * get<2>(rhs), *
this * get<3>(rhs)};
278 auto tmp = transpose(rhs._col0, rhs._col1, rhs._col2, rhs._col3);
279 return {std::get<0>(tmp), std::get<1>(tmp), std::get<2>(tmp), std::get<3>(tmp)};
283 [[nodiscard]]
static constexpr f32x4 reflect_column() noexcept
285 if constexpr (Axis ==
'x') {
286 return f32x4{1.0f, 0.0f, 0.0f, 0.0f};
287 }
else if constexpr (Axis ==
'X') {
288 return f32x4{-1.0f, 0.0f, 0.0f, 0.0f};
289 }
else if constexpr (Axis ==
'y') {
290 return f32x4{0.0f, 1.0f, 0.0f, 0.0f};
291 }
else if constexpr (Axis ==
'Y') {
292 return f32x4{0.0f, -1.0f, 0.0f, 0.0f};
293 }
else if constexpr (Axis ==
'z') {
294 return f32x4{0.0f, 0.0f, 1.0f, 0.0f};
295 }
else if constexpr (Axis ==
'Z') {
296 return f32x4{0.0f, 0.0f, -1.0f, 0.0f};
297 }
else if constexpr (Axis ==
'w') {
298 return f32x4{0.0f, 0.0f, 0.0f, 1.0f};
299 }
else if constexpr (Axis ==
'W') {
300 return f32x4{0.0f, 0.0f, 0.0f, -1.0f};
337 template<
char DstX,
char DstY,
char DstZ,
char DstW = 'w'>
341 return matrix{reflect_column<DstX>(), reflect_column<DstY>(), reflect_column<DstZ>(), reflect_column<DstW>()} * rhs;
345 [[nodiscard]]
constexpr bool operator==(
matrix<E> const& rhs)
const noexcept
347 return _col0 == rhs._col0 && _col1 == rhs._col1 && _col2 == rhs._col2 && _col3 == rhs._col3;
359 hilet s0c0 = _col0 * _col1.yxwz();
365 hilet s1c1 = _col0 * _col2.yxwz();
366 hilet s0c0s1c1 = hsub(s0c0, s1c1);
372 hilet s2c2 = _col0 * _col3.yxwz();
378 hilet s3c3 = _col1 * _col2.yxwz();
379 hilet s2c2s3c3 = hsub(s2c2, s3c3);
385 hilet s4c4 = _col1 * _col3.yxwz();
391 hilet s5c5 = _col2 * _col3.yxwz();
392 hilet s4c4s5c5 = hsub(s4c4, s5c5);
400 hilet s0123 = s0c0s1c1.xz00() + s2c2s3c3._00xz();
401 hilet s45__ = s4c4s5c5.xz00();
403 hilet c5432 = s4c4s5c5.wy00() + s2c2s3c3._00wy();
404 hilet c10__ = s0c0s1c1.wy00();
406 hilet det_prod_half0 = neg<0b0010>(s0123 * c5432);
407 hilet det_prod_half1 = neg<0b0001>(s45__ * c10__);
409 hilet det_sum0 = hadd(det_prod_half0, det_prod_half1);
410 hilet det_sum1 = hadd(det_sum0, det_sum0);
411 hilet det = hadd(det_sum1, det_sum1).xxxx();
413 if (det.x() == 0.0f) {
417 hilet invdet = rcp(det);
419 hilet t = transpose(*
this);
426 auto tmp_c5543 = neg<0b1010>(c5432.xxyz());
427 auto tmp_c4221 = neg<0b0101>(c5432.yww0() + c10__._000x());
428 auto tmp_c3100 = neg<0b1010>(c5432.z000() + c10__._0xyy());
429 hilet inv_col0 = ((t._col1.yxxx() * tmp_c5543) + (t._col1.zzyy() * tmp_c4221) + (t._col1.wwwz() * tmp_c3100)) * invdet;
435 tmp_c5543 = -tmp_c5543;
436 tmp_c4221 = -tmp_c4221;
437 tmp_c3100 = -tmp_c3100;
438 hilet inv_col1 = ((t._col0.yxxx() * tmp_c5543) + (t._col0.zzyy() * tmp_c4221) + (t._col0.wwwz() * tmp_c3100)) * invdet;
444 auto tmp_s5543 = neg<0b1010>(s45__.yyx0() + s0123._000w());
445 auto tmp_s4221 = neg<0b0101>(s45__.x000() + s0123._0zzy());
446 auto tmp_s3100 = neg<0b1010>(s0123.wyxx());
447 hilet inv_col2 = ((t._col3.yxxx() * tmp_s5543) + (t._col3.zzyy() * tmp_s4221) + (t._col3.wwwz() * tmp_s3100)) * invdet;
453 tmp_s5543 = -tmp_s5543;
454 tmp_s4221 = -tmp_s4221;
455 tmp_s3100 = -tmp_s3100;
456 hilet inv_col3 = ((t._col2.yxxx() * tmp_s5543) + (t._col2.zzyy() * tmp_s4221) + (t._col2.wwwz() * tmp_s3100)) * invdet;
458 return {inv_col0, inv_col1, inv_col2, inv_col3};