Expression Templates Library (ETL)
transpose.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/temporary.hpp"
16 
17 namespace etl::impl::standard {
18 
23 template <typename C>
24 void inplace_square_transpose(C&& c) {
25  using std::swap;
26 
27  const size_t N = etl::dim<0>(c);
28 
29  for (size_t i = 0; i < N - 1; ++i) {
30  size_t j = i + 1;
31 
32  for (; j + 1 < N; j += 2) {
33  swap(c(i, j + 0), c(j + 0, i));
34  swap(c(i, j + 1), c(j + 1, i));
35  }
36 
37  if (j < N) {
38  swap(c(i, j), c(j, i));
39  }
40  }
41 }
42 
47 template <typename C>
48 void inplace_rectangular_transpose(C&& mat) {
49  static constexpr bool row_major = decay_traits<C>::storage_order == order::RowMajor;
50 
51  auto copy = force_temporary(mat);
52 
53  //Dimensions prior to transposition
54  const size_t N = etl::dim<0>(mat);
55  const size_t M = etl::dim<1>(mat);
56 
57  // Note: cannot use operator(i,j) for lhs because it is indexed by its
58  // previous scheme (N instead of M)
59 
60  if constexpr (row_major) {
61  for (size_t i = 0; i < N; ++i) {
62  size_t j = 0;
63 
64  for (; j + 1 < M; j += 2) {
65  mat[(j + 0) * N + i] = copy(i, (j + 0));
66  mat[(j + 1) * N + i] = copy(i, (j + 1));
67  }
68 
69  if (j < M) {
70  mat[j * N + i] = copy(i, j);
71  }
72  }
73  } else {
74  for (size_t i = 0; i < N; ++i) {
75  size_t j = 0;
76 
77  for (; j + 1 < M; j += 2) {
78  mat[(j + 0) + M * i] = copy(i, (j + 0));
79  mat[(j + 1) + M * i] = copy(i, (j + 1));
80  }
81 
82  if (j < M) {
83  mat[j + M * i] = copy(i, j);
84  }
85  }
86  }
87 }
88 
97 template <typename C>
98 void real_inplace(C&& mat) {
99  using std::swap;
100 
101  const size_t N = etl::dim<0>(mat);
102  const size_t M = etl::dim<1>(mat);
103 
104  mat.ensure_cpu_up_to_date();
105 
106  auto data = mat.memory_start();
107 
108  for (size_t k = 0; k < N * M; k++) {
109  auto idx = k;
110  do {
111  idx = (idx % N) * M + (idx / N);
112  } while (idx < k);
113  std::swap(data[k], data[idx]);
114  }
115 }
116 
122 template <typename A, typename C>
123 void transpose(A&& a, C&& c) {
124  // Delegate aliasing transpose to inplace algorithm
125  if (a.alias(c)) {
126  if (etl::dim<0>(a) == etl::dim<1>(a)) {
127  inplace_square_transpose(c);
128  } else {
129  inplace_rectangular_transpose(c);
130  }
131  } else {
132  const size_t m = etl::dim<0>(a);
133  const size_t n = etl::dim<1>(a);
134 
135  // Note: cannot use operator(i,j) for rhs because it is indexed by its
136  // previous scheme (M instead of N)
137 
139  for (size_t i = 0; i < m; ++i) {
140  size_t j = 0;
141 
142  for (; j + 3 < n; j += 4) {
143  c[(j + 0) * m + i] = a[i * n + j + 0];
144  c[(j + 1) * m + i] = a[i * n + j + 1];
145  c[(j + 2) * m + i] = a[i * n + j + 2];
146  c[(j + 3) * m + i] = a[i * n + j + 3];
147  }
148 
149  for (; j + 1 < n; j += 2) {
150  c[(j + 0) * m + i] = a[i * n + j + 0];
151  c[(j + 1) * m + i] = a[i * n + j + 1];
152  }
153 
154  if (j < n) {
155  c[(j + 0) * m + i] = a[i * n + j];
156  }
157  }
158  } else {
159  for (size_t j = 0; j < n; ++j) {
160  for (size_t i = 0; i < m; ++i) {
161  c[i * n + j] = a[j * m + i];
162  }
163  }
164  }
165  }
166 }
167 
168 } //end of namespace etl::impl::standard
Definition: prob_pooling.hpp:10
auto transpose(const E &value)
Returns the transpose of the given expression.
Definition: expression_builder.hpp:528
Traits to get information about ETL types.
Definition: tmp.hpp:68
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
decltype(auto) force_temporary(E &&expr)
Force a temporary out of the expression.
Definition: temporary.hpp:91
void real_inplace(C &&mat)
Perform an inplace matrix transposition in O(1).
Definition: transpose.hpp:98
Row-Major storage.