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 C16901973D for ; Mon, 28 Mar 2016 01:45:00 +0000 (UTC) Received: (qmail 92734 invoked by uid 500); 28 Mar 2016 01:45:00 -0000 Delivered-To: apmail-commons-commits-archive@commons.apache.org Received: (qmail 92645 invoked by uid 500); 28 Mar 2016 01:45:00 -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 92632 invoked by uid 99); 28 Mar 2016 01:45:00 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 28 Mar 2016 01:45:00 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 002F5DFBA0; Mon, 28 Mar 2016 01:44:59 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: erans@apache.org To: commits@commons.apache.org Date: Mon, 28 Mar 2016 01:45:00 -0000 Message-Id: <4a44beaf7a1942feb023e9915b93337e@git.apache.org> In-Reply-To: References: X-Mailer: ASF-Git Admin Mailer Subject: [2/3] [math] MATH-1348 MATH-1348 Subclass of "java.util.Random". Project: http://git-wip-us.apache.org/repos/asf/commons-math/repo Commit: http://git-wip-us.apache.org/repos/asf/commons-math/commit/3411f29e Tree: http://git-wip-us.apache.org/repos/asf/commons-math/tree/3411f29e Diff: http://git-wip-us.apache.org/repos/asf/commons-math/diff/3411f29e Branch: refs/heads/feature-MATH-1158 Commit: 3411f29e2377788cdaa5a4eeaddc53355f085a78 Parents: e366894 Author: Gilles Authored: Mon Mar 28 03:25:05 2016 +0200 Committer: Gilles Committed: Mon Mar 28 03:25:05 2016 +0200 ---------------------------------------------------------------------- .../commons/math4/random/JDKRandomAdaptor.java | 148 +++++++++++++++++++ .../math4/random/JDKRandomAdaptorTest.java | 113 ++++++++++++++ 2 files changed, 261 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/commons-math/blob/3411f29e/src/main/java/org/apache/commons/math4/random/JDKRandomAdaptor.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math4/random/JDKRandomAdaptor.java b/src/main/java/org/apache/commons/math4/random/JDKRandomAdaptor.java new file mode 100644 index 0000000..f3ab22e --- /dev/null +++ b/src/main/java/org/apache/commons/math4/random/JDKRandomAdaptor.java @@ -0,0 +1,148 @@ +/* + * 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.math4.random; + +import java.util.Random; +import java.io.ObjectOutputStream; +import java.io.IOException; +import org.apache.commons.math4.exception.MathInternalError; +import org.apache.commons.math4.exception.MathUnsupportedOperationException; +import org.apache.commons.math4.rng.UniformRandomProvider; +import org.apache.commons.math4.distribution.RealDistribution; +import org.apache.commons.math4.distribution.NormalDistribution; + +/** + * Extension of {@link java.util.Random} that delegates the number + * generation to a {@link UniformRandomProvider}. + * + *

+ * This class allows usage of JDK utilities that take an instance + * of type {@code Random} as argument. + *
+ * Other than for this specific purpose, usage of this class + * is best avoided; indeed, because of the following limitations: + *

    + *
  • + * {@code MathUnsupportedOperationException} will be raised if + * serialization is attempted. + *
  • + *
  • + * Reseeding is not supported. + *
  • + *
+ * an instance of this class cannot be a substitute for an instance + * of the parent class if those functionalities are required. + *

+ * + * @since 4.0 + */ +public final class JDKRandomAdaptor extends Random { + /** Serial version identifier. */ + private static final long serialVersionUID = 666L; + /** Delegate. */ + private final transient UniformRandomProvider rng; + /** Cf. "nextGaussian()" method. */ + private final transient RealDistribution.Sampler gauss; + + /** + * Creates an adaptor. + * + * @param rng Generator. + */ + public JDKRandomAdaptor(UniformRandomProvider rng) { + super(0L); + + this.rng = rng; + gauss = new NormalDistribution().createSampler(rng); + } + + /** {@inheritDoc} */ + @Override + public boolean nextBoolean() { + return rng.nextBoolean(); + } + + /** {@inheritDoc} */ + @Override + public void nextBytes(byte[] bytes) { + rng.nextBytes(bytes); + } + + /** {@inheritDoc} */ + @Override + public double nextDouble() { + return rng.nextDouble(); + } + + /** {@inheritDoc} */ + @Override + public float nextFloat() { + return rng.nextFloat(); + } + + /** {@inheritDoc} */ + @Override + public double nextGaussian() { + return gauss.sample(); + } + + /** {@inheritDoc} */ + @Override + public int nextInt() { + return rng.nextInt(); + } + + /** {@inheritDoc} */ + @Override + public int nextInt(int n) { + return rng.nextInt(n); + } + + /** {@inheritDoc} */ + @Override + public long nextLong() { + return rng.nextLong(); + } + + /** {@inheritDoc} */ + @Override + protected int next(int bits) { + // Should never happen: it means that some methods were not overridden. + throw new MathInternalError(); + } + + /** + * Seeding is not supported. + * + * @param seed Ignored. + */ + @Override + public void setSeed(long seed) { + // Cannot throw because the constructor of "Random" calls it. + // throw new MathUnsupportedOperationException(); + } + + /** + * @param out Ignored. + * @throws IOException Ignored. + * @throws MathUnsupportedOperationException if called. + */ + private void writeObject(ObjectOutputStream out) + throws IOException { + throw new MathUnsupportedOperationException(); + } +} http://git-wip-us.apache.org/repos/asf/commons-math/blob/3411f29e/src/test/java/org/apache/commons/math4/random/JDKRandomAdaptorTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/commons/math4/random/JDKRandomAdaptorTest.java b/src/test/java/org/apache/commons/math4/random/JDKRandomAdaptorTest.java new file mode 100644 index 0000000..5ba68c7 --- /dev/null +++ b/src/test/java/org/apache/commons/math4/random/JDKRandomAdaptorTest.java @@ -0,0 +1,113 @@ +/* + * 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.math4.random; + +import java.util.Random; +import org.apache.commons.math4.exception.MathUnsupportedOperationException; +import org.apache.commons.math4.rng.UniformRandomProvider; +import org.apache.commons.math4.rng.RandomSource; +import org.apache.commons.math4.distribution.RealDistribution; +import org.apache.commons.math4.distribution.NormalDistribution; +import org.apache.commons.math4.TestUtils; +import org.junit.Assert; +import org.junit.Test; + +/** + * Test cases for {@link JDKRandomAdaptor}. + */ +public class JDKRandomAdaptorTest { + + @Test + public void testUniform() { + final RandomSource source = RandomSource.WELL_19937_C; + final long seed = RandomSource.createLong(); // Random seed. + + final UniformRandomProvider reference = RandomSource.create(source, seed); + final Random random = new JDKRandomAdaptor(RandomSource.create(source, seed)); + + final int n = 3; // Check several times, reusing the same RNG. + for (int i = 0; i < n; i++) { + checkUniform(reference, random); + } + } + + @Test + public void testGaussian() { + final RandomSource source = RandomSource.WELL_19937_C; + final long seed = RandomSource.createLong(); // Random seed. + + final UniformRandomProvider reference = RandomSource.create(source, seed); + final RealDistribution.Sampler s = new NormalDistribution(0, 1).createSampler(reference); + + final Random random = new JDKRandomAdaptor(RandomSource.create(source, seed)); + + final int n = 11; // Check several times, reusing the same RNG. + for (int i = 0; i < n; i++) { + Assert.assertEquals(s.sample(), random.nextGaussian(), 0); + } + } + + @Test + public void testSeedIsIgnored() { + final RandomSource source = RandomSource.WELL_19937_C; + final long seed = RandomSource.createLong(); // Random seed. + + Random random; + + random = new JDKRandomAdaptor(RandomSource.create(source, seed)); + final double withoutReseed = random.nextDouble(); + + // Same RNG. + random = new JDKRandomAdaptor(RandomSource.create(source, seed)); + final long differentSeed = seed + 1; + random.setSeed(differentSeed); // Is seeding ignored? + final double withReseed = random.nextDouble(); + + Assert.assertEquals(withoutReseed, withReseed, 0); + } + + @Test(expected=MathUnsupportedOperationException.class) + public void testSerializeIsNotSupported() { + TestUtils.serializeAndRecover(new JDKRandomAdaptor(RandomSource.create(RandomSource.WELL_512_A))); + } + + /** + * Check uniform random generator. + * + * @param rand1 Reference generator. + * @param rand2 Generator under test. + */ + private void checkUniform(UniformRandomProvider rand1, + Random rand2) { + final int len = 11; + final byte[] bytes1 = new byte[len]; + final byte[] bytes2 = new byte[len]; + rand1.nextBytes(bytes1); + rand2.nextBytes(bytes2); + Assert.assertArrayEquals(bytes1, bytes2); + + Assert.assertEquals(rand1.nextBoolean(), rand2.nextBoolean()); + + Assert.assertEquals(rand1.nextInt(), rand2.nextInt()); + Assert.assertEquals(rand1.nextInt(len), rand2.nextInt(len)); + + Assert.assertEquals(rand1.nextLong(), rand2.nextLong()); + + Assert.assertEquals(rand1.nextDouble(), rand2.nextDouble(), 0); + Assert.assertEquals(rand1.nextFloat(), rand2.nextFloat(), 0); + } +}