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, ); 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;