trangetest.c - numtools - perform numerical operations on vectors and matrices … | |
git clone git://src.adamsgaard.dk/numtools | |
Log | |
Files | |
Refs | |
README | |
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 maxit… | |
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", err… | |
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 } |