Beispiel #1
0
def abc_xyz_recur(n, prev_found_list, prev_total_cnt, new_found_list):

    # this function shall not be called if prev_total_cnt is zero
    assert(prev_total_cnt > 0)

    # j will be used to hold item in new found_list
    j = 0

    for i in range(prev_total_cnt):

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

        a_x = power_mod(a, x, n)
        b_y = power_mod(b, y, n)
        c_z = power_mod(c, z, n)

        tmp = a_x + b_y - c_z

        # found one which congruence to n
        if((tmp %n) == 0):
            
            print 'a = %4d, x = %4d, b = %4d, y = %4d, c = %4d, z = %4d'%(a, x, b, y, c, z)

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

            # move to next 
            j += 1

    # write the next line after the final line as watermark line, put some junk here.
    # this is ued to detect programming errors
    new_found_list[j][0]= -1
    new_found_list[j][1]= -1
    new_found_list[j][2]= -1
    new_found_list[j][3]= -1
    new_found_list[j][4]= -1
    new_found_list[j][5]= -1

    new_total_cnt = j
    print '======================== n = %5d, prev_total_cnt = %10d, new_total_cnt = %10d====================='%(n, prev_total_cnt, new_total_cnt)

    changed_flag = 0
    if(new_total_cnt != prev_total_cnt):
        changed_flag = 1

    return new_total_cnt, changed_flag
Beispiel #2
0
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
Beispiel #3
0
def eul_criter(n, p):

    i = (p - 1)/2
    n_p = power_mod(n, i, p)

    # power_mod(...) may return any number between 0, to p-1. For p-1, we want  to return -1 instead of p-1
    if(n_p > 1):
        n_p = n_p - p

    return n_p
Beispiel #4
0
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
Beispiel #5
0
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
Beispiel #6
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
Beispiel #7
0
def abc_fixed_xyz(n, a, b, c,  xy_power_range_start = 2, xy_power_range_end = 10,  x_same_y = 0):

    found_list = []
    find_item = [0]*6

    total_loop_cnt = 0

    if (xy_power_range_start > min_power_3):
        min_power = xy_power_range_start

    else:
        min_power = min_power_3

    for x in range(min_power, xy_power_range_end):

        # print 'x = %d'%(x)

        a_x = power_mod(a, x, n)

        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)

            # 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