Expression Templates Library (ETL)
dyn.hpp
Go to the documentation of this file.
1 //=======================================================================
2 // Copyright (c) 2014-2023 Baptiste Wicht
3 // Distributed under the terms of the MIT License.
4 // (See accompanying file LICENSE or copy at
5 // http://opensource.org/licenses/MIT)
6 //=======================================================================
7 
13 #pragma once
14 
15 #include "etl/dyn_base.hpp" //The base class and utilities
16 #include "etl/direct_fill.hpp" //direct_fill with GPU support
17 
18 namespace etl {
19 
25 template <typename T, order SO, size_t D>
26 struct dyn_matrix_impl final : dense_dyn_base<dyn_matrix_impl<T, SO, D>, T, SO, D>,
27  inplace_assignable<dyn_matrix_impl<T, SO, D>>,
28  expression_able<dyn_matrix_impl<T, SO, D>>,
29  value_testable<dyn_matrix_impl<T, SO, D>>,
30  iterable<dyn_matrix_impl<T, SO, D>, SO == order::RowMajor>,
31  dim_testable<dyn_matrix_impl<T, SO, D>> {
32  static constexpr size_t n_dimensions = D;
33  static constexpr order storage_order = SO;
35 
39  using value_type = T;
40  using dimension_storage_impl = std::array<size_t, n_dimensions>;
42  using const_memory_type = const value_type*;
43 
44  using iterator = std::conditional_t<SO == order::RowMajor, value_type*, etl::iterator<this_type>>;
45  using const_iterator = std::conditional_t<SO == order::RowMajor, const value_type*, etl::iterator<const this_type>>;
46 
50  template <typename V = default_vec>
51  using vec_type = typename V::template vec_type<T>;
52 
53 private:
54  using base_type::_dimensions;
55  using base_type::_memory;
56  using base_type::_size;
57 
58  using base_type::allocate;
59  using base_type::check_invariants;
60  using base_type::release;
61 
62 public:
63  using base_type::dim;
64  using base_type::memory_end;
65  using base_type::memory_start;
68 
69  // Construction
70 
77  dyn_matrix_impl() noexcept : base_type() {
78  //Nothing else to init
79  }
80 
85  dyn_matrix_impl(const dyn_matrix_impl& rhs) noexcept(assert_nothrow) : base_type(rhs) {
86  if (_size) {
87  _memory = allocate(alloc_size_mat<T>(_size, dim(n_dimensions - 1)));
88  } else {
89  _memory = nullptr;
90  }
91 
92  if (rhs.is_cpu_up_to_date()) {
93  direct_copy(rhs.memory_start(), rhs.memory_end(), memory_start());
94  }
95 
96  cpp_assert(rhs.is_cpu_up_to_date() == this->is_cpu_up_to_date(), "dyn_matrix_impl(&) must preserve CPU status");
97  cpp_assert(rhs.is_gpu_up_to_date() == this->is_gpu_up_to_date(), "dyn_matrix_impl(&) must preserve GPU status");
98  }
99 
104  dyn_matrix_impl(dyn_matrix_impl&& rhs) noexcept : base_type(std::move(rhs)) {
105  _memory = rhs._memory;
106 
107  rhs._size = 0;
108  rhs._memory = nullptr;
109  }
110 
115  dyn_matrix_impl(std::initializer_list<value_type> list) noexcept requires(n_dimensions == 1) : base_type(list.size(), {{list.size()}}) {
116  _memory = allocate(alloc_size_mat<T>(_size, dim(n_dimensions - 1)));
117 
118  std::copy(list.begin(), list.end(), begin());
119  }
120 
128  template <size_c... S>
129  explicit dyn_matrix_impl(S... sizes) noexcept requires(sizeof...(S) == D) : base_type(util::size(sizes...), {{static_cast<size_t>(sizes)...}}) {
130  _memory = allocate(alloc_size_mat<T>(_size, dim(n_dimensions - 1)));
131  }
132 
137  template <typename... S>
138  explicit dyn_matrix_impl(S... sizes) noexcept requires(dyn_detail::is_initializer_list_constructor<S...>::value && sizeof...(S) == D + 1)
139  : base_type(util::size(std::make_index_sequence<(sizeof...(S) - 1)>(), sizes...),
140  dyn_detail::sizes(std::make_index_sequence<(sizeof...(S) - 1)>(), sizes...)) {
141  _memory = allocate(alloc_size_mat<T>(_size, dim(n_dimensions - 1)));
142 
143  static_assert(sizeof...(S) == D + 1, "Invalid number of dimensions");
144 
145  auto list = cpp::last_value(sizes...);
146  std::copy(list.begin(), list.end(), begin());
147  }
148 
153  template <typename... S>
154  explicit dyn_matrix_impl(size_t s1, S... sizes) noexcept requires((sizeof...(S) == D) && cpp::specialization_of<values_t, typename cpp::last_type<size_t, S...>::type>)
155  : base_type(util::size(std::make_index_sequence<(sizeof...(S))>(), s1, sizes...),
156  dyn_detail::sizes(std::make_index_sequence<(sizeof...(S))>(), s1, sizes...)) {
157  _memory = allocate(alloc_size_mat<T>(_size, dim(n_dimensions - 1)));
158 
159  auto list = cpp::last_value(sizes...).template list<value_type>();
160  std::copy(list.begin(), list.end(), begin());
161  }
162 
169  template <typename... S>
170  explicit dyn_matrix_impl(size_t s1, S... sizes) noexcept requires((sizeof...(S) == D) && !cpp::specialization_of<values_t, typename cpp::last_type<size_t, S...>::type>)
171  : base_type(util::size(std::make_index_sequence<(sizeof...(S))>(), s1, sizes...),
172  dyn_detail::sizes(std::make_index_sequence<(sizeof...(S))>(), s1, sizes...)) {
173  _memory = allocate(alloc_size_mat<T>(_size, dim(n_dimensions - 1)));
174 
175  decltype(auto) value = cpp::last_value(s1, sizes...);
176  std::fill(begin(), end(), value);
177  }
178 
185  template <std_container Container>
186  explicit dyn_matrix_impl(const Container& container) requires(D == 1 && std::convertible_to<typename Container::value_type, value_type>) :
187  base_type(container.size(), {{container.size()}}) {
188  _memory = allocate(alloc_size_mat<T>(_size, dim(n_dimensions - 1)));
189 
190  // Copy the container directly inside the allocated memory
191  std::copy_n(container.begin(), _size, _memory);
192  }
193 
202  dyn_matrix_impl& operator=(const dyn_matrix_impl& rhs) noexcept(assert_nothrow) {
203  if (this != &rhs) {
204  if (!_size) {
205  cpp_assert(!_memory, "_size and _memory are not properly synced");
206 
207  _size = rhs._size;
208  _dimensions = rhs._dimensions;
209 
210  if (_size) {
211  _memory = allocate(alloc_size_mat<T>(_size, dim(n_dimensions - 1)));
212  } else {
213  _memory = nullptr;
214  }
215  } else {
216  validate_assign(*this, rhs);
217  }
218 
219  // TODO Find a better solution
220  const_cast<dyn_matrix_impl&>(rhs).assign_to(*this);
221  }
222 
223  check_invariants();
224 
225  cpp_assert(rhs.is_cpu_up_to_date() == this->is_cpu_up_to_date(), "dyn_matrix_impl::operator= must preserve CPU status");
226  cpp_assert(rhs.is_gpu_up_to_date() == this->is_gpu_up_to_date(), "dyn_matrix_impl::operator= must preserve GPU status");
227 
228  return *this;
229  }
230 
239  dyn_matrix_impl& operator=(dyn_matrix_impl&& rhs) noexcept {
240  if (this != &rhs) {
241  if (_memory) {
242  release(_memory, alloc_size_mat<T>(_size, dim(n_dimensions - 1)));
243  }
244 
245  _size = rhs._size;
246  _dimensions = std::move(rhs._dimensions);
247  _memory = rhs._memory;
248 
249  rhs._size = 0;
250  rhs._memory = nullptr;
251  }
252 
253  check_invariants();
254 
255  return *this;
256  }
257 
262  void resize_arr(const dimension_storage_impl& dimensions) {
263  auto new_size = std::accumulate(dimensions.begin(), dimensions.end(), size_t(1), std::multiplies<size_t>());
264 
265  if (_memory) {
266  auto new_memory = allocate(alloc_size_mat<T>(new_size, (dimensions.back())));
267 
268  for (size_t i = 0; i < std::min(_size, new_size); ++i) {
269  new_memory[i] = _memory[i];
270  }
271 
272  release(_memory, alloc_size_mat<T>(_size, dim(n_dimensions - 1)));
273 
274  _memory = new_memory;
275  } else {
276  _memory = allocate(alloc_size_mat<T>(new_size, (dimensions.back())));
277  }
278 
279  _size = new_size;
280  _dimensions = dimensions;
281  }
282 
287  template <typename... Sizes>
288  void resize(Sizes... sizes) requires(sizeof...(Sizes) == n_dimensions) {
289  static_assert(sizeof...(Sizes), "Cannot change number of dimensions");
290 
291  auto new_size = util::size(sizes...);
292 
293  if (_memory) {
294  auto new_memory = allocate(alloc_size_mat<T>(new_size, cpp::last_value(sizes...)));
295 
296  for (size_t i = 0; i < std::min(_size, new_size); ++i) {
297  new_memory[i] = _memory[i];
298  }
299 
300  release(_memory, alloc_size_mat<T>(_size, dim(n_dimensions - 1)));
301 
302  _memory = new_memory;
303  } else {
304  _memory = allocate(alloc_size_mat<T>(new_size, cpp::last_value(sizes...)));
305  }
306 
307  _size = new_size;
308  _dimensions = dyn_detail::sizes(std::make_index_sequence<D>(), sizes...);
309  }
310 
316  template <etl_expr E>
317  dyn_matrix_impl& operator=(E&& e) noexcept requires(!std::is_same_v<std::decay_t<E>, dyn_matrix_impl<T, SO, D>> && std::convertible_to<value_t<E>, value_type>) {
318  // It is possible that the matrix was not initialized before
319  // In the case, get the the dimensions from the expression and
320  // initialize the matrix
321  if (!_memory) {
322  inherit(e);
323  } else {
324  validate_assign(*this, e);
325  }
326 
327  // Avoid aliasing issues
328  if constexpr (!decay_traits<E>::is_linear) {
329  if (e.alias(*this)) {
330  // Create a temporary to hold the result
331  this_type tmp;
332 
333  // Get the proper size
334  tmp.inherit(e);
335 
336  // Assign the expression to the temporary
337  e.assign_to(tmp);
338 
339  // Assign the temporary to this matrix
340  *this = tmp;
341  } else {
342  e.assign_to(*this);
343  }
344  } else {
345  // Direct assignment of the expression into this matrix
346  e.assign_to(*this);
347  }
348 
349  check_invariants();
350 
351  return *this;
352  }
353 
359  template <std_container Container>
360  dyn_matrix_impl& operator=(const Container& vec) requires(std::convertible_to<typename Container::value_type, value_type>) {
361  // Inherit from the dimensions if possible
362  if (!_memory && D == 1) {
363  // Compute the size and new dimensions
364  _size = vec.size();
365  _dimensions[0] = vec.size();
366 
367  // Allocate the new memory
368  _memory = allocate(alloc_size_mat<T>(_size, dim(0)));
369  } else {
370  validate_assign(*this, vec);
371  }
372 
373  std::copy(vec.begin(), vec.end(), begin());
374 
375  this->validate_cpu();
376  this->invalidate_gpu();
377 
378  check_invariants();
379 
380  return *this;
381  }
382 
388  dyn_matrix_impl& operator=(const value_type& value) noexcept {
389  direct_fill(*this, value);
390 
391  check_invariants();
392 
393  return *this;
394  }
395 
399  ~dyn_matrix_impl() noexcept {
400  if (_memory) {
401  release(_memory, alloc_size_mat<T>(_size, dim(n_dimensions - 1)));
402  }
403  }
404 
410  void clear() {
411  if (_memory) {
412  release(_memory, alloc_size_mat<T>(_size, dim(n_dimensions - 1)));
413  }
414 
415  _memory = nullptr;
416  _size = 0;
417  }
418 
423  template <typename Y>
424  auto& gpu_compute_hint([[maybe_unused]] Y& y) {
425  this->ensure_gpu_up_to_date();
426  return *this;
427  }
428 
433  template <typename Y>
434  const auto& gpu_compute_hint([[maybe_unused]] Y& y) const {
435  this->ensure_gpu_up_to_date();
436  return *this;
437  }
438 
443  void swap(dyn_matrix_impl& other) {
444  using std::swap;
445  swap(_size, other._size);
446  swap(_dimensions, other._dimensions);
447  swap(_memory, other._memory);
448 
449  //TODO swap is likely screwing up GPU memory!
450 
451  check_invariants();
452  }
453 
460  template <typename V = default_vec>
461  ETL_STRONG_INLINE(void)
462  store(const vec_type<V> in, size_t i) noexcept {
463  V::store(_memory + i, in);
464  }
465 
472  template <typename V = default_vec>
473  ETL_STRONG_INLINE(void)
474  storeu(const vec_type<V> in, size_t i) noexcept {
475  V::storeu(_memory + i, in);
476  }
477 
484  template <typename V = default_vec>
485  ETL_STRONG_INLINE(void)
486  stream(const vec_type<V> in, size_t i) noexcept {
487  V::stream(_memory + i, in);
488  }
489 
496  template <typename V = default_vec>
497  ETL_STRONG_INLINE(vec_type<V>)
498  load(size_t i) const noexcept {
499  return V::load(_memory + i);
500  }
501 
508  template <typename V = default_vec>
509  ETL_STRONG_INLINE(vec_type<V>)
510  loadu(size_t i) const noexcept {
511  return V::loadu(_memory + i);
512  }
513 
521  size_t& unsafe_dimension_access(size_t i) {
522  cpp_assert(i < n_dimensions, "Out of bounds");
523  return _dimensions[i];
524  }
525 
531  template <exact_dimensions<D> E>
532  void inherit_if_null(const E& e) {
533  if (!_memory) {
534  inherit(e);
535  }
536  }
537 
538  // Assignment functions
539 
544  template <typename L>
545  void assign_to(L&& lhs) const {
546  std_assign_evaluate(*this, std::forward<L>(lhs));
547  }
548 
553  template <typename L>
554  void assign_add_to(L&& lhs) const {
555  std_add_evaluate(*this, std::forward<L>(lhs));
556  }
557 
562  template <typename L>
563  void assign_sub_to(L&& lhs) const {
564  std_sub_evaluate(*this, std::forward<L>(lhs));
565  }
566 
571  template <typename L>
572  void assign_mul_to(L&& lhs) const {
573  std_mul_evaluate(*this, std::forward<L>(lhs));
574  }
575 
580  template <typename L>
581  void assign_div_to(L&& lhs) const {
582  std_div_evaluate(*this, std::forward<L>(lhs));
583  }
584 
589  template <typename L>
590  void assign_mod_to(L&& lhs) const {
591  std_mod_evaluate(*this, std::forward<L>(lhs));
592  }
593 
594  // Internals
595 
600  void visit([[maybe_unused]] const detail::evaluator_visitor& visitor) const {}
601 
602 private:
608  template <typename E>
609  void inherit([[maybe_unused]] const E& e) {
610  if constexpr (etl::decay_traits<E>::is_generator) {
611  cpp_unreachable("Impossible to inherit dimensions from generators");
612  } else {
613  cpp_assert(n_dimensions == etl::dimensions(e), "Invalid number of dimensions");
614 
615  // Compute the size and new dimensions
616  _size = 1;
617  for (size_t d = 0; d < n_dimensions; ++d) {
618  _dimensions[d] = etl::dim(e, d);
619  _size *= _dimensions[d];
620  }
621 
622  // Allocate the new memory
623  _memory = allocate(alloc_size_mat<T>(_size, dim(n_dimensions - 1)));
624  }
625  }
626 
633  friend std::ostream& operator<<(std::ostream& os, const dyn_matrix_impl& mat) {
634  if (D == 1) {
635  return os << "V[" << mat.size() << "]";
636  }
637 
638  os << "M[" << mat.dim(0);
639 
640  for (size_t i = 1; i < D; ++i) {
641  os << "," << mat.dim(i);
642  }
643 
644  return os << "]";
645  }
646 };
647 
648 #ifndef CPP_UTILS_ASSERT_EXCEPTION
649 static_assert(std::is_nothrow_default_constructible_v<dyn_vector<double>>, "dyn_vector should be nothrow default constructible");
650 static_assert(std::is_nothrow_copy_constructible_v<dyn_vector<double>>, "dyn_vector should be nothrow copy constructible");
651 static_assert(std::is_nothrow_move_constructible_v<dyn_vector<double>>, "dyn_vector should be nothrow move constructible");
652 static_assert(std::is_nothrow_copy_assignable_v<dyn_vector<double>>, "dyn_vector should be nothrow copy assignable");
653 static_assert(std::is_nothrow_move_assignable_v<dyn_vector<double>>, "dyn_vector should be nothrow move assignable");
654 static_assert(std::is_nothrow_destructible_v<dyn_vector<double>>, "dyn_vector should be nothrow destructible");
655 #endif
656 
667 template <typename T, typename... Sizes>
668 etl::dyn_matrix<T, sizeof...(Sizes)> make_dyn_matrix(Sizes... sizes) {
669  return etl::dyn_matrix<T, sizeof...(Sizes)>(sizes...);
670 }
671 
677 template <typename T, order SO, size_t D>
679  lhs.swap(rhs);
680 }
681 
687 template <typename Stream, typename T, order SO, size_t D>
689  for (size_t i = 0; i < etl::dimensions(matrix); ++i) {
690  os << matrix.dim(i);
691  }
692 
693  for (const auto& value : matrix) {
694  os << value;
695  }
696 }
697 
703 template <typename Stream, typename T, order SO, size_t D>
705  typename std::decay_t<decltype(matrix)>::dimension_storage_impl new_dimensions;
706 
707  for (auto& value : new_dimensions) {
708  is >> value;
709  }
710 
711  matrix.resize_arr(new_dimensions);
712 
713  for (auto& value : matrix) {
714  is >> value;
715  }
716 }
717 
718 } //end of namespace etl
Simple collection of values to initialize a dyn matrix.
Definition: dyn_base.hpp:36
A deserializer for ETL expressions.
Definition: deserializer.hpp:16
CRTP class to inject iterators functions.
Definition: iterable.hpp:23
void swap(dyn_matrix_impl< T, SO, D > &lhs, dyn_matrix_impl< T, SO, D > &rhs)
Swap two dyn matrix.
Definition: dyn.hpp:678
void assign_add_to(L &&lhs) const
Add to the given left-hand-side expression.
Definition: dyn_matrix_view.hpp:217
static constexpr size_t alignment
The memory alignment.
Definition: dyn.hpp:34
Dense Matrix with run-time fixed dimensions. The matrix support an arbitrary number of dimensions...
Definition: dyn_base.hpp:294
void std_assign_evaluate(Expr &&expr, Result &&result)
Evaluation of the expr into result.
Definition: evaluator.hpp:1176
void assign_div_to(L &&lhs) const
Divide the given left-hand-side expression.
Definition: dyn_matrix_view.hpp:244
void assign_mul_to(L &&lhs) const
Multiply the given left-hand-side expression.
Definition: dyn_matrix_view.hpp:235
static constexpr order storage_order
The storage order.
Definition: dyn.hpp:33
std::conditional_t< SO==order::RowMajor, value_type *, etl::iterator< this_type > > iterator
The iterator type.
Definition: dyn.hpp:44
dyn_matrix_impl() noexcept
Construct an empty matrix.
Definition: dyn.hpp:77
void assign_to(L &&lhs) const
Assign to the given left-hand-side expression.
Definition: dyn_matrix_view.hpp:208
D D
The number of dimensions.
Definition: dyn_matrix_view.hpp:24
Standard memory utilities.
Define traits to get vectorization information for types when no vector mode is available.
Definition: no_vectorization.hpp:16
order
Storage order of a matrix.
Definition: order.hpp:15
dyn_matrix_impl(const dyn_matrix_impl &rhs) noexcept(assert_nothrow)
Copy construct a matrix.
Definition: dyn.hpp:85
void direct_copy(const S *first, const S *last, T *target)
Performs a direct memory copy.
Definition: memory.hpp:24
constexpr size_t dimensions() noexcept
Return the number of dimensions of the given ETL type.
Definition: helpers.hpp:28
void serialize(serializer< Stream > &os, const dyn_matrix_impl< T, SO, D > &matrix)
Serialize the given matrix using the given serializer.
Definition: dyn.hpp:688
bool is_cpu_up_to_date() const noexcept
Indicates if the CPU memory is up to date.
Definition: sub_view.hpp:777
CRTP class to inject functions testing values of the expressions.
Definition: value_testable.hpp:26
auto end() noexcept
Return an iterator to the past-the-end element of the matrix.
Definition: iterable.hpp:59
A serializer for ETL expressions.
Definition: serializer.hpp:16
auto load(size_t x) const noexcept
Load several elements of the expression at once.
Definition: dyn_matrix_view.hpp:143
Traits to get information about ETL types.
Definition: tmp.hpp:68
Root namespace for the ETL library.
Definition: adapter.hpp:15
value_type * memory_type
The memory type.
Definition: dyn.hpp:41
void invalidate_gpu() const noexcept
Invalidates the GPU memory.
Definition: sub_view.hpp:695
auto dim(E &&value, size_t i) -> detail::identity_helper< E, dim_view< detail::build_identity_type< E >, D >>
Return a view representing the ith Dth dimension.
Definition: view_expression_builder.hpp:25
CRTP class to inject functions creating new expressions.
Definition: expression_able.hpp:23
void store(vec_type< V > in, size_t i) noexcept
Store several elements in the matrix at once.
Definition: dyn_matrix_view.hpp:176
void stream(vec_type< V > in, size_t i) noexcept
Store several elements in the matrix at once, using non-temporal store.
Definition: dyn_matrix_view.hpp:165
std::ostream & operator<<(std::ostream &os, const etl::complex< T > &c)
Outputs a textual representation of the complex number in the given stream.
Definition: complex.hpp:576
etl::dyn_matrix< T, sizeof...(Sizes)> make_dyn_matrix(Sizes... sizes)
Helper to create a dyn matrix using the dimensions.
Definition: dyn.hpp:668
void deserialize(deserializer< Stream > &is, dyn_matrix_impl< T, SO, D > &matrix)
Deserialize the given matrix using the given serializer.
Definition: dyn.hpp:704
Visitor to perform local evaluation when necessary.
Definition: eval_visitors.hpp:23
T value_type
The value type.
Definition: dyn.hpp:39
void storeu(vec_type< V > in, size_t i) noexcept
Store several elements in the matrix at once.
Definition: dyn_matrix_view.hpp:187
CRTP class to inject inplace operations to matrix and vector structures.
Definition: inplace_assignable.hpp:26
void std_mod_evaluate(Expr &&expr, Result &&result)
Compound modulo evaluation of the expr into result.
Definition: evaluator.hpp:1271
auto begin() noexcept
Return an iterator to the first element of the matrix.
Definition: iterable.hpp:46
Matrix with run-time fixed dimensions.
Definition: dyn.hpp:26
void direct_fill(E &&mat, V value)
Fill the given ETL value class with the given value.
Definition: direct_fill.hpp:25
void std_mul_evaluate(Expr &&expr, Result &&result)
Compound multiply evaluation of the expr into result.
Definition: evaluator.hpp:1233
void swap(custom_dyn_matrix_impl< T, SO, D > &lhs, custom_dyn_matrix_impl< T, SO, D > &rhs)
Swap two dyn matrix.
Definition: custom_dyn.hpp:403
auto loadu(size_t x) const noexcept
Load several elements of the expression at once.
Definition: dyn_matrix_view.hpp:154
auto min(L &&lhs, R &&rhs)
Create an expression with the min value of lhs or rhs.
Definition: expression_builder.hpp:77
Base class and utilities for dyn matrix implementations.
std::array< size_t, n_dimensions > dimension_storage_impl
The type used to store the dimensions.
Definition: dyn.hpp:40
void visit(detail::evaluator_visitor &visitor) const
Apply the given visitor to this expression and its descendants.
Definition: dyn_matrix_view.hpp:263
std::conditional_t< SO==order::RowMajor, const value_type *, etl::iterator< const this_type > > const_iterator
The const iterator type.
Definition: dyn.hpp:45
requires(D > 0) struct dyn_base
Matrix with run-time fixed dimensions.
Definition: dyn_base.hpp:113
bool is_gpu_up_to_date() const noexcept
Indicates if the GPU memory is up to date.
Definition: sub_view.hpp:785
void ensure_gpu_up_to_date() const
Copy back from the GPU to the expression memory if necessary.
Definition: dyn_matrix_view.hpp:280
const value_type * const_memory_type
The const memory type.
Definition: dyn.hpp:42
dyn_matrix_impl(dyn_matrix_impl &&rhs) noexcept
Move construct a matrix.
Definition: dyn.hpp:104
dense_dyn_base< this_type, T, SO, D > base_type
The base type.
Definition: dyn.hpp:37
void std_sub_evaluate(Expr &&expr, Result &&result)
Compound subtract evaluation of the expr into result.
Definition: evaluator.hpp:1214
void assign_mod_to(L &&lhs) const
Modulo the given left-hand-side expression.
Definition: dyn_matrix_view.hpp:253
auto allocate(size_t size, mangling_faker< S >=mangling_faker< S >())
Allocate an array of the given size for the given type.
Definition: allocator.hpp:80
Traits to test if the constructor is an initializer list constructor.
Definition: dyn_base.hpp:89
typename V::template vec_type< T > vec_type
The vectorization type for V.
Definition: dyn.hpp:51
const auto & gpu_compute_hint([[maybe_unused]] Y &y) const
Return a GPU computed version of this expression.
Definition: sub_view.hpp:653
typename decay_traits< E >::value_type value_t
Traits to extract the value type out of an ETL type.
Definition: tmp.hpp:81
void std_div_evaluate(Expr &&expr, Result &&result)
Compound divide evaluation of the expr into result.
Definition: evaluator.hpp:1252
void validate_cpu() const noexcept
Validates the CPU memory.
Definition: sub_view.hpp:702
static constexpr size_t n_dimensions
The number of dimensions.
Definition: dyn.hpp:32
void std_add_evaluate(Expr &&expr, Result &&result)
Compound add evaluation of the expr into result.
Definition: evaluator.hpp:1195
value_type *ETL_RESTRICT _memory
Pointer to the allocated memory.
Definition: dyn_base.hpp:312
CRTP class to inject functions testing the dimensions.
Definition: dim_testable.hpp:45
void assign_sub_to(L &&lhs) const
Sub from the given left-hand-side expression.
Definition: dyn_matrix_view.hpp:226