Merged master 8748
This commit is contained in:
@@ -0,0 +1,365 @@
|
||||
subroutine osd174(llr,apmask,ndeep,decoded,cw,nhardmin,dmin)
|
||||
!
|
||||
! An ordered-statistics decoder for the (174,87) code.
|
||||
!
|
||||
include "ldpc_174_87_params.f90"
|
||||
|
||||
integer*1 apmask(N),apmaskr(N)
|
||||
integer*1 gen(K,N)
|
||||
integer*1 genmrb(K,N),g2(N,K)
|
||||
integer*1 temp(K),m0(K),me(K),mi(K),misub(K),e2sub(N-K),e2(N-K),ui(N-K)
|
||||
integer*1 r2pat(N-K)
|
||||
integer indices(N),nxor(N)
|
||||
integer*1 cw(N),ce(N),c0(N),hdec(N)
|
||||
integer*1 decoded(K)
|
||||
integer indx(N)
|
||||
real llr(N),rx(N),absrx(N)
|
||||
logical first,reset
|
||||
data first/.true./
|
||||
save first,gen
|
||||
|
||||
if( first ) then ! fill the generator matrix
|
||||
gen=0
|
||||
do i=1,M
|
||||
do j=1,22
|
||||
read(g(i)(j:j),"(Z1)") istr
|
||||
do jj=1, 4
|
||||
irow=(j-1)*4+jj
|
||||
if( btest(istr,4-jj) ) gen(irow,i)=1
|
||||
enddo
|
||||
enddo
|
||||
enddo
|
||||
do irow=1,K
|
||||
gen(irow,M+irow)=1
|
||||
enddo
|
||||
first=.false.
|
||||
endif
|
||||
|
||||
! Re-order received vector to place systematic msg bits at the end.
|
||||
rx=llr(colorder+1)
|
||||
apmaskr=apmask(colorder+1)
|
||||
|
||||
! Hard decisions on the received word.
|
||||
hdec=0
|
||||
where(rx .ge. 0) hdec=1
|
||||
|
||||
! Use magnitude of received symbols as a measure of reliability.
|
||||
absrx=abs(rx)
|
||||
call indexx(absrx,N,indx)
|
||||
|
||||
! Re-order the columns of the generator matrix in order of decreasing reliability.
|
||||
do i=1,N
|
||||
genmrb(1:K,i)=gen(1:K,indx(N+1-i))
|
||||
indices(i)=indx(N+1-i)
|
||||
enddo
|
||||
|
||||
! Do gaussian elimination to create a generator matrix with the most reliable
|
||||
! received bits in positions 1:K in order of decreasing reliability (more or less).
|
||||
do id=1,K ! diagonal element indices
|
||||
do icol=id,K+20 ! The 20 is ad hoc - beware
|
||||
iflag=0
|
||||
if( genmrb(id,icol) .eq. 1 ) then
|
||||
iflag=1
|
||||
if( icol .ne. id ) then ! reorder column
|
||||
temp(1:K)=genmrb(1:K,id)
|
||||
genmrb(1:K,id)=genmrb(1:K,icol)
|
||||
genmrb(1:K,icol)=temp(1:K)
|
||||
itmp=indices(id)
|
||||
indices(id)=indices(icol)
|
||||
indices(icol)=itmp
|
||||
endif
|
||||
do ii=1,K
|
||||
if( ii .ne. id .and. genmrb(ii,id) .eq. 1 ) then
|
||||
genmrb(ii,1:N)=ieor(genmrb(ii,1:N),genmrb(id,1:N))
|
||||
endif
|
||||
enddo
|
||||
exit
|
||||
endif
|
||||
enddo
|
||||
enddo
|
||||
|
||||
g2=transpose(genmrb)
|
||||
|
||||
! The hard decisions for the K MRB bits define the order 0 message, m0.
|
||||
! Encode m0 using the modified generator matrix to find the "order 0" codeword.
|
||||
! Flip various combinations of bits in m0 and re-encode to generate a list of
|
||||
! codewords. Return the member of the list that has the smallest Euclidean
|
||||
! distance to the received word.
|
||||
|
||||
hdec=hdec(indices) ! hard decisions from received symbols
|
||||
m0=hdec(1:K) ! zero'th order message
|
||||
absrx=absrx(indices)
|
||||
rx=rx(indices)
|
||||
apmaskr=apmaskr(indices)
|
||||
|
||||
call mrbencode(m0,c0,g2,N,K)
|
||||
nxor=ieor(c0,hdec)
|
||||
nhardmin=sum(nxor)
|
||||
dmin=sum(nxor*absrx)
|
||||
|
||||
cw=c0
|
||||
ntotal=0
|
||||
nrejected=0
|
||||
|
||||
if(ndeep.eq.0) goto 998 ! norder=0
|
||||
if(ndeep.gt.5) ndeep=5
|
||||
if( ndeep.eq. 1) then
|
||||
nord=1
|
||||
npre1=0
|
||||
npre2=0
|
||||
nt=40
|
||||
ntheta=12
|
||||
elseif(ndeep.eq.2) then
|
||||
nord=1
|
||||
npre1=1
|
||||
npre2=0
|
||||
nt=40
|
||||
ntheta=12
|
||||
elseif(ndeep.eq.3) then
|
||||
nord=1
|
||||
npre1=1
|
||||
npre2=1
|
||||
nt=40
|
||||
ntheta=12
|
||||
ntau=14
|
||||
elseif(ndeep.eq.4) then
|
||||
nord=2
|
||||
npre1=1
|
||||
npre2=0
|
||||
nt=40
|
||||
ntheta=12
|
||||
ntau=19
|
||||
elseif(ndeep.eq.5) then
|
||||
nord=2
|
||||
npre1=1
|
||||
npre2=1
|
||||
nt=40
|
||||
ntheta=12
|
||||
ntau=19
|
||||
endif
|
||||
|
||||
do iorder=1,nord
|
||||
misub(1:K-iorder)=0
|
||||
misub(K-iorder+1:K)=1
|
||||
iflag=K-iorder+1
|
||||
do while(iflag .ge.0)
|
||||
if(iorder.eq.nord .and. npre1.eq.0) then
|
||||
iend=iflag
|
||||
else
|
||||
iend=1
|
||||
endif
|
||||
do n1=iflag,iend,-1
|
||||
mi=misub
|
||||
mi(n1)=1
|
||||
if(any(iand(apmaskr(1:K),mi).eq.1)) cycle
|
||||
ntotal=ntotal+1
|
||||
me=ieor(m0,mi)
|
||||
if(n1.eq.iflag) then
|
||||
call mrbencode(me,ce,g2,N,K)
|
||||
e2sub=ieor(ce(K+1:N),hdec(K+1:N))
|
||||
e2=e2sub
|
||||
nd1Kpt=sum(e2sub(1:nt))+1
|
||||
d1=sum(ieor(me(1:K),hdec(1:K))*absrx(1:K))
|
||||
else
|
||||
e2=ieor(e2sub,g2(K+1:N,n1))
|
||||
nd1Kpt=sum(e2(1:nt))+2
|
||||
endif
|
||||
if(nd1Kpt .le. ntheta) then
|
||||
call mrbencode(me,ce,g2,N,K)
|
||||
nxor=ieor(ce,hdec)
|
||||
if(n1.eq.iflag) then
|
||||
dd=d1+sum(e2sub*absrx(K+1:N))
|
||||
else
|
||||
dd=d1+ieor(ce(n1),hdec(n1))*absrx(n1)+sum(e2*absrx(K+1:N))
|
||||
endif
|
||||
if( dd .lt. dmin ) then
|
||||
dmin=dd
|
||||
cw=ce
|
||||
nhardmin=sum(nxor)
|
||||
nd1Kptbest=nd1Kpt
|
||||
endif
|
||||
else
|
||||
nrejected=nrejected+1
|
||||
endif
|
||||
enddo
|
||||
! Get the next test error pattern, iflag will go negative
|
||||
! when the last pattern with weight iorder has been generated.
|
||||
call nextpat(misub,k,iorder,iflag)
|
||||
enddo
|
||||
enddo
|
||||
|
||||
if(npre2.eq.1) then
|
||||
reset=.true.
|
||||
ntotal=0
|
||||
do i1=K,1,-1
|
||||
do i2=i1-1,1,-1
|
||||
ntotal=ntotal+1
|
||||
mi(1:ntau)=ieor(g2(K+1:K+ntau,i1),g2(K+1:K+ntau,i2))
|
||||
call boxit(reset,mi(1:ntau),ntau,ntotal,i1,i2)
|
||||
enddo
|
||||
enddo
|
||||
|
||||
ncount2=0
|
||||
ntotal2=0
|
||||
reset=.true.
|
||||
! Now run through again and do the second pre-processing rule
|
||||
misub(1:K-nord)=0
|
||||
misub(K-nord+1:K)=1
|
||||
iflag=K-nord+1
|
||||
do while(iflag .ge.0)
|
||||
me=ieor(m0,misub)
|
||||
call mrbencode(me,ce,g2,N,K)
|
||||
e2sub=ieor(ce(K+1:N),hdec(K+1:N))
|
||||
do i2=0,ntau
|
||||
ntotal2=ntotal2+1
|
||||
ui=0
|
||||
if(i2.gt.0) ui(i2)=1
|
||||
r2pat=ieor(e2sub,ui)
|
||||
778 continue
|
||||
call fetchit(reset,r2pat(1:ntau),ntau,in1,in2)
|
||||
if(in1.gt.0.and.in2.gt.0) then
|
||||
ncount2=ncount2+1
|
||||
mi=misub
|
||||
mi(in1)=1
|
||||
mi(in2)=1
|
||||
if(sum(mi).lt.nord+npre1+npre2.or.any(iand(apmaskr(1:K),mi).eq.1)) cycle
|
||||
me=ieor(m0,mi)
|
||||
call mrbencode(me,ce,g2,N,K)
|
||||
nxor=ieor(ce,hdec)
|
||||
dd=sum(nxor*absrx)
|
||||
if( dd .lt. dmin ) then
|
||||
dmin=dd
|
||||
cw=ce
|
||||
nhardmin=sum(nxor)
|
||||
endif
|
||||
goto 778
|
||||
endif
|
||||
enddo
|
||||
call nextpat(misub,K,nord,iflag)
|
||||
enddo
|
||||
endif
|
||||
|
||||
998 continue
|
||||
! Re-order the codeword to place message bits at the end.
|
||||
cw(indices)=cw
|
||||
hdec(indices)=hdec
|
||||
decoded=cw(M+1:N)
|
||||
cw(colorder+1)=cw ! put the codeword back into received-word order
|
||||
return
|
||||
end subroutine osd174
|
||||
|
||||
subroutine mrbencode(me,codeword,g2,N,K)
|
||||
integer*1 me(K),codeword(N),g2(N,K)
|
||||
! fast encoding for low-weight test patterns
|
||||
codeword=0
|
||||
do i=1,K
|
||||
if( me(i) .eq. 1 ) then
|
||||
codeword=ieor(codeword,g2(1:N,i))
|
||||
endif
|
||||
enddo
|
||||
return
|
||||
end subroutine mrbencode
|
||||
|
||||
subroutine nextpat(mi,k,iorder,iflag)
|
||||
integer*1 mi(k),ms(k)
|
||||
! generate the next test error pattern
|
||||
ind=-1
|
||||
do i=1,k-1
|
||||
if( mi(i).eq.0 .and. mi(i+1).eq.1) ind=i
|
||||
enddo
|
||||
if( ind .lt. 0 ) then ! no more patterns of this order
|
||||
iflag=ind
|
||||
return
|
||||
endif
|
||||
ms=0
|
||||
ms(1:ind-1)=mi(1:ind-1)
|
||||
ms(ind)=1
|
||||
ms(ind+1)=0
|
||||
if( ind+1 .lt. k ) then
|
||||
nz=iorder-sum(ms)
|
||||
ms(k-nz+1:k)=1
|
||||
endif
|
||||
mi=ms
|
||||
do i=1,k ! iflag will point to the lowest-index 1 in mi
|
||||
if(mi(i).eq.1) then
|
||||
iflag=i
|
||||
exit
|
||||
endif
|
||||
enddo
|
||||
return
|
||||
end subroutine nextpat
|
||||
|
||||
subroutine boxit(reset,e2,ntau,npindex,i1,i2)
|
||||
integer*1 e2(1:ntau)
|
||||
integer indexes(4000,2),fp(0:525000),np(4000)
|
||||
logical reset
|
||||
common/boxes/indexes,fp,np
|
||||
|
||||
if(reset) then
|
||||
patterns=-1
|
||||
fp=-1
|
||||
np=-1
|
||||
sc=-1
|
||||
indexes=-1
|
||||
reset=.false.
|
||||
endif
|
||||
|
||||
indexes(npindex,1)=i1
|
||||
indexes(npindex,2)=i2
|
||||
ipat=0
|
||||
do i=1,ntau
|
||||
if(e2(i).eq.1) then
|
||||
ipat=ipat+ishft(1,ntau-i)
|
||||
endif
|
||||
enddo
|
||||
|
||||
ip=fp(ipat) ! see what's currently stored in fp(ipat)
|
||||
if(ip.eq.-1) then
|
||||
fp(ipat)=npindex
|
||||
else
|
||||
do while (np(ip).ne.-1)
|
||||
ip=np(ip)
|
||||
enddo
|
||||
np(ip)=npindex
|
||||
endif
|
||||
return
|
||||
end subroutine boxit
|
||||
|
||||
subroutine fetchit(reset,e2,ntau,i1,i2)
|
||||
integer indexes(4000,2),fp(0:525000),np(4000)
|
||||
integer lastpat
|
||||
integer*1 e2(ntau)
|
||||
logical reset
|
||||
common/boxes/indexes,fp,np
|
||||
save lastpat,inext
|
||||
|
||||
if(reset) then
|
||||
lastpat=-1
|
||||
reset=.false.
|
||||
endif
|
||||
|
||||
ipat=0
|
||||
do i=1,ntau
|
||||
if(e2(i).eq.1) then
|
||||
ipat=ipat+ishft(1,ntau-i)
|
||||
endif
|
||||
enddo
|
||||
index=fp(ipat)
|
||||
|
||||
if(lastpat.ne.ipat .and. index.gt.0) then ! return first set of indices
|
||||
i1=indexes(index,1)
|
||||
i2=indexes(index,2)
|
||||
inext=np(index)
|
||||
elseif(lastpat.eq.ipat .and. inext.gt.0) then
|
||||
i1=indexes(inext,1)
|
||||
i2=indexes(inext,2)
|
||||
inext=np(inext)
|
||||
else
|
||||
i1=-1
|
||||
i2=-1
|
||||
inext=-1
|
||||
endif
|
||||
lastpat=ipat
|
||||
return
|
||||
end subroutine fetchit
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,37 @@
|
||||
subroutine decode65b(s2,nflip,nadd,mode65,ntrials,naggressive,ndepth, &
|
||||
mycall,hiscall,hisgrid,nQSOProgress,ljt65apon,nexp_decode,nqd, &
|
||||
nft,qual, &
|
||||
nhist,decoded)
|
||||
|
||||
use jt65_mod
|
||||
real s2(66,126)
|
||||
real s3(64,63)
|
||||
logical ltext,ljt65apon
|
||||
character decoded*22
|
||||
character mycall*12,hiscall*12,hisgrid*6
|
||||
save
|
||||
|
||||
if(nqd.eq.-99) stop !Silence compiler warning
|
||||
do j=1,63
|
||||
k=mdat(j) !Points to data symbol
|
||||
if(nflip.lt.0) k=mdat2(j)
|
||||
do i=1,64
|
||||
s3(i,j)=s2(i+2,k)
|
||||
enddo
|
||||
enddo
|
||||
|
||||
call extract(s3,nadd,mode65,ntrials,naggressive,ndepth,nflip,mycall, &
|
||||
hiscall,hisgrid,nQSOProgress,ljt65apon,nexp_decode,ncount, &
|
||||
nhist,decoded,ltext,nft,qual)
|
||||
|
||||
! Suppress "birdie messages" and other garbage decodes:
|
||||
if(decoded(1:7).eq.'000AAA ') ncount=-1
|
||||
if(decoded(1:7).eq.'0L6MWK ') ncount=-1
|
||||
if(nflip.lt.0 .and. ltext) ncount=-1
|
||||
if(ncount.lt.0) then
|
||||
nft=0
|
||||
decoded=' '
|
||||
endif
|
||||
|
||||
return
|
||||
end subroutine decode65b
|
||||
@@ -1,415 +0,0 @@
|
||||
/* MAKE-LDPC.C - Make a Low Density Parity Check code's parity check matrix. */
|
||||
|
||||
/* Copyright (c) 1995-2012 by Radford M. Neal and Peter Junteng Liu.
|
||||
*
|
||||
* Permission is granted for anyone to copy, use, modify, and distribute
|
||||
* these programs and accompanying documents for any purpose, provided
|
||||
* this copyright notice is retained and prominently displayed, and note
|
||||
* is made of any changes made to these programs. These programs and
|
||||
* documents are distributed without any warranty, express or implied.
|
||||
* As the programs were written for research purposes only, they have not
|
||||
* been tested to the degree that would be advisable in any important
|
||||
* application. All use of these programs is entirely at the user's own
|
||||
* risk.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "rand.h"
|
||||
#include "alloc.h"
|
||||
#include "intio.h"
|
||||
#include "open.h"
|
||||
#include "mod2sparse.h"
|
||||
#include "mod2dense.h"
|
||||
#include "mod2convert.h"
|
||||
#include "rcode.h"
|
||||
#include "distrib.h"
|
||||
|
||||
|
||||
/* METHODS FOR CONSTRUCTING CODES. */
|
||||
|
||||
typedef enum
|
||||
{ Evencol, /* Uniform number of bits per column, with number specified */
|
||||
Evenboth /* Uniform (as possible) over both columns and rows */
|
||||
} make_method;
|
||||
|
||||
|
||||
void make_ldpc (int, make_method, distrib *, int);
|
||||
int *column_partition (distrib *, int);
|
||||
void usage (void);
|
||||
|
||||
|
||||
/* MAIN PROGRAM. */
|
||||
|
||||
int main
|
||||
( int argc,
|
||||
char **argv
|
||||
)
|
||||
{
|
||||
make_method method;
|
||||
char *file, **meth;
|
||||
int seed, no4cycle;
|
||||
distrib *d;
|
||||
char junk;
|
||||
FILE *f;
|
||||
|
||||
/* Look at initial arguments. */
|
||||
|
||||
if (!(file = argv[1])
|
||||
|| !argv[2] || sscanf(argv[2],"%d%c",&M,&junk)!=1 || M<=0
|
||||
|| !argv[3] || sscanf(argv[3],"%d%c",&N,&junk)!=1 || N<=0
|
||||
|| !argv[4] || sscanf(argv[4],"%d%c",&seed,&junk)!=1)
|
||||
{ usage();
|
||||
}
|
||||
|
||||
/* Look at the arguments specifying the method for producing the code. */
|
||||
|
||||
meth = argv+5;
|
||||
|
||||
if (!meth[0]) usage();
|
||||
|
||||
no4cycle = 0;
|
||||
|
||||
if (strcmp(meth[0],"evencol")==0 || strcmp(meth[0],"evenboth")==0)
|
||||
{ method = strcmp(meth[0],"evencol")==0 ? Evencol : Evenboth;
|
||||
if (!meth[1])
|
||||
{ usage();
|
||||
}
|
||||
d = distrib_create(meth[1]);
|
||||
if (d==0)
|
||||
{ usage();
|
||||
}
|
||||
if (meth[2])
|
||||
{ if (strcmp(meth[2],"no4cycle")==0)
|
||||
{ no4cycle = 1;
|
||||
if (meth[3])
|
||||
{ usage();
|
||||
}
|
||||
}
|
||||
else
|
||||
{ usage();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{ usage();
|
||||
}
|
||||
|
||||
/* Check for some problems. */
|
||||
|
||||
if (distrib_max(d)>M)
|
||||
{ fprintf(stderr,
|
||||
"At least one checks per bit (%d) is greater than total checks (%d)\n",
|
||||
distrib_max(d), M);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (distrib_max(d)==M && N>1 && no4cycle)
|
||||
{ fprintf(stderr,
|
||||
"Can't eliminate cycles of length four with this many checks per bit\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Make the parity check matrix. */
|
||||
|
||||
make_ldpc(seed,method,d,no4cycle);
|
||||
|
||||
/* Write out the parity check matrix. */
|
||||
|
||||
f = open_file_std(file,"wb");
|
||||
if (f==NULL)
|
||||
{ fprintf(stderr,"Can't create parity check file: %s\n",file);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
intio_write(f,('P'<<8)+0x80);
|
||||
|
||||
if (ferror(f) || !mod2sparse_write(f,H) || fclose(f)!=0)
|
||||
{ fprintf(stderr,"Error writing to parity check file %s\n",file);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* PRINT USAGE MESSAGE AND EXIT. */
|
||||
|
||||
void usage(void)
|
||||
{ fprintf(stderr,"Usage: make-ldpc pchk-file n-checks n-bits seed method\n");
|
||||
fprintf(stderr,"Method: evencol checks-per-col [ \"no4cycle\" ]\n");
|
||||
fprintf(stderr," or: evencol checks-distribution [ \"no4cycle\" ]\n");
|
||||
fprintf(stderr," or: evenboth checks-per-col [ \"no4cycle\" ]\n");
|
||||
fprintf(stderr," or: evenboth checks-distribution [ \"no4cycle\" ]\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
/* CREATE A SPARSE PARITY-CHECK MATRIX. Of size M by N, stored in H. */
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* PARTITION THE COLUMNS ACCORDING TO THE SPECIFIED PROPORTIONS. It
|
||||
may not be possible to do this exactly. Returns a pointer to an
|
||||
array of integers containing the numbers of columns corresponding
|
||||
to the entries in the distribution passed. */
|
||||
|
||||
int *column_partition
|
||||
( distrib *d, /* List of proportions and number of check-bits */
|
||||
int n /* Total number of columns to partition */
|
||||
)
|
||||
{
|
||||
double *trunc;
|
||||
int *part;
|
||||
int cur, used;
|
||||
int i, j;
|
||||
|
||||
trunc = chk_alloc (distrib_size(d), sizeof(double));
|
||||
part = chk_alloc (distrib_size(d), sizeof(int));
|
||||
|
||||
used = 0;
|
||||
for (i = 0; i<distrib_size(d); i++)
|
||||
{ cur = floor(distrib_prop(d,i)*n);
|
||||
part[i] = cur;
|
||||
trunc[i] = distrib_prop(d,i)*n - cur;
|
||||
used += cur;
|
||||
}
|
||||
|
||||
if (used>n)
|
||||
{ abort();
|
||||
}
|
||||
|
||||
while (used<n)
|
||||
{ cur = 0;
|
||||
for (j = 1; j<distrib_size(d); j++)
|
||||
{ if (trunc[j]>trunc[cur])
|
||||
{ cur = j;
|
||||
}
|
||||
}
|
||||
part[cur] += 1;
|
||||
used += 1;
|
||||
trunc[cur] = -1;
|
||||
}
|
||||
|
||||
free(trunc);
|
||||
return part;
|
||||
}
|
||||
Reference in New Issue
Block a user