00001
00002
00003
00004
00005
00006
00007 #include <stdio.h>
00008 #include "sparse_int.h"
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifdef FAST_AND_LOOSE
00018 sm_element *sm_element_freelist;
00019 sm_row *sm_row_freelist;
00020 sm_col *sm_col_freelist;
00021 #endif
00022
00023 sm_matrix *
00024 sm_allocate(void)
00025 {
00026 register sm_matrix *A;
00027
00028 A = ALLOC(sm_matrix, 1);
00029 A->rows = NIL(sm_row *);
00030 A->cols = NIL(sm_col *);
00031 A->nrows = A->ncols = 0;
00032 A->rows_size = A->cols_size = 0;
00033 A->first_row = A->last_row = NIL(sm_row);
00034 A->first_col = A->last_col = NIL(sm_col);
00035 A->user_word = NIL(char);
00036 return A;
00037 }
00038
00039
00040 sm_matrix *
00041 sm_alloc_size(int row, int col)
00042 {
00043 register sm_matrix *A;
00044
00045 A = sm_alloc();
00046 sm_resize(A, row, col);
00047 return A;
00048 }
00049
00050
00051 void
00052 sm_free_space(sm_matrix *A)
00053 {
00054 #ifdef FAST_AND_LOOSE
00055 register sm_row *prow;
00056
00057 if (A->first_row != 0) {
00058 for(prow = A->first_row; prow != 0; prow = prow->next_row) {
00059
00060 prow->last_col->next_col = sm_element_freelist;
00061 sm_element_freelist = prow->first_col;
00062 }
00063
00064
00065 A->last_row->next_row = sm_row_freelist;
00066 sm_row_freelist = A->first_row;
00067
00068
00069 A->last_col->next_col = sm_col_freelist;
00070 sm_col_freelist = A->first_col;
00071 }
00072 #else
00073 register sm_row *prow, *pnext_row;
00074 register sm_col *pcol, *pnext_col;
00075
00076 for(prow = A->first_row; prow != 0; prow = pnext_row) {
00077 pnext_row = prow->next_row;
00078 sm_row_free(prow);
00079 }
00080 for(pcol = A->first_col; pcol != 0; pcol = pnext_col) {
00081 pnext_col = pcol->next_col;
00082 pcol->first_row = pcol->last_row = NIL(sm_element);
00083 sm_col_free(pcol);
00084 }
00085 #endif
00086
00087
00088 FREE(A->rows);
00089 FREE(A->cols);
00090 FREE(A);
00091 }
00092
00093
00094 sm_matrix *
00095 sm_dup(sm_matrix *A)
00096 {
00097 register sm_row *prow;
00098 register sm_element *p;
00099 register sm_matrix *B;
00100
00101 B = sm_alloc();
00102 if (A->last_row != 0) {
00103 sm_resize(B, A->last_row->row_num, A->last_col->col_num);
00104 for(prow = A->first_row; prow != 0; prow = prow->next_row) {
00105 for(p = prow->first_col; p != 0; p = p->next_col) {
00106 (void) sm_insert(B, p->row_num, p->col_num);
00107 }
00108 }
00109 }
00110 return B;
00111 }
00112
00113
00114 void
00115 sm_resize(sm_matrix *A, int row, int col)
00116 {
00117 register int i, new_size;
00118
00119 if (row >= A->rows_size) {
00120 new_size = MAX(A->rows_size*2, row+1);
00121 A->rows = REALLOC(sm_row *, A->rows, new_size);
00122 for(i = A->rows_size; i < new_size; i++) {
00123 A->rows[i] = NIL(sm_row);
00124 }
00125 A->rows_size = new_size;
00126 }
00127
00128 if (col >= A->cols_size) {
00129 new_size = MAX(A->cols_size*2, col+1);
00130 A->cols = REALLOC(sm_col *, A->cols, new_size);
00131 for(i = A->cols_size; i < new_size; i++) {
00132 A->cols[i] = NIL(sm_col);
00133 }
00134 A->cols_size = new_size;
00135 }
00136 }
00137
00138
00139
00140
00141
00142 sm_element *
00143 sm_insert(sm_matrix *A, int row, int col)
00144 {
00145 register sm_row *prow;
00146 register sm_col *pcol;
00147 register sm_element *element;
00148 sm_element *save_element;
00149
00150 if (row >= A->rows_size || col >= A->cols_size) {
00151 sm_resize(A, row, col);
00152 }
00153
00154 prow = A->rows[row];
00155 if (prow == NIL(sm_row)) {
00156 prow = A->rows[row] = sm_row_alloc();
00157 prow->row_num = row;
00158 sorted_insert(sm_row, A->first_row, A->last_row, A->nrows,
00159 next_row, prev_row, row_num, row, prow);
00160 }
00161
00162 pcol = A->cols[col];
00163 if (pcol == NIL(sm_col)) {
00164 pcol = A->cols[col] = sm_col_alloc();
00165 pcol->col_num = col;
00166 sorted_insert(sm_col, A->first_col, A->last_col, A->ncols,
00167 next_col, prev_col, col_num, col, pcol);
00168 }
00169
00170
00171 sm_element_alloc(element);
00172 save_element = element;
00173
00174
00175 sorted_insert(sm_element, prow->first_col, prow->last_col,
00176 prow->length, next_col, prev_col, col_num, col, element);
00177
00178
00179 if (element == save_element) {
00180 sorted_insert(sm_element, pcol->first_row, pcol->last_row,
00181 pcol->length, next_row, prev_row, row_num, row, element);
00182 } else {
00183
00184 sm_element_free(save_element);
00185 }
00186 return element;
00187 }
00188
00189
00190 sm_element *
00191 sm_find(sm_matrix *A, int rownum, int colnum)
00192 {
00193 sm_row *prow;
00194 sm_col *pcol;
00195
00196 prow = sm_get_row(A, rownum);
00197 if (prow == NIL(sm_row)) {
00198 return NIL(sm_element);
00199 } else {
00200 pcol = sm_get_col(A, colnum);
00201 if (pcol == NIL(sm_col)) {
00202 return NIL(sm_element);
00203 }
00204 if (prow->length < pcol->length) {
00205 return sm_row_find(prow, colnum);
00206 } else {
00207 return sm_col_find(pcol, rownum);
00208 }
00209 }
00210 }
00211
00212
00213 void
00214 sm_remove(sm_matrix *A, int rownum, int colnum)
00215 {
00216 sm_remove_element(A, sm_find(A, rownum, colnum));
00217 }
00218
00219
00220
00221 void
00222 sm_remove_element(sm_matrix *A, sm_element *p)
00223 {
00224 register sm_row *prow;
00225 register sm_col *pcol;
00226
00227 if (p == 0) return;
00228
00229
00230 prow = sm_get_row(A, p->row_num);
00231 dll_unlink(p, prow->first_col, prow->last_col,
00232 next_col, prev_col, prow->length);
00233
00234
00235 if (prow->first_col == NIL(sm_element)) {
00236 sm_delrow(A, p->row_num);
00237 }
00238
00239
00240 pcol = sm_get_col(A, p->col_num);
00241 dll_unlink(p, pcol->first_row, pcol->last_row,
00242 next_row, prev_row, pcol->length);
00243
00244
00245 if (pcol->first_row == NIL(sm_element)) {
00246 sm_delcol(A, p->col_num);
00247 }
00248
00249 sm_element_free(p);
00250 }
00251
00252 void
00253 sm_delrow(sm_matrix *A, int i)
00254 {
00255 register sm_element *p, *pnext;
00256 sm_col *pcol;
00257 sm_row *prow;
00258
00259 prow = sm_get_row(A, i);
00260 if (prow != NIL(sm_row)) {
00261
00262 for(p = prow->first_col; p != 0; p = pnext) {
00263 pnext = p->next_col;
00264
00265
00266 pcol = sm_get_col(A, p->col_num);
00267 sm_col_remove_element(pcol, p);
00268
00269
00270 if (pcol->first_row == NIL(sm_element)) {
00271 sm_delcol(A, pcol->col_num);
00272 }
00273 }
00274
00275
00276 A->rows[i] = NIL(sm_row);
00277 dll_unlink(prow, A->first_row, A->last_row,
00278 next_row, prev_row, A->nrows);
00279 prow->first_col = prow->last_col = NIL(sm_element);
00280 sm_row_free(prow);
00281 }
00282 }
00283
00284 void
00285 sm_delcol(sm_matrix *A, int i)
00286 {
00287 register sm_element *p, *pnext;
00288 sm_row *prow;
00289 sm_col *pcol;
00290
00291 pcol = sm_get_col(A, i);
00292 if (pcol != NIL(sm_col)) {
00293
00294 for(p = pcol->first_row; p != 0; p = pnext) {
00295 pnext = p->next_row;
00296
00297
00298 prow = sm_get_row(A, p->row_num);
00299 sm_row_remove_element(prow, p);
00300
00301
00302 if (prow->first_col == NIL(sm_element)) {
00303 sm_delrow(A, prow->row_num);
00304 }
00305 }
00306
00307
00308 A->cols[i] = NIL(sm_col);
00309 dll_unlink(pcol, A->first_col, A->last_col,
00310 next_col, prev_col, A->ncols);
00311 pcol->first_row = pcol->last_row = NIL(sm_element);
00312 sm_col_free(pcol);
00313 }
00314 }
00315
00316 void
00317 sm_copy_row(sm_matrix *dest, int dest_row, sm_row *prow)
00318 {
00319 register sm_element *p;
00320
00321 for(p = prow->first_col; p != 0; p = p->next_col) {
00322 (void) sm_insert(dest, dest_row, p->col_num);
00323 }
00324 }
00325
00326
00327 void
00328 sm_copy_col(sm_matrix *dest, int dest_col, sm_col *pcol)
00329 {
00330 register sm_element *p;
00331
00332 for(p = pcol->first_row; p != 0; p = p->next_row) {
00333 (void) sm_insert(dest, dest_col, p->row_num);
00334 }
00335 }
00336
00337
00338 sm_row *
00339 sm_longest_row(sm_matrix *A)
00340 {
00341 register sm_row *large_row, *prow;
00342 register int max_length;
00343
00344 max_length = 0;
00345 large_row = NIL(sm_row);
00346 for(prow = A->first_row; prow != 0; prow = prow->next_row) {
00347 if (prow->length > max_length) {
00348 max_length = prow->length;
00349 large_row = prow;
00350 }
00351 }
00352 return large_row;
00353 }
00354
00355
00356 sm_col *
00357 sm_longest_col(sm_matrix *A)
00358 {
00359 register sm_col *large_col, *pcol;
00360 register int max_length;
00361
00362 max_length = 0;
00363 large_col = NIL(sm_col);
00364 for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) {
00365 if (pcol->length > max_length) {
00366 max_length = pcol->length;
00367 large_col = pcol;
00368 }
00369 }
00370 return large_col;
00371 }
00372
00373 int
00374 sm_num_elements(sm_matrix *A)
00375 {
00376 register sm_row *prow;
00377 register int num;
00378
00379 num = 0;
00380 sm_foreach_row(A, prow) {
00381 num += prow->length;
00382 }
00383 return num;
00384 }
00385
00386 int
00387 sm_read(FILE *fp, sm_matrix **A)
00388 {
00389 int i, j, err;
00390
00391 *A = sm_alloc();
00392 while (! feof(fp)) {
00393 err = fscanf(fp, "%d %d", &i, &j);
00394 if (err == EOF) {
00395 return 1;
00396 } else if (err != 2) {
00397 return 0;
00398 }
00399 (void) sm_insert(*A, i, j);
00400 }
00401 return 1;
00402 }
00403
00404
00405 int
00406 sm_read_compressed(FILE *fp, sm_matrix **A)
00407 {
00408 int i, j, k, nrows, ncols;
00409 unsigned long x;
00410
00411 *A = sm_alloc();
00412 if (fscanf(fp, "%d %d", &nrows, &ncols) != 2) {
00413 return 0;
00414 }
00415 sm_resize(*A, nrows, ncols);
00416
00417 for(i = 0; i < nrows; i++) {
00418 if (fscanf(fp, "%lx", &x) != 1) {
00419 return 0;
00420 }
00421 for(j = 0; j < ncols; j += 32) {
00422 if (fscanf(fp, "%lx", &x) != 1) {
00423 return 0;
00424 }
00425 for(k = j; x != 0; x >>= 1, k++) {
00426 if (x & 1) {
00427 (void) sm_insert(*A, i, k);
00428 }
00429 }
00430 }
00431 }
00432 return 1;
00433 }
00434
00435
00436 void
00437 sm_write(FILE *fp, sm_matrix *A)
00438 {
00439 register sm_row *prow;
00440 register sm_element *p;
00441
00442 for(prow = A->first_row; prow != 0; prow = prow->next_row) {
00443 for(p = prow->first_col; p != 0; p = p->next_col) {
00444 (void) fprintf(fp, "%d %d\n", p->row_num, p->col_num);
00445 }
00446 }
00447 }
00448
00449 void
00450 sm_print(FILE *fp, sm_matrix *A)
00451 {
00452 register sm_row *prow;
00453 register sm_col *pcol;
00454 int c;
00455
00456 if (A->last_col->col_num >= 100) {
00457 (void) fprintf(fp, " ");
00458 for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) {
00459 (void) fprintf(fp, "%d", (pcol->col_num / 100)%10);
00460 }
00461 putc('\n', fp);
00462 }
00463
00464 if (A->last_col->col_num >= 10) {
00465 (void) fprintf(fp, " ");
00466 for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) {
00467 (void) fprintf(fp, "%d", (pcol->col_num / 10)%10);
00468 }
00469 putc('\n', fp);
00470 }
00471
00472 (void) fprintf(fp, " ");
00473 for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) {
00474 (void) fprintf(fp, "%d", pcol->col_num % 10);
00475 }
00476 putc('\n', fp);
00477
00478 (void) fprintf(fp, " ");
00479 for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) {
00480 (void) fprintf(fp, "-");
00481 }
00482 putc('\n', fp);
00483
00484 for(prow = A->first_row; prow != 0; prow = prow->next_row) {
00485 (void) fprintf(fp, "%3d:", prow->row_num);
00486
00487 for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) {
00488 c = sm_row_find(prow, pcol->col_num) ? '1' : '.';
00489 putc(c, fp);
00490 }
00491 putc('\n', fp);
00492 }
00493 }
00494
00495
00496 void
00497 sm_dump(sm_matrix *A, char *s, int max)
00498 {
00499 FILE *fp = stdout;
00500
00501 (void) fprintf(fp, "%s %d rows by %d cols\n", s, A->nrows, A->ncols);
00502 if (A->nrows < max) {
00503 sm_print(fp, A);
00504 }
00505 }
00506
00507 void
00508 sm_cleanup(void)
00509 {
00510 #ifdef FAST_AND_LOOSE
00511 register sm_element *p, *pnext;
00512 register sm_row *prow, *pnextrow;
00513 register sm_col *pcol, *pnextcol;
00514
00515 for(p = sm_element_freelist; p != 0; p = pnext) {
00516 pnext = p->next_col;
00517 FREE(p);
00518 }
00519 sm_element_freelist = 0;
00520
00521 for(prow = sm_row_freelist; prow != 0; prow = pnextrow) {
00522 pnextrow = prow->next_row;
00523 FREE(prow);
00524 }
00525 sm_row_freelist = 0;
00526
00527 for(pcol = sm_col_freelist; pcol != 0; pcol = pnextcol) {
00528 pnextcol = pcol->next_col;
00529 FREE(pcol);
00530 }
00531 sm_col_freelist = 0;
00532 #endif
00533 }