JOGL v2.6.0-rc-20250706
JOGL, High-Performance Graphics Binding for Java™ (public API).
TestMatrix4f03InversionNOUI.java
Go to the documentation of this file.
1/**
2 * Copyright 2014 JogAmp Community. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without modification, are
5 * permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright notice, this list of
8 * conditions and the following disclaimer.
9 *
10 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11 * of conditions and the following disclaimer in the documentation and/or other materials
12 * provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
15 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
21 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
22 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 *
24 * The views and conclusions contained in the software and documentation are those of the
25 * authors and should not be interpreted as representing official policies, either expressed
26 * or implied, of JogAmp Community.
27 */
28
29package com.jogamp.opengl.test.junit.math;
30
31import org.junit.Assert;
32import org.junit.Test;
33import org.junit.FixMethodOrder;
34import org.junit.runners.MethodSorters;
35
36import com.jogamp.common.os.Platform;
37import com.jogamp.junit.util.JunitTracer;
38import com.jogamp.math.FloatUtil;
39import com.jogamp.math.Matrix4f;
40
41@FixMethodOrder(MethodSorters.NAME_ASCENDING)
42public class TestMatrix4f03InversionNOUI extends JunitTracer {
43
44 @Test
45 public void test01Ident(){
46 final float[] res1 = new float[16];
47 final float[] res2 = new float[16];
48 final float[] temp = new float[16];
49
50 final float[] identity = new float[] { 1, 0, 0, 0,
51 0, 1, 0, 0,
52 0, 0, 1, 0,
53 0, 0, 0, 1 };
54
55 FloatUtil.invertMatrix(identity, res1);
56 // System.err.println(FloatUtil.matrixToString(null, "inv-1: ", "%10.7f", res1, 0, 4, 4, false /* rowMajorOrder */));
57 invertMatrix(identity, res2, temp);
58 // System.err.println(FloatUtil.matrixToString(null, "inv-2: ", "%10.7f", res2, 0, 4, 4, false /* rowMajorOrder */));
59
60 Assert.assertArrayEquals("I1/I2 failure", res1, res2, FloatUtil.INV_DEVIANCE);
61 Assert.assertArrayEquals("I2 failure", identity, res2, FloatUtil.INV_DEVIANCE);
62 Assert.assertArrayEquals("I1 failure", identity, res1, FloatUtil.INV_DEVIANCE);
63
64 final Matrix4f res3 = new Matrix4f(identity);
65 Assert.assertTrue( res3.invert() );
66 // System.err.println(res3.toString(null, "inv-4: ", "%10.7f"));
67 Assert.assertEquals(new Matrix4f(res1), res3);
68 Assert.assertEquals(new Matrix4f(), res3);
69
70 final Matrix4fb res4 = new Matrix4fb(identity);
71 Assert.assertTrue( res4.invert() );
72 // System.err.println(res4.toString(null, "inv-5: ", "%10.7f"));
73 Assert.assertEquals(new Matrix4fb(res1), res4);
74 Assert.assertEquals(new Matrix4fb(), res4);
75 }
76
77 private void testImpl(final float[] matrix) {
78 final float[] inv1_0 = new float[16];
79 final float[] inv1_1 = new float[16];
80 final float[] inv1_2 = new float[16];
81 final float[] inv2_0 = new float[16];
82 final float[] inv2_1 = new float[16];
83 final float[] inv2_2 = new float[16];
84 final float[] temp = new float[16];
85
86 // System.err.println(FloatUtil.matrixToString(null, "orig : ", "%10.7f", matrix, 0, 4, 4, false /* rowMajorOrder */));
87 invertMatrix(matrix, inv1_0, temp);
88 invertMatrix(inv1_0, inv2_0, temp);
89 // System.err.println(FloatUtil.matrixToString(null, "inv1_0: ", "%10.7f", inv1_0, 0, 4, 4, false /* rowMajorOrder */));
90 // System.err.println(FloatUtil.matrixToString(null, "inv2_0: ", "%10.7f", inv2_0, 0, 4, 4, false /* rowMajorOrder */));
91 FloatUtil.invertMatrix(matrix, inv1_1);
92 FloatUtil.invertMatrix(inv1_1, inv2_1);
93 // System.err.println(FloatUtil.matrixToString(null, "inv1_1: ", "%10.7f", inv1_1, 0, 4, 4, false /* rowMajorOrder */));
94 // System.err.println(FloatUtil.matrixToString(null, "inv2_1: ", "%10.7f", inv2_1, 0, 4, 4, false /* rowMajorOrder */));
95 FloatUtil.invertMatrix(matrix, inv1_2);
96 FloatUtil.invertMatrix(inv1_2, inv2_2);
97 // System.err.println(FloatUtil.matrixToString(null, "inv1_2: ", "%10.7f", inv1_2, 0, 4, 4, false /* rowMajorOrder */));
98 // System.err.println(FloatUtil.matrixToString(null, "inv2_2: ", "%10.7f", inv2_2, 0, 4, 4, false /* rowMajorOrder */));
99
100 Assert.assertArrayEquals("I1_1/I1_2 failure", inv1_1, inv1_2, FloatUtil.INV_DEVIANCE);
101 Assert.assertArrayEquals("I2_1/I2_2 failure", inv2_1, inv2_2, FloatUtil.INV_DEVIANCE);
102
103 Assert.assertArrayEquals("I1_0/I1_1 failure", inv1_0, inv1_2, FloatUtil.INV_DEVIANCE);
104 Assert.assertArrayEquals("I2_0/I2_1 failure", inv2_0, inv2_2, FloatUtil.INV_DEVIANCE);
105
106 Assert.assertArrayEquals("I1 failure", matrix, inv2_0, FloatUtil.INV_DEVIANCE);
107 Assert.assertArrayEquals("I2 failure", matrix, inv2_2, FloatUtil.INV_DEVIANCE);
108 Assert.assertArrayEquals("I2 failure", matrix, inv2_1, FloatUtil.INV_DEVIANCE);
109
110 //
111 // Matrix4f
112 //
113
114 final Matrix4f matrix_m = new Matrix4f(matrix);
115 final Matrix4f inv1_4a = new Matrix4f(matrix_m);
116 Assert.assertTrue( inv1_4a.invert() );
117 final Matrix4f inv2_4a = new Matrix4f(inv1_4a);
118 Assert.assertTrue( inv2_4a.invert() );
119 // System.err.println(inv1_4a.toString(null, "inv1_4a: ", "%10.7f"));
120 // System.err.println(inv2_4a.toString(null, "inv2_4a: ", "%10.7f"));
121
122 // Assert.assertEquals(new Matrix4f(inv1_2), inv1_4a);
123 // Assert.assertEquals(new Matrix4f(inv2_2), inv2_4a);
124 Assert.assertArrayEquals("I5 failure", inv1_2, inv1_4a.get(temp), FloatUtil.INV_DEVIANCE);
125 Assert.assertArrayEquals("I5 failure", inv2_2, inv2_4a.get(temp), FloatUtil.INV_DEVIANCE);
126 Assert.assertTrue("I4 failure: "+matrix_m+" != "+inv2_4a, matrix_m.isEqual(inv2_4a, FloatUtil.INV_DEVIANCE));
127
128 final Matrix4f inv1_4b = new Matrix4f();
129 Assert.assertTrue( inv1_4b.invert(matrix_m) );
130 final Matrix4f inv2_4b = new Matrix4f();
131 Assert.assertTrue( inv2_4b.invert(inv1_4b) );
132 // System.err.println(inv1_4b.toString(null, "inv1_4b: ", "%10.7f"));
133 // System.err.println(inv2_4b.toString(null, "inv2_4b: ", "%10.7f"));
134
135 // Assert.assertEquals(new Matrix4f(inv1_2), inv1_4b);
136 // Assert.assertEquals(new Matrix4f(inv2_2), inv2_4b);
137 Assert.assertArrayEquals("I5 failure", inv1_2, inv1_4b.get(temp), FloatUtil.INV_DEVIANCE);
138 Assert.assertArrayEquals("I5 failure", inv2_2, inv2_4b.get(temp), FloatUtil.INV_DEVIANCE);
139 Assert.assertTrue("I4 failure: "+matrix_m+" != "+inv2_4b, matrix_m.isEqual(inv2_4b, FloatUtil.INV_DEVIANCE));
140
141 //
142 // Matrix4fb
143 //
144
145 final Matrix4fb matrix_n = new Matrix4fb(matrix);
146 final Matrix4fb inv1_5a = new Matrix4fb(matrix_n);
147 Assert.assertTrue( inv1_5a.invert() );
148 final Matrix4fb inv2_5a = new Matrix4fb(inv1_5a);
149 Assert.assertTrue( inv2_5a.invert() );
150 // System.err.println(inv1_5a.toString(null, "inv1_5a: ", "%10.7f"));
151 // System.err.println(inv2_5a.toString(null, "inv2_5a: ", "%10.7f"));
152
153 // Assert.assertEquals(new Matrix4fb(inv1_2), inv1_5a);
154 // Assert.assertEquals(new Matrix4fb(inv2_2), inv2_5a);
155 Assert.assertArrayEquals("I5 failure", inv1_2, inv1_5a.get(temp), FloatUtil.INV_DEVIANCE);
156 Assert.assertArrayEquals("I5 failure", inv2_2, inv2_5a.get(temp), FloatUtil.INV_DEVIANCE);
157 Assert.assertTrue("I5 failure: "+matrix_n+" != "+inv2_5a, matrix_n.isEqual(inv2_5a, FloatUtil.INV_DEVIANCE));
158
159 final Matrix4fb inv1_5b = new Matrix4fb();
160 Assert.assertTrue( inv1_5b.invert(matrix_n) );
161 final Matrix4fb inv2_5b = new Matrix4fb();
162 Assert.assertTrue( inv2_5b.invert(inv1_5b) );
163 // System.err.println(inv1_5b.toString(null, "inv1_5b: ", "%10.7f"));
164 // System.err.println(inv2_5b.toString(null, "inv2_5b: ", "%10.7f"));
165
166 // Assert.assertEquals(new Matrix4fb(inv1_2), inv1_5b);
167 // Assert.assertEquals(new Matrix4fb(inv2_2), inv2_5b);
168 Assert.assertArrayEquals("I5 failure", inv1_2, inv1_5b.get(temp), FloatUtil.INV_DEVIANCE);
169 Assert.assertArrayEquals("I5 failure", inv2_2, inv2_5b.get(temp), FloatUtil.INV_DEVIANCE);
170 Assert.assertTrue("I5 failure: "+matrix_n+" != "+inv2_5b, matrix_n.isEqual(inv2_5b, FloatUtil.INV_DEVIANCE));
171 }
172
173 @Test
174 public void test02(){
175 final float[] p = new float[] { 2.3464675f, 0, 0, 0,
176 0, 2.4142134f, 0, 0,
177 0, 0, -1.0002f, -1,
178 0, 0, -20.002f, 0 };
179 testImpl(p);
180 }
181
182 @Test
183 public void test03(){
184 final float[] mv = new float[] {
185 1, 0, 0, 0,
186 0, 1, 0, 0,
187 0, 0, 1, 0,
188 0, 0, -200, 1 } ;
189 testImpl(mv);
190 }
191
192 @Test
193 public void test04(){
194 final float[] p = new float[] {
195 2.3464675f, 0, 0, 0,
196 0, 2.4142134f, 0, 0,
197 0, 0, -1.0002f, -1,
198 0, 0, -20.002f, 0 };
199
200 testImpl(p);
201 }
202
203 @Test
204 public void test05Perf01(){
205 final float[] p1 = new float[] {
206 2.3464675f, 0, 0, 0,
207 0, 2.4142134f, 0, 0,
208 0, 0, -1.0002f, -1,
209 0, 0, -20.002f, 0 };
210 final Matrix4f p1_m = new Matrix4f(p1);
211 final Matrix4fb p1_n = new Matrix4fb(p1);
212
213 final float[] p2 = new float[]{
214 26, 59, 143, 71,
215 59, 174, 730, 386,
216 143, 730, 9770, 5370,
217 71, 386, 5370, 2954 };
218 final Matrix4f p2_m = new Matrix4f(p2);
219 final Matrix4fb p2_n = new Matrix4fb(p2);
220
221 final float[] res = new float[16];
222 final float[] temp = new float[16];
223
224 final Matrix4f res_m = new Matrix4f();
225 final Matrix4fb res_n = new Matrix4fb();
226
227 final int warmups = 1000;
228 final int loops = 10*1000*1000;
229 long tI0 = 0;
230 long tI2 = 0;
231 long tI4a = 0;
232 long tI4b = 0;
233 long tI5a = 0;
234 long tI5b = 0;
235
236 // warm-up
237 for(int i=0; i<warmups; i++) {
238 invertMatrix(p1, res, temp);
239 }
240 long t_0 = Platform.currentTimeMillis();
241 for(int i=0; i<loops; i++) {
242 // I0: p1 -> res
243 invertMatrix(p1, res, temp);
244
245 // I0: p2 -> res
246 invertMatrix(p2, res, temp);
247 }
248 tI0 = Platform.currentTimeMillis() - t_0;
249
250 // warm-up
251 for(int i=0; i<warmups; i++) {
252 FloatUtil.invertMatrix(p1, res);
253 FloatUtil.invertMatrix(p2, res);
254 }
255 t_0 = Platform.currentTimeMillis();
256 for(int i=0; i<loops; i++) {
257 // I2: p1 -> res
258 FloatUtil.invertMatrix(p1, res);
259
260 // I2: p2 -> res
261 FloatUtil.invertMatrix(p2, res);
262 }
263 tI2 = Platform.currentTimeMillis() - t_0;
264
265 // avoid optimizing out unused computation results by simply adding up determinat
266 double dr = 1;
267
268 //
269 // Matrix4f
270 //
271
272 // warm-up
273 for(int i=0; i<warmups; i++) {
274 res_m.invert(p1_m);
275 dr += res_m.determinant();
276 res_m.invert(p2_m);
277 dr += res_m.determinant();
278 }
279 t_0 = Platform.currentTimeMillis();
280 for(int i=0; i<loops; i++) {
281 res_m.invert(p1_m);
282 dr += res_m.determinant();
283 res_m.invert(p2_m);
284 dr += res_m.determinant();
285 }
286 tI4a = Platform.currentTimeMillis() - t_0;
287
288 // warm-up
289 for(int i=0; i<warmups; i++) {
290 res_m.load(p1_m).invert();
291 dr += res_m.determinant();
292 res_m.load(p2_m).invert();
293 dr += res_m.determinant();
294 }
295 t_0 = Platform.currentTimeMillis();
296 for(int i=0; i<loops; i++) {
297 res_m.load(p1_m).invert();
298 dr += res_m.determinant();
299 res_m.load(p2_m).invert();
300 dr += res_m.determinant();
301 }
302 tI4b = Platform.currentTimeMillis() - t_0;
303
304 //
305 // Matrix4fb
306 //
307
308 // warm-up
309 for(int i=0; i<warmups; i++) {
310 res_n.invert(p1_n);
311 dr += res_n.determinant();
312 res_n.invert(p2_n);
313 dr += res_n.determinant();
314 }
315 t_0 = Platform.currentTimeMillis();
316 for(int i=0; i<loops; i++) {
317 res_n.invert(p1_n);
318 dr += res_n.determinant();
319 res_n.invert(p2_n);
320 dr += res_n.determinant();
321 }
322 tI5a = Platform.currentTimeMillis() - t_0;
323
324 // warm-up
325 for(int i=0; i<warmups; i++) {
326 res_n.load(p1_n).invert();
327 res_n.load(p2_n).invert();
328 }
329 t_0 = Platform.currentTimeMillis();
330 for(int i=0; i<loops; i++) {
331 res_n.load(p1_n).invert();
332 dr += res_n.determinant();
333 res_n.load(p2_n).invert();
334 dr += res_n.determinant();
335 }
336 tI5b = Platform.currentTimeMillis() - t_0;
337
338 System.err.printf("Checkmark %f%n", dr);
339 System.err.printf("Summary loops %6d: I0 %6d ms total, %f us/inv%n", loops, tI0, tI0*1e3/loops);
340 System.err.printf("Summary loops %6d: I2 %6d ms total, %f us/inv, I2 / I0 %f%%%n", loops, tI2, tI2*1e3/2.0/loops, tI2/(double)tI0*100.0);
341 System.err.printf("Summary loops %6d: I4a %6d ms total, %f us/inv, I4a / I2 %f%%%n", loops, tI4a, tI4a*1e3/2.0/loops, (double)tI4a/(double)tI2*100.0);
342 System.err.printf("Summary loops %6d: I4b %6d ms total, %f us/inv, I4b / I2 %f%%%n", loops, tI4b, tI4b*1e3/2.0/loops, (double)tI4b/(double)tI2*100.0);
343 System.err.printf("Summary loops %6d: I5a %6d ms total, %f us/inv, I5a / I2 %f%%%n", loops, tI5a, tI5a*1e3/2.0/loops, (double)tI5a/(double)tI2*100.0);
344 System.err.printf("Summary loops %6d: I5b %6d ms total, %f us/inv, I5b / I2 %f%%%n", loops, tI5b, tI5b*1e3/2.0/loops, (double)tI5b/(double)tI2*100.0);
345 }
346
347 public static float[] invertMatrix(final float[] msrc, final float[] mres, final float[/*4*4*/] temp) {
348 int i, j, k, swap;
349 float t;
350 for (i = 0; i < 4; i++) {
351 final int i4 = i*4;
352 for (j = 0; j < 4; j++) {
353 temp[i4+j] = msrc[i4+j];
354 }
355 }
357
358 for (i = 0; i < 4; i++) {
359 final int i4 = i*4;
360
361 //
362 // Look for largest element in column
363 //
364 swap = i;
365 for (j = i + 1; j < 4; j++) {
366 if (Math.abs(temp[j*4+i]) > Math.abs(temp[i4+i])) {
367 swap = j;
368 }
369 }
370
371 if (swap != i) {
372 final int swap4 = swap*4;
373 //
374 // Swap rows.
375 //
376 for (k = 0; k < 4; k++) {
377 t = temp[i4+k];
378 temp[i4+k] = temp[swap4+k];
379 temp[swap4+k] = t;
380
381 t = mres[i4+k];
382 mres[i4+k] = mres[swap4+k];
383 mres[swap4+k] = t;
384 }
385 }
386
387 if (temp[i4+i] == 0) {
388 //
389 // No non-zero pivot. The matrix is singular, which shouldn't
390 // happen. This means the user gave us a bad matrix.
391 //
392 return null;
393 }
394
395 t = temp[i4+i];
396 for (k = 0; k < 4; k++) {
397 temp[i4+k] /= t;
398 mres[i4+k] /= t;
399 }
400 for (j = 0; j < 4; j++) {
401 if (j != i) {
402 final int j4 = j*4;
403 t = temp[j4+i];
404 for (k = 0; k < 4; k++) {
405 temp[j4+k] -= temp[i4+k] * t;
406 mres[j4+k] -= mres[i4+k]*t;
407 }
408 }
409 }
410 }
411 return mres;
412 }
413
414 public static void main(final String args[]) {
415 org.junit.runner.JUnitCore.main(TestMatrix4f03InversionNOUI.class.getName());
416 }
417}
Basic Float math utility functions.
Definition: FloatUtil.java:83
static final float INV_DEVIANCE
Inversion Epsilon, used with equals method to determine if two inverted matrices are close enough to ...
static float[] invertMatrix(final float[] msrc, final float[] mres)
Invert the given matrix.
Definition: FloatUtil.java:512
static float[] makeIdentity(final float[] m)
Make matrix an identity matrix.
Definition: FloatUtil.java:96
Basic 4x4 float matrix implementation using fields for intensive use-cases (host operations).
Definition: Matrix4f.java:89
boolean isEqual(final Matrix4f o, final float epsilon)
Equals check using a given FloatUtil#EPSILON value and FloatUtil#isEqual(float, float,...
Definition: Matrix4f.java:1631
Matrix4f load(final Matrix4f src)
Load the values of the given matrix src to this matrix.
Definition: Matrix4f.java:186
boolean invert()
Invert this matrix.
Definition: Matrix4f.java:530
float determinant()
Returns the determinant of this matrix.
Definition: Matrix4f.java:450
float get(final int i)
Gets the ith component, 0 <= i < 16.
Definition: Matrix4f.java:279
Basic 4x4 float matrix implementation using fields for intensive use-cases (host operations).
Definition: Matrix4fb.java:97
boolean invert()
Invert this matrix.
Definition: Matrix4fb.java:388
float determinant()
Returns the determinant of this matrix.
Definition: Matrix4fb.java:308
float get(final int i)
Gets the ith component, 0 <= i < 16.
Definition: Matrix4fb.java:204
boolean isEqual(final Matrix4fb o, final float epsilon)
Equals check using a given FloatUtil#EPSILON value and FloatUtil#isEqual(float, float,...
Matrix4fb load(final Matrix4fb src)
Load the values of the given matrix b to this matrix.
Definition: Matrix4fb.java:159
static float[] invertMatrix(final float[] msrc, final float[] mres, final float[] temp)