大数判定是否是质数
// #include < NTL / ZZ.h >
var prime = require("./genPrime")
var primeList = prime.getPrimes(2000).map(BigInt)
/**
*
* @param {bigint} n n为素数候选者
* @param {bigint} x x为随机数
* @returns
*/
function witness(n, x) {
let d, y, z;
let j, s;
if (x == 0n) return 0n;
//计算s,d,使得n-1 = 2^s * d, d是奇数:
s = 1;
d = n / 2n;
while (d % 2n == 0) {
s++;
d /= 2n;
}
/*在NTL内置的函数中,有一个刚好满足我们的要求:
m = n - 1;
k = MakeOdd(m);
*/
// z = PowerMod(x, d, n); // z = x^d % n
z = PowerMod(x, d, n)
if (z == 1n) return 0;
j = 0;
do {
y = z;
z = (y * y) % n;
j++;
} while (j < s && z != 1);
return z != 1n || y != n - 1n;
}
/**
*
* @param {BigInt} n n为待检测素数
* @param {BigInt} t t为检测次数
* @returns
*/
function PrimeTest(n, t) {
if (n <= 1n) return false;
//用2000以内的素数对n进行初筛
// PrimeSeq s; // 生成一个素数数列
let p;
p = primeList[0];
// first prime is always 2
let index = 0;
while (p && p < 2000n) {
if ((n % p) == 0n)
return (n == p);
index++;
p = primeList[index];
}
//Miller-Rabin法推演n的素性
let x;
for (var i = 0; i < t; i++) {
x = (BigInt(Math.random() * 0xffffffffffffff) * n / 0xffffffffffffffn)
// 随机数 between 0 and n-1
if (witness(n, x))//有凭证
return false;
}
return true;
}
/**
* x^d%n
* @param {bigint} x
* @param {bigint} d
* @param {bigint} n
* @returns {bigint}
*/
function PowerMod(x, d, n) {
let d2 = d.toString(2).split("").map(BigInt)
let collect = new Array(d2.length).fill(0n)
collect[d2.length - 1] = x % n
for (let index = 1; index < d2.length; index++) {
collect[d2.length - index - 1] = (collect[d2.length - index] * collect[d2.length - index]) % n
}
let temp1 = 1n;
for (let index = 0; index < collect.length; index++) {
if (d2[index])
temp1 = (temp1 * collect[index]) % n
}
return temp1
}
// console.log(PowerMod(4n, 4n, 7n));
console.log(PrimeTest(10865294066886871n, 1n))
genPrime 文件
function getPrimes(limit = 0x100000) {
var res = [];
res[0] = 2;
for (var i = 1, k = 3; k < limit; k += 2) {
var sqrt = Math.ceil(Math.sqrt(k));
for (var j = 0; j < i && res[j] <= sqrt; j++)
if (k % res[j] === 0)
break;
if (i !== j && res[j] <= sqrt)
continue;
res[i++] = k;
}
return res;
}
module.exports = { getPrimes}