Skip to content

Commit

Permalink
- Added the RangeNum lcm, lcm_by{...}, gcd and gcd_by{...} me…
Browse files Browse the repository at this point in the history
…thods.
  • Loading branch information
trizen committed Aug 31, 2019
1 parent 3d5cdf0 commit 845e61c
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 41 deletions.
36 changes: 11 additions & 25 deletions lib/Sidef/Types/Array/Array.pm
Original file line number Diff line number Diff line change
Expand Up @@ -965,7 +965,7 @@ package Sidef::Types::Array::Array {
$self->reduce_operator('+', $initial);
}

sub _sum_prod_by {
sub _reduce_by {
my ($self, $method, $result, $callback) = @_;

my @list;
Expand All @@ -990,14 +990,14 @@ package Sidef::Types::Array::Array {
sub sum_by {
my ($self, $block) = @_;
$block //= Sidef::Types::Block::Block::IDENTITY;
$self->_sum_prod_by('sum', Sidef::Types::Number::Number::ZERO, sub { $block->run($_[1]) });
$self->_reduce_by('sum', Sidef::Types::Number::Number::ZERO, sub { $block->run($_[1]) });
}

sub sum_kv {
my ($self, $block) = @_;
$self->_sum_prod_by('sum',
Sidef::Types::Number::Number::ZERO,
sub { $block->run(Sidef::Types::Number::Number->_set_uint($_[0]), $_[1]) });
$self->_reduce_by('sum',
Sidef::Types::Number::Number::ZERO,
sub { $block->run(Sidef::Types::Number::Number->_set_uint($_[0]), $_[1]) });
}

sub sum_2d {
Expand Down Expand Up @@ -1038,14 +1038,14 @@ package Sidef::Types::Array::Array {
sub prod_by {
my ($self, $block) = @_;
$block //= Sidef::Types::Block::Block::IDENTITY;
$self->_sum_prod_by('prod', Sidef::Types::Number::Number::ONE, sub { $block->run($_[1]) });
$self->_reduce_by('prod', Sidef::Types::Number::Number::ONE, sub { $block->run($_[1]) });
}

sub prod_kv {
my ($self, $block) = @_;
$self->_sum_prod_by('prod',
Sidef::Types::Number::Number::ONE,
sub { $block->run(Sidef::Types::Number::Number->_set_uint($_[0]), $_[1]) });
$self->_reduce_by('prod',
Sidef::Types::Number::Number::ONE,
sub { $block->run(Sidef::Types::Number::Number->_set_uint($_[0]), $_[1]) });
}

sub prod {
Expand All @@ -1060,15 +1060,8 @@ package Sidef::Types::Array::Array {

sub gcd_by {
my ($self, $block) = @_;

$block //= Sidef::Types::Block::Block::IDENTITY;

my @list;
foreach my $n (@$self) {
push @list, $block->run($n);
}

Sidef::Types::Number::Number::gcd(@list);
$self->_reduce_by('gcd', Sidef::Types::Number::Number::ZERO, sub { $block->run($_[1]) });
}

sub gcd {
Expand All @@ -1083,15 +1076,8 @@ package Sidef::Types::Array::Array {

sub lcm_by {
my ($self, $block) = @_;

$block //= Sidef::Types::Block::Block::IDENTITY;

my @list;
foreach my $n (@$self) {
push @list, $block->run($n);
}

Sidef::Types::Number::Number::lcm(@list);
$self->_reduce_by('lcm', Sidef::Types::Number::Number::ONE, sub { $block->run($_[1]) });
}

sub lcm {
Expand Down
10 changes: 7 additions & 3 deletions lib/Sidef/Types/Number/Number.pm
Original file line number Diff line number Diff line change
Expand Up @@ -8881,7 +8881,7 @@ package Sidef::Types::Number::Number {
my (@vals) = @_;
_valid(\(@vals));

@vals || return ZERO;
@vals || return ZERO; # By convention, gcd of an empty set is 0.
@vals == 1 and return $vals[0];

my $r = Math::GMPz::Rmpz_init();
Expand Down Expand Up @@ -8936,7 +8936,7 @@ package Sidef::Types::Number::Number {
my (@vals) = @_;
_valid(\(@vals));

@vals or return ZERO;
@vals or return ONE; # By convention, lcm of an empty set is 1.
@vals == 1 and return $vals[0];

if (@vals > 2) {
Expand Down Expand Up @@ -9252,6 +9252,8 @@ package Sidef::Types::Number::Number {
: Sidef::Types::Bool::Bool::FALSE;
}

*is_pseudoprime = \&is_fermat_pseudoprime;

sub is_euler_pseudoprime {
my ($n, @bases) = @_;
_valid(\(@bases));
Expand All @@ -9267,7 +9269,7 @@ package Sidef::Types::Number::Number {
: Sidef::Types::Bool::Bool::FALSE;
}

sub is_strong_pseudoprime {
sub is_strong_fermat_pseudoprime {
my ($n, @bases) = @_;
_valid(\(@bases));
__is_int__($$n)
Expand All @@ -9282,6 +9284,8 @@ package Sidef::Types::Number::Number {
: Sidef::Types::Bool::Bool::FALSE;
}

*is_strong_pseudoprime = \&is_strong_fermat_pseudoprime;

sub is_fibonacci_pseudoprime {
my ($n) = @_;

Expand Down
20 changes: 12 additions & 8 deletions lib/Sidef/Types/Number/Number.pod
Original file line number Diff line number Diff line change
Expand Up @@ -2048,14 +2048,6 @@ Return the

=cut

=head2 is_fermat_pseudoprime

Number.is_fermat_pseudoprime() -> I<Obj>

Return the

=cut

=head2 is_fibonacci_pseudoprime

Number.is_fibonacci_pseudoprime() -> I<Obj>
Expand Down Expand Up @@ -2316,6 +2308,16 @@ Aliases: I<is_provable_prime>

=cut

=head2 is_pseudoprime

Number.is_pseudoprime() -> I<Obj>

Return the

Aliases: I<is_fermat_pseudoprime>

=cut

=head2 isqrt

Number.isqrt() -> I<Obj>
Expand Down Expand Up @@ -2424,6 +2426,8 @@ Number.is_strong_pseudoprime() -> I<Obj>

Return the

Aliases: I<is_strong_fermat_pseudoprime>

=cut

=head2 is_totient
Expand Down
45 changes: 41 additions & 4 deletions lib/Sidef/Types/Range/RangeNumber.pm
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ package Sidef::Types::Range::RangeNumber {
);
}

sub _sum_prod_by {
sub _reduce_by {
my ($self, $method, $result, $callback) = @_;

my @list;
Expand All @@ -139,7 +139,7 @@ package Sidef::Types::Range::RangeNumber {
sub sum_by {
my ($self, $block) = @_;
$block //= Sidef::Types::Block::Block::IDENTITY;
$self->_sum_prod_by('sum', Sidef::Types::Number::Number::ZERO, sub { $block->run($_[0]) });
$self->_reduce_by('sum', Sidef::Types::Number::Number::ZERO, sub { $block->run($_[0]) });
}

sub sum {
Expand Down Expand Up @@ -184,7 +184,7 @@ package Sidef::Types::Range::RangeNumber {
sub prod_by {
my ($self, $block) = @_;
$block //= Sidef::Types::Block::Block::IDENTITY;
$self->_sum_prod_by('prod', Sidef::Types::Number::Number::ONE, sub { $block->run($_[0]) });
$self->_reduce_by('prod', Sidef::Types::Number::Number::ONE, sub { $block->run($_[0]) });
}

sub prod {
Expand All @@ -197,13 +197,50 @@ package Sidef::Types::Range::RangeNumber {
if ( $self->{step}->is_one
and $self->{from}->is_one
and $self->{to}->is_pos) {
$self->{_asc} //= 1;
return $self->{to}->factorial;
}

Sidef::Types::Number::Number::prod($self->to_list);
}

sub lcm_by {
my ($self, $block) = @_;
$block //= Sidef::Types::Block::Block::IDENTITY;
$self->_reduce_by('lcm', Sidef::Types::Number::Number::ONE, sub { $block->run($_[0]) });
}

sub lcm {
my ($self, $arg) = @_;

if (defined($arg)) {
goto &lcm_by;
}

if ( $self->{step}->is_one
and $self->{from}->is_one
and $self->{to}->is_pos) {
return $self->{to}->consecutive_lcm;
}

Sidef::Types::Number::Number::lcm($self->to_list);
}

sub gcd_by {
my ($self, $block) = @_;
$block //= Sidef::Types::Block::Block::IDENTITY;
$self->_reduce_by('gcd', Sidef::Types::Number::Number::ZERO, sub { $block->run($_[0]) });
}

sub gcd {
my ($self, $arg) = @_;

if (defined($arg)) {
goto &gcd_by;
}

Sidef::Types::Number::Number::gcd($self->to_list);
}

sub bsearch {
my ($self, $block) = @_;

Expand Down
32 changes: 32 additions & 0 deletions lib/Sidef/Types/Range/RangeNumber.pod
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,22 @@ Return the

=cut

=head2 gcd

RangeNumber.gcd() -> I<Obj>

Return the

=cut

=head2 gcd_by

RangeNumber.gcd_by() -> I<Obj>

Return the

=cut

=head2 iter

RangeNumber.iter() -> I<Obj>
Expand All @@ -71,6 +87,22 @@ Return the

=cut

=head2 lcm

RangeNumber.lcm() -> I<Obj>

Return the

=cut

=head2 lcm_by

RangeNumber.lcm_by() -> I<Obj>

Return the

=cut

=head2 new

RangeNumber.new() -> I<Obj>
Expand Down
33 changes: 32 additions & 1 deletion scripts/Tests/sum_and_prod.sf
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,45 @@ do {
assert_eq(arr, ["12", "42"])
}

# gcd/lcm
# Array gcd/lcm
do {
var arr = ["48", "120", "42"]

assert_eq(arr.lcm, lcm(42, 48, 120))
assert_eq(arr.gcd, gcd(42, 48, 120))

assert_eq(arr.lcm { _ }, lcm(42, 48, 120))
assert_eq(arr.lcm { .to_i**2 }, lcm(42**2, 48**2, 120**2))

assert_eq(arr.gcd { _ }, gcd(42, 48, 120))
assert_eq(arr.gcd { .to_i**2 }, gcd(42**2, 48**2, 120**2))

assert_eq(arr, ["48", "120", "42"])
}

# Range gcd/lcm
do {

assert_eq(lcm(1..10), lcm(@|1..10))
assert_eq(lcm(200..250), lcm(@|200..250))

assert_eq(lcm(20..10), 1)
assert_eq(gcd(20..10), 0)

assert_eq(lcm(1..-10), 1)
assert_eq(gcd(1..-10), 0)

assert_eq(20..10 -> lcm { _ }, 1)
assert_eq(20..10 -> gcd { _ }, 0)

assert_eq(1..10 -> lcm { _ }, lcm(1..10))
assert_eq(200..250 -> lcm { _+1 }, lcm(201..251))

assert_eq(gcd(42..60 `by` 2), 2)
assert_eq(gcd(42..60 `by` 3), 3)

assert_eq(4..10 -> gcd { _! }, 24)
assert_eq(4..10 -> flip.gcd { _! }, 24)
}

say "** Test passed!"

0 comments on commit 845e61c

Please sign in to comment.