From f1c9e6126217fbb47aefa3f6360cafb3e15976e1 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Tue, 27 Apr 2004 05:54:31 +0000 Subject: [PATCH] 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. Also, get rid of unused matrix.[ch]. --- src/ChangeLog | 30 +++++ src/Makefile.am | 2 +- src/ascii.c | 100 +++++++++------- src/matrix.c | 302 ------------------------------------------------ src/matrix.h | 96 --------------- 5 files changed, 88 insertions(+), 442 deletions(-) delete mode 100644 src/matrix.c delete mode 100644 src/matrix.h diff --git a/src/ChangeLog b/src/ChangeLog index a9112641a8..9691ad7c7c 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,33 @@ +Mon Apr 26 22:40:07 2004 Ben Pfaff + + 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 + + * matrix.c: Dead code. Removed. + + * matrix.h: Dead code. Removed. + Fri Apr 16 23:59:51 2004 Ben Pfaff Contrary to what I'd always understood, there is an efficient diff --git a/src/Makefile.am b/src/Makefile.am index 80195782e9..b96d96e842 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -60,7 +60,7 @@ file-type.c filename.c filename.h flip.c font.h format.c format.def \ 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 \ diff --git a/src/ascii.c b/src/ascii.c index 9c0103e0c5..bdaac41056 100644 --- a/src/ascii.c +++ b/src/ascii.c @@ -141,6 +141,14 @@ enum 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 { @@ -167,12 +175,9 @@ 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(). */ @@ -246,11 +251,8 @@ ascii_preopen_driver (struct outp_driver *this) 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; @@ -392,8 +394,14 @@ ascii_close_driver (struct outp_driver *this) 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); @@ -679,7 +687,7 @@ static int 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++; @@ -690,21 +698,20 @@ ascii_open_page (struct outp_driver *this) 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; @@ -715,18 +722,26 @@ ascii_open_page (struct outp_driver *this) 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<line_len[y1] < x2) + if (ext->lines[y1].char_cnt < x2) expand_line (ext, y1, x2); for (x = x1; x < x2; x++) @@ -796,7 +811,7 @@ ascii_line_vert (struct outp_driver *this, const struct rect *r, #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++) @@ -828,7 +843,7 @@ ascii_line_intersection (struct outp_driver *this, const struct rect *r, 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); } @@ -1086,7 +1101,7 @@ text_draw (struct outp_driver *this, struct outp_text *t) 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); @@ -1111,7 +1126,7 @@ text_draw (struct outp_driver *this, struct outp_text *t) 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); { @@ -1120,7 +1135,7 @@ text_draw (struct outp_driver *this, struct outp_text *t) if (len + x > ext->w) len = ext->w - x; while (len--) - ext->page[y + x++] = *s++ | attr; + ext->lines[y].chars[x++] = *s++ | attr; } } @@ -1356,8 +1371,9 @@ output_lines (struct outp_driver *this, int first, int count) /* 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; @@ -1367,8 +1383,8 @@ output_lines (struct outp_driver *this, int first, int count) 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 @@ -1576,7 +1592,7 @@ ascii_close_page (struct outp_driver *this) 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; @@ -1593,8 +1609,6 @@ ascii_close_page (struct outp_driver *this) if (line_p != line_buf && !commit_line_buf (this)) return 0; - x->n_output = 0; - this->page_open = 0; return 1; } diff --git a/src/matrix.c b/src/matrix.c deleted file mode 100644 index 4631e7d809..0000000000 --- a/src/matrix.c +++ /dev/null @@ -1,302 +0,0 @@ -/* PSPP - computes sample statistics. - Copyright (C) 1997-9, 2000 Free Software Foundation, Inc. - Written by Ben Pfaff . - - 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 -#include "matrix.h" -#include "error.h" -#include -#include "alloc.h" - -/* 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 - . - 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) - - -/* 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 -#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; -} - -/* 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; -} diff --git a/src/matrix.h b/src/matrix.h deleted file mode 100644 index c1e5c612c9..0000000000 --- a/src/matrix.h +++ /dev/null @@ -1,96 +0,0 @@ -/* PSPP - computes sample statistics. - Copyright (C) 1997-9, 2000 Free Software Foundation, Inc. - Written by Ben Pfaff . - - 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 - -/* 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 *); - -/* 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 */ -- 2.30.2