trangetest.c - 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
       ---
       trangetest.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 }