blob: e8ca582e1a12c3d86dd5cac984042950fc6a96d8 [file] [log] [blame]
Gavin Howardea7bea62018-02-22 18:55:03 -07001#! /bin/bash
Gavin Howard64f113c2018-09-25 09:38:57 -06002#
3# Copyright 2018 Gavin D. Howard
4#
5# Permission to use, copy, modify, and/or distribute this software for any
6# purpose with or without fee is hereby granted.
7#
8# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
9# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10# AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
11# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
13# OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14# PERFORMANCE OF THIS SOFTWARE.
15#
Gavin Howardea7bea62018-02-22 18:55:03 -070016
Gavin Howard9409a872018-09-08 19:29:29 -060017# This script uses a technique to use a keypress to get
18# out of an infinite loop. The technique was found here:
19# https://stackoverflow.com/questions/5297638/bash-how-to-end-infinite-loop-with-any-key-pressed
20
21finish() {
22 rm -rf "$out1" "$out2" "$math" "$results" "$opfile"
23}
24trap finish EXIT
25
Gavin Howardea7bea62018-02-22 18:55:03 -070026gen()
27{
Gavin Howardabe8c002018-09-06 11:30:04 -060028 limit="$1"
29 shift
30
31 result=$(dd if=/dev/urandom bs="$limit" count=1 2>/dev/null | od -t u4 | awk 'NR==1 {print $2}')
Gavin Howardea7bea62018-02-22 18:55:03 -070032 echo -n "$result"
33}
34
35neg()
36{
Gavin Howardabe8c002018-09-06 11:30:04 -060037 result=$(gen 1)
Gavin Howardea7bea62018-02-22 18:55:03 -070038 result="$((result & 1))"
39 echo -n "$result"
40}
41
42zero()
43{
Gavin Howardabe8c002018-09-06 11:30:04 -060044 result=$(gen 1)
45 echo -n "$result"
46}
47
48limit()
49{
50 max="$1"
51 shift
52
53 result=$(gen 1)
54 result=$(expr "$result" % "$max")
55 echo -n $(expr "$result" + 1)
Gavin Howardea7bea62018-02-22 18:55:03 -070056}
57
58num()
59{
Gavin Howardabe8c002018-09-06 11:30:04 -060060 n=""
Gavin Howardea7bea62018-02-22 18:55:03 -070061
62 neg=$1
Gavin Howardabe8c002018-09-06 11:30:04 -060063 shift
Gavin Howardea7bea62018-02-22 18:55:03 -070064
Gavin Howardabe8c002018-09-06 11:30:04 -060065 real=$1
66 shift
Gavin Howardea7bea62018-02-22 18:55:03 -070067
Gavin Howardabe8c002018-09-06 11:30:04 -060068 zero=$1
69 shift
Gavin Howardea7bea62018-02-22 18:55:03 -070070
Gavin Howardabe8c002018-09-06 11:30:04 -060071 if [ "$#" -gt 0 ]; then
72 limit="$1"
73 shift
74 else
75 limit="$(limit 4)"
76 fi
Gavin Howardea7bea62018-02-22 18:55:03 -070077
Gavin Howardabe8c002018-09-06 11:30:04 -060078 if [ "$zero" -ne 0 ]; then
79 z=$(zero)
80 else
81 z=1
82 fi
83
84 if [ "$z" -eq 0 ]; then
85 n="0"
86 else
Gavin Howardea7bea62018-02-22 18:55:03 -070087
88 if [ "$neg" -ne 0 ]; then
Gavin Howardabe8c002018-09-06 11:30:04 -060089
90 neg=$(neg)
91
92 if [ "$neg" -eq 0 ]; then
93 n="-"
94 fi
Gavin Howardea7bea62018-02-22 18:55:03 -070095 fi
Gavin Howardea7bea62018-02-22 18:55:03 -070096
Gavin Howardabe8c002018-09-06 11:30:04 -060097 g=$(gen $limit)
98 n="${n}${g}"
Gavin Howardea7bea62018-02-22 18:55:03 -070099
Gavin Howardabe8c002018-09-06 11:30:04 -0600100 if [ "$real" -ne 0 ]; then
Gavin Howardea7bea62018-02-22 18:55:03 -0700101
Gavin Howardabe8c002018-09-06 11:30:04 -0600102 z=$(neg)
Gavin Howardea7bea62018-02-22 18:55:03 -0700103
104 if [ "$z" -ne 0 ]; then
Gavin Howardabe8c002018-09-06 11:30:04 -0600105
106 limit=$(limit 25)
107 g=$(gen $limit)
108 n="$n.$g"
Gavin Howardea7bea62018-02-22 18:55:03 -0700109 fi
110 fi
111 fi
112
Gavin Howardabe8c002018-09-06 11:30:04 -0600113 echo -n "$n"
Gavin Howardea7bea62018-02-22 18:55:03 -0700114}
115
Gavin Howardea7bea62018-02-22 18:55:03 -0700116ops=( '+' '-' '*' '/' '%' '^' )
Gavin Howard19a3f0d2018-09-06 18:14:18 -0600117files=( "add" "subtract" "multiply" "divide" "modulus" "power" "sqrt" "exponent"
Gavin Howardabe8c002018-09-06 11:30:04 -0600118 "log" "arctangent" "sine" "cosine" "bessel" )
119funcs=( "sqrt" "e" "l" "a" "s" "c" "j" )
Gavin Howardea7bea62018-02-22 18:55:03 -0700120
121script="$0"
Gavin Howardea7bea62018-02-22 18:55:03 -0700122testdir=$(dirname "$script")
123
Gavin Howardea7bea62018-02-22 18:55:03 -0700124if [ "$#" -gt 0 ]; then
125 bc="$1"
126 shift
127else
128 bc="$testdir/../bc"
129fi
130
Gavin Howardd43ae752018-09-06 19:36:18 -0600131out1="$testdir/../.log_bc.txt"
132out2="$testdir/../.log_test.txt"
Gavin Howardea7bea62018-02-22 18:55:03 -0700133
Gavin Howard9409a872018-09-08 19:29:29 -0600134# Files to output failed tests to.
135math="$testdir/../.math.txt"
136results="$testdir/../.results.txt"
137opfile="$testdir/../.ops.txt"
Gavin Howardb809c3a2018-09-07 12:17:49 -0600138
Gavin Howard9409a872018-09-08 19:29:29 -0600139rm -rf "$math" "$results" "$opfile"
Gavin Howard8ceb6512018-09-06 14:34:46 -0600140
Gavin Howard9409a872018-09-08 19:29:29 -0600141# Set it so we can exit the loop on keypress.
142if [ -t 0 ]; then
143 stty -echo -icanon -icrnl time 0 min 0
144fi
145
146it=0
147keypress=''
148
149while [ "x$keypress" = "x" ]; do
150
151 t="$it"
152 it=$(expr "$it" + "1")
Gavin Howardea7bea62018-02-22 18:55:03 -0700153
Gavin Howardea7bea62018-02-22 18:55:03 -0700154 line=""
Gavin Howardabe8c002018-09-06 11:30:04 -0600155 operator=$(gen 1)
Gavin Howardabe8c002018-09-06 11:30:04 -0600156 op=$(expr "$operator" % 13)
Gavin Howardea7bea62018-02-22 18:55:03 -0700157
Gavin Howardabe8c002018-09-06 11:30:04 -0600158 if [ "$op" -lt 6 ]; then
Gavin Howardea7bea62018-02-22 18:55:03 -0700159
Gavin Howardabe8c002018-09-06 11:30:04 -0600160 line="$(num 1 1 1) ${ops[$op]}"
Gavin Howardea7bea62018-02-22 18:55:03 -0700161
Gavin Howard7de90762018-09-06 11:49:08 -0600162 if [ "$op" -eq 3 -o "$op" -eq 4 ]; then
Gavin Howardfc66b862018-09-06 12:04:30 -0600163
Gavin Howardabe8c002018-09-06 11:30:04 -0600164 number=$(num 1 1 0)
Gavin Howardfc66b862018-09-06 12:04:30 -0600165
166 scale=$(num 0 0 1 1)
167 scale=$(echo "s = $scale % 25; s /= 1; s" | bc)
168
169 line="scale = $scale; $line"
170
Gavin Howardea7bea62018-02-22 18:55:03 -0700171 elif [ "$op" -eq 5 ]; then
Gavin Howardabe8c002018-09-06 11:30:04 -0600172 number=$(num 1 0 1 1)
Gavin Howardea7bea62018-02-22 18:55:03 -0700173 else
Gavin Howardabe8c002018-09-06 11:30:04 -0600174 number=$(num 1 1 1)
Gavin Howardea7bea62018-02-22 18:55:03 -0700175 fi
176
Gavin Howardabe8c002018-09-06 11:30:04 -0600177 line="$line $number"
Gavin Howardea7bea62018-02-22 18:55:03 -0700178
179 else
Gavin Howardabe8c002018-09-06 11:30:04 -0600180
181 if [ "$op" -eq 6 ]; then
Gavin Howard741077a2018-09-06 16:34:15 -0600182
Gavin Howardabe8c002018-09-06 11:30:04 -0600183 number=$(num 0 1 1)
Gavin Howard741077a2018-09-06 16:34:15 -0600184
Gavin Howard9e28c102018-09-08 19:36:39 -0600185 # GNU bc gets "sqrt(1)" wrong, so skip it.
Gavin Howard741077a2018-09-06 16:34:15 -0600186 if [ "$number" == "1" ]; then
Gavin Howard9409a872018-09-08 19:29:29 -0600187 keypress=$(cat -v)
Gavin Howard741077a2018-09-06 16:34:15 -0600188 continue
189 fi
190
Gavin Howard7de90762018-09-06 11:49:08 -0600191 elif [ "$op" -eq 7 -o "$op" -eq 12 ]; then
192
Gavin Howardabe8c002018-09-06 11:30:04 -0600193 number=$(num 1 1 1 1)
Gavin Howard7de90762018-09-06 11:49:08 -0600194
195 if [ "$op" -eq 12 ]; then
196 number=$(echo "n = $number % 100; scale = 8; n /= 1; n" | bc)
197 fi
198
Gavin Howardabe8c002018-09-06 11:30:04 -0600199 else
200 number=$(num 1 1 1)
201 fi
202
203 func=$(expr "$op" - 6)
204 line="${funcs[$func]}($number"
205
206 if [ "$op" -ne 12 ]; then
207 line="$line)"
208 else
209 n=$(num 1 1 1)
Gavin Howard7de90762018-09-06 11:49:08 -0600210 n=$(echo "n = $n % 100; scale = 8; n /= 1; n" | bc)
Gavin Howardabe8c002018-09-06 11:30:04 -0600211 line="$line, $n)"
212 fi
Gavin Howardea7bea62018-02-22 18:55:03 -0700213 fi
214
Gavin Howardabe8c002018-09-06 11:30:04 -0600215 echo "Test $t: $line"
Gavin Howardea7bea62018-02-22 18:55:03 -0700216
Gavin Howardabe8c002018-09-06 11:30:04 -0600217 echo "$line; halt" | bc -lq > "$out1"
Gavin Howard741077a2018-09-06 16:34:15 -0600218
219 content=$(cat "$out1")
220
221 if [ "$content" == "" ]; then
222 echo " other bc returned an error ($error); continuing..."
Gavin Howard9409a872018-09-08 19:29:29 -0600223 keypress=$(cat -v)
Gavin Howard741077a2018-09-06 16:34:15 -0600224 continue
Gavin Howardd43ae752018-09-06 19:36:18 -0600225 elif [ "$content" == "-0" ]; then
226 echo "0" > "$out1"
Gavin Howard741077a2018-09-06 16:34:15 -0600227 fi
228
Gavin Howardd43ae752018-09-06 19:36:18 -0600229 echo "$line; halt" | "$bc" "$@" -lq > "$out2"
Gavin Howardea7bea62018-02-22 18:55:03 -0700230
231 error="$?"
232
233 if [ "$error" -ne 0 ]; then
Gavin Howarda7eabfc2018-09-08 20:10:08 -0600234 echo " bc returned an error ($error); adding \"$line\" to checklist..."
Gavin Howard17842292018-09-10 09:56:54 -0600235 echo "$line" >> "$math"
236 cat "$out1" >> "$results"
237 echo "$op" >> "$opfile"
Gavin Howarda7eabfc2018-09-08 20:10:08 -0600238 keypress=$(cat -v)
239 continue
Gavin Howardea7bea62018-02-22 18:55:03 -0700240 fi
241
Gavin Howard7de90762018-09-06 11:49:08 -0600242 diff "$out1" "$out2" > /dev/null
Gavin Howardea7bea62018-02-22 18:55:03 -0700243 error="$?"
244
245 if [ "$error" -ne 0 ]; then
Gavin Howarde97309c2018-09-07 12:18:20 -0600246
247 # This works around a bug in GNU bc that gets some
248 # transcendental functions slightly wrong.
249 if [ "$op" -ge 7 ]; then
250
251 # Have GNU bc calculate to one more decimal place and truncate by 1.
252 content=$(echo "scale += 10; $line; halt" | bc -lq)
Gavin Howard9409a872018-09-08 19:29:29 -0600253 content2=${content%??????????}
254 echo "$content2" > "$out1"
Gavin Howarde97309c2018-09-07 12:18:20 -0600255
256 # Compare the truncated.
257 diff "$out1" "$out2" > /dev/null
258 error="$?"
259
260 # GNU bc got it wrong.
261 if [ "$error" -eq 0 ]; then
262 echo " failed because of bug in other bc; continuing..."
Gavin Howard9409a872018-09-08 19:29:29 -0600263 keypress=$(cat -v)
Gavin Howarddccaf6f2018-09-07 14:42:23 -0600264 continue
265 fi
Gavin Howarde97309c2018-09-07 12:18:20 -0600266 fi
267
Gavin Howard9409a872018-09-08 19:29:29 -0600268 echo " failed; adding \"$line\" to checklist..."
Gavin Howard17842292018-09-10 09:56:54 -0600269 echo "$line" >> "$math"
270 cat "$out1" >> "$results"
271 echo "$op" >> "$opfile"
Gavin Howardea7bea62018-02-22 18:55:03 -0700272 fi
273
Gavin Howard9409a872018-09-08 19:29:29 -0600274 keypress=$(cat -v)
275
276done
277
278# Reset the input.
279if [ -t 0 ]; then
280 stty sane
281fi
282
283if [ ! -f "$math" ]; then
284 echo -e "\nNo items in checklist."
285 echo "Exiting..."
286 exit 0
287fi
288
289echo -e "\nGoing through the checklist...\n"
290
291paste "$math" "$results" "$opfile" | while read line result curop; do
292
293 echo -e "\n$line"
294
295 echo "$line; halt" | bc -lq > "$out1"
296 echo "$line; halt" | "$bc" "$@" -lq > "$out2"
297
298 diff "$out1" "$out2"
299
300 echo -en "\nAdd test to test suite? [y/N] "
301 read answer </dev/tty
302
303 if [ "$answer" != "${answer#[Yy]}" ] ;then
304 echo Yes
305 echo "$line" >> "$testdir/${files[$curop]}.txt"
306 cat "$result" >> "$testdir/${files[$curop]}_results.txt"
307 else
308 echo No
309 fi
Gavin Howard8ceb6512018-09-06 14:34:46 -0600310
Gavin Howardea7bea62018-02-22 18:55:03 -0700311done