diff --git a/lib/Sidef/Types/Number/Number.pm b/lib/Sidef/Types/Number/Number.pm index 111bf387..410e61a5 100644 --- a/lib/Sidef/Types/Number/Number.pm +++ b/lib/Sidef/Types/Number/Number.pm @@ -61,6 +61,9 @@ package Sidef::Types::Number::Number { HAS_NEW_PRIME_UTIL => (HAS_PRIME_UTIL and defined(&Math::Prime::Util::is_perfect_power)) // 0, HAS_NEWER_PRIME_UTIL => (HAS_PRIME_UTIL and defined(&Math::Prime::Util::is_congruent)) // 0, + # Check if we have a recent enough version of Math::Prime::Util::GMP + HAS_NEW_PRIME_UTIL_GMP => defined(&Math::Prime::Util::GMP::lucasvmod) // 0, + IS_PRIME_CACHE_SIZE => 1e5, # how many entries to cache INTSIZE => CORE::int(CORE::log(ULONG_MAX) / CORE::log(2)), # size of ULONG_MAX in base 2 PRIMECOUNT_MIN => List::Util::min(ULONG_MAX, (HAS_PRIME_UTIL ? 1e10 : 1e7)), # absolute value @@ -11535,18 +11538,36 @@ package Sidef::Types::Number::Number { and (ref($Q) ? (Math::GMPz::Rmpz_cmpabs_ui($Q, $LUCAS_PQ_LIMIT) < 0) : (CORE::abs($Q) < $LUCAS_PQ_LIMIT))) { my ($U, $V); if (HAS_NEW_PRIME_UTIL and (!ref($m) or Math::GMPz::Rmpz_fits_ulong_p($m)) and (!ref($n) or Math::GMPz::Rmpz_fits_ulong_p($n))) { - eval { - ($U, $V) = - Math::Prime::Util::lucas_sequence( - (ref($m) ? Math::GMPz::Rmpz_get_ui($m) : $m), - (ref($P) ? Math::GMPz::Rmpz_get_si($P) : $P), - (ref($Q) ? Math::GMPz::Rmpz_get_si($Q) : $Q), - (ref($n) ? Math::GMPz::Rmpz_get_ui($n) : $n) - ); - }; + if (HAS_NEWER_PRIME_UTIL) { + eval { + $U = + Math::Prime::Util::lucasumod( + (ref($P) ? Math::GMPz::Rmpz_get_si($P) : $P), + (ref($Q) ? Math::GMPz::Rmpz_get_si($Q) : $Q), + (ref($n) ? Math::GMPz::Rmpz_get_ui($n) : $n), + (ref($m) ? Math::GMPz::Rmpz_get_ui($m) : $m), + ); + }; + } + else { + eval { + ($U, $V) = + Math::Prime::Util::lucas_sequence( + (ref($m) ? Math::GMPz::Rmpz_get_ui($m) : $m), + (ref($P) ? Math::GMPz::Rmpz_get_si($P) : $P), + (ref($Q) ? Math::GMPz::Rmpz_get_si($Q) : $Q), + (ref($n) ? Math::GMPz::Rmpz_get_ui($n) : $n), + ); + }; + } } else { - eval { ($U, $V) = Math::Prime::Util::GMP::lucas_sequence($m, $P, $Q, $n) }; + if (HAS_NEW_PRIME_UTIL_GMP) { + eval { $U = Math::Prime::Util::GMP::lucasumod($P, $Q, $n, $m) }; + } + else { + eval { ($U, $V) = Math::Prime::Util::GMP::lucas_sequence($m, $P, $Q, $n) }; + } } defined($U) && return _str2obj($U); } @@ -11583,18 +11604,36 @@ package Sidef::Types::Number::Number { and (ref($Q) ? (Math::GMPz::Rmpz_cmpabs_ui($Q, $LUCAS_PQ_LIMIT) < 0) : (CORE::abs($Q) < $LUCAS_PQ_LIMIT))) { my ($U, $V); if (HAS_NEW_PRIME_UTIL and (!ref($m) or Math::GMPz::Rmpz_fits_ulong_p($m)) and (!ref($n) or Math::GMPz::Rmpz_fits_ulong_p($n))) { - eval { - ($U, $V) = - Math::Prime::Util::lucas_sequence( - (ref($m) ? Math::GMPz::Rmpz_get_ui($m) : $m), - (ref($P) ? Math::GMPz::Rmpz_get_si($P) : $P), - (ref($Q) ? Math::GMPz::Rmpz_get_si($Q) : $Q), - (ref($n) ? Math::GMPz::Rmpz_get_ui($n) : $n) - ); - }; + if (HAS_NEWER_PRIME_UTIL) { + eval { + $V = + Math::Prime::Util::lucasvmod( + (ref($P) ? Math::GMPz::Rmpz_get_si($P) : $P), + (ref($Q) ? Math::GMPz::Rmpz_get_si($Q) : $Q), + (ref($n) ? Math::GMPz::Rmpz_get_ui($n) : $n), + (ref($m) ? Math::GMPz::Rmpz_get_ui($m) : $m), + ); + }; + } + else { + eval { + ($U, $V) = + Math::Prime::Util::lucas_sequence( + (ref($m) ? Math::GMPz::Rmpz_get_ui($m) : $m), + (ref($P) ? Math::GMPz::Rmpz_get_si($P) : $P), + (ref($Q) ? Math::GMPz::Rmpz_get_si($Q) : $Q), + (ref($n) ? Math::GMPz::Rmpz_get_ui($n) : $n), + ); + }; + } } else { - eval { ($U, $V) = Math::Prime::Util::GMP::lucas_sequence($m, $P, $Q, $n) }; + if (HAS_NEW_PRIME_UTIL_GMP) { + eval { $V = Math::Prime::Util::GMP::lucasvmod($P, $Q, $n, $m) }; + } + else { + eval { ($U, $V) = Math::Prime::Util::GMP::lucas_sequence($m, $P, $Q, $n) }; + } } defined($V) && return _str2obj($V); } diff --git a/scripts/Tests/lucas_sequences.sf b/scripts/Tests/lucas_sequences.sf index e4becebd..cb8bbc86 100644 --- a/scripts/Tests/lucas_sequences.sf +++ b/scripts/Tests/lucas_sequences.sf @@ -187,5 +187,9 @@ assert_eq(fibmod(2**127 - 1, 4, 2**128 + 1), 27940561363156168276156076131587250 assert_eq(fibmod(2**128 + 1, 2, 2**128 - 1), fibmod(2**128 + 1, 2**128 - 1)) assert(%n[913, 150267335403, 430558874533, 14760229232131, 936916995253453].all { .is_bfw_psp }) +assert(%n[7056721, 79397009999, 443372888629441, 582920080863121, 2491924062668039, 14522256850701599, 39671149333495681, 242208715337316001, 729921147126771599, 842526563598720001, 1881405190466524799, 2380296518909971201, 3188618003602886401, 33711266676317630401, 54764632857801026161, 55470688965343048319, 72631455338727028799, 122762671289519184001, 361266866679292635601, 734097107648270852639].all{.is_chebyshev_psp}) + +assert(is_strong_fibonacci_pseudoprime(443372888629441)) +assert(is_strong_fibonacci_pseudoprime(39671149333495681)) say "** Test passed!" diff --git a/scripts/Tests/number_methods.sf b/scripts/Tests/number_methods.sf index 33f89ef1..4f2f8271 100644 --- a/scripts/Tests/number_methods.sf +++ b/scripts/Tests/number_methods.sf @@ -478,6 +478,8 @@ do { assert(!n.is_bpsw_prp) assert(!n.is_fib_psp) assert(!n.is_carmichael) + assert(!n.is_chebyshev_psp) + assert(!n.is_strong_fib_psp) assert(!n.is_lucas_psp) assert(!n.is_lucasU_psp(1, -1)) assert(!n.is_lucasV_psp(1, -1))