10#ifndef EIGEN_BLASUTIL_H
11#define EIGEN_BLASUTIL_H
17#include "../InternalHeaderCheck.h"
24template <
typename LhsScalar,
typename RhsScalar,
typename Index,
typename DataMapper,
int mr,
int nr,
25 bool ConjugateLhs =
false,
bool ConjugateRhs =
false>
28template <
typename Scalar,
typename Index,
typename DataMapper,
int nr,
int StorageOrder,
bool Conjugate =
false,
29 bool PanelMode =
false>
32template <
typename Scalar,
typename Index,
typename DataMapper,
int Pack1,
int Pack2,
typename Packet,
int StorageOrder,
33 bool Conjugate =
false,
bool PanelMode =
false>
36template <
typename Index,
typename LhsScalar,
int LhsStorageOrder,
bool ConjugateLhs,
typename RhsScalar,
37 int RhsStorageOrder,
bool ConjugateRhs,
int ResStorageOrder,
int ResInnerStride>
38struct general_matrix_matrix_product;
40template <
typename Index,
typename LhsScalar,
typename LhsMapper,
int LhsStorageOrder,
bool ConjugateLhs,
41 typename RhsScalar,
typename RhsMapper,
bool ConjugateRhs,
int Version = Specialized>
42struct general_matrix_vector_product;
44template <
typename From,
typename To>
46 EIGEN_DEVICE_FUNC
static EIGEN_STRONG_INLINE To run(
const From& x) {
return To(x); }
49template <
typename Scalar>
50struct get_factor<Scalar, typename NumTraits<Scalar>::Real> {
51 EIGEN_DEVICE_FUNC
static EIGEN_STRONG_INLINE
typename NumTraits<Scalar>::Real run(
const Scalar& x) {
52 return numext::real(x);
56template <
typename Scalar,
typename Index>
57class BlasVectorMapper {
59 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE BlasVectorMapper(Scalar* data) : m_data(data) {}
61 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Scalar operator()(Index i)
const {
return m_data[i]; }
62 template <
typename Packet,
int AlignmentType>
63 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet load(Index i)
const {
64 return ploadt<Packet, AlignmentType>(m_data + i);
67 template <
typename Packet>
68 EIGEN_DEVICE_FUNC
bool aligned(Index i)
const {
69 return (std::uintptr_t(m_data + i) %
sizeof(Packet)) == 0;
76template <
typename Scalar,
typename Index,
int AlignmentType,
int Incr = 1>
77class BlasLinearMapper;
79template <
typename Scalar,
typename Index,
int AlignmentType>
82 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE BlasLinearMapper(Scalar* data, Index incr = 1) : m_data(data) {
83 EIGEN_ONLY_USED_FOR_DEBUG(incr);
84 eigen_assert(incr == 1);
87 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
void prefetch(Index i)
const { internal::prefetch(&
operator()(i)); }
89 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Scalar& operator()(Index i)
const {
return m_data[i]; }
91 template <
typename PacketType>
92 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE PacketType loadPacket(Index i)
const {
93 return ploadt<PacketType, AlignmentType>(m_data + i);
96 template <
typename PacketType>
97 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE PacketType loadPacketPartial(Index i, Index n, Index offset = 0)
const {
98 return ploadt_partial<PacketType, AlignmentType>(m_data + i, n, offset);
101 template <
typename PacketType,
int AlignmentT>
102 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE PacketType load(Index i)
const {
103 return ploadt<PacketType, AlignmentT>(m_data + i);
106 template <
typename PacketType>
107 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
void storePacket(Index i,
const PacketType& p)
const {
108 pstoret<Scalar, PacketType, AlignmentType>(m_data + i, p);
111 template <
typename PacketType>
112 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
void storePacketPartial(Index i,
const PacketType& p, Index n,
113 Index offset = 0)
const {
114 pstoret_partial<Scalar, PacketType, AlignmentType>(m_data + i, p, n, offset);
122template <
typename Scalar,
typename Index,
int StorageOrder,
int AlignmentType = Unaligned,
int Incr = 1>
123class blas_data_mapper;
129template <
typename Index,
typename Scalar,
typename Packet,
int n,
int idx,
int StorageOrder>
130struct PacketBlockManagement {
131 PacketBlockManagement<
Index, Scalar, Packet, n, idx - 1, StorageOrder> pbm;
132 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
void store(Scalar* to,
const Index stride, Index i, Index j,
133 const PacketBlock<Packet, n>& block)
const {
134 pbm.store(to, stride, i, j, block);
135 pstoreu<Scalar>(to + i + (j + idx) * stride, block.packet[idx]);
140template <
typename Index,
typename Scalar,
typename Packet,
int n,
int idx>
141struct PacketBlockManagement<Index, Scalar, Packet, n, idx,
RowMajor> {
142 PacketBlockManagement<
Index, Scalar, Packet, n, idx - 1,
RowMajor> pbm;
143 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
void store(Scalar* to,
const Index stride, Index i, Index j,
144 const PacketBlock<Packet, n>& block)
const {
145 pbm.store(to, stride, i, j, block);
146 pstoreu<Scalar>(to + j + (i + idx) * stride, block.packet[idx]);
150template <
typename Index,
typename Scalar,
typename Packet,
int n,
int StorageOrder>
151struct PacketBlockManagement<Index, Scalar, Packet, n, -1, StorageOrder> {
152 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
void store(Scalar* to,
const Index stride, Index i, Index j,
153 const PacketBlock<Packet, n>& block)
const {
154 EIGEN_UNUSED_VARIABLE(to);
155 EIGEN_UNUSED_VARIABLE(stride);
156 EIGEN_UNUSED_VARIABLE(i);
157 EIGEN_UNUSED_VARIABLE(j);
158 EIGEN_UNUSED_VARIABLE(block);
162template <
typename Index,
typename Scalar,
typename Packet,
int n>
163struct PacketBlockManagement<Index, Scalar, Packet, n, -1,
RowMajor> {
164 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
void store(Scalar* to,
const Index stride, Index i, Index j,
165 const PacketBlock<Packet, n>& block)
const {
166 EIGEN_UNUSED_VARIABLE(to);
167 EIGEN_UNUSED_VARIABLE(stride);
168 EIGEN_UNUSED_VARIABLE(i);
169 EIGEN_UNUSED_VARIABLE(j);
170 EIGEN_UNUSED_VARIABLE(block);
174template <
typename Scalar,
typename Index,
int StorageOrder,
int AlignmentType>
175class blas_data_mapper<Scalar, Index, StorageOrder,
AlignmentType, 1> {
177 typedef BlasLinearMapper<Scalar, Index, AlignmentType> LinearMapper;
178 typedef blas_data_mapper<Scalar, Index, StorageOrder, AlignmentType> SubMapper;
179 typedef BlasVectorMapper<Scalar, Index> VectorMapper;
181 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE blas_data_mapper(Scalar* data, Index stride, Index incr = 1)
182 : m_data(data), m_stride(stride) {
183 EIGEN_ONLY_USED_FOR_DEBUG(incr);
184 eigen_assert(incr == 1);
187 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE SubMapper getSubMapper(Index i, Index j)
const {
188 return SubMapper(&
operator()(i, j), m_stride);
191 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE LinearMapper getLinearMapper(Index i, Index j)
const {
192 return LinearMapper(&
operator()(i, j));
195 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE VectorMapper getVectorMapper(Index i, Index j)
const {
196 return VectorMapper(&
operator()(i, j));
199 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
void prefetch(Index i, Index j)
const { internal::prefetch(&
operator()(i, j)); }
201 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Scalar& operator()(Index i, Index j)
const {
202 return m_data[StorageOrder ==
RowMajor ? j + i * m_stride : i + j * m_stride];
205 template <
typename PacketType>
206 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE PacketType loadPacket(Index i, Index j)
const {
207 return ploadt<PacketType, AlignmentType>(&
operator()(i, j));
210 template <
typename PacketType>
211 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE PacketType loadPacketPartial(Index i, Index j, Index n,
212 Index offset = 0)
const {
213 return ploadt_partial<PacketType, AlignmentType>(&
operator()(i, j), n, offset);
216 template <
typename PacketT,
int AlignmentT>
217 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE PacketT load(Index i, Index j)
const {
218 return ploadt<PacketT, AlignmentT>(&
operator()(i, j));
221 template <
typename PacketType>
222 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
void storePacket(Index i, Index j,
const PacketType& p)
const {
223 pstoret<Scalar, PacketType, AlignmentType>(&
operator()(i, j), p);
226 template <
typename PacketType>
227 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
void storePacketPartial(Index i, Index j,
const PacketType& p, Index n,
228 Index offset = 0)
const {
229 pstoret_partial<Scalar, PacketType, AlignmentType>(&
operator()(i, j), p, n, offset);
232 template <
typename SubPacket>
233 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
void scatterPacket(Index i, Index j,
const SubPacket& p)
const {
234 pscatter<Scalar, SubPacket>(&
operator()(i, j), p, m_stride);
237 template <
typename SubPacket>
238 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE SubPacket gatherPacket(Index i, Index j)
const {
239 return pgather<Scalar, SubPacket>(&
operator()(i, j), m_stride);
242 EIGEN_DEVICE_FUNC
const Index stride()
const {
return m_stride; }
243 EIGEN_DEVICE_FUNC
const Index incr()
const {
return 1; }
244 EIGEN_DEVICE_FUNC
const Scalar* data()
const {
return m_data; }
246 EIGEN_DEVICE_FUNC Index firstAligned(Index size)
const {
247 if (std::uintptr_t(m_data) %
sizeof(Scalar)) {
250 return internal::first_default_aligned(m_data, size);
253 template <
typename SubPacket,
int n>
254 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
void storePacketBlock(Index i, Index j,
255 const PacketBlock<SubPacket, n>& block)
const {
256 PacketBlockManagement<
Index, Scalar, SubPacket, n, n - 1, StorageOrder> pbm;
257 pbm.store(m_data, m_stride, i, j, block);
261 Scalar* EIGEN_RESTRICT m_data;
262 const Index m_stride;
268template <
typename Scalar,
typename Index,
int AlignmentType,
int Incr>
269class BlasLinearMapper {
271 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE BlasLinearMapper(Scalar* data, Index incr) : m_data(data), m_incr(incr) {}
273 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
void prefetch(
int i)
const { internal::prefetch(&
operator()(i)); }
275 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Scalar& operator()(Index i)
const {
return m_data[i * m_incr.value()]; }
277 template <
typename PacketType>
278 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE PacketType loadPacket(Index i)
const {
279 return pgather<Scalar, PacketType>(m_data + i * m_incr.value(), m_incr.value());
282 template <
typename PacketType>
283 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE PacketType loadPacketPartial(Index i, Index n, Index = 0)
const {
284 return pgather_partial<Scalar, PacketType>(m_data + i * m_incr.value(), m_incr.value(), n);
287 template <
typename PacketType>
288 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
void storePacket(Index i,
const PacketType& p)
const {
289 pscatter<Scalar, PacketType>(m_data + i * m_incr.value(), p, m_incr.value());
292 template <
typename PacketType>
293 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
void storePacketPartial(Index i,
const PacketType& p, Index n,
295 pscatter_partial<Scalar, PacketType>(m_data + i * m_incr.value(), p, m_incr.value(), n);
300 const internal::variable_if_dynamic<Index, Incr> m_incr;
303template <
typename Scalar,
typename Index,
int StorageOrder,
int AlignmentType,
int Incr>
304class blas_data_mapper {
306 typedef BlasLinearMapper<Scalar, Index, AlignmentType, Incr> LinearMapper;
307 typedef blas_data_mapper SubMapper;
309 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE blas_data_mapper(Scalar* data, Index stride, Index incr)
310 : m_data(data), m_stride(stride), m_incr(incr) {}
312 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE SubMapper getSubMapper(Index i, Index j)
const {
313 return SubMapper(&
operator()(i, j), m_stride, m_incr.value());
316 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE LinearMapper getLinearMapper(Index i, Index j)
const {
317 return LinearMapper(&
operator()(i, j), m_incr.value());
320 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
void prefetch(Index i, Index j)
const { internal::prefetch(&
operator()(i, j)); }
322 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Scalar& operator()(Index i, Index j)
const {
323 return m_data[StorageOrder ==
RowMajor ? j * m_incr.value() + i * m_stride : i * m_incr.value() + j * m_stride];
326 template <
typename PacketType>
327 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE PacketType loadPacket(Index i, Index j)
const {
328 return pgather<Scalar, PacketType>(&
operator()(i, j), m_incr.value());
331 template <
typename PacketType>
332 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE PacketType loadPacketPartial(Index i, Index j, Index n,
334 return pgather_partial<Scalar, PacketType>(&
operator()(i, j), m_incr.value(), n);
337 template <
typename PacketT,
int AlignmentT>
338 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE PacketT load(Index i, Index j)
const {
339 return pgather<Scalar, PacketT>(&
operator()(i, j), m_incr.value());
342 template <
typename PacketType>
343 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
void storePacket(Index i, Index j,
const PacketType& p)
const {
344 pscatter<Scalar, PacketType>(&
operator()(i, j), p, m_incr.value());
347 template <
typename PacketType>
348 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
void storePacketPartial(Index i, Index j,
const PacketType& p, Index n,
350 pscatter_partial<Scalar, PacketType>(&
operator()(i, j), p, m_incr.value(), n);
353 template <
typename SubPacket>
354 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
void scatterPacket(Index i, Index j,
const SubPacket& p)
const {
355 pscatter<Scalar, SubPacket>(&
operator()(i, j), p, m_stride);
358 template <
typename SubPacket>
359 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE SubPacket gatherPacket(Index i, Index j)
const {
360 return pgather<Scalar, SubPacket>(&
operator()(i, j), m_stride);
365 template <
typename SubPacket,
typename Scalar_,
int n,
int idx>
366 struct storePacketBlock_helper {
367 storePacketBlock_helper<SubPacket, Scalar_, n, idx - 1> spbh;
368 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
void store(
369 const blas_data_mapper<Scalar, Index, StorageOrder, AlignmentType, Incr>* sup, Index i, Index j,
370 const PacketBlock<SubPacket, n>& block)
const {
371 spbh.store(sup, i, j, block);
372 sup->template storePacket<SubPacket>(i, j + idx, block.packet[idx]);
376 template <
typename SubPacket,
int n,
int idx>
377 struct storePacketBlock_helper<SubPacket, std::complex<float>, n, idx> {
378 storePacketBlock_helper<SubPacket, std::complex<float>, n, idx - 1> spbh;
379 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
void store(
380 const blas_data_mapper<Scalar, Index, StorageOrder, AlignmentType, Incr>* sup, Index i, Index j,
381 const PacketBlock<SubPacket, n>& block)
const {
382 spbh.store(sup, i, j, block);
383 sup->template storePacket<SubPacket>(i, j + idx, block.packet[idx]);
387 template <
typename SubPacket,
int n,
int idx>
388 struct storePacketBlock_helper<SubPacket, std::complex<double>, n, idx> {
389 storePacketBlock_helper<SubPacket, std::complex<double>, n, idx - 1> spbh;
390 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
void store(
391 const blas_data_mapper<Scalar, Index, StorageOrder, AlignmentType, Incr>* sup, Index i, Index j,
392 const PacketBlock<SubPacket, n>& block)
const {
393 spbh.store(sup, i, j, block);
394 for (
int l = 0; l < unpacket_traits<SubPacket>::size; l++) {
395 std::complex<double>* v = &sup->operator()(i + l, j + idx);
396 v->real(block.packet[idx].v[2 * l + 0]);
397 v->imag(block.packet[idx].v[2 * l + 1]);
402 template <
typename SubPacket,
typename Scalar_,
int n>
403 struct storePacketBlock_helper<SubPacket, Scalar_, n, -1> {
404 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
void store(
405 const blas_data_mapper<Scalar, Index, StorageOrder, AlignmentType, Incr>*, Index, Index,
406 const PacketBlock<SubPacket, n>&)
const {}
409 template <
typename SubPacket,
int n>
410 struct storePacketBlock_helper<SubPacket, std::complex<float>, n, -1> {
411 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
void store(
412 const blas_data_mapper<Scalar, Index, StorageOrder, AlignmentType, Incr>*, Index, Index,
413 const PacketBlock<SubPacket, n>&)
const {}
416 template <
typename SubPacket,
int n>
417 struct storePacketBlock_helper<SubPacket, std::complex<double>, n, -1> {
418 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
void store(
419 const blas_data_mapper<Scalar, Index, StorageOrder, AlignmentType, Incr>*, Index, Index,
420 const PacketBlock<SubPacket, n>&)
const {}
424 template <
typename SubPacket,
int n>
425 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
void storePacketBlock(Index i, Index j,
426 const PacketBlock<SubPacket, n>& block)
const {
427 storePacketBlock_helper<SubPacket, Scalar, n, n - 1> spb;
428 spb.store(
this, i, j, block);
431 EIGEN_DEVICE_FUNC
const Index stride()
const {
return m_stride; }
432 EIGEN_DEVICE_FUNC
const Index incr()
const {
return m_incr.value(); }
433 EIGEN_DEVICE_FUNC Scalar* data()
const {
return m_data; }
436 Scalar* EIGEN_RESTRICT m_data;
437 const Index m_stride;
438 const internal::variable_if_dynamic<Index, Incr> m_incr;
442template <
typename Scalar,
typename Index,
int StorageOrder>
443class const_blas_data_mapper :
public blas_data_mapper<const Scalar, Index, StorageOrder> {
445 typedef const_blas_data_mapper<Scalar, Index, StorageOrder> SubMapper;
447 EIGEN_ALWAYS_INLINE const_blas_data_mapper(
const Scalar* data, Index stride)
448 : blas_data_mapper<const Scalar, Index, StorageOrder>(data, stride) {}
450 EIGEN_ALWAYS_INLINE SubMapper getSubMapper(Index i, Index j)
const {
451 return SubMapper(&(this->
operator()(i, j)), this->m_stride);
458template <
typename XprType>
460 typedef typename traits<XprType>::Scalar Scalar;
461 typedef const XprType& ExtractType;
462 typedef XprType ExtractType_;
464 IsComplex = NumTraits<Scalar>::IsComplex,
465 IsTransposed =
false,
466 NeedToConjugate =
false,
467 HasUsableDirectAccess =
469 (
bool(XprType::IsVectorAtCompileTime) || int(inner_stride_at_compile_time<XprType>::ret) == 1))
472 HasScalarFactor =
false
474 typedef std::conditional_t<bool(HasUsableDirectAccess), ExtractType,
typename ExtractType_::PlainObject>
475 DirectLinearAccessType;
476 EIGEN_DEVICE_FUNC
static inline EIGEN_DEVICE_FUNC ExtractType extract(
const XprType& x) {
return x; }
477 EIGEN_DEVICE_FUNC
static inline EIGEN_DEVICE_FUNC
const Scalar extractScalarFactor(
const XprType&) {
483template <
typename Scalar,
typename NestedXpr>
484struct blas_traits<CwiseUnaryOp<scalar_conjugate_op<Scalar>, NestedXpr> > : blas_traits<NestedXpr> {
485 typedef blas_traits<NestedXpr> Base;
486 typedef CwiseUnaryOp<scalar_conjugate_op<Scalar>, NestedXpr> XprType;
487 typedef typename Base::ExtractType ExtractType;
489 enum { IsComplex = NumTraits<Scalar>::IsComplex, NeedToConjugate = Base::NeedToConjugate ? 0 : IsComplex };
490 EIGEN_DEVICE_FUNC
static inline ExtractType extract(
const XprType& x) {
return Base::extract(x.nestedExpression()); }
491 EIGEN_DEVICE_FUNC
static inline Scalar extractScalarFactor(
const XprType& x) {
492 return conj(Base::extractScalarFactor(x.nestedExpression()));
497template <
typename Scalar,
typename NestedXpr,
typename Plain>
499 CwiseBinaryOp<scalar_product_op<Scalar>, const CwiseNullaryOp<scalar_constant_op<Scalar>, Plain>, NestedXpr> >
500 : blas_traits<NestedXpr> {
501 enum { HasScalarFactor =
true };
502 typedef blas_traits<NestedXpr> Base;
503 typedef CwiseBinaryOp<scalar_product_op<Scalar>,
const CwiseNullaryOp<scalar_constant_op<Scalar>, Plain>, NestedXpr>
505 typedef typename Base::ExtractType ExtractType;
506 EIGEN_DEVICE_FUNC
static inline EIGEN_DEVICE_FUNC ExtractType extract(
const XprType& x) {
507 return Base::extract(x.rhs());
509 EIGEN_DEVICE_FUNC
static inline EIGEN_DEVICE_FUNC Scalar extractScalarFactor(
const XprType& x) {
510 return x.lhs().functor().m_other * Base::extractScalarFactor(x.rhs());
513template <
typename Scalar,
typename NestedXpr,
typename Plain>
515 CwiseBinaryOp<scalar_product_op<Scalar>, NestedXpr, const CwiseNullaryOp<scalar_constant_op<Scalar>, Plain> > >
516 : blas_traits<NestedXpr> {
517 enum { HasScalarFactor =
true };
518 typedef blas_traits<NestedXpr> Base;
519 typedef CwiseBinaryOp<scalar_product_op<Scalar>, NestedXpr,
const CwiseNullaryOp<scalar_constant_op<Scalar>, Plain> >
521 typedef typename Base::ExtractType ExtractType;
522 EIGEN_DEVICE_FUNC
static inline ExtractType extract(
const XprType& x) {
return Base::extract(x.lhs()); }
523 EIGEN_DEVICE_FUNC
static inline Scalar extractScalarFactor(
const XprType& x) {
524 return Base::extractScalarFactor(x.lhs()) * x.rhs().functor().m_other;
527template <
typename Scalar,
typename Plain1,
typename Plain2>
528struct blas_traits<CwiseBinaryOp<scalar_product_op<Scalar>, const CwiseNullaryOp<scalar_constant_op<Scalar>, Plain1>,
529 const CwiseNullaryOp<scalar_constant_op<Scalar>, Plain2> > >
530 : blas_traits<CwiseNullaryOp<scalar_constant_op<Scalar>, Plain1> > {};
533template <
typename Scalar,
typename NestedXpr>
534struct blas_traits<CwiseUnaryOp<scalar_opposite_op<Scalar>, NestedXpr> > : blas_traits<NestedXpr> {
535 enum { HasScalarFactor =
true };
536 typedef blas_traits<NestedXpr> Base;
537 typedef CwiseUnaryOp<scalar_opposite_op<Scalar>, NestedXpr> XprType;
538 typedef typename Base::ExtractType ExtractType;
539 EIGEN_DEVICE_FUNC
static inline ExtractType extract(
const XprType& x) {
return Base::extract(x.nestedExpression()); }
540 EIGEN_DEVICE_FUNC
static inline Scalar extractScalarFactor(
const XprType& x) {
541 return -Base::extractScalarFactor(x.nestedExpression());
546template <
typename NestedXpr>
547struct blas_traits<Transpose<NestedXpr> > : blas_traits<NestedXpr> {
548 typedef typename NestedXpr::Scalar Scalar;
549 typedef blas_traits<NestedXpr> Base;
550 typedef Transpose<NestedXpr> XprType;
551 typedef Transpose<const typename Base::ExtractType_>
553 typedef Transpose<const typename Base::ExtractType_> ExtractType_;
554 typedef std::conditional_t<bool(Base::HasUsableDirectAccess), ExtractType,
typename ExtractType::PlainObject>
555 DirectLinearAccessType;
556 enum { IsTransposed = Base::IsTransposed ? 0 : 1 };
557 EIGEN_DEVICE_FUNC
static inline ExtractType extract(
const XprType& x) {
558 return ExtractType(Base::extract(x.nestedExpression()));
560 EIGEN_DEVICE_FUNC
static inline Scalar extractScalarFactor(
const XprType& x) {
561 return Base::extractScalarFactor(x.nestedExpression());
566struct blas_traits<const T> : blas_traits<T> {};
568template <typename T, bool HasUsableDirectAccess = blas_traits<T>::HasUsableDirectAccess>
569struct extract_data_selector {
570 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
static const typename T::Scalar* run(
const T& m) {
571 return blas_traits<T>::extract(m).data();
576struct extract_data_selector<T, false> {
577 EIGEN_DEVICE_FUNC
static typename T::Scalar* run(
const T&) {
return 0; }
581EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
const typename T::Scalar* extract_data(
const T& m) {
582 return extract_data_selector<T>::run(m);
589template <
typename ResScalar,
typename Lhs,
typename Rhs>
590struct combine_scalar_factors_impl {
591 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
static ResScalar run(
const Lhs& lhs,
const Rhs& rhs) {
592 return blas_traits<Lhs>::extractScalarFactor(lhs) * blas_traits<Rhs>::extractScalarFactor(rhs);
594 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
static ResScalar run(
const ResScalar& alpha,
const Lhs& lhs,
const Rhs& rhs) {
595 return alpha * blas_traits<Lhs>::extractScalarFactor(lhs) * blas_traits<Rhs>::extractScalarFactor(rhs);
598template <
typename Lhs,
typename Rhs>
599struct combine_scalar_factors_impl<bool, Lhs, Rhs> {
600 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
static bool run(
const Lhs& lhs,
const Rhs& rhs) {
601 return blas_traits<Lhs>::extractScalarFactor(lhs) && blas_traits<Rhs>::extractScalarFactor(rhs);
603 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
static bool run(
const bool& alpha,
const Lhs& lhs,
const Rhs& rhs) {
604 return alpha && blas_traits<Lhs>::extractScalarFactor(lhs) && blas_traits<Rhs>::extractScalarFactor(rhs);
608template <
typename ResScalar,
typename Lhs,
typename Rhs>
609EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE ResScalar combine_scalar_factors(
const ResScalar& alpha,
const Lhs& lhs,
611 return combine_scalar_factors_impl<ResScalar, Lhs, Rhs>::run(alpha, lhs, rhs);
613template <
typename ResScalar,
typename Lhs,
typename Rhs>
614EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE ResScalar combine_scalar_factors(
const Lhs& lhs,
const Rhs& rhs) {
615 return combine_scalar_factors_impl<ResScalar, Lhs, Rhs>::run(lhs, rhs);
AlignmentType
Definition Constants.h:234
@ RowMajor
Definition Constants.h:320
const unsigned int DirectAccessBit
Definition Constants.h:159
Namespace containing all symbols from the Eigen library.
Definition Core:137
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_conjugate_op< typename Derived::Scalar >, const Derived > conj(const Eigen::ArrayBase< Derived > &x)
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition Meta.h:83