@marlonwq/primality 1.0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Márlon C.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,70 @@
1
+ # Primality
2
+ A high-performance TypeScript library for primality testing using Miller-Rabin and Fermat algorithms. Designed with BigInt support for cryptographic-grade calculations.
3
+
4
+ [![NPM Version](https://img.shields.io/npm/v/@marlonwq/primality)](https://www.npmjs.com/package/@marlonwq/primality)
5
+ [![NPM Downloads](https://img.shields.io/npm/dm/@marlonwq/primality)](https://www.npmjs.com/package/@marlonwq/primality)
6
+ ![GitHub Repo stars](https://img.shields.io/github/stars/marlonwq/primality)
7
+ [![License](https://img.shields.io/npm/l/@marlonwq/primality)](https://github.com/marlonwq/primality/blob/main/LICENSE)
8
+
9
+ ## Features
10
+ - **Miller-Rabin Test**: Robust probabilistic test.
11
+ - **Fermat Primality Test**: Fast probabilistic test based on Fermat's Little Theorem.
12
+ - **BigInt Support**: Test extremely large numbers without precision loss.
13
+ - **Zero Dependencies**: Lightweight and optimized for performance.
14
+
15
+ ## Installation
16
+ ```sh
17
+ pnpm add @marlonwq/primality
18
+ ```
19
+
20
+ ## Usage
21
+
22
+ ```typescript
23
+ import { isPrimeMillerRabin, isPrimeFermat } from '@marlonwq/primality';
24
+
25
+ // Using Miller-Rabin (Recommended for high accuracy)
26
+ // Use the 'n' suffix for BigInt literals
27
+ const num1 = 104729n;
28
+ console.log(isPrimeMillerRabin(num1)); // true
29
+
30
+ // Using Fermat (Faster, but watch out for Carmichael numbers)
31
+ const num2 = 561n;
32
+ console.log(isPrimeFermat(num2)); // true (Fermat's false positive)
33
+ console.log(isPrimeMillerRabin(num2)); // false (Miller-Rabin's correct answer)
34
+ ```
35
+
36
+ ## How it Works
37
+
38
+ <details>
39
+ <summary>Click to expand the mathematical background</summary>
40
+
41
+ The Miller-Rabin test is an evolution of **Fermat's Little Theorem**. Fermat states that if $p$ is prime, then for any integer $a$, $a^{p-1} \equiv 1 \pmod p$. However, some composite numbers (known as **Carmichael numbers**) also satisfy this condition, leading to false positives.
42
+
43
+ ### The Miller-Rabin Secret
44
+ The core of Miller-Rabin is the fact that in a prime field $\mathbb{Z}_p$, the equation $x^2 \equiv 1 \pmod p$ has only two solutions: $x = 1$ and $x = p - 1$ (or $-1$).
45
+
46
+ **The Algorithm Steps:**
47
+ 1. Write $n - 1$ as $2^s \cdot d$ by repeatedly factoring out powers of 2.
48
+ 2. Pick a random base $a$ in the range $[2, n - 2]$.
49
+ 3. Compute $x = a^d \pmod n$. If $x = 1$ or $x = n - 1$, the number is a **probable prime**.
50
+ 4. Otherwise, square $x$ repeatedly ($x = x^2 \pmod n$) up to $s - 1$ times.
51
+ 5. If at any point $x = n - 1$, the number is a **probable prime**.
52
+ 6. If the loop finishes without ever hitting $n - 1$, the number is **definitely composite**.
53
+
54
+ ### Accuracy
55
+ Miller-Rabin is a probabilistic algorithm. Each iteration ($k$) reduces the probability of a composite number being declared prime to less than $1/4$. With $k=40$, the error probability is less than $4^{-40}$ — a value so infinitesimal that it is statistically more likely for a meteor to strike your computer than for the test to provide a wrong answer.
56
+
57
+ </details>
58
+
59
+ ## Contributing
60
+ We use `pnpm` as our package manager. To get started:
61
+
62
+ ```
63
+ pnpm install
64
+ pnpm build
65
+ pnpm test
66
+ ```
67
+ If you find this project helpful, please consider contributing in the following ways: Submitting a [pull request](https://github.com/marlonwq/primality/pulls), opening an [issue](https://github.com/marlonwq/primality/issues), giving the project a star or [buying me a coffee!](https://ko-fi.com/marlonwq)!
68
+
69
+ ## License
70
+ [MIT](https://github.com/marlonwq/primality/blob/main/LICENSE)
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Fermat Primality Test
3
+ * @param n - The number to test (BigInt)
4
+ * @param iterations - Number of trials (higher is more accurate)
5
+ * @returns boolean - True if probably prime, false if composite
6
+ */
7
+ declare function isPrimeFermat(n: bigint, iterations?: number): boolean;
8
+
9
+ /**
10
+ * Miller-Rabin Primality Test
11
+ * @param n - The number to test (BigInt)
12
+ * @param k - Number of iterations (accuracy). Default is 40 for high confidence.
13
+ */
14
+ declare function isPrimeMillerRabin(n: bigint, k?: number): boolean;
15
+
16
+ export { isPrimeFermat, isPrimeMillerRabin };
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Fermat Primality Test
3
+ * @param n - The number to test (BigInt)
4
+ * @param iterations - Number of trials (higher is more accurate)
5
+ * @returns boolean - True if probably prime, false if composite
6
+ */
7
+ declare function isPrimeFermat(n: bigint, iterations?: number): boolean;
8
+
9
+ /**
10
+ * Miller-Rabin Primality Test
11
+ * @param n - The number to test (BigInt)
12
+ * @param k - Number of iterations (accuracy). Default is 40 for high confidence.
13
+ */
14
+ declare function isPrimeMillerRabin(n: bigint, k?: number): boolean;
15
+
16
+ export { isPrimeFermat, isPrimeMillerRabin };
package/dist/index.js ADDED
@@ -0,0 +1,106 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ isPrimeFermat: () => isPrimeFermat,
24
+ isPrimeMillerRabin: () => isPrimeMillerRabin
25
+ });
26
+ module.exports = __toCommonJS(index_exports);
27
+
28
+ // src/fermat.ts
29
+ function isPrimeFermat(n, iterations = 5) {
30
+ if (n <= 1n) return false;
31
+ if (n <= 3n) return true;
32
+ if (n % 2n === 0n) return false;
33
+ for (let i = 0; i < iterations; i++) {
34
+ const a = BigInt(Math.floor(Math.random() * (Number(n) - 4))) + 2n;
35
+ if (powerModular(a, n - 1n, n) !== 1n) {
36
+ return false;
37
+ }
38
+ }
39
+ return true;
40
+ }
41
+ function powerModular(base, exp, mod) {
42
+ let res = 1n;
43
+ base = base % mod;
44
+ while (exp > 0n) {
45
+ if (exp % 2n === 1n) res = res * base % mod;
46
+ base = base * base % mod;
47
+ exp = exp / 2n;
48
+ }
49
+ return res;
50
+ }
51
+
52
+ // src/miller-rabin.ts
53
+ function getRandomBigInt(min, max) {
54
+ const range = max - min;
55
+ const bits = range.toString(2).length;
56
+ let res;
57
+ do {
58
+ let randStr = "";
59
+ for (let i = 0; i < bits; i++) {
60
+ randStr += Math.random() > 0.5 ? "1" : "0";
61
+ }
62
+ res = BigInt("0b" + randStr);
63
+ } while (res > range);
64
+ return res + min;
65
+ }
66
+ function isPrimeMillerRabin(n, k = 40) {
67
+ if (n <= 1n) return false;
68
+ if (n <= 3n) return true;
69
+ if (n % 2n === 0n) return false;
70
+ let d = n - 1n;
71
+ let s = 0n;
72
+ while (d % 2n === 0n) {
73
+ d /= 2n;
74
+ s++;
75
+ }
76
+ for (let i = 0; i < k; i++) {
77
+ const a = getRandomBigInt(2n, n - 2n);
78
+ let x = powerModular2(a, d, n);
79
+ if (x === 1n || x === n - 1n) continue;
80
+ let composite = true;
81
+ for (let r = 1n; r < s; r++) {
82
+ x = x * x % n;
83
+ if (x === n - 1n) {
84
+ composite = false;
85
+ break;
86
+ }
87
+ }
88
+ if (composite) return false;
89
+ }
90
+ return true;
91
+ }
92
+ function powerModular2(base, exp, mod) {
93
+ let res = 1n;
94
+ base = base % mod;
95
+ while (exp > 0n) {
96
+ if (exp % 2n === 1n) res = res * base % mod;
97
+ base = base * base % mod;
98
+ exp = exp / 2n;
99
+ }
100
+ return res;
101
+ }
102
+ // Annotate the CommonJS export names for ESM import in node:
103
+ 0 && (module.exports = {
104
+ isPrimeFermat,
105
+ isPrimeMillerRabin
106
+ });
package/dist/index.mjs ADDED
@@ -0,0 +1,78 @@
1
+ // src/fermat.ts
2
+ function isPrimeFermat(n, iterations = 5) {
3
+ if (n <= 1n) return false;
4
+ if (n <= 3n) return true;
5
+ if (n % 2n === 0n) return false;
6
+ for (let i = 0; i < iterations; i++) {
7
+ const a = BigInt(Math.floor(Math.random() * (Number(n) - 4))) + 2n;
8
+ if (powerModular(a, n - 1n, n) !== 1n) {
9
+ return false;
10
+ }
11
+ }
12
+ return true;
13
+ }
14
+ function powerModular(base, exp, mod) {
15
+ let res = 1n;
16
+ base = base % mod;
17
+ while (exp > 0n) {
18
+ if (exp % 2n === 1n) res = res * base % mod;
19
+ base = base * base % mod;
20
+ exp = exp / 2n;
21
+ }
22
+ return res;
23
+ }
24
+
25
+ // src/miller-rabin.ts
26
+ function getRandomBigInt(min, max) {
27
+ const range = max - min;
28
+ const bits = range.toString(2).length;
29
+ let res;
30
+ do {
31
+ let randStr = "";
32
+ for (let i = 0; i < bits; i++) {
33
+ randStr += Math.random() > 0.5 ? "1" : "0";
34
+ }
35
+ res = BigInt("0b" + randStr);
36
+ } while (res > range);
37
+ return res + min;
38
+ }
39
+ function isPrimeMillerRabin(n, k = 40) {
40
+ if (n <= 1n) return false;
41
+ if (n <= 3n) return true;
42
+ if (n % 2n === 0n) return false;
43
+ let d = n - 1n;
44
+ let s = 0n;
45
+ while (d % 2n === 0n) {
46
+ d /= 2n;
47
+ s++;
48
+ }
49
+ for (let i = 0; i < k; i++) {
50
+ const a = getRandomBigInt(2n, n - 2n);
51
+ let x = powerModular2(a, d, n);
52
+ if (x === 1n || x === n - 1n) continue;
53
+ let composite = true;
54
+ for (let r = 1n; r < s; r++) {
55
+ x = x * x % n;
56
+ if (x === n - 1n) {
57
+ composite = false;
58
+ break;
59
+ }
60
+ }
61
+ if (composite) return false;
62
+ }
63
+ return true;
64
+ }
65
+ function powerModular2(base, exp, mod) {
66
+ let res = 1n;
67
+ base = base % mod;
68
+ while (exp > 0n) {
69
+ if (exp % 2n === 1n) res = res * base % mod;
70
+ base = base * base % mod;
71
+ exp = exp / 2n;
72
+ }
73
+ return res;
74
+ }
75
+ export {
76
+ isPrimeFermat,
77
+ isPrimeMillerRabin
78
+ };
package/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "@marlonwq/primality",
3
+ "version": "1.0.0",
4
+ "description": "A high-performance TypeScript library for primality testing using Miller-Rabin and Fermat algorithms.",
5
+ "main": "dist/index.js",
6
+ "module": "dist/index.mjs",
7
+ "types": "dist/index.d.ts",
8
+ "files": [
9
+ "dist"
10
+ ],
11
+ "scripts": {
12
+ "build": "tsup src/index.ts --format cjs,esm --dts --out-dir dist --clean",
13
+ "test": "vitest"
14
+ },
15
+ "keywords": [
16
+ "math",
17
+ "primality",
18
+ "primes",
19
+ "miller-rabin",
20
+ "fermat",
21
+ "number-theory",
22
+ "cryptography",
23
+ "RSA",
24
+ "RSA cryptography",
25
+ "performance"
26
+ ],
27
+ "author": "Márlon",
28
+ "license": "MIT",
29
+ "packageManager": "pnpm@10.28.0",
30
+ "devDependencies": {
31
+ "tsup": "^8.5.1",
32
+ "typescript": "^5.9.3",
33
+ "vitest": "^4.0.18"
34
+ }
35
+ }