| 95 | } |
| 96 | |
| 97 | void square64::transpose(int n_rows, int n_cols) |
| 98 | { |
| 99 | #ifdef DEBUG_TRANS |
| 100 | cout << "transpose" << endl; |
| 101 | print(); |
| 102 | #endif |
| 103 | |
| 104 | assert(n_rows <= 64); |
| 105 | assert(n_cols <= 64); |
| 106 | |
| 107 | #ifndef __AVX2__ |
| 108 | square128 tmp2; |
| 109 | tmp2.set_zero(); |
| 110 | for (int i = 0; i < n_rows; i++) |
| 111 | tmp2.rows[i] = _mm_cvtsi64_si128(rows[i]); |
| 112 | tmp2.transpose(); |
| 113 | *this = {}; |
| 114 | for (int i = 0; i < n_cols; i++) |
| 115 | rows[i] = _mm_cvtsi128_si64(tmp2.rows[i]); |
| 116 | return; |
| 117 | #endif |
| 118 | |
| 119 | square64 tmp = *this; |
| 120 | *this = {}; |
| 121 | |
| 122 | for (int k = 0; k < DIV_CEIL(n_rows, 32); k++) |
| 123 | { |
| 124 | __m256i x[8], lows[4], highs[4]; |
| 125 | memcpy(x, &tmp.quadrows[8 * k], sizeof(x)); |
| 126 | #ifdef DEBUG_TRANS |
| 127 | for (int j = 0; j < 8; j++) |
| 128 | if (not _mm256_testz_si256(x[j], x[j])) |
| 129 | { |
| 130 | cout << "transpose k " << k << " j " << j << ": "; |
| 131 | for (int i = 0; i < 4; i++) |
| 132 | cout << hex << " " << ((long*)&x[j])[i]; |
| 133 | cout << dec << endl; |
| 134 | } |
| 135 | #endif |
| 136 | for (int chunk_size = 128; chunk_size >= 64; chunk_size /= 2) |
| 137 | { |
| 138 | for (int j = 0; j < 4; j ++) |
| 139 | { |
| 140 | int a, b; |
| 141 | if (chunk_size > 64) |
| 142 | { |
| 143 | a = j; |
| 144 | b = a + 4; |
| 145 | } |
| 146 | else if (chunk_size == 64) |
| 147 | { |
| 148 | a = j / 2 * 2 + j; |
| 149 | b = a + 2; |
| 150 | } |
| 151 | else |
| 152 | { |
| 153 | a = 2 * j; |
| 154 | b = a + 1; |