mirror of
https://gitlab.com/libeigen/eigen.git
synced 2024-12-21 07:19:46 +08:00
218 lines
7.0 KiB
C++
218 lines
7.0 KiB
C++
// This file is part of Eigen, a lightweight C++ template library
|
|
// for linear algebra.
|
|
//
|
|
// This Source Code Form is subject to the terms of the Mozilla
|
|
// Public License v. 2.0. If a copy of the MPL was not distributed
|
|
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
#include "main.h"
|
|
#include <Eigen/LU>
|
|
|
|
namespace {
|
|
template <typename Scalar>
|
|
void constructors() {
|
|
typedef Matrix<Scalar, 3, 1> Vector;
|
|
const Vector v = Vector::Random();
|
|
// l-value
|
|
const SkewSymmetricMatrix3<Scalar> s1(v);
|
|
const Vector& v1 = s1.vector();
|
|
VERIFY_IS_APPROX(v1, v);
|
|
VERIFY(s1.cols() == 3);
|
|
VERIFY(s1.rows() == 3);
|
|
|
|
// r-value
|
|
const SkewSymmetricMatrix3<Scalar> s2(std::move(v));
|
|
VERIFY_IS_APPROX(v1, s2.vector());
|
|
VERIFY_IS_APPROX(s1.toDenseMatrix(), s2.toDenseMatrix());
|
|
|
|
// from scalars
|
|
SkewSymmetricMatrix3<Scalar> s4(v1(0), v1(1), v1(2));
|
|
VERIFY_IS_APPROX(v1, s4.vector());
|
|
|
|
// constructors with four vectors do not compile
|
|
// Matrix<Scalar, 4, 1> vector4 = Matrix<Scalar, 4, 1>::Random();
|
|
// SkewSymmetricMatrix3<Scalar> s5(vector4);
|
|
}
|
|
|
|
template <typename Scalar>
|
|
void assignments() {
|
|
typedef Matrix<Scalar, 3, 1> Vector;
|
|
typedef Matrix<Scalar, 3, 3> SquareMatrix;
|
|
|
|
const Vector v = Vector::Random();
|
|
|
|
// assign to square matrix
|
|
SquareMatrix sq;
|
|
sq = v.asSkewSymmetric();
|
|
VERIFY(sq.isSkewSymmetric());
|
|
|
|
// assign to skew symmetric matrix
|
|
SkewSymmetricMatrix3<Scalar> sk;
|
|
sk = v.asSkewSymmetric();
|
|
VERIFY_IS_APPROX(v, sk.vector());
|
|
}
|
|
|
|
template <typename Scalar>
|
|
void plusMinus() {
|
|
typedef Matrix<Scalar, 3, 1> Vector;
|
|
typedef Matrix<Scalar, 3, 3> SquareMatrix;
|
|
|
|
const Vector v1 = Vector::Random();
|
|
const Vector v2 = Vector::Random();
|
|
|
|
SquareMatrix sq1;
|
|
sq1 = v1.asSkewSymmetric();
|
|
SquareMatrix sq2;
|
|
sq2 = v2.asSkewSymmetric();
|
|
|
|
SkewSymmetricMatrix3<Scalar> sk1;
|
|
sk1 = v1.asSkewSymmetric();
|
|
SkewSymmetricMatrix3<Scalar> sk2;
|
|
sk2 = v2.asSkewSymmetric();
|
|
|
|
VERIFY_IS_APPROX((sk1 + sk2).toDenseMatrix(), sq1 + sq2);
|
|
VERIFY_IS_APPROX((sk1 - sk2).toDenseMatrix(), sq1 - sq2);
|
|
|
|
SquareMatrix sq3 = v1.asSkewSymmetric();
|
|
VERIFY_IS_APPROX( sq3 = v1.asSkewSymmetric() + v2.asSkewSymmetric(), sq1 + sq2);
|
|
VERIFY_IS_APPROX( sq3 = v1.asSkewSymmetric() - v2.asSkewSymmetric(), sq1 - sq2);
|
|
VERIFY_IS_APPROX( sq3 = v1.asSkewSymmetric() - 2*v2.asSkewSymmetric() + v1.asSkewSymmetric(), sq1 - 2*sq2 + sq1);
|
|
|
|
VERIFY_IS_APPROX((sk1 + sk1).vector(), 2*v1);
|
|
VERIFY((sk1 - sk1).vector().isZero());
|
|
VERIFY((sk1 - sk1).toDenseMatrix().isZero());
|
|
}
|
|
|
|
|
|
template <typename Scalar>
|
|
void multiplyScale() {
|
|
typedef Matrix<Scalar, 3, 1> Vector;
|
|
typedef Matrix<Scalar, 3, 3> SquareMatrix;
|
|
|
|
const Vector v1 = Vector::Random();
|
|
SquareMatrix sq1;
|
|
sq1 = v1.asSkewSymmetric();
|
|
SkewSymmetricMatrix3<Scalar> sk1;
|
|
sk1 = v1.asSkewSymmetric();
|
|
|
|
const Scalar s1 = internal::random<Scalar>();
|
|
VERIFY_IS_APPROX(SkewSymmetricMatrix3<Scalar>(sk1*s1).vector(), sk1.vector() * s1);
|
|
VERIFY_IS_APPROX(SkewSymmetricMatrix3<Scalar>(s1*sk1).vector(), s1 * sk1.vector());
|
|
VERIFY_IS_APPROX(sq1 * (sk1 * s1), (sq1 * sk1) * s1);
|
|
|
|
const Vector v2 = Vector::Random();
|
|
SquareMatrix sq2;
|
|
sq2 = v2.asSkewSymmetric();
|
|
SkewSymmetricMatrix3<Scalar> sk2;
|
|
sk2 = v2.asSkewSymmetric();
|
|
VERIFY_IS_APPROX(sk1*sk2, sq1*sq2);
|
|
|
|
// null space
|
|
VERIFY((sk1*v1).isZero());
|
|
VERIFY((sk2*v2).isZero());
|
|
}
|
|
|
|
template<typename Matrix>
|
|
void skewSymmetricMultiplication(const Matrix& m) {
|
|
typedef Eigen::Matrix<typename Matrix::Scalar, 3, 1> Vector;
|
|
const Vector v = Vector::Random();
|
|
const Matrix m1 = Matrix::Random(m.rows(), m.cols());
|
|
const SkewSymmetricMatrix3<typename Matrix::Scalar> sk = v.asSkewSymmetric();
|
|
VERIFY_IS_APPROX(m1.transpose() * (sk * m1), (m1.transpose() * sk) * m1);
|
|
VERIFY((m1.transpose() * (sk * m1)).isSkewSymmetric());
|
|
}
|
|
|
|
template <typename Scalar>
|
|
void traceAndDet() {
|
|
typedef Matrix<Scalar, 3, 1> Vector;
|
|
const Vector v = Vector::Random();
|
|
// this does not work, values larger than 1.e-08 can be seen
|
|
//VERIFY_IS_APPROX(sq.determinant(), static_cast<Scalar>(0));
|
|
VERIFY_IS_APPROX(v.asSkewSymmetric().determinant(), static_cast<Scalar>(0));
|
|
VERIFY_IS_APPROX(v.asSkewSymmetric().toDenseMatrix().trace(), static_cast<Scalar>(0));
|
|
}
|
|
|
|
template <typename Scalar>
|
|
void transpose() {
|
|
typedef Matrix<Scalar, 3, 1> Vector;
|
|
const Vector v = Vector::Random();
|
|
// By definition of a skew symmetric matrix: A^T = -A
|
|
VERIFY_IS_APPROX(v.asSkewSymmetric().toDenseMatrix().transpose(), v.asSkewSymmetric().transpose().toDenseMatrix());
|
|
VERIFY_IS_APPROX(v.asSkewSymmetric().transpose().vector(), (-v).asSkewSymmetric().vector());
|
|
}
|
|
|
|
template <typename Scalar>
|
|
void exponentialIdentity() {
|
|
typedef Matrix<Scalar, 3, 1> Vector;
|
|
const Vector v1 = Vector::Zero();
|
|
VERIFY(v1.asSkewSymmetric().exponential().isIdentity());
|
|
|
|
Vector v2 = Vector::Random();
|
|
v2.normalize();
|
|
VERIFY((2*EIGEN_PI*v2).asSkewSymmetric().exponential().isIdentity());
|
|
|
|
Vector v3;
|
|
const auto precision = static_cast<Scalar>(1.1)*NumTraits<Scalar>::dummy_precision();
|
|
v3 << 0, 0, precision;
|
|
VERIFY(v3.asSkewSymmetric().exponential().isIdentity(precision));
|
|
}
|
|
|
|
template <typename Scalar>
|
|
void exponentialOrthogonality() {
|
|
typedef Matrix<Scalar, 3, 1> Vector;
|
|
typedef Matrix<Scalar, 3, 3> SquareMatrix;
|
|
const Vector v = Vector::Random();
|
|
SquareMatrix sq = v.asSkewSymmetric().exponential();
|
|
VERIFY(sq.isUnitary());
|
|
}
|
|
|
|
template <typename Scalar>
|
|
void exponentialRotation() {
|
|
typedef Matrix<Scalar, 3, 1> Vector;
|
|
typedef Matrix<Scalar, 3, 3> SquareMatrix;
|
|
|
|
// rotation axis is invariant
|
|
const Vector v1 = Vector::Random();
|
|
const SquareMatrix r1 = v1.asSkewSymmetric().exponential();
|
|
VERIFY_IS_APPROX(r1*v1, v1);
|
|
|
|
// rotate around z-axis
|
|
Vector v2;
|
|
v2 << 0, 0, EIGEN_PI;
|
|
const SquareMatrix r2 = v2.asSkewSymmetric().exponential();
|
|
VERIFY_IS_APPROX(r2*(Vector() << 1,0,0).finished(), (Vector() << -1,0,0).finished());
|
|
VERIFY_IS_APPROX(r2*(Vector() << 0,1,0).finished(), (Vector() << 0,-1,0).finished());
|
|
}
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
EIGEN_DECLARE_TEST(skew_symmetric_matrix3)
|
|
{
|
|
for(int i = 0; i < g_repeat; i++) {
|
|
CALL_SUBTEST_1(constructors<float>());
|
|
CALL_SUBTEST_1(constructors<double>());
|
|
CALL_SUBTEST_1(assignments<float>());
|
|
CALL_SUBTEST_1(assignments<double>());
|
|
|
|
CALL_SUBTEST_2(plusMinus<float>());
|
|
CALL_SUBTEST_2(plusMinus<double>());
|
|
CALL_SUBTEST_2(multiplyScale<float>());
|
|
CALL_SUBTEST_2(multiplyScale<double>());
|
|
CALL_SUBTEST_2(skewSymmetricMultiplication(MatrixXf(3,internal::random<int>(1,EIGEN_TEST_MAX_SIZE))));
|
|
CALL_SUBTEST_2(skewSymmetricMultiplication(MatrixXd(3,internal::random<int>(1,EIGEN_TEST_MAX_SIZE))));
|
|
CALL_SUBTEST_2(traceAndDet<float>());
|
|
CALL_SUBTEST_2(traceAndDet<double>());
|
|
CALL_SUBTEST_2(transpose<float>());
|
|
CALL_SUBTEST_2(transpose<double>());
|
|
|
|
CALL_SUBTEST_3(exponentialIdentity<float>());
|
|
CALL_SUBTEST_3(exponentialIdentity<double>());
|
|
CALL_SUBTEST_3(exponentialOrthogonality<float>());
|
|
CALL_SUBTEST_3(exponentialOrthogonality<double>());
|
|
CALL_SUBTEST_3(exponentialRotation<float>());
|
|
CALL_SUBTEST_3(exponentialRotation<double>());
|
|
}
|
|
}
|