Quaternion type: Difference between revisions
Added Easylang
(Added Easylang) |
|||
(33 intermediate revisions by 20 users not shown) | |||
Line 53:
* [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>
=={{header|Action!}}==
{{libheader|Action! Tool Kit}}
{{libheader|Action! Real Math}}
<syntaxhighlight lang="action!">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</syntaxhighlight>
{{out}}
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Quaternion_type.png Screenshot from Atari 8-bit computer]
<pre>
q = 1+2i+3j+4k
q1 = 2+3i+4j+5k
q2 = 3+4i+5j+6k
r = 7
Norm(q) = 5.47722543
Norm(q1) = 7.34846906
Norm(q2) = 9.27361833
-q = -1-2i-3j-4k
Conj(q) = 1-2i-3j-4k
q+r = 8+2i+3j+4k
q1+q2 = 5+7i+9j+11k
q2+q1 = 5+7i+9j+11k
q*r = 7+14i+21j+28k
q1*q2 = -56+16i+24j+26k
q2*q1 = -56+18i+20j+28k
</pre>
=={{header|Ada}}==
The package specification (works with any floating-point type):
<
type Real is digits <>;
package Quaternions is
Line 71 ⟶ 259:
function "*" (Left, Right : Quaternion) return Quaternion;
function Image (Left : Quaternion) return String;
end Quaternions;</
The package implementation:
<
package body Quaternions is
package Elementary_Functions is
Line 131 ⟶ 319:
Real'Image (Left.D) & "k";
end Image;
end Quaternions;</
Test program:
<
with Quaternions;
procedure Test_Quaternion is
Line 158 ⟶ 346:
Put_Line ("q1 * q2 = " & Image (q1 * q2));
Put_Line ("q2 * q1 = " & Image (q2 * q1));
end Test_Quaternion;</
{{out}}
<pre>
Line 184 ⟶ 372:
{{works with|ALGOL 68G|Any - tested with release [http://sourceforge.net/projects/algol68/files/algol68g/algol68g-2.6 algol68g-2.6].}}
{{wont work with|ELLA ALGOL 68|Any (with appropriate job cards) - tested with release [http://sourceforge.net/projects/algol68/files/algol68toc/algol68toc-1.8.8d/algol68toc-1.8-8d.fc9.i386.rpm/download 1.8-8d] - due to extensive use of '''format'''[ted] ''transput''.}}
'''File: prelude/Quaternion.a68'''<
COMMENT REQUIRES:
Line 442 ⟶ 630:
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 #</
# -*- coding: utf-8 -*- #
Line 496 ⟶ 684:
));
print((REPR(-q1*q2), ", ", REPR(-q2*q1), new line))
)</
{{out}}
<pre>
Line 530 ⟶ 718:
=={{header|ALGOL W}}==
<
% Quaternion record type %
record Quaternion ( real a, b, c, d );
Line 631 ⟶ 819:
end.
</syntaxhighlight>
{{out}}
<pre>
Line 651 ⟶ 839:
q2q1:(-56.0, 18.0, 20.0, 28.0)
</pre>
=={{header|Arturo}}==
<syntaxhighlight lang="arturo">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]</syntaxhighlight>
{{out}}
<pre>qnorm [1 2 3 4] = 5.477225575051661
qneg [1 2 3 4] = [-1 -2 -3 -4]
qconj [1 2 3 4] = [1 -2 -3 -4]
qaddr [1 2 3 4] 7 = [8 2 3 4]
qmulr [1 2 3 4] 7 = [7 14 21 28]
qadd [2 3 4 5] [3 4 5 6] = [5 7 9 11]
qmul [2 3 4 5] [3 4 5 6] = [-56 16 24 26]
qmul [3 4 5 6] [2 3 4 5] = [-56 18 20 28]</pre>
=={{header|ATS}}==
{{libheader|ats2-xprelude}}
<syntaxhighlight lang="ATS">
//--------------------------------------------------------------------
#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
//--------------------------------------------------------------------
</syntaxhighlight>
{{out}}
<pre>$ patscc -std=gnu2x -O2 quaternions_task.dats -lm && ./a.out
q = 1+2i+3j+4k
q1 = 2+3i+4j+5k
q2 = 3+4i+5j+6k
||q|| = 5.477226
||q1|| = 7.348469
||q2|| = 9.273618
-q = -1-2i-3j-4k
-q1 = -2-3i-4j-5k
-q2 = -3-4i-5j-6k
conj q = 1-2i-3j-4k
conj q1 = 2-3i-4j-5k
conj q2 = 3-4i-5j-6k
q + r = 8+2i+3j+4k
r + q = 8+2i+3j+4k
q1 + q2 = 5+7i+9j+11k
q * r = 7+14i+21j+28k
r * q = 7+14i+21j+28k
q1 * q2 = -56+16i+24j+26k
q2 * q1 = -56+18i+20j+28k
((q1 * q2) = (q2 * q1)) is false</pre>
=={{header|AutoHotkey}}==
{{works with|AutoHotkey_L}} (AutoHotkey1.1+)
<
q1 := [2, 3, 4, 5]
q2 := [3, 4, 5, 6]
Line 725 ⟶ 1,267:
b .= v (A_Index = q.MaxIndex() ? ")" : ", ")
return b
}</
{{out}}
<pre>q = (1, 2, 3, 4)
Line 743 ⟶ 1,285:
=={{header|Axiom}}==
Axiom has built-in support for quaternions.
<
Type: ((Integer,Integer,Integer,Integer) -> Quaternion(Integer))
Line 790 ⟶ 1,332:
(13) true
Type: Boolean</
=={{header|BASIC}}==
==={{header|BASIC256}}===
{{works with|BASIC256|2.0.0.11}}
<syntaxhighlight lang="basic256">
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))
</syntaxhighlight>
{{out}}
<pre>
q = (1, 2, 3, 4)
q1 = (2, 3, 4, 5)
q2 = (3, 4, 5, 6)
r = 7
norm(q) = 5.47722557505
neg(q) = (-1, -2, -3, -4)
conjugate(q) = (1, -2, -3, -4)
q+r = (8, 2, 3, 4)
q1+q2 = (5, 7, 9, 11)
qr = (7, 14, 21, 28)
q1q2 = (-56, 16, 24, 26)
q2q1 = (-56, 18, 20, 28)
</pre>
==={{header|BBC BASIC}}===
Although BBC BASIC doesn't have native support for quaternions its array arithmetic provides all of the required operations either directly or very straightforwardly.
<
q() = 1, 2, 3, 4
q1() = 2, 3, 4, 5
Line 835 ⟶ 1,484:
DEF FNq_show(q()) : LOCAL i%, a$ : a$ = "("
FOR i% = 0 TO 3 : a$ += STR$(q(i%)) + ", " : NEXT
= LEFT$(LEFT$(a$)) + ")"</
{{out}}
<pre>
Line 854 ⟶ 1,503:
=={{header|C}}==
<
#include <stdlib.h>
#include <stdbool.h>
Line 984 ⟶ 1,633:
printf("(%lf, %lf, %lf, %lf)\n",
q->q[0], q->q[1], q->q[2], q->q[3]);
}</
<
{
size_t i;
Line 1,043 ⟶ 1,692:
free(q[0]); free(q[1]); free(q[2]); free(r);
return EXIT_SUCCESS;
}</
=={{header|C sharp}}==
<
struct Quaternion : IEquatable<Quaternion>
Line 1,135 ⟶ 1,784:
#endregion
}</
Demonstration:
<
static class Program
Line 1,171 ⟶ 1,820:
Console.WriteLine("q1*q2 {0} q2*q1", (q1 * q2) == (q2 * q1) ? "==" : "!=");
}
}</
{{out}}
Line 1,195 ⟶ 1,844:
This example uses templates to provide the underlying data-type, and includes several extra functions and constructors that often come up when using quaternions.
<
using namespace std;
Line 1,310 ⟶ 1,959:
(q.z < T()) ? (io << " - " << (-q.z) << "k") : (io << " + " << q.z << "k");
return io;
}</
Test program:
<
{
Quaternion<> q0(1, 2, 3, 4);
Line 1,352 ⟶ 2,001:
Quaternion<int> q5(2), q6(3);
cout << endl << q5*q6 << endl;
}</
{{out}}
Line 1,387 ⟶ 2,036:
6 + 0i + 0j + 0k
</pre>
=={{header|CLU}}==
<syntaxhighlight lang="clu">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</syntaxhighlight>
{{out}}
<pre> q0 = 1.000 + 2.000i + 3.000j + 4.000k
q1 = 2.000 + 3.000i + 4.000j + 5.000k
q2 = 3.000 + 4.000i + 5.000j + 6.000k
r = 7.000
norm(q0) = 5.477
-q0 = -1.000 + -2.000i + -3.000j + -4.000k
conj(q0) = 1.000 + -2.000i + -3.000j + 4.000k
q0 + r = 8.000 + 9.000i + 10.000j + 11.000k
q1 + q2 = 5.000 + 7.000i + 9.000j + 11.000k
q0 * r = 7.000 + 14.000i + 21.000j + 28.000k
q1 * q2 = -56.000 + 16.000i + 24.000j + 26.000k
q2 * q1 = -56.000 + 18.000i + 20.000j + 28.000k
q1 * q2 ~= q2 * q1</pre>
=={{header|Common Lisp}}==
<
(defclass quaternion () ((a :accessor q-a :initarg :a :type real)
(b :accessor q-b :initarg :b :type real)
Line 1,467 ⟶ 2,215:
(format t "q*q1*q2 = ~a~&" (reduce #'mul (list q q1 q2)))
(format t "q-q1-q2 = ~a~&" (reduce #'sub (list q q1 q2)))
</syntaxhighlight>
{{out}}
Line 1,479 ⟶ 2,227:
=={{header|Crystal}}==
{{trans|Rust and Ruby}}
<
property a, b, c, d
Line 1,509 ⟶ 2,257:
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
Line 1,553 ⟶ 2,315:
puts
puts "q1 * q2 != q2 * q1 => #{(q1 * q2) != (q2 * q1)}"
puts "q1 * q2 == q2 * q1 => #{(q1 * q2) == (q2 * q1)}"</
{{out}}
<pre>q0 = (1 + 2i + 3j + 4k)
Line 1,595 ⟶ 2,357:
=={{header|D}}==
<
Line 1,820 ⟶ 2,582:
writeln(" exp(log(s)): ", exp(log(s)));
writeln(" log(exp(s)): ", log(exp(s)));
}</
{{out}}
<pre>1. q - norm: 7.34847
Line 1,852 ⟶ 2,614:
exp(log(s)): [2, 0.33427, 0.445694, 0.557117]
log(exp(s)): [2, 0.33427, 0.445694, 0.557117]</pre>
=={{header|Dart}}==
{{trans|Kotlin}}
<syntaxhighlight lang="Dart">
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}");
}
</syntaxhighlight>
{{out}}
<pre>
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
norm(q) = 5.477226
-q = (-1.0, -2.0, -3.0, -4.0)
conj(q) = (1.0, -2.0, -3.0, -4.0)
r + q = (8.0, 2.0, 3.0, 4.0)
q + r = (8.0, 2.0, 3.0, 4.0)
q1 + q2 = (5.0, 7.0, 9.0, 11.0)
r * q = (7.0, 14.0, 21.0, 28.0)
q * r = (7.0, 14.0, 21.0, 28.0)
q1 * q2 = (-56.0, 16.0, 24.0, 26.0)
q2 * q1 = (-56.0, 18.0, 20.0, 28.0)
q1 * q2 != q2 * q1 = true
</pre>
=={{header|Delphi}}==
<
interface
Line 1,983 ⟶ 2,838:
end;
end.</
Test program
<
{$APPTYPE CONSOLE}
Line 2,017 ⟶ 2,872:
writeln('q1 * q2 = ', (q1 * q2).ToString);
writeln('q2 * q1 = ', (q2 * q1).ToString);
end.</
{{out}}
Line 2,042 ⟶ 2,897:
=={{header|E}}==
<
def makeQuaternion(a, b, c, d) {
return def quaternion implements QS {
Line 2,102 ⟶ 2,957:
to d() { return d }
}
}</
<
# value: (2 + 3i + 4j + 5k)
Line 2,120 ⟶ 2,975:
? q1+(-2)
# value: (0 + 3i + 4j + 5k)</
=={{header|EasyLang}}==
<syntaxhighlight>
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"
.
</syntaxhighlight>
{{out}}
<pre>
q = [ 1 2 3 4 ]
q1 = [ 2 3 4 5 ]
q2 = [ 3 4 5 6 ]
r = 7
norm(q) = 5.48
neg(q) = [ -1 -2 -3 -4 ]
conjugate(q) = [ 1 -2 -3 -4 ]
q+r = [ 8 2 3 4 ]
q1+q2 = [ 5 7 9 11 ]
qr = [ 7 14 21 28 ]
q1q2 = [ -56 16 24 26 ]
q2q1 = [ -56 18 20 28 ]
q1 != q2
</pre>
=={{header|Eero}}==
<
interface Quaternion : Number
Line 2,224 ⟶ 3,161:
Log( 'q2 * q1 = %@', q2 * q1 )
return 0</
{{out}}
Line 2,245 ⟶ 3,182:
=={{header|Elena}}==
{{trans|C#}}
ELENA
<
import extensions;
import extensions'text;
Line 2,252 ⟶ 3,189:
struct Quaternion
{
constructor new(a, b, c, d)
Line 2,333 ⟶ 3,270:
console.printLineFormatted("q1*q2 {0} q2*q1", ((q1 * q2) == (q2 * q1)).iif("==","!="))
}</
{{out}}
<pre>
Line 2,355 ⟶ 3,292:
=={{header|ERRE}}==
<syntaxhighlight lang="erre">
PROGRAM QUATERNION
Line 2,460 ⟶ 3,397:
PRINTQ(R.)
END PROGRAM
</syntaxhighlight>
=={{header|Euphoria}}==
<
return sqrt(power(q[1],2)+power(q[2],2)+power(q[3],2)+power(q[4],2))
end function
Line 2,510 ⟶ 3,447:
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))})</
{{out}}
Line 2,524 ⟶ 3,461:
Mainly a {{trans|C#}} On the minus side we have no way to define a conversion to Quaternion from any suitable (numeric) type.
On the plus side we can avoid the stuff to make the equality structual (from the referential equality default) by just declaring it as an attribute to the type and let the compiler handle the details.
<
[<Struct; StructuralEquality; NoComparison>]
Line 2,586 ⟶ 3,523:
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</
{{out}}
<pre>q = Q(1.000000, 2.000000, 3.000000, 4.000000)
Line 2,608 ⟶ 3,545:
=={{header|Factor}}==
The <code>math.quaternions</code> vocabulary provides words for treating sequences like quaternions. <code>norm</code> and <code>vneg</code> come from the <code>math.vectors</code> vocabulary. Oddly, I wasn't able to find a word for adding a real to a quaternion, so I wrote one.
<
math.vectors prettyprint sequences ;
IN: rosetta-code.quaternion-type
Line 2,634 ⟶ 3,571:
[ q2 q1 [ q* ] ]
} 2show
]</
{{out}}
<pre>
Line 2,648 ⟶ 3,585:
=={{header|Forth}}==
<
: qvariable create 1 quaternions allot ;
Line 2,724 ⟶ 3,661:
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)</
=={{header|Fortran}}==
{{works with|Fortran|90 and later}}
<
implicit none
Line 2,888 ⟶ 3,825:
write(*, "(a, 4f8.3)") " q2 * q1 = ", q2 * q1
end program</
{{out}}
<pre> q = 1.000 2.000 3.000 4.000
Line 2,906 ⟶ 3,843:
=={{header|FreeBASIC}}==
<
Dim Shared As Integer q(3) = {1, 2, 3, 4}
Dim Shared As Integer q1(3) = {2, 3, 4, 5}
Line 2,984 ⟶ 3,921:
For i = 0 To 3 : t(i) = q2(i) : Next i : q_mul(t(),q1()) : Print "q2 * q1 = "; q_show(t())
End
</syntaxhighlight>
{{out}}
<pre>
Line 3,003 ⟶ 3,940:
=={{header|GAP}}==
<
A := QuaternionAlgebra(Rationals);
Line 3,112 ⟶ 4,049:
1/q;
# (1/30)*e+(-1/15)*i+(-1/10)*j+(-2/15)*k</
=={{header|Go}}==
Line 3,120 ⟶ 4,057:
The three inputs are reused repeatedly without being modified.
The output is also reused repeatedly, being overwritten for each operation.
<
import (
Line 3,198 ⟶ 4,135:
q1.r*q2.k+q1.i*q2.j-q1.j*q2.i+q1.k*q2.r
return z
}</
{{out}}
<pre>
Line 3,219 ⟶ 4,156:
=={{header|Haskell}}==
<
data Quaternion a =
Line 3,271 ⟶ 4,208:
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]"</
==Icon and {{header|Unicon}}==
Line 3,277 ⟶ 4,214:
Using Unicon's class system.
<syntaxhighlight lang="unicon">
class Quaternion(a, b, c, d)
Line 3,321 ⟶ 4,258:
self.d := if /d then 0 else d
end
</syntaxhighlight>
To test the above:
<syntaxhighlight lang="unicon">
procedure main ()
q := Quaternion (1,2,3,4)
Line 3,342 ⟶ 4,279:
write ("q2*q1 = " || q2.multiply(q1).string ())
end
</syntaxhighlight>
{{out}}
Line 3,361 ⟶ 4,298:
With [[wp:Dependent_type|dependent types]] we can implement the more general [[wp:Cayley-Dickson_construction|Cayley-Dickson construction]]. Here the dependent type <code>CD n a</code> is implemented. It depends on a natural number <code>n</code>, which is the number of iterations carried out, and the base type <code>a</code>. So the real numbers are just <code>CD 0 Double</code>, the complex numbers <code>CD 1 Double</code> and the quaternions <code>CD 2 Double</code>
<syntaxhighlight lang="idris">
module CayleyDickson
Line 3,457 ⟶ 4,394:
Abs (CD n Double) where
abs {n} = fromBase n . absCD
</syntaxhighlight>
To test it:
<syntaxhighlight lang="idris">
import CayleyDickson
Line 3,473 ⟶ 4,410:
printLn $ q2 * q1
printLn $ q1 * q2 == q2 * q1
</syntaxhighlight>
=={{header|J}}==
Line 3,479 ⟶ 4,416:
Derived from the [[j:System/Requests/Quaternions|j wiki]]:
<
ip=: +/ .* NB. inner product
T=. (_1^#:0 10 9 12)*0 7 16 23 A.=i.4
Line 3,489 ⟶ 4,426:
conj=: 1 _1 _1 _1 * toQ NB. + y
add=: +&toQ NB. x + y
mul=: (ip T ip ])&toQ NB. x * y</
T is a rank 3 tensor which allows us to express quaternion product ab as the inner product ATB if A and B are 4 element vectors representing the quaternions a and b. (Note also that once we have defined <code>mul</code> we no longer need to retain the definition of T, so we define T using =. instead of =:). The value of T is probably more interesting than its definition, so:
<
1 0 0 0
0 1 0 0
Line 3,512 ⟶ 4,449:
0 0 _1 0
0 1 0 0
1 0 0 0</
In other words, the last dimension of T corresponds to the structure of the right argument (columns, in the display of T), the first dimension of T corresponds to the structure of the left argument (tables, in the display of T) and the middle dimension of T corresponds to the structure of the result (rows, in the display of T).
Line 3,518 ⟶ 4,455:
Example use:
<syntaxhighlight lang="text"> q=: 1 2 3 4
q1=: 2 3 4 5
q2=: 3 4 5 6
Line 3,538 ⟶ 4,475:
_56 16 24 26
q2 mul q1
_56 18 20 28</
Finally, note that when quaternions are used to represent [[wp:Quaternions_and_spatial_rotation|orientation or rotation]], we are typically only interested in unit length quaternions. As this is the typical application for quaternions, you will sometimes see quaternion multiplication expressed using "simplifications" which are only valid for unit length quaternions. But note also that in many of those contexts you also need to normalize the quaternion length after multiplication.
Line 3,545 ⟶ 4,482:
=={{header|Java}}==
<
private final double a, b, c, d;
Line 3,647 ⟶ 4,584:
System.out.format("q1 \u00d7 q2 %s q2 \u00d7 q1%n", (q1q2.equals(q2q1) ? "=" : "\u2260"));
}
}</
{{out}}
Line 3,668 ⟶ 4,605:
Runs on Firefox 3+, limited support in other JS engines. More compatible JavaScript deserves its own entry.
<
// The Q() function takes an array argument and changes it
// prototype so that it becomes a Quaternion instance. This is
Line 3,725 ⟶ 4,662:
Quaternion.prototype = proto;
return Quaternion;
})();</
Task/Example Usage:
<
var q1 = Quaternion(2,3,4,5);
var q2 = Quaternion(3,4,5,6);
Line 3,746 ⟶ 4,683:
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)");</
{{out}}
Line 3,765 ⟶ 4,702:
=={{header|jq}}==
Program file: quaternion.jq<
# promotion of a real number to a quaternion
Line 3,856 ⟶ 4,793:
) ;
demo</
Example usage and output:
<
Quaternion(1;0;0;0) => 1 + 0i + 0j + 0k
abs($q) => 5.477225575051661
Line 3,874 ⟶ 4,811:
times($q1;$q2) => -56 + 16i + 24j + 26k
times($q2; $q1) => -56 + 18i + 20j + 28k
times($q1; $q2) != times($q2; $q1) => true</
=={{header|Julia}}==
https://github.com/andrioni/Quaternions.jl/blob/master/src/Quaternions.jl has a more complete implementation.
This is derived from the [https://github.com/JuliaLang/julia/blob/release-0.2/examples/quaternion.jl quaternion example file] included with Julia 0.2, which implements a quaternion type complete with arithmetic, type conversions / promotion rules, polymorphism over arbitrary real numeric types, and pretty-printing.
<
immutable Quaternion{T<:Real} <: Number
Line 3,919 ⟶ 4,856:
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)
</syntaxhighlight>
Example usage and output:
<
julia> q = Quaternion (1, 2, 3, 4)
q1 = Quaternion(2, 3, 4, 5)
Line 3,947 ⟶ 4,884:
julia> q1*q2, q2*q1, q1*q2 != q2*q1
(-56 + 16i + 24j + 26k,-56 + 18i + 20j + 28k,true)</
=={{header|Kotlin}}==
<
data class Quaternion(val a: Double, val b: Double, val c: Double, val d: Double) {
Line 4,006 ⟶ 4,943:
println("q2 * q1 = $q4\n")
println("q1 * q2 != q2 * q1 = ${q3 != q4}")
}</
{{out}}
Line 4,033 ⟶ 4,970:
=={{header|Liberty BASIC}}==
Quaternions saved as a space-separated string of four numbers.
<syntaxhighlight lang="lb">
q$ = q$( 1 , 2 , 3 , 4 )
Line 4,146 ⟶ 5,083:
add2$ =q$( ar +br, ai +bi, aj +bj, ak +bk)
end function
</
=={{header|Lua}}==
<
function Quaternion.new( a, b, c, d )
Line 4,211 ⟶ 5,148:
function Quaternion.print( p )
print( string.format( "%f + %fi + %fj + %fk\n", p.a, p.b, p.c, p.d ) )
end</
Examples:
<
q2 = Quaternion.new( 5, 6, 7, 8 )
r = 12
Line 4,225 ⟶ 5,162:
io.write( "q1*r = " ); Quaternion.print( q1*r )
io.write( "q1*q2 = " ); Quaternion.print( q1*q2 )
io.write( "q2*q1 = " ); Quaternion.print( q2*q1 )</
{{out}}
Line 4,240 ⟶ 5,177:
=={{header|M2000 Interpreter}}==
We can define Quaternions using a class, using operators for specific tasks, as negate, add, multiplication and equality with rounding to 13 decimal place (thats what doing "==" operator for doubles)
<syntaxhighlight lang="m2000 interpreter">
Module CheckIt {
class Quaternion {
Line 4,336 ⟶ 5,273:
Print q1q2==q2q1 ' false
\\ multiplication and equality in one expression
Print
Print
}
CheckIt
</syntaxhighlight>
{{out}}
<pre>
Line 4,355 ⟶ 5,292:
True
False
True</pre>
=={{header|Maple}}==
<syntaxhighlight lang="maple">
with(ArrayTools);
Line 4,506 ⟶ 5,443:
print("divide q1 by q2"):
q1 / q2;
</syntaxhighlight>
{{out}}<pre>
"q, q1, q2"
Line 4,559 ⟶ 5,496:
</pre>
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<
q=Quaternion[1,2,3,4]
q1=Quaternion[2,3,4,5]
Line 4,590 ⟶ 5,527:
q2**q1
->Quaternion[-56,18,20,28]
</syntaxhighlight>
=={{header|Mercury}}==
Line 4,596 ⟶ 5,533:
A possible implementation of quaternions in Mercury (the simplest representation) would look like this. Note that this is a full module implementation, complete with boilerplate, and that it works by giving an explicit conversion function for floats, converting a float into a quaternion representation of that float. Thus the float value <code>7.0</code> gets turned into the quaternion representation <code>q(7.0, 0.0, 0.0, 0.0)</code> through the function call <code>r(7.0)</code>.
<
:- interface.
Line 4,633 ⟶ 5,570:
W0*I1 + I0*W1 + J0*K1 - K0*J1,
W0*J1 - I0*K1 + J0*W1 + K0*I1,
W0*K1 + I0*J1 - J0*I1 + K0*W1 ).</
The following test module puts the module through its paces.
<
:- interface.
Line 4,712 ⟶ 5,649:
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.</
The output of the above code follows:
Line 4,750 ⟶ 5,687:
Q1 * Q2 = q(-56.000000, 16.000000, 24.000000, 26.000000)
Q2 * Q1 = q(-56.000000, 18.000000, 20.000000, 28.000000)
=={{header|Nim}}==
For simplicity, we have limited the type of quaternion fields to floats (i.e. float64). An implementation could use a generic type in order to allow other field types such as float32.
<syntaxhighlight lang="nim">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</syntaxhighlight>
{{out}}
<pre>∥q∥ = 5.477225575051661
-q = -1.0-2.0i-3.0j-4.0k
q* = 1.0-2.0i-3.0j-4.0k
q + r = 8.0+2.0i+3.0j+4.0k
r + q = 8.0+2.0i+3.0j+4.0k
q1 + q2 = 5.0+7.0i+9.0j+11.0k
qr = 7.0+14.0i+21.0j+28.0k
rq = 7.0+14.0i+21.0j+28.0k
q1 * q2 = -56.0+16.0i+24.0j+26.0k
q2 * q1 = -56.0+18.0i+20.0j+28.0k</pre>
As can be seen, <code>q1 * q2 != q2 * q1</code>.
=={{header|OCaml}}==
This implementation was build strictly to the specs without looking (too much) at other implementations. The implementation as a record type with only floats is said (on the ocaml mailing list) to be especially efficient. Put this into a file quaternion.ml:
<
type quaternion = {a: float; b: float; c: float; d: float}
Line 4,819 ⟶ 5,847:
pf "8. instead q2 * q1 = %s \n" (qstring (multq q2 q1));
pf "\n";
</syntaxhighlight>
using this file on the command line will produce:
Line 4,835 ⟶ 5,863:
</pre>
For completeness, and since data types are of utmost importance in OCaml, here the types produced by pasting the code into the toplevel (''ocaml'' is the toplevel):
<
type quaternion = { a : float; b : float; c : float; d : float; }
val norm : quaternion -> float = <fun>
Line 4,847 ⟶ 5,875:
val qmake : float -> float -> float -> float -> quaternion = <fun>
val qstring : quaternion -> string = <fun>
</syntaxhighlight>
=={{header|Octave}}==
Line 4,854 ⟶ 5,882:
Such a package can be install with the command:
<syntaxhighlight lang="text">pkg install -forge quaternion</
Here is a sample interactive session solving the task:
<syntaxhighlight lang="text">> q = quaternion (1, 2, 3, 4)
q = 1 + 2i + 3j + 4k
> q1 = quaternion (2, 3, 4, 5)
Line 4,881 ⟶ 5,909:
ans = -56 + 16i + 24j + 26k
> q1 == q2
ans = 0</
=={{header|Oforth}}==
Line 4,887 ⟶ 5,915:
neg is defined as "0 self -" into Number class, so no need to define it (if #- is defined).
<
Quaternion method: _a @a ;
Line 4,910 ⟶ 5,938:
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 * + ) ;</
Usage :
<
| q q1 q2 r |
Line 4,933 ⟶ 5,961:
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 ] ;</
{{out}}
Line 4,949 ⟶ 5,977:
q1q2 and q2q1 are different quaternions
</pre>
=={{header|Ol}}==
See also [[#Scheme|the entry for Scheme]].
<syntaxhighlight lang="scheme">
;;
;; 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)
</syntaxhighlight>
{{out}}
<pre>$ ol quaternions_task.scm
q = (1 2 3 4)
q1 = (2 3 4 5)
q2 = (3 4 5 6)
r = 7
(quaternion? q) = #true
(quaternion? q1) = #true
(quaternion? q2) = #true
(quaternion? r) = #false
(quaternion-norm q) = 116161/21208
(quaternion-norm q1) = 898285873/122241224
(quaternion-norm q2) = 6216793393/670374072
(quaternion- q) = (-1 -2 -3 -4)
(quaternion- q1 q2) = (-1 -1 -1 -1)
(quaternion- q q1 q2) = (-4 -5 -6 -7)
(quaternion-conjugate q) = (1 -2 -3 -4)
(quaternion+) = (0 0 0 0)
(quaternion+ q) = (1 2 3 4)
(quaternion+ r q) = (8 2 3 4)
(quaternion+ q r) = (8 2 3 4)
(quaternion+ q1 q2) = (5 7 9 11)
(quaternion+ q q1 q2) = (6 9 12 15)
(quaternion*) = (1 0 0 0)
(quaternion* q) = (1 2 3 4)
(quaternion* r q) = (7 14 21 28)
(quaternion* q r) = (7 14 21 28)
(quaternion* q1 q2) = (-56 16 24 26)
(quaternion* q q1 q2) = (-264 -114 -132 -198)
(quaternion=? q) = #true
(quaternion=? q q) = #true
(quaternion=? q1 q2) = #false
(quaternion=? q q q) = #true
(quaternion=? q1 q1 q2) = #false
(quaternion* q1 q2) = (-56 16 24 26)
(quaternion* q2 q1) = (-56 18 20 28)
(quaternion=? (quaternion* q1 q2)
(quaternion* q2 q1)) = #false</pre>
=={{header|ooRexx}}==
Note, this example uses operator overloads to perform the math operation. The operator overloads only work if the left-hand-side of the operation is a quaterion instance. Thus something like "7 + q1" would not work because this would get passed to the "+" of the string class. For those situations, the best solution would be an addition method on the .Quaternion class itself that took the appropriate action. I've chosen not to implement those to keep the example shorter.
<syntaxhighlight lang="oorexx">
q = .quaternion~new(1, 2, 3, 4)
q1 = .quaternion~new(2, 3, 4, 5)
Line 5,104 ⟶ 6,427:
::requires rxmath LIBRARY
</syntaxhighlight>
{{out}}
<pre>
Line 5,126 ⟶ 6,449:
{{works with|PARI/GP|version 2.4.2 and above}}<!-- Needs closures -->
Here is a simple solution in GP. I think it's possible to implement this type directly in Pari by abusing t_COMPLEX, but I haven't attempted this.
<
if(type(q) != "t_VEC" || #q != 4, error("incorrect type"));
sqrt(q[1]^2+q[2]^2+q[3]^2+q[4]^2)
Line 5,160 ⟶ 6,483:
)
)
};</
Usage:
<
q.norm
-q
Line 5,171 ⟶ 6,494:
q.mult(r) \\ or r*q or q*r
q1.mult(q2)
q1.mult(q2) != q2.mult(q1)</
=={{header|Pascal}}==
Line 5,177 ⟶ 6,500:
=={{header|Perl}}==
<
use List::Util 'reduce';
use List::MoreUtils 'pairwise';
Line 5,246 ⟶ 6,569:
print "a conjugate is ", $a->conjugate, "\n";
print "a * b = ", $a * $b, "\n";
print "b * a = ", $b * $a, "\n";</
=={{header|Phix}}==
<!--<syntaxhighlight lang="phix">(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>
<!--</syntaxhighlight>-->
{{out}}
<pre>
q1 = 2+3i+4j+5k
q2 = 3+4i+5j+6k
1. norm(q) = 5.47723
2. negative(q) = -1-2i-3j-4k
3. conjugate(q) = 1-2i-3j-4k
4.a q + 7 = 8+2i+3j+4k
.b 7 + q = 8+2i+3j+4k
5.a q1 + q2 = 5+7i+9j+11k
.b q2 + q1 = 5+7i+9j+11k
6.a q * 49 = 49+98i+147j+196k
.b 49 * q = 49+98i+147j+196k
7.a q1 * q2 = -56+16i+24j+26k
.b q2 * q1 = -56+18i+20j+28k
8.a 4.a === 4.b: true
.b 5.a === 5.b: true
.c 6.a === 6.b: true
.d 7.a === 7.b: false
</pre>
=={{header|Picat}}==
{{trans|Prolog}}
A quaternion is represented as a complex term <code>qx/4</code>.
<syntaxhighlight lang="picat">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.</syntaxhighlight>
{{out}}
<pre>abs(q) is 5.477225575051661
abs(q1) is 7.348469228349535
abs(q2) is 9.273618495495704
negate(q) is qx(-1,-2,-3,-4)
conjugate(q) is qx(1,-2,-3,-4)
q1+q2 is qx(5,7,9,11)
q2+q1 is qx(5,7,9,11)
q*r is qx(7,14,21,28)
r*q is qx(7,14,21,28)
q1*q2 is qx(-56,16,24,26)
q2*q1 is qx(-56,18,20,28)</pre>
=={{header|PicoLisp}}==
<
(def 'quatCopy copy)
Line 5,354 ⟶ 6,774:
(mapcar '((R S) (pack (format R *Scl) S))
Q
'(" + " "i + " "j + " "k") ) )</
Test:
<
Q (1.0 2.0 3.0 4.0)
Q1 (2.0 3.0 4.0 5.0)
Line 5,377 ⟶ 6,797:
(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"))</
{{out}}
<pre>R = 7.000000
Line 5,397 ⟶ 6,817:
=={{header|PL/I}}==
<
qu: Proc Options(main);
/**********************************************************************
Line 5,532 ⟶ 6,952:
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;</syntaxhighlight>
{{out}}
<pre>
Line 5,556 ⟶ 6,986:
=={{header|PowerShell}}==
===Implementation===
<syntaxhighlight lang="powershell">
class Quaternion {
[Double]$w
Line 5,615 ⟶ 7,045:
"`$q1 * `$q2: $([Quaternion]::show([Quaternion]::mul($q1,$q2)))"
"`$q2 * `$q1: $([Quaternion]::show([Quaternion]::mul($q2,$q1)))"
</syntaxhighlight>
<b>Output:</b>
<pre>
Line 5,628 ⟶ 7,058:
</pre>
===Library===
<syntaxhighlight lang="powershell">
function show([System.Numerics.Quaternion]$c) {
function st([Double]$r) {
Line 5,651 ⟶ 7,081:
"`$q1 * `$q2: $(show ([System.Numerics.Quaternion]::Multiply($q1,$q2)))"
"`$q2 * `$q1: $(show ([System.Numerics.Quaternion]::Multiply($q2,$q1)))"
</syntaxhighlight>
<b>Output:</b>
<pre>
Line 5,665 ⟶ 7,095:
=={{header|Prolog}}==
<
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.
Line 5,686 ⟶ 7,116:
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.</
'''Test:'''
<
data(q1, qx(2,3,4,5)).
data(q2, qx(3,4,5,6)).
Line 5,712 ⟶ 7,142:
test :- data(q1, Q1), data(q2, Q2), mul(Q2, Q1, Qx),
writef('q2*q1 is %w\n', [Qx]), fail.
test.</
{{out}}
<pre> ?- test.
Line 5,728 ⟶ 7,158:
=={{header|PureBasic}}==
<
a.f
b.f
Line 5,812 ⟶ 7,242:
EndIf
ProcedureReturn 1 ;true
EndProcedure</
Implementation & test
<
ProcedureReturn "{" + StrF(*x\a, NN) + "," + StrF(*x\b, NN) + "," + StrF(*x\c, NN) + "," + StrF(*x\d, NN) + "}"
EndProcedure
Line 5,842 ⟶ 7,272:
Print(#CRLF$ + #CRLF$ + "Press ENTER to exit"): Input()
CloseConsole()
EndIf</
Result
<pre>Q0 = {1,2,3,4}
Line 5,859 ⟶ 7,289:
=={{header|Python}}==
This example extends Pythons [http://docs.python.org/library/collections.html?highlight=namedtuple#collections.namedtuple namedtuples] to add extra functionality.
<
import math
Line 5,940 ⟶ 7,370:
q1 = Q(2, 3, 4, 5)
q2 = Q(3, 4, 5, 6)
r = 7</
'''Continued shell session'''
Run the above with the -i flag to python on the command line, or run with idle then continue in the shell as follows:
<
Quaternion(real=1.0, i=2.0, j=3.0, k=4.0)
>>> q1
Line 5,999 ⟶ 7,429:
>>> q1 * q1.reciprocal()
Quaternion(real=0.9999999999999999, i=0.0, j=0.0, k=0.0)
>>> </
=={{header|R}}==
Line 6,005 ⟶ 7,435:
Using the quaternions package.
<syntaxhighlight lang="r">
library(quaternions)
Line 6,040 ⟶ 7,470:
## q1*q2 != q2*q1
</syntaxhighlight>
=={{header|Racket}}==
<
(struct quaternion (a b c d)
Line 6,117 ⟶ 7,547:
(multiply q2 q1)
(equal? (multiply q1 q2)
(multiply q2 q1)))</
{{out}}
Line 6,149 ⟶ 7,579:
=={{header|Raku}}==
(formerly Perl 6)
<syntaxhighlight lang="raku"
has Real ( $.r, $.i, $.j, $.k );
Line 6,202 ⟶ 7,632:
say "6) q * r = {$q * $r}";
say "7) q1 * q2 = {$q1 * $q2}";
say "8) q1q2 { $q1 * $q2 eqv $q2 * $q1 ?? '==' !! '!=' } q2q1";</
{{out}}
<pre>1) q norm = 5.47722557505166
Line 6,214 ⟶ 7,644:
=={{header|Red}}==
<syntaxhighlight lang="red">
quaternion: context [
quaternion!: make typeset! [block! hash! vector!]
Line 6,274 ⟶ 7,704:
`equal? quaternion/multiply q1 q2 mold quaternion/multiply q2 q1` =>}
equal? quaternion/multiply q1 q2 quaternion/multiply q2 q1]
</syntaxhighlight>
Output:
Line 6,306 ⟶ 7,736:
=={{header|REXX}}==
The REXX language has no native quaternion support, but subroutines can be easily written.
<
q = 1 2 3 4 ; q1 = 2 3 4 5
r = 7 ; q2 = 3 4 5 6
Line 6,346 ⟶ 7,776:
do j=0 while h>9; m.j=h; h= h % 2 + 1; end /*j*/
do k=j+5 to 0 by -1; numeric digits m.k; g= (g + x/g)* .5; end /*k*/
numeric digits d; return (g/1)i /*make complex if X<0 */</
{{out|output|text= when using the internal default inputs:}}
<pre>
Line 6,362 ⟶ 7,792:
task 8: multiplication q2*q1 ──► -56+18i+20j+28k
</pre>
=={{header|RPL}}==
{{works with|Halcyon Calc|4.2.7}}
By considering quaternions as arrays, negation and addition can be directly achieved by resp. <code>NEG</code> and <code>+</code> instructions. Other operations need specific RPL words:
{| class="wikitable"
! RPL code
! Comment
|-
|
≪ 0 1 4 '''FOR''' q OVER q GET SQ + '''NEXT''' √ SWAP DROP
≫ '<span style="color:blue">QNORM</span>' STO
≪ NEG 1 DUP2 GET NEG PUT ≫ '<span style="color:blue">QCONJ</span>' STO
≪
DUP TYPE 3 == ≪ SWAP ≫ IFT
OVER 1 GET + 1 SWAP PUT
≫ '<span style="color:blue">QRADD</span>' STO
≪
ARRY→ DROP 5 ROLL ARRY→ DROP → a2 b2 c2 d2 a1 b1 c1 d1
≪ 'a1*a2 − b1*b2 − c1*c2 − d1*d2' EVAL
'a1*b2 + b1*a2 + c1*d2 − d1*c2' EVAL
'a1*c2 − b1*d2 + c1*a2 + d1*b2' EVAL
'a1*d2 + b1*c2 − c1*b2 + d1*a2' EVAL
{ 4 } →ARRY
≫ ≫ '<span style="color:blue">QMULT</span>' STO
|
<span style="color:blue">QNORM</span> ''( [ a b c d ] -- √(a²+b²+c²+d²) )''
<span style="color:blue">QCONJ</span> ''( [ a b c d ] -- [ a -b -c -d ] )''
<span style="color:blue">QRADD</span> ''( [ a b c d ] r -- [ a+r b c d ] )''
switch arguments if quaternion is at stack level 1
replace a by a+r
<span style="color:blue">QMULT</span> ''( [Q1] [Q2] -- [Q1 x Q2] )''
put the 2 quaternions in local variables
do the math in stack
convert stack to a quaternion
|}
[1 2 3 4] <span style="color:blue">QNORM</span>
[1 2 3 4] NEG
[1 2 3 4] <span style="color:blue">QCONJ</span>
[1 2 3 4] 7 <span style="color:blue">QRADD</span>
[2 3 4 5] [3 4 5 6] +
[1 2 3 4] 7 *
[2 3 4 5] [3 4 5 6] <span style="color:blue">QMULT</span>
[3 4 5 6] [2 3 4 5] <span style="color:blue">QMULT</span>
{{out}}
<pre>
8: 5.47722557505
7: [ -1 -2 -3 -4 ]
6: [ 1 -2 -3 -4 ]
5: [ 8 2 3 4 ]
4: [ 5 7 9 11 ]
3: [ 7 14 21 28 ]
2: [ -56 16 24 26 ]
1: [ -56 18 20 28 ]
</pre>
=== Quaternion multiplication through Cayley-Dickson construction===
This is a shorter and faster version of the <code>QMULT</code> word. {{trans|Ruby}}
{| class="wikitable"
! RPL code
! Comment
|-
|
≪
ARRY→ DROP R→C ROT ROT R→C ROT
ARRY→ DROP R→C ROT ROT R→C → d c b a
≪ a c * d CONJ b * - C→R
d a * b c CONJ * + C→R
{ 4 } →ARRY
≫ ≫ '<span style="color:blue">QMULT</span>' STO
|
<span style="color:blue">QMULT</span> ''( [Q1] [Q2] -- [Q1 x Q2] )''
convert the 2 quaternions into 2 pairs of complex numbers
and store them locally
(a,b)(c,d) = (ac - conj(d).b, // (a,b) and (c,d) are pairs
da + b.conj(c)) // of complex numbers
convert stack to a quaternion
|}
Output is the same.
===Using the matrix form===
This efficient implementation is based on an article of [https://edspi31415.blogspot.com/2015/06/hp-prime-and-hp-50g-quaternions.html?fbclid=IwAR1KTjHt4xVt2FoMqL-82MJ1SS3SBg8jNoF-8uNcqg2Y5bLD2oiyxVfO88Y Eddie's Math and Calculator Blog].
« ARRY→ DROP → a b c d
« a b R→C c d R→C
c NEG d R→C
3 PICK CONJ
{ 2 2 } →ARRY
» » '<span style="color:blue">→QTM</span>' STO <span style="color:grey">''@ ( [ a b c d ] → [[ a+bi c+di ][ -c+di a-bi ]] )''</span>
« DUP 1 GET RE LASTARG IM
ROT 2 GET RE LASTARG IM
{ 4 } →ARRY
» '<span style="color:blue">QTM→</span>' STO <span style="color:grey">''@ ( [[ a+bi c+di ][ -c+di a-bi ]] → [ a b c d ] )''</span>
« <span style="color:blue">→QTM</span> SWAP <span style="color:blue">QTM→</span> SWAP * <span style="color:blue">QTM→</span>
» '<span style="color:blue">QMULT</span>' STO <span style="color:grey">''@ ( q1 q2 → q1*q2 ) ''</span>
« <span style="color:blue">→QTM</span> DET √ ABS
» '<span style="color:blue">QNORM</span>' STO <span style="color:grey">''@ ( q → qnorm(q) ) ''</span>
« DUP INV SWAP <span style="color:blue">QNORM</span> SQ *
» '<span style="color:blue">QCONJ</span>' STO <span style="color:grey">''@ ( q → conj(q) ) ''</span>
Quaternions' matrix form allows to quickly develop additional operations:
« DUP <span style="color:blue">QNORM</span> /
» '<span style="color:blue">QSIGN</span>' STO <span style="color:grey">''@ ( q → q/norm(q) ) ''</span>
« <span style="color:blue">→QTM</span> INV <span style="color:blue">QTM→</span>
» '<span style="color:blue">QINV</span>' STO <span style="color:grey">''@ ( q → q^(-1) ) ''</span>
« <span style="color:blue">QINV QMULT</span>
» '<span style="color:blue">QDIV</span>' STO <span style="color:grey">''@ ( q1 q2 → q1/q2 )''</span>
=={{header|Ruby}}==
{{works with|Ruby|1.9}}
<
def initialize(*parts)
raise ArgumentError, "wrong number of arguments (#{parts.size} for 4)" unless parts.size == 4
Line 6,442 ⟶ 7,998:
puts "%20s = %s" % [exp, eval(exp)]
end
end</
{{out}}
<pre>
Line 6,466 ⟶ 8,022:
=={{header|Rust}}==
<
use std::ops::{Add, Mul, Neg};
Line 6,638 ⟶ 8,194:
println!();
println!("normal of q0 = {}", q0.norm());
}</
{{out}}
<pre>
Line 6,671 ⟶ 8,227:
=={{header|Scala}}==
<
lazy val im = (i, j, k)
private lazy val norm2 = re*re + i*i + j*j + k*k
Line 6,701 ⟶ 8,257:
implicit def number2Quaternion[T:Numeric](n: T) = Quaternion(n.toDouble)
}</
Demonstration:
<
val q1=Quaternion(2.0, 3.0, 4.0, 5.0);
val q2=Quaternion(3.0, 4.0, 5.0, 6.0);
Line 6,737 ⟶ 8,293:
println("q2/q1 = "+ q2/q1)
println("q1/r = "+ q1/r)
println("r/q1 = "+ r/q1)</
{{out}}
<pre>q0 = Q(1.00, 2.00i, 3.00j, 4.00k)
Line 6,768 ⟶ 8,324:
q1/r = Q(0.29, 0.43i, 0.57j, 0.71k)
r/q1 = Q(0.26, -0.39i, -0.52j, -0.65k)</pre>
=={{header|Scheme}}==
For the source code, see [[#Ol|the entry for Otus Lisp]]. However, with most Scheme implementations the output will look different:
{{out}}
<pre>$ ypsilon quaternions_task.scm
q = (1 2 3 4)
q1 = (2 3 4 5)
q2 = (3 4 5 6)
r = 7
(quaternion? q) = #t
(quaternion? q1) = #t
(quaternion? q2) = #t
(quaternion? r) = #f
(quaternion-norm q) = 5.477225575051661
(quaternion-norm q1) = 7.3484692283495345
(quaternion-norm q2) = 9.273618495495704
(quaternion- q) = (-1 -2 -3 -4)
(quaternion- q1 q2) = (-1 -1 -1 -1)
(quaternion- q q1 q2) = (-4 -5 -6 -7)
(quaternion-conjugate q) = (1 -2 -3 -4)
(quaternion+) = (0 0 0 0)
(quaternion+ q) = (1 2 3 4)
(quaternion+ r q) = (8 2 3 4)
(quaternion+ q r) = (8 2 3 4)
(quaternion+ q1 q2) = (5 7 9 11)
(quaternion+ q q1 q2) = (6 9 12 15)
(quaternion*) = (1 0 0 0)
(quaternion* q) = (1 2 3 4)
(quaternion* r q) = (7 14 21 28)
(quaternion* q r) = (7 14 21 28)
(quaternion* q1 q2) = (-56 16 24 26)
(quaternion* q q1 q2) = (-264 -114 -132 -198)
(quaternion=? q) = #t
(quaternion=? q q) = #t
(quaternion=? q1 q2) = #f
(quaternion=? q q q) = #t
(quaternion=? q1 q1 q2) = #f
(quaternion* q1 q2) = (-56 16 24 26)
(quaternion* q2 q1) = (-56 18 20 28)
(quaternion=? (quaternion* q1 q2)
(quaternion* q2 q1)) = #f</pre>
=={{header|Seed7}}==
<syntaxhighlight lang="seed7">$ 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;</syntaxhighlight>
{{out}}
<pre>
q = 1.0+2.0i+3.0j+4.0k
q1 = 2.0+3.0i+4.0j+5.0k
q2 = 3.0+4.0i+5.0j+6.0k
r = 7.0
norm(q) = 5.47722557505166
-q = -1.0-2.0i-3.0j-4.0k
conjugate(q) = 1.0-2.0i-3.0j-4.0k
q + r = 8.0+2.0i+3.0j+4.0k
r + q = 8.0+2.0i+3.0j+4.0k
q1 + q2 = 5.0+7.0i+9.0j+11.0k
q2 + q1 = 5.0+7.0i+9.0j+11.0k
q * r = 7.0+14.0i+21.0j+28.0k
r * q = 7.0+14.0i+21.0j+28.0k
q1 * q2 = -56.0+16.0i+24.0j+26.0k
q2 * q1 = -56.0+18.0i+20.0j+28.0k
</pre>
=={{header|Sidef}}==
{{trans|Raku}}
<
func qu(*r) { Quaternion(r...) }
Line 6,809 ⟶ 8,613:
say "6) q * r = #{q * r}"
say "7) q1 * q2 = #{q1 * q2}"
say "8) q1q2 #{ q1*q2 == q2*q1 ? '==' : '!=' } q2q1"</
{{out}}
<pre>
Line 6,823 ⟶ 8,627:
=={{header|Swift}}==
<
struct Quaternion {
Line 6,956 ⟶ 8,760:
q₂q₁ = \(q2 * q1)
q₁q₂ ≠ q₂q₁ is \(q1*q2 != q2*q1)
""")</
{{out}}
Line 6,977 ⟶ 8,781:
=={{header|Tcl}}==
{{works with|Tcl|8.6}} or {{libheader|TclOO}}
<
# Support class that provides C++-like RAII lifetimes
Line 7,075 ⟶ 8,879:
export - + * ==
}</
Demonstration code:
<
set q1 [Q new 2 3 4 5]
set q2 [Q new 3 4 5 6]
Line 7,098 ⟶ 8,902:
puts "q1 * q2 = [[$q1 * $q2] p]"
puts "q2 * q1 = [[$q2 * $q1] p]"
puts "equal(q1*q2, q2*q1) = [[$q1 * $q2] == [$q2 * $q1]]"</
{{out}}
<pre>
Line 7,120 ⟶ 8,924:
=={{header|VBA}}==
<
Private Function norm(q As Variant) As Double
norm = Sqr(WorksheetFunction.SumSq(q))
Line 7,190 ⟶ 8,994:
Debug.Print "q1 * q2 = ";: quats mult(q1, q2)
Debug.Print "q2 * q1 = ";: quats mult(q2, q1)
End Sub</
<pre>q = 1 + 2i + 3j + 4k
q1 = 2 + 3i + 4j + 5k
Line 7,209 ⟶ 9,013:
{{works with|.NET Core|2.1}}
<
Option Explicit On
Option Infer On
Line 7,304 ⟶ 9,108:
End Operator
#End Region
End Structure</
Demonstration:
<
Sub Main()
Dim q As New Quaternion(1, 2, 3, 4),
Line 7,331 ⟶ 9,135:
Console.WriteLine($"q1*q2 {If((q1 * q2) = (q2 * q1), "=", "!=")} q2*q1")
End Sub
End Module</
{{out}}
Line 7,350 ⟶ 9,154:
q2 * q1 = Q(-56, 18, 20, 28)
q1*q2 != q2*q1</pre>
=={{header|Wren}}==
<syntaxhighlight lang="wren">class Quaternion {
construct new(a, b, c, d ) {
_a = a
_b = b
_c = c
_d = d
}
a { _a }
b { _b }
c { _c }
d { _d }
norm { (a*a + b*b + c*c + d*d).sqrt }
- { Quaternion.new(-a, -b, -c, -d) }
conj { Quaternion.new(a, -b, -c, -d) }
+ (q) {
if (q is Num) return Quaternion.new(a + q, b, c, d)
return Quaternion.new(a + q.a, b + q.b, c + q.c, d + q.d)
}
* (q) {
if (q is Num) return Quaternion.new(a * q, b * q, c * q, d * q)
return 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)
}
== (q) { a == q.a && b == q.b && c == q.c && d == q.d }
!= (q) { !(this == q) }
toString { "(%(a), %(b), %(c), %(d))" }
static realAdd(r, q) { q + r }
static realMul(r, q) { q * r }
}
var q = Quaternion.new(1, 2, 3, 4)
var q1 = Quaternion.new(2, 3, 4, 5)
var q2 = Quaternion.new(3, 4, 5, 6)
var q3 = q1 * q2
var q4 = q2 * q1
var r = 7
System.print("q = %(q)")
System.print("q1 = %(q1)")
System.print("q2 = %(q2)")
System.print("r = %(r)")
System.print("norm(q) = %(q.norm)")
System.print("-q = %(-q)")
System.print("conj(q) = %(q.conj)")
System.print("r + q = %(Quaternion.realAdd(r, q))")
System.print("q + r = %(q + r))")
System.print("q1 + q2 = %(q1 + q2)")
System.print("q2 + q1 = %(q2 + q1)")
System.print("rq = %(Quaternion.realMul(r, q))")
System.print("qr = %(q * r)")
System.print("q1q2 = %(q3)")
System.print("q2q1 = %(q4)")
System.print("q1q2 ≠ q2q1 = %(q3 != q4)")</syntaxhighlight>
{{out}}
<pre>
q = (1, 2, 3, 4)
q1 = (2, 3, 4, 5)
q2 = (3, 4, 5, 6)
r = 7
norm(q) = 5.4772255750517
-q = (-1, -2, -3, -4)
conj(q) = (1, -2, -3, -4)
r + q = (8, 2, 3, 4)
q + r = (8, 2, 3, 4))
q1 + q2 = (5, 7, 9, 11)
q2 + q1 = (5, 7, 9, 11)
rq = (7, 14, 21, 28)
qr = (7, 14, 21, 28)
q1q2 = (-56, 16, 24, 26)
q2q1 = (-56, 18, 20, 28)
q1q2 ≠ q2q1 = true
</pre>
=={{header|XPL0}}==
<syntaxhighlight lang="xpl0">proc QPrint(Q); \Display quaternion
real Q;
[RlOut(0, Q(0)); Text(0, " + "); RlOut(0, Q(1)); Text(0, "i + ");
RlOut(0, Q(2)); Text(0, "j + "); RlOut(0, Q(3)); Text(0, "k");
CrLf(0);
];
func real QNorm(Q); \Return norm of a quaternion
real Q;
return sqrt( Q(0)*Q(0) + Q(1)*Q(1) + Q(2)*Q(2) + Q(3)*Q(3) );
func real QNeg(Q, R); \Return negative of a quaternion: Q:= -R
real Q, R;
[Q(0):= -R(0); Q(1):= -R(1); Q(2):= -R(2); Q(3):= -R(3);
return Q;
];
func real QConj(Q, R); \Return conjugate of a quaternion: Q:= conj R
real Q, R;
[Q(0):= R(0); Q(1):= -R(1); Q(2):= -R(2); Q(3):= -R(3);
return Q;
];
func real QRAdd(Q, R, Real); \Return quaternion plus real: Q:= R + Real
real Q, R, Real;
[Q(0):= R(0) + Real; Q(1):= R(1); Q(2):= R(2); Q(3):= R(3);
return Q;
];
func real QAdd(Q, R, S); \Return quaternion sum: Q:= R + S
real Q, R, S;
[Q(0):= R(0) + S(0); Q(1):= R(1) + S(1); Q(2):= R(2) + S(2); Q(3):= R(3) + S(3);
return Q;
];
func real QRMul(Q, R, Real); \Return quaternion times real: Q:= R + Real
real Q, R, Real;
[Q(0):= R(0) * Real; Q(1):= R(1) * Real; Q(2):= R(2) * Real; Q(3):= R(3) * Real;
return Q;
];
func real QMul(Q, R, S); \Return quaternion product: Q:= R * S
real Q, R, S;
[Q(0):= R(0)*S(0) - R(1)*S(1) - R(2)*S(2) - R(3)*S(3);
Q(1):= R(0)*S(1) + R(1)*S(0) + R(2)*S(3) - R(3)*S(2);
Q(2):= R(0)*S(2) - R(1)*S(3) + R(2)*S(0) + R(3)*S(1);
Q(3):= R(0)*S(3) + R(1)*S(2) - R(2)*S(1) + R(3)*S(0);
return Q;
];
real Q, Q1, Q2, R, Q0(4),;
[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;
Format(3, 1);
Text(0, "q = "); QPrint(Q);
Text(0, "q1 = "); QPrint(Q1);
Text(0, "q2 = "); QPrint(Q2);
Text(0, "norm(q) = "); RlOut(0, QNorm(Q)); CrLf(0);
Text(0, "-q = "); QPrint(QNeg(Q0, Q));
Text(0, "conj(q) = "); QPrint(QConj(Q0, Q));
Text(0, "r + q = "); QPrint(QRAdd(Q0, Q, R));
Text(0, "q1 + q2 = "); QPrint(QAdd (Q0, Q1, Q2));
Text(0, "r * q = "); QPrint(QRMul(Q0, Q, R));
Text(0, "q1 * q2 = "); QPrint(QMul (Q0, Q1, Q2));
Text(0, "q2 * q1 = "); QPrint(QMul (Q0, Q2, Q1));
]</syntaxhighlight>
{{out}}
<pre>
q = 1.0 + 2.0i + 3.0j + 4.0k
q1 = 2.0 + 3.0i + 4.0j + 5.0k
q2 = 3.0 + 4.0i + 5.0j + 6.0k
norm(q) = 5.5
-q = -1.0 + -2.0i + -3.0j + -4.0k
conj(q) = 1.0 + -2.0i + -3.0j + -4.0k
r + q = 8.0 + 2.0i + 3.0j + 4.0k
q1 + q2 = 5.0 + 7.0i + 9.0j + 11.0k
r * q = 7.0 + 14.0i + 21.0j + 28.0k
q1 * q2 = -56.0 + 16.0i + 24.0j + 26.0k
q2 * q1 = -56.0 + 18.0i + 20.0j + 28.0k
</pre>
=={{header|zkl}}==
{{trans|D}}
<
fcn init(real=0,i1=0,i2=0,i3=0){
var [const] vector= // Quat(r,i,j,k) or Quat( (r,i,j,k) )
Line 7,405 ⟶ 9,375:
(iversor*inorm.sin() + inorm.cos()) * r.exp();
}
}</
<
r:=7;
q:=Quat(2,3,4,5); q1:=Quat(2,3,4,5); q2:=Quat(3,4,5,6);
Line 7,444 ⟶ 9,414:
println(" s.log(): ", s.log());
println(" s.log().exp(): ", s.log().exp());
println(" s.exp().log(): ", s.exp().log());</
{{out}}
<pre>
|