def class_nr_pos_def_qf(D): r""" Compute the class number of positive definite quadratic forms. For fundamental discriminants this is the class number of Q(sqrt(D)), otherwise it is computed using: Cohen 'A course in Computational Algebraic Number Theory', p. 233 """ if D>0: return 0 D4 = D % 4 if D4 == 3 or D4==2: return 0 K = QuadraticField(D) if is_fundamental_discriminant(D): return K.class_number() else: D0 = K.discriminant() Df = ZZ(D).divide_knowing_divisible_by(D0) if not is_square(Df): raise ArithmeticError("Did not get a discrimimant * square! D={0} disc(D)={1}".format(D,D0)) D2 = sqrt(Df) h0 = QuadraticField(D0).class_number() w0 = _get_w(D0) w = _get_w(D) #print "w,w0=",w,w0 #print "h0=",h0 h = 1 for p in prime_divisors(D2): h = QQ(h)*(1-kronecker(D0,p)/QQ(p)) #print "h=",h #print "fak=", h=QQ(h*h0*D2*w)/QQ(w0) return h
def _pell_solve_1(D,m): # m^2 < D root_d = Integer(floor(sqrt(D))) a = Integer(floor(root_d)) P = Integer(0) Q = Integer(1) p = [Integer(1),Integer(a)] q = [Integer(0),Integer(1)] i = Integer(1) x0 = Integer(0) y0 = Integer(0) prim_sols = [] test = Integer(0) while not (Q == 1 and i%2 == 1) or i == 1: test = p[i]**2 - D* (q[i]**2) if test == 1: x0 = p[i] y0 = q[i] test = (m/test) if is_square(test) and test >= 1: test = Integer(test) prim_sols.append((test*p[i],test*q[i])) i+=1 P = a*Q - P Q = (D-P**2)/Q a = Integer(floor((P+root_d)/Q)) p.append(a*p[i-1]+p[i-2]) q.append(a*q[i-1]+q[i-2]) return (x0,y0), prim_sols
def find_rational_point(f, N = 2**8): out_rational = []; out_quad = []; for z in range(0, N): fz = f(z) fmz = f(-z) if is_square(fz) and fz != 0: out_rational += [(z, sqrt(fz))] elif fz != 0: out_quad += [(z, sqrt(fz))] if z != 0: if is_square(fmz) and fmz != 0: out_rational += [(-z, sqrt(fmz))] elif fmz != 0: out_quad += [(-z, sqrt(fmz))] return out_rational + sorted( out_quad, key=lambda point: RR(abs(point[1])) );
def is_valid_curve(q,t,r,k,D): """ Description: Tests that (q,t,r,k,D) is a valid elliptic curve Input: q - size of prime field t - trace of Frobenius r - size of prime order subgroup k - embedding degree D - (negative) fundamental discriminant Output: bool - true iff there exists an elliptic curve over F_q with trace t, a subgroup of order r with embedding degree k, and fundamental discriminant D """ if q == 0 or t == 0 or r == 0 or k == 0 or D == 0: return False if not is_prime(q): return False if not is_prime(r): return False if not fundamental_discriminant(D) == D: return False if D % 4 == 0: #check CM equation if not is_square(4*(t*t - 4*q)//D): return False if D % 4 == 1: if not is_square((t*t - 4*q)//D): return False if not (q+1-t) % r == 0: #check r | #E(F_q) return False if not power_mod(q,k,r) == 1: #check embedding degree is k return False return True
def is_valid_curve(q, t, r, k, D): """ Description: Tests that (q,t,r,k,D) is a valid elliptic curve Input: q - size of prime field t - trace of Frobenius r - size of prime order subgroup k - embedding degree D - (negative) fundamental discriminant Output: bool - true iff there exists an elliptic curve over F_q with trace t, a subgroup of order r with embedding degree k, and fundamental discriminant D """ if q == 0 or t == 0 or r == 0 or k == 0 or D == 0: return False if not is_prime(q): return False if not is_prime(r): return False if not fundamental_discriminant(D) == D: return False if D % 4 == 0: #check CM equation if not is_square(4 * (t * t - 4 * q) // D): return False if D % 4 == 1: if not is_square((t * t - 4 * q) // D): return False if not (q + 1 - t) % r == 0: #check r | #E(F_q) return False if not power_mod(q, k, r) == 1: #check embedding degree is k return False return True
def _pell_solve_2(D,m): # m^2 >= D prim_sols = [] t,u = _pell_solve_1(D,1)[0] if m > 0: L = Integer(0) U = Integer(floor(sqrt(m*(t-1)/(2*D)))) else: L = Integer(ceil(sqrt(-m/D))) U = Integer(floor(sqrt(-m*(t+1)/(2*D)))) for y in range(L,U+1): y = Integer(y) x = (m + D*(y**2)) if is_square(x): x = Integer(sqrt(x)) prim_sols.append((x,y)) if not ((-x*x - y*y*D) % m == 0 and (2*y*x) % m == 0): # (x,y) and (-x,y) are in different solution classes, so add both prim_sols.append((-x,y)) return (t,u),prim_sols
def pell_solve(D, m): """ Description: Solves the Pell equation x^2 - D*y^2 = m Input: D - nonsquare integer m - integer Output: (x0, y0) - minimal solution to x^2 - D*y^2 = 1 prim_sols - list of primitive solutions for each solution class to x^2 - D*y^2 = m """ assert not is_square(D), 'D cannot be a perfect square' if m*m >= D: return _pell_solve_2(D,m) else: return _pell_solve_1(D,m)
def list_of_basis(N, weight, prec=501, tol=1e-20, sv_min=1E-1, sv_max=1E15, set_dim=None): r""" Returns a list of pairs (r,D) forming a basis """ # First we find the smallest Discriminant for each of the components if set_dim != None and set_dim > 0: dim = set_dim else: dim = dimension_jac_cusp_forms(int(weight + 0.5), N, -1) basislist = dict() num_gotten = 0 co_tmp = dict() num_gotten = 0 C0 = 1 RF = RealField(prec) if (silent > 1): print("N={0}".format(N)) print("dim={0}".format(dim)) print("sv_min={0}".format(sv_min)) print("sv_max={0}".format(sv_max)) Aold = Matrix(RF, 1) tol0 = 1E-20 #tol # we start with the first discriminant, then the second etc. Z2N = IntegerModRing(2 * N) ZZ4N = IntegerModRing(4 * N) for Dp in [1..max(1000, 100 * dim)]: D = -Dp # we use the dual of the Weil representation D4N = ZZ4N(D) if (not (is_square(D4N))): continue for r in my_modsqrt(D4N, N): # I want to make sure that P_{(D,r)} is independent from the previously computed functions # The only sure way to do this is to compute all submatrices (to a much smaller precision than what we want at the end) # The candidate is [D,r] and we need to compute the vector of [D,r,D',r'] # for all D',r' already in the list ltmp1 = dict() ltmp2 = dict() j = 0 for [Dp, rp] in basislist.values(): ltmp1[j] = [D, r, Dp, rp] ltmp2[j] = [Dp, rp, D, r] j = j + 1 ltmp1[j] = [D, r, D, r] #print "Checking: D,r,D,r=",ltmp1 ctmp1 = ps_coefficients_holomorphic_vec(N, weight, ltmp1, tol0) # print "ctmp1=",ctmp1 if (j > 0): #print "Checking: D,r,Dp,rp=",ltmp2 # Data is ok?: {0: True} ctmp2 = ps_coefficients_holomorphic_vec(N, weight, ltmp2, tol0) # print "ctmp2=",ctmp2 #print "num_gotten=",num_gotten A = matrix(RF, num_gotten + 1) # The old matrixc with the elements that are already added to the basis # print "Aold=\n",A,"\n" # print "num_gotten=",num_gotten # print "Aold=\n",Aold,"\n" for k in range(Aold.nrows()): for l in range(Aold.ncols()): A[k, l] = Aold[k, l] # endfor # print "A set by old=\n",A,"\n" # Add the (D',r',D,r) for each D',r' in the list tmp = RF(1.0) for l in range(num_gotten): # we do not use the scaling factor when # determining linear independence # mm=RF(abs(ltmp2[l][0]))/N4 # tmp=RF(mm**(weight-one)) A[num_gotten, l] = ctmp2['data'][l] * tmp # Add the (D,r,D',r') for each D',r' in the list # print "ctmp1.keys()=",ctmp1.keys() for l in range(num_gotten + 1): #mm=RF(abs(ltmp1[l][2]))/4N #tmp=RF(mm**(weight-one)) # print "scaled with=",tmp.n(200) A[l, num_gotten] = ctmp1['data'][l] * tmp #[d,B]=mat_inverse(A) # d=det(A) #if(silent>1): #d=det(A) #print "det A = ",d # Now we have to determine whether we have a linearly independent set or not dold = mpmath.mp.dps mpmath.mp.dps = int(prec / 3.3) AInt = mpmath.matrix(int(A.nrows()), int(A.ncols())) AMp = mpmath.matrix(int(A.nrows()), int(A.ncols())) if (silent > 0): print("tol0={0}".format(tol0)) for ir in range(A.nrows()): for ik in range(A.ncols()): AInt[ir, ik] = mpmath.mp.mpi(A[ir, ik] - tol0, A[ir, ik] + tol0) AMp[ir, ik] = mpmath.mpf(A[ir, ik]) d = mpmath.det(AMp) di = mpmath.mp.mpi(mpmath.mp.det(AInt)) #for ir in range(A.nrows()): # for ik in range(A.ncols()): # #print "A.d=",AInt[ir,ik].delta if (silent > 0): print("mpmath.mp.dps={0}".format(mpmath.mp.dps)) print("det(A)={0}".format(d)) print("det(A-as-interval)={0}".format(di)) print("d.delta={0}".format(di.delta)) #if(not mpmath.mpi(d) in di): # raise ArithmeticError," Interval determinant not ok?" #ANP=A.numpy() #try: # u,s,vnp=svd(ANP) # s are the singular values # sl=s.tolist() # mins=min(sl) # the smallest singular value # maxs=max(sl) # if(silent>1): # print "singular values = ",s #except LinAlgError: # if(silent>0): # print "could not compute SVD!" # print "using abs(det) instead" # mins=abs(d) # maxs=abs(d) #if((mins>sv_min and maxs< sv_max)): zero = mpmath.mpi(0) if (zero not in di): if (silent > 1): print("Adding D,r={0}, {1}".format(D, r)) basislist[num_gotten] = [D, r] num_gotten = num_gotten + 1 if (num_gotten >= dim): return basislist else: #print "setting Aold to A" Aold = A else: if (silent > 1): print(" do not use D,r={0}, {1}".format(D, r)) # endif mpmath.mp.dps = dold # endfor if (num_gotten < dim): raise ValueError( " did not find enough good elements for a basis list!")