facto-rs icon indicating copy to clipboard operation
facto-rs copied to clipboard

Working prototype

FactoRS

FactoRS crate that provides different methods of factorization. Rug is used to handle big integer operations.
Some algorithms such as [Dixon] and [QuadraticSieve] have a linear algebra step. For these algorithms nalgebra is used to handle the operations.

How to use

The crate provides the following structs: TrialDivision, Fermat, Dixon, QuadraticSieve. Each one implements the Factorizer trait:

pub trait Factorizer {
    /// Return 2 factors of a number
    fn factor(&self) -> Option<(Integer, Integer)>;
}

To factor a number you must pass the number into the constructor (new::(n: Integer, ...)) alongside extra configurations.

For QuadraticSieve and Dixon I provided 2 builder classes QuadraticSieveBuilder and DixonBuilder that should help with the configuration of the algorithm.

Examples

Factorization using Fermat's algorithm

// Using the function
let n = Integer::from_str_radix("5959", 10).unwrap();
let res = fermat(&n);
assert_eq!(res, Some((Integer::from(59u32), Integer::from(101u32))));
// Using the struct
let f = Fermat::new(n.clone());
let res = f.factor();
assert_eq!(res, Some((Integer::from(59u32), Integer::from(101u32))));

Factorization using Quadratic sieve algorithm

let p = Integer::from_str_radix("3507360361", 10).unwrap();
let q = Integer::from_str_radix("3916272539", 10).unwrap();
let n = p.clone() * &q; // 13735779066161426579

let qs_builder = QuadraticSieveBuilder::new(n);
let qs = qs_builder.build();
let res = qs.factor();
assert_eq!(res, Some((p, q)));

An example using the builder API:

let n = Integer::from(15347u32);
let builder = QuadraticSieveBuilder::new(n)
    .bound(30)
    .factor_base(vec![2, 17, 23, 29])
    .extra_relations(1)
    .sieve_size(1000);
let qs: QuadraticSieve = builder.build();
let res = qs.factor();
assert_eq!(res, Some((Integer::from(103u32), Integer::from(149u32))));

The builders provide defaults. They are computed when we call the .build() method.
For example here we set only the bound parameter:

let n = Integer::from(15347u32);
let builder = QuadraticSieveBuilder::new(n)
    .bound(30);
let qs: QuadraticSieve = builder.build();
let res = qs.factor();
assert_eq!(res, Some((Integer::from(103u32), Integer::from(149u32))));

For more examples check out the examples directory.

Remarks

For bigger numbers (> 50 bits) use --release mode. Gaussian elimination takes too long for a reason unknown to me yet.