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 // Eigen is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 3 of the License, or (at your option) any later version.
10 //
11 // Alternatively, you can redistribute it and/or
12 // modify it under the terms of the GNU General Public License as
13 // published by the Free Software Foundation; either version 2 of
14 // the License, or (at your option) any later version.
15 //
16 // Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
17 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
19 // GNU General Public License for more details.
20 //
21 // You should have received a copy of the GNU Lesser General Public
22 // License and a copy of the GNU General Public License along with
23 // Eigen. If not, see <http://www.gnu.org/licenses/>.
24 
25 #ifndef EIGEN_DOT_H
26 #define EIGEN_DOT_H
27 
28 namespace Eigen {
29 
30 namespace internal {
31 
32 // helper function for dot(). The problem is that if we put that in the body of dot(), then upon calling dot
33 // with mismatched types, the compiler emits errors about failing to instantiate cwiseProduct BEFORE
34 // looking at the static assertions. Thus this is a trick to get better compile errors.
35 template<typename T, typename U,
36 // the NeedToTranspose condition here is taken straight from Assign.h
37  bool NeedToTranspose = T::IsVectorAtCompileTime
38  && U::IsVectorAtCompileTime
39  && ((int(T::RowsAtCompileTime) == 1 && int(U::ColsAtCompileTime) == 1)
40  | // FIXME | instead of || to please GCC 4.4.0 stupid warning "suggest parentheses around &&".
41  // revert to || as soon as not needed anymore.
42  (int(T::ColsAtCompileTime) == 1 && int(U::RowsAtCompileTime) == 1))
43 >
44 struct dot_nocheck
45 {
46  typedef typename scalar_product_traits<typename traits<T>::Scalar,typename traits<U>::Scalar>::ReturnType ResScalar;
47  static inline ResScalar run(const MatrixBase<T>& a, const MatrixBase<U>& b)
48  {
49  return a.template binaryExpr<scalar_conj_product_op<typename traits<T>::Scalar,typename traits<U>::Scalar> >(b).sum();
50  }
51 };
52 
53 template<typename T, typename U>
54 struct dot_nocheck<T, U, true>
55 {
56  typedef typename scalar_product_traits<typename traits<T>::Scalar,typename traits<U>::Scalar>::ReturnType ResScalar;
57  static inline ResScalar run(const MatrixBase<T>& a, const MatrixBase<U>& b)
58  {
59  return a.transpose().template binaryExpr<scalar_conj_product_op<typename traits<T>::Scalar,typename traits<U>::Scalar> >(b).sum();
60  }
61 };
62 
63 } // end namespace internal
64 
75 template<typename Derived>
76 template<typename OtherDerived>
77 typename internal::scalar_product_traits<typename internal::traits<Derived>::Scalar,typename internal::traits<OtherDerived>::Scalar>::ReturnType
79 {
82  EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(Derived,OtherDerived)
83  typedef internal::scalar_conj_product_op<Scalar,typename OtherDerived::Scalar> func;
84  EIGEN_CHECK_BINARY_COMPATIBILIY(func,Scalar,typename OtherDerived::Scalar);
85 
86  eigen_assert(size() == other.size());
87 
88  return internal::dot_nocheck<Derived,OtherDerived>::run(*this, other);
89 }
90 
91 #ifdef EIGEN2_SUPPORT
92 
101 template<typename Derived>
102 template<typename OtherDerived>
103 typename internal::traits<Derived>::Scalar
105 {
107  EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived)
108  EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(Derived,OtherDerived)
109  EIGEN_STATIC_ASSERT((internal::is_same<Scalar, typename OtherDerived::Scalar>::value),
110  YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
111 
112  eigen_assert(size() == other.size());
113 
114  return internal::dot_nocheck<OtherDerived,Derived>::run(other,*this);
115 }
116 #endif
117 
118 
119 //---------- implementation of L2 norm and related functions ----------
120 
127 template<typename Derived>
129 {
130  return internal::real((*this).cwiseAbs2().sum());
131 }
132 
139 template<typename Derived>
141 {
142  return internal::sqrt(squaredNorm());
143 }
144 
151 template<typename Derived>
152 inline const typename MatrixBase<Derived>::PlainObject
154 {
155  typedef typename internal::nested<Derived>::type Nested;
156  typedef typename internal::remove_reference<Nested>::type _Nested;
157  _Nested n(derived());
158  return n / n.norm();
159 }
160 
167 template<typename Derived>
169 {
170  *this /= norm();
171 }
172 
173 //---------- implementation of other norms ----------
174 
175 namespace internal {
176 
177 template<typename Derived, int p>
178 struct lpNorm_selector
179 {
180  typedef typename NumTraits<typename traits<Derived>::Scalar>::Real RealScalar;
181  static inline RealScalar run(const MatrixBase<Derived>& m)
182  {
183  return pow(m.cwiseAbs().array().pow(p).sum(), RealScalar(1)/p);
184  }
185 };
186 
187 template<typename Derived>
188 struct lpNorm_selector<Derived, 1>
189 {
190  static inline typename NumTraits<typename traits<Derived>::Scalar>::Real run(const MatrixBase<Derived>& m)
191  {
192  return m.cwiseAbs().sum();
193  }
194 };
195 
196 template<typename Derived>
197 struct lpNorm_selector<Derived, 2>
198 {
199  static inline typename NumTraits<typename traits<Derived>::Scalar>::Real run(const MatrixBase<Derived>& m)
200  {
201  return m.norm();
202  }
203 };
204 
205 template<typename Derived>
206 struct lpNorm_selector<Derived, Infinity>
207 {
208  static inline typename NumTraits<typename traits<Derived>::Scalar>::Real run(const MatrixBase<Derived>& m)
209  {
210  return m.cwiseAbs().maxCoeff();
211  }
212 };
213 
214 } // end namespace internal
215 
222 template<typename Derived>
223 template<int p>
224 inline typename NumTraits<typename internal::traits<Derived>::Scalar>::Real
226 {
227  return internal::lpNorm_selector<Derived, p>::run(*this);
228 }
229 
230 //---------- implementation of isOrthogonal / isUnitary ----------
231 
238 template<typename Derived>
239 template<typename OtherDerived>
241 (const MatrixBase<OtherDerived>& other, RealScalar prec) const
242 {
243  typename internal::nested<Derived,2>::type nested(derived());
244  typename internal::nested<OtherDerived,2>::type otherNested(other.derived());
245  return internal::abs2(nested.dot(otherNested)) <= prec * prec * nested.squaredNorm() * otherNested.squaredNorm();
246 }
247 
259 template<typename Derived>
261 {
262  typename Derived::Nested nested(derived());
263  for(Index i = 0; i < cols(); ++i)
264  {
265  if(!internal::isApprox(nested.col(i).squaredNorm(), static_cast<RealScalar>(1), prec))
266  return false;
267  for(Index j = 0; j < i; ++j)
268  if(!internal::isMuchSmallerThan(nested.col(i).dot(nested.col(j)), static_cast<Scalar>(1), prec))
269  return false;
270  }
271  return true;
272 }
273 
274 } // end namespace Eigen
275 
276 #endif // EIGEN_DOT_H