@mathigon/fermat
Version:
Powerful mathematics and statistics library for JavaScript.
125 lines (95 loc) • 3.06 kB
text/typescript
// ============================================================================
// Fermat.js | Number Theory
// (c) Mathigon
// ============================================================================
import {unique} from '@mathigon/core';
/** Calculates the greatest common divisor of multiple numbers. */
export function gcd(...numbers: number[]): number {
const [first, ...rest] = numbers;
if (rest.length > 1) return gcd(first, gcd(...rest));
let a = Math.abs(first);
let b = Math.abs(rest[0]);
while (b) [a, b] = [b, a % b];
return a;
}
/** Calculates the lowest common multiple of multiple numbers. */
export function lcm(...numbers: number[]): number {
const [first, ...rest] = numbers;
if (rest.length > 1) return lcm(first, lcm(...rest));
return Math.abs(first * rest[0]) / gcd(first, rest[0]);
}
/** Checks if a number n is prime. */
export function isPrime(n: number) {
if (n % 1 !== 0 || n < 2) return false;
if (n % 2 === 0) return (n === 2);
if (n % 3 === 0) return (n === 3);
const m = Math.sqrt(n);
for (let i = 5; i <= m; i += 6) {
if (n % i === 0) return false;
if (n % (i + 2) === 0) return false;
}
return true;
}
/** Finds the prime factorisation of a number n. */
export function primeFactorisation(n: number): number[] {
if (n === 1) return [];
if (isPrime(n)) return [n];
const maxf = Math.sqrt(n);
for (let f = 2; f <= maxf; ++f) {
if (n % f === 0) {
return primeFactorisation(f).concat(primeFactorisation(n / f));
}
}
return [];
}
/** Finds all prime factors of a number n. */
export function primeFactors(n: number) {
return unique(primeFactorisation(n));
}
/** Lists all prime numbers between 0 and n. */
export function listPrimes(n = 100) {
if (n < 2) return [];
const result = [2];
for (let i = 3; i <= n; i++) {
let notMultiple = false;
for (const r of result) {
notMultiple = notMultiple || (0 === i % r);
}
if (!notMultiple) result.push(i);
}
return result;
}
/** Generates a random prime number with d digits, where 2 <= d <= 16. */
export function generatePrime(d: number) {
if (d < 2 || d > 16) throw new Error('Invalid number of digits.');
const lastDigit = [1, 3, 7, 9];
const pow = Math.pow(10, d - 2);
while (true) {
const n = Math.floor(Math.random() * 9 * pow) + pow;
const x = 10 * n + lastDigit[Math.floor(4 * Math.random())];
if (isPrime(x)) return x;
}
}
/** Tries to write a number x as the sum of two primes. */
export function goldbach(x: number): [number, number] {
if (x === 4) return [2, 2];
let a = x / 2;
let b = x / 2;
if (a % 2 === 0) {
a--;
b++;
}
while (a >= 3) {
if (isPrime(a) && isPrime(b)) return [a, b];
a -= 2;
b += 2;
}
return [-1, -1];
}
/** Computes Euler's totient function (phi) for a given natural number x. */
export function eulerPhi(x: number) {
if (x <= 0) throw Error('Number should be greater than zero');
let n = x;
for (const p of primeFactors(x)) n *= (p - 1) / p;
return n;
}