Skip to content

Commit

Permalink
- Added the RangeNumber .each_squarefree_almost_prime(k, {...}) met…
Browse files Browse the repository at this point in the history
…hod.

Iterates over the squarefree k-almost primes in the self range a..b.

Example:

	# iterate over squarefree semiprimes in the range 1..100
	1..100 -> each_squarefree_almost_prime(2, { .say })

	# iterate over squarefree 3-almost primes in the range 50..100
	50..100 -> each_squarefree_almost_prime(3, { .say })

- Adjusted the stepping value when iterating over k-almost primes and squarefree k-almost primes for better performance.
  • Loading branch information
trizen committed Mar 9, 2021
1 parent 0a48608 commit 14cd46e
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 5 deletions.
42 changes: 37 additions & 5 deletions lib/Sidef/Types/Number/Number.pm
Original file line number Diff line number Diff line change
Expand Up @@ -994,7 +994,7 @@ package Sidef::Types::Number::Number {
$upto = $to;
}

## say ":: Sieving ($from, $upto) with step = $step";
#~ say ":: Sieving ($from, $upto) with step = $step";
@buffer = @{$buffer_callback->($from, $upto)};
$from = $upto + 1;
@buffer || next;
Expand Down Expand Up @@ -9933,6 +9933,18 @@ package Sidef::Types::Number::Number {
CORE::int($n * (CORE::log($n) + CORE::log(CORE::log($n)) - 1));
}

sub _nth_almost_prime_lower {
my ($n, $k) = @_;

my $factorial_km1 = 1;

for my $j (2 .. $k - 1) {
$factorial_km1 *= $j;
}

CORE::int(($n * CORE::log($n)) / ((CORE::log(CORE::log($n))**($k - 1)) / $factorial_km1));
}

sub _prime_count_range {
my ($x, $y) = @_;

Expand Down Expand Up @@ -15657,11 +15669,25 @@ package Sidef::Types::Number::Number {

$k = _any2ui($$k) // return ZERO;

if (Math::GMPz::Rmpz_sgn($from) <= 0) {
$from = $ONE;
if (Math::GMPz::Rmpz_cmp_ui($from, $k) <= 0 and $k > 0) {
$from = Math::GMPz::Rmpz_init_set_ui(0);
Math::GMPz::Rmpz_setbit($from, $k); # from = 2**k
}

_generic_each($from, $to, $block, sub { 5e6 }, sub { _sieve_almost_primes($_[0], $_[1], $k) });
#<<<
_generic_each($from, $to, $block, sub {
my ($from) = @_;

my $t = Math::GMPz::Rmpz_get_d($from);
my $step = ($k > 0) ? (_nth_almost_prime_lower($t + CORE::log($t) * 2e4, $k) - _nth_almost_prime_lower($t, $k)) : 0;

if ($step <= 0 or $step > 1e9) {
$step = 100_000_000 * $k;
}

$step;
}, sub { _sieve_almost_primes($_[0], $_[1], $k) });
#>>>
}

*each_almost_prime = \&almost_primes_each;
Expand Down Expand Up @@ -15722,7 +15748,13 @@ package Sidef::Types::Number::Number {
$from = $ONE;
}

_generic_each($from, $to, $block, sub { 1e7 }, sub { _sieve_almost_primes($_[0], $_[1], $k, squarefree => 1) });
my $step = ($k > 8) ? Math::Prime::Util::GMP::pn_primorial($k) : 1e7;

if ($step > ULONG_MAX) {
$step = Math::GMPz::Rmpz_init_set_str($step, 10);
}

_generic_each($from, $to, $block, sub { $step }, sub { _sieve_almost_primes($_[0], $_[1], $k, squarefree => 1) });
}

*each_squarefree_almost_prime = \&squarefree_almost_primes_each;
Expand Down
19 changes: 19 additions & 0 deletions lib/Sidef/Types/Range/RangeNumber.pm
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,25 @@ package Sidef::Types::Range::RangeNumber {
return $self;
}

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

$k = Sidef::Types::Number::Number->new($k);

if ($self->{step}->is_one) {

my $left = Sidef::Types::Number::Number->new($self->{from});
my $right = Sidef::Types::Number::Number->new($self->{to});

Sidef::Types::Number::Number::each_squarefree_almost_prime($k, $left, $right, $block);
return $self;
}

$self->lazy->grep(Sidef::Types::Block::Block->new(code => sub { $_[0]->is_squarefree && $_[0]->is_almost_prime($k) }))
->each($block);
return $self;
}

sub dump {
my ($self) = @_;
Sidef::Types::String::String->new("$self");
Expand Down
8 changes: 8 additions & 0 deletions lib/Sidef/Types/Range/RangeNumber.pod
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,14 @@ Return the

=cut

=head2 each_squarefree_almost_prime

RangeNumber.each_squarefree_almost_prime() -> I<Obj>

Return the

=cut

=head2 gcd

RangeNumber.gcd() -> I<Obj>
Expand Down
15 changes: 15 additions & 0 deletions scripts/Tests/number_methods.sf
Original file line number Diff line number Diff line change
Expand Up @@ -168,16 +168,31 @@ assert_eq(
2.almost_primes(10, 100)
)

assert_eq(
gather { 10..100 -> each_squarefree_almost_prime(2, {|k| take(k) }) },
2.squarefree_almost_primes(10, 100)
)

assert_eq(
gather { 10..100 -> each_almost_prime(3, {|k| take(k) }) },
3.almost_primes(10, 100)
)

assert_eq(
gather { 10..100 -> each_squarefree_almost_prime(3, {|k| take(k) }) },
3.squarefree_almost_primes(10, 100)
)

assert_eq(
gather { 10..100 `by` 3 -> each_almost_prime(3, {|k| take(k) }) },
10..100 `by` 3 -> grep { .is_almost_prime(3) }
)

assert_eq(
gather { 10..200 `by` 3 -> each_squarefree_almost_prime(3, {|k| take(k) }) },
10..200 `by` 3 -> grep { .is_almost_prime(3) && .is_squarefree }
)

assert_eq(
gather { 10..100 `by` 3 -> each_almost_prime(2, {|k| take(k) }) },
10..100 `by` 3 -> grep { .is_almost_prime(2) }
Expand Down

0 comments on commit 14cd46e

Please sign in to comment.