Time for an 2014 update…

This commit is contained in:
Ingy döt Net 2014-01-17 05:32:22 +00:00
parent 372c577f83
commit 09687c4926
2520 changed files with 34227 additions and 7318 deletions

View file

@ -2,8 +2,9 @@
A complex number has a real and complex part written sometimes as <code>a + bi</code>, 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 <code>-3 + 2i</code>, 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 <code>a + bi + cj + dk</code>. In this numbering system, <code>ii = jj = kk = ijk = -1</code>. The order of multiplication is important, as, in general, for two quaternions q<sub>1</sub> and q<sub>2</sub>; <code>q<sub>1</sub>q<sub>2</sub> != q<sub>2</sub>q<sub>1</sub></code>. An example of a quaternion might be <code>1 +2i +3j +4k</code>
A quaternion has one real part and ''three'' imaginary parts, i, j, and k. A quaternion might be written as <code>a + bi + cj + dk</code>. In this numbering system, <code>ii = jj = kk = ijk = -1</code>. The order of multiplication is important, as, in general, for two quaternions q<sub>1</sub> and q<sub>2</sub>; <code>q<sub>1</sub>q<sub>2</sub> != q<sub>2</sub>q<sub>1</sub></code>.
An example of a quaternion might be <code>1 +2i +3j +4k</code><br>
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'''<br>

View file

@ -9,10 +9,23 @@ b := BasisVectors(Basis(A));
q := [1, 2, 3, 4]*b;
# e+(2)*i+(3)*j+(4)*k
# Computing norm may be difficult, since the result would be in a quadratic field (Sqrt exists in GAP, is quite unusual, see ?E in GAP, and the following example
# Conjugate
ComplexConjugate(q);
# e+(-2)*i+(-3)*j+(-4)*k
# Division
1/q;
# (1/30)*e+(-1/15)*i+(-1/10)*j+(-2/15)*k
# Computing norm may be difficult, since the result would be in a quadratic field.
# Sqrt exists in GAP, but it is quite unusual: see ?E in GAP documentation, and the following example
Sqrt(5/3);
# 1/3*E(60)^7+1/3*E(60)^11-1/3*E(60)^19-1/3*E(60)^23-1/3*E(60)^31+1/3*E(60)^43-1/3*E(60)^47+1/3*E(60)^59
# However, the square of the norm is easy to compute
q*ComplexConjugate(q);
# (30)*e
q1 := [2, 3, 4, 5]*b;
# (2)*e+(3)*i+(4)*j+(5)*k
@ -23,17 +36,75 @@ q1*q2 - q2*q1;
# (-2)*i+(4)*j+(-2)*k
# Can't add directly to a rational, one must make a quaternion of it
r:=5/3*b[1];
r := 5/3*b[1];
# (5/3)*e
r + q;
# (8/3)*e+(2)*i+(3)*j+(4)*k
# For multiplication, no problem (we are in an algebra over rationals !)
r * q;
r*q;
# (5/3)*e+(10/3)*i+(5)*j+(20/3)*k
5/3 * q;
5/3*q;
# (5/3)*e+(10/3)*i+(5)*j+(20/3)*k
# Negative
-q;
(-1)*e+(-2)*i+(-3)*j+(-4)*k
# While quaternions are built-in, you can define an algebra in GAP by specifying it's multiplication table.
# See tutorial, p. 60, and reference of the functions used below.
# A multiplication table of dimension 4.
T := EmptySCTable(4, 0);
SetEntrySCTable(T, 1, 1, [1, 1]);
SetEntrySCTable(T, 1, 2, [1, 2]);
SetEntrySCTable(T, 1, 3, [1, 3]);
SetEntrySCTable(T, 1, 4, [1, 4]);
SetEntrySCTable(T, 2, 1, [1, 2]);
SetEntrySCTable(T, 2, 2, [-1, 1]);
SetEntrySCTable(T, 2, 3, [1, 4]);
SetEntrySCTable(T, 2, 4, [-1, 3]);
SetEntrySCTable(T, 3, 1, [1, 3]);
SetEntrySCTable(T, 3, 2, [-1, 4]);
SetEntrySCTable(T, 3, 3, [-1, 1]);
SetEntrySCTable(T, 3, 4, [1, 2]);
SetEntrySCTable(T, 4, 1, [1, 4]);
SetEntrySCTable(T, 4, 2, [1, 3]);
SetEntrySCTable(T, 4, 3, [-1, 2]);
SetEntrySCTable(T, 4, 4, [-1, 1]);
A := AlgebraByStructureConstants(Rationals, T, ["e", "i", "j", "k"]);
b := GeneratorsOfAlgebra(A);
IsAssociative(A);
# true
IsCommutative(A);
# false
# Then, like above
q := [1, 2, 3, 4]*b;
# e+(2)*i+(3)*j+(4)*k
# However, as is, GAP does not know division or conjugate on this algebra.
# QuaternionAlgebra is useful as well for extensions of rationals,
# and this one _has_ conjugate and division, as seen previously.
# Try this on Q[z] where z is the square root of 5 (in GAP it's ER(5))
F := FieldByGenerators([ER(5)]);
A := QuaternionAlgebra(F);
b := GeneratorsOfAlgebra(A);
q := [1, 2, 3, 4]*b;
# e+(2)*i+(3)*j+(4)*k
# Conjugate and division
ComplexConjugate(q);
# e+(-2)*i+(-3)*j+(-4)*k
1/q;
# (1/30)*e+(-1/15)*i+(-1/10)*j+(-2/15)*k

View file

@ -0,0 +1,48 @@
import Base: convert, promote_rule, show, real, imag, conj, abs, abs2, inv, +, -, /, *
immutable Quaternion{T<:Real} <: Number
q0::T
q1::T
q2::T
q3::T
end
Quaternion(q0::Real,q1::Real,q2::Real,q3::Real) = Quaternion(promote(q0,q1,q2,q3)...)
convert{T}(::Type{Quaternion{T}}, x::Real) =
Quaternion(convert(T,x), zero(T), zero(T), zero(T))
convert{T}(::Type{Quaternion{T}}, z::Complex) =
Quaternion(convert(T,real(z)), convert(T,imag(z)), zero(T), zero(T))
convert{T}(::Type{Quaternion{T}}, z::Quaternion) =
Quaternion(convert(T,z.q0), convert(T,z.q1), convert(T,z.q2), convert(T,z.q3))
promote_rule{T,S}(::Type{Complex{T}}, ::Type{Quaternion{S}}) = Quaternion{promote_type(T,S)}
promote_rule{T<:Real,S}(::Type{T}, ::Type{Quaternion{S}}) = Quaternion{promote_type(T,S)}
promote_rule{T,S}(::Type{Quaternion{T}}, ::Type{Quaternion{S}}) = Quaternion{promote_type(T,S)}
function show(io::IO, z::Quaternion)
pm(x) = x < 0 ? " - $(-x)" : " + $x"
print(io, z.q0, pm(z.q1), "i", pm(z.q2), "j", pm(z.q3), "k")
end
real(z::Quaternion) = z.q0
imag(z::Quaternion) = z.q1
conj(z::Quaternion) = Quaternion(z.q0, -z.q1, -z.q2, -z.q3)
abs(z::Quaternion) = sqrt(z.q0*z.q0 + z.q1*z.q1 + z.q2*z.q2 + z.q3*z.q3)
abs2(z::Quaternion) = z.q0*z.q0 + z.q1*z.q1 + z.q2*z.q2 + z.q3*z.q3
inv(z::Quaternion) = conj(z)/abs2(z)
(-)(z::Quaternion) = Quaternion(-z.q0, -z.q1, -z.q2, -z.q3)
(/)(z::Quaternion, x::Real) = Quaternion(z.q0/x, z.q1/x, z.q2/x, z.q3/x)
(+)(z::Quaternion, w::Quaternion) = Quaternion(z.q0 + w.q0, z.q1 + w.q1,
z.q2 + w.q2, z.q3 + w.q3)
(-)(z::Quaternion, w::Quaternion) = Quaternion(z.q0 - w.q0, z.q1 - w.q1,
z.q2 - w.q2, z.q3 - w.q3)
(*)(z::Quaternion, w::Quaternion) = Quaternion(z.q0*w.q0 - z.q1*w.q1 - z.q2*w.q2 - z.q3*w.q3,
z.q0*w.q1 + z.q1*w.q0 + z.q2*w.q3 - z.q3*w.q2,
z.q0*w.q2 - z.q1*w.q3 + z.q2*w.q0 + z.q3*w.q1,
z.q0*w.q3 + z.q1*w.q2 - z.q2*w.q1 + z.q3*w.q0)
(/)(z::Quaternion, w::Quaternion) = z*inv(w)

View file

@ -0,0 +1,26 @@
julia> q = Quaternion(1,0,0,0)
julia> q = Quaternion (1, 2, 3, 4)
q1 = Quaternion(2, 3, 4, 5)
q2 = Quaternion(3, 4, 5, 6)
r = 7.
julia> norm(q)
5.477225575051661
julia> -q
-1 - 2i - 3j - 4k
julia> conj(q)
1 - 2i - 3j - 4k
julia> r + q, q + r
(8.0 + 2.0i + 3.0j + 4.0k,8.0 + 2.0i + 3.0j + 4.0k)
julia> q1 + q2
5 + 7i + 9j + 11k
julia> r*q, q*r
(7.0 + 14.0i + 21.0j + 28.0k,7.0 + 14.0i + 21.0j + 28.0k)
julia> q1*q2, q2*q1, q1*q2 != q2*q1
(-56 + 16i + 24j + 26k,-56 + 18i + 20j + 28k,true)

View file

@ -1,34 +1,47 @@
class Qu {
class Quaternion {
has Real ( $.r, $.i, $.j, $.k );
multi method new ( Real $r, Real $i, Real $j, Real $k ) {
self.bless: *, :$r, :$i, :$j, :$k;
self.bless: :$r, :$i, :$j, :$k;
}
method Str ( ) { "$.r + {$.i}i + {$.j}j + {$.k}k" }
method reals ( ) { $.r, $.i, $.j, $.k }
method conj ( ) { self.new: $.r, -$.i, -$.j, -$.k }
method norm ( ) { sqrt [+] self.reals X** 2 }
}
multi qu(*@r) is export { Quaternion.new: |@r }
sub postfix:<j>(Real $x) is export { qu 0, 0, $x, 0 }
sub postfix:<k>(Real $x) is export { qu 0, 0, 0, $x }
multi sub infix:<eqv> ( Qu $a, Qu $b ) { [and] $a.reals Z== $b.reals }
multi sub infix:<+> ( Qu $a, Real $b ) { $a.new: $b+$a.r, $a.i, $a.j, $a.k }
multi sub infix:<+> ( Real $a, Qu $b ) { $b.new: $a+$b.r, $b.i, $b.j, $b.k }
multi sub infix:<+> ( Qu $a, Qu $b ) { $a.new: |( $a.reals Z+ $b.reals ) }
multi sub prefix:<-> ( Qu $a ) { $a.new: |( $a.reals X* -1 ) }
multi sub infix:<*> ( Qu $a, Real $b ) { $a.new: |( $a.reals X* $b ) }
multi sub infix:<*> ( Real $a, Qu $b ) { $b.new: |( $b.reals X* $a ) }
multi sub infix:<*> ( Qu $a, Qu $b ) {
my @a_rijk = $a.reals;
my ( $r, $i, $j, $k ) = $b.reals;
return $a.new: ( [+] @a_rijk Z* $r, -$i, -$j, -$k ), # real
( [+] @a_rijk Z* $i, $r, $k, -$j ), # i
( [+] @a_rijk Z* $j, -$k, $r, $i ), # j
( [+] @a_rijk Z* $k, $j, -$i, $r ); # k
}
method Str () { "$.r + {$.i}i + {$.j}j + {$.k}k" }
method reals () { $.r, $.i, $.j, $.k }
method conj () { qu $.r, -$.i, -$.j, -$.k }
method norm () { sqrt [+] self.reals X** 2 }
my Qu $q .= new: 1, 2, 3, 4;
my Qu $q1 .= new: 2, 3, 4, 5;
my Qu $q2 .= new: 3, 4, 5, 6;
multi infix:<eqv> ( Quaternion $a, Quaternion $b ) is export { $a.reals eqv $b.reals }
multi infix:<+> ( Quaternion $a, Real $b ) is export { qu $b+$a.r, $a.i, $a.j, $a.k }
multi infix:<+> ( Real $a, Quaternion $b ) is export { qu $a+$b.r, $b.i, $b.j, $b.k }
multi infix:<+> ( Quaternion $a, Complex $b ) is export { qu $b.re + $a.r, $b.im + $a.i, $a.j, $a.k }
multi infix:<+> ( Complex $a, Quaternion $b ) is export { qu $a.re + $b.r, $a.im + $b.i, $b.j, $b.k }
multi infix:<+> ( Quaternion $a, Quaternion $b ) is export { qu $a.reals Z+ $b.reals }
multi prefix:<-> ( Quaternion $a ) is export { qu $a.reals X* -1 }
multi infix:<*> ( Quaternion $a, Real $b ) is export { qu $a.reals X* $b }
multi infix:<*> ( Real $a, Quaternion $b ) is export { qu $b.reals X* $a }
multi infix:<*> ( Quaternion $a, Complex $b ) is export { $a * qu $b.reals, 0, 0 }
multi infix:<*> ( Complex $a, Quaternion $b ) is export { $b R* qu $a.reals, 0, 0 }
multi infix:<*> ( Quaternion $a, Quaternion $b ) is export {
my @a_rijk = $a.reals;
my ( $r, $i, $j, $k ) = $b.reals;
return qu [+]( @a_rijk Z* $r, -$i, -$j, -$k ), # real
[+]( @a_rijk Z* $i, $r, $k, -$j ), # i
[+]( @a_rijk Z* $j, -$k, $r, $i ), # j
[+]( @a_rijk Z* $k, $j, -$i, $r ); # k
}
}
import Quaternion;
my $q = 1 + 2i + 3j + 4k;
my $q1 = 2 + 3i + 4j + 5k;
my $q2 = 3 + 4i + 5j + 6k;
my $r = 7;
say "1) q norm = {$q.norm}";