63 lines
2.0 KiB
C#
63 lines
2.0 KiB
C#
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Microsoft Research Singularity
|
|
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
using System;
|
|
|
|
namespace Microsoft.Singularity.Crypto.PublicKey {
|
|
public class Random {
|
|
uint[] _state;
|
|
const int _N = 8;
|
|
void _Mix() {
|
|
uint[] square = new uint[_N];
|
|
ulong carry = 0;
|
|
for (int n = 0; n < _N; n++) {
|
|
ulong t = carry;
|
|
carry = 0;
|
|
for (int i = 0; i <= n; i++) {
|
|
int j = n - i;
|
|
t += (ulong)_state[i] * _state[j];
|
|
carry += t >> 32;
|
|
t = unchecked((uint)t);
|
|
}
|
|
square[n] = (uint)t;
|
|
carry += t >> 32;
|
|
}
|
|
square[0] |= 5;
|
|
carry = 0;
|
|
for (int i = 0; i < _N; i++) {
|
|
ulong t = carry + _state[i] + square[i];
|
|
_state[i] = unchecked((uint)t);
|
|
carry = t >> 32;
|
|
}
|
|
}
|
|
public uint Next() { _Mix(); return _state[_N - 1]; }
|
|
public uint Next(uint n) {
|
|
if (n <= 0) { throw new ArgumentException(); }
|
|
uint mask = 1;
|
|
while (mask < n - 1) { mask = mask << 1 | 1; }
|
|
while (true) {
|
|
uint next = Next() & mask;
|
|
if (next < n) { return next; }
|
|
}
|
|
}
|
|
public uint Next(uint lo, uint hi) {
|
|
if (lo >= hi) { throw new ArgumentException(); }
|
|
return lo + Next(hi - lo);
|
|
}
|
|
public Random(uint n) {
|
|
_state = new uint[_N];
|
|
for (int i = 0; i < _N; i++) {
|
|
_state[i] = n;
|
|
}
|
|
}
|
|
public Random() : this(250787849) {
|
|
// John DeTreville's Social Security Number
|
|
}
|
|
}
|
|
}
|