32 const std::string& operation)
34 auto step =
context.consume_steps(1, operation);
41 "power series truncation order must be positive",
51namespace detail::series_support {
63 "series variable name cannot be empty",
76 if (!
value || *
value < std::numeric_limits<int>::min() ||
77 *
value > std::numeric_limits<int>::max()) {
80 return static_cast<int>(*value);
84 const PowerNode& power,
const std::string& var) {
89 auto base = std::dynamic_pointer_cast<const VariableNode>(power.
base());
90 if (base && !base->is_constant() && base->name() == var) {
97 const BigInt product = BigInt(*nested) * BigInt(*
exponent);
98 if (product < BigInt(std::numeric_limits<int>::min()) ||
99 product > BigInt(std::numeric_limits<int>::max())) {
102 return static_cast<int>(*product.try_to_int64());
106 const std::shared_ptr<const SymbolicNode>&
node,
107 const std::string& var)
112 if (std::dynamic_pointer_cast<const NumberNode>(
node)) {
115 if (
auto variable = std::dynamic_pointer_cast<const VariableNode>(
node)) {
117 ? std::optional<int>(1) : std::nullopt;
119 if (
auto power = std::dynamic_pointer_cast<const PowerNode>(
node)) {
122 if (
auto multiply = std::dynamic_pointer_cast<const MultiplyNode>(
node)) {
123 BigInt total_power(0);
124 for (
const auto& operand : multiply->operands()) {
125 if (std::dynamic_pointer_cast<const NumberNode>(operand)) {
132 total_power += BigInt(*power);
134 if (total_power < BigInt(std::numeric_limits<int>::min()) ||
135 total_power > BigInt(std::numeric_limits<int>::max())) {
138 return static_cast<int>(*total_power.try_to_int64());
146 const std::vector<std::shared_ptr<SymbolicExpr>>& coeffs,
148 const std::string&
name)
150 for (
size_t i = 0; i < coeffs.size(); ++i) {
154 name +
" contains a null coefficient at index " + std::to_string(i),
165 const std::vector<std::shared_ptr<SymbolicExpr>>&
a,
166 const std::vector<std::shared_ptr<SymbolicExpr>>&
b) {
169 (
context).limits().max_ast_nodes,
"transform");
170 size_t len = std::max(
a.size(),
b.size());
171 std::vector<std::shared_ptr<SymbolicExpr>> result(len);
172 for (
size_t i = 0; i < len; ++i) {
173 auto ai = (i <
a.size() &&
a[i]) ?
a[i] : SymbolicExpr::number(0);
174 auto bi = (i <
b.size() &&
b[i]) ?
b[i] : SymbolicExpr::number(0);
181 const std::vector<std::shared_ptr<SymbolicExpr>>&
a,
182 const std::vector<std::shared_ptr<SymbolicExpr>>&
b,
int order,
185 (
context).limits().max_ast_nodes,
"transform");
186 const std::string operation =
"power_series_multiply";
187 auto order_check = validate_power_series_order(
order,
context, operation);
200 size_t n =
static_cast<size_t>(
order);
201 std::vector<std::shared_ptr<SymbolicExpr>> result(n, SymbolicExpr::number(0));
202 for (
size_t k = 0; k < n; ++k) {
203 auto step =
context.consume_steps(1, operation);
207 std::vector<std::shared_ptr<const SymbolicNode>> terms;
208 for (
size_t j = 0; j <= k; ++j) {
209 if (j >=
a.size() || (k-j) >=
b.size()) {
212 auto aj =
a[j] ?
a[j] : SymbolicExpr::number(0);
213 auto bkj =
b[k-j] ?
b[k-j] : SymbolicExpr::number(0);
217 result[k] = SymbolicExpr::number(0);
218 }
else if (terms.size() == 1) {
225}
catch (
const CasError& error) {
227}
catch (
const std::bad_alloc&) {
229}
catch (
const std::length_error& error) {
231}
catch (
const std::exception& error) {
236 const std::vector<std::shared_ptr<SymbolicExpr>>&
a,
237 const std::vector<std::shared_ptr<SymbolicExpr>>&
b,
int order) {
244 const std::vector<std::shared_ptr<SymbolicExpr>>& g,
245 std::vector<std::vector<std::shared_ptr<SymbolicExpr>>>& gp,
247 const size_t n = gp.size();
248 gp[0].resize(n, SymbolicExpr::number(0));
249 gp[0][0] = SymbolicExpr::number(1);
251 gp[1].resize(n, SymbolicExpr::number(0));
252 for (
size_t i = 0; i < std::min(g.size(), n); ++i) {
253 gp[1][i] = g[i] ? g[i] : SymbolicExpr::number(0);
256 for (
size_t k = 2; k < n; ++k) {
257 auto step =
context.consume_steps(1, operation);
265 gp[k] = std::move(multiplied.value());
271 const std::vector<std::shared_ptr<SymbolicExpr>>& f,
272 const std::vector<std::shared_ptr<SymbolicExpr>>& g,
int order,
275 (
context).limits().max_ast_nodes,
"transform");
276 const std::string operation =
"power_series_compose";
277 auto order_check = validate_power_series_order(
order,
context, operation);
290 size_t n =
static_cast<size_t>(
order);
291 if (!g.empty() && !g[0]->is_zero()) {
294 "power series composition around zero requires g(0) = 0",
297 std::vector<std::shared_ptr<SymbolicExpr>> result(n, SymbolicExpr::number(0));
298 std::vector<std::vector<std::shared_ptr<SymbolicExpr>>> gp(n);
303 for (
size_t k = 0; k < std::min(f.size(), n); ++k) {
304 auto step =
context.consume_steps(1, operation);
308 auto fk = f[k] ? f[k] : SymbolicExpr::number(0);
312 for (
size_t i = 0; i < n && i < gp[k].size(); ++i)
316}
catch (
const CasError& error) {
318}
catch (
const std::bad_alloc&) {
320}
catch (
const std::length_error& error) {
322}
catch (
const std::exception& error) {
327 const std::vector<std::shared_ptr<SymbolicExpr>>& f,
328 const std::vector<std::shared_ptr<SymbolicExpr>>& g,
int order) {
336 const std::shared_ptr<SymbolicExpr>& body,
const std::string& index,
337 const std::shared_ptr<SymbolicExpr>&
lower,
const std::shared_ptr<SymbolicExpr>&
upper) {
340 (
context).limits().max_ast_nodes,
"transform");
350 return SymbolicExpr::number(0);
352 const BigInt span = uv - lv;
353 if (span < BigInt(100)) {
354 const auto iterations = *span.try_to_uint64() + 1;
355 std::vector<std::shared_ptr<const SymbolicNode>> terms;
357 const BigInt increment(1);
358 for (std::uint64_t iteration = 0; iteration < iterations; ++iteration, k += increment) {
359 auto val = SymbolicExpr::number(k);
364 return SymbolicExpr::number(0);
366 if (terms.size() == 1) {
372 auto k_var = SymbolicExpr::variable(index);
373 if (body->to_string() == k_var->to_string()) {
375 auto u1 = SymbolicExpr::add(
u, SymbolicExpr::number(1));
376 auto su = SymbolicExpr::divide(SymbolicExpr::multiply(
u, u1), SymbolicExpr::number(2));
377 auto lm1 = SymbolicExpr::add(l, SymbolicExpr::number(-1));
378 auto sl = SymbolicExpr::divide(SymbolicExpr::multiply(lm1, l), SymbolicExpr::number(2));
385 const std::shared_ptr<SymbolicExpr>& body,
const std::string& index,
386 const std::shared_ptr<SymbolicExpr>&
lower,
const std::shared_ptr<SymbolicExpr>&
upper) {
389 (
context).limits().max_ast_nodes,
"transform");
399 return SymbolicExpr::number(1);
401 const BigInt span = uv - lv;
402 if (span < BigInt(50)) {
403 const auto iterations = *span.try_to_uint64() + 1;
404 auto result = SymbolicExpr::number(1);
406 const BigInt increment(1);
407 for (std::uint64_t iteration = 0; iteration < iterations; ++iteration, k += increment) {
408 auto val = SymbolicExpr::number(k);
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(T value)
Symbolic integration APIs.
Result< void > validate_power_series_order(int order, ComputationContext &context, const std::string &operation)
static std::optional< int > laurent_power_of_power(const PowerNode &power, const std::string &var)
std::optional< int > integer_value_from_node(const std::shared_ptr< const SymbolicNode > &node)
Result< void > validate_power_series_coefficients(const std::vector< std::shared_ptr< SymbolicExpr > > &coefficients, const std::string &operation, const std::string &name)
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
const std::string & variable
std::shared_ptr< const Node > make_node(Args &&... args)
ComputationContext const std::string & operation
SymbolicNodePtr normalize_node(const SymbolicNodePtr &node, RewriteBudget &budget, const FactsQuery &facts, Domain domain)
std::size_t std::size_t ComputationContext & context
SymbolicNodePtr substitute_node(const SymbolicNodePtr &node, const std::string &variable, const SymbolicNodePtr &replacement, RewriteBudget &budget, const FactsQuery &facts, Domain domain)
std::shared_ptr< SymbolicExpr > symbolic_product(const std::shared_ptr< SymbolicExpr > &body, const std::string &index, const std::shared_ptr< SymbolicExpr > &lower, const std::shared_ptr< SymbolicExpr > &upper)
__attribute__((visibility("default"))) ExprResult function(const std __attribute__((visibility("default"))) ExprResult finite_set(std ExprPtr upper
static Result< void > composition_inner_powers(const std::vector< std::shared_ptr< SymbolicExpr > > &g, std::vector< std::vector< std::shared_ptr< SymbolicExpr > > > &gp, int order, ComputationContext &context, const std::string &operation)
const std::vector< Polynomial< BigInt > > const BigInt ComputationContext & context
PowerSeriesResult power_series_multiply_checked(const std::vector< std::shared_ptr< SymbolicExpr > > &a, const std::vector< std::shared_ptr< SymbolicExpr > > &b, int order, ComputationContext &context)
ExprResult integer(Integer)=delete
bool try_get_integer_value(const std::shared_ptr< const NumberNode > &node, BigInt &value)
std::shared_ptr< SymbolicExpr > symbolic_sum(const std::shared_ptr< SymbolicExpr > &body, const std::string &index, const std::shared_ptr< SymbolicExpr > &lower, const std::shared_ptr< SymbolicExpr > &upper)
const std::vector< FGLMPoly > const MonomialOrder & order
Result< std::vector< std::shared_ptr< SymbolicExpr > > > PowerSeriesResult
__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 const std::shared_ptr< SymbolicExpr > & a
Result< void > validate_power_series_coefficients(const std::vector< std::shared_ptr< SymbolicExpr > > &coefficients, const std::string &operation, const std::string &name)
PowerSeriesResult power_series_compose_checked(const std::vector< std::shared_ptr< SymbolicExpr > > &f, const std::vector< std::shared_ptr< SymbolicExpr > > &g, int order, ComputationContext &context)
const std::string const ExprPtr & value
std::vector< std::shared_ptr< SymbolicExpr > > power_series_add(const std::vector< std::shared_ptr< SymbolicExpr > > &a, const std::vector< std::shared_ptr< SymbolicExpr > > &b)
__attribute__((visibility("default"))) Result< EqvProfile > eqv_profile_from_name(const std const std::string & name
__attribute__((visibility("default"))) VectorCalculusExprResult surface_integral_scalar_checked(const std __attribute__((visibility("default"))) VectorCalculusExprResult surface_integral_scalar_checked(const std __attribute__((visibility("default"))) std const VectorField const std::string & u
级数引擎模块:收敛性判定,幂级数运算,傅里叶级数,洛朗级数,渐近展开,符号求和与乘积.
符号表达式主类 SymbolicExpr 及其工厂方法,运算接口.