WPILibC++ 2027.0.0-alpha-4
Loading...
Searching...
No Matches
variable_matrix.hpp
Go to the documentation of this file.
1// Copyright (c) Sleipnir contributors
2
3#pragma once
4
5#include <algorithm>
6#include <concepts>
7#include <initializer_list>
8#include <iterator>
9#include <span>
10#include <utility>
11#include <vector>
12
13#include <Eigen/Core>
14#include <Eigen/QR>
15#include <gch/small_vector.hpp>
16
26
27namespace slp {
28
29/// A matrix of autodiff variables.
30///
31/// @tparam Scalar_ Scalar type.
32template <typename Scalar_>
34 public:
35 /// Scalar type alias.
36 using Scalar = Scalar_;
37
38 /// Constructs an empty VariableMatrix.
39 VariableMatrix() = default;
40
41 /// Constructs a zero-initialized VariableMatrix column vector with the given
42 /// rows.
43 ///
44 /// @param rows The number of matrix rows.
45 explicit VariableMatrix(int rows) : VariableMatrix{rows, 1} {}
46
47 /// Constructs a zero-initialized VariableMatrix with the given dimensions.
48 ///
49 /// @param rows The number of matrix rows.
50 /// @param cols The number of matrix columns.
51 VariableMatrix(int rows, int cols) : m_rows{rows}, m_cols{cols} {
52 m_storage.reserve(rows * cols);
53 for (int index = 0; index < rows * cols; ++index) {
54 m_storage.emplace_back();
55 }
56 }
57
58 /// Constructs an empty VariableMatrix with the given dimensions.
59 ///
60 /// @param rows The number of matrix rows.
61 /// @param cols The number of matrix columns.
63 : m_rows{rows}, m_cols{cols} {
64 m_storage.reserve(rows * cols);
65 for (int index = 0; index < rows * cols; ++index) {
66 m_storage.emplace_back(nullptr);
67 }
68 }
69
70 /// Constructs a scalar VariableMatrix from a nested list of Variables.
71 ///
72 /// @param list The nested list of Variables.
74 std::initializer_list<std::initializer_list<Variable<Scalar>>> list) {
75 // Get row and column counts for destination matrix
76 m_rows = list.size();
77 m_cols = 0;
78 if (list.size() > 0) {
79 m_cols = list.begin()->size();
80 }
81
82 // Assert all column counts are the same
83 for ([[maybe_unused]]
84 const auto& row : list) {
85 slp_assert(static_cast<int>(row.size()) == m_cols);
86 }
87
88 m_storage.reserve(rows() * cols());
89 for (const auto& row : list) {
90 std::ranges::copy(row, std::back_inserter(m_storage));
91 }
92 }
93
94 /// Constructs a scalar VariableMatrix from a nested list of scalars.
95 ///
96 /// This overload is for Python bindings only.
97 ///
98 /// @param list The nested list of Variables.
99 // NOLINTNEXTLINE (google-explicit-constructor)
100 VariableMatrix(const std::vector<std::vector<Scalar>>& list) {
101 // Get row and column counts for destination matrix
102 m_rows = list.size();
103 m_cols = 0;
104 if (list.size() > 0) {
105 m_cols = list.begin()->size();
106 }
107
108 // Assert all column counts are the same
109 for ([[maybe_unused]]
110 const auto& row : list) {
111 slp_assert(static_cast<int>(row.size()) == m_cols);
112 }
113
114 m_storage.reserve(rows() * cols());
115 for (const auto& row : list) {
116 std::ranges::copy(row, std::back_inserter(m_storage));
117 }
118 }
119
120 /// Constructs a scalar VariableMatrix from a nested list of Variables.
121 ///
122 /// This overload is for Python bindings only.
123 ///
124 /// @param list The nested list of Variables.
125 // NOLINTNEXTLINE (google-explicit-constructor)
126 VariableMatrix(const std::vector<std::vector<Variable<Scalar>>>& list) {
127 // Get row and column counts for destination matrix
128 m_rows = list.size();
129 m_cols = 0;
130 if (list.size() > 0) {
131 m_cols = list.begin()->size();
132 }
133
134 // Assert all column counts are the same
135 for ([[maybe_unused]]
136 const auto& row : list) {
137 slp_assert(static_cast<int>(row.size()) == m_cols);
138 }
139
140 m_storage.reserve(rows() * cols());
141 for (const auto& row : list) {
142 std::ranges::copy(row, std::back_inserter(m_storage));
143 }
144 }
145
146 /// Constructs a VariableMatrix from an Eigen matrix.
147 ///
148 /// @param values Eigen matrix of values.
149 template <typename Derived>
150 // NOLINTNEXTLINE (google-explicit-constructor)
151 VariableMatrix(const Eigen::MatrixBase<Derived>& values)
152 : m_rows{static_cast<int>(values.rows())},
153 m_cols{static_cast<int>(values.cols())} {
154 m_storage.reserve(values.rows() * values.cols());
155 for (int row = 0; row < values.rows(); ++row) {
156 for (int col = 0; col < values.cols(); ++col) {
157 m_storage.emplace_back(values(row, col));
158 }
159 }
160 }
161
162 /// Constructs a VariableMatrix from an Eigen diagonal matrix.
163 ///
164 /// @param values Diagonal matrix of values.
165 template <typename Derived>
166 // NOLINTNEXTLINE (google-explicit-constructor)
167 VariableMatrix(const Eigen::DiagonalBase<Derived>& values)
168 : m_rows{static_cast<int>(values.rows())},
169 m_cols{static_cast<int>(values.cols())} {
170 m_storage.reserve(values.rows() * values.cols());
171 for (int row = 0; row < values.rows(); ++row) {
172 for (int col = 0; col < values.cols(); ++col) {
173 if (row == col) {
174 m_storage.emplace_back(values.diagonal()[row]);
175 } else {
176 m_storage.emplace_back(Scalar(0));
177 }
178 }
179 }
180 }
181
182 /// Constructs a scalar VariableMatrix from a Variable.
183 ///
184 /// @param variable Variable.
185 // NOLINTNEXTLINE (google-explicit-constructor)
186 VariableMatrix(const Variable<Scalar>& variable) : m_rows{1}, m_cols{1} {
187 m_storage.emplace_back(variable);
188 }
189
190 /// Constructs a scalar VariableMatrix from a Variable.
191 ///
192 /// @param variable Variable.
193 // NOLINTNEXTLINE (google-explicit-constructor)
194 VariableMatrix(Variable<Scalar>&& variable) : m_rows{1}, m_cols{1} {
195 m_storage.emplace_back(std::move(variable));
196 }
197
198 /// Constructs a VariableMatrix from a VariableBlock.
199 ///
200 /// @param values VariableBlock of values.
201 // NOLINTNEXTLINE (google-explicit-constructor)
203 : m_rows{values.rows()}, m_cols{values.cols()} {
204 m_storage.reserve(rows() * cols());
205 for (int row = 0; row < rows(); ++row) {
206 for (int col = 0; col < cols(); ++col) {
207 m_storage.emplace_back(values(row, col));
208 }
209 }
210 }
211
212 /// Constructs a VariableMatrix from a VariableBlock.
213 ///
214 /// @param values VariableBlock of values.
215 // NOLINTNEXTLINE (google-explicit-constructor)
217 : m_rows{values.rows()}, m_cols{values.cols()} {
218 m_storage.reserve(rows() * cols());
219 for (int row = 0; row < rows(); ++row) {
220 for (int col = 0; col < cols(); ++col) {
221 m_storage.emplace_back(values(row, col));
222 }
223 }
224 }
225
226 /// Constructs a column vector wrapper around a Variable array.
227 ///
228 /// @param values Variable array to wrap.
229 explicit VariableMatrix(std::span<const Variable<Scalar>> values)
230 : m_rows{static_cast<int>(values.size())}, m_cols{1} {
231 m_storage.reserve(rows() * cols());
232 for (int row = 0; row < rows(); ++row) {
233 for (int col = 0; col < cols(); ++col) {
234 m_storage.emplace_back(values[row * cols() + col]);
235 }
236 }
237 }
238
239 /// Constructs a matrix wrapper around a Variable array.
240 ///
241 /// @param values Variable array to wrap.
242 /// @param rows The number of matrix rows.
243 /// @param cols The number of matrix columns.
244 VariableMatrix(std::span<const Variable<Scalar>> values, int rows, int cols)
245 : m_rows{rows}, m_cols{cols} {
246 slp_assert(static_cast<int>(values.size()) == rows * cols);
247 m_storage.reserve(rows * cols);
248 for (int row = 0; row < rows; ++row) {
249 for (int col = 0; col < cols; ++col) {
250 m_storage.emplace_back(values[row * cols + col]);
251 }
252 }
253 }
254
255 /// Assigns an Eigen matrix to a VariableMatrix.
256 ///
257 /// @param values Eigen matrix of values.
258 /// @return This VariableMatrix.
259 template <typename Derived>
260 VariableMatrix& operator=(const Eigen::MatrixBase<Derived>& values) {
261 slp_assert(rows() == values.rows() && cols() == values.cols());
262
263 for (int row = 0; row < values.rows(); ++row) {
264 for (int col = 0; col < values.cols(); ++col) {
265 (*this)(row, col) = values(row, col);
266 }
267 }
268
269 return *this;
270 }
271
272 /// Assigns a scalar to the matrix.
273 ///
274 /// This only works for matrices with one row and one column.
275 ///
276 /// @param value Value to assign.
277 /// @return This VariableMatrix.
279 slp_assert(rows() == 1 && cols() == 1);
280
281 (*this)(0, 0) = value;
282
283 return *this;
284 }
285
286 /// Sets the VariableMatrix's internal values.
287 ///
288 /// @param values Eigen matrix of values.
289 template <typename Derived>
290 requires std::same_as<typename Derived::Scalar, Scalar>
291 void set_value(const Eigen::MatrixBase<Derived>& values) {
292 slp_assert(rows() == values.rows() && cols() == values.cols());
293
294 for (int row = 0; row < values.rows(); ++row) {
295 for (int col = 0; col < values.cols(); ++col) {
296 (*this)(row, col).set_value(values(row, col));
297 }
298 }
299 }
300
301 /// Returns the element at the given row and column.
302 ///
303 /// @param row The row.
304 /// @param col The column.
305 /// @return The element at the given row and column.
307 slp_assert(row >= 0 && row < rows());
308 slp_assert(col >= 0 && col < cols());
309 return m_storage[row * cols() + col];
310 }
311
312 /// Returns the element at the given row and column.
313 ///
314 /// @param row The row.
315 /// @param col The column.
316 /// @return The element at the given row and column.
317 const Variable<Scalar>& operator()(int row, int col) const {
318 slp_assert(row >= 0 && row < rows());
319 slp_assert(col >= 0 && col < cols());
320 return m_storage[row * cols() + col];
321 }
322
323 /// Returns the element at the given index.
324 ///
325 /// @param index The index.
326 /// @return The element at the given index.
328 slp_assert(index >= 0 && index < rows() * cols());
329 return m_storage[index];
330 }
331
332 /// Returns the element at the given index.
333 ///
334 /// @param index The index.
335 /// @return The element at the given index.
337 slp_assert(index >= 0 && index < rows() * cols());
338 return m_storage[index];
339 }
340
341 /// Returns a block of the variable matrix.
342 ///
343 /// @param row_offset The row offset of the block selection.
344 /// @param col_offset The column offset of the block selection.
345 /// @param block_rows The number of rows in the block selection.
346 /// @param block_cols The number of columns in the block selection.
347 /// @return A block of the variable matrix.
348 VariableBlock<VariableMatrix> block(int row_offset, int col_offset,
349 int block_rows, int block_cols) {
350 slp_assert(row_offset >= 0 && row_offset <= rows());
351 slp_assert(col_offset >= 0 && col_offset <= cols());
352 slp_assert(block_rows >= 0 && block_rows <= rows() - row_offset);
353 slp_assert(block_cols >= 0 && block_cols <= cols() - col_offset);
354 return VariableBlock{*this, row_offset, col_offset, block_rows, block_cols};
355 }
356
357 /// Returns a block of the variable matrix.
358 ///
359 /// @param row_offset The row offset of the block selection.
360 /// @param col_offset The column offset of the block selection.
361 /// @param block_rows The number of rows in the block selection.
362 /// @param block_cols The number of columns in the block selection.
363 /// @return A block of the variable matrix.
365 int col_offset,
366 int block_rows,
367 int block_cols) const {
368 slp_assert(row_offset >= 0 && row_offset <= rows());
369 slp_assert(col_offset >= 0 && col_offset <= cols());
370 slp_assert(block_rows >= 0 && block_rows <= rows() - row_offset);
371 slp_assert(block_cols >= 0 && block_cols <= cols() - col_offset);
372 return VariableBlock{*this, row_offset, col_offset, block_rows, block_cols};
373 }
374
375 /// Returns a slice of the variable matrix.
376 ///
377 /// @param row_slice The row slice.
378 /// @param col_slice The column slice.
379 /// @return A slice of the variable matrix.
381 int row_slice_length = row_slice.adjust(rows());
382 int col_slice_length = col_slice.adjust(cols());
383 return VariableBlock{*this, std::move(row_slice), row_slice_length,
384 std::move(col_slice), col_slice_length};
385 }
386
387 /// Returns a slice of the variable matrix.
388 ///
389 /// @param row_slice The row slice.
390 /// @param col_slice The column slice.
391 /// @return A slice of the variable matrix.
393 Slice col_slice) const {
394 int row_slice_length = row_slice.adjust(rows());
395 int col_slice_length = col_slice.adjust(cols());
396 return VariableBlock{*this, std::move(row_slice), row_slice_length,
397 std::move(col_slice), col_slice_length};
398 }
399
400 /// Returns a slice of the variable matrix.
401 ///
402 /// The given slices aren't adjusted. This overload is for Python bindings
403 /// only.
404 ///
405 /// @param row_slice The row slice.
406 /// @param row_slice_length The row slice length.
407 /// @param col_slice The column slice.
408 /// @param col_slice_length The column slice length.
409 /// @return A slice of the variable matrix.
411 int row_slice_length,
412 Slice col_slice,
413 int col_slice_length) {
414 return VariableBlock{*this, std::move(row_slice), row_slice_length,
415 std::move(col_slice), col_slice_length};
416 }
417
418 /// Returns a slice of the variable matrix.
419 ///
420 /// The given slices aren't adjusted. This overload is for Python bindings
421 /// only.
422 ///
423 /// @param row_slice The row slice.
424 /// @param row_slice_length The row slice length.
425 /// @param col_slice The column slice.
426 /// @param col_slice_length The column slice length.
427 /// @return A slice of the variable matrix.
429 Slice row_slice, int row_slice_length, Slice col_slice,
430 int col_slice_length) const {
431 return VariableBlock{*this, std::move(row_slice), row_slice_length,
432 std::move(col_slice), col_slice_length};
433 }
434
435 /// Returns a segment of the variable vector.
436 ///
437 /// @param offset The offset of the segment.
438 /// @param length The length of the segment.
439 /// @return A segment of the variable vector.
440 VariableBlock<VariableMatrix> segment(int offset, int length) {
441 slp_assert(cols() == 1);
442 slp_assert(offset >= 0 && offset < rows());
443 slp_assert(length >= 0 && length <= rows() - offset);
444 return block(offset, 0, length, 1);
445 }
446
447 /// Returns a segment of the variable vector.
448 ///
449 /// @param offset The offset of the segment.
450 /// @param length The length of the segment.
451 /// @return A segment of the variable vector.
453 int length) const {
454 slp_assert(cols() == 1);
455 slp_assert(offset >= 0 && offset < rows());
456 slp_assert(length >= 0 && length <= rows() - offset);
457 return block(offset, 0, length, 1);
458 }
459
460 /// Returns a row slice of the variable matrix.
461 ///
462 /// @param row The row to slice.
463 /// @return A row slice of the variable matrix.
465 slp_assert(row >= 0 && row < rows());
466 return block(row, 0, 1, cols());
467 }
468
469 /// Returns a row slice of the variable matrix.
470 ///
471 /// @param row The row to slice.
472 /// @return A row slice of the variable matrix.
474 slp_assert(row >= 0 && row < rows());
475 return block(row, 0, 1, cols());
476 }
477
478 /// Returns a column slice of the variable matrix.
479 ///
480 /// @param col The column to slice.
481 /// @return A column slice of the variable matrix.
483 slp_assert(col >= 0 && col < cols());
484 return block(0, col, rows(), 1);
485 }
486
487 /// Returns a column slice of the variable matrix.
488 ///
489 /// @param col The column to slice.
490 /// @return A column slice of the variable matrix.
492 slp_assert(col >= 0 && col < cols());
493 return block(0, col, rows(), 1);
494 }
495
496 /// Matrix multiplication operator.
497 ///
498 /// @param lhs Operator left-hand side.
499 /// @param rhs Operator right-hand side.
500 template <EigenMatrixLike LHS, SleipnirMatrixLike<Scalar> RHS>
501 friend VariableMatrix<Scalar> operator*(const LHS& lhs, const RHS& rhs) {
502 slp_assert(lhs.cols() == rhs.rows());
503
504 VariableMatrix<Scalar> result(detail::empty, lhs.rows(), rhs.cols());
505
506#if __GNUC__ >= 12
507#pragma GCC diagnostic push
508#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
509#endif
510 for (int i = 0; i < lhs.rows(); ++i) {
511 for (int j = 0; j < rhs.cols(); ++j) {
512 Variable sum{Scalar(0)};
513 for (int k = 0; k < lhs.cols(); ++k) {
514 sum += lhs(i, k) * rhs(k, j);
515 }
516 result(i, j) = sum;
517 }
518 }
519
520 return result;
521 }
522
523 /// Matrix multiplication operator.
524 ///
525 /// @param lhs Operator left-hand side.
526 /// @param rhs Operator right-hand side.
527 template <SleipnirMatrixLike<Scalar> LHS, EigenMatrixLike RHS>
528 friend VariableMatrix<Scalar> operator*(const LHS& lhs, const RHS& rhs) {
529 slp_assert(lhs.cols() == rhs.rows());
530
531 VariableMatrix<Scalar> result(detail::empty, lhs.rows(), rhs.cols());
532
533 for (int i = 0; i < lhs.rows(); ++i) {
534 for (int j = 0; j < rhs.cols(); ++j) {
535 Variable sum{Scalar(0)};
536 for (int k = 0; k < lhs.cols(); ++k) {
537 sum += lhs(i, k) * rhs(k, j);
538 }
539 result(i, j) = sum;
540 }
541 }
542
543 return result;
544 }
545
546 /// Matrix multiplication operator.
547 ///
548 /// @param lhs Operator left-hand side.
549 /// @param rhs Operator right-hand side.
550 template <SleipnirMatrixLike<Scalar> LHS, SleipnirMatrixLike<Scalar> RHS>
551 friend VariableMatrix<Scalar> operator*(const LHS& lhs, const RHS& rhs) {
552 slp_assert(lhs.cols() == rhs.rows());
553
554 VariableMatrix<Scalar> result(detail::empty, lhs.rows(), rhs.cols());
555
556 for (int i = 0; i < lhs.rows(); ++i) {
557 for (int j = 0; j < rhs.cols(); ++j) {
558 Variable sum{Scalar(0)};
559 for (int k = 0; k < lhs.cols(); ++k) {
560 sum += lhs(i, k) * rhs(k, j);
561 }
562 result(i, j) = sum;
563 }
564 }
565#if __GNUC__ >= 12
566#pragma GCC diagnostic pop
567#endif
568
569 return result;
570 }
571
572 /// Matrix-scalar multiplication operator.
573 ///
574 /// @param lhs Operator left-hand side.
575 /// @param rhs Operator right-hand side.
576 template <EigenMatrixLike LHS>
577 friend VariableMatrix<Scalar> operator*(const LHS& lhs,
578 const Variable<Scalar>& rhs) {
579 VariableMatrix<Scalar> result(detail::empty, lhs.rows(), lhs.cols());
580
581 for (int row = 0; row < result.rows(); ++row) {
582 for (int col = 0; col < result.cols(); ++col) {
583 result(row, col) = lhs(row, col) * rhs;
584 }
585 }
586
587 return result;
588 }
589
590 /// Matrix-scalar multiplication operator.
591 ///
592 /// @param lhs Operator left-hand side.
593 /// @param rhs Operator right-hand side.
594 template <SleipnirMatrixLike<Scalar> LHS, ScalarLike RHS>
595 friend VariableMatrix<Scalar> operator*(const LHS& lhs, const RHS& rhs) {
596 VariableMatrix<Scalar> result(detail::empty, lhs.rows(), lhs.cols());
597
598 for (int row = 0; row < result.rows(); ++row) {
599 for (int col = 0; col < result.cols(); ++col) {
600 result(row, col) = lhs(row, col) * rhs;
601 }
602 }
603
604 return result;
605 }
606
607 /// Scalar-matrix multiplication operator.
608 ///
609 /// @param lhs Operator left-hand side.
610 /// @param rhs Operator right-hand side.
611 template <EigenMatrixLike RHS>
613 const RHS& rhs) {
614 VariableMatrix<Scalar> result(detail::empty, rhs.rows(), rhs.cols());
615
616 for (int row = 0; row < result.rows(); ++row) {
617 for (int col = 0; col < result.cols(); ++col) {
618 result(row, col) = rhs(row, col) * lhs;
619 }
620 }
621
622 return result;
623 }
624
625 /// Scalar-matrix multiplication operator.
626 ///
627 /// @param lhs Operator left-hand side.
628 /// @param rhs Operator right-hand side.
629 template <ScalarLike LHS, SleipnirMatrixLike<Scalar> RHS>
630 friend VariableMatrix<Scalar> operator*(const LHS& lhs, const RHS& rhs) {
631 VariableMatrix<Scalar> result(detail::empty, rhs.rows(), rhs.cols());
632
633 for (int row = 0; row < result.rows(); ++row) {
634 for (int col = 0; col < result.cols(); ++col) {
635 result(row, col) = rhs(row, col) * lhs;
636 }
637 }
638
639 return result;
640 }
641
642 /// Compound matrix multiplication-assignment operator.
643 ///
644 /// @param rhs Variable to multiply.
645 /// @return Result of multiplication.
647 slp_assert(cols() == rhs.rows() && cols() == rhs.cols());
648
649 for (int i = 0; i < rows(); ++i) {
650 for (int j = 0; j < rhs.cols(); ++j) {
651 Variable sum{Scalar(0)};
652 for (int k = 0; k < cols(); ++k) {
653 sum += (*this)(i, k) * rhs(k, j);
654 }
655 (*this)(i, j) = sum;
656 }
657 }
658
659 return *this;
660 }
661
662 /// Compound matrix-scalar multiplication-assignment operator.
663 ///
664 /// @param rhs Variable to multiply.
665 /// @return Result of multiplication.
667 for (int row = 0; row < rows(); ++row) {
668 for (int col = 0; col < rhs.cols(); ++col) {
669 (*this)(row, col) *= rhs;
670 }
671 }
672
673 return *this;
674 }
675
676 /// Binary division operator.
677 ///
678 /// @param lhs Operator left-hand side.
679 /// @param rhs Operator right-hand side.
680 /// @return Result of division.
681 template <EigenMatrixLike LHS>
682 friend VariableMatrix<Scalar> operator/(const LHS& lhs,
683 const Variable<Scalar>& rhs) {
684 VariableMatrix<Scalar> result(detail::empty, lhs.rows(), lhs.cols());
685
686 for (int row = 0; row < result.rows(); ++row) {
687 for (int col = 0; col < result.cols(); ++col) {
688 result(row, col) = lhs(row, col) / rhs;
689 }
690 }
691
692 return result;
693 }
694
695 /// Binary division operator.
696 ///
697 /// @param lhs Operator left-hand side.
698 /// @param rhs Operator right-hand side.
699 /// @return Result of division.
700 template <SleipnirMatrixLike<Scalar> LHS, ScalarLike RHS>
702 friend VariableMatrix<Scalar> operator/(const LHS& lhs, const RHS& rhs) {
703 VariableMatrix<Scalar> result(detail::empty, lhs.rows(), lhs.cols());
704
705 for (int row = 0; row < result.rows(); ++row) {
706 for (int col = 0; col < result.cols(); ++col) {
707 result(row, col) = lhs(row, col) / rhs;
708 }
709 }
710
711 return result;
712 }
713
714 /// Binary division operator.
715 ///
716 /// @param lhs Operator left-hand side.
717 /// @param rhs Operator right-hand side.
718 /// @return Result of division.
719 template <SleipnirMatrixLike<Scalar> LHS>
720 friend VariableMatrix<Scalar> operator/(const LHS& lhs,
721 const Variable<Scalar>& rhs) {
722 VariableMatrix<Scalar> result(detail::empty, lhs.rows(), lhs.cols());
723
724 for (int row = 0; row < result.rows(); ++row) {
725 for (int col = 0; col < result.cols(); ++col) {
726 result(row, col) = lhs(row, col) / rhs;
727 }
728 }
729
730 return result;
731 }
732
733 /// Compound matrix division-assignment operator.
734 ///
735 /// @param rhs Variable to divide.
736 /// @return Result of division.
738 for (int row = 0; row < rows(); ++row) {
739 for (int col = 0; col < cols(); ++col) {
740 (*this)(row, col) /= rhs;
741 }
742 }
743
744 return *this;
745 }
746
747 /// Binary addition operator.
748 ///
749 /// @param lhs Operator left-hand side.
750 /// @param rhs Operator right-hand side.
751 /// @return Result of addition.
752 template <EigenMatrixLike LHS, SleipnirMatrixLike<Scalar> RHS>
753 friend VariableMatrix<Scalar> operator+(const LHS& lhs, const RHS& rhs) {
754 slp_assert(lhs.rows() == rhs.rows() && lhs.cols() == rhs.cols());
755
756 VariableMatrix<Scalar> result(detail::empty, lhs.rows(), lhs.cols());
757
758 for (int row = 0; row < result.rows(); ++row) {
759 for (int col = 0; col < result.cols(); ++col) {
760 result(row, col) = lhs(row, col) + rhs(row, col);
761 }
762 }
763
764 return result;
765 }
766
767 /// Binary addition operator.
768 ///
769 /// @param lhs Operator left-hand side.
770 /// @param rhs Operator right-hand side.
771 /// @return Result of addition.
772 template <SleipnirMatrixLike<Scalar> LHS, EigenMatrixLike RHS>
773 friend VariableMatrix<Scalar> operator+(const LHS& lhs, const RHS& rhs) {
774 slp_assert(lhs.rows() == rhs.rows() && lhs.cols() == rhs.cols());
775
776 VariableMatrix<Scalar> result(detail::empty, lhs.rows(), lhs.cols());
777
778 for (int row = 0; row < result.rows(); ++row) {
779 for (int col = 0; col < result.cols(); ++col) {
780 result(row, col) = lhs(row, col) + rhs(row, col);
781 }
782 }
783
784 return result;
785 }
786
787 /// Binary addition operator.
788 ///
789 /// @param lhs Operator left-hand side.
790 /// @param rhs Operator right-hand side.
791 /// @return Result of addition.
792 template <SleipnirMatrixLike<Scalar> LHS, SleipnirMatrixLike<Scalar> RHS>
793 friend VariableMatrix<Scalar> operator+(const LHS& lhs, const RHS& rhs) {
794 slp_assert(lhs.rows() == rhs.rows() && lhs.cols() == rhs.cols());
795
796 VariableMatrix<Scalar> result(detail::empty, lhs.rows(), lhs.cols());
797
798 for (int row = 0; row < result.rows(); ++row) {
799 for (int col = 0; col < result.cols(); ++col) {
800 result(row, col) = lhs(row, col) + rhs(row, col);
801 }
802 }
803
804 return result;
805 }
806
807 /// Compound addition-assignment operator.
808 ///
809 /// @param rhs Variable to add.
810 /// @return Result of addition.
812 slp_assert(rows() == rhs.rows() && cols() == rhs.cols());
813
814 for (int row = 0; row < rows(); ++row) {
815 for (int col = 0; col < cols(); ++col) {
816 (*this)(row, col) += rhs(row, col);
817 }
818 }
819
820 return *this;
821 }
822
823 /// Compound addition-assignment operator.
824 ///
825 /// @param rhs Variable to add.
826 /// @return Result of addition.
828 slp_assert(rows() == 1 && cols() == 1);
829
830 for (int row = 0; row < rows(); ++row) {
831 for (int col = 0; col < cols(); ++col) {
832 (*this)(row, col) += rhs;
833 }
834 }
835
836 return *this;
837 }
838
839 /// Binary subtraction operator.
840 ///
841 /// @param lhs Operator left-hand side.
842 /// @param rhs Operator right-hand side.
843 /// @return Result of subtraction.
844 template <EigenMatrixLike LHS, SleipnirMatrixLike<Scalar> RHS>
845 friend VariableMatrix<Scalar> operator-(const LHS& lhs, const RHS& rhs) {
846 slp_assert(lhs.rows() == rhs.rows() && lhs.cols() == rhs.cols());
847
848 VariableMatrix<Scalar> result(detail::empty, lhs.rows(), lhs.cols());
849
850 for (int row = 0; row < result.rows(); ++row) {
851 for (int col = 0; col < result.cols(); ++col) {
852 result(row, col) = lhs(row, col) - rhs(row, col);
853 }
854 }
855
856 return result;
857 }
858
859 /// Binary subtraction operator.
860 ///
861 /// @param lhs Operator left-hand side.
862 /// @param rhs Operator right-hand side.
863 /// @return Result of subtraction.
864 template <SleipnirMatrixLike<Scalar> LHS, EigenMatrixLike RHS>
865 friend VariableMatrix<Scalar> operator-(const LHS& lhs, const RHS& rhs) {
866 slp_assert(lhs.rows() == rhs.rows() && lhs.cols() == rhs.cols());
867
868 VariableMatrix<Scalar> result(detail::empty, lhs.rows(), lhs.cols());
869
870 for (int row = 0; row < result.rows(); ++row) {
871 for (int col = 0; col < result.cols(); ++col) {
872 result(row, col) = lhs(row, col) - rhs(row, col);
873 }
874 }
875
876 return result;
877 }
878
879 /// Binary subtraction operator.
880 ///
881 /// @param lhs Operator left-hand side.
882 /// @param rhs Operator right-hand side.
883 /// @return Result of subtraction.
884 template <SleipnirMatrixLike<Scalar> LHS, SleipnirMatrixLike<Scalar> RHS>
885 friend VariableMatrix<Scalar> operator-(const LHS& lhs, const RHS& rhs) {
886 slp_assert(lhs.rows() == rhs.rows() && lhs.cols() == rhs.cols());
887
888 VariableMatrix<Scalar> result(detail::empty, lhs.rows(), lhs.cols());
889
890 for (int row = 0; row < result.rows(); ++row) {
891 for (int col = 0; col < result.cols(); ++col) {
892 result(row, col) = lhs(row, col) - rhs(row, col);
893 }
894 }
895
896 return result;
897 }
898
899 /// Compound subtraction-assignment operator.
900 ///
901 /// @param rhs Variable to subtract.
902 /// @return Result of subtraction.
904 slp_assert(rows() == rhs.rows() && cols() == rhs.cols());
905
906 for (int row = 0; row < rows(); ++row) {
907 for (int col = 0; col < cols(); ++col) {
908 (*this)(row, col) -= rhs(row, col);
909 }
910 }
911
912 return *this;
913 }
914
915 /// Compound subtraction-assignment operator.
916 ///
917 /// @param rhs Variable to subtract.
918 /// @return Result of subtraction.
920 slp_assert(rows() == 1 && cols() == 1);
921
922 for (int row = 0; row < rows(); ++row) {
923 for (int col = 0; col < cols(); ++col) {
924 (*this)(row, col) -= rhs;
925 }
926 }
927
928 return *this;
929 }
930
931 /// Unary minus operator.
932 ///
933 /// @param lhs Operand for unary minus.
935 const SleipnirMatrixLike<Scalar> auto& lhs) {
936 VariableMatrix<Scalar> result{detail::empty, lhs.rows(), lhs.cols()};
937
938 for (int row = 0; row < result.rows(); ++row) {
939 for (int col = 0; col < result.cols(); ++col) {
940 result(row, col) = -lhs(row, col);
941 }
942 }
943
944 return result;
945 }
946
947 /// Implicit conversion operator from 1x1 VariableMatrix to Variable.
948 // NOLINTNEXTLINE (google-explicit-constructor)
949 operator Variable<Scalar>() const {
950 slp_assert(rows() == 1 && cols() == 1);
951 return (*this)(0, 0);
952 }
953
954 /// Returns the transpose of the variable matrix.
955 ///
956 /// @return The transpose of the variable matrix.
959
960 for (int row = 0; row < rows(); ++row) {
961 for (int col = 0; col < cols(); ++col) {
962 result(col, row) = (*this)(row, col);
963 }
964 }
965
966 return result;
967 }
968
969 /// Returns the number of rows in the matrix.
970 ///
971 /// @return The number of rows in the matrix.
972 int rows() const { return m_rows; }
973
974 /// Returns the number of columns in the matrix.
975 ///
976 /// @return The number of columns in the matrix.
977 int cols() const { return m_cols; }
978
979 /// Returns an element of the variable matrix.
980 ///
981 /// @param row The row of the element to return.
982 /// @param col The column of the element to return.
983 /// @return An element of the variable matrix.
984 Scalar value(int row, int col) { return (*this)(row, col).value(); }
985
986 /// Returns an element of the variable matrix.
987 ///
988 /// @param index The index of the element to return.
989 /// @return An element of the variable matrix.
990 Scalar value(int index) { return (*this)[index].value(); }
991
992 /// Returns the contents of the variable matrix.
993 ///
994 /// @return The contents of the variable matrix.
995 Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic> value() {
996 Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic> result{rows(),
997 cols()};
998
999 for (int row = 0; row < rows(); ++row) {
1000 for (int col = 0; col < cols(); ++col) {
1001 result(row, col) = value(row, col);
1002 }
1003 }
1004
1005 return result;
1006 }
1007
1008 /// Transforms the matrix coefficient-wise with an unary operator.
1009 ///
1010 /// @param unary_op The unary operator to use for the transform operation.
1011 /// @return Result of the unary operator.
1014 const {
1016
1017 for (int row = 0; row < rows(); ++row) {
1018 for (int col = 0; col < cols(); ++col) {
1019 result(row, col) = unary_op((*this)(row, col));
1020 }
1021 }
1022
1023 return result;
1024 }
1025
1026#ifndef DOXYGEN_SHOULD_SKIP_THIS
1027
1028 class iterator {
1029 public:
1030 using iterator_category = std::bidirectional_iterator_tag;
1032 using difference_type = std::ptrdiff_t;
1035
1036 constexpr iterator() noexcept = default;
1037
1038 explicit constexpr iterator(
1039 gch::small_vector<Variable<Scalar>>::iterator it) noexcept
1040 : m_it{it} {}
1041
1042 constexpr iterator& operator++() noexcept {
1043 ++m_it;
1044 return *this;
1045 }
1046
1047 constexpr iterator operator++(int) noexcept {
1048 iterator retval = *this;
1049 ++(*this);
1050 return retval;
1051 }
1052
1053 constexpr iterator& operator--() noexcept {
1054 --m_it;
1055 return *this;
1056 }
1057
1058 constexpr iterator operator--(int) noexcept {
1059 iterator retval = *this;
1060 --(*this);
1061 return retval;
1062 }
1063
1064 constexpr bool operator==(const iterator&) const noexcept = default;
1065
1066 constexpr reference operator*() const noexcept { return *m_it; }
1067
1068 private:
1070 };
1071
1073 public:
1074 using iterator_category = std::bidirectional_iterator_tag;
1076 using difference_type = std::ptrdiff_t;
1079
1080 constexpr const_iterator() noexcept = default;
1081
1082 explicit constexpr const_iterator(
1083 gch::small_vector<Variable<Scalar>>::const_iterator it) noexcept
1084 : m_it{it} {}
1085
1086 constexpr const_iterator& operator++() noexcept {
1087 ++m_it;
1088 return *this;
1089 }
1090
1091 constexpr const_iterator operator++(int) noexcept {
1092 const_iterator retval = *this;
1093 ++(*this);
1094 return retval;
1095 }
1096
1097 constexpr const_iterator& operator--() noexcept {
1098 --m_it;
1099 return *this;
1100 }
1101
1102 constexpr const_iterator operator--(int) noexcept {
1103 const_iterator retval = *this;
1104 --(*this);
1105 return retval;
1106 }
1107
1108 constexpr bool operator==(const const_iterator&) const noexcept = default;
1109
1110 constexpr const_reference operator*() const noexcept { return *m_it; }
1111
1112 private:
1114 };
1115
1116 using reverse_iterator = std::reverse_iterator<iterator>;
1117 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
1118
1119#endif // DOXYGEN_SHOULD_SKIP_THIS
1120
1121 /// Returns begin iterator.
1122 ///
1123 /// @return Begin iterator.
1124 iterator begin() { return iterator{m_storage.begin()}; }
1125
1126 /// Returns end iterator.
1127 ///
1128 /// @return End iterator.
1129 iterator end() { return iterator{m_storage.end()}; }
1130
1131 /// Returns const begin iterator.
1132 ///
1133 /// @return Const begin iterator.
1134 const_iterator begin() const { return const_iterator{m_storage.begin()}; }
1135
1136 /// Returns const end iterator.
1137 ///
1138 /// @return Const end iterator.
1139 const_iterator end() const { return const_iterator{m_storage.end()}; }
1140
1141 /// Returns const begin iterator.
1142 ///
1143 /// @return Const begin iterator.
1144 const_iterator cbegin() const { return const_iterator{m_storage.begin()}; }
1145
1146 /// Returns const end iterator.
1147 ///
1148 /// @return Const end iterator.
1149 const_iterator cend() const { return const_iterator{m_storage.end()}; }
1150
1151 /// Returns reverse begin iterator.
1152 ///
1153 /// @return Reverse begin iterator.
1155
1156 /// Returns reverse end iterator.
1157 ///
1158 /// @return Reverse end iterator.
1160
1161 /// Returns const reverse begin iterator.
1162 ///
1163 /// @return Const reverse begin iterator.
1167
1168 /// Returns const reverse end iterator.
1169 ///
1170 /// @return Const reverse end iterator.
1174
1175 /// Returns const reverse begin iterator.
1176 ///
1177 /// @return Const reverse begin iterator.
1181
1182 /// Returns const reverse end iterator.
1183 ///
1184 /// @return Const reverse end iterator.
1188
1189 /// Returns number of elements in matrix.
1190 ///
1191 /// @return Number of elements in matrix.
1192 size_t size() const { return m_storage.size(); }
1193
1194 /// Returns a variable matrix filled with zeroes.
1195 ///
1196 /// @param rows The number of matrix rows.
1197 /// @param cols The number of matrix columns.
1198 /// @return A variable matrix filled with zeroes.
1201
1202 for (auto& elem : result) {
1203 elem = Scalar(0);
1204 }
1205
1206 return result;
1207 }
1208
1209 /// Returns a variable matrix filled with ones.
1210 ///
1211 /// @param rows The number of matrix rows.
1212 /// @param cols The number of matrix columns.
1213 /// @return A variable matrix filled with ones.
1216
1217 for (auto& elem : result) {
1218 elem = Scalar(1);
1219 }
1220
1221 return result;
1222 }
1223
1224 private:
1226 int m_rows = 0;
1227 int m_cols = 0;
1228};
1229
1230template <typename Derived>
1231VariableMatrix(const Eigen::MatrixBase<Derived>&)
1233
1234template <typename Derived>
1235VariableMatrix(const Eigen::DiagonalBase<Derived>&)
1237
1238/// Applies a coefficient-wise reduce operation to two matrices.
1239///
1240/// @tparam Scalar Scalar type.
1241/// @param lhs The left-hand side of the binary operator.
1242/// @param rhs The right-hand side of the binary operator.
1243/// @param binary_op The binary operator to use for the reduce operation.
1244template <typename Scalar>
1246 const VariableMatrix<Scalar>& lhs, const VariableMatrix<Scalar>& rhs,
1248 const Variable<Scalar>& y)>
1249 binary_op) {
1250 slp_assert(lhs.rows() == rhs.rows() && lhs.cols() == rhs.cols());
1251
1252 VariableMatrix<Scalar> result{detail::empty, lhs.rows(), lhs.cols()};
1253
1254 for (int row = 0; row < lhs.rows(); ++row) {
1255 for (int col = 0; col < lhs.cols(); ++col) {
1256 result(row, col) = binary_op(lhs(row, col), rhs(row, col));
1257 }
1258 }
1259
1260 return result;
1261}
1262
1263/// Assemble a VariableMatrix from a nested list of blocks.
1264///
1265/// Each row's blocks must have the same height, and the assembled block rows
1266/// must have the same width. For example, for the block matrix [[A, B], [C]] to
1267/// be constructible, the number of rows in A and B must match, and the number
1268/// of columns in [A, B] and [C] must match.
1269///
1270/// @tparam Scalar Scalar type.
1271/// @param list The nested list of blocks.
1272template <typename Scalar>
1274 std::initializer_list<std::initializer_list<VariableMatrix<Scalar>>> list) {
1275 // Get row and column counts for destination matrix
1276 int rows = 0;
1277 int cols = -1;
1278 for (const auto& row : list) {
1279 if (row.size() > 0) {
1280 rows += row.begin()->rows();
1281 }
1282
1283 // Get number of columns in this row
1284 int latest_cols = 0;
1285 for (const auto& elem : row) {
1286 // Assert the first and latest row have the same height
1287 slp_assert(row.begin()->rows() == elem.rows());
1288
1289 latest_cols += elem.cols();
1290 }
1291
1292 // If this is the first row, record the column count. Otherwise, assert the
1293 // first and latest column counts are the same.
1294 if (cols == -1) {
1295 cols = latest_cols;
1296 } else {
1297 slp_assert(cols == latest_cols);
1298 }
1299 }
1300
1301 VariableMatrix<Scalar> result{detail::empty, rows, cols};
1302
1303 int row_offset = 0;
1304 for (const auto& row : list) {
1305 int col_offset = 0;
1306 for (const auto& elem : row) {
1307 result.block(row_offset, col_offset, elem.rows(), elem.cols()) = elem;
1308 col_offset += elem.cols();
1309 }
1310 if (row.size() > 0) {
1311 row_offset += row.begin()->rows();
1312 }
1313 }
1314
1315 return result;
1316}
1317
1318/// Assemble a VariableMatrix from a nested list of blocks.
1319///
1320/// Each row's blocks must have the same height, and the assembled block rows
1321/// must have the same width. For example, for the block matrix [[A, B], [C]] to
1322/// be constructible, the number of rows in A and B must match, and the number
1323/// of columns in [A, B] and [C] must match.
1324///
1325/// This overload is for Python bindings only.
1326///
1327/// @tparam Scalar Scalar type.
1328/// @param list The nested list of blocks.
1329template <typename Scalar>
1331 const std::vector<std::vector<VariableMatrix<Scalar>>>& list) {
1332 // Get row and column counts for destination matrix
1333 int rows = 0;
1334 int cols = -1;
1335 for (const auto& row : list) {
1336 if (row.size() > 0) {
1337 rows += row.begin()->rows();
1338 }
1339
1340 // Get number of columns in this row
1341 int latest_cols = 0;
1342 for (const auto& elem : row) {
1343 // Assert the first and latest row have the same height
1344 slp_assert(row.begin()->rows() == elem.rows());
1345
1346 latest_cols += elem.cols();
1347 }
1348
1349 // If this is the first row, record the column count. Otherwise, assert the
1350 // first and latest column counts are the same.
1351 if (cols == -1) {
1352 cols = latest_cols;
1353 } else {
1354 slp_assert(cols == latest_cols);
1355 }
1356 }
1357
1358 VariableMatrix<Scalar> result{detail::empty, rows, cols};
1359
1360 int row_offset = 0;
1361 for (const auto& row : list) {
1362 int col_offset = 0;
1363 for (const auto& elem : row) {
1364 result.block(row_offset, col_offset, elem.rows(), elem.cols()) = elem;
1365 col_offset += elem.cols();
1366 }
1367 if (row.size() > 0) {
1368 row_offset += row.begin()->rows();
1369 }
1370 }
1371
1372 return result;
1373}
1374
1375/// Solves the VariableMatrix equation AX = B for X.
1376///
1377/// @tparam Scalar Scalar type.
1378/// @param A The left-hand side.
1379/// @param B The right-hand side.
1380/// @return The solution X.
1381template <typename Scalar>
1383 const VariableMatrix<Scalar>& B) {
1384 // m x n * n x p = m x p
1385 slp_assert(A.rows() == B.rows());
1386
1387 if (A.rows() == 1 && A.cols() == 1) {
1388 // Compute optimal inverse instead of using Eigen's general solver
1389 return B(0, 0) / A(0, 0);
1390 } else if (A.rows() == 2 && A.cols() == 2) {
1391 // Compute optimal inverse instead of using Eigen's general solver
1392 //
1393 // [a b]⁻¹ ___1___ [ d −b]
1394 // [c d] = ad − bc [−c a]
1395
1396 const auto& a = A(0, 0);
1397 const auto& b = A(0, 1);
1398 const auto& c = A(1, 0);
1399 const auto& d = A(1, 1);
1400
1401 VariableMatrix adj_A{{d, -b}, {-c, a}};
1402 auto det_A = a * d - b * c;
1403 return adj_A / det_A * B;
1404 } else if (A.rows() == 3 && A.cols() == 3) {
1405 // Compute optimal inverse instead of using Eigen's general solver
1406 //
1407 // [a b c]⁻¹
1408 // [d e f]
1409 // [g h i]
1410 // 1 [ei − fh ch − bi bf − ce]
1411 // = ------------------------------------ [fg − di ai − cg cd − af]
1412 // a(ei − fh) + b(fg − di) + c(dh − eg) [dh − eg bg − ah ae − bd]
1413 //
1414 // https://www.wolframalpha.com/input?i=inverse+%7B%7Ba%2C+b%2C+c%7D%2C+%7Bd%2C+e%2C+f%7D%2C+%7Bg%2C+h%2C+i%7D%7D
1415
1416 const auto& a = A(0, 0);
1417 const auto& b = A(0, 1);
1418 const auto& c = A(0, 2);
1419 const auto& d = A(1, 0);
1420 const auto& e = A(1, 1);
1421 const auto& f = A(1, 2);
1422 const auto& g = A(2, 0);
1423 const auto& h = A(2, 1);
1424 const auto& i = A(2, 2);
1425
1426 auto ae = a * e;
1427 auto af = a * f;
1428 auto ah = a * h;
1429 auto ai = a * i;
1430 auto bd = b * d;
1431 auto bf = b * f;
1432 auto bg = b * g;
1433 auto bi = b * i;
1434 auto cd = c * d;
1435 auto ce = c * e;
1436 auto cg = c * g;
1437 auto ch = c * h;
1438 auto dh = d * h;
1439 auto di = d * i;
1440 auto eg = e * g;
1441 auto ei = e * i;
1442 auto fg = f * g;
1443 auto fh = f * h;
1444
1445 auto adj_A00 = ei - fh;
1446 auto adj_A10 = fg - di;
1447 auto adj_A20 = dh - eg;
1448
1449 VariableMatrix adj_A{{adj_A00, ch - bi, bf - ce},
1450 {adj_A10, ai - cg, cd - af},
1451 {adj_A20, bg - ah, ae - bd}};
1452 auto det_A = a * adj_A00 + b * adj_A10 + c * adj_A20;
1453 return adj_A / det_A * B;
1454 } else if (A.rows() == 4 && A.cols() == 4) {
1455 // Compute optimal inverse instead of using Eigen's general solver
1456 //
1457 // [a b c d]⁻¹
1458 // [e f g h]
1459 // [i j k l]
1460 // [m n o p]
1461 //
1462 // https://www.wolframalpha.com/input?i=inverse+%7B%7Ba%2C+b%2C+c%2C+d%7D%2C+%7Be%2C+f%2C+g%2C+h%7D%2C+%7Bi%2C+j%2C+k%2C+l%7D%2C+%7Bm%2C+n%2C+o%2C+p%7D%7D
1463
1464 const auto& a = A(0, 0);
1465 const auto& b = A(0, 1);
1466 const auto& c = A(0, 2);
1467 const auto& d = A(0, 3);
1468 const auto& e = A(1, 0);
1469 const auto& f = A(1, 1);
1470 const auto& g = A(1, 2);
1471 const auto& h = A(1, 3);
1472 const auto& i = A(2, 0);
1473 const auto& j = A(2, 1);
1474 const auto& k = A(2, 2);
1475 const auto& l = A(2, 3);
1476 const auto& m = A(3, 0);
1477 const auto& n = A(3, 1);
1478 const auto& o = A(3, 2);
1479 const auto& p = A(3, 3);
1480
1481 auto afk = a * f * k;
1482 auto afl = a * f * l;
1483 auto afo = a * f * o;
1484 auto afp = a * f * p;
1485 auto agj = a * g * j;
1486 auto agl = a * g * l;
1487 auto agn = a * g * n;
1488 auto agp = a * g * p;
1489 auto ahj = a * h * j;
1490 auto ahk = a * h * k;
1491 auto ahn = a * h * n;
1492 auto aho = a * h * o;
1493 auto ajo = a * j * o;
1494 auto ajp = a * j * p;
1495 auto akn = a * k * n;
1496 auto akp = a * k * p;
1497 auto aln = a * l * n;
1498 auto alo = a * l * o;
1499 auto bek = b * e * k;
1500 auto bel = b * e * l;
1501 auto beo = b * e * o;
1502 auto bep = b * e * p;
1503 auto bgi = b * g * i;
1504 auto bgl = b * g * l;
1505 auto bgm = b * g * m;
1506 auto bgp = b * g * p;
1507 auto bhi = b * h * i;
1508 auto bhk = b * h * k;
1509 auto bhm = b * h * m;
1510 auto bho = b * h * o;
1511 auto bio = b * i * o;
1512 auto bip = b * i * p;
1513 auto bjp = b * j * p;
1514 auto bkm = b * k * m;
1515 auto bkp = b * k * p;
1516 auto blm = b * l * m;
1517 auto blo = b * l * o;
1518 auto cej = c * e * j;
1519 auto cel = c * e * l;
1520 auto cen = c * e * n;
1521 auto cep = c * e * p;
1522 auto cfi = c * f * i;
1523 auto cfl = c * f * l;
1524 auto cfm = c * f * m;
1525 auto cfp = c * f * p;
1526 auto chi = c * h * i;
1527 auto chj = c * h * j;
1528 auto chm = c * h * m;
1529 auto chn = c * h * n;
1530 auto cin = c * i * n;
1531 auto cip = c * i * p;
1532 auto cjm = c * j * m;
1533 auto cjp = c * j * p;
1534 auto clm = c * l * m;
1535 auto cln = c * l * n;
1536 auto dej = d * e * j;
1537 auto dek = d * e * k;
1538 auto den = d * e * n;
1539 auto deo = d * e * o;
1540 auto dfi = d * f * i;
1541 auto dfk = d * f * k;
1542 auto dfm = d * f * m;
1543 auto dfo = d * f * o;
1544 auto dgi = d * g * i;
1545 auto dgj = d * g * j;
1546 auto dgm = d * g * m;
1547 auto dgn = d * g * n;
1548 auto din = d * i * n;
1549 auto dio = d * i * o;
1550 auto djm = d * j * m;
1551 auto djo = d * j * o;
1552 auto dkm = d * k * m;
1553 auto dkn = d * k * n;
1554 auto ejo = e * j * o;
1555 auto ejp = e * j * p;
1556 auto ekn = e * k * n;
1557 auto ekp = e * k * p;
1558 auto eln = e * l * n;
1559 auto elo = e * l * o;
1560 auto fio = f * i * o;
1561 auto fip = f * i * p;
1562 auto fkm = f * k * m;
1563 auto fkp = f * k * p;
1564 auto flm = f * l * m;
1565 auto flo = f * l * o;
1566 auto gin = g * i * n;
1567 auto gip = g * i * p;
1568 auto gjm = g * j * m;
1569 auto gjp = g * j * p;
1570 auto glm = g * l * m;
1571 auto gln = g * l * n;
1572 auto hin = h * i * n;
1573 auto hio = h * i * o;
1574 auto hjm = h * j * m;
1575 auto hjo = h * j * o;
1576 auto hkm = h * k * m;
1577 auto hkn = h * k * n;
1578
1579 auto adj_A00 = fkp - flo - gjp + gln + hjo - hkn;
1580 auto adj_A01 = -bkp + blo + cjp - cln - djo + dkn;
1581 auto adj_A02 = bgp - bho - cfp + chn + dfo - dgn;
1582 auto adj_A03 = -bgl + bhk + cfl - chj - dfk + dgj;
1583 auto adj_A10 = -ekp + elo + gip - glm - hio + hkm;
1584 auto adj_A11 = akp - alo - cip + clm + dio - dkm;
1585 auto adj_A12 = -agp + aho + cep - chm - deo + dgm;
1586 auto adj_A13 = agl - ahk - cel + chi + dek - dgi;
1587 auto adj_A20 = ejp - eln - fip + flm + hin - hjm;
1588 auto adj_A21 = -ajp + aln + bip - blm - din + djm;
1589 auto adj_A22 = afp - ahn - bep + bhm + den - dfm;
1590 auto adj_A23 = -afl + ahj + bel - bhi - dej + dfi;
1591 auto adj_A30 = -ejo + ekn + fio - fkm - gin + gjm;
1592 // NOLINTNEXTLINE(build/include_what_you_use)
1593 auto adj_A31 = ajo - akn - bio + bkm + cin - cjm;
1594 auto adj_A32 = -afo + agn + beo - bgm - cen + cfm;
1595 auto adj_A33 = afk - agj - bek + bgi + cej - cfi;
1596
1597 VariableMatrix adj_A{{adj_A00, adj_A01, adj_A02, adj_A03},
1598 {adj_A10, adj_A11, adj_A12, adj_A13},
1599 {adj_A20, adj_A21, adj_A22, adj_A23},
1600 {adj_A30, adj_A31, adj_A32, adj_A33}};
1601 auto det_A = a * adj_A00 + b * adj_A10 + c * adj_A20 + d * adj_A30;
1602 return adj_A / det_A * B;
1603 } else {
1604 using MatrixXv =
1605 Eigen::Matrix<Variable<Scalar>, Eigen::Dynamic, Eigen::Dynamic>;
1606
1607 MatrixXv eigen_A{A.rows(), A.cols()};
1608 for (int row = 0; row < A.rows(); ++row) {
1609 for (int col = 0; col < A.cols(); ++col) {
1610 eigen_A(row, col) = A(row, col);
1611 }
1612 }
1613
1614 MatrixXv eigen_B{B.rows(), B.cols()};
1615 for (int row = 0; row < B.rows(); ++row) {
1616 for (int col = 0; col < B.cols(); ++col) {
1617 eigen_B(row, col) = B(row, col);
1618 }
1619 }
1620
1621 MatrixXv eigen_X = eigen_A.householderQr().solve(eigen_B);
1622
1623 VariableMatrix<Scalar> X{detail::empty, A.cols(), B.cols()};
1624 for (int row = 0; row < X.rows(); ++row) {
1625 for (int col = 0; col < X.cols(); ++col) {
1626 X(row, col) = eigen_X(row, col);
1627 }
1628 }
1629
1630 return X;
1631 }
1632}
1633
1636
1637} // namespace slp
#define slp_assert(condition)
Abort in C++.
Definition assert.hpp:25
@ index
Definition base.h:690
Marker interface for concepts to determine whether a given scalar or matrix type belongs to Sleipnir.
Definition sleipnir_base.hpp:9
Represents a sequence of elements in an iterable object.
Definition slice.hpp:25
constexpr int adjust(int length)
Adjusts start and end slice indices assuming a sequence of the specified length.
Definition slice.hpp:118
A submatrix of autodiff variables with reference semantics.
Definition variable_block.hpp:24
An autodiff variable pointing to an expression node.
Definition variable.hpp:47
Definition variable_matrix.hpp:1072
constexpr const_iterator() noexcept=default
const Variable< Scalar > & const_reference
Definition variable_matrix.hpp:1078
constexpr const_reference operator*() const noexcept
Definition variable_matrix.hpp:1110
constexpr const_iterator & operator--() noexcept
Definition variable_matrix.hpp:1097
std::bidirectional_iterator_tag iterator_category
Definition variable_matrix.hpp:1074
constexpr const_iterator operator++(int) noexcept
Definition variable_matrix.hpp:1091
constexpr bool operator==(const const_iterator &) const noexcept=default
std::ptrdiff_t difference_type
Definition variable_matrix.hpp:1076
constexpr const_iterator operator--(int) noexcept
Definition variable_matrix.hpp:1102
Variable< Scalar > * pointer
Definition variable_matrix.hpp:1077
Variable< Scalar > value_type
Definition variable_matrix.hpp:1075
constexpr const_iterator & operator++() noexcept
Definition variable_matrix.hpp:1086
Definition variable_matrix.hpp:1028
constexpr iterator & operator++() noexcept
Definition variable_matrix.hpp:1042
std::ptrdiff_t difference_type
Definition variable_matrix.hpp:1032
Variable< Scalar > value_type
Definition variable_matrix.hpp:1031
constexpr iterator & operator--() noexcept
Definition variable_matrix.hpp:1053
constexpr iterator operator--(int) noexcept
Definition variable_matrix.hpp:1058
std::bidirectional_iterator_tag iterator_category
Definition variable_matrix.hpp:1030
Variable< Scalar > & reference
Definition variable_matrix.hpp:1034
constexpr reference operator*() const noexcept
Definition variable_matrix.hpp:1066
constexpr iterator() noexcept=default
constexpr bool operator==(const iterator &) const noexcept=default
Variable< Scalar > * pointer
Definition variable_matrix.hpp:1033
constexpr iterator operator++(int) noexcept
Definition variable_matrix.hpp:1047
A matrix of autodiff variables.
Definition variable_matrix.hpp:33
const_reverse_iterator crbegin() const
Returns const reverse begin iterator.
Definition variable_matrix.hpp:1178
VariableMatrix(std::initializer_list< std::initializer_list< Variable< Scalar > > > list)
Constructs a scalar VariableMatrix from a nested list of Variables.
Definition variable_matrix.hpp:73
const_reverse_iterator crend() const
Returns const reverse end iterator.
Definition variable_matrix.hpp:1185
Scalar_ Scalar
Scalar type alias.
Definition variable_matrix.hpp:36
const VariableBlock< const VariableMatrix > operator()(Slice row_slice, Slice col_slice) const
Returns a slice of the variable matrix.
Definition variable_matrix.hpp:392
iterator end()
Returns end iterator.
Definition variable_matrix.hpp:1129
VariableMatrix(Variable< Scalar > &&variable)
Constructs a scalar VariableMatrix from a Variable.
Definition variable_matrix.hpp:194
const VariableBlock< const VariableMatrix > block(int row_offset, int col_offset, int block_rows, int block_cols) const
Returns a block of the variable matrix.
Definition variable_matrix.hpp:364
size_t size() const
Returns number of elements in matrix.
Definition variable_matrix.hpp:1192
static VariableMatrix< Scalar > zero(int rows, int cols)
Returns a variable matrix filled with zeroes.
Definition variable_matrix.hpp:1199
VariableBlock< VariableMatrix > block(int row_offset, int col_offset, int block_rows, int block_cols)
Returns a block of the variable matrix.
Definition variable_matrix.hpp:348
VariableMatrix(const std::vector< std::vector< Scalar > > &list)
Constructs a scalar VariableMatrix from a nested list of scalars.
Definition variable_matrix.hpp:100
VariableMatrix & operator=(ScalarLike auto value)
Assigns a scalar to the matrix.
Definition variable_matrix.hpp:278
VariableMatrix & operator-=(const MatrixLike auto &rhs)
Compound subtraction-assignment operator.
Definition variable_matrix.hpp:903
Variable< Scalar > & operator[](int index)
Returns the element at the given index.
Definition variable_matrix.hpp:327
VariableMatrix & operator=(const Eigen::MatrixBase< Derived > &values)
Assigns an Eigen matrix to a VariableMatrix.
Definition variable_matrix.hpp:260
friend VariableMatrix< Scalar > operator-(const LHS &lhs, const RHS &rhs)
Binary subtraction operator.
Definition variable_matrix.hpp:845
VariableMatrix & operator-=(const ScalarLike auto &rhs)
Compound subtraction-assignment operator.
Definition variable_matrix.hpp:919
friend VariableMatrix< Scalar > operator*(const Variable< Scalar > &lhs, const RHS &rhs)
Scalar-matrix multiplication operator.
Definition variable_matrix.hpp:612
VariableMatrix & operator*=(const ScalarLike auto &rhs)
Compound matrix-scalar multiplication-assignment operator.
Definition variable_matrix.hpp:666
Scalar value(int index)
Returns an element of the variable matrix.
Definition variable_matrix.hpp:990
VariableMatrix(const VariableBlock< VariableMatrix > &values)
Constructs a VariableMatrix from a VariableBlock.
Definition variable_matrix.hpp:202
VariableBlock< VariableMatrix > operator()(Slice row_slice, int row_slice_length, Slice col_slice, int col_slice_length)
Returns a slice of the variable matrix.
Definition variable_matrix.hpp:410
VariableMatrix(int rows, int cols)
Constructs a zero-initialized VariableMatrix with the given dimensions.
Definition variable_matrix.hpp:51
const_iterator cbegin() const
Returns const begin iterator.
Definition variable_matrix.hpp:1144
const_iterator begin() const
Returns const begin iterator.
Definition variable_matrix.hpp:1134
const_iterator cend() const
Returns const end iterator.
Definition variable_matrix.hpp:1149
Eigen::Matrix< Scalar, Eigen::Dynamic, Eigen::Dynamic > value()
Returns the contents of the variable matrix.
Definition variable_matrix.hpp:995
friend VariableMatrix< Scalar > operator/(const LHS &lhs, const Variable< Scalar > &rhs)
Binary division operator.
Definition variable_matrix.hpp:682
VariableMatrix(int rows)
Constructs a zero-initialized VariableMatrix column vector with the given rows.
Definition variable_matrix.hpp:45
const VariableBlock< const VariableMatrix > operator()(Slice row_slice, int row_slice_length, Slice col_slice, int col_slice_length) const
Returns a slice of the variable matrix.
Definition variable_matrix.hpp:428
const Variable< Scalar > & operator()(int row, int col) const
Returns the element at the given row and column.
Definition variable_matrix.hpp:317
VariableMatrix(std::span< const Variable< Scalar > > values, int rows, int cols)
Constructs a matrix wrapper around a Variable array.
Definition variable_matrix.hpp:244
VariableBlock< VariableMatrix > col(int col)
Returns a column slice of the variable matrix.
Definition variable_matrix.hpp:482
VariableMatrix(const Eigen::MatrixBase< Derived > &values)
Constructs a VariableMatrix from an Eigen matrix.
Definition variable_matrix.hpp:151
Variable< Scalar > & operator()(int row, int col)
Returns the element at the given row and column.
Definition variable_matrix.hpp:306
const VariableBlock< const VariableMatrix > col(int col) const
Returns a column slice of the variable matrix.
Definition variable_matrix.hpp:491
VariableMatrix & operator+=(const ScalarLike auto &rhs)
Compound addition-assignment operator.
Definition variable_matrix.hpp:827
friend VariableMatrix< Scalar > operator*(const LHS &lhs, const Variable< Scalar > &rhs)
Matrix-scalar multiplication operator.
Definition variable_matrix.hpp:577
VariableBlock< VariableMatrix > segment(int offset, int length)
Returns a segment of the variable vector.
Definition variable_matrix.hpp:440
std::reverse_iterator< iterator > reverse_iterator
Definition variable_matrix.hpp:1116
Scalar value(int row, int col)
Returns an element of the variable matrix.
Definition variable_matrix.hpp:984
const VariableBlock< const VariableMatrix > row(int row) const
Returns a row slice of the variable matrix.
Definition variable_matrix.hpp:473
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition variable_matrix.hpp:1117
VariableMatrix()=default
Constructs an empty VariableMatrix.
static VariableMatrix< Scalar > ones(int rows, int cols)
Returns a variable matrix filled with ones.
Definition variable_matrix.hpp:1214
VariableMatrix & operator+=(const MatrixLike auto &rhs)
Compound addition-assignment operator.
Definition variable_matrix.hpp:811
VariableMatrix(std::span< const Variable< Scalar > > values)
Constructs a column vector wrapper around a Variable array.
Definition variable_matrix.hpp:229
friend VariableMatrix< Scalar > operator-(const SleipnirMatrixLike< Scalar > auto &lhs)
Unary minus operator.
Definition variable_matrix.hpp:934
VariableMatrix< Scalar > T() const
Returns the transpose of the variable matrix.
Definition variable_matrix.hpp:957
VariableMatrix< Scalar > cwise_transform(function_ref< Variable< Scalar >(const Variable< Scalar > &x)> unary_op) const
Transforms the matrix coefficient-wise with an unary operator.
Definition variable_matrix.hpp:1012
friend VariableMatrix< Scalar > operator*(const LHS &lhs, const RHS &rhs)
Matrix multiplication operator.
Definition variable_matrix.hpp:501
VariableBlock< VariableMatrix > operator()(Slice row_slice, Slice col_slice)
Returns a slice of the variable matrix.
Definition variable_matrix.hpp:380
const_reverse_iterator rbegin() const
Returns const reverse begin iterator.
Definition variable_matrix.hpp:1164
VariableMatrix(const Variable< Scalar > &variable)
Constructs a scalar VariableMatrix from a Variable.
Definition variable_matrix.hpp:186
reverse_iterator rend()
Returns reverse end iterator.
Definition variable_matrix.hpp:1159
VariableMatrix(const VariableBlock< const VariableMatrix > &values)
Constructs a VariableMatrix from a VariableBlock.
Definition variable_matrix.hpp:216
int rows() const
Returns the number of rows in the matrix.
Definition variable_matrix.hpp:972
VariableMatrix(const Eigen::DiagonalBase< Derived > &values)
Constructs a VariableMatrix from an Eigen diagonal matrix.
Definition variable_matrix.hpp:167
const_reverse_iterator rend() const
Returns const reverse end iterator.
Definition variable_matrix.hpp:1171
VariableMatrix & operator*=(const MatrixLike auto &rhs)
Compound matrix multiplication-assignment operator.
Definition variable_matrix.hpp:646
VariableMatrix(detail::empty_t, int rows, int cols)
Constructs an empty VariableMatrix with the given dimensions.
Definition variable_matrix.hpp:62
const_iterator end() const
Returns const end iterator.
Definition variable_matrix.hpp:1139
void set_value(const Eigen::MatrixBase< Derived > &values)
Sets the VariableMatrix's internal values.
Definition variable_matrix.hpp:291
iterator begin()
Returns begin iterator.
Definition variable_matrix.hpp:1124
const VariableBlock< const VariableMatrix > segment(int offset, int length) const
Returns a segment of the variable vector.
Definition variable_matrix.hpp:452
reverse_iterator rbegin()
Returns reverse begin iterator.
Definition variable_matrix.hpp:1154
VariableBlock< VariableMatrix > row(int row)
Returns a row slice of the variable matrix.
Definition variable_matrix.hpp:464
friend VariableMatrix< Scalar > operator+(const LHS &lhs, const RHS &rhs)
Binary addition operator.
Definition variable_matrix.hpp:753
VariableMatrix(const std::vector< std::vector< Variable< Scalar > > > &list)
Constructs a scalar VariableMatrix from a nested list of Variables.
Definition variable_matrix.hpp:126
VariableMatrix & operator/=(const ScalarLike auto &rhs)
Compound matrix division-assignment operator.
Definition variable_matrix.hpp:737
const Variable< Scalar > & operator[](int index) const
Returns the element at the given index.
Definition variable_matrix.hpp:336
int cols() const
Returns the number of columns in the matrix.
Definition variable_matrix.hpp:977
Definition function_ref.hpp:13
FMT_CONSTEXPR auto fg(detail::color_type foreground) noexcept -> text_style
Creates a text style from the foreground (text) color.
Definition color.h:348
FMT_CONSTEXPR auto bg(detail::color_type background) noexcept -> text_style
Creates a text style from the background color.
Definition color.h:354
Definition concepts.hpp:18
Definition concepts.hpp:24
Definition concepts.hpp:33
Definition concepts.hpp:38
T * p
Definition format.h:758
Definition small_vector.hpp:7
wpi::util::SmallVector< T > small_vector
Definition small_vector.hpp:10
static constexpr empty_t empty
Designates an uninitialized VariableMatrix.
Definition empty.hpp:11
Definition expression_graph.hpp:11
VariableMatrix< Scalar > solve(const VariableMatrix< Scalar > &A, const VariableMatrix< Scalar > &B)
Solves the VariableMatrix equation AX = B for X.
Definition variable_matrix.hpp:1382
VariableMatrix< Scalar > cwise_reduce(const VariableMatrix< Scalar > &lhs, const VariableMatrix< Scalar > &rhs, function_ref< Variable< Scalar >(const Variable< Scalar > &x, const Variable< Scalar > &y)> binary_op)
Applies a coefficient-wise reduce operation to two matrices.
Definition variable_matrix.hpp:1245
VariableMatrix(const Eigen::MatrixBase< Derived > &) -> VariableMatrix< typename Derived::Scalar >
VariableMatrix< Scalar > block(std::initializer_list< std::initializer_list< VariableMatrix< Scalar > > > list)
Assemble a VariableMatrix from a nested list of blocks.
Definition variable_matrix.hpp:1273
Type tag used to designate an uninitialized VariableMatrix.
Definition empty.hpp:8
#define SLEIPNIR_DLLEXPORT
Definition symbol_exports.hpp:34