458 lines
10 KiB
C
458 lines
10 KiB
C
![]() |
// License: AGPLv3 or later. https://www.gnu.org/licenses/licenses.html
|
||
|
|
||
|
#ifndef _CFC_H_
|
||
|
#define _CFC_H_
|
||
|
|
||
|
#include <vector>
|
||
|
|
||
|
#include "auxiliary.h"
|
||
|
#include "general_functions.h"
|
||
|
|
||
|
class Mint
|
||
|
{
|
||
|
public:
|
||
|
Mint() {};
|
||
|
Mint(int Number, int Modulus);
|
||
|
int getNumber() const;
|
||
|
// standard function to be used for template codeword.
|
||
|
// it just 'return getNumber();'
|
||
|
int getSymbol() const;
|
||
|
int operator-(const Mint mint2) const;
|
||
|
static const int zeroSymbol = 0;
|
||
|
private:
|
||
|
int number;
|
||
|
int modulus;
|
||
|
};
|
||
|
|
||
|
class Melt
|
||
|
{
|
||
|
public:
|
||
|
Melt() {};
|
||
|
Melt(char Character);
|
||
|
char getCharacter() const;
|
||
|
// standard function to be used for template codeword.
|
||
|
// it just 'return getCharacter();'
|
||
|
char getSymbol() const;
|
||
|
int operator-(const Melt melt2) const;
|
||
|
static const char zeroSymbol = 'a';
|
||
|
private:
|
||
|
char character;
|
||
|
};
|
||
|
|
||
|
template<typename T>
|
||
|
class Codeword
|
||
|
{
|
||
|
public:
|
||
|
Codeword();
|
||
|
Codeword(std::vector<T> &aTVector);
|
||
|
Codeword(const Codeword<T> &aCodeword);
|
||
|
void push_back(T symbol);
|
||
|
std::vector<T> getCodeword() const;
|
||
|
int getWeight() const;
|
||
|
// return -1 if encounters error i.e.:
|
||
|
// If size of own codeword and codeword passed as argument
|
||
|
// mismatch However It Will Not Happen Within Runtime Of This
|
||
|
// Program. This is just defensive programming.
|
||
|
int Distance(const Codeword<T> &aCodeword) const;
|
||
|
void Display() const;
|
||
|
int size() const;
|
||
|
T getSymbolByIndex(int index) const;
|
||
|
//bool isZeroCodeword() const;
|
||
|
private:
|
||
|
void Weight();
|
||
|
void incrementalWeight();
|
||
|
//void calculateIfZeroCodeword();
|
||
|
std::vector<T> codeword;
|
||
|
int weight = 0;
|
||
|
//bool isZerocodeword;
|
||
|
};
|
||
|
|
||
|
template<typename T>
|
||
|
class Codebook
|
||
|
{
|
||
|
public:
|
||
|
Codebook();
|
||
|
Codebook(std::vector<T> &aTVector);
|
||
|
Codebook(const Codebook<T> &aCodebook);
|
||
|
void push_back(T codeword);
|
||
|
std::vector<T> getCodebook() const;
|
||
|
void Display() const;
|
||
|
int getMinimumWeight() const;
|
||
|
std::vector<std::vector<int>> getDistance() const;
|
||
|
int getMinimumDistance() const;
|
||
|
private:
|
||
|
// this function simply calls other three private functions
|
||
|
void doCalculations();
|
||
|
void minimumWeight();
|
||
|
void calcDistance();
|
||
|
void minimumDistance();
|
||
|
void doIncrementalCalculations();
|
||
|
void minimumIncrementalWeight();
|
||
|
void calcIncrementalDistance();
|
||
|
void minimumIncrementalDistance();
|
||
|
int minWeight = 0;
|
||
|
std::vector<std::vector<int>> distance;
|
||
|
int minDistance = 0;
|
||
|
std::vector<T> codebook;
|
||
|
inline void updateIfNewMinimumDistance(int aDistance);
|
||
|
};
|
||
|
|
||
|
class driver
|
||
|
{
|
||
|
public:
|
||
|
driver(processArguments &ProgArgs);
|
||
|
private:
|
||
|
template<typename U>
|
||
|
void processMintOrMelt(U aMintOrMelt);
|
||
|
void processMint(Codebook<Codeword<Mint>> &theCodebook);
|
||
|
void processMelt(Codebook<Codeword<Melt>> &theCodebook);
|
||
|
// placeholder functions which are never called and
|
||
|
// will print error and quit if called
|
||
|
void processMint(Codebook<Codeword<Melt>> &theCodebook);
|
||
|
void processMelt(Codebook<Codeword<Mint>> &theCodebook);
|
||
|
processArguments &ProgramArguments;
|
||
|
};
|
||
|
|
||
|
|
||
|
/******TEMPLATE CLASES AND FUNCTIONS DEFINITION STARTS FROM HERE******/
|
||
|
|
||
|
|
||
|
template<typename U>
|
||
|
void driver::processMintOrMelt(U aMintOrMelt)
|
||
|
{
|
||
|
Codebook<Codeword<U>> theCodebook;
|
||
|
Codeword<U> aCodeword;
|
||
|
for (int i=0; i < 1 &&i < ProgramArguments.codebookSize(); i++)
|
||
|
{
|
||
|
for (int j=0; j < ProgramArguments.codewordLength(); j++)
|
||
|
{
|
||
|
aCodeword.push_back(aMintOrMelt);
|
||
|
}
|
||
|
theCodebook.push_back(aCodeword);
|
||
|
}
|
||
|
if (typeid(U) == typeid(Mint))
|
||
|
{
|
||
|
processMint(theCodebook);
|
||
|
}
|
||
|
else if (typeid(U) == typeid(Melt))
|
||
|
{
|
||
|
processMelt(theCodebook);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
Codeword<T>::Codeword()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
Codeword<T>::Codeword(std::vector<T> &aTVector)
|
||
|
{
|
||
|
for (T symbol: aTVector)
|
||
|
{
|
||
|
codeword.push_back(symbol);
|
||
|
}
|
||
|
Weight();
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
Codeword<T>::Codeword(const Codeword<T> &aCodeword)
|
||
|
{
|
||
|
codeword = aCodeword.getCodeword();
|
||
|
weight = aCodeword.getWeight();
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
void Codeword<T>::push_back(T symbol)
|
||
|
{
|
||
|
codeword.push_back(symbol);
|
||
|
incrementalWeight();
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
std::vector<T> Codeword<T>::getCodeword() const
|
||
|
{
|
||
|
return codeword;
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
int Codeword<T>::getWeight() const
|
||
|
{
|
||
|
return weight;
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
int Codeword<T>::Distance(const Codeword<T> &aCodeword) const
|
||
|
{
|
||
|
int distance = 0;
|
||
|
if (codeword.size() != aCodeword.size())
|
||
|
{
|
||
|
cerr_only(
|
||
|
"Internal",
|
||
|
__FILE__,
|
||
|
__func__,
|
||
|
__LINE__,
|
||
|
"For calculating Codeword Distance, no. of symbols in own"
|
||
|
" codeword and codeword passed as argument mismatch. "
|
||
|
"Though technically a possiblity, it should not happen "
|
||
|
"within the run of this program."
|
||
|
);
|
||
|
distance = -1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
for (int i=0; i < size(); i++)
|
||
|
{
|
||
|
distance += codeword[i] - aCodeword.getSymbolByIndex(i);
|
||
|
}
|
||
|
}
|
||
|
return distance;
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
void Codeword<T>::Display() const
|
||
|
{
|
||
|
for(T symbol: codeword)
|
||
|
{
|
||
|
std::cout << symbol.getSymbol() << " ";
|
||
|
}
|
||
|
std::cout << " Weight: " << weight << std::endl;
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
int Codeword<T>::size() const
|
||
|
{
|
||
|
return codeword.size();
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
T Codeword<T>::getSymbolByIndex(int index) const
|
||
|
{
|
||
|
if (codeword.size() > index)
|
||
|
{
|
||
|
return codeword[index];
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
cerr_only(
|
||
|
"internal",
|
||
|
__FILE__,
|
||
|
__func__,
|
||
|
__LINE__,
|
||
|
"Index symbol requqested is greater than cointainer size "
|
||
|
"An empty symbol of same type will be returned but this "
|
||
|
"will therefore give garbage result."
|
||
|
);
|
||
|
T emptySymbol;
|
||
|
return emptySymbol;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
void Codeword<T>::Weight()
|
||
|
{
|
||
|
weight = 0;
|
||
|
for (T symbol: codeword)
|
||
|
{
|
||
|
if (symbol.getSymbol() != symbol.zeroSymbol)
|
||
|
{
|
||
|
weight++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
void Codeword<T>::incrementalWeight()
|
||
|
{
|
||
|
if (codeword[codeword.size()-1].getSymbol()
|
||
|
!= codeword[0].zeroSymbol)
|
||
|
{
|
||
|
weight++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
Codebook<T>::Codebook()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
Codebook<T>::Codebook(std::vector<T> &aTVector)
|
||
|
{
|
||
|
for (T codeword: aTVector)
|
||
|
{
|
||
|
codebook.push_back(codeword);
|
||
|
}
|
||
|
doCalculations();
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
Codebook<T>::Codebook(const Codebook<T> &aCodebook)
|
||
|
{
|
||
|
minWeight = aCodebook.getMinimumWeight();
|
||
|
distance = aCodebook.getDistance();
|
||
|
minDistance = aCodebook.getMinimumDistance();
|
||
|
codebook = aCodebook.getCodebook();
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
void Codebook<T>::push_back(T codeword)
|
||
|
{
|
||
|
codebook.push_back(codeword);
|
||
|
doIncrementalCalculations();
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
std::vector<T> Codebook<T>::getCodebook() const
|
||
|
{
|
||
|
return codebook;
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
void Codebook<T>::Display() const
|
||
|
{
|
||
|
for (T codeword: codebook)
|
||
|
{
|
||
|
codeword.Display();
|
||
|
}
|
||
|
std::cout
|
||
|
<< "Minimum Weight: " << minWeight << '\n'
|
||
|
<< "Minimum Distance: " << minDistance << '\n'
|
||
|
<< "Distances Table:" << std::endl;
|
||
|
for (auto row: distance)
|
||
|
{
|
||
|
for (int eachDistance: row)
|
||
|
{
|
||
|
std::cout << eachDistance << " ";
|
||
|
}
|
||
|
std::cout << "\b\n";
|
||
|
}
|
||
|
std::cout << std::flush;
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
int Codebook<T>::getMinimumWeight() const
|
||
|
{
|
||
|
return minWeight;
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
std::vector<std::vector<int>> Codebook<T>::getDistance() const
|
||
|
{
|
||
|
return distance;
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
int Codebook<T>::getMinimumDistance() const
|
||
|
{
|
||
|
return minDistance;
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
void Codebook<T>::doCalculations()
|
||
|
{
|
||
|
minimumWeight();
|
||
|
calcDistance();
|
||
|
minimumDistance();
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
void Codebook<T>::minimumWeight()
|
||
|
{
|
||
|
for (T codeword: codebook)
|
||
|
{
|
||
|
int weight = codeword.getWeight();
|
||
|
if (weight < minWeight or minWeight == 0)
|
||
|
{
|
||
|
minWeight = weight;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
void Codebook<T>::calcDistance()
|
||
|
{
|
||
|
int i = 0;
|
||
|
for (T codeword: codebook)
|
||
|
{
|
||
|
distance.emplace_back();
|
||
|
for(T otherCodeword: codebook)
|
||
|
{
|
||
|
int aDistance = codeword.Distance(otherCodeword);
|
||
|
distance[i].push_back(aDistance);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
void Codebook<T>::minimumDistance()
|
||
|
{
|
||
|
for (std::vector<int> distanceVector: distance)
|
||
|
{
|
||
|
for (int aDistance: distanceVector)
|
||
|
{
|
||
|
if ((aDistance < minDistance
|
||
|
and aDistance != 0)
|
||
|
or minDistance == 0)
|
||
|
{
|
||
|
minDistance = aDistance;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
void Codebook<T>::doIncrementalCalculations()
|
||
|
{
|
||
|
minimumIncrementalWeight();
|
||
|
calcIncrementalDistance();
|
||
|
minimumDistance();
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
void Codebook<T>::minimumIncrementalWeight()
|
||
|
{
|
||
|
int weight = codebook[codebook.size()-1].getWeight();
|
||
|
if (weight < minWeight or minWeight == 0)
|
||
|
{
|
||
|
minWeight = weight;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
void Codebook<T>::calcIncrementalDistance()
|
||
|
{
|
||
|
int lastCodeword = codebook.size()-1;
|
||
|
|
||
|
// Adding new column to table
|
||
|
// previous codewords - new codeowrd
|
||
|
for (int i=0; i < distance.size(); i++)
|
||
|
{
|
||
|
int aDistance = codebook[i].Distance(codebook[lastCodeword]);
|
||
|
distance[i].push_back(aDistance);
|
||
|
}
|
||
|
|
||
|
// Adding new row to table
|
||
|
// new codeword - all Codewords
|
||
|
distance.emplace_back();
|
||
|
for(T aCodeword: codebook)
|
||
|
{
|
||
|
int aDistance = codebook[lastCodeword].Distance(aCodeword);
|
||
|
distance[distance.size()-1].push_back(aDistance);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
void Codebook<T>::minimumIncrementalDistance()
|
||
|
{
|
||
|
for (int aDistance: distance[distance.size()-1])
|
||
|
{
|
||
|
if (aDistance < minDistance or minDistance == 0)
|
||
|
{
|
||
|
minDistance = aDistance;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#endif
|