/*
Quaternion type (Rosetta code) in Picat.
http://rosettacode.org/wiki/Quaternion_type
"""
Quaternion type
Quaternions are an extension of the idea of complex numbers.
A complex number has a real and complex part written sometimes as a + bi,
where a and b stand for real numbers and i stands for the square root of minus 1.
An example of a complex number might be -3 + 2i, where the real part, a is -3.0
and the complex part, b is +2.0.
A quaternion has one real part and three imaginary parts, i, j, and k. A quaternion
might be written as a + bi + cj + dk. In this numbering system, ii = jj = kk = ijk = -1.
The order of multiplication is important, as, in general, for two quaternions
q1 and q2; q1q2 != q2q1.
An example of a quaternion might be 1 +2i +3j +4k
There is a list form of notation where just the numbers are shown and the imaginary
multipliers i, j, and k are assumed by position. So the example above would be written as (1, 2, 3, 4)
Task Description
Given the three quaternions and their components:
q = (1, 2, 3, 4) = (a, b, c, d )
q1 = (2, 3, 4, 5) = (a1, b1, c1, d1)
q2 = (3, 4, 5, 6) = (a2, b2, c2, d2)
And a wholly real number r = 7.
Your task is to create functions or classes to perform simple maths with quaternions including computing:
The norm of a quaternion:
= sqrt{a^2 + b^2 + c^2 + d^2}
The negative of a quaternion:
=(-a, -b, -c, -d)
The conjugate of a quaternion:
=( a, -b, -c, -d)
Addition of a real number r and a quaternion q:
r + q = q + r = (a+r, b, c, d)
Addition of two quaternions:
q1 + q2 = (a1+a2, b1+b2, c1+c2, d1+d2)
Multiplication of a real number and a quaternion:
qr = rq = (ar, br, cr, dr)
Multiplication of two quaternions q1 and q2 is given by:
( a1a2 − b1b2 − c1c2 − d1d2,
a1b2 + b1a2 + c1d2 − d1c2,
a1c2 − b1d2 + c1a2 + d1b2,
a1d2 + b1c2 − c1b2 + d1a2 )
Show that, for the two quaternions q1 and q2:
q1q2 != q2q1
If your language has built-in support for quaternions then use it.
"""
This Picat model was created by Hakan Kjellerstrand, hakank@gmail.com
See also my Picat page: http://www.hakank.org/picat/
*/
% import util.
% import cp.
main => go.
go =>
test,
nl.
%
% From the Prolog solutions
%
index(-,-)
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 => true.
add(qx(R0,I0,J0,K0),qx(R1,I1,J1,K1),Q3) =>
Q3=$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(R0,I,J,K)) =>
add(QT, F, Qx).
mul(qx(R0,I0,J0,K0),qx(R1,I1,J1,K1),Q3) ?=>
Q3=$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(Q1,F,Q2) ?=>
number(F),
Q1=$qx(R0,I0,J0,K0),
Q2=$qx(R,I,J,K),
R is R0*F, I is I0*F, J is J0*F, K is K0*F.
mul(F, qx(R0,I0,J0,K0), Qx) =>
number(F),
QT=$qx(R0,I0,J0,K0),
mul(QT,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),Q2) =>
Q2=$qx(R,I,J,K),
R is -Ri, I is -Ii, J is -Ji, K is -Ki.
conjugate(qx(R,Ii,Ji,Ki),Q2) =>
Q2=$qx(R,I,J,K),
I is -Ii, J is -Ji, K is -Ki.