Struct num_prime::PrimalityTestConfig
source · #[non_exhaustive]pub struct PrimalityTestConfig {
pub sprp_trials: usize,
pub sprp_random_trials: usize,
pub slprp_test: bool,
pub eslprp_test: bool,
}
Expand description
Represents a configuration for a primality test
Fields (Non-exhaustive)§
This struct is marked as non-exhaustive
Non-exhaustive structs could have additional fields added in future. Therefore, non-exhaustive structs cannot be constructed in external crates using the traditional
Struct { .. }
syntax; cannot be matched against without a wildcard ..
; and struct update syntax will not work.sprp_trials: usize
Number of strong probable prime test, starting from base 2
sprp_random_trials: usize
Number of strong probable prime test with random bases
slprp_test: bool
Whether perform strong lucas probable prime test (with automatically selected parameters)
eslprp_test: bool
Whether perform extra strong lucas probable prime test (with automatically selected parameters)
Implementations§
source§impl PrimalityTestConfig
impl PrimalityTestConfig
sourcepub fn strict() -> Self
pub fn strict() -> Self
Create a configuration with a very strong primality check. It’s based on the strongest deterministic primality testing and some SPRP tests with random bases.
Examples found in repository?
More examples
src/nt_funcs.rs (line 804)
799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815
pub fn is_safe_prime<T: PrimalityBase>(target: &T) -> Primality
where
for<'r> &'r T: PrimalityRefBase<T>,
{
let buf = NaiveBuffer::new();
let config = Some(PrimalityTestConfig::strict());
// test (n-1)/2 first since its smaller
let sophie_p = buf.is_prime(&(target >> 1), config);
if matches!(sophie_p, Primality::No) {
return sophie_p;
}
// and then test target itself
let target_p = buf.is_prime(target, config);
target_p & sophie_p
}
src/rand.rs (line 129)
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216
fn gen_safe_prime(&mut self, bit_size: usize) -> u128 {
loop {
let config = Some(PrimalityTestConfig::strict());
let p = self.gen_prime(bit_size, config);
if is_prime(&SmallMint::from(p >> 1), config).probably() {
break p;
}
if let Some(p2) = p.checked_mul(2).and_then(|v| v.checked_add(1)) {
if is_prime(&p2, config).probably() {
break p2;
}
}
}
}
#[inline]
fn gen_safe_prime_exact(&mut self, bit_size: usize) -> u128 {
loop {
let config = Some(PrimalityTestConfig::strict());
let p = self.gen_prime_exact(bit_size, config);
if is_prime(&SmallMint::from(p >> 1), config).probably() {
break p;
}
if let Some(p2) = p.checked_mul(2).and_then(|v| v.checked_add(1)) {
if is_prime(&p2, config).probably() {
break p2;
}
}
}
}
}
#[cfg(feature = "num-bigint")]
impl<R: Rng> RandPrime<BigUint> for R {
#[inline]
fn gen_prime(&mut self, bit_size: usize, config: Option<PrimalityTestConfig>) -> BigUint {
loop {
let mut t = self.gen_biguint(bit_size as u64);
t.set_bit(0, true); // filter even numbers
if is_prime(&t, config).probably() {
break t;
} else if let Some(p) = next_prime(&t, config) {
break p;
}
}
}
#[inline]
fn gen_prime_exact(&mut self, bit_size: usize, config: Option<PrimalityTestConfig>) -> BigUint {
loop {
let mut t = self.gen_biguint(bit_size as u64);
t.set_bit(0, true); // filter even numbers
t.set_bit(bit_size as u64 - 1, true);
if is_prime(&t, config).probably() {
break t;
} else if let Some(p) = next_prime(&t, config) {
break p;
}
}
}
#[inline]
fn gen_safe_prime(&mut self, bit_size: usize) -> BigUint {
let config = Some(PrimalityTestConfig::strict());
let p = self.gen_prime(bit_size, config);
if is_prime(&(&p >> 1u8), config).probably() {
return p;
}
let p2 = (p << 1u8) + 1u8;
if is_prime(&p2, config).probably() {
return p2;
}
self.gen_safe_prime(bit_size)
}
#[inline]
fn gen_safe_prime_exact(&mut self, bit_size: usize) -> BigUint {
let config = Some(PrimalityTestConfig::strict());
let p = self.gen_prime_exact(bit_size, config);
if is_prime(&(&p >> 1u8), config).probably() {
return p;
}
let p2 = (p << 1u8) + 1u8;
if is_prime(&p2, config).probably() {
return p2;
}
self.gen_safe_prime(bit_size)
}
sourcepub fn bpsw() -> Self
pub fn bpsw() -> Self
Create a configuration for Baillie-PSW test (base 2 SPRP test + SLPRP test)
Examples found in repository?
More examples
src/nt_funcs.rs (line 395)
383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497
pub(crate) fn factorize128_advanced(cofactors: &[(u128, usize)]) -> Vec<(u128, usize)> {
let (mut todo128, mut todo64) = (Vec::new(), Vec::new()); // cofactors to be processed
let mut factored: Vec<(u128, usize)> = Vec::new(); // prime factor, exponent
for &(co, e) in cofactors.iter() {
if let Ok(co64) = u64::try_from(co) {
todo64.push((co64, e));
} else {
todo128.push((co, e));
};
}
while let Some((target, exp)) = todo128.pop() {
if is_prime(&SmallMint::from(target), Some(PrimalityTestConfig::bpsw())).probably() {
factored.push((target, exp));
continue;
}
// check perfect powers before other methods
// it suffices to check 2, 3, 5, 7 power if big-table is enabled, since tenth power of
// the smallest prime that haven't been checked is 8167^10 > 2^128
if let Some(d) = target.sqrt_exact() {
if let Ok(d64) = u64::try_from(d) {
todo64.push((d64, exp * 2));
} else {
todo128.push((d, exp * 2));
}
continue;
}
if let Some(d) = target.cbrt_exact() {
if let Ok(d64) = u64::try_from(d) {
todo64.push((d64, exp * 3));
} else {
todo128.push((d, exp * 3));
}
continue;
}
// TODO: check 5-th, 7-th power
// try to find a divisor
let mut i = 0usize;
let mut max_iter_ratio = 1;
let divisor = loop {
// try various factorization method iteratively, sort by time per iteration
const NMETHODS: usize = 3;
match i % NMETHODS {
0 => {
// Pollard's rho
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,
) {
break p.value();
}
}
1 => {
// Hart's one-line
let mul_target = target.checked_mul(480).unwrap_or(target);
let max_iter = max_iter_ratio << (mul_target.bits() / 6); // unoptimized heuristic
if let (Some(p), _) = one_line(&target, mul_target, max_iter) {
break p;
}
}
2 => {
// Shanks's squfof, try all mutipliers
let mut d = None;
for &k in SQUFOF_MULTIPLIERS.iter() {
if let Some(mul_target) = target.checked_mul(k as u128) {
let max_iter = max_iter_ratio * 2 * mul_target.sqrt().sqrt() as usize;
if let (Some(p), _) = squfof(&target, mul_target, max_iter) {
d = Some(p);
break;
}
}
}
if let Some(p) = d {
break p;
}
}
_ => unreachable!(),
}
i += 1;
// increase max iterations after trying all methods
if i % NMETHODS == 0 {
max_iter_ratio *= 2;
}
};
if let Ok(d64) = u64::try_from(divisor) {
todo64.push((d64, exp));
} else {
todo128.push((divisor, exp));
}
let co = target / divisor;
if let Ok(d64) = u64::try_from(co) {
todo64.push((d64, exp));
} else {
todo128.push((co, exp));
}
}
// forward 64 bit cofactors
factored.extend(
factorize64_advanced(&todo64)
.into_iter()
.map(|(p, exp)| (p as u128, exp)),
);
factored
}
Trait Implementations§
source§impl Clone for PrimalityTestConfig
impl Clone for PrimalityTestConfig
source§fn clone(&self) -> PrimalityTestConfig
fn clone(&self) -> PrimalityTestConfig
Returns a copy of the value. Read more
1.0.0 · source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
Performs copy-assignment from
source
. Read moresource§impl Debug for PrimalityTestConfig
impl Debug for PrimalityTestConfig
source§impl Default for PrimalityTestConfig
impl Default for PrimalityTestConfig
impl Copy for PrimalityTestConfig
Auto Trait Implementations§
impl RefUnwindSafe for PrimalityTestConfig
impl Send for PrimalityTestConfig
impl Sync for PrimalityTestConfig
impl Unpin for PrimalityTestConfig
impl UnwindSafe for PrimalityTestConfig
Blanket Implementations§
§impl<T> Conv for T
impl<T> Conv for T
§impl<T> FmtForward for T
impl<T> FmtForward for T
§fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
§fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
§fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
§fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
§fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
§fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
§fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
§fn fmt_list(self) -> FmtList<Self>where
&'a Self: for<'a> IntoIterator,
fn fmt_list(self) -> FmtList<Self>where
&'a Self: for<'a> IntoIterator,
Formats each item in a sequence. Read more
§impl<T> Pipe for Twhere
T: ?Sized,
impl<T> Pipe for Twhere
T: ?Sized,
§fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
Pipes by value. This is generally the method you want to use. Read more
§fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
Borrows
self
and passes that borrow into the pipe function. Read more§fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
Mutably borrows
self
and passes that borrow into the pipe function. Read more§fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> Rwhere
Self: Borrow<B>,
B: 'a + ?Sized,
R: 'a,
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> Rwhere
Self: Borrow<B>,
B: 'a + ?Sized,
R: 'a,
§fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R
) -> Rwhere
Self: BorrowMut<B>,
B: 'a + ?Sized,
R: 'a,
fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R
) -> Rwhere
Self: BorrowMut<B>,
B: 'a + ?Sized,
R: 'a,
§fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> Rwhere
Self: AsRef<U>,
U: 'a + ?Sized,
R: 'a,
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> Rwhere
Self: AsRef<U>,
U: 'a + ?Sized,
R: 'a,
Borrows
self
, then passes self.as_ref()
into the pipe function.§fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> Rwhere
Self: AsMut<U>,
U: 'a + ?Sized,
R: 'a,
fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> Rwhere
Self: AsMut<U>,
U: 'a + ?Sized,
R: 'a,
Mutably borrows
self
, then passes self.as_mut()
into the pipe
function.§impl<T> Tap for T
impl<T> Tap for T
§fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Selfwhere
Self: Borrow<B>,
B: ?Sized,
fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Selfwhere
Self: Borrow<B>,
B: ?Sized,
Immutable access to the
Borrow<B>
of a value. Read more§fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Selfwhere
Self: BorrowMut<B>,
B: ?Sized,
fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Selfwhere
Self: BorrowMut<B>,
B: ?Sized,
Mutable access to the
BorrowMut<B>
of a value. Read more§fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Selfwhere
Self: AsRef<R>,
R: ?Sized,
fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Selfwhere
Self: AsRef<R>,
R: ?Sized,
Immutable access to the
AsRef<R>
view of a value. Read more§fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Selfwhere
Self: AsMut<R>,
R: ?Sized,
fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Selfwhere
Self: AsMut<R>,
R: ?Sized,
Mutable access to the
AsMut<R>
view of a value. Read more§fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Selfwhere
Self: Deref<Target = T>,
T: ?Sized,
fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Selfwhere
Self: Deref<Target = T>,
T: ?Sized,
Immutable access to the
Deref::Target
of a value. Read more§fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Selfwhere
Self: DerefMut<Target = T> + Deref,
T: ?Sized,
fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Selfwhere
Self: DerefMut<Target = T> + Deref,
T: ?Sized,
Mutable access to the
Deref::Target
of a value. Read more§fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
Calls
.tap()
only in debug builds, and is erased in release builds.§fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
Calls
.tap_mut()
only in debug builds, and is erased in release
builds.§fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Selfwhere
Self: Borrow<B>,
B: ?Sized,
fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Selfwhere
Self: Borrow<B>,
B: ?Sized,
Calls
.tap_borrow()
only in debug builds, and is erased in release
builds.§fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Selfwhere
Self: BorrowMut<B>,
B: ?Sized,
fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Selfwhere
Self: BorrowMut<B>,
B: ?Sized,
Calls
.tap_borrow_mut()
only in debug builds, and is erased in release
builds.§fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Selfwhere
Self: AsRef<R>,
R: ?Sized,
fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Selfwhere
Self: AsRef<R>,
R: ?Sized,
Calls
.tap_ref()
only in debug builds, and is erased in release
builds.§fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Selfwhere
Self: AsMut<R>,
R: ?Sized,
fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Selfwhere
Self: AsMut<R>,
R: ?Sized,
Calls
.tap_ref_mut()
only in debug builds, and is erased in release
builds.