199template <
typename Derived>
201 return AdjointReturnType(this->
transpose());
210template <
typename MatrixType,
211 bool IsSquare = (MatrixType::RowsAtCompileTime == MatrixType::ColsAtCompileTime) &&
212 MatrixType::RowsAtCompileTime != Dynamic,
213 bool MatchPacketSize =
214 (
int(MatrixType::RowsAtCompileTime) ==
int(internal::packet_traits<typename MatrixType::Scalar>::size)) &&
216struct inplace_transpose_selector;
218template <
typename MatrixType>
219struct inplace_transpose_selector<MatrixType, true, false> {
220 static void run(MatrixType& m) {
221 m.matrix().template triangularView<StrictlyUpper>().swap(
222 m.matrix().transpose().template triangularView<StrictlyUpper>());
226template <
typename MatrixType>
227struct inplace_transpose_selector<MatrixType, true, true> {
228 static void run(MatrixType& m) {
229 using Scalar =
typename MatrixType::Scalar;
230 using Packet =
typename internal::packet_traits<typename MatrixType::Scalar>::type;
231 const Index PacketSize = internal::packet_traits<Scalar>::size;
232 const Index Alignment = internal::evaluator<MatrixType>::Alignment;
233 PacketBlock<Packet> A;
234 for (Index i = 0; i < PacketSize; ++i) A.packet[i] = m.template packetByOuterInner<Alignment>(i, 0);
235 internal::ptranspose(A);
236 for (Index i = 0; i < PacketSize; ++i)
237 m.template writePacket<Alignment>(m.rowIndexByOuterInner(i, 0), m.colIndexByOuterInner(i, 0), A.packet[i]);
241template <
typename MatrixType, Index Alignment>
242void BlockedInPlaceTranspose(MatrixType& m) {
243 using Scalar =
typename MatrixType::Scalar;
244 using Packet =
typename internal::packet_traits<typename MatrixType::Scalar>::type;
245 const Index PacketSize = internal::packet_traits<Scalar>::size;
246 eigen_assert(m.rows() == m.cols());
248 for (; row_start + PacketSize <= m.rows(); row_start += PacketSize) {
249 for (
int col_start = row_start; col_start + PacketSize <= m.cols(); col_start += PacketSize) {
250 PacketBlock<Packet> A;
251 if (row_start == col_start) {
252 for (Index i = 0; i < PacketSize; ++i)
253 A.packet[i] = m.template packetByOuterInner<Alignment>(row_start + i, col_start);
254 internal::ptranspose(A);
255 for (Index i = 0; i < PacketSize; ++i)
256 m.template writePacket<Alignment>(m.rowIndexByOuterInner(row_start + i, col_start),
257 m.colIndexByOuterInner(row_start + i, col_start), A.packet[i]);
259 PacketBlock<Packet> B;
260 for (Index i = 0; i < PacketSize; ++i) {
261 A.packet[i] = m.template packetByOuterInner<Alignment>(row_start + i, col_start);
262 B.packet[i] = m.template packetByOuterInner<Alignment>(col_start + i, row_start);
264 internal::ptranspose(A);
265 internal::ptranspose(B);
266 for (Index i = 0; i < PacketSize; ++i) {
267 m.template writePacket<Alignment>(m.rowIndexByOuterInner(row_start + i, col_start),
268 m.colIndexByOuterInner(row_start + i, col_start), B.packet[i]);
269 m.template writePacket<Alignment>(m.rowIndexByOuterInner(col_start + i, row_start),
270 m.colIndexByOuterInner(col_start + i, row_start), A.packet[i]);
275 for (Index row = row_start; row < m.rows(); ++row) {
276 m.matrix().row(row).head(row).swap(m.matrix().col(row).head(row).transpose());
280template <
typename MatrixType,
bool MatchPacketSize>
281struct inplace_transpose_selector<MatrixType, false, MatchPacketSize> {
282 static void run(MatrixType& m) {
283 using Scalar =
typename MatrixType::Scalar;
284 if (m.rows() == m.cols()) {
285 const Index PacketSize = internal::packet_traits<Scalar>::size;
286 EIGEN_IF_CONSTEXPR (!NumTraits<Scalar>::IsComplex && (internal::evaluator<MatrixType>::Flags &
PacketAccessBit)) {
287 if (m.rows() >= PacketSize) {
288 if ((m.rows() % PacketSize) == 0)
289 BlockedInPlaceTranspose<MatrixType, internal::evaluator<MatrixType>::Alignment>(m);
291 BlockedInPlaceTranspose<MatrixType, Unaligned>(m);
295 m.matrix().template triangularView<StrictlyUpper>().swap(
296 m.matrix().transpose().template triangularView<StrictlyUpper>());
298 m = m.transpose().eval();
324template <
typename Derived>
327 "transposeInPlace() called on a non-square non-resizable matrix");
328 internal::inplace_transpose_selector<Derived>::run(derived());
354template <
typename Derived>
359#ifndef EIGEN_NO_DEBUG
365template <
bool DestIsTransposed,
typename OtherDerived>
366struct check_transpose_aliasing_compile_time_selector
367 : bool_constant<bool(blas_traits<OtherDerived>::IsTransposed) != DestIsTransposed> {};
369template <
bool DestIsTransposed,
typename BinOp,
typename DerivedA,
typename DerivedB>
370struct check_transpose_aliasing_compile_time_selector<DestIsTransposed, CwiseBinaryOp<BinOp, DerivedA, DerivedB>>
371 : bool_constant<bool(blas_traits<DerivedA>::IsTransposed) != DestIsTransposed ||
372 bool(blas_traits<DerivedB>::IsTransposed) != DestIsTransposed> {};
374template <
typename Scalar,
bool DestIsTransposed,
typename OtherDerived>
375struct check_transpose_aliasing_run_time_selector {
376 EIGEN_DEVICE_FUNC
static bool run(
const Scalar* dest,
const OtherDerived& src) {
377 return (
bool(blas_traits<OtherDerived>::IsTransposed) != DestIsTransposed) &&
378 (dest != 0 && dest == (
const Scalar*)extract_data(src));
382template <
typename Scalar,
bool DestIsTransposed,
typename BinOp,
typename DerivedA,
typename DerivedB>
383struct check_transpose_aliasing_run_time_selector<Scalar, DestIsTransposed, CwiseBinaryOp<BinOp, DerivedA, DerivedB>> {
384 EIGEN_DEVICE_FUNC
static bool run(
const Scalar* dest,
const CwiseBinaryOp<BinOp, DerivedA, DerivedB>& src) {
385 return ((blas_traits<DerivedA>::IsTransposed != DestIsTransposed) &&
386 (dest != 0 && dest == (
const Scalar*)extract_data(src.lhs()))) ||
387 ((blas_traits<DerivedB>::IsTransposed != DestIsTransposed) &&
388 (dest != 0 && dest == (
const Scalar*)extract_data(src.rhs())));
398template <
typename Derived,
typename OtherDerived,
399 bool MightHaveTransposeAliasing =
400 check_transpose_aliasing_compile_time_selector<blas_traits<Derived>::IsTransposed, OtherDerived>::value>
401struct checkTransposeAliasing_impl {
402 EIGEN_DEVICE_FUNC
static void run(
const Derived& dst,
const OtherDerived& other) {
404 (!check_transpose_aliasing_run_time_selector<
typename Derived::Scalar, blas_traits<Derived>::IsTransposed,
405 OtherDerived>::run(extract_data(dst), other)) &&
406 "aliasing detected during transposition, use transposeInPlace() "
407 "or evaluate the rhs into a temporary using .eval()");
411template <
typename Derived,
typename OtherDerived>
412struct checkTransposeAliasing_impl<Derived, OtherDerived, false> {
413 EIGEN_DEVICE_FUNC
static void run(
const Derived&,
const OtherDerived&) {}
416template <
typename Dst,
typename Src>
417EIGEN_DEVICE_FUNC
inline void check_for_aliasing(
const Dst& dst,
const Src& src) {
418 EIGEN_IF_CONSTEXPR (!Dst::IsVectorAtCompileTime) {
419 if (dst.rows() > 1 && dst.cols() > 1) internal::checkTransposeAliasing_impl<Dst, Src>::run(dst, src);