Skip to content
Snippets Groups Projects
Select Git revision
  • 53396bde1522bc62998562d80dea78fe4626ed24
  • master default
  • 1.1
  • 1.0
4 results

inductor.cpp

Blame
  • translators.cpp 13.80 KiB
    #include "translators.h"
    #include <vector>
    #include <iostream>
    #include <cassert>
    #include <map>
    #include <algorithm>
    #include <sstream>
    
    #include "strops.h"
    #include "eistype.h"
    #include "log.h"
    #include "componant.h"
    
    namespace eis
    {
    
    const struct std::pair<const char*, const char*> eisRelaxisTable[] =
    {
    	{"r", "R"},
    	{"R", "R"},
    	{"c", "C"},
    	{"C", "C"},
    	{"l", "I"},
    	{"L", "I"},
    	{"p", "P"},
    	{"P", "P"},
    	{"w", "W"},
    	{"W", "W"},
    	{"t", "Tlmo"},
    	{"T", "Tlmo"},
    	{nullptr, nullptr}
    };
    
    const struct std::pair<const char*, const char*> eisCdcTable[] =
    {
    	{"r", "R"},
    	{"R", "R"},
    	{"c", "C"},
    	{"C", "C"},
    	{"l", "L"},
    	{"L", "L"},
    	{"p", "P"},
    	{"P", "P"},
    	{"w", "W"},
    	{"W", "W"},
    	{"t", "T"},
    	{"T", "T"},
    	{nullptr, nullptr}
    };
    
    const struct std::pair<const char*, const char*> eisMadapTable[] =
    {
    	{"r", "R"},
    	{"R", "R"},
    	{"c", "C"},
    	{"C", "C"},
    	{"l", "L"},
    	{"L", "L"},
    	{"p", "CPE"},
    	{"P", "CPE"},
    	{"w", "W"},
    	{"W", "W"},
    	{"w", "Wo"},
    	{"W", "Wo"},
    	{nullptr, nullptr}
    };
    
    static std::string translateElement(const std::string& in, const struct std::pair<const char*, const char*>* table, bool reverse = false)
    {
    	size_t i = 0;
    	while(!reverse ? table[i].first : table[i].second)
    	{
    		if(std::string(!reverse ? table[i].first : table[i].second) == in)
    			return std::string(reverse ? table[i].first : table[i].second);
    		++i;
    	}
    
    	return std::string("x");
    }
    
    static bool isValidSymbol(const std::string& in, const struct std::pair<const char*, const char*>* table, bool reverse = false)
    {
    	size_t i = 0;
    	while(!reverse ? table[i].first : table[i].second)
    	{
    		if(std::string(!reverse ? table[i].first : table[i].second) == in)
    			return true;
    		++i;
    	}
    	return false;
    }
    
    void purgeEisParamBrackets(std::string& in)
    {
    	int bracketCounter = 0;
    
    	std::string out;
    
    	for(size_t i = 0; i < in.size(); ++i)
    	{
    		if(in[i] == '{' || in[i] == '[' || in[i] == '<')
    			++bracketCounter;
    		if(bracketCounter == 0)
    			out.push_back(in[i]);
    		if(in[i] == '}' || in[i] == ']' || in[i] == '>')
    			--bracketCounter;
    	}
    	in = out;
    }
    
    std::string relaxisToEis(const std::string& in, const std::vector<double>& params)
    {
    	std::string out;
    	std::string work(in);
    	purgeEisParamBrackets(work);
    
    	for(size_t i = 0; i < work.size(); ++i)
    	{
    		if(isValidSymbol(std::string(1, work[i]), eisRelaxisTable, true))
    		{
    			if(i != 0 && work[i-1] != '(' && work[i-1] != '-')
    			{
    				work.insert(i, "-");
    				++i;
    			}
    			if(i < work.size()-1 && work[i+1] != ')' && work[i+1] != '-')
    				work.insert(i+1, "-");
    		}
    	}
    
    	for(size_t i = 0; i < work.size(); ++i)
    	{
    		if(isValidSymbol(std::string(1, work[i]), eisRelaxisTable, true))
    			out.append(translateElement(std::string(1, work[i]), eisRelaxisTable, true));
    		else if(work[i] == '-' || work[i] == '(' || work[i] == ')')
    			out.push_back(work[i]);
    		else
    			throw parse_errror("invalid or unkown symbol in relaxis circuit string: " + std::string(1, work[i]));
    	}
    
    	for(size_t i = 0; i < out.size(); ++i)
    	{
    		if(out[i] == '(' && i < out.size()-2 && out[i+2] == ')' )
    		{
    			out.erase(out.begin()+i+2);
    			out.erase(out.begin()+i);
    			--i;
    		}
    	}
    
    	if(!params.empty())
    	{
    		size_t elementIndex = 0;
    		for(size_t i = 0; i < out.size() && elementIndex < params.size(); ++i)
    		{
    			if(isValidSymbol(std::string(1, out[i]), eisRelaxisTable, false))
    			{
    				Log::Level oldLevel = Log::level;
    				Log::level =  Log::ERROR;
    				Componant* componant = Componant::createNewComponant(out[i]);
    				Log::level =  oldLevel;
    				if(componant->paramCount() > 0)
    				{
    					std::stringstream paramstream;
    					paramstream<<'{'<<std::scientific;
    					for(size_t j = 0; j < componant->paramCount() && elementIndex < params.size(); ++j)
    					{
    						paramstream<<params[elementIndex];
    						paramstream<<", ";
    						++elementIndex;
    					}
    					std::string paramStr = paramstream.str();
    					paramStr.pop_back();
    					paramStr.pop_back();
    					paramStr.push_back('}');
    					out.insert(i+1, paramStr);
    				}
    			}
    		}
    	}
    
    	if(out.size() < 3)
    		return out;
    
    	return out;
    }
    
    std::string eisToRelaxis(const std::string& in)
    {
    	std::string work = eisToCdc(in);
    	std::string out;
    
    	size_t level = 0;
    
    	for(size_t i = 0; i < work.size(); ++i)
    	{
    		if(work[i] == '[' || work[i] == '(')
    		{
    			out.push_back('(');
    			++level;
    		}
    		else if(work[i] == ']' || work[i] == ')')
    		{
    			if(out.back() == '-')
    				out.pop_back();
    			out.push_back(')');
    			--level;
    		}
    		else
    		{
    			std::string eisElement = translateElement(std::string(1, work[i]), eisCdcTable, true);
    			std::string relaxisElement = translateElement(eisElement, eisRelaxisTable, false);
    			if(level % 2 == 1)
    			{
    				relaxisElement.push_back(')');
    				relaxisElement.insert(relaxisElement.begin(), '(');
    			}
    			out.append(relaxisElement);
    			if(level % 2 == 0)
    				out.push_back('-');
    		}
    	}
    
    	if(out.back() == '-')
    		out.pop_back();
    
    	return out;
    }
    
    std::string cdcToEis(std::string in)
    {
    	std::string out;
    
    	size_t level = 0;
    
    	for(size_t i = 0; i < in.size(); ++i)
    	{
    		if(in[i] == '[' || in[i] == '(')
    		{
    			out.push_back('(');
    			++level;
    		}
    		else if(in[i] == ']' || in[i] == ')')
    		{
    			if(out.back() == '-')
    				out.pop_back();
    			out.push_back(')');
    			--level;
    		}
    		else
    		{
    			out.append(translateElement(std::string(1, in[i]), eisCdcTable, true));
    			if(level % 2 == 0)
    				out.push_back('-');
    		}
    	}
    
    	if(out.back() == '-')
    		out.pop_back();
    
    	eisRemoveUnneededBrackets(out);
    	return out;
    }
    
    static void balanceBrakets(std::string& in)
    {
    	std::string appendStr;
    	for(size_t i = 0; i < in.size(); ++i)
    	{
    		switch(in[i])
    		{
    			case '(':
    				appendStr.push_back(')');
    				continue;
    			case '[':
    				appendStr.push_back(']');
    				continue;
    			case ')':
    				appendStr.pop_back();
    				continue;
    			case ']':
    				appendStr.pop_back();
    				continue;
    			default:
    				continue;
    		}
    	}
    	for(size_t i = appendStr.size(); i > 0; --i)
    		in.push_back(appendStr[i-1]);
    }
    
    static std::string cdcForBacket(const std::string& in, long int bracketStart)
    {
    	size_t bracketEnd;
    	for(bracketEnd = bracketStart+1 ; bracketEnd < in.size() && in[bracketEnd] != ')'; ++bracketEnd);
    
    	std::string bracket = in.substr(bracketStart+1, bracketEnd-(bracketStart+1));
    
    	bool serial = true;
    
    	if(bracket.size() > 1 && bracket[1] != '-')
    		serial = false;
    
    	std::string out("[");
    	if(!serial)
    		out.push_back('(');
    
    	for(size_t i = 0; i < bracket.size(); ++i)
    	{
    		if(bracket[i] == '-')
    			continue;
    		if(serial && i+1 < bracket.size() && bracket[i+1] != '-')
    		{
    			out.push_back('(');
    			serial = false;
    		}
    
    		if(bracket[i] > 47 && bracket[i] < 58)
    			out.push_back(bracket[i]);
    		else if(isValidSymbol(std::string(1, bracket[i]), eisCdcTable))
    			out.append(translateElement(std::string(1, bracket[i]), eisCdcTable));
    
    		if(!serial && i+1 < bracket.size() && bracket[i+1] == '-' )
    		{
    			out.push_back(')');
    			serial = true;
    		}
    
    	}
    
    	balanceBrakets(out);
    
    	return out;
    }
    
    static size_t getDeepestBraket(const std::string& in, size_t& maxDepth)
    {
    	size_t loc = 0;
    	size_t depth = 0;
    	maxDepth = 0;
    
    	for(size_t i = 0; i < in.size(); ++i)
    	{
    		if(in[i] == '(')
    		{
    			++depth;
    			if(depth > maxDepth)
    			{
    				maxDepth = depth;
    				loc = i;
    			}
    		}
    		else if(in[i] == ')')
    		{
    			--depth;
    		}
    	}
    	return loc;
    }
    
    static void replaceBraket(std::string& in, size_t start, size_t num)
    {
    	char opposing;
    	switch(in[start])
    	{
    		case '(':
    			opposing = ')';
    			break;
    		case '[':
    			opposing = ']';
    			break;
    		default:
    			return;
    	}
    
    	size_t end;
    	for(end = start; end < in.size() && in[end] != opposing; ++end);
    
    	in.erase(start, (end-start)+1);
    	in.insert(start, std::to_string(num));
    
    }
    
    std::string eisToCdc(const std::string& in)
    {
    	std::vector<std::string> brackets;
    	std::string workString = in;
    	purgeEisParamBrackets(workString);
    
    	size_t maxDepth;
    	size_t bracketStart = getDeepestBraket(workString, maxDepth);
    	while(maxDepth > 0)
    	{
    		brackets.push_back(cdcForBacket(workString, bracketStart));
    		replaceBraket(workString, bracketStart, brackets.size()-1);
    		bracketStart = getDeepestBraket(workString, maxDepth);
    	}
    
    	std::string out = cdcForBacket(workString, -1);
    
    	for(size_t i = 0; i < out.size(); ++i)
    	{
    		if(out[i] > 47 && out[i] < 58 && static_cast<size_t>(out[i]-48) < brackets.size())
    		{
    			out.insert(i+1, brackets[out[i]-48]);
    			out.erase(out.begin()+i);
    		}
    	}
    
    	bool paralelFirst = false;
    	for(size_t i = 1; i < out.size(); ++i)
    	{
    		if(out[i] == '[')
    		{
    			paralelFirst = true;
    			break;
    		}
    		else if(out[i] == '(')
    		{
    			break;
    		}
    	}
    
    	if(!paralelFirst)
    	{
    		out.erase(out.begin());
    		out.erase(out.end()-1);
    	}
    
    	return out;
    }
    
    static std::string madapStrip(const std::string& in)
    {
    	std::string out;
    	out.reserve(in.size());
    	for(char ch : in)
    	{
    		if(ch == 'p')
    			continue;
    		out.push_back(ch);
    	}
    	return out;
    }
    
    std::string madapTranslateSerial(const std::string& in, const std::map<std::string, std::string>& parameters);
    
    std::string madapTranslateParalell(const std::string& in, const std::map<std::string, std::string>& parameters)
    {
    	std::string out;
    	out.push_back('(');
    	std::vector<std::string> tokens = tokenize(in, ',', '(', ')', '\\');
    	for(std::string& token : tokens)
    	{
    		out.push_back('(');
    		if(token[0] == '(')
    		{
    			if(token.back() != ')')
    				throw parse_errror("unbounded bracket");
    			token.pop_back();
    			token.erase(token.begin());
    			out.append(madapTranslateParalell(token, parameters));
    		}
    		else
    		{
    			out.append(madapTranslateSerial(token, parameters));
    		}
    		out.push_back(')');
    	}
    	out.push_back(')');
    	return out;
    }
    
    std::string madapTranslateSerial(const std::string& in, const std::map<std::string, std::string>& parameters)
    {
    	std::string out;
    
    	std::vector<std::string> tokens = tokenize(in, '-', '(', ')', '\\');
    	for(std::string& token : tokens)
    	{
    		if(token[0] == '(')
    		{
    			if(token.back() != ')')
    				throw parse_errror("unbounded bracket");
    			token.pop_back();
    			token.erase(token.begin());
    			out.append(madapTranslateParalell(token, parameters));
    		}
    		else
    		{
    			auto paramIterator = parameters.find(token);
    			std::string parameterStr;
    			if(paramIterator != parameters.end())
    				parameterStr = paramIterator->second;
    
    			if(token.back() >= 48 && token.back() <= 57)
    				token.pop_back();
    
    			if(!isValidSymbol(token, eisMadapTable, true))
    				throw parse_errror("invalid symbol \"" + token + "\"");
    			out.append(translateElement(token, eisMadapTable, true));
    			out.append(parameterStr);
    		}
    		out.push_back('-');
    	}
    
    	if(out.back() == '-')
    		out.pop_back();
    
    	return out;
    }
    
    std::vector<std::string> madapGetFlatComponants(const std::string& in)
    {
    	std::vector<std::string> out;
    	std::vector<std::string> tokens = tokenize(in, '-');
    	for(const std::string& token : tokens)
    	{
    		std::vector<std::string> subtokens = tokenize(token, ',');
    		for(std::string& subtoken : subtokens)
    		{
    			subtoken = stripWhitespace(subtoken);
    			if(subtoken.empty())
    				continue;
    			if(subtoken[0] == '(' || subtoken[0] == ')')
    				subtoken.erase(subtoken.begin());
    			if(subtoken.back() == '(' || subtoken.back() == ')')
    				subtoken.pop_back();
    			out.push_back(subtoken);
    		}
    	}
    	return out;
    }
    
    std::string madapGenerateEisParamString(const std::vector<double>& paramNums, size_t& currParam, size_t paramCount)
    {
    	if(paramCount == 0)
    		return "";
    	if(currParam+paramCount-1 >= paramNums.size())
    		throw parse_errror("Not enough parameters");
    
    	std::stringstream out;
    	out<<'{'<<std::scientific;
    
    	for(size_t i = 0; i < paramCount; ++i)
    	{
    		out<<paramNums.at(currParam);
    		if(i+1 != paramCount)
    			out<<", ";
    		++currParam;
    	}
    
    	out<<'}';
    	return out.str();
    }
    
    std::map<std::string, std::string> madapParseParameters(const std::string& in, std::string parameters)
    {
    	std::map<std::string, std::string> out;
    
    	if(parameters.empty())
    		return out;
    
    	parameters = stripWhitespace(parameters);
    	if(parameters[0] == '[')
    		parameters.erase(parameters.begin());
    	if(parameters.back() == ']')
    		parameters.pop_back();
    
    	std::vector<double> paramNums;
    	std::vector<std::string> tokens = tokenize(parameters, ',', '(', ')', '\\');
    	for(const std::string& token : tokens)
    	{
    		std::vector<std::string> subtokens = tokenize(token, ',');
    		if(subtokens[0][0] == '(')
    			subtokens[0].erase(subtokens[0].begin());
    		if(subtokens[0].back() == ')')
    			subtokens[0].pop_back();
    		Log(Log::DEBUG)<<__func__<<" Adding param "<<subtokens[0];
    		paramNums.push_back(std::stod(subtokens[0]));
    	}
    
    	if(paramNums.empty())
    		throw parse_errror("invaid parameter string");
    
    	size_t paramCounter = 0;
    	std::vector<std::string> componants = madapGetFlatComponants(in);
    	for(const std::string& componant : componants)
    	{
    		std::string workComponant = componant;
    		auto newEnd = std::remove_if(workComponant.begin(), workComponant.end(), [](char ch){return ch >= 48 && ch <= 57;});
    		workComponant.erase(newEnd, workComponant.end());
    		std::string eisComponant = translateElement(workComponant, eisMadapTable, true);
    		if(eisComponant == "x")
    			throw parse_errror("invalid symbol \"" + componant + "\"");
    		if(!out.insert({componant, ""}).second)
    			throw parse_errror("duplicate symbol \"" + componant + "\"");
    
    		if(eisComponant == "r")
    			out[componant] = madapGenerateEisParamString(paramNums, paramCounter, 1);
    		else if(eisComponant == "c")
    			out[componant] = madapGenerateEisParamString(paramNums, paramCounter, 1);
    		else if(eisComponant == "p")
    			out[componant] = madapGenerateEisParamString(paramNums, paramCounter, 2);
    		else if(eisComponant == "l")
    			out[componant] = madapGenerateEisParamString(paramNums, paramCounter, 1);
    		else if(eisComponant == "w")
    			out[componant] = madapGenerateEisParamString(paramNums, paramCounter, 1);
    	}
    
    	return out;
    }
    
    std::string madapToEis(const std::string& in, const std::string& parameters)
    {
    	if(in.empty())
    		return std::string("");
    	std::string work = madapStrip(in);
    	work = stripWhitespace(work);
    
    	std::map<std::string, std::string> parameterMap = madapParseParameters(work, parameters);
    
    	std::string out = madapTranslateSerial(work, parameterMap);
    
    	eisRemoveUnneededBrackets(out);
    
    	return out;
    }
    
    std::string eisToMadap(std::string in)
    {
    	purgeEisParamBrackets(in);
    	Log(Log::ERROR)<<__func__<<" is not implemented";
    	assert(false);
    	return in;
    }
    
    }