1 // This file is part of Eigen, a lightweight C++ template library
4 // Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
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/.
10 #define EIGEN_NO_STATIC_ASSERT
14 template<bool IsInteger
> struct adjoint_specific
;
16 template<> struct adjoint_specific
<true> {
17 template<typename Vec
, typename Mat
, typename Scalar
>
18 static void run(const Vec
& v1
, const Vec
& v2
, Vec
& v3
, const Mat
& square
, Scalar s1
, Scalar s2
) {
19 VERIFY(test_isApproxWithRef((s1
* v1
+ s2
* v2
).dot(v3
), numext::conj(s1
) * v1
.dot(v3
) + numext::conj(s2
) * v2
.dot(v3
), 0));
20 VERIFY(test_isApproxWithRef(v3
.dot(s1
* v1
+ s2
* v2
), s1
*v3
.dot(v1
)+s2
*v3
.dot(v2
), 0));
22 // check compatibility of dot and adjoint
23 VERIFY(test_isApproxWithRef(v1
.dot(square
* v2
), (square
.adjoint() * v1
).dot(v2
), 0));
27 template<> struct adjoint_specific
<false> {
28 template<typename Vec
, typename Mat
, typename Scalar
>
29 static void run(const Vec
& v1
, const Vec
& v2
, Vec
& v3
, const Mat
& square
, Scalar s1
, Scalar s2
) {
30 typedef typename NumTraits
<Scalar
>::Real RealScalar
;
33 RealScalar ref
= NumTraits
<Scalar
>::IsInteger
? RealScalar(0) : (std::max
)((s1
* v1
+ s2
* v2
).norm(),v3
.norm());
34 VERIFY(test_isApproxWithRef((s1
* v1
+ s2
* v2
).dot(v3
), numext::conj(s1
) * v1
.dot(v3
) + numext::conj(s2
) * v2
.dot(v3
), ref
));
35 VERIFY(test_isApproxWithRef(v3
.dot(s1
* v1
+ s2
* v2
), s1
*v3
.dot(v1
)+s2
*v3
.dot(v2
), ref
));
37 VERIFY_IS_APPROX(v1
.squaredNorm(), v1
.norm() * v1
.norm());
38 // check normalized() and normalize()
39 VERIFY_IS_APPROX(v1
, v1
.norm() * v1
.normalized());
42 VERIFY_IS_APPROX(v1
, v1
.norm() * v3
);
43 VERIFY_IS_APPROX(v3
, v1
.normalized());
44 VERIFY_IS_APPROX(v3
.norm(), RealScalar(1));
46 // check compatibility of dot and adjoint
47 ref
= NumTraits
<Scalar
>::IsInteger
? 0 : (std::max
)((std::max
)(v1
.norm(),v2
.norm()),(std::max
)((square
* v2
).norm(),(square
.adjoint() * v1
).norm()));
48 VERIFY(internal::isMuchSmallerThan(abs(v1
.dot(square
* v2
) - (square
.adjoint() * v1
).dot(v2
)), ref
, test_precision
<Scalar
>()));
50 // check that Random().normalized() works: tricky as the random xpr must be evaluated by
51 // normalized() in order to produce a consistent result.
52 VERIFY_IS_APPROX(Vec::Random(v1
.size()).normalized().norm(), RealScalar(1));
56 template<typename MatrixType
> void adjoint(const MatrixType
& m
)
58 /* this test covers the following files:
59 Transpose.h Conjugate.h Dot.h
62 typedef typename
MatrixType::Index Index
;
63 typedef typename
MatrixType::Scalar Scalar
;
64 typedef typename NumTraits
<Scalar
>::Real RealScalar
;
65 typedef Matrix
<Scalar
, MatrixType::RowsAtCompileTime
, 1> VectorType
;
66 typedef Matrix
<Scalar
, MatrixType::RowsAtCompileTime
, MatrixType::RowsAtCompileTime
> SquareMatrixType
;
68 Index rows
= m
.rows();
69 Index cols
= m
.cols();
71 MatrixType m1
= MatrixType::Random(rows
, cols
),
72 m2
= MatrixType::Random(rows
, cols
),
74 square
= SquareMatrixType::Random(rows
, rows
);
75 VectorType v1
= VectorType::Random(rows
),
76 v2
= VectorType::Random(rows
),
77 v3
= VectorType::Random(rows
),
78 vzero
= VectorType::Zero(rows
);
80 Scalar s1
= internal::random
<Scalar
>(),
81 s2
= internal::random
<Scalar
>();
83 // check basic compatibility of adjoint, transpose, conjugate
84 VERIFY_IS_APPROX(m1
.transpose().conjugate().adjoint(), m1
);
85 VERIFY_IS_APPROX(m1
.adjoint().conjugate().transpose(), m1
);
87 // check multiplicative behavior
88 VERIFY_IS_APPROX((m1
.adjoint() * m2
).adjoint(), m2
.adjoint() * m1
);
89 VERIFY_IS_APPROX((s1
* m1
).adjoint(), numext::conj(s1
) * m1
.adjoint());
91 // check basic properties of dot, squaredNorm
92 VERIFY_IS_APPROX(numext::conj(v1
.dot(v2
)), v2
.dot(v1
));
93 VERIFY_IS_APPROX(numext::real(v1
.dot(v1
)), v1
.squaredNorm());
95 adjoint_specific
<NumTraits
<Scalar
>::IsInteger
>::run(v1
, v2
, v3
, square
, s1
, s2
);
97 VERIFY_IS_MUCH_SMALLER_THAN(abs(vzero
.dot(v1
)), static_cast<RealScalar
>(1));
99 // like in testBasicStuff, test operator() to check const-qualification
100 Index r
= internal::random
<Index
>(0, rows
-1),
101 c
= internal::random
<Index
>(0, cols
-1);
102 VERIFY_IS_APPROX(m1
.conjugate()(r
,c
), numext::conj(m1(r
,c
)));
103 VERIFY_IS_APPROX(m1
.adjoint()(c
,r
), numext::conj(m1(r
,c
)));
105 // check inplace transpose
107 m3
.transposeInPlace();
108 VERIFY_IS_APPROX(m3
,m1
.transpose());
109 m3
.transposeInPlace();
110 VERIFY_IS_APPROX(m3
,m1
);
112 // check inplace adjoint
115 VERIFY_IS_APPROX(m3
,m1
.adjoint());
116 m3
.transposeInPlace();
117 VERIFY_IS_APPROX(m3
,m1
.conjugate());
119 // check mixed dot product
120 typedef Matrix
<RealScalar
, MatrixType::RowsAtCompileTime
, 1> RealVectorType
;
121 RealVectorType rv1
= RealVectorType::Random(rows
);
122 VERIFY_IS_APPROX(v1
.dot(rv1
.template cast
<Scalar
>()), v1
.dot(rv1
));
123 VERIFY_IS_APPROX(rv1
.template cast
<Scalar
>().dot(v1
), rv1
.dot(v1
));
128 for(int i
= 0; i
< g_repeat
; i
++) {
129 CALL_SUBTEST_1( adjoint(Matrix
<float, 1, 1>()) );
130 CALL_SUBTEST_2( adjoint(Matrix3d()) );
131 CALL_SUBTEST_3( adjoint(Matrix4f()) );
132 CALL_SUBTEST_4( adjoint(MatrixXcf(internal::random
<int>(1,EIGEN_TEST_MAX_SIZE
/2), internal::random
<int>(1,EIGEN_TEST_MAX_SIZE
/2))) );
133 CALL_SUBTEST_5( adjoint(MatrixXi(internal::random
<int>(1,EIGEN_TEST_MAX_SIZE
), internal::random
<int>(1,EIGEN_TEST_MAX_SIZE
))) );
134 CALL_SUBTEST_6( adjoint(MatrixXf(internal::random
<int>(1,EIGEN_TEST_MAX_SIZE
), internal::random
<int>(1,EIGEN_TEST_MAX_SIZE
))) );
136 // test a large static matrix only once
137 CALL_SUBTEST_7( adjoint(Matrix
<float, 100, 100>()) );
139 #ifdef EIGEN_TEST_PART_4
141 MatrixXcf
a(10,10), b(10,10);
142 VERIFY_RAISES_ASSERT(a
= a
.transpose());
143 VERIFY_RAISES_ASSERT(a
= a
.transpose() + b
);
144 VERIFY_RAISES_ASSERT(a
= b
+ a
.transpose());
145 VERIFY_RAISES_ASSERT(a
= a
.conjugate().transpose());
146 VERIFY_RAISES_ASSERT(a
= a
.adjoint());
147 VERIFY_RAISES_ASSERT(a
= a
.adjoint() + b
);
148 VERIFY_RAISES_ASSERT(a
= b
+ a
.adjoint());
150 // no assertion should be triggered for these cases:
151 a
.transpose() = a
.transpose();
152 a
.transpose() += a
.transpose();
153 a
.transpose() += a
.transpose() + b
;
154 a
.transpose() = a
.adjoint();
155 a
.transpose() += a
.adjoint();
156 a
.transpose() += a
.adjoint() + b
;