reb
Class QH

Object
  extended by reb:QH

class 
Object:QH

Functions for Quaternion and Hypercomplex operations.

For quaternions, multiplication is not commutative and division is always defined.

For hypercomplex, multiplication is commutative and division is not always defined. The inverses which are not defined lieon two orthogonal 4D hyperplanes.

The hypercomplex code is based upon the complex number methods of Clyde Davenport using his complex/complex model.

Davenport's Website

H1 = [a1,a2]

where a1 and a2 are both complex numbers. This is the method used in Fractint. a1 and a2 are converted to two new complex numbers:

fa1 = a1 - conj(flip(a2))
fa2 = a1 + conj(flip(a2))

These new complex numbers (and correspondingly fb1 and fb2) can be used for ordinary complex math, including multiplication, division, trancendental functions, powers, etc. For example, sqrt:

fa1 = sqrt(fa1)
fa2 = sqrt(fa2)

A second conversion is done at the end of the operation(s):

c1 = 0.5*(fa1+fa2)
c2 = 0.5*(conj(flip(fa1)) - conj(flip(fa2)))

H2 = [c1, c2]


Ultra Fractal Source

Toggle UF Source Code Display

 Class QH {
   import "common.ulb"
 ; Functions for Quaternion and Hypercomplex operations. <br>
 ; <p>
 ; For quaternions, multiplication is not commutative and division is always
 ; defined.
 ; <p>
 ; For hypercomplex, multiplication is commutative and division is not always
 ; defined. The inverses which are not defined lieon two orthogonal
 ; 4D hyperplanes.
 ; <p>
 ; The hypercomplex code is based upon the complex number methods of Clyde
 ; Davenport using his complex/complex model.
 ; <p>
 ;   <a href="http://home.comcast.net/~cmdaven/bhyprcpx.htm">Davenport's Website</a><br>
 ; <p>
 ;   H1 = [a1,a2] <br>
 ; <p>
 ; where a1 and a2 are both complex numbers.  This is the method used in Fractint.
 ; a1 and a2 are converted to two new complex numbers:
 ; <p>
 ;   fa1 = a1 - conj(flip(a2)) <br>
 ;   fa2 = a1 + conj(flip(a2)) <br>
 ; <p>
 ; These new complex numbers (and correspondingly fb1 and fb2) can be used for
 ; ordinary complex math, including multiplication, division, trancendental
 ; functions, powers, etc. For example, sqrt:
 ; <p>
 ;   fa1 = sqrt(fa1) <br>
 ;   fa2 = sqrt(fa2) <br>
 ; <p>
 ; A second conversion is done at the end of the operation(s):
 ;  <p>
 ;   c1 = 0.5*(fa1+fa2)<br>
 ;   c2 = 0.5*(conj(flip(fa1)) - conj(flip(fa2)))<br>
 ;  <p>
 ;   H2 = [c1, c2] <br>
 ; public:
 
 ; Quaternian multiplication
   static func Qmul(Vector a, Vector b, Vector c)
     ; Q1*Q2 = [r1*r2 - V1.V2, r2*V1 + r1*V2 + V1xV2]
     ; calc V . V
     float dot = a.m_y*b.m_y + a.m_z*b.m_z + a.m_w*b.m_w
     ; calc V x V
     c.m_y = a.m_z*b.m_w - b.m_z*a.m_w
     c.m_z = -(a.m_y*b.m_w - b.m_y*a.m_w)
     c.m_w = a.m_y*b.m_z - b.m_y*a.m_z
 
     c.m_x = a.m_x*b.m_x-dot
     c.m_y = c.m_y + a.m_x*b.m_y + b.m_x*a.m_y
     c.m_z = c.m_z + a.m_x*b.m_z + b.m_x*a.m_z
     c.m_w = c.m_w + a.m_x*b.m_w + b.m_x*a.m_w
   endfunc
 
 ; Quaternian division calculated as Q2*(1/Q1)
   static func Qdiv(Vector a, Vector b, Vector c)
     ; 1/Q = [r, -V]/(r*r + V.V)
     ; then calculate Q2*(1/Q1) as for QMul
     float denom = 1/(b.m_x*b.m_x + b.m_y*b.m_y + b.m_z*b.m_z + b.m_w*b.m_w)
     ; calc V . V
     float dot = -(a.m_y*b.m_y + a.m_z*b.m_z + a.m_w*b.m_w)
     ; calc V x V
     c.m_y = -a.m_z*b.m_w + b.m_z*a.m_w
     c.m_z = a.m_y*b.m_w - b.m_y*a.m_w
     c.m_w = -a.m_y*b.m_z + b.m_y*a.m_z
 
     c.m_x = (a.m_x*b.m_x-dot)*denom
     c.m_y = (c.m_y - a.m_x*b.m_y + b.m_x*a.m_y)*denom
     c.m_z = (c.m_z - a.m_x*b.m_z + b.m_x*a.m_z)*denom
     c.m_w = (c.m_w - a.m_x*b.m_w + b.m_x*a.m_w)*denom
   endfunc
 
 ; Quaternian division calculated as 1/Q1)*Q2
   static func Qdiv2(Vector a, Vector b, Vector c)
     ; 1/Q = [r, -V]/(r*r + V.V)
     ; then calculate (1/Q1)*Q2 as for QMul
     float denom = 1/(b.m_x*b.m_x + b.m_y*b.m_y + b.m_z*b.m_z + b.m_w*b.m_w)
     ; calc V . V
     float dot = -(a.m_y*b.m_y + a.m_z*b.m_z + a.m_w*b.m_w)
     ; calc V x V
     c.m_y = -b.m_z*a.m_w + a.m_z*b.m_w
     c.m_z = b.m_y*a.m_w - a.m_y*b.m_w
     c.m_w = -b.m_y*a.m_z + a.m_y*b.m_z
 
     c.m_x = (a.m_x*b.m_x-dot)*denom
     c.m_y = (c.m_y + b.m_x*a.m_y - a.m_x*b.m_y)*denom
     c.m_z = (c.m_z + b.m_x*a.m_z - a.m_x*b.m_z)*denom
     c.m_w = (c.m_w + b.m_x*a.m_w - a.m_x*b.m_w)*denom
   endfunc
 
 ; Quaternian square
   static func Qsqr(Vector a, Vector b)
     ; Q*Q = [r*r-V.V, 2*r*V]
     ; calc V . V
     float dot = a.m_y*a.m_y + a.m_z*a.m_z + a.m_w*a.m_w
     if dot == 0
       dot = 1e-100
     endif
     b.m_x = a.m_x*a.m_x-dot
     b.m_y = 2*a.m_x*a.m_y
     b.m_z = 2*a.m_x*a.m_z
     b.m_w = 2*a.m_x*a.m_w
   endfunc
 
 ; Quaternian square root
   static func Qsqrt(Vector a, Vector b)
     ; derived from the inverse of the equations for Qsqr
     float sdot = a.m_y*a.m_y + a.m_z*a.m_z + a.m_w*a.m_w
     if sdot == 0
       sdot = 1e-100
     endif
     b.m_x = sqrt((a.m_x + sqrt(a.m_x^2 + sdot))/2)
     float factor = 1/(2*b.m_x)
     b.m_y = a.m_y*factor
     b.m_z = a.m_z*factor
     b.m_w = a.m_w*factor
   endfunc
 
 ; Quaternian reciprocal or inverse
   static func Qrecip(Vector a, Vector b)
     ; 1/Q = [r, -V]/(r*r + V.V)
     float denom = 1/(a.m_x*a.m_x + a.m_y*a.m_y + a.m_z*a.m_z + a.m_w*a.m_w)
     b.m_x = a.m_x*denom
     b.m_y = -a.m_y*denom
     b.m_z = -a.m_z*denom
     b.m_w = -a.m_w*denom
   endfunc
 
 ; Quaternian natural log
   static func Qlog(Vector a, Vector b)
     float norm = sqrt(a.m_y*a.m_y + a.m_z*a.m_z + a.m_w*a.m_w)
     if norm == 0
       norm = 1e-100
     endif
     complex z = a.m_x + flip(norm)
     z = log(z)
     float at = imag(z)/norm
     b.m_x = real(z)
     b.m_y = at*a.m_y
     b.m_z = at*a.m_z
     b.m_w = at*a.m_w
   endfunc
 
 ; Quaternian exponential
   static func Qexp(Vector a, Vector b)
     float norm = sqrt(a.m_y*a.m_y + a.m_z*a.m_z + a.m_w*a.m_w)
     if norm == 0
       norm = 1e-100
     endif
     complex z = a.m_x + flip(norm)
     z = exp(z)
     float at = imag(z)/norm
     b.m_x = real(z)
     b.m_y = at*a.m_y
     b.m_z = at*a.m_z
     b.m_w = at*a.m_w
   endfunc
 
 ; Quaternian power calculated as exp(ln(Q1)*Q2)
   static func Qpower(Vector a, Vector b, Vector c)
 ;    Q1^Q2 = exp(ln(Q1)*Q2)
 ;   Find the log of Q1
     float norm = sqrt(a.m_y*a.m_y + a.m_z*a.m_z + a.m_w*a.m_w)
     if norm == 0
       norm = 1e-100
     endif
     complex z = a.m_x + flip(norm)
     z = log(z)
     float at = imag(z)/norm
     float x1 = real(z)
     float y1 = at*a.m_y
     float z1 = at*a.m_z
     float w1 = at*a.m_w
 ;   Multiply log by Q2
     float dot = y1*b.m_y + z1*b.m_z + w1*b.m_w
     ; calc V x V
     float y2 = z1*b.m_w - b.m_z*w1
     float z2 = -(y1*b.m_w - b.m_y*w1)
     float w2 = y1*b.m_z - b.m_y*z1
 
     float x2 = x1*b.m_x-dot
     y2 = y2 + x1*b.m_y + b.m_x*y1
     z2 = z2 + x1*b.m_z + b.m_x*z1
     w2 = w2 + x1*b.m_w + b.m_x*w1
 ;   Take the exponential
     norm = sqrt(y2*y2 + z2*z2 + w2*w2)
     if norm == 0
       norm = 1e-100
     endif
     z = x2 + flip(norm)
     z = exp(z)
     at = imag(z)/norm
     c.m_x = real(z)
     c.m_y = at*y2
     c.m_z = at*z2
     c.m_w = at*w2
   endfunc
 
 ; Quaternian power calculated as exp(Q2*ln(Q1))
   static func Qpower2(Vector a, Vector b, Vector c)
 ;    Q1^Q2 = exp(Q2*ln(Q1))
  ;   Find the log of Q1
      float norm = sqrt(a.m_y*a.m_y + a.m_z*a.m_z + a.m_w*a.m_w)
      if norm == 0
        norm = 1e-100
      endif
      complex z = a.m_x + flip(norm)
      z = log(z)
      float at = imag(z)/norm
      float x1 = real(z)
      float y1 = at*a.m_y
      float z1 = at*a.m_z
      float w1 = at*a.m_w
  ;   Multiply log by Q2
      float dot = y1*b.m_y + z1*b.m_z + w1*b.m_w
      ; calc V x V
      float y2 = -z1*b.m_w + b.m_z*w1
      float z2 = (y1*b.m_w - b.m_y*w1)
      float w2 = -y1*b.m_z + b.m_y*z1
 
      float x2 = x1*b.m_x-dot
      y2 = y2 + x1*b.m_y + b.m_x*y1
      z2 = z2 + x1*b.m_z + b.m_x*z1
      w2 = w2 + x1*b.m_w + b.m_x*w1
 
  ;   Take the exponential
      norm = sqrt(y2*y2 + z2*z2 + w2*w2)
      if norm == 0
        norm = 1e-100
      endif
      z = x2 + flip(norm)
      z = exp(z)
      at = imag(z)/norm
      c.m_x = real(z)
      c.m_y = at*y2
      c.m_z = at*z2
      c.m_w = at*w2
   endfunc
 
 ; Quaternian sine
   static func Qsin(Vector a, Vector b)
     float norm = sqrt(a.m_y*a.m_y + a.m_z*a.m_z + a.m_w*a.m_w)
     if norm == 0
       norm = 1e-100
     endif
     complex z = a.m_x + flip(norm)
     z = sin(z)
     float at = imag(z)/norm
     b.m_x = real(z)
     b.m_y = at*a.m_y
     b.m_z = at*a.m_z
     b.m_w = at*a.m_w
   endfunc
 
 ; Quaternian arcsine
   static func Qasin(Vector a, Vector b)
     float norm = sqrt(a.m_y*a.m_y + a.m_z*a.m_z + a.m_w*a.m_w)
     if norm == 0
       norm = 1e-100
     endif
     complex z = a.m_x + flip(norm)
     z = asin(z)
     float at = imag(z)/norm
     b.m_x = real(z)
     b.m_y = at*a.m_y
     b.m_z = at*a.m_z
     b.m_w = at*a.m_w
   endfunc
 
 ; Quaternian cosine
   static func Qcos(Vector a, Vector b)
     float norm = sqrt(a.m_y*a.m_y + a.m_z*a.m_z + a.m_w*a.m_w)
     if norm == 0
       norm = 1e-100
     endif
     complex z = a.m_x + flip(norm)
     z = cos(z)
     float at = imag(z)/norm
     b.m_x = real(z)
     b.m_y = at*a.m_y
     b.m_z = at*a.m_z
     b.m_w = at*a.m_w
   endfunc
 
 ; Quaternian arccosine
   static func Qacos(Vector a, Vector b)
     float norm = sqrt(a.m_y*a.m_y + a.m_z*a.m_z + a.m_w*a.m_w)
     if norm == 0
       norm = 1e-100
     endif
     complex z = a.m_x + flip(norm)
     z = acos(z)
     float at = imag(z)/norm
     b.m_x = real(z)
     b.m_y = at*a.m_y
     b.m_z = at*a.m_z
     b.m_w = at*a.m_w
   endfunc
 
 ; Quaternian tangent
   static func Qtan(Vector a, Vector b)
     float norm = sqrt(a.m_y*a.m_y + a.m_z*a.m_z + a.m_w*a.m_w)
     if norm == 0
       norm = 1e-100
     endif
     complex z = a.m_x + flip(norm)
     z = tan(z)
     float at = imag(z)/norm
     b.m_x = real(z)
     b.m_y = at*a.m_y
     b.m_z = at*a.m_z
     b.m_w = at*a.m_w
   endfunc
 
 ; Quaternian hyperbolic tangent
   static func Qtanh(Vector a, Vector b)
     float norm = sqrt(a.m_y*a.m_y + a.m_z*a.m_z + a.m_w*a.m_w)
     if norm == 0
       norm = 1e-100
     endif
     complex z = a.m_x + flip(norm)
     z = tanh(z)
     float at = imag(z)/norm
     b.m_x = real(z)
     b.m_y = at*a.m_y
     b.m_z = at*a.m_z
     b.m_w = at*a.m_w
   endfunc
 
 ; Quaternian hyperbolic arctangent
   static func Qatanh(Vector a, Vector b)
     float norm = sqrt(a.m_y*a.m_y + a.m_z*a.m_z + a.m_w*a.m_w)
     if norm == 0
       norm = 1e-100
     endif
     complex z = a.m_x + flip(norm)
     z = atanh(z)
     float at = imag(z)/norm
     b.m_x = real(z)
     b.m_y = at*a.m_y
     b.m_z = at*a.m_z
     b.m_w = at*a.m_w
   endfunc
 
 ; Quaternian arctangent
   static func Qatan(Vector a, Vector b)
     float norm = sqrt(a.m_y*a.m_y + a.m_z*a.m_z + a.m_w*a.m_w)
     if norm == 0
       norm = 1e-100
     endif
     complex z = a.m_x + flip(norm)
     z = atan(z)
     float at = imag(z)/norm
     b.m_x = real(z)
     b.m_y = at*a.m_y
     b.m_z = at*a.m_z
     b.m_w = at*a.m_w
   endfunc
 
 ; Quaternian conjugate
   static func Qconj(Vector a, Vector b)
     ; conj(Q) = [r,-V]
     b.m_x = a.m_x
     b.m_y = -a.m_y
     b.m_z = -a.m_z
     b.m_w = -a.m_w
   endfunc
 
 ; Quaternian hyperbolic sine
   static func Qsinh(Vector a, Vector b)
     float norm = sqrt(a.m_y*a.m_y + a.m_z*a.m_z + a.m_w*a.m_w)
     if norm == 0
       norm = 1e-100
     endif
     complex z = a.m_x + flip(norm)
     z = sinh(z)
     float at = imag(z)/norm
     b.m_x = real(z)
     b.m_y = at*a.m_y
     b.m_z = at*a.m_z
     b.m_w = at*a.m_w
   endfunc
 
 ; Quaternian hyperbolic cosine
   static func Qcosh(Vector a, Vector b)
     float norm = sqrt(a.m_y*a.m_y + a.m_z*a.m_z + a.m_w*a.m_w)
     if norm == 0
       norm = 1e-100
     endif
     complex z = a.m_x + flip(norm)
     z = cosh(z)
     float at = imag(z)/norm
     b.m_x = real(z)
     b.m_y = at*a.m_y
     b.m_z = at*a.m_z
     b.m_w = at*a.m_w
   endfunc
 
 ; Quaternian hyperbolic arcsine
   static func Qasinh(Vector a, Vector b)
     float norm = sqrt(a.m_y*a.m_y + a.m_z*a.m_z + a.m_w*a.m_w)
     if norm == 0
       norm = 1e-100
     endif
     complex z = a.m_x + flip(norm)
     z = asinh(z)
     float at = imag(z)/norm
     b.m_x = real(z)
     b.m_y = at*a.m_y
     b.m_z = at*a.m_z
     b.m_w = at*a.m_w
   endfunc
 
 ; Quaternian hyperbolic arccosine
   static func Qacosh(Vector a, Vector b)
     float norm = sqrt(a.m_y*a.m_y + a.m_z*a.m_z + a.m_w*a.m_w)
     if norm == 0
       norm = 1e-100
     endif
     complex z = a.m_x + flip(norm)
     z = acosh(z)
     float at = imag(z)/norm
     b.m_x = real(z)
     b.m_y = at*a.m_y
     b.m_z = at*a.m_z
     b.m_w = at*a.m_w
   endfunc
 
 ; Quaternian cotangent
   static func Qcotan(Vector a, Vector b)
     float norm = sqrt(a.m_y*a.m_y + a.m_z*a.m_z + a.m_w*a.m_w)
     if norm == 0
       norm = 1e-100
     endif
     complex z = a.m_x + flip(norm)
     z = cotan(z)
     float at = imag(z)/norm
     b.m_x = real(z)
     b.m_y = at*a.m_y
     b.m_z = at*a.m_z
     b.m_w = at*a.m_w
   endfunc
 
 ; Quaternian hyperbolic cotangent
   static func Qcotanh(Vector a, Vector b)
     float norm = sqrt(a.m_y*a.m_y + a.m_z*a.m_z + a.m_w*a.m_w)
     if norm == 0
       norm = 1e-100
     endif
     complex z = a.m_x + flip(norm)
     z = cotanh(z)
     float at = imag(z)/norm
     b.m_x = real(z)
     b.m_y = at*a.m_y
     b.m_z = at*a.m_z
     b.m_w = at*a.m_w
   endfunc
 
 
 ; Hypercomplex multiplication
   static func Hmul(Vector a, Vector b, Vector c)
     complex a1 = a.m_x + flip(a.m_y)
     complex a2 = a.m_z + flip(a.m_w)
     complex b1 = b.m_x + flip(b.m_y)
     complex b2 = b.m_z + flip(b.m_w)
     complex fa1 = a1 - conj(flip(a2))
     complex fa2 = a1 + conj(flip(a2))
     complex fb1 = b1 - conj(flip(b2))
     complex fb2 = b1 + conj(flip(b2))
     fa1 = fa1*fb1
     fa2 = fa2*fb2
     c1 = 0.5*(fa1+fa2)
     c2 = 0.5*(conj(flip(fa1)) - conj(flip(fa2)))
     c.m_x = real(c1)
     c.m_y = imag(c1)
     c.m_z = real(c2)
     c.m_w = imag(c2)
   endfunc
 
 ; Hypercomplex division
   static func Hdiv(Vector a, Vector b, Vector c)
     complex a1 = a.m_x + flip(a.m_y)
     complex a2 = a.m_z + flip(a.m_w)
     complex b1 = b.m_x + flip(b.m_y)
     complex b2 = b.m_z + flip(b.m_w)
     complex fa1 = a1 - conj(flip(a2))
     complex fa2 = a1 + conj(flip(a2))
     complex fb1 = b1 - conj(flip(b2))
     complex fb2 = b1 + conj(flip(b2))
     fa1 = fa1/fb1
     fa2 = fa2/fb2
     c1 = 0.5*(fa1+fa2)
     c2 = 0.5*(conj(flip(fa1)) - conj(flip(fa2)))
     c.m_x = real(c1)
     c.m_y = imag(c1)
     c.m_z = real(c2)
     c.m_w = imag(c2)
   endfunc
 
 ; Hypercomplex square
   static func Hsqr(Vector a, Vector b)
     complex a1 = a.m_x + flip(a.m_y)
     complex a2 = a.m_z + flip(a.m_w)
     complex fa1 = a1 - conj(flip(a2))
     complex fa2 = a1 + conj(flip(a2))
     fa1 = fa1*fa1
     fa2 = fa2*fa2
     c1 = 0.5*(fa1+fa2)
     c2 = 0.5*(conj(flip(fa1)) - conj(flip(fa2)))
     b.m_x = real(c1)
     b.m_y = imag(c1)
     b.m_z = real(c2)
     b.m_w = imag(c2)
   endfunc
 
 ; Hypercomplex square root
   static func Hsqrt(Vector a, Vector b)
     complex a1 = a.m_x + flip(a.m_y)
     complex a2 = a.m_z + flip(a.m_w)
     complex fa1 = a1 - conj(flip(a2))
     complex fa2 = a1 + conj(flip(a2))
     fa1 = sqrt(fa1)
     fa2 = sqrt(fa2)
     c1 = 0.5*(fa1+fa2)
     c2 = 0.5*(conj(flip(fa1)) - conj(flip(fa2)))
     b.m_x = real(c1)
     b.m_y = imag(c1)
     b.m_z = real(c2)
     b.m_w = imag(c2)
   endfunc
 
 ; Hypercomplex reciprocal or inverse
   static func Hrecip(Vector a, Vector b)
     complex a1 = a.m_x + flip(a.m_y)
     complex a2 = a.m_z + flip(a.m_w)
     complex fa1 = a1 - conj(flip(a2))
     complex fa2 = a1 + conj(flip(a2))
     fa1 = 1/fa1
     fa2 = 1/fa2
     c1 = 0.5*(fa1+fa2)
     c2 = 0.5*(conj(flip(fa1)) - conj(flip(fa2)))
     b.m_x = real(c1)
     b.m_y = imag(c1)
     b.m_z = real(c2)
     b.m_w = imag(c2)
   endfunc
 
 ; Hypercomplex natural log
   static func Hlog(Vector a, Vector b)
     complex a1 = a.m_x + flip(a.m_y)
     complex a2 = a.m_z + flip(a.m_w)
     complex fa1 = a1 - conj(flip(a2))
     complex fa2 = a1 + conj(flip(a2))
     fa1 = log(fa1)
     fa2 = log(fa2)
     c1 = 0.5*(fa1+fa2)
     c2 = 0.5*(conj(flip(fa1)) - conj(flip(fa2)))
     b.m_x = real(c1)
     b.m_y = imag(c1)
     b.m_z = real(c2)
     b.m_w = imag(c2)
   endfunc
 
 ; Hypercomplex exponential
   static func Hexp(Vector a, Vector b)
     complex a1 = a.m_x + flip(a.m_y)
     complex a2 = a.m_z + flip(a.m_w)
     complex fa1 = a1 - conj(flip(a2))
     complex fa2 = a1 + conj(flip(a2))
     fa1 = exp(fa1)
     fa2 = exp(fa2)
     c1 = 0.5*(fa1+fa2)
     c2 = 0.5*(conj(flip(fa1)) - conj(flip(fa2)))
     b.m_x = real(c1)
     b.m_y = imag(c1)
     b.m_z = real(c2)
     b.m_w = imag(c2)
   endfunc
 
 ; Hypercomplex power
   static func Hpower(Vector a, Vector b, Vector c)
 ;    Q1^Q2 = exp(ln(Q1)*Q2)
 ;
 ; Find the log of Q1
     complex a1 = a.m_x + flip(a.m_y)
     complex a2 = a.m_z + flip(a.m_w)
     complex b1 = b.m_x + flip(b.m_y)
     complex b2 = b.m_z + flip(b.m_w)
     complex fa1 = a1 - conj(flip(a2))
     complex fa2 = a1 + conj(flip(a2))
     complex fb1 = b1 - conj(flip(b2))
     complex fb2 = b1 + conj(flip(b2))
     fa1 = log(fa1)
     fa2 = log(fa2)
 ;
 ; Multiply log by Q2
     fa1 =  fa1*fb1
     fa2 =  fa2*fb2
 ;
 ; Take exponential
     fa1 = exp(fa1)
     fa2 = exp(fa2)
     c1 = 0.5*(fa1+fa2)
     c2 = 0.5*(conj(flip(fa1)) - conj(flip(fa2)))
     c.m_x = real(c1)
     c.m_y = imag(c1)
     c.m_z = real(c2)
     c.m_w = imag(c2)
   endfunc
 
   static func Hsin(Vector a, Vector b)
     complex a1 = a.m_x + flip(a.m_y)
     complex a2 = a.m_z + flip(a.m_w)
     complex fa1 = a1 - conj(flip(a2))
     complex fa2 = a1 + conj(flip(a2))
     fa1 = sin(fa1)
     fa2 = sin(fa2)
     c1 = 0.5*(fa1+fa2)
     c2 = 0.5*(conj(flip(fa1)) - conj(flip(fa2)))
     b.m_x = real(c1)
     b.m_y = imag(c1)
     b.m_z = real(c2)
     b.m_w = imag(c2)
   endfunc
 
 ; Hypercomplex cosine
   static func Hcos(Vector a, Vector b)
     complex a1 = a.m_x + flip(a.m_y)
     complex a2 = a.m_z + flip(a.m_w)
     complex fa1 = a1 - conj(flip(a2))
     complex fa2 = a1 + conj(flip(a2))
     fa1 = cos(fa1)
     fa2 = cos(fa2)
     c1 = 0.5*(fa1+fa2)
     c2 = 0.5*(conj(flip(fa1)) - conj(flip(fa2)))
     b.m_x = real(c1)
     b.m_y = imag(c1)
     b.m_z = real(c2)
     b.m_w = imag(c2)
   endfunc
 
 ; Hypercomplex hyperbolic sine
   static func Hsinh(Vector a, Vector b)
     complex a1 = a.m_x + flip(a.m_y)
     complex a2 = a.m_z + flip(a.m_w)
     complex fa1 = a1 - conj(flip(a2))
     complex fa2 = a1 + conj(flip(a2))
     fa1 = sinh(fa1)
     fa2 = sinh(fa2)
     c1 = 0.5*(fa1+fa2)
     c2 = 0.5*(conj(flip(fa1)) - conj(flip(fa2)))
     b.m_x = real(c1)
     b.m_y = imag(c1)
     b.m_z = real(c2)
     b.m_w = imag(c2)
   endfunc
 
 ; Hypercomplex hyperbolic cosine
     static func Hcosh(Vector a, Vector b)
     complex a1 = a.m_x + flip(a.m_y)
     complex a2 = a.m_z + flip(a.m_w)
     complex fa1 = a1 - conj(flip(a2))
     complex fa2 = a1 + conj(flip(a2))
     fa1 = cosh(fa1)
     fa2 = cosh(fa2)
     c1 = 0.5*(fa1+fa2)
     c2 = 0.5*(conj(flip(fa1)) - conj(flip(fa2)))
     b.m_x = real(c1)
     b.m_y = imag(c1)
     b.m_z = real(c2)
     b.m_w = imag(c2)
   endfunc
 
 ; Hypercomplex conjugate
   static func Hconj(Vector a, Vector b)
     complex a1 = a.m_x + flip(a.m_y)
     complex a2 = a.m_z + flip(a.m_w)
     complex fa1 = a1 - conj(flip(a2))
     complex fa2 = a1 + conj(flip(a2))
     fa1 = conj(fa1)
     fa2 = conj(fa2)
     c1 = 0.5*(fa1+fa2)
     c2 = 0.5*(conj(flip(fa1)) - conj(flip(fa2)))
     b.m_x = real(c1)
     b.m_y = imag(c1)
     b.m_z = real(c2)
     b.m_w = imag(c2)
   endfunc
 
 ; Hypercomplex tangent
   static func Htan(Vector a, Vector b)
     complex a1 = a.m_x + flip(a.m_y)
     complex a2 = a.m_z + flip(a.m_w)
     complex fa1 = a1 - conj(flip(a2))
     complex fa2 = a1 + conj(flip(a2))
     fa1 = tan(fa1)
     fa2 = tan(fa2)
     c1 = 0.5*(fa1+fa2)
     c2 = 0.5*(conj(flip(fa1)) - conj(flip(fa2)))
     b.m_x = real(c1)
     b.m_y = imag(c1)
     b.m_z = real(c2)
     b.m_w = imag(c2)
   endfunc
 
 ; Hypercomplex arcsine
   static func Hasin(Vector a, Vector b)
     complex a1 = a.m_x + flip(a.m_y)
     complex a2 = a.m_z + flip(a.m_w)
     complex fa1 = a1 - conj(flip(a2))
     complex fa2 = a1 + conj(flip(a2))
     fa1 = asin(fa1)
     fa2 = asin(fa2)
     c1 = 0.5*(fa1+fa2)
     c2 = 0.5*(conj(flip(fa1)) - conj(flip(fa2)))
     b.m_x = real(c1)
     b.m_y = imag(c1)
     b.m_z = real(c2)
     b.m_w = imag(c2)
   endfunc
 
 ; Hypercomplex arccosine
   static func Hacos(Vector a, Vector b)
     complex a1 = a.m_x + flip(a.m_y)
     complex a2 = a.m_z + flip(a.m_w)
     complex fa1 = a1 - conj(flip(a2))
     complex fa2 = a1 + conj(flip(a2))
     fa1 = acos(fa1)
     fa2 = acos(fa2)
     c1 = 0.5*(fa1+fa2)
     c2 = 0.5*(conj(flip(fa1)) - conj(flip(fa2)))
     b.m_x = real(c1)
     b.m_y = imag(c1)
     b.m_z = real(c2)
     b.m_w = imag(c2)
   endfunc
 
 ; Hypercomplex arctangent
   static func Hatan(Vector a, Vector b)
     complex a1 = a.m_x + flip(a.m_y)
     complex a2 = a.m_z + flip(a.m_w)
     complex fa1 = a1 - conj(flip(a2))
     complex fa2 = a1 + conj(flip(a2))
     fa1 = atan(fa1)
     fa2 = atan(fa2)
     c1 = 0.5*(fa1+fa2)
     c2 = 0.5*(conj(flip(fa1)) - conj(flip(fa2)))
     b.m_x = real(c1)
     b.m_y = imag(c1)
     b.m_z = real(c2)
     b.m_w = imag(c2)
   endfunc
 
 ; Hypercomplex hyperbolic tangent
   static func Htanh(Vector a, Vector b)
     complex a1 = a.m_x + flip(a.m_y)
     complex a2 = a.m_z + flip(a.m_w)
     complex fa1 = a1 - conj(flip(a2))
     complex fa2 = a1 + conj(flip(a2))
     fa1 = tanh(fa1)
     fa2 = tanh(fa2)
     c1 = 0.5*(fa1+fa2)
     c2 = 0.5*(conj(flip(fa1)) - conj(flip(fa2)))
     b.m_x = real(c1)
     b.m_y = imag(c1)
     b.m_z = real(c2)
     b.m_w = imag(c2)
   endfunc
 
 ; Hypercomplex hyperbolic arcsine
   static func Hasinh(Vector a, Vector b)
     complex a1 = a.m_x + flip(a.m_y)
     complex a2 = a.m_z + flip(a.m_w)
     complex fa1 = a1 - conj(flip(a2))
     complex fa2 = a1 + conj(flip(a2))
     fa1 = asinh(fa1)
     fa2 = asinh(fa2)
     c1 = 0.5*(fa1+fa2)
     c2 = 0.5*(conj(flip(fa1)) - conj(flip(fa2)))
     b.m_x = real(c1)
     b.m_y = imag(c1)
     b.m_z = real(c2)
     b.m_w = imag(c2)
   endfunc
 
 ; Hypercomplex hyperbolic arccosine
   static func Hacosh(Vector a, Vector b)
     complex a1 = a.m_x + flip(a.m_y)
     complex a2 = a.m_z + flip(a.m_w)
     complex fa1 = a1 - conj(flip(a2))
     complex fa2 = a1 + conj(flip(a2))
     fa1 = acosh(fa1)
     fa2 = acosh(fa2)
     c1 = 0.5*(fa1+fa2)
     c2 = 0.5*(conj(flip(fa1)) - conj(flip(fa2)))
     b.m_x = real(c1)
     b.m_y = imag(c1)
     b.m_z = real(c2)
     b.m_w = imag(c2)
   endfunc
 
 ; Hypercomplex hyperbolic arctangent
   static func Hatanh(Vector a, Vector b)
     complex a1 = a.m_x + flip(a.m_y)
     complex a2 = a.m_z + flip(a.m_w)
     complex fa1 = a1 - conj(flip(a2))
     complex fa2 = a1 + conj(flip(a2))
     fa1 = atanh(fa1)
     fa2 = atanh(fa2)
     c1 = 0.5*(fa1+fa2)
     c2 = 0.5*(conj(flip(fa1)) - conj(flip(fa2)))
     b.m_x = real(c1)
     b.m_y = imag(c1)
     b.m_z = real(c2)
     b.m_w = imag(c2)
   endfunc
 
 ; Hypercomplex cotangent
   static func Hcotan(Vector a, Vector b)
     complex a1 = a.m_x + flip(a.m_y)
     complex a2 = a.m_z + flip(a.m_w)
     complex fa1 = a1 - conj(flip(a2))
     complex fa2 = a1 + conj(flip(a2))
     fa1 = cotan(fa1)
     fa2 = cotan(fa2)
     c1 = 0.5*(fa1+fa2)
     c2 = 0.5*(conj(flip(fa1)) - conj(flip(fa2)))
     b.m_x = real(c1)
     b.m_y = imag(c1)
     b.m_z = real(c2)
     b.m_w = imag(c2)
   endfunc
 
 ; Hypercomplex hyperbolic cotangent
   static func Hcotanh(Vector a, Vector b)
     complex a1 = a.m_x + flip(a.m_y)
     complex a2 = a.m_z + flip(a.m_w)
     complex fa1 = a1 - conj(flip(a2))
     complex fa2 = a1 + conj(flip(a2))
     fa1 = cotanh(fa1)
     fa2 = cotanh(fa2)
     c1 = 0.5*(fa1+fa2)
     c2 = 0.5*(conj(flip(fa1)) - conj(flip(fa2)))
     b.m_x = real(c1)
     b.m_y = imag(c1)
     b.m_z = real(c2)
     b.m_w = imag(c2)
   endfunc
   
 default:
   title = "Quat Hyper Methods"
   int param v_quathyper
     caption = "Version (Quat Hyper Methods)"
     default = 100
     hint = "This version parameter is used to detect when a change has been made to the formula that is incompatible with the previous version. When that happens, this field will reflect the old version number to alert you to the fact that an alternate rendering is being used."
     visible = @v_quathyper < 100
   endparam
 }
 


Constructor Summary
QH()
           
 
Method Summary
static void Hacos(Vector a, Vector b)
          Hypercomplex arccosine
static void Hacosh(Vector a, Vector b)
          Hypercomplex hyperbolic arccosine
static void Hasin(Vector a, Vector b)
          Hypercomplex arcsine
static void Hasinh(Vector a, Vector b)
          Hypercomplex hyperbolic arcsine
static void Hatan(Vector a, Vector b)
          Hypercomplex arctangent
static void Hatanh(Vector a, Vector b)
          Hypercomplex hyperbolic arctangent
static void Hconj(Vector a, Vector b)
          Hypercomplex conjugate
static void Hcos(Vector a, Vector b)
          Hypercomplex cosine
static void Hcosh(Vector a, Vector b)
          Hypercomplex hyperbolic cosine
static void Hcotan(Vector a, Vector b)
          Hypercomplex cotangent
static void Hcotanh(Vector a, Vector b)
          Hypercomplex hyperbolic cotangent
static void Hdiv(Vector a, Vector b, Vector c)
          Hypercomplex division
static void Hexp(Vector a, Vector b)
          Hypercomplex exponential
static void Hlog(Vector a, Vector b)
          Hypercomplex natural log
static void Hmul(Vector a, Vector b, Vector c)
          Hypercomplex multiplication
static void Hpower(Vector a, Vector b, Vector c)
          Hypercomplex power
static void Hrecip(Vector a, Vector b)
          Hypercomplex reciprocal or inverse
static void Hsin(Vector a, Vector b)
           
static void Hsinh(Vector a, Vector b)
          Hypercomplex hyperbolic sine
static void Hsqr(Vector a, Vector b)
          Hypercomplex square
static void Hsqrt(Vector a, Vector b)
          Hypercomplex square root
static void Htan(Vector a, Vector b)
          Hypercomplex tangent
static void Htanh(Vector a, Vector b)
          Hypercomplex hyperbolic tangent
static void Qacos(Vector a, Vector b)
          Quaternian arccosine
static void Qacosh(Vector a, Vector b)
          Quaternian hyperbolic arccosine
static void Qasin(Vector a, Vector b)
          Quaternian arcsine
static void Qasinh(Vector a, Vector b)
          Quaternian hyperbolic arcsine
static void Qatan(Vector a, Vector b)
          Quaternian arctangent
static void Qatanh(Vector a, Vector b)
          Quaternian hyperbolic arctangent
static void Qconj(Vector a, Vector b)
          Quaternian conjugate
static void Qcos(Vector a, Vector b)
          Quaternian cosine
static void Qcosh(Vector a, Vector b)
          Quaternian hyperbolic cosine
static void Qcotan(Vector a, Vector b)
          Quaternian cotangent
static void Qcotanh(Vector a, Vector b)
          Quaternian hyperbolic cotangent
static void Qdiv(Vector a, Vector b, Vector c)
          Quaternian division calculated as Q2*(1/Q1)
static void Qdiv2(Vector a, Vector b, Vector c)
          Quaternian division calculated as 1/Q1)*Q2
static void Qexp(Vector a, Vector b)
          Quaternian exponential
static void Qlog(Vector a, Vector b)
          Quaternian natural log
static void Qmul(Vector a, Vector b, Vector c)
          Quaternian multiplication
static void Qpower(Vector a, Vector b, Vector c)
          Quaternian power calculated as exp(ln(Q1)*Q2)
static void Qpower2(Vector a, Vector b, Vector c)
          Quaternian power calculated as exp(Q2*ln(Q1))
static void Qrecip(Vector a, Vector b)
          Quaternian reciprocal or inverse
static void Qsin(Vector a, Vector b)
          Quaternian sine
static void Qsinh(Vector a, Vector b)
          Quaternian hyperbolic sine
static void Qsqr(Vector a, Vector b)
          Quaternian square
static void Qsqrt(Vector a, Vector b)
          Quaternian square root
static void Qtan(Vector a, Vector b)
          Quaternian tangent
static void Qtanh(Vector a, Vector b)
          Quaternian hyperbolic tangent
 
Methods inherited from class Object
 

Constructor Detail

QH

public QH()
Method Detail

Qmul

public static void Qmul(Vector a,
                        Vector b,
                        Vector c)
Quaternian multiplication


Qdiv

public static void Qdiv(Vector a,
                        Vector b,
                        Vector c)
Quaternian division calculated as Q2*(1/Q1)


Qdiv2

public static void Qdiv2(Vector a,
                         Vector b,
                         Vector c)
Quaternian division calculated as 1/Q1)*Q2


Qsqr

public static void Qsqr(Vector a,
                        Vector b)
Quaternian square


Qsqrt

public static void Qsqrt(Vector a,
                         Vector b)
Quaternian square root


Qrecip

public static void Qrecip(Vector a,
                          Vector b)
Quaternian reciprocal or inverse


Qlog

public static void Qlog(Vector a,
                        Vector b)
Quaternian natural log


Qexp

public static void Qexp(Vector a,
                        Vector b)
Quaternian exponential


Qpower

public static void Qpower(Vector a,
                          Vector b,
                          Vector c)
Quaternian power calculated as exp(ln(Q1)*Q2)


Qpower2

public static void Qpower2(Vector a,
                           Vector b,
                           Vector c)
Quaternian power calculated as exp(Q2*ln(Q1))


Qsin

public static void Qsin(Vector a,
                        Vector b)
Quaternian sine


Qasin

public static void Qasin(Vector a,
                         Vector b)
Quaternian arcsine


Qcos

public static void Qcos(Vector a,
                        Vector b)
Quaternian cosine


Qacos

public static void Qacos(Vector a,
                         Vector b)
Quaternian arccosine


Qtan

public static void Qtan(Vector a,
                        Vector b)
Quaternian tangent


Qtanh

public static void Qtanh(Vector a,
                         Vector b)
Quaternian hyperbolic tangent


Qatanh

public static void Qatanh(Vector a,
                          Vector b)
Quaternian hyperbolic arctangent


Qatan

public static void Qatan(Vector a,
                         Vector b)
Quaternian arctangent


Qconj

public static void Qconj(Vector a,
                         Vector b)
Quaternian conjugate


Qsinh

public static void Qsinh(Vector a,
                         Vector b)
Quaternian hyperbolic sine


Qcosh

public static void Qcosh(Vector a,
                         Vector b)
Quaternian hyperbolic cosine


Qasinh

public static void Qasinh(Vector a,
                          Vector b)
Quaternian hyperbolic arcsine


Qacosh

public static void Qacosh(Vector a,
                          Vector b)
Quaternian hyperbolic arccosine


Qcotan

public static void Qcotan(Vector a,
                          Vector b)
Quaternian cotangent


Qcotanh

public static void Qcotanh(Vector a,
                           Vector b)
Quaternian hyperbolic cotangent


Hmul

public static void Hmul(Vector a,
                        Vector b,
                        Vector c)
Hypercomplex multiplication


Hdiv

public static void Hdiv(Vector a,
                        Vector b,
                        Vector c)
Hypercomplex division


Hsqr

public static void Hsqr(Vector a,
                        Vector b)
Hypercomplex square


Hsqrt

public static void Hsqrt(Vector a,
                         Vector b)
Hypercomplex square root


Hrecip

public static void Hrecip(Vector a,
                          Vector b)
Hypercomplex reciprocal or inverse


Hlog

public static void Hlog(Vector a,
                        Vector b)
Hypercomplex natural log


Hexp

public static void Hexp(Vector a,
                        Vector b)
Hypercomplex exponential


Hpower

public static void Hpower(Vector a,
                          Vector b,
                          Vector c)
Hypercomplex power


Hsin

public static void Hsin(Vector a,
                        Vector b)

Hcos

public static void Hcos(Vector a,
                        Vector b)
Hypercomplex cosine


Hsinh

public static void Hsinh(Vector a,
                         Vector b)
Hypercomplex hyperbolic sine


Hcosh

public static void Hcosh(Vector a,
                         Vector b)
Hypercomplex hyperbolic cosine


Hconj

public static void Hconj(Vector a,
                         Vector b)
Hypercomplex conjugate


Htan

public static void Htan(Vector a,
                        Vector b)
Hypercomplex tangent


Hasin

public static void Hasin(Vector a,
                         Vector b)
Hypercomplex arcsine


Hacos

public static void Hacos(Vector a,
                         Vector b)
Hypercomplex arccosine


Hatan

public static void Hatan(Vector a,
                         Vector b)
Hypercomplex arctangent


Htanh

public static void Htanh(Vector a,
                         Vector b)
Hypercomplex hyperbolic tangent


Hasinh

public static void Hasinh(Vector a,
                          Vector b)
Hypercomplex hyperbolic arcsine


Hacosh

public static void Hacosh(Vector a,
                          Vector b)
Hypercomplex hyperbolic arccosine


Hatanh

public static void Hatanh(Vector a,
                          Vector b)
Hypercomplex hyperbolic arctangent


Hcotan

public static void Hcotan(Vector a,
                          Vector b)
Hypercomplex cotangent


Hcotanh

public static void Hcotanh(Vector a,
                           Vector b)
Hypercomplex hyperbolic cotangent