-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathp3a_matrix2x2.hpp
145 lines (132 loc) · 3.62 KB
/
p3a_matrix2x2.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#pragma once
#include "p3a_vector2.hpp"
namespace p3a {
template <class T>
class matrix2x2 {
T m_xx;
T m_xy;
T m_yx;
T m_yy;
public:
P3A_ALWAYS_INLINE constexpr matrix2x2() = default;
P3A_HOST_DEVICE P3A_ALWAYS_INLINE constexpr
matrix2x2(
T const& a, T const& b,
T const& c, T const& d)
:m_xx(a)
,m_xy(b)
,m_yx(c)
,m_yy(d)
{
}
[[nodiscard]] P3A_HOST_DEVICE P3A_ALWAYS_INLINE constexpr
T const& xx() const { return m_xx; }
[[nodiscard]] P3A_HOST_DEVICE P3A_ALWAYS_INLINE constexpr
T const& xy() const { return m_xy; }
[[nodiscard]] P3A_HOST_DEVICE P3A_ALWAYS_INLINE constexpr
T const& yx() const { return m_yx; }
[[nodiscard]] P3A_HOST_DEVICE P3A_ALWAYS_INLINE constexpr
T const& yy() const { return m_yy; }
[[nodiscard]] P3A_HOST_DEVICE P3A_ALWAYS_INLINE constexpr
T& xx() { return m_xx; }
[[nodiscard]] P3A_HOST_DEVICE P3A_ALWAYS_INLINE constexpr
T& xy() { return m_xy; }
[[nodiscard]] P3A_HOST_DEVICE P3A_ALWAYS_INLINE constexpr
T& yx() { return m_yx; }
[[nodiscard]] P3A_HOST_DEVICE P3A_ALWAYS_INLINE constexpr
T& yy() { return m_yy; }
[[nodiscard]] P3A_HOST_DEVICE P3A_ALWAYS_INLINE static constexpr
matrix2x2<T> zero()
{
return matrix2x2<T>(
T(0), T(0),
T(0), T(0));
}
};
template <class T>
P3A_HOST_DEVICE P3A_ALWAYS_INLINE constexpr
void operator+=(matrix2x2<T>& a, matrix2x2<T> const& b)
{
a.xx() += b.xx();
a.xy() += b.xy();
a.yx() += b.yx();
a.yy() += b.yy();
}
template <class A, class B>
[[nodiscard]] P3A_HOST_DEVICE P3A_ALWAYS_INLINE constexpr
typename std::enable_if<is_scalar<B>, matrix2x2<decltype(A() / B())>>::type
operator/(matrix2x2<A> const& a, B const& b)
{
using result_type = decltype(a.xx() / b);
return matrix2x2<result_type>(
a.xx() / b, a.xy() / b,
a.yx() / b, a.yy() / b);
}
template <class A, class B>
[[nodiscard]] P3A_HOST_DEVICE P3A_ALWAYS_INLINE constexpr
auto operator*(matrix2x2<A> const& a, vector2<B> const& b)
{
using result_type = decltype(a.xx() * b.x());
return vector2<result_type>(
a.xx() * b.x() + a.xy() * b.y(),
a.yx() * b.x() + a.yy() * b.y());
}
template <class A, class B>
[[nodiscard]] P3A_HOST_DEVICE P3A_ALWAYS_INLINE constexpr
auto outer_product(vector2<A> const& a, vector2<B> const& b)
{
using result_type = decltype(a.x() * b.x());
return matrix2x2<result_type>(
a.x() * b.x(), a.x() * b.y(),
a.y() * b.x(), a.y() * b.y());
}
template <class T>
[[nodiscard]] P3A_HOST_DEVICE P3A_ALWAYS_INLINE constexpr
auto determinant(matrix2x2<T> const& m)
{
T const& a = m.xx();
T const& b = m.xy();
T const& c = m.yx();
T const& d = m.yy();
return (a * d) - (b * c);
}
template <class T>
[[nodiscard]] P3A_HOST_DEVICE P3A_ALWAYS_INLINE constexpr
auto adjugate(matrix2x2<T> const& m)
{
T const& a = m.xx();
T const& b = m.xy();
T const& c = m.yx();
T const& d = m.yy();
return matrix2x2<T>(
d, -b,
-c, a);
}
template <class T>
[[nodiscard]] P3A_HOST_DEVICE P3A_ALWAYS_INLINE constexpr
auto inverse(matrix2x2<T> const& m)
{
return adjugate(m) / determinant(m);
}
template <class T>
[[nodiscard]] P3A_HOST_DEVICE P3A_ALWAYS_INLINE constexpr
matrix2x2<T> transpose(matrix2x2<T> const& m)
{
return matrix2x2<T>(
m.xx(), m.yx(),
m.xy(), m.yy());
}
template <class A, class B>
[[nodiscard]] P3A_ALWAYS_INLINE P3A_HOST_DEVICE inline constexpr
auto operator*(
matrix2x2<A> const& a,
matrix2x2<B> const& b)
{
using C = decltype(a.xx() * b.xx());
return matrix2x2<C>(
a.xx() * b.xx() + a.xy() * b.yx(),
a.xx() * b.xy() + a.xy() * b.yy(),
a.yx() * b.xx() + a.yy() * b.yx(),
a.yx() * b.xy() + a.yy() * b.yy());
}
}