Sleipnir C++ API
Loading...
Searching...
No Matches
variable_block.hpp
1// Copyright (c) Sleipnir contributors
2
3#pragma once
4
5#include <concepts>
6#include <cstddef>
7#include <iterator>
8#include <type_traits>
9#include <utility>
10
11#include <Eigen/Core>
12
13#include "sleipnir/autodiff/sleipnir_base.hpp"
14#include "sleipnir/autodiff/slice.hpp"
15#include "sleipnir/autodiff/variable.hpp"
16#include "sleipnir/util/assert.hpp"
17#include "sleipnir/util/concepts.hpp"
18#include "sleipnir/util/empty.hpp"
19#include "sleipnir/util/function_ref.hpp"
20
21namespace slp {
22
26template <typename Mat>
28 public:
30 using Scalar = typename Mat::Scalar;
31
34
40 if (this == &values) {
41 return *this;
42 }
43
44 if (m_mat == nullptr) {
45 m_mat = values.m_mat;
46 m_row_slice = values.m_row_slice;
47 m_row_slice_length = values.m_row_slice_length;
48 m_col_slice = values.m_col_slice;
49 m_col_slice_length = values.m_col_slice_length;
50 } else {
51 slp_assert(rows() == values.rows() && cols() == values.cols());
52
53 for (int row = 0; row < rows(); ++row) {
54 for (int col = 0; col < cols(); ++col) {
55 (*this)[row, col] = values[row, col];
56 }
57 }
58 }
59
60 return *this;
61 }
62
65
71 if (this == &values) {
72 return *this;
73 }
74
75 if (m_mat == nullptr) {
76 m_mat = values.m_mat;
77 m_row_slice = values.m_row_slice;
78 m_row_slice_length = values.m_row_slice_length;
79 m_col_slice = values.m_col_slice;
80 m_col_slice_length = values.m_col_slice_length;
81 } else {
82 slp_assert(rows() == values.rows() && cols() == values.cols());
83
84 for (int row = 0; row < rows(); ++row) {
85 for (int col = 0; col < cols(); ++col) {
86 (*this)[row, col] = values[row, col];
87 }
88 }
89 }
90
91 return *this;
92 }
93
97 // NOLINTNEXTLINE (google-explicit-constructor)
99
108 int block_cols)
109 : m_mat{&mat},
110 m_row_slice{row_offset, row_offset + block_rows, 1},
111 m_row_slice_length{m_row_slice.adjust(mat.rows())},
112 m_col_slice{col_offset, col_offset + block_cols, 1},
113 m_col_slice_length{m_col_slice.adjust(mat.cols())} {}
114
126 : m_mat{&mat},
127 m_row_slice{std::move(row_slice)},
128 m_row_slice_length{row_slice_length},
129 m_col_slice{std::move(col_slice)},
130 m_col_slice_length{col_slice_length} {}
131
139 slp_assert(rows() == 1 && cols() == 1);
140
141 (*this)[0, 0] = value;
142
143 return *this;
144 }
145
152 slp_assert(rows() == 1 && cols() == 1);
153
154 (*this)[0, 0].set_value(value);
155 }
156
161 template <typename Derived>
162 VariableBlock<Mat>& operator=(const Eigen::MatrixBase<Derived>& values) {
163 slp_assert(rows() == values.rows() && cols() == values.cols());
164
165 for (int row = 0; row < rows(); ++row) {
166 for (int col = 0; col < cols(); ++col) {
167 (*this)[row, col] = values[row, col];
168 }
169 }
170
171 return *this;
172 }
173
177 template <typename Derived>
178 requires std::same_as<typename Derived::Scalar, Scalar>
179 void set_value(const Eigen::MatrixBase<Derived>& values) {
180 slp_assert(rows() == values.rows() && cols() == values.cols());
181
182 for (int row = 0; row < rows(); ++row) {
183 for (int col = 0; col < cols(); ++col) {
184 (*this)[row, col].set_value(values[row, col]);
185 }
186 }
187 }
188
194 slp_assert(rows() == values.rows() && cols() == values.cols());
195
196 for (int row = 0; row < rows(); ++row) {
197 for (int col = 0; col < cols(); ++col) {
198 (*this)[row, col] = values[row, col];
199 }
200 }
201 return *this;
202 }
203
209 slp_assert(rows() == values.rows() && cols() == values.cols());
210
211 for (int row = 0; row < rows(); ++row) {
212 for (int col = 0; col < cols(); ++col) {
213 (*this)[row, col] = std::move(values[row, col]);
214 }
215 }
216 return *this;
217 }
218
225 requires(!std::is_const_v<Mat>)
226 {
227 slp_assert(row >= 0 && row < rows());
228 slp_assert(col >= 0 && col < cols());
229 return (*m_mat)[m_row_slice.start + row * m_row_slice.step,
230 m_col_slice.start + col * m_col_slice.step];
231 }
232
238 const Variable<Scalar>& operator[](int row, int col) const {
239 slp_assert(row >= 0 && row < rows());
240 slp_assert(col >= 0 && col < cols());
241 return (*m_mat)[m_row_slice.start + row * m_row_slice.step,
242 m_col_slice.start + col * m_col_slice.step];
243 }
244
250 requires(!std::is_const_v<Mat>)
251 {
252 slp_assert(index >= 0 && index < rows() * cols());
253 return (*this)[index / cols(), index % cols()];
254 }
255
260 const Variable<Scalar>& operator[](int index) const {
261 slp_assert(index >= 0 && index < rows() * cols());
262 return (*this)[index / cols(), index % cols()];
263 }
264
273 int block_cols) {
274 slp_assert(row_offset >= 0 && row_offset <= rows());
275 slp_assert(col_offset >= 0 && col_offset <= cols());
276 slp_assert(block_rows >= 0 && block_rows <= rows() - row_offset);
277 slp_assert(block_cols >= 0 && block_cols <= cols() - col_offset);
278 return (*this)[Slice{row_offset, row_offset + block_rows, 1},
280 }
281
290 int block_rows, int block_cols) const {
291 slp_assert(row_offset >= 0 && row_offset <= rows());
292 slp_assert(col_offset >= 0 && col_offset <= cols());
293 slp_assert(block_rows >= 0 && block_rows <= rows() - row_offset);
294 slp_assert(block_cols >= 0 && block_cols <= cols() - col_offset);
295 return (*this)[Slice{row_offset, row_offset + block_rows, 1},
297 }
298
305 int row_slice_length = row_slice.adjust(m_row_slice_length);
306 int col_slice_length = col_slice.adjust(m_col_slice_length);
308 }
309
316 Slice col_slice) const {
317 int row_slice_length = row_slice.adjust(m_row_slice_length);
318 int col_slice_length = col_slice.adjust(m_col_slice_length);
320 }
321
334 return VariableBlock{
335 *m_mat,
336 {m_row_slice.start + row_slice.start * m_row_slice.step,
337 m_row_slice.start + row_slice.stop * m_row_slice.step,
338 row_slice.step * m_row_slice.step},
340 {m_col_slice.start + col_slice.start * m_col_slice.step,
341 m_col_slice.start + col_slice.stop * m_col_slice.step,
342 col_slice.step * m_col_slice.step},
344 }
345
359 int col_slice_length) const {
360 return VariableBlock{
361 *m_mat,
362 {m_row_slice.start + row_slice.start * m_row_slice.step,
363 m_row_slice.start + row_slice.stop * m_row_slice.step,
364 row_slice.step * m_row_slice.step},
366 {m_col_slice.start + col_slice.start * m_col_slice.step,
367 m_col_slice.start + col_slice.stop * m_col_slice.step,
368 col_slice.step * m_col_slice.step},
370 }
371
378 slp_assert(cols() == 1);
379 slp_assert(offset >= 0 && offset < rows());
380 slp_assert(length >= 0 && length <= rows() - offset);
381 return block(offset, 0, length, 1);
382 }
383
389 const VariableBlock<Mat> segment(int offset, int length) const {
390 slp_assert(cols() == 1);
391 slp_assert(offset >= 0 && offset < rows());
392 slp_assert(length >= 0 && length <= rows() - offset);
393 return block(offset, 0, length, 1);
394 }
395
401 slp_assert(row >= 0 && row < rows());
402 return block(row, 0, 1, cols());
403 }
404
410 slp_assert(row >= 0 && row < rows());
411 return block(row, 0, 1, cols());
412 }
413
419 slp_assert(col >= 0 && col < cols());
420 return block(0, col, rows(), 1);
421 }
422
428 slp_assert(col >= 0 && col < cols());
429 return block(0, col, rows(), 1);
430 }
431
437 slp_assert(cols() == rhs.rows() && cols() == rhs.cols());
438
439 for (int i = 0; i < rows(); ++i) {
440 Mat lhs_old_row = row(i);
441 for (int j = 0; j < rhs.cols(); ++j) {
442 Variable sum{Scalar(0)};
443 for (int k = 0; k < cols(); ++k) {
444 sum += lhs_old_row[k] * rhs[k, j];
445 }
446 (*this)[i, j] = sum;
447 }
448 }
449
450 return *this;
451 }
452
458 for (int row = 0; row < rows(); ++row) {
459 for (int col = 0; col < cols(); ++col) {
460 (*this)[row, col] *= rhs;
461 }
462 }
463
464 return *this;
465 }
466
472 for (int row = 0; row < rows(); ++row) {
473 for (int col = 0; col < cols(); ++col) {
474 (*this)[row, col] /= rhs;
475 }
476 }
477
478 return *this;
479 }
480
486 slp_assert(rows() == rhs.rows() && cols() == rhs.cols());
487
488 for (int row = 0; row < rows(); ++row) {
489 for (int col = 0; col < cols(); ++col) {
490 (*this)[row, col] += rhs[row, col];
491 }
492 }
493
494 return *this;
495 }
496
502 slp_assert(rows() == 1 && cols() == 1);
503
504 for (int row = 0; row < rows(); ++row) {
505 for (int col = 0; col < cols(); ++col) {
506 (*this)[row, col] += rhs;
507 }
508 }
509
510 return *this;
511 }
512
518 slp_assert(rows() == rhs.rows() && cols() == rhs.cols());
519
520 for (int row = 0; row < rows(); ++row) {
521 for (int col = 0; col < cols(); ++col) {
522 (*this)[row, col] -= rhs[row, col];
523 }
524 }
525
526 return *this;
527 }
528
534 slp_assert(rows() == 1 && cols() == 1);
535
536 for (int row = 0; row < rows(); ++row) {
537 for (int col = 0; col < cols(); ++col) {
538 (*this)[row, col] -= rhs;
539 }
540 }
541
542 return *this;
543 }
544
546 // NOLINTNEXTLINE (google-explicit-constructor)
547 operator Variable<Scalar>() const {
548 slp_assert(rows() == 1 && cols() == 1);
549 return (*this)[0, 0];
550 }
551
555 std::remove_cv_t<Mat> T() const {
556 std::remove_cv_t<Mat> result{detail::empty, cols(), rows()};
557
558 for (int row = 0; row < rows(); ++row) {
559 for (int col = 0; col < cols(); ++col) {
560 result[col, row] = (*this)[row, col];
561 }
562 }
563
564 return result;
565 }
566
570 int rows() const { return m_row_slice_length; }
571
575 int cols() const { return m_col_slice_length; }
576
582 Scalar value(int row, int col) { return (*this)[row, col].value(); }
583
588 Scalar value(int index) {
589 slp_assert(index >= 0 && index < rows() * cols());
590 return value(index / cols(), index % cols());
591 }
592
596 Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic> value() {
597 Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic> result{rows(),
598 cols()};
599
600 for (int row = 0; row < rows(); ++row) {
601 for (int col = 0; col < cols(); ++col) {
602 result[row, col] = value(row, col);
603 }
604 }
605
606 return result;
607 }
608
613 std::remove_cv_t<Mat> cwise_transform(
615 const {
616 std::remove_cv_t<Mat> result{detail::empty, rows(), cols()};
617
618 for (int row = 0; row < rows(); ++row) {
619 for (int col = 0; col < cols(); ++col) {
620 result[row, col] = unary_op((*this)[row, col]);
621 }
622 }
623
624 return result;
625 }
626
630 std::remove_cv_t<Mat> exp() const {
631 return std::remove_cv_t<Mat>{*this}.exp();
632 }
633
634#ifndef DOXYGEN_SHOULD_SKIP_THIS
635
636 class iterator {
637 public:
638 using iterator_category = std::bidirectional_iterator_tag;
639 using value_type = Variable<Scalar>;
640 using difference_type = std::ptrdiff_t;
641 using pointer = Variable<Scalar>*;
643
644 constexpr iterator() noexcept = default;
645
646 constexpr iterator(VariableBlock<Mat>* mat, int index) noexcept
647 : m_mat{mat}, m_index{index} {}
648
649 constexpr iterator& operator++() noexcept {
650 ++m_index;
651 return *this;
652 }
653
654 constexpr iterator operator++(int) noexcept {
655 iterator retval = *this;
656 ++(*this);
657 return retval;
658 }
659
660 constexpr iterator& operator--() noexcept {
661 --m_index;
662 return *this;
663 }
664
665 constexpr iterator operator--(int) noexcept {
666 iterator retval = *this;
667 --(*this);
668 return retval;
669 }
670
671 constexpr bool operator==(const iterator&) const noexcept = default;
672
673 constexpr reference operator*() const noexcept { return (*m_mat)[m_index]; }
674
675 private:
676 VariableBlock<Mat>* m_mat = nullptr;
677 int m_index = 0;
678 };
679
680 class const_iterator {
681 public:
682 using iterator_category = std::bidirectional_iterator_tag;
683 using value_type = Variable<Scalar>;
684 using difference_type = std::ptrdiff_t;
685 using pointer = Variable<Scalar>*;
686 using const_reference = const Variable<Scalar>&;
687
688 constexpr const_iterator() noexcept = default;
689
690 constexpr const_iterator(const VariableBlock<Mat>* mat, int index) noexcept
691 : m_mat{mat}, m_index{index} {}
692
693 constexpr const_iterator& operator++() noexcept {
694 ++m_index;
695 return *this;
696 }
697
698 constexpr const_iterator operator++(int) noexcept {
699 const_iterator retval = *this;
700 ++(*this);
701 return retval;
702 }
703
704 constexpr const_iterator& operator--() noexcept {
705 --m_index;
706 return *this;
707 }
708
709 constexpr const_iterator operator--(int) noexcept {
710 iterator retval = *this;
711 --(*this);
712 return retval;
713 }
714
715 constexpr bool operator==(const const_iterator&) const noexcept = default;
716
717 constexpr const_reference operator*() const noexcept {
718 return (*m_mat)[m_index];
719 }
720
721 private:
722 const VariableBlock<Mat>* m_mat = nullptr;
723 int m_index = 0;
724 };
725
726 using reverse_iterator = std::reverse_iterator<iterator>;
727 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
728
729#endif // DOXYGEN_SHOULD_SKIP_THIS
730
734 iterator begin() { return iterator(this, 0); }
735
739 iterator end() { return iterator(this, rows() * cols()); }
740
744 const_iterator begin() const { return const_iterator(this, 0); }
745
749 const_iterator end() const { return const_iterator(this, rows() * cols()); }
750
754 const_iterator cbegin() const { return const_iterator(this, 0); }
755
759 const_iterator cend() const { return const_iterator(this, rows() * cols()); }
760
764 reverse_iterator rbegin() { return reverse_iterator{end()}; }
765
769 reverse_iterator rend() { return reverse_iterator{begin()}; }
770
774 const_reverse_iterator rbegin() const {
775 return const_reverse_iterator{end()};
776 }
777
781 const_reverse_iterator rend() const {
782 return const_reverse_iterator{begin()};
783 }
784
788 const_reverse_iterator crbegin() const {
789 return const_reverse_iterator{cend()};
790 }
791
795 const_reverse_iterator crend() const {
796 return const_reverse_iterator{cbegin()};
797 }
798
802 size_t size() const { return rows() * cols(); }
803
804 private:
805 Mat* m_mat = nullptr;
806
807 Slice m_row_slice;
808 int m_row_slice_length = 0;
809
810 Slice m_col_slice;
811 int m_col_slice_length = 0;
812};
813
814} // namespace slp
Definition intrusive_shared_ptr.hpp:27
Definition sleipnir_base.hpp:9
Represents a sequence of elements in an iterable object.
Definition slice.hpp:25
int step
Step.
Definition slice.hpp:34
int start
Start index (inclusive).
Definition slice.hpp:28
Definition variable_block.hpp:27
VariableBlock< Mat > & operator=(const Mat &values)
Definition variable_block.hpp:193
VariableBlock< Mat > & operator*=(const ScalarLike auto &rhs)
Definition variable_block.hpp:457
const_iterator begin() const
Definition variable_block.hpp:744
const_iterator end() const
Definition variable_block.hpp:749
void set_value(const Eigen::MatrixBase< Derived > &values)
Definition variable_block.hpp:179
const_iterator cbegin() const
Definition variable_block.hpp:754
void set_value(Scalar value)
Definition variable_block.hpp:151
VariableBlock< Mat > row(int row)
Definition variable_block.hpp:400
VariableBlock< Mat > operator[](Slice row_slice, int row_slice_length, Slice col_slice, int col_slice_length)
Definition variable_block.hpp:332
VariableBlock< Mat > & operator=(ScalarLike auto value)
Definition variable_block.hpp:138
Variable< Scalar > & operator[](int index)
Definition variable_block.hpp:249
Variable< Scalar > & operator[](int row, int col)
Definition variable_block.hpp:224
VariableBlock< Mat > & operator+=(const MatrixLike auto &rhs)
Definition variable_block.hpp:485
VariableBlock< Mat > & operator*=(const MatrixLike auto &rhs)
Definition variable_block.hpp:436
iterator begin()
Definition variable_block.hpp:734
std::remove_cv_t< Mat > exp() const
Definition variable_block.hpp:630
VariableBlock(VariableBlock< Mat > &&)=default
Move constructor.
VariableBlock< Mat > & operator=(const VariableBlock< Mat > &values)
Definition variable_block.hpp:39
const Variable< Scalar > & operator[](int index) const
Definition variable_block.hpp:260
VariableBlock< const Mat > col(int col) const
Definition variable_block.hpp:427
int rows() const
Definition variable_block.hpp:570
VariableBlock< Mat > operator[](Slice row_slice, Slice col_slice)
Definition variable_block.hpp:304
VariableBlock< Mat > col(int col)
Definition variable_block.hpp:418
const VariableBlock< const Mat > operator[](Slice row_slice, Slice col_slice) const
Definition variable_block.hpp:315
VariableBlock< Mat > & operator=(const Eigen::MatrixBase< Derived > &values)
Definition variable_block.hpp:162
Scalar value(int index)
Definition variable_block.hpp:588
reverse_iterator rbegin()
Definition variable_block.hpp:764
VariableBlock< Mat > & operator=(Mat &&values)
Definition variable_block.hpp:208
const_iterator cend() const
Definition variable_block.hpp:759
const Variable< Scalar > & operator[](int row, int col) const
Definition variable_block.hpp:238
const_reverse_iterator crbegin() const
Definition variable_block.hpp:788
VariableBlock< Mat > & operator-=(const ScalarLike auto &rhs)
Definition variable_block.hpp:533
VariableBlock(Mat &mat, int row_offset, int col_offset, int block_rows, int block_cols)
Definition variable_block.hpp:107
VariableBlock< Mat > & operator/=(const ScalarLike auto &rhs)
Definition variable_block.hpp:471
VariableBlock< Mat > segment(int offset, int length)
Definition variable_block.hpp:377
const_reverse_iterator rend() const
Definition variable_block.hpp:781
VariableBlock< Mat > & operator-=(const MatrixLike auto &rhs)
Definition variable_block.hpp:517
VariableBlock< Mat > & operator+=(const ScalarLike auto &rhs)
Definition variable_block.hpp:501
Eigen::Matrix< Scalar, Eigen::Dynamic, Eigen::Dynamic > value()
Definition variable_block.hpp:596
iterator end()
Definition variable_block.hpp:739
VariableBlock(Mat &mat)
Definition variable_block.hpp:98
VariableBlock< const Mat > row(int row) const
Definition variable_block.hpp:409
const VariableBlock< Mat > segment(int offset, int length) const
Definition variable_block.hpp:389
Scalar value(int row, int col)
Definition variable_block.hpp:582
int cols() const
Definition variable_block.hpp:575
VariableBlock< Mat > block(int row_offset, int col_offset, int block_rows, int block_cols)
Definition variable_block.hpp:272
reverse_iterator rend()
Definition variable_block.hpp:769
size_t size() const
Definition variable_block.hpp:802
std::remove_cv_t< Mat > T() const
Definition variable_block.hpp:555
VariableBlock(const VariableBlock< Mat > &)=default
Copy constructor.
std::remove_cv_t< Mat > cwise_transform(function_ref< Variable< Scalar >(const Variable< Scalar > &x)> unary_op) const
Definition variable_block.hpp:613
VariableBlock< Mat > & operator=(VariableBlock< Mat > &&values)
Definition variable_block.hpp:70
VariableBlock(Mat &mat, Slice row_slice, int row_slice_length, Slice col_slice, int col_slice_length)
Definition variable_block.hpp:124
const VariableBlock< const Mat > operator[](Slice row_slice, int row_slice_length, Slice col_slice, int col_slice_length) const
Definition variable_block.hpp:356
const_reverse_iterator crend() const
Definition variable_block.hpp:795
const_reverse_iterator rbegin() const
Definition variable_block.hpp:774
const VariableBlock< const Mat > block(int row_offset, int col_offset, int block_rows, int block_cols) const
Definition variable_block.hpp:289
typename Mat::Scalar Scalar
Scalar type alias.
Definition variable_block.hpp:30
Definition variable.hpp:55
Definition function_ref.hpp:13
Definition concepts.hpp:18
Definition concepts.hpp:24