Raw File
test_la.cpp
/*
    This file is part of Mitsuba, a physically based rendering system.

    Copyright (c) 2007-2014 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
back to top