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 }