Skip to content

Instantly share code, notes, and snippets.

@mxrguspxrt
Created November 9, 2012 09:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mxrguspxrt/4044808 to your computer and use it in GitHub Desktop.
Save mxrguspxrt/4044808 to your computer and use it in GitHub Desktop.
java2-home4.java
import java.util.*;
import java.util.regex.*;
/** Quaternions. Basic operations. */
public class Quaternion {
public double realPart;
public double i;
public double j;
public double k;
// TODO!!! Your fields here!
/** Constructor from four double values.
* @param a real part
* @param b imaginary part i
* @param c imaginary part j
* @param d imaginary part k
*/
public Quaternion (double a, double b, double c, double d) {
this.realPart = a;
this.i = b;
this.j = c;
this.k = d;
}
/** Real part of the quaternion.
* @return real part
*/
public double getRpart() {
return this.realPart;
}
/** Imaginary part i of the quaternion.
* @return imaginary part i
*/
public double getIpart() {
return this.i;
}
/** Imaginary part j of the quaternion.
* @return imaginary part j
*/
public double getJpart() {
return this.j;
}
/** Imaginary part k of the quaternion.
* @return imaginary part k
*/
public double getKpart() {
return this.k;
}
/** Conversion of the quaternion to the string.
* @return a string form of this quaternion:
* "a+bi+cj+dk"
* (without any brackets)
*/
@Override
public String toString() {
return this.realPart + "+" + this.i + "i+" + this.j + "j+" + this.k + "k";
}
/** Conversion from the string to the quaternion.
* Reverse to <code>toString</code> method.
* @throws IllegalArgumentException if string s does not represent
* a quaternion (defined by the <code>toString</code> method)
* @param s string of form produced by the <code>toString</code> method
* @return a quaternion represented by string s
*/
public static Quaternion valueOf (String s) {
Pattern p = Pattern.compile("(\\d+\\.\\d+)+(\\d+\\.\\d+)i+(\\d+\\.\\d+)j+(\\d+\\.\\d+)k");
Matcher m = p.matcher(s);
try {
m.find();
} catch(Exception e) {}
if(m.groupCount()!=4) throw new IllegalArgumentException();
String realNumberAndRest[] = s.split("\\+", 2);
double realNumber = Double.valueOf(realNumberAndRest[0]);
String iAndRest[] = realNumberAndRest[1].split("i\\+", 2);
double i = Double.valueOf(iAndRest[0]);
String jAndRest[] = iAndRest[1].split("j\\+", 2);
double j = Double.valueOf(jAndRest[0]);
String kAndRest[] = jAndRest[1].split("k", 2);
double k = Double.valueOf(kAndRest[0]);
return new Quaternion(realNumber, i, j, k);
}
/** Clone of the quaternion.
* @return independent clone of <code>this</code>
*/
@Override
public Object clone() throws CloneNotSupportedException {
return new Quaternion(realPart, i, j, k);
}
/** Test whether the quaternion is zero.
* @return true, if the real part and all the imaginary parts are (close to) zero
*/
public boolean isZero() {
boolean is = doubleCompare(0, this.realPart) && doubleCompare(0, this.i) && doubleCompare(0, j) && doubleCompare(0, this.k);
return is;
}
/** Conjugate of the quaternion. Expressed by the formula
* conjugate(a+bi+cj+dk) = a-bi-cj-dk
* @return conjugate of <code>this</code>
*/
public Quaternion conjugate() {
return new Quaternion(this.realPart, -this.i, -this.j, -this.k);
}
/** Opposite of the quaternion. Expressed by the formula
* opposite(a+bi+cj+dk) = -a-bi-cj-dk
* @return quaternion <code>-this</code>
*/
public Quaternion opposite() {
return new Quaternion(-this.realPart, -this.i, -this.j, -this.k);
}
/** Sum of quaternions. Expressed by the formula
* (a1+b1i+c1j+d1k) + (a2+b2i+c2j+d2k) = (a1+a2) + (b1+b2)i + (c1+c2)j + (d1+d2)k
* @param q addend
* @return quaternion <code>this+q</code>
*/
public Quaternion plus (Quaternion q) {
return new Quaternion(this.realPart+q.realPart, this.i+q.i, this.j+q.j, this.k+q.k);
}
/** Product of quaternions. Expressed by the formula
* (a1+b1i+c1j+d1k) * (a2+b2i+c2j+d2k) = (a1a2-b1b2-c1c2-d1d2) + (a1b2+b1a2+c1d2-d1c2)i +
* (a1c2-b1d2+c1a2+d1b2)j + (a1d2+b1c2-c1b2+d1a2)k
* @param q factor
* @return quaternion <code>this*q</code>
*/
public Quaternion times(Quaternion q) {
double a1 = this.realPart;
double b1 = this.i;
double c1 = this.j;
double d1 = this.k;
double a2 = q.realPart;
double b2 = q.i;
double c2 = q.j;
double d2 = q.k;
double realPart = a1*a2-b1*b2-c1*c2-d1*d2;
double i = a1*b2+b1*a2+c1*d2-d1*c2;
double j = a1*c2-b1*d2+c1*a2+d1*b2;
double k = a1*d2+b1*c2-c1*b2+d1*a2;
return new Quaternion(realPart, i, j, k);
}
/** Multiplication by a coefficient.
* @param r coefficient
* @return quaternion <code>this*r</code>
*/
public Quaternion times (double r) {
return new Quaternion(this.realPart*r, this.i*r, this.j*r, this.k*r);
}
/** Inverse of the quaternion. Expressed by the formula
* 1/(a+bi+cj+dk) = a/(a*a+b*b+c*c+d*d) +
* ((-b)/(a*a+b*b+c*c+d*d))i + ((-c)/(a*a+b*b+c*c+d*d))j + ((-d)/(a*a+b*b+c*c+d*d))k
* @return quaternion <code>1/this</code>
* 1 / new Quaternion(a, bi, cj, dk);
*/
public Quaternion inverse() {
double x = this.realPart*this.realPart + this.i*this.i + this.j*this.j + this.k*this.k;
return new Quaternion(this.realPart/x, (-this.i)/x, (-this.j)/x, (-this.k)/x);
}
/** Difference of quaternions. Expressed as addition to the opposite.
* @param q subtrahend
* @return quaternion <code>this-q</code>
*/
public Quaternion minus(Quaternion q) {
return this.plus(q.opposite());
}
/** Right quotient of quaternions. Expressed as multiplication to the inverse.
* @param q (right) divisor
* @return quaternion <code>this*inverse(q)</code>
*/
public Quaternion divideByRight (Quaternion q) {
return this.times(q.inverse());
}
/** Left quotient of quaternions.
* @param q (left) divisor
* @return quaternion <code>inverse(q)*this</code>
*/
public Quaternion divideByLeft (Quaternion q) {
return q.inverse().times(this);
}
public static boolean doubleCompare(double a, double b){
if(Math.abs(a-b)<0.0001) return true;
return false;
}
/** Equality test of quaternions. Difference of equal numbers
* is (close to) zero.
* @param qo second quaternion
* @return logical value of the expression <code>this.equals(qo)</code>
*/
public boolean equals (Object q) {
if(q instanceof Quaternion) {
if(doubleCompare(this.realPart, ((Quaternion) q).getRpart()) && doubleCompare(this.i, ((Quaternion) q).getIpart()) && doubleCompare(this.j, ((Quaternion) q).getJpart()) && doubleCompare(this.k, ((Quaternion) q).getKpart()))
return true;
}
return false;
}
/** Dot product of quaternions. (p*conjugate(q) + q*conjugate(p))/2
* @param q factor
* @return dot product of this and q
*/
public Quaternion dotMult (Quaternion q) {
Quaternion x = this.times(q.conjugate());
return x.plus(x).times(0.5);
}
/** Integer hashCode has to be the same for equal objects.
* @return hashcode
*/
@Override
public int hashCode() {
return new Double(this.realPart).hashCode() + new Double(this.i).hashCode() + new Double(this.j).hashCode() + new Double(this.k).hashCode();
}
/** Norm of the quaternion. Expressed by the formula
* norm(a+bi+cj+dk) = Math.sqrt(a*a+b*b+c*c+d*d)
* @return norm of <code>this</code> (norm is a real number)
*/
public double norm() {
return Math.sqrt(this.realPart*this.realPart+this.i*this.i+this.j*this.j+this.k*this.k);
}
/** Main method for testing purposes.
* @param arg command line parameters
*/
public static void main (String[] arg) {
Quaternion arv1 = new Quaternion (-1., 1, 2., -2.);
if (arg.length > 0)
arv1 = valueOf (arg[0]);
System.out.println ("first: " + arv1.toString());
System.out.println ("real: " + arv1.getRpart());
System.out.println ("imagi: " + arv1.getIpart());
System.out.println ("imagj: " + arv1.getJpart());
System.out.println ("imagk: " + arv1.getKpart());
System.out.println ("isZero: " + arv1.isZero());
System.out.println ("conjugate: " + arv1.conjugate());
System.out.println ("opposite: " + arv1.opposite());
System.out.println ("hashCode: " + arv1.hashCode());
Quaternion res = null;
try {
res = (Quaternion)arv1.clone();
} catch (CloneNotSupportedException e) {};
System.out.println ("clone equals to original: " + res.equals (arv1));
System.out.println ("clone is not the same object: " + (res!=arv1));
System.out.println ("hashCode: " + res.hashCode());
res = valueOf (arv1.toString());
System.out.println ("string conversion equals to original: "
+ res.equals (arv1));
Quaternion arv2 = new Quaternion (1., -2., -1., 2.);
if (arg.length > 1)
arv2 = valueOf (arg[1]);
System.out.println ("second: " + arv2.toString());
System.out.println ("hashCode: " + arv2.hashCode());
System.out.println ("equals: " + arv1.equals (arv2));
res = arv1.plus (arv2);
System.out.println ("plus: " + res);
System.out.println ("times: " + arv1.times (arv2));
System.out.println ("minus: " + arv1.minus (arv2));
double mm = arv1.norm();
System.out.println ("norm: " + mm);
System.out.println ("inverse: " + arv1.inverse());
System.out.println ("divideByRight: " + arv1.divideByRight (arv2));
System.out.println ("divideByLeft: " + arv1.divideByLeft (arv2));
System.out.println ("dotMult: " + arv1.dotMult (arv2));
Quaternion fag1 = new Quaternion(1.12, 2, 3, 4);
Quaternion fag2 = new Quaternion(1.12, 2, 3, 4);
System.out.println("OMF" + fag1.equals(fag2));
Quaternion fag3 = new Quaternion(1.12, 2, 3, 4);
Quaternion fag4 = new Quaternion(1.12, 2.1, 3, 4);
System.out.println("OMF" + fag3.equals(fag4));
boolean wtf = Quaternion.valueOf("2.0+3.0i+6.0j+24.0k").equals(Quaternion.valueOf("2.0000000000000004+3.0i+6.0j+24.0k"));
System.out.println("WTTTF" + wtf);
}
}
// end of file
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment