Expression Templates Library (ETL)
flip_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 
11 
12 namespace etl {
13 
19 template <etl_2d T>
21  using sub_type = T;
23 
25 
26  static constexpr bool gpu_computable = impl::egblas::has_sone_if_max_sub && all_row_major<T> && all_floating<T>;
27 
28 private:
29  sub_type sub;
30 
31  std::vector<size_t> max_indices;
32 
33 public:
38  explicit one_if_max_sub_transformer(sub_type expr) : sub(expr), max_indices(etl::dim<0>(expr)) {
39  for (size_t i = 0; i < etl::dim<0>(expr); ++i) {
40  max_indices[i] = max_index(sub(i));
41  }
42  }
43 
49  value_type operator[](size_t i) const {
50  size_t i_i = i / dim<1>(sub);
51  size_t i_j = i % dim<1>(sub);
52  return i_j == max_indices[i_i] ? value_type(1) : value_type(0);
53  }
54 
61  value_type read_flat(size_t i) const {
62  size_t i_i = i / dim<1>(sub);
63  size_t i_j = i % dim<1>(sub);
64  return i_j == max_indices[i_i] ? value_type(1) : value_type(0);
65  }
66 
73  value_type operator()(size_t i, size_t j) const {
74  return j == max_indices[i] ? value_type(1) : value_type(0);
75  }
76 
82  template <typename E>
83  bool alias(const E& rhs) const noexcept {
84  return sub.alias(rhs);
85  }
86 
94  template <typename Y>
95  auto gpu_compute_hint(Y& y) const noexcept {
96  decltype(auto) t1 = smart_gpu_compute_hint(sub, y);
97 
98  auto t2 = force_temporary_gpu_dim_only(t1);
99 
100  impl::egblas::one_if_max_sub(etl::dim<0>(y), etl::dim<1>(y), 1, t1.gpu_memory(), 1, t2.gpu_memory(), 1);
101 
102  t2.validate_gpu();
103  t2.invalidate_cpu();
104 
105  return t2;
106  }
113  template <typename Y>
114  Y& gpu_compute(Y& y) const noexcept {
115  decltype(auto) t1 = select_smart_gpu_compute(sub, y);
116 
117  impl::egblas::one_if_max_sub(etl::dim<0>(y), etl::dim<1>(y), 1, t1.gpu_memory(), 1, y.gpu_memory(), 1);
118 
119  y.validate_gpu();
120  y.invalidate_cpu();
121 
122  return y;
123  }
124 
125  // Internals
126 
131  template <typename V>
132  void visit(V&& visitor) const {
133  sub.visit(std::forward<V>(visitor));
134  }
135 
140  void ensure_cpu_up_to_date() const {
141  // Need to ensure sub value
142  sub.ensure_cpu_up_to_date();
143  }
144 
149  void ensure_gpu_up_to_date() const {
150  // Need to ensure both LHS and RHS
151  sub.ensure_gpu_up_to_date();
152  }
153 
160  friend std::ostream& operator<<(std::ostream& os, const one_if_max_sub_transformer& transformer) {
161  return os << "one_if_max_sub(" << transformer.sub << ")";
162  }
163 };
164 
169 template <typename T>
171  using sub_type = T;
173 
175 
176  static constexpr bool gpu_computable = false;
177 
178 private:
179  sub_type sub;
180 
181 public:
186  explicit hflip_transformer(sub_type expr) : sub(expr) {}
187 
188  static constexpr bool matrix = is_2d<sub_type>;
189 
195  value_type operator[](size_t i) const {
196  if constexpr (matrix) {
197  size_t i_i = i / dim<1>(sub);
198  size_t i_j = i % dim<1>(sub);
199  return sub[i_i * dim<1>(sub) + (dim<1>(sub) - 1 - i_j)];
200  } else {
201  return sub[etl::size(sub) - i - 1];
202  }
203  }
204 
211  value_type read_flat(size_t i) const {
212  if constexpr (matrix) {
213  size_t i_i = i / dim<1>(sub);
214  size_t i_j = i % dim<1>(sub);
215  return sub.read_flat(i_i * dim<1>(sub) + (dim<1>(sub) - 1 - i_j));
216  } else {
217  return sub.read_flat(etl::size(sub) - i - 1);
218  }
219  }
220 
226  value_type operator()(size_t i) const {
227  return sub(etl::size(sub) - 1 - i);
228  }
229 
236  value_type operator()(size_t i, size_t j) const {
237  return sub(i, columns(sub) - 1 - j);
238  }
239 
245  template <typename E>
246  bool alias(const E& rhs) const noexcept {
247  return sub.alias(rhs);
248  }
249 
250  // Internals
251 
256  template <typename V>
257  void visit(V&& visitor) const {
258  sub.visit(std::forward<V>(visitor));
259  }
260 
265  void ensure_cpu_up_to_date() const {
266  // Need to ensure sub value
267  sub.ensure_cpu_up_to_date();
268  }
269 
274  void ensure_gpu_up_to_date() const {
275  // Need to ensure both LHS and RHS
276  sub.ensure_gpu_up_to_date();
277  }
278 
285  friend std::ostream& operator<<(std::ostream& os, const hflip_transformer& transformer) {
286  return os << "hflip(" << transformer.sub << ")";
287  }
288 };
289 
294 template <typename T>
296  using sub_type = T;
298 
300 
301  static constexpr bool gpu_computable = false;
302 
303 private:
304  sub_type sub;
305 
306 public:
311  explicit vflip_transformer(sub_type expr) : sub(expr) {}
312 
313  static constexpr bool matrix = is_2d<sub_type>;
314 
320  value_type operator[](size_t i) const {
321  if constexpr (matrix) {
322  size_t i_i = i / dim<1>(sub);
323  size_t i_j = i % dim<1>(sub);
324  return sub[(dim<0>(sub) - 1 - i_i) * dim<1>(sub) + i_j];
325  } else {
326  return sub[i];
327  }
328  }
329 
336  value_type read_flat(size_t i) const {
337  if constexpr (matrix) {
338  size_t i_i = i / dim<1>(sub);
339  size_t i_j = i % dim<1>(sub);
340  return sub.read_flat((dim<0>(sub) - 1 - i_i) * dim<1>(sub) + i_j);
341  } else {
342  return sub.read_flat(i);
343  }
344  }
345 
351  value_type operator()(size_t i) const {
352  return sub(i);
353  }
354 
361  value_type operator()(size_t i, size_t j) const {
362  return sub(rows(sub) - 1 - i, j);
363  }
364 
370  template <typename E>
371  bool alias(const E& rhs) const noexcept {
372  return sub.alias(rhs);
373  }
374 
375  // Internals
376 
381  template <typename V>
382  void visit(V&& visitor) const {
383  sub.visit(std::forward<V>(visitor));
384  }
385 
390  void ensure_cpu_up_to_date() const {
391  // Need to ensure sub value
392  sub.ensure_cpu_up_to_date();
393  }
394 
399  void ensure_gpu_up_to_date() const {
400  // Need to ensure both LHS and RHS
401  sub.ensure_gpu_up_to_date();
402  }
403 
410  friend std::ostream& operator<<(std::ostream& os, const vflip_transformer& transformer) {
411  return os << "vflip(" << transformer.sub << ")";
412  }
413 };
414 
419 template <typename T>
421  using sub_type = T;
423 
425 
426  static constexpr bool gpu_computable = false;
427 
428 private:
429  sub_type sub;
430 
431 public:
436  explicit fflip_transformer(sub_type expr) : sub(expr) {}
437 
443  value_type operator[](size_t i) const {
444  if (dimensions(sub) == 1) {
445  return sub[i];
446  } else {
447  return sub[etl::size(sub) - i - 1];
448  }
449  }
450 
457  value_type read_flat(size_t i) const {
458  if (dimensions(sub) == 1) {
459  return sub.read_flat(i);
460  } else {
461  return sub.read_flat(etl::size(sub) - i - 1);
462  }
463  }
464 
470  value_type operator()(size_t i) const {
471  return sub(i);
472  }
473 
480  value_type operator()(size_t i, size_t j) const {
481  return sub(rows(sub) - 1 - i, columns(sub) - 1 - j);
482  }
483 
489  template <typename E>
490  bool alias(const E& rhs) const noexcept {
491  return sub.alias(rhs);
492  }
493 
494  // Internals
495 
500  template <typename V>
501  void visit(V&& visitor) const {
502  sub.visit(std::forward<V>(visitor));
503  }
504 
509  void ensure_cpu_up_to_date() const {
510  // Need to ensure sub value
511  sub.ensure_cpu_up_to_date();
512  }
513 
518  void ensure_gpu_up_to_date() const {
519  // Need to ensure both LHS and RHS
520  sub.ensure_gpu_up_to_date();
521  }
522 
529  friend std::ostream& operator<<(std::ostream& os, const fflip_transformer& transformer) {
530  return os << "fflip(" << transformer.sub << ")";
531  }
532 };
533 
537 template <typename T>
538 requires( cpp::specialization_of<etl::hflip_transformer, T>
539  || cpp::specialization_of<etl::vflip_transformer, T>
540  || cpp::specialization_of<etl::fflip_transformer, T>
541  || cpp::specialization_of<etl::one_if_max_sub_transformer, T>)
542 struct etl_traits<T> {
543  using expr_t = T;
544  using sub_expr_t = std::decay_t<typename T::sub_type>;
546 
547  static constexpr bool is_etl = true;
548  static constexpr bool is_transformer = true;
549  static constexpr bool is_view = false;
550  static constexpr bool is_magic_view = false;
551  static constexpr bool is_fast = etl_traits<sub_expr_t>::is_fast;
552  static constexpr bool is_linear = false;
553  static constexpr bool is_thread_safe = true;
554  static constexpr bool is_value = false;
555  static constexpr bool is_direct = false;
556  static constexpr bool is_generator = false;
557  static constexpr bool is_padded = false;
558  static constexpr bool is_aligned = false;
559  static constexpr bool is_temporary = etl_traits<sub_expr_t>::is_temporary;
560  static constexpr bool gpu_computable = T::gpu_computable;
561  static constexpr order storage_order = etl_traits<sub_expr_t>::storage_order;
562 
568  template <vector_mode_t V>
569  static constexpr bool vectorizable = false;
570 
576  static size_t size(const expr_t& v) {
577  return etl_traits<sub_expr_t>::size(v.sub);
578  }
579 
586  static size_t dim(const expr_t& v, size_t d) {
587  return etl_traits<sub_expr_t>::dim(v.sub, d);
588  }
589 
594  static constexpr size_t size() {
596  }
597 
603  template <size_t D>
604  static constexpr size_t dim() {
605  return etl_traits<sub_expr_t>::template dim<D>();
606  }
607 
612  static constexpr size_t dimensions() {
614  }
615 
620  static constexpr int complexity() noexcept {
621  return -1;
622  }
623 };
624 
625 } //end of namespace etl
value_type operator()(size_t i, size_t j) const
Access to the value at the given (i, j) position.
Definition: flip_transformers.hpp:236
Transform (dynamic) that flips a matrix vertically and horizontally.
Definition: flip_transformers.hpp:420
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: flip_transformers.hpp:140
constexpr int complexity([[maybe_unused]] const E &expr) noexcept
Return the complexity of the expression.
Definition: helpers.hpp:38
Transformer to implement one if max sub on 2D matrix.
Definition: flip_transformers.hpp:20
Transformer functor for optimizable expression.
Definition: expr_fwd.hpp:19
vflip_transformer(sub_type expr)
Construct a new transformer around the given expression.
Definition: flip_transformers.hpp:311
Transform (dynamic) that flips a matrix horizontally.
Definition: flip_transformers.hpp:170
value_type read_flat(size_t i) const
Returns the value at the given index This function never has side effects.
Definition: flip_transformers.hpp:336
void visit(V &&visitor) const
Apply the given visitor to this expression and its descendants.
Definition: flip_transformers.hpp:132
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
bool alias(const E &rhs) const noexcept
Test if this expression aliases with the given expression.
Definition: flip_transformers.hpp:490
T sub_type
The type on which the expression works.
Definition: flip_transformers.hpp:421
value_type read_flat(size_t i) const
Returns the value at the given index This function never has side effects.
Definition: flip_transformers.hpp:61
friend std::ostream & operator<<(std::ostream &os, const hflip_transformer &transformer)
Display the transformer on the given stream.
Definition: flip_transformers.hpp:285
friend std::ostream & operator<<(std::ostream &os, const vflip_transformer &transformer)
Display the transformer on the given stream.
Definition: flip_transformers.hpp:410
bool alias(const E &rhs) const noexcept
Test if this expression aliases with the given expression.
Definition: flip_transformers.hpp:371
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: flip_transformers.hpp:390
decltype(auto) select_smart_gpu_compute(X &x, Y &y)
Compute the expression into a representation that is GPU up to date and possibly store this represent...
Definition: helpers.hpp:434
void ensure_gpu_up_to_date() const
Copy back from the GPU to the expression memory if necessary.
Definition: flip_transformers.hpp:518
order
Storage order of a matrix.
Definition: order.hpp:15
value_type operator()(size_t i) const
Access to the value at the given (i) position.
Definition: flip_transformers.hpp:470
auto gpu_compute_hint(Y &y) const noexcept
Compute the result of the operation using the GPU.
Definition: flip_transformers.hpp:95
value_t< T > value_type
The type of valuie.
Definition: flip_transformers.hpp:297
value_type operator()(size_t i, size_t j) const
Access to the value at the given (i, j) position.
Definition: flip_transformers.hpp:73
auto one_if_max_sub(const E &value)
Return, for each original position, 1.0 if the value is the max of the sub matrix, 0.0 otherwise.
Definition: expression_builder.hpp:488
bool alias(const E &rhs) const noexcept
Test if this expression aliases with the given expression.
Definition: flip_transformers.hpp:83
constexpr bool is_fast
Traits to test if the given ETL expresion type is fast (sizes known at compile-time) ...
Definition: traits.hpp:588
void ensure_gpu_up_to_date() const
Copy back from the GPU to the expression memory if necessary.
Definition: flip_transformers.hpp:399
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
size_t max_index(E &&values)
Returns the index of the maximum element contained in the expression.
Definition: expression_builder.hpp:720
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
hflip_transformer(sub_type expr)
Construct a new transformer around the given expression.
Definition: flip_transformers.hpp:186
size_t columns(const E &expr)
Returns the number of columns of the given ETL expression.
Definition: helpers.hpp:78
void ensure_gpu_up_to_date() const
Copy back from the GPU to the expression memory if necessary.
Definition: flip_transformers.hpp:149
value_type operator()(size_t i) const
Access to the value at the given (i) position.
Definition: flip_transformers.hpp:226
T sub_type
The type on which the expression works.
Definition: flip_transformers.hpp:171
value_type operator[](size_t i) const
Returns the value at the given index.
Definition: flip_transformers.hpp:49
value_t< T > value_type
The type of valuie.
Definition: flip_transformers.hpp:22
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: flip_transformers.hpp:265
friend std::ostream & operator<<(std::ostream &os, const fflip_transformer &transformer)
Display the transformer on the given stream.
Definition: flip_transformers.hpp:529
value_type read_flat(size_t i) const
Returns the value at the given index This function never has side effects.
Definition: flip_transformers.hpp:457
value_t< T > value_type
The type of valuie.
Definition: flip_transformers.hpp:172
decltype(auto) force_temporary_gpu_dim_only(E &&expr)
Force a temporary out of the expression, without copying its content.
Definition: temporary.hpp:223
constexpr bool is_transformer
Traits indicating if the given ETL type is a transformer expression.
Definition: traits.hpp:297
Transform (dynamic) that flips a matrix vertically.
Definition: flip_transformers.hpp:295
T sub_type
The type on which the expression works.
Definition: flip_transformers.hpp:296
value_t< T > value_type
The type of valuie.
Definition: flip_transformers.hpp:422
one_if_max_sub_transformer(sub_type expr)
Construct a new transformer around the given expression.
Definition: flip_transformers.hpp:38
constexpr size_t size(const E &expr) noexcept
Returns the size of the given ETL expression.
Definition: helpers.hpp:108
void visit(V &&visitor) const
Apply the given visitor to this expression and its descendants.
Definition: flip_transformers.hpp:257
requires(D > 0) struct dyn_base
Matrix with run-time fixed dimensions.
Definition: dyn_base.hpp:113
T sub_type
The type on which the expression works.
Definition: flip_transformers.hpp:21
constexpr bool is_view
Traits indicating if the given ETL type is a view expression.
Definition: traits.hpp:304
value_type operator[](size_t i) const
Returns the value at the given index.
Definition: flip_transformers.hpp:195
EGBLAS wrappers for the one_if_max_sub operation.
void visit(V &&visitor) const
Apply the given visitor to this expression and its descendants.
Definition: flip_transformers.hpp:501
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: flip_transformers.hpp:509
void visit(V &&visitor) const
Apply the given visitor to this expression and its descendants.
Definition: flip_transformers.hpp:382
value_type operator()(size_t i, size_t j) const
Access to the value at the given (i, j) position.
Definition: flip_transformers.hpp:361
constexpr bool is_thread_safe
Traits to test if the given ETL expresion type is thread safe.
Definition: traits.hpp:687
bool alias(const E &rhs) const noexcept
Test if this expression aliases with the given expression.
Definition: flip_transformers.hpp:246
Y & gpu_compute(Y &y) const noexcept
Compute the result of the operation using the GPU.
Definition: flip_transformers.hpp:114
friend std::ostream & operator<<(std::ostream &os, const one_if_max_sub_transformer &transformer)
Display the transformer on the given stream.
Definition: flip_transformers.hpp:160
size_t rows(const E &expr)
Returns the number of rows of the given ETL expression.
Definition: helpers.hpp:58
decltype(auto) smart_gpu_compute_hint(E &expr, Y &y)
Compute the expression into a representation that is GPU up to date.
Definition: helpers.hpp:368
value_type operator()(size_t i, size_t j) const
Access to the value at the given (i, j) position.
Definition: flip_transformers.hpp:480
typename decay_traits< E >::value_type value_t
Traits to extract the value type out of an ETL type.
Definition: tmp.hpp:81
value_type read_flat(size_t i) const
Returns the value at the given index This function never has side effects.
Definition: flip_transformers.hpp:211
value_type operator[](size_t i) const
Returns the value at the given index.
Definition: flip_transformers.hpp:443
value_type operator[](size_t i) const
Returns the value at the given index.
Definition: flip_transformers.hpp:320
void ensure_gpu_up_to_date() const
Copy back from the GPU to the expression memory if necessary.
Definition: flip_transformers.hpp:274
fflip_transformer(sub_type expr)
Construct a new transformer around the given expression.
Definition: flip_transformers.hpp:436
value_type operator()(size_t i) const
Access to the value at the given (i) position.
Definition: flip_transformers.hpp:351