def next_prime_not_dividing(P, I): while True: p = P.smallest_integer() if p == 1: Q = F.ideal(2) elif p % 5 in [2,3]: # inert Q = F.primes_above(next_prime(p))[0] elif p == 5: Q = F.ideal(7) else: # p split A = F.primes_above(p) if A[0] == P: Q = A[1] else: Q = F.primes_above(next_prime(p))[0] if not Q.divides(I): return Q else: P = Q # try again
def find_mod2_splitting(): """ Return elements w0, w1, w2, w3 that determine a mod-2 splitting of the Hamilton quaternion algebra over Q(sqrt(5)). OUTPUT: - four 2x2 matrices over the residue field of Q(sqrt(5)) of order 4. EXAMPLES:: sage: import sage.modular.hilbert.sqrt5_fast_python sage: w = sage.modular.hilbert.sqrt5_fast_python.find_mod2_splitting(); w ( [ 1 abar] [ 0 abar + 1] [abar + 1 abar] [1 1] [abar + 1 0], [ abar 0], [ abar abar + 1], [0 1] ) sage: w[1]^2, w[2]^2 ( [1 0] [1 0] [0 1], [0 1] ) sage: span([vector(z.list()) for z in w]).dimension() 4 """ P = F.primes_above(2)[0] k = P.residue_field() M = MatrixSpace(k,2) V = k**4 g = k.gen() # image of golden ratio m1 = M(-1) sqrt_minus_1 = [(w, V(w.list())) for w in M if w*w == m1] one = M(1) v_one = V(one.list()) for w1, v1 in sqrt_minus_1: for w2, v2 in sqrt_minus_1: w0 = (g-1)*(w1+w2 - w1*w2) w3 = g*w0 + w2*w1 if w0*w0 != w0 - 1: continue if w3*w3 != -1: continue if V.span([w0.list(),v1,v2,w3.list()]).dimension() == 4: return w0, w1, w2, w3
def find_mod2pow_splitting(i): P = F.primes_above(2)[0] if i == 1: R = ResidueRing(P, 1) M = MatrixSpace(R, 2) return [M(matrix_lift(a).list()) for a in find_mod2_splitting()] R = ResidueRing(P, i) M = MatrixSpace(R, 2) # arbitrary lift wbar = [M(matrix_lift(a).list()) for a in find_mod2pow_splitting(i - 1)] # Find lifts of wbar[1] and wbar[2] that have square -1 k = P.residue_field() Mk = MatrixSpace(k, 2) t = 2**(i - 1) s = M(t) L = [] for j in [1, 2]: C = Mk(matrix_lift(wbar[j]**2 + M(1)) / t) A = Mk(matrix_lift(wbar[j])) # Find all matrices B in Mk such that AB+BA=C. L.append([ wbar[j] + s * M(matrix_lift(B)) for B in Mk if A * B + B * A == C ]) g = M(F.gen()) t = M(t) two = M(2) ginv = M(F.gen()**(-1)) for w1 in L[0]: for w2 in L[1]: w0 = ginv * (two * g * wbar[3] - w1 - w2 - w1 * w2) w3 = g * w0 + w2 * w1 if w0 * w0 != w0 - M(1): continue if w3 * w3 != M(-1): continue return w0, w1, w2, w3 raise ValueError
def find_mod2pow_splitting(i): P = F.primes_above(2)[0] if i == 1: R = ResidueRing(P, 1) M = MatrixSpace(R, 2) return [M(matrix_lift(a).list()) for a in find_mod2_splitting()] R = ResidueRing(P, i) M = MatrixSpace(R, 2) # arbitrary lift wbar = [M(matrix_lift(a).list()) for a in find_mod2pow_splitting(i - 1)] # Find lifts of wbar[1] and wbar[2] that have square -1 k = P.residue_field() Mk = MatrixSpace(k, 2) t = 2 ** (i - 1) s = M(t) L = [] for j in [1, 2]: C = Mk(matrix_lift(wbar[j] ** 2 + M(1)) / t) A = Mk(matrix_lift(wbar[j])) # Find all matrices B in Mk such that AB+BA=C. L.append([wbar[j] + s * M(matrix_lift(B)) for B in Mk if A * B + B * A == C]) g = M(F.gen()) t = M(t) two = M(2) ginv = M(F.gen() ** (-1)) for w1 in L[0]: for w2 in L[1]: w0 = ginv * (two * g * wbar[3] - w1 - w2 - w1 * w2) w3 = g * w0 + w2 * w1 if w0 * w0 != w0 - M(1): continue if w3 * w3 != M(-1): continue return w0, w1, w2, w3 raise ValueError
def find_mod2_splitting(): P = F.primes_above(2)[0] k = P.residue_field() M = MatrixSpace(k, 2) V = k ** 4 g = k.gen() # image of golden ratio m1 = M(-1) sqrt_minus_1 = [(w, V(w.list())) for w in M if w * w == m1] one = M(1) v_one = V(one.list()) for w1, v1 in sqrt_minus_1: for w2, v2 in sqrt_minus_1: w0 = (g - 1) * (w1 + w2 - w1 * w2) w3 = g * w0 + w2 * w1 if w0 * w0 != w0 - 1: continue if w3 * w3 != -1: continue if V.span([w0.list(), v1, v2, w3.list()]).dimension() == 4: return w0, w1, w2, w3
def find_mod2_splitting(): P = F.primes_above(2)[0] k = P.residue_field() M = MatrixSpace(k, 2) V = k**4 g = k.gen() # image of golden ratio m1 = M(-1) sqrt_minus_1 = [(w, V(w.list())) for w in M if w * w == m1] one = M(1) v_one = V(one.list()) for w1, v1 in sqrt_minus_1: for w2, v2 in sqrt_minus_1: w0 = (g - 1) * (w1 + w2 - w1 * w2) w3 = g * w0 + w2 * w1 if w0 * w0 != w0 - 1: continue if w3 * w3 != -1: continue if V.span([w0.list(), v1, v2, w3.list()]).dimension() == 4: return w0, w1, w2, w3
def next_prime_of_characteristic_coprime_to(P, I): p = next_prime(P.smallest_integer()) N = ZZ(I.norm()) while N%p == 0: p = next_prime(p) return F.primes_above(p)[0]
def find_mod2pow_splitting(i): """ Return elements w0, w1, w2, w3 that determine a mod-`2^i` splitting of the Hamilton quaternion algebra over Q(sqrt(5)). INPUT: - `i` -- positive integer OUTPUT: - four 2x2 matrices over a residue ring of Q(sqrt(5)) of characteristic a power of 2 EXAMPLES:: sage: import sage.modular.hilbert.sqrt5_fast_python sage: w = sage.modular.hilbert.sqrt5_fast_python.find_mod2pow_splitting(1); w ( [ 1 g] [ 0 1 + g] [1 + g g] [1 1] [1 + g 0], [ g 0], [ g 1 + g], [0 1] ) sage: w = sage.modular.hilbert.sqrt5_fast_python.find_mod2pow_splitting(2); w ( [ 3 2 + 3*g] [ 0 1 + 3*g] [3 + 3*g 3*g] [ 1 + g 2], [ g 0], [ 3*g 1 + g], [3 + 2*g 3 + 2*g] [ 2 1 + 2*g] ) sage: w[1]^2 [3 0] [0 3] sage: w[2]^2 [3 0] [0 3] sage: w = sage.modular.hilbert.sqrt5_fast_python.find_mod2pow_splitting(4) sage: w[1]^2 [15 0] [ 0 15] sage: w[2]^2 [15 0] [ 0 15] sage: w[1], w[2] ( [ 0 1 + 15*g] [15 + 15*g 12 + 7*g] [ g 0], [ 4 + 11*g 1 + g] ) TESTS: The power must be positive:: sage: sage.modular.hilbert.sqrt5_fast_python.find_mod2pow_splitting(0) Traceback (most recent call last): ... ValueError: i must be positive """ P = F.primes_above(2)[0] i = ZZ(i) if i <= 0: raise ValueError, "i must be positive" if i == 1: R = ResidueRing(P, 1) M = MatrixSpace(R,2) return tuple([M(matrix_lift(a).list()) for a in find_mod2_splitting()]) R = ResidueRing(P, i) M = MatrixSpace(R,2) # arbitrary lift wbar = [M(matrix_lift(a).list()) for a in find_mod2pow_splitting(i-1)] # Find lifts of wbar[1] and wbar[2] that have square -1 k = P.residue_field() Mk = MatrixSpace(k, 2) t = 2**(i-1) s = M(t) L = [] for j in [1,2]: C = Mk(matrix_lift(wbar[j]**2 + M(1)) / t) A = Mk(matrix_lift(wbar[j])) # Find all matrices B in Mk such that AB+BA=C. L.append([wbar[j]+s*M(matrix_lift(B)) for B in Mk if A*B + B*A == C]) g = M(F.gen()) t = M(t) two = M(2) ginv = M(F.gen()**(-1)) for w1 in L[0]: for w2 in L[1]: w0 = ginv*(two*g*wbar[3] -w1 -w2 - w1*w2) w3 = g*w0 + w2*w1 if w0*w0 != w0 - M(1): continue if w3*w3 != M(-1): continue return w0, w1, w2, w3 raise ValueError