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