Skip to content

Commit

Permalink
Pollard rho algorithm now passes a measly few tests
Browse files Browse the repository at this point in the history
  • Loading branch information
leto committed Jul 1, 2009
1 parent 46f6e77 commit c1c294b
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 36 deletions.
58 changes: 30 additions & 28 deletions lib/Math/Factoring.pm
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use base 'Exporter';
use constant GMP => 'Math::GMPz';
our @EXPORT_OK = qw/factor/;
our @EXPORT = qw//;
use Data::Dumper;

=head1 NAME
Expand All @@ -21,47 +22,26 @@ Version 0.01

our $VERSION = '0.01';

sub factor($)
{
my $n = GMP->new($_[0]);
my @factors;
if ($n >= 0 and $n <= 3) {
push @factors, "$n"; # won't work without stringification ???
} else {
my ($a,$x0) = (-1,3);
my $t;
while( !is_prime($n) ) {
$t = _factor_pollard_rho($n,$a,$x0);

last if $t == 0;

push @factors, "$n";
$n /= $t;
}
push @factors, "$n";
}

return @factors;
}
sub _random()
{
my $n = GMP->new(int rand(1e9) );
my $n = GMP->new(int rand(1e15) );
my $state = rand_init($n);
my $rand = GMP->new;
Rmpz_urandomm($rand, $state, $n);
Rmpz_urandomm($rand, $state, $n,1);
return $rand;
}

sub _factor_pollard_rho($$$)
{
my ($n,$a,$y0) = @_;
my ($n,$a,$x0) = @_;
my ($x,$y,$q,$d) = map { GMP->new } ( 1 .. 4 );
my ($i,$j,$x0) = (1,1);
my ($i,$j) = (1,1);
$q = 1; $x = $x0; $y = $x0;

do {
$x = ($x*$x + $a ) % $n;
$y = ($y*$y + $a ) % $n;
$y = ($y*$y + $a ) % $n;
$q *= ($x - $y);
$q %= $n;

Expand All @@ -72,19 +52,41 @@ sub _factor_pollard_rho($$$)
Rmpz_gcd($d, $q, $n);
if ($d != 1) {
if (!is_prime($d)) {
return _factor_pollar_rho( $d,
no warnings 'prototype';
return _factor_pollard_rho( $d,
(_random() & 32) - 16,
_random() & 31 );
} else {
return $d;
}
}
}

return 0;
} while (1);

}

sub factor($)
{
my $n = GMP->new($_[0]);
my @factors;
if ($n >= 0 and $n <= 3) {
return "$n";
} else {
my ($a,$x0) = (-1,3);
my $t;
while( !is_prime($n) ) {
$t = _factor_pollard_rho($n,$a,$x0);
warn "found t=$t";
last if $t == 0;
push @factors, "$t";
$n /= $t;
}
push @factors, "$n";
}

return sort { $a <=> $b } @factors;
}
=head1 SYNOPSIS
use Math::Factoring;
Expand Down
18 changes: 10 additions & 8 deletions t/01-basic.t
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,21 @@

use Test::More tests => 7;
use Math::Factoring qw/factor/;
use Data::Dumper;

local $TODO = "implement factor()";

my $factor_data = [
[ 0 => [ 0 ] ],
[ 1 => [ 1 ] ],
[ 4 => [ 2, 2 ] ],
[ 6 => [ 2, 3 ] ],
[ 8 => [ 2, 4 ] ],
[ 9 => [ 3, 3 ] ],
[ 10 => [ 2, 5 ] ],
# n factors (from smallest to largest)
[ 0 => [ 0 ] ],
[ 1 => [ 1 ] ],
[ 4 => [ 2, 2 ] ],
[ 6 => [ 2, 3 ] ],
[ 8 => [ 2, 4 ] ],
[ 9 => [ 3, 3 ] ],
[ 10 => [ 2, 5 ] ],
];

local $TODO = "implement factor()";
for my $f (@$factor_data) {
my ($num,$factors) = @$f;
is_deeply( [factor($num)], $factors,
Expand Down

0 comments on commit c1c294b

Please sign in to comment.