Dist m4ri 0.0.1.alpha
Computing distance of a classical or quantum CSS code
Loading...
Searching...
No Matches
util_m4ri.h
Go to the documentation of this file.
1#ifndef UTIL_M4RI_H
2#define UTIL_M4RI_H
3
4/************************************************************************
5 * helper functions for use with m4ri library, including binary sparse
6 * matrices and conversion utilities
7 * author: Leonid Pryadko <leonid.pryadko@ucr.edu>
8 * some code borrowed from various sources
9 ************************************************************************/
10
11#define SWAPINT(a,b) do{ int t=a; a=b; b=t; } while(0)
12
13#define ERROR(fmt,...) \
14 do{ \
15 fprintf (stderr, "%s:%d: *** ERROR in function '%s()' ***\n", __FILE__, __LINE__, __FUNCTION__); \
16 fprintf(stderr, " ␛[31;1m " fmt " ␛[0m\n",##__VA_ARGS__); \
17 exit(-1); \
18 } \
19 while(0)
20
22static inline word const * mzd_row_cons(const mzd_t * mat, const int row){
23 // return mat->rows[row] ;
24#pragma GCC diagnostic push
25#pragma GCC diagnostic ignored "-Wdiscarded-qualifiers"
26 return mzd_row(mat,row);
27#pragma GCC diagnostic pop
28}
29
30
36#define SETWD(pos) ((pos)>>6)
37#define SETBT(pos) ((pos)&0x3F)
38#define TIMESWORDSIZE(w) ((w)<<6) /* w*WORDSIZE */
39
40#define FIRSTBIT(x) __builtin_ctzll(x) // number of trailing zeros
41
42// #ifdef __POPCNT__
43#if 1
44
45/*
46 * optimized code copied verbatim from https://danluu.com/assembly-intrinsics/
47 */
48/* uint32_t builtin_popcnt_unrolled_errata_manual(const uint64_t* buf, int len) { */
49/* assert(len % 4 == 0); */
50/* uint64_t cnt[4]; */
51/* for (int i = 0; i < 4; ++i) { */
52/* cnt[i] = 0; */
53/* } */
54
55/* for (int i = 0; i < len; i+=4) { */
56/* __asm__( */
57/* "popcnt %4, %4 \n\t" */
58/* "add %4, %0 \n\t" */
59/* "popcnt %5, %5 \n\t" */
60/* "add %5, %1 \n\t" */
61/* "popcnt %6, %6 \n\t" */
62/* "add %6, %2 \n\t" */
63/* "popcnt %7, %7 \n\t" */
64/* "add %7, %3 \n\t" // +r means input/output, r means intput */
65/* : "+r" (cnt[0]), "+r" (cnt[1]), "+r" (cnt[2]), "+r" (cnt[3]) */
66/* : "r" (buf[i]), "r" (buf[i+1]), "r" (buf[i+2]), "r" (buf[i+3])); */
67/* } */
68/* return cnt[0] + cnt[1] + cnt[2] + cnt[3]; */
69/* } */
70
71static inline int m4ri_bitcount(word w){
72 return __builtin_popcountll(w);
73}
74
75#else /* no __POPCNT__ */
76
77#define MASK(c) (((uint64_t)(-1)) / (__M4RI_TWOPOW(__M4RI_TWOPOW(c)) + 1))
78#define COUNT(x,c) ((x) & MASK(c)) + (((x) >> (__M4RI_TWOPOW(c))) & MASK(c))
79
80static inline int m4ri_bitcount(word w) {
81 uint64_t n = __M4RI_CONVERT_TO_UINT64_T(w);
82 n = COUNT(n, 0);
83 n = COUNT(n, 1);
84 n = COUNT(n, 2);
85 n = COUNT(n, 3);
86 n = COUNT(n, 4);
87 n = COUNT(n, 5);
88 return (int)n;
89}
90
91static inline int std_bitcount ( uint64_t x) {
92 uint64_t c1 = UINT64_C (0x5555555555555555 );
93 uint64_t c2 = UINT64_C (0x3333333333333333 );
94 uint64_t c4 = UINT64_C (0x0F0F0F0F0F0F0F0F );
95 x -= (x >> 1) & c1;
96 x = (( x >> 2) & c2) + (x & c2);
97 x = ( x + (x >> 4) ) & c4;
98 x *= UINT64_C (0x0101010101010101 );
99 return (int) (x >> 56);
100}
101
102#endif /* __POPCNT__ */
103
104
110typedef struct{ /* */
111 int rows ; /* number of rows */
112 int cols ; /* number of columns */
113 int nz ; /* # of entries in triplet matrix */
114 int nzmax ; /* # allocated size */
115 int *p ; /* row pointers (size rows+1) OR row indices */
116 int *i ; /* col indices, size nzmax */
117} csr_t ;
118
119
120typedef struct { int a; int b; } int_pair;
121
122
123#if defined(__cplusplus) && !defined (_MSC_VER)
124extern "C" {
125#endif
126
132 size_t mzd_weight(const mzd_t *A);
133
139 size_t mzd_weight_naive(const mzd_t *A);
140
147 size_t mzd_weight_row(const mzd_t *A, rci_t i);
148
159 static inline int nextelement(const word * const set1, const int m, const int pos){
160 word setwd;
161 int w;
162 if (pos < 0){
163 w = 0;
164 setwd = set1[0];
165 }
166 else{
167 w = SETWD(pos);
168 if (w >= m) return -1;
169 setwd = set1[w] & (m4ri_ffff<< SETBT(pos));
170 }
171
172 for (;;){
173 if (setwd != 0)
174 return TIMESWORDSIZE(w) + FIRSTBIT(setwd);
175 if (++w == m)
176 return -1;
177 setwd = set1[w];
178 }
179 }
180
181
193 rci_t mzd_gauss_naive(mzd_t *M, mzp_t *q, int full);
194
200 int csr_max_row_wght(const csr_t * const p);
201
211 csr_t * csr_transpose(csr_t *dst, const csr_t * const p);
212
213
221 mzd_t *mzd_from_csr(mzd_t *dst, const csr_t *p);
222
234 mzd_t *mzd_generator_from_csr(mzd_t *G, const csr_t * const H);
235
247 mzd_t * csr_mzd_mul(mzd_t *C, const csr_t *S, const mzd_t *B, int clear);
248
260 mzd_t * syndrome_vector(mzd_t *syndrome, mzd_t *row, csr_t *spaQ, int clear);
261
262
273 size_t product_weight_csr_mzd(const csr_t *A, const mzd_t *B, int transpose);
274
280 int rand_uniform(const int max);
281
292 mzp_t * mzp_rand_len(mzp_t *q, rci_t length);
293
299 static inline mzp_t * mzp_rand(mzp_t *q){
300 if (q==NULL){
301 printf("mzp_rand: permutation must be initialized!");
302 exit(-1);
303 }
304 return mzp_rand_len(q,q->length);
305 }
306
311 void mzp_out(mzp_t const *p);
312
321 mzp_t *perm_p(mzp_t *q, const mzp_t *p,rci_t start);
322
331 mzp_t *perm_p_trans(mzp_t *q, const mzp_t *p,const rci_t start);
332
339
351 csr_t *csr_init(csr_t *mat, int rows, int cols, int nzmax);
352
361 void csr_compress(csr_t *mat);
362
373 csr_t * csr_from_pairs(csr_t *mat, const int nz, int_pair * const prs, const int nrows, const int ncols);
374
379 void csr_out(const csr_t *mat);
380
386 void csr_print(const csr_t * const smat, const char str[]);
387
396 csr_t *csr_mm_read(char *fin, csr_t *mat, int transpose);
397
406 csr_t *csr_apply_perm(csr_t *dst, const csr_t * const src, const mzp_t * const perm);
407
408
417static inline void mzd_flip_bit(mzd_t * const M, rci_t const row, rci_t const col ) {
418 word * const rawrow = mzd_row(M,row);
419 __M4RI_FLIP_BIT(rawrow[col/m4ri_radix], col%m4ri_radix);
420}
421
429static inline int gauss_one(mzd_t *M, const int idx, const int begrow){
431 rci_t startrow = begrow;
432 rci_t pivots = 0;
433 const rci_t i = idx;
434 // for (rci_t i = startcol; i < endcol ; ++i) {
435 for(rci_t j = startrow ; j < M->nrows; ++j) {
436 if (mzd_read_bit(M, j, i)) {
437 mzd_row_swap(M, startrow, j);
438 ++pivots;
439 for(rci_t ii = 0 ; ii < M->nrows; ++ii) {
440 if (ii != startrow) {
441 if (mzd_read_bit(M, ii, i)) {
442 mzd_row_add_offset(M, ii, startrow,0);
443 }
444 }
445 }
446 startrow = startrow + 1;
447 break;
448 }
449 }
450 // }
451 return pivots;
452 // if one, need to update the current pivot list
453}
454
466static inline int sparse_syndrome_non_zero(const csr_t * const H, const int cnt, const int ee[]){
467 for(int ir=0; ir < H->rows; ir++){
468 int nz=0;
469 for(int iL = H->p[ir], iE = 0; iL < H->p[ir+1]; iL++){
470 int ic = H->i[iL];
471 while((iE < cnt) && (ee[iE] < ic))
472 iE++;
473 if(iE >= cnt)
474 break;
475 if(ee[iE]==ic)
476 nz ^= 1;
477 }
478 if (nz)
479 return 1;
480 }
481 return 0;
482}
483
490 int csr_csr_mul_non_zero(const csr_t * const A, const csr_t * const B);
491
498 int syndrome_bit_count(const mzd_t * const row, const csr_t * const spaQ);
499
512 int do_reduce(mzd_t *row, const mzd_t *matP0, const rci_t rankP0);
513
519 void make_err(mzd_t *row, double p);
520
524 int do_dist_clus(const csr_t * const P, const mzd_t * const G, int debug, int wmax, int start, const int rankG);
525
532 csr_t * Lx_for_CSS_code(const csr_t * const Hx, const csr_t *const Hz);
533
534#if defined(__cplusplus) && !defined (_MSC_VER)
535}
536#endif
537
538#endif /* UTIL_M4RI_H */
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
params_t *const p
Definition util_io.c:52
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
int do_reduce(mzd_t *row, const mzd_t *matP0, const rci_t rankP0)
Reduce a row vector against a matrix in standard form.
Definition util_m4ri.c:770
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
#define FIRSTBIT(x)
Definition util_m4ri.h:40
void make_err(mzd_t *row, double p)
Generate a random binary error vector with error probability p.
Definition util_m4ri.c:808
int do_dist_clus(const csr_t *const P, const mzd_t *const G, int debug, int wmax, int start, const int rankG)
(Internal) Run cluster distance algorithm on matrices.
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 *A, 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)
Construct the logical matrix Lx for a quantum CSS code given Hx and Hz.
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
#define SETBT(pos)
Definition util_m4ri.h:37
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
#define SETWD(pos)
Definition util_m4ri.h:36
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)
Get the maximum row weight of a CSR sparse matrix.
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 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
#define TIMESWORDSIZE(w)
Definition util_m4ri.h:38
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