public static Vector Cross(Normal v1, Vector v2)
 {
     if (v1.HasNaNs() || v2.HasNaNs()) throw new InvalidOperationException();
     double v1x = v1.x, v1y = v1.y, v1z = v1.z;
     double v2x = v2.x, v2y = v2.y, v2z = v2.z;
     return new Vector((v1y * v2z) - (v1z * v2y),
                   (v1z * v2x) - (v1x * v2z),
                   (v1x * v2y) - (v1y * v2x));
 }
 public static double Dot(Vector v, Normal n)
 {
     if (v.HasNaNs() || n.HasNaNs()) throw new InvalidOperationException();
     return v.x * n.x + v.y * n.y + v.z * n.z;
 }
 public static double Dot(Normal n, Vector v)
 {
     if (n.HasNaNs() || v.HasNaNs()) throw new InvalidOperationException();
     return n.x * v.x + n.y * v.y + n.z * v.z;
 }
 public static double AbsDot(Normal n1, Normal n2)
 {
     if (n1.HasNaNs() || n2.HasNaNs()) throw new InvalidOperationException();
     return Math.Abs(n1.x * n2.x + n1.y * n2.y + n1.z * n2.z);
 }