📄 mod2sparse.c
字号:
if (!mod2sparse_at_end(re) && mod2sparse_col(re)==col) { return re; } if (mod2sparse_at_end(re) || mod2sparse_col(re)>col) { break; } re = mod2sparse_next_in_row(re); } } ne = alloc_entry(m); ne->row = row; ne->col = col; ne->left = re->left; ne->right = re; ne->left->right = ne; ne->right->left = ne; /* Insert new entry into column. If we find an existing entry here, the matrix must be garbled, since we didn't find it in the row. */ ce = mod2sparse_last_in_col(m,col); if (!mod2sparse_at_end(ce) && mod2sparse_row(ce)==row) { fprintf(stderr,"mod2sparse_insert: Garbled matrix\n"); exit(1); } if (mod2sparse_at_end(ce) || mod2sparse_row(ce)<row) { ce = ce->down; } else { ce = mod2sparse_first_in_col(m,col); for (;;) { if (!mod2sparse_at_end(ce) && mod2sparse_row(ce)==row) { fprintf(stderr,"mod2sparse_insert: Garbled matrix\n"); exit(1); } if (mod2sparse_at_end(ce) || mod2sparse_row(ce)>row) { break; } ce = mod2sparse_next_in_col(ce); } } ne->up = ce->up; ne->down = ce; ne->up->down = ne; ne->down->up = ne; /* Return the new entry. */ return ne;}/* DELETE AN ENTRY FROM A SPARSE MATRIX. Deletes a non-zero entry - ie, effectively sets the element of the matrix to zero. The entry is freed for future use in the same matrix, but not (immediately, at least) for use in other matrices, or generally. */void mod2sparse_delete( mod2sparse *m, mod2entry *e){ if (e==0) { fprintf(stderr,"mod2sparse_delete: Trying to delete a null entry\n"); exit(1); } if (e->row<0 || e->col<0) { fprintf(stderr,"mod2sparse_delete: Trying to delete a header entry\n"); exit(1); } e->left->right = e->right; e->right->left = e->left; e->up->down = e->down; e->down->up = e->up; e->left = m->next_free; m->next_free = e;}/* TEST WHETHER TWO SPARSE MATRICES ARE EQUAL. Returns one if they are, zero if they aren't. The matrices must have the same dimensions. */int mod2sparse_equal( mod2sparse *m1, mod2sparse *m2){ mod2entry *e1, *e2; int i; if (mod2sparse_rows(m1)!=mod2sparse_rows(m2) || mod2sparse_cols(m1)!=mod2sparse_cols(m2)) { fprintf(stderr,"mod2sparse_equal: Matrices have different dimensions\n"); exit(1); } for (i = 0; i<mod2sparse_rows(m1); i++) { e1 = mod2sparse_first_in_row(m1,i); e2 = mod2sparse_first_in_row(m2,i); while (!mod2sparse_at_end(e1) && !mod2sparse_at_end(e2)) { if (mod2sparse_col(e1)!=mod2sparse_col(e2)) { return 0; } e1 = mod2sparse_next_in_row(e1); e2 = mod2sparse_next_in_row(e2); } if (!mod2sparse_at_end(e1) || !mod2sparse_at_end(e2)) { return 0; } } return 1;}/* COMPUTE THE TRANSPOSE OF A SPARSE MOD2 MATRIX. Stores the transpose of the first matrix in the second matrix (which must already exist, and have as many rows as the first matrix has columns, and as many columns as the first matrix has rows). The result matrix must not be the same as the operand. */void mod2sparse_transpose( mod2sparse *m, /* Matrix to compute transpose of (left unchanged) */ mod2sparse *r /* Result of transpose operation */){ mod2entry *e; int i; if (mod2sparse_rows(m)!=mod2sparse_cols(r) || mod2sparse_cols(m)!=mod2sparse_rows(r)) { fprintf(stderr, "mod2sparse_transpose: Matrices have incompatible dimensions\n"); exit(1); } if (r==m) { fprintf(stderr, "mod2sparse_transpose: Result matrix is the same as the operand\n"); exit(1); } mod2sparse_clear(r); for (i = 0; i<mod2sparse_rows(m); i++) { e = mod2sparse_first_in_row(m,i); while (!mod2sparse_at_end(e)) { mod2sparse_insert(r,mod2sparse_col(e),i); e = mod2sparse_next_in_row(e); } }}/* ADD TWO SPARSE MOD2 MATRICES. Adds the first matrix by the second matrix, storing the result in the third matrix. Neither of the first two matrices is changed by this operation. The three matrices must have the same numbers of rows and columns. The result matrix must not be the same as either operand. */void mod2sparse_add( mod2sparse *m1, /* Left operand of add */ mod2sparse *m2, /* Right operand of add */ mod2sparse *r /* Place to store result of add */){ mod2entry *e1, *e2; int i; if (mod2sparse_rows(m1)!=mod2sparse_rows(r) || mod2sparse_cols(m1)!=mod2sparse_cols(r) || mod2sparse_rows(m2)!=mod2sparse_rows(r) || mod2sparse_cols(m2)!=mod2sparse_cols(r)) { fprintf(stderr,"mod2sparse_add: Matrices have different dimensions\n"); exit(1); } if (r==m1 || r==m2) { fprintf(stderr, "mod2sparse_add: Result matrix is the same as one of the operands\n"); exit(1); } mod2sparse_clear(r); for (i = 0; i<mod2sparse_rows(r); i++) { e1 = mod2sparse_first_in_row(m1,i); e2 = mod2sparse_first_in_row(m2,i); while (!mod2sparse_at_end(e1) && !mod2sparse_at_end(e2)) { if (mod2sparse_col(e1)==mod2sparse_col(e2)) { e1 = mod2sparse_next_in_row(e1); e2 = mod2sparse_next_in_row(e2); } else if (mod2sparse_col(e1)<mod2sparse_col(e2)) { mod2sparse_insert(r,i,mod2sparse_col(e1)); e1 = mod2sparse_next_in_row(e1); } else { mod2sparse_insert(r,i,mod2sparse_col(e2)); e2 = mod2sparse_next_in_row(e2); } } while (!mod2sparse_at_end(e1)) { mod2sparse_insert(r,i,mod2sparse_col(e1)); e1 = mod2sparse_next_in_row(e1); } while (!mod2sparse_at_end(e2)) { mod2sparse_insert(r,i,mod2sparse_col(e2)); e2 = mod2sparse_next_in_row(e2); } }}/* MULTIPLY TWO SPARSE MOD2 MATRICES. Multiplies the first matrix by the second matrix, storing the result in the third matrix. Neither of the first two matrices is changed by this operation. The previous contents of the third matrix are destroyed, and its entries release for general reuse. The three matrices must have compatible numbers of rows and columns. The result matrix must not be the same as either operand. */void mod2sparse_multiply ( mod2sparse *m1, /* Left operand of multiply */ mod2sparse *m2, /* Right operand of multiply */ mod2sparse *r /* Place to store result of multiply */){ mod2entry *e1, *e2; int i, j, b; if (mod2sparse_cols(m1)!=mod2sparse_rows(m2) || mod2sparse_rows(m1)!=mod2sparse_rows(r) || mod2sparse_cols(m2)!=mod2sparse_cols(r)) { fprintf (stderr, "mod2sparse_multiply: Matrices have incompatible dimensions\n"); exit(1); } if (r==m1 || r==m2) { fprintf(stderr, "mod2sparse_multiply: Result matrix is the same as one of the operands\n"); exit(1); } mod2sparse_clear(r); for (i = 0; i<mod2sparse_rows(m1); i++) { if (mod2sparse_at_end(mod2sparse_first_in_row(m1,i))) { continue; } for (j = 0; j<mod2sparse_cols(m2); j++) { b = 0; e1 = mod2sparse_first_in_row(m1,i); e2 = mod2sparse_first_in_col(m2,j); while (!mod2sparse_at_end(e1) && !mod2sparse_at_end(e2)) { if (mod2sparse_col(e1)==mod2sparse_row(e2)) { b ^= 1; e1 = mod2sparse_next_in_row(e1); e2 = mod2sparse_next_in_col(e2); } else if (mod2sparse_col(e1)<mod2sparse_row(e2)) { e1 = mod2sparse_next_in_row(e1); } else { e2 = mod2sparse_next_in_col(e2); } } if (b) { mod2sparse_insert(r,i,j); } } }}/* MULTIPLY VECTOR BY SPARSE MATRIX. Multiplies a column vector, unpacked one bit per byte, by a sparse matrix. The result is stored in another unpacked vector, which must not overlap the input vector. */void mod2sparse_mulvec( mod2sparse *m, /* The sparse matrix, with M rows and N columns */ char *u, /* The input vector, N long */ char *v /* Place to store the result, M long */){ mod2entry *e; int M, N; int i, j; M = mod2sparse_rows(m); N = mod2sparse_cols(m); for (i = 0; i<M; i++) v[i] = 0; for (j = 0; j<N; j++) { if (u[j]==1) { for (e = mod2sparse_first_in_col(m,j); !mod2sparse_at_end(e); e = mod2sparse_next_in_col(e)) { v[mod2sparse_row(e)] ^= 1; } } }}/* COUNT ENTRIES IN A ROW. */int mod2sparse_count_row( mod2sparse *m, int row){ mod2entry *e; int count; if (row<0 || row>=mod2sparse_rows(m)) { fprintf(stderr,"mod2sparse_count_row: row index out of bounds\n"); exit(1); } count = 0; for (e = mod2sparse_first_in_row(m,row); !mod2sparse_at_end(e); e = mod2sparse_next_in_row(e)) { count += 1; } return count;}/* COUNT ENTRIES IN A COLUMN. */int mod2sparse_count_col( mod2sparse *m, int col){ mod2entry *e; int count; if (col<0 || col>=mod2sparse_cols(m)) { fprintf(stderr,"mod2sparse_count_col: column index out of bounds\n"); exit(1); } count = 0; for (e = mod2sparse_first_in_col(m,col); !mod2sparse_at_end(e); e = mod2sparse_next_in_col(e)) { count += 1; } return count;}/* ADD TO A ROW. */void mod2sparse_add_row( mod2sparse *m1, /* Matrix containing row to add to */ int row1, /* Index in this matrix of row to add to */ mod2sparse *m2, /* Matrix containing row to add from */ int row2 /* Index in this matrix of row to add from */){ mod2entry *f1, *f2, *ft; if (mod2sparse_cols(m1)<mod2sparse_cols(m2)) { fprintf (stderr, "mod2sparse_add_row: row added to is shorter than row added from\n"); exit(1); } if (row1<0 || row1>=mod2sparse_rows(m1) || row2<0 || row2>=mod2sparse_rows(m2)) { fprintf (stderr,"mod2sparse_add_row: row index out of range\n"); exit(1); } f1 = mod2sparse_first_in_row(m1,row1); f2 = mod2sparse_first_in_row(m2,row2); while (!mod2sparse_at_end(f1) && !mod2sparse_at_end(f2)) { if (mod2sparse_col(f1)>mod2sparse_col(f2)) { mod2sparse_insert(m1,row1,mod2sparse_col(f2)); f2 = mod2sparse_next_in_row(f2); } else { ft = mod2sparse_next_in_row(f1); if (mod2sparse_col(f1)==mod2sparse_col(f2)) { mod2sparse_delete(m1,f1); f2 = mod2sparse_next_in_row(f2); } f1 = ft; } } while (!mod2sparse_at_end(f2)) { mod2sparse_insert(m1,row1,mod2sparse_col(f2)); f2 = mod2sparse_next_in_row(f2); }}/* ADD TO A COLUMN. */void mod2sparse_add_col( mod2sparse *m1, /* Matrix containing column to add to */ int col1, /* Index in this matrix of column to add to */ mod2sparse *m2, /* Matrix containing column to add from */ int col2 /* Index in this matrix of column to add from */){ mod2entry *f1, *f2, *ft; if (mod2sparse_rows(m1)<mod2sparse_rows(m2)) { fprintf (stderr, "mod2sparse_add_col: Column added to is shorter than column added from\n"); exit(1); } if (col1<0 || col1>=mod2sparse_cols(m1) || col2<0 || col2>=mod2sparse_cols(m2)) { fprintf (stderr,"mod2sparse_add_col: Column index out of range\n"); exit(1); } f1 = mod2sparse_first_in_col(m1,col1); f2 = mod2sparse_first_in_col(m2,col2); while (!mod2sparse_at_end(f1) && !mod2sparse_at_end(f2)) { if (mod2sparse_row(f1)>mod2sparse_row(f2)) { mod2sparse_insert(m1,mod2sparse_row(f2),col1); f2 = mod2sparse_next_in_col(f2); } else { ft = mod2sparse_next_in_col(f1); if (mod2sparse_row(f1)==mod2sparse_row(f2))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -