Skip to content

Commit

Permalink
- Added the Number flt_factor(n, tries=1e4) method.
Browse files Browse the repository at this point in the history
Tries to find a factor of `n`, using a new factorization method, inspired by Fermat's Little Theorem (FLT).

The method is particularily effective for numbers that have factors closed to each other, or have a factor `k` for which `znorder(2,k)` is small.

Example:

	say flt_factor(1759590140239532167230871849749630652332178307219845847129)	#=> [12072684186515582507, 145749703467343411357142937615495959947]
	say flt_factor(28168370236334094367936640078057043313881469151722840306493)	#=> [30426633744568826749, 925780041026134419587821276142742168257]

...taking 0.007s in total.
  • Loading branch information
trizen committed Jan 7, 2021
1 parent 17a7333 commit d52bb1f
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 0 deletions.
50 changes: 50 additions & 0 deletions lib/Sidef/Types/Number/Number.pm
Original file line number Diff line number Diff line change
Expand Up @@ -12975,6 +12975,56 @@ package Sidef::Types::Number::Number {
Sidef::Types::Array::Array->new([bless(\$n)]);
}

# "Fermat's Little Theorem" factorization method
sub flt_factor {
my ($n, $k) = @_;
_valid(\$k) if defined($k);

$n = _any2mpz($$n) // return Sidef::Types::Array::Array->new();

if (defined($k)) {
$k = _any2ui($$k) // 1e4;
}
else {
$k = 1e4;
}

state $z = Math::GMPz::Rmpz_init_nobless();
state $t = Math::GMPz::Rmpz_init_nobless();

Math::GMPz::Rmpz_powm($z, $TWO, $n, $n);

# Cannot factor Fermat pseudoprimes
if (Math::GMPz::Rmpz_cmp_ui($z, 2) == 0) {
return Sidef::Types::Array::Array->new([bless \$n]);
}

for (my $j = 1 ; $j <= $k ; $j += 2) {

Math::GMPz::Rmpz_powm_ui($t, $TWO, $j, $n);
Math::GMPz::Rmpz_sub($t, $z, $t);
Math::GMPz::Rmpz_gcd($t, $t, $n);

if (Math::GMPz::Rmpz_cmp_ui($t, 1) > 0) {

if (Math::GMPz::Rmpz_cmp($t, $n) == 0) {
return Sidef::Types::Array::Array->new([bless \$n]);
}

my $x = Math::GMPz::Rmpz_init();
my $y = Math::GMPz::Rmpz_init();

Math::GMPz::Rmpz_set($y, $t);
Math::GMPz::Rmpz_divexact($x, $n, $t);

my @f = map { bless \$_ } sort { Math::GMPz::Rmpz_cmp($a, $b) } ($x, $y);
return Sidef::Types::Array::Array->new(\@f);
}
}

Sidef::Types::Array::Array->new([bless(\$n)]);
}

sub squfof_factor {
my ($n, $k) = @_;
_valid(\$k) if defined($k);
Expand Down
8 changes: 8 additions & 0 deletions lib/Sidef/Types/Number/Number.pod
Original file line number Diff line number Diff line change
Expand Up @@ -1902,6 +1902,14 @@ Return the

=cut

=head2 flt_factor

Number.flt_factor() -> I<Obj>

Return the

=cut

=head2 gcd

Number.gcd() -> I<Obj>
Expand Down

0 comments on commit d52bb1f

Please sign in to comment.