Data update
This commit is contained in:
parent
5150844a7d
commit
4bb20c9b71
7735 changed files with 38060 additions and 199180 deletions
|
|
@ -1,53 +1 @@
|
|||
[[wp:Quaternion|Quaternions]] are an extension of the idea of [[Arithmetic/Complex|complex numbers]].
|
||||
|
||||
A complex number has a real and complex part, sometimes written as <big> <code> a + bi, </code> </big>
|
||||
<br>where <big> <code> a </code> </big> and <big> <code> b </code> </big> stand for real numbers, and <big> <code> i </code> </big> stands for the square root of minus 1.
|
||||
|
||||
An example of a complex number might be <big> <code> -3 + 2i, </code> </big>
|
||||
<br>where the real part, <big> <code> a </code> </big> is <big> <code> '''-3.0''' </code> </big> and the complex part, <big> <code> b </code> </big> is <big> <code> '''+2.0'''. </code> </big>
|
||||
|
||||
A quaternion has one real part and ''three'' imaginary parts, <big> <code> i, </code> </big> <big> <code> j, </code> </big> and <big> <code> k. </code> </big>
|
||||
|
||||
A quaternion might be written as <big> <code> a + bi + cj + dk. </code> </big>
|
||||
|
||||
In the quaternion numbering system:
|
||||
:::* <big> <code> i∙i = j∙j = k∙k = i∙j∙k = -1, </code> </big> or more simply,
|
||||
:::* <big> <code> ii = jj = kk = ijk = -1. </code> </big>
|
||||
|
||||
The order of multiplication is important, as, in general, for two quaternions:
|
||||
:::: <big> <code> q<sub>1</sub> </code> </big> and <big> <code> q<sub>2</sub>: </code> </big> <big> <code> q<sub>1</sub>q<sub>2</sub> ≠ q<sub>2</sub>q<sub>1</sub>. </code> </big>
|
||||
|
||||
An example of a quaternion might be <big> <code> 1 +2i +3j +4k </code> </big>
|
||||
|
||||
There is a list form of notation where just the numbers are shown and the imaginary multipliers <big> <code>i, </code> </big> <big> <code> j, </code> </big> and <big> <code> k </code> </big> are assumed by position.
|
||||
|
||||
So the example above would be written as <big> <code> (1, 2, 3, 4) </code> </big>
|
||||
|
||||
|
||||
;Task:
|
||||
Given the three quaternions and their components: <big>
|
||||
q = (1, 2, 3, 4) = (a,<sub> </sub> b,<sub> </sub> c,<sub> </sub> d)
|
||||
q<sub>1</sub> = (2, 3, 4, 5) = (a<sub>1</sub>, b<sub>1</sub>, c<sub>1</sub>, d<sub>1</sub>)
|
||||
q<sub>2</sub> = (3, 4, 5, 6) = (a<sub>2</sub>, b<sub>2</sub>, c<sub>2</sub>, d<sub>2</sub>) </big>
|
||||
And a wholly real number <big> <code> r = 7. </code> </big>
|
||||
|
||||
|
||||
Create functions (or classes) to perform simple maths with quaternions including computing:
|
||||
# The norm of a quaternion: <br><big><code><math>= \sqrt{a^2 + b^2 + c^2 + d^2}</math></code></big>
|
||||
# The negative of a quaternion: <br> <big> <code> = (-a, -b, -c, -d)</code> </big>
|
||||
# The conjugate of a quaternion: <br> <big> <code> = ( a, -b, -c, -d)</code> </big>
|
||||
# Addition of a real number <big> <code> r </code> </big> and a quaternion <big> <code> q: </code> </big> <br> <big> <code> r + q = q + r = (a+r, b, c, d) </code> </big>
|
||||
# Addition of two quaternions: <br> <big> <code> q<sub>1</sub> + q<sub>2</sub> = (a<sub>1</sub>+a<sub>2</sub>, b<sub>1</sub>+b<sub>2</sub>, c<sub>1</sub>+c<sub>2</sub>, d<sub>1</sub>+d<sub>2</sub>) </code> </big>
|
||||
# Multiplication of a real number and a quaternion: <br> <big> <code> qr = rq = (ar, br, cr, dr) </code> </big>
|
||||
# Multiplication of two quaternions <big> <code> q<sub>1</sub> </code> </big> and <big><code>q<sub>2</sub> </code> </big> is given by: <br> <big> <code> ( a<sub>1</sub>a<sub>2</sub> − b<sub>1</sub>b<sub>2</sub> − c<sub>1</sub>c<sub>2</sub> − d<sub>1</sub>d<sub>2</sub>, </code> <br> <code> a<sub>1</sub>b<sub>2</sub> + b<sub>1</sub>a<sub>2</sub> + c<sub>1</sub>d<sub>2</sub> − d<sub>1</sub>c<sub>2</sub>, </code> <br> <code> a<sub>1</sub>c<sub>2</sub> − b<sub>1</sub>d<sub>2</sub> + c<sub>1</sub>a<sub>2</sub> + d<sub>1</sub>b<sub>2</sub>, </code> <br> <code> a<sub>1</sub>d<sub>2</sub> + b<sub>1</sub>c<sub>2</sub> − c<sub>1</sub>b<sub>2</sub> + d<sub>1</sub>a<sub>2</sub> ) </code> </big>
|
||||
# Show that, for the two quaternions <big> <code> q<sub>1</sub> </code> </big> and <big> <code> q<sub>2</sub>: <br> q<sub>1</sub>q<sub>2</sub> ≠ q<sub>2</sub>q<sub>1</sub> </code> </big>
|
||||
|
||||
<br>
|
||||
If a language has built-in support for quaternions, then use it.
|
||||
|
||||
|
||||
;C.f.:
|
||||
* [[Vector products]]
|
||||
* [http://www.maths.tcd.ie/pub/HistMath/People/Hamilton/QLetter/QLetter.pdf 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.
|
||||
<br><br>
|
||||
|
||||
#REDIRECT [[Quaternion]]
|
||||
|
|
|
|||
|
|
@ -1,259 +0,0 @@
|
|||
# -*- coding: utf-8 -*- #
|
||||
|
||||
COMMENT REQUIRES:
|
||||
MODE QUATSCAL = REAL; # Scalar #
|
||||
QUATSCAL quat small scal = small real;
|
||||
END COMMENT
|
||||
|
||||
# PROVIDES: #
|
||||
FORMAT quat scal fmt := $g(-0, 4)$;
|
||||
FORMAT signed fmt = $b("+", "")f(quat scal fmt)$;
|
||||
|
||||
FORMAT quat fmt = $f(quat scal fmt)"+"f(quat scal fmt)"i+"f(quat scal fmt)"j+"f(quat scal fmt)"k"$;
|
||||
FORMAT squat fmt = $f(signed fmt)f(signed fmt)"i"f(signed fmt)"j"f(signed fmt)"k"$;
|
||||
|
||||
MODE QUAT = STRUCT(QUATSCAL r, i, j, k);
|
||||
QUAT i=(0, 1, 0, 0),
|
||||
j=(0, 0, 1, 0),
|
||||
k=(0, 0, 0, 1);
|
||||
|
||||
MODE QUATCOSCAL = UNION(INT, SHORT REAL, SHORT INT);
|
||||
MODE QUATSUBSCAL = UNION(QUATCOSCAL, QUATSCAL);
|
||||
|
||||
MODE COMPLSCAL = STRUCT(QUATSCAL r, im);
|
||||
# compatable but not the same #
|
||||
MODE ISOQUAT = UNION([]REAL, []INT, []SHORT REAL, []SHORT INT, []QUATSCAL);
|
||||
MODE COQUAT = UNION(COMPLSCAL, QUATCOSCAL, ISOQUAT);
|
||||
MODE SUBQUAT = UNION(COQUAT, QUAT); # subset is itself #
|
||||
|
||||
MODE QUATERNION = QUAT;
|
||||
|
||||
PROC quat fix type error = (QUAT quat, []STRING msg)BOOL: (
|
||||
putf(stand error, ($"Type error:"$,$" "g$, msg, quat fmt, quat, $l$));
|
||||
stop
|
||||
);
|
||||
|
||||
COMMENT
|
||||
For a list of coercions expected in A68 c.f.
|
||||
* http://rosettacode.org/wiki/ALGOL_68#Coercion_.28casting.29 # ...
|
||||
|
||||
Pre-Strong context: Deproceduring, dereferencing & uniting. e.g. OP arguments
|
||||
* soft(deproceduring for assignment),
|
||||
* weak(dereferencing for slicing and OF selection),
|
||||
* meek(dereferencing for indexing, enquiries and PROC calls),
|
||||
* firm(uniting of OPerators),
|
||||
Strong context only: widening (INT=>REAL=>COMPL), rowing (REAL=>[]REAL) & voiding
|
||||
* strong(widening,rowing,voiding for identities/initialisations, arguments and casts et al)
|
||||
Key points:
|
||||
* arguments to OPerators do not widen or row!
|
||||
* UNITING is permitted in OP/String ccontext.
|
||||
|
||||
There are 4 principle scenerios for most operators:
|
||||
+---------------+-------------------------------+-------------------------------+
|
||||
| OP e.g. * | SCALar | QUATernion |
|
||||
+---------------+-------------------------------+-------------------------------+
|
||||
| SCALar | SCAL * SCAL ... inherit | SCAL * QUAT |
|
||||
+---------------+-------------------------------+-------------------------------+
|
||||
| QUATernion | QUAT * SCAL | QUAT * QUAT |
|
||||
+---------------+-------------------------------+-------------------------------+
|
||||
However this is compounded with SUBtypes of the SCALar & isomorphs the QUATernion,
|
||||
e.g.
|
||||
* SCAL may be a superset of SHORT REAL or INT - a widening coercion is required
|
||||
* QUAT may be a superset eg of COMPL or [4]INT
|
||||
* QUAT may be a structural isomorph eg of [4]REAL
|
||||
+---------------+---------------+---------------+---------------+---------------+
|
||||
| OP e.g. * | SUBSCAL | SCALar | COQUAT | QUATernion |
|
||||
+---------------+---------------+---------------+---------------+---------------+
|
||||
| SUBSCAL | | inherit | SUBSCAT*QUAT |
|
||||
+---------------+ inherit +---------------+---------------+
|
||||
| SCALar | | inherit | SCAL * QUAT |
|
||||
+---------------+---------------+---------------+---------------+---------------+
|
||||
| COQUAT | inherit | inherit | inherit | COQUAT*QUAT |
|
||||
+---------------+---------------+---------------+---------------+---------------+
|
||||
| QUATernion | QUAT*SUBSCAL | QUAT*SCAL | QUAT * COQUAT | QUAT * QUAT |
|
||||
+---------------+---------------+---------------+---------------+---------------+
|
||||
Keypoint: if an EXPLICIT QUAT is not involved, then we can simple inherit, OR QUATINIT!
|
||||
END COMMENT
|
||||
|
||||
MODE CLASSQUAT = STRUCT(
|
||||
PROC (REF QUAT #new#, QUATSCAL #r#, QUATSCAL #i#, QUATSCAL #j#, QUATSCAL #k#)REF QUAT new,
|
||||
PROC (REF QUAT #self#)QUAT conjugate,
|
||||
PROC (REF QUAT #self#)QUATSCAL norm sq,
|
||||
PROC (REF QUAT #self#)QUATSCAL norm,
|
||||
PROC (REF QUAT #self#)QUAT reciprocal,
|
||||
PROC (REF QUAT #self#)STRING repr,
|
||||
PROC (REF QUAT #self#)QUAT neg,
|
||||
PROC (REF QUAT #self#, SUBQUAT #other#)QUAT add,
|
||||
PROC (REF QUAT #self#, SUBQUAT #other#)QUAT radd,
|
||||
PROC (REF QUAT #self#, SUBQUAT #other#)QUAT sub,
|
||||
PROC (REF QUAT #self#, SUBQUAT #other#)QUAT mul,
|
||||
PROC (REF QUAT #self#, SUBQUAT #other#)QUAT rmul,
|
||||
PROC (REF QUAT #self#, SUBQUAT #other#)QUAT div,
|
||||
PROC (REF QUAT #self#, SUBQUAT #other#)QUAT rdiv,
|
||||
PROC (REF QUAT #self#)QUAT exp
|
||||
);
|
||||
|
||||
CLASSQUAT class quat = (
|
||||
|
||||
# PROC new =#(REF QUAT new, QUATSCAL r, i, j, k)REF QUAT: (
|
||||
# 'Defaults all parts of quaternion to zero' #
|
||||
IF new ISNT REF QUAT(NIL) THEN new ELSE HEAP QUAT FI := (r, i, j, k)
|
||||
),
|
||||
|
||||
# PROC conjugate =#(REF QUAT self)QUAT:
|
||||
(r OF self, -i OF self, -j OF self, -k OF self),
|
||||
|
||||
# PROC norm sq =#(REF QUAT self)QUATSCAL:
|
||||
r OF self**2 + i OF self**2 + j OF self**2 + k OF self**2,
|
||||
|
||||
# PROC norm =#(REF QUAT self)QUATSCAL:
|
||||
sqrt((norm sq OF class quat)(self)),
|
||||
|
||||
# PROC reciprocal =#(REF QUAT self)QUAT:(
|
||||
QUATSCAL n2 = (norm sq OF class quat)(self);
|
||||
QUAT conj = (conjugate OF class quat)(self);
|
||||
(r OF conj/n2, i OF conj/n2, j OF conj/n2, k OF conj/n2)
|
||||
),
|
||||
|
||||
# PROC repr =#(REF QUAT self)STRING: (
|
||||
# 'Shorter form of Quaternion as string' #
|
||||
FILE f; STRING s; associate(f, s);
|
||||
putf(f, (squat fmt, r OF self>=0, r OF self,
|
||||
i OF self>=0, i OF self, j OF self>=0, j OF self, k OF self>=0, k OF self));
|
||||
close(f);
|
||||
s
|
||||
),
|
||||
|
||||
# PROC neg =#(REF QUAT self)QUAT:
|
||||
(-r OF self, -i OF self, -j OF self, -k OF self),
|
||||
|
||||
# PROC add =#(REF QUAT self, SUBQUAT other)QUAT:
|
||||
CASE other IN
|
||||
(QUAT other): (r OF self + r OF other, i OF self + i OF other, j OF self + j OF other, k OF self + k OF other),
|
||||
(QUATSUBSCAL other): (r OF self + QUATSCALINIT other, i OF self, j OF self, k OF self)
|
||||
OUT IF quat fix type error(SKIP,"in add") THEN SKIP ELSE stop FI
|
||||
ESAC,
|
||||
|
||||
# PROC radd =#(REF QUAT self, SUBQUAT other)QUAT:
|
||||
(add OF class quat)(self, other),
|
||||
|
||||
# PROC sub =#(REF QUAT self, SUBQUAT other)QUAT:
|
||||
CASE other IN
|
||||
(QUAT other): (r OF self - r OF other, i OF self - i OF other, j OF self - j OF other, k OF self - k OF other),
|
||||
(QUATSCAL other): (r OF self - other, i OF self, j OF self, k OF self)
|
||||
OUT IF quat fix type error(self,"in sub") THEN SKIP ELSE stop FI
|
||||
ESAC,
|
||||
|
||||
# PROC mul =#(REF QUAT self, SUBQUAT other)QUAT:
|
||||
CASE other IN
|
||||
(QUAT other):(
|
||||
r OF self*r OF other - i OF self*i OF other - j OF self*j OF other - k OF self*k OF other,
|
||||
r OF self*i OF other + i OF self*r OF other + j OF self*k OF other - k OF self*j OF other,
|
||||
r OF self*j OF other - i OF self*k OF other + j OF self*r OF other + k OF self*i OF other,
|
||||
r OF self*k OF other + i OF self*j OF other - j OF self*i OF other + k OF self*r OF other
|
||||
),
|
||||
(QUATSCAL other): ( r OF self * other, i OF self * other, j OF self * other, k OF self * other)
|
||||
OUT IF quat fix type error(self,"in mul") THEN SKIP ELSE stop FI
|
||||
ESAC,
|
||||
|
||||
# PROC rmul =#(REF QUAT self, SUBQUAT other)QUAT:
|
||||
CASE other IN
|
||||
(QUAT other): (mul OF class quat)(LOC QUAT := other, self),
|
||||
(QUATSCAL other): (mul OF class quat)(self, other)
|
||||
OUT IF quat fix type error(self,"in rmul") THEN SKIP ELSE stop FI
|
||||
ESAC,
|
||||
|
||||
# PROC div =#(REF QUAT self, SUBQUAT other)QUAT:
|
||||
CASE other IN
|
||||
(QUAT other): (mul OF class quat)(self, (reciprocal OF class quat)(LOC QUAT := other)),
|
||||
(QUATSCAL other): (mul OF class quat)(self, 1/other)
|
||||
OUT IF quat fix type error(self,"in div") THEN SKIP ELSE stop FI
|
||||
ESAC,
|
||||
|
||||
# PROC rdiv =#(REF QUAT self, SUBQUAT other)QUAT:
|
||||
CASE other IN
|
||||
(QUAT other): (div OF class quat)(LOC QUAT := other, self),
|
||||
(QUATSCAL other): (div OF class quat)(LOC QUAT := (other, 0, 0, 0), self)
|
||||
OUT IF quat fix type error(self,"in rdiv") THEN SKIP ELSE stop FI
|
||||
ESAC,
|
||||
|
||||
# PROC exp =#(REF QUAT self)QUAT: (
|
||||
QUAT fac := self;
|
||||
QUAT sum := 1.0 + fac;
|
||||
FOR i FROM 2 TO bits width WHILE ABS(fac + quat small scal) /= quat small scal DO
|
||||
VOID(sum +:= (fac *:= self / ##QUATSCAL(i)))
|
||||
OD;
|
||||
sum
|
||||
)
|
||||
);
|
||||
|
||||
PRIO INIT = 1;
|
||||
OP QUATSCALINIT = (QUATSUBSCAL scal)QUATSCAL:
|
||||
CASE scal IN
|
||||
(INT scal): scal,
|
||||
(SHORT INT scal): scal,
|
||||
(SHORT REAL scal): scal
|
||||
OUT IF quat fix type error(SKIP,"in QUATSCALINIT") THEN SKIP ELSE stop FI
|
||||
ESAC;
|
||||
|
||||
OP INIT = (REF QUAT new, SUBQUAT from)REF QUAT:
|
||||
new :=
|
||||
CASE from IN
|
||||
(QUATSUBSCAL scal):(QUATSCALINIT scal, 0, 0, 0)
|
||||
#(COQUAT rijk):(new OF class quat)(LOC QUAT := new, rijk[1], rijk[2], rijk[3], rijk[4]),#
|
||||
OUT IF quat fix type error(SKIP,"in INIT") THEN SKIP ELSE stop FI
|
||||
ESAC;
|
||||
|
||||
|
||||
OP QUATINIT = (COQUAT lhs)REF QUAT: (HEAP QUAT)INIT lhs;
|
||||
|
||||
OP + = (QUAT q)QUAT: q,
|
||||
- = (QUAT q)QUAT: (neg OF class quat)(LOC QUAT := q),
|
||||
CONJ = (QUAT q)QUAT: (conjugate OF class quat)(LOC QUAT := q),
|
||||
ABS = (QUAT q)QUATSCAL: (norm OF class quat)(LOC QUAT := q),
|
||||
REPR = (QUAT q)STRING: (repr OF class quat)(LOC QUAT := q);
|
||||
# missing: Diadic: I, J, K END #
|
||||
|
||||
OP +:= = (REF QUAT a, QUAT b)QUAT: a:=( add OF class quat)(a, b),
|
||||
+:= = (REF QUAT a, COQUAT b)QUAT: a:=( add OF class quat)(a, b),
|
||||
+=: = (QUAT a, REF QUAT b)QUAT: b:=(radd OF class quat)(b, a),
|
||||
+=: = (COQUAT a, REF QUAT b)QUAT: b:=(radd OF class quat)(b, a);
|
||||
# missing: Worthy PLUSAB, PLUSTO for SHORT/LONG INT QUATSCAL & COMPL #
|
||||
|
||||
OP -:= = (REF QUAT a, QUAT b)QUAT: a:=( sub OF class quat)(a, b),
|
||||
-:= = (REF QUAT a, COQUAT b)QUAT: a:=( sub OF class quat)(a, b);
|
||||
# missing: Worthy MINUSAB for SHORT/LONG INT ##COQUAT & COMPL #
|
||||
|
||||
PRIO *=: = 1, /=: = 1;
|
||||
OP *:= = (REF QUAT a, QUAT b)QUAT: a:=( mul OF class quat)(a, b),
|
||||
*:= = (REF QUAT a, COQUAT b)QUAT: a:=( mul OF class quat)(a, b),
|
||||
*=: = (QUAT a, REF QUAT b)QUAT: b:=(rmul OF class quat)(b, a),
|
||||
*=: = (COQUAT a, REF QUAT b)QUAT: b:=(rmul OF class quat)(b, a);
|
||||
# missing: Worthy TIMESAB, TIMESTO for SHORT/LONG INT ##COQUAT & COMPL #
|
||||
|
||||
OP /:= = (REF QUAT a, QUAT b)QUAT: a:=( div OF class quat)(a, b),
|
||||
/:= = (REF QUAT a, COQUAT b)QUAT: a:=( div OF class quat)(a, b),
|
||||
/=: = (QUAT a, REF QUAT b)QUAT: b:=(rdiv OF class quat)(b, a),
|
||||
/=: = (COQUAT a, REF QUAT b)QUAT: b:=(rdiv OF class quat)(b, a);
|
||||
# missing: Worthy OVERAB, OVERTO for SHORT/LONG INT ##COQUAT & COMPL #
|
||||
|
||||
OP + = (QUAT a, b)QUAT: ( add OF class quat)(LOC QUAT := a, b),
|
||||
+ = (QUAT a, COQUAT b)QUAT: ( add OF class quat)(LOC QUAT := a, b),
|
||||
+ = (COQUAT a, QUAT b)QUAT: (radd OF class quat)(LOC QUAT := b, a);
|
||||
|
||||
OP - = (QUAT a, b)QUAT: ( sub OF class quat)(LOC QUAT := a, b),
|
||||
- = (QUAT a, COQUAT b)QUAT: ( sub OF class quat)(LOC QUAT := a, b),
|
||||
- = (COQUAT a, QUAT b)QUAT:-( sub OF class quat)(LOC QUAT := b, a);
|
||||
|
||||
OP * = (QUAT a, b)QUAT: ( mul OF class quat)(LOC QUAT := a, b),
|
||||
* = (QUAT a, COQUAT b)QUAT: ( mul OF class quat)(LOC QUAT := a, b),
|
||||
* = (COQUAT a, QUAT b)QUAT: (rmul OF class quat)(LOC QUAT := b, a);
|
||||
|
||||
OP / = (QUAT a, b)QUAT: ( div OF class quat)(LOC QUAT := a, b),
|
||||
/ = (QUAT a, COQUAT b)QUAT: ( div OF class quat)(LOC QUAT := a, b),
|
||||
/ = (COQUAT a, QUAT b)QUAT:
|
||||
( div OF class quat)(LOC QUAT := QUATINIT 1, a);
|
||||
|
||||
PROC quat exp = (QUAT q)QUAT: (exp OF class quat)(LOC QUAT := q);
|
||||
|
||||
SKIP # missing: quat arc{sin, cos, tan}h, log, exp, ln etc END #
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
#!/usr/bin/a68g --script #
|
||||
# -*- coding: utf-8 -*- #
|
||||
|
||||
# REQUIRES: #
|
||||
MODE QUATSCAL = REAL; # Scalar #
|
||||
QUATSCAL quat small scal = small real;
|
||||
|
||||
PR READ "prelude/Quaternion.a68" PR;
|
||||
|
||||
test:(
|
||||
REAL r = 7;
|
||||
QUAT q = (1, 2, 3, 4),
|
||||
q1 = (2, 3, 4, 5),
|
||||
q2 = (3, 4, 5, 6);
|
||||
|
||||
printf((
|
||||
$"r = " f(quat scal fmt)l$, r,
|
||||
$"q = " f(quat fmt)l$, q,
|
||||
$"q1 = " f(quat fmt)l$, q1,
|
||||
$"q2 = " f(quat fmt)l$, q2,
|
||||
$"ABS q = " f(quat scal fmt)", "$, ABS q,
|
||||
$"ABS q1 = " f(quat scal fmt)", "$, ABS q1,
|
||||
$"ABS q2 = " f(quat scal fmt)l$, ABS q2,
|
||||
$"-q = " f(quat fmt)l$, -q,
|
||||
$"CONJ q = " f(quat fmt)l$, CONJ q,
|
||||
$"r + q = " f(quat fmt)l$, r + q,
|
||||
$"q + r = " f(quat fmt)l$, q + r,
|
||||
$"q1 + q2 = "f(quat fmt)l$, q1 + q2,
|
||||
$"q2 + q1 = "f(quat fmt)l$, q2 + q1,
|
||||
$"q * r = " f(quat fmt)l$, q * r,
|
||||
$"r * q = " f(quat fmt)l$, r * q,
|
||||
$"q1 * q2 = "f(quat fmt)l$, q1 * q2,
|
||||
$"q2 * q1 = "f(quat fmt)l$, q2 * q1
|
||||
));
|
||||
|
||||
CO
|
||||
$"ASSERT q1 * q2 != q2 * q1 = "f(quat fmt)l$, ASSERT q1 * q2 != q2 * q1, $l$;
|
||||
END CO
|
||||
|
||||
printf((
|
||||
$"i*i = " f(quat fmt)l$, i*i,
|
||||
$"j*j = " f(quat fmt)l$, j*j,
|
||||
$"k*k = " f(quat fmt)l$, k*k,
|
||||
$"i*j*k = " f(quat fmt)l$, i*j*k,
|
||||
$"q1 / q2 = " f(quat fmt)l$, q1 / q2,
|
||||
$"q1 / q2 * q2 = "f(quat fmt)l$, q1 / q2 * q2,
|
||||
$"q2 * q1 / q2 = "f(quat fmt)l$, q2 * q1 / q2,
|
||||
$"1/q1 * q1 = " f(quat fmt)l$, 1.0/q1 * q1,
|
||||
$"q1 / q1 = " f(quat fmt)l$, q1 / q1,
|
||||
$"quat exp(pi * i) = " f(quat fmt)l$, quat exp(pi * i),
|
||||
$"quat exp(pi * j) = " f(quat fmt)l$, quat exp(pi * j),
|
||||
$"quat exp(pi * k) = " f(quat fmt)l$, quat exp(pi * k)
|
||||
));
|
||||
print((REPR(-q1*q2), ", ", REPR(-q2*q1), new line))
|
||||
)
|
||||
|
|
@ -1,101 +0,0 @@
|
|||
begin
|
||||
% Quaternion record type %
|
||||
record Quaternion ( real a, b, c, d );
|
||||
|
||||
% returns the norm of the specified quaternion %
|
||||
real procedure normQ ( reference(Quaternion) value q ) ;
|
||||
sqrt( (a(q) * a(q)) + (b(q) * b(q)) + (c(q) * c(q)) + (d(q) * d(q)) );
|
||||
|
||||
% returns the negative of the specified quaternion %
|
||||
reference(Quaternion) procedure negQ ( reference(Quaternion) value q ) ;
|
||||
Quaternion( - a(q), - b(q), - c(q), - d(q) );
|
||||
|
||||
% returns the conjugate of the specified quaternion %
|
||||
reference(Quaternion) procedure conjQ ( reference(Quaternion) value q ) ;
|
||||
Quaternion( a(q), - b(q), - c(q), - d(q) );
|
||||
|
||||
% returns the sum of a real and a quaternion %
|
||||
reference(Quaternion) procedure addRQ ( real value r
|
||||
; reference(Quaternion) value q
|
||||
) ;
|
||||
Quaternion( r + a(q), b(q), c(q), d(q) );
|
||||
|
||||
% returns the sum of a quaternion and a real %
|
||||
reference(Quaternion) procedure addQR ( reference(Quaternion) value q
|
||||
; real value r
|
||||
) ;
|
||||
Quaternion( r + a(q), b(q), c(q), d(q) );
|
||||
|
||||
% returns the sum of the specified quaternions %
|
||||
reference(Quaternion) procedure addQQ ( reference(Quaternion) value q1
|
||||
; reference(Quaternion) value q2
|
||||
) ;
|
||||
Quaternion( a(q1) + a(q2), b(q1) + b(q2), c(q1) + c(q2), d(q1) + d(q2) );
|
||||
|
||||
% returns the specified quaternion multiplied by a real %
|
||||
reference(Quaternion) procedure mulQR ( reference(Quaternion) value q
|
||||
; real value r
|
||||
) ;
|
||||
Quaternion( r * a(q), r * b(q), r * c(q), r * d(q) );
|
||||
|
||||
% returns a real multiplied by the specified quaternion %
|
||||
reference(Quaternion) procedure mulRQ ( real value r
|
||||
; reference(Quaternion) value q
|
||||
) ;
|
||||
mulQR( q, r );
|
||||
|
||||
% returns the Quaternion product of the specified quaternions %
|
||||
reference(Quaternion) procedure mulQQ( reference(Quaternion) value q1
|
||||
; reference(Quaternion) value q2
|
||||
) ;
|
||||
Quaternion( (a(q1) * a(q2)) - (b(q1) * b(q2)) - (c(q1) * c(q2)) - (d(q1) * d(q2))
|
||||
, (a(q1) * b(q2)) + (b(q1) * a(q2)) + (c(q1) * d(q2)) - (d(q1) * c(q2))
|
||||
, (a(q1) * c(q2)) - (b(q1) * d(q2)) + (c(q1) * a(q2)) + (d(q1) * b(q2))
|
||||
, (a(q1) * d(q2)) + (b(q1) * c(q2)) - (c(q1) * b(q2)) + (d(q1) * a(q2))
|
||||
);
|
||||
|
||||
% returns true if the two quaternions are equal, false otherwise %
|
||||
logical procedure equalQ( reference(Quaternion) value q1
|
||||
; reference(Quaternion) value q2
|
||||
) ;
|
||||
a(q1) = a(q2) and b(q1) = b(q2) and c(q1) = c(q2) and d(q1) = d(q2);
|
||||
|
||||
% writes a quaternion %
|
||||
procedure writeonQ( reference(Quaternion) value q ) ;
|
||||
writeon( "(", a(q), ", ", b(q), ", ", c(q), ", ", d(q), ")" );
|
||||
|
||||
|
||||
% test q1q2 = q2q1 %
|
||||
reference(Quaternion) q, q1, q2;
|
||||
|
||||
q := Quaternion( 1, 2, 3, 4 );
|
||||
q1 := Quaternion( 2, 3, 4, 5 );
|
||||
q2 := Quaternion( 3, 4, 5, 6 );
|
||||
|
||||
% set output format %
|
||||
s_w := 0; r_format := "A"; r_w := 5; r_d := 1;
|
||||
|
||||
write( " q:" );writeonQ( q );
|
||||
write( " q1:" );writeonQ( q1 );
|
||||
write( " q2:" );writeonQ( q2 );
|
||||
write( "norm q:" );writeon( normQ( q ) );
|
||||
write( "norm q1:" );writeon( normQ( q1 ) );
|
||||
write( "norm q2:" );writeon( normQ( q2 ) );
|
||||
|
||||
write( " conj q:" );writeonQ( conjQ( q ) );
|
||||
write( " - q:" );writeonQ( negQ( q ) );
|
||||
write( " 7 + q:" );writeonQ( addRQ( 7, q ) );
|
||||
write( " q + 9:" );writeonQ( addQR( q, 9 ) );
|
||||
write( " q + q1:" );writeonQ( addQQ( q, q1 ) );
|
||||
write( " 3 * q:" );writeonQ( mulRQ( 3, q ) );
|
||||
write( " q * 4:" );writeonQ( mulQR( q, 4 ) );
|
||||
|
||||
% check that q1q2 not = q2q1 %
|
||||
if equalQ( mulQQ( q1, q2 ), mulQQ( q2, q1 ) )
|
||||
then write( "q1q2 = q2q1 ??" )
|
||||
else write( "q1q2 <> q2q1" );
|
||||
|
||||
write( " q1q2:" );writeonQ( mulQQ( q1, q2 ) );
|
||||
write( " q2q1:" );writeonQ( mulQQ( q2, q1 ) );
|
||||
|
||||
end.
|
||||
|
|
@ -1,266 +0,0 @@
|
|||
//--------------------------------------------------------------------
|
||||
|
||||
#include "share/atspre_staload.hats"
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
(* Here is one way to get a sqrt function without going beyond the ATS
|
||||
prelude. The prelude (at the time of this writing) contains some
|
||||
templates for which implementations were never added. Here I add an
|
||||
implementation.
|
||||
|
||||
The ats2-xprelude package at
|
||||
https://sourceforge.net/p/chemoelectric/ats2-xprelude contains a
|
||||
much more extensive and natural interface to the C math library. *)
|
||||
|
||||
%{^
|
||||
#include <math.h>
|
||||
%}
|
||||
|
||||
implement (* "Generic" square root. *)
|
||||
gsqrt_val<double> x =
|
||||
(* Call "sqrt" from the C math library. *)
|
||||
$extfcall (double, "sqrt", x)
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
abst@ype quaternion (tk : tkind) =
|
||||
(* The following determines the SIZE of a quaternion, but not its
|
||||
actual representation: *)
|
||||
@(g0float tk, g0float tk, g0float tk, g0float tk)
|
||||
|
||||
extern fn {tk : tkind} quaternion_make :
|
||||
(g0float tk, g0float tk, g0float tk, g0float tk) -<> quaternion tk
|
||||
|
||||
extern fn {tk : tkind} fprint_quaternion :
|
||||
(FILEref, quaternion tk) -> void
|
||||
extern fn {tk : tkind} print_quaternion :
|
||||
quaternion tk -> void
|
||||
|
||||
extern fn {tk : tkind} quaternion_norm_squared :
|
||||
quaternion tk -<> g0float tk
|
||||
extern fn {tk : tkind} quaternion_norm :
|
||||
quaternion tk -< !exn > g0float tk
|
||||
|
||||
extern fn {tk : tkind} quaternion_neg :
|
||||
quaternion tk -<> quaternion tk
|
||||
extern fn {tk : tkind} quaternion_conj :
|
||||
quaternion tk -<> quaternion tk
|
||||
|
||||
extern fn {tk : tkind} add_quaternion_g0float :
|
||||
(quaternion tk, g0float tk) -<> quaternion tk
|
||||
extern fn {tk : tkind} add_g0float_quaternion :
|
||||
(g0float tk, quaternion tk) -<> quaternion tk
|
||||
extern fn {tk : tkind} add_quaternion_quaternion :
|
||||
(quaternion tk, quaternion tk) -<> quaternion tk
|
||||
|
||||
extern fn {tk : tkind} mul_quaternion_g0float :
|
||||
(quaternion tk, g0float tk) -<> quaternion tk
|
||||
extern fn {tk : tkind} mul_g0float_quaternion :
|
||||
(g0float tk, quaternion tk) -<> quaternion tk
|
||||
extern fn {tk : tkind} mul_quaternion_quaternion :
|
||||
(quaternion tk, quaternion tk) -<> quaternion tk
|
||||
|
||||
extern fn {tk : tkind} quaternion_eq :
|
||||
(quaternion tk, quaternion tk) -<> bool
|
||||
|
||||
overload fprint with fprint_quaternion
|
||||
overload print with print_quaternion
|
||||
|
||||
overload norm_squared with quaternion_norm_squared
|
||||
overload norm with quaternion_norm
|
||||
|
||||
overload ~ with quaternion_neg
|
||||
overload conj with quaternion_conj
|
||||
|
||||
overload + with add_quaternion_g0float
|
||||
overload + with add_g0float_quaternion
|
||||
overload + with add_quaternion_quaternion
|
||||
|
||||
overload * with mul_quaternion_g0float
|
||||
overload * with mul_g0float_quaternion
|
||||
overload * with mul_quaternion_quaternion
|
||||
|
||||
overload = with quaternion_eq
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
local
|
||||
|
||||
(* Now we decide the REPRESENTATION of a quaternion. A quaternion is
|
||||
represented as an unboxed 4-tuple of "real" numbers of any one
|
||||
particular typekind. *)
|
||||
typedef _quaternion (tk : tkind) =
|
||||
@(g0float tk, g0float tk, g0float tk, g0float tk)
|
||||
|
||||
assume quaternion tk = _quaternion tk
|
||||
|
||||
in (* local *)
|
||||
|
||||
implement {tk}
|
||||
quaternion_make (a, b, c, d) =
|
||||
@(a, b, c, d)
|
||||
|
||||
implement {tk}
|
||||
fprint_quaternion (outf, q) =
|
||||
let
|
||||
typedef t = g0float tk
|
||||
val @(a, b, c, d) = q
|
||||
in
|
||||
fprint_val<t> (outf, a);
|
||||
if g0i2f 0 <= b then fprint_val<string> (outf, "+");
|
||||
fprint_val<t> (outf, b);
|
||||
fprint_val<string> (outf, "i");
|
||||
if g0i2f 0 <= c then fprint_val<string> (outf, "+");
|
||||
fprint_val<t> (outf, c);
|
||||
fprint_val<string> (outf, "j");
|
||||
if g0i2f 0 <= d then fprint_val<string> (outf, "+");
|
||||
fprint_val<t> (outf, d);
|
||||
fprint_val<string> (outf, "k");
|
||||
end
|
||||
|
||||
implement {tk}
|
||||
print_quaternion q =
|
||||
fprint_quaternion (stdout_ref, q)
|
||||
|
||||
implement {tk}
|
||||
quaternion_norm_squared q =
|
||||
let
|
||||
val @(a, b, c, d) = q
|
||||
in
|
||||
(a * a) + (b * b) + (c * c) + (d * d)
|
||||
end
|
||||
|
||||
implement {tk}
|
||||
quaternion_norm q =
|
||||
gsqrt_val<g0float tk> (quaternion_norm_squared q)
|
||||
|
||||
implement {tk}
|
||||
quaternion_neg q =
|
||||
let
|
||||
val @(a, b, c, d) = q
|
||||
in
|
||||
@(~a, ~b, ~c, ~d)
|
||||
end
|
||||
|
||||
implement {tk}
|
||||
quaternion_conj q =
|
||||
let
|
||||
val @(a, b, c, d) = q
|
||||
in
|
||||
@(a, ~b, ~c, ~d)
|
||||
end
|
||||
|
||||
implement {tk}
|
||||
add_quaternion_g0float (q, r) =
|
||||
let
|
||||
val @(a, b, c, d) = q
|
||||
in
|
||||
@(a + r, b, c, d)
|
||||
end
|
||||
|
||||
implement {tk}
|
||||
add_g0float_quaternion (r, q) =
|
||||
let
|
||||
val @(a, b, c, d) = q
|
||||
in
|
||||
@(r + a, b, c, d)
|
||||
end
|
||||
|
||||
implement {tk}
|
||||
add_quaternion_quaternion (q1, q2) =
|
||||
let
|
||||
val @(a1, b1, c1, d1) = q1
|
||||
and @(a2, b2, c2, d2) = q2
|
||||
in
|
||||
@(a1 + a2, b1 + b2, c1 + c2, d1 + d2)
|
||||
end
|
||||
|
||||
implement {tk}
|
||||
mul_quaternion_g0float (q, r) =
|
||||
let
|
||||
val @(a, b, c, d) = q
|
||||
in
|
||||
@(a * r, b * r, c * r, d * r)
|
||||
end
|
||||
|
||||
implement {tk}
|
||||
mul_g0float_quaternion (r, q) =
|
||||
let
|
||||
val @(a, b, c, d) = q
|
||||
in
|
||||
@(r * a, r * b, r * c, r * d)
|
||||
end
|
||||
|
||||
implement {tk}
|
||||
mul_quaternion_quaternion (q1, q2) =
|
||||
let
|
||||
val @(a1, b1, c1, d1) = q1
|
||||
and @(a2, b2, c2, d2) = q2
|
||||
in
|
||||
@((a1 * a2) - (b1 * b2) - (c1 * c2) - (d1 * d2),
|
||||
(a1 * b2) + (b1 * a2) + (c1 * d2) - (d1 * c2),
|
||||
(a1 * c2) - (b1 * d2) + (c1 * a2) + (d1 * b2),
|
||||
(a1 * d2) + (b1 * c2) - (c1 * b2) + (d1 * a2))
|
||||
end
|
||||
|
||||
implement {tk}
|
||||
quaternion_eq (q1, q2) =
|
||||
let
|
||||
val @(a1, b1, c1, d1) = q1
|
||||
and @(a2, b2, c2, d2) = q2
|
||||
in
|
||||
(a1 = a2) * (b1 = b2) * (c1 = c2) * (d1 = d2)
|
||||
end
|
||||
|
||||
end (* local *)
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
val q = quaternion_make (1.0, 2.0, 3.0, 4.0)
|
||||
and q1 = quaternion_make (2.0, 3.0, 4.0, 5.0)
|
||||
and q2 = quaternion_make (3.0, 4.0, 5.0, 6.0)
|
||||
and r = 7.0
|
||||
|
||||
implement
|
||||
main0 () =
|
||||
let
|
||||
(* Let us print double precision numbers in a format more readable
|
||||
than is the prelude's default. *)
|
||||
implement
|
||||
fprint_val<double> (outf, x) =
|
||||
let
|
||||
typedef f = $extype"FILE *"
|
||||
val _ = $extfcall (int, "fprintf", $UNSAFE.cast{f} outf,
|
||||
"%g", x)
|
||||
in
|
||||
end
|
||||
in
|
||||
println! ("q = ", q);
|
||||
println! ("q1 = ", q1);
|
||||
println! ("q2 = ", q2);
|
||||
println! ();
|
||||
println! ("||q|| = ", norm q);
|
||||
println! ("||q1|| = ", norm q1);
|
||||
println! ("||q2|| = ", norm q2);
|
||||
println! ();
|
||||
println! ("-q = ", ~q);
|
||||
println! ("-q1 = ", ~q1);
|
||||
println! ("-q2 = ", ~q2);
|
||||
println! ();
|
||||
println! ("conj q = ", conj q);
|
||||
println! ("conj q1 = ", conj q1);
|
||||
println! ("conj q2 = ", conj q2);
|
||||
println! ();
|
||||
println! ("q + r = ", q + r);
|
||||
println! ("r + q = ", r + q);
|
||||
println! ("q1 + q2 = ", q1 + q2);
|
||||
println! ();
|
||||
println! ("q * r = ", q * r);
|
||||
println! ("r * q = ", r * q);
|
||||
println! ("q1 * q2 = ", q1 * q2);
|
||||
println! ("q2 * q1 = ", q2 * q1);
|
||||
println! ("((q1 * q2) = (q2 * q1)) is ", (q1 * q2) = (q2 * q1))
|
||||
end
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
|
@ -1,164 +0,0 @@
|
|||
INCLUDE "H6:REALMATH.ACT"
|
||||
|
||||
DEFINE A_="+0"
|
||||
DEFINE B_="+6"
|
||||
DEFINE C_="+12"
|
||||
DEFINE D_="+18"
|
||||
|
||||
TYPE Quaternion=[CARD a1,a2,a3,b1,b2,b3,c1,c2,c3,d1,d2,d3]
|
||||
REAL neg
|
||||
|
||||
PROC Init()
|
||||
ValR("-1",neg)
|
||||
RETURN
|
||||
|
||||
BYTE FUNC Positive(REAL POINTER x)
|
||||
BYTE ARRAY tmp
|
||||
|
||||
tmp=x
|
||||
IF (tmp(0)&$80)=$00 THEN
|
||||
RETURN (1)
|
||||
FI
|
||||
RETURN (0)
|
||||
|
||||
PROC PrintQuat(Quaternion POINTER q)
|
||||
PrintR(q A_)
|
||||
IF Positive(q B_) THEN Put('+) FI
|
||||
PrintR(q B_) Put('i)
|
||||
IF Positive(q C_) THEN Put('+) FI
|
||||
PrintR(q C_) Put('j)
|
||||
IF Positive(q D_) THEN Put('+) FI
|
||||
PrintR(q D_) Put('k)
|
||||
RETURN
|
||||
|
||||
PROC PrintQuatE(Quaternion POINTER q)
|
||||
PrintQuat(q) PutE()
|
||||
RETURN
|
||||
|
||||
PROC QuatIntInit(Quaternion POINTER q INT ia,ib,ic,id)
|
||||
IntToReal(ia,q A_)
|
||||
IntToReal(ib,q B_)
|
||||
IntToReal(ic,q C_)
|
||||
IntToReal(id,q D_)
|
||||
RETURN
|
||||
|
||||
PROC Sqr(REAL POINTER a,b)
|
||||
RealMult(a,a,b)
|
||||
RETURN
|
||||
|
||||
PROC QuatNorm(Quaternion POINTER q REAL POINTER res)
|
||||
REAL r1,r2,r3
|
||||
|
||||
Sqr(q A_,r1) ;r1=q.a^2
|
||||
Sqr(q B_,r2) ;r2=q.b^2
|
||||
RealAdd(r1,r2,r3) ;r3=q.a^2+q.b^2
|
||||
Sqr(q C_,r1) ;r1=q.c^2
|
||||
RealAdd(r3,r1,r2) ;r2=q.a^2+q.b^2+q.c^2
|
||||
Sqr(q D_,r1) ;r1=q.d^2
|
||||
RealAdd(r2,r1,r3) ;r3=q.a^2+q.b^2+q.c^2+q.d^2
|
||||
Sqrt(r3,res) ;res=sqrt(q.a^2+q.b^2+q.c^2+q.d^2)
|
||||
RETURN
|
||||
|
||||
PROC QuatNegative(Quaternion POINTER q,res)
|
||||
RealMult(q A_,neg,res A_) ;res.a=-q.a
|
||||
RealMult(q B_,neg,res B_) ;res.b=-q.b
|
||||
RealMult(q C_,neg,res C_) ;res.c=-q.c
|
||||
RealMult(q D_,neg,res D_) ;res.d=-q.d
|
||||
RETURN
|
||||
|
||||
PROC QuatConjugate(Quaternion POINTER q,res)
|
||||
RealAssign(q A_,res A_) ;res.a=q.a
|
||||
RealMult(q B_,neg,res B_) ;res.b=-q.b
|
||||
RealMult(q C_,neg,res C_) ;res.c=-q.c
|
||||
RealMult(q D_,neg,res D_) ;res.d=-q.d
|
||||
RETURN
|
||||
|
||||
PROC QuatAddReal(Quaternion POINTER q REAL POINTER r
|
||||
Quaternion POINTER res)
|
||||
RealAdd(q A_,r,res A_) ;res.a=q.a+r
|
||||
RealAssign(q B_,res B_) ;res.b=q.b
|
||||
RealAssign(q C_,res C_) ;res.c=q.c
|
||||
RealAssign(q D_,res D_) ;res.d=q.d
|
||||
RETURN
|
||||
|
||||
PROC QuatAdd(Quaternion POINTER q1,q2,res)
|
||||
RealAdd(q1 A_,q2 A_,res A_) ;res.a=q1.a+q2.a
|
||||
RealAdd(q1 B_,q2 B_,res B_) ;res.b=q1.b+q2.b
|
||||
RealAdd(q1 C_,q2 C_,res C_) ;res.c=q1.c+q2.c
|
||||
RealAdd(q1 D_,q2 D_,res D_) ;res.d=q1.d+q2.d
|
||||
RETURN
|
||||
|
||||
PROC QuatMultReal(Quaternion POINTER q REAL POINTER r
|
||||
Quaternion POINTER res)
|
||||
RealMult(q A_,r,res A_) ;res.a=q.a*r
|
||||
RealMult(q B_,r,res B_) ;res.b=q.b*r
|
||||
RealMult(q C_,r,res C_) ;res.c=q.c*r
|
||||
RealMult(q D_,r,res D_) ;res.d=q.d*r
|
||||
RETURN
|
||||
|
||||
PROC QuatMult(Quaternion POINTER q1,q2,res)
|
||||
REAL r1,r2
|
||||
|
||||
RealMult(q1 A_,q2 A_,r1) ;r1=q1.a*q2.a
|
||||
RealMult(q1 B_,q2 B_,r2) ;r2=q1.b*q2.b
|
||||
RealSub(r1,r2,r3) ;r3=q1.a*q2.a-q1.b*q2.b
|
||||
RealMult(q1 C_,q2 C_,r1) ;r1=q1.c*q2.c
|
||||
RealSub(r3,r1,r2) ;r2=q1.a*q2.a-q1.b*q2.b-q1.c*q2.c
|
||||
RealMult(q1 D_,q2 D_,r1) ;r1=q1.d*q2.d
|
||||
RealSub(r2,r1,res A_) ;res.a=q1.a*q2.a-q1.b*q2.b-q1.c*q2.c-q1.d*q2.d
|
||||
|
||||
RealMult(q1 A_,q2 B_,r1) ;r1=q1.a*q2.b
|
||||
RealMult(q1 B_,q2 A_,r2) ;r2=q1.b*q2.a
|
||||
RealAdd(r1,r2,r3) ;r3=q1.a*q2.b+q1.b*q2.a
|
||||
RealMult(q1 C_,q2 D_,r1) ;r1=q1.c*q2.d
|
||||
RealAdd(r3,r1,r2) ;r2=q1.a*q2.b+q1.b*q2.a+q1.c*q2.d
|
||||
RealMult(q1 D_,q2 C_,r1) ;r1=q1.d*q2.c
|
||||
RealSub(r2,r1,res B_) ;res.b=q1.a*q2.b+q1.b*q2.a+q1.c*q2.d-q1.d*q2.c
|
||||
|
||||
RealMult(q1 A_,q2 C_,r1) ;r1=q1.a*q2.c
|
||||
RealMult(q1 B_,q2 D_,r2) ;r2=q1.b*q2.d
|
||||
RealSub(r1,r2,r3) ;r3=q1.a*q2.c-q1.b*q2.d
|
||||
RealMult(q1 C_,q2 A_,r1) ;r1=q1.c*q2.a
|
||||
RealAdd(r3,r1,r2) ;r2=q1.a*q2.c-q1.b*q2.d+q1.c*q2.a
|
||||
RealMult(q1 D_,q2 B_,r1) ;r1=q1.d*q2.b
|
||||
RealAdd(r2,r1,res C_) ;res.c=q1.a*q2.c-q1.b*q2.d+q1.c*q2.a+q1.d*q2.b
|
||||
|
||||
RealMult(q1 A_,q2 D_,r1) ;r1=q1.a*q2.d
|
||||
RealMult(q1 B_,q2 C_,r2) ;r2=q1.b*q2.c
|
||||
RealAdd(r1,r2,r3) ;r3=q1.a*q2.d+q1.b*q2.c
|
||||
RealMult(q1 C_,q2 B_,r1) ;r1=q1.c*q2.b
|
||||
RealSub(r3,r1,r2) ;r2=q1.a*q2.d+q1.b*q2.c-q1.c*q2.b
|
||||
RealMult(q1 D_,q2 A_,r1) ;r1=q1.d*q2.a
|
||||
RealAdd(r2,r1,res D_) ;res.d=q1.a*q2.d+q1.b*q2.c-q1.c*q2.b+q1.d*q2.a
|
||||
RETURN
|
||||
|
||||
PROC Main()
|
||||
Quaternion q,q1,q2,q3
|
||||
REAL r,r2
|
||||
|
||||
Put(125) PutE() ;clear the screen
|
||||
MathInit()
|
||||
Init()
|
||||
|
||||
QuatIntInit(q,1,2,3,4)
|
||||
QuatIntInit(q1,2,3,4,5)
|
||||
QuatIntInit(q2,3,4,5,6)
|
||||
IntToReal(7,r)
|
||||
|
||||
Print(" q = ") PrintQuatE(q)
|
||||
Print("q1 = ") PrintQuatE(q1)
|
||||
Print("q2 = ") PrintQuatE(q2)
|
||||
Print(" r = ") PrintRE(r) PutE()
|
||||
|
||||
QuatNorm(q,r2) Print(" Norm(q) = ") PrintRE(r2)
|
||||
QuatNorm(q1,r2) Print("Norm(q1) = ") PrintRE(r2)
|
||||
QuatNorm(q2,r2) Print("Norm(q2) = ") PrintRE(r2)
|
||||
QuatNegative(q,q3) Print(" -q = ") PrintQuatE(q3)
|
||||
QuatConjugate(q,q3) Print(" Conj(q) = ") PrintQuatE(q3)
|
||||
QuatAddReal(q,r,q3) Print(" q+r = ") PrintQuatE(q3)
|
||||
QuatAdd(q1,q2,q3) Print(" q1+q2 = ") PrintQuatE(q3)
|
||||
QuatAdd(q2,q1,q3) Print(" q2+q1 = ") PrintQuatE(q3)
|
||||
QuatMultReal(q,r,q3) Print(" q*r = ") PrintQuatE(q3)
|
||||
QuatMult(q1,q2,q3) Print(" q1*q2 = ") PrintQuatE(q3)
|
||||
QuatMult(q2,q1,q3) Print(" q2*q1 = ") PrintQuatE(q3)
|
||||
RETURN
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
generic
|
||||
type Real is digits <>;
|
||||
package Quaternions is
|
||||
type Quaternion is record
|
||||
A, B, C, D : Real;
|
||||
end record;
|
||||
function "abs" (Left : Quaternion) return Real;
|
||||
function Conj (Left : Quaternion) return Quaternion;
|
||||
function "-" (Left : Quaternion) return Quaternion;
|
||||
function "+" (Left, Right : Quaternion) return Quaternion;
|
||||
function "-" (Left, Right : Quaternion) return Quaternion;
|
||||
function "*" (Left : Quaternion; Right : Real) return Quaternion;
|
||||
function "*" (Left : Real; Right : Quaternion) return Quaternion;
|
||||
function "*" (Left, Right : Quaternion) return Quaternion;
|
||||
function Image (Left : Quaternion) return String;
|
||||
end Quaternions;
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
with Ada.Numerics.Generic_Elementary_Functions;
|
||||
package body Quaternions is
|
||||
package Elementary_Functions is
|
||||
new Ada.Numerics.Generic_Elementary_Functions (Real);
|
||||
use Elementary_Functions;
|
||||
function "abs" (Left : Quaternion) return Real is
|
||||
begin
|
||||
return Sqrt (Left.A**2 + Left.B**2 + Left.C**2 + Left.D**2);
|
||||
end "abs";
|
||||
function Conj (Left : Quaternion) return Quaternion is
|
||||
begin
|
||||
return (A => Left.A, B => -Left.B, C => -Left.C, D => -Left.D);
|
||||
end Conj;
|
||||
function "-" (Left : Quaternion) return Quaternion is
|
||||
begin
|
||||
return (A => -Left.A, B => -Left.B, C => -Left.C, D => -Left.D);
|
||||
end "-";
|
||||
function "+" (Left, Right : Quaternion) return Quaternion is
|
||||
begin
|
||||
return
|
||||
( A => Left.A + Right.A, B => Left.B + Right.B,
|
||||
C => Left.C + Right.C, D => Left.D + Right.D
|
||||
);
|
||||
end "+";
|
||||
function "-" (Left, Right : Quaternion) return Quaternion is
|
||||
begin
|
||||
return
|
||||
( A => Left.A - Right.A, B => Left.B - Right.B,
|
||||
C => Left.C - Right.C, D => Left.D - Right.D
|
||||
);
|
||||
end "-";
|
||||
function "*" (Left : Quaternion; Right : Real) return Quaternion is
|
||||
begin
|
||||
return
|
||||
( A => Left.A * Right, B => Left.B * Right,
|
||||
C => Left.C * Right, D => Left.D * Right
|
||||
);
|
||||
end "*";
|
||||
function "*" (Left : Real; Right : Quaternion) return Quaternion is
|
||||
begin
|
||||
return Right * Left;
|
||||
end "*";
|
||||
function "*" (Left, Right : Quaternion) return Quaternion is
|
||||
begin
|
||||
return
|
||||
( A => Left.A * Right.A - Left.B * Right.B - Left.C * Right.C - Left.D * Right.D,
|
||||
B => Left.A * Right.B + Left.B * Right.A + Left.C * Right.D - Left.D * Right.C,
|
||||
C => Left.A * Right.C - Left.B * Right.D + Left.C * Right.A + Left.D * Right.B,
|
||||
D => Left.A * Right.D + Left.B * Right.C - Left.C * Right.B + Left.D * Right.A
|
||||
);
|
||||
end "*";
|
||||
function Image (Left : Quaternion) return String is
|
||||
begin
|
||||
return Real'Image (Left.A) & " +" &
|
||||
Real'Image (Left.B) & "i +" &
|
||||
Real'Image (Left.C) & "j +" &
|
||||
Real'Image (Left.D) & "k";
|
||||
end Image;
|
||||
end Quaternions;
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
with Ada.Text_IO; use Ada.Text_IO;
|
||||
with Quaternions;
|
||||
procedure Test_Quaternion is
|
||||
package Float_Quaternion is new Quaternions (Float);
|
||||
use Float_Quaternion;
|
||||
q : Quaternion := (1.0, 2.0, 3.0, 4.0);
|
||||
q1 : Quaternion := (2.0, 3.0, 4.0, 5.0);
|
||||
q2 : Quaternion := (3.0, 4.0, 5.0, 6.0);
|
||||
r : Float := 7.0;
|
||||
begin
|
||||
Put_Line ("q = " & Image (q));
|
||||
Put_Line ("q1 = " & Image (q1));
|
||||
Put_Line ("q2 = " & Image (q2));
|
||||
Put_Line ("r =" & Float'Image (r));
|
||||
Put_Line ("abs q =" & Float'Image (abs q));
|
||||
Put_Line ("abs q1 =" & Float' Image (abs q1));
|
||||
Put_Line ("abs q2 =" & Float' Image (abs q2));
|
||||
Put_Line ("-q = " & Image (-q));
|
||||
Put_Line ("conj q = " & Image (Conj (q)));
|
||||
Put_Line ("q1 + q2 = " & Image (q1 + q2));
|
||||
Put_Line ("q2 + q1 = " & Image (q2 + q1));
|
||||
Put_Line ("q * r = " & Image (q * r));
|
||||
Put_Line ("r * q = " & Image (r * q));
|
||||
Put_Line ("q1 * q2 = " & Image (q1 * q2));
|
||||
Put_Line ("q2 * q1 = " & Image (q2 * q1));
|
||||
end Test_Quaternion;
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
qnorm: $ => [sqrt fold & [x y] -> x + y*y]
|
||||
|
||||
qneg: $ => [map & => neg]
|
||||
|
||||
qconj: $[q] [@[q\0] ++ qneg drop q]
|
||||
|
||||
qaddr: function [q r][
|
||||
[a b c d]: q
|
||||
@[a+r b c d]
|
||||
]
|
||||
|
||||
qadd: $ => [map couple & & => sum]
|
||||
|
||||
qmulr: $[q r] [map q'x -> x*r]
|
||||
|
||||
qmul: function [q1 q2][
|
||||
[a1 b1 c1 d1]: q1
|
||||
[a2 b2 c2 d2]: q2
|
||||
@[
|
||||
(((a1*a2) - b1*b2) - c1*c2) - d1*d2,
|
||||
(((a1*b2) + b1*a2) + c1*d2) - d1*c2,
|
||||
(((a1*c2) - b1*d2) + c1*a2) + d1*b2,
|
||||
(((a1*d2) + b1*c2) - c1*b2) + d1*a2
|
||||
]
|
||||
]
|
||||
|
||||
; --- test quaternions ---
|
||||
q: [1 2 3 4]
|
||||
q1: [2 3 4 5]
|
||||
q2: [3 4 5 6]
|
||||
r: 7
|
||||
|
||||
print ['qnorm q '= qnorm q]
|
||||
print ['qneg q '= qneg q]
|
||||
print ['qconj q '= qconj q]
|
||||
print ['qaddr q r '= qaddr q r]
|
||||
print ['qmulr q r '= qmulr q r]
|
||||
print ['qadd q1 q2 '= qadd q1 q2]
|
||||
print ['qmul q1 q2 '= qmul q1 q2]
|
||||
print ['qmul q2 q1 '= qmul q2 q1]
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
q := [1, 2, 3, 4]
|
||||
q1 := [2, 3, 4, 5]
|
||||
q2 := [3, 4, 5, 6]
|
||||
r := 7
|
||||
|
||||
MsgBox, % "q = " PrintQ(q)
|
||||
. "`nq1 = " PrintQ(q1)
|
||||
. "`nq2 = " PrintQ(q2)
|
||||
. "`nr = " r
|
||||
. "`nNorm(q) = " Norm(q)
|
||||
. "`nNegative(q) = " PrintQ(Negative(q))
|
||||
. "`nConjugate(q) = " PrintQ(Conjugate(q))
|
||||
. "`nq + r = " PrintQ(AddR(q, r))
|
||||
. "`nq1 + q2 = " PrintQ(AddQ(q1, q2))
|
||||
. "`nq2 + q1 = " PrintQ(AddQ(q2, q1))
|
||||
. "`nqr = " PrintQ(MulR(q, r))
|
||||
. "`nq1q2 = " PrintQ(MulQ(q1, q2))
|
||||
. "`nq2q1 = " PrintQ(MulQ(q2, q1))
|
||||
|
||||
Norm(q) {
|
||||
return sqrt(q[1]**2 + q[2]**2 + q[3]**2 + q[4]**2)
|
||||
}
|
||||
|
||||
Negative(q) {
|
||||
a := []
|
||||
for k, v in q
|
||||
a[A_Index] := v * -1
|
||||
return a
|
||||
}
|
||||
|
||||
Conjugate(q) {
|
||||
a := []
|
||||
for k, v in q
|
||||
a[A_Index] := v * (A_Index = 1 ? 1 : -1)
|
||||
return a
|
||||
}
|
||||
|
||||
AddR(q, r) {
|
||||
a := []
|
||||
for k, v in q
|
||||
a[A_Index] := v + (A_Index = 1 ? r : 0)
|
||||
return a
|
||||
}
|
||||
|
||||
AddQ(q1, q2) {
|
||||
a := []
|
||||
for k, v in q1
|
||||
a[A_Index] := v + q2[A_Index]
|
||||
return a
|
||||
}
|
||||
|
||||
MulR(q, r) {
|
||||
a := []
|
||||
for k, v in q
|
||||
a[A_Index] := v * r
|
||||
return a
|
||||
}
|
||||
|
||||
MulQ(q, u) {
|
||||
a := []
|
||||
, a[1] := q[1]*u[1] - q[2]*u[2] - q[3]*u[3] - q[4]*u[4]
|
||||
, a[2] := q[1]*u[2] + q[2]*u[1] + q[3]*u[4] - q[4]*u[3]
|
||||
, a[3] := q[1]*u[3] - q[2]*u[4] + q[3]*u[1] + q[4]*u[2]
|
||||
, a[4] := q[1]*u[4] + q[2]*u[3] - q[3]*u[2] + q[4]*u[1]
|
||||
return a
|
||||
}
|
||||
|
||||
PrintQ(q, b="(") {
|
||||
for k, v in q
|
||||
b .= v (A_Index = q.MaxIndex() ? ")" : ", ")
|
||||
return b
|
||||
}
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
qi := quatern$Quaternion(Integer);
|
||||
|
||||
Type: ((Integer,Integer,Integer,Integer) -> Quaternion(Integer))
|
||||
q := qi(1,2,3,4);
|
||||
|
||||
Type: Quaternion(Integer)
|
||||
q1 := qi(2,3,4,5);
|
||||
|
||||
Type: Quaternion(Integer)
|
||||
q2 := qi(3,4,5,6);
|
||||
|
||||
Type: Quaternion(Integer)
|
||||
r : Integer := 7;
|
||||
|
||||
Type: Integer
|
||||
sqrt norm q
|
||||
|
||||
+--+
|
||||
(6) \|30
|
||||
Type: AlgebraicNumber
|
||||
-q
|
||||
|
||||
(7) - 1 - 2i - 3j - 4k
|
||||
Type: Quaternion(Integer)
|
||||
conjugate q
|
||||
|
||||
(8) 1 - 2i - 3j - 4k
|
||||
Type: Quaternion(Integer)
|
||||
r + q
|
||||
|
||||
(9) 8 + 2i + 3j + 4k
|
||||
Type: Quaternion(Integer)
|
||||
q1 + q2
|
||||
|
||||
(10) 5 + 7i + 9j + 11k
|
||||
Type: Quaternion(Integer)
|
||||
q*r
|
||||
|
||||
(11) 7 + 14i + 21j + 28k
|
||||
Type: Quaternion(Integer)
|
||||
r*q
|
||||
|
||||
(12) 7 + 14i + 21j + 28k
|
||||
Type: Quaternion(Integer)
|
||||
q1*q2 ~= q2*q1
|
||||
|
||||
(13) true
|
||||
Type: Boolean
|
||||
|
|
@ -1,86 +0,0 @@
|
|||
dim q(4)
|
||||
dim q1(4)
|
||||
dim q2(4)
|
||||
q[0] = 1: q[1] = 2: q[2] = 3: q[3] = 4
|
||||
q1[0] = 2: q1[1] = 3: q1[2] = 4: q1[3] = 5
|
||||
q2[0] = 3: q2[1] = 4: q2[2] = 5: q2[3] = 6
|
||||
r = 7
|
||||
|
||||
function printq(q)
|
||||
return "("+q[0]+", "+q[1]+", "+q[2]+", "+q[3]+")"
|
||||
end function
|
||||
|
||||
function q_equal(q1, q2)
|
||||
return q1[0]=q2[0] and q1[1]=q2[1] and q1[2]=q2[2] and q1[3]=q2[3]
|
||||
end function
|
||||
|
||||
function q_norm(q)
|
||||
return sqr(q[0]*q[0]+q[1]*q[1]+q[2]*q[2]+q[3]*q[3])
|
||||
end function
|
||||
|
||||
function q_neg(q)
|
||||
dim result[4]
|
||||
result[0] = -q[0]
|
||||
result[1] = -q[1]
|
||||
result[2] = -q[2]
|
||||
result[3] = -q[3]
|
||||
return result
|
||||
end function
|
||||
|
||||
function q_conj(q)
|
||||
dim result[4]
|
||||
result[0] = q[0]
|
||||
result[1] = -q[1]
|
||||
result[2] = -q[2]
|
||||
result[3] = -q[3]
|
||||
return result
|
||||
end function
|
||||
|
||||
function q_addreal(q, r)
|
||||
dim result[4]
|
||||
result[0] = q[0]+r
|
||||
result[1] = q[1]
|
||||
result[2] = q[2]
|
||||
result[3] = q[3]
|
||||
return result
|
||||
end function
|
||||
|
||||
function q_add(q1, q2)
|
||||
dim result[4]
|
||||
result[0] = q1[0]+q2[0]
|
||||
result[1] = q1[1]+q2[1]
|
||||
result[2] = q1[2]+q2[2]
|
||||
result[3] = q1[3]+q2[3]
|
||||
return result
|
||||
end function
|
||||
|
||||
function q_mulreal(q, r)
|
||||
dim result[4]
|
||||
result[0] = q[0]*r
|
||||
result[1] = q[1]*r
|
||||
result[2] = q[2]*r
|
||||
result[3] = q[3]*r
|
||||
return result
|
||||
end function
|
||||
|
||||
function q_mul(q1, q2)
|
||||
dim result[4]
|
||||
result[0] = q1[0]*q2[0]-q1[1]*q2[1]-q1[2]*q2[2]-q1[3]*q2[3]
|
||||
result[1] = q1[0]*q2[1]+q1[1]*q2[0]+q1[2]*q2[3]-q1[3]*q2[2]
|
||||
result[2] = q1[0]*q2[2]-q1[1]*q2[3]+q1[2]*q2[0]+q1[3]*q2[1]
|
||||
result[3] = q1[0]*q2[3]+q1[1]*q2[2]-q1[2]*q2[1]+q1[3]*q2[0]
|
||||
return result
|
||||
end function
|
||||
|
||||
print "q = ";printq(q)
|
||||
print "q1 = ";printq(q1)
|
||||
print "q2 = ";printq(q2)
|
||||
print "r = "; r
|
||||
print "norm(q) = "; q_norm(q)
|
||||
print "neg(q) = ";printq(q_neg(q))
|
||||
print "conjugate(q) = ";printq(q_conj(q))
|
||||
print "q+r = ";printq(q_addreal(q,r))
|
||||
print "q1+q2 = ";printq(q_add(q1,q2))
|
||||
print "qr = ";printq(q_mulreal(q,r))
|
||||
print "q1q2 = ";printq(q_mul(q1,q2))
|
||||
print "q2q1 = ";printq(q_mul(q2,q1))
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
DIM q(3), q1(3), q2(3), t(3)
|
||||
q() = 1, 2, 3, 4
|
||||
q1() = 2, 3, 4, 5
|
||||
q2() = 3, 4, 5, 6
|
||||
r = 7
|
||||
|
||||
PRINT "q = " FNq_show(q())
|
||||
PRINT "q1 = " FNq_show(q1())
|
||||
PRINT "q2 = " FNq_show(q2())
|
||||
PRINT "r = "; r
|
||||
PRINT "norm(q) = "; FNq_norm(q())
|
||||
t() = q() : PROCq_neg(t()) : PRINT "neg(q) = " FNq_show(t())
|
||||
t() = q() : PROCq_conj(t()) : PRINT "conjugate(q) = " FNq_show(t())
|
||||
t() = q() : PROCq_addreal(t(),r) : PRINT "q + r = " FNq_show(t())
|
||||
t() = q1() : PROCq_add(t(),q2()) : PRINT "q1 + q2 = " FNq_show(t())
|
||||
t() = q2() : PROCq_add(t(),q1()) : PRINT "q2 + q1 = " FNq_show(t())
|
||||
t() = q() : PROCq_mulreal(t(),r) : PRINT "qr = " FNq_show(t())
|
||||
t() = q1() : PROCq_mul(t(),q2()) : PRINT "q1q2 = " FNq_show(t())
|
||||
t() = q2() : PROCq_mul(t(),q1()) : PRINT "q2q1 = " FNq_show(t())
|
||||
END
|
||||
|
||||
DEF FNq_norm(q()) = MOD(q())
|
||||
|
||||
DEF PROCq_neg(q()) : q() *= -1 : ENDPROC
|
||||
|
||||
DEF PROCq_conj(q()) : q() *= -1 : q(0) *= -1 : ENDPROC
|
||||
|
||||
DEF PROCq_addreal(q(), r) : q(0) += r : ENDPROC
|
||||
|
||||
DEF PROCq_add(q(), r()) : q() += r() : ENDPROC
|
||||
|
||||
DEF PROCq_mulreal(q(), r) : q() *= r : ENDPROC
|
||||
|
||||
DEF PROCq_mul(q(), r()) : LOCAL s() : DIM s(3,3)
|
||||
s() = r(0), -r(1), -r(2), -r(3), r(1), r(0), r(3), -r(2), \
|
||||
\ r(2), -r(3), r(0), r(1), r(3), r(2), -r(1), r(0)
|
||||
q() = s() . q()
|
||||
ENDPROC
|
||||
|
||||
DEF FNq_show(q()) : LOCAL i%, a$ : a$ = "("
|
||||
FOR i% = 0 TO 3 : a$ += STR$(q(i%)) + ", " : NEXT
|
||||
= LEFT$(LEFT$(a$)) + ")"
|
||||
|
|
@ -1,116 +0,0 @@
|
|||
#include <iostream>
|
||||
using namespace std;
|
||||
|
||||
template<class T = double>
|
||||
class Quaternion
|
||||
{
|
||||
public:
|
||||
T w, x, y, z;
|
||||
|
||||
// Numerical constructor
|
||||
Quaternion(const T &w, const T &x, const T &y, const T &z): w(w), x(x), y(y), z(z) {};
|
||||
Quaternion(const T &x, const T &y, const T &z): w(T()), x(x), y(y), z(z) {}; // For 3-rotations
|
||||
Quaternion(const T &r): w(r), x(T()), y(T()), z(T()) {};
|
||||
Quaternion(): w(T()), x(T()), y(T()), z(T()) {};
|
||||
|
||||
// Copy constructor and assignment
|
||||
Quaternion(const Quaternion &q): w(q.w), x(q.x), y(q.y), z(q.z) {};
|
||||
Quaternion& operator=(const Quaternion &q) { w=q.w; x=q.x; y=q.y; z=q.z; return *this; }
|
||||
|
||||
// Unary operators
|
||||
Quaternion operator-() const { return Quaternion(-w, -x, -y, -z); }
|
||||
Quaternion operator~() const { return Quaternion(w, -x, -y, -z); } // Conjugate
|
||||
|
||||
// Norm-squared. SQRT would have to be made generic to be used here
|
||||
T normSquared() const { return w*w + x*x + y*y + z*z; }
|
||||
|
||||
// In-place operators
|
||||
Quaternion& operator+=(const T &r)
|
||||
{ w += r; return *this; }
|
||||
Quaternion& operator+=(const Quaternion &q)
|
||||
{ w += q.w; x += q.x; y += q.y; z += q.z; return *this; }
|
||||
|
||||
Quaternion& operator-=(const T &r)
|
||||
{ w -= r; return *this; }
|
||||
Quaternion& operator-=(const Quaternion &q)
|
||||
{ w -= q.w; x -= q.x; y -= q.y; z -= q.z; return *this; }
|
||||
|
||||
Quaternion& operator*=(const T &r)
|
||||
{ w *= r; x *= r; y *= r; z *= r; return *this; }
|
||||
Quaternion& operator*=(const Quaternion &q)
|
||||
{
|
||||
T oldW(w), oldX(x), oldY(y), oldZ(z);
|
||||
w = oldW*q.w - oldX*q.x - oldY*q.y - oldZ*q.z;
|
||||
x = oldW*q.x + oldX*q.w + oldY*q.z - oldZ*q.y;
|
||||
y = oldW*q.y + oldY*q.w + oldZ*q.x - oldX*q.z;
|
||||
z = oldW*q.z + oldZ*q.w + oldX*q.y - oldY*q.x;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Quaternion& operator/=(const T &r)
|
||||
{ w /= r; x /= r; y /= r; z /= r; return *this; }
|
||||
Quaternion& operator/=(const Quaternion &q)
|
||||
{
|
||||
T oldW(w), oldX(x), oldY(y), oldZ(z), n(q.normSquared());
|
||||
w = (oldW*q.w + oldX*q.x + oldY*q.y + oldZ*q.z) / n;
|
||||
x = (oldX*q.w - oldW*q.x + oldY*q.z - oldZ*q.y) / n;
|
||||
y = (oldY*q.w - oldW*q.y + oldZ*q.x - oldX*q.z) / n;
|
||||
z = (oldZ*q.w - oldW*q.z + oldX*q.y - oldY*q.x) / n;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Binary operators based on in-place operators
|
||||
Quaternion operator+(const T &r) const { return Quaternion(*this) += r; }
|
||||
Quaternion operator+(const Quaternion &q) const { return Quaternion(*this) += q; }
|
||||
Quaternion operator-(const T &r) const { return Quaternion(*this) -= r; }
|
||||
Quaternion operator-(const Quaternion &q) const { return Quaternion(*this) -= q; }
|
||||
Quaternion operator*(const T &r) const { return Quaternion(*this) *= r; }
|
||||
Quaternion operator*(const Quaternion &q) const { return Quaternion(*this) *= q; }
|
||||
Quaternion operator/(const T &r) const { return Quaternion(*this) /= r; }
|
||||
Quaternion operator/(const Quaternion &q) const { return Quaternion(*this) /= q; }
|
||||
|
||||
// Comparison operators, as much as they make sense
|
||||
bool operator==(const Quaternion &q) const
|
||||
{ return (w == q.w) && (x == q.x) && (y == q.y) && (z == q.z); }
|
||||
bool operator!=(const Quaternion &q) const { return !operator==(q); }
|
||||
|
||||
// The operators above allow quaternion op real. These allow real op quaternion.
|
||||
// Uses the above where appropriate.
|
||||
template<class T> friend Quaternion<T> operator+(const T &r, const Quaternion<T> &q);
|
||||
template<class T> friend Quaternion<T> operator-(const T &r, const Quaternion<T> &q);
|
||||
template<class T> friend Quaternion<T> operator*(const T &r, const Quaternion<T> &q);
|
||||
template<class T> friend Quaternion<T> operator/(const T &r, const Quaternion<T> &q);
|
||||
|
||||
// Allows cout << q
|
||||
template<class T> friend ostream& operator<<(ostream &io, const Quaternion<T> &q);
|
||||
};
|
||||
|
||||
// Friend functions need to be outside the actual class definition
|
||||
template<class T>
|
||||
Quaternion<T> operator+(const T &r, const Quaternion<T> &q)
|
||||
{ return q+r; }
|
||||
|
||||
template<class T>
|
||||
Quaternion<T> operator-(const T &r, const Quaternion<T> &q)
|
||||
{ return Quaternion<T>(r-q.w, q.x, q.y, q.z); }
|
||||
|
||||
template<class T>
|
||||
Quaternion<T> operator*(const T &r, const Quaternion<T> &q)
|
||||
{ return q*r; }
|
||||
|
||||
template<class T>
|
||||
Quaternion<T> operator/(const T &r, const Quaternion<T> &q)
|
||||
{
|
||||
T n(q.normSquared());
|
||||
return Quaternion(r*q.w/n, -r*q.x/n, -r*q.y/n, -r*q.z/n);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
ostream& operator<<(ostream &io, const Quaternion<T> &q)
|
||||
{
|
||||
io << q.w;
|
||||
(q.x < T()) ? (io << " - " << (-q.x) << "i") : (io << " + " << q.x << "i");
|
||||
(q.y < T()) ? (io << " - " << (-q.y) << "j") : (io << " + " << q.y << "j");
|
||||
(q.z < T()) ? (io << " - " << (-q.z) << "k") : (io << " + " << q.z << "k");
|
||||
return io;
|
||||
}
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
int main()
|
||||
{
|
||||
Quaternion<> q0(1, 2, 3, 4);
|
||||
Quaternion<> q1(2, 3, 4, 5);
|
||||
Quaternion<> q2(3, 4, 5, 6);
|
||||
double r = 7;
|
||||
|
||||
cout << "q0: " << q0 << endl;
|
||||
cout << "q1: " << q1 << endl;
|
||||
cout << "q2: " << q2 << endl;
|
||||
cout << "r: " << r << endl;
|
||||
cout << endl;
|
||||
cout << "-q0: " << -q0 << endl;
|
||||
cout << "~q0: " << ~q0 << endl;
|
||||
cout << endl;
|
||||
cout << "r * q0: " << r*q0 << endl;
|
||||
cout << "r + q0: " << r+q0 << endl;
|
||||
cout << "q0 / r: " << q0/r << endl;
|
||||
cout << "q0 - r: " << q0-r << endl;
|
||||
cout << endl;
|
||||
cout << "q0 + q1: " << q0+q1 << endl;
|
||||
cout << "q0 - q1: " << q0-q1 << endl;
|
||||
cout << "q0 * q1: " << q0*q1 << endl;
|
||||
cout << "q0 / q1: " << q0/q1 << endl;
|
||||
cout << endl;
|
||||
cout << "q0 * ~q0: " << q0*~q0 << endl;
|
||||
cout << "q0 + q1*q2: " << q0+q1*q2 << endl;
|
||||
cout << "(q0 + q1)*q2: " << (q0+q1)*q2 << endl;
|
||||
cout << "q0*q1*q2: " << q0*q1*q2 << endl;
|
||||
cout << "(q0*q1)*q2: " << (q0*q1)*q2 << endl;
|
||||
cout << "q0*(q1*q2): " << q0*(q1*q2) << endl;
|
||||
cout << endl;
|
||||
cout << "||q0||: " << sqrt(q0.normSquared()) << endl;
|
||||
cout << endl;
|
||||
cout << "q0*q1 - q1*q0: " << (q0*q1 - q1*q0) << endl;
|
||||
|
||||
// Other base types
|
||||
Quaternion<int> q5(2), q6(3);
|
||||
cout << endl << q5*q6 << endl;
|
||||
}
|
||||
|
|
@ -1,90 +0,0 @@
|
|||
using System;
|
||||
|
||||
struct Quaternion : IEquatable<Quaternion>
|
||||
{
|
||||
public readonly double A, B, C, D;
|
||||
|
||||
public Quaternion(double a, double b, double c, double d)
|
||||
{
|
||||
this.A = a;
|
||||
this.B = b;
|
||||
this.C = c;
|
||||
this.D = d;
|
||||
}
|
||||
|
||||
public double Norm()
|
||||
{
|
||||
return Math.Sqrt(A * A + B * B + C * C + D * D);
|
||||
}
|
||||
|
||||
public static Quaternion operator -(Quaternion q)
|
||||
{
|
||||
return new Quaternion(-q.A, -q.B, -q.C, -q.D);
|
||||
}
|
||||
|
||||
public Quaternion Conjugate()
|
||||
{
|
||||
return new Quaternion(A, -B, -C, -D);
|
||||
}
|
||||
|
||||
// implicit conversion takes care of real*quaternion and real+quaternion
|
||||
public static implicit operator Quaternion(double d)
|
||||
{
|
||||
return new Quaternion(d, 0, 0, 0);
|
||||
}
|
||||
|
||||
public static Quaternion operator +(Quaternion q1, Quaternion q2)
|
||||
{
|
||||
return new Quaternion(q1.A + q2.A, q1.B + q2.B, q1.C + q2.C, q1.D + q2.D);
|
||||
}
|
||||
|
||||
public static Quaternion operator *(Quaternion q1, Quaternion q2)
|
||||
{
|
||||
return new Quaternion(
|
||||
q1.A * q2.A - q1.B * q2.B - q1.C * q2.C - q1.D * q2.D,
|
||||
q1.A * q2.B + q1.B * q2.A + q1.C * q2.D - q1.D * q2.C,
|
||||
q1.A * q2.C - q1.B * q2.D + q1.C * q2.A + q1.D * q2.B,
|
||||
q1.A * q2.D + q1.B * q2.C - q1.C * q2.B + q1.D * q2.A);
|
||||
}
|
||||
|
||||
public static bool operator ==(Quaternion q1, Quaternion q2)
|
||||
{
|
||||
return q1.A == q2.A && q1.B == q2.B && q1.C == q2.C && q1.D == q2.D;
|
||||
}
|
||||
|
||||
public static bool operator !=(Quaternion q1, Quaternion q2)
|
||||
{
|
||||
return !(q1 == q2);
|
||||
}
|
||||
|
||||
#region Object Members
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (obj is Quaternion)
|
||||
return Equals((Quaternion)obj);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return A.GetHashCode() ^ B.GetHashCode() ^ C.GetHashCode() ^ D.GetHashCode();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("Q({0}, {1}, {2}, {3})", A, B, C, D);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IEquatable<Quaternion> Members
|
||||
|
||||
public bool Equals(Quaternion other)
|
||||
{
|
||||
return other == this;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
using System;
|
||||
|
||||
static class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
Quaternion q = new Quaternion(1, 2, 3, 4);
|
||||
Quaternion q1 = new Quaternion(2, 3, 4, 5);
|
||||
Quaternion q2 = new Quaternion(3, 4, 5, 6);
|
||||
double r = 7;
|
||||
|
||||
Console.WriteLine("q = {0}", q);
|
||||
Console.WriteLine("q1 = {0}", q1);
|
||||
Console.WriteLine("q2 = {0}", q2);
|
||||
Console.WriteLine("r = {0}", r);
|
||||
|
||||
Console.WriteLine("q.Norm() = {0}", q.Norm());
|
||||
Console.WriteLine("q1.Norm() = {0}", q1.Norm());
|
||||
Console.WriteLine("q2.Norm() = {0}", q2.Norm());
|
||||
|
||||
Console.WriteLine("-q = {0}", -q);
|
||||
Console.WriteLine("q.Conjugate() = {0}", q.Conjugate());
|
||||
|
||||
Console.WriteLine("q + r = {0}", q + r);
|
||||
Console.WriteLine("q1 + q2 = {0}", q1 + q2);
|
||||
Console.WriteLine("q2 + q1 = {0}", q2 + q1);
|
||||
|
||||
Console.WriteLine("q * r = {0}", q * r);
|
||||
Console.WriteLine("q1 * q2 = {0}", q1 * q2);
|
||||
Console.WriteLine("q2 * q1 = {0}", q2 * q1);
|
||||
|
||||
Console.WriteLine("q1*q2 {0} q2*q1", (q1 * q2) == (q2 * q1) ? "==" : "!=");
|
||||
}
|
||||
}
|
||||
|
|
@ -1,131 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <math.h>
|
||||
|
||||
typedef struct quaternion
|
||||
{
|
||||
double q[4];
|
||||
} quaternion_t;
|
||||
|
||||
|
||||
quaternion_t *quaternion_new(void)
|
||||
{
|
||||
return malloc(sizeof(quaternion_t));
|
||||
}
|
||||
|
||||
quaternion_t *quaternion_new_set(double q1,
|
||||
double q2,
|
||||
double q3,
|
||||
double q4)
|
||||
{
|
||||
quaternion_t *q = malloc(sizeof(quaternion_t));
|
||||
if (q != NULL) {
|
||||
q->q[0] = q1; q->q[1] = q2; q->q[2] = q3; q->q[3] = q4;
|
||||
}
|
||||
return q;
|
||||
}
|
||||
|
||||
|
||||
void quaternion_copy(quaternion_t *r, quaternion_t *q)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (r == NULL || q == NULL) return;
|
||||
for(i = 0; i < 4; i++) r->q[i] = q->q[i];
|
||||
}
|
||||
|
||||
|
||||
double quaternion_norm(quaternion_t *q)
|
||||
{
|
||||
size_t i;
|
||||
double r = 0.0;
|
||||
|
||||
if (q == NULL) {
|
||||
fprintf(stderr, "NULL quaternion in norm\n");
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
for(i = 0; i < 4; i++) r += q->q[i] * q->q[i];
|
||||
return sqrt(r);
|
||||
}
|
||||
|
||||
|
||||
void quaternion_neg(quaternion_t *r, quaternion_t *q)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (q == NULL || r == NULL) return;
|
||||
for(i = 0; i < 4; i++) r->q[i] = -q->q[i];
|
||||
}
|
||||
|
||||
|
||||
void quaternion_conj(quaternion_t *r, quaternion_t *q)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (q == NULL || r == NULL) return;
|
||||
r->q[0] = q->q[0];
|
||||
for(i = 1; i < 4; i++) r->q[i] = -q->q[i];
|
||||
}
|
||||
|
||||
|
||||
void quaternion_add_d(quaternion_t *r, quaternion_t *q, double d)
|
||||
{
|
||||
if (q == NULL || r == NULL) return;
|
||||
quaternion_copy(r, q);
|
||||
r->q[0] += d;
|
||||
}
|
||||
|
||||
|
||||
void quaternion_add(quaternion_t *r, quaternion_t *a, quaternion_t *b)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (r == NULL || a == NULL || b == NULL) return;
|
||||
for(i = 0; i < 4; i++) r->q[i] = a->q[i] + b->q[i];
|
||||
}
|
||||
|
||||
|
||||
void quaternion_mul_d(quaternion_t *r, quaternion_t *q, double d)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (r == NULL || q == NULL) return;
|
||||
for(i = 0; i < 4; i++) r->q[i] = q->q[i] * d;
|
||||
}
|
||||
|
||||
bool quaternion_equal(quaternion_t *a, quaternion_t *b)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for(i = 0; i < 4; i++) if (a->q[i] != b->q[i]) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#define A(N) (a->q[(N)])
|
||||
#define B(N) (b->q[(N)])
|
||||
#define R(N) (r->q[(N)])
|
||||
void quaternion_mul(quaternion_t *r, quaternion_t *a, quaternion_t *b)
|
||||
{
|
||||
size_t i;
|
||||
double ri = 0.0;
|
||||
|
||||
if (r == NULL || a == NULL || b == NULL) return;
|
||||
R(0) = A(0)*B(0) - A(1)*B(1) - A(2)*B(2) - A(3)*B(3);
|
||||
R(1) = A(0)*B(1) + A(1)*B(0) + A(2)*B(3) - A(3)*B(2);
|
||||
R(2) = A(0)*B(2) - A(1)*B(3) + A(2)*B(0) + A(3)*B(1);
|
||||
R(3) = A(0)*B(3) + A(1)*B(2) - A(2)*B(1) + A(3)*B(0);
|
||||
}
|
||||
#undef A
|
||||
#undef B
|
||||
#undef R
|
||||
|
||||
|
||||
void quaternion_print(quaternion_t *q)
|
||||
{
|
||||
if (q == NULL) return;
|
||||
printf("(%lf, %lf, %lf, %lf)\n",
|
||||
q->q[0], q->q[1], q->q[2], q->q[3]);
|
||||
}
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
int main()
|
||||
{
|
||||
size_t i;
|
||||
double d = 7.0;
|
||||
quaternion_t *q[3];
|
||||
quaternion_t *r = quaternion_new();
|
||||
|
||||
quaternion_t *qd = quaternion_new_set(7.0, 0.0, 0.0, 0.0);
|
||||
q[0] = quaternion_new_set(1.0, 2.0, 3.0, 4.0);
|
||||
q[1] = quaternion_new_set(2.0, 3.0, 4.0, 5.0);
|
||||
q[2] = quaternion_new_set(3.0, 4.0, 5.0, 6.0);
|
||||
|
||||
printf("r = %lf\n", d);
|
||||
|
||||
for(i = 0; i < 3; i++) {
|
||||
printf("q[%u] = ", i);
|
||||
quaternion_print(q[i]);
|
||||
printf("abs q[%u] = %lf\n", i, quaternion_norm(q[i]));
|
||||
}
|
||||
|
||||
printf("-q[0] = ");
|
||||
quaternion_neg(r, q[0]);
|
||||
quaternion_print(r);
|
||||
|
||||
printf("conj q[0] = ");
|
||||
quaternion_conj(r, q[0]);
|
||||
quaternion_print(r);
|
||||
|
||||
printf("q[1] + q[2] = ");
|
||||
quaternion_add(r, q[1], q[2]);
|
||||
quaternion_print(r);
|
||||
|
||||
printf("q[2] + q[1] = ");
|
||||
quaternion_add(r, q[2], q[1]);
|
||||
quaternion_print(r);
|
||||
|
||||
|
||||
printf("q[0] * r = ");
|
||||
quaternion_mul_d(r, q[0], d);
|
||||
quaternion_print(r);
|
||||
|
||||
printf("q[0] * (r, 0, 0, 0) = ");
|
||||
quaternion_mul(r, q[0], qd);
|
||||
quaternion_print(r);
|
||||
|
||||
|
||||
printf("q[1] * q[2] = ");
|
||||
quaternion_mul(r, q[1], q[2]);
|
||||
quaternion_print(r);
|
||||
|
||||
printf("q[2] * q[1] = ");
|
||||
quaternion_mul(r, q[2], q[1]);
|
||||
quaternion_print(r);
|
||||
|
||||
|
||||
free(q[0]); free(q[1]); free(q[2]); free(r);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -1,82 +0,0 @@
|
|||
quat = cluster is make, minus, norm, conj, add, addr, mul, mulr,
|
||||
equal, get_a, get_b, get_c, get_d, q_form
|
||||
rep = struct[a,b,c,d: real]
|
||||
|
||||
make = proc (a,b,c,d: real) returns (cvt)
|
||||
return (rep${a:a, b:b, c:c, d:d})
|
||||
end make
|
||||
|
||||
minus = proc (q: cvt) returns (cvt)
|
||||
return (down(make(-q.a, -q.b, -q.c, -q.d)))
|
||||
end minus
|
||||
|
||||
norm = proc (q: cvt) returns (real)
|
||||
return ((q.a**2.0 + q.b**2.0 + q.c**2.0 + q.d**2.0) ** 0.5)
|
||||
end norm
|
||||
|
||||
conj = proc (q: cvt) returns (cvt)
|
||||
return (down(make(q.a, -q.b, -q.c, q.d)))
|
||||
end conj
|
||||
|
||||
add = proc (q1, q2: cvt) returns (cvt)
|
||||
return (down(make(q1.a+q2.a, q1.b+q2.b, q1.c+q2.c, q1.d+q2.d)))
|
||||
end add
|
||||
|
||||
addr = proc (q: cvt, r: real) returns (cvt)
|
||||
return (down(make(q.a+r, q.b+r, q.c+r, q.d+r)))
|
||||
end addr
|
||||
|
||||
mul = proc (q1, q2: cvt) returns (cvt)
|
||||
a: real := q1.a*q2.a - q1.b*q2.b - q1.c*q2.c - q1.d*q2.d
|
||||
b: real := q1.a*q2.b + q1.b*q2.a + q1.c*q2.d - q1.d*q2.c
|
||||
c: real := q1.a*q2.c - q1.b*q2.d + q1.c*q2.a + q1.d*q2.b
|
||||
d: real := q1.a*q2.d + q1.b*q2.c - q1.c*q2.b + q1.d*q2.a
|
||||
return (down(make(a,b,c,d)))
|
||||
end mul
|
||||
|
||||
mulr = proc (q: cvt, r: real) returns (cvt)
|
||||
return (down(make(q.a*r, q.b*r, q.c*r, q.d*r)))
|
||||
end mulr
|
||||
|
||||
equal = proc (q1, q2: cvt) returns (bool)
|
||||
return (q1.a = q2.a & q1.b = q2.b & q1.c = q2.c & q1.d = q2.d)
|
||||
end equal
|
||||
|
||||
get_a = proc (q: cvt) returns (real) return (q.a) end get_a
|
||||
get_b = proc (q: cvt) returns (real) return (q.b) end get_b
|
||||
get_c = proc (q: cvt) returns (real) return (q.c) end get_c
|
||||
get_d = proc (q: cvt) returns (real) return (q.d) end get_d
|
||||
|
||||
q_form = proc (q: cvt, a, b: int) returns (string)
|
||||
return ( f_form(q.a, a, b) || " + "
|
||||
|| f_form(q.b, a, b) || "i + "
|
||||
|| f_form(q.c, a, b) || "j + "
|
||||
|| f_form(q.d, a, b) || "k" )
|
||||
end q_form
|
||||
end quat
|
||||
|
||||
start_up = proc ()
|
||||
po: stream := stream$primary_output()
|
||||
|
||||
q0: quat := quat$make(1.0, 2.0, 3.0, 4.0)
|
||||
q1: quat := quat$make(2.0, 3.0, 4.0, 5.0)
|
||||
q2: quat := quat$make(3.0, 4.0, 5.0, 6.0)
|
||||
r: real := 7.0
|
||||
|
||||
stream$putl(po, " q0 = " || quat$q_form(q0, 3, 3))
|
||||
stream$putl(po, " q1 = " || quat$q_form(q1, 3, 3))
|
||||
stream$putl(po, " q2 = " || quat$q_form(q2, 3, 3))
|
||||
stream$putl(po, " r = " || f_form(r, 3, 3))
|
||||
stream$putl(po, "")
|
||||
|
||||
stream$putl(po, "norm(q0) = " || f_form(quat$norm(q0), 3, 3))
|
||||
stream$putl(po, " -q0 = " || quat$q_form(-q0, 3, 3))
|
||||
stream$putl(po, "conj(q0) = " || quat$q_form(quat$conj(q0), 3, 3))
|
||||
stream$putl(po, " q0 + r = " || quat$q_form(quat$addr(q0, r), 3, 3))
|
||||
stream$putl(po, " q1 + q2 = " || quat$q_form(q1 + q2, 3, 3))
|
||||
stream$putl(po, " q0 * r = " || quat$q_form(quat$mulr(q0, r), 3, 3))
|
||||
stream$putl(po, " q1 * q2 = " || quat$q_form(q1 * q2, 3, 3))
|
||||
stream$putl(po, " q2 * q1 = " || quat$q_form(q2 * q1, 3, 3))
|
||||
|
||||
if q1*q2 ~= q2*q1 then stream$putl(po, "q1 * q2 ~= q2 * q1") end
|
||||
end start_up
|
||||
|
|
@ -1,77 +0,0 @@
|
|||
(defclass quaternion () ((a :accessor q-a :initarg :a :type real)
|
||||
(b :accessor q-b :initarg :b :type real)
|
||||
(c :accessor q-c :initarg :c :type real)
|
||||
(d :accessor q-d :initarg :d :type real))
|
||||
(:default-initargs :a 0 :b 0 :c 0 :d 0))
|
||||
|
||||
(defun make-q (&optional (a 0) (b 0) (c 0) (d 0))
|
||||
(make-instance 'quaternion :a a :b b :c c :d d))
|
||||
|
||||
(defgeneric sum (x y))
|
||||
|
||||
(defmethod sum ((x quaternion) (y quaternion))
|
||||
(make-q (+ (q-a x) (q-a y))
|
||||
(+ (q-b x) (q-b y))
|
||||
(+ (q-c x) (q-c y))
|
||||
(+ (q-d x) (q-d y))))
|
||||
|
||||
(defmethod sum ((x quaternion) (y real))
|
||||
(make-q (+ (q-a x) y) (q-b x) (q-c x) (q-d x)))
|
||||
|
||||
(defmethod sum ((x real) (y quaternion))
|
||||
(make-q (+ (q-a y) x) (q-b y) (q-c y) (q-d y)))
|
||||
|
||||
(defgeneric sub (x y))
|
||||
|
||||
(defmethod sub ((x quaternion) (y quaternion))
|
||||
(make-q (- (q-a x) (q-a y))
|
||||
(- (q-b x) (q-b y))
|
||||
(- (q-c x) (q-c y))
|
||||
(- (q-d x) (q-d y))))
|
||||
|
||||
(defmethod sub ((x quaternion) (y real))
|
||||
(make-q (- (q-a x) y)
|
||||
(q-b x)
|
||||
(q-c x)
|
||||
(q-d x)))
|
||||
|
||||
(defmethod sub ((x real) (y quaternion))
|
||||
(make-q (- (q-a y) x)
|
||||
(q-b y)
|
||||
(q-c y)
|
||||
(q-d y)))
|
||||
|
||||
(defgeneric mul (x y))
|
||||
|
||||
(defmethod mul ((x quaternion) (y real))
|
||||
(make-q (* (q-a x) y)
|
||||
(* (q-b x) y)
|
||||
(* (q-c x) y)
|
||||
(* (q-d x) y)))
|
||||
|
||||
(defmethod mul ((x real) (y quaternion))
|
||||
(make-q (* (q-a y) x)
|
||||
(* (q-b y) x)
|
||||
(* (q-c y) x)
|
||||
(* (q-d y) x)))
|
||||
|
||||
(defmethod mul ((x quaternion) (y quaternion))
|
||||
(make-q (- (* (q-a x) (q-a y)) (* (q-b x) (q-b y)) (* (q-c x) (q-c y)) (* (q-d x) (q-d y)))
|
||||
(- (+ (* (q-a x) (q-b y)) (* (q-b x) (q-a y)) (* (q-c x) (q-d y))) (* (q-d x) (q-c y)))
|
||||
(- (+ (* (q-a x) (q-c y)) (* (q-c x) (q-a y)) (* (q-d x) (q-b y))) (* (q-b x) (q-d y)))
|
||||
(- (+ (* (q-a x) (q-d y)) (* (q-b x) (q-c y)) (* (q-d x) (q-a y))) (* (q-c x) (q-b y)))))
|
||||
|
||||
(defmethod norm ((x quaternion))
|
||||
(+ (sqrt (q-a x)) (sqrt (q-b x)) (sqrt (q-c x)) (sqrt (q-d x))))
|
||||
|
||||
(defmethod print-object ((x quaternion) stream)
|
||||
(format stream "~@f~@fi~@fj~@fk" (q-a x) (q-b x) (q-c x) (q-d x)))
|
||||
|
||||
(defvar q (make-q 0 1 0 0))
|
||||
(defvar q1 (make-q 0 0 1 0))
|
||||
(defvar q2 (make-q 0 0 0 1))
|
||||
(defvar r 7)
|
||||
(format t "q+q1+q2 = ~a~&" (reduce #'sum (list q q1 q2)))
|
||||
(format t "r*(q+q1+q2) = ~a~&" (mul r (reduce #'sum (list q q1 q2))))
|
||||
(format t "q*q1*q2 = ~a~&" (reduce #'mul (list q q1 q2)))
|
||||
(format t "q-q1-q2 = ~a~&" (reduce #'sub (list q q1 q2)))
|
||||
|
|
@ -1,89 +0,0 @@
|
|||
class Quaternion
|
||||
property a, b, c, d
|
||||
|
||||
def initialize(@a : Int64, @b : Int64, @c : Int64, @d : Int64) end
|
||||
|
||||
def norm; Math.sqrt(a**2 + b**2 + c**2 + d**2) end
|
||||
def conj; Quaternion.new(a, -b, -c, -d) end
|
||||
def +(n) Quaternion.new(a + n, b, c, d) end
|
||||
def -(n) Quaternion.new(a - n, b, c, d) end
|
||||
def -() Quaternion.new(-a, -b, -c, -d) end
|
||||
def *(n) Quaternion.new(a * n, b * n, c * n, d * n) end
|
||||
def ==(rhs : Quaternion) self.to_s == rhs.to_s end
|
||||
def +(rhs : Quaternion)
|
||||
Quaternion.new(a + rhs.a, b + rhs.b, c + rhs.c, d + rhs.d)
|
||||
end
|
||||
|
||||
def -(rhs : Quaternion)
|
||||
Quaternion.new(a - rhs.a, b - rhs.b, c - rhs.c, d - rhs.d)
|
||||
end
|
||||
|
||||
def *(rhs : Quaternion)
|
||||
Quaternion.new(
|
||||
a * rhs.a - b * rhs.b - c * rhs.c - d * rhs.d,
|
||||
a * rhs.b + b * rhs.a + c * rhs.d - d * rhs.c,
|
||||
a * rhs.c - b * rhs.d + c * rhs.a + d * rhs.b,
|
||||
a * rhs.d + b * rhs.c - c * rhs.b + d * rhs.a)
|
||||
end
|
||||
|
||||
def to_s(io : IO) io << "(#{a} #{sgn(b)}i #{sgn(c)}j #{sgn(d)}k)\n" end
|
||||
private def sgn(n) n.sign|1 == 1 ? "+ #{n}" : "- #{n.abs}" end
|
||||
end
|
||||
|
||||
struct Number
|
||||
def +(rhs : Quaternion)
|
||||
Quaternion.new(rhs.a + self, rhs.b, rhs.c, rhs.d)
|
||||
end
|
||||
|
||||
def -(rhs : Quaternion)
|
||||
Quaternion.new(-rhs.a + self, -rhs.b, -rhs.c, -rhs.d)
|
||||
end
|
||||
|
||||
def *(rhs : Quaternion)
|
||||
Quaternion.new(rhs.a * self, rhs.b * self, rhs.c * self, rhs.d * self)
|
||||
end
|
||||
end
|
||||
|
||||
q0 = Quaternion.new(a: 1, b: 2, c: 3, d: 4)
|
||||
q1 = Quaternion.new(2, 3, 4, 5)
|
||||
q2 = Quaternion.new(3, 4, 5, 6)
|
||||
r = 7
|
||||
|
||||
puts "q0 = #{q0}"
|
||||
puts "q1 = #{q1}"
|
||||
puts "q2 = #{q2}"
|
||||
puts "r = #{r}"
|
||||
puts
|
||||
puts "normal of q0 = #{q0.norm}"
|
||||
puts "-q0 = #{-q0}"
|
||||
puts "conjugate of q0 = #{q0.conj}"
|
||||
puts "q0 * (conjugate of q0) = #{q0 * q0.conj}"
|
||||
puts "(conjugate of q0) * q0 = #{q0.conj * q0}"
|
||||
puts
|
||||
puts "r + q0 = #{r + q0}"
|
||||
puts "q0 + r = #{q0 + r}"
|
||||
puts
|
||||
puts " q0 - r = #{q0 - r}"
|
||||
puts "-q0 - r = #{-q0 - r}"
|
||||
puts " r - q0 = #{r - q0}"
|
||||
puts "-q0 + r = #{-q0 + r}"
|
||||
puts
|
||||
puts "r * q0 = #{r * q0}"
|
||||
puts "q0 * r = #{q0 * r}"
|
||||
puts
|
||||
puts "q0 + q1 = #{q0 + q1}"
|
||||
puts "q0 - q1 = #{q2 - q1}"
|
||||
puts "q0 * q1 = #{q0 * q1}"
|
||||
puts
|
||||
puts " q0 + q1 * q2 = #{q0 + q1 * q2}"
|
||||
puts "(q0 + q1) * q2 = #{(q0 + q1) * q2}"
|
||||
puts
|
||||
puts " q0 * q1 * q2 = #{q0 * q1 * q2}"
|
||||
puts "(q0 * q1) * q2 = #{(q0 * q1) * q2}"
|
||||
puts " q0 * (q1 * q2) = #{q0 * (q1 * q2)}"
|
||||
puts
|
||||
puts "q1 * q2 = #{q1 * q2}"
|
||||
puts "q2 * q1 = #{q2 * q1}"
|
||||
puts
|
||||
puts "q1 * q2 != q2 * q1 => #{(q1 * q2) != (q2 * q1)}"
|
||||
puts "q1 * q2 == q2 * q1 => #{(q1 * q2) == (q2 * q1)}"
|
||||
|
|
@ -1,226 +0,0 @@
|
|||
import std.math, std.numeric, std.traits, std.conv, std.complex;
|
||||
|
||||
|
||||
struct Quat(T) if (isFloatingPoint!T) {
|
||||
alias CT = Complex!T;
|
||||
|
||||
union {
|
||||
struct { T re, i, j, k; } // Default init to NaN.
|
||||
struct { CT x, y; }
|
||||
struct { T[4] vector; }
|
||||
}
|
||||
|
||||
string toString() const pure /*nothrow*/ @safe {
|
||||
return vector.text;
|
||||
}
|
||||
|
||||
@property T norm2() const pure nothrow @safe @nogc { /// Norm squared.
|
||||
return re ^^ 2 + i ^^ 2 + j ^^ 2 + k ^^ 2;
|
||||
}
|
||||
|
||||
@property T abs() const pure nothrow @safe @nogc { /// Norm.
|
||||
return sqrt(norm2);
|
||||
}
|
||||
|
||||
@property T arg() const pure nothrow @safe @nogc { /// Theta.
|
||||
return acos(re / abs); // this may be incorrect...
|
||||
}
|
||||
|
||||
@property Quat!T conj() const pure nothrow @safe @nogc { /// Conjugate.
|
||||
return Quat!T(re, -i, -j, -k);
|
||||
}
|
||||
|
||||
@property Quat!T recip() const pure nothrow @safe @nogc { /// Reciprocal.
|
||||
return Quat!T(re / norm2, -i / norm2, -j / norm2, -k / norm2);
|
||||
}
|
||||
|
||||
@property Quat!T pureim() const pure nothrow @safe @nogc { /// Pure imagery.
|
||||
return Quat!T(0, i, j, k);
|
||||
}
|
||||
|
||||
@property Quat!T versor() const pure nothrow @safe @nogc { /// Unit versor.
|
||||
return this / abs;
|
||||
}
|
||||
|
||||
/// Unit versor of imagery part.
|
||||
@property Quat!T iversor() const pure nothrow @safe @nogc {
|
||||
return pureim / pureim.abs;
|
||||
}
|
||||
|
||||
/// Assignment.
|
||||
Quat!T opAssign(U : T)(Quat!U z) pure nothrow @safe @nogc {
|
||||
x = z.x; y = z.y;
|
||||
return this;
|
||||
}
|
||||
|
||||
Quat!T opAssign(U : T)(Complex!U c) pure nothrow @safe @nogc {
|
||||
x = c; y = 0;
|
||||
return this;
|
||||
}
|
||||
|
||||
Quat!T opAssign(U : T)(U r) pure nothrow @safe @nogc
|
||||
if (isNumeric!U) {
|
||||
re = r; i = 0; y = 0;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// Test for equal, not ordered so no opCmp.
|
||||
bool opEquals(U : T)(Quat!U z) const pure nothrow @safe @nogc {
|
||||
return re == z.re && i == z.i && j == z.j && k == z.k;
|
||||
}
|
||||
|
||||
bool opEquals(U : T)(Complex!U c) const pure nothrow @safe @nogc {
|
||||
return re == c.re && i == c.im && j == 0 && k == 0;
|
||||
}
|
||||
|
||||
bool opEquals(U : T)(U r) const pure nothrow @safe @nogc
|
||||
if (isNumeric!U) {
|
||||
return re == r && i == 0 && j == 0 && k == 0;
|
||||
}
|
||||
|
||||
/// Unary op.
|
||||
Quat!T opUnary(string op)() const pure nothrow @safe @nogc
|
||||
if (op == "+") {
|
||||
return this;
|
||||
}
|
||||
|
||||
Quat!T opUnary(string op)() const pure nothrow @safe @nogc
|
||||
if (op == "-") {
|
||||
return Quat!T(-re, -i, -j, -k);
|
||||
}
|
||||
|
||||
/// Binary op, Quaternion on left of op.
|
||||
Quat!(CommonType!(T,U)) opBinary(string op, U)(Quat!U z)
|
||||
const pure nothrow @safe @nogc {
|
||||
alias typeof(return) C;
|
||||
|
||||
static if (op == "+" ) {
|
||||
return C(re + z.re, i + z.i, j + z.j, k + z.k);
|
||||
} else static if (op == "-") {
|
||||
return C(re - z.re, i - z.i, j - z.j, k - z.k);
|
||||
} else static if (op == "*") {
|
||||
return C(re * z.re - i * z.i - j * z.j - k * z.k,
|
||||
re * z.i + i * z.re + j * z.k - k * z.j,
|
||||
re * z.j - i * z.k + j * z.re + k * z.i,
|
||||
re * z.k + i * z.j - j * z.i + k * z.re);
|
||||
} else static if (op == "/") {
|
||||
return this * z.recip;
|
||||
}
|
||||
}
|
||||
|
||||
/// Extend complex to quaternion.
|
||||
Quat!(CommonType!(T,U)) opBinary(string op, U)(Complex!U c)
|
||||
const pure nothrow @safe @nogc {
|
||||
return opBinary!op(typeof(return)(c.re, c.im, 0, 0));
|
||||
}
|
||||
|
||||
/// For scalar.
|
||||
Quat!(CommonType!(T,U)) opBinary(string op, U)(U r)
|
||||
const pure nothrow @safe @nogc
|
||||
if (isNumeric!U) {
|
||||
alias typeof(return) C;
|
||||
|
||||
static if (op == "+" ) {
|
||||
return C(re + r, i, j, k);
|
||||
} else static if (op == "-") {
|
||||
return C(re - r, i, j, k);
|
||||
} else static if (op == "*") {
|
||||
return C(re * r, i * r, j * r, k * r);
|
||||
} else static if (op == "/") {
|
||||
return C(re / r, i / r, j / r, k / r);
|
||||
} else static if (op == "^^") {
|
||||
return pow(r);
|
||||
}
|
||||
}
|
||||
|
||||
/// Power function.
|
||||
Quat!(CommonType!(T,U)) pow(U)(U r)
|
||||
const pure nothrow @safe @nogc
|
||||
if (isNumeric!U) {
|
||||
return (abs^^r) * exp(r * iversor * arg);
|
||||
}
|
||||
|
||||
/// Handle binary op if Quaternion on right of op and left is
|
||||
/// not quaternion.
|
||||
Quat!(CommonType!(T,U)) opBinaryRight(string op, U)(Complex!U c)
|
||||
const pure nothrow @safe @nogc {
|
||||
alias typeof(return) C;
|
||||
auto w = C(c.re, c.im, 0, 0);
|
||||
return w.opBinary!(op)(this);
|
||||
}
|
||||
|
||||
Quat!(CommonType!(T,U)) opBinaryRight(string op, U)(U r)
|
||||
const pure nothrow @safe @nogc
|
||||
if (isNumeric!U) {
|
||||
alias typeof(return) C;
|
||||
|
||||
static if (op == "+" || op == "*") {
|
||||
return opBinary!op(r);
|
||||
} else static if (op == "-") {
|
||||
return C(r - re , -i, -j, -k);
|
||||
} else static if (op == "/") {
|
||||
auto w = C(re, i, j, k);
|
||||
return w.recip * r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
HT exp(HT)(HT z) pure nothrow @safe @nogc
|
||||
if (is(HT T == Quat!T)) {
|
||||
immutable inorm = z.pureim.abs;
|
||||
return std.math.exp(z.re) * (cos(inorm) + z.iversor * sin(inorm));
|
||||
}
|
||||
|
||||
HT log(HT)(HT z) pure nothrow @safe @nogc
|
||||
if (is(HT T == Quat!T)) {
|
||||
return std.math.log(z.abs) + z.iversor * acos(z.re / z.abs);
|
||||
}
|
||||
|
||||
|
||||
void main() @safe { // Demo code.
|
||||
import std.stdio;
|
||||
|
||||
alias QR = Quat!real;
|
||||
enum real r = 7.0;
|
||||
|
||||
immutable QR q = QR(2, 3, 4, 5),
|
||||
q1 = QR(2, 3, 4, 5),
|
||||
q2 = QR(3, 4, 5, 6);
|
||||
|
||||
writeln("1. q - norm: ", q.abs);
|
||||
writeln("2. q - negative: ", -q);
|
||||
writeln("3. q - conjugate: ", q.conj);
|
||||
writeln("4. r + q: ", r + q);
|
||||
writeln(" q + r: ", q + r);
|
||||
writeln("5. q1 + q2: ", q1 + q2);
|
||||
writeln("6. r * q: ", r * q);
|
||||
writeln(" q * r: ", q * r);
|
||||
writeln("7. q1 * q2: ", q1 * q2);
|
||||
writeln(" q2 * q1: ", q2 * q1);
|
||||
writeln("8. q1 * q2 != q2 * Q1 ? ", q1 * q2 != q2 * q1);
|
||||
|
||||
immutable QR i = QR(0, 1, 0, 0),
|
||||
j = QR(0, 0, 1, 0),
|
||||
k = QR(0, 0, 0, 1);
|
||||
writeln("9.1 i * i: ", i * i);
|
||||
writeln(" J * j: ", j * j);
|
||||
writeln(" k * k: ", k * k);
|
||||
writeln(" i * j * k: ", i * j * k);
|
||||
writeln("9.2 q1 / q2: ", q1 / q2);
|
||||
writeln("9.3 q1 / q2 * q2: ", q1 / q2 * q2);
|
||||
writeln(" q2 * q1 / q2: ", q2 * q1 / q2);
|
||||
writeln("9.4 exp(pi * i): ", exp(PI * i));
|
||||
writeln(" exp(pi * j): ", exp(PI * j));
|
||||
writeln(" exp(pi * k): ", exp(PI * k));
|
||||
writeln(" exp(q): ", exp(q));
|
||||
writeln(" log(q): ", log(q));
|
||||
writeln(" exp(log(q)): ", exp(log(q)));
|
||||
writeln(" log(exp(q)): ", log(exp(q)));
|
||||
immutable s = q.exp.log;
|
||||
writeln("9.5 let s = log(exp(q)): ", s);
|
||||
writeln(" exp(s): ", exp(s));
|
||||
writeln(" log(s): ", log(s));
|
||||
writeln(" exp(log(s)): ", exp(log(s)));
|
||||
writeln(" log(exp(s)): ", log(exp(s)));
|
||||
}
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
import 'dart:math' as math;
|
||||
|
||||
class Quaternion {
|
||||
final double a, b, c, d;
|
||||
|
||||
Quaternion(this.a, this.b, this.c, this.d);
|
||||
|
||||
Quaternion operator +(Object other) {
|
||||
if (other is Quaternion) {
|
||||
return Quaternion(a + other.a, b + other.b, c + other.c, d + other.d);
|
||||
} else if (other is double) {
|
||||
return Quaternion(a + other, b, c, d);
|
||||
}
|
||||
throw ArgumentError('Invalid type for addition: ${other.runtimeType}');
|
||||
}
|
||||
|
||||
Quaternion operator *(Object other) {
|
||||
if (other is Quaternion) {
|
||||
return Quaternion(
|
||||
a * other.a - b * other.b - c * other.c - d * other.d,
|
||||
a * other.b + b * other.a + c * other.d - d * other.c,
|
||||
a * other.c - b * other.d + c * other.a + d * other.b,
|
||||
a * other.d + b * other.c - c * other.b + d * other.a,
|
||||
);
|
||||
} else if (other is double) {
|
||||
return Quaternion(a * other, b * other, c * other, d * other);
|
||||
}
|
||||
throw ArgumentError('Invalid type for multiplication: ${other.runtimeType}');
|
||||
}
|
||||
|
||||
Quaternion operator -() => Quaternion(-a, -b, -c, -d);
|
||||
|
||||
Quaternion conj() => Quaternion(a, -b, -c, -d);
|
||||
|
||||
double norm() => math.sqrt(a * a + b * b + c * c + d * d);
|
||||
|
||||
@override
|
||||
String toString() => '($a, $b, $c, $d)';
|
||||
}
|
||||
|
||||
void main() {
|
||||
var q = Quaternion(1.0, 2.0, 3.0, 4.0);
|
||||
var q1 = Quaternion(2.0, 3.0, 4.0, 5.0);
|
||||
var q2 = Quaternion(3.0, 4.0, 5.0, 6.0);
|
||||
var r = 7.0;
|
||||
print("q = $q");
|
||||
print("q1 = $q1");
|
||||
print("q2 = $q2");
|
||||
print("r = $r\n");
|
||||
print("norm(q) = ${q.norm().toStringAsFixed(6)}");
|
||||
print("-q = ${-q}");
|
||||
print("conj(q) = ${q.conj()}\n");
|
||||
print("r + q = ${q + r}");
|
||||
print("q + r = ${q + r}");
|
||||
print("q1 + q2 = ${q1 + q2}\n");
|
||||
print("r * q = ${q * r}");
|
||||
print("q * r = ${q * r}");
|
||||
var q3 = q1 * q2;
|
||||
var q4 = q2 * q1;
|
||||
print("q1 * q2 = $q3");
|
||||
print("q2 * q1 = $q4\n");
|
||||
print("q1 * q2 != q2 * q1 = ${q3 != q4}");
|
||||
}
|
||||
|
|
@ -1,129 +0,0 @@
|
|||
unit Quaternions;
|
||||
|
||||
interface
|
||||
|
||||
type
|
||||
|
||||
TQuaternion = record
|
||||
A, B, C, D: double;
|
||||
|
||||
function Init (aA, aB, aC, aD : double): TQuaternion;
|
||||
function Norm : double;
|
||||
function Conjugate : TQuaternion;
|
||||
function ToString : string;
|
||||
|
||||
class operator Negative (Left : TQuaternion): TQuaternion;
|
||||
class operator Positive (Left : TQuaternion): TQuaternion;
|
||||
class operator Add (Left, Right : TQuaternion): TQuaternion;
|
||||
class operator Add (Left : TQuaternion; Right : double): TQuaternion; overload;
|
||||
class operator Add (Left : double; Right : TQuaternion): TQuaternion; overload;
|
||||
class operator Subtract (Left, Right : TQuaternion): TQuaternion;
|
||||
class operator Multiply (Left, Right : TQuaternion): TQuaternion;
|
||||
class operator Multiply (Left : TQuaternion; Right : double): TQuaternion; overload;
|
||||
class operator Multiply (Left : double; Right : TQuaternion): TQuaternion; overload;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
SysUtils;
|
||||
|
||||
{ TQuaternion }
|
||||
|
||||
function TQuaternion.Init(aA, aB, aC, aD: double): TQuaternion;
|
||||
begin
|
||||
A := aA;
|
||||
B := aB;
|
||||
C := aC;
|
||||
D := aD;
|
||||
|
||||
result := Self;
|
||||
end;
|
||||
|
||||
function TQuaternion.Norm: double;
|
||||
begin
|
||||
result := sqrt(sqr(A) + sqr(B) + sqr(C) + sqr(D));
|
||||
end;
|
||||
|
||||
function TQuaternion.Conjugate: TQuaternion;
|
||||
begin
|
||||
result.B := -B;
|
||||
result.C := -C;
|
||||
result.D := -D;
|
||||
end;
|
||||
|
||||
class operator TQuaternion.Negative(Left: TQuaternion): TQuaternion;
|
||||
begin
|
||||
result.A := -Left.A;
|
||||
result.B := -Left.B;
|
||||
result.C := -Left.C;
|
||||
result.D := -Left.D;
|
||||
end;
|
||||
|
||||
class operator TQuaternion.Positive(Left: TQuaternion): TQuaternion;
|
||||
begin
|
||||
result := Left;
|
||||
end;
|
||||
|
||||
class operator TQuaternion.Add(Left, Right: TQuaternion): TQuaternion;
|
||||
begin
|
||||
result.A := Left.A + Right.A;
|
||||
result.B := Left.B + Right.B;
|
||||
result.C := Left.C + Right.C;
|
||||
result.D := Left.D + Right.D;
|
||||
end;
|
||||
|
||||
class operator TQuaternion.Add(Left: TQuaternion; Right: double): TQuaternion;
|
||||
begin
|
||||
result.A := Left.A + Right;
|
||||
result.B := Left.B;
|
||||
result.C := Left.C;
|
||||
result.D := Left.D;
|
||||
end;
|
||||
|
||||
class operator TQuaternion.Add(Left: double; Right: TQuaternion): TQuaternion;
|
||||
begin
|
||||
result.A := Left + Right.A;
|
||||
result.B := Right.B;
|
||||
result.C := Right.C;
|
||||
result.D := Right.D;
|
||||
end;
|
||||
|
||||
class operator TQuaternion.Subtract(Left, Right: TQuaternion): TQuaternion;
|
||||
begin
|
||||
result.A := Left.A - Right.A;
|
||||
result.B := Left.B - Right.B;
|
||||
result.C := Left.C - Right.C;
|
||||
result.D := Left.D - Right.D;
|
||||
end;
|
||||
|
||||
class operator TQuaternion.Multiply(Left, Right: TQuaternion): TQuaternion;
|
||||
begin
|
||||
result.A := Left.A * Right.A - Left.B * Right.B - Left.C * Right.C - Left.D * Right.D;
|
||||
result.B := Left.A * Right.B + Left.B * Right.A + Left.C * Right.D - Left.D * Right.C;
|
||||
result.C := Left.A * Right.C - Left.B * Right.D + Left.C * Right.A + Left.D * Right.B;
|
||||
result.D := Left.A * Right.D + Left.B * Right.C - Left.C * Right.B + Left.D * Right.A;
|
||||
end;
|
||||
|
||||
class operator TQuaternion.Multiply(Left: double; Right: TQuaternion): TQuaternion;
|
||||
begin
|
||||
result.A := Left * Right.A;
|
||||
result.B := Left * Right.B;
|
||||
result.C := Left * Right.C;
|
||||
result.D := Left * Right.D;
|
||||
end;
|
||||
|
||||
class operator TQuaternion.Multiply(Left: TQuaternion; Right: double): TQuaternion;
|
||||
begin
|
||||
result.A := Left.A * Right;
|
||||
result.B := Left.B * Right;
|
||||
result.C := Left.C * Right;
|
||||
result.D := Left.D * Right;
|
||||
end;
|
||||
|
||||
function TQuaternion.ToString: string;
|
||||
begin
|
||||
result := Format('%f + %fi + %fj + %fk', [A, B, C, D]);
|
||||
end;
|
||||
|
||||
end.
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
program QuaternionTest;
|
||||
|
||||
{$APPTYPE CONSOLE}
|
||||
|
||||
uses
|
||||
Quaternions in 'Quaternions.pas';
|
||||
|
||||
var
|
||||
r : double;
|
||||
q, q1, q2 : TQuaternion;
|
||||
begin
|
||||
r := 7;
|
||||
q := q .Init(1, 2, 3, 4);
|
||||
q1 := q1.Init(2, 3, 4, 5);
|
||||
q2 := q2.Init(3, 4, 5, 6);
|
||||
|
||||
writeln('q = ', q.ToString);
|
||||
writeln('q1 = ', q1.ToString);
|
||||
writeln('q2 = ', q2.ToString);
|
||||
writeln('r = ', r);
|
||||
writeln('Norm(q ) = ', q.Norm);
|
||||
writeln('Norm(q1) = ', q1.Norm);
|
||||
writeln('Norm(q2) = ', q2.Norm);
|
||||
writeln('-q = ', (-q).ToString);
|
||||
writeln('Conjugate q = ', q.Conjugate.ToString);
|
||||
writeln('q1 + q2 = ', (q1 + q2).ToString);
|
||||
writeln('q2 + q1 = ', (q2 + q1).ToString);
|
||||
writeln('q * r = ', (q * r).ToString);
|
||||
writeln('r * q = ', (r * q).ToString);
|
||||
writeln('q1 * q2 = ', (q1 * q2).ToString);
|
||||
writeln('q2 * q1 = ', (q2 * q1).ToString);
|
||||
end.
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
interface Quaternion guards QS {}
|
||||
def makeQuaternion(a, b, c, d) {
|
||||
return def quaternion implements QS {
|
||||
|
||||
to __printOn(out) {
|
||||
out.print("(", a, " + ", b, "i + ")
|
||||
out.print(c, "j + ", d, "k)")
|
||||
}
|
||||
|
||||
# Task requirement 1
|
||||
to norm() {
|
||||
return (a**2 + b**2 + c**2 + d**2).sqrt()
|
||||
}
|
||||
|
||||
# Task requirement 2
|
||||
to negate() {
|
||||
return makeQuaternion(-a, -b, -c, -d)
|
||||
}
|
||||
|
||||
# Task requirement 3
|
||||
to conjugate() {
|
||||
return makeQuaternion(a, -b, -c, -d)
|
||||
}
|
||||
|
||||
# Task requirement 4, 5
|
||||
# This implements q + r; r + q is deliberately prohibited by E
|
||||
to add(other :any[Quaternion, int, float64]) {
|
||||
switch (other) {
|
||||
match q :Quaternion {
|
||||
return makeQuaternion(
|
||||
a+q.a(), b+q.b(), c+q.c(), d+q.d())
|
||||
}
|
||||
match real {
|
||||
return makeQuaternion(a+real, b, c, d)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Task requirement 6, 7
|
||||
# This implements q * r; r * q is deliberately prohibited by E
|
||||
to multiply(other :any[Quaternion, int, float64]) {
|
||||
switch (other) {
|
||||
match q :Quaternion {
|
||||
return makeQuaternion(
|
||||
a*q.a() - b*q.b() - c*q.c() - d*q.d(),
|
||||
a*q.b() + b*q.a() + c*q.d() - d*q.c(),
|
||||
a*q.c() - b*q.d() + c*q.a() + d*q.b(),
|
||||
a*q.d() + b*q.c() - c*q.b() + d*q.a())
|
||||
}
|
||||
match real {
|
||||
return makeQuaternion(real*a, real*b, real*c, real*d)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
to a() { return a }
|
||||
to b() { return b }
|
||||
to c() { return c }
|
||||
to d() { return d }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
? def q1 := makeQuaternion(2,3,4,5)
|
||||
# value: (2 + 3i + 4j + 5k)
|
||||
|
||||
? def q2 := makeQuaternion(3,4,5,6)
|
||||
# value: (3 + 4i + 5j + 6k)
|
||||
|
||||
? q1+q2
|
||||
# value: (5 + 7i + 9j + 11k)
|
||||
|
||||
? q1*q2
|
||||
# value: (-56 + 16i + 24j + 26k)
|
||||
|
||||
? q2*q1
|
||||
# value: (-56 + 18i + 20j + 28k)
|
||||
|
||||
? q1+(-2)
|
||||
# value: (0 + 3i + 4j + 5k)
|
||||
|
|
@ -1,104 +0,0 @@
|
|||
PROGRAM QUATERNION
|
||||
|
||||
!$DOUBLE
|
||||
|
||||
TYPE QUATERNION=(A,B,C,D)
|
||||
|
||||
DIM Q:QUATERNION,Q1:QUATERNION,Q2:QUATERNION
|
||||
|
||||
|
||||
DIM R:QUATERNION,S:QUATERNION,T:QUATERNION
|
||||
|
||||
PROCEDURE NORM(T.->NORM)
|
||||
NORM=SQR(T.A*T.A+T.B*T.B+T.C*T.C+T.D*T.D)
|
||||
END PROCEDURE
|
||||
|
||||
PROCEDURE NEGATIVE(T.->T.)
|
||||
T.A=-T.A
|
||||
T.B=-T.B
|
||||
T.C=-T.C
|
||||
T.D=-T.D
|
||||
END PROCEDURE
|
||||
|
||||
PROCEDURE CONJUGATE(T.->T.)
|
||||
T.A=T.A
|
||||
T.B=-T.B
|
||||
T.C=-T.C
|
||||
T.D=-T.D
|
||||
END PROCEDURE
|
||||
|
||||
PROCEDURE ADD_REAL(T.,REAL->T.)
|
||||
T.A=T.A+REAL
|
||||
T.B=T.B
|
||||
T.C=T.C
|
||||
T.D=T.D
|
||||
END PROCEDURE
|
||||
|
||||
PROCEDURE ADD(T.,S.->T.)
|
||||
T.A=T.A+S.A
|
||||
T.B=T.B+S.B
|
||||
T.C=T.C+S.C
|
||||
T.D=T.D+S.D
|
||||
END PROCEDURE
|
||||
|
||||
PROCEDURE MULT_REAL(T.,REAL->T.)
|
||||
T.A=T.A*REAL
|
||||
T.B=T.B*REAL
|
||||
T.C=T.C*REAL
|
||||
T.D=T.D*REAL
|
||||
END PROCEDURE
|
||||
|
||||
PROCEDURE MULT(T.,S.->R.)
|
||||
R.A=T.A*S.A-T.B*S.B-T.C*S.C-T.D*S.D
|
||||
R.B=T.A*S.B+T.B*S.A+T.C*S.D-T.D*S.C
|
||||
R.C=T.A*S.C-T.B*S.D+T.C*S.A+T.D*S.B
|
||||
R.D=T.A*S.D+T.B*S.C-T.C*S.B+T.D*S.A
|
||||
END PROCEDURE
|
||||
|
||||
PROCEDURE PRINTQ(T.)
|
||||
PRINT("(";T.A;",";T.B;",";T.C;",";T.D;")")
|
||||
END PROCEDURE
|
||||
|
||||
BEGIN
|
||||
Q.A=1 Q.B=2 Q.C=3 Q.D=4
|
||||
Q1.A=2 Q1.B=3 Q1.C=4 Q1.D=5
|
||||
Q2.A=3 Q2.B=4 Q2.C=5 Q2.D=6
|
||||
REAL=7
|
||||
|
||||
NORM(Q.->NORM)
|
||||
PRINT("Norm(q)=";NORM)
|
||||
|
||||
NEGATIVE(Q.->T.)
|
||||
PRINT("Negative(q) =";)
|
||||
PRINTQ(T.)
|
||||
|
||||
CONJUGATE(Q.->T.)
|
||||
PRINT("Conjugate(q) =";)
|
||||
PRINTQ(T.)
|
||||
|
||||
ADD_REAL(Q.,REAL->T.)
|
||||
PRINT("q + real =";)
|
||||
PRINTQ(T.)
|
||||
|
||||
! addition is commutative
|
||||
ADD(Q1.,Q2.->T.)
|
||||
PRINT("q1 + q2 =";)
|
||||
PRINTQ(T.)
|
||||
|
||||
ADD(Q2.,Q1.->T.)
|
||||
PRINT("q2 + q1 = ";)
|
||||
PRINTQ(T.)
|
||||
|
||||
MULT_REAL(Q.,REAL->T.)
|
||||
PRINT("q * real =";)
|
||||
PRINTQ(T.)
|
||||
|
||||
! multiplication is not commutative
|
||||
MULT(Q1.,Q2.->R.)
|
||||
PRINT("q1 * q2=";)
|
||||
PRINTQ(R.)
|
||||
|
||||
MULT(Q2.,Q1.->R.)
|
||||
PRINT("q2 * q1=";)
|
||||
PRINTQ(R.)
|
||||
END PROGRAM
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
func qnorm q[] .
|
||||
for i to 4
|
||||
s += q[i] * q[i]
|
||||
.
|
||||
return sqrt s
|
||||
.
|
||||
func[] qneg q[] .
|
||||
for i to 4
|
||||
q[i] = -q[i]
|
||||
.
|
||||
return q[]
|
||||
.
|
||||
func[] qconj q[] .
|
||||
for i = 2 to 4
|
||||
q[i] = -q[i]
|
||||
.
|
||||
return q[]
|
||||
.
|
||||
func[] qaddreal q[] r .
|
||||
q[1] += r
|
||||
return q[]
|
||||
.
|
||||
func[] qadd q[] q2[] .
|
||||
for i to 4
|
||||
q[i] += q2[i]
|
||||
.
|
||||
return q[]
|
||||
.
|
||||
func[] qmulreal q[] r .
|
||||
for i to 4
|
||||
q[i] *= r
|
||||
.
|
||||
return q[]
|
||||
.
|
||||
func[] qmul q1[] q2[] .
|
||||
res[] &= q1[1] * q2[1] - q1[2] * q2[2] - q1[3] * q2[3] - q1[4] * q2[4]
|
||||
res[] &= q1[1] * q2[2] + q1[2] * q2[1] + q1[3] * q2[4] - q1[4] * q2[3]
|
||||
res[] &= q1[1] * q2[3] - q1[2] * q2[4] + q1[3] * q2[1] + q1[4] * q2[2]
|
||||
res[] &= q1[1] * q2[4] + q1[2] * q2[3] - q1[3] * q2[2] + q1[4] * q2[1]
|
||||
return res[]
|
||||
.
|
||||
q[] = [ 1 2 3 4 ]
|
||||
q1[] = [ 2 3 4 5 ]
|
||||
q2[] = [ 3 4 5 6 ]
|
||||
r = 7
|
||||
#
|
||||
print "q = " & q[]
|
||||
print "q1 = " & q1[]
|
||||
print "q2 = " & q2[]
|
||||
print "r = " & r
|
||||
print "norm(q) = " & qnorm q[]
|
||||
print "neg(q) = " & qneg q[]
|
||||
print "conjugate(q) = " & qconj q[]
|
||||
print "q+r = " & qaddreal q[] r
|
||||
print "q1+q2 = " & qadd q1[] q2[]
|
||||
print "qr = " & qmulreal q[] r
|
||||
print "q1q2 = " & qmul q1[] q2[]
|
||||
print "q2q1 = " & qmul q2[] q1[]
|
||||
if q1[] <> q2[]
|
||||
print "q1 != q2"
|
||||
.
|
||||
|
|
@ -1,102 +0,0 @@
|
|||
#import <Foundation/Foundation.h>
|
||||
|
||||
interface Quaternion : Number
|
||||
// Properties -- note that this is an immutable class.
|
||||
double real, i, j, k {readonly}
|
||||
end
|
||||
|
||||
implementation Quaternion
|
||||
|
||||
initWithReal: double, i: double, j: double, k: double, return instancetype
|
||||
self = super.init
|
||||
if self
|
||||
_real = real; _i = i; _j = j; _k = k
|
||||
return self
|
||||
|
||||
+new: double real, ..., return instancetype
|
||||
va_list args
|
||||
va_start(args, real)
|
||||
object := Quaternion.alloc.initWithReal: real,
|
||||
i: va_arg(args, double),
|
||||
j: va_arg(args, double),
|
||||
k: va_arg(args, double)
|
||||
va_end(args)
|
||||
return object
|
||||
|
||||
descriptionWithLocale: id, return String = String.stringWithFormat:
|
||||
'(%.1f, %.1f, %.1f, %.1f)', self.real, self.i, self.j, self.k
|
||||
|
||||
norm, return double =
|
||||
sqrt(self.real * self.real +
|
||||
self.i * self.i + self.j * self.j + self.k * self.k)
|
||||
|
||||
negative, return Quaternion =
|
||||
Quaternion.new: -self.real, -self.i, -self.j, -self.k
|
||||
|
||||
conjugate, return Quaternion =
|
||||
Quaternion.new: self.real, -self.i, -self.j, -self.k
|
||||
|
||||
// Overload "+" operator (left operand is Quaternion)
|
||||
plus: Number operand, return Quaternion
|
||||
real := self.real, i = self.i, j = self.j, k = self.k
|
||||
if operand.isKindOfClass: Quaternion.class
|
||||
q := (Quaternion)operand
|
||||
real += q.real; i += q.i; j += q.j; k += q.k
|
||||
else
|
||||
real += (double)operand
|
||||
return Quaternion.new: real, i, j, k
|
||||
|
||||
// Overload "*" operator (left operand is Quaternion)
|
||||
multipliedBy: Number operand, return Quaternion
|
||||
real := self.real, i = self.i, j = self.j, k = self.k
|
||||
if operand.isKindOfClass: Quaternion.class
|
||||
q := (Quaternion)operand
|
||||
real = self.real * q.real - self.i* q.i - self.j * q.j - self.k * q.k
|
||||
i = self.real * q.i + self.i * q.real + self.j * q.k - self.k * q.j
|
||||
j = self.real * q.j - self.i * q.k + self.j * q.real + self.k * q.i
|
||||
k = self.real * q.k + self.i * q.j - self.j * q.i + self.k * q.real
|
||||
else
|
||||
real *= (double)operand
|
||||
i *= (double)operand; j *= (double)operand; k *= (double)operand
|
||||
return Quaternion.new: real, i, j, k
|
||||
|
||||
end
|
||||
|
||||
implementation Number (QuaternionOperators)
|
||||
|
||||
// Overload "+" operator (left operand is Number)
|
||||
plus: Quaternion operand, return Quaternion
|
||||
real := (double)self + operand.real
|
||||
return Quaternion.new: real, operand.i, operand.j, operand.k
|
||||
|
||||
// Overload "*" operator (left operand is Number)
|
||||
multipliedBy: Quaternion operand, return Quaternion
|
||||
r := (double)self
|
||||
return Quaternion.new: r * operand.real, r * operand.i,
|
||||
r * operand.j, r * operand.k
|
||||
|
||||
end
|
||||
|
||||
int main()
|
||||
autoreleasepool
|
||||
|
||||
q := Quaternion.new: 1.0, 2.0, 3.0, 4.0
|
||||
q1 := Quaternion.new: 2.0, 3.0, 4.0, 5.0
|
||||
q2 := Quaternion.new: 3.0, 4.0, 5.0, 6.0
|
||||
|
||||
Log( 'q = %@', q )
|
||||
Log( 'q1 = %@', q1 )
|
||||
Log( 'q2 = %@\n\n', q2 )
|
||||
|
||||
Log( 'q norm = %.3f', q.norm )
|
||||
Log( 'q negative = %@', q.negative )
|
||||
Log( 'q conjugate = %@', q.conjugate )
|
||||
Log( '7 + q = %@', 7.0 + q )
|
||||
Log( 'q + 7 = %@', q + 7.0 )
|
||||
Log( 'q1 + q2 = %@', q1 + q2 )
|
||||
Log( '7 * q = %@', 7 * q)
|
||||
Log( 'q * 7 = %@', q * 7.0 )
|
||||
Log( 'q1 * q2 = %@', q1 * q2 )
|
||||
Log( 'q2 * q1 = %@', q2 * q1 )
|
||||
|
||||
return 0
|
||||
|
|
@ -1,88 +0,0 @@
|
|||
import system'math;
|
||||
import extensions;
|
||||
import extensions'text;
|
||||
|
||||
struct Quaternion
|
||||
{
|
||||
real A : rprop;
|
||||
real B : rprop;
|
||||
real C : rprop;
|
||||
real D : rprop;
|
||||
|
||||
constructor new(a, b, c, d)
|
||||
<= new(cast real(a), cast real(b), cast real(c), cast real(d));
|
||||
|
||||
constructor new(real a, real b, real c, real d)
|
||||
{
|
||||
A := a;
|
||||
B := b;
|
||||
C := c;
|
||||
D := d
|
||||
}
|
||||
|
||||
constructor(real r)
|
||||
{
|
||||
A := r;
|
||||
B := 0.0r;
|
||||
C := 0.0r;
|
||||
D := 0.0r
|
||||
}
|
||||
|
||||
real Norm = (A*A + B*B + C*C + D*D).sqrt();
|
||||
|
||||
Quaternion Negative = Quaternion.new(A.Negative,B.Negative,C.Negative,D.Negative);
|
||||
|
||||
Quaternion Conjugate = Quaternion.new(A,B.Negative,C.Negative,D.Negative);
|
||||
|
||||
Quaternion add(Quaternion q)
|
||||
= Quaternion.new(A + q.A, B + q.B, C + q.C, D + q.D);
|
||||
|
||||
Quaternion multiply(Quaternion q)
|
||||
= Quaternion.new(
|
||||
A * q.A - B * q.B - C * q.C - D * q.D,
|
||||
A * q.B + B * q.A + C * q.D - D * q.C,
|
||||
A * q.C - B * q.D + C * q.A + D * q.B,
|
||||
A * q.D + B * q.C - C * q.B + D * q.A);
|
||||
|
||||
Quaternion add(real r)
|
||||
<= add(Quaternion.new(r,0,0,0));
|
||||
|
||||
Quaternion multiply(real r)
|
||||
<= multiply(Quaternion.new(r,0,0,0));
|
||||
|
||||
bool equal(Quaternion q)
|
||||
= (A == q.A) && (B == q.B) && (C == q.C) && (D == q.D);
|
||||
|
||||
string toPrintable()
|
||||
= new StringWriter().printFormatted("Q({0}, {1}, {2}, {3})",A,B,C,D);
|
||||
}
|
||||
|
||||
public program()
|
||||
{
|
||||
auto q := Quaternion.new(1,2,3,4);
|
||||
auto q1 := Quaternion.new(2,3,4,5);
|
||||
auto q2 := Quaternion.new(3,4,5,6);
|
||||
real r := 7;
|
||||
|
||||
console.printLine("q = ", q);
|
||||
console.printLine("q1 = ", q1);
|
||||
console.printLine("q2 = ", q2);
|
||||
console.printLine("r = ", r);
|
||||
|
||||
console.printLine("q.Norm() = ", q.Norm);
|
||||
console.printLine("q1.Norm() = ", q1.Norm);
|
||||
console.printLine("q2.Norm() = ", q2.Norm);
|
||||
|
||||
console.printLine("-q = ", q.Negative);
|
||||
console.printLine("q.Conjugate() = ", q.Conjugate);
|
||||
|
||||
console.printLine("q + r = ", q + r);
|
||||
console.printLine("q1 + q2 = ", q1 + q2);
|
||||
console.printLine("q2 + q1 = ", q2 + q1);
|
||||
|
||||
console.printLine("q * r = ", q * r);
|
||||
console.printLine("q1 * q2 = ", q1 * q2);
|
||||
console.printLine("q2 * q1 = ", q2 * q1);
|
||||
|
||||
console.printLineFormatted("q1*q2 {0} q2*q1", ((q1 * q2) == (q2 * q1)).iif("==","!="))
|
||||
}
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
function norm(sequence q)
|
||||
return sqrt(power(q[1],2)+power(q[2],2)+power(q[3],2)+power(q[4],2))
|
||||
end function
|
||||
|
||||
function conj(sequence q)
|
||||
q[2..4] = -q[2..4]
|
||||
return q
|
||||
end function
|
||||
|
||||
function add(object q1, object q2)
|
||||
if atom(q1) != atom(q2) then
|
||||
if atom(q1) then
|
||||
q1 = {q1,0,0,0}
|
||||
else
|
||||
q2 = {q2,0,0,0}
|
||||
end if
|
||||
end if
|
||||
return q1+q2
|
||||
end function
|
||||
|
||||
function mul(object q1, object q2)
|
||||
if sequence(q1) and sequence(q2) then
|
||||
return { q1[1]*q2[1] - q1[2]*q2[2] - q1[3]*q2[3] - q1[4]*q2[4],
|
||||
q1[1]*q2[2] + q1[2]*q2[1] + q1[3]*q2[4] - q1[4]*q2[3],
|
||||
q1[1]*q2[3] - q1[2]*q2[4] + q1[3]*q2[1] + q1[4]*q2[2],
|
||||
q1[1]*q2[4] + q1[2]*q2[3] - q1[3]*q2[2] + q1[4]*q2[1] }
|
||||
else
|
||||
return q1*q2
|
||||
end if
|
||||
end function
|
||||
|
||||
function quats(sequence q)
|
||||
return sprintf("%g + %gi + %gj + %gk",q)
|
||||
end function
|
||||
|
||||
constant
|
||||
q = {1, 2, 3, 4},
|
||||
q1 = {2, 3, 4, 5},
|
||||
q2 = {5, 6, 7, 8},
|
||||
r = 7
|
||||
|
||||
printf(1, "norm(q) = %g\n", norm(q))
|
||||
printf(1, "-q = %s\n", {quats(-q)})
|
||||
printf(1, "conj(q) = %s\n", {quats(conj(q))})
|
||||
printf(1, "q + r = %s\n", {quats(add(q,r))})
|
||||
printf(1, "q1 + q2 = %s\n", {quats(add(q1,q2))})
|
||||
printf(1, "q1 * q2 = %s\n", {quats(mul(q1,q2))})
|
||||
printf(1, "q2 * q1 = %s\n", {quats(mul(q2,q1))})
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
open System
|
||||
|
||||
[<Struct; StructuralEquality; NoComparison>]
|
||||
type Quaternion(r : float, i : float, j : float, k : float) =
|
||||
member this.A = r
|
||||
member this.B = i
|
||||
member this.C = j
|
||||
member this.D = k
|
||||
|
||||
new (f : float) = Quaternion(f, 0., 0., 0.)
|
||||
|
||||
static member (~-) (q : Quaternion) = Quaternion(-q.A, -q.B, -q.C, -q.D)
|
||||
|
||||
static member (+) (q1 : Quaternion, q2 : Quaternion) =
|
||||
Quaternion(q1.A + q2.A, q1.B + q2.B, q1.C + q2.C, q1.D + q2.D)
|
||||
static member (+) (q : Quaternion, r : float) = q + Quaternion(r)
|
||||
static member (+) (r : float, q: Quaternion) = Quaternion(r) + q
|
||||
|
||||
static member (*) (q1 : Quaternion, q2 : Quaternion) =
|
||||
Quaternion(
|
||||
q1.A * q2.A - q1.B * q2.B - q1.C * q2.C - q1.D * q2.D,
|
||||
q1.A * q2.B + q1.B * q2.A + q1.C * q2.D - q1.D * q2.C,
|
||||
q1.A * q2.C - q1.B * q2.D + q1.C * q2.A + q1.D * q2.B,
|
||||
q1.A * q2.D + q1.B * q2.C - q1.C * q2.B + q1.D * q2.A)
|
||||
static member (*) (q : Quaternion, r : float) = q * Quaternion(r)
|
||||
static member (*) (r : float, q: Quaternion) = Quaternion(r) * q
|
||||
|
||||
member this.Norm = Math.Sqrt(r * r + i * i + j * j + k * k)
|
||||
|
||||
member this.Conjugate = Quaternion(r, -i, -j, -k)
|
||||
|
||||
override this.ToString() = sprintf "Q(%f, %f, %f, %f)" r i j k
|
||||
|
||||
[<EntryPoint>]
|
||||
let main argv =
|
||||
let q = Quaternion(1., 2., 3., 4.)
|
||||
let q1 = Quaternion(2., 3., 4., 5.)
|
||||
let q2 = Quaternion(3., 4., 5., 6.)
|
||||
let r = 7.
|
||||
|
||||
printfn "q = %A" q
|
||||
printfn "q1 = %A" q1
|
||||
printfn "q2 = %A" q2
|
||||
printfn "r = %A" r
|
||||
|
||||
printfn "q.Norm = %A" q.Norm
|
||||
printfn "q1.Norm = %A" q1.Norm
|
||||
printfn "q2.Norm = %A" q2.Norm
|
||||
|
||||
printfn "-q = %A" -q
|
||||
printfn "q.Conjugate = %A" q.Conjugate
|
||||
|
||||
printfn "q + r = %A" (q + (Quaternion r))
|
||||
printfn "q1 + q2 = %A" (q1 + q2)
|
||||
printfn "q2 + q1 = %A" (q2 + q1)
|
||||
|
||||
printfn "q * r = %A" (q * r)
|
||||
printfn "q1 * q2 = %A" (q1 * q2)
|
||||
printfn "q2 * q1 = %A" (q2 * q1)
|
||||
|
||||
printfn "q1*q2 %s q2*q1" (if (q1 * q2) = (q2 * q1) then "=" else "<>")
|
||||
printfn "q %s Q(1.,2.,3.,4.)" (if q = Quaternion(1., 2., 3., 4.) then "=" else "<>")
|
||||
0
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
USING: generalizations io kernel locals math.quaternions
|
||||
math.vectors prettyprint sequences ;
|
||||
IN: rosetta-code.quaternion-type
|
||||
|
||||
: show ( quot -- )
|
||||
[ unparse 2 tail but-last "= " append write ] [ call . ] bi
|
||||
; inline
|
||||
|
||||
: 2show ( quots -- )
|
||||
[ 2curry show ] map-compose [ call ] each ; inline
|
||||
|
||||
: q+n ( q n -- q+n ) n>q q+ ;
|
||||
|
||||
[let
|
||||
{ 1 2 3 4 } 7 { 2 3 4 5 } { 3 4 5 6 } :> ( q r q1 q2 )
|
||||
q [ norm ]
|
||||
q [ vneg ]
|
||||
q [ qconjugate ]
|
||||
[ curry show ] 2tri@
|
||||
{
|
||||
[ q r [ q+n ] ]
|
||||
[ q r [ q*n ] ]
|
||||
[ q1 q2 [ q+ ] ]
|
||||
[ q1 q2 [ q* ] ]
|
||||
[ q2 q1 [ q* ] ]
|
||||
} 2show
|
||||
]
|
||||
|
|
@ -1,77 +0,0 @@
|
|||
: quaternions 4 * floats ;
|
||||
|
||||
: qvariable create 1 quaternions allot ;
|
||||
|
||||
: q! ( a b c d q -- )
|
||||
dup 3 floats + f! dup 2 floats + f! dup float+ f! f! ;
|
||||
|
||||
: qcopy ( src dest -- ) 1 quaternions move ;
|
||||
|
||||
: qnorm ( q -- f )
|
||||
0e 4 0 do dup f@ fdup f* f+ float+ loop drop fsqrt ;
|
||||
|
||||
: qf* ( q f -- )
|
||||
4 0 do dup f@ fover f* dup f! float+ loop fdrop drop ;
|
||||
|
||||
: qnegate ( q -- ) -1e qf* ;
|
||||
|
||||
: qconj ( q -- )
|
||||
float+ 3 0 do dup f@ fnegate dup f! float+ loop drop ;
|
||||
|
||||
: qf+ ( q f -- ) dup f@ f+ f! ;
|
||||
|
||||
: q+ ( q1 q2 -- )
|
||||
4 0 do over f@ dup f@ f+ dup f! float+ swap float+ swap loop 2drop ;
|
||||
|
||||
\ access
|
||||
: q.a f@ ;
|
||||
: q.b float+ f@ ;
|
||||
: q.c 2 floats + f@ ;
|
||||
: q.d 3 floats + f@ ;
|
||||
|
||||
: q* ( dest q1 q2 -- )
|
||||
over q.a dup q.d f* over q.b dup q.c f* f+ over q.c dup q.b f* f- over q.d dup q.a f* f+
|
||||
over q.a dup q.c f* over q.b dup q.d f* f- over q.c dup q.a f* f+ over q.d dup q.b f* f+
|
||||
over q.a dup q.b f* over q.b dup q.a f* f+ over q.c dup q.d f* f+ over q.d dup q.c f* f-
|
||||
over q.a dup q.a f* over q.b dup q.b f* f- over q.c dup q.c f* f- over q.d dup q.d f* f-
|
||||
2drop 4 0 do dup f! float+ loop drop ;
|
||||
|
||||
: q= ( q1 q2 -- ? )
|
||||
4 0 do
|
||||
over f@ dup f@ f<> if 2drop false unloop exit then
|
||||
float+ swap float+
|
||||
loop
|
||||
2drop true ;
|
||||
|
||||
\ testing
|
||||
|
||||
: q. ( q -- )
|
||||
[char] ( emit space
|
||||
4 0 do dup f@ f. float+ loop drop
|
||||
[char] ) emit space ;
|
||||
|
||||
qvariable q 1e 2e 3e 4e q q!
|
||||
qvariable q1 2e 3e 4e 5e q1 q!
|
||||
create q2 3e f, 4e f, 5e f, 6e f, \ by hand
|
||||
|
||||
qvariable tmp
|
||||
qvariable m1
|
||||
qvariable m2
|
||||
|
||||
q qnorm f. \ 5.47722557505166
|
||||
q tmp qcopy tmp qnegate tmp q. \ ( -1. -2. -3. -4. )
|
||||
q tmp qcopy tmp qconj tmp q. \ ( 1. -2. -3. -4. )
|
||||
|
||||
q m1 qcopy m1 7e qf+ m1 q. \ ( 8. 2. 3. 4. )
|
||||
q m2 qcopy 7e m2 qf+ m2 q. \ ( 8. 2. 3. 4. )
|
||||
m1 m2 q= . \ -1 (true)
|
||||
|
||||
q2 tmp qcopy q1 tmp q+ tmp q. \ ( 5. 7. 9. 11. )
|
||||
|
||||
q m1 qcopy m1 7e qf* m1 q. \ ( 7. 14. 21. 28. )
|
||||
q m2 qcopy 7e m2 qf* m2 q. \ ( 7. 14. 21. 28. )
|
||||
m1 m2 q= . \ -1 (true)
|
||||
|
||||
m1 q1 q2 q* m1 q. \ ( -56. 16. 24. 26. )
|
||||
m2 q2 q1 q* m2 q. \ ( -56. 18. 20. 28. )
|
||||
m1 m2 q= . \ 0 (false)
|
||||
|
|
@ -1,161 +0,0 @@
|
|||
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
|
||||
|
|
@ -1,77 +0,0 @@
|
|||
Dim Shared As Integer q(3) = {1, 2, 3, 4}
|
||||
Dim Shared As Integer q1(3) = {2, 3, 4, 5}
|
||||
Dim Shared As Integer q2(3) = {3, 4, 5, 6}
|
||||
Dim Shared As Integer i, r = 7, t(3)
|
||||
|
||||
Function q_norm(q() As Integer) As Double
|
||||
' medida o valor absoluto de un cuaternión
|
||||
Dim As Double a = 0
|
||||
For i = 0 To 3
|
||||
a += q(i)^2
|
||||
Next i
|
||||
Return Sqr(a)
|
||||
End Function
|
||||
|
||||
Sub q_neg(q() As Integer)
|
||||
For i = 0 To 3
|
||||
q(i) *= -1
|
||||
Next i
|
||||
End Sub
|
||||
|
||||
Sub q_conj(q() As Integer)
|
||||
' conjugado de un cuaternión
|
||||
For i = 1 To 3
|
||||
q(i) *= -1
|
||||
Next i
|
||||
End Sub
|
||||
|
||||
Sub q_addreal(q() As Integer, r As Integer)
|
||||
q(0) += r
|
||||
End Sub
|
||||
|
||||
Sub q_add(q() As Integer, r() As Integer)
|
||||
' adición entre cuaternios
|
||||
For i = 0 To 3
|
||||
q(i) += r(i)
|
||||
Next i
|
||||
End Sub
|
||||
|
||||
Sub q_mulreal(q() As Integer, r As Integer)
|
||||
For i = 0 To 3
|
||||
q(i) *= r
|
||||
Next i
|
||||
End Sub
|
||||
|
||||
Sub q_mul(q() As Integer, r() As Integer)
|
||||
' producto entre cuaternios
|
||||
Dim As Integer m(3)
|
||||
m(0) = q(0)*r(0) - q(1)*r(1) - q(2)*r(2) - q(3)*r(3)
|
||||
m(1) = q(0)*r(1) + q(1)*r(0) + q(2)*r(3) - q(3)*r(2)
|
||||
m(2) = q(0)*r(2) - q(1)*r(3) + q(2)*r(0) + q(3)*r(1)
|
||||
m(3) = q(0)*r(3) + q(1)*r(2) - q(2)*r(1) + q(3)*r(0)
|
||||
For i = 0 To 3 : q(i) = m(i) : Next i
|
||||
End Sub
|
||||
|
||||
Function q_show(q() As Integer) As String
|
||||
Dim As String a = "("
|
||||
For i = 0 To 3
|
||||
a += Str(q(i)) + ", "
|
||||
Next i
|
||||
Return Mid(a,1,Len(a)-2) + ")"
|
||||
End Function
|
||||
|
||||
'--- Programa Principal ---
|
||||
Print " q = "; q_show(q())
|
||||
Print "q1 = "; q_show(q1())
|
||||
Print "q2 = "; q_show(q2())
|
||||
Print " r = "; r
|
||||
Print "norm(q) ="; q_norm(q())
|
||||
For i = 0 To 3 : t(i) = q(i) : Next i : q_neg(t()) : Print " neg(q) = "; q_show(t())
|
||||
For i = 0 To 3 : t(i) = q(i) : Next i : q_conj(t()) : Print "conj(q) = "; q_show(t())
|
||||
For i = 0 To 3 : t(i) = q(i) : Next i : q_addreal(t(),r) : Print " r + q = "; q_show(t())
|
||||
For i = 0 To 3 : t(i) = q1(i) : Next i : q_add(t(),q2()) : Print "q1 + q2 = "; q_show(t())
|
||||
For i = 0 To 3 : t(i) = q2(i) : Next i : q_add(t(),q1()) : Print "q2 + q1 = "; q_show(t())
|
||||
For i = 0 To 3 : t(i) = q(i) : Next i : q_mulreal(t(),r) : Print " r * q = "; q_show(t())
|
||||
For i = 0 To 3 : t(i) = q1(i) : Next i : q_mul(t(),q2()) : Print "q1 * q2 = "; q_show(t())
|
||||
For i = 0 To 3 : t(i) = q2(i) : Next i : q_mul(t(),q1()) : Print "q2 * q1 = "; q_show(t())
|
||||
End
|
||||
|
|
@ -1,110 +0,0 @@
|
|||
# GAP has built-in support for quaternions
|
||||
|
||||
A := QuaternionAlgebra(Rationals);
|
||||
# <algebra-with-one of dimension 4 over Rationals>
|
||||
|
||||
b := BasisVectors(Basis(A));
|
||||
# [ e, i, j, k ]
|
||||
|
||||
q := [1, 2, 3, 4]*b;
|
||||
# e+(2)*i+(3)*j+(4)*k
|
||||
|
||||
# Conjugate
|
||||
ComplexConjugate(q);
|
||||
# e+(-2)*i+(-3)*j+(-4)*k
|
||||
|
||||
# Division
|
||||
1/q;
|
||||
# (1/30)*e+(-1/15)*i+(-1/10)*j+(-2/15)*k
|
||||
|
||||
# Computing norm may be difficult, since the result would be in a quadratic field.
|
||||
# Sqrt exists in GAP, but it is quite unusual: see ?E in GAP documentation, and the following example
|
||||
Sqrt(5/3);
|
||||
# 1/3*E(60)^7+1/3*E(60)^11-1/3*E(60)^19-1/3*E(60)^23-1/3*E(60)^31+1/3*E(60)^43-1/3*E(60)^47+1/3*E(60)^59
|
||||
|
||||
# However, the square of the norm is easy to compute
|
||||
q*ComplexConjugate(q);
|
||||
# (30)*e
|
||||
|
||||
q1 := [2, 3, 4, 5]*b;
|
||||
# (2)*e+(3)*i+(4)*j+(5)*k
|
||||
|
||||
q2 := [3, 4, 5, 6]*b;
|
||||
# (3)*e+(4)*i+(5)*j+(6)*k
|
||||
|
||||
q1*q2 - q2*q1;
|
||||
# (-2)*i+(4)*j+(-2)*k
|
||||
|
||||
# Can't add directly to a rational, one must make a quaternion of it
|
||||
r := 5/3*b[1];
|
||||
# (5/3)*e
|
||||
r + q;
|
||||
# (8/3)*e+(2)*i+(3)*j+(4)*k
|
||||
|
||||
# For multiplication, no problem (we are in an algebra over rationals !)
|
||||
r*q;
|
||||
# (5/3)*e+(10/3)*i+(5)*j+(20/3)*k
|
||||
5/3*q;
|
||||
# (5/3)*e+(10/3)*i+(5)*j+(20/3)*k
|
||||
|
||||
# Negative
|
||||
-q;
|
||||
(-1)*e+(-2)*i+(-3)*j+(-4)*k
|
||||
|
||||
|
||||
# While quaternions are built-in, you can define an algebra in GAP by specifying it's multiplication table.
|
||||
# See tutorial, p. 60, and reference of the functions used below.
|
||||
|
||||
# A multiplication table of dimension 4.
|
||||
|
||||
T := EmptySCTable(4, 0);
|
||||
SetEntrySCTable(T, 1, 1, [1, 1]);
|
||||
SetEntrySCTable(T, 1, 2, [1, 2]);
|
||||
SetEntrySCTable(T, 1, 3, [1, 3]);
|
||||
SetEntrySCTable(T, 1, 4, [1, 4]);
|
||||
SetEntrySCTable(T, 2, 1, [1, 2]);
|
||||
SetEntrySCTable(T, 2, 2, [-1, 1]);
|
||||
SetEntrySCTable(T, 2, 3, [1, 4]);
|
||||
SetEntrySCTable(T, 2, 4, [-1, 3]);
|
||||
SetEntrySCTable(T, 3, 1, [1, 3]);
|
||||
SetEntrySCTable(T, 3, 2, [-1, 4]);
|
||||
SetEntrySCTable(T, 3, 3, [-1, 1]);
|
||||
SetEntrySCTable(T, 3, 4, [1, 2]);
|
||||
SetEntrySCTable(T, 4, 1, [1, 4]);
|
||||
SetEntrySCTable(T, 4, 2, [1, 3]);
|
||||
SetEntrySCTable(T, 4, 3, [-1, 2]);
|
||||
SetEntrySCTable(T, 4, 4, [-1, 1]);
|
||||
|
||||
A := AlgebraByStructureConstants(Rationals, T, ["e", "i", "j", "k"]);
|
||||
b := GeneratorsOfAlgebra(A);
|
||||
|
||||
IsAssociative(A);
|
||||
# true
|
||||
|
||||
IsCommutative(A);
|
||||
# false
|
||||
|
||||
# Then, like above
|
||||
|
||||
q := [1, 2, 3, 4]*b;
|
||||
# e+(2)*i+(3)*j+(4)*k
|
||||
|
||||
# However, as is, GAP does not know division or conjugate on this algebra.
|
||||
# QuaternionAlgebra is useful as well for extensions of rationals,
|
||||
# and this one _has_ conjugate and division, as seen previously.
|
||||
|
||||
# Try this on Q[z] where z is the square root of 5 (in GAP it's ER(5))
|
||||
F := FieldByGenerators([ER(5)]);
|
||||
A := QuaternionAlgebra(F);
|
||||
b := GeneratorsOfAlgebra(A);
|
||||
|
||||
q := [1, 2, 3, 4]*b;
|
||||
# e+(2)*i+(3)*j+(4)*k
|
||||
|
||||
# Conjugate and division
|
||||
|
||||
ComplexConjugate(q);
|
||||
# e+(-2)*i+(-3)*j+(-4)*k
|
||||
|
||||
1/q;
|
||||
# (1/30)*e+(-1/15)*i+(-1/10)*j+(-2/15)*k
|
||||
|
|
@ -1,79 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
)
|
||||
|
||||
type qtn struct {
|
||||
r, i, j, k float64
|
||||
}
|
||||
|
||||
var (
|
||||
q = &qtn{1, 2, 3, 4}
|
||||
q1 = &qtn{2, 3, 4, 5}
|
||||
q2 = &qtn{3, 4, 5, 6}
|
||||
|
||||
r float64 = 7
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println("Inputs")
|
||||
fmt.Println("q:", q)
|
||||
fmt.Println("q1:", q1)
|
||||
fmt.Println("q2:", q2)
|
||||
fmt.Println("r:", r)
|
||||
|
||||
var qr qtn
|
||||
fmt.Println("\nFunctions")
|
||||
fmt.Println("q.norm():", q.norm())
|
||||
fmt.Println("neg(q):", qr.neg(q))
|
||||
fmt.Println("conj(q):", qr.conj(q))
|
||||
fmt.Println("addF(q, r):", qr.addF(q, r))
|
||||
fmt.Println("addQ(q1, q2):", qr.addQ(q1, q2))
|
||||
fmt.Println("mulF(q, r):", qr.mulF(q, r))
|
||||
fmt.Println("mulQ(q1, q2):", qr.mulQ(q1, q2))
|
||||
fmt.Println("mulQ(q2, q1):", qr.mulQ(q2, q1))
|
||||
}
|
||||
|
||||
func (q *qtn) String() string {
|
||||
return fmt.Sprintf("(%g, %g, %g, %g)", q.r, q.i, q.j, q.k)
|
||||
}
|
||||
|
||||
func (q *qtn) norm() float64 {
|
||||
return math.Sqrt(q.r*q.r + q.i*q.i + q.j*q.j + q.k*q.k)
|
||||
}
|
||||
|
||||
func (z *qtn) neg(q *qtn) *qtn {
|
||||
z.r, z.i, z.j, z.k = -q.r, -q.i, -q.j, -q.k
|
||||
return z
|
||||
}
|
||||
|
||||
func (z *qtn) conj(q *qtn) *qtn {
|
||||
z.r, z.i, z.j, z.k = q.r, -q.i, -q.j, -q.k
|
||||
return z
|
||||
}
|
||||
|
||||
func (z *qtn) addF(q *qtn, r float64) *qtn {
|
||||
z.r, z.i, z.j, z.k = q.r+r, q.i, q.j, q.k
|
||||
return z
|
||||
}
|
||||
|
||||
func (z *qtn) addQ(q1, q2 *qtn) *qtn {
|
||||
z.r, z.i, z.j, z.k = q1.r+q2.r, q1.i+q2.i, q1.j+q2.j, q1.k+q2.k
|
||||
return z
|
||||
}
|
||||
|
||||
func (z *qtn) mulF(q *qtn, r float64) *qtn {
|
||||
z.r, z.i, z.j, z.k = q.r*r, q.i*r, q.j*r, q.k*r
|
||||
return z
|
||||
}
|
||||
|
||||
func (z *qtn) mulQ(q1, q2 *qtn) *qtn {
|
||||
z.r, z.i, z.j, z.k =
|
||||
q1.r*q2.r-q1.i*q2.i-q1.j*q2.j-q1.k*q2.k,
|
||||
q1.r*q2.i+q1.i*q2.r+q1.j*q2.k-q1.k*q2.j,
|
||||
q1.r*q2.j-q1.i*q2.k+q1.j*q2.r+q1.k*q2.i,
|
||||
q1.r*q2.k+q1.i*q2.j-q1.j*q2.i+q1.k*q2.r
|
||||
return z
|
||||
}
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
import Control.Monad (join)
|
||||
|
||||
data Quaternion a =
|
||||
Q a a a a
|
||||
deriving (Show, Eq)
|
||||
|
||||
realQ :: Quaternion a -> a
|
||||
realQ (Q r _ _ _) = r
|
||||
|
||||
imagQ :: Quaternion a -> [a]
|
||||
imagQ (Q _ i j k) = [i, j, k]
|
||||
|
||||
quaternionFromScalar :: (Num a) => a -> Quaternion a
|
||||
quaternionFromScalar s = Q s 0 0 0
|
||||
|
||||
listFromQ :: Quaternion a -> [a]
|
||||
listFromQ (Q a b c d) = [a, b, c, d]
|
||||
|
||||
quaternionFromList :: [a] -> Quaternion a
|
||||
quaternionFromList [a, b, c, d] = Q a b c d
|
||||
|
||||
normQ :: (RealFloat a) => Quaternion a -> a
|
||||
normQ = sqrt . sum . join (zipWith (*)) . listFromQ
|
||||
|
||||
conjQ :: (Num a) => Quaternion a -> Quaternion a
|
||||
conjQ (Q a b c d) = Q a (-b) (-c) (-d)
|
||||
|
||||
instance (RealFloat a) => Num (Quaternion a) where
|
||||
(Q a b c d) + (Q p q r s) = Q (a + p) (b + q) (c + r) (d + s)
|
||||
(Q a b c d) - (Q p q r s) = Q (a - p) (b - q) (c - r) (d - s)
|
||||
(Q a b c d) * (Q p q r s) =
|
||||
Q
|
||||
(a * p - b * q - c * r - d * s)
|
||||
(a * q + b * p + c * s - d * r)
|
||||
(a * r - b * s + c * p + d * q)
|
||||
(a * s + b * r - c * q + d * p)
|
||||
negate (Q a b c d) = Q (-a) (-b) (-c) (-d)
|
||||
abs q = quaternionFromScalar (normQ q)
|
||||
signum (Q 0 0 0 0) = 0
|
||||
signum q@(Q a b c d) = Q (a/n) (b/n) (c/n) (d/n) where n = normQ q
|
||||
fromInteger n = quaternionFromScalar (fromInteger n)
|
||||
|
||||
main :: IO ()
|
||||
main = do
|
||||
let q, q1, q2 :: Quaternion Double
|
||||
q = Q 1 2 3 4
|
||||
q1 = Q 2 3 4 5
|
||||
q2 = Q 3 4 5 6
|
||||
print $ (Q 0 1 0 0) * (Q 0 0 1 0) * (Q 0 0 0 1) -- i*j*k; prints "Q (-1.0) 0.0 0.0 0.0"
|
||||
print $ q1 * q2 -- prints "Q (-56.0) 16.0 24.0 26.0"
|
||||
print $ q2 * q1 -- prints "Q (-56.0) 18.0 20.0 28.0"
|
||||
print $ q1 * q2 == q2 * q1 -- prints "False"
|
||||
print $ imagQ q -- prints "[2.0,3.0,4.0]"
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
class Quaternion(a, b, c, d)
|
||||
|
||||
method norm ()
|
||||
return sqrt (a*a + b*b + c*c + d*d)
|
||||
end
|
||||
|
||||
method negative ()
|
||||
return Quaternion(-a, -b, -c, -d)
|
||||
end
|
||||
|
||||
method conjugate ()
|
||||
return Quaternion(a, -b, -c, -d)
|
||||
end
|
||||
|
||||
method add (n)
|
||||
if type(n) == "Quaternion__state"
|
||||
then return Quaternion(a+n.a, b+n.b, c+n.c, d+n.d)
|
||||
else return Quaternion(a+n, b, c, d)
|
||||
end
|
||||
|
||||
method multiply (n)
|
||||
if type(n) == "Quaternion__state"
|
||||
then return Quaternion(a*n.a - b*n.b - c*n.c - d*n.d,
|
||||
a*n.b + b*n.a + c*n.d - d*n.c,
|
||||
a*n.c - b*n.d + c*n.a + d*n.b,
|
||||
a*n.d + b*n.c - c*n.b + d*n.a)
|
||||
else return Quaternion(a*n, b*n, c*n, d*n)
|
||||
end
|
||||
|
||||
method sign (n)
|
||||
return if n >= 0 then "+" else "-"
|
||||
end
|
||||
|
||||
method string ()
|
||||
return ("" || a || sign(b) || abs(b) || "i" || sign(c) || abs(c) || "j" || sign(d) || abs(d) || "k");
|
||||
end
|
||||
|
||||
initially(a, b, c, d)
|
||||
self.a := if /a then 0 else a
|
||||
self.b := if /b then 0 else b
|
||||
self.c := if /c then 0 else c
|
||||
self.d := if /d then 0 else d
|
||||
end
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
procedure main ()
|
||||
q := Quaternion (1,2,3,4)
|
||||
q1 := Quaternion (2,3,4,5)
|
||||
q2 := Quaternion (3,4,5,6)
|
||||
r := 7
|
||||
|
||||
write ("The norm of " || q.string() || " is " || q.norm ())
|
||||
write ("The negative of " || q.string() || " is " || q.negative().string ())
|
||||
write ("The conjugate of " || q.string() || " is " || q.conjugate().string ())
|
||||
write ("Sum of " || q.string() || " and " || r || " is " || q.add(r).string ())
|
||||
write ("Sum of " || q.string() || " and " || q1.string() || " is " || q.add(q1).string ())
|
||||
write ("Product of " || q.string() || " and " || r || " is " || q.multiply(r).string ())
|
||||
write ("Product of " || q.string() || " and " || q1.string() || " is " || q.multiply(q1).string ())
|
||||
write ("q1*q2 = " || q1.multiply(q2).string ())
|
||||
write ("q2*q1 = " || q2.multiply(q1).string ())
|
||||
end
|
||||
|
|
@ -1,95 +0,0 @@
|
|||
module CayleyDickson
|
||||
|
||||
data CD : Nat -> Type -> Type where
|
||||
CDBase : a -> CD 0 a
|
||||
CDProd : CD n a -> CD n a -> CD (S n) a
|
||||
|
||||
pairTy : Nat -> Type -> Type
|
||||
pairTy Z a = a
|
||||
pairTy (S n) a = let b = pairTy n a in (b, b)
|
||||
|
||||
fromPair : (n : Nat) -> pairTy n a -> CD n a
|
||||
fromPair Z x = CDBase x
|
||||
fromPair (S m) (x, y) = CDProd (fromPair m x) $ fromPair m y
|
||||
|
||||
toPair : CD n a -> pairTy n a
|
||||
toPair (CDBase x) = x
|
||||
toPair (CDProd x v) = (toPair x, toPair v)
|
||||
|
||||
first : CD n a -> a
|
||||
first (CDBase x) = x
|
||||
first (CDProd x v) = first x
|
||||
|
||||
fromBase : Num a => (n : Nat) -> a -> CD n a
|
||||
fromBase Z x = CDBase x
|
||||
fromBase (S m) x = CDProd (fromBase m x) $ fromBase m 0
|
||||
|
||||
multSclr : Num a => CD n a -> a -> CD n a
|
||||
multSclr (CDBase x) y = CDBase $ x * y
|
||||
multSclr (CDProd x v) y = CDProd (multSclr x y) $ multSclr v y
|
||||
|
||||
divSclr : Fractional a => CD n a -> a -> CD n a
|
||||
divSclr (CDBase x) y = CDBase $ x / y
|
||||
divSclr (CDProd x v) y = CDProd (divSclr x y) $ divSclr v y
|
||||
|
||||
plusCD : Num a => CD n a -> CD n a -> CD n a
|
||||
plusCD (CDBase x) (CDBase y) = CDBase $ x + y
|
||||
plusCD (CDProd x v) (CDProd y w) = CDProd (plusCD x y) $ plusCD v w
|
||||
|
||||
negCD : Neg a => CD n a -> CD n a
|
||||
negCD (CDBase x) = CDBase $ negate x
|
||||
negCD (CDProd x v) = CDProd (negCD x) $ negCD v
|
||||
|
||||
minusCD : Neg a => CD n a -> CD n a -> CD n a
|
||||
minusCD (CDBase x) (CDBase y) = CDBase $ x - y
|
||||
minusCD (CDProd x v) (CDProd y w) = CDProd (minusCD x y) $ minusCD v w
|
||||
|
||||
conjCD : Neg a => CD n a -> CD n a
|
||||
conjCD (CDBase x) = CDBase x
|
||||
conjCD (CDProd x v) = CDProd (conjCD x) $ negCD v
|
||||
|
||||
multCD : Neg a => CD n a -> CD n a -> CD n a
|
||||
multCD (CDBase x) (CDBase y) = CDBase $ x * y
|
||||
multCD (CDProd x v) (CDProd y w) = CDProd (minusCD (multCD x y) (multCD (conjCD w) v)) $ plusCD (multCD w x) $ multCD v $ conjCD y
|
||||
|
||||
absSqrCD : Neg a => CD n a -> CD n a
|
||||
absSqrCD x = multCD x $ conjCD x
|
||||
|
||||
sqrLnCD : Neg a => CD n a -> a
|
||||
sqrLnCD = first . absSqrCD
|
||||
|
||||
recipCD : Neg a => Fractional a => CD n a -> CD n a
|
||||
recipCD x = conjCD $ divSclr x $ sqrLnCD x
|
||||
|
||||
divCD : Neg a => Fractional a => CD n a -> CD n a -> CD n a
|
||||
divCD x y = multCD x $ recipCD y
|
||||
|
||||
absCD : CD n Double -> Double
|
||||
absCD x = sqrt $ sqrLnCD x
|
||||
|
||||
showComps : Show a => CD n a -> String
|
||||
showComps (CDBase x) = show x
|
||||
showComps (CDProd x v) = showComps x ++ ", " ++ showComps v
|
||||
|
||||
Eq a => Eq (CD n a) where
|
||||
(CDBase x) == (CDBase y) = x == y
|
||||
(CDProd x v) == (CDProd y w) = x == y && v == w
|
||||
|
||||
Show a => Show (CD n a) where
|
||||
show x = "(" ++ showComps x ++ ")"
|
||||
|
||||
Neg a => Num (CD n a) where
|
||||
(+) = plusCD
|
||||
(*) = multCD
|
||||
fromInteger m {n} = fromBase n $ fromInteger m
|
||||
|
||||
Neg a => Neg (CD n a) where
|
||||
negate = negCD
|
||||
(-) = minusCD
|
||||
|
||||
(Neg a, Fractional a) => Fractional (CD n a) where
|
||||
(/) = divCD
|
||||
recip = recipCD
|
||||
|
||||
Abs (CD n Double) where
|
||||
abs {n} = fromBase n . absCD
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
import CayleyDickson
|
||||
|
||||
main : IO ()
|
||||
main =
|
||||
do
|
||||
let q = fromPair 2 ((1, 2), (3, 4))
|
||||
let q1 = fromPair 2 ((2, 3), (4, 5))
|
||||
let q2 = fromPair 2 ((3, 4), (5, 6))
|
||||
printLn $ q1 * q2
|
||||
printLn $ q2 * q1
|
||||
printLn $ q1 * q2 == q2 * q1
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
NB. utilities
|
||||
ip=: +/ .* NB. inner product
|
||||
T=. (_1^#:0 10 9 12)*0 7 16 23 A.=i.4
|
||||
toQ=: 4&{."1 :[: NB. real scalars -> quaternion
|
||||
|
||||
NB. task
|
||||
norm=: %:@ip~@toQ NB. | y
|
||||
neg=: -&toQ NB. - y and x - y
|
||||
conj=: 1 _1 _1 _1 * toQ NB. + y
|
||||
add=: +&toQ NB. x + y
|
||||
mul=: (ip T ip ])&toQ NB. x * y
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
T
|
||||
1 0 0 0
|
||||
0 1 0 0
|
||||
0 0 1 0
|
||||
0 0 0 1
|
||||
|
||||
0 _1 0 0
|
||||
1 0 0 0
|
||||
0 0 0 _1
|
||||
0 0 1 0
|
||||
|
||||
0 0 _1 0
|
||||
0 0 0 1
|
||||
1 0 0 0
|
||||
0 _1 0 0
|
||||
|
||||
0 0 0 _1
|
||||
0 0 _1 0
|
||||
0 1 0 0
|
||||
1 0 0 0
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
q=: 1 2 3 4
|
||||
q1=: 2 3 4 5
|
||||
q2=: 3 4 5 6
|
||||
r=: 7
|
||||
|
||||
norm q
|
||||
5.47723
|
||||
neg q
|
||||
_1 _2 _3 _4
|
||||
conj q
|
||||
1 _2 _3 _4
|
||||
r add q
|
||||
8 2 3 4
|
||||
q1 add q2
|
||||
5 7 9 11
|
||||
r mul q
|
||||
7 14 21 28
|
||||
q1 mul q2
|
||||
_56 16 24 26
|
||||
q2 mul q1
|
||||
_56 18 20 28
|
||||
|
|
@ -1,103 +0,0 @@
|
|||
public class Quaternion {
|
||||
private final double a, b, c, d;
|
||||
|
||||
public Quaternion(double a, double b, double c, double d) {
|
||||
this.a = a;
|
||||
this.b = b;
|
||||
this.c = c;
|
||||
this.d = d;
|
||||
}
|
||||
public Quaternion(double r) {
|
||||
this(r, 0.0, 0.0, 0.0);
|
||||
}
|
||||
|
||||
public double norm() {
|
||||
return Math.sqrt(a * a + b * b + c * c + d * d);
|
||||
}
|
||||
|
||||
public Quaternion negative() {
|
||||
return new Quaternion(-a, -b, -c, -d);
|
||||
}
|
||||
|
||||
public Quaternion conjugate() {
|
||||
return new Quaternion(a, -b, -c, -d);
|
||||
}
|
||||
|
||||
public Quaternion add(double r) {
|
||||
return new Quaternion(a + r, b, c, d);
|
||||
}
|
||||
public static Quaternion add(Quaternion q, double r) {
|
||||
return q.add(r);
|
||||
}
|
||||
public static Quaternion add(double r, Quaternion q) {
|
||||
return q.add(r);
|
||||
}
|
||||
public Quaternion add(Quaternion q) {
|
||||
return new Quaternion(a + q.a, b + q.b, c + q.c, d + q.d);
|
||||
}
|
||||
public static Quaternion add(Quaternion q1, Quaternion q2) {
|
||||
return q1.add(q2);
|
||||
}
|
||||
|
||||
public Quaternion times(double r) {
|
||||
return new Quaternion(a * r, b * r, c * r, d * r);
|
||||
}
|
||||
public static Quaternion times(Quaternion q, double r) {
|
||||
return q.times(r);
|
||||
}
|
||||
public static Quaternion times(double r, Quaternion q) {
|
||||
return q.times(r);
|
||||
}
|
||||
public Quaternion times(Quaternion q) {
|
||||
return new Quaternion(
|
||||
a * q.a - b * q.b - c * q.c - d * q.d,
|
||||
a * q.b + b * q.a + c * q.d - d * q.c,
|
||||
a * q.c - b * q.d + c * q.a + d * q.b,
|
||||
a * q.d + b * q.c - c * q.b + d * q.a
|
||||
);
|
||||
}
|
||||
public static Quaternion times(Quaternion q1, Quaternion q2) {
|
||||
return q1.times(q2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (!(obj instanceof Quaternion)) return false;
|
||||
final Quaternion other = (Quaternion) obj;
|
||||
if (Double.doubleToLongBits(this.a) != Double.doubleToLongBits(other.a)) return false;
|
||||
if (Double.doubleToLongBits(this.b) != Double.doubleToLongBits(other.b)) return false;
|
||||
if (Double.doubleToLongBits(this.c) != Double.doubleToLongBits(other.c)) return false;
|
||||
if (Double.doubleToLongBits(this.d) != Double.doubleToLongBits(other.d)) return false;
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%.2f + %.2fi + %.2fj + %.2fk", a, b, c, d).replaceAll("\\+ -", "- ");
|
||||
}
|
||||
|
||||
public String toQuadruple() {
|
||||
return String.format("(%.2f, %.2f, %.2f, %.2f)", a, b, c, d);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
Quaternion q = new Quaternion(1.0, 2.0, 3.0, 4.0);
|
||||
Quaternion q1 = new Quaternion(2.0, 3.0, 4.0, 5.0);
|
||||
Quaternion q2 = new Quaternion(3.0, 4.0, 5.0, 6.0);
|
||||
double r = 7.0;
|
||||
System.out.format("q = %s%n", q);
|
||||
System.out.format("q1 = %s%n", q1);
|
||||
System.out.format("q2 = %s%n", q2);
|
||||
System.out.format("r = %.2f%n%n", r);
|
||||
System.out.format("\u2016q\u2016 = %.2f%n", q.norm());
|
||||
System.out.format("-q = %s%n", q.negative());
|
||||
System.out.format("q* = %s%n", q.conjugate());
|
||||
System.out.format("q + r = %s%n", q.add(r));
|
||||
System.out.format("q1 + q2 = %s%n", q1.add(q2));
|
||||
System.out.format("q \u00d7 r = %s%n", q.times(r));
|
||||
Quaternion q1q2 = q1.times(q2);
|
||||
Quaternion q2q1 = q2.times(q1);
|
||||
System.out.format("q1 \u00d7 q2 = %s%n", q1q2);
|
||||
System.out.format("q2 \u00d7 q1 = %s%n", q2q1);
|
||||
System.out.format("q1 \u00d7 q2 %s q2 \u00d7 q1%n", (q1q2.equals(q2q1) ? "=" : "\u2260"));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
var Quaternion = (function() {
|
||||
// The Q() function takes an array argument and changes it
|
||||
// prototype so that it becomes a Quaternion instance. This is
|
||||
// scoped only for prototype member access.
|
||||
function Q(a) {
|
||||
a.__proto__ = proto;
|
||||
return a;
|
||||
}
|
||||
|
||||
// Actual constructor. This constructor converts its arguments to
|
||||
// an array, then that array to a Quaternion instance, then
|
||||
// returns that instance. (using "new" with this constructor is
|
||||
// optional)
|
||||
function Quaternion() {
|
||||
return Q(Array.prototype.slice.call(arguments, 0, 4));
|
||||
}
|
||||
|
||||
// Prototype for all Quaternions
|
||||
const proto = {
|
||||
// Inherits from a 4-element Array
|
||||
__proto__ : [0,0,0,0],
|
||||
|
||||
// Properties -- In addition to Array[0..3] access, we
|
||||
// also define matching a, b, c, and d properties
|
||||
get a() this[0],
|
||||
get b() this[1],
|
||||
get c() this[2],
|
||||
get d() this[3],
|
||||
|
||||
// Methods
|
||||
norm : function() Math.sqrt(this.map(function(x) x*x).reduce(function(x,y) x+y)),
|
||||
negate : function() Q(this.map(function(x) -x)),
|
||||
conjugate : function() Q([ this[0] ].concat(this.slice(1).map(function(x) -x))),
|
||||
add : function(x) {
|
||||
if ("number" === typeof x) {
|
||||
return Q([ this[0] + x ].concat(this.slice(1)));
|
||||
} else {
|
||||
return Q(this.map(function(v,i) v+x[i]));
|
||||
}
|
||||
},
|
||||
mul : function(r) {
|
||||
var q = this;
|
||||
if ("number" === typeof r) {
|
||||
return Q(q.map(function(e) e*r));
|
||||
} else {
|
||||
return Q([ q[0] * r[0] - q[1] * r[1] - q[2] * r[2] - q[3] * r[3],
|
||||
q[0] * r[1] + q[1] * r[0] + q[2] * r[3] - q[3] * r[2],
|
||||
q[0] * r[2] - q[1] * r[3] + q[2] * r[0] + q[3] * r[1],
|
||||
q[0] * r[3] + q[1] * r[2] - q[2] * r[1] + q[3] * r[0] ]);
|
||||
}
|
||||
},
|
||||
equals : function(q) this.every(function(v,i) v === q[i]),
|
||||
toString : function() (this[0] + " + " + this[1] + "i + "+this[2] + "j + " + this[3] + "k").replace(/\+ -/g, '- ')
|
||||
};
|
||||
|
||||
Quaternion.prototype = proto;
|
||||
return Quaternion;
|
||||
})();
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
var q = Quaternion(1,2,3,4);
|
||||
var q1 = Quaternion(2,3,4,5);
|
||||
var q2 = Quaternion(3,4,5,6);
|
||||
var r = 7;
|
||||
|
||||
console.log("q = "+q);
|
||||
console.log("q1 = "+q1);
|
||||
console.log("q2 = "+q2);
|
||||
console.log("r = "+r);
|
||||
console.log("1. q.norm() = "+q.norm());
|
||||
console.log("2. q.negate() = "+q.negate());
|
||||
console.log("3. q.conjugate() = "+q.conjugate());
|
||||
console.log("4. q.add(r) = "+q.add(r));
|
||||
console.log("5. q1.add(q2) = "+q1.add(q2));
|
||||
console.log("6. q.mul(r) = "+q.mul(r));
|
||||
console.log("7.a. q1.mul(q2) = "+q1.mul(q2));
|
||||
console.log("7.b. q2.mul(q1) = "+q2.mul(q1));
|
||||
console.log("8. q1.mul(q2) " + (q1.mul(q2).equals(q2.mul(q1)) ? "==" : "!=") + " q2.mul(q1)");
|
||||
|
|
@ -1,92 +0,0 @@
|
|||
def Quaternion(q0;q1;q2;q3): { "q0": q0, "q1": q1, "q2": q2, "q3": q3, "type": "Quaternion" };
|
||||
|
||||
# promotion of a real number to a quaternion
|
||||
def Quaternion(r): if (r|type) == "number" then Quaternion(r;0;0;0) else r end;
|
||||
|
||||
# thoroughly recursive pretty-print
|
||||
def pp:
|
||||
|
||||
def signage: if . >= 0 then "+ \(.)" else "- \(-.)" end;
|
||||
|
||||
if type == "object" then
|
||||
if .type == "Quaternion" then
|
||||
"\(.q0) \(.q1|signage)i \(.q2|signage)j \(.q3|signage)k"
|
||||
else with_entries( {key, "value" : (.value|pp)} )
|
||||
end
|
||||
elif type == "array" then map(pp)
|
||||
else .
|
||||
end ;
|
||||
|
||||
def real(z): Quaternion(z).q0;
|
||||
|
||||
# Note: imag(z) returns the "i" component only,
|
||||
# reflecting the embedding of the complex numbers within the quaternions:
|
||||
def imag(z): Quaternion(z).q1;
|
||||
|
||||
def conj(z): Quaternion(z) | Quaternion(.q0; -(.q1); -(.q2); -(.q3));
|
||||
|
||||
def abs2(z): Quaternion(z) | .q0 * .q0 + .q1*.q1 + .q2*.q2 + .q3*.q3;
|
||||
|
||||
def abs(z): abs2(z) | sqrt;
|
||||
|
||||
def negate(z): Quaternion(z) | Quaternion(-.q0; -.q1; -.q2; -.q3);
|
||||
|
||||
# z + w
|
||||
def plus(z; w):
|
||||
def plusq(z;w): Quaternion(z.q0 + w.q0; z.q1 + w.q1;
|
||||
z.q2 + w.q2; z.q3 + w.q3);
|
||||
plusq( Quaternion(z); Quaternion(w) );
|
||||
|
||||
# z - w
|
||||
def minus(z; w):
|
||||
def minusq(z;w): Quaternion(z.q0 - w.q0; z.q1 - w.q1;
|
||||
z.q2 - w.q2; z.q3 - w.q3);
|
||||
minusq( Quaternion(z); Quaternion(w) );
|
||||
|
||||
# *
|
||||
def times(z; w):
|
||||
def timesq(z; w):
|
||||
Quaternion(z.q0*w.q0 - z.q1*w.q1 - z.q2*w.q2 - z.q3*w.q3;
|
||||
z.q0*w.q1 + z.q1*w.q0 + z.q2*w.q3 - z.q3*w.q2;
|
||||
z.q0*w.q2 - z.q1*w.q3 + z.q2*w.q0 + z.q3*w.q1;
|
||||
z.q0*w.q3 + z.q1*w.q2 - z.q2*w.q1 + z.q3*w.q0);
|
||||
timesq( Quaternion(z); Quaternion(w) );
|
||||
|
||||
# (z/w)
|
||||
def div(z; w):
|
||||
if (w|type) == "number" then Quaternion(z.q0/w; z.q1/w; z.q2/w; z.q3/w)
|
||||
else times(z; inv(w))
|
||||
end;
|
||||
|
||||
def inv(z): div(conj(z); abs2(z));
|
||||
|
||||
|
||||
# Example usage and output:
|
||||
|
||||
def say(msg; e): "\(msg) => \(e|pp)";
|
||||
|
||||
def demo:
|
||||
say( "Quaternion(1;0;0;0)"; Quaternion(1;0;0;0)),
|
||||
(Quaternion (1; 2; 3; 4) as $q
|
||||
| Quaternion(2; 3; 4; 5) as $q1
|
||||
| Quaternion(3; 4; 5; 6) as $q2
|
||||
| 7 as $r
|
||||
| say( "abs($q)"; abs($q) ), # norm
|
||||
say( "negate($q)"; negate($q) ),
|
||||
say( "conj($q)"; conj($q) ),
|
||||
"",
|
||||
say( "plus($r; $q)"; plus($r; $q)),
|
||||
say( "plus($q; $r)"; plus($q; $r)),
|
||||
"",
|
||||
say( "plus($q1; $q2 )"; plus($q1; $q2)),
|
||||
"",
|
||||
say( "times($r;$q)"; times($r;$q)),
|
||||
say( "times($q;$r)"; times($q;$r)),
|
||||
"",
|
||||
say( "times($q1;$q2)"; times($q1;$q2)),
|
||||
say( "times($q2; $q1)"; times($q2; $q1)),
|
||||
say( "times($q1; $q2) != times($q2; $q1)";
|
||||
times($q1; $q2) != times($q2; $q1) )
|
||||
) ;
|
||||
|
||||
demo
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
# jq -c -n -R -f quaternion.jq
|
||||
Quaternion(1;0;0;0) => 1 + 0i + 0j + 0k
|
||||
abs($q) => 5.477225575051661
|
||||
negate($q) => -1 - 2i - 3j + -4k
|
||||
conj($q) => 1 - 2i - 3j - 4k
|
||||
|
||||
plus($r; $q) => 8 + 2i + 3j + 4k
|
||||
plus($q; $r) => 8 + 2i + 3j + 4k
|
||||
|
||||
plus($q1; $q2 ) => 5 + 7i + 9j + 11k
|
||||
|
||||
times($r;$q) => 7 + 14i + 21j + 28k
|
||||
times($q;$r) => 7 + 14i + 21j + 28k
|
||||
|
||||
times($q1;$q2) => -56 + 16i + 24j + 26k
|
||||
times($q2; $q1) => -56 + 18i + 20j + 28k
|
||||
times($q1; $q2) != times($q2; $q1) => true
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
import Base: convert, promote_rule, show, conj, abs, +, -, *
|
||||
|
||||
immutable Quaternion{T<:Real} <: Number
|
||||
q0::T
|
||||
q1::T
|
||||
q2::T
|
||||
q3::T
|
||||
end
|
||||
|
||||
Quaternion(q0::Real,q1::Real,q2::Real,q3::Real) = Quaternion(promote(q0,q1,q2,q3)...)
|
||||
|
||||
convert{T}(::Type{Quaternion{T}}, x::Real) =
|
||||
Quaternion(convert(T,x), zero(T), zero(T), zero(T))
|
||||
convert{T}(::Type{Quaternion{T}}, z::Complex) =
|
||||
Quaternion(convert(T,real(z)), convert(T,imag(z)), zero(T), zero(T))
|
||||
convert{T}(::Type{Quaternion{T}}, z::Quaternion) =
|
||||
Quaternion(convert(T,z.q0), convert(T,z.q1), convert(T,z.q2), convert(T,z.q3))
|
||||
|
||||
promote_rule{T,S}(::Type{Complex{T}}, ::Type{Quaternion{S}}) = Quaternion{promote_type(T,S)}
|
||||
promote_rule{T<:Real,S}(::Type{T}, ::Type{Quaternion{S}}) = Quaternion{promote_type(T,S)}
|
||||
promote_rule{T,S}(::Type{Quaternion{T}}, ::Type{Quaternion{S}}) = Quaternion{promote_type(T,S)}
|
||||
|
||||
function show(io::IO, z::Quaternion)
|
||||
pm(x) = x < 0 ? " - $(-x)" : " + $x"
|
||||
print(io, z.q0, pm(z.q1), "i", pm(z.q2), "j", pm(z.q3), "k")
|
||||
end
|
||||
|
||||
conj(z::Quaternion) = Quaternion(z.q0, -z.q1, -z.q2, -z.q3)
|
||||
abs(z::Quaternion) = sqrt(z.q0*z.q0 + z.q1*z.q1 + z.q2*z.q2 + z.q3*z.q3)
|
||||
|
||||
(-)(z::Quaternion) = Quaternion(-z.q0, -z.q1, -z.q2, -z.q3)
|
||||
|
||||
(+)(z::Quaternion, w::Quaternion) = Quaternion(z.q0 + w.q0, z.q1 + w.q1,
|
||||
z.q2 + w.q2, z.q3 + w.q3)
|
||||
(-)(z::Quaternion, w::Quaternion) = Quaternion(z.q0 - w.q0, z.q1 - w.q1,
|
||||
z.q2 - w.q2, z.q3 - w.q3)
|
||||
(*)(z::Quaternion, w::Quaternion) = Quaternion(z.q0*w.q0 - z.q1*w.q1 - z.q2*w.q2 - z.q3*w.q3,
|
||||
z.q0*w.q1 + z.q1*w.q0 + z.q2*w.q3 - z.q3*w.q2,
|
||||
z.q0*w.q2 - z.q1*w.q3 + z.q2*w.q0 + z.q3*w.q1,
|
||||
z.q0*w.q3 + z.q1*w.q2 - z.q2*w.q1 + z.q3*w.q0)
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
julia> q = Quaternion(1,0,0,0)
|
||||
julia> q = Quaternion (1, 2, 3, 4)
|
||||
q1 = Quaternion(2, 3, 4, 5)
|
||||
q2 = Quaternion(3, 4, 5, 6)
|
||||
r = 7.
|
||||
|
||||
julia> norm(q)
|
||||
5.477225575051661
|
||||
|
||||
julia> -q
|
||||
-1 - 2i - 3j - 4k
|
||||
|
||||
julia> conj(q)
|
||||
1 - 2i - 3j - 4k
|
||||
|
||||
julia> r + q, q + r
|
||||
(8.0 + 2.0i + 3.0j + 4.0k,8.0 + 2.0i + 3.0j + 4.0k)
|
||||
|
||||
julia> q1 + q2
|
||||
5 + 7i + 9j + 11k
|
||||
|
||||
julia> r*q, q*r
|
||||
(7.0 + 14.0i + 21.0j + 28.0k,7.0 + 14.0i + 21.0j + 28.0k)
|
||||
|
||||
julia> q1*q2, q2*q1, q1*q2 != q2*q1
|
||||
(-56 + 16i + 24j + 26k,-56 + 18i + 20j + 28k,true)
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
// version 1.1.2
|
||||
|
||||
data class Quaternion(val a: Double, val b: Double, val c: Double, val d: Double) {
|
||||
operator fun plus(other: Quaternion): Quaternion {
|
||||
return Quaternion (this.a + other.a, this.b + other.b,
|
||||
this.c + other.c, this.d + other.d)
|
||||
}
|
||||
|
||||
operator fun plus(r: Double) = Quaternion(a + r, b, c, d)
|
||||
|
||||
operator fun times(other: Quaternion): Quaternion {
|
||||
return Quaternion(
|
||||
this.a * other.a - this.b * other.b - this.c * other.c - this.d * other.d,
|
||||
this.a * other.b + this.b * other.a + this.c * other.d - this.d * other.c,
|
||||
this.a * other.c - this.b * other.d + this.c * other.a + this.d * other.b,
|
||||
this.a * other.d + this.b * other.c - this.c * other.b + this.d * other.a
|
||||
)
|
||||
}
|
||||
|
||||
operator fun times(r: Double) = Quaternion(a * r, b * r, c * r, d * r)
|
||||
|
||||
operator fun unaryMinus() = Quaternion(-a, -b, -c, -d)
|
||||
|
||||
fun conj() = Quaternion(a, -b, -c, -d)
|
||||
|
||||
fun norm() = Math.sqrt(a * a + b * b + c * c + d * d)
|
||||
|
||||
override fun toString() = "($a, $b, $c, $d)"
|
||||
}
|
||||
|
||||
// extension functions for Double type
|
||||
operator fun Double.plus(q: Quaternion) = q + this
|
||||
operator fun Double.times(q: Quaternion) = q * this
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
val q = Quaternion(1.0, 2.0, 3.0, 4.0)
|
||||
val q1 = Quaternion(2.0, 3.0, 4.0, 5.0)
|
||||
val q2 = Quaternion(3.0, 4.0, 5.0, 6.0)
|
||||
val r = 7.0
|
||||
println("q = $q")
|
||||
println("q1 = $q1")
|
||||
println("q2 = $q2")
|
||||
println("r = $r\n")
|
||||
println("norm(q) = ${"%f".format(q.norm())}")
|
||||
println("-q = ${-q}")
|
||||
println("conj(q) = ${q.conj()}\n")
|
||||
println("r + q = ${r + q}")
|
||||
println("q + r = ${q + r}")
|
||||
println("q1 + q2 = ${q1 + q2}\n")
|
||||
println("r * q = ${r * q}")
|
||||
println("q * r = ${q * r}")
|
||||
val q3 = q1 * q2
|
||||
val q4 = q2 * q1
|
||||
println("q1 * q2 = $q3")
|
||||
println("q2 * q1 = $q4\n")
|
||||
println("q1 * q2 != q2 * q1 = ${q3 != q4}")
|
||||
}
|
||||
|
|
@ -1,111 +0,0 @@
|
|||
q$ = q$( 1 , 2 , 3 , 4 )
|
||||
q1$ = q$( 2 , 3 , 4 , 5 )
|
||||
q2$ = q$( 3 , 4 , 5 , 6 )
|
||||
|
||||
real = 7
|
||||
|
||||
print "q = " ; q$
|
||||
print "q1 = " ; q1$
|
||||
print "q2 = " ; q2$
|
||||
|
||||
print "real = " ; real
|
||||
|
||||
print "length /norm q = " ; length( q$ ) ' =norm norm of q
|
||||
print "negative (-q1) = " ; negative$( q1$ ) ' =negative negated q1
|
||||
print "conjugate q = " ; conjugate$( q$ ) ' conjugate conjugate q
|
||||
print "real + q = " ; add1$( q$ , real ) ' real +quaternion real +q
|
||||
print "q + q2 = " ; add2$( q$ , q2$ ) ' sum two quaternions q +q2
|
||||
print "real * q = " ; multiply1$( q$ , real ) ' real *quaternion real *q
|
||||
print "q1 * q2 = " ; multiply2$( q1$ , q2$ ) ' product of two quaternions q1 & q2
|
||||
print "q2 * q1 = " ; multiply2$( q2$ , q1$ ) ' show q1 *q2 <> q2 *q1
|
||||
|
||||
end
|
||||
|
||||
function q$( r , i , j , k )
|
||||
q$ = str$( r); " "; str$( i); " "; str$( j); " "; str$( k)
|
||||
end function
|
||||
|
||||
function length( q$ )
|
||||
r = val( word$( q$ , 1 ) )
|
||||
i = val( word$( q$ , 2 ) )
|
||||
j = val( word$( q$ , 3 ) )
|
||||
k = val( word$( q$ , 4 ) )
|
||||
length =sqr( r^2 +i^2 +j^2 +k^2)
|
||||
end function
|
||||
|
||||
function multiply1$( q$ , d )
|
||||
r = val( word$( q$ , 1 ) )
|
||||
i = val( word$( q$ , 2 ) )
|
||||
j = val( word$( q$ , 3 ) )
|
||||
k = val( word$( q$ , 4 ) )
|
||||
multiply1$ =q$( r*d, i*d, j*d, k*d)
|
||||
end function
|
||||
|
||||
function multiply2$( q$ , b$ )
|
||||
ar = val( word$( q$ , 1 ) ) 'a1
|
||||
ai = val( word$( q$ , 2 ) ) 'b1
|
||||
aj = val( word$( q$ , 3 ) ) 'c1
|
||||
ak = val( word$( q$ , 4 ) ) 'd1
|
||||
|
||||
br = val( word$( b$ , 1 ) ) 'a2
|
||||
bi = val( word$( b$ , 2 ) ) 'b2
|
||||
bj = val( word$( b$ , 3 ) ) 'c2
|
||||
bk = val( word$( b$ , 4 ) ) 'd2
|
||||
|
||||
multiply2$ =q$( _
|
||||
ar *br_
|
||||
+( 0 -ai) *bi_
|
||||
+( 0 -aj) *bj_
|
||||
+( 0 -ak) *bk _
|
||||
,_
|
||||
ar *bi_
|
||||
+ai *br_
|
||||
+aj *bk_
|
||||
+( 0 -ak) *bj_
|
||||
,_
|
||||
ar *bj_
|
||||
+( 0 -ai) *bk_
|
||||
+aj *br_
|
||||
+ak *bi_
|
||||
,_
|
||||
ar *bk_
|
||||
+ai *bj_
|
||||
+( 0 -aj) *bi_
|
||||
+ak *br )
|
||||
end function
|
||||
|
||||
function negative$( q$ )
|
||||
r = val( word$( q$ , 1 ) )
|
||||
i = val( word$( q$ , 2 ) )
|
||||
j = val( word$( q$ , 3 ) )
|
||||
k = val( word$( q$ , 4 ) )
|
||||
negative$ =q$( 0-r, 0-i, 0-j, 0-k)
|
||||
end function
|
||||
|
||||
function conjugate$( q$ )
|
||||
r = val( word$( q$ , 1 ) )
|
||||
i = val( word$( q$ , 2 ) )
|
||||
j = val( word$( q$ , 3 ) )
|
||||
k = val( word$( q$ , 4 ) )
|
||||
conjugate$ =q$( r, 0-i, 0-j, 0-k)
|
||||
end function
|
||||
|
||||
function add1$( q$ , real )
|
||||
r = val( word$( q$ , 1 ) )
|
||||
i = val( word$( q$ , 2 ) )
|
||||
j = val( word$( q$ , 3 ) )
|
||||
k = val( word$( q$ , 4 ) )
|
||||
add1$ =q$( r +real, i, j, k)
|
||||
end function
|
||||
|
||||
function add2$( q$ , b$ )
|
||||
ar = val( word$( q$ , 1 ) )
|
||||
ai = val( word$( q$ , 2 ) )
|
||||
aj = val( word$( q$ , 3 ) )
|
||||
ak = val( word$( q$ , 4 ) )
|
||||
br = val( word$( b$ , 1 ) )
|
||||
bi = val( word$( b$ , 2 ) )
|
||||
bj = val( word$( b$ , 3 ) )
|
||||
bk = val( word$( b$ , 4 ) )
|
||||
add2$ =q$( ar +br, ai +bi, aj +bj, ak +bk)
|
||||
end function
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
Quaternion = {}
|
||||
|
||||
function Quaternion.new( a, b, c, d )
|
||||
local q = { a = a or 1, b = b or 0, c = c or 0, d = d or 0 }
|
||||
|
||||
local metatab = {}
|
||||
setmetatable( q, metatab )
|
||||
metatab.__add = Quaternion.add
|
||||
metatab.__sub = Quaternion.sub
|
||||
metatab.__unm = Quaternion.unm
|
||||
metatab.__mul = Quaternion.mul
|
||||
|
||||
return q
|
||||
end
|
||||
|
||||
function Quaternion.add( p, q )
|
||||
if type( p ) == "number" then
|
||||
return Quaternion.new( p+q.a, q.b, q.c, q.d )
|
||||
elseif type( q ) == "number" then
|
||||
return Quaternion.new( p.a+q, p.b, p.c, p.d )
|
||||
else
|
||||
return Quaternion.new( p.a+q.a, p.b+q.b, p.c+q.c, p.d+q.d )
|
||||
end
|
||||
end
|
||||
|
||||
function Quaternion.sub( p, q )
|
||||
if type( p ) == "number" then
|
||||
return Quaternion.new( p-q.a, q.b, q.c, q.d )
|
||||
elseif type( q ) == "number" then
|
||||
return Quaternion.new( p.a-q, p.b, p.c, p.d )
|
||||
else
|
||||
return Quaternion.new( p.a-q.a, p.b-q.b, p.c-q.c, p.d-q.d )
|
||||
end
|
||||
end
|
||||
|
||||
function Quaternion.unm( p )
|
||||
return Quaternion.new( -p.a, -p.b, -p.c, -p.d )
|
||||
end
|
||||
|
||||
function Quaternion.mul( p, q )
|
||||
if type( p ) == "number" then
|
||||
return Quaternion.new( p*q.a, p*q.b, p*q.c, p*q.d )
|
||||
elseif type( q ) == "number" then
|
||||
return Quaternion.new( p.a*q, p.b*q, p.c*q, p.d*q )
|
||||
else
|
||||
return Quaternion.new( p.a*q.a - p.b*q.b - p.c*q.c - p.d*q.d,
|
||||
p.a*q.b + p.b*q.a + p.c*q.d - p.d*q.c,
|
||||
p.a*q.c - p.b*q.d + p.c*q.a + p.d*q.b,
|
||||
p.a*q.d + p.b*q.c - p.c*q.b + p.d*q.a )
|
||||
end
|
||||
end
|
||||
|
||||
function Quaternion.conj( p )
|
||||
return Quaternion.new( p.a, -p.b, -p.c, -p.d )
|
||||
end
|
||||
|
||||
function Quaternion.norm( p )
|
||||
return math.sqrt( p.a^2 + p.b^2 + p.c^2 + p.d^2 )
|
||||
end
|
||||
|
||||
function Quaternion.print( p )
|
||||
print( string.format( "%f + %fi + %fj + %fk\n", p.a, p.b, p.c, p.d ) )
|
||||
end
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
q1 = Quaternion.new( 1, 2, 3, 4 )
|
||||
q2 = Quaternion.new( 5, 6, 7, 8 )
|
||||
r = 12
|
||||
|
||||
print( "norm(q1) = ", Quaternion.norm( q1 ) )
|
||||
io.write( "-q1 = " ); Quaternion.print( -q1 )
|
||||
io.write( "conj(q1) = " ); Quaternion.print( Quaternion.conj( q1 ) )
|
||||
io.write( "r+q1 = " ); Quaternion.print( r+q1 )
|
||||
io.write( "q1+r = " ); Quaternion.print( q1+r )
|
||||
io.write( "r*q1 = " ); Quaternion.print( r*q1 )
|
||||
io.write( "q1*r = " ); Quaternion.print( q1*r )
|
||||
io.write( "q1*q2 = " ); Quaternion.print( q1*q2 )
|
||||
io.write( "q2*q1 = " ); Quaternion.print( q2*q1 )
|
||||
|
|
@ -1,99 +0,0 @@
|
|||
Module CheckIt {
|
||||
class Quaternion {
|
||||
\\ by default are double
|
||||
a,b,c,d
|
||||
Property ToString$ {
|
||||
Value {
|
||||
link parent a,b,c, d to a,b,c,d
|
||||
value$=format$("{0} + {1}i + {2}j + {3}k",a,b,c,d)
|
||||
}
|
||||
}
|
||||
Property Norm { Value}
|
||||
Operator "==" {
|
||||
read n
|
||||
push .a==n.a and .b==n.b and .c==n.c and .d==n.d
|
||||
}
|
||||
Module CalcNorm {
|
||||
.[Norm]<=sqrt(.a**2+.b**2+.c**2+.d**2)
|
||||
}
|
||||
Operator Unary {
|
||||
.a-! : .b-! : .c-! :.d-!
|
||||
}
|
||||
Function Conj {
|
||||
q=this
|
||||
for q {
|
||||
.b-! : .c-! :.d-!
|
||||
}
|
||||
=q
|
||||
}
|
||||
Function Add {
|
||||
q=this
|
||||
for q {
|
||||
.a+=Number : .CalcNorm
|
||||
}
|
||||
=q
|
||||
}
|
||||
Operator "+" {
|
||||
Read q2
|
||||
For this, q2 {
|
||||
.a+=..a :.b+=..b:.c+=..c:.d+=..d
|
||||
.CalcNorm
|
||||
}
|
||||
}
|
||||
Function Mul(r) {
|
||||
q=this
|
||||
for q {
|
||||
.a*=r:.b*=r:.c*=r:.d*=r:.CalcNorm
|
||||
}
|
||||
=q
|
||||
}
|
||||
Operator "*" {
|
||||
Read q2
|
||||
For This, q2 {
|
||||
Push .a*..a-.b*..b-.c*..c-.d*..d
|
||||
Push .a*..b+.b*..a+.c*..d-.d*..c
|
||||
Push .a*..c-.b*..d+.c*..a+.d*..b
|
||||
.d<=.a*..d+.b*..c-.c*..b+.d*..a
|
||||
Read .c, .b, .a
|
||||
.CalcNorm
|
||||
}
|
||||
}
|
||||
class:
|
||||
module Quaternion {
|
||||
if match("NNNN") then {
|
||||
Read .a,.b,.c,.d
|
||||
.CalcNorm
|
||||
}
|
||||
}
|
||||
}
|
||||
\\ variables
|
||||
r=7
|
||||
q=Quaternion(1,2,3,4)
|
||||
q1=Quaternion(2,3,4,5)
|
||||
q2=Quaternion(3,4,5,6)
|
||||
|
||||
\\ perform negate, conjugate, multiply by real, add a real, multiply quanterions, multiply in reverse order
|
||||
qneg=-q
|
||||
qconj=q.conj()
|
||||
qmul=q.Mul(r)
|
||||
qadd=q.Add(r)
|
||||
q1q2=q1*q2
|
||||
q2q1=q2*q1
|
||||
|
||||
Print "q = ";q.ToString$
|
||||
Print "Normal q = ";q.Norm
|
||||
Print "Neg q = ";qneg.ToString$
|
||||
Print "Conj q = ";qconj.ToString$
|
||||
Print "Mul q 7 = ";qmul.ToString$
|
||||
Print "Add q 7 = ";qadd.ToString$
|
||||
Print "q1 = ";q1.ToString$
|
||||
Print "q2 = ";q2.ToString$
|
||||
Print "q1 * q2 = ";q1q2.ToString$
|
||||
Print "q2 * q1 = ";q2q1.ToString$
|
||||
Print q1==q1 ' true
|
||||
Print q1q2==q2q1 ' false
|
||||
\\ multiplication and equality in one expression
|
||||
Print q1 * q2 == q2 * q1 ' false
|
||||
Print q1 * q2 == q1 * q2 ' true
|
||||
}
|
||||
CheckIt
|
||||
|
|
@ -1,146 +0,0 @@
|
|||
with(ArrayTools);
|
||||
|
||||
module Quaternion()
|
||||
option object;
|
||||
local real := 0;
|
||||
local i := 0;
|
||||
local j := 0;
|
||||
local k := 0;
|
||||
|
||||
export getReal::static := proc(self::Quaternion, $)
|
||||
return self:-real;
|
||||
end proc;
|
||||
|
||||
export getI::static := proc(self::Quaternion, $)
|
||||
return self:-i;
|
||||
end proc;
|
||||
|
||||
export getJ::static := proc(self::Quaternion, $)
|
||||
return self:-j;
|
||||
end proc;
|
||||
|
||||
export getK::static := proc(self::Quaternion, $)
|
||||
return self:-k;
|
||||
end proc;
|
||||
|
||||
export Norm::static := proc(self::Quaternion, $)
|
||||
return sqrt(self:-real^2 + self:-i^2 + self:-j^2 + self:-k^2);
|
||||
end proc;
|
||||
|
||||
# NegativeQuaternion returns the additive inverse of the quaternion
|
||||
export NegativeQuaternion::static := proc(self::Quaternion, $)
|
||||
return Quaternion(- self:-real, - self:-i, - self:-j, - self:-k);
|
||||
end proc;
|
||||
|
||||
export Conjugate::static := proc(self::Quaternion, $)
|
||||
return Quaternion(self:-real, - self:-i, - self:-j, - self:-k);
|
||||
end proc;
|
||||
|
||||
# quaternion addition
|
||||
export `+`::static := overload ([
|
||||
proc(self::Quaternion, x::Quaternion) option overload;
|
||||
return Quaternion(self:-real + getReal(x), self:-i + getI(x), self:-j + getJ(x), self:-k + getK(x));
|
||||
end proc,
|
||||
proc(self::Quaternion, x::algebraic) option overload;
|
||||
return Quaternion(self:-real + x, self:-i, self:-j, self:-k);
|
||||
end proc,
|
||||
proc(x::algebraic, self::Quaternion) option overload;
|
||||
return Quaternion(x + self:-real, self:-i, self:-j, self:-k);
|
||||
end
|
||||
]);
|
||||
|
||||
# convert quaternion to additive inverse
|
||||
export `-`::static := overload([
|
||||
proc(self::Quaternion) option overload;
|
||||
return Quaternion(-self:-real, -self:-i, -self:-j, -self:-k);
|
||||
end
|
||||
]);
|
||||
|
||||
# quaternion multiplication is non-abelian so the `.` operator needs to be used
|
||||
export `.`::static := overload([
|
||||
proc(self::Quaternion, x::Quaternion) option overload;
|
||||
return Quaternion(self:-real * getReal(x) - self:-i * getI(x) - self:-j * getJ(x) - self:-k * getK(x),
|
||||
self:-real * getI(x) + self:-i * getReal(x) + self:-j * getK(x) - self:-k * getJ(x),
|
||||
self:-real * getJ(x) + self:-j * getReal(x) - self:-i * getK(x) + self:-k * getI(x),
|
||||
self:-real * getK(x) + self:-k * getReal(x) + self:-i * getJ(x) - self:-j * getI(x));
|
||||
end proc,
|
||||
proc(self::Quaternion, x::algebraic) option overload;
|
||||
return Quaternion(self:-real * x, self:-i * x, self:-j * x, self:-k * x);
|
||||
end proc,
|
||||
proc(x::algebraic, self::Quaternion) option overload;
|
||||
return Quaternion(self:-real * x, self:-i * x, self:-j * x, self:-k * x);
|
||||
end
|
||||
]);
|
||||
|
||||
# redirect division to `.` operator
|
||||
export `*`::static := overload([
|
||||
proc(self::Quaternion, x::Quaternion) option overload;
|
||||
use `*` = `.` in return self * x; end use
|
||||
end proc,
|
||||
proc(self::Quaternion, x::algebraic) option overload;
|
||||
use `*` = `.` in return x * self; end use
|
||||
end proc,
|
||||
proc(x::algebraic, self::Quaternion) option overload;
|
||||
use `*` = `.` in return x * self; end use
|
||||
end
|
||||
]);
|
||||
|
||||
# convert quaternion to multiplicative inverse
|
||||
export `/`::static := overload([
|
||||
proc(self::Quaternion) option overload;
|
||||
return Conjugate(self) . (1/(Norm(self)^2));
|
||||
end proc
|
||||
]);
|
||||
|
||||
# QuaternionCommutator computes the commutator of self and x
|
||||
export QuaternionCommutator::static := proc(x::Quaternion, y::Quaternion, $)
|
||||
return (x . y) - (y . x);
|
||||
end proc;
|
||||
|
||||
# display quaternion
|
||||
export ModulePrint::static := proc(self::Quaternion, $);
|
||||
return cat(self:-real, " + ", self:-i, "i + ", self:-j, "j + ", self:-k, "k"):
|
||||
end proc;
|
||||
|
||||
export ModuleApply::static := proc()
|
||||
Object(Quaternion, _passed);
|
||||
end proc;
|
||||
|
||||
export ModuleCopy::static := proc(new::Quaternion, proto::Quaternion, R::algebraic, imag::algebraic, J::algebraic, K::algebraic, $)
|
||||
new:-real := R;
|
||||
new:-i := imag;
|
||||
new:-j := J;
|
||||
new:-k := K;
|
||||
end proc;
|
||||
end module:
|
||||
|
||||
q := Quaternion(1, 2, 3, 4):
|
||||
q1 := Quaternion(2, 3, 4, 5):
|
||||
q2 := Quaternion(3, 4, 5, 6):
|
||||
r := 7:
|
||||
|
||||
quats := Array([q, q1, q2]):
|
||||
print("q, q1, q2"):
|
||||
seq(quats[i], i = 1..3);
|
||||
print("norms"):
|
||||
seq(Norm(quats[i]), i = 1..3);
|
||||
print("negative"):
|
||||
seq(NegativeQuaternion(quats[i]), i = 1..3);
|
||||
print("conjugate"):
|
||||
seq(Conjugate(quats[i]), i = 1..3);
|
||||
print("addition of real number 7"):
|
||||
seq(quats[i] + r, i = 1..3);
|
||||
print("multiplication by real number 7"):
|
||||
seq(quats[i] . r, i = 1..3);
|
||||
print("division by real number 7"):
|
||||
seq(quats[i] / 7, i = 1..3);
|
||||
print("add quaternions q1 and q2"):
|
||||
q1 + q2;
|
||||
print("multiply quaternions q1 and q2");
|
||||
q1 . q2;
|
||||
print("multiply quaternions q2 and q1"):
|
||||
q2 . q1;
|
||||
print("quaternion commutator of q1 and q2"):
|
||||
QuaternionCommutator(q1,q2);
|
||||
print("divide q1 by q2"):
|
||||
q1 / q2;
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
<<Quaternions`
|
||||
q=Quaternion[1,2,3,4]
|
||||
q1=Quaternion[2,3,4,5]
|
||||
q2=Quaternion[3,4,5,6]
|
||||
r=7
|
||||
->Quaternion[1,2,3,4]
|
||||
->Quaternion[2,3,4,5]
|
||||
->Quaternion[3,4,5,6]
|
||||
->7
|
||||
|
||||
Abs[q]
|
||||
->√30
|
||||
-q
|
||||
->Quaternion[-1,-2,-3,-4]
|
||||
Conjugate[q]
|
||||
->Quaternion[1,-2,-3,-4]
|
||||
r+q
|
||||
->Quaternion[8,2,3,4]
|
||||
q+r
|
||||
->Quaternion[8,2,3,4]
|
||||
q1+q2
|
||||
->Quaternion[5,7,9,11]
|
||||
q*r
|
||||
->Quaternion[7,14,21,28]
|
||||
r*q
|
||||
->Quaternion[7,14,21,28]
|
||||
q1**q2
|
||||
->Quaternion[-56,16,24,26]
|
||||
q2**q1
|
||||
->Quaternion[-56,18,20,28]
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
:- module quaternion.
|
||||
|
||||
:- interface.
|
||||
|
||||
:- import_module float.
|
||||
|
||||
:- type quaternion
|
||||
---> q( w :: float,
|
||||
i :: float,
|
||||
j :: float,
|
||||
k :: float ).
|
||||
|
||||
% conversion
|
||||
:- func r(float) = quaternion is det.
|
||||
|
||||
% operations
|
||||
:- func norm(quaternion) = float is det.
|
||||
:- func -quaternion = quaternion is det.
|
||||
:- func conjugate(quaternion) = quaternion is det.
|
||||
:- func quaternion + quaternion = quaternion is det.
|
||||
:- func quaternion * quaternion = quaternion is det.
|
||||
|
||||
:- implementation.
|
||||
|
||||
:- import_module math.
|
||||
|
||||
% conversion
|
||||
r(W) = q(W, 0.0, 0.0, 0.0).
|
||||
|
||||
% operations
|
||||
norm(q(W, I, J, K)) = math.sqrt(W*W + I*I + J*J + K*K).
|
||||
-q(W, I, J, K) = q(-W, -I, -J, -K).
|
||||
conjugate(q(W, I, J, K)) = q(W, -I, -J, -K).
|
||||
q(W0, I0, J0, K0) + q(W1, I1, J1, K1) = q(W0+W1, I0+I1, J0+J1, K0+K1).
|
||||
q(W0, I0, J0, K0) * q(W1, I1, J1, K1) = q(W0*W1 - I0*I1 - J0*J1 - K0*K1,
|
||||
W0*I1 + I0*W1 + J0*K1 - K0*J1,
|
||||
W0*J1 - I0*K1 + J0*W1 + K0*I1,
|
||||
W0*K1 + I0*J1 - J0*I1 + K0*W1 ).
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
:- module test_quaternion.
|
||||
|
||||
:- interface.
|
||||
|
||||
:- import_module io.
|
||||
|
||||
:- pred main(io::di, io::uo) is det.
|
||||
|
||||
:- implementation.
|
||||
|
||||
:- import_module quaternion.
|
||||
|
||||
:- import_module exception.
|
||||
:- import_module float.
|
||||
:- import_module list.
|
||||
:- import_module string.
|
||||
|
||||
:- func to_string(quaternion) = string is det.
|
||||
|
||||
main(!IO) :-
|
||||
Q = q(1.0, 2.0, 3.0, 4.0),
|
||||
Q1 = q(2.0, 3.0, 4.0, 5.0),
|
||||
Q2 = q(3.0, 4.0, 5.0, 6.0),
|
||||
R = 7.0,
|
||||
QR = r(R),
|
||||
|
||||
io.print("Q = ", !IO), io.print(to_string(Q), !IO), io.nl(!IO),
|
||||
io.print("Q1 = ", !IO), io.print(to_string(Q1), !IO), io.nl(!IO),
|
||||
io.print("Q2 = ", !IO), io.print(to_string(Q2), !IO), io.nl(!IO),
|
||||
io.print("R = ", !IO), io.print(R, !IO), io.nl(!IO),
|
||||
io.nl(!IO),
|
||||
|
||||
io.print("1. The norm of a quaternion.\n", !IO),
|
||||
io.print("norm(Q) = ", !IO), io.print(norm(Q), !IO), io.nl(!IO),
|
||||
io.nl(!IO),
|
||||
|
||||
io.print("2. The negative of a quaternion.\n", !IO),
|
||||
io.print("-Q = ", !IO), io.print(to_string(-Q), !IO), io.nl(!IO),
|
||||
io.nl(!IO),
|
||||
|
||||
io.print("3. The conjugate of a quaternion.\n", !IO),
|
||||
io.print("conjugate(Q) = ", !IO), io.print(to_string(conjugate(Q)), !IO),
|
||||
io.nl(!IO),
|
||||
io.nl(!IO),
|
||||
|
||||
io.print("4. Addition of a real number and a quaternion.\n", !IO),
|
||||
( Q + QR = QR + Q -> io.print("Addition is commutative.\n", !IO)
|
||||
; io.print("Addition is not commutative.\n", !IO) ),
|
||||
io.print("Q + R = ", !IO), io.print(to_string(Q + QR), !IO), io.nl(!IO),
|
||||
io.print("R + Q = ", !IO), io.print(to_string(QR + Q), !IO), io.nl(!IO),
|
||||
io.nl(!IO),
|
||||
|
||||
io.print("5. Addition of two quaternions.\n", !IO),
|
||||
( Q1 + Q2 = Q2 + Q1 -> io.print("Addition is commutative.\n", !IO)
|
||||
; io.print("Addition is not commutative.\n", !IO) ),
|
||||
io.print("Q1 + Q2 = ", !IO), io.print(to_string(Q1 + Q2), !IO), io.nl(!IO),
|
||||
io.print("Q2 + Q1 = ", !IO), io.print(to_string(Q2 + Q1), !IO), io.nl(!IO),
|
||||
io.nl(!IO),
|
||||
|
||||
io.print("6. Multiplication of a real number and a quaternion.\n", !IO),
|
||||
( Q * QR = QR * Q -> io.print("Multiplication is commutative.\n", !IO)
|
||||
; io.print("Multiplication is not commutative.\n", !IO) ),
|
||||
io.print("Q * R = ", !IO), io.print(to_string(Q * QR), !IO), io.nl(!IO),
|
||||
io.print("R * Q = ", !IO), io.print(to_string(QR * Q), !IO), io.nl(!IO),
|
||||
io.nl(!IO),
|
||||
|
||||
io.print("7. Multiplication of two quaternions.\n", !IO),
|
||||
( Q1 * Q2 = Q2 * Q1 -> io.print("Multiplication is commutative.\n", !IO)
|
||||
; io.print("Multiplication is not commutative.\n", !IO) ),
|
||||
io.print("Q1 * Q2 = ", !IO), io.print(to_string(Q1 * Q2), !IO), io.nl(!IO),
|
||||
io.print("Q2 * Q1 = ", !IO), io.print(to_string(Q2 * Q1), !IO), io.nl(!IO),
|
||||
io.nl(!IO).
|
||||
|
||||
to_string(q(I, J, K, W)) = string.format("q(%f, %f, %f, %f)",
|
||||
[f(I), f(J), f(K), f(W)]).
|
||||
:- end_module test_quaternion.
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
import math, tables
|
||||
|
||||
type Quaternion* = object
|
||||
a, b, c, d: float
|
||||
|
||||
func initQuaternion*(a, b, c, d = 0.0): Quaternion =
|
||||
Quaternion(a: a, b: b, c: c, d: d)
|
||||
|
||||
func `-`*(q: Quaternion): Quaternion =
|
||||
initQuaternion(-q.a, -q.b, -q.c, -q.d)
|
||||
|
||||
func `+`*(q: Quaternion; r: float): Quaternion =
|
||||
initQuaternion(q.a + r, q.b, q.c, q.d)
|
||||
|
||||
func `+`*(r: float; q: Quaternion): Quaternion =
|
||||
initQuaternion(q.a + r, q.b, q.c, q.d)
|
||||
|
||||
func `+`*(q1, q2: Quaternion): Quaternion =
|
||||
initQuaternion(q1.a + q2.a, q1.b + q2.b, q1.c + q2.c, q1.d + q2.d)
|
||||
|
||||
func `*`*(q: Quaternion; r: float): Quaternion =
|
||||
initQuaternion(q.a * r, q.b * r, q.c * r, q.d * r)
|
||||
|
||||
func `*`*(r: float; q: Quaternion): Quaternion =
|
||||
initQuaternion(q.a * r, q.b * r, q.c * r, q.d * r)
|
||||
|
||||
func `*`*(q1, q2: Quaternion): Quaternion =
|
||||
initQuaternion(q1.a * q2.a - q1.b * q2.b - q1.c * q2.c - q1.d * q2.d,
|
||||
q1.a * q2.b + q1.b * q2.a + q1.c * q2.d - q1.d * q2.c,
|
||||
q1.a * q2.c - q1.b * q2.d + q1.c * q2.a + q1.d * q2.b,
|
||||
q1.a * q2.d + q1.b * q2.c - q1.c * q2.b + q1.d * q2.a)
|
||||
|
||||
func conjugate*(q: Quaternion): Quaternion =
|
||||
initQuaternion(q.a, -q.b, -q.c, -q.d)
|
||||
|
||||
func norm*(q: Quaternion): float =
|
||||
sqrt(q.a * q.a + q.b * q.b + q.c * q.c + q.d * q.d)
|
||||
|
||||
func `==`*(q: Quaternion; r: float): bool =
|
||||
if q.b != 0 or q.c != 0 or q.d != 0: false
|
||||
else: q.a == r
|
||||
|
||||
func `$`(q: Quaternion): string =
|
||||
## Return the representation of a quaternion.
|
||||
const Letter = {"a": "", "b": "i", "c": "j", "d": "k"}.toTable
|
||||
if q == 0: return "0"
|
||||
for name, value in q.fieldPairs:
|
||||
if value != 0:
|
||||
var val = value
|
||||
if result.len != 0:
|
||||
result.add if value >= 0: '+' else: '-'
|
||||
val = abs(val)
|
||||
result.add $val & Letter[name]
|
||||
|
||||
|
||||
when isMainModule:
|
||||
let
|
||||
q = initQuaternion(1, 2, 3, 4)
|
||||
q1 = initQuaternion(2, 3, 4, 5)
|
||||
q2 = initQuaternion(3, 4, 5, 6)
|
||||
r = 7.0
|
||||
|
||||
echo "∥q∥ = ", norm(q)
|
||||
echo "-q = ", -q
|
||||
echo "q* = ", conjugate(q)
|
||||
echo "q + r = ", q + r
|
||||
echo "r + q = ", r + q
|
||||
echo "q1 + q2 = ", q1 + q2
|
||||
echo "qr = ", q * r
|
||||
echo "rq = ", r * q
|
||||
echo "q1 * q2 = ", q1 * q2
|
||||
echo "q2 * q1 = ", q2 * q1
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
type quaternion = {a: float; b: float; c: float; d: float}
|
||||
|
||||
let norm q = sqrt (q.a**2.0 +.
|
||||
q.b**2.0 +.
|
||||
q.c**2.0 +.
|
||||
q.d**2.0 )
|
||||
|
||||
let floatneg r = ~-. r (* readability *)
|
||||
|
||||
let negative q =
|
||||
{a = floatneg q.a;
|
||||
b = floatneg q.b;
|
||||
c = floatneg q.c;
|
||||
d = floatneg q.d }
|
||||
|
||||
let conjugate q =
|
||||
{a = q.a;
|
||||
b = floatneg q.b;
|
||||
c = floatneg q.c;
|
||||
d = floatneg q.d }
|
||||
|
||||
let addrq r q = {q with a = q.a +. r}
|
||||
|
||||
let addq q1 q2 =
|
||||
{a = q1.a +. q2.a;
|
||||
b = q1.b +. q2.b;
|
||||
c = q1.c +. q2.c;
|
||||
d = q1.d +. q2.d }
|
||||
|
||||
let multrq r q =
|
||||
{a = q.a *. r;
|
||||
b = q.b *. r;
|
||||
c = q.c *. r;
|
||||
d = q.d *. r }
|
||||
|
||||
let multq q1 q2 =
|
||||
{a = q1.a*.q2.a -. q1.b*.q2.b -. q1.c*.q2.c -. q1.d*.q2.d;
|
||||
b = q1.a*.q2.b +. q1.b*.q2.a +. q1.c*.q2.d -. q1.d*.q2.c;
|
||||
c = q1.a*.q2.c -. q1.b*.q2.d +. q1.c*.q2.a +. q1.d*.q2.b;
|
||||
d = q1.a*.q2.d +. q1.b*.q2.c -. q1.c*.q2.b +. q1.d*.q2.a }
|
||||
|
||||
let qmake a b c d = {a;b;c;d} (* readability omitting a= b=... *)
|
||||
|
||||
let qstring q =
|
||||
Printf.sprintf "(%g, %g, %g, %g)" q.a q.b q.c q.d ;;
|
||||
|
||||
(* test data *)
|
||||
let q = qmake 1.0 2.0 3.0 4.0
|
||||
let q1 = qmake 2.0 3.0 4.0 5.0
|
||||
let q2 = qmake 3.0 4.0 5.0 6.0
|
||||
let r = 7.0
|
||||
|
||||
let () = (* written strictly to spec *)
|
||||
let pf = Printf.printf in
|
||||
pf "starting with data q=%s, q1=%s, q2=%s, r=%g\n" (qstring q) (qstring q1) (qstring q2) r;
|
||||
pf "1. norm of q = %g \n" (norm q) ;
|
||||
pf "2. negative of q = %s \n" (qstring (negative q));
|
||||
pf "3. conjugate of q = %s \n" (qstring (conjugate q));
|
||||
pf "4. adding r to q = %s \n" (qstring (addrq r q));
|
||||
pf "5. adding q1 and q2 = %s \n" (qstring (addq q1 q2));
|
||||
pf "6. multiply r and q = %s \n" (qstring (multrq r q));
|
||||
pf "7. multiply q1 and q2 = %s \n" (qstring (multq q1 q2));
|
||||
pf "8. instead q2 * q1 = %s \n" (qstring (multq q2 q1));
|
||||
pf "\n";
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
type quaternion = { a : float; b : float; c : float; d : float; }
|
||||
val norm : quaternion -> float = <fun>
|
||||
val floatneg : float -> float = <fun>
|
||||
val negative : quaternion -> quaternion = <fun>
|
||||
val conjugate : quaternion -> quaternion = <fun>
|
||||
val addrq : float -> quaternion -> quaternion = <fun>
|
||||
val addq : quaternion -> quaternion -> quaternion = <fun>
|
||||
val multrq : float -> quaternion -> quaternion = <fun>
|
||||
val multq : quaternion -> quaternion -> quaternion = <fun>
|
||||
val qmake : float -> float -> float -> float -> quaternion = <fun>
|
||||
val qstring : quaternion -> string = <fun>
|
||||
|
|
@ -1 +0,0 @@
|
|||
pkg install -forge quaternion
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
> q = quaternion (1, 2, 3, 4)
|
||||
q = 1 + 2i + 3j + 4k
|
||||
> q1 = quaternion (2, 3, 4, 5)
|
||||
q1 = 2 + 3i + 4j + 5k
|
||||
> q2 = quaternion (3, 4, 5, 6)
|
||||
q2 = 3 + 4i + 5j + 6k
|
||||
> r = 7
|
||||
r = 7
|
||||
> norm(q)
|
||||
ans = 5.4772
|
||||
> -q
|
||||
ans = -1 - 2i - 3j - 4k
|
||||
> conj(q)
|
||||
ans = 1 - 2i - 3j - 4k
|
||||
> q + r
|
||||
ans = 8 + 2i + 3j + 4k
|
||||
> q1 + q2
|
||||
ans = 5 + 7i + 9j + 11k
|
||||
> q * r
|
||||
ans = 7 + 14i + 21j + 28k
|
||||
> q1 * q2
|
||||
ans = -56 + 16i + 24j + 26k
|
||||
> q1 == q2
|
||||
ans = 0
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
160 Number Class newPriority: Quaternion(a, b, c, d)
|
||||
|
||||
Quaternion method: _a @a ;
|
||||
Quaternion method: _b @b ;
|
||||
Quaternion method: _c @c ;
|
||||
Quaternion method: _d @d ;
|
||||
|
||||
Quaternion method: initialize := d := c := b := a ;
|
||||
Quaternion method: << '(' <<c @a << ',' <<c @b << ',' <<c @c << ',' <<c @d << ')' <<c ;
|
||||
|
||||
Integer method: asQuaternion self 0 0 0 Quaternion new ;
|
||||
Float method: asQuaternion self 0 0 0 Quaternion new ;
|
||||
|
||||
Quaternion method: ==(q) q _a @a == q _b @b == and q _c @c == and q _d @d == and ;
|
||||
Quaternion method: norm @a sq @b sq + @c sq + @d sq + sqrt ;
|
||||
Quaternion method: conj @a @b neg @c neg @d neg Quaternion new ;
|
||||
Quaternion method: +(q) Quaternion new(q _a @a +, q _b @b +, q _c @c +, q _d @d +) ;
|
||||
Quaternion method: -(q) Quaternion new(q _a @a -, q _b @b -, q _c @c -, q _d @d -) ;
|
||||
|
||||
Quaternion method: *(q)
|
||||
Quaternion new(q _a @a * q _b @b * - q _c @c * - q _d @d * -,
|
||||
q _a @b * q _b @a * + q _c @d * + q _d @c * -,
|
||||
q _a @c * q _b @d * - q _c @a * + q _d @b * +,
|
||||
q _a @d * q _b @c * + q _c @b * - q _d @a * + ) ;
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
: test
|
||||
| q q1 q2 r |
|
||||
|
||||
Quaternion new(1, 2, 3, 4) ->q
|
||||
Quaternion new(2, 3, 4, 5) ->q1
|
||||
Quaternion new(3, 4, 5, 6) ->q2
|
||||
7.0 -> r
|
||||
|
||||
System.Out "q = " << q << cr
|
||||
System.Out "q1 = " << q1 << cr
|
||||
System.Out "q2 = " << q2 << cr
|
||||
|
||||
System.Out "norm q = " << q norm << cr
|
||||
System.Out "neg q = " << q neg << cr
|
||||
System.Out "conj q = " << q conj << cr
|
||||
System.Out "q +r = " << q r + << cr
|
||||
System.Out "q1 + q2 = " << q1 q2 + << cr
|
||||
System.Out "q * r = " << q r * << cr
|
||||
System.Out "q1 * q2 = " << q1 q2 * << cr
|
||||
q1 q2 * q2 q1 * == ifFalse: [ "q1q2 and q2q1 are different quaternions" println ] ;
|
||||
|
|
@ -1,241 +0,0 @@
|
|||
;;
|
||||
;; This program is written to run without modification both in Otus
|
||||
;; Lisp and in any of many Scheme dialects. I assume the presence of
|
||||
;; "case-lambda", but not of "let-values". The program has worked
|
||||
;; (without modification) in Otus Lisp 2.4, Guile >= 2.0 (but not in
|
||||
;; Guile version 1.8), CHICKEN Scheme 5.3.0, Chez Scheme 9.5.8, Gauche
|
||||
;; Scheme 0.9.12, Ypsilon 0.9.6-update3.
|
||||
;;
|
||||
;; Here a quaternion is represented as a linked list of four real
|
||||
;; numbers. Such a representation probably has the greatest
|
||||
;; portability between Scheme dialects. However, this representation
|
||||
;; can be replaced, simply by redefining the procedures "quaternion?",
|
||||
;; "quaternion-components", "quaternion->list", and "quaternion".
|
||||
;;
|
||||
|
||||
(define (quaternion? q) ; Can q be used as a quaternion?
|
||||
(and (pair? q)
|
||||
(let ((a (car q))
|
||||
(q (cdr q)))
|
||||
(and (real? a) (pair? q)
|
||||
(let ((b (car q))
|
||||
(q (cdr q)))
|
||||
(and (real? b) (pair? q)
|
||||
(let ((c (car q))
|
||||
(q (cdr q)))
|
||||
(and (real? c) (pair? q)
|
||||
(let ((d (car q))
|
||||
(q (cdr q)))
|
||||
(and (real? d) (null? q)))))))))))
|
||||
|
||||
(define (quaternion-components q) ; Extract the basis components.
|
||||
(let ((a (car q))
|
||||
(q (cdr q)))
|
||||
(let ((b (car q))
|
||||
(q (cdr q)))
|
||||
(let ((c (car q))
|
||||
(q (cdr q)))
|
||||
(let ((d (car q)))
|
||||
(values a b c d))))))
|
||||
|
||||
(define (quaternion->list q) ; Get a list of the basis components.
|
||||
q)
|
||||
|
||||
(define quaternion ; Make a quaternion.
|
||||
(case-lambda
|
||||
((a b c d)
|
||||
;; Make the quaternion from basis components.
|
||||
(list a b c d))
|
||||
((q)
|
||||
;; Make the quaternion from a scalar or from another quaternion.
|
||||
;; WARNING: in the latter case, the quaternion is NOT
|
||||
;; copied. This is not a problem, if you avoid things like
|
||||
;; "set-car!" and "set-cdr!".
|
||||
(if (real? q)
|
||||
(list q 0 0 0)
|
||||
q))))
|
||||
|
||||
(define (quaternion-norm q) ; The euclidean norm of a quaternion.
|
||||
(let ((q (quaternion q)))
|
||||
(call-with-values (lambda () (quaternion-components q))
|
||||
(lambda (a b c d)
|
||||
(sqrt (+ (* a a) (* b b) (* c c) (* d d)))))))
|
||||
|
||||
(define (quaternion-conjugate q) ; Conjugate a quaternion.
|
||||
(let ((q (quaternion q)))
|
||||
(call-with-values (lambda () (quaternion-components q))
|
||||
(lambda (a b c d)
|
||||
(quaternion a (- b) (- c) (- d))))))
|
||||
|
||||
(define quaternion+ ; Add quaternions.
|
||||
(let ((quaternion-add
|
||||
(lambda (q1 q2)
|
||||
(let ((q1 (quaternion q1))
|
||||
(q2 (quaternion q2)))
|
||||
(call-with-values
|
||||
(lambda () (quaternion-components q1))
|
||||
(lambda (a1 b1 c1 d1)
|
||||
(call-with-values
|
||||
(lambda () (quaternion-components q2))
|
||||
(lambda (a2 b2 c2 d2)
|
||||
(quaternion (+ a1 a2) (+ b1 b2)
|
||||
(+ c1 c2) (+ d1 d2))))))))))
|
||||
(case-lambda
|
||||
(() (quaternion 0))
|
||||
((q . q*)
|
||||
(let loop ((accum q)
|
||||
(q* q*))
|
||||
(if (pair? q*)
|
||||
(loop (quaternion-add accum (car q*)) (cdr q*))
|
||||
accum))))))
|
||||
|
||||
(define quaternion- ; Negate or subtract quaternions.
|
||||
(let ((quaternion-sub
|
||||
(lambda (q1 q2)
|
||||
(let ((q1 (quaternion q1))
|
||||
(q2 (quaternion q2)))
|
||||
(call-with-values
|
||||
(lambda () (quaternion-components q1))
|
||||
(lambda (a1 b1 c1 d1)
|
||||
(call-with-values
|
||||
(lambda () (quaternion-components q2))
|
||||
(lambda (a2 b2 c2 d2)
|
||||
(quaternion (- a1 a2) (- b1 b2)
|
||||
(- c1 c2) (- d1 d2))))))))))
|
||||
(case-lambda
|
||||
((q)
|
||||
(let ((q (quaternion q)))
|
||||
(call-with-values (lambda () (quaternion-components q))
|
||||
(lambda (a b c d)
|
||||
(quaternion (- a) (- b) (- c) (- d))))))
|
||||
((q . q*)
|
||||
(let loop ((accum q)
|
||||
(q* q*))
|
||||
(if (pair? q*)
|
||||
(loop (quaternion-sub accum (car q*)) (cdr q*))
|
||||
accum))))))
|
||||
|
||||
(define quaternion* ; Multiply quaternions.
|
||||
(let ((quaternion-mul
|
||||
(lambda (q1 q2)
|
||||
(let ((q1 (quaternion q1))
|
||||
(q2 (quaternion q2)))
|
||||
(call-with-values
|
||||
(lambda () (quaternion-components q1))
|
||||
(lambda (a1 b1 c1 d1)
|
||||
(call-with-values
|
||||
(lambda () (quaternion-components q2))
|
||||
(lambda (a2 b2 c2 d2)
|
||||
(quaternion (- (* a1 a2) (* b1 b2)
|
||||
(* c1 c2) (* d1 d2))
|
||||
(- (+ (* a1 b2) (* b1 a2) (* c1 d2))
|
||||
(* d1 c2))
|
||||
(- (+ (* a1 c2) (* c1 a2) (* d1 b2))
|
||||
(* b1 d2))
|
||||
(- (+ (* a1 d2) (* b1 c2) (* d1 a2))
|
||||
(* c1 b2)))))))))))
|
||||
(case-lambda
|
||||
(() (quaternion 1))
|
||||
((q . q*)
|
||||
(let loop ((accum q)
|
||||
(q* q*))
|
||||
(if (pair? q*)
|
||||
(loop (quaternion-mul accum (car q*)) (cdr q*))
|
||||
accum))))))
|
||||
|
||||
(define quaternion=? ; Are the quaternions equal?
|
||||
(let ((=? (lambda (q1 q2)
|
||||
(let ((q1 (quaternion q1))
|
||||
(q2 (quaternion q2)))
|
||||
(call-with-values
|
||||
(lambda () (quaternion-components q1))
|
||||
(lambda (a1 b1 c1 d1)
|
||||
(call-with-values
|
||||
(lambda () (quaternion-components q2))
|
||||
(lambda (a2 b2 c2 d2)
|
||||
(and (= a1 a2) (= b1 b2)
|
||||
(= c1 c2) (= d1 d2))))))))))
|
||||
(lambda (q . q*)
|
||||
(let loop ((q* q*))
|
||||
(if (pair? q*)
|
||||
(and (=? q (car q*))
|
||||
(loop (cdr q*)))
|
||||
#t)))))
|
||||
|
||||
(define q (quaternion 1 2 3 4))
|
||||
(define q1 (quaternion 2 3 4 5))
|
||||
(define q2 (quaternion 3 4 5 6))
|
||||
(define r 7)
|
||||
|
||||
(display "q = ") (display (quaternion->list q)) (newline)
|
||||
(display "q1 = ") (display (quaternion->list q1)) (newline)
|
||||
(display "q2 = ") (display (quaternion->list q2)) (newline)
|
||||
(display "r = ") (display r) (newline)
|
||||
(newline)
|
||||
(display "(quaternion? q) = ") (display (quaternion? q)) (newline)
|
||||
(display "(quaternion? q1) = ") (display (quaternion? q1)) (newline)
|
||||
(display "(quaternion? q2) = ") (display (quaternion? q2)) (newline)
|
||||
(display "(quaternion? r) = ") (display (quaternion? r)) (newline)
|
||||
(newline)
|
||||
(display "(quaternion-norm q) = ")
|
||||
(display (quaternion-norm q)) (newline)
|
||||
(display "(quaternion-norm q1) = ")
|
||||
(display (quaternion-norm q1)) (newline)
|
||||
(display "(quaternion-norm q2) = ")
|
||||
(display (quaternion-norm q2)) (newline)
|
||||
(newline)
|
||||
(display "(quaternion- q) = ")
|
||||
(display (quaternion->list (quaternion- q))) (newline)
|
||||
(display "(quaternion- q1 q2) = ")
|
||||
(display (quaternion->list (quaternion- q1 q2))) (newline)
|
||||
(display "(quaternion- q q1 q2) = ")
|
||||
(display (quaternion->list (quaternion- q q1 q2))) (newline)
|
||||
(newline)
|
||||
(display "(quaternion-conjugate q) = ")
|
||||
(display (quaternion->list (quaternion-conjugate q))) (newline)
|
||||
(newline)
|
||||
(display "(quaternion+) = ")
|
||||
(display (quaternion->list (quaternion+))) (newline)
|
||||
(display "(quaternion+ q) = ")
|
||||
(display (quaternion->list (quaternion+ q))) (newline)
|
||||
(display "(quaternion+ r q) = ")
|
||||
(display (quaternion->list (quaternion+ r q))) (newline)
|
||||
(display "(quaternion+ q r) = ")
|
||||
(display (quaternion->list (quaternion+ q r))) (newline)
|
||||
(display "(quaternion+ q1 q2) = ")
|
||||
(display (quaternion->list (quaternion+ q1 q2))) (newline)
|
||||
(display "(quaternion+ q q1 q2) = ")
|
||||
(display (quaternion->list (quaternion+ q q1 q2))) (newline)
|
||||
(newline)
|
||||
(display "(quaternion*) = ")
|
||||
(display (quaternion->list (quaternion*))) (newline)
|
||||
(display "(quaternion* q) = ")
|
||||
(display (quaternion->list (quaternion* q))) (newline)
|
||||
(display "(quaternion* r q) = ")
|
||||
(display (quaternion->list (quaternion* r q))) (newline)
|
||||
(display "(quaternion* q r) = ")
|
||||
(display (quaternion->list (quaternion* q r))) (newline)
|
||||
(display "(quaternion* q1 q2) = ")
|
||||
(display (quaternion->list (quaternion* q1 q2))) (newline)
|
||||
(display "(quaternion* q q1 q2) = ")
|
||||
(display (quaternion->list (quaternion* q q1 q2))) (newline)
|
||||
(newline)
|
||||
(display "(quaternion=? q) = ")
|
||||
(display (quaternion=? q)) (newline)
|
||||
(display "(quaternion=? q q) = ")
|
||||
(display (quaternion=? q q)) (newline)
|
||||
(display "(quaternion=? q1 q2) = ")
|
||||
(display (quaternion=? q1 q2)) (newline)
|
||||
(display "(quaternion=? q q q) = ")
|
||||
(display (quaternion=? q q q)) (newline)
|
||||
(display "(quaternion=? q1 q1 q2) = ")
|
||||
(display (quaternion=? q1 q1 q2)) (newline)
|
||||
(newline)
|
||||
(display "(quaternion* q1 q2) = ")
|
||||
(display (quaternion->list (quaternion* q1 q2))) (newline)
|
||||
(display "(quaternion* q2 q1) = ")
|
||||
(display (quaternion->list (quaternion* q2 q1))) (newline)
|
||||
(display "(quaternion=? (quaternion* q1 q2)") (newline)
|
||||
(display " (quaternion* q2 q1)) = ")
|
||||
(display (quaternion=? (quaternion* q1 q2)
|
||||
(quaternion* q2 q1))) (newline)
|
||||
|
|
@ -1,150 +0,0 @@
|
|||
q = .quaternion~new(1, 2, 3, 4)
|
||||
q1 = .quaternion~new(2, 3, 4, 5)
|
||||
q2 = .quaternion~new(3, 4, 5, 6)
|
||||
r = 7
|
||||
|
||||
say "q =" q
|
||||
say "q1 =" q1
|
||||
say "q2 =" q2
|
||||
say "r =" r
|
||||
say "norm(q) =" q~norm
|
||||
say "-q =" (-q)
|
||||
say "q* =" q~conjugate
|
||||
say "q + r =" q + r
|
||||
say "q1 + q2 =" q1 + q2
|
||||
say "q * r =" q * r
|
||||
q1q2 = q1 * q2
|
||||
q2q1 = q2 * q1
|
||||
say "q1 * q2 =" q1q2
|
||||
say "q2 * q1 =" q2q1
|
||||
say "q1 == q1 =" (q1 == q1)
|
||||
say "q1q2 == q2q1 =" (q1q2 == q2q1)
|
||||
|
||||
|
||||
::class quaternion
|
||||
::method init
|
||||
expose r i j k
|
||||
use strict arg r, i = 0, j = 0, k = 0
|
||||
|
||||
-- quaternion instances are immutable, so these are
|
||||
-- read only attributes
|
||||
::attribute r GET
|
||||
::attribute i GET
|
||||
::attribute j GET
|
||||
::attribute k GET
|
||||
|
||||
::method norm
|
||||
expose r i j k
|
||||
return rxcalcsqrt(r * r + i * i + j * j + k * k)
|
||||
|
||||
::method invert
|
||||
expose r i j k
|
||||
norm = self~norm
|
||||
return self~class~new(r / norm, i / norm, j / norm, k / norm)
|
||||
|
||||
::method negative
|
||||
expose r i j k
|
||||
return self~class~new(-r, -i, -j, -k)
|
||||
|
||||
::method conjugate
|
||||
expose r i j k
|
||||
return self~class~new(r, -i, -j, -k)
|
||||
|
||||
::method add
|
||||
expose r i j k
|
||||
use strict arg other
|
||||
if other~isa(.quaternion) then
|
||||
return self~class~new(r + other~r, i + other~i, j + other~j, k + other~k)
|
||||
else return self~class~new(r + other, i, j, k)
|
||||
|
||||
::method subtract
|
||||
expose r i j k
|
||||
use strict arg other
|
||||
if other~isa(.quaternion) then
|
||||
return self~class~new(r - other~r, i - other~i, j - other~j, k - other~k)
|
||||
else return self~class~new(r - other, i, j, k)
|
||||
|
||||
::method times
|
||||
expose r i j k
|
||||
use strict arg other
|
||||
if other~isa(.quaternion) then
|
||||
return self~class~new(r * other~r - i * other~i - j * other~j - k * other~k, -
|
||||
r * other~i + i * other~r + j * other~k - k * other~j, -
|
||||
r * other~j - i * other~k + j * other~r + k * other~i, -
|
||||
r * other~k + i * other~j - j * other~i + k * other~r)
|
||||
else return self~class~new(r * other, i * other, j * other, k * other)
|
||||
|
||||
::method divide
|
||||
use strict arg other
|
||||
-- this is easier if everything is a quaternion
|
||||
if \other~isA(.quaternion) then other = .quaternion~new(other)
|
||||
-- division is multiplication with the inversion
|
||||
return self * other~invert
|
||||
|
||||
::method "=="
|
||||
expose r i j k
|
||||
use strict arg other
|
||||
|
||||
if \other~isa(.quaternion) then return .false
|
||||
-- Note: these are numeric comparisons, so we're using the "="
|
||||
-- method so those are handled correctly
|
||||
return r = other~r & i = other~i & j = other~j & k = other~k
|
||||
|
||||
::method "\=="
|
||||
use strict arg other
|
||||
return \self~"\=="(other)
|
||||
|
||||
::method "="
|
||||
-- this is equivalent of "=="
|
||||
forward message("==")
|
||||
|
||||
::method "\="
|
||||
-- this is equivalent of "\=="
|
||||
forward message("\==")
|
||||
|
||||
::method "<>"
|
||||
-- this is equivalent of "\=="
|
||||
forward message("\==")
|
||||
|
||||
::method "><"
|
||||
-- this is equivalent of "\=="
|
||||
forward message("\==")
|
||||
|
||||
-- some operator overrides -- these only work if the left-hand-side of the
|
||||
-- subexpression is a quaternion
|
||||
::method "*"
|
||||
forward message("TIMES")
|
||||
|
||||
::method "/"
|
||||
forward message("DIVIDE")
|
||||
|
||||
::method "-"
|
||||
-- need to check if this is a prefix minus or a subtract
|
||||
if arg() == 0 then
|
||||
forward message("NEGATIVE")
|
||||
else
|
||||
forward message("SUBTRACT")
|
||||
|
||||
::method "+"
|
||||
-- need to check if this is a prefix plus or an addition
|
||||
if arg() == 0 then
|
||||
return self -- we can return this copy since it is immutable
|
||||
else
|
||||
forward message("ADD")
|
||||
|
||||
::method string
|
||||
expose r i j k
|
||||
return r self~formatnumber(i)"i" self~formatnumber(j)"j" self~formatnumber(k)"k"
|
||||
|
||||
::method formatnumber private
|
||||
use arg value
|
||||
if value > 0 then return "+" value
|
||||
else return "-" value~abs
|
||||
|
||||
-- override hashcode for collection class hash uses
|
||||
::method hashCode
|
||||
expose r i j k
|
||||
return r~hashcode~bitxor(i~hashcode)~bitxor(j~hashcode)~bitxor(k~hashcode)
|
||||
|
||||
|
||||
::requires rxmath LIBRARY
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
q.norm={
|
||||
if(type(q) != "t_VEC" || #q != 4, error("incorrect type"));
|
||||
sqrt(q[1]^2+q[2]^2+q[3]^2+q[4]^2)
|
||||
};
|
||||
q.conj={
|
||||
if(type(q) != "t_VEC" || #q != 4, error("incorrect type"));
|
||||
-[-q[1],q[2],q[3],q[4]]
|
||||
};
|
||||
q.add={
|
||||
if(type(q) != "t_VEC" || #q != 4, error("incorrect type"));
|
||||
x->if(type(x) == "t_INT" || type(x) == t_REAL,
|
||||
[q[1]+x,q[2],q[3],q[4]]
|
||||
,
|
||||
if(type(x) == "t_VEC" && #x == 4,
|
||||
q+x
|
||||
,
|
||||
error("incorrect type")
|
||||
)
|
||||
)
|
||||
};
|
||||
q.mult={
|
||||
if(type(q) != "t_VEC" || #q != 4, error("incorrect type"));
|
||||
x->if(type(x) == "t_INT" || type(x) == t_REAL,
|
||||
x*q
|
||||
,
|
||||
if(type(x) == "t_VEC" && #x == 4,
|
||||
[q[1]*x[1] - q[2]*x[2] - q[3]*x[3] - q[4]*x[4],
|
||||
q[1]*x[2] + q[2]*x[1] + q[3]*x[4] - q[4]*x[3],
|
||||
q[1]*x[3] - q[2]*x[4] + q[3]*x[1] + q[4]*x[2],
|
||||
q[1]*x[4] + q[2]*x[3] - q[3]*x[2] + q[4]*x[1]]
|
||||
,
|
||||
error("incorrect type")
|
||||
)
|
||||
)
|
||||
};
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
r=7;q=[1,2,3,4];q1=[2,3,4,5];q2=[3,4,5,6];
|
||||
q.norm
|
||||
-q
|
||||
q.conj
|
||||
q.add(r)
|
||||
q1.add(q2)
|
||||
q1.add(q2) \\ or q1+q2
|
||||
q.mult(r) \\ or r*q or q*r
|
||||
q1.mult(q2)
|
||||
q1.mult(q2) != q2.mult(q1)
|
||||
|
|
@ -1,146 +0,0 @@
|
|||
*process source attributes xref or(!);
|
||||
qu: Proc Options(main);
|
||||
/**********************************************************************
|
||||
* 06.09.2013 Walter Pachl translated from REXX
|
||||
* added tasks 9 and A
|
||||
**********************************************************************/
|
||||
dcl v(4) Char(1) Var Init('','i','j','k');
|
||||
define structure 1 quat, 2 x(4) Dec Float(15);
|
||||
Dcl q type quat; Call quat_init(q, 1,2,3,4);
|
||||
Dcl q1 type quat; Call quat_init(q1,2,3,4,5);
|
||||
Dcl q2 type quat; Call quat_init(q2,3,4,5,6);
|
||||
Dcl q3 type quat; Call quat_init(q3,-2,3,-4,-5);
|
||||
Dcl r Dec Float(15)Init(7);
|
||||
|
||||
call showq(' ','q' ,q);
|
||||
call showq(' ','q1' ,q1);
|
||||
call showq(' ','q2' ,q2);
|
||||
call showq(' ','q3' ,q3);
|
||||
call shows(' ','r' ,r);
|
||||
Call shows('task 1:','norm q' ,norm(q));
|
||||
Call showq('task 2:','quatneg q' ,quatneg(q));
|
||||
Call showq('task 3:','conjugate q' ,quatConj(q));
|
||||
Call showq('task 4:','addition r+q' ,quatAddsq(r,q));
|
||||
Call showq('task 5:','addition q1+q2' ,quatAdd(q1,q2));
|
||||
Call showq('task 6:','multiplication q*r' ,quatMulqs(q,r));
|
||||
Call showq('task 7:','multiplication q1*q2' ,quatMul(q1,q2));
|
||||
Call showq('task 8:','multiplication q2*q1' ,quatMul(q2,q1));
|
||||
Call showq('task 9:','quatsub q1-q1' ,quatAdd(q1,quatneg(q1)));
|
||||
Call showq('task A:','addition q1+q3' ,quatAdd(q1,q3));
|
||||
Call showt('task B:','equal' ,quatEqual(quatMul(q1,q2),
|
||||
quatMul(q2,q1)));
|
||||
Call showt('task C:','q1=q1' ,quatEqual(q1,q1));
|
||||
|
||||
quatNeg: procedure(qp) Returns(type quat);
|
||||
Dcl (qp,qr) type quat;
|
||||
qr.x(*)=-qp.x(*);
|
||||
Return (qr);
|
||||
End;
|
||||
|
||||
quatAdd: procedure(qp,qq) Returns(type quat);
|
||||
Dcl (qp,qq,qr) type quat;
|
||||
qr.x(*)=qp.x(*)+qq.x(*);
|
||||
Return (qr);
|
||||
End;
|
||||
|
||||
quatAddsq: procedure(v,qp) Returns(type quat);
|
||||
Dcl v Dec Float(15);
|
||||
Dcl (qp,qr) type quat;
|
||||
qr.x(*)=qp.x(*);
|
||||
qr.x(1)=qp.x(1)+v;
|
||||
Return (qr);
|
||||
End;
|
||||
|
||||
quatConj: procedure(qp) Returns(type quat);
|
||||
Dcl (qp,qr) type quat;
|
||||
qr.x(*)=-qp.x(*);
|
||||
qr.x(1)= qp.x(1);
|
||||
Return (qr);
|
||||
End;
|
||||
|
||||
quatMul: procedure(qp,qq) Returns(type quat);
|
||||
Dcl (qp,qq,qr) type quat;
|
||||
qr.x(1)=
|
||||
qp.x(1)*qq.x(1)-qp.x(2)*qq.x(2)-qp.x(3)*qq.x(3)-qp.x(4)*qq.x(4);
|
||||
qr.x(2)=
|
||||
qp.x(1)*qq.x(2)+qp.x(2)*qq.x(1)+qp.x(3)*qq.x(4)-qp.x(4)*qq.x(3);
|
||||
qr.x(3)=
|
||||
qp.x(1)*qq.x(3)-qp.x(2)*qq.x(4)+qp.x(3)*qq.x(1)+qp.x(4)*qq.x(2);
|
||||
qr.x(4)=
|
||||
qp.x(1)*qq.x(4)+qp.x(2)*qq.x(3)-qp.x(3)*qq.x(2)+qp.x(4)*qq.x(1);
|
||||
Return (qr);
|
||||
End;
|
||||
|
||||
quatMulqs: procedure(qp,v) Returns(type quat);
|
||||
Dcl (qp,qr) type quat;
|
||||
Dcl v Dec Float(15);
|
||||
qr.x(*)=qp.x(*)*v;
|
||||
Return (qr);
|
||||
End;
|
||||
|
||||
shows: Procedure(t1,t2,v);
|
||||
Dcl (t1,t2) Char(*);
|
||||
Dcl v Dec Float(15);
|
||||
Put Edit(t1,right(t2,24),' --> ',v)(Skip,a,a,a,f(15,13));
|
||||
End;
|
||||
|
||||
showt: Procedure(t1,t2,v);
|
||||
Dcl (t1,t2) Char(*);
|
||||
Dcl v Char(*) Var);
|
||||
Put Edit(t1,right(t2,24),' --> ',v)(Skip,a,a,a,a);
|
||||
End;
|
||||
|
||||
showq: Procedure(t1,t2,qp);
|
||||
Dcl qp type quat;
|
||||
Dcl (t1,t2) Char(*);
|
||||
Dcl (s,s2,p) Char(100) Var Init('');
|
||||
Dcl i Bin Fixed(31);
|
||||
Put String(s) Edit(t1,right(t2,24),' --> ')(a,a,a);
|
||||
Do i=1 To 4;
|
||||
Put String(p) Edit(abs(qp.x(i)))(p'ZZZ9');
|
||||
p=trim(p);
|
||||
Select;
|
||||
When(qp.x(i)<0) p='-'!!p!!v(i);
|
||||
When(p=0) p='';
|
||||
Otherwise Do
|
||||
If s2^='' Then p='+'!!p;
|
||||
If i>1 Then p=p!!v(i);
|
||||
End;
|
||||
End;
|
||||
s2=s2!!p
|
||||
End;
|
||||
If s2='' Then
|
||||
s2='0';
|
||||
Put Edit(s!!s2)(Skip,a);
|
||||
End;
|
||||
|
||||
norm: Procedure(qp) Returns(Dec Float(15));
|
||||
Dcl qp type quat;
|
||||
Dcl r Dec Float(15) Init(0);
|
||||
Dcl i Bin Fixed(31);
|
||||
Do i=1 To 4;
|
||||
r=r+qp.x(i)**2;
|
||||
End;
|
||||
Return (sqrt(r));
|
||||
End;
|
||||
|
||||
quat_init: Proc(qp,x,y,z,u);
|
||||
Dcl qp type quat;
|
||||
Dcl (x,y,z,u) Dec Float(15);
|
||||
qp.x(1)=x;
|
||||
qp.x(2)=y;
|
||||
qp.x(3)=z;
|
||||
qp.x(4)=u;
|
||||
End;
|
||||
|
||||
quatEqual: procedure(qp,qq) Returns(Char(12) Var);
|
||||
Dcl (qp,qq) type quat;
|
||||
Dcl i Bin Fixed(15);
|
||||
Do i=1 To 4;
|
||||
If qp.x(i)^=qq.x(i) Then
|
||||
Return('not equal');
|
||||
End;
|
||||
Return('equal');
|
||||
End;
|
||||
|
||||
End;
|
||||
|
|
@ -1,70 +0,0 @@
|
|||
package Quaternion;
|
||||
use List::Util 'reduce';
|
||||
use List::MoreUtils 'pairwise';
|
||||
|
||||
sub make {
|
||||
my $cls = shift;
|
||||
if (@_ == 1) { return bless [ @_, 0, 0, 0 ] }
|
||||
elsif (@_ == 4) { return bless [ @_ ] }
|
||||
else { die "Bad number of components: @_" }
|
||||
}
|
||||
|
||||
sub _abs { sqrt reduce { $a + $b * $b } @{ +shift } }
|
||||
sub _neg { bless [ map(-$_, @{+shift}) ] }
|
||||
sub _str { "(@{+shift})" }
|
||||
|
||||
sub _add {
|
||||
my ($x, $y) = @_;
|
||||
$y = [ $y, 0, 0, 0 ] unless ref $y;
|
||||
bless [ pairwise { $a + $b } @$x, @$y ]
|
||||
}
|
||||
|
||||
sub _sub {
|
||||
my ($x, $y, $swap) = @_;
|
||||
$y = [ $y, 0, 0, 0 ] unless ref $y;
|
||||
my @x = pairwise { $a - $b } @$x, @$y;
|
||||
if ($swap) { $_ = -$_ for @x }
|
||||
bless \@x;
|
||||
}
|
||||
|
||||
sub _mul {
|
||||
my ($x, $y) = @_;
|
||||
if (!ref $y) { return bless [ map($_ * $y, @$x) ] }
|
||||
my ($a1, $b1, $c1, $d1) = @$x;
|
||||
my ($a2, $b2, $c2, $d2) = @$y;
|
||||
bless [ $a1 * $a2 - $b1 * $b2 - $c1 * $c2 - $d1 * $d2,
|
||||
$a1 * $b2 + $b1 * $a2 + $c1 * $d2 - $d1 * $c2,
|
||||
$a1 * $c2 - $b1 * $d2 + $c1 * $a2 + $d1 * $b2,
|
||||
$a1 * $d2 + $b1 * $c2 - $c1 * $b2 + $d1 * $a2]
|
||||
}
|
||||
|
||||
sub conjugate {
|
||||
my @a = map { -$_ } @{$_[0]};
|
||||
$a[0] = $_[0][0];
|
||||
bless \@a
|
||||
}
|
||||
|
||||
use overload (
|
||||
'""' => \&_str,
|
||||
'+' => \&_add,
|
||||
'-' => \&_sub,
|
||||
'*' => \&_mul,
|
||||
'neg' => \&_neg,
|
||||
'abs' => \&_abs,
|
||||
);
|
||||
|
||||
package main;
|
||||
|
||||
my $a = Quaternion->make(1, 2, 3, 4);
|
||||
my $b = Quaternion->make(1, 1, 1, 1);
|
||||
|
||||
print "a = $a\n";
|
||||
print "b = $b\n";
|
||||
print "|a| = ", abs($a), "\n";
|
||||
print "-a = ", -$a, "\n";
|
||||
print "a + 1 = ", $a + 1, "\n";
|
||||
print "a + b = ", $a + $b, "\n";
|
||||
print "a - b = ", $a - $b, "\n";
|
||||
print "a conjugate is ", $a->conjugate, "\n";
|
||||
print "a * b = ", $a * $b, "\n";
|
||||
print "b * a = ", $b * $a, "\n";
|
||||
|
|
@ -1,74 +0,0 @@
|
|||
(phixonline)-->
|
||||
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
|
||||
<span style="color: #008080;">function</span> <span style="color: #000000;">norm</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">q</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #7060A8;">sqrt</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">sum</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">sq_power</span><span style="color: #0000FF;">(</span><span style="color: #000000;">q</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)))</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
|
||||
<span style="color: #008080;">function</span> <span style="color: #000000;">conjugate</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">q</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #000000;">q</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">q</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #000000;">q</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">..</span><span style="color: #000000;">4</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sq_uminus</span><span style="color: #0000FF;">(</span><span style="color: #000000;">q</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">..</span><span style="color: #000000;">4</span><span style="color: #0000FF;">])</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #000000;">q</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
|
||||
<span style="color: #008080;">function</span> <span style="color: #000000;">negative</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">q</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #7060A8;">sq_uminus</span><span style="color: #0000FF;">(</span><span style="color: #000000;">q</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
|
||||
<span style="color: #008080;">function</span> <span style="color: #000000;">add</span><span style="color: #0000FF;">(</span><span style="color: #004080;">object</span> <span style="color: #000000;">q1</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">object</span> <span style="color: #000000;">q2</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #004080;">atom</span><span style="color: #0000FF;">(</span><span style="color: #000000;">q1</span><span style="color: #0000FF;">)!=</span><span style="color: #004080;">atom</span><span style="color: #0000FF;">(</span><span style="color: #000000;">q2</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #004080;">atom</span><span style="color: #0000FF;">(</span><span style="color: #000000;">q1</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">q1</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">q1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">}</span>
|
||||
<span style="color: #008080;">else</span>
|
||||
<span style="color: #000000;">q2</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">q2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">}</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #7060A8;">sq_add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">q1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">q2</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
|
||||
<span style="color: #008080;">function</span> <span style="color: #000000;">mul</span><span style="color: #0000FF;">(</span><span style="color: #004080;">object</span> <span style="color: #000000;">q1</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">object</span> <span style="color: #000000;">q2</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #004080;">sequence</span><span style="color: #0000FF;">(</span><span style="color: #000000;">q1</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">and</span> <span style="color: #004080;">sequence</span><span style="color: #0000FF;">(</span><span style="color: #000000;">q2</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #004080;">atom</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">r1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">i1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">j1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">k1</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">q1</span><span style="color: #0000FF;">,</span>
|
||||
<span style="color: #0000FF;">{</span><span style="color: #000000;">r2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">i2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">j2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">k2</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">q2</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span> <span style="color: #000000;">r1</span><span style="color: #0000FF;">*</span><span style="color: #000000;">r2</span> <span style="color: #0000FF;">-</span> <span style="color: #000000;">i1</span><span style="color: #0000FF;">*</span><span style="color: #000000;">i2</span> <span style="color: #0000FF;">-</span> <span style="color: #000000;">j1</span><span style="color: #0000FF;">*</span><span style="color: #000000;">j2</span> <span style="color: #0000FF;">-</span> <span style="color: #000000;">k1</span><span style="color: #0000FF;">*</span><span style="color: #000000;">k2</span><span style="color: #0000FF;">,</span>
|
||||
<span style="color: #000000;">r1</span><span style="color: #0000FF;">*</span><span style="color: #000000;">i2</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">i1</span><span style="color: #0000FF;">*</span><span style="color: #000000;">r2</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">j1</span><span style="color: #0000FF;">*</span><span style="color: #000000;">k2</span> <span style="color: #0000FF;">-</span> <span style="color: #000000;">k1</span><span style="color: #0000FF;">*</span><span style="color: #000000;">j2</span><span style="color: #0000FF;">,</span>
|
||||
<span style="color: #000000;">r1</span><span style="color: #0000FF;">*</span><span style="color: #000000;">j2</span> <span style="color: #0000FF;">-</span> <span style="color: #000000;">i1</span><span style="color: #0000FF;">*</span><span style="color: #000000;">k2</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">j1</span><span style="color: #0000FF;">*</span><span style="color: #000000;">r2</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">k1</span><span style="color: #0000FF;">*</span><span style="color: #000000;">i2</span><span style="color: #0000FF;">,</span>
|
||||
<span style="color: #000000;">r1</span><span style="color: #0000FF;">*</span><span style="color: #000000;">k2</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">i1</span><span style="color: #0000FF;">*</span><span style="color: #000000;">j2</span> <span style="color: #0000FF;">-</span> <span style="color: #000000;">j1</span><span style="color: #0000FF;">*</span><span style="color: #000000;">i2</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">k1</span><span style="color: #0000FF;">*</span><span style="color: #000000;">r2</span> <span style="color: #0000FF;">}</span>
|
||||
<span style="color: #008080;">else</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #7060A8;">sq_mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">q1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">q2</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
|
||||
<span style="color: #008080;">function</span> <span style="color: #000000;">quats</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">q</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"%g%+gi%+gj%+gk"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">q</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
|
||||
<span style="color: #008080;">constant</span>
|
||||
<span style="color: #000000;">q</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">4</span><span style="color: #0000FF;">},</span>
|
||||
<span style="color: #000000;">q1</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">5</span><span style="color: #0000FF;">},</span>
|
||||
<span style="color: #000000;">q2</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">5</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">6</span><span style="color: #0000FF;">}</span>
|
||||
|
||||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">" q = %s\n"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">quats</span><span style="color: #0000FF;">(</span><span style="color: #000000;">q</span><span style="color: #0000FF;">)})</span>
|
||||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">" q1 = %s\n"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">quats</span><span style="color: #0000FF;">(</span><span style="color: #000000;">q1</span><span style="color: #0000FF;">)})</span>
|
||||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">" q2 = %s\n"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">quats</span><span style="color: #0000FF;">(</span><span style="color: #000000;">q2</span><span style="color: #0000FF;">)})</span>
|
||||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"\n"</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"1. norm(q) = %g\n"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">norm</span><span style="color: #0000FF;">(</span><span style="color: #000000;">q</span><span style="color: #0000FF;">))</span>
|
||||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"2. negative(q) = %s\n"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">quats</span><span style="color: #0000FF;">(</span><span style="color: #000000;">negative</span><span style="color: #0000FF;">(</span><span style="color: #000000;">q</span><span style="color: #0000FF;">))})</span>
|
||||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"3. conjugate(q) = %s\n"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">quats</span><span style="color: #0000FF;">(</span><span style="color: #000000;">conjugate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">q</span><span style="color: #0000FF;">))})</span>
|
||||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"\n"</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"4.a q + 7 = %s\n"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">quats</span><span style="color: #0000FF;">(</span><span style="color: #000000;">add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">q</span><span style="color: #0000FF;">,</span><span style="color: #000000;">7</span><span style="color: #0000FF;">))})</span>
|
||||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">" .b 7 + q = %s\n"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">quats</span><span style="color: #0000FF;">(</span><span style="color: #000000;">add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">7</span><span style="color: #0000FF;">,</span><span style="color: #000000;">q</span><span style="color: #0000FF;">))})</span>
|
||||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"\n"</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"5.a q1 + q2 = %s\n"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">quats</span><span style="color: #0000FF;">(</span><span style="color: #000000;">add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">q1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">q2</span><span style="color: #0000FF;">))})</span>
|
||||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">" .b q2 + q1 = %s\n"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">quats</span><span style="color: #0000FF;">(</span><span style="color: #000000;">add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">q2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">q1</span><span style="color: #0000FF;">))})</span>
|
||||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"\n"</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"6.a q * 49 = %s\n"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">quats</span><span style="color: #0000FF;">(</span><span style="color: #000000;">mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">q</span><span style="color: #0000FF;">,</span><span style="color: #000000;">49</span><span style="color: #0000FF;">))})</span>
|
||||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">" .b 49 * q = %s\n"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">quats</span><span style="color: #0000FF;">(</span><span style="color: #000000;">mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">49</span><span style="color: #0000FF;">,</span><span style="color: #000000;">q</span><span style="color: #0000FF;">))})</span>
|
||||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"\n"</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"7.a q1 * q2 = %s\n"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">quats</span><span style="color: #0000FF;">(</span><span style="color: #000000;">mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">q1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">q2</span><span style="color: #0000FF;">))})</span>
|
||||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">" .b q2 * q1 = %s\n"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">quats</span><span style="color: #0000FF;">(</span><span style="color: #000000;">mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">q2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">q1</span><span style="color: #0000FF;">))})</span>
|
||||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"\n"</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"8.a 4.a === 4.b: %t\n"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #7060A8;">equal</span><span style="color: #0000FF;">(</span><span style="color: #000000;">add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">q</span><span style="color: #0000FF;">,</span><span style="color: #000000;">7</span><span style="color: #0000FF;">),</span><span style="color: #000000;">add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">7</span><span style="color: #0000FF;">,</span><span style="color: #000000;">q</span><span style="color: #0000FF;">))})</span>
|
||||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">" .b 5.a === 5.b: %t\n"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #7060A8;">equal</span><span style="color: #0000FF;">(</span><span style="color: #000000;">add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">q1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">q2</span><span style="color: #0000FF;">),</span><span style="color: #000000;">add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">q2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">q1</span><span style="color: #0000FF;">))})</span>
|
||||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">" .c 6.a === 6.b: %t\n"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #7060A8;">equal</span><span style="color: #0000FF;">(</span><span style="color: #000000;">mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">q</span><span style="color: #0000FF;">,</span><span style="color: #000000;">49</span><span style="color: #0000FF;">),</span><span style="color: #000000;">mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">49</span><span style="color: #0000FF;">,</span><span style="color: #000000;">q</span><span style="color: #0000FF;">))})</span>
|
||||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">" .d 7.a === 7.b: %t\n"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #7060A8;">equal</span><span style="color: #0000FF;">(</span><span style="color: #000000;">mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">q1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">q2</span><span style="color: #0000FF;">),</span><span style="color: #000000;">mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">q2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">q1</span><span style="color: #0000FF;">))})</span>
|
||||
<!--
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
go =>
|
||||
test,
|
||||
nl.
|
||||
|
||||
add(qx(R0,I0,J0,K0), qx(R1,I1,J1,K1), qx(R,I,J,K)) :-
|
||||
!, R is R0+R1, I is I0+I1, J is J0+J1, K is K0+K1.
|
||||
add(qx(R0,I,J,K), F, qx(R,I,J,K)) :-
|
||||
number(F), !, R is R0 + F.
|
||||
add(F, qx(R0,I,J,K), Qx) :-
|
||||
add($qx(R0,I,J,K), F, Qx).
|
||||
mul(qx(R0,I0,J0,K0), qx(R1,I1,J1,K1), qx(R,I,J,K)) :- !,
|
||||
R is R0*R1 - I0*I1 - J0*J1 - K0*K1,
|
||||
I is R0*I1 + I0*R1 + J0*K1 - K0*J1,
|
||||
J is R0*J1 - I0*K1 + J0*R1 + K0*I1,
|
||||
K is R0*K1 + I0*J1 - J0*I1 + K0*R1.
|
||||
mul(qx(R0,I0,J0,K0), F, qx(R,I,J,K)) :-
|
||||
number(F), !, R is R0*F, I is I0*F, J is J0*F, K is K0*F.
|
||||
mul(F, qx(R0,I0,J0,K0), Qx) :-
|
||||
mul($qx(R0,I0,J0,K0),F,Qx).
|
||||
abs(qx(R,I,J,K), Norm) :-
|
||||
Norm is sqrt(R*R+I*I+J*J+K*K).
|
||||
negate(qx(Ri,Ii,Ji,Ki),qx(R,I,J,K)) :-
|
||||
R is -Ri, I is -Ii, J is -Ji, K is -Ki.
|
||||
conjugate(qx(R,Ii,Ji,Ki),qx(R,I,J,K)) :-
|
||||
I is -Ii, J is -Ji, K is -Ki.
|
||||
|
||||
data(q, qx(1,2,3,4)).
|
||||
data(q1, qx(2,3,4,5)).
|
||||
data(q2, qx(3,4,5,6)).
|
||||
data(r, 7).
|
||||
|
||||
test :- data(Name, $qx(A,B,C,D)), abs($qx(A,B,C,D), Norm),
|
||||
printf("abs(%w) is %w\n", Name, Norm), fail.
|
||||
test :- data(q, Qx), negate(Qx, Nqx),
|
||||
printf("negate(%w) is %w\n", q, Nqx), fail.
|
||||
test :- data(q, Qx), conjugate(Qx, Nqx),
|
||||
printf("conjugate(%w) is %w\n", q, Nqx), fail.
|
||||
test :- data(q1, Q1), data(q2, Q2), add(Q1, Q2, Qx),
|
||||
printf("q1+q2 is %w\n", Qx), fail.
|
||||
test :- data(q1, Q1), data(q2, Q2), add(Q2, Q1, Qx),
|
||||
printf("q2+q1 is %w\n", Qx), fail.
|
||||
test :- data(q, Qx), data(r, R), mul(Qx, R, Nqx),
|
||||
printf("q*r is %w\n", Nqx), fail.
|
||||
test :- data(q, Qx), data(r, R), mul(R, Qx, Nqx),
|
||||
printf("r*q is %w\n", Nqx), fail.
|
||||
test :- data(q1, Q1), data(q2, Q2), mul(Q1, Q2, Qx),
|
||||
printf("q1*q2 is %w\n", Qx), fail.
|
||||
test :- data(q1, Q1), data(q2, Q2), mul(Q2, Q1, Qx),
|
||||
printf("q2*q1 is %w\n", Qx), fail.
|
||||
test.
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
(scl 6)
|
||||
|
||||
(def 'quatCopy copy)
|
||||
|
||||
(de quatNorm (Q)
|
||||
(sqrt (sum * Q Q)) )
|
||||
|
||||
(de quatNeg (Q)
|
||||
(mapcar - Q) )
|
||||
|
||||
(de quatConj (Q)
|
||||
(cons (car Q) (mapcar - (cdr Q))) )
|
||||
|
||||
(de quatAddR (Q R)
|
||||
(cons (+ R (car Q)) (cdr Q)) )
|
||||
|
||||
(de quatAdd (Q1 Q2)
|
||||
(mapcar + Q1 Q2) )
|
||||
|
||||
(de quatMulR (Q R)
|
||||
(mapcar */ (mapcar * Q (circ R)) (1.0 .)) )
|
||||
|
||||
(de quatMul (Q1 Q2)
|
||||
(mapcar
|
||||
'((Ops I)
|
||||
(sum '((Op R I) (Op (*/ R (get Q2 I) 1.0))) Ops Q1 I) )
|
||||
'((+ - - -) (+ + + -) (+ - + +) (+ + - +))
|
||||
'((1 2 3 4) (2 1 4 3) (3 4 1 2) (4 3 2 1)) ) )
|
||||
|
||||
(de quatFmt (Q)
|
||||
(mapcar '((R S) (pack (format R *Scl) S))
|
||||
Q
|
||||
'(" + " "i + " "j + " "k") ) )
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
(setq
|
||||
Q (1.0 2.0 3.0 4.0)
|
||||
Q1 (2.0 3.0 4.0 5.0)
|
||||
Q2 (3.0 4.0 5.0 6.0)
|
||||
R 7.0 )
|
||||
|
||||
(prinl "R = " (format R *Scl))
|
||||
(prinl "Q = " (quatFmt Q))
|
||||
(prinl "Q1 = " (quatFmt Q1))
|
||||
(prinl "Q2 = " (quatFmt Q2))
|
||||
(prinl)
|
||||
(prinl "norm(Q) = " (format (quatNorm Q) *Scl))
|
||||
(prinl "norm(Q1) = " (format (quatNorm Q1) *Scl))
|
||||
(prinl "norm(Q2) = " (format (quatNorm Q2) *Scl))
|
||||
(prinl "neg(Q) = " (quatFmt (quatNeg Q)))
|
||||
(prinl "conj(Q) = " (quatFmt (quatConj Q)))
|
||||
(prinl "Q + R = " (quatFmt (quatAddR Q R)))
|
||||
(prinl "Q1 + Q2 = " (quatFmt (quatAdd Q1 Q2)))
|
||||
(prinl "Q * R = " (quatFmt (quatMulR Q R)))
|
||||
(prinl "Q1 * Q2 = " (quatFmt (quatMul Q1 Q2)))
|
||||
(prinl "Q2 * Q1 = " (quatFmt (quatMul Q2 Q1)))
|
||||
(prinl (if (= (quatMul Q1 Q2) (quatMul Q2 Q1)) "Equal" "Not equal"))
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
class Quaternion {
|
||||
[Double]$w
|
||||
[Double]$x
|
||||
[Double]$y
|
||||
[Double]$z
|
||||
Quaternion() {
|
||||
$this.w = 0
|
||||
$this.x = 0
|
||||
$this.y = 0
|
||||
$this.z = 0
|
||||
}
|
||||
Quaternion([Double]$a, [Double]$b, [Double]$c, [Double]$d) {
|
||||
$this.w = $a
|
||||
$this.x = $b
|
||||
$this.y = $c
|
||||
$this.z = $d
|
||||
}
|
||||
[Double]abs2() {return $this.w*$this.w + $this.x*$this.x + $this.y*$this.y + $this.z*$this.z}
|
||||
[Double]abs() {return [math]::sqrt($this.wbs2())}
|
||||
static [Quaternion]real([Double]$r) {return [Quaternion]::new($r, 0, 0, 0)}
|
||||
static [Quaternion]add([Quaternion]$m,[Quaternion]$n) {return [Quaternion]::new($m.w+$n.w, $m.x+$n.x, $m.y+$n.y, $m.z+$n.z)}
|
||||
[Quaternion]addreal([Double]$r) {return [Quaternion]::add($this,[Quaternion]::real($r))}
|
||||
static [Quaternion]mul([Quaternion]$m,[Quaternion]$n) {
|
||||
return [Quaternion]::new(
|
||||
($m.w*$n.w) - ($m.x*$n.x) - ($m.y*$n.y) - ($m.z*$n.z),
|
||||
($m.w*$n.x) + ($m.x*$n.w) + ($m.y*$n.z) - ($m.z*$n.y),
|
||||
($m.w*$n.y) - ($m.x*$n.z) + ($m.y*$n.w) + ($m.z*$n.x),
|
||||
($m.w*$n.z) + ($m.x*$n.y) - ($m.y*$n.x) + ($m.z*$n.w))
|
||||
}
|
||||
|
||||
[Quaternion]mul([Double]$r) {return [Quaternion]::new($r*$this.w, $r*$this.x, $r*$this.y, $r*$this.z)}
|
||||
[Quaternion]negate() {return $this.mul(-1)}
|
||||
[Quaternion]conjugate() {return [Quaternion]::new($this.w, -$this.x, -$this.y, -$this.z)}
|
||||
static [String]st([Double]$r) {
|
||||
if(0 -le $r) {return "+$r"} else {return "$r"}
|
||||
}
|
||||
[String]show() {return "$($this.w)$([Quaternion]::st($this.x))i$([Quaternion]::st($this.y))j$([Quaternion]::st($this.z))k"}
|
||||
static [String]show([Quaternion]$other) {return $other.show()}
|
||||
}
|
||||
|
||||
|
||||
$q = [Quaternion]::new(1, 2, 3, 4)
|
||||
$q1 = [Quaternion]::new(2, 3, 4, 5)
|
||||
$q2 = [Quaternion]::new(3, 4, 5, 6)
|
||||
$r = 7
|
||||
"`$q: $($q.show())"
|
||||
"`$q1: $($q1.show())"
|
||||
"`$q2: $($q2.show())"
|
||||
"`$r: $r"
|
||||
""
|
||||
"norm `$q: $($q.wbs())"
|
||||
"negate `$q: $($q.negate().show())"
|
||||
"conjugate `$q: $($q.yonjugate().show())"
|
||||
"`$q + `$r: $($q.wddreal($r).show())"
|
||||
"`$q1 + `$q2: $([Quaternion]::show([Quaternion]::add($q1,$q2)))"
|
||||
"`$q * `$r: $($q.mul($r).show())"
|
||||
"`$q1 * `$q2: $([Quaternion]::show([Quaternion]::mul($q1,$q2)))"
|
||||
"`$q2 * `$q1: $([Quaternion]::show([Quaternion]::mul($q2,$q1)))"
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
function show([System.Numerics.Quaternion]$c) {
|
||||
function st([Double]$r) {
|
||||
if(0 -le $r) {return "+$r"} else {return "$r"}
|
||||
}
|
||||
return "$($c.w)$(st $c.y)i$(st $c.y)j$(st $c.z)k"
|
||||
}
|
||||
$q = [System.Numerics.Quaternion]::new(1, 2, 3, 4)
|
||||
$q1 = [System.Numerics.Quaternion]::new(2, 3, 4, 5)
|
||||
$q2 = [System.Numerics.Quaternion]::new(3, 4, 5, 6)
|
||||
$r = 7
|
||||
"`$q: $(show $q)"
|
||||
"`$q1: $(show $q1)"
|
||||
"`$q2: $(show $q2)"
|
||||
"`$r: $r"
|
||||
"norm `$q: $($q.Length())"
|
||||
"negate `$q: $(show ([System.Numerics.Quaternion]::Negate($q)))"
|
||||
"conjugate `$q: $(show ([System.Numerics.Quaternion]::Conjugate($q)))"
|
||||
"`$q + `$r: $(show ([System.Numerics.Quaternion]::new($q.w + $r, $q.x, $q.y, $q.z)))"
|
||||
"`$q1 + `$q2: $(show ([System.Numerics.Quaternion]::Add($q1,$q2)))"
|
||||
"`$q * `$r: $(show ([System.Numerics.Quaternion]::new($q.w * $r, $q.x * $r, $q.y * $r, $q.z * $r)))"
|
||||
"`$q1 * `$q2: $(show ([System.Numerics.Quaternion]::Multiply($q1,$q2)))"
|
||||
"`$q2 * `$q1: $(show ([System.Numerics.Quaternion]::Multiply($q2,$q1)))"
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
% A quaternion is represented as a complex term qx/4
|
||||
add(qx(R0,I0,J0,K0), qx(R1,I1,J1,K1), qx(R,I,J,K)) :-
|
||||
!, R is R0+R1, I is I0+I1, J is J0+J1, K is K0+K1.
|
||||
add(qx(R0,I,J,K), F, qx(R,I,J,K)) :-
|
||||
number(F), !, R is R0 + F.
|
||||
add(F, qx(R0,I,J,K), Qx) :-
|
||||
add(qx(R0,I,J,K), F, Qx).
|
||||
mul(qx(R0,I0,J0,K0), qx(R1,I1,J1,K1), qx(R,I,J,K)) :- !,
|
||||
R is R0*R1 - I0*I1 - J0*J1 - K0*K1,
|
||||
I is R0*I1 + I0*R1 + J0*K1 - K0*J1,
|
||||
J is R0*J1 - I0*K1 + J0*R1 + K0*I1,
|
||||
K is R0*K1 + I0*J1 - J0*I1 + K0*R1.
|
||||
mul(qx(R0,I0,J0,K0), F, qx(R,I,J,K)) :-
|
||||
number(F), !, R is R0*F, I is I0*F, J is J0*F, K is K0*F.
|
||||
mul(F, qx(R0,I0,J0,K0), Qx) :-
|
||||
mul(qx(R0,I0,J0,K0),F,Qx).
|
||||
abs(qx(R,I,J,K), Norm) :-
|
||||
Norm is sqrt(R*R+I*I+J*J+K*K).
|
||||
negate(qx(Ri,Ii,Ji,Ki),qx(R,I,J,K)) :-
|
||||
R is -Ri, I is -Ii, J is -Ji, K is -Ki.
|
||||
conjugate(qx(R,Ii,Ji,Ki),qx(R,I,J,K)) :-
|
||||
I is -Ii, J is -Ji, K is -Ki.
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
data(q, qx(1,2,3,4)).
|
||||
data(q1, qx(2,3,4,5)).
|
||||
data(q2, qx(3,4,5,6)).
|
||||
data(r, 7).
|
||||
|
||||
test :- data(Name, qx(A,B,C,D)), abs(qx(A,B,C,D), Norm),
|
||||
writef('abs(%w) is %w\n', [Name, Norm]), fail.
|
||||
test :- data(q, Qx), negate(Qx, Nqx),
|
||||
writef('negate(%w) is %w\n', [q, Nqx]), fail.
|
||||
test :- data(q, Qx), conjugate(Qx, Nqx),
|
||||
writef('conjugate(%w) is %w\n', [q, Nqx]), fail.
|
||||
test :- data(q1, Q1), data(q2, Q2), add(Q1, Q2, Qx),
|
||||
writef('q1+q2 is %w\n', [Qx]), fail.
|
||||
test :- data(q1, Q1), data(q2, Q2), add(Q2, Q1, Qx),
|
||||
writef('q2+q1 is %w\n', [Qx]), fail.
|
||||
test :- data(q, Qx), data(r, R), mul(Qx, R, Nqx),
|
||||
writef('q*r is %w\n', [Nqx]), fail.
|
||||
test :- data(q, Qx), data(r, R), mul(R, Qx, Nqx),
|
||||
writef('r*q is %w\n', [Nqx]), fail.
|
||||
test :- data(q1, Q1), data(q2, Q2), mul(Q1, Q2, Qx),
|
||||
writef('q1*q2 is %w\n', [Qx]), fail.
|
||||
test :- data(q1, Q1), data(q2, Q2), mul(Q2, Q1, Qx),
|
||||
writef('q2*q1 is %w\n', [Qx]), fail.
|
||||
test.
|
||||
|
|
@ -1,85 +0,0 @@
|
|||
Structure Quaternion
|
||||
a.f
|
||||
b.f
|
||||
c.f
|
||||
d.f
|
||||
EndStructure
|
||||
|
||||
Procedure.f QNorm(*x.Quaternion)
|
||||
ProcedureReturn Sqr(Pow(*x\a, 2) + Pow(*x\b, 2) + Pow(*x\c, 2) + Pow(*x\d, 2))
|
||||
EndProcedure
|
||||
|
||||
;If supplied, the result is returned in the quaternion structure *res,
|
||||
;otherwise a new quaternion is created. A pointer to the result is returned.
|
||||
Procedure QNeg(*x.Quaternion, *res.Quaternion = 0)
|
||||
If *res = 0: *res.Quaternion = AllocateMemory(SizeOf(Quaternion)): EndIf
|
||||
If *res
|
||||
*res\a = -*x\a
|
||||
*res\b = -*x\b
|
||||
*res\c = -*x\c
|
||||
*res\d = -*x\d
|
||||
EndIf
|
||||
ProcedureReturn *res
|
||||
EndProcedure
|
||||
|
||||
Procedure QConj(*x.Quaternion, *res.Quaternion = 0)
|
||||
If *res = 0: *res.Quaternion = AllocateMemory(SizeOf(Quaternion)): EndIf
|
||||
If *res
|
||||
*res\a = *x\a
|
||||
*res\b = -*x\b
|
||||
*res\c = -*x\c
|
||||
*res\d = -*x\d
|
||||
EndIf
|
||||
ProcedureReturn *res
|
||||
EndProcedure
|
||||
|
||||
Procedure QAddReal(r.f, *x.Quaternion, *res.Quaternion = 0)
|
||||
If *res = 0: *res.Quaternion = AllocateMemory(SizeOf(Quaternion)): EndIf
|
||||
If *res
|
||||
*res\a = *x\a + r
|
||||
*res\b = *x\b
|
||||
*res\c = *x\c
|
||||
*res\d = *x\d
|
||||
EndIf
|
||||
ProcedureReturn *res
|
||||
EndProcedure
|
||||
|
||||
Procedure QAddQuaternion(*x.Quaternion, *y.Quaternion, *res.Quaternion = 0)
|
||||
If *res = 0: *res.Quaternion = AllocateMemory(SizeOf(Quaternion)): EndIf
|
||||
If *res
|
||||
*res\a = *x\a + *y\a
|
||||
*res\b = *x\b + *y\b
|
||||
*res\c = *x\c + *y\c
|
||||
*res\d = *x\d + *y\d
|
||||
EndIf
|
||||
ProcedureReturn *res
|
||||
EndProcedure
|
||||
|
||||
Procedure QMulReal_and_Quaternion(r.f, *x.Quaternion, *res.Quaternion = 0)
|
||||
If *res = 0: *res.Quaternion = AllocateMemory(SizeOf(Quaternion)): EndIf
|
||||
If *res
|
||||
*res\a = *x\a * r
|
||||
*res\b = *x\b * r
|
||||
*res\c = *x\c * r
|
||||
*res\d = *x\d * r
|
||||
EndIf
|
||||
ProcedureReturn *res
|
||||
EndProcedure
|
||||
|
||||
Procedure QMulQuaternion(*x.Quaternion, *y.Quaternion, *res.Quaternion = 0)
|
||||
If *res = 0: *res.Quaternion = AllocateMemory(SizeOf(Quaternion)): EndIf
|
||||
If *res
|
||||
*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
|
||||
EndIf
|
||||
ProcedureReturn *res
|
||||
EndProcedure
|
||||
|
||||
Procedure Q_areEqual(*x.Quaternion, *y.Quaternion)
|
||||
If (*x\a <> *y\a) Or (*x\b <> *y\b) Or (*x\c <> *y\c) Or (*x\d <> *y\d)
|
||||
ProcedureReturn 0 ;false
|
||||
EndIf
|
||||
ProcedureReturn 1 ;true
|
||||
EndProcedure
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
Procedure.s ShowQ(*x.Quaternion, NN = 0)
|
||||
ProcedureReturn "{" + StrF(*x\a, NN) + "," + StrF(*x\b, NN) + "," + StrF(*x\c, NN) + "," + StrF(*x\d, NN) + "}"
|
||||
EndProcedure
|
||||
|
||||
If OpenConsole()
|
||||
Define.Quaternion Q0, Q1, Q2, res, res2
|
||||
Define.f r = 7
|
||||
|
||||
Q0\a = 1: Q0\b = 2: Q0\c = 3: Q0\d = 4
|
||||
Q1\a = 2: Q1\b = 3: Q1\c = 4: Q1\d = 5
|
||||
Q2\a = 3: Q2\b = 4: Q2\c = 5: Q2\d = 6
|
||||
|
||||
PrintN("Q0 = " + ShowQ(Q0, 0))
|
||||
PrintN("Q1 = " + ShowQ(Q1, 0))
|
||||
PrintN("Q2 = " + ShowQ(Q2, 0))
|
||||
|
||||
PrintN("Normal of Q0 = " + StrF(QNorm(Q0)))
|
||||
PrintN("Neg(Q0) = " + ShowQ(QNeg(Q0, res)))
|
||||
PrintN("Conj(Q0) = " + ShowQ(QConj(Q0, res)))
|
||||
PrintN("r + Q0 = " + ShowQ(QAddReal(r, Q0, res)))
|
||||
PrintN("Q0 + Q1 = " + ShowQ(QAddQuaternion(Q0, Q1, res)))
|
||||
PrintN("Q1 + Q2 = " + ShowQ(QAddQuaternion(Q1, Q2, res)))
|
||||
PrintN("Q1 * Q2 = " + ShowQ(QMulQuaternion(Q1, Q2, res)))
|
||||
PrintN("Q2 * Q1 = " + ShowQ(QMulQuaternion(Q2, Q1, res2)))
|
||||
Print( "Q1 * Q2"): If Q_areEqual(res, res2): Print(" = "): Else: Print(" <> "): EndIf: Print( "Q2 * Q1")
|
||||
|
||||
Print(#CRLF$ + #CRLF$ + "Press ENTER to exit"): Input()
|
||||
CloseConsole()
|
||||
EndIf
|
||||
|
|
@ -1,82 +0,0 @@
|
|||
from collections import namedtuple
|
||||
import math
|
||||
|
||||
class Q(namedtuple('Quaternion', 'real, i, j, k')):
|
||||
'Quaternion type: Q(real=0.0, i=0.0, j=0.0, k=0.0)'
|
||||
|
||||
__slots__ = ()
|
||||
|
||||
def __new__(_cls, real=0.0, i=0.0, j=0.0, k=0.0):
|
||||
'Defaults all parts of quaternion to zero'
|
||||
return super().__new__(_cls, float(real), float(i), float(j), float(k))
|
||||
|
||||
def conjugate(self):
|
||||
return Q(self.real, -self.i, -self.j, -self.k)
|
||||
|
||||
def _norm2(self):
|
||||
return sum( x*x for x in self)
|
||||
|
||||
def norm(self):
|
||||
return math.sqrt(self._norm2())
|
||||
|
||||
def reciprocal(self):
|
||||
n2 = self._norm2()
|
||||
return Q(*(x / n2 for x in self.conjugate()))
|
||||
|
||||
def __str__(self):
|
||||
'Shorter form of Quaternion as string'
|
||||
return 'Q(%g, %g, %g, %g)' % self
|
||||
|
||||
def __neg__(self):
|
||||
return Q(-self.real, -self.i, -self.j, -self.k)
|
||||
|
||||
def __add__(self, other):
|
||||
if type(other) == Q:
|
||||
return Q( *(s+o for s,o in zip(self, other)) )
|
||||
try:
|
||||
f = float(other)
|
||||
except:
|
||||
return NotImplemented
|
||||
return Q(self.real + f, self.i, self.j, self.k)
|
||||
|
||||
def __radd__(self, other):
|
||||
return Q.__add__(self, other)
|
||||
|
||||
def __mul__(self, other):
|
||||
if type(other) == Q:
|
||||
a1,b1,c1,d1 = self
|
||||
a2,b2,c2,d2 = other
|
||||
return Q(
|
||||
a1*a2 - b1*b2 - c1*c2 - d1*d2,
|
||||
a1*b2 + b1*a2 + c1*d2 - d1*c2,
|
||||
a1*c2 - b1*d2 + c1*a2 + d1*b2,
|
||||
a1*d2 + b1*c2 - c1*b2 + d1*a2 )
|
||||
try:
|
||||
f = float(other)
|
||||
except:
|
||||
return NotImplemented
|
||||
return Q(self.real * f, self.i * f, self.j * f, self.k * f)
|
||||
|
||||
def __rmul__(self, other):
|
||||
return Q.__mul__(self, other)
|
||||
|
||||
def __truediv__(self, other):
|
||||
if type(other) == Q:
|
||||
return self.__mul__(other.reciprocal())
|
||||
try:
|
||||
f = float(other)
|
||||
except:
|
||||
return NotImplemented
|
||||
return Q(self.real / f, self.i / f, self.j / f, self.k / f)
|
||||
|
||||
def __rtruediv__(self, other):
|
||||
return other * self.reciprocal()
|
||||
|
||||
__div__, __rdiv__ = __truediv__, __rtruediv__
|
||||
|
||||
Quaternion = Q
|
||||
|
||||
q = Q(1, 2, 3, 4)
|
||||
q1 = Q(2, 3, 4, 5)
|
||||
q2 = Q(3, 4, 5, 6)
|
||||
r = 7
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
>>> q
|
||||
Quaternion(real=1.0, i=2.0, j=3.0, k=4.0)
|
||||
>>> q1
|
||||
Quaternion(real=2.0, i=3.0, j=4.0, k=5.0)
|
||||
>>> q2
|
||||
Quaternion(real=3.0, i=4.0, j=5.0, k=6.0)
|
||||
>>> r
|
||||
7
|
||||
>>> q.norm()
|
||||
5.477225575051661
|
||||
>>> q1.norm()
|
||||
7.3484692283495345
|
||||
>>> q2.norm()
|
||||
9.273618495495704
|
||||
>>> -q
|
||||
Quaternion(real=-1.0, i=-2.0, j=-3.0, k=-4.0)
|
||||
>>> q.conjugate()
|
||||
Quaternion(real=1.0, i=-2.0, j=-3.0, k=-4.0)
|
||||
>>> r + q
|
||||
Quaternion(real=8.0, i=2.0, j=3.0, k=4.0)
|
||||
>>> q + r
|
||||
Quaternion(real=8.0, i=2.0, j=3.0, k=4.0)
|
||||
>>> q1 + q2
|
||||
Quaternion(real=5.0, i=7.0, j=9.0, k=11.0)
|
||||
>>> q2 + q1
|
||||
Quaternion(real=5.0, i=7.0, j=9.0, k=11.0)
|
||||
>>> q * r
|
||||
Quaternion(real=7.0, i=14.0, j=21.0, k=28.0)
|
||||
>>> r * q
|
||||
Quaternion(real=7.0, i=14.0, j=21.0, k=28.0)
|
||||
>>> q1 * q2
|
||||
Quaternion(real=-56.0, i=16.0, j=24.0, k=26.0)
|
||||
>>> q2 * q1
|
||||
Quaternion(real=-56.0, i=18.0, j=20.0, k=28.0)
|
||||
>>> assert q1 * q2 != q2 * q1
|
||||
>>>
|
||||
>>> i, j, k = Q(0,1,0,0), Q(0,0,1,0), Q(0,0,0,1)
|
||||
>>> i*i
|
||||
Quaternion(real=-1.0, i=0.0, j=0.0, k=0.0)
|
||||
>>> j*j
|
||||
Quaternion(real=-1.0, i=0.0, j=0.0, k=0.0)
|
||||
>>> k*k
|
||||
Quaternion(real=-1.0, i=0.0, j=0.0, k=0.0)
|
||||
>>> i*j*k
|
||||
Quaternion(real=-1.0, i=0.0, j=0.0, k=0.0)
|
||||
>>> q1 / q2
|
||||
Quaternion(real=0.7906976744186047, i=0.023255813953488358, j=-2.7755575615628914e-17, k=0.046511627906976744)
|
||||
>>> q1 / q2 * q2
|
||||
Quaternion(real=2.0000000000000004, i=3.0000000000000004, j=4.000000000000001, k=5.000000000000001)
|
||||
>>> q2 * q1 / q2
|
||||
Quaternion(real=2.0, i=3.465116279069768, j=3.906976744186047, k=4.767441860465116)
|
||||
>>> q1.reciprocal() * q1
|
||||
Quaternion(real=0.9999999999999999, i=0.0, j=0.0, k=0.0)
|
||||
>>> q1 * q1.reciprocal()
|
||||
Quaternion(real=0.9999999999999999, i=0.0, j=0.0, k=0.0)
|
||||
>>>
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
library(quaternions)
|
||||
|
||||
q <- Q(1, 2, 3, 4)
|
||||
q1 <- Q(2, 3, 4, 5)
|
||||
q2 <- Q(3, 4, 5, 6)
|
||||
r <- 7.0
|
||||
|
||||
display <- function(x){
|
||||
e <- deparse(substitute(x))
|
||||
res <- if(class(x) == "Q") paste(x$r, "+", x$i, "i+", x$j, "j+", x$k, "k", sep = "") else x
|
||||
cat(noquote(paste(c(e, " = ", res, "\n"), collapse="")))
|
||||
invisible(res)
|
||||
}
|
||||
|
||||
display(norm(q))
|
||||
display(-q)
|
||||
display(Conj(q))
|
||||
display(r + q)
|
||||
display(q1 + q2)
|
||||
display(r*q)
|
||||
display(q*r)
|
||||
if(display(q1*q2) == display(q2*q1)) cat("q1*q2 == q2*q1\n") else cat("q1*q2 != q2*q1\n")
|
||||
|
||||
## norm(q) = 5.47722557505166
|
||||
## -q = -1+-2i+-3j+-4k
|
||||
## Conj(q) = 1+-2i+-3j+-4k
|
||||
## r + q = 8+2i+3j+4k
|
||||
## q1 + q2 = 5+7i+9j+11k
|
||||
## r * q = 7+14i+21j+28k
|
||||
## q * r = 7+14i+21j+28k
|
||||
## q1 * q2 = -56+16i+24j+26k
|
||||
## q2 * q1 = -56+18i+20j+28k
|
||||
## q1*q2 != q2*q1
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
-- 28 Jul 2025
|
||||
include Settings
|
||||
|
||||
say 'QUATERNION TYPE'
|
||||
say version
|
||||
say
|
||||
i = '0 1'; j = '0 0 1'; k = '0 0 0 1'
|
||||
q = '1 2 3 4'; q1 = '2 3 4 5'; q2 = '3 4 5 6'; r = 7
|
||||
say 'VALUES'
|
||||
say 'i =' Lst2FormH(i)
|
||||
say 'j =' Lst2FormH(j)
|
||||
say 'k =' Lst2FormH(k)
|
||||
say 'q =' Lst2FormH(q)
|
||||
say 'q1 =' Lst2FormH(q1)
|
||||
say 'q2 =' Lst2FormH(q2)
|
||||
say 'r =' Lst2FormH(r)
|
||||
say
|
||||
say 'BASICS'
|
||||
say 'i*i =' Lst2FormH(SquareH(i))
|
||||
say 'j*j =' Lst2FormH(SquareH(j))
|
||||
say 'k*k =' Lst2FormH(SquareH(k))
|
||||
say 'i*j*k =' Lst2FormH(MulH(i,j,k))
|
||||
say '||q|| =' Std(NormH(q))
|
||||
say '-q =' Lst2FormH(NegH(q))
|
||||
say 'q* =' Lst2FormH(ConjH(q))
|
||||
say 'q+r =' Lst2FormH(AddH(q,r))
|
||||
say 'r+q =' Lst2FormH(AddH(r,q))
|
||||
say 'q1+q2 =' Lst2FormH(AddH(q1,q2))
|
||||
say 'q2+q1 =' Lst2FormH(AddH(q2,q1))
|
||||
say 'q*r =' Lst2FormH(MulH(q,r))
|
||||
say 'r*q =' Lst2FormH(MulH(r,q))
|
||||
say 'q1*q2 =' Lst2FormH(MulH(q1,q2)) 'does not'
|
||||
say 'q2*q1 =' Lst2FormH(MulH(q2,q1)) 'commute!'
|
||||
say
|
||||
say 'BONUS'
|
||||
say '1/q =' Lst2FormH(InvH(q))
|
||||
say 'q1/q2 =' Lst2FormH(DivLeftH(q1,q2)) 'left division'
|
||||
say 'q1/q2 =' Lst2FormH(DivRightH(q1,q2)) 'right division'
|
||||
exit
|
||||
|
||||
include Math
|
||||
|
|
@ -1,75 +0,0 @@
|
|||
#lang racket
|
||||
|
||||
(struct quaternion (a b c d)
|
||||
#:transparent)
|
||||
|
||||
(define-match-expander quaternion:
|
||||
(λ (stx)
|
||||
(syntax-case stx ()
|
||||
[(_ a b c d)
|
||||
#'(or (quaternion a b c d)
|
||||
(and a (app (λ(_) 0) b) (app (λ(_) 0) c) (app (λ(_) 0) d)))])))
|
||||
|
||||
(define (norm q)
|
||||
(match q
|
||||
[(quaternion: a b c d)
|
||||
(sqrt (+ (sqr a) (sqr b) (sqr c) (sqr d)))]))
|
||||
|
||||
(define (negate q)
|
||||
(match q
|
||||
[(quaternion: a b c d)
|
||||
(quaternion (- a) (- b) (- c) (- d))]))
|
||||
|
||||
(define (conjugate q)
|
||||
(match q
|
||||
[(quaternion: a b c d)
|
||||
(quaternion a (- b) (- c) (- d))]))
|
||||
|
||||
(define (add q1 q2 . q-rest)
|
||||
(let ((ans (match* (q1 q2)
|
||||
[((quaternion: a1 b1 c1 d1) (quaternion: a2 b2 c2 d2))
|
||||
(quaternion (+ a1 a2) (+ b1 b2) (+ c1 c2) (+ d1 d2))])))
|
||||
(if (empty? q-rest)
|
||||
ans
|
||||
(apply add (cons ans q-rest)))))
|
||||
|
||||
(define (multiply q1 q2 . q-rest)
|
||||
(let ((ans (match* (q1 q2)
|
||||
[((quaternion: a1 b1 c1 d1) (quaternion: a2 b2 c2 d2))
|
||||
(quaternion (- (* a1 a2) (* b1 b2) (* c1 c2) (* d1 d2))
|
||||
(+ (* a1 b2) (* b1 a2) (* c1 d2) (- (* d1 c2)))
|
||||
(+ (* a1 c2) (- (* b1 d2)) (* c1 a2) (* d1 b2))
|
||||
(+ (* a1 d2) (* b1 c2) (- (* c1 b2)) (* d1 a2)))])))
|
||||
(if (empty? q-rest)
|
||||
ans
|
||||
(apply multiply (cons ans q-rest)))))
|
||||
|
||||
;; Tests
|
||||
(module+ main
|
||||
(define i (quaternion 0 1 0 0))
|
||||
(define j (quaternion 0 0 1 0))
|
||||
(define k (quaternion 0 0 0 1))
|
||||
(displayln (multiply i j k))
|
||||
(newline)
|
||||
|
||||
(define q (quaternion 1 2 3 4))
|
||||
(define q1 (quaternion 2 3 4 5))
|
||||
(define q2 (quaternion 3 4 5 6))
|
||||
(define r 7)
|
||||
|
||||
(for ([quat (list q q1 q2)])
|
||||
(displayln quat)
|
||||
(displayln (norm quat))
|
||||
(displayln (negate quat))
|
||||
(displayln (conjugate quat))
|
||||
(newline))
|
||||
|
||||
(add r q)
|
||||
(add q1 q2)
|
||||
(multiply r q)
|
||||
|
||||
(newline)
|
||||
(multiply q1 q2)
|
||||
(multiply q2 q1)
|
||||
(equal? (multiply q1 q2)
|
||||
(multiply q2 q1)))
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
class Quaternion {
|
||||
has Real ( $.r, $.i, $.j, $.k );
|
||||
|
||||
multi method new ( Real $r, Real $i, Real $j, Real $k ) {
|
||||
self.bless: :$r, :$i, :$j, :$k;
|
||||
}
|
||||
multi qu(*@r) is export { Quaternion.new: |@r }
|
||||
sub postfix:<j>(Real $x) is export { qu 0, 0, $x, 0 }
|
||||
sub postfix:<k>(Real $x) is export { qu 0, 0, 0, $x }
|
||||
|
||||
method Str () { "$.r + {$.i}i + {$.j}j + {$.k}k" }
|
||||
method reals () { $.r, $.i, $.j, $.k }
|
||||
method conj () { qu $.r, -$.i, -$.j, -$.k }
|
||||
method norm () { sqrt [+] self.reals X** 2 }
|
||||
|
||||
multi infix:<eqv> ( Quaternion $a, Quaternion $b ) is export { $a.reals eqv $b.reals }
|
||||
|
||||
multi infix:<+> ( Quaternion $a, Real $b ) is export { qu $b+$a.r, $a.i, $a.j, $a.k }
|
||||
multi infix:<+> ( Real $a, Quaternion $b ) is export { qu $a+$b.r, $b.i, $b.j, $b.k }
|
||||
multi infix:<+> ( Quaternion $a, Complex $b ) is export { qu $b.re + $a.r, $b.im + $a.i, $a.j, $a.k }
|
||||
multi infix:<+> ( Complex $a, Quaternion $b ) is export { qu $a.re + $b.r, $a.im + $b.i, $b.j, $b.k }
|
||||
multi infix:<+> ( Quaternion $a, Quaternion $b ) is export { qu $a.reals Z+ $b.reals }
|
||||
|
||||
multi prefix:<-> ( Quaternion $a ) is export { qu $a.reals X* -1 }
|
||||
|
||||
multi infix:<*> ( Quaternion $a, Real $b ) is export { qu $a.reals X* $b }
|
||||
multi infix:<*> ( Real $a, Quaternion $b ) is export { qu $b.reals X* $a }
|
||||
multi infix:<*> ( Quaternion $a, Complex $b ) is export { $a * qu $b.reals, 0, 0 }
|
||||
multi infix:<*> ( Complex $a, Quaternion $b ) is export { $b R* qu $a.reals, 0, 0 }
|
||||
|
||||
multi infix:<*> ( Quaternion $a, Quaternion $b ) is export {
|
||||
my @a_rijk = $a.reals;
|
||||
my ( $r, $i, $j, $k ) = $b.reals;
|
||||
return qu [+]( @a_rijk Z* $r, -$i, -$j, -$k ), # real
|
||||
[+]( @a_rijk Z* $i, $r, $k, -$j ), # i
|
||||
[+]( @a_rijk Z* $j, -$k, $r, $i ), # j
|
||||
[+]( @a_rijk Z* $k, $j, -$i, $r ); # k
|
||||
}
|
||||
}
|
||||
import Quaternion;
|
||||
|
||||
my $q = 1 + 2i + 3j + 4k;
|
||||
my $q1 = 2 + 3i + 4j + 5k;
|
||||
my $q2 = 3 + 4i + 5j + 6k;
|
||||
my $r = 7;
|
||||
|
||||
say "1) q norm = {$q.norm}";
|
||||
say "2) -q = {-$q}";
|
||||
say "3) q conj = {$q.conj}";
|
||||
say "4) q + r = {$q + $r}";
|
||||
say "5) q1 + q2 = {$q1 + $q2}";
|
||||
say "6) q * r = {$q * $r}";
|
||||
say "7) q1 * q2 = {$q1 * $q2}";
|
||||
say "8) q1q2 { $q1 * $q2 eqv $q2 * $q1 ?? '==' !! '!=' } q2q1";
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
quaternion: context [
|
||||
quaternion!: make typeset! [block! hash! vector!]
|
||||
multiply: function [q [integer! float! quaternion!] p [integer! float! 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! float! quaternion!] p [integer! float! 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!]][sqrt first multiply q conjugate copy q]
|
||||
normalize: function [q [quaternion!]][n: norm q collect [forall q [keep q/1 / n]]]
|
||||
inverse: func [q [quaternion!]][(conjugate q) / ((norm q) ** 2)]
|
||||
]
|
||||
|
||||
set [q q1 q2 r] [[1 2 3 4] [2 3 4 5] [3 4 5 6] 7]
|
||||
|
||||
print [{
|
||||
1. The norm of a quaternion:
|
||||
`quaternion/norm q` =>} quaternion/norm q {
|
||||
|
||||
2. The negative of a quaternion:
|
||||
`quaternion/negate q` =>} mold quaternion/negate q {
|
||||
|
||||
3. The conjugate of a quaternion:
|
||||
<code>quaternion/conjugate q</code> =>} mold quaternion/conjugate q {
|
||||
|
||||
4. Addition of a real number `r` and a quaternion `q`:
|
||||
`quaternion/add r q` =>} mold quaternion/add r q {
|
||||
`quaternion/add q r` =>} mold quaternion/add q r {
|
||||
|
||||
5. Addition of two quaternions:
|
||||
`quaternion/add q1 q2` =>} mold quaternion/add q1 q2 {
|
||||
|
||||
6. Multiplication of a real number and a quaternion:
|
||||
`quaternion/multiply q r` =>} mold quaternion/multiply q r {
|
||||
`quaternion/multiply r q` =>} mold quaternion/multiply r q {
|
||||
|
||||
7. Multiplication of two quaternions `q1` and `q2` is given by:
|
||||
`quaternion/multiply q1 q2` =>} mold quaternion/multiply q1 q2 {
|
||||
|
||||
8. Show that, for the two quaternions `q1` and `q2`:
|
||||
`equal? quaternion/multiply q1 q2 mold quaternion/multiply q2 q1` =>}
|
||||
equal? quaternion/multiply q1 q2 quaternion/multiply q2 q1]
|
||||
|
|
@ -1,77 +0,0 @@
|
|||
class Quaternion
|
||||
def initialize(*parts)
|
||||
raise ArgumentError, "wrong number of arguments (#{parts.size} for 4)" unless parts.size == 4
|
||||
raise ArgumentError, "invalid value of quaternion parts #{parts}" unless parts.all? {|x| x.is_a?(Numeric)}
|
||||
@parts = parts
|
||||
end
|
||||
|
||||
def to_a; @parts; end
|
||||
def to_s; "Quaternion#{@parts.to_s}" end
|
||||
alias inspect to_s
|
||||
def complex_parts; [Complex(*to_a[0..1]), Complex(*to_a[2..3])]; end
|
||||
|
||||
def real; @parts.first; end
|
||||
def imag; @parts[1..3]; end
|
||||
def conj; Quaternion.new(real, *imag.map(&:-@)); end
|
||||
def norm; Math.sqrt(to_a.reduce(0){|sum,e| sum + e**2}) end # In Rails: Math.sqrt(to_a.sum { e**2 })
|
||||
|
||||
def ==(other)
|
||||
case other
|
||||
when Quaternion; to_a == other.to_a
|
||||
when Numeric; to_a == [other, 0, 0, 0]
|
||||
else false
|
||||
end
|
||||
end
|
||||
def -@; Quaternion.new(*to_a.map(&:-@)); end
|
||||
def -(other); self + -other; end
|
||||
|
||||
def +(other)
|
||||
case other
|
||||
when Numeric
|
||||
Quaternion.new(real + other, *imag)
|
||||
when Quaternion
|
||||
Quaternion.new(*to_a.zip(other.to_a).map { |x,y| x + y }) # In Rails: zip(other).map(&:sum)
|
||||
end
|
||||
end
|
||||
|
||||
def *(other)
|
||||
case other
|
||||
when Numeric
|
||||
Quaternion.new(*to_a.map { |x| x * other })
|
||||
when Quaternion
|
||||
# Multiplication of quaternions in C x C space. See "Cayley-Dickson construction".
|
||||
a, b, c, d = *complex_parts, *other.complex_parts
|
||||
x, y = a*c - d.conj*b, a*d + b*c.conj
|
||||
Quaternion.new(x.real, x.imag, y.real, y.imag)
|
||||
end
|
||||
end
|
||||
|
||||
# Coerce is called by Ruby to return a compatible type/receiver when the called method/operation does not accept a Quaternion
|
||||
def coerce(other)
|
||||
case other
|
||||
when Numeric then [Scalar.new(other), self]
|
||||
else raise TypeError, "#{other.class} can't be coerced into #{self.class}"
|
||||
end
|
||||
end
|
||||
|
||||
class Scalar
|
||||
def initialize(val); @val = val; end
|
||||
def +(other); other + @val; end
|
||||
def *(other); other * @val; end
|
||||
def -(other); Quaternion.new(@val, 0, 0, 0) - other; end
|
||||
end
|
||||
end
|
||||
|
||||
if __FILE__ == $0
|
||||
q = Quaternion.new(1,2,3,4)
|
||||
q1 = Quaternion.new(2,3,4,5)
|
||||
q2 = Quaternion.new(3,4,5,6)
|
||||
r = 7
|
||||
expressions = ["q", "q1", "q2",
|
||||
"q.norm", "-q", "q.conj", "q + r", "r + q","q1 + q2", "q2 + q1",
|
||||
"q * r", "r * q", "q1 * q2", "q2 * q1", "(q1 * q2 != q2 * q1)",
|
||||
"q - r", "r - q"]
|
||||
expressions.each do |exp|
|
||||
puts "%20s = %s" % [exp, eval(exp)]
|
||||
end
|
||||
end
|
||||
|
|
@ -1,173 +0,0 @@
|
|||
use std::fmt::{Display, Error, Formatter};
|
||||
use std::ops::{Add, Mul, Neg};
|
||||
|
||||
#[derive(Clone,Copy,Debug)]
|
||||
struct Quaternion {
|
||||
a: f64,
|
||||
b: f64,
|
||||
c: f64,
|
||||
d: f64
|
||||
}
|
||||
|
||||
impl Quaternion {
|
||||
pub fn new(a: f64, b: f64, c: f64, d: f64) -> Quaternion {
|
||||
Quaternion {
|
||||
a: a,
|
||||
b: b,
|
||||
c: c,
|
||||
d: d
|
||||
}
|
||||
}
|
||||
|
||||
pub fn norm(&self) -> f64 {
|
||||
(self.a.powi(2) + self.b.powi(2) + self.c.powi(2) + self.d.powi(2)).sqrt()
|
||||
}
|
||||
|
||||
pub fn conjugate(&self) -> Quaternion {
|
||||
Quaternion {
|
||||
a: self.a,
|
||||
b: -self.b,
|
||||
c: -self.c,
|
||||
d: -self.d
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Add for Quaternion {
|
||||
type Output = Quaternion;
|
||||
|
||||
#[inline]
|
||||
fn add(self, other: Quaternion) -> Self::Output {
|
||||
Quaternion {
|
||||
a: self.a + other.a,
|
||||
b: self.b + other.b,
|
||||
c: self.c + other.c,
|
||||
d: self.d + other.d
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<f64> for Quaternion {
|
||||
type Output = Quaternion;
|
||||
|
||||
#[inline]
|
||||
fn add(self, other: f64) -> Self::Output {
|
||||
Quaternion {
|
||||
a: self.a + other,
|
||||
b: self.b,
|
||||
c: self.c,
|
||||
d: self.d
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<Quaternion> for f64 {
|
||||
type Output = Quaternion;
|
||||
|
||||
#[inline]
|
||||
fn add(self, other: Quaternion) -> Self::Output {
|
||||
Quaternion {
|
||||
a: other.a + self,
|
||||
b: other.b,
|
||||
c: other.c,
|
||||
d: other.d
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Quaternion {
|
||||
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
|
||||
write!(f, "({} + {}i + {}j + {}k)", self.a, self.b, self.c, self.d)
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul for Quaternion {
|
||||
type Output = Quaternion;
|
||||
|
||||
#[inline]
|
||||
fn mul(self, rhs: Quaternion) -> Self::Output {
|
||||
Quaternion {
|
||||
a: self.a * rhs.a - self.b * rhs.b - self.c * rhs.c - self.d * rhs.d,
|
||||
b: self.a * rhs.b + self.b * rhs.a + self.c * rhs.d - self.d * rhs.c,
|
||||
c: self.a * rhs.c - self.b * rhs.d + self.c * rhs.a + self.d * rhs.b,
|
||||
d: self.a * rhs.d + self.b * rhs.c - self.c * rhs.b + self.d * rhs.a,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<f64> for Quaternion {
|
||||
type Output = Quaternion;
|
||||
|
||||
#[inline]
|
||||
fn mul(self, other: f64) -> Self::Output {
|
||||
Quaternion {
|
||||
a: self.a * other,
|
||||
b: self.b * other,
|
||||
c: self.c * other,
|
||||
d: self.d * other
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<Quaternion> for f64 {
|
||||
type Output = Quaternion;
|
||||
|
||||
#[inline]
|
||||
fn mul(self, other: Quaternion) -> Self::Output {
|
||||
Quaternion {
|
||||
a: other.a * self,
|
||||
b: other.b * self,
|
||||
c: other.c * self,
|
||||
d: other.d * self
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Neg for Quaternion {
|
||||
type Output = Quaternion;
|
||||
|
||||
#[inline]
|
||||
fn neg(self) -> Self::Output {
|
||||
Quaternion {
|
||||
a: -self.a,
|
||||
b: -self.b,
|
||||
c: -self.c,
|
||||
d: -self.d
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let q0 = Quaternion { a: 1., b: 2., c: 3., d: 4. };
|
||||
let q1 = Quaternion::new(2., 3., 4., 5.);
|
||||
let q2 = Quaternion::new(3., 4., 5., 6.);
|
||||
let r: f64 = 7.;
|
||||
|
||||
println!("q0 = {}", q0);
|
||||
println!("q1 = {}", q1);
|
||||
println!("q2 = {}", q2);
|
||||
println!("r = {}", r);
|
||||
println!();
|
||||
println!("-q0 = {}", -q0);
|
||||
println!("conjugate of q0 = {}", q0.conjugate());
|
||||
println!();
|
||||
println!("r + q0 = {}", r + q0);
|
||||
println!("q0 + r = {}", q0 + r);
|
||||
println!();
|
||||
println!("r * q0 = {}", r * q0);
|
||||
println!("q0 * r = {}", q0 * r);
|
||||
println!();
|
||||
println!("q0 + q1 = {}", q0 + q1);
|
||||
println!("q0 * q1 = {}", q0 * q1);
|
||||
println!();
|
||||
println!("q0 * (conjugate of q0) = {}", q0 * q0.conjugate());
|
||||
println!();
|
||||
println!(" q0 + q1 * q2 = {}", q0 + q1 * q2);
|
||||
println!("(q0 + q1) * q2 = {}", (q0 + q1) * q2);
|
||||
println!();
|
||||
println!(" q0 * q1 * q2 = {}", q0 *q1 * q2);
|
||||
println!("(q0 * q1) * q2 = {}", (q0 * q1) * q2);
|
||||
println!(" q0 * (q1 * q2) = {}", q0 * (q1 * q2));
|
||||
println!();
|
||||
println!("normal of q0 = {}", q0.norm());
|
||||
}
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
case class Quaternion(re: Double = 0.0, i: Double = 0.0, j: Double = 0.0, k: Double = 0.0) {
|
||||
lazy val im = (i, j, k)
|
||||
private lazy val norm2 = re*re + i*i + j*j + k*k
|
||||
lazy val norm = math.sqrt(norm2)
|
||||
|
||||
def negative = Quaternion(-re, -i, -j, -k)
|
||||
def conjugate = Quaternion(re, -i, -j, -k)
|
||||
def reciprocal = Quaternion(re/norm2, -i/norm2, -j/norm2, -k/norm2)
|
||||
|
||||
def +(q: Quaternion) = Quaternion(re+q.re, i+q.i, j+q.j, k+q.k)
|
||||
def -(q: Quaternion) = Quaternion(re-q.re, i-q.i, j-q.j, k-q.k)
|
||||
def *(q: Quaternion) = Quaternion(
|
||||
re*q.re - i*q.i - j*q.j - k*q.k,
|
||||
re*q.i + i*q.re + j*q.k - k*q.j,
|
||||
re*q.j - i*q.k + j*q.re + k*q.i,
|
||||
re*q.k + i*q.j - j*q.i + k*q.re
|
||||
)
|
||||
def /(q: Quaternion) = this * q.reciprocal
|
||||
|
||||
def unary_- = negative
|
||||
def unary_~ = conjugate
|
||||
|
||||
override def toString = "Q(%.2f, %.2fi, %.2fj, %.2fk)".formatLocal(java.util.Locale.ENGLISH, re, i, j, k)
|
||||
}
|
||||
|
||||
object Quaternion {
|
||||
import scala.language.implicitConversions
|
||||
import Numeric.Implicits._
|
||||
|
||||
implicit def number2Quaternion[T:Numeric](n: T) = Quaternion(n.toDouble)
|
||||
}
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
val q0=Quaternion(1.0, 2.0, 3.0, 4.0);
|
||||
val q1=Quaternion(2.0, 3.0, 4.0, 5.0);
|
||||
val q2=Quaternion(3.0, 4.0, 5.0, 6.0);
|
||||
val r=7;
|
||||
|
||||
println("q0 = "+ q0)
|
||||
println("q1 = "+ q1)
|
||||
println("q2 = "+ q2)
|
||||
println("r = "+ r)
|
||||
println()
|
||||
|
||||
println("q0.re = "+ q0.re)
|
||||
println("q0.im = "+ q0.im)
|
||||
println("q0.norm = "+ q0.norm)
|
||||
println("q0.negative = "+ q0.negative)
|
||||
println("-q0 = "+ -q0)
|
||||
println("q0.conjugate = "+ q0.conjugate)
|
||||
println("~q0 = "+ ~q0)
|
||||
println("q1+q2 = "+ (q1+q2))
|
||||
println("q2+q1 = "+ (q2+q1))
|
||||
println("q1+r = "+ (q1+r))
|
||||
println("r+q1 = "+ (r+q1))
|
||||
println("q1-q2 = "+ (q1-q2))
|
||||
println("q2-q1 = "+ (q2-q1))
|
||||
println("q1-r = "+ (q1-r))
|
||||
println("r-q1 = "+ (r-q1))
|
||||
println("q1*q2 = "+ q1*q2)
|
||||
println("q2*q1 = "+ q2*q1)
|
||||
println("q1*r = "+ q1*r)
|
||||
println("r*q1 = "+ r*q1)
|
||||
println("(q1*q2)!=(q2*q1) = "+ ((q1*q2)!=(q2*q1)))
|
||||
println("q1/q2 = "+ q1/q2)
|
||||
println("q2/q1 = "+ q2/q1)
|
||||
println("q1/r = "+ q1/r)
|
||||
println("r/q1 = "+ r/q1)
|
||||
|
|
@ -1,177 +0,0 @@
|
|||
$ include "seed7_05.s7i";
|
||||
include "float.s7i";
|
||||
include "math.s7i";
|
||||
|
||||
|
||||
# Define the quaternion number data type.
|
||||
const type: quaternion is new object struct
|
||||
var float: a is 0.0;
|
||||
var float: b is 0.0;
|
||||
var float: c is 0.0;
|
||||
var float: d is 0.0;
|
||||
end struct;
|
||||
|
||||
|
||||
# Create a quaternion number from its real and imaginary parts.
|
||||
const func quaternion: quaternion
|
||||
(in float: a, in float: b, in float: c, in float: d) is func
|
||||
result
|
||||
var quaternion: aQuaternion is quaternion.value;
|
||||
begin
|
||||
aQuaternion.a := a;
|
||||
aQuaternion.b := b;
|
||||
aQuaternion.c := c;
|
||||
aQuaternion.d := d;
|
||||
end func;
|
||||
|
||||
|
||||
# Helper function for str().
|
||||
const func string: signed (in float: number, in string: part) is func
|
||||
result
|
||||
var string: stri is str(number) & part;
|
||||
begin
|
||||
if number > 0.0 then
|
||||
stri := "+" & stri;
|
||||
elsif number = 0.0 then
|
||||
stri := "";
|
||||
end if;
|
||||
end func;
|
||||
|
||||
|
||||
# Convert a quaternion number to a string.
|
||||
const func string: str (in quaternion: number) is func
|
||||
result
|
||||
var string: stri is "";
|
||||
begin
|
||||
if number.a <> 0.0 then
|
||||
stri &:= str(number.a);
|
||||
end if;
|
||||
stri &:= signed(number.b, "i");
|
||||
stri &:= signed(number.c, "j");
|
||||
stri &:= signed(number.d, "k");
|
||||
end func;
|
||||
|
||||
|
||||
# Compute the norm of a quaternion number.
|
||||
const func float: norm (in quaternion: number) is func
|
||||
result
|
||||
var float: qnorm is 0.0;
|
||||
begin
|
||||
qnorm := sqrt(
|
||||
number.a ** 2.0 + number.b ** 2.0 +
|
||||
number.c ** 2.0 + number.d ** 2.0
|
||||
);
|
||||
end func;
|
||||
|
||||
|
||||
# Compute the negative of a quaternion number.
|
||||
const func quaternion: - (in quaternion: number) is func
|
||||
result
|
||||
var quaternion: negatedNumber is quaternion.value;
|
||||
begin
|
||||
negatedNumber.a := -number.a;
|
||||
negatedNumber.b := -number.b;
|
||||
negatedNumber.c := -number.c;
|
||||
negatedNumber.d := -number.d;
|
||||
end func;
|
||||
|
||||
|
||||
# Compute the conjugate of a quaternion number.
|
||||
const func quaternion: conjugate (in quaternion: number) is func
|
||||
result
|
||||
var quaternion: conjugateNumber is quaternion.value;
|
||||
begin
|
||||
conjugateNumber.a := number.a;
|
||||
conjugateNumber.b := -number.b;
|
||||
conjugateNumber.c := -number.c;
|
||||
conjugateNumber.d := -number.d;
|
||||
end func;
|
||||
|
||||
|
||||
# Add a float to a quaternion number.
|
||||
const func quaternion: (in quaternion: number) + (in float: real) is func
|
||||
result
|
||||
var quaternion: sum is quaternion.value;
|
||||
begin
|
||||
sum.a := number.a + real;
|
||||
sum.b := number.b;
|
||||
sum.c := number.c;
|
||||
sum.d := number.d;
|
||||
end func;
|
||||
|
||||
|
||||
# Add a quaternion number to a float.
|
||||
const func quaternion: (in float: real) + (in quaternion: number) is
|
||||
return number + real;
|
||||
|
||||
|
||||
# Add two quaternion numbers.
|
||||
const func quaternion: (in quaternion: number1) + (in quaternion: number2) is func
|
||||
result
|
||||
var quaternion: sum is quaternion.value;
|
||||
begin
|
||||
sum.a := number1.a + number2.a;
|
||||
sum.b := number1.b + number2.b;
|
||||
sum.c := number1.c + number2.c;
|
||||
sum.d := number1.d + number2.d;
|
||||
end func;
|
||||
|
||||
|
||||
# Multiply a float and a quaternion number.
|
||||
const func quaternion: (in float: real) * (in quaternion: number) is func
|
||||
result
|
||||
var quaternion: product is quaternion.value;
|
||||
begin
|
||||
product.a := number.a * real;
|
||||
product.b := number.b * real;
|
||||
product.c := number.c * real;
|
||||
product.d := number.d * real;
|
||||
end func;
|
||||
|
||||
|
||||
# Multiply a quaternion number and a float.
|
||||
const func quaternion: (in quaternion: number) * (in float: real) is
|
||||
return real * number;
|
||||
|
||||
|
||||
# Multiply two quaternion numbers.
|
||||
const func quaternion: (in quaternion: x) * (in quaternion: y) is func
|
||||
result
|
||||
var quaternion: product is quaternion.value;
|
||||
begin
|
||||
product.a := x.a * y.a - x.b * y.b - x.c * y.c - x.d * y.d;
|
||||
product.b := x.a * y.b + x.b * y.a + x.c * y.d - x.d * y.c;
|
||||
product.c := x.a * y.c - x.b * y.d + x.c * y.a + x.d * y.b;
|
||||
product.d := x.a * y.d + x.b * y.c - x.c * y.b + x.d * y.a;
|
||||
end func;
|
||||
|
||||
|
||||
# Allow quaternions to be written using write(), writeln() etc.
|
||||
enable_output(quaternion);
|
||||
|
||||
|
||||
# Demonstrate quaternion numbers.
|
||||
const proc: main is func
|
||||
local
|
||||
const quaternion: q is quaternion(1.0, 2.0, 3.0, 4.0);
|
||||
const quaternion: q1 is quaternion(2.0, 3.0, 4.0, 5.0);
|
||||
const quaternion: q2 is quaternion(3.0, 4.0, 5.0, 6.0);
|
||||
const float: r is 7.0;
|
||||
begin
|
||||
writeln(" q = " <& q);
|
||||
writeln("q1 = " <& q1);
|
||||
writeln("q2 = " <& q2);
|
||||
writeln(" r = " <& r <& "\n");
|
||||
|
||||
writeln("norm(q) = " <& norm(q));
|
||||
writeln("-q = " <& -q);
|
||||
writeln("conjugate(q) = " <& conjugate(q));
|
||||
writeln("q + r = " <& q + r);
|
||||
writeln("r + q = " <& r + q);
|
||||
writeln("q1 + q2 = " <& q1 + q2);
|
||||
writeln("q2 + q1 = " <& q2 + q1);
|
||||
writeln("q * r = " <& q * r);
|
||||
writeln("r * q = " <& r * q);
|
||||
writeln("q1 * q2 = " <& q1 * q2);
|
||||
writeln("q2 * q1 = " <& q2 * q1);
|
||||
end func;
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue