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
 | 
