def try_all_beals(lim=1000):
    
    populate_all()
    
    #b is in the primes since composite moduli don't have primitve roots.  Techincally, b could be in the prime powers or 2p^k, but the first is redundant for this application while the second isn't satisfied since b must be a power greater than two
    for b in prob_primes:
        
        print(b)        
        b_gp = get_gen_psq(b)
        
        for a in range(3, lim):
            if is_gen_n_k(a, b, all_fact[b]):            
                for c in range(3, lim):
                    if odd_num_evens(a, b, c) and is_coprime(a, c) and is_coprime(b, c):
                        for z in range(3, lim):
                            r = beals_solver(a, b, c, z, b_gp)
                            
                            #print(a, b, c, z)
                            
                            if r[2][0]:
                                if r[0] > 2 and r[1] > 2:
                                    print("\t!!!!{!s}^{!s} {} {!s}^{!s} = {!s}^{!s}!!!!".format(a, r[0], r[2][1], b, r[1], c, z))
                                    #wait = input("\tPossible solution found.  Press enter to continue.")
                                elif r[0] > 1 and r[1] > 1 and max(r[0], r[1]) > 2:
                                    print("\t{!s}^{!s} {} {!s}^{!s} = {!s}^{!s}".format(a, r[0], r[2][1], b, r[1], c, z))
def get_gen_psq(x):
    
    gen_prime_sq = []
    
    for i, pprime in enumerate(prob_primes):
        if is_gen_n_k(x, pprime, all_fact[pprime]):
            gen_prime_sq.append([pprime, pprime**2, prime_sq_fact[i][0], [pprime, 1]])

    return gen_prime_sq
def test_beals_solver(n_tests=100):
    
    populate_all()
    
    num_pp = len(prob_primes)
    num_af = len(all_fact)
    
    print("Beginning {!s} tests of Beals Solver...".format(n_tests))
    
    while (n_tests > 0):
        
        a = randrange(num_af)
        b = prob_primes[randrange(num_pp)]
        
        if is_gen_n_k(a, b, all_fact[b]):
            x = randrange(num_af)
            
            #need to ensure that y is large enough that phi(b^y) > x
            min_y = tot_cover(b, num_af)
            y = randrange(min_y, num_af)
            
            ax = a**x
            by = b**y
            
            if randrange(0, 2):
                c = ax + by
                s = '+'
            else:
                c = ax - by
                
                if c < 0:
                    continue
                else:
                    s = '-'
        
            b_gp = get_gen_psq(b)
            
            #print("\Solving {!s}^{!s} {!s} {!s}^{!s}...".format(a, x, s, b, y))
            r = beals_solver(a, b, c, 1, b_gp)
            
            assert r[0] == x and r[1] == y and r[2][0] and r[2][1] == s
            
            n_tests -= 1
            
    print("All tests passed!")            
def get_y(a, x, c, z, b, lrab, max_yc):
    
    y_res_mod = []
    
    max_ya = x * lrab
    max_y = max(max_ya, max_yc)
    
    p = 1
    mr = MontgomeryReduction()
    
    for i, pprime in enumerate(prob_primes):
        if is_gen_n_k(b, pprime, all_fact[pprime]): 
            m = pprime**2
            
            #squaring ensures totient is divisible by prime
            mr.set_modulus(m, prime_sq_fact[i])
                    
            ra, rc, rb = mr.convert(a), mr.convert(c), mr.convert(b)
            rax, rcz = mr.exp(ra, x), mr.exp(rc, z)
            
            rd = (rax - rcz) % m
            
            if is_coprime(rd, m):                
                y_sp = mr.dlog_mod(rb, rd, [pprime, 1])
                y_res_mod.append([y_sp, pprime])
                
                p *= pprime
                
                if p > max_y:
                    break
    else:
        ipdb.set_trace()
        print("Not enough primes to get y")
        #raise Error("Not enough primes to get y")
    
    return crt(y_res_mod)