Define a quaternion type over a given number type T. Implement addition and multiplication, as well as scaling by a number.
Hint:
immutable instead of type when declaring the type+ and * from Base; see the manual for details
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]:
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.)