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

rangetest.c (2170B)


      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <err.h>
      4 #include <limits.h>
      5 #include <string.h>
      6 #include <unistd.h>
      7 
      8 #include "util.h"
      9 
     10 #define VALUESTR "@VAL@"
     11 
     12 static void
     13 usage(void)
     14 {
     15 	errx(1, "usage: rangetest [-n maxiter] cmd min_val max_val\n"
     16 		"where cmd must contain the string '" VALUESTR "'");
     17 }
     18 
     19 static int
     20 launch(char *cmd, char *cmd0, double val)
     21 {
     22 	char *c;
     23 
     24 	if ((c = strstr(cmd0, VALUESTR)) == NULL)
     25 		errx(1, VALUESTR " not found in cmd");
     26 	if (strlcpy(cmd, cmd0, PATH_MAX) >= PATH_MAX)
     27 		err(1, "cmd too long");
     28 	sprintf(cmd + (c - cmd0), "%.17g%s >/dev/null",
     29 	        val, c + strnlen(VALUESTR, sizeof(cmd)));
     30 	if (system(cmd)) {
     31 		fprintf(stderr, "%.17g\n", val);
     32 		return 1;
     33 	} else
     34 		printf("%.17g\n", val);
     35 
     36 	return 0;
     37 }
     38 
     39 static void
     40 binary_search(char *cmd, char *cmd0, double minv, double maxv, int maxiter)
     41 {
     42 	int minfail, maxfail, iter = 0;
     43 	double val;
     44 
     45 	minfail = launch(cmd, cmd0, minv);
     46 	maxfail = launch(cmd, cmd0, maxv);
     47 	if (minfail && maxfail)
     48 		errx(2, "both min_val and max_val runs errored");
     49 	else if (!minfail && !maxfail)
     50 		errx(3, "both min_val and max_val ran successfully");
     51 
     52 	while (minv <= maxv && iter < maxiter) {
     53 		val = minv + 0.5 * (maxv - minv);
     54 		if (launch(cmd, cmd0, val)) {
     55 			if (maxfail) {
     56 				maxv = val;
     57 				maxfail = 1;
     58 			} else {
     59 				minv = val;
     60 			}
     61 		} else {
     62 			if (maxfail) {
     63 				minv = val;
     64 			} else {
     65 				maxv = val;
     66 				maxfail = 0;
     67 			}
     68 		}
     69 		iter++;
     70 	}
     71 }
     72 
     73 int
     74 main(int argc, char *argv[])
     75 {
     76 	int ch, maxiter = 10;
     77 	double minv, maxv;
     78 	char cmd0[PATH_MAX] = "", cmd[PATH_MAX] = "";
     79 	const char *errstr;
     80 
     81 	while ((ch = getopt(argc, argv, "N:")) != -1) {
     82 		switch (ch) {
     83 		case 'N':
     84 			maxiter = strtonum(optarg, 0, INT_MAX, &errstr);
     85 			if (errstr != NULL)
     86 				errx(1, "bad maxiter value, %s: %s", errstr, optarg);
     87 			break;
     88 		default:
     89 			usage();
     90 		}
     91 	}
     92 	argc -= optind;
     93 	argv += optind;
     94 	if (argc == 3) {
     95 		if (strlcpy(cmd0, argv[0], sizeof(cmd0)) >= sizeof(cmd0))
     96 			err(1, "cmd too long");
     97 		minv = atof(argv[1]);
     98 		maxv = atof(argv[2]);
     99 		if (minv >= maxv)
    100 			errx(1, "min_val must be smaller than max_val");
    101 		binary_search(cmd, cmd0, minv, maxv, maxiter);
    102 	} else
    103 		usage();
    104 
    105 	return 0;
    106 }