Rebol3 Code Examplex
Quaternion
A four-part number used to represent rotations in 3D space and other geometric transformations.
Rebol [
title: "Rosetta code: Quaternion"
file: %Quaternion.r3
url: https://rosettacode.org/wiki/Quaternion
note: "Translated from Red"
]
quaternion: context [
quaternion!: make typeset! [block! hash! vector!]
multiply: func [
q [integer! decimal! quaternion!]
p [integer! decimal! quaternion!]
][
case [
number? q [collect [forall p [keep p/1 * q]]]
number? p [collect [forall q [keep q/1 * p]]]
'else [
reduce [
(q/1 * p/1) - (q/2 * p/2) - (q/3 * p/3) - (q/4 * p/4)
(q/1 * p/2) + (q/2 * p/1) + (q/3 * p/4) - (q/4 * p/3)
(q/1 * p/3) + (q/3 * p/1) + (q/4 * p/2) - (q/2 * p/4)
(q/1 * p/4) + (q/4 * p/1) + (q/2 * p/3) - (q/3 * p/2)
]
]
]
]
add: func [
q [integer! decimal! quaternion!]
p [integer! decimal! quaternion!]
][
case [
number? q [head change copy p p/1 + q]
number? p [head change copy q q/1 + p]
'else [collect [forall q [keep q/1 + p/(index? q)]]]
]
]
negate: func [q [quaternion!]][collect [forall q [keep 0 - q/1]]]
conjugate: func [q [quaternion!]][collect [keep q/1 q: next q forall q [keep 0 - q/1]]]
norm: func [q [quaternion!]][square-root first multiply q conjugate copy q]
normalize: func [q [quaternion!] /local n][n: norm q collect [forall q [keep q/1 / n]]]
inverse: func [q [quaternion!]][(conjugate q) / ((norm q) ** 2)]
]
print as-yellow "With values:"
foreach [var value][
q [1 2 3 4]
q1 [2 3 4 5]
q2 [3 4 5 6]
r 7
][
printf [-5 ": "][var mold value]
set var value
]
tests: [
"1. The norm of a quaternion:"
[quaternion/norm q]
"2. The negative of a quaternion:"
[quaternion/negate q]
"3. The conjugate of a quaternion:"
[quaternion/conjugate q]
"4. Addition of a real number `r` and a quaternion `q`:"
[quaternion/add r q]
[quaternion/add q r]
"5. Addition of two quaternions:"
[quaternion/add q1 q2]
"6. Multiplication of a real number and a quaternion:"
[quaternion/multiply q r]
[quaternion/multiply r q]
"7. Multiplication of two quaternions `q1` and `q2` is given by:"
[quaternion/multiply q1 q2]
"8. Show that, for the two quaternions `q1` and `q2`:"
[equal? quaternion/multiply q1 q2 quaternion/multiply q2 q1]
]
parse tests [some [
( print "" )
set title string! (print as-yellow title)
some [set code block! (
print [mold/only code "==" mold try code]
)]
]]Output:
With values:
q: [1 2 3 4]
q1: [2 3 4 5]
q2: [3 4 5 6]
r: 7
1. The norm of a quaternion:
quaternion/norm q == 5.47722557505166
2. The negative of a quaternion:
quaternion/negate q == [-1 -2 -3 -4]
3. The conjugate of a quaternion:
quaternion/conjugate q == [1 -2 -3 -4]
4. Addition of a real number `r` and a quaternion `q`:
quaternion/add r q == [8 2 3 4]
quaternion/add q r == [8 2 3 4]
5. Addition of two quaternions:
quaternion/add q1 q2 == [5 7 9 11]
6. Multiplication of a real number and a quaternion:
quaternion/multiply q r == [7 14 21 28]
quaternion/multiply r q == [7 14 21 28]
7. Multiplication of two quaternions `q1` and `q2` is given by:
quaternion/multiply q1 q2 == [-56 16 24 26]
8. Show that, for the two quaternions `q1` and `q2`:
equal? quaternion/multiply q1 q2 quaternion/multiply q2 q1 == #(false)