OXYGENHUB
◆ main openmsx / src / unittest / gl_mat.cc
19.3 KiB · C++ · last changed chore(): initial commit 1 month ago source blame history raw
e8555c89 Andy McCall 1
#include "catch.hpp"
2
#include "gl_mat.hh"
3
4
using namespace gl;
5
6
// Test approximations.
7
static constexpr bool approxEq(const mat4& x, const mat4&y)
8
{
9
	return norm2_2(x - y) < 1.0e-3f;
10
}
11
12
// Extra matrix types used in this test.
13
using imat2 = matMxN<2, 2, int>;
14
using imat3 = matMxN<3, 3, int>;
15
using imat4 = matMxN<4, 4, int>;
16
using mat32 = matMxN<3, 2, float>;
17
using mat23 = matMxN<2, 3, float>;
18
19
// It's useful to test both integer and float variants because the
20
// former are implemented in plain C++ and (only) the latter have SSE
21
// optimizations.
22
23
TEST_CASE("gl_mat: constructors")
24
{
25
	SECTION("default constructor") {
26
		mat2 m2;
27
		CHECK(m2[0] == vec2(1, 0));
28
		CHECK(m2[1] == vec2(0, 1));
29
30
		imat2 i2;
31
		CHECK(i2[0] == ivec2(1, 0));
32
		CHECK(i2[1] == ivec2(0, 1));
33
34
		mat3 m3;
35
		CHECK(m3[0] == vec3(1, 0, 0));
36
		CHECK(m3[1] == vec3(0, 1, 0));
37
		CHECK(m3[2] == vec3(0, 0, 1));
38
39
		imat3 i3;
40
		CHECK(i3[0] == ivec3(1, 0, 0));
41
		CHECK(i3[1] == ivec3(0, 1, 0));
42
		CHECK(i3[2] == ivec3(0, 0, 1));
43
44
		mat4 m4;
45
		CHECK(m4[0] == vec4(1, 0, 0, 0));
46
		CHECK(m4[1] == vec4(0, 1, 0, 0));
47
		CHECK(m4[2] == vec4(0, 0, 1, 0));
48
		CHECK(m4[3] == vec4(0, 0, 0, 1));
49
50
		imat4 i4;
51
		CHECK(i4[0] == ivec4(1, 0, 0, 0));
52
		CHECK(i4[1] == ivec4(0, 1, 0, 0));
53
		CHECK(i4[2] == ivec4(0, 0, 1, 0));
54
		CHECK(i4[3] == ivec4(0, 0, 0, 1));
55
56
		mat32 m32;
57
		CHECK(m32[0] == vec3(1, 0, 0));
58
		CHECK(m32[1] == vec3(0, 1, 0));
59
60
		mat23 m23;
61
		CHECK(m23[0] == vec2(1, 0));
62
		CHECK(m23[1] == vec2(0, 1));
63
		CHECK(m23[2] == vec2(0, 0));
64
	}
65
	SECTION("diagonal constructor") {
66
		mat2 m2(vec2(2, 3));
67
		CHECK(m2[0] == vec2(2, 0));
68
		CHECK(m2[1] == vec2(0, 3));
69
70
		imat2 i2(ivec2(2, 3));
71
		CHECK(i2[0] == ivec2(2, 0));
72
		CHECK(i2[1] == ivec2(0, 3));
73
74
		mat3 m3(vec3(2, 3, 4));
75
		CHECK(m3[0] == vec3(2, 0, 0));
76
		CHECK(m3[1] == vec3(0, 3, 0));
77
		CHECK(m3[2] == vec3(0, 0, 4));
78
79
		imat3 i3(ivec3(2, 3, 4));
80
		CHECK(i3[0] == ivec3(2, 0, 0));
81
		CHECK(i3[1] == ivec3(0, 3, 0));
82
		CHECK(i3[2] == ivec3(0, 0, 4));
83
84
		mat4 m4(vec4(2, 3, 4, 5));
85
		CHECK(m4[0] == vec4(2, 0, 0, 0));
86
		CHECK(m4[1] == vec4(0, 3, 0, 0));
87
		CHECK(m4[2] == vec4(0, 0, 4, 0));
88
		CHECK(m4[3] == vec4(0, 0, 0, 5));
89
90
		imat4 i4(ivec4(2, 3, 4, 5));
91
		CHECK(i4[0] == ivec4(2, 0, 0, 0));
92
		CHECK(i4[1] == ivec4(0, 3, 0, 0));
93
		CHECK(i4[2] == ivec4(0, 0, 4, 0));
94
		CHECK(i4[3] == ivec4(0, 0, 0, 5));
95
96
		mat32 m32(vec2(2, 3));
97
		CHECK(m32[0] == vec3(2, 0, 0));
98
		CHECK(m32[1] == vec3(0, 3, 0));
99
100
		mat23 m23(vec2(2, 3));
101
		CHECK(m23[0] == vec2(2, 0));
102
		CHECK(m23[1] == vec2(0, 3));
103
		CHECK(m23[2] == vec2(0, 0));
104
	}
105
	SECTION("construct from columns") {
106
		mat2 m2(vec2(2, 3), vec2(4, 5));
107
		CHECK(m2[0] == vec2(2, 3));
108
		CHECK(m2[1] == vec2(4, 5));
109
110
		imat2 i2(ivec2(2, 3), ivec2(4, 5));
111
		CHECK(i2[0] == ivec2(2, 3));
112
		CHECK(i2[1] == ivec2(4, 5));
113
114
		mat3 m3(vec3(2, 3, 4), vec3(5, 6, 7), vec3(8, 9, 1));
115
		CHECK(m3[0] == vec3(2, 3, 4));
116
		CHECK(m3[1] == vec3(5, 6, 7));
117
		CHECK(m3[2] == vec3(8, 9, 1));
118
119
		imat3 i3(ivec3(2, 3, 4), ivec3(5, 6, 7), ivec3(8, 9, 1));
120
		CHECK(i3[0] == ivec3(2, 3, 4));
121
		CHECK(i3[1] == ivec3(5, 6, 7));
122
		CHECK(i3[2] == ivec3(8, 9, 1));
123
124
		mat4 m4(vec4(2, 3, 4, 5), vec4(3, 4, 5, 6), vec4(4, 5, 6, 7), vec4(5, 6, 7, 8));
125
		CHECK(m4[0] == vec4(2, 3, 4, 5));
126
		CHECK(m4[1] == vec4(3, 4, 5, 6));
127
		CHECK(m4[2] == vec4(4, 5, 6, 7));
128
		CHECK(m4[3] == vec4(5, 6, 7, 8));
129
130
		imat4 i4(ivec4(2, 3, 4, 5), ivec4(3, 4, 5, 6), ivec4(4, 5, 6, 7), ivec4(5, 6, 7, 8));
131
		CHECK(i4[0] == ivec4(2, 3, 4, 5));
132
		CHECK(i4[1] == ivec4(3, 4, 5, 6));
133
		CHECK(i4[2] == ivec4(4, 5, 6, 7));
134
		CHECK(i4[3] == ivec4(5, 6, 7, 8));
135
136
		mat32 m32(vec3(2, 3, 4), vec3(5, 6, 7));
137
		CHECK(m32[0] == vec3(2, 3, 4));
138
		CHECK(m32[1] == vec3(5, 6, 7));
139
140
		mat23 m23(vec2(2, 3), vec2(4, 5), vec2(6, 7));
141
		CHECK(m23[0] == vec2(2, 3));
142
		CHECK(m23[1] == vec2(4, 5));
143
		CHECK(m23[2] == vec2(6, 7));
144
	}
145
}
146
147
TEST_CASE("gl_mat: modify columns or elements")
148
{
149
	mat2 m2(vec2(2, 3));
150
	m2[1] = vec2(8, 9); m2[0][1] = 7;
151
	CHECK(m2[0] == vec2(2, 7));
152
	CHECK(m2[1] == vec2(8, 9));
153
154
	imat2 i2(ivec2(2, 3));
155
	i2[0] = ivec2(8, 9); i2[1][1] = 7;
156
	CHECK(i2[0] == ivec2(8, 9));
157
	CHECK(i2[1] == ivec2(0, 7));
158
159
	mat3 m3(vec3(2, 3, 4));
160
	m3[1] = vec3(7, 8, 9); m3[0][1] = 6;
161
	CHECK(m3[0] == vec3(2, 6, 0));
162
	CHECK(m3[1] == vec3(7, 8, 9));
163
	CHECK(m3[2] == vec3(0, 0, 4));
164
165
	imat3 i3(ivec3(2, 3, 4));
166
	i3[0] = ivec3(7, 8, 9); i3[2][0] = 6;
167
	CHECK(i3[0] == ivec3(7, 8, 9));
168
	CHECK(i3[1] == ivec3(0, 3, 0));
169
	CHECK(i3[2] == ivec3(6, 0, 4));
170
171
	mat4 m4(vec4(2, 3, 4, 5));
172
	m4[3] = vec4(6, 7, 8, 9); m4[1][1] = 1;
173
	CHECK(m4[0] == vec4(2, 0, 0, 0));
174
	CHECK(m4[1] == vec4(0, 1, 0, 0));
175
	CHECK(m4[2] == vec4(0, 0, 4, 0));
176
	CHECK(m4[3] == vec4(6, 7, 8, 9));
177
178
	imat4 i4(ivec4(2, 3, 4, 5));
179
	i4[1] = ivec4(6, 7, 8, 9); i4[2][3] = 1;
180
	CHECK(i4[0] == ivec4(2, 0, 0, 0));
181
	CHECK(i4[1] == ivec4(6, 7, 8, 9));
182
	CHECK(i4[2] == ivec4(0, 0, 4, 1));
183
	CHECK(i4[3] == ivec4(0, 0, 0, 5));
184
185
	mat32 m32(vec2(2, 3));
186
	m32[0] = vec3(7, 8, 9); m32[1][0] = 6;
187
	CHECK(m32[0] == vec3(7, 8, 9));
188
	CHECK(m32[1] == vec3(6, 3, 0));
189
190
	mat23 m23(vec2(2, 3));
191
	m23[1] = vec2(8, 9); m23[1][0] = 7;
192
	CHECK(m23[0] == vec2(2, 0));
193
	CHECK(m23[1] == vec2(7, 9));
194
	CHECK(m23[2] == vec2(0, 0));
195
}
196
197
TEST_CASE("gl_mat: (in)equality")
198
{
199
	mat3 m3(vec3(1, 2, 3), vec3(4, 5, 6), vec3(7, 8, 9));
200
	mat3 n3(vec3(1, 0, 3), vec3(4, 5, 6), vec3(7, 8, 9));
201
	mat3 o3(vec3(1, 2, 3), vec3(4, 5, 0), vec3(7, 8, 9));
202
	mat3 p3(vec3(1, 2, 3), vec3(4, 5, 6), vec3(7, 0, 9));
203
	CHECK(m3 == m3);
204
	CHECK(m3 != n3);
205
	CHECK(m3 != o3);
206
	CHECK(m3 != p3);
207
208
	imat3 i3(ivec3(1, 2, 3), ivec3(4, 5, 6), ivec3(7, 8, 9));
209
	imat3 j3(ivec3(1, 2, 3), ivec3(4, 5, 6), ivec3(7, 0, 9));
210
	imat3 k3(ivec3(1, 2, 3), ivec3(4, 5, 0), ivec3(7, 8, 9));
211
	imat3 l3(ivec3(0, 2, 3), ivec3(4, 5, 6), ivec3(7, 8, 9));
212
	CHECK(i3 == i3);
213
	CHECK(i3 != j3);
214
	CHECK(i3 != k3);
215
	CHECK(i3 != l3);
216
217
	mat4 m4(vec4(1, 2, 3, 4), vec4(3, 4, 5, 6), vec4(5, 6, 7, 8), vec4(7, 8, 9, 0));
218
	mat4 n4(vec4(1, 2, 0, 4), vec4(3, 4, 5, 6), vec4(5, 6, 7, 8), vec4(7, 8, 9, 0));
219
	mat4 o4(vec4(1, 2, 3, 4), vec4(0, 4, 5, 6), vec4(5, 6, 7, 8), vec4(7, 8, 9, 0));
220
	mat4 p4(vec4(1, 2, 3, 4), vec4(3, 4, 5, 6), vec4(5, 0, 7, 8), vec4(7, 8, 9, 0));
221
	mat4 q4(vec4(1, 2, 3, 4), vec4(3, 4, 5, 6), vec4(5, 6, 7, 8), vec4(7, 8, 9, 1));
222
	CHECK(m4 == m4);
223
	CHECK(m4 != n4);
224
	CHECK(m4 != o4);
225
	CHECK(m4 != p4);
226
	CHECK(m4 != q4);
227
228
	imat4 i4(ivec4(1, 2, 3, 4), ivec4(3, 4, 5, 6), ivec4(5, 6, 7, 8), ivec4(7, 8, 9, 0));
229
	imat4 j4(ivec4(1, 0, 3, 4), ivec4(3, 4, 5, 6), ivec4(5, 6, 7, 8), ivec4(7, 8, 9, 0));
230
	imat4 k4(ivec4(1, 2, 3, 4), ivec4(3, 4, 0, 6), ivec4(5, 6, 7, 8), ivec4(7, 8, 9, 0));
231
	imat4 l4(ivec4(1, 2, 3, 4), ivec4(3, 4, 5, 6), ivec4(5, 6, 7, 0), ivec4(7, 8, 9, 0));
232
	imat4 h4(ivec4(1, 2, 3, 4), ivec4(3, 4, 5, 6), ivec4(5, 6, 7, 8), ivec4(0, 8, 9, 0));
233
	CHECK(i4 == i4);
234
	CHECK(i4 != j4);
235
	CHECK(i4 != k4);
236
	CHECK(i4 != l4);
237
	CHECK(i4 != h4);
238
239
	mat32 m32(vec3(2, 3, 4), vec3(5, 6, 7));
240
	mat32 n32(vec3(2, 3, 0), vec3(5, 6, 7));
241
	mat32 o32(vec3(2, 3, 4), vec3(0, 6, 7));
242
	CHECK(m32 == m32);
243
	CHECK(m32 != n32);
244
	CHECK(m32 != o32);
245
246
	mat23 m23(vec2(2, 3), vec2(4, 5), vec2(6, 7));
247
	mat23 n23(vec2(0, 3), vec2(4, 5), vec2(6, 7));
248
	mat23 o23(vec2(2, 3), vec2(4, 0), vec2(6, 7));
249
	mat23 p23(vec2(2, 3), vec2(4, 5), vec2(0, 7));
250
	CHECK(m23 == m23);
251
	CHECK(m23 != n23);
252
	CHECK(m23 != o23);
253
	CHECK(m23 != p23);
254
}
255
256
TEST_CASE("gl_mat: copy constructor, assignment")
257
{
258
	SECTION("mat2") {
259
		mat2 m(vec2(2, 3));
260
		mat2 n(m);   CHECK(n == m);
261
		m[1][0] = 9; CHECK(n != m);
262
		n = m;       CHECK(n == m);
263
	}
264
	SECTION("imat2") {
265
		imat2 m(ivec2(2, 3));
266
		imat2 n(m);  CHECK(n == m);
267
		m[0][1] = 9; CHECK(n != m);
268
		n = m;       CHECK(n == m);
269
	}
270
	SECTION("mat3") {
271
		mat3 m(vec3(3, 4, 5));
272
		mat3 n(m);   CHECK(n == m);
273
		m[2][1] = 8; CHECK(n != m);
274
		n = m;       CHECK(n == m);
275
	}
276
	SECTION("imat3") {
277
		imat3 m(ivec3(3, 4, 5));
278
		imat3 n(m);  CHECK(n == m);
279
		m[1][2] = 8; CHECK(n != m);
280
		n = m;       CHECK(n == m);
281
	}
282
	SECTION("mat4") {
283
		mat4 m(vec4(4, 5, 6, 7));
284
		mat4 n(m);   CHECK(n == m);
285
		m[3][1] = 2; CHECK(n != m);
286
		n = m;       CHECK(n == m);
287
	}
288
	SECTION("imat3") {
289
		imat4 m(ivec4(4, 5, 6, 7));
290
		imat4 n(m);  CHECK(n == m);
291
		m[0][1] = 1; CHECK(n != m);
292
		n = m;       CHECK(n == m);
293
	}
294
}
295
296
TEST_CASE("gl_mat: construct from larger matrix")
297
{
298
	mat4 m4(vec4(1, 2, 3, 4), vec4(4, 5, 6, 7), vec4(7, 8, 9, 1), vec4(1, 0, 0, 0));
299
	mat3 m3(vec3(1, 2, 3), vec3(4, 5, 6), vec3(7, 8, 9));
300
	mat2 m2(vec2(1, 2), vec2(4, 5));
301
	CHECK(mat3(m4) == m3);
302
	CHECK(mat2(m4) == m2);
303
	CHECK(mat2(m3) == m2);
304
305
	imat4 i4(ivec4(1, 2, 3, 4), ivec4(4, 5, 6, 7), ivec4(7, 8, 9, 1), ivec4(1, 0, 0, 0));
306
	imat3 i3(ivec3(1, 2, 3), ivec3(4, 5, 6), ivec3(7, 8, 9));
307
	imat2 i2(ivec2(1, 2), ivec2(4, 5));
308
	CHECK(imat3(i4) == i3);
309
	CHECK(imat2(i4) == i2);
310
	CHECK(imat2(i3) == i2);
311
312
	CHECK(mat32(m4) == mat32(vec3(1, 2, 3), vec3(4, 5, 6)));
313
	CHECK(mat32(m3) == mat32(vec3(1, 2, 3), vec3(4, 5, 6)));
314
	CHECK(mat23(m4) == mat23(vec2(1, 2), vec2(4, 5), vec2(7, 8)));
315
	CHECK(mat23(m3) == mat23(vec2(1, 2), vec2(4, 5), vec2(7, 8)));
316
}
317
318
TEST_CASE("gl_mat: addition, subtraction, negation")
319
{
320
	mat3 m3(vec3(1, 2, 3), vec3(4, 5, 6), vec3(7, 8, 9));
321
	mat3 n3(vec3(2, 4, 6), vec3(1, 3, 5), vec3(7, 8, 9));
322
	mat3 o3 = m3 + n3;
323
	mat3 p3 = m3 - n3;
324
	CHECK(o3 == mat3(vec3( 3,  6,  9), vec3(5, 8, 11), vec3(14, 16, 18)));
325
	CHECK(p3 == mat3(vec3(-1, -2, -3), vec3(3, 2,  1), vec3( 0,  0,  0)));
326
	p3 += n3;
327
	o3 -= n3;
328
	CHECK(o3 == m3);
329
	CHECK(p3 == m3);
330
	CHECK(-m3 == mat3(vec3(-1, -2, -3), vec3(-4, -5, -6), vec3(-7, -8, -9)));
331
332
	imat3 i3(ivec3(6, 3, 0), ivec3(2, 4, 6), ivec3(3, 4, 5));
333
	imat3 j3(ivec3(1, 2, 3), ivec3(4, 0, 4), ivec3(0, 1, 1));
334
	imat3 k3 = i3 + j3;
335
	imat3 l3 = i3 - j3;
336
	CHECK(k3 == imat3(ivec3(7, 5,  3), ivec3( 6, 4, 10), ivec3(3, 5, 6)));
337
	CHECK(l3 == imat3(ivec3(5, 1, -3), ivec3(-2, 4,  2), ivec3(3, 3, 4)));
338
	l3 += j3;
339
	k3 -= j3;
340
	CHECK(k3 == i3);
341
	CHECK(l3 == i3);
342
	CHECK(-i3 == imat3(ivec3(-6, -3, -0), ivec3(-2, -4, -6), ivec3(-3, -4, -5)));
343
344
	mat4 m4(vec4(1, 2, 3, 4), vec4(4, 5, 6, 7), vec4(7, 8, 9, 1), vec4(1, 0, 0, 0));
345
	mat4 n4(vec4(2, 4, 6, 8), vec4(1, 3, 5, 7), vec4(7, 8, 9, 2), vec4(0, 0, 0, 1));
346
	mat4 o4 = m4 + n4;
347
	mat4 p4 = m4 - n4;
348
	CHECK(o4 == mat4(vec4( 3,  6,  9, 12), vec4(5, 8, 11, 14), vec4(14, 16, 18,  3), vec4(1, 0, 0,  1)));
349
	CHECK(p4 == mat4(vec4(-1, -2, -3, -4), vec4(3, 2,  1,  0), vec4( 0,  0,  0, -1), vec4(1, 0, 0, -1)));
350
	p4 += n4;
351
	o4 -= n4;
352
	CHECK(o4 == m4);
353
	CHECK(p4 == m4);
354
	CHECK(-m4 == mat4(vec4(-1, -2, -3, -4), vec4(-4, -5, -6, -7), vec4(-7, -8, -9, -1), vec4(-1, 0, 0, 0)));
355
356
	imat4 i4(ivec4(0, 1, 2, 3), ivec4(4, 3, 2, 1), ivec4(1, 1, 1, 1), ivec4(5, 5, 4, 4));
357
	imat4 j4(ivec4(2, 3, 4, 5), ivec4(1, 1, 2, 2), ivec4(0, 0, 1, 2), ivec4(1, 2, 2, 0));
358
	imat4 k4 = i4 + j4;
359
	imat4 l4 = i4 - j4;
360
	CHECK(k4 == imat4(ivec4( 2,  4,  6,  8), ivec4(5, 4, 4,  3), ivec4(1, 1, 2,  3), ivec4(6, 7, 6, 4)));
361
	CHECK(l4 == imat4(ivec4(-2, -2, -2, -2), ivec4(3, 2, 0, -1), ivec4(1, 1, 0, -1), ivec4(4, 3, 2, 4)));
362
	l4 += j4;
363
	k4 -= j4;
364
	CHECK(k4 == i4);
365
	CHECK(l4 == i4);
366
	CHECK(-i4 == imat4(ivec4(0, -1, -2, -3), ivec4(-4, -3, -2, -1), ivec4(-1, -1, -1, -1), ivec4(-5, -5, -4, -4)));
367
368
	mat32 m32(vec3(3, 4, 5), vec3(4, 2, 0));
369
	mat32 n32(vec3(1, 1, 2), vec3(4, 4, 3));
370
	mat32 o32 = m32 + n32;
371
	mat32 p32 = m32 - n32;
372
	CHECK(o32 == mat32(vec3(4, 5, 7), vec3(8,  6,  3)));
373
	CHECK(p32 == mat32(vec3(2, 3, 3), vec3(0, -2, -3)));
374
	p32 += n32;
375
	o32 -= n32;
376
	CHECK(o32 == m32);
377
	CHECK(p32 == m32);
378
	CHECK(-m32 == mat32(vec3(-3, -4, -5), vec3(-4, -2, 0)));
379
}
380
381
TEST_CASE("gl_mat: matrix * scalar")
382
{
383
	mat3 m3(vec3(1, 2, 3), vec3(4,  5,  6), vec3( 7,  8,  9));
384
	mat3 n3(vec3(2, 4, 6), vec3(8, 10, 12), vec3(14, 16, 18));
385
	CHECK((2.0f * m3) == n3);
386
	CHECK((m3 * 2.0f) == n3);
387
	m3 *= 2.0f;
388
	CHECK(m3 == n3);
389
390
	imat3 i3(ivec3(2, 1, 0), ivec3(-1,  5, 3), ivec3( 7, 0, -3));
391
	imat3 j3(ivec3(4, 2, 0), ivec3(-2, 10, 6), ivec3(14, 0, -6));
392
	CHECK((2 * i3) == j3);
393
	CHECK((i3 * 2) == j3);
394
	i3 *= 2;
395
	CHECK(i3 == j3);
396
397
	mat4 m4(vec4(1, 2, 3, 4), vec4(4,  5,  6,  7), vec4( 7,  8,  9, 10), vec4(0, 0, -1, -2));
398
	mat4 n4(vec4(2, 4, 6, 8), vec4(8, 10, 12, 14), vec4(14, 16, 18, 20), vec4(0, 0, -2, -4));
399
	CHECK((2.0f * m4) == n4);
400
	CHECK((m4 * 2.0f) == n4);
401
	m4 *= 2.0f;
402
	CHECK(m4 == n4);
403
404
	imat4 i4(ivec4(0, 1, 2, 3), ivec4(1, 0, 0, 2), ivec4(3, 2, 1, 0), ivec4(0, 0, -1, -2));
405
	imat4 j4(ivec4(0, 3, 6, 9), ivec4(3, 0, 0, 6), ivec4(9, 6, 3, 0), ivec4(0, 0, -3, -6));
406
	CHECK((3 * i4) == j4);
407
	CHECK((i4 * 3) == j4);
408
	i4 *= 3;
409
	CHECK(i4 == j4);
410
411
	mat32 m32(vec3( 3,  4,   5), vec3( 4,  2, 0));
412
	mat32 n32(vec3(-6, -8, -10), vec3(-8, -4, 0));
413
	CHECK((-2.0f * m32) == n32);
414
	CHECK((m32 * -2.0f) == n32);
415
	m32 *= -2.0f;
416
	CHECK(m32 == n32);
417
}
418
419
TEST_CASE("gl_mat: matrix * column-vector")
420
{
421
	mat3 m3(vec3(1, 2, 3), vec3(4, 5, 6), vec3(7, 8, 9));
422
	CHECK((m3 * vec3(1, 0, 0)) == vec3( 1,  2,  3));
423
	CHECK((m3 * vec3(0, 2, 0)) == vec3( 8, 10, 12));
424
	CHECK((m3 * vec3(0, 0, 3)) == vec3(21, 24, 27));
425
	CHECK((m3 * vec3(1, 2, 3)) == vec3(30, 36, 42));
426
427
	imat3 i3(ivec3(0, -2, 1), ivec3(1, -1, 0), ivec3(-1, -2, 1));
428
	CHECK((i3 * ivec3(-1, 0, 0)) == ivec3( 0,  2, -1));
429
	CHECK((i3 * ivec3( 0, 0, 0)) == ivec3( 0,  0,  0));
430
	CHECK((i3 * ivec3( 0, 0, 3)) == ivec3(-3, -6,  3));
431
	CHECK((i3 * ivec3(-1, 0, 3)) == ivec3(-3, -4,  2));
432
433
	mat4 m4(vec4(1, 2, 3, 4), vec4(4, 5, 6, 7), vec4(7, 8, 9, 1), vec4(0, 1, 0, -1));
434
	CHECK((m4 * vec4(1, 0, 0, 0)) == vec4( 1,  2,  3,  4));
435
	CHECK((m4 * vec4(0, 2, 0, 0)) == vec4( 8, 10, 12, 14));
436
	CHECK((m4 * vec4(0, 0, 3, 0)) == vec4(21, 24, 27,  3));
437
	CHECK((m4 * vec4(0, 0, 0, 4)) == vec4( 0,  4,  0, -4));
438
	CHECK((m4 * vec4(1, 2, 3, 4)) == vec4(30, 40, 42, 17));
439
440
	imat4 i4(ivec4(-1, 2, 0, -3), ivec4(0, 1, 2, -1), ivec4(0, 1, 1, 0), ivec4(-1, 1, 0, -1));
441
	CHECK((i4 * ivec4(-1, 0,  0, 0)) == ivec4( 1, -2,  0,  3));
442
	CHECK((i4 * ivec4( 0, 2,  0, 0)) == ivec4( 0,  2,  4, -2));
443
	CHECK((i4 * ivec4( 0, 0, -2, 0)) == ivec4( 0, -2, -2,  0));
444
	CHECK((i4 * ivec4( 0, 0,  0, 1)) == ivec4(-1,  1,  0, -1));
445
	CHECK((i4 * ivec4(-1, 2, -2, 1)) == ivec4( 0, -1,  2,  0));
446
447
	mat32 m32(vec3(3, 4, 5), vec3(4, 2, 0));
448
	CHECK((m32 * vec2(2, 3)) == vec3(18, 14, 10));
449
450
	mat23 m23(vec2(3, 4), vec2(1, 5), vec2(4, 2));
451
	CHECK((m23 * vec3(1, 2, 3)) == vec2(17, 20));
452
}
453
454
TEST_CASE("gl_mat: matrix * matrix")
455
{
456
	mat3 m3(vec3(1, -1,  1), vec3(2,  0, -1), vec3(0, 1, 1));
457
	mat3 n3(vec3(1,  1, -1), vec3(0, -2,  1), vec3(1, 0, 1));
458
	mat3 o3(vec3(0, -1,  2), vec3(1,  2, -2), vec3(0, 2, 1));
459
	CHECK((m3 * n3) == mat3(vec3(3, -2, -1), vec3(-4,  1,  3), vec3(1,  0, 2)));
460
	CHECK((n3 * o3) == mat3(vec3(2,  2,  1), vec3(-1, -3, -1), vec3(1, -4, 3)));
461
	CHECK(((m3 * n3) * o3) == (m3 * (n3 * o3)));
462
463
	imat3 i3(ivec3( 1, 1,  1), ivec3(-2,  0, -1), ivec3(0, -1, 1));
464
	imat3 j3(ivec3(-1, 0, -1), ivec3( 1, -2,  1), ivec3(1, -1, 1));
465
	CHECK((i3 * j3) == imat3(ivec3(-1, 0, -2), ivec3(5, 0, 4), ivec3(3, 0, 3)));
466
467
	mat4 m4(vec4(1, -1,  1, 0), vec4(2,  0, -1, 1), vec4(0, 1, 1, -1), vec4(2, 0, 1, -1));
468
	mat4 n4(vec4(1,  1, -1, 1), vec4(0, -2,  1, 0), vec4(1, 0, 1, -1), vec4(0, 1, 2, -2));
469
	CHECK((m4 * n4) == mat4(vec4(5, -2, 0, 1), vec4(-4, 1,  3, -3), vec4(-1,  0, 1, 0), vec4(-2, 2, -1, 1)));
470
	CHECK((n4 * m4) == mat4(vec4(2, 3, -1, 0), vec4( 1, 3, -1,  1), vec4( 1, -3, 0, 1), vec4( 3, 1, -3, 3)));
471
472
	imat4 i4(ivec4(1, -1,  1, 2), ivec4(2, -1, -1,  1), ivec4(2,  1, 1, -1), ivec4( 2, -1, 1, -1));
473
	imat4 j4(ivec4(1,  1, -1, 1), ivec4(2, -2,  1, -1), ivec4(1, -2, 1, -1), ivec4(-1,  1, 2, -2));
474
	CHECK((i4 * j4) == imat4(ivec4(3, -4, 0, 3), ivec4(-2, 2, 4, 2), ivec4(-3, 3, 3, 0), ivec4(1, 4, -2, -1)));
475
476
	mat32 m32(vec3(1, 2, -1), vec3(-1, -1, 2));
477
	mat23 m23(vec2(1, -2), vec2(2, -1), vec2(1, -1));
478
	CHECK((m32 * m23) == mat3(vec3(3, 4, -5), vec3(3, 5, -4), vec3(2, 3, -3)));
479
	CHECK((m23 * m32) == mat2(vec2(4, -3), vec2(-1, 1)));
480
	CHECK((m3  * m32) == mat32(vec3(5, -2, -2), vec3(-3, 3, 2)));
481
	CHECK((m23 * m3 ) == mat23(vec2(0, -2), vec2(1, -3), vec2(3, -2)));
482
}
483
484
TEST_CASE("gl_mat: transpose")
485
{
486
	mat3 m3(vec3(1, -1, 1), vec3(2, 0, -1), vec3(0, 1, 1));
487
	CHECK(transpose(m3) == mat3(vec3(1, 2, 0), vec3(-1, 0, 1), vec3(1, -1, 1)));
488
489
	imat3 i3(ivec3(1, 1, 1), ivec3(-2, 0, -1), ivec3(0, -1, 1));
490
	CHECK(transpose(i3) == imat3(ivec3(1, -2, 0), ivec3(1, 0, -1), ivec3(1, -1, 1)));
491
492
	mat4 m4(vec4(1, -1, 1, 0), vec4(2, 0, -1, 1), vec4(0, 1, 1, -1), vec4(2, 0, 1, -1));
493
	CHECK(transpose(m4) == mat4(vec4(1, 2, 0, 2), vec4(-1, 0, 1, 0), vec4(1, -1, 1, 1), vec4(0, 1, -1, -1)));
494
495
	imat4 i4(ivec4(1, -1, 1, 2), ivec4(2, -1, -1, 1), ivec4(2, 1, 1, -1), ivec4(2, -1, 1, -1));
496
	CHECK(transpose(i4) == imat4(ivec4(1, 2, 2, 2), ivec4(-1, -1, 1, -1), ivec4(1, -1, 1, 1), ivec4(2, 1, -1, -1)));
497
498
	mat32 m32(vec3(1, 2, 3), vec3(4, 5, 6));
499
	mat23 m23(vec2(1, 4), vec2(2, 5), vec2(3, 6));
500
	CHECK(transpose(m32) == m23);
501
	CHECK(transpose(m23) == m32);
502
}
503
504
TEST_CASE("gl_mat: determinant, inverse")
505
{
506
	mat2 m2(vec2(1, -1), vec2(0, 1));
507
	CHECK(determinant(m2) == 1.0f);
508
	mat2 i2 = inverse(m2);
509
	CHECK(determinant(i2) == 1.0f);
510
	CHECK(i2 == mat2(vec2(1, 1), vec2(0, 1)));
511
	CHECK(m2 * i2 == mat2());
512
	CHECK(i2 * m2 == mat2());
513
514
	mat3 m3(vec3(1, 0, -1), vec3(0, 1, 0), vec3(1, -1, 1));
515
	CHECK(determinant(m3) == 2.0f);
516
	mat3 i3 = inverse(m3);
517
	CHECK(determinant(i3) == 0.5f);
518
	CHECK(i3 == mat3(vec3(0.5f, 0.5f, 0.5f), vec3(0, 1, 0), vec3(-0.5f, 0.5f, 0.5f)));
519
	CHECK(m3 * i3 == mat3());
520
	CHECK(i3 * m3 == mat3());
521
522
	mat4 m4(vec4(0, 1, 1, 0), vec4(-1, 0, 1, 0), vec4(1, 1, 0, -1), vec4(0, 1, 0, 0));
523
	CHECK(determinant(m4) == -1.0f);
524
	mat4 i4 = inverse(m4);
525
	CHECK(approxEq(i4, mat4(vec4(1, -1, 0, -1), vec4(0, 0, 0, 1), vec4(1, 0, 0, -1), vec4(1, -1, -1, 0))));
526
	CHECK(approxEq(m4 * i4, mat4()));
527
	CHECK(approxEq(i4 * m4, mat4()));
528
}
529
530
TEST_CASE("gl_mat: norm-2 squared")
531
{
532
	mat3 m3(vec3(1, -1, 1), vec3(2, 0, -1), vec3(0, 1, 1));
533
	CHECK(norm2_2(m3) == 10);
534
535
	imat3 i3(ivec3(1, 2, 1), ivec3(-2, 3, -1), ivec3(2, 1, 4));
536
	CHECK(norm2_2(i3) == 41);
537
538
	mat4 m4(vec4(1, -1, 1, 2), vec4(2, 0, -1, 1), vec4(0, 1, 1, 0), vec4(0, 1, 1, 3));
539
	CHECK(norm2_2(m4) == 26);
540
541
	imat4 i4(ivec4(1, 2, 1, -3), ivec4(-2, 3, -1, 0), ivec4(2, 1, 4, -2), ivec4(0, 2, 2, 2));
542
	CHECK(norm2_2(i4) == 66);
543
544
	mat32 m32(vec3(1, 2, -1), vec3(-1, -1, 2));
545
	mat23 m23(vec2(1, -1), vec2(2, -1), vec2(-1, 2));
546
	CHECK(norm2_2(m32) == norm2_2(m23));
547
}
548
549
550
#if 0
551
552
// The following functions are not part of the actual test. They get compiled,
553
// but never executed. I used them to (manually) inspect the quality of the
554
// generated code. Only for mat4, because the code was only optimized for that
555
// type.
556
557
void test_constr(mat4& A)
558
{
559
	A = mat4();
560
}
561
void test_constr(const vec4& x, mat4& A)
562
{
563
	A = mat4(x);
564
}
565
void test_constr(const vec4& x, const vec4& y, const vec4& z, const vec4& w, mat4& A)
566
{
567
	A = mat4(x, y, z, w);
568
}
569
void test_constr(const mat4& A, mat3& B)
570
{
571
	B = mat3(A);
572
}
573
574
void test_change0(const vec4& x, mat4& A)
575
{
576
	A[0] = x;
577
}
578
void test_change2(const vec4& x, mat4& A)
579
{
580
	A[2] = x;
581
}
582
void test_extr0(const mat4& A, vec4& x)
583
{
584
	x = A[0];
585
}
586
void test_extr2(const mat4& A, vec4& x)
587
{
588
	x = A[2];
589
}
590
591
bool test_equal(const mat4& A, const mat4& B)
592
{
593
	return A == B;
594
}
595
bool test_not_equal(const mat4& A, const mat4& B)
596
{
597
	return A != B;
598
}
599
600
void test_add(const mat4& A, const mat4& B, mat4& C)
601
{
602
	C = A + B;
603
}
604
void test_add(const mat4& A, mat4& B)
605
{
606
	B += A;
607
}
608
void test_sub(const mat4& A, const mat4& B, mat4& C)
609
{
610
	C = A - B;
611
}
612
void test_negate(const mat4& A, mat4& B)
613
{
614
	B = -A;
615
}
616
617
void test_mul(float x, const mat4& A, mat4& B)
618
{
619
	B = x * A;
620
}
621
void test_mul(const mat4& A, const vec4& x, vec4& y)
622
{
623
	y = A * x;
624
}
625
void test_mul(const mat4& A, const mat4& B, mat4& C)
626
{
627
	C = A * B;
628
}
629
630
void test_transpose(const mat4& A, mat4& B)
631
{
632
	B = transpose(A);
633
}
634
635
void test_determinant(const mat4& A, float& x)
636
{
637
	x = determinant(A);
638
}
639
640
void test_inverse(const mat4& A, mat4& B)
641
{
642
	B = inverse(A);
643
}
644
645
void test_norm(const mat4& A, float& x)
646
{
647
	x = norm2_2(A);
648
}
649
650
#endif