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
627#ifndef DOXYGEN_SHOULD_SKIP_THIS
628
629 class iterator {
630 public:
631 using iterator_category = std::bidirectional_iterator_tag;
632 using value_type = Variable<Scalar>;
633 using difference_type = std::ptrdiff_t;
634 using pointer = Variable<Scalar>*;
636
637 constexpr iterator() noexcept = default;
638
639 constexpr iterator(VariableBlock<Mat>* mat, int index) noexcept
640 : m_mat{mat}, m_index{index} {}
641
642 constexpr iterator& operator++() noexcept {
643 ++m_index;
644 return *this;
645 }
646
647 constexpr iterator operator++(int) noexcept {
648 iterator retval = *this;
649 ++(*this);
650 return retval;
651 }
652
653 constexpr iterator& operator--() noexcept {
654 --m_index;
655 return *this;
656 }
657
658 constexpr iterator operator--(int) noexcept {
659 iterator retval = *this;
660 --(*this);
661 return retval;
662 }
663
664 constexpr bool operator==(const iterator&) const noexcept = default;
665
666 constexpr reference operator*() const noexcept { return (*m_mat)[m_index]; }
667
668 private:
669 VariableBlock<Mat>* m_mat = nullptr;
670 int m_index = 0;
671 };
672
673 class const_iterator {
674 public:
675 using iterator_category = std::bidirectional_iterator_tag;
676 using value_type = Variable<Scalar>;
677 using difference_type = std::ptrdiff_t;
678 using pointer = Variable<Scalar>*;
679 using const_reference = const Variable<Scalar>&;
680
681 constexpr const_iterator() noexcept = default;
682
683 constexpr const_iterator(const VariableBlock<Mat>* mat, int index) noexcept
684 : m_mat{mat}, m_index{index} {}
685
686 constexpr const_iterator& operator++() noexcept {
687 ++m_index;
688 return *this;
689 }
690
691 constexpr const_iterator operator++(int) noexcept {
692 const_iterator retval = *this;
693 ++(*this);
694 return retval;
695 }
696
697 constexpr const_iterator& operator--() noexcept {
698 --m_index;
699 return *this;
700 }
701
702 constexpr const_iterator operator--(int) noexcept {
703 iterator retval = *this;
704 --(*this);
705 return retval;
706 }
707
708 constexpr bool operator==(const const_iterator&) const noexcept = default;
709
710 constexpr const_reference operator*() const noexcept {
711 return (*m_mat)[m_index];
712 }
713
714 private:
715 const VariableBlock<Mat>* m_mat = nullptr;
716 int m_index = 0;
717 };
718
719 using reverse_iterator = std::reverse_iterator<iterator>;
720 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
721
722#endif // DOXYGEN_SHOULD_SKIP_THIS
723
727 iterator begin() { return iterator(this, 0); }
728
732 iterator end() { return iterator(this, rows() * cols()); }
733
737 const_iterator begin() const { return const_iterator(this, 0); }
738
742 const_iterator end() const { return const_iterator(this, rows() * cols()); }
743
747 const_iterator cbegin() const { return const_iterator(this, 0); }
748
752 const_iterator cend() const { return const_iterator(this, rows() * cols()); }
753
757 reverse_iterator rbegin() { return reverse_iterator{end()}; }
758
762 reverse_iterator rend() { return reverse_iterator{begin()}; }
763
767 const_reverse_iterator rbegin() const {
768 return const_reverse_iterator{end()};
769 }
770
774 const_reverse_iterator rend() const {
775 return const_reverse_iterator{begin()};
776 }
777
781 const_reverse_iterator crbegin() const {
782 return const_reverse_iterator{cend()};
783 }
784
788 const_reverse_iterator crend() const {
789 return const_reverse_iterator{cbegin()};
790 }
791
795 size_t size() const { return rows() * cols(); }
796
797 private:
798 Mat* m_mat = nullptr;
799
800 Slice m_row_slice;
801 int m_row_slice_length = 0;
802
803 Slice m_col_slice;
804 int m_col_slice_length = 0;
805};
806
807} // 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:737
const_iterator end() const
Definition variable_block.hpp:742
void set_value(const Eigen::MatrixBase< Derived > &values)
Definition variable_block.hpp:179
const_iterator cbegin() const
Definition variable_block.hpp:747
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:727
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:757
VariableBlock< Mat > & operator=(Mat &&values)
Definition variable_block.hpp:208
const_iterator cend() const
Definition variable_block.hpp:752
const Variable< Scalar > & operator[](int row, int col) const
Definition variable_block.hpp:238
const_reverse_iterator crbegin() const
Definition variable_block.hpp:781
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:774
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:732
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:762
size_t size() const
Definition variable_block.hpp:795
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:788
const_reverse_iterator rbegin() const
Definition variable_block.hpp:767
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