Skip to content

Commit

Permalink
Fixing PseudoRandom
Browse files Browse the repository at this point in the history
  • Loading branch information
Gekctek committed Oct 27, 2023
1 parent a6802df commit ed4df18
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 32 deletions.
12 changes: 7 additions & 5 deletions src/PsuedoRandomX.mo → src/PseudoRandomX.mo
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,27 @@ import Nat32 "mo:base/Nat32";

module Module {

public type PsuedoRandomGenerator = {
public type PseudoRandomGenerator = {
nextInt : (min : Int, max : Int) -> Int;
nextNat : (min : Nat, max : Nat) -> Nat;
nextCoin : () -> Bool;
nextRatio : (trueCount : Nat, totalCount : Nat) -> Bool;
shuffleBuffer : <T>(buffer : Buffer.Buffer<T>) -> ();
};

public func fromSeed(seed : Nat32) : PsuedoRandomGenerator {
public func fromSeed(seed : Nat32) : PseudoRandomGenerator {
LinearCongruentialGenerator(seed);
};

public class LinearCongruentialGenerator(seed : Nat32) : PsuedoRandomGenerator {
public class LinearCongruentialGenerator(seed : Nat32) : PseudoRandomGenerator {
var currentValue = seed;
let a : Nat32 = 1664525;
let c : Nat32 = 1013904223;

public func nextSeed() : Nat32 {
currentValue := a * currentValue + c; // Overflow is ok
private func nextSeed() : Nat32 {
currentValue := currentValue
|> Nat32.mulWrap(a, _)
|> Nat32.addWrap(_, c); // Overflow is ok
return currentValue;
};

Expand Down
51 changes: 24 additions & 27 deletions test/RandomX.test.mo
Original file line number Diff line number Diff line change
Expand Up @@ -2,74 +2,71 @@ import Iter "mo:base/Iter";
import { test } "mo:test";
import Debug "mo:base/Debug";
import Int "mo:base/Int";
import RandomX "../src/RandomX";
import PseudoRandomX "../src/PseudoRandomX";

let assertEqualInt = func(expected : Int, actual : ?Int) : () {
if (actual != ?expected) {
switch (actual) {
case (null) Debug.trap("Expected " # Int.toText(expected) # ", but ran out of entropy.");
case (?i) Debug.trap("Expected " # Int.toText(expected) # ", got " # Int.toText(i));
};
let assertEqualInt = func(expected : Int, actual : Int) : () {
if (actual != expected) {
Debug.trap("Expected " # Int.toText(expected) # ", got " # Int.toText(actual));
};
};

test(
"int",
"nextInt",
func() {
let testCases : [{ seed : Blob; expected : Int; min : Int; max : Int }] = [
let testCases : [{ seed : Nat32; expected : Int; min : Int; max : Int }] = [
{
seed = "\A1\B2\C3\D4\E5\F6\10\11\12\13\14\15\16\17\18\19\1A\1B\1C\1D\1E\1F\20\21\22\23\24\25\26\27\1A\1B\1C\1D\1E\1F\20\21\22\23\24\25\26\27\1A\1B\1C\1D\1E\1F\20\21\22\23\24\25\26\27\1A\1B\1C\1D\1E\1F\20\21\22\23\24\25\26\27\1A\1B\1C\1D\1E\1F\20\21\22\23\24\25\26\27\1A\1B\1C\1D\1E\1F\20\21\22\23\24\25\26\27\1A\1B\1C\1D\1E\1F\20\21\22\23\24\25\26\27\1A\1B\1C\1D\1E\1F\20\21\22\23\24\25\26\27";
expected = 1;
seed = 1;
expected = 7;
min = 0;
max = 10;
},
{
seed = "\A1\B2\C8\D4\E5\F6\10\11\12\13\14\15\16\17\18\19\1A\1B\1C\1D\1E\1F\20\21\22\23\24\25\26\27\1A\1B\1C\1D\1E\1F\20\21\22\23\24\25\26\27\1A\1B\1C\1D\1E\1F\20\21\22\23\24\25\26\27\1A\1B\1C\1D\1E\1F\20\21\22\23\24\25\26\27\1A\1B\1C\1D\1E\1F\20\21\22\23\24\25\26\27\1A\1B\1C\1D\1E\1F\20\21\22\23\24\25\26\27\1A\1B\1C\1D\1E\1F\20\21\22\23\24\25\26\27\1A\1B\1C\1D\1E\1F\20\21\22\23\24\25\26\27";
expected = -3;
seed = 2;
expected = -1;
min = -4;
max = 5;
},
{
seed = "\A1\B2\C8\D4\E5\F6\10\11\12\13\14\15\16\17\18\19\1A\1B\1C\1D\1E\1F\20\21\22\23\24\25\26\27\1A\1B\1C\1D\1E\1F\20\21\22\23\24\25\26\27\1A\1B\1C\1D\1E\1F\20\21\22\23\24\25\26\27\1A\1B\1C\1D\1E\1F\20\21\22\23\24\25\26\27\1A\1B\1C\1D\1E\1F\20\21\22\23\24\25\26\27\1A\1B\1C\1D\1E\1F\20\21\22\23\24\25\26\27\1A\1B\1C\1D\1E\1F\20\21\22\23\24\25\26\27\1A\1B\1C\1D\1E\1F\20\21\22\23\24\25\26\27";
expected = 711156982585303;
seed = 3;
expected = 1018897797;
min = -1;
max = 1_000_000_000_000_000;
},
];
for (testCase in Iter.fromArray(testCases)) {
let rand = RandomX.fromSeed(testCase.seed);
let randInt = rand.int(testCase.min, testCase.max);
let rand = PseudoRandomX.fromSeed(testCase.seed);
let randInt = rand.nextInt(testCase.min, testCase.max);
assertEqualInt(testCase.expected, randInt);
};
},
);

test(
"nat",
"nextNat",
func() {
let testCases : [{ seed : Blob; expected : Nat; min : Nat; max : Nat }] = [
let testCases : [{ seed : Nat32; expected : Nat; min : Nat; max : Nat }] = [
{
seed = "\A1\B2\C3\D4\E5\F6\10\11\12\13\14\15\16\17\18\19\1A\1B\1C\1D\1E\1F\20\21\22\23\24\25\26\27\1A\1B\1C\1D\1E\1F\20\21\22\23\24\25\26\27\1A\1B\1C\1D\1E\1F\20\21\22\23\24\25\26\27\1A\1B\1C\1D\1E\1F\20\21\22\23\24\25\26\27\1A\1B\1C\1D\1E\1F\20\21\22\23\24\25\26\27\1A\1B\1C\1D\1E\1F\20\21\22\23\24\25\26\27\1A\1B\1C\1D\1E\1F\20\21\22\23\24\25\26\27\1A\1B\1C\1D\1E\1F\20\21\22\23\24\25\26\27";
expected = 1;
seed = 1;
expected = 7;
min = 0;
max = 10;
},
{
seed = "\A1\B2\C8\D4\E5\F6\10\11\12\13\14\15\16\17\18\19\1A\1B\1C\1D\1E\1F\20\21\22\23\24\25\26\27\1A\1B\1C\1D\1E\1F\20\21\22\23\24\25\26\27\1A\1B\1C\1D\1E\1F\20\21\22\23\24\25\26\27\1A\1B\1C\1D\1E\1F\20\21\22\23\24\25\26\27\1A\1B\1C\1D\1E\1F\20\21\22\23\24\25\26\27\1A\1B\1C\1D\1E\1F\20\21\22\23\24\25\26\27\1A\1B\1C\1D\1E\1F\20\21\22\23\24\25\26\27\1A\1B\1C\1D\1E\1F\20\21\22\23\24\25\26\27";
expected = 2;
seed = 2;
expected = 4;
min = 1;
max = 5;
},
{
seed = "\A1\B2\C8\D4\E5\F6\10\11\12\13\14\15\16\17\18\19\1A\1B\1C\1D\1E\1F\20\21\22\23\24\25\26\27\1A\1B\1C\1D\1E\1F\20\21\22\23\24\25\26\27\1A\1B\1C\1D\1E\1F\20\21\22\23\24\25\26\27\1A\1B\1C\1D\1E\1F\20\21\22\23\24\25\26\27\1A\1B\1C\1D\1E\1F\20\21\22\23\24\25\26\27\1A\1B\1C\1D\1E\1F\20\21\22\23\24\25\26\27\1A\1B\1C\1D\1E\1F\20\21\22\23\24\25\26\27\1A\1B\1C\1D\1E\1F\20\21\22\23\24\25\26\27";
expected = 711156982685303;
seed = 3;
expected = 1018997797;
min = 99999;
max = 1_000_000_000_000_000;
},
];
for (testCase in Iter.fromArray(testCases)) {
let rand = RandomX.fromSeed(testCase.seed);
let randInt = rand.nat(testCase.min, testCase.max);
let rand = PseudoRandomX.fromSeed(testCase.seed);
let randInt = rand.nextNat(testCase.min, testCase.max);
assertEqualInt(testCase.expected, randInt);
};
},
Expand Down

0 comments on commit ed4df18

Please sign in to comment.