完整的GCC C++代码实现,整合了MATIO库、Eigen矩阵计算、多线程处理及日志系统,并支持MATLAB风格的矩阵运算和基本数学函数。
#include <iostream>
#include <fstream>
#include <vector>
#include <map>
#include <regex>
#include <thread>
#include <future>
#include <queue>
#include <mutex>
#include <condition_variable>
#include <filesystem>
#include <sstream>
#include <cctype>
#include <stdexcept>
#include <chrono>
#include <iomanip>
#include <backward.hpp>
#include <matio.h>
#include <Eigen/Dense>
#include <cmath>
#include <limits>
#include <spdlog/spdlog.h>
#include <spdlog/sinks/stdout_color_sinks.h>
#include <spdlog/sinks/basic_file_sink.h>
namespace fs = std::filesystem;
namespace backward { backward::SignalHandling sh; }
using Eigen::MatrixXd;
using Eigen::VectorXd;
using EigenMap = std::map<std::string, MatrixXd>;
// 全局日志器初始化
std::shared_ptr<spdlog::logger> init_logger() {
auto console_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
console_sink->set_pattern("%^[%Y-%m-%d %H:%M:%S.%e] [%l]%$ %v");
auto file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>("matrix_calc.log", true);
file_sink->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%l] %v");
std::vector<spdlog::sink_ptr> sinks{console_sink, file_sink};
auto logger = std::make_shared<spdlog::logger>("mat_exec", sinks.begin(), sinks.end());
logger->set_level(spdlog::level::debug);
spdlog::register_logger(logger);
return logger;
}
auto logger = init_logger();
// 异常处理宏定义
#define THROW_EXCEPTION(msg) \
do { \
std::stringstream ss; \
ss << msg << " [文件: " << __FILE__ << " 行: " << __LINE__ << "]"; \
logger->error(ss.str()); \
throw std::runtime_error(ss.str()); \
} while(0)
// 矩阵运算工具类
namespace MatrixOps {
// 基本矩阵运算
MatrixXd add(const MatrixXd& a, const MatrixXd& b) {
if (a.rows() != b.rows() || a.cols() != b.cols())
THROW_EXCEPTION("矩阵加法维度不匹配");
return a + b;
}
MatrixXd subtract(const MatrixXd& a, const MatrixXd& b) {
if (a.rows() != b.rows() || a.cols() != b.cols())
THROW_EXCEPTION("矩阵减法维度不匹配");
return a - b;
}
MatrixXd multiply(const MatrixXd& a, const MatrixXd& b) {
if (a.cols() != b.rows())
THROW_EXCEPTION("矩阵乘法维度不匹配");
return a * b;
}
MatrixXd elementwise_multiply(const MatrixXd& a, const MatrixXd& b) {
if (a.rows() != b.rows() || a.cols() != b.cols())
THROW_EXCEPTION("矩阵逐元素乘法维度不匹配");
return a.cwiseProduct(b);
}
MatrixXd divide(const MatrixXd& a, const MatrixXd& b) {
if (a.rows() != b.rows() || a.cols() != b.cols())
THROW_EXCEPTION("矩阵逐元素除法维度不匹配");
return a.cwiseQuotient(b);
}
MatrixXd inv(const MatrixXd& m) {
if (m.rows() != m.cols()) THROW_EXCEPTION("求逆要求方阵");
return m.inverse();
}
MatrixXd pinv(const MatrixXd& m, double tol = 1e-6) {
Eigen::JacobiSVD<MatrixXd> svd(m, Eigen::ComputeThinU | Eigen::ComputeThinV);
VectorXd sv = svd.singularValues();
MatrixXd S_inv = MatrixXd::Zero(m.cols(), m.rows());
for (int i = 0; i < sv.size(); ++i) {
if (sv(i) > tol) S_inv(i, i) = 1.0 / sv(i);
}
return svd.matrixV() * S_inv * svd.matrixU().transpose();
}
MatrixXd eig(const MatrixXd& m) {
if (m.rows() != m.cols()) THROW_EXCEPTION("特征值要求方阵");
Eigen::EigenSolver<MatrixXd> solver(m);
return solver.eigenvalues().real();
}
MatrixXd svd(const MatrixXd& m) {
Eigen::JacobiSVD<MatrixXd> svd(m, Eigen::ComputeThinU | Eigen::ComputeThinV);
return svd.singularValues();
}
MatrixXd chol(const MatrixXd& m) {
if (m.rows() != m.cols()) THROW_EXCEPTION("Cholesky分解要求方阵");
Eigen::LLT<MatrixXd> llt(m);
if (llt.info() == Eigen::NumericalIssue)
THROW_EXCEPTION("矩阵非正定,无法Cholesky分解");
return llt.matrixL();
}
// 基本数学函数
MatrixXd sin(const MatrixXd& m) { return m.array().sin().matrix(); }
MatrixXd cos(const MatrixXd& m) { return m.array().cos().matrix(); }
MatrixXd tan(const MatrixXd& m) { return m.array().tan().matrix(); }
MatrixXd asin(const MatrixXd& m) { return m.array().asin().matrix(); }
MatrixXd acos(const MatrixXd& m) { return m.array().acos().matrix(); }
MatrixXd atan(const MatrixXd& m) { return m.array().atan().matrix(); }
MatrixXd sinh(const MatrixXd& m) { return m.array().sinh().matrix(); }
MatrixXd cosh(const MatrixXd& m) { return m.array().cosh().matrix(); }
MatrixXd tanh(const MatrixXd& m) { return m.array().tanh().matrix(); }
MatrixXd asinh(const MatrixXd& m) { return m.array().asinh().matrix(); }
MatrixXd acosh(const MatrixXd& m) { return m.array().acosh().matrix(); }
MatrixXd atanh(const MatrixXd& m) { return m.array().atanh().matrix(); }
MatrixXd exp(const MatrixXd& m) { return m.array().exp().matrix(); }
MatrixXd log(const MatrixXd& m) { return m.array().log().matrix(); }
MatrixXd log10(const MatrixXd& m) { return m.array().log10().matrix(); }
MatrixXd log2(const MatrixXd& m) {
return m.array().log() / std::log(2);
}
MatrixXd sqrt(const MatrixXd& m) { return m.array().sqrt().matrix(); }
MatrixXd abs(const MatrixXd& m) { return m.array().abs().matrix(); }
MatrixXd sign(const MatrixXd& m) {
return m.array().unaryExpr([](double x) {
return (x > 0) ? 1 : ((x < 0) ? -1 : 0);
}).matrix();
}
MatrixXd round(const MatrixXd& m) { return m.array().round().matrix(); }
MatrixXd floor(const MatrixXd& m) { return m.array().floor().matrix(); }
MatrixXd ceil(const MatrixXd& m) { return m.array().ceil().matrix(); }
MatrixXd fix(const MatrixXd& m) {
return m.array().unaryExpr([](double x) {
return (x > 0) ? std::floor(x) : std::ceil(x);
}).matrix();
}
MatrixXd pow(const MatrixXd& m, double exponent) {
return m.array().pow(exponent).matrix();
}
MatrixXd atan2(const MatrixXd& y, const MatrixXd& x) {
if (y.rows() != x.rows() || y.cols() != x.cols()) {
THROW_EXCEPTION("atan2: 矩阵维度不匹配");
}
MatrixXd result(y.rows(), y.cols());
for (int i = 0; i < y.size(); ++i) {
result(i) = std::atan2(y(i), x(i));
}
return result;
}
MatrixXd mod(const MatrixXd& x, const MatrixXd& y) {
if (x.rows() != y.rows() || x.cols() != y.cols()) {
THROW_EXCEPTION("mod: 矩阵维度不匹配");
}
MatrixXd result(x.rows(), x.cols());
for (int i = 0; i < x.size(); ++i) {
result(i) = std::fmod(x(i), y(i));
}
return result;
}
MatrixXd rem(const MatrixXd& x, const MatrixXd& y) {
if (x.rows() != y.rows() || x.cols() != y.cols()) {
THROW_EXCEPTION("rem: 矩阵维度不匹配");
}
MatrixXd result(x.rows(), x.cols());
for (int i = 0; i < x.size(); ++i) {
double a = x(i);
double b = y(i);
result(i) = (b == 0) ? std::numeric_limits<double>::quiet_NaN() : a - b * std::floor(a / b);
}
return result;
}
MatrixXd max(const MatrixXd& a, const MatrixXd& b) {
if (a.rows() != b.rows() || a.cols() != b.cols()) {
THROW_EXCEPTION("max: 矩阵维度不匹配");
}
MatrixXd result(a.rows(), a.cols());
for (int i = 0; i < a.size(); ++i) {
result(i) = std::max(a(i), b(i));
}
return result;
}
MatrixXd min(const MatrixXd& a, const MatrixXd& b) {
if (a.rows() != b.rows() || a.cols() != b.cols()) {
THROW_EXCEPTION("min: 矩阵维度不匹配");
}
MatrixXd result(a.rows(), a.cols());
for (int i = 0; i < a.size(); ++i) {
result(i) = std::min(a(i), b(i));
}
return result;
}
MatrixXd sum(const MatrixXd& m) {
return MatrixXd::Constant(1, 1, m.sum());
}
MatrixXd mean(const MatrixXd& m) {
return MatrixXd::Constant(1, 1, m.mean());
}
MatrixXd prod(const MatrixXd& m) {
double product = 1.0;
for (int i = 0; i < m.size(); ++i) {
product *= m(i);
}
return MatrixXd::Constant(1, 1, product);
}
MatrixXd max_val(const MatrixXd& m) {
return MatrixXd::Constant(1, 1, m.maxCoeff());
}
MatrixXd min_val(const MatrixXd& m) {
return MatrixXd::Constant(1, 1, m.minCoeff());
}
}
// MAT文件处理类
class MatFileHandler {
public:
static EigenMap load(const std::string& path) {
if (!fs::exists(path)) THROW_EXCEPTION("文件不存在: " + path);
mat_t* mat = Mat_Open(path.c_str(), MAT_ACC_RDONLY);
if (!mat) THROW_EXCEPTION("无法打开MAT文件: " + path);
EigenMap variables;
matvar_t* var;
while ((var = Mat_VarReadNext(mat)) != nullptr) {
if (var->data_type == MAT_T_DOUBLE && var->rank == 2) {
MatrixXd matrix(var->dims[0], var->dims[1]);
memcpy(matrix.data(), var->data, var->nbytes);
variables[var->name] = matrix;
logger->debug("加载变量: {} [{}x{}]", var->name,
var->dims[0], var->dims[1]);
}
Mat_VarFree(var);
}
Mat_Close(mat);
return variables;
}
static void save(const std::string& path, const EigenMap& variables) {
mat_t* mat = Mat_CreateVer(path.c_str(), nullptr, MAT_FT_MAT5);
if (!mat) THROW_EXCEPTION("无法创建MAT文件: " + path);
for (const auto& [name, matrix] : variables) {
size_t dims[2] = {
static_cast<size_t>(matrix.rows()),
static_cast<size_t>(matrix.cols())
};
matvar_t* var = Mat_VarCreate(
name.c_str(), MAT_C_DOUBLE, MAT_T_DOUBLE, 2, dims,
(void*)matrix.data(), MAT_F_DONT_COPY_DATA
);
if (!var || Mat_VarWrite(mat, var, MAT_COMPRESSION_NONE) != 0) {
Mat_VarFree(var);
Mat_Close(mat);
THROW_EXCEPTION("写入变量失败: " + name);
}
Mat_VarFree(var);
logger->debug("保存变量: {} [{}x{}]", name, dims[0], dims[1]);
}
Mat_Close(mat);
}
};
// 其他格式输出类
class FormatExporter {
public:
static void save_csv(const std::string& path, const EigenMap& variables) {
std::ofstream file(path);
if (!file.is_open()) THROW_EXCEPTION("无法创建CSV文件: " + path);
for (const auto& [name, matrix] : variables) {
file << "=== " << name << " (" << matrix.rows() << "x" << matrix.cols() << ") ===" << std::endl;
for (int i = 0; i < matrix.rows(); ++i) {
for (int j = 0; j < matrix.cols(); ++j) {
file << matrix(i, j);
if (j < matrix.cols() - 1) file << ",";
}
file << std::endl;
}
file << std::endl;
}
}
static void save_excel(const std::string& path, const EigenMap& variables) {
logger->warn("Excel格式暂未实现: {}", path);
}
static void save_parquet(const std::string& path, const EigenMap& variables) {
logger->warn("Parquet格式暂未实现: {}", path);
}
};
// M代码解析器
class MCodeParser {
public:
explicit MCodeParser(const std::string& script_path) {
parse_script(script_path);
}
void execute(EigenMap& variables) const {
for (size_t i = 0; i < instructions.size(); ++i) {
try {
const auto& [lhs, rhs] = instructions[i];
MatrixXd result = evaluate_expression(rhs, variables);
variables[lhs] = result;
logger->info("执行成功: {} = [{}x{}矩阵] (行 {})",
lhs, result.rows(), result.cols(), i + 1);
} catch (const std::exception& e) {
logger->error("执行失败 (行 {}): {}\n{}",
i + 1, instructions[i].first + " = " + instructions[i].second, e.what());
}
}
}
private:
std::vector<std::pair<std::string, std::string>> instructions;
void parse_script(const std::string& path) {
std::ifstream file(path);
if (!file.is_open()) THROW_EXCEPTION("无法打开M文件: " + path);
std::string line;
int line_num = 0;
while (std::getline(file, line)) {
line_num++;
// 移除注释和空白
size_t comment_pos = line.find('%');
if (comment_pos != std::string::npos) {
line = line.substr(0, comment_pos);
}
line = trim(line);
if (line.empty()) continue;
// 解析赋值语句
size_t eq_pos = line.find('=');
if (eq_pos == std::string::npos) {
logger->warn("忽略无效语句 (行 {}): {}", line_num, line);
continue;
}
std::string lhs = trim(line.substr(0, eq_pos));
std::string rhs = trim(line.substr(eq_pos + 1));
if (lhs.empty() || rhs.empty()) {
logger->warn("忽略不完整赋值 (行 {}): {}", line_num, line);
continue;
}
instructions.emplace_back(lhs, rhs);
}
logger->info("解析完成: {} 条有效指令", instructions.size());
}
static std::string trim(const std::string& s) {
auto start = std::find_if_not(s.begin(), s.end(), ::isspace);
auto end = std::find_if_not(s.rbegin(), s.rend(), ::isspace).base();
return (start < end) ? std::string(start, end) : "";
}
MatrixXd evaluate_expression(const std::string& expr, const EigenMap& vars) const {
// 处理函数调用
static std::regex func_re(R"((\w+)\s*\(\s*([^)]*)\s*\))");
std::smatch match;
if (std::regex_match(expr, match, func_re)) {
std::string func = match[1];
std::vector<std::string> args = split_arguments(match[2]);
return call_function(func, args, vars);
}
// 处理二元运算
static std::vector<std::pair<std::regex, std::function<MatrixXd(const MatrixXd&, const MatrixXd&)>>> ops = {
{std::regex(R"(^\s*(\w+)\s*\+\s*(\w+)\s*$)"), MatrixOps::add},
{std::regex(R"(^\s*(\w+)\s*\-\s*(\w+)\s*$)"), MatrixOps::subtract},
{std::regex(R"(^\s*(\w+)\s*\*\s*(\w+)\s*$)"), MatrixOps::multiply},
{std::regex(R"(^\s*(\w+)\s*\/\s*(\w+)\s*$)"), MatrixOps::divide},
{std::regex(R"(^\s*(\w+)\s*\*\*\s*(\w+)\s*$)"), [](const MatrixXd& a, const MatrixXd& b) { return MatrixOps::pow(a, b(0,0)); }},
};
for (const auto& [op_re, op_func] : ops) {
if (std::regex_match(expr, match, op_re)) {
std::string a_name = match[1];
std::string b_name = match[2];
if (!vars.count(a_name)) THROW_EXCEPTION("未定义变量: " + a_name);
if (!vars.count(b_name)) THROW_EXCEPTION("未定义变量: " + b_name);
return op_func(vars.at(a_name), vars.at(b_name));
}
}
// 处理一元运算
static std::vector<std::pair<std::regex, std::function<MatrixXd(const MatrixXd&)>>> unary_ops = {
{std::regex(R"(^\s*sin\s*\(\s*(\w+)\s*\)$)"), [](const MatrixXd& m) { return MatrixOps::sin(m); }},
{std::regex(R"(^\s*cos\s*\(\s*(\w+)\s*\)$)"), [](const MatrixXd& m) { return MatrixOps::cos(m); }},
{std::regex(R"(^\s*tan\s*\(\s*(\w+)\s*\)$)"), [](const MatrixXd& m) { return MatrixOps::tan(m); }},
{std::regex(R"(^\s*exp\s*\(\s*(\w+)\s*\)$)"), [](const MatrixXd& m) { return MatrixOps::exp(m); }},
{std::regex(R"(^\s*log\s*\(\s*(\w+)\s*\)$)"), [](const MatrixXd& m) { return MatrixOps::log(m); }},
{std::regex(R"(^\s*sqrt\s*\(\s*(\w+)\s*\)$)"), [](const MatrixXd& m) { return MatrixOps::sqrt(m); }},
{std::regex(R"(^\s*abs\s*\(\s*(\w+)\s*\)$)"), [](const MatrixXd& m) { return MatrixOps::abs(m); }},
};
for (const auto& [op_re, op_func] : unary_ops) {
if (std::regex_match(expr, match, op_re)) {
std::string var_name = match[1];
if (!vars.count(var_name)) THROW_EXCEPTION("未定义变量: " + var_name);
return op_func(vars.at(var_name));
}
}
// 处理变量引用
if (vars.count(expr)) {
return vars.at(expr);
}
THROW_EXCEPTION("无法解析表达式: " + expr);
}
static std::vector<std::string> split_arguments(const std::string& args_str) {
std::vector<std::string> args;
std::istringstream iss(args_str);
std::string arg;
while (std::getline(iss, arg, ',')) {
arg = trim(arg);
if (!arg.empty()) args.push_back(arg);
}
return args;
}
MatrixXd call_function(const std::string& name, const std::vector<std::string>& args, const EigenMap& vars) const {
if (args.empty()) THROW_EXCEPTION("函数调用缺少参数: " + name);
// 检查所有参数是否存在
for (const auto& arg : args) {
if (!vars.count(arg)) THROW_EXCEPTION("函数参数未定义: " + arg);
}
// 调用对应矩阵函数
if (name == "inv" && args.size() == 1) return MatrixOps::inv(vars.at(args[0]));
if (name == "pinv" && args.size() == 1) return MatrixOps::pinv(vars.at(args[0]));
if (name == "eig" && args.size() == 1) return MatrixOps::eig(vars.at(args[0]));
if (name == "svd" && args.size() == 1) return MatrixOps::svd(vars.at(args[0]));
if (name == "chol" && args.size() == 1) return MatrixOps::chol(vars.at(args[0]));
if (name == "sin" && args.size() == 1) return MatrixOps::sin(vars.at(args[0]));
if (name == "cos" && args.size() == 1) return MatrixOps::cos(vars.at(args[0]));
if (name == "tan" && args.size() == 1) return MatrixOps::tan(vars.at(args[0]));
if (name == "exp" && args.size() == 1) return MatrixOps::exp(vars.at(args[0]));
if (name == "log" && args.size() == 1) return MatrixOps::log(vars.at(args[0]));
if (name == "log10" && args.size() == 1) return MatrixOps::log10(vars.at(args[0]));
if (name == "log2" && args.size() == 1) return MatrixOps::log2(vars.at(args[0]));
if (name == "sqrt" && args.size() == 1) return MatrixOps::sqrt(vars.at(args[0]));
if (name == "abs" && args.size() == 1) return MatrixOps::abs(vars.at(args[0]));
if (name == "sign" && args.size() == 1) return MatrixOps::sign(vars.at(args[0]));
if (name == "round" && args.size() == 1) return MatrixOps::round(vars.at(args[0]));
if (name == "floor" && args.size() == 1) return MatrixOps::floor(vars.at(args[0]));
if (name == "ceil" && args.size() == 1) return MatrixOps::ceil(vars.at(args[0]));
if (name == "fix" && args.size() == 1) return MatrixOps::fix(vars.at(args[0]));
if (name == "sum" && args.size() == 1) return MatrixOps::sum(vars.at(args[0]));
if (name == "mean" && args.size() == 1) return MatrixOps::mean(vars.at(args[0]));
if (name == "prod" && args.size() == 1) return MatrixOps::prod(vars.at(args[0]));
if (name == "max" && args.size() == 1) return MatrixOps::max_val(vars.at(args[0]));
if (name == "min" && args.size() == 1) return MatrixOps::min_val(vars.at(args[0]));
// 二元函数
if (args.size() == 2) {
if (name == "atan2") return MatrixOps::atan2(vars.at(args[0]), vars.at(args[1]));
if (name == "mod") return MatrixOps::mod(vars.at(args[0]), vars.at(args[1]));
if (name == "rem") return MatrixOps::rem(vars.at(args[0]), vars.at(args[1]));
if (name == "max") return MatrixOps::max(vars.at(args[0]), vars.at(args[1]));
if (name == "min") return MatrixOps::min(vars.at(args[0]), vars.at(args[1]));
}
THROW_EXCEPTION("不支持的函数或参数数量错误: " + name);
}
};
// 线程池处理器
class ThreadPool {
public:
explicit ThreadPool(size_t threads = std::thread::hardware_concurrency())
: stop(false) {
for (size_t i = 0; i < threads; ++i) {
workers.emplace_back([this] {
while (true) {
std::function<void()> task;
{
std::unique_lock<std::mutex> lock(queue_mutex);
condition.wait(lock, [this] { return stop || !tasks.empty(); });
if (stop && tasks.empty()) return;
task = std::move(tasks.front());
tasks.pop();
}
task();
}
});
}
logger->info("线程池初始化完成,线程数: {}", workers.size());
}
template<class F>
void enqueue(F&& f) {
{
std::unique_lock<std::mutex> lock(queue_mutex);
if (stop) throw std::runtime_error("线程池已停止,无法添加任务");
tasks.emplace(std::forward<F>(f));
}
condition.notify_one();
}
~ThreadPool() {
{
std::unique_lock<std::mutex> lock(queue_mutex);
stop = true;
}
condition.notify_all();
for (std::thread& worker : workers) {
if (worker.joinable()) worker.join();
}
}
private:
std::vector<std::thread> workers;
std::queue<std::function<void()>> tasks;
std::mutex queue_mutex;
std::condition_variable condition;
bool stop;
};
// 文件处理函数
void process_file(const std::string& mat_path,
const std::string& m_script,
const std::vector<std::string>& output_formats) {
try {
logger->info("开始处理: {}", mat_path);
// 加载MAT文件变量
EigenMap variables = MatFileHandler::load(mat_path);
logger->info("加载变量数量: {}", variables.size());
// 解析并执行M代码
MCodeParser parser(m_script);
parser.execute(variables);
// 生成输出文件名(移除原扩展名)
std::string base_name = fs::path(mat_path).stem().string();
// 保存结果到指定格式
for (const auto& format : output_formats) {
std::string output_path = base_name + "." + format;
if (format == "mat") {
MatFileHandler::save(output_path, variables);
} else if (format == "csv") {
FormatExporter::save_csv(output_path, variables);
} else if (format == "xlsx") {
FormatExporter::save_excel(output_path, variables);
} else if (format == "parquet") {
FormatExporter::save_parquet(output_path, variables);
} else {
logger->warn("不支持的输出格式: {}", format);
continue;
}
logger->info("已保存到: {}", output_path);
}
logger->info("处理完成: {}", mat_path);
} catch (const std::exception& e) {
logger->error("处理文件失败: {}\n{}", mat_path, e.what());
}
}
// 目录处理函数
void process_directory(const std::string& dir_path,
const std::string& m_script,
const std::vector<std::string>& output_formats,
ThreadPool& pool) {
if (!fs::is_directory(dir_path)) {
logger->error("不是有效目录: {}", dir_path);
return;
}
for (const auto& entry : fs::directory_iterator(dir_path)) {
if (entry.is_regular_file() && entry.path().extension() == ".mat") {
pool.enqueue([=] {
process_file(entry.path().string(), m_script, output_formats);
});
}
}
logger->info("目录任务已全部加入队列: {}", dir_path);
}
// 命令行参数解析
struct CmdArgs {
std::string input_path;
std::string script_path;
std::vector<std::string> output_formats;
size_t threads = std::thread::hardware_concurrency();
};
CmdArgs parse_args(int argc, char* argv[]) {
if (argc < 4) {
std::cerr << "用法: " << argv[0]
<< " <输入路径(.mat或目录)> <M脚本路径> <输出格式(用逗号分隔)> [线程数]\n"
<< "示例: " << argv[0]
<< " data.mat calc.m mat,csv 4\n"
<< "支持格式: mat, csv, xlsx(待实现), parquet(待实现)\n";
exit(1);
}
CmdArgs args;
args.input_path = argv[1];
args.script_path = argv[2];
// 解析输出格式
std::istringstream iss(argv[3]);
std::string format;
while (std::getline(iss, format, ',')) {
if (!format.empty()) args.output_formats.push_back(format);
}
// 解析线程数
if (argc >= 5) {
try {
args.threads = std::stoul(argv[4]);
if (args.threads == 0) args.threads = 1;
} catch (...) {
logger->warn("无效线程数,使用默认值: {}", args.threads);
}
}
// 验证输入
if (!fs::exists(args.input_path)) {
THROW_EXCEPTION("输入路径不存在: " + args.input_path);
}
if (!fs::exists(args.script_path) || fs::path(args.script_path).extension() != ".m") {
THROW_EXCEPTION("无效M脚本文件: " + args.script_path);
}
if (args.output_formats.empty()) {
THROW_EXCEPTION("未指定输出格式");
}
return args;
}
int main(int argc, char* argv[]) {
try {
logger->info("程序启动");
// 解析命令行参数
CmdArgs args = parse_args(argc, argv);
logger->info("输入路径: {}", args.input_path);
logger->info("M脚本: {}", args.script_path);
logger->info("输出格式: {}", fmt::format("{}", fmt::join(args.output_formats, ",")));
logger->info("线程数: {}", args.threads);
// 初始化线程池
ThreadPool pool(args.threads);
// 处理输入(文件或目录)
if (fs::is_regular_file(args.input_path) &&
fs::path(args.input_path).extension() == ".mat") {
// 处理单个MAT文件
pool.enqueue([&] {
process_file(args.input_path, args.script_path, args.output_formats);
});
} else if (fs::is_directory(args.input_path)) {
// 处理目录下所有MAT文件
process_directory(args.input_path, args.script_path, args.output_formats, pool);
} else {
THROW_EXCEPTION("输入必须是.mat文件或目录: " + args.input_path);
}
// 等待所有任务完成(通过线程池析构实现)
logger->info("等待所有任务完成...");
} catch (const std::exception& e) {
logger->critical("程序异常终止: {}", e.what());
return 1;
}
logger->info("程序正常结束");
return 0;
}
这个完整的GCC C++代码实现了以下功能:
主要特性
矩阵运算支持:
- 基本运算:加法、减法、乘法、除法
- 高级运算:矩阵求逆、伪逆、特征值、SVD、Cholesky分解
- 逐元素运算:sin, cos, tan, exp, log, sqrt, abs等
数学函数支持:
- 三角函数:sin, cos, tan, asin, acos, atan, sinh, cosh, tanh
- 指数对数:exp, log, log10, log2
- 取整函数:round, floor, ceil, fix
- 其他函数:sign, pow, atan2, mod, rem
文件处理:
- MAT文件读写(使用MATIO库)
- 支持CSV格式输出
- 预留Excel和Parquet格式接口
多线程处理:
- 线程池实现并行处理多个MAT文件
- 任务队列管理
- 线程安全控制
日志系统:
- 使用spdlog实现多级别日志
- 控制台和文件双重输出
- 详细的错误信息记录
M代码解析:
- 解析简单的赋值语句
- 支持函数调用
- 错误处理和调试信息
编译说明
要编译此代码,您需要安装以下依赖库:
- GCC/G++ (建议版本 9 或更高)
- MATIO库 (用于MAT文件处理)
- Eigen库 (用于矩阵计算)
- spdlog库 (用于日志系统)
- Boost库 (用于backward错误追踪)
编译命令示例:
g++ -std=c++17 -o matrix_calc main.cpp -lmatio -I/path/to/eigen -I/path/to/spdlog -I/path/to/boost -lpthread -lstdc++fs
使用方法
# 处理单个MAT文件
./matrix_calc data.mat calc.m mat,csv 4
# 处理目录下所有MAT文件
./matrix_calc /path/to/mat_files calc.m mat 8
这个实现提供了完整的MATLAB风格矩阵运算功能,支持多种数学函数,并具有良好的扩展性和错误处理机制。