home *** CD-ROM | disk | FTP | other *** search
/ H4CK3R 5 / hacker05 / 05_HACK_05.ISO / programacao / freewrap / TCLLIBsampleApp.exe / sample / tcllib / tcllib1.0 / math / math.tcl next >
Encoding:
Text File  |  2001-08-17  |  7.7 KB  |  339 lines

  1. # math.tcl --
  2. #
  3. #    Collection of math functions.
  4. #
  5. # Copyright (c) 1998-2000 by Ajuba Solutions.
  6. #
  7. # See the file "license.terms" for information on usage and redistribution
  8. # of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  9. # RCS: @(#) $Id: math.tcl,v 1.9 2001/08/02 16:38:06 andreas_kupries Exp $
  10.  
  11. package require Tcl 8.2        ;# uses [lindex $l end-$integer]
  12. namespace eval ::math {
  13. }
  14.  
  15. # ::math::cov --
  16. #
  17. #    Return the coefficient of variation of three or more values
  18. #
  19. # Arguments:
  20. #    val1    first value
  21. #    val2    second value
  22. #    args    other values
  23. #
  24. # Results:
  25. #    cov    coefficient of variation expressed as percent value
  26.  
  27. proc ::math::cov {val1 val2 args} {
  28.      set sum [ expr { $val1+$val2 } ]
  29.      set N [ expr { [ llength $args ] + 2 } ]
  30.      foreach val $args {
  31.         set sum [ expr { $sum+$val } ]
  32.      }
  33.      set mean [ expr { $sum/$N } ]
  34.      set sigma_sq 0
  35.      foreach val [ concat $val1 $val2 $args ] {
  36.         set sigma_sq [ expr { $sigma_sq+pow(($val-$mean),2) } ]
  37.      }
  38.      set sigma_sq [ expr { $sigma_sq/($N-1) } ] 
  39.      set sigma [ expr { sqrt($sigma_sq) } ]
  40.      set cov [ expr { ($sigma/$mean)*100 } ]
  41.      set cov
  42. }
  43.  
  44. # ::math::fibonacci --
  45. #
  46. #    Return the n'th fibonacci number.
  47. #
  48. # Arguments:
  49. #    n    The index in the sequence to compute.
  50. #
  51. # Results:
  52. #    fib    The n'th fibonacci number.
  53.  
  54. proc ::math::fibonacci {n} {
  55.     if { $n == 0 } {
  56.     return 0
  57.     } else {
  58.     set prev0 0
  59.     set prev1 1
  60.     for {set i 1} {$i < $n} {incr i} {
  61.         set tmp $prev1
  62.         incr prev1 $prev0
  63.         set prev0 $tmp
  64.     }
  65.     return $prev1
  66.     }
  67. }
  68.  
  69. # ::math::integrate --
  70. #
  71. #    calculate the area under a curve defined by a set of (x,y) data pairs.
  72. #    the x data must increase monotonically throughout the data set for the 
  73. #    calculation to be meaningful, therefore the monotonic condition is
  74. #    tested, and an error is thrown if the x value is found to be
  75. #    decreasing.
  76. #
  77. # Arguments:
  78. #    xy_pairs    list of x y pairs (eg, 0 0 10 10 20 20 ...); at least 5
  79. #            data pairs are required, and if the number of data
  80. #            pairs is even, a padding value of (x0, 0) will be
  81. #            added.
  82. # Results:
  83. #    result        A two-element list consisting of the area and error
  84. #            bound (calculation is "Simpson's rule")
  85.  
  86. proc ::math::integrate { xy_pairs } {
  87.      
  88.      set length [ llength $xy_pairs ]
  89.      
  90.      if { $length < 10 } {
  91.         return -code error "at least 5 x,y pairs must be given"
  92.      }   
  93.      
  94.      ;## are we dealing with x,y pairs?
  95.      if { [ expr {$length % 2} ] } {
  96.         return -code error "unmatched xy pair in input"
  97.      }
  98.      
  99.      ;## are there an even number of pairs?  Augment.
  100.      if { ! [ expr {$length % 4} ] } {
  101.         set xy_pairs [ concat [ lindex $xy_pairs 0 ] 0 $xy_pairs ]
  102.      }
  103.      set x0   [ lindex $xy_pairs 0     ]
  104.      set x1   [ lindex $xy_pairs 2     ]
  105.      set xn   [ lindex $xy_pairs end-1 ]
  106.      set xnminus1 [ lindex $xy_pairs end-3 ]
  107.     
  108.      if { $x1 < $x0 } {
  109.         return -code error "monotonicity broken by x1"
  110.      }
  111.  
  112.      if { $xn < $xnminus1 } {
  113.         return -code error "monotonicity broken by xn"
  114.      }   
  115.      
  116.      ;## handle the assymetrical elements 0, n, and n-1.
  117.      set sum [ expr {[ lindex $xy_pairs 1 ] + [ lindex $xy_pairs end ]} ]
  118.      set sum [ expr {$sum + (4*[ lindex $xy_pairs end-2 ])} ]
  119.  
  120.      set data [ lrange $xy_pairs 2 end-4 ]
  121.      
  122.      set xmax $x1
  123.      set i 1
  124.      foreach {x1 y1 x2 y2} $data {
  125.         incr i
  126.         if { $x1 < $xmax } {
  127.            return -code error "monotonicity broken by x$i"
  128.         }
  129.         set xmax $x1
  130.         incr i
  131.         if { $x2 < $xmax } {
  132.            return -code error "monotonicity broken by x$i"
  133.         }
  134.         set xmax $x2
  135.         set sum [ expr {$sum + (4*$y1) + (2*$y2)} ]
  136.      }   
  137.      
  138.      if { $xmax > $xnminus1 } {
  139.         return -code error "monotonicity broken by xn-1"
  140.      }   
  141.     
  142.      set h [ expr { ( $xn - $x0 ) / $i } ]
  143.      set area [ expr { ( $h / 3.0 ) * $sum } ]
  144.      set err_bound  [ expr { ( ( $xn - $x0 ) / 180.0 ) * pow($h,4) * $xn } ]  
  145.      return [ list $area $err_bound ]
  146. }
  147.  
  148. # ::math::max --
  149. #
  150. #    Return the maximum of two or more values
  151. #
  152. # Arguments:
  153. #    val    first value
  154. #    args    other values
  155. #
  156. # Results:
  157. #    max    maximum value
  158.  
  159. proc ::math::max {val args} {
  160.     set max $val
  161.     foreach val $args {
  162.     if { $val > $max } {
  163.         set max $val
  164.     }
  165.     }
  166.     set max
  167. }
  168.  
  169. # ::math::mean --
  170. #
  171. #    Return the mean of two or more values
  172. #
  173. # Arguments:
  174. #    val    first value
  175. #    args    other values
  176. #
  177. # Results:
  178. #    mean    arithmetic mean value
  179.  
  180. proc ::math::mean {val args} {
  181.     set sum $val
  182.     set N [ expr { [ llength $args ] + 1 } ]
  183.     foreach val $args {
  184.         set sum [ expr { $sum + $val } ]
  185.     }
  186.     set mean [expr { double($sum) / $N }]
  187. }
  188.  
  189. # ::math::min --
  190. #
  191. #    Return the minimum of two or more values
  192. #
  193. # Arguments:
  194. #    val    first value
  195. #    args    other values
  196. #
  197. # Results:
  198. #    min    minimum value
  199.  
  200. proc ::math::min {val args} {
  201.     set min $val
  202.     foreach val $args {
  203.     if { $val < $min } {
  204.         set min $val
  205.     }
  206.     }
  207.     set min
  208. }
  209.  
  210. # ::math::product --
  211. #
  212. #    Return the product of one or more values
  213. #
  214. # Arguments:
  215. #    val    first value
  216. #    args    other values
  217. #
  218. # Results:
  219. #    prod     product of multiplying all values in the list
  220.  
  221. proc ::math::product {val args} {
  222.     set prod $val
  223.     foreach val $args {
  224.         set prod [ expr { $prod*$val } ]
  225.     }
  226.     set prod
  227. }
  228.  
  229. # ::math::random --
  230. #
  231. #    Return a random number in a given range.
  232. #
  233. # Arguments:
  234. #    args    optional arguments that specify the range within which to
  235. #        choose a number:
  236. #            (null)        choose a number between 0 and 1
  237. #            val        choose a number between 0 and val
  238. #            val1 val2    choose a number between val1 and val2
  239. #
  240. # Results:
  241. #    num    a random number in the range.
  242.  
  243. proc ::math::random {args} {
  244.     set num [expr {rand()}]
  245.     if { [llength $args] == 0 } {
  246.     return $num
  247.     } elseif { [llength $args] == 1 } {
  248.     return [expr {int($num * [lindex $args 0])}]
  249.     } elseif { [llength $args] == 2 } {
  250.     foreach {lower upper} $args break
  251.     set range [expr {$upper - $lower}]
  252.     return [expr {int($num * $range) + $lower}]
  253.     } else {
  254.     set fn [lindex [info level 0] 0]
  255.     error "wrong # args: should be \"$fn ?value1? ?value2?\""
  256.     }
  257. }
  258.  
  259. # ::math::sigma --
  260. #
  261. #    Return the standard deviation of three or more values
  262. #
  263. # Arguments:
  264. #    val1    first value
  265. #    val2    second value
  266. #    args    other values
  267. #
  268. # Results:
  269. #    sigma    population standard deviation value
  270.  
  271. proc ::math::sigma {val1 val2 args} {
  272.      set sum [ expr { $val1+$val2 } ]
  273.      set N [ expr { [ llength $args ] + 2 } ]
  274.      foreach val $args {
  275.         set sum [ expr { $sum+$val } ]
  276.      }
  277.      set mean [ expr { $sum/$N } ]
  278.      set sigma_sq 0
  279.      foreach val [ concat $val1 $val2 $args ] {
  280.         set sigma_sq [ expr { $sigma_sq+pow(($val-$mean),2) } ]
  281.      }
  282.      set sigma_sq [ expr { $sigma_sq/($N-1) } ] 
  283.      set sigma [ expr { sqrt($sigma_sq) } ]
  284.      set sigma
  285. }     
  286.  
  287. # ::math::stats --
  288. #
  289. #    Return the mean, standard deviation, and coefficient of variation as
  290. #    percent, as a list.
  291. #
  292. # Arguments:
  293. #    val1    first value
  294. #    val2    first value
  295. #    args    all other values
  296. #
  297. # Results:
  298. #    {mean stddev coefvar}
  299.  
  300. proc ::math::stats {val1 val2 args} {
  301.      set sum [ expr { $val1+$val2 } ]
  302.      set N [ expr { [ llength $args ] + 2 } ]
  303.      foreach val $args {
  304.         set sum [ expr { $sum+$val } ]
  305.      }
  306.      set mean [ expr { $sum/$N } ]
  307.      set sigma_sq 0
  308.      foreach val [ concat $val1 $val2 $args ] {
  309.         set sigma_sq [ expr { $sigma_sq+pow(($val-$mean),2) } ]
  310.      }
  311.      set sigma_sq [ expr { $sigma_sq/($N-1) } ] 
  312.      set sigma [ expr { sqrt($sigma_sq) } ]
  313.      set cov [ expr { ($sigma/$mean)*100 } ]
  314.      return [ list $mean $sigma $cov ]
  315. }
  316.  
  317. # ::math::sum --
  318. #
  319. #    Return the sum of one or more values
  320. #
  321. # Arguments:
  322. #    val    first value
  323. #    args    all other values
  324. #
  325. # Results:
  326. #    sum    arithmetic sum of all values in args
  327.  
  328. proc ::math::sum {val args} {
  329.     set sum $val
  330.     foreach val $args {
  331.         set sum [ expr { $sum+$val } ]
  332.     }
  333.     set sum
  334. }
  335.  
  336. package provide math 1.1
  337.