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

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

test: check for NaN in LU decomposition results.

  • Property svn:eol-style set to LF
  • Property svn:keywords set to Id
File size: 8.5 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_4x4)
67    {
68        mat4 m0(1.f);
69        mat4 m1(1.f);
70        mat4 m2 = m0 * m1;
71
72        for (int j = 0; j < 4; ++j)
73        for (int i = 0; i < 4; ++i)
74            lolunit_assert_doubles_equal(m2[i][j], mat4(1.f)[i][j], 1e-5);
75    }
76
77    lolunit_declare_test(inverse_2x2)
78    {
79        mat2 m0 = inv2;
80        mat2 m1 = inverse(m0);
81        mat2 m2 = m0 * m1;
82
83        for (int j = 0; j < 2; ++j)
84        for (int i = 0; i < 2; ++i)
85            lolunit_assert_doubles_equal(m2[i][j], mat2(1.f)[i][j], 1e-5);
86    }
87
88    lolunit_declare_test(lu_decomposition_3x3)
89    {
90        mat3 m(vec3(2, 3, 5),
91               vec3(3, 2, 3),
92               vec3(9, 5, 7));
93        mat3 L, U;
94        lu_decomposition(m, L, U);
95        mat3 m2 = L * U;
96
97        for (int j = 0; j < 3; ++j)
98        for (int i = 0; i < 3; ++i)
99        {
100            lolunit_assert(!isnan(U[i][j]));
101            lolunit_assert(!isnan(L[i][j]));
102
103            if (i < j)
104                lolunit_assert_doubles_equal(U[i][j], 0.f, 1e-5);
105            if (i == j)
106                lolunit_assert_doubles_equal(L[i][j], 1.f, 1e-5);
107            if (j < i)
108                lolunit_assert_doubles_equal(L[i][j], 0.f, 1e-5);
109
110            lolunit_assert_doubles_equal(m2[i][j], m[i][j], 1e-5);
111        }
112    }
113
114    lolunit_declare_test(lu_decomposition_4x4_full)
115    {
116        mat4 m(vec4( 1,  1,  2, -1),
117               vec4(-2, -1, -2,  2),
118               vec4( 4,  2,  5, -4),
119               vec4( 5, -3, -7, -6));
120        mat4 L, U;
121        lu_decomposition(m, L, U);
122        mat4 m2 = L * U;
123
124        for (int j = 0; j < 4; ++j)
125        for (int i = 0; i < 4; ++i)
126        {
127            lolunit_assert(!isnan(U[i][j]));
128            lolunit_assert(!isnan(L[i][j]));
129
130            if (i < j)
131                lolunit_assert_doubles_equal(U[i][j], 0.f, 1e-5);
132            if (i == j)
133                lolunit_assert_doubles_equal(L[i][j], 1.f, 1e-5);
134            if (j < i)
135                lolunit_assert_doubles_equal(L[i][j], 0.f, 1e-5);
136
137            lolunit_assert_doubles_equal(m2[i][j], m[i][j], 1e-5);
138        }
139    }
140
141    lolunit_declare_test(lu_decomposition_4x4_sparse)
142    {
143        mat4 m(vec4(1,  0,  0,  0),
144               vec4(0,  0,  1,  0),
145               vec4(0, -1,  0,  0),
146               vec4(0,  0, -1,  1));
147        mat4 L, U;
148        lu_decomposition(m, L, U);
149        mat4 m2 = L * U;
150
151        for (int j = 0; j < 4; ++j)
152        for (int i = 0; i < 4; ++i)
153        {
154            lolunit_assert(!isnan(U[i][j]));
155            lolunit_assert(!isnan(L[i][j]));
156
157            if (i < j)
158                lolunit_assert_doubles_equal(U[i][j], 0.f, 1e-5);
159            if (i == j)
160                lolunit_assert_doubles_equal(L[i][j], 1.f, 1e-5);
161            if (j < i)
162                lolunit_assert_doubles_equal(L[i][j], 0.f, 1e-5);
163
164            lolunit_assert_doubles_equal(m2[i][j], m[i][j], 1e-5);
165        }
166    }
167
168    lolunit_declare_test(l_inverse_3x3)
169    {
170        mat3 m(vec3(2, 3, 5),
171               vec3(3, 2, 3),
172               vec3(9, 5, 7));
173        mat3 L, U;
174        lu_decomposition(m, L, U);
175        mat3 m1 = l_inverse(L);
176        mat3 m2 = m1 * L;
177
178        for (int j = 0; j < 3; ++j)
179        for (int i = 0; i < 3; ++i)
180            lolunit_assert_doubles_equal(m2[i][j], mat3(1.f)[i][j], 1e-5);
181    }
182
183    lolunit_declare_test(l_inverse_4x4)
184    {
185        mat4 m(vec4( 1,  1,  2, -1),
186               vec4(-2, -1, -2,  2),
187               vec4( 4,  2,  5, -4),
188               vec4( 5, -3, -7, -6));
189        mat4 L, U;
190        lu_decomposition(m, L, U);
191        mat4 m1 = l_inverse(L);
192        mat4 m2 = m1 * L;
193
194        for (int j = 0; j < 4; ++j)
195        for (int i = 0; i < 4; ++i)
196            lolunit_assert_doubles_equal(m2[i][j], mat4(1.f)[i][j], 1e-5);
197    }
198
199    lolunit_declare_test(u_inverse_3x3)
200    {
201        mat3 m(vec3(2, 3, 5),
202               vec3(3, 2, 3),
203               vec3(9, 5, 7));
204        mat3 L, U;
205        lu_decomposition(m, L, U);
206        mat3 m1 = u_inverse(U);
207        mat3 m2 = m1 * U;
208
209        for (int j = 0; j < 3; ++j)
210        for (int i = 0; i < 3; ++i)
211            lolunit_assert_doubles_equal(m2[i][j], mat3(1.f)[i][j], 1e-5);
212    }
213
214    lolunit_declare_test(u_inverse_4x4)
215    {
216        mat4 m(vec4( 1,  1,  2, -1),
217               vec4(-2, -1, -2,  2),
218               vec4( 4,  2,  5, -4),
219               vec4( 5, -3, -7, -6));
220        mat4 L, U;
221        lu_decomposition(m, L, U);
222        mat4 m1 = u_inverse(U);
223        mat4 m2 = m1 * U;
224
225        for (int j = 0; j < 4; ++j)
226        for (int i = 0; i < 4; ++i)
227            lolunit_assert_doubles_equal(m2[i][j], mat4(1.f)[i][j], 1e-5);
228    }
229
230    lolunit_declare_test(inverse_3x3)
231    {
232        mat3 m(vec3(2, 3, 5),
233               vec3(3, 2, 3),
234               vec3(9, 5, 7));
235        mat3 m2 = inverse(m) * m;
236
237        for (int j = 0; j < 3; ++j)
238        for (int i = 0; i < 3; ++i)
239            lolunit_assert_doubles_equal(m2[i][j], mat3(1.f)[i][j], 1e-5);
240    }
241
242    lolunit_declare_test(inverse_4x4_full)
243    {
244        mat4 m(vec4( 1,  1,  2, -1),
245               vec4(-2, -1, -2,  2),
246               vec4( 4,  2,  5, -4),
247               vec4( 5, -3, -7, -6));
248        mat4 m2 = inverse(m) * m;
249
250        for (int j = 0; j < 4; ++j)
251        for (int i = 0; i < 4; ++i)
252            lolunit_assert_doubles_equal(m2[i][j], mat4(1.f)[i][j], 1e-5);
253    }
254
255    lolunit_declare_test(inverse_4x4_sparse)
256    {
257        mat4 m(vec4(1,  0,  0,  0),
258               vec4(0,  0,  1,  0),
259               vec4(0, -1,  0,  0),
260               vec4(0,  0, -1,  1));
261        mat4 m2 = inverse(m) * m;
262
263        for (int j = 0; j < 4; ++j)
264        for (int i = 0; i < 4; ++i)
265            lolunit_assert_doubles_equal(m2[i][j], mat4(1.f)[i][j], 1e-5);
266    }
267
268    lolunit_declare_test(kronecker_product)
269    {
270        int const COLS1 = 2, ROWS1 = 3;
271        int const COLS2 = 5, ROWS2 = 7;
272
273        mat_t<int, COLS1, ROWS1> a;
274        mat_t<int, COLS2, ROWS2> b;
275
276        for (int i = 0; i < COLS1; ++i)
277            for (int j = 0; j < ROWS1; ++j)
278                a[i][j] = (i + 11) * (j + 13);
279
280        for (int i = 0; i < COLS2; ++i)
281            for (int j = 0; j < ROWS2; ++j)
282                b[i][j] = (i + 17) * (j + 19);
283
284        mat_t<int, COLS1 * COLS2, ROWS1 * ROWS2> m = outer(a, b);
285
286        for (int i1 = 0; i1 < COLS1; ++i1)
287        for (int j1 = 0; j1 < ROWS1; ++j1)
288        for (int i2 = 0; i2 < COLS2; ++i2)
289        for (int j2 = 0; j2 < ROWS2; ++j2)
290        {
291            int expected = a[i1][j1] * b[i2][j2];
292            int actual = m[i1 * COLS2 + i2][j1 * ROWS2 + j2];
293
294            lolunit_assert_equal(actual, expected);
295        }
296    }
297
298    mat2 tri2, inv2;
299    mat3 tri3, inv3;
300    mat4 tri4, inv4;
301};
302
303} /* namespace lol */
304
Note: See TracBrowser for help on using the repository browser.