161 lines
6.6 KiB
C++
161 lines
6.6 KiB
C++
/*
|
|
This file is part of Mitsuba, a physically based rendering system.
|
|
|
|
Copyright (c) 2007-2012 by Wenzel Jakob and others.
|
|
|
|
Mitsuba is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License Version 3
|
|
as published by the Free Software Foundation.
|
|
|
|
Mitsuba is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include <mitsuba/render/testcase.h>
|
|
|
|
MTS_NAMESPACE_BEGIN
|
|
|
|
class TestLinearAlgebra : public TestCase {
|
|
public:
|
|
MTS_BEGIN_TESTCASE()
|
|
MTS_DECLARE_TEST(test01_basicOperations)
|
|
MTS_DECLARE_TEST(test02_eigenDecomp)
|
|
MTS_DECLARE_TEST(test03_gaussJordan)
|
|
MTS_DECLARE_TEST(test04_lu)
|
|
MTS_DECLARE_TEST(test05_chol)
|
|
MTS_END_TESTCASE()
|
|
|
|
void test01_basicOperations() {
|
|
Float refA[] = { 1, 2, 3, 4, 5, 6 };
|
|
Float refB[] = { 7, 8, 9, 10, 11, 12 };
|
|
Float refC[] = { 58, 64, 139, 154 };
|
|
Matrix<2, 3, Float> A(refA);
|
|
Matrix<3, 2, Float> B(refB);
|
|
Matrix<2, 2, Float> C(refC);
|
|
assertEqualsEpsilon(A*B, C, 1e-6);
|
|
|
|
Matrix2x2 A2(1, 2, 3, 4), B2(3, 4, 5, 6);
|
|
assertEqualsEpsilon(A2*B2, Matrix2x2(13, 16, 29, 36), 1e-6);
|
|
}
|
|
|
|
void test02_eigenDecomp() {
|
|
Matrix4x4 A(
|
|
1.4541, 1.1233, 1.2407, 1.2548,
|
|
1.1233, 0.2597, 0.3819, 1.3917,
|
|
1.2407, 0.3819, 1.1552, 1.1048,
|
|
1.2548, 1.3917, 1.1048, 1.4712
|
|
);
|
|
Matrix4x4 Q;
|
|
Vector4 d;
|
|
A.symEig(Q, (Float *) &d);
|
|
|
|
Vector4 refD(-0.823889076095475, 0.130902702868822,
|
|
0.557486242256414, 4.47570013097024);
|
|
|
|
Matrix4x4 refQ(
|
|
0.294383137629217, 0.746207030711883, 0.191065628242818, 0.565692108217809,
|
|
-0.789565156329591, 0.139585328270248, -0.459560990857043, 0.381977087957391,
|
|
-0.286639718342894, -0.415237779451033, 0.738328701906588, 0.447533223711729,
|
|
0.455810381691897, -0.501266984714151, -0.45515749947419, 0.577754235510108
|
|
);
|
|
|
|
assertEqualsEpsilon(d, refD, 1e-6);
|
|
assertEqualsEpsilon(Q, refQ, 1e-6);
|
|
}
|
|
|
|
void test03_gaussJordan() {
|
|
Float orig[5][5] = {
|
|
{0.603220764324061,0.0160774582181293, 0.508210763233408, 0.953606295121746, 0.990510667271985},
|
|
{0.636413405652896, 0.728102544189785, 0.295895331742393, 0.214085933989557, 0.289789452981086},
|
|
{0.757872433764296, 0.176768920514461, 0.222846809207195, 0.437099780859822, 0.285546115075973},
|
|
{0.72645673174838, 0.331824027228289, 0.247810107847795, 0.426238413898285, 0.305370139440192},
|
|
{0.0129043790455411, 0.192371759818767, 0.492432530540112,0.65379652583481, 0.573781874886137}
|
|
};
|
|
Matrix<5, 5, Float> randomMatrix(orig);
|
|
Matrix<5, 5, Float> inverse;
|
|
randomMatrix.invert(inverse);
|
|
|
|
Float refInverse[5][5] = {
|
|
{0.0703474910195987,1.40983808579044,5.61251124156711, -5.76223929771622, -0.559883685809967},
|
|
{-0.0613980284171623, -1.63235458842233, -10.5399802908894,12.4851221198693, -0.468956103463839},
|
|
{-2.29568951232449,7.39978908961836,27.3281328010324, -33.1622231774198, 4.27485563386439},
|
|
{-0.885020418512179, -6.82656789249295, -15.71882942499, 23.104992960391, 0.501523848970031},
|
|
{2.99765294474105, 1.9434481868496, -2.13526601478719, -1.92274014105124, -2.32759821076299}
|
|
};
|
|
Matrix<5, 5, Float> refInverseMatrix(refInverse);
|
|
assertEqualsEpsilon(inverse, refInverseMatrix, 1e-4);
|
|
}
|
|
|
|
void test04_lu() {
|
|
Float orig[5][5] = {
|
|
{0.603220764324061,0.0160774582181293, 0.508210763233408, 0.953606295121746, 0.990510667271985},
|
|
{0.636413405652896, 0.728102544189785, 0.295895331742393, 0.214085933989557, 0.289789452981086},
|
|
{0.757872433764296, 0.176768920514461, 0.222846809207195, 0.437099780859822, 0.285546115075973},
|
|
{0.72645673174838, 0.331824027228289, 0.247810107847795, 0.426238413898285, 0.305370139440192},
|
|
{0.0129043790455411, 0.192371759818767, 0.492432530540112,0.65379652583481, 0.573781874886137}
|
|
};
|
|
Matrix<5, 5, Float> randomMatrix(orig);
|
|
Matrix<5, 5, Float> lu;
|
|
int piv[5], pivsign;
|
|
if (!randomMatrix.lu(lu, piv, pivsign))
|
|
Log(EError, "Could not generate LU decomposition!");
|
|
|
|
Float det = lu.luDet(pivsign);
|
|
assertEqualsEpsilon(det, 0.00294638676819103, 1e-6);
|
|
assertEqualsEpsilon(randomMatrix.det(), 0.00294638676819103, 1e-6);
|
|
|
|
Float b[5] = { 0.088842801947558, 0.717330636910085,
|
|
0.689651610365336, 0.76615421808756, 0.274406750300772 };
|
|
Float xref[5] = { 0.319847529827911, 0.991537144805428,
|
|
-0.283297199558031, 2.02355933108543, -1.92399896347868 };
|
|
|
|
Matrix<5, 1, Float> B(b);
|
|
Matrix<5, 1, Float> X;
|
|
lu.luSolve(B, X, piv);
|
|
|
|
Matrix<5, 1, Float> Xref(xref);
|
|
assertEqualsEpsilon(X, Xref, 1e-5);
|
|
}
|
|
|
|
void test05_chol() {
|
|
Float orig[5][5] = {
|
|
{5.51302956379742, -1.36613599367125, -0.56818386886837, 1.43247259160815, -0.341242075046427},
|
|
{-1.36613599367125, 4.32377082646249, -1.78941813087798, -0.0389694848978303, -1.36129441356894},
|
|
{-0.56818386886837, -1.78941813087798, 3.16179437285643, -0.169145503847853, -0.175824617890457},
|
|
{1.43247259160815, -0.0389694848978303, -0.169145503847853, 3.43678526823342, -0.0421265728657415},
|
|
{-0.341242075046427, -1.36129441356894, -0.175824617890457, -0.0421265728657415, 2.75055078833228}
|
|
};
|
|
Float cholRef[5][5] = {
|
|
{2.34798414896639, 0, 0, 0, 0},
|
|
{-0.581833567433853, 1.99630672149089, 0, 0, 0},
|
|
{-0.241987949159917, -0.966892923734769, 1.47253328632987, 0, 0},
|
|
{0.610086142293059, 0.158291863826668, 0.0893285569680872, 1.74113303971054, 0},
|
|
{-0.145334062496395, -0.724264780584955, -0.618852021434583, 0.124324850430034, 1.34403676785521}
|
|
};
|
|
Matrix<5, 5, Float> M(orig), L;
|
|
if (!M.chol(L))
|
|
Log(EError, "Could not generate Cholesky decomposition!");
|
|
Matrix<5, 5, Float> Lref(cholRef);
|
|
assertEqualsEpsilon(L, Lref, 1e-6);
|
|
assertEqualsEpsilon(L.cholDet(), 260.892331265789, 1e-4);
|
|
|
|
Float b[5] = { 0.331003261288103, 0.601514197755584, 0.0474150216556957, 0.363418224633018, 0.47712128258488 };
|
|
Float xref[5] = { 0.25931313190664, 0.544146878658952, 0.398994177053345, 0.0296072370438656, 0.500901199816733 };
|
|
|
|
Matrix<5, 1, Float> B(b);
|
|
Matrix<5, 1, Float> X;
|
|
L.cholSolve(B, X);
|
|
|
|
Matrix<5, 1, Float> Xref(xref);
|
|
assertEqualsEpsilon(X, Xref, 1e-5);
|
|
}
|
|
};
|
|
|
|
MTS_EXPORT_TESTCASE(TestLinearAlgebra, "Testcase for Linear Algebra routines")
|
|
MTS_NAMESPACE_END
|