This is an automated email from the ASF dual-hosted git repository. aherbert pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/commons-rng.git
commit cb6423ccfc742b209df5b9b181140bf9c15d6314 Author: Alex Herbert <aherb...@apache.org> AuthorDate: Wed Mar 6 22:06:27 2019 +0000 RNG-82: Add XorShift1024StarPhi generator --- .../rng/core/source64/XorShift1024Star.java | 26 ++++++++++--- .../rng/core/source64/XorShift1024StarPhi.java | 44 ++++++++++++++++++++++ .../org/apache/commons/rng/core/ProvidersList.java | 3 +- ...4StarTest.java => XorShift1024StarPhiTest.java} | 37 ++++++++++++------ .../rng/core/source64/XorShift1024StarTest.java | 11 ++++++ .../apache/commons/rng/simple/RandomSource.java | 8 ++++ .../rng/simple/internal/ProviderBuilder.java | 4 ++ .../apache/commons/rng/simple/ProvidersList.java | 1 + 8 files changed, 116 insertions(+), 18 deletions(-) diff --git a/commons-rng-core/src/main/java/org/apache/commons/rng/core/source64/XorShift1024Star.java b/commons-rng-core/src/main/java/org/apache/commons/rng/core/source64/XorShift1024Star.java index 1d48896..c3557d0 100644 --- a/commons-rng-core/src/main/java/org/apache/commons/rng/core/source64/XorShift1024Star.java +++ b/commons-rng-core/src/main/java/org/apache/commons/rng/core/source64/XorShift1024Star.java @@ -21,11 +21,9 @@ import java.util.Arrays; import org.apache.commons.rng.core.util.NumberFactory; /** - * A fast RNG. - * - * @see <a href="http://xorshift.di.unimi.it/xorshift1024star.c"> - * Original source code</a> + * A fast RNG implementing the {@code XorShift1024*} algorithm. * + * @see <a href="http://xorshift.di.unimi.it/xorshift1024star.c">Original source code</a> * @see <a href="https://en.wikipedia.org/wiki/Xorshift">Xorshift (Wikipedia)</a> * @since 1.0 */ @@ -34,6 +32,8 @@ public class XorShift1024Star extends LongProvider { private static final int SEED_SIZE = 16; /** State. */ private final long[] state = new long[SEED_SIZE]; + /** The multiplier for the XorShift1024 algorithm. */ + private final long multiplier; /** Index in "state" array. */ private int index; @@ -44,8 +44,24 @@ public class XorShift1024Star extends LongProvider { * If the length is larger than 16, only the first 16 elements will * be used; if smaller, the remaining elements will be automatically * set. + * A seed containing all zeros will create a non-functional generator. */ public XorShift1024Star(long[] seed) { + this(1181783497276652981L, seed); + } + + /** + * Creates a new instance. + * + * @param multiplier The multiplier for the XorShift1024 algorithm. + * @param seed Initial seed. + * If the length is larger than 16, only the first 16 elements will + * be used; if smaller, the remaining elements will be automatically + * set. + * A seed containing all zeros will create a non-functional generator. + */ + protected XorShift1024Star(long multiplier, long[] seed) { + this.multiplier = multiplier; setSeedInternal(seed); } @@ -90,6 +106,6 @@ public class XorShift1024Star extends LongProvider { long s1 = state[index = (index + 1) & 15]; s1 ^= s1 << 31; // a state[index] = s1 ^ s0 ^ (s1 >>> 11) ^ (s0 >>> 30); // b,c - return state[index] * 1181783497276652981L; + return state[index] * multiplier; } } diff --git a/commons-rng-core/src/main/java/org/apache/commons/rng/core/source64/XorShift1024StarPhi.java b/commons-rng-core/src/main/java/org/apache/commons/rng/core/source64/XorShift1024StarPhi.java new file mode 100644 index 0000000..710dd6c --- /dev/null +++ b/commons-rng-core/src/main/java/org/apache/commons/rng/core/source64/XorShift1024StarPhi.java @@ -0,0 +1,44 @@ +/* + * 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.core.source64; + +/** + * A fast RNG implementing the {@code XorShift1024*} algorithm. + * + * <p>This supersedes {@link XorShift1024Star}. The generator differs only in the multiplier (a + * fixed-point representation of the golden ratio), which eliminates linear dependencies from one of + * the lowest bits. + * + * @see <a href="http://xorshift.di.unimi.it/xorshift1024star.c">Original source code</a> + * @see <a href="https://en.wikipedia.org/wiki/Xorshift">Xorshift (Wikipedia)</a> + * @since 1.3 + */ +public class XorShift1024StarPhi extends XorShift1024Star { + /** + * Creates a new instance. + * + * @param seed Initial seed. + * If the length is larger than 16, only the first 16 elements will + * be used; if smaller, the remaining elements will be automatically + * set. + * A seed containing all zeros will create a non-functional generator. + */ + public XorShift1024StarPhi(long[] seed) { + super(0x9e3779b97f4a7c13L, seed); + } +} diff --git a/commons-rng-core/src/test/java/org/apache/commons/rng/core/ProvidersList.java b/commons-rng-core/src/test/java/org/apache/commons/rng/core/ProvidersList.java index 767074a..c03b07f 100644 --- a/commons-rng-core/src/test/java/org/apache/commons/rng/core/ProvidersList.java +++ b/commons-rng-core/src/test/java/org/apache/commons/rng/core/ProvidersList.java @@ -16,7 +16,6 @@ */ package org.apache.commons.rng.core; -import java.util.Arrays; import java.util.List; import java.util.ArrayList; import java.util.Collections; @@ -35,6 +34,7 @@ import org.apache.commons.rng.core.source32.MultiplyWithCarry256; import org.apache.commons.rng.core.source32.KISSRandom; import org.apache.commons.rng.core.source64.SplitMix64; import org.apache.commons.rng.core.source64.XorShift1024Star; +import org.apache.commons.rng.core.source64.XorShift1024StarPhi; import org.apache.commons.rng.core.source64.TwoCmres; import org.apache.commons.rng.core.source64.MersenneTwister64; import org.apache.commons.rng.RestorableUniformRandomProvider; @@ -81,6 +81,7 @@ public class ProvidersList { // "long"-based RNGs. add(LIST64, new SplitMix64(g.nextLong())); add(LIST64, new XorShift1024Star(new long[] { g.nextLong(), g.nextLong(), g.nextLong(), g.nextLong() })); + add(LIST64, new XorShift1024StarPhi(new long[] { g.nextLong(), g.nextLong(), g.nextLong(), g.nextLong() })); add(LIST64, new TwoCmres(g.nextInt())); add(LIST64, new TwoCmres(g.nextInt(), 5, 8)); add(LIST64, new MersenneTwister64(new long[] { g.nextLong(), g.nextLong(), g.nextLong(), g.nextLong() })); diff --git a/commons-rng-core/src/test/java/org/apache/commons/rng/core/source64/XorShift1024StarTest.java b/commons-rng-core/src/test/java/org/apache/commons/rng/core/source64/XorShift1024StarPhiTest.java similarity index 51% copy from commons-rng-core/src/test/java/org/apache/commons/rng/core/source64/XorShift1024StarTest.java copy to commons-rng-core/src/test/java/org/apache/commons/rng/core/source64/XorShift1024StarPhiTest.java index e158393..ffde7a4 100644 --- a/commons-rng-core/src/test/java/org/apache/commons/rng/core/source64/XorShift1024StarTest.java +++ b/commons-rng-core/src/test/java/org/apache/commons/rng/core/source64/XorShift1024StarPhiTest.java @@ -16,10 +16,13 @@ */ package org.apache.commons.rng.core.source64; +import org.apache.commons.math3.stat.correlation.PearsonsCorrelation; +import org.apache.commons.math3.stat.descriptive.SummaryStatistics; import org.apache.commons.rng.core.RandomAssert; +import org.junit.Assert; import org.junit.Test; -public class XorShift1024StarTest { +public class XorShift1024StarPhiTest { @Test public void testReferenceCode() { /* @@ -34,18 +37,28 @@ public class XorShift1024StarTest { }; final long[] expectedSequence = { - 0xd85e9fc0855614cdL, 0xaf4965c9c1ac6a3dL, 0x067da398791111d8L, 0x2771c41db58d7644L, - 0xf71a471e1ac2b03eL, 0x953449ae275f7409L, 0x8aa570c72de0af5eL, 0xae59db2acdae32beL, - 0x3d46f316b8f97301L, 0x72dc8399b7a70957L, 0xf5624d788b3b6f4eL, 0xb7a79275f6c0e7b1L, - 0xf79354208377d498L, 0x0e5d2f2ac2b4f28fL, 0x0f8f57edc8aa802fL, 0x5e918ea72ece0c36L, - 0xeeb8dbdb00ac7a5aL, 0xf16f88dfef0d6047L, 0x1244c29e0e0d8d2dL, 0xaa94f1cc42691eb7L, - 0xd06425dd329e5de5L, 0x968b1c2e016f159cL, 0x6aadff7055065295L, 0x3bce2efcb0d00876L, - 0xb28d5b69ad8fb719L, 0x1e4040c451376920L, 0x6b0801a8a00de7d7L, 0x891ba2cbe2a4675bL, - 0x6355008481852527L, 0x7a47bcd9960126f3L, 0x07f72fcd4ebe3580L, 0x4658b29c126840ccL, - 0xdc7b36d3037c7539L, 0x9e30aab0410122e8L, 0x7215126e0fce932aL, 0xda63f12a489fc8deL, - 0x769997671b2a0158L, 0xfa9cd84e0ffc174dL, 0x34df1cd959dca211L, 0xccea41a33ec1f763L, + 0xc9351be6ae9af4bbL, 0x2696a1a51e3040cbL, 0xdcbbc38b838b4be8L, 0xc989eee03351a25cL, + 0xc4ad829b653ada72L, 0x1cff4000cc0118dfL, 0x988f3aaf7bfb2852L, 0x3a621d4d5fb27bf2L, + 0x0153d81cf33ff4a7L, 0x8a1b5adb974750c1L, 0x182799e238df6de2L, 0x92d9bda951cd6377L, + 0x601f077d2a659728L, 0x90536cc64ad5bc49L, 0x5d99d9e84e3d7fa9L, 0xfc66f4610240613aL, + 0x0ff67da640cdd6b6L, 0x973c7a6afbb41751L, 0x5089cb5236ac1b5bL, 0x7ed6edc1e4d7e261L, + 0x3e37630df0c00b63L, 0x49ec234a0d03bcc4L, 0x2bcbe2fa4b80fa33L, 0xbaafc47b960baefaL, + 0x1855fa47be98c84fL, 0x8d59cb57e34a73e0L, 0x256b15bb001bf641L, 0x28ad378895f5615dL, + 0x865547335ba2a571L, 0xfefe4c356e154585L, 0xeb87f7a74e076680L, 0x990d2f5d1e60b914L, + 0x3bf0f6864688af2fL, 0x8c6304df9b945d58L, 0x63bc09c335b63666L, 0x1038139f53734ad2L, + 0xf41b58faf5680868L, 0xa50ba830813c163bL, 0x7dc1ca503ae39817L, 0xea3d0f2f37f5ce95L, }; - RandomAssert.assertEquals(expectedSequence, new XorShift1024Star(seed)); + RandomAssert.assertEquals(expectedSequence, new XorShift1024StarPhi(seed)); + } + + @Test + public void testConstructorWithZeroSeed() { + // This is allowed even though the generator is non-functional + final int size = 16; + final XorShift1024StarPhi rng = new XorShift1024StarPhi(new long[size]); + for (int i = size * 2; i-- != 0; ) { + Assert.assertEquals("Expected the generator to be broken", 0L, rng.nextLong()); + } } } diff --git a/commons-rng-core/src/test/java/org/apache/commons/rng/core/source64/XorShift1024StarTest.java b/commons-rng-core/src/test/java/org/apache/commons/rng/core/source64/XorShift1024StarTest.java index e158393..67fd4bb 100644 --- a/commons-rng-core/src/test/java/org/apache/commons/rng/core/source64/XorShift1024StarTest.java +++ b/commons-rng-core/src/test/java/org/apache/commons/rng/core/source64/XorShift1024StarTest.java @@ -17,6 +17,7 @@ package org.apache.commons.rng.core.source64; import org.apache.commons.rng.core.RandomAssert; +import org.junit.Assert; import org.junit.Test; public class XorShift1024StarTest { @@ -48,4 +49,14 @@ public class XorShift1024StarTest { RandomAssert.assertEquals(expectedSequence, new XorShift1024Star(seed)); } + + @Test + public void testConstructorWithZeroSeed() { + // This is allowed even though the generator is non-functional + final int size = 16; + final XorShift1024Star rng = new XorShift1024Star(new long[size]); + for (int i = size * 2; i-- != 0; ) { + Assert.assertEquals("Expected the generator to be broken", 0L, rng.nextLong()); + } + } } diff --git a/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/RandomSource.java b/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/RandomSource.java index adc8f43..f2a9bd5 100644 --- a/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/RandomSource.java +++ b/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/RandomSource.java @@ -246,6 +246,14 @@ public enum RandomSource { */ XOR_SHIFT_1024_S(ProviderBuilder.RandomSourceInternal.XOR_SHIFT_1024_S), /** + * Source of randomness is {@link org.apache.commons.rng.core.source64.XorShift1024StarPhi}. + * <ul> + * <li>Native seed type: {@code long[]}.</li> + * <li>Native seed size: 16.</li> + * </ul> + */ + XOR_SHIFT_1024_S_PHI(ProviderBuilder.RandomSourceInternal.XOR_SHIFT_1024_S_PHI), + /** * Source of randomness is {@link org.apache.commons.rng.core.source64.TwoCmres}. * This generator is equivalent to {@link #TWO_CMRES_SELECT} with the choice of the * pair {@code (0, 1)} for the two subcycle generators. diff --git a/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/internal/ProviderBuilder.java b/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/internal/ProviderBuilder.java index cf82d95..e3a540e 100644 --- a/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/internal/ProviderBuilder.java +++ b/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/internal/ProviderBuilder.java @@ -39,6 +39,7 @@ import org.apache.commons.rng.core.source32.MultiplyWithCarry256; import org.apache.commons.rng.core.source32.KISSRandom; import org.apache.commons.rng.core.source64.SplitMix64; import org.apache.commons.rng.core.source64.XorShift1024Star; +import org.apache.commons.rng.core.source64.XorShift1024StarPhi; import org.apache.commons.rng.core.source64.TwoCmres; import org.apache.commons.rng.core.source64.MersenneTwister64; @@ -290,6 +291,9 @@ public final class ProviderBuilder { /** Source of randomness is {@link XorShift1024Star}. */ XOR_SHIFT_1024_S(XorShift1024Star.class, long[].class), + /** Source of randomness is {@link XorShift1024StarPhi}. */ + XOR_SHIFT_1024_S_PHI(XorShift1024StarPhi.class, + long[].class), /** Source of randomness is {@link TwoCmres}. */ TWO_CMRES(TwoCmres.class, Integer.class), diff --git a/commons-rng-simple/src/test/java/org/apache/commons/rng/simple/ProvidersList.java b/commons-rng-simple/src/test/java/org/apache/commons/rng/simple/ProvidersList.java index 2271cf8..cb88bf2 100644 --- a/commons-rng-simple/src/test/java/org/apache/commons/rng/simple/ProvidersList.java +++ b/commons-rng-simple/src/test/java/org/apache/commons/rng/simple/ProvidersList.java @@ -57,6 +57,7 @@ public class ProvidersList { // "long"-based RNGs. add(LIST64, RandomSource.SPLIT_MIX_64, -988777666655555L); add(LIST64, RandomSource.XOR_SHIFT_1024_S, new long[] { 123456L, 234567L, -345678L }); + add(LIST64, RandomSource.XOR_SHIFT_1024_S_PHI, new long[] { -234567L, -345678L, 3456789L }); add(LIST64, RandomSource.TWO_CMRES, 55443322); add(LIST64, RandomSource.TWO_CMRES_SELECT, -987654321, 5, 8); add(LIST64, RandomSource.MT_64, new long[] { 1234567L, 2345678L, -3456789L });