Skip to content

Commit

Permalink
- Added the Number Num!USE_FACTORDB class variable (disabled by def…
Browse files Browse the repository at this point in the history
…ault).

When set to `true`, it will use factordb.com for factoring large integers.

Example:

	local Num!USE_FACTORDB = true
	local Num!VERBOSE = true

	say factor(43**97 + 1)

Output:

Looking for special factors: 279537573644609324609042104488898292179227641428833250707338521965848560587594478267049297188913790105014252135597060227656392076730684760843507116797578121644
Recursively factoring: 383960572410536595776063541827409905215247470510012696415691036963446563403266708495873816280688363840075142584625595952461796016693661410799
FactorDB: factoring 383960572410536595776063541827409905215247470510012696415691036963446563403266708495873816280688363840075142584625595952461796016693661410799
FactorDB: successful factorization.
[2, 2, 11, 47143, 350981049593, 3245397572372494387092668895749, 13880602646142985759764836199055032337616468929, 8523351548729334004564485798482488516034506243457731885729213219]
  • Loading branch information
trizen committed Feb 6, 2023
1 parent 3da4988 commit d5e1528
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 1 deletion.
66 changes: 65 additions & 1 deletion lib/Sidef/Types/Number/Number.pm
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@ package Sidef::Types::Number::Number {
use List::Util qw();
use Math::Prime::Util::GMP qw();

our ($ROUND, $PREC, $USE_PRIMECOUNT, $USE_YAFU, $VERBOSE, $SPECIAL_FACTORS);
our ($ROUND, $PREC, $USE_PRIMECOUNT, $USE_YAFU, $USE_FACTORDB, $VERBOSE, $SPECIAL_FACTORS);

BEGIN {
$ROUND = Math::MPFR::MPFR_RNDN(); # rounding mode for floating-point numbers
$PREC = 192; # precision in bits for floating-point numbers
$USE_PRIMECOUNT = 0; # true to use Kim Walisch's primecount for large n
$USE_YAFU = 0; # true to use YAFU for factoring large integers
$USE_FACTORDB = 0; # true to use factordb.com for factoring large integers
$VERBOSE = 0; # true to enable verbose/debug mode
$SPECIAL_FACTORS = 1; # true to check for special factors in `_factor(n)`
}
Expand Down Expand Up @@ -49,6 +50,7 @@ package Sidef::Types::Number::Number {
use constant {

YAFU_CUTOFF => 49, # in decimal digits
FACTORDB_CUTOFF => 65, # in decimal digits
SPECIAL_FACTORS_CUTOFF => 49, # in decimal digits (must be greater than SMALL_NUMBER_BITS)
SMALL_NUMBER_BITS => 110, # in bits (numbers that can be factorized fast)
MEDIUM_NUMBER_BITS => 150, # in bits (numbers that can be factorized moderately fast)
Expand Down Expand Up @@ -949,6 +951,67 @@ package Sidef::Types::Number::Number {
return (@factors, @special_factors);
}

if (length($n) >= FACTORDB_CUTOFF and $USE_FACTORDB) {

if (_is_prob_prime($n, \%is_prob_prime_cache)) {
return (@factors, $n);
}

say "FactorDB: factoring $n" if $VERBOSE;

require JSON;
require HTTP::Tiny;

my $url = "http://factordb.com/api?query=$n";
my $response = HTTP::Tiny->new->get($url);

if ($response->{success}) {
my $json = $response->{content};
my $data = eval { JSON::from_json($json) };

if (ref($data) eq 'HASH' and exists($data->{factors}) and ref($data->{factors}) eq 'ARRAY') {

my @factordb_factors;
my @factor_exp = @{$data->{factors}};

foreach my $pp (@factor_exp) {
my ($p, $e) = @$pp;

if (_is_prob_prime($p, \%is_prob_prime_cache)) {
push @factordb_factors, ($p) x $e;
}
else {
say "FactorDB: composite factor $p" if $VERBOSE;
local $USE_FACTORDB = 0;
my @arr = _factor($p);
foreach my $i (1 .. $e) {
push @factordb_factors, @arr;
}
}
}

my $factors_prod = Math::Prime::Util::GMP::vecprod(@factordb_factors);

if ($factors_prod ne $n and Math::Prime::Util::GMP::modint($n, $factors_prod) eq '0') {
say "FactorDB: recursively factoring the remainder." if $VERBOSE;
my $r = Math::Prime::Util::GMP::divint($n, $factors_prod);
local $USE_FACTORDB = 0;
push @factordb_factors, _factor($r);
$factors_prod = Math::Prime::Util::GMP::mulint($factors_prod, $r);
}

# The prime factors must multiply back to n
if ($factors_prod eq $n) {
say "FactorDB: successful factorization." if $VERBOSE;
@factordb_factors = map { $_->[0] }
sort { Math::GMPz::Rmpz_cmp($a->[1], $b->[1]) }
map { [$_, Math::GMPz::Rmpz_init_set_str($_, 10)] } @factordb_factors;
return (@factors, @factordb_factors);
}
}
}
}

if (length($n) >= YAFU_CUTOFF and $USE_YAFU) {

if (_is_prob_prime($n, \%is_prob_prime_cache)) {
Expand Down Expand Up @@ -1254,6 +1317,7 @@ package Sidef::Types::Number::Number {
my $r = Math::GMPz::Rmpz_init_set($n);

local $USE_YAFU = 0;
local $USE_FACTORDB = 0;
local $SPECIAL_FACTORS = 0;

my @factors = _factor(Math::GMPz::Rmpz_get_str($g, 10));
Expand Down
1 change: 1 addition & 0 deletions lib/Sidef/Types/Number/Number.pod
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ The following class-variables can be changed during runtime:
Num!ROUND = 0 # rounding mode for floating-point numbers
Num!VERBOSE = false # true to enable verbose/debug mode
Num!USE_YAFU = false # true to use YAFU for factoring large integers
Num!USE_FACTORDB = false # true to use factordb.com for factoring large integers
Num!USE_PRIMECOUNT = false # true to use Kim Walisch's primecount in prime_count(n)
Num!SPECIAL_FACTORS = true # true to try to find factors of special form in factor(n)

Expand Down

0 comments on commit d5e1528

Please sign in to comment.