Example #1
0
def fixed_prec(r, digs=3):
    n = RealField(200)(r) * (10**digs)
    n = str(n.round())
    head = int(n[:-digs])
    if head >= 10**4:
        head = comma(head)
    return str(head) + '.' + n[-digs:]
Example #2
0
def fixed_prec(r, digs=3):
  n = RealField(200)(r)*(10**digs)
  n = str(n.round())
  head = int(n[:-digs])
  if head>=10**4:
    head = comma(head)
  return str(head)+'.'+n[-digs:]
def polish_approx_hyperbolic_structure(approx_hyperbolic_structure,
                                       bits_prec=53,
                                       verbose=False):

    RF = RealField(bits_prec + 20)

    twoPi = 2 * RF.pi()

    edge_parameters = vector(RF, approx_hyperbolic_structure.edge_lengths)

    epsilon = RF(0.5)**bits_prec

    if not (approx_hyperbolic_structure.exact_edges
            and approx_hyperbolic_structure.var_edges):
        raise Exception("Did not pick exact/var edges")

    for i in range(100):
        try:
            result = HyperbolicStructure(
                approx_hyperbolic_structure.mcomplex, edge_parameters,
                approx_hyperbolic_structure.exact_edges,
                approx_hyperbolic_structure.var_edges)
        except BadDihedralAngleError as e:
            raise PolishingFailedWithBadDihedralAngleError("When polishing", e)

        errs = vector(
            [result.angle_sums[e] - twoPi for e in result.exact_edges])

        max_err = max([abs(err) for err in errs])

        if verbose:
            print("Iteration %d: error = %s" % (i, RealField(53)(max_err)))

        if max_err < epsilon:
            return result

        j = result.full_rank_jacobian_submatrix()
        try:
            jinv = j.inverse()
        except ZeroDivisionError:
            raise PolishingError("Singular matrix")

        delta = jinv * errs

        for e, d in zip(result.var_edges, delta):
            edge_parameters[e] -= d

    print("Max error", max_err)
    print(approx_hyperbolic_structure.full_rank_jacobian_submatrix().SVD()
          [1].diagonal())

    raise PolishingError("Newton method did not produce a result")
Example #4
0
def tensor_get_an_no_deg1(L1, L2, d1, d2, BadPrimeInfo):
    """
    Same as the above in the case no dimension is 1
    """
    if d1==1 or d2==1:
        raise ValueError('min(d1,d2) should not be 1, use direct method then')
    s1 = len(L1)
    s2 = len(L2)
    if s1 < s2:
        S = s1
    if s2 <= s1:
        S = s2
    BadPrimes = []
    for bpi in BadPrimeInfo:
        BadPrimes.append(bpi[0])
    P = prime_range(S+1)
    Z = S * [1]
    S = RealField()(S)
    for p in P:
        f = S.log(base=p).floor()
        q = 1
        E1 = []
        E2 = []
        if not p in BadPrimes:
            for i in range(f):
                q=q*p
                E1.append(L1[q-1])
                E2.append(L2[q-1])
            e1 = list_to_euler_factor(E1,f+1)
            e2 = list_to_euler_factor(E2,f+1)
            # ld1 = d1 # not used
            # ld2 = d2 # not used
        else: # either convolve, or have one input be the answer and other 1-t
            i = BadPrimes.index(p)
            e1 = BadPrimeInfo[i][1]
            e2 = BadPrimeInfo[i][2]
            # ld1 = e1.degree() # not used
            # ld2 = e2.degree() # not used
            F = e1.list()[0].parent().fraction_field()
            R = PowerSeriesRing(F, "T", default_prec=f+1)
            e1 = R(e1)
            e2 = R(e2)
        E = tensor_local_factors(e1,e2,f)
        A = euler_factor_to_list(E,f)
        while len(A) < f:
            A.append(0)
        q = 1
        for i in range(f):
            q = q*p
            Z[q-1]=A[i]
    all_an_from_prime_powers(Z)
    return Z
Example #5
0
def tensor_get_an_no_deg1(L1, L2, d1, d2, BadPrimeInfo):
    """
    Same as the above in the case no dimension is 1
    """
    if d1 == 1 or d2 == 1:
        raise ValueError('min(d1,d2) should not be 1, use direct method then')
    s1 = len(L1)
    s2 = len(L2)
    if s1 < s2:
        S = s1
    if s2 <= s1:
        S = s2
    BadPrimes = []
    for bpi in BadPrimeInfo:
        BadPrimes.append(bpi[0])
    P = prime_range(S + 1)
    Z = S * [1]
    S = RealField()(S)
    for p in P:
        f = S.log(base=p).floor()
        q = 1
        E1 = []
        E2 = []
        if not p in BadPrimes:
            for i in range(f):
                q = q * p
                E1.append(L1[q - 1])
                E2.append(L2[q - 1])
            e1 = list_to_euler_factor(E1, f + 1)
            e2 = list_to_euler_factor(E2, f + 1)
            # ld1 = d1 # not used
            # ld2 = d2 # not used
        else:  # either convolve, or have one input be the answer and other 1-t
            i = BadPrimes.index(p)
            e1 = BadPrimeInfo[i][1]
            e2 = BadPrimeInfo[i][2]
            # ld1 = e1.degree() # not used
            # ld2 = e2.degree() # not used
            F = e1.list()[0].parent().fraction_field()
            R = PowerSeriesRing(F, "T", default_prec=f + 1)
            e1 = R(e1)
            e2 = R(e2)
        E = tensor_local_factors(e1, e2, f)
        A = euler_factor_to_list(E, f)
        while len(A) < f:
            A.append(0)
        q = 1
        for i in range(f):
            q = q * p
            Z[q - 1] = A[i]
    all_an_from_prime_powers(Z)
    return Z
Example #6
0
 def special_value(self,n):
     r"""
     Compute L(f,n)
     Recall that L(f,n+1)=(2pii)^(n+1)*(-1)^(n+1)/Gamma(n+1) * r_n(f)
     """
     RF = RealField(self._prec)
     CF = ComplexField(self._prec)
     if n < 0 or n>self._w+1:
         print "{0} is not a special point for this f!".format(n)
         return 
     if not self._polynomials:
         self._get_polynomials()
     rk = self.get_rk(0,n-1)
     return CF(0,2*RF.pi())**(n)*(-1)**(n)/RF(n).gamma()*rk
Example #7
0
 def special_value(self, n):
     r"""
     Compute L(f,n)
     Recall that L(f,n+1)=(2pii)^(n+1)*(-1)^(n+1)/Gamma(n+1) * r_n(f)
     """
     RF = RealField(self._prec)
     CF = ComplexField(self._prec)
     if n < 0 or n > self._w + 1:
         print "{0} is not a special point for this f!".format(n)
         return
     if not self._polynomials:
         self._get_polynomials()
     rk = self.get_rk(0, n - 1)
     return CF(0, 2 * RF.pi())**(n) * (-1)**(n) / RF(n).gamma() * rk
Example #8
0
def get_euler_factor(L,p):
    """
    takes L list of all ans and p is a prime
    it returns the euler factor at p
    # utility function to get an Euler factor, unused
    """
    S = RealField()(len(L))
    f = S.log(base=p).floor()
    E = []
    q = 1
    for i in range(f):
        q = q*p
        E.append(L[q-1])
    return list_to_euler_factor(E,f)
Example #9
0
def get_euler_factor(L, p):
    """
    takes L list of all ans and p is a prime
    it returns the euler factor at p
    # utility function to get an Euler factor, unused
    """
    S = RealField()(len(L))
    f = S.log(base=p).floor()
    E = []
    q = 1
    for i in range(f):
        q = q * p
        E.append(L[q - 1])
    return list_to_euler_factor(E, f)
Example #10
0
 def coefficient_at_coset(self, n):
     r"""
     Compute Fourier coefficients of f|A_n 
     """
     if hasattr(n, "matrix"):
         n = self._get_coset_n(n)
     if not self._base_coeffs:
         self.coefficients_f()
     CF = ComplexField(self._prec)
     if not self._coefficients_at_coset.has_key(n):
         M = self.truncation_M(n)
         h, w = self.get_shift_and_width_for_coset(n)
         zN = CyclotomicField(w).gens()[0]
         prec1 = self._prec + ceil(log_b(M, 2))
         RF = RealField(prec1)
         coeffs = []
         fak = RF(w)**-(RF(self._k) / RF(2))
         #print "f=",f,n
         for i in range(M):
             al = CF(self.atkin_lehner(n))
             c0 = self._base_coeffs_embedding[i]
             #if hasattr(c0,"complex_embeddings"):
             #    c0 = c0.complex_embedding(prec1)
             #else:
             #    c0 = CF(c0)
             qN = zN**((i + 1) * h)
             #print "qN=",qN,type(qN)
             an = fak * al * c0 * qN.complex_embedding(prec1)
             #an = self.atkin_lehner(n)*self._base_coeffs[i]*zN**((i+1)*h)
             #an = f*an.complex_embedding(prec1)
             coeffs.append(an)
         self._coefficients_at_coset[n] = coeffs
     return self._coefficients_at_coset[n]
Example #11
0
 def coefficients_f(self):
     r"""
     Compute the maximum number of coefficients we need to use (with current precision).
     """
     if not self._base_coeffs:
         kf = 0.5 * (self._k - 1.0)
         M0 = self.maxM()
         prec1 = self._prec + ceil(log_b(M0 * 6, 2))
         if hasattr(self._f, "O"):
             self._base_coeffs = self._f.coefficients()
             if len(self._base_coeffs) < M0:
                 raise ValueError, "Too few coefficients available!"
         else:
             self._base_coeffs = self._f.coefficients(ZZ(M0))
         self._base_coeffs_embedding = []
         #precn = prec1
         if hasattr(self._base_coeffs[0], "complex_embedding"):
             n = 1
             #print "kf=",kf
             #print "kfprec1=",prec1
             for a in self._base_coeffs:
                 ## Use precision high enough that c(n)/n^((k-1)/2) have self._prec correct bits
                 precn = prec1 + kf * ceil(log_b(n, 2))
                 self._base_coeffs_embedding.append(
                     a.complex_embedding(precn))
                 n += 1
         else:
             ## Here we have a rational number so we can ue the default number of bits
             n = 1
             for a in self._base_coeffs:
                 precn = prec1 + kf * ceil(log_b(n, 2))
                 aa = RealField(precn)(a)
                 self._base_coeffs_embedding.append(a)  #self._RF(a))
                 n += 1
     return self._base_coeffs
Example #12
0
    def TwoPointsMinusInfinity(self, P, Q): # Creates a divisor class of P + Q - g*\infty
        maxlower = self.lower
        xP, yP = self.Rextraprec(P[0]), self.Rextraprec(P[1])
        xQ, yQ = self.Rextraprec(Q[0]), self.Rextraprec(Q[1])

        assert (self.f(xP) - yP**2).abs() <= (yP**2).abs() * self.almostzero
        assert (self.f(xQ) - yQ**2).abs() <= (yQ**2).abs() * self.almostzero

        WPQ = Matrix(self.Rextraprec, self.nZ, 3 * self.g + 7) # H0(3D0  - g*\infty)
        Ev = Matrix(self.Rextraprec, 2, 3 * self.g + 7) # basis of  H0(3D0  - g*\infty) evaluated at P and Q
        Exps=[]
        for n in range( 2 * self.g + 4):
            Exps.append((n,0))
            if n > self.g:
                Exps.append(( n - self.g - 1, 1))

        for j in range( 3 * self.g + 7):
            u, v = Exps[j]
            for i in range( self.nZ ):
                x, y = self.Z[i]
                WPQ[ i, j ] = x**u * y**v

            Ev[0,j] = xP**u * yP**v
            Ev[1,j] = xQ**u * yQ**v
        
        K, upper, lower = Kernel(Ev, 2)
        assert self.threshold_check(upper, lower), "upper = %s lower = %s" % (RealField(35)(upper), RealField(35)(lower))
        maxlower = max(maxlower, lower);
        #Returns H0(3*D0 - P - Q - g infty)
        # note that  [P + Q + g infty - D0] ~ P + Q - infty
        return (WPQ * K).change_ring(self.R), maxlower
Example #13
0
def signature_function_of_integral_matrix(V, prec=53):
    """
    Computes the signature function sigma of V via numerical methods.
    Returns two lists, the first representing a partition of [0, 1]:

         x_0 = 0 < x_1 < x_2 < ... < x_n = 1

    and the second list consisting of the values [v_0, ... , v_(n-1)]
    of sigma on the interval (x_i, x_(i+1)).  Currently, the value of
    sigma *at* x_i is not computed.
    """
    poly = alexander_poly_from_seifert(V)
    RR = RealField(prec)
    CC = ComplexField(prec)
    pi = RR.pi()
    I = CC.gen()
    partition = [RR(0)] + [a for a, e in roots_on_unit_circle(poly, prec)
                           ] + [RR(1)]
    n = len(partition) - 1
    values = []
    for i in range(n):
        omega = exp((2 * pi * I) * (partition[i] + partition[i + 1]) / 2)
        A = (1 - omega) * V + (1 - omega.conjugate()) * V.transpose()
        values.append(signature_via_numpy(A))

    assert list(reversed(values)) == values
    return partition, values
Example #14
0
    def PointMinusInfinity(self, P, sign = 0):
        # Creates a divisor class of P- \inty_{(-1)**sign}
        maxlower = self.lower 
        assert self.f.degree() == 2*self.g + 2;
        sqrtan = (-1)**sign * self.Rextraprec( sqrt( self.Rdoubleextraprec(self.an)) );

        xP, yP = self.Rextraprec(P[0]),self.Rextraprec(P[1])
        assert (self.f(xP) - yP**2).abs() <= (yP**2).abs() * self.almostzero

        if xP != 0 and self.a0 != 0:
            x0 = self.Rextraprec(0);    
        else:
            x0 = xP
            while x0 == xP:
                x0 = self.Rextraprec(ZZ.random_element())
            
        y0 =  self.Rextraprec( sqrt( self.Rdoubleextraprec( self.f( x0 )))) # P0 = (x0, y0) 

        WP1 = Matrix(self.Rextraprec, self.nZ, 3 * self.g + 6) # H0(3D0 - P0 - g \infty) = H0(3D0 - P0 - g(\infty_{+} + \infty_{-}))
        EvP = Matrix(self.Rextraprec, 1, 3 * self.g + 6) # the functions of  H0(3D0-P0-g \infty) at P
        B =  Matrix(self.Rextraprec, self.nZ, 3 * self.g + 5) # H0(3D0 - \infty_{sign} - P0 - g\infty)

        # adds the functions x - x0, (x - x0)**1,  ..., (x - x0)**(2g+2) to it
        for j in xrange(2 * self.g + 2 ):
            for i, (x, y) in enumerate( self.Z ):
                WP1[ i, j] = B[ i, j] = (x - x0) ** (j + 1)
            EvP[ 0, j] = (xP - x0) ** (j + 1)
        
        # adds y - y0
        for i, (x, y) in enumerate( self.Z ):
            WP1[ i, 2 * self.g + 2 ] = B[ i, 2 * self.g + 2] = y - y0
        EvP[ 0, 2 * self.g + 2] = yP - y0

        # adds (x - x0) * y ... (x-x0)**(g+1)*y
        for j in range(1, self.g + 2):
            for i, (x,y) in enumerate( self.Z ):
                WP1[ i, 2 * self.g + 2 + j ] = B[ i, 2 * self.g + 2 + j] = (x-x0)**j * y 
            EvP[ 0, 2 * self.g + 2 + j] = (xP - x0)**j * yP


        # adds (x - x0)**(2g + 3) and  y *  (x - x0)**(g + 2)
        for i,(x,y) in enumerate(self.Z):
            WP1[ i, 3 * self.g + 4 ] =  (x - x0)**( 2 * self.g + 3)
            WP1[ i, 3 * self.g + 5 ] = y *  (x - x0)**(self.g + 2)
            B[ i, 3 * self.g + 4 ] =  (x - x0)**( self.g + 2) * ( y - sqrtan * x**(self.g + 1) )

        EvP[ 0, 3 * self.g + 4] = (xP - x0) ** ( 2 * self.g + 3)
        EvP[ 0, 3 * self.g + 5] = yP * (xP - x0)**(self.g + 2)
        
        # A = functions in  H0(3D0-P0-g \infty) that vanish at P
        # = H**0(3D0 - P0 - P -g \infty)
        K, upper, lower = Kernel(EvP, EvP.ncols() - (3 * self.g + 5))
        assert self.threshold_check(upper, lower), "upper = %s lower = %s" % (RealField(35)(upper), RealField(35)(lower))
        maxlower = max(maxlower, lower);

        A = WP1 * K
        # A - B = P0 + P + g \infty - (\infty_{+} + P0 + g\infty) = P - \inty_{+}
        res, lower = self.Sub(A,B)
        maxlower = max(maxlower, lower);
        return res.change_ring(self.R), maxlower;
Example #15
0
def EC_nf_plot(E, base_field_gen_name):
    K = E.base_field()
    n1 = K.signature()[0]
    if n1 == 0:
        return plot([])
    prec = 53
    maxprec = 10 ** 6
    while prec < maxprec:  # Try to base change to R. May fail if resulting curve is almost singular, so increase precision.
        try:
            SR = K.embeddings(RealField(prec))
            X = [E.base_extend(s) for s in SR]
            break
        except ArithmeticError:
            prec *= 2
    if prec >= maxprec:
        return text("Unable to plot", (1, 1), fontsize="xx-large")
    X = [e.plot() for e in X]
    xmin = min([x.xmin() for x in X])
    xmax = max([x.xmax() for x in X])
    ymin = min([x.ymin() for x in X])
    ymax = max([x.ymax() for x in X])
    cols = ["blue", "red", "green", "orange", "brown"]  # Preset colours, because rainbow tends to return too pale ones
    if n1 > len(cols):
        cols = rainbow(n1)
    return sum([EC_R_plot([SR[i](a) for a in E.ainvs()], xmin, xmax, ymin, ymax, cols[i], "$" + base_field_gen_name + " \mapsto$ " + str(SR[i].im_gens()[0].n(20))) for i in range(n1)])
Example #16
0
def real_parabolic_reps_from_ptolemy(M, pari_prec=15):
    R = PolynomialRing(QQ, 'x')
    RR = RealField(1000)
    ans = []
    obs_classes = M.ptolemy_obstruction_classes()
    for obs in obs_classes:
        V = M.ptolemy_variety(N=2, obstruction_class=obs)
        #for sol in V.retrieve_solutions():
        for sol in V.compute_solutions(engine='magma'):
            if sol.dimension > 0:
                print("Positive dimensional component!")
                continue
            prec = snappy.pari.set_real_precision(pari_prec)
            is_geometric = sol.is_geometric()
            snappy.pari.set_real_precision(prec)
            cross_ratios = sol.cross_ratios()
            shapes = [
                R(cross_ratios['z_0000_%d' % i].lift())
                for i in range(M.num_tetrahedra())
            ]
            s = shapes[0]
            p = R(sol.number_field())
            if p == 0:  # Field is Q
                assert False
            # print p, '\n'
            for r in p.roots(RR, False):
                rho = pe.real_reps.PSL2RRepOf3ManifoldGroup(
                    M,
                    target_meridian_holonomy=RR(1),
                    rough_shapes=[cr(r) for cr in shapes])
                rho.is_galois_conj_of_geom = is_geometric
                ans.append(rho)
    return ans
Example #17
0
 def central_char_function(self):
     dim = self.dimension()
     dfactor = (-1)**dim
     # doubling insures integers below
     # we could test for when we need it, but then we carry the "if"
     # throughout
     charf = 2*self.character_field()
     localfactors = self.local_factors_table()
     bad = [0 if dim+1>len(z) else 1 for z in localfactors]
     localfactors = [self.from_conjugacy_class_index_to_polynomial(j+1) for j in range(len(localfactors))]
     localfactors = [z.leading_coefficient()*dfactor for z in localfactors]
     # Now take logs to figure out what power these are
     mypi = RealField(100)(pi)
     localfactors = [charf*log(z)/(2*I*mypi) for z in localfactors]
     localfactorsa = [z.real().round() % charf for z in localfactors]
     # Test to see if we are ok?
     localfactorsa = [localfactorsa[j] if bad[j]>0 else -1 for j in range(len(localfactorsa))]
     def myfunc(inp, n):
         fn = list(factor(inp))
         pvals = [[localfactorsa[self.any_prime_to_cc_index(z[0])-1], z[1]] for z in fn]
         # -1 is the marker that the prime divides the conductor
         for j in range(len(pvals)):
             if pvals[j][0] < 0:
                 return -1
         pvals = sum([z[0]*z[1] for z in pvals])
         return (pvals % n)
     return myfunc
Example #18
0
def display_float(x,
                  digits,
                  method="truncate",
                  extra_truncation_digits=3,
                  try_halfinteger=True):
    if abs(x) < 10.**(-digits - extra_truncation_digits):
        return "0"
    # if small, try to display it as an exact or half integer
    if try_halfinteger and abs(x) < 10.**digits:
        if is_exact(x):
            s = str(x)
            if len(s) < digits + 2:  # 2 = '/' + '-'
                return str(x)
        k = round_to_half_int(x)
        if k == x:
            k2 = None
            try:
                k2 = ZZ(2 * x)
            except TypeError:
                pass
            # the second statment checks for overflow
            if k2 == 2 * x and (2 * x + 1) - k2 == 1:
                if k2 % 2 == 0:
                    s = '%s' % (k2 / 2)
                else:
                    s = '%s' % (float(k2) / 2)
                return s
    if method == 'truncate':
        rnd = 'RNDZ'
    else:
        rnd = 'RNDN'
    no_sci = 'e' not in "%.{}g".format(digits) % float(x)
    try:
        s = RealField(max(53, 4 * digits), rnd=rnd)(x).str(digits=digits,
                                                           no_sci=no_sci)
    except TypeError:
        # older versions of Sage don't support the digits keyword
        s = RealField(max(53, 4 * digits), rnd=rnd)(x).str(no_sci=no_sci)
        point = s.find('.')
        if point != -1:
            if point < digits:
                s = s[:digits + 1]
            else:
                s = s[:point]
    return s
Example #19
0
def all_an_from_prime_powers(L):
    """
    L is a list of an such that the terms
    are correct for all n which are prime powers
    and all others are equal to 1;
    this function changes the list in place to make
    the correct ans for all n
    """
    S = ZZ(len(L))
    for p in prime_range(S + 1):
        q = 1
        Sr = RealField()(len(L))
        f = Sr.log(base=p).floor()
        for k in range(f):
            q = q * p
            for m in range(2, 1 + (S // q)):
                if (m % p) != 0:
                    L[m * q - 1] = L[m * q - 1] * L[q - 1]
Example #20
0
def mpmath_matrix_to_sage(A):
    entries = list(A)
    if all(isinstance(e, mp.mpf) for e in entries):
        F = RealField(mp.prec)
        entries = [F(e) for e in entries]
    else:
        F = ComplexField(mp.prec)
        entries = [F(e.real, e.imag) for e in entries]
    return matrix(F, A.rows, A.cols, entries)
Example #21
0
def all_an_from_prime_powers(L):
    """
    L is a list of an such that the terms
    are correct for all n which are prime powers
    and all others are equal to 1;
    this function changes the list in place to make
    the correct ans for all n
    """
    S = ZZ(len(L))
    for p in prime_range(S+1):
        q = 1
        Sr = RealField()(len(L))
        f = Sr.log(base=p).floor()
        for k in range(f):
            q = q*p
            for m in range(2, 1+(S//q)):
                if (m%p) != 0:
                    L[m*q-1] = L[m*q-1] * L[q-1]
Example #22
0
def real_root_arguments(p, prec=212):
    """
    Note: if p(x) = g(x + 1/x) then p'(1) = p'(-1) = 0 by the chain
    rule; in particular, 1 and -1 are *never* simple roots of p(x).
    """
    assert p(1) != 0 and p(-1) != 0
    g = compact_form(p)
    RR = RealField(prec)
    roots = sorted([(arccos(x/2), e) for x, e in g.roots(RR) if abs(x) <= 2])
    return roots
Example #23
0
def display_float(x, digits, method = "truncate",
                             extra_truncation_digits=3,
                             try_halfinteger=True):
    if abs(x) < 10.**(- digits - extra_truncation_digits):
        return "0"
    # if small, try to display it as an exact or half integer
    if try_halfinteger and abs(x) < 10.**digits:
        if is_exact(x):
            s = str(x)
            if len(s) < digits + 2: # 2 = '/' + '-'
                return str(x)
        k = round_to_half_int(x)
        if k == x :
            k2 = None
            try:
                k2 = ZZ(2*x)
            except TypeError:
                pass
            # the second statment checks for overflow
            if k2 == 2*x and (2*x + 1) - k2 == 1:
                if k2 % 2 == 0:
                    s = '%s' % (k2/2)
                else:
                    s = '%s' % (float(k2)/2)
                return s
    if method == 'truncate':
        rnd = 'RNDZ'
    else:
        rnd = 'RNDN'
    no_sci = 'e' not in "%.{}g".format(digits) % float(x)
    try:
        s = RealField(max(53,4*digits),  rnd=rnd)(x).str(digits=digits, no_sci=no_sci)
    except TypeError:
        # older versions of Sage don't support the digits keyword
        s = RealField(max(53,4*digits),  rnd=rnd)(x).str(no_sci=no_sci)
        point = s.find('.')
        if point != -1:
            if point < digits:
                s = s[:digits+1]
            else:
                s = s[:point]
    return s
Example #24
0
 def __init__(self, real, imag=None):
     def find_prec(s):
         if isinstance(s, string_types):
             # strip negatives and exponent
             s = s.replace("-","")
             if "e" in s:
                 s = s[:s.find("e")]
             return ceil(len(s) * 3.322)
         else:
             try:
                 return s.parent().precision()
             except Exception:
                 return 53
     if imag is None:
         # Process strings
         if isinstance(real, string_types):
             M = CC_RE.match(real)
             if M is None:
                 raise ValueError("'%s' not a valid complex number" % real)
             a, b = M.groups()
             # handle missing coefficient of i
             if b == '-':
                 b = '-1'
             elif b in ['+', '']:
                 b = '1'
             # The following is a good guess for the bit-precision,
             # but we use LmfdbRealLiterals to ensure that our number
             # prints the same as we got it.
             prec = max(find_prec(a), find_prec(b), 53)
             parent = ComplexField(prec)
             R = parent._real_field()
             self._real_literal = LmfdbRealLiteral(R, a)
             self._imag_literal = LmfdbRealLiteral(R, b)
         elif isinstance(real, LmfdbRealLiteral):
             parent = ComplexField(real.parent().precision())
             self._real_literal = real
             self._imag_literal = parent._real_field()(0)
         elif isintance(real, ComplexLiteral):
             parent = real.parent()
             self._real_literal = real._real_literal
             self._imag_literal = real._imag_literal
         else:
             raise TypeError("Object '%s' of type %s not valid input" % (real, type(real)))
     else:
         prec = max(find_prec(real), find_prec(imag), 53)
         R = RealField(prec)
         parent = ComplexField(prec)
         for x, xname in [(real, '_real_literal'), (imag, '_imag_literal')]:
             if isinstance(x, string_types):
                 x = LmfdbRealLiteral(R, x)
             if not isinstance(x, LmfdbRealLiteral):
                 raise TypeError("Object '%s' of type %s not valid input" % (x, type(x)))
             setattr(self, xname, x)
     ComplexNumber.__init__(self, self.real(), self.imag())
Example #25
0
def preserves_hermitian_form(SL2C_matrices):
    """
    >>> CC = ComplexField(100)
    >>> A = matrix(CC, [[1, 1], [1, 2]]);
    >>> B = matrix(CC, [[0, 1], [-1, 0]])
    >>> C = matrix(CC, [[CC('I'),0], [0, -CC('I')]])
    >>> ans, sig, form = preserves_hermitian_form([A, B])
    >>> ans
    True
    >>> sig
    'indefinite'
    >>> form.change_ring(ComplexField(10))
    [  0.00 -1.0*I]
    [ 1.0*I   0.00]
    >>> preserves_hermitian_form([A, B, C])
    (False, None, None)
    >>> ans, sig, form = preserves_hermitian_form([B, C])
    >>> sig
    'definite'
    """
    M = block_matrix(len(SL2C_matrices), 1, [
        left_mult_by_adjoint(A) - right_mult_by_inverse(A)
        for A in SL2C_matrices
    ])

    CC = M.base_ring()
    mp.prec = CC.prec()
    RR = RealField(CC.prec())
    epsilon = RR(2)**(-int(0.8 * mp.prec))
    U, S, V = mp.svd(sage_matrix_to_mpmath(M))
    S = list(mp.chop(S, epsilon))
    if mp.zero not in S:
        return False, None, None
    elif S.count(mp.zero) > 1:
        for i, A in enumerate(SL2C_matrices):
            for B in SL2C_matrices[i + 1:]:
                assert (A * B - B * A).norm() < epsilon

        sig = 'indefinite' if any(abs(A.trace()) > 2
                                  for A in SL2C_matrices) else 'both'
        return True, sig, None
    else:
        in_kernel = list(mp.chop(V.H.column(S.index(mp.zero))))
        J = mp.matrix([in_kernel[:2], in_kernel[2:]])
        iJ = mp.mpc(imag=1) * J
        J1, J2 = J + J.H, iJ + iJ.H
        J = J1 if mp.norm(J1) >= mp.norm(J2) else J2
        J = (1 / mp.sqrt(abs(mp.det(J)))) * J
        J = mpmath_matrix_to_sage(J)
        assert all((A.conjugate_transpose() * J * A - J).norm() < epsilon
                   for A in SL2C_matrices)
        sig = 'definite' if J.det() > 0 else 'indefinite'
        return True, sig, J
Example #26
0
def compute_p_from_w_and_parity(w, parity):
    """
    Compute p such that w - p * pi * i should have imaginary part between
    -pi and pi and p has the same parity as the given value for parity
    (the given value is supposed to be 0 or 1).

    Note that this computation is not verified.
    """

    RF = RealField(w.parent().precision())
    real_part = (w.imag().center() / RF(pi) - parity) / 2
    return 2 * Integer(real_part.round()) + parity
Example #27
0
def tensor_get_an_deg1(L, D, BadPrimeInfo):
    """
    Same as above, except that the BadPrimeInfo
    is now a list of lists of the form
    [p,f] where f is a polynomial.
    """
    s1 = len(L)
    s2 = len(D)
    if s1 < s2:
        S = s1
    if s2 <= s1:
        S = s2
    BadPrimes = []
    for bpi in BadPrimeInfo:
        BadPrimes.append(bpi[0])
    P = prime_range(S + 1)
    Z = S * [1]
    S = RealField()(S)  # fix bug
    for p in P:
        f = S.log(base=p).floor()
        q = 1
        u = 1
        e = D[p - 1]
        if not p in BadPrimes:
            for i in range(f):
                q = q * p
                u = u * e
                Z[q - 1] = u * L[q - 1]
        else:
            i = BadPrimes.index(p)
            e = BadPrimeInfo[i][1]
            F = e.list()[0].parent().fraction_field()
            R = PowerSeriesRing(F, "T", default_prec=f + 1)
            e = R(e)
            A = euler_factor_to_list(e, f)
            for i in range(f):
                q = q * p
                Z[q - 1] = A[i]
    all_an_from_prime_powers(Z)
    return Z
Example #28
0
def tensor_get_an_deg1(L, D, BadPrimeInfo):
    """
    Same as above, except that the BadPrimeInfo
    is now a list of lists of the form
    [p,f] where f is a polynomial.
    """
    s1 = len(L)
    s2 = len(D)
    if s1 < s2:
        S = s1
    if s2 <= s1:
        S = s2
    BadPrimes = []
    for bpi in BadPrimeInfo:
        BadPrimes.append(bpi[0])
    P = prime_range(S+1)
    Z = S * [1]
    S = RealField()(S) # fix bug
    for p in P:
        f = S.log(base=p).floor()
        q = 1
        u = 1
        e = D[p-1]
        if not p in BadPrimes:
            for i in range(f):
                q = q*p
                u = u*e
                Z[q-1] = u*L[q-1]
        else:
            i = BadPrimes.index(p)
            e = BadPrimeInfo[i][1]
            F = e.list()[0].parent().fraction_field()
            R = PowerSeriesRing(F, "T", default_prec=f+1)
            e = R(e)
            A = euler_factor_to_list(e,f)
            for i in range(f):
                q = q*p
                Z[q-1] = A[i]
    all_an_from_prime_powers(Z)
    return Z
Example #29
0
 def sage(self):
     """
     Return as an element of the approriate RealField or
     ComplexField
     """
     if not _within_sage:
         raise ImportError("Not within SAGE.")
     if self.gen.type() == 't_REAL':
         return RealField(self._precision)(self.gen)
     elif self.gen.type() == 't_COMPLEX':
         return ComplexField(self._precision)(self.gen)
     else:
         return self.gen.sage()
Example #30
0
    def evf(cls, m, max_klen, prec=53):
        """
        Estimate norm of target vector.

        :param m: number of samples
        :param klen: length of key to recover
        :param prec: precision to use

        """
        w = 2 ** (max_klen - 1)
        RR = RealField(prec)
        w = RR(w)
        return RR(sqrt(m * (w ** 2 / 3 + 1 / RR(6)) + w ** 2))
Example #31
0
 def __init__(self,
              G,
              k=0,
              prec=53,
              multiplier=None,
              verbose=0,
              holomorphic=True):
     r"""
     Setup the associated space.
     """
     if isinstance(G, (int, Integer)):
         self._N = G
         self._group = MySubgroup(Gamma0(G))
     else:
         self._group = G
         self._N = G.level()
     self._k = k
     self._verbose = verbose
     self._holomorphic = holomorphic
     self._prec = prec
     self._RF = RealField(prec)
     self._CF = ComplexField(prec)
Example #32
0
def lifted_slope(M, target_meridian_holonomy_arg, shapes):
    RR = RealField()
    target = RR(target_meridian_holonomy_arg)
    rho = PSL2CRepOf3ManifoldGroup(M,
                                   target,
                                   rough_shapes=shapes,
                                   precision=1000)
    assert rho.polished_holonomy().check_representation() < 1.0e-100
    rho_real = PSL2RRepOf3ManifoldGroup(rho)
    meridian, longitude = rho.polished_holonomy().peripheral_curves()[0]
    rho_tilde = rho_real.lift_on_cusped_manifold()
    M, L = rho_tilde.peripheral_translations()
    return -L / M
Example #33
0
    def volf(cls, m, p, klen_list, prec=53):
        """
        Lattice volume.

        :param m: number of samples
        :param p: ECDSA modulus
        :param klen_list: list of lengths of key to recover
        :param prec: precision to use

        """
        w = 2 ** (max(klen_list) - 1)
        RR = RealField(prec)
        f_list = [Integer(w / (2 ** (klen - 1))) for klen in klen_list]
        return RR(exp(log(p) * (m - 1) + sum(map(log, f_list)) + log(w)))
Example #34
0
def compute_kernel(args):
    if args.seed is not None:
        set_random_seed(args.seed)
        FPLLL.set_random_seed(args.seed)

    ecdsa = ECDSA(nbits=args.nlen)

    lines, k_list, _ = ecdsa.sample(m=args.m, klen_list=args.klen_list, seed=args.seed, errors=args.e)
    w_list = [2 ** (klen - 1) for klen in args.klen_list]
    f_list = [Integer(max(w_list) / wi) for wi in w_list]

    targetvector = vector([(k - w) * f for k, w, f in zip(k_list, w_list, f_list)] + [max(w_list)])

    try:
        solver = ECDSASolver(ecdsa, lines, m=args.m, d=args.d, threads=args.threads)
    except KeyError:
        raise ValueError("Algorithm {alg} unknown".format(alg=args.alg))

    expected_length = solver.evf(args.m, max(args.klen_list), prec=args.nlen // 2)
    gh = solver.ghf(args.m, ecdsa.n, args.klen_list, prec=args.nlen // 2)
    params = args.params if args.params else {}
    key, res = solver(solver=args.algorithm, flavor=args.flavor, **params)

    RR = RealField(args.nlen // 2)
    logging.info(
        (
            "try: {i:3d}, tag: 0x{tag:016x}, success: {success:1d}, "
            "|v|: 2^{v:.2f}, |b[0]|: 2^{b0:.2f}, "
            "|v|/|b[0]|: {b0r:.3f}, "
            "E|v|/|b[0]|: {eb0r:.3f}, "
            "|v|/E|b[0]|: {b0er:.3f}, "
            "cpu: {cpu:10.1f}s, "
            "wall: {wall:10.1f}s, "
            "work: {total:d}"
        ).format(
            i=args.i,
            tag=args.tag,
            success=int(res.success),
            v=float(log(RR(targetvector.norm()), 2)),
            b0=float(log(RR(res.b0), 2)),
            b0r=float(RR(targetvector.norm()) / RR(res.b0)),
            eb0r=float(RR(expected_length) / RR(res.b0)),
            b0er=float(RR(targetvector.norm()) / gh),
            cpu=float(res.cputime),
            wall=float(res.walltime),
            total=res.ntests,
        )
    )

    return key, res, float(targetvector.norm())
Example #35
0
def parse_file(filename, prec=53):
    from sage.all import RealField, ComplexField
    RR = RealField(prec)
    CC = ComplexField(prec)
    data = open(filename).read()
    open('polys.txt', 'w').write(data)
    data = data.split('THE SOLUTIONS')[-1]
    data = re.subn('[*]{3,}', '', data)[0]
    ans = []
    solutions = re.findall('(solution \d+ : \s* start residual .*?) ==', data,
                           re.DOTALL)
    for sol in solutions:
        kind = sol.split('=')[-1].strip()
        if kind == 'no solution':
            continue
        mult = int(re.search('^m : (\d+)', sol, re.MULTILINE).group(1))
        err = float(re.search('== err :\s+(.*?)\s+= ', sol).group(1))
        coors = re.findall('^ (.*) :\s+(\S*)\s+(\S*)', sol, re.MULTILINE)
        if kind.startswith('real'):
            coors = {
                restore_forbidden(var): RR(real)
                for var, real, imag in coors
            }
            ans.append({
                'kind': 'real',
                'mult': mult,
                'err': err,
                'coors': coors
            })
        elif kind.startswith('complex'):
            coors = {
                restore_forbidden(var): CC(RR(real), RR(imag))
                for var, real, imag in coors
            }
            ans.append({
                'kind': 'complex',
                'mult': mult,
                'err': err,
                'coors': coors
            })

    num_real = int(
        re.search('Number of real solutions\s+:\s(.*).', data).group(1))
    num_complex = int(
        re.search('Number of complex solutions\s+:\s(.*).', data).group(1))
    kinds = [sol['kind'] for sol in ans]
    assert kinds.count('real') == num_real
    assert kinds.count('complex') == num_complex
    return ans
Example #36
0
    def mvf(cls, m, max_klen, prec=53):
        """
        Maximal norm of target vector.

        :param m: number of samples
        :param max_klen: length of key to recover
        :param prec: precision to use


        """
        w = 2 ** (max_klen - 1)
        RR = RealField(prec)
        w = RR(w)
        d = m + 1
        return RR(sqrt(d) * w)
Example #37
0
    def ghf(cls, m, p, klen_list, prec=53):
        """
        Estimate norm of shortest vector according to Gaussian Heuristic.

        :param m: number of samples
        :param p: ECDSA modulus
        :param klen_list: list of lengths of key to recover
        :param prec: precision to use

        """
        # NOTE: The Gaussian Heuristic does not hold in small dimensions
        w = 2 ** (max(klen_list) - 1)
        RR = RealField(prec)
        w = RR(w)
        f_list = [Integer(w / (2 ** (klen - 1))) for klen in klen_list]
        d = m + 1
        log_vol = log(p) * (m - 1) + sum(map(log, f_list)) + log(w)
        lgh = log_gamma(1 + d / 2.0) * (1.0 / d) - log(sqrt(pi)) + log_vol * (1.0 / d)
        return RR(exp(lgh))
Example #38
0
class PeriodPolynomial(SageObject):
    r"""
    Class for (numerical approximations to) period polynomials of modular forms
    
    """
    def __init__(self,f,prec=53,verbose=0,data={}):
        r"""
        Initialize the period polynomial of f.

        INPUT:
         - `f` -- Newform
         - ``
        
        EXAMPLES:

        # First elliptic curve

        sage: f=Newforms(11,2)[0]             
        sage: pp=PeriodPolynomial(f,prec=103)
        sage: L=f.cuspform_lseries()
        sage: pp.petersson_norm()
        0.00390834565612459898524738548154 - 5.53300833748482053164300189100e-35*I
        sage: pp.special_value(1)            
        0.253841860855910684337758923267
        sage: L(1)
        0.253841860855911

        # We can also study rationality of the coefficients of the 
        sage: pp.test_rationality()
        P(f 0)^+/omega_+=1.00000000000000000000000000000
        P(f 0)^-/omega_-=0
        P(f 1)^+/omega_+=-1.00000000000000000000000000000
        P(f 1)^-/omega_-=0
        P(f 2)^+/omega_+=0
        P(f 2)^-/omega_-=1.27412157006452456511355616309e-31 + 1.01489446868406102099789763444e-28*I
        P(f 3)^+/omega_+=-5.00000000000000000000000000133
        P(f 3)^-/omega_-=-1.16793587723237638257725820700e-60 + 8.24993716616779655911027615609e-29*I
        P(f 4)^+/omega_+=-2.50000000000000000000000000073
        P(f 4)^-/omega_-=-3.39765752017206550696948310188e-32 + 2.39999999999999999999999999940*I
        P(f 5)^+/omega_+=2.50000000000000000000000000073
        P(f 5)^-/omega_-=-3.39765752017206550696948310188e-32 + 2.39999999999999999999999999940*I
        P(f 6)^+/omega_+=5.00000000000000000000000000133
        P(f 6)^-/omega_-=1.16793587723237638257725820700e-60 - 8.24993716616779655911027615609e-29*I
        P(f 7)^+/omega_+=5.00000000000000000000000000133
        P(f 7)^-/omega_-=-1.16793587723237638257725820700e-60 + 8.24993716616779655911027615609e-29*I
        P(f 8)^+/omega_+=2.50000000000000000000000000073
        P(f 8)^-/omega_-=3.39765752017206550696948310188e-32 - 2.39999999999999999999999999940*I
        P(f 9)^+/omega_+=-2.50000000000000000000000000073
        P(f 9)^-/omega_-=3.39765752017206550696948310188e-32 - 2.39999999999999999999999999940*I
        P(f10)^+/omega_+=-5.00000000000000000000000000133
        P(f10)^-/omega_-=1.16793587723237638257725820700e-60 - 8.24993716616779655911027615609e-29*I
        P(f11)^+/omega_+=0
        P(f11)^-/omega_-=-1.27412157006452456511355616309e-31 - 1.01489446868406102099789763444e-28*I
        o1= 0.0404001869188632792144191985239*I
        o2= -1.36955018267536771772869542629e-33 - 0.0967407815209822856536332369020*I

        
        sage: f=Newforms(5,8,names='a')[0];f
        q - 14*q^2 - 48*q^3 + 68*q^4 + 125*q^5 + O(q^6)
        sage: L=f.cuspform_lseries()  
        sage: pp=PeriodPolynomial(f,prec=103)
        sage: pp.special_value(4)
        -3.34183629241748201816194829811e-29 + 8.45531852674217908762910051272e-60*I
        sage: pp.special_value(3)
        -0.729970592499451187790964533256 + 2.56020879251697431818575640846e-31*I
        sage: L(3)                  
        -0.729970592499451
        sage: L(4)
        0.000000000000000
        
        



        """
        self._f = f
        self._level = None
        if data<>{}:
            self.init_from_dict(data)
        if self._level==None:
            self._level = f.level()
            self._k = f.weight()
            self._w = self._k - 2
            self._verbose = verbose
            self._polynomials = {}
            self._prec = prec
            self._rks = {}
            self._coset_reps={}
            self._dim = Gamma0(self._level).index()
            self._coefficients_at_coset = {}
            self._base_coeffs=[]
            self._base_coeffs_embedding=[]
            self._M = {}
            self._M0 = 0
            self._width={}
            self._shift={}
            self._atkin_lehner={}
            self._integrals={}
            self._pplus = {}
            self._pminus={}
            self._peterson_norm=0
            self._canonical_periods=[]
        # Check
        assert is_squarefree(self._level)
        ## Some numerical definitions
        self._RF = RealField(prec)
        self._eps = self._RF(2)**-self._RF(prec)
        self._pi = self._RF.pi()


    def __repr__(self):
        s="Period Polynomial associated to the weight {0} and level {1} MF {2}".format(self._k,self._level,self._f)
        return s

    def __reduce__(self):
        return (PeriodPolynomial,(self._f,self._prec,self._verbose,self.__dict__))
    

    ## If the dict is non-empty we initialize from it
    def init_from_dict(self,data={}):
        self._level = data.get("_level")
        self._k = data.get("_k",None)
        self._w = data.get("_w")
        self._verbose = data.get("_verbose")
        self._polynomials = data.get("_polynomials")
        self._prec = data.get("_prec")
        self._rks = data.get("_rks")
        self._coset_reps=data.get("_coset_reps")
        self._dim = data.get("_dim")
        self._coefficients_at_coset =data.get("_coefficients_at_coset")
        self._base_coeffs=data.get("_base_coeffs")
        self._base_coeffs_embedding=data.get("_base_coeffs_embedding")
        self._M = data.get("_M")
        self._M0 = data.get("_M0")
        self._width=data.get("_width")
        self._shift=data.get("_shift")
        self._atkin_lehner=data.get("_atkin_lehner")
        self._integrals=data.get("_integrals")
        self._pplus =data.get("_pplus")
        self._pminus=data.get("_pminus")
        self._peterson_norm=data.get("_peterson_norm")
        self._canonical_periods=data.get("_canonical_periods")
        
        

    def level(self):
        return self._level

    def weight(self):
        return self._k

    def function(self):
        return self._f

    def polynomial(self,n):
        if not self._polynomials:
            self._get_polynomials()
        if hasattr(n,"matrix"):
            if n in SL2Z:
                n = self._get_coset_n(n)
            else:
                raise ValueError,"{0} not in SL(2,Z)".format(n)
        return self._polynomials.get(n,None)

    def polynomials(self):
        r"""
        Return a list of the polynomials  P(f|A_n)(X), 0<=n<dim
        """
        if not self._polynomials:
            self._get_polynomials()
        return self._polynomials
    

    def special_value(self,n):
        r"""
        Compute L(f,n)
        Recall that L(f,n+1)=(2pii)^(n+1)*(-1)^(n+1)/Gamma(n+1) * r_n(f)
        """
        RF = RealField(self._prec)
        CF = ComplexField(self._prec)
        if n < 0 or n>self._w+1:
            print "{0} is not a special point for this f!".format(n)
            return 
        if not self._polynomials:
            self._get_polynomials()
        rk = self.get_rk(0,n-1)
        return CF(0,2*RF.pi())**(n)*(-1)**(n)/RF(n).gamma()*rk
        #print "Warning: r_{0}(f) not computed!".format(n)


    def polynomial_plus(self,n):
        if not self._pplus.has_key(n):
            E = Matrix(ZZ,2,2,[-1,0,0,1])
            p1 = self.polynomial(n)
            p2 = self.slash_action(n,E)
            self._pplus[n]=(p1+p2)/2
            self._pminus[n]=(p1-p2)/2
        return self._pplus[n]

    def polynomial_minus(self,n):
        if not self._pminus.has_key(n):
            E = Matrix(ZZ,2,2,[-1,0,0,1])
            p1 = self.polynomial(n)
            p2 = self.slash_action(n,E)
            self._pplus[n]=(p1+p2)/2
            self._pminus[n]=(p1-p2)/2
        return self._pminus[n]        


    def petersson_norm(self,type=1):
        r"""
        Compute the Petersson norm of f.

        ALGORITHM:

        Uses
        (f,f) = < rho_{f}^{+} | T - T^-1 , rho_f^{-}>
        for k even and 
        (f,f) = < rho_{f}^{+} | T - T^-1 , rho_f^{+}>
        for k odd.
        See e.g. Thm 3.3. in Pasol - Popa "Modular forms and period polynomials"
        """
        if self._peterson_norm<>0:
            return self._peterson_norm
        T=SL2Z([1,1,0,1])
        Ti=SL2Z([1,-1,0,1])
        norm = 0
        for n in range(self._dim):
            if type==1:
                p1 = self.slash_action(n,T,sym='plus')
                p2 = self.slash_action(n,Ti,sym='plus')
            else:
                p1 = self.slash_action(n,T,sym='minus')
                p2 = self.slash_action(n,Ti,sym='minus')
            pL = p1 - p2
            #print "Pl=",pL
            if self.function().weight() % 2 == 1:
                if type==1:
                    pR = self.polynomial_plus(n)
                else:
                    pR = self.polynomial_minus(n)
            else:
                if type==1:
                    pR = self.polynomial_minus(n)
                else:
                    pR = self.polynomial_plus(n)
            #print "PR=",pR
            t = self.pair_two_pols(pL,pR)
           
            #print "t=",t
            norm+=t
        CF=ComplexField(self._prec)
        c2 = CF(3)*CF(0,2)**(self._k-1)
        self._peterson_norm = -norm/c2
        return self._peterson_norm



    
    def omega_plus_minus(self):
        r"""
        Compute two  periods $\omega_+$ and $\omega_{-}$
        where we take $\omega_{+}$ to be the highest (non-vanishing)
        coefficient of $\rho(f)$ (corresponding to the trivial coset)
        and $\omega_{-}=||f||/\omega_{+}$.

        OUTPUT:
        - '\omega_{+},\omega_{-}'
        """
        if self._canonical_periods<>[]:
            return self._canonical_periods
        norm = self.petersson_norm()
        o1 = self.get_rk(0,0)
        o2 = norm/o1
        self._o1 = o1
        self._o2 = o2
        self._canonical_periods = o1,o2
        return o1,o2
    
    def pair_two_pols(self,p1,p2):
        res = 0
        cp1 = p1.coefficients(sparse=False)
        cp2 = p2.coefficients(sparse=False)
        for n in range(self._w+1):
            if n < len(cp1):
                c1 = cp1[n]
            else:
                c1 = 0
            k = self._w -n
            if k < len(cp2):
                c2 = cp2[k]
            else:
                c2 = 0
            term = c1*conjugate(c2)*(-1)**(self._w-n)/binomial(self._w,n)
            res = res + term
        return res/self._dim
            
    def _get_polynomials(self,prec=None):
        r"""
        Compute all P(f|A_n)(X), 0<=n<dim
        """
        if prec==None:
            prec = self._prec
        for n in range(self._dim):
            for k in range(self._w+1):
                self.get_rk(n,k)
            self._polynomials[n]=self._get_polynomial(n)
        return self._polynomials
    
    def _get_polynomial(self,n):
        r"""
        Compute P(f|A_n)(X)
        """
        if self._polynomials.has_key(n):
            return self._polynomials[n]
        CF = ComplexField(self._prec)
        X=CF['X'].gens()[0]
        k = self._k
        pols = {}
        ## For each component we get a polynomial
        p = X.parent().zero()
        for l in range(self._w+1):
            rk = self.get_rk(n,self._w-l)
            if self._verbose>0:
                print "rk=",rk
            fak = binomial(self._w,l)*(-1)**l
            p+=CF(fak)*CF(rk)*X**l
        self._polynomials[n]=p
        return p
#        self._polynomials = #get_period_pol_from_rks(self._f,self._rks,prec=prec,verbose=self._verbose)

        
    def coset_rep(self,n):
        r"""
        Return coset rep nr. n
        """
        if not self._coset_reps:
            self._set_coset_reps()
        return self._coset_reps[n]


    def _set_coset_reps(self):
        if is_prime(self._level):
            self._coset_reps[0] = SL2Z([1,0,0,1])
            for n in range(self._level):
                self._coset_reps[n+1] = SL2Z([0,-1,1,n])
        else:
            G = Gamma0(self._level)
            n = 0
            for A in G.coset_reps():
                self._coset_reps[n] = A
                n+=1
        
    def _get_coset_n(self,A):
        r"""
        Find n s.t. A in Gamma_0(N)A_n 
        """
        G = Gamma0(self._level)
        if A in G:
            return 0  ## Always use 0 for the trivial coset
        else:
            n=0
            for n in range(self._dim):
                An  = self.coset_rep(n)
                if A*An**-1 in G:
                    return n
                n+=1
        raise ArithmeticError,"Can not find coset of A={0}".format(A)


    def _get_shifted_coset_m(self,n,A):
        r"""
        Get the index m s.t. A_n*A**-1 is in Gamma0(N)A_m
        """
        An = self.coset_rep(n)
        if A.det()==1:
            m = self._get_coset_n(An*A**-1)
        elif A.det()==-1 and A[0,1]==0 and A[1,0]==0:
            AE = SL2Z([An[0,0],-An[0,1],-An[1,0],An[1,1]])
            m = self._get_coset_n(AE)
        else:
            raise ValueError,"Call with SL2Z element or [-1,0,1,0]. Got:{0}".format(E)
        return m
        
    def slash_action(self,n,gamma,sym='none'):
        r"""
        Act of P^{+/-}(f|A_n) with an element of SL2Z
        """        
        # First shift the coset
        m = self._get_shifted_coset_m(n,gamma)
        #print "m=",m
        if sym=='plus':
            P0 = self.polynomial_plus(m)
        elif sym=='minus':
            P0 = self.polynomial_minus(m)
        else:
            P0 = self.polynomial(m)
        if P0==None:
            return
        X = P0.parent().gens()[0]
        coeffs = P0.coefficients(sparse=False)
        p = P0.parent().zero()
        if hasattr(gamma,"matrix"):
            a,b,c,d=gamma
        else:
            a,b,c,d=gamma.list()
            
        denom = (c*X+d)
        numer = (a*X+b)
        w = self._w
        for k in P0.exponents():
            ak = coeffs[k]
            p+=ak*numer**k*denom**(w-k)
        return p


    def slash_action_vector(self,gamma,sym=0):
        res = {}
        for n in range(self._dim):
            res[n] = self.polynomial_slash_action(n,gamma,sym=sym)
        

    def __mul__(self,l):
        r"""
        Acts on all polynomials of self by l
        """

        res = {}
        for n in range(self._dim):
            if l in SL2Z:
                res[n]=self.slash_action(n,l)
            elif isinstance(l,list):
                res[n] = self.action_by_lin_comb(n,l)
            else:
                raise NotImplementedError

        return res
    
    def action_by_lin_comb(self,n,l,sym=0):
        r"""
        Act on polynomial n of self by the element of the group ring c_1*A_1+...+c_k*A_k
        INPUT:
        -`l` -- list of pairs (c,A) with c complex and A in SL2Z
        """
        p = self.polynomial(n).parent().zero()
        try:
            for c,A in l:            
                p+=c*self.slash_action(n,A,sym=sym)
        except:
            raise ValueError,"Need a list of tuples! Got:{0}".format(l)
        return p


    def maxM(self):
        r"""
        Compute the maximum truncation point.
        """
        if self._M0 == 0:
            self.get_shifts_and_widths()
        return self._M0

    def set_M(self,Mset):
        r"""
        Sets the truncation point to at most a fixed integer Mset
        """
        M0 = self.maxM()
        for n in range(self._dim):
            m = self._M[n]
            if m > Mset:
                self._M[n] = Mset
        if M0>Mset:
            self._M0 = Mset
        if verbose>0:
            print "Warning: the precision of results might be lower than expected!"
        
    
    def truncation_M(self,n):
        r"""
        Compute the truncation point at coset nr. n.
        """        
        if not self._M.has_key(n):
            h,w = self.get_shift_and_width_for_coset(n)
            #self._M[n]=self._get_truncation(w,self._k,self._prec)
            self._M[n]=get_truncation(self._k,w,self._prec)
        return self._M[n]


    
    def coefficients_f(self):
        r"""
        Compute the maximum number of coefficients we need to use (with current precision).
        """
        if not self._base_coeffs:
            kf = 0.5*(self._k-1.0)
            M0 = self.maxM()
            prec1 =  self._prec + ceil(log_b(M0*6,2))
            if hasattr(self._f,"O"):
                self._base_coeffs = self._f.coefficients()
                if len(self._base_coeffs)<M0:
                    raise ValueError,"Too few coefficients available!"
            else:
                self._base_coeffs = self._f.coefficients(ZZ(M0))
            self._base_coeffs_embedding=[]
            #precn = prec1
            if hasattr(self._base_coeffs[0],"complex_embedding"):
                n=1
                #print "kf=",kf
                #print "kfprec1=",prec1
                for a in self._base_coeffs:
                    ## Use precision high enough that c(n)/n^((k-1)/2) have self._prec correct bits
                    precn = prec1 + kf*ceil(log_b(n,2))
                    self._base_coeffs_embedding.append(a.complex_embedding(precn))
                    n+=1
            else:
                ## Here we have a rational number so we can ue the default number of bits
                n=1
                for a in self._base_coeffs:
                    precn = prec1 + kf*ceil(log_b(n,2))
                    aa = RealField(precn)(a)
                    self._base_coeffs_embedding.append(a) #self._RF(a))
                    n+=1
        return self._base_coeffs
    
    def coefficient_at_coset(self,n):
        r"""
        Compute Fourier coefficients of f|A_n 
        """
        if hasattr(n,"matrix"):
            n = self._get_coset_n(n)
        if not self._base_coeffs:
            self.coefficients_f()
        CF = ComplexField(self._prec)
        if not self._coefficients_at_coset.has_key(n):
            M = self.truncation_M(n)
            h,w = self.get_shift_and_width_for_coset(n)
            zN = CyclotomicField(w).gens()[0]
            prec1 = self._prec + ceil(log_b(M,2))
            RF = RealField(prec1)
            coeffs=[]
            fak  = RF(w)**-(RF(self._k)/RF(2))
            #print "f=",f,n
            for i in range(M):
                al = CF(self.atkin_lehner(n))
                c0 = self._base_coeffs_embedding[i]
                #if hasattr(c0,"complex_embeddings"):
                #    c0 = c0.complex_embedding(prec1)
                #else:
                #    c0 = CF(c0)
                qN = zN**((i+1)*h)
                #print "qN=",qN,type(qN)
                an = fak*al*c0*qN.complex_embedding(prec1)
                #an = self.atkin_lehner(n)*self._base_coeffs[i]*zN**((i+1)*h)
                #an = f*an.complex_embedding(prec1)
                coeffs.append(an)
            self._coefficients_at_coset[n] = coeffs
        return self._coefficients_at_coset[n]

    def get_rk(self,n,k):
        r"""
        Compute the coefficient r_k((f|A_n))
        """
        if not self._rks.has_key((n,k)):
            S,T = SL2Z.gens()
            nstar = self._get_shifted_coset_m(n,S)
            kstar = self._k-2-k
            i1 = self.get_integral_from_1_to_oo(n,k)
            i2 = self.get_integral_from_1_to_oo(nstar,kstar)
            if self._verbose>0:
                print "i1=",i1
                print "i2=",i2
            self._rks[(n,k)] = i1+i2*(-1)**(k+1)
        return self._rks[(n,k)]

    def get_integral_from_1_to_oo(self,n,k):
        r"""
        Compute \int_{1}^{+Infinity} f|A_n(it) t^k dt 
        """
        CF = ComplexField(self._prec)
        if not self._integrals.has_key((n,k)):
            c = self.coefficient_at_coset(n)
            w = self.width(n)
            my_integral = 0
            if self._prec<=53:
                if w==1:
                    l = 1
                    for a in c: 
                        my_integral+= a*exp_z_integral(CF(0,1),l,k)
                        l+=1
                else:
                    l = 1
                    for a in c: 
                        my_integral+= a*exp_z_integral_w(CF(0,1),l,w,k)
                        l+=1
            else:
                l = 1
                for a in c: 
                    my_integral+= a*exp_z_integral_wmp(CF(0,1),l,w,k)
                    l+=1
            self._integrals[(n,k)]=my_integral
        return self._integrals[(n,k)]

            
    def width(self,n):
        r"""
        Compute the width of the cusp at coset nr. n.
        """
        if not self._width.has_key(n):
            self.get_shifts_and_widths()
        return self._width[n]
        
    def atkin_lehner(self,n):
        r"""
        Compute the Atkin-Lehner eigenvalue at the cusp of coset nr. n.
        """
        if not self._atkin_lehner.has_key(n):
            A = self.coset_rep(n)
            c = Cusp(A[0,0],A[1,0])
            G=Gamma0(self._level)
            for Q in divisors(self._level):
                cQ = Cusp(Q,self._level)
                if G.are_equivalent(c,cQ):
                    self._atkin_lehner[n]=self._f.atkin_lehner_eigenvalue(Q)
                    break
        return  self._atkin_lehner[n]
    
    def get_shifts_and_widths(self):
        r"""
        Compute the shifts and widths of all cosets.
        """
        self._width[0]=1
        self._shift[0]=0
        for n in range(0,self._dim):
            h,w = self.get_shift_and_width_for_coset(n)            
            self._M[n] = get_truncation(self._k,w,self._prec)
        self._M0 = max(self._M.values())
            
    def get_shift_and_width_for_coset(self,n):
        r"""
        Compute the shift and width of coset nr. n.
        """
        if self._shift.has_key(n) and self._width.has_key(n):
            return self._shift[n],self._width[n]
        if not is_squarefree(self._level):
            raise NotImplementedError,"Only square-free levels implemented"
        G = Gamma0(self._level)
        A = self.coset_rep(n)
        a = A[0,0]; c=A[1,0]
        width = G.cusp_width(Cusp(a,c))
        if self._verbose>0:
            print "width=",width
        Amat = Matrix(ZZ,2,2,A.matrix().list())
        h = -1 
        for j in range(width):
            Th = Matrix(ZZ,2,2,[width,-j,0,1])
            W = Amat*Th
            if self._verbose>1:
                print "W=",W
                
            if self.is_involution(W):
                h = j
                break
        if h<0:
            raise ArithmeticError,"Could not find shift!"
        self._shift[n]=h
        self._width[n]=width
        return h,width        

    def is_involution(self,W,verbose=0):
        r"""
        Explicit test if W is an involution of Gamma0(self._level)
        """
        G = Gamma0(self._level)
        for g in G.gens():
            gg = Matrix(ZZ,2,2,g.matrix().list())
            g1 = W*gg*W**-1
            if verbose>0:
                print "WgW^-1=",g1
            if g1 not in G:
                return False
        W2 = W*W
        c = gcd(W2.list())
        if c>1:
            W2 = W2/c
        if verbose>0:
            print "W^2=",W2
        if W2 not in G:
            return False
        return True
    
    def test_relations(self):
        
        I = SL2Z([1,0,0,1])
        S = SL2Z([0,-1,1,0])
        U = SL2Z([1,-1,1,0])
        U2 = SL2Z([0,-1,1,-1])
        lS = [(1,I),(1,S)]
        lU = [(1,I),(1,U),(1,U2)]
        pS = self*lS
        pU = self*lU 
        maxS = 0; maxU=0
        if self._verbose>0:
            print "pS=",pS
            print "pU=",pU
        for p in pS.values():
            if hasattr(p,"coeffs"):
                if p.coefficients(sparse=False)<>[]:
                    tmp = max(map(abs,p.coefficients(sparse=False)))
                else:
                    tmp = 0
            else:
                tmp = abs(p)
            if tmp>maxS:
                maxS = tmp
        for p in pU.values():
            if hasattr(p,"coefficients"):
                if p.coefficients(sparse=False)<>[]:
                    tmp = max(map(abs,p.coefficients(sparse=False)))
                else:
                    tmp = 0
            else:
                tmp = abs(p)
            if tmp>maxU:
                maxU = tmp                
        print "Max coeff of self|(1+S)=",maxS
        print "Max coeff of self|(1+U+U^2)=",maxU


    def test_relations_plusminus(self):
        
        I = SL2Z([1,0,0,1])
        S = SL2Z([0,-1,1,0])
        U = SL2Z([1,-1,1,0])
        U2 = SL2Z([0,-1,1,-1])
        lS = [(1,I),(1,S)]
        lU = [(1,I),(1,U),(1,U2)]
        ppp1={};ppp2={};ppp3={};ppp4={}
        for n in range(self._dim):
            p1 = self.action_by_lin_comb(n,lS,sym=1)
            p2 = self.action_by_lin_comb(n,lU,sym=1)
            ppp1[n]=p1
            ppp2[n]=p2
            p1 = self.action_by_lin_comb(n,lS,sym=-1)
            p2 = self.action_by_lin_comb(n,lU,sym=-1)
            ppp3[n]=p1
            ppp4[n]=p2

        for pp in [ppp1,ppp2,ppp3,ppp4]:
            maxv=0
            for p in pp.values():
                if hasattr(p,"coeffs"):
                    if p.coefficients(sparse=False)<>[]:
                        tmp = max(map(abs,p.coefficients(sparse=False)))
                    else:
                        tmp = 0
                else:
                    tmp = abs(p)
                if tmp>maxv:
                    maxv = tmp
            print "maxv=",maxv

        #print "Max coeff of self|(1+S)=",maxS
        #print "Max coeff of self|(1+U+U^2)=",maxU

    def test_rationality(self):        
        omega1 = self.canonical_periods()[0]
        omega2 = self.canonical_periods()[1]
        for n in range(self._dim):          
            pp = self.polynomial_plus(n)/omega1
            pm = self.polynomial_minus(n)/omega2
            print "P(f{0:2d})^+/omega_+={1}".format(n,pp)
            print "P(f{0:2d})^-/omega_-={1}".format(n,pm)
        print "o1=",omega1
        print "o2=",omega2
Example #39
0
    def __init__(self,f,prec=53,verbose=0,data={}):
        r"""
        Initialize the period polynomial of f.

        INPUT:
         - `f` -- Newform
         - ``
        
        EXAMPLES:

        # First elliptic curve

        sage: f=Newforms(11,2)[0]             
        sage: pp=PeriodPolynomial(f,prec=103)
        sage: L=f.cuspform_lseries()
        sage: pp.petersson_norm()
        0.00390834565612459898524738548154 - 5.53300833748482053164300189100e-35*I
        sage: pp.special_value(1)            
        0.253841860855910684337758923267
        sage: L(1)
        0.253841860855911

        # We can also study rationality of the coefficients of the 
        sage: pp.test_rationality()
        P(f 0)^+/omega_+=1.00000000000000000000000000000
        P(f 0)^-/omega_-=0
        P(f 1)^+/omega_+=-1.00000000000000000000000000000
        P(f 1)^-/omega_-=0
        P(f 2)^+/omega_+=0
        P(f 2)^-/omega_-=1.27412157006452456511355616309e-31 + 1.01489446868406102099789763444e-28*I
        P(f 3)^+/omega_+=-5.00000000000000000000000000133
        P(f 3)^-/omega_-=-1.16793587723237638257725820700e-60 + 8.24993716616779655911027615609e-29*I
        P(f 4)^+/omega_+=-2.50000000000000000000000000073
        P(f 4)^-/omega_-=-3.39765752017206550696948310188e-32 + 2.39999999999999999999999999940*I
        P(f 5)^+/omega_+=2.50000000000000000000000000073
        P(f 5)^-/omega_-=-3.39765752017206550696948310188e-32 + 2.39999999999999999999999999940*I
        P(f 6)^+/omega_+=5.00000000000000000000000000133
        P(f 6)^-/omega_-=1.16793587723237638257725820700e-60 - 8.24993716616779655911027615609e-29*I
        P(f 7)^+/omega_+=5.00000000000000000000000000133
        P(f 7)^-/omega_-=-1.16793587723237638257725820700e-60 + 8.24993716616779655911027615609e-29*I
        P(f 8)^+/omega_+=2.50000000000000000000000000073
        P(f 8)^-/omega_-=3.39765752017206550696948310188e-32 - 2.39999999999999999999999999940*I
        P(f 9)^+/omega_+=-2.50000000000000000000000000073
        P(f 9)^-/omega_-=3.39765752017206550696948310188e-32 - 2.39999999999999999999999999940*I
        P(f10)^+/omega_+=-5.00000000000000000000000000133
        P(f10)^-/omega_-=1.16793587723237638257725820700e-60 - 8.24993716616779655911027615609e-29*I
        P(f11)^+/omega_+=0
        P(f11)^-/omega_-=-1.27412157006452456511355616309e-31 - 1.01489446868406102099789763444e-28*I
        o1= 0.0404001869188632792144191985239*I
        o2= -1.36955018267536771772869542629e-33 - 0.0967407815209822856536332369020*I

        
        sage: f=Newforms(5,8,names='a')[0];f
        q - 14*q^2 - 48*q^3 + 68*q^4 + 125*q^5 + O(q^6)
        sage: L=f.cuspform_lseries()  
        sage: pp=PeriodPolynomial(f,prec=103)
        sage: pp.special_value(4)
        -3.34183629241748201816194829811e-29 + 8.45531852674217908762910051272e-60*I
        sage: pp.special_value(3)
        -0.729970592499451187790964533256 + 2.56020879251697431818575640846e-31*I
        sage: L(3)                  
        -0.729970592499451
        sage: L(4)
        0.000000000000000
        
        



        """
        self._f = f
        self._level = None
        if data<>{}:
            self.init_from_dict(data)
        if self._level==None:
            self._level = f.level()
            self._k = f.weight()
            self._w = self._k - 2
            self._verbose = verbose
            self._polynomials = {}
            self._prec = prec
            self._rks = {}
            self._coset_reps={}
            self._dim = Gamma0(self._level).index()
            self._coefficients_at_coset = {}
            self._base_coeffs=[]
            self._base_coeffs_embedding=[]
            self._M = {}
            self._M0 = 0
            self._width={}
            self._shift={}
            self._atkin_lehner={}
            self._integrals={}
            self._pplus = {}
            self._pminus={}
            self._peterson_norm=0
            self._canonical_periods=[]
        # Check
        assert is_squarefree(self._level)
        ## Some numerical definitions
        self._RF = RealField(prec)
        self._eps = self._RF(2)**-self._RF(prec)
        self._pi = self._RF.pi()