26 (
context).limits().max_ast_nodes,
"transform");
30 auto neg_x = SymbolicExpr::multiply(SymbolicExpr::number(-1), SymbolicExpr::variable(var));
37 auto diff_even = SymbolicExpr::add(f_neg, SymbolicExpr::multiply(SymbolicExpr::number(-1), f_s));
41 auto diff_odd = SymbolicExpr::add(f_neg, f_s);
54 const std::shared_ptr<SymbolicExpr>& expr,
55 const std::shared_ptr<SymbolicExpr>& center,
56 const std::string& var,
58 const std::string& operation)
66 "series expression and center cannot be null",
75 const std::string& operation)
77 if (order_neg < 0 || order_pos < 0 || order_neg > 64 || order_pos > 64) {
79 "Laurent truncation orders must be between 0 and 64",
86 const std::shared_ptr<SymbolicExpr>& f,
90 (
context).limits().max_ast_nodes,
"transform");
91 auto fn = std::dynamic_pointer_cast<const FunctionNode>(
detail::node(f));
93 fn->arguments().size() != 1) {
97 auto power = std::dynamic_pointer_cast<const PowerNode>(
detail::node(argument));
102 power->exponent(), -std::numeric_limits<int>::max(), std::numeric_limits<int>::max());
108 if (base->compare(delta) == 0 && *
exponent < 0) {
111 auto nested = std::dynamic_pointer_cast<const PowerNode>(
detail::node(base));
114 nested->exponent(), 1, std::numeric_limits<int>::max());
116 if (m && nested_base->compare(delta) == 0) {
124 const std::shared_ptr<SymbolicExpr>& shift,
int m,
int order_neg,
127 (
context).limits().max_ast_nodes,
"transform");
128 constexpr const char* operation =
"laurent_series_full";
129 auto series = SymbolicExpr::number(1);
131 for (
int k = 1; k <= order_neg / m; ++k) {
132 auto step =
context.consume_steps(1, operation);
136 factorial *= BigInt(k);
137 auto term = SymbolicExpr::divide(
138 SymbolicExpr::number(1),
139 SymbolicExpr::multiply(
140 SymbolicExpr::number(factorial),
141 SymbolicExpr::power(shift, SymbolicExpr::number(m * k))));
142 series = SymbolicExpr::add(series, term);
146 SymbolicExpr::number(m == 1 ? 1 : 0)};
147}
catch (
const CasError& error) {
149}
catch (
const std::bad_alloc&) {
151}
catch (
const std::length_error& error) {
153}
catch (
const std::exception& error) {
157 const std::shared_ptr<SymbolicExpr>&,
159 const std::shared_ptr<SymbolicExpr>&,
162 Integrator&
integrator,
const std::shared_ptr<SymbolicExpr>& f,
163 const std::string& var,
const std::shared_ptr<SymbolicExpr>& half_lo,
164 const std::shared_ptr<SymbolicExpr>& half_hi,
165 const std::shared_ptr<SymbolicExpr>& L,
166 const std::shared_ptr<SymbolicExpr>& arg,
bool cosine,
169 (
context).limits().max_ast_nodes,
"transform");
170 auto integrand = SymbolicExpr::multiply(
171 f, cosine ? SymbolicExpr::cos(arg) : SymbolicExpr::sin(arg));
172 auto integrated =
integrator.integrate_def_checked(
173 *integrand, var, *half_lo, *half_hi,
context);
180 result = SymbolicExpr::add(
181 result, SymbolicExpr::multiply(
182 coefficient, cosine ? SymbolicExpr::cos(arg) : SymbolicExpr::sin(arg)));
185}
catch (
const CasError& error) {
187}
catch (
const std::bad_alloc&) {
189}
catch (
const std::length_error& error) {
191}
catch (
const std::exception& error) {
196 std::shared_ptr<SymbolicExpr>
two;
198 std::shared_ptr<SymbolicExpr>
lower;
199 std::shared_ptr<SymbolicExpr>
upper;
204 const std::shared_ptr<SymbolicExpr>& period,
const std::string& var,
207 std::optional<detail::AssumptionFacts> assumed;
208 if (
context.assumptions()) { assumed.emplace(*
context.assumptions()); }
216 "Fourier period must be a proved positive constant",
"fourier_series");
220 auto two = SymbolicExpr::number(2);
221 auto L = SymbolicExpr::divide(T, two);
222 auto half_lo = SymbolicExpr::multiply(SymbolicExpr::number(-1), L);
224 auto w = SymbolicExpr::divide(SymbolicExpr::multiply(two,
pi), T);
225 return FourierPeriod{std::move(two), std::move(L), std::move(half_lo),
226 std::move(half_hi), std::move(w)};
230 const std::shared_ptr<SymbolicExpr>& f,
const std::string& var,
233 (
context).limits().max_ast_nodes,
"transform");
234 auto a0_integral =
integrator.integrate_def_checked(
239 return SymbolicExpr::divide(a0, period.
two);
240}
catch (
const CasError& error) {
242}
catch (
const std::bad_alloc&) {
244}
catch (
const std::length_error& error) {
246}
catch (
const std::exception& error) {
251 const std::shared_ptr<SymbolicExpr>& f,
const std::string& var,
252 const FourierPeriod& period,
const std::shared_ptr<SymbolicExpr>& x,
254 for (
int k = 1; k <= n_terms; ++k) {
255 auto kw = SymbolicExpr::multiply(SymbolicExpr::number(k), period.
frequency);
256 auto arg = SymbolicExpr::multiply(kw, x);
260 if (!added) {
return added; }
265 if (!added) {
return added; }
272 const std::shared_ptr<SymbolicExpr>& f,
const std::string& var,
273 const std::shared_ptr<SymbolicExpr>& period,
int n_terms,
276 (
context).limits().max_ast_nodes,
"transform");
277 constexpr const char* operation =
"fourier_series";
278 if (!f || !period || var.empty() || n_terms < 0) {
281 "Fourier expansion requires an expression, variable, positive period, and non-negative term count",
284 const std::size_t expansion_terms =
285 1 + 2 *
static_cast<std::size_t
>(n_terms);
286 if (expansion_terms >
context.limits().max_expansion_terms) {
289 "Fourier term count exceeds the expansion budget", operation);
293 auto access =
context.consume_steps(1, operation);
303 auto x = SymbolicExpr::variable(var);
306 if (!constant) {
return constant; }
307 auto result = std::move(constant.value());
312 }
catch (
const std::bad_alloc&) {
315 "Fourier expansion allocation failed", operation);
320}
catch (
const CasError& error) {
322}
catch (
const std::bad_alloc&) {
324}
catch (
const std::length_error& error) {
326}
catch (
const std::exception& error) {
331 const std::shared_ptr<SymbolicExpr>& f,
const std::string& var,
332 const std::shared_ptr<SymbolicExpr>& period,
int n_terms) {
339 const std::shared_ptr<SymbolicExpr>& f,
340 const std::string& var,
341 const std::shared_ptr<SymbolicExpr>& center,
347 (
context).limits().max_ast_nodes,
"transform");
349 f, var, center, order_neg, order_pos,
context);
354 auto supported_power = simplified
358 if (center->is_zero() && supported_power && *supported_power < 0) {
362}
catch (
const CasError& error) {
364}
catch (
const std::bad_alloc&) {
366}
catch (
const std::length_error& error) {
368}
catch (
const std::exception& error) {
373 const std::shared_ptr<SymbolicExpr>& f,
374 const std::string& var,
375 const std::shared_ptr<SymbolicExpr>& center,
384 const LaurentResult& result,
const std::optional<int>& supported_power,
385 const std::shared_ptr<SymbolicExpr>& center,
const std::string& operation) {
389 "Laurent series could not be constructed in the supported domain",
395 "Laurent series produced a null residue expression",
398 if (supported_power && center->is_zero()) {
399 BigInt expected_pole_order =
400 *supported_power < 0 ? -BigInt(*supported_power) : BigInt(0);
401 if (BigInt(result.
pole_order) != expected_pole_order) {
404 "Laurent pole order could not be verified",
412 const std::shared_ptr<SymbolicExpr>& f,
413 const std::string& var,
414 const std::shared_ptr<SymbolicExpr>& center,
420 (
context).limits().max_ast_nodes,
"transform");
421 const std::string operation =
"laurent_series_full";
430 auto budget =
context.consume_steps(
static_cast<std::size_t
>(order_neg + order_pos + 1) * 16 + 16,
440 "checked Laurent input could not be simplified in the supported domain",
446 f, var, center, order_neg, order_pos,
context);
450 auto result = std::move(built.value());
458 }
catch (
const std::bad_alloc&) {
460 "allocation failed while calculating Laurent series",
467}
catch (
const CasError& error) {
469}
catch (
const std::bad_alloc&) {
471}
catch (
const std::length_error& error) {
473}
catch (
const std::exception& error) {
478 const std::shared_ptr<SymbolicExpr>& f,
479 const std::string& var,
480 const std::shared_ptr<SymbolicExpr>& center,
495 const std::shared_ptr<SymbolicExpr>& f,
const std::string& var,
497 constexpr const char* operation =
"laurent_series_full";
498 auto fn = std::dynamic_pointer_cast<const FunctionNode>(
detail::node(f));
505 if (polynomial.value()) {
510 "Laurent singularity could not be proved", operation);
514 const std::shared_ptr<SymbolicExpr>& f,
const std::string& var,
515 const std::shared_ptr<SymbolicExpr>& center,
516 const std::shared_ptr<SymbolicExpr>& shift,
519 (
context).limits().max_ast_nodes,
"transform");
520 constexpr const char* operation =
"laurent_series_full";
521 auto center_number = std::dynamic_pointer_cast<const NumberNode>(
detail::node(center));
522 if (!center_number) {
524 "Laurent center must be an exact number", operation);
526 Rational
point = std::holds_alternative<BigInt>(center_number->value())
527 ? Rational(std::get<BigInt>(center_number->value()))
528 : std::get<Rational>(center_number->value());
534 if (!recognized.value()) {
537 if (numerator.is_zero()) {
543 auto step =
context.consume_steps(1, operation);
547 if (pole_order >= 64) {
549 "Laurent pole order exceeds supported range", operation);
554 if (pole_order > 0) {
556 SymbolicExpr::power(shift, SymbolicExpr::number(pole_order)), f)->cancel()), transform_budget));
559}
catch (
const CasError& error) {
561}
catch (
const std::bad_alloc&) {
563}
catch (
const std::length_error& error) {
565}
catch (
const std::exception& error) {
570 const std::shared_ptr<SymbolicExpr>& f,
const std::string& var,
571 const std::shared_ptr<SymbolicExpr>& center,
int order_neg,
int order_pos,
574 (
context).limits().max_ast_nodes,
"transform");
580 auto x = SymbolicExpr::variable(var);
581 auto shift = SymbolicExpr::add(x, SymbolicExpr::multiply(SymbolicExpr::number(-1), center));
588 std::shared_ptr<SymbolicExpr> regular = f;
590 f, var, center, shift, regular,
context);
594 const int pole_order = extracted.value();
597 int taylor_order = order_pos + pole_order + 1;
598 if (taylor_order < 1) {
601 auto taylor = regular->series(var, center, taylor_order);
607 std::shared_ptr<SymbolicExpr> laurent = taylor;
608 if (pole_order > 0) {
609 auto powm = SymbolicExpr::power(shift, SymbolicExpr::number(pole_order));
615 if (pole_order == 0) {
622 if (pole_order >= 1) {
624 auto deriv = regular;
632 auto val = std::move(limited.value());
636 auto fact = BigInt::factorial_checked(BigInt(pole_order - 1),
context);
644}
catch (
const CasError& error) {
646}
catch (
const std::bad_alloc&) {
648}
catch (
const std::length_error& error) {
650}
catch (
const std::exception& error) {
655 const std::shared_ptr<SymbolicExpr>& f,
const std::string& var,
int order) {
658 (
context).limits().max_ast_nodes,
"transform");
659 if (!f ||
order < 0) {
664 auto x = SymbolicExpr::variable(var);
665 std::string tname = var +
"__asym_t";
666 auto t = SymbolicExpr::variable(tname);
667 auto inv_t = SymbolicExpr::divide(SymbolicExpr::number(1),
t);
673 auto taylor_t = g->series(tname, SymbolicExpr::number(0),
order + 1);
678 auto inv_x = SymbolicExpr::divide(SymbolicExpr::number(1), x);
static Result failure(CasErrc code, std::string message, std::string operation={})
static Result success(T value)
std::optional< int > supported_laurent_integer_power(const std::shared_ptr< const SymbolicNode > &node, const std::string &variable)
Result< void > validate_series_variable(const std::string &variable, ComputationContext &context, const std::string &operation)
SymbolicNodePtr differentiate_node(const SymbolicNodePtr &node, const std::string &variable, RewriteBudget &budget, const FactsQuery &facts, Domain domain)
std::shared_ptr<::LMCAS::SymbolicExpr > make_expression_ptr(SymbolicNodePtr root)
const SymbolicNodePtr & node(const ::LMCAS::SymbolicExpr &expression) noexcept
const FactsQuery & no_facts() noexcept
std::shared_ptr< const Node > make_node(Args &&... args)
Result< bool > extract_rational(const SymbolicExpr &expr, const std::string &var, Polynomial< Rational > &numerator, Polynomial< Rational > &denominator)
SymbolicNodePtr normalize_node(const SymbolicNodePtr &node, RewriteBudget &budget, const FactsQuery &facts, Domain domain)
Result< Tribool > query_positive_value(const Node &node, const FactsQuery &facts, ComputationContext &context)
SymbolicNodePtr substitute_node(const SymbolicNodePtr &node, const std::string &variable, const SymbolicNodePtr &replacement, RewriteBudget &budget, const FactsQuery &facts, Domain domain)
const std::string const LimitExprPtr & point
ExpressionResult fourier_series_checked(const std::shared_ptr< SymbolicExpr > &f, const std::string &var, const std::shared_ptr< SymbolicExpr > &period, int n_terms, ComputationContext &context)
static int detect_parity(const std::shared_ptr< SymbolicExpr > &f, const std::string &var, ComputationContext &context)
std::shared_ptr< SymbolicExpr > half_length
const std::vector< Polynomial< BigInt > > const BigInt ComputationContext & context
static LaurentSeriesResult essential_laurent(const std::shared_ptr< SymbolicExpr > &shift, int m, int order_neg, ComputationContext &context)
SingularityType singularity
奇点类型
const std::vector< FGLMPoly > const MonomialOrder & order
static bool regular_laurent_type(FunctionNode::FuncType type)
ExpressionResult laurent_series_checked(const std::shared_ptr< SymbolicExpr > &f, const std::string &var, const std::shared_ptr< SymbolicExpr > ¢er, int order_neg, int order_pos, ComputationContext &context)
bool expression_depends_on_variable(const detail::SymbolicNodePtr &expression, const std::string &variable, detail::RewriteBudget *budget)
@ True
Property definitely holds
@ False
Property definitely does not hold
int pole_order
极点阶数(非极点时为 0)
LimitExpressionResult limit_expression_checked(const LimitExprPtr &expression, const std::string &variable, const LimitExprPtr &point, LimitDirection direction, ComputationContext &context, Domain domain)
static Result< void > validate_laurent_result(const LaurentResult &result, const std::optional< int > &supported_power, const std::shared_ptr< SymbolicExpr > ¢er, const std::string &operation)
Result< std::shared_ptr< SymbolicExpr > > ExpressionResult
Result of an operation that produces a symbolic expression.
std::shared_ptr< SymbolicExpr > upper
static LaurentSeriesResult laurent_series_full_impl(const std::shared_ptr< SymbolicExpr > &, const std::string &, const std::shared_ptr< SymbolicExpr > &, int, int, ComputationContext &)
static Result< FourierPeriod > prepare_fourier_period(const std::shared_ptr< SymbolicExpr > &period, const std::string &var, ComputationContext &context)
Result< void > validate_series_expr_point(const std::shared_ptr< SymbolicExpr > &expr, const std::shared_ptr< SymbolicExpr > ¢er, const std::string &var, ComputationContext &context, const std::string &operation)
static Result< int > recognize_regular_laurent(const std::shared_ptr< SymbolicExpr > &f, const std::string &var, ComputationContext &context)
std::shared_ptr< SymbolicExpr > two
std::optional< int > exact_small_integer_node(const detail::SymbolicNodePtr &node, int min_value, int max_value)
static Result< void > fourier_harmonics(Integrator &integrator, const std::shared_ptr< SymbolicExpr > &f, const std::string &var, const FourierPeriod &period, const std::shared_ptr< SymbolicExpr > &x, int n_terms, int parity, std::shared_ptr< SymbolicExpr > &result, ComputationContext &context)
LaurentSeriesResult laurent_series_full_checked(const std::shared_ptr< SymbolicExpr > &f, const std::string &var, const std::shared_ptr< SymbolicExpr > ¢er, int order_neg, int order_pos, ComputationContext &context)
std::shared_ptr< SymbolicExpr > frequency
static std::optional< int > essential_exponent(const std::shared_ptr< SymbolicExpr > &f, const std::shared_ptr< SymbolicExpr > &shift, ComputationContext &context)
static ExpressionResult fourier_constant_coefficient(Integrator &integrator, const std::shared_ptr< SymbolicExpr > &f, const std::string &var, const FourierPeriod &period, ComputationContext &context)
Result< void > validate_laurent_orders(int order_neg, int order_pos, const std::string &operation)
Result< OptionalRationalPolynomial > recognize_rational_polynomial(const SymbolicExpr &expression, const std::string &variable, ComputationContext &context)
Result< LaurentResult > LaurentSeriesResult
std::shared_ptr< SymbolicExpr > residue
留数((z-z_0)-¹ 的系数)
std::shared_ptr< SymbolicExpr > asymptotic_expand(const std::shared_ptr< SymbolicExpr > &f, const std::string &var, int order)
std::shared_ptr< SymbolicExpr > series
洛朗级数表达式
std::optional< int > supported_laurent_integer_power(const std::shared_ptr< const SymbolicNode > &node, const std::string &variable)
static Result< int > extract_laurent_regular_part(const std::shared_ptr< SymbolicExpr > &f, const std::string &var, const std::shared_ptr< SymbolicExpr > ¢er, const std::shared_ptr< SymbolicExpr > &shift, std::shared_ptr< SymbolicExpr > ®ular, ComputationContext &context)
static Result< void > add_fourier_harmonic(Integrator &integrator, const std::shared_ptr< SymbolicExpr > &f, const std::string &var, const std::shared_ptr< SymbolicExpr > &half_lo, const std::shared_ptr< SymbolicExpr > &half_hi, const std::shared_ptr< SymbolicExpr > &L, const std::shared_ptr< SymbolicExpr > &arg, bool cosine, std::shared_ptr< SymbolicExpr > &result, ComputationContext &context)
const ExprPtr & denominator
__attribute__((visibility("default"))) VectorCalculusExprResult curve_integral_scalar_checked(const std __attribute__((visibility("default"))) VectorCalculusExprResult curve_integral_scalar_checked(const std __attribute__((visibility("default"))) std const VectorField const std::string & t
std::shared_ptr< SymbolicExpr > lower
const std::vector< IntegrationStep > Integrator & integrator
Result< void > validate_series_variable(const std::string &variable, ComputationContext &context, const std::string &operation)
级数引擎模块:收敛性判定,幂级数运算,傅里叶级数,洛朗级数,渐近展开,符号求和与乘积.
符号表达式主类 SymbolicExpr 及其工厂方法,运算接口.