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 discrinimant * 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 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 oezman_sieve(p, N): """Returns True iff p is in S_N. Only makes sense if p ramifies in K""" M = QuadraticField(-N) h_M = M.class_number() H = M.hilbert_class_field("b") primes_above_p = M.primes_above(p) primes_tot_split_in_hcf = [] for P in primes_above_p: if len(H.primes_above(P)) == h_M: primes_tot_split_in_hcf.append(P) if not primes_tot_split_in_hcf: return False f = R(hilbert_class_polynomial(M.discriminant())) B = NumberField(f, name="t") assert B.degree() == h_M possible_nus = B.primes_above(p) for nu in possible_nus: if nu.residue_class_degree() == 1: return True return False
def compare_formulas_1(D, k): DG = DirichletGroup(abs(D)) chi = DG(kronecker_character(D)) d1 = dimension_new_cusp_forms(chi, k) #if D>0: # lvals=sage.lfunctions.all.lcalc.twist_values(1,2,D) #else: # lvals=sage.lfunctions.all.lcalc.twist_values(1,D,0) #s1=RR(sum([sqrt(abs(lv[0]))*lv[1]*2**len(prime_factors(D/lv[0])) for lv in lvals if lv[0].divides(D) and Zmod(lv[0])(abs(D/lv[0])).is_square()])) #d2=RR(1/pi*s1) d2 = 0 for d in divisors(D): if is_fundamental_discriminant(-d): K = QuadraticField(-d) DD = old_div(ZZ(D), ZZ(d)) ep = euler_phi((chi * DG(kronecker_character(-d))).conductor()) #ep=euler_phi(squarefree_part(abs(D*d))) print("ep=", ep, D, d) ids = [a for a in K.ideals_of_bdd_norm(-DD)[-DD]] eulers1 = [] for a in ids: e = a.euler_phi() if e != 1 and ep == 1: if K(-1).mod(a) != K(1).mod(a): e = old_div(e, (2 * ep)) else: e = old_div(e, ep) eulers1.append(e) print(eulers1, ep) s = sum(eulers1) if ep == 1 and not (d.divides(DD) or abs(DD) == 1): continue print(d, s) if len(eulers1) > 0: d2 += s * K.class_number() return d1 - d2