Arjen Markus At the Third European Tcl/Tk Users Meeting I presented a "mathematical workbench". This page shows a small example of this work. The idea is described in the abstract:
A handheld calculator is a great way to do all kinds of ad hoc calculations. You do not write a C or Fortran program with hard-coded numbers to add them for balancing your books. In a similar way doing mathematics - for instance solve some geometrical problem - requires a handheld calculator suitable for that type of calculations.
The essential ingredients are an interactive program that interprets dedicated commands, and a few conventions to make its use more or less uniform.
This paper describes the application of Tkcon and such a set of conventions to provide the interface. It illustrates the concepts with three different mathematical tools: complex numbers, ordinary differential equations and (statistical) optimisation.
The script below contains a few commands that illustrate the idea compactly:
If you run the script from within Tkcon or a similar shell, you can experiment with it.
(Note: the full workbench contains much more convenient commands)
The workbench is available at the Starkit Distribution Archive [L1 ].
AM A small but significant improvement: xderiv_impl now uses the original function, so that you can use it to calculate the second-order derivative and so on! [Did this improvement make it into the latest starkit?]
5Jan2011 JM Is there any demo on the starkit? if so, how is it named?
AM (7 january 2011) I will have to brush off the code - if you are interested, I can do so, but I have not really expanded it of late. The idea still interests me, but with Tcllib and Tklib there is a whole bunch of quite useable modules available.
JM (7 january 2011) Thanks, for now I will look through your other posts, which are very interesting.
# functions.tcl -- # # Package for analysing real functions # (sample Workbench module) # # Notes: # This package provides basic analysis functionality for real # functions of one variable. # # Version information: # version 0.1: initial implementation, july 2002 package provide Functions 0.1 namespace eval ::Workbench { variable nextID 0 # uniqueID -- # Create a unique ID (private) # # Arguments: # expression Expression using "x" as independent variable # evaluating to the function value # # Result: # Name of a new command implementing the function # # Side effect: # Create a new command that takes one argument, x, and # returns the function value # proc uniqueID {typename} { variable nextID incr nextID return "${typename}##$nextID" } } ;# End of namespace namespace eval ::Functions { namespace export func deriv # func -- # Create a new function # # Arguments: # expression Expression using "x" as independent variable # evaluating to the function value # # Result: # Name of a new command implementing the function # # Side effect: # Create a new command that takes one argument, x, and # returns the function value # proc func {expression} { set name [::Workbench::uniqueID "X-FUNCTION"] interp alias {} $name {} [namespace current]::xfunc_impl $expression return $name } # xfunc_impl -- # Implementation of an "x function" # # Arguments: # expression Expression using "x" (hidden via [interp alias]) # x Independent variable # # Result: # Function value # proc xfunc_impl {expression x} { expr $expression } # deriv -- # Create a new function that evaluates to the derivative of the given # function # # Arguments: # funcname Name (!) of the function # step Step for the numerical derivation # # Result: # Name of a new command implementing the function's derivative # # Side effect: # Create a new command that takes one argument, x, and # returns the original function's derivative # proc deriv {funcname {step 0.01} } { upvar $funcname fname set name [::Workbench::uniqueID "X-DERIVATIVE"] set expression [lindex [interp alias {} $fname] 1] interp alias {} $name {} [namespace current]::xderiv_impl $fname [expr {$step*0.5}] return $name } # xderiv_impl -- # Implementation of the derivative of an "x function" # # Arguments: # fname Name (!) of the function # step Step size for numerical derivation # xv Independent variable # Result: # Value of derivative # # Note: # By using the # proc xderiv_impl {fname step xv} { set x [expr {$xv-$step}] set fx1 [$fname $x] set x [expr {$xv+$step}] set fx2 [$fname $x] expr {($fx2-$fx1)/(2.0*$step)} } } ;# End of namespace # # Import the functions procedures # namespace import ::Functions::* # # Simple demo # if { [file tail [info script]] == [file tail $::argv0] } { puts "Simply a parabola: y = x^2" set f [func {$x*$x}] set df [deriv f] set x 0.0 while { $x < 10.1 } { puts "[$f $x] [$df $x]" set x [expr {$x+1.0}] } puts "A more complex function" set f [func {sin($x)*$x}] set df [deriv f] set x 0.0 while { $x < 10.1 } { puts "[$f $x] [$df $x]" set x [expr {$x+0.1}] } }