1#!/usr/bin/env bash
2set -euo pipefail
3
4# Math Library for Testing
5# A collection of mathematical functions demonstrating testable bash code
6# Can be sourced by other scripts or run standalone for demonstration
7
8# ============================================================================
9# Basic Arithmetic Operations
10# ============================================================================
11
12# Add two numbers
13# Args: $1 - first number, $2 - second number
14# Returns: sum of the two numbers
15add() {
16 local a=$1
17 local b=$2
18 echo $((a + b))
19}
20
21# Subtract two numbers
22# Args: $1 - first number, $2 - second number
23# Returns: difference (first - second)
24subtract() {
25 local a=$1
26 local b=$2
27 echo $((a - b))
28}
29
30# Multiply two numbers
31# Args: $1 - first number, $2 - second number
32# Returns: product of the two numbers
33multiply() {
34 local a=$1
35 local b=$2
36 echo $((a * b))
37}
38
39# Divide two numbers
40# Args: $1 - dividend, $2 - divisor
41# Returns: quotient (integer division)
42# Exits with error if divisor is zero
43divide() {
44 local a=$1
45 local b=$2
46
47 if [[ $b -eq 0 ]]; then
48 echo "Error: Division by zero" >&2
49 return 1
50 fi
51
52 echo $((a / b))
53}
54
55# ============================================================================
56# Advanced Mathematical Functions
57# ============================================================================
58
59# Calculate factorial of a number
60# Args: $1 - non-negative integer
61# Returns: factorial of the number
62factorial() {
63 local n=$1
64
65 if [[ $n -lt 0 ]]; then
66 echo "Error: Factorial not defined for negative numbers" >&2
67 return 1
68 fi
69
70 if [[ $n -eq 0 ]] || [[ $n -eq 1 ]]; then
71 echo 1
72 return 0
73 fi
74
75 local result=1
76 local i
77 for ((i = 2; i <= n; i++)); do
78 result=$((result * i))
79 done
80
81 echo $result
82}
83
84# Check if a number is prime
85# Args: $1 - positive integer
86# Returns: 0 (true) if prime, 1 (false) otherwise
87is_prime() {
88 local n=$1
89
90 if [[ $n -lt 2 ]]; then
91 return 1
92 fi
93
94 if [[ $n -eq 2 ]]; then
95 return 0
96 fi
97
98 if [[ $((n % 2)) -eq 0 ]]; then
99 return 1
100 fi
101
102 local i
103 local sqrt_n=$(awk "BEGIN {print int(sqrt($n))}")
104
105 for ((i = 3; i <= sqrt_n; i += 2)); do
106 if [[ $((n % i)) -eq 0 ]]; then
107 return 1
108 fi
109 done
110
111 return 0
112}
113
114# Calculate greatest common divisor (GCD)
115# Args: $1 - first number, $2 - second number
116# Returns: GCD of the two numbers
117gcd() {
118 local a=${1#-} # Remove negative sign if present
119 local b=${2#-}
120
121 while [[ $b -ne 0 ]]; do
122 local temp=$b
123 b=$((a % b))
124 a=$temp
125 done
126
127 echo $a
128}
129
130# Calculate least common multiple (LCM)
131# Args: $1 - first number, $2 - second number
132# Returns: LCM of the two numbers
133lcm() {
134 local a=${1#-} # Remove negative sign if present
135 local b=${2#-}
136
137 if [[ $a -eq 0 ]] || [[ $b -eq 0 ]]; then
138 echo 0
139 return 0
140 fi
141
142 local gcd_val
143 gcd_val=$(gcd "$a" "$b")
144 echo $(( (a * b) / gcd_val ))
145}
146
147# ============================================================================
148# Demo Functions (only run when executed, not sourced)
149# ============================================================================
150
151demo_basic_operations() {
152 echo "=== Basic Arithmetic Operations ==="
153 echo "add 10 5 = $(add 10 5)"
154 echo "subtract 10 5 = $(subtract 10 5)"
155 echo "multiply 10 5 = $(multiply 10 5)"
156 echo "divide 10 5 = $(divide 10 5)"
157 echo
158}
159
160demo_advanced_functions() {
161 echo "=== Advanced Mathematical Functions ==="
162 echo "factorial 5 = $(factorial 5)"
163 echo "factorial 0 = $(factorial 0)"
164
165 if is_prime 17; then
166 echo "17 is prime"
167 else
168 echo "17 is not prime"
169 fi
170
171 if is_prime 20; then
172 echo "20 is prime"
173 else
174 echo "20 is not prime"
175 fi
176
177 echo "gcd 48 18 = $(gcd 48 18)"
178 echo "lcm 12 18 = $(lcm 12 18)"
179 echo
180}
181
182demo_error_handling() {
183 echo "=== Error Handling ==="
184 echo "Testing division by zero:"
185 if ! divide 10 0; then
186 echo "Correctly caught division by zero error"
187 fi
188
189 echo
190 echo "Testing negative factorial:"
191 if ! factorial -5; then
192 echo "Correctly caught negative factorial error"
193 fi
194 echo
195}
196
197# Main execution (only if script is run directly, not sourced)
198if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
199 echo "Math Library Demonstration"
200 echo "=========================="
201 echo
202
203 demo_basic_operations
204 demo_advanced_functions
205 demo_error_handling
206
207 echo "To use this library in other scripts, source it:"
208 echo " source math_lib.sh"
209fi