# -*- tcl -*- # linalg.test -- # Tests for the linear algebra package # # NOTE: # Comparison by numbers, not strings, needed! # # TODO: # Tests for: # - show, angle # - solveGaussBand, solveTriangularBand # - mkHilbert and so on # - matmul # ------------------------------------------------------------------------- set regular 1 if {$regular==1} then { source [file join \ [file dirname [file dirname [file join [pwd] [info script]]]] \ devtools testutilities.tcl] testsNeedTcl 8.4 testsNeedTcltest 2.1 support { useLocal math.tcl math } testing { useLocal linalg.tcl math::linearalgebra } } else { package require tcltest tcltest::configure -verbose {start body error pass} #tcltest::configure -match largesteigen-* namespace import tcltest::test namespace import tcltest::customMatch set basedir [file normalize [file dirname [info script]]] set ::auto_path [linsert $::auto_path 0 $basedir] package require -exact math::linearalgebra 1.1.3 } # ------------------------------------------------------------------------- namespace import -force ::math::linearalgebra::* set old_precision $::tcl_precision set ::tcl_precision 17 # # Returns 1 if the expected value is close to the actual value, # that is their relative difference is small with respect to the # given epsilon. # If the expected value is zero, use an absolute error instead. # proc areClose {expected actual epsilon} { if {$actual=="" && $expected!=""} then { return 0 } if {$actual!="" && $expected==""} then { return 0 } set match 1 if { [llength [lindex $expected 0]] > 1 } { foreach a $actual e $expected { set match [matchNumbers $e $a] if { $match == 0 } { break } } } else { foreach a $actual e $expected { if {[string is double $a]==0 || [string is double $e]==0} then { return 0 } if {$e!=0.0} then { set shift [expr {abs($a-$e)/abs($e)}] } else { set shift [expr {abs($a-$e)}] } #puts "a=$a, e=$e, shift = $shift" if {$shift > $epsilon} { set match 0 break } } } return $match } # # Matching procedure - flatten the lists # proc matchNumbers {expected actual} { if {$actual=="" && $expected!=""} then { return 0 } if {$actual!="" && $expected==""} then { return 0 } set match 1 if { [llength [lindex $expected 0]] > 1 } { foreach a $actual e $expected { set match [matchNumbers $e $a] if { $match == 0 } { break } } } else { foreach a $actual e $expected { if {[string is double $a]==0 || [string is double $e]==0} then { return 0 } if {abs($a-$e) > 0.1e-6} { set match 0 break } } } return $match } customMatch numbers matchNumbers test dimshape-1.0 "dimension of scalar" -body { dim 1 } -result 0 test dimshape-1.1 "dimension of vector" -body { dim {1 2 3} } -result 1 test dimshape-1.2 "dimension of matrix" -body { dim { {1 2 3} {4 5 6} } } -result 2 test dimshape-2.0 "shape of scalar" -body { shape 1 } -result {1} test dimshape-2.1 "shape of vector" -body { shape {1 2 3} } -result 3 test dimshape-2.2 "shape of matrix" -body { shape { {1 2 3} {4 5 6} } } -result {2 3} test symmetric-1.0 "non-symmetric matrix" -body { symmetric { {1 2 3} {4 5 6} {7 8 9}} } -result 0 test symmetric-1.1 "symmetric matrix" -body { symmetric { {1 2 3} {2 1 4} {3 4 1}} } -result 1 test symmetric-1.2 "non-square matrix" -body { symmetric { {1 2 3} {2 1 4}} } -result 0 test norm-1.0 "one-norm - 5 components" -match numbers -body { norm {1 2 3 0 -1} 1 } -result 7.0 test norm-1.1 "one-norm - 2 components" -match numbers -body { norm {1 -1} 1 } -result 2.0 test norm-1.2 "two-norm - 5 components" -match numbers -body { norm {1 2 3 0 -1} 2 } -result [expr {sqrt(15)}] test norm-1.3 "two-norm - 2 components" -match numbers -body { norm {1 -1} 2 } -result [expr {sqrt(2)}] test norm-1.4 "two-norm - no underflow" -match numbers -body { norm {3.0e-140 -4.0e-140} 2 } -result 5.0e-140 test norm-1.5 "two-norm - no overflow" -match numbers -body { norm {3.0e140 -4.0e140} 2 } -result 5.0e140 test norm-1.6 "max-norm - 5 components" -match numbers -body { norm {1 2 3 0 -4} max } -result 4 test norm-1.7 "max-norm - 2 components" -match numbers -body { norm {1 -1} max } -result 1 test norm-2.0 "matrix-norm - 2x2 - max" -match numbers -body { normMatrix {{1 -1} {1 1}} max } -result 1 test norm-2.1 "matrix-norm - 2x2 - 1" -match numbers -body { normMatrix {{1 -1} {1 1}} 1 } -result 4 test norm-2.2 "matrix-norm - 2x2 - 2" -match numbers -body { normMatrix {{1 -1} {1 1}} 2 } -result 2 test norm-3.0 "statistical normalisation - vector" -match numbers -body { normalizeStat {1 0 0 0} } -result {1.5 -0.5 -0.5 -0.5} test norm-3.1 "statistical normalisation - matrix" -match numbers -body { normalizeStat {{1 0 0 0} {0 0 0 1} {0 1 1 0} {0 0 0 0}} } -result {{ 1.5 -0.5 -0.5 -0.5} {-0.5 -0.5 -0.5 1.5} {-0.5 1.5 1.5 -0.5} {-0.5 -0.5 -0.5 -0.5}} test dotproduct-1.0" "dot-product - 2 components" -match numbers -body { dotproduct {1 -1} {1 -1} } -result 2.0 test dotproduct-1.1" "dot-product - 5 components" -match numbers -body { dotproduct {1 2 3 4 5} {5 4 3 2 1} } -result [expr {5.0+8+9+8+5}] test unitlength-1.0" "unitlength - 2 components" -match numbers -body { unitLengthVector {3 4} } -result {0.6 0.8} test unitlength-1.1" "unitlength - 4 components" -match numbers -body { unitLengthVector {1 1 1 1} } -result {0.5 0.5 0.5 0.5} test axpy-1.0 "axpy - vectors" -body { axpy 2 {1 -1} {2 -2} } -result {4 -4} test axpy-1.1 "axpy - matrices" -body { axpy 2 { {1 -1} {2 -2} {3 4} {-3 4} } \ { {5 -5} {5 -5} {6 6} {-6 6} } } -result {{7 -7} {9 -9} {12 14} {-12 14}} test add-1.0 "add - vectors" -body { add {1 -1} {2 -2} } -result {3 -3} test add-1.1 "add - matrices" -body { add { {1 -1} {2 -2} {3 4} {-3 4} } \ { {5 -5} {5 -5} {6 6} {-6 6} } } -result {{6 -6} {7 -7} {9 10} {-9 10}} test sub-1.0 "sub - vectors" -body { sub {1 -1} {2 -2} } -result {-1 1} test sub-1.1 "sub - matrices" -body { sub { {1 -1} {2 -2} {3 4} {-3 4} } \ { {5 -5} {5 -5} {6 6} {-6 6} } } -result {{-4 4} {-3 3} {-3 -2} {3 -2}} test scale-1.0 "scale - vectors" -body { scale 3 {2 -2} } -result {6 -6} test scale-1.1 "scale - matrices" -body { scale 3 { {5 -5} {5 -5} {6 6} {-6 6} } } -result {{15 -15} {15 -15} {18 18} {-18 18}} test make-1.0 "mkVector - create a null vector" -body { mkVector 3 } -result {0.0 0.0 0.0} test make-1.1 "mkVector - create a vector with values 1" -body { mkVector 3 1.0 } -result {1.0 1.0 1.0} test make-2.0 "mkMatrix - create a matrix with 3 rows, 2 columns" -body { mkMatrix 3 2 2.0 } -result {{2.0 2.0} {2.0 2.0} {2.0 2.0}} test make-2.1 "mkMatrix - create a matrix with 2 rows, 3 columns" -body { mkMatrix 2 3 1.0 } -result {{1.0 1.0 1.0} {1.0 1.0 1.0}} test make-3.0 "mkIdentity - create an identity matrix 2x2" -body { mkIdentity 2 } -result {{1.0 0.0} {0.0 1.0}} test make-3.1 "mkIdentity - create an identity matrix 3x3" -body { mkIdentity 3 } -result {{1.0 0.0 0.0} {0.0 1.0 0.0} {0.0 0.0 1.0}} test make-4.0 "mkDiagonal - create a diagonal matrix 2x2" -body { mkDiagonal {2.0 3.0} } -result {{2.0 0.0} {0.0 3.0}} test make-4.1 "mkDiagonal - create a diagonal matrix 3x3" -body { mkDiagonal {2.0 3.0 4.0} } -result {{2.0 0.0 0.0} {0.0 3.0 0.0} {0.0 0.0 4.0}} test getset-1.0 "getrow - get first row from a matrix" -body { getrow {{1 2 3} {4 5 6} {7 8 9} {10 11 12}} 0 } -result {1 2 3} test getset-1.1 "getrow - get last row from a matrix" -body { getrow {{1 2 3} {4 5 6} {7 8 9} {10 11 12}} 3 } -result {10 11 12} test getset-1.1b "getrow - get row of a vector" -body { getrow {1 2 3} 1 } -result {2} test getset-1.1c "getrow - get row #1, for columns #2 to #3" -body { getrow {{1 2 3 4 5 6} {7 8 9 10 11 12} {13 14 15 16 17 18}} 1 2 3 } -result {9 10} test getset-1.2 "getcol - get first column from a matrix" -body { getcol {{1 2 3} {4 5 6} {7 8 9} {10 11 12}} 0 } -result {1 4 7 10} test getset-1.3 "getcol - get last column from a matrix" -body { getcol {{1 2 3} {4 5 6} {7 8 9} {10 11 12}} 2 } -result {3 6 9 12} test getset-1.4 "getcol - get column #1 from lines #2 to #3" -body { getcol {{1 2 3} {4 5 6} {7 8 9} {10 11 12} {13 14 15}} 1 2 3 } -result {8 11} test getset-2.0 "setrow - set first row in a matrix" -body { set M {{1 2 3} {4 5 6} {7 8 9} {10 11 12}} setrow M 0 {3 2 1} } -result {{3 2 1} {4 5 6} {7 8 9} {10 11 12}} test getset-2.1 "setrow - set last row in a matrix" -body { set M {{1 2 3} {4 5 6} {7 8 9} {10 11 12}} setrow M 3 {3 2 1} } -result {{1 2 3} {4 5 6} {7 8 9} {3 2 1}} test getset-2.1b "setrow - set row #1 from column #2 to column #3" -body { set M {{1 2 3 4 5} {6 7 8 9 10} {11 12 13 14 15}} setrow M 1 {99 100} 2 3 } -result {{1 2 3 4 5} {6 7 99 100 10} {11 12 13 14 15}} test getset-2.2 "setcol - set first column in a matrix" -body { set M {{1 2 3} {4 5 6} {7 8 9} {10 11 12}} setcol M 0 {3 2 1 0} } -result {{3 2 3} {2 5 6} {1 8 9} {0 11 12}} test getset-2.3 "setcol - set last column in a matrix" -body { set M {{1 2 3} {4 5 6} {7 8 9} {10 11 12}} setcol M 2 {3 2 1 0} } -result {{1 2 3} {4 5 2} {7 8 1} {10 11 0}} test getset-2.4 "setcol - set column #1 from lines #2 to #3" -body { set M {{1 2 3} {4 5 6} {7 8 9} {10 11 12} {13 14 15}} setcol M 1 {99 100} 2 3 } -result {{1 2 3} {4 5 6} {7 99 9} {10 100 12} {13 14 15}} test getset-3.0 "getelem - get element (0,0) in a matrix" -body { getelem {{1 2 3} {4 5 6} {7 8 9} {10 11 12}} 0 0 } -result 1 test getset-3.1 "getelem - set element (1,2) in a matrix" -body { getelem {{1 2 3} {4 5 6} {7 8 9} {10 11 12}} 1 2 } -result 6 test getset-3.2 "setelem - set element (0,0) in a matrix" -body { set M {{1 2 3} {4 5 6} {7 8 9} {10 11 12}} setelem M 0 0 100 } -result {{100 2 3} {4 5 6} {7 8 9} {10 11 12}} test getset-3.3 "setelem - set element (1,2) in a matrix" -body { set M {{1 2 3} {4 5 6} {7 8 9} {10 11 12}} setelem M 1 2 100 } -result {{1 2 3} {4 5 100} {7 8 9} {10 11 12}} test getset-4.0 "getelem - get element 1 from a vector" -body { set V {1 2 3} getelem $V 1 } -result 2 test getset-4.1 "setelem - set element 1 in a vector" -body { set V {1 2 3} setelem V 1 4 } -result {1 4 3} test swaprows-1 "swap two rows of a matrix" -body { set M {{1 2 3} {4 5 6} {7 8 9} {10 11 12}} swaprows M 1 2 } -result {{1 2 3} {7 8 9} {4 5 6} {10 11 12}} test swaprows-2 "swap rows #1 and #2 from columns #2 to #3" -body { set M {{1 2 3 4 5} {6 7 8 9 10} {11 12 13 14 15} {16 17 18 19 20}} swaprows M 1 2 2 3 } -result {{1 2 3 4 5} {6 7 13 14 10} {11 12 8 9 15} {16 17 18 19 20}} test swapcols-1 "swap two columns of a matrix" -body { set M {{1 2 3 4 5} {6 7 8 9 10} {11 12 13 14 15} {16 17 18 19 20}} swapcols M 1 2 } -result {{1 3 2 4 5} {6 8 7 9 10} {11 13 12 14 15} {16 18 17 19 20}} test swapcols-2 "swap columns #1 and #2 from lines #1 to #2" -body { set M {{1 2 3 4 5} {6 7 8 9 10} {11 12 13 14 15} {16 17 18 19 20}} swapcols M 1 2 1 2 } -result {{1 2 3 4 5} {6 8 7 9 10} {11 13 12 14 15} {16 17 18 19 20}} test rotate-1.0 "rotate - over 90 degrees" -body { set v1 {1 2 3} set v2 {4 5 6} rotate 0 1 $v1 $v2 } -result {{-4 -5 -6} {1 2 3}} test rotate-1.1 "rotate - over 180 degrees" -body { set v1 {1 2 3 4 5 6} set v2 {7 8 9 10 11 12} rotate -1 0 $v1 $v2 } -result {{-1 -2 -3 -4 -5 -6} {-7 -8 -9 -10 -11 -12}} test matmul-1.0 "multiply matrix - vector" -match numbers -body { set v1 {1 2 3} set m {{0 0 1} {0 5 0} {-1 0 0}} matmul $m $v1 } -result {3 10 -1} test matmul-1.1 "multiply vector - matrix" -match numbers -body { set v1 {{1 2 3}} ;# Row vector set m {{0 0 1} {0 5 0} {-1 0 0}} matmul $v1 $m } -result {{-3 10 1}} test matmul-1.2 "multiply matrix - matrix" -match numbers -body { set m1 {{0 0 1} {0 5 0} {-1 0 0}} set m2 {{0 0 1} {1 5 1} {-1 0 0}} matmul $m1 $m2 } -result {{-1 0 0} {5 25 5} {0 0 -1}} test matmul-1.3 "multiply vector - vector" -match numbers -body { set v1 {1 2 3} set v2 {4 5 6} matmul $v1 $v2 } -result {{4 5 6} {8 10 12} {12 15 18}} test matmul-1.4 "multiply row vector - column vector" -match numbers -body { set v1 [transpose {1 2 3}] set v2 {4 5 6} matmul $v1 $v2 } -result 32 test matmul-1.5 "multiply column vector - row vector" -match numbers -body { set v1 {1 2 3} set v2 [transpose {4 5 6}] matmul $v1 $v2 } -result {{4 5 6} {8 10 12} {12 15 18}} test matmul-1.6 "multiply scalar - scalar" -match numbers -body { set v1 {1} set v2 {1} matmul $v1 $v2 } -result {1} test solve-1.1 "solveGauss - 2x2 matrix" -match numbers -body { set b {{2 3} {-2 3}} set M {{2 3} {-2 3}} solveGauss $M $b } -result {{1 0} {0 1}} test solve-1.2 "solveGauss - 3x3 matrix" -match numbers -body { set b {{2 3 4} {-2 3 4} {1 1 1}} set M {{2 3 4} {-2 3 4} {1 1 1}} solveGauss $M $b } -result {{1 0 0} {0 1 0} {0 0 1}} test solve-1.3 "solveGauss - 3x3 matrix - less trivial" -match numbers -body { set b {{6 -3 6} {2 -3 2} {2 -1 2}} set M {{2 3 4} {-2 3 4} {1 1 1}} solveGauss $M $b } -result {{1 0 1} {0 -1 0} {1 0 1}} # # MB # test solve-1.4 "solveGauss - 3x3 matrix - but better pivots may be found" -match numbers -body { set b {{67 67} {4 4} {6 6}} set M {{3 17 10} {2 4 -2} {6 18 -12}} solveGauss $M $b } -result {{1 1} {2 2} {3 3}} test solve-1.5 "solveGauss - Hilbert matrix" -match numbers -body { set expected [mkVector 10 1.0] set M [mkHilbert 10] # b is expected as a list of colums set b [mkMatrix 10 1] setcol b 0 [matmul $M $expected] set computed [solveGauss $M $b] set diff [sub $computed $expected] set norm [normMatrix $diff max] # Computed norm : 0.00043691152972824554 set result [expr {$norm<1.e-3}] } -result {1} test solvepgauss-1.6 "solveGauss - 2x2 difficult matrix with necessary permutations" -match numbers -body { set M {{1.e-8 1} {1 1}} set b [list [expr {1.+1.e-8}] 2.] set computed [solveGauss $M $b] set expected {1. 1.} set diff [sub $computed $expected] set norm [norm $diff max] # Computed norm : 5.0247592753294157e-09 set result [expr {$norm<1.e-8}] } -result {1} test solvepgauss-1 "solvePGauss - 3x3 matrix with two permutations" -match numbers -body { set b {{67} {4} {6}} set M {{3 17 10} {2 4 -2} {6 18 -12}} solvePGauss $M $b } -result {{1} {2} {3}} test solvepgauss-2 "solvePGauss - 3x3 matrix" -match numbers -body { set b {{6 -3 6} {2 -3 2} {2 -1 2}} set M {{2 3 4} {-2 3 4} {1 1 1}} solvePGauss $M $b } -result {{1 0 1} {0 -1 0} {1 0 1}} test solvepgauss-3 "solvePGauss - 10x10 Hilbert matrix" -match numbers -body { set expected [mkVector 10 1.0] set M [mkHilbert 10] # b is expected as a list of colums set b [mkMatrix 10 1] setcol b 0 [matmul $M $expected] set computed [solvePGauss $M $b] set diff [sub $computed $expected] set norm [normMatrix $diff max] # Computed norm : 0.00031339500191851499 set result [expr {$norm<1.e-3}] } -result {1} test solvepgauss-4 "solvePGauss - 2x2 difficult matrix with necessary permutations" -match numbers -body { set M {{1.e-8 1} {1 1}} set b [list [expr {1.+1.e-8}] 2.] set computed [solvePGauss $M $b] set expected {1. 1.} set diff [sub $computed $expected] set norm [norm $diff max] # Computed norm : 0. set result [expr {$norm<1.e-15}] } -result {1} test orthon-1.0 "orthonormalize columns - 3x3" -match numbers -body { set M {{1 1 1} {0 1 1} {0 0 1}} orthonormalizeColumns $M } -result {{1 0 0} {0 1 0} {0 0 1}} test orthon-1.1 "orthonormalize rows - 3x3" -match numbers -body { set M {{1 0 0} {1 1 0} {1 1 1}} orthonormalizeRows $M } -result {{1 0 0} {0 1 0} {0 0 1}} test orthon-1.2 "orthonormalize rows - 3x4" -match numbers -body { set M {{1 0 0 0} {1 1 0 0} {1 1 1 0}} orthonormalizeRows $M } -result {{1 0 0 0} {0 1 0 0} {0 0 1 0}} # # The results from the original LA package have been used # as a benchmark: # # test svd-1.0 "singular value decomposition - 2x2" -match numbers -body { set M {{1.0 2.0} {2.0 1.0}} determineSVD $M } -result { {{0.70710678118654757 0.70710678118654746} {0.70710678118654746 -0.70710678118654757}} {3.0 1.0} {{0.70710678118654757 -0.70710678118654746} {0.70710678118654746 0.70710678118654757}} } test svd-1.1 "singular value decomposition - 10x10" -match numbers -body { set M [mkDingdong 10] show [lindex [determineSVD $M] 1] %6.4f } -result {1.5708 1.5708 1.5708 1.5708 1.5708 1.5707 1.5695 1.5521 1.3935 0.6505} test LA-1.0 "to_LA - vector" -match numbers -body { set vector {1 2 3} to_LA $vector } -result {2 3 0 1 2 3} test LA-1.1 "to_LA - matrix" -match numbers -body { set matrix {{1 2 3} {4 5 6} {7 8 9} {10 11 12}} to_LA $matrix } -result {2 4 3 1 2 3 4 5 6 7 8 9 10 11 12} test LA-2.0 "from_LA - vector" -match numbers -body { set vector {2 3 0 1 2 3} from_LA $vector } -result {1 2 3} test LA-2.1 "from_LA - matrix" -match numbers -body { set matrix {2 4 3 1 2 3 4 5 6 7 8 9 10 11 12} from_LA $matrix } -result {{1 2 3} {4 5 6} {7 8 9} {10 11 12}} test choleski-1.0 "choleski decomposition of Moler matrix" -match numbers -body { set matrix [mkMoler 5] choleski $matrix } -result {{1 0 0 0 0} {-1 1 0 0 0} {-1 -1 1 0 0} {-1 -1 -1 1 0} {-1 -1 -1 -1 1}} test leastsquares-1.0 "Least-squares solution" -match numbers -body { # # Known relation: z = 1.0 + x + 0.1*y # Model this as: z = z0 + x + 0.1*y # (The column of 1s allows us to use a non-zero intercept) # # z0 x y z set Ab { { 1 1.0 1.0} 2.1 { 1 2.0 1.0} 3.1 { 1 2.0 2.0} 3.2 { 1 4.0 2.0} 5.2 { 1 4.0 22.0} 7.2 { 1 5.0 -2.0} 5.8 } set A {} set b {} foreach {Ar br} $Ab { lappend A $Ar lappend b $br } set x [::math::linearalgebra::leastSquaresSVD $A $b] } -result {1.0 1.0 0.1} test eigenvectors-1.0 "Eigenvectors solution" -match numbers -body { # # Matrix: # /2 1\ # \1 2/ # has eigenvalues 3 and 1 with eigenvectors: # / 1\ /1\ # \-1/ and \1/ # (so include a factor 1/sqrt(2) in the answer) # set A { {2 1} {1 2} } ;# Note: integer coefficients! set result [::math::linearalgebra::eigenvectorsSVD $A] } -result {{{0.7071068 -0.7071068} {0.7071068 0.7071068}} {3.0 1.0}} test mkHilbert-1.0 "Hilbert matrix" -match numbers -body { set computed [mkHilbert 3] set expected {{1.0 0.5 0.333333333333} {0.5 0.333333333333 0.25} {0.333333333333 0.25 0.2}} set diff [sub $computed $expected] set norm [normMatrix $diff max] set result [expr {$norm<1.e-10}] } -result {1} test dger-1 "dger" -match numbers -body { set M {{1 2 3} {4 5 6} {7 8 9}} set x {1 2 3} set y {4 5 6} set alpha -1. dger M $alpha $x $y } -result {{-3 -3 -3} {-4 -5 -6} {-5 -7 -9}} test dger-2 "dger" -match numbers -body { set M {{1 2 3 4 5} {6 7 8 9 10} {11 12 13 14 15} {16 17 18 19 20}} set x {1 2 3} set y {4 5 6} set alpha -1. set imin 1 set imax 3 set jmin 2 set jmax 4 set scope [list $imin $imax $jmin $jmax] dger M $alpha $x $y $scope } -result {{1 2 3 4 5} {6 7 4 4 4} {11 12 5 4 3} {16 17 6 4 2}} test dgetrf-1 "dgetrf" -body { set M {{3 17 10} {2 4 -2} {6 18 -12}} set ipiv [dgetrf M] # Check matrix set expectedmat {{6 18 -12} {0.5 8.0 16.0} {0.33333333333333331 -0.25 6.0}} set diff [sub $M $expectedmat] set norm [normMatrix $diff max] set expectation1 [expr {$norm<1.e-10}] # Check pivots set expectedpivots {2 2} set diff [sub $ipiv $expectedpivots] set norm [normMatrix $diff max] set expectation2 [expr {$norm<1.e-10}] set result [list $expectation1 $expectation2] } -result {1 1} test solvetriangular-1 "upper triangular matrix" -match numbers -body { set M {{3 17 10} {0 4 -2} {0 0 -12}} set b {{67 30} {2 2} {-36 -12}} set computed [solveTriangular $M $b] } -result {{1 1} {2 1} {3 1}} test solvetriangular-2 "lower triangular matrix" -match numbers -body { set M {{3 0 0} {2 4 0} {6 18 -12}} set b {{3 3} {10 6} {6 12}} set computed [solveTriangular $M $b "L"] } -result {{1 1} {2 1} {3 1}} test solvetriangular-3 "lower triangular random matrix" -match numbers -body { set M [mkTriangular 10 "L" 1.] set xexpected [mkVector 10 1.] set b [matmul $M $xexpected] set computed [solveTriangular $M $b "L"] } -result {1 1 1 1 1 1 1 1 1 1} test solvetriangular-4 "upper triangular random matrix" -match numbers -body { set M [mkTriangular 10 "U" 1.] set xexpected [mkVector 10 1.] set b [matmul $M $xexpected] set computed [solveTriangular $M $b "U"] } -result {1 1 1 1 1 1 1 1 1 1} test mkTriangular-1 "make triangular matrix" -match numbers -body { mkTriangular 3 } -result {{1.0 1.0 1.0} {0. 1.0 1.0} {0. 0. 1.0}} test mkTriangular-2 "make triangular matrix" -match numbers -body { mkTriangular 3 "L" 2. } -result {{2. 0. 0.} {2. 2. 0.} {2. 2. 2.}} test mkBorder "make border matrix" -match numbers -body { mkBorder 5 } -result { {1.0 0.0 0.0 0.0 1.0} {0.0 1.0 0.0 0.0 0.5} {0.0 0.0 1.0 0.0 0.25} {0.0 0.0 0.0 1.0 0.125} {1.0 0.5 0.25 0.125 1.0}} test mkWilkinsonW- "make Wilkinson W- matrix" -match numbers -body { mkWilkinsonW- 5 } -result { {2.0 1.0 0.0 0.0 0.0} {1.0 1.0 1.0 0.0 0.0} {0.0 1.0 0.0 1.0 0.0} {0.0 0.0 1.0 -1.0 1.0} {0.0 0.0 0.0 1.0 -2.0}} test mkWilkinsonW+ "make Wilkinson W+ matrix" -match numbers -body { mkWilkinsonW+ 7 } -result { {3.0 1.0 0.0 0.0 0.0 0.0 0.0} {1.0 2.0 1.0 0.0 0.0 0.0 0.0} {0.0 1.0 1.0 1.0 0.0 0.0 0.0} {0.0 0.0 1.0 0.0 1.0 0.0 0.0} {0.0 0.0 0.0 1.0 1.0 1.0 0.0} {0.0 0.0 0.0 0.0 1.0 2.0 1.0} {0.0 0.0 0.0 0.0 0.0 1.0 3.0}} test det-1 "determinant" -match numbers -body { set a [mkBorder 5] set det [det $a] } -result {-0.328125} test det-2 "determinant" -match numbers -body { set a [mkWilkinsonW+ 5] set det [det $a] } -result {-4.0} test det-3 "determinant" -match numbers -body { set a [mkWilkinsonW- 5] set det [det $a] } -result {0.0} test det-4 "determinant with pre-computed decomposition" -match numbers -body { set a [mkWilkinsonW- 5] set ipiv [dgetrf a] set det [det $a $ipiv] } -result {0.0} #set ::tcl_precision 17 test largesteigen-1 "power method" -body { set a {{-261 209 -49} {-530 422 -98} {-800 631 -144}} set pm [largesteigen $a 1.e-8 200] set eigval [lindex $pm 0] set eigvec [lindex $pm 1] set res {} set expected {-0.2672612419124256177838 -0.5345224838248414656050 -0.8017837257372776305075} lappend res -eigvec [areClose $expected $eigvec 1.e-8] lappend res -eigval [areClose 10.0 $eigval 1.e-8] } -result {-eigvec 1 -eigval 1} test largesteigen-2 "power method" -body { set a {{-261 209 -49} {-530 422 -98} {-800 631 -144}} set pm [largesteigen $a] set eigval [lindex $pm 0] set eigvec [lindex $pm 1] set res {} set expected {-0.2672612419124256177838 -0.5345224838248414656050 -0.8017837257372776305075} lappend res -eigvec [areClose $expected $eigvec 1.e-5] lappend res -eigval [areClose 10.0 $eigval 1.e-5] } -result {-eigvec 1 -eigval 1} test largesteigen-3 "power method" -body { set a {{0.0 0.0 0.0} {0.0 0.0 0.0} {0.0 0.0 0.0}} catch { set pm [largesteigen $a] } errmsg set errmsg } -result {Cannot continue power method : matrix is singular} # Additional tests: procedures by Federico Ferri #source ferri/ferri.test set ::tcl_precision $old_precision if {$regular==1} then { testsuiteCleanup } else { tcltest::cleanupTests }