Dist m4ri 0.0.1.alpha
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 <ctype.h>
11#include "mmio.h"
12
13#include "util_m4ri.h"
14
15
16size_t mzd_weight_naive(const mzd_t *A){
17 size_t count = 0;
18 for(rci_t i = 0; i < A->nrows; ++i)
19 for(rci_t j = 0; j < A->ncols; ++j)
20 if(mzd_read_bit(A, i, j))
21 ++count;
22 return (count);
23}
24
25size_t mzd_weight_row(const mzd_t * const A, const rci_t i){
26 size_t count = 0;
27 assert(i >=0 && i < A->nrows);
28 if(A->width == 1) {
29 for(rci_t j = 0; j < A->ncols; ++j)
30 if(mzd_read_bit(A, i, j))
31 ++count;
32 return (count);
33 }
34 const word * const truerow = mzd_row_cons(A,i);
35 for(wi_t j = 0; j < A->width - 1; j ++){
36 count += m4ri_bitcount(truerow[j]);
37 }
38 for(rci_t j = m4ri_radix * (A-> width - 1) ; j < A->ncols ; ++j)
39 if(mzd_read_bit(A, i, j))
40 ++count;
41 return count ;
42}
43
44size_t mzd_weight(const mzd_t *A){
45 size_t count = 0;
46 if(A->width == 1) {
47 for(rci_t i = 0; i < A->nrows; ++i)
48 for(rci_t j = 0; j < A->ncols; ++j)
49 if(mzd_read_bit(A, i, j))
50 ++count;
51 return (count);
52 }
53 for(rci_t i = 0; i < A->nrows; ++i) {
54 const word * const truerow = mzd_row_cons(A,i);
55 for(wi_t j = 0; j < A->width - 1; j ++){
56 count += m4ri_bitcount(truerow[j]);
57 // count += std_bitcount(truerow[j]);
58 // printf(" %d",std_bitcount(truerow[j]));
59 }
60 for(rci_t j = m4ri_radix * (A-> width - 1) ; j < A->ncols ; ++j)
61 if(mzd_read_bit(A, i, j))
62 ++count;
63 }
64 // printf(" count=%d\n",count);
65 return count ;
66}
67
68
74rci_t mzd_gauss_naive(mzd_t *M, mzp_t *q, int full) {
75 rci_t startcol=0, startrow = 0;
76 rci_t pivots = 0;
77#if 0
78 if (q==NULL)
79 q=mzp_init(M->ncols);
80 else {
81 if ((q->length)!=M->ncols){
82 mzp_free(q);
83 q=mzp_init(M->ncols);
84 }
85 else
86 mzp_set_ui(q,1);
87 }
88#endif
89
90 for (rci_t i = startcol; i < M->ncols ; ++i) {
91 for(rci_t j = startrow ; j < M->nrows; ++j) {
92 if (mzd_read_bit(M, j, i)) {
93 mzd_row_swap(M, startrow, j);
94 q->values[pivots]=i; /* request cols swap: pivots <--> i */
95 ++pivots;
96 for(rci_t ii = full ? 0 : startrow + 1; ii < M->nrows; ++ii) {
97 if (ii != startrow) {
98 if (mzd_read_bit(M, ii, i)) {
99 mzd_row_add_offset(M, ii, startrow, i);
100 }
101 }
102 }
103 startrow = startrow + 1;
104 break;
105 }
106 }
107 }
108 return pivots;
109}
110
115int csr_max_row_wght(const csr_t * const p){
116 int m=p->rows;
117 int wmax=0;
118 for(int i=0;i<m;i++){
119 int w=(p->p[i+1])-(p->p[i]);
120 if (w>wmax)
121 wmax=w;
122 }
123 return wmax;
124}
125
126
133csr_t * csr_transpose(csr_t *dst, const csr_t * const p){
134 int rows=p->rows, cols=p->cols, nz=p->p[rows];
135 if (dst == NULL)
136 dst = csr_init(NULL,cols,rows,nz);
137 else if ((dst->cols != rows) || (dst->rows != cols) || (dst->nzmax < MAX(nz, cols+1)))
138 ERROR("Wrong size for return matrix.\n");
139 else
140 dst->nz=0; /* clear matrix */
141 for(int i=0;i<rows;i++)
142 for(int j=p->p[i]; j < p->p[i+1] ; j++){
143 dst->p[j]=p->i[j]; // pair format, to be compressed later
144 dst->i[j]=i ;
145 }
146 dst->nz=nz;
147 csr_compress(dst);
148 return dst;
149}
150
151
156mzd_t *mzd_from_csr(mzd_t *dst, const csr_t *p) {
157 int m=p->rows, n=p->cols, nz=p->nz;
158 if (dst == NULL)
159 dst = mzd_init(m,n);
160 else if ((dst->nrows != m) || (dst->ncols != n))
161 ERROR("Wrong size for return matrix.\n");
162 else
163 mzd_set_ui(dst,0); /* clear bits */
164
165 if(nz==-1){ // binary CSR matrix in Compressed Row Form
166 for(int i=0;i<m;i++)
167 for(int j=p->p[i]; j < p->p[i+1] ; j++)
168 mzd_write_bit(dst, i, p->i[j], 1);
169 }
170 else{ // binary CSR matrix in Pair Form
171 for(int i=0;i<p->nz;i++)
172 mzd_write_bit(dst, p->p[i],p->i[i],1);
173 }
174 return dst;
175}
176
183mzd_t *mzd_generator_from_csr(mzd_t *G, const csr_t * const H){
184 rci_t n=H->cols;
185 mzd_t *mat=mzd_from_csr(NULL,H); /* convert to dense matrix */
186 mzp_t * pivots = mzp_init(n); /* initialize the permutation */
187 rci_t ra = mzd_gauss_naive(mat, pivots, 1);
188#if 0
189 if ((prm.debug & 2048) && (n<=80)){
190 mzd_print(mat);
191 mzp_out(pivots);
192 printf("\n");
193 }
194#endif
195 /* now we can check if G is the right size and reallocate if needed */
196 if ((G!=NULL) && ((G->ncols!=n) || (G->nrows!=n-ra))){
197 mzd_free(G);
198 G=NULL;
199 }
200 if (G==NULL)
201 G=mzd_init(n-ra,n);
202 else
203 mzd_set_ui(G,0); /* clear the matrix */
204 mzd_apply_p_right_trans(mat,pivots); /* permute columns to make std form [ I C ] */
205 mzd_t *matC = mzd_submatrix(NULL, mat, 0, ra, ra, n); /* C size ra by n-ra */
206 mzd_t * winCT=mzd_init_window(G,0,0,n-ra,ra);
207 mzd_transpose(winCT,matC);
208 mzd_free(winCT); /* window is no longer needed */
209 mzd_free(matC); /* \todo see why window does not seem to work here */
210 for(int i=0; i<n-ra ; i++)
211 mzd_write_bit(G,i,i+ra,1); /* identity matrix on the right */
212
213 mzd_apply_p_right(G,pivots); /* permute columns back */
214 mzp_free(pivots);
215 mzd_free(mat);
216 return G;
217}
218
219
224mzd_t * csr_mzd_mul(mzd_t *C, const csr_t *S, const mzd_t *B, int clear){
225 if (S->cols != B->nrows)
226 ERROR("column dim of S and row dim of B should match, %d=%d",S->cols,B->nrows);
227 if (C == NULL)
228 C = mzd_init(S->rows, B->ncols);
229 else {
230 if (C->nrows != S->rows || C->ncols != B->ncols)
231 ERROR("Provided return matrix has wrong dimensions.\n");
232 if(clear)
233 mzd_set_ui(C,0);
234 }
235 rci_t const m = S->rows;
236
237 for(rci_t i = 0; i < m; ++i)
238 for(int j=S->p[i]; j < S->p[i+1] ; j++)
239 mzd_combine(C,i,0, C,i,0, B,S->i[j],0); /* combine the two rows */
240 return C;
241}
242
247void addto(mzd_t *row, const csr_t *spaQ, const int i){
248#if 0
249 if (i>=spaQ->rows)
250 ERROR("addto: attempt to get row=%d of %d",i,spaQ->rows);
251 if (row->ncols != spaQ->cols)
252 ERROR("addto: column number mismatch");
253 // mzd_print(row);
254#endif
255 for (int j=spaQ->p[i]; j<spaQ->p[i+1]; j++)
256 mzd_flip_bit(row, 0,spaQ->i[j]); /* flip that bit */
257}
258
259
264static inline void addto_inline(mzd_t *row, const csr_t *spaQ, const int i){
265#ifndef NDEBUG
266 if (i>=spaQ->rows)
267 ERROR("addto: attempt to get row=%d of %d",i,spaQ->rows);
268 if (row->ncols != spaQ->cols)
269 ERROR("addto: column number mismatch");
270 // mzd_print(row);
271#endif
272 for (int j=spaQ->p[i]; j<spaQ->p[i+1]; j++)
273 mzd_flip_bit(row, 0,spaQ->i[j]); /* flip that bit */
274}
275
276
281mzd_t * syndrome_vector(mzd_t *syndrome, mzd_t *row, csr_t *spaQ, int clear){
282 if (row->ncols != spaQ->rows)
283 ERROR("column dim of row and row dim of spaQ should match, %d=%d",row->ncols,spaQ->rows);
284 if (syndrome == NULL)
285 syndrome = mzd_init(row->nrows, spaQ->cols);
286 else {
287 if (syndrome->nrows != row->nrows || syndrome->ncols != spaQ->cols)
288 ERROR("Provided return matrix has wrong dimensions.\n");
289 if(clear)
290 mzd_set_ui(syndrome,0);
291 }
292 for (rci_t i=0; i< row->nrows; i++){
293 const word * const rawrow = mzd_row_cons(row,i);
294 rci_t j=-1;
295 rci_t n=row->ncols;
296 do{
297 j=nextelement(rawrow,row->width,j+1);
298 if((j==-1)||(j>=n)) // no more non-zero elements
299 break;
300 else
301 for (int j1=spaQ->p[j]; j1<spaQ->p[j+1]; j1++)
302 mzd_flip_bit(syndrome, i,spaQ->i[j1]); /* flip that bit */
303 }
304 while( TRUE);
305 }
306 return syndrome;
307}
308
309int csr_csr_mul_non_zero(const csr_t * const A, const csr_t * const B){
310 if(!A)
311 ERROR("matrix A is NULL");
312 if(A->nz != -1)
313 ERROR("matrix A shold be in compressed form");
314 if(!B)
315 ERROR("matrix B is NULL");
316 if(A->nz != -1)
317 ERROR("matrix B should be in compressed form");
318 if (A->cols != B->cols)
319 ERROR("col count mismatch: A[%d,%d] and B[%d,%d]",
320 A->rows,A->cols, B->rows, B->cols);
321
322 for(int i=0; i < B->rows; i++){
323 const int begr = B->p[i];
324 if(sparse_syndrome_non_zero(A,B->p[i+1] - begr, & (B->i[begr])))
325 return 1;
326 }
327 return 0;
328}
329
333int syndrome_bit_count(const mzd_t * const row, const csr_t * const spaQ){
334 int wei=0;
335 int m=spaQ->rows;
336 // mzd_print(row);
337 for(int i=0;i<m;i++){
338 rci_t bit=0;
339 for (int j=spaQ->p[i]; j<spaQ->p[i+1]; j++){
340 // printf("##### here ######## m=%d j=%d %d\n",m,j,spaQ->i[j]);
341 /* printf("checking %d %d: %d\n",i,spaQ->i[j], */
342 /* mzd_read_bit(row, 0,spaQ->i[j]) ? 1 : 0); */
343 bit ^= mzd_read_bit(row, 0,spaQ->i[j]);
344 }
345 wei+=bit;
346 // printf("wei=%d i=%d bit=%d \n",wei,i,bit);
347 }
348 return wei;
349}
350
356size_t product_weight_csr_mzd(const csr_t *A, const mzd_t *B, int transpose){
357 mzd_t *Prod;
358 mzd_t *mA=mzd_from_csr(NULL,A);
359 if (transpose){
360 mzd_t *BT=mzd_transpose(NULL,B);
361 Prod=mzd_mul_naive(NULL,mA,BT);
362 mzd_free(BT);
363 }
364 else
365 Prod=mzd_mul_naive(NULL,mA,B);
366 mzd_free(mA);
367 // mzd_print(Prod); printf("\n");
368 size_t wei=mzd_weight(Prod);
369 mzd_free(Prod);
370 return wei;
371}
372
376int rand_uniform(const int max){
377#if 1
378 int divisor = RAND_MAX/(max);
379 int retval;
380 do
381 retval = rand() / divisor;
382 while (retval >= max);
383 return retval;
384#else
385 return (int) floor(max * tinymt64_generate_double(&tinymt));
386#endif /* 0 */
387}
388
396mzp_t * mzp_rand_len(mzp_t *q, rci_t length){
397 if (q==NULL)
398 ERROR("permutation must be initialized!");
399 if (length>q->length)
400 ERROR("mzp_rand_len: second parameter too large, %d > %d", length, q->length);
401 for(int i=0;i<=length-2;i++){
402 q->values[i]= i+rand_uniform(length-i);
403 }
404 for(int i=length-1; i< (q-> length); i++)
405 q->values[i]=i; /* no swap for the remaining columns */
406 return q;
407}
408
412void mzp_out(mzp_t const *p){
413 printf("[");
414 for(rci_t i=0;i<p->length;i++)
415 printf(" %d",p->values[i]);
416 printf(" ]\n");
417}
418
424mzp_t *perm_p(mzp_t *q, const mzp_t *p,rci_t start){
425 assert(p!=NULL);
426 if (q==NULL)
427 q=mzp_init(p->length);
428 else if (p->length != q->length)
429 ERROR("mzp length mismatch %d and %d !\n", p->length , q->length);
430 rci_t length = p->length;
431 rci_t *perm = q->values;
432 for(rci_t i = start; i < length; ++i)
433 SWAPINT(perm[i], perm[p->values[i]]);
434 return q;
435}
436
442mzp_t *perm_p_trans(mzp_t *q, const mzp_t *p,const rci_t start){
443 assert(p!=NULL);
444 if (q==NULL)
445 q=mzp_init(p->length);
446 else if (p->length != q->length)
447 ERROR("mzp length mismatch %d and %d !\n", p->length , q->length);
448 rci_t length = p->length;
449 rci_t *perm = q->values;
450 for(rci_t i = start; i < length; ++i)
451 SWAPINT(perm[length-i-1], perm[p->values[length-i-1]]);
452 return q;
453}
454
455
460 if(p!=NULL){
461 free(p->i);
462 free(p->p);
463 p->nzmax=0;
464 p->nz=0;
465 p->rows=0;
466 p->cols=0;
467 free(p);
468 }
469 return NULL;
470}
471
476csr_t *csr_init(csr_t *mat, int rows, int cols, int nzmax){
477 if ((mat!=NULL)&&((mat->nzmax < nzmax)||(mat->nzmax < rows+1))){
478 // mat=csr_free(mat); /* allocated size was too small */
480 mat->p = realloc(mat->p,MAX(nzmax,(rows+1))*sizeof(int));
481 mat->i = realloc(mat->i, nzmax*sizeof(int));
482 if ((mat->p==NULL) || (mat->i==NULL))
483 ERROR("csr_init: failed to reallocate CSR rows=%d cols=%d nzmax=%d",
484 rows,cols,nzmax);
485 mat->nzmax=nzmax;
486 }
487 else if(mat==NULL){
488 mat=malloc(sizeof(csr_t));
489 mat->p=calloc(MAX(nzmax,(rows+1)),sizeof(int));
490 mat->i=calloc(nzmax,sizeof(int));
491 if ((mat == NULL) || (mat->p==NULL) || (mat->i==NULL))
492 ERROR("csr_init: failed to allocate CSR rows=%d cols=%d nzmax=%d",
493 rows,cols,nzmax);
494 mat->nzmax=nzmax;
495 }
496 mat->rows=rows;
497 mat->cols=cols;
498 mat->nz=0; /* empty */
499 return mat;
500}
501
502/* helper function */
503static int cmp_int_pairs(const void *p1, const void *p2){
504 if ((((int_pair *) p1)->a)!=(((int_pair *) p2)->a))
505 return ((((int_pair *) p1)->a)-(((int_pair *) p2)->a));
506 return ((((int_pair *) p1)->b)-(((int_pair *) p2)->b));
507}
508
513 int nz=mat->nz;
514 if(nz==-1)
515 ERROR("matrix already compressed");
516 int_pair *pairs=calloc(nz,sizeof(int_pair));
517 for(int i=0;i<nz;i++){
518 pairs[i].a=mat->p[i];
519 pairs[i].b=mat->i[i];
520 }
521 qsort(pairs,nz,sizeof(int_pair),cmp_int_pairs);
522 int i, j=0;
523 for(i=0;i<mat->rows;i++){
524 mat->p[i]=j;
525 while ((j<nz)&&(pairs[j].a == i)){
526 mat->i[j]=pairs[j].b;
527 j++;
528 }
529 }
530 mat->p[i]=j; /* final value */
531 mat->nz=-1; /* indicate compressed form */
532 free(pairs);
533}
534
535csr_t * csr_from_pairs(csr_t *mat, const int nz, int_pair * const prs, const int nrows, const int ncols){
536 mat = csr_init(mat, nrows, ncols, nz);
537 qsort(prs, nz, sizeof(int_pair), cmp_int_pairs);
538 int i, j=0;
539 for(i=0; i < nrows; i++){
540 mat->p[i]=j;
541 while ((j<nz) && (prs[j].a == i)){
542 mat->i[j]=prs[j].b;
543 j++;
544 }
545 }
546 mat->p[i]=j; /* final value */
547 mat->nz=-1; /* indicate compressed form */
548 return mat;
549}
550
554void csr_out(const csr_t *mat){
555 int nz=mat->nz;
556 if(nz==-1){
557 printf("# binary CSR matrix (%d x %d) in Compressed Row Form: "
558 "nzmax= %d, nz=%d\n",
559 mat->rows,mat->cols,mat->nzmax,mat->p[mat->rows]);
560 for(int i=0;i<mat->rows;i++){
561 printf("%d:",i+1);
562 for(int j=mat->p[i]; j < mat->p[i+1] ; j++)
563 printf(" %d",mat->i[j]+1);
564 printf("\n");
565 }
566 }
567 else{
568 printf("# binary CSR matrix (%d x %d) in Pair Form: "
569 "nzmax= %d, nz=%d\n",
570 mat->rows,mat->cols,mat->nzmax,mat->nz);
571 for(int i=0;i<mat->nz;i++)
572 printf("%d %d\n",mat->p[i]+1,mat->i[i]+1);
573 }
574}
575
576void csr_print(const csr_t * const smat, const char str[]){
577 mzd_t *mH0 = mzd_from_csr(NULL,smat);
578 if(str)
579 printf("matrix %s:\n",str);
580 else
581 printf("matrix:\n");
582 mzd_print(mH0);
583 mzd_free(mH0);
584}
585
586
587
593csr_t *csr_mm_read(char *fin, csr_t *mat, int transpose){
594 int ret_code;
595 MM_typecode matcode;
596 FILE *f;
597 int M, N, nz;
598
599 if ((f = fopen(fin, "r")) == NULL)
600 ERROR("can't open file %s",fin);
601
602 if (mm_read_banner(f, &matcode) != 0)
603 ERROR("Could not process Matrix Market banner.");
604
605 if (!mm_is_matrix(matcode))
606 ERROR("Only Matrix Market 'matrix' object is supported.");
607
608 if (!mm_is_integer(matcode) && !mm_is_pattern(matcode)) {
609 ERROR("Only integer or pattern matrices are supported. Found: %s", mm_typecode_to_str(matcode));
610 }
611
612 if (!mm_is_general(matcode) && !mm_is_symmetric(matcode)) {
613 ERROR("Only general or symmetric matrices are supported. Found: %s", mm_typecode_to_str(matcode));
614 }
615
616 /* find out size of matrix .... */
617 if (mm_is_coordinate(matcode)) {
618 if ((ret_code = mm_read_mtx_crd_size(f, &M, &N, &nz)) != 0)
619 ERROR("Cannot read coordinate size in input file %s", fin);
620 } else { // array (dense)
621 if ((ret_code = mm_read_mtx_array_size(f, &M, &N)) != 0)
622 ERROR("Cannot read array size in input file %s", fin);
623 if (mm_is_symmetric(matcode)) {
624 nz = M * M;
625 } else {
626 nz = M * N;
627 }
628 }
629
630 int nzmax;
631 if (mm_is_coordinate(matcode)) {
632 if (mm_is_symmetric(matcode)) {
633 nzmax = 2 * nz;
634 } else {
635 nzmax = nz;
636 }
637 } else { // array
638 if (mm_is_symmetric(matcode)) {
639 nzmax = M * M;
640 } else {
641 nzmax = M * N;
642 }
643 }
644
645 int rows = M;
646 int cols = N;
647 if (transpose) {
648 rows = N;
649 cols = M;
650 }
651
652 mat = csr_init(mat, rows, cols, nzmax);
653 int k = 0;
654
655 if (mm_is_coordinate(matcode)) {
656 for (int i = 0; i < nz; i++) {
657 int r, c;
658 int v = 1; // default for pattern
659 if (mm_is_integer(matcode)) {
660 if (fscanf(f, "%d %d %d\n", &r, &c, &v) != 3) {
661 ERROR("Failed to read coordinate entry %d in %s", i, fin);
662 }
663 } else { // pattern
664 if (fscanf(f, "%d %d\n", &r, &c) != 2) {
665 ERROR("Failed to read pattern entry %d in %s", i, fin);
666 }
667 }
668 r--; c--; // 1-based to 0-based
669
670 if (v % 2 != 0) {
671 int r_store = transpose ? c : r;
672 int c_store = transpose ? r : c;
673 mat->p[k] = r_store;
674 mat->i[k] = c_store;
675 k++;
676
677 if (mm_is_symmetric(matcode) && r != c) {
678 mat->p[k] = c_store;
679 mat->i[k] = r_store;
680 k++;
681 }
682 }
683 }
684 } else { // array (dense)
685 if (mm_is_general(matcode)) {
686 for (int c = 0; c < N; c++) {
687 for (int r = 0; r < M; r++) {
688 int v;
689 if (fscanf(f, "%d\n", &v) != 1) {
690 ERROR("Failed to read dense general entry at r=%d, c=%d in %s", r, c, fin);
691 }
692 if (v % 2 != 0) {
693 int r_store = transpose ? c : r;
694 int c_store = transpose ? r : c;
695 mat->p[k] = r_store;
696 mat->i[k] = c_store;
697 k++;
698 }
699 }
700 }
701 } else if (mm_is_symmetric(matcode)) {
702 for (int c = 0; c < N; c++) {
703 for (int r = c; r < M; r++) {
704 int v;
705 if (fscanf(f, "%d\n", &v) != 1) {
706 ERROR("Failed to read dense symmetric entry at r=%d, c=%d in %s", r, c, fin);
707 }
708 if (v % 2 != 0) {
709 int r_store = transpose ? c : r;
710 int c_store = transpose ? r : c;
711 mat->p[k] = r_store;
712 mat->i[k] = c_store;
713 k++;
714
715 if (r != c) {
716 mat->p[k] = c_store;
717 mat->i[k] = r_store;
718 k++;
719 }
720 }
721 }
722 }
723 }
724 }
725
726 mat->nz = k;
727 csr_compress(mat); /* sort entries by row and remove duplicates */
728 fclose(f);
729 return mat;
730}
731
732
736csr_t *csr_apply_perm(csr_t *dst, const csr_t * const src, const mzp_t * const perm){
737 int m=src->rows, n=src->cols;
738 if (src->nz!=-1)
739 ERROR("pair format unsupported, nz=%d; expected \"-1\"",src->nz);
740 int nz=src->p[m];
741 if(src->cols != perm-> length)
742 ERROR("perm length=%d should match cols=%d",perm->length,src->cols);
743 if (dst == NULL)
744 dst = csr_init(dst,m,n,nz);
745 else if ((dst->rows != m) || (dst->cols != n) || (nz > dst->nzmax))
746 ERROR("Wrong size for return matrix.\n");
747 for(int i=0;i<m;i++)
748 for(int j=src->p[i]; j < src->p[i+1] ; j++){
749 dst->p[j]=i; // pair format, to be compressed later
750 dst->i[j]= perm->values[src->i[j]];
751 // printf("row %d: mapping %d to %d\n",i,src->i[j],perm->values[src->i[j]]);
752 }
753 dst->nz=nz;
754 // csr_out(dst);
755 csr_compress(dst);
756 //csr_out(dst);
757 return dst;
758}
759
760
761
770int do_reduce(mzd_t *row, const mzd_t *matG0, const rci_t rankG0){
771 word * const rawrow = mzd_row(row,0);
772 rci_t j=-1;
773 rci_t n=row->ncols;
774 do{
775 j=nextelement(rawrow,row->width,j);
776 if(j==-1) // empty line after simplification
777 return j;
778 else if (j<rankG0)
779 mzd_combine_even_in_place(row,0,0,matG0,j,0);
780 } while (j < rankG0);
781 if (j<n)
782 return j;
783 return -1;
784}
785
786static inline uint64_t rotl(const uint64_t x, int k) {
787 return (x << k) | (x >> (64 - k));
788}
789
790/*** see arXiv:1805.01407 on fast RNGs ****
791
792uint64_t s[4];
793const int A=17, B=45, S=5, R=7, T=9;
794const uint64_t result_plus = s[0] + s[3];
795const uint64_t result_starstar = rotl(s[1] * S, R) * T;
796const uint64_t t = s[1] << A;
797s[2] ^= s[0];
798s[3] ^= s[1];
799s[1] ^= s[2];
800s[0] ^= s[3];
801s[2] ^= t;
802s[3] = rotl(s[3], B);
803*/
804
805/*
806 * generate binary error vector with error probability p
807 */
808void make_err(mzd_t *row, double p){
809 // const int max=MIN(10000,RAND_MAX);
810 const int cutoff=p*RAND_MAX;
811 if (row==NULL)
812 ERROR("make_err: row vector must be allocated to correct size!");
813 // mzd_set_ui(row,0);
814 // printf(" rows=%d cols=%d\n",row->nrows,row->ncols);
815 for(rci_t i = 0; i < row->nrows; ++i){
816 mzd_row_clear_offset(row,i,0);
817 printf("i=%d\n",i); // mzd_print(row);
818 for(rci_t j = 0; j < row->ncols; ++j){
819 // printf("%d %d\t",j,rand_uniform(max));
820 if (rand()<cutoff)
821 mzd_write_bit(row,i,j,1);
822 // printf("%d %d -> %d %d\n",i,j,mzd_read_bit(row,i,j),cutoff);
823 }
824 // mzd_print(row);
825 }
826}
827
828
837csr_t * csr_from_mzd(csr_t *mat, const mzd_t * const orig){
838 int nz=mzd_weight(orig);
839 mat = csr_init(mat, orig->nrows, orig->ncols, nz);
840 int i, j=0;
841 for(i=0;i < mat->rows; i++){
842 mat->p[i]=j;
843#if 1
844 int idx=0;
845 const word * const rawrow = mzd_row_cons(orig,i);
846 while(((idx=nextelement(rawrow,orig->width,idx))!=-1)&&(idx<orig->ncols)){
847 mat->i[j++]=idx++;
848 }
849#else
850 for(int idx=0; idx< orig->ncols; idx++)
851 if(mzd_read_bit(orig,i,idx)){
852 mat->i[j++]=idx;
853 // printf("i=%d j=%d idx=%d\n",i,j,idx);
854 }
855#endif /* 0 */
856 }
857 mat->p[i]=j; /* final value */
858 assert(j==nz);
859 mat->nz=-1; /* indicate compressed form */
860 return mat;
861}
862
872csr_t * Lx_for_CSS_code(const csr_t * const Hx, const csr_t *const Hz){
873 rci_t n=Hx->cols;
874 if(n!=Hz->cols)
875 ERROR("unequal number of columns in matrices Hx[%d,%d] and Hz[%d,%d]",
876 Hx->rows, Hx->cols, Hz->rows, Hz->cols);
877 mzd_t *Mx = mzd_from_csr(NULL,Hx); /* convert to dense matrix */
878 mzp_t *pivots = mzp_init(n); /* initialize the permutation */
879 rci_t rank = mzd_gauss_naive(Mx, pivots, 1);
880 mzd_apply_p_right_trans(Mx,pivots);
881 mzp_t *perm = perm_p( NULL, pivots,0);
882 mzp_t *permT = perm_p_trans(NULL, pivots,0);
883 mzp_free(pivots);
884 csr_t* HzPerm=csr_apply_perm(NULL,Hz,permT);
885 mzp_free(permT);
886#ifndef NDEBUG
887 mzd_t *MxT = mzd_transpose(NULL,Mx);
888 if(product_weight_csr_mzd(HzPerm,MxT,0))
889 ERROR("rows of Hx and Hz should be orthogonal ");
890 mzd_free(MxT);
891#endif
892 mzd_t *MzStar = mzd_generator_from_csr(NULL, HzPerm);
893 csr_free(HzPerm);
894
895 mzd_t *mat = mzd_stack(NULL,Mx,MzStar);
896 mzd_free(MzStar);
897 // printf("stacked:\n"); mzd_print(mat);
898 int rank1=mzd_echelonize(mat,0);
899 // printf("after gauss %d -> %d:\n", rank, rank1); mzd_print(mat);
900
901 mzd_t *window = mzd_init_window(mat,rank,0,rank1,n);
902 csr_t *Lx=csr_from_mzd(NULL, window);
903 csr_t *ans = csr_apply_perm(NULL,Lx,perm);
904 mzd_free(Mx);
905 csr_free(Lx);
906 mzd_free(window);
907 mzp_free(perm);
908 mzd_free(mat);
909 return ans;
910}
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
int nz
Definition util_m4ri.h:113
int nzmax
Definition util_m4ri.h:114
int * p
Definition util_m4ri.h:115
int * i
Definition util_m4ri.h:116
int rows
Definition util_m4ri.h:111
int cols
Definition util_m4ri.h:112
int debug
Definition util_io.h:32
params_t *const p
Definition util_io.c:52
params_t prm
Definition util_io.c:7
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:333
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:396
csr_t * csr_from_mzd(csr_t *mat, const mzd_t *const orig)
convert m4ri dense matrix to csr
Definition util_m4ri.c:837
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:309
void make_err(mzd_t *row, double p)
Generate a random binary error vector with error probability p.
Definition util_m4ri.c:808
mzd_t * syndrome_vector(mzd_t *syndrome, mzd_t *row, csr_t *spaQ, int clear)
Calculate syndrome vector change.
Definition util_m4ri.c:281
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:25
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:535
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:183
csr_t * csr_transpose(csr_t *dst, const csr_t *const p)
Transpose a compressed CSR sparse matrix.
Definition util_m4ri.c:133
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:593
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:872
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:476
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:156
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:442
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:770
void csr_out(const csr_t *mat)
Print raw contents of a CSR matrix to stdout.
Definition util_m4ri.c:554
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:576
csr_t * csr_free(csr_t *p)
Free memory allocated for a CSR sparse matrix.
Definition util_m4ri.c:459
void csr_compress(csr_t *mat)
Compress CSR matrix (sort indices and remove duplicates/zeros).
Definition util_m4ri.c:512
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:115
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:74
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:44
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:424
void addto(mzd_t *row, const csr_t *spaQ, const int i)
Definition util_m4ri.c:247
void mzp_out(mzp_t const *p)
Print the permutation to stdout.
Definition util_m4ri.c:412
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:16
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:224
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:356
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:736
int rand_uniform(const int max)
Return a uniformly distributed random integer in the range [0, max-1].
Definition util_m4ri.c:376
#define ERROR(fmt,...)
Definition util_m4ri.h:13
#define SWAPINT(a, b)
Definition util_m4ri.h:11