The '''::tcl::mathfunc''' [namespace] provides commands for all the functions available in [[`[expr]`] <> ** See Also ** * [Additional math functions] ** Documentation ** [http://www.tcl.tk/man/tcl/TclCmd/mathfunc.htm%|%official reference]: [TIP] [http://tip.tcl.tk/232%|%232]: for the creation of the '''::[tcl::mathfunc]''' [namespace] [TIP] [http://www.tcl.tk/cgi-bin/tct/tip/174.html%|%174]: [Math Operators as Commands]. Presents various usage ideas. ** Description ** `::tcl::mathfunc` was made available in Tcl 8.5. Operators are in [tcl::mathop]. Note that changing or adding to these commands changes the set of functions available in [expr]. Also note that when your code is executing in a namespace other than the global one, you can define your own functions in the "''yourNS''::tcl::mathfunc" namespace. ** List of build-in functions ** %| Operation | Name | Args || Operation | Name | Args |% &| 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'' |||||& ** User-Defined Functions ** [TIP] [http://tip.tcl.tk/232%|%2323] provides for script-level creation of new functions, analagous to the [C] level [http://www.tcl.tk/man/tcl8.5/TclLib/CrtMathFnc.htm%|%Tcl_CreateMathFunc(3)]. [[`[expr]`] can be extended with new functions by adding commands to `::tcl::mathfunc`, or to a `tcl::matchfunc` child [namespace] of any other [namespace]. In the latter case, the additional [[`[expr]`] functions are only available to commands in the parent namespace. Functions can also be overriden or deleted from [[`[expr]`] by overriding or modifying the corresponding procedure in an appropriate `tcl::mathfunc` namespace. This functionality was previously not available, even at the [C] level. [[`[expr]`] function arguments are now just as flexible as those of Tcl [proc]s and [command]s. Variadic numbers of arguments are also possible, and illustrated by by the '''min()''' and '''max()''' functions. [[`[expr]`] functions can now also be called as procedures without using [[`[expr]`] at all. This is one way to to bypassing the problems discussed at [brace your expr-essions]. ** Definig New Functions at the [C] Level ** [AM]: On the [comp.lang.tcl%|%c.l.t] the other day [[is this as of May 2003?]], Martin Russell asked about how to define new math functions. If you want to do it without the help of [DKF]'s extension [[??]] and CrtLib [[ [critcl]'s critlib?]], then here is a recipe provided by [Pat Thoyts]: Something along these lines. ======c static Tcl_MathProc ArbLogProc; static int ArbLogProc(clientData, interp, args, resultPtr) ClientData clientData; Tcl_Interp *interp; /* current interpreter */ Tcl_Value *args; /* input arguments */ Tcl_Value *resultPtr; /* where to store the result */ { double b, n, d; b = args[0].doubleValue; n = args[1].doubleValue; /* do your maths and assign d to the result */ d = 1.0; resultPtr->type = TCL_DOUBLE; resultPtr->doubleValue = d; return TCL_OK; } ====== in your package initialisation... ======c Tcl_ValueType arblogArgs[2] = { TCL_DOUBLE, TCL_DOUBLE }; Tcl_CreateMathFunc(interp, "arblog", 2, arblogArgs, ArbLogProc, (ClientData)NULL); ====== ** Namespace-local `tcllib::mathfun` ** As of Tcl 8.5, if any namespace has a child namespace called ``tcl::mathfunc`` (notice that it's a relative name), [[`[expr]`] will look first in that namespace for available functions. I.e., either ::tcl::matfunc::f or [[namespace current]]::tcl::mathfunc::f can resolve f($x)). In the following example, any proc in `mynamesapce` can uset the `lobgase()` function. ====== namespace eval mynamespace { proc tcl::mathfunc::logbase {x b} { expr {log($x) / log($b)} } proc dostuff {} { ... expr {logbase($some_var,$some_other_var)} } } ====== [DKF]: A little helper for when writing custom functions: ====== proc func {name arguments body} { proc tcl::mathfunc::$name $arguments [list expr $body] } ====== This lets us write factorials as just this: ====== func fac x { $x<2 ? 1 : $x*fac($x-1) } ====== It can be useful to import functions from elsewhere into the local tcl::mathfunc namespace: ====== namespace eval tcl::mathfunc { namespace import ::otherns::* } ====== References: [http://groups.google.com/group/comp.lang.tcl/msg/f868deda4d3905ac%|%tcl talked badly (and high on reddit) ,comp.lang.tcl ,2008-02-15%|%] ** Using Math Functions in a Namespace ** [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. ** atan2 ** [AMG]: The man page for atan2 says that its arguments can't both be zero [http://www.tcl.tk/man/tcl8.6/TclCmd/mathfunc.htm#M10]. On one system I checked, `expr atan2(0,0)` returns `0.0`. On other systems, I suspect it may behave differently. Right? If so, shouldn't the implementation of atan2 check if both arguments are zero and throw an [error]? ** Non-Math mathfunc ** [bsg]: Non-math mathfunc: who says all mathfunc's have to be about math. Turning common tcl commands into functions can clean up conditional statements making them easier to read. Turn something like this: ====== if {[lindex $data [expr {2*$i +1}]] eq [lindex $items [expr {2*$itemno +1}]]} {break} ====== into this: ====== if {lindex($data, (2*$i+1)) eq lindex($items, (2*$itemno +1))} {break} ====== Another example: ====== if { $priv(mBar) eq [string range $menu 0 [expr {[string length $priv(mBar)] - 1}]]} { ... } if { $priv(mBar) eq substr($menu, 0, (strlen($priv(mBar)) - 1))} { ... } ====== Notice how it also eliminates the recursive [expr] calls. Here's what I've found useful so far: ====== namespace eval tcl::mathfunc { proc strlen {str} { ::string length $str } proc stridx {str index} { ::string index $str $index } proc substr {str first last} { ::string range $str $first $last } proc llength {list} { ::llength $list } proc lindex {list index args} { ::lindex $list $index {*}$args } proc lrange {list first last} { ::lrange $list $first $last } } ====== <> Command | Syntax | Mathematics