# This file contains information about points in EX^* whose coordinates
# are rational, or rational multiples of sqrt(2), or otherwise
# arithmetically simple.
#@ c_rational
c_rational[0] := (t) -> [t^2-1,2*t,0,0] /~ (t^2+1);
c_rational_condition[0] := (t) -> type(t,rational);
c_rational[1] := (st) -> [ st[1],st[1],st[2],0];
c_rational_condition[1] :=
(st) -> type(st,[rational,rational]) and 2*st[1]^2 + st[2]^2 = 1;
c_rational[2] := (st) -> [-st[1],st[1],st[2],0];
c_rational_condition[2] :=
(st) -> type(st,[rational,rational]) and 2*st[1]^2 + st[2]^2 = 1;
#@ c_quasirational
c_quasirational[1] := (t) ->
[ 1-t^2-2*t ,1-t^2-2*t,sqrt(2)*(1-t^2+2*t),0] /~ (2*(1+t^2));
c_quasirational_condition[1] := (t) -> type(t,rational);
c_quasirational[2] := (t) ->
[-(1-t^2-2*t),1-t^2-2*t,sqrt(2)*(1-t^2+2*t),0] /~ (2*(1+t^2));
c_quasirational_condition[2] := (t) -> type(t,rational);
c_quasirational[3] := (st) -> [0, st[2],sqrt(2)*st[1],-st[1]];
c_quasirational_condition[3] :=
(st) -> type(st,[rational,rational]) and 3*st[1]^2 + st[2]^2 = 1;
c_quasirational[4] := (st) -> [-st[2],0,sqrt(2)*st[1], st[1]];
c_quasirational_condition[4] :=
(st) -> type(st,[rational,rational]) and 3*st[1]^2 + st[2]^2 = 1;
c_quasirational[5] := (t) -> [sqrt((1-t)*t/(t+2)), 0, sqrt(2/(t+2)), -sqrt(t^2/(t+2))];
##################################################
# farey_count(n) is the number of rationals in [0,1] with denominator
# at most n.
#@ farey_count
farey_count := (n) -> 1 + add(numtheory[phi](i),i=1..n):
# farey(n) is the list of rationals in [0,1] with denominator at most n.
#@ farey
farey := proc(n)
local F,a,b,c,d,a0,b0,k;
a := 0;
b := 1;
c := 1;
d := n;
F := a/b;
while c <= n do
k := floor((n+b)/d);
a0 := a;
b0 := b;
a := c;
b := d;
c := k*c - a0;
d := k*d - b0;
F := F,a/b;
od;
return [F];
end:
##################################################
# This section is about solutions to 2 s^2 + t^2 = 1.
# two_roots is the set of roots of unity in Q(sqrt(-2)).
#@ two_roots
two_roots := [1,-1];
# two_primes is a list of prime numbers that factor in Q(sqrt(-2))
# For each such prime p, two_pi[p] is the prime element of
# Q(sqrt(-2)) in the upper half plane that divides p, and
# two_u[p] is two_pi[p] / conjugate(two_pi[p]), which has
# norm one.
#@ two_primes
two_primes := NULL;
#@ two_pi
#@ two_u
for i from 2 to 200 do
p := ithprime(i);
if modp(p,8) = 1 or modp(p,8) = 3 then
two_primes := two_primes,p;
uv := select(ab -> (ab[1]>0 and ab[2]>0),map(s -> subs(s,[a,b]),[isolve(p=2*a^2+b^2)]))[1];
two_pi[p] := uv[1]*sqrt(-2) + uv[2];
two_u[p] := expand(rationalize(two_pi[p]/conjugate(two_pi[p])));
fi;
od;
# two_units_aux(n) is a list of units in Q(sqrt(-2)) with
# denominator equal to n.
#@ two_units_aux
two_units_aux := proc(n)
local ff,f,Q;
if n = 1 then return {1}; fi;
ff := ifactor(n);
if type(ff,`*`) then ff := [op(ff)]; else ff := [ff]; fi;
ff := map(f -> `if`(type(f,`^`),[op(f)],[f,1]),ff);
ff := map(f -> two_u[op(op(1,f))]^op(2,f),ff);
Q := {1};
for f in ff do
Q := {op(Q *~ f),op(Q /~ f)};
od;
Q := expand(rationalize(Q));
return(Q);
end:
#@ two_circle
two_circle := proc(max_denom)
local NN,C;
NN := {seq(n,n=1..max_denom)};
NN := select(n -> mods({1,3,op(prime_factors(n))},8) = {1,3},NN);
C := map(op,map(two_units_aux,NN));
C := map(op,map(u -> expand(u *~ two_roots),C));
C := map(u -> [Im(u)/sqrt(2),Re(u)],C);
C := sort([op(C)]);
return C;
end:
##################################################
# This section is about solutions to 3 s^2 + t^2 = 1.
# three_roots is the set of roots of unity in Q(sqrt(-3)).
#@ three_roots
three_roots := simplify([seq(exp(Pi*I*k/3),k=0..5)]);
# three_primes is a list of prime numbers that factor in Q(sqrt(-3))
# For each such prime p, three_pi[p] is the prime element of
# Q(sqrt(-3)) in the upper half plane that divides p, and
# three_u[p] is three_pi[p] / conjugate(three_pi[p]), which has
# norm one.
#@ three_primes
three_primes := NULL:
#@ three_pi
#@ three_u
for i from 3 to 200 do
p := ithprime(i);
if mods(p,3) = 1 then
three_primes := three_primes,p;
uv := select(ab -> (ab[1]>0 and ab[2]>0),map(s -> subs(s,[a,b]),[isolve(p=3*a^2+b^2)]))[1];
three_pi[p] := uv[1]*sqrt(-3) + uv[2];
three_u[p] := expand(rationalize(three_pi[p]/conjugate(three_pi[p])));
fi;
od:
# three_units_aux(n) is a list of units in Q(sqrt(-3)) with
# denominator equal to n.
#@ three_units_aux
three_units_aux := proc(n)
local ff,f,Q;
if n = 1 then return {1}; fi;
ff := ifactor(n);
if type(ff,`*`) then ff := [op(ff)]; else ff := [ff]; fi;
ff := map(f -> `if`(type(f,`^`),[op(f)],[f,1]),ff);
ff := map(f -> three_u[op(op(1,f))]^op(2,f),ff);
Q := {1};
for f in ff do
Q := {op(Q *~ f),op(Q /~ f)};
od;
Q := expand(rationalize(Q));
return(Q);
end:
#@ three_circle
three_circle := proc(max_denom)
local NN,C;
NN := {seq(n,n=1..max_denom)};
NN := select(n -> mods({1,op(prime_factors(n))},3) = {1},NN);
C := map(op,map(three_units_aux,NN));
C := map(op,map(u -> expand(u *~ three_roots),C));
C := map(u -> [Im(u)/sqrt(3),Re(u)],C);
C := sort([op(C)]);
return C;
end:
######################################################################
#@ elliptic_t
elliptic_t := (x) -> x[1]^2;
#@ elliptic_u
elliptic_u := (x) -> x[1]*(x[4]^2-5/sqrt(2)*x[3]*x[4]-1);
#@ elliptic_r
elliptic_r[0] := (x) -> x[1]^2+x[3]^2+x[4]^2-1;
elliptic_r[1] := (x) -> x[1]^2+x[4]^2+x[3]*x[4]/sqrt(2);
#@ elliptic_a
elliptic_a[0] := (x) -> -6*sqrt(2)*(x[3]+sqrt(2)*x[4])*x[4]^3;
elliptic_a[1] := (x) -> (1-x[3]^2-x[4]^2) * (x[3]^2 -10*x[4]^2 + 9 + x[3]*x[4]/sqrt(2));
elliptic_a[2] := (x) -> x[3]^2 + 2*x[4]^2 + x[3]*x[4]/sqrt(2) - x[1]^2 + 9;
#@ elliptic_rel
elliptic_rel := (u,t) -> u^2 - (t^3 - 10*t^2 + t);
######################################################################
#@ quasirational_proj
quasirational_proj := (x) -> [x[3]/sqrt(2),x[2]^2 - x[1]^2 - 3*x[3]*x[4]/sqrt(2)];
#@ quasirational_lift
quasirational_lift := proc(s)
local t1,t2,t3,p1,p2,p3,p4;
t1 := s[1]^2;
t2 := 6*s[1]^2 - 2;
t3 := -2*s[2]^2-4;
p1 := 2+t1*t3;
p2 := s[2]*t2;
p3 := p1+p2;
p4 := p1-p2;
return([sqrt(p3)/2,sqrt(p4)/2,sqrt(2)*s[1],-s[1]*s[2]]);
end;
#@ is_quasirational
is_quasirational := proc(x)
type(x /~ [1,1,sqrt(2),1],[rational $ 4]);
end:
#@ inner_quasirational_projections
inner_quasirational_projections := [
[103/154, 65/449],
[103/554, 2945/3041],
[104/1073, 105/233],
[1/10, 13/19],
[1/10, 16/17],
[1/10, 245/267],
[11/118, 819/1331],
[11/1190, 1664/2057],
[1127/2194, 581/731],
[1135/2114, 1088/1137],
[1147/2390, 97/961],
[1147/2830, 640/1369],
[1151/3722, 11/139],
[1223/2330, 16/17],
[12/29, 247/297],
[125/262, 16/59],
[1255/2146, 1547/1675],
[1260/3599, 559/1009],
[127/450, 416/417],
[1301/2270, 16/33],
[13/30, 145/1521],
[13/30, 16/33],
[1389/3038, 176/1049],
[1424/3913, 1571/2179],
[148/215, 29/323],
[151/338, 279/1129],
[1549/3038, 2768/3307],
[1603/2350, 19/147],
[1611/3878, 355/643],
[1648/2875, 2295/3113],
[1672/3329, 1257/2057],
[169/322, 475/507],
[17/106, 1760/2601],
[172/511, 15/17],
[175/298, 2464/2825],
[175/362, 112/163],
[1792/3635, 2623/3649],
[1809/3050, 32/41],
[1829/2750, 97/961],
[1864/2843, 145/2993],
[191/3490, 1211/1243],
[1939/3350, 19/147],
[196/335, 2719/3553],
[1964/3085, 31/97],
[19/70, 16/33],
[2093/3534, 115/147],
[209/338, 819/1331],
[211/350, 80/107],
[23/154, 895/993],
[23/34, 481/2881],
[23/50, 32/41],
[2435/3854, 16/59],
[248/401, 95/449],
[248/665, 29/323],
[256/377, 35/387],
[25/82, 237/275],
[2636/3887, 445/4003],
[280/457, 1243/2107],
[28/45, 559/1617],
[307/830, 267/779],
[31/202, 355/1507],
[313/466, 560/2651],
[3/14, 5/27],
[31/50, 355/1507],
[316/487, 835/2243],
[32/49, 767/2433],
[341/1070, 97/961],
[359/610, 463/1969],
[364/687, 409/441],
[36/77, 2575/2673],
[367/986, 2176/3401],
[37/190, 688/1369],
[373/630, 16/33],
[37/70, 5/27],
[401/650, 16/1067],
[403/590, 97/961],
[404/685, 31/97],
[415/706, 341/459],
[427/694, 128/803],
[43/166, 224/251],
[432/1681, 1055/3553],
[43/94, 480/1849],
[4/47, 65/193],
[455/778, 973/1075],
[463/1970, 16/17],
[468/775, 385/673],
[47/106, 80/97],
[4/7, 15/17],
[48/235, 107/459],
[501/742, 5/27],
[52/205, 137/169],
[555/974, 163/675],
[560/3163, 951/1225],
[56/107, 605/931],
[569/1042, 2735/2993],
[57/130, 32/41],
[577/1546, 1680/1873],
[600/913, 7/25],
[61/718, 581/731],
[65/122, 32/507],
[65/122, 973/1075],
[65/274, 2777/2873],
[700/1303, 931/3075],
[704/1163, 1435/2299],
[7/106, 245/267],
[71/130, 13/19],
[7/194, 1855/3777],
[72/115, 217/729],
[73/274, 1253/1947],
[735/1594, 1024/2401],
[739/1318, 249/601],
[7/466, 656/931],
[75/134, 341/459],
[75/134, 656/675],
[76/143, 327/473],
[767/1834, 235/779],
[777/2050, 224/513],
[7/90, 19/147],
[80/187, 799/2049],
[8/25, 1007/1041],
[8/25, 31/97],
[827/2590, 1963/3531],
[83/126, 5/27],
[839/2170, 736/857],
[881/1538, 160/209],
[907/2046, 1075/1203],
[92/381, 1127/2073],
[95/202, 1264/1411],
[95/202, 301/499],
[965/2086, 1072/1075],
NULL
]:
#@ inner_quasirational_points
inner_quasirational_points :=
map(quasirational_lift,inner_quasirational_projections);
#@ F16_C0_quasirational_points
F16_C0_quasirational_points := select(u -> (is_in_F16_E0_measure(evalf(u)) = 0),map(q -> c_rational[0](1/(1-q/2)),farey(12))):
#@ F16_C1_quasirational_points
F16_C1_quasirational_points := select(u -> (is_in_F16_E0_measure(evalf(u)) = 0),map(q -> c_quasirational[1](q-1/2),farey(12))):
#@ F16_C3_quasirational_points
F16_C3_quasirational_points := select(u -> (is_in_F16_E0_measure(evalf(u)) = 0),map(c_quasirational[3],three_circle(99))):
#@ F16_C5_quasirational_points
F16_C5_quasirational_points := select(u -> (is_in_F16_E0_measure(evalf(u)) = 0),map(c_quasirational[5],farey(20))):
#@ quasirational_points
quasirational_points := [
op(inner_quasirational_points),
op(F16_C0_quasirational_points),
op(F16_C1_quasirational_points),
op(F16_C3_quasirational_points),
op(F16_C5_quasirational_points)
];
#@ inner_quasirational_points_latex
inner_quasirational_points_latex := proc()
local P,num_cols,S,T,L,i,j,s;
P := inner_quasirational_projections;
num_cols := 8;
S := cat("\\[ \\renewcommand{\\arraystretch}{2} \n \\begin{array}{","c" $ num_cols,"}\n");
j := 0;
L := "\\\\ \n";
for i from 1 to nops(P) do
s := P[i];
T := sprintf("\\left(\\frac{%4d}{%4d},\\frac{%4d}{%4d}\\right)",
numer(s[1]),denom(s[1]),numer(s[2]),denom(s[2]));
S := cat(S,T);
j := j+1;
if j = num_cols then
if i < nops(P) then
S := cat(S,L);
fi;
j := 0;
else
S := cat(S," &\n");
fi;
od;
S := cat(S,"\n\\end{array} \\]\n");
return(S);
end:
#@ inner_quasirational_points_tikz
inner_quasirational_points_tikz := proc()
local P,S,T,s,i;
P := inner_quasirational_projections;
S := "\\begin{center}\n \\begin{tikzpicture}[scale=8]\n";
S := cat(S," \\draw[cyan ] (0.000,0.000) -- (0.000,0.707);\n");
S := cat(S," \\draw[green ] (0.000,0.000) -- (1.000,0.000);\n");
S := cat(S," \\draw[magenta] (0.000,0.707) -- (0.816,0.707);\n");
T := " \\draw[blue,smooth] ";
for i from 0 to 11 do
T := cat(T, sprintf("(%1.3f,%1.3f) -- ",op(evalf(y_proj0(c_E0[5](i*Pi/12))))));
od;
T := cat(T, "(0.816,0.707);\n");
S := cat(S,T);
for i from 1 to nops(P) do
s := evalf(P[i] *~ [sqrt(2),1/sqrt(2)]);
S := cat(S,sprintf(" \\fill(%1.3f,%1.3f) circle(0.004);\n",s[1],s[2]));
od;
S := cat(S," \\end{tikzpicture}\n\\end{center}\n");
return(S);
end:
######################################################################
# The following table gives a 7 x 5 grid of arithmetically simple
# points that lie in F16 and are quite evenly spaced.
#@ rational_grid_points
rational_grid_points := [[
[(1/2)*sqrt(2), (1/2)*sqrt(2), 0, 0],
[23/34, 23/34, (7/34)*sqrt(2), 0],
[79/130, 79/130, (47/130)*sqrt(2), 0],
[1/2, 1/2, (1/2)*sqrt(2), 0],
[79/202, 79/202, (119/202)*sqrt(2), 0],
[7/34, 7/34, (23/34)*sqrt(2), 0],
[0, 0, 1, 0]
],[
[407/745, 624/745, 0, 0],
[92124/152207, 232883/304414, (31/202)*sqrt(2), -11005/304414],
[1287/2425, 344/485, (8/25)*sqrt(2), -248/2425],
[7267/15458, 8565/15458, (125/262)*sqrt(2), -1000/7729],
[92619/240218, 224276/600545, (359/610)*sqrt(2), -166217/1201090],
[143/486, 298/1701, (83/126)*sqrt(2), -415/3402],
[(1/60)*sqrt(195), 0, (1/4)*sqrt(15), -(1/60)*sqrt(30)]
],[
[5/13, 12/13, 0, 0], [15/38, 86/95, (1/10)*sqrt(2), -13/190],
[214099/533478, 217940/266739, (73/274)*sqrt(2), -91469/533478],
[37323/100798, 29390/50399, (95/202)*sqrt(2), -28595/100798],
[5389/14982, 27671/74910, (1301/2270)*sqrt(2), -10408/37455],
[42732/137557, 20435/137557, (280/457)*sqrt(2), -49720/137557],
[(3/70)*sqrt(55), 0, (2/7)*sqrt(10), -(9/70)*sqrt(5)]
],[
[9/41, 40/41, 0, 0], [4793/21846, 72098/76461, (23/154)*sqrt(2), -20585/152922],
[1121/4510, 1864/2255, (25/82)*sqrt(2), -237/902],
[22828/111879, 1572959/2461338, (907/2046)*sqrt(2), -975025/2461338],
[342221/1435238, 4932765/10046666, (1549/3038)*sqrt(2), -2143816/5023333],
[23/119, 4/17, (4/7)*sqrt(2), -60/119],
[(1/68)*sqrt(238), 0, (1/12)*sqrt(102), -(7/102)*sqrt(51)]
],[
[0, 1, 0, 0],
[0, 59/62, (11/62)*sqrt(2), -11/62],
[0, 11/13, (4/13)*sqrt(2), -4/13],
[0, 61/86, (35/86)*sqrt(2), -35/86],
[0, 1/2, (1/2)*sqrt(2), -1/2],
[0, 11/38, (21/38)*sqrt(2), -21/38],
[0, 0, (1/3)*sqrt(6), -(1/3)*sqrt(3)]
]];