Exemplo n.º 1
0
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
Exemplo n.º 2
0
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
Exemplo n.º 3
0
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])) );
Exemplo n.º 4
0
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
Exemplo n.º 5
0
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
Exemplo n.º 6
0
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
Exemplo n.º 7
0
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)
Exemplo n.º 8
0
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!")