From 8e049a0ef028ffa332aa147893f702c310e01ce0 Mon Sep 17 00:00:00 2001 From: Gilles Date: Fri, 14 Aug 2015 16:03:52 +0200 Subject: [PATCH] MATH-1244 Utility method "cosAngle". --- src/changes/changes.xml | 3 + .../apache/commons/math3/util/MathArrays.java | 11 ++++ .../commons/math3/util/MathArraysTest.java | 55 +++++++++++++++++++ 3 files changed, 69 insertions(+) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 4b81140b9..0353cecd7 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -73,6 +73,9 @@ If the output is not quite correct, check for invisible trailing spaces! 2-sample Kolmogorov-Smirnov tests. Error was causing incorrect p-values returned by exactP and monteCarloP methods (used by default for small, mid-size samples). + + Method "cosAngle" in "o.a.c.m.util.MathArrays". + "KolmogorovSmirnovTest#ksSum(...)" returned wrong result in case the provided t-parameters was zero. This affected the calculation of "approximateP(...)" for diff --git a/src/main/java/org/apache/commons/math3/util/MathArrays.java b/src/main/java/org/apache/commons/math3/util/MathArrays.java index 3305c771a..b7148ccd0 100644 --- a/src/main/java/org/apache/commons/math3/util/MathArrays.java +++ b/src/main/java/org/apache/commons/math3/util/MathArrays.java @@ -242,6 +242,17 @@ public class MathArrays { return FastMath.sqrt(sum); } + /** + * Calculates the cosine of the angle between two vectors. + * + * @param v1 Cartesian coordinates of the first vector. + * @param v2 Cartesian coordinates of the second vector. + * @return the cosine of the angle between the vectors. + */ + public static double cosAngle(double[] v1, double[] v2) { + return linearCombination(v1, v2) / (safeNorm(v1) * safeNorm(v2)); + } + /** * Calculates the L2 (Euclidean) distance between two points. * diff --git a/src/test/java/org/apache/commons/math3/util/MathArraysTest.java b/src/test/java/org/apache/commons/math3/util/MathArraysTest.java index cf5e39237..bb2de4e6d 100644 --- a/src/test/java/org/apache/commons/math3/util/MathArraysTest.java +++ b/src/test/java/org/apache/commons/math3/util/MathArraysTest.java @@ -172,6 +172,61 @@ public class MathArraysTest { Assert.assertEquals(4, MathArrays.distanceInf(p1, p2)); } + @Test + public void testCosAngle2D() { + double expected; + + final double[] v1 = { 1, 0 }; + expected = 1; + Assert.assertEquals(expected, MathArrays.cosAngle(v1, v1), 0d); + + final double[] v2 = { 0, 1 }; + expected = 0; + Assert.assertEquals(expected, MathArrays.cosAngle(v1, v2), 0d); + + final double[] v3 = { 7, 7 }; + expected = Math.sqrt(2) / 2; + Assert.assertEquals(expected, MathArrays.cosAngle(v1, v3), 1e-15); + Assert.assertEquals(expected, MathArrays.cosAngle(v3, v2), 1e-15); + + final double[] v4 = { -5, 0 }; + expected = -1; + Assert.assertEquals(expected, MathArrays.cosAngle(v1, v4), 0); + + final double[] v5 = { -100, 100 }; + expected = 0; + Assert.assertEquals(expected, MathArrays.cosAngle(v3, v5), 0); + } + + @Test + public void testCosAngle3D() { + double expected; + + final double[] v1 = { 1, 1, 0 }; + expected = 1; + Assert.assertEquals(expected, MathArrays.cosAngle(v1, v1), 1e-15); + + final double[] v2 = { 1, 1, 1 }; + expected = Math.sqrt(2) / Math.sqrt(3); + Assert.assertEquals(expected, MathArrays.cosAngle(v1, v2), 1e-15); + } + + @Test + public void testCosAngleExtreme() { + double expected; + + final double tiny = 1e-200; + final double[] v1 = { tiny, tiny }; + final double big = 1e200; + final double[] v2 = { -big, -big }; + expected = -1; + Assert.assertEquals(expected, MathArrays.cosAngle(v1, v2), 1e-15); + + final double[] v3 = { big, -big }; + expected = 0; + Assert.assertEquals(expected, MathArrays.cosAngle(v1, v3), 1e-15); + } + @Test public void testCheckOrder() { MathArrays.checkOrder(new double[] {-15, -5.5, -1, 2, 15},