DNA Calib 1.1
Project brief
Mat.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5#include "tdm/Types.h"
6#include "tdm/Vec.h"
7
8namespace tdm {
9
10template<dim_t R, dim_t C, typename T>
11inline mat<C, R, T> transpose(const mat<R, C, T>& m);
12
13template<dim_t N, typename T>
14inline mat<N, N, T> inverse(const mat<N, N, T>& m);
15
16template<dim_t R, dim_t C, typename T>
17struct mat {
18 using value_type = T;
21
22 static constexpr dim_t rows() {
24 }
25
26 static constexpr dim_t columns() {
27 return row_type::dimensions();
28 }
29
30 private:
32
33 public:
34 mat() : values{} {
35 }
36
37 ~mat() = default;
38
39 mat(const mat&) = default;
40 mat& operator=(const mat&) = default;
41
42 mat(mat&&) = default;
43 mat& operator=(mat&&) = default;
44
45 template<typename U>
46 explicit mat(U scalar) {
47 apply([scalar](row_type& row, dim_t /*unused*/) {
48 row = row_type{scalar};
49 });
50 }
51
52 template<typename ... Us, typename std::enable_if<sizeof...(Us) == R * C>::type* = nullptr>
53 mat(Us... scalars) {
54 T tmp[sizeof...(Us)] = {static_cast<T>(scalars)...};
55 apply([&tmp](row_type& row, dim_t ri) {
56 row.apply([&tmp, ri](value_type& value, dim_t ci) {
57 value = tmp[ri * columns() + ci];
58 });
59 });
60 }
61
62 template<typename U>
63 mat(const mat<R, C, U>& rhs) {
64 apply([&rhs](row_type& row, dim_t ri) {
65 row = rhs[ri];
66 });
67 }
68
69 template<typename U>
70 mat& operator=(const mat<R, C, U>& rhs) {
71 return operator=(mat<R, C, T>{rhs});
72 }
73
74 template<typename ... Us, typename std::enable_if<sizeof...(Us) == R>::type* = nullptr>
75 mat(const vec<C, Us>& ... vs) : values{row_type{vs} ...} {
76 }
77
78 template<typename ... Us, typename std::enable_if<sizeof...(Us) == R>::type * = nullptr>
79 static mat fromRows(const vec<C, Us>& ... vs) {
80 return mat{vs ...};
81 }
82
83 template<typename ... Us, typename std::enable_if<sizeof...(Us) == C>::type* = nullptr>
84 static mat fromColumns(const vec<R, Us>& ... vs) {
85 mat<sizeof...(vs), R, T> tmp{vs ...};
86 return tdm::transpose(tmp);
87 }
88
89 template<typename U, typename ..., dim_t H = R, dim_t W = C>
90 static typename std::enable_if<H == W, mat>::type diagonal(U scalar) {
91 mat ret;
92 ret.apply([scalar](row_type& row, dim_t ri) {
93 row[ri] = scalar;
94 });
95 return ret;
96 }
97
98 template<typename U, typename ..., dim_t H = R, dim_t W = C>
99 static typename std::enable_if<H == W, mat>::type diagonal(const vec<W, U>& scalars) {
100 mat ret;
101 ret.apply([&scalars](row_type& row, dim_t ri) {
102 row[ri] = scalars[ri];
103 });
104 return ret;
105 }
106
107 template<typename ... Us, dim_t H = R, dim_t W = C>
108 static typename std::enable_if<(H == W) && (sizeof...(Us) == H), mat>::type diagonal(Us... scalars) {
109 return diagonal(vec<R, T>{scalars ...});
110 }
111
112 template<typename ..., dim_t H = R, dim_t W = C>
113 static typename std::enable_if<H == W, mat>::type identity() {
114 return diagonal(static_cast<T>(1));
115 }
116
118 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay)
119 assert(index < rows());
120 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-constant-array-index)
121 return values[index];
122 }
123
124 const row_type& operator[](dim_t index) const {
125 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay)
126 assert(index < rows());
127 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-constant-array-index)
128 return values[index];
129 }
130
131 T& operator()(dim_t rowIndex, dim_t colIndex) {
132 return operator[](rowIndex)[colIndex];
133 }
134
135 const T& operator()(dim_t rowIndex, dim_t colIndex) const {
136 return operator[](rowIndex)[colIndex];
137 }
138
139 template<typename F>
140 mat& apply(F func) {
141 for (dim_t ri{}; ri != rows(); ++ri) {
142 func(values[ri], ri);
143 }
144 return *this;
145 }
146
147 template<typename F>
148 const mat& apply(F func) const {
149 for (dim_t ri{}; ri != rows(); ++ri) {
150 func(values[ri], ri);
151 }
152 return *this;
153 }
154
156 return apply([](row_type& row, dim_t /*unused*/) {
157 ++row;
158 });
159 }
160
162 return apply([](row_type& row, dim_t /*unused*/) {
163 --row;
164 });
165 }
166
167 template<typename U>
168 mat& operator+=(U rhs) {
169 return apply([rhs](row_type& row, dim_t /*unused*/) {
170 row += rhs;
171 });
172 }
173
174 template<typename U>
176 return apply([&rhs](row_type& row, dim_t ri) {
177 row += rhs[ri];
178 });
179 }
180
181 mat& operator+=(const mat& rhs) {
182 return operator+=<T>(rhs);
183 }
184
185 template<typename U>
186 mat& operator-=(U rhs) {
187 return apply([rhs](row_type& row, dim_t /*unused*/) {
188 row -= rhs;
189 });
190 }
191
192 template<typename U>
194 return apply([&rhs](row_type& row, dim_t ri) {
195 row -= rhs[ri];
196 });
197 }
198
199 mat& operator-=(const mat& rhs) {
200 return operator-=<T>(rhs);
201 }
202
203 template<typename U>
204 mat& operator*=(U rhs) {
205 return apply([rhs](row_type& row, dim_t /*unused*/) {
206 row *= rhs;
207 });
208 }
209
210 template<typename U>
212 return (*this = *this * rhs);
213 }
214
215 mat& operator*=(const mat& rhs) {
216 return operator*=<T>(rhs);
217 }
218
219 template<typename U>
220 mat& operator/=(U rhs) {
221 return apply([rhs](row_type& row, dim_t /*unused*/) {
222 row /= rhs;
223 });
224 }
225
226 template<typename U>
228 return operator*=(inverse(rhs));
229 }
230
231 mat& operator/=(const mat& rhs) {
232 return operator/=<T>(rhs);
233 }
234
235 template<typename ..., dim_t H = R, dim_t W = C>
236 typename std::enable_if<H == W, mat&>::type transpose() {
237 return (*this = tdm::transpose(*this));
238 }
239
241 apply([](row_type& row, dim_t /*unused*/) {
242 row.negate();
243 });
244 return *this;
245 }
246
247 row_type row(dim_t index) const {
248 return operator[](index);
249 }
250
251 column_type column(dim_t index) const {
252 column_type col;
253 apply([&col, index](const row_type& row, dim_t ri) {
254 col[ri] = row[index];
255 });
256 return col;
257 }
258
259 template<dim_t H, dim_t W>
260 typename std::enable_if<(H > 1 && W > 1 && H <= R && W <= C), mat<H, W, T> >::type submat(dim_t y, dim_t x) const {
261 assert(H + y <= rows());
262 assert(W + x <= columns());
263 mat<H, W, T> ret;
264 ret.apply([this, y, x](typename mat<H, W, T>::row_type& row, dim_t ri) {
265 row.apply([this, y, x, ri](value_type& value, dim_t ci) {
266 value = values[y + ri][x + ci];
267 });
268 });
269 return ret;
270 }
271
272};
273
274template<dim_t R, dim_t C, typename T>
275inline bool operator==(const mat<R, C, T>& lhs, const mat<R, C, T>& rhs) {
276 using row_type = typename mat<R, C, T>::row_type;
277 bool retval = true;
278 lhs.apply([&rhs, &retval](const row_type& row, dim_t ri) {
279 retval = retval && (row == rhs[ri]);
280 });
281 return retval;
282}
283
284template<dim_t R, dim_t C, typename T>
285inline bool operator!=(const mat<R, C, T>& lhs, const mat<R, C, T>& rhs) {
286 return !(lhs == rhs);
287}
288
289template<dim_t R, dim_t C, typename T>
291 return m;
292}
293
294template<dim_t R, dim_t C, typename T>
296 mat<R, C, T> ret{m};
297 ret.negate();
298 return ret;
299}
300
301template<dim_t R, dim_t C, typename T>
302inline mat<R, C, T> operator+(const mat<R, C, T>& lhs, T rhs) {
303 return mat<R, C, T>(lhs) += rhs;
304}
305
306template<dim_t R, dim_t C, typename T>
307inline mat<R, C, T> operator+(T lhs, const mat<R, C, T>& rhs) {
308 return mat<R, C, T>(lhs) += rhs;
309}
310
311template<dim_t R, dim_t C, typename T>
312inline mat<R, C, T> operator+(const mat<R, C, T>& lhs, const mat<R, C, T>& rhs) {
313 return mat<R, C, T>(lhs) += rhs;
314}
315
316template<dim_t R, dim_t C, typename T>
317inline mat<R, C, T> operator-(const mat<R, C, T>& lhs, T rhs) {
318 return mat<R, C, T>(lhs) -= rhs;
319}
320
321template<dim_t R, dim_t C, typename T>
322inline mat<R, C, T> operator-(T lhs, const mat<R, C, T>& rhs) {
323 return mat<R, C, T>(lhs) -= rhs;
324}
325
326template<dim_t R, dim_t C, typename T>
327inline mat<R, C, T> operator-(const mat<R, C, T>& lhs, const mat<R, C, T>& rhs) {
328 return mat<R, C, T>(lhs) -= rhs;
329}
330
331template<dim_t R, dim_t C, typename T>
332inline mat<R, C, T> operator*(const mat<R, C, T>& lhs, T rhs) {
333 return mat<R, C, T>(lhs) *= rhs;
334}
335
336template<dim_t R, dim_t C, typename T>
337inline mat<R, C, T> operator*(T lhs, const mat<R, C, T>& rhs) {
338 return mat<R, C, T>(rhs) *= lhs;
339}
340
341template<dim_t R, dim_t C, typename T>
342inline typename mat<R, C, T>::row_type operator*(const typename mat<R, C, T>::column_type& lhs, const mat<R, C, T>& rhs) {
343 using row_type = typename mat<R, C, T>::row_type;
344 row_type ret;
345 rhs.apply([&ret, &lhs](const row_type& row, dim_t ri) {
346 ret += (row * row_type{lhs[ri]});
347 });
348 return ret;
349}
350
351template<dim_t R, dim_t C, typename T>
352inline typename mat<R, C, T>::column_type operator*(const mat<R, C, T>& lhs, const typename mat<R, C, T>::row_type& rhs) {
353 using column_type = typename mat<R, C, T>::column_type;
354 using value_type = typename column_type::value_type;
355 column_type ret;
356 rhs.apply([&ret, &lhs](value_type value, dim_t ci) {
357 ret += (lhs.column(ci) * column_type{value});
358 });
359 return ret;
360}
361
362template<dim_t R, dim_t S, dim_t C, typename T>
363inline mat<R, C, T> operator*(const mat<R, S, T>& lhs, const mat<S, C, T>& rhs) {
364 using row_type = typename mat<R, C, T>::row_type;
365 mat<R, C, T> ret;
366 ret.apply([&lhs, &rhs](row_type& row, dim_t ri) {
367 row = (lhs[ri] * rhs);
368 });
369 return ret;
370}
371
372template<dim_t R, dim_t C, typename T>
373inline mat<R, C, T> operator/(const mat<R, C, T>& lhs, T rhs) {
374 return mat<R, C, T>(lhs) /= rhs;
375}
376
377template<dim_t R, dim_t C, typename T>
378inline mat<R, C, T> operator/(T lhs, const mat<R, C, T>& rhs) {
379 using row_type = typename mat<R, C, T>::row_type;
380 mat<R, C, T> tmp{rhs};
381 tmp.apply([lhs](row_type& row, dim_t /*unused*/) {
382 row = lhs / row;
383 });
384 return tmp;
385}
386
387template<dim_t R, dim_t C, typename T>
388inline typename mat<R, C, T>::row_type operator/(const typename mat<R, C, T>::column_type& lhs, const mat<R, C, T>& rhs) {
389 return (lhs * inverse(rhs));
390}
391
392template<dim_t R, dim_t C, typename T>
393inline typename mat<R, C, T>::column_type operator/(const mat<R, C, T>& lhs, const typename mat<R, C, T>::row_type& rhs) {
394 return (inverse(lhs) * rhs);
395}
396
397template<dim_t R, dim_t C, typename T>
398inline mat<R, C, T> operator/(const mat<R, C, T>& lhs, const mat<R, C, T>& rhs) {
399 return mat<R, C, T>(lhs) /= rhs;
400}
401
402} // namespace tdm
Definition: Computations.h:19
std::size_t dim_t
Definition: Types.h:22
bool operator!=(const mat< R, C, T > &lhs, const mat< R, C, T > &rhs)
Definition: Mat.h:285
bool operator==(const mat< R, C, T > &lhs, const mat< R, C, T > &rhs)
Definition: Mat.h:275
mat< R, C, T > operator*(const mat< R, C, T > &lhs, T rhs)
Definition: Mat.h:332
mat< R, C, T > operator/(const mat< R, C, T > &lhs, T rhs)
Definition: Mat.h:373
mat< R, C, T > operator-(const mat< R, C, T > &m)
Definition: Mat.h:295
mat< C, R, T > transpose(const mat< R, C, T > &m)
Definition: Computations.h:57
mat< R, C, T > operator+(const mat< R, C, T > &m)
Definition: Mat.h:290
mat< N, N, T > inverse(const mat< N, N, T > &m)
Definition: Computations.h:134
Definition: Mat.h:17
std::enable_if< H==W, mat & >::type transpose()
Definition: Mat.h:236
static constexpr dim_t columns()
Definition: Mat.h:26
mat & operator/=(const mat< R, C, U > &rhs)
Definition: Mat.h:227
const mat & apply(F func) const
Definition: Mat.h:148
~mat()=default
mat & operator/=(U rhs)
Definition: Mat.h:220
row_type values[R]
Definition: Mat.h:31
static std::enable_if< H==W, mat >::type identity()
Definition: Mat.h:113
mat & operator*=(const mat< R, C, U > &rhs)
Definition: Mat.h:211
row_type & operator[](dim_t index)
Definition: Mat.h:117
mat & operator-=(const mat &rhs)
Definition: Mat.h:199
mat & operator-=(U rhs)
Definition: Mat.h:186
mat & operator+=(const mat &rhs)
Definition: Mat.h:181
T & operator()(dim_t rowIndex, dim_t colIndex)
Definition: Mat.h:131
column_type column(dim_t index) const
Definition: Mat.h:251
mat(const mat< R, C, U > &rhs)
Definition: Mat.h:63
const T & operator()(dim_t rowIndex, dim_t colIndex) const
Definition: Mat.h:135
mat(const mat &)=default
static std::enable_if< H==W, mat >::type diagonal(U scalar)
Definition: Mat.h:90
row_type row(dim_t index) const
Definition: Mat.h:247
mat & apply(F func)
Definition: Mat.h:140
mat & operator--()
Definition: Mat.h:161
mat & operator=(const mat &)=default
static std::enable_if<(H==W)&&(sizeof...(Us)==H), mat >::type diagonal(Us... scalars)
Definition: Mat.h:108
mat()
Definition: Mat.h:34
mat(const vec< C, Us > &... vs)
Definition: Mat.h:75
mat & operator+=(U rhs)
Definition: Mat.h:168
mat(Us... scalars)
Definition: Mat.h:53
mat & operator*=(const mat &rhs)
Definition: Mat.h:215
mat & operator=(const mat< R, C, U > &rhs)
Definition: Mat.h:70
static mat fromColumns(const vec< R, Us > &... vs)
Definition: Mat.h:84
mat & negate()
Definition: Mat.h:240
mat & operator=(mat &&)=default
const row_type & operator[](dim_t index) const
Definition: Mat.h:124
static std::enable_if< H==W, mat >::type diagonal(const vec< W, U > &scalars)
Definition: Mat.h:99
mat & operator+=(const mat< R, C, U > &rhs)
Definition: Mat.h:175
mat & operator/=(const mat &rhs)
Definition: Mat.h:231
mat(mat &&)=default
static constexpr dim_t rows()
Definition: Mat.h:22
T value_type
Definition: Mat.h:18
mat(U scalar)
Definition: Mat.h:46
mat & operator-=(const mat< R, C, U > &rhs)
Definition: Mat.h:193
std::enable_if<(H >1 &&W >1 &&H<=R &&W<=C), mat< H, W, T > >::type submat(dim_t y, dim_t x) const
Definition: Mat.h:260
mat & operator++()
Definition: Mat.h:155
static mat fromRows(const vec< C, Us > &... vs)
Definition: Mat.h:79
mat & operator*=(U rhs)
Definition: Mat.h:204
static constexpr dim_t dimensions()
Definition: Vec.h:13
vec & apply(F func)
Definition: Vec.h:68
vec & negate()
Definition: Vec.h:178