Eigen  5.0.1-dev+60122df6
 
Loading...
Searching...
No Matches
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
16namespace Eigen {
17
18namespace 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
26template <typename ComplexScalar>
27struct complex_array_access : std::false_type {};
28template <>
29struct complex_array_access<std::complex<float>> : std::true_type {};
30template <>
31struct complex_array_access<std::complex<double>> : std::true_type {};
32template <>
33struct complex_array_access<std::complex<long double>> : std::true_type {};
34
35template <typename Xpr>
36struct 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
63template <typename Xpr>
64struct 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
182template <typename Xpr>
183class 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
218template <typename Xpr>
219EIGEN_DEVICE_FUNC RealView<Xpr>& RealView<Xpr>::operator=(const RealView& other) {
220 internal::call_assignment(*this, other);
221 return *this;
222}
223
224template <typename Xpr>
225template <typename OtherDerived>
226EIGEN_DEVICE_FUNC RealView<Xpr>& RealView<Xpr>::operator=(const RealView<OtherDerived>& other) {
227 internal::call_assignment(*this, other);
228 return *this;
229}
230
231template <typename Xpr>
232template <typename OtherDerived>
233EIGEN_DEVICE_FUNC RealView<Xpr>& RealView<Xpr>::operator=(const DenseBase<OtherDerived>& other) {
234 internal::call_assignment(*this, other.derived());
235 return *this;
236}
237
238template <typename Derived>
239EIGEN_DEVICE_FUNC typename DenseBase<Derived>::RealViewReturnType DenseBase<Derived>::realView() {
240 return RealViewReturnType(derived());
241}
242
243template <typename Derived>
244EIGEN_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
Base class for all dense matrices, vectors, and arrays.
Definition DenseBase.h:44
const unsigned int ActualPacketAccessBit
Definition Constants.h:108
const unsigned int PacketAccessBit
Definition Constants.h:97
const unsigned int LinearAccessBit
Definition Constants.h:133
const unsigned int DirectAccessBit
Definition Constants.h:159
const unsigned int LvalueBit
Definition Constants.h:148
const unsigned int RowMajorBit
Definition Constants.h:70
Namespace containing all symbols from the Eigen library.
Definition B01_Experimental.dox:1
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition Meta.h:82
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_imag_op< typename Derived::Scalar >, const Derived > imag(const Eigen::ArrayBase< Derived > &x)
const int Dynamic
Definition Constants.h:25