private static void SeekStateInternal(ref uint state0, ref uint state1, ulong offset, bool reverse) { if (offset >= _MaximumPeriod) { offset %= _MaximumPeriod; } if (offset == 0) { return; } { MyUInt256 aexpn = new MyUInt256(reverse ? _Multiplier0Inverse : _Multiplier0); aexpn.ExpMod(offset, new MyUInt256(_Modulus)); state0 = unchecked ((uint)((aexpn.ToUInt64() * state0) % _Modulus)); } { MyUInt256 aexpn = new MyUInt256(reverse ? _Multiplier1Inverse : _Multiplier1); aexpn.ExpMod(offset, new MyUInt256(_Modulus1)); state1 = unchecked ((uint)((aexpn.ToUInt64() * state1) % _Modulus1)); } }
/// <summary> /// Computes the state at the specified position in the pseudorandom stream relative to a given initial state. /// </summary> /// <param name="state">The state at position zero in the stream.</param> /// <param name="offset">The number of states to skip.</param> /// <param name="multiplier">The linear congruential generator's multiplier constant, or its multiplicative inverse modulo <paramref name="divisor"/> to go backwards.</param> /// <param name="increment">The linear congruential generator's increment constant, /// or its additive inverse modulo <paramref name="divisor"/> multiplied by the multiplicative inverse to go backwards.</param> /// <param name="divisor">The linear congruential generator's modulus constant.</param> /// <returns>The state at position <paramref name="offset"/> in the stream.</returns> protected static ulong SeekState(ulong state, ulong offset, ulong multiplier, ulong increment, ulong divisor) { // NewState = (Multiplier**Offset * OldState) + Increment * (Multiplier**Offset - 1) / (Multiplier - 1) // caller can substitute Multiplier**-1 and -Increment * Multiplier**-1 to go backwards if (offset == 0) { return(state); } if (multiplier == 0) { return(increment); } else if (multiplier == 1) { MyUInt256 product = new MyUInt256(increment); product.Multiply(offset); if (divisor != 0) { product.Modulo(divisor); } return(product.ToUInt64()); } MyUInt256 compdivisor = new MyUInt256(divisor); if (divisor == 0) { compdivisor.Set(0, 1); } compdivisor.Multiply(multiplier - 1); MyUInt256 aexpn = new MyUInt256(multiplier); aexpn.ExpMod(offset, compdivisor); // = Multiplier**Offset MyUInt256 fraction = new MyUInt256(aexpn); fraction.Subtract(1); fraction.Divide(multiplier - 1); // should always divide evenly; that's why divisor has to include (Multiplier - 1) factor though fraction.Multiply(increment); // = Increment * (Multiplier**Offset - 1) / (Multiplier - 1) MyUInt256 newstate = new MyUInt256(state); newstate.Multiply(aexpn); // = Multiplier**Offset * OldState newstate.Add(fraction); // = (Multiplier**Offset * OldState) + Increment * (Multiplier**Offset - 1) / (Multiplier - 1) if (divisor != 0) { newstate.Modulo(divisor); // now that we've divided by (Multiplier - 1), we can go back to using 'divisor' instead of 'compdivisor' } return(newstate.ToUInt64()); } //PrngLcgBase.SeekState
/// <summary> /// Computes the state at the specified position in the pseudorandom stream relative to a given initial state. /// </summary> /// <param name="state">The state at position zero in the stream.</param> /// <param name="offset">The number of states to skip.</param> /// <param name="multiplier">The linear congruential generator's multiplier constant, or its multiplicative inverse modulo <paramref name="divisor"/> to go backwards.</param> /// <param name="divisor">The linear congruential generator's modulus constant.</param> /// <returns>The state at position <paramref name="offset"/> in the stream.</returns> protected static ulong SeekState(ulong state, ulong offset, ulong multiplier, ulong divisor) { // NewState = (Multiplier**Offset * OldState) // caller can substitute Multiplier**-1 to go backwards if (offset == 0) { return(state); } MyUInt256 fullmodulus = (divisor == 0 ? new MyUInt256(0, 1) : new MyUInt256(divisor)); MyUInt256 aexpn = new MyUInt256(multiplier); aexpn.ExpMod(offset, fullmodulus); aexpn.Multiply(state); if (divisor != 0) { aexpn.Modulo(fullmodulus); } return(aexpn.ToUInt64()); } //PrngLehmerBase.SeekState
private static void SeekStateInternal(ref uint state0, ref uint state1, ulong offset, bool reverse) { if (offset >= _MaximumPeriod) offset %= _MaximumPeriod; if (offset == 0) return; { MyUInt256 aexpn = new MyUInt256(reverse ? _Multiplier0Inverse : _Multiplier0); aexpn.ExpMod(offset, new MyUInt256(_Modulus)); state0 = unchecked((uint)((aexpn.ToUInt64() * state0) % _Modulus)); } { MyUInt256 aexpn = new MyUInt256(reverse ? _Multiplier1Inverse : _Multiplier1); aexpn.ExpMod(offset, new MyUInt256(_Modulus1)); state1 = unchecked((uint)((aexpn.ToUInt64() * state1) % _Modulus1)); } }
/// <summary> /// Computes the state at the specified position in the pseudorandom stream relative to a given initial state. /// </summary> /// <param name="state">The state at position zero in the stream.</param> /// <param name="offset">The number of states to skip.</param> /// <param name="multiplier">The linear congruential generator's multiplier constant, or its multiplicative inverse modulo <paramref name="divisor"/> to go backwards.</param> /// <param name="divisor">The linear congruential generator's modulus constant.</param> /// <returns>The state at position <paramref name="offset"/> in the stream.</returns> protected static ulong SeekState(ulong state, ulong offset, ulong multiplier, ulong divisor) { // NewState = (Multiplier**Offset * OldState) // caller can substitute Multiplier**-1 to go backwards if (offset == 0) return state; MyUInt256 fullmodulus = (divisor == 0 ? new MyUInt256(0, 1) : new MyUInt256(divisor)); MyUInt256 aexpn = new MyUInt256(multiplier); aexpn.ExpMod(offset, fullmodulus); aexpn.Multiply(state); if (divisor != 0) aexpn.Modulo(fullmodulus); return aexpn.ToUInt64(); }
/// <summary> /// Computes the state at the specified position in the pseudorandom stream relative to a given initial state. /// </summary> /// <param name="state">The state at position zero in the stream.</param> /// <param name="offset">The number of states to skip.</param> /// <param name="multiplier">The linear congruential generator's multiplier constant, or its multiplicative inverse modulo <paramref name="divisor"/> to go backwards.</param> /// <param name="increment">The linear congruential generator's increment constant, /// or its additive inverse modulo <paramref name="divisor"/> multiplied by the multiplicative inverse to go backwards.</param> /// <param name="divisor">The linear congruential generator's modulus constant.</param> /// <returns>The state at position <paramref name="offset"/> in the stream.</returns> protected static ulong SeekState(ulong state, ulong offset, ulong multiplier, ulong increment, ulong divisor) { // NewState = (Multiplier**Offset * OldState) + Increment * (Multiplier**Offset - 1) / (Multiplier - 1) // caller can substitute Multiplier**-1 and -Increment * Multiplier**-1 to go backwards if (offset == 0) return state; if (multiplier == 0) { return increment; } else if (multiplier == 1) { MyUInt256 product = new MyUInt256(increment); product.Multiply(offset); if (divisor != 0) product.Modulo(divisor); return product.ToUInt64(); } MyUInt256 compdivisor = new MyUInt256(divisor); if (divisor == 0) compdivisor.Set(0, 1); compdivisor.Multiply(multiplier - 1); MyUInt256 aexpn = new MyUInt256(multiplier); aexpn.ExpMod(offset, compdivisor); // = Multiplier**Offset MyUInt256 fraction = new MyUInt256(aexpn); fraction.Subtract(1); fraction.Divide(multiplier - 1); // should always divide evenly; that's why divisor has to include (Multiplier - 1) factor though fraction.Multiply(increment); // = Increment * (Multiplier**Offset - 1) / (Multiplier - 1) MyUInt256 newstate = new MyUInt256(state); newstate.Multiply(aexpn); // = Multiplier**Offset * OldState newstate.Add(fraction); // = (Multiplier**Offset * OldState) + Increment * (Multiplier**Offset - 1) / (Multiplier - 1) if (divisor != 0) newstate.Modulo(divisor); // now that we've divided by (Multiplier - 1), we can go back to using 'divisor' instead of 'compdivisor' return newstate.ToUInt64(); }