Expression Templates Library (ETL)
rep_transformers.hpp
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 
8 #pragma once
9 
10 namespace etl {
11 
16 template <typename T, typename D>
18  using derived_t = D;
19  using sub_type = T;
21 
22  static constexpr bool gpu_computable = false;
23 
24 protected:
26 
27 public:
32  explicit rep_transformer(sub_type expr) : sub(expr) {}
33 
39  template <typename... Sizes>
40  value_type operator()(Sizes... args) const {
41  return as_derived().selected_only(make_index_range<derived_t::dim_start, derived_t::dim_end>(), args...);
42  }
43 
49  template <typename E>
50  bool alias(const E& rhs) const noexcept {
51  return sub.alias(rhs);
52  }
53 
54  // Internals
55 
60  template <typename V>
61  void visit(V&& visitor) const {
62  sub.visit(std::forward<V>(visitor));
63  }
64 
69  void ensure_cpu_up_to_date() const {
70  // Need to ensure sub value
71  sub.ensure_cpu_up_to_date();
72  }
73 
78  void ensure_gpu_up_to_date() const {
79  // Need to ensure both LHS and RHS
80  sub.ensure_gpu_up_to_date();
81  }
82 
83 private:
88  const derived_t& as_derived() const noexcept {
89  return *static_cast<const derived_t*>(this);
90  }
91 };
92 
98 template <typename T, size_t... D>
99 struct rep_r_transformer : rep_transformer<T, rep_r_transformer<T, D...>> {
100  using this_type = rep_r_transformer<T, D...>;
102  using sub_type = typename base_type::sub_type;
104 
105  static constexpr bool gpu_computable = false;
106 
107 private:
108  static constexpr size_t sub_d = decay_traits<sub_type>::dimensions();
109  static constexpr size_t dimensions = sizeof...(D) + sub_d;
110  static constexpr size_t dim_start = 0;
111  static constexpr size_t dim_end = sub_d;
112 
113  friend struct rep_transformer<T, rep_r_transformer>;
114  friend struct etl_traits<rep_r_transformer>;
115 
116 public:
121  explicit rep_r_transformer(sub_type expr) : base_type(expr) {}
122 
128  value_type operator[](size_t i) const {
129  return this->sub[i / (D * ...)];
130  }
131 
138  value_type read_flat(size_t i) const noexcept {
139  return this->sub.read_flat(i / (D * ...));
140  }
141 
145  template <typename... Sizes, size_t... I>
146  value_type selected_only(const std::index_sequence<I...>& /*seq*/, Sizes... sizes) const {
147  return this->sub(cpp::nth_value<I>(sizes...)...);
148  }
149 
156  friend std::ostream& operator<<(std::ostream& os, const rep_r_transformer& transformer) {
157  return os << "rep_r[" << concat_sizes(D...) << "](" << transformer.sub << ")";
158  }
159 };
160 
166 template <typename T, size_t... D>
167 struct rep_l_transformer : rep_transformer<T, rep_l_transformer<T, D...>> {
168  using this_type = rep_l_transformer<T, D...>;
170  using sub_type = typename base_type::sub_type;
172 
173  static constexpr bool gpu_computable = false;
174 
175 private:
176  static constexpr size_t sub_d = decay_traits<sub_type>::dimensions();
177  static constexpr size_t dimensions = sizeof...(D) + sub_d;
178  static constexpr size_t dim_start = sizeof...(D);
179  static constexpr size_t dim_end = dimensions;
180 
181  friend struct rep_transformer<T, rep_l_transformer>;
182  friend struct etl_traits<rep_l_transformer>;
183 
184 public:
189  explicit rep_l_transformer(sub_type expr) : base_type(expr) {}
190 
196  value_type operator[](size_t i) const {
197  return this->sub[i % etl::size(this->sub)];
198  }
199 
206  value_type read_flat(size_t i) const noexcept {
207  return this->sub.read_flat(i % etl::size(this->sub));
208  }
209 
213  template <typename... Sizes, size_t... I>
214  value_type selected_only(const std::index_sequence<I...>& /*seq*/, Sizes... sizes) const {
215  return this->sub(cpp::nth_value<I>(sizes...)...);
216  }
217 
224  friend std::ostream& operator<<(std::ostream& os, const rep_l_transformer& transformer) {
225  return os << "rep_l[" << concat_sizes(D...) << "](" << transformer.sub << ")";
226  }
227 };
228 
234 template <typename T, size_t D>
235 struct dyn_rep_r_transformer : rep_transformer<T, dyn_rep_r_transformer<T, D>> {
238  using sub_type = typename base_type::sub_type;
240 
241  static constexpr bool gpu_computable = false;
242 
243 private:
244  static constexpr size_t sub_d = decay_traits<sub_type>::dimensions();
245  static constexpr size_t dimensions = D + sub_d;
246  static constexpr size_t dim_start = 0;
247  static constexpr size_t dim_end = sub_d;
248 
249  std::array<size_t, D> reps;
250  size_t m;
251 
252  friend struct rep_transformer<T, dyn_rep_r_transformer>;
253  friend struct etl_traits<dyn_rep_r_transformer>;
254 
255 public:
261  dyn_rep_r_transformer(sub_type expr, std::array<size_t, D> reps_a) : base_type(expr), reps(reps_a) {
262  m = std::accumulate(reps.begin(), reps.end(), 1UL, [](size_t a, size_t b) { return a * b; });
263  }
264 
270  value_type operator[](size_t i) const {
271  return this->sub[i / m];
272  }
273 
280  value_type read_flat(size_t i) const noexcept {
281  return this->sub.read_flat(i / m);
282  }
283 
287  template <typename... Sizes, size_t... I>
288  value_type selected_only(const std::index_sequence<I...>& /*seq*/, Sizes... sizes) const {
289  return this->sub(cpp::nth_value<I>(sizes...)...);
290  }
291 };
292 
298 template <typename T, size_t D>
299 struct dyn_rep_l_transformer : rep_transformer<T, dyn_rep_l_transformer<T, D>> {
302  using sub_type = typename base_type::sub_type;
304 
305  static constexpr bool gpu_computable = false;
306 
307 private:
308  static constexpr size_t sub_d = decay_traits<sub_type>::dimensions();
309  static constexpr size_t dimensions = D + sub_d;
310  static constexpr size_t dim_start = D;
311  static constexpr size_t dim_end = dimensions;
312 
313  std::array<size_t, D> reps;
314  size_t m;
315 
316  friend struct rep_transformer<T, dyn_rep_l_transformer>;
317  friend struct etl_traits<dyn_rep_l_transformer>;
318 
319 public:
325  dyn_rep_l_transformer(sub_type expr, std::array<size_t, D> reps_a) : base_type(expr), reps(reps_a) {
326  m = std::accumulate(reps.begin(), reps.end(), 1UL, [](size_t a, size_t b) { return a * b; });
327  }
328 
334  value_type operator[](size_t i) const {
335  return this->sub[i % etl::size(this->sub)];
336  }
337 
344  value_type read_flat(size_t i) const {
345  return this->sub.read_flat(i % etl::size(this->sub));
346  }
347 
351  template <typename... Sizes, size_t... I>
352  value_type selected_only(const std::index_sequence<I...>& /*seq*/, Sizes... sizes) const {
353  return this->sub(cpp::nth_value<I>(sizes...)...);
354  }
355 };
356 
360 template <typename T, size_t... D>
362  using expr_t = etl::rep_r_transformer<T, D...>;
363  using sub_expr_t = std::decay_t<T>;
365 
366  static constexpr bool is_etl = true;
367  static constexpr bool is_transformer = true;
368  static constexpr bool is_view = false;
369  static constexpr bool is_magic_view = false;
370  static constexpr bool is_fast = etl_traits<sub_expr_t>::is_fast;
371  static constexpr bool is_linear = false;
373  static constexpr bool is_value = false;
374  static constexpr bool is_direct = false;
375  static constexpr bool is_generator = false;
376  static constexpr bool is_padded = false;
377  static constexpr bool is_aligned = false;
378  static constexpr bool is_temporary = etl_traits<sub_expr_t>::is_temporary;
379  static constexpr bool gpu_computable = false;
380  static constexpr order storage_order = etl_traits<sub_expr_t>::storage_order;
381 
382  static constexpr size_t sub_d = etl_traits<sub_expr_t>::dimensions();
383 
389  template <vector_mode_t V>
390  static constexpr bool vectorizable = false;
391 
397  static size_t size(const expr_t& v) {
398  return (D * ...) * etl_traits<sub_expr_t>::size(v.sub);
399  }
400 
407  static size_t dim(const expr_t& v, size_t d) {
408  if (d < sub_d) {
409  return etl_traits<sub_expr_t>::dim(v.sub, d);
410  } else {
411  return dyn_nth_size<D...>(d - sub_d);
412  }
413  }
414 
419  static constexpr size_t size() {
420  return (D * ...) * etl_traits<sub_expr_t>::size();
421  }
422 
426  template <size_t D2>
427  static constexpr size_t dim() {
428  if constexpr (D2 < sub_d) {
429  return etl_traits<sub_expr_t>::template dim<D2>();
430  } else {
431  return nth_size<D2 - sub_d, 0, D...>();
432  }
433  }
434 
439  static constexpr size_t dimensions() {
440  return sizeof...(D) + etl_traits<sub_expr_t>::dimensions();
441  }
442 
447  static constexpr int complexity() noexcept {
448  return 3;
449  }
450 };
451 
455 template <typename T, size_t... D>
457  using expr_t = etl::rep_l_transformer<T, D...>;
458  using sub_expr_t = std::decay_t<T>;
460 
461  static constexpr bool is_etl = true;
462  static constexpr bool is_transformer = true;
463  static constexpr bool is_view = false;
464  static constexpr bool is_magic_view = false;
465  static constexpr bool is_fast = etl_traits<sub_expr_t>::is_fast;
466  static constexpr bool is_linear = false;
468  static constexpr bool is_value = false;
469  static constexpr bool is_direct = false;
470  static constexpr bool is_generator = false;
471  static constexpr bool is_padded = false;
472  static constexpr bool is_aligned = false;
473  static constexpr bool is_temporary = etl_traits<sub_expr_t>::is_temporary;
474  static constexpr bool gpu_computable = false;
475  static constexpr order storage_order = etl_traits<sub_expr_t>::storage_order;
476 
482  template <vector_mode_t V>
483  static constexpr bool vectorizable = false;
484 
490  static size_t size(const expr_t& v) {
491  return (D * ...) * etl_traits<sub_expr_t>::size(v.sub);
492  }
493 
500  static size_t dim(const expr_t& v, size_t d) {
501  if (d >= sizeof...(D)) {
502  return etl_traits<sub_expr_t>::dim(v.sub, d - sizeof...(D));
503  } else {
504  return dyn_nth_size<D...>(d);
505  }
506  }
507 
512  static constexpr size_t size() {
513  return (D * ...) * etl_traits<sub_expr_t>::size();
514  }
515 
521  template <size_t D2>
522  static constexpr size_t dim() {
523  if constexpr (D2 >= sizeof...(D)) {
524  return etl_traits<sub_expr_t>::template dim<D2 - sizeof...(D)>();
525  } else {
526  return nth_size<D2, 0, D...>();
527  }
528  }
529 
534  static constexpr size_t dimensions() {
535  return sizeof...(D) + etl_traits<sub_expr_t>::dimensions();
536  }
537 
542  static constexpr int complexity() noexcept {
543  return 3;
544  }
545 };
546 
550 template <typename T, size_t D>
553  using sub_expr_t = std::decay_t<T>;
555 
556  static constexpr bool is_etl = true;
557  static constexpr bool is_transformer = true;
558  static constexpr bool is_view = false;
559  static constexpr bool is_magic_view = false;
560  static constexpr bool is_fast = false;
561  static constexpr bool is_linear = false;
563  static constexpr bool is_value = false;
564  static constexpr bool is_direct = false;
565  static constexpr bool is_generator = false;
566  static constexpr bool is_padded = false;
567  static constexpr bool is_aligned = false;
568  static constexpr bool is_temporary = etl_traits<sub_expr_t>::is_temporary;
569  static constexpr bool gpu_computable = false;
570  static constexpr order storage_order = etl_traits<sub_expr_t>::storage_order;
571 
572  static constexpr size_t sub_d = etl_traits<sub_expr_t>::dimensions();
573 
579  template <vector_mode_t V>
580  static constexpr bool vectorizable = false;
581 
587  static size_t size(const expr_t& v) {
588  return v.m * etl_traits<sub_expr_t>::size(v.sub);
589  }
590 
597  static size_t dim(const expr_t& v, size_t d) {
598  return d < sub_d ? etl_traits<sub_expr_t>::dim(v.sub, d) : v.reps[d - sub_d];
599  }
600 
605  static constexpr size_t dimensions() {
607  }
608 
613  static constexpr int complexity() noexcept {
614  return 3;
615  }
616 };
617 
621 template <typename T, size_t D>
624  using sub_expr_t = std::decay_t<T>;
626 
627  static constexpr bool is_etl = true;
628  static constexpr bool is_transformer = true;
629  static constexpr bool is_view = false;
630  static constexpr bool is_magic_view = false;
631  static constexpr bool is_fast = false;
632  static constexpr bool is_linear = false;
634  static constexpr bool is_value = false;
635  static constexpr bool is_direct = false;
636  static constexpr bool is_generator = false;
637  static constexpr bool is_padded = false;
638  static constexpr bool is_aligned = false;
639  static constexpr bool is_temporary = etl_traits<sub_expr_t>::is_temporary;
640  static constexpr bool gpu_computable = false;
641  static constexpr order storage_order = etl_traits<sub_expr_t>::storage_order;
642 
648  template <vector_mode_t V>
649  static constexpr bool vectorizable = false;
650 
656  static size_t size(const expr_t& v) {
657  return v.m * etl_traits<sub_expr_t>::size(v.sub);
658  }
659 
666  static size_t dim(const expr_t& v, size_t d) {
667  return d >= D ? etl_traits<sub_expr_t>::dim(v.sub, d - D) : v.reps[d];
668  }
669 
674  static constexpr size_t dimensions() {
676  }
677 
682  static constexpr int complexity() noexcept {
683  return 3;
684  }
685 };
686 
687 } //end of namespace etl
dyn_rep_l_transformer(sub_type expr, std::array< size_t, D > reps_a)
Construct a new transformer around the given expression.
Definition: rep_transformers.hpp:325
typename base_type::value_type value_type
The type of value.
Definition: rep_transformers.hpp:239
value_type operator[](size_t i) const
Returns the value at the given index.
Definition: rep_transformers.hpp:128
static constexpr size_t dimensions()
Returns the number of expressions for this type.
Definition: rep_transformers.hpp:605
static size_t dim(const expr_t &v, size_t d)
Returns the dth dimension of the given expression.
Definition: rep_transformers.hpp:500
std::decay_t< T > sub_expr_t
The sub expression type.
Definition: rep_transformers.hpp:624
value_type operator[](size_t i) const
Returns the value at the given index.
Definition: rep_transformers.hpp:270
value_t< T > value_type
The type of valuie.
Definition: rep_transformers.hpp:20
Transformer functor for optimizable expression.
Definition: expr_fwd.hpp:19
std::decay_t< T > sub_expr_t
The sub expression type.
Definition: rep_transformers.hpp:553
std::decay_t< T > sub_expr_t
The sub expression type.
Definition: rep_transformers.hpp:458
static size_t size(const expr_t &v)
Returns the size of the given expression.
Definition: rep_transformers.hpp:397
sub_type sub
The subexpression.
Definition: rep_transformers.hpp:25
size_t dyn_nth_size(size_t i)
Returns the dth (dynamic) dimension from the variadic list D.
Definition: tmp.hpp:116
value_t< sub_type > value_type
The value contained in the expression.
Definition: dyn_matrix_view.hpp:31
constexpr bool is_magic_view
Traits indicating if the given ETL type is a magic view expression.
Definition: traits.hpp:311
rep_l_transformer(sub_type expr)
Construct a new transformer around the given expression.
Definition: rep_transformers.hpp:189
static constexpr size_t dimensions()
Returns the number of expressions for this type.
Definition: rep_transformers.hpp:439
dyn_rep_r_transformer(sub_type expr, std::array< size_t, D > reps_a)
Construct a new transformer around the given expression.
Definition: rep_transformers.hpp:261
typename base_type::value_type value_type
The type of value.
Definition: rep_transformers.hpp:103
friend std::ostream & operator<<(std::ostream &os, const rep_r_transformer &transformer)
Display the transformer on the given stream.
Definition: rep_transformers.hpp:156
D D
The number of dimensions.
Definition: dyn_matrix_view.hpp:24
void visit(V &&visitor) const
Apply the given visitor to this expression and its descendants.
Definition: rep_transformers.hpp:61
typename base_type::sub_type sub_type
The type on which the expression works.
Definition: rep_transformers.hpp:302
order
Storage order of a matrix.
Definition: order.hpp:15
typename etl_traits< sub_expr_t >::value_type value_type
The value type of this expression.
Definition: rep_transformers.hpp:459
constexpr size_t nth_size()
Traits to get the Sth dimension in Dims..
Definition: tmp.hpp:102
static constexpr int complexity() noexcept
Estimate the complexity of computation.
Definition: rep_transformers.hpp:542
std::decay_t< T > sub_expr_t
The sub expression type.
Definition: rep_transformers.hpp:363
static size_t size(const expr_t &v)
Returns the size of the given expression.
Definition: rep_transformers.hpp:490
static constexpr int complexity() noexcept
Estimate the complexity of computation.
Definition: rep_transformers.hpp:613
typename base_type::value_type value_type
The type of value.
Definition: rep_transformers.hpp:171
typename base_type::sub_type sub_type
The type on which the expression works.
Definition: rep_transformers.hpp:102
Transform (dynamic) that repeats the expression to the right.
Definition: rep_transformers.hpp:235
T sub_type
The sub type.
Definition: dyn_matrix_view.hpp:30
typename base_type::value_type value_type
The type of value.
Definition: rep_transformers.hpp:303
std::string concat_sizes(Dims... sizes)
Returns a string representation of the given dimensions.
Definition: tmp.hpp:192
value_type operator[](size_t i) const
Returns the value at the given index.
Definition: rep_transformers.hpp:334
Transform that repeats the expression to the right.
Definition: rep_transformers.hpp:99
typename base_type::sub_type sub_type
The type on which the expression works.
Definition: rep_transformers.hpp:170
constexpr bool is_fast
Traits to test if the given ETL expresion type is fast (sizes known at compile-time) ...
Definition: traits.hpp:588
static constexpr size_t dimensions()
Returns the number of expressions for this type.
Definition: rep_transformers.hpp:534
Traits to get information about ETL types.
Definition: tmp.hpp:68
Root namespace for the ETL library.
Definition: adapter.hpp:15
static constexpr size_t dimensions()
Return the number of dimensions of the expression.
Definition: traits_base.hpp:31
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
static constexpr size_t size()
Returns the size of an expression of this fast type.
Definition: rep_transformers.hpp:419
friend std::ostream & operator<<(std::ostream &os, const rep_l_transformer &transformer)
Display the transformer on the given stream.
Definition: rep_transformers.hpp:224
typename etl_traits< sub_expr_t >::value_type value_type
The value type of this expression.
Definition: rep_transformers.hpp:625
static size_t size(const expr_t &v)
Returns the size of the given expression.
Definition: rep_transformers.hpp:587
value_type selected_only(const std::index_sequence< I... > &, Sizes... sizes) const
Returns the value at the given indices inside the range.
Definition: rep_transformers.hpp:146
static constexpr size_t size()
Returns the size of an expression of this fast type.
Definition: rep_transformers.hpp:512
value_type read_flat(size_t i) const noexcept
Returns the value at the given index This function never has side effects.
Definition: rep_transformers.hpp:206
value_type read_flat(size_t i) const noexcept
Returns the value at the given index This function never has side effects.
Definition: rep_transformers.hpp:138
T sub_type
The type on which the expression works.
Definition: rep_transformers.hpp:19
value_type operator[](size_t i) const
Returns the value at the given index.
Definition: rep_transformers.hpp:196
bool alias(const E &rhs) const noexcept
Test if this expression aliases with the given expression.
Definition: rep_transformers.hpp:50
constexpr bool is_transformer
Traits indicating if the given ETL type is a transformer expression.
Definition: traits.hpp:297
typename base_type::sub_type sub_type
The type on which the expression works.
Definition: rep_transformers.hpp:238
Transform that repeats the expression to the left.
Definition: rep_transformers.hpp:167
value_type operator()(Sizes... args) const
Access to the value at the given (args...) position.
Definition: rep_transformers.hpp:40
typename etl_traits< sub_expr_t >::value_type value_type
The value type of this expression.
Definition: rep_transformers.hpp:554
value_type selected_only(const std::index_sequence< I... > &, Sizes... sizes) const
Returns the value at the given indices inside the range.
Definition: rep_transformers.hpp:214
constexpr size_t size(const E &expr) noexcept
Returns the size of the given ETL expression.
Definition: helpers.hpp:108
typename etl_traits< sub_expr_t >::value_type value_type
The value type of this expression.
Definition: rep_transformers.hpp:364
static constexpr int complexity() noexcept
Estimate the complexity of computation.
Definition: rep_transformers.hpp:447
value_type read_flat(size_t i) const noexcept
Returns the value at the given index This function never has side effects.
Definition: rep_transformers.hpp:280
constexpr bool is_view
Traits indicating if the given ETL type is a view expression.
Definition: traits.hpp:304
static size_t dim(const expr_t &v, size_t d)
Returns the dth dimension of the given expression.
Definition: rep_transformers.hpp:407
Abstract repeat Transformer that repeats the expression to the right.
Definition: rep_transformers.hpp:17
make_integer_range< size_t, Begin, End > make_index_range
Helper to create an integer_range of size_t numbers.
Definition: tmp.hpp:186
void ensure_gpu_up_to_date() const
Copy back from the GPU to the expression memory if necessary.
Definition: rep_transformers.hpp:78
static size_t dim(const expr_t &v, size_t d)
Returns the dth dimension of the given expression.
Definition: rep_transformers.hpp:666
static constexpr size_t dimensions()
Returns the number of expressions for this type.
Definition: rep_transformers.hpp:674
static constexpr size_t dim()
Returns the D2th dimension of the expression.
Definition: rep_transformers.hpp:427
value_type selected_only(const std::index_sequence< I... > &, Sizes... sizes) const
Returns the value at the given indices inside the range.
Definition: rep_transformers.hpp:352
value_type read_flat(size_t i) const
Returns the value at the given index This function never has side effects.
Definition: rep_transformers.hpp:344
constexpr bool is_thread_safe
Traits to test if the given ETL expresion type is thread safe.
Definition: traits.hpp:687
void ensure_cpu_up_to_date() const
Ensures that the GPU memory is allocated and that the GPU memory is up to date (to undefined value)...
Definition: rep_transformers.hpp:69
static constexpr int complexity() noexcept
Estimate the complexity of computation.
Definition: rep_transformers.hpp:682
typename decay_traits< E >::value_type value_t
Traits to extract the value type out of an ETL type.
Definition: tmp.hpp:81
rep_r_transformer(sub_type expr)
Construct a new transformer around the given expression.
Definition: rep_transformers.hpp:121
static size_t size(const expr_t &v)
Returns the size of the given expression.
Definition: rep_transformers.hpp:656
value_type selected_only(const std::index_sequence< I... > &, Sizes... sizes) const
Returns the value at the given indices inside the range.
Definition: rep_transformers.hpp:288
static constexpr size_t dim()
Returns the D2th dimension of an expression of this type.
Definition: rep_transformers.hpp:522
rep_transformer(sub_type expr)
Construct a new transformer around the given expression.
Definition: rep_transformers.hpp:32
static size_t dim(const expr_t &v, size_t d)
Returns the dth dimension of the given expression.
Definition: rep_transformers.hpp:597
Transform (dynamic) that repeats the expression to the left.
Definition: rep_transformers.hpp:299