@Test
public final void testProductQuaternionQuaternion() {
// Case : analytic test case
final Quaternion qA = new Quaternion(1, 0.5, -3, 4);
final Quaternion qB = new Quaternion(6, 2, 1, -9);
final Quaternion qResult = Quaternion.multiply(qA, qB);
Assert.assertEquals(44, qResult.getQ0(), EPS);
Assert.assertEquals(28, qResult.getQ1(), EPS);
Assert.assertEquals(-4.5, qResult.getQ2(), EPS);
Assert.assertEquals(21.5, qResult.getQ3(), EPS);
// comparison with the result given by the formula :
// qResult = (scalarA * scalarB - vectorA . vectorB) + (scalarA * vectorB + scalarB * vectorA + vectorA ^
// vectorB)
final Vector3D vectorA = new Vector3D(qA.getVectorPart());
final Vector3D vectorB = new Vector3D(qB.getVectorPart());
final Vector3D vectorResult = new Vector3D(qResult.getVectorPart());
final double scalarPartRef = qA.getScalarPart() * qB.getScalarPart() - Vector3D.dotProduct(vectorA, vectorB);
Assert.assertEquals(scalarPartRef, qResult.getScalarPart(), EPS);
final Vector3D vectorPartRef = ((vectorA.scalarMultiply(qB.getScalarPart())).add(vectorB.scalarMultiply(qA
.getScalarPart()))).add(Vector3D.crossProduct(vectorA, vectorB));
final double norm = (vectorResult.subtract(vectorPartRef)).getNorm();
Assert.assertEquals(0, norm, EPS);
// Conjugate of the product of two quaternions and product of their conjugates :
// Conj(qA * qB) = Conj(qB) * Conj(qA)
final Quaternion conjugateOfProduct = qB.getConjugate().multiply(qA.getConjugate());
final Quaternion productOfConjugate = (qA.multiply(qB)).getConjugate();
Assert.assertEquals(conjugateOfProduct.getQ0(), productOfConjugate.getQ0(), EPS);
Assert.assertEquals(conjugateOfProduct.getQ1(), productOfConjugate.getQ1(), EPS);
Assert.assertEquals(conjugateOfProduct.getQ2(), productOfConjugate.getQ2(), EPS);
Assert.assertEquals(conjugateOfProduct.getQ3(), productOfConjugate.getQ3(), EPS);
}