374 lines
9.3 KiB
JavaScript
374 lines
9.3 KiB
JavaScript
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
exports.structuralRegionState = exports.structuralRegion = exports.makeGenKind = exports.isGeneratorFunction = exports.isGenKind = exports.internalCall = exports.adapter = exports.YieldWrapTypeId = exports.YieldWrap = exports.SingleShotGen = exports.PCGRandom = exports.GenKindTypeId = exports.GenKindImpl = void 0;
|
|
exports.yieldWrapGet = yieldWrapGet;
|
|
var _Function = require("./Function.js");
|
|
var _GlobalValue = require("./GlobalValue.js");
|
|
var _errors = require("./internal/errors.js");
|
|
var _Predicate = require("./Predicate.js");
|
|
/**
|
|
* @since 2.0.0
|
|
*/
|
|
|
|
/*
|
|
* Copyright 2014 Thom Chiovoloni, released under the MIT license.
|
|
*
|
|
* A random number generator based on the basic implementation of the PCG algorithm,
|
|
* as described here: http://www.pcg-random.org/
|
|
*
|
|
* Adapted for TypeScript from Thom's original code at https://github.com/thomcc/pcg-random
|
|
*
|
|
* forked from https://github.com/frptools
|
|
*
|
|
* @since 2.0.0
|
|
*/
|
|
/**
|
|
* @category symbols
|
|
* @since 2.0.0
|
|
*/
|
|
const GenKindTypeId = exports.GenKindTypeId = /*#__PURE__*/Symbol.for("effect/Gen/GenKind");
|
|
/**
|
|
* @category predicates
|
|
* @since 3.0.6
|
|
*/
|
|
const isGenKind = u => (0, _Predicate.isObject)(u) && GenKindTypeId in u;
|
|
/**
|
|
* @category constructors
|
|
* @since 2.0.0
|
|
*/
|
|
exports.isGenKind = isGenKind;
|
|
class GenKindImpl {
|
|
value;
|
|
constructor(
|
|
/**
|
|
* @since 2.0.0
|
|
*/
|
|
value) {
|
|
this.value = value;
|
|
}
|
|
/**
|
|
* @since 2.0.0
|
|
*/
|
|
get _F() {
|
|
return _Function.identity;
|
|
}
|
|
/**
|
|
* @since 2.0.0
|
|
*/
|
|
get _R() {
|
|
return _ => _;
|
|
}
|
|
/**
|
|
* @since 2.0.0
|
|
*/
|
|
get _O() {
|
|
return _ => _;
|
|
}
|
|
/**
|
|
* @since 2.0.0
|
|
*/
|
|
get _E() {
|
|
return _ => _;
|
|
}
|
|
/**
|
|
* @since 2.0.0
|
|
*/
|
|
[GenKindTypeId] = GenKindTypeId;
|
|
/**
|
|
* @since 2.0.0
|
|
*/
|
|
[Symbol.iterator]() {
|
|
return new SingleShotGen(this);
|
|
}
|
|
}
|
|
/**
|
|
* @category constructors
|
|
* @since 2.0.0
|
|
*/
|
|
exports.GenKindImpl = GenKindImpl;
|
|
class SingleShotGen {
|
|
self;
|
|
called = false;
|
|
constructor(self) {
|
|
this.self = self;
|
|
}
|
|
/**
|
|
* @since 2.0.0
|
|
*/
|
|
next(a) {
|
|
return this.called ? {
|
|
value: a,
|
|
done: true
|
|
} : (this.called = true, {
|
|
value: this.self,
|
|
done: false
|
|
});
|
|
}
|
|
/**
|
|
* @since 2.0.0
|
|
*/
|
|
return(a) {
|
|
return {
|
|
value: a,
|
|
done: true
|
|
};
|
|
}
|
|
/**
|
|
* @since 2.0.0
|
|
*/
|
|
throw(e) {
|
|
throw e;
|
|
}
|
|
/**
|
|
* @since 2.0.0
|
|
*/
|
|
[Symbol.iterator]() {
|
|
return new SingleShotGen(this.self);
|
|
}
|
|
}
|
|
/**
|
|
* @category constructors
|
|
* @since 2.0.0
|
|
*/
|
|
exports.SingleShotGen = SingleShotGen;
|
|
const makeGenKind = kind => new GenKindImpl(kind);
|
|
/**
|
|
* @category adapters
|
|
* @since 2.0.0
|
|
*/
|
|
exports.makeGenKind = makeGenKind;
|
|
const adapter = () => function () {
|
|
let x = arguments[0];
|
|
for (let i = 1; i < arguments.length; i++) {
|
|
x = arguments[i](x);
|
|
}
|
|
return new GenKindImpl(x);
|
|
};
|
|
exports.adapter = adapter;
|
|
const defaultIncHi = 0x14057b7e;
|
|
const defaultIncLo = 0xf767814f;
|
|
const MUL_HI = 0x5851f42d >>> 0;
|
|
const MUL_LO = 0x4c957f2d >>> 0;
|
|
const BIT_53 = 9007199254740992.0;
|
|
const BIT_27 = 134217728.0;
|
|
/**
|
|
* PCG is a family of simple fast space-efficient statistically good algorithms
|
|
* for random number generation. Unlike many general-purpose RNGs, they are also
|
|
* hard to predict.
|
|
*
|
|
* @category model
|
|
* @since 2.0.0
|
|
*/
|
|
class PCGRandom {
|
|
_state;
|
|
constructor(seedHi, seedLo, incHi, incLo) {
|
|
if ((0, _Predicate.isNullable)(seedLo) && (0, _Predicate.isNullable)(seedHi)) {
|
|
seedLo = Math.random() * 0xffffffff >>> 0;
|
|
seedHi = 0;
|
|
} else if ((0, _Predicate.isNullable)(seedLo)) {
|
|
seedLo = seedHi;
|
|
seedHi = 0;
|
|
}
|
|
if ((0, _Predicate.isNullable)(incLo) && (0, _Predicate.isNullable)(incHi)) {
|
|
incLo = this._state ? this._state[3] : defaultIncLo;
|
|
incHi = this._state ? this._state[2] : defaultIncHi;
|
|
} else if ((0, _Predicate.isNullable)(incLo)) {
|
|
incLo = incHi;
|
|
incHi = 0;
|
|
}
|
|
this._state = new Int32Array([0, 0, incHi >>> 0, ((incLo || 0) | 1) >>> 0]);
|
|
this._next();
|
|
add64(this._state, this._state[0], this._state[1], seedHi >>> 0, seedLo >>> 0);
|
|
this._next();
|
|
return this;
|
|
}
|
|
/**
|
|
* Returns a copy of the internal state of this random number generator as a
|
|
* JavaScript Array.
|
|
*
|
|
* @category getters
|
|
* @since 2.0.0
|
|
*/
|
|
getState() {
|
|
return [this._state[0], this._state[1], this._state[2], this._state[3]];
|
|
}
|
|
/**
|
|
* Restore state previously retrieved using `getState()`.
|
|
*
|
|
* @since 2.0.0
|
|
*/
|
|
setState(state) {
|
|
this._state[0] = state[0];
|
|
this._state[1] = state[1];
|
|
this._state[2] = state[2];
|
|
this._state[3] = state[3] | 1;
|
|
}
|
|
/**
|
|
* Get a uniformly distributed 32 bit integer between [0, max).
|
|
*
|
|
* @category getter
|
|
* @since 2.0.0
|
|
*/
|
|
integer(max) {
|
|
return Math.round(this.number() * Number.MAX_SAFE_INTEGER) % max;
|
|
}
|
|
/**
|
|
* Get a uniformly distributed IEEE-754 double between 0.0 and 1.0, with
|
|
* 53 bits of precision (every bit of the mantissa is randomized).
|
|
*
|
|
* @category getters
|
|
* @since 2.0.0
|
|
*/
|
|
number() {
|
|
const hi = (this._next() & 0x03ffffff) * 1.0;
|
|
const lo = (this._next() & 0x07ffffff) * 1.0;
|
|
return (hi * BIT_27 + lo) / BIT_53;
|
|
}
|
|
/** @internal */
|
|
_next() {
|
|
// save current state (what we'll use for this number)
|
|
const oldHi = this._state[0] >>> 0;
|
|
const oldLo = this._state[1] >>> 0;
|
|
// churn LCG.
|
|
mul64(this._state, oldHi, oldLo, MUL_HI, MUL_LO);
|
|
add64(this._state, this._state[0], this._state[1], this._state[2], this._state[3]);
|
|
// get least sig. 32 bits of ((oldstate >> 18) ^ oldstate) >> 27
|
|
let xsHi = oldHi >>> 18;
|
|
let xsLo = (oldLo >>> 18 | oldHi << 14) >>> 0;
|
|
xsHi = (xsHi ^ oldHi) >>> 0;
|
|
xsLo = (xsLo ^ oldLo) >>> 0;
|
|
const xorshifted = (xsLo >>> 27 | xsHi << 5) >>> 0;
|
|
// rotate xorshifted right a random amount, based on the most sig. 5 bits
|
|
// bits of the old state.
|
|
const rot = oldHi >>> 27;
|
|
const rot2 = (-rot >>> 0 & 31) >>> 0;
|
|
return (xorshifted >>> rot | xorshifted << rot2) >>> 0;
|
|
}
|
|
}
|
|
exports.PCGRandom = PCGRandom;
|
|
function mul64(out, aHi, aLo, bHi, bLo) {
|
|
let c1 = (aLo >>> 16) * (bLo & 0xffff) >>> 0;
|
|
let c0 = (aLo & 0xffff) * (bLo >>> 16) >>> 0;
|
|
let lo = (aLo & 0xffff) * (bLo & 0xffff) >>> 0;
|
|
let hi = (aLo >>> 16) * (bLo >>> 16) + ((c0 >>> 16) + (c1 >>> 16)) >>> 0;
|
|
c0 = c0 << 16 >>> 0;
|
|
lo = lo + c0 >>> 0;
|
|
if (lo >>> 0 < c0 >>> 0) {
|
|
hi = hi + 1 >>> 0;
|
|
}
|
|
c1 = c1 << 16 >>> 0;
|
|
lo = lo + c1 >>> 0;
|
|
if (lo >>> 0 < c1 >>> 0) {
|
|
hi = hi + 1 >>> 0;
|
|
}
|
|
hi = hi + Math.imul(aLo, bHi) >>> 0;
|
|
hi = hi + Math.imul(aHi, bLo) >>> 0;
|
|
out[0] = hi;
|
|
out[1] = lo;
|
|
}
|
|
// add two 64 bit numbers (given in parts), and store the result in `out`.
|
|
function add64(out, aHi, aLo, bHi, bLo) {
|
|
let hi = aHi + bHi >>> 0;
|
|
const lo = aLo + bLo >>> 0;
|
|
if (lo >>> 0 < aLo >>> 0) {
|
|
hi = hi + 1 | 0;
|
|
}
|
|
out[0] = hi;
|
|
out[1] = lo;
|
|
}
|
|
/**
|
|
* @since 3.0.6
|
|
*/
|
|
const YieldWrapTypeId = exports.YieldWrapTypeId = /*#__PURE__*/Symbol.for("effect/Utils/YieldWrap");
|
|
/**
|
|
* @since 3.0.6
|
|
*/
|
|
class YieldWrap {
|
|
/**
|
|
* @since 3.0.6
|
|
*/
|
|
#value;
|
|
constructor(value) {
|
|
this.#value = value;
|
|
}
|
|
/**
|
|
* @since 3.0.6
|
|
*/
|
|
[YieldWrapTypeId]() {
|
|
return this.#value;
|
|
}
|
|
}
|
|
/**
|
|
* @since 3.0.6
|
|
*/
|
|
exports.YieldWrap = YieldWrap;
|
|
function yieldWrapGet(self) {
|
|
if (typeof self === "object" && self !== null && YieldWrapTypeId in self) {
|
|
return self[YieldWrapTypeId]();
|
|
}
|
|
throw new Error((0, _errors.getBugErrorMessage)("yieldWrapGet"));
|
|
}
|
|
/**
|
|
* Note: this is an experimental feature made available to allow custom matchers in tests, not to be directly used yet in user code
|
|
*
|
|
* @since 3.1.1
|
|
* @status experimental
|
|
* @category modifiers
|
|
*/
|
|
const structuralRegionState = exports.structuralRegionState = /*#__PURE__*/(0, _GlobalValue.globalValue)("effect/Utils/isStructuralRegion", () => ({
|
|
enabled: false,
|
|
tester: undefined
|
|
}));
|
|
/**
|
|
* Note: this is an experimental feature made available to allow custom matchers in tests, not to be directly used yet in user code
|
|
*
|
|
* @since 3.1.1
|
|
* @status experimental
|
|
* @category modifiers
|
|
*/
|
|
const structuralRegion = (body, tester) => {
|
|
const current = structuralRegionState.enabled;
|
|
const currentTester = structuralRegionState.tester;
|
|
structuralRegionState.enabled = true;
|
|
if (tester) {
|
|
structuralRegionState.tester = tester;
|
|
}
|
|
try {
|
|
return body();
|
|
} finally {
|
|
structuralRegionState.enabled = current;
|
|
structuralRegionState.tester = currentTester;
|
|
}
|
|
};
|
|
exports.structuralRegion = structuralRegion;
|
|
const standard = {
|
|
effect_internal_function: body => {
|
|
return body();
|
|
}
|
|
};
|
|
const forced = {
|
|
effect_internal_function: body => {
|
|
try {
|
|
return body();
|
|
} finally {
|
|
//
|
|
}
|
|
}
|
|
};
|
|
const isNotOptimizedAway = /*#__PURE__*/standard.effect_internal_function(() => new Error().stack)?.includes("effect_internal_function") === true;
|
|
/**
|
|
* @since 3.2.2
|
|
* @status experimental
|
|
* @category tracing
|
|
*/
|
|
const internalCall = exports.internalCall = isNotOptimizedAway ? standard.effect_internal_function : forced.effect_internal_function;
|
|
const genConstructor = function* () {}.constructor;
|
|
/**
|
|
* @since 3.11.0
|
|
*/
|
|
const isGeneratorFunction = u => (0, _Predicate.isObject)(u) && u.constructor === genConstructor;
|
|
exports.isGeneratorFunction = isGeneratorFunction;
|
|
//# sourceMappingURL=Utils.js.map
|