ACTS
Experiment-independent tracking
Loading...
Searching...
No Matches
generic_matrix.hpp
1// This file is part of the ACTS project.
2//
3// Copyright (C) 2016 CERN for the benefit of the ACTS project
4//
5// This Source Code Form is subject to the terms of the Mozilla Public
6// License, v. 2.0. If a copy of the MPL was not distributed with this
7// file, You can obtain one at https://mozilla.org/MPL/2.0/.
8
9#pragma once
10
11// Project include(s).
12#include "detray/algebra/common/math.hpp"
13#include "detray/algebra/concepts.hpp"
14#include "detray/algebra/generic/algorithms/utils/algorithm_selector.hpp"
15#include "detray/algebra/generic/impl/generic_vector.hpp"
16#include "detray/definitions/detail/qualifiers.hpp"
17
18namespace detray::algebra::generic::math {
19
21template <concepts::matrix M>
22DETRAY_HOST_DEVICE constexpr M zero() {
23 using index_t = detray::traits::index_t<M>;
24 using element_getter_t = detray::traits::element_getter_t<M>;
25
26 M ret{};
27
28 for (index_t j = 0; j < detray::traits::columns<M>; ++j) {
29 for (index_t i = 0; i < detray::traits::rows<M>; ++i) {
30 element_getter_t{}(ret, i, j) = 0;
31 }
32 }
33
34 return ret;
35}
36
38template <concepts::matrix M>
39DETRAY_HOST_DEVICE constexpr M identity() {
40 using index_t = detray::traits::index_t<M>;
41 using element_getter_t = detray::traits::element_getter_t<M>;
42
43 auto ret{zero<M>()};
44
45 for (index_t i = 0; i < detray::traits::max_rank<M>; ++i) {
46 element_getter_t{}(ret, i, i) = 1;
47 }
48
49 return ret;
50}
51
53template <concepts::matrix M>
54DETRAY_HOST_DEVICE constexpr void set_zero(M &m) {
55 m = zero<M>();
56}
57
59template <concepts::matrix M>
60DETRAY_HOST_DEVICE constexpr void set_identity(M &m) {
61 m = identity<M>();
62}
63
65template <concepts::matrix M>
66DETRAY_HOST_DEVICE constexpr auto transpose(const M &m) {
67 using index_t = detray::traits::index_t<M>;
68 using value_t = detray::traits::value_t<M>;
69 using element_getter_t = detray::traits::element_getter_t<M>;
70
71 constexpr index_t rows{detray::traits::rows<M>};
72 constexpr index_t columns{detray::traits::columns<M>};
73
74 detray::traits::get_matrix_t<M, columns, rows, value_t> ret;
75
76 for (index_t i = 0; i < rows; ++i) {
77 for (index_t j = 0; j < columns; ++j) {
78 element_getter_t{}(ret, j, i) = element_getter_t{}(m, i, j);
79 }
80 }
81
82 return ret;
83}
84
86template <concepts::square_matrix M, concepts::vector3D V>
87 requires(detray::traits::max_rank<M> == 3u)
88DETRAY_HOST_DEVICE constexpr M column_wise_cross(const M &m, const V &v) {
89 using block_getter_t = detray::traits::block_getter_t<M>;
90 constexpr block_getter_t block{};
91
92 M ret{};
93
94 const V m_col0 = block.template vector<3>(m, 0u, 0u);
95 const V m_col1 = block.template vector<3>(m, 0u, 1u);
96 const V m_col2 = block.template vector<3>(m, 0u, 2u);
97
98 block.set(ret, static_cast<V>(cross(m_col0, v)), 0u, 0u);
99 block.set(ret, static_cast<V>(cross(m_col1, v)), 0u, 1u);
100 block.set(ret, static_cast<V>(cross(m_col2, v)), 0u, 2u);
101
102 return ret;
103}
104
106template <concepts::square_matrix M, concepts::vector V>
107 requires(detray::traits::max_rank<M> == detray::traits::size<V>)
108DETRAY_HOST_DEVICE inline M column_wise_multiply(const M &m, const V &v) {
109 using element_getter_t = detray::traits::element_getter_t<M>;
110 constexpr element_getter_t elem{};
111
112 M ret{};
113
114 constexpr std::size_t N{detray::traits::max_rank<M>};
115 for (std::size_t i = 0u; i < N; i++) {
116 for (std::size_t j = 0u; j < N; j++) {
117 elem(ret, j, i) = elem(m, j, i) * elem(v, j);
118 }
119 }
120
121 return ret;
122}
123
125template <concepts::vector3D V3>
126DETRAY_HOST_DEVICE inline auto cross_matrix(const V3 &v) {
127 using scalar_t = detray::traits::scalar_t<V3>;
128 using matrix_33_t = detray::traits::get_matrix_t<V3, 3, 3, scalar_t>;
129
130 using element_getter_t = detray::traits::element_getter_t<V3>;
131 constexpr element_getter_t elem{};
132
133 matrix_33_t ret{};
134 elem(ret, 0u, 0u) = 0.f;
135 elem(ret, 0u, 1u) = -elem(v, 2u);
136 elem(ret, 0u, 2u) = elem(v, 1u);
137 elem(ret, 1u, 0u) = elem(v, 2u);
138 elem(ret, 1u, 1u) = 0.f;
139 elem(ret, 1u, 2u) = -elem(v, 0u);
140 elem(ret, 2u, 0u) = -elem(v, 1u);
141 elem(ret, 2u, 1u) = elem(v, 0u);
142 elem(ret, 2u, 2u) = 0.f;
143
144 return ret;
145}
146
148template <concepts::vector V>
149DETRAY_HOST_DEVICE inline detray::traits::get_matrix_t<
150 V, detray::traits::size<V>, detray::traits::size<V>,
151 detray::traits::scalar_t<V>>
152outer_product(const V &v1, const V &v2) {
153 using scalar_t = detray::traits::scalar_t<V>;
154 using index_t = detray::traits::index_t<V>;
155
156 constexpr auto N{static_cast<index_t>(detray::traits::size<V>)};
157 using matrix_t = detray::traits::get_matrix_t<V, N, N, scalar_t>;
158
159 using element_getter_t = detray::traits::element_getter_t<V>;
160 constexpr element_getter_t elem{};
161
162 matrix_t ret{};
163
164 // TODO: vectorize better
165 for (index_t row = 0; row < N; row++) {
166 for (index_t col = 0; col < N; col++) {
167 elem(ret, row, col) = elem(v1, row) * elem(v2, col);
168 }
169 }
170
171 return ret;
172}
173
174// Set matrix C to the product AB
175template <concepts::matrix MC, concepts::matrix MA, concepts::matrix MB>
176DETRAY_HOST_DEVICE constexpr void set_product(MC &C, const MA &A, const MB &B)
177 requires(detray::concepts::matrix_multipliable_into<MA, MB, MC>)
178{
179 using index_t = detray::traits::index_t<MC>;
180 using value_t = detray::traits::value_t<MC>;
181
182 for (index_t i = 0; i < detray::traits::rows<MC>; ++i) {
183 for (index_t j = 0; j < detray::traits::columns<MC>; ++j) {
184 value_t t = 0.f;
185
186 for (index_t k = 0; k < detray::traits::rows<MB>; ++k) {
187 t += detray::traits::element_getter_t<MA>()(A, i, k) *
188 detray::traits::element_getter_t<MB>()(B, k, j);
189 }
190
191 detray::traits::element_getter_t<MC>()(C, i, j) = t;
192 }
193 }
194}
195
196// Set matrix C to the product A^TB
197template <concepts::matrix MC, concepts::matrix MA, concepts::matrix MB>
198DETRAY_HOST_DEVICE constexpr void set_product_left_transpose(MC &C, const MA &A,
199 const MB &B)
200 requires(detray::concepts::matrix_multipliable_into<
201 decltype(transpose(std::declval<MA>())), MB, MC>)
202{
203 using index_t = detray::traits::index_t<MC>;
204 using value_t = detray::traits::value_t<MC>;
205
206 for (index_t i = 0; i < detray::traits::rows<MC>; ++i) {
207 for (index_t j = 0; j < detray::traits::columns<MC>; ++j) {
208 value_t t = 0.f;
209
210 for (index_t k = 0; k < detray::traits::rows<MB>; ++k) {
211 t += detray::traits::element_getter_t<MA>()(A, k, i) *
212 detray::traits::element_getter_t<MB>()(B, k, j);
213 }
214
215 detray::traits::element_getter_t<MC>()(C, i, j) = t;
216 }
217 }
218}
219
220// Set matrix C to the product AB^T
221template <concepts::matrix MC, concepts::matrix MA, concepts::matrix MB>
222DETRAY_HOST_DEVICE constexpr void set_product_right_transpose(MC &C,
223 const MA &A,
224 const MB &B)
225 requires(detray::concepts::matrix_multipliable_into<
226 MA, decltype(transpose(std::declval<MB>())), MC>)
227{
228 using index_t = detray::traits::index_t<MC>;
229 using value_t = detray::traits::value_t<MC>;
230
231 for (index_t i = 0; i < detray::traits::rows<MC>; ++i) {
232 for (index_t j = 0; j < detray::traits::columns<MC>; ++j) {
233 value_t t = 0.f;
234
235 for (index_t k = 0; k < detray::traits::columns<MA>; ++k) {
236 t += detray::traits::element_getter_t<MA>()(A, i, k) *
237 detray::traits::element_getter_t<MB>()(B, j, k);
238 }
239
240 detray::traits::element_getter_t<MC>()(C, i, j) = t;
241 }
242 }
243}
244
245// Set matrix A to the product AB in place
246template <concepts::matrix MA, concepts::matrix MB>
247DETRAY_HOST_DEVICE constexpr void set_inplace_product_right(MA &A, const MB &B)
248 requires(detray::concepts::matrix_multipliable_into<MA, MB, MA>)
249{
250 using index_t = detray::traits::index_t<MA>;
251 using value_t = detray::traits::value_t<MA>;
252
253 for (index_t i = 0; i < detray::traits::rows<MA>; ++i) {
254 detray::traits::get_matrix_t<MA, 1, detray::traits::columns<MA>, value_t> Q;
255
256 for (index_t j = 0; j < detray::traits::columns<MA>; ++j) {
257 detray::traits::element_getter_t<decltype(Q)>()(Q, 0, j) =
258 detray::traits::element_getter_t<MA>()(A, i, j);
259 }
260
261 for (index_t j = 0; j < detray::traits::columns<MA>; ++j) {
262 value_t t = 0.f;
263
264 for (index_t k = 0; k < detray::traits::rows<MB>; ++k) {
265 t += detray::traits::element_getter_t<decltype(Q)>()(Q, 0, k) *
266 detray::traits::element_getter_t<MB>()(B, k, j);
267 }
268
269 detray::traits::element_getter_t<MA>()(A, i, j) = t;
270 }
271 }
272}
273
274// Set matrix A to the product BA in place
275template <concepts::matrix MA, concepts::matrix MB>
276DETRAY_HOST_DEVICE constexpr void set_inplace_product_left(MA &A, const MB &B)
277 requires(detray::concepts::matrix_multipliable_into<MB, MA, MA>)
278{
279 using index_t = detray::traits::index_t<MA>;
280 using value_t = detray::traits::value_t<MA>;
281
282 for (index_t j = 0; j < detray::traits::columns<MA>; ++j) {
283 detray::traits::get_matrix_t<MA, 1, detray::traits::columns<MA>, value_t> Q;
284
285 for (index_t i = 0; i < detray::traits::rows<MA>; ++i) {
286 detray::traits::element_getter_t<decltype(Q)>()(Q, 0, i) =
287 detray::traits::element_getter_t<MA>()(A, i, j);
288 }
289
290 for (index_t i = 0; i < detray::traits::rows<MA>; ++i) {
291 value_t t = 0.f;
292
293 for (index_t k = 0; k < detray::traits::columns<MB>; ++k) {
294 t += detray::traits::element_getter_t<MB>()(B, i, k) *
295 detray::traits::element_getter_t<decltype(Q)>()(Q, 0, k);
296 }
297
298 detray::traits::element_getter_t<MA>()(A, i, j) = t;
299 }
300 }
301}
302
303// Set matrix A to the product AB^T in place
304template <concepts::matrix MA, concepts::matrix MB>
305DETRAY_HOST_DEVICE constexpr void set_inplace_product_right_transpose(
306 MA &A, const MB &B)
307 requires(detray::concepts::matrix_multipliable_into<
308 MA, decltype(transpose(std::declval<MB>())), MA>)
309{
310 using index_t = detray::traits::index_t<MA>;
311 using value_t = detray::traits::value_t<MA>;
312
313 for (index_t i = 0; i < detray::traits::rows<MA>; ++i) {
314 detray::traits::get_matrix_t<MA, 1, detray::traits::columns<MA>, value_t> Q;
315
316 for (index_t j = 0; j < detray::traits::columns<MA>; ++j) {
317 detray::traits::element_getter_t<decltype(Q)>()(Q, 0, j) =
318 detray::traits::element_getter_t<MA>()(A, i, j);
319 }
320
321 for (index_t j = 0; j < detray::traits::columns<MA>; ++j) {
322 value_t T = 0.f;
323
324 for (index_t k = 0; k < detray::traits::columns<MB>; ++k) {
325 T += detray::traits::element_getter_t<decltype(Q)>()(Q, 0, k) *
326 detray::traits::element_getter_t<MB>()(B, j, k);
327 }
328
329 detray::traits::element_getter_t<MA>()(A, i, j) = T;
330 }
331 }
332}
333
334// Set matrix A to the product B^TA in place
335template <concepts::matrix MA, concepts::matrix MB>
336DETRAY_HOST_DEVICE constexpr void set_inplace_product_left_transpose(
337 MA &A, const MB &B)
338 requires(detray::concepts::matrix_multipliable_into<
339 decltype(transpose(std::declval<MB>())), MA, MA>)
340{
341 using index_t = detray::traits::index_t<MA>;
342 using value_t = detray::traits::value_t<MA>;
343
344 for (index_t j = 0; j < detray::traits::columns<MA>; ++j) {
345 detray::traits::get_matrix_t<MA, 1, detray::traits::columns<MA>, value_t> Q;
346
347 for (index_t i = 0; i < detray::traits::rows<MA>; ++i) {
348 detray::traits::element_getter_t<decltype(Q)>()(Q, 0, i) =
349 detray::traits::element_getter_t<MA>()(A, i, j);
350 }
351
352 for (index_t i = 0; i < detray::traits::rows<MA>; ++i) {
353 value_t T = 0.f;
354
355 for (index_t k = 0; k < detray::traits::rows<MB>; ++k) {
356 T += detray::traits::element_getter_t<MB>()(B, k, i) *
357 detray::traits::element_getter_t<decltype(Q)>()(Q, 0, k);
358 }
359
360 detray::traits::element_getter_t<MA>()(A, i, j) = T;
361 }
362 }
363}
364
365template <bool transpose, concepts::matrix M>
366DETRAY_HOST_DEVICE constexpr detray::traits::value_t<M> transposable_get(
367 const M &A, const detray::traits::index_t<M> i,
368 const detray::traits::index_t<M> j) {
369 if constexpr (transpose) {
370 return detray::traits::element_getter_t<M>()(A, j, i);
371 } else {
372 return detray::traits::element_getter_t<M>()(A, i, j);
373 }
374}
375
376template <bool transpose_left, bool transpose_right, concepts::matrix MA,
377 concepts::matrix MB>
378DETRAY_HOST_DEVICE constexpr auto transposed_product(const MA &A, const MB &B)
379 requires(detray::concepts::matrix_multipliable<
380 std::conditional_t<transpose_left,
381 decltype(transpose(std::declval<MA>())), MA>,
382 std::conditional_t<transpose_right,
383 decltype(transpose(std::declval<MB>())), MB>>)
384{
385 using index_t = detray::traits::index_t<MA>;
386 using value_t = detray::traits::value_t<MA>;
387
388 using effective_lhs_t =
389 std::conditional_t<transpose_left,
390 decltype(transpose(std::declval<MA>())), MA>;
391 using effective_rhs_t =
392 std::conditional_t<transpose_right,
393 decltype(transpose(std::declval<MB>())), MB>;
394
395 using result_t =
396 detray::traits::get_matrix_t<MA, detray::traits::rows<effective_lhs_t>,
397 detray::traits::columns<effective_rhs_t>,
398 value_t>;
399
400 result_t C = zero<result_t>();
401
402 for (index_t i = 0; i < detray::traits::columns<effective_lhs_t>; ++i) {
403 for (index_t j = 0; j < detray::traits::columns<result_t>; ++j) {
404 for (index_t k = 0; k < detray::traits::rows<result_t>; ++k) {
405 detray::traits::element_getter_t<result_t>()(C, k, j) +=
406 transposable_get<transpose_left>(A, k, i) *
407 transposable_get<transpose_right>(B, i, j);
408 }
409 }
410 }
411
412 return C;
413}
414
416template <concepts::square_matrix M>
417DETRAY_HOST_DEVICE constexpr detray::traits::scalar_t<M> determinant(
418 const M &m) {
419 return determinant_t<M>{}(m);
420}
421
423template <concepts::square_matrix M>
424DETRAY_HOST_DEVICE constexpr M inverse(const M &m) {
425 return inversion_t<M>{}(m);
426}
427
429template <concepts::square_matrix M>
430DETRAY_HOST_DEVICE constexpr M cholesky_decomposition(const M &m) {
431 using index_t = detray::traits::index_t<M>;
432 using scalar_t = detray::traits::scalar_t<M>;
433 using element_getter_t = detray::traits::element_getter_t<M>;
434
435 constexpr element_getter_t elem{};
436 constexpr index_t N{detray::traits::max_rank<M>};
437
438 auto L = zero<M>();
439
440 // Cholesky–Banachiewicz algorithm
441 for (std::size_t i = 0u; i < N; i++) {
442 for (std::size_t j = 0u; j <= i; j++) {
443 scalar_t sum = 0.f;
444 for (std::size_t k = 0u; k < j; k++) {
445 sum += elem(L, i, k) * elem(L, j, k);
446 }
447
448 if (i == j) {
449 elem(L, i, j) = static_cast<scalar_t>(
450 detray::algebra::math::sqrt(elem(m, i, i) - sum));
451 } else {
452 elem(L, i, j) = (1.f / elem(L, j, j) * (elem(m, i, j) - sum));
453 }
454 }
455 }
456
457 return L;
458}
459
460} // namespace detray::algebra::generic::math
constexpr double m
Meter.
Definition Units.hpp:97
constexpr double T
Magnetic field, native unit (eV*s)/(e*m²).
Definition Units.hpp:168
constexpr decltype(auto) sqrt(T &&vec)
Definition vc_soa_math.hpp:78