LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
rational_polynomial_recognition.cpp
浏览该文件的文档.
3#include <cstdint>
4#include <utility>
5
6namespace LMCAS {
7namespace {
8
9constexpr const char* kOperation = "recognize_rational_polynomial";
10
12public:
14 ~RecursionScope() { context_.leave_recursion(); }
15
16private:
18};
19
21 const std::shared_ptr<const SymbolicNode>& node,
22 const std::string& variable, ComputationContext& context);
23
25 const NumberNode& number, const std::string& variable) {
26 if (std::holds_alternative<BigInt>(number.value())) {
28 Rational(std::get<BigInt>(number.value())), variable));
29 }
30 if (std::holds_alternative<Rational>(number.value())) {
32 std::get<Rational>(number.value()), variable));
33 }
35}
36
38 const AddNode& add, const std::string& variable, ComputationContext& context) {
40 for (const auto& operand : add.operands()) {
41 auto child = recognize_node(operand, variable, context);
42 if (!child) return child;
43 if (!child.value()) {
45 }
46 result = result + *child.value();
47 if (result.coeffs.size() > context.limits().max_expansion_terms) {
49 CasErrc::ResourceLimit, "polynomial term budget exhausted", kOperation);
50 }
51 }
52 return Result<OptionalRationalPolynomial>::success(std::move(result));
53}
54
56 const MultiplyNode& multiply, const std::string& variable, ComputationContext& context) {
57 Polynomial<Rational> result({Rational(1)}, variable);
58 for (const auto& operand : multiply.operands()) {
59 auto child = recognize_node(operand, variable, context);
60 if (!child) return child;
61 if (!child.value()) {
63 }
64 const std::size_t projected_terms = result.is_zero() || child.value()->is_zero()
65 ? 0
66 : result.coeffs.size() + child.value()->coeffs.size() - 1;
67 if (projected_terms > context.limits().max_expansion_terms) {
70 "polynomial expansion term budget exhausted",
72 }
73 result = result * *child.value();
74 }
75 return Result<OptionalRationalPolynomial>::success(std::move(result));
76}
77
79 const PowerNode& power, const std::string& variable, ComputationContext& context) {
80 auto exponent_node = std::dynamic_pointer_cast<const NumberNode>(power.exponent());
81 if (!exponent_node) {
83 }
84
85 BigInt exponent;
86 if (std::holds_alternative<BigInt>(exponent_node->value())) {
87 exponent = std::get<BigInt>(exponent_node->value());
88 } else {
89 const Rational& rational = std::get<Rational>(exponent_node->value());
90 if (!rational.is_integer()) {
92 }
93 exponent = rational.to_bigint();
94 }
95
96 auto exponent_value = exponent.try_to_int64();
97 if (!exponent_value || *exponent_value <= 0) {
99 }
100 if (static_cast<std::uint64_t>(*exponent_value) >=
101 context.limits().max_expansion_terms) {
104 "polynomial exponent exceeds the expansion term budget",
105 kOperation);
106 }
107
108 auto base = recognize_node(power.base(), variable, context);
109 if (!base) return base;
110 if (!base.value()) {
112 }
113
114 Polynomial<Rational> result({Rational(1)}, variable);
115 for (std::int64_t i = 0; i < *exponent_value; ++i) {
116 auto step = context.consume_steps(1, kOperation);
117 if (!step) return Result<OptionalRationalPolynomial>::failure(step.error());
118 const std::size_t projected_terms = result.is_zero() || base.value()->is_zero()
119 ? 0
120 : result.coeffs.size() + base.value()->coeffs.size() - 1;
121 if (projected_terms > context.limits().max_expansion_terms) {
124 "polynomial expansion term budget exhausted",
125 kOperation);
126 }
127 result = result * *base.value();
128 }
129 return Result<OptionalRationalPolynomial>::success(std::move(result));
130}
131
133 const std::shared_ptr<const SymbolicNode>& node,
134 const std::string& variable,
136 auto entered = context.enter_recursion(kOperation);
137 if (!entered) return Result<OptionalRationalPolynomial>::failure(entered.error());
138 RecursionScope scope(context);
139
140 if (!node) {
143 "polynomial recognition encountered a null AST node",
144 kOperation);
145 }
146
147 if (auto number = std::dynamic_pointer_cast<const NumberNode>(node)) {
148 return recognize_number(*number, variable);
149 }
150 if (auto symbol = std::dynamic_pointer_cast<const VariableNode>(node)) {
151 if (symbol->is_constant() || symbol->name() != variable) {
153 }
155 Polynomial<Rational>({Rational(0), Rational(1)}, variable));
156 }
157 if (auto add = std::dynamic_pointer_cast<const AddNode>(node)) {
159 }
160 if (auto multiply = std::dynamic_pointer_cast<const MultiplyNode>(node)) {
161 return recognize_product(*multiply, variable, context);
162 }
163 if (auto power = std::dynamic_pointer_cast<const PowerNode>(node)) {
164 return recognize_power(*power, variable, context);
165 }
167}
168
169}
170
172 const SymbolicExpr& expression,
173 const std::string& variable,
175 if (!LMCAS::detail::node(expression)) {
177 CasErrc::InvalidArgument, "expression cannot be null", kOperation);
178 }
179 if (variable.empty()) {
181 CasErrc::InvalidArgument, "polynomial variable cannot be empty", kOperation);
182 }
183 return recognize_node(LMCAS::detail::node(expression), variable, context);
184}
185
186}
加法节点,表示多个操作数的求和。
乘法节点,表示多个操作数的乘积。
const std::variant< BigInt, Rational > & value() const noexcept
一元多项式模板类
std::vector< CoeffType > coeffs
系数数组,coeffs[i] 为 x^i 的系数
幂运算节点,表示 base^exponent。
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)
Result< OptionalRationalPolynomial > recognize_product(const MultiplyNode &multiply, const std::string &variable, ComputationContext &context)
Result< OptionalRationalPolynomial > recognize_node(const std::shared_ptr< const SymbolicNode > &node, const std::string &variable, ComputationContext &context)
Result< OptionalRationalPolynomial > recognize_number(const NumberNode &number, const std::string &variable)
Result< OptionalRationalPolynomial > recognize_sum(const AddNode &add, const std::string &variable, ComputationContext &context)
Result< OptionalRationalPolynomial > recognize_power(const PowerNode &power, const std::string &variable, ComputationContext &context)
const SymbolicNodePtr & node(const ::LMCAS::SymbolicExpr &expression) noexcept
const std::string & variable
const std::vector< Polynomial< BigInt > > const BigInt ComputationContext & context
ExprResult add(const ExprPtr &lhs, const ExprPtr &rhs, ComputationContext &context)
const ExprPtr & exponent
Result< OptionalRationalPolynomial > recognize_rational_polynomial(const SymbolicExpr &expression, const std::string &variable, ComputationContext &context)
ExprResult rational(const Rational &value)
符号表达式与一元多项式的转换。
内部 AST 定义。