@thi.ng/math 5.7.6 → 5.7.7

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/CHANGELOG.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Change Log
2
2
 
3
- - **Last updated**: 2023-12-09T19:12:03Z
3
+ - **Last updated**: 2023-12-11T10:07:09Z
4
4
  - **Generator**: [thi.ng/monopub](https://thi.ng/monopub)
5
5
 
6
6
  All notable changes to this project will be documented in this file.
package/README.md CHANGED
@@ -67,7 +67,7 @@ For Node.js REPL:
67
67
  const math = await import("@thi.ng/math");
68
68
  ```
69
69
 
70
- Package sizes (brotli'd, pre-treeshake): ESM: 4.08 KB
70
+ Package sizes (brotli'd, pre-treeshake): ESM: 4.07 KB
71
71
 
72
72
  ## Dependencies
73
73
 
package/abs.js CHANGED
@@ -1,3 +1,7 @@
1
1
  import { EPS } from "./api.js";
2
- export const absDiff = (x, y) => Math.abs(x - y);
3
- export const sign = (x, eps = EPS) => (x > eps ? 1 : x < -eps ? -1 : 0);
2
+ const absDiff = (x, y) => Math.abs(x - y);
3
+ const sign = (x, eps = EPS) => x > eps ? 1 : x < -eps ? -1 : 0;
4
+ export {
5
+ absDiff,
6
+ sign
7
+ };
package/angle.js CHANGED
@@ -1,129 +1,61 @@
1
1
  import { DEG2RAD, HALF_PI, INV_HALF_PI, PI, RAD2DEG, TAU } from "./api.js";
2
- /**
3
- * Returns vector of `[sin(theta)*n, cos(theta)*n]`.
4
- *
5
- * @param theta -
6
- * @param n -
7
- */
8
- export const sincos = (theta, n = 1) => [
9
- Math.sin(theta) * n,
10
- Math.cos(theta) * n,
2
+ const sincos = (theta, n = 1) => [
3
+ Math.sin(theta) * n,
4
+ Math.cos(theta) * n
11
5
  ];
12
- /**
13
- * Returns vector of `[cos(theta)*n, sin(theta)*n]`.
14
- *
15
- * @param theta -
16
- * @param n -
17
- */
18
- export const cossin = (theta, n = 1) => [
19
- Math.cos(theta) * n,
20
- Math.sin(theta) * n,
6
+ const cossin = (theta, n = 1) => [
7
+ Math.cos(theta) * n,
8
+ Math.sin(theta) * n
21
9
  ];
22
- /**
23
- * Projects `theta` into [0 .. 2π] interval.
24
- *
25
- * @param theta -
26
- */
27
- export const absTheta = (theta) => ((theta %= TAU), theta < 0 ? TAU + theta : theta);
28
- export const absInnerAngle = (theta) => ((theta = Math.abs(theta)), theta > PI ? TAU - theta : theta);
29
- /**
30
- * Returns smallest absolute angle difference between `a` and `b`.
31
- * Result will be in [0 .. π] interval.
32
- *
33
- * @param a -
34
- * @param b -
35
- */
36
- export const angleDist = (a, b) => absInnerAngle(absTheta((b % TAU) - (a % TAU)));
37
- /**
38
- * Like `Math.atan2`, but always returns angle in [0 .. TAU) interval.
39
- *
40
- * @param y -
41
- * @param x -
42
- */
43
- export const atan2Abs = (y, x) => absTheta(Math.atan2(y, x));
44
- /**
45
- * Returns quadrant ID (0-3) of given angle (in radians).
46
- *
47
- * @param theta -
48
- */
49
- export const quadrant = (theta) => (absTheta(theta) * INV_HALF_PI) | 0;
50
- /**
51
- * Converts angle to degrees.
52
- *
53
- * @param theta - angle in radians
54
- */
55
- export const deg = (theta) => theta * RAD2DEG;
56
- /**
57
- * Converts angle to radians.
58
- *
59
- * @param theta - angle in degrees
60
- */
61
- export const rad = (theta) => theta * DEG2RAD;
62
- /**
63
- * Cosecant. Approaches `±Infinity` for `theta` near multiples of π.
64
- *
65
- * @param theta - angle in radians
66
- */
67
- export const csc = (theta) => 1 / Math.sin(theta);
68
- /**
69
- * Secant. Approaches `±Infinity` for `theta` near π/2 ± nπ
70
- *
71
- * @param theta - angle in radians
72
- */
73
- export const sec = (theta) => 1 / Math.cos(theta);
74
- /**
75
- * Cotangent. Approaches `±Infinity` for `theta` near multiples of π.
76
- *
77
- * @param theta - angle in radians
78
- */
79
- export const cot = (theta) => 1 / Math.tan(theta);
80
- /**
81
- * Law of Cosines. Takes length of two sides of a triangle and the inner
82
- * angle (in radians) between them. Returns length of third side.
83
- *
84
- * @param a -
85
- * @param b -
86
- * @param gamma -
87
- */
88
- export const loc = (a, b, gamma) => Math.sqrt(a * a + b * b - 2 * a * b * Math.cos(gamma));
89
- /**
90
- * Approximates cos(xπ) for x in [-1,1]
91
- *
92
- * @param x -
93
- */
94
- export const normCos = (x) => {
95
- const x2 = x * x;
96
- return 1.0 + x2 * (-4 + 2 * x2);
10
+ const absTheta = (theta) => (theta %= TAU, theta < 0 ? TAU + theta : theta);
11
+ const absInnerAngle = (theta) => (theta = Math.abs(theta), theta > PI ? TAU - theta : theta);
12
+ const angleDist = (a, b) => absInnerAngle(absTheta(b % TAU - a % TAU));
13
+ const atan2Abs = (y, x) => absTheta(Math.atan2(y, x));
14
+ const quadrant = (theta) => absTheta(theta) * INV_HALF_PI | 0;
15
+ const deg = (theta) => theta * RAD2DEG;
16
+ const rad = (theta) => theta * DEG2RAD;
17
+ const csc = (theta) => 1 / Math.sin(theta);
18
+ const sec = (theta) => 1 / Math.cos(theta);
19
+ const cot = (theta) => 1 / Math.tan(theta);
20
+ const loc = (a, b, gamma) => Math.sqrt(a * a + b * b - 2 * a * b * Math.cos(gamma));
21
+ const normCos = (x) => {
22
+ const x2 = x * x;
23
+ return 1 + x2 * (-4 + 2 * x2);
97
24
  };
98
25
  const __fastCos = (x) => {
99
- const x2 = x * x;
100
- return 0.99940307 + x2 * (-0.49558072 + 0.03679168 * x2);
26
+ const x2 = x * x;
27
+ return 0.99940307 + x2 * (-0.49558072 + 0.03679168 * x2);
101
28
  };
102
- /**
103
- * Fast cosine approximation using {@link normCos} (polynomial). Max. error
104
- * ~0.00059693
105
- *
106
- * In [0 .. 2π] interval, approx. 18-20% faster than `Math.cos` on V8.
107
- *
108
- * @param theta - in radians
109
- */
110
- export const fastCos = (theta) => {
111
- theta %= TAU;
112
- theta < 0 && (theta = -theta);
113
- switch ((theta * INV_HALF_PI) | 0) {
114
- case 0:
115
- return __fastCos(theta);
116
- case 1:
117
- return -__fastCos(PI - theta);
118
- case 2:
119
- return -__fastCos(theta - PI);
120
- default:
121
- return __fastCos(TAU - theta);
122
- }
29
+ const fastCos = (theta) => {
30
+ theta %= TAU;
31
+ theta < 0 && (theta = -theta);
32
+ switch (theta * INV_HALF_PI | 0) {
33
+ case 0:
34
+ return __fastCos(theta);
35
+ case 1:
36
+ return -__fastCos(PI - theta);
37
+ case 2:
38
+ return -__fastCos(theta - PI);
39
+ default:
40
+ return __fastCos(TAU - theta);
41
+ }
42
+ };
43
+ const fastSin = (theta) => fastCos(HALF_PI - theta);
44
+ export {
45
+ absInnerAngle,
46
+ absTheta,
47
+ angleDist,
48
+ atan2Abs,
49
+ cossin,
50
+ cot,
51
+ csc,
52
+ deg,
53
+ fastCos,
54
+ fastSin,
55
+ loc,
56
+ normCos,
57
+ quadrant,
58
+ rad,
59
+ sec,
60
+ sincos
123
61
  };
124
- /**
125
- * {@link fastCos}
126
- *
127
- * @param theta - in radians
128
- */
129
- export const fastSin = (theta) => fastCos(HALF_PI - theta);
package/api.js CHANGED
@@ -1,20 +1,42 @@
1
- export const PI = Math.PI;
2
- export const TAU = PI * 2;
3
- export const HALF_PI = PI / 2;
4
- export const THIRD_PI = PI / 3;
5
- export const QUARTER_PI = PI / 4;
6
- export const SIXTH_PI = PI / 6;
7
- export const INV_PI = 1 / PI;
8
- export const INV_TAU = 1 / TAU;
9
- export const INV_HALF_PI = 1 / HALF_PI;
10
- export const DEG2RAD = PI / 180;
11
- export const RAD2DEG = 180 / PI;
12
- export const PHI = (1 + Math.sqrt(5)) / 2;
13
- export const SQRT2 = Math.SQRT2;
14
- export const SQRT3 = Math.sqrt(3);
15
- export const SQRT2_2 = SQRT2 / 2;
16
- export const SQRT3_2 = SQRT3 / 2;
17
- export const THIRD = 1 / 3;
18
- export const TWO_THIRD = 2 / 3;
19
- export const SIXTH = 1 / 6;
20
- export let EPS = 1e-6;
1
+ const PI = Math.PI;
2
+ const TAU = PI * 2;
3
+ const HALF_PI = PI / 2;
4
+ const THIRD_PI = PI / 3;
5
+ const QUARTER_PI = PI / 4;
6
+ const SIXTH_PI = PI / 6;
7
+ const INV_PI = 1 / PI;
8
+ const INV_TAU = 1 / TAU;
9
+ const INV_HALF_PI = 1 / HALF_PI;
10
+ const DEG2RAD = PI / 180;
11
+ const RAD2DEG = 180 / PI;
12
+ const PHI = (1 + Math.sqrt(5)) / 2;
13
+ const SQRT2 = Math.SQRT2;
14
+ const SQRT3 = Math.sqrt(3);
15
+ const SQRT2_2 = SQRT2 / 2;
16
+ const SQRT3_2 = SQRT3 / 2;
17
+ const THIRD = 1 / 3;
18
+ const TWO_THIRD = 2 / 3;
19
+ const SIXTH = 1 / 6;
20
+ let EPS = 1e-6;
21
+ export {
22
+ DEG2RAD,
23
+ EPS,
24
+ HALF_PI,
25
+ INV_HALF_PI,
26
+ INV_PI,
27
+ INV_TAU,
28
+ PHI,
29
+ PI,
30
+ QUARTER_PI,
31
+ RAD2DEG,
32
+ SIXTH,
33
+ SIXTH_PI,
34
+ SQRT2,
35
+ SQRT2_2,
36
+ SQRT3,
37
+ SQRT3_2,
38
+ TAU,
39
+ THIRD,
40
+ THIRD_PI,
41
+ TWO_THIRD
42
+ };
package/crossing.js CHANGED
@@ -1,60 +1,10 @@
1
1
  import { EPS } from "./api.js";
2
2
  import { eqDelta } from "./eqdelta.js";
3
- /**
4
- * Returns true if line A rises up over B.
5
- *
6
- * @example
7
- * ```ts
8
- * b1 a2
9
- * \/
10
- * /\
11
- * a1 b2
12
- * ```
13
- *
14
- * @param a1 -
15
- * @param a2 -
16
- * @param b1 -
17
- * @param b2 -
18
- */
19
- export const isCrossOver = (a1, a2, b1, b2) => a1 < b1 && a2 > b2;
20
- /**
21
- * Returns true if line A rises up over B.
22
- *
23
- * @example
24
- * ```ts
25
- * a1 b2
26
- * \/
27
- * /\
28
- * b1 a2
29
- * ```
30
- *
31
- * @param a1 -
32
- * @param a2 -
33
- * @param b1 -
34
- * @param b2 -
35
- */
36
- export const isCrossUnder = (a1, a2, b1, b2) => a1 > b1 && a2 < b2;
37
- /**
38
- * Returns {@link Crossing} classifier indicating the relationship of line A
39
- * to line B. The optional epsilon value is used to determine if both
40
- * lines are considered equal or flat.
41
- *
42
- * - {@link isCrossOver}
43
- * - {@link isCrossUnder}
44
- * - {@link Crossing}
45
- *
46
- * @param a1 -
47
- * @param a2 -
48
- * @param b1 -
49
- * @param b2 -
50
- * @param eps -
51
- */
52
- export const classifyCrossing = (a1, a2, b1, b2, eps = EPS) => eqDelta(a1, b1, eps) && eqDelta(a2, b2, eps)
53
- ? eqDelta(a1, b2, eps)
54
- ? "flat"
55
- : "equal"
56
- : isCrossOver(a1, a2, b1, b2)
57
- ? "over"
58
- : isCrossUnder(a1, a2, b1, b2)
59
- ? "under"
60
- : "other";
3
+ const isCrossOver = (a1, a2, b1, b2) => a1 < b1 && a2 > b2;
4
+ const isCrossUnder = (a1, a2, b1, b2) => a1 > b1 && a2 < b2;
5
+ const classifyCrossing = (a1, a2, b1, b2, eps = EPS) => eqDelta(a1, b1, eps) && eqDelta(a2, b2, eps) ? eqDelta(a1, b2, eps) ? "flat" : "equal" : isCrossOver(a1, a2, b1, b2) ? "over" : isCrossUnder(a1, a2, b1, b2) ? "under" : "other";
6
+ export {
7
+ classifyCrossing,
8
+ isCrossOver,
9
+ isCrossUnder
10
+ };
package/eqdelta.js CHANGED
@@ -1,25 +1,9 @@
1
1
  import { EPS } from "./api.js";
2
2
  const abs = Math.abs;
3
3
  const max = Math.max;
4
- /**
5
- * Similar to {@link eqDeltaScaled}, but uses given `eps` as is.
6
- *
7
- * @param a - left value
8
- * @param b - right value
9
- * @param eps - epsilon / tolerance, default `1e-6`
10
- */
11
- export const eqDelta = (a, b, eps = EPS) => abs(a - b) <= eps;
12
- /**
13
- * Checks if `|a - b| <= ε` and adapts given epsilon value to the given
14
- * arguments:
15
- *
16
- * ε is factored with the largest absolute value of `a` or `b` (but
17
- * never lesser than the given `eps` value):
18
- *
19
- * `ε = ε * max(1, |a|, |b|)`
20
- *
21
- * @param a - left value
22
- * @param b - right value
23
- * @param eps - epsilon / tolerance, default `1e-6`
24
- */
25
- export const eqDeltaScaled = (a, b, eps = EPS) => abs(a - b) <= eps * max(1, abs(a), abs(b));
4
+ const eqDelta = (a, b, eps = EPS) => abs(a - b) <= eps;
5
+ const eqDeltaScaled = (a, b, eps = EPS) => abs(a - b) <= eps * max(1, abs(a), abs(b));
6
+ export {
7
+ eqDelta,
8
+ eqDeltaScaled
9
+ };
package/extrema.js CHANGED
@@ -1,74 +1,32 @@
1
- /**
2
- * Returns true if `b` is a local minima, i.e. iff a > b and b < c.
3
- *
4
- * @param a -
5
- * @param b -
6
- * @param c -
7
- */
8
- export const isMinima = (a, b, c) => a > b && b < c;
9
- /**
10
- * Returns true if `b` is a local maxima, i.e. iff a < b and b > c.
11
- *
12
- * @param a -
13
- * @param b -
14
- * @param c -
15
- */
16
- export const isMaxima = (a, b, c) => a < b && b > c;
1
+ const isMinima = (a, b, c) => a > b && b < c;
2
+ const isMaxima = (a, b, c) => a < b && b > c;
17
3
  const index = (pred, values, from = 0, to = values.length) => {
18
- to--;
19
- for (let i = from + 1; i < to; i++) {
20
- if (pred(values[i - 1], values[i], values[i + 1])) {
21
- return i;
22
- }
4
+ to--;
5
+ for (let i = from + 1; i < to; i++) {
6
+ if (pred(values[i - 1], values[i], values[i + 1])) {
7
+ return i;
23
8
  }
24
- return -1;
9
+ }
10
+ return -1;
25
11
  };
26
- /**
27
- * Returns index of the first local & internal minima found in given
28
- * `values` array, or -1 if no such minima exists. The search range can
29
- * be optionally defined via semi-open [from, to) index interval.
30
- *
31
- * @param values -
32
- * @param from -
33
- * @param to -
34
- */
35
- export const minimaIndex = (values, from = 0, to = values.length) => index(isMinima, values, from, to);
36
- /**
37
- * Returns index of the first local & internal maxima found in given
38
- * `values` array, or -1 if no such maxima exists. The search range can
39
- * be optionally defined via semi-open [from, to) index interval.
40
- *
41
- * @param values -
42
- * @param from -
43
- * @param to -
44
- */
45
- export const maximaIndex = (values, from = 0, to = values.length) => index(isMaxima, values, from, to);
12
+ const minimaIndex = (values, from = 0, to = values.length) => index(isMinima, values, from, to);
13
+ const maximaIndex = (values, from = 0, to = values.length) => index(isMaxima, values, from, to);
46
14
  function* indices(fn, vals, from = 0, to = vals.length) {
47
- while (from < to) {
48
- const i = fn(vals, from, to);
49
- if (i < 0)
50
- return;
51
- yield i;
52
- from = i + 1;
53
- }
15
+ while (from < to) {
16
+ const i = fn(vals, from, to);
17
+ if (i < 0)
18
+ return;
19
+ yield i;
20
+ from = i + 1;
21
+ }
54
22
  }
55
- /**
56
- * Returns an iterator yielding all minima indices in given `values`
57
- * array. The search range can be optionally defined via semi-open
58
- * [from, to) index interval.
59
- *
60
- * @param values -
61
- * @param from -
62
- * @param to -
63
- */
64
- export const minimaIndices = (values, from = 0, to = values.length) => indices(minimaIndex, values, from, to);
65
- /**
66
- * Returns an iterator yielding all maxima indices in given `values`
67
- * array. The search range can be optionally defined via semi-open
68
- * [from, to) index interval.
69
- *
70
- * @param values -
71
- * @param from -
72
- * @param to -
73
- */
74
- export const maximaIndices = (values, from = 0, to = values.length) => indices(minimaIndex, values, from, to);
23
+ const minimaIndices = (values, from = 0, to = values.length) => indices(minimaIndex, values, from, to);
24
+ const maximaIndices = (values, from = 0, to = values.length) => indices(minimaIndex, values, from, to);
25
+ export {
26
+ isMaxima,
27
+ isMinima,
28
+ maximaIndex,
29
+ maximaIndices,
30
+ minimaIndex,
31
+ minimaIndices
32
+ };
package/fit.js CHANGED
@@ -1,58 +1,15 @@
1
1
  import { clamp01, clamp11 } from "./interval.js";
2
- /**
3
- * Returns normalized value of `x` WRT to interval `a .. b`. If `a`
4
- * equals `b`, returns 0.
5
- *
6
- * @param x -
7
- * @param a -
8
- * @param b -
9
- */
10
- export const norm = (x, a, b) => (b !== a ? (x - a) / (b - a) : 0);
11
- /**
12
- * Returns a number in the `[c,d]` interval which is relative to `x` in the
13
- * `[a,b]` interval. **No** clamping will be performed if `x` lies outside the
14
- * original range (for that use {@link fitClamped} instead).
15
- *
16
- * @param x
17
- * @param a
18
- * @param b
19
- * @param c
20
- * @param d
21
- */
22
- export const fit = (x, a, b, c, d) => c + (d - c) * norm(x, a, b);
23
- /**
24
- * Clamped version of {@link fit}, i.e. before mapping `x` into the target
25
- * interval `[c,d]`, it will be clamped to the source interval `[a,b]`.
26
- *
27
- * @param x
28
- * @param a
29
- * @param b
30
- * @param c
31
- * @param d
32
- */
33
- export const fitClamped = (x, a, b, c, d) => c + (d - c) * clamp01(norm(x, a, b));
34
- /**
35
- * Similar to {@link fitClamped}, assuming [0,1] as source interval.
36
- *
37
- * @param x
38
- * @param a
39
- * @param b
40
- */
41
- export const fit01 = (x, a, b) => a + (b - a) * clamp01(x);
42
- /**
43
- * Similar to {@link fitClamped}, assuming the reverse ordered [1,0] as source
44
- * interval.
45
- *
46
- * @param x
47
- * @param a
48
- * @param b
49
- */
50
- export const fit10 = (x, a, b) => b + (a - b) * clamp01(x);
51
- /**
52
- * Similar to {@link fitClamped}, assuming [-1,1] as source interval.
53
- *
54
- * @param x
55
- * @param a
56
- * @param b
57
- */
58
- export const fit11 = (x, a, b) => a + (b - a) * (0.5 + 0.5 * clamp11(x));
2
+ const norm = (x, a, b) => b !== a ? (x - a) / (b - a) : 0;
3
+ const fit = (x, a, b, c, d) => c + (d - c) * norm(x, a, b);
4
+ const fitClamped = (x, a, b, c, d) => c + (d - c) * clamp01(norm(x, a, b));
5
+ const fit01 = (x, a, b) => a + (b - a) * clamp01(x);
6
+ const fit10 = (x, a, b) => b + (a - b) * clamp01(x);
7
+ const fit11 = (x, a, b) => a + (b - a) * (0.5 + 0.5 * clamp11(x));
8
+ export {
9
+ fit,
10
+ fit01,
11
+ fit10,
12
+ fit11,
13
+ fitClamped,
14
+ norm
15
+ };