#!/usr/bin/env python3

import unittest
from Cryptotools.Numbers.primeNumber import isPrimeNumber, _millerRabinTest, getPrimeNumber
from math import sqrt, isqrt, ceil
from sympy import sqrt as sq

def get_closest_prime(p):
    q = p + 1
    l = list()
    while True:
        if _millerRabinTest(q):
            l.append(q)
        if len(l) == 20:
            break
        q += 1
    return l

def test():
    while True:
        p = getPrimeNumber(64)
        b = sqrt(p)
        if b % 2 == 0.0:
            break
    print(p)

#test()  
#exit(1)
p = 7901
q = 7817
#p = getPrimeNumber(64)
#q = get_closest_prime(p)[1]
p = 7943202761666983 # Works
q = 7943202761667119
#p = 314159200000000028138418196395985880850000485810513
#q = 314159200000000028138415196395985880850000485810479
print(f"p = {p}")
print(f"q = {q}")
n = p * q
print(f"n = {n}")

a = ceil(sqrt(n))
#print(a)
#print(sqrt(n))
#print(sqrt(n) < n) # True
#print(a * a)
#print(a * a < n)
#print()
#a = isqrt(n) + 1
iteration = 0
while True:
    # b2 = (a ** 2) - n
    iteration += 1
    b2 = pow(a, 2) - n
    #b2 = ceil(a*a) - n
    # print(b2)
    sqb2 = ceil(sqrt(b2))
    # print(b2, isqrt(pow(b2, 2)))
    if b2 % 2 == 0.0:
    #if isqrt(pow(b2, 2)) == b2:
        b = isqrt(b2)
        break
    a = a + 1

print(f"Iteration: {iteration}") 
print(f"a = {a}")
print(f"b2 = {b2}")
print(f"b = {b}")
p = int((a + b))
q = int((a - b))
print(p)
print(q)
#N = (a + b) * (a - b)
N = p * q
print(_millerRabinTest(p))
print(_millerRabinTest(q))
print(f"N = {N}")
print(n == N)
print()

