static void impulse_response(int rnk, dim_stuff *d, R impulse_amp, R *A, int N) { if (rnk == 0) A[0] = impulse_amp; else { int i; N /= d->n; for (i = 0; i < d->n; ++i) { impulse_response(rnk - 1, d + 1, impulse_amp * d->ti(d->i0, d->k0 + i, d->n0), A + i * N, N); } } }
static double rimpulse(dim_stuff *d, R impulse_amp, int n, int vecn, info *nfo, R *inA, R *inB, R *inC, R *outA, R *outB, R *outC, R *tmp, int rounds, double tol) { double e = 0.0; int N = n * vecn; int i; int j; /* test 2: check that the unit impulse is transformed properly */ for (i = 0; i < N; ++i) { /* pls */ inA[i] = 0.0; } for (i = 0; i < vecn; ++i) { inA[i * n] = (i+1) / (double)(vecn+1); /* transform of the pls */ impulse_response(nfo->probsz->rnk, d, impulse_amp * inA[i * n], outA + i * n, n); } dofft(nfo, inA, tmp); e = dmax(e, racmp(tmp, outA, N, "impulse 1", tol)); for (j = 0; j < rounds; ++j) { rarand(inB, N); rasub(inC, inA, inB, N); dofft(nfo, inB, outB); dofft(nfo, inC, outC); raadd(tmp, outB, outC, N); e = dmax(e, racmp(tmp, outA, N, "impulse", tol)); } return e; }
void SISO::gen_chtrellis(void) // generate trellis for precoded FIR channels with real coefficients { //get parameters int mem_len = impulse_response.cols()-1;//memory length of the channel int p_order = prec_gen.length()-1;//order of the precoder polynomial //other variables register int n,k,j; double inputs[] = {1.0,-1.0};//1->-1, 0->+1 int index; double feedback[2]; //create channel trellis int equiv_ch_mem_len = std::max(mem_len, p_order); chtrellis.stateNb = (1<<equiv_ch_mem_len); chtrellis.output = new double[2*chtrellis.stateNb]; chtrellis.nextState = new int[2*chtrellis.stateNb]; chtrellis.prevState = new int[2*chtrellis.stateNb]; chtrellis.input = new int[2*chtrellis.stateNb]; //initialize trellis itpp::ivec enc_mem(equiv_ch_mem_len); #pragma omp parallel for private(n,enc_mem,k,feedback,j) for (n=0; n<chtrellis.stateNb; n++) //initial state { enc_mem = 1-2*itpp::to_ivec(itpp::dec2bin(equiv_ch_mem_len, n));//1->-1, 0->+1 //output for (k=0; k<2; k++) { feedback[k] = inputs[k]; for (j=1; j<=p_order; j++) if (prec_gen[j]) feedback[k] *= enc_mem[j-1];//xor truth table must remain the same chtrellis.output[n+k*chtrellis.stateNb] = feedback[k]*impulse_response(0,0); for (j=1; j<=mem_len; j++) chtrellis.output[n+k*chtrellis.stateNb] += (enc_mem[j-1]*impulse_response(0,j)); } //next state for (j=(equiv_ch_mem_len-1); j>0; j--) enc_mem[j] = enc_mem[j-1]; for (k=0; k<2; k++) { enc_mem[0] = int(feedback[k]); chtrellis.nextState[n+k*chtrellis.stateNb] = itpp::bin2dec(itpp::to_bvec((1-enc_mem)/2), true);//-1->1, +1->0 } } #pragma omp parallel for private(j,index,n,k) for (j=0; j<chtrellis.stateNb; j++) { index = 0; for (n=0; n<chtrellis.stateNb; n++) { for (k=0; k<2; k++) { if (chtrellis.nextState[n+k*chtrellis.stateNb]==j) { chtrellis.prevState[j+index*chtrellis.stateNb] = n; chtrellis.input[j+index*chtrellis.stateNb] = k;//this is an index to the channel input index++; } } } } }