diff --git a/CMakeLists.txt b/CMakeLists.txt index 83d6efe68b86491f205aff5173bf7c74410cd02c..1b6e12fbab6213f0133e489c10aab61be9d6c7fd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.20) project(ehigeneratorsa) -set(SRC_FILES main.cpp cap.cpp resistor.cpp model.cpp) +set(SRC_FILES main.cpp cap.cpp resistor.cpp model.cpp tokenize.cpp) find_package(PkgConfig REQUIRED) pkg_check_modules(SPICE REQUIRED ngspice) @@ -10,6 +10,6 @@ pkg_check_modules(SPICE REQUIRED ngspice) add_executable(${PROJECT_NAME} ${SRC_FILES}) target_link_libraries(${PROJECT_NAME} ${SPICE_LIBRARIES}) target_include_directories(${PROJECT_NAME} PUBLIC ${SPICE_CFLAGS} .) -set_target_properties(${PROJECT_NAME} PROPERTIES COMPILE_FLAGS "-std=c++20 -Wall -O3 -march=native" LINK_FLAGS "-flto") +set_target_properties(${PROJECT_NAME} PROPERTIES COMPILE_FLAGS "-std=c++20 -Wall -O0 -march=native -g" LINK_FLAGS "-flto") install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION bin) diff --git a/cap.cpp b/cap.cpp index b5b35b91cfd27f5db18b8afc4bf0cb222a426833..447d5641fcb25ba4efbd34172dfda5ca135f82e5 100644 --- a/cap.cpp +++ b/cap.cpp @@ -1,11 +1,53 @@ #include "cap.h" +#include "tokenize.h" +#include <cstdlib> +#include <math.h> Cap::Cap(double c): _C(c) { } +Cap::Cap(std::string paramStr) +{ + std::vector<std::string> tokens = tokenize(paramStr, ','); + if(tokens.empty()) + { + std::cout<<"Warning: to few parameters in "<<__func__<<" parameter string: "<<paramStr<<'\n'; + _C = 1e-6; + return; + } + else + { + try + { + _C = std::stod(tokens[0]); + } + catch(const std::invalid_argument& ia) + { + std::cout<<"Warning: cant parse parameter in "<<__func__<<" parameter: "<<tokens[0]<<'\n'; + _C = 1e3; + } + } +} + std::complex<double> Cap::execute(double omega) { return std::complex<double>(0, 0.0-(1.0/(_C*omega))); } + +std::vector<double> Cap::getParam() +{ + return std::vector<double>({_C}); +} + +void Cap::setParam(const std::vector<double>& param) +{ + if(param.empty()) + { + std::cout<<"Warning: invalid parameter list sent to "<<__func__<<'\n'; + return; + } + + _C = param[0]; +} diff --git a/cap.h b/cap.h index accff8773824b3cd632c7584c06687ec5f7a1ff5..95c7bb2e6a1797df9525be61eed1817a2cb94326 100644 --- a/cap.h +++ b/cap.h @@ -1,5 +1,7 @@ #pragma once #include <complex> +#include <string> +#include <vector> #include "componant.h" class Cap: public Componant @@ -7,6 +9,9 @@ class Cap: public Componant private: double _C; public: - Cap(double c); + Cap(std::string paramStr); + Cap(double c = 1e-6); virtual std::complex<double> execute(double omega) override; + virtual std::vector<double> getParam() override; + virtual void setParam(const std::vector<double>& param) override; }; diff --git a/componant.h b/componant.h index e026c9a5002bbb24e6998cbaa7b52c2bd376ce00..c5f3a53b929643d8dea456d3cf10ee7408a6a1ca 100644 --- a/componant.h +++ b/componant.h @@ -1,6 +1,7 @@ #pragma once #include <complex> #include <iostream> +#include <vector> class Componant { @@ -10,4 +11,10 @@ class Componant std::cout<<"warning incompleat model\n"; return std::complex<double> (1,0); } + + virtual std::vector<double> getParam() + { + return std::vector<double>(); + }; + virtual void setParam(const std::vector<double>& param){}; }; diff --git a/main.cpp b/main.cpp index cdd51fafa175cbdc4ae48d3078ba0a930feb8eae..7f83be72605ad92c890f6242f0887e36a0b301c9 100644 --- a/main.cpp +++ b/main.cpp @@ -11,12 +11,11 @@ double omegafn(size_t i) int main(int argc, char** argv) { - std::vector<double> params = {1.0e3, 1.0e-6, 1.0e3, 1.0e-6}; - std::string modelStr("r-(c-r)r-(cr-(rc-r))"); + std::string modelStr("r{1e3}-(c{1e-6}r{1e3})"); std::vector<Model::DataPoint> results; - Model model(modelStr, params); + Model model(modelStr); auto start = std::chrono::high_resolution_clock::now(); for(size_t i = 0; i < 50; ++i) results.push_back(model.execute(omegafn(i))); diff --git a/model.cpp b/model.cpp index 017db9c155799b0f4ae66fc714f0ced0c5c42948..375ce2741e37366d16f894e18b911d99c93b2145 100644 --- a/model.cpp +++ b/model.cpp @@ -32,11 +32,11 @@ std::complex<double> Model::Serial::execute(double omega) return accum; } -size_t Model::opposingBraket(const std::string& str, size_t index) +size_t Model::opposingBraket(const std::string& str, size_t index, char bracketChar) { for(size_t i = index; i < str.size(); ++i) { - if(str[i] == ')') + if(str[i] == bracketChar) return i; } return std::string::npos; @@ -62,19 +62,19 @@ size_t Model::deepestBraket(const std::string& str) return deepestPos; } -Componant *Model::processBrackets(std::string& str, size_t& bracketCounter, const std::vector<double>& param) +Componant *Model::processBrackets(std::string& str, size_t& bracketCounter) { size_t bracketStart = deepestBraket(str); std::cout<<str<<" bracket start "<<(bracketStart == std::string::npos ? std::string("npos") : std::to_string(bracketStart))<<'\n'; if(bracketStart == std::string::npos) { - Componant* componant = processBracket(str, param); + Componant* componant = processBracket(str); if(!componant) { - std::cout<<"Warning: can not create componant for "<<str; + std::cout<<"Warning: can not create componant type B for "<<str<<'\n'; } - return processBracket(str, param); + return componant; } size_t bracketEnd = opposingBraket(str, bracketStart); @@ -84,58 +84,83 @@ Componant *Model::processBrackets(std::string& str, size_t& bracketCounter, cons return nullptr; } - std::string bracket = str.substr(bracketStart+1, bracketEnd-1); + std::string bracket = str.substr(bracketStart+1, bracketEnd-1-bracketStart); - Componant* componant = processBracket(bracket, param); - _bracketComponants.push_back(processBracket(bracket, param)); + Componant* componant = processBracket(bracket); if(!componant) { - std::cout<<"Warning: can not create componant for "<<bracket; + std::cout<<"Warning: can not create componant type A for "<<bracket<<'\n'; } + _bracketComponants.push_back(componant); str.erase(str.begin()+bracketStart, str.begin()+bracketEnd+1); str.insert(str.begin()+bracketStart, bracketCounter+48); ++bracketCounter; - return processBrackets(str, bracketCounter, param); + return processBrackets(str, bracketCounter); } -Componant *Model::processBracket(std::string& str, const std::vector<double>& param) +std::string Model::getParamStr(const std::string& str, size_t index) { - std::vector<std::string> tokens = tokenize(str, '-'); + if(str.size()-index < 3 || str[index+1] != '{') + { + std::cout<<"Warning: missing parameter for "<<str[index]<<'\n'; + return 0; + } - std::vector<Componant*> nodes; + size_t end = opposingBraket(str, index, '}'); + std::string parameterStr = str.substr(index+2, end-index-2); + std::cout<<"param for "<<str[index]<<' '<<parameterStr<<'\n'; + return parameterStr; +} + +Componant *Model::processBracket(std::string& str) +{ + std::cout<<__func__<<'('<<str<<")\n"; + std::vector<std::string> tokens = tokenize(str, '-', '{', '}'); - size_t paramCounter = 0; + std::vector<Componant*> nodes; for(const std::string& nodeStr : tokens) { + std::cout<<__func__<<" full node str: "<<nodeStr<<'\n'; std::vector<Componant*> componants; - for(char c : nodeStr) + for(size_t i = 0; i < nodeStr.size(); ++i) { - if(paramCounter >= param.size()) - break; - switch(c) + std::cout<<__func__<<" arg: "<<nodeStr[i]<<'\n'; + switch(nodeStr[i]) { case 'c': case 'C': - componants.push_back(new Cap(1e-6)); + componants.push_back(new Cap(getParamStr(nodeStr, i))); + i = opposingBraket(nodeStr, i, '}'); break; case 'r': case 'R': - componants.push_back(new Resistor(1e3)); + componants.push_back(new Resistor(getParamStr(nodeStr, i))); + i = opposingBraket(nodeStr, i, '}'); + break; + case '{': + i = opposingBraket(nodeStr, i, '}'); + case '}': + std::cout<<"Warning: stray "<<nodeStr[i]<<" in model string\n"; break; case '0' ... '9': { - size_t i = c-48; - if(_bracketComponants.size() > i) - componants.push_back(_bracketComponants[i]); + size_t j = nodeStr[i]-48; + if(_bracketComponants.size() > j) + componants.push_back(_bracketComponants[j]); break; } default: break; } } - nodes.push_back(new Paralell(componants)); + if(componants.size() > 1) + nodes.push_back(new Paralell(componants)); + else if(componants.size() == 1) + nodes.push_back(componants[0]); + else + std::cout<<"Warning: empty node for "<<nodeStr<<'\n'; } if(nodes.size() > 1) @@ -146,11 +171,11 @@ Componant *Model::processBracket(std::string& str, const std::vector<double>& pa return nullptr; } -Model::Model(const std::string& str, const std::vector<double>& param) +Model::Model(const std::string& str): _modelStr(str) { size_t bracketCounter = 0; std::string strCpy(str); - _model = processBrackets(strCpy, bracketCounter, param); + _model = processBrackets(strCpy, bracketCounter); } Model::DataPoint Model::execute(double omega) @@ -163,6 +188,8 @@ Model::DataPoint Model::execute(double omega) return dataPoint; } else + { std::cout<<"Warning: model not ready\n"; + } return DataPoint({std::complex<double>(0,0), 0}); } diff --git a/model.h b/model.h index 4d6e439ce70451a769593bcccdd921cb06c6c55c..bee488ed2c6a227542ea518f0d7052b86cdc7931 100644 --- a/model.h +++ b/model.h @@ -33,16 +33,21 @@ private: virtual std::complex<double> execute(double omaga) override; }; - size_t opposingBraket(const std::string& str, size_t index); + size_t opposingBraket(const std::string& str, size_t index, char bracketChar = ')'); size_t deepestBraket(const std::string& str); - Componant *processBrackets(std::string& str, size_t& bracketCounter, const std::vector<double>& param); - Componant *processBracket(std::string& str, const std::vector<double>& param); + Componant *processBrackets(std::string& str, size_t& bracketCounter); + Componant *processBracket(std::string& str); + std::string getParamStr(const std::string& str, size_t index); private: Componant *_model = nullptr; std::vector<Componant*> _bracketComponants; + std::string _modelStr; + std::vector<Componant*> _flatComponants; public: - Model(const std::string& str, const std::vector<double>& params); + Model(const std::string& str); DataPoint execute(double omaga); + std::string getModelStr(); + std::vector<Componant*> getFlatComponants(); }; diff --git a/resistor.cpp b/resistor.cpp index 6db453f1ba5b04ff746e657f90465ca586e14110..d9b33b32a3235ff3b2f21487b42020b0097bed39 100644 --- a/resistor.cpp +++ b/resistor.cpp @@ -1,10 +1,52 @@ #include "resistor.h" +#include "tokenize.h" +#include <vector> +#include <math.h> Resistor::Resistor(double r): _R(r) {} +Resistor::Resistor(std::string paramStr) +{ + std::vector<std::string> tokens = tokenize(paramStr, ','); + if(tokens.empty()) + { + std::cout<<"Warning: to few parameters in "<<__func__<<" parameter string: "<<paramStr<<'\n'; + _R = 1e3; + return; + } + else + { + try + { + _R = std::stod(tokens[0]); + } + catch(const std::invalid_argument& ia) + { + std::cout<<"Warning: cant parse parameter in "<<__func__<<" parameter: "<<tokens[0]<<'\n'; + _R = 1e3; + } + } +} + std::complex<double> Resistor::execute(double omega) { (void)omega; return std::complex<double>(_R, 0); } + +std::vector<double> Resistor::getParam() +{ + return std::vector<double>({_R}); +} + +void Resistor::setParam(const std::vector<double>& param) +{ + if(param.empty()) + { + std::cout<<"Warning: invalid parameter list sent to "<<__func__<<'\n'; + return; + } + + _R = param[0]; +} diff --git a/resistor.h b/resistor.h index dd9a500f1406c0306bcea8729e95dcf6097bd4c8..0f9d2cd2c73e723ddd5274264d3090127fb991fd 100644 --- a/resistor.h +++ b/resistor.h @@ -1,5 +1,6 @@ #pragma once #include "componant.h" +#include <string> class Resistor: public Componant { @@ -8,5 +9,8 @@ private: public: Resistor(double r); + Resistor(std::string paramStr); virtual std::complex<double> execute(double omega) override; + virtual std::vector<double> getParam() override; + virtual void setParam(const std::vector<double>& param) override; }; diff --git a/tokenize.cpp b/tokenize.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f09da75ba3233d51c0501535cae2281c8d3f9c13 --- /dev/null +++ b/tokenize.cpp @@ -0,0 +1,30 @@ +#include "tokenize.h" + +std::vector<std::string> tokenize(const std::string& str, const char delim, const char ignBracketStart, const char ignBracketEnd) +{ + std::stringstream ss(str); + std::vector<std::string> tokens; + + std::string token; + size_t bracketCounter = 0; + for(char ch : str) + { + if(ch == delim && bracketCounter == 0) + { + tokens.push_back(token); + token.clear(); + } + else + { + token.push_back(ch); + } + + if(ignBracketStart == ch) + ++bracketCounter; + else if(ignBracketEnd == ch) + --bracketCounter; + } + if(bracketCounter == 0) + tokens.push_back(token); + return tokens; +} diff --git a/tokenize.h b/tokenize.h index b0af8346b945a164fa384d0771a4d6117d9c07d1..5f36a46bfc73ef851a72abb638c739f8c27839cf 100644 --- a/tokenize.h +++ b/tokenize.h @@ -1,14 +1,6 @@ +#pragma once #include <string> #include <vector> #include <sstream> -std::vector<std::string> tokenize(const std::string& str, const char delim = ' ') -{ - std::stringstream ss(str); - std::vector<std::string> tokens; - - std::string token; - while(getline(ss, token, delim)) - tokens.push_back(token); - return tokens; -} +std::vector<std::string> tokenize(const std::string& str, const char delim = ' ', const char ignBracketStart = '\0', const char ignBracketEnd = '\0');