Blender V4.3
BLI_math_matrix_types_test.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
5#include "testing/testing.h"
6
7#include "BLI_math_matrix.hh"
9
10namespace blender::tests {
11
12using namespace blender::math;
13
14TEST(math_matrix_types, DefaultConstructor)
15{
16 float2x2 m{};
17 EXPECT_EQ(m[0][0], 0.0f);
18 EXPECT_EQ(m[1][1], 0.0f);
19 EXPECT_EQ(m[0][1], 0.0f);
20 EXPECT_EQ(m[1][0], 0.0f);
21}
22
23TEST(math_matrix_types, StaticConstructor)
24{
26 EXPECT_EQ(m[0][0], 1.0f);
27 EXPECT_EQ(m[1][1], 1.0f);
28 EXPECT_EQ(m[0][1], 0.0f);
29 EXPECT_EQ(m[1][0], 0.0f);
30
31 m = float2x2::zero();
32 EXPECT_EQ(m[0][0], 0.0f);
33 EXPECT_EQ(m[1][1], 0.0f);
34 EXPECT_EQ(m[0][1], 0.0f);
35 EXPECT_EQ(m[1][0], 0.0f);
36
37 m = float2x2::diagonal(2);
38 EXPECT_EQ(m[0][0], 2.0f);
39 EXPECT_EQ(m[1][1], 2.0f);
40 EXPECT_EQ(m[0][1], 0.0f);
41 EXPECT_EQ(m[1][0], 0.0f);
42
43 m = float2x2::all(1);
44 EXPECT_EQ(m[0][0], 1.0f);
45 EXPECT_EQ(m[1][1], 1.0f);
46 EXPECT_EQ(m[0][1], 1.0f);
47 EXPECT_EQ(m[1][0], 1.0f);
48}
49
50TEST(math_matrix_types, VectorConstructor)
51{
52 float3x2 m({1.0f, 2.0f}, {3.0f, 4.0f}, {5.0f, 6.0f});
53 EXPECT_EQ(m[0][0], 1.0f);
54 EXPECT_EQ(m[0][1], 2.0f);
55 EXPECT_EQ(m[1][0], 3.0f);
56 EXPECT_EQ(m[1][1], 4.0f);
57 EXPECT_EQ(m[2][0], 5.0f);
58 EXPECT_EQ(m[2][1], 6.0f);
59}
60
61TEST(math_matrix_types, SmallerMatrixConstructor)
62{
63 float2x2 m2({1.0f, 2.0f}, {3.0f, 4.0f});
64 float3x3 m3(m2);
65 EXPECT_EQ(m3[0][0], 1.0f);
66 EXPECT_EQ(m3[0][1], 2.0f);
67 EXPECT_EQ(m3[0][2], 0.0f);
68 EXPECT_EQ(m3[1][0], 3.0f);
69 EXPECT_EQ(m3[1][1], 4.0f);
70 EXPECT_EQ(m3[1][2], 0.0f);
71 EXPECT_EQ(m3[2][0], 0.0f);
72 EXPECT_EQ(m3[2][1], 0.0f);
73 EXPECT_EQ(m3[2][2], 1.0f);
74}
75
76TEST(math_matrix_types, ComponentMasking)
77{
78 float3x3 m3({1.1f, 1.2f, 1.3f}, {2.1f, 2.2f, 2.3f}, {3.1f, 3.2f, 3.3f});
79 float2x2 m2(m3);
80 EXPECT_EQ(m2[0][0], 1.1f);
81 EXPECT_EQ(m2[0][1], 1.2f);
82 EXPECT_EQ(m2[1][0], 2.1f);
83 EXPECT_EQ(m2[1][1], 2.2f);
84}
85
86TEST(math_matrix_types, PointerConversion)
87{
88 float array[4] = {1.0f, 2.0f, 3.0f, 4.0f};
89 float2x2 m2(array);
90 EXPECT_EQ(m2[0][0], 1.0f);
91 EXPECT_EQ(m2[0][1], 2.0f);
92 EXPECT_EQ(m2[1][0], 3.0f);
93 EXPECT_EQ(m2[1][1], 4.0f);
94}
95
96TEST(math_matrix_types, TypeConversion)
97{
98 float3x2 m(double3x2({1.0f, 2.0f}, {3.0f, 4.0f}, {5.0f, 6.0f}));
99 EXPECT_EQ(m[0][0], 1.0f);
100 EXPECT_EQ(m[0][1], 2.0f);
101 EXPECT_EQ(m[1][0], 3.0f);
102 EXPECT_EQ(m[1][1], 4.0f);
103 EXPECT_EQ(m[2][0], 5.0f);
104 EXPECT_EQ(m[2][1], 6.0f);
105
106 double3x2 d(m);
107 EXPECT_EQ(d[0][0], 1.0f);
108 EXPECT_EQ(d[0][1], 2.0f);
109 EXPECT_EQ(d[1][0], 3.0f);
110 EXPECT_EQ(d[1][1], 4.0f);
111 EXPECT_EQ(d[2][0], 5.0f);
112 EXPECT_EQ(d[2][1], 6.0f);
113}
114
115TEST(math_matrix_types, PointerArrayConversion)
116{
117 float array[2][2] = {{1.0f, 2.0f}, {3.0f, 4.0f}};
118 float(*ptr)[2] = array;
119 float2x2 m2(ptr);
120 EXPECT_EQ(m2[0][0], 1.0f);
121 EXPECT_EQ(m2[0][1], 2.0f);
122 EXPECT_EQ(m2[1][0], 3.0f);
123 EXPECT_EQ(m2[1][1], 4.0f);
124}
125
126TEST(math_matrix_types, ComponentAccess)
127{
128 float3x3 m3({1.1f, 1.2f, 1.3f}, {2.1f, 2.2f, 2.3f}, {3.1f, 3.2f, 3.3f});
129 EXPECT_EQ(m3.x.x, 1.1f);
130 EXPECT_EQ(m3.x.y, 1.2f);
131 EXPECT_EQ(m3.y.x, 2.1f);
132 EXPECT_EQ(m3.y.y, 2.2f);
133}
134
135TEST(math_matrix_types, AddOperator)
136{
137 float3x3 m3({1.1f, 1.2f, 1.3f}, {2.1f, 2.2f, 2.3f}, {3.1f, 3.2f, 3.3f});
138
139 m3 = m3 + float3x3::diagonal(2);
140 EXPECT_EQ(m3[0][0], 3.1f);
141 EXPECT_EQ(m3[0][2], 1.3f);
142 EXPECT_EQ(m3[2][0], 3.1f);
143 EXPECT_EQ(m3[2][2], 5.3f);
144
145 m3 += float3x3::diagonal(-1.0f);
146 EXPECT_EQ(m3[0][0], 2.1f);
147 EXPECT_EQ(m3[0][2], 1.3f);
148 EXPECT_EQ(m3[2][0], 3.1f);
149 EXPECT_EQ(m3[2][2], 4.3f);
150
151 m3 += 1.0f;
152 EXPECT_EQ(m3[0][0], 3.1f);
153 EXPECT_EQ(m3[0][2], 2.3f);
154 EXPECT_EQ(m3[2][0], 4.1f);
155 EXPECT_EQ(m3[2][2], 5.3f);
156
157 m3 = m3 + 1.0f;
158 EXPECT_EQ(m3[0][0], 4.1f);
159 EXPECT_EQ(m3[0][2], 3.3f);
160 EXPECT_EQ(m3[2][0], 5.1f);
161 EXPECT_EQ(m3[2][2], 6.3f);
162
163 m3 = 1.0f + m3;
164 EXPECT_EQ(m3[0][0], 5.1f);
165 EXPECT_EQ(m3[0][2], 4.3f);
166 EXPECT_EQ(m3[2][0], 6.1f);
167 EXPECT_EQ(m3[2][2], 7.3f);
168}
169
170TEST(math_matrix_types, SubtractOperator)
171{
172 float3x3 m3({10.0f, 10.2f, 10.3f}, {20.1f, 20.2f, 20.3f}, {30.1f, 30.2f, 30.3f});
173
174 m3 = m3 - float3x3::diagonal(2);
175 EXPECT_EQ(m3[0][0], 8.0f);
176 EXPECT_EQ(m3[0][2], 10.3f);
177 EXPECT_EQ(m3[2][0], 30.1f);
178 EXPECT_EQ(m3[2][2], 28.3f);
179
180 m3 -= float3x3::diagonal(-1.0f);
181 EXPECT_EQ(m3[0][0], 9.0f);
182 EXPECT_EQ(m3[0][2], 10.3f);
183 EXPECT_EQ(m3[2][0], 30.1f);
184 EXPECT_EQ(m3[2][2], 29.3f);
185
186 m3 -= 1.0f;
187 EXPECT_EQ(m3[0][0], 8.0f);
188 EXPECT_EQ(m3[0][2], 9.3f);
189 EXPECT_EQ(m3[2][0], 29.1f);
190 EXPECT_EQ(m3[2][2], 28.3f);
191
192 m3 = m3 - 1.0f;
193 EXPECT_EQ(m3[0][0], 7.0f);
194 EXPECT_EQ(m3[0][2], 8.3f);
195 EXPECT_EQ(m3[2][0], 28.1f);
196 EXPECT_EQ(m3[2][2], 27.3f);
197
198 m3 = 1.0f - m3;
199 EXPECT_EQ(m3[0][0], -6.0f);
200 EXPECT_EQ(m3[0][2], -7.3f);
201 EXPECT_EQ(m3[2][0], -27.1f);
202 EXPECT_EQ(m3[2][2], -26.3f);
203}
204
205TEST(math_matrix_types, MultiplyOperator)
206{
207 float3x3 m3(float3(1.0f), float3(2.0f), float3(2.0f));
208
209 m3 = m3 * 2;
210 EXPECT_EQ(m3[0][0], 2.0f);
211 EXPECT_EQ(m3[2][2], 4.0f);
212
213 m3 = 2 * m3;
214 EXPECT_EQ(m3[0][0], 4.0f);
215 EXPECT_EQ(m3[2][2], 8.0f);
216
217 m3 *= 2;
218 EXPECT_EQ(m3[0][0], 8.0f);
219 EXPECT_EQ(m3[2][2], 16.0f);
220}
221
222TEST(math_matrix_types, MatrixMultiplyOperator)
223{
224 float2x2 a(float2(1, 2), float2(3, 4));
225 float2x2 b(float2(5, 6), float2(7, 8));
226
227 float2x2 result = a * b;
228 EXPECT_EQ(result[0][0], 23);
229 EXPECT_EQ(result[0][1], 34);
230 EXPECT_EQ(result[1][0], 31);
231 EXPECT_EQ(result[1][1], 46);
232
233 result = a;
234 result *= b;
235 EXPECT_EQ(result[0][0], 23);
236 EXPECT_EQ(result[0][1], 34);
237 EXPECT_EQ(result[1][0], 31);
238 EXPECT_EQ(result[1][1], 46);
239
240 /* Test SSE2 implementation. */
242 EXPECT_EQ(result2, float4x4::diagonal(12));
243
245 EXPECT_EQ(result3, float3x3::diagonal(12));
246
247 /* Non square matrices. */
248 float3x2 a4(float2(1, 2), float2(3, 4), float2(5, 6));
249 float2x3 b4(float3(11, 7, 5), float3(13, 11, 17));
250
251 float2x2 expect4(float2(57, 80), float2(131, 172));
252
253 float2x2 result4 = a4 * b4;
254 EXPECT_EQ(result4[0][0], expect4[0][0]);
255 EXPECT_EQ(result4[0][1], expect4[0][1]);
256 EXPECT_EQ(result4[1][0], expect4[1][0]);
257 EXPECT_EQ(result4[1][1], expect4[1][1]);
258
259 float3x4 a5(float4(1), float4(3), float4(5));
260 float2x3 b5(float3(11, 7, 5), float3(13, 11, 17));
261
262 float2x4 expect5(float4(57), float4(131));
263
264 float2x4 result5 = a5 * b5;
265 EXPECT_EQ(result5[0][0], expect5[0][0]);
266 EXPECT_EQ(result5[0][1], expect5[0][1]);
267 EXPECT_EQ(result5[0][2], expect5[0][2]);
268 EXPECT_EQ(result5[0][3], expect5[0][3]);
269 EXPECT_EQ(result5[1][0], expect5[1][0]);
270 EXPECT_EQ(result5[1][1], expect5[1][1]);
271 EXPECT_EQ(result5[1][2], expect5[1][2]);
272 EXPECT_EQ(result5[1][3], expect5[1][3]);
273}
274
275TEST(math_matrix_types, VectorMultiplyOperator)
276{
277 float3x2 mat(float2(1, 2), float2(3, 4), float2(5, 6));
278
279 float2 result = mat * float3(7, 8, 9);
280 EXPECT_EQ(result[0], 76);
281 EXPECT_EQ(result[1], 100);
282
283 float3 result2 = float2(2, 3) * mat;
284 EXPECT_EQ(result2[0], 8);
285 EXPECT_EQ(result2[1], 18);
286 EXPECT_EQ(result2[2], 28);
287}
288
289TEST(math_matrix_types, ViewConstructor)
290{
291 float4x4 mat = float4x4(
292 float4(1, 2, 3, 4), float4(5, 6, 7, 8), float4(9, 10, 11, 12), float4(13, 14, 15, 16));
293
294 auto view = mat.view<2, 2, 1, 1>();
295 EXPECT_EQ(view[0][0], 6);
296 EXPECT_EQ(view[0][1], 7);
297 EXPECT_EQ(view[1][0], 10);
298 EXPECT_EQ(view[1][1], 11);
299
300 float2x2 center = view;
301 EXPECT_EQ(center[0][0], 6);
302 EXPECT_EQ(center[0][1], 7);
303 EXPECT_EQ(center[1][0], 10);
304 EXPECT_EQ(center[1][1], 11);
305}
306
307TEST(math_matrix_types, ViewFromCstyleMatrix)
308{
309 float c_style_mat[4][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}, {13, 14, 15, 16}};
310 float4x4_view c_mat_view = float4x4_view(c_style_mat);
311
312 float4x4_mutableview c_mat_mutable_view = float4x4_mutableview(c_style_mat);
313
314 float4x4 expect = float4x4({2, 4, 6, 8}, {10, 12, 14, 16}, {18, 20, 22, 24}, {26, 28, 30, 32});
315
316 float4x4 mat = float4x4::diagonal(2.0f) * c_mat_view;
317 EXPECT_M4_NEAR(expect, mat, 1e-8f);
318
319 c_mat_mutable_view *= float4x4::diagonal(2.0f);
320 EXPECT_M4_NEAR(expect, c_mat_mutable_view, 1e-8f);
321}
322
323TEST(math_matrix_types, ViewAssignment)
324{
325 float4x4 mat = float4x4(
326 float4(1, 2, 3, 4), float4(5, 6, 7, 8), float4(9, 10, 11, 12), float4(13, 14, 15, 16));
327
328 mat.view<2, 2, 1, 1>() = float2x2({-1, -2}, {-3, -4});
329
330 float4x4 expect = float4x4({1, 2, 3, 4}, {5, -1, -2, 8}, {9, -3, -4, 12}, {13, 14, 15, 16});
331 EXPECT_M4_NEAR(expect, mat, 1e-8f);
332
333 /* Test view-view assignment. */
334 mat.view<2, 2, 2, 2>() = mat.view<2, 2, 0, 0>();
335 float4x4 expect2 = float4x4({1, 2, 3, 4}, {5, -1, -2, 8}, {9, -3, 1, 2}, {13, 14, 5, -1});
336 EXPECT_M4_NEAR(expect2, mat, 1e-8f);
337
338 mat.view<2, 2, 0, 0>() = mat.view<2, 2, 1, 1>();
339 float4x4 expect3 = float4x4({-1, -2, 3, 4}, {-3, 1, -2, 8}, {9, -3, 1, 2}, {13, 14, 5, -1});
340 EXPECT_M4_NEAR(expect3, mat, 1e-8f);
341
342 /* Should fail to compile. */
343 // const float4x4 &mat_const = mat;
344 // mat.view<2, 2, 2, 2>() = mat_const.view<2, 2, 0, 0>();
345
346 /* Should fail to run. */
347 // mat.view<2, 2, 1, 1>() = mat.view<2, 2>();
348}
349
350TEST(math_matrix_types, ViewScalarOperators)
351{
352 float4x4 mat = float4x4({1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}, {13, 14, 15, 16});
353
354 auto view = mat.view<2, 2, 1, 1>();
355 EXPECT_EQ(view[0][0], 6);
356 EXPECT_EQ(view[0][1], 7);
357 EXPECT_EQ(view[1][0], 10);
358 EXPECT_EQ(view[1][1], 11);
359
360 view += 1;
361 EXPECT_EQ(view[0][0], 7);
362 EXPECT_EQ(view[0][1], 8);
363 EXPECT_EQ(view[1][0], 11);
364 EXPECT_EQ(view[1][1], 12);
365
366 view -= 2;
367 EXPECT_EQ(view[0][0], 5);
368 EXPECT_EQ(view[0][1], 6);
369 EXPECT_EQ(view[1][0], 9);
370 EXPECT_EQ(view[1][1], 10);
371
372 view *= 4;
373 EXPECT_EQ(view[0][0], 20);
374 EXPECT_EQ(view[0][1], 24);
375 EXPECT_EQ(view[1][0], 36);
376 EXPECT_EQ(view[1][1], 40);
377
378 /* Since we modified the view, we expect the source to have changed. */
379 float4x4 expect = float4x4({1, 2, 3, 4}, {5, 20, 24, 8}, {9, 36, 40, 12}, {13, 14, 15, 16});
380 EXPECT_M4_NEAR(expect, mat, 1e-8f);
381
382 view = -view;
383 EXPECT_EQ(view[0][0], -20);
384 EXPECT_EQ(view[0][1], -24);
385 EXPECT_EQ(view[1][0], -36);
386 EXPECT_EQ(view[1][1], -40);
387}
388
389TEST(math_matrix_types, ViewMatrixMultiplyOperator)
390{
391 float4x4 mat = float4x4({1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}, {13, 14, 15, 16});
392 auto view = mat.view<2, 2, 1, 1>();
393 view = float2x2({1, 2}, {3, 4});
394
395 float2x2 result = view * float2x2({5, 6}, {7, 8});
396 EXPECT_EQ(result[0][0], 23);
397 EXPECT_EQ(result[0][1], 34);
398 EXPECT_EQ(result[1][0], 31);
399 EXPECT_EQ(result[1][1], 46);
400
401 view *= float2x2({5, 6}, {7, 8});
402 EXPECT_EQ(view[0][0], 23);
403 EXPECT_EQ(view[0][1], 34);
404 EXPECT_EQ(view[1][0], 31);
405 EXPECT_EQ(view[1][1], 46);
406}
407
408TEST(math_matrix_types, ViewVectorMultiplyOperator)
409{
410 float4x4 mat = float4x4({1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}, {13, 14, 15, 16});
411 auto view = mat.view<2, 3, 1, 1>();
412
413 float3 result = view * float2(4, 5);
414 EXPECT_EQ(result[0], 74);
415 EXPECT_EQ(result[1], 83);
416 EXPECT_EQ(result[2], 92);
417
418 float2 result2 = float3(1, 2, 3) * view;
419 EXPECT_EQ(result2[0], 44);
420 EXPECT_EQ(result2[1], 68);
421}
422
423TEST(math_matrix_types, ViewMatrixNormalize)
424{
425 float4x4 mat = float4x4({1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}, {13, 14, 15, 16});
426 mat.view<3, 3>() = normalize(mat.view<3, 3>());
427
428 float4x4 expect = float4x4({0.267261236, 0.534522473, 0.80178368, 4},
429 {0.476731300, 0.572077572, 0.66742378, 8},
430 {0.517891824, 0.575435340, 0.63297885, 12},
431 {13, 14, 15, 16});
432 EXPECT_M4_NEAR(expect, mat, 1e-8f);
433}
434
435} // namespace blender::tests
EXPECT_EQ(BLI_expr_pylike_eval(expr, nullptr, 0, &result), EXPR_PYLIKE_INVALID)
static AppView * view
SIMD_FORCE_INLINE btVector3 & normalize()
Normalize this vector x^2 + y^2 + z^2 = 1.
Definition btVector3.h:303
local_group_size(16, 16) .push_constant(Type b
draw_view in_light_buf[] float
TEST(any, DefaultConstructor)
MatBase< float, 2, 2 > float2x2
MatBase< float, 4, 4 > float4x4
VecBase< float, 4 > float4
MatView< float, 4, 4, 4, 4, 0, 0, alignof(float)> float4x4_view
VecBase< float, 2 > float2
MutableMatView< float, 4, 4, 4, 4, 0, 0, alignof(float)> float4x4_mutableview
MatBase< double, 3, 2 > double3x2
VecBase< float, 3 > float3
static MatBase diagonal(T value)
const MatView< T, ViewNumCol, ViewNumRow, NumCol, NumRow, SrcStartCol, SrcStartRow, Alignment > view() const
static MatBase all(T value)
static MatBase identity()
PointerRNA * ptr
Definition wm_files.cc:4126