MSHV-269-Non-Gendered/src/HvDecoderMs/decoderpom.cpp
2024-02-12 11:29:54 +11:00

1946 lines
59 KiB
C++

/* MSHV decoderpom
* Copyright 2020 Hrisimir Hristov, LZ2HV
* (Edited by Harper Innes, VK1TTY - to remove Gendered Language and Replace with Non-Gendered language) NOTE:May be used under the terms of the GNU General Public License (GPL)
*/
//#include "decoderms.h"
#include "decoderpom.h"
#include <QRegExp>
#include <unistd.h>
//#include <QtGui>
//// F2A ///
//nflags=FFTW_ESTIMATE;
//if (npatience==1) nflags=FFTW_ESTIMATE_PATIENT;
//if (npatience==2) nflags=FFTW_MEASURE;
//if (npatience==3) nflags=FFTW_PATIENT;
//if (npatience==4) nflags=FFTW_EXHAUSTIVE;
// MSK144 four2a_c2c nfft=32768 7 plans four2a_d2c none
// MSKMS four2a_c2c nfft=32768 7 plans four2a_d2c none
// JTMS four2a_c2c nfft=20552 20 plans four2a_d2c nfft=524288 4 plans + ZAP only
// FSK441 four2a_c2c nfft=32768 8 plans four2a_d2c nfft=524288 4 plans + ZAP only
// ISCAT four2a_c2c nfft=73728 2 plans four2a_d2c nfft=524288 4 plans + ZAP only
// JT6M four2a_c2c nfft=512 1 plans four2a_d2c nfft=524288 4 plans + ZAP only
// FT8 four2a_c2c nfft=180000 4 plans four2a_d2c nfft=192000 3 plans
// FT4 four2a_c2c nfft=72576 4 plans four2a_d2c nfft=72576 2 plans
// JT65 four2a_c2c nfft=2048 2 plans four2a_d2c nfft=8192 1 plans
// PI4 four2a_c2c none four2a_d2c nfft=768000 3 plans
// Q65 four2a_c2c 1440000 for x120sec
//static int retr = 0;
//static int cplu = 0;
#define SLPAMIN 2000 //2000 importent SLPAMIN > SLPASTEP
#define SLPASTEP 1000 //1000 importent SLPAMIN > SLPASTEP
static bool _block_th_all_ = false; //need to be static for all
static int _wait_t_ = SLPAMIN - SLPASTEP; //need to be static for all
static int setup_c2c_d2c_(bool &wait,fftw_plan &p,double complex *a,int nfft,int isign,int iform,double *d = 0)
{
if (_block_th_all_ || !wait)
{
_wait_t_ += SLPASTEP;
wait = true; //retr++; qDebug()<<"retry---->"<<retr<<_wait_t_;
return _wait_t_;
}
_block_th_all_ = true; //if (cplu == 0) qDebug()<<"----------------------"; cplu++; qDebug()<<"PLANS="<<cplu<<nfft;
if (isign==-1 && iform==1)
p=fftw_plan_dft_1d(nfft,a,a,FFTW_FORWARD,FFTW_ESTIMATE_PATIENT);
else if (isign==1 && iform==1)
p=fftw_plan_dft_1d(nfft,a,a,FFTW_BACKWARD,FFTW_ESTIMATE_PATIENT);
else if (isign==-1 && iform==0)
p=fftw_plan_dft_r2c_1d(nfft,d,a,FFTW_ESTIMATE_PATIENT);
else if (isign==1 && iform==-1)
p=fftw_plan_dft_c2r_1d(nfft,a,d,FFTW_ESTIMATE_PATIENT);
_block_th_all_ = false;
return 0;
}
#define NPAMAX 1441000 //q65 max=1440000 PI4 max 768000
#define NSMALL 16384
void HvThr::four2a_c2c(double complex *a,double complex *a1,fftw_plan *pc,int &cpc,int nfft,int isign,int iform)
{
double complex aa[NSMALL+10];
if (cpc>NPMAX || nfft>NPAMAX) return;
bool found_plan = false;
int z = 0;
for (z = 0; z < cpc; ++z)
{
if (nfft==nn_c2c[z] && isign==ns_c2c[z] && iform==nf_c2c[z])
{
found_plan = true;
break;
}
}
for (int i = 0; i < nfft; ++i)
a1[i]=a[i];
if (nfft<=NSMALL)
{
int jz=nfft;
if (iform==0) jz=nfft/2;//iform==0 no in c2c
for (int i = 0; i<jz; ++i)
aa[i]=a1[i];
}
if (!found_plan)
{
z = cpc;
nn_c2c[z]=nfft;
ns_c2c[z]=isign;
nf_c2c[z]=iform;
int slpp = 1000;
bool wait = false; //if (nthreads==1) wait = false; ??? hv
while (slpp!=0)
{
usleep(slpp);
slpp = setup_c2c_d2c_(wait,pc[z],a1,nfft,isign,iform);
}
cpc++; //qDebug()<<"c2c====="<<cpc<<nfft;
}
if (nfft<=NSMALL)
{
int jz=nfft;
if (iform==0) jz=nfft/2;//iform==0 no in c2c
for (int i = 0; i<jz; ++i)
a1[i]=aa[i];
}
fftw_execute(pc[z]);
for (int i = 0; i < nfft; ++i)
a[i]=a1[i];
}
void HvThr::four2a_d2c(double complex *a,double complex *a1,double *d,double *d1,fftw_plan *pd,int &cpd,
int nfft,int isign,int iform)
{
double complex aa[NSMALL+10];
if (cpd>NPMAX || nfft>NPAMAX) return;
bool found_plan = false;
int z = 0;
for (z = 0; z < cpd; ++z)
{
if (nfft==nn_d2c[z] && isign==ns_d2c[z] && iform==nf_d2c[z])
{
found_plan = true;
break;
}
}
int cfft = nfft;
if (iform==0) cfft = nfft/2;
for (int i = 0; i < nfft; ++i)
{
if (i<cfft)
a1[i]=a[i];
d1[i]=d[i];
}
if (nfft<=NSMALL)
{
for (int i = 0; i<cfft; ++i)
aa[i]=a1[i];
}
if (!found_plan)
{
z = cpd;
nn_d2c[z]=nfft;
ns_d2c[z]=isign;
nf_d2c[z]=iform;
int slpp = 1000;
bool wait = false; //if (nthreads==1) wait = false; ??? hv
while (slpp!=0)
{
usleep(slpp);
slpp = setup_c2c_d2c_(wait,pd[z],a1,nfft,isign,iform,d1);
}
cpd++; //qDebug()<<"d2c="<<cpd<<nfft;
}
if (nfft<=NSMALL)
{
for (int i = 0; i<cfft; ++i)
a1[i]=aa[i];
}
fftw_execute(pd[z]);
for (int i = 0; i < nfft; ++i)
{
if (i<cfft)
a[i]=a1[i];
d[i]=d1[i];
}
}
#define NPLIM 20 // reset if > 20 JTMS
void HvThr::DestroyPlans(fftw_plan *pc,int &cpc,fftw_plan *pd,int &cpd,bool imid)
{
if (cpc > NPLIM || imid)
{
//qDebug()<<"Plans C2C="<<cpc;
for (int z = 0; z < cpc; ++z)
fftw_destroy_plan(pc[z]);
cpc = 0;
_wait_t_ = SLPAMIN - SLPASTEP;
}
if (cpd > NPLIM || imid)
{
//qDebug()<<"Plans D2C="<<cpd;
for (int z = 0; z < cpd; ++z)
fftw_destroy_plan(pd[z]);
cpd = 0;
_wait_t_ = SLPAMIN - SLPASTEP;
}
}
//// END class HvThr ///
//// class F2A ///
static int nplan_c2c0 = 0;
static fftw_plan plan_c2c0[NPMAX+10];
static double complex ca_c2c0[NPAMAX+10];
static int nplan_c2c1 = 0;
static fftw_plan plan_c2c1[NPMAX+10];
static double complex ca_c2c1[NPAMAX+10];
static int nplan_c2c2 = 0;
static fftw_plan plan_c2c2[NPMAX+10];
static double complex ca_c2c2[NPAMAX+10];
static int nplan_c2c3 = 0;
static fftw_plan plan_c2c3[NPMAX+10];
static double complex ca_c2c3[NPAMAX+10];
static int nplan_c2c4 = 0;
static fftw_plan plan_c2c4[NPMAX+10];
static double complex ca_c2c4[NPAMAX+10];
static int nplan_c2c5 = 0;
static fftw_plan plan_c2c5[NPMAX+10];
static double complex ca_c2c5[NPAMAX+10];
void F2a::four2a_c2c(double complex *a,int nfft,int isign,int iform,int thr)
{
if (thr==0) HvThr0.four2a_c2c(a,ca_c2c0,plan_c2c0,nplan_c2c0,nfft,isign,iform);
else if (thr==1) HvThr1.four2a_c2c(a,ca_c2c1,plan_c2c1,nplan_c2c1,nfft,isign,iform);
else if (thr==2) HvThr2.four2a_c2c(a,ca_c2c2,plan_c2c2,nplan_c2c2,nfft,isign,iform);
else if (thr==3) HvThr3.four2a_c2c(a,ca_c2c3,plan_c2c3,nplan_c2c3,nfft,isign,iform);
else if (thr==4) HvThr4.four2a_c2c(a,ca_c2c4,plan_c2c4,nplan_c2c4,nfft,isign,iform);
else if (thr==5) HvThr5.four2a_c2c(a,ca_c2c5,plan_c2c5,nplan_c2c5,nfft,isign,iform);
}
static int nplan_d2c0 = 0;
static fftw_plan plan_d2c0[NPMAX+10];
static double da_d2c0[NPAMAX+10];
static double complex ca_d2c0[NPAMAX+10];
static int nplan_d2c1 = 0;
static fftw_plan plan_d2c1[NPMAX+10];
static double da_d2c1[NPAMAX+10];
static double complex ca_d2c1[NPAMAX+10];
static int nplan_d2c2 = 0;
static fftw_plan plan_d2c2[NPMAX+10];
static double da_d2c2[NPAMAX+10];
static double complex ca_d2c2[NPAMAX+10];
static int nplan_d2c3 = 0;
static fftw_plan plan_d2c3[NPMAX+10];
static double da_d2c3[NPAMAX+10];
static double complex ca_d2c3[NPAMAX+10];
static int nplan_d2c4 = 0;
static fftw_plan plan_d2c4[NPMAX+10];
static double da_d2c4[NPAMAX+10];
static double complex ca_d2c4[NPAMAX+10];
static int nplan_d2c5 = 0;
static fftw_plan plan_d2c5[NPMAX+10];
static double da_d2c5[NPAMAX+10];
static double complex ca_d2c5[NPAMAX+10];
void F2a::four2a_d2c(double complex *a,double *d,int nfft,int isign,int iform,int thr)
{
if (thr==0) HvThr0.four2a_d2c(a,ca_d2c0,d,da_d2c0,plan_d2c0,nplan_d2c0,nfft,isign,iform);
else if (thr==1) HvThr1.four2a_d2c(a,ca_d2c1,d,da_d2c1,plan_d2c1,nplan_d2c1,nfft,isign,iform);
else if (thr==2) HvThr2.four2a_d2c(a,ca_d2c2,d,da_d2c2,plan_d2c2,nplan_d2c2,nfft,isign,iform);
else if (thr==3) HvThr3.four2a_d2c(a,ca_d2c3,d,da_d2c3,plan_d2c3,nplan_d2c3,nfft,isign,iform);
else if (thr==4) HvThr4.four2a_d2c(a,ca_d2c4,d,da_d2c4,plan_d2c4,nplan_d2c4,nfft,isign,iform);
else if (thr==5) HvThr5.four2a_d2c(a,ca_d2c5,d,da_d2c5,plan_d2c5,nplan_d2c5,nfft,isign,iform);
}
void F2a::DestroyPlansAll(bool imid)
{
//imid = true; // test only
//qDebug()<<"Plans C2C="<<nplan_c2c0<<nplan_c2c1<<nplan_c2c2<<nplan_c2c3<<nplan_c2c4<<nplan_c2c5;
//qDebug()<<"Plans D2C="<<nplan_d2c0<<nplan_d2c1<<nplan_d2c2<<nplan_d2c3<<nplan_d2c4<<nplan_d2c5;
HvThr0.DestroyPlans(plan_c2c0,nplan_c2c0,plan_d2c0,nplan_d2c0,imid);
HvThr1.DestroyPlans(plan_c2c1,nplan_c2c1,plan_d2c1,nplan_d2c1,imid);
HvThr2.DestroyPlans(plan_c2c2,nplan_c2c2,plan_d2c2,nplan_d2c2,imid);
HvThr3.DestroyPlans(plan_c2c3,nplan_c2c3,plan_d2c3,nplan_d2c3,imid);
HvThr4.DestroyPlans(plan_c2c4,nplan_c2c4,plan_d2c4,nplan_d2c4,imid);
HvThr5.DestroyPlans(plan_c2c5,nplan_c2c5,plan_d2c5,nplan_d2c5,imid);
//qDebug()<<"Destroy2-------------------";
//cplu = 0;
//retr = 0;
}
//// END F2A ///
//// POMALL ///
void PomAll::initPomAll()
{
for (int i = 0; i < 141100; ++i) pctile_shell_tmp[i] = 0.0;//int NMAX=141072;
}
double PomAll::peakup(double ym,double y0,double yp)
{
double dx = 0.0;
double b=(yp-ym)/2.0;
double c=(yp+ym-(2*y0))/2.0;
dx=-b/(2.0*c);
return dx;
}
double PomAll::maxval_da_beg_to_end(double*a,int a_beg,int a_end)
{
double max = a[a_beg];
for (int i = a_beg; i < a_end; i++)
{
if (a[i]>max)
{
max = a[i];
}
}
return max;
}
int PomAll::maxloc_da_end_to_beg(double*a,int a_beg,int a_end)
{
double max = a[a_end];
int loc = a_end;
for (int i = a_end-1; i >= a_beg; i--)
{
if (a[i]>max)
{
loc = i;
max = a[i];
}
}
return loc;
}
/*int PomAll::minloc_da(double *da,int count)
{
int pos = 0;
double min = da[0];
for (int i= 1; i < count; ++i)//MAXMSG
{
if (da[i]<min)
{
min=da[i];
pos = i;
}
}
return pos;
}*/
double PomAll::db(double x)
{
double db=-99.0;
//c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
if (x>1.259e-10)
{
if (x<0.000001) x=0.000001;
db=10.0*log10(x);
}
return db;
}
double PomAll::determ(double array_[10][10],int norder)
{
//real*8 function determ(array,norder)
//implicit real*8 (a-h,o-z)
//real*8 array(10,10)
double determ=1.0;
for (int k = 0; k<norder; k++)
{//do k=1,norder
if (array_[k][k]!=0) goto c41;
int j;
for (j = k; j<norder; j++)
{//do j=k,norder
if (array_[j][k]!=0) goto c31;
}
determ=0.0;
goto c60;
c31:
for (int i = k; i<norder; i++)
{//do i=k,norder
double s8tt=array_[j][i];
array_[j][i]=array_[k][i];
array_[k][i]=s8tt;
}
determ=-1.0*determ;
c41:
determ=determ*array_[k][k];
if (k<norder-1) //hv -1 if(k.lt.norder) then
{
int k1=k+1;
for (int i = k1; i<norder; i++)
{//do i=k1,norder
for (j = k1; j<norder; j++)
{//do j=k1,norder
//array(i,j)=array(i,j)-array(i,k)*array(k,j)/array(k,k)
array_[j][i]=array_[j][i]-array_[k][i]*array_[j][k]/array_[k][k];
}
}
}
}
c60:
return determ;
}
void PomAll::polyfit(double*x,double*y,double*sigmay,int npts,int nterms,int mode,double*a,double &chisqr)
{
//subroutine polyfit(x,y,sigmay,npts,nterms,mode,a,chisqr)
//implicit real*8 (a-h,o-z)
//real*8 x(npts), y(npts), sigmay(npts), a(nterms)
//real*8 sumx(10), sumy(10), array(10,10)
double sumx[10];
double sumy[10];
double array_[10][10];
//double sigmay[npts];
//! Accumulate weighted sums
int nmax = 2*nterms-1;//hv -1=0
zero_double_beg_end(sumx,0,10);
zero_double_beg_end(sumy,0,10);
double chisq=0.0;
for (int i = 0; i<npts; i++)
{//do i=1,npts //c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
double xi=x[i];
double yi=y[i];
double weight=0.0;
if (mode<0)
weight=1.0/fabs(yi);
else if (mode==0)
weight=1.0;
else
weight=1.0/(sigmay[i]*sigmay[i]);
//qDebug()<<"weight"<<weight<<sigmay[i];
double xterm=weight;
for (int n = 0; n<nmax; n++)
{//do n=1,nmax
sumx[n]=sumx[n]+xterm;
xterm=xterm*xi;
//qDebug()<<"chisq"<<sumx[n]<<xterm<<xi<<n;
}
double yterm=weight*yi;
for (int n = 0; n<nterms; n++)
{//do n=1,nterms
sumy[n]=sumy[n]+yterm;
yterm=yterm*xi;
}
chisq+=weight*(yi*yi); //chisq=chisq+weight*yi**2
}
//! Construct matrices and calculate coefficients
for (int j = 0; j<nterms; j++)
{//do j=1,nterms
for (int k = 0; k<nterms; k++)
{//do k=1,nterms
int n=j+k-0;//-1
array_[k][j]=sumx[n];
//qDebug()<<n;
}
}
double delta=determ(array_,nterms);
//qDebug()<<"delta="<<delta;
if (delta==0.0)
{
chisqr=0.0;
zero_double_beg_end(a,0,5);
}
else
{
for (int l = 0; l<nterms; l++)
{//do l=1,nterms
for (int j = 0; j<nterms; j++)
{//do j=1,nterms
for (int k = 0; k<nterms; k++)
{//do k=1,nterms
int n=j+k-0; // -1
array_[k][j]=sumx[n];
}
array_[l][j]=sumy[j];
}
a[l]=determ(array_,nterms)/delta;
}
//! Calculate chi square
for (int j = 0; j<nterms; j++)
{//do j=1,nterms
chisq-=2.0*a[j]*sumy[j]; //chisq=chisq-2*a(j)*sumy(j)
for (int k = 0; k<nterms; k++)
{//do k=1,nterms
int n=j+k-0; // -1
chisq+=a[j]*a[k]*sumx[n]; //chisq=chisq+a(j)*a(k)*sumx(n)
}
}
double free=npts-nterms; //qDebug()<<"free"<<free;
if (free==0.0)// no devide by zero
free=1.0;
chisqr=chisq/free;
//qDebug()<<chisq<<free;
}
//qDebug()<<"chisq"<<a[0]<<a[1]<<a[2]<<a[3]<<a[4];
}
void PomAll::zero_double_beg_end(double*d,int begin,int end)
{
for (int i = begin; i<end; i++)
{
d[i]=0.0;
}
}
void PomAll::shell(int n,double*a)
{
int i,j,inc;
double v;
//c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
inc=1;//inc=1;
c1:
inc=3*inc+1;
if (inc<=n) goto c1;
c2:
inc=inc/3;
//qDebug()<<"INC="<<inc<<n;
for (i = inc+0; i < n+0; i++)
{//do i=inc+1,n
//qDebug()<<"MINA"<<i;
v=a[i];
j=i;
c3:
if (a[j-inc]>v)
{
a[j]=a[j-inc];
j=j-inc;
if (j<=inc) goto c4;
goto c3;
}
c4:
a[j]=v;
}
if (inc>1) goto c2;
}
double PomAll::pctile_shell(double *x,int npts,int npct)
{
double xpct = 1.0;
int NMAX=141072;// 100000;//100000 32768
//real*4 x(npts)
//double tmp[NMAX];// ={0.0};//real*4 tmp(NMAX)
//double *tmp = new double[NMAX];// ={0.0};//real*4 tmp(NMAX)
int j =0;
//c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
if (npts<=0)
{
xpct=1.0;
goto c900;
}
if (npts>NMAX) return xpct; // if(npts.gt.NMAX) stop
for (j = 0; j < npts; j++)
pctile_shell_tmp[j]=x[j]; // tmp(1:npts)=x +beg
shell(npts,pctile_shell_tmp);
j=(int)((double)npts*0.01*npct);
//sort(npts,tmp);
if (j<0) j=0;//0 if(j.lt.1) j=1
if (j>npts-1) j=npts-1; // if(j.gt.npts) j=npts
xpct=pctile_shell_tmp[j];
c900:
return xpct;
}
int PomAll::maxloc_da_beg_to_end(double*a,int a_beg,int a_end)
{
double max = a[a_beg];
int loc = a_beg;
for (int i = a_beg; i < a_end; i++)//1.68 i++ ok
{
if (a[i]>max)
{
loc = i;
max = a[i];
}
}
return loc;
}
void PomAll::zero_double_comp_beg_end(double complex*d,int begin,int end)
{
for (int i = begin; i<end; i++)
d[i]=0.0+0.0*I;
}
double PomAll::ps_hv(double complex z)
{
//(real(c(i))**2 + aimag(c(i))**2)
double d;
d = creal(z)*creal(z) + cimag(z)*cimag(z);
//d = pow(creal(z),2) + pow(cimag(z),2);
return d;
}
void PomAll::cshift1(double complex *a,int cou_a,int ish)
{
//HV for single shift vareable
//Left Shift ISHFT ISHFT(N,M) (M > 0) << n<<m n shifted left by m bits
//Right Shift ISHFT ISHFT(N,M) (M < 0) >> n>>m n shifted right by m bits
//double complex t[cou_a]; //garmi hv v1.42
//double complex t[cou_a*2+ish+50]; //garmi hv v1.43 ok
double complex *t = new double complex[cou_a+100]; //garmi pri goliam count hv v1.43 correct ok
for (int i=0; i< cou_a; i++)
t[i]=a[i];
if (ish>0)
{
for (int i = 0; i < cou_a; i++)
{
if (i+ish<cou_a)
a[i]=t[i+ish];
else
a[i]=t[i+ish-cou_a];
}
}
if (ish<0)
{
for (int i = 0; i < cou_a; i++)
{
if (i+ish<0)
a[i]=t[i+ish+cou_a];
else
a[i]=t[i+ish];
}
}
delete [] t;
}
double complex PomAll::sum_dca_mplay_conj_dca(double complex *a,int a_beg,int a_end,double complex *b)
{
//sum(cdat(i:i+41)*conjg(cb))
double complex sum = 0.0+0.0*I;
int b_c = 0;
for (int i = a_beg; i < a_end; i++)//1.68 i++ ok
{
sum+=a[i]*conj(b[b_c]);
b_c++;
}
return sum;
}
void PomAll::indexx_msk(double *arr,int n,int *indx)
{
int M=7;
const int NSTACK=50;
//integer n,indx(n)
//real arr(n)
int i,indxt,ir,itemp,j,jstack,k,l;
int istack[NSTACK+5];//v1.46 +5
double a;
for (j = 0; j <= n; j++)
{//do j=1,n
indx[j]=j;
}
jstack=-1;//-1-hv 0;
l=0;//l=1;
ir=n; //c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
c1:
if (ir-l<M)
{
for (j = l+1; j <= ir; j++)
{//do j=l+1,ir
indxt=indx[j];
a=arr[indxt];
for (i = j-1; i >= 0; i--)
{//do i=j-1,1,-1
if (arr[indx[i]]<=a) goto c2;
indx[i+1]=indx[i];
}
i=-1;//-1-hv 0;
c2:
indx[i+1]=indxt;
//if(indxt>350 || indxt<5)
//qDebug()<<"indxt="<<indxt<<"max="<<n;
}
if (jstack==-1) return;//-1-hv 0;
ir=istack[jstack];
l=istack[jstack-1];
jstack=jstack-2;
}
else
{
k=(l+ir)/2;
itemp=indx[k];
indx[k]=indx[l+1];
indx[l+1]=itemp;
if (arr[indx[l+1]]>arr[indx[ir]])
{
itemp=indx[l+1];
indx[l+1]=indx[ir];
indx[ir]=itemp;
}
//c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
if (arr[indx[l]]>arr[indx[ir]])
{
itemp=indx[l];
indx[l]=indx[ir];
indx[ir]=itemp;
}
if (arr[indx[l+1]]>arr[indx[l]])
{
itemp=indx[l+1];
indx[l+1]=indx[l];
indx[l]=itemp;
}
i=l+1;
j=ir;
indxt=indx[l];
a=arr[indxt];
c3: //continue
i=i+1;
if (arr[indx[i]]<a) goto c3;
c4: //continue
j=j-1;
if (arr[indx[j]]>a) goto c4;
if (j<i) goto c5;
itemp=indx[i];
indx[i]=indx[j];
indx[j]=itemp;
goto c3;
c5:
indx[l]=indx[j];
indx[j]=indxt;
jstack=jstack+2;
if (jstack>NSTACK) return;//stop //'NSTACK too small in indexx'
if (ir-i+1>=j-l)
{
istack[jstack]=ir;
istack[jstack-1]=i;
ir=j-1;
}
else
{
istack[jstack]=j-1;
istack[jstack-1]=l;
l=i;
}
}
goto c1;
}
bool PomAll::isStandardCall(QString w)//2.61 same as MultiAnswerModW
{
//static QRegularExpression standard_call_re {
// R"(
// ^\s* # optional leading spaces
// ( [A-Z]{0,2} | [A-Z][0-9] | [0-9][A-Z] ) # part 1
// ( [0-9][A-Z]{0,3} ) # part 2
// (/R | /P)? # optional suffix
// \s*$ # optional trailing spaces
// )", QRegularExpression::CaseInsensitiveOption | QRegularExpression::ExtendedPatternSyntaxOption};
//return standard_call_re.match (w).hasMatch ();
QRegExp rx("^\\s*([A-Z]{0,2}|[A-Z][0-9]|[0-9][A-Z])([0-9][A-Z]{0,3})(/R|/P)?\\s*$");
rx.setCaseSensitivity(Qt::CaseInsensitive);
bool res0 = rx.exactMatch(w); //qDebug()<<w<<res0;
return res0;
}
/*bool PomAll::isStandardCall(QString w)
{
bool res = true;
bool spr = true;
short n = w.count();
if (n<2) return false;
if (w[n-2]=='/')
{
if (w.at(n-1)=='P' || w.at(n-1)=='R') n = n - 2;
else spr = false;
}
//! Check for standard callsign
short iarea=-1;
//int n = strlen(callsign); //n=len(trim(callsign))
int i;
for (i = n-1; i >=1; --i)
{//do i=n,2,-1
if (w.at(i).isDigit()) break;//exit
}
iarea=i; //!Right-most digit (call area)
short npdig=0; //!Digits before call area
short nplet=0; //!Letters before call area
for (i = 0; i < iarea; ++i)
{//do i=1,iarea-1
if (w.at(i).isDigit()) npdig++;
if (w.at(i).isLetter()) nplet++;
}
short nslet=0; //!Letters in suffix
for (i = iarea+1; i < n; ++i)
{//do i=iarea+1,n
if (w.at(i).isLetter()) nslet++;
}
if (iarea<1 || iarea>2 || nplet==0 || npdig>=iarea || nslet>3) res = false;
if (!res || !spr) res = false;
return res;
}*/
/*bool PomAll::is_digit(char c)
{
bool res = false;
if (c>='0' && c<='9') res = true;
return res;
}
bool PomAll::is_letter(char c)
{
bool res = false;
if (c>='A' && c<='Z') res = true;
return res;
}
bool PomAll::isStandardCall(QString callsign0)//not correct XX2XX/P or R is standard
{
char callsign[100];
strncpy(callsign,callsign0.toUtf8(),32);
int n = callsign0.count();
bool res = true;
bool spr = true;
if (n<2) return false;
if (callsign[n-2]=='/')
{
if (callsign[n-1]=='P' || callsign[n-1]=='R') n = n - 2;
else spr = false;
}
//! Check for standard callsign
int iarea=-1;
//int n = strlen(callsign); //n=len(trim(callsign))
int i;
for (i = n-1; i >=1; --i)
{//do i=n,2,-1
if (is_digit(callsign[i])) break;//exit
}
iarea=i; //!Right-most digit (call area)
int npdig=0; //!Digits before call area
int nplet=0; //!Letters before call area
for (i = 0; i < iarea; ++i)
{//do i=1,iarea-1
if (is_digit(callsign[i])) npdig++;
if (is_letter(callsign[i])) nplet++;
}
int nslet=0; //!Letters in suffix
for (i = iarea+1; i < n; ++i)
{//do i=iarea+1,n
if (is_letter(callsign[i])) nslet++;
}
//c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
//if(iarea<2 || iarea>3 || nplet==0 || npdig>=iarea-1 || nslet>3)
if (iarea<1 || iarea>2 || nplet==0 || npdig>=iarea || nslet>3) res = false;
if (!res || !spr) res = false;
return res;
}*/
//// END POMALL ///
//// POMFT ///
#define MN_NM_NRW_FT_174_91
#include "../HvMsPlayer/libsound/HvGenFt8/bpdecode_ft8_174_91.h"
/*PomFt::PomFt()
{
lastpat_ft8_2 = 0;
inext_ft8_2 = 0;
first_osd174_91 = true;
twopi=8.0*atan(1.0);
}
PomFt::~PomFt()
{}*/
void PomFt::initPomFt()
{
//pomAll.initPomAll();//2.66 no pctile_shell no need init
lastpat_ft8_2 = -1;//0;
inext_ft8_2 = -1;//0;
first_osd174_91 = true;
first_enc174_91_nocrc = true;
twopi=8.0*atan(1.0);
pi=4.0*atan(1.0);
}
/*
#include "../HvMsPlayer/libsound/boost/boost_14.hpp"
short crc14_pomft(unsigned char const * data, int length)
{
return boost::augmented_crc<14, TRUNCATED_POLYNOMIAL14>(data, length);
}
short PomFt::crc14(unsigned char const * data, int length)
{
return crc14_pomft(data,length);
}
*/
void PomFt::nuttal_window(double *win,int n)
{
double a0=0.3635819;
double a1=-0.4891775;
double a2=0.1365995;
double a3=-0.0106411;
for (int i = 0; i < n; ++i)
{//do i=1,n
//win[i]=a0+a1*cos(2*pi*(i-1)/(n))+a2*cos(4*pi*(i-1)/(n))+a3*cos(6*pi*(i-1)/(n));
win[i]=a0+a1*cos(2.0*pi*(double)i/(double)n)+a2*cos(4.0*pi*(double)i/(double)n)+a3*cos(6.0*pi*(double)i/(double)n);
}
}
void PomFt::normalizebmet(double *bmet,int n)
{
double bmetav = 0.0;
double bmet2av = 0.0;
for (int z = 0; z < n; ++z)
{
bmetav+=bmet[z];////bmetav=sum(bmet)/real(n)
bmet2av+=bmet[z]*bmet[z];//bmet2av=sum(bmet*bmet)/real(n)
}
//bmetav=sum(bmet)/real(n)
//bmet2av=sum(bmet*bmet)/real(n)
bmetav=bmetav/(double)n;
bmet2av=bmet2av/(double)n;
double var=bmet2av-bmetav*bmetav;//var=bmet2av-bmetav*bmetav
double bmetsig = 0.0;
if ( var > 0.0 ) //c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
bmetsig=sqrt(var);
else
bmetsig=sqrt(bmet2av);
if (bmetsig<=0.00001)//2.68 crash no devide by zero
bmetsig=0.00001;
//if (bmetsig<=0.00001) qDebug()<<"bmetsig="<<bmetsig;
for (int z = 0; z < n; ++z)
bmet[z]=bmet[z]/bmetsig;
}
void PomFt::twkfreq1(double complex *ca,int npts,double fsample,double *a,double complex *cb)
{
//double twopi1=6.283185307;
//! Mix the complex signal
double complex w=1.0+1.0*I;
//double complex wstep=1.0+1.0*I;
int x0=0.5*(npts);//x0=0.5*(npts+1)
double s=2.0/(double)npts;//s=2.0/npts
for (int i =0; i<npts; ++i)
{//do i=1,npts
double x=s*(i-x0);//x=s*(i-x0)
double p2=1.5*x*x - 0.5; //p2=1.5*x*x - 0.5
double p3=2.5*pow(x,3.0) - 1.5*x; //p3=2.5*(x**3) - 1.5*x
double p4=4.375*pow(x,4.0) - 3.75*pow(x,2.0) + 0.375; //p4=4.375*(x**4) - 3.75*(x**2) + 0.375
double dphi=(a[0] + x*a[1] + p2*a[2] + p3*a[3] + p4*a[4]) * (twopi/fsample);
double complex wstep=cos(dphi)+sin(dphi)*I;//wstep=cmplx(cos(dphi),sin(dphi))
w=w*wstep;
cb[i]=w*ca[i];
}
}
/*
void PomFt::chkcrc14a(bool *decoded,int &nbadcrc)
{
unsigned char i1Dec8BitBytes[12+5];
for (int ibyte = 0; ibyte<12; ++ibyte)
{//do ibyte=1,10
int itmp=0;
for (int ibit = 0; ibit<8; ++ibit)
{//do ibit=1,8
itmp=(itmp << 1)+(1 & decoded[(ibyte-0)*8+ibit]);//itmp=ishft(itmp,1)+iand(1,decoded((ibyte-1)*8+ibit))
//qDebug()<<(int)decoded[(ibyte-0)*7+ibit];
}
i1Dec8BitBytes[ibyte]=itmp;
}
int ncrc14=0;
for (int ibit = 0; ibit<14; ++ibit)
ncrc14=(ncrc14 << 1)+(1 & decoded[77+ibit]);
i1Dec8BitBytes[9]=(i1Dec8BitBytes[9] & 248); //i1Dec8BitBytes(10)=iand(i1Dec8BitBytes(10),128+64+32+16+8)
i1Dec8BitBytes[10]=0;
i1Dec8BitBytes[11]=0;
int icrc14=crc14(i1Dec8BitBytes,12);
nbadcrc=1; //qDebug()<<"ncrc14==icrc14"<<ncrc14<<icrc14;
if (ncrc14==icrc14)// && ncrc14!=0 sum_5687 || sum_5687==0
nbadcrc=0;
}
*/
void PomFt::platanh(double x, double &y)
{
double isign=+1.0;
double z;
z=x;
//c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
if ( x < 0.0 )
{
isign=-1.0;
z=fabs(x);
}
if ( z <= 0.664 )
{
y=x/0.83;
return;
}
else if ( z <= 0.9217 )
{
y=isign*(z - 0.4064)/0.322;
return;
}
else if ( z <= 0.9951 )
{
y=isign*(z - 0.8378)/0.0524;
return;
}
else if ( z <= 0.9998 )
{
y=isign*(z - 0.9914)/0.0012;
return;
}
else
{
y=isign*7.0;
return;
}
}
void PomFt::mrbencode91(bool *me,bool *codeword,bool g2_[91][174],int N,int K)
{
for (int i = 0; i < N; ++i)
codeword[i]=0;
for (int i = 0; i < K; ++i)
{//do i=1,K
if ( me[i] == 1 ) //then
{
for (int j = 0; j < N; ++j)
codeword[j]=(codeword[j] ^ g2_[i][j]); //(1:N,i)
}
}
}
void PomFt::nextpat_step1_91(bool *mi,int k,int iorder,int &iflag)
{
//iorder = 3;
if ( iflag <= 0 )
{
iflag=-1;
return;
}
int beg = iflag - 1;
int end = iflag + iorder;
if (end > k)
end = k;
//qDebug()<<"beg end="<<beg<<end;
for (int i = beg; i < end; ++i)// add only order and move step=1
{
if (i >= beg && i < beg + iorder)
mi[i]=1;
else
mi[i]=0;
}
iflag--;
}
bool PomFt::any_ca_iand_ca_eq1_91(bool *a,bool *b,int count)
{
bool res = false;
for (int i = 0; i < count; ++i)
{
if ((a[i] & b[i])==1)
{
res = true;
break;
}
}
return res;
}
void PomFt::boxit91(bool &reset,bool *e2,int ntau,int npindex,int i1,int i2)
{
/*integer*1 e2(1:ntau)
v2 integer indexes(5000,2),fp(0:525000),np(5000) v1 integer indexes(4000,2),fp(0:525000),np(4000)
logical reset
common/boxes/indexes,fp,np*/
if (reset)
{
//patterns=-1
//sc=-1
for (int i = 0; i < 525000; ++i)
fp_ft8_2[i]=-1;
for (int i = 0; i < 5000; ++i)
{
np_ft8_2[i]=-1;
indexes_ft8_2_[0][i]=-1;
indexes_ft8_2_[1][i]=-1;
}
reset=false;
}
indexes_ft8_2_[0][npindex]=i1;
indexes_ft8_2_[1][npindex]=i2;
//Left Shift ISHFT ISHFT(N,M) (M > 0) << n<<m n shifted left by m bits
//Right Shift ISHFT ISHFT(N,M) (M < 0) >> n>>m n shifted right by m bits
int ipat=0;
for (int i = 0; i < ntau; ++i)//ntau=19,14
{//do i=1,ntau
if (e2[i]==1)
ipat+=(1 << ((ntau-1)-i)); //??? hv->(ntau-1) ipat=ipat+ishft(1,ntau-i)
}
//qDebug()<<"ipatipat="<<ipat;
int ip=fp_ft8_2[ipat]; //! see what's currently stored in fp(ipat)
if (ip==-1)
fp_ft8_2[ipat]=npindex;
else
{
while (np_ft8_2[ip]!=-1)
{
ip=np_ft8_2[ip];
}
np_ft8_2[ip]=npindex;
}
}
void PomFt::fetchit91(bool &reset,bool *e2,int ntau,int &i1,int &i2)
{
/*v2 integer indexes(5000,2),fp(0:525000),np(5000) v1 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)
{
lastpat_ft8_2=-1;
reset=false;
}
int ipat=0;
for (int i = 0; i < ntau; ++i)
{//do i=1,ntau
if (e2[i]==1)
ipat+=(1 << ((ntau-1)-i));//ipat=ipat+ishft(1,ntau-i)
}
int index=fp_ft8_2[ipat];
//c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
if (lastpat_ft8_2!=ipat && index>=0) //hv>=0 if(lastpat.ne.ipat .and. index>0) then then ! return first set of indices
{
i1=indexes_ft8_2_[0][index];//i1=indexes(index,1)
i2=indexes_ft8_2_[1][index];//i2=indexes(index,2)
inext_ft8_2=np_ft8_2[index]; //inext=np(index)
}
else if (lastpat_ft8_2==ipat && inext_ft8_2>=0)//hv>=0 elseif(lastpat.eq.ipat .and. inext>0) then
{
i1=indexes_ft8_2_[0][inext_ft8_2];//i1=indexes(inext,1)
i2=indexes_ft8_2_[1][inext_ft8_2];//i2=indexes(inext,2)
inext_ft8_2=np_ft8_2[inext_ft8_2]; //inext=np(inext)
}
else
{
i1=-1;
i2=-1;
inext_ft8_2=-1;
}
lastpat_ft8_2=ipat;
}
void PomFt::bshift1(bool *a,int cou_a,int ish)
{
//HV for single shift vareable
//Left Shift ISHFT ISHFT(N,M) (M > 0) << n<<m n shifted left by m bits
//Right Shift ISHFT ISHFT(N,M) (M < 0) >> n>>m n shifted right by m bits
//double complex t[cou_a]; //garmi hv v1.42
//double complex t[cou_a*2+ish+50]; //garmi hv v1.43 ok
bool *t = new bool[cou_a+100]; //garmi pri goliam count hv v1.43 correct ok
for (int i=0; i< cou_a; i++)
t[i]=a[i];
if (ish>0)
{
for (int i = 0; i < cou_a; i++)
{
if (i+ish<cou_a)
a[i]=t[i+ish];
else
a[i]=t[i+ish-cou_a];
}
}
if (ish<0)
{
for (int i = 0; i < cou_a; i++)
{
if (i+ish<0)
a[i]=t[i+ish+cou_a];
else
a[i]=t[i+ish];
}
}
delete [] t;
}
void PomFt::get_crc14(bool *mc,int len,int &ncrc)
{
//! 1. To calculate 14-bit CRC, mc(1:len-14) is the message and mc(len-13:len) are zero.
//! 2. To check a received CRC, mc(1:len is the received message plus CRC.
//! ncrc will be zero if the received message/CRC are consistent
bool r[15+5];
bool p[15]={1,1,0,0,1,1,1,0,1,0,1,0,1,1,1};//=26455
//bool p[15]={1,1,0,0,1,1,1,0,1,0,1,0,1,1,1};
//! divide by polynomial
for (int i = 0; i<15; ++i)
r[i]=mc[i]; //r=mc(1:15)
for (int i = 0; i<len-14; ++i) //(len-15)=81 (len-14)=82
{//do i=0,len-15
r[14]=mc[i+14];//r(15)=mc(i+15)
bool r0 = r[0]; //qDebug()<<i+14;
for (int j = 0; j<15; ++j)
r[j]=fmod(r[j]+r0*p[j],2);//r=mod(r+r(1)*p,2)
//for (int j = 0; j<15; ++j)
bshift1(r,15,1);//r=cshift(r,1)
}
/*write(c14,'(14b1)') r(1:14)
read(c14,'(b14.14)') ncrc*/
ncrc = 0;
for (int i = 0; i < 14; ++i)
{
ncrc <<= 1;
ncrc |= r[i];
}
//qDebug()<<ncrc;
}
void PomFt::decode174_91(double *llr,int maxosd,int norder,bool *apmask,bool *message91,bool *cw,int &nharderror,double &dmin)
//int Keff=91,
{
const int N=174;
const int K=91;
const int M=(N-K);//83
double zsave_[3][N];//zsave(N,3)
double tov_[N][3];//(3,N)
double toc_[M][7];//(7,M)
double tanhtoc_[M][7];//(7,M)
double zsum[N];
double zn[N];
int ncw=3;
bool m96[96+5];
bool hdec[N+2];
bool nxor[N+2];
int synd[M];
//bool decoded[K+20];//91 need 96 for check14a integer*1 decoded(K)
//c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
int maxiterations=30;
//int max_iterations=40;//for FT4
/*for (int i = 0; i<3; ++i)
{
for (int j = 0; j<N; ++j)
zsave_[i][j] = 0.0;
}*/
//maxosd +=1;
int nosd=0;
if (maxosd>3) maxosd=3;
if (maxosd==0) //then //! osd with channel llrs
{
nosd=1;
for (int i = 0; i < N; ++i)
zsave_[0][i]=llr[i];
}
else if (maxosd>0)// then !
nosd=maxosd;
else if (maxosd<0) //then ! just bp
nosd=0;
for (int i = 0; i<N; ++i)
{
zsum[i]=0.0;
for (int j = 0; j<3; ++j)
tov_[i][j]=0.0;//tov=0
}
for (int j = 0; j<M; ++j)
{//do j=1,M
for (int i = 0; i<(nrw_ft8_174_91[j]); ++i)
{//do i=1,nrw(j)
toc_[j][i]=llr[Nm_ft8_174_91_[j][i]-1];//toc(i,j)=llr((Nm(i,j)))
}
}
int ncnt=0;
int nclast=0;
for (int iter = 0; iter<=maxiterations; ++iter)
{
//! Update bit log likelihood ratios (tov=0 in iteration 0).
//for (int i = 0; i<N; ++i) zsum[i]=0.0;
for (int i = 0; i< N; ++i)
{//do i=1,N
if ( apmask[i] != 1 )
{
double sumt = 0.0;
for (int x = 0; x < ncw; ++x)
sumt+=tov_[i][x];//zn[i]=llr[i]+sum(tov(1:ncw,i))
zn[i]=llr[i]+sumt;
}
else
zn[i]=llr[i];
if (zn[i]>0.0)//cw=0 //where( zn .gt. 0. ) cw=1
cw[i]=1;
else
cw[i]=0;
//if (iter<=maxosd)
if (iter<maxosd)
zsum[i]+=zn[i]; //zsum=zsum+zn
}//c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
// diff -> if(iter.gt.0 .and. iter.le.maxosd) then
//if (iter>0 && iter<=maxosd)
if (iter<maxosd)
{
for (int i = 0; i< N; ++i)
//zsave_[iter-1][i]=zsum[i];// llr[i];
zsave_[iter][i]=zsum[i];
}
int ncheck=0;
for (int i = 0; i < M; ++i)
{//do i=1,M
// synd(i)=sum(cw(Nm(1:nrw(i),i)))
int sum = 0;
for (int x = 0; x < nrw_ft8_174_91[i]; ++x)
sum += (int)cw[Nm_ft8_174_91_[i][x]-1];//hv-1
synd[i]= sum;
//if( mod(synd(i),2) .ne. 0 ) ncheck=ncheck+1
if ( fmod(synd[i],2) != 0 ) ncheck++;
//! if( mod(synd(i),2) .ne. 0 ) write(*,*) 'check ',i,' unsatisfied'
}
if ( ncheck == 0 ) //then ! we have a codeword - if crc is good, return it
{
int nbadcrc;
/*for (int i = 0; i < K; ++i)
{
decoded[i]=cw[i];//decoded=cw(1:K)
}
chkcrc14a(decoded,nbadcrc);*/
for (int i = 0; i < 96; ++i)
{
m96[i]=0;
if (i<77) m96[i]=cw[i]; //m96(1:77)=cw(1:77)
if (i>81) m96[i]=cw[i-5];//m96(83:96)=cw(78:91) {m96[i]=cw[i-5]; qDebug()<<i<<i-5; }
}
//int nbadcrc1;
get_crc14(m96,96,nbadcrc);
//nharderror=count( (2*cw-1)*llr .lt. 0.0 )
if (nbadcrc==0) //then
{
int count = 0;
for (int i = 0; i < N; ++i)
{
//if (llr[i]*(double)(cw[i]*2-1)<0.0)
/*double xx = cw[i];
if ((2.0*xx-1.0)*llr[i] < 0.0 )
count++;*/
if ((double)(2*cw[i]-1)*llr[i] < 0.0 )
count++;
}
nharderror=count;
for (int i = 0; i < 91; ++i)
message91[i]=cw[i];// message91=cw(1:91)
for (int i = 0; i < N; ++i) //where(llr .ge. 0) hdec=1 //c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
{
/*if (llr[i]>=0.0)
hdec[i]=1;
else
hdec[i]=0;*/
hdec[i]=0;
if (llr[i]>=0.0) hdec[i]=1;
nxor[i]=hdec[i] ^ cw[i]; //nxor=ieor(hdec,cw)
dmin+=(double)nxor[i]*fabs(llr[i]); //dmin=sum(nxor*abs(llr))
}
//for (int i = 0; i < N; ++i)
//dmin+=nxor[i]*fabs(llr[i]);//dmin=sum(nxor*abs(llr))
//ntype=1
return;
}
}
if ( iter > 0 ) //! this code block implements an early stopping criterion
{ //if( iter.gt.10000 )
int nd=ncheck-nclast;
if ( nd < 0 ) //! # of unsatisfied parity checks decreased
ncnt=0; //! reset counter
else
ncnt++; //ncnt=ncnt+1;
//! write(*,*) iter,ncheck,nd,ncnt
if ( ncnt >= 5 && iter >= 10 && ncheck > 15)//if( ncnt .ge. 5 .and. iter .ge. 10 .and. ncheck .gt. 15) then
{
nharderror=-1;
//if (iter<5) qDebug()<<"iter FFFFF="<<iter;
break;//exit return;
}
}
nclast=ncheck;
//! Send messages from bits to check nodes
for (int j = 0; j < M; ++j)
{//do j=1,M
for (int i = 0; i < nrw_ft8_174_91[j]; ++i)
{//do i=1,nrw
int ibj=Nm_ft8_174_91_[j][i]-1;//ibj=Nm(i,j)
toc_[j][i]=zn[ibj];//toc(i,j)=zn(ibj)
for (int kk = 0; kk < ncw; kk++)
{//do kk=1,ncw //! subtract off what the bit had received from the check
if ( Mn_ft8_174_91_[ibj][kk]-1 == j )//hv-1 if( Mn(kk,ibj) .eq. j ) then //! Mn(3,128)
toc_[j][i]=toc_[j][i]-tov_[ibj][kk]; //hv-1 toc(i,j)=toc(i,j)-tov(kk,ibj)
}
//tanhtoc_[j][i]=tanh(-toc_[j][i]/2.0);//tanhtoc(1:nrw,i)=tanh(-toc(1:nrw,i)/2)
}
}
//! send messages from check nodes to variable nodes
for (int i = 0; i < M; ++i)
{//do i=1,M
for (int x = 0; x < 7; ++x)////tanhtoc(1:nrw,i)=tanh(-toc(1:nrw,i)/2)
tanhtoc_[i][x]=tanh(-toc_[i][x]/2.0);
}
for (int j = 0; j < N; ++j)
{//do j=1,N
for (int i = 0; i < ncw; ++i)
{//do i=1,ncw
int ichk=Mn_ft8_174_91_[j][i]-1; //ichk=Mn(i,j) //! Mn(:,j) are the checks that include bit j
//Tmn=product(tanhtoc(1:nrw(ichk),ichk),mask=Nm(1:nrw(ichk),ichk).ne.j)
double Tmn = 1.0;//mulilay
for (int z = 0; z < nrw_ft8_174_91[ichk]; ++z)
{
if (Nm_ft8_174_91_[ichk][z]-1 != j)
Tmn = Tmn*tanhtoc_[ichk][z];
}
double y;
platanh(-Tmn,y);//call platanh(-Tmn,y)
//! y=atanh(-Tmn)
tov_[j][i]=2.0*y;
}
}
} //! bp iterations
for (int io = 0; io < nosd; ++io)//c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
{//do i=1,nosd
for (int j = 0; j < N; ++j)
zn[j]=zsave_[io][j];//zn=zsave(:,i)
double dminosd = 0.0;
osd174_91_1(zn,apmask,norder,message91,cw,nharderror,dminosd);//Keff=91
if (nharderror>0)//then
{
for (int i = 0; i < N; ++i) //where(llr .ge. 0) hdec=1 //c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
{
/*if (llr[i]>=0.0)
hdec[i]=1;
else
hdec[i]=0;*/
hdec[i]=0;
if (llr[i]>=0.0) hdec[i]=1;
nxor[i]=hdec[i] ^ cw[i]; //nxor=ieor(hdec,cw)
dmin+=(double)nxor[i]*fabs(llr[i]); //dmin=sum(nxor*abs(llr))
}
//qDebug()<<nharderror<<cw[0]<<cw[1]<<cw[2]<<cw[3];
//ntype=2;
return;
}
}
//ntype=0
nharderror=-1;
//dminosd=0.0;
}
void PomFt::encode174_91_nocrc(bool *message910,bool *codeword)
{
const int N=174;
const int K=91;
const int M=N-K;//=83
bool pchecks[95];
if (first_enc174_91_nocrc)
{
for (int i = 0; i < 95; ++i)//91 83 gen_osd174_91_nocrc[100][95];
{
for (int j = 0; j < 85; ++j)
gen_osd174_91_nocrc[i][j]=0;
}
for (int i = 0; i < M; ++i)//M=83
{
for (int j = 0; j < 23; ++j)
{
bool ok;
QString temp = g_ft8_174_91[i].mid(j,1);
int istr = temp.toInt(&ok, 16);//read(g(i)(j:j),"(Z1)") istr
for (int jj = 0; jj < 4; ++jj)
{
int irow=(j)*4+jj;//irow=(j-1)*4+jj
if ( irow <= 90 ) gen_osd174_91_nocrc[irow][i]=(1 & (istr >> (3-jj)));//if( btest(istr,4-jj) ) gen(irow,i)=1
}
}
}
first_enc174_91_nocrc=false;
}
for (int i = 0; i < 83; ++i)
{
int nsum=0;
for (int j = 0; j < 91; ++j)
{
nsum+=message910[j]*gen_osd174_91_nocrc[j][i];//nsum=nsum+message(j)*gen(i,j);
}
pchecks[i]=fmod(nsum,2);
}
// codeword(1:K)=message
// codeword(K+1:N)=pchecks
for (int i = 0; i < K; ++i)//91
codeword[i]=message910[i];
for (int i = 0; i < M; ++i)//174-91=83
codeword[i+91]=pchecks[i];
}
void PomFt::osd174_91_1(double *llr,/*int Keff=91*/bool *apmask,int ndeep,bool *message91,bool *cw,int &nhardmin,double &dmin)
{
const int N=174;
const int K=91;
const int M=N-K;// M=83
double rx[N];
bool apmaskr[N];
bool apmaskr2[N];
bool hdec[N+2];
bool hdec2[N+2];
double absrx[N];
double absrx2[N];
bool genmrb_[N][K];//(K,N)
bool g2_[K][N]; //(N,K)
int indices[N];
int indx[N];
bool temp[K];
bool m0[K];
bool c0[N];
int nxor[N+2];
bool misub[K+5];
bool me[K],mi[K];
bool ce[N];
bool e2sub[M];//e2sub(N-K)
bool e2[M];//e2(N-K)
bool ui[M];//ui(N-K)
bool r2pat[M];
bool cw_t[N];
bool m96[96+5];
//bool decoded[K];//91
//qDebug()<<first_osd174_91<<lastpat_ft8_2<<inext_ft8_2;
if (first_osd174_91) //then ! fill the generator matrix
{
for (int i = 0; i < N; ++i)
{
for (int j = 0; j < K; ++j)
gen_osd174_91_[i][j]=0;
}
for (int i = 0; i < K; ++i) //c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
{//do i=1,k
bool message910[120];
for (int j = 0; j < 91; ++j)
message910[j]=0;
message910[i]=1;
/*if (i<77)
{
//m96=0
//m96(1:91)=message91
//call get_crc14(m96,96,ncrc14)
//write(c14,'(b14.14)') ncrc14
//read(c14,'(14i1)') message91(78:91)
for (int j = 77; j < K; ++j)
message91[j]=0;//message91(78:k)=0
}*/
encode174_91_nocrc(message910,cw);
for (int j = 0; j < N; ++j)
gen_osd174_91_[j][i]=cw[j];
}
first_osd174_91=false;
}
for (int i = 0; i < N; ++i)//c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
{
rx[i]=llr[i];//rx=llr
apmaskr[i]=apmask[i];//apmaskr=apmask
hdec[i]=0;//hdec=0
if (rx[i]>=0.0) hdec[i]=1; // where(rx .ge. 0) hdec=1
absrx[i]=fabs(rx[i]);//absrx=abs(rx)
}
//if (N>0)//2.12 no needed
pomAll.indexx_msk(absrx,N-1,indx);//call indexx(absrx,N,indx)
//! Re-order the columns of the generator matrix in order of decreasing reliability.
for (int i = 0; i < N; ++i)
{//do i=1,N
for (int j = 0; j < K; ++j)
genmrb_[i][j]=gen_osd174_91_[indx[(N-1)-i]][j];//genmrb(1:K,i)=gen(1:K,indx(N+1-i))
indices[i]=indx[(N-1)-i];//indices[i]=indx(N+1-i)
}
//! 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).
int iflag=0;
for (int id = 0; id < K; ++id)
{//do id=1,K //! diagonal element indices
for (int icol = id; icol < K+20; ++icol)//+20 ???
{//do icol=id,K+20 ! The 20 is ad hoc - beware
iflag=0;
if ( genmrb_[icol][id] == 1 ) //then (id,icol) //c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
{
iflag=1;
if ( icol != id ) //then ! reorder column;//if( icol .ne. id ) then ! reorder column
{
for (int z = 0; z < K; ++z)
{
temp[z]=genmrb_[id][z];//temp(1:K)=genmrb(1:K,id)
genmrb_[id][z]=genmrb_[icol][z];//genmrb(1:K,id)=genmrb(1:K,icol)
genmrb_[icol][z]=temp[z];//genmrb(1:K,icol)=temp(1:K)
}
int itmp=indices[id];
indices[id]=indices[icol];
indices[icol]=itmp;
}
for (int ii = 0; ii < K; ++ii)
{//do ii=1,K
if ( ii != id && genmrb_[id][ii] == 1 ) //then if( ii != id && genmrb(ii,id) .eq. 1 ) then
{
for (int z = 0; z < N; ++z)
genmrb_[z][ii]=(genmrb_[z][ii] ^ genmrb_[z][id]);//genmrb(ii,1:N)=ieor(genmrb(ii,1:N),genmrb(id,1:N))
}
}
break; //exit
}
}
}
for (int i = 0; i < N; ++i)
{
for (int j = 0; j < K; ++j)//char genmrb_[N][K];
g2_[j][i]=genmrb_[i][j]; //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.
for (int i = 0; i < N; ++i)// N
{
hdec2[i]=hdec[indices[i]]; //hdec=hdec(indices)
absrx2[i]=absrx[indices[i]]; //absrx=absrx(indices)
//rx_t[i]=rx[indices[i]]; //rx=rx(indices)
apmaskr2[i]=apmaskr[indices[i]]; //apmaskr=apmaskr(indices)
}
for (int i = 0; i < K; ++i)
m0[i]=hdec2[i]; // m0=hdec(1:K) ! zero'th order message //! zero'th order message
mrbencode91(m0,c0,g2_,N,K);// mrbencode91(m0,c0,g2,N,K);
nhardmin = 0;
dmin = 0.0;
for (int i = 0; i < N; ++i)
{
nxor[i]=(c0[i] ^ hdec2[i]);
nhardmin+=nxor[i];//nhardmin=sum(nxor)
dmin+=(double)nxor[i]*absrx2[i];
}
for (int i = 0; i < N; ++i)
cw[i]=c0[i];
int nt=0;
int nrejected=0;
int nord = 0;
int npre1 = 0;
int npre2 = 0;
int ntheta = 0;
int ntau = 0;
int ntotal=0;
if (ndeep==0) goto c998; //! norder=0 //c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
if (ndeep>6) ndeep=6;
if ( ndeep==1)
{
nord=1;
npre1=0;
npre2=0;
nt=40;
ntheta=12;
}
else if (ndeep==2)
{
nord=1;
npre1=1;
npre2=0;
nt=40;
ntheta=12;//2.2.0org=ntheta=10; ntheta=12;
}
else if (ndeep==3)
{
nord=1;
npre1=1;
npre2=1;
nt=40;
ntheta=12;
ntau=14;
}
else if (ndeep==4)
{
nord=2;
npre1=1;
npre2=1; //npre2=0;
nt=40;
ntheta=12;
ntau=17;//ntau=19;
}
else if (ndeep==5)
{
nord=3;//nord=2;
npre1=1;
npre2=1;
nt=40;
ntheta=12;
ntau=15;//ntau=19;
}
else //if (ndeep==6)
{
nord=4;
npre1=1;
npre2=1;
nt=95;
ntheta=12;
ntau=15;
}
for (int iorder = 1; iorder <= nord; ++iorder)
{//do iorder=1,nord
for (int z = 0; z < K-iorder; ++z) //misub(1:K-iorder)=0
misub[z]=0;
for (int z = K-iorder; z < K; ++z)
misub[z]=1; // misub(K-iorder+1:K)=1
iflag=K-iorder; //iflag=K-iorder+1
while (iflag >= 0 ) //c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
{//do while(iflag .ge.0)
int iend = 0;
if (iorder==nord && npre1==0)
iend=iflag;
else
iend=0;//iend=1
double d1 = 0.0;
//double dd = 0.0;
//int nd1Kpt = 0;
for (int n1 = iflag; n1 >= iend; --n1)
{//do n1=iflag,iend,-1
for (int x = 0; x < K; ++x)
mi[x]=misub[x];//mi=misub
mi[n1]=1;//mi(n1)=1;
//if(any(iand(apmaskr(1:K),mi).eq.1)) continue;//cycle
if (any_ca_iand_ca_eq1_91(apmaskr2,mi,K)) continue;//cycle
ntotal++;
for (int x = 0; x < K; ++x)
me[x]=(m0[x] ^ mi[x]);//me=ieor(m0,mi)
int nd1Kpt = 0;
//double d1 = 0.0; //hv testsed //error hv ->
if (n1==iflag)
{
mrbencode91(me,ce,g2_,N,K);
for (int x = 0; x < M; ++x)//K=91 M=87
{
e2sub[x]=(ce[K+x] ^ hdec2[K+x]);//e2sub=ieor(ce(K+1:N),hdec(K+1:N))
e2[x]=e2sub[x];
}
nd1Kpt = 0;
for (int x = 0; x < nt; ++x)//nt=40 K=87 M=87
nd1Kpt+=e2sub[x];//nd1Kpt=sum(e2sub(1:nt))+1;
nd1Kpt = nd1Kpt + 1;
d1 = 0.0;
for (int x = 0; x < K; ++x)
d1+=(double)(me[x] ^ hdec2[x])*absrx2[x];//d1=sum(ieor(me(1:K),hdec(1:K))*absrx(1:K))
}
else
{
for (int x = 0; x < M; ++x)
e2[x]=(e2sub[x] ^ g2_[n1][K+x]);//e2=ieor(e2sub,g2(K+1:N,n1))
nd1Kpt = 0;
for (int x = 0; x < nt; ++x)
nd1Kpt+=e2[x];//nd1Kpt=sum(e2(1:nt))+2
nd1Kpt = nd1Kpt + 2;
}
if (nd1Kpt <= ntheta) //c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
{
mrbencode91(me,ce,g2_,N,K);
for (int x = 0; x < N; ++x)
nxor[x]=(ce[x] ^ hdec2[x]);//nxor=ieor(ce,hdec)
double dd = 0.0;
if (n1==iflag)
{
dd = 0.0;
for (int x = 0; x < M; ++x)
dd+=(double)e2sub[x]*absrx2[K+x];//dd=d1+sum(e2sub*absrx(K+1:N))
dd=d1 + dd;
}
else
{
//dd=d1+ieor(ce(n1),hdec(n1))*absrx(n1)+sum(e2*absrx(K+1:N))
dd = 0.0;
for (int x = 0; x < M; ++x)
dd+=(double)e2[x]*absrx2[K+x];
dd = d1+(double)(ce[n1] ^ hdec2[n1])*absrx2[n1] + dd;
}
if ( dd < dmin )
{
dmin=dd;
for (int x = 0; x < N; ++x)
cw[x]=ce[x];//cw=ce
nhardmin = 0;
for (int x = 0; x < N; ++x)
nhardmin+=nxor[x];//nhardmin=sum(nxor)
//nd1Kptbest=nd1Kpt;
}
}
else
nrejected++;
}
/*QString sss = "";///gen_osd174_[174][87];
for (int z= 0; z < 87; z++)//decoded=87 cw-174
{
sss.append(QString("%1").arg((int)misub[z]));
sss.append(",");
}
qDebug()<<"222 mi="<<sss<<iorder;*/
//! Get the next test error pattern, iflag will go negative
//! when the last pattern with weight iorder has been generated.
//nextpat(misub,K,iorder,iflag);
nextpat_step1_91(misub,K,iorder,iflag);
//qDebug()<<"iflag mi="<<iflag;
}
}
//qDebug()<<"1OSD1 nhardmin================"<<nhardmin;
if (npre2==1)
{
//qDebug()<<"npre2 mi=================";
bool reset=true;
ntotal=0;
for (int i1 = K-1; i1 >= 0; --i1)
{//do i1=K,1,-1
for (int i2 = i1-1; i2 >= 0; --i2)//hv ??? i1-1
{//do i2=i1-1,1,-1
//ntotal=ntotal+1;
for (int x = 0; x < ntau; ++x)//char g2_[87][174];//(N=174,K=87); ntau=19,14
mi[x]=(g2_[i1][K+x] ^ g2_[i2][K+x]);//mi=ieor(g2(K+1:K+ntau,i1),g2(K+1:K+ntau,i2))
boxit91(reset,mi,ntau,ntotal,i1,i2);//call boxit(reset,mi(1:ntau),ntau,ntotal,i1,i2)
ntotal++;
}
}
//int ncount2=0;
//int ntotal2=0;
reset=true;
//! Now run through again and do the second pre-processing rule
for (int z = 0; z < K-nord; ++z) //misub(1:K-iorder)=0
misub[z]=0;
for (int z = K-nord; z < K; ++z)
misub[z]=1; // misub(K-iorder+1:K)=1
iflag=K-nord; //iflag=K-iorder+1
while (iflag>=0)//c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
{
for (int z = 0; z < K; ++z)
me[z]=(m0[z] ^ misub[z]);//me=ieor(m0,misub)
mrbencode91(me,ce,g2_,N,K);
for (int z = 0; z < M; ++z)
e2sub[z]=(ce[K+z] ^ hdec2[K+z]);//e2sub=ieor(ce(K+1:N),hdec(K+1:N))
for (int i2 = -1; i2 < ntau; ++i2)//hv ntau+1 do i2=0,ntau
{//do i2=0,ntau
//ntotal2++;// no use???
for (int x = 0; x < M; ++x)
ui[x]=0;
if (i2>-1) ui[i2]=1; ///hv i2>0 if(i2>0) ui(i2)=1
for (int x = 0; x < M; ++x)
r2pat[x]=(e2sub[x] ^ ui[x]);//r2pat=ieor(e2sub,ui)
c778: // continue;
int in1=-1;//hv reset -1
int in2=-1;//hv reset -1
fetchit91(reset,r2pat,ntau,in1,in2);//fetchit(reset,r2pat(1:ntau),ntau,in1,in2)
if (in1>=0 && in2>=0)//hv >=0 if(in1>0.and.in2>0) then
{
//ncount2++;
for (int z = 0; z < K; ++z)
mi[z]=misub[z];
mi[in1]=1;
mi[in2]=1;
int sum_mi = 0;
for (int z = 0; z < K; ++z)
sum_mi+=mi[z];
//if(sum(mi).lt.nord+npre1+npre2.or.any(iand(apmaskr(1:K),mi).eq.1)) cycle
if (sum_mi<nord+npre1+npre2 || any_ca_iand_ca_eq1_91(apmaskr2,mi,K)) continue;//cycle
for (int z = 0; z < K; ++z)
me[z]=(m0[z] ^ mi[z]);
mrbencode91(me,ce,g2_,N,K);
for (int z = 0; z < N; ++z)
nxor[z]=(ce[z] ^ hdec2[z]);
double dd = 0.0;
for (int z = 0; z < N; ++z)
dd+=(double)nxor[z]*absrx2[z];//dd=sum(nxor*absrx)
if ( dd < dmin )
{
dmin=dd;
for (int z = 0; z < N; ++z)
cw[z]=ce[z];
nhardmin = 0;
for (int x = 0; x < N; ++x)
nhardmin+=nxor[x];//nhardmin=sum(nxor)
}
goto c778;
}
}
//nextpat(misub,K,nord,iflag);
nextpat_step1_91(misub,K,nord,iflag);
}
}
//qDebug()<<"2OSD1 nhardmin================"<<nhardmin;
c998:
//! Re-order the codeword to place message bits at the end.
for (int i = 0; i < N; ++i)
cw_t[indices[i]]=cw[i]; //cw(indices)=cw
for (int i = 0; i < N; ++i)
{
cw[i]=cw_t[i]; //cw(indices)=cw
if (i<91)
message91[i]=cw_t[i]; //message77=decoded(1:77)
if (i<96)
{
m96[i]=0;
if (i<77) m96[i]=cw[i]; //m96(1:77)=cw(1:77)
if (i>81) m96[i]=cw[i-5];//m96(83:96)=cw(78:91)
}
}
int nbadcrc;
get_crc14(m96,96,nbadcrc); //qDebug()<<nbadcrc;
if (nbadcrc!=0) nhardmin=-nhardmin;
//if(nbadcrc==1) nhardmin=-nhardmin;
//qDebug()<<"OSD2 nhardmin================"<<nhardmin<<dmin;
}
//// END POMFT ///