/*
* 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