20 using value_type = Scalar;
62 values_(std::move(row_major)) {}
64 constexpr bool operator==(
const Matrix3x3T &rhs)
const {
65 return values_ == rhs.values_;
74 constexpr static uint_fast8_t
indexof(uint_fast8_t r, uint_fast8_t c) {
78 constexpr const Scalar &operator() (uint_fast8_t r, uint_fast8_t c)
const {
82 Scalar &operator() (uint_fast8_t r, uint_fast8_t c) {
87 constexpr const Scalar &
operator[] (uint_fast8_t i)
const {
96 Vec3 getRow(uint_fast8_t r)
const {
97 return Vec3((*
this)(r,0), (*
this)(r,1), (*
this)(r,2));
99 void setRow(uint_fast8_t r,
const Vec3 &v) {
100 for (uint_fast8_t c = 0; c < 3; ++c) {
101 (*this)(r, c) = v[c];
104 Vec3 getCol(uint_fast8_t c)
const {
105 return Vec3((*
this)(0,c), (*
this)(1,c), (*
this)(2,c));
107 void setCol(uint_fast8_t c,
const Vec3 &v) {
108 for (uint_fast8_t r = 0; r < 3; ++r) {
109 (*this)(r, c) = v[r];
113 constexpr Matrix3x3T operator*(
const Matrix3x3T &rhs)
const {
115 (*this)(0, 0) * rhs(0, 0) + (*this)(0, 1) * rhs(1, 0) + (*this)(0, 2) * rhs(2, 0),
116 (*this)(0, 0) * rhs(0, 1) + (*this)(0, 1) * rhs(1, 1) + (*this)(0, 2) * rhs(2, 1),
117 (*this)(0, 0) * rhs(0, 2) + (*this)(0, 1) * rhs(1, 2) + (*this)(0, 2) * rhs(2, 2),
119 (*this)(1, 0) * rhs(0, 0) + (*this)(1, 1) * rhs(1, 0) + (*this)(1, 2) * rhs(2, 0),
120 (*this)(1, 0) * rhs(0, 1) + (*this)(1, 1) * rhs(1, 1) + (*this)(1, 2) * rhs(2, 1),
121 (*this)(1, 0) * rhs(0, 2) + (*this)(1, 1) * rhs(1, 2) + (*this)(1, 2) * rhs(2, 2),
123 (*this)(2, 0) * rhs(0, 0) + (*this)(2, 1) * rhs(1, 0) + (*this)(2, 2) * rhs(2, 0),
124 (*this)(2, 0) * rhs(0, 1) + (*this)(2, 1) * rhs(1, 1) + (*this)(2, 2) * rhs(2, 1),
125 (*this)(2, 0) * rhs(0, 2) + (*this)(2, 1) * rhs(1, 2) + (*this)(2, 2) * rhs(2, 2),
129 template<
typename OtherScalar>
130 constexpr auto operator*(
const VectorT<OtherScalar,3> &rhs)
const
134 (*this)(0, 0) * rhs[0] + (*
this)(0, 1) * rhs[1] + (*
this)(0, 2) * rhs[2],
135 (*
this)(1, 0) * rhs[0] + (*
this)(1, 1) * rhs[1] + (*
this)(1, 2) * rhs[2],
136 (*
this)(2, 0) * rhs[0] + (*
this)(2, 1) * rhs[1] + (*
this)(2, 2) * rhs[2]
140 template<
typename OtherScalar>
141 constexpr friend auto operator*(VectorT<OtherScalar,3> v,
const Matrix3x3T &rhs)
145 rhs(0, 0) * v[0] + rhs(0, 1) * v[1] + rhs(0, 2) * v[2],
146 rhs(1, 0) * v[0] + rhs(1, 1) * v[1] + rhs(1, 2) * v[2],
147 rhs(2, 0) * v[0] + rhs(2, 1) * v[1] + rhs(2, 2) * v[2]
151 constexpr Matrix3x3T operator*(Scalar c)
const {
153 (*this)[0] * c, (*this)[1] * c, (*this)[2] * c,
154 (*this)[3] * c, (*this)[4] * c, (*this)[5] * c,
155 (*this)[6] * c, (*this)[7] * c, (*this)[8] * c,
159 constexpr friend Matrix3x3T operator*(Scalar c,
const Matrix3x3T &rhs) {
161 rhs[0] * c, rhs[1] * c, rhs[2] * c,
162 rhs[3] * c, rhs[4] * c, rhs[5] * c,
163 rhs[6] * c, rhs[7] * c, rhs[8] * c,
167 constexpr Matrix3x3T operator+ (
const Matrix3x3T &rhs)
const {
169 (*this)[0] + rhs[0], (*this)[1] + rhs[1], (*this)[2] + rhs[2],
170 (*this)[3] + rhs[3], (*this)[4] + rhs[4], (*this)[5] + rhs[5],
171 (*this)[6] + rhs[6], (*this)[7] + rhs[7], (*this)[8] + rhs[8],
175 constexpr Matrix3x3T operator- (
const Matrix3x3T &rhs)
const {
177 (*this)[0] - rhs[0], (*this)[1] - rhs[1], (*this)[2] - rhs[2],
178 (*this)[3] - rhs[3], (*this)[4] - rhs[4], (*this)[5] - rhs[5],
179 (*this)[6] - rhs[6], (*this)[7] - rhs[7], (*this)[8] - rhs[8],
183 constexpr Matrix3x3T operator- ()
const {
185 -values_[0], -values_[1], -values_[2],
186 -values_[3], -values_[4], -values_[5],
187 -values_[6], -values_[7], -values_[8]
191 const Matrix3x3T &operator*=(
const Matrix3x3T &rhs) {
192 (*this) = operator*(rhs);
196 constexpr Scalar det()
const {
197 return (*
this)(0, 0) * ((*
this)(1, 1) * (*
this)(2, 2) - (*
this)(2, 1) * (*
this)(1, 2)) -
198 (*this)(0, 1) * ((*
this)(1, 0) * (*
this)(2, 2) - (*
this)(1, 2) * (*
this)(2, 0)) +
199 (*this)(0, 2) * ((*
this)(1, 0) * (*
this)(2, 1) - (*
this)(1, 1) * (*
this)(2, 0));
211 constexpr Scalar trace()
const {
212 return (*
this)[0] + (*this)[4] + (*this)[8];
216 std::swap(values_[1], values_[3]);
217 std::swap(values_[2], values_[6]);
218 std::swap(values_[5], values_[7]);
221 constexpr Matrix3x3T transposed()
const {
223 values_[0], values_[3], values_[6],
224 values_[1], values_[4], values_[7],
225 values_[2], values_[5], values_[8],
233 Matrix3x3T inverse()
const {
234 const Scalar invdet = 1.0 / det();
236 ((*this)(1, 1) * (*
this)(2, 2) - (*
this)(2, 1) * (*
this)(1, 2)) * invdet,
237 ((*this)(0, 2) * (*
this)(2, 1) - (*
this)(0, 1) * (*
this)(2, 2)) * invdet,
238 ((*this)(0, 1) * (*
this)(1, 2) - (*
this)(0, 2) * (*
this)(1, 1)) * invdet,
239 ((*this)(1, 2) * (*
this)(2, 0) - (*
this)(1, 0) * (*
this)(2, 2)) * invdet,
240 ((*this)(0, 0) * (*
this)(2, 2) - (*
this)(0, 2) * (*
this)(2, 0)) * invdet,
241 ((*this)(1, 0) * (*
this)(0, 2) - (*
this)(0, 0) * (*
this)(1, 2)) * invdet,
242 ((*this)(1, 0) * (*
this)(2, 1) - (*
this)(2, 0) * (*
this)(1, 1)) * invdet,
243 ((*this)(2, 0) * (*
this)(0, 1) - (*
this)(0, 0) * (*
this)(2, 1)) * invdet,
244 ((*this)(0, 0) * (*
this)(1, 1) - (*
this)(1, 0) * (*
this)(0, 1)) * invdet,
248 constexpr Scalar frobeniusSquared()
const {
249 return std::inner_product(
250 values_.begin(), values_.end(), values_.begin(), Scalar(0.0));
253 constexpr double frobenius()
const {
254 return std::sqrt(frobeniusSquared());
259 std::ostream &operator<< (std::ostream &os,
const Matrix3x3T &m) {
260 os <<
"[[" << m[0] <<
", " << m[1] <<
", " << m[2] <<
"], "
261 "[" << m[3] <<
", " << m[4] <<
", " << m[5] <<
"], "
262 "[" << m[6] <<
", " << m[7] <<
", " << m[8] <<
"]]";
267 std::array<Scalar, 9> values_;