
(*This file contains some basic algebraic
routines which are used in the other files.
After each routine (or group of routines)
we give another routine which checks that
the original routines work.  These checking
routines are quite simple and we do not also
give more routines checking that they work!*)

(* compute the fixed points of a mobius transformation T, order
them with the smaller norm appearing first *)

FixedPoints[T_]:=(e=Eigenvectors[T];
f1=e[[1,1]]/e[[1,2]];
f2=e[[2,1]]/e[[2,2]];
test=Abs[f1]-Abs[f2];
g1=If[test<0,f1,f2];
g2=If[test<0,f2,f1];
{g1,g2})

(*The mobius action of a matrix on a complex number *)
Mob[T_,z_]:=(T[[1,1]] z + T[[1,2]])/(T[[2,1]] z + T[[2,2]]);
(*The mobius action on a segment *)
Mobs[T_,s_]:={Mob[T,s[[1]]],Mob[T,s[[2]]]}


FixedPointsCheck[]:=(
T={{Random[],Random[]},{Random[],Random[]}};
f=FixedPoints[T];
test1=Mob[T,f[[1]]]-f[[1]];
test2=Mob[T,f[[2]]]-f[[2]];
test3=Mobs[T,f]-f;
Chop[{test1,test2,test3}])

(*cross ratio*)
cr[a_,b_,c_,d_]:=(c-a)(d-b)/(d-c)/(b-a)
(* we can see this works by inspecting the well-known formula*)


(*compute planar intersection of two line segments.
We found the complicated formula for ss by
solving the problem symbolically.*)

PlaneIntersect[{z1_,z2_},{w1_,w2_}]:=(
u1=Re[z1];
u2=Re[w1];
u3=Re[z2];
u4=Re[w2];
v1=Im[z1];
v2=Im[w1];
v3=Im[z2];
v4=Im[w2];
ns= u3 v2 - u4 v2 - u2 v3 + u4 v3 + u2 v4 - u3 v4;
ds=u2 v1 - u4 v1 - u1 v2 + u3 v2 - u2 v3 + u4 v3 + u1 v4 - u3 v4;
ss=ns/ds;
ss z1 + (1-ss) z2)


PlaneIntersectCheck[]:=(
z1=3+Random[]+Random[] I;
z2=-3+Random[]+Random[] I;
w1=3 I +Random[]+Random[] I;
w2=-3 I +Random[]+Random[] I;
x=PlaneIntersect[{z1,z2},{w1,w2}];
Show[Graphics[{
sg[{z1,z2}],
sg[{w1,w2}],
PointSize[.02],
pt[x]}]]
)


(* suppose a and b are the projections to the plane
of two points in H^3.  Suppose also that the endpoints
of the geodesic connecting a to b are -1 and 1.
this routine finds the projection to the plane of the
midpoint of the geodesic segment connecting a to b. *)

SpecialInterpolate[a_,b_]:=(
d1=(1+b) Sqrt[1-a a];
d2=(1-a) Sqrt[1-b b];
(d1-d2)/(d1+d2))

(* The hyperbolic distance between a and x
can be computed in terms of a cross ratio.
Likewise the hyperbolic distance between
b and x be computed in terms of a cross
ratio.  The checker takes these two cross
ratios and verifies that they are the same.*)

SpecialInterpolateCheck[]:=(
a=-.5+Random[]/10;
b=.5+Random[]/10;
x=SpecialInterpolate[a,b];
aa=a+Sqrt[1-a a] I;
bb=b+Sqrt[1-b b] I;
xx=x+Sqrt[1-x x] I;
test1=cr[-1,aa,xx,1];
test2=cr[-1,xx,bb,1];
test1-test2)


(*complex affine map taking (x,y) to (-1,1)*)
Aff1[x_,y_,a_]:=2 a/(y-x)-(x+y)/(y-x)
Aff1Check[]:=Simplify[{Aff[x,y,x],Aff[x,y,y]}]

(*complex affine map taking (1,-1) to (x,y))*)
Aff2[x_,y_,a_]:=(y-x) a/2 + (x+y)/2
Aff2Check[]:=Simplify[{Aff2[x,y,-1],Aff2[x,y,1]}]


HyperbolicInterpolate[x_,X_,Y_,y_]:= (
a=Aff1[x,y,X];
b=Aff1[x,y,Y];
cen=SpecialInterpolate[a,b];
Aff2[x,y,cen])

(* Given the straightforward way that this
last routine extends the SimpleInterpolate routine,
our check is somewhat circular.  Mainly we just want
to see that we didn't make any typos in the definition. *)

HyperbolicInterpolateCheck[]:=(
a1=Random[]+Random[] I;
a2=Random[]+Random[] I;
c1=-.5 + Random[]/10;
c2=.5+Random[]/10;
x=Aff2[a1,a2,-1];
X=Aff2[a1,a2,c1];
Y=Aff2[a1,a2,c2];
y=Aff2[a1,a2,1];
zz=HyperbolicInterpolate[x,X,Y,y];
z=SimpleInterpolate[c1,c2];
Aff2[a1,a2,z]-zz)





(* compute intersection in hyperbolic space of two
geodesics.  The geodesics are given in terms of
their endpoints.  The geodesics have to intersect,
meaning that the endpoints are co-circular *)


SpaceIntersect[{z1_,z2_},{w1_,w2_}]:=(
x1=PlaneIntersect[{z1,z2},{w1,w2}];
diam=Abs[z1-z2];
rad=diam/2;
center=z1/2+z2/2;
dist=Abs[x1-center];
t1=Sqrt[rad rad- dist dist];
{x1,t1})






(*Given two points X,Y in hyperbolic space, let Z be the
midpoint of the geodesic segment joining X and Y.
This routine finds the projection of Z into
the plane.  The idea:  Let x and y be the two
endpoints of the geodesic.  Then the Euclidean straight
line xY intersects the Euclidean straight line
yX in a point which lies on the same vertical line
as Z.  Thus we project this intersection
point into the plane *)

(*

PlaneHyperbolicInterpolate[x_,X_,Y_,y_]:=(
u1=Re[x];
u2=Re[X[[1]]];
u3=Re[Y[[1]]];
u4=Re[y];
v1=0;
v2=X[[2]];
v3=Y[[2]];
v4=0;
ns= u3 v2 - u4 v2 - u2 v3 + u4 v3 + u2 v4 - u3 v4;
ds=u2 v1 - u4 v1 - u1 v2 + u3 v2 - u2 v3 + u4 v3 + u1 v4 - u3 v4;
ss=ns/ds;
ss x + (1-ss) Y[[1]])

*)

SpaceHyperbolicInterpolate[x_,X_,Y_,y_]:=(
x1=PlaneHyperbolicInterpolate[x,X,Y,y];
diam=Abs[x-y];
rad=diam/2;
center=x/2+y/2;
dist=Abs[x1-center];
t1=Sqrt[rad rad- dist dist];
{x1,t1})


