Example #1
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 #2
0
    def from_conjugacy_class_index_to_polynomial(self, index):
        """ A function converting from a conjugacy class index (starting at 1) to the local Euler polynomial.
            Saves a sequence of processed polynomials, obtained from the local factors table, so it can reuse computations from prime to prime
            This sequence is indexed by conjugacy class indices (starting at 1, filled with dummy first) and gives the corresponding polynomials in the form
            [coeff_deg_0, coeff_deg_1, ...], where coeff_deg_i is in ComplexField(). This could be changed later, or made parametrizable
        """
        try:
            return self._from_conjugacy_class_index_to_polynomial_fn(index)
        except AttributeError:
            local_factors = self.local_factors_table()
            field = ComplexField()
            root_of_unity = exp(
                (field.gen()) * 2 * field.pi() / int(self.character_field()))
            local_factor_processed_pols = [
                0
            ]  # dummy to account for the shift in indices
            for pol in local_factors:
                local_factor_processed_pols.append(
                    process_polynomial_over_algebraic_integer(
                        pol, field, root_of_unity))

            def tmp(conjugacy_class_index_start_1):
                return local_factor_processed_pols[
                    conjugacy_class_index_start_1]

            self._from_conjugacy_class_index_to_polynomial_fn = tmp
            return self._from_conjugacy_class_index_to_polynomial_fn(index)
Example #3
0
 def eu(p):
     """
     local euler factor
     """
     if self.selfdual:
         K = QQ
     else:
         K = ComplexField()
     R = PolynomialRing(K, "T")
     T = R.gens()[0]
     if self.conductor % p != 0:
         return 1 - ComplexField()(chi(p)) * T
     else:
         return R(1)
Example #4
0
def AJ1_digits(f, P, desired_digits, mesh=4):
    for k in range(1, f.degree() + 1):
        assert mesh >= 2
        # the guess should take less than 2s
        working_digits = 300
        SetPariPrec(working_digits)
        CF = ComplexField(ceil(RR(log(10) / log(2)) * working_digits))
        aj = {}
        correct_digits = {}
        sum = 0
        total = 0
        guess = 10000
        CF = ComplexField(log(10) / log(2) * working_digits)
        for i in range(mesh, max(0, mesh - 3), -1):
            PariIntNumInit(i)
            aj[i] = AJ1(CF, f, P, k)
            if i < mesh:
                correct_digits[i] = RR((-log(
                    max([
                        abs(CF((aj[mesh][j] - x) / aj[mesh][j]))
                        for j, x in enumerate(aj[i])
                    ])) / log(10.)) / working_digits)
            if i + 1 < mesh:
                sum += correct_digits[i + 1] / correct_digits[i]
                total += 1
        for i in sorted(correct_digits.keys()):
            if correct_digits[i] > 1:
                guess = i
                break
        avg = sum / total
        if guess == 0 and avg > 1.1:
            guess = mesh - 1 + ceil(
                log((1.1 / correct_digits[mesh - 1])) / log(avg))

        if guess != 0 and 2**guess * desired_digits**2 * log(
                RR(desired_digits))**3 < (300**2 * 2**11 * log(RR(300))**3):
            SetPariPrec(ceil(desired_digits) + 10 * guess)
            PariIntNumInit(guess)
            CF = ComplexField(log(10) / log(2) * desired_digits)
            result = vector(CF, AJ1(CF, f, P, k))
            # avoiding memory leaks
            gp._reset_expect()
            load_gp()
            return result
    else:
        gp._reset_expect()
        load_gp()
        raise OverflowError
Example #5
0
 def coefficient_embedding(self, n, i):
     r"""
     Return the i-th complex embedding of coefficient C(n).
     Note that if it is not in the dictionary we compute the embedding (but not the coefficient).
     """
     embc = self._embeddings['values'].get(n, None)
     bitprec = self._embeddings['bitprec']
     if embc is None:
         c = self.coefficient(n)
         if hasattr(c, "complex_embeddings"):
             embc = c.complex_embeddings(bitprec)
         else:
             embc = [
                 ComplexField(bitprec)(c)
                 for x in range(self.coefficient_field_degree)
             ]
         self._embeddings['values'][n] = embc
     else:
         if len(embc) < self.coefficient_field_degree:
             embc = [embc[0] for x in range(self.coefficient_field_degree)]
             self._embeddings['values'][n] = embc
     if i > len(embc):
         raise ValueError, "Embedding nr. {0} does not exist of a number field of degree {1},embc={2}".format(
             i, self.coefficient_field.absolute_degree(), embc)
     return embc[i]
Example #6
0
 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)]
Example #7
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 #8
0
 def polish_R_longitude_vals(self, precision=196):
     R = ComplexField(precision)
     L_holo = self.gluing_system.L_nomial
     # The minus sign is because the FFT path is oriented clockwise.
     path = [
         R(self.radius) * U1Q(-n, self.order, precision=precision)
         for n in range(self.order)
     ]
     holos = []
     evs = []
     self._print('Polishing shapes to %d bits precision:' % precision)
     for m in range(self.degree):
         row = []
         for n in range(self.order):
             self._print('\rlift %d %d   ' % (m, n), end='')
             r = self.R_fibers[n].shapes[m]
             s = PolishedShapeSet(rough_shapes=r,
                                  target_holonomy=path[n],
                                  precision=precision)
             row.append(L_holo(array(list(s))))
         holos.append(row)
         self._print('\r', end='')
         row = [sqrt(z) for z in row]
         row = [
             self.set_sign(choice, z)
             for choice, z in zip(self.R_choices[m], row)
         ]
         evs.append(row)
     self.polished_R_path = path
     self.polished_R_longitude_holos = holos
     self.polished_R_longitude_evs = evs
Example #9
0
def bisection(H, low, high, s, target_slope, epsilon=1.0e-8):
    CC = ComplexField()
    low_fiber = H.T_fibers[low]
    high_fiber = H.T_fibers[high]
    M = H.manifold
    F = H.fibrator
    assert check_slope(H, low, s) < target_slope < check_slope(H, high, s)
    print('finding:', target_slope)
    count = 0
    while count < 100:
        z = (low_fiber.H_meridian + high_fiber.H_meridian) / 2
        target_holonomy = z / abs(z)
        target_holonomy_arg = CC(target_holonomy).log().imag()
        new_fiber = H.transport(low_fiber, complex(target_holonomy))
        shapes = new_fiber.shapes[s]
        new_slope = lifted_slope(M, target_holonomy_arg, shapes)
        if abs(new_slope - target_slope) < epsilon:
            return new_fiber.shapes[s]
        if new_slope < target_slope:
            low_fiber = new_fiber
            print(new_slope, 'too low')
        else:
            high_fiber = new_fiber
            print(new_slope, 'too high')
        count += 1
        print(count)
    print('limit exceeded')
    return new_fiber.shapes[s]
Example #10
0
    def __call__(self, prec):
        roots = [r[0] for r in self._min_poly.roots(ComplexField(prec))]

        def dist_to_defining_root(z):
            return abs(z - self._approx_root)

        return sorted(roots, key=dist_to_defining_root)[0]
 def __init__(self, f, prec, verbose=False):
     self.verbose = verbose
     self.prec = prec
     self.f = f
     self.C = ComplexField(prec)
     self.Pic = PicardGroup.PicardGroup(f, self.C, self.verbose)
     self.iajlocal = InvertAJlocal.InvertAJlocal(f, prec, verbose=verbose)
     self.genus = self.iajlocal
Example #12
0
 def _initialize(self):
     N, F = self.N, ComplexField(self.precision)
     self.zhat = array([F((-2 * k * pi * I / N).exp()) for k in range(N)],
                       dtype='O')
     self.izhat = array([F((2 * k * pi * I / N).exp()) for k in range(N)],
                        dtype='O')
     self.z2hat = self.zhat.take(xrange(0, 2 * N, 2), mode='wrap')
     self.iz2hat = self.izhat.take(xrange(0, 2 * N, 2), mode='wrap')
Example #13
0
def signature_via_numpy(A):
    CC = ComplexField(53)
    A = A.change_ring(CC).numpy()
    assert np.linalg.norm(A - A.conjugate().transpose()) < 10e-10
    eigs = np.linalg.eigh(A)[0]
    smallest = min(np.abs(eigs))
    assert smallest > 1e-5
    return np.sum(eigs > 0) - np.sum(eigs < 0)
Example #14
0
    def init_dir_char(self, chi):
        """
        Initiate with a Web Dirichlet character.
        """
        self.original_object = [chi]
        chi = chi.chi.primitive_character()
        self.object_type = "dirichletcharacter"
        self.dim = 1
        self.motivic_weight = 0
        self.conductor = ZZ(chi.conductor())
        self.bad_semistable_primes = []
        self.bad_pot_good = self.conductor.prime_factors()
        if chi.is_odd():
            aa = 1
            bb = I
        else:
            aa = 0
            bb = 1
        self.sign = chi.gauss_sum_numerical() / (bb *
                                                 float(sqrt(chi.modulus())))
        # this has now type python complex. later we need a gp complex
        self.sign = ComplexField()(self.sign)
        self.mu_fe = [aa]
        self.nu_fe = []
        self.gammaV = [aa]
        self.langlands = True
        self.selfdual = (chi.multiplicative_order() <= 2)
        # rather than all(  abs(chi(m).imag) < 0.0001 for m in range(chi.modulus() ) )
        self.primitive = True
        self.set_dokchitser_Lfunction()
        self.set_number_of_coefficients()
        self.dirichlet_coefficients = [
            chi(m) for m in range(self.numcoeff + 1)
        ]
        if self.selfdual:
            self.coefficient_type = 2
        else:
            self.coefficient_type = 3
        self.coefficient_period = chi.modulus()
        self.besancon_bound = 10000

        def eu(p):
            """
            local euler factor
            """
            if self.selfdual:
                K = QQ
            else:
                K = ComplexField()
            R = PolynomialRing(K, "T")
            T = R.gens()[0]
            if self.conductor % p != 0:
                return 1 - ComplexField()(chi(p)) * T
            else:
                return R(1)

        self.local_euler_factor = eu
        self.ld.gp().quit()
Example #15
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 #16
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 #17
0
def qrp_wrapper(A, rank = None, extra_prec = 16, ctx = None):
    with mpmath.mp.workprec(A.base_ring().precision() + extra_prec):
#        print mpmath.mp.prec
        Am = mpmath.matrix(map(list, A.rows()))
        qm, rm, pm = qrp_mpmath(Am, rank, extra_prec, ctx)
        
        def to_sage(field,A):
            return Matrix(field, [[ field(A[i,j].real, A[i,j].imag) for j in range(A.cols)] for i in range(A.rows)])
        
        return to_sage(ComplexField(mpmath.mp.prec), qm), to_sage(A.base_ring(), rm), to_sage(A.base_ring(), pm)
Example #18
0
def tensor_local_factors(f1, f2, d):
    """
    takes two euler factors f1, f2 and a prec and
    returns the euler factor for the tensor
    product (with respect to that precision d
    """
    # base rings are either QQ or CC
    K1 = f1.base_ring()
    K2 = f2.base_ring()
    if K1 == ComplexField() or K2 == ComplexField():
        K = ComplexField()
    else:
        K = QQ
    R = PowerSeriesRing(K, "T")
    if not f1.parent().is_exact():  # ideally f1,f2 should already be in PSR
        if f1.prec() < d:
            raise ValueError
    if not f2.parent().is_exact():  # but the user might give them as polys...
        if f2.prec() < d:
            raise ValueError
    f1 = R(f1)
    f2 = R(f2)
    if f1 == 1 or f2 == 1:
        f = R(1)
        f = f.add_bigoh(d + 1)
        return f
    l1 = f1.log().derivative()
    p1 = l1.prec()
    c1 = l1.list()
    while len(c1) < p1:
        c1.append(0)
    l2 = f2.log().derivative()
    p2 = l2.prec()
    c2 = l2.list()
    while len(c2) < p2:
        c2.append(0)
    C = [0] * len(c1)
    for i in range(len(c1)):
        C[i] = c1[i] * c2[i]
    E = -R(C).integral()
    E = E.add_bigoh(d + 1)
    E = E.exp()  # coerce to R
    return E
Example #19
0
    def from_conjugacy_class_index_to_polynomial(self, index):
        """ A function converting from a conjugacy class index (starting at 1) to the local Euler polynomial.
            Saves a sequence of processed polynomials, obtained from the local factors table, so it can reuse computations from prime to prime
            This sequence is indexed by conjugacy class indices (starting at 1, filled with dummy first) and gives the corresponding polynomials in the form
            [coeff_deg_0, coeff_deg_1, ...], where coeff_deg_i is in ComplexField(). This could be changed later, or made parametrizable
        """
        try:
            return self._from_conjugacy_class_index_to_polynomial_fn(index)
        except AttributeError:
            local_factors = self.local_factors_table()
            field = ComplexField()
            root_of_unity = exp((field.gen()) * 2 * field.pi() / int(self.character_field()))
            local_factor_processed_pols = [0]   # dummy to account for the shift in indices
            for pol in local_factors:
                local_factor_processed_pols.append(
                    process_polynomial_over_algebraic_integer(pol, field, root_of_unity))

            def tmp(conjugacy_class_index_start_1):
                return local_factor_processed_pols[conjugacy_class_index_start_1]
            self._from_conjugacy_class_index_to_polynomial_fn = tmp
            return self._from_conjugacy_class_index_to_polynomial_fn(index)
Example #20
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 #21
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 #22
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 #23
0
 def eu(p):
     """
     Local euler factor
     """
     ans = F.q_expansion_embeddings(p + 1)
     K = ComplexField()
     R = PolynomialRing(K, "T")
     T = R.gens()[0]
     N = self.conductor
     if N % p != 0 : # good reduction
         return 1 - ans[p-1][self.number] * T + T**2
     elif N % (p**2) != 0: # semistable reduction
         return 1 - ans[p-1][self.number] * T
     else:
         return R(1)
Example #24
0
    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
Example #25
0
 def eu(p):
     """
     Local euler factor
     """
     # There was no function q_expansion_embeddings before the transition to postgres
     # so I'm not sure what this is supposed to do.
     ans = F.q_expansion_embeddings(p + 1)
     K = ComplexField()
     R = PolynomialRing(K, "T")
     T = R.gens()[0]
     N = self.conductor
     if N % p != 0:  # good reduction
         return 1 - ans[p - 1][self.number] * T + T**2
     elif N % (p**2) != 0:  # semistable reduction
         return 1 - ans[p - 1][self.number] * T
     else:
         return R(1)
Example #26
0
 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
Example #27
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 #28
0
 def __repr__(self):
     out = ""
     out += "A divisor class of the hyperelliptic curve defined by %s" % self.Pic.f
     if self.coordinates_input:
         if len(self.coordinates_cache) == 1:
             if self.sign == 0:
                 sign = "+"
             else:
                 sign = "-"
             out += " equivalent to [%s - \infty_%s]." % (
                 self.coordinates_cache[0], sign)
         if len(self.coordinates_cache) == 2:
             out += " equivalent to [%s + %s - (\infty_{+} + \infty_{-}]." % (
                 self.coordinates_cache[0], self.coordinates_cache[1])
     else:
         out += " equivalent to "
         for i in range(1, self.Pic.g):
             out += "P%d + " % i
         out += "P%d  - %d * (\infty_+ \infty_-) satisfying " % (
             self.Pic.g, self.Pic.g / 2)
         out += "\nP_i = %s" % Matrix(ComplexField(20),
                                      self.compute_coordinates())
     return out
Example #29
0
def h(t, prec):

    Dop, x, Dx = DifferentialOperators(QQ)
    L = Dx * (x * (x - 1) * (x - t)) * Dx + x

    hprec = prec + 100
    C = ComplexField(hprec)
    CBF = ComplexBallField(hprec)

    # Formal monodromy + connection matrices
    base = t / 2
    m1 = L.numerical_transition_matrix([0, base], ZZ(2)**(-prec))
    m2 = L.numerical_transition_matrix([t, base], ZZ(2)**(-prec))
    delta = matrix(CBF, [[1, 0], [2 * pi * i, 1]])
    mat = m1 * delta * ~m1 * m2 * delta * ~m2

    # log(eigenvalue)
    tr = mat.trace().real().mid()
    Pol, la = PolynomialRing(C, 'la').objgen()
    char = (la + 1 / la - tr).numerator()
    rt = char.roots(multiplicities=False)[0]
    val = (rt.log() / C(2 * i * pi))**2

    return val
Example #30
0
def get_satake_parameters(k, N=1, chi=0, fi=0, prec=10, bits=53, angles=False):
    r""" Compute the Satake parameters and return an html-table.

    INPUT:
    - ''k'' -- positive integer : the weight
    - ''N'' -- positive integer (default 1) : level
    - ''chi'' -- non-neg. integer (default 0) use character nr. chi    - ''fi'' -- non-neg. integer (default 0) We want to use the element nr. fi f=Newforms(N,k)[fi]
    -''prec'' -- compute parameters for p <=prec
    -''bits'' -- do real embedings intoi field of bits precision
    -''angles''-- return the angles t_p instead of the alpha_p
                  here alpha_p=p^((k-1)/2)exp(i*t_p)

    """
    (t, f) = _get_newform(k, N, chi, fi)
    if (not t):
        return f
    K = f.base_ring()
    RF = RealField(bits)
    CF = ComplexField(bits)
    if (K != QQ):
        M = len(K.complex_embeddings())
        ems = dict()
        for j in range(M):
            ems[j] = list()
    ps = prime_range(prec)
    alphas = list()
    for p in ps:
        ap = f.coefficients(ZZ(prec))[p]
        if (K == QQ):
            f1 = QQ(4 * p**(k - 1) - ap**2)
            alpha_p = (QQ(ap) + I * f1.sqrt()) / QQ(2)
            # beta_p=(QQ(ap)-I*f1.sqrt())/QQ(2)
            # satake[p]=(alpha_p,beta_p)
            ab = RF(p**((k - 1) / 2))
            norm_alpha = alpha_p / ab
            t_p = CF(norm_alpha).argument()
            if (angles):
                alphas.append(t_p)
            else:
                alphas.append(alpha_p)

        else:
            for j in range(M):
                app = ap.complex_embeddings(bits)[j]
                f1 = (4 * p**(k - 1) - app**2)
                alpha_p = (app + I * f1.sqrt()) / RealField(bits)(2)
                ab = RF(p**((k - 1) / 2))
                norm_alpha = alpha_p / ab
                t_p = CF(norm_alpha).argument()
                if (angles):
                    ems[j].append(t_p)
                else:
                    ems[j].append(alpha_p)

    tbl = dict()
    tbl['headersh'] = ps
    if (K == QQ):
        tbl['headersv'] = [""]
        tbl['data'] = [alphas]
        tbl['corner_label'] = "$p$"
    else:
        tbl['data'] = list()
        tbl['headersv'] = list()
        tbl['corner_label'] = "Embedding \ $p$"
        for j in ems.keys():
            tbl['headersv'].append(j)
            tbl['data'].append(ems[j])
    # logger.debug(tbl)
    s = html_table(tbl)
    return s
Example #31
0
def get_values_at_CM_points(k, N=1, chi=0, fi=0, digits=12, verbose=0):
    r""" Computes and returns a list of values of f at a collection of CM points as complex floating point numbers.

    INPUT:

    - ''k'' -- positive integer : the weight
    - ''N'' -- positive integer (default 1) : level
    - ''chi'' -- non-neg. integer (default 0) use character nr. chi    - ''fi'' -- non-neg. integer (default 0) We want to use the element nr. fi f=Newforms(N,k)[fi]
    -''digits'' -- we want this number of corrrect digits in the value

    OUTPUT:
    -''s'' string representation of a dictionary {I:f(I):rho:f(rho)}.

    TODO: Get explicit, algebraic values if possible!
    """
    (t, f) = _get_newform(k, N, chi, fi)
    if (not t):
        return f
    bits = max(53, ceil(digits * 4))
    CF = ComplexField(bits)
    RF = ComplexField(bits)
    eps = RF(10**-(digits + 1))
    logger.debug("eps=" % eps)
    K = f.base_ring()
    cm_vals = dict()
    # the points we want are i and rho. More can be added later...
    rho = CyclotomicField(3).gen()
    zi = CyclotomicField(4).gen()
    points = [rho, zi]
    maxprec = 1000  # max size of q-expansion
    minprec = 10  # max size of q-expansion
    for tau in points:
        q = CF(exp(2 * pi * I * tau))
        fexp = dict()
        if (K == QQ):
            v1 = CF(0)
            v2 = CF(1)
            try:
                for prec in range(minprec, maxprec, 10):
                    logger.debug("prec=%s" % prec)
                    v2 = f.q_expansion(prec)(q)
                    err = abs(v2 - v1)
                    logger.debug("err=%s" % err)
                    if (err < eps):
                        raise StopIteration()
                    v1 = v2
                cm_vals[tau] = ""
            except StopIteration:
                cm_vals[tau] = str(fq)
        else:
            v1 = dict()
            v2 = dict()
            err = dict()
            cm_vals[tau] = dict()
            for h in range(K.degree()):
                v1[h] = 1
                v2[h] = 0
            try:
                for prec in range(minprec, maxprec, 10):
                    logger.debug("prec=%s" % prec)
                    for h in range(K.degree()):
                        fexp[h] = list()
                        v2[h] = 0
                        for n in range(prec):
                            c = f.coefficients(ZZ(prec))[n]
                            cc = c.complex_embeddings(CF.prec())[h]
                            v2[h] = v2[h] + cc * q**n
                        err[h] = abs(v2[h] - v1[h])
                        logger.debug("v1[%s]=%s" % (h, v1[h]))
                        logger.debug("v2[%s]=%s" % (h, v2[h]))
                        logger.debug("err[%s]=%s" % (h, err[h]))
                        if (max(err.values()) < eps):
                            raise StopIteration()
                        v1[h] = v2[h]
            except StopIteration:
                pass
            for h in range(K.degree()):
                if (err[h] < eps):
                    cm_vals[tau][h] = v2[h]
                else:
                    cm_vals[tau][h] = ""

    logger.debug("vals=%s" % cm_vals)
    logger.debug("errs=%s" % err)
    tbl = dict()
    tbl['corner_label'] = ['$\tau$']
    tbl['headersh'] = ['$\\rho=\zeta_{3}$', '$i$']
    if (K == QQ):
        tbl['headersv'] = ['$f(\\tau)$']
        tbl['data'] = [cm_vals]
    else:
        tbl['data'] = list()
        tbl['headersv'] = list()
        for h in range(K.degree()):
            tbl['headersv'].append("$\sigma_{%s}(f(\\tau))$" % h)
            row = list()
            for tau in points:
                row.append(cm_vals[tau][h])
            tbl['data'].append(row)

    s = html_table(tbl)
    # s=html.table([cm_vals.keys(),cm_vals.values()])
    return s
 def compute_cm_values_numeric(self,digits=12,insert_in_db=True):
     r"""
     Compute CM-values numerically.
     """
     if isinstance(self._cm_values,dict) and self._cm_values  <> {}:
         return self._cm_values
      # the points we want are i and rho. More can be added later...
     bits = ceil(int(digits) * int(4))
     CF = ComplexField(bits)
     RF = ComplexField(bits)
     eps = RF(10 ** - (digits + 1))
     if(self._verbose > 1):
         wmf_logger.debug("eps={0}".format(eps))
     K = self.base_ring()
     # recall that
     degree = self.degree()
     cm_vals = dict()
     rho = CyclotomicField(3).gen()
     zi = CyclotomicField(4).gen()
     points = [rho, zi]
     maxprec = 1000  # max size of q-expansion
     minprec = 10  # max size of q-expansion
     for tau in points:
         q = CF(exp(2 * pi * I * tau))
         fexp = dict()
         cm_vals[tau] = dict()
         if(tau == I and self.level() == -1):
             # cv=    #"Exact(soon...)" #_cohen_exact_formula(k)
             for h in range(degree):
                 cm_vals[tau][h] = cv
             continue
         if K.absolute_degree()==1:
             v1 = CF(0)
             v2 = CF(1)
             try:
                 for prec in range(minprec, maxprec, 10):
                     if(self._verbose > 1):
                         wmf_logger.debug("prec={0}".format(prec))
                     v2 = self.as_factor().q_eigenform(prec).truncate(prec)(q)
                     err = abs(v2 - v1)
                     if(self._verbose > 1):
                         wmf_logger.debug("err={0}".format(err))
                     if(err < eps):
                         raise StopIteration()
                     v1 = v2
                 cm_vals[tau][0] = None
             except StopIteration:
                 cm_vals[tau][0] = v2
         else:
             v1 = dict()
             v2 = dict()
             err = dict()
             for h in range(degree):
                 v1[h] = 1
                 v2[h] = 0
             try:
                 for prec in range(minprec, maxprec, 10):
                     if(self._verbose > 1):
                         wmf_logger.debug("prec={0}".format(prec))
                     c = self.coefficients(range(prec),insert_in_db=insert_in_db)
                     for h in range(degree):
                         fexp[h] = list()
                         v2[h] = 0
                         for n in range(prec):
                             cn = c[n]
                             if hasattr(cn, 'complex_embeddings'):
                                 cc = cn.complex_embeddings(CF.prec())[h]
                             else:
                                 cc = CF(cn)
                             v2[h] = v2[h] + cc * q ** n
                         err[h] = abs(v2[h] - v1[h])
                         if(self._verbose > 1):
                             wmf_logger.debug("v1[{0}]={1}".format(h,v1[h]))
                             wmf_logger.debug("v2[{0}]={1}".format(h,v2[h]))
                             wmf_logger.debug("err[{0}]={2}".format(h,err[h]))
                         if(max(err.values()) < eps):
                             raise StopIteration()
                         v1[h] = v2[h]
             except StopIteration:
                 pass
             for h in range(degree):
                 if(err[h] < eps):
                     cm_vals[tau][h] = v2[h]
                 else:
                     cm_vals[tau][h] = None
     self._cm_values = cm_vals
Example #33
0
    def dimension(self,k,ignore=False, debug = 0):
        if k < 2 and not ignore:
            raise NotImplementedError("k has to >= 2")
        s = self._signature
        if not (2*k in ZZ):
            raise ValueError("k has to be integral or half-integral")
        if (2*k+s)%2 != 0:
            return 0
        m = self._m
        n2 = self._n2
        if self._v2.has_key(0):
            v2 = self._v2[0]
        else:
            v2 = 1

        if self._g != None:
            if not self._aniso_formula:
                vals = self._g.values()
            #else:
                #print "using aniso_formula"
            M = self._g
        else:
            vals = self._M.values()
            M = self._M

        if (2*k+s)%4 == 0:
            d = Integer(1)/Integer(2)*(m+n2) # |dimension of the Weil representation on even functions|
            self._d = d
            self._alpha4 = 1/Integer(2)*(vals[0]+v2) # the codimension of SkL in MkL
        else:
            d = Integer(1)/Integer(2)*(m-n2) # |dimension of the Weil representation on odd functions|
            self._d = d
            self._alpha4 = 1/Integer(2)*(vals[0]-v2) # the codimension of SkL in MkL
            
        prec = ceil(max(log(M.order(),2),52)+1)+17
        #print prec
        RR = RealField(prec)
        CC = ComplexField(prec)
        
        if debug > 0: print "d, m = {0}, {1}".format(d,m)
        eps = exp( 2 * CC.pi() * CC(0,1) * (s + 2*k) / Integer(4) )
        eps = round(real(eps))        
        if self._alpha3 is None or self._last_eps != eps:
            self._last_eps = eps
            if self._aniso_formula:
                self._alpha4 = 1
                self._alpha3 = -sum([BB(a)*mm for a,mm in self._v2.iteritems() if a != 0])
                #print self._alpha3
                self._alpha3 += Integer(d) - Integer(1) - self._g.beta_formula()
                #print self._alpha3, self._g.a5prime_formula()
                self._alpha3 = self._alpha3/RR(2)
            else:
                self._alpha3 = eps*sum([(1-a)*mm for a,mm in self._v2.iteritems() if a != 0])
                if debug>0: print "alpha3t = ", self._alpha3
                self._alpha3 += sum([(1-a)*mm for a,mm in vals.iteritems() if a != 0])
                #print self._alpha3
                self._alpha3 = self._alpha3 / Integer(2)
        alpha3 = self._alpha3
        alpha4 = self._alpha4
        if debug > 0: print alpha3, alpha4
        g1=M.char_invariant(1)
        g1=CC(g1[0]*g1[1])
        #print g1
        g2=M.char_invariant(2)
        g2=CC(g2[0]*g2[1])
        if debug > 0: print g2, g2.parent()
        g3=M.char_invariant(-3)
        g3=CC(g3[0]*g3[1])
        if debug > 0: print "eps = {0}".format(eps)
        if debug > 0: print "d/4 = {0}, m/4 = {1}, e^(2pi i (2k+s)/8) = {2}".format(RR(d) / RR(4), sqrt(RR(m)) / RR(4), CC(exp(2 * CC.pi() * CC(0,1) * (2 * k + s) / Integer(8))))
        if eps == 1:
            g2_2 = real(g2)
        else:
            g2_2 = imag(g2)*CC(0,1)
        alpha1 = RR(d) / RR(4) - sqrt(RR(m)) / RR(4)  * CC(exp(2 * CC.pi() * CC(0,1) * (2 * k + s) / Integer(8)) * g2_2)
        if debug > 0: print alpha1
        alpha2 = RR(d) / RR(3) + sqrt(RR(m)) / (3 * sqrt(RR(3))) * real(exp(CC(2 * CC.pi() * CC(0,1) * (4 * k + 3 * s - 10) / 24)) * (g1 + eps*g3))
        if debug > 0: print "alpha1 = {0}, alpha2 = {1}, alpha3 = {2}, g1 = {3}, g2 = {4}, g3 = {5}, d = {6}, k = {7}, s = {8}".format(alpha1, alpha2, alpha3, g1, g2, g3, d, k, s)
        dim = real(d + (d * k / Integer(12)) - alpha1 - alpha2 - alpha3)
        if debug > 0:
            print "dimension:", dim
        if abs(dim-round(dim)) > 1e-6:
            raise RuntimeError("Error ({0}) too large in dimension formula for {1} and k={2}".format(abs(dim-round(dim)), self._M if self._M is not None else self._g, k))
        dimr = dim
        dim = Integer(round(dim))
        if k >=2 and dim < 0:
            raise RuntimeError("Negative dimension (= {0}, {1})!".format(dim, dimr))
        return dim
Example #34
0
    def dimension(self,k,ignore=False, debug = 0):
        if k < 2 and not ignore:
            raise NotImplementedError("k has to >= 2")
        s = self._signature
        if not (2*k in ZZ):
            raise ValueError("k has to be integral or half-integral")
        if (2*k+s)%4 != 0 and not ignore:
            raise NotImplementedError("2k has to be congruent to -signature mod 4")
        if self._v2.has_key(0):
            v2 = self._v2[0]
        else:
            v2 = 1

        if self._g != None:
            if not self._aniso_formula:
                vals = self._g.values()
            #else:
                #print "using aniso_formula"
            M = self._g
        else:
            vals = self._M.values()
            M = self._M
            
        prec = ceil(max(log(M.order(),2),52)+1)+17
        #print prec
        RR = RealField(prec)
        CC = ComplexField(prec)
        d = self._d
        m = self._m
        if debug > 0: print d,m
            
        if self._alpha3 == None:
            if self._aniso_formula:
                self._alpha4 = 1
                self._alpha3 = -sum([BB(a)*mm for a,mm in self._v2.iteritems() if a != 0])
                #print self._alpha3
                self._alpha3 += Integer(d) - Integer(1) - self._g.beta_formula()
                #print self._alpha3, self._g.a5prime_formula()
                self._alpha3 = self._alpha3/RR(2)
            else:
                self._alpha3 = sum([(1-a)*mm for a,mm in self._v2.iteritems() if a != 0])
                #print self._alpha3
                self._alpha3 += sum([(1-a)*mm for a,mm in vals.iteritems() if a != 0])
                #print self._alpha3
                self._alpha3 = self._alpha3 / Integer(2)
                self._alpha4 = 1/Integer(2)*(vals[0]+v2) # the codimension of SkL in MkL
        alpha3 = self._alpha3
        alpha4 = self._alpha4
        if debug > 0: print alpha3, alpha4
        g1=M.char_invariant(1)
        g1=CC(g1[0]*g1[1])
        #print g1
        g2=M.char_invariant(2)
        g2=RR(real(g2[0]*g2[1]))
        if debug > 0: print g2, g2.parent()
        g3=M.char_invariant(-3)
        g3=CC(g3[0]*g3[1])
        if debug > 0: print RR(d) / RR(4), sqrt(RR(m)) / RR(4), CC(exp(2 * CC.pi() * CC(0,1) * (2 * k + s) / Integer(8)))
        alpha1 = RR(d) / RR(4) - (sqrt(RR(m)) / RR(4)  * CC(exp(2 * CC.pi() * CC(0,1) * (2 * k + s) / Integer(8))) * g2)
        if debug > 0: print alpha1
        alpha2 = RR(d) / RR(3) + sqrt(RR(m)) / (3 * sqrt(RR(3))) * real(exp(CC(2 * CC.pi() * CC(0,1) * (4 * k + 3 * s - 10) / 24)) * (g1+g3))
        if debug > 0: print alpha1, alpha2, g1, g2, g3, d, k, s
        dim = real(d + (d * k / Integer(12)) - alpha1 - alpha2 - alpha3)
        if debug > 0:
            print "dimension:", dim
        if abs(dim-round(dim)) > 1e-6:
            raise RuntimeError("Error ({0}) too large in dimension formula for {1} and k={2}".format(abs(dim-round(dim)), self._M if self._M is not None else self._g, k))
        dimr = dim
        dim = Integer(round(dim))
        if k >=2 and dim < 0:
            raise RuntimeError("Negative dimension (= {0}, {1})!".format(dim, dimr))
        return dim
Example #35
0
def get_values_at_CM_points(k, N=1, chi=0, fi=0, digits=12, verbose=0):
    r""" Computes and returns a list of values of f at a collection of CM points as complex floating point numbers.

    INPUT:

    - ''k'' -- positive integer : the weight
    - ''N'' -- positive integer (default 1) : level
    - ''chi'' -- non-neg. integer (default 0) use character nr. chi    - ''fi'' -- non-neg. integer (default 0) We want to use the element nr. fi f=Newforms(N,k)[fi]
    -''digits'' -- we want this number of corrrect digits in the value

    OUTPUT:
    -''s'' string representation of a dictionary {I:f(I):rho:f(rho)}.

    TODO: Get explicit, algebraic values if possible!
    """
    (t, f) = _get_newform(k, N, chi, fi)
    if(not t):
        return f
    bits = max(53, ceil(digits * 4))
    CF = ComplexField(bits)
    RF = ComplexField(bits)
    eps = RF(10 ** -(digits + 1))
    logger.debug("eps=" % eps)
    K = f.base_ring()
    cm_vals = dict()
    # the points we want are i and rho. More can be added later...
    rho = CyclotomicField(3).gen()
    zi = CyclotomicField(4).gen()
    points = [rho, zi]
    maxprec = 1000  # max size of q-expansion
    minprec = 10  # max size of q-expansion
    for tau in points:
        q = CF(exp(2 * pi * I * tau))
        fexp = dict()
        if(K == QQ):
            v1 = CF(0)
            v2 = CF(1)
            try:
                for prec in range(minprec, maxprec, 10):
                    logger.debug("prec=%s" % prec)
                    v2 = f.q_expansion(prec)(q)
                    err = abs(v2 - v1)
                    logger.debug("err=%s" % err)
                    if(err < eps):
                        raise StopIteration()
                    v1 = v2
                cm_vals[tau] = ""
            except StopIteration:
                cm_vals[tau] = str(fq)
        else:
            v1 = dict()
            v2 = dict()
            err = dict()
            cm_vals[tau] = dict()
            for h in range(K.degree()):
                v1[h] = 1
                v2[h] = 0
            try:
                for prec in range(minprec, maxprec, 10):
                    logger.debug("prec=%s" % prec)
                    for h in range(K.degree()):
                        fexp[h] = list()
                        v2[h] = 0
                        for n in range(prec):
                            c = f.coefficients(ZZ(prec))[n]
                            cc = c.complex_embeddings(CF.prec())[h]
                            v2[h] = v2[h] + cc * q ** n
                        err[h] = abs(v2[h] - v1[h])
                        logger.debug("v1[%s]=%s" % (h, v1[h]))
                        logger.debug("v2[%s]=%s" % (h, v2[h]))
                        logger.debug("err[%s]=%s" % (h, err[h]))
                        if(max(err.values()) < eps):
                            raise StopIteration()
                        v1[h] = v2[h]
            except StopIteration:
                pass
            for h in range(K.degree()):
                if(err[h] < eps):
                    cm_vals[tau][h] = v2[h]
                else:
                    cm_vals[tau][h] = ""

    logger.debug("vals=%s" % cm_vals)
    logger.debug("errs=%s" % err)
    tbl = dict()
    tbl['corner_label'] = ['$\tau$']
    tbl['headersh'] = ['$\\rho=\zeta_{3}$', '$i$']
    if(K == QQ):
        tbl['headersv'] = ['$f(\\tau)$']
        tbl['data'] = [cm_vals]
    else:
        tbl['data'] = list()
        tbl['headersv'] = list()
        for h in range(K.degree()):
            tbl['headersv'].append("$\sigma_{%s}(f(\\tau))$" % h)
            row = list()
            for tau in points:
                row.append(cm_vals[tau][h])
            tbl['data'].append(row)

    s = html_table(tbl)
    # s=html.table([cm_vals.keys(),cm_vals.values()])
    return s
Example #36
0
    def init_tensor_product(self, V, W):
        """
        We are given two Galois representations and we
        will return their tensor product.
        """
        self.original_object = V.original_object + W.original_object
        self.object_type = "tensorproduct"
        self.V1 = V
        self.V2 = W
        self.dim = V.dim * W.dim
        self.motivic_weight = V.motivic_weight + W.motivic_weight
        self.langlands = False # status 2014 :)
        self.besancon_bound = min(V.besancon_bound, W.besancon_bound)

        bad2 = ZZ(W.conductor).prime_factors()
        bad_primes = [x for x in ZZ(V.conductor).prime_factors() if x in bad2]
        for p in bad_primes:
            if ( p not in V.bad_semistable_primes and p not in W.bad_semistable_primes) :
                # this condition above only applies to the current type of objects
                # for general reps we would have to test the lines below
                # to be certain that the formulae are correct.
                #if ((p not in V.bad_semistable_primes or p not in W.bad_pot_good) and
                    #(p not in W.bad_semistable_primes or p not in V.bad_pot_good) and
                    #(p not in V.bad_semistable_primes or p not in W.bad_semistable_primes)):
                raise NotImplementedError("Currently tensor products of Galois representations are only implemented under some conditions.",
                                          "The behaviour at %d is too wild (both factors must be semistable)." % p)

        # check for the possibily of getting poles
        if V.weight == W.weight and V.conductor == W.conductor :
            Vans = V.algebraic_coefficients(50)
            Wans = W.algebraic_coefficients(50)
            CC = ComplexField()
            if ((Vans[2] in ZZ and Wans[2] in ZZ and
                all(Vans[n] == Wans[n] for n in range(1,50) ) ) or
                all( CC(Vans[n]) == CC(Wans[n]) for n in range(1,50) ) ):
                    raise NotImplementedError("It seems you are asking to tensor a "+
                                              "Galois representation with its dual " +
                                              "which results in the L-function having "+
                                              "a pole. This is not implemented here.")

        scommon = [x for x in V.bad_semistable_primes if x in W.bad_semistable_primes]

        N = W.conductor ** V.dim
        N *= V.conductor ** W.dim
        for p in bad_primes:
            n1_tame = V.dim - V.local_euler_factor(p).degree()
            n2_tame = W.dim - W.local_euler_factor(p).degree()
            nn = n1_tame * n2_tame
            N = N // p ** nn
            if p in scommon: # both are degree 1 in this case
                N = N // p
        self.conductor = N

        h1 = selberg_to_hodge(V.motivic_weight,V.mu_fe,V.nu_fe)
        h2 = selberg_to_hodge(W.motivic_weight,W.mu_fe,W.nu_fe)
        h = tensor_hodge(h1, h2)
        w,m,n = hodge_to_selberg(h)
        self.mu_fe = m
        self.nu_fe = n
        _, self.gammaV = gamma_factors(h)

        # this is used in getting the Dirichlet coefficients.
        self.bad_primes_info = []
        for p in bad_primes:
            # we have to check if this works in all bad cases !
            f1 = V.local_euler_factor(p)
            f2 = W.local_euler_factor(p)
            # might be dodgy if f1 or f2 is an approx to the Euler factor
            if p in scommon:
                E = tensor_local_factors(f1,f2,V.dim*W.dim)
                T = f1.parent().gens()[0] # right answer is E(T)*E(pT)
                self.bad_primes_info.append([p,E*E(p*T),1-T]) #bad_primes_info.append() with 1-T as the second argument is equivalent to taking the first argument as the results (it does a convolution, as in the next line)
            else:
                self.bad_primes_info.append([p,f1,f2])

        CC = ComplexField()
        I = CC.gens()[0]
        self.sign = I ** root_number_at_oo(h)
        self.sign /= I ** (root_number_at_oo(h1) * V.dim)
        self.sign /= I ** (root_number_at_oo(h2) * W.dim)
        self.sign *= V.sign ** W.dim
        self.sign *= W.sign ** V.dim
        for p in bad_primes:
            if p not in V.bad_semistable_primes or p not in V.bad_semistable_primes:
                f1 = V.local_euler_factor(p)
                f2 = W.local_euler_factor(p)
                det1 = f1.leading_coefficient() * (-1) ** f1.degree()
                det2 = f2.leading_coefficient() * (-1) ** f2.degree()
                n1_tame = V.dim - f1.degree()
                n2_tame = W.dim - f2.degree()
                n1_wild = ZZ(V.conductor).valuation(p) - n1_tame
                n2_wild = ZZ(W.conductor).valuation(p) - n2_tame
                # additionally, we would need to correct this by
                # replacing det1 by chi1(p) if p is semistable for V
                # however for all the possible input this currently does
                # not affect the sign
                if p in V.bad_semistable_primes:
                    chi1p = 1 # here
                else:
                    chi1p = det1
                if p in W.bad_semistable_primes:
                    chi2p = 1 # here
                else:
                    chi2p = det2

                corr = chi1p ** n2_wild
                corr *= det1 ** n2_tame
                corr *= chi2p ** n1_wild
                corr *= det2 ** n1_tame
                corr *= (-1) ** (n1_tame * n2_tame)

                self.sign *= corr/corr.abs()

        #self.primitive = False
        self.set_dokchitser_Lfunction()
        # maybe we should change this to take as many coefficients as implemented
        # in other Lfunctions
        self.set_number_of_coefficients()

        someans = self.algebraic_coefficients(50) # why not.
        if all( x in ZZ for x in someans):
            self.selfdual = True
        else:
            CC = ComplexField()
            self.selfdual = all( CC(an).imag().abs() < 0.0001 for an in someans)

        self.coefficient_type = max(V.coefficient_type, W.coefficient_type)
        self.coefficient_period = ZZ(V.coefficient_period).lcm(W.coefficient_period)
        self.ld.gp().quit()