Skip to content

Commit

Permalink
- Better performance in computing the modular Lucas V and U sequences…
Browse files Browse the repository at this point in the history
… when the current GitHub version of Math::Prime::Util and Math::Prime::Util::GMP is installed.

By using the `lucasvmod` and `lucasumod` functions, which are faster than `lucas_sequence` (which compute both U and V).
  • Loading branch information
trizen committed Oct 15, 2023
1 parent 5aae172 commit 919bfb3
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 20 deletions.
79 changes: 59 additions & 20 deletions lib/Sidef/Types/Number/Number.pm
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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);
}
Expand Down
4 changes: 4 additions & 0 deletions scripts/Tests/lucas_sequences.sf
Original file line number Diff line number Diff line change
Expand Up @@ -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!"
2 changes: 2 additions & 0 deletions scripts/Tests/number_methods.sf
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down

0 comments on commit 919bfb3

Please sign in to comment.