Homework

Define a quaternion type over a given number type T. Implement addition and multiplication, as well as scaling by a number.

Hint:

  • Use immutable instead of type when declaring the type
  • Import (at least) the operators + and * from Base; see the manual for details
  • To cheat, look for an existing Julia package providing quaterions

In [1]:
using Base.Test

In [2]:
# The definition of the Quaternion
import Base.+
import Base.*
import Base.-
import Base./
import Base.conj
import Base.inv
import Base.\
immutable Quaternion{T<:Number} <: Number
    r::T
    i::T
    j::T
    k::T
end

In [24]:
# Define multiplication
function *{T<:Number}(q1::Quaternion{T},q2::Quaternion{T})
    r = q1.r*q2.r - q1.i*q2.i - q1.j*q2.j - q1.k*q2.k
    i = q1.r*q2.i + q1.i*q2.r + q1.j*q2.k - q1.k*q2.j
    j = q1.r*q2.j + q1.j*q2.r - q1.i*q2.k + q1.k*q2.i
    k = q1.r*q2.k + q1.k*q2.r + q1.i*q2.j - q1.j*q2.i
    Quaternion{T}(r,i,j,k)
end
# The definition of scalar multiplication
*(s::Bool,q::Quaternion{Bool}) = Quaternion{Bool}(q.r*s,q.i*s,q.j*s,q.k*s) # Bools are special for some reason
*{T<:Number}(s::T,q::Quaternion{T}) = Quaternion{T}(q.r*s,q.i*s,q.j*s,q.k*s)
# Define Addition, subtraction, and additive inversion
+{T<:Number}(q1::Quaternion{T},q2::Quaternion{T}) = Quaternion{T}(q1.r+q2.r,q1.i+q2.i,q1.j+q2.j,q1.k+q2.k)
-{T<:Number}(q::Quaternion{T}) = Quaternion{T}(-q.r,-q.i,-q.j,-q.k)
-{T<:Number}(q1::Quaternion{T},q2::Quaternion{T})=q1+(-(q2))
# And a commutator
commutator{T<:Number}(q1::Quaternion{T},q2::Quaternion{T})=q1*q2-q2*q1
# Conjugate 
function conj{T<:Number}(q::Quaternion{T})
    Quaternion{T}(q.r,-q.i,-q.j,-q.k)
end
# Norm
norm{T<:Number}(q::Quaternion{T})=sqrt((conj(q)*q).r)
# Inverse
function inv{T}(q::Quaternion{T})
    n2 = norm(q)*norm(q)
    inv(n2)*conj(q)
end
# Scalar Division
/{T<:Number}(q::Quaternion{T},s::T) = inv(s)*q
# Division
function /{T<:Number}(q1::Quaternion{T},q2::Quaternion{T})
    q1*inv(q2)
end
function \{T<:Number}(q1::Quaternion{T},q2::Quaternion{T})
    inv(q1)*q1
end


Out[24]:
\ (generic function with 61 methods)

The tests


In [17]:
q1=Quaternion(1.,2.,3.,4.);
q2=Quaternion(1./2.,2./3.,3./4.,4./5.);

In [42]:
# Test norm
@test_approx_eq(norm(q1),sqrt(1.+4.+9.+16.))
# Test multiplication and addition
@test 2.q1 == q1+q1
# Test inverse
@test_approx_eq(norm(q1/q1),1.)
@test_approx_eq(norm(q1\q1),1.)