1 ###### Matrix.tcl #################################################
3 # Copyright (C) 2024 Jaime E. Villate
4 # Time-stamp: "2024-03-20 14:40:38 villate
6 # For distribution under GNU public License. See COPYING.tcl
7 # (Based on William F. Schelter's work, Copyright (C) 1998)
9 ###################################################################
11 # In this file a matrix is represented as in Maxima.
12 # Namely, as a list of rows, where each row is itself a list.
13 # {{1 0} {0 1}} would then be the two by two identity.
14 # vectors are represented by lists.
17 # Given a matrix {{a00 a01} {a10 a11}} and a constant vector {k0 k1},
18 # it returns the symbolic expression:
19 # {prefix0 prefix1} {[expr {a00*$prefix0+a01*$prefix1+k0}]
20 # [expr {a10*$prefix0+a11*$prefix1+k1}]}
21 # which will be used by mkMultLeft to define a procedure with input
22 # parameters {prefix0 prefix1}
24 proc mkMultLeftExpr
{mat prefix
{constant
""}} {
27 set n
[llength [lindex $mat 0]]
28 for { set i
0} { $i < $n} {incr i
} { append vars
" $prefix$i" }
29 foreach row
$mat c
$constant {
32 foreach a
$row v
$vars {
33 append prod
"$op$a*\$$v"
35 if {$c ne
""} {append prod
"+$c"}
36 append ans
[concat \[expr [list $prod]\]]
38 return [list $vars $ans]}
41 # Creates a procedure named "name" with as many input parameters as
42 # the number of columns o matrix mat.
43 # That procedure will return a vector with as many components as
44 # the number of rows of mat.
45 # If given, constant is a vector with as many components as the number
46 # of rows of mat. Each component on the returned vector is the linear
47 # combination of the input parameters with the corresponding row of mat,
48 # plus the corresponding component of "constant" if it is given.
50 proc mkMultLeftFun
{mat name
{constant
""} } {
51 set expr [mkMultLeftExpr
$mat _a
$constant]
52 set bod1
[string trim
[lindex $expr 1] " "]
53 set bod
[concat list [lindex $expr 1]]
54 proc $name [lindex $expr 0] $bod}
57 # Computes the matrix of the rotation by azimuth th, and elevation ph
58 # matrix([cos(th),sin(th),0], [-cos(ph)*sin(th),cos(ph)*cos(th),sin(ph)],
59 # [sin(ph)*sin(th),-sin(ph)*cos(th),cos(ph)]);
60 proc rotationMatrix
{th ph
{ignore
{} } } {
61 set cph
[expr {cos
($ph)}]
62 set sph
[expr {sin
($ph)}]
63 set cth
[expr {cos
($th)}]
64 set sth
[expr {sin
($th)}]
65 return [list [list $cth $sth 0] \
66 [list [expr {-$cph*$sth}] [expr {$cph*$cth}] $sph] \
67 [list [expr {$sph*$sth}] [expr {-$sph*$cth}] $cph]]}
70 # Returns the product of matrices mat1 and mat2
71 proc matMul
{mat1 mat2
} {
72 set rows
[llength $mat1]
73 set cols
[llength [lindex $mat2 0]]
75 for {set j
0} {$j < $cols} {incr j
} {
76 lappend col
$j [lindex $r $j]}}
77 for {set i
0} {$i < $rows} {incr i
} {
78 for {set j
0} {$j < $cols} {incr j
} {
79 lappend row
$i [vectDot
[lindex $mat1 $i] [set col
$j]]}
80 lappend mat3
[set row
$i]}
84 # Returns the dot product of vectors vec1 and vec2
85 proc vectDot
{vec1 vec2
} {
87 foreach c1
$vec1 c2
$vec2 {
88 set prod
[expr {$prod + $c1*$c2}]}
92 # Returns the vector obtained by applying the infix operator "op"
93 # between vectors vec1 and vec2
94 proc vectorOp
{vec1 op vec2
} {
96 foreach ai
$vec1 bi
$vec2 {lappend ans
[expr [list $ai $op $bi]]}
100 # Returns the vector obtained by multiplying vector by scalar
101 proc scalarTimesVector
{scalar vector
} {
102 foreach coord
$vector {lappend ans
[expr {$scalar*$coord}]}
105 ## endsource matrix.tcl