@gkucmierz/utils 2.0.6 → 2.0.8

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/README.md CHANGED
@@ -41,6 +41,7 @@ This library provides a wide range of mathematical functions and data structures
41
41
  - `mod`, `powMod`: Modular arithmetic with Python-like behavior for negative numbers.
42
42
  - `egcd`: Extended Euclidean Algorithm.
43
43
  - `tonelliShanksBI`: Modular square root algorithm.
44
+ - `lucasLehmerBI`: Lucas-Lehmer primality test for Mersenne primes.
44
45
 
45
46
  - **Sequences & Formulas**:
46
47
  - `gpn`: Generalized Pentagonal Numbers.
@@ -54,6 +55,7 @@ This library provides a wide range of mathematical functions and data structures
54
55
  - `bijectiveNumeration`: Bijective base-k numeration system.
55
56
 
56
57
  - **Developer Utilities**:
58
+ - `setSafeInterval`: A safe, asynchronous alternative to `setInterval` that prevents overlapping executions and supports immediate yielding.
57
59
  - `consumeIteratorNonBlocking`: Yield consumption macro-tasks queue resolver for heavy computations.
58
60
  - `memoize`: Function memoization based on arguments.
59
61
  - `binarySearch`: Various binary search implementations (exact, lower bound, upper bound).
package/main.mjs CHANGED
@@ -59,6 +59,9 @@ import {
59
59
  import {
60
60
  ListNode
61
61
  } from './src/list-node.mjs'
62
+ import {
63
+ lucasLehmerBI
64
+ } from './src/lucas-lehmer.mjs'
62
65
  import {
63
66
  axisAngleToMatrix4, crossProduct, dotProduct, getRotationMatrixFromVectors, multiplyMatrix4, normalize, projectToTrackball
64
67
  } from './src/math3d.mjs'
@@ -98,6 +101,9 @@ import {
98
101
  import {
99
102
  array2range, range2array
100
103
  } from './src/range-array.mjs'
104
+ import {
105
+ setSafeInterval
106
+ } from './src/set-safe-interval.mjs'
101
107
  import {
102
108
  simulatedAnnealing
103
109
  } from './src/simulated-annealing.mjs'
@@ -128,6 +134,7 @@ export * from './src/heap.mjs';
128
134
  export * from './src/herons-formula.mjs';
129
135
  export * from './src/lcm.mjs';
130
136
  export * from './src/list-node.mjs';
137
+ export * from './src/lucas-lehmer.mjs';
131
138
  export * from './src/math3d.mjs';
132
139
  export * from './src/matrix.mjs';
133
140
  export * from './src/memoize.mjs';
@@ -141,10 +148,11 @@ export * from './src/phi.mjs';
141
148
  export * from './src/pow-mod.mjs';
142
149
  export * from './src/rand-normal.mjs';
143
150
  export * from './src/range-array.mjs';
151
+ export * from './src/set-safe-interval.mjs';
144
152
  export * from './src/simulated-annealing.mjs';
145
153
  export * from './src/square-root.mjs';
146
154
  export * from './src/tonelli-shanks.mjs';
147
155
 
148
156
  export default [
149
- SetCnt, Trie, arrayHistogram, fromBase64, fromBase64Url, toBase64, toBase64Url, bijective2num, bijective2numBI, num2bijective, num2bijectiveBI, binarySearchArr, binarySearchGE, binarySearchLE, binarySearchRangeIncl, combinations, combinationsIterator, consumeIteratorNonBlocking, copyCase, egcd, factors, factorsBI, formatBigNumber, formatBigNumberBI, wrapFn, gcd, gcdBI, getType, gpn, gpnBI, bin2gray, gray2bin, Heap, heronsFormula, heronsFormulaBI, lcm, lcmBI, ListNode, axisAngleToMatrix4, crossProduct, dotProduct, getRotationMatrixFromVectors, multiplyMatrix4, normalize, projectToTrackball, matrixAsArray, memoize, mod, modBI, nChooseK, naturalSearch, nelderMead, particleSwarmOptimization, permutations, permutationsIterator, phi, phiBI, powMod, powModBI, randNormal, array2range, range2array, simulatedAnnealing, squareRoot, squareRootBI, tonelliShanksBI
157
+ SetCnt, Trie, arrayHistogram, fromBase64, fromBase64Url, toBase64, toBase64Url, bijective2num, bijective2numBI, num2bijective, num2bijectiveBI, binarySearchArr, binarySearchGE, binarySearchLE, binarySearchRangeIncl, combinations, combinationsIterator, consumeIteratorNonBlocking, copyCase, egcd, factors, factorsBI, formatBigNumber, formatBigNumberBI, wrapFn, gcd, gcdBI, getType, gpn, gpnBI, bin2gray, gray2bin, Heap, heronsFormula, heronsFormulaBI, lcm, lcmBI, ListNode, lucasLehmerBI, axisAngleToMatrix4, crossProduct, dotProduct, getRotationMatrixFromVectors, multiplyMatrix4, normalize, projectToTrackball, matrixAsArray, memoize, mod, modBI, nChooseK, naturalSearch, nelderMead, particleSwarmOptimization, permutations, permutationsIterator, phi, phiBI, powMod, powModBI, randNormal, array2range, range2array, setSafeInterval, simulatedAnnealing, squareRoot, squareRootBI, tonelliShanksBI
150
158
  ];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gkucmierz/utils",
3
- "version": "2.0.6",
3
+ "version": "2.0.8",
4
4
  "type": "module",
5
5
  "description": "Usefull functions for solving programming tasks",
6
6
  "keywords": [
@@ -19,8 +19,10 @@
19
19
  "iterator",
20
20
  "javascript",
21
21
  "lcm",
22
+ "lucas-lehmer",
22
23
  "math",
23
24
  "memoize",
25
+ "mersenne",
24
26
  "mod",
25
27
  "n-choose-k",
26
28
  "node",
@@ -29,7 +31,12 @@
29
31
  "permutations",
30
32
  "phi",
31
33
  "pow-mod",
34
+ "primality-test",
35
+ "prime",
32
36
  "range-array",
37
+ "set-safe-interval",
38
+ "setinterval",
39
+ "settimeout",
33
40
  "square-root",
34
41
  "tonelli-shanks",
35
42
  "trie",
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Calculates whether a given Mersenne number (2^p - 1) is prime using the Lucas-Lehmer primality test.
3
+ *
4
+ * @param {number|bigint} exp - The exponent p of the Mersenne number M_p.
5
+ * @param {boolean} [verbose=false] - If true, logs the calculation progress.
6
+ * @returns {boolean} True if the Mersenne number is prime, false otherwise.
7
+ */
8
+ export const lucasLehmerBI = (exp, verbose = false) => {
9
+ const steps = exp - 2;
10
+ const prime = 2n ** BigInt(exp) - 1n;
11
+ verbose && console.log('prime: ', prime);
12
+ let s = 4n;
13
+ for (let i = 0; i < steps; ++i) {
14
+ s = (s ** 2n - 2n) % prime;
15
+ verbose && console.log(i, s);
16
+ }
17
+ return s === 0n;
18
+ };
package/src/math3d.mjs CHANGED
@@ -20,9 +20,9 @@ export const projectToTrackball = (x, y, radius = 1) => {
20
20
  const d2 = x*x + y*y;
21
21
  const r2 = radius * radius;
22
22
  if (d2 <= r2 * 0.5) {
23
- return normalize([x, y, Math.sqrt(r2 - d2)]);
23
+ return normalize([x, y, Math.sqrt(r2 - d2)]);
24
24
  } else {
25
- return normalize([x, y, (r2 * 0.5) / Math.sqrt(d2)]);
25
+ return normalize([x, y, (r2 * 0.5) / Math.sqrt(d2)]);
26
26
  }
27
27
  };
28
28
 
@@ -47,7 +47,7 @@ export const multiplyMatrix4 = (a, b) => {
47
47
  for (let r = 0; r < 4; r++) {
48
48
  let sum = 0;
49
49
  for (let i = 0; i < 4; i++) {
50
- sum += a[i*4 + r] * b[c*4 + i]; // Note: column-major alignment
50
+ sum += a[i*4 + r] * b[c*4 + i]; // Note: column-major alignment
51
51
  }
52
52
  out[c*4 + r] = sum;
53
53
  }
@@ -58,7 +58,7 @@ export const multiplyMatrix4 = (a, b) => {
58
58
  export const getRotationMatrixFromVectors = (u, v) => {
59
59
  const axis = crossProduct(u, v);
60
60
  if (axis[0] === 0 && axis[1] === 0 && axis[2] === 0) {
61
- return [1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1]; // Identity
61
+ return [1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1]; // Identity
62
62
  }
63
63
  const dot = dotProduct(u, v);
64
64
  const angle = Math.acos(Math.max(-1, Math.min(1, dot)));
@@ -1,3 +1,10 @@
1
+ /**
2
+ * Generates a random number from a normal (Gaussian) distribution.
3
+ * Uses the Box-Muller transform.
4
+ * @param {number} [mean=0] - The mean of the normal distribution.
5
+ * @param {number} [sigma=1] - The standard deviation of the normal distribution.
6
+ * @returns {number} A random number from the specified normal distribution.
7
+ */
1
8
  export const randNormal = (mean = 0, sigma = 1) => {
2
9
  const y1 = Math.random();
3
10
  const y2 = Math.random();
@@ -0,0 +1,44 @@
1
+ /**
2
+ * A safe alternative to setInterval that uses recursive setTimeout.
3
+ * It waits for the callback (even if it's async) to finish before scheduling the next tick,
4
+ * preventing overlapping executions and event loop blocking.
5
+ *
6
+ * @param {Function} cb - Function to execute (can be async)
7
+ * @param {number} delay - Delay in ms between executions
8
+ * @param {boolean} [immediate=true] - Whether to fire the first execution immediately
9
+ * @param {boolean} [nextTick=false] - If immediate is true, whether to yield to the event loop before the first execution
10
+ * @returns {Function} A function to clear the interval
11
+ */
12
+ export const setSafeInterval = (cb, delay, immediate = true, nextTick = false) => {
13
+ let isCleared = false;
14
+ let timerId = null;
15
+
16
+ const loop = async () => {
17
+ if (isCleared) return;
18
+
19
+ try {
20
+ await cb();
21
+ } catch (e) {
22
+ console.error('SafeInterval callback error:', e);
23
+ }
24
+
25
+ if (!isCleared) {
26
+ timerId = setTimeout(loop, delay);
27
+ }
28
+ };
29
+
30
+ if (immediate) {
31
+ if (nextTick) {
32
+ timerId = setTimeout(loop, 0);
33
+ } else {
34
+ loop();
35
+ }
36
+ } else {
37
+ timerId = setTimeout(loop, delay);
38
+ }
39
+
40
+ return () => {
41
+ isCleared = true;
42
+ clearTimeout(timerId);
43
+ };
44
+ };