UNPKG

@mathigon/fermat

Version:

Powerful mathematics and statistics library for JavaScript.

125 lines (95 loc) 3.06 kB
// ============================================================================ // 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; }