Dist m4ri 0.16.1
Computing distance of a classical or quantum CSS code
Loading...
Searching...
No Matches
util_m4ri.c
Go to the documentation of this file.
1/************************************************************************
2 * helper functions for use with m4ri library,
3 * including binary sparse matrices and conversion utilities
4 * author: Leonid Pryadko <leonid.pryadko@ucr.edu>
5 * some code borrowed from various sources
6 ************************************************************************/
7#include <m4ri/m4ri.h>
8#include <m4ri/mzd.h>
9#include <stdio.h>
10#include <stdlib.h>
11#include <string.h>
12#include <ctype.h>
13#include "mmio.h"
14
15#include "util_m4ri.h"
16
17
18#ifdef __M4RI_MAX_MZD_BLOCKSIZE
19/* gauss_one_rows() for rows not at equal distances in memory (M4RI before 2024, a matrix spanning several blocks):
20 * each row is found with mzd_row(). Kept out of line, so that the inlined gauss_one_rows() stays small. */
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) {
27 if (j != begrow) {
28 mzd_row_swap(M, begrow, j);
29 }
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];
36 }
37 }
38 }
39 return 1;
40 }
41 }
42 return 0;
43}
44#endif /* __M4RI_MAX_MZD_BLOCKSIZE */
45
46size_t mzd_weight_naive(const mzd_t *A){
47 size_t count = 0;
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))
51 ++count;
52 return (count);
53}
54
55size_t mzd_weight_row(const mzd_t * const A, const rci_t i){
56 size_t count = 0;
57 assert(i >=0 && i < A->nrows);
58 if(A->width == 1) {
59 for(rci_t j = 0; j < A->ncols; ++j)
60 if(mzd_read_bit(A, i, j))
61 ++count;
62 return (count);
63 }
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]);
67 }
68 for(rci_t j = m4ri_radix * (A-> width - 1) ; j < A->ncols ; ++j)
69 if(mzd_read_bit(A, i, j))
70 ++count;
71 return count ;
72}
73
74size_t mzd_weight(const mzd_t *A){
75 size_t count = 0;
76 if(A->width == 1) {
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))
80 ++count;
81 return (count);
82 }
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]);
87 // count += std_bitcount(truerow[j]);
88 // printf(" %d",std_bitcount(truerow[j]));
89 }
90 for(rci_t j = m4ri_radix * (A-> width - 1) ; j < A->ncols ; ++j)
91 if(mzd_read_bit(A, i, j))
92 ++count;
93 }
94 // printf(" count=%d\n",count);
95 return count ;
96}
97
98
104rci_t mzd_gauss_naive(mzd_t *M, mzp_t *q, int full) {
105 rci_t startcol=0, startrow = 0;
106 rci_t pivots = 0;
107#if 0
108 if (q==NULL)
109 q=mzp_init(M->ncols);
110 else {
111 if ((q->length)!=M->ncols){
112 mzp_free(q);
113 q=mzp_init(M->ncols);
114 }
115 else
116 mzp_set_ui(q,1);
117 }
118#endif
119
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);
124 q->values[pivots]=i; /* request cols swap: pivots <--> i */
125 ++pivots;
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);
130 }
131 }
132 }
133 startrow = startrow + 1;
134 break;
135 }
136 }
137 }
138 return pivots;
139}
140
145int csr_max_row_wght(const csr_t * const p){
146 int m=p->rows;
147 int wmax=0;
148 for(int i=0;i<m;i++){
149 int w=(p->p[i+1])-(p->p[i]);
150 if (w>wmax)
151 wmax=w;
152 }
153 return wmax;
154}
155
156
163csr_t * csr_transpose(csr_t *dst, const csr_t * const p){
164 int rows=p->rows, cols=p->cols, nz=p->p[rows];
165 if (dst == NULL)
166 dst = csr_init(NULL,cols,rows,nz);
167 else if ((dst->cols != rows) || (dst->rows != cols) || (dst->nzmax < MAX(nz, cols+1)))
168 ERROR("Wrong size for return matrix.\n");
169 else
170 dst->nz=0; /* clear matrix */
171 for(int i=0;i<rows;i++)
172 for(int j=p->p[i]; j < p->p[i+1] ; j++){
173 dst->p[j]=p->i[j]; // pair format, to be compressed later
174 dst->i[j]=i ;
175 }
176 dst->nz=nz;
177 csr_compress(dst);
178 return dst;
179}
180
181
186mzd_t *mzd_from_csr(mzd_t *dst, const csr_t *p) {
187 int m=p->rows, n=p->cols, nz=p->nz;
188 if (dst == NULL)
189 dst = mzd_init(m,n);
190 else if ((dst->nrows != m) || (dst->ncols != n))
191 ERROR("Wrong size for return matrix.\n");
192 else
193 mzd_set_ui(dst,0); /* clear bits */
194
195 if(nz==-1){ // binary CSR matrix in Compressed Row Form
196 for(int i=0;i<m;i++)
197 for(int j=p->p[i]; j < p->p[i+1] ; j++)
198 mzd_write_bit(dst, i, p->i[j], 1);
199 }
200 else{ // binary CSR matrix in Pair Form
201 for(int i=0;i<p->nz;i++)
202 mzd_write_bit(dst, p->p[i],p->i[i],1);
203 }
204 return dst;
205}
206
213mzd_t *mzd_generator_from_csr(mzd_t *G, const csr_t * const H){
214 rci_t n=H->cols;
215 mzd_t *mat=mzd_from_csr(NULL,H); /* convert to dense matrix */
216 mzp_t * pivots = mzp_init(n); /* initialize the permutation */
217 rci_t ra = mzd_gauss_naive(mat, pivots, 1);
218#if 0
219 if ((prm.debug & 2048) && (n<=80)){
220 mzd_print(mat);
221 mzp_out(pivots);
222 printf("\n");
223 }
224#endif
225 /* now we can check if G is the right size and reallocate if needed */
226 if ((G!=NULL) && ((G->ncols!=n) || (G->nrows!=n-ra))){
227 mzd_free(G);
228 G=NULL;
229 }
230 if (G==NULL)
231 G=mzd_init(n-ra,n);
232 else
233 mzd_set_ui(G,0); /* clear the matrix */
234 if (ra > 0 && ra < n) {
235 mzd_apply_p_right_trans(mat,pivots); /* permute columns to make std form [ I C ] */
236 mzd_t *matC = mzd_submatrix(NULL, mat, 0, ra, ra, n); /* C size ra by n-ra */
237 mzd_t * winCT=mzd_init_window(G,0,0,n-ra,ra);
238 mzd_transpose(winCT,matC);
239 mzd_free(winCT); /* window is no longer needed */
240 mzd_free(matC); /* \todo see why window does not seem to work here */
241 }
242 for(int i=0; i<n-ra ; i++)
243 mzd_write_bit(G,i,i+ra,1); /* identity matrix on the right */
244
245 if (ra < n)
246 mzd_apply_p_right(G,pivots); /* permute columns back */
247 mzp_free(pivots);
248 mzd_free(mat);
249 return G;
250}
251
252
257mzd_t * csr_mzd_mul(mzd_t *C, const csr_t *S, const mzd_t *B, int clear){
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);
260 if (C == NULL)
261 C = mzd_init(S->rows, B->ncols);
262 else {
263 if (C->nrows != S->rows || C->ncols != B->ncols)
264 ERROR("Provided return matrix has wrong dimensions.\n");
265 if(clear)
266 mzd_set_ui(C,0);
267 }
268 rci_t const m = S->rows;
269
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); /* combine the two rows */
273 return C;
274}
275
280void addto(mzd_t *row, const csr_t *spaQ, const int i){
281#if 0
282 if (i>=spaQ->rows)
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");
286 // mzd_print(row);
287#endif
288 for (int j=spaQ->p[i]; j<spaQ->p[i+1]; j++)
289 mzd_flip_bit(row, 0,spaQ->i[j]); /* flip that bit */
290}
291
292
297static inline void addto_inline(mzd_t *row, const csr_t *spaQ, const int i){
298#ifndef NDEBUG
299 if (i>=spaQ->rows)
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");
303 // mzd_print(row);
304#endif
305 for (int j=spaQ->p[i]; j<spaQ->p[i+1]; j++)
306 mzd_flip_bit(row, 0,spaQ->i[j]); /* flip that bit */
307}
308
309
314mzd_t * syndrome_vector(mzd_t *syndrome, mzd_t *row, csr_t *spaQ, int clear){
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);
319 else {
320 if (syndrome->nrows != row->nrows || syndrome->ncols != spaQ->cols)
321 ERROR("Provided return matrix has wrong dimensions.\n");
322 if(clear)
323 mzd_set_ui(syndrome,0);
324 }
325 for (rci_t i=0; i< row->nrows; i++){
326 const word * const rawrow = mzd_row_cons(row,i);
327 rci_t j=-1;
328 rci_t n=row->ncols;
329 do{
330 j=nextelement(rawrow,row->width,j+1);
331 if((j==-1)||(j>=n)) // no more non-zero elements
332 break;
333 else
334 for (int j1=spaQ->p[j]; j1<spaQ->p[j+1]; j1++)
335 mzd_flip_bit(syndrome, i,spaQ->i[j1]); /* flip that bit */
336 }
337 while( TRUE);
338 }
339 return syndrome;
340}
341
342int csr_csr_mul_non_zero(const csr_t * const A, const csr_t * const B){
343 if(!A)
344 ERROR("matrix A is NULL");
345 if(A->nz != -1)
346 ERROR("matrix A shold be in compressed form");
347 if(!B)
348 ERROR("matrix B is NULL");
349 if(B->nz != -1)
350 ERROR("matrix B should be in compressed form");
351 if (A->cols != B->cols)
352 ERROR("col count mismatch: A[%d,%d] and B[%d,%d]",
353 A->rows,A->cols, B->rows, B->cols);
354
355 /* for each row b of B, the parities of its overlaps with the rows of A, accumulated over the columns j of b from
356 * the rows of A with a nonzero in column j (the transpose of A): O(nnz(A) + nnz(B) * column weight of A) operations
357 * instead of O(rows(B) * nnz(A)). A column repeated in a row counts once (the rows of both matrices are sorted), as
358 * in mzd_from_csr(), which gives the dense matrices used for the logical operators (Lx_for_CSS_code()). */
359 csr_t * const AT = csr_transpose(NULL, A);
360 unsigned char * const par = calloc((size_t)A->rows + 1, 1); /* bit 0: the parity, bit 1: touched by the row b */
361 int * const touched = malloc(((size_t)A->rows + 1) * sizeof(int));
362 if (!par || !touched)
363 ERROR("memory allocation");
364 int nonzero = 0;
365 for (int i = 0; (i < B->rows) && !nonzero; i++) {
366 int nt = 0;
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]))
370 continue;
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]))
374 continue;
375 if (!(par[r] & 2)) {
376 par[r] = 2;
377 touched[nt++] = r;
378 }
379 par[r] ^= 1;
380 }
381 }
382 for (int t = 0; t < nt; t++) {
383 nonzero |= par[touched[t]] & 1;
384 par[touched[t]] = 0;
385 }
386 }
387 free(touched);
388 free(par);
389 csr_free(AT);
390 return nonzero;
391}
392
396int syndrome_bit_count(const mzd_t * const row, const csr_t * const spaQ){
397 int wei=0;
398 int m=spaQ->rows;
399 // mzd_print(row);
400 for(int i=0;i<m;i++){
401 rci_t bit=0;
402 for (int j=spaQ->p[i]; j<spaQ->p[i+1]; j++){
403 // printf("##### here ######## m=%d j=%d %d\n",m,j,spaQ->i[j]);
404 /* printf("checking %d %d: %d\n",i,spaQ->i[j], */
405 /* mzd_read_bit(row, 0,spaQ->i[j]) ? 1 : 0); */
406 bit ^= mzd_read_bit(row, 0,spaQ->i[j]);
407 }
408 wei+=bit;
409 // printf("wei=%d i=%d bit=%d \n",wei,i,bit);
410 }
411 return wei;
412}
413
419size_t product_weight_csr_mzd(const csr_t *A, const mzd_t *B, int transpose){
420 mzd_t *Prod;
421 mzd_t *mA=mzd_from_csr(NULL,A);
422 if (transpose){
423 mzd_t *BT=mzd_transpose(NULL,B);
424 Prod=mzd_mul_naive(NULL,mA,BT);
425 mzd_free(BT);
426 }
427 else
428 Prod=mzd_mul_naive(NULL,mA,B);
429 mzd_free(mA);
430 // mzd_print(Prod); printf("\n");
431 size_t wei=mzd_weight(Prod);
432 mzd_free(Prod);
433 return wei;
434}
435
439int rand_uniform(const int max){
440#if 1
441 int divisor = RAND_MAX/(max);
442 int retval;
443 do
444 retval = rand() / divisor;
445 while (retval >= max);
446 return retval;
447#else
448 return (int) floor(max * tinymt64_generate_double(&tinymt));
449#endif /* 0 */
450}
451
459mzp_t * mzp_rand_len(mzp_t *q, rci_t length){
460 if (q==NULL)
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++){
465 q->values[i]= i+rand_uniform(length-i);
466 }
467 for(int i=length-1; i< (q-> length); i++)
468 q->values[i]=i; /* no swap for the remaining columns */
469 return q;
470}
471
475void mzp_out(mzp_t const *p){
476 printf("[");
477 for(rci_t i=0;i<p->length;i++)
478 printf(" %d",p->values[i]);
479 printf(" ]\n");
480}
481
487mzp_t *perm_p(mzp_t *q, const mzp_t *p,rci_t start){
488 assert(p!=NULL);
489 if (q==NULL)
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]]);
497 return q;
498}
499
505mzp_t *perm_p_trans(mzp_t *q, const mzp_t *p,const rci_t start){
506 assert(p!=NULL);
507 if (q==NULL)
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]]);
515 return q;
516}
517
518
523 if(p!=NULL){
524 free(p->i);
525 free(p->p);
526 p->nzmax=0;
527 p->nz=0;
528 p->rows=0;
529 p->cols=0;
530 free(p);
531 }
532 return NULL;
533}
534
539csr_t *csr_init(csr_t *mat, int rows, int cols, int nzmax){
540 if ((mat!=NULL)&&((mat->nzmax < nzmax)||(mat->nzmax < rows+1))){
541 // mat=csr_free(mat); /* allocated size was too small */
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",
547 rows,cols,nzmax);
548 mat->nzmax=nzmax;
549 }
550 else if(mat==NULL){
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",
556 rows,cols,nzmax);
557 mat->nzmax=nzmax;
558 }
559 mat->rows=rows;
560 mat->cols=cols;
561 mat->nz=0; /* empty */
562 return mat;
563}
564
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
569#include "sort.h"
570
575 int nz=mat->nz;
576 if(nz==-1)
577 ERROR("matrix already compressed");
578 int_pair *pairs=calloc(nz,sizeof(int_pair));
579 for(int i=0;i<nz;i++){
580 pairs[i].a=mat->p[i];
581 pairs[i].b=mat->i[i];
582 }
583 int_pair_quick_sort(pairs, nz);
584 int i, j=0;
585 for(i=0;i<mat->rows;i++){
586 mat->p[i]=j;
587 while ((j<nz)&&(pairs[j].a == i)){
588 mat->i[j]=pairs[j].b;
589 j++;
590 }
591 }
592 mat->p[i]=j; /* final value */
593 mat->nz=-1; /* indicate compressed form */
594 free(pairs);
595}
596
597csr_t * csr_from_pairs(csr_t *mat, const int nz, int_pair * const prs, const int nrows, const int ncols){
598 mat = csr_init(mat, nrows, ncols, nz);
599 int_pair_quick_sort(prs, nz);
600 int i, j=0;
601 for(i=0; i < nrows; i++){
602 mat->p[i]=j;
603 while ((j<nz) && (prs[j].a == i)){
604 mat->i[j]=prs[j].b;
605 j++;
606 }
607 }
608 mat->p[i]=j; /* final value */
609 mat->nz=-1; /* indicate compressed form */
610 return mat;
611}
612
616void csr_out(const csr_t *mat){
617 int nz=mat->nz;
618 if(nz==-1){
619 printf("# binary CSR matrix (%d x %d) in Compressed Row Form: "
620 "nzmax= %d, nz=%d\n",
621 mat->rows,mat->cols,mat->nzmax,mat->p[mat->rows]);
622 for(int i=0;i<mat->rows;i++){
623 printf("%d:",i+1);
624 for(int j=mat->p[i]; j < mat->p[i+1] ; j++)
625 printf(" %d",mat->i[j]+1);
626 printf("\n");
627 }
628 }
629 else{
630 printf("# binary CSR matrix (%d x %d) in Pair Form: "
631 "nzmax= %d, nz=%d\n",
632 mat->rows,mat->cols,mat->nzmax,mat->nz);
633 for(int i=0;i<mat->nz;i++)
634 printf("%d %d\n",mat->p[i]+1,mat->i[i]+1);
635 }
636}
637
638void csr_print(const csr_t * const smat, const char str[]){
639 mzd_t *mH0 = mzd_from_csr(NULL,smat);
640 if(str)
641 printf("matrix %s:\n",str);
642 else
643 printf("matrix:\n");
644 mzd_print(mH0);
645 mzd_free(mH0);
646}
647
648
649
655csr_t *csr_mm_read(char *fin, csr_t *mat, int transpose){
656 int ret_code;
657 MM_typecode matcode;
658 FILE *f;
659 int M, N, nz;
660
661 if ((f = fopen(fin, "r")) == NULL)
662 ERROR("can't open file %s",fin);
663
664 if (mm_read_banner(f, &matcode) != 0)
665 ERROR("Could not process Matrix Market banner.");
666
667 if (!mm_is_matrix(matcode))
668 ERROR("Only Matrix Market 'matrix' object is supported.");
669
670 if (!mm_is_integer(matcode) && !mm_is_pattern(matcode)) {
671 ERROR("Only integer or pattern matrices are supported. Found: %s", mm_typecode_to_str(matcode));
672 }
673
674 if (!mm_is_general(matcode) && !mm_is_symmetric(matcode)) {
675 ERROR("Only general or symmetric matrices are supported. Found: %s", mm_typecode_to_str(matcode));
676 }
677
678 /* find out size of matrix .... */
679 if (mm_is_coordinate(matcode)) {
680 if ((ret_code = mm_read_mtx_crd_size(f, &M, &N, &nz)) != 0)
681 ERROR("Cannot read coordinate size in input file %s", fin);
682 } else { // array (dense)
683 if ((ret_code = mm_read_mtx_array_size(f, &M, &N)) != 0)
684 ERROR("Cannot read array size in input file %s", fin);
685 if (mm_is_symmetric(matcode)) {
686 nz = M * M;
687 } else {
688 nz = M * N;
689 }
690 }
691
692 int nzmax;
693 if (mm_is_coordinate(matcode)) {
694 if (mm_is_symmetric(matcode)) {
695 nzmax = 2 * nz;
696 } else {
697 nzmax = nz;
698 }
699 } else { // array
700 if (mm_is_symmetric(matcode)) {
701 nzmax = M * M;
702 } else {
703 nzmax = M * N;
704 }
705 }
706
707 int rows = M;
708 int cols = N;
709 if (transpose) {
710 rows = N;
711 cols = M;
712 }
713
714 mat = csr_init(mat, rows, cols, nzmax);
715 int k = 0;
716
717 if (mm_is_coordinate(matcode)) {
718 for (int i = 0; i < nz; i++) {
719 int r, c;
720 int v = 1; // default for pattern
721 if (mm_is_integer(matcode)) {
722 if (fscanf(f, "%d %d %d\n", &r, &c, &v) != 3) {
723 ERROR("Failed to read coordinate entry %d in %s", i, fin);
724 }
725 } else { // pattern
726 if (fscanf(f, "%d %d\n", &r, &c) != 2) {
727 ERROR("Failed to read pattern entry %d in %s", i, fin);
728 }
729 }
730 r--; c--; // 1-based to 0-based
731
732 if (v % 2 != 0) {
733 int r_store = transpose ? c : r;
734 int c_store = transpose ? r : c;
735 mat->p[k] = r_store;
736 mat->i[k] = c_store;
737 k++;
738
739 if (mm_is_symmetric(matcode) && r != c) {
740 mat->p[k] = c_store;
741 mat->i[k] = r_store;
742 k++;
743 }
744 }
745 }
746 } else { // array (dense)
747 if (mm_is_general(matcode)) {
748 for (int c = 0; c < N; c++) {
749 for (int r = 0; r < M; r++) {
750 int v;
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);
753 }
754 if (v % 2 != 0) {
755 int r_store = transpose ? c : r;
756 int c_store = transpose ? r : c;
757 mat->p[k] = r_store;
758 mat->i[k] = c_store;
759 k++;
760 }
761 }
762 }
763 } else if (mm_is_symmetric(matcode)) {
764 for (int c = 0; c < N; c++) {
765 for (int r = c; r < M; r++) {
766 int v;
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);
769 }
770 if (v % 2 != 0) {
771 int r_store = transpose ? c : r;
772 int c_store = transpose ? r : c;
773 mat->p[k] = r_store;
774 mat->i[k] = c_store;
775 k++;
776
777 if (r != c) {
778 mat->p[k] = c_store;
779 mat->i[k] = r_store;
780 k++;
781 }
782 }
783 }
784 }
785 }
786 }
787
788 mat->nz = k;
789 csr_compress(mat); /* sort entries by row and remove duplicates */
790 fclose(f);
791 return mat;
792}
793
794
798csr_t *csr_apply_perm(csr_t *dst, const csr_t * const src, const mzp_t * const perm){
799 int m=src->rows, n=src->cols;
800 if (src->nz!=-1)
801 ERROR("pair format unsupported, nz=%d; expected \"-1\"",src->nz);
802 int nz=src->p[m];
803 if(src->cols != perm-> length)
804 ERROR("perm length=%d should match cols=%d",perm->length,src->cols);
805 if (dst == NULL)
806 dst = csr_init(dst,m,n,nz);
807 else if ((dst->rows != m) || (dst->cols != n) || (nz > dst->nzmax))
808 ERROR("Wrong size for return matrix.\n");
809 for(int i=0;i<m;i++)
810 for(int j=src->p[i]; j < src->p[i+1] ; j++){
811 dst->p[j]=i; // pair format, to be compressed later
812 dst->i[j]= perm->values[src->i[j]];
813 // printf("row %d: mapping %d to %d\n",i,src->i[j],perm->values[src->i[j]]);
814 }
815 dst->nz=nz;
816 // csr_out(dst);
817 csr_compress(dst);
818 //csr_out(dst);
819 return dst;
820}
821
822
823
831
832int do_reduce(mzd_t *row, const mzd_t *matG0, const rci_t rankG0){
833 word * const rawrow = mzd_row(row,0);
834 rci_t j=-1;
835 rci_t n=row->ncols;
836 do{
837 j=nextelement(rawrow,row->width,j);
838 if(j==-1) // empty line after simplification
839 return j;
840 else if (j<rankG0)
841 mzd_combine_even_in_place(row,0,0,matG0,j,0);
842 } while (j < rankG0);
843 if (j<n)
844 return j;
845 return -1;
846}
847
848static inline uint64_t rotl(const uint64_t x, int k) {
849 return (x << k) | (x >> (64 - k));
850}
851
852/*** see arXiv:1805.01407 on fast RNGs ****
853
854uint64_t s[4];
855const int A=17, B=45, S=5, R=7, T=9;
856const uint64_t result_plus = s[0] + s[3];
857const uint64_t result_starstar = rotl(s[1] * S, R) * T;
858const uint64_t t = s[1] << A;
859s[2] ^= s[0];
860s[3] ^= s[1];
861s[1] ^= s[2];
862s[0] ^= s[3];
863s[2] ^= t;
864s[3] = rotl(s[3], B);
865*/
866
867/*
868 * generate binary error vector with error probability p
869 */
870void make_err(mzd_t *row, double p){
871 // const int max=MIN(10000,RAND_MAX);
872 const int cutoff=p*RAND_MAX;
873 if (row==NULL)
874 ERROR("make_err: row vector must be allocated to correct size!");
875 // mzd_set_ui(row,0);
876 // printf(" rows=%d cols=%d\n",row->nrows,row->ncols);
877 for(rci_t i = 0; i < row->nrows; ++i){
878 mzd_row_clear_offset(row,i,0);
879 printf("i=%d\n",i); // mzd_print(row);
880 for(rci_t j = 0; j < row->ncols; ++j){
881 // printf("%d %d\t",j,rand_uniform(max));
882 if (rand()<cutoff)
883 mzd_write_bit(row,i,j,1);
884 // printf("%d %d -> %d %d\n",i,j,mzd_read_bit(row,i,j),cutoff);
885 }
886 // mzd_print(row);
887 }
888}
889
890
899csr_t * csr_from_mzd(csr_t *mat, const mzd_t * const orig){
900 int nz=mzd_weight(orig);
901 mat = csr_init(mat, orig->nrows, orig->ncols, nz);
902 int i, j=0;
903 for(i=0;i < mat->rows; i++){
904 mat->p[i]=j;
905#if 1
906 int idx=0;
907 const word * const rawrow = mzd_row_cons(orig,i);
908 while(((idx=nextelement(rawrow,orig->width,idx))!=-1)&&(idx<orig->ncols)){
909 mat->i[j++]=idx++;
910 }
911#else
912 for(int idx=0; idx< orig->ncols; idx++)
913 if(mzd_read_bit(orig,i,idx)){
914 mat->i[j++]=idx;
915 // printf("i=%d j=%d idx=%d\n",i,j,idx);
916 }
917#endif /* 0 */
918 }
919 mat->p[i]=j; /* final value */
920 assert(j==nz);
921 mat->nz=-1; /* indicate compressed form */
922 return mat;
923}
924
933
934csr_t * Lx_for_CSS_code(const csr_t * const Hx, const csr_t *const Hz){
935 rci_t n=Hx->cols;
936 if(n!=Hz->cols)
937 ERROR("unequal number of columns in matrices Hx[%d,%d] and Hz[%d,%d]",
938 Hx->rows, Hx->cols, Hz->rows, Hz->cols);
939 mzd_t *Mx = mzd_from_csr(NULL,Hx); /* convert to dense matrix */
940 mzp_t *pivots = mzp_init(n); /* initialize the permutation */
941 rci_t rank = mzd_gauss_naive(Mx, pivots, 1);
942 mzd_apply_p_right_trans(Mx,pivots);
943 mzp_t *perm = perm_p( NULL, pivots,0);
944 mzp_t *permT = perm_p_trans(NULL, pivots,0);
945 mzp_free(pivots);
946 csr_t* HzPerm=csr_apply_perm(NULL,Hz,permT);
947 mzp_free(permT);
948#ifndef NDEBUG
949 mzd_t *MxT = mzd_transpose(NULL,Mx);
950 if(product_weight_csr_mzd(HzPerm,MxT,0))
951 ERROR("rows of Hx and Hz should be orthogonal ");
952 mzd_free(MxT);
953#endif
954 mzd_t *MzStar = mzd_generator_from_csr(NULL, HzPerm);
955 csr_free(HzPerm);
956
957 mzd_t *mat = mzd_stack(NULL,Mx,MzStar);
958 mzd_free(MzStar);
959 // printf("stacked:\n"); mzd_print(mat);
960 int rank1=mzd_echelonize(mat,0);
961 // printf("after gauss %d -> %d:\n", rank, rank1); mzd_print(mat);
962
963 mzd_t *window = mzd_init_window(mat,rank,0,rank1,n);
964 csr_t *Lx=csr_from_mzd(NULL, window);
965 csr_t *ans = csr_apply_perm(NULL,Lx,perm);
966 mzd_free(Mx);
967 csr_free(Lx);
968 mzd_free(window);
969 mzp_free(perm);
970 mzd_free(mat);
971 return ans;
972}
973
974mzd_t * mzd_nullspace(const csr_t * const H) {
975 if (!H) return NULL;
976 mzd_t *mH = mzd_from_csr(NULL, H);
977 mzd_t *X = mzd_kernel_left_pluq(mH, 0);
978 mzd_free(mH);
979 if (!X) return NULL;
980 mzd_t *N = mzd_transpose(NULL, X);
981 mzd_free(X);
982 return N;
983}
984
985colmask_t * colmask_from_csr(const csr_t * const A) {
986 if (!A || A->nz != -1) ERROR("expected a sparse matrix in CSR form");
987 colmask_t *cm = malloc(sizeof(colmask_t));
988 if (!cm) ERROR("memory allocation");
989 cm->rows = A->rows;
990 cm->cols = A->cols;
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; /* duplicate entries cancel */
999 }
1000 return cm;
1001}
1002
1004 if (cm) {
1005 free(cm->mask);
1006 free(cm);
1007 }
1008 return NULL;
1009}
1010
1011cols_ws_t * cols_ws_init(const int m) {
1012 cols_ws_t *ws = calloc(1, sizeof(cols_ws_t));
1013 if (!ws) ERROR("memory allocation");
1014 ws->m = m;
1015 ws->rmap = malloc((size_t)(m > 0 ? m : 1) * sizeof(int));
1016 ws->rlist = malloc((size_t)(m > 0 ? m : 1) * sizeof(int));
1017 if (!ws->rmap || !ws->rlist) ERROR("memory allocation");
1018 for (int r = 0; r < m; r++) ws->rmap[r] = -1;
1019 return ws;
1020}
1021
1023 if (ws) {
1024 free(ws->rmap);
1025 free(ws->rlist);
1026 free(ws->bits);
1027 free(ws);
1028 }
1029 return NULL;
1030}
1031
1032/* The rows of H touched by the columns cols[0..cnt-1], numbered in ws->rmap (ws->rlist: the rows); returns their
1033 * number. The caller restores rmap with cols_ws_clear(). */
1034static int cols_ws_rows(const csr_t * const HT, const int cnt, const int cols[], cols_ws_t * const ws) {
1035 int nr = 0;
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) {
1040 ws->rmap[r] = nr;
1041 ws->rlist[nr++] = r;
1042 }
1043 }
1044 }
1045 return nr;
1046}
1047
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;
1050}
1051
1052/* cnt rows of `stride` words in ws->bits, set to zero; the column i in the first words of row i (its bits: the rows
1053 * touched, see cols_ws_rows()) */
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) {
1058 free(ws->bits);
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");
1062 }
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); /* duplicate entries cancel */
1069 }
1070 }
1071 return M;
1072}
1073
1074/* Gaussian elimination of the cnt rows of M (`stride` words each) on their first nr bits; returns the rank, the
1075 * independent rows first. Rows rank..cnt-1 are then zero in the first nr bits (the other words of the rows, e.g.,
1076 * the tracked combinations, are transformed alike). */
1077static int cols_ws_eliminate(word * const M, const int cnt, const int nr, const size_t stride) {
1078 int rank = 0;
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);
1082 int piv = -1;
1083 for (int i = rank; i < cnt; i++) {
1084 if (M[(size_t)i * stride + wb] & mb) {
1085 piv = i;
1086 break;
1087 }
1088 }
1089 if (piv < 0) continue;
1090 word * const pr = M + (size_t)rank * stride;
1091 if (piv != rank) {
1092 word * const qr = M + (size_t)piv * stride;
1093 for (size_t x = 0; x < stride; x++) {
1094 const word t = pr[x];
1095 pr[x] = qr[x];
1096 qr[x] = t;
1097 }
1098 }
1099 /* (the rows rank.. are zero in the bits below b, so that the words below wb need no update) */
1100 for (int i = rank + 1; i < cnt; i++) {
1101 word * const ri = M + (size_t)i * stride;
1102 if (ri[wb] & mb)
1103 for (size_t x = wb; x < stride; x++) ri[x] ^= pr[x];
1104 }
1105 rank++;
1106 }
1107 return rank;
1108}
1109
1110int csr_cols_rank(const csr_t * const HT, const int cnt, const int cols[], cols_ws_t * const ws) {
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);
1114 int rank = 0;
1115 if (nw > 0) {
1116 word * const M = cols_ws_matrix(HT, cnt, cols, ws, nw);
1117 rank = cols_ws_eliminate(M, cnt, nr, nw);
1118 }
1119 cols_ws_clear(ws, nr);
1120 return rank;
1121}
1122
1123int csr_cols_dependency(const csr_t * const HT, const int cnt, const int cols[], cols_ws_t * const ws, int sub[]) {
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; /* the column on the rows touched, then the combination of the columns */
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);
1132 /* the rows rank..cnt-1: a basis of the kernel (their combinations have zero sums); one of them is neither zero nor
1133 * the all-ones vector if the kernel has dimension at least 2 */
1134 for (int i = rank; i < cnt; i++) {
1135 const word * const t = M + (size_t)i * stride + nw;
1136 int k = 0;
1137 for (int j = 0; j < cnt; j++)
1138 if ((t[j >> 6] >> (j & 63)) & 1) k++;
1139 if (k == 0 || k == cnt) continue;
1140 k = 0;
1141 for (int j = 0; j < cnt; j++)
1142 if ((t[j >> 6] >> (j & 63)) & 1) sub[k++] = cols[j];
1143 return k;
1144 }
1145 return 0;
1146}
1147
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);
1153}
1154
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);
1158}
1159
1160void localized_window_perm(mzp_t *perm, int nvar, int seed_col, int kwin, int win_mode,
1161 const csr_t *spaH, const csr_t *mHT,
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]);
1169 }
1170 return;
1171 }
1172
1173 (*visit_marker)++;
1174 int marker = *visit_marker;
1175 if (marker <= 0) {
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));
1179 }
1180 *visit_marker = marker = 1;
1181 }
1182
1183 int count = 0;
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;
1189
1190 while (count < kwin) {
1191 if (head < tail) {
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;
1203 }
1204 }
1205 }
1206 }
1207 } else {
1208 int r_start = util_rand_uniform(nvar, rng_state);
1209 int found = -1;
1210 for (int offset = 0; offset < nvar; offset++) {
1211 int cand = (r_start + offset) % nvar;
1212 if (visited_cols[cand] != marker) {
1213 found = cand;
1214 break;
1215 }
1216 }
1217 if (found == -1) break;
1218 visited_cols[found] = marker;
1219 col_queue[tail++] = found;
1220 perm->values[count++] = found;
1221 }
1222 }
1223 } else {
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;
1228 }
1229 }
1230
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]);
1235 }
1236
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;
1241 }
1242 }
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]);
1246 }
1247}
1248
1249void refresh_nullspace_basis(mzd_t *N, const int *cw_arr, int cw_wt, uint64_t *rng_state) {
1250 if (!N || N->nrows == 0 || N->ncols == 0) return;
1251 const rci_t nu = N->nrows;
1252 const rci_t n = N->ncols;
1253
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);
1260 free(piv_cols);
1261 return;
1262 }
1263
1264 for (int i = 0; i <= (int)n - 2; i++) {
1265 pivs->values[i] = i + util_rand_uniform(n - i, rng_state);
1266 }
1267 pivs->values[n - 1] = n - 1;
1268
1269 mzp_set_ui(perm, 1);
1270 perm = perm_p_trans(perm, pivs, 0);
1271
1272 rci_t rank = 0;
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;
1277 }
1278 }
1279
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) {
1287 size_t r_wt = mzd_weight_row(N, r);
1288 if (r_wt > (size_t)cw_wt && r_wt > max_row_wt) {
1289 max_row_wt = r_wt;
1290 target_row = r;
1291 }
1292 break;
1293 }
1294 }
1295 }
1296 }
1297
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);
1303 }
1304 }
1305 }
1306
1307 free(piv_cols);
1308 mzp_free(perm);
1309 mzp_free(pivs);
1310}
1311
1312int csr_all_ones_in_rowspan(const csr_t * const H) {
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");
1317 int covered = 0;
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]) {
1321 has_nz[c] = 1;
1322 covered++;
1323 }
1324 }
1325 free(has_nz);
1326 if (covered < n) return 0;
1327 mzd_t * const mH = mzd_from_csr(NULL, H);
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);
1332 mzd_free(mH);
1333 mzd_free(m1);
1334 const rci_t rank_Aug = mzd_echelonize(mAug, 0);
1335 mzd_free(mAug);
1336 return rank_Aug == rank_H;
1337}
char * mm_typecode_to_str(MM_typecode matcode)
Convert a Matrix Market typecode to a human-readable string.
Definition mmio.c:464
int mm_read_mtx_array_size(FILE *f, int *M, int *N)
Read dimensions for an array (dense) matrix.
Definition mmio.c:229
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.
Definition mmio.c:198
int mm_read_banner(FILE *f, MM_typecode *matcode)
Read the Matrix Market banner from a file.
Definition mmio.c:105
char MM_typecode[4]
Definition mmio.h:16
#define mm_is_matrix(typecode)
Definition mmio.h:90
#define mm_is_coordinate(typecode)
Definition mmio.h:93
#define mm_is_pattern(typecode)
Definition mmio.h:99
#define mm_is_general(typecode)
Definition mmio.h:103
#define mm_is_integer(typecode)
Definition mmio.h:100
#define mm_is_symmetric(typecode)
Definition mmio.h:102
#define MAX(x, y)
Definition sort.h:54
word * mask
Definition util_m4ri.h:142
int * rmap
Definition util_m4ri.h:152
size_t cap
Definition util_m4ri.h:155
word * bits
Definition util_m4ri.h:154
int * rlist
Definition util_m4ri.h:153
int nz
Definition util_m4ri.h:123
int nzmax
Definition util_m4ri.h:124
int * p
Definition util_m4ri.h:125
int * i
Definition util_m4ri.h:126
int rows
Definition util_m4ri.h:121
int cols
Definition util_m4ri.h:122
params_t *const p
Definition util_io.c:93
params_t prm
Definition util_io.c:8
mzd_t * mzd_nullspace(const csr_t *const H)
Compute the null space basis N = ker(H) of dimension nu x n.
Definition util_m4ri.c:974
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.
Definition util_m4ri.c:1011
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.
Definition util_m4ri.c:396
colmask_t * colmask_free(colmask_t *cm)
Free the column masks allocated by colmask_from_csr().
Definition util_m4ri.c:1003
cols_ws_t * cols_ws_free(cols_ws_t *ws)
Free the workspace allocated by cols_ws_init().
Definition util_m4ri.c:1022
mzp_t * mzp_rand_len(mzp_t *q, rci_t length)
Generate a random permutation of a given length in-place.
Definition util_m4ri.c:459
csr_t * csr_from_mzd(csr_t *mat, const mzd_t *const orig)
convert m4ri dense matrix to csr
Definition util_m4ri.c:899
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.
Definition util_m4ri.c:342
void make_err(mzd_t *row, double p)
Generate a random binary error vector with error probability p.
Definition util_m4ri.c:870
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.
Definition util_m4ri.c:1110
mzd_t * syndrome_vector(mzd_t *syndrome, mzd_t *row, csr_t *spaQ, int clear)
Calculate syndrome vector change.
Definition util_m4ri.c:314
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.
Definition util_m4ri.c:55
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.
Definition util_m4ri.c:597
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.
Definition util_m4ri.c:213
csr_t * csr_transpose(csr_t *dst, const csr_t *const p)
Transpose a compressed CSR sparse matrix.
Definition util_m4ri.c:163
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.
Definition util_m4ri.c:655
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.
Definition util_m4ri.c:934
csr_t * csr_init(csr_t *mat, int rows, int cols, int nzmax)
Initialize or reallocate a CSR sparse matrix to target size.
Definition util_m4ri.c:539
mzd_t * mzd_from_csr(mzd_t *dst, const csr_t *p)
Convert a CSR sparse matrix to an MZD dense matrix.
Definition util_m4ri.c:186
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.
Definition util_m4ri.c:505
int do_reduce(mzd_t *row, const mzd_t *matG0, const rci_t rankG0)
Reduce a row vector against a matrix in standard form.
Definition util_m4ri.c:832
void csr_out(const csr_t *mat)
Print raw contents of a CSR matrix to stdout.
Definition util_m4ri.c:616
void csr_print(const csr_t *const smat, const char str[])
Print a CSR matrix with a label string (formatted output).
Definition util_m4ri.c:638
csr_t * csr_free(csr_t *p)
Free memory allocated for a CSR sparse matrix.
Definition util_m4ri.c:522
void csr_compress(csr_t *mat)
Compress CSR matrix (sort indices and remove duplicates/zeros).
Definition util_m4ri.c:574
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
Definition util_m4ri.c:145
rci_t mzd_gauss_naive(mzd_t *M, mzp_t *q, int full)
Perform Gaussian elimination (naive) and return pivot column list.
Definition util_m4ri.c:104
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.
Definition util_m4ri.c:1160
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...
Definition util_m4ri.c:1249
colmask_t * colmask_from_csr(const csr_t *const A)
Construct the column bit masks of a sparse binary matrix (see colmask_t).
Definition util_m4ri.c:985
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).
Definition util_m4ri.c:1312
size_t mzd_weight(const mzd_t *A)
Compute the number of set bits (Hamming weight) in a dense matrix A.
Definition util_m4ri.c:74
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.
Definition util_m4ri.c:487
void addto(mzd_t *row, const csr_t *spaQ, const int i)
Definition util_m4ri.c:280
void mzp_out(mzp_t const *p)
Print the permutation to stdout.
Definition util_m4ri.c:475
size_t mzd_weight_naive(const mzd_t *A)
Naive implementation to compute the Hamming weight of a dense matrix A.
Definition util_m4ri.c:46
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.
Definition util_m4ri.c:257
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.
Definition util_m4ri.c:419
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.
Definition util_m4ri.c:798
int rand_uniform(const int max)
Return a uniformly distributed random integer in the range [0, max-1].
Definition util_m4ri.c:439
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.
Definition util_m4ri.c:1123
#define ERROR(fmt,...)
Definition util_m4ri.h:13
#define SWAPINT(a, b)
Definition util_m4ri.h:11