| 140 | |
| 141 | template<typename T, bool conjugate> |
| 142 | void transpose_inplace(Param<T> input) { |
| 143 | const af::dim4 idims = input.dims(); |
| 144 | const af::dim4 istrides = input.strides(); |
| 145 | |
| 146 | T *in = input.get(); |
| 147 | |
| 148 | for (dim_t l = 0; l < idims[3]; ++l) { |
| 149 | for (dim_t k = 0; k < idims[2]; ++k) { |
| 150 | // Outermost loop handles batch mode |
| 151 | // if input has no data along third dimension |
| 152 | // this loop runs only once |
| 153 | // |
| 154 | // Run only bottom triangle. std::swap swaps with upper triangle |
| 155 | for (dim_t j = 0; j < idims[1]; ++j) { |
| 156 | for (dim_t i = j + 1; i < idims[0]; ++i) { |
| 157 | // calculate array indices based on offsets and strides |
| 158 | // the helper getIdx takes care of indices |
| 159 | const dim_t iIdx = getIdx(istrides, j, i, k, l); |
| 160 | const dim_t oIdx = getIdx(istrides, i, j, k, l); |
| 161 | if (conjugate) { |
| 162 | in[iIdx] = getConjugate(in[iIdx]); |
| 163 | in[oIdx] = getConjugate(in[oIdx]); |
| 164 | std::swap(in[iIdx], in[oIdx]); |
| 165 | } else { |
| 166 | std::swap(in[iIdx], in[oIdx]); |
| 167 | } |
| 168 | } |
| 169 | } |
| 170 | } |
| 171 | } |
| 172 | } |
| 173 | |
| 174 | template<typename T> |
| 175 | void transpose_inplace(Param<T> in, const bool conjugate) { |