1#include "include/laplace.h"
2#define _USE_MATH_DEFINES
12void LaplaceTransform::initializeTransformTable() {
13 if (!transformTable.empty())
return;
39 return w_complex / (s * s + w_complex * w_complex);
45 return s / (s * s + w_complex * w_complex);
52 return a_complex / (s * s - a_complex * a_complex);
58 return s / (s * s - a_complex * a_complex);
63std::shared_ptr<Expression> LaplaceTransform::transform(std::shared_ptr<Expression> expr,
const std::string& var) {
64 initializeTransformTable();
67 throw std::invalid_argument(
"Expression cannot be null");
71 std::string exprStr = expr->toString();
79 return std::make_shared<Variable>(
"1/s");
81 else if (exprStr == var) {
83 return std::make_shared<Variable>(
"1/s^2");
85 else if (exprStr.find(
"exp") != std::string::npos) {
88 return std::make_shared<Variable>(
"1/(s-a)");
90 else if (exprStr.find(
"sin") != std::string::npos) {
92 return std::make_shared<Variable>(
"w/(s^2+w^2)");
94 else if (exprStr.find(
"cos") != std::string::npos) {
96 return std::make_shared<Variable>(
"s/(s^2+w^2)");
100 return std::make_shared<Variable>(
"L{" + exprStr +
"}");
103std::shared_ptr<Expression> LaplaceTransform::inverseTransform(std::shared_ptr<Expression> expr,
const std::string& var) {
105 throw std::invalid_argument(
"Expression cannot be null");
108 std::string exprStr = expr->toString();
111 if (exprStr ==
"1/s") {
112 return std::make_shared<Variable>(
"1");
114 else if (exprStr ==
"1/s^2") {
115 return std::make_shared<Variable>(var);
117 else if (exprStr.find(
"1/(s-") != std::string::npos) {
119 return std::make_shared<Variable>(
"exp(a*" + var +
")");
121 else if (exprStr.find(
"/(s^2+") != std::string::npos) {
122 if (exprStr.find(
"s/(s^2+") != std::string::npos) {
124 return std::make_shared<Variable>(
"cos(w*" + var +
")");
127 return std::make_shared<Variable>(
"sin(w*" + var +
")");
132 return std::make_shared<Variable>(
"L^{-1}{" + exprStr +
"}");
137 if (s.getValue().real() <= 0) {
138 throw std::invalid_argument(
"Real part of s must be positive for convergence");
141 const int samples = 1000;
142 double dt = T / samples;
145 for (
int n = 0; n < samples; ++n) {
151 ComplexNumber(-s.getValue().real() * t, -s.getValue().imag() * t);
161double factorial(
int n)
167 for (
int i = 2; i <= n; ++i) {
173std::function<double(
double)> LaplaceTransform::numericalInverseTransform(
176 return [F, t_max](
double t) ->
double {
177 if (t < 0)
return 0.0;
184 double ln2_t = log(2.0) / t;
187 std::vector<double> V(N + 1);
188 for (
int i = 1; i <= N; ++i) {
190 int k_min = (i + 1) / 2;
191 int k_max = std::min(i, N / 2);
193 for (
int k = k_min; k <= k_max; ++k) {
194 double term = pow(k, N / 2) * factorial(2 * k);
195 term /= (factorial(N / 2 - k) * factorial(k) * factorial(k - 1) * factorial(i - k) * factorial(2 * k - i));
199 V[i] = pow(-1, i + N / 2) * sum;
203 for (
int i = 1; i <= N; ++i) {
206 result += V[i] * F_s.getValue().real();
209 return ln2_t * result;
225 return omega_complex / (s * s + omega_complex * omega_complex);
235 for (
int i = 0; i <= p.getDegree(); ++i) {
236 double coeff = p.getCoeff(i);
237 if (std::abs(coeff) < 1e-15)
continue;
240 double factorial_i = factorial(i);
242 for (
int j = 1; j < i + 1; ++j) {
243 s_power = s_power * s;
247 result = result + term;
254std::shared_ptr<Expression> LaplaceTransform::convolution(std::shared_ptr<Expression> f1, std::shared_ptr<Expression> f2) {
256 throw std::invalid_argument(
"Expressions cannot be null");
260 auto F1 = transform(f1);
261 auto F2 = transform(f2);
264 std::string result_str =
"(" + F1->toString() +
") * (" + F2->toString() +
")";
265 return std::make_shared<Variable>(result_str);
268std::shared_ptr<Expression> LaplaceTransform::timeShift(std::shared_ptr<Expression> expr,
double a) {
270 throw std::invalid_argument(
"Expression cannot be null");
274 throw std::invalid_argument(
"Time shift must be non-negative");
278 auto F = transform(expr);
279 std::string result_str =
"exp(-" + std::to_string(a) +
"*s) * (" + F->toString() +
")";
280 return std::make_shared<Variable>(result_str);
283std::shared_ptr<Expression> LaplaceTransform::frequencyShift(std::shared_ptr<Expression> expr,
double a) {
285 throw std::invalid_argument(
"Expression cannot be null");
289 auto F = transform(expr);
290 std::string original = F->toString();
294 std::string result_str = original;
296 while ((pos = result_str.find(
's', pos)) != std::string::npos) {
297 result_str.replace(pos, 1,
"(s-" + std::to_string(a) +
")");
298 pos += 4 + std::to_string(a).length();
301 return std::make_shared<Variable>(result_str);