Manin map#

Represents maps from a set of right coset representatives to a coefficient module.

This is a basic building block for implementing modular symbols, and provides basic arithmetic and right action of matrices.

EXAMPLES:

sage: E = EllipticCurve('11a')
sage: phi = E.pollack_stevens_modular_symbol()
sage: phi
Modular symbol of level 11 with values in Sym^0 Q^2
sage: phi.values()
[-1/5, 1, 0]

sage: from sage.modular.pollack_stevens.manin_map import ManinMap, M2Z
sage: from sage.modular.pollack_stevens.fund_domain import ManinRelations
sage: D = OverconvergentDistributions(0, 11, 10)
sage: MR = ManinRelations(11)
sage: data  = {M2Z([1,0,0,1]):D([1,2]), M2Z([0,-1,1,3]):D([3,5]), M2Z([-1,-1,3,2]):D([1,1])}
sage: f = ManinMap(D, MR, data)
sage: f(M2Z([1,0,0,1]))
(1 + O(11^2), 2 + O(11))

sage: S = Symk(0,QQ)
sage: MR = ManinRelations(37)
sage: data  = {M2Z([-2,-3,5,7]): S(0), M2Z([1,0,0,1]): S(0), M2Z([-1,-2,3,5]): S(0), M2Z([-1,-4,2,7]): S(1), M2Z([0,-1,1,4]): S(1), M2Z([-3,-1,7,2]): S(-1), M2Z([-2,-3,3,4]): S(0), M2Z([-4,-3,7,5]): S(0), M2Z([-1,-1,4,3]): S(0)}
sage: f = ManinMap(S,MR,data)
sage: f(M2Z([2,3,4,5]))
1
>>> from sage.all import *
>>> E = EllipticCurve('11a')
>>> phi = E.pollack_stevens_modular_symbol()
>>> phi
Modular symbol of level 11 with values in Sym^0 Q^2
>>> phi.values()
[-1/5, 1, 0]

>>> from sage.modular.pollack_stevens.manin_map import ManinMap, M2Z
>>> from sage.modular.pollack_stevens.fund_domain import ManinRelations
>>> D = OverconvergentDistributions(Integer(0), Integer(11), Integer(10))
>>> MR = ManinRelations(Integer(11))
>>> data  = {M2Z([Integer(1),Integer(0),Integer(0),Integer(1)]):D([Integer(1),Integer(2)]), M2Z([Integer(0),-Integer(1),Integer(1),Integer(3)]):D([Integer(3),Integer(5)]), M2Z([-Integer(1),-Integer(1),Integer(3),Integer(2)]):D([Integer(1),Integer(1)])}
>>> f = ManinMap(D, MR, data)
>>> f(M2Z([Integer(1),Integer(0),Integer(0),Integer(1)]))
(1 + O(11^2), 2 + O(11))

>>> S = Symk(Integer(0),QQ)
>>> MR = ManinRelations(Integer(37))
>>> data  = {M2Z([-Integer(2),-Integer(3),Integer(5),Integer(7)]): S(Integer(0)), M2Z([Integer(1),Integer(0),Integer(0),Integer(1)]): S(Integer(0)), M2Z([-Integer(1),-Integer(2),Integer(3),Integer(5)]): S(Integer(0)), M2Z([-Integer(1),-Integer(4),Integer(2),Integer(7)]): S(Integer(1)), M2Z([Integer(0),-Integer(1),Integer(1),Integer(4)]): S(Integer(1)), M2Z([-Integer(3),-Integer(1),Integer(7),Integer(2)]): S(-Integer(1)), M2Z([-Integer(2),-Integer(3),Integer(3),Integer(4)]): S(Integer(0)), M2Z([-Integer(4),-Integer(3),Integer(7),Integer(5)]): S(Integer(0)), M2Z([-Integer(1),-Integer(1),Integer(4),Integer(3)]): S(Integer(0))}
>>> f = ManinMap(S,MR,data)
>>> f(M2Z([Integer(2),Integer(3),Integer(4),Integer(5)]))
1
class sage.modular.pollack_stevens.manin_map.ManinMap(codomain, manin_relations, defining_data, check=True)[source]#

Bases: object

Map from a set of right coset representatives of \(\Gamma_0(N)\) in \(SL_2(\ZZ)\) to a coefficient module that satisfies the Manin relations.

INPUT:

  • codomain – coefficient module

  • manin_relations – a sage.modular.pollack_stevens.fund_domain.ManinRelations object

  • defining_data – a dictionary whose keys are a superset of manin_relations.gens() and a subset of manin_relations.reps(), and whose values are in the codomain.

  • check – do numerous (slow) checks and transformations to ensure that the input data is perfect.

EXAMPLES:

sage: from sage.modular.pollack_stevens.manin_map import M2Z, ManinMap
sage: D = OverconvergentDistributions(0, 11, 10)
sage: manin = sage.modular.pollack_stevens.fund_domain.ManinRelations(11)
sage: data  = {M2Z([1,0,0,1]):D([1,2]), M2Z([0,-1,1,3]):D([3,5]), M2Z([-1,-1,3,2]):D([1,1])}
sage: f = ManinMap(D, manin, data); f # indirect doctest
Map from the set of right cosets of Gamma0(11) in SL_2(Z) to Space of 11-adic distributions with k=0 action and precision cap 10
sage: f(M2Z([1,0,0,1]))
(1 + O(11^2), 2 + O(11))
>>> from sage.all import *
>>> from sage.modular.pollack_stevens.manin_map import M2Z, ManinMap
>>> D = OverconvergentDistributions(Integer(0), Integer(11), Integer(10))
>>> manin = sage.modular.pollack_stevens.fund_domain.ManinRelations(Integer(11))
>>> data  = {M2Z([Integer(1),Integer(0),Integer(0),Integer(1)]):D([Integer(1),Integer(2)]), M2Z([Integer(0),-Integer(1),Integer(1),Integer(3)]):D([Integer(3),Integer(5)]), M2Z([-Integer(1),-Integer(1),Integer(3),Integer(2)]):D([Integer(1),Integer(1)])}
>>> f = ManinMap(D, manin, data); f # indirect doctest
Map from the set of right cosets of Gamma0(11) in SL_2(Z) to Space of 11-adic distributions with k=0 action and precision cap 10
>>> f(M2Z([Integer(1),Integer(0),Integer(0),Integer(1)]))
(1 + O(11^2), 2 + O(11))
apply(f, codomain=None, to_moments=False)[source]#

Return Manin map given by \(x \mapsto f(self(x))\), where \(f\) is anything that can be called with elements of the coefficient module.

This might be used to normalize, reduce modulo a prime, change base ring, etc.

INPUT:

  • f – anything that can be called with elements of the coefficient module

  • codomain – (default: None) the codomain of the return map

  • to_moments – (default: False) if True, will apply f to each of the moments instead

EXAMPLES:

sage: from sage.modular.pollack_stevens.manin_map import M2Z, ManinMap
sage: from sage.modular.pollack_stevens.fund_domain import ManinRelations
sage: S = Symk(0,QQ)
sage: MR = ManinRelations(37)
sage: data  = {M2Z([-2,-3,5,7]): S(0), M2Z([1,0,0,1]): S(0), M2Z([-1,-2,3,5]): S(0), M2Z([-1,-4,2,7]): S(1), M2Z([0,-1,1,4]): S(1), M2Z([-3,-1,7,2]): S(-1), M2Z([-2,-3,3,4]): S(0), M2Z([-4,-3,7,5]): S(0), M2Z([-1,-1,4,3]): S(0)}
sage: f = ManinMap(S,MR,data)
sage: list(f.apply(lambda t:2*t))
[0, 2, 0, 0, 0, -2, 2, 0, 0]
>>> from sage.all import *
>>> from sage.modular.pollack_stevens.manin_map import M2Z, ManinMap
>>> from sage.modular.pollack_stevens.fund_domain import ManinRelations
>>> S = Symk(Integer(0),QQ)
>>> MR = ManinRelations(Integer(37))
>>> data  = {M2Z([-Integer(2),-Integer(3),Integer(5),Integer(7)]): S(Integer(0)), M2Z([Integer(1),Integer(0),Integer(0),Integer(1)]): S(Integer(0)), M2Z([-Integer(1),-Integer(2),Integer(3),Integer(5)]): S(Integer(0)), M2Z([-Integer(1),-Integer(4),Integer(2),Integer(7)]): S(Integer(1)), M2Z([Integer(0),-Integer(1),Integer(1),Integer(4)]): S(Integer(1)), M2Z([-Integer(3),-Integer(1),Integer(7),Integer(2)]): S(-Integer(1)), M2Z([-Integer(2),-Integer(3),Integer(3),Integer(4)]): S(Integer(0)), M2Z([-Integer(4),-Integer(3),Integer(7),Integer(5)]): S(Integer(0)), M2Z([-Integer(1),-Integer(1),Integer(4),Integer(3)]): S(Integer(0))}
>>> f = ManinMap(S,MR,data)
>>> list(f.apply(lambda t:Integer(2)*t))
[0, 2, 0, 0, 0, -2, 2, 0, 0]
compute_full_data()[source]#

Compute the values of self on all coset reps from its values on our generating set.

EXAMPLES:

sage: from sage.modular.pollack_stevens.manin_map import M2Z, ManinMap
sage: from sage.modular.pollack_stevens.fund_domain import ManinRelations
sage: S = Symk(0,QQ)
sage: MR = ManinRelations(37); MR.gens()
[
[1 0]  [ 0 -1]  [-1 -1]  [-1 -2]  [-2 -3]  [-3 -1]  [-1 -4]  [-4 -3]
[0 1], [ 1  4], [ 4  3], [ 3  5], [ 5  7], [ 7  2], [ 2  7], [ 7  5],

[-2 -3]
[ 3  4]
]

sage: data  = {M2Z([-2,-3,5,7]): S(0), M2Z([1,0,0,1]): S(0), M2Z([-1,-2,3,5]): S(0), M2Z([-1,-4,2,7]): S(1), M2Z([0,-1,1,4]): S(1), M2Z([-3,-1,7,2]): S(-1), M2Z([-2,-3,3,4]): S(0), M2Z([-4,-3,7,5]): S(0), M2Z([-1,-1,4,3]): S(0)}
sage: f = ManinMap(S,MR,data)
sage: len(f._dict)
9
sage: f.compute_full_data()
sage: len(f._dict)
38
>>> from sage.all import *
>>> from sage.modular.pollack_stevens.manin_map import M2Z, ManinMap
>>> from sage.modular.pollack_stevens.fund_domain import ManinRelations
>>> S = Symk(Integer(0),QQ)
>>> MR = ManinRelations(Integer(37)); MR.gens()
[
[1 0]  [ 0 -1]  [-1 -1]  [-1 -2]  [-2 -3]  [-3 -1]  [-1 -4]  [-4 -3]
[0 1], [ 1  4], [ 4  3], [ 3  5], [ 5  7], [ 7  2], [ 2  7], [ 7  5],
<BLANKLINE>
[-2 -3]
[ 3  4]
]

>>> data  = {M2Z([-Integer(2),-Integer(3),Integer(5),Integer(7)]): S(Integer(0)), M2Z([Integer(1),Integer(0),Integer(0),Integer(1)]): S(Integer(0)), M2Z([-Integer(1),-Integer(2),Integer(3),Integer(5)]): S(Integer(0)), M2Z([-Integer(1),-Integer(4),Integer(2),Integer(7)]): S(Integer(1)), M2Z([Integer(0),-Integer(1),Integer(1),Integer(4)]): S(Integer(1)), M2Z([-Integer(3),-Integer(1),Integer(7),Integer(2)]): S(-Integer(1)), M2Z([-Integer(2),-Integer(3),Integer(3),Integer(4)]): S(Integer(0)), M2Z([-Integer(4),-Integer(3),Integer(7),Integer(5)]): S(Integer(0)), M2Z([-Integer(1),-Integer(1),Integer(4),Integer(3)]): S(Integer(0))}
>>> f = ManinMap(S,MR,data)
>>> len(f._dict)
9
>>> f.compute_full_data()
>>> len(f._dict)
38
extend_codomain(new_codomain, check=True)[source]#

Extend the codomain of self to new_codomain. There must be a valid conversion operation from the old to the new codomain. This is most often used for extension of scalars from \(\QQ\) to \(\QQ_p\).

EXAMPLES:

sage: from sage.modular.pollack_stevens.manin_map import ManinMap, M2Z
sage: from sage.modular.pollack_stevens.fund_domain import ManinRelations
sage: S = Symk(0,QQ)
sage: MR = ManinRelations(37)
sage: data  = {M2Z([-2,-3,5,7]): S(0), M2Z([1,0,0,1]): S(0), M2Z([-1,-2,3,5]): S(0), M2Z([-1,-4,2,7]): S(1), M2Z([0,-1,1,4]): S(1), M2Z([-3,-1,7,2]): S(-1), M2Z([-2,-3,3,4]): S(0), M2Z([-4,-3,7,5]): S(0), M2Z([-1,-1,4,3]): S(0)}
sage: m = ManinMap(S, MR, data); m
Map from the set of right cosets of Gamma0(37) in SL_2(Z) to Sym^0 Q^2
sage: m.extend_codomain(Symk(0, Qp(11)))
Map from the set of right cosets of Gamma0(37) in SL_2(Z) to Sym^0 Q_11^2
>>> from sage.all import *
>>> from sage.modular.pollack_stevens.manin_map import ManinMap, M2Z
>>> from sage.modular.pollack_stevens.fund_domain import ManinRelations
>>> S = Symk(Integer(0),QQ)
>>> MR = ManinRelations(Integer(37))
>>> data  = {M2Z([-Integer(2),-Integer(3),Integer(5),Integer(7)]): S(Integer(0)), M2Z([Integer(1),Integer(0),Integer(0),Integer(1)]): S(Integer(0)), M2Z([-Integer(1),-Integer(2),Integer(3),Integer(5)]): S(Integer(0)), M2Z([-Integer(1),-Integer(4),Integer(2),Integer(7)]): S(Integer(1)), M2Z([Integer(0),-Integer(1),Integer(1),Integer(4)]): S(Integer(1)), M2Z([-Integer(3),-Integer(1),Integer(7),Integer(2)]): S(-Integer(1)), M2Z([-Integer(2),-Integer(3),Integer(3),Integer(4)]): S(Integer(0)), M2Z([-Integer(4),-Integer(3),Integer(7),Integer(5)]): S(Integer(0)), M2Z([-Integer(1),-Integer(1),Integer(4),Integer(3)]): S(Integer(0))}
>>> m = ManinMap(S, MR, data); m
Map from the set of right cosets of Gamma0(37) in SL_2(Z) to Sym^0 Q^2
>>> m.extend_codomain(Symk(Integer(0), Qp(Integer(11))))
Map from the set of right cosets of Gamma0(37) in SL_2(Z) to Sym^0 Q_11^2
hecke(ell, algorithm='prep')[source]#

Return the image of this Manin map under the Hecke operator \(T_{\ell}\).

INPUT:

  • ell – a prime

  • algorithm – a string, either ‘prep’ (default) or ‘naive’

OUTPUT:

  • The image of this ManinMap under the Hecke operator \(T_{\ell}\)

EXAMPLES:

sage: E = EllipticCurve('11a')
sage: phi = E.pollack_stevens_modular_symbol()
sage: phi.values()
[-1/5, 1, 0]
sage: phi.is_Tq_eigensymbol(7,7,10)
True
sage: phi.hecke(7).values()
[2/5, -2, 0]
sage: phi.Tq_eigenvalue(7,7,10)
-2
>>> from sage.all import *
>>> E = EllipticCurve('11a')
>>> phi = E.pollack_stevens_modular_symbol()
>>> phi.values()
[-1/5, 1, 0]
>>> phi.is_Tq_eigensymbol(Integer(7),Integer(7),Integer(10))
True
>>> phi.hecke(Integer(7)).values()
[2/5, -2, 0]
>>> phi.Tq_eigenvalue(Integer(7),Integer(7),Integer(10))
-2
normalize()[source]#

Normalize every value of self – e.g., reduces each value’s \(j\)-th moment modulo \(p^{N-j}\)

EXAMPLES:

sage: from sage.modular.pollack_stevens.manin_map import M2Z, ManinMap
sage: D = OverconvergentDistributions(0, 11, 10)
sage: manin = sage.modular.pollack_stevens.fund_domain.ManinRelations(11)
sage: data  = {M2Z([1,0,0,1]):D([1,2]), M2Z([0,-1,1,3]):D([3,5]), M2Z([-1,-1,3,2]):D([1,1])}
sage: f = ManinMap(D, manin, data)
sage: f._dict[M2Z([1,0,0,1])]
(1 + O(11^2), 2 + O(11))
sage: g = f.normalize()
sage: g._dict[M2Z([1,0,0,1])]
(1 + O(11^2), 2 + O(11))
>>> from sage.all import *
>>> from sage.modular.pollack_stevens.manin_map import M2Z, ManinMap
>>> D = OverconvergentDistributions(Integer(0), Integer(11), Integer(10))
>>> manin = sage.modular.pollack_stevens.fund_domain.ManinRelations(Integer(11))
>>> data  = {M2Z([Integer(1),Integer(0),Integer(0),Integer(1)]):D([Integer(1),Integer(2)]), M2Z([Integer(0),-Integer(1),Integer(1),Integer(3)]):D([Integer(3),Integer(5)]), M2Z([-Integer(1),-Integer(1),Integer(3),Integer(2)]):D([Integer(1),Integer(1)])}
>>> f = ManinMap(D, manin, data)
>>> f._dict[M2Z([Integer(1),Integer(0),Integer(0),Integer(1)])]
(1 + O(11^2), 2 + O(11))
>>> g = f.normalize()
>>> g._dict[M2Z([Integer(1),Integer(0),Integer(0),Integer(1)])]
(1 + O(11^2), 2 + O(11))
p_stabilize(p, alpha, V)[source]#

Return the \(p\)-stabilization of self to level \(N*p\) on which \(U_p\) acts by \(\alpha\).

INPUT:

  • p – a prime.

  • alpha – a \(U_p\)-eigenvalue.

  • V – a space of modular symbols.

OUTPUT:

  • The image of this ManinMap under the Hecke operator \(T_{\ell}\)

EXAMPLES:

sage: E = EllipticCurve('11a')
sage: phi = E.pollack_stevens_modular_symbol()
sage: f = phi._map
sage: V = phi.parent()
sage: f.p_stabilize(5,1,V)
Map from the set of right cosets of Gamma0(11) in SL_2(Z) to Sym^0 Q^2
>>> from sage.all import *
>>> E = EllipticCurve('11a')
>>> phi = E.pollack_stevens_modular_symbol()
>>> f = phi._map
>>> V = phi.parent()
>>> f.p_stabilize(Integer(5),Integer(1),V)
Map from the set of right cosets of Gamma0(11) in SL_2(Z) to Sym^0 Q^2
reduce_precision(M)[source]#

Reduce the precision of all the values of the Manin map.

INPUT:

  • M – an integer, the new precision.

EXAMPLES:

sage: from sage.modular.pollack_stevens.manin_map import M2Z, ManinMap
sage: D = OverconvergentDistributions(0, 11, 10)
sage: manin = sage.modular.pollack_stevens.fund_domain.ManinRelations(11)
sage: data  = {M2Z([1,0,0,1]):D([1,2]), M2Z([0,-1,1,3]):D([3,5]), M2Z([-1,-1,3,2]):D([1,1])}
sage: f = ManinMap(D, manin, data)
sage: f._dict[M2Z([1,0,0,1])]
(1 + O(11^2), 2 + O(11))
sage: g = f.reduce_precision(1)
sage: g._dict[M2Z([1,0,0,1])]
1 + O(11^2)
>>> from sage.all import *
>>> from sage.modular.pollack_stevens.manin_map import M2Z, ManinMap
>>> D = OverconvergentDistributions(Integer(0), Integer(11), Integer(10))
>>> manin = sage.modular.pollack_stevens.fund_domain.ManinRelations(Integer(11))
>>> data  = {M2Z([Integer(1),Integer(0),Integer(0),Integer(1)]):D([Integer(1),Integer(2)]), M2Z([Integer(0),-Integer(1),Integer(1),Integer(3)]):D([Integer(3),Integer(5)]), M2Z([-Integer(1),-Integer(1),Integer(3),Integer(2)]):D([Integer(1),Integer(1)])}
>>> f = ManinMap(D, manin, data)
>>> f._dict[M2Z([Integer(1),Integer(0),Integer(0),Integer(1)])]
(1 + O(11^2), 2 + O(11))
>>> g = f.reduce_precision(Integer(1))
>>> g._dict[M2Z([Integer(1),Integer(0),Integer(0),Integer(1)])]
1 + O(11^2)
specialize(*args)[source]#

Specialize all the values of the Manin map to a new coefficient module. Assumes that the codomain has a specialize method, and passes all its arguments to that method.

EXAMPLES:

sage: from sage.modular.pollack_stevens.manin_map import M2Z, ManinMap
sage: D = OverconvergentDistributions(0, 11, 10)
sage: manin = sage.modular.pollack_stevens.fund_domain.ManinRelations(11)
sage: data  = {M2Z([1,0,0,1]):D([1,2]), M2Z([0,-1,1,3]):D([3,5]), M2Z([-1,-1,3,2]):D([1,1])}
sage: f = ManinMap(D, manin, data)
sage: g = f.specialize()
sage: g._codomain
Sym^0 Z_11^2
>>> from sage.all import *
>>> from sage.modular.pollack_stevens.manin_map import M2Z, ManinMap
>>> D = OverconvergentDistributions(Integer(0), Integer(11), Integer(10))
>>> manin = sage.modular.pollack_stevens.fund_domain.ManinRelations(Integer(11))
>>> data  = {M2Z([Integer(1),Integer(0),Integer(0),Integer(1)]):D([Integer(1),Integer(2)]), M2Z([Integer(0),-Integer(1),Integer(1),Integer(3)]):D([Integer(3),Integer(5)]), M2Z([-Integer(1),-Integer(1),Integer(3),Integer(2)]):D([Integer(1),Integer(1)])}
>>> f = ManinMap(D, manin, data)
>>> g = f.specialize()
>>> g._codomain
Sym^0 Z_11^2
sage.modular.pollack_stevens.manin_map.unimod_matrices_from_infty(r, s)[source]#

Return a list of matrices whose associated unimodular paths connect \(\infty\) to r/s.

INPUT:

  • r, s – rational numbers

OUTPUT:

  • a list of \(SL_2(\ZZ)\) matrices

EXAMPLES:

sage: v = sage.modular.pollack_stevens.manin_map.unimod_matrices_from_infty(19,23); v
[
[ 0  1]  [-1  0]  [-4  1]  [-5 -4]  [-19   5]
[-1  0], [-1 -1], [-5  1], [-6 -5], [-23   6]
]
sage: [a.det() for a in v]
[1, 1, 1, 1, 1]

sage: sage.modular.pollack_stevens.manin_map.unimod_matrices_from_infty(11,25)
[
[ 0  1]  [-1  0]  [-3  1]  [-4 -3]  [-11   4]
[-1  0], [-2 -1], [-7  2], [-9 -7], [-25   9]
]
>>> from sage.all import *
>>> v = sage.modular.pollack_stevens.manin_map.unimod_matrices_from_infty(Integer(19),Integer(23)); v
[
[ 0  1]  [-1  0]  [-4  1]  [-5 -4]  [-19   5]
[-1  0], [-1 -1], [-5  1], [-6 -5], [-23   6]
]
>>> [a.det() for a in v]
[1, 1, 1, 1, 1]

>>> sage.modular.pollack_stevens.manin_map.unimod_matrices_from_infty(Integer(11),Integer(25))
[
[ 0  1]  [-1  0]  [-3  1]  [-4 -3]  [-11   4]
[-1  0], [-2 -1], [-7  2], [-9 -7], [-25   9]
]

ALGORITHM:

This is Manin’s continued fraction trick, which gives an expression \(\{\infty,r/s\} = \{\infty,0\} + ... + \{a,b\} + ... + \{*,r/s\}\), where each \(\{a,b\}\) is the image of \(\{0,\infty\}\) under a matrix in \(SL_2(\ZZ)\).

sage.modular.pollack_stevens.manin_map.unimod_matrices_to_infty(r, s)[source]#

Return a list of matrices whose associated unimodular paths connect \(0\) to r/s.

INPUT:

  • r, s – rational numbers

OUTPUT:

  • a list of matrices in \(SL_2(\ZZ)\)

EXAMPLES:

sage: v = sage.modular.pollack_stevens.manin_map.unimod_matrices_to_infty(19,23); v
[
[1 0]  [ 0  1]  [1 4]  [-4  5]  [ 5 19]
[0 1], [-1  1], [1 5], [-5  6], [ 6 23]
]
sage: [a.det() for a in v]
[1, 1, 1, 1, 1]

sage: sage.modular.pollack_stevens.manin_map.unimod_matrices_to_infty(11,25)
[
[1 0]  [ 0  1]  [1 3]  [-3  4]  [ 4 11]
[0 1], [-1  2], [2 7], [-7  9], [ 9 25]
]
>>> from sage.all import *
>>> v = sage.modular.pollack_stevens.manin_map.unimod_matrices_to_infty(Integer(19),Integer(23)); v
[
[1 0]  [ 0  1]  [1 4]  [-4  5]  [ 5 19]
[0 1], [-1  1], [1 5], [-5  6], [ 6 23]
]
>>> [a.det() for a in v]
[1, 1, 1, 1, 1]

>>> sage.modular.pollack_stevens.manin_map.unimod_matrices_to_infty(Integer(11),Integer(25))
[
[1 0]  [ 0  1]  [1 3]  [-3  4]  [ 4 11]
[0 1], [-1  2], [2 7], [-7  9], [ 9 25]
]

ALGORITHM:

This is Manin’s continued fraction trick, which gives an expression \(\{0,r/s\} = \{0,\infty\} + ... + \{a,b\} + ... + \{*,r/s\}\), where each \(\{a,b\}\) is the image of \(\{0,\infty\}\) under a matrix in \(SL_2(\ZZ)\).