1c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// This file is part of Eigen, a lightweight C++ template library
2c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// for linear algebra.
3c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath//
4c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
5c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath//
6c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// This Source Code Form is subject to the terms of the Mozilla
7c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// Public License v. 2.0. If a copy of the MPL was not distributed
8c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
9c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
10c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#define EIGEN_NO_STATIC_ASSERT
11c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
12c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#include "main.h"
13c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
147faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandeztemplate<bool IsInteger> struct adjoint_specific;
157faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
167faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandeztemplate<> struct adjoint_specific<true> {
177faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  template<typename Vec, typename Mat, typename Scalar>
187faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  static void run(const Vec& v1, const Vec& v2, Vec& v3, const Mat& square, Scalar s1, Scalar s2) {
197faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    VERIFY(test_isApproxWithRef((s1 * v1 + s2 * v2).dot(v3),     numext::conj(s1) * v1.dot(v3) + numext::conj(s2) * v2.dot(v3), 0));
207faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    VERIFY(test_isApproxWithRef(v3.dot(s1 * v1 + s2 * v2),       s1*v3.dot(v1)+s2*v3.dot(v2), 0));
217faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
227faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    // check compatibility of dot and adjoint
237faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    VERIFY(test_isApproxWithRef(v1.dot(square * v2), (square.adjoint() * v1).dot(v2), 0));
247faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  }
257faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez};
267faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
277faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandeztemplate<> struct adjoint_specific<false> {
287faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  template<typename Vec, typename Mat, typename Scalar>
297faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  static void run(const Vec& v1, const Vec& v2, Vec& v3, const Mat& square, Scalar s1, Scalar s2) {
307faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    typedef typename NumTraits<Scalar>::Real RealScalar;
317faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    using std::abs;
327faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
337faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    RealScalar ref = NumTraits<Scalar>::IsInteger ? RealScalar(0) : (std::max)((s1 * v1 + s2 * v2).norm(),v3.norm());
347faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    VERIFY(test_isApproxWithRef((s1 * v1 + s2 * v2).dot(v3),     numext::conj(s1) * v1.dot(v3) + numext::conj(s2) * v2.dot(v3), ref));
357faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    VERIFY(test_isApproxWithRef(v3.dot(s1 * v1 + s2 * v2),       s1*v3.dot(v1)+s2*v3.dot(v2), ref));
367faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
377faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    VERIFY_IS_APPROX(v1.squaredNorm(),                v1.norm() * v1.norm());
387faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    // check normalized() and normalize()
397faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    VERIFY_IS_APPROX(v1, v1.norm() * v1.normalized());
407faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    v3 = v1;
417faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    v3.normalize();
427faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    VERIFY_IS_APPROX(v1, v1.norm() * v3);
437faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    VERIFY_IS_APPROX(v3, v1.normalized());
447faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    VERIFY_IS_APPROX(v3.norm(), RealScalar(1));
457faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
467faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    // check compatibility of dot and adjoint
477faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    ref = NumTraits<Scalar>::IsInteger ? 0 : (std::max)((std::max)(v1.norm(),v2.norm()),(std::max)((square * v2).norm(),(square.adjoint() * v1).norm()));
487faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    VERIFY(internal::isMuchSmallerThan(abs(v1.dot(square * v2) - (square.adjoint() * v1).dot(v2)), ref, test_precision<Scalar>()));
497faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
507faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    // check that Random().normalized() works: tricky as the random xpr must be evaluated by
517faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    // normalized() in order to produce a consistent result.
527faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    VERIFY_IS_APPROX(Vec::Random(v1.size()).normalized().norm(), RealScalar(1));
537faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  }
547faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez};
557faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
56c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename MatrixType> void adjoint(const MatrixType& m)
57c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
58c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  /* this test covers the following files:
59c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     Transpose.h Conjugate.h Dot.h
60c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  */
617faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  using std::abs;
62c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef typename MatrixType::Index Index;
63c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef typename MatrixType::Scalar Scalar;
64c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef typename NumTraits<Scalar>::Real RealScalar;
65c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
66c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> SquareMatrixType;
67c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
68c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  Index rows = m.rows();
69c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  Index cols = m.cols();
70c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
71c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  MatrixType m1 = MatrixType::Random(rows, cols),
72c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath             m2 = MatrixType::Random(rows, cols),
73c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath             m3(rows, cols),
74c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath             square = SquareMatrixType::Random(rows, rows);
75c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  VectorType v1 = VectorType::Random(rows),
76c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath             v2 = VectorType::Random(rows),
77c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath             v3 = VectorType::Random(rows),
78c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath             vzero = VectorType::Zero(rows);
79c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
80c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  Scalar s1 = internal::random<Scalar>(),
81c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath         s2 = internal::random<Scalar>();
82c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
83c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  // check basic compatibility of adjoint, transpose, conjugate
84c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  VERIFY_IS_APPROX(m1.transpose().conjugate().adjoint(),    m1);
85c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  VERIFY_IS_APPROX(m1.adjoint().conjugate().transpose(),    m1);
86c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
87c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  // check multiplicative behavior
88c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  VERIFY_IS_APPROX((m1.adjoint() * m2).adjoint(),           m2.adjoint() * m1);
897faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  VERIFY_IS_APPROX((s1 * m1).adjoint(),                     numext::conj(s1) * m1.adjoint());
90c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
917faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  // check basic properties of dot, squaredNorm
927faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  VERIFY_IS_APPROX(numext::conj(v1.dot(v2)),               v2.dot(v1));
937faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  VERIFY_IS_APPROX(numext::real(v1.dot(v1)),               v1.squaredNorm());
94c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
957faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  adjoint_specific<NumTraits<Scalar>::IsInteger>::run(v1, v2, v3, square, s1, s2);
96c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
977faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  VERIFY_IS_MUCH_SMALLER_THAN(abs(vzero.dot(v1)),  static_cast<RealScalar>(1));
98c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
99c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  // like in testBasicStuff, test operator() to check const-qualification
100c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  Index r = internal::random<Index>(0, rows-1),
101c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      c = internal::random<Index>(0, cols-1);
1027faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  VERIFY_IS_APPROX(m1.conjugate()(r,c), numext::conj(m1(r,c)));
1037faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  VERIFY_IS_APPROX(m1.adjoint()(c,r), numext::conj(m1(r,c)));
104c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
105c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  // check inplace transpose
106c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  m3 = m1;
107c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  m3.transposeInPlace();
108c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  VERIFY_IS_APPROX(m3,m1.transpose());
109c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  m3.transposeInPlace();
110c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  VERIFY_IS_APPROX(m3,m1);
111c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
112c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  // check inplace adjoint
113c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  m3 = m1;
114c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  m3.adjointInPlace();
115c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  VERIFY_IS_APPROX(m3,m1.adjoint());
116c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  m3.transposeInPlace();
117c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  VERIFY_IS_APPROX(m3,m1.conjugate());
118c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
119c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  // check mixed dot product
120c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef Matrix<RealScalar, MatrixType::RowsAtCompileTime, 1> RealVectorType;
121c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  RealVectorType rv1 = RealVectorType::Random(rows);
122c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  VERIFY_IS_APPROX(v1.dot(rv1.template cast<Scalar>()), v1.dot(rv1));
123c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  VERIFY_IS_APPROX(rv1.template cast<Scalar>().dot(v1), rv1.dot(v1));
124c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath}
125c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
126c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathvoid test_adjoint()
127c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
128c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  for(int i = 0; i < g_repeat; i++) {
129c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    CALL_SUBTEST_1( adjoint(Matrix<float, 1, 1>()) );
130c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    CALL_SUBTEST_2( adjoint(Matrix3d()) );
131c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    CALL_SUBTEST_3( adjoint(Matrix4f()) );
132c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    CALL_SUBTEST_4( adjoint(MatrixXcf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2), internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2))) );
133c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    CALL_SUBTEST_5( adjoint(MatrixXi(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
134c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    CALL_SUBTEST_6( adjoint(MatrixXf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
135c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  }
136c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  // test a large static matrix only once
137c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  CALL_SUBTEST_7( adjoint(Matrix<float, 100, 100>()) );
138c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
139c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#ifdef EIGEN_TEST_PART_4
140c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  {
141c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    MatrixXcf a(10,10), b(10,10);
142c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    VERIFY_RAISES_ASSERT(a = a.transpose());
143c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    VERIFY_RAISES_ASSERT(a = a.transpose() + b);
144c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    VERIFY_RAISES_ASSERT(a = b + a.transpose());
145c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    VERIFY_RAISES_ASSERT(a = a.conjugate().transpose());
146c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    VERIFY_RAISES_ASSERT(a = a.adjoint());
147c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    VERIFY_RAISES_ASSERT(a = a.adjoint() + b);
148c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    VERIFY_RAISES_ASSERT(a = b + a.adjoint());
149c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
150c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    // no assertion should be triggered for these cases:
151c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    a.transpose() = a.transpose();
152c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    a.transpose() += a.transpose();
153c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    a.transpose() += a.transpose() + b;
154c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    a.transpose() = a.adjoint();
155c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    a.transpose() += a.adjoint();
156c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    a.transpose() += a.adjoint() + b;
157c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  }
158c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#endif
159c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath}
160c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
161