Skip to content

Instantly share code, notes, and snippets.

@propensive
Created August 1, 2012 02:01
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save propensive/3222735 to your computer and use it in GitHub Desktop.
Save propensive/3222735 to your computer and use it in GitHub Desktop.
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