Mathter
A configurable 3D math library for game developers.
MatrixArithmetic.hpp
Go to the documentation of this file.
1 #pragma once
2 
3 #include "MatrixImpl.hpp"
4 
5 namespace mathter {
6 
7 // Macros for manual matrix multiplication loop unrolling
8 
9 // Row-major * Row-major
10 #define MATHTER_MATMUL_EXPAND(...) __VA_ARGS__
11 
12 #define MATHTER_MATMUL_RR_FACTOR(X, Y) rhs.stripes[X] * lhs(Y, X)
13 
14 #define MATHTER_MATMUL_RR_STRIPE_1(Y) MATHTER_MATMUL_RR_FACTOR(0, Y)
15 #define MATHTER_MATMUL_RR_STRIPE_2(Y) MATHTER_MATMUL_RR_STRIPE_1(Y) + MATHTER_MATMUL_RR_FACTOR(1, Y)
16 #define MATHTER_MATMUL_RR_STRIPE_3(Y) MATHTER_MATMUL_RR_STRIPE_2(Y) + MATHTER_MATMUL_RR_FACTOR(2, Y)
17 #define MATHTER_MATMUL_RR_STRIPE_4(Y) MATHTER_MATMUL_RR_STRIPE_3(Y) + MATHTER_MATMUL_RR_FACTOR(3, Y)
18 #define MATHTER_MATMUL_RR_STRIPE(CX, Y) \
19  MATHTER_MATMUL_EXPAND(MATHTER_MATMUL_RR_STRIPE_##CX) \
20  (Y)
21 
22 #define MATHTER_MATMUL_RR_ARRAY_1(CX) result.stripes[0] = MATHTER_MATMUL_RR_STRIPE(CX, 0);
23 #define MATHTER_MATMUL_RR_ARRAY_2(CX) \
24  MATHTER_MATMUL_RR_ARRAY_1(CX) \
25  result.stripes[1] = MATHTER_MATMUL_RR_STRIPE(CX, 1);
26 #define MATHTER_MATMUL_RR_ARRAY_3(CX) \
27  MATHTER_MATMUL_RR_ARRAY_2(CX) \
28  result.stripes[2] = MATHTER_MATMUL_RR_STRIPE(CX, 2);
29 #define MATHTER_MATMUL_RR_ARRAY_4(CX) \
30  MATHTER_MATMUL_RR_ARRAY_3(CX) \
31  result.stripes[3] = MATHTER_MATMUL_RR_STRIPE(CX, 3);
32 
33 #define MATHTER_MATMUL_RR_ARRAY(CX, CY) \
34  MATHTER_MATMUL_EXPAND(MATHTER_MATMUL_RR_ARRAY_##CY) \
35  (CX)
36 
37 #define MATHTER_MATMUL_RR_UNROLL(MATCH, ROWS1) \
38  if (Rows1 == ROWS1 && Match == MATCH) { \
39  MATHTER_MATMUL_RR_ARRAY(MATCH, ROWS1) \
40  return result; \
41  }
42 
43 // Column-major * Column-major
44 #define MATHTER_MATMUL_CC_FACTOR(X, Y) lhs.stripes[Y] * rhs(Y, X)
45 
46 #define MATHTER_MATMUL_CC_STRIPE_1(X) MATHTER_MATMUL_CC_FACTOR(X, 0)
47 #define MATHTER_MATMUL_CC_STRIPE_2(X) MATHTER_MATMUL_CC_STRIPE_1(X) + MATHTER_MATMUL_CC_FACTOR(X, 1)
48 #define MATHTER_MATMUL_CC_STRIPE_3(X) MATHTER_MATMUL_CC_STRIPE_2(X) + MATHTER_MATMUL_CC_FACTOR(X, 2)
49 #define MATHTER_MATMUL_CC_STRIPE_4(X) MATHTER_MATMUL_CC_STRIPE_3(X) + MATHTER_MATMUL_CC_FACTOR(X, 3)
50 #define MATHTER_MATMUL_CC_STRIPE(CY, X) \
51  MATHTER_MATMUL_EXPAND(MATHTER_MATMUL_CC_STRIPE_##CY) \
52  (X)
53 
54 #define MATHTER_MATMUL_CC_ARRAY_1(CY) result.stripes[0] = MATHTER_MATMUL_CC_STRIPE(CY, 0);
55 #define MATHTER_MATMUL_CC_ARRAY_2(CY) \
56  MATHTER_MATMUL_CC_ARRAY_1(CY) \
57  result.stripes[1] = MATHTER_MATMUL_CC_STRIPE(CY, 1);
58 #define MATHTER_MATMUL_CC_ARRAY_3(CY) \
59  MATHTER_MATMUL_CC_ARRAY_2(CY) \
60  result.stripes[2] = MATHTER_MATMUL_CC_STRIPE(CY, 2);
61 #define MATHTER_MATMUL_CC_ARRAY_4(CY) \
62  MATHTER_MATMUL_CC_ARRAY_3(CY) \
63  result.stripes[3] = MATHTER_MATMUL_CC_STRIPE(CY, 3);
64 
65 #define MATHTER_MATMUL_CC_ARRAY(CX, CY) \
66  MATHTER_MATMUL_EXPAND(MATHTER_MATMUL_CC_ARRAY_##CX) \
67  (CY)
68 
69 #define MATHTER_MATMUL_CC_UNROLL(COLUMNS2, MATCH) \
70  if (Columns2 == COLUMNS2 && Match == MATCH) { \
71  MATHTER_MATMUL_CC_ARRAY(COLUMNS2, MATCH) \
72  return result; \
73  }
74 
75 
76 
77 template <class T, class U, int Rows1, int Match, int Columns2, eMatrixOrder Order1, eMatrixOrder Order2, bool Packed, class V>
82 
86 
90 
94 
95  // general algorithm
96  for (int i = 0; i < Rows1; ++i) {
97  result.stripes[i] = rhs.stripes[0] * lhs(i, 0);
98  }
99  for (int i = 0; i < Rows1; ++i) {
100  for (int j = 1; j < Match; ++j) {
101  result.stripes[i] += rhs.stripes[j] * lhs(i, j);
102  }
103  }
104 
105  return result;
106 }
107 
108 template <class T, class U, int Rows1, int Match, int Columns2, eMatrixOrder Order1, eMatrixOrder Order2, bool Packed, class V>
113 
114  for (int j = 0; j < Columns2; ++j) {
115  for (int i = 0; i < Rows1; ++i) {
116  result(i, j) = Dot(lhs.stripes[i], rhs.stripes[j]);
117  }
118  }
119 
120  return result;
121 }
122 
123 template <class T, class U, int Rows1, int Match, int Columns2, eMatrixOrder Order1, eMatrixOrder Order2, bool Packed, class V>
128 
132 
136 
140 
141  // general algorithm
142  for (int j = 0; j < Columns2; ++j) {
143  result.stripes[j] = lhs.stripes[0] * rhs(0, j);
144  }
145  for (int i = 1; i < Match; ++i) {
146  for (int j = 0; j < Columns2; ++j) {
147  result.stripes[j] += lhs.stripes[i] * rhs(i, j);
148  }
149  }
150 
151  return result;
152 }
153 
154 template <class T, class U, int Rows1, int Match, int Columns2, eMatrixOrder Order1, eMatrixOrder Order2, bool Packed, class V>
159 
163 
167 
171 
172  // general algorithm
173  // CC algorithm is completely fine for COL_MAJOR x ROW_MAJOR
174  // see that rhs is only indexed per-element, so its layout does not matter
175  for (int j = 0; j < Columns2; ++j) {
176  result.stripes[j] = lhs.stripes[0] * rhs(0, j);
177  }
178  for (int i = 1; i < Match; ++i) {
179  for (int j = 0; j < Columns2; ++j) {
180  result.stripes[j] += lhs.stripes[i] * rhs(i, j);
181  }
182  }
183 
184  return result;
185 }
186 
187 
188 template <class T1, class T2, int Rows1, int Match, int Columns2, eMatrixOrder Order1, eMatrixOrder Order2, eMatrixLayout Layout1, eMatrixLayout Layout2, bool PackedA>
191  -> Matrix<traits::MatMulElemT<T1, T2>, Rows1, Columns2, Order1, Layout1, PackedA> {
192  return mathter::operator*<T1, T2, Rows1, Match, Columns2, Order1, Order2, PackedA, traits::MatMulElemT<T1, T2>>(lhs, rhs);
193 }
194 
195 
196 // Assign-multiply
197 template <class T1, class T2, int Dim, eMatrixOrder Order1, eMatrixOrder Order2, eMatrixLayout Layout1, eMatrixLayout Layout2, bool Packed>
199  lhs = operator*<T1, T2, Dim, Dim, Dim, Order1, Order2, Packed, T1>(lhs, rhs);
200  return lhs;
201 }
202 
203 #define MATHTER_MATADD_SAME_ARRAY_1(OP) result.stripes[0] = lhs.stripes[0] OP rhs.stripes[0];
204 #define MATHTER_MATADD_SAME_ARRAY_2(OP) \
205  MATHTER_MATADD_SAME_ARRAY_1(OP) \
206  result.stripes[1] = lhs.stripes[1] OP rhs.stripes[1];
207 #define MATHTER_MATADD_SAME_ARRAY_3(OP) \
208  MATHTER_MATADD_SAME_ARRAY_2(OP) \
209  result.stripes[2] = lhs.stripes[2] OP rhs.stripes[2];
210 #define MATHTER_MATADD_SAME_ARRAY_4(OP) \
211  MATHTER_MATADD_SAME_ARRAY_3(OP) \
212  result.stripes[3] = lhs.stripes[3] OP rhs.stripes[3];
213 #define MATHTER_MATADD_SAME_UNROLL(S, OP) \
214  if (result.StripeCount == S) { \
215  MATHTER_MATMUL_EXPAND(MATHTER_MATADD_SAME_ARRAY_##S) \
216  (OP) return result; \
217  }
218 
219 
220 // Add & sub same layout
221 template <class T, class U, int Rows, int Columns, eMatrixOrder Order1, eMatrixOrder Order2, eMatrixLayout SameLayout, bool Packed, class V = decltype(T() + U())>
226 
231 
232  for (int i = 0; i < result.StripeCount; ++i) {
233  result.stripes[i] = lhs.stripes[i] + rhs.stripes[i];
234  }
235  return result;
236 }
237 
238 template <class T, class U, int Rows, int Columns, eMatrixOrder Order1, eMatrixOrder Order2, eMatrixLayout SameLayout, bool Packed, class V = decltype(T() - U())>
243 
248 
249  for (int i = 0; i < result.StripeCount; ++i) {
250  result.stripes[i] = lhs.stripes[i] - rhs.stripes[i];
251  }
252  return result;
253 }
254 
255 
256 // Add & sub opposite layout
257 template <class T, class U, int Rows, int Columns, eMatrixOrder Order1, eMatrixOrder Order2, eMatrixLayout Layout1, eMatrixLayout Layout2, bool Packed, class V, class = typename std::enable_if<Layout1 != Layout2>::type>
262  for (int i = 0; i < result.RowCount(); ++i) {
263  for (int j = 0; j < result.ColumnCount(); ++j) {
264  result(i, j) = lhs(i, j) + rhs(i, j);
265  }
266  }
267  return result;
268 }
269 
270 template <class T, class U, int Rows, int Columns, eMatrixOrder Order1, eMatrixOrder Order2, eMatrixLayout Layout1, eMatrixLayout Layout2, bool Packed, class V, class = typename std::enable_if<Layout1 != Layout2>::type>
275  for (int i = 0; i < result.RowCount(); ++i) {
276  for (int j = 0; j < result.ColumnCount(); ++j) {
277  result(i, j) = lhs(i, j) - rhs(i, j);
278  }
279  }
280  return result;
281 }
282 
283 
284 
286 template <class T, class U, int Rows, int Columns, eMatrixOrder Order1, eMatrixOrder Order2, eMatrixLayout Layout1, eMatrixLayout Layout2, bool Packed, class V>
290  lhs = lhs + rhs;
291  return lhs;
292 }
293 
295 template <class T, class U, int Rows, int Columns, eMatrixOrder Order1, eMatrixOrder Order2, eMatrixLayout Layout1, eMatrixLayout Layout2, bool Packed, class V>
299  lhs = lhs - rhs;
300  return lhs;
301 }
302 
303 
304 
305 //------------------------------------------------------------------------------
306 // Matrix-Scalar arithmetic
307 //------------------------------------------------------------------------------
308 
309 
310 // Scalar multiplication
312 template <class T, int Rows, int Columns, eMatrixOrder Order, eMatrixLayout Layout, bool Packed>
314  for (auto& stripe : mat.stripes) {
315  stripe *= s;
316  }
317  return mat;
318 }
320 template <class T, int Rows, int Columns, eMatrixOrder Order, eMatrixLayout Layout, bool Packed>
322  mat *= T(1 / s);
323  return mat;
324 }
325 
326 
327 template <class T, int Rows, int Columns, eMatrixOrder Order, eMatrixLayout Layout, bool Packed>
329  return mat * s;
330 }
331 
332 template <class T, int Rows, int Columns, eMatrixOrder Order, eMatrixLayout Layout, bool Packed>
334  return mat / s;
335 }
336 
337 template <class T, int Rows, int Columns, eMatrixOrder Order, eMatrixLayout Layout, bool Packed>
340  copy *= s;
341  return copy;
342 }
343 
344 template <class T, int Rows, int Columns, eMatrixOrder Order, eMatrixLayout Layout, bool Packed>
347  copy /= s;
348  return copy;
349 }
350 
351 
352 //------------------------------------------------------------------------------
353 // Elementwise multiply and divide
354 //------------------------------------------------------------------------------
355 template <class T, class T2, int Rows, int Columns, eMatrixOrder Order, eMatrixOrder Order2, eMatrixLayout Layout, bool Packed>
358  for (int i = 0; i < result.StripeCount; ++i) {
359  result.stripes[i] = lhs.stripes[i] * rhs.stripes[i];
360  }
361  return result;
362 }
363 
364 template <class T, class T2, int Rows, int Columns, eMatrixOrder Order, eMatrixOrder Order2, eMatrixLayout Layout, bool Packed>
365 auto MulElementwise(const Matrix<T, Rows, Columns, Order, Layout, Packed>& lhs, const Matrix<T2, Rows, Columns, Order2, traits::OppositeLayout<Layout>::value, Packed>& rhs) {
367  for (int i = 0; i < Rows; ++i) {
368  for (int j = 0; j < Columns; ++j) {
369  result(i, j) = lhs(i, j) * rhs(i, j);
370  }
371  }
372  return result;
373 }
374 
375 template <class T, class T2, int Rows, int Columns, eMatrixOrder Order, eMatrixOrder Order2, eMatrixLayout Layout, bool Packed>
378  for (int i = 0; i < result.StripeCount; ++i) {
379  result.stripes[i] = lhs.stripes[i] / rhs.stripes[i];
380  }
381  return result;
382 }
383 
384 template <class T, class T2, int Rows, int Columns, eMatrixOrder Order, eMatrixOrder Order2, eMatrixLayout Layout, bool Packed>
385 auto DivElementwise(const Matrix<T, Rows, Columns, Order, Layout, Packed>& lhs, const Matrix<T2, Rows, Columns, Order2, traits::OppositeLayout<Layout>::value, Packed>& rhs) {
387  for (int i = 0; i < Rows; ++i) {
388  for (int j = 0; j < Columns; ++j) {
389  result(i, j) = lhs(i, j) / rhs(i, j);
390  }
391  }
392  return result;
393 }
394 
395 
396 
397 //------------------------------------------------------------------------------
398 // Unary signs
399 //------------------------------------------------------------------------------
400 template <class U, class T, int Rows, int Columns, eMatrixOrder Order, eMatrixLayout Layout, bool Packed>
403 }
404 
405 template <class U, class T, int Rows, int Columns, eMatrixOrder Order, eMatrixLayout Layout, bool Packed>
408 }
409 
410 
411 
412 } // namespace mathter
Matrix< U, Rows, Columns, Order1, Layout1, Packed > & operator+=(Matrix< T, Rows, Columns, Order1, Layout1, Packed > &lhs, const Matrix< U, Rows, Columns, Order2, Layout2, Packed > &rhs)
Performs matrix addition and stores result in this.
Definition: MatrixArithmetic.hpp:287
#define MATHTER_MATMUL_CC_UNROLL(COLUMNS2, MATCH)
Definition: MatrixArithmetic.hpp:69
auto DivElementwise(const Matrix< T, Rows, Columns, Order, Layout, Packed > &lhs, const Matrix< T2, Rows, Columns, Order2, Layout, Packed > &rhs)
Definition: MatrixArithmetic.hpp:376
auto operator*(const Matrix< T, Rows1, Match, Order1, eMatrixLayout::ROW_MAJOR, Packed > &lhs, const Matrix< U, Match, Columns2, Order2, eMatrixLayout::ROW_MAJOR, Packed > &rhs) -> Matrix< V, Rows1, Columns2, Order1, eMatrixLayout::ROW_MAJOR, Packed >
Definition: MatrixArithmetic.hpp:78
static constexpr int StripeCount
Definition: MatrixImpl.hpp:44
T Dot(const Vector< T, Dim, Packed > &lhs, const Vector< T, Dim, Packed > &rhs)
Calculates the scalar product (dot product) of the two arguments.
Definition: VectorFunction.hpp:111
auto MulElementwise(const Matrix< T, Rows, Columns, Order, Layout, Packed > &lhs, const Matrix< T2, Rows, Columns, Order2, Layout, Packed > &rhs)
Definition: MatrixArithmetic.hpp:356
std::array< Vector< T, StripeDim, Packed >, StripeCount > stripes
Definition: MatrixImpl.hpp:46
Definition: Approx.hpp:11
#define MATHTER_MATADD_SAME_UNROLL(S, OP)
Definition: MatrixArithmetic.hpp:213
Matrix< T, Rows, Columns, Order, Layout, Packed > operator/(T s, const Matrix< T, Rows, Columns, Order, Layout, Packed > &mat)
Definition: MatrixArithmetic.hpp:333
Matrix< U, Rows, Columns, Order1, Layout1, Packed > & operator-=(Matrix< T, Rows, Columns, Order1, Layout1, Packed > &lhs, const Matrix< U, Rows, Columns, Order2, Layout2, Packed > &rhs)
Performs matrix subtraction and stores result in this.
Definition: MatrixArithmetic.hpp:296
constexpr int ColumnCount() const
Returns the number of columns of the matrix.
Definition: MatrixImpl.hpp:27
Definition: Definitions.hpp:63
Definition: Traits.hpp:52
Matrix< U, Rows, Columns, Order1, SameLayout, Packed > operator-(const Matrix< T, Rows, Columns, Order1, SameLayout, Packed > &lhs, const Matrix< U, Rows, Columns, Order2, SameLayout, Packed > &rhs)
Definition: MatrixArithmetic.hpp:239
Matrix< T1, Dim, Dim, Order1, Layout1, Packed > & operator*=(Matrix< T1, Dim, Dim, Order1, Layout1, Packed > &lhs, const Matrix< T2, Dim, Dim, Order2, Layout2, Packed > &rhs)
Definition: MatrixArithmetic.hpp:198
Matrix< T, Rows, Columns, Order, Layout, Packed > & operator/=(Matrix< T, Rows, Columns, Order, Layout, Packed > &mat, T s)
Divides all elements of the matrix by scalar.
Definition: MatrixArithmetic.hpp:321
eMatrixOrder
Determines if you want to left- or right-multiply your matrices with vectors.
Definition: Definitions.hpp:22
Matrix< U, Rows, Columns, Order1, SameLayout, Packed > operator+(const Matrix< T, Rows, Columns, Order1, SameLayout, Packed > &lhs, const Matrix< U, Rows, Columns, Order2, SameLayout, Packed > &rhs)
Definition: MatrixArithmetic.hpp:222
#define MATHTER_MATMUL_RR_UNROLL(MATCH, ROWS1)
Definition: MatrixArithmetic.hpp:37
decltype(T() *U()+T()+U()) MatMulElemT
Definition: Traits.hpp:60
constexpr int RowCount() const
Returns the number of rows of the matrix.
Definition: MatrixImpl.hpp:31
eMatrixLayout
Determines the memory layout of matrices.
Definition: Definitions.hpp:36