예제 #1
0
def D_N_K_q_sum_over_k_1st(N, K, q, e_itkN_arr, gbc_con_expect, print_option = False):

    Shape = [q, q]
    main_term_l_l2_2d_arr = np.zeros(Shape, dtype = np.complex64)

    for l in range(1, q):

        if(l >= N):
            break

        gcd_l_q = gcd(l, q)
        if(gcd_l_q == 1):

            for l2 in range(1, q):

                if(l2 >= N):
                    break

                gcd_l2_q = gcd(l2, q)
                if(gcd_l2_q == 1):

                    for k in range(0, K):

                        # sieg_walf will NOT be used when (q%K == 0)
                        assert(q%K == 0)

                        main_term_s_k_N_q_l, error_term_s_k_N_q_l =  s_k_N_q_l(k, K, N, q, l)
                        main_term_s_k_N_q_l2, error_term_s_k_N_q_l2 =  s_k_N_q_l(k, K, N, q, l2)

                        assert(main_term_s_k_N_q_l.real > error_term_s_k_N_q_l.real)
                        assert(main_term_s_k_N_q_l2.real > error_term_s_k_N_q_l2.real)

                        e_itkN = e_itkN_arr[k]
                        main_term_l_l2 = e_itkN*main_term_s_k_N_q_l*main_term_s_k_N_q_l2
                        main_term_l_l2_2d_arr[l, l2] = main_term_l_l2
예제 #2
0
def co_prime_check(a, x, b, y, c, z):

    ab_gcd = gcd(a, b)
    ac_gcd = gcd(a, c)
    abc_gcd = gcd(ab_gcd, ac_gcd)

    if(abc_gcd == 1):
        print '!!! ============== co_prime_check: a = %4d, x = %4d, b = %4d, y = %4d, c = %4d, z = %4d'%(a, x, b, y, c, z)

    return abc_gcd
예제 #3
0
def s_k_N_q_sum_all_l(k, K, N, q, e_itkl_2d_arr):

    main_term_s_k_N_q_sum_all_l = 0
    error_term_s_k_N_q_sum_all_l = 0

    for l in range(1, q):

        if(l >= N):
            break

        gcd_l_q = gcd(l, q)
        if(gcd_l_q == 1):

            main_term_with_phase, main_term_no_phase,  error_term_no_phase, error_term_with_phase  = s_k_N_q_l(k, K, N, q, l, e_itkl_2d_arr)

            # main_term_sum need to be added with phase, so lots of cancellation can happen
            main_term_s_k_N_q_sum_all_l += main_term_with_phase

            # error_term_sum need to be added with no phase, so error will get larger and larger when more terms are include
            error_term_s_k_N_q_sum_all_l += error_term_no_phase

    # print " main_term_sum = ",  main_term_sum, ", error_term_sum = ", error_term_sum
    # assert(main_term_s_k_N_q_sum_all_l >  error_term_s_k_N_q_sum_all_l )

    return main_term_s_k_N_q_sum_all_l, error_term_s_k_N_q_sum_all_l
예제 #4
0
def get_quadr_recip_using_multiplicative_properties(n, p, prime_list):

    check_p_is_prime  = p in prime_list
    if(check_p_is_prime == False):
        print 'get_quadr_recip_using_multiplicative_properties only work for p is a prime, p %d'%(p)
        assert(0)

    if(gcd(n, p) >1):
        return 0

    # first find reminder of m = n%p
    m = n%p

    # factor m into products of prime powers, and use multiplicative properties
    factor_list = factor_a_number(m, prime_list)
    tmp_qr = 1
    count = len(factor_list)

    # using the multiplicative properties
    for x in range(count):

        # we can use either of the following methods to get (l | p) where l is a prime smaller than p
        # l = factor_list[x]
        #
        # We can further simplify the calculation by using quad_recip formula to reduce
        # (l | p) to (p | l) if NOT (l = 3 mod(4) and p = 3 mod(4))
        # tmp2 = get_quadr_recip_brute_force(factor_list[x][0], p)          # method 1
        tmp2 = eul_criter(factor_list[x][0], p)                             # method 2

        tmp3 = int(round(np.power(tmp2, factor_list[x][1] )))
        tmp_qr *= tmp3

    return tmp_qr
예제 #5
0
def get_major_ar(Q, t):

    MA =[]
    MA_a_q =[]
    for q in range(1, Q + 1):
        for a in range(q):
            if (gcd(a, q) == 1):

                I_q_a_t = get_I_q_a_t(q, a, t)
                tmp = deepcopy(I_q_a_t)
                MA.append(tmp)
                MA_a_q.append([a, q])

    # sorted MA and return as 2D array
    MajorA_2d_arr = np.asarray(MA)
    MajorA_2d_sorted_arr = np.sort(MajorA_2d_arr, axis=0)
    # print MajorA_2d_sorted_arr

    # also output sorted [a, q] list, which shall be the fare_seq except the 1st one, which can be negative
    MajorA_2d_sorted_index_arr = np.argsort(MajorA_2d_arr, axis=0)

    print 'MajorA_2d_sorted_index_arr = ', MajorA_2d_sorted_index_arr

    MA_a_q_sorted_arr = []
    cnt = len(MajorA_2d_sorted_index_arr)
    for i in range(cnt):
        MA_a_q_sorted_arr.append(MA_a_q[MajorA_2d_sorted_index_arr[i][0]])

    print MA_a_q_sorted_arr
    return MajorA_2d_sorted_arr, MA_a_q_sorted_arr
예제 #6
0
def rama_sum_use_mobi_phi(n, m):

    a = gcd(n, m)
    N = n/a

    phi_n, coprime_list = eul_totie(n)
    phi_N, coprime_list = eul_totie(N)

    c_n_m = mobi_list[N - 1]*phi_n/phi_N

    return c_n_m
예제 #7
0
def rama_sum_use_prim_unit_root(q, m):

    c_q_m = 0

    for h in range(1, q +1):

        gcd_h_q = gcd(h, q)

        if(gcd_h_q == 1):
            factor = 1j*2*np.pi*h*m/q
            c_q_m += np.exp(factor)

    return c_q_m
예제 #8
0
def get_quadr_recip_brute_force(n, p):

    if(gcd(n, p) >1):
        return 0

    nRp_list = []

    for x in range(p):
        if ((x*x - n)%p == 0):
            nRp_list.append(x)

    if(len(nRp_list ) > 0):
        return 1

    else:
        return -1
예제 #9
0
def calculate_e_itkl_2d_arr(K, q):

    # if gcd(l, q) != 0, then e_itkl_2d_arr[k, l]= 0,
    # we need to check gcd(l, q) != 0 condition, to ensure that this function will not be called under
    # such condition.

    Shape = [K, q]
    e_itkl_2d_arr = np.zeros(Shape, dtype = np.complex64)

    theta = 2*np.pi/K

    for k in range(0, K):
        for l in range(1, q):
            gcd_l_q = gcd(l, q)

            if(gcd_l_q == 1):
                e_itkl_2d_arr[k, l] = np.exp(1j*theta*k*l)

    return e_itkl_2d_arr
예제 #10
0
def sum_of_product_for_orthog_property(m1, m2):

    # m = lcm(m1, m2)
    m = (m1*m2)/gcd(m1, m2)

    # print 'm = ', m

    sum = 0
    for k in range(1, m+1):
        tmp1 = rama_sum_use_mobi(m1, k)
        # tmp1 =  rama_sum_use_prim_unit_root(m1, k)
        tmp2 = rama_sum_use_mobi(m2, k)
        # tmp2 =  rama_sum_use_prim_unit_root(m2, k)

        tmp= tmp1*tmp2
        sum += tmp

        # print 'tmp1 = ', tmp1, ', tmp2 = ', tmp2, ', tmp = ', tmp
    sum = sum/float(m)

    return sum
예제 #11
0
def s_k_N_q_l(k, K, N, q, l, e_itkl_2d_arr, error_option = 1):

    # since this function is based on sieg_walf, so it requires assert(q%K == 0)
    assert(q%K == 0)

    # print "l = ", l
    assert(gcd(l, q) == 1)

    # phase
    e_itkl = e_itkl_2d_arr[k, l]

    phi_q, coprime_list = eul_totie(q)
    assert(phi_q > 0)

    # main term, N/(log(N)*phi(q))
    main_term_no_phase = N/(np.log(N)*phi_q)

    # sieg_walf error term
    if(error_option == 1):
        # error term,  N/(log(N)^2*phi(q)), with extra log(N) in denominator
        error_term_no_phase = N/(((np.log(N))**2)*phi_q)

    # GRH error term
    elif (error_option == 2):
        # error term,  (np.sqrt(N)*np.log(N))/phi_q, with extra log(N) in numerator
        error_term_no_phase = (np.sqrt(N)*np.log(N))/phi_q

    # not support
    else:
        assert(0)

    main_term_with_phase = e_itkl* main_term_no_phase
    error_term_with_phase = e_itkl*error_term_no_phase

    # print " main_term_no_phase = ",  main_term_no_phase, ", error_term_no_phase = ", error_term_no_phase

    assert(main_term_no_phase > error_term_no_phase)

    return main_term_with_phase, main_term_no_phase,  error_term_no_phase, error_term_with_phase
예제 #12
0
def lamda_k(f_k_list, g_k_list, xi, mobi_list, k_range):

    lamda_k_list = []

    # sum(u^2(m)/f(m) when 1 <= m <= xi
    sum_u_square_over_fm = 0

    for m in range(1, xi):
        tmp = mobi_list[m - 1] * mobi_list[m - 1] / f_k_list[m - 1]
        sum_u_square_over_fm += tmp

    assert sum_u_square_over_fm != 0

    for k in range(1, k_range + 1):

        # sum(u^2(m)/f(m) when 1 <= m <= xi/k and (m, k) = 1
        sum_u_square_over_fm_mod_k = 0

        xi_k = xi / k

        # when 1 <= m <= xi/k
        for m in range(1, xi_k):

            # (m, k) = 1
            if gcd(m, k) == 1:
                tmp = mobi_list[m - 1] * mobi_list[m - 1] / f_k_list[m - 1]
                sum_u_square_over_fm_mod_k += tmp

        # u_k_over_f_k_g_k = u(k)/f(k)g(k)
        u_k_over_f_k_g_k = mobi_list[k - 1] / (f_k_list[k - 1] * g_k_list[k - 1])

        # lamda_k
        lamda_k = u_k_over_f_k_g_k * sum_u_square_over_fm_mod_k / sum_u_square_over_fm

        lamda_k_list.append(lamda_k)

    return lamda_k_list
예제 #13
0
def verify_gaus_sum_of_char_prod(N, M):

    # this function only work for N, M are co-prime
    assert(gcd(N, M) == 1)
    
    ALMOST_ZERO = 0.001

    # get dirich_char_mat, which is a 2D matrix
    dirich_char_mat_N, phi_n, coprime_list, prim_char_stat_all = dirichi_char_for_n(N)

    # get dirich_char_mat, which is a 2D matrix
    dirich_char_mat_M, phi_m, coprime_list, prim_char_stat_all = dirichi_char_for_n(M)

    # number of row. Note: 1st row is principle
    for i in range(0, phi_n):
        for j in range(0, phi_m):

            chi_i = dirich_char_mat_N[i]
            chi_j = dirich_char_mat_M[j]

            chi_i_chi_j = char_product(chi_i,  chi_j)

            gaus_sum_chi_prod = gaus_sum_for_dirich_char(chi_i_chi_j)
            chi_i_M = chi_i[M%N]
            chi_j_N = chi_j[N%M]
            gaus_sum_chi_i = gaus_sum_for_dirich_char(chi_i)
            gaus_sum_chi_j = gaus_sum_for_dirich_char(chi_j)

            tmp = chi_i_M*chi_j_N*gaus_sum_chi_i*gaus_sum_chi_j

            assert(np.absolute(gaus_sum_chi_prod - tmp) < ALMOST_ZERO)
            # print 'chi      = ', chi
            # print 'chi_conj = ', chi_conj
            # print 'N = %d, M = %d, i = %d, j = %d'%(N, M,  i, j), ', gaus_sum_chi_prod = ', gaus_sum_chi_prod, ', tmp = ', tmp

    print 'verify_gaus_sum_of_char_prod() pass !'
예제 #14
0
def least_common_multiplier(k1, k2):

    lcm = (k1 * k2) / gcd(k1, k2)

    return lcm
def D_N_K_q_fixed_l(N, K, q, e_itkN_arr, e_itkl_2d_arr, gbc_con_expect_N_may_larger_than_K_fixed_l, print_option=False):

    main_term_for_D_N_q = 0
    error_term_for_D_N_q = 0  # not consider phase factor, add error together
    error_term_with_phase_for_D_N_q = 0  # consider error with phase factor, will have cancellation

    is_q_good = 0
    is_q_good_with_error_cancellation = 0

    l1 = 1
    l2 = (N - 1) % q

    assert gcd(l2, q) == 1

    for k in range(0, K):

        # sieg_walf can NOT be used when (q%K != 0)
        assert q % K == 0

        main_term_with_phase_l1, main_term_no_phase_l1, error_term_no_phase_l1, error_term_with_phase_l1 = s_k_N_q_l(
            k, K, N, q, l1, e_itkl_2d_arr
        )
        main_term_with_phase_l2, main_term_no_phase_l2, error_term_no_phase_l2, error_term_with_phase_l2 = s_k_N_q_l(
            k, K, N, q, l2, e_itkl_2d_arr
        )

        main_term_sum_square_k_N_q = main_term_with_phase_l1 * main_term_with_phase_l2
        error_term_sum_square_k_N_q = (
            main_term_no_phase_l1 * error_term_no_phase_l2
            + main_term_no_phase_l2 * error_term_no_phase_l1
            + error_term_no_phase_l1 * error_term_no_phase_l2
        )
        error_term_sum_square_with_phase_k_N_q = (
            main_term_with_phase_l1 * error_term_with_phase_l2
            + main_term_with_phase_l2 * error_term_with_phase_l1
            + error_term_with_phase_l1 * error_term_with_phase_l2
        )

        # when sum over k, main_term needs to adjust with phase factor
        e_itkN = e_itkN_arr[k]

        main_term_for_D_N_q += e_itkN * main_term_sum_square_k_N_q

        # for error term, we calculate in two different methods, including phase factors or not including phase factors.
        # error_term_with_phase_for_D_N_q will be smallest error we can get theoretically, so it will be
        # the lower bound. It will be something that we can try to reach.
        error_term_for_D_N_q += error_term_sum_square_k_N_q
        error_term_with_phase_for_D_N_q += e_itkN * error_term_sum_square_with_phase_k_N_q

    if print_option:
        print "N = ", N, ", q = ", q, ", l1 = ", l1, ", l2 = ", l2, ", main_term_for_D_N_q/K = ", main_term_for_D_N_q / K, ", error_term_for_D_N_q/K = ", error_term_for_D_N_q / K, ", error_term_with_phase_for_D_N_q = ", error_term_with_phase_for_D_N_q / K, ", gbc_con_expect_N_may_larger_than_K_fixed_l = ", gbc_con_expect_N_may_larger_than_K_fixed_l

    if main_term_for_D_N_q.real > error_term_for_D_N_q:
        is_q_good = 1
        if (main_term_for_D_N_q.real - error_term_for_D_N_q) > gbc_con_expect_N_may_larger_than_K_fixed_l:
            is_q_good = 2

    if main_term_for_D_N_q.real > error_term_with_phase_for_D_N_q.real:
        is_q_good_with_error_cancellation = 1
        if (
            main_term_for_D_N_q.real - error_term_with_phase_for_D_N_q.real
        ) > gbc_con_expect_N_may_larger_than_K_fixed_l:
            is_q_good_with_error_cancellation = 2

    return (
        main_term_for_D_N_q / K,
        error_term_for_D_N_q / K,
        is_q_good,
        error_term_with_phase_for_D_N_q,
        is_q_good_with_error_cancellation,
    )
def D_N_K_search_K_for_fixed_N_q_l_for_N_list(
    q, N_list, only_search_1st_k=True, K_start=6, K_end=400, print_option=False
):

    print "D_N_K_search_K_for_fixed_N_q_l,  K range(%d, %d), q = %d, tests start... " % (K_start, K_end, q)
    print "N_list = ", N_list

    N_K_good_list = []
    skip_N_list = []
    N_cnt = 0
    N_K_good_cnt = 0

    for N in N_list:

        # N only allow even number
        if N % 2 == 1:
            continue

        N_cnt += 1

        # we will be only interested in the case that l2 is co-prime with q
        l2 = (N - 1) % q
        if gcd(l2, q) != 1:
            skip_N_list.append(N)
            continue

        gbc_con_expect = gbc_con_6_upto_target[(N - 6) / 2][1]

        for K in range(K_start, K_end):

            # because of sieg_walf, q must be the multiplier of K
            if q % K != 0:
                continue

            e_itkN_arr = calculate_e_itkN_arr(K, N)
            e_itkl_2d_arr = calculate_e_itkl_2d_arr(K, q)

            # get D_N_K_q_fixed_l() and D_N_K_counting_direct_fixed_l()
            main_term_for_D_N_q_K, error_term_for_D_N_q_K, is_N_K_good, error_term_with_phase_for_D_N_q, is_q_good_with_error_cancellation = D_N_K_q_fixed_l(
                N, K, q, e_itkN_arr, e_itkl_2d_arr, gbc_con_expect, print_option=False
            )
            gbc_con_expect_N_may_larger_than_K_counting_direct_fixed_l = D_N_K_counting_direct_fixed_l(
                N, K, q, gbc_con_expect, l1=1, print_option=False
            )

            if print_option:
                print "***** N = ", N, ", K = ", K, "q = ", q, ",  main_term_for_D_N_q_K = ", main_term_for_D_N_q_K, ", gbc_con_expect_N_may_larger_than_K_counting_direct_fixed_l = ", gbc_con_expect_N_may_larger_than_K_counting_direct_fixed_l, ", gbc_con_expect = ", gbc_con_expect

            # we try to assert main_term_for_D_N_q_K.real <= gbc_con_expect_N_may_larger_than_K_counting_direct_fixed_l
            # but numerical round issues requires we loose the condition a bit. + 0.1 is needed in case that
            # gbc_con_expect_N_may_larger_than_K_counting_direct_fixed_l = 0
            # assert(main_term_for_D_N_q_K.real <= 1.1*(gbc_con_expect_N_may_larger_than_K_counting_direct_fixed_l + 0.1))

            if is_N_K_good > 0:
                N_K_good_list.append([N, K, q, main_term_for_D_N_q_K, error_term_for_D_N_q_K])
                if only_search_1st_k == True:
                    N_K_good_cnt += 1
                    break

    print "\nq = %d, l1 = 1, fixed: N_K_good_list.append([N, K, q, main_term_for_D_N_q_K, error_term_for_D_N_q_K]) = \n" % (
        q
    ), np.asarray(
        N_K_good_list
    )
    print "skip_N_list = ", skip_N_list
    failed_cnt = N_cnt - N_K_good_cnt - len(skip_N_list)
    print "N_cnt = %d, N_K_good_cnt %d, len(skip_N_list) = %d, failed_cnt = %d, q = %d" % (
        N_cnt,
        N_K_good_cnt,
        len(skip_N_list),
        failed_cnt,
        q,
    )
    print "D_N_K_search_K_for_fixed_N_q_l, K range(%d, %d), q = %d, fixed l1 = 1, done !" % (K_start, K_end, q)

    return N_cnt, N_K_good_cnt, skip_N_list, failed_cnt, N_K_good_list
def gbc_discre_for_N_K_Q_fixed_l(N, K, Q, l1=1):

    print "N = ", N, ", K = ", K, ", Q = ", Q

    e_itkN_arr = calculate_e_itkN_arr(K, N)

    print gbc_con_6_upto_target[(N - 6) / 2]
    gbc_con_expect = gbc_con_6_upto_target[(N - 6) / 2][1]
    assert gbc_con_6_upto_target[(N - 6) / 2][0] == N
    print "N = %d, gbc_con_expect = %d" % (N, gbc_con_expect)

    # q_good_list[] will hold a set of q ( 2 <= q <= Q) and
    q_good_list = []

    q = Q

    # For easy counting, D_N_K_q_2d_arr include q = 0, q =1, which are always 0
    # and it will go up to q (include q).
    Shape = [q + 1, 3]
    D_N_K_q_2d_arr = np.zeros(Shape, dtype=np.complex64)

    # record main term, error term, and gbc_con_expect_N_may_larger_than_K_fixed_l for every q with fixed l
    main_term_arr = np.zeros(q + 1, dtype=np.complex64)
    error_term_arr = np.zeros(q + 1, dtype=np.complex64)
    gbc_con_expect_N_may_larger_than_K_fixed_l_arr = np.zeros(q + 1, dtype=np.complex64)

    for q in range(2, Q + 1):

        l2 = (N - 1) % q

        # if (N-1)%q is not co-prime with q, this will make things complicated if we try to find out a good
        # model for it, let's skip such q for now.
        if gcd(l2, q) != 1:
            continue

        # sieg_walf can NOT be used when (q%K != 0)
        if q % K != 0:
            continue

        e_itkl_2d_arr = calculate_e_itkl_2d_arr(K, q)

        # get gbc_con directly by counting. This function allows N > K and N <= K
        gbc_con_expect_N_may_larger_than_K_fixed_l = D_N_K_counting_direct_fixed_l(
            N, K, q, gbc_con_expect, l1, print_option=False
        )

        main_term_for_D_N_q, error_term_for_D_N_q, is_q_good, error_term_with_phase_for_D_N_q, is_q_good_with_error_cancellation = D_N_K_q_fixed_l(
            N, K, q, e_itkN_arr, e_itkl_2d_arr, gbc_con_expect_N_may_larger_than_K_fixed_l
        )
        D_N_K_q_2d_arr[q][0] = main_term_for_D_N_q
        D_N_K_q_2d_arr[q][1] = error_term_for_D_N_q
        D_N_K_q_2d_arr[q][2] = is_q_good

        main_term_arr[q] = main_term_for_D_N_q
        error_term_arr[q] = error_term_for_D_N_q
        gbc_con_expect_N_may_larger_than_K_fixed_l_arr[q] = gbc_con_expect_N_may_larger_than_K_fixed_l

        if is_q_good > 0:
            q_good_list.append([q, main_term_for_D_N_q, error_term_for_D_N_q])

    # plotting
    plt.figure()
    q_range = range(0, Q + 1)
    plot_one_list(main_term_arr.real, "main_term_arr.real", q_range, "ro-")
    plot_one_list(error_term_arr.real, "error_term_arr.real", q_range, "bx-")
    plot_one_list(
        gbc_con_expect_N_may_larger_than_K_fixed_l_arr.real,
        "gbc_con_expect_N_may_larger_than_K_fixed_l_arr.real",
        q_range,
        "gd-",
    )
    title_str = (
        "D_N_K_q_fixed_l: main: Red, error: blue, gbc_con_expect_fixed_l, green, gbc_con_expect = %d, N = %d, K = %d, Q = %d"
        % (gbc_con_expect, N, K, Q)
    )
    plt.title(title_str)
    plt.xlabel("q range")
    plt.show(block=False)
예제 #18
0
def abc_xyz(n, ab_search_range_start = 2, ab_search_range_end = 10, xy_power_range_start = 2, xy_power_range_end = 10, only_co_prime = 0, x_same_y = 0, abc_odd_option = 0):

    found_list = []
    find_item = [0]*6

    total_loop_cnt = 0

    global     skip_cnt_for_c_not_include_all_prime_factors_of_a_b

    if (xy_power_range_start > min_power_3):
        min_power = xy_power_range_start

    else:
        min_power = min_power_3

    for a in range(ab_search_range_start, ab_search_range_end):

        # if we are only interested in a, b, c are all odd
        if(abc_odd_option == 7) and (a%2 == 0):
            continue

        for x in range(min_power, xy_power_range_end):

            a_x = power_mod(a, x, n)

            # we only need to consider b>= a,
            # so that we will only count 3^3 + 6^3 = 3^5, not count
            # 6^3 + 3^3 = 3^5
            for b in range(a, ab_search_range_end):

                # if we are only interested in a, b, c are all odd
                if(abc_odd_option == 7) and (b%2 == 0):
                    continue

                # if we are interested in at least one of a, b is odd
                if(abc_odd_option == 1) and (a%2 == 0) and (b%2 != 1):
                    continue

                ab_gcd = gcd(a, b)

                for y in range(min_power, xy_power_range_end):
                        
                        # if x_same_y flag is set, we will only handle the case y = x
                        # In fact, it will be better if we just let y = x and not go into this 
                        # loop, but because y range is not much, so that will not be too much wasted.
                        if(x_same_y == 1) and (y != x):
                            continue
                            
                        b_y = power_mod(b, y, n)

                        # need a better algorithm to find a range for c
                        c_range = 6*(a + b)

                        for c in range(2, c_range):

                            # if we are only interested in a, b, c are all odd
                            if(abc_odd_option == 7) and (c%2 == 0):
                                continue

                            # skip obvious no-solution case
                            # if a, b has gcd factor (ab_gcd) which is larger than 1.
                            # and ab_gcd has prime factor p1, p2, ..pr
                            # then c must also contain those prime factors
                            if(ab_gcd > 1):

                                # Note: not sure if the following check will speed up program
                                # because it involve factoring a number, which can be slow.
                                # But if we have large z range, this will help.
                                # Plus, it will also reduce the memory to save initial list.
                                ret = check_c_contain_prime_factors_of_ab_gcd(ab_gcd, c)

                                # c does not contain all prime factors of ab_gcd,
                                # we need to skip this c.
                                if (ret == 0):
                                    skip_cnt_for_c_not_include_all_prime_factors_of_a_b += 1
                                    continue

                            # if only check co_prime, then, we will skip those numbers
                            # which are not co_primes
                            if(only_co_prime == 1):
                                abc_gcd = gcd_for_three_numbers(a, b, c)
                                
                                if(abc_gcd > 1):
                                    continue

                            # it can happen that z_start > z_end in case z_end = 2
                            # in this case, we just skip the z loop
                            z_start, z_end = get_range_for_z(a, x, b, y, c, min_power)

                            for z in range(z_start, z_end):
                                c_z = power_mod(c, z, n)

                                tmp = a_x + b_y - c_z

                                # found one, (tmp %n) == 0 is natural for mod(n)
                                if((tmp %n) == 0):

                                    # do additional filtering, this will reduce memory usage
                                    # needed for initial list saving.
                                    if(additional_filtering(tmp, initial_mod)):

                                        print 'a = %4d, x = %4d, b = %4d, y = %4d, c = %4d, z = %4d'%(a, x, b, y, c, z)

                                        find_item[0]=a
                                        find_item[1]=x
                                        find_item[2]=b
                                        find_item[3]=y
                                        find_item[4]=c
                                        find_item[5]=z

                                        tmp_arr = deepcopy(find_item)
                                        found_list.append(tmp_arr)
                                        # found_list.append(find_item)

                                total_loop_cnt += 1

    total_cnt = len(found_list)
    print '================== n = %5d, total_cnt = %10d ========================='%(n, total_cnt)

    return found_list, total_cnt, total_loop_cnt
예제 #19
0
def check_jacob_symb_vs_quadr_recip(n, prime_list):

    print '=============== check_jacob_symb_vs_quadr_recip for up to n = %d'%(n)

    total_cnt = 0

    # when jacob_symb is not proper indicator or quadr_recip.
    # We seperate them into type 1 or type 2
    not_qr_indicator_type_1_cnt = 0
    not_qr_indicator_type_2_cnt = 0

    # only loop through odd integers,
    # because jacob_symb was only defined for odd prime number, not include 2
    for p in xrange(3, n, 2):
        for q in range(3, n, 2):

            if(p == q):
                continue

            if(gcd(p, q) >1):
                continue

            jacob_p_q = jacob_sym(p, q, prime_list)
            jacob_q_p = jacob_sym(q, p, prime_list)

            total_cnt += 1

            # brute force way to check quard_recip
            qr_bf_p_q = get_quadr_recip_brute_force(p, q)
            qr_bf_q_p = get_quadr_recip_brute_force(q, p)

            tmp = p_1_q_1_divide_by_4(p, q)

            if(tmp%2 == 0):
                right_side = 1
            else:
                right_side = -1

            # assert (p|q)(q|p) == (-1)^((p-1)*(q - 1)/4)
            assert(right_side == jacob_p_q*jacob_q_p)

            # Note 1: For jacob, it could happen that jacob(q|n) == 1, while q is not quadr_recip of n, when n is composite number.
            # Note 2: For jacob, if quadr_recip = 1,  jacob(q | n) must be 1
            #                    if quadr_recip = -1, jacob(q | n) can be 1 or -1
            #                    if jacob(q | n) = 1, quadr_recip can be 1 or -1
            #                    if jacob(q | n) = -1, quadr_recip must -1
            if( qr_bf_p_q  == 1):
                assert(jacob_p_q == 1)

            if( jacob_p_q == -1):
                assert(qr_bf_p_q == -1)

            # if qr_bf_p_q == -1, but jacob_p_q = 1, which means jacob_symp not an indicator of quadr_recip
            if(qr_bf_p_q == -1):                
                if(jacob_p_q != -1):
                    not_qr_indicator_type_1_cnt += 1                    
                    # print ' : p = %d, q = %d, qr_bf_p_q = %d, jacob_p_q = %d'%(p, q, qr_bf_p_q, jacob_p_q)

            # if jacob_p_q == 1, but qr_bf_p_q = -1, which means jacob_symp not an indicator of quadr_recip
            if(jacob_p_q == 1):
                if(qr_bf_p_q != 1):
                    not_qr_indicator_type_2_cnt += 1
                    # print ' : p = %d, q = %d, qr_bf_p_q = %d, jacob_p_q = %d'%(p, q, qr_bf_p_q, jacob_p_q)

    not_qr_indicator_cnt = not_qr_indicator_type_1_cnt + not_qr_indicator_type_2_cnt
    not_qr_indictor_ratio = float(not_qr_indicator_cnt)/total_cnt

    print 'check_jacob_symb_vs_quadr_recip, n = ', n, ', total_cnt = ', total_cnt,  ', not_qr_indicator_type_1_cnt = ', not_qr_indicator_type_1_cnt, ',not_qr_indicator_type_2_cnt = ',not_qr_indicator_type_2_cnt
    print 'check_jacob_symb_vs_quadr_recip, n = ', n, ', not_qr_indictor_ratio = ', not_qr_indictor_ratio

    return not_qr_indictor_ratio