@rian8337/osu-base 3.0.0-beta.4 → 3.0.0-beta.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/dist/index.js +309 -0
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/typings/index.d.ts +118 -1
package/dist/index.js
CHANGED
|
@@ -2797,6 +2797,49 @@ class Precision {
|
|
|
2797
2797
|
return (this.almostEqualsNumber(vec1.x, vec2.x, acceptableDifference) &&
|
|
2798
2798
|
this.almostEqualsNumber(vec1.y, vec2.y, acceptableDifference));
|
|
2799
2799
|
}
|
|
2800
|
+
/**
|
|
2801
|
+
* Checks whether two real numbers are almost equal.
|
|
2802
|
+
*
|
|
2803
|
+
* @param a The first number.
|
|
2804
|
+
* @param b The second number.
|
|
2805
|
+
* @param maximumError The accuracy required for being almost equal. Defaults to `10 * 2^(-53)`.
|
|
2806
|
+
* @returns Whether the two values differ by no more than 10 * 2^(-52).
|
|
2807
|
+
*/
|
|
2808
|
+
static almostEqualRelative(a, b, maximumError = 10 * Math.pow(2, -53)) {
|
|
2809
|
+
return this.almostEqualNormRelative(a, b, a - b, maximumError);
|
|
2810
|
+
}
|
|
2811
|
+
/**
|
|
2812
|
+
* Compares two numbers and determines if they are equal within the specified maximum error.
|
|
2813
|
+
*
|
|
2814
|
+
* @param a The norm of the first value (can be negative).
|
|
2815
|
+
* @param b The norm of the second value (can be negative).
|
|
2816
|
+
* @param diff The norm of the difference of the two values (can be negative).
|
|
2817
|
+
* @param maximumError The accuracy required for being almost equal.
|
|
2818
|
+
* @returns Whether both numbers are almost equal up to the specified maximum error.
|
|
2819
|
+
*/
|
|
2820
|
+
static almostEqualNormRelative(a, b, diff, maximumError) {
|
|
2821
|
+
// If A or B are infinity (positive or negative) then
|
|
2822
|
+
// only return true if they are exactly equal to each other -
|
|
2823
|
+
// that is, if they are both infinities of the same sign.
|
|
2824
|
+
if (!Number.isFinite(a) || !Number.isFinite(b)) {
|
|
2825
|
+
return a === b;
|
|
2826
|
+
}
|
|
2827
|
+
// If A or B are a NAN, return false. NANs are equal to nothing,
|
|
2828
|
+
// not even themselves.
|
|
2829
|
+
if (Number.isNaN(a) || Number.isNaN(b)) {
|
|
2830
|
+
return false;
|
|
2831
|
+
}
|
|
2832
|
+
// If one is almost zero, fall back to absolute equality.
|
|
2833
|
+
const doublePrecision = Math.pow(2, -53);
|
|
2834
|
+
if (Math.abs(a) < doublePrecision || Math.abs(b) < doublePrecision) {
|
|
2835
|
+
return Math.abs(diff) < maximumError;
|
|
2836
|
+
}
|
|
2837
|
+
if ((a === 0 && Math.abs(b) < maximumError) ||
|
|
2838
|
+
(b === 0 && Math.abs(a) < maximumError)) {
|
|
2839
|
+
return true;
|
|
2840
|
+
}
|
|
2841
|
+
return (Math.abs(diff) < maximumError * Math.max(Math.abs(a), Math.abs(b)));
|
|
2842
|
+
}
|
|
2800
2843
|
}
|
|
2801
2844
|
|
|
2802
2845
|
/**
|
|
@@ -6200,6 +6243,236 @@ class BeatmapEncoder extends Encoder {
|
|
|
6200
6243
|
}
|
|
6201
6244
|
}
|
|
6202
6245
|
|
|
6246
|
+
class ZeroCrossingBracketing {
|
|
6247
|
+
/**
|
|
6248
|
+
* Detect a range containing at least one root.
|
|
6249
|
+
*
|
|
6250
|
+
* This iterative method stops when two values with opposite signs are found.
|
|
6251
|
+
*
|
|
6252
|
+
* @param f The function to detect roots from.
|
|
6253
|
+
* @param bounds The upper and lower value of the range.
|
|
6254
|
+
* @param factor The growing factor of research. Defaults to 1.6.
|
|
6255
|
+
* @param maxIterations Maximum number of iterations. Defaults to 50.
|
|
6256
|
+
* @returns Whether the bracketing operation succeeded.
|
|
6257
|
+
*/
|
|
6258
|
+
static expand(f, bounds, factor = 1.6, maxIterations = 50) {
|
|
6259
|
+
const originalUpperBound = bounds.upperBound;
|
|
6260
|
+
const originalLowerBound = bounds.lowerBound;
|
|
6261
|
+
if (originalLowerBound >= originalUpperBound) {
|
|
6262
|
+
throw new RangeError("Upper bound must be greater than lower bound.");
|
|
6263
|
+
}
|
|
6264
|
+
let fmin = f(originalLowerBound);
|
|
6265
|
+
let fmax = f(originalUpperBound);
|
|
6266
|
+
for (let i = 0; i < maxIterations; ++i) {
|
|
6267
|
+
if (Math.sign(fmin) !== Math.sign(fmax)) {
|
|
6268
|
+
return true;
|
|
6269
|
+
}
|
|
6270
|
+
if (Math.abs(fmin) < Math.abs(fmax)) {
|
|
6271
|
+
bounds.lowerBound +=
|
|
6272
|
+
factor * (bounds.lowerBound - bounds.upperBound);
|
|
6273
|
+
fmin = f(bounds.lowerBound);
|
|
6274
|
+
}
|
|
6275
|
+
else {
|
|
6276
|
+
bounds.upperBound +=
|
|
6277
|
+
factor * (bounds.upperBound - bounds.lowerBound);
|
|
6278
|
+
fmax = f(bounds.upperBound);
|
|
6279
|
+
}
|
|
6280
|
+
}
|
|
6281
|
+
bounds.lowerBound = originalLowerBound;
|
|
6282
|
+
bounds.upperBound = originalUpperBound;
|
|
6283
|
+
return false;
|
|
6284
|
+
}
|
|
6285
|
+
static reduce(f, bounds, subdivisions = 1000) {
|
|
6286
|
+
const originalUpperBound = bounds.upperBound;
|
|
6287
|
+
const originalLowerBound = bounds.lowerBound;
|
|
6288
|
+
if (originalLowerBound >= originalUpperBound) {
|
|
6289
|
+
throw new RangeError("Upper bound must be greater than lower bound.");
|
|
6290
|
+
}
|
|
6291
|
+
// TODO: Consider binary-style search instead of linear scan
|
|
6292
|
+
const fmin = f(bounds.lowerBound);
|
|
6293
|
+
const fmax = f(bounds.upperBound);
|
|
6294
|
+
if (Math.sign(fmin) != Math.sign(fmax)) {
|
|
6295
|
+
return true;
|
|
6296
|
+
}
|
|
6297
|
+
const subdiv = (bounds.upperBound - bounds.lowerBound) / subdivisions;
|
|
6298
|
+
let smin = bounds.lowerBound;
|
|
6299
|
+
const sign = Math.sign(fmin);
|
|
6300
|
+
for (let i = 0; i < subdivisions; ++i) {
|
|
6301
|
+
const smax = smin + subdiv;
|
|
6302
|
+
const sfmax = f(smax);
|
|
6303
|
+
if (!Number.isFinite(sfmax)) {
|
|
6304
|
+
// expand interval to include pole
|
|
6305
|
+
smin = smax;
|
|
6306
|
+
continue;
|
|
6307
|
+
}
|
|
6308
|
+
if (Math.sign(sfmax) != sign) {
|
|
6309
|
+
bounds.upperBound = smax;
|
|
6310
|
+
bounds.lowerBound = smin;
|
|
6311
|
+
return true;
|
|
6312
|
+
}
|
|
6313
|
+
smin = smax;
|
|
6314
|
+
}
|
|
6315
|
+
bounds.lowerBound = originalLowerBound;
|
|
6316
|
+
bounds.upperBound = originalUpperBound;
|
|
6317
|
+
return false;
|
|
6318
|
+
}
|
|
6319
|
+
static expandReduce(f, bounds, expansionFactor = 1.6, expansionMaxIterations = 50, reduceSubdivisions = 100) {
|
|
6320
|
+
return (this.expand(f, bounds, expansionFactor, expansionMaxIterations) ||
|
|
6321
|
+
this.reduce(f, bounds, reduceSubdivisions));
|
|
6322
|
+
}
|
|
6323
|
+
}
|
|
6324
|
+
|
|
6325
|
+
/**
|
|
6326
|
+
* Algorithm by Brent, Van Wijngaarden, Dekker et al.
|
|
6327
|
+
*
|
|
6328
|
+
* Implementation inspired by Press, Teukolsky, Vetterling, and Flannery, "Numerical Recipes in C", 2nd edition, Cambridge University Press.
|
|
6329
|
+
*/
|
|
6330
|
+
class Brent {
|
|
6331
|
+
/**
|
|
6332
|
+
* Finds a solution to the equation f(x) = 0.
|
|
6333
|
+
*
|
|
6334
|
+
* @param f The function to find roots from.
|
|
6335
|
+
* @param bounds The upper and lower root bounds.
|
|
6336
|
+
* @param accuracy The desired accuracy. The root will be refined until the accuracy or the maximum number of iterations is reached. Defaults to 1e-8. Must be greater than 0.
|
|
6337
|
+
* @param maxIterations The maximum number of iterations. Defaults to 100.
|
|
6338
|
+
* @param expandFactor The factor at which to expand the bounds, if needed. Defaults to 1.6.
|
|
6339
|
+
* @param maxExpandIterations The maximum number of expand iterations. Defaults to 100.
|
|
6340
|
+
* @returns The root with the specified accuracy. Throws an error if the algorithm failed to converge.
|
|
6341
|
+
*/
|
|
6342
|
+
static findRootExpand(f, bounds, accuracy = 1e-8, maxIterations = 100, expandFactor = 1.6, maxExpandIterations = 100) {
|
|
6343
|
+
ZeroCrossingBracketing.expandReduce(f, bounds, expandFactor, maxExpandIterations, maxExpandIterations * 10);
|
|
6344
|
+
return this.findRoot(f, bounds, accuracy, maxIterations);
|
|
6345
|
+
}
|
|
6346
|
+
/**
|
|
6347
|
+
* Finds a solution to the equation f(x) = 0.
|
|
6348
|
+
*
|
|
6349
|
+
* @param f The function to find roots from.
|
|
6350
|
+
* @param bounds The upper and lower root bounds.
|
|
6351
|
+
* @param accuracy The desired accuracy. The root will be refined until the accuracy or the maximum number of iterations is reached. Defaults to 1e-8. Must be greater than 0.
|
|
6352
|
+
* @param maxIterations The maximum number of iterations. Defaults to 100.
|
|
6353
|
+
* @returns The root with the specified accuracy. Throws an error if the algorithm failed to converge.
|
|
6354
|
+
*/
|
|
6355
|
+
static findRoot(f, bounds, accuracy = 1e-8, maxIterations = 100) {
|
|
6356
|
+
const root = this.tryFindRoot(f, bounds, accuracy, maxIterations);
|
|
6357
|
+
if (root === null) {
|
|
6358
|
+
throw new Error("The algorithm has failed, exceeded the number of iterations allowed or there is no root within the provided bounds.");
|
|
6359
|
+
}
|
|
6360
|
+
return root;
|
|
6361
|
+
}
|
|
6362
|
+
/**
|
|
6363
|
+
* Finds a solution to the equation f(x) = 0.
|
|
6364
|
+
*
|
|
6365
|
+
* @param f The function to find roots from.
|
|
6366
|
+
* @param bounds The upper and lower root bounds.
|
|
6367
|
+
* @param accuracy The desired accuracy. The root will be refined until the accuracy or the maximum number of iterations is reached. Must be greater than 0.
|
|
6368
|
+
* @param maxIterations The maximum number of iterations. Usually 100.
|
|
6369
|
+
* @returns The root with the specified accuracy, `null` if not found.
|
|
6370
|
+
*/
|
|
6371
|
+
static tryFindRoot(f, bounds, accuracy, maxIterations) {
|
|
6372
|
+
if (accuracy <= 0) {
|
|
6373
|
+
throw new RangeError("Accuracy must be greater than 0.");
|
|
6374
|
+
}
|
|
6375
|
+
let { lowerBound, upperBound } = bounds;
|
|
6376
|
+
let fmin = f(lowerBound);
|
|
6377
|
+
let fmax = f(upperBound);
|
|
6378
|
+
let froot = fmax;
|
|
6379
|
+
let d = 0;
|
|
6380
|
+
let e = 0;
|
|
6381
|
+
let root = upperBound;
|
|
6382
|
+
let xMid = Number.NaN;
|
|
6383
|
+
// Root must be bracketed.
|
|
6384
|
+
if (Math.sign(fmin) === Math.sign(fmax)) {
|
|
6385
|
+
return null;
|
|
6386
|
+
}
|
|
6387
|
+
for (let i = 0; i <= maxIterations; ++i) {
|
|
6388
|
+
// Adjust bounds.
|
|
6389
|
+
if (Math.sign(froot) === Math.sign(fmax)) {
|
|
6390
|
+
upperBound = lowerBound;
|
|
6391
|
+
fmax = fmin;
|
|
6392
|
+
e = d = root - lowerBound;
|
|
6393
|
+
}
|
|
6394
|
+
if (Math.abs(fmax) < Math.abs(froot)) {
|
|
6395
|
+
lowerBound = root;
|
|
6396
|
+
root = upperBound;
|
|
6397
|
+
upperBound = lowerBound;
|
|
6398
|
+
fmin = froot;
|
|
6399
|
+
froot = fmax;
|
|
6400
|
+
fmax = fmin;
|
|
6401
|
+
}
|
|
6402
|
+
// Convergence check
|
|
6403
|
+
const xAcc1 = 2 * Math.pow(2, -53) * Math.abs(root) + accuracy / 2;
|
|
6404
|
+
const xMidOld = xMid;
|
|
6405
|
+
xMid = (upperBound - root) / 2;
|
|
6406
|
+
if (Math.abs(xMid) <= xAcc1 ||
|
|
6407
|
+
Precision.almostEqualNormRelative(froot, 0, froot, accuracy)) {
|
|
6408
|
+
return root;
|
|
6409
|
+
}
|
|
6410
|
+
if (xMid === xMidOld) {
|
|
6411
|
+
// accuracy not sufficient, but cannot be improved further
|
|
6412
|
+
return null;
|
|
6413
|
+
}
|
|
6414
|
+
if (Math.abs(e) >= xAcc1 && Math.abs(fmin) > Math.abs(froot)) {
|
|
6415
|
+
// Attempt inverse quadratic interpolation
|
|
6416
|
+
const s = froot / fmin;
|
|
6417
|
+
let p;
|
|
6418
|
+
let q;
|
|
6419
|
+
if (Precision.almostEqualRelative(lowerBound, upperBound)) {
|
|
6420
|
+
p = 2 * xMid * s;
|
|
6421
|
+
q = 1 - s;
|
|
6422
|
+
}
|
|
6423
|
+
else {
|
|
6424
|
+
q = fmin / fmax;
|
|
6425
|
+
const r = froot / fmax;
|
|
6426
|
+
p =
|
|
6427
|
+
s *
|
|
6428
|
+
(2 * xMid * q * (q - r) -
|
|
6429
|
+
(root - lowerBound) * (r - 1));
|
|
6430
|
+
q = (q - 1) * (r - 1) * (s - 1);
|
|
6431
|
+
}
|
|
6432
|
+
if (p > 0) {
|
|
6433
|
+
// Check whether in bounds
|
|
6434
|
+
q = -q;
|
|
6435
|
+
}
|
|
6436
|
+
p = Math.abs(p);
|
|
6437
|
+
if (2 * p <
|
|
6438
|
+
Math.min(3 * xMid * q - Math.abs(xAcc1 * q), Math.abs(e * q))) {
|
|
6439
|
+
// Accept interpolation
|
|
6440
|
+
e = d;
|
|
6441
|
+
d = p / q;
|
|
6442
|
+
}
|
|
6443
|
+
else {
|
|
6444
|
+
// Interpolation failed, use bisection
|
|
6445
|
+
d = xMid;
|
|
6446
|
+
e = d;
|
|
6447
|
+
}
|
|
6448
|
+
}
|
|
6449
|
+
else {
|
|
6450
|
+
// Bounds decreasing too slowly, use bisection
|
|
6451
|
+
d = xMid;
|
|
6452
|
+
e = d;
|
|
6453
|
+
}
|
|
6454
|
+
lowerBound = root;
|
|
6455
|
+
fmin = froot;
|
|
6456
|
+
if (Math.abs(d) > xAcc1) {
|
|
6457
|
+
root += d;
|
|
6458
|
+
}
|
|
6459
|
+
else {
|
|
6460
|
+
root += this.sign(xAcc1, xMid);
|
|
6461
|
+
}
|
|
6462
|
+
froot = f(root);
|
|
6463
|
+
}
|
|
6464
|
+
return null;
|
|
6465
|
+
}
|
|
6466
|
+
/**
|
|
6467
|
+
* Helper method useful for preventing rounding errors.
|
|
6468
|
+
*
|
|
6469
|
+
* @returns a * sign(b)
|
|
6470
|
+
*/
|
|
6471
|
+
static sign(a, b) {
|
|
6472
|
+
return b >= 0 ? (a >= 0 ? a : -a) : a >= 0 ? -a : a;
|
|
6473
|
+
}
|
|
6474
|
+
}
|
|
6475
|
+
|
|
6203
6476
|
/**
|
|
6204
6477
|
* Types of easing.
|
|
6205
6478
|
*
|
|
@@ -6665,6 +6938,29 @@ class ErrorFunction {
|
|
|
6665
6938
|
}
|
|
6666
6939
|
return this.erfImp(x, false);
|
|
6667
6940
|
}
|
|
6941
|
+
/**
|
|
6942
|
+
* Calculates the complementary error function.
|
|
6943
|
+
*
|
|
6944
|
+
* @param x The value to evaluate.
|
|
6945
|
+
* @returns The complementary error function evaluated at given value, or:
|
|
6946
|
+
* - 0 if `x === Number.POSITIVE_INFINITY`;
|
|
6947
|
+
* - 2 if `x === Number.NEGATIVE_INFINITY`.
|
|
6948
|
+
*/
|
|
6949
|
+
static erfc(x) {
|
|
6950
|
+
if (x === 0) {
|
|
6951
|
+
return 1;
|
|
6952
|
+
}
|
|
6953
|
+
if (x === Number.POSITIVE_INFINITY) {
|
|
6954
|
+
return 0;
|
|
6955
|
+
}
|
|
6956
|
+
if (x === Number.NEGATIVE_INFINITY) {
|
|
6957
|
+
return 2;
|
|
6958
|
+
}
|
|
6959
|
+
if (Number.isNaN(x)) {
|
|
6960
|
+
return Number.NaN;
|
|
6961
|
+
}
|
|
6962
|
+
return this.erfImp(x, true);
|
|
6963
|
+
}
|
|
6668
6964
|
/**
|
|
6669
6965
|
* Calculates the inverse error function evaluated at z.
|
|
6670
6966
|
*
|
|
@@ -7508,6 +7804,16 @@ class MapInfo {
|
|
|
7508
7804
|
}
|
|
7509
7805
|
}
|
|
7510
7806
|
|
|
7807
|
+
/**
|
|
7808
|
+
* Represents the osu! playfield.
|
|
7809
|
+
*/
|
|
7810
|
+
class Playfield {
|
|
7811
|
+
/**
|
|
7812
|
+
* The size of the playfield, which is 512x384.
|
|
7813
|
+
*/
|
|
7814
|
+
static baseSize = new Vector2(512, 384);
|
|
7815
|
+
}
|
|
7816
|
+
|
|
7511
7817
|
dotenv.config();
|
|
7512
7818
|
|
|
7513
7819
|
exports.Accuracy = Accuracy;
|
|
@@ -7526,6 +7832,7 @@ exports.BeatmapMetadata = BeatmapMetadata;
|
|
|
7526
7832
|
exports.BeatmapVideo = BeatmapVideo;
|
|
7527
7833
|
exports.BlendingParameters = BlendingParameters;
|
|
7528
7834
|
exports.BreakPoint = BreakPoint;
|
|
7835
|
+
exports.Brent = Brent;
|
|
7529
7836
|
exports.Circle = Circle;
|
|
7530
7837
|
exports.Command = Command;
|
|
7531
7838
|
exports.CommandLoop = CommandLoop;
|
|
@@ -7570,6 +7877,7 @@ exports.ModUtil = ModUtil;
|
|
|
7570
7877
|
exports.OsuAPIRequestBuilder = OsuAPIRequestBuilder;
|
|
7571
7878
|
exports.OsuHitWindow = OsuHitWindow;
|
|
7572
7879
|
exports.PathApproximator = PathApproximator;
|
|
7880
|
+
exports.Playfield = Playfield;
|
|
7573
7881
|
exports.Polynomial = Polynomial;
|
|
7574
7882
|
exports.Precision = Precision;
|
|
7575
7883
|
exports.RGBColor = RGBColor;
|
|
@@ -7595,4 +7903,5 @@ exports.TimingControlPoint = TimingControlPoint;
|
|
|
7595
7903
|
exports.TimingControlPointManager = TimingControlPointManager;
|
|
7596
7904
|
exports.Utils = Utils;
|
|
7597
7905
|
exports.Vector2 = Vector2;
|
|
7906
|
+
exports.ZeroCrossingBracketing = ZeroCrossingBracketing;
|
|
7598
7907
|
//# sourceMappingURL=index.js.map
|