20 if (std::holds_alternative<BigInt>(number.
value())) {
21 return std::get<BigInt>(number.
value()).to_double();
23 return std::get<Rational>(number.
value()).to_double();
30 return expr->is_number();
69 const std::shared_ptr<SymbolicExpr>&,
73 const std::string& index_var) {
81 (
context).limits().max_ast_nodes,
"transform");
82 auto exponent_variable = std::dynamic_pointer_cast<const VariableNode>(
89 std::vector<std::shared_ptr<const SymbolicNode>>{
93 auto base_variable = std::dynamic_pointer_cast<const VariableNode>(
97 return SymbolicExpr::number(1);
103 const std::shared_ptr<SymbolicExpr>& general_coefficient,
104 const std::string& index_var,
106 constexpr const char* operation =
"convergence_radius";
111 "convergence radius requires a coefficient term and index variable",
114 auto step =
context.consume_steps(2, operation);
119 if (
auto number = std::dynamic_pointer_cast<const NumberNode>(node)) {
121 number->is_zero() ? SymbolicExpr::infinity()
122 : SymbolicExpr::number(1));
124 if (
auto power = std::dynamic_pointer_cast<const PowerNode>(node)) {
132 "coefficient-term limit is outside the supported ratio/root-test domain",
137 const std::shared_ptr<SymbolicExpr>& general_coefficient,
138 const std::string& index_var) {
141 general_coefficient, index_var,
context);
145 const std::vector<std::shared_ptr<SymbolicExpr>>& coefficients,
146 const std::string& var,
149 const std::string operation =
"convergence_radius";
154 if (coefficients.empty()) {
156 "coefficient list cannot be empty",
160 coefficients, operation,
"polynomial");
164 auto budget =
context.consume_steps(coefficients.size() + 1, operation);
169 for (
size_t index = 0; index < coefficients.size(); ++index) {
174 "coefficient at index " + std::to_string(index) +
175 " depends on the series variable",
184 }
catch (
const std::bad_alloc&) {
187 "allocation failed while constructing convergence radius",
189 }
catch (
const std::exception& ex) {
196 const std::vector<std::shared_ptr<SymbolicExpr>>& coefficients,
197 const std::string& var)
205 const std::shared_ptr<SymbolicExpr>& general_term,
206 const std::string& index_var,
209 const std::string operation =
"convergence_test";
216 "general term cannot be null",
219 auto budget =
context.consume_steps(32, operation);
229 auto info = std::move(analyzed.value());
233 "convergence test is outside the current supported domain",
239 }
catch (
const std::bad_alloc&) {
241 "allocation failed while testing convergence",
243 }
catch (
const std::exception& ex) {
251 const std::shared_ptr<SymbolicExpr>& general_term,
252 const std::string& index_var)
259 const std::shared_ptr<const SymbolicNode>& node,
260 const std::string& index_var) {
261 auto power = std::dynamic_pointer_cast<const PowerNode>(node);
265 auto exponent = std::dynamic_pointer_cast<const VariableNode>(power->exponent());
266 auto base = std::dynamic_pointer_cast<const NumberNode>(power->base());
271 bool inside_unit_circle =
false;
272 if (
const auto*
integer = std::get_if<BigInt>(&base->value())) {
273 inside_unit_circle = *
integer > BigInt(-1) && *
integer < BigInt(1);
274 }
else if (
const auto*
rational = std::get_if<Rational>(&base->value())) {
284 const std::shared_ptr<const SymbolicNode>& node,
285 const std::string& index_var) {
286 auto power = std::dynamic_pointer_cast<const PowerNode>(node);
290 auto base_var = std::dynamic_pointer_cast<const VariableNode>(power->base());
291 auto exponent = std::dynamic_pointer_cast<const NumberNode>(power->exponent());
292 if (!base_var || base_var->is_constant() || base_var->name() != index_var || !
exponent) {
296 bool below_negative_one =
false;
297 bool at_or_above_negative_one =
false;
299 below_negative_one = *
integer < BigInt(-1);
300 at_or_above_negative_one = !below_negative_one;
301 }
else if (
const auto*
rational = std::get_if<Rational>(&
exponent->value())) {
302 below_negative_one = *
rational < Rational(-1);
303 at_or_above_negative_one = !below_negative_one;
305 if (below_negative_one) {
309 if (at_or_above_negative_one) {
320 (
context).limits().max_ast_nodes,
"transform");
326 ? std::dynamic_pointer_cast<const FunctionNode>(
detail::node(ls))
337 if (
const auto*
integer = std::get_if<BigInt>(&number->value())) {
342 if (
const auto*
rational = std::get_if<Rational>(&number->value())) {
351 const std::shared_ptr<SymbolicExpr>& general_term,
354 (
context).limits().max_ast_nodes,
"transform");
355 auto n = SymbolicExpr::variable(index_var);
356 auto n1 = SymbolicExpr::add(n, SymbolicExpr::number(1));
357 auto inf = SymbolicExpr::infinity();
361 auto ratio = SymbolicExpr::divide(a_n1, general_term);
372 auto lim = std::move(limited.value());
377}
catch (
const CasError& error) {
379}
catch (
const std::bad_alloc&) {
381}
catch (
const std::length_error& error) {
383}
catch (
const std::exception& error) {
388 const std::shared_ptr<SymbolicExpr>& general_term,
389 const std::string& index_var,
397 return std::move(*geometric);
401 return std::move(*power_info);
409 if (*laurent_power < -1) {
413 if (*laurent_power >= -1) {
const std::variant< BigInt, Rational > & value() const noexcept
const std::shared_ptr< const SymbolicNode > & exponent() const noexcept
const std::shared_ptr< const SymbolicNode > & base() const noexcept
static Result failure(CasErrc code, std::string message, std::string operation={})
static Result success(std::shared_ptr< SymbolicExpr > value)
bool series_is_infinity(const std::shared_ptr< SymbolicExpr > &expression)
double series_number_value(const NumberNode &number)
Result< void > validate_power_series_coefficients(const std::vector< std::shared_ptr< SymbolicExpr > > &coefficients, const std::string &operation, const std::string &name)
bool series_is_number(const std::shared_ptr< SymbolicExpr > &expression)
double series_get_double(const std::shared_ptr< SymbolicExpr > &expression)
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)
std::shared_ptr<::LMCAS::SymbolicExpr > make_expression_ptr(SymbolicNodePtr root)
const SymbolicNodePtr & node(const ::LMCAS::SymbolicExpr &expression) noexcept
std::shared_ptr< const Node > make_node(Args &&... args)
SymbolicNodePtr normalize_node(const SymbolicNodePtr &node, RewriteBudget &budget, const FactsQuery &facts, Domain domain)
SymbolicNodePtr substitute_node(const SymbolicNodePtr &node, const std::string &variable, const SymbolicNodePtr &replacement, RewriteBudget &budget, const FactsQuery &facts, Domain domain)
std::shared_ptr< SymbolicExpr > num(int value)
Result< ConvergenceInfo > ConvergenceInfoResult
const std::string & variable
static ConvergenceInfoResult ratio_convergence_test(const std::shared_ptr< SymbolicExpr > &general_term, const std::string &index_var, ComputationContext &context)
const std::vector< Polynomial< BigInt > > const BigInt ComputationContext & context
ExprResult integer(Integer)=delete
static bool series_index_variable(const std::shared_ptr< const VariableNode > &variable, const std::string &index_var)
static std::optional< ConvergenceInfo > power_term_convergence(const std::shared_ptr< const SymbolicNode > &node, const std::string &index_var)
bool expression_depends_on_variable(const detail::SymbolicNodePtr &expression, const std::string &variable, detail::RewriteBudget *budget)
LimitExpressionResult limit_expression_checked(const LimitExprPtr &expression, const std::string &variable, const LimitExprPtr &point, LimitDirection direction, ComputationContext &context, Domain domain)
Result< std::shared_ptr< SymbolicExpr > > ExpressionResult
Result of an operation that produces a symbolic expression.
ConvergenceInfoResult convergence_test_checked(const std::shared_ptr< SymbolicExpr > &general_term, const std::string &index_var, ComputationContext &context)
Result< void > validate_power_series_coefficients(const std::vector< std::shared_ptr< SymbolicExpr > > &coefficients, const std::string &operation, const std::string &name)
static std::optional< ConvergenceInfo > geometric_term_convergence(const std::shared_ptr< const SymbolicNode > &node, const std::string &index_var)
static ConvergenceInfo classify_ratio_limit(const std::shared_ptr< SymbolicExpr > &lim, ComputationContext &context)
std::optional< int > supported_laurent_integer_power(const std::shared_ptr< const SymbolicNode > &node, const std::string &variable)
static std::optional< std::shared_ptr< SymbolicExpr > > coefficient_power_radius(const PowerNode &power, const std::string &index_var, ComputationContext &context)
ExpressionResult convergence_radius_checked(const std::shared_ptr< SymbolicExpr > &general_coefficient, const std::string &index_var, ComputationContext &context)
static ConvergenceInfoResult convergence_test_impl(const std::shared_ptr< SymbolicExpr > &, const std::string &, ComputationContext &)
ExprResult rational(const Rational &value)
Result< void > validate_series_variable(const std::string &variable, ComputationContext &context, const std::string &operation)
级数引擎模块:收敛性判定,幂级数运算,傅里叶级数,洛朗级数,渐近展开,符号求和与乘积.
符号表达式主类 SymbolicExpr 及其工厂方法,运算接口.