Quaternion type: Difference between revisions
Content deleted Content added
m formatting |
→Tcl: Added implementation |
||
Line 144: | Line 144: | ||
Quaternion(real=-1.0, i=0.0, j=0.0, k=0.0) |
Quaternion(real=-1.0, i=0.0, j=0.0, k=0.0) |
||
>>> </lang> |
>>> </lang> |
||
=={{header|Tcl}}== |
|||
<lang tcl># Support class that provides C++-like RAII lifetimes |
|||
oo::class create RAII-support { |
|||
constructor {} { |
|||
upvar 1 { end } end |
|||
lappend end [self] |
|||
trace add variable end unset [namespace code {my destroy}] |
|||
} |
|||
destructor { |
|||
catch { |
|||
upvar 1 { end } end |
|||
trace remove variable end unset [namespace code {my destroy}] |
|||
} |
|||
} |
|||
method return {{level 1}} { |
|||
incr level |
|||
upvar 1 { end } end |
|||
upvar $level { end } parent |
|||
trace remove variable end unset [namespace code {my destroy}] |
|||
lappend parent [self] |
|||
trace add variable parent unset [namespace code {my destroy}] |
|||
return -level $level [self] |
|||
} |
|||
} |
|||
# Class of quaternions |
|||
oo::class create Q { |
|||
superclass RAII-support |
|||
variable R I J K |
|||
constructor {{real 0} {i 0} {j 0} {k 0}} { |
|||
next |
|||
namespace import ::tcl::mathfunc::* ::tcl::mathop::* |
|||
variable R [double $real] I [double $i] J [double $j] K [double $k] |
|||
} |
|||
self method return args { |
|||
[my new {*}$args] return 2 |
|||
} |
|||
method p {} { |
|||
return "Q($R,$I,$J,$K)" |
|||
} |
|||
method values {} { |
|||
list $R $I $J $K |
|||
} |
|||
method Norm {} { |
|||
+ [* $R $R] [* $I $I] [* $J $J] [* $K $K] |
|||
} |
|||
method conjugate {} { |
|||
Q return $R [- $I] [- $J] [- $K] |
|||
} |
|||
method norm {} { |
|||
sqrt [my Norm] |
|||
} |
|||
method unit {} { |
|||
set n [my norm] |
|||
Q return [/ $R $n] [/ $I $n] [/ $J $n] [/ $K $n] |
|||
} |
|||
method reciprocal {} { |
|||
set n2 [my Norm] |
|||
Q return [/ $R $n2] [/ $I $n2] [/ $J $n2] [/ $K $n2] |
|||
} |
|||
method - {{q ""}} { |
|||
if {[llength [info level 0]] == 2} { |
|||
Q return [- $R] [- $I] [- $J] [- $K] |
|||
} |
|||
[my + [$q -]] return |
|||
} |
|||
method + q { |
|||
if {[info object isa object $q]} { |
|||
lassign [$q values] real i j k |
|||
Q return [+ $R $real] [+ $I $i] [+ $J $j] [+ $K $k] |
|||
} |
|||
Q return [+ $R [double $q]] $I $J $K |
|||
} |
|||
method * q { |
|||
if {[info object isa object $q]} { |
|||
lassign [my values] a1 b1 c1 d1 |
|||
lassign [$q values] a2 b2 c2 d2 |
|||
Q return [expr {$a1*$a2 - $b1*$b2 - $c1*$c2 - $d1*$d2}] \ |
|||
[expr {$a1*$b2 + $b1*$a2 + $c1*$d2 - $d1*$c2}] \ |
|||
[expr {$a1*$c2 - $b1*$d2 + $c1*$a2 + $d1*$b2}] \ |
|||
[expr {$a1*$d2 + $b1*$c2 - $c1*$b2 + $d1*$a2}] |
|||
} |
|||
set f [double $q] |
|||
Q return [* $R $f] [* $I $f] [* $J $f] [* $K $f] |
|||
} |
|||
method == q { |
|||
expr { |
|||
[info object isa object $q] |
|||
&& [info object isa typeof $q [self class]] |
|||
&& [my values] eq [$q values] |
|||
} |
|||
} |
|||
export - + * == |
|||
}</lang> |
|||
Demonstration code: |
|||
<lang tcl>set q [Q new 1 2 3 4] |
|||
set q1 [Q new 2 3 4 5] |
|||
set q2 [Q new 3 4 5 6] |
|||
set r 7 |
|||
puts "q = [$q p]" |
|||
puts "q1 = [$q1 p]" |
|||
puts "q2 = [$q2 p]" |
|||
puts "r = $r" |
|||
puts "q norm = [$q norm]" |
|||
puts "q1 norm = [$q1 norm]" |
|||
puts "q2 norm = [$q2 norm]" |
|||
puts "-q = [[$q -] p]" |
|||
puts "q conj = [[$q conjugate] p]" |
|||
puts "q + r = [[$q + $r] p]" |
|||
# Real numbers are not objects, so no extending operations for them |
|||
puts "q1 + q2 = [[$q1 + $q2] p]" |
|||
puts "q2 + q1 = [[$q2 + $q1] p]" |
|||
puts "q * r = [[$q * $r] p]" |
|||
puts "q1 * q2 = [[$q1 * $q2] p]" |
|||
puts "q2 * q1 = [[$q2 * $q1] p]" |
|||
puts "equal(q1*q2, q2*q1) = [[$q1 * $q2] == [$q2 * $q1]]"</lang> |
|||
Output: |
|||
<pre> |
|||
q = Q(1.0,2.0,3.0,4.0) |
|||
q1 = Q(2.0,3.0,4.0,5.0) |
|||
q2 = Q(3.0,4.0,5.0,6.0) |
|||
r = 7 |
|||
q norm = 5.477225575051661 |
|||
q1 norm = 7.3484692283495345 |
|||
q2 norm = 9.273618495495704 |
|||
-q = Q(-1.0,-2.0,-3.0,-4.0) |
|||
q conj = Q(1.0,-2.0,-3.0,-4.0) |
|||
q + r = Q(8.0,2.0,3.0,4.0) |
|||
q1 + q2 = Q(5.0,7.0,9.0,11.0) |
|||
q2 + q1 = Q(5.0,7.0,9.0,11.0) |
|||
q * r = Q(7.0,14.0,21.0,28.0) |
|||
q1 * q2 = Q(-56.0,16.0,24.0,26.0) |
|||
q2 * q1 = Q(-56.0,18.0,20.0,28.0) |
|||
equal(q1*q2, q2*q1) = 0 |
|||
</pre> |