Dot.h
Go to the documentation of this file.
1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2006-2008, 2010 Benoit Jacob <jacob.benoit.1@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_DOT_H
11 #define EIGEN_DOT_H
12 
13 #include "./InternalHeaderCheck.h"
14 
15 namespace Eigen {
16 
17 namespace internal {
18 
19 // helper function for dot(). The problem is that if we put that in the body of dot(), then upon calling dot
20 // with mismatched types, the compiler emits errors about failing to instantiate cwiseProduct BEFORE
21 // looking at the static assertions. Thus this is a trick to get better compile errors.
22 template<typename T, typename U,
23  bool NeedToTranspose = T::IsVectorAtCompileTime && U::IsVectorAtCompileTime &&
24  ((int(T::RowsAtCompileTime) == 1 && int(U::ColsAtCompileTime) == 1) ||
25  (int(T::ColsAtCompileTime) == 1 && int(U::RowsAtCompileTime) == 1))>
26 struct dot_nocheck
27 {
28  typedef scalar_conj_product_op<typename traits<T>::Scalar,typename traits<U>::Scalar> conj_prod;
29  typedef typename conj_prod::result_type ResScalar;
31  EIGEN_STRONG_INLINE
32  static ResScalar run(const MatrixBase<T>& a, const MatrixBase<U>& b)
33  {
34  return a.template binaryExpr<conj_prod>(b).sum();
35  }
36 };
37 
38 template<typename T, typename U>
39 struct dot_nocheck<T, U, true>
40 {
41  typedef scalar_conj_product_op<typename traits<T>::Scalar,typename traits<U>::Scalar> conj_prod;
42  typedef typename conj_prod::result_type ResScalar;
44  EIGEN_STRONG_INLINE
45  static ResScalar run(const MatrixBase<T>& a, const MatrixBase<U>& b)
46  {
47  return a.transpose().template binaryExpr<conj_prod>(b).sum();
48  }
49 };
50 
51 } // end namespace internal
52 
64 template<typename Derived>
65 template<typename OtherDerived>
67 EIGEN_STRONG_INLINE
68 typename ScalarBinaryOpTraits<typename internal::traits<Derived>::Scalar,typename internal::traits<OtherDerived>::Scalar>::ReturnType
70 {
73  EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(Derived,OtherDerived)
74 #if !(defined(EIGEN_NO_STATIC_ASSERT) && defined(EIGEN_NO_DEBUG))
76  Eigen::internal::scalar_conj_product_op<Scalar EIGEN_COMMA typename OtherDerived::Scalar>,
77  Scalar, typename OtherDerived::Scalar);
78 #endif
79 
80  eigen_assert(size() == other.size());
81 
82  return internal::dot_nocheck<Derived,OtherDerived>::run(*this, other);
83 }
84 
85 //---------- implementation of L2 norm and related functions ----------
86 
93 template<typename Derived>
95 {
96  return numext::real((*this).cwiseAbs2().sum());
97 }
98 
105 template<typename Derived>
107 {
108  return numext::sqrt(squaredNorm());
109 }
110 
120 template<typename Derived>
121 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::PlainObject
123 {
124  typedef typename internal::nested_eval<Derived,2>::type Nested_;
125  Nested_ n(derived());
126  RealScalar z = n.squaredNorm();
127  // NOTE: after extensive benchmarking, this conditional does not impact performance, at least on recent x86 CPU
128  if(z>RealScalar(0))
129  return n / numext::sqrt(z);
130  else
131  return n;
132 }
133 
142 template<typename Derived>
144 {
145  RealScalar z = squaredNorm();
146  // NOTE: after extensive benchmarking, this conditional does not impact performance, at least on recent x86 CPU
147  if(z>RealScalar(0))
148  derived() /= numext::sqrt(z);
149 }
150 
163 template<typename Derived>
164 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::PlainObject
166 {
167  typedef typename internal::nested_eval<Derived,3>::type Nested_;
168  Nested_ n(derived());
169  RealScalar w = n.cwiseAbs().maxCoeff();
170  RealScalar z = (n/w).squaredNorm();
171  if(z>RealScalar(0))
172  return n / (numext::sqrt(z)*w);
173  else
174  return n;
175 }
176 
188 template<typename Derived>
190 {
191  RealScalar w = cwiseAbs().maxCoeff();
192  RealScalar z = (derived()/w).squaredNorm();
193  if(z>RealScalar(0))
194  derived() /= numext::sqrt(z)*w;
195 }
196 
197 //---------- implementation of other norms ----------
198 
199 namespace internal {
200 
201 template<typename Derived, int p>
202 struct lpNorm_selector
203 {
206  static inline RealScalar run(const MatrixBase<Derived>& m)
207  {
209  return pow(m.cwiseAbs().array().pow(p).sum(), RealScalar(1)/p);
210  }
211 };
212 
213 template<typename Derived>
214 struct lpNorm_selector<Derived, 1>
215 {
217  static inline typename NumTraits<typename traits<Derived>::Scalar>::Real run(const MatrixBase<Derived>& m)
218  {
219  return m.cwiseAbs().sum();
220  }
221 };
222 
223 template<typename Derived>
224 struct lpNorm_selector<Derived, 2>
225 {
227  static inline typename NumTraits<typename traits<Derived>::Scalar>::Real run(const MatrixBase<Derived>& m)
228  {
229  return m.norm();
230  }
231 };
232 
233 template<typename Derived>
234 struct lpNorm_selector<Derived, Infinity>
235 {
236  typedef typename NumTraits<typename traits<Derived>::Scalar>::Real RealScalar;
238  static inline RealScalar run(const MatrixBase<Derived>& m)
239  {
240  if(Derived::SizeAtCompileTime==0 || (Derived::SizeAtCompileTime==Dynamic && m.size()==0))
241  return RealScalar(0);
242  return m.cwiseAbs().maxCoeff();
243  }
244 };
245 
246 } // end namespace internal
247 
258 template<typename Derived>
259 template<int p>
260 #ifndef EIGEN_PARSED_BY_DOXYGEN
261 EIGEN_DEVICE_FUNC inline typename NumTraits<typename internal::traits<Derived>::Scalar>::Real
262 #else
264 #endif
266 {
267  return internal::lpNorm_selector<Derived, p>::run(*this);
268 }
269 
270 //---------- implementation of isOrthogonal / isUnitary ----------
271 
278 template<typename Derived>
279 template<typename OtherDerived>
281 (const MatrixBase<OtherDerived>& other, const RealScalar& prec) const
282 {
283  typename internal::nested_eval<Derived,2>::type nested(derived());
284  typename internal::nested_eval<OtherDerived,2>::type otherNested(other.derived());
285  return numext::abs2(nested.dot(otherNested)) <= prec * prec * nested.squaredNorm() * otherNested.squaredNorm();
286 }
287 
299 template<typename Derived>
301 {
302  typename internal::nested_eval<Derived,1>::type self(derived());
303  for(Index i = 0; i < cols(); ++i)
304  {
305  if(!internal::isApprox(self.col(i).squaredNorm(), static_cast<RealScalar>(1), prec))
306  return false;
307  for(Index j = 0; j < i; ++j)
308  if(!internal::isMuchSmallerThan(self.col(i).dot(self.col(j)), static_cast<Scalar>(1), prec))
309  return false;
310  }
311  return true;
312 }
313 
314 } // end namespace Eigen
315 
316 #endif // EIGEN_DOT_H
Matrix3f m
Array< int, 3, 1 > b
int n
ColXpr col(Index i)
This is the const version of col().
RealReturnType real() const
#define EIGEN_USING_STD(FUNC)
Definition: Macros.h:1080
#define EIGEN_DEVICE_FUNC
Definition: Macros.h:883
#define eigen_assert(x)
Definition: Macros.h:902
const CwiseAbsReturnType cwiseAbs() const
RowVector3d w
#define EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(TYPE0, TYPE1)
Definition: StaticAssert.h:61
#define EIGEN_STATIC_ASSERT_VECTOR_ONLY(TYPE)
Definition: StaticAssert.h:36
float * p
Eigen::Triplet< double > T
#define EIGEN_CHECK_BINARY_COMPATIBILIY(BINOP, LHS, RHS)
Definition: XprHelper.h:900
NumTraits< Scalar >::Real RealScalar
Definition: DenseBase.h:68
internal::traits< Derived >::Scalar Scalar
Definition: DenseBase.h:61
EIGEN_CONSTEXPR Index size() const EIGEN_NOEXCEPT
Definition: EigenBase.h:69
Base class for all dense matrices, vectors, and expressions.
Definition: MatrixBase.h:52
void stableNormalize()
Definition: Dot.h:189
RealScalar norm() const
Definition: Dot.h:106
const PlainObject stableNormalized() const
Definition: Dot.h:165
const PlainObject normalized() const
Definition: Dot.h:122
RealScalar lpNorm() const
Definition: Dot.h:265
bool isUnitary(const RealScalar &prec=NumTraits< Scalar >::dummy_precision()) const
Definition: Dot.h:300
Base::PlainObject PlainObject
Definition: MatrixBase.h:106
RealScalar squaredNorm() const
Definition: Dot.h:94
void normalize()
Definition: Dot.h:143
ScalarBinaryOpTraits< typename internal::traits< Derived >::Scalar, typename internal::traits< OtherDerived >::Scalar >::ReturnType dot(const MatrixBase< OtherDerived > &other) const
Definition: Dot.h:69
bool isOrthogonal(const MatrixBase< OtherDerived > &other, const RealScalar &prec=NumTraits< Scalar >::dummy_precision()) const
Definition: Dot.h:281
bfloat16 pow(const bfloat16 &a, const bfloat16 &b)
Definition: BFloat16.h:626
bool isApprox(const Scalar &x, const Scalar &y, const typename NumTraits< Scalar >::Real &precision=NumTraits< Scalar >::dummy_precision())
bool isMuchSmallerThan(const Scalar &x, const OtherScalar &y, const typename NumTraits< Scalar >::Real &precision=NumTraits< Scalar >::dummy_precision())
bool abs2(bool x)
EIGEN_ALWAYS_INLINE float sqrt(const float &x)
: InteropHeaders
Definition: Core:139
const int Infinity
Definition: Constants.h:38
const int Dynamic
Definition: Constants.h:24
Eigen::Index Index
The interface type of indices.
Definition: EigenBase.h:41
Holds information about the various numeric (i.e. scalar) types allowed by Eigen.
Definition: NumTraits.h:231
std::ptrdiff_t j