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
def detect_primes_using_ster_broc_mat_format(start_num, end_num): if(start_num%2 == 1): print "--- detect_primes_using_ster_broc_mat_format(), start_num needs to be even ------------------------------------------" # b is even number, b_list = np.arange(start_num, end_num, 2, dtype = int) print b_list for b in b_list: # print b # we are only interested in the case tht a is odd number, and a is smaller than b # so that we will get a/b a_list = np.arange(3, b, 2, dtype = int) # print a_list # find coprimes of b cnt, coprime_list = eul_totie(b) # print coprime_list for a in a_list: if a in coprime_list: # get count_fract for the input fraction a/b cf_list = get_cont_fract(a, b) # get the matrix format for a/b cf_mat_list, ster_brot_mat, a_b = ster_brot_mat_format_for_cont_fract(cf_list) # we can print out finding # print cf_mat_list, ster_brot_mat, a_b if a in prime_list: sys.stdout.write("<================================== prime\n\n")
def F_N_a_q(MA_a_q_sorted_arr, N): print "MA_a_q_sorted_arr = ", MA_a_q_sorted_arr total_cnt = len(MA_a_q_sorted_arr) a_q_list = [] F_N_a_q_list = [] for i in range(total_cnt): a = MA_a_q_sorted_arr[i][0] q = MA_a_q_sorted_arr[i][1] a_q = float(a)/q u_q = mobi_list[q - 1] phi_q, coprime_list = eul_totie(q) F_N_a_q = N*float(u_q)/phi_q a_q_list.append(a_q) F_N_a_q_list.append(F_N_a_q) print "a_q_list = ", np.asarray(a_q_list) print "F_N_a_q_list = ", F_N_a_q_list return a_q_list, F_N_a_q_list
def prim_roots(n, smllest_only = True): phi_i, coprime_list = eul_totie(n) prim_root_list = [] # coprime_list include 1 as first element, skip it for g in coprime_list[1:]: for i in range(2, (phi_i + 1)): # g_power_i = int(round(np.power(g, i))) # g_power_i_mod_n = g_power_i%n g_power_i_mod_n = power_mod(g, i, n) if(g_power_i_mod_n == 1): # break i loop and go to another number if (i < phi_i): break # break i loop if (i == phi_i): prim_root_list.append(g) # print 'prim_root_list: n = ', n, ' g = ', g, ' i = ', i, ' g_power_i = ', g_power_i, ' g_power_i_mod_n = ', g_power_i_mod_n break # if only want to find smallest option is on, break the loop if we find one if(smllest_only == True): # if find smallest prim_root, break the loop if (len(prim_root_list) != 0): break return prim_root_list
def dirichi_char_for_n(n): prime_list = get_prime_list(n) factor_list = factor_a_number(n, prime_list) num_of_diff_primes = len(factor_list) # this will be a list of 2D matrix, each 2D matrix hold a dirich_char matrix for a prime dirich_char_mat_list =[] prim_char_stat_list = [] # handle all prime factor for i in range(0, num_of_diff_primes): p = factor_list[i][0] l = factor_list[i][1] dirich_char_p_mat, phi_p_l, coprime_list, prim_char_stat = dirich_char_power_p(p, l) print 'p = ', p, ', l = ', l, np.asarray(dirich_char_p_mat).shape dirich_char_mat_list.append(dirich_char_p_mat) prim_char_stat_list.append(prim_char_stat) print prim_char_stat # form a product of all of above matrix tmp_mat = np.eye(1) for i in range(0, num_of_diff_primes): tmp_mat = dirich_char_mat_product(tmp_mat, dirich_char_mat_list[i]) print 'n = ', n, ', matrix shape = ', np.asarray(tmp_mat).shape phi_p_n, coprime_list = eul_totie(n) # set initial default value for statistics count prim_char_stat_all = {} prim_char_stat_all['num_of_total_char'] = -1 prim_char_stat_all['num_of_prim_char'] = -1 prim_char_stat_all['num_of_non_prim_char'] = -1 # include principle char prim_char_stat_all['num_of_real_char'] = -1 num_of_total_char_all = 1 num_of_prim_char_all = 1 num_of_prim_char_real = 1 for i in range(0, num_of_diff_primes): num_of_total_char_all = num_of_total_char_all*prim_char_stat_list[i]['num_of_total_char'] num_of_prim_char_all = num_of_prim_char_all*prim_char_stat_list[i]['num_of_prim_char'] num_of_prim_char_real = num_of_prim_char_real*prim_char_stat_list[i]['num_of_real_char'] prim_char_stat_all['num_of_total_char'] = num_of_total_char_all prim_char_stat_all['num_of_prim_char'] = num_of_prim_char_all prim_char_stat_all['num_of_non_prim_char'] = num_of_total_char_all - num_of_prim_char_all prim_char_stat_all['num_of_real_char'] = num_of_prim_char_real print prim_char_stat_all return tmp_mat, phi_p_n, coprime_list, prim_char_stat_all
def verify_range_for_fixed_q(): for q in range(1, 100): phi_q, coprime_list = eul_totie(q) for m in range(1, 100): c_q_m = rama_sum_use_mobi(q, m) assert(c_q_m <= phi_q) print 'verify_range_for_fixed_q: pass ! '
def dirich_char_simple_simulation(n): # we include n = 1 for completeness, it is a trival character, it will fail the # assertion check in verify_orthogonality_simple for 1st column all be zero. if (n == 1): phi_n = 1 unit_roots=[1] coprime_list=[1] dirich_char_mat=np.eye(1) # this is a trival character, will fail assertion check for 1st column return dirich_char_mat, phi_n, unit_roots, coprime_list phi_n, coprime_list = eul_totie(n) # the order of roots are not guranteed, except 1st one will be 1. unit_roots = nth_unit_root(phi_n) print "unit_roots: ", unit_roots # initialize matrix with all zeros s = (phi_n, n) dirich_char_mat = np.zeros(s, dtype = np.complex64) # print dirich_char_mat # create number of row for i in range(phi_n): # pick a generate root, this will make sure each row will pick a different root # all together, there will be phi_n unit roots. Those roots are all different. generate_root = unit_roots[i] for j in range(n): # only when j in coprime_list, character not zero if j in coprime_list: # find the index of each coprime in coprime_list # because the way we order roots, # 1 will be return as pos_in_coprime_list = 0 pos_in_coprime_list = coprime_list.index(j) # we pick a root for each row, and get its power of i for other columns # we need to ensure X(1) = 1 for all characters. That is # dirich_char_mat[i, 1] = 1 # In the following, when j = 1, pos_in_coprime_list = 0, phi_n - pos_in_coprime_list = phi_n # root^phi_n will guranteed to be 1 for any unit root. # __WARNING__, this implementation is NOT a correct implementation of Dirich_char, # it is just a simulation dirich_char_mat[i, j] = np.power(generate_root, phi_n - pos_in_coprime_list) # if j is not co-prime, the column must be zero else: dirich_char_mat[i, j] = 0 return dirich_char_mat, phi_n, coprime_list
def verify_c_q_q_same_as_phi_q(): ALMOST_ZERO = 0.001 for q in range(1, 100): c_q_q = rama_sum_use_mobi(q, q) phi_q, coprime_list = eul_totie(q) assert(c_q_q == phi_q) print 'verify_c_q_q_same_as_phi_q(): pass ! '
def unit_test_dirich_char_simulation(n): print '\ndirich_char for n: ', n phi_i, coprime_list = eul_totie(n) unit_roots = nth_unit_root(phi_i) # print 'unit_roots = ', unit_roots dirich_char_mat, phi_n, coprime_list, prim_char_stat_all = dirich_char_simple_simulation(n) print dirich_char_mat verify_orthogonality_simple(dirich_char_mat, n, phi_i)
def detect_prime_pairs_using_ster_broc_mat_format_with_fix_denomi(fix_denomi): print '\n=== detect_prime_pairs_using_ster_broc_mat_format_with_fix_denomi = ', fix_denomi # a is odd number a_list = np.arange(3, fix_denomi, 2, dtype = int) b = fix_denomi # print a_list # find co-prime of b cnt, coprime_list = eul_totie(b) # print coprime_list display_option = False # a1 will be p for a1 in a_list: # we only need to check a in 1st half of a_list if(a1 > end_num/2): break # if a1 is a coprime of b if a1 in coprime_list: # get count_fract for the input fraction a/b a1_cf_list = get_cont_fract(a1, b) # get the matrix format for a1/b a1_cf_mat_list, a1_ster_brot_mat, a1_b = ster_brot_mat_format_for_cont_fract(a1_cf_list, display_option) # since we are only interested in p + q = N, which is a1 + a2 = b, # therefore, a2 = b - a1 a2 = b - a1 # get count_fract for the input fraction a2/b a2_cf_list = get_cont_fract(a2, b) # get the matrix format for a2/b a2_cf_mat_list, a2_ster_brot_mat, a2_b = ster_brot_mat_format_for_cont_fract(a2_cf_list, display_option) # if a1 and a2 both are primes if (a1 in prime_list) and (a2 in prime_list): print a1_cf_list, ", ", ", num_of_turns: ", len(a1_cf_list), ", num_of_prod: ", np.sum(a1_cf_list), ", ", a1_b, " <==== GBC" print a2_cf_list, ", ", ", num_of_turns: ", len(a2_cf_list), ", num_of_prod: ", np.sum(a2_cf_list), ", ", a2_b, " <==== GBC" else: print a1_cf_list, ", ", ", num_of_turns: ", len(a1_cf_list), ", num_of_prod: ", np.sum(a1_cf_list), ", ", a1_b print a2_cf_list, ", ", ", num_of_turns: ", len(a2_cf_list), ", num_of_prod: ", np.sum(a2_cf_list), ", ", a2_b print a1_ster_brot_mat print a2_ster_brot_mat
def get_bn(n, l): bn_found = -1 if(n%2 == 0): print 'get_bn only works for odd number' return bn_found if(l <= 2): print 'get_bn only works for l >= 3' return bn_found p_power_l = int(round(np.power(2, l))) # print 'l = ', l, ', p_power_l = ', p_power_l phi_p_l, coprime_list = eul_totie(p_power_l) up_bound = (phi_p_l)/2 bn_found_cnt = 0 for bn in range(1, up_bound + 1): tmp1 = int(round(np.power(-1, (n-1)/2))) tmp2 = power_mod(5, bn, p_power_l) tmp = tmp1*tmp2 if((n - tmp)%(p_power_l) == 0): bn_found = bn bn_found_cnt += 1 # if we do not break from here, we can check if the solution is unique # It turns out that solution is indeed unique break if (bn_found == -1): print 'get_bn fail for n ', n, ', l = ', l, ', p_power_l = ', p_power_l # according to theorem, this should never happen assert(0) # solution must be unique assert(bn_found_cnt == 1) # print 'get_bn: n ', n, ', l = ', l, ' bn = ', bn return bn_found
def indice_g_n(a, g, n): phi_n, coprime_list = eul_totie(n) indice = -1 # if a is NOT co-prime with n, if ((a in coprime_list ) == False): return indice for i in range(phi_n): b = power_mod(g, i, n) if(a%n == b): indice = i break return indice
def get_max_cheby_minus_x_phi_over_coprimes(x, q): phi_q, coprime_list = eul_totie(q) # cheby_mod_list will be list of list, 2D array cheby_mod_list = [] # let's calculate cheby_lst_for_a mod(q) 1st for a in range(q): # only calculate when a and q is coprime, this is needed, because # only these choice will get something similar to x/phi_q if a in coprime_list: # we use the cheby_fun_q_a_integer_use_saved_von_mang() instead of the following function # to speed up calculation. # cheby_list_for_a = cheby_fun_q_a_integer(x, q, a) # calculate von_mang every time. cheby_list_for_a = cheby_fun_q_a_integer_use_saved_von_mang(x, q, a) # use cached von_mang tmp = deepcopy(cheby_list_for_a) cheby_mod_list.append(tmp) num_of_coprimes = len(coprime_list) cheby_minus_x_phi_max = [] for i in range(x): # initialize largest for each a, in the follow, i is actual x in # analytic formula, we just need to do (i+1) because array count start from 0 x_phi_q = float(i + 1)/phi_q largest = np.absolute(cheby_mod_list[0][i] - x_phi_q ) # loop for 1<= a <= q, (a, q) = 1 for a in range(num_of_coprimes): tmp = np.absolute(cheby_mod_list[a][i] - x_phi_q) if(tmp > largest): largest = tmp cheby_minus_x_phi_max.append(largest) return cheby_minus_x_phi_max
def get_max_cheby_minus_x_phi_fast_simulation(x, q): print 'get_max_cheby_minus_x_phi use fast simulation. x = %d, q = %d'%(x, q) phi_q, coprime_list = eul_totie(q) a = 1 cheby_list_for_a = cheby_fun_q_a_integer_use_saved_von_mang(x, q, a) cheby_minus_x_phi_max = [] for i in range(x): # initialize largest for each a, in the follow, i is actual x in # analytic formula, we just need to do (i+1) because array count start from 0 x_phi_q = float(i + 1)/phi_q largest = np.absolute(cheby_list_for_a[i] - x_phi_q ) cheby_minus_x_phi_max.append(largest) return cheby_minus_x_phi_max
def F_N_x(MA_a_q_sorted_arr, MajorA_2d_sorted_arr, N, step): print "MA_a_q_sorted_arr = ", MA_a_q_sorted_arr total_cnt = len(MA_a_q_sorted_arr) a_q_x_list = [] F_N_a_q_x_list = [] total_point_cnt = 0 for i in range(total_cnt): a = MA_a_q_sorted_arr[i][0] q = MA_a_q_sorted_arr[i][1] a_q = float(a)/q arc_start = MajorA_2d_sorted_arr[i][0] arc_end = MajorA_2d_sorted_arr[i][1] assert(a_q >= arc_start ) and (a_q <= arc_end) u_q = mobi_list[q - 1] phi_q, coprime_list = eul_totie(q) arc_split_arr = np.arange(arc_start, arc_end, step ) for x in arc_split_arr: beta = x - a_q F_N_a_q_x = u_beta(beta, N)*float(u_q)/phi_q a_q_x_list.append(x) F_N_a_q_x_list.append(F_N_a_q_x) total_point_cnt += 1 # print "a_q_x_list = ", a_q_x_list # print "F_N_a_q_x_list = ", F_N_a_q_x_list print 'F_N_x, total_point_cnt = ', total_point_cnt return a_q_x_list, F_N_a_q_x_list
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
def dirich_char_power_2(l): # set initial default value for statistics count prim_char_stat = {} prim_char_stat['num_of_total_char'] = -1 prim_char_stat['num_of_prim_char'] = -1 prim_char_stat['num_of_non_prim_char'] = -1 # include principle char prim_char_stat['num_of_real_char'] = -1 # hardcode when l = 1 if (l == 1): phi_p_l = 1 p_power_l = 2 s = (phi_p_l, p_power_l) dirich_char_mat = np.zeros(s, dtype = np.complex64) dirich_char_mat[0][0] = 0 dirich_char_mat[0][1] = 1 coprime_list=[1] prim_char_stat['num_of_total_char'] = 1 prim_char_stat['num_of_prim_char'] = 1 # only one character, it is principle char and also prim char prim_char_stat['num_of_non_prim_char'] = 1 # include principle char prim_char_stat['num_of_real_char'] = 1 # hardcode when l = 2 if (l == 2): phi_p_l = 2 p_power_l = 4 s = (phi_p_l, p_power_l) dirich_char_mat = np.zeros(s, dtype = np.complex64) dirich_char_mat[0] = [0, 1, 0, 1] dirich_char_mat[1] = [0, 1, 0, -1] coprime_list=[1, 3] prim_char_stat['num_of_total_char'] = 2 prim_char_stat['num_of_prim_char'] = 1 # WARNING: we set this to 1 for future muliptilcation prim_char_stat['num_of_non_prim_char'] = 1 # include principle char prim_char_stat['num_of_real_char'] = 2 return dirich_char_mat, phi_p_l, coprime_list, prim_char_stat if (l >= 3): p_power_l = int(round(np.power(2, l))) phi_p_l, coprime_list = eul_totie(p_power_l) # dirich_char_mat is 2D matrix, shape: phi_p_l, p_power_l. # for example, in case l = 6, p_power_l = 2^6 = 32, phi_p_l = 16 # all even columns 0, 2,..., will be zero s = (phi_p_l, p_power_l) dirich_char_mat = np.zeros(s, dtype = np.complex64) print 'p = ', 2, ', l = ', l, ' phi_p_l = ', phi_p_l, ' , p_power_l = ', p_power_l num_of_prim_char = 0 num_of_total_char = 0 # a only can be 0 or 1 for a in range(0, 2): # c can be 0, 1, 2, ..., phi/2 - 1, we choose this instead of # c can be 1, 2, ,,, phi/2 so that principle character will be on 1st row for c in range(0, (phi_p_l/2)): # row index of matrix. row_index = a*phi_p_l/2 + c for n in range(p_power_l): # will find value for all odd n if(n%2 == 1): # use the formula in hua's book. # Apost book, Kalachuba book have same formula # bn = get_bn(n, l) # do calculation at run time bn = get_bn_from_saved(n, l) # get bn_from_saved tmp1 = int(round(np.power(-1, ((n-1)*a)/2))) tmp2 = int(round(np.power(2, l-2))) tmp3 = 1j*np.pi*2*bn*c/tmp2 tmp4 = np.exp(tmp3) # print 'n = ', n, ' bn = ', bn, 'a = ', a, 'c = ', c, ' tmp1 = ', tmp1, ', tmp2 = ', tmp2, ' tmp3 = ', tmp3, ' tmp4 = ', np.asarray(tmp4) dirich_char_mat[row_index][n] = tmp1*tmp4 # count prim_character # Xa,c(n) is a prim_char if and only if (c%2) != 0, in other words, c is odd if((c%2) != 0): num_of_prim_char += 1 num_of_total_char += 1 # prim_char_stat counting prim_char_stat['num_of_total_char'] = num_of_total_char prim_char_stat['num_of_prim_char'] = num_of_prim_char prim_char_stat['num_of_non_prim_char'] = num_of_total_char - num_of_prim_char # include principle char prim_char_stat['num_of_real_char'] = 4 # according to theory return dirich_char_mat, phi_p_l, coprime_list, prim_char_stat
def dirich_char_power_p(p, l): # p == 2 need special handling, we process it and return if(p == 2): dirich_char_mat, phi_p_l, coprime_list, prim_char_stat = dirich_char_power_2(l) return dirich_char_mat, phi_p_l, coprime_list, prim_char_stat # if p not 2, p_power_l = int(round(np.power(p, l))) phi_p_l, coprime_list = eul_totie(p_power_l) print 'p = ', p, ', l = ', l, ' phi_p_l = ', phi_p_l, ' , p_power_l = ', p_power_l # set initial default value for statistics count prim_char_stat = {} prim_char_stat['num_of_total_char'] = -1 prim_char_stat['num_of_prim_char'] = -1 prim_char_stat['num_of_non_prim_char'] = -1 # include principle char prim_char_stat['num_of_real_char'] = -1 num_of_prim_char = 0 num_of_total_char = 0 num_of_non_prim_char = 0 # __WARNING__ we do NOT need this anymore, because we pre-calculate indn # get smallest prim root for p_power_l, # g_list = prim_roots(p_power_l, smllest_only = True) # g = g_list[0] s = (phi_p_l, p_power_l) dirich_char_mat = np.zeros(s, dtype = np.complex64) # a's value 0, 1,, 2, ,,,, phi_p_l - 1, # Note: in Hua's book, it uses, 1, 2, phi_p_l, # we choose above setting so that principle character will be 1st row of matrix. for a in range(0, phi_p_l): for n in range(p_power_l): # will find value for all co-prime with n if n in coprime_list: # The following is the normal way to get indn # we optimize it by pre-calculate all indn agaist smallest prim root # indn = indice_g_n(n, g, p_power_l) # indn is calculated against the smallest prim root of p_power_l indn = get_indice_from_saved(n, p_power_l) # use the formula in hua's book. tmp1 = 1j*np.pi*2*a*indn/phi_p_l tmp2 = np.exp(tmp1) dirich_char_mat[a][n] = tmp2 # a character is non-prim if and only if p|a if((a%p) == 0): num_of_non_prim_char += 1 num_of_total_char += 1 num_of_prim_char = num_of_total_char - num_of_non_prim_char prim_char_stat['num_of_total_char'] = num_of_total_char prim_char_stat['num_of_prim_char'] = num_of_prim_char prim_char_stat['num_of_non_prim_char'] = num_of_non_prim_char # include principle char prim_char_stat['num_of_real_char'] = 2 # according to theory return dirich_char_mat, phi_p_l, coprime_list, prim_char_stat