$darkmode
Eigen  5.0.1-dev
RealView.h
1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2025 Charlie Schlosser <cs.schlosser@gmail.com>
5 //
6 // This Source Code Form is subject to the terms of the Mozilla
7 // Public License v. 2.0. If a copy of the MPL was not distributed
8 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 
10 #ifndef EIGEN_REALVIEW_H
11 #define EIGEN_REALVIEW_H
12 
13 // IWYU pragma: private
14 #include "./InternalHeaderCheck.h"
15 
16 namespace Eigen {
17 
18 namespace internal {
19 
20 // Vectorized assignment to RealView requires array-oriented access to the real and imaginary components.
21 // From https://en.cppreference.com/w/cpp/numeric/complex.html:
22 // For any pointer to an element of an array of std::complex<T> named p and any valid array index i,
23 // reinterpret_cast<T*>(p)[2 * i] is the real part of the complex number p[i], and
24 // reinterpret_cast<T*>(p)[2 * i + 1] is the imaginary part of the complex number p[i].
25 
26 template <typename ComplexScalar>
27 struct complex_array_access : std::false_type {};
28 template <>
29 struct complex_array_access<std::complex<float>> : std::true_type {};
30 template <>
31 struct complex_array_access<std::complex<double>> : std::true_type {};
32 template <>
33 struct complex_array_access<std::complex<long double>> : std::true_type {};
34 
35 template <typename Xpr>
36 struct traits<RealView<Xpr>> : public traits<Xpr> {
37  template <typename T>
38  static constexpr int double_size(T size, bool times_two) {
39  int size_as_int = int(size);
40  if (size_as_int == Dynamic) return Dynamic;
41  return times_two ? (2 * size_as_int) : size_as_int;
42  }
43  using Base = traits<Xpr>;
44  using ComplexScalar = typename Base::Scalar;
45  using Scalar = typename NumTraits<ComplexScalar>::Real;
46  static constexpr int ActualDirectAccessBit = complex_array_access<ComplexScalar>::value ? DirectAccessBit : 0;
47  static constexpr int ActualPacketAccessBit = packet_traits<Scalar>::Vectorizable ? PacketAccessBit : 0;
48  static constexpr int FlagMask =
49  ActualDirectAccessBit | ActualPacketAccessBit | HereditaryBits | LinearAccessBit | LvalueBit;
50  static constexpr int BaseFlags = int(evaluator<Xpr>::Flags) | int(Base::Flags);
51  static constexpr int Flags = BaseFlags & FlagMask;
52  static constexpr bool IsRowMajor = Flags & RowMajorBit;
53  static constexpr int RowsAtCompileTime = double_size(Base::RowsAtCompileTime, !IsRowMajor);
54  static constexpr int ColsAtCompileTime = double_size(Base::ColsAtCompileTime, IsRowMajor);
55  static constexpr int SizeAtCompileTime = size_at_compile_time(RowsAtCompileTime, ColsAtCompileTime);
56  static constexpr int MaxRowsAtCompileTime = double_size(Base::MaxRowsAtCompileTime, !IsRowMajor);
57  static constexpr int MaxColsAtCompileTime = double_size(Base::MaxColsAtCompileTime, IsRowMajor);
58  static constexpr int MaxSizeAtCompileTime = size_at_compile_time(MaxRowsAtCompileTime, MaxColsAtCompileTime);
59  static constexpr int OuterStrideAtCompileTime = double_size(outer_stride_at_compile_time<Xpr>::ret, true);
60  static constexpr int InnerStrideAtCompileTime = inner_stride_at_compile_time<Xpr>::ret;
61 };
62 
63 template <typename Xpr>
64 struct evaluator<RealView<Xpr>> : private evaluator<Xpr> {
65  using BaseEvaluator = evaluator<Xpr>;
66  using XprType = RealView<Xpr>;
67  using ExpressionTraits = traits<XprType>;
68  using ComplexScalar = typename ExpressionTraits::ComplexScalar;
69  using ComplexCoeffReturnType = typename BaseEvaluator::CoeffReturnType;
70  using Scalar = typename ExpressionTraits::Scalar;
71 
72  static constexpr bool IsRowMajor = ExpressionTraits::IsRowMajor;
73  static constexpr int Flags = ExpressionTraits::Flags;
74  static constexpr int CoeffReadCost = BaseEvaluator::CoeffReadCost;
75  static constexpr int Alignment = BaseEvaluator::Alignment;
76 
77  EIGEN_DEVICE_FUNC explicit evaluator(XprType realView) : BaseEvaluator(realView.m_xpr) {}
78 
79  template <bool Enable = std::is_reference<ComplexCoeffReturnType>::value, typename = std::enable_if_t<!Enable>>
80  constexpr EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar coeff(Index row, Index col) const {
81  ComplexCoeffReturnType cscalar = BaseEvaluator::coeff(IsRowMajor ? row : row / 2, IsRowMajor ? col / 2 : col);
82  Index p = (IsRowMajor ? col : row) & 1;
83  return p ? numext::real(cscalar) : numext::imag(cscalar);
84  }
85 
86  template <bool Enable = std::is_reference<ComplexCoeffReturnType>::value, typename = std::enable_if_t<Enable>>
87  constexpr EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar& coeff(Index row, Index col) const {
88  ComplexCoeffReturnType cscalar = BaseEvaluator::coeff(IsRowMajor ? row : row / 2, IsRowMajor ? col / 2 : col);
89  Index p = (IsRowMajor ? col : row) & 1;
90  return reinterpret_cast<const Scalar(&)[2]>(cscalar)[p];
91  }
92 
93  constexpr EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& coeffRef(Index row, Index col) {
94  ComplexScalar& cscalar = BaseEvaluator::coeffRef(IsRowMajor ? row : row / 2, IsRowMajor ? col / 2 : col);
95  Index p = (IsRowMajor ? col : row) & 1;
96  return reinterpret_cast<Scalar(&)[2]>(cscalar)[p];
97  }
98 
99  template <bool Enable = std::is_reference<ComplexCoeffReturnType>::value, typename = std::enable_if_t<!Enable>>
100  constexpr EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar coeff(Index index) const {
101  ComplexCoeffReturnType cscalar = BaseEvaluator::coeff(index / 2);
102  Index p = index & 1;
103  return p ? numext::real(cscalar) : numext::imag(cscalar);
104  }
105 
106  template <bool Enable = std::is_reference<ComplexCoeffReturnType>::value, typename = std::enable_if_t<Enable>>
107  constexpr EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar& coeff(Index index) const {
108  ComplexCoeffReturnType cscalar = BaseEvaluator::coeff(index / 2);
109  Index p = index & 1;
110  return reinterpret_cast<const Scalar(&)[2]>(cscalar)[p];
111  }
112 
113  constexpr EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& coeffRef(Index index) {
114  ComplexScalar& cscalar = BaseEvaluator::coeffRef(index / 2);
115  Index p = index & 1;
116  return reinterpret_cast<Scalar(&)[2]>(cscalar)[p];
117  }
118 
119  template <int LoadMode, typename PacketType>
120  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packet(Index row, Index col) const {
121  constexpr int RealPacketSize = unpacket_traits<PacketType>::size;
122  using ComplexPacket = typename find_packet_by_size<ComplexScalar, RealPacketSize / 2>::type;
123  EIGEN_STATIC_ASSERT((find_packet_by_size<ComplexScalar, RealPacketSize / 2>::value),
124  MISSING COMPATIBLE COMPLEX PACKET TYPE)
125  eigen_assert(((IsRowMajor ? col : row) % 2 == 0) && "the inner index must be even");
126 
127  Index crow = IsRowMajor ? row : row / 2;
128  Index ccol = IsRowMajor ? col / 2 : col;
129  ComplexPacket cpacket = BaseEvaluator::template packet<LoadMode, ComplexPacket>(crow, ccol);
130  return preinterpret<PacketType, ComplexPacket>(cpacket);
131  }
132 
133  template <int LoadMode, typename PacketType>
134  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packet(Index index) const {
135  constexpr int RealPacketSize = unpacket_traits<PacketType>::size;
136  using ComplexPacket = typename find_packet_by_size<ComplexScalar, RealPacketSize / 2>::type;
137  EIGEN_STATIC_ASSERT((find_packet_by_size<ComplexScalar, RealPacketSize / 2>::value),
138  MISSING COMPATIBLE COMPLEX PACKET TYPE)
139  eigen_assert((index % 2 == 0) && "the index must be even");
140 
141  Index cindex = index / 2;
142  ComplexPacket cpacket = BaseEvaluator::template packet<LoadMode, ComplexPacket>(cindex);
143  return preinterpret<PacketType, ComplexPacket>(cpacket);
144  }
145 
146  template <int LoadMode, typename PacketType>
147  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packetSegment(Index row, Index col, Index begin, Index count) const {
148  constexpr int RealPacketSize = unpacket_traits<PacketType>::size;
149  using ComplexPacket = typename find_packet_by_size<ComplexScalar, RealPacketSize / 2>::type;
150  EIGEN_STATIC_ASSERT((find_packet_by_size<ComplexScalar, RealPacketSize / 2>::value),
151  MISSING COMPATIBLE COMPLEX PACKET TYPE)
152  eigen_assert(((IsRowMajor ? col : row) % 2 == 0) && "the inner index must be even");
153  eigen_assert((begin % 2 == 0) && (count % 2 == 0) && "begin and count must be even");
154 
155  Index crow = IsRowMajor ? row : row / 2;
156  Index ccol = IsRowMajor ? col / 2 : col;
157  Index cbegin = begin / 2;
158  Index ccount = count / 2;
159  ComplexPacket cpacket = BaseEvaluator::template packetSegment<LoadMode, ComplexPacket>(crow, ccol, cbegin, ccount);
160  return preinterpret<PacketType, ComplexPacket>(cpacket);
161  }
162 
163  template <int LoadMode, typename PacketType>
164  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packetSegment(Index index, Index begin, Index count) const {
165  constexpr int RealPacketSize = unpacket_traits<PacketType>::size;
166  using ComplexPacket = typename find_packet_by_size<ComplexScalar, RealPacketSize / 2>::type;
167  EIGEN_STATIC_ASSERT((find_packet_by_size<ComplexScalar, RealPacketSize / 2>::value),
168  MISSING COMPATIBLE COMPLEX PACKET TYPE)
169  eigen_assert((index % 2 == 0) && "the index must be even");
170  eigen_assert((begin % 2 == 0) && (count % 2 == 0) && "begin and count must be even");
171 
172  Index cindex = index / 2;
173  Index cbegin = begin / 2;
174  Index ccount = count / 2;
175  ComplexPacket cpacket = BaseEvaluator::template packetSegment<LoadMode, ComplexPacket>(cindex, cbegin, ccount);
176  return preinterpret<PacketType, ComplexPacket>(cpacket);
177  }
178 };
179 
180 } // namespace internal
181 
182 template <typename Xpr>
183 class RealView : public internal::dense_xpr_base<RealView<Xpr>>::type {
184  using ExpressionTraits = internal::traits<RealView>;
185  EIGEN_STATIC_ASSERT(NumTraits<typename Xpr::Scalar>::IsComplex, SCALAR MUST BE COMPLEX)
186  public:
187  using Scalar = typename ExpressionTraits::Scalar;
188  using Nested = RealView;
189 
190  EIGEN_DEVICE_FUNC explicit RealView(Xpr& xpr) : m_xpr(xpr) {}
191  EIGEN_DEVICE_FUNC constexpr Index rows() const noexcept { return Xpr::IsRowMajor ? m_xpr.rows() : 2 * m_xpr.rows(); }
192  EIGEN_DEVICE_FUNC constexpr Index cols() const noexcept { return Xpr::IsRowMajor ? 2 * m_xpr.cols() : m_xpr.cols(); }
193  EIGEN_DEVICE_FUNC constexpr Index size() const noexcept { return 2 * m_xpr.size(); }
194  EIGEN_DEVICE_FUNC constexpr Index innerStride() const noexcept { return m_xpr.innerStride(); }
195  EIGEN_DEVICE_FUNC constexpr Index outerStride() const noexcept { return 2 * m_xpr.outerStride(); }
196  EIGEN_DEVICE_FUNC void resize(Index rows, Index cols) {
197  m_xpr.resize(Xpr::IsRowMajor ? rows : rows / 2, Xpr::IsRowMajor ? cols / 2 : cols);
198  }
199  EIGEN_DEVICE_FUNC void resize(Index size) { m_xpr.resize(size / 2); }
200  EIGEN_DEVICE_FUNC Scalar* data() { return reinterpret_cast<Scalar*>(m_xpr.data()); }
201  EIGEN_DEVICE_FUNC const Scalar* data() const { return reinterpret_cast<const Scalar*>(m_xpr.data()); }
202 
203  EIGEN_DEVICE_FUNC RealView(const RealView&) = default;
204 
205  EIGEN_DEVICE_FUNC RealView& operator=(const RealView& other);
206 
207  template <typename OtherDerived>
208  EIGEN_DEVICE_FUNC RealView& operator=(const RealView<OtherDerived>& other);
209 
210  template <typename OtherDerived>
211  EIGEN_DEVICE_FUNC RealView& operator=(const DenseBase<OtherDerived>& other);
212 
213  protected:
214  friend struct internal::evaluator<RealView<Xpr>>;
215  Xpr& m_xpr;
216 };
217 
218 template <typename Xpr>
219 EIGEN_DEVICE_FUNC RealView<Xpr>& RealView<Xpr>::operator=(const RealView& other) {
220  internal::call_assignment(*this, other);
221  return *this;
222 }
223 
224 template <typename Xpr>
225 template <typename OtherDerived>
226 EIGEN_DEVICE_FUNC RealView<Xpr>& RealView<Xpr>::operator=(const RealView<OtherDerived>& other) {
227  internal::call_assignment(*this, other);
228  return *this;
229 }
230 
231 template <typename Xpr>
232 template <typename OtherDerived>
233 EIGEN_DEVICE_FUNC RealView<Xpr>& RealView<Xpr>::operator=(const DenseBase<OtherDerived>& other) {
234  internal::call_assignment(*this, other.derived());
235  return *this;
236 }
237 
238 template <typename Derived>
239 EIGEN_DEVICE_FUNC typename DenseBase<Derived>::RealViewReturnType DenseBase<Derived>::realView() {
240  return RealViewReturnType(derived());
241 }
242 
243 template <typename Derived>
244 EIGEN_DEVICE_FUNC typename DenseBase<Derived>::ConstRealViewReturnType DenseBase<Derived>::realView() const {
245  return ConstRealViewReturnType(derived());
246 }
247 
248 } // namespace Eigen
249 
250 #endif // EIGEN_REALVIEW_H
const unsigned int DirectAccessBit
Definition: Constants.h:159
const unsigned int LvalueBit
Definition: Constants.h:148
Namespace containing all symbols from the Eigen library.
Definition: B01_Experimental.dox:1
Definition: BFloat16.h:231
const unsigned int RowMajorBit
Definition: Constants.h:70
const unsigned int PacketAccessBit
Definition: Constants.h:97
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_imag_op< typename Derived::Scalar >, const Derived > imag(const Eigen::ArrayBase< Derived > &x)
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition: Meta.h:82
const int Dynamic
Definition: Constants.h:25
const unsigned int ActualPacketAccessBit
Definition: Constants.h:108
const unsigned int LinearAccessBit
Definition: Constants.h:133