Cartier cached version
system:sage


{{{id=10|

///
}}}

{{{id=1|
%python
from sage.misc.cachefunc import CachedFunction 

@cached_function
def Cartier_matrix(self):
    r"""
    INPUT:
            - 'self' - Hyperelliptic Curve of the form y^2 = f(x) over a finite field, Fq
    
    OUTPUT:
    - 'matrix(Fq,M)' The matrix M = (c_(pi-j)), f(x)^((p-1)/2) = \sum c_i x^i
    - 'Coeff' List of Coeffs of F, this is needed for Hasse-Witt function. 
    - 'g' genus of the curve self, this is needed by a-number. 
    - 'Fq' is the base field of self, and it is needed for Hasse-Witt
    - 'p' is the char(Fq), this is needed for Hasse-Witt. 
  
    """
    
#Compute the finite field and prime p.     
    Fq=self.base_ring();
    p=Fq.characteristic()
#checks
    
    if p == 2:
        raise ValueError, "p must be odd"; 

    g = self.genus()
        
    #retrieve the function f(x) ,where y^2=f(x)        
    f,h = self.hyperelliptic_polynomials()  
    #This implementation only deals with h=0      
    
    if h !=0:
       raise ValueError, "E must be of the form y^2 = f(x)"
        
    d = f.degree()
    #this implementation is for odd degree only, even degree will be handled later. 
    if d%2 == 0:
        raise ValueError, "In this implementation the degree of f must be odd"
    #Compute resultant to make sure no repeated roots        
    df=f.derivative()
    R=df.resultant(f)
    if R == 0:
        raise ValueError, "so curve is not smooth"    

#computing F, since the entries of the matrix are c_i where F= \sum c_i x^i

    F = f**((p-1)/2)

#coefficients returns a_0, ... , a_n where f(x) = a_n x^n + ... + a_0

    Coeff = F.list()
    
    #inserting zeros when necessary-- that is, when deg(F) < p*g-1, (simplified if p <2g-1) 
    #which is the highest powered coefficient needed for our matrix
    #So we don't have enough coefficients we add extra zeros to have the same poly,
    #but enough coeff.

    zeros = [0 for i in range(p*g-len(Coeff))]
    Coeff = Coeff + zeros

# compute each row of matrix as list and then M=list of lists(rows) 
   
    M=[];
    for j in range(1,g+1):
        H=[Coeff[i] for i in range((p*j-1), (p*j-g-1),-1)]
        M.append(H);
    return matrix(Fq,M), Coeff, g, Fq,p
///
}}}

{{{id=5|
%python
@cached_function
def Hasse_Witt(self):
    r"""
    INPUT:
    - 'self' - Hyperelliptic Curve of the form y^2 = f(x) over a finite field
  
    OUTPUT:
    - 'N' - The matrix N = M M^(p)...M^(p^(g-1)) where M = (c_(pi-j)), f(x)^((p-1)/2) = \sum c_i x^i
    """
# If Cartier Matrix is already cached for this curve, use that or evaluate it to get M,
#Coeffs, genus, Fq=base field of self, p=char(Fq). This is so we have one less matrix to
#compute.     
    A=Cartier_matrix.get_cache();
    print A.keys()[-1][0][0], self
    if A.keys()[-1][0][0]==self:
        print "c cached";
        M,Coeffs,g, Fq, p = A.items()[-1][1];
    else:
        A.clear()
        M, Coeffs,g, Fq, p= Cartier_matrix(self)

    def frob_mat(Coeffs, k):
        a = p**k
        mat = []
        Coeffs_pow = [c**a for c in Coeffs]
        for i in range(1,g+1):
            H=[(Coeffs[j]) for j in range((p*i-1), (p*i - g-1), -1)]
            mat.append(H);
        return matrix(Fq,mat)

    

#Computes all the different possible action of frobenius on matrix M and stores in list Mall       
    Mall = [M] + [frob_mat(Coeffs,k) for k in srange(1,g)]
    
#initial N=I, so we can go through Mall and multiply all matrices with I and 
#get the Hasse-Witt matrix. 
    N = identity_matrix(Fq,g)
    for l in Mall:
        N = N*l;
    return N
///
}}}

{{{id=2|
%python

def a_number(self):
    r"""
    INPUT:
    - 'self' - Hyperelliptic Curve of the form y^2 = f(x) over a finite field, Fq
    
    OUTPUT:
    - 'a' - a-number
  
    """
    A=Cartier_matrix.get_cache();
    if A.keys()[-1][0][0]==self:
        print "c cached in a";

        M,Coeffs,g, Fq, p = A.items()[0][1];
    else:
        A.clear()
        M, Coeffs,g, Fq, p= Cartier_matrix(self)
    a=g-rank(M);
    return a;
///
}}}

{{{id=6|
%python
def p_rank(self):
    r"""
    INPUT:
    - 'self' - Hyperelliptic Curve of the form y^2 = f(x) over a finite field, Fq
    
    OUTPUT:
    - 'pr' - r-rank
  
    """
    A=Hasse_Witt.get_cache();
    if A.keys()[-1][0][0]==self:
        print "H is cached";
        N = A.items()[0][1];
    else:
        A.clear()
        N= Hasse_Witt(self)
    pr=rank(N);
    return pr
///
}}}

{{{id=3|
for p in srange(7,20):
    if p.is_prime():
        P.<x>=GF(p,'a')[];
        E = HyperellipticCurve(x^11+x+1,0);
      #  print p, Cartier_matrix1(E),Hasse_Witt(E),a_number(E), p_rank(E);
        print p, timeit('Cartier_matrix(E)'), timeit('Hasse_Witt(E)'), timeit('a_number(E)'), timeit('p_rank(E)');
///
7 625 loops, best of 3: 1.27 ms per loop
None 625 loops, best of 3: 1.27 ms per loop
None 625 loops, best of 3: 31.7 µs per loop
None 625 loops, best of 3: 30.9 µs per loop
None
11 625 loops, best of 3: 1.26 ms per loop
None 625 loops, best of 3: 1.27 ms per loop
None 625 loops, best of 3: 31.6 µs per loop
None 625 loops, best of 3: 30.7 µs per loop
None
13 625 loops, best of 3: 1.26 ms per loop
None 625 loops, best of 3: 1.26 ms per loop
None 625 loops, best of 3: 31.5 µs per loop
None 625 loops, best of 3: 30.8 µs per loop
None
17 625 loops, best of 3: 1.27 ms per loop
None 625 loops, best of 3: 1.27 ms per loop
None 625 loops, best of 3: 31.5 µs per loop
None 625 loops, best of 3: 30.9 µs per loop
None
19 625 loops, best of 3: 1.26 ms per loop
None 625 loops, best of 3: 1.28 ms per loop
None 625 loops, best of 3: 31.8 µs per loop
None 625 loops, best of 3: 30.9 µs per loop
None
}}}

{{{id=4|

///
}}}

{{{id=12|

///
4
}}}

{{{id=14|

///
}}}