18#ifdef __M4RI_MAX_MZD_BLOCKSIZE
21int gauss_one_rows_blocks(mzd_t *M,
const int idx,
const int begrow,
const rci_t nrows_eff) {
22 const wi_t word_idx = idx >> 6;
23 const word bit_mask = (word)1 << (idx & 63);
24 const wi_t width = M->width;
25 for (rci_t j = begrow; j < nrows_eff; ++j) {
26 if (mzd_row(M, j)[word_idx] & bit_mask) {
28 mzd_row_swap(M, begrow, j);
30 const word *
const piv_row = mzd_row(M, begrow);
31 for (rci_t ii = 0; ii < nrows_eff; ++ii) {
32 word *
const dst_row = mzd_row(M, ii);
33 if (ii != begrow && (dst_row[word_idx] & bit_mask)) {
34 for (wi_t w = 0; w < width; ++w) {
35 dst_row[w] ^= piv_row[w];
48 for(rci_t i = 0; i < A->nrows; ++i)
49 for(rci_t j = 0; j < A->ncols; ++j)
50 if(mzd_read_bit(A, i, j))
57 assert(i >=0 && i < A->nrows);
59 for(rci_t j = 0; j < A->ncols; ++j)
60 if(mzd_read_bit(A, i, j))
64 const word *
const truerow = mzd_row_cons(A,i);
65 for(wi_t j = 0; j < A->width - 1; j ++){
66 count += m4ri_bitcount(truerow[j]);
68 for(rci_t j = m4ri_radix * (A-> width - 1) ; j < A->ncols ; ++j)
69 if(mzd_read_bit(A, i, j))
77 for(rci_t i = 0; i < A->nrows; ++i)
78 for(rci_t j = 0; j < A->ncols; ++j)
79 if(mzd_read_bit(A, i, j))
83 for(rci_t i = 0; i < A->nrows; ++i) {
84 const word *
const truerow = mzd_row_cons(A,i);
85 for(wi_t j = 0; j < A->width - 1; j ++){
86 count += m4ri_bitcount(truerow[j]);
90 for(rci_t j = m4ri_radix * (A-> width - 1) ; j < A->ncols ; ++j)
91 if(mzd_read_bit(A, i, j))
105 rci_t startcol=0, startrow = 0;
109 q=mzp_init(M->ncols);
111 if ((q->length)!=M->ncols){
113 q=mzp_init(M->ncols);
120 for (rci_t i = startcol; i < M->ncols ; ++i) {
121 for(rci_t j = startrow ; j < M->nrows; ++j) {
122 if (mzd_read_bit(M, j, i)) {
123 mzd_row_swap(M, startrow, j);
126 for(rci_t ii = full ? 0 : startrow + 1; ii < M->nrows; ++ii) {
127 if (ii != startrow) {
128 if (mzd_read_bit(M, ii, i)) {
129 mzd_row_add_offset(M, ii, startrow, i);
133 startrow = startrow + 1;
148 for(
int i=0;i<m;i++){
149 int w=(
p->p[i+1])-(
p->p[i]);
164 int rows=
p->rows, cols=
p->cols, nz=
p->p[rows];
167 else if ((dst->
cols != rows) || (dst->
rows != cols) || (dst->
nzmax <
MAX(nz, cols+1)))
168 ERROR(
"Wrong size for return matrix.\n");
171 for(
int i=0;i<rows;i++)
172 for(
int j=
p->p[i]; j < p->
p[i+1] ; j++){
187 int m=
p->rows, n=
p->cols, nz=
p->nz;
190 else if ((dst->nrows != m) || (dst->ncols != n))
191 ERROR(
"Wrong size for return matrix.\n");
197 for(
int j=
p->p[i]; j < p->
p[i+1] ; j++)
198 mzd_write_bit(dst, i,
p->i[j], 1);
201 for(
int i=0;i<
p->nz;i++)
202 mzd_write_bit(dst,
p->p[i],
p->i[i],1);
216 mzp_t * pivots = mzp_init(n);
219 if ((
prm.debug & 2048) && (n<=80)){
226 if ((G!=NULL) && ((G->ncols!=n) || (G->nrows!=n-ra))){
234 if (ra > 0 && ra < n) {
235 mzd_apply_p_right_trans(mat,pivots);
236 mzd_t *matC = mzd_submatrix(NULL, mat, 0, ra, ra, n);
237 mzd_t * winCT=mzd_init_window(G,0,0,n-ra,ra);
238 mzd_transpose(winCT,matC);
242 for(
int i=0; i<n-ra ; i++)
243 mzd_write_bit(G,i,i+ra,1);
246 mzd_apply_p_right(G,pivots);
258 if (S->
cols != B->nrows)
259 ERROR(
"column dim of S and row dim of B should match, %d=%d",S->
cols,B->nrows);
261 C = mzd_init(S->
rows, B->ncols);
263 if (C->nrows != S->
rows || C->ncols != B->ncols)
264 ERROR(
"Provided return matrix has wrong dimensions.\n");
268 rci_t
const m = S->
rows;
270 for(rci_t i = 0; i < m; ++i)
271 for(
int j=S->
p[i]; j < S->
p[i+1] ; j++)
272 mzd_combine(C,i,0, C,i,0, B,S->
i[j],0);
283 ERROR(
"addto: attempt to get row=%d of %d",i,spaQ->
rows);
284 if (row->ncols != spaQ->
cols)
285 ERROR(
"addto: column number mismatch");
288 for (
int j=spaQ->
p[i]; j<spaQ->
p[i+1]; j++)
289 mzd_flip_bit(row, 0,spaQ->
i[j]);
297static inline void addto_inline(mzd_t *row,
const csr_t *spaQ,
const int i){
300 ERROR(
"addto: attempt to get row=%d of %d",i,spaQ->
rows);
301 if (row->ncols != spaQ->
cols)
302 ERROR(
"addto: column number mismatch");
305 for (
int j=spaQ->
p[i]; j<spaQ->
p[i+1]; j++)
306 mzd_flip_bit(row, 0,spaQ->
i[j]);
315 if (row->ncols != spaQ->
rows)
316 ERROR(
"column dim of row and row dim of spaQ should match, %d=%d",row->ncols,spaQ->
rows);
317 if (syndrome == NULL)
318 syndrome = mzd_init(row->nrows, spaQ->
cols);
320 if (syndrome->nrows != row->nrows || syndrome->ncols != spaQ->
cols)
321 ERROR(
"Provided return matrix has wrong dimensions.\n");
323 mzd_set_ui(syndrome,0);
325 for (rci_t i=0; i< row->nrows; i++){
326 const word *
const rawrow = mzd_row_cons(row,i);
330 j=nextelement(rawrow,row->width,j+1);
334 for (
int j1=spaQ->
p[j]; j1<spaQ->
p[j+1]; j1++)
335 mzd_flip_bit(syndrome, i,spaQ->
i[j1]);
344 ERROR(
"matrix A is NULL");
346 ERROR(
"matrix A shold be in compressed form");
348 ERROR(
"matrix B is NULL");
350 ERROR(
"matrix B should be in compressed form");
352 ERROR(
"col count mismatch: A[%d,%d] and B[%d,%d]",
360 unsigned char *
const par = calloc((
size_t)A->
rows + 1, 1);
361 int *
const touched = malloc(((
size_t)A->
rows + 1) *
sizeof(
int));
362 if (!par || !touched)
363 ERROR(
"memory allocation");
365 for (
int i = 0; (i < B->
rows) && !nonzero; i++) {
367 for (
int k = B->
p[i]; k < B->
p[i + 1]; k++) {
368 const int j = B->
i[k];
369 if ((k > B->
p[i]) && (j == B->
i[k - 1]))
371 for (
int t = AT->
p[j]; t < AT->
p[j + 1]; t++) {
372 const int r = AT->
i[t];
373 if ((t > AT->
p[j]) && (r == AT->
i[t - 1]))
382 for (
int t = 0; t < nt; t++) {
383 nonzero |= par[touched[t]] & 1;
400 for(
int i=0;i<m;i++){
402 for (
int j=spaQ->
p[i]; j<spaQ->
p[i+1]; j++){
406 bit ^= mzd_read_bit(row, 0,spaQ->
i[j]);
423 mzd_t *BT=mzd_transpose(NULL,B);
424 Prod=mzd_mul_naive(NULL,mA,BT);
428 Prod=mzd_mul_naive(NULL,mA,B);
441 int divisor = RAND_MAX/(max);
444 retval = rand() / divisor;
445 while (retval >= max);
448 return (
int) floor(max * tinymt64_generate_double(&tinymt));
461 ERROR(
"permutation must be initialized!");
462 if (length>q->length)
463 ERROR(
"mzp_rand_len: second parameter too large, %d > %d", length, q->length);
464 for(
int i=0;i<=length-2;i++){
467 for(
int i=length-1; i< (q-> length); i++)
477 for(rci_t i=0;i<
p->length;i++)
478 printf(
" %d",
p->values[i]);
487mzp_t *
perm_p(mzp_t *q,
const mzp_t *
p,rci_t start){
490 q=mzp_init(
p->length);
491 else if (
p->length != q->length)
492 ERROR(
"mzp length mismatch %d and %d !\n",
p->length , q->length);
493 rci_t length =
p->length;
494 rci_t *perm = q->values;
495 for(rci_t i = start; i < length; ++i)
496 SWAPINT(perm[i], perm[
p->values[i]]);
508 q=mzp_init(
p->length);
509 else if (
p->length != q->length)
510 ERROR(
"mzp length mismatch %d and %d !\n",
p->length , q->length);
511 rci_t length =
p->length;
512 rci_t *perm = q->values;
513 for(rci_t i = start; i < length; ++i)
514 SWAPINT(perm[length-i-1], perm[
p->values[length-i-1]]);
540 if ((mat!=NULL)&&((mat->
nzmax < nzmax)||(mat->
nzmax < rows+1))){
543 mat->
p = realloc(mat->
p,
MAX(nzmax,(rows+1))*
sizeof(
int));
544 mat->
i = realloc(mat->
i, nzmax*
sizeof(
int));
545 if ((mat->
p==NULL) || (mat->
i==NULL))
546 ERROR(
"csr_init: failed to reallocate CSR rows=%d cols=%d nzmax=%d",
551 mat=malloc(
sizeof(
csr_t));
552 mat->
p=calloc(
MAX(nzmax,(rows+1)),
sizeof(
int));
553 mat->
i=calloc(nzmax,
sizeof(
int));
554 if ((mat == NULL) || (mat->
p==NULL) || (mat->
i==NULL))
555 ERROR(
"csr_init: failed to allocate CSR rows=%d cols=%d nzmax=%d",
565#define SORT_NAME int_pair
566#define SORT_TYPE int_pair
567#define SORT_CMP(x, y) (((x).a != (y).a) ? ((x).a - (y).a) : ((x).b - (y).b))
568#define SORT_DEF static inline
577 ERROR(
"matrix already compressed");
579 for(
int i=0;i<nz;i++){
580 pairs[i].
a=mat->
p[i];
581 pairs[i].
b=mat->
i[i];
583 int_pair_quick_sort(pairs, nz);
585 for(i=0;i<mat->
rows;i++){
587 while ((j<nz)&&(pairs[j].a == i)){
588 mat->
i[j]=pairs[j].
b;
598 mat =
csr_init(mat, nrows, ncols, nz);
599 int_pair_quick_sort(prs, nz);
601 for(i=0; i < nrows; i++){
603 while ((j<nz) && (prs[j].a == i)){
619 printf(
"# binary CSR matrix (%d x %d) in Compressed Row Form: "
620 "nzmax= %d, nz=%d\n",
622 for(
int i=0;i<mat->
rows;i++){
624 for(
int j=mat->
p[i]; j < mat->
p[i+1] ; j++)
625 printf(
" %d",mat->
i[j]+1);
630 printf(
"# binary CSR matrix (%d x %d) in Pair Form: "
631 "nzmax= %d, nz=%d\n",
633 for(
int i=0;i<mat->
nz;i++)
634 printf(
"%d %d\n",mat->
p[i]+1,mat->
i[i]+1);
641 printf(
"matrix %s:\n",str);
661 if ((f = fopen(fin,
"r")) == NULL)
662 ERROR(
"can't open file %s",fin);
665 ERROR(
"Could not process Matrix Market banner.");
668 ERROR(
"Only Matrix Market 'matrix' object is supported.");
681 ERROR(
"Cannot read coordinate size in input file %s", fin);
684 ERROR(
"Cannot read array size in input file %s", fin);
714 mat =
csr_init(mat, rows, cols, nzmax);
718 for (
int i = 0; i < nz; i++) {
722 if (fscanf(f,
"%d %d %d\n", &r, &c, &v) != 3) {
723 ERROR(
"Failed to read coordinate entry %d in %s", i, fin);
726 if (fscanf(f,
"%d %d\n", &r, &c) != 2) {
727 ERROR(
"Failed to read pattern entry %d in %s", i, fin);
733 int r_store = transpose ? c : r;
734 int c_store = transpose ? r : c;
748 for (
int c = 0; c < N; c++) {
749 for (
int r = 0; r < M; r++) {
751 if (fscanf(f,
"%d\n", &v) != 1) {
752 ERROR(
"Failed to read dense general entry at r=%d, c=%d in %s", r, c, fin);
755 int r_store = transpose ? c : r;
756 int c_store = transpose ? r : c;
764 for (
int c = 0; c < N; c++) {
765 for (
int r = c; r < M; r++) {
767 if (fscanf(f,
"%d\n", &v) != 1) {
768 ERROR(
"Failed to read dense symmetric entry at r=%d, c=%d in %s", r, c, fin);
771 int r_store = transpose ? c : r;
772 int c_store = transpose ? r : c;
801 ERROR(
"pair format unsupported, nz=%d; expected \"-1\"",src->
nz);
803 if(src->
cols != perm-> length)
804 ERROR(
"perm length=%d should match cols=%d",perm->length,src->
cols);
807 else if ((dst->
rows != m) || (dst->
cols != n) || (nz > dst->
nzmax))
808 ERROR(
"Wrong size for return matrix.\n");
810 for(
int j=src->
p[i]; j < src->
p[i+1] ; j++){
812 dst->
i[j]= perm->values[src->
i[j]];
832int do_reduce(mzd_t *row,
const mzd_t *matG0,
const rci_t rankG0){
833 word *
const rawrow = mzd_row(row,0);
837 j=nextelement(rawrow,row->width,j);
841 mzd_combine_even_in_place(row,0,0,matG0,j,0);
842 }
while (j < rankG0);
848static inline uint64_t rotl(
const uint64_t x,
int k) {
849 return (x << k) | (x >> (64 - k));
872 const int cutoff=
p*RAND_MAX;
874 ERROR(
"make_err: row vector must be allocated to correct size!");
877 for(rci_t i = 0; i < row->nrows; ++i){
878 mzd_row_clear_offset(row,i,0);
880 for(rci_t j = 0; j < row->ncols; ++j){
883 mzd_write_bit(row,i,j,1);
901 mat =
csr_init(mat, orig->nrows, orig->ncols, nz);
903 for(i=0;i < mat->
rows; i++){
907 const word *
const rawrow = mzd_row_cons(orig,i);
908 while(((idx=nextelement(rawrow,orig->width,idx))!=-1)&&(idx<orig->ncols)){
912 for(
int idx=0; idx< orig->ncols; idx++)
913 if(mzd_read_bit(orig,i,idx)){
937 ERROR(
"unequal number of columns in matrices Hx[%d,%d] and Hz[%d,%d]",
940 mzp_t *pivots = mzp_init(n);
942 mzd_apply_p_right_trans(Mx,pivots);
943 mzp_t *perm =
perm_p( NULL, pivots,0);
949 mzd_t *MxT = mzd_transpose(NULL,Mx);
951 ERROR(
"rows of Hx and Hz should be orthogonal ");
957 mzd_t *mat = mzd_stack(NULL,Mx,MzStar);
960 int rank1=mzd_echelonize(mat,0);
963 mzd_t *window = mzd_init_window(mat,rank,0,rank1,n);
977 mzd_t *X = mzd_kernel_left_pluq(mH, 0);
980 mzd_t *N = mzd_transpose(NULL, X);
986 if (!A || A->
nz != -1)
ERROR(
"expected a sparse matrix in CSR form");
988 if (!cm)
ERROR(
"memory allocation");
991 cm->
kw = (A->
rows + 63) >> 6;
992 const size_t num = (size_t)A->
cols * (
size_t)cm->
kw;
993 cm->
mask = calloc(num > 0 ? num : 1,
sizeof(word));
994 if (!cm->
mask)
ERROR(
"memory allocation");
995 for (
int ir = 0; ir < A->
rows; ir++) {
996 const word bit = (word)1 << (ir & 63);
997 for (
int iL = A->
p[ir]; iL < A->
p[ir + 1]; iL++)
998 cm->
mask[(size_t)A->
i[iL] * cm->
kw + (ir >> 6)] ^= bit;
1013 if (!ws)
ERROR(
"memory allocation");
1015 ws->
rmap = malloc((
size_t)(m > 0 ? m : 1) *
sizeof(
int));
1016 ws->
rlist = malloc((
size_t)(m > 0 ? m : 1) *
sizeof(
int));
1018 for (
int r = 0; r < m; r++) ws->
rmap[r] = -1;
1034static int cols_ws_rows(
const csr_t *
const HT,
const int cnt,
const int cols[],
cols_ws_t *
const ws) {
1036 for (
int i = 0; i < cnt; i++) {
1037 for (
int k = HT->
p[cols[i]]; k < HT->
p[cols[i] + 1]; k++) {
1038 const int r = HT->
i[k];
1039 if (ws->
rmap[r] < 0) {
1041 ws->
rlist[nr++] = r;
1048static void cols_ws_clear(
cols_ws_t *
const ws,
const int nr) {
1049 for (
int i = 0; i < nr; i++) ws->
rmap[ws->
rlist[i]] = -1;
1054static word * cols_ws_matrix(
const csr_t *
const HT,
const int cnt,
const int cols[],
cols_ws_t *
const ws,
1055 const size_t stride) {
1056 const size_t num = (size_t)cnt * stride;
1057 if (num > ws->
cap) {
1059 ws->
cap = (num > 2 * ws->
cap) ? num : 2 * ws->cap;
1060 ws->
bits = malloc(ws->
cap *
sizeof(word));
1061 if (!ws->
bits)
ERROR(
"memory allocation");
1063 word *
const M = ws->
bits;
1064 if (num > 0) memset(M, 0, num *
sizeof(word));
1065 for (
int i = 0; i < cnt; i++) {
1066 for (
int k = HT->
p[cols[i]]; k < HT->
p[cols[i] + 1]; k++) {
1067 const int b = ws->
rmap[HT->
i[k]];
1068 M[(size_t)i * stride + (b >> 6)] ^= (word)1 << (b & 63);
1077static int cols_ws_eliminate(word *
const M,
const int cnt,
const int nr,
const size_t stride) {
1079 for (
int b = 0; b < nr && rank < cnt; b++) {
1080 const size_t wb = (size_t)(b >> 6);
1081 const word mb = (word)1 << (b & 63);
1083 for (
int i = rank; i < cnt; i++) {
1084 if (M[(
size_t)i * stride + wb] & mb) {
1089 if (piv < 0)
continue;
1090 word *
const pr = M + (size_t)rank * stride;
1092 word *
const qr = M + (size_t)piv * stride;
1093 for (
size_t x = 0; x < stride; x++) {
1094 const word t = pr[x];
1100 for (
int i = rank + 1; i < cnt; i++) {
1101 word *
const ri = M + (size_t)i * stride;
1103 for (
size_t x = wb; x < stride; x++) ri[x] ^= pr[x];
1111 if (cnt <= 0)
return 0;
1112 const int nr = cols_ws_rows(HT, cnt, cols, ws);
1113 const size_t nw = (size_t)((nr + 63) >> 6);
1116 word *
const M = cols_ws_matrix(HT, cnt, cols, ws, nw);
1117 rank = cols_ws_eliminate(M, cnt, nr, nw);
1119 cols_ws_clear(ws, nr);
1124 if (cnt <= 1)
return 0;
1125 const int nr = cols_ws_rows(HT, cnt, cols, ws);
1126 const size_t nw = (size_t)((nr + 63) >> 6), tw = (size_t)((cnt + 63) >> 6);
1127 const size_t stride = nw + tw;
1128 word *
const M = cols_ws_matrix(HT, cnt, cols, ws, stride);
1129 cols_ws_clear(ws, nr);
1130 for (
int i = 0; i < cnt; i++) M[(
size_t)i * stride + nw + (size_t)(i >> 6)] |= (word)1 << (i & 63);
1131 const int rank = cols_ws_eliminate(M, cnt, nr, stride);
1134 for (
int i = rank; i < cnt; i++) {
1135 const word *
const t = M + (size_t)i * stride + nw;
1137 for (
int j = 0; j < cnt; j++)
1138 if ((t[j >> 6] >> (j & 63)) & 1) k++;
1139 if (k == 0 || k == cnt)
continue;
1141 for (
int j = 0; j < cnt; j++)
1142 if ((t[j >> 6] >> (j & 63)) & 1) sub[k++] = cols[j];
1148static inline uint64_t util_splitmix64(uint64_t *state) {
1149 uint64_t z = (*state += 0x9e3779b97f4a7c15ULL);
1150 z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9ULL;
1151 z = (z ^ (z >> 27)) * 0x94d049bb133111ebULL;
1152 return z ^ (z >> 31);
1155static inline int util_rand_uniform(
int max, uint64_t *state) {
1156 if (max <= 1)
return 0;
1157 return (
int)(util_splitmix64(state) % (uint64_t)max);
1162 int *visited_cols,
int *visited_checks,
int *col_queue,
1163 int *visit_marker, uint64_t *rng_state) {
1164 if (kwin <= 0 || kwin >= nvar || !visited_cols) {
1165 for (
int i = 0; i < nvar; i++) perm->values[i] = i;
1166 for (
int i = 0; i < nvar - 1; i++) {
1167 int j = i + util_rand_uniform(nvar - i, rng_state);
1168 SWAPINT(perm->values[i], perm->values[j]);
1174 int marker = *visit_marker;
1176 memset(visited_cols, 0, (
size_t)nvar *
sizeof(
int));
1177 if (spaH && visited_checks) {
1178 memset(visited_checks, 0, (
size_t)spaH->
rows *
sizeof(
int));
1180 *visit_marker = marker = 1;
1184 if (win_mode == 0 && spaH && mHT && visited_checks && col_queue) {
1185 int head = 0, tail = 0;
1186 visited_cols[seed_col] = marker;
1187 col_queue[tail++] = seed_col;
1188 perm->values[count++] = seed_col;
1190 while (count < kwin) {
1192 int col = col_queue[head++];
1193 for (
int p_idx = mHT->
p[col]; p_idx < mHT->
p[col + 1] && count < kwin; p_idx++) {
1194 int chk = mHT->
i[p_idx];
1195 if (visited_checks[chk] != marker) {
1196 visited_checks[chk] = marker;
1197 for (
int h_idx = spaH->
p[chk]; h_idx < spaH->
p[chk + 1] && count < kwin; h_idx++) {
1198 int c_adj = spaH->
i[h_idx];
1199 if (visited_cols[c_adj] != marker) {
1200 visited_cols[c_adj] = marker;
1201 col_queue[tail++] = c_adj;
1202 perm->values[count++] = c_adj;
1208 int r_start = util_rand_uniform(nvar, rng_state);
1210 for (
int offset = 0; offset < nvar; offset++) {
1211 int cand = (r_start + offset) % nvar;
1212 if (visited_cols[cand] != marker) {
1217 if (found == -1)
break;
1218 visited_cols[found] = marker;
1219 col_queue[tail++] = found;
1220 perm->values[count++] = found;
1224 for (
int i = 0; i < kwin; i++) {
1225 int col = (seed_col + i) % nvar;
1226 visited_cols[col] = marker;
1227 perm->values[count++] = col;
1231 int win_actual = count;
1232 for (
int i = 0; i < win_actual - 1; i++) {
1233 int j = i + util_rand_uniform(win_actual - i, rng_state);
1234 SWAPINT(perm->values[i], perm->values[j]);
1237 int rem_idx = win_actual;
1238 for (
int col = 0; col < nvar; col++) {
1239 if (visited_cols[col] != marker) {
1240 perm->values[rem_idx++] = col;
1243 for (
int i = win_actual; i < nvar - 1; i++) {
1244 int j = i + util_rand_uniform(nvar - i, rng_state);
1245 SWAPINT(perm->values[i], perm->values[j]);
1250 if (!N || N->nrows == 0 || N->ncols == 0)
return;
1251 const rci_t nu = N->nrows;
1252 const rci_t n = N->ncols;
1254 mzp_t *pivs = mzp_init(n);
1255 mzp_t *perm = mzp_init(n);
1256 rci_t *piv_cols = malloc((
size_t)nu *
sizeof(rci_t));
1257 if (!pivs || !perm || !piv_cols) {
1258 if (pivs) mzp_free(pivs);
1259 if (perm) mzp_free(perm);
1264 for (
int i = 0; i <= (int)n - 2; i++) {
1265 pivs->values[i] = i + util_rand_uniform(n - i, rng_state);
1267 pivs->values[n - 1] = n - 1;
1269 mzp_set_ui(perm, 1);
1273 for (rci_t i = 0; i < n && rank < nu; i++) {
1274 int col = perm->values[i];
1275 if (gauss_one(N, col, rank)) {
1276 piv_cols[rank++] = col;
1280 int target_row = -1;
1281 size_t max_row_wt = 0;
1282 if (cw_arr && cw_wt > 0) {
1283 for (rci_t r = 0; r < rank; r++) {
1284 int orig_col = piv_cols[r];
1285 for (
int k = 0; k < cw_wt; k++) {
1286 if (cw_arr[k] == orig_col) {
1288 if (r_wt > (
size_t)cw_wt && r_wt > max_row_wt) {
1298 if (target_row >= 0 && cw_arr && cw_wt > 0) {
1299 mzd_row_clear_offset(N, target_row, 0);
1300 for (
int k = 0; k < cw_wt; k++) {
1301 if (cw_arr[k] >= 0 && cw_arr[k] < n) {
1302 mzd_write_bit(N, target_row, cw_arr[k], 1);
1313 if (!H || H->
rows <= 0 || H->
cols <= 0 || H->
nz != -1)
return 0;
1314 const int m = H->
rows, n = H->
cols;
1315 char *
const has_nz = calloc((
size_t)n, 1);
1316 if (!has_nz)
ERROR(
"memory allocation");
1318 for (
int t = 0; t < H->
p[m]; t++) {
1319 const int c = H->
i[t];
1320 if (c >= 0 && c < n && !has_nz[c]) {
1326 if (covered < n)
return 0;
1328 const rci_t rank_H = mzd_echelonize(mH, 0);
1329 mzd_t *
const m1 = mzd_init(1, n);
1330 for (
int c = 0; c < n; c++) mzd_write_bit(m1, 0, c, 1);
1331 mzd_t *
const mAug = mzd_stack(NULL, mH, m1);
1334 const rci_t rank_Aug = mzd_echelonize(mAug, 0);
1336 return rank_Aug == rank_H;
char * mm_typecode_to_str(MM_typecode matcode)
Convert a Matrix Market typecode to a human-readable string.
int mm_read_mtx_array_size(FILE *f, int *M, int *N)
Read dimensions for an array (dense) matrix.
int mm_read_mtx_crd_size(FILE *f, int *M, int *N, int *nz)
Read dimensions and number of non-zero entries for a coordinate matrix.
int mm_read_banner(FILE *f, MM_typecode *matcode)
Read the Matrix Market banner from a file.
#define mm_is_matrix(typecode)
#define mm_is_coordinate(typecode)
#define mm_is_pattern(typecode)
#define mm_is_general(typecode)
#define mm_is_integer(typecode)
#define mm_is_symmetric(typecode)
mzd_t * mzd_nullspace(const csr_t *const H)
Compute the null space basis N = ker(H) of dimension nu x n.
cols_ws_t * cols_ws_init(const int m)
Allocate the workspace of csr_cols_rank() and csr_cols_dependency() for a matrix H with m rows.
int syndrome_bit_count(const mzd_t *const row, const csr_t *const spaQ)
Compute the Hamming weight of the syndrome of a dense row vector against spaQ.
colmask_t * colmask_free(colmask_t *cm)
Free the column masks allocated by colmask_from_csr().
cols_ws_t * cols_ws_free(cols_ws_t *ws)
Free the workspace allocated by cols_ws_init().
mzp_t * mzp_rand_len(mzp_t *q, rci_t length)
Generate a random permutation of a given length in-place.
csr_t * csr_from_mzd(csr_t *mat, const mzd_t *const orig)
convert m4ri dense matrix to csr
int csr_csr_mul_non_zero(const csr_t *const A, const csr_t *const B)
Check if the product of two sparse matrices A * B^T is non-zero.
void make_err(mzd_t *row, double p)
Generate a random binary error vector with error probability p.
int csr_cols_rank(const csr_t *const HT, const int cnt, const int cols[], cols_ws_t *const ws)
Rank of a set of columns of a sparse binary matrix H.
mzd_t * syndrome_vector(mzd_t *syndrome, mzd_t *row, csr_t *spaQ, int clear)
Calculate syndrome vector change.
size_t mzd_weight_row(const mzd_t *const A, const rci_t i)
Compute the Hamming weight of a specific row in a dense matrix.
csr_t * csr_from_pairs(csr_t *mat, const int nz, int_pair *const prs, const int nrows, const int ncols)
Construct a CSR sparse matrix from an array of coordinate pairs.
mzd_t * mzd_generator_from_csr(mzd_t *G, const csr_t *const H)
Construct the generator matrix from a parity check matrix in CSR form.
csr_t * csr_transpose(csr_t *dst, const csr_t *const p)
Transpose a compressed CSR sparse matrix.
csr_t * csr_mm_read(char *fin, csr_t *mat, int transpose)
Read a sparse matrix from a Matrix Market (.mtx) file into CSR format.
csr_t * Lx_for_CSS_code(const csr_t *const Hx, const csr_t *const Hz)
Compute logical generator matrix Lx for a CSS code.
csr_t * csr_init(csr_t *mat, int rows, int cols, int nzmax)
Initialize or reallocate a CSR sparse matrix to target size.
mzd_t * mzd_from_csr(mzd_t *dst, const csr_t *p)
Convert a CSR sparse matrix to an MZD dense matrix.
mzp_t * perm_p_trans(mzp_t *q, const mzp_t *p, const rci_t start)
Apply transposed pivot permutation p to permutation q in-place.
int do_reduce(mzd_t *row, const mzd_t *matG0, const rci_t rankG0)
Reduce a row vector against a matrix in standard form.
void csr_out(const csr_t *mat)
Print raw contents of a CSR matrix to stdout.
void csr_print(const csr_t *const smat, const char str[])
Print a CSR matrix with a label string (formatted output).
csr_t * csr_free(csr_t *p)
Free memory allocated for a CSR sparse matrix.
void csr_compress(csr_t *mat)
Compress CSR matrix (sort indices and remove duplicates/zeros).
int csr_max_row_wght(const csr_t *const p)
return max row weight of CSR matrix p TODO: add code for List of Pairs
rci_t mzd_gauss_naive(mzd_t *M, mzp_t *q, int full)
Perform Gaussian elimination (naive) and return pivot column list.
void localized_window_perm(mzp_t *perm, int nvar, int seed_col, int kwin, int win_mode, const csr_t *spaH, const csr_t *mHT, int *visited_cols, int *visited_checks, int *col_queue, int *visit_marker, uint64_t *rng_state)
Construct a column permutation with a localized window at the front.
void refresh_nullspace_basis(mzd_t *N, const int *cw_arr, int cw_wt, uint64_t *rng_state)
Refresh the null space basis N under a random column permutation and optionally inject a low-weight c...
colmask_t * colmask_from_csr(const csr_t *const A)
Construct the column bit masks of a sparse binary matrix (see colmask_t).
int csr_all_ones_in_rowspan(const csr_t *const H)
Check whether the all-ones vector lies in the row span of a binary CSR matrix H over GF(2).
size_t mzd_weight(const mzd_t *A)
Compute the number of set bits (Hamming weight) in a dense matrix A.
mzp_t * perm_p(mzp_t *q, const mzp_t *p, rci_t start)
Apply pivot permutation p to permutation q in-place starting from index.
void addto(mzd_t *row, const csr_t *spaQ, const int i)
void mzp_out(mzp_t const *p)
Print the permutation to stdout.
size_t mzd_weight_naive(const mzd_t *A)
Naive implementation to compute the Hamming weight of a dense matrix A.
mzd_t * csr_mzd_mul(mzd_t *C, const csr_t *S, const mzd_t *B, int clear)
Multiply a sparse matrix by a dense matrix.
size_t product_weight_csr_mzd(const csr_t *A, const mzd_t *B, int transpose)
Compute the weight of the product of a sparse matrix and a dense matrix.
csr_t * csr_apply_perm(csr_t *dst, const csr_t *const src, const mzp_t *const perm)
Permute columns of a CSR sparse matrix.
int rand_uniform(const int max)
Return a uniformly distributed random integer in the range [0, max-1].
int csr_cols_dependency(const csr_t *const HT, const int cnt, const int cols[], cols_ws_t *const ws, int sub[])
A nonempty proper subset of a set of columns of H with zero sum, if there is one.