Skip to main content
  • Home
  • Development
  • Documentation
  • Donate
  • Operational login
  • Browse the archive

swh logo
SoftwareHeritage
Software
Heritage
Archive
Features
  • Search

  • Downloads

  • Save code now

  • Add forge now

  • Help

https://github.com/koffie/mdmagma
22 August 2025, 12:46:07 UTC
  • Code
  • Branches (5)
  • Releases (0)
  • Visits
    • Branches
    • Releases
    • HEAD
    • refs/heads/master
    • refs/heads/patch-1
    • refs/tags/v0.1.0
    • refs/tags/v0.2.0
    • refs/tags/v0.2.1
    No releases to show
  • 0d70025
  • /
  • v2
  • /
  • modular_curves
  • /
  • X1.m
Raw File Download Save again
Take a new snapshot of a software origin

If the archived software origin currently browsed is not synchronized with its upstream version (for instance when new commits have been issued), you can explicitly request Software Heritage to take a new snapshot of it.

Use the form below to proceed. Once a request has been submitted and accepted, it will be processed as soon as possible. You can then check its processing state by visiting this dedicated page.
swh spinner

Processing "take a new snapshot" request ...

To reference or cite the objects present in the Software Heritage archive, permalinks based on SoftWare Hash IDentifiers (SWHIDs) must be used.
Select below a type of object currently browsed in order to display its associated SWHID and permalink.

  • content
  • directory
  • revision
  • snapshot
origin badgecontent badge
swh:1:cnt:282c83a6e386e2909a161c2dfac9a71f44975084
origin badgedirectory badge
swh:1:dir:761cad03363ad789f4d1c77f65b15baafc1f6c5c
origin badgerevision badge
swh:1:rev:4fdd829a268f4236ec4e9dfa781f2c0ad5956c53
origin badgesnapshot badge
swh:1:snp:69a0fcb477f0fe8dbd9256da2f6292c8d8cf7556

This interface enables to generate software citations, provided that the root directory of browsed objects contains a citation.cff or codemeta.json file.
Select below a type of object currently browsed in order to generate citations for them.

  • content
  • directory
  • revision
  • snapshot
Generate software citation in BibTex format (requires biblatex-software package)
Generating citation ...
Generate software citation in BibTex format (requires biblatex-software package)
Generating citation ...
Generate software citation in BibTex format (requires biblatex-software package)
Generating citation ...
Generate software citation in BibTex format (requires biblatex-software package)
Generating citation ...
Tip revision: 4fdd829a268f4236ec4e9dfa781f2c0ad5956c53 authored by Maarten Derickx on 12 August 2025, 17:58:16 UTC
Fix whitespace issues
Tip revision: 4fdd829
X1.m

declare type MDCrvMod1: MDCrvMod;
declare attributes MDCrvMod1:level, curve, N, _E, _P,
    _coordinates, _coordinates_xy, _coordinates_F2F3, _cusp_data, _classgroup;

X1LevelStructure := recformat< P : PtEll>;


intrinsic Print(X::MDCrvMod1)
{Print X}
   base_ring := BaseRing(X);
   printf "The modular curve X_1(%o) over %o", X`N,  base_ring;
end intrinsic;

intrinsic MDX1(N::RngIntElt, base_ring::Rng) -> MDCrvMod1
{ Create the modular curve X_1(N) }
  require N ge 10: "X_1(N) is only implemented for N >= 10";
  X := New(MDCrvMod1);
  _InitMDCrvMod1(X, N, base_ring);
  return X;
end intrinsic;

intrinsic _InitMDCrvMod1(X::MDCrvMod1, N::RngIntElt,
    base_ring::Rng: equation_directory:="")
{Initialize an MDCrvMod1 object}
    X`N := N;
    curve, E, P, coordinates, coordinates_xy, coordinates_F2F3 := _equation_X1(
        N,base_ring : equation_directory:=equation_directory
    );
    X`_P := P;
    X`_coordinates := coordinates;
    X`_coordinates_xy := coordinates_xy;
    X`_coordinates_F2F3 := coordinates_F2F3;
    _InitMDCrvMod(X, N,  curve, E);
end intrinsic;

intrinsic LevelStructure(X::MDCrvMod1, x::PlcCrvElt) -> Rec
{   Return the level structure corresponding to the place x on Y1(N).
    To be precise. It returns is a RecFormat r such that r`P is a point of order N.
    It raises an error if x is a cusp.
}
    Ex := EllipticCurve(X, x);
    Px := Ex ! [Evaluate(f, x) : f in X`_P];
    return rec<X1LevelStructure | P := Px>;
end intrinsic;


intrinsic ModuliPoint(X::MDCrvMod1, E::CrvEll, levelstructure::Rec) -> PlcCrvElt
{   Return the place x on X1(N), corresponding to the pair (E, levelstructure).
    It assumes that levelstructure is a RecFormat  such that levelstructure`P is a point
    of order N.
}
    K := BaseRing(E);
    xy := TateNormalForm_xy(E, levelstructure`P);
    dP := Places(Curve(X)(K) ! xy);
    assert #dP eq 1;
    return dP[1];
end intrinsic;

intrinsic TateNormalForm_bc(E::CrvEll, P::PtEll) -> Seq
{ Return the b,c of the tate normal form of (E,P) as in equation (2) of http://arxiv.org/pdf/1307.5719v1.pdf }
    assert P[3] eq 1;
    x0:=P[1];
    y0:=P[2];

    a1,a2,a3,a4,a6:=Explode(aInvariants(E));
    aa1:=a1;
    aa3:=2*y0+a3+a1*x0;
    aa2:=3*x0+a2;
    aa4:=3*x0^2+2*x0*a2+a4-a1*y0;

    aaa1:=2*aa4/aa3+aa1;
    aaa3:=aa3;
    aaa2:=aa2-(aa4/aa3)^2-aa1*aa4/aa3;


    b:=-aaa2^3/aaa3^2;
    c:=-(aaa1*aaa2-aaa3)/aaa3;
    return [b,c];
end intrinsic;

intrinsic TateNormalForm_xy(E::CrvEll, P::PtEll) -> Seq
{ return the x,y of the tate normal form of (E,P) as in section 2.1 http://arxiv.org/pdf/1307.5719v1.pdf }
    b,c := Explode(TateNormalForm_bc(E,P));
    r := b/c;
    s := c^2/(b-c);
    t := (r*s-2*r+1);
    x := (s-r)/t;
    y := t/(s^2-s-r+1);
    return [x,y];
end intrinsic;


intrinsic ApplyIsogeny(X::MDCrvMod1, phi:: MapSch[CrvEll, CrvEll], levelstructure::Rec) -> Rec
{   Return the level structure corresponding to phi(levelstructure)
}
    return rec<X1LevelStructure | P := phi(levelstructure`P)>;
end intrinsic;

intrinsic DiamondOperator(X::MDCrvMod1, d::RngIntElt, levelstructure::Rec) -> Rec
{   Return the level structure corresponding to d*P; where d is coprime to the level
}
    require GCD(d, Level(X)) eq 1: "d should be coprime to the level";
    return rec<X1LevelStructure | P := d*levelstructure`P>;
end intrinsic;


intrinsic DegeneracyMap(X::MDCrvMod1, d::RngIntElt, levelstructure::Rec) -> Rec
{   Return the level structure corresponding to d*P; where d is a divisor of the level
}
    assert (Level(X) mod d) eq 0;
    return rec<X1LevelStructure | P := d*levelstructure`P>;
end intrinsic;


intrinsic DegeneracyMap(X::MDCrvMod1, Y::MDCrvMod1, x::PlcCrvElt) -> PlcCrvElt
{ If the place x corresponds to (E,P) the place y corresponding to (E,P*Level(X)/Level(Y))
  taking into account multiplicities. I.e. if deg(y) = deg(x) it returns y, if not
  y deg(x)/deg(y) is returned.}
    M := Level(X);
    N := Level(Y);
    require M mod N eq 0: "the level of Y should divide the level of X";
    E := EllipticCurve(X, x);
    L := LevelStructure(X, x);
    y := ModuliPoint(Y, E, DegeneracyMap(X, M div N, L));
    assert Degree(x) mod Degree(y) eq 0;
    return (Degree(x) div Degree(y))*y;
end intrinsic;

intrinsic _equation_X1(n,base_ring : equation_directory:="") -> CrvPln
{  Input: n - an integer
          base_ring - a ring
          equation_directory - directory with files FFFc<n>.txt containing models
    Output: C - a curve
    Returns an algebraic model C of the modular curve X_1(n) as a curve over base_ring
}
    if equation_directory eq "" then
      equation_directory := MDMagmaSourceDir() cat "/../models_X1_n";
    end if;

    n_str := IntegerToString(n);
    file_name := equation_directory cat "/FFFc" cat n_str cat ".txt";
    data := Read(file_name);

    A<x,y> := AffineSpace(base_ring,2);
    X := eval(data);
    C := Curve(A,X);
    FF := FunctionField(C);
    x := FF.1;
    y := FF.2;
    r := (x^2*y-x*y+y-1)/x/(x*y-1);
    s := (x*y-y+1)/x/y;
    b := r*s*(r-1);
    c := s*(r-1);
    E := [1-c, -b, -b, FF ! 0, FF ! 0];
    P := [FF ! 0, FF ! 0];
    coordinates := [b, c];
    coordinates_xy := [x, y];
    coordinates_F2F3 :=  [b/(16*b^2+(1-20*c-8*c^2)*b + c*(c-1)^3),b];
    return ProjectiveClosure(C), E, P, coordinates, coordinates_xy, coordinates_F2F3;
end intrinsic;

intrinsic CongruenceSubgroup(X::MDCrvMod1) -> GrpPSL2
{ The subgroup of PSL2 corresponding to this modular curve }
    return Gamma1(Level(X));
end intrinsic;

intrinsic Cusps(X::MDCrvMod1) -> SeqEnum[PlcCrvElt]
{ The cusps on this modular curve }
    cusps := Support(Divisor(DiscriminantMap(X)));
    nr_cusps := #Cusps(CongruenceSubgroup(X));
    xy := X`_coordinates_xy;
    cusps := Seqset(cusps cat Poles(xy[1]) cat Poles(xy[2]));
    assert &+[Degree(c) : c in cusps] eq nr_cusps;
    return Setseq(cusps);
end intrinsic;

intrinsic CuspSignature(X::MDCrvMod1, C::PlcCrvElt) -> SeqEnum[RngIntElt]
{ Returns the valuation of F2 and F3 at the place C }
    require IsCusp(X, C) : "C should be a cusp!";
    return [Valuation(f, C) : f in X`_coordinates_F2F3];
end intrinsic;

intrinsic CuspOrbitCountQ(X::MDCrvMod1) -> RngIntElt
{ Returns the number of Galois orbits of cusps of X_1(n) using 2.8(1) of
https://arxiv.org/pdf/2007.13929 . }
    n := Level(X);
    orbits:=0;
    divs:=Divisors(n);
    for d in divs do
        if d eq 1 or d eq 2 then
           orbits:=orbits+1;
        end if;
        if d gt 2 then
           orbits:=orbits+(EulerPhi(d) div 2);
        end if;
    end for;
    return orbits;
end intrinsic;

intrinsic _InitialiseCuspData(X::MDCrvMod1)
{ Compute the signatures of all cusps, and create a lookup table to get the cusps
corresponding to a signature. It raises an error if the signature doesn't uniquely
determine the galois orbit over Q. }
    if assigned X`_cusp_data then
        return;
    end if;
    cusp_data := AssociativeArray();
    for c in Cusps(X) do
        signature :=  CuspSignature(X,c);
        if IsDefined(cusp_data, signature) then
            Append(~cusp_data[signature], c);
        else
            cusp_data[signature] := [c];
        end if;
    end for;
    assert #cusp_data eq CuspOrbitCountQ(X);
    X`_cusp_data := cusp_data;
end intrinsic;

intrinsic _CuspData(X::MDCrvMod1) -> Assoc
{ Return the associative array mapping cusp signatures to cusps }
    _InitialiseCuspData(X);
    return X`_cusp_data;
end intrinsic;

intrinsic CuspsWithSignature(X::MDCrvMod1, signature::SeqEnum[RngIntElt]) -> SeqEnum[PlcCrvElt]
{ Returns the cusps of the given signature }
    _InitialiseCuspData(X);
    return X`_cusp_data[signature];
end intrinsic;

intrinsic IsCuspSignatureUnique(X::MDCrvMod1) -> BoolElt
{ Returns true if and only if there is only one galois orbit of cusps per cusp signature }
    return &and[#c eq 1 : c in MDValues(_CuspData(X))];
end intrinsic;

intrinsic CuspOrbitsQ(X::MDCrvMod1) -> SeqEnum[DivCrvElt]
{ The galois orbits over Q of cusps on this modular curve as divisors. Note that when
  the modular curve is defined over a finite field of positive characteristic one still
  has an action of the galois group over Q.
}
    orbits := [&+c : c in MDValues(_CuspData(X))];
    return orbits;
end intrinsic;

back to top

Software Heritage — Copyright (C) 2015–2026, The Software Heritage developers. License: GNU AGPLv3+.
The source code of Software Heritage itself is available on our development forge.
The source code files archived by Software Heritage are available under their own copyright and licenses.
Terms of use: Archive access, API— Content policy— Contact— JavaScript license information— Web API