tadd rangetest for binary search testing of programs - numtools - perform numerical operations on vectors and matrices in unix pipes
 (HTM) git clone git://src.adamsgaard.dk/numtools
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 75d269fb6d9921f0090d9ec5ddf7880d25fd0247
 (DIR) parent b26d630f43826b38df0e7ec28242b28bb99178ab
 (HTM) Author: Anders Damsgaard <anders@adamsgaard.dk>
       Date:   Wed, 13 Jan 2021 12:08:02 +0100
       
       add rangetest for binary search testing of programs
       
       Diffstat:
         A rangetest                           |      75 +++++++++++++++++++++++++++++++
       
       1 file changed, 75 insertions(+), 0 deletions(-)
       ---
 (DIR) diff --git a/rangetest b/rangetest
       t@@ -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)
       +}