Path Tracer
BlasUtil.h
1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2009-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
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_BLASUTIL_H
11 #define EIGEN_BLASUTIL_H
12 
13 // This file contains many lightweight helper classes used to
14 // implement and control fast level 2 and level 3 BLAS-like routines.
15 
16 namespace Eigen {
17 
18 namespace internal {
19 
20 // forward declarations
21 template<typename LhsScalar, typename RhsScalar, typename Index, typename DataMapper, int mr, int nr, bool ConjugateLhs=false, bool ConjugateRhs=false>
22 struct gebp_kernel;
23 
24 template<typename Scalar, typename Index, typename DataMapper, int nr, int StorageOrder, bool Conjugate = false, bool PanelMode=false>
26 
27 template<typename Scalar, typename Index, typename DataMapper, int Pack1, int Pack2, typename Packet, int StorageOrder, bool Conjugate = false, bool PanelMode = false>
29 
30 template<
31  typename Index,
32  typename LhsScalar, int LhsStorageOrder, bool ConjugateLhs,
33  typename RhsScalar, int RhsStorageOrder, bool ConjugateRhs,
34  int ResStorageOrder, int ResInnerStride>
36 
37 template<typename Index,
38  typename LhsScalar, typename LhsMapper, int LhsStorageOrder, bool ConjugateLhs,
39  typename RhsScalar, typename RhsMapper, bool ConjugateRhs, int Version=Specialized>
41 
42 
43 template<bool Conjugate> struct conj_if;
44 
45 template<> struct conj_if<true> {
46  template<typename T>
47  inline T operator()(const T& x) const { return numext::conj(x); }
48  template<typename T>
49  inline T pconj(const T& x) const { return internal::pconj(x); }
50 };
51 
52 template<> struct conj_if<false> {
53  template<typename T>
54  inline const T& operator()(const T& x) const { return x; }
55  template<typename T>
56  inline const T& pconj(const T& x) const { return x; }
57 };
58 
59 // Generic implementation for custom complex types.
60 template<typename LhsScalar, typename RhsScalar, bool ConjLhs, bool ConjRhs>
62 {
64 
65  EIGEN_STRONG_INLINE Scalar pmadd(const LhsScalar& x, const RhsScalar& y, const Scalar& c) const
66  { return padd(c, pmul(x,y)); }
67 
68  EIGEN_STRONG_INLINE Scalar pmul(const LhsScalar& x, const RhsScalar& y) const
69  { return conj_if<ConjLhs>()(x) * conj_if<ConjRhs>()(y); }
70 };
71 
72 template<typename Scalar> struct conj_helper<Scalar,Scalar,false,false>
73 {
74  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar pmadd(const Scalar& x, const Scalar& y, const Scalar& c) const { return internal::pmadd(x,y,c); }
75  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar pmul(const Scalar& x, const Scalar& y) const { return internal::pmul(x,y); }
76 };
77 
78 template<typename RealScalar> struct conj_helper<std::complex<RealScalar>, std::complex<RealScalar>, false,true>
79 {
80  typedef std::complex<RealScalar> Scalar;
81  EIGEN_STRONG_INLINE Scalar pmadd(const Scalar& x, const Scalar& y, const Scalar& c) const
82  { return c + pmul(x,y); }
83 
84  EIGEN_STRONG_INLINE Scalar pmul(const Scalar& x, const Scalar& y) const
85  { return Scalar(numext::real(x)*numext::real(y) + numext::imag(x)*numext::imag(y), numext::imag(x)*numext::real(y) - numext::real(x)*numext::imag(y)); }
86 };
87 
88 template<typename RealScalar> struct conj_helper<std::complex<RealScalar>, std::complex<RealScalar>, true,false>
89 {
90  typedef std::complex<RealScalar> Scalar;
91  EIGEN_STRONG_INLINE Scalar pmadd(const Scalar& x, const Scalar& y, const Scalar& c) const
92  { return c + pmul(x,y); }
93 
94  EIGEN_STRONG_INLINE Scalar pmul(const Scalar& x, const Scalar& y) const
95  { return Scalar(numext::real(x)*numext::real(y) + numext::imag(x)*numext::imag(y), numext::real(x)*numext::imag(y) - numext::imag(x)*numext::real(y)); }
96 };
97 
98 template<typename RealScalar> struct conj_helper<std::complex<RealScalar>, std::complex<RealScalar>, true,true>
99 {
100  typedef std::complex<RealScalar> Scalar;
101  EIGEN_STRONG_INLINE Scalar pmadd(const Scalar& x, const Scalar& y, const Scalar& c) const
102  { return c + pmul(x,y); }
103 
104  EIGEN_STRONG_INLINE Scalar pmul(const Scalar& x, const Scalar& y) const
105  { return Scalar(numext::real(x)*numext::real(y) - numext::imag(x)*numext::imag(y), - numext::real(x)*numext::imag(y) - numext::imag(x)*numext::real(y)); }
106 };
107 
108 template<typename RealScalar,bool Conj> struct conj_helper<std::complex<RealScalar>, RealScalar, Conj,false>
109 {
110  typedef std::complex<RealScalar> Scalar;
111  EIGEN_STRONG_INLINE Scalar pmadd(const Scalar& x, const RealScalar& y, const Scalar& c) const
112  { return padd(c, pmul(x,y)); }
113  EIGEN_STRONG_INLINE Scalar pmul(const Scalar& x, const RealScalar& y) const
114  { return conj_if<Conj>()(x)*y; }
115 };
116 
117 template<typename RealScalar,bool Conj> struct conj_helper<RealScalar, std::complex<RealScalar>, false,Conj>
118 {
119  typedef std::complex<RealScalar> Scalar;
120  EIGEN_STRONG_INLINE Scalar pmadd(const RealScalar& x, const Scalar& y, const Scalar& c) const
121  { return padd(c, pmul(x,y)); }
122  EIGEN_STRONG_INLINE Scalar pmul(const RealScalar& x, const Scalar& y) const
123  { return x*conj_if<Conj>()(y); }
124 };
125 
126 template<typename From,typename To> struct get_factor {
127  EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE To run(const From& x) { return To(x); }
128 };
129 
130 template<typename Scalar> struct get_factor<Scalar,typename NumTraits<Scalar>::Real> {
131  EIGEN_DEVICE_FUNC
132  static EIGEN_STRONG_INLINE typename NumTraits<Scalar>::Real run(const Scalar& x) { return numext::real(x); }
133 };
134 
135 
136 template<typename Scalar, typename Index>
138  public:
139  EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE BlasVectorMapper(Scalar *data) : m_data(data) {}
140 
141  EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Scalar operator()(Index i) const {
142  return m_data[i];
143  }
144  template <typename Packet, int AlignmentType>
145  EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet load(Index i) const {
146  return ploadt<Packet, AlignmentType>(m_data + i);
147  }
148 
149  template <typename Packet>
150  EIGEN_DEVICE_FUNC bool aligned(Index i) const {
151  return (UIntPtr(m_data+i)%sizeof(Packet))==0;
152  }
153 
154  protected:
155  Scalar* m_data;
156 };
157 
158 template<typename Scalar, typename Index, int AlignmentType, int Incr=1>
159 class BlasLinearMapper;
160 
161 template<typename Scalar, typename Index, int AlignmentType>
163 {
164 public:
165  EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE BlasLinearMapper(Scalar *data, Index incr=1)
166  : m_data(data)
167  {
168  EIGEN_ONLY_USED_FOR_DEBUG(incr);
169  eigen_assert(incr==1);
170  }
171 
172  EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE void prefetch(int i) const {
173  internal::prefetch(&operator()(i));
174  }
175 
176  EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Scalar& operator()(Index i) const {
177  return m_data[i];
178  }
179 
180  template<typename PacketType>
181  EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE PacketType loadPacket(Index i) const {
182  return ploadt<PacketType, AlignmentType>(m_data + i);
183  }
184 
185  template<typename PacketType>
186  EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE void storePacket(Index i, const PacketType &p) const {
187  pstoret<Scalar, PacketType, AlignmentType>(m_data + i, p);
188  }
189 
190 protected:
191  Scalar *m_data;
192 };
193 
194 // Lightweight helper class to access matrix coefficients.
195 template<typename Scalar, typename Index, int StorageOrder, int AlignmentType = Unaligned, int Incr = 1>
196 class blas_data_mapper;
197 
198 // TMP to help PacketBlock store implementation.
199 // There's currently no known use case for PacketBlock load.
200 // The default implementation assumes ColMajor order.
201 // It always store each packet sequentially one `stride` apart.
202 template<typename Index, typename Scalar, typename Packet, int n, int idx, int StorageOrder>
204 {
205  PacketBlockManagement<Index, Scalar, Packet, n, idx - 1, StorageOrder> pbm;
206  EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE void store(Scalar *to, const Index stride, Index i, Index j, const PacketBlock<Packet, n> &block) const {
207  pbm.store(to, stride, i, j, block);
208  pstoreu<Scalar>(to + i + (j + idx)*stride, block.packet[idx]);
209  }
210 };
211 
212 // PacketBlockManagement specialization to take care of RowMajor order without ifs.
213 template<typename Index, typename Scalar, typename Packet, int n, int idx>
214 struct PacketBlockManagement<Index, Scalar, Packet, n, idx, RowMajor>
215 {
216  PacketBlockManagement<Index, Scalar, Packet, n, idx - 1, RowMajor> pbm;
217  EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE void store(Scalar *to, const Index stride, Index i, Index j, const PacketBlock<Packet, n> &block) const {
218  pbm.store(to, stride, i, j, block);
219  pstoreu<Scalar>(to + j + (i + idx)*stride, block.packet[idx]);
220  }
221 };
222 
223 template<typename Index, typename Scalar, typename Packet, int n, int StorageOrder>
224 struct PacketBlockManagement<Index, Scalar, Packet, n, -1, StorageOrder>
225 {
226  EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE void store(Scalar *to, const Index stride, Index i, Index j, const PacketBlock<Packet, n> &block) const {
227  EIGEN_UNUSED_VARIABLE(to);
228  EIGEN_UNUSED_VARIABLE(stride);
229  EIGEN_UNUSED_VARIABLE(i);
230  EIGEN_UNUSED_VARIABLE(j);
231  EIGEN_UNUSED_VARIABLE(block);
232  }
233 };
234 
235 template<typename Index, typename Scalar, typename Packet, int n>
236 struct PacketBlockManagement<Index, Scalar, Packet, n, -1, RowMajor>
237 {
238  EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE void store(Scalar *to, const Index stride, Index i, Index j, const PacketBlock<Packet, n> &block) const {
239  EIGEN_UNUSED_VARIABLE(to);
240  EIGEN_UNUSED_VARIABLE(stride);
241  EIGEN_UNUSED_VARIABLE(i);
242  EIGEN_UNUSED_VARIABLE(j);
243  EIGEN_UNUSED_VARIABLE(block);
244  }
245 };
246 
247 template<typename Scalar, typename Index, int StorageOrder, int AlignmentType>
248 class blas_data_mapper<Scalar,Index,StorageOrder,AlignmentType,1>
249 {
250 public:
253 
254  EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE blas_data_mapper(Scalar* data, Index stride, Index incr=1)
255  : m_data(data), m_stride(stride)
256  {
257  EIGEN_ONLY_USED_FOR_DEBUG(incr);
258  eigen_assert(incr==1);
259  }
260 
261  EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE blas_data_mapper<Scalar, Index, StorageOrder, AlignmentType>
262  getSubMapper(Index i, Index j) const {
263  return blas_data_mapper<Scalar, Index, StorageOrder, AlignmentType>(&operator()(i, j), m_stride);
264  }
265 
266  EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE LinearMapper getLinearMapper(Index i, Index j) const {
267  return LinearMapper(&operator()(i, j));
268  }
269 
270  EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE VectorMapper getVectorMapper(Index i, Index j) const {
271  return VectorMapper(&operator()(i, j));
272  }
273 
274 
275  EIGEN_DEVICE_FUNC
276  EIGEN_ALWAYS_INLINE Scalar& operator()(Index i, Index j) const {
277  return m_data[StorageOrder==RowMajor ? j + i*m_stride : i + j*m_stride];
278  }
279 
280  template<typename PacketType>
281  EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE PacketType loadPacket(Index i, Index j) const {
282  return ploadt<PacketType, AlignmentType>(&operator()(i, j));
283  }
284 
285  template <typename PacketT, int AlignmentT>
286  EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE PacketT load(Index i, Index j) const {
287  return ploadt<PacketT, AlignmentT>(&operator()(i, j));
288  }
289 
290  template<typename SubPacket>
291  EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE void scatterPacket(Index i, Index j, const SubPacket &p) const {
292  pscatter<Scalar, SubPacket>(&operator()(i, j), p, m_stride);
293  }
294 
295  template<typename SubPacket>
296  EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE SubPacket gatherPacket(Index i, Index j) const {
297  return pgather<Scalar, SubPacket>(&operator()(i, j), m_stride);
298  }
299 
300  EIGEN_DEVICE_FUNC const Index stride() const { return m_stride; }
301  EIGEN_DEVICE_FUNC const Scalar* data() const { return m_data; }
302 
303  EIGEN_DEVICE_FUNC Index firstAligned(Index size) const {
304  if (UIntPtr(m_data)%sizeof(Scalar)) {
305  return -1;
306  }
307  return internal::first_default_aligned(m_data, size);
308  }
309 
310  template<typename SubPacket, int n>
311  EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE void storePacketBlock(Index i, Index j, const PacketBlock<SubPacket, n> &block) const {
312  PacketBlockManagement<Index, Scalar, SubPacket, n, n-1, StorageOrder> pbm;
313  pbm.store(m_data, m_stride, i, j, block);
314  }
315 protected:
316  Scalar* EIGEN_RESTRICT m_data;
317  const Index m_stride;
318 };
319 
320 // Implementation of non-natural increment (i.e. inner-stride != 1)
321 // The exposed API is not complete yet compared to the Incr==1 case
322 // because some features makes less sense in this case.
323 template<typename Scalar, typename Index, int AlignmentType, int Incr>
325 {
326 public:
327  EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE BlasLinearMapper(Scalar *data,Index incr) : m_data(data), m_incr(incr) {}
328 
329  EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE void prefetch(int i) const {
330  internal::prefetch(&operator()(i));
331  }
332 
333  EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Scalar& operator()(Index i) const {
334  return m_data[i*m_incr.value()];
335  }
336 
337  template<typename PacketType>
338  EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE PacketType loadPacket(Index i) const {
339  return pgather<Scalar,PacketType>(m_data + i*m_incr.value(), m_incr.value());
340  }
341 
342  template<typename PacketType>
343  EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE void storePacket(Index i, const PacketType &p) const {
344  pscatter<Scalar, PacketType>(m_data + i*m_incr.value(), p, m_incr.value());
345  }
346 
347 protected:
348  Scalar *m_data;
350 };
351 
352 template<typename Scalar, typename Index, int StorageOrder, int AlignmentType,int Incr>
354 {
355 public:
357 
358  EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE blas_data_mapper(Scalar* data, Index stride, Index incr) : m_data(data), m_stride(stride), m_incr(incr) {}
359 
360  EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE blas_data_mapper
361  getSubMapper(Index i, Index j) const {
362  return blas_data_mapper(&operator()(i, j), m_stride, m_incr.value());
363  }
364 
365  EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE LinearMapper getLinearMapper(Index i, Index j) const {
366  return LinearMapper(&operator()(i, j), m_incr.value());
367  }
368 
369  EIGEN_DEVICE_FUNC
370  EIGEN_ALWAYS_INLINE Scalar& operator()(Index i, Index j) const {
371  return m_data[StorageOrder==RowMajor ? j*m_incr.value() + i*m_stride : i*m_incr.value() + j*m_stride];
372  }
373 
374  template<typename PacketType>
375  EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE PacketType loadPacket(Index i, Index j) const {
376  return pgather<Scalar,PacketType>(&operator()(i, j),m_incr.value());
377  }
378 
379  template <typename PacketT, int AlignmentT>
380  EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE PacketT load(Index i, Index j) const {
381  return pgather<Scalar,PacketT>(&operator()(i, j),m_incr.value());
382  }
383 
384  template<typename SubPacket>
385  EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE void scatterPacket(Index i, Index j, const SubPacket &p) const {
386  pscatter<Scalar, SubPacket>(&operator()(i, j), p, m_stride);
387  }
388 
389  template<typename SubPacket>
390  EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE SubPacket gatherPacket(Index i, Index j) const {
391  return pgather<Scalar, SubPacket>(&operator()(i, j), m_stride);
392  }
393 
394  // storePacketBlock_helper defines a way to access values inside the PacketBlock, this is essentially required by the Complex types.
395  template<typename SubPacket, typename ScalarT, int n, int idx>
397  {
398  storePacketBlock_helper<SubPacket, ScalarT, n, idx-1> spbh;
399  EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE void store(const blas_data_mapper<Scalar, Index, StorageOrder, AlignmentType, Incr>* sup, Index i, Index j, const PacketBlock<SubPacket, n>& block) const {
400  spbh.store(sup, i,j,block);
401  for(int l = 0; l < unpacket_traits<SubPacket>::size; l++)
402  {
403  ScalarT *v = &sup->operator()(i+l, j+idx);
404  *v = block.packet[idx][l];
405  }
406  }
407  };
408 
409  template<typename SubPacket, int n, int idx>
410  struct storePacketBlock_helper<SubPacket, std::complex<float>, n, idx>
411  {
413  EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE void store(const blas_data_mapper<Scalar, Index, StorageOrder, AlignmentType, Incr>* sup, Index i, Index j, const PacketBlock<SubPacket, n>& block) const {
414  spbh.store(sup,i,j,block);
415  for(int l = 0; l < unpacket_traits<SubPacket>::size; l++)
416  {
417  std::complex<float> *v = &sup->operator()(i+l, j+idx);
418  v->real(block.packet[idx].v[2*l+0]);
419  v->imag(block.packet[idx].v[2*l+1]);
420  }
421  }
422  };
423 
424  template<typename SubPacket, int n, int idx>
425  struct storePacketBlock_helper<SubPacket, std::complex<double>, n, idx>
426  {
428  EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE void store(const blas_data_mapper<Scalar, Index, StorageOrder, AlignmentType, Incr>* sup, Index i, Index j, const PacketBlock<SubPacket, n>& block) const {
429  spbh.store(sup,i,j,block);
430  for(int l = 0; l < unpacket_traits<SubPacket>::size; l++)
431  {
432  std::complex<double> *v = &sup->operator()(i+l, j+idx);
433  v->real(block.packet[idx].v[2*l+0]);
434  v->imag(block.packet[idx].v[2*l+1]);
435  }
436  }
437  };
438 
439  template<typename SubPacket, typename ScalarT, int n>
440  struct storePacketBlock_helper<SubPacket, ScalarT, n, -1>
441  {
442  EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE void store(const blas_data_mapper<Scalar, Index, StorageOrder, AlignmentType, Incr>*, Index, Index, const PacketBlock<SubPacket, n>& ) const {
443  }
444  };
445 
446  template<typename SubPacket, int n>
447  struct storePacketBlock_helper<SubPacket, std::complex<float>, n, -1>
448  {
449  EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE void store(const blas_data_mapper<Scalar, Index, StorageOrder, AlignmentType, Incr>*, Index, Index, const PacketBlock<SubPacket, n>& ) const {
450  }
451  };
452 
453  template<typename SubPacket, int n>
454  struct storePacketBlock_helper<SubPacket, std::complex<double>, n, -1>
455  {
456  EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE void store(const blas_data_mapper<Scalar, Index, StorageOrder, AlignmentType, Incr>*, Index, Index, const PacketBlock<SubPacket, n>& ) const {
457  }
458  };
459  // This function stores a PacketBlock on m_data, this approach is really quite slow compare to Incr=1 and should be avoided when possible.
460  template<typename SubPacket, int n>
461  EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE void storePacketBlock(Index i, Index j, const PacketBlock<SubPacket, n>&block) const {
462  storePacketBlock_helper<SubPacket, Scalar, n, n-1> spb;
463  spb.store(this, i,j,block);
464  }
465 protected:
466  Scalar* EIGEN_RESTRICT m_data;
467  const Index m_stride;
469 };
470 
471 // lightweight helper class to access matrix coefficients (const version)
472 template<typename Scalar, typename Index, int StorageOrder>
473 class const_blas_data_mapper : public blas_data_mapper<const Scalar, Index, StorageOrder> {
474  public:
475  EIGEN_ALWAYS_INLINE const_blas_data_mapper(const Scalar *data, Index stride) : blas_data_mapper<const Scalar, Index, StorageOrder>(data, stride) {}
476 
477  EIGEN_ALWAYS_INLINE const_blas_data_mapper<Scalar, Index, StorageOrder> getSubMapper(Index i, Index j) const {
478  return const_blas_data_mapper<Scalar, Index, StorageOrder>(&(this->operator()(i, j)), this->m_stride);
479  }
480 };
481 
482 
483 /* Helper class to analyze the factors of a Product expression.
484  * In particular it allows to pop out operator-, scalar multiples,
485  * and conjugate */
486 template<typename XprType> struct blas_traits
487 {
488  typedef typename traits<XprType>::Scalar Scalar;
489  typedef const XprType& ExtractType;
490  typedef XprType _ExtractType;
491  enum {
492  IsComplex = NumTraits<Scalar>::IsComplex,
493  IsTransposed = false,
494  NeedToConjugate = false,
495  HasUsableDirectAccess = ( (int(XprType::Flags)&DirectAccessBit)
496  && ( bool(XprType::IsVectorAtCompileTime)
498  ) ? 1 : 0,
499  HasScalarFactor = false
500  };
501  typedef typename conditional<bool(HasUsableDirectAccess),
502  ExtractType,
503  typename _ExtractType::PlainObject
504  >::type DirectLinearAccessType;
505  static inline EIGEN_DEVICE_FUNC ExtractType extract(const XprType& x) { return x; }
506  static inline EIGEN_DEVICE_FUNC const Scalar extractScalarFactor(const XprType&) { return Scalar(1); }
507 };
508 
509 // pop conjugate
510 template<typename Scalar, typename NestedXpr>
511 struct blas_traits<CwiseUnaryOp<scalar_conjugate_op<Scalar>, NestedXpr> >
512  : blas_traits<NestedXpr>
513 {
516  typedef typename Base::ExtractType ExtractType;
517 
518  enum {
519  IsComplex = NumTraits<Scalar>::IsComplex,
520  NeedToConjugate = Base::NeedToConjugate ? 0 : IsComplex
521  };
522  static inline ExtractType extract(const XprType& x) { return Base::extract(x.nestedExpression()); }
523  static inline Scalar extractScalarFactor(const XprType& x) { return conj(Base::extractScalarFactor(x.nestedExpression())); }
524 };
525 
526 // pop scalar multiple
527 template<typename Scalar, typename NestedXpr, typename Plain>
528 struct blas_traits<CwiseBinaryOp<scalar_product_op<Scalar>, const CwiseNullaryOp<scalar_constant_op<Scalar>,Plain>, NestedXpr> >
529  : blas_traits<NestedXpr>
530 {
531  enum {
532  HasScalarFactor = true
533  };
536  typedef typename Base::ExtractType ExtractType;
537  static inline EIGEN_DEVICE_FUNC ExtractType extract(const XprType& x) { return Base::extract(x.rhs()); }
538  static inline EIGEN_DEVICE_FUNC Scalar extractScalarFactor(const XprType& x)
539  { return x.lhs().functor().m_other * Base::extractScalarFactor(x.rhs()); }
540 };
541 template<typename Scalar, typename NestedXpr, typename Plain>
542 struct blas_traits<CwiseBinaryOp<scalar_product_op<Scalar>, NestedXpr, const CwiseNullaryOp<scalar_constant_op<Scalar>,Plain> > >
543  : blas_traits<NestedXpr>
544 {
545  enum {
546  HasScalarFactor = true
547  };
550  typedef typename Base::ExtractType ExtractType;
551  static inline ExtractType extract(const XprType& x) { return Base::extract(x.lhs()); }
552  static inline Scalar extractScalarFactor(const XprType& x)
553  { return Base::extractScalarFactor(x.lhs()) * x.rhs().functor().m_other; }
554 };
555 template<typename Scalar, typename Plain1, typename Plain2>
557  const CwiseNullaryOp<scalar_constant_op<Scalar>,Plain2> > >
558  : blas_traits<CwiseNullaryOp<scalar_constant_op<Scalar>,Plain1> >
559 {};
560 
561 // pop opposite
562 template<typename Scalar, typename NestedXpr>
563 struct blas_traits<CwiseUnaryOp<scalar_opposite_op<Scalar>, NestedXpr> >
564  : blas_traits<NestedXpr>
565 {
566  enum {
567  HasScalarFactor = true
568  };
571  typedef typename Base::ExtractType ExtractType;
572  static inline ExtractType extract(const XprType& x) { return Base::extract(x.nestedExpression()); }
573  static inline Scalar extractScalarFactor(const XprType& x)
574  { return - Base::extractScalarFactor(x.nestedExpression()); }
575 };
576 
577 // pop/push transpose
578 template<typename NestedXpr>
579 struct blas_traits<Transpose<NestedXpr> >
580  : blas_traits<NestedXpr>
581 {
582  typedef typename NestedXpr::Scalar Scalar;
585  typedef Transpose<const typename Base::_ExtractType> ExtractType; // const to get rid of a compile error; anyway blas traits are only used on the RHS
587  typedef typename conditional<bool(Base::HasUsableDirectAccess),
588  ExtractType,
589  typename ExtractType::PlainObject
590  >::type DirectLinearAccessType;
591  enum {
592  IsTransposed = Base::IsTransposed ? 0 : 1
593  };
594  static inline ExtractType extract(const XprType& x) { return ExtractType(Base::extract(x.nestedExpression())); }
595  static inline Scalar extractScalarFactor(const XprType& x) { return Base::extractScalarFactor(x.nestedExpression()); }
596 };
597 
598 template<typename T>
599 struct blas_traits<const T>
600  : blas_traits<T>
601 {};
602 
603 template<typename T, bool HasUsableDirectAccess=blas_traits<T>::HasUsableDirectAccess>
605  static const typename T::Scalar* run(const T& m)
606  {
607  return blas_traits<T>::extract(m).data();
608  }
609 };
610 
611 template<typename T>
612 struct extract_data_selector<T,false> {
613  static typename T::Scalar* run(const T&) { return 0; }
614 };
615 
616 template<typename T> const typename T::Scalar* extract_data(const T& m)
617 {
619 }
620 
621 } // end namespace internal
622 
623 } // end namespace Eigen
624 
625 #endif // EIGEN_BLASUTIL_H
Eigen::internal::variable_if_dynamic< Index, Incr >
Eigen
Namespace containing all symbols from the Eigen library.
Definition: LDLT.h:16
Eigen::CwiseBinaryOp
Generic expression where a coefficient-wise binary operator is applied to two expressions.
Definition: CwiseBinaryOp.h:84
Eigen::internal::general_matrix_vector_product
Definition: BlasUtil.h:40
Eigen::internal::PacketBlock
Definition: GenericPacketMath.h:875
Eigen::internal::BlasVectorMapper
Definition: BlasUtil.h:137
Eigen::ScalarBinaryOpTraits
Determines whether the given binary operation of two numeric types is allowed and what the scalar ret...
Definition: XprHelper.h:814
Eigen::RowMajor
@ RowMajor
Definition: Constants.h:320
Eigen::internal::scalar_product_op
Definition: BinaryFunctors.h:71
Eigen::Transpose
Expression of the transpose of a matrix.
Definition: Transpose.h:54
Eigen::DirectAccessBit
const unsigned int DirectAccessBit
Definition: Constants.h:154
Eigen::CwiseNullaryOp
Generic expression of a matrix where all coefficients are defined by a functor.
Definition: CwiseNullaryOp.h:61
Eigen::CwiseBinaryOp::lhs
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const _LhsNested & lhs() const
Definition: CwiseBinaryOp.h:138
Eigen::internal::true_type
Definition: Meta.h:63
Eigen::internal::PacketBlockManagement
Definition: BlasUtil.h:204
Eigen::internal::scalar_constant_op
Definition: NullaryFunctors.h:18
Eigen::CwiseUnaryOp::nestedExpression
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const internal::remove_all< XprTypeNested >::type & nestedExpression() const
Definition: CwiseUnaryOp.h:80
spb
Definition: spbreader.hpp:46
Eigen::internal::extract_data_selector
Definition: BlasUtil.h:604
Eigen::internal::conj_if
Definition: BlasUtil.h:43
Eigen::internal::Packet
Definition: ZVector/PacketMath.h:53
Eigen::internal::get_factor
Definition: BlasUtil.h:126
Eigen::internal::gemm_pack_rhs
Definition: BlasUtil.h:25
Eigen::internal::inner_stride_at_compile_time
Definition: DenseCoeffsBase.h:659
Eigen::internal::blas_data_mapper
Definition: BlasUtil.h:354
Eigen::internal::traits
Definition: ForwardDeclarations.h:17
Eigen::internal::gemm_pack_lhs
Definition: BlasUtil.h:28
Eigen::internal::const_blas_data_mapper
Definition: BlasUtil.h:473
Eigen::internal::blas_data_mapper::storePacketBlock_helper
Definition: BlasUtil.h:397
Eigen::internal::scalar_opposite_op
Definition: UnaryFunctors.h:22
Eigen::AlignmentType
AlignmentType
Definition: Constants.h:231
Eigen::internal::conj_helper
Definition: BlasUtil.h:62
Eigen::CwiseUnaryOp
Generic expression where a coefficient-wise unary operator is applied to an expression.
Definition: CwiseUnaryOp.h:56
Eigen::internal::conditional
Definition: Meta.h:76
Eigen::CwiseBinaryOp::rhs
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const _RhsNested & rhs() const
Definition: CwiseBinaryOp.h:141
Eigen::internal::blas_traits
Definition: BlasUtil.h:487
Eigen::internal::BlasLinearMapper
Definition: BlasUtil.h:325
Eigen::NumTraits
Holds information about the various numeric (i.e. scalar) types allowed by Eigen.
Definition: NumTraits.h:213
Eigen::internal::BlasLinearMapper< Scalar, Index, AlignmentType >
Definition: BlasUtil.h:163
Eigen::internal::scalar_conjugate_op
Definition: UnaryFunctors.h:109
Eigen::internal::general_matrix_matrix_product
Definition: BlasUtil.h:35
Eigen::Transpose::nestedExpression
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const internal::remove_all< MatrixTypeNested >::type & nestedExpression() const
Definition: Transpose.h:76
Eigen::Index
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition: Meta.h:42