-
Notifications
You must be signed in to change notification settings - Fork 34
/
fermat_factorization_method_2.pl
executable file
·68 lines (50 loc) · 1.35 KB
/
fermat_factorization_method_2.pl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#!/usr/bin/perl
# Daniel "Trizen" Șuteu
# Date: 13 September 2017
# https://github.com/trizen
# Fermat's factorization method.
# Theorem:
# If the absolute difference between the prime factors of a
# semiprime `n` is known, then `n` can be factored in polynomial time.
# Based on the following quadratic equation:
# x^2 + (a - b)*x - a*b = 0
#
# which has the solutions:
# x₁ = -a
# x₂ = +b
# See also:
# https://en.wikipedia.org/wiki/Fermat%27s_factorization_method
use 5.020;
use strict;
use warnings;
use experimental qw(signatures);
use ntheory qw(vecprod sqrtint is_prime is_square valuation);
sub fermat_factorization ($n) {
# Check for primes and negative numbers
return () if ($n <= 1);
return ($n) if is_prime($n);
# Check for divisibility by 2
if (!($n & 1)) {
my $v = valuation($n, 2);
return ((2) x $v, __SUB__->($n >> $v));
}
my $p = sqrtint($n);
my $q = $p * $p - $n;
until (is_square($q)) {
$q += 2 * $p++ + 1;
}
my $s = sqrtint($q);
my ($x1, $x2) = (
($p + $s),
($p - $s),
);
return sort { $a <=> $b } (
__SUB__->($x1),
__SUB__->($x2)
);
}
foreach my $n (160587846247027, 5040, 65127835124, 6469693230) {
my @f = fermat_factorization($n);
say join(' * ', @f), " = $n";
die 'error' if vecprod(@f) != $n;
}