Skip to content

Commit

Permalink
- Added the Number gcd_factors(n, [a,b,c,...]) method.
Browse files Browse the repository at this point in the history
Given a positive integer and an array of integers, it tries to find non-trivial factors of
n, checking each `gcd(n, array[0])`, `gcd(n, array[1])`, etc.

    var n = 43*43*97*503
    var a = [19*43*97, 1, 13*41*43*101]
    gcd_factors(n, a) #=> [43, 43, 97, 503]

The product of the factors gives back C<n>. However, some factors may be composite.
  • Loading branch information
trizen committed Jul 1, 2022
1 parent 57845ba commit ef7938a
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 34 deletions.
32 changes: 1 addition & 31 deletions lib/Sidef/Math/Math.pm
Original file line number Diff line number Diff line change
Expand Up @@ -170,37 +170,7 @@ package Sidef::Math::Math {

sub gcd_factors {
my ($self, $n, $arr) = @_;

$n->is_pos
|| return Sidef::Types::Array::Array->new;

my $orig_n = $n;

my @factors;
my $G = Sidef::Types::Array::Array->new([grep { $_->is_ntf($n) } map { $n->gcd($_) } @$arr])->sort->uniq;

foreach my $g (@$G) {

my $new_g = $g;

if ($new_g->divides($n)) {
## ok
}
else {
$new_g = $n->gcd($g);
$new_g->is_ntf($n) || next;
}

my $v = $n->valuation($new_g);
$n = $n->remove($new_g);
push @factors, ($new_g) x CORE::int($v);
}

if (!$n->is_one) {
push @factors, $n;
}

Sidef::Types::Array::Array->new(\@factors)->sort;
Sidef::Types::Number::Number::gcd_factors($n, $arr);
}

sub smooth_numbers {
Expand Down
4 changes: 2 additions & 2 deletions lib/Sidef/Math/Math.pod
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,9 @@ Returns the greatest common divisor (GCD) of a list of integers.

=head2 gcd_factors

Math.gcd_factors(n, array)
Math.gcd_factors(n, [a, b, ...])

Given a positive integer and a list of numbers, it tries to find non-trivial factors of n, checking each C<gcd(n, array[0])>, C<gcd(n, array[1])>, etc.
Given a positive integer and an array of integers, it tries to find non-trivial factors of n, checking each C<gcd(n, array[0])>, C<gcd(n, array[1])>, etc.

var n = 43*43*97*503
var a = [19*43*97, 1, 13*41*43*101]
Expand Down
51 changes: 50 additions & 1 deletion lib/Sidef/Types/Number/Number.pm
Original file line number Diff line number Diff line change
Expand Up @@ -16266,6 +16266,55 @@ package Sidef::Types::Number::Number {
_set_int($f[-1]);
}

sub gcd_factors {
my ($n, $arr) = @_;

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

Math::GMPz::Rmpz_sgn($n) > 0
or return Sidef::Types::Array::Array->new;

my $z = Math::GMPz::Rmpz_init_set($n); # copy
state $t = Math::GMPz::Rmpz_init_nobless();

my @gcds;
my %seen;

foreach my $k (@$arr) {
_valid(\$k);
my $m = _any2mpz($$k) // next;
Math::GMPz::Rmpz_gcd($t, $z, $m);
Math::GMPz::Rmpz_cmp_ui($t, 1) > 0 or next;
Math::GMPz::Rmpz_cmp($t, $z) < 0 or next;
if (!$seen{Math::GMPz::Rmpz_get_str($t, 10)}++) {
push @gcds, Math::GMPz::Rmpz_init_set($t);
}
}

@gcds = sort { Math::GMPz::Rmpz_cmp($a, $b) } @gcds;

my @factors;

foreach my $g (@gcds) {

Math::GMPz::Rmpz_gcd($t, $g, $z);
Math::GMPz::Rmpz_cmp_ui($t, 1) > 0 or next;
Math::GMPz::Rmpz_cmp($t, $z) < 0 or next;

my $v = Math::GMPz::Rmpz_remove($z, $z, $t);
push(@factors, (Math::GMPz::Rmpz_init_set($t)) x $v);
}

if (Math::GMPz::Rmpz_cmp_ui($z, 1) > 0) {
push @factors, $z;
}

@factors = sort { Math::GMPz::Rmpz_cmp($a, $b) } @factors;
@factors = map { bless \$_ } @factors;

Sidef::Types::Array::Array->new(\@factors);
}

sub factor {
my ($n, $block) = @_;

Expand All @@ -16282,7 +16331,7 @@ package Sidef::Types::Number::Number {
}
)
)->uniq;
return Sidef::Math::Math->gcd_factors($n, $f);
return $n->gcd_factors($f);
}

$n = _big2pistr($n) // return Sidef::Types::Array::Array->new();
Expand Down
14 changes: 14 additions & 0 deletions lib/Sidef/Types/Number/Number.pod
Original file line number Diff line number Diff line change
Expand Up @@ -2751,6 +2751,20 @@ The value of C<d> is always non-negative.

=cut

=head2 gcd_factors

gcd_factors(n, [a, b, ...])

Given a positive integer and an array of integers, it tries to find non-trivial factors of n, checking each C<gcd(n, array[0])>, C<gcd(n, array[1])>, etc.

var n = 43*43*97*503
var a = [19*43*97, 1, 13*41*43*101]
say gcd_factors(n, a) #=> [43, 43, 97, 503]

The product of the factors gives back C<n>. However, some factors may be composite.

=cut

=head2 gcud

gcud(...)
Expand Down

0 comments on commit ef7938a

Please sign in to comment.