Conjugate transpose: Difference between revisions

Content added Content deleted
(→‎Tcl: Added implementation)
Line 241: Line 241:
print ' unitary? false'
print ' unitary? false'
end</lang>
end</lang>

=={{header|Tcl}}==
{{tcllib|math::complexnumbers}}
{{tcllib|struct::matrix}}
<lang tcl>package require struct::matrix
package require math::complexnumbers

proc conjugateTranspose {matrix} {
set mat [struct::matrix]
$mat = $matrix
$mat transpose
for {set c 0} {$c < [$mat columns]} {incr c} {
for {set r 0} {$r < [$mat rows]} {incr r} {
set val [$mat get cell $c $r]
$mat set cell $c $r [math::complexnumbers::conj $val]
}
}
return $mat
}

proc complexMatrix.equal {m1 m2 {epsilon 1e-14}} {
if {[$m1 rows] != [$m2 rows] || [$m1 columns] != [$m2 columns]} {
return 0
}
# Compute the magnitude of the difference between two complex numbers
set ceq [list apply {{epsilon a b} {
expr {[mod [- $a $b]] < $epsilon}
} ::math::complexnumbers} $epsilon]
for {set i 0} {$i<[$m1 columns]} {incr i} {
for {set j 0} {$j<[$m1 rows]} {incr j} {
if {![{*}$ceq [$m1 get cell $i $j] [$m2 get cell $i $j]]} {
return 0
}
}
}
return 1
}

proc isHermitian {matrix {epsilon 1e-14}} {
if {[$matrix rows] != [$matrix columns]} {
# Must be square!
return 0
}
set cc [conjugateTranspose $matrix]
set result [complexMatrix.equal $matrix $cc $epsilon]
$cc destroy
return $result
}

proc complexMatrix.multiply {a b} {
if {[$a columns] != [$b rows]} {
error "incompatible sizes"
}
# Simplest to use a lambda in the complex NS
set cpm {{sum a b} {
+ $sum [* $a $b]
} ::math::complexnumbers}
set c0 [math::complexnumbers::complex 0.0 0.0]; # Complex zero
set c [struct::matrix]
$c add columns [$b columns]
$c add rows [$a rows]
for {set i 0} {$i < [$a rows]} {incr i} {
for {set j 0} {$j < [$b columns]} {incr j} {
set sum $c0
foreach rv [$a get row $i] cv [$b get column $j] {
set sum [apply $cpm $sum $rv $cv]
}
$c set cell $j $i $sum
}
}
return $c
}

proc isNormal {matrix {epsilon 1e-14}} {
if {[$matrix rows] != [$matrix columns]} {
# Must be square!
return 0
}
set mh [conjugateTranspose $matrix]
set mhm [complexMatrix.multiply $mh $matrix]
set mmh [complexMatrix.multiply $matrix $mh]
$mh destroy
set result [complexMatrix.equal $mhm $mmh $epsilon]
$mhm destroy
$mmh destroy
return $result
}

proc isUnitary {matrix {epsilon 1e-14}} {
if {[$matrix rows] != [$matrix columns]} {
# Must be square!
return 0
}
set mh [conjugateTranspose $matrix]
set mhm [complexMatrix.multiply $mh $matrix]
set mmh [complexMatrix.multiply $matrix $mh]
$mh destroy
set result [complexMatrix.equal $mhm $mmh $epsilon]
$mhm destroy
if {$result} {
set id [struct::matrix]
$id = $matrix; # Just for its dimensions
for {set c 0} {$c < [$id columns]} {incr c} {
for {set r 0} {$r < [$id rows]} {incr r} {
$id set cell $c $r \
[math::complexnumbers::complex [expr {$c==$r}] 0]
}
}
set result [complexMatrix.equal $mmh $id $epsilon]
$id destroy
}
$mmh destroy
return $result
}</lang>
<!-- Wot, no demonstration? -->