batmat 0.0.13
Batched linear algebra routines
Loading...
Searching...
No Matches
view.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file
4/// Non-owning view of a batch of matrices.
5/// @ingroup topic-matrix
6
7#include <batmat/assume.hpp>
8#include <batmat/config.hpp>
10#include <guanaqo/mat-view.hpp>
11
12namespace batmat::matrix {
13
14/// Non-owning view of a batch of matrices.
15/// @tparam T
16/// Element value type (possibly const-qualified).
17/// @tparam I
18/// Index and size type. Usually `std::ptrdiff_t` or `int`.
19/// @tparam S
20/// Inner stride type (batch size). Usually `std::integral_constant<I, N>` for some `N`.
21/// @tparam D
22/// Batch depth type. Usually equal to @p S for a single batch, or @p I for a dynamic depth.
23/// @tparam L
24/// Layer stride type. Usually @ref DefaultStride (which implies that the layer stride is
25/// equal to `outer_stride() * outer_size()`), or @p I for a dynamic layer stride.
26/// Dynamic strides are used for subviews of views with a larger `outer_size()`.
27/// @tparam O
28/// Storage order (column or row major).
29/// @ingroup topic-matrix
30template <class T, class I = index_t, class S = std::integral_constant<I, 1>, class D = I,
31 class L = DefaultStride, StorageOrder O = StorageOrder::ColMajor>
32struct View {
34 using value_type = T;
43 static constexpr bool is_row_major = layout_type::is_row_major;
44
45 /// True if @ref batch_size() and @ref depth() are compile-time constants and are equal.
46 /// @note Views with dynamic batch size and depth may still have a single batch at runtime,
47 /// but this cannot be statically asserted.
48 static constexpr bool has_single_batch_at_compile_time = requires {
49 S::value;
50 D::value;
51 } && S{} == D{};
52 /// True if @ref depth() is a compile-time constant and is equal to one.
53 static constexpr bool has_single_layer_at_compile_time = requires { D::value; } && D{} == 1;
54 /// When extracing a single batch, the depth equals the batch size, and the layer stride is no
55 /// longer relevant.
57 /// When slicing along the outer dimension, the layer stride stays the same, but the outer size
58 /// may be smaller, which means that even if the original view has a default layer stride, the
59 /// sliced view may require a dynamic layer stride. For a single batch, the layer stride is not
60 /// relevant, so it is preserved.
62 std::conditional_t<has_single_batch_at_compile_time, View, View<T, I, S, D, I, O>>;
63 /// View with the correct layer stride when slicing along the column dimension.
64 /// For row-major storage, slicing along columns does not change the outer size, in which case
65 /// the layer stride is still correct. For column-major storage, slicing along columns does
66 /// change the outer size, in which case we need a dynamic layer stride.
67 using col_slice_view_type = std::conditional_t<is_row_major, View, general_slice_view_type>;
68 /// View with the correct layer stride when slicing along the row dimension.
69 /// @see @ref col_slice_view_type
70 using row_slice_view_type = std::conditional_t<is_column_major, View, general_slice_view_type>;
71
72 /// Pointer to the first element of the first layer.
74 /// Layout describing the dimensions and strides of the view.
76
77 /// POD helper struct to enable designated initializers during construction.
89
90 /// Create a new view.
91 /// @note It is recommended to use designated initializers for the arguments to avoid mistakes.
92 constexpr View(PlainBatchedMatrixView p = {})
93 : data_ptr{p.data}, layout{{.depth = p.depth,
94 .rows = p.rows,
95 .cols = p.cols,
96 .outer_stride = p.outer_stride,
97 .batch_size = p.batch_size,
98 .layer_stride = p.layer_stride}} {}
99 /// Create a new view with the given layout, using the given buffer.
100 constexpr View(std::span<T> data, layout_type layout) : data_ptr{data.data()}, layout{layout} {
101 BATMAT_ASSERT(data.size() == layout.padded_size());
102 }
103 /// Create a new view with the given layout, using the given buffer.
105
106 /// Copy a view. No data is copied.
107 View(const View &) = default;
108
109 /// Non-const views implicitly convert to const views.
110 operator const_view_type() const
111 requires(!std::is_const_v<T>)
112 {
113 return {data_ptr, layout};
114 }
115 /// Explicit conversion to a const view.
116 [[nodiscard]] const_view_type as_const() const { return *this; }
117
118 /// If we have a single layer at compile time, we can implicitly convert to a non-batched view.
124
125 /// Access a single layer @p l as a non-batched view.
126 /// @note The inner stride of the returned view is equal to the batch size of this view, so it
127 /// cannot be used directly with functions that require unit inner stride (e.g. BLAS).
130 return layout(data_ptr, l);
131 }
132
133 /// Access a single element at layer @p l, row @p r and column @p c.
134 [[nodiscard]] value_type &operator()(index_type l, index_type r, index_type c) const {
135 return layout(data_ptr, l, r, c);
136 }
137
138 /// @name Batch-wise slicing
139 /// @{
140
141 /// Access a batch of @ref batch_size() layers, starting at batch index @p b (i.e. starting at
142 /// layer `b * batch_size()`).
143 [[nodiscard]] batch_view_type batch(index_type b) const {
144 const auto layer = b * static_cast<index_t>(batch_size());
145 return {{.data = data() + layout.layer_index(layer),
146 .depth = batch_size(),
147 .rows = rows(),
148 .cols = cols(),
149 .outer_stride = outer_stride(),
150 .batch_size = batch_size()}};
151 }
152
153 /// Same as @ref batch(), but returns a view with a dynamic batch size. If the total depth is
154 /// not a multiple of the batch size, the last batch will have a smaller size.
156 const auto d = static_cast<I>(depth());
157 const auto layer = b * static_cast<index_t>(batch_size());
158 const auto last = b == d / batch_size();
159 return {{.data = data() + layout.layer_index(layer),
160 .depth = last ? d - layout.floor_depth() : batch_size(),
161 .rows = rows(),
162 .cols = cols(),
163 .outer_stride = outer_stride(),
164 .batch_size = batch_size(),
165 .layer_stride = layout.layer_stride}};
166 }
167
168 /// Get a view of the first @p n layers. Note that @p n can be a compile-time constant.
169 template <class N>
170 [[nodiscard]] View<T, I, S, N, L, O> first_layers(N n) const {
171 BATMAT_ASSERT(n <= depth());
172 return {{.data = data(),
173 .depth = n,
174 .rows = rows(),
175 .cols = cols(),
176 .outer_stride = outer_stride(),
177 .batch_size = batch_size(),
178 .layer_stride = layout.layer_stride}};
179 }
180
181 /// Get a view of @p n layers starting at layer @p l. Note that @p n can be a compile-time
182 /// constant.
183 /// @pre `l % batch_size() == 0` (i.e. the starting layer must be at the start of a batch).
184 template <class N>
185 [[nodiscard]] View<T, I, S, N, L, O> middle_layers(index_type l, N n) const {
186 BATMAT_ASSERT(l + n <= depth());
187 BATMAT_ASSERT(l % static_cast<I>(batch_size()) == 0);
188 return {{.data = data() + layout.layer_index(l),
189 .depth = n,
190 .rows = rows(),
191 .cols = cols(),
192 .outer_stride = outer_stride(),
193 .batch_size = batch_size(),
194 .layer_stride = layout.layer_stride}};
195 }
196
197 /// @}
198
199 /// @name Iterators and buffer access
200 /// @{
201
202 /// Get a pointer to the first element of the first layer.
203 T *data() const { return data_ptr; }
204
205 /// Iterator over all elements of a view.
207 using value_type = T;
208 using reference = T &;
211 T *end;
215
217 ++data;
218 if (data == next_jump && data != end) {
221 }
222 return *this;
223 }
225 linear_iterator t = *this;
226 ++*this;
227 return t;
228 }
229 reference operator*() const { return *data; }
230 bool operator==(std::default_sentinel_t) const { return data == end; }
231 };
232
233 /// Iterate linearly (in storage order) over all elements of the view.
234 /// @pre `has_full_outer_stride()` (i.e. no padding within layers).
235 /// @pre `has_full_layer_stride()` (i.e. no padding between batches).
236 [[nodiscard]] linear_iterator begin() const {
239 // Number of elements in each layer
240 const auto size = layout.rows * layout.cols;
241 // How many layers are in batches that are completely full?
242 const auto contig_layers = layout.floor_depth();
243 // How many layers in total?
244 const auto depth = static_cast<I>(layout.depth);
245 // Remaining layers have padding we should skip over (in the last batch)
246 const auto remaining_layers = depth - contig_layers;
247 // Index of the first padding element
248 const auto first_jump = contig_layers * size + remaining_layers;
249 // Index of last layer in our storage
250 const auto padded_end = layout.ceil_depth();
251 const auto padding_layers = padded_end - depth;
252 const auto end = padded_end * size - padding_layers;
253 const auto batch_size = static_cast<I>(layout.batch_size);
254 return {
255 .data = data(),
256 .end = data() + end,
257 .next_jump = remaining_layers ? data() + first_jump : nullptr,
258 .padding_size = batch_size - remaining_layers,
259 .batch_size = batch_size,
260 };
261 }
262 /// Sentinel for @ref begin().
263 [[nodiscard]] std::default_sentinel_t end() const { return {}; }
264
265 /// @name Dimensions and strides
266 /// @{
267
268 /// Total number of elements in the view (excluding padding).
269 [[nodiscard]] constexpr index_type size() const { return layout.size(); }
270 /// Total number of elements in the view (including all padding).
271 [[nodiscard]] constexpr index_type padded_size() const { return layout.padded_size(); }
272
273 /// Number of layers in the view (i.e. depth).
274 [[nodiscard, gnu::always_inline]] constexpr depth_type depth() const { return layout.depth; }
275 /// The depth rounded up to a multiple of the batch size.
276 [[nodiscard, gnu::always_inline]] constexpr index_type ceil_depth() const {
277 return layout.ceil_depth();
278 }
279 /// Number of batches in the view, i.e. `ceil_depth() / batch_size()`.
280 [[nodiscard, gnu::always_inline]] constexpr index_type num_batches() const {
281 return layout.num_batches();
282 }
283 /// Number of rows of the matrices.
284 [[nodiscard, gnu::always_inline]] constexpr index_type rows() const { return layout.rows; }
285 /// Number of columns of the matrices.
286 [[nodiscard, gnu::always_inline]] constexpr index_type cols() const { return layout.cols; }
287 /// Outer stride of the matrices (leading dimension in BLAS parlance). Should be multiplied by
288 /// the batch size to get the actual number of elements.
289 [[nodiscard, gnu::always_inline]] constexpr index_type outer_stride() const {
290 return layout.outer_stride;
291 }
292 /// The size of the outer dimension, i.e. the number of columns for column-major storage, or the
293 /// number of rows for row-major storage.
294 [[nodiscard, gnu::always_inline]] constexpr index_type outer_size() const {
295 return layout.outer_size();
296 }
297 /// The size of the inner dimension, i.e. the number of rows for column-major storage, or the
298 /// number of columns for row-major storage.
299 [[nodiscard, gnu::always_inline]] constexpr index_type inner_size() const {
300 return layout.inner_size();
301 }
302 /// The inner stride of the matrices. Should be multiplied by the batch size to get the actual
303 /// number of elements.
304 [[nodiscard, gnu::always_inline]] constexpr index_type inner_stride() const { return 1; }
305 /// The batch size, i.e. the number of layers in each batch. Equals the inner stride.
306 [[nodiscard, gnu::always_inline]] constexpr batch_size_type batch_size() const {
307 return layout.batch_size;
308 }
309 /// The layer stride, i.e. the distance between the first layer of one batch and the first layer
310 /// of the next batch. Should be multiplied by the batch size to get the actual number of
311 /// elements.
312 [[nodiscard, gnu::always_inline]] constexpr index_type layer_stride() const {
313 return layout.get_layer_stride();
314 }
315 /// Whether the `layer_stride() == outer_stride() * outer_size()`.
316 [[nodiscard, gnu::always_inline]] constexpr bool has_full_layer_stride() const {
317 return layout.has_full_layer_stride();
318 }
319 /// Whether the `outer_stride() == inner_stride() * inner_size()`.
320 [[nodiscard, gnu::always_inline]] constexpr bool has_full_outer_stride() const {
321 return layout.has_full_outer_stride();
322 }
323 /// Whether the `inner_stride() == 1`. Always true.
324 [[nodiscard, gnu::always_inline]] constexpr bool has_full_inner_stride() const {
325 return layout.has_full_inner_stride();
326 }
327
328 /// @}
329
330 private:
331 template <class V>
332 constexpr auto get_layer_stride_for() const {
333 if constexpr (std::is_same_v<typename V::layer_stride_type, layer_stride_type>)
334 return layout.layer_stride;
335 else
336 return layer_stride();
337 }
338
339 public:
340 /// @name Reshaping and slicing
341 /// @{
342
343 /// Reshape the view to the given dimensions. The total size should not change.
345 BATMAT_ASSERT(rows * cols == this->rows() * this->cols());
347 return general_slice_view_type{typename general_slice_view_type::PlainBatchedMatrixView{
348 .data = data(),
349 .depth = depth(),
350 .rows = rows,
351 .cols = cols,
352 .outer_stride = is_row_major ? cols : rows,
353 .batch_size = batch_size(),
354 .layer_stride = this->get_layer_stride_for<general_slice_view_type>()}};
355 }
356
357 /// Get a view of the first @p n rows.
358 [[nodiscard]] row_slice_view_type top_rows(index_type n) const {
359 BATMAT_ASSERT(0 <= n && n <= rows());
360 return row_slice_view_type{typename row_slice_view_type::PlainBatchedMatrixView{
361 .data = data(),
362 .depth = depth(),
363 .rows = n,
364 .cols = cols(),
365 .outer_stride = outer_stride(),
366 .batch_size = batch_size(),
367 .layer_stride = this->get_layer_stride_for<row_slice_view_type>()}};
368 }
369
370 /// Get a view of the first @p n columns.
371 [[nodiscard]] col_slice_view_type left_cols(index_type n) const {
372 BATMAT_ASSERT(0 <= n && n <= cols());
373 return col_slice_view_type{typename col_slice_view_type::PlainBatchedMatrixView{
374 .data = data(),
375 .depth = depth(),
376 .rows = rows(),
377 .cols = n,
378 .outer_stride = outer_stride(),
379 .batch_size = batch_size(),
380 .layer_stride = this->get_layer_stride_for<col_slice_view_type>()}};
381 }
382
383 /// Get a view of the last @p n rows.
385 BATMAT_ASSERT(0 <= n && n <= rows());
386 const auto bs = static_cast<I>(batch_size());
387 const auto offset = (is_row_major ? outer_stride() : 1) * bs * (rows() - n);
388 return row_slice_view_type{typename row_slice_view_type::PlainBatchedMatrixView{
389 .data = data() + offset,
390 .depth = depth(),
391 .rows = n,
392 .cols = cols(),
393 .outer_stride = outer_stride(),
394 .batch_size = batch_size(),
395 .layer_stride = this->get_layer_stride_for<row_slice_view_type>()}};
396 }
397
398 /// Get a view of the last @p n columns.
400 BATMAT_ASSERT(0 <= n && n <= cols());
401 const auto bs = static_cast<I>(batch_size());
402 const auto offset = (is_row_major ? 1 : outer_stride()) * bs * (cols() - n);
403 return col_slice_view_type{typename col_slice_view_type::PlainBatchedMatrixView{
404 .data = data() + offset,
405 .depth = depth(),
406 .rows = rows(),
407 .cols = n,
408 .outer_stride = outer_stride(),
409 .batch_size = batch_size(),
410 .layer_stride = this->get_layer_stride_for<col_slice_view_type>()}};
411 }
412
413 /// Get a view of @p n rows starting at row @p r.
415 return bottom_rows(rows() - r).top_rows(n);
416 }
417
418 /// Get a view of @p n columns starting at column @p c.
420 return right_cols(cols() - c).left_cols(n);
421 }
422
423 /// Get a view of the top-left @p nr by @p nc block of the matrices.
425 return top_rows(nr).left_cols(nc);
426 }
427
428 /// Get a view of the top-right @p nr by @p nc block of the matrices.
430 return top_rows(nr).right_cols(nc);
431 }
432
433 /// Get a view of the bottom-left @p nr by @p nc block of the matrices.
435 return bottom_rows(nr).left_cols(nc);
436 }
437
438 /// Get a view of the bottom-right @p nr by @p nc block of the matrices.
440 return bottom_rows(nr).right_cols(nc);
441 }
442
443 /// Get a view of the @p nr by @p nc block of the matrices starting at row @p r and column @p c.
445 index_type nc) const {
446 return middle_rows(r, nr).middle_cols(c, nc);
447 }
448
449 /// Get a view of the given span as a column vector.
450 [[nodiscard]] static View as_column(std::span<T> v) {
451 return {{.data = v.data(), .rows = static_cast<index_type>(v.size()), .cols = 1}};
452 }
453
454 /// Get a transposed view of the matrices. Note that the data itself is not modified, the
455 /// returned view simply accesses the same data with rows and column indices swapped.
456 [[nodiscard]] auto transposed() const {
457 using TpBm = View<T, I, S, D, L, transpose(O)>;
458 return TpBm{typename TpBm::PlainBatchedMatrixView{.data = data(),
459 .depth = depth(),
460 .rows = cols(),
461 .cols = rows(),
462 .outer_stride = outer_stride(),
463 .batch_size = batch_size(),
464 .layer_stride = layout.layer_stride}};
465 }
466
467 /// @}
468
469 /// @name Value manipulation
470 /// @{
471
473 const auto bs = static_cast<I>(batch_size());
474 const auto n = std::min(rows(), cols());
475 for (index_type b = 0; b < num_batches(); ++b) {
476 auto *p = batch(b).data();
477 for (index_type i = 0; i < n; ++i) {
478 for (index_type r = 0; r < bs; ++r)
479 *p++ += t;
480 p += bs * outer_stride();
481 }
482 }
483 }
484
486 const auto bs = static_cast<I>(batch_size());
487 for (index_type b = 0; b < num_batches(); ++b) {
488 auto *dst = this->batch(b).data();
489 for (index_type c = 0; c < this->outer_size(); ++c) {
490 auto *dst_ = dst;
491 const index_type n = inner_size() * bs;
492 for (index_type r = 0; r < n; ++r)
493 *dst_++ = t;
494 dst += bs * this->outer_stride();
495 }
496 }
497 }
498
499 void negate() {
500 const auto bs = static_cast<I>(batch_size());
501 for (index_type b = 0; b < num_batches(); ++b) {
502 auto *dst = this->batch(b).data();
503 for (index_type c = 0; c < this->outer_size(); ++c) {
504 auto *dst_ = dst;
505 const index_type n = inner_size() * bs;
506 for (index_type r = 0; r < n; ++r, ++dst_)
507 *dst_ = -*dst_;
508 dst += bs * this->outer_stride();
509 }
510 }
511 }
512
513 template <class Other>
514 void copy_values(const Other &other) const {
515 static_assert(is_row_major == Other::is_row_major);
516 assert(other.rows() == this->rows());
517 assert(other.cols() == this->cols());
518 assert(other.batch_size() == this->batch_size());
519 const auto bs = static_cast<I>(batch_size());
520 for (index_type b = 0; b < num_batches(); ++b) {
521 const auto *src = other.batch(b).data();
522 auto *dst = this->batch(b).data();
523 for (index_type c = 0; c < this->outer_size(); ++c) {
524 const auto *src_ = src;
525 auto *dst_ = dst;
526 const index_type n = inner_size() * bs;
527 for (index_type r = 0; r < n; ++r)
528 *dst_++ = *src_++;
529 src += bs * other.outer_stride();
530 dst += bs * this->outer_stride();
531 }
532 }
533 }
534
535 /// Copy assignment copies the values from another view with the same layout to this view.
536 View &operator=(const View &other) {
537 if (this != &other)
538 copy_values(other);
539 return *this;
540 }
541 /// Copy values from another view with a compatible value type and the same layout to this view.
542 template <class U, class J, class R, class E, class M>
543 requires(!std::is_const_v<T> && std::convertible_to<U, std::remove_cv_t<T>> &&
544 std::equality_comparable_with<I, J>)
545 View &operator=(View<U, J, R, E, M, O> other) {
546 copy_values(other);
547 return *this;
548 }
549 // TODO: abstract logic into generic function (and check performance)
550 template <class U, class J, class R, class E, class M>
551 requires(!std::is_const_v<T> && std::convertible_to<U, std::remove_cv_t<T>> &&
552 std::equality_comparable_with<I, J>)
553 View &operator+=(View<U, J, R, E, M, O> other) {
554 assert(other.rows() == this->rows());
555 assert(other.cols() == this->cols());
556 assert(other.batch_size() == this->batch_size());
557 const auto bs = static_cast<I>(batch_size());
558 for (index_type b = 0; b < num_batches(); ++b) {
559 const auto *src = other.batch(b).data();
560 auto *dst = this->batch(b).data();
561 for (index_type c = 0; c < this->outer_size(); ++c) {
562 const auto *src_ = src;
563 auto *dst_ = dst;
564 const index_type n = inner_size() * bs;
565 for (index_type r = 0; r < n; ++r)
566 *dst_++ += *src_++;
567 src += bs * other.outer_stride();
568 dst += bs * this->outer_stride();
569 }
570 }
571 return *this;
572 }
573
574 /// @}
575
576 /// Reassign the buffer and layout of this view to those of another view. No data is copied.
578 this->data_ptr = other.data_ptr;
579 this->layout = other.layout;
580 return *this;
581 }
582
583 /// Implicit conversion to a view with a dynamic depth.
585 requires(!std::same_as<integral_value_type_t<D>, D>)
586 {
587 const auto bs = static_cast<integral_value_type_t<D>>(batch_size());
588 return {{.data = data(),
589 .depth = depth(),
590 .rows = rows(),
591 .cols = cols(),
592 .outer_stride = outer_stride(),
593 .batch_size = bs,
594 .layer_stride = layout.layer_stride}};
595 }
596 /// Implicit conversion to a view with a dynamic depth, going from non-const to const.
598 requires(!std::is_const_v<T> && !std::same_as<integral_value_type_t<D>, D>)
599 {
600 const auto bs = static_cast<integral_value_type_t<D>>(batch_size());
601 return {{.data = data(),
602 .depth = depth(),
603 .rows = rows(),
604 .cols = cols(),
605 .outer_stride = outer_stride(),
606 .batch_size = bs,
607 .layer_stride = layout.layer_stride}};
608 }
609 /// Implicit conversion to a view with a dynamic layer stride.
610 operator View<T, I, S, D, I, O>() const
611 requires(!std::same_as<I, L>)
612 {
613 return {{.data = data(),
614 .depth = depth(),
615 .rows = rows(),
616 .cols = cols(),
617 .outer_stride = outer_stride(),
618 .batch_size = batch_size(),
619 .layer_stride = layer_stride()}};
620 }
621 /// Implicit conversion to a view with a dynamic layer stride, going from non-const to const.
623 requires(!std::is_const_v<T> && !std::same_as<I, L>)
624 {
625 return {{.data = data(),
626 .depth = depth(),
627 .rows = rows(),
628 .cols = cols(),
629 .outer_stride = outer_stride(),
630 .batch_size = batch_size(),
631 .layer_stride = layer_stride()}};
632 }
633};
634
635template <class T, class I, class S, class D, class L, StorageOrder P>
636bool operator==(std::default_sentinel_t s, typename View<T, I, S, D, L, P>::linear_iterator i) {
637 return i == s;
638}
639template <class T, class I, class S, class D, class L, StorageOrder P>
640bool operator!=(std::default_sentinel_t s, typename View<T, I, S, D, L, P>::linear_iterator i) {
641 return !(i == s);
642}
643template <class T, class I, class S, class D, class L, StorageOrder P>
644bool operator!=(typename View<T, I, S, D, L, P>::linear_iterator i, std::default_sentinel_t s) {
645 return !(i == s);
646}
647
648// TODO: tag-invoke style CPOs instead of free functions with ADL?
649
650template <class T, class I, class S, class D, class L, StorageOrder O>
651constexpr auto data(const View<T, I, S, D, L, O> &v) {
652 return v.data();
653}
654template <class T, class I, class S, class D, class L, StorageOrder O>
655constexpr auto rows(const View<T, I, S, D, L, O> &v) {
656 return v.rows();
657}
658template <class T, class I, class S, class D, class L, StorageOrder O>
659constexpr auto cols(const View<T, I, S, D, L, O> &v) {
660 return v.cols();
661}
662template <class T, class I, class S, class D, class L, StorageOrder O>
663constexpr auto outer_stride(const View<T, I, S, D, L, O> &v) {
664 return v.outer_stride();
665}
666template <class T, class I, class S, class D, class L, StorageOrder O>
667constexpr auto depth(const View<T, I, S, D, L, O> &v) {
668 return v.depth();
669}
670
671} // namespace batmat::matrix
#define BATMAT_ASSERT(x)
Definition assume.hpp:14
Layout description for a batch of matrices, independent of any storage.
constexpr auto cols(const Matrix< T, I, S, D, O, A > &v)
Definition matrix.hpp:247
typename integral_value_type< T >::type integral_value_type_t
Definition layout.hpp:24
constexpr auto data(Matrix< T, I, S, D, O, A > &v)
Definition matrix.hpp:233
constexpr auto outer_stride(const Matrix< T, I, S, D, O, A > &v)
Definition matrix.hpp:251
bool operator!=(std::default_sentinel_t s, typename View< T, I, S, D, L, P >::linear_iterator i)
Definition view.hpp:640
constexpr auto rows(const Matrix< T, I, S, D, O, A > &v)
Definition matrix.hpp:243
bool operator==(std::default_sentinel_t s, typename View< T, I, S, D, L, P >::linear_iterator i)
Definition view.hpp:636
constexpr auto depth(const Matrix< T, I, S, D, O, A > &v)
Definition matrix.hpp:255
Shape and strides describing a batch of matrices, independent of any storage.
Definition layout.hpp:45
static constexpr bool is_column_major
Definition layout.hpp:53
static constexpr bool is_row_major
Definition layout.hpp:54
static constexpr StorageOrder storage_order
Definition layout.hpp:52
std::conditional_t< requires { S::value; }, std::integral_constant< index_t, S::value >, index_t > standard_stride_type
Definition layout.hpp:56
Iterator over all elements of a view.
Definition view.hpp:206
bool operator==(std::default_sentinel_t) const
Definition view.hpp:230
linear_iterator operator++(int)
Definition view.hpp:224
linear_iterator & operator++()
Definition view.hpp:216
Non-owning view of a batch of matrices.
Definition view.hpp:32
constexpr View(PlainBatchedMatrixView p={})
Create a new view.
Definition view.hpp:92
Layout< index_t, stride, stride, layer_stride, O > layout_type
Definition view.hpp:33
View< T, I, S, N, L, O > first_layers(N n) const
Get a view of the first n layers. Note that n can be a compile-time constant.
Definition view.hpp:170
typename layout_type::layer_stride_type layer_stride_type
Definition view.hpp:38
guanaqo::MatrixView< S, index_t, standard_stride_type, O > operator()(index_type l) const
Definition view.hpp:129
general_slice_view_type bottom_right(index_type nr, index_type nc) const
Get a view of the bottom-right nr by nc block of the matrices.
Definition view.hpp:439
typename layout_type::batch_size_type batch_size_type
Definition view.hpp:36
typename layout_type::standard_stride_type standard_stride_type
Definition view.hpp:39
View< T, index_t, stride, stride, DefaultStride, O > batch_view_type
Definition view.hpp:56
general_slice_view_type block(index_type r, index_type c, index_type nr, index_type nc) const
Get a view of the nr by nc block of the matrices starting at row r and column c.
Definition view.hpp:444
void set_constant(value_type t)
Definition view.hpp:485
value_type & operator()(index_type l, index_type r, index_type c) const
Access a single element at layer l, row r and column c.
Definition view.hpp:134
auto transposed() const
Get a transposed view of the matrices.
Definition view.hpp:456
constexpr index_type num_batches() const
Number of batches in the view, i.e. ceil_depth() / batch_size().
Definition view.hpp:280
constexpr View(value_type *data, layout_type layout)
Create a new view with the given layout, using the given buffer.
Definition view.hpp:104
col_slice_view_type middle_cols(index_type c, index_type n) const
Get a view of n columns starting at column c.
Definition view.hpp:419
constexpr index_type padded_size() const
Total number of elements in the view (including all padding).
Definition view.hpp:271
void add_to_diagonal(const value_type &t)
Definition view.hpp:472
linear_iterator begin() const
Iterate linearly (in storage order) over all elements of the view.
Definition view.hpp:236
constexpr auto get_layer_stride_for() const
Definition view.hpp:332
row_slice_view_type bottom_rows(index_type n) const
Get a view of the last n rows.
Definition view.hpp:384
general_slice_view_type reshaped(index_type rows, index_type cols) const
Reshape the view to the given dimensions. The total size should not change.
Definition view.hpp:344
View< T, I, S, N, L, O > middle_layers(index_type l, N n) const
Get a view of n layers starting at layer l.
Definition view.hpp:185
View(const View &)=default
Copy a view. No data is copied.
general_slice_view_type bottom_left(index_type nr, index_type nc) const
Get a view of the bottom-left nr by nc block of the matrices.
Definition view.hpp:434
View< const T, index_t, stride, stride, layer_stride, O > const_view_type
Definition view.hpp:40
row_slice_view_type middle_rows(index_type r, index_type n) const
Get a view of n rows starting at row r.
Definition view.hpp:414
constexpr index_type cols() const
Number of columns of the matrices.
Definition view.hpp:286
col_slice_view_type right_cols(index_type n) const
Get a view of the last n columns.
Definition view.hpp:399
View< T, I, S, I, L, O > batch_dyn(index_type b) const
Same as batch(), but returns a view with a dynamic batch size.
Definition view.hpp:155
constexpr bool has_full_inner_stride() const
Whether the inner_stride() == 1. Always true.
Definition view.hpp:324
col_slice_view_type left_cols(index_type n) const
Get a view of the first n columns.
Definition view.hpp:371
static View as_column(std::span< T > v)
Get a view of the given span as a column vector.
Definition view.hpp:450
row_slice_view_type top_rows(index_type n) const
Get a view of the first n rows.
Definition view.hpp:358
constexpr index_type inner_stride() const
The inner stride of the matrices.
Definition view.hpp:304
constexpr index_type rows() const
Number of rows of the matrices.
Definition view.hpp:284
constexpr index_type inner_size() const
The size of the inner dimension, i.e.
Definition view.hpp:299
constexpr index_type ceil_depth() const
The depth rounded up to a multiple of the batch size.
Definition view.hpp:276
View & operator=(const View &other)
Copy assignment copies the values from another view with the same layout to this view.
Definition view.hpp:536
std::conditional_t< has_single_batch_at_compile_time, View, View< T, index_t, stride, stride, index_t, O > > general_slice_view_type
Definition view.hpp:61
std::conditional_t< is_column_major, View, general_slice_view_type > row_slice_view_type
Definition view.hpp:70
constexpr View(std::span< T > data, layout_type layout)
Create a new view with the given layout, using the given buffer.
Definition view.hpp:100
general_slice_view_type top_left(index_type nr, index_type nc) const
Get a view of the top-left nr by nc block of the matrices.
Definition view.hpp:424
constexpr index_type outer_size() const
The size of the outer dimension, i.e.
Definition view.hpp:294
constexpr index_type layer_stride() const
The layer stride, i.e.
Definition view.hpp:312
const_view_type as_const() const
Explicit conversion to a const view.
Definition view.hpp:116
general_slice_view_type top_right(index_type nr, index_type nc) const
Get a view of the top-right nr by nc block of the matrices.
Definition view.hpp:429
std::conditional_t< is_row_major, View, general_slice_view_type > col_slice_view_type
Definition view.hpp:67
void copy_values(const Other &other) const
Definition view.hpp:514
View & reassign(View other)
Reassign the buffer and layout of this view to those of another view. No data is copied.
Definition view.hpp:577
constexpr index_type outer_stride() const
Outer stride of the matrices (leading dimension in BLAS parlance).
Definition view.hpp:289
batch_view_type batch(index_type b) const
Access a batch of batch_size() layers, starting at batch index b (i.e.
Definition view.hpp:143
POD helper struct to enable designated initializers during construction.
Definition view.hpp:78