6bool LimitVisitor::is_limit_variable(
const std::shared_ptr<const SymbolicNode>& node)
const {
7 auto variable = std::dynamic_pointer_cast<const VariableNode>(node);
11bool LimitVisitor::is_positive_variable_power(
const std::shared_ptr<const SymbolicNode>& node)
const {
12 if (is_limit_variable(node)) {
15 auto power = std::dynamic_pointer_cast<const PowerNode>(node);
19 auto exponent = std::dynamic_pointer_cast<const NumberNode>(power->exponent());
20 return is_limit_variable(power->base()) &&
exponent &&
exponent->is_positive();
23bool LimitVisitor::is_variable_reciprocal(
const std::shared_ptr<const SymbolicNode>& node)
const {
24 auto power = std::dynamic_pointer_cast<const PowerNode>(node);
25 if (!power || !is_limit_variable(power->base())) {
28 auto exponent = std::dynamic_pointer_cast<const NumberNode>(power->exponent());
32bool LimitVisitor::is_log_variable(
const std::shared_ptr<const SymbolicNode>& node)
const {
33 auto function = std::dynamic_pointer_cast<const FunctionNode>(node);
41 return is_limit_variable(
function->arguments()[0]);
44bool LimitVisitor::logarithmic_zero_product(
const MultiplyNode& node)
const {
45 auto number = std::dynamic_pointer_cast<const NumberNode>(
point);
49 if (!number->is_zero() ||
direction !=
"+") {
52 bool has_power =
false;
53 bool has_logarithm =
false;
54 for (
const auto& operand :
node.operands()) {
55 if (!is_positive_variable_power(operand) && !is_log_variable(operand) &&
56 !std::dynamic_pointer_cast<const NumberNode>(operand)) {
return false; }
57 has_power = has_power || is_positive_variable_power(operand);
58 has_logarithm = has_logarithm || is_log_variable(operand);
60 return has_power && has_logarithm;
63std::shared_ptr<const SymbolicNode> LimitVisitor::one_plus_term(
const AddNode& node)
const {
65 std::vector<std::shared_ptr<const SymbolicNode>> terms;
66 for (
const auto& operand :
node.operands()) {
67 if (!has_one && operand->is_one()) has_one =
true;
68 else terms.push_back(operand);
70 if (!has_one || terms.empty())
return nullptr;
74std::shared_ptr<const SymbolicNode> LimitVisitor::variable_fraction_numerator(
75 const std::shared_ptr<const SymbolicNode>& node)
const {
76 if (is_variable_reciprocal(node)) {
79 auto product = std::dynamic_pointer_cast<const MultiplyNode>(node);
83 bool has_denominator =
false;
84 std::vector<std::shared_ptr<const SymbolicNode>> factors;
85 for (
const auto& operand : product->operands()) {
86 if (!has_denominator && is_variable_reciprocal(operand)) has_denominator =
true;
87 else factors.push_back(operand);
89 if (!has_denominator) {
92 return make_product_or_one(factors);
95std::optional<std::shared_ptr<const SymbolicNode>> LimitVisitor::logarithmic_remaining_limit(
97 const std::shared_ptr<const SymbolicNode>& numerator) {
98 std::vector<std::shared_ptr<const SymbolicNode>> values{numerator};
99 bool has_variable =
false;
100 for (
const auto& operand :
node.operands()) {
101 if (operand.get() == logarithm) {
104 if (!has_variable && is_limit_variable(operand)) {
108 auto value = eval_limit(operand);
112 values.push_back(
value);
118 make_product_or_one(values)->accept(norm);
119 return norm.get_result();
122bool LimitVisitor::logarithmic_product_limit(
const MultiplyNode& node) {
123 for (
const auto& operand :
node.operands()) {
124 auto function = std::dynamic_pointer_cast<const FunctionNode>(operand);
132 auto sum = std::dynamic_pointer_cast<const AddNode>(
function->arguments()[0]);
136 auto small_term = one_plus_term(*sum);
140 if (!is_zero_limit(eval_limit(small_term)))
continue;
141 auto numerator = variable_fraction_numerator(small_term);
145 auto value = logarithmic_remaining_limit(node, operand.get(), numerator);
155 for (
const auto& operand :
node.operands()) {
156 if (operand.get() == exponential) {
159 if (!polynomial_logarithmic_bound(operand)) {
166bool LimitVisitor::decaying_exponential_product(
const MultiplyNode& node) {
167 for (
const auto& operand :
node.operands()) {
168 auto function = std::dynamic_pointer_cast<const FunctionNode>(operand);
173 auto exponent_limit = eval_limit(
function->arguments()[0]);
174 if (!is_neg_inf(exponent_limit)) {
177 if (proves_superlogarithmic_magnitude(
function->arguments()[0]) &&
178 has_slower_factors(node, operand.get())) {
185std::shared_ptr<const SymbolicNode> LimitVisitor::matching_reciprocal(
186 const MultiplyNode& node,
const std::shared_ptr<const SymbolicNode>& argument)
const {
187 for (
const auto& operand :
node.operands()) {
188 auto power = std::dynamic_pointer_cast<const PowerNode>(operand);
192 auto exponent = std::dynamic_pointer_cast<const NumberNode>(power->exponent());
193 if (!
exponent || !power->base() || power->base()->compare(*argument) != 0) {
196 if (get_numeric_value(
exponent) == -1.0) {
203std::shared_ptr<const SymbolicNode> LimitVisitor::trigonometric_remaining_limit(
205 std::vector<std::shared_ptr<const SymbolicNode>> values;
206 for (
const auto& operand :
node.operands()) {
207 if (operand.get() ==
function || operand.get() == reciprocal) {
210 auto value = eval_limit(operand);
214 values.push_back(
value);
218 make_product_or_one(values)->accept(norm);
219 return norm.get_result();
222bool LimitVisitor::trigonometric_product_limit(
const MultiplyNode& node) {
223 for (
const auto& operand :
node.operands()) {
224 auto function = std::dynamic_pointer_cast<const FunctionNode>(operand);
232 const auto& argument =
function->arguments()[0];
233 auto reciprocal = matching_reciprocal(node, argument);
237 auto argument_limit = eval_limit(argument);
238 if (is_zero_limit(argument_limit)) {
239 result = trigonometric_remaining_limit(node, operand.get(), reciprocal.get());
240 return result !=
nullptr;
统一规范化数值幂。 精确操作数保留整数和有理数运算;近似求根要求指数精确等于 1/2。 有限浮点幂直接折叠,省去倒数中间值;非有限结果保留幂表达式。
极限访问器,通过代入和 L'Hôpital 法则计算极限。
const SymbolicNodePtr & node(const ::LMCAS::SymbolicExpr &expression) noexcept
const FactsQuery & no_facts() noexcept
std::shared_ptr< const Node > make_node(Args &&... args)
const std::string const LimitExprPtr & point
const std::string & variable
const std::string const LimitExprPtr LimitDirection direction
const std::string const ExprPtr & value
ExprResult function(const std::string &name, std::vector< ExprPtr > arguments)