func CompareDistances(x, a, b Point) int {
	sign := triageCompareCosDistances(x, a, b)
	if sign != 0 {
		return sign
	}
	if a == b {
		return 0
	}
	cosAX := a.Dot(x.Vector)
	if cosAX > 1/math.Sqrt2 {
		sign = triageCompareSin2Distances(x, a, b)
	} else if cosAX < -1/math.Sqrt2 {
		sign = -triageCompareSin2Distances(x, a, b)
	}
	if sign != 0 {
		return sign
	}
	sign = exactCompareDistances(r3.PreciseVectorFromVector(x.Vector), r3.PreciseVectorFromVector(a.Vector), r3.PreciseVectorFromVector(b.Vector))
	if sign != 0 {
		return sign
	}
	return symbolicCompareDistances(x, a, b)
}
CompareDistances returns -1, 0, or +1 according to whether AX < BX, A == B,
or AX > BX respectively. Distances are measured with respect to the positions
of X, A, and B as though they were reprojected to lie exactly on the surface of
the unit sphere. Furthermore, this method uses symbolic perturbations to
ensure that the result is non-zero whenever A != B, even when AX == BX
exactly, or even when A and B project to the same point on the sphere.
Such results are guaranteed to be self-consistent, i.e. if AB < BC and
BC < AC, then AB < AC.
package s2
import (
	"math"
	"math/big"
	"github.com/golang/geo/r3"
	"github.com/golang/geo/s1"
)
const (
	epsilon = 1e-15
	dblEpsilon = 2.220446049250313e-16
	dblError = 1.110223024625156e-16
	maxDeterminantError = 1.8274 * dblEpsilon
	detErrorMultiplier = 3.2321 * dblEpsilon
)
type Direction int
const (
	Clockwise        Direction = -1
	Indeterminate    Direction = 0
	CounterClockwise Direction = 1
)
func newBigFloat() *big.Float { return new(big.Float).SetPrec(big.MaxPrec) }
func Sign(a, b, c Point) bool {
	return c.Cross(a.Vector).Dot(b.Vector) > 0
}
func RobustSign(a, b, c Point) Direction {
	sign := triageSign(a, b, c)
	if sign == Indeterminate {
		sign = expensiveSign(a, b, c)
	}
	return sign
}
func stableSign(a, b, c Point) Direction {
	ab := b.Sub(a.Vector)
	ab2 := ab.Norm2()
	bc := c.Sub(b.Vector)
	bc2 := bc.Norm2()
	ca := a.Sub(c.Vector)
	ca2 := ca.Norm2()
	var e1, e2, op r3.Vector
	if ab2 >= bc2 && ab2 >= ca2 {
		e1, e2, op = ca, bc, c.Vector
	} else if bc2 >= ca2 {
		e1, e2, op = ab, ca, a.Vector
	} else {
		e1, e2, op = bc, ab, b.Vector
	}
	det := -e1.Cross(e2).Dot(op)
	maxErr := detErrorMultiplier * math.Sqrt(e1.Norm2()*e2.Norm2())
	if det > maxErr {
		return CounterClockwise
	}
	if det < -maxErr {
		return Clockwise
	}
	return Indeterminate
}
func triageSign(a, b, c Point) Direction {
	det := a.Cross(b.Vector).Dot(c.Vector)
	if det > maxDeterminantError {
		return CounterClockwise
	}
	if det < -maxDeterminantError {
		return Clockwise
	}
	return Indeterminate
}
func expensiveSign(a, b, c Point) Direction {
	if a == b || b == c || c == a {
		return Indeterminate
	}
	detSign := stableSign(a, b, c)
	if detSign != Indeterminate {
		return detSign
	}
	return exactSign(a, b, c, true)
}
func exactSign(a, b, c Point, perturb bool) Direction {
	permSign := CounterClockwise
	pa := &a
	pb := &b
	pc := &c
	if pa.Cmp(pb.Vector) > 0 {
		pa, pb = pb, pa
		permSign = -permSign
	}
	if pb.Cmp(pc.Vector) > 0 {
		pb, pc = pc, pb
		permSign = -permSign
	}
	if pa.Cmp(pb.Vector) > 0 {
		pa, pb = pb, pa
		permSign = -permSign
	}
	xa := r3.PreciseVectorFromVector(pa.Vector)
	xb := r3.PreciseVectorFromVector(pb.Vector)
	xc := r3.PreciseVectorFromVector(pc.Vector)
	xbCrossXc := xb.Cross(xc)
	det := xa.Dot(xbCrossXc)
	detSign := Direction(det.Sign())
	if detSign == Indeterminate && perturb {
		detSign = symbolicallyPerturbedSign(xa, xb, xc, xbCrossXc)
	}
	return permSign * detSign
}
func symbolicallyPerturbedSign(a, b, c, bCrossC r3.PreciseVector) Direction {
	detSign := bCrossC.Z.Sign()  
	if detSign != 0 {
		return Direction(detSign)
	}
	detSign = bCrossC.Y.Sign()  
	if detSign != 0 {
		return Direction(detSign)
	}
	detSign = bCrossC.X.Sign()  
	if detSign != 0 {
		return Direction(detSign)
	}
	detSign = newBigFloat().Sub(newBigFloat().Mul(c.X, a.Y), newBigFloat().Mul(c.Y, a.X)).Sign()  
	if detSign != 0 {
		return Direction(detSign)
	}
	detSign = c.X.Sign()  
	if detSign != 0 {
		return Direction(detSign)
	}
	detSign = -(c.Y.Sign())  
	if detSign != 0 {
		return Direction(detSign)
	}
	detSign = newBigFloat().Sub(newBigFloat().Mul(c.Z, a.X), newBigFloat().Mul(c.X, a.Z)).Sign()  
	if detSign != 0 {
		return Direction(detSign)
	}
	detSign = c.Z.Sign()  
	if detSign != 0 {
		return Direction(detSign)
	}
	detSign = newBigFloat().Sub(newBigFloat().Mul(a.X, b.Y), newBigFloat().Mul(a.Y, b.X)).Sign()  
	if detSign != 0 {
		return Direction(detSign)
	}
	detSign = -(b.X.Sign())  
	if detSign != 0 {
		return Direction(detSign)
	}
	detSign = b.Y.Sign()  
	if detSign != 0 {
		return Direction(detSign)
	}
	detSign = a.X.Sign()  
	if detSign != 0 {
		return Direction(detSign)
	}
	return CounterClockwise  
}