/* * $Id$ * This file is a part of the Arakhne Foundation Classes, http://www.arakhne.org/afc * * Copyright (c) 2000-2012 Stephane GALLAND. * Copyright (c) 2005-10, Multiagent Team, Laboratoire Systemes et Transports, * Universite de Technologie de Belfort-Montbeliard. * Copyright (c) 2013-2016 The original authors, and other authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.arakhne.afc.math.matrix; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import org.junit.Rule; import org.junit.Test; import org.arakhne.afc.math.AbstractMathTestCase; import org.arakhne.afc.math.geometry.coordinatesystem.CoordinateSystem2DTestRule; import org.arakhne.afc.math.geometry.d2.d.Point2d; import org.arakhne.afc.math.geometry.d2.d.Vector2d; @SuppressWarnings("all") public class Matrix2dTest extends AbstractMathTestCase { @Rule public CoordinateSystem2DTestRule csTestRule = new CoordinateSystem2DTestRule(); @Test public void setIdentity() { Matrix2d matrix = this.randomMatrix2f(); matrix.setIdentity(); assertEpsilonEquals(new Matrix2d(1,0,0,1), matrix); } @Test public void addDouble() { Matrix2d m1 = this.randomMatrix2f(); Matrix2d m2 = m1.clone(); double s = getRandom().nextDouble(); m2.set(m2.m00+s, m2.m01+s, m2.m10+s, m2.m11+s); m1.add(s); assertEpsilonEquals(m2, m1); } @Test public void addDoubleMatrix2D() { Matrix2d m1 = this.randomMatrix2f(); Matrix2d m2 = m1.clone(); double s = getRandom().nextDouble(); m2.set(m2.m00+s, m2.m01+s, m2.m10+s, m2.m11+s); m1.add(s,m1); assertEpsilonEquals(m2, m1); } @Test public void addMatrix2DMatrix2D() { Matrix2d m1 = this.randomMatrix2f(); Matrix2d m2 = this.randomMatrix2f(); Matrix2d m3 = new Matrix2d(); m3.set(m1.m00+m2.m00, m1.m01+m2.m01, m1.m10+m2.m10, m1.m11+m2.m11); m1.add(m1,m2); assertEpsilonEquals(m3, m1); } @Test public void addMatrix2D() { Matrix2d m1 = this.randomMatrix2f(); Matrix2d m2 = this.randomMatrix2f(); Matrix2d m3 = new Matrix2d(); m3.set(m1.m00+m2.m00, m1.m01+m2.m01, m1.m10+m2.m10, m1.m11+m2.m11); m1.add(m2); assertEpsilonEquals(m3, m1); } @Test public void subMatrix2DMatrix2D() { Matrix2d m1 = this.randomMatrix2f(); Matrix2d m2 = this.randomMatrix2f(); Matrix2d m3 = new Matrix2d(); m3.set(m1.m00-m2.m00, m1.m01-m2.m01, m1.m10-m2.m10, m1.m11-m2.m11); m1.sub(m1,m2); assertEpsilonEquals(m3, m1); } @Test public void subMatrix2D() { Matrix2d m1 = this.randomMatrix2f(); Matrix2d m2 = this.randomMatrix2f(); Matrix2d m3 = new Matrix2d(); m3.set(m1.m00-m2.m00, m1.m01-m2.m01, m1.m10-m2.m10, m1.m11-m2.m11); m1.sub(m2); assertEpsilonEquals(m3, m1); } @Test public void transpose() { Matrix2d m1 = this.randomMatrix2f(); Matrix2d transpose = new Matrix2d(); double [] v = new double[3]; m1.getRow(0, v); transpose.setColumn(0, v); m1.getRow(1, v); transpose.setColumn(1, v); m1.transpose(); assertEpsilonEquals(transpose,m1); } @Test public void transposeMatrix2D() { Matrix2d m1 = this.randomMatrix2f(); Matrix2d transpose = new Matrix2d(); double [] v = new double[3]; m1.getRow(0, v); transpose.setColumn(0, v); m1.getRow(1, v); transpose.setColumn(1, v); m1.transpose(m1); assertEpsilonEquals(transpose, m1); } @Test public void determinant() { double a = getRandom().nextDouble(); double b = getRandom().nextDouble(); double c = getRandom().nextDouble(); double d = getRandom().nextDouble(); Matrix2d matrix = new Matrix2d(a,b,c,d); double determinant = a*d-c*b; assertEpsilonEquals(determinant, matrix.determinant()); } @Test public void mulDouble() { double a = getRandom().nextDouble(); double b = getRandom().nextDouble(); double c = getRandom().nextDouble(); double d = getRandom().nextDouble(); Matrix2d matrix = new Matrix2d(a,b,c,d); double s = getRandom().nextDouble(); Matrix2d prodScal = new Matrix2d(a*s,b*s,c*s,d*s); matrix.mul(s); assertEpsilonEquals(prodScal, matrix); } @Test public void mulDoubleMatrix2D() { double a = getRandom().nextDouble(); double b = getRandom().nextDouble(); double c = getRandom().nextDouble(); double d = getRandom().nextDouble(); Matrix2d matrix = new Matrix2d(a,b,c,d); double s = getRandom().nextDouble(); Matrix2d prodScal = new Matrix2d(a*s,b*s,c*s,d*s); matrix.mul(s,matrix); assertEpsilonEquals(prodScal, matrix); } @Test public void mulMatrix2D() { double a = getRandom().nextDouble(); double b = getRandom().nextDouble(); double c = getRandom().nextDouble(); double d = getRandom().nextDouble(); //double i = getRandom().nextDouble(); Matrix2d m1 = new Matrix2d(a,b,c,d); double e = getRandom().nextDouble(); double f = getRandom().nextDouble(); double g = getRandom().nextDouble(); double h = getRandom().nextDouble(); Matrix2d m2= new Matrix2d(e,f,g,h); Matrix2d prod = new Matrix2d( a*e+b*g, a*f+b*h, c*e+d*g, c*f+d*h); m1.mul(m2); assertEpsilonEquals(prod, m1); } @Test public void mulVector2D() { Vector2d vector = this.randomVector2f(); Matrix2d matrix = new Matrix2d(1,2,4,-1); Vector2d product = new Vector2d(vector.getX()+2*vector.getY(),4*vector.getX()-vector.getY()); Vector2d result = new Vector2d(); matrix.mul(vector, result); assertEpsilonEquals(product, result); } @Test public void mulMatrix2DMatrix2D() { double a = getRandom().nextDouble(); double b = getRandom().nextDouble(); double c = getRandom().nextDouble(); double d = getRandom().nextDouble(); //double i = getRandom().nextDouble(); Matrix2d m1 = new Matrix2d(a,b,c,d); double e = getRandom().nextDouble(); double f = getRandom().nextDouble(); double g = getRandom().nextDouble(); double h = getRandom().nextDouble(); Matrix2d m2= new Matrix2d(e,f,g,h); Matrix2d prod = new Matrix2d( a*e+b*g, a*f+b*h, c*e+d*g, c*f+d*h); m1.mul(m1,m2); assertEpsilonEquals(prod, m1); } @Test public void mulTransposeBoth() { Matrix2d m1 = this.randomMatrix2f(); Matrix2d m2 = this.randomMatrix2f(); Matrix2d multrans = new Matrix2d(); multrans.mulTransposeBoth(m1, m2); m1.transpose(); m2.transpose(); m1.mul(m2); assertEpsilonEquals(multrans, m1); } @Test public void mulTransposeRight() { Matrix2d m1 = this.randomMatrix2f(); Matrix2d m2 = this.randomMatrix2f(); Matrix2d multrans = new Matrix2d(); multrans.mulTransposeRight(m1, m2); //m1.transpose(); m2.transpose(); m1.mul(m2); assertEpsilonEquals(multrans, m1); } @Test public void mulTransposeLeft() { Matrix2d m1 = this.randomMatrix2f(); Matrix2d m2 = this.randomMatrix2f(); Matrix2d multrans = new Matrix2d(); multrans.mulTransposeLeft(m1, m2); m1.transpose(); //m2.transpose(); m1.mul(m2); assertEpsilonEquals(multrans, m1); } @Test public void normalizeCP_zero() { Matrix2d m = new Matrix2d(); m.normalizeCP(); assertNaN(m.getM00()); assertNaN(m.getM01()); assertNaN(m.getM10()); assertNaN(m.getM10()); } @Test public void normalizeCP_identity() { Matrix2d m = new Matrix2d(); m.setIdentity(); m.normalizeCP(); assertEpsilonEquals(1, m.getM00()); assertEpsilonEquals(0, m.getM01()); assertEpsilonEquals(0, m.getM10()); assertEpsilonEquals(1, m.getM11()); } @Test public void normalizeCP_std() { Matrix2d m = new Matrix2d(1, 2, 3, 4); m.normalizeCP(); assertEpsilonEquals(1/Math.sqrt(10), m.getM00()); assertEpsilonEquals(2/Math.sqrt(20), m.getM01()); assertEpsilonEquals(3/Math.sqrt(10), m.getM10()); assertEpsilonEquals(4/Math.sqrt(20), m.getM11()); } @Test public void normalizeCPMatrix2D_zero() { Matrix2d m = new Matrix2d(); Matrix2d r = new Matrix2d(); r.normalizeCP(m); assertNaN(r.getM00()); assertNaN(r.getM01()); assertNaN(r.getM00()); assertNaN(r.getM01()); } @Test public void normalizeCPMatrix2D_identity() { Matrix2d m = new Matrix2d(); m.setIdentity(); Matrix2d r = new Matrix2d(); r.normalizeCP(m); assertEpsilonEquals(1, r.getM00()); assertEpsilonEquals(0, r.getM01()); assertEpsilonEquals(0, r.getM10()); assertEpsilonEquals(1, r.getM11()); } @Test public void normalizeCPMatrix2D_std() { Matrix2d m = new Matrix2d(1, 2, 3, 4); Matrix2d r = new Matrix2d(); r.normalizeCP(m); assertEpsilonEquals(1/Math.sqrt(10), r.getM00()); assertEpsilonEquals(2/Math.sqrt(20), r.getM01()); assertEpsilonEquals(3/Math.sqrt(10), r.getM10()); assertEpsilonEquals(4/Math.sqrt(20), r.getM11()); } @Test public void setZero() { Matrix2d m = this.randomMatrix2f(); m.setZero(); assertEpsilonEquals(new Matrix2d(0,0,0,0), m); } @Test public void setDiagonal() { Matrix2d m = this.randomMatrix2f(); double s = getRandom().nextDouble(); m.setDiagonal(s,s); assertEpsilonEquals(new Matrix2d(s,0,0,s), m); } @Test public void negate() { Matrix2d m1 = this.randomMatrix2f(); Matrix2d m2 = m1.clone(); Matrix2d temp = new Matrix2d(); Matrix2d temp2 = new Matrix2d(); m1.negate(); temp.add(m1, m2); assertEpsilonEquals(new Matrix2d(0,0,0,0), temp); temp.mul(m1, m2); m2.negate(); assertEpsilonEquals(m1, m2); m1.negate(); temp2.mul(m1, m2); assertEpsilonEquals(temp, temp2); } @Test public void negateMatrix2D() { Matrix2d m1 = this.randomMatrix2f(); Matrix2d m2 = m1.clone(); Matrix2d temp = new Matrix2d(); Matrix2d temp2 = new Matrix2d(); m1.negate(m1); temp.add(m1, m2); assertEpsilonEquals(new Matrix2d(0,0,0,0), temp); temp.mul(m1, m2); m2.negate(m2); assertEpsilonEquals(m1, m2); m1.negate(m1); temp2.mul(m1, m2); assertEpsilonEquals(temp, temp2); } @Test public void cloneTest() { Matrix2d m = this.randomMatrix2f(); Matrix2d m2 = m.clone(); assertEpsilonEquals(m, m2); } @Test public void isSymmetric() { Matrix2d m = this.randomMatrix2f(); boolean b = m.m01==m.m10; assertEquals(b, m.isSymmetric()); m.setZero(); assertTrue(m.isSymmetric()); m.setIdentity(); assertTrue(m.isSymmetric()); m.set(1, 1, 2, 2); assertFalse(m.isSymmetric()); } @Test public void eigenVectorsOfSymmetricMatrix_zero() { Matrix2d m = new Matrix2d(); Matrix2d eigenVectors = new Matrix2d(); double[] eigenValues = m.eigenVectorsOfSymmetricMatrix(eigenVectors); assertEpsilonEquals(0, eigenValues[0]); assertEpsilonEquals(0, eigenValues[1]); Vector2d vector1 = new Vector2d(); Vector2d vector2 = new Vector2d(); eigenVectors.getColumn(0, vector1); eigenVectors.getColumn(1, vector2); assertFpVectorEquals(1, 0, vector1); assertFpVectorEquals(0, 1, vector2); } @Test public void eigenVectorsOfSymmetricMatrix_identity() { Matrix2d m = new Matrix2d(); m.setIdentity(); Matrix2d eigenVectors = new Matrix2d(); double[] eigenValues = m.eigenVectorsOfSymmetricMatrix(eigenVectors); assertEpsilonEquals(1, eigenValues[0]); assertEpsilonEquals(1, eigenValues[1]); Vector2d vector1 = new Vector2d(); Vector2d vector2 = new Vector2d(); eigenVectors.getColumn(0, vector1); eigenVectors.getColumn(1, vector2); assertFpVectorEquals(1, 0, vector1); assertFpVectorEquals(0, 1, vector2); } @Test public void eigenVectorsOfSymmetricMatrix_sym() { Matrix2d m = new Matrix2d(1, 5, 5, 2); Matrix2d eigenVectors = new Matrix2d(); double[] eigenValues = m.eigenVectorsOfSymmetricMatrix(eigenVectors); assertEpsilonEquals(-3.5249, eigenValues[0]); assertEpsilonEquals(6.5249, eigenValues[1]); Vector2d vector1 = new Vector2d(); Vector2d vector2 = new Vector2d(); eigenVectors.getColumn(0, vector1); eigenVectors.getColumn(1, vector2); assertFpVectorEquals(0.74145, -0.67101, vector1); assertFpVectorEquals(0.67101, 0.74145, vector2); } @Test public void isIdentity() { Matrix2d m = this.randomMatrix2f(); boolean b = m.m00==1 && m.m01==0 && m.m10==0 && m.m11==1; assertTrue(b==m.isIdentity()); m.setIdentity(); assertTrue(m.isIdentity()); m.setZero(); assertFalse(m.isIdentity()); m.set(1, 1, 2, 2); assertFalse(m.isIdentity()); } @Test public void covMatrix2Tuple2dArray_theory() { Vector2d v1 = new Vector2d(1, 3); Vector2d v2 = new Vector2d(4, -2); Vector2d m = new Vector2d(); m.add(v1,v2); m.scale(.5f); Matrix2d expected = new Matrix2d(); expected.m00 = ((v1.getX()-m.getX()) * (v1.getX()-m.getX()) + (v2.getX()-m.getX()) * (v2.getX()-m.getX())) / 2f; expected.m01 = ((v1.getX()-m.getX()) * (v1.getY()-m.getY()) + (v2.getX()-m.getX()) * (v2.getY()-m.getY())) / 2f; expected.m10 = ((v1.getY()-m.getY()) * (v1.getX()-m.getX()) + (v2.getY()-m.getY()) * (v2.getX()-m.getX())) / 2f; expected.m11 = ((v1.getY()-m.getY()) * (v1.getY()-m.getY()) + (v2.getY()-m.getY()) * (v2.getY()-m.getY())) / 2f; Matrix2d mat = new Matrix2d(); Vector2d mean = new Vector2d(); mat.cov(mean, v1, v2); assertEpsilonEquals(m, mean); for(int i=0; i<2; ++i) { for(int j=0; j<2; ++j) { assertEpsilonEquals("i="+i+"; j="+j, //$NON-NLS-1$ //$NON-NLS-2$ expected.getElement(i, j), mat.getElement(i, j)); } } } /** */ @Test public void covMatrix2Tuple2dArray_example() { // From "Mathematics for 3D Game Programming and Computer Graphics" pp.220 // Adapted to 2D by Stephane Galland // // P1 = [ -1, -2 ] // P2 = [ 1, 0 ] // P3 = [ 2, -1 ] // P4 = [ 2, -1 ] // // average: m = [ 1, -1 ] // // Cov = [ 1.5 , .5 ] // [ .5 , .5 ] Point2d p1 = new Point2d(-1, -2); Point2d p2 = new Point2d(1, 0); Point2d p3 = new Point2d(2, -1); Point2d p4 = new Point2d(2, -1); Matrix2d cov = new Matrix2d(); Vector2d mean = new Vector2d(); cov.cov(mean, p1, p2, p3, p4); Point2d expectedMean = new Point2d(1, -1); Matrix2d expectedCov = new Matrix2d(); expectedCov.m00 = 1.5f; expectedCov.m01 = .5f; expectedCov.m10 = .5f; expectedCov.m11 = .5f; assertEpsilonEquals(expectedMean, mean); for(int i=0; i<2; ++i) { for(int j=0; j<2; ++j) { assertEpsilonEquals("i="+i+"; j="+j, //$NON-NLS-1$ //$NON-NLS-2$ expectedCov.getElement(i, j), cov.getElement(i, j)); } } } @Test public void operator_addMatrix2f() { Matrix2d m1 = this.randomMatrix2f(); Matrix2d m2 = this.randomMatrix2f(); Matrix2d m3 = new Matrix2d(); m3.set(m1.m00+m2.m00, m1.m01+m2.m01, m1.m10+m2.m10, m1.m11+m2.m11); m1.operator_add(m2); assertEpsilonEquals(m3, m1); } @Test public void operator_addDouble() { Matrix2d m1 = this.randomMatrix2f(); Matrix2d m2 = m1.clone(); double s = getRandom().nextDouble() * 100; m2.set(m2.m00+s, m2.m01+s, m2.m10+s, m2.m11+s); m1.operator_add(s); assertEpsilonEquals(m2, m1); } @Test public void operator_removeMatrix2f() { Matrix2d m1 = this.randomMatrix2f(); Matrix2d m2 = this.randomMatrix2f(); Matrix2d m3 = new Matrix2d(); m3.set(m1.m00-m2.m00, m1.m01-m2.m01, m1.m10-m2.m10, m1.m11-m2.m11); m1.operator_remove(m2); assertEpsilonEquals(m3, m1); } @Test public void operator_removeDouble() { Matrix2d m1 = this.randomMatrix2f(); Matrix2d m2 = m1.clone(); double s = getRandom().nextDouble() * 100; m2.set(m2.m00-s, m2.m01-s, m2.m10-s, m2.m11-s); m1.operator_remove(s); assertEpsilonEquals(m2, m1); } @Test public void operator_plusMatrix2f() { Matrix2d m1 = this.randomMatrix2f(); Matrix2d m2 = this.randomMatrix2f(); Matrix2d m3 = new Matrix2d(); m3.set(m1.m00+m2.m00, m1.m01+m2.m01, m1.m10+m2.m10, m1.m11+m2.m11); Matrix2d r = m1.operator_plus(m2); assertEpsilonEquals(m3, r); } @Test public void operator_plusDouble() { Matrix2d m1 = this.randomMatrix2f(); Matrix2d m2 = m1.clone(); double s = getRandom().nextDouble() * 100; m2.set(m2.m00+s, m2.m01+s, m2.m10+s, m2.m11+s); Matrix2d r = m1.operator_plus(s); assertEpsilonEquals(m2, r); } @Test public void operator_minusMatrix2f() { Matrix2d m1 = this.randomMatrix2f(); Matrix2d m2 = this.randomMatrix2f(); Matrix2d m3 = new Matrix2d(); m3.set(m1.m00-m2.m00, m1.m01-m2.m01, m1.m10-m2.m10, m1.m11-m2.m11); Matrix2d r = m1.operator_minus(m2); assertEpsilonEquals(m3, r); } @Test public void operator_minusDouble() { Matrix2d m1 = this.randomMatrix2f(); Matrix2d m2 = m1.clone(); double s = getRandom().nextDouble() * 100; m2.set(m2.m00-s, m2.m01-s, m2.m10-s, m2.m11-s); Matrix2d r = m1.operator_minus(s); assertEpsilonEquals(m2, r); } @Test public void operator_minus() { Matrix2d m1 = this.randomMatrix2f(); Matrix2d m2 = m1.clone(); m2.set(-m2.m00, -m2.m01, -m2.m10, -m2.m11); Matrix2d r = m1.operator_minus(); assertEpsilonEquals(m2, r); } @Test public void operator_multiplyMatrix2f() { double a = getRandom().nextDouble() * 100; double b = getRandom().nextDouble() * 100; double c = getRandom().nextDouble() * 100; double d = getRandom().nextDouble() * 100; //double i = getRandom().nextDouble(); Matrix2d m1 = new Matrix2d(a,b,c,d); double e = getRandom().nextDouble() * 100; double f = getRandom().nextDouble() * 100; double g = getRandom().nextDouble() * 100; double h = getRandom().nextDouble() * 100; Matrix2d m2= new Matrix2d(e,f,g,h); Matrix2d prod = new Matrix2d( a*e+b*g, a*f+b*h, c*e+d*g, c*f+d*h); Matrix2d r = m1.operator_multiply(m2); assertEpsilonEquals(prod, r); } @Test public void operator_multiplyDouble() { double a = getRandom().nextDouble() * 100; double b = getRandom().nextDouble() * 100; double c = getRandom().nextDouble() * 100; double d = getRandom().nextDouble() * 100; Matrix2d matrix = new Matrix2d(a,b,c,d); double s = getRandom().nextDouble() * 100; Matrix2d prodScal = new Matrix2d(a*s,b*s,c*s,d*s); Matrix2d r = matrix.operator_multiply(s); assertEpsilonEquals(prodScal, r); } @Test public void operator_divideDouble() { double a = getRandom().nextDouble() * 100; double b = getRandom().nextDouble() * 100; double c = getRandom().nextDouble() * 100; double d = getRandom().nextDouble() * 100; Matrix2d matrix = new Matrix2d(a,b,c,d); double s = getRandom().nextDouble() * 100; Matrix2d prodScal = new Matrix2d(a/s,b/s,c/s,d/s); Matrix2d r = matrix.operator_divide(s); assertEpsilonEquals(prodScal, r); } @Test public void operator_plusPlus() { Matrix2d m1 = this.randomMatrix2f(); Matrix2d m2 = m1.clone(); m2.set(m2.m00+1, m2.m01+1, m2.m10+1, m2.m11+1); m1.operator_plusPlus(); assertEpsilonEquals(m2, m1); } @Test public void operator_moinsMoins() { Matrix2d m1 = this.randomMatrix2f(); Matrix2d m2 = m1.clone(); m2.set(m2.m00-1, m2.m01-1, m2.m10-1, m2.m11-1); m1.operator_moinsMoins(); assertEpsilonEquals(m2, m1); } @Test public void operator_not() { Matrix2d m1 = this.randomMatrix2f(); Matrix2d transpose = new Matrix2d(); double [] v = new double[3]; m1.getRow(0, v); transpose.setColumn(0, v); m1.getRow(1, v); transpose.setColumn(1, v); Matrix2d r = m1.operator_not(); assertEpsilonEquals(transpose, r); } }