mirror of
https://github.com/uutils/num-prime.git
synced 2026-06-10 16:12:35 -07:00
Change the prime table (fix #5)
This commit is contained in:
+5
-1
@@ -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
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user