void testPunctureUnpuncture(const char *label, const unsigned int *punk, size_t plth) { bool ok = true; // Things could go wrong and be missed due to we're just wrangling bit vectors, // so run each speed a few times to reduce the probability of missing an error. for (int i = 0; i < 5; i++) { // generate orig BitVector orig = randomBitVector(448+plth); // puncture BitVector punctured(orig.size() - plth); orig.copyPunctured(punctured, punk, plth); SoftVector softPunctured(punctured); // unpuncture SoftVector unpunctured(orig.size()); softPunctured.copyUnPunctured(unpunctured, punk, plth); // verify const unsigned *p = punk; for (unsigned i = 0; i < orig.size(); i++) { if (unpunctured[i] == 0.5) { if (*p++ != i) ok = false; } else { if (orig.bit(i) != unpunctured[i]) ok = false; } } ok = ok && (p == punk + plth); } cout << "puncture->unpuncture " << label << " " << (ok ? "ok" : "NOT ok") << endl; }
static void printdiff(BitVector &v1, BitVector &v2) { int diffbit, v1size = v1.size(); for (diffbit=0; diffbit < v1size; diffbit++) { if (v1.bit(diffbit) != v2.bit(diffbit)) { break; } } if (diffbit < v1size) { //printf("vectors size %d differ at bit %d\n",v1.size(),diffbit); //printf("1= %s\n",v1.hexstr().c_str()); //printf("2= %s\n",v2.hexstr().c_str()); printf("d="); for (int i = 0; i < v1size; i++) { if (v1.bit(i) != v2.bit(i)) { printf("%c", '0' + v1.bit(i)); } else { printf("-"); } } printf("\n"); } }
void print(io::Output& out, const BitVector& v) { t::uint32 w = 0; int c = 0; for(int i = 0; i < v.size(); i++) { if(v.bit(i)) w |= 1 << c; c++; if(c == 31) { out << ' ' << io::hex(w).width(8).pad('0').right(); w = 0; c = 0; } } if(c) out << ' ' << io::hex(w).width(8).pad('0').right(); }
// Return true if we send a block on the downlink. bool PDCHL1Downlink::send1DataFrame( //SVGDBG RLCDownEngine *engdown, RLCDownlinkDataBlock *block, // block to send. int makeres, // 0 = no res, 1 = optional res, 2 = required res. MsgTransactionType mttype, // Type of reservation unsigned *pcounter) { //ScopedLock lock(testlock); TBF *tbf = engdown->getTBF(); if (! setMACFields(block,mchParent,tbf,makeres,mttype,pcounter)) { return false; } // The rest of the RLC header is already set, but we did not know the tfi // when we created the RLCDownlinkDataBlocks (because tbf not yet attached) // so set tfi now that we know. Update 8-2012: Above comment is stale because we // make the RLCDownlinkBlocks on the fly now. block->mTFI = tbf->mtTFI; // block->mPR = 1; // DEBUG test; made no diff. tbf->talkedDown(); BitVector tobits = block->getBitVector(); // tobits deallocated when this function exits. if (block->mChannelCoding == 0) { devassert(tobits.size() == 184); } if (GPRSDebug & 1) { RLCBlockReservation *res = mchParent->getReservation(gBSNNext); std::ostringstream sshdr; block->text(sshdr,false); //block->RLCDownlinkDataBlockHeader::text(sshdr); ByteVector content(tobits); GPRSLOG(1) << "send1DataFrame "<<parent()<<" "<<tbf<<LOGVAR(tbf->mtExpectedAckBSN) << " "<<sshdr.str() <<" "<<(res ? res->str() : "") << LOGVAR2("content",content); //<< " enc="<<tbf->mtChannelCoding <<" "<<os.str() << "\nbits:" <<bits.str(); //<<" " <<block->str() <<"\nbits:" <<tobits.hexstr(); } #if FEC_DEBUG BitVector copybits; copybits.clone(tobits); #endif send1Frame(tobits,block->mChannelCoding,0); #if FEC_DEBUG BitVector *result = debugDecoder.getResult(); devassert(result); devassert(copybits == tobits); if (result && !(*result == tobits)) { int diffbit = -1; char thing[500]; for (int i = 0; i < (int)result->size(); i++) { thing[i] = '-'; if (result->bit(i) != tobits.bit(i)) { if (diffbit == -1) diffbit = i; thing[i] = '0' + result->bit(i); } } thing[result->size()] = 0; GPRSLOG(1) <<"encoding error" <<LOGVAR2("cs",(int)debugDecoder.getCS()) <<LOGVAR(diffbit) <<LOGVAR2("in:size",tobits.size()) <<LOGVAR2("out:size",result->size()) <<"\n"<<tobits <<"\n"<<*result <<"\n"<<thing; } else { //GPRSLOG(1) <<"encoding ok" <<LOGVAR2("cs",(int)debugDecoder.getCS()); } #endif return true; }
void ViterbiTCH_AFS7_4::decode(const SoftVector &in, BitVector& target) { ViterbiTCH_AFS7_4 &decoder = *this; const size_t sz = in.size() - 12; const unsigned deferral = decoder.deferral(); const size_t ctsz = sz + deferral*decoder.iRate(); assert(sz == decoder.iRate()*target.size()); // Build a "history" array where each element contains the full history. uint32_t history[ctsz]; { BitVector bits = in.sliced(); uint32_t accum = 0; for (size_t i=0; i<sz; i++) { accum = (accum<<1) | bits.bit(i); history[i] = accum; } // Repeat last bit at the end. for (size_t i=sz; i<ctsz; i++) { accum = (accum<<1) | (accum & 0x01); history[i] = accum; } } // Precompute metric tables. float matchCostTable[ctsz]; float mismatchCostTable[ctsz]; { const float *dp = in.begin(); for (size_t i=0; i<sz; i++) { // pVal is the probability that a bit is correct. // ipVal is the probability that a bit is incorrect. float pVal = dp[i]; if (pVal>0.5F) pVal = 1.0F-pVal; float ipVal = 1.0F-pVal; // This is a cheap approximation to an ideal cost function. if (pVal<0.01F) pVal = 0.01; if (ipVal<0.01F) ipVal = 0.01; matchCostTable[i] = 0.25F/ipVal; mismatchCostTable[i] = 0.25F/pVal; } // pad end of table with unknowns for (size_t i=sz; i<ctsz; i++) { matchCostTable[i] = 0.5F; mismatchCostTable[i] = 0.5F; } } { decoder.initializeStates(); // Each sample of history[] carries its history. // So we only have to process every iRate-th sample. const unsigned step = decoder.iRate(); // input pointer const uint32_t *ip = history + step - 1; // output pointers char *op = target.begin(); const char *const opt = target.end(); // table pointers const float* match = matchCostTable; const float* mismatch = mismatchCostTable; size_t oCount = 0; while (op<opt) { // Viterbi algorithm assert(match-matchCostTable<(int)(sizeof(matchCostTable)/sizeof(matchCostTable[0])-1)); assert(mismatch-mismatchCostTable<(int)(sizeof(mismatchCostTable)/sizeof(mismatchCostTable[0])-1)); const ViterbiTCH_AFS7_4::vCand &minCost = decoder.step(*ip, match, mismatch); ip += step; match += step; mismatch += step; // output if (oCount>=deferral) *op++ = (minCost.iState >> deferral)&0x01; oCount++; } } }