/*****
Last Modification: 6 November 2006
****
****
N.B.: Use formula (51) on page 632 of Shannon's 1959 paper,
See also
http://www.comelec.enst.fr/~boutros/coding/Allerton99_VialleBoutros_paper.pdf
*****/
#include "mathcom.h"
static int n;
static double RateFunction();
int main(argc, argv)
int argc;
char **argv;
{
char chain[200], filename[200];
double theta, rate;
double a, b, c;
int iter;
double val, diff;
double A, G, EL, factor, Pe, log_Pe, snrdb, snr;
double snrdb1, snrdb2, snrstep;
printf("######## Optimal Code (Spherical) Performance on AWGN Channel ######### \n");
printf("Q(theta) formula (51) of Shannon 1959, page 632. \n");
printf("Using the asymptotic rate formula (28), page 624 Shannon 1959\n");
printf("Computing the cone half-angle for a given rate\n");
printf("R=(1/n-1)*log2(sin(theta))+1/n*log2(cos(theta)*sqrt(2PIn)) \n\n");
printf("Real Space dimension (from 20 up to 200000) [1000] : ");
ReadString(chain);
if(chain[0]) sscanf(chain,"%d", &n);
else n=1000;
if((n<20)||(n>200000))
{
fprintf(stderr,"%s: n out of range 100...200000\n", argv[0]);
return(-1);
}
printf("Information Rate in bits/dimension (from 1/10 up to 8) [0.50] : ");
ReadString(chain);
if(chain[0]) sscanf(chain,"%lf", &rate);
else rate=0.50;
if((rate<0.1)||(rate>8.0))
{
fprintf(stderr,"%s: rate out of range 1/10...8\n", argv[0]);
return(-1);
}
/* rate=1/10 <=> theta0=00.20 degrees */
/* rate=8 <=> theta0=69.50 degrees */
iter=0;
a=0.20; b=70.0;
do
{
c=(a+b)/2.0;
val=RateFunction(c);
if(val < rate) b=c; else a=c;
c=(a+b)/2.0; ++iter;
diff=b-a;
}
while((diff>1e-8)&&(iter<1000));
printf("The cone half-angle for %1.4f bits/dimension is equal to %1.8f degrees \n", rate, c);
theta=c*PI/180.0; /* we switch to radians */
if(SQR(tan(theta)) >= (0.25*n) )
{
fprintf(stderr,"OmegaFunction(): Warning, theta too close to 90 or n is small !\n");
}
printf("The modulation alphabet is spherical, Es=energie per real symbol.\n");
printf("n*P=squared radius of the sphere= n*2*Es=n*2*rate*Eb, P=2*rate*Eb \n");
printf("A^2=P/N0=2*rate*Eb/N0, the SNR per bit is SNR=Eb/N0 \n");
printf("Here, N0 is the noise variance per real component.\n\n");
snrdb1=-1.50;
printf("Start Eb/N0 in dB [%1.2f]: ", snrdb1);
ReadString(chain);
if(chain[0]) sscanf(chain,"%lf", &snrdb1);
snrdb2=20.00;
printf("End Eb/N0 in dB [%1.2f]: ", snrdb2);
ReadString(chain);
if(chain[0]) sscanf(chain,"%lf", &snrdb2);
snrstep=0.05;
printf("SNR step in dB [%1.2f]: ", snrstep);
ReadString(chain);
if(chain[0]) sscanf(chain,"%lf", &snrstep);
sprintf(filename,"optimal_spherical_code_awgn_n=%d_rate=%1.2f_WER.dat", n, rate);
printf("Output file name for WER versus SNR [%s]: ", filename);
ReadString(chain);
if(chain[0]) strcpy(filename, chain);
sprintf(chain,"rm -f %s", filename);
system(chain);
printf("Eb/N0 (dB) || Word Error Rate (WER)\n");
Pe=1.0;
for(snrdb=snrdb1; snrdb <= snrdb2+0.01; snrdb += snrstep)
{
if(Pe<1e-20) break;
snr=exp10(0.1*snrdb);
A=sqrt(2*rate*snr);
if(atan(1.0/A) > theta)
{
/***
fprintf(stderr,"Warning : theta=%1.4f but lower limit is cot^-1(1/A)=%1.4f ! \n",
theta*180.0/PI, atan(1.0/A)*180.0/PI);
fprintf(stderr,"%s: Please increase the SNR for this rate=%1.4f.\n", argv[0], rate);
***/
continue;
}
G=0.5*(A*cos(theta)+sqrt(A*A*cos(theta)*cos(theta)+4.0));
EL=0.5*A*A-0.5*A*G*cos(theta)-log(G*sin(theta));
factor=sqrt(n*PI)*sqrt(1.0+G*G)*sin(theta)
*(A*G*sin(theta)*sin(theta)-cos(theta));
Pe=exp(-n*EL)/factor;
if(Pe<1.0)
{
printf("%1.2f %1.4e \n", snrdb, Pe);
WritePlotFile(filename, snrdb, Pe, "%1.2f", "%1.4e");
}
}/* end of snrdb loop */
return(0);
}/* end of main() */
/*---------------------------------------------------------------*/
static double RateFunction(theta)
double theta; /* in degrees, not radians */
{
return( (1.0/n-1.0)*log2(sin(theta*PI/180.0))
+1.0/n*log2(cos(theta*PI/180.0)*sqrt(2.0*PI*n)) );
}/* end of RateFunction() */
/*---------------------------------------------------------------*/
Joseph Jean Boutros
2006-11-11