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