@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 +1 -1
- package/README.md +1 -1
- package/abs.js +6 -2
- package/angle.js +54 -122
- package/api.js +42 -20
- package/crossing.js +8 -58
- package/eqdelta.js +6 -22
- package/extrema.js +27 -69
- package/fit.js +14 -57
- package/int.js +128 -64
- package/interval.js +73 -205
- package/libc.js +38 -107
- package/min-error.js +27 -39
- package/mix.js +109 -391
- package/package.json +7 -4
- package/permutations.js +18 -47
- package/prec.js +18 -31
- package/prime.js +31 -48
- package/ratio.js +18 -16
- package/safe-div.js +4 -7
- package/solve.js +37 -92
- package/step.js +14 -63
package/CHANGELOG.md
CHANGED
package/README.md
CHANGED
package/abs.js
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
1
|
import { EPS } from "./api.js";
|
|
2
|
-
|
|
3
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
*
|
|
33
|
-
|
|
34
|
-
|
|
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
|
-
|
|
100
|
-
|
|
26
|
+
const x2 = x * x;
|
|
27
|
+
return 0.99940307 + x2 * (-0.49558072 + 0.03679168 * x2);
|
|
101
28
|
};
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
*
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
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
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
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
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
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
|
-
|
|
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
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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
|
-
|
|
9
|
+
}
|
|
10
|
+
return -1;
|
|
25
11
|
};
|
|
26
|
-
|
|
27
|
-
|
|
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
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
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
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
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
|
-
|
|
4
|
-
|
|
5
|
-
*
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
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
|
+
};
|