ModelSpace
All Classes Namespaces Functions Variables Enumerations Pages
matrixmath.hpp
1/******************************************************************************
2* Copyright (c) ATTX LLC 2024. All Rights Reserved.
3*
4* This software and associated documentation (the "Software") are the
5* proprietary and confidential information of ATTX, LLC. The Software is
6* furnished under a license agreement between ATTX and the user organization
7* and may be used or copied only in accordance with the terms of the agreement.
8* Refer to 'license/attx_license.adoc' for standard license terms.
9*
10* EXPORT CONTROL NOTICE: THIS SOFTWARE MAY INCLUDE CONTENT CONTROLLED UNDER THE
11* INTERNATIONAL TRAFFIC IN ARMS REGULATIONS (ITAR) OR THE EXPORT ADMINISTRATION
12* REGULATIONS (EAR99). No part of the Software may be used, reproduced, or
13* transmitted in any form or by any means, for any purpose, without the express
14* written permission of ATTX, LLC.
15******************************************************************************/
16/*
17Matrix math header file
18-----------------------
19This file defines basic functions for mathematical operations on
20the matrix class
21Rather than raising an error on fail cases (i.e. divide by zero),
22the following libraries are designed to check for errors and return
23corresponding codes.
24
25Note: The naming convention observed for matrix math is as follows:
26- Capital letters represent matrices
27- Lowercase letters represent scalars
28- All vectors are 1-dimensional matrices for the purpose of math
29- Pass by reference return values are all named "result"
30- The letter used in math indicates the order of operations - A/a
31 comes first, then B/b. A/a or B/b always represent the "other"
32 value in an operation
33
34Author: Alex Reynolds
35*/
36
37#ifndef MATRIXMATH_HPP
38#define MATRIXMATH_HPP
39
40#include "Matrix.hpp"
42
43namespace clockwerk {
44
45 /// ---------------------------------------------------------------------------------------------------
46 /// Standard functions
47 /// ---------------------------------------------------------------------------------------------------
48
49 /// @brief Function to multiply two matrices
50 /// @param A First matrix in the multiplication operation
51 /// @param B Second matrix in the multiplication operation
52 /// @param result PBR return of A*B result
53 /// @return Error code corresponding to errors in clockwerkerrors.h
54 /// @note Here we are using the "standard" O^3 matrix multiplication algorithm. Quick lookup
55 /// indicates that more highly optimized matrix multiplication algorithms, such as strassen,
56 /// require much larger sizes than we will typically be working with to be valuable.
57 template<typename T, unsigned int R1, unsigned int C1R2, unsigned int C2>
58 void multiply(Matrix<T, R1, C1R2> A, Matrix<T, C1R2, C2> B, Matrix<T, R1, C2> &result) {
59 /// Check and enforce matrix size constraints
60 /// Note: A number of checks necessary for matrix multiplication are performed at compile time.
61 /// The number of rows and columns in matrix result needs to correcpond to the number of rows
62 /// in matrix one and columns in matrix two -- this is enforced by templating size constraints
63 /// and will not compile if incorrect
64 /// The number of columns in matrix one need to correspond to the number of rows in matrix 2.
65 /// This constraint is enforced by the template variable C1R2 and will not compile if incorrect
66 /// Note: Because size checks are performed by templating, this function does not return an error code.
67 /// If a size error exists, function will not compile
68
69 /// Now we can perform our multiplication operation
70 /// Note: Because of templating size checks, we know that no operations
71 /// will request an index out of bounds in a matrix. Therefore, we can ignore these checks
72 /// for speed in this function
73 unsigned int i, j, k;
74 for(i = 0; i < R1; i++) {
75 for(j = 0; j < C2; j++) {
76 result.values[i][j] = T(); /// Note: here we're explicitly calling the default constructor.
77 /// should be zero for basic types but essentially enforces assumption
78 /// that object in question has a default constructor.
79 for(k = 0; k < C1R2; k++) {
80 /// NOTE: Per the above dimension check
81 result.values[i][j] += A.values[i][k]*B.values[k][j];
82 }
83 }
84 }
85 }
86
87 /// @brief Function to multiply a scalar by a matrix
88 /// @param a Scalar by which to multiply A
89 /// @param A Matrix in the scalar multiplication operation
90 /// @param result PBR return of a*A result
91 /// @return Error code corresponding to errors in clockwerkerrors.h
92 template<typename T, unsigned int R, unsigned int C>
93 void multiply(const T &a, Matrix<T, R, C> A, Matrix<T, R, C> &result) {
94 /// Check and enforce matrix size constraints
95 /// Note: The check necessary to ensure safe operations here is that the size of result
96 /// and A match -- That is enforced via templating and the compiler at compile time
97 /// Note: Because size checks are performed by templating, this function does not return an error code.
98 /// If a size error exists, function will not compile
99
100 /// Now we can perform our multiplication operation
101 /// Note: Because of templating size checks, we know that no operations
102 /// will request an index out of bounds in a matrix. Therefore, we can ignore these checks
103 /// for speed in this function
104 unsigned int i, j;
105 for(i = 0; i < R; i++) {
106 for(j = 0; j < C; j++) {
107 result.values[i][j] = a*A.values[i][j];
108 }
109 }
110 }
111
112 /// @brief Function to multiply two matrices element-wise
113 /// @param A First matrix in the element-wise multiplication operation
114 /// @param B Second matrix in the element-wise multiplication operation
115 /// @param result PBR return of A.*B result
116 /// @return Error code corresponding to errors in clockwerkerrors.h
117 template<typename T, unsigned int R, unsigned int C>
118 void eMultiply(Matrix<T, R, C> A, Matrix<T, R, C> B, Matrix<T, R, C> &result) {
119 /// Check and enforce matrix size constraints
120 /// Note: The check necessary to ensure safe operations here is that the sizes of result,
121 /// A, and B match -- That is enforced via templating and the compiler at compile time
122 /// Note: Because size checks are performed by templating, this function does not return an error code.
123 /// If a size error exists, function will not compile
124
125 /// Now we can perform our multiplication operation
126 /// Note: Because of templating size checks, we know that no operations
127 /// will request an index out of bounds in a matrix. Therefore, we can ignore these checks
128 /// for speed in this function
129 unsigned int i, j;
130 for(i = 0; i < R; i++) {
131 for(j = 0; j < C; j++) {
132 result.values[i][j] = A.values[i][j]*B.values[i][j];
133 }
134 }
135 }
136
137 /// @brief Function to add a scalar to a matrix
138 /// @param a Scalar to add to A
139 /// @param A Matrix in the scalar addition operation
140 /// @param result PBR return of a+A result
141 /// @return Error code corresponding to errors in clockwerkerrors.h
142 template<typename T, unsigned int R, unsigned int C>
143 void add(const T &a, Matrix<T, R, C> A, Matrix<T, R, C> &result) {
144 /// Check and enforce matrix size constraints
145 /// Note: The check necessary to ensure safe operations here is that the size of result
146 /// and A match -- That is enforced via templating and the compiler at compile time
147 /// Note: Because size checks are performed by templating, this function does not return an error code.
148 /// If a size error exists, function will not compile
149
150 /// Now we can perform our multiplication operation
151 /// Note: Because of templating size checks, we know that no operations
152 /// will request an index out of bounds in a matrix. Therefore, we can ignore these checks
153 /// for speed in this function
154 unsigned int i, j;
155 for(i = 0; i < R; i++) {
156 for(j = 0; j < C; j++) {
157 result.values[i][j] = a + A.values[i][j];
158 }
159 }
160 }
161
162 /// @brief Function to add two matrices element-wise
163 /// @param A First matrix in the element-wise addition operation
164 /// @param B Second matrix in the element-wise addition operation
165 /// @param result PBR return of A+B result
166 /// @return Error code corresponding to errors in clockwerkerrors.h
167 template<typename T, unsigned int R, unsigned int C>
168 void eAdd(Matrix<T, R, C> A, Matrix<T, R, C> B, Matrix<T, R, C> &result) {
169 /// Check and enforce matrix size constraints
170 /// Note: The check necessary to ensure safe operations here is that the sizes of result,
171 /// A, and B match -- That is enforced via templating and the compiler at compile time
172 /// Note: Because size checks are performed by templating, this function does not return an error code.
173 /// If a size error exists, function will not compile
174
175 /// Now we can perform our multiplication operation
176 /// Note: Because of templating size checks, we know that no operations
177 /// will request an index out of bounds in a matrix. Therefore, we can ignore these checks
178 /// for speed in this function
179 unsigned int i, j;
180 for(i = 0; i < R; i++) {
181 for(j = 0; j < C; j++) {
182 result.values[i][j] = A.values[i][j] + B.values[i][j];
183 }
184 }
185 }
186
187 /// @brief Function to subtract B from A, element-wise
188 /// @param A First matrix in the element-wise subtraction operation
189 /// @param B Second matrix in the element-wise subtraction operation
190 /// @param result PBR return of A-B result
191 /// @return Error code corresponding to errors in clockwerkerrors.h
192 template<typename T, unsigned int R, unsigned int C>
193 void eSubtract(Matrix<T, R, C> A, Matrix<T, R, C> B, Matrix<T, R, C> &result) {
194 /// Check and enforce matrix size constraints
195 /// Note: The check necessary to ensure safe operations here is that the sizes of result,
196 /// A, and B match -- That is enforced via templating and the compiler at compile time
197 /// Note: Because size checks are performed by templating, this function does not return an error code.
198 /// If a size error exists, function will not compile
199
200 /// Now we can perform our multiplication operation
201 /// Note: Because of templating size checks, we know that no operations
202 /// will request an index out of bounds in a matrix. Therefore, we can ignore these checks
203 /// for speed in this function
204 unsigned int i, j;
205 for(i = 0; i < R; i++) {
206 for(j = 0; j < C; j++) {
207 result.values[i][j] = A.values[i][j] - B.values[i][j];
208 }
209 }
210 }
211
212 /// ------------------------------------------------------------------------------------------------------
213 /// Operator overloads -- NOTE: May be less efficient than equivalent PBR function in some cases due to
214 /// return by value. Where overload is less efficient, it is explicitly noted.
215 /// ------------------------------------------------------------------------------------------------------
216 /// @brief Overload of matrix multiplication - Two matrices
217 /// @note Returns value -- less efficient in some cases
218 template<typename T, unsigned int R1, unsigned int C1R2, unsigned int C2>
219 Matrix<T, R1, C2> operator*(const Matrix<T, R1, C1R2> &A, const Matrix<T, C1R2, C2> &B) {
220 /// Call our function to add two matrices and return the result
221 Matrix<T, R1, C2> result;
222 multiply(A, B, result);
223 return result;
224 }
225
226 /// @brief Overload of matrix multiplication - Matrix and scalar
227 /// @note Returns value -- less efficient in some cases
228 template<typename T, unsigned int R, unsigned int C>
229 Matrix<T, R, C> operator*(const T &a, const Matrix<T, R, C> &A) {
230 /// Call our function to multiply and return the result
231 Matrix<T, R, C> result;
232 multiply(a, A, result);
233 return result;
234 }
235 template<typename T, unsigned int R, unsigned int C>
236 Matrix<T, R, C> operator*(const Matrix<T, R, C> &A, const T &a) {
237 /// Call our function to multiply and return the result
238 Matrix<T, R, C> result;
239 multiply(a, A, result);
240 return result;
241 }
242
243 /// @brief Overload of matrix addition - Two matrices
244 /// @note Returns value -- less efficient in some cases
245 template<typename T, unsigned int R, unsigned int C>
246 Matrix<T, R, C> operator+(const Matrix<T, R, C> &A, const Matrix<T, R, C> &B) {
247 /// Call our function to add two matrices and return the result
248 Matrix<T, R, C> result;
249 eAdd(A, B, result);
250 return result;
251 }
252
253 /// @brief Overload of matrix addition - Matrix and scalar
254 /// @note Returns value -- less efficient in some cases
255 template<typename T, unsigned int R, unsigned int C>
256 Matrix<T, R, C> operator+(const T &a, const Matrix<T, R, C> &A) {
257 /// Call our function to add two matrices and return the result
258 Matrix<T, R, C> result;
259 add(a, A, result);
260 return result;
261 }
262 template<typename T, unsigned int R, unsigned int C>
263 Matrix<T, R, C> operator+(const Matrix<T, R, C> &A, const T &a) {
264 /// Call our function to add two matrices and return the result
265 Matrix<T, R, C> result;
266 add(a, A, result);
267 return result;
268 }
269
270 /// Returns value -- less efficient in some cases
271 template<typename T, unsigned int R, unsigned int C>
272 Matrix<T, R, C> operator-(const Matrix<T, R, C> &A, const Matrix<T, R, C> &B) {
273 /// Call our function to add two matrices and return the result
274 Matrix<T, R, C> result;
275 eSubtract(A, B, result);
276 return result;
277 }
278
279}
280
281#endif
Matrix math implementation.
Definition Matrix.hpp:54