// License: AGPLv3 or later. https://www.gnu.org/licenses/licenses.html #ifndef _CFC_H_ #define _CFC_H_ #include #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 class Codeword { public: Codeword(); Codeword(std::vector &aTVector); Codeword(const Codeword &aCodeword); void push_back(T symbol); std::vector 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 &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 codeword; int weight = 0; //bool isZerocodeword; }; template class Codebook { public: Codebook(); Codebook(std::vector &aTVector); Codebook(const Codebook &aCodebook); void push_back(T codeword); std::vector getCodebook() const; void Display() const; int getMinimumWeight() const; std::vector> 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> distance; int minDistance = 0; std::vector codebook; inline void updateIfNewMinimumDistance(int aDistance); }; class driver { public: driver(processArguments &ProgArgs); private: template void processMintOrMelt(U aMintOrMelt); void processMint(Codebook> &theCodebook); void processMelt(Codebook> &theCodebook); // placeholder functions which are never called and // will print error and quit if called void processMint(Codebook> &theCodebook); void processMelt(Codebook> &theCodebook); processArguments &ProgramArguments; }; /******TEMPLATE CLASES AND FUNCTIONS DEFINITION STARTS FROM HERE******/ template void driver::processMintOrMelt(U aMintOrMelt) { Codebook> theCodebook; Codeword 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 Codeword::Codeword() { } template Codeword::Codeword(std::vector &aTVector) { for (T symbol: aTVector) { codeword.push_back(symbol); } Weight(); } template Codeword::Codeword(const Codeword &aCodeword) { codeword = aCodeword.getCodeword(); weight = aCodeword.getWeight(); } template void Codeword::push_back(T symbol) { codeword.push_back(symbol); incrementalWeight(); } template std::vector Codeword::getCodeword() const { return codeword; } template int Codeword::getWeight() const { return weight; } template int Codeword::Distance(const Codeword &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 void Codeword::Display() const { for(T symbol: codeword) { std::cout << symbol.getSymbol() << " "; } std::cout << " Weight: " << weight << std::endl; } template int Codeword::size() const { return codeword.size(); } template T Codeword::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 void Codeword::Weight() { weight = 0; for (T symbol: codeword) { if (symbol.getSymbol() != symbol.zeroSymbol) { weight++; } } } template void Codeword::incrementalWeight() { if (codeword[codeword.size()-1].getSymbol() != codeword[0].zeroSymbol) { weight++; } } template Codebook::Codebook() { } template Codebook::Codebook(std::vector &aTVector) { for (T codeword: aTVector) { codebook.push_back(codeword); } doCalculations(); } template Codebook::Codebook(const Codebook &aCodebook) { minWeight = aCodebook.getMinimumWeight(); distance = aCodebook.getDistance(); minDistance = aCodebook.getMinimumDistance(); codebook = aCodebook.getCodebook(); } template void Codebook::push_back(T codeword) { codebook.push_back(codeword); doIncrementalCalculations(); } template std::vector Codebook::getCodebook() const { return codebook; } template void Codebook::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 int Codebook::getMinimumWeight() const { return minWeight; } template std::vector> Codebook::getDistance() const { return distance; } template int Codebook::getMinimumDistance() const { return minDistance; } template void Codebook::doCalculations() { minimumWeight(); calcDistance(); minimumDistance(); } template void Codebook::minimumWeight() { for (T codeword: codebook) { int weight = codeword.getWeight(); if (weight < minWeight or minWeight == 0) { minWeight = weight; } } } template void Codebook::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 void Codebook::minimumDistance() { for (std::vector distanceVector: distance) { for (int aDistance: distanceVector) { if ((aDistance < minDistance and aDistance != 0) or minDistance == 0) { minDistance = aDistance; } } } } template void Codebook::doIncrementalCalculations() { minimumIncrementalWeight(); calcIncrementalDistance(); minimumDistance(); } template void Codebook::minimumIncrementalWeight() { int weight = codebook[codebook.size()-1].getWeight(); if (weight < minWeight or minWeight == 0) { minWeight = weight; } } template void Codebook::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 void Codebook::minimumIncrementalDistance() { for (int aDistance: distance[distance.size()-1]) { if (aDistance < minDistance or minDistance == 0) { minDistance = aDistance; } } } #endif