misc.tcl
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 package require Tcl 8.2 ;
00013 namespace ::math {
00014 }
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 ret ::math::cov (type val1 , type val2 , type args) {
00029 set sum [ expr { $val1+$val2 } ]
00030 set N [ expr { [ llength $args ] + 2 } ]
00031 foreach val $args {
00032 set sum [ expr { $sum+$val } ]
00033 }
00034 set mean [ expr { $sum/$N } ]
00035 set sigma_sq 0
00036 foreach val [ concat $val1 $val2 $args ] {
00037 set sigma_sq [ expr { $sigma_sq+pow(($val-$mean),2) } ]
00038 }
00039 set sigma_sq [ expr { $sigma_sq/($N-1) } ]
00040 set sigma [ expr { sqrt($sigma_sq) } ]
00041 if { $mean != 0.0 } {
00042 set cov [ expr { ($sigma/$mean)*100 } ]
00043 } else {
00044 return -code error -errorinfo "Cov undefined for data with zero mean" -errorcode {ARITH DOMAIN}
00045 }
00046 set cov
00047 }
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059 ret ::math::fibonacci (type n) {
00060 if { $n == 0 } {
00061 return 0
00062 } else {
00063 set prev0 0
00064 set prev1 1
00065 for {set i 1} {$i < $n} {incr i} {
00066 set tmp $prev1
00067 incr prev1 $prev0
00068 set prev0 $tmp
00069 }
00070 return $prev1
00071 }
00072 }
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092 ret ::math::integrate ( type xy_, type pairs ) {
00093
00094 set length [ llength $xy_pairs ]
00095
00096 if { $length < 10 } {
00097 return -code error "at least 5 x,y pairs must be given"
00098 }
00099
00100 ;## are we dealing with x,y pairs?
00101 if { [ expr {$length % 2} ] } {
00102 return -code error "unmatched xy pair in input"
00103 }
00104
00105 ;## are there an even number of pairs? Augment.
00106 if { ! [ expr {$length % 4} ] } {
00107 set xy_pairs [ concat [ lindex $xy_pairs 0 ] 0 $xy_pairs ]
00108 }
00109 set x0 [ lindex $xy_pairs 0 ]
00110 set x1 [ lindex $xy_pairs 2 ]
00111 set xn [ lindex $xy_pairs end-1 ]
00112 set xnminus1 [ lindex $xy_pairs end-3 ]
00113
00114 if { $x1 < $x0 } {
00115 return -code error "monotonicity broken by x1"
00116 }
00117
00118 if { $xn < $xnminus1 } {
00119 return -code error "monotonicity broken by xn"
00120 }
00121
00122 ;## handle the assymetrical elements 0, n, and n-1.
00123 set sum [ expr {[ lindex $xy_pairs 1 ] + [ lindex $xy_pairs end ]} ]
00124 set sum [ expr {$sum + (4*[ lindex $xy_pairs end-2 ])} ]
00125
00126 set data [ lrange $xy_pairs 2 end-4 ]
00127
00128 set xmax $x1
00129 set i 1
00130 foreach {x1 y1 x2 y2} $data {
00131 incr i
00132 if { $x1 < $xmax } {
00133 return -code error "monotonicity broken by x$i"
00134 }
00135 set xmax $x1
00136 incr i
00137 if { $x2 < $xmax } {
00138 return -code error "monotonicity broken by x$i"
00139 }
00140 set xmax $x2
00141 set sum [ expr {$sum + (4*$y1) + (2*$y2)} ]
00142 }
00143
00144 if { $xmax > $xnminus1 } {
00145 return -code error "monotonicity broken by xn-1"
00146 }
00147
00148 set h [ expr { ( $xn - $x0 ) / $i } ]
00149 set area [ expr { ( $h / 3.0 ) * $sum } ]
00150 set err_bound [ expr { ( ( $xn - $x0 ) / 180.0 ) * pow($h,4) * $xn } ]
00151 return [ list $area $err_bound ]
00152 }
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165 ret ::math::max (type val , type args) {
00166 set max $val
00167 foreach val $args {
00168 if { $val > $max } {
00169 set max $val
00170 }
00171 }
00172 set max
00173 }
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186 ret ::math::mean (type val , type args) {
00187 set sum $val
00188 set N [ expr { [ llength $args ] + 1 } ]
00189 foreach val $args {
00190 set sum [ expr { $sum + $val } ]
00191 }
00192 set mean [expr { double($sum) / $N }]
00193 }
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206 ret ::math::min (type val , type args) {
00207 set min $val
00208 foreach val $args {
00209 if { $val < $min } {
00210 set min $val
00211 }
00212 }
00213 set min
00214 }
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227 ret ::math::product (type val , type args) {
00228 set prod $val
00229 foreach val $args {
00230 set prod [ expr { $prod*$val } ]
00231 }
00232 set prod
00233 }
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249 ret ::math::random (type args) {
00250 set num [expr {rand()}]
00251 if { [llength $args] == 0 } {
00252 return $num
00253 } elseif { [llength $args] == 1 } {
00254 return [expr {int($num * [lindex $args 0])}]
00255 } elseif { [llength $args] == 2 } {
00256 foreach {lower upper} $args break
00257 set range [expr {$upper - $lower}]
00258 return [expr {int($num * $range) + $lower}]
00259 } else {
00260 set fn [lindex [info level 0] 0]
00261 error "wrong # args: should be \"$fn ?value1? ?value2?\""
00262 }
00263 }
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277 ret ::math::sigma (type val1 , type val2 , type args) {
00278 set sum [ expr { $val1+$val2 } ]
00279 set N [ expr { [ llength $args ] + 2 } ]
00280 foreach val $args {
00281 set sum [ expr { $sum+$val } ]
00282 }
00283 set mean [ expr { $sum/$N } ]
00284 set sigma_sq 0
00285 foreach val [ concat $val1 $val2 $args ] {
00286 set sigma_sq [ expr { $sigma_sq+pow(($val-$mean),2) } ]
00287 }
00288 set sigma_sq [ expr { $sigma_sq/($N-1) } ]
00289 set sigma [ expr { sqrt($sigma_sq) } ]
00290 set sigma
00291 }
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306 ret ::math::stats (type val1 , type val2 , type args) {
00307 set sum [ expr { $val1+$val2 } ]
00308 set N [ expr { [ llength $args ] + 2 } ]
00309 foreach val $args {
00310 set sum [ expr { $sum+$val } ]
00311 }
00312 set mean [ expr { $sum/$N } ]
00313 set sigma_sq 0
00314 foreach val [ concat $val1 $val2 $args ] {
00315 set sigma_sq [ expr { $sigma_sq+pow(($val-$mean),2) } ]
00316 }
00317 set sigma_sq [ expr { $sigma_sq/($N-1) } ]
00318 set sigma [ expr { sqrt($sigma_sq) } ]
00319 set cov [ expr { ($sigma/$mean)*100 } ]
00320 return [ list $mean $sigma $cov ]
00321 }
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334 ret ::math::sum (type val , type args) {
00335 set sum $val
00336 foreach val $args {
00337 set sum [ expr { $sum+$val } ]
00338 }
00339 set sum
00340 }
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360 ret ::math::expectDouble ( type arg ) {
00361 return [format "expected a floating-point number but found \"%.50s\"" $arg]
00362 }
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382 ret ::math::expectInteger ( type arg ) {
00383 return [format "expected an integer but found \"%.50s\"" $arg]
00384 }
00385
00386