umeyama.cpp File Reference
#include "main.h"
#include <Eigen/Core>
#include <Eigen/Geometry>
#include <Eigen/LU>
#include <Eigen/SVD>

Functions

template<typename T >
Eigen::Matrix< T, Eigen::Dynamic, Eigen::DynamicrandMatrixUnitary (int size)
 
template<typename T >
Eigen::Matrix< T, Eigen::Dynamic, Eigen::DynamicrandMatrixSpecialUnitary (int size)
 
template<typename MatrixType >
void run_test (int dim, int num_elements)
 
template<typename Scalar , int Dimension>
void run_fixed_size_test (int num_elements)
 
 EIGEN_DECLARE_TEST (umeyama)
 

Function Documentation

◆ EIGEN_DECLARE_TEST()

EIGEN_DECLARE_TEST ( umeyama  )
148  {
149  for (int i = 0; i < g_repeat; ++i) {
150  const int num_elements = internal::random<int>(40, 500);
151 
152  // works also for dimensions bigger than 3...
153  for (int dim = 2; dim < 8; ++dim) {
154  CALL_SUBTEST_1(run_test<MatrixXd>(dim, num_elements));
155  CALL_SUBTEST_2(run_test<MatrixXf>(dim, num_elements));
156  }
157 
158  CALL_SUBTEST_3((run_fixed_size_test<float, 2>(num_elements)));
159  CALL_SUBTEST_4((run_fixed_size_test<float, 3>(num_elements)));
160  CALL_SUBTEST_5((run_fixed_size_test<float, 4>(num_elements)));
161 
162  CALL_SUBTEST_6((run_fixed_size_test<double, 2>(num_elements)));
163  CALL_SUBTEST_7((run_fixed_size_test<double, 3>(num_elements)));
164  CALL_SUBTEST_8((run_fixed_size_test<double, 4>(num_elements)));
165  }
166 
167  // Those two calls don't compile and result in meaningful error messages!
168  // umeyama(MatrixXcf(),MatrixXcf());
169  // umeyama(MatrixXcd(),MatrixXcd());
170 }
int i
Definition: BiCGSTAB_step_by_step.cpp:9
static int g_repeat
Definition: main.h:191
#define CALL_SUBTEST_6(FUNC)
Definition: split_test_helper.h:34
#define CALL_SUBTEST_3(FUNC)
Definition: split_test_helper.h:16
#define CALL_SUBTEST_1(FUNC)
Definition: split_test_helper.h:4
#define CALL_SUBTEST_8(FUNC)
Definition: split_test_helper.h:46
#define CALL_SUBTEST_5(FUNC)
Definition: split_test_helper.h:28
#define CALL_SUBTEST_2(FUNC)
Definition: split_test_helper.h:10
#define CALL_SUBTEST_7(FUNC)
Definition: split_test_helper.h:40
#define CALL_SUBTEST_4(FUNC)
Definition: split_test_helper.h:22

References CALL_SUBTEST_1, CALL_SUBTEST_2, CALL_SUBTEST_3, CALL_SUBTEST_4, CALL_SUBTEST_5, CALL_SUBTEST_6, CALL_SUBTEST_7, CALL_SUBTEST_8, Eigen::g_repeat, and i.

◆ randMatrixSpecialUnitary()

template<typename T >
Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> randMatrixSpecialUnitary ( int  size)
68  {
69  typedef T Scalar;
70 
72 
73  // initialize unitary matrix
74  MatrixType Q = randMatrixUnitary<Scalar>(size);
75 
76  // tweak the first column to make the determinant be 1
77  Q.col(0) *= numext::conj(Q.determinant());
78 
79  return Q;
80 }
AnnoyingScalar conj(const AnnoyingScalar &x)
Definition: AnnoyingScalar.h:133
MatrixXf Q
Definition: HouseholderQR_householderQ.cpp:1
Scalar Scalar int size
Definition: benchVecAdd.cpp:17
SCALAR Scalar
Definition: bench_gemm.cpp:45
MatrixXf MatrixType
Definition: benchmark-blocking-sizes.cpp:52
The matrix class, also used for vectors and row-vectors.
Definition: Eigen/Eigen/src/Core/Matrix.h:186

References conj(), Q, and size.

◆ randMatrixUnitary()

template<typename T >
Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> randMatrixUnitary ( int  size)
22  {
23  typedef T Scalar;
25 
26  MatrixType Q;
27 
28  int max_tries = 40;
29  bool is_unitary = false;
30 
31  while (!is_unitary && max_tries > 0) {
32  // initialize random matrix
33  Q = MatrixType::Random(size, size);
34 
35  // orthogonalize columns using the Gram-Schmidt algorithm
36  for (int col = 0; col < size; ++col) {
37  typename MatrixType::ColXpr colVec = Q.col(col);
38  for (int prevCol = 0; prevCol < col; ++prevCol) {
39  typename MatrixType::ColXpr prevColVec = Q.col(prevCol);
40  colVec -= colVec.dot(prevColVec) * prevColVec;
41  }
42  Q.col(col) = colVec.normalized();
43  }
44 
45  // this additional orthogonalization is not necessary in theory but should enhance
46  // the numerical orthogonality of the matrix
47  for (int row = 0; row < size; ++row) {
48  typename MatrixType::RowXpr rowVec = Q.row(row);
49  for (int prevRow = 0; prevRow < row; ++prevRow) {
50  typename MatrixType::RowXpr prevRowVec = Q.row(prevRow);
51  rowVec -= rowVec.dot(prevRowVec) * prevRowVec;
52  }
53  Q.row(row) = rowVec.normalized();
54  }
55 
56  // final check
57  is_unitary = Q.isUnitary();
58  --max_tries;
59  }
60 
61  if (max_tries == 0) eigen_assert(false && "randMatrixUnitary: Could not construct unitary matrix!");
62 
63  return Q;
64 }
#define eigen_assert(x)
Definition: Macros.h:910
m col(1)
m row(1)

References col(), eigen_assert, Q, row(), and size.

◆ run_fixed_size_test()

template<typename Scalar , int Dimension>
void run_fixed_size_test ( int  num_elements)
112  {
113  using std::abs;
116  typedef Matrix<Scalar, Dimension, Dimension> FixedMatrix;
117  typedef Matrix<Scalar, Dimension, 1> FixedVector;
118 
119  const int dim = Dimension;
120 
121  // MUST be positive because in any other case det(cR_t) may become negative for
122  // odd dimensions!
123  // Also if c is to small compared to t.norm(), problem is ill-posed (cf. Bug 744)
124  const Scalar c = internal::random<Scalar>(0.5, 2.0);
125 
126  FixedMatrix R = randMatrixSpecialUnitary<Scalar>(dim);
127  FixedVector t = Scalar(32) * FixedVector::Random(dim, 1);
128 
129  HomMatrix cR_t = HomMatrix::Identity(dim + 1, dim + 1);
130  cR_t.block(0, 0, dim, dim) = c * R;
131  cR_t.block(0, dim, dim, 1) = t;
132 
133  MatrixX src = MatrixX::Random(dim + 1, num_elements);
134  src.row(dim) = Matrix<Scalar, 1, Dynamic>::Constant(num_elements, Scalar(1));
135 
136  MatrixX dst = cR_t * src;
137 
138  Block<MatrixX, Dimension, Dynamic> src_block(src, 0, 0, dim, num_elements);
139  Block<MatrixX, Dimension, Dynamic> dst_block(dst, 0, 0, dim, num_elements);
140 
141  HomMatrix cR_t_umeyama = umeyama(src_block, dst_block);
142 
143  const Scalar error = (cR_t_umeyama * src - dst).squaredNorm();
144 
146 }
AnnoyingScalar abs(const AnnoyingScalar &x)
Definition: AnnoyingScalar.h:135
@ R
Definition: StatisticsVector.h:21
Expression of a fixed-size or dynamic-size block.
Definition: Block.h:110
internal::umeyama_transform_matrix_type< Derived, OtherDerived >::type umeyama(const MatrixBase< Derived > &src, const MatrixBase< OtherDerived > &dst, bool with_scaling=true)
Returns the transformation between two point sets.
Definition: Umeyama.h:94
#define VERIFY(a)
Definition: main.h:362
int c
Definition: calibrate.py:100
int error
Definition: calibrate.py:297
double epsilon
Definition: osc_ring_sarah_asymptotics.h:43
t
Definition: plotPSD.py:36

References abs(), calibrate::c, oomph::SarahBL::epsilon, calibrate::error, R, plotPSD::t, Eigen::umeyama(), and VERIFY.

◆ run_test()

template<typename MatrixType >
void run_test ( int  dim,
int  num_elements 
)
83  {
84  using std::abs;
88 
89  // MUST be positive because in any other case det(cR_t) may become negative for
90  // odd dimensions!
91  const Scalar c = abs(internal::random<Scalar>());
92 
93  MatrixX R = randMatrixSpecialUnitary<Scalar>(dim);
94  VectorX t = Scalar(50) * VectorX::Random(dim, 1);
95 
96  MatrixX cR_t = MatrixX::Identity(dim + 1, dim + 1);
97  cR_t.block(0, 0, dim, dim) = c * R;
98  cR_t.block(0, dim, dim, 1) = t;
99 
100  MatrixX src = MatrixX::Random(dim + 1, num_elements);
101  src.row(dim) = Matrix<Scalar, 1, Dynamic>::Constant(num_elements, Scalar(1));
102 
103  MatrixX dst = cR_t * src;
104 
105  MatrixX cR_t_umeyama = umeyama(src.block(0, 0, dim, num_elements), dst.block(0, 0, dim, num_elements));
106 
107  const Scalar error = (cR_t_umeyama * src - dst).norm() / dst.norm();
109 }
Matrix< Scalar, Dynamic, 1 > VectorX
Definition: sparse_lu.cpp:43

References abs(), calibrate::c, oomph::SarahBL::epsilon, calibrate::error, R, plotPSD::t, Eigen::umeyama(), and VERIFY.