/* * Encog(tm) Core v3.4 - Java Version * http://www.heatonresearch.com/encog/ * https://github.com/encog/encog-java-core * Copyright 2008-2016 Heaton Research, Inc. * * Licensed 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. * * For more information on Heaton Research copyrights, licenses * and trademarks visit: * http://www.heatonresearch.com/copyright */ package org.encog.mathutil.randomize.generate; /** * In Multiply with Carry (MWC) is a pseudo random number generator computer science, multiply-with-carry (MWC) * is a method invented by George Marsaglia for generating sequences of random integers based on an initial set * from two to many thousands of randomly chosen seed values. The main advantages of the MWC method are that it * invokes simple computer integer arithmetic and leads to very fast generation of sequences of random numbers * with immense periods. * * This class was implemented using information from the following sources: * @see <a href="http://www.javaprogrammingforums.com/blogs/helloworld922/11-complimentary-multiply-carry-better-way-generate-pseudo-random-numbers.html"></a> * @see <a href="http://en.wikipedia.org/wiki/Multiply-with-carry"></a> */ public class MultiplyWithCarryGenerateRandom extends AbstractBoxMuller { private long c; private long multiplier; private int n = 0; private int r; private final long[] seed; public MultiplyWithCarryGenerateRandom(final long seed) { this(new long[]{seed}, seed / 2, 64, 987657110L); } public MultiplyWithCarryGenerateRandom() { this(new long[]{System.currentTimeMillis()}, System.nanoTime(), 64, 987657110L); } public MultiplyWithCarryGenerateRandom(long[] seeds, final long carry, final int r, final long multiplier) { setR(r); setMultiplier(multiplier); this.seed = new long[r]; if (seeds == null || seeds.length == 0) { seeds = new long[]{System.currentTimeMillis()}; } final LinearCongruentialRandom rnd = new LinearCongruentialRandom(seeds[0]); this.c = (carry & 0xFFFFFFFFL) % multiplier; for (int i = 0; i < r; ++i) { if (i < seeds.length) { this.seed[i] = seeds[i] & 0xFFFFFFFFL; } else { this.seed[i] = rnd.nextInt() & 0xFFFFFFFFL; } if (this.seed[i] == 0xFFFFFFFFL) { this.seed[i] = 1L; } } } /** * {@inheritDoc} */ @Override public double nextDouble() { return (((long) next(26) << 27) + next(27)) / (double) (1L << 53); } private int next(final int bits) { final long t = multiplier * seed[n] + c; final long d32 = t >>> 32; c = d32 + ((t & 0xFFFFFFFFL) >= 0xFFFFFFFFL - d32 ? 1L : 0L); seed[n] = 0xFFFFFFFEL - (t & 0xFFFFFFFFL) - (c - d32 << 32) - c & 0xFFFFFFFFL; final long result = seed[n]; n = n + 1 & r - 1; return (int) (result >>> 32 - bits); } private void setMultiplier(final long theMultiplier) { this.multiplier = theMultiplier; } private void setR(int theR) { if (theR <= 0) { theR = 256; } else { boolean validR = true; long a = theR; while (a != 1 && validR) { if (a % 2 != 0) { theR = 256; validR = false; } a >>>= 1; } } this.r = theR; } /** * {@inheritDoc} */ @Override public long nextLong() { return ((long) next(32) << 32) + next(32); } /** * {@inheritDoc} */ @Override public boolean nextBoolean() { return nextDouble() > 0.5; } /** * {@inheritDoc} */ @Override public float nextFloat() { return (float) nextDouble(); } /** * {@inheritDoc} */ @Override public int nextInt() { return (int) nextLong(); } }