Vector3D implements Serializable, Vector<Euclidean3D> { public Vector3D crossProduct(final Vector<Euclidean3D> v) { final Vector3D v3 = (Vector3D) v; return new Vector3D(MathArrays.linearCombination(y, v3.z, -z, v3.y), MathArrays.linearCombination(z, v3.x, -x, v3.z), MathArrays.linearCombination(x, v3.y, -y, v3.x)); } Vector3D(double x, double y, double z);  Vector3D(double[] v);  Vector3D(double alpha, double delta);  Vector3D(double a, Vector3D u);  Vector3D(double a1, Vector3D u1, double a2, Vector3D u2);  Vector3D(double a1, Vector3D u1, double a2, Vector3D u2,
                    double a3, Vector3D u3);  Vector3D(double a1, Vector3D u1, double a2, Vector3D u2,
                    double a3, Vector3D u3, double a4, Vector3D u4); double getX(); double getY(); double getZ(); double[] toArray(); Space getSpace(); Vector3D getZero(); double getNorm1(); double getNorm(); double getNormSq(); double getNormInf(); double getAlpha(); double getDelta(); Vector3D add(final Vector<Euclidean3D> v); Vector3D add(double factor, final Vector<Euclidean3D> v); Vector3D subtract(final Vector<Euclidean3D> v); Vector3D subtract(final double factor, final Vector<Euclidean3D> v); Vector3D normalize(); Vector3D orthogonal(); static double angle(Vector3D v1, Vector3D v2); Vector3D negate(); Vector3D scalarMultiply(double a); boolean isNaN(); boolean isInfinite(); @Override boolean equals(Object other); @Override int hashCode(); double dotProduct(final Vector<Euclidean3D> v); Vector3D crossProduct(final Vector<Euclidean3D> v); double distance1(Vector<Euclidean3D> v); double distance(Vector<Euclidean3D> v); double distance(Point<Euclidean3D> v); double distanceInf(Vector<Euclidean3D> v); double distanceSq(Vector<Euclidean3D> v); static double dotProduct(Vector3D v1, Vector3D v2); static Vector3D crossProduct(final Vector3D v1, final Vector3D v2); static double distance1(Vector3D v1, Vector3D v2); static double distance(Vector3D v1, Vector3D v2); static double distanceInf(Vector3D v1, Vector3D v2); static double distanceSq(Vector3D v1, Vector3D v2); @Override String toString(); String toString(final NumberFormat format); static final Vector3D ZERO; static final Vector3D PLUS_I; static final Vector3D MINUS_I; static final Vector3D PLUS_J; static final Vector3D MINUS_J; static final Vector3D PLUS_K; static final Vector3D MINUS_K; static final Vector3D NaN; static final Vector3D POSITIVE_INFINITY; static final Vector3D NEGATIVE_INFINITY; }
@Test public void testCrossProductCancellation() { Vector3D v1 = new Vector3D(9070467121.0, 4535233560.0, 1); Vector3D v2 = new Vector3D(9070467123.0, 4535233561.0, 1); checkVector(Vector3D.crossProduct(v1, v2), -1, 2, 1); double scale = FastMath.scalb(1.0, 100); Vector3D big1 = new Vector3D(scale, v1); Vector3D small2 = new Vector3D(1 / scale, v2); checkVector(Vector3D.crossProduct(big1, small2), -1, 2, 1); }
@Test public void testCrossProduct() { Well1024a random = new Well1024a(885362227452043214l); for (int i = 0; i < 10000; ++i) { double ux = 10000 * random.nextDouble(); double uy = 10000 * random.nextDouble(); double uz = 10000 * random.nextDouble(); double vx = 10000 * random.nextDouble(); double vy = 10000 * random.nextDouble(); double vz = 10000 * random.nextDouble(); Vector3D cNaive = new Vector3D(uy * vz - uz * vy, uz * vx - ux * vz, ux * vy - uy * vx); Vector3D cAccurate = new Vector3D(ux, uy, uz).crossProduct(new Vector3D(vx, vy, vz)); Assert.assertEquals(0.0, cAccurate.distance(cNaive), 6.0e-15 * cAccurate.getNorm()); } }