Repository: commons-rng Updated Branches: refs/heads/master 2f0a3e4ff -> c0b975767
RNG-56: Missing statements in least used branch entail infinite loop. Loop was replaced by recursion that would raise "StackOverFlow" error, rather than run forever in case of a bad RNG implementation. Project: http://git-wip-us.apache.org/repos/asf/commons-rng/repo Commit: http://git-wip-us.apache.org/repos/asf/commons-rng/commit/4f92fa2b Tree: http://git-wip-us.apache.org/repos/asf/commons-rng/tree/4f92fa2b Diff: http://git-wip-us.apache.org/repos/asf/commons-rng/diff/4f92fa2b Branch: refs/heads/master Commit: 4f92fa2b6db0f533810d3ec9efcd2f31d58dc041 Parents: 74c2b58 Author: Gilles <er...@apache.org> Authored: Fri Aug 24 18:11:57 2018 +0200 Committer: Gilles <er...@apache.org> Committed: Fri Aug 24 18:11:57 2018 +0200 ---------------------------------------------------------------------- .../ZigguratNormalizedGaussianSampler.java | 38 ++++++++-------- .../ZigguratNormalizedGaussianSamplerTest.java | 48 ++++++++++++++++++++ src/changes/changes.xml | 3 ++ 3 files changed, 70 insertions(+), 19 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/commons-rng/blob/4f92fa2b/commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/distribution/ZigguratNormalizedGaussianSampler.java ---------------------------------------------------------------------- diff --git a/commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/distribution/ZigguratNormalizedGaussianSampler.java b/commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/distribution/ZigguratNormalizedGaussianSampler.java index b52c926..48d4342 100644 --- a/commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/distribution/ZigguratNormalizedGaussianSampler.java +++ b/commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/distribution/ZigguratNormalizedGaussianSampler.java @@ -122,27 +122,27 @@ public class ZigguratNormalizedGaussianSampler double x; double y; - while (true) { - x = hz * W[iz]; - if (iz == 0) { - // Base strip. - do { - y = -Math.log(rng.nextDouble()); - x = -Math.log(rng.nextDouble()) * ONE_OVER_R; - } while (y + y < x * x); - - final double out = R + x; - return hz > 0 ? out : -out; + x = hz * W[iz]; + if (iz == 0) { + // Base strip. + do { + y = -Math.log(rng.nextDouble()); + x = -Math.log(rng.nextDouble()) * ONE_OVER_R; + } while (y + y < x * x); + + final double out = R + x; + return hz > 0 ? out : -out; + } else { + // Wedge of other strips. + if (F[iz] + rng.nextDouble() * (F[iz - 1] - F[iz]) < gauss(x)) { + return x; } else { - // Wedge of other strips. - if (F[iz] + rng.nextDouble() * (F[iz - 1] - F[iz]) < gauss(x)) { - return x; + final long hzNew = rng.nextLong(); + final int izNew = (int) (hzNew & LAST); + if (Math.abs(hzNew) < K[izNew]) { + return hzNew * W[izNew]; } else { - final long hzNew = rng.nextLong(); - final int izNew = (int) (hzNew & LAST); - if (Math.abs(hzNew) < K[izNew]) { - return hzNew * W[izNew]; - } + return fix(hzNew, izNew); } } } http://git-wip-us.apache.org/repos/asf/commons-rng/blob/4f92fa2b/commons-rng-sampling/src/test/java/org/apache/commons/rng/sampling/distribution/ZigguratNormalizedGaussianSamplerTest.java ---------------------------------------------------------------------- diff --git a/commons-rng-sampling/src/test/java/org/apache/commons/rng/sampling/distribution/ZigguratNormalizedGaussianSamplerTest.java b/commons-rng-sampling/src/test/java/org/apache/commons/rng/sampling/distribution/ZigguratNormalizedGaussianSamplerTest.java new file mode 100644 index 0000000..ebeea5b --- /dev/null +++ b/commons-rng-sampling/src/test/java/org/apache/commons/rng/sampling/distribution/ZigguratNormalizedGaussianSamplerTest.java @@ -0,0 +1,48 @@ +/* + * 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.rng.sampling.distribution; + +import org.junit.Assert; +import org.junit.Test; +import org.apache.commons.rng.simple.RandomSource; +import org.apache.commons.rng.UniformRandomProvider; + +/** + * Test for {@link ZigguratNormalizedGaussianSampler}. + */ +public class ZigguratNormalizedGaussianSamplerTest { + // Cf. RNG-56 + @Test(expected = StackOverflowError.class) + public void testInfiniteLoop() { + // A bad implementation whose only purpose is to force access + // to the rarest branch. + final UniformRandomProvider bad = new UniformRandomProvider() { + public long nextLong(long n) { return 0; } + public long nextLong() { return Long.MAX_VALUE; } + public int nextInt(int n) { return 0; } + public int nextInt() { return Integer.MAX_VALUE; } + public float nextFloat() { return 1; } + public double nextDouble() { return 1;} + public void nextBytes(byte[] bytes, int start, int len) {} + public void nextBytes(byte[] bytes) {} + public boolean nextBoolean() { return false; } + }; + + // Infinite loop (in v1.1). + new ZigguratNormalizedGaussianSampler(bad).sample(); + } +} http://git-wip-us.apache.org/repos/asf/commons-rng/blob/4f92fa2b/src/changes/changes.xml ---------------------------------------------------------------------- diff --git a/src/changes/changes.xml b/src/changes/changes.xml index bbb9893..f161dcd 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -67,6 +67,9 @@ Additional code is provided in the following module: It is however not part of the official API and no compatibility should be expected in subsequent releases. "> + <action dev="erans" type="fix" issue="RNG-56"> + "ZigguratNormalizedGaussianSampler": Missing statements in least used branch. + </action> <action dev="erans" type="fix" issue="RNG-55" due-to="Alex D. Herbert"> "UnitSphereSampler": Prevent returning NaN components and forbid negative dimension.