The Museum of HP Calculators


Quaternions for the HP-41

This program is Copyright © 2004 by Jean-Marc Baillard and is used here by permission.

This program is supplied without representation or warranty of any kind. Jean-Marc Baillard and The Museum of HP Calculators therefore assume no responsibility and shall have no liability, consequential or otherwise, of any kind arising from the use of this program material or any part thereof.

Overview

-A quaternion ( or hypercomplex number ) is an expression of the form  q = x + y.i + z.j + t.k
  where x , y , z , t  are 4 real numbers and  i ; j ; k  are 3 imaginary units without any linear relation between them.
-More precisely, a quaternion can be regarded as an element ( x ; y ; z ; t ) of  R4
  and 1 ; i ; j ; k as the standard basis ( 1 ; 0 ; 0 ; 0 ) ( 0 ; 1 ; 0 ; 0 ) ( 0 ; 0 ; 1 ; 0 ) ( 0 ; 0 ; 0 ; 1 )
-Addition and subtraction are defined like ordinary vectors, but the multiplication is defined by the rules:
    i.j = -j.i = k
   j.k = -k.j = i       and     i2 = j2 = k2 = -1          Therefore, the product of 2 quaternions is not commutative.But it has the associative and distributive properties.
   k.i =  -i.k = j
-The following programs perform a few basic calculations, namely: addition, subtraction, multiplication, reciprocal, polar-rectangular conversions,
  natural exponential and logarithm, and raising a quaternion to a power.
-Then, we solve equations in one unknown.
-And the last program illustrates a link between quaternions and 3-dimensional rotations.

 
Addition and Subtraction of 2 Quaternions

 
Data Registers:             R00:  unused
                            •   R01 = a        •  R05 = a'
                            •   R02 = b        •  R06 = b'       with    q  =  a + b.i + c.j + d.k            R01 thru R08 are to be initialized
                            •   R03 = c        •  R07 = c'        and    q' = a' + b'.i + c'.j + d'.k
                            •   R04 = d        •  R08 = d'

Flag:  F01    CF 01 = addition
                     SF 01 = subtraction
Subroutine:  none
 

01  LBL "Q+"
02  RCL 04
03  RCL 08
04  FS? 01
05  CHS
06  +
07  RCL 03
08  RCL 07
09  FS? 01
10  CHS
11  +
12  RCL 02
13  RCL 06
14  FS? 01
15  CHS
16  +
17  RCL 01
18  X<> 05
19  FS? 01
20  CHS
21  ST+ 05
22  FS? 01
23  CHS
24  X<> 05
25  END
 
( 40 bytes / SIZE 009 )
 

      STACK        INPUTS      OUTPUTS
           T             /             t
           Z             /             z
           Y             /             y
           X             /             x

  with      q + q'   =  x + y.i + z.j + t.k    ( if CF 01 )
    or       q - q'    =  x + y.i + z.j + t.k    ( if SF 01 )
 

Example:   q = 2 - 3i + 4j - 7k  and  q' = 1 - 4i + 2j + 5k       calculate  q + q'  and   q - q'

  2   STO 01     1  STO 05       CF 01   XEQ "Q+"  yields    3                  and         SF 01   XEQ "Q+"  ( or R/S )    produces     1
 -3  STO 02    -4  STO 06                                       RDN    -7                                                                                    RDN        1
  4  STO 03      2  STO 07                                       RDN    6                                                                                     RDN         2
 -7  STO 04     5  STO 08                                       RDN    -2                                                                                    RDN      -12

Thus      q + q'  = 3 -7i + 6j - 2k      and     q - q' =  1 + i + 2j - 12k
 

Multiplication of 2 Quaternions
 

Data Registers:           R00:  unused
                            •   R01 = a        •  R05 = a'
                            •   R02 = b        •  R06 = b'       with    q  =  a + b.i + c.j + d.k            R01 thru R08 are to be initialized
                            •   R03 = c        •  R07 = c'        and    q' = a' + b'.i + c'.j + d'.k
                            •   R04 = d        •  R08 = d'
Flag: none
Subroutine:  none
 

N.B:  Synthetic registers M and N can of course be replaced by any other unused registers,
         but avoid registers usage conflict between "Q*" and other programs when "Q*" is used as a subroutine.

 
01  LBL "Q*"
02  RCL 01
03  RCL 05
04  *
05  RCL 02
06  RCL 06
07  *
08  -
09  RCL 03
10  RCL 07
11  *
12  -
13  RCL 04
14  RCL 08
15  *
16  -
17  STO M
18  RCL 01
19  RCL 06
20  *
21  RCL 02
22  RCL 05
23  *
24  +
25  RCL 03
26  RCL 08
27  *
28  +
29  RCL 04
30  RCL 07
31  *
32  -
33  STO N
34  RCL 01
35  RCL 08
36  *
37  RCL 04
38  RCL 05
39  *
40  +
41  RCL 02
42  RCL 07
43  *
44  +
45  RCL 03
46  RCL 06
47  *
48  -
49  RCL 01
50  RCL 07
51  *
52  RCL 03
53  RCL 05
54  *
55  +
56  RCL 02
57  RCL 08
58  *
59  -
60  RCL 04
61  RCL 06
62  *
63  +
64  0
65  X<> N
66  0
67  X<> M
68  END

( 79 bytes / SIZE 009 )


      STACK        INPUTS      OUTPUTS
           T             /             t
           Z             /             z
           Y             /             y
           X             /             x

 with      q.q'  =  x + y.i + z.j + t.k
 
Example1:   q = 2 - 3i + 4j - 7k  and  q' = 1 - 4i + 2j + 5k       calculate  q.q'

  2   STO 01     1  STO 05              XEQ "Q*"    yields    17
 -3  STO 02    -4  STO 06                                   RDN    23
  4  STO 03      2  STO 07                                   RDN    51
 -7  STO 04     5  STO 08                                   RDN    13

Thus    q.q' = 17 + 23i + 51j + 13k                      ( remark:    q'.q = 17 - 45i -35j - 7k )
 
Example2:   A theorem states that  if  q = b.i + c.j + d.k   and   q' = b'.i + c'.j +d'.k  are 2 purely imaginary quaternions,
           then the real part of  q.q'  is -U.U'  where  U.U'  is the dot product of the 3D-vectors   U(b;c;d)   and   U'(b';c';d')
     and the constituents of the imaginary part of  q.q'  are the 3 constituents of the cross product   UxU'

-For instance, calculate the dot product and the cross product of the 2 vectors:    U(2;-4;9)    U'(3;8;-6)

   0  STO 01          0  STO 05         XEQ "Q*"    gives     80
   2  STO 02          3  STO 06                             RDN   -48          therefore    U.U'  =   - 80
  -4  STO 03          8  STO 07                            RDN     39              and        UxU' =  ( -48 ; 39 ; 28 )
   9  STO 04         -6  STO 08                            RDN     28
 

Reciprocal of a Quaternion
 

01  LBL "1/Q"
02  STO N
03  X^2
04  STO M
05  X<> T
06  CHS
07  ENTER^
08  X^2
09  ST+ M
10  X<> T
11  CHS
12  ENTER^
13  X^2
14  ST+ M
15  X<> T
16  CHS
17  ENTER^
18  X^2
19  ST+ M
20  CLX
21  X<> M
22  ST/ N
23  ST/ T
24  ST/ Z
25  /
26  0
27  X<> N
28  END

( 49 bytes / SIZE 000 )

 
      STACK        INPUTS      OUTPUTS
           T             d             t
           Z             c             z
           Y             b             y
           X             a             x
           L             /             µ2

 with      q =  a + b.i + c.j + d.k     ;    1/q =  x + y.i + z.j + t.k    and    µ = ( a2 + b2 + c2 + d2 )1/2 = the modulus of the quaternion q
 

Example:   q = 2 - 3i + 4j - 7k  evaluate 1/q

  -7   ENTER^
   4   ENTER^
  -3   ENTER^
   2   XEQ "1/Q"   yields    0.0256
                             RDN    0.0385
                             RDN  -0.0513
                             RDN    0.0897             thus   1/q = 0.0256 + 0.0385 i  -0.0513 j + 0.0897 k   ( rounded to 4D )
   ( L = µ2 = 78 )
 
Note:  Here is a shorter program to compute 1/q using the rectangular-polar conversions:
 
01  LBL "1/Q"
02  XEQ "POL"
03  1/X
04  X<>Y
05  CHS
06  X<>Y
07  XEQ "REC"
08  END

( 24 bytes / SIZE 000 )

 
Rectangular-Polar conversions

-A quaternion   q =  x + y.i + z.j + t.k   can also be defined by its modulus  µ = ( x2 + y2 + z2 + t2 )1/2  and 3 angles A , B , C such that:

                       x = µ cos A                                      A = the amplitude of the quaternion
                       y = µ sin A cos B                              B = the co-latitude ---------------
                       z = µ sin A sin B cos C                     C = the longitude   ---------------
                       t = µ sin A sin B sin C

-The 2 following programs perform these conversions and work in all angular mode.

 
        1°) Rectangular-Polar
 
 
01  LBL "POL"
02  R^
03  R^
04  R-P
05  R^
06  R-P
07  R^
08  R-P
09  END

( 17 bytes / SIZE 000 )


      STACK        INPUTS      OUTPUTS
           T             t             C
           Z             z             B
           Y             y             A
           X             x             µ
           L             /             x


Example:   q = 2 - 3i + 4j - 7k      ( in DEG mode )

 -7   ENTER^
   4   ENTER^
  -3   ENTER^
   2   XEQ "POL"     gives       8.8318  = µ      ( actually  781/2 )
                                RDN    76.9115  = A
                                RDN  110.4104  = B
                                RDN  -60.2551  = C
 

         2°) Polar-Rectangular
 
 
01  LBL "REC"
02  P-R
03  RDN
04  P-R
05  RDN
06  P-R
07  R^
08  R^
09  END

( 17 bytes / SIZE 000 )

 
      STACK        INPUTS      OUTPUTS
           T             C             t
           Z             B             z
           Y             A             y
           X             µ             x

 
Example:   Find the rectangular form of the quaternion q defined by:       µ = 7 ;  A = 41° ; B = 37°  ;  C = -168°

[DEG]    -168   ENTER^
                  37  ENTER^
                  41  ENTER^
                   7   XEQ "REC"      yields      5.2830
                                                 RDN      3.6677
                                                 RDN     -2.7034
                                                 RDN     -0.5746        thus      q = 5.2830 + 3.6677 i  -2.7034 j -0.5746 k     ( rounded to 4D )
 
Natural Exponential and Logarithm

          1°) Exponential

-The exponential of a quaternion q is defined by the serie  exp ( q ) = 1 + q + q2/2! + q3/3! + ....... + qn/n! + ........
  but the polar form provides a much faster way to compute eq
 

Flag: none
Subroutine:  "REC"


01  LBL "E^Q"
02  DEG
03  R^
04  R^
05  R-P
06  R^
07  R-P
08  R-D
09  R^
10  E^X
11  XEQ "REC"
12  END

( 24 bytes / SIZE 000 )


      STACK        INPUTS      OUTPUTS
           T             d             t
           Z             c             z
           Y             b             y
           X             a             x

 with      q =  a + b.i + c.j + d.k     ;    eq =  x + y.i + z.j + t.k
 
Example:   q = 2 - 3i + 4j - 7k  evaluate eq

  -7   ENTER^
   4   ENTER^
  -3   ENTER^
   2   XEQ "E^Q"     produces    -5.0277
                                   RDN       -1.8884
                                   RDN        2.5178
                                   RDN       -4.4062       and    eq  =   -5.0277 -1.8884 i + 2.5178 j - 4.4062 k   ( rounded to 4D )

N.B:  a)  ln (  eq ) is not always equal to q       ( like ordinary complex numbers )
        b)  eq.eq'    ---------------------  eq+q'
      c)  Hyperbolic functions can easily be defined too.

 
          2°) Logarithm
 

Flag: none
Subroutine:  "POL"

 
01  LBL "LNQ"
02  DEG
03  XEQ "POL"
04  LN
05  RDN
06  D-R
07  P-R
08  RDN
09  P-R
10  R^
11  R^
12  END

( 24 bytes / SIZE 000 )

 
      STACK        INPUTS      OUTPUTS
           T             d             t
           Z             c             z
           Y             b             y
           X             a             x

 with      q =  a + b.i + c.j + d.k     ;    ln q =  x + y.i + z.j + t.k
 
Example:   q = 2 - 3i + 4j - 7k  evaluate  ln q

  -7   ENTER^
   4   ENTER^
  -3   ENTER^
   2   XEQ "LNQ"    yields       2.1784
                                RDN      -0.4681
                                RDN       0.6242
                                RDN     -1.0923         ln q = 2.1784 -0.4681 i + 0.6242 j -1.0923 k         ( once again rounded to 4D )

 
Raising a Quaternion to a power

 
   1°) Real exponent

Data Register:
    • R00 = r  is to be initialized before executing Q^R
Flag: none
Subroutines:  "POL" "REC"

 
01  LBL "Q^R"
02  XEQ "POL"
03  X<>Y
04  X<> 00
05  ST* 00
06  Y^X
07  LASTX
08  X<> 00
09  X<>Y
10  XEQ "REC"
11  END

( 30 bytes / SIZE 001 )

 
      STACK        INPUTS      OUTPUTS
           T             d             t
           Z             c             z
           Y             b             y
           X             a             x

 with      q =  a + b.i + c.j + d.k     ;    qr =  x + y.i + z.j + t.k
 
 
Example1:   q = 2 - 3i + 4j - 7k  evaluate  q3.14

  3.14   STO 00
     -7   ENTER^
      4   ENTER^
     -3   ENTER^
      2   XEQ "Q^R"   yields    -445.8830
                                 RDN     286.4187
                                 RDN    -381.8916
                                 RDN     668.3104              therefore   q3.14 =   - 445.8830 + 286.4187 i  - 381.8916 j + 668.3104 k  ( to 4D )

Example2:   q = 2 - 3i + 4j - 7k  calculate one cube root of q  i-e  q1/3

  3  1/X   STO 00
        -7   ENTER^
         4   ENTER^
       -3   ENTER^
        2   XEQ "Q^R"   yields   1.8635
                                   RDN  -0.3119
                                   RDN   0.4159
                                   RDN  -0.7278        thus     q1/3 =  1.8635 - 0.3119 i + 0.4159 j - 0.7278 k  ( 4D )

Notes:   -A non-zero quaternion has in general n  n-th roots.
          -However, -1 has an infinity of square roots!   Namely, if  b2 + c2 + d2 = 1  then   ( b.i + c.j + d.k )2 = -1
       -This program gives  ( -1 )1/2 = i

 
    2°) Quaternion exponent

-This program calculates  qq' with the definition   qq' =   eq'.lnq
 
Data Registers:           R00:  unused
                            •   R01 = a        •  R05 = a'
                            •   R02 = b        •  R06 = b'       with    q  =  a + b.i + c.j + d.k            R01 thru R08 are to be initialized
                            •   R03 = c        •  R07 = c'        and    q' = a' + b'.i + c'.j + d'.k
                            •   R04 = d        •  R08 = d'
Flag: none
Subroutines:  "LNQ"  "E^Q"  "Q*"

Note:  When this program stops, registers R01 thru R04 contain q'
                                           and registers R05 thru R08  ------- ln q
 
 
01  LBL "Q^Q"
02  RCL 04
03  RCL 03
04  RCL 02
05  RCL 01
06  XEQ "LNQ"
07  X<> 05
08  STO 01
09  RDN
10  X<> 06
11  STO 02
12  RDN
13  X<> 07
14  STO 03
15  RDN
16  X<> 08
17  STO 04
18  XEQ "Q*"
19  XEQ "E^Q"
20  END
 
( 43 bytes / SIZE 009 )
 
 
      STACK        INPUTS      OUTPUTS
           T             /             t
           Z             /             z
           Y             /             y
           X             /             x

 with      qq'  =  x + y.i + z.j + t.k

Example:   q = 2 - 3i + 4j - 7k  and  q' = 1 - 4i + 2j + 5k       calculate  qq'

  2   STO 01     1  STO 05              XEQ "Q^Q"    yields    -45.8455
 -3  STO 02    -4  STO 06                                      RDN     68.7134
  4  STO 03      2  STO 07                                      RDN       8.2012
 -7  STO 04     5  STO 08                                      RDN    -39.0781
Thus    qq' = - 45.8455 +  68.7134 i + 8.2012 j  - 39.0781 k   ( rounded to 4D )

 
Solving a quaternion equation:       f ( q ) = q


-The following program uses an iterative method:
-The equation must be rewritten in the form:    f ( q ) = q
  and if  f  satisfies a Lipschitz condition   | f(q) - f(q') | < m | q - q' |    ,    m<1   ,   provided q and q' are close to the solution,
  then the sequence  qn+1 = f ( qn )  converges to a root.
 
Data Registers:

   •  R00 = function name            R09 to R12 also contain   a ; b ; c ; d    when the subroutine is executed.
   •  R01 = a                               R13 = function name too.
   •  R02 = b
   •  R03 = c
   •  R04 = d                               with    q0  =  a + b.i + c.j + d.k  = guess      ( R00 thru R04 are to be initialized )

Flag:  none
Subroutine:  the function f  ( assuming  q = x + y.i + z.j + t.k  is registers R01 thru R04 upon entry )
          >>>      f(q) = X + Y.i + Z.j + T.k  must end up in the stack registers X ; Y ; Z ; T
      -Registers R00 thru R08 and R14 or greater can be used ( and altered ) to compute f(q)
      -Registers R09 thru R13 can't be modified but can be used too.
 
 
01  LBL "SOLVE"
02  RCL 00
03  STO 13
04  LBL 01
05  VIEW 01                the real parts of the successive approximations are displayed
06  RCL 01
07  STO 09
08  RCL 02
09  STO 10
10  RCL 03
11  STO 11
12  RCL 04
13  STO 12
14  XEQ IND 13
15  STO 01
16  ST- 09
17  RDN
18  STO 02
19  ST- 10
20  RDN
21  STO 03
22  ST- 11
23  RDN
24  STO 04
25  ST- 12
26  RCL 09
27  X^2
28  RCL 10
29  X^2
30  RCL 11
31  X^2
32  RCL 12
33  X^2
34  +
35  +
36  +
37  X#0?                     to avoid a possible infinite loop, replace this line by the 2 instructions:    E-16        ( or another "small" number  )
38  GTO 01                                                                                                                           X<Y?
39  RCL 13
40  STO 00
41  RCL 04
42  RCL 03
43  RCL 02
44  RCL 01
45  END

( 62 bytes / SIZE 014 )

 
      STACK        INPUTS      OUTPUTS
           T             /             t
           Z             /             z
           Y             /             y
           X             /             x

      with   q =  x + y.i + z.j + t.k  = one solution     ( x ; y ; z ; t are also in registers R01 to R04 )

Example:    Find a root of:    q3 + ( 1 + 2.i + 3.j + 4.k ) q + ( 2 - 3.i + 4.j - 7.k ) = 0
  -This equation can be put in the form  q = f ( q ) in many ways but, unfortunately,  f doesn't necessarily satisfy the required Lipschitz condition!
  -Let's try:      q = ( -1-2.i -3.j -4.k )-1  ( q3 + 2 - 3.i + 4.j - 7.k ) = f(q)      and let's key in the subroutine:
 
 LBL "T"
 3
 STO 00
 RCL 04
 RCL 03
 RCL 02
 RCL 01
 XEQ "Q^R"
 STO 05
 RDN
 STO 06
 RDN
 STO 07
 RDN
 STO 08
 2
 ST+ 05
 3
 ST- 06
 4
 ST+ 07
 7
 ST- 08
 4
 CHS
 3
 CHS
 2
 CHS
 1
 CHS
 XEQ "1/Q"
 STO 01
 RDN
 STO 02
 RDN
 STO 03
 RDN
 STO 04
 XEQ "Q*"
 RTN
 
Then,   T  ASTO 00
           CLX   STO 01  STO 02  STO 03  STO 04       ( if we choose q = 0 as initial value )
           XEQ "SOLVE"

The successive approximations are displayed:
                                    0.000000000
                                    0.666666666
                                    0.873580246
                                    .....................
                                    .....................
 and eventually:             0.808540975
                        RDN  -1.290564599
                        RDN  -0.290931376
                        RDN   0.490521464       whence   q =  0.808540975 - 1.290564599 i  - 0.290931376 j + 0.490521464 k  is a root of this polynomial.
 
Notes:

 -Convergence may be slow.
 -If  f doesn't satisfy the required Lipschitz condition or if we choose a bad initial guess, the algorithm may be divergent.
 -The last decimals may vary according to the first guess and/or the method for computing f(q).
        For instance, the short version of "1/Q" is slightly less accurate than the long one.
 -I've tried to generalize the secant method to solve directly  f(q) = 0  but the results are somewhat disappointing and convergence is very slow and chaotic.
 
Exercise:     Find a root of the equation:         k.ln q + q2 + i + j + k = 0
 answer:       A solution is          q = 0.791739122  - 0.754317889 i - 0.231635888 j - 0.844420665 k
 

Rotations and Quaternions


-Quaternions can describe the spin of elementary particles, and they are useful in geometry too:
-A rotation ( in space ) can be defined by an angle A and a 3D-vector u(a;b;c)
-This rotation transforms a 3D-vector  V(x;y;z)  into  V'(x';y';z') and the following program computes  x' ; y' ; z'  from  x ; y ; z
-The formula is:
                             x'.i + y'.j + z'.k = q-1 ( x.i + y.j + z.k ) q     where  q = cos(A/2) -  sin(A/2) ( a.i + b.j + c.k ) / ( a2 + b2 + c2 )1/2

Data Registers:    • R00 = A      • R01 = a     • R02 = b    • R03 = c         are to be initialized before executing  "ROT"
                                  R04 thru R11 are used for temporary data storage
Flag: none
Subroutines:   "Q*"

Notes:  -Registers R01-R02-R03  are altered during the calculations but they are restored at the end.
           -The sign of the rotation angle A is determined by the right-hand rule.
 
 
01  LBL "ROT"
02  STO 06
03  RDN
04  STO 07
05  X<>Y
06  STO 08
07  CLX
08  STO 05
09  RCL 00
10  2
11  /
12  1
13  P-R
14  X<> 01
15  STO 09
16  X^2
17  LASTX
18  X<> 02
19  STO 10
20  X^2
21  LASTX
22  X<> 03
23  STO 04
24  STO 11
25  X^2
26  +
27  +
28  SQRT
29  /
30  ST* 02
31  ST* 03
32  ST* 04
33  XEQ "Q*"
34  X<> 01
35  STO 05
36  RDN
37  X<> 02
38  CHS
39  STO 06
40  RDN
41  X<> 03
42  CHS
43  STO 07
44  X<>Y
45  X<> 04
46  CHS
47  STO 08
48  XEQ "Q*"
49  CLX
50  RCL 09
51  STO 01
52  CLX
53  RCL 10
54  STO 02
55  CLX
56  RCL 11
57  STO 03
58  RDN
59  END

( 83 bytes / SIZE 012 )

 
      STACK        INPUTS      OUTPUTS
           Z             z             z'
           Y             y             y'
           X             x             x'

 
Example:     If r is the rotation defined by  A = 37°     and    u(1;2;4)      evaluate  V' = r(V)  where  V( 2 ; 3 ; 7 )

-Set your HP-41 in DEG mode and    37  STO 00     1  STO 01   2  STO 02   4  STO 03
      
-Then       7   ENTER^
                3   ENTER^
                2   XEQ "ROT"   produces    2.2051
                                              RDN       3.2176
                                              RDN       6.8399      and   V' = (  2.2051 ;  3.2176 ; 6.8399 )         ( rounded to 4D )

Go back to the HP-41 software library
Go back to the general software library
Go back to the main exhibit hall