GoLang :Simulation of QPSK SER in AWGN Channel

on Tuesday, January 1
The new (atleast to me) programming language Go. The philosophy behind the change and need for the new notations and the language writing itself impressed me. I am a long time C,C++ user. The website has few sample programs to run online itself (Check the Tour).

Wanted to test out a simple code within my domain. And what else could be simplest code for a wireless system modelling - A BER performance of QPSK modulated symbols in AWGN channel. Here goes the code.

package main
import (
"fmt"
"math/rand"
"math"
"io/ioutil"
"time"
"flag"
"runtime"
)
var concflag *bool = flag.Bool("conc", true, "#Enables Concurrent Goroutines Default [true]")
var randomize *bool = flag.Bool("randomize", false, "#Randomize Seed ")
func main(){
flag.Parse()
flag.PrintDefaults()
if *randomize{
rand.Seed(time.Now().UnixNano())
}
concurrent:=*concflag
fmt.Printf("\nMax Available CPUS %v",runtime.NumCPU())
fmt.Printf("\nCurrent SET CPUS %v",runtime.GOMAXPROCS(-1))
t:=time.Now()
fmt.Printf("\nTime Now : %v",t)
snr,ber:=simulate(20,concurrent)
fmt.Printf("\nElapsed : %v",time.Since(t))
fmt.Printf("\n With Concurrent : %v",concurrent)
fmt.Printf("\n SNR = %v",snr)
fmt.Printf("\n BER = %v",ber)
towrite:=false
if(towrite){
var txttowrite =fmt.Sprintf("snr =%v\n",snr)+fmt.Sprintf("ber =%v\n",ber)
ioutil.WriteFile("results.m",[]byte(txttowrite),0600)
}
fmt.Printf("\n Done..\n")
}
func simulate(n int,runtype bool) (snrdB []float64,ber []float64) {
var f=make([]float64, n)
var snr=make([]float64, n)
var initSNR float64
initSNR= 0
if runtype{
ch := make(chan float64,20)
for k := 0; k < n; k++ {
var currentSNR=initSNR+float64(k)
snr[k]=currentSNR
go link(ch, float64(currentSNR))
}
for k := 0; k < n; k++ {
f[k] = <-ch
}
} else {
for k := 0; k < n; k++ {
var currentSNR=initSNR+float64(k)
snr[k]=currentSNR
f[k]=seqlink(currentSNR)
}
}
return snr,f
}
func link(ch chan float64, k float64) {
Nbits:=1024*100 //*(50-int(k))
var symbols=[]complex128{0.7+0.7i,+0.7-0.7i,-0.7+0.7i,-0.7-0.7i}
var txbits=make([]int,Nbits)
for i:=0;i<len(txbits);i++{
txbits[i]=rand.Intn(4)
}
var txsymbols=make([]complex128,Nbits)
var noise=make([]complex128,Nbits)
var rxnoise=make([]complex128,Nbits)
var noisevar float64
lsnr:=float64(math.Pow(10,(k/10)))
Es:=float64(1)
noisevar=Es/lsnr
errorbits:=int(0)
for i,indx :=range txbits{
txsymbols[i]=symbols[indx]
noise[i]=complex(rand.NormFloat64()*math.Sqrt(noisevar*0.5),rand.NormFloat64()*math.Sqrt(noisevar*0.5))
tmp:=txsymbols[i]+noise[i]
switch
{
case real(tmp)>0 && imag(tmp)>0:rxnoise[i]=symbols[0]
case real(tmp)>0 && imag(tmp)<0:rxnoise[i]=symbols[1]
case real(tmp)<0 && imag(tmp)>0:rxnoise[i]=symbols[2]
case real(tmp)<0 && imag(tmp)<0:rxnoise[i]=symbols[3]
}
if (rxnoise[i]!=txsymbols[i]){
errorbits++
}
}
var ber =float64(errorbits)/float64(Nbits)
ch <- ber
}
func seqlink(k float64) float64 {
Nbits:=1024*100 //*(50-int(k))
var symbols=[]complex128{0.7+0.7i,+0.7-0.7i,-0.7+0.7i,-0.7-0.7i}
var txbits=make([]int,Nbits)
for i:=0;i<len(txbits);i++{
txbits[i]=rand.Intn(4)
}
var txsymbols=make([]complex128,Nbits)
var noise=make([]complex128,Nbits)
var rxnoise=make([]complex128,Nbits)
var noisevar float64
lsnr:=float64(math.Pow(10,(k/10)))
Es:=float64(1)
noisevar=Es/lsnr
errorbits:=int(0)
for i,indx :=range txbits{
txsymbols[i]=symbols[indx]
noise[i]=complex(rand.NormFloat64()*math.Sqrt(noisevar*0.5),rand.NormFloat64()*math.Sqrt(noisevar*0.5))
tmp:=txsymbols[i]+noise[i]
switch
{
case real(tmp)>0 && imag(tmp)>0:rxnoise[i]=symbols[0]
case real(tmp)>0 && imag(tmp)<0:rxnoise[i]=symbols[1]
case real(tmp)<0 && imag(tmp)>0:rxnoise[i]=symbols[2]
case real(tmp)<0 && imag(tmp)<0:rxnoise[i]=symbols[3]
}
if (rxnoise[i]!=txsymbols[i]){
errorbits++
}
}
var ber =float64(errorbits)/float64(Nbits)
return ber
}
view raw qpskber.go hosted with ❤ by GitHub
The C++ code is here
#include <math.h>
#include <complex>
#include <ctime>
#include <stdio.h>
#include <cstdlib>
#include <random>
struct result
{
double snr[20];
double ber[20];
};
result simulate(int n ,bool runtype);
double seqlink(double k);
int main()
{
double snr[20];
double ber[20];
struct result ans;
clock_t start = clock();
// program goes here
ans=simulate(20,false);
clock_t ends = clock();
printf("Time elapsed %fms",(float) 1000*(ends - start) / CLOCKS_PER_SEC);
printf("\nSNR = [");
for(int k=0;k<20;k++) printf("%5.2f ",ans.snr[k]);printf("]");
printf("\nBER= [");
for(int k=0;k<20;k++) printf("%f ",ans.ber[k]);printf("]");
printf("\n Done..\n");
}
result simulate(int n ,bool runtype)
{
result ans;
double f[n];
double snr[n];
double initSNR= 0;
for (int k = 0; k < n; k++) {
double currentSNR=initSNR+double(k);
ans.snr[k]=currentSNR;
ans.ber[k]=seqlink(currentSNR);
}
}
return ans;
}
double seqlink(double k) {
int Nbits=1024*100; //*(50-int(k))
std::complex <double> symbols[4];
symbols[0]=std::complex <double> (0.7,0.7); //,+0.7-0.7i,-0.7+0.7i,-0.7-0.7i}
symbols[1]=std::complex <double> (0.7,-0.7); //,+0.7-0.7i,-0.7+0.7i,-0.7-0.7i}
symbols[2]=std::complex <double> (-0.7,0.7); //,+0.7-0.7i,-0.7+0.7i,-0.7-0.7i}
symbols[3]=std::complex <double> (-0.7,-0.7); //,+0.7-0.7i,-0.7+0.7i,-0.7-0.7i}
int txbits[Nbits];
for (int i=0;i<Nbits;i++){
txbits[i]=rand() % 4;
}
std::complex<double> txsymbols[Nbits];
std::complex<double> noise[Nbits];
std::complex<double> rxnoise[Nbits];
double lsnr=double(pow(10,(k/10)));
double Es=1;
double noisevar=Es/lsnr;
int errorbits=0;
std::default_random_engine generator;
std::normal_distribution<double> distribution;
for (int i=0;i<Nbits;i++){
txsymbols[i]=symbols[txbits[i]];
double re=distribution(generator);
double im=distribution(generator);
noise[i]=std::complex<double>(re*sqrt(noisevar*0.5),im*sqrt(noisevar*0.5));
std::complex <double> tmp=txsymbols[i]+noise[i];
{
if(real(tmp)>0 && imag(tmp)>0) rxnoise[i]=symbols[0];
if(real(tmp)>0 && imag(tmp)<0)rxnoise[i]=symbols[1];
if(real(tmp)<0 && imag(tmp)>0)rxnoise[i]=symbols[2];
if(real(tmp)<0 && imag(tmp)<0)rxnoise[i]=symbols[3];
}
if (rxnoise[i]!=txsymbols[i]){
errorbits++;
}
}
double ber =double(errorbits)/double(Nbits);
return ber;
}
view raw qpskber.cpp hosted with ❤ by GitHub