numtools

perform numerical operations on vectors and matrices in unix pipes
git clone git://src.adamsgaard.dk/numtools # fast
git clone https://src.adamsgaard.dk/numtools.git # slow
Log | Files | Refs | README | LICENSE Back to index

commit 75d269fb6d9921f0090d9ec5ddf7880d25fd0247
parent b26d630f43826b38df0e7ec28242b28bb99178ab
Author: Anders Damsgaard <anders@adamsgaard.dk>
Date:   Wed, 13 Jan 2021 12:08:02 +0100

add rangetest for binary search testing of programs

Diffstat:
Arangetest | 75+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 75 insertions(+), 0 deletions(-)

diff --git a/rangetest b/rangetest @@ -0,0 +1,75 @@ +#!/usr/bin/awk -f +# uses a binary search to run a "cmd" where the first occurence of +# string @PARAM@ is substituted for a value between "min_val" and +# max_val". Successful runs are reported on stdout, failed runs on +# stderr. The "cmd" command must successfully run with either "min_val" +# or "max_val". + +function die(s) { + printf "error: %s\n", s > "/dev/stderr" + exit 1 +} + +function launch(cmd, val) { + sub(/@PARAM@/, val, cmd) + if (system(cmd)) { + printf "%g\n", val > "/dev/stderr" + return 1 + } else { + printf "%g\n", val > "/dev/stdout" + return 0 + } +} + +function binary_search(cmd, min, max, maxiter) { + + minfail = launch(cmd, min) + maxfail = launch(cmd, max) + + if (minfail && maxfail) + die("both min_val and max_val runs errored") + + if (!minfail && !maxfail) + die("both min_val and max_val ran successfully") + + while (min <= max && iter < maxiter) { + val = min + 0.5 * (max - min) + + if (launch(cmd, val)) { # the cmd fails + if (maxfail) { + max = val + maxfail = 1 + } else { + min = val + minfail = 1 + } + } else { # the cmd is ok + if (maxfail) { + min = val + minfail = 0 + } else { + max = val + maxfail = 0 + } + } + iter++ + } +} + +BEGIN { + + if (ARGC != 4) + die("usage: rangetest cmd min_val max_val") + + cmd = ARGV[1] + min = ARGV[2] + max = ARGV[3] + + if (!match(cmd, /@PARAM@/)) + die("@PARAM@ not found in cmd") + + if (min >= max) + die("min_val must be smaller than max_val") + + binary_search(cmd, min, max, 20) +}