xref: /titanic_51/usr/src/lib/libshell/common/tests/arith.sh (revision 3e14f97f673e8a630f076077de35afdd43dc1587)
1da2e3ebdSchin########################################################################
2da2e3ebdSchin#                                                                      #
3da2e3ebdSchin#               This software is part of the ast package               #
4*3e14f97fSRoger A. Faulkner#          Copyright (c) 1982-2010 AT&T Intellectual Property          #
5da2e3ebdSchin#                      and is licensed under the                       #
6da2e3ebdSchin#                  Common Public License, Version 1.0                  #
77c2fbfb3SApril Chin#                    by AT&T Intellectual Property                     #
8da2e3ebdSchin#                                                                      #
9da2e3ebdSchin#                A copy of the License is available at                 #
10da2e3ebdSchin#            http://www.opensource.org/licenses/cpl1.0.txt             #
11da2e3ebdSchin#         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         #
12da2e3ebdSchin#                                                                      #
13da2e3ebdSchin#              Information and Software Systems Research               #
14da2e3ebdSchin#                            AT&T Research                             #
15da2e3ebdSchin#                           Florham Park NJ                            #
16da2e3ebdSchin#                                                                      #
17da2e3ebdSchin#                  David Korn <dgk@research.att.com>                   #
18da2e3ebdSchin#                                                                      #
19da2e3ebdSchin########################################################################
20da2e3ebdSchinfunction err_exit
21da2e3ebdSchin{
22da2e3ebdSchin	print -u2 -n "\t"
23da2e3ebdSchin	print -u2 -r ${Command}[$1]: "${@:2}"
24da2e3ebdSchin	let Errors+=1
25da2e3ebdSchin}
26da2e3ebdSchinalias err_exit='err_exit $LINENO'
27da2e3ebdSchin
28da2e3ebdSchinCommand=${0##*/}
29da2e3ebdSchininteger Errors=0
3034f9b3eeSRoland Mainz
3134f9b3eeSRoland Mainztmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
3234f9b3eeSRoland Mainztrap "cd /; rm -rf $tmp" EXIT
3334f9b3eeSRoland Mainz
3434f9b3eeSRoland Mainztrap '' FPE # NOTE: osf.alpha requires this (no ieee math)
3534f9b3eeSRoland Mainz
36da2e3ebdSchininteger x=1 y=2 z=3
37da2e3ebdSchinif	(( 2+2 != 4 ))
38da2e3ebdSchinthen	err_exit 2+2!=4
39da2e3ebdSchinfi
40da2e3ebdSchinif	((x+y!=z))
41da2e3ebdSchinthen	err_exit x+y!=z
42da2e3ebdSchinfi
43da2e3ebdSchinif	(($x+$y!=$z))
44da2e3ebdSchinthen	err_exit $x+$y!=$z
45da2e3ebdSchinfi
46da2e3ebdSchinif	(((x|y)!=z))
47da2e3ebdSchinthen	err_exit "(x|y)!=z"
48da2e3ebdSchinfi
49da2e3ebdSchinif	((y >= z))
50da2e3ebdSchinthen	err_exit "y>=z"
51da2e3ebdSchinfi
52da2e3ebdSchinif	((y+3 != z+2))
53da2e3ebdSchinthen	err_exit "y+3!=z+2"
54da2e3ebdSchinfi
55da2e3ebdSchinif	((y<<2 != 1<<3))
56da2e3ebdSchinthen	err_exit "y<<2!=1<<3"
57da2e3ebdSchinfi
58da2e3ebdSchinif	((133%10 != 3))
59da2e3ebdSchinthen	err_exit "133%10!=3"
60da2e3ebdSchin	if	(( 2.5 != 2.5 ))
61da2e3ebdSchin	then	err_exit 2.5!=2.5
62da2e3ebdSchin	fi
63da2e3ebdSchinfi
64da2e3ebdSchind=0
65da2e3ebdSchin((d || 1)) || err_exit 'd=0; ((d||1))'
66da2e3ebdSchinif	(( d++!=0))
67da2e3ebdSchinthen	err_exit "d++!=0"
68da2e3ebdSchinfi
69da2e3ebdSchinif	(( --d!=0))
70da2e3ebdSchinthen	err_exit "--d!=0"
71da2e3ebdSchinfi
72da2e3ebdSchinif	(( (d++,6)!=6 && d!=1))
73da2e3ebdSchinthen	err_exit '(d++,6)!=6 && d!=1'
74da2e3ebdSchinfi
75da2e3ebdSchind=0
76da2e3ebdSchinif	(( (1?2+1:3*4+d++)!=3 || d!=0))
77da2e3ebdSchinthen	err_exit '(1?2+1:3*4+d++) !=3'
78da2e3ebdSchinfi
79da2e3ebdSchinfor	((i=0; i < 20; i++))
80da2e3ebdSchindo	:
81da2e3ebdSchindone
82da2e3ebdSchinif	(( i != 20))
83da2e3ebdSchinthen	err_exit 'for (( expr)) failed'
84da2e3ebdSchinfi
85da2e3ebdSchinfor	((i=0; i < 20; i++)); do	: ; done
86da2e3ebdSchinif	(( i != 20))
87da2e3ebdSchinthen	err_exit 'for (( expr));... failed'
88da2e3ebdSchinfi
89da2e3ebdSchinfor	((i=0; i < 20; i++)) do	: ; done
90da2e3ebdSchinif	(( i != 20))
91da2e3ebdSchinthen	err_exit 'for (( expr))... failed'
92da2e3ebdSchinfi
93da2e3ebdSchinif	(( (i?0:1) ))
94da2e3ebdSchinthen	err_exit '(( (i?0:1) )) failed'
95da2e3ebdSchinfi
96da2e3ebdSchinif	(( (1 || 1 && 0) != 1 ))
97da2e3ebdSchinthen	err_exit '( (1 || 1 && 0) != 1) failed'
98da2e3ebdSchinfi
99da2e3ebdSchinif	(( (_=1)+(_x=0)-_ ))
100da2e3ebdSchinthen	err_exit '(_=1)+(_x=0)-_ failed'
101da2e3ebdSchinfi
102da2e3ebdSchinif	((  (3^6) != 5))
103da2e3ebdSchinthen	err_exit '((3^6) != 5) failed'
104da2e3ebdSchinfi
105da2e3ebdSchininteger x=1
106da2e3ebdSchinif	(( (x=-x) != -1 ))
107da2e3ebdSchinthen	err_exit '(x=-x) != -1 failed'
108da2e3ebdSchinfi
109da2e3ebdSchini=2
110da2e3ebdSchinif	(( 1$(($i))3 != 123 ))
111da2e3ebdSchinthen	err_exit ' 1$(($i))3 failed'
112da2e3ebdSchinfi
113da2e3ebdSchin((pi=4*atan(1.)))
114da2e3ebdSchinpoint=(
115da2e3ebdSchin	float x
116da2e3ebdSchin	float y
117da2e3ebdSchin)
118da2e3ebdSchin(( point.x = cos(pi/6), point.y = sin(pi/6) ))
119da2e3ebdSchinif	(( point.x*point.x + point.y*point.y > 1.01 ))
120da2e3ebdSchinthen	err_exit 'cos*cos +sin*sin > 1.01'
121da2e3ebdSchinfi
122da2e3ebdSchinif	(( point.x*point.x + point.y*point.y < .99 ))
123da2e3ebdSchinthen	err_exit 'cos*cos +sin*sin < .99'
124da2e3ebdSchinfi
125da2e3ebdSchinif [[ $((y=x=1.5)) != 1 ]]
126da2e3ebdSchinthen	err_exit 'typecast not working in arithmetic evaluation'
127da2e3ebdSchinfi
128da2e3ebdSchintypeset -E x=1.5
129da2e3ebdSchin( ((x++))  ) 2>/dev/null
130da2e3ebdSchinif [[ $? == 0 ]]
131da2e3ebdSchinthen	err_exit 'postincrement of floating point allowed'
132da2e3ebdSchinfi
133da2e3ebdSchin( ((++x))  ) 2>/dev/null
134da2e3ebdSchinif [[ $? == 0 ]]
135da2e3ebdSchinthen	err_exit 'preincrement of floating point allowed'
136da2e3ebdSchinfi
137da2e3ebdSchinx=1.5
138da2e3ebdSchin( ((x%1.1))  ) 2>/dev/null
139da2e3ebdSchinif [[ $? == 0 ]]
140da2e3ebdSchinthen	err_exit 'floating point allowed with % operator'
141da2e3ebdSchinfi
142da2e3ebdSchinx=.125
143da2e3ebdSchinif	[[ $(( 4 * x/2 )) != 0.25 ]]
144da2e3ebdSchinthen	err_exit '(( 4 * x/2 )) is not 0.25, with x=.125'
145da2e3ebdSchinfi
146da2e3ebdSchinif	[[ $(( pow(2,3) )) != 8 ]]
147da2e3ebdSchinthen	err_exit '$(( pow(2,3) )) != 8'
148da2e3ebdSchinfi
149da2e3ebdSchin( [[ $(( pow(2,(3)) )) == 8 ]] ) 2> /dev/null
150da2e3ebdSchinif	(( $? ))
151da2e3ebdSchinthen	err_exit '$(( pow(2,(3)) )) != 8'
152da2e3ebdSchinfi
153da2e3ebdSchinunset x
154da2e3ebdSchininteger x=1; integer x=1
155da2e3ebdSchinif	[[ $x != 1 ]]
156da2e3ebdSchinthen	err_exit 'two consecutive integer x=1 not working'
157da2e3ebdSchinfi
158da2e3ebdSchinunset z
159da2e3ebdSchin{ z=$(typeset -RZ2 z2; (( z2 = 8 )); print $z2) ;} 2>/dev/null
160da2e3ebdSchinif [[ $z != "08" ]]
161da2e3ebdSchinthen	err_exit "typeset -RZ2 leading 0 decimal not working [z=$z]"
162da2e3ebdSchinfi
163da2e3ebdSchin{ z=$(typeset -RZ3 z3; (( z3 = 8 )); print $z3) ;} 2>/dev/null
164da2e3ebdSchinif [[ $z != "008" ]]
165da2e3ebdSchinthen	err_exit "typeset -RZ3 leading 0 decimal not working [z=$z]"
166da2e3ebdSchinfi
167da2e3ebdSchinunset z
168da2e3ebdSchintypeset -Z3 z=010
169da2e3ebdSchin(( z=z+1))
170da2e3ebdSchinif	[[ $z != 011 ]]
171da2e3ebdSchinthen	err_exit "leading 0's in -Z not treated as decimal"
172da2e3ebdSchinfi
173da2e3ebdSchinunset x
174da2e3ebdSchininteger x=0
175da2e3ebdSchinif	[[ $((x+=1)) != 1  ]] || ((x!=1))
176da2e3ebdSchinthen	err_exit "+= not working"
177da2e3ebdSchin	x=1
178da2e3ebdSchinfi
179da2e3ebdSchinx=1
180da2e3ebdSchinif	[[ $((x*=5)) != 5  ]] || ((x!=5))
181da2e3ebdSchinthen	err_exit "*= not working"
182da2e3ebdSchin	x=5
183da2e3ebdSchinfi
184da2e3ebdSchinif	[[ $((x%=4)) != 1  ]] || ((x!=1))
185da2e3ebdSchinthen	err_exit "%= not working"
186da2e3ebdSchin	x=1
187da2e3ebdSchinfi
188da2e3ebdSchinif	[[ $((x|=6)) != 7  ]] || ((x!=7))
189da2e3ebdSchinthen	err_exit "|= not working"
190da2e3ebdSchin	x=7
191da2e3ebdSchinfi
192da2e3ebdSchinif	[[ $((x&=5)) != 5  ]] || ((x!=5))
193da2e3ebdSchinthen	err_exit "&= not working"
194da2e3ebdSchin	x=5
195da2e3ebdSchinfi
196da2e3ebdSchinfunction newscope
197da2e3ebdSchin{
198da2e3ebdSchin	float x=1.5
199da2e3ebdSchin	(( x += 1 ))
200da2e3ebdSchin	print -r -- $x
201da2e3ebdSchin}
202da2e3ebdSchinif	[[ $(newscope) != 2.5 ]]
203da2e3ebdSchinthen	err_exit "arithmetic using wrong scope"
204da2e3ebdSchinfi
205da2e3ebdSchinunset x
206da2e3ebdSchininteger y[3]=9 y[4]=2 i=3
207da2e3ebdSchin(( x = y[3] + y[4] ))
208da2e3ebdSchinif	[[ $x != 11 ]]
209da2e3ebdSchinthen	err_exit "constant index array arithmetic failure"
210da2e3ebdSchinfi
211da2e3ebdSchin(( x = $empty y[3] + y[4] ))
212da2e3ebdSchinif	[[ $x != 11 ]]
213da2e3ebdSchinthen	err_exit "empty constant index array arithmetic failure"
214da2e3ebdSchinfi
215da2e3ebdSchin(( x = y[i] + y[i+1] ))
216da2e3ebdSchinif	[[ $x != 11 ]]
217da2e3ebdSchinthen	err_exit "variable subscript index array arithmetic failure"
218da2e3ebdSchinfi
219da2e3ebdSchininteger a[5]=3 a[2]=4
220da2e3ebdSchin(( x = y[a[5]] + y[a[2]] ))
221da2e3ebdSchinif	[[ $x != 11 ]]
222da2e3ebdSchinthen	err_exit "nested subscript index array arithmetic failure"
223da2e3ebdSchinfi
224da2e3ebdSchinunset y
225da2e3ebdSchintypeset -Ai y
226da2e3ebdSchiny[three]=9 y[four]=2
227da2e3ebdSchinthree=four
228da2e3ebdSchinfour=three
229da2e3ebdSchin(( x = y[three] + y[four] ))
230da2e3ebdSchinif	[[ $x != 11 ]]
231da2e3ebdSchinthen	err_exit "constant associative array arithmetic failure"
232da2e3ebdSchinfi
233da2e3ebdSchin(( x = y[$three] + y[$four] ))
234da2e3ebdSchinif	[[ $x != 11 ]]
235da2e3ebdSchinthen	err_exit "variable subscript associative array arithmetic failure"
236da2e3ebdSchinfi
237da2e3ebdSchin$SHELL -nc '((a = 1))' 2> /dev/null || err_exit "sh -n fails with arithmetic"
238da2e3ebdSchin$SHELL -nc '((a.b++))' 2> /dev/null || err_exit "sh -n fails with arithmetic2"
239da2e3ebdSchinunset z
240da2e3ebdSchinfloat z=7.5
241da2e3ebdSchinif	{ (( z%2 != 1));} 2> /dev/null
242da2e3ebdSchinthen	err_exit '% not working on floating point'
243da2e3ebdSchinfi
244da2e3ebdSchinchr=(a ' ' '=' '\r' '\n' '\\' '\"' '$' "\\'" '[' ']' '(' ')' '<' '\xab' '\040' '`' '{' '}' '*' '\E')
245da2e3ebdSchinif	(('a' == 97))
246da2e3ebdSchinthen	val=(97 32  61 13 10 92 34 36 39 91 93 40 41 60 171 32 96 123 125 42 27)
247da2e3ebdSchinelse	val=(129 64 126 13 21 224 127 91 125 173 189 77 93 76 171 32 121 192 208 92 39 21)
248da2e3ebdSchinfi
249da2e3ebdSchinq=0
250da2e3ebdSchinfor ((i=0; i < ${#chr[@]}; i++))
251da2e3ebdSchindo	if	(( '${chr[i]}' != ${val[i]} ))
252da2e3ebdSchin	then	err_exit "(( '${chr[i]}'  !=  ${val[i]} ))"
253da2e3ebdSchin	fi
254da2e3ebdSchin	if	[[ $(( '${chr[i]}' )) != ${val[i]} ]]
255da2e3ebdSchin	then	err_exit "(( '${chr[i]}' )) !=  ${val[i]}"
256da2e3ebdSchin	fi
257da2e3ebdSchin	if	[[ $(( L'${chr[i]}' )) != ${val[i]} ]]
258da2e3ebdSchin	then	err_exit "(( '${chr[i]}' )) !=  ${val[i]}"
259da2e3ebdSchin	fi
260da2e3ebdSchin	if	eval '((' "'${chr[i]}'" != ${val[i]} '))'
261da2e3ebdSchin	then	err_exit "eval (( '${chr[i]}'  !=  ${val[i]} ))"
262da2e3ebdSchin	fi
263da2e3ebdSchin	if	eval '((' "'${chr[i]}'" != ${val[i]} ' + $q ))'
264da2e3ebdSchin	then	err_exit "eval (( '${chr[i]}'  !=  ${val[i]} ))"
265da2e3ebdSchin	fi
266da2e3ebdSchindone
267da2e3ebdSchinunset x
268da2e3ebdSchintypeset -ui x=4294967293
269da2e3ebdSchin[[ $x != 4294967293 ]]  && err_exit "unsigned integers not working"
270da2e3ebdSchinx=32767
271da2e3ebdSchinx=x+1
272da2e3ebdSchin[[ $x != 32768 ]]  && err_exit "unsigned integer addition not working"
273da2e3ebdSchinunset x
274da2e3ebdSchinfloat x=99999999999999999999999999
275da2e3ebdSchinif	(( x < 1e20 ))
276da2e3ebdSchinthen	err_exit 'large integer constants not working'
277da2e3ebdSchinfi
278da2e3ebdSchinunset x  y
279da2e3ebdSchinfunction foobar
280da2e3ebdSchin{
281da2e3ebdSchin	nameref x=$1
282da2e3ebdSchin	(( x +=1 ))
283da2e3ebdSchin	print $x
284da2e3ebdSchin}
285da2e3ebdSchinx=0 y=4
286da2e3ebdSchinif	[[ $(foobar y) != 5 ]]
287da2e3ebdSchinthen	err_exit 'name references in arithmetic statements in functions broken'
288da2e3ebdSchinfi
289da2e3ebdSchinif	(( 2**3 != pow(2,3) ))
290da2e3ebdSchinthen	err_exit '2**3 not working'
291da2e3ebdSchinfi
292da2e3ebdSchinif	(( 2**3*2 != pow(2,3)*2 ))
293da2e3ebdSchinthen	err_exit '2**3*2 not working'
294da2e3ebdSchinfi
295da2e3ebdSchinif	(( 4**3**2 != pow(4,pow(3,2)) ))
296da2e3ebdSchinthen	err_exit '4**3**2 not working'
297da2e3ebdSchinfi
298da2e3ebdSchinif	(( (4**3)**2 != pow(pow(4,3),2) ))
299da2e3ebdSchinthen	err_exit '(4**3)**2 not working'
300da2e3ebdSchinfi
301da2e3ebdSchintypeset -Z3 x=11
302da2e3ebdSchintypeset -i x
303da2e3ebdSchinif	(( x != 11 ))
304da2e3ebdSchinthen	err_exit '-Z3 not treated as decimal'
305da2e3ebdSchinfi
306da2e3ebdSchinunset x
307da2e3ebdSchintypeset -ui x=-1
308da2e3ebdSchin(( x >= 0 )) || err_exit 'unsigned integer not working'
309da2e3ebdSchin(( $x >= 0 )) || err_exit 'unsigned integer not working as $x'
310da2e3ebdSchinunset x
311da2e3ebdSchintypeset -ui42 x=50
312da2e3ebdSchinif	[[ $x != 42#18 ]]
313da2e3ebdSchinthen	err_exit 'display of unsigned integers in non-decimal bases wrong'
314da2e3ebdSchinfi
315da2e3ebdSchin$SHELL -c 'i=0;(( ofiles[i] != -1 && (ofiles[i] < mins || mins == -1) ));exit 0' 2> /dev/null || err_exit 'lexical error with arithemtic expression'
316da2e3ebdSchin$SHELL -c '(( +1 == 1))' 2> /dev/null || err_exit 'unary + not working'
317da2e3ebdSchintypeset -E20 val=123.01234567890
318da2e3ebdSchin[[ $val == 123.0123456789 ]] || err_exit "rounding error val=$val"
319da2e3ebdSchinif	[[ $(print x$((10))=foo) != x10=foo ]]
320da2e3ebdSchinthen	err_exit 'parsing error with x$((10))=foo'
321da2e3ebdSchinfi
322da2e3ebdSchin$SHELL -c 'typeset x$((10))=foo' 2> /dev/null || err_exit 'typeset x$((10)) parse error'
323da2e3ebdSchinunset x
324da2e3ebdSchinx=$(( exp(log(2.0)) ))
325da2e3ebdSchin(( x > 1.999 && x < 2.001 )) || err_exit 'composite functions not working'
326da2e3ebdSchinunset x y n
327da2e3ebdSchintypeset -Z8 x=0 y=0
328da2e3ebdSchininteger n
329da2e3ebdSchinfor	(( n=0; n < 20; n++ ))
330da2e3ebdSchindo	let "x = $x+1"
331da2e3ebdSchin	(( y = $y+1 ))
332da2e3ebdSchindone
333da2e3ebdSchin(( x == n ))  || err_exit 'let with zero filled fields not working'
334da2e3ebdSchin(( y == n ))  || err_exit '((...)) with zero filled fields not working'
3357c2fbfb3SApril Chintypeset -RZ3 x=10
336da2e3ebdSchin[[ $(($x)) == 10 && $((1$x)) == 1010 ]] || err_exit 'zero filled fields not preserving leading zeros'
337da2e3ebdSchinunset y
338da2e3ebdSchin[[ $(let y=$x;print $y) == 10 && $(let y=1$x;print $y) == 1010 ]] || err_exit 'zero filled fields not preserving leading zeros with let'
339da2e3ebdSchinunset i ip ipx
340da2e3ebdSchintypeset -i hex=( 172 30 18 1)
341da2e3ebdSchintypeset -iu ip=0 ipx=0
342da2e3ebdSchininteger i
343da2e3ebdSchinfor	((i=0; i < 4; i++))
344da2e3ebdSchindo	(( ip =  (ip<<8) | hex[i]))
345da2e3ebdSchindone
346da2e3ebdSchinfor ((i=0; i < 4; i++))
347da2e3ebdSchindo	(( ipx = ip % 256 ))
348da2e3ebdSchin	(( ip /= 256 ))
349da2e3ebdSchin	(( ipx != hex[3-i] )) && err_exit "hex digit $((3-i)) not correct"
350da2e3ebdSchindone
351da2e3ebdSchinunset x
352da2e3ebdSchinx=010
353da2e3ebdSchin(( x == 8 )) || err_exit 'leading zeros not treated as octal arithmetic'
354da2e3ebdSchin(( $x == 8 )) || err_exit 'leading zeros not treated as octal arithmetic with $x'
355da2e3ebdSchinunset x
356da2e3ebdSchintypeset -Z x=010
357da2e3ebdSchin(( x == 10 )) || err_exit 'leading zeros not ignored for arithmetic'
358da2e3ebdSchin(( $x == 10 )) || err_exit 'leading zeros not ignored for arithmetic with $x'
359da2e3ebdSchintypeset -i i=x
360da2e3ebdSchin(( i == 10 )) || err_exit 'leading zeros not ignored for arithmetic assignment'
361da2e3ebdSchin(( ${x:0:1} == 0 )) || err_exit 'leading zero should not be stripped for x:a:b'
362da2e3ebdSchinc010=3
363da2e3ebdSchin(( c$x  == 3 )) || err_exit 'leading zero with variable should not be stripped'
3647c2fbfb3SApril Chin[[ $( ($SHELL -c '((++1))' 2>&1)2>/dev/null ) == *lvalue* ]] || err_exit "((++1)) not generating error message"
365da2e3ebdSchini=2
366da2e3ebdSchin(( "22" == 22 )) || err_exit "double quoted constants fail"
367da2e3ebdSchin(( "2$i" == 22 )) || err_exit "double quoted variables fail"
368da2e3ebdSchin(( "18+$i+2" == 22 )) || err_exit "double quoted expressions fail"
369da2e3ebdSchin# 04-04-28 bug fix
370da2e3ebdSchinunset i; typeset -i i=01-2
371da2e3ebdSchin(( i == -1 )) || err_exit "01-2 is not -1"
372da2e3ebdSchin
37334f9b3eeSRoland Mainzcat > $tmp/script <<-\!
374da2e3ebdSchintests=$*
375da2e3ebdSchintypeset -A blop
376da2e3ebdSchinfunction blop.get
377da2e3ebdSchin{
378da2e3ebdSchin	.sh.value=777
379da2e3ebdSchin}
380da2e3ebdSchinfunction mkobj
381da2e3ebdSchin{
382da2e3ebdSchin	nameref obj=$1
383da2e3ebdSchin	obj=()
384da2e3ebdSchin	[[ $tests == *1* ]] && {
385da2e3ebdSchin		(( obj.foo = 1 ))
386da2e3ebdSchin		(( obj.bar = 2 ))
387da2e3ebdSchin		(( obj.baz = obj.foo + obj.bar ))	# ok
388da2e3ebdSchin		echo $obj
389da2e3ebdSchin	}
390da2e3ebdSchin	[[ $tests == *2* ]] && {
391da2e3ebdSchin		(( obj.faz = faz = obj.foo + obj.bar ))	# ok
392da2e3ebdSchin		echo $obj
393da2e3ebdSchin	}
394da2e3ebdSchin	[[ $tests == *3* ]] && {
395da2e3ebdSchin		# case 3, 'active' variable involved, w/ intermediate variable
396da2e3ebdSchin		(( obj.foz = foz = ${blop[1]} ))	# coredump
397da2e3ebdSchin		echo $obj
398da2e3ebdSchin	}
399da2e3ebdSchin	[[ $tests == *4* ]] && {
400da2e3ebdSchin		# case 4, 'active' variable, in two steps
401da2e3ebdSchin		(( foz = ${blop[1]} ))	# ok
402da2e3ebdSchin		(( obj.foz = foz ))		# ok
403da2e3ebdSchin		echo $obj
404da2e3ebdSchin	}
405da2e3ebdSchin	[[ $tests == *5* ]] && {
406da2e3ebdSchin		# case 5, 'active' variable involved, w/o intermediate variable
407da2e3ebdSchin		(( obj.fuz = ${blop[1]} ))	# coredump
408da2e3ebdSchin		echo $obj
409da2e3ebdSchin	}
410da2e3ebdSchin	[[ $tests == *6* ]] && {
411da2e3ebdSchin		echo $(( obj.baz = obj.foo + obj.bar ))	# coredump
412da2e3ebdSchin	}
413da2e3ebdSchin	[[ $tests == *7* ]] && {
414da2e3ebdSchin		echo $(( obj.foo + obj.bar ))	# coredump
415da2e3ebdSchin	}
416da2e3ebdSchin}
417da2e3ebdSchinmkobj bla
418da2e3ebdSchin!
41934f9b3eeSRoland Mainzchmod +x $tmp/script
42034f9b3eeSRoland Mainz[[ $($tmp/script 1) != '( bar=2 baz=3 foo=1 )' ]] 2>/dev/null && err_exit 'compound var arithmetic failed'
42134f9b3eeSRoland Mainz[[ $($tmp/script 2) != '( faz=0 )' ]] 2>/dev/null && err_exit 'compound var arithmetic failed'
42234f9b3eeSRoland Mainz[[ $($tmp/script 3) != '( foz=777 )' ]] 2>/dev/null && err_exit 'compound var arithmetic failed'
42334f9b3eeSRoland Mainz[[ $($tmp/script 4) != '( foz=777 )' ]] 2>/dev/null && err_exit 'compound var arithmetic failed'
42434f9b3eeSRoland Mainz[[ $($tmp/script 5) != '( fuz=777 )' ]] 2>/dev/null && err_exit 'compound var arithmetic failed'
42534f9b3eeSRoland Mainz[[ $($tmp/script 6) != '0' ]] 2>/dev/null && err_exit 'compound var arithmetic failed'
42634f9b3eeSRoland Mainz[[ $($tmp/script 7) != '0' ]] 2>/dev/null && err_exit 'compound var arithmetic failed'
427da2e3ebdSchinunset foo
428da2e3ebdSchintypeset -F1 foo=123456789.19
429da2e3ebdSchin[[ $foo == 123456789.2 ]] || err_exit 'typeset -F1 not working correctly'
430da2e3ebdSchin
431da2e3ebdSchin# divide by zero
432da2e3ebdSchin
433da2e3ebdSchinfor expr in '1/(1/2)' '8%(1/2)' '8%(1.0/2)'
434da2e3ebdSchindo	[[ $( ( $SHELL -c "( (($expr)) )  || print ok" ) 2>/dev/null ) == ok ]] || err_exit "divide by zero not trapped: $expr"
435da2e3ebdSchindone
436da2e3ebdSchin
437da2e3ebdSchinfor expr in '1/(1.0/2)' '1/(1/2.0)'
438da2e3ebdSchindo	[[ $( ( $SHELL -c "( print -r -- \$(($expr)) )" ) 2>/dev/null ) == 2 ]] || err_exit "invalid value for: $expr"
439da2e3ebdSchindone
440da2e3ebdSchin[[ $((5||0)) == 1 ]] || err_exit '$((5||0))'" == $((5||0)) should be 1"
441da2e3ebdSchin$SHELL -c 'integer x=3 y=2; (( (y += x += 2) == 7  && x==5))' 2> /dev/null || err_exit '((y += x += 2)) not working'
442da2e3ebdSchin$SHELL -c 'b=0; [[ $((b?a=1:b=9)) == 9 ]]' 2> /dev/null || err_exit 'b?a=1:b=9 not working'
443da2e3ebdSchinunset x
444da2e3ebdSchin(( x = 4*atan(1.0) ))
445da2e3ebdSchin[[ $x == "$((x))" ]] || err_exit  '$x !- $((x)) when x is pi'
446da2e3ebdSchin$SHELL -c  "[[  ${x//./} == {14,100}(\d) ]]" 2> /dev/null || err_exit 'pi has less than 14 significant places'
447da2e3ebdSchinif	(( Inf+1 == Inf ))
4487c2fbfb3SApril Chinthen	set \
4497c2fbfb3SApril Chin		Inf		inf	\
4507c2fbfb3SApril Chin		-Inf		-inf	\
4517c2fbfb3SApril Chin		Nan		nan	\
4527c2fbfb3SApril Chin		-Nan		-nan	\
4537c2fbfb3SApril Chin		1.0/0.0		inf
4547c2fbfb3SApril Chin	while	(( $# >= 2 ))
4557c2fbfb3SApril Chin	do	x=$(printf "%g\n" $(($1)))
4567c2fbfb3SApril Chin		[[ $x == $2 ]] || err_exit "printf '%g\\n' \$(($1)) failed -- expected $2, got $x"
4577c2fbfb3SApril Chin		x=$(printf "%g\n" $1)
4587c2fbfb3SApril Chin		[[ $x == $2 ]] || err_exit "printf '%g\\n' $1 failed -- expected $2, got $x"
4597c2fbfb3SApril Chin		x=$(printf -- $(($1)))
4607c2fbfb3SApril Chin		[[ $x == $2 ]] || err_exit "print -- \$(($1)) failed -- expected $2, got $x"
4617c2fbfb3SApril Chin		shift 2
4627c2fbfb3SApril Chin	done
463da2e3ebdSchin	(( 1.0/0.0 == Inf )) || err_exit '1.0/0.0 != Inf'
4647c2fbfb3SApril Chin	[[ $(print -- $((0.0/0.0))) == ?(-)nan ]] || err_exit '0.0/0.0 != NaN'
465da2e3ebdSchin	(( Inf*Inf == Inf )) || err_exit 'Inf*Inf != Inf'
466da2e3ebdSchin	(( NaN != NaN )) || err_exit 'NaN == NaN'
467da2e3ebdSchin	(( -5*Inf == -Inf )) || err_exit '-5*Inf != -Inf'
4687c2fbfb3SApril Chin	[[ $(print -- $((sqrt(-1.0)))) == ?(-)nan ]]|| err_exit 'sqrt(-1.0) != NaN'
469da2e3ebdSchin	(( pow(1.0,Inf) == 1.0 )) || err_exit 'pow(1.0,Inf) != 1.0'
470da2e3ebdSchin	(( pow(Inf,0.0) == 1.0 )) || err_exit 'pow(Inf,0.0) != 1.0'
4717c2fbfb3SApril Chin	[[ $(print -- $((NaN/Inf))) == ?(-)nan ]] || err_exit 'NaN/Inf != NaN'
472da2e3ebdSchin	(( 4.0/Inf == 0.0 )) || err_exit '4.0/Inf != 0.0'
473da2e3ebdSchinelse	err_exit 'Inf and NaN not working'
474da2e3ebdSchinfi
4757c2fbfb3SApril Chinunset x y n r
4767c2fbfb3SApril Chinn=14.555
4777c2fbfb3SApril Chinfloat x=$n y
478da2e3ebdSchiny=$(printf "%a" x)
4797c2fbfb3SApril Chinr=$y
4807c2fbfb3SApril Chin[[ $r == $n ]] || err_exit "output of printf %a not self preserving -- expected $x, got $y"
4817c2fbfb3SApril Chinunset x y r
4827c2fbfb3SApril Chinx=-0
4837c2fbfb3SApril Chiny=$(printf "%g %g %g %g %g %g\n" -0. -0 $((-0)) x $x $((x)))
4847c2fbfb3SApril Chinr="-0 -0 -0 -0 -0 -0"
4857c2fbfb3SApril Chin[[ $y == "$r" ]] || err_exit "-0 vs -0.0 inconsistency -- expected '$r', got '$y'"
4867c2fbfb3SApril Chin$SHELL -c '(( x=));:' 2> /dev/null && err_exit '((x=)) should be an error'
4877c2fbfb3SApril Chin$SHELL -c '(( x+=));:' 2> /dev/null && err_exit '((x+=)) should be an error'
4887c2fbfb3SApril Chin$SHELL -c '(( x=+));:' 2> /dev/null && err_exit '((x=+)) should be an error'
4897c2fbfb3SApril Chin$SHELL -c 'x=();x.arr[0]=(z=3); ((x.arr[0].z=2))' 2> /dev/null || err_exit '(((x.arr[0].z=2)) should not be an error'
49034f9b3eeSRoland Mainz
49134f9b3eeSRoland Mainzfloat t
49234f9b3eeSRoland Mainztypeset a b r
49334f9b3eeSRoland Mainzv="-0.0 0.0 +0.0 -1.0 1.0 +1.0"
49434f9b3eeSRoland Mainzfor a in $v
49534f9b3eeSRoland Mainzdo	for b in $v
49634f9b3eeSRoland Mainz	do	(( r = copysign(a,b) ))
49734f9b3eeSRoland Mainz		(( t = copysign(a,b) ))
49834f9b3eeSRoland Mainz		[[ $r == $t ]] || err_exit $(printf "float t=copysign(%3.1f,%3.1f) => %3.1f -- expected %3.1f\n" a b t r)
49934f9b3eeSRoland Mainz	done
50034f9b3eeSRoland Mainzdone
50134f9b3eeSRoland Mainz
50234f9b3eeSRoland Mainztypeset -l y y_ascii
50334f9b3eeSRoland Mainz(( y=sin(90) ))
50434f9b3eeSRoland Mainzy_ascii=$y
50534f9b3eeSRoland Mainz(( y == y_ascii )) || err_exit "no match,\n\t$(printf "%a\n" y)\n!=\n\t$(printf "%a\n" y_ascii)"
50634f9b3eeSRoland Mainz
50734f9b3eeSRoland Mainz( $SHELL  <<- \EOF
50834f9b3eeSRoland Mainz	p=5
50934f9b3eeSRoland Mainz	t[p]=6
51034f9b3eeSRoland Mainz	while (( t[p] != 0 )) ; do
51134f9b3eeSRoland Mainz		((
51234f9b3eeSRoland Mainz		p+=1 ,
51334f9b3eeSRoland Mainz		t[p]+=2 ,
51434f9b3eeSRoland Mainz		p+=3 ,
51534f9b3eeSRoland Mainz		t[p]+=5 ,
51634f9b3eeSRoland Mainz		p+=1 ,
51734f9b3eeSRoland Mainz		t[p]+=2 ,
51834f9b3eeSRoland Mainz		p+=1 ,
51934f9b3eeSRoland Mainz		t[p]+=1 ,
52034f9b3eeSRoland Mainz		p-=6  ,
52134f9b3eeSRoland Mainz		t[p]-=1
52234f9b3eeSRoland Mainz		))
52334f9b3eeSRoland Mainz	:
52434f9b3eeSRoland Mainz	done
52534f9b3eeSRoland MainzEOF) 2> /dev/null ||  err_exit 'error with comma expression'
52634f9b3eeSRoland Mainz
52734f9b3eeSRoland MainzN=(89551 89557)
52834f9b3eeSRoland Mainzi=0 j=1
52934f9b3eeSRoland Mainz[[ $(printf "%d" N[j]-N[i]) == 6 ]] || err_exit 'printf %d N[i]-N[j] failed'
53034f9b3eeSRoland Mainz[[ $((N[j]-N[i])) == 6 ]] || err_exit  '$((N[j]-N[i])) incorrect'
53134f9b3eeSRoland Mainz
532*3e14f97fSRoger A. Faulknerunset a x
533*3e14f97fSRoger A. Faulknerx=0
534*3e14f97fSRoger A. Faulkner((a[++x]++))
535*3e14f97fSRoger A. Faulkner(( x==1)) || err_exit '((a[++x]++)) should only increment x once'
536*3e14f97fSRoger A. Faulkner(( a[1]==1))  || err_exit 'a[1] not incremented'
537*3e14f97fSRoger A. Faulknerunset a
538*3e14f97fSRoger A. Faulknerx=0
539*3e14f97fSRoger A. Faulkner((a[x++]++))
540*3e14f97fSRoger A. Faulkner(( x==1)) || err_exit '((a[x++]++)) should only increment x once'
541*3e14f97fSRoger A. Faulkner(( a[0]==1))  || err_exit 'a[0] not incremented'
542*3e14f97fSRoger A. Faulknerunset a
543*3e14f97fSRoger A. Faulknerx=0
544*3e14f97fSRoger A. Faulkner((a[x+=2]+=1))
545*3e14f97fSRoger A. Faulkner(( x==2)) || err_exit '((a[x+=2]++)) should result in x==2'
546*3e14f97fSRoger A. Faulkner(( a[2]==1))  || err_exit 'a[0] not 1'
547*3e14f97fSRoger A. Faulkner
548*3e14f97fSRoger A. Faulknerunset a i
549*3e14f97fSRoger A. Faulknertypeset -a a
550*3e14f97fSRoger A. Faulkneri=1
551*3e14f97fSRoger A. Faulkner(( a[i]=1 ))
552*3e14f97fSRoger A. Faulkner(( a[0] == 0 )) || err_exit 'a[0] not 0'
553*3e14f97fSRoger A. Faulkner(( a[1] == 1 )) || err_exit 'a[1] not 1'
554*3e14f97fSRoger A. Faulkner
555*3e14f97fSRoger A. Faulknerunset a
556*3e14f97fSRoger A. Faulknertypeset -i a
557*3e14f97fSRoger A. Faulknerfor ((i=0;i<1000;i++))
558*3e14f97fSRoger A. Faulknerdo ((a[RANDOM%2]++))
559*3e14f97fSRoger A. Faulknerdone
560*3e14f97fSRoger A. Faulkner(( (a[0]+a[1])==1000)) || err_exit '(a[0]+a[1])!=1000'
561*3e14f97fSRoger A. Faulkner
562da2e3ebdSchinexit $((Errors))
563