1# Commands covered: ::tcl::mathop::...
2#
3# This file contains a collection of tests for one or more of the Tcl built-in
4# commands. Sourcing this file into Tcl runs the tests and generates output
5# for errors. No output means no errors were found.
6#
7# Copyright © 2006 Donal K. Fellows
8# Copyright © 2006 Peter Spjuth
9#
10# See the file "license.terms" for information on usage and redistribution of
11# this file, and for a DISCLAIMER OF ALL WARRANTIES.
12
13if {"::tcltest" ni [namespace children]} {
14    package require tcltest 2.5
15    namespace import -force ::tcltest::*
16}
17
18# A namespace to test that operators are exported and that they
19# work when imported
20namespace eval ::testmathop2 {
21    namespace import ::tcl::mathop::*
22}
23
24# Helper to test math ops.
25# Test different invokation variants and see that they do the same thing.
26# Byte compiled / non byte compiled version
27# Shared / unshared arguments
28# Original / imported
29proc TestOp {op args} {
30    set results {}
31
32    # Non byte compiled version, shared args
33    if {[catch {::tcl::mathop::$op {*}$args} res]} {
34        append res " $::errorCode"
35    }
36    lappend results $res
37
38    # Non byte compiled version, unshared args
39    set cmd ::tcl::mathop::\$op
40    foreach arg $args {
41        append cmd " \[format %s [list $arg]\]"
42    }
43    if {[catch $cmd res]} {
44        append res " $::errorCode"
45    }
46    lappend results $res
47
48    # Non byte compiled imported
49    if {[catch {::testmathop2::$op {*}$args} res]} {
50        append res " $::errorCode"
51    }
52    lappend results [string map {testmathop2 tcl::mathop} $res]
53
54    # BC version
55    set argList1 {}
56    set argList2 {}
57    set argList3 {}
58    for {set t 0} {$t < [llength $args]} {incr t} {
59        lappend argList1 a$t
60        lappend argList2 \$a$t
61        lappend argList3 "\[format %s \$a$t\]"
62    }
63    # Shared args
64    proc _TestOp  $argList1 "::tcl::mathop::$op [join $argList2]"
65    # Unshared args
66    proc _TestOp2 $argList1 "::tcl::mathop::$op [join $argList3]"
67    # Imported
68    proc _TestOp3 $argList1 "::testmathop2::$op [join $argList2]"
69
70    set ::tcl_traceCompile 0  ;# Set to 2 to help with debug
71    if {[catch {_TestOp {*}$args} res]} {
72        append res " $::errorCode"
73    }
74    set ::tcl_traceCompile 0
75    lappend results $res
76
77    if {[catch {_TestOp2 {*}$args} res]} {
78        append res " $::errorCode"
79    }
80    lappend results $res
81
82    if {[catch {_TestOp3 {*}$args} res]} {
83        append res " $::errorCode"
84    }
85    lappend results [string map {testmathop2 tcl::mathop} $res]
86
87    # Check that they do the same
88    set len [llength $results]
89    for {set i 0} {$i < ($len - 1)} {incr i} {
90        set res1 [lindex $results $i]
91        set res2 [lindex $results $i+1]
92        if {$res1 ne $res2} {
93            return "$i:($res1 != $res2)"
94        }
95    }
96    return [lindex $results 0]
97}
98
99# start of tests
100
101namespace eval ::testmathop {
102    namespace path ::tcl::mathop
103    variable op ;# stop surprises!
104
105    test mathop-1.1 {compiled +} { + } 0
106    test mathop-1.2 {compiled +} { + 1 } 1
107    test mathop-1.3 {compiled +} { + 1 2 } 3
108    test mathop-1.4 {compiled +} { + 1 2 3 } 6
109    test mathop-1.5 {compiled +} { + 1.0 2 3 } 6.0
110    test mathop-1.6 {compiled +} { + 1 2 3.0 } 6.0
111    test mathop-1.7 {compiled +} { + 100000000000 2 3 } 100000000005
112    test mathop-1.8 {compiled +} { + 1 2 300000000000 } 300000000003
113    test mathop-1.9 {compiled +} { + 1000000000000000000000 2 3 } 1000000000000000000005
114    test mathop-1.10 {compiled +} { + 1 2 3000000000000000000000 } 3000000000000000000003
115    test mathop-1.11 {compiled +: errors} -returnCodes error -body {
116	+ x 0
117    } -result {can't use non-numeric string as operand of "+"}
118    test mathop-1.12 {compiled +: errors} -returnCodes error -body {
119	+ nan 0
120    } -result {can't use non-numeric floating-point value as operand of "+"}
121    test mathop-1.13 {compiled +: errors} -returnCodes error -body {
122	+ 0 x
123    } -result {can't use non-numeric string as operand of "+"}
124    test mathop-1.14 {compiled +: errors} -returnCodes error -body {
125	+ 0 nan
126    } -result {can't use non-numeric floating-point value as operand of "+"}
127    test mathop-1.15 {compiled +: errors} -returnCodes error -body {
128	+ 0o8 0
129    } -result {can't use invalid octal number as operand of "+"}
130    test mathop-1.16 {compiled +: errors} -returnCodes error -body {
131	+ 0 0o8
132    } -result {can't use invalid octal number as operand of "+"}
133    test mathop-1.17 {compiled +: errors} -returnCodes error -body {
134	+ 0 [error expectedError]
135    } -result expectedError
136    test mathop-1.18 {compiled +: argument processing order} -body {
137	# Bytecode compilation known hard for 3+ arguments
138	list [catch {
139	    + [set x 0] [incr x] NaN [incr x] [error expected] [incr x]
140	} msg] $msg $x
141    } -result {1 expected 2}
142    set op +
143    test mathop-1.19 {interpreted +} { $op } 0
144    test mathop-1.20 {interpreted +} { $op 1 } 1
145    test mathop-1.21 {interpreted +} { $op 1 2 } 3
146    test mathop-1.22 {interpreted +} { $op 1 2 3 } 6
147    test mathop-1.23 {interpreted +} { $op 1.0 2 3 } 6.0
148    test mathop-1.24 {interpreted +} { $op 1 2 3.0 } 6.0
149    test mathop-1.25 {interpreted +} { $op 100000000000 2 3 } 100000000005
150    test mathop-1.26 {interpreted +} { $op 1 2 300000000000 } 300000000003
151    test mathop-1.27 {interpreted +} { $op 1000000000000000000000 2 3 } 1000000000000000000005
152    test mathop-1.28 {interpreted +} { $op 1 2 3000000000000000000000 } 3000000000000000000003
153    test mathop-1.29 {interpreted +: errors} -returnCodes error -body {
154	$op x 0
155    } -result {can't use non-numeric string as operand of "+"}
156    test mathop-1.30 {interpreted +: errors} -returnCodes error -body {
157	$op nan 0
158    } -result {can't use non-numeric floating-point value as operand of "+"}
159    test mathop-1.31 {interpreted +: errors} -returnCodes error -body {
160	$op 0 x
161    } -result {can't use non-numeric string as operand of "+"}
162    test mathop-1.32 {interpreted +: errors} -returnCodes error -body {
163	$op 0 nan
164    } -result {can't use non-numeric floating-point value as operand of "+"}
165    test mathop-1.33 {interpreted +: errors} -returnCodes error -body {
166	$op 0o8 0
167    } -result {can't use invalid octal number as operand of "+"}
168    test mathop-1.34 {interpreted +: errors} -returnCodes error -body {
169	$op 0 0o8
170    } -result {can't use invalid octal number as operand of "+"}
171    test mathop-1.35 {interpreted +: errors} -returnCodes error -body {
172	$op 0 [error expectedError]
173    } -result expectedError
174    test mathop-1.36 {interpreted +: argument processing order} -body {
175	list [catch {
176	    $op [set x 0] [incr x] NaN [incr x] [error expected] [incr x]
177	} msg] $msg $x
178    } -result {1 expected 2}
179
180    test mathop-2.1 {compiled *} { * } 1
181    test mathop-2.2 {compiled *} { * 2 } 2
182    test mathop-2.3 {compiled *} { * 2 3 } 6
183    test mathop-2.4 {compiled *} { * 2 3 4 } 24
184    test mathop-2.5 {compiled *} { * 1.0 2 3 } 6.0
185    test mathop-2.6 {compiled *} { * 1 2 3.0 } 6.0
186    test mathop-2.7 {compiled *} { * 100000000000 2 3 } 600000000000
187    test mathop-2.8 {compiled *} { * 1 2 300000000000 } 600000000000
188    test mathop-2.9 {compiled *} { * 1000000000000000000000 2 3 } 6000000000000000000000
189    test mathop-2.10 {compiled *} { * 1 2 3000000000000000000000 } 6000000000000000000000
190    test mathop-2.11 {compiled *: errors} -returnCodes error -body {
191	* x 0
192    } -result {can't use non-numeric string as operand of "*"}
193    test mathop-2.12 {compiled *: errors} -returnCodes error -body {
194	* nan 0
195    } -result {can't use non-numeric floating-point value as operand of "*"}
196    test mathop-2.13 {compiled *: errors} -returnCodes error -body {
197	* 0 x
198    } -result {can't use non-numeric string as operand of "*"}
199    test mathop-2.14 {compiled *: errors} -returnCodes error -body {
200	* 0 nan
201    } -result {can't use non-numeric floating-point value as operand of "*"}
202    test mathop-2.15 {compiled *: errors} -returnCodes error -body {
203	* 0o8 0
204    } -result {can't use invalid octal number as operand of "*"}
205    test mathop-2.16 {compiled *: errors} -returnCodes error -body {
206	* 0 0o8
207    } -result {can't use invalid octal number as operand of "*"}
208    test mathop-2.17 {compiled *: errors} -returnCodes error -body {
209	* 0 [error expectedError]
210    } -result expectedError
211    test mathop-2.18 {compiled *: argument processing order} -body {
212	# Bytecode compilation known hard for 3+ arguments
213	list [catch {
214	    * [set x 0] [incr x] NaN [incr x] [error expected] [incr x]
215	} msg] $msg $x
216    } -result {1 expected 2}
217    set op *
218    test mathop-2.19 {interpreted *} { $op } 1
219    test mathop-2.20 {interpreted *} { $op 2 } 2
220    test mathop-2.21 {interpreted *} { $op 2 3 } 6
221    test mathop-2.22 {interpreted *} { $op 2 3 4 } 24
222    test mathop-2.23 {interpreted *} { $op 1.0 2 3 } 6.0
223    test mathop-2.24 {interpreted *} { $op 1 2 3.0 } 6.0
224    test mathop-2.25 {interpreted *} { $op 100000000000 2 3 } 600000000000
225    test mathop-2.26 {interpreted *} { $op 1 2 300000000000 } 600000000000
226    test mathop-2.27 {interpreted *} { $op 1000000000000000000000 2 3 } 6000000000000000000000
227    test mathop-2.28 {interpreted *} { $op 1 2 3000000000000000000000 } 6000000000000000000000
228    test mathop-2.29 {interpreted *: errors} -returnCodes error -body {
229	$op x 0
230    } -result {can't use non-numeric string as operand of "*"}
231    test mathop-2.30 {interpreted *: errors} -returnCodes error -body {
232	$op nan 0
233    } -result {can't use non-numeric floating-point value as operand of "*"}
234    test mathop-2.31 {interpreted *: errors} -returnCodes error -body {
235	$op 0 x
236    } -result {can't use non-numeric string as operand of "*"}
237    test mathop-2.32 {interpreted *: errors} -returnCodes error -body {
238	$op 0 nan
239    } -result {can't use non-numeric floating-point value as operand of "*"}
240    test mathop-2.33 {interpreted *: errors} -returnCodes error -body {
241	$op 0o8 0
242    } -result {can't use invalid octal number as operand of "*"}
243    test mathop-2.34 {interpreted *: errors} -returnCodes error -body {
244	$op 0 0o8
245    } -result {can't use invalid octal number as operand of "*"}
246    test mathop-2.35 {interpreted *: errors} -returnCodes error -body {
247	$op 0 [error expectedError]
248    } -result expectedError
249    test mathop-2.36 {interpreted *: argument processing order} -body {
250	list [catch {
251	    $op [set x 0] [incr x] NaN [incr x] [error expected] [incr x]
252	} msg] $msg $x
253    } -result {1 expected 2}
254
255    test mathop-3.1 {compiled !} {! 0} 1
256    test mathop-3.2 {compiled !} {! 1} 0
257    test mathop-3.3 {compiled !} {! false} 1
258    test mathop-3.4 {compiled !} {! true} 0
259    test mathop-3.5 {compiled !} {! 0.0} 1
260    test mathop-3.6 {compiled !} {! 10000000000} 0
261    test mathop-3.7 {compiled !} {! 10000000000000000000000000} 0
262    test mathop-3.8 {compiled !: errors} -body {
263	! foobar
264    } -returnCodes error -result {can't use non-numeric string as operand of "!"}
265    test mathop-3.9 {compiled !: errors} -body {
266	! 0 0
267    } -returnCodes error -result "wrong # args: should be \"! boolean\""
268    test mathop-3.10 {compiled !: errors} -body {
269	!
270    } -returnCodes error -result "wrong # args: should be \"! boolean\""
271    set op !
272    test mathop-3.11 {interpreted !} {$op 0} 1
273    test mathop-3.12 {interpreted !} {$op 1} 0
274    test mathop-3.13 {interpreted !} {$op false} 1
275    test mathop-3.14 {interpreted !} {$op true} 0
276    test mathop-3.15 {interpreted !} {$op 0.0} 1
277    test mathop-3.16 {interpreted !} {$op 10000000000} 0
278    test mathop-3.17 {interpreted !} {$op 10000000000000000000000000} 0
279    test mathop-3.18 {interpreted !: errors} -body {
280	$op foobar
281    } -returnCodes error -result {can't use non-numeric string as operand of "!"}
282    test mathop-3.19 {interpreted !: errors} -body {
283	$op 0 0
284    } -returnCodes error -result "wrong # args: should be \"! boolean\""
285    test mathop-3.20 {interpreted !: errors} -body {
286	$op
287    } -returnCodes error -result "wrong # args: should be \"! boolean\""
288    test mathop-3.21 {compiled !: error} -returnCodes error -body {
289	! NaN
290    } -result {can't use non-numeric floating-point value as operand of "!"}
291    test mathop-3.22 {interpreted !: error} -returnCodes error -body {
292	$op NaN
293    } -result {can't use non-numeric floating-point value as operand of "!"}
294
295    test mathop-4.1 {compiled ~} {~ 0} -1
296    test mathop-4.2 {compiled ~} {~ 1} -2
297    test mathop-4.3 {compiled ~} {~ 31} -32
298    test mathop-4.4 {compiled ~} {~ -127} 126
299    test mathop-4.5 {compiled ~} {~ -0} -1
300    test mathop-4.6 {compiled ~} {~ 10000000000} -10000000001
301    test mathop-4.7 {compiled ~} {~ 10000000000000000000000000} -10000000000000000000000001
302    test mathop-4.8 {compiled ~: errors} -body {
303	~ foobar
304    } -returnCodes error -result {can't use non-numeric string as operand of "~"}
305    test mathop-4.9 {compiled ~: errors} -body {
306	~ 0 0
307    } -returnCodes error -result "wrong # args: should be \"~ integer\""
308    test mathop-4.10 {compiled ~: errors} -body {
309	~
310    } -returnCodes error -result "wrong # args: should be \"~ integer\""
311    test mathop-4.11 {compiled ~: errors} -returnCodes error -body {
312	~ 0.0
313    } -result {can't use floating-point value as operand of "~"}
314    test mathop-4.12 {compiled ~: errors} -returnCodes error -body {
315	~ NaN
316    } -result {can't use non-numeric floating-point value as operand of "~"}
317    set op ~
318    test mathop-4.13 {interpreted ~} {$op 0} -1
319    test mathop-4.14 {interpreted ~} {$op 1} -2
320    test mathop-4.15 {interpreted ~} {$op 31} -32
321    test mathop-4.16 {interpreted ~} {$op -127} 126
322    test mathop-4.17 {interpreted ~} {$op -0} -1
323    test mathop-4.18 {interpreted ~} {$op 10000000000} -10000000001
324    test mathop-4.19 {interpreted ~} {$op 10000000000000000000000000} -10000000000000000000000001
325    test mathop-4.20 {interpreted ~: errors} -body {
326	$op foobar
327    } -returnCodes error -result {can't use non-numeric string as operand of "~"}
328    test mathop-4.21 {interpreted ~: errors} -body {
329	$op 0 0
330    } -returnCodes error -result "wrong # args: should be \"~ integer\""
331    test mathop-4.22 {interpreted ~: errors} -body {
332	$op
333    } -returnCodes error -result "wrong # args: should be \"~ integer\""
334    test mathop-4.23 {interpreted ~: errors} -returnCodes error -body {
335	$op 0.0
336    } -result {can't use floating-point value as operand of "~"}
337    test mathop-4.24 {interpreted ~: errors} -returnCodes error -body {
338	$op NaN
339    } -result {can't use non-numeric floating-point value as operand of "~"}
340
341    test mathop-5.1 {compiled eq} {eq {} a} 0
342    test mathop-5.2 {compiled eq} {eq a a} 1
343    test mathop-5.3 {compiled eq} {eq a {}} 0
344    test mathop-5.4 {compiled eq} {eq a b} 0
345    test mathop-5.5 {compiled eq} { eq } 1
346    test mathop-5.6 {compiled eq} {eq a} 1
347    test mathop-5.7 {compiled eq} {eq a a a} 1
348    test mathop-5.8 {compiled eq} {eq a a b} 0
349    test mathop-5.9 {compiled eq} -body {
350	eq a b [error foobar]
351    } -returnCodes error -result foobar
352    test mathop-5.10 {compiled eq} {eq NaN Na NaN} 0
353    set op eq
354    test mathop-5.11 {interpreted eq} {$op {} a} 0
355    test mathop-5.12 {interpreted eq} {$op a a} 1
356    test mathop-5.13 {interpreted eq} {$op a {}} 0
357    test mathop-5.14 {interpreted eq} {$op a b} 0
358    test mathop-5.15 {interpreted eq} { $op } 1
359    test mathop-5.16 {interpreted eq} {$op a} 1
360    test mathop-5.17 {interpreted eq} {$op a a a} 1
361    test mathop-5.18 {interpreted eq} {$op a a b} 0
362    test mathop-5.19 {interpreted eq} -body {
363	$op a b [error foobar]
364    } -returnCodes error -result foobar
365    test mathop-5.20 {interpreted eq} {$op NaN Na NaN} 0
366
367    variable big1      12135435435354435435342423948763867876
368    variable big2       2746237174783836746262564892918327847
369    variable wide1                             12345678912345
370    variable wide2                             87321847232215
371    variable small1                                     87345
372    variable small2                                     16753
373
374    test mathop-6.1 {compiled &} { & } -1
375    test mathop-6.2 {compiled &} { & 1 } 1
376    test mathop-6.3 {compiled &} { & 1 2 } 0
377    test mathop-6.4 {compiled &} { & 3 7 6 } 2
378    test mathop-6.5 {compiled &} -returnCodes error -body {
379	& 1.0 2 3
380    } -result {can't use floating-point value as operand of "&"}
381    test mathop-6.6 {compiled &} -returnCodes error -body {
382	& 1 2 3.0
383    } -result {can't use floating-point value as operand of "&"}
384    test mathop-6.7 {compiled &} { & 100000000002 18 -126 } 2
385    test mathop-6.8 {compiled &} { & 0xff 0o377 333333333333 } 85
386    test mathop-6.9 {compiled &} { & 1000000000000000000002 18 -126 } 2
387    test mathop-6.10 {compiled &} { & 0xff 0o377 3333333333333333333333 } 85
388    test mathop-6.11 {compiled &: errors} -returnCodes error -body {
389	& x 0
390    } -result {can't use non-numeric string as operand of "&"}
391    test mathop-6.12 {compiled &: errors} -returnCodes error -body {
392	& nan 0
393    } -result {can't use non-numeric floating-point value as operand of "&"}
394    test mathop-6.13 {compiled &: errors} -returnCodes error -body {
395	& 0 x
396    } -result {can't use non-numeric string as operand of "&"}
397    test mathop-6.14 {compiled &: errors} -returnCodes error -body {
398	& 0 nan
399    } -result {can't use non-numeric floating-point value as operand of "&"}
400    test mathop-6.15 {compiled &: errors} -returnCodes error -body {
401	& 0o8 0
402    } -result {can't use invalid octal number as operand of "&"}
403    test mathop-6.16 {compiled &: errors} -returnCodes error -body {
404	& 0 0o8
405    } -result {can't use invalid octal number as operand of "&"}
406    test mathop-6.17 {compiled &: errors} -returnCodes error -body {
407	& 0 [error expectedError]
408    } -result expectedError
409    test mathop-6.18 {compiled &: argument processing order} -body {
410	# Bytecode compilation known hard for 3+ arguments
411	list [catch {
412	    & [set x 0] [incr x] NaN [incr x] [error expected] [incr x]
413	} msg] $msg $x
414    } -result {1 expected 2}
415    set op &
416    test mathop-6.19 {interpreted &} { $op } -1
417    test mathop-6.20 {interpreted &} { $op 1 } 1
418    test mathop-6.21 {interpreted &} { $op 1 2 } 0
419    test mathop-6.22 {interpreted &} { $op 3 7 6 } 2
420    test mathop-6.23 {interpreted &} -returnCodes error -body {
421	$op 1.0 2 3
422    } -result {can't use floating-point value as operand of "&"}
423    test mathop-6.24 {interpreted &} -returnCodes error -body {
424	$op 1 2 3.0
425    } -result {can't use floating-point value as operand of "&"}
426    test mathop-6.25 {interpreted &} { $op 100000000002 18 -126 } 2
427    test mathop-6.26 {interpreted &} { $op 0xff 0o377 333333333333 } 85
428    test mathop-6.27 {interpreted &} { $op 1000000000000000000002 18 -126 } 2
429    test mathop-6.28 {interpreted &} { $op 0xff 0o377 3333333333333333333333 } 85
430    test mathop-6.29 {interpreted &: errors} -returnCodes error -body {
431	$op x 0
432    } -result {can't use non-numeric string as operand of "&"}
433    test mathop-6.30 {interpreted &: errors} -returnCodes error -body {
434	$op nan 0
435    } -result {can't use non-numeric floating-point value as operand of "&"}
436    test mathop-6.31 {interpreted &: errors} -returnCodes error -body {
437	$op 0 x
438    } -result {can't use non-numeric string as operand of "&"}
439    test mathop-6.32 {interpreted &: errors} -returnCodes error -body {
440	$op 0 nan
441    } -result {can't use non-numeric floating-point value as operand of "&"}
442    test mathop-6.33 {interpreted &: errors} -returnCodes error -body {
443	$op 0o8 0
444    } -result {can't use invalid octal number as operand of "&"}
445    test mathop-6.34 {interpreted &: errors} -returnCodes error -body {
446	$op 0 0o8
447    } -result {can't use invalid octal number as operand of "&"}
448    test mathop-6.35 {interpreted &: errors} -returnCodes error -body {
449	$op 0 [error expectedError]
450    } -result expectedError
451    test mathop-6.36 {interpreted &: argument processing order} -body {
452	list [catch {
453	    $op [set x 0] [incr x] NaN [incr x] [error expected] [incr x]
454	} msg] $msg $x
455    } -result {1 expected 2}
456    test mathop-6.37 {& and bignums} {
457	list [& $big1 $big2] [$op $big1 $big2]
458    } {712439449294653815890598856501796 712439449294653815890598856501796}
459    test mathop-6.38 {& and bignums} {
460	list [& $big1 $wide2] [$op $big1 $wide2]
461    } {78521450111684 78521450111684}
462    test mathop-6.39 {& and bignums} {
463	list [& $big1 $small2] [$op $big1 $small2]
464    } {96 96}
465    test mathop-6.40 {& and bignums} {
466	list [& $wide1 $big2] [$op $wide1 $big2]
467    } {2371422390785 2371422390785}
468    test mathop-6.41 {& and bignums} {
469	list [& $wide1 $wide2] [$op $wide1 $wide2]
470    } {12275881497169 12275881497169}
471    test mathop-6.42 {& and bignums} {
472	list [& $wide1 $small2] [$op $wide1 $small2]
473    } {16721 16721}
474    test mathop-6.43 {& and bignums} {
475	list [& $small1 $big2] [$op $small1 $big2]
476    } {33 33}
477    test mathop-6.44 {& and bignums} {
478	list [& $small1 $wide2] [$op $small1 $wide2]
479    } {87057 87057}
480    test mathop-6.45 {& and bignums} {
481	list [& $small1 $small2] [$op $small1 $small2]
482    } {16689 16689}
483
484    test mathop-7.1 {compiled |} { | } 0
485    test mathop-7.2 {compiled |} { | 1 } 1
486    test mathop-7.3 {compiled |} { | 1 2 } 3
487    test mathop-7.4 {compiled |} { | 3 7 6 } 7
488    test mathop-7.5 {compiled |} -returnCodes error -body {
489	| 1.0 2 3
490    } -result {can't use floating-point value as operand of "|"}
491    test mathop-7.6 {compiled |} -returnCodes error -body {
492	| 1 2 3.0
493    } -result {can't use floating-point value as operand of "|"}
494    test mathop-7.7 {compiled |} { | 100000000002 18 -126 } -110
495    test mathop-7.8 {compiled |} { | 0xff 0o377 333333333333 } 333333333503
496    test mathop-7.9 {compiled |} { | 1000000000000000000002 18 -126 } -110
497    test mathop-7.10 {compiled |} { | 0xff 0o377 3333333333333333333333 } 3333333333333333333503
498    test mathop-7.11 {compiled |: errors} -returnCodes error -body {
499	| x 0
500    } -result {can't use non-numeric string as operand of "|"}
501    test mathop-7.12 {compiled |: errors} -returnCodes error -body {
502	| nan 0
503    } -result {can't use non-numeric floating-point value as operand of "|"}
504    test mathop-7.13 {compiled |: errors} -returnCodes error -body {
505	| 0 x
506    } -result {can't use non-numeric string as operand of "|"}
507    test mathop-7.14 {compiled |: errors} -returnCodes error -body {
508	| 0 nan
509    } -result {can't use non-numeric floating-point value as operand of "|"}
510    test mathop-7.15 {compiled |: errors} -returnCodes error -body {
511	| 0o8 0
512    } -result {can't use invalid octal number as operand of "|"}
513    test mathop-7.16 {compiled |: errors} -returnCodes error -body {
514	| 0 0o8
515    } -result {can't use invalid octal number as operand of "|"}
516    test mathop-7.17 {compiled |: errors} -returnCodes error -body {
517	| 0 [error expectedError]
518    } -result expectedError
519    test mathop-7.18 {compiled |: argument processing order} -body {
520	# Bytecode compilation known hard for 3+ arguments
521	list [catch {
522	    | [set x 0] [incr x] NaN [incr x] [error expected] [incr x]
523	} msg] $msg $x
524    } -result {1 expected 2}
525    set op |
526    test mathop-7.19 {interpreted |} { $op } 0
527    test mathop-7.20 {interpreted |} { $op 1 } 1
528    test mathop-7.21 {interpreted |} { $op 1 2 } 3
529    test mathop-7.22 {interpreted |} { $op 3 7 6 } 7
530    test mathop-7.23 {interpreted |} -returnCodes error -body {
531	$op 1.0 2 3
532    } -result {can't use floating-point value as operand of "|"}
533    test mathop-7.24 {interpreted |} -returnCodes error -body {
534	$op 1 2 3.0
535    } -result {can't use floating-point value as operand of "|"}
536    test mathop-7.25 {interpreted |} { $op 100000000002 18 -126 } -110
537    test mathop-7.26 {interpreted |} { $op 0xff 0o377 333333333333 } 333333333503
538    test mathop-7.27 {interpreted |} { $op 1000000000000000000002 18 -126 } -110
539    test mathop-7.28 {interpreted |} { $op 0xff 0o377 3333333333333333333333 } 3333333333333333333503
540    test mathop-7.29 {interpreted |: errors} -returnCodes error -body {
541	$op x 0
542    } -result {can't use non-numeric string as operand of "|"}
543    test mathop-7.30 {interpreted |: errors} -returnCodes error -body {
544	$op nan 0
545    } -result {can't use non-numeric floating-point value as operand of "|"}
546    test mathop-7.31 {interpreted |: errors} -returnCodes error -body {
547	$op 0 x
548    } -result {can't use non-numeric string as operand of "|"}
549    test mathop-7.32 {interpreted |: errors} -returnCodes error -body {
550	$op 0 nan
551    } -result {can't use non-numeric floating-point value as operand of "|"}
552    test mathop-7.33 {interpreted |: errors} -returnCodes error -body {
553	$op 0o8 0
554    } -result {can't use invalid octal number as operand of "|"}
555    test mathop-7.34 {interpreted |: errors} -returnCodes error -body {
556	$op 0 0o8
557    } -result {can't use invalid octal number as operand of "|"}
558    test mathop-7.35 {interpreted |: errors} -returnCodes error -body {
559	$op 0 [error expectedError]
560    } -result expectedError
561    test mathop-7.36 {interpreted |: argument processing order} -body {
562	list [catch {
563	    $op [set x 0] [incr x] NaN [incr x] [error expected] [incr x]
564	} msg] $msg $x
565    } -result {1 expected 2}
566    test mathop-7.37 {| and bignums} {
567	list [| $big1 $big2] [$op $big1 $big2]
568    } {14880960170688977527789098242825693927 14880960170688977527789098242825693927}
569    test mathop-7.38 {| and bignums} {
570	list [| $big1 $wide2] [$op $big1 $wide2]
571    } {12135435435354435435342432749160988407 12135435435354435435342432749160988407}
572    test mathop-7.39 {| and bignums} {
573	list [| $big1 $small2] [$op $big1 $small2]
574    } {12135435435354435435342423948763884533 12135435435354435435342423948763884533}
575    test mathop-7.40 {| and bignums} {
576	list [| $wide1 $big2] [$op $wide1 $big2]
577    } {2746237174783836746262574867174849407 2746237174783836746262574867174849407}
578    test mathop-7.41 {| and bignums} {
579	list [| $wide1 $wide2] [$op $wide1 $wide2]
580    } {87391644647391 87391644647391}
581    test mathop-7.42 {| and bignums} {
582	list [| $wide1 $small2] [$op $wide1 $small2]
583    } {12345678912377 12345678912377}
584    test mathop-7.43 {| and bignums} {
585	list [| $small1 $big2] [$op $small1 $big2]
586    } {2746237174783836746262564892918415159 2746237174783836746262564892918415159}
587    test mathop-7.44 {| and bignums} {
588	list [| $small1 $wide2] [$op $small1 $wide2]
589    } {87321847232503 87321847232503}
590    test mathop-7.45 {| and bignums} {
591	list [| $small1 $small2] [$op $small1 $small2]
592    } {87409 87409}
593
594    test mathop-8.1 {compiled ^} { ^ } 0
595    test mathop-8.2 {compiled ^} { ^ 1 } 1
596    test mathop-8.3 {compiled ^} { ^ 1 2 } 3
597    test mathop-8.4 {compiled ^} { ^ 3 7 6 } 2
598    test mathop-8.5 {compiled ^} -returnCodes error -body {
599	^ 1.0 2 3
600    } -result {can't use floating-point value as operand of "^"}
601    test mathop-8.6 {compiled ^} -returnCodes error -body {
602	^ 1 2 3.0
603    } -result {can't use floating-point value as operand of "^"}
604    test mathop-8.7 {compiled ^} { ^ 100000000002 18 -126 } -100000000110
605    test mathop-8.8 {compiled ^} { ^ 0xff 0o377 333333333333 } 333333333333
606    test mathop-8.9 {compiled ^} { ^ 1000000000000000000002 18 -126 } -1000000000000000000110
607    test mathop-8.10 {compiled ^} { ^ 0xff 0o377 3333333333333333333333 } 3333333333333333333333
608    test mathop-8.11 {compiled ^: errors} -returnCodes error -body {
609	^ x 0
610    } -result {can't use non-numeric string as operand of "^"}
611    test mathop-8.12 {compiled ^: errors} -returnCodes error -body {
612	^ nan 0
613    } -result {can't use non-numeric floating-point value as operand of "^"}
614    test mathop-8.13 {compiled ^: errors} -returnCodes error -body {
615	^ 0 x
616    } -result {can't use non-numeric string as operand of "^"}
617    test mathop-8.14 {compiled ^: errors} -returnCodes error -body {
618	^ 0 nan
619    } -result {can't use non-numeric floating-point value as operand of "^"}
620    test mathop-8.15 {compiled ^: errors} -returnCodes error -body {
621	^ 0o8 0
622    } -result {can't use invalid octal number as operand of "^"}
623    test mathop-8.16 {compiled ^: errors} -returnCodes error -body {
624	^ 0 0o8
625    } -result {can't use invalid octal number as operand of "^"}
626    test mathop-8.17 {compiled ^: errors} -returnCodes error -body {
627	^ 0 [error expectedError]
628    } -result expectedError
629    test mathop-8.18 {compiled ^: argument processing order} -body {
630	# Bytecode compilation known hard for 3+ arguments
631	list [catch {
632	    ^ [set x 0] [incr x] NaN [incr x] [error expected] [incr x]
633	} msg] $msg $x
634    } -result {1 expected 2}
635    set op ^
636    test mathop-8.19 {interpreted ^} { $op } 0
637    test mathop-8.20 {interpreted ^} { $op 1 } 1
638    test mathop-8.21 {interpreted ^} { $op 1 2 } 3
639    test mathop-8.22 {interpreted ^} { $op 3 7 6 } 2
640    test mathop-8.23 {interpreted ^} -returnCodes error -body {
641	$op 1.0 2 3
642    } -result {can't use floating-point value as operand of "^"}
643    test mathop-8.24 {interpreted ^} -returnCodes error -body {
644	$op 1 2 3.0
645    } -result {can't use floating-point value as operand of "^"}
646    test mathop-8.25 {interpreted ^} { $op 100000000002 18 -126 } -100000000110
647    test mathop-8.26 {interpreted ^} { $op 0xff 0o377 333333333333 } 333333333333
648    test mathop-8.27 {interpreted ^} { $op 1000000000000000000002 18 -126 } -1000000000000000000110
649    test mathop-8.28 {interpreted ^} { $op 0xff 0o377 3333333333333333333333 } 3333333333333333333333
650    test mathop-8.29 {interpreted ^: errors} -returnCodes error -body {
651	$op x 0
652    } -result {can't use non-numeric string as operand of "^"}
653    test mathop-8.30 {interpreted ^: errors} -returnCodes error -body {
654	$op nan 0
655    } -result {can't use non-numeric floating-point value as operand of "^"}
656    test mathop-8.31 {interpreted ^: errors} -returnCodes error -body {
657	$op 0 x
658    } -result {can't use non-numeric string as operand of "^"}
659    test mathop-8.32 {interpreted ^: errors} -returnCodes error -body {
660	$op 0 nan
661    } -result {can't use non-numeric floating-point value as operand of "^"}
662    test mathop-8.33 {interpreted ^: errors} -returnCodes error -body {
663	$op 0o8 0
664    } -result {can't use invalid octal number as operand of "^"}
665    test mathop-8.34 {interpreted ^: errors} -returnCodes error -body {
666	$op 0 0o8
667    } -result {can't use invalid octal number as operand of "^"}
668    test mathop-8.35 {interpreted ^: errors} -returnCodes error -body {
669	$op 0 [error expectedError]
670    } -result expectedError
671    test mathop-8.36 {interpreted ^: argument processing order} -body {
672	list [catch {
673	    $op [set x 0] [incr x] NaN [incr x] [error expected] [incr x]
674	} msg] $msg $x
675    } -result {1 expected 2}
676    test mathop-8.37 {^ and bignums} {
677	list [^ $big1 $big2] [$op $big1 $big2]
678    } {14880247731239682873973207643969192131 14880247731239682873973207643969192131}
679    test mathop-8.38 {^ and bignums} {
680	list [^ $big1 $wide2] [$op $big1 $wide2]
681    } {12135435435354435435342354227710876723 12135435435354435435342354227710876723}
682    test mathop-8.39 {^ and bignums} {
683	list [^ $big1 $small2] [$op $big1 $small2]
684    } {12135435435354435435342423948763884437 12135435435354435435342423948763884437}
685    test mathop-8.40 {^ and bignums} {
686	list [^ $wide1 $big2] [$op $wide1 $big2]
687    } {2746237174783836746262572495752458622 2746237174783836746262572495752458622}
688    test mathop-8.41 {^ and bignums} {
689	list [^ $wide1 $wide2] [$op $wide1 $wide2]
690    } {75115763150222 75115763150222}
691    test mathop-8.42 {^ and bignums} {
692	list [^ $wide1 $small2] [$op $wide1 $small2]
693    } {12345678895656 12345678895656}
694    test mathop-8.43 {^ and bignums} {
695	list [^ $small1 $big2] [$op $small1 $big2]
696    } {2746237174783836746262564892918415126 2746237174783836746262564892918415126}
697    test mathop-8.44 {^ and bignums} {
698	list [^ $small1 $wide2] [$op $small1 $wide2]
699    } {87321847145446 87321847145446}
700    test mathop-8.45 {^ and bignums} {
701	list [^ $small1 $small2] [$op $small1 $small2]
702    } {70720 70720}
703
704    # TODO: % ** << >>  - /  == != < <= > >=  ne  in ni
705
706    test mathop-13.100 {compiled -: argument processing order} -body {
707      # Bytecode compilation known hard for 3+ arguments
708      list [catch {
709          - [set x 0] [incr x] NaN [incr x] [error expected] [incr x]
710      } msg] $msg $x
711    } -result {1 expected 2}
712
713    test mathop-14.100 {compiled /: argument processing order} -body {
714      # Bytecode compilation known hard for 3+ arguments
715      list [catch {
716          / [set x 0] [incr x] NaN [incr x] [error expected] [incr x]
717      } msg] $msg $x
718    } -result {1 expected 2}
719}
720
721test mathop-20.1 { zero args, return unit } {
722    set res {}
723    foreach op {+ * & ^ | ** < <= > >= == eq} {
724        lappend res [TestOp $op]
725    }
726    set res
727} {0 1 -1 0 0 1 1 1 1 1 1 1}
728test mathop-20.2 { zero args, not allowed } {
729    set exp {}
730    foreach op {~ ! << >> % != ne in ni - /} {
731        set res [TestOp $op]
732        if {[string match "wrong # args: should be * TCL WRONGARGS" $res]} {
733            lappend exp 0
734        } else {
735            lappend exp $res
736        }
737    }
738    set exp
739} {0 0 0 0 0 0 0 0 0 0 0}
740test mathop-20.3 { one arg } {
741    set res {}
742    foreach val {7 8.3} {
743        foreach op {+ ** - * / < <= > >= == eq !} {
744            lappend res [TestOp $op $val]
745        }
746    }
747    set res
748} [list 7   7   -7   7   [expr {1.0/7.0}] 1 1 1 1 1 1 0 \
749        8.3 8.3 -8.3 8.3 [expr {1.0/8.3}] 1 1 1 1 1 1 0]
750test mathop-20.4 { one arg, integer only ops } {
751    set res {}
752    foreach val {23} {
753        foreach op {& | ^ ~} {
754            lappend res [TestOp $op $val]
755        }
756    }
757    set res
758} [list 23 23 23 -24]
759test mathop-20.5 { one arg, not allowed } {
760    set exp {}
761    foreach op {% != ne in ni << >>} {
762        set res [TestOp $op 1]
763        if {[string match "wrong # args: should be * TCL WRONGARGS" $res]} {
764            lappend exp 0
765        } else {
766            lappend exp $res
767        }
768    }
769    set exp
770} {0 0 0 0 0 0 0}
771test mathop-20.6 { one arg, error } {
772    set res {}
773    set exp {}
774    foreach vals {x {1 x} {1 1 x} {1 x 1}} {
775        # skipping - for now, knownbug...
776        foreach op {+ * / & | ^ **} {
777            lappend res [TestOp $op {*}$vals]
778            lappend exp "can't use non-numeric string as operand of \"$op\"\
779		ARITH DOMAIN {non-numeric string}"
780        }
781    }
782    foreach op {+ * / & | ^ **} {
783	lappend res [TestOp $op NaN 1]
784	lappend exp "can't use non-numeric floating-point value as operand of \"$op\"\
785	    ARITH DOMAIN {non-numeric floating-point value}"
786    }
787    expr {$res eq $exp ? 0 : $res}
788} 0
789test mathop-20.7 { multi arg } {
790    set res {}
791    foreach vals {{1 2} {3 4 5} {4 3 2 1}} {
792        foreach op {+ - * /} {
793            lappend res [TestOp $op {*}$vals]
794        }
795    }
796    set res
797} [list 3 -1 2 0  12 -6 60 0  10 -2 24 0]
798test mathop-20.8 { multi arg, double } {
799    set res {}
800    foreach vals {{1.0 2} {3.0 4 5} {4 3.0 2 1}
801	    {1.0 -1.0 1e-18} {1.0 1.0 1e-18}} {
802        foreach op {+ - * /} {
803            lappend res [TestOp $op {*}$vals]
804        }
805    }
806    set res
807} [list 3.0 -1.0 2.0 0.5  12.0 -6.0 60.0 0.15  10.0 -2.0 24.0 [expr {2.0/3}] 1e-18 2.0 -1e-18 [expr {-1.0/1e-18}] 2.0 -1e-18 1e-18 [expr {1.0/1e-18}]]
808
809test mathop-21.1 { unary ops, bitnot } {
810    set res {}
811    lappend res [TestOp ~ 7]
812    lappend res [TestOp ~ -5]
813    lappend res [TestOp ~ 354657483923456]
814    lappend res [TestOp ~ 123456789123456789123456789]
815    set res
816} [list -8 4 -354657483923457 -123456789123456789123456790]
817test mathop-21.2 { unary ops, logical not } {
818    set res {}
819    lappend res [TestOp ! 0]
820    lappend res [TestOp ! 1]
821    lappend res [TestOp ! true]
822    lappend res [TestOp ! false]
823    lappend res [TestOp ! 37]
824    lappend res [TestOp ! 8.5]
825    set res
826} [list 1 0 0 1 0 0]
827test mathop-21.3 { unary ops, negation } {
828    set res {}
829    lappend res [TestOp -  7.2]
830    lappend res [TestOp - -5]
831    lappend res [TestOp - -2147483648]                  ;# -2**31
832    lappend res [TestOp - -9223372036854775808]         ;# -2**63
833    lappend res [TestOp -  354657483923456]             ;# wide
834    lappend res [TestOp -  123456789123456789123456789] ;# big
835    set res
836} [list -7.2 5 2147483648 9223372036854775808 -354657483923456 \
837           -123456789123456789123456789]
838test mathop-21.4 { unary ops, inversion } {
839    set res {}
840    lappend res [TestOp / 1]
841    lappend res [TestOp / 5]
842    lappend res [TestOp / 5.6]
843    lappend res [TestOp / -8]
844    lappend res [TestOp /  354657483923456]             ;# wide
845    lappend res [TestOp /  123456789123456789123456789] ;# big
846    set res
847} [list 1.0 0.2 0.17857142857142858 -0.125 \
848           2.8196218755553604e-15 8.10000006561e-27]
849test mathop-21.5 { unary ops, bad values } {
850    set res {}
851    set exp {}
852    lappend res [TestOp / x]
853    lappend exp "can't use non-numeric string as operand of \"/\" ARITH DOMAIN {non-numeric string}"
854    lappend res [TestOp - x]
855    lappend exp "can't use non-numeric string as operand of \"-\" ARITH DOMAIN {non-numeric string}"
856    lappend res [TestOp ~ x]
857    lappend exp "can't use non-numeric string as operand of \"~\" ARITH DOMAIN {non-numeric string}"
858    lappend res [TestOp ! x]
859    lappend exp "can't use non-numeric string as operand of \"!\" ARITH DOMAIN {non-numeric string}"
860    lappend res [TestOp ~ 5.0]
861    lappend exp "can't use floating-point value as operand of \"~\" ARITH DOMAIN {floating-point value}"
862    expr {$res eq $exp ? 0 : $res}
863} 0
864test mathop-21.6 { unary ops, too many } {
865    set exp {}
866    foreach op {~ !} {
867        set res [TestOp $op 7 8]
868        if {[string match "wrong # args: should be * TCL WRONGARGS" $res]} {
869            lappend exp 0
870        } else {
871            lappend exp $res
872        }
873    }
874    set exp
875} {0 0}
876
877test mathop-22.1 { bitwise ops } {
878    set res {}
879    foreach vals {5 {1 6} {1 2 3} {1 2 3 4}} {
880        foreach op {& | ^} {
881            lappend res [TestOp $op {*}$vals]
882        }
883    }
884    set res
885} [list 5 5 5  0 7 7  0 3 0  0 7 4]
886test mathop-22.2 { bitwise ops on bignums } {
887    set dig 50
888    set a 0x[string repeat 5 $dig]
889    set b 0x[string repeat 7 $dig]
890    set c 0x[string repeat 9 $dig]
891    set bn [expr {~$b}]
892    set cn [expr {~$c}]
893
894    set res {}
895    foreach vals [list [list $a $b] [list $a $c] [list $b $c] \
896                          [list $a $bn] [list $bn $c] [list $bn $cn]] {
897        foreach op {& | ^} {
898            lappend res [TestOp $op {*}$vals]
899        }
900    }
901    set exp {}
902    foreach d {5 7 2  1 D C  1 F E  0 -D -D  8 -9 -1  -0 -E E} {
903        if {[string match "-*" $d]} {
904            set d [format %X [expr {15-"0x[string range $d 1 end]"}]]
905            set val [expr {-"0x[string repeat $d $dig]"-1}]
906        } else {
907            set val [expr {"0x[string repeat $d $dig]"}]
908        }
909        lappend exp $val
910    }
911    expr {$exp eq $res ? 1 : "($res != $exp"}
912} 1
913test mathop-22.3 { bitwise ops } {
914    set big1      12135435435354435435342423948763867876
915    set big2       2746237174783836746262564892918327847
916    set wide1                             12345678912345
917    set wide2                             87321847232215
918    set small1                                     87345
919    set small2                                     16753
920
921    set res {}
922    foreach op {& | ^} {
923        lappend res [TestOp $op $big1   $big2]
924        lappend res [TestOp $op $big1   $wide2]
925        lappend res [TestOp $op $big1   $small2]
926        lappend res [TestOp $op $wide1  $big2]
927        lappend res [TestOp $op $wide1  $wide2]
928        lappend res [TestOp $op $wide1  $small2]
929        lappend res [TestOp $op $small1 $big2]
930        lappend res [TestOp $op $small1 $wide2]
931        lappend res [TestOp $op $small1 $small2]
932    }
933    set res
934} [list \
935           712439449294653815890598856501796 \
936           78521450111684 \
937           96 \
938           2371422390785 \
939           12275881497169 \
940           16721 \
941           33 \
942           87057 \
943           16689 \
944           14880960170688977527789098242825693927 \
945           12135435435354435435342432749160988407 \
946           12135435435354435435342423948763884533 \
947           2746237174783836746262574867174849407 \
948           87391644647391 \
949           12345678912377 \
950           2746237174783836746262564892918415159 \
951           87321847232503 \
952           87409 \
953           14880247731239682873973207643969192131 \
954           12135435435354435435342354227710876723 \
955           12135435435354435435342423948763884437 \
956           2746237174783836746262572495752458622 \
957           75115763150222 \
958           12345678895656 \
959           2746237174783836746262564892918415126 \
960           87321847145446 \
961           70720 \
962          ]
963test mathop-22.4 { unary ops, bad values } {
964    set res {}
965    set exp {}
966    foreach op {& | ^} {
967        lappend res [TestOp $op x 5]
968        lappend exp "can't use non-numeric string as operand of \"$op\" ARITH DOMAIN {non-numeric string}"
969        lappend res [TestOp $op 5 x]
970        lappend exp "can't use non-numeric string as operand of \"$op\" ARITH DOMAIN {non-numeric string}"
971    }
972    expr {$res eq $exp ? 0 : $res}
973} 0
974
975test mathop-23.1 { comparison ops, numerical } {
976    set res {}
977    set todo {5 {1 6} {1 2 2 3} {4 3 2 1} {5.0 5.0} {6 3 3 1} {5.0 5}}
978    lappend todo [list 2342476234762482734623842342 234827463876473 3434]
979    lappend todo [list 2653 453735910264536 453735910264537 2384762472634982746239847637]
980    lappend todo [list 2653 2384762472634982746239847637]
981    lappend todo [list 2653 -2384762472634982746239847637]
982    lappend todo [list 3789253678212653 -2384762472634982746239847637]
983    lappend todo [list 5.0 6 7.0 8 1e13 1945628567352654 1.1e20 \
984                          6734253647589123456784564378 2.3e50]
985    set a 7
986    lappend todo [list $a $a] ;# Same object
987    foreach vals $todo {
988        foreach op {< <= > >= == eq} {
989            lappend res [TestOp $op {*}$vals]
990        }
991    }
992    set res
993} [list 1 1 1 1 1 1 \
994        1 1 0 0 0 0 \
995        0 1 0 0 0 0 \
996        0 0 1 1 0 0 \
997        0 1 0 1 1 1 \
998        0 0 0 1 0 0 \
999        0 1 0 1 1 0 \
1000        0 0 1 1 0 0 \
1001        1 1 0 0 0 0 \
1002        1 1 0 0 0 0 \
1003        0 0 1 1 0 0 \
1004        0 0 1 1 0 0 \
1005        1 1 0 0 0 0 \
1006        0 1 0 1 1 1 \
1007       ]
1008test mathop-23.2 { comparison ops, string } {
1009    set res {}
1010    set todo {a {a b} {5 b b c} {d c b a} {xy xy} {gy ef ef ab}}
1011    set a x
1012    lappend todo [list $a $a]
1013    foreach vals $todo {
1014        foreach op {< <= > >= == eq} {
1015            lappend res [TestOp $op {*}$vals]
1016        }
1017    }
1018    set res
1019} [list 1 1 1 1 1 1 \
1020        1 1 0 0 0 0 \
1021        0 1 0 0 0 0 \
1022        0 0 1 1 0 0 \
1023        0 1 0 1 1 1 \
1024        0 0 0 1 0 0 \
1025        0 1 0 1 1 1 \
1026       ]
1027test mathop-23.3 { comparison ops, nonequal} {
1028    set res {}
1029    foreach vals {{a b} {17.0 0x11} {foo foo} {10 10}} {
1030        foreach op {!= ne} {
1031            lappend res [TestOp $op {*}$vals]
1032        }
1033    }
1034    set res
1035} [list 1 1  0 1  0 0  0 0 ]
1036
1037test mathop-24.1 { binary ops } {
1038    set res {}
1039    foreach vals {{3 5} {17 7} {199 5} {293234675763434238476239486 17} \
1040                  {5 1} {0 7}} {
1041        foreach op {% << >> in ni} {
1042            lappend res [TestOp $op {*}$vals]
1043        }
1044    }
1045    set res
1046} [list 3 96 0 0 1  3 2176 0 0 1  4 6368 6 0 1 \
1047        14 38434855421664852505557661908992 2237203031642412097749 0 1 \
1048        0 10 2 0 1  0 0 0 0 1]
1049test mathop-24.2 { binary ops, modulo } {
1050    # Test different combinations to get all code paths
1051    set res {}
1052
1053    set bigbig 14372423674564535234543545248972634923869
1054    set big       12135435435354435435342423948763867876
1055    set wide                              12345678912345
1056    set negwide                          -12345678912345
1057    set small                                          5
1058    set neg                                           -5
1059
1060    lappend res [TestOp % $bigbig  $big]
1061    lappend res [TestOp % $wide    $big]
1062    lappend res [TestOp % $negwide $big]
1063    lappend res [TestOp % $small   $big]
1064    lappend res [TestOp % $neg     $big]
1065    lappend res [TestOp % $small  $wide]
1066    lappend res [TestOp % $neg    $wide]
1067    lappend res [TestOp % $wide  $small]
1068    set res
1069} [list   4068119104883679098115293636215358685 \
1070                                 12345678912345 \
1071         12135435435354435435342411603084955531 \
1072                                              5 \
1073         12135435435354435435342423948763867871 \
1074                                              5 \
1075                                 12345678912340 \
1076                                              0 \
1077          ]
1078test mathop-24.3 { binary ops, bad values } {
1079    set res {}
1080    set exp {}
1081    foreach op {% << >>} {
1082        lappend res [TestOp $op x 1]
1083        lappend exp "can't use non-numeric string as operand of \"$op\" ARITH DOMAIN {non-numeric string}"
1084        lappend res [TestOp $op 1 x]
1085        lappend exp "can't use non-numeric string as operand of \"$op\" ARITH DOMAIN {non-numeric string}"
1086    }
1087    foreach op {% << >>} {
1088        lappend res [TestOp $op 5.0 1]
1089        lappend exp "can't use floating-point value as operand of \"$op\" ARITH DOMAIN {floating-point value}"
1090        lappend res [TestOp $op 1 5.0]
1091        lappend exp "can't use floating-point value as operand of \"$op\" ARITH DOMAIN {floating-point value}"
1092    }
1093    foreach op {in ni} {
1094        lappend res [TestOp $op 5 "a b \{ c"]
1095        lappend exp "unmatched open brace in list TCL VALUE LIST BRACE"
1096    }
1097    lappend res [TestOp % 5 0]
1098    lappend exp "divide by zero ARITH DIVZERO {divide by zero}"
1099    lappend res [TestOp % 9838923468297346238478737647637375 0]
1100    lappend exp "divide by zero ARITH DIVZERO {divide by zero}"
1101    lappend res [TestOp / 5 0]
1102    lappend exp "divide by zero ARITH DIVZERO {divide by zero}"
1103    lappend res [TestOp / 9838923468297346238478737647637375 0]
1104    lappend exp "divide by zero ARITH DIVZERO {divide by zero}"
1105    expr {$res eq $exp ? 0 : $res}
1106} 0
1107test mathop-24.4 { binary ops, negative shift } {
1108    set res {}
1109
1110    set big      -12135435435354435435342423948763867876
1111    set wide                             -12345678912345
1112    set small                                         -1
1113
1114    lappend res [TestOp << 10 $big]
1115    lappend res [TestOp << 10 $wide]
1116    lappend res [TestOp << 10 $small]
1117    lappend res [TestOp >> 10 $big]
1118    lappend res [TestOp >> 10 $wide]
1119    lappend res [TestOp >> 10 $small]
1120
1121    set exp [lrepeat 6 "negative shift argument NONE"]
1122    expr {$res eq $exp ? 0 : $res}
1123} 0
1124test mathop-24.5 { binary ops, large shift } {
1125    set res {}
1126    set exp {}
1127
1128    set big      12135435435354435435342423948763867876
1129    set wide                             12345678912345
1130    set small                                         1
1131
1132    lappend res [TestOp << 1 2147483648]
1133    lappend exp "integer value too large to represent NONE"
1134    lappend res [TestOp << 1 4294967296]
1135    lappend exp "integer value too large to represent NONE"
1136    lappend res [TestOp << $small $wide]
1137    lappend exp "integer value too large to represent NONE"
1138    lappend res [TestOp << $small $big]
1139    lappend exp "integer value too large to represent NONE"
1140    lappend res [TestOp >> $big $wide]
1141    lappend exp 0
1142    lappend res [TestOp >> $big $big]
1143    lappend exp 0
1144    lappend res [TestOp >> $small 70]
1145    lappend exp 0
1146    lappend res [TestOp >> $wide 70]
1147    lappend exp 0
1148    lappend res [TestOp >> -$big $wide]
1149    lappend exp -1
1150    lappend res [TestOp >> -$wide $wide]
1151    lappend exp -1
1152    lappend res [TestOp >> -$small $wide]
1153    lappend exp -1
1154    lappend res [TestOp >> -$small 70]
1155    lappend exp -1
1156    lappend res [TestOp >> -$wide 70]
1157    lappend exp -1
1158
1159    expr {$res eq $exp ? 0 : $res}
1160} 0
1161test mathop-24.6 { binary ops, shift } {
1162    # Test different combinations to get all code paths
1163    set res {}
1164
1165    set bigbig 14372423674564535234543545248972634923869
1166    set big       12135435435354435435342423948763867876
1167    set wide                              12345678912345
1168    set negwide                          -12345678912345
1169    set small                                          5
1170    set neg                                           -5
1171
1172    lappend res [TestOp << $wide $small]
1173    lappend res [TestOp >> $wide $small]
1174    set res
1175} [list   395061725195040 \
1176             385802466010 \
1177          ]
1178test mathop-24.7 { binary ops, list search } {
1179    set res {}
1180
1181    foreach op {in ni} {
1182        lappend res [TestOp $op 5 {7 5 8}]
1183        lappend res [TestOp $op hej {foo bar hej}]
1184        lappend res [TestOp $op 5 {7 0x5 8}]
1185    }
1186    set res
1187} [list 1 1 0  0 0 1]
1188test mathop-24.8 { binary ops, too many } {
1189    set exp {}
1190    foreach op {<< >> % != ne in ni ~ !} {
1191        set res [TestOp $op 7 8 9]
1192        if {[string match "wrong # args: should be * TCL WRONGARGS" $res]} {
1193            lappend exp 0
1194        } else {
1195            lappend exp $res
1196        }
1197    }
1198    set exp
1199} {0 0 0 0 0 0 0 0 0}
1200
1201test mathop-25.1  { exp operator } {TestOp **        } 1
1202test mathop-25.2  { exp operator } {TestOp **   0    } 0
1203test mathop-25.3  { exp operator } {TestOp **   0   5} 0
1204test mathop-25.4  { exp operator } {TestOp ** 7.5    } 7.5
1205test mathop-25.5  { exp operator } {TestOp **   1   5} 1
1206test mathop-25.6  { exp operator } {TestOp **   5   1} 5
1207test mathop-25.7  { exp operator } {TestOp ** 4 3 2 1} 262144
1208test mathop-25.8  { exp operator } {TestOp ** 5.5   4} 915.0625
1209test mathop-25.8a { exp operator } {TestOp ** 4.0  -1} 0.25
1210test mathop-25.8b { exp operator } {TestOp ** 2.0  -2} 0.25
1211test mathop-25.9  { exp operator } {TestOp **  16 3.5} 16384.0
1212test mathop-25.10 { exp operator } {TestOp ** 3.5   0} 1.0
1213test mathop-25.11 { exp operator } {TestOp ** 378   0} 1
1214test mathop-25.12 { exp operator } {TestOp ** 7.8   1} 7.8
1215test mathop-25.13 { exp operator } {TestOp ** 748   1} 748
1216test mathop-25.14 { exp operator } {TestOp ** 1.6  -1} 0.625
1217test mathop-25.15 { exp operator } {TestOp ** 683  -1} 0
1218test mathop-25.16 { exp operator } {TestOp **   1  -1} 1
1219test mathop-25.17 { exp operator } {TestOp **  -1  -1} -1
1220test mathop-25.18 { exp operator } {TestOp **  -1  -2} 1
1221test mathop-25.19 { exp operator } {TestOp **  -1   3} -1
1222test mathop-25.20 { exp operator } {TestOp **  -1   4} 1
1223test mathop-25.21 { exp operator } {TestOp **   2  63} 9223372036854775808
1224test mathop-25.22 { exp operator } {TestOp **   2 256} 115792089237316195423570985008687907853269984665640564039457584007913129639936
1225set big 83756485763458746358734658473567847567473
1226test mathop-25.23 { exp operator } {TestOp ** $big  2} 7015148907444467657897585474493757781161998914521537835809623408157343003287605729
1227test mathop-25.24 { exp operator } {TestOp ** $big  0} 1
1228test mathop-25.25 { exp operator } {TestOp ** $big  1} $big
1229test mathop-25.26 { exp operator } {TestOp ** $big -1} 0
1230test mathop-25.27 { exp operator } {TestOp ** $big -2} 0
1231test mathop-25.28 { exp operator } {TestOp ** $big -$big} 0
1232test mathop-25.29 { exp operator } {expr {[set res [TestOp **  $big -1.0]]   >  0 && $res < 1.2e-41}} 1
1233test mathop-25.30 { exp operator } {expr {[set res [TestOp **  $big -1e-18]] >  0 && $res < 1}} 1
1234test mathop-25.31 { exp operator } {expr {[set res [TestOp ** -$big -1.0]]   > -1 && $res < 0}} 1
1235test mathop-25.32 { exp operator } {expr {[set res [TestOp ** -$big -2.0]]   >  0 && $res < 1}} 1
1236test mathop-25.33 { exp operator } {expr {[set res [TestOp ** -$big -3.0]]   > -1 && $res < 0}} 1
1237test mathop-25.34 { exp operator } {TestOp ** $big -1e-30} 1.0
1238test mathop-25.35 { exp operator } {TestOp ** $big -1e+30} 0.0
1239test mathop-25.36 { exp operator } {TestOp **    0  $big}             0
1240test mathop-25.37 { exp operator } {TestOp **    1  $big}             1
1241test mathop-25.38 { exp operator } {TestOp **   -1  $big}            -1
1242test mathop-25.39 { exp operator } {TestOp **   -1  [expr {$big+1}]}  1
1243test mathop-25.40 { exp operator (small exponent power helper and its boundaries) } {
1244    set pwr 0
1245    set res 1
1246    while {[incr pwr] <= 17 && [set i [TestOp ** 15 $pwr]] == [set res [expr {$res * 15}]]} {}
1247    list [incr pwr -1] $res
1248} {17 98526125335693359375}
1249test mathop-25.41 { exp operator errors } {
1250    set res {}
1251    set exp {}
1252
1253    set huge     [string repeat 145782 1000]
1254    set big      12135435435354435435342423948763867876
1255    set wide                             12345678912345
1256    set small                                         2
1257
1258    lappend res [TestOp ** 0 -5]
1259    lappend exp "exponentiation of zero by negative power ARITH DOMAIN {exponentiation of zero by negative power}"
1260    lappend res [TestOp ** 0.0 -5.0]
1261    lappend exp "exponentiation of zero by negative power ARITH DOMAIN {exponentiation of zero by negative power}"
1262    lappend res [TestOp ** $small $wide]
1263    lappend exp "exponent too large NONE"
1264    lappend res [TestOp ** 2 $big]
1265    lappend exp "exponent too large NONE"
1266    lappend res [TestOp ** $huge 2.1]
1267    lappend exp "Inf"
1268    lappend res [TestOp ** 2 foo]
1269    lappend exp "can't use non-numeric string as operand of \"**\" ARITH DOMAIN {non-numeric string}"
1270    lappend res [TestOp ** foo 2]
1271    lappend exp "can't use non-numeric string as operand of \"**\" ARITH DOMAIN {non-numeric string}"
1272
1273    expr {$res eq $exp ? 0 : $res}
1274} 0
1275
1276test mathop-26.1 { misc ops, size combinations } {
1277    set big1      12135435435354435435342423948763867876
1278    set big2       2746237174783836746262564892918327847
1279    set wide1                             87321847232215
1280    set wide2                             12345678912345
1281    set small1                                     87345
1282    set small2                                     16753
1283
1284    set res {}
1285    foreach op {+ * - /} {
1286        lappend res [TestOp $op $big1   $big2]
1287        lappend res [TestOp $op $big1   $wide2]
1288        lappend res [TestOp $op $big1   $small2]
1289        lappend res [TestOp $op $wide1  $big2]
1290        lappend res [TestOp $op $wide1  $wide2]
1291        lappend res [TestOp $op $wide1  $small2]
1292        lappend res [TestOp $op $small1 $big2]
1293        lappend res [TestOp $op $small1 $wide2]
1294        lappend res [TestOp $op $small1 $small2]
1295    }
1296    set res
1297} [list \
1298           14881672610138272181604988841682195723 \
1299           12135435435354435435342436294442780221 \
1300           12135435435354435435342423948763884629 \
1301           2746237174783836746262652214765560062 \
1302           99667526144560 \
1303           87321847248968 \
1304           2746237174783836746262564892918415192 \
1305           12345678999690 \
1306           104098 \
1307           33326783924759424684447891401270222910405366244661685890993770489959542972 \
1308           149820189346379518024969783068410988366610965329220 \
1309           203304949848492856848291628413641078526628 \
1310           239806503039903915972546163440347114360602909991105 \
1311           1078047487961768329845194175 \
1312           1462902906681297895 \
1313           239870086031494220602303730571951345796215 \
1314           1078333324598774025 \
1315           1463290785 \
1316           9389198260570598689079859055845540029 \
1317           12135435435354435435342411603084955531 \
1318           12135435435354435435342423948763851123 \
1319           -2746237174783836746262477571071095632 \
1320           74976168319870 \
1321           87321847215462 \
1322           -2746237174783836746262564892918240502 \
1323           -12345678825000 \
1324           70592 \
1325           4 \
1326           982970278225822587257201 \
1327           724373869477373332259441529801460 \
1328           0 \
1329           7 \
1330           5212311062 \
1331           0 \
1332           0 \
1333           5 \
1334          ]
1335test mathop-26.2 { misc ops, corner cases } {
1336    set res {}
1337    lappend res [TestOp - 0 -2147483648]                  ;# -2**31
1338    lappend res [TestOp - 0 -9223372036854775808]         ;# -2**63
1339    lappend res [TestOp / -9223372036854775808 -1]
1340    lappend res [TestOp * 2147483648 2]
1341    lappend res [TestOp * 9223372036854775808 2]
1342    set res
1343} [list 2147483648 9223372036854775808 9223372036854775808 4294967296 18446744073709551616]
1344
1345test mathop-27.1 {lt operator} {::tcl::mathop::lt} 1
1346test mathop-27.2 {lt operator} {::tcl::mathop::lt a} 1
1347test mathop-27.3 {lt operator} {::tcl::mathop::lt a b} 1
1348test mathop-27.4 {lt operator} {::tcl::mathop::lt b a} 0
1349test mathop-27.5 {lt operator} {::tcl::mathop::lt a a} 0
1350test mathop-27.6 {lt operator} {::tcl::mathop::lt a b c} 1
1351test mathop-27.7 {lt operator} {::tcl::mathop::lt b a c} 0
1352test mathop-27.8 {lt operator} {::tcl::mathop::lt a c b} 0
1353test mathop-27.9 {lt operator} {::tcl::mathop::lt 012 0x0} 1
1354
1355test mathop-28.1 {le operator} {::tcl::mathop::le} 1
1356test mathop-28.2 {le operator} {::tcl::mathop::le a} 1
1357test mathop-28.3 {le operator} {::tcl::mathop::le a b} 1
1358test mathop-28.4 {le operator} {::tcl::mathop::le b a} 0
1359test mathop-28.5 {le operator} {::tcl::mathop::le a a} 1
1360test mathop-28.6 {le operator} {::tcl::mathop::le a b c} 1
1361test mathop-28.7 {le operator} {::tcl::mathop::le b a c} 0
1362test mathop-28.8 {le operator} {::tcl::mathop::le a c b} 0
1363test mathop-28.9 {le operator} {::tcl::mathop::le 012 0x0} 1
1364
1365test mathop-29.1 {gt operator} {::tcl::mathop::gt} 1
1366test mathop-29.2 {gt operator} {::tcl::mathop::gt a} 1
1367test mathop-29.3 {gt operator} {::tcl::mathop::gt a b} 0
1368test mathop-29.4 {gt operator} {::tcl::mathop::gt b a} 1
1369test mathop-29.5 {gt operator} {::tcl::mathop::gt a a} 0
1370test mathop-29.6 {gt operator} {::tcl::mathop::gt c b a} 1
1371test mathop-29.7 {gt operator} {::tcl::mathop::gt b a c} 0
1372test mathop-29.8 {gt operator} {::tcl::mathop::gt a c b} 0
1373test mathop-29.9 {gt operator} {::tcl::mathop::gt 0x0 012} 1
1374
1375test mathop-30.1 {ge operator} {::tcl::mathop::ge} 1
1376test mathop-30.2 {ge operator} {::tcl::mathop::ge a} 1
1377test mathop-30.3 {ge operator} {::tcl::mathop::ge a b} 0
1378test mathop-30.4 {ge operator} {::tcl::mathop::ge b a} 1
1379test mathop-30.5 {ge operator} {::tcl::mathop::ge a a} 1
1380test mathop-30.6 {ge operator} {::tcl::mathop::ge c b a} 1
1381test mathop-30.7 {ge operator} {::tcl::mathop::ge b a c} 0
1382test mathop-30.8 {ge operator} {::tcl::mathop::ge a c b} 0
1383test mathop-30.9 {ge operator} {::tcl::mathop::ge 0x0 012} 1
1384
1385if 0 {
1386    # Compare ops to expr bytecodes
1387    namespace import ::tcl::mathop::*
1388    proc _X {a b c} {
1389        set x [+ $a [- $b $c]]
1390        set y [expr {$a + ($b - $c)}]
1391        set z [< $a $b $c]
1392    }
1393    set ::tcl_traceCompile 2
1394    _X 3 4 5
1395    set ::tcl_traceCompile 0
1396}
1397
1398# cleanup
1399namespace delete ::testmathop
1400namespace delete ::testmathop2
1401::tcltest::cleanupTests
1402return
1403
1404# Local Variables:
1405# mode: tcl
1406# End:
1407