mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-08-04 23:17:46 +00:00
factor::miller_rabin: Use a specialized basis for 32b integers
~3% faster
This commit is contained in:
parent
e68bb192f2
commit
a440807e6c
2 changed files with 25 additions and 8 deletions
|
@ -2,10 +2,27 @@
|
|||
|
||||
use crate::numeric::*;
|
||||
|
||||
// Small set of bases for the Miller-Rabin prime test, valid for all 64b integers;
|
||||
// discovered by Jim Sinclair on 2011-04-20, see miller-rabin.appspot.com
|
||||
#[allow(clippy::unreadable_literal)]
|
||||
const BASIS: [u64; 7] = [2, 325, 9375, 28178, 450775, 9780504, 1795265022];
|
||||
pub(crate) trait Basis {
|
||||
const BASIS: &'static [u64];
|
||||
}
|
||||
|
||||
impl Basis for Montgomery {
|
||||
// Small set of bases for the Miller-Rabin prime test, valid for all 64b integers;
|
||||
// discovered by Jim Sinclair on 2011-04-20, see miller-rabin.appspot.com
|
||||
#[allow(clippy::unreadable_literal)]
|
||||
const BASIS: &'static [u64] = &[2, 325, 9375, 28178, 450775, 9780504, 1795265022];
|
||||
}
|
||||
|
||||
impl Basis for Montgomery32 {
|
||||
// Small set of bases for the Miller-Rabin prime test, valid for all 32b integers;
|
||||
// discovered by Steve Worley on 2013-05-27, see miller-rabin.appspot.com
|
||||
#[allow(clippy::unreadable_literal)]
|
||||
const BASIS: &'static [u64] = &[
|
||||
4230279247111683200,
|
||||
14694767155120705706,
|
||||
16641139526367750375,
|
||||
];
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq)]
|
||||
pub(crate) enum Result {
|
||||
|
@ -23,7 +40,7 @@ impl Result {
|
|||
// Deterministic Miller-Rabin primality-checking algorithm, adapted to extract
|
||||
// (some) dividers; it will fail to factor strong pseudoprimes.
|
||||
#[allow(clippy::many_single_char_names)]
|
||||
pub(crate) fn test<A: Arithmetic>(m: A) -> Result {
|
||||
pub(crate) fn test<A: Arithmetic + Basis>(m: A) -> Result {
|
||||
use self::Result::*;
|
||||
|
||||
let n = m.modulus();
|
||||
|
@ -41,7 +58,7 @@ pub(crate) fn test<A: Arithmetic>(m: A) -> Result {
|
|||
let one = m.one();
|
||||
let minus_one = m.minus_one();
|
||||
|
||||
for _a in BASIS.iter() {
|
||||
for _a in A::BASIS.iter() {
|
||||
let _a = _a % n;
|
||||
if _a == 0 {
|
||||
break;
|
||||
|
|
|
@ -15,7 +15,7 @@ use crate::miller_rabin::Result::*;
|
|||
use crate::numeric::*;
|
||||
use crate::{miller_rabin, Factors};
|
||||
|
||||
fn find_divisor<A: Arithmetic>(n: A) -> u64 {
|
||||
fn find_divisor<A: Arithmetic + miller_rabin::Basis>(n: A) -> u64 {
|
||||
#![allow(clippy::many_single_char_names)]
|
||||
let mut rand = {
|
||||
let range = Uniform::new(1, n.modulus());
|
||||
|
@ -48,7 +48,7 @@ fn find_divisor<A: Arithmetic>(n: A) -> u64 {
|
|||
}
|
||||
}
|
||||
|
||||
fn _factor<A: Arithmetic>(num: u64) -> Factors {
|
||||
fn _factor<A: Arithmetic + miller_rabin::Basis>(num: u64) -> Factors {
|
||||
// Shadow the name, so the recursion automatically goes from “Big” arithmetic to small.
|
||||
let _factor = |n| {
|
||||
if n < (1 << 32) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue