Quaternions in Scala
| object Algebra { | |
| // Build up increasingly complex algebras | |
| trait Magma[T] { | |
| def add(x : T, y : T) : T | |
| } | |
| trait Monoid[T] extends Magma[T] { | |
| def zero : T | |
| } | |
| trait Group[T] extends Monoid[T] { | |
| def negation(x : T) : T | |
| } | |
| trait Ring[T] extends Group[T] { | |
| def one : T | |
| def multiply(x : T, y : T) : T | |
| } | |
| trait Field[T] extends Ring[T] { | |
| def divide(x : T, y : T) : T | |
| def inverse(x : T) : T = divide(one, x) | |
| // This is required later... | |
| def conjugate(x : T) : T = x | |
| } | |
| // Specify how doubles form a field | |
| implicit object DoubleField extends Field[Double] { | |
| def add(x : Double, y : Double) = x+y | |
| def negation(x : Double) = -x | |
| def zero = 0 | |
| def one = 1 | |
| def multiply(x : Double, y : Double) = x*y | |
| def divide(x : Double, y : Double) = x/y | |
| } | |
| // Define complex numbers over a type T (e.g. Double) | |
| object Complex { | |
| def apply[T : Field](re : T, im : T) = new Complex[T](re, im) | |
| def unapply[T : Field](re : T, im : T) = Some((re, im)) | |
| } | |
| class Complex[T](val re : T, val im : T)(implicit base : Field[T]) { | |
| import base._ | |
| def +(that : Complex[T]) : Complex[T] = | |
| Complex[T](add(re, that.re), add(im, that.im)) | |
| def -(that : Complex[T]) : Complex[T] = | |
| Complex[T](add(re, negation(that.re)), add(im, negation(that.im))) | |
| // Note this definition of multiplication isn't the most obvious one | |
| def *(that : Complex[T]) : Complex[T] = | |
| Complex[T](add(multiply(re, that.re), negation(multiply(im, base.conjugate(that.im)))), | |
| add(multiply(that.im, re), multiply(im, base.conjugate(that.re)))) | |
| def /(that : Complex[T]) : Complex[T] = | |
| Complex[T](divide(add(multiply(re, that.re), multiply(im, that.im)), add(multiply(that.re, that.re), multiply(that.im, that.im))), divide(add(multiply(im, that.re), negation(multiply(that.im, re))), add(multiply(that.re, that.re), multiply(that.im, that.im)))) | |
| def negate : Complex[T] = Complex[T](negation(re), negation(im)) | |
| // Note the "real" part | |
| def conjugate : Complex[T] = Complex[T](base.conjugate(re), negation(im)) | |
| override def toString = "("+re.toString+" + "+im.toString+"i)" | |
| } | |
| // Specify how complex numbers over any type T form a field | |
| implicit def complexIsField[T](implicit base : Field[T]) = new Field[Complex[T]] { | |
| def add(x : Complex[T], y : Complex[T]) = x + y | |
| def zero : Complex[T] = Complex[T](base.zero, base.zero) | |
| def negation(x : Complex[T]) = x.negate | |
| def one : Complex[T] = Complex[T](base.one, base.zero) | |
| def multiply(x : Complex[T], y : Complex[T]) = x*y | |
| def divide(x : Complex[T], y : Complex[T]) = x/y | |
| override def conjugate(x : Complex[T]) = x.conjugate | |
| } | |
| // The magic bit | |
| case class Quaternion[T : Field](x : T, i : T, j : T, k : T) | |
| extends Complex[Complex[T]](Complex[T](x, i), Complex[T](j, k)) | |
| implicit def doubleToQuaternion(d : Double) = Quaternion(d, 0.0, 0.0, 0.0) | |
| val h = Quaternion(1.0, 0.0, 0.0, 0.0) // == 1.0 | |
| val i = Quaternion(0.0, 1.0, 0.0, 0.0) | |
| val j = Quaternion(0.0, 0.0, 1.0, 0.0) | |
| val k = Quaternion(0.0, 0.0, 0.0, 1.0) | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment