Updated 2012-05-18 21:10:58 by RLE

Calculating determinants. Not really difficult, but sometimes helpful if there is some script where it is yet done.

See also Matrix determinant, for another implementation and a discussion of why row expansion is not an efficient algorithm for computing determinants.
 #
 # detVal determinant
 # returns value of $determinant
 # where determinant has the form {{a b} {c d}}
 # or {{a b c} {d e f} {g h i}}
 # or {{a b c d} {e f g h} {i j k l} {m n o p}}
 # ...
 #
 proc detVal determinant {
     if {[llength $determinant] == 1} then {
         set determinant
     } else {
         set result 0
         set sign 1
         set i 0
         foreach num [lindex $determinant 0] {
             set subDeterminant [subDet $determinant $i]
             set subDetVal [detVal $subDeterminant]
             set sign [expr {- $sign}]
             set result [expr {$result + $num * $subDetVal * $sign}]
             incr i
         }
         set result
     }
 }
 
 #
 # subDet determinant n
 # returns ${n}th subdeterminant of $determinant
 # e.g. subDet {{a b} {c d}} 0 => d
 # or subDet {{a b} {c d}} 1 => c
 # or subDet {{a b c} {d e f} {g h i}} 1 => {{d f} {g i}}
 # ...
 #
 proc subDet {determinant n} {
     set result {}
     foreach oldRow [lrange $determinant 1 end] {
         set newRow {}
         set i 0
         foreach num $oldRow {
             if {$i != $n} then {
                 lappend newRow $num
             }
             incr i
         }
         lappend result $newRow
     }
     set result
 }
 
 #
 # detColSet determinant colNum col
 # returns copy of $determinant where ${colNum}th col 
 # is replaced with $col
 #
 proc detColSet {determinant colNum col} {
     set i 0
     foreach num $col {
         lset determinant $i $colNum $num
         incr i
     }
     set determinant
 }
 
 
 # debug
 if true {
     #
     # vertical cmd ...
     # aligns result of [cmd ...] vertically
     # e.g. 
     # % vertical subDet $det1 0
     # 11 9
     # 50 1
     #
     proc vertical args {
         join [eval $args] \n
     }
 
     set det0 {
         {2 3}
         {9 10}
     }
 
     set det1 {
         {2 3 5}
         {12 11 9}
         {30 50 1}
     }
 }