Version 11 of mathfunc

Updated 2007-11-11 12:08:03 by dkf

AMG: TIP 232 [L1 ] creates the ::tcl::mathfunc namespace which contains commands implementing the [expr] math functions. The functions are documented in the mathfunc(n) man page [L2 ]. (Previous to TIP 232, the math functions were documented in expr(n).)


List of functions:

 Absolute value              abs    arg     Hypotenuse length             hypot  x y
 Arc cosine                  acos   arg     Coerce to word-sized integer  int    arg
 Arc sine                    asin   arg     Natural logarithm             log    arg
 Arc tangent                 atan   arg     Base-10 logarithm             log10  arg
 Four-quadrant arc tangent   atan2  y x     Greatest value                max    args
 Coerce to boolean           bool   arg     Least value                   min    args
 Round up to whole number    ceil   arg     Power                         pow    x y
 Cosine                      cos    arg     Random float in range [0,1)   rand
 Hyberbolic cosine           cosh   arg     Round to whole number         round  arg
 Coerce to float             double arg     Sine                          sin    arg
 Coerce to integer           entier arg     Hyperbolic sine               sinh   arg
 Exponential                 exp    arg     Square root                   sqrt   arg
 Round down to whole number  floor  arg     Seed random number generator  srand  arg
 Remainder                   fmod   x y     Tangent                       tan    arg
 Coerce to 64-bit integer    wide   arg     Hyperbolic tangent            tanh   arg
 Integer part of square root isqrt  arg

Thanks to TIP 232, you can create new functions without having to resort to Tcl_CreateMathFunc(3) [L3 ]. This makes it possible for pure Tcl scripts to extend [expr]. Also this makes it possible to rewrite or delete math functions, two things that were previously impossible even for extensions written in C. (I have written code that needed this functionality; I guess it's time to update it!)

This makes math function arguments much more flexible, just as flexible as those of Tcl procs and commands. One possibility worth noting is variadic numbers of arguments, a feature used by the shiny, new min() and max() functions.

One more neat trick is calling math functions without using [expr]; they're regular Tcl commands now. Combine this with TIP 174 Math Operators as Commands, and you can avoid using [expr] altogether, bypassing the problems discussed at brace your expr-essions.

See the TIP for more creative usage ideas.


DKF: If you like doing your computations the Lisp way, add this to your scripts:

  namespace path {::tcl::mathop ::tcl::mathfunc}

Now you can use all the above functions (and the math operators) as commands without qualification.


AMG: Here's a math function I sometimes find useful. It accepts three arguments, and it returns whichever of the three is between the other two. It's mostly useful to clamp a number to a range.

 proc ::tcl::mathfunc::mid {a b c} {
     lindex [lsort -real [list $a $b $c]] 1
 }

It can also be implemented as a bunch of [if]s, which is how I do it in C.

Here is one incorrect implementation you should watch out for:

 proc ::tcl::mathfunc::mid {a b c} {
     expr {max($a, min($b, $c))}
 }

This is what Allegro (include/allegro/base.h) has used since the dawn of time. :^( I'm reporting it now; hopefully it'll be fixed. If you're curious, see [L4 ] for my writeup.

KPV The folk algorithm for finding the middle number (or second highest in a longer list) is to take the max of the pair-wise mins. To wit:

  max(min($a,$b), min($a,$c), min($b,$c))

LV So what is an example of a case in which the second, incorrect, version of the algorithm fails? Answer: "incorrect_mid 1 0 0" returns 1. The problem is it doesn't (always) handle the case where two of the inputs are the same. Doh.

AMG: I thought the problem was that it doesn't handle the case of the first input being greater than the other two. This wasn't a problem for Allegro because everyone used its MID macro thusly: MID(minimum_value, value_to_clamp, maximum_value).


[ Category Command | Category Syntax | Category Mathematics ]