singrdk/base/Libraries/Crypto/Random.cs

68 lines
2.1 KiB
C#
Raw Permalink Normal View History

2008-11-17 18:29:00 -05:00
// ----------------------------------------------------------------------------
2008-03-05 09:52:00 -05:00
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
2008-11-17 18:29:00 -05:00
// ----------------------------------------------------------------------------
2008-03-05 09:52:00 -05:00
using System;
2008-11-17 18:29:00 -05:00
namespace Microsoft.Singularity.Crypto.PublicKey
{
2008-03-05 09:52:00 -05:00
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) {
2008-11-17 18:29:00 -05:00
if (n <= 0) {
throw new ArgumentException();
}
2008-03-05 09:52:00 -05:00
uint mask = 1;
2008-11-17 18:29:00 -05:00
while (mask < n - 1) {
mask = mask << 1 | 1;
}
2008-03-05 09:52:00 -05:00
while (true) {
uint next = Next() & mask;
2008-11-17 18:29:00 -05:00
if (next < n) {
return next;
}
2008-03-05 09:52:00 -05:00
}
}
public uint Next(uint lo, uint hi) {
2008-11-17 18:29:00 -05:00
if (lo >= hi) {
throw new ArgumentException();
}
2008-03-05 09:52:00 -05:00
return lo + Next(hi - lo);
}
public Random(uint n) {
_state = new uint[_N];
for (int i = 0; i < _N; i++) {
_state[i] = n;
}
}
2008-11-17 18:29:00 -05:00
public Random() : this(1372455507) { } // Randomly selected 32-bit integer
2008-03-05 09:52:00 -05:00
}
}