File indexing completed on 2025-01-18 09:56:18
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef EIGEN_TRANSPOSE_H
0012 #define EIGEN_TRANSPOSE_H
0013
0014 namespace Eigen {
0015
0016 namespace internal {
0017 template<typename MatrixType>
0018 struct traits<Transpose<MatrixType> > : public traits<MatrixType>
0019 {
0020 typedef typename ref_selector<MatrixType>::type MatrixTypeNested;
0021 typedef typename remove_reference<MatrixTypeNested>::type MatrixTypeNestedPlain;
0022 enum {
0023 RowsAtCompileTime = MatrixType::ColsAtCompileTime,
0024 ColsAtCompileTime = MatrixType::RowsAtCompileTime,
0025 MaxRowsAtCompileTime = MatrixType::MaxColsAtCompileTime,
0026 MaxColsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
0027 FlagsLvalueBit = is_lvalue<MatrixType>::value ? LvalueBit : 0,
0028 Flags0 = traits<MatrixTypeNestedPlain>::Flags & ~(LvalueBit | NestByRefBit),
0029 Flags1 = Flags0 | FlagsLvalueBit,
0030 Flags = Flags1 ^ RowMajorBit,
0031 InnerStrideAtCompileTime = inner_stride_at_compile_time<MatrixType>::ret,
0032 OuterStrideAtCompileTime = outer_stride_at_compile_time<MatrixType>::ret
0033 };
0034 };
0035 }
0036
0037 template<typename MatrixType, typename StorageKind> class TransposeImpl;
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052 template<typename MatrixType> class Transpose
0053 : public TransposeImpl<MatrixType,typename internal::traits<MatrixType>::StorageKind>
0054 {
0055 public:
0056
0057 typedef typename internal::ref_selector<MatrixType>::non_const_type MatrixTypeNested;
0058
0059 typedef typename TransposeImpl<MatrixType,typename internal::traits<MatrixType>::StorageKind>::Base Base;
0060 EIGEN_GENERIC_PUBLIC_INTERFACE(Transpose)
0061 typedef typename internal::remove_all<MatrixType>::type NestedExpression;
0062
0063 EIGEN_DEVICE_FUNC
0064 explicit EIGEN_STRONG_INLINE Transpose(MatrixType& matrix) : m_matrix(matrix) {}
0065
0066 EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Transpose)
0067
0068 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR
0069 Index rows() const EIGEN_NOEXCEPT { return m_matrix.cols(); }
0070 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR
0071 Index cols() const EIGEN_NOEXCEPT { return m_matrix.rows(); }
0072
0073
0074 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
0075 const typename internal::remove_all<MatrixTypeNested>::type&
0076 nestedExpression() const { return m_matrix; }
0077
0078
0079 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
0080 typename internal::remove_reference<MatrixTypeNested>::type&
0081 nestedExpression() { return m_matrix; }
0082
0083
0084 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
0085 void resize(Index nrows, Index ncols) {
0086 m_matrix.resize(ncols,nrows);
0087 }
0088
0089 protected:
0090 typename internal::ref_selector<MatrixType>::non_const_type m_matrix;
0091 };
0092
0093 namespace internal {
0094
0095 template<typename MatrixType, bool HasDirectAccess = has_direct_access<MatrixType>::ret>
0096 struct TransposeImpl_base
0097 {
0098 typedef typename dense_xpr_base<Transpose<MatrixType> >::type type;
0099 };
0100
0101 template<typename MatrixType>
0102 struct TransposeImpl_base<MatrixType, false>
0103 {
0104 typedef typename dense_xpr_base<Transpose<MatrixType> >::type type;
0105 };
0106
0107 }
0108
0109
0110 template<typename XprType, typename StorageKind>
0111 class TransposeImpl
0112 : public internal::generic_xpr_base<Transpose<XprType> >::type
0113 {
0114 public:
0115 typedef typename internal::generic_xpr_base<Transpose<XprType> >::type Base;
0116 };
0117
0118 template<typename MatrixType> class TransposeImpl<MatrixType,Dense>
0119 : public internal::TransposeImpl_base<MatrixType>::type
0120 {
0121 public:
0122
0123 typedef typename internal::TransposeImpl_base<MatrixType>::type Base;
0124 using Base::coeffRef;
0125 EIGEN_DENSE_PUBLIC_INTERFACE(Transpose<MatrixType>)
0126 EIGEN_INHERIT_ASSIGNMENT_OPERATORS(TransposeImpl)
0127
0128 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
0129 Index innerStride() const { return derived().nestedExpression().innerStride(); }
0130 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
0131 Index outerStride() const { return derived().nestedExpression().outerStride(); }
0132
0133 typedef typename internal::conditional<
0134 internal::is_lvalue<MatrixType>::value,
0135 Scalar,
0136 const Scalar
0137 >::type ScalarWithConstIfNotLvalue;
0138
0139 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
0140 ScalarWithConstIfNotLvalue* data() { return derived().nestedExpression().data(); }
0141 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
0142 const Scalar* data() const { return derived().nestedExpression().data(); }
0143
0144
0145 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
0146 const Scalar& coeffRef(Index rowId, Index colId) const
0147 {
0148 return derived().nestedExpression().coeffRef(colId, rowId);
0149 }
0150
0151 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
0152 const Scalar& coeffRef(Index index) const
0153 {
0154 return derived().nestedExpression().coeffRef(index);
0155 }
0156 protected:
0157 EIGEN_DEFAULT_EMPTY_CONSTRUCTOR_AND_DESTRUCTOR(TransposeImpl)
0158 };
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179 template<typename Derived>
0180 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
0181 Transpose<Derived>
0182 DenseBase<Derived>::transpose()
0183 {
0184 return TransposeReturnType(derived());
0185 }
0186
0187
0188
0189
0190
0191
0192 template<typename Derived>
0193 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
0194 typename DenseBase<Derived>::ConstTransposeReturnType
0195 DenseBase<Derived>::transpose() const
0196 {
0197 return ConstTransposeReturnType(derived());
0198 }
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219 template<typename Derived>
0220 EIGEN_DEVICE_FUNC inline const typename MatrixBase<Derived>::AdjointReturnType
0221 MatrixBase<Derived>::adjoint() const
0222 {
0223 return AdjointReturnType(this->transpose());
0224 }
0225
0226
0227
0228
0229
0230 namespace internal {
0231
0232 template<typename MatrixType,
0233 bool IsSquare = (MatrixType::RowsAtCompileTime == MatrixType::ColsAtCompileTime) && MatrixType::RowsAtCompileTime!=Dynamic,
0234 bool MatchPacketSize =
0235 (int(MatrixType::RowsAtCompileTime) == int(internal::packet_traits<typename MatrixType::Scalar>::size))
0236 && (internal::evaluator<MatrixType>::Flags&PacketAccessBit) >
0237 struct inplace_transpose_selector;
0238
0239 template<typename MatrixType>
0240 struct inplace_transpose_selector<MatrixType,true,false> {
0241 static void run(MatrixType& m) {
0242 m.matrix().template triangularView<StrictlyUpper>().swap(m.matrix().transpose().template triangularView<StrictlyUpper>());
0243 }
0244 };
0245
0246 template<typename MatrixType>
0247 struct inplace_transpose_selector<MatrixType,true,true> {
0248 static void run(MatrixType& m) {
0249 typedef typename MatrixType::Scalar Scalar;
0250 typedef typename internal::packet_traits<typename MatrixType::Scalar>::type Packet;
0251 const Index PacketSize = internal::packet_traits<Scalar>::size;
0252 const Index Alignment = internal::evaluator<MatrixType>::Alignment;
0253 PacketBlock<Packet> A;
0254 for (Index i=0; i<PacketSize; ++i)
0255 A.packet[i] = m.template packetByOuterInner<Alignment>(i,0);
0256 internal::ptranspose(A);
0257 for (Index i=0; i<PacketSize; ++i)
0258 m.template writePacket<Alignment>(m.rowIndexByOuterInner(i,0), m.colIndexByOuterInner(i,0), A.packet[i]);
0259 }
0260 };
0261
0262
0263 template <typename MatrixType, Index Alignment>
0264 void BlockedInPlaceTranspose(MatrixType& m) {
0265 typedef typename MatrixType::Scalar Scalar;
0266 typedef typename internal::packet_traits<typename MatrixType::Scalar>::type Packet;
0267 const Index PacketSize = internal::packet_traits<Scalar>::size;
0268 eigen_assert(m.rows() == m.cols());
0269 int row_start = 0;
0270 for (; row_start + PacketSize <= m.rows(); row_start += PacketSize) {
0271 for (int col_start = row_start; col_start + PacketSize <= m.cols(); col_start += PacketSize) {
0272 PacketBlock<Packet> A;
0273 if (row_start == col_start) {
0274 for (Index i=0; i<PacketSize; ++i)
0275 A.packet[i] = m.template packetByOuterInner<Alignment>(row_start + i,col_start);
0276 internal::ptranspose(A);
0277 for (Index i=0; i<PacketSize; ++i)
0278 m.template writePacket<Alignment>(m.rowIndexByOuterInner(row_start + i, col_start), m.colIndexByOuterInner(row_start + i,col_start), A.packet[i]);
0279 } else {
0280 PacketBlock<Packet> B;
0281 for (Index i=0; i<PacketSize; ++i) {
0282 A.packet[i] = m.template packetByOuterInner<Alignment>(row_start + i,col_start);
0283 B.packet[i] = m.template packetByOuterInner<Alignment>(col_start + i, row_start);
0284 }
0285 internal::ptranspose(A);
0286 internal::ptranspose(B);
0287 for (Index i=0; i<PacketSize; ++i) {
0288 m.template writePacket<Alignment>(m.rowIndexByOuterInner(row_start + i, col_start), m.colIndexByOuterInner(row_start + i,col_start), B.packet[i]);
0289 m.template writePacket<Alignment>(m.rowIndexByOuterInner(col_start + i, row_start), m.colIndexByOuterInner(col_start + i,row_start), A.packet[i]);
0290 }
0291 }
0292 }
0293 }
0294 for (Index row = row_start; row < m.rows(); ++row) {
0295 m.matrix().row(row).head(row).swap(
0296 m.matrix().col(row).head(row).transpose());
0297 }
0298 }
0299
0300 template<typename MatrixType,bool MatchPacketSize>
0301 struct inplace_transpose_selector<MatrixType,false,MatchPacketSize> {
0302 static void run(MatrixType& m) {
0303 typedef typename MatrixType::Scalar Scalar;
0304 if (m.rows() == m.cols()) {
0305 const Index PacketSize = internal::packet_traits<Scalar>::size;
0306 if (!NumTraits<Scalar>::IsComplex && m.rows() >= PacketSize) {
0307 if ((m.rows() % PacketSize) == 0)
0308 BlockedInPlaceTranspose<MatrixType,internal::evaluator<MatrixType>::Alignment>(m);
0309 else
0310 BlockedInPlaceTranspose<MatrixType,Unaligned>(m);
0311 }
0312 else {
0313 m.matrix().template triangularView<StrictlyUpper>().swap(m.matrix().transpose().template triangularView<StrictlyUpper>());
0314 }
0315 } else {
0316 m = m.transpose().eval();
0317 }
0318 }
0319 };
0320
0321
0322 }
0323
0324
0325
0326
0327
0328
0329
0330
0331
0332
0333
0334
0335
0336
0337
0338
0339
0340
0341
0342
0343 template<typename Derived>
0344 EIGEN_DEVICE_FUNC inline void DenseBase<Derived>::transposeInPlace()
0345 {
0346 eigen_assert((rows() == cols() || (RowsAtCompileTime == Dynamic && ColsAtCompileTime == Dynamic))
0347 && "transposeInPlace() called on a non-square non-resizable matrix");
0348 internal::inplace_transpose_selector<Derived>::run(derived());
0349 }
0350
0351
0352
0353
0354
0355
0356
0357
0358
0359
0360
0361
0362
0363
0364
0365
0366
0367
0368
0369
0370
0371
0372
0373
0374 template<typename Derived>
0375 EIGEN_DEVICE_FUNC inline void MatrixBase<Derived>::adjointInPlace()
0376 {
0377 derived() = adjoint().eval();
0378 }
0379
0380 #ifndef EIGEN_NO_DEBUG
0381
0382
0383
0384 namespace internal {
0385
0386 template<bool DestIsTransposed, typename OtherDerived>
0387 struct check_transpose_aliasing_compile_time_selector
0388 {
0389 enum { ret = bool(blas_traits<OtherDerived>::IsTransposed) != DestIsTransposed };
0390 };
0391
0392 template<bool DestIsTransposed, typename BinOp, typename DerivedA, typename DerivedB>
0393 struct check_transpose_aliasing_compile_time_selector<DestIsTransposed,CwiseBinaryOp<BinOp,DerivedA,DerivedB> >
0394 {
0395 enum { ret = bool(blas_traits<DerivedA>::IsTransposed) != DestIsTransposed
0396 || bool(blas_traits<DerivedB>::IsTransposed) != DestIsTransposed
0397 };
0398 };
0399
0400 template<typename Scalar, bool DestIsTransposed, typename OtherDerived>
0401 struct check_transpose_aliasing_run_time_selector
0402 {
0403 static bool run(const Scalar* dest, const OtherDerived& src)
0404 {
0405 return (bool(blas_traits<OtherDerived>::IsTransposed) != DestIsTransposed) && (dest!=0 && dest==(const Scalar*)extract_data(src));
0406 }
0407 };
0408
0409 template<typename Scalar, bool DestIsTransposed, typename BinOp, typename DerivedA, typename DerivedB>
0410 struct check_transpose_aliasing_run_time_selector<Scalar,DestIsTransposed,CwiseBinaryOp<BinOp,DerivedA,DerivedB> >
0411 {
0412 static bool run(const Scalar* dest, const CwiseBinaryOp<BinOp,DerivedA,DerivedB>& src)
0413 {
0414 return ((blas_traits<DerivedA>::IsTransposed != DestIsTransposed) && (dest!=0 && dest==(const Scalar*)extract_data(src.lhs())))
0415 || ((blas_traits<DerivedB>::IsTransposed != DestIsTransposed) && (dest!=0 && dest==(const Scalar*)extract_data(src.rhs())));
0416 }
0417 };
0418
0419
0420
0421
0422
0423
0424
0425 template<typename Derived, typename OtherDerived,
0426 bool MightHaveTransposeAliasing
0427 = check_transpose_aliasing_compile_time_selector
0428 <blas_traits<Derived>::IsTransposed,OtherDerived>::ret
0429 >
0430 struct checkTransposeAliasing_impl
0431 {
0432 static void run(const Derived& dst, const OtherDerived& other)
0433 {
0434 eigen_assert((!check_transpose_aliasing_run_time_selector
0435 <typename Derived::Scalar,blas_traits<Derived>::IsTransposed,OtherDerived>
0436 ::run(extract_data(dst), other))
0437 && "aliasing detected during transposition, use transposeInPlace() "
0438 "or evaluate the rhs into a temporary using .eval()");
0439
0440 }
0441 };
0442
0443 template<typename Derived, typename OtherDerived>
0444 struct checkTransposeAliasing_impl<Derived, OtherDerived, false>
0445 {
0446 static void run(const Derived&, const OtherDerived&)
0447 {
0448 }
0449 };
0450
0451 template<typename Dst, typename Src>
0452 void check_for_aliasing(const Dst &dst, const Src &src)
0453 {
0454 if((!Dst::IsVectorAtCompileTime) && dst.rows()>1 && dst.cols()>1)
0455 internal::checkTransposeAliasing_impl<Dst, Src>::run(dst, src);
0456 }
0457
0458 }
0459
0460 #endif
0461
0462 }
0463
0464 #endif