From 9df78d7f638a39b2843f7c585dcfa56645cc07ac Mon Sep 17 00:00:00 2001 From: trizen Date: Mon, 21 Jun 2021 13:38:46 +0300 Subject: [PATCH] - Added the Number `n.prime_lower` and `n.prime_upper` methods. Lower and upper bounds for the n-th prime. Example: say 1e12.prime_lower #=> 29996219470245 say 1e12.prime_upper #=> 29996230936979 say 1e12.prime #=> 29996224275833 (exact value) --- lib/Sidef/Types/Number/Number.pm | 91 +++++++++++++++++++++++++++++-- lib/Sidef/Types/Number/Number.pod | 22 +++++++- 2 files changed, 108 insertions(+), 5 deletions(-) diff --git a/lib/Sidef/Types/Number/Number.pm b/lib/Sidef/Types/Number/Number.pm index 84a4a5c2..a6c670d7 100644 --- a/lib/Sidef/Types/Number/Number.pm +++ b/lib/Sidef/Types/Number/Number.pm @@ -10022,6 +10022,11 @@ package Sidef::Types::Number::Number { CORE::int($n * (CORE::log($n) + CORE::log(CORE::log($n)) - 1)); } + sub _nth_prime_upper { + my ($n) = @_; + CORE::int($n * (CORE::log($n) + CORE::log(CORE::log($n)))); + } + sub _nth_almost_prime_lower { my ($n, $k) = @_; @@ -10494,19 +10499,97 @@ package Sidef::Types::Number::Number { *count_primes = \&prime_count; sub prime_count_lower { - my $prime_pi = Math::Prime::Util::GMP::prime_count_lower(&_big2uistr // return ZERO) // 0; - _set_int($prime_pi); + my ($n) = @_; + + $n = _any2mpz($$n) // return ZERO; + + if (Math::GMPz::Rmpz_sgn($n) <= 0) { + return ZERO; + } + + if (HAS_PRIME_UTIL and Math::GMPz::Rmpz_fits_ulong_p($n)) { + return _set_int(Math::Prime::Util::prime_count_lower(Math::GMPz::Rmpz_get_ui($n))); + } + + _set_int(Math::Prime::Util::GMP::prime_count_lower(Math::GMPz::Rmpz_get_str($n, 10))); } *primepi_lower = \&prime_count_lower; sub prime_count_upper { - my $prime_pi = Math::Prime::Util::GMP::prime_count_upper(&_big2uistr // return ZERO) // 0; - _set_int($prime_pi); + my ($n) = @_; + + $n = _any2mpz($$n) // return ZERO; + + if (Math::GMPz::Rmpz_sgn($n) <= 0) { + return ZERO; + } + + if (HAS_PRIME_UTIL and Math::GMPz::Rmpz_fits_ulong_p($n)) { + return _set_int(Math::Prime::Util::prime_count_upper(Math::GMPz::Rmpz_get_ui($n))); + } + + _set_int(Math::Prime::Util::GMP::prime_count_upper(Math::GMPz::Rmpz_get_str($n, 10))); } *primepi_upper = \&prime_count_upper; + sub _nth_prime_lower_bound { + my ($n) = @_; + my $log_n = $n->log; + $n->mul($log_n->add($log_n->log)->dec); + } + + sub _nth_prime_upper_bound { + my ($n) = @_; + my $log_n = $n->log; + $n->mul($log_n->add($log_n->log)); + } + + sub nth_prime_lower { + my ($n) = @_; + + my $z = _any2mpz($$n) // goto &nan; + + if (Math::GMPz::Rmpz_cmp_ui($z, 10) <= 0) { + return $n->nth_prime; + } + + bsearch_min( + $n->_nth_prime_lower_bound, + $n->_nth_prime_upper_bound, + Sidef::Types::Block::Block->new( + code => sub { + $_[0]->prime_count_upper->cmp($n); + } + ) + ); + } + + *prime_lower = \&nth_prime_lower; + + sub nth_prime_upper { + my ($n) = @_; + + my $z = _any2mpz($$n) // goto &nan; + + if (Math::GMPz::Rmpz_cmp_ui($z, 10) <= 0) { + return $n->nth_prime; + } + + bsearch_max( + $n->_nth_prime_lower_bound, + $n->_nth_prime_upper_bound, + Sidef::Types::Block::Block->new( + code => sub { + $_[0]->prime_count_lower->cmp($n); + } + ) + ); + } + + *prime_upper = \&nth_prime_upper; + sub almost_prime_count { my ($k, $from, $to) = @_; diff --git a/lib/Sidef/Types/Number/Number.pod b/lib/Sidef/Types/Number/Number.pod index 88af14e5..139b3793 100644 --- a/lib/Sidef/Types/Number/Number.pod +++ b/lib/Sidef/Types/Number/Number.pod @@ -5169,6 +5169,16 @@ Returns the unique prime factors of C. =cut +=head2 prime_lower + + n.prime_lower + +Lower bound for the n-th prime. + +Aliases: I + +=cut + =head2 primepi primepi(n) @@ -5345,7 +5355,7 @@ Aliases: I, I =head2 prime_udivisors - n.prime_udivisors() + n.prime_udivisors Returns the unique unitary prime factors of C. @@ -5353,6 +5363,16 @@ Aliases: I, I =cut +=head2 prime_upper + + n.prime_upper + +Upper bound for the n-th prime. + +Aliases: I + +=cut + =head2 prime_usigma n.prime_usigma(k=1)