PhysicsBasedAnimationToolkit 0.0.10
Cross-platform C++20 library of algorithms and data structures commonly used in computer graphics research on physically-based simulation.
Loading...
Searching...
No Matches
Matrix.h
1#ifndef PBAT_MATH_LINALG_MINI_MATRIX_H
2#define PBAT_MATH_LINALG_MINI_MATRIX_H
3
4#include "Api.h"
5#include "Concepts.h"
6#include "pbat/HostDevice.h"
8
9#include <array>
10#include <cstdint>
11#include <initializer_list>
12#include <string.h>
13#include <utility>
14
15namespace pbat {
16namespace math {
17namespace linalg {
18namespace mini {
19
20template <class TScalar, int M, int N = 1>
21class Ones
22{
23 public:
24 using ScalarType = TScalar;
25 using SelfType = Ones<ScalarType, M, N>;
26
27 static auto constexpr kRows = M;
28 static auto constexpr kCols = N;
29 static bool constexpr bRowMajor = false;
30
31 PBAT_HOST_DEVICE ScalarType operator()([[maybe_unused]] auto i, [[maybe_unused]] auto j) const
32 {
33 return ScalarType{1};
34 }
35
36 // Vector(ized) access
37 PBAT_HOST_DEVICE ScalarType operator()([[maybe_unused]] auto i) const { return ScalarType{1}; }
38 PBAT_HOST_DEVICE ScalarType operator[](auto i) const { return (*this)(i); }
39
40 template <auto S, auto T>
41 PBAT_HOST_DEVICE auto Slice([[maybe_unused]] auto i, [[maybe_unused]] auto j) const
42 {
44 }
45 PBAT_HOST_DEVICE auto Col([[maybe_unused]] auto j) const
46 {
48 }
49 PBAT_HOST_DEVICE auto Row([[maybe_unused]] auto i) const
50 {
52 }
53
54 PBAT_MINI_DIMENSIONS_API
55 PBAT_MINI_CONST_TRANSPOSE_API(SelfType)
56};
57
58template <class TScalar, int M, int N = 1>
59class Zeros
60{
61 public:
62 using ScalarType = TScalar;
63 using SelfType = Zeros<ScalarType, M, N>;
64
65 static auto constexpr kRows = M;
66 static auto constexpr kCols = N;
67 static bool constexpr bRowMajor = false;
68
69 PBAT_HOST_DEVICE ScalarType operator()([[maybe_unused]] auto i, [[maybe_unused]] auto j) const
70 {
71 return ScalarType{0};
72 }
73
74 // Vector(ized) access
75 PBAT_HOST_DEVICE ScalarType operator()([[maybe_unused]] auto i) const { return ScalarType{0}; }
76 PBAT_HOST_DEVICE ScalarType operator[](auto i) const { return (*this)(i); }
77
78 template <auto S, auto T>
79 PBAT_HOST_DEVICE auto Slice([[maybe_unused]] auto i, [[maybe_unused]] auto j) const
80 {
82 }
83 PBAT_HOST_DEVICE auto Col([[maybe_unused]] auto j) const
84 {
86 }
87 PBAT_HOST_DEVICE auto Row([[maybe_unused]] auto i) const
88 {
90 }
91
92 PBAT_MINI_DIMENSIONS_API
93 PBAT_MINI_CONST_TRANSPOSE_API(SelfType)
94};
95
96template <class TScalar, int M, int N>
98{
99 public:
100 using ScalarType = TScalar;
101 using SelfType = Identity<ScalarType, M, N>;
102
103 static auto constexpr kRows = M;
104 static auto constexpr kCols = N;
105 static bool constexpr bRowMajor = false;
106
107 PBAT_HOST_DEVICE ScalarType operator()(auto i, auto j) const
108 {
109 return static_cast<ScalarType>(i == j);
110 }
111
112 // Vector(ized) access
113 PBAT_HOST_DEVICE ScalarType operator()(auto i) const { return (*this)(i % kRows, i / kRows); }
114 PBAT_HOST_DEVICE ScalarType operator[](auto i) const { return (*this)(i); }
115
116 PBAT_MINI_READ_API(SelfType)
117};
118
119template <class TScalar, int M, int N = 1>
120class SMatrix
121{
122 public:
123 using ScalarType = TScalar;
124 using SelfType = SMatrix<ScalarType, M, N>;
125#include "pbat/warning/Push.h"
126#include "pbat/warning/SignConversion.h"
127 using StorageType = std::array<ScalarType, M * N>;
128#include "pbat/warning/Pop.h"
129 using IndexType = typename StorageType::size_type;
130
131 static auto constexpr kRows = M;
132 static auto constexpr kCols = N;
133 static bool constexpr bRowMajor = false;
134
135 PBAT_HOST_DEVICE SMatrix() : a() {}
136
137 template <class... T>
138 PBAT_HOST_DEVICE SMatrix(T... values) : a{values...}
139 {
140 }
141
142 template <class /*CMatrix*/ TMatrix>
143 PBAT_HOST_DEVICE SMatrix(TMatrix&& B) : a()
144 {
145 Assign(*this, std::forward<TMatrix>(B));
146 }
147
148 PBAT_HOST_DEVICE void SetConstant(ScalarType k) { AssignScalar(*this, k); }
149
150 PBAT_HOST_DEVICE ScalarType operator()(auto i, auto j) const
151 {
152 auto k = static_cast<IndexType>(j * M + i);
153 return a[k];
154 }
155 PBAT_HOST_DEVICE ScalarType& operator()(auto i, auto j)
156 {
157 auto k = static_cast<IndexType>(j * M + i);
158 return a[k];
159 }
160
161 // Vector(ized) access
162 PBAT_HOST_DEVICE ScalarType operator()(auto i) const
163 {
164 auto k = static_cast<IndexType>(i);
165 return a[k];
166 }
167 PBAT_HOST_DEVICE ScalarType& operator()(auto i)
168 {
169 auto k = static_cast<IndexType>(i);
170 return a[k];
171 }
172 PBAT_HOST_DEVICE ScalarType operator[](auto i) const
173 {
174 auto k = static_cast<IndexType>(i);
175 return a[k];
176 }
177 PBAT_HOST_DEVICE ScalarType& operator[](auto i)
178 {
179 auto k = static_cast<IndexType>(i);
180 return a[k];
181 }
182
183 PBAT_HOST_DEVICE void SetZero() { memset(a.data(), 0, kRows * kCols * sizeof(ScalarType)); }
184
185 ScalarType* Data() { return a.data(); }
186 ScalarType const* Data() const { return a.data(); }
187
188 PBAT_MINI_READ_WRITE_API(SelfType)
189
190 private:
191 StorageType a;
192};
193
194template <class TScalar, int M>
195using SVector = SMatrix<TScalar, M, 1>;
196
197template <class TScalar, int M, int N>
198class SMatrixView
199{
200 public:
201 using ScalarType = TScalar;
202 using SelfType = SMatrixView<ScalarType, M, N>;
203
204 static auto constexpr kRows = M;
205 static auto constexpr kCols = N;
206 static bool constexpr bRowMajor = false;
207
208 PBAT_HOST_DEVICE SMatrixView(ScalarType* a) : mA(a) {}
209
210 PBAT_HOST_DEVICE void SetConstant(ScalarType k) { AssignScalar(*this, k); }
211
212 PBAT_HOST_DEVICE ScalarType operator()(auto i, auto j) const { return mA[j * M + i]; }
213 PBAT_HOST_DEVICE ScalarType& operator()(auto i, auto j) { return mA[j * M + i]; }
214
215 // Vector(ized) access
216 PBAT_HOST_DEVICE ScalarType operator()(auto i) const { return mA[i]; }
217 PBAT_HOST_DEVICE ScalarType& operator()(auto i) { return mA[i]; }
218 PBAT_HOST_DEVICE ScalarType operator[](auto i) const { return mA[i]; }
219 PBAT_HOST_DEVICE ScalarType& operator[](auto i) { return mA[i]; }
220
221 PBAT_HOST_DEVICE void SetZero() { memset(mA, 0, kRows * kCols * sizeof(ScalarType)); }
222
223 ScalarType* Data() { return mA; }
224 ScalarType const* Data() const { return mA; }
225
226 PBAT_MINI_READ_WRITE_API(SelfType)
227
228 private:
229 ScalarType* mA;
230};
231
232template <class TScalar, int M>
233using SVectorView = SMatrixView<TScalar, M, 1>;
234
235template <class TScalar, int M>
236PBAT_HOST_DEVICE auto Unit(auto i)
237{
238 return Identity<TScalar, M, M>().Col(i);
239}
240
241template <auto M, auto N, class TScalar>
242PBAT_HOST_DEVICE auto FromFlatBuffer(TScalar* buf, std::int64_t bi)
243{
244 return SMatrixView<TScalar, M, N>(buf + M * N * bi);
245}
246
247template <class TScalar, CMatrix TIndexMatrix>
248PBAT_HOST_DEVICE auto FromFlatBuffer(TScalar* buf, TIndexMatrix const& inds)
249{
250 using IntegerType = typename TIndexMatrix::ScalarType;
251 static_assert(std::is_integral_v<IntegerType>, "inds must be matrix of indices");
252 auto constexpr M = TIndexMatrix::kRows;
253 auto constexpr N = TIndexMatrix::kCols;
254 using ScalarType = std::remove_cvref_t<TScalar>;
255 SMatrix<ScalarType, M, N> A{};
257 ForRange<0, N>([&]<auto j>() { ForRange<0, M>([&]<auto i>() { A(i, j) = buf[inds(i, j)]; }); });
258 return A;
259}
260
261template <CMatrix TMatrix>
262PBAT_HOST_DEVICE void
263ToFlatBuffer(TMatrix const& A, typename TMatrix::ScalarType* buf, std::int64_t bi)
264{
265 auto constexpr M = TMatrix::kRows;
266 auto constexpr N = TMatrix::kCols;
267 FromFlatBuffer<M, N>(buf, bi) = A;
268}
269
270template <CMatrix TMatrix, CMatrix TIndexMatrix>
271PBAT_HOST_DEVICE void
272ToFlatBuffer(TMatrix const& A, TIndexMatrix const& inds, typename TMatrix::ScalarType* buf)
273{
274 auto constexpr MA = TMatrix::kRows;
275 auto constexpr NA = TMatrix::kCols;
276 auto constexpr MI = TIndexMatrix::kRows;
277 auto constexpr NI = TIndexMatrix::kCols;
278 static_assert(MA == MI or MI == 1, "A must have same rows as inds or inds is a row vector");
279 static_assert(NA == NI, "A must have same cols as inds");
281 if constexpr (MA > 1 and MI == 1)
282 {
283 // In this case, I will assume that the user wishes to put each column of A in the
284 // corresponding "column" in the flat buffer buf, as if column major, according to inds.
285 ForRange<0, NA>([&]<auto j>() {
286 ForRange<0, MA>([&]<auto i>() { buf[MA * inds(0, j) + i] = A(i, j); });
287 });
288 }
289 else
290 {
291 ForRange<0, NA>(
292 [&]<auto j>() { ForRange<0, MA>([&]<auto i>() { buf[inds(i, j)] = A(i, j); }); });
293 }
294}
295
296template <auto M, auto N, class TScalar>
297PBAT_HOST_DEVICE auto FromBuffers(std::array<TScalar*, M> buf, std::int64_t bi)
298{
299 using ScalarType = std::remove_const_t<TScalar>;
302 ForRange<0, M>([&]<auto i>() { A.Row(i) = FromFlatBuffer<1, N>(buf[i], bi); });
303 return A;
304}
305
306template <auto K, class TScalar, CMatrix TIndexMatrix>
307PBAT_HOST_DEVICE auto FromBuffers(std::array<TScalar*, K> buf, TIndexMatrix const& inds)
308{
309 using IntegerType = typename TIndexMatrix::ScalarType;
310 static_assert(std::is_integral_v<IntegerType>, "inds must be matrix of indices");
311 auto constexpr M = TIndexMatrix::kRows;
312 auto constexpr N = TIndexMatrix::kCols;
313 using ScalarType = std::remove_cvref_t<TScalar>;
316 ForRange<0, K>(
317 [&]<auto k>() { A.template Slice<M, N>(k * M, 0) = FromFlatBuffer(buf[k], inds); });
318 return A;
319}
320
321template <CMatrix TMatrix, auto M>
322PBAT_HOST_DEVICE void
323ToBuffers(TMatrix const& A, std::array<typename TMatrix::ScalarType*, M> buf, std::int64_t bi)
324{
325 static_assert(M == TMatrix::kRows, "A must have same rows as number of buffers");
326 auto constexpr N = TMatrix::kCols;
328 ForRange<0, M>([&]<auto i>() { FromFlatBuffer<1, N>(buf[i], bi) = A.Row(i); });
329}
330
331template <CMatrix TMatrix, CMatrix TIndexMatrix, auto K>
332PBAT_HOST_DEVICE void ToBuffers(
333 TMatrix const& A,
334 TIndexMatrix const& inds,
335 std::array<typename TMatrix::ScalarType*, K> buf)
336{
337 auto constexpr MA = TMatrix::kRows;
338 auto constexpr NA = TMatrix::kCols;
339 auto constexpr MI = TIndexMatrix::kRows;
340 auto constexpr NI = TIndexMatrix::kCols;
341 static_assert(MA % MI == 0, "Rows of A must be multiple of rows of inds");
342 static_assert(NA == NI, "A and inds must have same number of columns");
343 static_assert(MA / MI == K, "A must have number of rows == #buffers*#rows of inds");
345 ForRange<0, K>(
346 [&]<auto k>() { ToFlatBuffer(A.template Slice<MI, NI>(k * MI, 0), inds, buf[k]); });
347}
348
349} // namespace mini
350} // namespace linalg
351} // namespace math
352} // namespace pbat
353
354#endif // PBAT_MATH_LINALG_MINI_MATRIX_H
Compile-time for loops.
Definition Matrix.h:22
Definition Matrix.h:121
Definition Matrix.h:60
constexpr void ForRange(F &&f)
Compile-time for loop over a range of values.
Definition ConstexprFor.h:55
Mini linear algebra related functionality.
Definition Assign.h:12
Linear Algebra related functionality.
Definition FilterEigenvalues.h:7
Math related functionality.
Definition Concepts.h:19
The main namespace of the library.
Definition Aliases.h:15