# Iteration 13: Arithmetic Expansion and Evaluation
# === Basic $((...)) arithmetic expansion ===
=== simple addition
echo $((1 + 2))
---
(command (word "echo") (word "$((1 + 2))"))
---
=== simple subtraction
echo $((5 - 3))
---
(command (word "echo") (word "$((5 - 3))"))
---
=== simple multiplication
echo $((4 * 3))
---
(command (word "echo") (word "$((4 * 3))"))
---
=== simple division
echo $((10 / 2))
---
(command (word "echo") (word "$((10 / 2))"))
---
=== modulo
echo $((10 % 3))
---
(command (word "echo") (word "$((10 % 3))"))
---
=== exponentiation
echo $((2 ** 8))
---
(command (word "echo") (word "$((2 ** 8))"))
---
=== negative numbers
echo $((-5))
---
(command (word "echo") (word "$((-5))"))
---
=== unary plus
echo $((+5))
---
(command (word "echo") (word "$((+5))"))
---
=== no spaces
echo $((1+2))
---
(command (word "echo") (word "$((1+2))"))
---
=== mixed spacing
echo $((1+ 2))
---
(command (word "echo") (word "$((1+ 2))"))
---
=== variable without dollar
echo $((x + 1))
---
(command (word "echo") (word "$((x + 1))"))
---
=== variable with dollar
echo $(($x + 1))
---
(command (word "echo") (word "$(($x + 1))"))
---
=== braced variable
echo $((${x} + 1))
---
(command (word "echo") (word "$((${x} + 1))"))
---
=== multiple variables
echo $((a + b))
---
(command (word "echo") (word "$((a + b))"))
---
=== less than
echo $((1 < 2))
---
(command (word "echo") (word "$((1 < 2))"))
---
=== greater than
echo $((2 > 1))
---
(command (word "echo") (word "$((2 > 1))"))
---
=== less or equal
echo $((1 <= 2))
---
(command (word "echo") (word "$((1 <= 2))"))
---
=== greater or equal
echo $((2 >= 1))
---
(command (word "echo") (word "$((2 >= 1))"))
---
=== equality
echo $((1 == 1))
---
(command (word "echo") (word "$((1 == 1))"))
---
=== inequality
echo $((1 != 2))
---
(command (word "echo") (word "$((1 != 2))"))
---
=== logical and
echo $((1 && 1))
---
(command (word "echo") (word "$((1 && 1))"))
---
=== logical or
echo $((0 || 1))
---
(command (word "echo") (word "$((0 || 1))"))
---
=== logical not
echo $((!0))
---
(command (word "echo") (word "$((!0))"))
---
=== bitwise and
echo $((5 & 3))
---
(command (word "echo") (word "$((5 & 3))"))
---
=== bitwise or
echo $((5 | 3))
---
(command (word "echo") (word "$((5 | 3))"))
---
=== bitwise xor
echo $((5 ^ 3))
---
(command (word "echo") (word "$((5 ^ 3))"))
---
=== bitwise not
echo $((~5))
---
(command (word "echo") (word "$((~5))"))
---
=== left shift
echo $((1 << 4))
---
(command (word "echo") (word "$((1 << 4))"))
---
=== right shift
echo $((16 >> 2))
---
(command (word "echo") (word "$((16 >> 2))"))
---
=== left shift inside command substitution
x=$( echo $(( 1<<2 )) )
---
(command (word "x=$(echo $(( 1<<2 )))"))
---
=== simple assignment
echo $((x = 5))
---
(command (word "echo") (word "$((x = 5))"))
---
=== add assign
echo $((x += 5))
---
(command (word "echo") (word "$((x += 5))"))
---
=== subtract assign
echo $((x -= 5))
---
(command (word "echo") (word "$((x -= 5))"))
---
=== multiply assign
echo $((x *= 5))
---
(command (word "echo") (word "$((x *= 5))"))
---
=== divide assign
echo $((x /= 5))
---
(command (word "echo") (word "$((x /= 5))"))
---
=== modulo assign
echo $((x %= 5))
---
(command (word "echo") (word "$((x %= 5))"))
---
=== pre-increment
echo $((++x))
---
(command (word "echo") (word "$((++x))"))
---
=== post-increment
echo $((x++))
---
(command (word "echo") (word "$((x++))"))
---
=== pre-decrement
echo $((--x))
---
(command (word "echo") (word "$((--x))"))
---
=== post-decrement
echo $((x--))
---
(command (word "echo") (word "$((x--))"))
---
=== ternary true
echo $((1 ? 10 : 20))
---
(command (word "echo") (word "$((1 ? 10 : 20))"))
---
=== ternary false
echo $((0 ? 10 : 20))
---
(command (word "echo") (word "$((0 ? 10 : 20))"))
---
=== ternary with expressions
echo $((x > 0 ? x : -x))
---
(command (word "echo") (word "$((x > 0 ? x : -x))"))
---
=== comma operator
echo $((x = 1, y = 2, x + y))
---
(command (word "echo") (word "$((x = 1, y = 2, x + y))"))
---
=== parentheses grouping
echo $(((1 + 2) * 3))
---
(command (word "echo") (word "$(((1 + 2) * 3))"))
---
=== nested parentheses
echo $((((1 + 2)) * 3))
---
(command (word "echo") (word "$((((1 + 2)) * 3))"))
---
=== complex grouping
echo $(((a + b) * (c + d)))
---
(command (word "echo") (word "$(((a + b) * (c + d)))"))
---
=== arithmetic in assignment
x=$((1 + 2))
---
(command (word "x=$((1 + 2))"))
---
=== arithmetic in middle of word
echo prefix$((1+2))suffix
---
(command (word "echo") (word "prefix$((1+2))suffix"))
---
=== multiple arithmetic in word
echo $((1+2))$((3+4))
---
(command (word "echo") (word "$((1+2))$((3+4))"))
---
=== arithmetic in double quotes
echo "result: $((1 + 2))"
---
(command (word "echo") (word "\"result: $((1 + 2))\""))
---
=== arithmetic command simple
((x = 5))
---
(arith (word "x = 5"))
---
=== arithmetic command increment
((x++))
---
(arith (word "x++"))
---
=== arithmetic command comparison
((x > 0))
---
(arith (word "x > 0"))
---
=== arithmetic command in if
if ((x > 0)); then echo positive; fi
---
(if (arith (word "x > 0")) (command (word "echo") (word "positive")))
---
=== arithmetic command in while
while ((i < 10)); do echo $i; ((i++)); done
---
(while (arith (word "i < 10")) (semi (command (word "echo") (word "$i")) (arith (word "i++"))))
---
=== arithmetic command with semicolon
((x = 1)); echo $x
---
(semi (arith (word "x = 1")) (command (word "echo") (word "$x")))
---
=== complex expression
echo $((a * b + c / d - e % f))
---
(command (word "echo") (word "$((a * b + c / d - e % f))"))
---
=== mixed operators
echo $((1 + 2 * 3 - 4 / 2))
---
(command (word "echo") (word "$((1 + 2 * 3 - 4 / 2))"))
---
=== chained comparisons via logical
echo $((a > 0 && a < 10))
---
(command (word "echo") (word "$((a > 0 && a < 10))"))
---
=== extra whitespace
echo $(( 1 + 2 ))
---
(command (word "echo") (word "$(( 1 + 2 ))"))
---
=== newline in arithmetic
echo $((1 +
2))
---
(command (word "echo") (word "$((1 +\n2))"))
---
=== tabs
echo $(( 1 + 2 ))
---
(command (word "echo") (word "$((\t1\t+\t2\t))"))
---
=== hex number
echo $((0xFF))
---
(command (word "echo") (word "$((0xFF))"))
---
=== octal number
echo $((0777))
---
(command (word "echo") (word "$((0777))"))
---
=== binary number
echo $((2#1010))
---
(command (word "echo") (word "$((2#1010))"))
---
=== base 36
echo $((36#z))
---
(command (word "echo") (word "$((36#z))"))
---
=== just zero
echo $((0))
---
(command (word "echo") (word "$((0))"))
---
=== just variable
echo $((x))
---
(command (word "echo") (word "$((x))"))
---
=== nested arithmetic expansion
echo $((1 + $((2 + 3))))
---
(command (word "echo") (word "$((1 + $((2 + 3))))"))
---
=== empty arithmetic
echo $(())
---
(command (word "echo") (word "$(())"))
---
=== only spaces
echo $(( ))
---
(command (word "echo") (word "$(( ))"))
---
=== deeply nested parens
echo $(((((1+2)))))
---
(command (word "echo") (word "$(((((1+2)))))"))
---
=== double negative
echo $((--5))
---
(command (word "echo") (word "$((--5))"))
---
=== double positive
echo $((++5))
---
(command (word "echo") (word "$((++5))"))
---
=== negate negative
echo $((-(-5)))
---
(command (word "echo") (word "$((-(-5)))"))
---
=== subtract negative
echo $((1 - -2))
---
(command (word "echo") (word "$((1 - -2))"))
---
=== subtract negative no space
echo $((1--2))
---
(command (word "echo") (word "$((1--2))"))
---
=== add positive no space
echo $((1++2))
---
(command (word "echo") (word "$((1++2))"))
---
=== chained assignment
echo $((a = b = c = 5))
---
(command (word "echo") (word "$((a = b = c = 5))"))
---
=== nested ternary
echo $((a ? b ? 1 : 2 : 3))
---
(command (word "echo") (word "$((a ? b ? 1 : 2 : 3))"))
---
=== ternary with comma
echo $((a ? (b++, c) : d))
---
(command (word "echo") (word "$((a ? (b++, c) : d))"))
---
=== array subscript
echo $((arr[0] + arr[1]))
---
(command (word "echo") (word "$((arr[0] + arr[1]))"))
---
=== array subscript expression
echo $((arr[i+1]))
---
(command (word "echo") (word "$((arr[i+1]))"))
---
=== complex array subscript
echo $((arr[arr[0]]))
---
(command (word "echo") (word "$((arr[arr[0]]))"))
---
=== all bitwise ops
echo $((~a | b & c ^ d << 2 >> 1))
---
(command (word "echo") (word "$((~a | b & c ^ d << 2 >> 1))"))
---
=== bitwise assign ops
echo $((x &= 0xFF, y |= 0x80, z ^= 0x01))
---
(command (word "echo") (word "$((x &= 0xFF, y |= 0x80, z ^= 0x01))"))
---
=== mixed bases
echo $((0xFF + 0777 + 2#1010))
---
(command (word "echo") (word "$((0xFF + 0777 + 2#1010))"))
---
=== base 64
echo $((64#_))
---
(command (word "echo") (word "$((64#_))"))
---
=== RANDOM in arithmetic
echo $((RANDOM % 100))
---
(command (word "echo") (word "$((RANDOM % 100))"))
---
=== special params in arithmetic
echo $(($# + $?))
---
(command (word "echo") (word "$(($# + $?))"))
---
=== empty arithmetic command
(())
---
(arith (word ""))
---
=== arithmetic command with assignment chain
((a = b = 0))
---
(arith (word "a = b = 0"))
---
=== arithmetic command multiple expressions
((a++, b--, c = a + b))
---
(arith (word "a++, b--, c = a + b"))
---
=== arithmetic command in conditional
if ((1)); then echo yes; fi
---
(if (arith (word "1")) (command (word "echo") (word "yes")))
---
=== arithmetic command zero is false
if ((0)); then echo yes; else echo no; fi
---
(if (arith (word "0")) (command (word "echo") (word "yes")) (command (word "echo") (word "no")))
---
=== adjacent arithmetic expansions
echo $((1))$((2))$((3))
---
(command (word "echo") (word "$((1))$((2))$((3))"))
---
=== param expansion in arithmetic
echo $((${x:-5} + 1))
---
(command (word "echo") (word "$((${x:-5} + 1))"))
---
=== complex param in arithmetic
echo $((${#arr[@]} - 1))
---
(command (word "echo") (word "$((${#arr[@]} - 1))"))
---
=== arithmetic command pipeline
((x++)) && echo incremented
---
(and (arith (word "x++")) (command (word "echo") (word "incremented")))
---
=== arithmetic command or
((x > 0)) || echo "not positive"
---
(or (arith (word "x > 0")) (command (word "echo") (word "\"not positive\"")))
---
=== counter loop idiom
i=0; while ((i++ < 10)); do echo $i; done
---
(semi (command (word "i=0")) (while (arith (word "i++ < 10")) (command (word "echo") (word "$i"))))
---
=== bounds check
((index >= 0 && index < ${#arr[@]})) && echo valid
---
(and (arith (word "index >= 0 && index < ${#arr[@]}")) (command (word "echo") (word "valid")))
---
=== flag toggle
((flag ^= 1))
---
(arith (word "flag ^= 1"))
---
=== power of two check
(((n & (n - 1)) == 0))
---
(arith (word "(n & (n - 1)) == 0"))
---
=== arithmetic with hex prefix and command substitution
x=$((0x$(cmd 2>/dev/null)))
---
(command (word "x=$((0x$(cmd 2> /dev/null)))"))
---
=== hex number with variable expansion in arithmetic
echo $(( (0x$x) ))
---
(command (word "echo") (word "$(( (0x$x) ))"))
---
=== parameter length in arithmetic
a=$((#${x}))
---
(command (word "a=$((#${x}))"))
---
=== triple paren arithmetic with trailing expression
$(((1)*2)+1)
---
(command (word "$(((1)*2)+1)"))
---