source: trunk/src/t/math/matrix.cpp @ 3813

Last change on this file since 3813 was 3813, checked in by sam, 7 years ago

test: add more unit tests for matrix inversion.

  • Property svn:eol-style set to LF
  • Property svn:keywords set to Id
File size: 7.9 KB
Line 
1//
2// Lol Engine
3//
4// Copyright: (c) 2010-2014 Sam Hocevar <sam@hocevar.net>
5//   This program is free software; you can redistribute it and/or
6//   modify it under the terms of the Do What The Fuck You Want To
7//   Public License, Version 2, as published by Sam Hocevar. See
8//   http://www.wtfpl.net/ for more details.
9//
10
11#include <lol/engine-internal.h>
12
13#include <lolunit.h>
14
15namespace lol
16{
17
18lolunit_declare_fixture(MatrixTest)
19{
20    void SetUp()
21    {
22        tri2 = mat2(vec2(1.0f, 0.0f),
23                    vec2(7.0f, 2.0f));
24        inv2 = mat2(vec2(4.0f, 3.0f),
25                    vec2(3.0f, 2.0f));
26
27        tri3 = mat3(vec3(1.0f, 0.0f, 0.0f),
28                    vec3(7.0f, 2.0f, 0.0f),
29                    vec3(1.0f, 5.0f, 3.0f));
30        inv3 = mat3(vec3(2.0f, 3.0f, 5.0f),
31                    vec3(3.0f, 2.0f, 3.0f),
32                    vec3(9.0f, 5.0f, 7.0f));
33
34        tri4 = mat4(vec4(1.0f, 0.0f, 0.0f, 0.0f),
35                    vec4(7.0f, 2.0f, 0.0f, 0.0f),
36                    vec4(1.0f, 5.0f, 3.0f, 0.0f),
37                    vec4(8.0f, 9.0f, 2.0f, 4.0f));
38        inv4 = mat4(vec4( 1.0f,  1.0f,  2.0f, -1.0f),
39                    vec4(-2.0f, -1.0f, -2.0f,  2.0f),
40                    vec4( 4.0f,  2.0f,  5.0f, -4.0f),
41                    vec4( 5.0f, -3.0f, -7.0f, -6.0f));
42    }
43
44    void TearDown() {}
45
46    lolunit_declare_test(Determinant)
47    {
48        float d1, d2;
49
50        d1 = determinant(tri2);
51        lolunit_assert_doubles_equal(d1, 2.0f, 1e-5);
52        d2 = determinant(inv2);
53        lolunit_assert_doubles_equal(d2, -1.0f, 1e-5);
54
55        d1 = determinant(tri3);
56        lolunit_assert_doubles_equal(d1, 6.0f, 1e-5);
57        d2 = determinant(inv3);
58        lolunit_assert_doubles_equal(d2, 1.0f, 1e-5);
59
60        d1 = determinant(tri4);
61        lolunit_assert_doubles_equal(d1, 24.0f, 1e-5);
62        d2 = determinant(inv4);
63        lolunit_assert_doubles_equal(d2, -1.0f, 1e-5);
64    }
65
66    lolunit_declare_test(Multiplication)
67    {
68        mat4 m0(1.f);
69        mat4 m1(1.f);
70        mat4 m2 = m0 * m1;
71
72        lolunit_assert_equal(m2[0][0], 1.0f);
73        lolunit_assert_equal(m2[1][0], 0.0f);
74        lolunit_assert_equal(m2[2][0], 0.0f);
75        lolunit_assert_equal(m2[3][0], 0.0f);
76
77        lolunit_assert_equal(m2[0][1], 0.0f);
78        lolunit_assert_equal(m2[1][1], 1.0f);
79        lolunit_assert_equal(m2[2][1], 0.0f);
80        lolunit_assert_equal(m2[3][1], 0.0f);
81
82        lolunit_assert_equal(m2[0][2], 0.0f);
83        lolunit_assert_equal(m2[1][2], 0.0f);
84        lolunit_assert_equal(m2[2][2], 1.0f);
85        lolunit_assert_equal(m2[3][2], 0.0f);
86
87        lolunit_assert_equal(m2[0][3], 0.0f);
88        lolunit_assert_equal(m2[1][3], 0.0f);
89        lolunit_assert_equal(m2[2][3], 0.0f);
90        lolunit_assert_equal(m2[3][3], 1.0f);
91    }
92
93    lolunit_declare_test(Inverse2x2)
94    {
95        mat2 m0 = inv2;
96        mat2 m1 = inverse(m0);
97
98        mat2 m2 = m0 * m1;
99
100        lolunit_assert_equal(m2[0][0], 1.0f);
101        lolunit_assert_equal(m2[1][0], 0.0f);
102
103        lolunit_assert_equal(m2[0][1], 0.0f);
104        lolunit_assert_equal(m2[1][1], 1.0f);
105    }
106
107    lolunit_declare_test(LUDecomposition3x3)
108    {
109        mat3 m0 = inv3;
110
111        mat3 L, U;
112
113        lu_decomposition(inv3, L, U);
114
115        mat3 result = L * U;
116
117        for (int i = 0; i < 3; ++i)
118        {
119            for (int j = 0; j < 3; ++j)
120            {
121                if (i > j)
122                    lolunit_assert_equal(L[i][j], 0);
123                else if (i < j)
124                    lolunit_assert_equal(U[i][j], 0);
125                else
126                    lolunit_assert_equal(L[i][j], 1);
127
128                lolunit_assert_equal(result[i][j], inv3[i][j]);
129            }
130        }
131    }
132
133    lolunit_declare_test(LUDecomposition4x4)
134    {
135        mat4 m0 = inv4;
136
137        mat4 L, U;
138
139        lu_decomposition(inv4, L, U);
140
141        mat4 result = L * U;
142
143        for (int i = 0; i < 4; ++i)
144        {
145            for (int j = 0; j < 4; ++j)
146            {
147                if (i > j)
148                    lolunit_assert_equal(L[i][j], 0);
149                else if (i < j)
150                    lolunit_assert_equal(U[i][j], 0);
151                else
152                    lolunit_assert_equal(L[i][j], 1);
153
154                lolunit_assert_equal(result[i][j], inv4[i][j]);
155            }
156        }
157    }
158
159    lolunit_declare_test(LInverse3x3)
160    {
161        mat3 m0 = inv3;
162        mat3 L, U;
163        lu_decomposition(inv3, L, U);
164        mat3 l_inv = l_inverse(L);
165
166        mat3 identity = l_inv * L;
167
168        for (int i = 0 ; i < 3 ; ++i)
169            for (int j = 0 ; j < 3 ; ++j)
170                lolunit_assert_doubles_equal(identity[i][j], i == j ? 1 : 0, 1e-5);
171    }
172
173    lolunit_declare_test(LInverse4x4)
174    {
175        mat4 m0 = inv4;
176        mat4 L, U;
177        lu_decomposition(inv4, L, U);
178        mat4 l_inv = l_inverse(L);
179
180        mat4 identity = l_inv * L;
181
182        for (int i = 0 ; i < 4 ; ++i)
183            for (int j = 0 ; j < 4 ; ++j)
184                lolunit_assert_doubles_equal(identity[i][j], i == j ? 1 : 0, 1e-5);
185    }
186
187    lolunit_declare_test(UInverse3x3)
188    {
189        mat3 m0 = inv3;
190        mat3 L, U;
191        lu_decomposition(inv3, L, U);
192        mat3 u_inv = u_inverse(U);
193
194        mat3 identity = u_inv * U;
195
196        for (int i = 0 ; i < 3 ; ++i)
197            for (int j = 0 ; j < 3 ; ++j)
198                lolunit_assert_doubles_equal(identity[i][j], i == j ? 1 : 0, 1e-5);
199    }
200
201    lolunit_declare_test(UInverse4x4)
202    {
203        mat4 m0 = inv4;
204        mat4 L, U;
205        lu_decomposition(inv4, L, U);
206        mat4 u_inv = u_inverse(U);
207
208        mat4 identity = u_inv * U;
209
210        for (int i = 0 ; i < 4 ; ++i)
211            for (int j = 0 ; j < 4 ; ++j)
212                lolunit_assert_doubles_equal(identity[i][j], i == j ? 1 : 0, 1e-5);
213    }
214
215    lolunit_declare_test(Inverse3x3)
216    {
217        mat3 m0 = inv3;
218        mat3 m1 = inverse(m0);
219
220        mat3 m2 = m0 * m1;
221
222        lolunit_assert_doubles_equal(m2[0][0], 1.0f, 1e-4);
223        lolunit_assert_doubles_equal(m2[1][0], 0.0f, 1e-4);
224        lolunit_assert_doubles_equal(m2[2][0], 0.0f, 1e-4);
225
226        lolunit_assert_doubles_equal(m2[0][1], 0.0f, 1e-4);
227        lolunit_assert_doubles_equal(m2[1][1], 1.0f, 1e-4);
228        lolunit_assert_doubles_equal(m2[2][1], 0.0f, 1e-4);
229
230        lolunit_assert_doubles_equal(m2[0][2], 0.0f, 1e-4);
231        lolunit_assert_doubles_equal(m2[1][2], 0.0f, 1e-4);
232        lolunit_assert_doubles_equal(m2[2][2], 1.0f, 1e-4);
233    }
234
235    lolunit_declare_test(inverse_4x4_1)
236    {
237        mat4 m = inv4;
238        mat4 m2 = inverse(m) * m;
239
240        for (int j = 0; j < 4; ++j)
241        for (int i = 0; i < 4; ++i)
242            lolunit_assert_equal(m2[i][j], mat4(1.f)[i][j]);
243    }
244
245    lolunit_declare_test(inverse_4x4_2)
246    {
247        mat4 m(vec4(1.f,  0.f,  0.f, 0.f),
248               vec4(0.f,  0.f,  1.f, 0.f),
249               vec4(0.f, -1.f,  0.f, 0.f),
250               vec4(0.f,  0.f, -1.f, 1.f));
251        mat4 m2 = inverse(m) * m;
252
253        for (int j = 0; j < 4; ++j)
254        for (int i = 0; i < 4; ++i)
255            lolunit_assert_equal(m2[i][j], mat4(1.f)[i][j]);
256    }
257
258    lolunit_declare_test(Kronecker)
259    {
260        int const COLS1 = 2, ROWS1 = 3;
261        int const COLS2 = 5, ROWS2 = 7;
262
263        mat_t<int, COLS1, ROWS1> a;
264        mat_t<int, COLS2, ROWS2> b;
265
266        for (int i = 0; i < COLS1; ++i)
267            for (int j = 0; j < ROWS1; ++j)
268                a[i][j] = (i + 11) * (j + 13);
269
270        for (int i = 0; i < COLS2; ++i)
271            for (int j = 0; j < ROWS2; ++j)
272                b[i][j] = (i + 17) * (j + 19);
273
274        mat_t<int, COLS1 * COLS2, ROWS1 * ROWS2> m = outer(a, b);
275
276        for (int i1 = 0; i1 < COLS1; ++i1)
277        for (int j1 = 0; j1 < ROWS1; ++j1)
278        for (int i2 = 0; i2 < COLS2; ++i2)
279        for (int j2 = 0; j2 < ROWS2; ++j2)
280        {
281            int expected = a[i1][j1] * b[i2][j2];
282            int actual = m[i1 * COLS2 + i2][j1 * ROWS2 + j2];
283
284            lolunit_assert_equal(actual, expected);
285        }
286    }
287
288    mat2 tri2, inv2;
289    mat3 tri3, inv3;
290    mat4 tri4, inv4;
291};
292
293} /* namespace lol */
294
Note: See TracBrowser for help on using the repository browser.