# ::math::integrate -- # # calculate the area under a curve defined by a # set of (x,y) data pairs. the x data must increase # monotonically throughout the data set for the # calculation to be meaningful, therefore the # monotonic condition is tested, and an error is thrown # if the x value is found to be decreasing. # # Arguments: # (x,y) pairs in list format # # Results: # Area and error bound # (calculation is "Simpson's rule") # # at least 5 data pairs are required, and if the number # of data pairs is even, a padding value of (x0,0) will # be added. # # 04-13-2000 -- by: Phil Ehrens at The LIGO Lab namespace eval math {} proc ::math::integrate { xy_pairs } { set length [ llength $xy_pairs ] if { $length < 10 } { return -code error "at least 5 x,y pairs must be given" } ;## are we dealing with x,y pairs? if { [ expr $length % 2 ] } { return -code error "unmatched xy pair in input" } ;## are there an even number of pairs? Augment. if { ! [ expr $length % 4 ] } { set xy_pairs [ concat [ lindex $xy_pairs 0 ] 0 $xy_pairs ] } set x0 [ lindex $xy_pairs 0 ] set x1 [ lindex $xy_pairs 2 ] set xn [ lindex $xy_pairs end-1 ] set xnminus1 [ lindex $xy_pairs end-3 ] if { $x1 < $x0 } { return -code error "monotonicity broken by x1" } if { $xn < $xnminus1 } { return -code error "monotonicity broken by xn" } ;## handle the assymetrical elements 0, n, and n-1. set sum [ expr {[ lindex $xy_pairs 1 ] + [ lindex $xy_pairs end ]} ] set sum [ expr {$sum + (4*[ lindex $xy_pairs end-2 ])} ] set data [ lrange $xy_pairs 2 end-4 ] set xmax $x1 set i 1 foreach {x1 y1 x2 y2} $data { incr i if { $x1 < $xmax } { return -code error "monotonicity broken by x$i" } set xmax $x1 incr i if { $x2 < $xmax } { return -code error "monotonicity broken by x$i" } set xmax $x2 set sum [ expr {$sum + (4*$y1) + (2*$y2)} ] } if { $xmax > $xnminus1 } { return -code error "monotonicity broken by xn-1" } set h [ expr { ( $xn - $x0 ) / $i } ] set area [ expr { ( $h / 3.0 ) * $sum } ] set err_bound [ expr { ( ( $xn - $x0 ) / 180.0 ) * pow($h,4) * $xn } ] return [ list $area $err_bound ] }
Arjen Markus I have a set of procedures ready that will allow one to integrate functions and sets of ordinary differential equations. I just proposed adding this to the Tcllib.