EnergySpectrumAnalyer/src/DataCalcProcess/AdaptiveSimpsonIntegrate.h
2026-04-20 18:02:41 +08:00

78 lines
2.4 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#ifndef ADAPTIVESIMPSONINTEGRATE_H
#define ADAPTIVESIMPSONINTEGRATE_H
namespace AdaptiveSimpsonIntegrate {
#include <armadillo>
#include <cmath>
#include <iostream>
//#include <iomanip>
// 定义被积函数y = A*exp(-(x-P)²/(2*delt²)) + H/(1+exp((x-P)/W)) + C
struct FitFunction {
// 拟合公式的参数
double A; // 高斯项振幅
double P; // 中心位置
double delt; // 高斯项宽度
double H; // Sigmoid项高度
double W; // Sigmoid项宽度
double C; // 常数项
// 重载()运算符计算给定点x的函数值
double operator()(double x) const {
// 高斯项A*exp(-(x-P)²/(2*delt²))
double gaussian_term = A * ::std::exp(-::std::pow(x - P, 2) / (2 * ::std::pow(delt, 2)));
// Sigmoid项H/(1+exp((x-P)/W))
double sigmoid_term = H / (1 + ::std::exp((x - P) / W));
// 常数项 + 两项之和
return gaussian_term + sigmoid_term + C;
}
};
// 辛普森积分核心计算(单区间)
template<typename Func>
double simpson(double a, double b, const Func& f) {
double h = (b - a) / 2.0;
double fa = f(a), fb = f(b), fc = f(a + h);
return h * (fa + 4 * fc + fb) / 3.0;
}
// 自适应辛普森积分(递归实现,控制精度)
template<typename Func>
double adaptive_simpson(double a, double b, double eps, const Func& f,
double whole, double fa, double fb, double fc, int depth) {
// 防止递归过深(避免栈溢出)
if (depth > 20) return whole;
double c = (a + b) / 2.0;
double h = (b - a) / 4.0;
double fd = f(a + h), fe = f(b - h);
// 计算左右子区间的辛普森值
double left = simpson(a, c, f);
double right = simpson(c, b, f);
// 精度判断:满足则返回,不满足则递归细分
if (::std::abs(left + right - whole) <= 15 * eps) {
return left + right + (left + right - whole) / 15.0;
}
return adaptive_simpson(a, c, eps/2, f, left, fa, fc, fd, depth+1) +
adaptive_simpson(c, b, eps/2, f, right, fc, fb, fe, depth+1);
}
// 积分入口函数(对外接口)
template<typename Func>
double integrate(Func f, double a, double b, double eps = 1e-8) {
double c = (a + b) / 2.0;
double fa = f(a), fb = f(b), fc = f(c);
double whole = simpson(a, b, f);
return adaptive_simpson(a, b, eps, f, whole, fa, fb, fc, 0);
}
}
#endif // ADAPTIVESIMPSONINTEGRATE_H