aherbert commented on code in PR #191: URL: https://github.com/apache/commons-rng/pull/191#discussion_r2789265387
########## commons-rng-core/src/test/java/org/apache/commons/rng/core/source64/Philox4x64Test.java: ########## @@ -0,0 +1,203 @@ +/* + * 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; + +import org.apache.commons.rng.UniformRandomProvider; +import org.apache.commons.rng.core.RandomAssert; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class Philox4x64Test { + /* + * Data from python randomgen.philox.Philox(key=1234,number=4,width=32) random_raw() + * https://bashtage.github.io/randomgen/bit_generators/philox.html + */ + + private static final long[] EXPECTED_SEQUENCE_1234 = { + 6174562084317992592L, -7568142518571726206L, -5685918792241859306L, + 6151287208724416091L, -7525285015497232737L, -2526119061336846091L, + -2093373494943999176L, 2505686065164099867L, 1493954073060533072L, + 2386252059344830309L, -3981277096068706128L, 4825385527958964709L, + 5896359280427319232L, 2130638389021018825L, 1001529696243618836L, + 6229771985419955916L, -8030183820248387325L, 5924921954534026109L, + -2430661683740471500L, -7119094164204651921L, 2451935767711287279L, + 8424479353221384040L, -5011970289299902244L, 8792348508803652203L, + 9109768561113011588L, 24126314432238277L, -8946976403367747978L, + 6224712922535513938L, 8733921062828259483L, 3855129282970288492L, + -15371244630355388L, -3103082637265535013L, -5696416329331263984L, + -5000982493478729316L, -3077201427991874994L, 4502749081228919907L, + 1930363720599024367L, -7884649763770700010L, 9162677665382083018L, + -1491083349895074892L + }; + + private static final long[] EXPECTED_SEQUENCE_DEFAULT = { + 7651105821017786633L, -986727441099762072L, -1758232618730818806L, + -6892647654339096064L, 2003912625120555464L, 847995992558080923L, + 2561190448322591348L, 5089323078274549892L, -6215224099279536444L, + 2839273132443259286L, -1538091565590055595L, 2262400997606952131L, + 4794890345824897152L, 2654554423835782039L, 5232844452212050618L, + 4968309811735346778L, -6677562093502275256L, -2345486924693103657L, + 2546479265789531422L, 1397198500311783458L, -3029924206687987745L, + 3915450377326980183L, -1798629713529533718L, 7813856890368443409L, + -7530219763187390588L, 7752320264114599504L, 4497386005519180400L, + 8983526426341050924L, 3157770966203722859L, 6531619948763639990L, + -2561361262383382379L, -7341089376366770572L, 5588349311041971766L, + -5547961913507498237L, 557535079196835645L, -7564858493373145745L, + -5687482083658299050L, -6040393957990987713L, 3376696212464637986L, + -4460669316800568753L + }; + + private static final long[] EXPECTED_SEQUENCE_AFTER_JUMP = { + -8246258822028745854L, -8108712508154901372L, 2654408923912105318L, + -6418747939867464899L, 8695124057120477387L, -4062778777418832523L, + -2866609061902870832L, -1985485291750970064L, -3716513824860297891L, + 2708966168515282018L, -8441862438570589384L, -3332504021977608920L, + 8275431876927502767L, -37683753608778224L, 4850475723424833501L, + -2864632267522668999L, -6547048909303846355L, -6804759155034193445L, + -1607076952104749058L, 7993605125443204784L, 7601442483044023354L, + -7379694727972198096L, -1902536664833944445L, -908773878773086264L, + -7367142976738044337L, 2845297286559921499L, 5398165976383543580L, + 2574122219286874876L, 3780790808954139828L, -7038343169285503987L, + 1381442423564430946L, -4910467881295472851L, 839863310680617535L, + 3700507604505113976L, 2586645934793105407L, 1058068213122536369L, + -1876209807038423750L, 8994121856634859944L, 4145729862086221315L, + -7214331765643557828L + }; + + private static final long[] EXPECTED_SEQUENCE_AFTER_LONG_JUMP = { + 234199833207670492L, 4847236961490835302L, 4652995647109309910L, + -3737386356448340712L, -5273383760715124519L, -3647957810120825499L, + 5146817817305263920L, 5710973906845063179L, -1479449555641285865L, + 4084674574582715314L, -5547600708256898652L, -4421640461296589483L, + -2968992335347510287L, -4790862279320238050L, -2473190691392812606L, + 965983568262991078L, 601327440871821012L, 8223565539892887311L, + 7546441310634873026L, 2825517271552261878L, 1821450327999942380L, + 1829354945050293158L, -4141883204296663957L, 2272925410140103105L, + 6950466720264053689L, 942049061182241074L, -423320710605977014L, + -7153892430601162036L, -3577327671114607603L, 2251213489013696162L, + -869366985991136417L, 6210870867759981069L, 8104504070499194349L, + -5828300645374305433L, -8988635423527025878L, 2037830179166981888L, + 600555068878135939L, -1046966376945680441L, 9153700819137910983L, + 6246833740445288808L + }; + + @Test + void testReferenceCode() { + RandomAssert.assertEquals(EXPECTED_SEQUENCE_1234, new Philox4x64(new long[]{1234L, 0})); + } + + @Test + void testReferenceCodeDefaultSeed() { + RandomAssert.assertEquals(EXPECTED_SEQUENCE_DEFAULT, new Philox4x64()); + } + + + @Test + void testJump() { + RandomAssert.assertJumpEquals(EXPECTED_SEQUENCE_DEFAULT, EXPECTED_SEQUENCE_AFTER_JUMP, + new Philox4x64(new long[]{67280421310721L, 0x9E3779B97F4A7C15L})); + } + + @Test + void testLongJump() { + RandomAssert.assertLongJumpEquals(EXPECTED_SEQUENCE_DEFAULT, EXPECTED_SEQUENCE_AFTER_LONG_JUMP, new Philox4x64()); + } + + @Test + void testInternalCounter() { + //test of incrementCounter + Philox4x64 rng = new Philox4x64(new long[]{67280421310721L, 1234L, 0xffffffffffffffffL, 0, 0, 0}); + for (int i = 0; i < 4; i++) { + rng.next(); + } + long value = rng.next(); + Philox4x64 rng2 = new Philox4x64(new long[]{67280421310721L, 1234L, 0, 1, 0, 0}); + long value2 = rng2.next(); + assertEquals(value, value2); + + rng = new Philox4x64(new long[]{67280421310721L, 1234L, 0xffffffffffffffffL, 0xffffffffffffffffL, 0, 0}); + for (int i = 0; i < 4; i++) { + rng.next(); + } + value = rng.next(); + rng2 = new Philox4x64(new long[]{67280421310721L, 1234L, 0, 0, 1, 0}); + value2 = rng2.next(); + assertEquals(value, value2); + + rng = new Philox4x64(new long[]{67280421310721L, 1234L, 0xffffffffffffffffL, 0xffffffffffffffffL, 0xffffffffffffffffL, 0}); + for (int i = 0; i < 4; i++) { + rng.next(); + } + value = rng.next(); + rng2 = new Philox4x64(new long[]{67280421310721L, 1234L, 0, 0, 0, 1}); + value2 = rng2.next(); + assertEquals(value, value2); + + } + + @Test + void testLongJumpCounter() { + Philox4x64 rng = new Philox4x64(new long[]{1234L, 0, 0xffffffffffffffffL, 0, 0xffffffffffffffffL, 0}); + UniformRandomProvider rngOrig = rng.jump(); Review Comment: `rngOrig` is unused. ########## commons-rng-core/src/main/java/org/apache/commons/rng/core/source32/Philox4x32.java: ########## @@ -0,0 +1,324 @@ +/* + * 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.source32; + +import org.apache.commons.rng.JumpableUniformRandomProvider; +import org.apache.commons.rng.LongJumpableUniformRandomProvider; +import org.apache.commons.rng.UniformRandomProvider; +import org.apache.commons.rng.core.util.NumberFactory; + +import java.util.Arrays; + +/** + * This class implements the Philox4x32 128-bit counter-based generator with 10 rounds. + * Jumping in the sequence is essentially instantaneous. This generator provides subsequences for easy parallelization. + * + * @see <a href="https://www.thesalmons.org/john/random123/papers/random123sc11.pdf">Parallel Random Numbers: As Easy as 1,2,3</a> + * for details regarding the engine. + * @since 1.7 + */ +public final class Philox4x32 extends IntProvider implements LongJumpableUniformRandomProvider { + /** + * Philox 32-bit mixing constant for counter 0. + */ + private static final int K_PHILOX_10_A = 0x9E3779B9; + /** + * Philox 32-bit mixing constant for counter 1. + */ + private static final int K_PHILOX_10_B = 0xBB67AE85; + /** + * Philox 32-bit constant for key 0. + */ + private static final int K_PHILOX_SA = 0xD2511F53; + /** + * Philox 32-bit constant for key 1. + */ + private static final int K_PHILOX_SB = 0xCD9E8D57; + /** + * Internal buffer size. + */ + private static final int PHILOX_BUFFER_SIZE = 4; + /** + * number of int variables. + */ + private static final int STATE_SIZE = 7; + + /** + * Counter 0. + */ + private int counter0; + /** + * Counter 1. + */ + private int counter1; + /** + * Counter 2. + */ + private int counter2; + /** + * Counter 3. + */ + private int counter3; + /** + * Output point. + */ + private int[] buffer = new int[PHILOX_BUFFER_SIZE]; // UINT4 + /** + * Key low bits. + */ + private int key0; + /** + * Key high bits. + */ + private int key1; + /** + * State index: which output word is next (0..3). + */ + private int bufferPosition; + + + /** + * Copy constructor. + * + * @param source Source to copy. + */ + private Philox4x32(Philox4x32 source) { + super(source); + counter0 = source.counter0; + counter1 = source.counter1; + counter2 = source.counter2; + counter3 = source.counter3; + key0 = source.key0; + key1 = source.key1; + bufferPosition = source.bufferPosition; + buffer = source.buffer.clone(); + } + + /** + * Creates a new instance with default seed. Subsequence and offset (or equivalently, the internal counter) + * are set to zero. + */ + public Philox4x32() { + this(67280421310721L); + } + + /** + * Creates a new instance with a given seed. Subsequence and offset (or equivalently, the internal counter) + * are set to zero. + * + * @param key the low 32 bits constitute the first int key of Philox, + * and the high 32 bits constitute the second int key of Philox + */ + public Philox4x32(long key) { + this(new int[]{(int) key, (int) (key >>> 32)}); + } + + /** + * Creates a new instance based on an array of int containing, key (first two ints) and + * the counter (next 4 ints, starts at first int). The counter is not scrambled and may + * be used to create contiguous blocks with size a multiple of 4 ints. + * + * @param seed an array of size 6 defining key0,key1,counter0,counter1,counter2,counter3. + * If the size is smaller, zero values are assumed. + */ + public Philox4x32(int[] seed) { + final int[] input = seed.length < 6 ? Arrays.copyOf(seed, 6) : seed; + key0 = input[0]; + key1 = input[1]; + counter0 = input[2]; + counter1 = input[3]; + counter2 = input[4]; + counter3 = input[5]; + bufferPosition = PHILOX_BUFFER_SIZE; + } + + /** + * Fetch next integer from the buffer, or regenerate the buffer using 10 rounds. + * + * @return random integer + */ + @Override + public int next() { + final int p = bufferPosition; + if (p < PHILOX_BUFFER_SIZE) { + bufferPosition = p + 1; + return buffer[p]; + } + incrementCounter(); + rand10(); + bufferPosition = 1; + return buffer[0]; + } + + /** + * Increment by one. + */ + private void incrementCounter() { + counter0++; + if (counter0 != 0) { + return; + } + + counter1++; + if (counter1 != 0) { + return; + } + + counter2++; + if (counter2 != 0) { + return; + } + + counter3++; + } + + /** + * Performs a single round of philox. + * + * @param ctr local counter, which will be updated after each call. + * @param key0 key low bits + * @param key1 key high bits + */ + private static void singleRound(int[] ctr, int key0, int key1) { + long product = (K_PHILOX_SA & 0xFFFFFFFFL) * (ctr[0] & 0xFFFFFFFFL); + final int hi0 = (int) (product >>> 32); + final int lo0 = (int) product; + product = (K_PHILOX_SB & 0xFFFFFFFFL) * (ctr[2] & 0xFFFFFFFFL); + final int hi1 = (int) (product >>> 32); + final int lo1 = (int) product; + + ctr[0] = hi1 ^ ctr[1] ^ key0; + ctr[1] = lo1; + ctr[2] = hi0 ^ ctr[3] ^ key1; + ctr[3] = lo0; + } + + /** + * Perform 10 rounds, using counter0, counter1, counter2, counter3 as starting point. + * It updates the buffer member variable, but no others. + */ + private void rand10() { + buffer[0] = counter0; + buffer[1] = counter1; + buffer[2] = counter2; + buffer[3] = counter3; + + int k0 = key0; + int k1 = key1; + + //unrolled loop for performance + singleRound(buffer, k0, k1); + k0 += K_PHILOX_10_A; + k1 += K_PHILOX_10_B; + singleRound(buffer, k0, k1); + k0 += K_PHILOX_10_A; + k1 += K_PHILOX_10_B; + singleRound(buffer, k0, k1); + k0 += K_PHILOX_10_A; + k1 += K_PHILOX_10_B; + singleRound(buffer, k0, k1); + k0 += K_PHILOX_10_A; + k1 += K_PHILOX_10_B; + singleRound(buffer, k0, k1); + k0 += K_PHILOX_10_A; + k1 += K_PHILOX_10_B; + singleRound(buffer, k0, k1); + k0 += K_PHILOX_10_A; + k1 += K_PHILOX_10_B; + singleRound(buffer, k0, k1); + k0 += K_PHILOX_10_A; + k1 += K_PHILOX_10_B; + singleRound(buffer, k0, k1); + k0 += K_PHILOX_10_A; + k1 += K_PHILOX_10_B; + singleRound(buffer, k0, k1); + k0 += K_PHILOX_10_A; + k1 += K_PHILOX_10_B; + singleRound(buffer, k0, k1); + } + + + /** + * {@inheritDoc} + * + * <p>Increments the subsequence by 1.</p> + * <p>The jump size is the equivalent of 4*2<sup>96</sup> calls to + * {@link UniformRandomProvider#nextInt() nextInt()}. + */ + @Override + public JumpableUniformRandomProvider longJump() { + final Philox4x32 copy = copy(); + counter3++; + rand10(); + return copy; Review Comment: Still missing a call to `resetCachedState()` ########## commons-rng-core/src/test/java/org/apache/commons/rng/core/source32/Philox4x32Test.java: ########## @@ -0,0 +1,198 @@ +/* + * 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.source32; + +import org.apache.commons.rng.UniformRandomProvider; +import org.apache.commons.rng.core.RandomAssert; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class Philox4x32Test { + + /* + * Data from python randomgen.philox.Philox(key=1234,number=4,width=32) random_raw() + * https://bashtage.github.io/randomgen/bit_generators/philox.html + */ + + private static final int[] EXPECTED_SEQUENCE_1234 = { + -1628512715, 482218876, -98078573, 343858512, 1070188760, + -66651592, -870905049, -1994573039, -1238984130, 599211371, + 1926069095, -394512546, 346514135, -352142790, 196394741, + -107436867, -903274039, 860026475, -1309487194, -1778049224, + -49503714, -1441076994, -866074276, -1339523817, -1290919251, + 1857369626, -1839251177, -2041498882, -1956330288, 905306810, + -2114083635, 200746399, 20291031, 214040874, -1628891823, + -1958807646, 9198301, -1607720479, -1349496224, 1418271217 + }; + + private static final int[] EXPECTED_SEQUENCE_DEFAULT = { + 623720234, -686991347, 358698524, 234508473, 1303720625, + 1235930736, -75297729, 110380616, 829652807, -1101240720, + -1443748750, -1366075136, -1702811520, 232450464, 350957237, + 1425642103, 256542391, 1837662153, -448554748, 637025846, + -902021712, 1085962074, -1391041963, 201580325, 1416828610, + 599210676, -628463662, -576572235, 457140358, -1026551805, + -917125498, 529387774, 1254882949, 1278069784, 724938314, + -4044975, -1211844829, -198846304, 286548119, 2085574084 + }; + + private static final int[] EXPECTED_SEQUENCE_AFTER_JUMP = { + -1941342745, 535234737, -1560986946, 1333403881, -467630828, + -1212243215, 1924495835, 1889500660, 118588722, -444471278, + -984974572, 2134204567, 620921081, -929199568, -44345645, + -346841340, -557091335, 1023562906, -1544843001, 2014718360, + -186712859, -874952234, -1016908504, 953606755, -1406346322, + -1297454974, 1426742334, 1461035068, 206733349, 1606578263, + -1354963004, -604654637, 782017623, 1501746828, 853947605, + -1380277812, 1855551741, -1023933348, -635058958, 1752530776 + }; + + private static final int[] EXPECTED_SEQUENCE_AFTER_LONG_JUMP = { + -643973534, -1464631510, -1204127809, 380399830, 1336312468, + 862647039, -970571153, -1473390944, 811398823, -598244991, + -1474151641, -1228756553, -166611808, -231601273, -2055417682, + -1102476522, 1497124960, 438167652, -657449781, -404513325, + -621271837, -10198296, -267651022, -296539606, -1564719261, + -652626768, -973911394, 1388361366, 1675611708, -1270745165, + -620748722, -1569788343, 831908952, 1873081673, -1058521087, + -26171115, -1211556401, -65210719, -1194284085, 1579466740 + }; + + @Test + void testReferenceCode() { + RandomAssert.assertEquals(EXPECTED_SEQUENCE_1234, new Philox4x32(1234L)); + } + + @Test + void testReferenceCodeDefaultSeed() { + RandomAssert.assertEquals(EXPECTED_SEQUENCE_DEFAULT, new Philox4x32(67280421310721L)); + } + + @Test + void testConstructors() { + Philox4x32[] rngs = new Philox4x32[]{ + new Philox4x32(), + new Philox4x32(67280421310721L), + new Philox4x32(new int[]{(int) 67280421310721L, (int) (67280421310721L >>> 32), 0, 0, 0, 0}) + }; + int refValue = rngs[0].next(); + for (int i = 1; i < rngs.length; i++) { + int value = rngs[i].next(); + assertEquals(refValue, value, "Philox4x32 initialization for i=" + i); + } + rngs = new Philox4x32[]{ + new Philox4x32(new int[]{1234, 0, 1}), + new Philox4x32(new int[]{1234, 0, 1, 0, 0, 0}), + }; + refValue = rngs[0].next(); + for (int i = 1; i < rngs.length; i++) { + int value = rngs[i].next(); + assertEquals(refValue, value, "Philox4x32 initialization for i=" + i); + } + rngs = new Philox4x32[]{ + new Philox4x32(1234L), + new Philox4x32(new int[]{1234}), + new Philox4x32(new int[]{1234, 0}), + new Philox4x32(new int[]{1234, 0, 0}), + new Philox4x32(new int[]{1234, 0, 0, 0}), + new Philox4x32(new int[]{1234, 0, 0, 0, 0}), + new Philox4x32(new int[]{1234, 0, 0, 0, 0, 0}), + new Philox4x32(new int[]{1234, 0, 0, 0, 0, 0, 0}), + }; + refValue = rngs[0].next(); + for (int i = 1; i < rngs.length; i++) { + int value = rngs[i].next(); + assertEquals(refValue, value, "Philox4x32 initialization for i=" + i); + } + } + + @Test + void testJump() { + RandomAssert.assertJumpEquals(EXPECTED_SEQUENCE_DEFAULT, EXPECTED_SEQUENCE_AFTER_JUMP, new Philox4x32(67280421310721L)); + } + + @Test + void testLongJump() { + RandomAssert.assertLongJumpEquals(EXPECTED_SEQUENCE_DEFAULT, EXPECTED_SEQUENCE_AFTER_LONG_JUMP, new Philox4x32(67280421310721L)); + } + + @Test + void testDouble() { + Philox4x32 rng = new Philox4x32(); + final int v = rng.nextInt(); + final int w = rng.nextInt(); + final long high = Integer.toUnsignedLong(v) << 21; + final long low = Integer.toUnsignedLong(w); + double valueOpen = ((high ^ low) | 1) * 0x1.0p-53d; + rng = new Philox4x32(); + double value = rng.nextDouble(); + assertEquals(value, valueOpen, Math.pow(2, -20)); //will differ after 20bits + } + + @Test + void testInternalCounter() { + //test of incrementCounter + Philox4x32 rng = new Philox4x32(new int[]{(int) 67280421310721L, (int) (67280421310721L >>> 32), 0xffffffff, 0, 0, 0}); + for (int i = 0; i < 4; i++) { + rng.next(); + } + long value = rng.next(); + Philox4x32 rng2 = new Philox4x32(new int[]{(int) 67280421310721L, (int) (67280421310721L >>> 32), 0, 1, 0, 0}); + long value2 = rng2.next(); + assertEquals(value, value2); + + rng = new Philox4x32(new int[]{(int) 67280421310721L, (int) (67280421310721L >>> 32), 0xffffffff, 0xffffffff, 0, 0}); + for (int i = 0; i < 4; i++) { + rng.next(); + } + value = rng.next(); + rng2 = new Philox4x32(new int[]{(int) 67280421310721L, (int) (67280421310721L >>> 32), 0, 0, 1, 0}); + value2 = rng2.next(); + assertEquals(value, value2); + + rng = new Philox4x32(new int[]{(int) 67280421310721L, (int) (67280421310721L >>> 32), 0xffffffff, 0xffffffff, 0xffffffff, 0}); + for (int i = 0; i < 4; i++) { + rng.next(); + } + value = rng.next(); + rng2 = new Philox4x32(new int[]{(int) 67280421310721L, (int) (67280421310721L >>> 32), 0, 0, 0, 1}); + value2 = rng2.next(); + assertEquals(value, value2); + } + + @Test + void testLongJumpCounter() { + Philox4x32 rng = new Philox4x32(new int[]{1234, 0, 0xffffffff, 0xffffffff, 0xffffffff, 0}); + UniformRandomProvider rngOrig = rng.longJump(); + long value = rng.nextInt(); + Philox4x32 rng2 = new Philox4x32(new int[]{1234, 0, 0xffffffff, 0xffffffff, 0xffffffff, 1}); + long value2 = rng2.nextInt(); + assertEquals(value2, value); + } + + @Test + void testJumpCounter() { + Philox4x32 rng = new Philox4x32(new int[]{1234, 0, 0xffffffff, 0xffffffff, 0xffffffff, 0}); + UniformRandomProvider rngOrig = rng.jump(); Review Comment: `rngOrig` is not used. ########## commons-rng-core/src/test/java/org/apache/commons/rng/core/source32/Philox4x32Test.java: ########## @@ -0,0 +1,198 @@ +/* + * 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.source32; + +import org.apache.commons.rng.UniformRandomProvider; +import org.apache.commons.rng.core.RandomAssert; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class Philox4x32Test { + + /* + * Data from python randomgen.philox.Philox(key=1234,number=4,width=32) random_raw() + * https://bashtage.github.io/randomgen/bit_generators/philox.html + */ + + private static final int[] EXPECTED_SEQUENCE_1234 = { + -1628512715, 482218876, -98078573, 343858512, 1070188760, + -66651592, -870905049, -1994573039, -1238984130, 599211371, + 1926069095, -394512546, 346514135, -352142790, 196394741, + -107436867, -903274039, 860026475, -1309487194, -1778049224, + -49503714, -1441076994, -866074276, -1339523817, -1290919251, + 1857369626, -1839251177, -2041498882, -1956330288, 905306810, + -2114083635, 200746399, 20291031, 214040874, -1628891823, + -1958807646, 9198301, -1607720479, -1349496224, 1418271217 + }; + + private static final int[] EXPECTED_SEQUENCE_DEFAULT = { + 623720234, -686991347, 358698524, 234508473, 1303720625, + 1235930736, -75297729, 110380616, 829652807, -1101240720, + -1443748750, -1366075136, -1702811520, 232450464, 350957237, + 1425642103, 256542391, 1837662153, -448554748, 637025846, + -902021712, 1085962074, -1391041963, 201580325, 1416828610, + 599210676, -628463662, -576572235, 457140358, -1026551805, + -917125498, 529387774, 1254882949, 1278069784, 724938314, + -4044975, -1211844829, -198846304, 286548119, 2085574084 + }; + + private static final int[] EXPECTED_SEQUENCE_AFTER_JUMP = { + -1941342745, 535234737, -1560986946, 1333403881, -467630828, + -1212243215, 1924495835, 1889500660, 118588722, -444471278, + -984974572, 2134204567, 620921081, -929199568, -44345645, + -346841340, -557091335, 1023562906, -1544843001, 2014718360, + -186712859, -874952234, -1016908504, 953606755, -1406346322, + -1297454974, 1426742334, 1461035068, 206733349, 1606578263, + -1354963004, -604654637, 782017623, 1501746828, 853947605, + -1380277812, 1855551741, -1023933348, -635058958, 1752530776 + }; + + private static final int[] EXPECTED_SEQUENCE_AFTER_LONG_JUMP = { + -643973534, -1464631510, -1204127809, 380399830, 1336312468, + 862647039, -970571153, -1473390944, 811398823, -598244991, + -1474151641, -1228756553, -166611808, -231601273, -2055417682, + -1102476522, 1497124960, 438167652, -657449781, -404513325, + -621271837, -10198296, -267651022, -296539606, -1564719261, + -652626768, -973911394, 1388361366, 1675611708, -1270745165, + -620748722, -1569788343, 831908952, 1873081673, -1058521087, + -26171115, -1211556401, -65210719, -1194284085, 1579466740 + }; + + @Test + void testReferenceCode() { + RandomAssert.assertEquals(EXPECTED_SEQUENCE_1234, new Philox4x32(1234L)); + } + + @Test + void testReferenceCodeDefaultSeed() { + RandomAssert.assertEquals(EXPECTED_SEQUENCE_DEFAULT, new Philox4x32(67280421310721L)); + } + + @Test + void testConstructors() { + Philox4x32[] rngs = new Philox4x32[]{ + new Philox4x32(), + new Philox4x32(67280421310721L), + new Philox4x32(new int[]{(int) 67280421310721L, (int) (67280421310721L >>> 32), 0, 0, 0, 0}) + }; + int refValue = rngs[0].next(); + for (int i = 1; i < rngs.length; i++) { + int value = rngs[i].next(); + assertEquals(refValue, value, "Philox4x32 initialization for i=" + i); + } + rngs = new Philox4x32[]{ + new Philox4x32(new int[]{1234, 0, 1}), + new Philox4x32(new int[]{1234, 0, 1, 0, 0, 0}), + }; + refValue = rngs[0].next(); + for (int i = 1; i < rngs.length; i++) { + int value = rngs[i].next(); + assertEquals(refValue, value, "Philox4x32 initialization for i=" + i); + } + rngs = new Philox4x32[]{ + new Philox4x32(1234L), + new Philox4x32(new int[]{1234}), + new Philox4x32(new int[]{1234, 0}), + new Philox4x32(new int[]{1234, 0, 0}), + new Philox4x32(new int[]{1234, 0, 0, 0}), + new Philox4x32(new int[]{1234, 0, 0, 0, 0}), + new Philox4x32(new int[]{1234, 0, 0, 0, 0, 0}), + new Philox4x32(new int[]{1234, 0, 0, 0, 0, 0, 0}), + }; + refValue = rngs[0].next(); + for (int i = 1; i < rngs.length; i++) { + int value = rngs[i].next(); + assertEquals(refValue, value, "Philox4x32 initialization for i=" + i); + } + } + + @Test + void testJump() { + RandomAssert.assertJumpEquals(EXPECTED_SEQUENCE_DEFAULT, EXPECTED_SEQUENCE_AFTER_JUMP, new Philox4x32(67280421310721L)); + } + + @Test + void testLongJump() { + RandomAssert.assertLongJumpEquals(EXPECTED_SEQUENCE_DEFAULT, EXPECTED_SEQUENCE_AFTER_LONG_JUMP, new Philox4x32(67280421310721L)); + } + + @Test + void testDouble() { + Philox4x32 rng = new Philox4x32(); + final int v = rng.nextInt(); + final int w = rng.nextInt(); + final long high = Integer.toUnsignedLong(v) << 21; + final long low = Integer.toUnsignedLong(w); + double valueOpen = ((high ^ low) | 1) * 0x1.0p-53d; + rng = new Philox4x32(); + double value = rng.nextDouble(); + assertEquals(value, valueOpen, Math.pow(2, -20)); //will differ after 20bits + } + + @Test + void testInternalCounter() { + //test of incrementCounter Review Comment: These tests could use: `TestUtils.assertNextIntEquals`. Matching a single output is unlikely but possible with different seeds. Matching a sequence of output is increasingly unlikely with length. ########## commons-rng-core/src/test/java/org/apache/commons/rng/core/source64/Philox4x64Test.java: ########## @@ -0,0 +1,203 @@ +/* + * 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; + +import org.apache.commons.rng.UniformRandomProvider; +import org.apache.commons.rng.core.RandomAssert; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class Philox4x64Test { + /* + * Data from python randomgen.philox.Philox(key=1234,number=4,width=32) random_raw() + * https://bashtage.github.io/randomgen/bit_generators/philox.html + */ + + private static final long[] EXPECTED_SEQUENCE_1234 = { + 6174562084317992592L, -7568142518571726206L, -5685918792241859306L, + 6151287208724416091L, -7525285015497232737L, -2526119061336846091L, + -2093373494943999176L, 2505686065164099867L, 1493954073060533072L, + 2386252059344830309L, -3981277096068706128L, 4825385527958964709L, + 5896359280427319232L, 2130638389021018825L, 1001529696243618836L, + 6229771985419955916L, -8030183820248387325L, 5924921954534026109L, + -2430661683740471500L, -7119094164204651921L, 2451935767711287279L, + 8424479353221384040L, -5011970289299902244L, 8792348508803652203L, + 9109768561113011588L, 24126314432238277L, -8946976403367747978L, + 6224712922535513938L, 8733921062828259483L, 3855129282970288492L, + -15371244630355388L, -3103082637265535013L, -5696416329331263984L, + -5000982493478729316L, -3077201427991874994L, 4502749081228919907L, + 1930363720599024367L, -7884649763770700010L, 9162677665382083018L, + -1491083349895074892L + }; + + private static final long[] EXPECTED_SEQUENCE_DEFAULT = { + 7651105821017786633L, -986727441099762072L, -1758232618730818806L, + -6892647654339096064L, 2003912625120555464L, 847995992558080923L, + 2561190448322591348L, 5089323078274549892L, -6215224099279536444L, + 2839273132443259286L, -1538091565590055595L, 2262400997606952131L, + 4794890345824897152L, 2654554423835782039L, 5232844452212050618L, + 4968309811735346778L, -6677562093502275256L, -2345486924693103657L, + 2546479265789531422L, 1397198500311783458L, -3029924206687987745L, + 3915450377326980183L, -1798629713529533718L, 7813856890368443409L, + -7530219763187390588L, 7752320264114599504L, 4497386005519180400L, + 8983526426341050924L, 3157770966203722859L, 6531619948763639990L, + -2561361262383382379L, -7341089376366770572L, 5588349311041971766L, + -5547961913507498237L, 557535079196835645L, -7564858493373145745L, + -5687482083658299050L, -6040393957990987713L, 3376696212464637986L, + -4460669316800568753L + }; + + private static final long[] EXPECTED_SEQUENCE_AFTER_JUMP = { + -8246258822028745854L, -8108712508154901372L, 2654408923912105318L, + -6418747939867464899L, 8695124057120477387L, -4062778777418832523L, + -2866609061902870832L, -1985485291750970064L, -3716513824860297891L, + 2708966168515282018L, -8441862438570589384L, -3332504021977608920L, + 8275431876927502767L, -37683753608778224L, 4850475723424833501L, + -2864632267522668999L, -6547048909303846355L, -6804759155034193445L, + -1607076952104749058L, 7993605125443204784L, 7601442483044023354L, + -7379694727972198096L, -1902536664833944445L, -908773878773086264L, + -7367142976738044337L, 2845297286559921499L, 5398165976383543580L, + 2574122219286874876L, 3780790808954139828L, -7038343169285503987L, + 1381442423564430946L, -4910467881295472851L, 839863310680617535L, + 3700507604505113976L, 2586645934793105407L, 1058068213122536369L, + -1876209807038423750L, 8994121856634859944L, 4145729862086221315L, + -7214331765643557828L + }; + + private static final long[] EXPECTED_SEQUENCE_AFTER_LONG_JUMP = { + 234199833207670492L, 4847236961490835302L, 4652995647109309910L, + -3737386356448340712L, -5273383760715124519L, -3647957810120825499L, + 5146817817305263920L, 5710973906845063179L, -1479449555641285865L, + 4084674574582715314L, -5547600708256898652L, -4421640461296589483L, + -2968992335347510287L, -4790862279320238050L, -2473190691392812606L, + 965983568262991078L, 601327440871821012L, 8223565539892887311L, + 7546441310634873026L, 2825517271552261878L, 1821450327999942380L, + 1829354945050293158L, -4141883204296663957L, 2272925410140103105L, + 6950466720264053689L, 942049061182241074L, -423320710605977014L, + -7153892430601162036L, -3577327671114607603L, 2251213489013696162L, + -869366985991136417L, 6210870867759981069L, 8104504070499194349L, + -5828300645374305433L, -8988635423527025878L, 2037830179166981888L, + 600555068878135939L, -1046966376945680441L, 9153700819137910983L, + 6246833740445288808L + }; + + @Test + void testReferenceCode() { + RandomAssert.assertEquals(EXPECTED_SEQUENCE_1234, new Philox4x64(new long[]{1234L, 0})); + } + + @Test + void testReferenceCodeDefaultSeed() { + RandomAssert.assertEquals(EXPECTED_SEQUENCE_DEFAULT, new Philox4x64()); + } + + + @Test + void testJump() { + RandomAssert.assertJumpEquals(EXPECTED_SEQUENCE_DEFAULT, EXPECTED_SEQUENCE_AFTER_JUMP, + new Philox4x64(new long[]{67280421310721L, 0x9E3779B97F4A7C15L})); + } + + @Test + void testLongJump() { + RandomAssert.assertLongJumpEquals(EXPECTED_SEQUENCE_DEFAULT, EXPECTED_SEQUENCE_AFTER_LONG_JUMP, new Philox4x64()); + } + + @Test + void testInternalCounter() { + //test of incrementCounter Review Comment: These tests could use: `TestUtils.assertNextLongEquals`. Matching a single output is unlikely but possible with different seeds. Matching a sequence of output is increasingly unlikely with length. ########## commons-rng-examples/examples-jmh/src/main/java/org/apache/commons/rng/examples/jmh/simple/ConstructionPerformance.java: ########## @@ -329,6 +333,7 @@ private static int findNativeSeedLength(RandomSource randomSource) { case SPLIT_MIX_64: case TWO_CMRES: case TWO_CMRES_SELECT: + case PHILOX_4X32: Review Comment: This generator has a native seed size of 6. ########## commons-rng-core/src/test/java/org/apache/commons/rng/core/source32/Philox4x32Test.java: ########## @@ -0,0 +1,198 @@ +/* + * 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.source32; + +import org.apache.commons.rng.UniformRandomProvider; +import org.apache.commons.rng.core.RandomAssert; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class Philox4x32Test { + + /* + * Data from python randomgen.philox.Philox(key=1234,number=4,width=32) random_raw() + * https://bashtage.github.io/randomgen/bit_generators/philox.html + */ + + private static final int[] EXPECTED_SEQUENCE_1234 = { + -1628512715, 482218876, -98078573, 343858512, 1070188760, + -66651592, -870905049, -1994573039, -1238984130, 599211371, + 1926069095, -394512546, 346514135, -352142790, 196394741, + -107436867, -903274039, 860026475, -1309487194, -1778049224, + -49503714, -1441076994, -866074276, -1339523817, -1290919251, + 1857369626, -1839251177, -2041498882, -1956330288, 905306810, + -2114083635, 200746399, 20291031, 214040874, -1628891823, + -1958807646, 9198301, -1607720479, -1349496224, 1418271217 + }; + + private static final int[] EXPECTED_SEQUENCE_DEFAULT = { + 623720234, -686991347, 358698524, 234508473, 1303720625, + 1235930736, -75297729, 110380616, 829652807, -1101240720, + -1443748750, -1366075136, -1702811520, 232450464, 350957237, + 1425642103, 256542391, 1837662153, -448554748, 637025846, + -902021712, 1085962074, -1391041963, 201580325, 1416828610, + 599210676, -628463662, -576572235, 457140358, -1026551805, + -917125498, 529387774, 1254882949, 1278069784, 724938314, + -4044975, -1211844829, -198846304, 286548119, 2085574084 + }; + + private static final int[] EXPECTED_SEQUENCE_AFTER_JUMP = { + -1941342745, 535234737, -1560986946, 1333403881, -467630828, + -1212243215, 1924495835, 1889500660, 118588722, -444471278, + -984974572, 2134204567, 620921081, -929199568, -44345645, + -346841340, -557091335, 1023562906, -1544843001, 2014718360, + -186712859, -874952234, -1016908504, 953606755, -1406346322, + -1297454974, 1426742334, 1461035068, 206733349, 1606578263, + -1354963004, -604654637, 782017623, 1501746828, 853947605, + -1380277812, 1855551741, -1023933348, -635058958, 1752530776 + }; + + private static final int[] EXPECTED_SEQUENCE_AFTER_LONG_JUMP = { + -643973534, -1464631510, -1204127809, 380399830, 1336312468, + 862647039, -970571153, -1473390944, 811398823, -598244991, + -1474151641, -1228756553, -166611808, -231601273, -2055417682, + -1102476522, 1497124960, 438167652, -657449781, -404513325, + -621271837, -10198296, -267651022, -296539606, -1564719261, + -652626768, -973911394, 1388361366, 1675611708, -1270745165, + -620748722, -1569788343, 831908952, 1873081673, -1058521087, + -26171115, -1211556401, -65210719, -1194284085, 1579466740 + }; + + @Test + void testReferenceCode() { + RandomAssert.assertEquals(EXPECTED_SEQUENCE_1234, new Philox4x32(1234L)); + } + + @Test + void testReferenceCodeDefaultSeed() { + RandomAssert.assertEquals(EXPECTED_SEQUENCE_DEFAULT, new Philox4x32(67280421310721L)); + } + + @Test + void testConstructors() { + Philox4x32[] rngs = new Philox4x32[]{ + new Philox4x32(), + new Philox4x32(67280421310721L), + new Philox4x32(new int[]{(int) 67280421310721L, (int) (67280421310721L >>> 32), 0, 0, 0, 0}) + }; + int refValue = rngs[0].next(); + for (int i = 1; i < rngs.length; i++) { + int value = rngs[i].next(); + assertEquals(refValue, value, "Philox4x32 initialization for i=" + i); + } + rngs = new Philox4x32[]{ + new Philox4x32(new int[]{1234, 0, 1}), + new Philox4x32(new int[]{1234, 0, 1, 0, 0, 0}), + }; + refValue = rngs[0].next(); + for (int i = 1; i < rngs.length; i++) { + int value = rngs[i].next(); + assertEquals(refValue, value, "Philox4x32 initialization for i=" + i); + } + rngs = new Philox4x32[]{ + new Philox4x32(1234L), + new Philox4x32(new int[]{1234}), + new Philox4x32(new int[]{1234, 0}), + new Philox4x32(new int[]{1234, 0, 0}), + new Philox4x32(new int[]{1234, 0, 0, 0}), + new Philox4x32(new int[]{1234, 0, 0, 0, 0}), + new Philox4x32(new int[]{1234, 0, 0, 0, 0, 0}), + new Philox4x32(new int[]{1234, 0, 0, 0, 0, 0, 0}), + }; + refValue = rngs[0].next(); + for (int i = 1; i < rngs.length; i++) { + int value = rngs[i].next(); + assertEquals(refValue, value, "Philox4x32 initialization for i=" + i); + } + } + + @Test + void testJump() { + RandomAssert.assertJumpEquals(EXPECTED_SEQUENCE_DEFAULT, EXPECTED_SEQUENCE_AFTER_JUMP, new Philox4x32(67280421310721L)); + } + + @Test + void testLongJump() { + RandomAssert.assertLongJumpEquals(EXPECTED_SEQUENCE_DEFAULT, EXPECTED_SEQUENCE_AFTER_LONG_JUMP, new Philox4x32(67280421310721L)); + } + + @Test + void testDouble() { Review Comment: This test is not required. Note that this test is doomed by using a `xor` of the first 21-bits for the upper (v) and the full 32-bits of the lower (w) when comparing to the `nextDouble` method which composes the most significant 26 from v with 27 from w. Anyway remove this redundant test. ########## commons-rng-core/src/test/java/org/apache/commons/rng/core/source32/Philox4x32Test.java: ########## @@ -0,0 +1,198 @@ +/* + * 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.source32; + +import org.apache.commons.rng.UniformRandomProvider; +import org.apache.commons.rng.core.RandomAssert; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class Philox4x32Test { + + /* + * Data from python randomgen.philox.Philox(key=1234,number=4,width=32) random_raw() + * https://bashtage.github.io/randomgen/bit_generators/philox.html + */ + + private static final int[] EXPECTED_SEQUENCE_1234 = { + -1628512715, 482218876, -98078573, 343858512, 1070188760, + -66651592, -870905049, -1994573039, -1238984130, 599211371, + 1926069095, -394512546, 346514135, -352142790, 196394741, + -107436867, -903274039, 860026475, -1309487194, -1778049224, + -49503714, -1441076994, -866074276, -1339523817, -1290919251, + 1857369626, -1839251177, -2041498882, -1956330288, 905306810, + -2114083635, 200746399, 20291031, 214040874, -1628891823, + -1958807646, 9198301, -1607720479, -1349496224, 1418271217 + }; + + private static final int[] EXPECTED_SEQUENCE_DEFAULT = { + 623720234, -686991347, 358698524, 234508473, 1303720625, + 1235930736, -75297729, 110380616, 829652807, -1101240720, + -1443748750, -1366075136, -1702811520, 232450464, 350957237, + 1425642103, 256542391, 1837662153, -448554748, 637025846, + -902021712, 1085962074, -1391041963, 201580325, 1416828610, + 599210676, -628463662, -576572235, 457140358, -1026551805, + -917125498, 529387774, 1254882949, 1278069784, 724938314, + -4044975, -1211844829, -198846304, 286548119, 2085574084 + }; + + private static final int[] EXPECTED_SEQUENCE_AFTER_JUMP = { + -1941342745, 535234737, -1560986946, 1333403881, -467630828, + -1212243215, 1924495835, 1889500660, 118588722, -444471278, + -984974572, 2134204567, 620921081, -929199568, -44345645, + -346841340, -557091335, 1023562906, -1544843001, 2014718360, + -186712859, -874952234, -1016908504, 953606755, -1406346322, + -1297454974, 1426742334, 1461035068, 206733349, 1606578263, + -1354963004, -604654637, 782017623, 1501746828, 853947605, + -1380277812, 1855551741, -1023933348, -635058958, 1752530776 + }; + + private static final int[] EXPECTED_SEQUENCE_AFTER_LONG_JUMP = { + -643973534, -1464631510, -1204127809, 380399830, 1336312468, + 862647039, -970571153, -1473390944, 811398823, -598244991, + -1474151641, -1228756553, -166611808, -231601273, -2055417682, + -1102476522, 1497124960, 438167652, -657449781, -404513325, + -621271837, -10198296, -267651022, -296539606, -1564719261, + -652626768, -973911394, 1388361366, 1675611708, -1270745165, + -620748722, -1569788343, 831908952, 1873081673, -1058521087, + -26171115, -1211556401, -65210719, -1194284085, 1579466740 + }; + + @Test + void testReferenceCode() { + RandomAssert.assertEquals(EXPECTED_SEQUENCE_1234, new Philox4x32(1234L)); + } + + @Test + void testReferenceCodeDefaultSeed() { + RandomAssert.assertEquals(EXPECTED_SEQUENCE_DEFAULT, new Philox4x32(67280421310721L)); + } + + @Test + void testConstructors() { + Philox4x32[] rngs = new Philox4x32[]{ + new Philox4x32(), + new Philox4x32(67280421310721L), + new Philox4x32(new int[]{(int) 67280421310721L, (int) (67280421310721L >>> 32), 0, 0, 0, 0}) + }; + int refValue = rngs[0].next(); + for (int i = 1; i < rngs.length; i++) { + int value = rngs[i].next(); + assertEquals(refValue, value, "Philox4x32 initialization for i=" + i); + } + rngs = new Philox4x32[]{ + new Philox4x32(new int[]{1234, 0, 1}), + new Philox4x32(new int[]{1234, 0, 1, 0, 0, 0}), + }; + refValue = rngs[0].next(); + for (int i = 1; i < rngs.length; i++) { + int value = rngs[i].next(); + assertEquals(refValue, value, "Philox4x32 initialization for i=" + i); + } + rngs = new Philox4x32[]{ + new Philox4x32(1234L), + new Philox4x32(new int[]{1234}), + new Philox4x32(new int[]{1234, 0}), + new Philox4x32(new int[]{1234, 0, 0}), + new Philox4x32(new int[]{1234, 0, 0, 0}), + new Philox4x32(new int[]{1234, 0, 0, 0, 0}), + new Philox4x32(new int[]{1234, 0, 0, 0, 0, 0}), + new Philox4x32(new int[]{1234, 0, 0, 0, 0, 0, 0}), + }; + refValue = rngs[0].next(); + for (int i = 1; i < rngs.length; i++) { + int value = rngs[i].next(); + assertEquals(refValue, value, "Philox4x32 initialization for i=" + i); + } + } + + @Test + void testJump() { + RandomAssert.assertJumpEquals(EXPECTED_SEQUENCE_DEFAULT, EXPECTED_SEQUENCE_AFTER_JUMP, new Philox4x32(67280421310721L)); + } + + @Test + void testLongJump() { + RandomAssert.assertLongJumpEquals(EXPECTED_SEQUENCE_DEFAULT, EXPECTED_SEQUENCE_AFTER_LONG_JUMP, new Philox4x32(67280421310721L)); + } + + @Test + void testDouble() { + Philox4x32 rng = new Philox4x32(); + final int v = rng.nextInt(); + final int w = rng.nextInt(); + final long high = Integer.toUnsignedLong(v) << 21; + final long low = Integer.toUnsignedLong(w); + double valueOpen = ((high ^ low) | 1) * 0x1.0p-53d; + rng = new Philox4x32(); + double value = rng.nextDouble(); + assertEquals(value, valueOpen, Math.pow(2, -20)); //will differ after 20bits + } + + @Test + void testInternalCounter() { + //test of incrementCounter + Philox4x32 rng = new Philox4x32(new int[]{(int) 67280421310721L, (int) (67280421310721L >>> 32), 0xffffffff, 0, 0, 0}); + for (int i = 0; i < 4; i++) { + rng.next(); + } + long value = rng.next(); + Philox4x32 rng2 = new Philox4x32(new int[]{(int) 67280421310721L, (int) (67280421310721L >>> 32), 0, 1, 0, 0}); + long value2 = rng2.next(); + assertEquals(value, value2); + + rng = new Philox4x32(new int[]{(int) 67280421310721L, (int) (67280421310721L >>> 32), 0xffffffff, 0xffffffff, 0, 0}); + for (int i = 0; i < 4; i++) { + rng.next(); + } + value = rng.next(); + rng2 = new Philox4x32(new int[]{(int) 67280421310721L, (int) (67280421310721L >>> 32), 0, 0, 1, 0}); + value2 = rng2.next(); + assertEquals(value, value2); + + rng = new Philox4x32(new int[]{(int) 67280421310721L, (int) (67280421310721L >>> 32), 0xffffffff, 0xffffffff, 0xffffffff, 0}); + for (int i = 0; i < 4; i++) { + rng.next(); + } + value = rng.next(); + rng2 = new Philox4x32(new int[]{(int) 67280421310721L, (int) (67280421310721L >>> 32), 0, 0, 0, 1}); + value2 = rng2.next(); + assertEquals(value, value2); + } + + @Test + void testLongJumpCounter() { + Philox4x32 rng = new Philox4x32(new int[]{1234, 0, 0xffffffff, 0xffffffff, 0xffffffff, 0}); + UniformRandomProvider rngOrig = rng.longJump(); Review Comment: `rngOrig` is not used. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
