Change the prime table (fix #5)

This commit is contained in:
Jacob Zhong
2022-09-18 12:21:17 -04:00
parent 49519f4f4a
commit 0752505755
4 changed files with 1971 additions and 1202 deletions
+5 -1
View File
@@ -229,7 +229,11 @@ mod tests {
let x = rng.gen_biguint(150);
assert!(matches!(ExactRoots::sqrt_exact(&(&x * &x)), Some(v) if v == x));
let x = rng.gen_biguint(150);
assert!(matches!(ExactRoots::cbrt_exact(&(&x * &x * &x)), Some(v) if v == x), "failed at {}", x);
assert!(
matches!(ExactRoots::cbrt_exact(&(&x * &x * &x)), Some(v) if v == x),
"failed at {}",
x
);
}
// test non-perfect powers
for _ in 0..10 {
+45 -93
View File
@@ -5,8 +5,8 @@ use core::ops::*;
use either::*;
use num_integer::{Integer, Roots};
use num_modular::{
ModularCoreOps, ModularInteger, ModularPow, ModularSymbols, ModularUnaryOps, Reducer,
ReducedInt, Montgomery,
ModularCoreOps, ModularInteger, ModularPow, ModularSymbols, ModularUnaryOps, Montgomery,
ReducedInt, Reducer,
};
use num_traits::{FromPrimitive, Num, One, Pow, ToPrimitive, Zero};
@@ -20,27 +20,6 @@ use crate::{BitTest, ExactRoots};
#[derive(Debug, Clone, Copy)]
pub struct Mint<T: Integer, R: Reducer<T>>(Either<T, ReducedInt<T, R>>);
// // it seems that auto derivation struggles to provide an implementation for Copy, Clone and Debug with proper trait bounds
// impl<T: Integer + Clone> Clone for Mint<T>
// where
// T::Inv: Clone,
// {
// #[inline(always)]
// fn clone(&self) -> Self {
// Self(self.0.clone())
// }
// }
// impl<T: Integer + Copy> Copy for Mint<T> where T::Inv: Copy {}
// impl<T: Integer + core::fmt::Debug> core::fmt::Debug for Mint<T>
// where
// T::Inv: core::fmt::Debug,
// {
// #[inline(always)]
// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
// self.0.fmt(f)
// }
// }
impl<T: Integer, R: Reducer<T>> From<T> for Mint<T, R> {
#[inline(always)]
fn from(v: T) -> Self {
@@ -102,8 +81,7 @@ macro_rules! forward_uops_ref {
};
}
impl<T: Integer + Clone, R: Reducer<T>> PartialEq for Mint<T, R>
{
impl<T: Integer + Clone, R: Reducer<T>> PartialEq for Mint<T, R> {
fn eq(&self, other: &Self) -> bool {
match (&self.0, &other.0) {
(Left(v1), Left(v2)) => v1 == v2,
@@ -112,12 +90,9 @@ impl<T: Integer + Clone, R: Reducer<T>> PartialEq for Mint<T, R>
}
}
}
impl<T: Integer + Clone, R: Reducer<T>> Eq for Mint<T, R>
{
}
impl<T: Integer + Clone, R: Reducer<T>> Eq for Mint<T, R> {}
impl<T: Integer + Clone, R: Reducer<T> + Clone> PartialOrd for Mint<T, R>
{
impl<T: Integer + Clone, R: Reducer<T> + Clone> PartialOrd for Mint<T, R> {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
match (&self.0, &other.0) {
(Left(v1), Left(v2)) => v1.partial_cmp(v2),
@@ -130,8 +105,7 @@ impl<T: Integer + Clone, R: Reducer<T> + Clone> PartialOrd for Mint<T, R>
}
}
}
impl<T: Integer + Clone, R: Reducer<T> + Clone> Ord for Mint<T, R>
{
impl<T: Integer + Clone, R: Reducer<T> + Clone> Ord for Mint<T, R> {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
match (&self.0, &other.0) {
(Left(v1), Left(v2)) => v1.cmp(v2),
@@ -142,8 +116,7 @@ impl<T: Integer + Clone, R: Reducer<T> + Clone> Ord for Mint<T, R>
}
}
impl<T: Integer + Clone, R: Reducer<T> + Clone> Mint<T, R>
{
impl<T: Integer + Clone, R: Reducer<T> + Clone> Mint<T, R> {
#[inline(always)]
pub fn value(&self) -> T {
match &self.0 {
@@ -156,8 +129,7 @@ impl<T: Integer + Clone, R: Reducer<T> + Clone> Mint<T, R>
// forward binary operators by converting result to MontgomeryInt whenever possible
macro_rules! forward_binops_right {
(impl $imp:ident, $method:ident) => {
impl<T: Integer + Clone, R: Reducer<T> + Clone> $imp for Mint<T, R>
{
impl<T: Integer + Clone, R: Reducer<T> + Clone> $imp for Mint<T, R> {
type Output = Self;
#[inline]
fn $method(self, rhs: Self) -> Self::Output {
@@ -173,8 +145,8 @@ macro_rules! forward_binops_right {
}
}
impl<T: Integer + Clone + for<'r> $imp<&'r T, Output = T>, R: Reducer<T> + Clone> $imp<&Self>
for Mint<T, R>
impl<T: Integer + Clone + for<'r> $imp<&'r T, Output = T>, R: Reducer<T> + Clone>
$imp<&Self> for Mint<T, R>
{
type Output = Mint<T, R>;
#[inline]
@@ -191,8 +163,7 @@ macro_rules! forward_binops_right {
}
}
impl<T: Integer + Clone, R: Reducer<T> + Clone> $imp<Mint<T, R>> for &Mint<T, R>
{
impl<T: Integer + Clone, R: Reducer<T> + Clone> $imp<Mint<T, R>> for &Mint<T, R> {
type Output = Mint<T, R>;
// FIXME: additional clone here due to https://github.com/rust-lang/rust/issues/39959
// (same for ref & ref operation below, and those for Div and Rem)
@@ -209,8 +180,12 @@ macro_rules! forward_binops_right {
})
}
}
impl<'a, 'b, T: Integer + Clone + for<'r> $imp<&'r T, Output = T>, R: Reducer<T> + Clone>
$imp<&'b Mint<T, R>> for &'a Mint<T, R>
impl<
'a,
'b,
T: Integer + Clone + for<'r> $imp<&'r T, Output = T>,
R: Reducer<T> + Clone,
> $imp<&'b Mint<T, R>> for &'a Mint<T, R>
{
type Output = Mint<T, R>;
#[inline]
@@ -233,8 +208,7 @@ forward_binops_right!(impl Add, add);
forward_binops_right!(impl Sub, sub);
forward_binops_right!(impl Mul, mul);
impl<T: Integer + Clone, R: Reducer<T>> Div for Mint<T, R>
{
impl<T: Integer + Clone, R: Reducer<T>> Div for Mint<T, R> {
type Output = Self;
#[inline]
@@ -243,8 +217,7 @@ impl<T: Integer + Clone, R: Reducer<T>> Div for Mint<T, R>
Self(Left(v1.div(v2)))
}
}
impl<T: Integer + Clone + for<'r> Div<&'r T, Output = T>, R: Reducer<T>> Div<&Self> for Mint<T, R>
{
impl<T: Integer + Clone + for<'r> Div<&'r T, Output = T>, R: Reducer<T>> Div<&Self> for Mint<T, R> {
type Output = Self;
#[inline]
@@ -255,8 +228,7 @@ impl<T: Integer + Clone + for<'r> Div<&'r T, Output = T>, R: Reducer<T>> Div<&Se
}
}
}
impl<T: Integer + Clone, R: Reducer<T>> Div<Mint<T, R>> for &Mint<T, R>
{
impl<T: Integer + Clone, R: Reducer<T>> Div<Mint<T, R>> for &Mint<T, R> {
type Output = Mint<T, R>;
#[inline]
@@ -280,8 +252,7 @@ impl<'a, 'b, T: Integer + Clone + for<'r> Div<&'r T, Output = T>, R: Reducer<T>>
}
}
impl<T: Integer + Clone, R: Reducer<T> + Clone> Rem for Mint<T, R>
{
impl<T: Integer + Clone, R: Reducer<T> + Clone> Rem for Mint<T, R> {
type Output = Self;
#[inline]
@@ -296,8 +267,7 @@ impl<T: Integer + Clone, R: Reducer<T> + Clone> Rem for Mint<T, R>
}
}
}
impl<T: Integer + Clone, R: Reducer<T> + Clone> Rem<&Self> for Mint<T, R>
{
impl<T: Integer + Clone, R: Reducer<T> + Clone> Rem<&Self> for Mint<T, R> {
type Output = Self;
#[inline]
@@ -312,9 +282,7 @@ impl<T: Integer + Clone, R: Reducer<T> + Clone> Rem<&Self> for Mint<T, R>
}
}
}
impl<T: Integer + Clone, R: Reducer<T> + Clone> Rem<Mint<T, R>> for &Mint<T, R>
where
{
impl<T: Integer + Clone, R: Reducer<T> + Clone> Rem<Mint<T, R>> for &Mint<T, R> {
type Output = Mint<T, R>;
#[inline]
@@ -329,9 +297,7 @@ where
}
}
}
impl<'a, 'b, T: Integer + Clone, R: Reducer<T> + Clone> Rem<&'b Mint<T, R>>
for &'a Mint<T, R>
{
impl<'a, 'b, T: Integer + Clone, R: Reducer<T> + Clone> Rem<&'b Mint<T, R>> for &'a Mint<T, R> {
type Output = Mint<T, R>;
#[inline]
@@ -347,8 +313,7 @@ impl<'a, 'b, T: Integer + Clone, R: Reducer<T> + Clone> Rem<&'b Mint<T, R>>
}
}
impl<T: Integer + Clone, R: Reducer<T> + Clone> Zero for Mint<T, R>
{
impl<T: Integer + Clone, R: Reducer<T> + Clone> Zero for Mint<T, R> {
#[inline(always)]
fn zero() -> Self {
Self(Left(T::zero()))
@@ -362,8 +327,7 @@ impl<T: Integer + Clone, R: Reducer<T> + Clone> Zero for Mint<T, R>
}
}
impl<T: Integer + Clone, R: Reducer<T> + Clone> One for Mint<T, R>
{
impl<T: Integer + Clone, R: Reducer<T> + Clone> One for Mint<T, R> {
#[inline(always)]
fn one() -> Self {
Self(Left(T::one()))
@@ -371,8 +335,7 @@ impl<T: Integer + Clone, R: Reducer<T> + Clone> One for Mint<T, R>
forward_uops_ref!(is_one => bool);
}
impl<T: Integer + Clone, R: Reducer<T> + Clone> Num for Mint<T, R>
{
impl<T: Integer + Clone, R: Reducer<T> + Clone> Num for Mint<T, R> {
type FromStrRadixErr = <T as Num>::FromStrRadixErr;
#[inline(always)]
@@ -381,8 +344,7 @@ impl<T: Integer + Clone, R: Reducer<T> + Clone> Num for Mint<T, R>
}
}
impl<T: Integer + Clone, R: Reducer<T> + Clone> Integer for Mint<T, R>
{
impl<T: Integer + Clone, R: Reducer<T> + Clone> Integer for Mint<T, R> {
forward_binops_left_ref_only!(div_floor);
forward_binops_left_ref_only!(mod_floor);
forward_binops_left_ref_only!(lcm);
@@ -408,8 +370,7 @@ impl<T: Integer + Clone, R: Reducer<T> + Clone> Integer for Mint<T, R>
}
}
impl<T: Integer + Clone + Roots, R: Reducer<T> + Clone> Roots for Mint<T, R>
{
impl<T: Integer + Clone + Roots, R: Reducer<T> + Clone> Roots for Mint<T, R> {
#[inline]
fn nth_root(&self, n: u32) -> Self {
match &self.0 {
@@ -419,8 +380,7 @@ impl<T: Integer + Clone + Roots, R: Reducer<T> + Clone> Roots for Mint<T, R>
}
}
impl<T: Integer + Clone + FromPrimitive, R: Reducer<T>> FromPrimitive for Mint<T, R>
{
impl<T: Integer + Clone + FromPrimitive, R: Reducer<T>> FromPrimitive for Mint<T, R> {
#[inline]
fn from_f64(n: f64) -> Option<Self> {
T::from_f64(n).map(|v| Self(Left(v)))
@@ -435,8 +395,7 @@ impl<T: Integer + Clone + FromPrimitive, R: Reducer<T>> FromPrimitive for Mint<T
}
}
impl<T: Integer + Clone + ToPrimitive, R: Reducer<T> + Clone> ToPrimitive for Mint<T, R>
{
impl<T: Integer + Clone + ToPrimitive, R: Reducer<T> + Clone> ToPrimitive for Mint<T, R> {
#[inline]
fn to_f64(&self) -> Option<f64> {
match &self.0 {
@@ -460,8 +419,7 @@ impl<T: Integer + Clone + ToPrimitive, R: Reducer<T> + Clone> ToPrimitive for Mi
}
}
impl<T: Integer + Clone + Pow<u32, Output = T>, R: Reducer<T>> Pow<u32> for Mint<T, R>
{
impl<T: Integer + Clone + Pow<u32, Output = T>, R: Reducer<T>> Pow<u32> for Mint<T, R> {
type Output = Self;
#[inline]
fn pow(self, rhs: u32) -> Self::Output {
@@ -472,8 +430,7 @@ impl<T: Integer + Clone + Pow<u32, Output = T>, R: Reducer<T>> Pow<u32> for Mint
}
}
impl<T: Integer + Clone + ExactRoots, R: Reducer<T> + Clone> ExactRoots for Mint<T, R>
{
impl<T: Integer + Clone + ExactRoots, R: Reducer<T> + Clone> ExactRoots for Mint<T, R> {
#[inline]
fn nth_root_exact(&self, n: u32) -> Option<Self> {
match &self.0 {
@@ -483,8 +440,7 @@ impl<T: Integer + Clone + ExactRoots, R: Reducer<T> + Clone> ExactRoots for Mint
}
}
impl<T: Integer + Clone + BitTest, R: Reducer<T>> BitTest for Mint<T, R>
{
impl<T: Integer + Clone + BitTest, R: Reducer<T>> BitTest for Mint<T, R> {
#[inline]
fn bit(&self, position: usize) -> bool {
match &self.0 {
@@ -508,8 +464,7 @@ impl<T: Integer + Clone + BitTest, R: Reducer<T>> BitTest for Mint<T, R>
}
}
impl<T: Integer + Clone + Shr<usize, Output = T>, R: Reducer<T>> Shr<usize> for Mint<T, R>
{
impl<T: Integer + Clone + Shr<usize, Output = T>, R: Reducer<T>> Shr<usize> for Mint<T, R> {
type Output = Self;
#[inline]
fn shr(self, rhs: usize) -> Self::Output {
@@ -519,8 +474,7 @@ impl<T: Integer + Clone + Shr<usize, Output = T>, R: Reducer<T>> Shr<usize> for
}
}
}
impl<T: Integer + Clone + Shr<usize, Output = T>, R: Reducer<T>> Shr<usize> for &Mint<T, R>
{
impl<T: Integer + Clone + Shr<usize, Output = T>, R: Reducer<T>> Shr<usize> for &Mint<T, R> {
type Output = Mint<T, R>;
#[inline]
fn shr(self, rhs: usize) -> Self::Output {
@@ -531,8 +485,7 @@ impl<T: Integer + Clone + Shr<usize, Output = T>, R: Reducer<T>> Shr<usize> for
}
}
impl<T: Integer + Clone, R: Reducer<T> + Clone> ModularCoreOps<&Self, &Self> for Mint<T, R>
{
impl<T: Integer + Clone, R: Reducer<T> + Clone> ModularCoreOps<&Self, &Self> for Mint<T, R> {
type Output = Self;
#[inline]
fn addm(self, rhs: &Self, m: &Self) -> Self::Output {
@@ -565,8 +518,8 @@ impl<T: Integer + Clone, R: Reducer<T> + Clone> ModularCoreOps<&Self, &Self> for
}
}
}
impl<'a, 'b, T: Integer + Clone, R: Reducer<T> + Clone> ModularCoreOps<&'b Mint<T, R>, &'b Mint<T, R>>
for &'a Mint<T, R>
impl<'a, 'b, T: Integer + Clone, R: Reducer<T> + Clone>
ModularCoreOps<&'b Mint<T, R>, &'b Mint<T, R>> for &'a Mint<T, R>
{
type Output = Mint<T, R>;
#[inline]
@@ -601,8 +554,7 @@ impl<'a, 'b, T: Integer + Clone, R: Reducer<T> + Clone> ModularCoreOps<&'b Mint<
}
}
impl<T: Integer + Clone, R: Reducer<T> + Clone> ModularUnaryOps<&Self> for Mint<T, R>
{
impl<T: Integer + Clone, R: Reducer<T> + Clone> ModularUnaryOps<&Self> for Mint<T, R> {
type Output = Self;
#[inline]
fn negm(self, m: &Self) -> Self::Output {
@@ -641,7 +593,8 @@ impl<T: Integer + Clone, R: Reducer<T> + Clone> ModularUnaryOps<&Self> for Mint<
}))
}
}
impl<'a, 'b, T: Integer + Clone, R: Reducer<T> + Clone> ModularUnaryOps<&'b Mint<T, R>> for &'a Mint<T, R>
impl<'a, 'b, T: Integer + Clone, R: Reducer<T> + Clone> ModularUnaryOps<&'b Mint<T, R>>
for &'a Mint<T, R>
{
type Output = Mint<T, R>;
#[inline]
@@ -682,8 +635,8 @@ impl<'a, 'b, T: Integer + Clone, R: Reducer<T> + Clone> ModularUnaryOps<&'b Mint
}
}
impl<T: Integer + Clone + for<'r> ModularSymbols<&'r T>, R: Reducer<T> + Clone> ModularSymbols<&Self>
for Mint<T, R>
impl<T: Integer + Clone + for<'r> ModularSymbols<&'r T>, R: Reducer<T> + Clone>
ModularSymbols<&Self> for Mint<T, R>
{
#[inline]
fn checked_jacobi(&self, n: &Self) -> Option<i8> {
@@ -711,8 +664,7 @@ impl<T: Integer + Clone + for<'r> ModularSymbols<&'r T>, R: Reducer<T> + Clone>
}
}
impl<T: Integer + Clone, R: Reducer<T> + Clone> ModularPow<&Self, &Self> for Mint<T, R>
{
impl<T: Integer + Clone, R: Reducer<T> + Clone> ModularPow<&Self, &Self> for Mint<T, R> {
type Output = Self;
#[inline]
fn powm(self, exp: &Self, m: &Self) -> Self::Output {
+58 -54
View File
@@ -16,7 +16,8 @@ use crate::factor::{one_line, pollard_rho, squfof, SQUFOF_MULTIPLIERS};
use crate::mint::SmallMint;
use crate::primality::{PrimalityBase, PrimalityRefBase};
use crate::tables::{
MOEBIUS_ODD, SMALL_PRIMES, SMALL_PRIMES_NEXT, WHEEL_NEXT, WHEEL_PREV, WHEEL_SIZE,
MILLER_RABIN_BASE32, MOEBIUS_ODD, SMALL_PRIMES, SMALL_PRIMES_NEXT, WHEEL_NEXT, WHEEL_PREV,
WHEEL_SIZE,
};
#[cfg(feature = "big-table")]
use crate::tables::{SMALL_PRIMES_INV, ZETA_LOG_TABLE};
@@ -32,10 +33,10 @@ use std::collections::BTreeMap;
use std::convert::TryFrom;
#[cfg(feature = "big-table")]
use crate::tables::{MILLER_RABIN_BASE32, MILLER_RABIN_BASE64};
use crate::tables::MILLER_RABIN_BASE64;
/// Fast primality test on a u64 integer. It's based on
/// deterministic Miller-rabin tests. if target is larger than 2^64 or more
/// deterministic Miller-rabin tests. If target is larger than 2^64 or more
/// controlled primality tests are desired, please use [is_prime()]
#[cfg(not(feature = "big-table"))]
pub fn is_prime64(target: u64) -> bool {
@@ -62,28 +63,6 @@ pub fn is_prime64(target: u64) -> bool {
is_prime64_miller(target)
}
// Primality test for u64 with only miller-rabin tests, used during factorization.
// It assumes the target is odd, not too small and cannot be divided small primes
#[cfg(not(feature = "big-table"))]
fn is_prime64_miller(target: u64) -> bool {
// The collection of witnesses are from http://miller-rabin.appspot.com/
if let Ok(u) = u16::try_from(target) {
// 2, 3 for u16 range
let u = Mint::from(u);
return u.is_sprp(Mint::from(2)) && u.is_sprp(Mint::from(3));
}
if let Ok(u) = u32::try_from(target) {
// 2, 7, 61 for u32 range
let u = Mint::from(u);
return u.is_sprp(Mint::from(2)) && u.is_sprp(Mint::from(7)) && u.is_sprp(Mint::from(61));
}
// 2, 325, 9375, 28178, 450775, 9780504, 1795265022 for u64 range
const WITNESS64: [u64; 7] = [2, 325, 9375, 28178, 450775, 9780504, 1795265022];
let u = Mint::from(target);
WITNESS64.iter().all(|&x| u.is_sprp(Mint::from(x)))
}
/// Very fast primality test on a u64 integer is a prime number. It's based on
/// deterministic Miller-rabin tests with hashing. if target is larger than 2^64 or more controlled
/// primality tests are desired, please use [is_prime()]
@@ -97,7 +76,7 @@ pub fn is_prime64(target: u64) -> bool {
return target == 2;
}
// trial division
// remove small factors
if target < SMALL_PRIMES_NEXT {
// find in the prime list if the target is small enough
return SMALL_PRIMES.binary_search(&(target as u16)).is_ok();
@@ -110,40 +89,52 @@ pub fn is_prime64(target: u64) -> bool {
}
}
// Then do a deterministic Miller-rabin test
is_prime64_miller(target)
}
fn is_prime32_miller(target: u32) -> bool {
let h = target;
let h = ((h >> 16) ^ h).wrapping_mul(0x45d9f3b);
let h = ((h >> 16) ^ h).wrapping_mul(0x45d9f3b);
let h = ((h >> 16) ^ h) & 255;
let u = SmallMint::from(target);
return u.is_sprp(SmallMint::from(MILLER_RABIN_BASE32[h as usize] as u32));
}
// Primality test for u64 with only miller-rabin tests, used during factorization.
// It assumes the target is odd, not too small and cannot be divided small primes
#[cfg(not(feature = "big-table"))]
fn is_prime64_miller(target: u64) -> bool {
if let Ok(u) = u32::try_from(target) {
return is_prime32_miller(u);
}
// The collection of witnesses are from http://miller-rabin.appspot.com/
const WITNESS64: [u64; 7] = [2, 325, 9375, 28178, 450775, 9780504, 1795265022];
let u = SmallMint::from(target);
WITNESS64.iter().all(|&x| u.is_sprp(SmallMint::from(x)))
}
// Primality test for u64 with only miller-rabin tests, used during factorization.
// It assumes the target is odd, not too small and cannot be divided small primes
#[cfg(feature = "big-table")]
fn is_prime64_miller(target: u64) -> bool {
// 32bit test
const MAGIC: u32 = 0xAD625B89;
if let Ok(u) = u32::try_from(target) {
let base = u.wrapping_mul(MAGIC) >> 24;
let u = SmallMint::from(u);
return u.is_sprp(SmallMint::from(MILLER_RABIN_BASE32[base as usize] as u32));
return is_prime32_miller(u);
}
// 49bit test
let mt = SmallMint::from(target);
if !mt.is_sprp(2.into()) {
let u = SmallMint::from(target);
if !u.is_sprp(2.into()) {
return false;
}
let u = target as u32; // truncate
let base = u.wrapping_mul(MAGIC) >> 18;
if !mt.is_sprp(SmallMint::from(MILLER_RABIN_BASE64[base as usize] as u64)) {
return false;
}
if target < (1u64 << 49) {
return true;
}
// 64bit test
const SECOND_BASES: [u64; 8] = [15, 135, 13, 60, 15, 117, 65, 29];
let base = base >> 13;
mt.is_sprp(SmallMint::from(SECOND_BASES[base as usize]))
let h = target;
let h = ((h >> 32) ^ h).wrapping_mul(0x45d9f3b3335b369);
let h = ((h >> 32) ^ h).wrapping_mul(0x3335b36945d9f3b);
let h = ((h >> 32) ^ h) & 16383;
let b = MILLER_RABIN_BASE64[h as usize];
return u.is_sprp((b as u64 & 4095).into()) && u.is_sprp((b as u64 >> 12).into());
}
/// Fast integer factorization on a u64 target. It's based on a selection of factorization methods.
@@ -276,9 +267,12 @@ pub(crate) fn factorize64_advanced(cofactors: &[(u64, usize)]) -> Vec<(u64, usiz
let start = MontgomeryInt::new(random::<u64>(), &target);
let offset = start.convert(random::<u64>());
let max_iter = max_iter_ratio << (target.bits() / 6); // unoptimized heuristic
if let (Some(p), _) =
pollard_rho(&SmallMint::from(target), start.into(), offset.into(), max_iter)
{
if let (Some(p), _) = pollard_rho(
&SmallMint::from(target),
start.into(),
offset.into(),
max_iter,
) {
break p.value();
}
}
@@ -434,9 +428,12 @@ pub(crate) fn factorize128_advanced(cofactors: &[(u128, usize)]) -> Vec<(u128, u
let start = MontgomeryInt::new(random::<u128>(), &target);
let offset = start.convert(random::<u128>());
let max_iter = max_iter_ratio << (target.bits() / 6); // unoptimized heuristic
if let (Some(p), _) =
pollard_rho(&SmallMint::from(target), start.into(), offset.into(), max_iter)
{
if let (Some(p), _) = pollard_rho(
&SmallMint::from(target),
start.into(),
offset.into(),
max_iter,
) {
break p.value();
}
}
@@ -1000,7 +997,8 @@ pub fn prime_pi_est<T: ToPrimitive + FromPrimitive>(target: &T) -> T {
T::from_f64(total + 1f64).unwrap()
}
/// Estimate the value of nth prime by bisecting on [prime_pi_est]
/// Estimate the value of nth prime by bisecting on [prime_pi_est].
/// If the result is larger than maximum of `T`, [None] will be returned.
pub fn nth_prime_est<T: ToPrimitive + FromPrimitive + Num + PartialOrd>(target: &T) -> Option<T>
where
for<'r> &'r T: RefNum<T>,
@@ -1044,6 +1042,7 @@ mod tests {
for x in 2..100 {
assert_eq!(SMALL_PRIMES.contains(&x), is_prime64(x as u64));
}
assert!(is_prime64(677));
// some large primes
assert!(is_prime64(6469693333));
@@ -1060,6 +1059,11 @@ mod tests {
assert!(!is_prime64(8651776913431));
assert!(!is_prime64(1152965996591997761));
// false positives reported by JASory (#4)
assert!(!is_prime64(600437059821397));
assert!(!is_prime64(3866032210719337));
assert!(!is_prime64(4100599722623587));
// ensure no factor for 100 random primes
let mut rng = rand::thread_rng();
for _ in 0..100 {
+1863 -1054
View File
File diff suppressed because it is too large Load Diff