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 lpp_table(self): """generate the large putative primes table""" output_str = r"${Delta_K}$ & $\Q(\sqrt{{{D}}})$ & {large_putative_primes}\\" latex_output = [] for D in range(-self.range, self.range + 1): if Integer(D).is_squarefree(): if not D in CLASS_NUMBER_ONE_DISCS: if D != 1: K = QuadraticField(D) Delta_K = K.discriminant() candidates = get_isogeny_primes(K, aux_prime_count=25, bound=2000, loop_curves=False) candidates = [ c for c in candidates if c not in EC_Q_ISOGENY_PRIMES ] candidates = [c for c in candidates if c > 71] candidates.sort() large_putative_primes = ", ".join(map(str, candidates)) output_here = output_str.format( Delta_K=Delta_K, D=D, large_putative_primes=large_putative_primes, ) latex_output.append(output_here) for one_line in latex_output: print(one_line)
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 test_interval(D): K = QuadraticField(D) if not K.discriminant() in CLASS_NUMBER_ONE_DISCS: superset, _ = get_isogeny_primes(K, **TEST_SETTINGS) # test that there are not too many primes left over todo = set(superset).difference(EC_Q_ISOGENY_PRIMES) assert len(todo) == 0 or max(todo) <= 109 assert len(todo) <= 2 or max(todo) <= 31
def oezman_sieve(p, N): """If p is unramified in Q(sqrt(-N)) this always returns True. Otherwise returns True iff p is in S_N or . Only makes sense if p ramifies in K""" M = QuadraticField(-N) if p.divides(M.discriminant()): return True pp = (M * p).factor()[0][0] C_M = M.class_group() if C_M(pp).order() == 1: return True return False
def main(): for D in square_free_D: K = QuadraticField(D) if not K.discriminant() in CLASS_NUMBER_ONE_DISCS: superset, _ = get_isogeny_primes( K, bound=1000, ice_filter=True, appendix_bound=1000, norm_bound=50, auto_stop_strategy=True, repeat_bound=4, ) possible_new_isog_primes = superset - EC_Q_ISOGENY_PRIMES possible_new_isog_primes_list = list(possible_new_isog_primes) possible_new_isog_primes_list.sort() if possible_new_isog_primes_list: print(f"D = {D} possible isogenies = {possible_new_isog_primes_list}")
def dlmv_table(self): """generate the dlmv table""" output_str = ( r"${Delta_K}$ & $\Q(\sqrt{{{D}}})$ & ${rem} \times 10^{{{exp_at_10}}}$\\" ) for D in range(-self.range, self.range + 1): if Integer(D).is_squarefree(): if not D in CLASS_NUMBER_ONE_DISCS: if D != 1: K = QuadraticField(D) Delta_K = K.discriminant() dlmv_bound = RR(DLMV(K)) log_dlmv_bound = dlmv_bound.log10() exp_at_10 = int(log_dlmv_bound) rem = log_dlmv_bound - exp_at_10 rem = 10**rem rem = rem.numerical_approx(digits=3) output_here = output_str.format(Delta_K=Delta_K, D=D, rem=rem, exp_at_10=exp_at_10) print(output_here)