Version 1 of Matrix Multiplication

Updated 2003-11-06 18:16:27

Arjen Markus Just a little experiment with a common form of matrix multiplication: transform coordinates in a 3D space. This type of operation arises when you want to do 3D graphics for instance. It can easily be adjusted to any fixed number of dimensions, but if you have serious needs for matrix multiplication or matrix manipulation in general, I suggest you look at Ed Hume's LA package.


 # matrices.tcl --
 #    Simple demonstration of matrix-vector multiplications
 #
 # The idea:
 #    In 3D space:
 #    - A vector is represented as a list of 3 numbers
 #    - A matrix is represented as a list of 3 lists of 3 numbers
 #    - A series of vectors is also a list of lists
 #    For instance:
 #    The identity matrix is { {1 0 0} {0 1 0} {0 0 1}}
 #    Rotation over X degrees around the z-axis is implemented
 #    via:
 #    { {C  -S  0}
 #      {S   C  0}
 #      {0   0  1}}
 #    where C = cos X, S = sin X
 #
 #    Rotating the vector {0 1 1} thus gives:
 #    { [expr {C*0-S*1+0*1}] [expr {S*0+C*1+0*1}] [expr {0*0+0*1+1*1}] }
 #    = {-S C 1}
 #
 namespace eval ::matrices {
    namespace export matmul
 }

 # matmul --
 #    Multiply a vector (or list of vectors) by a 3x3 matrix
 #
 # Arguments:
 #    matrix       Matrix to multiply with
 #    vector       Vector operand (or list of vectors)
 # Result:
 #    Transformed vector (vector list)
 # Note:
 #    A vector list of 3 vectors is identical to a 3x3 matrix,
 #    hence this procedure can be used for matrix multiplications too
 #    Transposition is implied by the implementation (just to remind
 #    myself :)
 #
 proc ::matrices::matmul {matrix vector} {
    set n1 11
    set n2 12
    set n3 13
    foreach row $matrix {
       foreach [list m$n1 m$n2 m$n3] $row { break }
       incr n1 10
       incr n2 10
       incr n3 10
    }

    #
    # Add an extra level of list if there is only one vector
    #
    if { [llength [lindex $vector 0]] == 1 } {
       set vector [list $vector]
    }
    set r [list]
    foreach v $vector {
       foreach {x y z} $v { break }
       lappend r [list [expr {$m11*$x+$m12*$y+$m13*$z}] \
                       [expr {$m21*$x+$m22*$y+$m23*$z}] \
                       [expr {$m31*$x+$m32*$y+$m33*$z}] ]
    }
    return $r
 }

 # Test code
 #
 namespace import ::matrices::*

 set vectors  { {1.0 0.0 0.0} {0.0 1.0 0.0} {0.0 0.0 1.0} }
 set matrix   { {1.0 2.0 3.0} {4.0 5.0 6.0} {7.0 8.0 9.0} }
 set expected { {1.0 4.0 7.0} {2.0 5.0 8.0} {3.0 6.0 9.0} }

 puts "Per vector:"
 foreach vector $vectors exp $expected {
    set result [matmul $matrix $vector]
    puts "$result -- $exp"
 }
 puts "For a list of vectors:"
 set result [matmul $matrix $vectors]
 puts "$result -- $expected"

 puts "Matrix multiplication (matrix**2 is identity)"
 set matrix   { {0.0 1.0 0.0} {1.0 0.0 0.0} {0.0 0.0 1.0} }
 set result [matmul $matrix $matrix]
 puts "$result"

[ Category Mathematics ]