def test_shanks_middle(numOfTests: int,
                       numOfBits: list,
                       randSeed=0,
                       centered=True):
    import matplotlib.pyplot as plt
    seed(randSeed)
    giant_steps_class_list, times_clasic = [], []
    giant_steps_centered_list, times_centered = [], []
    for bits in numOfBits:
        time_clas, time_cent = [], []
        giant_clas, giant_cent = [], []
        for iter in range(numOfTests):
            p, g, exp, h = gnp.logarithm_test_numbers(bits, centered)
            # print("iter:", iter)
            t = timer()
            x_c, _, giant_steps_c, _ = shanks_classic(g, h, p, p - 1)
            giant_clas.append(giant_steps_c)
            passed_time = (timer() - t) * 1000
            time_clas.append(passed_time)
            # print(f"C_passed x:{x_c}, exp:{exp}, sm:{small_steps_c}, gs:{giant_steps_c} time:{passed_time:.3f}")

            t = timer()
            x_m, _, giant_steps_m = shanks_centered(g, h, p, p - 1)
            giant_cent.append(giant_steps_m)
            passed_time = (timer() - t) * 1000
            time_cent.append(passed_time)
            # print(f"M_passed x:{x_c}, exp:{exp}, sm:{small_steps_m}, gs:{giant_steps_m} time:{passed_time:.3f} \n")
        print()
        giant_steps_class_list.append(avg(giant_clas))
        giant_steps_centered_list.append(avg(giant_cent))
        times_clasic.append(avg(time_clas))
        times_centered.append(avg(time_cent))
def test_shanks_same_p(numOfTests: int, numOfBits: int, rs=[2], radn_seed=0):
    seed(radn_seed)
    times_g, smalls_g, giants_g, memsizes_g = [], [], [], []
    p, g, exps, hs = gnp.logarithm_test_numbers_same_p(numOfTests, numOfBits)
    l, m = optim_factors(p - 1)
    r_opt = r_optim(p - 1, numOfTests)
    print(f"r optim:{r_opt:.2f}")

    print("General started!")
    t_start_c = timer()
    x_cs, small_steps_c, giant_steps_c, memsize_c = shanks_classic_with_memory(
        g, hs, p, p - 1)
    time_c = (timer() - t_start_c) * 1000
    print("General finished!")

    print("Factor started!")
    t_start_f = timer()
    x_fs, small_steps_f, giant_steps_f, memsize_f = shanks_factor_with_memory(
        g, hs, p, l, m)
    time_f = (timer() - t_start_f) * 1000
    print("Factor finished!")

    rs += [r_opt]
    for r in rs:
        print(f"Gen {r:.3f} started!")
        t_start_g = timer()
        x_gs, small_steps_g, giant_steps_g, memsize_g = shanks_general_with_memory(
            g, hs, p, p - 1, r)
        times_g.append((timer() - t_start_g) * 1000)
        smalls_g.append(small_steps_g)
        giants_g.append(avg(giant_steps_g))
        memsizes_g.append(memsize_g)
        print(f"Gen {r:.3f} finished!")

    print(
        f"t_c: {time_c/numOfTests:.3f} ms, t_f: {time_f/numOfTests:.3f} ms, t_g:",
        end=' ')
    for r, t in zip(rs, times_g):
        print(f"r= {r}: {t/numOfTests:0.3f} ms", end=" ")
    print(
        f"\n\nsm_c: {small_steps_c/ceil(sqrt(p)):.3f}, sm_f: {small_steps_f/ceil(sqrt(p)):.3f}, sm_g:",
        end=' ')
    for r, s in zip(rs, smalls_g):
        print(f"r= {r}: {s/ceil(sqrt(p)):.3f}", end=" ")
    print(
        f"\n\ngc_avg: {avg(giant_steps_c)/ceil(sqrt(p)):.3f}, gf_avg: {avg(giant_steps_f)/ceil(sqrt(p)):.3f}, gg_avg:",
        end=' ')
    for r, g in zip(rs, giants_g):
        print(f"r= {r}: {g/ceil(sqrt(p)):.3f}", end=" ")
    print(
        f"\n\nsize_c: {memsize_c/ceil(sqrt(p)):.3f} bytes, size_f: {memsize_f/ceil(sqrt(p)):.3f} bytes, size_g:",
        end=' ')
    for r, m in zip(rs, memsizes_g):
        print(f"r= {r}: {m/ceil(sqrt(p)):.3f} bytes", end=" ")
def shanks_worst_tests(numOfTests: int, numOfBits: list, randSeed=0):
    seed(randSeed)
    total_steps_class_list, times_clasic_list, total_memory_clasic = [], [], []
    total_steps_grumpy_list, times_grumpy_list, total_memory_grumpy = [], [], []
    for bits in numOfBits:
        time_clas, time_grumpy = [], []
        steps_clas, steps_grumpy = [], []
        mem_clas, mem_grumpy = [], []
        print("Started: ", bits)
        if bits >= 50:
            numOfTests = 50
        elif bits >= 40:
            numOfTests = 100
        for iter in range(numOfTests):
            p, g, exp, h = gnp.worst_shanks_numbers(bits)
            t = timer()
            x_c, small_clas, giant_clas, mem_c = shanks_classic(g, h, p, p - 1)
            steps_clas.append(small_clas + giant_clas)
            mem_clas.append(mem_c)
            passed_time = (timer() - t) * 1000
            time_clas.append(passed_time)

            t = timer()
            x_c, oper, mem_c = shanks_two_grumpys_one_baby(g, h, p, p - 1)
            if x_c != exp:
                print("NG")
            steps_grumpy.append(oper)
            mem_grumpy.append(mem_c)
            passed_time = (timer() - t) * 1000
            time_grumpy.append(passed_time)
        print(
            f"Avg steps clasic:{avg(steps_clas) / ceil(sqrt(p)):.4f} -- Avg steps grumpy:{avg(steps_grumpy) / ceil(sqrt(p)):.4f}"
        )
        print(
            f"Avg memory clasic:{avg(mem_clas) / ceil(sqrt(p)):.4f} -- Avg memory grumpy:{avg(mem_grumpy) / ceil(sqrt(p)):.4f}"
        )
        print(
            f"Avg time clasic:{avg(time_clas):.4f} -- Avg time grumpy:{avg(time_grumpy):.4f}"
        )
        total_steps_class_list.append(avg(steps_clas) / ceil(sqrt(p)))
        total_steps_grumpy_list.append(avg(steps_grumpy) / ceil(sqrt(p)))
        times_clasic_list.append(avg(time_clas))
        times_grumpy_list.append(avg(time_grumpy))
        total_memory_clasic.append(avg(mem_clas) / ceil(sqrt(p)))
        total_memory_grumpy.append(avg(mem_grumpy) / ceil(sqrt(p)))
        print(f"Finished: {bits}\n")

    print(
        f"Avg steps clasic:{avg(total_steps_class_list):.4f} -- Avg steps grumpy:{avg(total_steps_grumpy_list):.4f}"
    )
    print(
        f"Avg memory clasic:{avg(total_memory_clasic):.4f} -- Avg memory grumpy:{avg(total_memory_grumpy):.4f}"
    )
    print(
        f"Avg time clasic:{avg(times_clasic_list):.4f} -- Avg time grumpy:{avg(times_grumpy_list):.4f}"
    )
def test_pollard(numOfTests: int,
                 listOfBits: list,
                 contests: dict,
                 img_path: str,
                 rand_seeds=[0]):
    import matplotlib.pyplot as plt
    from matplotlib.lines import Line2D
    from itertools import cycle
    marker = cycle(rand.sample(Line2D.markers.keys(), len(contests)))
    plt.tight_layout(pad=0.05)

    times = [[[0 for _ in rand_seeds] for _ in contests] for _ in listOfBits]
    times_avg = [[0 for _ in contests] for _ in listOfBits]
    iterations = [[[0 for _ in rand_seeds] for _ in contests]
                  for _ in listOfBits]
    iterations_avg = [[0 for _ in contests] for _ in listOfBits]

    for ind_b, bits in enumerate(listOfBits):
        print("Bits: ", bits)
        tests = num_of_tests(bits, numOfTests)
        print("Nr of tests: ", tests)
        p_set = set()
        print("Seed: ", end='')
        for ind_s, seed in enumerate(rand_seeds):
            rand.seed(seed)
            print(seed, end=', ')
            distinct_primes = number_of_distinct_primes(bits)
            for _ in range(tests):
                p, g, exp, h = logarithm_test_numbers(bits, safe=False)
                p_iter = 0
                while p in p_set and len(
                        p_set) < distinct_primes - 1 and p_iter < 10**2:
                    p, g, exp, h = logarithm_test_numbers(bits, safe=False)
                    p_iter += 1
                p_set.add(p)

                bit_seed = rand.randint(1, seed)
                for ind_c, c in enumerate(contests):
                    t = timer()
                    x, iter = pollard_rho(g,
                                          h,
                                          p,
                                          cycle=c[0],
                                          func=c[1],
                                          rand_seed=bit_seed)
                    if x != exp:
                        print("WRONG " + c[0] + " " + c[1])
                    times[ind_b][ind_c][ind_s] += (timer() - t) * 1000
                    iterations[ind_b][ind_c][ind_s] += iter

            for ind_c, c in enumerate(contests):
                iterations[ind_b][ind_c][ind_s] /= tests
                times[ind_b][ind_c][ind_s] /= tests
        print()
        for ind_c, c in enumerate(contests):
            iterations_avg[ind_b][ind_c] = avg(
                iterations[ind_b][ind_c]) / ceil(sqrt(p))
            times_avg[ind_b][ind_c] = avg(times[ind_b][ind_c])
            print(
                f"Cycle: {c[0]}, function: {c[1]}, itertions: {iterations_avg[ind_b][ind_c]:.4f}, time: {times_avg[ind_b][ind_c]:.3f}"
            )
        print()

    plt.figure(0)
    for ind_c, c in enumerate(contests):
        the_times = [t[ind_c] for t in times_avg]
        plt.plot(listOfBits,
                 the_times,
                 marker=next(marker),
                 label=c[0] + '_' + c[1])
    plt.legend()
    plt.ylabel("Milisecunde")
    plt.xlabel("biti")
    # plt.ticklabel_format(style='sci', axis='y', scilimits=(0, 0))
    plt.yscale('log')
    plt.savefig(img_path + '/pollard_time.png', bbox_inches='tight')

    plt.figure(1)
    print("The avg number of iterations: ", end='')
    avgits = []
    for ind_c, c in enumerate(contests):
        the_iterations = [it[ind_c] for it in iterations_avg]
        avg_c = avg(the_iterations)
        print(c[0] + '-' + c[1] + f": {avg_c:.4f}", end=' ')
        avgits.append(avg_c)
        plt.plot(listOfBits,
                 the_iterations,
                 marker=next(marker),
                 label=c[0] + '_' + c[1])
    plt.legend()
    plt.ylabel("Iteratii")
    plt.xlabel("biti")
    # plt.ticklabel_format(style='sci', axis='y', scilimits=(0, 0))
    plt.yscale('log')
    plt.savefig(img_path + '/pollard_iter.png', bbox_inches='tight')
    plt.show()
    return avgits
def test_pollard_dellays(numOfTests: int,
                         listOfBits: list,
                         contests: dict,
                         img_path: str,
                         rand_seeds=[0]):
    iterations = [[[0 for _ in rand_seeds] for _ in contests]
                  for _ in listOfBits]
    iterations_avg = [[0 for _ in contests] for _ in listOfBits]

    lambs = [[[0 for _ in rand_seeds] for _ in contests] for _ in listOfBits]
    lambs_avg = [[0 for _ in contests] for _ in listOfBits]

    mus = [[[0 for _ in rand_seeds] for _ in contests] for _ in listOfBits]
    mus_avg = [[0 for _ in contests] for _ in listOfBits]

    for ind_b, bits in enumerate(listOfBits):
        print("Bits: ", bits)
        tests = num_of_tests(bits, numOfTests)
        print("Nr of tests: ", tests)
        p_set = set()
        print("Seed: ", end='')
        for ind_s, seed in enumerate(rand_seeds):
            rand.seed(seed)
            print(seed, end=', ')
            distinct_primes = number_of_distinct_primes(bits)
            for _ in range(tests):
                p, g, exp, h = logarithm_test_numbers(bits, safe=False)
                p_iter = 0
                while p in p_set and len(
                        p_set) < distinct_primes - 1 and p_iter < 10**2:
                    p, g, exp, h = logarithm_test_numbers(bits, safe=False)
                    p_iter += 1
                p_set.add(p)

                bit_seed = rand.randint(1, seed)
                for ind_c, c in enumerate(contests):
                    x, iter, lamb, mu = pollard_rho(g,
                                                    h,
                                                    p,
                                                    cycle=c[0],
                                                    func=c[1],
                                                    rand_seed=bit_seed)
                    if x != exp:
                        print("WRONG " + c[0] + " " + c[1])
                    iterations[ind_b][ind_c][ind_s] += iter
                    lambs[ind_b][ind_c][ind_s] += lamb
                    mus[ind_b][ind_c][ind_s] += mu

            for ind_c, c in enumerate(contests):
                iterations[ind_b][ind_c][ind_s] /= tests
                lambs[ind_b][ind_c][ind_s] /= tests
                mus[ind_b][ind_c][ind_s] /= tests
        print()
        for ind_c, c in enumerate(contests):
            iterations_avg[ind_b][ind_c] = avg(
                iterations[ind_b][ind_c]) / ceil(sqrt(p))
            lambs_avg[ind_b][ind_c] = avg(lambs[ind_b][ind_c]) / ceil(sqrt(p))
            mus_avg[ind_b][ind_c] = avg(mus[ind_b][ind_c]) / ceil(sqrt(p))
            print(
                f"Cycle: {c[0]}, function: {c[1]}, itertions: {iterations_avg[ind_b][ind_c]:.4f}, lambs: {lambs_avg[ind_b][ind_c]:.4f} mus: {mus_avg[ind_b][ind_c]:.4f}, "
                f"rho: {lambs_avg[ind_b][ind_c] + mus_avg[ind_b][ind_c]:.4f} delay: {iterations_avg[ind_b][ind_c]/(lambs_avg[ind_b][ind_c] + mus_avg[ind_b][ind_c]):.4f}"
            )
        print()

    for ind_c, c in enumerate(contests):
        the_iterations = avg([it[ind_c] for it in iterations_avg])
        the_lambs = [lamb[ind_c] for lamb in lambs_avg]
        the_mus = [mu[ind_c] for mu in mus_avg]
        the_rhos = avg([x + y for x, y in zip(the_lambs, the_mus)])
        print(
            f"Cycle: {c[0]}, function: {c[1]}, itertions_avg: {the_iterations:.4f}, rho: {the_rhos:.4f}, delays {the_iterations/the_rhos:.4f}"
        )
Exemplo n.º 6
0
def test_qe_solver(listOfBits: list,
                   numOfTests: int,
                   contests: list,
                   rand_seeds=[0]):
    n = len(contests)
    times = [[[0 for _ in rand_seeds] for _ in range(n)] for _ in listOfBits]
    # iterations = [[[0 for _ in rand_seeds] for _ in range(n)] for _ in listOfBits]
    # iterations_avg = [[0 for _ in range(n)] for _ in listOfBits]
    times_avg = [[0 for _ in range(n)] for _ in listOfBits]

    for ind_b, bits in enumerate(listOfBits):
        tests = num_of_tests(bits, numOfTests)
        p_set = set()
        print("\nStarted bits: ", bits)
        print("Number of tests: ", tests)
        print("Seeds:", end=' ')
        for ind_s, s in enumerate(rand_seeds):
            print(s, end=', ')
            seed(s)
            i = 0
            distinct_primes = number_of_distinct_primes(bits)
            last_sum = 0
            while i < tests:
                p, g, exp, h = logarithm_test_numbers(bits, safe=False)
                p_iter = 0

                while (p in p_set or ceil(sqrt(p)) > 30000000
                       ) and len(p_set) < distinct_primes and p_iter < 10**2:
                    p, g, exp, h = logarithm_test_numbers(bits, safe=False)
                    p_iter += 1
                p_set.add(p)

                bit_seed = randint(1, s)
                for ind_c, c in enumerate(contests):

                    if c[0] == 'shoup':
                        qeAlg = partial(shoup_alg)
                    else:
                        qeAlg = partial(pohlig_hellman_alg)

                    if c[1] == 'shanks':
                        Solver = partial(Shanks, type=c[2], r=2.25)
                    else:
                        Solver = partial(pollard_rho,
                                         cycle=c[2],
                                         func=c[3],
                                         rand_seed=bit_seed)

                    t = timer()
                    x = silver_pohlig_hellman_alg(g,
                                                  h,
                                                  p,
                                                  fact=factorint,
                                                  qeAlg=qeAlg,
                                                  solver=Solver)
                    if x != exp:
                        print("WRONG " + c[0] + " " + c[1] + ' ' + c[2] + ' ' +
                              c[3])
                    times[ind_b][ind_c][ind_s] += (timer() - t) * 1000
                    # iterations[ind_b][ind_c][ind_s] += iter
                i += 1

        for ind_c, c in enumerate(contests):
            # iterations[ind_b][ind_c][ind_s] /= tests * ceil(sqrt(p))
            times[ind_b][ind_c][ind_s] /= tests
        print()
        for ind_c, c in enumerate(contests):
            # iterations_avg[ind_b][ind_c] = avg([it for it in iterations[ind_b][ind_c]]) {iterations_avg[ind_b][ind_c]:.4f},
            times_avg[ind_b][ind_c] = avg([it for it in times[ind_b][ind_c]])
            print(
                f"Qe_alg: {c[0]},  solver: {c[1]}: type: {c[2]}, function: {c[3]}, time: {times_avg[ind_b][ind_c]:.3f}"
            )
def test_shanks_vs_pollard(numOfTests: int,
                           listOfBits: list,
                           contests: list,
                           rand_seeds=[0]):
    n = len(contests) + 2
    times = [[[0 for _ in rand_seeds] for _ in range(n)] for _ in listOfBits]
    iterations = [[[0 for _ in rand_seeds] for _ in range(n)]
                  for _ in listOfBits]
    iterations_avg = [[0 for _ in range(n)] for _ in listOfBits]
    times_avg = [[0 for _ in range(n)] for _ in listOfBits]

    for ind_b, bits in enumerate(listOfBits):
        tests = num_of_tests(bits, numOfTests)
        p_set = set()
        print("\nStarted bits: ", bits)
        print("Number of tests: ", tests)
        print("Seeds:", end=' ')
        for ind_s, s in enumerate(rand_seeds):
            print(s, end=',\n')
            seed(s)
            i = 0
            distinct_primes = number_of_distinct_primes(bits)
            last_sum = 0
            while i < tests:
                p, g, exp, h = logarithm_test_numbers(bits, safe=False)
                p_iter = 0

                while (p in p_set or ceil(sqrt(p)) > 30000000
                       ) and len(p_set) < distinct_primes and p_iter < 10**2:
                    p, g, exp, h = logarithm_test_numbers(bits, safe=False)
                    p_iter += 1
                p_set.add(p)

                bit_seed = randint(1, s)
                print(f"sqrt(p): {ceil(sqrt(p))}")

                t = timer()
                x, iter = poll.pollard_simple(g, h, p, rand_seed=bit_seed)
                if x != exp:
                    if x == None:
                        continue
                    print("WRONG Pollard simplu")
                times[ind_b][n - 2][ind_s] += (timer() - t) * 1000
                iterations[ind_b][n - 2][ind_s] += iter
                # print("Poll simplu Done!:", (timer() - t) * 1000)

                t = timer()
                x, sm, gs, _ = shanks.shanks_classic(g, h, p, p - 1)
                if x != exp:
                    if x == None:
                        continue
                    print("WRONG Shanks clasic")
                times[ind_b][n - 1][ind_s] += (timer() - t) * 1000
                iterations[ind_b][n - 1][ind_s] += sm + gs
                # print("Shanks Done!", (timer() - t) * 1000)

                for ind_c, c in enumerate(contests):
                    t = timer()
                    x, iter = poll.pollard_rho(g,
                                               h,
                                               p,
                                               cycle=c[0],
                                               func=c[1],
                                               rand_seed=bit_seed)
                    if x != exp:
                        print("WRONG " + c[0] + " " + c[1])
                    times[ind_b][ind_c][ind_s] += (timer() - t) * 1000
                    iterations[ind_b][ind_c][ind_s] += iter
                    new_sum = sum([t[0] for t in times[ind_b][:]])
                print(f"Test {i} done, time: {new_sum - last_sum:.4f}")
                last_sum = new_sum
                i += 1

                # t = timer()
                # x, op, _ = shanks.shanks_two_grumpys_one_baby(g, h, p, p - 1)
                # if x != exp:
                #   print("WRONG Shanks clasic")
                # times[ind_b][n - 1][ind_s] += (timer() - t) * 1000
                # iterations[ind_b][n - 1][ind_s] += op

            for ind_c, c in enumerate(contests):
                iterations[ind_b][ind_c][ind_s] /= tests * ceil(sqrt(p))
                times[ind_b][ind_c][ind_s] /= tests
            iterations[ind_b][n - 2][ind_s] /= tests * ceil(sqrt(p))
            times[ind_b][n - 2][ind_s] /= tests
            iterations[ind_b][n - 1][ind_s] /= tests * ceil(sqrt(p))
            times[ind_b][n - 1][ind_s] /= tests
            # iterations[ind_b][n - 1][ind_s] /= tests * ceil(sqrt(p)); times[ind_b][n - 1][ind_s] /= tests
        print()
        for ind_c, c in enumerate(contests):
            iterations_avg[ind_b][ind_c] = avg(
                [it for it in iterations[ind_b][ind_c]])
            times_avg[ind_b][ind_c] = avg([it for it in times[ind_b][ind_c]])
            print(
                f"Cycle: {c[0]},  function: {c[1]}: itertions: {iterations_avg[ind_b][ind_c]:.4f}, time: {times_avg[ind_b][ind_c]:.3f}"
            )
        iterations_avg[ind_b][n - 2] = avg(
            [it for it in iterations[ind_b][n - 2]])
        times_avg[ind_b][n - 2] = avg([it for it in times[ind_b][n - 2]])
        print(
            f"Pollard simple: itertions: {iterations_avg[ind_b][n - 2] :.4f}, time: {times_avg[ind_b][n - 2]:.3f}"
        )
        iterations_avg[ind_b][n - 1] = avg(
            [it for it in iterations[ind_b][n - 1]])
        times_avg[ind_b][n - 1] = avg([it for it in times[ind_b][n - 1]])
        print(
            f"Shanks clasic: itertions: {iterations_avg[ind_b][n - 1] :.4f}, time: {times_avg[ind_b][n - 1]:.3f}"
        )
        # iterations_avg[ind_b][n - 1] = avg([it for it in iterations[ind_b][n - 1]])
        # times_avg[ind_b][n - 1] = avg([it for it in times[ind_b][n - 1]])
        # print(f"Two giants: itertions: {iterations_avg[ind_b][n - 1]:.4f}, time: {times_avg[ind_b][n - 1]:.3f}")

        print("Finished bits: ", bits)

    print("\nThe avg number of iterations: ", end='')
    avgits = []
    for ind_c, c in enumerate(contests):
        avg_c = avg([it[ind_c] for it in iterations_avg])
        print(c[0] + '-' + c[1] + f": {avg_c:.4f}", end=' ')
        avgits.append(avg_c)
    avg_c = avg([it[n - 2] for it in iterations_avg])
    print(f"pollard simple: {avg_c:.4f}", end=', ')
    avg_c = avg([it[n - 1] for it in iterations_avg])
    print(f"shanks clasic: {avg_c:.4f}", end=', ')
    # avg_c = avg([it[n - 1] for it in iterations_avg])
    # print(f"two giants: {avg_c:.4f}", end=' .')

    return iterations_avg


# def test_shanks_vs_pollard(numOfTests: int, listOfBits: list, contests: dict, rand_seeds = [0]):
#   n = len(contests) + 2
#   times = [[[0 for _ in rand_seeds] for _ in range(n)] for _ in listOfBits]
#   iterations = [[[0 for _ in rand_seeds] for _ in range(n)] for _ in listOfBits]
#   iterations_avg = [[0 for _ in range(n)] for _ in listOfBits]
#   times_avg = [[0 for _ in range(n)] for _ in listOfBits]
#   for ind_b, bits in enumerate(listOfBits):
#     tests = num_of_tests(bits, numOfTests)
#     p_set = set()
#     print("\nStarted bits: ", bits)
#     print("Seeds:", end = ' ')
#     for ind_s, s in enumerate(rand_seeds):
#       print(s, end=', ')
#       seed(s)
#       i = 0
#       distinct_primes = number_of_distinct_primes(bits)
#       while i < tests:
#         p, g, exp, h = logarithm_test_numbers(bits, safe=False)
#         p_iter = 0
#         while (p in p_set or ceil(sqrt(p)) > 30000000) and len(p_set) < distinct_primes and p_iter < 10**2:
#           p, g, exp, h = logarithm_test_numbers(bits, safe=False)
#           p_iter += 1
#         p_set.add(p)
#
#         bit_seed = randint(1, s)
#         # print(f"sqrt(p): {ceil(sqrt(p))}")
#
#         t = timer()
#         x, iter = poll.pollard_simple(g, h, p, rand_seed=bit_seed)
#         if x != exp:
#           if x == None:
#               continue
#           print("WRONG Pollard simplu")
#         times[ind_b][n - 2][ind_s] += (timer() - t) * 1000
#         iterations[ind_b][n - 2][ind_s] += iter
#         # print("Poll simplu Done!:", (timer() - t) * 1000)
#
#         t = timer()
#         x, sm, gs, _ = shanks.shanks_classic(g, h, p, p - 1)
#         if x != exp:
#           if x == None:
#               continue
#           print("WRONG Shanks clasic")
#         times[ind_b][n - 1][ind_s] += (timer() - t) * 1000
#         iterations[ind_b][n - 1][ind_s] += sm + gs
#         # print("Shanks Done!", (timer() - t) * 1000)
#
#
#         for ind_c, c in enumerate(contests):
#           t = timer()
#           x, iter = poll.pollard_rho(g, h, p, cycle=c[0], func=c[1], rand_seed=bit_seed)
#           if x != exp:
#             print("WRONG " + c[0] + " " + c[1])
#           times[ind_b][ind_c][ind_s] += (timer() - t) * 1000
#           iterations[ind_b][ind_c][ind_s] += iter
#         # print("Polls done")
#         i += 1
#
#         # t = timer()
#         # x, op, _ = shanks.shanks_two_grumpys_one_baby(g, h, p, p - 1)
#         # if x != exp:
#         #   print("WRONG Shanks clasic")
#         # times[ind_b][n - 1][ind_s] += (timer() - t) * 1000
#         # iterations[ind_b][n - 1][ind_s] += op
#
#       for ind_c, c in enumerate(contests):
#         iterations[ind_b][ind_c][ind_s] /= tests * ceil(sqrt(p))
#         times[ind_b][ind_c][ind_s] /= tests
#       iterations[ind_b][n - 2][ind_s] /= tests * ceil(sqrt(p)); times[ind_b][n - 2][ind_s] /= tests
#       iterations[ind_b][n - 1][ind_s] /= tests * ceil(sqrt(p)); times[ind_b][n - 1][ind_s] /= tests
#       # iterations[ind_b][n - 1][ind_s] /= tests * ceil(sqrt(p)); times[ind_b][n - 1][ind_s] /= tests
#     print()
#     for ind_c, c in enumerate(contests):
#       iterations_avg[ind_b][ind_c] = avg([it for it in iterations[ind_b][ind_c]])
#       times_avg[ind_b][ind_c] = avg([it for it in times[ind_b][ind_c]])
#       print(f"Cycle: {c[0]},  function: {c[1]}: itertions: {iterations_avg[ind_b][ind_c]:.4f}, time: {times_avg[ind_b][ind_c]:.3f}")
#     iterations_avg[ind_b][n - 2] = avg([it for it in iterations[ind_b][n - 2]])
#     times_avg[ind_b][n - 2] = avg([it for it in times[ind_b][n - 2]])
#     print(f"Pollard simple: itertions: {iterations_avg[ind_b][n - 2] :.4f}, time: {times_avg[ind_b][n - 2]:.3f}")
#     iterations_avg[ind_b][n - 1] = avg([it for it in iterations[ind_b][n - 1]])
#     times_avg[ind_b][n - 1] = avg([it for it in times[ind_b][n - 1]])
#     print(f"Shanks clasic: itertions: {iterations_avg[ind_b][n - 1] :.4f}, time: {times_avg[ind_b][n - 1]:.3f}")
#     # iterations_avg[ind_b][n - 1] = avg([it for it in iterations[ind_b][n - 1]])
#     # times_avg[ind_b][n - 1] = avg([it for it in times[ind_b][n - 1]])
#     # print(f"Two giants: itertions: {iterations_avg[ind_b][n - 1]:.4f}, time: {times_avg[ind_b][n - 1]:.3f}")
#
#     print("Finished bits: ", bits)
#
#   print("\nThe avg number of iterations: ", end='');
#   avgits = []
#   for ind_c, c in enumerate(contests):
#     avg_c = avg([it[ind_c] for it in iterations_avg])
#     print(c[0] + '-' + c[1] + f": {avg_c:.4f}", end=' ')
#     avgits.append(avg_c)
#   avg_c = avg([it[n - 2] for it in iterations_avg])
#   print(f"pollard simple: {avg_c:.4f}", end=', ')
#   avg_c = avg([it[n - 1] for it in iterations_avg])
#   print(f"shanks clasic: {avg_c:.4f}", end=', ')
#   # avg_c = avg([it[n - 1] for it in iterations_avg])
#   # print(f"two giants: {avg_c:.4f}", end=' .')
#
#   return iterations_avg

# if __name__ == "__main__":
#   numOfTests = 100
#   bits = [15]
#   seed(42)
#   rand_seeds = sample(range(0, 5000), 1)
#   contests = [('brent', 'pollard'), ('floyd', 'pollard'), ('teske', 'pollard')]
#   iters = test_shanks_vs_pollard(numOfTests, bits, contests, rand_seeds)
def test_shanks_clasic_inter_grumpy(numOfTests: int,
                                    numOfBits: list,
                                    randSeeds=[0]):
    total_steps_class_list, times_clasic_list, total_memory_clasic = [], [], []
    total_steps_inter_list, times_inter_list, total_memory_inter = [], [], []
    total_steps_grumpy_list, times_grumpy_list, total_memory_grumpy = [], [], []
    for bits in numOfBits:
        seed_steps_class_list, seed_times_clasic_list, seed_total_memory_clasic = [], [], []
        seed_steps_inter_list, seed_times_inter_list, seed_total_memory_inter = [], [], []
        seed_steps_grumpy_list, seed_times_grumpy_list, seed_total_memory_grumpy = [], [], []
        print("Started: ", bits)
        if bits >= 50:
            numOfTests = 50
        elif bits >= 40:
            numOfTests = 100
        elif bits >= 30:
            numOfTests = 500
        for s in randSeeds:
            seed(s)
            time_clas, time_inter, time_grumpy = [], [], []
            steps_clas, steps_inter, steps_grumpy = [], [], []
            mem_clas, mem_inter, mem_grumpy = [], [], []
            for iter in range(numOfTests):
                p, g, exp, h = gnp.logarithm_test_numbers(bits, False)
                t = timer()
                x_c, small_clas, giant_clas, mem_c = shanks_classic(
                    g, h, p, p - 1)
                steps_clas.append(small_clas + giant_clas)
                mem_clas.append(mem_c)
                passed_time = (timer() - t) * 1000
                time_clas.append(passed_time)

                t = timer()
                x_c, oper, mem_c = shanks_interleved(g, h, p, p - 1)
                if x_c != exp:
                    print("NI")
                steps_inter.append(oper)
                mem_inter.append(mem_c)
                passed_time = (timer() - t) * 1000
                time_inter.append(passed_time)

                t = timer()
                x_c, oper, mem_c = shanks_two_grumpys_one_baby(g, h, p, p - 1)
                if x_c != exp:
                    print("NG")
                steps_grumpy.append(oper)
                mem_grumpy.append(mem_c)
                passed_time = (timer() - t) * 1000
                time_grumpy.append(passed_time)
            seed_steps_class_list.append(avg(steps_clas) / ceil(sqrt(p)))
            seed_steps_inter_list.append(avg(steps_inter) / ceil(sqrt(p)))
            seed_steps_grumpy_list.append(avg(steps_grumpy) / ceil(sqrt(p)))
            seed_times_clasic_list.append(avg(time_clas))
            seed_times_inter_list.append(avg(time_inter))
            seed_times_grumpy_list.append(avg(time_grumpy))
            seed_total_memory_clasic.append(avg(mem_clas) / ceil(sqrt(p)))
            seed_total_memory_inter.append(avg(mem_inter) / ceil(sqrt(p)))
            seed_total_memory_grumpy.append(avg(mem_grumpy) / ceil(sqrt(p)))
        print(
            f"Avg steps clasic:{avg(seed_steps_class_list):.4f} -- Avg steps inter:{avg(seed_steps_inter_list):.4f} -- Avg steps grumpy:{avg(seed_steps_grumpy_list):.4f}"
        )
        print(
            f"Avg memory clasic:{avg(seed_total_memory_clasic):.4f} -- Avg memory inter:{avg(seed_total_memory_inter):.4f} -- Avg memory grumpy:{avg(seed_total_memory_grumpy):.4f}"
        )
        print(
            f"Avg time clasic:{avg(seed_times_clasic_list):.4f} -- Avg time inter:{avg(seed_times_inter_list):.4f} -- Avg time grumpy:{avg(seed_times_grumpy_list):.4f}"
        )
        total_steps_class_list.append(avg(seed_steps_class_list))
        total_steps_inter_list.append(avg(seed_steps_inter_list))
        total_steps_grumpy_list.append(avg(seed_steps_grumpy_list))
        times_clasic_list.append(avg(seed_times_clasic_list))
        times_inter_list.append(avg(seed_times_inter_list))
        times_grumpy_list.append(avg(seed_times_grumpy_list))
        total_memory_clasic.append(avg(seed_total_memory_clasic))
        total_memory_inter.append(avg(seed_total_memory_inter))
        total_memory_grumpy.append(avg(seed_total_memory_grumpy))
        print(f"Finished: {bits}\n")

    print(
        f"Avg steps clasic:{avg(total_steps_class_list):.4f} -- Avg steps inter:{avg(total_steps_inter_list):.4f} -- Avg steps grumpy:{avg(total_steps_grumpy_list):.4f}"
    )
    print(
        f"Avg memory clasic:{avg(total_memory_clasic):.4f} -- Avg memory inter:{avg(total_memory_inter):.4f} -- Avg memory grumpy:{avg(total_memory_grumpy):.4f}"
    )
    print(
        f"Avg time clasic:{avg(times_clasic_list):.4f} -- Avg time inter:{avg(times_inter_list):.4f} -- Avg time grumpy:{avg(times_grumpy_list):.4f}"
    )
 i = 0
 ts, tts = [], []
 its = []
 seed(42)
 for q in range(5):
     for _ in range(500):
         ok = 1
         while ok:
             ok = 0
             p, g, exponent, h = logarithm_test_numbers(15, safe=False)
         x = 2**ceil(log2(p - 1))
         B = ceil(exp(1 / sqrt(2) * sqrt(log(x) * log(log(x)))) / 2)
         # print(L(p), shanks_complex(p))
         primesB = primes_up_to_B(B)
         max_equations = primes_upto(B) + 5
         # print(B, max_equations, p)
         t = timer()
         x, ta, it = SELD_lect11(g, h, p, B, max_equations, primesB, 42)
         ts.append((timer() - t) * 1000)
         its.append(it)
         if x == exponent:
             # print("DA")
             i += 1
         else:
             if pow(g, x, p) != h:
                 print("Nu")
     avg_ts = avg(ts)
     tts.append(avg_ts)
     print("\n", i, avg_ts)
     print("\n", i, sum(its))
 print(avg(tts))