Example #1
0
class BianchiDistributionElement(ModuleElement):
    r"""
    This class represents elements in an overconvergent Bianchi coefficient module.

    INPUT:

     - ``parent`` - An overconvergent coefficient module.

     - ``val`` - The value that it needs to store (default: 0). It can be another BianchiDistributionElement,
       in which case the values are copied. It can also be a column vector (or something
       coercible to a column vector) which represents the values of the element applied to
       the polynomials `1`, `x`, `y`, `x^2`, `xy`, `y^2`, ... ,`y^n`.

     - ``check`` - boolean (default: True). If set to False, no checks are done and ``val`` is
       assumed to be the a column vector.

    """
    def __init__(self, parent, val=0, check=True, normalize=False):
        """
        Initialisation function. Takes as input a vector val, which should have length equal to the 
        dimension of the space, which is the nth triangle number, where n is the depth. This corresponds
        to the ordered basis for distributions (namely, the dual basis to the basis 1, x, y, x^2, xy, ...).

        Input:
            - parent: BianchiDistributions object of depth n
            - val : vector of length n^2 encoding the moments of the distribution
        """
        ## Parents/precision
        ModuleElement.__init__(self, parent)
        self._parent = parent
        self._depth = self._parent._depth
        self._dimension = self._parent._dimension

        ## check multiple possibilities for input
        if not check:
            self._moments = val
        else:
            ## is input already a distribution?
            if isinstance(val, self.__class__):
                ## if depth is the same, then keep this
                if val._parent._depth == parent._depth:
                    self._moments = val._moments
                else:
                    ## depths are different, take the minimum
                    d = min([val.nrows(), parent.dimension()])
                    self._moments = val._moments.submatrix(0, 0, nrows=d)

            elif isinstance(val, int) or isinstance(val, Integer):
                ## Initialise distribution to be trivial, i.e. constant moment = input and rest = 0
                self._moments = MatrixSpace(self._parent._R, self._dimension,
                                            1)(0)
                self._moments[0, 0] = val

            ## input is a vector storing the moments
            elif isinstance(val, Vector_integer_dense) or isinstance(
                    val, FreeModuleElement_generic_dense):
                self._moments = MatrixSpace(self._parent._R, self._dimension,
                                            1)(0)
                for i, o in enumerate(val.list()):
                    self._moments[i, 0] = o

            ## input is a list storing the moments
            elif isinstance(val, list):
                self._moments = MatrixSpace(self._parent._R, self._dimension,
                                            1)(0)
                for i, o in enumerate(val):
                    self._moments[i, 0] = o
            else:
                try:
                    self._moments = Matrix(self._parent._R, self._depth, 1,
                                           val)
                except (TypeError, ValueError):
                    self._moments = self._parent._R(val) * MatrixSpace(
                        self._parent._R, self._dimension, 1)(1)

    def __hash__(self):
        return hash(self._moments)

    def moment(self, ij):
        """
        Returns the (i,j)th moment mu(x^iy^j).

        EXAMPLES::

            sage: from darmonpoints.ocbianchi import BianchiDistributions
            sage: D = BianchiDistributions(11,4)
            sage: mu = D.basis_vector((2,3))
            sage: mu.moment((2,3))
            1 + O(11^3)
            sage: mu.moment((2,1))
            O(11^3)

        """
        if isinstance(ij, tuple):
            idx = self._parent.index(ij)
        else:
            idx = ij
        return self._parent._Rmod(self._moments[idx, 0])

    def moments(self):
        """
        Returns the moments (as a column vector).

        EXAMPLES::

            sage: from darmonpoints.ocbianchi import BianchiDistributions
            sage: D = BianchiDistributions(11,2)
            sage: mu = D.basis_vector((1,1))
            sage: mu.moments()
            [0]
            [0]
            [0]
            [1]
        """
        return self._moments

    def __getitem__(self, ij):
        r"""

        """
        return self.moment(ij)

    def __setitem__(self, ij, val):
        r"""
        Sets the value of ``self`` on the polynomial `x^iy^j` to ``val``.

        INPUT:
        - ``r`` - an integer. The power of `x`.
        - ``val`` - a value.

        """
        if isinstance(ij, tuple):
            idx = self._parent.index(ij[0], ij[1])
        else:
            idx = ij
        self._moments[idx, 0] = val

    def element(self):
        r"""
        The element ``self`` represents.
        """
        tmp = self.matrix_rep()
        return [tmp[ii, 0] for ii in range(tmp.nrows())]

    def list(self):
        r"""
        The element ``self`` represents.
        """
        return self.element()

    def matrix_rep(self, B=None):
        r"""
        Returns a matrix representation of ``self``.
        """
        #Express the element in terms of the basis B
        if B is None:
            B = self._parent.basis()

        A = Matrix(self._parent._R, self._parent.dimension(),
                   self._parent.dimension(),
                   [[b._moments[ii, 0] for b in B]
                    for ii in range(self._dimension)])
        tmp = A.solve_right(self._moments)
        return tmp

    def _add_(self, y):
        r"""
        Add two elements.

        EXAMPLES::

            sage: from darmonpoints.ocbianchi import BianchiDistributions
            sage: D = BianchiDistributions(11,4)
            sage: mu1 = D.basis_vector((2,3))
            sage: mu2 = D.basis_vector((1,2))
            sage: mu1 + mu2
            X*Y^2 + X^2*Y^3

        """
        val = self._moments + y._moments
        return self.__class__(self._parent, val, check=False)

    def _sub_(self, y):
        r"""
        Subtract two elements.
        """
        val = self._moments - y._moments
        return self.__class__(self._parent, val, check=False)

    def _neg_(self):
        return self.__class__(self._parent, -self._moments, check=False)

    def _rmul_(self, a):
        #assume that a is a scalar
        return self.__class__(self._parent, a * self._moments, check=False)

    def _repr_(self):
        r"""
        Returns the representation of self as a string. The monomial X^iY^j is the dual basis vector
        to the monomial x^iy^j in the ring of analytic functions.

        EXAMPLES::

            sage: from darmonpoints.ocbianchi import BianchiDistributions
            sage: D = BianchiDistributions(11,4)
            sage: mu = D.basis_vector((2,1)) + D.basis_vector((1,0))
            sage: mu
            X + X^2*Y
            sage: D.basis_vector((1,1)) + 2*D.basis_vector((2,1))
            X*Y + 2*X^2*Y

        """
        R = self.parent()._repr_R
        s = str(
            sum([
                ZZ(self._moments[idx, 0]) *
                self._parent.monomial_from_index(idx, R)
                for idx in range(self._moments.nrows())
            ]))
        return s

    def __cmp__(self, other):
        return cmp(self._moments, other._moments)

    def __nonzero__(self):
        return self._moments != 0

    def evaluate_at_poly(self, P, R=None, depth=None):
        r"""
        Evaluate ``self`` at a polynomial. The polynomial can be defined over ZZ or Zp.

        By default, this function picks the ring R to be a ring that coerces to both the 
        base ring of the polynomial and the Bianchi distribution.

        You can specify depth, but this currently does nothing at all.

        EXAMPLES::

            sage: from darmonpoints.ocbianchi import BianchiDistributions
            sage: D = BianchiDistributions(11,4)
            sage: x,y = D.analytic_vars()
            sage: mu = D.basis_vector((2,1)) + D.basis_vector((1,0))
            sage: mu(x^2*y)
            1
            sage: mu(y)
            0
            sage: mu(x^2*y + x)
            2
        """
        p = self._parent._p

        ## Currently empty functionality
        if depth is None:
            depth = self._depth

        # Define the ring R, if not specified
        if R is None:
            try:
                R = pushout(P.parent().base_ring(), self.parent().base_ring())
            except AttributeError:
                R = self.parent().base_ring()

        ## Attempt to coerce the input into a form we can evaluate
        P = self.parent().analytic_functions()(P)

        ## For each monomial x^iy^j in the polynomial, multip] ly the coefficient of X^iY^j (in mu) by the
        ## coefficient of x^iy^j (in f) and take the sum. This is our final value
        ##          --> P.coefficients is a dictionary which has monomials as keys; we generate monomials using exponents.
        ##         --> self._moments takes as input an index and spits out the cofficient. So generate the index from the exponent.

        coefficient_list = []
        for polx in P.padded_list(self._depth):
            coefficient_list.extend(polx.padded_list(self._depth))

        return ZZ((Matrix(coefficient_list) * self.moments())[0, 0])

    def __call__(self, P):
        r"""
        Call function; evaluates the distribution at an analytic function.
        """
        return self.evaluate_at_poly(P)

    def reduce_mod(self, N=None):
        r"""
        Reduces all the moments modulo N.
        """
        if N is None:
            N = self.parent()._pN
        self._moments = self._moments.apply_map(lambda x: x % N)
        return self

    def max_filtration_step(self):
        r"""
        Computes the maximal step of the filtration in which mu lives.
        """

        ## Take min of v_p(mu(x^i*y^j)) + i + j
        p = self._parent._p
        min_modified_moment = min(
            (o[0].valuation(p) + sum(tuple(self.parent().ij_from_pos(n)))
             for n, o in enumerate(self._moments)))

        ## Last filtration step in which this appears is step r, where r is the min such that this min/2 - r >= 0
        ## ..... IN THE SUPERSINGULAR CASE!
        ## In the ordinary case, the min r is sufficient *without* dividing by 2!!!
        return min_modified_moment  ## QQ(min_modified_moment/2).floor()

    def normalize(self, r=None):
        r"""
        Adjust the moments to the precision given by the filtration step where self belongs.
        """
        if r is None:
            r = self.max_filtration_step()
        V = self._moments
        p = self._parent._p
        for n in xrange(self._moments.nrows()):
            k = r - sum(tuple(self.parent().ij_from_pos(n)))
            self._moments[n, 0] = self._moments[n, 0] % p**k
        return self

    def valuation(self):
        r"""
        Returns the same as max_filtration_step, defining an element to have valuation r
        if Filr^(r,r) is the maximal filtration step in which it lives.
        """
        return self.max_filtration_step()
Example #2
0
class OCVnElement(ModuleElement):
    r"""
    This class represents elements in an overconvergent coefficient module.

    INPUT:

     - ``parent`` - An overconvergent coefficient module.

     - ``val`` - The value that it needs to store (default: 0). It can be another OCVnElement,
       in which case the values are copied. It can also be a column vector (or something
       coercible to a column vector) which represents the values of the element applied to
       the polynomials `1`, `x`, `x^2`, ... ,`x^n`.

     - ``check`` - boolean (default: True). If set to False, no checks are done and ``val`` is
       assumed to be the a column vector.

    AUTHORS:

    - Cameron Franc (2012-02-20)
    - Marc Masdeu (2012-02-20)
    """
    def __init__(self, parent, val=0, check=True, normalize=False):
        ModuleElement.__init__(self, parent)
        self._parent = parent
        self._depth = self._parent._depth
        if not check:
            self._val = val
        else:
            if isinstance(val, self.__class__):
                if val._parent._depth == parent._depth:
                    self._val = val._val
                else:
                    d = min([val._parent._depth, parent._depth])
                    self._val = val._val.submatrix(0, 0, nrows=d)

            elif isinstance(val, Vector_integer_dense) or isinstance(
                    val, FreeModuleElement_generic_dense):
                self._val = MatrixSpace(self._parent._R, self._depth, 1)(0)
                for i, o in enumerate(val.list()):
                    self._val[i, 0] = o
            else:
                try:
                    self._val = Matrix(self._parent._R, self._depth, 1, val)
                except (TypeError, ValueError):
                    self._val = self._parent._R(val) * MatrixSpace(
                        self._parent._R, self._depth, 1)(1)
        self._moments = self._val

    def lift(self, p=None, M=None):
        return self

    def moment(self, i):
        return self._parent._Rmod(self._moments[i, 0])

    def __getitem__(self, r):
        r"""
        Returns the value of ``self`` on the polynomial `x^r`.

        INPUT:
          - ``r`` - an integer. The power of `x`.

        EXAMPLES:

        """
        return self._val[r, 0]

    def __setitem__(self, r, val):
        r"""
        Sets the value of ``self`` on the polynomial `x^r` to ``val``.

        INPUT:
        - ``r`` - an integer. The power of `x`.
        - ``val`` - a value.

        EXAMPLES:

        """
        self._val[r, 0] = val

    def element(self):
        r"""
        The element ``self`` represents.
        """
        tmp = self.matrix_rep()
        return [tmp[ii, 0] for ii in range(tmp.nrows())]

    def list(self):
        r"""
        The element ``self`` represents.
        """
        return self.element()

    def matrix_rep(self, B=None):
        r"""
        Returns a matrix representation of ``self``.
        """
        #Express the element in terms of the basis B
        if B is None:
            B = self._parent.basis()
        A = Matrix(self._parent._R, self._parent.dimension(),
                   self._parent.dimension(),
                   [[b._val[ii, 0] for b in B] for ii in range(self._depth)])
        tmp = A.solve_right(self._val)
        return tmp

    def _add_(self, y):
        r"""
        Add two elements.
        """
        val = self._val + y._val
        return self.__class__(self._parent, val, check=False)

    def _sub_(self, y):
        r"""
        Subtract two elements.
        """
        val = self._val - y._val
        return self.__class__(self._parent, val, check=False)

    def _div_(self, right):
        r"""
        Finds the scalar such that self = a * right (assuming that it exists)
        """
        if self.is_zero():
            return 0
        else:
            a = None
            for u, v in zip(self._moments, right._moments):
                if u != 0:
                    a = u / v
                    break
            assert a is not None
            assert (self -
                    a * right).is_zero(), 'Not a scalar multiple of right'
            return a

    def r_act_by(self, x):
        r"""
        Act on the right by a matrix.
        """
        #assert(x.nrows()==2 and x.ncols()==2) #An element of GL2
        return self._acted_upon_(x.adjugate(), False)

    def _acted_upon_(self, x, right_action):  # Act by x on the left
        try:
            x = x.matrix()
        except AttributeError:
            pass
        if right_action:
            return self._acted_upon_(x.adjugate(), False)
        else:
            R = self._parent._R
            A = self._parent._get_powers(x)
            tmp = A * self._val
            return self.__class__(self._parent, tmp, check=False)

    def _neg_(self):
        return self.__class__(self._parent, -self._val, check=False)

    def _rmul_(self, a):
        #assume that a is a scalar
        return self.__class__(self._parent,
                              self._parent._Rmod(a) * self._val,
                              check=False)

    def _repr_(self):
        r"""
        Returns the representation of self as a string.
        """
        R = PowerSeriesRing(self._parent._R,
                            default_prec=self._depth,
                            name='z')
        z = R.gen()
        s = str(sum([R(self._val[ii, 0] * z**ii)
                     for ii in range(self._depth)]))
        return s

    def __cmp__(self, other):
        return cmp(self._val, other._val)

    def __nonzero__(self):
        return self._val != 0

    def evaluate_at_poly(self, P, R=None, depth=None):
        r"""
        Evaluate ``self`` at a polynomial
        """
        p = self._parent._p
        if R is None:
            try:
                R = pushout(P.parent().base_ring(), self.parent().base_ring())
            except AttributeError:
                R = self.parent().base_ring()
        if depth is None and hasattr(P, 'degree'):
            try:
                depth = min([P.degree() + 1, self._depth])
                return sum(R(self._val[ii, 0]) * P[ii] for ii in xrange(depth))
            except NotImplementedError:
                pass
            return R(self._val[0, 0]) * P
        else:
            return sum(
                R(self._val[ii, 0]) * P[ii] for ii in xrange(self._depth))

    def valuation(self, l=None):
        r"""
        The `l`-adic valuation of ``self``.

        INPUT: a prime `l`. The default (None) uses the prime of the parent.

        """
        if not self._parent.base_ring().is_exact():
            if (not l is None and l != self._parent._Rmod.prime()):
                raise ValueError(
                    "This function can only be called with the base prime")
            l = self._parent._Rmod.prime()
            return min(
                [self._val[ii, 0].valuation(l) for ii in range(self._depth)])
        else:
            return min(
                [self._val[ii, 0].valuation(l) for ii in range(self._depth)])

    def valuation_list(self, l=None):
        r"""
        The `l`-adic valuation of ``self``, as a list.

        INPUT: a prime `l`. The default (None) uses the prime of the parent.

        """
        if not self._parent.base_ring().is_exact():
            if (not l is None and l != self._parent._Rmod.prime()):
                raise ValueError(
                    "This function can only be called with the base prime")
            l = self._parent._Rmod.prime()
            return [self._val[ii, 0].valuation(l) for ii in range(self._depth)]
        else:
            return [self._val[ii, 0].valuation(l) for ii in range(self._depth)]

    def reduce_mod(self, N=None):
        if N is None:
            N = self.parent()._pN
        self._val = self._val.apply_map(lambda x: x % N)
        return self
Example #3
0
class OCVnElement(ModuleElement):
    r"""
    This class represents elements in an overconvergent coefficient module.

    INPUT:

     - ``parent`` - An overconvergent coefficient module.

     - ``val`` - The value that it needs to store (default: 0). It can be another OCVnElement,
       in which case the values are copied. It can also be a column vector (or something
       coercible to a column vector) which represents the values of the element applied to
       the polynomials `1`, `x`, `x^2`, ... ,`x^n`.

     - ``check`` - boolean (default: True). If set to False, no checks are done and ``val`` is
       assumed to be the a column vector.

    AUTHORS:

    - Cameron Franc (2012-02-20)
    - Marc Masdeu (2012-02-20)
    """
    def __init__(self,parent,val = 0,check = True,normalize=False):
        ModuleElement.__init__(self,parent)
        self._parent = parent
        self._depth = self._parent._depth
        if not check:
            self._val = val
        else:
            if isinstance(val,self.__class__):
                if val._parent._depth == parent._depth:
                    self._val = val._val
                else:
                    d = min([val._parent._depth,parent._depth])
                    self._val = val._val.submatrix(0,0,nrows = d)

            elif isinstance(val, Vector_integer_dense) or isinstance(val, FreeModuleElement_generic_dense):
                self._val = MatrixSpace(self._parent._R, self._depth, 1)(0)
                for i,o in enumerate(val.list()):
                    self._val[i,0] = o
            else:
                try:
                    self._val = Matrix(self._parent._R,self._depth,1,val)
                except (TypeError, ValueError):
                    self._val= self._parent._R(val) * MatrixSpace(self._parent._R,self._depth,1)(1)
        self._moments = self._val

    def lift(self, p=None,M=None):
        return self

    def moment(self, i):
        return self._parent._Rmod(self._moments[i,0])

    def __getitem__(self,r):
        r"""
        Returns the value of ``self`` on the polynomial `x^r`.

        INPUT:
          - ``r`` - an integer. The power of `x`.

        EXAMPLES:

        """
        return self._val[r,0]

    def __setitem__(self,r, val):
        r"""
        Sets the value of ``self`` on the polynomial `x^r` to ``val``.

        INPUT:
        - ``r`` - an integer. The power of `x`.
        - ``val`` - a value.

        EXAMPLES:

        """
        self._val[r,0] = val

    def element(self):
        r"""
        The element ``self`` represents.
        """
        tmp = self.matrix_rep()
        return [tmp[ii,0] for ii in range(tmp.nrows())]

    def list(self):
        r"""
        The element ``self`` represents.
        """
        return self.element()

    def matrix_rep(self,B=None):
        r"""
        Returns a matrix representation of ``self``.
        """
        #Express the element in terms of the basis B
        if B is None:
            B = self._parent.basis()
        A=Matrix(self._parent._R,self._parent.dimension(),self._parent.dimension(),[[b._val[ii,0] for b in B] for ii in range(self._depth)])
        tmp=A.solve_right(self._val)
        return tmp

    def _add_(self,y):
        r"""
        Add two elements.
        """
        val=self._val+y._val
        return self.__class__(self._parent,val, check = False)

    def _sub_(self,y):
        r"""
        Subtract two elements.
        """
        val=self._val-y._val
        return self.__class__(self._parent,val, check = False)

    def r_act_by(self,x):
        r"""
        Act on the right by a matrix.
        """
        #assert(x.nrows()==2 and x.ncols()==2) #An element of GL2
        return self._acted_upon_(x.adjoint(), False)

    def _acted_upon_(self,x, right_action): # Act by x on the left
        try:
            x = x.matrix()
        except AttributeError: pass
        if right_action:
            return self._acted_upon_(x.adjoint(), False)
        else:
            R = self._parent._R
            A = self._parent._get_powers(x)
            tmp = A * self._val
            return self.__class__(self._parent, tmp, check = False)

    def _neg_(self):
        return self.__class__(self._parent,-self._val, check = False)


    def _rmul_(self,a):
        #assume that a is a scalar
        return self.__class__(self._parent,a*self._val, check = False)

    def _repr_(self):
        r"""
        Returns the representation of self as a string.
        """
        R = PowerSeriesRing(self._parent._R,default_prec=self._depth,name='z')
        z = R.gen()
        s = str(sum([R(self._val[ii,0]*z**ii) for ii in range(self._depth)]))
        return s

    def __cmp__(self,other):
        return cmp(self._val,other._val)

    def __nonzero__(self):
        return self._val!=0

    def evaluate_at_poly(self,P,R = None,depth = None):
        r"""
        Evaluate ``self`` at a polynomial
        """
        p = self._parent._p
        if R is None:
            try:
                R = pushout(P.parent().base_ring(),self.parent().base_ring())
            except AttributeError:
                R = self.parent().base_ring()
        if depth is None and hasattr(P,'degree'):
            try:
                depth = min([P.degree()+1,self._depth])
                return sum(R(self._val[ii,0])*P[ii] for ii in xrange(depth))
            except NotImplementedError: pass
            return R(self._val[0,0])*P
        else:
            return sum(R(self._val[ii,0])*P[ii] for ii in xrange(depth))


    def valuation(self,l=None):
        r"""
        The `l`-adic valuation of ``self``.

        INPUT: a prime `l`. The default (None) uses the prime of the parent.

        """
        if not self._parent.base_ring().is_exact():
            if(not l is None and l!=self._parent._Rmod.prime()):
                raise ValueError, "This function can only be called with the base prime"
            l = self._parent._Rmod.prime()
            return min([self._val[ii,0].valuation(l) for ii in range(self._depth)])
        else:
            return min([self._val[ii,0].valuation(l) for ii in range(self._depth)])

    def reduce_mod(self, N = None):
        if N is None:
            N = self.parent()._pN
        self._val = self._val.apply_map(lambda x: x % N)
        return self
    def apply_Up(self,c,group = None,scale = 1,parallelize = False,times = 0,progress_bar = False,method = 'naive', repslocal = None, Up_reps = None, steps = 1):
        r"""
        Apply the Up Hecke operator operator to ``c``.
        """
        assert steps >= 1

        V = self.coefficient_module()
        R = V.base_ring()
        gammas = self.group().gens()

        if Up_reps is None:
            Up_reps = self.S_arithgroup().get_Up_reps()

        if repslocal is None:
            try:
                prec = V.base_ring().precision_cap()
            except AttributeError:
                prec = None
            repslocal = self.get_Up_reps_local(prec)
        i = 0
        if method == 'naive':
            assert times == 0
            G = self.S_arithgroup()
            Gn = G.large_group()
            if self.use_shapiro():
                if self.coefficient_module().trivial_action():
                    def calculate_Up_contribution(lst, c, i, j):
                        return sum([c.evaluate_and_identity(tt) for sk, tt in lst])
                else:
                    def calculate_Up_contribution(lst, c, i, j):
                        return sum([sk * c.evaluate_and_identity(tt) for sk, tt in lst])

                input_vec = []
                for j, gamma in enumerate(gammas):
                    for i, xi in enumerate(G.coset_reps()):
                        delta = Gn(G.get_coset_ti(set_immutable(xi * gamma.quaternion_rep))[0])
                        input_vec.append(([(sk, Gn.get_hecke_ti(g,delta)) for sk, g in zip(repslocal, Up_reps)], c, i, j))
                vals = [[V.coefficient_module()(0,normalize=False) for xi in G.coset_reps()] for gamma in gammas]
                if parallelize:
                    for inp, outp in parallel(calculate_Up_contribution)(input_vec):
                        vals[inp[0][-1]][inp[0][-2]] += outp
                else:
                    for inp in input_vec:
                        outp = calculate_Up_contribution(*inp)
                        vals[inp[-1]][inp[-2]] += outp
                ans = self([V(o) for o in vals])
            else:
                Gpn = G.small_group()
                if self.trivial_action():
                    def calculate_Up_contribution(lst,c,num_gamma):
                        return sum([c.evaluate(tt) for sk, tt in lst], V(0,normalize=False))
                else:
                    def calculate_Up_contribution(lst,c,num_gamma,pb_fraction=None):
                        i = 0
                        ans = V(0, normalize=False)
                        for sk, tt in lst:
                            ans += sk * c.evaluate(tt)
                            update_progress(i * pb_fraction, 'Up action')
                        return ans
                input_vec = []
                for j,gamma in enumerate(gammas):
                    input_vec.append(([(sk, Gpn.get_hecke_ti(g,gamma)) for sk, g in zip(repslocal, Up_reps)], c, j))
                vals = [V(0,normalize=False) for gamma in gammas]
                if parallelize:
                    for inp,outp in parallel(calculate_Up_contribution)(input_vec):
                        vals[inp[0][-1]] += outp
                else:
                    for counter, inp in enumerate(input_vec):
                        outp = calculate_Up_contribution(*inp, pb_fraction=float(1)/float(len(repslocal) * len(input_vec)))
                        vals[inp[-1]] += outp
                ans = self(vals)
            if scale != 1:
                ans = scale * ans
        else:
            assert method == 'bigmatrix'
            verbose('Getting Up matrices...')
            try:
                N = len(V(0)._moments.list())
            except AttributeError:
                N = 1
            nreps = len(Up_reps)
            ngens = len(self.group().gens())
            NN = ngens * N
            A = Matrix(ZZ,NN,NN,0)
            total_counter = ngens**2
            counter = 0
            iS = 0
            for i,gi in enumerate(self.group().gens()):
                ti = [tuple(self.group().get_hecke_ti(sk,gi).word_rep) for sk in Up_reps]
                jS = 0
                for ans in find_newans(self,repslocal,ti):
                    A.set_block(iS,jS,ans)
                    jS += N
                    if progress_bar:
                        counter +=1
                        update_progress(float(counter)/float(total_counter),'Up matrix')
                iS += N
            verbose('Computing 2^(%s)-th power of a %s x %s matrix'%(times,A.nrows(),A.ncols()))
            for i in range(times):
                A = A**2
                if N != 0:
                    A = A.apply_map(lambda x: x % self._pN)
                update_progress(float(i+1)/float(times),'Exponentiating matrix')
            verbose('Done computing 2^(%s)-th power'%times)
            if times > 0:
                scale_factor = ZZ(scale).powermod(2**times,self._pN)
            else:
                scale_factor = ZZ(scale)
            bvec = Matrix(R,NN,1,[o for b in c._val for o in b._moments.list()])
            if scale_factor != 1:
                bvec = scale_factor * bvec
            valmat = A * bvec
            appr_module = V.approx_module(N)
            ans = self([V(appr_module(valmat.submatrix(row=i,nrows = N).list())) for i in xrange(0,valmat.nrows(),N)])
        if steps <= 1:
            return ans
        else:
            return self.apply_Up(ans, group = group,scale = scale,parallelize = parallelize,times = times,progress_bar = progress_bar,method = method, repslocal = repslocal, steps = steps -1)