Quaternions   are an extension of the idea of   complex numbers.

A complex number has a real and complex part,   sometimes written as     a + bi,  

where     a     and     b     stand for real numbers, and     i     stands for the square root of minus 1.

An example of a complex number might be     -3 + 2i,    

where the real part,     a     is     -3.0     and the complex part,     b     is     +2.0.  

A quaternion has one real part and three imaginary parts,     i,       j,     and     k.  

A quaternion might be written as     a + bi + cj + dk.  

In the quaternion numbering system:

     i∙i = j∙j = k∙k = i∙j∙k = -1,         or more simply,
     ii  = jj  = kk  = ijk   = -1.  
The order of multiplication is important, as, in general, for two quaternions:

     q1     and     q2:         q1q2 ≠ q2q1.  
An example of a quaternion might be     1 +2i +3j +4k  

There is a list form of notation where just the numbers are shown and the imaginary multipliers    i,       j,     and     k     are assumed by position.

So the example above would be written as     (1, 2, 3, 4)  



Task

Given the three quaternions and their components: 

   q  = (1, 2, 3, 4) = (a,  b,  c,  d)
   q1 = (2, 3, 4, 5) = (a1, b1, c1, d1)
   q2 = (3, 4, 5, 6) = (a2, b2, c2, d2) 

And a wholly real number     r = 7.  



Create functions   (or classes)   to perform simple maths with quaternions including computing:

 The norm of a quaternion: 




=



a

2


+

b

2


+

c

2


+

d

2






{\displaystyle ={\sqrt {a^{2}+b^{2}+c^{2}+d^{2}}}}

 
 The negative of a quaternion: 
   = (-a, -b, -c, -d)  
 The conjugate of a quaternion: 
   = ( a, -b, -c, -d)  
 Addition of a real number     r     and a quaternion     q:  
  r + q = q + r = (a+r, b, c, d)  
 Addition of two quaternions: 
   q1 + q2 = (a1+a2, b1+b2, c1+c2, d1+d2)  
 Multiplication of a real number and a quaternion: 
   qr = rq = (ar, br, cr, dr)  
 Multiplication of two quaternions     q1     and   q2     is given by: 
   ( a1a2 − b1b2 − c1c2 − d1d2, 
   a1b2 + b1a2 + c1d2 − d1c2, 
   a1c2 − b1d2 + c1a2 + d1b2, 
   a1d2 + b1c2 − c1b2 + d1a2 )  
 Show that, for the two quaternions     q1     and     q2: 
 q1q2 ≠ q2q1  


If a language has built-in support for quaternions, then use it.



C.f.

   Vector products
   On Quaternions;   or on a new System of Imaginaries in Algebra.   By Sir William Rowan Hamilton LL.D, P.R.I.A., F.R.A.S., Hon. M. R. Soc. Ed. and Dub., Hon. or Corr. M. of the Royal or Imperial Academies of St. Petersburgh, Berlin, Turin and Paris, Member of the American Academy of Arts and Sciences, and of other Scientific Societies at Home and Abroad, Andrews' Prof. of Astronomy in the University of Dublin, and Royal Astronomer of Ireland.


module Q_mod
  implicit none
 
  type quaternion
    real :: a, b, c, d
  end type
 
  public :: norm, neg, conj
  public :: operator (+)
  public :: operator (*)
 
  private ::  q_plus_q, q_plus_r, r_plus_q, &
              q_mult_q, q_mult_r, r_mult_q, &
              norm_q, neg_q, conj_q
 
  interface norm
    module procedure norm_q
  end interface
 
  interface neg
    module procedure neg_q
  end interface
 
  interface conj
    module procedure conj_q
  end interface
 
  interface operator (+)
    module procedure q_plus_q, q_plus_r, r_plus_q
  end interface
 
  interface operator (*)
    module procedure q_mult_q, q_mult_r, r_mult_q
  end interface
 
contains
 
function norm_q(x) result(res)
  real :: res
  type (quaternion), intent (in) :: x
 
  res = sqrt(x%a*x%a + x%b*x%b + x%c*x%c + x%d*x%d)
 
end function norm_q
 
function neg_q(x) result(res)
  type (quaternion) :: res
  type (quaternion), intent (in) :: x
 
  res%a = -x%a
  res%b = -x%b
  res%c = -x%c
  res%d = -x%d
 
end function neg_q
 
function conj_q(x) result(res)
  type (quaternion) :: res
  type (quaternion), intent (in) :: x
 
  res%a = x%a
  res%b = -x%b
  res%c = -x%c
  res%d = -x%d
 
end function conj_q
 
function q_plus_q(x, y) result (res)
  type (quaternion) :: res
  type (quaternion), intent (in) :: x, y
 
  res%a = x%a + y%a
  res%b = x%b + y%b
  res%c = x%c + y%c
  res%d = x%d + y%d
 
end function q_plus_q
 
function q_plus_r(x, r) result (res)
  type (quaternion) :: res 
  type (quaternion), intent (in) :: x
  real, intent(in) :: r
 
   res = x
   res%a = x%a + r
 
end function q_plus_r
 
function r_plus_q(r, x) result (res)
  type (quaternion) :: res 
  type (quaternion), intent (in) :: x
  real, intent(in) :: r
 
   res = x
   res%a = x%a + r
 
end function r_plus_q
 
function q_mult_q(x, y) result (res)
  type (quaternion) :: res 
  type (quaternion), intent (in) :: x, y
 
   res%a = x%a*y%a - x%b*y%b - x%c*y%c - x%d*y%d
   res%b = x%a*y%b + x%b*y%a + x%c*y%d - x%d*y%c
   res%c = x%a*y%c - x%b*y%d + x%c*y%a + x%d*y%b
   res%d = x%a*y%d + x%b*y%c - x%c*y%b + x%d*y%a
 
end function q_mult_q
 
function q_mult_r(x, r) result (res)
  type (quaternion) :: res 
  type (quaternion), intent (in) :: x
  real, intent(in) ::  r
 
   res%a = x%a*r
   res%b = x%b*r
   res%c = x%c*r  
   res%d = x%d*r 
 
end function q_mult_r
 
function r_mult_q(r, x) result (res)
  type (quaternion) :: res 
  type (quaternion), intent (in) :: x
  real, intent(in) ::  r
 
   res%a = x%a*r
   res%b = x%b*r
   res%c = x%c*r  
   res%d = x%d*r 
 
end function r_mult_q
end module Q_mod
 
program Quaternions
  use Q_mod
  implicit none
 
  real :: r = 7.0
  type(quaternion) :: q, q1, q2
 
  q  = quaternion(1, 2, 3, 4)
  q1 = quaternion(2, 3, 4, 5)
  q2 = quaternion(3, 4, 5, 6)
 
  write(*, "(a, 4f8.3)") "             q = ", q
  write(*, "(a, 4f8.3)") "            q1 = ", q1
  write(*, "(a, 4f8.3)") "            q2 = ", q2
  write(*, "(a, f8.3)")  "             r = ", r
  write(*, "(a, f8.3)")  "     Norm of q = ", norm(q) 
  write(*, "(a, 4f8.3)") " Negative of q = ", neg(q)
  write(*, "(a, 4f8.3)") "Conjugate of q = ", conj(q) 
  write(*, "(a, 4f8.3)") "         q + r = ", q + r
  write(*, "(a, 4f8.3)") "         r + q = ", r + q
  write(*, "(a, 4f8.3)") "       q1 + q2 = ", q1 + q2
  write(*, "(a, 4f8.3)") "         q * r = ", q * r  
  write(*, "(a, 4f8.3)") "         r * q = ", r * q 
  write(*, "(a, 4f8.3)") "       q1 * q2 = ", q1 * q2 
  write(*, "(a, 4f8.3)") "       q2 * q1 = ", q2 * q1 
 
end program