+Mon Apr 26 22:40:07 2004 Ben Pfaff <blp@gnu.org>
+
+ We're abusing the current ASCII driver by telling it to allocate a
+ 9999-line, 9999-character page in the tests. This causes some
+ systems to curl up and die because it allocates 20 MB of
+ contiguous RAM. This change alleviates at least part of the
+ problem. It is mostly a stop-gap until the new output system is
+ ready.
+
+ * ascii.c: (struct line) New structure.
+ (struct ascii_driver_ext) Remove `page', `page_size', `line_len',
+ `line_len_size', `n_output' members. Add `lines', `lines_cap'.
+ (ascii_preopen_driver) Initialize new members, not old ones.
+ (ascii_close_driver) Destroy new members, not old ones.
+ (ascii_open_page) Allocate new members, not old ones.
+ (expand_line) Allocate room in line.
+ (draw_line) Use new members.
+ (ascii_line_horz) Ditto.
+ (ascii_line_vert) Ditto.
+ (ascii_line_intersection) Ditto.
+ (text_draw) Ditto.
+ (output_lines) Ditto.
+ (ascii_close_page) Ditto.
+
+Sun Apr 25 23:40:15 2004 Ben Pfaff <blp@gnu.org>
+
+ * matrix.c: Dead code. Removed.
+
+ * matrix.h: Dead code. Removed.
+
Fri Apr 16 23:59:51 2004 Ben Pfaff <blp@gnu.org>
Contrary to what I'd always understood, there is an efficient
format.h formats.c get.c getline.c getline.h glob.c glob.h \
groff-font.c hash.c hash.h html.c htmlP.h include.c inpt-pgm.c lexer.c \
lexer.h levene.c levene.h log.h loop.c magic.c magic.h main.c main.h \
-matrix-data.c matrix.c matrix.h mis-val.c misc.c misc.h modify-vars.c \
+matrix-data.c mis-val.c misc.c misc.h modify-vars.c \
moments.c moments.h numeric.c output.c output.h pfm-read.c pfm-write.c \
pfm.h pool.c pool.h postscript.c print.c random.c random.h recode.c \
rename-vars.c repeat.c repeat.h sample.c sel-if.c settings.h \
FSTY_COUNT = 6 /* Number of font styles. */
};
+/* A line of text. */
+struct line
+ {
+ unsigned short *chars; /* Characters and attributes. */
+ int char_cnt; /* Length. */
+ int char_cap; /* Allocated bytes. */
+ };
+
/* ASCII output driver extension record. */
struct ascii_driver_ext
{
/* Internal state. */
struct file_ext file; /* Output file. */
int page_number; /* Current page number. */
- unsigned short *page; /* Page content. */
- int page_size; /* Number of bytes allocated for page, attr. */
- int *line_len; /* Length of each line in page, attr. */
- int line_len_size; /* Number of ints allocated for line_len. */
+ struct line *lines; /* Page content. */
+ int lines_cap; /* Number of lines allocated. */
int w, l; /* Actual width & length w/o margins, etc. */
- int n_output; /* Number of lines output so far. */
int cur_font; /* Current font by OUTP_F_*. */
#if GLOBAL_DEBUGGING
int debug; /* Set by som_text_draw(). */
x->file.postopen = postopen;
x->file.preclose = preclose;
x->page_number = 0;
- x->page = NULL;
- x->page_size = 0;
- x->line_len = NULL;
- x->line_len_size = 0;
- x->n_output = 0;
+ x->lines = NULL;
+ x->lines_cap = 0;
x->cur_font = OUTP_F_R;
#if GLOBAL_DEBUGGING
x->debug = 0;
msg (VM (2), _("%s: Beginning closing..."), this->name);
x = this->ext;
- free (x->page);
- free (x->line_len);
+ if (x->lines != NULL)
+ {
+ int line;
+
+ for (line = 0; line < x->lines_cap; line++)
+ free (x->lines[line].chars);
+ free (x->lines);
+ }
fn_close_ext (&x->file);
free (x->file.filename);
free (x);
ascii_open_page (struct outp_driver *this)
{
struct ascii_driver_ext *x = this->ext;
- int req_page_size;
+ int i;
assert (this->driver_open && !this->page_open);
x->page_number++;
return 0;
}
- req_page_size = x->w * x->l;
- if (req_page_size > x->page_size || req_page_size / 2 < x->page_size)
+ if (x->l > x->lines_cap)
{
- x->page_size = req_page_size;
- x->page = xrealloc (x->page, sizeof *x->page * req_page_size);
+ x->lines = xrealloc (x->lines, sizeof *x->lines * x->l);
+ for (i = x->lines_cap; i < x->l; i++)
+ {
+ struct line *line = &x->lines[i];
+ line->chars = NULL;
+ line->char_cap = 0;
+ }
+ x->lines_cap = x->l;
}
- if (x->l > x->line_len_size)
- {
- x->line_len_size = x->l;
- x->line_len = xrealloc (x->line_len,
- sizeof *x->line_len * x->line_len_size);
- }
-
- memset (x->line_len, 0, sizeof *x->line_len * x->l);
+ for (i = 0; i < x->l; i++)
+ x->lines[i].char_cnt = 0;
this->page_open = 1;
return 1;
static inline void
expand_line (struct ascii_driver_ext *x, int i, int l)
{
- int limit = i * x->w + l;
+ struct line *line;
int j;
- for (j = i * x->w + x->line_len[i]; j < limit; j++)
- x->page[j] = ' ';
- x->line_len[i] = l;
+ assert (i < x->lines_cap);
+ line = &x->lines[i];
+ if (l > line->char_cap)
+ {
+ line->char_cap = l * 2;
+ line->chars = xrealloc (line->chars,
+ line->char_cap * sizeof *line->chars);
+ }
+ for (j = line->char_cnt; j < l; j++)
+ line->chars[j] = ' ';
+ line->char_cnt = l;
}
/* Puts line L at (H,K) in the current output page. Assumes
struct ascii_driver_ext named `ext'. */
#define draw_line(H, K, L) \
- ext->page[ext->w * (K) + (H)] = (L) | 0x800
+ ext->lines[K].chars[H] = (L) | 0x800
/* Line styles for each position. */
#define T(STYLE) (STYLE<<LNS_TOP)
}
#endif
- if (ext->line_len[y1] < x2)
+ if (ext->lines[y1].char_cnt < x2)
expand_line (ext, y1, x2);
for (x = x1; x < x2; x++)
#endif
for (y = y1; y < y2; y++)
- if (ext->line_len[y] <= x1)
+ if (ext->lines[y].char_cnt <= x1)
expand_line (ext, y, x1 + 1);
for (y = y1; y < y2; y++)
l = ((style->l << LNS_LEFT) | (style->r << LNS_RIGHT)
| (style->t << LNS_TOP) | (style->b << LNS_BOTTOM));
- if (ext->line_len[y] <= x)
+ if (ext->lines[y].char_cnt <= x)
expand_line (ext, y, x + 1);
draw_line (x, y, l);
}
unsigned attr = ext->cur_font << 8;
int x = t->x;
- int y = t->y * ext->w;
+ int y = t->y;
char *s = ls_value (&t->s);
if (!(t->y < ext->l && x < ext->w))
return;
min_len = min (x + ls_length (&t->s), ext->w);
- if (ext->line_len[t->y] < min_len)
+ if (ext->lines[t->y].char_cnt < min_len)
expand_line (ext, t->y, min_len);
{
if (len + x > ext->w)
len = ext->w - x;
while (len--)
- ext->page[y + x++] = *s++ | attr;
+ ext->lines[y].chars[x++] = *s++ | attr;
}
}
\f
/* Iterate over all the lines to be output. */
for (line_num = first; line_num < first + count; line_num++)
{
- unsigned short *p = &ext->page[ext->w * line_num];
- unsigned short *end_p = p + ext->line_len[line_num];
+ struct line *line = &ext->lines[line_num];
+ unsigned short *p = line->chars;
+ unsigned short *end_p = p + line->char_cnt;
unsigned short *bp, *ep;
unsigned short attr = 0;
requested. */
if (ext->squeeze_blank_lines
&& line_num > first
- && ext->line_len[line_num] == 0
- && ext->line_len[line_num - 1] == 0)
+ && ext->lines[line_num].char_cnt == 0
+ && ext->lines[line_num - 1].char_cnt == 0)
continue;
/* Output every character in the line in the appropriate
if (line_p != line_buf && !commit_line_buf (this))
return 0;
- output_lines (this, x->n_output, x->l - x->n_output);
+ output_lines (this, 0, x->l);
ff_len = ls_length (&x->ops[OPS_FORMFEED]);
total_len = x->bottom_margin * nl_len + ff_len;
if (line_p != line_buf && !commit_line_buf (this))
return 0;
- x->n_output = 0;
-
this->page_open = 0;
return 1;
}
+++ /dev/null
-/* PSPP - computes sample statistics.
- Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
- Written by Ben Pfaff <blp@gnu.org>.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA. */
-
-#include <config.h>
-#include "matrix.h"
-#include "error.h"
-#include <stdlib.h>
-#include "alloc.h"
-\f
-/* Kahan summation formula, Thm. 8, _What Every Computer Scientist
- Should Know About Floating-Point Arithmetic_, David Goldberg,
- orig. March 1991 issue of Computing Surveys, also at
- <URL:http://www.wam.umd.edu/whats_new/workshop3.0/common-tools/numerical_comp_guide/goldberg1.doc.html>.
- Hopefully your compiler won't try to optimize the code below too
- much, because that will ruin the precision. */
-#define KAHAN_SUMMATION_FORMULA(S) \
- do \
- { \
- double S_c; \
- int S_j; \
- \
- S = SUMMATION_ELEMENT (0); \
- S_c = 0.; \
- for (S_j = 1; S_j < SUMMATION_COUNT; S_j++) \
- { \
- double S_y = SUMMATION_ELEMENT (S_j) - S_c; \
- double S_t = S + S_y; \
- S_c = (S_t - S) - S_y; \
- S = S_t; \
- } \
- } \
- while (0)
-
-\f
-/* Vectors. */
-
-/* Allocate a new vector of length N. */
-struct vector *
-vec_alloc (int n)
-{
- struct vector *vec = xmalloc (sizeof *vec);
- vec->data = xmalloc (sizeof *vec->data * n);
- vec->n = vec->m = n;
- return vec;
-}
-
-/* Change the length of VEC to N. The amount of space allocated will
- not be lowered, but may be enlarged. */
-void
-vec_realloc (struct vector *vec, int n)
-{
- if (n < vec->m)
- {
- vec->m = n;
- vec->data = xrealloc (vec->data, sizeof *vec->data * n);
- }
- vec->n = n;
-}
-
-/* Free vector VEC. */
-void
-vec_free (struct vector *vec)
-{
- free (vec->data);
- free (vec);
-}
-
-/* Set the values in vector VEC to constant VALUE. */
-#if 0
-void
-vec_init (struct vector *vec, double value)
-{
- double *p;
- int i;
-
- p = vec->data;
- for (i = 0; i < vec->n; i++)
- *p++ = value;
-}
-#endif
-
-/* Print out vector VEC to stdout for debugging purposes. */
-#if GLOBAL_DEBUGGING
-#include <stdio.h>
-#include "settings.h"
-
-void
-vec_print (const struct vector *vec)
-{
- int i;
-
- for (i = 0; i < vec->n; i++)
- {
- if (i % ((get_viewwidth() - 4) / 8) == 0)
- {
- if (i)
- putchar ('\n');
- printf ("%3d:", i);
- }
-
- printf ("%8g", vec_elem (vec, i));
- }
-}
-#endif
-
-/* Return the sum of the values in VEC. */
-double
-vec_total (const struct vector *vec)
-{
- double sum;
-
-#define SUMMATION_COUNT (vec->n)
-#define SUMMATION_ELEMENT(INDEX) (vec_elem (vec, (INDEX)))
- KAHAN_SUMMATION_FORMULA (sum);
-#undef SUMMATION_COUNT
-#undef SUMMATION_ELEMENT
-
- return sum;
-}
-\f
-/* Matrices. */
-
-/* Allocate a new matrix with NR rows and NC columns. */
-struct matrix *
-mat_alloc (int nr, int nc)
-{
- struct matrix *mat = xmalloc (sizeof *mat);
- mat->nr = nr;
- mat->nc = nc;
- mat->m = nr * nc;
- mat->data = xmalloc (sizeof *mat->data * nr * nc);
- return mat;
-}
-
-/* Set the size of matrix MAT to NR rows and NC columns. The matrix
- data array will be enlarged if necessary but will not be shrunk. */
-void
-mat_realloc (struct matrix *mat, int nr, int nc)
-{
- if (nc * nr > mat->m)
- {
- mat->m = nc * nr;
- mat->data = xrealloc (mat->data, sizeof *mat->data * mat->m);
- }
- mat->nr = nr;
- mat->nc = nc;
-}
-
-/* Free matrix MAT. */
-void
-mat_free (struct matrix *mat)
-{
- free (mat->data);
- free (mat);
-}
-
-/* Set all matrix MAT entries to VALUE. */
-void
-mat_init (struct matrix *mat, double value)
-{
- double *p;
- int i;
-
- p = mat->data;
- for (i = 0; i < mat->nr * mat->nc; i++)
- *p++ = value;
-}
-
-/* Set all MAT entries in row R to VALUE. */
-void
-mat_init_row (struct matrix *mat, int r, double value)
-{
- double *p;
- int i;
-
- p = &mat_elem (mat, r, 0);
- for (i = 0; i < mat->nc; i++)
- *p++ = value;
-}
-
-/* Set all MAT entries in column C to VALUE. */
-void
-mat_init_col (struct matrix *mat, int c, double value)
-{
- double *p;
- int i;
-
- p = &mat_elem (mat, 0, c);
- for (i = 0; i < mat->nr; i++)
- {
- *p = value;
- p += mat->nc;
- }
-}
-
-/* Print out MAT entries to stdout, optionally with row and column
- labels ROW_LABELS and COL_LABELS. */
-#if GLOBAL_DEBUGGING
-void
-mat_print (const struct matrix *mat,
- const struct vector *row_labels,
- const struct vector *col_labels)
-{
- int r, c;
-
- assert (!row_labels || row_labels->n == mat->nr);
- if (col_labels)
- {
- int c;
-
- assert (col_labels->n == mat->nc);
- if (row_labels)
- printf (" ");
- for (c = 0; c < mat->nc; c++)
- printf ("%8g", vec_elem (col_labels, c));
- }
-
- for (r = 0; r < mat->nr; r++)
- {
- if (row_labels)
- printf ("%8g:", vec_elem (row_labels, r));
- for (c = 0; c < mat->nc; c++)
- printf ("%8g", mat_elem (mat, r, c));
- putchar ('\n');
- }
-}
-#endif /* GLOBAL_DEBUGGING */
-
-/* Calculate row totals for matrix MAT into vector ROW_TOTS. */
-void
-mat_row_totals (const struct matrix *mat, struct vector *row_tots)
-{
- int r;
-
- vec_realloc (row_tots, mat->nr);
- for (r = 0; r < mat->nr; r++)
- {
- double sum;
-
-#define SUMMATION_COUNT (mat->nc)
-#define SUMMATION_ELEMENT(INDEX) (mat_elem (mat, r, INDEX))
- KAHAN_SUMMATION_FORMULA (sum);
-#undef SUMMATION_COUNT
-#undef SUMMATION_ELEMENT
-
- vec_elem (row_tots, r) = sum;
- }
-}
-
-/* Calculate column totals for matrix MAT into vector COL_TOTS. */
-void
-mat_col_totals (const struct matrix *mat, struct vector *col_tots)
-{
- int c;
-
- vec_realloc (col_tots, mat->nc);
- for (c = 0; c < mat->nc; c++)
- {
- double sum;
-
-#define SUMMATION_COUNT (mat->nr)
-#define SUMMATION_ELEMENT(INDEX) (mat_elem (mat, INDEX, c))
- KAHAN_SUMMATION_FORMULA (sum);
-#undef SUMMATION_COUNT
-#undef SUMMATION_ELEMENT
-
- vec_elem (col_tots, c) = sum;
- }
-}
-
-/* Return the grand total for matrix MAT. Of course, if you're also
- calculating column or row totals, it would be faster to use
- vec_total on one of those sets of totals. */
-double
-mat_grand_total (const struct matrix *mat)
-{
- double sum;
-
-#define SUMMATION_COUNT (mat->nr * mat->nc)
-#define SUMMATION_ELEMENT(INDEX) (mat->data[INDEX])
- KAHAN_SUMMATION_FORMULA (sum);
-#undef SUMMATION_COUNT
-#undef SUMMATION_ELEMENT
-
- return sum;
-}
+++ /dev/null
-/* PSPP - computes sample statistics.
- Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
- Written by Ben Pfaff <blp@gnu.org>.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA. */
-
-#if !matrix_h
-#define matrix_h 1
-\f
-/* Vector representation. */
-struct vector
- {
- int n;
- int m;
- double *data;
- };
-
-/* Allocate vectors. */
-struct vector *vec_alloc (int n);
-void vec_realloc (struct vector *, int n);
-void vec_free (struct vector *);
-
-/* Vector elements. */
-#define vec_elem(VEC, INDEX) ((VEC)->data[INDEX])
-
-/* Set the vector to a constant value. */
-void vec_init (struct vector *, double);
-
-/* Print out the vector to stdout. */
-#if GLOBAL_DEBUGGING
-void vec_print (const struct vector *);
-#endif
-
-/* Sum the vector values. */
-double vec_total (const struct vector *);
-\f
-/* Matrix representation. */
-struct matrix
- {
- int nr, nc;
- int m;
- double *data;
- };
-
-/* Allocate matrices. */
-struct matrix *mat_alloc (int nr, int nc);
-void mat_realloc (struct matrix *, int nr, int nc);
-void mat_free (struct matrix *);
-
-/* Matrix elements. */
-#define mat_elem(MAT, R, C) ((MAT)->data[(C) + (R) * (MAT)->nc])
-
-/* Set matrix values to a constant. */
-void mat_init (struct matrix *, double);
-void mat_init_row (struct matrix *, int r, double);
-void mat_init_col (struct matrix *, int c, double);
-
-/* Print out the matrix values to stdout, optionally with row and
- column labels (for debugging purposes). */
-#if GLOBAL_DEBUGGING
-void mat_print (const struct matrix *,
- const struct vector *row_labels, const struct vector *col_labels);
-#endif
-
-/* Sum matrix values. */
-void mat_row_totals (const struct matrix *, struct vector *row_tots);
-void mat_col_totals (const struct matrix *, struct vector *col_tots);
-double mat_grand_total (const struct matrix *);
-
-/* Chi-square statistics. */
-enum
- {
- CHISQ_PEARSON,
- CHISQ_LIKELIHOOD_RATIO,
- CHISQ_FISHER,
- CHISQ_CC,
- CHISQ_LINEAR,
- N_CHISQ
- };
-
-void mat_chisq (const struct matrix *, double chisq[N_CHISQ], int df[N_CHISQ]);
-
-#endif /* matrix_h */