Cleaned 66 files across all eqpalg subdirectories: - Removed commented-out dead code - Removed redundant Chinese inline comments that restate variable/function names - Removed trailing ///< annotations on self-explanatory fields - Removed namespace closing comments - Preserved all file headers, Doxygen documentation, and logic explanations - No code changes — only comment removal
369 lines
9.2 KiB
C++
369 lines
9.2 KiB
C++
#pragma once
|
|
#include <boost/regex.hpp>
|
|
#include <chrono>
|
|
#include <functional>
|
|
#include <limits>
|
|
#include <map>
|
|
#include <memory>
|
|
#include <mix_cc/json.h>
|
|
#include <mix_cc/matheval/matheval.hpp>
|
|
#include <string>
|
|
#include <vector>
|
|
namespace StatExp {
|
|
using std::string;
|
|
using std::vector;
|
|
using namespace std::chrono;
|
|
/**
|
|
* @brief 保持时间仿函数
|
|
* 内部变量:
|
|
* 1.当前保持时间 keep_time ms
|
|
* 2.起始时间点 t1
|
|
*/
|
|
struct KeepT {
|
|
/**
|
|
* @brief KeepT(lt,rt)
|
|
* @param lt double
|
|
* @param rt double
|
|
* @return int 累计的lt==rt的时间 (ms)
|
|
*/
|
|
inline int64_t operator()(double lt, double rt) {
|
|
if (fabs(lt - rt) > std::numeric_limits<double>::epsilon()) {
|
|
t1 = std::chrono::system_clock::now();
|
|
keep_time = 0;
|
|
return 0;
|
|
} else {
|
|
keep_time =
|
|
duration_cast<milliseconds>(std::chrono::system_clock::now() - t1)
|
|
.count();
|
|
}
|
|
return keep_time;
|
|
}
|
|
|
|
private:
|
|
int64_t keep_time = 0;
|
|
std::chrono::system_clock::time_point t1 =
|
|
std::chrono::system_clock::now();
|
|
};
|
|
/**
|
|
* @brief KeepC 保持次数仿函数
|
|
* 内部变量:
|
|
* 保持次数 keep_times
|
|
*/
|
|
struct KeepC {
|
|
/**
|
|
* @brief KeepC(lt,rt)
|
|
* @param lt double
|
|
* @param rt double
|
|
* @return int 累计的lt==rt的次数
|
|
*/
|
|
inline int operator()(double lt, double rt) {
|
|
if (fabs(lt - rt) > std::numeric_limits<double>::epsilon()) {
|
|
keep_times = 0;
|
|
return 0;
|
|
} else {
|
|
keep_times += 1;
|
|
}
|
|
return keep_times;
|
|
}
|
|
|
|
private:
|
|
int keep_times = 0;
|
|
};
|
|
|
|
/**
|
|
* @brief 上升沿次数
|
|
*/
|
|
struct RiseEdge {
|
|
/**
|
|
* @brief RiseEdge 上升沿次数累计仿函数
|
|
* @param data 数据项
|
|
* @param is_reset 是否重置
|
|
* @return int 次数
|
|
*/
|
|
inline int operator()(double data, double is_reset) {
|
|
last_data = now_data;
|
|
now_data = (bool)data;
|
|
if (keep_times == -1) {
|
|
return ++keep_times;
|
|
}
|
|
keep_times += int(!last_data && now_data);
|
|
if (is_reset) {
|
|
keep_times = -1;
|
|
return 0;
|
|
}
|
|
return keep_times;
|
|
}
|
|
|
|
private:
|
|
bool last_data = false;
|
|
bool now_data = false;
|
|
int keep_times = -1;
|
|
};
|
|
|
|
/**
|
|
* @brief 真 检测器
|
|
* 为真的次数
|
|
*/
|
|
struct Detect {
|
|
/**
|
|
* @brief Detect 为真检测的仿函数
|
|
* @param data 数据
|
|
* @param is_reset 是否重置
|
|
* @return int
|
|
*/
|
|
inline int operator()(double data, double is_reset) {
|
|
if (is_reset) {
|
|
keep_times = 0;
|
|
return 0;
|
|
}
|
|
if (data) {
|
|
return ++keep_times;
|
|
}
|
|
return keep_times;
|
|
}
|
|
|
|
private:
|
|
int keep_times = 0;
|
|
};
|
|
|
|
/**
|
|
* @brief
|
|
*/
|
|
struct DelayT {
|
|
using Clock = std::chrono::steady_clock;
|
|
using Milliseconds = std::chrono::milliseconds;
|
|
|
|
int operator()(bool data, bool is_reset) {
|
|
if (is_reset) {
|
|
accumulated_time = 0;
|
|
last_data = false;
|
|
counting = false;
|
|
return 0;
|
|
}
|
|
if (!last_data && data) {
|
|
start_time = Clock::now();
|
|
counting = true;
|
|
} else if (last_data && !data) {
|
|
if (counting) {
|
|
auto current_time = Clock::now();
|
|
accumulated_time +=
|
|
std::chrono::duration_cast<Milliseconds>(current_time - start_time)
|
|
.count();
|
|
counting = false;
|
|
}
|
|
}
|
|
last_data = data;
|
|
if (counting) {
|
|
auto current_time = Clock::now();
|
|
int current_duration =
|
|
std::chrono::duration_cast<Milliseconds>(current_time - start_time)
|
|
.count();
|
|
return accumulated_time + current_duration;
|
|
} else {
|
|
return accumulated_time;
|
|
}
|
|
}
|
|
|
|
private:
|
|
int accumulated_time = 0;
|
|
bool last_data = false;
|
|
bool counting = false;
|
|
Clock::time_point start_time{};
|
|
};
|
|
|
|
using FIDD = std::function<int(double, double)>;
|
|
|
|
enum class FiddType {
|
|
KeepT = 0,
|
|
KeepC,
|
|
RiseEdge,
|
|
Detect
|
|
};
|
|
|
|
const std::map<std::string, FiddType> Fidd2M = {
|
|
{"KeepT", FiddType::KeepT},
|
|
{"KeepC", FiddType::KeepC},
|
|
{"RiseEdge", FiddType::RiseEdge},
|
|
{"Detect", FiddType::Detect}};
|
|
|
|
const std::map<FiddType, std::string> FType2Regex = {
|
|
{FiddType::KeepT, "KeepT\\((\\S+?),(\\S+?)\\)"},
|
|
{FiddType::KeepC, "KeepC\\((\\S+?),(\\S+?)\\)"},
|
|
{FiddType::RiseEdge, "RiseEdge\\((\\S+?),(\\S+?)\\)"},
|
|
{FiddType::Detect, "Detect\\((\\S+?),(\\S+?)\\)"}};
|
|
const std::map<FiddType, std::string> FType2RegexAll = {
|
|
{FiddType::KeepT, "(KeepT\\(\\S+?,\\S+?\\))"},
|
|
{FiddType::KeepC, "(KeepC\\(\\S+?,\\S+?\\))"},
|
|
{FiddType::RiseEdge, "(RiseEdge\\(\\S+?,\\S+?\\))"},
|
|
{FiddType::Detect, "(Detect\\(\\S+?,\\S+?\\))"}};
|
|
|
|
inline FIDD CreateFIDD(FiddType type) {
|
|
switch (type) {
|
|
case FiddType::KeepC:
|
|
return KeepC{};
|
|
break;
|
|
case FiddType::KeepT:
|
|
return KeepT{};
|
|
break;
|
|
case FiddType::RiseEdge:
|
|
return RiseEdge{};
|
|
break;
|
|
case FiddType::Detect:
|
|
return Detect{};
|
|
break;
|
|
default:
|
|
return KeepT{};
|
|
break;
|
|
}
|
|
}
|
|
|
|
inline mix_cc::json search_regs(const string &str, const string ®_str) {
|
|
mix_cc::json res;
|
|
boost::regex reg(reg_str.c_str());
|
|
string::const_iterator start(str.begin()), end(str.end());
|
|
boost::match_results<string::const_iterator> what;
|
|
int i = 0;
|
|
res[i] = reg_str;
|
|
while (regex_search(start, end, what, reg, boost::match_default)) {
|
|
vector<string> v1;
|
|
for (int j = 1; j < what.size(); j++) {
|
|
v1.push_back(what[j]);
|
|
}
|
|
res[i + 1] = v1;
|
|
i++;
|
|
start = what[0].second;
|
|
}
|
|
return res;
|
|
}
|
|
|
|
inline std::string regex_str(const string ®_str, const string ®_t) {
|
|
boost::regex base_regex(("(\\" + reg_t + ")").c_str());
|
|
std::string plv;
|
|
std::stringstream ss;
|
|
ss << R"(\\$1)";
|
|
plv = ss.str();
|
|
auto ret = boost::regex_replace(reg_str, base_regex, plv);
|
|
return ret;
|
|
}
|
|
inline std::string regex_str(const string ®_str) {
|
|
std::string str2 = reg_str;
|
|
std::vector<std::string> rex = {"+", "*", "(", ")", ".", "^", "|"};
|
|
for (auto item : rex) {
|
|
str2 = StatExp::regex_str(str2, item);
|
|
}
|
|
return str2;
|
|
}
|
|
|
|
struct BinaryF {
|
|
BinaryF() {}
|
|
BinaryF(const string &exp_str, std::map<std::string, double> *const mm_vars,
|
|
FiddType type) {
|
|
ftype = type;
|
|
try {
|
|
auto res = search_regs(exp_str, FType2Regex.at(type));
|
|
var1 = std::make_unique<mix_cc::matheval::Expression>(
|
|
res[1][0].get<string>(), mm_vars);
|
|
var2 = std::make_unique<mix_cc::matheval::Expression>(
|
|
res[1][1].get<string>(), mm_vars);
|
|
Fun = CreateFIDD(type);
|
|
} catch (const std::exception &e) {
|
|
}
|
|
}
|
|
|
|
FIDD Fun;
|
|
FiddType ftype;
|
|
std::unique_ptr<mix_cc::matheval::Expression> var1;
|
|
std::unique_ptr<mix_cc::matheval::Expression> var2;
|
|
inline double operator()() {
|
|
if (var1 != nullptr && var2 != nullptr) {
|
|
switch (ftype) {
|
|
case FiddType::RiseEdge:
|
|
case FiddType::Detect:
|
|
return (double)Fun(
|
|
var2->evaluate() ? var1->evaluate() : !var1->evaluate(), 0);
|
|
break;
|
|
|
|
default:
|
|
return (double)Fun(var1->evaluate(), var2->evaluate());
|
|
break;
|
|
}
|
|
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
};
|
|
|
|
class FunVars {
|
|
public:
|
|
FunVars() {}
|
|
~FunVars() {}
|
|
inline std::pair<bool, std::string>
|
|
add_exp_str(const std::string &exp_str,
|
|
std::map<std::string, double> *const mm_vars) {
|
|
std::string out_str = exp_str;
|
|
try {
|
|
for (auto item : FType2RegexAll) {
|
|
auto res = search_regs(exp_str, item.second);
|
|
if (res.size() > 1) {
|
|
for (int i = 1; i < res.size(); i++) {
|
|
std::string expi = res[i][0].get<string>();
|
|
if (exp2fvar.find(expi) == exp2fvar.end()) {
|
|
exp2binayF[expi] = BinaryF(expi, mm_vars, item.first);
|
|
std::string f_var = pre_var + std::to_string(index++);
|
|
exp2fvar[expi] = f_var;
|
|
exp2ftype[expi] = item.first;
|
|
mm_vars->operator[](f_var) = 0;
|
|
out_str = boost::regex_replace(
|
|
out_str, boost::regex(regex_str(expi).c_str()),
|
|
f_var.c_str());
|
|
} else {
|
|
std::string f_var = exp2fvar[expi];
|
|
out_str = boost::regex_replace(
|
|
out_str, boost::regex(regex_str(expi).c_str()),
|
|
f_var.c_str());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return std::make_pair(true, out_str);
|
|
} catch (const std::exception &e) {
|
|
return std::make_pair(false, e.what());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief 刷新 fun[index]变量
|
|
* @param is_reset 是否重置 bool
|
|
* @param mm_vars std::map<std::string, double>* const
|
|
* @return true 刷新成功
|
|
* @return false 刷新失败
|
|
*/
|
|
inline bool refresh_fun_vars(bool is_reset,
|
|
std::map<std::string, double> *const mm_vars) {
|
|
try {
|
|
for (auto fi : exp2fvar) {
|
|
if (is_reset) {
|
|
mm_vars->operator[](fi.second) =
|
|
(double)exp2binayF[fi.first].Fun(0.0, 1.0);
|
|
} else {
|
|
mm_vars->operator[](fi.second) = exp2binayF[fi.first]();
|
|
}
|
|
}
|
|
|
|
return true;
|
|
} catch (const std::exception &e) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
inline bool empty() { return exp2fvar.empty(); }
|
|
|
|
private:
|
|
const std::string pre_var = "fun";
|
|
int index = 0;
|
|
std::map<std::string, BinaryF> exp2binayF;
|
|
std::map<std::string, std::string> exp2fvar;
|
|
std::map<std::string, FiddType> exp2ftype;
|
|
};
|
|
} |