Sleipnir C++ API
Loading...
Searching...
No Matches
variable_matrix.hpp
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
15#include "sleipnir/autodiff/slice.hpp"
16#include "sleipnir/autodiff/variable.hpp"
17#include "sleipnir/autodiff/variable_block.hpp"
18#include "sleipnir/util/assert.hpp"
19#include "sleipnir/util/concepts.hpp"
20#include "sleipnir/util/function_ref.hpp"
21#include "sleipnir/util/small_vector.hpp"
22#include "sleipnir/util/symbol_exports.hpp"
23
24namespace slp {
25
29class SLEIPNIR_DLLEXPORT VariableMatrix {
30 public:
34 struct empty_t {};
35
39 static constexpr empty_t empty{};
40
44 VariableMatrix() = default;
45
51 explicit VariableMatrix(int rows) : m_rows{rows}, m_cols{1} {
52 m_storage.reserve(rows);
53 for (int row = 0; row < rows; ++row) {
54 m_storage.emplace_back();
55 }
56 }
57
64 VariableMatrix(int rows, int cols) : m_rows{rows}, m_cols{cols} {
65 m_storage.reserve(rows * cols);
66 for (int index = 0; index < rows * cols; ++index) {
67 m_storage.emplace_back();
68 }
69 }
70
77 VariableMatrix(empty_t, int rows, int cols) : m_rows{rows}, m_cols{cols} {
78 m_storage.reserve(rows * cols);
79 for (int index = 0; index < rows * cols; ++index) {
80 m_storage.emplace_back(nullptr);
81 }
82 }
83
89 VariableMatrix( // NOLINT
90 std::initializer_list<std::initializer_list<Variable>> list) {
91 // Get row and column counts for destination matrix
92 m_rows = list.size();
93 m_cols = 0;
94 if (list.size() > 0) {
95 m_cols = list.begin()->size();
96 }
97
98 // Assert the first and latest column counts are the same
99 for ([[maybe_unused]]
100 const auto& row : list) {
101 slp_assert(list.begin()->size() == row.size());
102 }
103
104 m_storage.reserve(rows() * cols());
105 for (const auto& row : list) {
106 std::ranges::copy(row, std::back_inserter(m_storage));
107 }
108 }
109
117 VariableMatrix(const std::vector<std::vector<double>>& list) { // NOLINT
118 // Get row and column counts for destination matrix
119 m_rows = list.size();
120 m_cols = 0;
121 if (list.size() > 0) {
122 m_cols = list.begin()->size();
123 }
124
125 // Assert the first and latest column counts are the same
126 for ([[maybe_unused]]
127 const auto& row : list) {
128 slp_assert(list.begin()->size() == row.size());
129 }
130
131 m_storage.reserve(rows() * cols());
132 for (const auto& row : list) {
133 std::ranges::copy(row, std::back_inserter(m_storage));
134 }
135 }
136
144 VariableMatrix(const std::vector<std::vector<Variable>>& list) { // NOLINT
145 // Get row and column counts for destination matrix
146 m_rows = list.size();
147 m_cols = 0;
148 if (list.size() > 0) {
149 m_cols = list.begin()->size();
150 }
151
152 // Assert the first and latest column counts are the same
153 for ([[maybe_unused]]
154 const auto& row : list) {
155 slp_assert(list.begin()->size() == row.size());
156 }
157
158 m_storage.reserve(rows() * cols());
159 for (const auto& row : list) {
160 std::ranges::copy(row, std::back_inserter(m_storage));
161 }
162 }
163
169 template <typename Derived>
170 VariableMatrix(const Eigen::MatrixBase<Derived>& values) // NOLINT
171 : m_rows{static_cast<int>(values.rows())},
172 m_cols{static_cast<int>(values.cols())} {
173 m_storage.reserve(values.rows() * values.cols());
174 for (int row = 0; row < values.rows(); ++row) {
175 for (int col = 0; col < values.cols(); ++col) {
176 m_storage.emplace_back(values(row, col));
177 }
178 }
179 }
180
186 template <typename Derived>
187 VariableMatrix(const Eigen::DiagonalBase<Derived>& values) // NOLINT
188 : m_rows{static_cast<int>(values.rows())},
189 m_cols{static_cast<int>(values.cols())} {
190 m_storage.reserve(values.rows() * values.cols());
191 for (int row = 0; row < values.rows(); ++row) {
192 for (int col = 0; col < values.cols(); ++col) {
193 if (row == col) {
194 m_storage.emplace_back(values.diagonal()[row]);
195 } else {
196 m_storage.emplace_back(0.0);
197 }
198 }
199 }
200 }
201
208 template <typename Derived>
209 VariableMatrix& operator=(const Eigen::MatrixBase<Derived>& values) {
210 slp_assert(rows() == values.rows() && cols() == values.cols());
211
212 for (int row = 0; row < values.rows(); ++row) {
213 for (int col = 0; col < values.cols(); ++col) {
214 (*this)[row, col] = values(row, col);
215 }
216 }
217
218 return *this;
219 }
220
230 slp_assert(rows() == 1 && cols() == 1);
231
232 (*this)[0, 0] = value;
233
234 return *this;
235 }
236
242 template <typename Derived>
243 requires std::same_as<typename Derived::Scalar, double>
244 void set_value(const Eigen::MatrixBase<Derived>& values) {
245 slp_assert(rows() == values.rows() && cols() == values.cols());
246
247 for (int row = 0; row < values.rows(); ++row) {
248 for (int col = 0; col < values.cols(); ++col) {
249 (*this)[row, col].set_value(values(row, col));
250 }
251 }
252 }
253
259 VariableMatrix(const Variable& variable) // NOLINT
260 : m_rows{1}, m_cols{1} {
261 m_storage.emplace_back(variable);
262 }
263
269 VariableMatrix(Variable&& variable) : m_rows{1}, m_cols{1} { // NOLINT
270 m_storage.emplace_back(std::move(variable));
271 }
272
279 : m_rows{values.rows()}, m_cols{values.cols()} {
280 m_storage.reserve(rows() * cols());
281 for (int row = 0; row < rows(); ++row) {
282 for (int col = 0; col < cols(); ++col) {
283 m_storage.emplace_back(values[row, col]);
284 }
285 }
286 }
287
294 : m_rows{values.rows()}, m_cols{values.cols()} {
295 m_storage.reserve(rows() * cols());
296 for (int row = 0; row < rows(); ++row) {
297 for (int col = 0; col < cols(); ++col) {
298 m_storage.emplace_back(values[row, col]);
299 }
300 }
301 }
302
308 explicit VariableMatrix(std::span<const Variable> values)
309 : m_rows{static_cast<int>(values.size())}, m_cols{1} {
310 m_storage.reserve(rows() * cols());
311 for (int row = 0; row < rows(); ++row) {
312 for (int col = 0; col < cols(); ++col) {
313 m_storage.emplace_back(values[row * cols() + col]);
314 }
315 }
316 }
317
325 VariableMatrix(std::span<const Variable> values, int rows, int cols)
326 : m_rows{rows}, m_cols{cols} {
327 slp_assert(static_cast<int>(values.size()) == rows * cols);
328 m_storage.reserve(rows * cols);
329 for (int row = 0; row < rows; ++row) {
330 for (int col = 0; col < cols; ++col) {
331 m_storage.emplace_back(values[row * cols + col]);
332 }
333 }
334 }
335
343 Variable& operator[](int row, int col) {
344 slp_assert(row >= 0 && row < rows());
345 slp_assert(col >= 0 && col < cols());
346 return m_storage[row * cols() + col];
347 }
348
356 const Variable& operator[](int row, int col) const {
357 slp_assert(row >= 0 && row < rows());
358 slp_assert(col >= 0 && col < cols());
359 return m_storage[row * cols() + col];
360 }
361
369 slp_assert(row >= 0 && row < rows() * cols());
370 return m_storage[row];
371 }
372
379 const Variable& operator[](int row) const {
380 slp_assert(row >= 0 && row < rows() * cols());
381 return m_storage[row];
382 }
383
393 VariableBlock<VariableMatrix> block(int row_offset, int col_offset,
394 int block_rows, int block_cols) {
395 slp_assert(row_offset >= 0 && row_offset <= rows());
396 slp_assert(col_offset >= 0 && col_offset <= cols());
397 slp_assert(block_rows >= 0 && block_rows <= rows() - row_offset);
398 slp_assert(block_cols >= 0 && block_cols <= cols() - col_offset);
399 return VariableBlock{*this, row_offset, col_offset, block_rows, block_cols};
400 }
401
412 int col_offset,
413 int block_rows,
414 int block_cols) const {
415 slp_assert(row_offset >= 0 && row_offset <= rows());
416 slp_assert(col_offset >= 0 && col_offset <= cols());
417 slp_assert(block_rows >= 0 && block_rows <= rows() - row_offset);
418 slp_assert(block_cols >= 0 && block_cols <= cols() - col_offset);
419 return VariableBlock{*this, row_offset, col_offset, block_rows, block_cols};
420 }
421
430 int row_slice_length = row_slice.adjust(rows());
431 int col_slice_length = col_slice.adjust(cols());
432 return VariableBlock{*this, std::move(row_slice), row_slice_length,
433 std::move(col_slice), col_slice_length};
434 }
435
444 Slice col_slice) const {
445 int row_slice_length = row_slice.adjust(rows());
446 int col_slice_length = col_slice.adjust(cols());
447 return VariableBlock{*this, std::move(row_slice), row_slice_length,
448 std::move(col_slice), col_slice_length};
449 }
450
465 int row_slice_length,
466 Slice col_slice,
467 int col_slice_length) {
468 return VariableBlock{*this, std::move(row_slice), row_slice_length,
469 std::move(col_slice), col_slice_length};
470 }
471
485 Slice row_slice, int row_slice_length, Slice col_slice,
486 int col_slice_length) const {
487 return VariableBlock{*this, std::move(row_slice), row_slice_length,
488 std::move(col_slice), col_slice_length};
489 }
490
498 VariableBlock<VariableMatrix> segment(int offset, int length) {
499 slp_assert(offset >= 0 && offset < rows() * cols());
500 slp_assert(length >= 0 && length <= rows() * cols() - offset);
501 return block(offset, 0, length, 1);
502 }
503
512 int length) const {
513 slp_assert(offset >= 0 && offset < rows() * cols());
514 slp_assert(length >= 0 && length <= rows() * cols() - offset);
515 return block(offset, 0, length, 1);
516 }
517
525 slp_assert(row >= 0 && row < rows());
526 return block(row, 0, 1, cols());
527 }
528
536 slp_assert(row >= 0 && row < rows());
537 return block(row, 0, 1, cols());
538 }
539
547 slp_assert(col >= 0 && col < cols());
548 return block(0, col, rows(), 1);
549 }
550
558 slp_assert(col >= 0 && col < cols());
559 return block(0, col, rows(), 1);
560 }
561
568 template <MatrixLike LHS, MatrixLike RHS>
570 friend SLEIPNIR_DLLEXPORT VariableMatrix operator*(const LHS& lhs,
571 const RHS& rhs) {
572 slp_assert(lhs.cols() == rhs.rows());
573
574 VariableMatrix result(VariableMatrix::empty, lhs.rows(), rhs.cols());
575
576 for (int i = 0; i < lhs.rows(); ++i) {
577 for (int j = 0; j < rhs.cols(); ++j) {
578 Variable sum;
579 for (int k = 0; k < lhs.cols(); ++k) {
581 sum += lhs[i, k] * rhs[k, j];
582 } else if constexpr (SleipnirMatrixLike<LHS> &&
584 sum += lhs[i, k] * rhs(k, j);
585 } else if constexpr (EigenMatrixLike<LHS> &&
587 sum += lhs(i, k) * rhs[k, j];
588 }
589 }
590 result[i, j] = sum;
591 }
592 }
593
594 return result;
595 }
596
603 friend SLEIPNIR_DLLEXPORT VariableMatrix
604 operator*(const SleipnirMatrixLike auto& lhs, const ScalarLike auto& rhs) {
605 VariableMatrix result{VariableMatrix::empty, lhs.rows(), lhs.cols()};
606
607 for (int row = 0; row < result.rows(); ++row) {
608 for (int col = 0; col < result.cols(); ++col) {
609 result[row, col] = lhs[row, col] * rhs;
610 }
611 }
612
613 return result;
614 }
615
622 friend SLEIPNIR_DLLEXPORT VariableMatrix operator*(const MatrixLike auto& lhs,
623 const Variable& rhs) {
624 VariableMatrix result(VariableMatrix::empty, lhs.rows(), lhs.cols());
625
626 for (int row = 0; row < result.rows(); ++row) {
627 for (int col = 0; col < result.cols(); ++col) {
628 if constexpr (SleipnirMatrixLike<decltype(lhs)>) {
629 result[row, col] = lhs[row, col] * rhs;
630 } else {
631 result[row, col] = lhs(row, col) * rhs;
632 }
633 }
634 }
635
636 return result;
637 }
638
645 friend SLEIPNIR_DLLEXPORT VariableMatrix
646 operator*(const ScalarLike auto& lhs, const SleipnirMatrixLike auto& rhs) {
647 VariableMatrix result{VariableMatrix::empty, rhs.rows(), rhs.cols()};
648
649 for (int row = 0; row < result.rows(); ++row) {
650 for (int col = 0; col < result.cols(); ++col) {
651 result[row, col] = rhs[row, col] * lhs;
652 }
653 }
654
655 return result;
656 }
657
664 friend SLEIPNIR_DLLEXPORT VariableMatrix
665 operator*(const Variable& lhs, const MatrixLike auto& rhs) {
666 VariableMatrix result(VariableMatrix::empty, rhs.rows(), rhs.cols());
667
668 for (int row = 0; row < result.rows(); ++row) {
669 for (int col = 0; col < result.cols(); ++col) {
670 if constexpr (SleipnirMatrixLike<decltype(rhs)>) {
671 result[row, col] = rhs[row, col] * lhs;
672 } else {
673 result[row, col] = rhs(row, col) * lhs;
674 }
675 }
676 }
677
678 return result;
679 }
680
688 slp_assert(cols() == rhs.rows() && cols() == rhs.cols());
689
690 for (int i = 0; i < rows(); ++i) {
691 for (int j = 0; j < rhs.cols(); ++j) {
692 Variable sum;
693 for (int k = 0; k < cols(); ++k) {
694 if constexpr (SleipnirMatrixLike<decltype(rhs)>) {
695 sum += (*this)[i, k] * rhs[k, j];
696 } else {
697 sum += (*this)[i, k] * rhs(k, j);
698 }
699 }
700 (*this)[i, j] = sum;
701 }
702 }
703
704 return *this;
705 }
706
714 for (int row = 0; row < rows(); ++row) {
715 for (int col = 0; col < rhs.cols(); ++col) {
716 (*this)[row, col] *= rhs;
717 }
718 }
719
720 return *this;
721 }
722
730 friend SLEIPNIR_DLLEXPORT VariableMatrix
731 operator/(const MatrixLike auto& lhs, const ScalarLike auto& rhs) {
732 VariableMatrix result(VariableMatrix::empty, lhs.rows(), lhs.cols());
733
734 for (int row = 0; row < result.rows(); ++row) {
735 for (int col = 0; col < result.cols(); ++col) {
736 if constexpr (SleipnirMatrixLike<decltype(lhs)>) {
737 result[row, col] = lhs[row, col] / rhs;
738 } else {
739 result[row, col] = lhs(row, col) / rhs;
740 }
741 }
742 }
743
744 return result;
745 }
746
754 for (int row = 0; row < rows(); ++row) {
755 for (int col = 0; col < cols(); ++col) {
756 (*this)[row, col] /= rhs;
757 }
758 }
759
760 return *this;
761 }
762
770 template <MatrixLike LHS, MatrixLike RHS>
772 friend SLEIPNIR_DLLEXPORT VariableMatrix operator+(const LHS& lhs,
773 const RHS& rhs) {
774 slp_assert(lhs.rows() == rhs.rows() && lhs.cols() == rhs.cols());
775
776 VariableMatrix result(VariableMatrix::empty, lhs.rows(), lhs.cols());
777
778 for (int row = 0; row < result.rows(); ++row) {
779 for (int col = 0; col < result.cols(); ++col) {
781 result[row, col] = lhs[row, col] + rhs[row, col];
782 } else if constexpr (SleipnirMatrixLike<LHS> && EigenMatrixLike<RHS>) {
783 result[row, col] = lhs[row, col] + rhs(row, col);
784 } else if constexpr (EigenMatrixLike<LHS> && SleipnirMatrixLike<RHS>) {
785 result[row, col] = lhs(row, col) + rhs[row, col];
786 }
787 }
788 }
789
790 return result;
791 }
792
800 slp_assert(rows() == rhs.rows() && cols() == rhs.cols());
801
802 for (int row = 0; row < rows(); ++row) {
803 for (int col = 0; col < cols(); ++col) {
804 if constexpr (SleipnirMatrixLike<decltype(rhs)>) {
805 (*this)[row, col] += rhs[row, col];
806 } else {
807 (*this)[row, col] += rhs(row, col);
808 }
809 }
810 }
811
812 return *this;
813 }
814
822 slp_assert(rows() == 1 && cols() == 1);
823
824 for (int row = 0; row < rows(); ++row) {
825 for (int col = 0; col < cols(); ++col) {
826 (*this)[row, col] += rhs;
827 }
828 }
829
830 return *this;
831 }
832
840 template <MatrixLike LHS, MatrixLike RHS>
842 friend SLEIPNIR_DLLEXPORT VariableMatrix operator-(const LHS& lhs,
843 const RHS& rhs) {
844 slp_assert(lhs.rows() == rhs.rows() && lhs.cols() == rhs.cols());
845
846 VariableMatrix result(VariableMatrix::empty, lhs.rows(), lhs.cols());
847
848 for (int row = 0; row < result.rows(); ++row) {
849 for (int col = 0; col < result.cols(); ++col) {
851 result[row, col] = lhs[row, col] - rhs[row, col];
852 } else if constexpr (SleipnirMatrixLike<LHS> && EigenMatrixLike<RHS>) {
853 result[row, col] = lhs[row, col] - rhs(row, col);
854 } else if constexpr (EigenMatrixLike<LHS> && SleipnirMatrixLike<RHS>) {
855 result[row, col] = lhs(row, col) - rhs[row, col];
856 }
857 }
858 }
859
860 return result;
861 }
862
870 slp_assert(rows() == rhs.rows() && cols() == rhs.cols());
871
872 for (int row = 0; row < rows(); ++row) {
873 for (int col = 0; col < cols(); ++col) {
874 if constexpr (SleipnirMatrixLike<decltype(rhs)>) {
875 (*this)[row, col] -= rhs[row, col];
876 } else {
877 (*this)[row, col] -= rhs(row, col);
878 }
879 }
880 }
881
882 return *this;
883 }
884
892 slp_assert(rows() == 1 && cols() == 1);
893
894 for (int row = 0; row < rows(); ++row) {
895 for (int col = 0; col < cols(); ++col) {
896 (*this)[row, col] -= rhs;
897 }
898 }
899
900 return *this;
901 }
902
908 friend SLEIPNIR_DLLEXPORT VariableMatrix
909 operator-(const SleipnirMatrixLike auto& lhs) {
910 VariableMatrix result{VariableMatrix::empty, lhs.rows(), lhs.cols()};
911
912 for (int row = 0; row < result.rows(); ++row) {
913 for (int col = 0; col < result.cols(); ++col) {
914 result[row, col] = -lhs[row, col];
915 }
916 }
917
918 return result;
919 }
920
924 operator Variable() const { // NOLINT
925 slp_assert(rows() == 1 && cols() == 1);
926 return (*this)[0, 0];
927 }
928
935 VariableMatrix result{VariableMatrix::empty, cols(), rows()};
936
937 for (int row = 0; row < rows(); ++row) {
938 for (int col = 0; col < cols(); ++col) {
939 result[col, row] = (*this)[row, col];
940 }
941 }
942
943 return result;
944 }
945
951 int rows() const { return m_rows; }
952
958 int cols() const { return m_cols; }
959
967 double value(int row, int col) {
968 slp_assert(row >= 0 && row < rows());
969 slp_assert(col >= 0 && col < cols());
970 return m_storage[row * cols() + col].value();
971 }
972
979 double value(int index) {
980 slp_assert(index >= 0 && index < rows() * cols());
981 return m_storage[index].value();
982 }
983
989 Eigen::MatrixXd value() {
990 Eigen::MatrixXd result{rows(), cols()};
991
992 for (int row = 0; row < rows(); ++row) {
993 for (int col = 0; col < cols(); ++col) {
994 result(row, col) = value(row, col);
995 }
996 }
997
998 return result;
999 }
1000
1008 function_ref<Variable(const Variable& x)> unary_op) const {
1009 VariableMatrix result{VariableMatrix::empty, rows(), cols()};
1010
1011 for (int row = 0; row < rows(); ++row) {
1012 for (int col = 0; col < cols(); ++col) {
1013 result[row, col] = unary_op((*this)[row, col]);
1014 }
1015 }
1016
1017 return result;
1018 }
1019
1020#ifndef DOXYGEN_SHOULD_SKIP_THIS
1021
1022 class iterator {
1023 public:
1024 using iterator_category = std::forward_iterator_tag;
1025 using value_type = Variable;
1026 using difference_type = std::ptrdiff_t;
1027 using pointer = Variable*;
1028 using reference = Variable&;
1029
1030 constexpr iterator() noexcept = default;
1031
1032 explicit constexpr iterator(small_vector<Variable>::iterator it) noexcept
1033 : m_it{it} {}
1034
1035 constexpr iterator& operator++() noexcept {
1036 ++m_it;
1037 return *this;
1038 }
1039
1040 constexpr iterator operator++(int) noexcept {
1041 iterator retval = *this;
1042 ++(*this);
1043 return retval;
1044 }
1045
1046 constexpr bool operator==(const iterator&) const noexcept = default;
1047
1048 constexpr reference operator*() const noexcept { return *m_it; }
1049
1050 private:
1051 small_vector<Variable>::iterator m_it;
1052 };
1053
1054 class const_iterator {
1055 public:
1056 using iterator_category = std::forward_iterator_tag;
1057 using value_type = Variable;
1058 using difference_type = std::ptrdiff_t;
1059 using pointer = Variable*;
1060 using const_reference = const Variable&;
1061
1062 constexpr const_iterator() noexcept = default;
1063
1064 explicit constexpr const_iterator(
1065 small_vector<Variable>::const_iterator it) noexcept
1066 : m_it{it} {}
1067
1068 constexpr const_iterator& operator++() noexcept {
1069 ++m_it;
1070 return *this;
1071 }
1072
1073 constexpr const_iterator operator++(int) noexcept {
1074 const_iterator retval = *this;
1075 ++(*this);
1076 return retval;
1077 }
1078
1079 constexpr bool operator==(const const_iterator&) const noexcept = default;
1080
1081 constexpr const_reference operator*() const noexcept { return *m_it; }
1082
1083 private:
1084 small_vector<Variable>::const_iterator m_it;
1085 };
1086
1087#endif // DOXYGEN_SHOULD_SKIP_THIS
1088
1094 iterator begin() { return iterator{m_storage.begin()}; }
1095
1101 iterator end() { return iterator{m_storage.end()}; }
1102
1108 const_iterator begin() const { return const_iterator{m_storage.begin()}; }
1109
1115 const_iterator end() const { return const_iterator{m_storage.end()}; }
1116
1122 const_iterator cbegin() const { return const_iterator{m_storage.cbegin()}; }
1123
1129 const_iterator cend() const { return const_iterator{m_storage.cend()}; }
1130
1136 size_t size() const { return m_storage.size(); }
1137
1145 static VariableMatrix zero(int rows, int cols) {
1146 VariableMatrix result{VariableMatrix::empty, rows, cols};
1147
1148 for (auto& elem : result) {
1149 elem = 0.0;
1150 }
1151
1152 return result;
1153 }
1154
1162 static VariableMatrix ones(int rows, int cols) {
1163 VariableMatrix result{VariableMatrix::empty, rows, cols};
1164
1165 for (auto& elem : result) {
1166 elem = 1.0;
1167 }
1168
1169 return result;
1170 }
1171
1172 private:
1173 small_vector<Variable> m_storage;
1174 int m_rows = 0;
1175 int m_cols = 0;
1176};
1177
1185SLEIPNIR_DLLEXPORT inline VariableMatrix cwise_reduce(
1186 const VariableMatrix& lhs, const VariableMatrix& rhs,
1187 function_ref<Variable(const Variable& x, const Variable& y)> binary_op) {
1188 slp_assert(lhs.rows() == rhs.rows() && lhs.rows() == rhs.rows());
1189
1190 VariableMatrix result{VariableMatrix::empty, lhs.rows(), lhs.cols()};
1191
1192 for (int row = 0; row < lhs.rows(); ++row) {
1193 for (int col = 0; col < lhs.cols(); ++col) {
1194 result[row, col] = binary_op(lhs[row, col], rhs[row, col]);
1195 }
1196 }
1197
1198 return result;
1199}
1200
1211SLEIPNIR_DLLEXPORT inline VariableMatrix block(
1212 std::initializer_list<std::initializer_list<VariableMatrix>> list) {
1213 // Get row and column counts for destination matrix
1214 int rows = 0;
1215 int cols = -1;
1216 for (const auto& row : list) {
1217 if (row.size() > 0) {
1218 rows += row.begin()->rows();
1219 }
1220
1221 // Get number of columns in this row
1222 int latest_cols = 0;
1223 for (const auto& elem : row) {
1224 // Assert the first and latest row have the same height
1225 slp_assert(row.begin()->rows() == elem.rows());
1226
1227 latest_cols += elem.cols();
1228 }
1229
1230 // If this is the first row, record the column count. Otherwise, assert the
1231 // first and latest column counts are the same.
1232 if (cols == -1) {
1233 cols = latest_cols;
1234 } else {
1235 slp_assert(cols == latest_cols);
1236 }
1237 }
1238
1239 VariableMatrix result{VariableMatrix::empty, rows, cols};
1240
1241 int row_offset = 0;
1242 for (const auto& row : list) {
1243 int col_offset = 0;
1244 for (const auto& elem : row) {
1245 result.block(row_offset, col_offset, elem.rows(), elem.cols()) = elem;
1246 col_offset += elem.cols();
1247 }
1248 row_offset += row.begin()->rows();
1249 }
1250
1251 return result;
1252}
1253
1266SLEIPNIR_DLLEXPORT inline VariableMatrix block(
1267 const std::vector<std::vector<VariableMatrix>>& list) {
1268 // Get row and column counts for destination matrix
1269 int rows = 0;
1270 int cols = -1;
1271 for (const auto& row : list) {
1272 if (row.size() > 0) {
1273 rows += row.begin()->rows();
1274 }
1275
1276 // Get number of columns in this row
1277 int latest_cols = 0;
1278 for (const auto& elem : row) {
1279 // Assert the first and latest row have the same height
1280 slp_assert(row.begin()->rows() == elem.rows());
1281
1282 latest_cols += elem.cols();
1283 }
1284
1285 // If this is the first row, record the column count. Otherwise, assert the
1286 // first and latest column counts are the same.
1287 if (cols == -1) {
1288 cols = latest_cols;
1289 } else {
1290 slp_assert(cols == latest_cols);
1291 }
1292 }
1293
1294 VariableMatrix result{VariableMatrix::empty, rows, cols};
1295
1296 int row_offset = 0;
1297 for (const auto& row : list) {
1298 int col_offset = 0;
1299 for (const auto& elem : row) {
1300 result.block(row_offset, col_offset, elem.rows(), elem.cols()) = elem;
1301 col_offset += elem.cols();
1302 }
1303 row_offset += row.begin()->rows();
1304 }
1305
1306 return result;
1307}
1308
1316SLEIPNIR_DLLEXPORT VariableMatrix solve(const VariableMatrix& A,
1317 const VariableMatrix& B);
1318
1319} // namespace slp
Definition slice.hpp:31
constexpr int adjust(int length)
Definition slice.hpp:134
Definition variable_block.hpp:24
Definition variable_matrix.hpp:29
VariableMatrix & operator=(ScalarLike auto value)
Definition variable_matrix.hpp:229
Eigen::MatrixXd value()
Definition variable_matrix.hpp:989
const VariableBlock< const VariableMatrix > operator[](Slice row_slice, int row_slice_length, Slice col_slice, int col_slice_length) const
Definition variable_matrix.hpp:484
const VariableBlock< const VariableMatrix > row(int row) const
Definition variable_matrix.hpp:535
VariableBlock< VariableMatrix > segment(int offset, int length)
Definition variable_matrix.hpp:498
VariableMatrix(const Eigen::DiagonalBase< Derived > &values)
Definition variable_matrix.hpp:187
const_iterator end() const
Definition variable_matrix.hpp:1115
VariableBlock< VariableMatrix > operator[](Slice row_slice, int row_slice_length, Slice col_slice, int col_slice_length)
Definition variable_matrix.hpp:464
const_iterator cend() const
Definition variable_matrix.hpp:1129
VariableMatrix(const Variable &variable)
Definition variable_matrix.hpp:259
VariableBlock< VariableMatrix > block(int row_offset, int col_offset, int block_rows, int block_cols)
Definition variable_matrix.hpp:393
friend SLEIPNIR_DLLEXPORT VariableMatrix operator*(const ScalarLike auto &lhs, const SleipnirMatrixLike auto &rhs)
Definition variable_matrix.hpp:646
VariableMatrix & operator*=(const MatrixLike auto &rhs)
Definition variable_matrix.hpp:687
size_t size() const
Definition variable_matrix.hpp:1136
VariableMatrix & operator+=(const ScalarLike auto &rhs)
Definition variable_matrix.hpp:821
friend SLEIPNIR_DLLEXPORT VariableMatrix operator-(const LHS &lhs, const RHS &rhs)
Definition variable_matrix.hpp:842
VariableMatrix & operator/=(const ScalarLike auto &rhs)
Definition variable_matrix.hpp:753
VariableMatrix()=default
const VariableBlock< const VariableMatrix > block(int row_offset, int col_offset, int block_rows, int block_cols) const
Definition variable_matrix.hpp:411
const Variable & operator[](int row) const
Definition variable_matrix.hpp:379
VariableMatrix(const Eigen::MatrixBase< Derived > &values)
Definition variable_matrix.hpp:170
const VariableBlock< const VariableMatrix > operator[](Slice row_slice, Slice col_slice) const
Definition variable_matrix.hpp:443
friend SLEIPNIR_DLLEXPORT VariableMatrix operator*(const Variable &lhs, const MatrixLike auto &rhs)
Definition variable_matrix.hpp:665
VariableMatrix & operator+=(const MatrixLike auto &rhs)
Definition variable_matrix.hpp:799
VariableMatrix T() const
Definition variable_matrix.hpp:934
VariableMatrix & operator*=(const ScalarLike auto &rhs)
Definition variable_matrix.hpp:713
VariableMatrix cwise_transform(function_ref< Variable(const Variable &x)> unary_op) const
Definition variable_matrix.hpp:1007
const Variable & operator[](int row, int col) const
Definition variable_matrix.hpp:356
static VariableMatrix ones(int rows, int cols)
Definition variable_matrix.hpp:1162
double value(int index)
Definition variable_matrix.hpp:979
VariableMatrix & operator-=(const MatrixLike auto &rhs)
Definition variable_matrix.hpp:869
VariableMatrix(int rows, int cols)
Definition variable_matrix.hpp:64
VariableBlock< VariableMatrix > operator[](Slice row_slice, Slice col_slice)
Definition variable_matrix.hpp:429
friend SLEIPNIR_DLLEXPORT VariableMatrix operator*(const MatrixLike auto &lhs, const Variable &rhs)
Definition variable_matrix.hpp:622
VariableMatrix(int rows)
Definition variable_matrix.hpp:51
VariableMatrix(const VariableBlock< const VariableMatrix > &values)
Definition variable_matrix.hpp:293
friend SLEIPNIR_DLLEXPORT VariableMatrix operator/(const MatrixLike auto &lhs, const ScalarLike auto &rhs)
Definition variable_matrix.hpp:731
iterator end()
Definition variable_matrix.hpp:1101
VariableBlock< VariableMatrix > row(int row)
Definition variable_matrix.hpp:524
VariableMatrix & operator-=(const ScalarLike auto &rhs)
Definition variable_matrix.hpp:891
const_iterator cbegin() const
Definition variable_matrix.hpp:1122
VariableMatrix(empty_t, int rows, int cols)
Definition variable_matrix.hpp:77
Variable & operator[](int row)
Definition variable_matrix.hpp:368
VariableMatrix(std::span< const Variable > values)
Definition variable_matrix.hpp:308
VariableMatrix(std::span< const Variable > values, int rows, int cols)
Definition variable_matrix.hpp:325
const_iterator begin() const
Definition variable_matrix.hpp:1108
Variable & operator[](int row, int col)
Definition variable_matrix.hpp:343
double value(int row, int col)
Definition variable_matrix.hpp:967
iterator begin()
Definition variable_matrix.hpp:1094
static VariableMatrix zero(int rows, int cols)
Definition variable_matrix.hpp:1145
VariableMatrix & operator=(const Eigen::MatrixBase< Derived > &values)
Definition variable_matrix.hpp:209
friend SLEIPNIR_DLLEXPORT VariableMatrix operator-(const SleipnirMatrixLike auto &lhs)
Definition variable_matrix.hpp:909
const VariableBlock< const VariableMatrix > col(int col) const
Definition variable_matrix.hpp:557
int rows() const
Definition variable_matrix.hpp:951
int cols() const
Definition variable_matrix.hpp:958
VariableMatrix(Variable &&variable)
Definition variable_matrix.hpp:269
const VariableBlock< const VariableMatrix > segment(int offset, int length) const
Definition variable_matrix.hpp:511
friend SLEIPNIR_DLLEXPORT VariableMatrix operator*(const SleipnirMatrixLike auto &lhs, const ScalarLike auto &rhs)
Definition variable_matrix.hpp:604
VariableMatrix(std::initializer_list< std::initializer_list< Variable > > list)
Definition variable_matrix.hpp:89
void set_value(const Eigen::MatrixBase< Derived > &values)
Definition variable_matrix.hpp:244
VariableMatrix(const std::vector< std::vector< double > > &list)
Definition variable_matrix.hpp:117
VariableMatrix(const std::vector< std::vector< Variable > > &list)
Definition variable_matrix.hpp:144
VariableBlock< VariableMatrix > col(int col)
Definition variable_matrix.hpp:546
static constexpr empty_t empty
Definition variable_matrix.hpp:39
friend SLEIPNIR_DLLEXPORT VariableMatrix operator*(const LHS &lhs, const RHS &rhs)
Definition variable_matrix.hpp:570
friend SLEIPNIR_DLLEXPORT VariableMatrix operator+(const LHS &lhs, const RHS &rhs)
Definition variable_matrix.hpp:772
VariableMatrix(const VariableBlock< VariableMatrix > &values)
Definition variable_matrix.hpp:278
Definition variable.hpp:41
Definition function_ref.hpp:13
Definition concepts.hpp:26
Definition concepts.hpp:40
Definition concepts.hpp:13
Definition concepts.hpp:30
Definition variable_matrix.hpp:34