INET Framework for OMNeT++/OMNEST
inet::physicallayer::ConvolutionalCoder Class Reference

#include <ConvolutionalCoder.h>

Inheritance diagram for inet::physicallayer::ConvolutionalCoder:
inet::physicallayer::IFecCoder inet::IPrintableObject

Classes

class  TrellisGraphNode
 

Public Types

typedef std::vector< std::vector< ShortBitVector > > ShortBitVectorMatrix
 
- Public Types inherited from inet::IPrintableObject
enum  PrintLevel {
  PRINT_LEVEL_TRACE, PRINT_LEVEL_DEBUG, PRINT_LEVEL_DETAIL, PRINT_LEVEL_INFO,
  PRINT_LEVEL_COMPLETE = INT_MIN
}
 
enum  PrintFlag { PRINT_FLAG_FORMATTED = (1 << 0), PRINT_FLAG_MULTILINE = (1 << 1) }
 

Public Member Functions

 ConvolutionalCoder (const ConvolutionalCode *convolutionalCode)
 
 ~ConvolutionalCoder ()
 
BitVector encode (const BitVector &informationBits) const override
 
std::pair< BitVector, bool > decode (const BitVector &encodedBits) const override
 
const ConvolutionalCodegetForwardErrorCorrection () const override
 
unsigned int getMemorySizeSum () const
 
const std::vector< int > & getConstraintLengthVector () const
 
const ShortBitVectorMatrixgetTransferFunctionMatrix () const
 
const std::vector< ShortBitVector > & getPuncturingMatrix () const
 
int getNumberOfStates () const
 
int getNumberOfOutputSymbols () const
 
int getNumberOfInputSymbols () const
 
const int ** getStateTransitionTable () const
 
const int ** getOutputTable () const
 
std::ostream & printToStream (std::ostream &stream, int level, int evFlags=0) const override
 Prints this object to the provided output stream. More...
 
- Public Member Functions inherited from inet::IPrintableObject
virtual ~IPrintableObject ()
 
virtual std::string printToString () const
 
virtual std::string printToString (int level, int evFlags=0) const
 
virtual std::string getInfoStringRepresentation (int evFlags=0) const
 
virtual std::string getDetailStringRepresentation (int evFlags=0) const
 
virtual std::string getDebugStringRepresentation (int evFlags=0) const
 
virtual std::string getTraceStringRepresentation (int evFlags=0) const
 
virtual std::string getCompleteStringRepresentation (int evFlags=0) const
 

Protected Member Functions

bool eXOR (bool alpha, bool beta) const
 
void setTransferFunctionMatrix (std::vector< std::vector< int >> &transferFMatrix)
 
ShortBitVector inputSymbolToOutputSymbol (const ShortBitVector &state, const ShortBitVector &inputSymbol) const
 
bool modulo2Adder (const ShortBitVector &shiftRegisters, const ShortBitVector &generatorPolynomial) const
 
ShortBitVector giveNextOutputSymbol (const BitVector &encodedBits, int decodedLength, const BitVector &isPunctured, ShortBitVector &excludedFromHammingDistance) const
 
BitVector puncturing (const BitVector &informationBits) const
 
BitVector depuncturing (const BitVector &decodedBits, BitVector &isPunctured) const
 
BitVector getPuncturedIndices (unsigned int length) const
 
unsigned int computeHammingDistance (const ShortBitVector &u, const ShortBitVector &excludedBits, const ShortBitVector &w) const
 
void updateTrellisGraph (TrellisGraphNode **trellisGraph, unsigned int time, const ShortBitVector &outputSymbol, const ShortBitVector &excludedFromHammingDistance) const
 
bool isCompletelyDecoded (unsigned int encodedLength, unsigned int decodedLength) const
 
void initParameters ()
 
void memoryAllocations ()
 
void computeHammingDistanceLookupTable ()
 
void computeMemorySizes ()
 
void computeMemorySizeSum ()
 
void computeNumberOfStates ()
 
void computeNumberOfInputAndOutputSymbols ()
 
void computeStateTransitions ()
 
void computeOutputAndInputSymbols ()
 
void computeDecimalToOutputSymbolVector ()
 
void printStateTransitions () const
 
void printOutputs () const
 
void printTransferFunctionMatrix () const
 
void parseMatrix (const char *strMatrix, std::vector< std::vector< int >> &matrix) const
 
void parseVector (const char *strVector, std::vector< int > &vector) const
 
void convertToShortBitVectorMatrix (std::vector< std::vector< int >> &matrix, std::vector< ShortBitVector > &boolMatrix) const
 
ShortBitVector octalToBinary (int octalNum, int fixedSize) const
 
int octalToDec (int octalNum) const
 
std::pair< BitVector, bool > traversePath (const TrellisGraphNode &bestNode, TrellisGraphNode **bestPaths, bool isTruncatedMode) const
 

Protected Attributes

const char * mode
 
unsigned int codeRateParamaterK
 
unsigned int codeRateParamaterN
 
unsigned int codeRatePuncturingK
 
unsigned int codeRatePuncturingN
 
int memorySizeSum
 
std::vector< int > memorySizes
 
std::vector< int > constraintLengths
 
int numberOfStates
 
int numberOfInputSymbols
 
int numberOfOutputSymbols
 
ShortBitVectorMatrix transferFunctionMatrix
 
std::vector< ShortBitVectorpuncturingMatrix
 
int ** inputSymbols
 
ShortBitVector ** outputSymbols
 
ShortBitVectordecimalToInputSymbol
 
ShortBitVectordecimalToOutputSymbol
 
int ** stateTransitions
 
unsigned char *** hammingDistanceLookupTable
 
std::vector< std::vector< TrellisGraphNode > > trellisGraph
 
const ConvolutionalCodeconvolutionalCode
 

Member Typedef Documentation

◆ ShortBitVectorMatrix

Constructor & Destructor Documentation

◆ ConvolutionalCoder()

inet::physicallayer::ConvolutionalCoder::ConvolutionalCoder ( const ConvolutionalCode convolutionalCode)
489 {
490  const char *strTransferFunctionMatrix = convolutionalCode->getTransferFunctionMatrix();
491  const char *strPuncturingMatrix = convolutionalCode->getPuncturingMatrix();
492  const char *strConstraintLengthVector = convolutionalCode->getConstraintLengthVector();
494  if (strcmp(mode, "terminated") && strcmp(mode, "truncated"))
495  throw cRuntimeError("Unknown (= %s ) coding mode", mode);
498  parseVector(strConstraintLengthVector, constraintLengths);
499  std::vector<std::vector<int>> pMatrix;
500  parseMatrix(strPuncturingMatrix, pMatrix);
502  std::vector<std::vector<int>> transferFMatrix;
503  parseMatrix(strTransferFunctionMatrix, transferFMatrix);
504  codeRateParamaterK = transferFMatrix.size();
505  codeRateParamaterN = transferFMatrix.at(0).size();
506  for (unsigned int i = 0; i < transferFMatrix.size(); i++) {
507  for (unsigned int j = 0; j < transferFMatrix.at(i).size(); j++) {
508  int decPolynom = octalToDec(transferFMatrix.at(i).at(j));
509  int constraintLength = constraintLengths[i];
510  if (decPolynom >= pow(2, constraintLength))
511  throw cRuntimeError("Code size is greater then constraint length");
512  }
513  }
514  // TODO check whether it is less than..
515  for (unsigned int i = 0; i < codeRateParamaterK; i++)
516  if (transferFMatrix.at(i).size() != codeRateParamaterN)
517  throw cRuntimeError("Transfer function matrix must be a k-by-n matrix of octal numbers");
518  if (transferFMatrix.size() != constraintLengths.size())
519  throw cRuntimeError("Constraint length vector must be a 1-by-k vector of integers");
520  if (puncturingMatrix.size() != codeRateParamaterN)
521  throw cRuntimeError("Puncturing matrix must be a n-by-arbitrary bool matrix");
522  setTransferFunctionMatrix(transferFMatrix);
523  initParameters();
524 }

◆ ~ConvolutionalCoder()

inet::physicallayer::ConvolutionalCoder::~ConvolutionalCoder ( )
540 {
541  for (int i = 0; i < numberOfOutputSymbols; i++) {
542  for (int j = 0; j < numberOfOutputSymbols; j++)
543  delete[] hammingDistanceLookupTable[i][j];
544  delete[] hammingDistanceLookupTable[i];
545  }
547  for (int i = 0; i < numberOfStates; i++) {
548  delete[] stateTransitions[i];
549  delete[] outputSymbols[i];
550  delete[] inputSymbols[i];
551  }
552  delete[] stateTransitions;
553  delete[] outputSymbols;
554  delete[] inputSymbols;
555  delete[] decimalToOutputSymbol;
556  delete[] decimalToInputSymbol;
557 }

Member Function Documentation

◆ computeDecimalToOutputSymbolVector()

void inet::physicallayer::ConvolutionalCoder::computeDecimalToOutputSymbolVector ( )
protected
360 {
361  for (int i = 0; i != numberOfOutputSymbols; i++) {
362  ShortBitVector outputSymbol(i, codeRateParamaterN);
363  decimalToOutputSymbol[outputSymbol.reverseToDecimal()] = outputSymbol;
364  }
365 }

Referenced by initParameters().

◆ computeHammingDistance()

unsigned int inet::physicallayer::ConvolutionalCoder::computeHammingDistance ( const ShortBitVector u,
const ShortBitVector excludedBits,
const ShortBitVector w 
) const
inlineprotected
86  {
87 #ifndef NDEBUG
88  if (u.isEmpty() || w.isEmpty())
89  throw cRuntimeError("You can't compute the Hamming distance between undefined BitVectors");
90  if (u.getSize() != w.getSize())
91  throw cRuntimeError("You can't compute Hamming distance between two vectors with different sizes");
92 #endif // ifndef NDEBUG
93  return hammingDistanceLookupTable[u.toDecimal()][w.toDecimal()][excludedBits.toDecimal()];
94  }

Referenced by updateTrellisGraph().

◆ computeHammingDistanceLookupTable()

void inet::physicallayer::ConvolutionalCoder::computeHammingDistanceLookupTable ( )
protected
170 {
171  for (int i = 0; i < numberOfOutputSymbols; i++) {
172  for (int j = 0; j < numberOfOutputSymbols; j++) {
173  for (int k = 0; k < numberOfOutputSymbols; k++) {
174  unsigned int hammingDistance = i ^ j;
175  hammingDistance = hammingDistance & k;
176  hammingDistance = hammingDistance - ((hammingDistance >> 1) & 0x55555555);
177  hammingDistance = (hammingDistance & 0x33333333) + ((hammingDistance >> 2) & 0x33333333);
178  hammingDistanceLookupTable[i][j][k] = (((hammingDistance + (hammingDistance >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24;
179  }
180  }
181  }
182 }

Referenced by initParameters().

◆ computeMemorySizes()

void inet::physicallayer::ConvolutionalCoder::computeMemorySizes ( )
protected
146 {
147  for (auto& elem : constraintLengths)
148  memorySizes.push_back(elem - 1);
149 }

Referenced by initParameters().

◆ computeMemorySizeSum()

void inet::physicallayer::ConvolutionalCoder::computeMemorySizeSum ( )
protected
163 {
164  memorySizeSum = 0;
165  for (auto& elem : memorySizes)
166  memorySizeSum += elem;
167 }

Referenced by initParameters().

◆ computeNumberOfInputAndOutputSymbols()

void inet::physicallayer::ConvolutionalCoder::computeNumberOfInputAndOutputSymbols ( )
protected
157 {
160 }

Referenced by initParameters().

◆ computeNumberOfStates()

void inet::physicallayer::ConvolutionalCoder::computeNumberOfStates ( )
protected
152 {
153  numberOfStates = (int)pow(2, memorySizeSum);
154 }

Referenced by initParameters().

◆ computeOutputAndInputSymbols()

void inet::physicallayer::ConvolutionalCoder::computeOutputAndInputSymbols ( )
protected
101 {
102  for (int i = 0; i != numberOfInputSymbols; i++) {
103  ShortBitVector inputSymbol(i, codeRateParamaterK);
104  decimalToInputSymbol[inputSymbol.reverseToDecimal()] = inputSymbol;
105  }
106  for (int decState = 0; decState != numberOfStates; decState++) {
107  ShortBitVector state(decState, memorySizeSum);
108  for (int decInputSymbol = 0; decInputSymbol != numberOfInputSymbols; decInputSymbol++) {
109  const ShortBitVector& inputSymbol = decimalToInputSymbol[decInputSymbol];
110  ShortBitVector outputSymbol = inputSymbolToOutputSymbol(state, inputSymbol);
111  int decOutputSymbol = outputSymbol.reverseToDecimal();
112  int reverseDec = state.reverseToDecimal();
113  outputSymbols[reverseDec][decInputSymbol] = outputSymbol;
114  inputSymbols[reverseDec][decOutputSymbol] = decInputSymbol;
115  }
116  }
117 }

Referenced by initParameters().

◆ computeStateTransitions()

void inet::physicallayer::ConvolutionalCoder::computeStateTransitions ( )
protected
244 {
245  for (int decState = 0; decState != numberOfStates; decState++) {
246  ShortBitVector state(decState, memorySizeSum);
247  ShortBitVector shiftedState = state;
248  shiftedState.leftShift(1);
249  for (int is = 0; is != numberOfInputSymbols; is++) {
250  ShortBitVector nextState = shiftedState;
251  ShortBitVector inputSymbol(is, codeRateParamaterK);
252  int shift = 0;
253  for (int m = inputSymbol.getSize() - 1; m >= 0; m--) {
254  nextState.setBit(shift, inputSymbol.getBit(m));
255  shift += memorySizes.at(m);
256  }
257  stateTransitions[state.reverseToDecimal()][inputSymbol.reverseToDecimal()] = nextState.reverseToDecimal();
258  }
259  }
260 }

Referenced by initParameters().

◆ convertToShortBitVectorMatrix()

void inet::physicallayer::ConvolutionalCoder::convertToShortBitVectorMatrix ( std::vector< std::vector< int >> &  matrix,
std::vector< ShortBitVector > &  boolMatrix 
) const
protected
303 {
304  for (auto& elem : matrix) {
305  std::vector<int> matrixRow = elem;
306  ShortBitVector row;
307  for (auto& matrixRow_j : matrixRow) {
308  if (matrixRow_j == 1)
309  row.appendBit(true);
310  else if (matrixRow_j == 0)
311  row.appendBit(false);
312  else
313  throw cRuntimeError("A bool matrix only contains 0-1 values");
314  }
315  boolMatrix.push_back(row);
316  }
317 }

Referenced by ConvolutionalCoder().

◆ decode()

std::pair< BitVector, bool > inet::physicallayer::ConvolutionalCoder::decode ( const BitVector encodedBits) const
overridevirtual

Implements inet::physicallayer::IFecCoder.

428 {
429  BitVector isPunctured;
430  BitVector depuncturedEncodedBits = depuncturing(encodedBits, isPunctured);
431  unsigned int encodedBitsSize = depuncturedEncodedBits.getSize();
432  if (encodedBitsSize % codeRateParamaterN != 0)
433  throw cRuntimeError("Length of encodedBits must be a multiple of codeRateParamaterN = %d", codeRateParamaterN);
434  bool isTruncatedMode = false;
435  if (!strcmp(mode, "truncated"))
436  isTruncatedMode = true;
437  else if (!strcmp(mode, "terminated"))
438  isTruncatedMode = false;
439  else
440  throw cRuntimeError("Unknown decodingMode = %s decodingMode", mode);
441  TrellisGraphNode **trellisGraph;
442  trellisGraph = new TrellisGraphNode *[numberOfStates];
443  for (int i = 0; i != numberOfStates; i++) {
444  int length = depuncturedEncodedBits.getSize() / codeRateParamaterN + 1;
445  trellisGraph[i] = new TrellisGraphNode[length];
446  for (int j = 0; j < length; j++)
447  trellisGraph[i][j] = TrellisGraphNode(-1, -1, -1, INT32_MAX, 0, 0);
448  }
449  trellisGraph[0][0].state = 0;
450  EV_DEBUG << "Decoding the following bits: " << depuncturedEncodedBits << endl;
451  ShortBitVector countsOnHammingDistance;
452  countsOnHammingDistance.appendBit(true, codeRateParamaterN);
453  ShortBitVector nextOutputSymbol = giveNextOutputSymbol(depuncturedEncodedBits, 0, isPunctured, countsOnHammingDistance);
454  unsigned int time = 0;
455  while (!nextOutputSymbol.isEmpty()) {
456  updateTrellisGraph(trellisGraph, time, nextOutputSymbol, countsOnHammingDistance);
457  time++;
458  countsOnHammingDistance = ShortBitVector();
459  countsOnHammingDistance.appendBit(true, codeRateParamaterN);
460  nextOutputSymbol = giveNextOutputSymbol(depuncturedEncodedBits, time * codeRateParamaterK, isPunctured, countsOnHammingDistance);
461  }
462  TrellisGraphNode bestNode;
463  if (!isTruncatedMode)
464  bestNode = trellisGraph[0][time];
465  else {
466  bestNode = trellisGraph[0][time];
467  for (int i = 1; i != numberOfStates; i++) {
468  TrellisGraphNode currentNode = trellisGraph[i][time];
469  if (currentNode.symbol != -1 && currentNode.comulativeHammingDistance < bestNode.comulativeHammingDistance)
470  bestNode = currentNode;
471  }
472  }
473  std::pair<BitVector, bool> result = traversePath(bestNode, trellisGraph, isTruncatedMode);
474  if (result.second) {
475  EV_DEBUG << "Recovered message: " << result.first << endl;
476  EV_DEBUG << "Number of errors: " << bestNode.numberOfErrors
477  << " Cumulative error (Hamming distance): " << bestNode.comulativeHammingDistance
478  << " End state: " << bestNode.state << endl;
479  }
480  else
481  EV_DEBUG << "None of the paths in the trellis graph lead to the all-zeros state" << endl;
482  for (int i = 0; i < numberOfStates; i++)
483  delete[] trellisGraph[i];
484  delete[] trellisGraph;
485  return result;
486 }

Referenced by inet::physicallayer::ConvolutionalCoderModule::decode().

◆ depuncturing()

BitVector inet::physicallayer::ConvolutionalCoder::depuncturing ( const BitVector decodedBits,
BitVector isPunctured 
) const
protected
52 {
53  ASSERT(decodedBits.getSize() % codeRatePuncturingN == 0);
54  int encodedLength = (decodedBits.getSize() / codeRatePuncturingN) * codeRatePuncturingK;
55  int depuncturedLength = (encodedLength / codeRateParamaterK) * codeRateParamaterN;
56  isPunctured = getPuncturedIndices(depuncturedLength);
57  BitVector depuncturedDecodedBits;
58  int idx = 0;
59  for (int i = 0; i < depuncturedLength; i++) {
60  if (isPunctured.getBit(i))
61  depuncturedDecodedBits.appendBit(false);
62  else {
63  depuncturedDecodedBits.appendBit(decodedBits.getBit(idx));
64  idx++;
65  }
66  }
67  return depuncturedDecodedBits;
68 }

Referenced by decode().

◆ encode()

BitVector inet::physicallayer::ConvolutionalCoder::encode ( const BitVector informationBits) const
overridevirtual

Implements inet::physicallayer::IFecCoder.

198 {
199  EV_DEBUG << "Encoding the following bits: " << informationBits << endl;
200  if (informationBits.getSize() % codeRateParamaterK)
201  throw cRuntimeError("Length of informationBits must be a multiple of codeRateParamaterK = %d", codeRateParamaterK);
202  BitVector encodedInformationBits;
203  int state = 0;
204  for (unsigned int i = 0; i < informationBits.getSize(); i += codeRateParamaterK) {
205  ShortBitVector inputSymbol;
206  for (unsigned int j = i; j < i + codeRateParamaterK; j++)
207  inputSymbol.appendBit(informationBits.getBit(j));
208  int inputSymbolDec = inputSymbol.reverseToDecimal();
209  const ShortBitVector& encodedSymbol = outputSymbols[state][inputSymbolDec];
210  state = stateTransitions[state][inputSymbolDec];
211  for (unsigned int j = 0; j < encodedSymbol.getSize(); j++)
212  encodedInformationBits.appendBit(encodedSymbol.getBit(j));
213  }
214  BitVector puncturedEncodedInformationBits = puncturing(encodedInformationBits);
215  EV_DEBUG << "The encoded bits are: " << puncturedEncodedInformationBits << endl;
216  return puncturedEncodedInformationBits;
217 }

Referenced by inet::physicallayer::ConvolutionalCoderModule::encode().

◆ eXOR()

bool inet::physicallayer::ConvolutionalCoder::eXOR ( bool  alpha,
bool  beta 
) const
inlineprotected
77 { return alpha != beta; }

Referenced by inputSymbolToOutputSymbol(), and modulo2Adder().

◆ getConstraintLengthVector()

const std::vector<int>& inet::physicallayer::ConvolutionalCoder::getConstraintLengthVector ( ) const
inline
130 { return constraintLengths; }

◆ getForwardErrorCorrection()

const ConvolutionalCode* inet::physicallayer::ConvolutionalCoder::getForwardErrorCorrection ( ) const
inlineoverridevirtual

◆ getMemorySizeSum()

unsigned int inet::physicallayer::ConvolutionalCoder::getMemorySizeSum ( ) const
inline
129 { return memorySizeSum; }

◆ getNumberOfInputSymbols()

int inet::physicallayer::ConvolutionalCoder::getNumberOfInputSymbols ( ) const
inline
135 { return numberOfInputSymbols; }

◆ getNumberOfOutputSymbols()

int inet::physicallayer::ConvolutionalCoder::getNumberOfOutputSymbols ( ) const
inline
134 { return numberOfOutputSymbols; }

◆ getNumberOfStates()

int inet::physicallayer::ConvolutionalCoder::getNumberOfStates ( ) const
inline
133 { return numberOfStates; }

◆ getOutputTable()

const int** inet::physicallayer::ConvolutionalCoder::getOutputTable ( ) const
inline
141 { return (const int **)inputSymbols; }

◆ getPuncturedIndices()

BitVector inet::physicallayer::ConvolutionalCoder::getPuncturedIndices ( unsigned int  length) const
protected
25 {
26  BitVector isPunctured;
27  isPunctured.appendBit(false, length);
28  int puncturingMatrixSize = puncturingMatrix.at(0).getSize();
29  for (unsigned int i = 0; i < codeRateParamaterN; i++) {
30  int idx = 0;
31  for (unsigned int j = 0; codeRateParamaterN * j + i < length; j++) {
32  int place = idx % puncturingMatrixSize;
33  bool stolen = !puncturingMatrix.at(i).getBit(place);
34  isPunctured.setBit(codeRateParamaterN * j + i, stolen);
35  idx++;
36  }
37  }
38  return isPunctured;
39 }

Referenced by depuncturing(), and puncturing().

◆ getPuncturingMatrix()

const std::vector<ShortBitVector>& inet::physicallayer::ConvolutionalCoder::getPuncturingMatrix ( ) const
inline
132 { return puncturingMatrix; }

◆ getStateTransitionTable()

const int** inet::physicallayer::ConvolutionalCoder::getStateTransitionTable ( ) const
inline
140 { return (const int **)stateTransitions; }

◆ getTransferFunctionMatrix()

const ShortBitVectorMatrix& inet::physicallayer::ConvolutionalCoder::getTransferFunctionMatrix ( ) const
inline
131 { return transferFunctionMatrix; }

◆ giveNextOutputSymbol()

ShortBitVector inet::physicallayer::ConvolutionalCoder::giveNextOutputSymbol ( const BitVector encodedBits,
int  decodedLength,
const BitVector isPunctured,
ShortBitVector excludedFromHammingDistance 
) const
protected
263 {
264  if (isCompletelyDecoded(encodedBits.getSize(), decodedLength))
265  return ShortBitVector();
266  int pos = decodedLength / codeRateParamaterK;
267  ShortBitVector nextSymbol;
268  int idx = 0;
269  for (unsigned int i = pos * codeRateParamaterN; i < (pos + 1) * codeRateParamaterN; i++) {
270  if (isPunctured.getBit(i))
271  countsOnHammingDistance.setBit(idx, false);
272  nextSymbol.appendBit(encodedBits.getBit(i));
273  idx++;
274  }
275  return nextSymbol;
276 }

Referenced by decode().

◆ initParameters()

void inet::physicallayer::ConvolutionalCoder::initParameters ( )
protected

◆ inputSymbolToOutputSymbol()

ShortBitVector inet::physicallayer::ConvolutionalCoder::inputSymbolToOutputSymbol ( const ShortBitVector state,
const ShortBitVector inputSymbol 
) const
protected
71 {
72  ShortBitVector outputSymbol;
73  outputSymbol.appendBit(false, codeRateParamaterN);
74  int shift = 0;
75  for (int i = inputSymbol.getSize() - 1; i >= 0; i--) {
76  ShortBitVector shiftRegisters;
77  shiftRegisters.appendBit(inputSymbol.getBit(i));
78  for (int k = shift; k < shift + memorySizes[i]; k++)
79  shiftRegisters.appendBit((unsigned int)k >= state.getSize() ? false : state.getBit(k));
80  const std::vector<ShortBitVector>& row = transferFunctionMatrix.at(i);
81  for (unsigned int j = 0; j < row.size(); j++) {
82  const ShortBitVector& generatorPolynomial = row.at(j);
83  outputSymbol.setBit(j, eXOR(outputSymbol.getBit(j), modulo2Adder(shiftRegisters, generatorPolynomial)));
84  }
85  shift += memorySizes[i];
86  }
87  return outputSymbol;
88 }

Referenced by computeOutputAndInputSymbols().

◆ isCompletelyDecoded()

bool inet::physicallayer::ConvolutionalCoder::isCompletelyDecoded ( unsigned int  encodedLength,
unsigned int  decodedLength 
) const
protected
279 {
280  ASSERT(decodedLength % codeRateParamaterK == 0);
281  unsigned int pos = decodedLength / codeRateParamaterK;
282  return (pos + 1) * codeRateParamaterN > encodedLength;
283 }

Referenced by giveNextOutputSymbol().

◆ memoryAllocations()

void inet::physicallayer::ConvolutionalCoder::memoryAllocations ( )
protected
120 {
121  decimalToOutputSymbol = new ShortBitVector[numberOfOutputSymbols];
122  outputSymbols = new ShortBitVector *[numberOfStates];
123  decimalToInputSymbol = new ShortBitVector[numberOfInputSymbols];
124  stateTransitions = new int *[numberOfStates];
125  inputSymbols = new int *[numberOfStates];
126  hammingDistanceLookupTable = new unsigned char **[numberOfOutputSymbols];
127  for (int i = 0; i < numberOfOutputSymbols; i++) {
128  hammingDistanceLookupTable[i] = new unsigned char *[numberOfOutputSymbols];
129  for (int j = 0; j < numberOfOutputSymbols; j++)
130  hammingDistanceLookupTable[i][j] = new unsigned char[numberOfOutputSymbols];
131  }
132  for (int i = 0; i < numberOfStates; i++) {
134  inputSymbols[i] = new int[numberOfOutputSymbols];
135  outputSymbols[i] = new ShortBitVector[numberOfInputSymbols];
136  for (int j = 0; j < numberOfInputSymbols; j++) {
137  stateTransitions[i][j] = -1;
138  outputSymbols[i][j] = ShortBitVector();
139  }
140  for (int j = 0; j < numberOfOutputSymbols; j++)
141  inputSymbols[i][j] = -1;
142  }
143 }

Referenced by initParameters().

◆ modulo2Adder()

bool inet::physicallayer::ConvolutionalCoder::modulo2Adder ( const ShortBitVector shiftRegisters,
const ShortBitVector generatorPolynomial 
) const
protected
91 {
92  bool sum = false;
93  for (unsigned int i = 0; i < generatorPolynomial.getSize(); i++) {
94  if (generatorPolynomial.getBit(i))
95  sum = eXOR(sum, shiftRegisters.getBit(i));
96  }
97  return sum;
98 }

Referenced by inputSymbolToOutputSymbol().

◆ octalToBinary()

ShortBitVector inet::physicallayer::ConvolutionalCoder::octalToBinary ( int  octalNum,
int  fixedSize 
) const
protected
320 {
321  unsigned int powerOfEight = 1;
322  unsigned int decimal = 0;
323  while (octalNum > 0) {
324  unsigned int octalDigit = octalNum % 10;
325  octalNum /= 10;
326  decimal += octalDigit * powerOfEight;
327  powerOfEight *= 8;
328  }
329  return ShortBitVector(decimal, fixedSize);
330 }

Referenced by setTransferFunctionMatrix().

◆ octalToDec()

int inet::physicallayer::ConvolutionalCoder::octalToDec ( int  octalNum) const
protected
527 {
528  int powersOfEight = 1;
529  int decVal = 0;
530  while (octalNum != 0) {
531  int octDigit = octalNum % 10;
532  decVal += octDigit * powersOfEight;
533  octalNum /= 10;
534  powersOfEight *= 8;
535  }
536  return decVal;
537 }

Referenced by ConvolutionalCoder().

◆ parseMatrix()

void inet::physicallayer::ConvolutionalCoder::parseMatrix ( const char *  strMatrix,
std::vector< std::vector< int >> &  matrix 
) const
protected
286 {
287  cStringTokenizer tokenizer(strMatrix, ";");
288  while (tokenizer.hasMoreTokens()) {
289  std::vector<int> row;
290  parseVector(tokenizer.nextToken(), row);
291  matrix.push_back(row);
292  }
293 }

Referenced by ConvolutionalCoder().

◆ parseVector()

void inet::physicallayer::ConvolutionalCoder::parseVector ( const char *  strVector,
std::vector< int > &  vector 
) const
protected
296 {
297  cStringTokenizer tokenizer(strVector);
298  while (tokenizer.hasMoreTokens())
299  vector.push_back(atoi(tokenizer.nextToken()));
300 }

Referenced by ConvolutionalCoder(), and parseMatrix().

◆ printOutputs()

void inet::physicallayer::ConvolutionalCoder::printOutputs ( ) const
protected
220 {
221  std::cout << "Outputs" << endl;
222  for (int i = 0; i != numberOfStates; i++) {
223  std::cout << outputSymbols[i][0].reverseToDecimal();
224  for (int j = 1; j != numberOfInputSymbols; j++)
225  std::cout << " " << outputSymbols[i][j].reverseToDecimal();
226  std::cout << endl;
227  }
228  std::cout << "End Outputs" << endl;
229 }

◆ printStateTransitions()

void inet::physicallayer::ConvolutionalCoder::printStateTransitions ( ) const
protected
232 {
233  std::cout << "State transitions" << endl;
234  for (int i = 0; i != numberOfStates; i++) {
235  std::cout << stateTransitions[i][0];
236  for (int j = 1; j != numberOfInputSymbols; j++)
237  std::cout << " " << stateTransitions[i][j];
238  std::cout << endl;
239  }
240  std::cout << "End State transitions" << endl;
241 }

◆ printToStream()

std::ostream & inet::physicallayer::ConvolutionalCoder::printToStream ( std::ostream &  stream,
int  level,
int  evFlags = 0 
) const
overridevirtual

Prints this object to the provided output stream.

Reimplemented from inet::IPrintableObject.

17 {
18  stream << "ConvolutionalCoder";
19  if (level <= PRINT_LEVEL_TRACE)
21  return stream;
22 }

Referenced by inet::physicallayer::ConvolutionalCoderModule::printToStream().

◆ printTransferFunctionMatrix()

void inet::physicallayer::ConvolutionalCoder::printTransferFunctionMatrix ( ) const
protected
349 {
350  std::cout << "Transfer function matrix" << endl;
351  for (auto& elem : transferFunctionMatrix) {
352  std::cout << elem.at(0);
353  for (unsigned int j = 1; j < elem.size(); j++)
354  std::cout << "," << elem.at(j);
355  std::cout << endl;
356  }
357 }

◆ puncturing()

BitVector inet::physicallayer::ConvolutionalCoder::puncturing ( const BitVector informationBits) const
protected
42 {
43  BitVector puncturedInformationBits;
44  BitVector isPunctured = getPuncturedIndices(informationBits.getSize());
45  for (unsigned int i = 0; i < informationBits.getSize(); i++)
46  if (!isPunctured.getBit(i))
47  puncturedInformationBits.appendBit(informationBits.getBit(i));
48  return puncturedInformationBits;
49 }

Referenced by encode().

◆ setTransferFunctionMatrix()

void inet::physicallayer::ConvolutionalCoder::setTransferFunctionMatrix ( std::vector< std::vector< int >> &  transferFMatrix)
protected
333 {
334  for (unsigned int i = 0; i < transferFMatrix.size(); i++) {
335  const std::vector<int>& row = transferFMatrix.at(i);
336  std::vector<ShortBitVector> bitRow;
337  for (auto& elem : row) {
338  ShortBitVector bin = octalToBinary(elem, constraintLengths.at(i));
339  ShortBitVector reverseBin;
340  for (int k = bin.getSize() - 1; k >= 0; k--)
341  reverseBin.appendBit(bin.getBit(k));
342  bitRow.push_back(reverseBin);
343  }
344  transferFunctionMatrix.push_back(bitRow);
345  }
346 }

Referenced by ConvolutionalCoder().

◆ traversePath()

std::pair< BitVector, bool > inet::physicallayer::ConvolutionalCoder::traversePath ( const TrellisGraphNode bestNode,
TrellisGraphNode **  bestPaths,
bool  isTruncatedMode 
) const
protected
409 {
410  if (!isTruncatedMode && bestNode.symbol == -1)
411  return std::pair<BitVector, bool>(BitVector(), false);
412  TrellisGraphNode path = bestNode;
413  BitVector reverseDecodedBits;
414  int depth = bestNode.depth;
415  while (depth--) {
416  const ShortBitVector& inputSymbol = decimalToInputSymbol[path.symbol];
417  for (int i = inputSymbol.getSize() - 1; i >= 0; i--)
418  reverseDecodedBits.appendBit(inputSymbol.getBit(i));
419  path = trellisGraph[path.prevState][depth];
420  }
421  BitVector decodedBits;
422  for (int i = reverseDecodedBits.getSize() - 1; i >= 0; i--)
423  decodedBits.appendBit(reverseDecodedBits.getBit(i));
424  return std::pair<BitVector, bool>(decodedBits, true);
425 }

Referenced by decode().

◆ updateTrellisGraph()

void inet::physicallayer::ConvolutionalCoder::updateTrellisGraph ( TrellisGraphNode **  trellisGraph,
unsigned int  time,
const ShortBitVector outputSymbol,
const ShortBitVector excludedFromHammingDistance 
) const
protected
368 {
369  int tieBreakingCounter = 0;
370  for (int prevState = 0; prevState != numberOfStates; prevState++) {
371  const TrellisGraphNode& node = trellisGraph[prevState][time];
372  for (int j = 0; j != numberOfOutputSymbols && node.state != -1; j++) {
373  int feasibleDecodedSymbol = inputSymbols[prevState][j];
374  if (feasibleDecodedSymbol != -1) {
375  const ShortBitVector& otherOutputSymbol = decimalToOutputSymbol[j];
376  int hammingDistance = computeHammingDistance(outputSymbol, excludedFromHammingDistance, otherOutputSymbol);
377  int newState = stateTransitions[prevState][feasibleDecodedSymbol];
378  int cumulativeHammingDistance = hammingDistance;
379  if (node.comulativeHammingDistance != INT32_MAX)
380  cumulativeHammingDistance += node.comulativeHammingDistance;
381  TrellisGraphNode& best = trellisGraph[newState][time + 1];
382  bool replace = false;
383  if (cumulativeHammingDistance == best.comulativeHammingDistance) {
384  tieBreakingCounter++;
385  if (RNGCONTEXT dblrand() < 1.0 / tieBreakingCounter)
386  replace = true;
387  }
388  else if (cumulativeHammingDistance < best.comulativeHammingDistance) {
389  tieBreakingCounter = 0;
390  replace = true;
391  }
392  if (replace) {
393  best.state = newState;
394  best.prevState = prevState;
395  best.depth = node.depth + 1;
396  best.comulativeHammingDistance = cumulativeHammingDistance;
397  if (hammingDistance > 0)
398  best.numberOfErrors = node.numberOfErrors + 1;
399  else
400  best.numberOfErrors = node.numberOfErrors;
401  best.symbol = feasibleDecodedSymbol;
402  }
403  }
404  }
405  }
406 }

Referenced by decode().

Member Data Documentation

◆ codeRateParamaterK

◆ codeRateParamaterN

◆ codeRatePuncturingK

unsigned int inet::physicallayer::ConvolutionalCoder::codeRatePuncturingK
protected

Referenced by ConvolutionalCoder(), and depuncturing().

◆ codeRatePuncturingN

unsigned int inet::physicallayer::ConvolutionalCoder::codeRatePuncturingN
protected

Referenced by ConvolutionalCoder(), and depuncturing().

◆ constraintLengths

std::vector<int> inet::physicallayer::ConvolutionalCoder::constraintLengths
protected

◆ convolutionalCode

const ConvolutionalCode* inet::physicallayer::ConvolutionalCoder::convolutionalCode
protected

◆ decimalToInputSymbol

ShortBitVector* inet::physicallayer::ConvolutionalCoder::decimalToInputSymbol
protected

◆ decimalToOutputSymbol

ShortBitVector* inet::physicallayer::ConvolutionalCoder::decimalToOutputSymbol
protected

◆ hammingDistanceLookupTable

unsigned char*** inet::physicallayer::ConvolutionalCoder::hammingDistanceLookupTable
protected

◆ inputSymbols

int** inet::physicallayer::ConvolutionalCoder::inputSymbols
protected

◆ memorySizes

std::vector<int> inet::physicallayer::ConvolutionalCoder::memorySizes
protected

◆ memorySizeSum

int inet::physicallayer::ConvolutionalCoder::memorySizeSum
protected

◆ mode

const char* inet::physicallayer::ConvolutionalCoder::mode
protected

Referenced by ConvolutionalCoder(), and decode().

◆ numberOfInputSymbols

int inet::physicallayer::ConvolutionalCoder::numberOfInputSymbols
protected

◆ numberOfOutputSymbols

◆ numberOfStates

◆ outputSymbols

ShortBitVector** inet::physicallayer::ConvolutionalCoder::outputSymbols
protected

◆ puncturingMatrix

std::vector<ShortBitVector> inet::physicallayer::ConvolutionalCoder::puncturingMatrix
protected

◆ stateTransitions

int** inet::physicallayer::ConvolutionalCoder::stateTransitions
protected

◆ transferFunctionMatrix

ShortBitVectorMatrix inet::physicallayer::ConvolutionalCoder::transferFunctionMatrix
protected

◆ trellisGraph

std::vector<std::vector<TrellisGraphNode> > inet::physicallayer::ConvolutionalCoder::trellisGraph
protected

The documentation for this class was generated from the following files:
inet::physicallayer::ConvolutionalCoder::mode
const char * mode
Definition: ConvolutionalCoder.h:56
inet::physicallayer::ConvolutionalCoder::codeRateParamaterK
unsigned int codeRateParamaterK
Definition: ConvolutionalCoder.h:57
inet::physicallayer::ConvolutionalCoder::codeRatePuncturingK
unsigned int codeRatePuncturingK
Definition: ConvolutionalCoder.h:58
inet::physicallayer::ConvolutionalCode::getCodeRatePuncturingK
int getCodeRatePuncturingK() const
Definition: ConvolutionalCode.h:30
inet::physicallayer::ConvolutionalCoder::giveNextOutputSymbol
ShortBitVector giveNextOutputSymbol(const BitVector &encodedBits, int decodedLength, const BitVector &isPunctured, ShortBitVector &excludedFromHammingDistance) const
Definition: ConvolutionalCoder.cc:262
inet::physicallayer::ConvolutionalCoder::inputSymbols
int ** inputSymbols
Definition: ConvolutionalCoder.h:67
inet::physicallayer::ConvolutionalCoder::hammingDistanceLookupTable
unsigned char *** hammingDistanceLookupTable
Definition: ConvolutionalCoder.h:72
inet::physicallayer::ConvolutionalCoder::updateTrellisGraph
void updateTrellisGraph(TrellisGraphNode **trellisGraph, unsigned int time, const ShortBitVector &outputSymbol, const ShortBitVector &excludedFromHammingDistance) const
Definition: ConvolutionalCoder.cc:367
RNGCONTEXT
#define RNGCONTEXT
Definition: INETDefs.h:82
inet::physicallayer::ConvolutionalCoder::trellisGraph
std::vector< std::vector< TrellisGraphNode > > trellisGraph
Definition: ConvolutionalCoder.h:73
inet::physicallayer::ConvolutionalCoder::computeDecimalToOutputSymbolVector
void computeDecimalToOutputSymbolVector()
Definition: ConvolutionalCoder.cc:359
inet::physicallayer::ConvolutionalCoder::isCompletelyDecoded
bool isCompletelyDecoded(unsigned int encodedLength, unsigned int decodedLength) const
Definition: ConvolutionalCoder.cc:278
inet::physicallayer::ConvolutionalCoder::numberOfStates
int numberOfStates
Definition: ConvolutionalCoder.h:62
inet::physicallayer::ConvolutionalCoder::octalToDec
int octalToDec(int octalNum) const
Definition: ConvolutionalCoder.cc:526
inet::ShortBitVector::reverseToDecimal
unsigned int reverseToDecimal() const
Definition: ShortBitVector.h:40
inet::physicallayer::ConvolutionalCoder::computeNumberOfStates
void computeNumberOfStates()
Definition: ConvolutionalCoder.cc:151
inet::physicallayer::ConvolutionalCoder::codeRatePuncturingN
unsigned int codeRatePuncturingN
Definition: ConvolutionalCoder.h:58
inet::physicallayer::ConvolutionalCode::getConstraintLengthVector
const char * getConstraintLengthVector() const
Definition: ConvolutionalCode.h:32
inet::physicallayer::ConvolutionalCoder::memorySizeSum
int memorySizeSum
Definition: ConvolutionalCoder.h:59
inet::physicallayer::ConvolutionalCoder::outputSymbols
ShortBitVector ** outputSymbols
Definition: ConvolutionalCoder.h:68
inet::physicallayer::ConvolutionalCoder::numberOfOutputSymbols
int numberOfOutputSymbols
Definition: ConvolutionalCoder.h:64
inet::physicallayer::ConvolutionalCoder::computeStateTransitions
void computeStateTransitions()
Definition: ConvolutionalCoder.cc:243
inet::physicallayer::ConvolutionalCoder::codeRateParamaterN
unsigned int codeRateParamaterN
Definition: ConvolutionalCoder.h:57
inet::physicallayer::ConvolutionalCoder::decimalToInputSymbol
ShortBitVector * decimalToInputSymbol
Definition: ConvolutionalCoder.h:69
inet::physicallayer::ConvolutionalCoder::parseMatrix
void parseMatrix(const char *strMatrix, std::vector< std::vector< int >> &matrix) const
Definition: ConvolutionalCoder.cc:285
inet::printFieldToString
std::string printFieldToString(const IPrintableObject *object, int level, int evFlags=0)
Definition: IPrintableObject.h:98
inet::physicallayer::ConvolutionalCoder::setTransferFunctionMatrix
void setTransferFunctionMatrix(std::vector< std::vector< int >> &transferFMatrix)
Definition: ConvolutionalCoder.cc:332
inet::physicallayer::ConvolutionalCoder::eXOR
bool eXOR(bool alpha, bool beta) const
Definition: ConvolutionalCoder.h:77
inet::physicallayer::ConvolutionalCoder::computeMemorySizes
void computeMemorySizes()
Definition: ConvolutionalCoder.cc:145
inet::physicallayer::ConvolutionalCoder::octalToBinary
ShortBitVector octalToBinary(int octalNum, int fixedSize) const
Definition: ConvolutionalCoder.cc:319
inet::physicallayer::ConvolutionalCoder::transferFunctionMatrix
ShortBitVectorMatrix transferFunctionMatrix
Definition: ConvolutionalCoder.h:65
EV_FIELD
#define EV_FIELD(...)
Definition: INETDefs.h:112
inet::physicallayer::ConvolutionalCoder::initParameters
void initParameters()
Definition: ConvolutionalCoder.cc:184
inet::physicallayer::ConvolutionalCoder::puncturing
BitVector puncturing(const BitVector &informationBits) const
Definition: ConvolutionalCoder.cc:41
inet::physicallayer::ConvolutionalCoder::computeNumberOfInputAndOutputSymbols
void computeNumberOfInputAndOutputSymbols()
Definition: ConvolutionalCoder.cc:156
inet::physicallayer::ConvolutionalCoder::inputSymbolToOutputSymbol
ShortBitVector inputSymbolToOutputSymbol(const ShortBitVector &state, const ShortBitVector &inputSymbol) const
Definition: ConvolutionalCoder.cc:70
inet::physicallayer::ConvolutionalCode::getCodeRatePuncturingN
int getCodeRatePuncturingN() const
Definition: ConvolutionalCode.h:31
inet::physicallayer::ConvolutionalCoder::puncturingMatrix
std::vector< ShortBitVector > puncturingMatrix
Definition: ConvolutionalCoder.h:66
inet::ShortBitVector::appendBit
void appendBit(bool value)
Definition: ShortBitVector.h:56
inet::physicallayer::ConvolutionalCoder::modulo2Adder
bool modulo2Adder(const ShortBitVector &shiftRegisters, const ShortBitVector &generatorPolynomial) const
Definition: ConvolutionalCoder.cc:90
inet::physicallayer::ConvolutionalCode::getPuncturingMatrix
const char * getPuncturingMatrix() const
Definition: ConvolutionalCode.h:34
inet::physicallayer::ConvolutionalCoder::convolutionalCode
const ConvolutionalCode * convolutionalCode
Definition: ConvolutionalCoder.h:74
inet::physicallayer::ConvolutionalCoder::constraintLengths
std::vector< int > constraintLengths
Definition: ConvolutionalCoder.h:61
inet::physicallayer::ConvolutionalCoder::computeMemorySizeSum
void computeMemorySizeSum()
Definition: ConvolutionalCoder.cc:162
inet::physicallayer::ConvolutionalCoder::computeOutputAndInputSymbols
void computeOutputAndInputSymbols()
Definition: ConvolutionalCoder.cc:100
inet::IPrintableObject::PRINT_LEVEL_TRACE
@ PRINT_LEVEL_TRACE
Definition: IPrintableObject.h:22
inet::physicallayer::ConvolutionalCoder::numberOfInputSymbols
int numberOfInputSymbols
Definition: ConvolutionalCoder.h:63
inet::physicallayer::ConvolutionalCoder::memoryAllocations
void memoryAllocations()
Definition: ConvolutionalCoder.cc:119
inet::physicallayer::k
const double k
Definition: Qam1024Modulation.cc:14
inet::physicallayer::ConvolutionalCoder::depuncturing
BitVector depuncturing(const BitVector &decodedBits, BitVector &isPunctured) const
Definition: ConvolutionalCoder.cc:51
inet::evFlags
int evFlags
Definition: INETDefs.cc:12
inet::physicallayer::ConvolutionalCoder::stateTransitions
int ** stateTransitions
Definition: ConvolutionalCoder.h:71
inet::physicallayer::ConvolutionalCoder::parseVector
void parseVector(const char *strVector, std::vector< int > &vector) const
Definition: ConvolutionalCoder.cc:295
inet::physicallayer::ConvolutionalCoder::computeHammingDistanceLookupTable
void computeHammingDistanceLookupTable()
Definition: ConvolutionalCoder.cc:169
inet::units::constants::alpha
const value< double, units::unit > alpha(7.2973525376e-3)
inet::physicallayer::ConvolutionalCoder::computeHammingDistance
unsigned int computeHammingDistance(const ShortBitVector &u, const ShortBitVector &excludedBits, const ShortBitVector &w) const
Definition: ConvolutionalCoder.h:85
inet::physicallayer::ConvolutionalCoder::memorySizes
std::vector< int > memorySizes
Definition: ConvolutionalCoder.h:60
inet::physicallayer::ConvolutionalCode::getTransferFunctionMatrix
const char * getTransferFunctionMatrix() const
Definition: ConvolutionalCode.h:35
inet::units::values::m
value< double, units::m > m
Definition: Units.h:1233
inet::physicallayer::ConvolutionalCoder::decimalToOutputSymbol
ShortBitVector * decimalToOutputSymbol
Definition: ConvolutionalCoder.h:70
inet::physicallayer::ConvolutionalCode::getMode
const char * getMode() const
Definition: ConvolutionalCode.h:33
inet::physicallayer::ConvolutionalCoder::convertToShortBitVectorMatrix
void convertToShortBitVectorMatrix(std::vector< std::vector< int >> &matrix, std::vector< ShortBitVector > &boolMatrix) const
Definition: ConvolutionalCoder.cc:302
inet::physicallayer::ConvolutionalCoder::traversePath
std::pair< BitVector, bool > traversePath(const TrellisGraphNode &bestNode, TrellisGraphNode **bestPaths, bool isTruncatedMode) const
Definition: ConvolutionalCoder.cc:408
inet::physicallayer::ConvolutionalCoder::getPuncturedIndices
BitVector getPuncturedIndices(unsigned int length) const
Definition: ConvolutionalCoder.cc:24