smath 1.13.3 → 1.15.0

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/bin.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  "use strict";
3
- var _a, _b, _c, _d, _e;
3
+ var _a, _b, _c, _d;
4
4
  Object.defineProperty(exports, "__esModule", { value: true });
5
5
  var SMath = require(".");
6
6
  var func = ((_a = process.argv[2]) !== null && _a !== void 0 ? _a : '').toLowerCase(), nums = process.argv.slice(3).map(function (arg, i) {
@@ -41,9 +41,14 @@ if (func.includes('help')) {
41
41
  console.log(' rint <min> <max> : Generate a uniformly-distributed random integer, range inclusive');
42
42
  console.log(' rnorm [mean] [stdev] : Generate a normally-distributed random float');
43
43
  console.log(' rdist <n> [mean] [stdev] : Generate `n` normally-distributed random floats');
44
+ console.log(' shuffle <c0> [c1] ... [cn]');
45
+ console.log(' : Shuffle an array of arbirary elements');
46
+ console.log(' selectRandom <c0> [c1] ... [cn]');
47
+ console.log(' : Select a number at random from a list');
48
+ console.log(' selectRandomWeighted <c0> [c1] ... [cn]');
49
+ console.log(' : Select an index at random from a list of weights');
44
50
  console.log(' rat <n> [eps] : Decompose `n` into a ratio');
45
51
  console.log(' mixed <n> [eps] : Decompose `n` into a mixed number');
46
- console.log(' toHex <n> [length] : Convert decimal `n` into hexadecimal');
47
52
  process.exit(1);
48
53
  }
49
54
  switch (func) {
@@ -139,6 +144,18 @@ switch (func) {
139
144
  console.log(SMath.rdist(nums[0], nums[1], nums[2]));
140
145
  break;
141
146
  }
147
+ case ('shuffle'): {
148
+ console.log(SMath.shuffle(nums));
149
+ break;
150
+ }
151
+ case ('selectRandom'): {
152
+ console.log(SMath.selectRandom(nums));
153
+ break;
154
+ }
155
+ case ('selectRandomWeighted'): {
156
+ console.log(SMath.selectRandomWeighted(nums));
157
+ break;
158
+ }
142
159
  case ('rat'): {
143
160
  console.log(SMath.rat(nums[0], (_c = nums[1]) !== null && _c !== void 0 ? _c : 1e-6));
144
161
  break;
@@ -147,11 +164,6 @@ switch (func) {
147
164
  console.log(SMath.mixed(nums[0], (_d = nums[1]) !== null && _d !== void 0 ? _d : 1e-6));
148
165
  break;
149
166
  }
150
- case ('tohex'): {
151
- console.warn('toHex() is deprecated!');
152
- console.log(SMath.toHex(nums[0], (_e = nums[1]) !== null && _e !== void 0 ? _e : 0));
153
- break;
154
- }
155
167
  case (''): {
156
168
  console.error('Missing argument. Use with "help" for a list of commands.');
157
169
  process.exit(1);
package/dist/index.js CHANGED
@@ -35,12 +35,13 @@ exports.rint = rint;
35
35
  exports.rnorm = rnorm;
36
36
  exports.rdist = rdist;
37
37
  exports.shuffle = shuffle;
38
+ exports.selectRandom = selectRandom;
39
+ exports.selectRandomWeighted = selectRandomWeighted;
38
40
  exports.lim = lim;
39
41
  exports.differentiate = differentiate;
40
42
  exports.integrate = integrate;
41
43
  exports.rat = rat;
42
44
  exports.mixed = mixed;
43
- exports.toHex = toHex;
44
45
  /**
45
46
  * @packageDocumentation
46
47
  * Small math function library
@@ -229,7 +230,12 @@ function round2(n, base) {
229
230
  * const e = SMath.error(22.5, 25); // -0.1
230
231
  */
231
232
  function error(experimental, actual) {
232
- return (experimental - actual) / actual;
233
+ if (experimental === 0 && actual === 0) {
234
+ return 0;
235
+ }
236
+ else {
237
+ return (experimental - actual) / actual;
238
+ }
233
239
  }
234
240
  /**
235
241
  * Add up all the inputs.
@@ -395,6 +401,32 @@ function shuffle(stack) {
395
401
  }
396
402
  return rawData.sort(function (a, b) { return a.index - b.index; }).map(function (a) { return a.value; });
397
403
  }
404
+ /**
405
+ * Select a single item from an array at random with uniform weights.
406
+ * @param stack An array of arbirary item
407
+ * @returns A single randomly selected item
408
+ * @example
409
+ * const selected = SMath.selectRandom([10, 20, 30, 40]); // 30
410
+ */
411
+ function selectRandom(stack) {
412
+ return stack[rint(0, stack.length - 1)];
413
+ }
414
+ /**
415
+ * Select a single index in an array at random with different weights.
416
+ * @param weights The weights for each item
417
+ * @returns The index of the randomly selected item
418
+ */
419
+ function selectRandomWeighted(weights) {
420
+ var startWeights = [];
421
+ var accumulation = 0;
422
+ for (var _i = 0, weights_1 = weights; _i < weights_1.length; _i++) {
423
+ var weight = weights_1[_i];
424
+ accumulation += clamp(0, weight, Infinity);
425
+ startWeights.push(accumulation);
426
+ }
427
+ var random = runif(0, accumulation);
428
+ return startWeights.findIndex(function (weight) { return random < weight; });
429
+ }
398
430
  /**
399
431
  * Take the limit of a function. A return value of `NaN` indicates
400
432
  * that no limit exists either due to a discontinuity or imaginary value.
@@ -407,8 +439,8 @@ function shuffle(stack) {
407
439
  * const y = SMath.lim(Math.log, 0); // -Infinity
408
440
  */
409
441
  function lim(f, x, h, discontinuity_cutoff) {
410
- if (h === void 0) { h = 1e-3; }
411
- if (discontinuity_cutoff === void 0) { discontinuity_cutoff = 1; }
442
+ if (h === void 0) { h = 1e-6; }
443
+ if (discontinuity_cutoff === void 0) { discontinuity_cutoff = 1e-3; }
412
444
  var center = f(x), left1 = f(x - h), left2 = f(x - h / 2), right1 = f(x + h), right2 = f(x + h / 2);
413
445
  var left, right;
414
446
  if (Number.isFinite(center)) {
@@ -416,46 +448,46 @@ function lim(f, x, h, discontinuity_cutoff) {
416
448
  }
417
449
  // Check the limit approaching from the left
418
450
  if (Number.isFinite(left1) && Number.isFinite(left2)) {
419
- if (left2 > left1 + 2 * h) {
420
- left = Infinity;
451
+ if (approx(left1, left2, discontinuity_cutoff)) {
452
+ left = left2; // Converges
453
+ }
454
+ else if (left1 > 0 && left2 > left1) {
455
+ left = Infinity; // Diverges to +inf
421
456
  }
422
- else if (left2 < left1 - 2 * h) {
423
- left = -Infinity;
457
+ else if (left1 < 0 && left2 < left1) {
458
+ left = -Infinity; // Diverges to -inf
424
459
  }
425
460
  else {
426
- left = avg([left1, left2]);
461
+ left = NaN; // Diverges
427
462
  }
428
463
  }
429
- else if (left1 === left2) { // Handles +/-Infinity case
430
- left = left1;
431
- }
432
464
  else {
433
- left = NaN;
465
+ left = NaN; // Discontinuous
434
466
  }
435
467
  // Check the limit approaching from the right
436
468
  if (Number.isFinite(right1) && Number.isFinite(right2)) {
437
- if (right2 > right1 + 2 * h) {
438
- right = Infinity;
469
+ if (approx(right1, right2, discontinuity_cutoff)) {
470
+ right = right2; // Converges
439
471
  }
440
- else if (right2 < right1 - 2 * h) {
441
- right = -Infinity;
472
+ else if (right1 > 0 && right2 > right1) {
473
+ right = Infinity; // Diverges to +inf
474
+ }
475
+ else if (right1 < 0 && right2 < right1) {
476
+ right = -Infinity; // Diverges to -inf
442
477
  }
443
478
  else {
444
- right = avg([right1, right2]);
479
+ right = NaN; // Diverges
445
480
  }
446
481
  }
447
- else if (right1 === right2) { // Handles +/-Infinity case
448
- right = right1;
449
- }
450
482
  else {
451
- right = NaN;
483
+ right = NaN; // Discontinuous
452
484
  }
453
485
  // Check if limits match or are close
454
486
  if (left === right) { // Handles +/-Infinity case
455
487
  return left;
456
488
  }
457
- else if (approx(left, right, discontinuity_cutoff)) {
458
- return avg([left, right]);
489
+ else if (Number.isNaN(left) && Number.isNaN(right)) {
490
+ return center;
459
491
  }
460
492
  else if (!Number.isNaN(left) && Number.isNaN(right)) {
461
493
  return left;
@@ -463,6 +495,9 @@ function lim(f, x, h, discontinuity_cutoff) {
463
495
  else if (Number.isNaN(left) && !Number.isNaN(right)) {
464
496
  return right;
465
497
  }
498
+ else if (approx(left, right, discontinuity_cutoff)) {
499
+ return avg([left, right]);
500
+ }
466
501
  else {
467
502
  return NaN;
468
503
  }
@@ -471,14 +506,14 @@ function lim(f, x, h, discontinuity_cutoff) {
471
506
  * Take the derivative of a function.
472
507
  * @param f Function `f(x)`
473
508
  * @param x The x-value where to evaluate the derivative
474
- * @param h Small step value
509
+ * @param epsilon Small step value
475
510
  * @returns `f'(x)`
476
511
  * @example
477
512
  * const y = SMath.differentiate(x => 3 * x ** 2, 2); // 12
478
513
  */
479
- function differentiate(f, x, h) {
480
- if (h === void 0) { h = 1e-3; }
481
- return (f(x + h) - f(x - h)) / (2 * h);
514
+ function differentiate(f, x, epsilon) {
515
+ if (epsilon === void 0) { epsilon = 1e-6; }
516
+ return lim(function (h) { return (f(x + h) - f(x - h)) / (2 * h); }, 0, epsilon);
482
517
  }
483
518
  /**
484
519
  * Compute the definite integral of a function.
@@ -491,7 +526,7 @@ function differentiate(f, x, h) {
491
526
  * const y = SMath.integrate(x => 3 * x ** 2, 1, 2); // 7
492
527
  */
493
528
  function integrate(f, a, b, Ndx) {
494
- if (Ndx === void 0) { Ndx = 1e3; }
529
+ if (Ndx === void 0) { Ndx = 1e6; }
495
530
  return ((b - a) / Ndx) * sum(linspace(a, b, Ndx).map(function (x) { return f(x); }));
496
531
  }
497
532
  /**
@@ -531,16 +566,3 @@ function mixed(n, epsilon) {
531
566
  if (epsilon === void 0) { epsilon = 1e-6; }
532
567
  return __assign({ whole: n | 0 }, rat(n < -1 ? (n | 0) - n : n - (n | 0), epsilon));
533
568
  }
534
- /**
535
- * Convert any number to its hexadecimal equivalent.
536
- * @param n A decimal number to convert
537
- * @param length The minimum number of digits to show
538
- * @returns The number `n` converted to hexadecimal
539
- * @example
540
- * const hex = SMath.toHex(10, 2); // '0A'
541
- * @deprecated Use native `number.toString(16)`
542
- */
543
- function toHex(n, length) {
544
- if (length === void 0) { length = 0; }
545
- return (n < 0 ? '-' : '') + (n < 0 ? -n : n).toString(16).padStart(length, '0').toUpperCase();
546
- }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "smath",
3
- "version": "1.13.3",
3
+ "version": "1.15.0",
4
4
  "description": "Small math function library",
5
5
  "homepage": "https://npm.nicfv.com/",
6
6
  "bin": "dist/bin.js",
@@ -52,7 +52,7 @@
52
52
  "repository": "github:nicfv/npm",
53
53
  "license": "MIT",
54
54
  "devDependencies": {
55
- "@types/node": "24.3.0",
55
+ "@types/node": "25.0.10",
56
56
  "t6": "1.2.1"
57
57
  }
58
58
  }
package/types/index.d.ts CHANGED
@@ -233,6 +233,20 @@ export declare function rdist(count: number, mean?: number, stdev?: number): num
233
233
  * const shuffled = SMath.shuffle(['a', 'b', 'c']); // [ 'c', 'a', 'b' ]
234
234
  */
235
235
  export declare function shuffle<T>(stack: T[]): T[];
236
+ /**
237
+ * Select a single item from an array at random with uniform weights.
238
+ * @param stack An array of arbirary item
239
+ * @returns A single randomly selected item
240
+ * @example
241
+ * const selected = SMath.selectRandom([10, 20, 30, 40]); // 30
242
+ */
243
+ export declare function selectRandom<T>(stack: T[]): T;
244
+ /**
245
+ * Select a single index in an array at random with different weights.
246
+ * @param weights The weights for each item
247
+ * @returns The index of the randomly selected item
248
+ */
249
+ export declare function selectRandomWeighted(weights: number[]): number;
236
250
  /**
237
251
  * Take the limit of a function. A return value of `NaN` indicates
238
252
  * that no limit exists either due to a discontinuity or imaginary value.
@@ -249,12 +263,12 @@ export declare function lim(f: (x: number) => number, x: number, h?: number, dis
249
263
  * Take the derivative of a function.
250
264
  * @param f Function `f(x)`
251
265
  * @param x The x-value where to evaluate the derivative
252
- * @param h Small step value
266
+ * @param epsilon Small step value
253
267
  * @returns `f'(x)`
254
268
  * @example
255
269
  * const y = SMath.differentiate(x => 3 * x ** 2, 2); // 12
256
270
  */
257
- export declare function differentiate(f: (x: number) => number, x: number, h?: number): number;
271
+ export declare function differentiate(f: (x: number) => number, x: number, epsilon?: number): number;
258
272
  /**
259
273
  * Compute the definite integral of a function.
260
274
  * @param f Function `f(x)`
@@ -294,13 +308,3 @@ export declare function mixed(n: number, epsilon?: number): {
294
308
  num: number;
295
309
  den: number;
296
310
  };
297
- /**
298
- * Convert any number to its hexadecimal equivalent.
299
- * @param n A decimal number to convert
300
- * @param length The minimum number of digits to show
301
- * @returns The number `n` converted to hexadecimal
302
- * @example
303
- * const hex = SMath.toHex(10, 2); // '0A'
304
- * @deprecated Use native `number.toString(16)`
305
- */
306
- export declare function toHex(n: number, length?: number): string;