void make_ldpc ( int seed, /* Random number seed */ make_method method, /* How to make it */ distrib *d, /* Distribution list specified */ int no4cycle /* Eliminate cycles of length four? */ ) { mod2entry *e, *f, *g, *h; int added, uneven, elim4, all_even, n_full, left; int i, j, k, t, z, cb_N; int *part, *u; rand_seed(10*seed+1); H = mod2sparse_allocate(M,N); part = column_partition(d,N); /* Create the initial version of the parity check matrix. */ switch (method) { case Evencol: { z = 0; left = part[z]; for (j = 0; j<N; j++) { while (left==0) { z += 1; if (z>distrib_size(d)) { abort(); } left = part[z]; } for (k = 0; k<distrib_num(d,z); k++) { do { i = rand_int(M); } while (mod2sparse_find(H,i,j)); mod2sparse_insert(H,i,j); } left -= 1; } break; } case Evenboth: { cb_N = 0; for (z = 0; z<distrib_size(d); z++) { cb_N += distrib_num(d,z) * part[z]; } u = chk_alloc (cb_N, sizeof *u); for (k = cb_N-1; k>=0; k--) { u[k] = k%M; } uneven = 0; t = 0; z = 0; left = part[z]; for (j = 0; j<N; j++) { while (left==0) { z += 1; if (z>distrib_size(d)) { abort(); } left = part[z]; } for (k = 0; k<distrib_num(d,z); k++) { for (i = t; i<cb_N && mod2sparse_find(H,u[i],j); i++) ; if (i==cb_N) { uneven += 1; do { i = rand_int(M); } while (mod2sparse_find(H,i,j)); mod2sparse_insert(H,i,j); } else { do { i = t + rand_int(cb_N-t); } while (mod2sparse_find(H,u[i],j)); mod2sparse_insert(H,u[i],j); u[i] = u[t]; t += 1; } } left -= 1; } if (uneven>0) { fprintf(stderr,"Had to place %d checks in rows unevenly\n",uneven); } break; } default: abort(); } /* Add extra bits to avoid rows with less than two checks. */ added = 0; for (i = 0; i<M; i++) { e = mod2sparse_first_in_row(H,i); if (mod2sparse_at_end(e)) { j = rand_int(N); e = mod2sparse_insert(H,i,j); added += 1; } e = mod2sparse_first_in_row(H,i); if (mod2sparse_at_end(mod2sparse_next_in_row(e)) && N>1) { do { j = rand_int(N); } while (j==mod2sparse_col(e)); mod2sparse_insert(H,i,j); added += 1; } } if (added>0) { fprintf(stderr, "Added %d extra bit-checks to make row counts at least two\n", added); } /* Add extra bits to try to avoid problems with even column counts. */ n_full = 0; all_even = 1; for (z = 0; z<distrib_size(d); z++) { if (distrib_num(d,z)==M) { n_full += part[z]; } if (distrib_num(d,z)%2==1) { all_even = 0; } } if (all_even && N-n_full>1 && added<2) { int a; for (a = 0; added+a<2; a++) { do { i = rand_int(M); j = rand_int(N); } while (mod2sparse_find(H,i,j)); mod2sparse_insert(H,i,j); } fprintf(stderr, "Added %d extra bit-checks to try to avoid problems from even column counts\n", a); } /* Eliminate cycles of length four, if asked, and if possible. */ if (no4cycle) { elim4 = 0; for (t = 0; t<10; t++) { k = 0; for (j = 0; j<N; j++) { for (e = mod2sparse_first_in_col(H,j); !mod2sparse_at_end(e); e = mod2sparse_next_in_col(e)) { for (f = mod2sparse_first_in_row(H,mod2sparse_row(e)); !mod2sparse_at_end(f); f = mod2sparse_next_in_row(f)) { if (f==e) continue; for (g = mod2sparse_first_in_col(H,mod2sparse_col(f)); !mod2sparse_at_end(g); g = mod2sparse_next_in_col(g)) { if (g==f) continue; for (h = mod2sparse_first_in_row(H,mod2sparse_row(g)); !mod2sparse_at_end(h); h = mod2sparse_next_in_row(h)) { if (mod2sparse_col(h)==j) { do { i = rand_int(M); } while (mod2sparse_find(H,i,j)); mod2sparse_delete(H,e); mod2sparse_insert(H,i,j); elim4 += 1; k += 1; goto nextj; } } } } } nextj: ; } if (k==0) break; } if (elim4>0) { fprintf(stderr, "Eliminated %d cycles of length four by moving checks within column\n", elim4); } if (t==10) { fprintf(stderr, "Couldn't eliminate all cycles of length four in 10 passes\n"); } } }
mod2sparse* CreatePchkMatrix ( int nbRows, int nbCols, make_method makeMethod, int leftDegree, int seed, bool no4cycle, SessionType type, int verbosity ) { mod2entry *e; #if 0 mod2entry *f, *g, *h; /* using by no4cycle mode */ int elim4; #endif int added, uneven; int i, j, k, t; int *u; mod2sparse *pchkMatrix = NULL; int skipCols = 0; // avoid warning int nbDataCols = 0; // avoid warning if (type != TypeLDGM && type != TypeSTAIRS && type != TypeTRIANGLE) { fprintf(stderr, "unsupported code type (%d)\n", type); return NULL; } skipCols = nbRows; nbDataCols = nbCols-skipCols; // Check for some problems. if (leftDegree>nbRows) { fprintf(stderr, "ERROR, Number of checks per bit (%d) is greater than total checks (%d)\n", leftDegree, nbRows); return NULL; } #if 0 if (leftDegree==nbRows && nbCols>1 && no4cycle) { fprintf(stderr, "ERROR, Can't eliminate cycles of length four with this many checks per bit\n"); return NULL; } #endif if (no4cycle) { fprintf(stderr, "ERROR: no4cycle mode is no longer supported!\n"); exit(-1); } ldpc_srand(seed); pchkMatrix = mod2sparse_allocate(nbRows, nbCols); /* Create the initial version of the parity check matrix. */ switch (makeMethod) { case Evencol: for(j=skipCols; j<nbCols; j++) { for(k=0; k<leftDegree; k++) { do { i = ldpc_rand(nbRows); } while (mod2sparse_find(pchkMatrix,i,j)); mod2sparse_insert(pchkMatrix,i,j); } } break; case Evenboth: u = (int*)chk_alloc (leftDegree*nbDataCols, sizeof *u); /* initialize a list of possible choices to guarantee a homogeneous "1" distribution */ for(k = leftDegree*nbDataCols-1; k>=0; k--) { u[k] = k%nbRows; } uneven = 0; t = 0; /* left limit within the list of possible choices, u[] */ for(j = skipCols; j<nbCols; j++) /* for each source symbol column */ { for(k = 0; k<leftDegree; k++) /* add left_degree "1s" */ { /* check that valid available choices remain */ for(i = t; i<leftDegree*nbDataCols && mod2sparse_find(pchkMatrix,u[i],j); i++) ; if(i < leftDegree*nbDataCols) { /* choose one index within the list of possible choices */ do { i = t + ldpc_rand(leftDegree*nbDataCols-t); } while (mod2sparse_find(pchkMatrix,u[i],j)); mod2sparse_insert(pchkMatrix,u[i],j); /* replace with u[t] which has never been chosen */ u[i] = u[t]; t++; } else { /* no choice left, choose one randomly */ uneven += 1; do { i = ldpc_rand(nbRows); } while (mod2sparse_find(pchkMatrix,i,j)); mod2sparse_insert(pchkMatrix,i,j); } } } if(uneven > 0 && verbosity >= 1) { fprintf(stderr,"Had to place %d checks in rows unevenly\n",uneven); } free(u); /* VR: added */ break; default: abort(); } /* Add extra bits to avoid rows with less than two checks. */ added = 0; for(i = 0; i<nbRows; i++) { e = mod2sparse_first_in_row(pchkMatrix,i); if(mod2sparse_at_end(e)) { j = (ldpc_rand(nbDataCols))+skipCols; e = mod2sparse_insert(pchkMatrix,i,j); added ++; } e = mod2sparse_first_in_row(pchkMatrix,i); if(mod2sparse_at_end(mod2sparse_next_in_row(e)) && nbDataCols>1) { do { j = (ldpc_rand(nbDataCols))+skipCols; } while (j==mod2sparse_col(e)); mod2sparse_insert(pchkMatrix,i,j); added ++; } } if(added > 0 && verbosity >= 1) { fprintf(stderr, "Added %d extra bit-checks to make row counts at least two\n", added); } /* Add extra bits to try to avoid problems with even column counts. */ if(leftDegree%2==0 && leftDegree<nbRows && nbDataCols>1 && added<2) { int a; for(a = 0; added+a<2; a++) { do { i = ldpc_rand(nbRows); j = (ldpc_rand(nbDataCols))+skipCols; } while (mod2sparse_find(pchkMatrix,i,j)); mod2sparse_insert(pchkMatrix,i,j); } if (verbosity >= 1) { fprintf(stderr, "Added %d extra bit-checks to try to avoid problems from even column counts\n", a); } } #if 0 /* Eliminate cycles of length four, if asked, and if possible. */ if(no4cycle) { elim4 = 0; for(t = 0; t<10; t++) { k = 0; for(j = 0; j<nbCols; j++) { for( e=mod2sparse_first_in_col(pchkMatrix,j); !mod2sparse_at_end(e); e=mod2sparse_next_in_col(e) ) { for( f=mod2sparse_first_in_row(pchkMatrix,mod2sparse_row(e)); !mod2sparse_at_end(f); f=mod2sparse_next_in_row(f) ) { if(f==e) continue; for(g=mod2sparse_first_in_col(pchkMatrix,mod2sparse_col(f)); !mod2sparse_at_end(g); g=mod2sparse_next_in_col(g) ) { if(g==f) continue; for( h=mod2sparse_first_in_row(pchkMatrix,mod2sparse_row(g)); !mod2sparse_at_end(h); h = mod2sparse_next_in_row(h) ) { if(mod2sparse_col(h)==j) { do { i = ldpc_rand(nbRows); } while (mod2sparse_find(pchkMatrix,i,j)); mod2sparse_delete(pchkMatrix,e); mod2sparse_insert(pchkMatrix,i,j); elim4 += 1; k += 1; goto nextj; } } } } } nextj: ; } if(k==0) break; } if(elim4>0) { fprintf(stderr, "Eliminated %d cycles of length four by moving checks within column\n", elim4); } if(t==10) { fprintf(stderr, "Couldn't eliminate all cycles of length four in 10 passes\n"); } } #endif switch (type) { case TypeLDGM: for (i = 0; i < nbRows; i++) { /* identity */ mod2sparse_insert(pchkMatrix, i, i); } break; case TypeSTAIRS: mod2sparse_insert(pchkMatrix, 0, 0); /* 1st row */ for (i = 1; i < nbRows; i++) { /* for all other rows */ /* identity */ mod2sparse_insert(pchkMatrix, i, i); /* staircase */ mod2sparse_insert(pchkMatrix, i, i-1); } break; case TypeTRIANGLE: mod2sparse_insert(pchkMatrix, 0, 0); /* 1st row */ for (i = 1; i < nbRows; i++) { /* for all other rows */ /* identity */ mod2sparse_insert(pchkMatrix, i, i); /* staircase */ mod2sparse_insert(pchkMatrix, i, i-1); /* triangle */ j = i-1; for (int l = 0; l < j; l++) { /* limit the # of "1s" added */ j = ldpc_rand(j); mod2sparse_insert(pchkMatrix, i, j); } } break; } return pchkMatrix; }