Return-Path: X-Original-To: apmail-commons-commits-archive@minotaur.apache.org Delivered-To: apmail-commons-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 88502E175 for ; Wed, 30 Jan 2013 23:28:05 +0000 (UTC) Received: (qmail 64956 invoked by uid 500); 30 Jan 2013 23:28:05 -0000 Delivered-To: apmail-commons-commits-archive@commons.apache.org Received: (qmail 64897 invoked by uid 500); 30 Jan 2013 23:28:05 -0000 Mailing-List: contact commits-help@commons.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@commons.apache.org Delivered-To: mailing list commits@commons.apache.org Received: (qmail 64890 invoked by uid 99); 30 Jan 2013 23:28:05 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 30 Jan 2013 23:28:05 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 30 Jan 2013 23:28:01 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 9E29223888E7; Wed, 30 Jan 2013 23:27:41 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1440734 - in /commons/proper/math/trunk/src: changes/changes.xml main/java/org/apache/commons/math3/random/UnitSphereRandomVectorGenerator.java test/java/org/apache/commons/math3/random/UnitSphereRandomVectorGeneratorTest.java Date: Wed, 30 Jan 2013 23:27:41 -0000 To: commits@commons.apache.org From: erans@apache.org X-Mailer: svnmailer-1.0.8-patched Message-Id: <20130130232741.9E29223888E7@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: erans Date: Wed Jan 30 23:27:41 2013 New Revision: 1440734 URL: http://svn.apache.org/viewvc?rev=1440734&view=rev Log: MATH-931 Efficiency improvement and unit test (thanks to Sean Owen). Added: commons/proper/math/trunk/src/test/java/org/apache/commons/math3/random/UnitSphereRandomVectorGeneratorTest.java (with props) Modified: commons/proper/math/trunk/src/changes/changes.xml commons/proper/math/trunk/src/main/java/org/apache/commons/math3/random/UnitSphereRandomVectorGenerator.java Modified: commons/proper/math/trunk/src/changes/changes.xml URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/changes/changes.xml?rev=1440734&r1=1440733&r2=1440734&view=diff ============================================================================== --- commons/proper/math/trunk/src/changes/changes.xml (original) +++ commons/proper/math/trunk/src/changes/changes.xml Wed Jan 30 23:27:41 2013 @@ -55,6 +55,9 @@ This is a minor release: It combines bug Changes to existing features were made in a backwards-compatible way such as to allow drop-in replacement of the v3.1[.1] JAR file. "> + + Greater efficiency in "UnitSphereRandomVectorGenerator". + Improved class javadoc wrt convergence criteria and added additional constructors to override the default epsilon and cut-off Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/random/UnitSphereRandomVectorGenerator.java URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/random/UnitSphereRandomVectorGenerator.java?rev=1440734&r1=1440733&r2=1440734&view=diff ============================================================================== --- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/random/UnitSphereRandomVectorGenerator.java (original) +++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/random/UnitSphereRandomVectorGenerator.java Wed Jan 30 23:27:41 2013 @@ -59,18 +59,17 @@ public class UnitSphereRandomVectorGener /** {@inheritDoc} */ public double[] nextVector() { - final double[] v = new double[dimension]; - double normSq; - do { - normSq = 0; - for (int i = 0; i < dimension; i++) { - final double comp = 2 * rand.nextDouble() - 1; - v[i] = comp; - normSq += comp * comp; - } - } while (normSq > 1); + // See http://mathworld.wolfram.com/SpherePointPicking.html for example. + // Pick a point by choosing a standard Gaussian for each element, and then + // normalizing to unit length. + double normSq = 0; + for (int i = 0; i < dimension; i++) { + final double comp = rand.nextGaussian(); + v[i] = comp; + normSq += comp * comp; + } final double f = 1 / FastMath.sqrt(normSq); for (int i = 0; i < dimension; i++) { @@ -78,7 +77,5 @@ public class UnitSphereRandomVectorGener } return v; - } - } Added: commons/proper/math/trunk/src/test/java/org/apache/commons/math3/random/UnitSphereRandomVectorGeneratorTest.java URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math3/random/UnitSphereRandomVectorGeneratorTest.java?rev=1440734&view=auto ============================================================================== --- commons/proper/math/trunk/src/test/java/org/apache/commons/math3/random/UnitSphereRandomVectorGeneratorTest.java (added) +++ commons/proper/math/trunk/src/test/java/org/apache/commons/math3/random/UnitSphereRandomVectorGeneratorTest.java Wed Jan 30 23:27:41 2013 @@ -0,0 +1,68 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.commons.math3.random; + +import org.apache.commons.math3.util.FastMath; +import org.junit.Assert; +import org.junit.Test; + +public class UnitSphereRandomVectorGeneratorTest { + /** + * Test the distribution of points from {@link UnitSphereRandomVectorGenerator#nextVector()} + * in two dimensions. + */ + @Test + public void test2DDistribution() { + + RandomGenerator rg = new JDKRandomGenerator(); + rg.setSeed(17399225432l); + UnitSphereRandomVectorGenerator generator = new UnitSphereRandomVectorGenerator(2, rg); + + // In 2D, angles with a given vector should be uniformly distributed + int[] angleBuckets = new int[100]; + int steps = 1000000; + for (int i = 0; i < steps; ++i) { + final double[] v = generator.nextVector(); + Assert.assertEquals(2, v.length); + Assert.assertEquals(1, length(v), 1e-10); + // Compute angle formed with vector (1,0) + // Cosine of angle is their dot product, because both are unit length + // Dot product here is just the first element of the vector by construction + final double angle = FastMath.acos(v[0]); + final int bucket = (int) (angleBuckets.length * (angle / FastMath.PI)); + ++angleBuckets[bucket]; + } + + // Simplistic test for roughly even distribution + final int expectedBucketSize = steps / angleBuckets.length; + for (int bucket : angleBuckets) { + Assert.assertTrue("Bucket count " + bucket + " vs expected " + expectedBucketSize, + FastMath.abs(expectedBucketSize - bucket) < 350); + } + } + + /** + * @return length (L2 norm) of given vector + */ + private static double length(double[] vector) { + double total = 0; + for (double d : vector) { + total += d * d; + } + return FastMath.sqrt(total); + } +} Propchange: commons/proper/math/trunk/src/test/java/org/apache/commons/math3/random/UnitSphereRandomVectorGeneratorTest.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: commons/proper/math/trunk/src/test/java/org/apache/commons/math3/random/UnitSphereRandomVectorGeneratorTest.java ------------------------------------------------------------------------------ svn:keywords = Id Revision