You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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