1 /* 2 * License : The MIT License 3 * Copyright(c) 2022 Olyutorskii 4 */ 5 6 package io.github.olyutorskii.aletojio.rng.mwc; 7 8 /** 9 * Complementary-multiply-with-carry random number generator. 10 * 11 * <p>Random sequence X(n) is derived as follows with parameter a(multiplier), b(divisor). 12 * <ul> 13 * <li>{@code T(n) = a * X(n-r) + C(n-1)} 14 * <li>{@code C(n) = T(n) / b} 15 * <li>{@code Y(n) = T(n) mod b} 16 * <li>{@code X(n) = b - 1 - Y(n)} 17 * </ul> 18 * 19 * <p>r is the length of the record that stores past results. 20 * "carry" comes from C(n-1). 21 * 22 * @see <a href="https://en.wikipedia.org/wiki/Multiply-with-carry_pseudorandom_number_generator"> 23 * Multiply-with-carry pseudorandom number generator (Wikipedia) 24 * </a> 25 */ 26 public class Cmwc extends Mwc { 27 28 private static final int DEF_RECORDS = 1024; 29 private static final long DEF_MULTIPLIER = 987769338L; 30 private static final long DEF_DIVISOR = (1L << 32) - 1L; 31 32 33 private final long minuend; 34 35 36 /** 37 * Constructor. 38 * 39 * <ul> 40 * <li>record length must be greater than 0. 41 * <li>multiplier must be greater than 1. 42 * <li>divisor must be greater than 1. 43 * </ul> 44 * 45 * <p>If you want 32-bit uniformly distributed random numbers, 46 * the divisor must be 2**32, but you can compromise with 2**32 -1. 47 * 48 * @param recLen records length 49 * @param mulArg multiplier 50 * @param divArg divisor 51 * @throws IllegalArgumentException illegal argument 52 */ 53 public Cmwc(int recLen, long mulArg, long divArg) throws IllegalArgumentException { 54 super(recLen, mulArg, divArg); 55 this.minuend = divArg - 1; 56 return; 57 } 58 59 /** 60 * Constructor. 61 * 62 * <ul> 63 * <li>Default record length = 1024 64 * <li>Default multiplier value = 987769338 65 * <li>Default divisor value = 2**32 - 1 66 * </ul> 67 * 68 * <p>* Caution : If you don't provide your entropy to seeds, 69 * it takes over million trials until the seed is scrambled. 70 * 71 * @throws IllegalArgumentException illegal argument 72 * @see <a href="http://digitalcommons.wayne.edu/cgi/viewcontent.cgi?article=1725&context=jmasm"> 73 * Random Number Generators 74 * </a> 75 */ 76 public Cmwc() throws IllegalArgumentException { 77 this(DEF_RECORDS, DEF_MULTIPLIER, DEF_DIVISOR); 78 // this(4, 987654978L, (1L << 32) - 1L); 79 // this(8, 987651670L, (1L << 32) - 1L); 80 // this(2048, 1047570L, (1L << 32) - 1L); 81 // this(4096, 18782L, (1L << 32) - 1L); 82 // this(42658, 15455296L, 1L << 32); 83 return; 84 } 85 86 87 /** 88 * {@inheritDoc} 89 * 90 * @param tVal {@inheritDoc} 91 * @return {@inheritDoc} 92 */ 93 @Override 94 protected int funcRndFromTval(long tVal) { 95 long lVal = this.minuend - super.funcRndFromTval(tVal); 96 int result = (int) lVal; 97 return result; 98 } 99 100 }