文件
mynode/packages/tools/fuzzer/utils/SeededRandom.ts
chen 301194963b
一些检查失败了
automerge / automerge (push) Has been cancelled
react-native-android-build-apk / AssembleRelease (push) Has been cancelled
Build macOS M1 / Main (push) Has been cancelled
Joplin Continuous Integration / Main (macos-15-intel) (push) Has been cancelled
Joplin Continuous Integration / Main (ubuntu-22.04) (push) Has been cancelled
Joplin Continuous Integration / Main (ubuntu-22.04-arm) (push) Has been cancelled
Joplin Continuous Integration / Main (windows-11-vs2026-arm) (push) Has been cancelled
Joplin Continuous Integration / Main (windows-2025) (push) Has been cancelled
Joplin Continuous Integration / ServerDockerImage (ubuntu-22.04) (push) Has been cancelled
Joplin Continuous Integration / ServerDockerImage (ubuntu-22.04-arm) (push) Has been cancelled
Joplin UI tests / Main (ubuntu-22.04) (push) Has been cancelled
Joplin UI tests / Main (windows-2025) (push) Has been cancelled
Joplin UI tests / Mobile (push) Has been cancelled
Close stale issues / ProcessStaleIssues (push) Has been cancelled
feat: Initial clean release of CHM
2026-11-04 11:29:39 +08:00

71 行
1.9 KiB
TypeScript

// SeededRandom provides a very simple random number generator
// that can be seeded (since NodeJS built-ins can't).
//
// See also:
// - https://arxiv.org/pdf/1704.00358
// - https://en.wikipedia.org/wiki/Middle-square_method
// Some large odd number, see https://en.wikipedia.org/wiki/Weyl_sequence
const step = BigInt('0x12345678ABCDE123'); // uint64
const maxSize = BigInt(1) << BigInt(64);
const extractMiddle = (value: bigint, halfSize: bigint) => {
// Remove the lower quarter
const quarterSize = halfSize / BigInt(2);
value >>= quarterSize;
// Remove the upper quarter
const halfMaximumValue = BigInt(1) << halfSize;
value %= halfMaximumValue;
return value;
};
export interface RandomState {
value: bigint|string;
step: bigint|string;
}
export default class SeededRandom {
private value_: bigint;
private nextStep_: bigint = step;
private halfSize_ = BigInt(32);
public constructor(
seed: number|bigint|string,
) {
this.value_ = typeof seed !== 'bigint' ? BigInt(seed) : seed;
}
public static fromState({ value, step }: RandomState) {
const random = new SeededRandom(value);
random.nextStep_ = typeof step !== 'bigint' ? BigInt(step) : step;
return random;
}
// Returns a state that can be used to save/restore this random number generator.
public get state(): RandomState {
return { value: this.value_, step: this.nextStep_ };
}
public next() {
this.value_ = this.value_ * this.value_ + this.nextStep_;
// Move to the next item in the sequence. Mod to prevent from getting
// too large. See https://en.wikipedia.org/wiki/Weyl_sequence.
this.nextStep_ = (step + this.nextStep_) % maxSize;
this.value_ = extractMiddle(this.value_, this.halfSize_);
return this.value_;
}
// The resultant range includes `a` but excludes `b`.
public nextInRange(a: number, b: number) {
if (b <= a + 1) return a;
const range = b - a;
return Number(this.next() % BigInt(range)) + a;
}
}