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 
29 package com.jogamp.opengl.test.junit.jogl.math;
30 
31 import org.junit.Assert;
32 import org.junit.Test;
33 import org.junit.FixMethodOrder;
34 import org.junit.runners.MethodSorters;
35 
36 import com.jogamp.common.os.Platform;
37 import com.jogamp.opengl.math.FloatUtil;
38 
39 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
40 public class TestFloatUtil03InversionNOUI {
41 
42     @Test
test01Ident()43     public void test01Ident(){
44         final float[] res1 = new float[16];
45         final float[] res2 = new float[16];
46         final float[] temp = new float[16];
47 
48         final float[] identity = new float[] { 1, 0, 0, 0,
49                                                0, 1, 0, 0,
50                                                0, 0, 1, 0,
51                                                0, 0, 0, 1 };
52 
53         FloatUtil.invertMatrix(identity, 0, res1, 0);
54         System.err.println(FloatUtil.matrixToString(null, "inv-1: ", "%10.7f", res1, 0, 4, 4, false /* rowMajorOrder */));
55         invertMatrix(identity, 0, res2, 0, temp);
56         System.err.println(FloatUtil.matrixToString(null, "inv-2: ", "%10.7f", res2, 0, 4, 4, false /* rowMajorOrder */));
57 
58         Assert.assertArrayEquals("I1/I2 failure", res1, res2, FloatUtil.INV_DEVIANCE);
59         Assert.assertArrayEquals("I2 failure", identity, res2, FloatUtil.INV_DEVIANCE);
60         Assert.assertArrayEquals("I1 failure", identity, res1, FloatUtil.INV_DEVIANCE);
61     }
62 
testImpl(final float[] matrix)63     private void testImpl(final float[] matrix) {
64         final float[] inv1_0 = new float[16];
65         final float[] inv1_1 = new float[16];
66         final float[] inv1_2 = new float[16];
67         final float[] inv2_0 = new float[16];
68         final float[] inv2_1 = new float[16];
69         final float[] inv2_2 = new float[16];
70         final float[] temp = new float[16];
71 
72         System.err.println(FloatUtil.matrixToString(null, "orig  : ", "%10.7f", matrix, 0, 4, 4, false /* rowMajorOrder */));
73         invertMatrix(matrix, 0, inv1_0, 0, temp);
74         invertMatrix(inv1_0, 0, inv2_0, 0, temp);
75         System.err.println(FloatUtil.matrixToString(null, "inv1_0: ", "%10.7f", inv1_0, 0, 4, 4, false /* rowMajorOrder */));
76         System.err.println(FloatUtil.matrixToString(null, "inv2_0: ", "%10.7f", inv2_0, 0, 4, 4, false /* rowMajorOrder */));
77         FloatUtil.invertMatrix(matrix, 0, inv1_1, 0);
78         FloatUtil.invertMatrix(inv1_1, 0, inv2_1, 0);
79         System.err.println(FloatUtil.matrixToString(null, "inv1_1: ", "%10.7f", inv1_1, 0, 4, 4, false /* rowMajorOrder */));
80         System.err.println(FloatUtil.matrixToString(null, "inv2_1: ", "%10.7f", inv2_1, 0, 4, 4, false /* rowMajorOrder */));
81         FloatUtil.invertMatrix(matrix, inv1_2);
82         FloatUtil.invertMatrix(inv1_2, inv2_2);
83         System.err.println(FloatUtil.matrixToString(null, "inv1_2: ", "%10.7f", inv1_2, 0, 4, 4, false /* rowMajorOrder */));
84         System.err.println(FloatUtil.matrixToString(null, "inv2_2: ", "%10.7f", inv2_2, 0, 4, 4, false /* rowMajorOrder */));
85 
86         Assert.assertArrayEquals("I1_1/I1_2 failure", inv1_1, inv1_2, FloatUtil.INV_DEVIANCE);
87         Assert.assertArrayEquals("I2_1/I2_2 failure", inv2_1, inv2_2, FloatUtil.INV_DEVIANCE);
88 
89         Assert.assertArrayEquals("I1_0/I1_1 failure", inv1_0, inv1_2, FloatUtil.INV_DEVIANCE);
90         Assert.assertArrayEquals("I2_0/I2_1 failure", inv2_0, inv2_2, FloatUtil.INV_DEVIANCE);
91 
92         Assert.assertArrayEquals("I1 failure", matrix, inv2_0, FloatUtil.INV_DEVIANCE);
93         Assert.assertArrayEquals("I2 failure", matrix, inv2_2, FloatUtil.INV_DEVIANCE);
94         Assert.assertArrayEquals("I2 failure", matrix, inv2_1, FloatUtil.INV_DEVIANCE);
95     }
96 
97     @Test
test02()98     public void test02(){
99         final float[] p = new float[] { 2.3464675f, 0,          0,        0,
100                                   0,          2.4142134f, 0,        0,
101                                   0,          0,         -1.0002f, -1,
102                                   0,          0,        -20.002f,   0 };
103         testImpl(p);
104     }
105 
106     @Test
test03()107     public void test03(){
108         final float[] mv = new float[] { 1, 0,    0, 0,
109                                    0, 1,    0, 0,
110                                    0, 0,    1, 0,
111                                    0, 0, -200, 1 } ;
112         testImpl(mv);
113     }
114 
115     @Test
test04()116     public void test04(){
117         final float[] p = new float[] { 2.3464675f, 0,          0,        0,
118                                   0,          2.4142134f, 0,        0,
119                                   0,          0,         -1.0002f, -1,
120                                   0,          0,        -20.002f,   0 };
121 
122         testImpl(p);
123     }
124 
125     @Test
test05Perf()126     public void test05Perf(){
127         final float[] p1 = new float[] { 2.3464675f, 0,          0,        0,
128                                    0,          2.4142134f, 0,        0,
129                                    0,          0,         -1.0002f, -1,
130                                    0,          0,        -20.002f,   0 };
131 
132         final float[] p2 = new float[]{   26,   59,  143,   71,
133                                     59,  174,  730,  386,
134                                    143,  730, 9770, 5370,
135                                     71,  386, 5370, 2954 };
136 
137         final float[] res1 = new float[16];
138         final float[] res2 = new float[16];
139         final float[] temp = new float[16];
140 
141         final int loops = 1000000;
142         long tI0 = 0;
143         long tI1 = 0;
144         long tI2 = 0;
145 
146         // warm-up
147         for(int i=0; i<10; i++) {
148             invertMatrix(p1, 0, res2, 0, temp);
149             FloatUtil.invertMatrix(p1, 0, res1, 0);
150             FloatUtil.invertMatrix(p1, res1);
151 
152             invertMatrix(p2, 0, res2, 0, temp);
153             FloatUtil.invertMatrix(p2, 0, res1, 0);
154             FloatUtil.invertMatrix(p2, res1);
155         }
156 
157 
158         for(int i=0; i<loops; i++) {
159 
160             final long t_0 = Platform.currentTimeMillis();
161 
162             invertMatrix(p1, 0, res2, 0, temp);
163             final long t_1 = Platform.currentTimeMillis();
164             tI0 += t_1 - t_0;
165 
166             FloatUtil.invertMatrix(p1, 0, res1, 0);
167             final long t_2 = Platform.currentTimeMillis();
168             tI1 += t_2 - t_1;
169 
170             FloatUtil.invertMatrix(p1, res1);
171             final long t_3 = Platform.currentTimeMillis();
172             tI2 += t_3 - t_2;
173 
174             invertMatrix(p2, 0, res2, 0, temp);
175             final long t_4 = Platform.currentTimeMillis();
176             tI0 += t_4 - t_3;
177 
178             FloatUtil.invertMatrix(p2, 0, res1, 0);
179             final long t_5 = Platform.currentTimeMillis();
180             tI1 += t_5 - t_4;
181 
182             FloatUtil.invertMatrix(p2, res2);
183             final long t_6 = Platform.currentTimeMillis();
184             tI2 += t_6 - t_5;
185         }
186         System.err.printf("Summary loops %6d: I1 %6d ms total, %f ms/inv%n", loops, tI0, (double)tI0/loops);
187         System.err.printf("Summary loops %6d: I2 %6d ms total, %f ms/inv%n", loops, tI1, (double)tI1/loops);
188         System.err.printf("Summary loops %6d: I3 %6d ms total, %f ms/inv%n", loops, tI2, (double)tI2/loops);
189 
190     }
191 
invertMatrix(final float[] msrc, final int msrc_offset, final float[] mres, final int mres_offset, final float[ ] temp)192     public static float[] invertMatrix(final float[] msrc, final int msrc_offset, final float[] mres, final int mres_offset, final float[/*4*4*/] temp) {
193         int i, j, k, swap;
194         float t;
195         for (i = 0; i < 4; i++) {
196             final int i4 = i*4;
197             for (j = 0; j < 4; j++) {
198                 temp[i4+j] = msrc[i4+j+msrc_offset];
199             }
200         }
201         FloatUtil.makeIdentity(mres, mres_offset);
202 
203         for (i = 0; i < 4; i++) {
204             final int i4 = i*4;
205 
206             //
207             // Look for largest element in column
208             //
209             swap = i;
210             for (j = i + 1; j < 4; j++) {
211                 if (Math.abs(temp[j*4+i]) > Math.abs(temp[i4+i])) {
212                     swap = j;
213                 }
214             }
215 
216             if (swap != i) {
217                 final int swap4 = swap*4;
218                 //
219                 // Swap rows.
220                 //
221                 for (k = 0; k < 4; k++) {
222                     t = temp[i4+k];
223                     temp[i4+k] = temp[swap4+k];
224                     temp[swap4+k] = t;
225 
226                     t = mres[i4+k+mres_offset];
227                     mres[i4+k+mres_offset] = mres[swap4+k+mres_offset];
228                     mres[swap4+k+mres_offset] = t;
229                 }
230             }
231 
232             if (temp[i4+i] == 0) {
233                 //
234                 // No non-zero pivot. The matrix is singular, which shouldn't
235                 // happen. This means the user gave us a bad matrix.
236                 //
237                 return null;
238             }
239 
240             t = temp[i4+i];
241             for (k = 0; k < 4; k++) {
242                 temp[i4+k] /= t;
243                 mres[i4+k+mres_offset] /= t;
244             }
245             for (j = 0; j < 4; j++) {
246                 if (j != i) {
247                     final int j4 = j*4;
248                     t = temp[j4+i];
249                     for (k = 0; k < 4; k++) {
250                         temp[j4+k] -= temp[i4+k] * t;
251                         mres[j4+k+mres_offset] -= mres[i4+k+mres_offset]*t;
252                     }
253                 }
254             }
255         }
256         return mres;
257     }
258 
main(final String args[])259     public static void main(final String args[]) {
260         org.junit.runner.JUnitCore.main(TestFloatUtil03InversionNOUI.class.getName());
261     }
262 }
263