From d3304f5ae40f3b69cef0bceb90f7803e817db094 Mon Sep 17 00:00:00 2001 From: dkf Date: Sun, 26 Nov 2006 12:52:55 +0000 Subject: More bits and pieces of the TIP#174 implementation --- ChangeLog | 9 ++- doc/mathop.n | 210 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ tests/mathop.test | 184 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 401 insertions(+), 2 deletions(-) create mode 100644 doc/mathop.n create mode 100644 tests/mathop.test diff --git a/ChangeLog b/ChangeLog index 4991ee1..7ff29b2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,11 +1,16 @@ +2006-11-26 Donal K. Fellows + + * tests/mathop.test, doc/mathop.n: More bits and pieces of the TIP#174 + implementation. Note that the test suite is not yet complete. + 2006-11-26 Daniel Steffen - * tcl.m4 (Linux): --enable-64bit support. [Patch 1597389], [Bug 1230558] + * tcl.m4 (Linux): --enable-64bit support. [Patch 1597389] [Bug 1230558] * configure: autoconf-2.59 2006-11-25 Donal K. Fellows - TIP#269 IMPLEMENTATION + TIP#174 IMPLEMENTATION * generic/tclMathOp.c (new file): Completed the implementation of the interpreted versions of all the tcl::mathop commands. Moved to a new diff --git a/doc/mathop.n b/doc/mathop.n new file mode 100644 index 0000000..1dbd022 --- /dev/null +++ b/doc/mathop.n @@ -0,0 +1,210 @@ +`\" -*- nroff -*- +`\" Copyright (c) 2006 Donal K. Fellows. +`\" +`\" See the file "license.terms" for information on usage and redistribution +`\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +`\" +`\" RCS: @(#) $Id: mathop.n,v 1.1 2006/11/26 12:52:55 dkf Exp $ +`\" +.so man.macros +.TH mathfunc n 8.5 Tcl "Tcl Mathematical Operator Commands" +.BS +`\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +mathop \- Mathematical operators as Tcl commands +.SH SYNOPSIS +package require \fBTcl 8.5\fR +.sp +\fB::tcl::mathop::!\fR \fIarg\fR +.br +\fB::tcl::mathop::~\fR \fIarg\fR +.br +\fB::tcl::mathop::+\fR ?\fIarg\fR ...? +.br +\fB::tcl::mathop::\-\fR \fIarg\fR ?\fIarg\fR ...? +.br +\fB::tcl::mathop::*\fR ?\fIarg\fR ...? +.br +\fB::tcl::mathop::/\fR \fIarg\fR ?\fIarg\fR ...? +.br +\fB::tcl::mathop::%\fR \fIarg arg\fR +.br +\fB::tcl::mathop::**\fR ?\fIarg\fR ...? +.br +\fB::tcl::mathop::&\fR ?\fIarg\fR ...? +.br +\fB::tcl::mathop::|\fR ?\fIarg\fR ...? +.br +\fB::tcl::mathop::^\fR ?\fIarg\fR ...? +.br +\fB::tcl::mathop::<<\fR \fIarg arg\fR +.br +\fB::tcl::mathop::>>\fR \fIarg arg\fR +.br +\fB::tcl::mathop::==\fR ?\fIarg\fR ...? +.br +\fB::tcl::mathop::!=\fR \fIarg arg\fR +.br +\fB::tcl::mathop::<\fR ?\fIarg\fR ...? +.br +\fB::tcl::mathop::<=\fR ?\fIarg\fR ...? +.br +\fB::tcl::mathop::=>\fR ?\fIarg\fR ...? +.br +\fB::tcl::mathop::>\fR ?\fIarg\fR ...? +.br +\fB::tcl::mathop::eq\fR ?\fIarg\fR ...? +.br +\fB::tcl::mathop::ne\fR \fIarg arg\fR +.br +\fB::tcl::mathop::in\fR \fIarg list\fR +.br +\fB::tcl::mathop::ni\fR \fIarg list\fR +.sp +.BE +.SH DESCRIPTION +.PP +The commands in the \fB::tcl::mathop\fR namespace implement the same set of +operations as supported by the \fBexpr\fR command. All are exported from the +namespace, but are not imported into any other namespace by default. Note that +renaming, reimplementing or deleting any of the commands in the namespace does +\fInot\fR alter the way that the \fBexpr\fR command behaves. +.PP +The following operator commands are supported: +.DS +.ta 2c 4c 6c 8c +\fB~\fR \fB!\fR \fB+\fR \fB\-\fR \fB*\fR +\fB/\fR \fB%\fR \fB**\fR \fB&\fR \fB|\fR +\fB^\fR \fB>>\fR \fB<<\fR \fB==\fR \fBeq\fR +\fB!=\fR \fBne\fR \fB<\fR \fB<=\fR \fB>\fR +\fB>=\fR \fBin\fR \fBni\fR +.DE +.PP +.TP +\fB~\fR \fIarg\fR +Returns the bit-wise negation of \fIarg\fR. \fIArg\fR may be an integer of any +size. +.TP +\fB!\fR \fIarg\fR +Returns the boolean negation of \fIarg\fR. \fIArg\fR may be any numeric value +or any other form of boolean value. +.TP +\fB+\fR ?\fIarg\fR ...? +Returns the sum of arbitrarily many arguments. Each \fIarg\fR may be any +numeric value. If no arguments are given, the result will be zero. +.TP +\fB\-\fR \fIarg\fR ?\fIarg\fR ...? +Returns the either the negation of the first argument (if only one argument is +given) or the result of subtracting arbitrarily many additional arguments from +the first argument. Each \fIarg\fR may be any numeric value. At least one +argument must be given. +.TP +\fB*\fR ?\fIarg\fR ...? +Returns the product of arbitrarily many arguments. Each \fIarg\fR may be any +numeric value. If no arguments are given, the result will be one. +.TP +\fB/\fR \fIarg\fR ?\fIarg\fR ...? +Returns the either the reciprocal of the first argument (if only one argument +is given) or the result of dividing the first argument by arbitrarily many +additional arguments. Each \fIarg\fR may be any numeric value. At least one +argument must be given. +.TP +\fB%\fR \fIarg arg\fR +Returns the integral modulus of the first argument with respect to the +second. Each \fIarg\fR must have an integral value. +.TP +\fB**\fR ?\fIarg\fR ...? +Returns the result of raising each value to the power of the result of +recursively operating on the result of processing the following +arguments, so \fB** 2 3 4\fR is the same as \fB** 2 [** 3 4]\fR. Each +\fIarg\fR may be any numeric value. If no arguments are given, the result will +be one, and if only one argument is given, the result will be that argument. +.TP +\fB&\fR ?\fIarg\fR ...? +Returns the bit-wise AND of each of the arbitrarily many arguments. Each +\fIarg\fR must have an integral value. If no arguments are given, the result +will be minus one. +.TP +\fB|\fR ?\fIarg\fR ...? +Returns the bit-wise OR of each of the arbitrarily many arguments. Each +\fIarg\fR must have an integral value. If no arguments are given, the result +will be zero. +.TP +\fB^\fR ?\fIarg\fR ...? +Returns the bit-wise XOR of each of the arbitrarily many arguments. Each +\fIarg\fR must have an integral value. If no arguments are given, the result +will be zero. +.TP +\fB<<\fR \fIarg arg\fR +Returns the result of shifting the first argument left by the number of bits +specified in the second argument. Each \fIarg\fR must have an integral value. +.TP +\fB>>\fR \fIarg arg\fR +Returns the result of shifting the first argument right by the number of bits +specified in the second argument. Each \fIarg\fR must have an integral value. +.TP +\fB==\fR ?\fIarg\fR ...? +Returns whether each argument is equal to the arguments on each side of it in +the sense of the \fBexpr\fR == operator (\fIi.e.\fR, numeric comparison if +possible). If fewer than two arguments are given, this operation always +returns a true value. +.TP +\fBeq\fR ?\fIarg\fR ...? +Returns whether each argument is equal to the arguments on each side of it +using exact string comparison. If fewer than two arguments are given, this +operation always returns a true value. +.TP +\fB!=\fR \fIarg arg\fR +Returns whether the two arguments are not equal to each other, in the sense of +the \fBexpr\fR != operator (\fIi.e.\fR, numeric comparison if possible). +.TP +\fBne\fR \fIarg arg\fR +Returns whether the two arguments are not equal to each other using exact +string comparison. +.TP +\fB<\fR ?\fIarg\fR ...? +Returns whether the arbitrarily-many arguments are ordered, with each argument +after the first having to be strictly more than the one preceding it. +Comparisons are performed preferentially on the numeric values. If fewer than +two arguments are present, this operation always returns a true value. +.TP +\fB<=\fR ?\fIarg\fR ...? +Returns whether the arbitrarily-many arguments are ordered, with each argument +after the first having to be equal to or more than the one preceding it. +Comparisons are performed preferentially on the numeric values. If fewer than +two arguments are present, this operation always returns a true value. +.TP +\fB>\fR ?\fIarg\fR ...? +Returns whether the arbitrarily-many arguments are ordered, with each argument +after the first having to be strictly less than the one preceding it. +Comparisons are performed preferentially on the numeric values. If fewer than +two arguments are present, this operation always returns a true value. +.TP +\fB>=\fR ?\fIarg\fR ...? +Returns whether the arbitrarily-many arguments are ordered, with each argument +after the first having to be equal to or less than the one preceding it. +Comparisons are performed preferentially on the numeric values. If fewer than +two arguments are present, this operation always returns a true value. +.TP +\fBin\fR \fIarg list\fR +Returns whether the value \fIarg\fR is present in the list \fIlist\fR. +.TP +\fBni\fR \fIarg list\fR +Returns whether the value \fIarg\fR is not present in the list \fIlist\fR. +.SH EXAMPLES +.CS +namespace path {::tcl::mathop ::tcl::mathfunc} + +set sum [\fB+\fR 1 2 3] + +set list {1 2 3 4 5 6} +set mean [\fB/\fR [\fB+\fR {expand}$list] [double [llength $list]]] + +set gotIt [\fBin\fR 3 $list] + +set inRange [\fB<=\fR 1 $x 5] +.CE +.SH "SEE ALSO" +expr(n), namespace(n) +.SH KEYWORDS +command, expression, operator diff --git a/tests/mathop.test b/tests/mathop.test new file mode 100644 index 0000000..9ad66f6 --- /dev/null +++ b/tests/mathop.test @@ -0,0 +1,184 @@ +# Commands covered: ::tcl::mathop::... +# +# This file contains a collection of tests for one or more of the Tcl built-in +# commands. Sourcing this file into Tcl runs the tests and generates output +# for errors. No output means no errors were found. +# +# Copyright (c) 2006 Donal K. Fellows +# +# See the file "license.terms" for information on usage and redistribution of +# this file, and for a DISCLAIMER OF ALL WARRANTIES. +# +# RCS: @(#) $Id: mathop.test,v 1.1 2006/11/26 12:52:55 dkf Exp $ + +if {[lsearch [namespace children] ::tcltest] == -1} { + package require tcltest 2.1 + namespace import -force ::tcltest::* +} + +# start of tests + +namespace eval ::testmathop { + namespace path ::tcl::mathop + + test mathop-1.1 {compiled +} { + } 0 + test mathop-1.2 {compiled +} { + 1 } 1 + test mathop-1.3 {compiled +} { + 1 2 } 3 + test mathop-1.4 {compiled +} { + 1 2 3 } 6 + test mathop-1.5 {compiled +} { + 1.0 2 3 } 6.0 + test mathop-1.6 {compiled +} { + 1 2 3.0 } 6.0 + test mathop-1.7 {compiled +} { + 100000000000 2 3 } 100000000005 + test mathop-1.8 {compiled +} { + 1 2 300000000000 } 300000000003 + test mathop-1.9 {compiled +} { + 1000000000000000000000 2 3 } 1000000000000000000005 + test mathop-1.10 {compiled +} { + 1 2 3000000000000000000000 } 3000000000000000000003 + test mathop-1.11 {compiled +: errors} -returnCodes error -body { + + x 0 + } -result {can't use non-numeric string as operand of "+"} + test mathop-1.12 {compiled +: errors} -returnCodes error -body { + + nan 0 + } -result {can't use non-numeric floating-point value as operand of "+"} + test mathop-1.13 {compiled +: errors} -returnCodes error -body { + + 0 x + } -result {can't use non-numeric string as operand of "+"} + test mathop-1.14 {compiled +: errors} -returnCodes error -body { + + 0 nan + } -result {can't use non-numeric floating-point value as operand of "+"} + test mathop-1.15 {compiled +: errors} -returnCodes error -body { + + 08 0 + } -result {can't use invalid octal number as operand of "+"} + test mathop-1.16 {compiled +: errors} -returnCodes error -body { + + 0 08 + } -result {can't use invalid octal number as operand of "+"} + test mathop-1.17 {compiled +: errors} -returnCodes error -body { + + 0 [error expectedError] + } -result expectedError + test mathop-1.18 {compiled +: argument processing order} -body { + # Bytecode compilation known buggy for 3+ arguments + list [catch { + + [set x 0] [incr x] NaN [incr x] [error expected] [incr x] + } msg] $msg $x + } -result {1 expected 2} -constraints knownBug + set op + + test mathop-1.19 {interpreted +} { $op } 0 + test mathop-1.20 {interpreted +} { $op 1 } 1 + test mathop-1.21 {interpreted +} { $op 1 2 } 3 + test mathop-1.22 {interpreted +} { $op 1 2 3 } 6 + test mathop-1.23 {interpreted +} { $op 1.0 2 3 } 6.0 + test mathop-1.24 {interpreted +} { $op 1 2 3.0 } 6.0 + test mathop-1.25 {interpreted +} { $op 100000000000 2 3 } 100000000005 + test mathop-1.26 {interpreted +} { $op 1 2 300000000000 } 300000000003 + test mathop-1.27 {interpreted +} { $op 1000000000000000000000 2 3 } 1000000000000000000005 + test mathop-1.28 {interpreted +} { $op 1 2 3000000000000000000000 } 3000000000000000000003 + test mathop-1.29 {interpreted +: errors} -returnCodes error -body { + $op x 0 + } -result {can't use non-numeric string as operand of "+"} + test mathop-1.30 {interpreted +: errors} -returnCodes error -body { + $op nan 0 + } -result {can't use non-numeric floating-point value as operand of "+"} + test mathop-1.31 {interpreted +: errors} -returnCodes error -body { + $op 0 x + } -result {can't use non-numeric string as operand of "+"} + test mathop-1.32 {interpreted +: errors} -returnCodes error -body { + $op 0 nan + } -result {can't use non-numeric floating-point value as operand of "+"} + test mathop-1.33 {interpreted +: errors} -returnCodes error -body { + $op 08 0 + } -result {can't use invalid octal number as operand of "+"} + test mathop-1.34 {interpreted +: errors} -returnCodes error -body { + $op 0 08 + } -result {can't use invalid octal number as operand of "+"} + test mathop-1.35 {interpreted +: errors} -returnCodes error -body { + $op 0 [error expectedError] + } -result expectedError + test mathop-1.36 {interpreted +: argument processing order} -body { + list [catch { + $op [set x 0] [incr x] NaN [incr x] [error expected] [incr x] + } msg] $msg $x + } -result {1 expected 2} + + test mathop-2.1 {compiled *} { * } 1 + test mathop-2.2 {compiled *} { * 2 } 2 + test mathop-2.3 {compiled *} { * 2 3 } 6 + test mathop-2.4 {compiled *} { * 2 3 4 } 24 + test mathop-2.5 {compiled *} { * 1.0 2 3 } 6.0 + test mathop-2.6 {compiled *} { * 1 2 3.0 } 6.0 + test mathop-2.7 {compiled *} { * 100000000000 2 3 } 600000000000 + test mathop-2.8 {compiled *} { * 1 2 300000000000 } 600000000000 + test mathop-2.9 {compiled *} { * 1000000000000000000000 2 3 } 6000000000000000000000 + test mathop-2.10 {compiled *} { * 1 2 3000000000000000000000 } 6000000000000000000000 + test mathop-2.11 {compiled *: errors} -returnCodes error -body { + * x 0 + } -result {can't use non-numeric string as operand of "*"} + test mathop-2.12 {compiled *: errors} -returnCodes error -body { + * nan 0 + } -result {can't use non-numeric floating-point value as operand of "*"} + test mathop-2.13 {compiled *: errors} -returnCodes error -body { + * 0 x + } -result {can't use non-numeric string as operand of "*"} + test mathop-2.14 {compiled *: errors} -returnCodes error -body { + * 0 nan + } -result {can't use non-numeric floating-point value as operand of "*"} + test mathop-2.15 {compiled *: errors} -returnCodes error -body { + * 08 0 + } -result {can't use invalid octal number as operand of "*"} + test mathop-2.16 {compiled *: errors} -returnCodes error -body { + * 0 08 + } -result {can't use invalid octal number as operand of "*"} + test mathop-2.17 {compiled *: errors} -returnCodes error -body { + * 0 [error expectedError] + } -result expectedError + test mathop-2.18 {compiled *: argument processing order} -body { + # Bytecode compilation known buggy for 3+ arguments + list [catch { + * [set x 0] [incr x] NaN [incr x] [error expected] [incr x] + } msg] $msg $x + } -result {1 expected 2} -constraints knownBug + set op * + test mathop-2.19 {interpreted *} { $op } 1 + test mathop-2.20 {interpreted *} { $op 2 } 2 + test mathop-2.21 {interpreted *} { $op 2 3 } 6 + test mathop-2.22 {interpreted *} { $op 2 3 4 } 24 + test mathop-2.23 {interpreted *} { $op 1.0 2 3 } 6.0 + test mathop-2.24 {interpreted *} { $op 1 2 3.0 } 6.0 + test mathop-2.25 {interpreted *} { $op 100000000000 2 3 } 600000000000 + test mathop-2.26 {interpreted *} { $op 1 2 300000000000 } 600000000000 + test mathop-2.27 {interpreted *} { $op 1000000000000000000000 2 3 } 6000000000000000000000 + test mathop-2.28 {interpreted *} { $op 1 2 3000000000000000000000 } 6000000000000000000000 + test mathop-2.29 {interpreted *: errors} -returnCodes error -body { + $op x 0 + } -result {can't use non-numeric string as operand of "*"} + test mathop-2.30 {interpreted *: errors} -returnCodes error -body { + $op nan 0 + } -result {can't use non-numeric floating-point value as operand of "*"} + test mathop-2.31 {interpreted *: errors} -returnCodes error -body { + $op 0 x + } -result {can't use non-numeric string as operand of "*"} + test mathop-2.32 {interpreted *: errors} -returnCodes error -body { + $op 0 nan + } -result {can't use non-numeric floating-point value as operand of "*"} + test mathop-2.33 {interpreted *: errors} -returnCodes error -body { + $op 08 0 + } -result {can't use invalid octal number as operand of "*"} + test mathop-2.34 {interpreted *: errors} -returnCodes error -body { + $op 0 08 + } -result {can't use invalid octal number as operand of "*"} + test mathop-2.35 {interpreted *: errors} -returnCodes error -body { + $op 0 [error expectedError] + } -result expectedError + test mathop-2.36 {interpreted *: argument processing order} -body { + list [catch { + $op [set x 0] [incr x] NaN [incr x] [error expected] [incr x] + } msg] $msg $x + } -result {1 expected 2} + + # TODO: ! ~ & | ^ % ** << >> - / == != < <= > >= eq ne in ni +} + +# cleanup +namespace delete ::testmathop +::tcltest::cleanupTests +return + +# Local Variables: +# mode: tcl +# End: -- cgit v0.12