summaryrefslogtreecommitdiff
path: root/lab10/lab10.py
blob: 2e63379f8e6e9fffdb01907b403ab431757162a7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
import math
import random


def erathosphene(n):
    is_prime = [True] * n
    p = 2
    while p * p < n:
        cur = p * p;
        while cur < n:
            is_prime[cur] = False;
            cur += p;
        while not is_prime[p + 1]:
            p += 1;
        p += 1
    primes = []
    for i, p in enumerate(is_prime):
        if p:
            primes.append(i)
    return primes[2:]


def fast_power(base, power):
    result = 1
    while power > 0:
        if power % 2 == 0:
            power = power // 2
            base *= base
        else:
            power -= 1
            result = result * base
            power = power // 2
            base *= base
    return result


def get_only_prime_divisors(n):
    factors = []
    if (n % 2 == 0):
        factors.append(2)

    while (n % 2 == 0):
        n = n // 2

    for i in range(3, int(math.sqrt(n)) + 1, 2):
        if (n % i == 0):
            factors.append(i)

        while (n % i == 0):
            n = n // i

    if (n > 2):
        factors.append(n)

    return factors


def pocklington_criterion(n, borded_a):
    prev_n = n - 1
    prime_divisors = get_only_prime_divisors(prev_n)
    prime_divisors = filter(lambda q: q > math.sqrt(n) - 1, prime_divisors)

    for a in range(2, borded_a):
        if pow(a, prev_n, n) != 1:
            continue
        for q in prime_divisors:
            if math.gcd(n, fast_power(a, prev_n // q) - 1) == 1:
                return True
    return False


def get_random_number(n):
    while True:
        number = random.randrange(2 ** (n-1) + 1, 2 ** n - 1)
        for divisor in first_primes_list:
            if number % divisor == 0 and divisor ** 2 <= number:
                break
        else:
            return number


def create_prime(n, a):
    while True:
        number = get_random_number(n)
        if pocklington_criterion(number, a):
            return number


first_primes_list = erathosphene(500)
if __name__ == "__main__":
    print("Введите количество бит генерируемого простого числа:")
    n = int(input())
    print("Введите верхнюю границу числа 'a' в критерии Поклингтона (не меньше 3):")
    a = int(input())
    result = create_prime(n, a)
    print(f"Сгенерированное простое число: {result}")