@flighthq/math 0.3.0 → 0.3.1-next.1041.35b950c
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 +16 -1
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +16 -1
- package/dist/constants.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.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/constants.test.ts +32 -1
- package/src/hash.test.ts +3 -0
- package/src/interpolationAdvanced.test.ts +14 -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 +88 -0
- package/src/randomRange.test.ts +12 -0
- package/src/statistics.test.ts +59 -0
package/dist/constants.d.ts
CHANGED
|
@@ -1,4 +1,19 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/**
|
|
2
|
+
* Control-point distance, as a fraction of the radius, for approximating a quarter circle with one
|
|
3
|
+
* cubic Bezier: `4 * (sqrt(2) - 1) / 3`.
|
|
4
|
+
*
|
|
5
|
+
* Named for the circle that defines it rather than the arcs that use it. Written as a literal and
|
|
6
|
+
* pinned to that formula by the colocated test, which IS the recomputation a transcribed decimal
|
|
7
|
+
* would otherwise lack — the digits are long enough that a wrong one reads as correct and still
|
|
8
|
+
* draws a circle that looks round.
|
|
9
|
+
*
|
|
10
|
+
* A literal rather than the expression because `Math.SQRT2` is a property of a mutable global: no
|
|
11
|
+
* correct minifier may evaluate `4 * (Math.SQRT2 - 1) / 3` at build time, so that form reaches the
|
|
12
|
+
* bundle as a runtime computation of a compile-time-known number. Neither form is inlined at its
|
|
13
|
+
* use sites and both measure the same gzipped size, so this buys evaluation, not bytes.
|
|
14
|
+
*/
|
|
15
|
+
export declare const CIRCLE_KAPPA = 0.5522847498307936;
|
|
16
|
+
/** Default absolute tolerance for approximate floating-point comparisons. */
|
|
2
17
|
export declare const EPSILON = 0.000001;
|
|
3
18
|
/** Full circle in radians (2π). Prefer `TAU` over `2 * Math.PI` for clarity. */
|
|
4
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,
|
|
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
|
@@ -1,4 +1,19 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/**
|
|
2
|
+
* Control-point distance, as a fraction of the radius, for approximating a quarter circle with one
|
|
3
|
+
* cubic Bezier: `4 * (sqrt(2) - 1) / 3`.
|
|
4
|
+
*
|
|
5
|
+
* Named for the circle that defines it rather than the arcs that use it. Written as a literal and
|
|
6
|
+
* pinned to that formula by the colocated test, which IS the recomputation a transcribed decimal
|
|
7
|
+
* would otherwise lack — the digits are long enough that a wrong one reads as correct and still
|
|
8
|
+
* draws a circle that looks round.
|
|
9
|
+
*
|
|
10
|
+
* A literal rather than the expression because `Math.SQRT2` is a property of a mutable global: no
|
|
11
|
+
* correct minifier may evaluate `4 * (Math.SQRT2 - 1) / 3` at build time, so that form reaches the
|
|
12
|
+
* bundle as a runtime computation of a compile-time-known number. Neither form is inlined at its
|
|
13
|
+
* use sites and both measure the same gzipped size, so this buys evaluation, not bytes.
|
|
14
|
+
*/
|
|
15
|
+
export const CIRCLE_KAPPA = 0.5522847498307936;
|
|
16
|
+
/** Default absolute tolerance for approximate floating-point comparisons. */
|
|
2
17
|
export const EPSILON = 1e-6;
|
|
3
18
|
/** Full circle in radians (2π). Prefer `TAU` over `2 * Math.PI` for clarity. */
|
|
4
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,
|
|
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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
export { DEG_TO_RAD, EPSILON, HALF_PI, RAD_TO_DEG,
|
|
1
|
+
export { CIRCLE_KAPPA, DEG_TO_RAD, EPSILON, HALF_PI, RAD_TO_DEG, TAU, approxEqual, approxEqualRelative, approxZero, ceilPowerOfTwo, ceilTo, clamp, createRandomSource, createRandomSourceFromHash, damp, degToRad, deltaAngle, euclideanMod, factorial, floorPowerOfTwo, floorTo, fract, gcd, hash2D, hash3D, hashCombine, hashUint32, hypot2, inRange, inverseLerp, isEven, isOdd, isPowerOfTwo, lcm, lerp, lerpAngle, mean, median, moveTowards, nextMultipleOf, nextPowerOfTwo, normalizeAngle, pick, pingPong, previousPowerOfTwo, quantize, radToDeg, randomBool, randomExponential, randomGaussian, randomGaussianPair, randomInsideUnitDisc, randomInsideUnitSphere, randomInt, randomOnUnitCircle, randomOnUnitSphere, randomPoisson, randomRange, randomSign, randomWeighted, remap, repeat, roundTo, saturate, shuffle, shuffleInPlace, sign, smoothStep, smootherStep, standardDeviation, step, variance, weightedAverage, } from './contract';
|
|
2
|
+
export type { RandomSource } from './contract';
|
|
2
3
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,OAAO,EACP,OAAO,EACP,UAAU,EACV,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,UAAU,EACV,OAAO,EACP,OAAO,EACP,UAAU,EACV,GAAG,EACH,WAAW,EACX,mBAAmB,EACnB,UAAU,EACV,cAAc,EACd,MAAM,EACN,KAAK,EACL,kBAAkB,EAClB,0BAA0B,EAC1B,IAAI,EACJ,QAAQ,EACR,UAAU,EACV,YAAY,EACZ,SAAS,EACT,eAAe,EACf,OAAO,EACP,KAAK,EACL,GAAG,EACH,MAAM,EACN,MAAM,EACN,WAAW,EACX,UAAU,EACV,MAAM,EACN,OAAO,EACP,WAAW,EACX,MAAM,EACN,KAAK,EACL,YAAY,EACZ,GAAG,EACH,IAAI,EACJ,SAAS,EACT,IAAI,EACJ,MAAM,EACN,WAAW,EACX,cAAc,EACd,cAAc,EACd,cAAc,EACd,IAAI,EACJ,QAAQ,EACR,kBAAkB,EAClB,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,iBAAiB,EACjB,cAAc,EACd,kBAAkB,EAClB,oBAAoB,EACpB,sBAAsB,EACtB,SAAS,EACT,kBAAkB,EAClB,kBAAkB,EAClB,aAAa,EACb,WAAW,EACX,UAAU,EACV,cAAc,EACd,KAAK,EACL,MAAM,EACN,OAAO,EACP,QAAQ,EACR,OAAO,EACP,cAAc,EACd,IAAI,EACJ,UAAU,EACV,YAAY,EACZ,iBAAiB,EACjB,IAAI,EACJ,QAAQ,EACR,eAAe,GAChB,MAAM,YAAY,CAAC;AAKpB,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { DEG_TO_RAD, EPSILON, HALF_PI, RAD_TO_DEG, TAU, approxEqual, approxEqualRelative, approxZero, ceilPowerOfTwo, ceilTo, clamp, createRandomSource, createRandomSourceFromHash, damp, degToRad, deltaAngle, euclideanMod, factorial, floorPowerOfTwo, floorTo, fract, gcd, hash2D, hash3D, hashCombine, hashUint32, hypot2, inRange, inverseLerp, isEven, isOdd, isPowerOfTwo, lcm, lerp, lerpAngle, mean, median, moveTowards, nextMultipleOf, nextPowerOfTwo, normalizeAngle, pick, pingPong, previousPowerOfTwo, quantize, radToDeg, randomBool, randomExponential, randomGaussian, randomGaussianPair, randomInsideUnitDisc, randomInsideUnitSphere, randomInt, randomOnUnitCircle, randomOnUnitSphere, randomPoisson, randomRange, randomSign, randomWeighted, remap, repeat, roundTo, saturate, shuffle, shuffleInPlace, sign, smoothStep, smootherStep, standardDeviation, step, variance, weightedAverage, } from './contract';
|
|
1
|
+
export { CIRCLE_KAPPA, DEG_TO_RAD, EPSILON, HALF_PI, RAD_TO_DEG, TAU, approxEqual, approxEqualRelative, approxZero, ceilPowerOfTwo, ceilTo, clamp, createRandomSource, createRandomSourceFromHash, damp, degToRad, deltaAngle, euclideanMod, factorial, floorPowerOfTwo, floorTo, fract, gcd, hash2D, hash3D, hashCombine, hashUint32, hypot2, inRange, inverseLerp, isEven, isOdd, isPowerOfTwo, lcm, lerp, lerpAngle, mean, median, moveTowards, nextMultipleOf, nextPowerOfTwo, normalizeAngle, pick, pingPong, previousPowerOfTwo, quantize, radToDeg, randomBool, randomExponential, randomGaussian, randomGaussianPair, randomInsideUnitDisc, randomInsideUnitSphere, randomInt, randomOnUnitCircle, randomOnUnitSphere, randomPoisson, randomRange, randomSign, randomWeighted, remap, repeat, roundTo, saturate, shuffle, shuffleInPlace, sign, smoothStep, smootherStep, standardDeviation, step, variance, weightedAverage, } from './contract';
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,OAAO,EACP,OAAO,EACP,UAAU,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,UAAU,EACV,OAAO,EACP,OAAO,EACP,UAAU,EACV,GAAG,EACH,WAAW,EACX,mBAAmB,EACnB,UAAU,EACV,cAAc,EACd,MAAM,EACN,KAAK,EACL,kBAAkB,EAClB,0BAA0B,EAC1B,IAAI,EACJ,QAAQ,EACR,UAAU,EACV,YAAY,EACZ,SAAS,EACT,eAAe,EACf,OAAO,EACP,KAAK,EACL,GAAG,EACH,MAAM,EACN,MAAM,EACN,WAAW,EACX,UAAU,EACV,MAAM,EACN,OAAO,EACP,WAAW,EACX,MAAM,EACN,KAAK,EACL,YAAY,EACZ,GAAG,EACH,IAAI,EACJ,SAAS,EACT,IAAI,EACJ,MAAM,EACN,WAAW,EACX,cAAc,EACd,cAAc,EACd,cAAc,EACd,IAAI,EACJ,QAAQ,EACR,kBAAkB,EAClB,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,iBAAiB,EACjB,cAAc,EACd,kBAAkB,EAClB,oBAAoB,EACpB,sBAAsB,EACtB,SAAS,EACT,kBAAkB,EAClB,kBAAkB,EAClB,aAAa,EACb,WAAW,EACX,UAAU,EACV,cAAc,EACd,KAAK,EACL,MAAM,EACN,OAAO,EACP,QAAQ,EACR,OAAO,EACP,cAAc,EACd,IAAI,EACJ,UAAU,EACV,YAAY,EACZ,iBAAiB,EACjB,IAAI,EACJ,QAAQ,EACR,eAAe,GAChB,MAAM,YAAY,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.
|
|
3
|
+
"version": "0.3.1-next.1041.35b950c",
|
|
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.
|
|
41
|
+
"@flighthq/types": "0.3.1-next.1041.35b950c"
|
|
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/constants.test.ts
CHANGED
|
@@ -1,6 +1,37 @@
|
|
|
1
|
-
import { DEG_TO_RAD, EPSILON, HALF_PI, RAD_TO_DEG, TAU } from './constants';
|
|
1
|
+
import { CIRCLE_KAPPA, DEG_TO_RAD, EPSILON, HALF_PI, RAD_TO_DEG, TAU } from './constants';
|
|
2
2
|
|
|
3
3
|
describe('constants', () => {
|
|
4
|
+
describe('CIRCLE_KAPPA', () => {
|
|
5
|
+
// Asserted against the COMPUTED expression, never a transcribed decimal. A test that restates the
|
|
6
|
+
// digits agrees with a typo in them, which is how a wrong digit at the 13th decimal survived a
|
|
7
|
+
// full suite. Exact equality, not toBeCloseTo: the error this guards against is far smaller than
|
|
8
|
+
// any tolerance worth writing.
|
|
9
|
+
//
|
|
10
|
+
// MEASURED, not assumed: mutating the constant's 13th decimal from ...36 to ...46 and running
|
|
11
|
+
// the whole repository fails exactly ONE test of 17,045 — this one. The sweep below passes over
|
|
12
|
+
// the wrong digit, as does every path, shape and clip test. That is the entire case for pinning
|
|
13
|
+
// a literal to its formula here rather than trusting geometry to notice, and it is why the
|
|
14
|
+
// original wrong digit survived a full suite.
|
|
15
|
+
it('equals four thirds of the square root of two less one', () => {
|
|
16
|
+
expect(CIRCLE_KAPPA).toBe((4 * (Math.sqrt(2) - 1)) / 3);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it('sweeps a unit quarter circle when used as the cubic control distance', () => {
|
|
20
|
+
// Catches a wrong FORMULA, not a wrong digit — and only that. A mistyped decimal moves the
|
|
21
|
+
// swept radius far less than the cubic's own approximation error, so this cannot stand in for
|
|
22
|
+
// the exact equality above. What it does add is independence from it: if the constant and that
|
|
23
|
+
// assertion were ever edited to agree on a wrong expression, the geometry would still object.
|
|
24
|
+
const radiusAt = (t: number): number => {
|
|
25
|
+
const u = 1 - t;
|
|
26
|
+
const x = u * u * u + 3 * u * u * t + 3 * u * t * t * CIRCLE_KAPPA;
|
|
27
|
+
const y = 3 * u * u * t * CIRCLE_KAPPA + 3 * u * t * t + t * t * t;
|
|
28
|
+
return Math.hypot(x, y);
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
for (const t of [0, 0.25, 0.5, 0.75, 1]) expect(radiusAt(t)).toBeCloseTo(1, 3);
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
|
|
4
35
|
describe('DEG_TO_RAD', () => {
|
|
5
36
|
it('converts 180 degrees to π', () => {
|
|
6
37
|
expect(180 * DEG_TO_RAD).toBeCloseTo(Math.PI, 10);
|
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', () => {
|
|
@@ -38,6 +38,10 @@ describe('lerpAngle', () => {
|
|
|
38
38
|
const normalised = ((result % TAU) + TAU) % TAU;
|
|
39
39
|
expect(normalised).toBeCloseTo(0, 5);
|
|
40
40
|
});
|
|
41
|
+
it('takes the shortest arc clockwise across 0/2π', () => {
|
|
42
|
+
const result = lerpAngle(Math.PI * 0.1, Math.PI * 1.9, 0.5);
|
|
43
|
+
expect(result).toBeCloseTo(0, 10);
|
|
44
|
+
});
|
|
41
45
|
it('returns a at t = 0', () => {
|
|
42
46
|
expect(lerpAngle(1, 2, 0)).toBeCloseTo(1, 10);
|
|
43
47
|
});
|
|
@@ -71,8 +75,11 @@ describe('pingPong', () => {
|
|
|
71
75
|
it('bounces back at t = 1.5 * length', () => {
|
|
72
76
|
expect(pingPong(1.5, 1)).toBeCloseTo(0.5, 10);
|
|
73
77
|
});
|
|
74
|
-
|
|
75
|
-
|
|
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();
|
|
76
83
|
});
|
|
77
84
|
it('works with larger lengths', () => {
|
|
78
85
|
expect(pingPong(3, 2)).toBeCloseTo(1, 10);
|
|
@@ -91,8 +98,11 @@ describe('repeat', () => {
|
|
|
91
98
|
expect(r).toBeGreaterThanOrEqual(0);
|
|
92
99
|
expect(r).toBeLessThan(1);
|
|
93
100
|
});
|
|
94
|
-
|
|
95
|
-
|
|
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();
|
|
96
106
|
});
|
|
97
107
|
});
|
|
98
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();
|
|
@@ -60,10 +71,17 @@ describe('randomExponential', () => {
|
|
|
60
71
|
for (let i = 0; i < n; i++) sum += randomExponential(random, 2);
|
|
61
72
|
expect(sum / n).toBeCloseTo(0.5, 0);
|
|
62
73
|
});
|
|
74
|
+
it('substitutes epsilon when the random source returns zero', () => {
|
|
75
|
+
expect(randomExponential(() => 0)).toBe(-Math.log(Number.EPSILON));
|
|
76
|
+
});
|
|
63
77
|
it('throws for rate <= 0', () => {
|
|
64
78
|
expect(() => randomExponential(rng(), 0)).toThrow(RangeError);
|
|
65
79
|
expect(() => randomExponential(rng(), -1)).toThrow(RangeError);
|
|
66
80
|
});
|
|
81
|
+
it('rejects non-finite rates', () => {
|
|
82
|
+
expect(() => randomExponential(rng(), NaN)).toThrow(RangeError);
|
|
83
|
+
expect(() => randomExponential(rng(), Infinity)).toThrow(RangeError);
|
|
84
|
+
});
|
|
67
85
|
it('is deterministic for the same seed', () => {
|
|
68
86
|
const a = rng();
|
|
69
87
|
const b = rng();
|
|
@@ -83,6 +101,14 @@ describe('randomGaussian', () => {
|
|
|
83
101
|
for (let i = 0; i < n; i++) sum += randomGaussian(random, 5, 1);
|
|
84
102
|
expect(sum / n).toBeCloseTo(5, 0);
|
|
85
103
|
});
|
|
104
|
+
it('substitutes epsilon when the first random sample is zero', () => {
|
|
105
|
+
const samples = [0, 0.25];
|
|
106
|
+
expect(randomGaussian(() => samples.shift()!)).toBeCloseTo(0, 10);
|
|
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
|
+
});
|
|
86
112
|
it('is deterministic for the same seed', () => {
|
|
87
113
|
const a = rng();
|
|
88
114
|
const b = rng();
|
|
@@ -107,6 +133,16 @@ describe('randomGaussianPair', () => {
|
|
|
107
133
|
}
|
|
108
134
|
expect(sum / (n * 2)).toBeCloseTo(10, 0);
|
|
109
135
|
});
|
|
136
|
+
it('substitutes epsilon when the first random sample is zero', () => {
|
|
137
|
+
const samples = [0, 0.25];
|
|
138
|
+
const [z0, z1] = randomGaussianPair(() => samples.shift()!);
|
|
139
|
+
expect(z0).toBeCloseTo(0, 10);
|
|
140
|
+
expect(z1).toBeCloseTo(Math.sqrt(-2 * Math.log(Number.EPSILON)), 10);
|
|
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
|
+
});
|
|
110
146
|
});
|
|
111
147
|
|
|
112
148
|
describe('randomInsideUnitDisc', () => {
|
|
@@ -138,6 +174,11 @@ describe('randomInsideUnitDisc', () => {
|
|
|
138
174
|
expect(outA.y).toBe(outB.y);
|
|
139
175
|
}
|
|
140
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
|
+
});
|
|
141
182
|
});
|
|
142
183
|
|
|
143
184
|
describe('randomInsideUnitSphere', () => {
|
|
@@ -170,6 +211,11 @@ describe('randomInsideUnitSphere', () => {
|
|
|
170
211
|
expect(outA.z).toBe(outB.z);
|
|
171
212
|
}
|
|
172
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
|
+
});
|
|
173
219
|
});
|
|
174
220
|
|
|
175
221
|
describe('randomOnUnitCircle', () => {
|
|
@@ -200,6 +246,12 @@ describe('randomOnUnitCircle', () => {
|
|
|
200
246
|
expect(outA.y).toBe(outB.y);
|
|
201
247
|
}
|
|
202
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
|
+
});
|
|
203
255
|
});
|
|
204
256
|
|
|
205
257
|
describe('randomOnUnitSphere', () => {
|
|
@@ -233,6 +285,18 @@ describe('randomOnUnitSphere', () => {
|
|
|
233
285
|
expect(outA.z).toBe(outB.z);
|
|
234
286
|
}
|
|
235
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
|
+
});
|
|
236
300
|
});
|
|
237
301
|
|
|
238
302
|
describe('randomPoisson', () => {
|
|
@@ -262,6 +326,13 @@ describe('randomPoisson', () => {
|
|
|
262
326
|
expect(() => randomPoisson(rng(), 0)).toThrow(RangeError);
|
|
263
327
|
expect(() => randomPoisson(rng(), -1)).toThrow(RangeError);
|
|
264
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
|
+
});
|
|
265
336
|
it('is deterministic for the same seed', () => {
|
|
266
337
|
const a = rng();
|
|
267
338
|
const b = rng();
|
|
@@ -291,6 +362,12 @@ describe('randomWeighted', () => {
|
|
|
291
362
|
expect(randomWeighted(random, [0, 10, 0])).toBe(1);
|
|
292
363
|
}
|
|
293
364
|
});
|
|
365
|
+
it('falls back to the final bucket for an out-of-range random source', () => {
|
|
366
|
+
expect(randomWeighted(() => 1.1, [1, 2, 7])).toBe(2);
|
|
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
|
+
});
|
|
294
371
|
it('is deterministic for the same seed', () => {
|
|
295
372
|
const a = rng();
|
|
296
373
|
const b = rng();
|
|
@@ -345,4 +422,15 @@ describe('shuffleInPlace', () => {
|
|
|
345
422
|
shuffleInPlace(rng(), b);
|
|
346
423
|
expect(a).toEqual(b);
|
|
347
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
|
+
});
|
|
348
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
|
});
|