@flighthq/math 0.3.1-next.887.9f59a84 → 0.3.1-next.970.9691e7b
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/constants.d.ts +1 -1
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +1 -1
- package/dist/constants.js.map +1 -1
- package/dist/interpolationAdvanced.d.ts.map +1 -1
- package/dist/interpolationAdvanced.js +8 -4
- package/dist/interpolationAdvanced.js.map +1 -1
- package/dist/nextPowerOfTwo.d.ts.map +1 -1
- package/dist/nextPowerOfTwo.js +6 -1
- package/dist/nextPowerOfTwo.js.map +1 -1
- package/dist/numberTheory.d.ts +2 -2
- package/dist/numberTheory.d.ts.map +1 -1
- package/dist/numberTheory.js +5 -2
- package/dist/numberTheory.js.map +1 -1
- package/dist/randomDistributions.d.ts +2 -2
- package/dist/randomDistributions.d.ts.map +1 -1
- package/dist/randomDistributions.js +8 -6
- package/dist/randomDistributions.js.map +1 -1
- package/dist/randomRange.d.ts +3 -4
- package/dist/randomRange.d.ts.map +1 -1
- package/dist/randomRange.js +3 -4
- package/dist/randomRange.js.map +1 -1
- package/dist/statistics.d.ts.map +1 -1
- package/dist/statistics.js +101 -13
- package/dist/statistics.js.map +1 -1
- package/package.json +2 -2
- package/src/angle.test.ts +3 -0
- package/src/hash.test.ts +3 -0
- package/src/interpolationAdvanced.test.ts +10 -4
- package/src/nextPowerOfTwo.test.ts +11 -0
- package/src/numberTheory.test.ts +9 -0
- package/src/random.test.ts +7 -0
- package/src/randomDistributions.test.ts +72 -0
- package/src/randomRange.test.ts +12 -0
- package/src/statistics.test.ts +59 -0
package/dist/constants.d.ts
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* use sites and both measure the same gzipped size, so this buys evaluation, not bytes.
|
|
14
14
|
*/
|
|
15
15
|
export declare const CIRCLE_KAPPA = 0.5522847498307936;
|
|
16
|
-
/**
|
|
16
|
+
/** Default absolute tolerance for approximate floating-point comparisons. */
|
|
17
17
|
export declare const EPSILON = 0.000001;
|
|
18
18
|
/** Full circle in radians (2π). Prefer `TAU` over `2 * Math.PI` for clarity. */
|
|
19
19
|
export declare const TAU: number;
|
package/dist/constants.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,YAAY,qBAAqB,CAAC;AAE/C,
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,YAAY,qBAAqB,CAAC;AAE/C,6EAA6E;AAC7E,eAAO,MAAM,OAAO,WAAO,CAAC;AAE5B,gFAAgF;AAChF,eAAO,MAAM,GAAG,QAAc,CAAC;AAE/B,yBAAyB;AACzB,eAAO,MAAM,OAAO,QAAc,CAAC;AAEnC,wDAAwD;AACxD,eAAO,MAAM,UAAU,QAAgB,CAAC;AAExC,wDAAwD;AACxD,eAAO,MAAM,UAAU,QAAgB,CAAC"}
|
package/dist/constants.js
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* use sites and both measure the same gzipped size, so this buys evaluation, not bytes.
|
|
14
14
|
*/
|
|
15
15
|
export const CIRCLE_KAPPA = 0.5522847498307936;
|
|
16
|
-
/**
|
|
16
|
+
/** Default absolute tolerance for approximate floating-point comparisons. */
|
|
17
17
|
export const EPSILON = 1e-6;
|
|
18
18
|
/** Full circle in radians (2π). Prefer `TAU` over `2 * Math.PI` for clarity. */
|
|
19
19
|
export const TAU = Math.PI * 2;
|
package/dist/constants.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,kBAAkB,CAAC;AAE/C,
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,kBAAkB,CAAC;AAE/C,6EAA6E;AAC7E,MAAM,CAAC,MAAM,OAAO,GAAG,IAAI,CAAC;AAE5B,gFAAgF;AAChF,MAAM,CAAC,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC;AAE/B,yBAAyB;AACzB,MAAM,CAAC,MAAM,OAAO,GAAG,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC;AAEnC,wDAAwD;AACxD,MAAM,CAAC,MAAM,UAAU,GAAG,IAAI,CAAC,EAAE,GAAG,GAAG,CAAC;AAExC,wDAAwD;AACxD,MAAM,CAAC,MAAM,UAAU,GAAG,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interpolationAdvanced.d.ts","sourceRoot":"","sources":["../src/interpolationAdvanced.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,wBAAgB,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAG/F;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAKjE;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAIrF;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"interpolationAdvanced.d.ts","sourceRoot":"","sources":["../src/interpolationAdvanced.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,wBAAgB,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAG/F;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAKjE;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAIrF;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAQ1D;AAED;;;GAGG;AACH,wBAAgB,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAMxD;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAI5E"}
|
|
@@ -42,8 +42,10 @@ export function moveTowards(current, target, maxDelta) {
|
|
|
42
42
|
* `pingPong(t, 1)` cycles: 0 → 1 → 0 → 1 → …
|
|
43
43
|
*/
|
|
44
44
|
export function pingPong(t, length) {
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
// No guard on a non-positive length: the arithmetic yields NaN and NaN PROPAGATES. These functions do not
|
|
46
|
+
// invent values — a silent 0 turns a loud upstream failure into a plausible number, and IEEE propagation
|
|
47
|
+
// lowers for free where an explicit branch does not. Callers who want a warning get one from a guard
|
|
48
|
+
// layer, not from silent coercion here.
|
|
47
49
|
const cycle = 2 * length;
|
|
48
50
|
const mod = ((t % cycle) + cycle) % cycle;
|
|
49
51
|
return mod <= length ? mod : cycle - mod;
|
|
@@ -53,8 +55,10 @@ export function pingPong(t, length) {
|
|
|
53
55
|
* `repeat(1.6, 1)` → `0.6`. Analogous to Unity's `Mathf.Repeat`.
|
|
54
56
|
*/
|
|
55
57
|
export function repeat(t, length) {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
+
// No guard on a non-positive length: the arithmetic yields NaN and NaN PROPAGATES. These functions do not
|
|
59
|
+
// invent values — a silent 0 turns a loud upstream failure into a plausible number, and IEEE propagation
|
|
60
|
+
// lowers for free where an explicit branch does not. Callers who want a warning get one from a guard
|
|
61
|
+
// layer, not from silent coercion here.
|
|
58
62
|
return ((t % length) + length) % length;
|
|
59
63
|
}
|
|
60
64
|
/** Hermite interpolation with a smoother quintic ease curve (Ken Perlin).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interpolationAdvanced.js","sourceRoot":"","sources":["../src/interpolationAdvanced.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,MAAM,UAAU,IAAI,CAAC,OAAe,EAAE,MAAc,EAAE,MAAc,EAAE,SAAiB;IACrF,IAAI,SAAS,IAAI,CAAC,IAAI,MAAM,IAAI,CAAC;QAAE,OAAO,OAAO,CAAC;IAClD,OAAO,MAAM,GAAG,CAAC,OAAO,GAAG,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;AACrE,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,SAAS,CAAC,CAAS,EAAE,CAAS,EAAE,CAAS;IACvD,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC;IACxB,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC;IACzC,IAAI,IAAI,GAAG,IAAI,CAAC,EAAE;QAAE,IAAI,IAAI,GAAG,CAAC;IAChC,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC;AACtB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,WAAW,CAAC,OAAe,EAAE,MAAc,EAAE,QAAgB;IAC3E,MAAM,KAAK,GAAG,MAAM,GAAG,OAAO,CAAC;IAC/B,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,QAAQ;QAAE,OAAO,MAAM,CAAC;IAC/C,OAAO,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,QAAQ,CAAC;AAC/C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,QAAQ,CAAC,CAAS,EAAE,MAAc;IAChD,
|
|
1
|
+
{"version":3,"file":"interpolationAdvanced.js","sourceRoot":"","sources":["../src/interpolationAdvanced.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,MAAM,UAAU,IAAI,CAAC,OAAe,EAAE,MAAc,EAAE,MAAc,EAAE,SAAiB;IACrF,IAAI,SAAS,IAAI,CAAC,IAAI,MAAM,IAAI,CAAC;QAAE,OAAO,OAAO,CAAC;IAClD,OAAO,MAAM,GAAG,CAAC,OAAO,GAAG,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;AACrE,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,SAAS,CAAC,CAAS,EAAE,CAAS,EAAE,CAAS;IACvD,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC;IACxB,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC;IACzC,IAAI,IAAI,GAAG,IAAI,CAAC,EAAE;QAAE,IAAI,IAAI,GAAG,CAAC;IAChC,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC;AACtB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,WAAW,CAAC,OAAe,EAAE,MAAc,EAAE,QAAgB;IAC3E,MAAM,KAAK,GAAG,MAAM,GAAG,OAAO,CAAC;IAC/B,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,QAAQ;QAAE,OAAO,MAAM,CAAC;IAC/C,OAAO,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,QAAQ,CAAC;AAC/C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,QAAQ,CAAC,CAAS,EAAE,MAAc;IAChD,0GAA0G;IAC1G,yGAAyG;IACzG,qGAAqG;IACrG,wCAAwC;IACxC,MAAM,KAAK,GAAG,CAAC,GAAG,MAAM,CAAC;IACzB,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,GAAG,KAAK,CAAC,GAAG,KAAK,CAAC;IAC1C,OAAO,GAAG,IAAI,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,GAAG,GAAG,CAAC;AAC3C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,MAAM,CAAC,CAAS,EAAE,MAAc;IAC9C,0GAA0G;IAC1G,yGAAyG;IACzG,qGAAqG;IACrG,wCAAwC;IACxC,OAAO,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,MAAM,CAAC;AAC1C,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,KAAa,EAAE,KAAa,EAAE,CAAS;IAClE,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC;IACxC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACpC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC;AAC7C,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nextPowerOfTwo.d.ts","sourceRoot":"","sources":["../src/nextPowerOfTwo.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAE/C;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAItE;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAWhD;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"nextPowerOfTwo.d.ts","sourceRoot":"","sources":["../src/nextPowerOfTwo.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAE/C;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAItE;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAWhD;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAepD"}
|
package/dist/nextPowerOfTwo.js
CHANGED
|
@@ -41,12 +41,17 @@ export function previousPowerOfTwo(n) {
|
|
|
41
41
|
if (n <= 1)
|
|
42
42
|
return 1;
|
|
43
43
|
// Fill all bits below the highest set bit, then shift right by 1.
|
|
44
|
+
//
|
|
45
|
+
// The shift is UNSIGNED, matching nextPowerOfTwo's `>>> 0`. With a signed `>>` the fill leaves bit 31 set
|
|
46
|
+
// for any input at or above 2^30, and sign extension then returned a NEGATIVE power of two — -1073741824
|
|
47
|
+
// for both 2^30 and 2^31-1. The two functions are mirror images and the operator is the only place they
|
|
48
|
+
// were allowed to differ.
|
|
44
49
|
n = n | 0;
|
|
45
50
|
n |= n >> 1;
|
|
46
51
|
n |= n >> 2;
|
|
47
52
|
n |= n >> 4;
|
|
48
53
|
n |= n >> 8;
|
|
49
54
|
n |= n >> 16;
|
|
50
|
-
return (n + 1)
|
|
55
|
+
return (n + 1) >>> 1;
|
|
51
56
|
}
|
|
52
57
|
//# sourceMappingURL=nextPowerOfTwo.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nextPowerOfTwo.js","sourceRoot":"","sources":["../src/nextPowerOfTwo.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,CAAS;IACpC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;AACtC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,KAAa,EAAE,QAAgB;IAC5D,IAAI,QAAQ,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IAChC,MAAM,SAAS,GAAG,KAAK,GAAG,QAAQ,CAAC;IACnC,OAAO,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,QAAQ,GAAG,SAAS,CAAC;AAChE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,CAAS;IACtC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,CAAC,CAAC;IACrB,qEAAqE;IACrE,4DAA4D;IAC5D,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;IAChB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACZ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACZ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACZ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACZ,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;IACb,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;AACvB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,CAAS;IAC1C,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,CAAC,CAAC;IACrB,kEAAkE;IAClE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACV,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACZ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACZ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACZ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACZ,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;IACb,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"nextPowerOfTwo.js","sourceRoot":"","sources":["../src/nextPowerOfTwo.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,CAAS;IACpC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;AACtC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,KAAa,EAAE,QAAgB;IAC5D,IAAI,QAAQ,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IAChC,MAAM,SAAS,GAAG,KAAK,GAAG,QAAQ,CAAC;IACnC,OAAO,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,QAAQ,GAAG,SAAS,CAAC;AAChE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,CAAS;IACtC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,CAAC,CAAC;IACrB,qEAAqE;IACrE,4DAA4D;IAC5D,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;IAChB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACZ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACZ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACZ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACZ,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;IACb,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;AACvB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,CAAS;IAC1C,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,CAAC,CAAC;IACrB,kEAAkE;IAClE,EAAE;IACF,0GAA0G;IAC1G,yGAAyG;IACzG,wGAAwG;IACxG,0BAA0B;IAC1B,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACV,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACZ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACZ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACZ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACZ,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;IACb,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;AACvB,CAAC"}
|
package/dist/numberTheory.d.ts
CHANGED
|
@@ -8,8 +8,8 @@ export declare function factorial(n: number): number;
|
|
|
8
8
|
/** Return the greatest common divisor of `a` and `b` (Euclidean algorithm).
|
|
9
9
|
*
|
|
10
10
|
* Operates on the absolute values of the inputs, so negative arguments are
|
|
11
|
-
* accepted. Throws when both `a` and `b` are `0`
|
|
12
|
-
* of zero and zero is undefined).
|
|
11
|
+
* accepted. Throws for non-finite inputs or when both `a` and `b` are `0`
|
|
12
|
+
* (programmer errors — the GCD of zero and zero is undefined).
|
|
13
13
|
*/
|
|
14
14
|
export declare function gcd(a: number, b: number): number;
|
|
15
15
|
/** Return the squared distance `x² + y²`.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"numberTheory.d.ts","sourceRoot":"","sources":["../src/numberTheory.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAM3C;AAED;;;;;GAKG;AACH,wBAAgB,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"numberTheory.d.ts","sourceRoot":"","sources":["../src/numberTheory.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAM3C;AAED;;;;;GAKG;AACH,wBAAgB,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAahD;AAED;;;;;GAKG;AACH,wBAAgB,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED,oCAAoC;AACpC,wBAAgB,MAAM,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAEzC;AAED,mCAAmC;AACnC,wBAAgB,KAAK,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAExC;AAED;;;;;GAKG;AACH,wBAAgB,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAGhD"}
|
package/dist/numberTheory.js
CHANGED
|
@@ -17,10 +17,13 @@ export function factorial(n) {
|
|
|
17
17
|
/** Return the greatest common divisor of `a` and `b` (Euclidean algorithm).
|
|
18
18
|
*
|
|
19
19
|
* Operates on the absolute values of the inputs, so negative arguments are
|
|
20
|
-
* accepted. Throws when both `a` and `b` are `0`
|
|
21
|
-
* of zero and zero is undefined).
|
|
20
|
+
* accepted. Throws for non-finite inputs or when both `a` and `b` are `0`
|
|
21
|
+
* (programmer errors — the GCD of zero and zero is undefined).
|
|
22
22
|
*/
|
|
23
23
|
export function gcd(a, b) {
|
|
24
|
+
if (!Number.isFinite(a) || !Number.isFinite(b)) {
|
|
25
|
+
throw new RangeError('gcd: arguments must be finite');
|
|
26
|
+
}
|
|
24
27
|
a = Math.abs(Math.trunc(a));
|
|
25
28
|
b = Math.abs(Math.trunc(b));
|
|
26
29
|
if (a === 0 && b === 0)
|
package/dist/numberTheory.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"numberTheory.js","sourceRoot":"","sources":["../src/numberTheory.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CAAC,CAAS;IACjC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;QAAE,MAAM,IAAI,UAAU,CAAC,6CAA6C,CAAC,CAAC;IACvG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IACjC,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE;QAAE,MAAM,IAAI,CAAC,CAAC;IACzC,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,GAAG,CAAC,CAAS,EAAE,CAAS;IACtC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5B,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5B,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,MAAM,IAAI,UAAU,CAAC,mCAAmC,CAAC,CAAC;IAClF,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACf,MAAM,CAAC,GAAG,CAAC,CAAC;QACZ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACV,CAAC,GAAG,CAAC,CAAC;IACR,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,MAAM,CAAC,CAAS,EAAE,CAAS;IACzC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AACvB,CAAC;AAED,oCAAoC;AACpC,MAAM,UAAU,MAAM,CAAC,CAAS;IAC9B,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;AACvB,CAAC;AAED,mCAAmC;AACnC,MAAM,UAAU,KAAK,CAAC,CAAS;IAC7B,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;AACvB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,GAAG,CAAC,CAAS,EAAE,CAAS;IACtC,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACpB,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AACjE,CAAC"}
|
|
1
|
+
{"version":3,"file":"numberTheory.js","sourceRoot":"","sources":["../src/numberTheory.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CAAC,CAAS;IACjC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;QAAE,MAAM,IAAI,UAAU,CAAC,6CAA6C,CAAC,CAAC;IACvG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IACjC,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE;QAAE,MAAM,IAAI,CAAC,CAAC;IACzC,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,GAAG,CAAC,CAAS,EAAE,CAAS;IACtC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/C,MAAM,IAAI,UAAU,CAAC,+BAA+B,CAAC,CAAC;IACxD,CAAC;IACD,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5B,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5B,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,MAAM,IAAI,UAAU,CAAC,mCAAmC,CAAC,CAAC;IAClF,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACf,MAAM,CAAC,GAAG,CAAC,CAAC;QACZ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACV,CAAC,GAAG,CAAC,CAAC;IACR,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,MAAM,CAAC,CAAS,EAAE,CAAS;IACzC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AACvB,CAAC;AAED,oCAAoC;AACpC,MAAM,UAAU,MAAM,CAAC,CAAS;IAC9B,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;AACvB,CAAC;AAED,mCAAmC;AACnC,MAAM,UAAU,KAAK,CAAC,CAAS;IAC7B,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;AACvB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,GAAG,CAAC,CAAS,EAAE,CAAS;IACtC,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACpB,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AACjE,CAAC"}
|
|
@@ -11,7 +11,7 @@ export declare function pick<T>(random: RandomSource, items: Readonly<T[]>): T |
|
|
|
11
11
|
* Suitable for modeling inter-arrival times in a Poisson process, particle
|
|
12
12
|
* lifetimes, and decay events.
|
|
13
13
|
*
|
|
14
|
-
* The result is always non-negative. Throws if `rate
|
|
14
|
+
* The result is always non-negative. Throws if `rate` is non-finite or not positive.
|
|
15
15
|
*
|
|
16
16
|
* Deterministic: same `random` sequence → same output sequence.
|
|
17
17
|
*/
|
|
@@ -78,7 +78,7 @@ export declare function randomOnUnitSphere(random: RandomSource, out: Vector3Lik
|
|
|
78
78
|
* `lambda` (λ ≤ ~30); for large lambda, `randomGaussian(random, lambda,
|
|
79
79
|
* Math.sqrt(lambda))` is a faster approximation.
|
|
80
80
|
*
|
|
81
|
-
* The result is a non-negative integer. Throws if `lambda
|
|
81
|
+
* The result is a non-negative integer. Throws if `lambda` is non-finite or not positive.
|
|
82
82
|
*
|
|
83
83
|
* Deterministic: same `random` sequence → same output sequence.
|
|
84
84
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"randomDistributions.d.ts","sourceRoot":"","sources":["../src/randomDistributions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAEvF;;;GAGG;AACH,wBAAgB,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,SAAS,CAGjF;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,YAAY,EAAE,IAAI,GAAE,MAAU,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"randomDistributions.d.ts","sourceRoot":"","sources":["../src/randomDistributions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAEvF;;;GAGG;AACH,wBAAgB,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,SAAS,CAGjF;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,YAAY,EAAE,IAAI,GAAE,MAAU,GAAG,MAAM,CAOhF;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,YAAY,EAAE,IAAI,GAAE,MAAU,EAAE,iBAAiB,GAAE,MAAU,GAAG,MAAM,CAO5G;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,YAAY,EACpB,IAAI,GAAE,MAAU,EAChB,iBAAiB,GAAE,MAAU,GAC5B,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAQ3B;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,EAAE,WAAW,GAAG,IAAI,CAUjF;AAED;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,EAAE,WAAW,GAAG,IAAI,CAYnF;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,EAAE,WAAW,GAAG,IAAI,CAM/E;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,EAAE,WAAW,GAAG,IAAI,CAiB/E;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,YAAY,EAAE,MAAM,GAAE,MAAU,GAAG,MAAM,CAY9E;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC,GAAG,MAAM,CAUxF;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAI1E;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,IAAI,CAOxE"}
|
|
@@ -14,13 +14,14 @@ export function pick(random, items) {
|
|
|
14
14
|
* Suitable for modeling inter-arrival times in a Poisson process, particle
|
|
15
15
|
* lifetimes, and decay events.
|
|
16
16
|
*
|
|
17
|
-
* The result is always non-negative. Throws if `rate
|
|
17
|
+
* The result is always non-negative. Throws if `rate` is non-finite or not positive.
|
|
18
18
|
*
|
|
19
19
|
* Deterministic: same `random` sequence → same output sequence.
|
|
20
20
|
*/
|
|
21
21
|
export function randomExponential(random, rate = 1) {
|
|
22
|
-
if (rate <= 0)
|
|
23
|
-
throw new RangeError('randomExponential: rate must be > 0');
|
|
22
|
+
if (!Number.isFinite(rate) || rate <= 0) {
|
|
23
|
+
throw new RangeError('randomExponential: rate must be finite and > 0');
|
|
24
|
+
}
|
|
24
25
|
const u = random();
|
|
25
26
|
// Avoid ln(0) — replace exactly 0 with the smallest usable positive value.
|
|
26
27
|
return -Math.log(u === 0 ? Number.EPSILON : u) / rate;
|
|
@@ -147,13 +148,14 @@ export function randomOnUnitSphere(random, out) {
|
|
|
147
148
|
* `lambda` (λ ≤ ~30); for large lambda, `randomGaussian(random, lambda,
|
|
148
149
|
* Math.sqrt(lambda))` is a faster approximation.
|
|
149
150
|
*
|
|
150
|
-
* The result is a non-negative integer. Throws if `lambda
|
|
151
|
+
* The result is a non-negative integer. Throws if `lambda` is non-finite or not positive.
|
|
151
152
|
*
|
|
152
153
|
* Deterministic: same `random` sequence → same output sequence.
|
|
153
154
|
*/
|
|
154
155
|
export function randomPoisson(random, lambda = 1) {
|
|
155
|
-
if (lambda <= 0)
|
|
156
|
-
throw new RangeError('randomPoisson: lambda must be > 0');
|
|
156
|
+
if (!Number.isFinite(lambda) || lambda <= 0) {
|
|
157
|
+
throw new RangeError('randomPoisson: lambda must be finite and > 0');
|
|
158
|
+
}
|
|
157
159
|
const limit = Math.exp(-lambda);
|
|
158
160
|
let k = 0;
|
|
159
161
|
let product = random();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"randomDistributions.js","sourceRoot":"","sources":["../src/randomDistributions.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,UAAU,IAAI,CAAI,MAAoB,EAAE,KAAoB;IAChE,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IACzC,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;AACpD,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAoB,EAAE,OAAe,CAAC;IACtE,IAAI,IAAI,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"randomDistributions.js","sourceRoot":"","sources":["../src/randomDistributions.ts"],"names":[],"mappings":"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"}
|
package/dist/randomRange.d.ts
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import type { RandomSource } from '@flighthq/types/contract';
|
|
2
2
|
/** Return a random boolean with the given `probability` of being `true`.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* Values outside `[0, 1]` behave like the nearest endpoint; `0.5` is a fair coin flip.
|
|
5
5
|
*/
|
|
6
6
|
export declare function randomBool(random: RandomSource, probability?: number): boolean;
|
|
7
7
|
/** Return a random integer in the inclusive range `[min, max]`.
|
|
8
8
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* if `min > max`.
|
|
9
|
+
* Bounds are passed through `Math.floor`, so fractional bounds are rounded down
|
|
10
|
+
* rather than rejected. Throws if the resulting `min` is greater than `max`.
|
|
12
11
|
*/
|
|
13
12
|
export declare function randomInt(random: RandomSource, min: number, max: number): number;
|
|
14
13
|
/** Return a random float in the half-open range `[min, max)`. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"randomRange.d.ts","sourceRoot":"","sources":["../src/randomRange.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAE7D;;;GAGG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,YAAY,EAAE,WAAW,GAAE,MAAY,GAAG,OAAO,CAEnF;AAED
|
|
1
|
+
{"version":3,"file":"randomRange.d.ts","sourceRoot":"","sources":["../src/randomRange.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAE7D;;;GAGG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,YAAY,EAAE,WAAW,GAAE,MAAY,GAAG,OAAO,CAEnF;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAKhF;AAED,iEAAiE;AACjE,wBAAgB,WAAW,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAElF;AAED,uEAAuE;AACvE,wBAAgB,UAAU,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAEvD"}
|
package/dist/randomRange.js
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
/** Return a random boolean with the given `probability` of being `true`.
|
|
2
2
|
*
|
|
3
|
-
*
|
|
3
|
+
* Values outside `[0, 1]` behave like the nearest endpoint; `0.5` is a fair coin flip.
|
|
4
4
|
*/
|
|
5
5
|
export function randomBool(random, probability = 0.5) {
|
|
6
6
|
return random() < probability;
|
|
7
7
|
}
|
|
8
8
|
/** Return a random integer in the inclusive range `[min, max]`.
|
|
9
9
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* if `min > max`.
|
|
10
|
+
* Bounds are passed through `Math.floor`, so fractional bounds are rounded down
|
|
11
|
+
* rather than rejected. Throws if the resulting `min` is greater than `max`.
|
|
13
12
|
*/
|
|
14
13
|
export function randomInt(random, min, max) {
|
|
15
14
|
const lo = Math.floor(min);
|
package/dist/randomRange.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"randomRange.js","sourceRoot":"","sources":["../src/randomRange.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,MAAoB,EAAE,cAAsB,GAAG;IACxE,OAAO,MAAM,EAAE,GAAG,WAAW,CAAC;AAChC,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"randomRange.js","sourceRoot":"","sources":["../src/randomRange.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,MAAoB,EAAE,cAAsB,GAAG;IACxE,OAAO,MAAM,EAAE,GAAG,WAAW,CAAC;AAChC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,SAAS,CAAC,MAAoB,EAAE,GAAW,EAAE,GAAW;IACtE,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3B,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3B,IAAI,EAAE,GAAG,EAAE;QAAE,MAAM,IAAI,UAAU,CAAC,+BAA+B,CAAC,CAAC;IACnE,OAAO,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;AACnD,CAAC;AAED,iEAAiE;AACjE,MAAM,UAAU,WAAW,CAAC,MAAoB,EAAE,GAAW,EAAE,GAAW;IACxE,OAAO,GAAG,GAAG,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;AACtC,CAAC;AAED,uEAAuE;AACvE,MAAM,UAAU,UAAU,CAAC,MAAoB;IAC7C,OAAO,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACjC,CAAC"}
|
package/dist/statistics.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"statistics.d.ts","sourceRoot":"","sources":["../src/statistics.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"statistics.d.ts","sourceRoot":"","sources":["../src/statistics.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC,GAAG,MAAM,CAMvD;AAED;;;;GAIG;AACH,wBAAgB,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC,GAAG,MAAM,CAKzD;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC,GAAG,MAAM,CAMpE;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC,GAAG,MAAM,CAQ3D;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC,GAAG,MAAM,CAwB/F"}
|
package/dist/statistics.js
CHANGED
|
@@ -5,10 +5,12 @@
|
|
|
5
5
|
export function mean(values) {
|
|
6
6
|
if (values.length === 0)
|
|
7
7
|
return NaN;
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
const scale = finiteAbsoluteScale(values);
|
|
9
|
+
if (!Number.isFinite(scale))
|
|
10
|
+
return unscaledMean(values);
|
|
11
|
+
if (scale === 0)
|
|
12
|
+
return 0;
|
|
13
|
+
return (scaledSum(values, scale) / values.length) * scale;
|
|
12
14
|
}
|
|
13
15
|
/** Return the median of `values`.
|
|
14
16
|
*
|
|
@@ -20,14 +22,21 @@ export function median(values) {
|
|
|
20
22
|
return NaN;
|
|
21
23
|
const sorted = values.slice().sort((a, b) => a - b);
|
|
22
24
|
const mid = Math.floor(sorted.length / 2);
|
|
23
|
-
return sorted.length % 2 !== 0 ? sorted[mid] : (sorted[mid - 1]
|
|
25
|
+
return sorted.length % 2 !== 0 ? sorted[mid] : midpoint(sorted[mid - 1], sorted[mid]);
|
|
24
26
|
}
|
|
25
27
|
/** Return the population standard deviation of `values`.
|
|
26
28
|
*
|
|
27
29
|
* Returns `NaN` for an empty array.
|
|
28
30
|
*/
|
|
29
31
|
export function standardDeviation(values) {
|
|
30
|
-
|
|
32
|
+
if (values.length === 0)
|
|
33
|
+
return NaN;
|
|
34
|
+
const scale = finiteAbsoluteScale(values);
|
|
35
|
+
if (!Number.isFinite(scale))
|
|
36
|
+
return Math.sqrt(unscaledVariance(values));
|
|
37
|
+
if (scale === 0)
|
|
38
|
+
return 0;
|
|
39
|
+
return Math.sqrt(scaledVariance(values, scale)) * scale;
|
|
31
40
|
}
|
|
32
41
|
/** Return the population variance of `values`.
|
|
33
42
|
*
|
|
@@ -36,13 +45,15 @@ export function standardDeviation(values) {
|
|
|
36
45
|
export function variance(values) {
|
|
37
46
|
if (values.length === 0)
|
|
38
47
|
return NaN;
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
48
|
+
const scale = finiteAbsoluteScale(values);
|
|
49
|
+
if (!Number.isFinite(scale))
|
|
50
|
+
return unscaledVariance(values);
|
|
51
|
+
if (scale === 0)
|
|
52
|
+
return 0;
|
|
53
|
+
const normalized = scaledVariance(values, scale);
|
|
54
|
+
if (normalized === 0)
|
|
55
|
+
return 0;
|
|
56
|
+
return normalized * scale * scale;
|
|
46
57
|
}
|
|
47
58
|
/** Return the weighted average of `values` using `weights`.
|
|
48
59
|
*
|
|
@@ -56,6 +67,83 @@ export function weightedAverage(values, weights) {
|
|
|
56
67
|
}
|
|
57
68
|
if (values.length === 0)
|
|
58
69
|
return NaN;
|
|
70
|
+
const valueScale = finiteAbsoluteScale(values);
|
|
71
|
+
const weightScale = finiteAbsoluteScale(weights);
|
|
72
|
+
if (!Number.isFinite(valueScale) || !Number.isFinite(weightScale)) {
|
|
73
|
+
return unscaledWeightedAverage(values, weights);
|
|
74
|
+
}
|
|
75
|
+
if (weightScale === 0)
|
|
76
|
+
return NaN;
|
|
77
|
+
const sumWeights = scaledSum(weights, weightScale);
|
|
78
|
+
if (sumWeights === 0)
|
|
79
|
+
return NaN;
|
|
80
|
+
if (valueScale === 0)
|
|
81
|
+
return 0;
|
|
82
|
+
let sumProduct = 0;
|
|
83
|
+
let correction = 0;
|
|
84
|
+
for (let i = 0; i < values.length; i++) {
|
|
85
|
+
const term = (values[i] / valueScale) * (weights[i] / weightScale) - correction;
|
|
86
|
+
const next = sumProduct + term;
|
|
87
|
+
correction = next - sumProduct - term;
|
|
88
|
+
sumProduct = next;
|
|
89
|
+
}
|
|
90
|
+
return (sumProduct / sumWeights) * valueScale;
|
|
91
|
+
}
|
|
92
|
+
function finiteAbsoluteScale(values) {
|
|
93
|
+
let scale = 0;
|
|
94
|
+
for (let i = 0; i < values.length; i++)
|
|
95
|
+
scale = Math.max(scale, Math.abs(values[i]));
|
|
96
|
+
return scale;
|
|
97
|
+
}
|
|
98
|
+
function midpoint(a, b) {
|
|
99
|
+
if (!Number.isFinite(a) || !Number.isFinite(b))
|
|
100
|
+
return (a + b) / 2;
|
|
101
|
+
if (Object.is(a, b))
|
|
102
|
+
return a;
|
|
103
|
+
if ((a >= 0 && b >= 0) || (a <= 0 && b <= 0))
|
|
104
|
+
return a + (b - a) / 2;
|
|
105
|
+
return a / 2 + b / 2;
|
|
106
|
+
}
|
|
107
|
+
function scaledSum(values, scale) {
|
|
108
|
+
let sum = 0;
|
|
109
|
+
let correction = 0;
|
|
110
|
+
for (let i = 0; i < values.length; i++) {
|
|
111
|
+
const term = values[i] / scale - correction;
|
|
112
|
+
const next = sum + term;
|
|
113
|
+
correction = next - sum - term;
|
|
114
|
+
sum = next;
|
|
115
|
+
}
|
|
116
|
+
return sum;
|
|
117
|
+
}
|
|
118
|
+
function scaledVariance(values, scale) {
|
|
119
|
+
const normalizedMean = scaledSum(values, scale) / values.length;
|
|
120
|
+
let sum = 0;
|
|
121
|
+
let correction = 0;
|
|
122
|
+
for (let i = 0; i < values.length; i++) {
|
|
123
|
+
const difference = values[i] / scale - normalizedMean;
|
|
124
|
+
const term = difference * difference - correction;
|
|
125
|
+
const next = sum + term;
|
|
126
|
+
correction = next - sum - term;
|
|
127
|
+
sum = next;
|
|
128
|
+
}
|
|
129
|
+
return Math.max(0, sum / values.length);
|
|
130
|
+
}
|
|
131
|
+
function unscaledMean(values) {
|
|
132
|
+
let sum = 0;
|
|
133
|
+
for (let i = 0; i < values.length; i++)
|
|
134
|
+
sum += values[i];
|
|
135
|
+
return sum / values.length;
|
|
136
|
+
}
|
|
137
|
+
function unscaledVariance(values) {
|
|
138
|
+
const average = unscaledMean(values);
|
|
139
|
+
let sum = 0;
|
|
140
|
+
for (let i = 0; i < values.length; i++) {
|
|
141
|
+
const difference = values[i] - average;
|
|
142
|
+
sum += difference * difference;
|
|
143
|
+
}
|
|
144
|
+
return sum / values.length;
|
|
145
|
+
}
|
|
146
|
+
function unscaledWeightedAverage(values, weights) {
|
|
59
147
|
let sumWeights = 0;
|
|
60
148
|
let sumProduct = 0;
|
|
61
149
|
for (let i = 0; i < values.length; i++) {
|
package/dist/statistics.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"statistics.js","sourceRoot":"","sources":["../src/statistics.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,UAAU,IAAI,CAAC,MAA0B;IAC7C,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,GAAG,CAAC;IACpC,
|
|
1
|
+
{"version":3,"file":"statistics.js","sourceRoot":"","sources":["../src/statistics.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flighthq/math",
|
|
3
|
-
"version": "0.3.1-next.
|
|
3
|
+
"version": "0.3.1-next.970.9691e7b",
|
|
4
4
|
"author": "Joshua Granick and other contributors",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"clean:dist": "tsx ../../scripts/clean-package-dist.ts"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@flighthq/types": "0.3.1-next.
|
|
41
|
+
"@flighthq/types": "0.3.1-next.970.9691e7b"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"typescript": "^5.3.0"
|
package/src/angle.test.ts
CHANGED
|
@@ -32,6 +32,9 @@ describe('deltaAngle', () => {
|
|
|
32
32
|
it('returns a negative delta when the target is behind', () => {
|
|
33
33
|
expect(deltaAngle(Math.PI / 2, 0)).toBeCloseTo(-Math.PI / 2, 10);
|
|
34
34
|
});
|
|
35
|
+
it('keeps the positive half-turn in its documented (-π, π] range', () => {
|
|
36
|
+
expect(deltaAngle(0, Math.PI)).toBe(Math.PI);
|
|
37
|
+
});
|
|
35
38
|
it('result is always within (-π, π]', () => {
|
|
36
39
|
for (let i = -10; i <= 10; i++) {
|
|
37
40
|
const d = deltaAngle(i, i + 3);
|
package/src/hash.test.ts
CHANGED
|
@@ -63,6 +63,9 @@ describe('hashCombine', () => {
|
|
|
63
63
|
it('produces different results for different seeds', () => {
|
|
64
64
|
expect(hashCombine(1, 100)).not.toBe(hashCombine(2, 100));
|
|
65
65
|
});
|
|
66
|
+
it('pins the complete multi-term mix with a known-answer vector', () => {
|
|
67
|
+
expect(hashCombine(100, 200)).toBe(3347962280);
|
|
68
|
+
});
|
|
66
69
|
});
|
|
67
70
|
|
|
68
71
|
describe('hashUint32', () => {
|
|
@@ -75,8 +75,11 @@ describe('pingPong', () => {
|
|
|
75
75
|
it('bounces back at t = 1.5 * length', () => {
|
|
76
76
|
expect(pingPong(1.5, 1)).toBeCloseTo(0.5, 10);
|
|
77
77
|
});
|
|
78
|
-
|
|
79
|
-
|
|
78
|
+
// NaN, not 0. These functions do not invent values: a non-positive length has no wrap interval, the
|
|
79
|
+
// arithmetic yields NaN, and NaN propagates so an upstream failure stays visible. A silent 0 is a
|
|
80
|
+
// plausible number that hides the break — this assertion previously pinned that coercion.
|
|
81
|
+
it('propagates NaN when length is 0', () => {
|
|
82
|
+
expect(pingPong(1, 0)).toBeNaN();
|
|
80
83
|
});
|
|
81
84
|
it('works with larger lengths', () => {
|
|
82
85
|
expect(pingPong(3, 2)).toBeCloseTo(1, 10);
|
|
@@ -95,8 +98,11 @@ describe('repeat', () => {
|
|
|
95
98
|
expect(r).toBeGreaterThanOrEqual(0);
|
|
96
99
|
expect(r).toBeLessThan(1);
|
|
97
100
|
});
|
|
98
|
-
|
|
99
|
-
|
|
101
|
+
// NaN, not 0. These functions do not invent values: a non-positive length has no wrap interval, the
|
|
102
|
+
// arithmetic yields NaN, and NaN propagates so an upstream failure stays visible. A silent 0 is a
|
|
103
|
+
// plausible number that hides the break — this assertion previously pinned that coercion.
|
|
104
|
+
it('propagates NaN when length is 0', () => {
|
|
105
|
+
expect(repeat(1, 0)).toBeNaN();
|
|
100
106
|
});
|
|
101
107
|
});
|
|
102
108
|
|
|
@@ -82,3 +82,14 @@ describe('previousPowerOfTwo', () => {
|
|
|
82
82
|
expect(previousPowerOfTwo(1025)).toBe(1024);
|
|
83
83
|
});
|
|
84
84
|
});
|
|
85
|
+
|
|
86
|
+
describe('previousPowerOfTwo', () => {
|
|
87
|
+
// BY VALUE, not by sign: a `>= 0` assertion would pass against a still-broken version returning 0,
|
|
88
|
+
// which is exactly what input 2147483648 did before the fix. The signed `>>` returned -1073741824 for
|
|
89
|
+
// both of these inputs — the negative value is the thing being pinned.
|
|
90
|
+
it('returns a positive power of two at and above 2^30, where a signed shift sign-extended', () => {
|
|
91
|
+
expect(previousPowerOfTwo(1073741824)).toBe(1073741824);
|
|
92
|
+
expect(previousPowerOfTwo(2147483647)).toBe(1073741824);
|
|
93
|
+
expect(nextPowerOfTwo(1073741824)).toBe(1073741824);
|
|
94
|
+
});
|
|
95
|
+
});
|
package/src/numberTheory.test.ts
CHANGED
|
@@ -40,6 +40,11 @@ describe('gcd', () => {
|
|
|
40
40
|
it('throws when both arguments are 0', () => {
|
|
41
41
|
expect(() => gcd(0, 0)).toThrow(RangeError);
|
|
42
42
|
});
|
|
43
|
+
it('rejects non-finite inputs instead of returning a non-finite value or looping', () => {
|
|
44
|
+
expect(() => gcd(Infinity, 0)).toThrow(RangeError);
|
|
45
|
+
expect(() => gcd(0, -Infinity)).toThrow(RangeError);
|
|
46
|
+
expect(() => gcd(NaN, 0)).toThrow(RangeError);
|
|
47
|
+
});
|
|
43
48
|
});
|
|
44
49
|
|
|
45
50
|
describe('hypot2', () => {
|
|
@@ -92,4 +97,8 @@ describe('lcm', () => {
|
|
|
92
97
|
it('accepts negative inputs', () => {
|
|
93
98
|
expect(lcm(-4, 6)).toBe(12);
|
|
94
99
|
});
|
|
100
|
+
it('rejects non-finite inputs through the shared GCD validation', () => {
|
|
101
|
+
expect(() => lcm(Infinity, 0)).toThrow(RangeError);
|
|
102
|
+
expect(() => lcm(0, NaN)).toThrow(RangeError);
|
|
103
|
+
});
|
|
95
104
|
});
|
package/src/random.test.ts
CHANGED
|
@@ -24,6 +24,13 @@ describe('createRandomSource', () => {
|
|
|
24
24
|
expect(differs).toBe(true);
|
|
25
25
|
});
|
|
26
26
|
|
|
27
|
+
it('pins the mulberry32 transform with a known-answer sequence', () => {
|
|
28
|
+
const rng = createRandomSource(0xc0ffee);
|
|
29
|
+
expect([rng(), rng(), rng(), rng()]).toEqual([
|
|
30
|
+
0.021141508361324668, 0.6661099966149777, 0.7799714196007699, 0.7395844468846917,
|
|
31
|
+
]);
|
|
32
|
+
});
|
|
33
|
+
|
|
27
34
|
it('tolerates non-finite seeds without producing NaN', () => {
|
|
28
35
|
const rng = createRandomSource(NaN);
|
|
29
36
|
const v = rng();
|
|
@@ -16,6 +16,14 @@ import {
|
|
|
16
16
|
|
|
17
17
|
const rng = () => createRandomSource(0xabcdef);
|
|
18
18
|
|
|
19
|
+
function sequenceRandom(...values: number[]): () => number {
|
|
20
|
+
let index = 0;
|
|
21
|
+
return () => {
|
|
22
|
+
if (index >= values.length) throw new Error('sequenceRandom exhausted');
|
|
23
|
+
return values[index++];
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
19
27
|
describe('pick', () => {
|
|
20
28
|
it('returns an element from the array', () => {
|
|
21
29
|
const items = [1, 2, 3, 4, 5];
|
|
@@ -31,6 +39,9 @@ describe('pick', () => {
|
|
|
31
39
|
const random = rng();
|
|
32
40
|
for (let i = 0; i < 20; i++) expect(pick(random, [42])).toBe(42);
|
|
33
41
|
});
|
|
42
|
+
it('selects the bucket named by an exact deterministic sample', () => {
|
|
43
|
+
expect(pick(() => 0.75, ['a', 'b', 'c', 'd'])).toBe('d');
|
|
44
|
+
});
|
|
34
45
|
it('is deterministic for the same seed', () => {
|
|
35
46
|
const items = ['a', 'b', 'c', 'd'];
|
|
36
47
|
const a = rng();
|
|
@@ -67,6 +78,10 @@ describe('randomExponential', () => {
|
|
|
67
78
|
expect(() => randomExponential(rng(), 0)).toThrow(RangeError);
|
|
68
79
|
expect(() => randomExponential(rng(), -1)).toThrow(RangeError);
|
|
69
80
|
});
|
|
81
|
+
it('rejects non-finite rates', () => {
|
|
82
|
+
expect(() => randomExponential(rng(), NaN)).toThrow(RangeError);
|
|
83
|
+
expect(() => randomExponential(rng(), Infinity)).toThrow(RangeError);
|
|
84
|
+
});
|
|
70
85
|
it('is deterministic for the same seed', () => {
|
|
71
86
|
const a = rng();
|
|
72
87
|
const b = rng();
|
|
@@ -90,6 +105,10 @@ describe('randomGaussian', () => {
|
|
|
90
105
|
const samples = [0, 0.25];
|
|
91
106
|
expect(randomGaussian(() => samples.shift()!)).toBeCloseTo(0, 10);
|
|
92
107
|
});
|
|
108
|
+
it('matches a deterministic Box–Muller vector with mean and scale', () => {
|
|
109
|
+
const standard = Math.sqrt(-2 * Math.log(0.5));
|
|
110
|
+
expect(randomGaussian(sequenceRandom(0.5, 0), 10, 2)).toBeCloseTo(10 + standard * 2, 12);
|
|
111
|
+
});
|
|
93
112
|
it('is deterministic for the same seed', () => {
|
|
94
113
|
const a = rng();
|
|
95
114
|
const b = rng();
|
|
@@ -120,6 +139,10 @@ describe('randomGaussianPair', () => {
|
|
|
120
139
|
expect(z0).toBeCloseTo(0, 10);
|
|
121
140
|
expect(z1).toBeCloseTo(Math.sqrt(-2 * Math.log(Number.EPSILON)), 10);
|
|
122
141
|
});
|
|
142
|
+
it('matches both values of a deterministic Box–Muller pair', () => {
|
|
143
|
+
const component = Math.sqrt(-2 * Math.log(0.5)) * Math.SQRT1_2;
|
|
144
|
+
expect(randomGaussianPair(sequenceRandom(0.5, 0.125), 3, 2)).toEqual([3 + component * 2, 3 + component * 2]);
|
|
145
|
+
});
|
|
123
146
|
});
|
|
124
147
|
|
|
125
148
|
describe('randomInsideUnitDisc', () => {
|
|
@@ -151,6 +174,11 @@ describe('randomInsideUnitDisc', () => {
|
|
|
151
174
|
expect(outA.y).toBe(outB.y);
|
|
152
175
|
}
|
|
153
176
|
});
|
|
177
|
+
it('accepts and preserves a deterministic boundary point', () => {
|
|
178
|
+
const out = { x: 0, y: 0 };
|
|
179
|
+
randomInsideUnitDisc(sequenceRandom(1, 0.5, 0.5, 0.5), out);
|
|
180
|
+
expect(out).toEqual({ x: 1, y: 0 });
|
|
181
|
+
});
|
|
154
182
|
});
|
|
155
183
|
|
|
156
184
|
describe('randomInsideUnitSphere', () => {
|
|
@@ -183,6 +211,11 @@ describe('randomInsideUnitSphere', () => {
|
|
|
183
211
|
expect(outA.z).toBe(outB.z);
|
|
184
212
|
}
|
|
185
213
|
});
|
|
214
|
+
it('accepts and preserves a deterministic boundary point', () => {
|
|
215
|
+
const out = { x: 0, y: 0, z: 0 };
|
|
216
|
+
randomInsideUnitSphere(sequenceRandom(1, 0.5, 0.5, 0.5, 0.5, 0.5), out);
|
|
217
|
+
expect(out).toEqual({ x: 1, y: 0, z: 0 });
|
|
218
|
+
});
|
|
186
219
|
});
|
|
187
220
|
|
|
188
221
|
describe('randomOnUnitCircle', () => {
|
|
@@ -213,6 +246,12 @@ describe('randomOnUnitCircle', () => {
|
|
|
213
246
|
expect(outA.y).toBe(outB.y);
|
|
214
247
|
}
|
|
215
248
|
});
|
|
249
|
+
it('maps a quarter-turn sample to the top of the circle', () => {
|
|
250
|
+
const out = { x: 0, y: 0 };
|
|
251
|
+
randomOnUnitCircle(() => 0.25, out);
|
|
252
|
+
expect(out.x).toBeCloseTo(0, 12);
|
|
253
|
+
expect(out.y).toBeCloseTo(1, 12);
|
|
254
|
+
});
|
|
216
255
|
});
|
|
217
256
|
|
|
218
257
|
describe('randomOnUnitSphere', () => {
|
|
@@ -246,6 +285,18 @@ describe('randomOnUnitSphere', () => {
|
|
|
246
285
|
expect(outA.z).toBe(outB.z);
|
|
247
286
|
}
|
|
248
287
|
});
|
|
288
|
+
it('projects a deterministic disc sample onto the sphere', () => {
|
|
289
|
+
const out = { x: 0, y: 0, z: 0 };
|
|
290
|
+
randomOnUnitSphere(sequenceRandom(0.75, 0.5), out);
|
|
291
|
+
expect(out.x).toBeCloseTo(Math.sqrt(3) / 2, 12);
|
|
292
|
+
expect(out.y).toBe(0);
|
|
293
|
+
expect(out.z).toBe(0.5);
|
|
294
|
+
});
|
|
295
|
+
it('rejects a disc-boundary sample before projecting', () => {
|
|
296
|
+
const out = { x: 0, y: 0, z: 0 };
|
|
297
|
+
randomOnUnitSphere(sequenceRandom(1, 0.5, 0.5, 0.5), out);
|
|
298
|
+
expect(out).toEqual({ x: 0, y: 0, z: 1 });
|
|
299
|
+
});
|
|
249
300
|
});
|
|
250
301
|
|
|
251
302
|
describe('randomPoisson', () => {
|
|
@@ -275,6 +326,13 @@ describe('randomPoisson', () => {
|
|
|
275
326
|
expect(() => randomPoisson(rng(), 0)).toThrow(RangeError);
|
|
276
327
|
expect(() => randomPoisson(rng(), -1)).toThrow(RangeError);
|
|
277
328
|
});
|
|
329
|
+
it('rejects non-finite means', () => {
|
|
330
|
+
expect(() => randomPoisson(rng(), NaN)).toThrow(RangeError);
|
|
331
|
+
expect(() => randomPoisson(rng(), Infinity)).toThrow(RangeError);
|
|
332
|
+
});
|
|
333
|
+
it('stops when the product exactly reaches the limit', () => {
|
|
334
|
+
expect(randomPoisson(sequenceRandom(0.5, 0.5), Math.log(2))).toBe(0);
|
|
335
|
+
});
|
|
278
336
|
it('is deterministic for the same seed', () => {
|
|
279
337
|
const a = rng();
|
|
280
338
|
const b = rng();
|
|
@@ -307,6 +365,9 @@ describe('randomWeighted', () => {
|
|
|
307
365
|
it('falls back to the final bucket for an out-of-range random source', () => {
|
|
308
366
|
expect(randomWeighted(() => 1.1, [1, 2, 7])).toBe(2);
|
|
309
367
|
});
|
|
368
|
+
it('selects the earlier bucket when the sample lands exactly on its boundary', () => {
|
|
369
|
+
expect(randomWeighted(() => 1 / 3, [1, 2])).toBe(0);
|
|
370
|
+
});
|
|
310
371
|
it('is deterministic for the same seed', () => {
|
|
311
372
|
const a = rng();
|
|
312
373
|
const b = rng();
|
|
@@ -361,4 +422,15 @@ describe('shuffleInPlace', () => {
|
|
|
361
422
|
shuffleInPlace(rng(), b);
|
|
362
423
|
expect(a).toEqual(b);
|
|
363
424
|
});
|
|
425
|
+
it('pins the swaps and consumes exactly one sample per Fisher–Yates step', () => {
|
|
426
|
+
const values = [0.75, 0.5, 0.25];
|
|
427
|
+
let calls = 0;
|
|
428
|
+
const items = ['a', 'b', 'c', 'd'];
|
|
429
|
+
shuffleInPlace(() => {
|
|
430
|
+
calls++;
|
|
431
|
+
return values[calls - 1];
|
|
432
|
+
}, items);
|
|
433
|
+
expect(items).toEqual(['c', 'a', 'b', 'd']);
|
|
434
|
+
expect(calls).toBe(3);
|
|
435
|
+
});
|
|
364
436
|
});
|
package/src/randomRange.test.ts
CHANGED
|
@@ -19,6 +19,9 @@ describe('randomBool', () => {
|
|
|
19
19
|
const random = rng();
|
|
20
20
|
for (let i = 0; i < 10; i++) expect(randomBool(random, 0)).toBe(false);
|
|
21
21
|
});
|
|
22
|
+
it('uses a half-open comparison at the probability boundary', () => {
|
|
23
|
+
expect(randomBool(() => 0.5, 0.5)).toBe(false);
|
|
24
|
+
});
|
|
22
25
|
it('is deterministic for the same seed', () => {
|
|
23
26
|
const a = rng();
|
|
24
27
|
const b = rng();
|
|
@@ -44,6 +47,12 @@ describe('randomInt', () => {
|
|
|
44
47
|
const random = rng();
|
|
45
48
|
expect(() => randomInt(random, 10, 5)).toThrow(RangeError);
|
|
46
49
|
});
|
|
50
|
+
it('can select the inclusive upper endpoint', () => {
|
|
51
|
+
expect(randomInt(() => 0.999999, 2, 4)).toBe(4);
|
|
52
|
+
});
|
|
53
|
+
it('rounds negative fractional bounds down', () => {
|
|
54
|
+
expect(randomInt(() => 0, -1.2, -0.2)).toBe(-2);
|
|
55
|
+
});
|
|
47
56
|
it('is deterministic for the same seed', () => {
|
|
48
57
|
const a = rng();
|
|
49
58
|
const b = rng();
|
|
@@ -91,6 +100,9 @@ describe('randomSign', () => {
|
|
|
91
100
|
expect(sawPositive).toBe(true);
|
|
92
101
|
expect(sawNegative).toBe(true);
|
|
93
102
|
});
|
|
103
|
+
it('selects the positive sign at the half-open boundary', () => {
|
|
104
|
+
expect(randomSign(() => 0.5)).toBe(1);
|
|
105
|
+
});
|
|
94
106
|
it('is deterministic for the same seed', () => {
|
|
95
107
|
const a = rng();
|
|
96
108
|
const b = rng();
|
package/src/statistics.test.ts
CHANGED
|
@@ -13,6 +13,17 @@ describe('mean', () => {
|
|
|
13
13
|
it('handles negative values', () => {
|
|
14
14
|
expect(mean([-2, 0, 2])).toBe(0);
|
|
15
15
|
});
|
|
16
|
+
it('does not overflow when the finite mean is representable', () => {
|
|
17
|
+
expect(mean([Number.MAX_VALUE, Number.MAX_VALUE])).toBe(Number.MAX_VALUE);
|
|
18
|
+
});
|
|
19
|
+
it('retains a small term across cancellation', () => {
|
|
20
|
+
expect(mean([1, Number.EPSILON / 2, -1])).toBe(Number.EPSILON / 6);
|
|
21
|
+
});
|
|
22
|
+
it('preserves zero and non-finite propagation', () => {
|
|
23
|
+
expect(mean([0, 0])).toBe(0);
|
|
24
|
+
expect(mean([Infinity, Infinity])).toBe(Infinity);
|
|
25
|
+
expect(mean([Infinity, -Infinity])).toBeNaN();
|
|
26
|
+
});
|
|
16
27
|
});
|
|
17
28
|
|
|
18
29
|
describe('median', () => {
|
|
@@ -31,6 +42,17 @@ describe('median', () => {
|
|
|
31
42
|
median(values);
|
|
32
43
|
expect(values).toEqual(original);
|
|
33
44
|
});
|
|
45
|
+
it('does not overflow when averaging identical finite middle values', () => {
|
|
46
|
+
expect(median([Number.MAX_VALUE, Number.MAX_VALUE])).toBe(Number.MAX_VALUE);
|
|
47
|
+
});
|
|
48
|
+
it('does not prematurely underflow when averaging subnormal middle values', () => {
|
|
49
|
+
expect(median([Number.MIN_VALUE * 2, Number.MIN_VALUE * 3])).toBe(Number.MIN_VALUE * 2);
|
|
50
|
+
});
|
|
51
|
+
it('averages negative and non-finite middle values without changing their semantics', () => {
|
|
52
|
+
expect(median([-4, -2])).toBe(-3);
|
|
53
|
+
expect(median([-Number.MAX_VALUE, Number.MAX_VALUE])).toBe(0);
|
|
54
|
+
expect(median([Infinity, Infinity])).toBe(Infinity);
|
|
55
|
+
});
|
|
34
56
|
});
|
|
35
57
|
|
|
36
58
|
describe('standardDeviation', () => {
|
|
@@ -43,6 +65,13 @@ describe('standardDeviation', () => {
|
|
|
43
65
|
it('computes the population standard deviation', () => {
|
|
44
66
|
expect(standardDeviation([2, 4, 4, 4, 5, 5, 7, 9])).toBeCloseTo(2, 5);
|
|
45
67
|
});
|
|
68
|
+
it('returns zero for identical maximum finite values', () => {
|
|
69
|
+
expect(standardDeviation([Number.MAX_VALUE, Number.MAX_VALUE])).toBe(0);
|
|
70
|
+
});
|
|
71
|
+
it('handles zero and preserves non-finite propagation', () => {
|
|
72
|
+
expect(standardDeviation([0, 0])).toBe(0);
|
|
73
|
+
expect(standardDeviation([Infinity])).toBeNaN();
|
|
74
|
+
});
|
|
46
75
|
});
|
|
47
76
|
|
|
48
77
|
describe('variance', () => {
|
|
@@ -55,6 +84,16 @@ describe('variance', () => {
|
|
|
55
84
|
it('computes the population variance', () => {
|
|
56
85
|
expect(variance([2, 4, 4, 4, 5, 5, 7, 9])).toBeCloseTo(4, 5);
|
|
57
86
|
});
|
|
87
|
+
it('returns zero for identical maximum finite values', () => {
|
|
88
|
+
expect(variance([Number.MAX_VALUE, Number.MAX_VALUE])).toBe(0);
|
|
89
|
+
});
|
|
90
|
+
it('compensates the sum of squared deviations', () => {
|
|
91
|
+
expect(variance([-1, 1_000_000_000_000, 1_000_000_000_000])).toBe(2.2222222222266665e23);
|
|
92
|
+
});
|
|
93
|
+
it('handles zero and preserves non-finite propagation', () => {
|
|
94
|
+
expect(variance([0, 0])).toBe(0);
|
|
95
|
+
expect(variance([Infinity])).toBeNaN();
|
|
96
|
+
});
|
|
58
97
|
});
|
|
59
98
|
|
|
60
99
|
describe('weightedAverage', () => {
|
|
@@ -71,4 +110,24 @@ describe('weightedAverage', () => {
|
|
|
71
110
|
it('throws when arrays have different lengths', () => {
|
|
72
111
|
expect(() => weightedAverage([1, 2], [1])).toThrow(RangeError);
|
|
73
112
|
});
|
|
113
|
+
it('does not overflow when the finite weighted average is representable', () => {
|
|
114
|
+
expect(weightedAverage([Number.MAX_VALUE, Number.MAX_VALUE], [1, 1])).toBe(Number.MAX_VALUE);
|
|
115
|
+
});
|
|
116
|
+
it('uses normalized weights in the weighted product', () => {
|
|
117
|
+
expect(weightedAverage([2, 10], [1, 3])).toBe(8);
|
|
118
|
+
});
|
|
119
|
+
it('retains small weighted terms across cancellation', () => {
|
|
120
|
+
expect(weightedAverage([10_000_000_000_000_000, -1_000_000_000_000_000, -10_000_000_000_000_000], [2, 1, 1])).toBe(
|
|
121
|
+
2_250_000_000_000_000,
|
|
122
|
+
);
|
|
123
|
+
});
|
|
124
|
+
it('handles zero values and cancelling non-zero weights', () => {
|
|
125
|
+
expect(weightedAverage([0, 0], [1, 1])).toBe(0);
|
|
126
|
+
expect(weightedAverage([1, 2], [1, -1])).toBeNaN();
|
|
127
|
+
});
|
|
128
|
+
it('preserves non-finite weighted-average propagation', () => {
|
|
129
|
+
expect(weightedAverage([Infinity], [1])).toBe(Infinity);
|
|
130
|
+
expect(weightedAverage([Infinity, 1], [1, -1])).toBeNaN();
|
|
131
|
+
expect(weightedAverage([1], [Infinity])).toBeNaN();
|
|
132
|
+
});
|
|
74
133
|
});
|