/* * Copyright 2008, 2009, 2014 Free Software Foundation, Inc. * Copyright 2014 Range Networks, Inc. * * * This software is distributed under the terms of the GNU Affero Public License. * See the COPYING file in the main directory for details. * * This use of this software may be subject to additional restrictions. * See the LEGAL file in the main directory for details. This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ #include "BitVector.h" #include "ViterbiR204.h" #include #include #include #include using namespace std; /** Apply a Galois polymonial to a binary seqeunce. @param val The input sequence. @param poly The polynomial. @param order The order of the polynomial. @return Single-bit result. */ unsigned ViterbiBase::applyPoly(uint64_t val, uint64_t poly, unsigned order) { uint64_t prod = val & poly; unsigned sum = prod; for (unsigned i=1; i>i; return sum & 0x01; } unsigned ViterbiBase::applyPoly(uint64_t val, uint64_t poly) { uint64_t prod = val & poly; prod = (prod ^ (prod >> 32)); prod = (prod ^ (prod >> 16)); prod = (prod ^ (prod >> 8)); prod = (prod ^ (prod >> 4)); prod = (prod ^ (prod >> 2)); prod = (prod ^ (prod >> 1)); return prod & 0x01; } //void BitVector::encode(const ViterbiR2O4& coder, BitVector& target) void ViterbiR2O4::encode(const BitVector& in, BitVector& target) const { const ViterbiR2O4& coder = *this; size_t sz = in.size(); assert(sz*coder.iRate() == target.size()); // Build a "history" array where each element contains the full history. uint32_t history[sz]; uint32_t accum = 0; for (size_t i=0; iiState) << 1; // input state for 0 const uint32_t iState1 = iState0 | 0x01; // input state for 1 const uint32_t oStateShifted = (sp->oState) << mIRate; // shifted output (by 2) const float cost = sp->cost; int bec = sp->bitErrorCnt; sp++; // 0 input extension mCandidates[i].cost = cost; // mCMask is the low 5 bits, ie, full width of mGeneratorTable. mCandidates[i].oState = oStateShifted | mGeneratorTable[iState0 & mCMask]; mCandidates[i].iState = iState0; mCandidates[i].bitErrorCnt = bec; // 1 input extension mCandidates[i+1].cost = cost; mCandidates[i+1].oState = oStateShifted | mGeneratorTable[iState1 & mCMask]; mCandidates[i+1].iState = iState1; mCandidates[i+1].bitErrorCnt = bec; } } void ViterbiR2O4::getSoftCostMetrics(const uint32_t inSample, const float *matchCost, const float *mismatchCost) { const float *cTab[2] = {matchCost,mismatchCost}; for (unsigned i=0; i>1)&0x01][0]; if (mismatched & 1) { thisCand.bitErrorCnt++; } if (mismatched & 2) { thisCand.bitErrorCnt++; } } } void ViterbiR2O4::pruneCandidates() { const vCand* c1 = mCandidates; // 0-prefix const vCand* c2 = mCandidates + mIStates; // 1-prefix for (unsigned i=0; i=minCost) continue; minCost = thisCost; minIndex=i; } return mSurvivors[minIndex]; } const ViterbiR2O4::vCand* ViterbiR2O4::vstep(uint32_t inSample, const float *probs, const float *iprobs, bool isNotTailBits) { branchCandidates(); // (pat) tail bits do not affect cost or error bit count of any branch. if (isNotTailBits) getSoftCostMetrics(inSample,probs,iprobs); pruneCandidates(); return &minCost(); } void ViterbiR2O4::decode(const SoftVector &in, BitVector& target) { ViterbiR2O4& decoder = *this; const size_t sz = in.size(); const unsigned oSize = in.size() / decoder.iRate(); 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. // (pat) We only use every other history element, so why are we setting them? uint32_t history[ctsz]; { BitVector bits = in.sliced(); uint32_t accum = 0; for (size_t i=0; i0.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 // Note that these bits should not contribute to Bit Error Count. for (size_t i=sz; i=deferral) *op++ = (minCost->iState >> deferral)&0x01; oCount++; } // Dont think minCost == NULL can happen. mBitErrorCnt = minCost ? minCost->bitErrorCnt : 0; } } // vim: ts=4 sw=4