Я пытаюсь преобразовать реализацию теста примитивности Baillie – PSW из Python в Java.
Я думаю, что я сделал это в основном правильно, но есть часть, где ответы начинают отклоняться, и в результате весь алгоритм не может обнаружить простые числа. Это отклонение начинает возникать, когда алгоритм начинает использовать критерий Лукаса.
Вот оригинальный код для части этого теста (часть этого репо ):
def U_V_subscript(k, n, U, V, P, Q, D):
k, n, U, V, P, Q, D = map(int, (k, n, U, V, P, Q, D))
digits = list(map(int, str(bin(k))[2:]))
subscript = 1
for digit in digits[1:]:
U, V = U*V % n, (pow(V, 2, n) - 2*pow(Q, subscript, n)) % n
subscript *= 2
if digit == 1:
if not (P*U + V) & 1:
if not (D*U + P*V) & 1:
U, V = (P*U + V) >> 1, (D*U + P*V) >> 1
else:
U, V = (P*U + V) >> 1, (D*U + P*V + n) >> 1
elif not (D*U + P*V) & 1:
U, V = (P*U + V + n) >> 1, (D*U + P*V) >> 1
else:
U, V = (P*U + V + n) >> 1, (D*U + P*V + n) >> 1
subscript += 1
U, V = U % n, V % n
return U, V
А вот мой аналог Java:
static long[] UVSubscript(long k, long n, long U, long V, long P, long Q, long D){
BitSet bitDigits = convert(k);
long subscript = 1;
for (int i = bitDigits.length()-2; i >= 0; i--) {
U = U*V % n;
V = (powerModulus(V, 2, n) - 2*powerModulus(Q, subscript, n)) % n;
subscript *= 2;
if (bitDigits.get(i)){
if (((P * U + V) & 1) == 0){
if (((D*U + P*V) & 1) == 0){
U = (P*U + V) >> 1;
V = (D*U + P*V) >> 1;
}else{
U = (P*U + V) >> 1;
V = (D*U + P*V + n) >> 1;
}
} else if (((D * U + P * V) & 1) == 0){
U = (P*U + V + n) >> 1;
V = (D*U + P*V) >> 1;
}else{
U = (P*U + V + n) >> 1;
V = (D*U + P*V + n) >> 1;
}
subscript += 1;
U = U % n;
V = V % n;
}
}
return new long[]{U, V};
}
Может кто-нибудь помочь мне? Вот исполняемая версия всего скрипта Python , если кому-то интересно. И вот вставка всего моего перевода на Java .
PS Если кто-нибудь знает о готовой Java-реализации теста примитивности Baillie – PSW, я мог бы просто использовать это!