1
// Copyright (c) 2007, 2008 libmv authors.
3
// Permission is hereby granted, free of charge, to any person obtaining a copy
4
// of this software and associated documentation files (the "Software"), to
5
// deal in the Software without restriction, including without limitation the
6
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7
// sell copies of the Software, and to permit persons to whom the Software is
8
// furnished to do so, subject to the following conditions:
10
// The above copyright notice and this permission notice shall be included in
11
// all copies or substantial portions of the Software.
13
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21
// Matrix and vector classes, based on Eigen2.
23
// Avoid using Eigen2 classes directly; instead typedef them here.
25
#ifndef LIBMV_NUMERIC_NUMERIC_H
26
#define LIBMV_NUMERIC_NUMERIC_H
28
#include <Eigen/Cholesky>
30
#include <Eigen/Eigenvalues>
31
#include <Eigen/Geometry>
36
#if (defined(_WIN32) || defined(__APPLE__) || defined(__FreeBSD__)) && !defined(__MINGW64__)
37
void static sincos (double x, double *sinx, double *cosx) {
41
#endif //_WIN32 || __APPLE__
43
#if (defined(WIN32) || defined(WIN64)) && !defined(__MINGW32__)
44
inline long lround(double d) {
45
return (long)(d>0 ? d+0.5 : ceil(d-0.5));
47
inline int round(double d) {
48
return (d>0) ? int(d+0.5) : int(d-0.5);
50
typedef unsigned int uint;
55
typedef Eigen::MatrixXd Mat;
56
typedef Eigen::VectorXd Vec;
58
typedef Eigen::MatrixXf Matf;
59
typedef Eigen::VectorXf Vecf;
61
typedef Eigen::Matrix<unsigned int, Eigen::Dynamic, Eigen::Dynamic> Matu;
62
typedef Eigen::Matrix<unsigned int, Eigen::Dynamic, 1> Vecu;
63
typedef Eigen::Matrix<unsigned int, 2, 1> Vec2u;
65
typedef Eigen::Matrix<double, 2, 2> Mat2;
66
typedef Eigen::Matrix<double, 2, 3> Mat23;
67
typedef Eigen::Matrix<double, 3, 3> Mat3;
68
typedef Eigen::Matrix<double, 3, 4> Mat34;
69
typedef Eigen::Matrix<double, 3, 5> Mat35;
70
typedef Eigen::Matrix<double, 4, 1> Mat41;
71
typedef Eigen::Matrix<double, 4, 3> Mat43;
72
typedef Eigen::Matrix<double, 4, 4> Mat4;
73
typedef Eigen::Matrix<double, 4, 6> Mat46;
74
typedef Eigen::Matrix<float, 2, 2> Mat2f;
75
typedef Eigen::Matrix<float, 2, 3> Mat23f;
76
typedef Eigen::Matrix<float, 3, 3> Mat3f;
77
typedef Eigen::Matrix<float, 3, 4> Mat34f;
78
typedef Eigen::Matrix<float, 3, 5> Mat35f;
79
typedef Eigen::Matrix<float, 4, 3> Mat43f;
80
typedef Eigen::Matrix<float, 4, 4> Mat4f;
81
typedef Eigen::Matrix<float, 4, 6> Mat46f;
83
typedef Eigen::Matrix<double, 3, 3, Eigen::RowMajor> RMat3;
84
typedef Eigen::Matrix<double, 4, 4, Eigen::RowMajor> RMat4;
86
typedef Eigen::Matrix<double, 2, Eigen::Dynamic> Mat2X;
87
typedef Eigen::Matrix<double, 3, Eigen::Dynamic> Mat3X;
88
typedef Eigen::Matrix<double, 4, Eigen::Dynamic> Mat4X;
89
typedef Eigen::Matrix<double, Eigen::Dynamic, 2> MatX2;
90
typedef Eigen::Matrix<double, Eigen::Dynamic, 3> MatX3;
91
typedef Eigen::Matrix<double, Eigen::Dynamic, 4> MatX4;
92
typedef Eigen::Matrix<double, Eigen::Dynamic, 5> MatX5;
93
typedef Eigen::Matrix<double, Eigen::Dynamic, 6> MatX6;
94
typedef Eigen::Matrix<double, Eigen::Dynamic, 7> MatX7;
95
typedef Eigen::Matrix<double, Eigen::Dynamic, 8> MatX8;
96
typedef Eigen::Matrix<double, Eigen::Dynamic, 9> MatX9;
97
typedef Eigen::Matrix<double, Eigen::Dynamic,15> MatX15;
98
typedef Eigen::Matrix<double, Eigen::Dynamic,16> MatX16;
100
typedef Eigen::Vector2d Vec2;
101
typedef Eigen::Vector3d Vec3;
102
typedef Eigen::Vector4d Vec4;
103
typedef Eigen::Matrix<double, 5, 1> Vec5;
104
typedef Eigen::Matrix<double, 6, 1> Vec6;
105
typedef Eigen::Matrix<double, 7, 1> Vec7;
106
typedef Eigen::Matrix<double, 8, 1> Vec8;
107
typedef Eigen::Matrix<double, 9, 1> Vec9;
108
typedef Eigen::Matrix<double, 10, 1> Vec10;
109
typedef Eigen::Matrix<double, 11, 1> Vec11;
110
typedef Eigen::Matrix<double, 12, 1> Vec12;
111
typedef Eigen::Matrix<double, 13, 1> Vec13;
112
typedef Eigen::Matrix<double, 14, 1> Vec14;
113
typedef Eigen::Matrix<double, 15, 1> Vec15;
114
typedef Eigen::Matrix<double, 16, 1> Vec16;
115
typedef Eigen::Matrix<double, 17, 1> Vec17;
116
typedef Eigen::Matrix<double, 18, 1> Vec18;
117
typedef Eigen::Matrix<double, 19, 1> Vec19;
118
typedef Eigen::Matrix<double, 20, 1> Vec20;
120
typedef Eigen::Vector2f Vec2f;
121
typedef Eigen::Vector3f Vec3f;
122
typedef Eigen::Vector4f Vec4f;
124
typedef Eigen::VectorXi VecXi;
126
typedef Eigen::Vector2i Vec2i;
127
typedef Eigen::Vector3i Vec3i;
128
typedef Eigen::Vector4i Vec4i;
130
typedef Eigen::Matrix<float,
133
Eigen::RowMajor> RMatf;
135
typedef Eigen::NumTraits<double> EigenDouble;
138
using Eigen::Dynamic;
141
// Find U, s, and VT such that
143
// A = U * diag(s) * VT
145
template <typename TMat, typename TVec>
146
inline void SVD(TMat *A, Vec *s, Mat *U, Mat *VT) {
150
// Solve the linear system Ax = 0 via SVD. Store the solution in x, such that
151
// ||x|| = 1.0. Return the singluar value corresponding to the solution.
152
// Destroys A and resizes x if necessary.
153
// TODO(maclean): Take the SVD of the transpose instead of this zero padding.
154
template <typename TMat, typename TVec>
155
double Nullspace(TMat *A, TVec *nullspace) {
156
Eigen::JacobiSVD<TMat> svd(*A, Eigen::ComputeFullV);
157
(*nullspace) = svd.matrixV().col(A->cols()-1);
158
if (A->rows() >= A->cols())
159
return svd.singularValues()(A->cols()-1);
164
// Solve the linear system Ax = 0 via SVD. Finds two solutions, x1 and x2, such
165
// that x1 is the best solution and x2 is the next best solution (in the L2
166
// norm sense). Store the solution in x1 and x2, such that ||x|| = 1.0. Return
167
// the singluar value corresponding to the solution x1. Destroys A and resizes
169
template <typename TMat, typename TVec1, typename TVec2>
170
double Nullspace2(TMat *A, TVec1 *x1, TVec2 *x2) {
171
Eigen::JacobiSVD<TMat> svd(*A, Eigen::ComputeFullV);
172
*x1 = svd.matrixV().col(A->cols() - 1);
173
*x2 = svd.matrixV().col(A->cols() - 2);
174
if (A->rows() >= A->cols())
175
return svd.singularValues()(A->cols()-1);
180
// In place transpose for square matrices.
182
inline void TransposeInPlace(TA *A) {
183
*A = A->transpose().eval();
186
template<typename TVec>
187
inline double NormL1(const TVec &x) {
188
return x.array().abs().sum();
191
template<typename TVec>
192
inline double NormL2(const TVec &x) {
196
template<typename TVec>
197
inline double NormLInfinity(const TVec &x) {
198
return x.array().abs().maxCoeff();
201
template<typename TVec>
202
inline double DistanceL1(const TVec &x, const TVec &y) {
203
return (x - y).array().abs().sum();
206
template<typename TVec>
207
inline double DistanceL2(const TVec &x, const TVec &y) {
208
return (x - y).norm();
210
template<typename TVec>
211
inline double DistanceLInfinity(const TVec &x, const TVec &y) {
212
return (x - y).array().abs().maxCoeff();
215
// Normalize a vector with the L1 norm, and return the norm before it was
217
template<typename TVec>
218
inline double NormalizeL1(TVec *x) {
219
double norm = NormL1(*x);
224
// Normalize a vector with the L2 norm, and return the norm before it was
226
template<typename TVec>
227
inline double NormalizeL2(TVec *x) {
228
double norm = NormL2(*x);
233
// Normalize a vector with the L^Infinity norm, and return the norm before it
235
template<typename TVec>
236
inline double NormalizeLInfinity(TVec *x) {
237
double norm = NormLInfinity(*x);
242
// Return the square of a number.
244
inline T Square(T x) {
248
Mat3 RotationAroundX(double angle);
249
Mat3 RotationAroundY(double angle);
250
Mat3 RotationAroundZ(double angle);
252
// Returns the rotation matrix of a rotation of angle |axis| around axis.
253
// This is computed using the Rodrigues formula, see:
254
// http://mathworld.wolfram.com/RodriguesRotationFormula.html
255
Mat3 RotationRodrigues(const Vec3 &axis);
257
// Make a rotation matrix such that center becomes the direction of the
258
// positive z-axis, and y is oriented close to up.
259
Mat3 LookAt(Vec3 center);
261
// Return a diagonal matrix from a vector containg the diagonal values.
262
template <typename TVec>
263
inline Mat Diag(const TVec &x) {
264
return x.asDiagonal();
267
template<typename TMat>
268
inline double FrobeniusNorm(const TMat &A) {
269
return sqrt(A.array().abs2().sum());
272
template<typename TMat>
273
inline double FrobeniusDistance(const TMat &A, const TMat &B) {
274
return FrobeniusNorm(A - B);
277
inline Vec3 CrossProduct(const Vec3 &x, const Vec3 &y) {
281
Mat3 CrossProductMatrix(const Vec3 &x);
283
void MeanAndVarianceAlongRows(const Mat &A,
285
Vec *variance_pointer);
288
// TODO(bomboze): un-#if this for both platforms once tested under Windows
289
/* This solution was extensively discussed here http://forum.kde.org/viewtopic.php?f=74&t=61940 */
290
#define SUM_OR_DYNAMIC(x,y) (x==Eigen::Dynamic||y==Eigen::Dynamic)?Eigen::Dynamic:(x+y)
292
template<typename Derived1, typename Derived2>
293
struct hstack_return {
294
typedef typename Derived1::Scalar Scalar;
296
RowsAtCompileTime = Derived1::RowsAtCompileTime,
297
ColsAtCompileTime = SUM_OR_DYNAMIC(Derived1::ColsAtCompileTime, Derived2::ColsAtCompileTime),
298
Options = Derived1::Flags&Eigen::RowMajorBit ? Eigen::RowMajor : 0,
299
MaxRowsAtCompileTime = Derived1::MaxRowsAtCompileTime,
300
MaxColsAtCompileTime = SUM_OR_DYNAMIC(Derived1::MaxColsAtCompileTime, Derived2::MaxColsAtCompileTime)
302
typedef Eigen::Matrix<Scalar,
306
MaxRowsAtCompileTime,
307
MaxColsAtCompileTime> type;
310
template<typename Derived1, typename Derived2>
311
typename hstack_return<Derived1,Derived2>::type
312
HStack (const Eigen::MatrixBase<Derived1>& lhs, const Eigen::MatrixBase<Derived2>& rhs) {
313
typename hstack_return<Derived1,Derived2>::type res;
314
res.resize(lhs.rows(), lhs.cols()+rhs.cols());
320
template<typename Derived1, typename Derived2>
321
struct vstack_return {
322
typedef typename Derived1::Scalar Scalar;
324
RowsAtCompileTime = SUM_OR_DYNAMIC(Derived1::RowsAtCompileTime, Derived2::RowsAtCompileTime),
325
ColsAtCompileTime = Derived1::ColsAtCompileTime,
326
Options = Derived1::Flags&Eigen::RowMajorBit ? Eigen::RowMajor : 0,
327
MaxRowsAtCompileTime = SUM_OR_DYNAMIC(Derived1::MaxRowsAtCompileTime, Derived2::MaxRowsAtCompileTime),
328
MaxColsAtCompileTime = Derived1::MaxColsAtCompileTime
330
typedef Eigen::Matrix<Scalar,
334
MaxRowsAtCompileTime,
335
MaxColsAtCompileTime> type;
338
template<typename Derived1, typename Derived2>
339
typename vstack_return<Derived1,Derived2>::type
340
VStack (const Eigen::MatrixBase<Derived1>& lhs, const Eigen::MatrixBase<Derived2>& rhs) {
341
typename vstack_return<Derived1,Derived2>::type res;
342
res.resize(lhs.rows()+rhs.rows(), lhs.cols());
350
// Since it is not possible to typedef privately here, use a macro.
351
// Always take dynamic columns if either side is dynamic.
353
((ColsLeft == Eigen::Dynamic || ColsRight == Eigen::Dynamic) \
354
? Eigen::Dynamic : (ColsLeft + ColsRight))
356
// Same as above, except that prefer fixed size if either is fixed.
358
((RowsLeft == Eigen::Dynamic && RowsRight == Eigen::Dynamic) \
360
: ((RowsLeft == Eigen::Dynamic) \
366
// TODO(keir): Add a static assert if both rows are at compiletime.
367
template<typename T, int RowsLeft, int RowsRight, int ColsLeft, int ColsRight>
368
Eigen::Matrix<T, ROWS, COLS>
369
HStack(const Eigen::Matrix<T, RowsLeft, ColsLeft> &left,
370
const Eigen::Matrix<T, RowsRight, ColsRight> &right) {
371
assert(left.rows() == right.rows());
373
int m1 = left.cols();
374
int m2 = right.cols();
376
Eigen::Matrix<T, ROWS, COLS> stacked(n, m1 + m2);
377
stacked.block(0, 0, n, m1) = left;
378
stacked.block(0, m1, n, m2) = right;
382
// Reuse the above macros by swapping the order of Rows and Cols. Nasty, but
383
// the duplication is worse.
384
// TODO(keir): Add a static assert if both rows are at compiletime.
385
// TODO(keir): Mail eigen list about making this work for general expressions
386
// rather than only matrix types.
387
template<typename T, int RowsLeft, int RowsRight, int ColsLeft, int ColsRight>
388
Eigen::Matrix<T, COLS, ROWS>
389
VStack(const Eigen::Matrix<T, ColsLeft, RowsLeft> &top,
390
const Eigen::Matrix<T, ColsRight, RowsRight> &bottom) {
391
assert(top.cols() == bottom.cols());
393
int n2 = bottom.rows();
396
Eigen::Matrix<T, COLS, ROWS> stacked(n1 + n2, m);
397
stacked.block(0, 0, n1, m) = top;
398
stacked.block(n1, 0, n2, m) = bottom;
407
void HorizontalStack(const Mat &left, const Mat &right, Mat *stacked);
409
template<typename TTop, typename TBot, typename TStacked>
410
void VerticalStack(const TTop &top, const TBot &bottom, TStacked *stacked) {
411
assert(top.cols() == bottom.cols());
413
int n2 = bottom.rows();
416
stacked->resize(n1 + n2, m);
417
stacked->block(0, 0, n1, m) = top;
418
stacked->block(n1, 0, n2, m) = bottom;
421
void MatrixColumn(const Mat &A, int i, Vec2 *v);
422
void MatrixColumn(const Mat &A, int i, Vec3 *v);
423
void MatrixColumn(const Mat &A, int i, Vec4 *v);
425
template <typename TMat, typename TCols>
426
TMat ExtractColumns(const TMat &A, const TCols &columns) {
427
TMat compressed(A.rows(), columns.size());
428
for (int i = 0; i < columns.size(); ++i) {
429
compressed.col(i) = A.col(columns[i]);
434
template <typename TMat, typename TDest>
435
void reshape(const TMat &a, int rows, int cols, TDest *b) {
436
assert(a.rows()*a.cols() == rows*cols);
437
b->resize(rows, cols);
438
for (int i = 0; i < rows; i++) {
439
for (int j = 0; j < cols; j++) {
440
(*b)(i, j) = a[cols*i + j];
445
inline bool isnan(double i) {
447
return _isnan(i) > 0;
449
return std::isnan(i);
453
/// Ceil function that has the same behaviour for positive
454
/// and negative values
455
template <typename FloatType>
456
FloatType ceil0(const FloatType& value) {
457
FloatType result = std::ceil( std::fabs( value ) );
458
return (value < 0.0) ? -result : result;
461
/// Returns the skew anti-symmetric matrix of a vector
462
inline Mat3 SkewMat(const Vec3 &x) {
464
skew << 0 , -x(2), x(1),
469
/// Returns the skew anti-symmetric matrix of a vector with only
470
/// the first two (independent) lines
471
inline Mat23 SkewMatMinimal(const Vec2 &x) {
478
/// Returns the rotaiton matrix built from given vector of euler angles
479
inline Mat3 RotationFromEulerVector(Vec3 euler_vector) {
480
double theta = euler_vector.norm();
482
return Mat3::Identity();
484
Vec3 w = euler_vector / theta;
485
Mat3 w_hat = CrossProductMatrix(w);
486
return Mat3::Identity() + w_hat*sin(theta) + w_hat*w_hat*(1 - cos(theta));
490
#endif // LIBMV_NUMERIC_NUMERIC_H