Deleted Added
full compact
ministat.c (161692) ministat.c (176106)
1/*
2 * ----------------------------------------------------------------------------
3 * "THE BEER-WARE LICENSE" (Revision 42):
4 * <phk@FreeBSD.ORG> wrote this file. As long as you retain this notice you
5 * can do whatever you want with this stuff. If we meet some day, and you think
6 * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
7 * ----------------------------------------------------------------------------
8 *
9 */
10
11#include <sys/cdefs.h>
1/*
2 * ----------------------------------------------------------------------------
3 * "THE BEER-WARE LICENSE" (Revision 42):
4 * <phk@FreeBSD.ORG> wrote this file. As long as you retain this notice you
5 * can do whatever you want with this stuff. If we meet some day, and you think
6 * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
7 * ----------------------------------------------------------------------------
8 *
9 */
10
11#include <sys/cdefs.h>
12__FBSDID("$FreeBSD: head/usr.bin/ministat/ministat.c 161692 2006-08-28 08:27:02Z phk $");
12__FBSDID("$FreeBSD: head/usr.bin/ministat/ministat.c 176106 2008-02-08 10:58:50Z dwmalone $");
13
14#include <stdio.h>
15#include <math.h>
16#include <err.h>
17#include <string.h>
18#include <stdlib.h>
19#include <unistd.h>
20#include <sys/ioctl.h>
21#include <sys/queue.h>
22#include <sys/ttycom.h>
23
24#define NSTUDENT 100
25#define NCONF 6
26double const studentpct[] = { 80, 90, 95, 98, 99, 99.5 };
27double student [NSTUDENT + 1][NCONF] = {
28/* inf */ { 1.282, 1.645, 1.960, 2.326, 2.576, 3.090 },
29/* 1. */ { 3.078, 6.314, 12.706, 31.821, 63.657, 318.313 },
30/* 2. */ { 1.886, 2.920, 4.303, 6.965, 9.925, 22.327 },
31/* 3. */ { 1.638, 2.353, 3.182, 4.541, 5.841, 10.215 },
32/* 4. */ { 1.533, 2.132, 2.776, 3.747, 4.604, 7.173 },
33/* 5. */ { 1.476, 2.015, 2.571, 3.365, 4.032, 5.893 },
34/* 6. */ { 1.440, 1.943, 2.447, 3.143, 3.707, 5.208 },
35/* 7. */ { 1.415, 1.895, 2.365, 2.998, 3.499, 4.782 },
36/* 8. */ { 1.397, 1.860, 2.306, 2.896, 3.355, 4.499 },
37/* 9. */ { 1.383, 1.833, 2.262, 2.821, 3.250, 4.296 },
38/* 10. */ { 1.372, 1.812, 2.228, 2.764, 3.169, 4.143 },
39/* 11. */ { 1.363, 1.796, 2.201, 2.718, 3.106, 4.024 },
40/* 12. */ { 1.356, 1.782, 2.179, 2.681, 3.055, 3.929 },
41/* 13. */ { 1.350, 1.771, 2.160, 2.650, 3.012, 3.852 },
42/* 14. */ { 1.345, 1.761, 2.145, 2.624, 2.977, 3.787 },
43/* 15. */ { 1.341, 1.753, 2.131, 2.602, 2.947, 3.733 },
44/* 16. */ { 1.337, 1.746, 2.120, 2.583, 2.921, 3.686 },
45/* 17. */ { 1.333, 1.740, 2.110, 2.567, 2.898, 3.646 },
46/* 18. */ { 1.330, 1.734, 2.101, 2.552, 2.878, 3.610 },
47/* 19. */ { 1.328, 1.729, 2.093, 2.539, 2.861, 3.579 },
48/* 20. */ { 1.325, 1.725, 2.086, 2.528, 2.845, 3.552 },
49/* 21. */ { 1.323, 1.721, 2.080, 2.518, 2.831, 3.527 },
50/* 22. */ { 1.321, 1.717, 2.074, 2.508, 2.819, 3.505 },
51/* 23. */ { 1.319, 1.714, 2.069, 2.500, 2.807, 3.485 },
52/* 24. */ { 1.318, 1.711, 2.064, 2.492, 2.797, 3.467 },
53/* 25. */ { 1.316, 1.708, 2.060, 2.485, 2.787, 3.450 },
54/* 26. */ { 1.315, 1.706, 2.056, 2.479, 2.779, 3.435 },
55/* 27. */ { 1.314, 1.703, 2.052, 2.473, 2.771, 3.421 },
56/* 28. */ { 1.313, 1.701, 2.048, 2.467, 2.763, 3.408 },
57/* 29. */ { 1.311, 1.699, 2.045, 2.462, 2.756, 3.396 },
58/* 30. */ { 1.310, 1.697, 2.042, 2.457, 2.750, 3.385 },
59/* 31. */ { 1.309, 1.696, 2.040, 2.453, 2.744, 3.375 },
60/* 32. */ { 1.309, 1.694, 2.037, 2.449, 2.738, 3.365 },
61/* 33. */ { 1.308, 1.692, 2.035, 2.445, 2.733, 3.356 },
62/* 34. */ { 1.307, 1.691, 2.032, 2.441, 2.728, 3.348 },
63/* 35. */ { 1.306, 1.690, 2.030, 2.438, 2.724, 3.340 },
64/* 36. */ { 1.306, 1.688, 2.028, 2.434, 2.719, 3.333 },
65/* 37. */ { 1.305, 1.687, 2.026, 2.431, 2.715, 3.326 },
66/* 38. */ { 1.304, 1.686, 2.024, 2.429, 2.712, 3.319 },
67/* 39. */ { 1.304, 1.685, 2.023, 2.426, 2.708, 3.313 },
68/* 40. */ { 1.303, 1.684, 2.021, 2.423, 2.704, 3.307 },
69/* 41. */ { 1.303, 1.683, 2.020, 2.421, 2.701, 3.301 },
70/* 42. */ { 1.302, 1.682, 2.018, 2.418, 2.698, 3.296 },
71/* 43. */ { 1.302, 1.681, 2.017, 2.416, 2.695, 3.291 },
72/* 44. */ { 1.301, 1.680, 2.015, 2.414, 2.692, 3.286 },
73/* 45. */ { 1.301, 1.679, 2.014, 2.412, 2.690, 3.281 },
74/* 46. */ { 1.300, 1.679, 2.013, 2.410, 2.687, 3.277 },
75/* 47. */ { 1.300, 1.678, 2.012, 2.408, 2.685, 3.273 },
76/* 48. */ { 1.299, 1.677, 2.011, 2.407, 2.682, 3.269 },
77/* 49. */ { 1.299, 1.677, 2.010, 2.405, 2.680, 3.265 },
78/* 50. */ { 1.299, 1.676, 2.009, 2.403, 2.678, 3.261 },
79/* 51. */ { 1.298, 1.675, 2.008, 2.402, 2.676, 3.258 },
80/* 52. */ { 1.298, 1.675, 2.007, 2.400, 2.674, 3.255 },
81/* 53. */ { 1.298, 1.674, 2.006, 2.399, 2.672, 3.251 },
82/* 54. */ { 1.297, 1.674, 2.005, 2.397, 2.670, 3.248 },
83/* 55. */ { 1.297, 1.673, 2.004, 2.396, 2.668, 3.245 },
84/* 56. */ { 1.297, 1.673, 2.003, 2.395, 2.667, 3.242 },
85/* 57. */ { 1.297, 1.672, 2.002, 2.394, 2.665, 3.239 },
86/* 58. */ { 1.296, 1.672, 2.002, 2.392, 2.663, 3.237 },
87/* 59. */ { 1.296, 1.671, 2.001, 2.391, 2.662, 3.234 },
88/* 60. */ { 1.296, 1.671, 2.000, 2.390, 2.660, 3.232 },
89/* 61. */ { 1.296, 1.670, 2.000, 2.389, 2.659, 3.229 },
90/* 62. */ { 1.295, 1.670, 1.999, 2.388, 2.657, 3.227 },
91/* 63. */ { 1.295, 1.669, 1.998, 2.387, 2.656, 3.225 },
92/* 64. */ { 1.295, 1.669, 1.998, 2.386, 2.655, 3.223 },
93/* 65. */ { 1.295, 1.669, 1.997, 2.385, 2.654, 3.220 },
94/* 66. */ { 1.295, 1.668, 1.997, 2.384, 2.652, 3.218 },
95/* 67. */ { 1.294, 1.668, 1.996, 2.383, 2.651, 3.216 },
96/* 68. */ { 1.294, 1.668, 1.995, 2.382, 2.650, 3.214 },
97/* 69. */ { 1.294, 1.667, 1.995, 2.382, 2.649, 3.213 },
98/* 70. */ { 1.294, 1.667, 1.994, 2.381, 2.648, 3.211 },
99/* 71. */ { 1.294, 1.667, 1.994, 2.380, 2.647, 3.209 },
100/* 72. */ { 1.293, 1.666, 1.993, 2.379, 2.646, 3.207 },
101/* 73. */ { 1.293, 1.666, 1.993, 2.379, 2.645, 3.206 },
102/* 74. */ { 1.293, 1.666, 1.993, 2.378, 2.644, 3.204 },
103/* 75. */ { 1.293, 1.665, 1.992, 2.377, 2.643, 3.202 },
104/* 76. */ { 1.293, 1.665, 1.992, 2.376, 2.642, 3.201 },
105/* 77. */ { 1.293, 1.665, 1.991, 2.376, 2.641, 3.199 },
106/* 78. */ { 1.292, 1.665, 1.991, 2.375, 2.640, 3.198 },
107/* 79. */ { 1.292, 1.664, 1.990, 2.374, 2.640, 3.197 },
108/* 80. */ { 1.292, 1.664, 1.990, 2.374, 2.639, 3.195 },
109/* 81. */ { 1.292, 1.664, 1.990, 2.373, 2.638, 3.194 },
110/* 82. */ { 1.292, 1.664, 1.989, 2.373, 2.637, 3.193 },
111/* 83. */ { 1.292, 1.663, 1.989, 2.372, 2.636, 3.191 },
112/* 84. */ { 1.292, 1.663, 1.989, 2.372, 2.636, 3.190 },
113/* 85. */ { 1.292, 1.663, 1.988, 2.371, 2.635, 3.189 },
114/* 86. */ { 1.291, 1.663, 1.988, 2.370, 2.634, 3.188 },
115/* 87. */ { 1.291, 1.663, 1.988, 2.370, 2.634, 3.187 },
116/* 88. */ { 1.291, 1.662, 1.987, 2.369, 2.633, 3.185 },
117/* 89. */ { 1.291, 1.662, 1.987, 2.369, 2.632, 3.184 },
118/* 90. */ { 1.291, 1.662, 1.987, 2.368, 2.632, 3.183 },
119/* 91. */ { 1.291, 1.662, 1.986, 2.368, 2.631, 3.182 },
120/* 92. */ { 1.291, 1.662, 1.986, 2.368, 2.630, 3.181 },
121/* 93. */ { 1.291, 1.661, 1.986, 2.367, 2.630, 3.180 },
122/* 94. */ { 1.291, 1.661, 1.986, 2.367, 2.629, 3.179 },
123/* 95. */ { 1.291, 1.661, 1.985, 2.366, 2.629, 3.178 },
124/* 96. */ { 1.290, 1.661, 1.985, 2.366, 2.628, 3.177 },
125/* 97. */ { 1.290, 1.661, 1.985, 2.365, 2.627, 3.176 },
126/* 98. */ { 1.290, 1.661, 1.984, 2.365, 2.627, 3.175 },
127/* 99. */ { 1.290, 1.660, 1.984, 2.365, 2.626, 3.175 },
128/* 100. */ { 1.290, 1.660, 1.984, 2.364, 2.626, 3.174 }
129};
130
131#define MAX_DS 8
132static char symbol[MAX_DS] = { ' ', 'x', '+', '*', '%', '#', '@', 'O' };
133
134TAILQ_HEAD(pointlist, point);
135
136struct dataset {
137 char *name;
138 struct pointlist list;
139 double sy, syy;
140 int n;
141};
142
143static struct dataset *
144NewSet(void)
145{
146 struct dataset *ds;
147
148 ds = calloc(1, sizeof *ds);
149 TAILQ_INIT(&ds->list);
150 return(ds);
151}
152
153struct point {
154 TAILQ_ENTRY(point) list;
155 double val;
156};
157
158static void
159AddPoint(struct dataset *ds, double a)
160{
161 struct point *pp, *pp2;
162
163 pp = calloc(1, sizeof *pp);
164 pp->val = a;
165
166 ds->n++;
167 ds->sy += a;
168 ds->syy += a * a;
169 if (TAILQ_EMPTY(&ds->list)) {
170 TAILQ_INSERT_HEAD(&ds->list, pp, list);
171 return;
172 }
173 TAILQ_FOREACH(pp2, &ds->list, list) {
174 if (pp->val < pp2->val) {
175 TAILQ_INSERT_BEFORE(pp2, pp, list);
176 return;
177 }
178 }
179 TAILQ_INSERT_TAIL(&ds->list, pp, list);
180}
181
182static double
183Min(struct dataset *ds)
184{
185
186 return (TAILQ_FIRST(&ds->list)->val);
187}
188
189static double
190Max(struct dataset *ds)
191{
192
193 return(TAILQ_LAST(&ds->list, pointlist)->val);
194}
195
196static double
197Avg(struct dataset *ds)
198{
199
200 return(ds->sy / ds->n);
201}
202
203static double
204Median(struct dataset *ds)
205{
206 int even, i;
207 struct point *p1, *p2;
208
209 if ((ds->n % 2) == 1) {
210 i = (ds->n / 2) + 1;
211 even = 0;
212 } else {
213 i = ds->n / 2;
214 even = 1;
215 }
216 TAILQ_FOREACH(p1, &ds->list, list) {
217 --i;
218 if (i == 0)
219 break;
220 }
221 if (even) {
222 p2 = TAILQ_NEXT(p1, list);
223 return ((p2->val + p1->val) / 2);
224 }
225 return (p1->val);
226}
227
228static double
229Var(struct dataset *ds)
230{
231
232 return (ds->syy - ds->sy * ds->sy / ds->n) / (ds->n - 1.0);
233}
234
235static double
236Stddev(struct dataset *ds)
237{
238
239 return sqrt(Var(ds));
240}
241
242static void
243VitalsHead(void)
244{
245
246 printf(" N Min Max Median Avg Stddev\n");
247}
248
249static void
250Vitals(struct dataset *ds, int flag)
251{
13
14#include <stdio.h>
15#include <math.h>
16#include <err.h>
17#include <string.h>
18#include <stdlib.h>
19#include <unistd.h>
20#include <sys/ioctl.h>
21#include <sys/queue.h>
22#include <sys/ttycom.h>
23
24#define NSTUDENT 100
25#define NCONF 6
26double const studentpct[] = { 80, 90, 95, 98, 99, 99.5 };
27double student [NSTUDENT + 1][NCONF] = {
28/* inf */ { 1.282, 1.645, 1.960, 2.326, 2.576, 3.090 },
29/* 1. */ { 3.078, 6.314, 12.706, 31.821, 63.657, 318.313 },
30/* 2. */ { 1.886, 2.920, 4.303, 6.965, 9.925, 22.327 },
31/* 3. */ { 1.638, 2.353, 3.182, 4.541, 5.841, 10.215 },
32/* 4. */ { 1.533, 2.132, 2.776, 3.747, 4.604, 7.173 },
33/* 5. */ { 1.476, 2.015, 2.571, 3.365, 4.032, 5.893 },
34/* 6. */ { 1.440, 1.943, 2.447, 3.143, 3.707, 5.208 },
35/* 7. */ { 1.415, 1.895, 2.365, 2.998, 3.499, 4.782 },
36/* 8. */ { 1.397, 1.860, 2.306, 2.896, 3.355, 4.499 },
37/* 9. */ { 1.383, 1.833, 2.262, 2.821, 3.250, 4.296 },
38/* 10. */ { 1.372, 1.812, 2.228, 2.764, 3.169, 4.143 },
39/* 11. */ { 1.363, 1.796, 2.201, 2.718, 3.106, 4.024 },
40/* 12. */ { 1.356, 1.782, 2.179, 2.681, 3.055, 3.929 },
41/* 13. */ { 1.350, 1.771, 2.160, 2.650, 3.012, 3.852 },
42/* 14. */ { 1.345, 1.761, 2.145, 2.624, 2.977, 3.787 },
43/* 15. */ { 1.341, 1.753, 2.131, 2.602, 2.947, 3.733 },
44/* 16. */ { 1.337, 1.746, 2.120, 2.583, 2.921, 3.686 },
45/* 17. */ { 1.333, 1.740, 2.110, 2.567, 2.898, 3.646 },
46/* 18. */ { 1.330, 1.734, 2.101, 2.552, 2.878, 3.610 },
47/* 19. */ { 1.328, 1.729, 2.093, 2.539, 2.861, 3.579 },
48/* 20. */ { 1.325, 1.725, 2.086, 2.528, 2.845, 3.552 },
49/* 21. */ { 1.323, 1.721, 2.080, 2.518, 2.831, 3.527 },
50/* 22. */ { 1.321, 1.717, 2.074, 2.508, 2.819, 3.505 },
51/* 23. */ { 1.319, 1.714, 2.069, 2.500, 2.807, 3.485 },
52/* 24. */ { 1.318, 1.711, 2.064, 2.492, 2.797, 3.467 },
53/* 25. */ { 1.316, 1.708, 2.060, 2.485, 2.787, 3.450 },
54/* 26. */ { 1.315, 1.706, 2.056, 2.479, 2.779, 3.435 },
55/* 27. */ { 1.314, 1.703, 2.052, 2.473, 2.771, 3.421 },
56/* 28. */ { 1.313, 1.701, 2.048, 2.467, 2.763, 3.408 },
57/* 29. */ { 1.311, 1.699, 2.045, 2.462, 2.756, 3.396 },
58/* 30. */ { 1.310, 1.697, 2.042, 2.457, 2.750, 3.385 },
59/* 31. */ { 1.309, 1.696, 2.040, 2.453, 2.744, 3.375 },
60/* 32. */ { 1.309, 1.694, 2.037, 2.449, 2.738, 3.365 },
61/* 33. */ { 1.308, 1.692, 2.035, 2.445, 2.733, 3.356 },
62/* 34. */ { 1.307, 1.691, 2.032, 2.441, 2.728, 3.348 },
63/* 35. */ { 1.306, 1.690, 2.030, 2.438, 2.724, 3.340 },
64/* 36. */ { 1.306, 1.688, 2.028, 2.434, 2.719, 3.333 },
65/* 37. */ { 1.305, 1.687, 2.026, 2.431, 2.715, 3.326 },
66/* 38. */ { 1.304, 1.686, 2.024, 2.429, 2.712, 3.319 },
67/* 39. */ { 1.304, 1.685, 2.023, 2.426, 2.708, 3.313 },
68/* 40. */ { 1.303, 1.684, 2.021, 2.423, 2.704, 3.307 },
69/* 41. */ { 1.303, 1.683, 2.020, 2.421, 2.701, 3.301 },
70/* 42. */ { 1.302, 1.682, 2.018, 2.418, 2.698, 3.296 },
71/* 43. */ { 1.302, 1.681, 2.017, 2.416, 2.695, 3.291 },
72/* 44. */ { 1.301, 1.680, 2.015, 2.414, 2.692, 3.286 },
73/* 45. */ { 1.301, 1.679, 2.014, 2.412, 2.690, 3.281 },
74/* 46. */ { 1.300, 1.679, 2.013, 2.410, 2.687, 3.277 },
75/* 47. */ { 1.300, 1.678, 2.012, 2.408, 2.685, 3.273 },
76/* 48. */ { 1.299, 1.677, 2.011, 2.407, 2.682, 3.269 },
77/* 49. */ { 1.299, 1.677, 2.010, 2.405, 2.680, 3.265 },
78/* 50. */ { 1.299, 1.676, 2.009, 2.403, 2.678, 3.261 },
79/* 51. */ { 1.298, 1.675, 2.008, 2.402, 2.676, 3.258 },
80/* 52. */ { 1.298, 1.675, 2.007, 2.400, 2.674, 3.255 },
81/* 53. */ { 1.298, 1.674, 2.006, 2.399, 2.672, 3.251 },
82/* 54. */ { 1.297, 1.674, 2.005, 2.397, 2.670, 3.248 },
83/* 55. */ { 1.297, 1.673, 2.004, 2.396, 2.668, 3.245 },
84/* 56. */ { 1.297, 1.673, 2.003, 2.395, 2.667, 3.242 },
85/* 57. */ { 1.297, 1.672, 2.002, 2.394, 2.665, 3.239 },
86/* 58. */ { 1.296, 1.672, 2.002, 2.392, 2.663, 3.237 },
87/* 59. */ { 1.296, 1.671, 2.001, 2.391, 2.662, 3.234 },
88/* 60. */ { 1.296, 1.671, 2.000, 2.390, 2.660, 3.232 },
89/* 61. */ { 1.296, 1.670, 2.000, 2.389, 2.659, 3.229 },
90/* 62. */ { 1.295, 1.670, 1.999, 2.388, 2.657, 3.227 },
91/* 63. */ { 1.295, 1.669, 1.998, 2.387, 2.656, 3.225 },
92/* 64. */ { 1.295, 1.669, 1.998, 2.386, 2.655, 3.223 },
93/* 65. */ { 1.295, 1.669, 1.997, 2.385, 2.654, 3.220 },
94/* 66. */ { 1.295, 1.668, 1.997, 2.384, 2.652, 3.218 },
95/* 67. */ { 1.294, 1.668, 1.996, 2.383, 2.651, 3.216 },
96/* 68. */ { 1.294, 1.668, 1.995, 2.382, 2.650, 3.214 },
97/* 69. */ { 1.294, 1.667, 1.995, 2.382, 2.649, 3.213 },
98/* 70. */ { 1.294, 1.667, 1.994, 2.381, 2.648, 3.211 },
99/* 71. */ { 1.294, 1.667, 1.994, 2.380, 2.647, 3.209 },
100/* 72. */ { 1.293, 1.666, 1.993, 2.379, 2.646, 3.207 },
101/* 73. */ { 1.293, 1.666, 1.993, 2.379, 2.645, 3.206 },
102/* 74. */ { 1.293, 1.666, 1.993, 2.378, 2.644, 3.204 },
103/* 75. */ { 1.293, 1.665, 1.992, 2.377, 2.643, 3.202 },
104/* 76. */ { 1.293, 1.665, 1.992, 2.376, 2.642, 3.201 },
105/* 77. */ { 1.293, 1.665, 1.991, 2.376, 2.641, 3.199 },
106/* 78. */ { 1.292, 1.665, 1.991, 2.375, 2.640, 3.198 },
107/* 79. */ { 1.292, 1.664, 1.990, 2.374, 2.640, 3.197 },
108/* 80. */ { 1.292, 1.664, 1.990, 2.374, 2.639, 3.195 },
109/* 81. */ { 1.292, 1.664, 1.990, 2.373, 2.638, 3.194 },
110/* 82. */ { 1.292, 1.664, 1.989, 2.373, 2.637, 3.193 },
111/* 83. */ { 1.292, 1.663, 1.989, 2.372, 2.636, 3.191 },
112/* 84. */ { 1.292, 1.663, 1.989, 2.372, 2.636, 3.190 },
113/* 85. */ { 1.292, 1.663, 1.988, 2.371, 2.635, 3.189 },
114/* 86. */ { 1.291, 1.663, 1.988, 2.370, 2.634, 3.188 },
115/* 87. */ { 1.291, 1.663, 1.988, 2.370, 2.634, 3.187 },
116/* 88. */ { 1.291, 1.662, 1.987, 2.369, 2.633, 3.185 },
117/* 89. */ { 1.291, 1.662, 1.987, 2.369, 2.632, 3.184 },
118/* 90. */ { 1.291, 1.662, 1.987, 2.368, 2.632, 3.183 },
119/* 91. */ { 1.291, 1.662, 1.986, 2.368, 2.631, 3.182 },
120/* 92. */ { 1.291, 1.662, 1.986, 2.368, 2.630, 3.181 },
121/* 93. */ { 1.291, 1.661, 1.986, 2.367, 2.630, 3.180 },
122/* 94. */ { 1.291, 1.661, 1.986, 2.367, 2.629, 3.179 },
123/* 95. */ { 1.291, 1.661, 1.985, 2.366, 2.629, 3.178 },
124/* 96. */ { 1.290, 1.661, 1.985, 2.366, 2.628, 3.177 },
125/* 97. */ { 1.290, 1.661, 1.985, 2.365, 2.627, 3.176 },
126/* 98. */ { 1.290, 1.661, 1.984, 2.365, 2.627, 3.175 },
127/* 99. */ { 1.290, 1.660, 1.984, 2.365, 2.626, 3.175 },
128/* 100. */ { 1.290, 1.660, 1.984, 2.364, 2.626, 3.174 }
129};
130
131#define MAX_DS 8
132static char symbol[MAX_DS] = { ' ', 'x', '+', '*', '%', '#', '@', 'O' };
133
134TAILQ_HEAD(pointlist, point);
135
136struct dataset {
137 char *name;
138 struct pointlist list;
139 double sy, syy;
140 int n;
141};
142
143static struct dataset *
144NewSet(void)
145{
146 struct dataset *ds;
147
148 ds = calloc(1, sizeof *ds);
149 TAILQ_INIT(&ds->list);
150 return(ds);
151}
152
153struct point {
154 TAILQ_ENTRY(point) list;
155 double val;
156};
157
158static void
159AddPoint(struct dataset *ds, double a)
160{
161 struct point *pp, *pp2;
162
163 pp = calloc(1, sizeof *pp);
164 pp->val = a;
165
166 ds->n++;
167 ds->sy += a;
168 ds->syy += a * a;
169 if (TAILQ_EMPTY(&ds->list)) {
170 TAILQ_INSERT_HEAD(&ds->list, pp, list);
171 return;
172 }
173 TAILQ_FOREACH(pp2, &ds->list, list) {
174 if (pp->val < pp2->val) {
175 TAILQ_INSERT_BEFORE(pp2, pp, list);
176 return;
177 }
178 }
179 TAILQ_INSERT_TAIL(&ds->list, pp, list);
180}
181
182static double
183Min(struct dataset *ds)
184{
185
186 return (TAILQ_FIRST(&ds->list)->val);
187}
188
189static double
190Max(struct dataset *ds)
191{
192
193 return(TAILQ_LAST(&ds->list, pointlist)->val);
194}
195
196static double
197Avg(struct dataset *ds)
198{
199
200 return(ds->sy / ds->n);
201}
202
203static double
204Median(struct dataset *ds)
205{
206 int even, i;
207 struct point *p1, *p2;
208
209 if ((ds->n % 2) == 1) {
210 i = (ds->n / 2) + 1;
211 even = 0;
212 } else {
213 i = ds->n / 2;
214 even = 1;
215 }
216 TAILQ_FOREACH(p1, &ds->list, list) {
217 --i;
218 if (i == 0)
219 break;
220 }
221 if (even) {
222 p2 = TAILQ_NEXT(p1, list);
223 return ((p2->val + p1->val) / 2);
224 }
225 return (p1->val);
226}
227
228static double
229Var(struct dataset *ds)
230{
231
232 return (ds->syy - ds->sy * ds->sy / ds->n) / (ds->n - 1.0);
233}
234
235static double
236Stddev(struct dataset *ds)
237{
238
239 return sqrt(Var(ds));
240}
241
242static void
243VitalsHead(void)
244{
245
246 printf(" N Min Max Median Avg Stddev\n");
247}
248
249static void
250Vitals(struct dataset *ds, int flag)
251{
252 double a;
253
254 printf("%c %3d %13.8g %13.8g %13.8g %13.8g %13.8g", symbol[flag],
255 ds->n, Min(ds), Max(ds), Median(ds), Avg(ds), Stddev(ds));
256 printf("\n");
257}
258
259static void
260Relative(struct dataset *ds, struct dataset *rs, int confidx)
261{
262 double spool, s, d, e, t;
252
253 printf("%c %3d %13.8g %13.8g %13.8g %13.8g %13.8g", symbol[flag],
254 ds->n, Min(ds), Max(ds), Median(ds), Avg(ds), Stddev(ds));
255 printf("\n");
256}
257
258static void
259Relative(struct dataset *ds, struct dataset *rs, int confidx)
260{
261 double spool, s, d, e, t;
263 int i, c;
262 int i;
264
265 i = ds->n + rs->n - 2;
266 if (i > NSTUDENT)
267 t = student[0][confidx];
268 else
269 t = student[i][confidx];
270 spool = (ds->n - 1) * Var(ds) + (rs->n - 1) * Var(rs);
271 spool /= ds->n + rs->n - 2;
272 spool = sqrt(spool);
273 s = spool * sqrt(1.0 / ds->n + 1.0 / rs->n);
274 d = Avg(ds) - Avg(rs);
275 e = t * s;
276
277 if (fabs(d) > e) {
278
279 printf("Difference at %.1f%% confidence\n", studentpct[confidx]);
280 printf(" %g +/- %g\n", d, e);
281 printf(" %g%% +/- %g%%\n", d * 100 / Avg(rs), e * 100 / Avg(rs));
282 printf(" (Student's t, pooled s = %g)\n", spool);
283 } else {
284 printf("No difference proven at %.1f%% confidence\n",
285 studentpct[confidx]);
286 }
287}
288
289struct plot {
290 double min;
291 double max;
292 double span;
293 int width;
294
295 double x0, dx;
296 int height;
297 char *data;
298 char **bar;
299 int separate_bars;
300 int num_datasets;
301};
302
303static struct plot plot;
304
305static void
306SetupPlot(int width, int separate, int num_datasets)
307{
308 struct plot *pl;
309
310 pl = &plot;
311 pl->width = width;
312 pl->height = 0;
313 pl->data = NULL;
314 pl->bar = NULL;
315 pl->separate_bars = separate;
316 pl->num_datasets = num_datasets;
317 pl->min = 999e99;
318 pl->max = -999e99;
319}
320
321static void
322AdjPlot(double a)
323{
324 struct plot *pl;
325
326 pl = &plot;
327 if (a < pl->min)
328 pl->min = a;
329 if (a > pl->max)
330 pl->max = a;
331 pl->span = pl->max - pl->min;
332 pl->dx = pl->span / (pl->width - 1.0);
333 pl->x0 = pl->min - .5 * pl->dx;
334}
335
336static void
337DimPlot(struct dataset *ds)
338{
339 AdjPlot(Min(ds));
340 AdjPlot(Max(ds));
341 AdjPlot(Avg(ds) - Stddev(ds));
342 AdjPlot(Avg(ds) + Stddev(ds));
343}
344
345static void
346PlotSet(struct dataset *ds, int val)
347{
348 struct plot *pl;
349 struct point *pp;
350 int i, j, m, x;
351 int bar;
352
353 pl = &plot;
354 if (pl->span == 0)
355 return;
356
357 if (pl->separate_bars)
358 bar = val-1;
359 else
360 bar = 0;
361
362 if (pl->bar == NULL) {
363 pl->bar = malloc(sizeof(char *) * pl->num_datasets);
364 memset(pl->bar, 0, sizeof(char*) * pl->num_datasets);
365 }
366 if (pl->bar[bar] == NULL) {
367 pl->bar[bar] = malloc(pl->width);
368 memset(pl->bar[bar], 0, pl->width);
369 }
370
371 m = 1;
372 i = -1;
373 j = 0;
374 TAILQ_FOREACH(pp, &ds->list, list) {
375 x = (pp->val - pl->x0) / pl->dx;
376 if (x == i) {
377 j++;
378 if (j > m)
379 m = j;
380 } else {
381 j = 1;
382 i = x;
383 }
384 }
385 m += 1;
386 if (m > pl->height) {
387 pl->data = realloc(pl->data, pl->width * m);
388 memset(pl->data + pl->height * pl->width, 0,
389 (m - pl->height) * pl->width);
390 }
391 pl->height = m;
392 i = -1;
393 TAILQ_FOREACH(pp, &ds->list, list) {
394 x = (pp->val - pl->x0) / pl->dx;
395 if (x == i) {
396 j++;
397 } else {
398 j = 1;
399 i = x;
400 }
401 pl->data[j * pl->width + x] |= val;
402 }
403 if (!isnan(Stddev(ds))) {
404 x = ((Avg(ds) - Stddev(ds)) - pl->x0) / pl->dx;
405 m = ((Avg(ds) + Stddev(ds)) - pl->x0) / pl->dx;
406 pl->bar[bar][m] = '|';
407 pl->bar[bar][x] = '|';
408 for (i = x + 1; i < m; i++)
409 if (pl->bar[bar][i] == 0)
410 pl->bar[bar][i] = '_';
411 }
412 x = (Median(ds) - pl->x0) / pl->dx;
413 pl->bar[bar][x] = 'M';
414 x = (Avg(ds) - pl->x0) / pl->dx;
415 pl->bar[bar][x] = 'A';
416}
417
418static void
419DumpPlot(void)
420{
421 struct plot *pl;
422 int i, j, k;
423
424 pl = &plot;
425 if (pl->span == 0) {
426 printf("[no plot, span is zero width]\n");
427 return;
428 }
429
430 putchar('+');
431 for (i = 0; i < pl->width; i++)
432 putchar('-');
433 putchar('+');
434 putchar('\n');
435 for (i = 1; i < pl->height; i++) {
436 putchar('|');
437 for (j = 0; j < pl->width; j++) {
438 k = pl->data[(pl->height - i) * pl->width + j];
439 if (k >= 0 && k < MAX_DS)
440 putchar(symbol[k]);
441 else
442 printf("[%02x]", k);
443 }
444 putchar('|');
445 putchar('\n');
446 }
447 for (i = 0; i < pl->num_datasets; i++) {
448 if (pl->bar[i] == NULL)
449 continue;
450 putchar('|');
451 for (j = 0; j < pl->width; j++) {
452 k = pl->bar[i][j];
453 if (k == 0)
454 k = ' ';
455 putchar(k);
456 }
457 putchar('|');
458 putchar('\n');
459 }
460 putchar('+');
461 for (i = 0; i < pl->width; i++)
462 putchar('-');
463 putchar('+');
464 putchar('\n');
465}
466
467
468static struct dataset *
263
264 i = ds->n + rs->n - 2;
265 if (i > NSTUDENT)
266 t = student[0][confidx];
267 else
268 t = student[i][confidx];
269 spool = (ds->n - 1) * Var(ds) + (rs->n - 1) * Var(rs);
270 spool /= ds->n + rs->n - 2;
271 spool = sqrt(spool);
272 s = spool * sqrt(1.0 / ds->n + 1.0 / rs->n);
273 d = Avg(ds) - Avg(rs);
274 e = t * s;
275
276 if (fabs(d) > e) {
277
278 printf("Difference at %.1f%% confidence\n", studentpct[confidx]);
279 printf(" %g +/- %g\n", d, e);
280 printf(" %g%% +/- %g%%\n", d * 100 / Avg(rs), e * 100 / Avg(rs));
281 printf(" (Student's t, pooled s = %g)\n", spool);
282 } else {
283 printf("No difference proven at %.1f%% confidence\n",
284 studentpct[confidx]);
285 }
286}
287
288struct plot {
289 double min;
290 double max;
291 double span;
292 int width;
293
294 double x0, dx;
295 int height;
296 char *data;
297 char **bar;
298 int separate_bars;
299 int num_datasets;
300};
301
302static struct plot plot;
303
304static void
305SetupPlot(int width, int separate, int num_datasets)
306{
307 struct plot *pl;
308
309 pl = &plot;
310 pl->width = width;
311 pl->height = 0;
312 pl->data = NULL;
313 pl->bar = NULL;
314 pl->separate_bars = separate;
315 pl->num_datasets = num_datasets;
316 pl->min = 999e99;
317 pl->max = -999e99;
318}
319
320static void
321AdjPlot(double a)
322{
323 struct plot *pl;
324
325 pl = &plot;
326 if (a < pl->min)
327 pl->min = a;
328 if (a > pl->max)
329 pl->max = a;
330 pl->span = pl->max - pl->min;
331 pl->dx = pl->span / (pl->width - 1.0);
332 pl->x0 = pl->min - .5 * pl->dx;
333}
334
335static void
336DimPlot(struct dataset *ds)
337{
338 AdjPlot(Min(ds));
339 AdjPlot(Max(ds));
340 AdjPlot(Avg(ds) - Stddev(ds));
341 AdjPlot(Avg(ds) + Stddev(ds));
342}
343
344static void
345PlotSet(struct dataset *ds, int val)
346{
347 struct plot *pl;
348 struct point *pp;
349 int i, j, m, x;
350 int bar;
351
352 pl = &plot;
353 if (pl->span == 0)
354 return;
355
356 if (pl->separate_bars)
357 bar = val-1;
358 else
359 bar = 0;
360
361 if (pl->bar == NULL) {
362 pl->bar = malloc(sizeof(char *) * pl->num_datasets);
363 memset(pl->bar, 0, sizeof(char*) * pl->num_datasets);
364 }
365 if (pl->bar[bar] == NULL) {
366 pl->bar[bar] = malloc(pl->width);
367 memset(pl->bar[bar], 0, pl->width);
368 }
369
370 m = 1;
371 i = -1;
372 j = 0;
373 TAILQ_FOREACH(pp, &ds->list, list) {
374 x = (pp->val - pl->x0) / pl->dx;
375 if (x == i) {
376 j++;
377 if (j > m)
378 m = j;
379 } else {
380 j = 1;
381 i = x;
382 }
383 }
384 m += 1;
385 if (m > pl->height) {
386 pl->data = realloc(pl->data, pl->width * m);
387 memset(pl->data + pl->height * pl->width, 0,
388 (m - pl->height) * pl->width);
389 }
390 pl->height = m;
391 i = -1;
392 TAILQ_FOREACH(pp, &ds->list, list) {
393 x = (pp->val - pl->x0) / pl->dx;
394 if (x == i) {
395 j++;
396 } else {
397 j = 1;
398 i = x;
399 }
400 pl->data[j * pl->width + x] |= val;
401 }
402 if (!isnan(Stddev(ds))) {
403 x = ((Avg(ds) - Stddev(ds)) - pl->x0) / pl->dx;
404 m = ((Avg(ds) + Stddev(ds)) - pl->x0) / pl->dx;
405 pl->bar[bar][m] = '|';
406 pl->bar[bar][x] = '|';
407 for (i = x + 1; i < m; i++)
408 if (pl->bar[bar][i] == 0)
409 pl->bar[bar][i] = '_';
410 }
411 x = (Median(ds) - pl->x0) / pl->dx;
412 pl->bar[bar][x] = 'M';
413 x = (Avg(ds) - pl->x0) / pl->dx;
414 pl->bar[bar][x] = 'A';
415}
416
417static void
418DumpPlot(void)
419{
420 struct plot *pl;
421 int i, j, k;
422
423 pl = &plot;
424 if (pl->span == 0) {
425 printf("[no plot, span is zero width]\n");
426 return;
427 }
428
429 putchar('+');
430 for (i = 0; i < pl->width; i++)
431 putchar('-');
432 putchar('+');
433 putchar('\n');
434 for (i = 1; i < pl->height; i++) {
435 putchar('|');
436 for (j = 0; j < pl->width; j++) {
437 k = pl->data[(pl->height - i) * pl->width + j];
438 if (k >= 0 && k < MAX_DS)
439 putchar(symbol[k]);
440 else
441 printf("[%02x]", k);
442 }
443 putchar('|');
444 putchar('\n');
445 }
446 for (i = 0; i < pl->num_datasets; i++) {
447 if (pl->bar[i] == NULL)
448 continue;
449 putchar('|');
450 for (j = 0; j < pl->width; j++) {
451 k = pl->bar[i][j];
452 if (k == 0)
453 k = ' ';
454 putchar(k);
455 }
456 putchar('|');
457 putchar('\n');
458 }
459 putchar('+');
460 for (i = 0; i < pl->width; i++)
461 putchar('-');
462 putchar('+');
463 putchar('\n');
464}
465
466
467static struct dataset *
469ReadSet(char *n, int column, char *delim)
468ReadSet(const char *n, int column, const char *delim)
470{
471 FILE *f;
472 char buf[BUFSIZ], *p, *t;
473 struct dataset *s;
474 double d;
475 int line;
476 int i;
477
478 if (n == NULL) {
479 f = stdin;
480 n = "<stdin>";
481 } else if (!strcmp(n, "-")) {
482 f = stdin;
483 n = "<stdin>";
484 } else {
485 f = fopen(n, "r");
486 }
487 if (f == NULL)
488 err(1, "Cannot open %s", n);
489 s = NewSet();
490 s->name = strdup(n);
491 line = 0;
492 while (fgets(buf, sizeof buf, f) != NULL) {
493 line++;
494
495 i = strlen(buf);
496 if (buf[i-1] == '\n')
497 buf[i-1] = '\0';
498 for (i = 1, t = strtok(buf, delim);
499 t != NULL && *t != '#';
500 i++, t = strtok(NULL, delim)) {
501 if (i == column)
502 break;
503 }
504 if (t == NULL || *t == '#')
505 continue;
506
507 d = strtod(t, &p);
508 if (p != NULL && *p != '\0')
509 err(2, "Invalid data on line %d in %s\n", line, n);
510 if (*buf != '\0')
511 AddPoint(s, d);
512 }
513 fclose(f);
514 if (s->n < 3) {
515 fprintf(stderr,
516 "Dataset %s must contain at least 3 data points\n", n);
517 exit (2);
518 }
519 return (s);
520}
521
522static void
523usage(char const *whine)
524{
525 int i;
526
527 fprintf(stderr, "%s\n", whine);
528 fprintf(stderr,
529 "Usage: ministat [-C column] [-c confidence] [-d delimiter(s)] [-ns] [-w width] [file [file ...]]\n");
530 fprintf(stderr, "\tconfidence = {");
531 for (i = 0; i < NCONF; i++) {
532 fprintf(stderr, "%s%g%%",
533 i ? ", " : "",
534 studentpct[i]);
535 }
536 fprintf(stderr, "}\n");
537 fprintf(stderr, "\t-C : column number to extract (starts and defaults to 1)\n");
538 fprintf(stderr, "\t-d : delimiter(s) string, default to \" \\t\"\n");
539 fprintf(stderr, "\t-n : print summary statistics only, no graph/test\n");
540 fprintf(stderr, "\t-s : print avg/median/stddev bars on separate lines\n");
541 fprintf(stderr, "\t-w : width of graph/test output (default 74 or terminal width)\n");
542 exit (2);
543}
544
545int
546main(int argc, char **argv)
547{
548 struct dataset *ds[7];
549 int nds;
550 double a;
469{
470 FILE *f;
471 char buf[BUFSIZ], *p, *t;
472 struct dataset *s;
473 double d;
474 int line;
475 int i;
476
477 if (n == NULL) {
478 f = stdin;
479 n = "<stdin>";
480 } else if (!strcmp(n, "-")) {
481 f = stdin;
482 n = "<stdin>";
483 } else {
484 f = fopen(n, "r");
485 }
486 if (f == NULL)
487 err(1, "Cannot open %s", n);
488 s = NewSet();
489 s->name = strdup(n);
490 line = 0;
491 while (fgets(buf, sizeof buf, f) != NULL) {
492 line++;
493
494 i = strlen(buf);
495 if (buf[i-1] == '\n')
496 buf[i-1] = '\0';
497 for (i = 1, t = strtok(buf, delim);
498 t != NULL && *t != '#';
499 i++, t = strtok(NULL, delim)) {
500 if (i == column)
501 break;
502 }
503 if (t == NULL || *t == '#')
504 continue;
505
506 d = strtod(t, &p);
507 if (p != NULL && *p != '\0')
508 err(2, "Invalid data on line %d in %s\n", line, n);
509 if (*buf != '\0')
510 AddPoint(s, d);
511 }
512 fclose(f);
513 if (s->n < 3) {
514 fprintf(stderr,
515 "Dataset %s must contain at least 3 data points\n", n);
516 exit (2);
517 }
518 return (s);
519}
520
521static void
522usage(char const *whine)
523{
524 int i;
525
526 fprintf(stderr, "%s\n", whine);
527 fprintf(stderr,
528 "Usage: ministat [-C column] [-c confidence] [-d delimiter(s)] [-ns] [-w width] [file [file ...]]\n");
529 fprintf(stderr, "\tconfidence = {");
530 for (i = 0; i < NCONF; i++) {
531 fprintf(stderr, "%s%g%%",
532 i ? ", " : "",
533 studentpct[i]);
534 }
535 fprintf(stderr, "}\n");
536 fprintf(stderr, "\t-C : column number to extract (starts and defaults to 1)\n");
537 fprintf(stderr, "\t-d : delimiter(s) string, default to \" \\t\"\n");
538 fprintf(stderr, "\t-n : print summary statistics only, no graph/test\n");
539 fprintf(stderr, "\t-s : print avg/median/stddev bars on separate lines\n");
540 fprintf(stderr, "\t-w : width of graph/test output (default 74 or terminal width)\n");
541 exit (2);
542}
543
544int
545main(int argc, char **argv)
546{
547 struct dataset *ds[7];
548 int nds;
549 double a;
551 char *delim = " \t";
550 const char *delim = " \t";
552 char *p;
553 int c, i, ci;
554 int column = 1;
555 int flag_s = 0;
556 int flag_n = 0;
557 int termwidth = 74;
558
559 if (isatty(STDOUT_FILENO)) {
560 struct winsize wsz;
561
562 if ((p = getenv("COLUMNS")) != NULL && *p != '\0')
563 termwidth = atoi(p);
564 else if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &wsz) != -1 &&
565 wsz.ws_col > 0)
566 termwidth = wsz.ws_col - 2;
567 }
568
569 ci = -1;
570 while ((c = getopt(argc, argv, "C:c:d:snw:")) != -1)
571 switch (c) {
572 case 'C':
573 column = strtol(optarg, &p, 10);
574 if (p != NULL && *p != '\0')
575 usage("Invalid column number.");
576 if (column <= 0)
577 usage("Column number should be positive.");
578 break;
579 case 'c':
580 a = strtod(optarg, &p);
581 if (p != NULL && *p != '\0')
582 usage("Not a floating point number");
583 for (i = 0; i < NCONF; i++)
584 if (a == studentpct[i])
585 ci = i;
586 if (ci == -1)
587 usage("No support for confidence level");
588 break;
589 case 'd':
590 if (*optarg == '\0')
591 usage("Can't use empty delimiter string");
592 delim = optarg;
593 break;
594 case 'n':
595 flag_n = 1;
596 break;
597 case 's':
598 flag_s = 1;
599 break;
600 case 'w':
601 termwidth = strtol(optarg, &p, 10);
602 if (p != NULL && *p != '\0')
603 usage("Invalid width, not a number.");
604 if (termwidth < 0)
605 usage("Unable to move beyond left margin.");
606 break;
607 default:
608 usage("Unknown option");
609 break;
610 }
611 if (ci == -1)
612 ci = 2;
613 argc -= optind;
614 argv += optind;
615
616 if (argc == 0) {
617 ds[0] = ReadSet("-", column, delim);
618 nds = 1;
619 } else {
620 if (argc > (MAX_DS - 1))
621 usage("Too many datasets.");
622 nds = argc;
623 for (i = 0; i < nds; i++)
624 ds[i] = ReadSet(argv[i], column, delim);
625 }
626
627 for (i = 0; i < nds; i++)
628 printf("%c %s\n", symbol[i+1], ds[i]->name);
629
630 if (!flag_n) {
631 SetupPlot(termwidth, flag_s, nds);
632 for (i = 0; i < nds; i++)
633 DimPlot(ds[i]);
634 for (i = 0; i < nds; i++)
635 PlotSet(ds[i], i + 1);
636 DumpPlot();
637 }
638 VitalsHead();
639 Vitals(ds[0], 1);
640 for (i = 1; i < nds; i++) {
641 Vitals(ds[i], i + 1);
642 if (!flag_n)
643 Relative(ds[i], ds[0], ci);
644 }
645 exit(0);
646}
551 char *p;
552 int c, i, ci;
553 int column = 1;
554 int flag_s = 0;
555 int flag_n = 0;
556 int termwidth = 74;
557
558 if (isatty(STDOUT_FILENO)) {
559 struct winsize wsz;
560
561 if ((p = getenv("COLUMNS")) != NULL && *p != '\0')
562 termwidth = atoi(p);
563 else if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &wsz) != -1 &&
564 wsz.ws_col > 0)
565 termwidth = wsz.ws_col - 2;
566 }
567
568 ci = -1;
569 while ((c = getopt(argc, argv, "C:c:d:snw:")) != -1)
570 switch (c) {
571 case 'C':
572 column = strtol(optarg, &p, 10);
573 if (p != NULL && *p != '\0')
574 usage("Invalid column number.");
575 if (column <= 0)
576 usage("Column number should be positive.");
577 break;
578 case 'c':
579 a = strtod(optarg, &p);
580 if (p != NULL && *p != '\0')
581 usage("Not a floating point number");
582 for (i = 0; i < NCONF; i++)
583 if (a == studentpct[i])
584 ci = i;
585 if (ci == -1)
586 usage("No support for confidence level");
587 break;
588 case 'd':
589 if (*optarg == '\0')
590 usage("Can't use empty delimiter string");
591 delim = optarg;
592 break;
593 case 'n':
594 flag_n = 1;
595 break;
596 case 's':
597 flag_s = 1;
598 break;
599 case 'w':
600 termwidth = strtol(optarg, &p, 10);
601 if (p != NULL && *p != '\0')
602 usage("Invalid width, not a number.");
603 if (termwidth < 0)
604 usage("Unable to move beyond left margin.");
605 break;
606 default:
607 usage("Unknown option");
608 break;
609 }
610 if (ci == -1)
611 ci = 2;
612 argc -= optind;
613 argv += optind;
614
615 if (argc == 0) {
616 ds[0] = ReadSet("-", column, delim);
617 nds = 1;
618 } else {
619 if (argc > (MAX_DS - 1))
620 usage("Too many datasets.");
621 nds = argc;
622 for (i = 0; i < nds; i++)
623 ds[i] = ReadSet(argv[i], column, delim);
624 }
625
626 for (i = 0; i < nds; i++)
627 printf("%c %s\n", symbol[i+1], ds[i]->name);
628
629 if (!flag_n) {
630 SetupPlot(termwidth, flag_s, nds);
631 for (i = 0; i < nds; i++)
632 DimPlot(ds[i]);
633 for (i = 0; i < nds; i++)
634 PlotSet(ds[i], i + 1);
635 DumpPlot();
636 }
637 VitalsHead();
638 Vitals(ds[0], 1);
639 for (i = 1; i < nds; i++) {
640 Vitals(ds[i], i + 1);
641 if (!flag_n)
642 Relative(ds[i], ds[0], ci);
643 }
644 exit(0);
645}