This function is definitely a performance hotspot, so I unrolled and inlined just about everything.  It would be much simpler (but also much slower) if I used Ellipsoid methods.