-#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;