1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
function NextPrimeInArithmeticProgression(p, a, b);
// the smallest prime q > p such that q mod a = b mod a
  assert GCD(a,b) eq 1;
  b := b mod a;
  q := p;
  repeat q := NextPrime(q); until q mod a eq b;
  return q;
end function;

function UnitExponent(N)
// the exponent of the group (Z/NZ)^*
  return Exponent(UnitGroup(Integers(N)));
end function;

function SuitableRootOfUnity(N : lowerbound := 0)
//
  r := UnitExponent(N);
  if lowerbound eq 0 then
    lowerbound := r;
  end if;
  p := NextPrimeInArithmeticProgression(lowerbound, r, 1);
  zeta := RootOfUnity(r, GF(p));
  return zeta, r;
end function;


function NextSuitableRootOfUnity(zeta, r)
//
  p := Characteristic(Parent(zeta));
  p := NextPrimeInArithmeticProgression(p, r, 1);
  zeta := RootOfUnity(r, GF(p));
  return zeta, r;
end function;

function IsStrange(label : zeta := 0, r := 0, new := false)
    chi := DirichletCharacter(label: zeta:=zeta, r:=r);
    S := CuspidalSubspace(ModularSymbols(chi, 2, 1));
    if new then
      S := NewSubspace(S);
    end if;
    if Dimension(S) eq 0 then return false, 0, 0; end if;
    W := WindingSubmodule(S);
    dimS := Dimension(S);
    dimW := Dimension(W);
    return dimS ne dimW, dimW, dimS;
end function;



function StrangeInfo(N : lowerbound := 2^25, tries := 10, new := false, proof := true)
    zeta, r := SuitableRootOfUnity(N : lowerbound := lowerbound);
    potentially_strange_characters := [];
    for label in ConreyCharacterOrbitReps(N) do
      // skip the trivial character
      if Order(label) eq 1 then continue; end if;

      success := false;
      for i in [1..tries] do
        try
          is_strange, dimW, dimS := IsStrange(label : zeta:=zeta, r:=r, new := new);
          success := true;
          break;
        catch e
          zeta, r := NextSuitableRootOfUnity(zeta, r);
        end try;
      end for;
      error if not success, "computation did not succeed, increase the number of tries";


      if is_strange and proof then
        is_strange, dimW, dimS := IsStrange(label : zeta:=0, r:=0, new := new);
      end if;

      if is_strange then
        Append(~potentially_strange_characters, <CharacterOrbitLabel(label), Order(label), dimS - dimW, dimS>);
      end if;

    end for;
    return potentially_strange_characters;
end function;

function Quote(o)
  return Sprintf("\"%o\"",o);
end function;

function AsListOfStrings(l)
  return [Quote(x) : x in l];
end function;

function PrintStrangeInfoRange(a, b : lowerbound := 2^25, tries := 10, new := false, proof := true)
  print "{";
  separator := ",";
  for N in [a..b] do
    strange_info := StrangeInfo(N : lowerbound := lowerbound, tries := tries, new := new, proof := proof);
    if N eq b then separator := ""; end if;
    print Quote(N), ":", [AsListOfStrings(l) : l in strange_info], separator;
  end for;
  print "}";
  return "";
end function;

if assigned start and assigned stop then
  start := StringToInteger(start);
  stop := StringToInteger(stop);
  if not assigned new then
    new := false;
  else
    new := new eq "true";
  end if;
  PrintStrangeInfoRange(start, stop : new := new);
  exit;
end if;