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