summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog9
-rw-r--r--doc/mathop.n210
-rw-r--r--tests/mathop.test184
3 files changed, 401 insertions, 2 deletions
diff --git a/ChangeLog b/ChangeLog
index 4991ee1..7ff29b2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,11 +1,16 @@
+2006-11-26 Donal K. Fellows <dkf@users.sf.net>
+
+ * 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 <das@users.sourceforge.net>
- * 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 <dkf@users.sf.net>
- 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: