-\f
-#if 0
-/* Statistical calculation. */
-
-static int degree[6];
-static int maxdegree, minmax;
-
-static void stat_func (struct freq *, VISIT, int);
-static void calc_stats (int);
-static void display_stats (int);
-
-/* mapping of data[]:
- * 0=>8
- * 1=>9
- * 2=>10
- * index 3: number of modes found (detects multiple modes)
- * index 4: number of nodes processed, for calculation of median
- * 5=>11
- *
- * mapping of dbl[]:
- * index 0-3: sum of X**i
- * index 4: minimum
- * index 5: maximum
- * index 6: mode
- * index 7: median
- * index 8: number of cases, valid and missing
- * index 9: number of valid cases
- * index 10: maximum frequency found, for calculation of mode
- * index 11: maximum frequency
- */
-static void
-out_stats (int i)
-{
- int j;
-
- if (cur_var->type == ALPHA)
- return;
- for (j = 0; j < 8; j++)
- cur_var->dbl[j] = 0.;
- cur_var->dbl[10] = 0;
- cur_var->dbl[4] = DBL_MAX;
- cur_var->dbl[5] = -DBL_MAX;
- for (j = 2; j < 5; j++)
- cur_var->data[j] = 0;
- cur_var->p.frq.median_ncases = cur_var->p.frq.t.valid_cases / 2;
- avlwalk (cur_var->p.frq.t.f, stat_func, LEFT_TO_RIGHT);
- calc_stats (i);
- display_stats (i);
-}
-
-static void
-calc_stats (int i)
-{
- struct variable *v;
- double n;
- double *d;
-
- v = v_variables[i];
- n = v->p.frq.t.valid_cases;
- d = v->dbl;
-
- if (n < 2 || (n < 3 && stat[FRQ_ST_7]))
- {
- warn (_("only %g case%s for variable %s, statistics not "
- "computed"), n, n == 1 ? "" : "s", v->name);
- return;
- }
- if (stat[FRQ_ST_9])
- v->res[FRQ_ST_9] = d[5] - d[4];
- if (stat[FRQ_ST_10])
- v->res[FRQ_ST_10] = d[4];
- if (stat[FRQ_ST_11])
- v->res[FRQ_ST_11] = d[5];
- if (stat[FRQ_ST_12])
- v->res[FRQ_ST_12] = d[0];
- if (stat[FRQ_ST_1] || stat[FRQ_ST_2] || stat[FRQ_ST_5] || stat[FRQ_ST_6] || stat[FRQ_ST_7])
- {
- v->res[FRQ_ST_1] = calc_mean (d, n);
- v->res[FRQ_ST_6] = calc_variance (d, n);
- }
- if (stat[FRQ_ST_2] || stat[FRQ_ST_5] || stat[FRQ_ST_7])
- v->res[FRQ_ST_5] = calc_stddev (v->res[FRQ_ST_6]);
- if (stat[FRQ_ST_2])
- v->res[FRQ_ST_2] = calc_semean (v->res[FRQ_ST_5], n);
- if (stat[FRQ_ST_7])
- {
- v->res[FRQ_ST_7] = calc_kurt (d, n, v->res[FRQ_ST_6]);
- v->res[FRQ_ST_14] = calc_sekurt (n);
- }
- if (stat[FRQ_ST_8])
- {
- v->res[FRQ_ST_8] = calc_skew (d, n, v->res[FRQ_ST_5]);
- v->res[FRQ_ST_15] = calc_seskew (n);
- }
- if (stat[FRQ_ST_MODE])
- {
- v->res[FRQ_ST_MODE] = v->dbl[6];
- if (v->data[3] > 1)
- warn (_("The variable %s has %d modes. The lowest of these "
- "is the one given in the table."), v->name, v->data[3]);
- }
- if (stat[FRQ_ST_MEDIAN])
- v->res[FRQ_ST_MEDIAN] = v->dbl[7];
-}
-
-static void
-stat_func (struct freq * x, VISIT order, int param)
-{
- double d, f;
-
- if (order != INORDER)
- return;
- f = d = x->v.f;
- cur_var->dbl[0] += (d * x->c);
- switch (maxdegree)
- {
- case 1:
- f *= d;
- cur_var->dbl[1] += (f * x->c);
- break;
- case 2:
- f *= d;
- cur_var->dbl[1] += (f * x->c);
- f *= d;
- cur_var->dbl[2] += (f * x->c);
- break;
- case 3:
- f *= d;
- cur_var->dbl[1] += (f * x->c);
- f *= d;
- cur_var->dbl[2] += (f * x->c);
- f *= d;
- cur_var->dbl[3] += (f * x->c);
- break;
- }
- if (minmax)
- {
- if (d < cur_var->dbl[4])
- cur_var->dbl[4] = d;
- if (d > cur_var->dbl[5])
- cur_var->dbl[5] = d;
- }
- if (x->c > cur_var->dbl[10])
- {
- cur_var->data[3] = 1;
- cur_var->dbl[10] = x->c;
- cur_var->dbl[6] = x->v.f;
- }
- else if (x->c == cur_var->dbl[10])
- cur_var->data[3]++;
- if (cur_var->data[4] < cur_var->p.frq.median_ncases
- && cur_var->data[4] + x->c >= cur_var->p.frq.median_ncases)
- cur_var->dbl[7] = x->v.f;
- cur_var->data[4] += x->c;
-}
-\f
-/* Statistical display. */
-static int column, ncolumns;
-
-static void outstat (char *, double);
-
-static void
-display_stats (int i)
-{
- statname *sp;
- struct variable *v;
- int nlines;
-
- v = v_variables[i];
- ncolumns = (margin_width + 3) / 26;
- if (ncolumns < 1)
- ncolumns = 1;
- nlines = sc / ncolumns + (sc % ncolumns > 0);
- if (nlines == 2 && sc == 4)
- ncolumns = 2;
- if (nlines == 3 && sc == 9)
- ncolumns = 3;
- if (nlines == 4 && sc == 12)
- ncolumns = 3;
- column = 0;
- for (sp = st_name; sp->s != -1; sp++)
- if (stat[sp->s] == 1)
- outstat (gettext (sp->s10), v->res[sp->s]);
- if (column)
- out_eol ();
- blank_line ();
-}
-
-static void
-outstat (char *label, double value)
-{
- char buf[128], *cp;
- int dw, n;
-
- cp = &buf[0];
- if (!column)
- out_header ();
- else
- {
- memset (buf, ' ', 3);
- cp = &buf[3];
- }
- dw = 4;
- n = nsprintf (cp, "%-10s %12.4f", label, value);
- while (n > 23 && dw > 0)
- n = nsprintf (cp, "%-10s %12.*f", label, --dw, value);
- outs (buf);
- column++;
- if (column == ncolumns)
- {
- column = 0;
- out_eol ();
- }
-}
-\f
-/* Graphs. */
-
-static rect pb, gb; /* Page border, graph border. */
-static int px, py; /* Page width, height. */
-static int ix, iy; /* Inch width, height. */
-
-static void draw_bar_chart (int);
-static void draw_histogram (int);
-static int scale_dep_axis (int);
-
-static void
-out_graphs (int i)
-{
- struct variable *v;
-
- v = v_variables[i];
- if (avlcount (cur_var->p.frq.t.f) < 2
- || (chart == HIST && v_variables[i]->type == ALPHA))
- return;
- if (driver_id && set_highres == 1)
- {
- char *text;
-
- graf_page_size (&px, &py, &ix, &iy);
- graf_feed_page ();
-
- /* Calculate borders. */
- pb.x1 = ix;
- pb.y1 = iy;
- pb.x2 = px - ix;
- pb.y2 = py - iy;
- gb.x1 = pb.x1 + ix;
- gb.y1 = pb.y1 + iy;
- gb.x2 = pb.x2 - ix / 2;
- gb.y2 = pb.y2 - iy;
-
- /* Draw borders. */
- graf_frame_rect (COMPONENTS (pb));
- graf_frame_rect (COMPONENTS (gb));
-
- /* Draw axis labels. */
- graf_font_size (iy / 4); /* 18-point text */
- text = format == PERCENT ? _("Percentage") : _("Frequency");
- graf_text (pb.x1 + max (ix, iy) / 4 + max (ix, iy) / 16, gb.y2, text,
- SIDEWAYS);
- text = v->label ? v->label : v->name;
- graf_text (gb.x1, pb.y2 - iy / 4, text, UPRIGHT);
-
- /* Draw axes, chart proper. */
- if (chart == BAR ||
- (chart == HBAR
- && (avlcount (cur_var->p.frq.t.f) || v_variables[i]->type == ALPHA)))
- draw_bar_chart (i);
- else
- draw_histogram (i);
-
- graf_eject_page ();
- }
- if (set_lowres == 1 || (set_lowres == 2 && (!driver_id || !set_highres)))
- {
- static warned;
-
- /* Do character-based graphs. */
- if (!warned)
- {
- warn (_("low-res graphs not implemented"));
- warned = 1;
- }
- }
-}
-
-#if __GNUC__ && !__CHECKER__
-#define BIG_TYPE long long
-#else /* !__GNUC__ */
-#define BIG_TYPE double
-#endif /* !__GNUC__ */
-
-static void
-draw_bar_chart (int i)
-{
- int bar_width, bar_spacing;
- int w, max, row;
- double val;
- struct freq *f;
- rect r;
- AVLtraverser *t = NULL;
-
- w = (px - ix * 7 / 2) / avlcount (cur_var->p.frq.t.f);
- bar_width = w * 2 / 3;
- bar_spacing = w - bar_width;
-
-#if !ALLOW_HUGE_BARS
- if (bar_width > ix / 2)
- bar_width = ix / 2;
-#endif /* !ALLOW_HUGE_BARS */
-
- max = scale_dep_axis (cur_var->p.frq.t.max_freq);
-
- row = 0;
- r.x1 = gb.x1 + bar_spacing / 2;
- r.x2 = r.x1 + bar_width;
- r.y2 = gb.y2;
- graf_fill_color (255, 0, 0);
- for (f = avltrav (cur_var->p.frq.t.f, &t); f;
- f = avltrav (cur_var->p.frq.t.f, &t))
- {
- char buf2[64];
- char *buf;
-
- val = f->c;
- if (format == PERCENT)
- val = val * 100 / cur_var->p.frq.t.valid_cases;
- r.y1 = r.y2 - val * (height (gb) - 1) / max;
- graf_fill_rect (COMPONENTS (r));
- graf_frame_rect (COMPONENTS (r));
- buf = get_val_lab (cur_var, f->v, 0);
- if (!buf)
- if (cur_var->type == ALPHA)
- buf = f->v.s;
- else
- {
- sprintf (buf2, "%g", f->v.f);
- buf = buf2;
- }
- graf_text (r.x1 + bar_width / 2,
- gb.y2 + iy / 32 + row * iy / 9, buf, TCJUST);
- row ^= 1;
- r.x1 += bar_width + bar_spacing;
- r.x2 += bar_width + bar_spacing;
- }
- graf_fill_color (0, 0, 0);
-}
-
-#define round_down(X, V) \
- (floor ((X) / (V)) * (V))
-#define round_up(X, V) \
- (ceil ((X) / (V)) * (V))
-
-static void
-draw_histogram (int i)
-{
- double lower, upper, interval;
- int bars[MAX_HIST_BARS + 1], top, j;
- int err, addend, rem, nbars, row, max_freq;
- char buf[25];
- rect r;
- struct freq *f;
- AVLtraverser *t = NULL;
-
- lower = min == SYSMIS ? cur_var->dbl[4] : min;
- upper = max == SYSMIS ? cur_var->dbl[5] : max;
- if (upper - lower >= 10)
- {
- double l, u;
-
- u = round_up (upper, 5);
- l = round_down (lower, 5);
- nbars = (u - l) / 5;
- if (nbars * 2 + 1 <= MAX_HIST_BARS)
- {
- nbars *= 2;
- u = round_up (upper, 2.5);
- l = round_down (lower, 2.5);
- if (l + 1.25 <= lower && u - 1.25 >= upper)
- nbars--, lower = l + 1.25, upper = u - 1.25;
- else if (l + 1.25 <= lower)
- lower = l + 1.25, upper = u + 1.25;
- else if (u - 1.25 >= upper)
- lower = l - 1.25, upper = u - 1.25;
- else
- nbars++, lower = l - 1.25, upper = u + 1.25;
- }
- else if (nbars < MAX_HIST_BARS)
- {
- if (l + 2.5 <= lower && u - 2.5 >= upper)
- nbars--, lower = l + 2.5, upper = u - 2.5;
- else if (l + 2.5 <= lower)
- lower = l + 2.5, upper = u + 2.5;
- else if (u - 2.5 >= upper)
- lower = l - 2.5, upper = u - 2.5;
- else
- nbars++, lower = l - 2.5, upper = u + 2.5;
- }
- else
- nbars = MAX_HIST_BARS;
- }
- else
- {
- nbars = avlcount (cur_var->p.frq.t.f);
- if (nbars > MAX_HIST_BARS)
- nbars = MAX_HIST_BARS;
- }
- if (nbars < MIN_HIST_BARS)
- nbars = MIN_HIST_BARS;
- interval = (upper - lower) / nbars;
-
- memset (bars, 0, sizeof (int[nbars + 1]));
- if (lower >= upper)
- {
- msg (SE, _("Could not make histogram for %s for specified "
- "minimum %g and maximum %g; please discard graph."), cur_var->name,
- lower, upper);
- return;
- }
- for (f = avltrav (cur_var->p.frq.t.f, &t); f;
- f = avltrav (cur_var->p.frq.t.f, &t))
- if (f->v.f == upper)
- bars[nbars - 1] += f->c;
- else if (f->v.f >= lower && f->v.f < upper)
- bars[(int) ((f->v.f - lower) / interval)] += f->c;
- bars[nbars - 1] += bars[nbars];
- for (j = top = 0; j < nbars; j++)
- if (bars[j] > top)
- top = bars[j];
- max_freq = top;
- top = scale_dep_axis (top);
-
- err = row = 0;
- addend = width (gb) / nbars;
- rem = width (gb) % nbars;
- r.x1 = gb.x1;
- r.x2 = r.x1 + addend;
- r.y2 = gb.y2;
- err += rem;
- graf_fill_color (255, 0, 0);
- for (j = 0; j < nbars; j++)
- {
- int w;
-
- r.y1 = r.y2 - (BIG_TYPE) bars[j] * (height (gb) - 1) / top;
- graf_fill_rect (COMPONENTS (r));
- graf_frame_rect (COMPONENTS (r));
- sprintf (buf, "%g", lower + interval / 2 + interval * j);
- graf_text (r.x1 + addend / 2,
- gb.y2 + iy / 32 + row * iy / 9, buf, TCJUST);
- row ^= 1;
- w = addend;
- err += rem;
- while (err >= addend)
- {
- w++;
- err -= addend;
- }
- r.x1 = r.x2;
- r.x2 = r.x1 + w;
- }
- if (normal)
- {
- double x, y, variance, mean, step, factor;
-
- variance = cur_var->res[FRQ_ST_VARIANCE];
- mean = cur_var->res[FRQ_ST_MEAN];
- factor = (1. / (sqrt (2. * PI * variance))
- * cur_var->p.frq.t.valid_cases * interval);
- graf_polyline_begin ();
- for (x = lower, step = (upper - lower) / (POLYLINE_DENSITY);
- x <= upper; x += step)
- {
- y = factor * exp (-square (x - mean) / (2. * variance));
- debug_printf (("(%20.10f, %20.10f)\n", x, y));
- graf_polyline_point (gb.x1 + (x - lower) / (upper - lower) * width (gb),
- gb.y2 - y * (height (gb) - 1) / top);
- }
- graf_polyline_end ();
- }
- graf_fill_color (0, 0, 0);
-}
-
-static int
-scale_dep_axis (int max)
-{
- int j, s, x, y, ty, by;
- char buf[10];
-
- x = 10, s = 2;
- if (scale != SYSMIS && max < scale)
- x = scale, s = scale / 5;
- else if (format == PERCENT)
- {
- max = ((BIG_TYPE) 100 * cur_var->p.frq.t.max_freq
- / cur_var->p.frq.t.valid_cases + 1);
- if (max < 5)
- x = 5, s = 1;
- else if (max < 10)
- x = 10, s = 2;
- else if (max < 25)
- x = 25, s = 5;
- else if (max < 50)
- x = 50, s = 10;
- else
- max = 100, s = 20;
- }
- else /* format==FREQ */
- /* Uses a progression of 10, 20, 50, 100, 200, 500, ... */
- for (;;)
- {
- if (x > max)
- break;
- x *= 2;
- s *= 2;
- if (x > max)
- break;
- x = x / 2 * 5;
- s = s / 2 * 5;
- if (x > max)
- break;
- x *= 2;
- s *= 2;
- }
- graf_font_size (iy / 9); /* 8-pt text */
- for (j = 0; j <= x; j += s)
- {
- y = gb.y2 - (BIG_TYPE) j *(height (gb) - 1) / x;
- ty = y - iy / 64;
- by = y + iy / 64;
- if (ty < gb.y1)
- ty += iy / 64, by += iy / 64;
- else if (by > gb.y2)
- ty -= iy / 64, by -= iy / 64;
- graf_fill_rect (gb.x1 - ix / 16, ty, gb.x1, by);
- sprintf (buf, "%d", j);
- graf_text (gb.x1 - ix / 8, (ty + by) / 2, buf, CRJUST);
- }
- return x;
-}
-\f
-/* Percentiles. */
-
-static void ungrouped_pcnt (int i);
-static int grouped_interval_pcnt (int i);
-static void out_pcnt (double, double);
-
-static void
-out_percentiles (int i)
-{
- if (cur_var->type == ALPHA || !n_percentiles)
- return;
-
- outs_line (_("Percentile Value "
- "Percentile Value "
- "Percentile Value"));
- blank_line ();
-
- column = 0;
- if (!g_var[i])
- ungrouped_pcnt (i);
- else if (g_var[i] == 1)
- grouped_interval_pcnt (i);
-#if 0
- else if (g_var[i] == -1)
- grouped_pcnt (i);
- else
- grouped_boundaries_pcnt (i);
-#else /* !0 */
- else
- warn (_("this form of percentiles not supported"));
-#endif
- if (column)
- out_eol ();
-}
-
-static void
-out_pcnt (double pcnt, double value)
-{
- if (!column)
- out_header ();
- else
- outs (" ");
- out ("%7.2f%13.3f", pcnt * 100., value);
- column++;
- if (column == 3)
- {
- out_eol ();
- column = 0;
- }
-}
-
-static void
-ungrouped_pcnt (int i)
-{
- AVLtraverser *t = NULL;
- struct freq *f;
- double *p, *e;
- int sum;
-
- p = percentiles;
- e = &percentiles[n_percentiles];
- sum = 0;
- for (f = avltrav (cur_var->p.frq.t.f, &t);
- f && p < e; f = avltrav (cur_var->p.frq.t.f, &t))
- {
- sum += f->c;
- while (sum >= p[0] * cur_var->p.frq.t.valid_cases && p < e)
- out_pcnt (*p++, f->v.f);
- }
-}
-
-
-static int
-grouped_interval_pcnt (int i)
-{
- AVLtraverser * t = NULL;
- struct freq * f, *fp;
- double *p, *e, w;
- int sum, psum;
-
- p = percentiles;
- e = &percentiles[n_percentiles];
- w = gl_var[i][0];
- sum = psum = 0;
- for (fp = 0, f = avltrav (cur_var->p.frq.t.f, &t);
- f && p < e;
- fp = f, f = avltrav (cur_var->p.frq.t.f, &t))
- {
- if (fp)
- if (fabs (f->v.f - fp->v.f) < w)
- {
- out_eol ();
- column = 0;
- return msg (SE, _("Difference between %g and %g is "
- "too small for grouping interval %g."), f->v.f,
- fp->v.f, w);
- }
- psum = sum;
- sum += f->c;
- while (sum >= p[0] * cur_var->p.frq.t.valid_cases && p < e)
- {
- out_pcnt (p[0], (((p[0] * cur_var->p.frq.t.valid_cases) - psum) * w / f->c
- + (f->v.f - w / 2)));
- p++;
- }
- }
- return 1;
-}
-#endif
-