LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
special_forms.hpp
浏览该文件的文档.
1/** @file internal/symbolic_ast/special_forms.hpp */
2#pragma once
3
5#include "limit_direction.hpp"
7
8#include <cstddef>
9
10
11namespace LMCAS {
12class LimitNode : public SymbolicNode {
13private:
14 template <typename Node, typename... Args>
15 friend std::shared_ptr<const Node>
16 LMCAS::detail::make_node(Args&&... args);
17
18 const std::shared_ptr<const SymbolicNode> body_;
19 const std::string variable_;
20 const std::shared_ptr<const SymbolicNode> point_;
22
23 LimitNode(std::shared_ptr<const SymbolicNode> body,
24 std::string variable,
25 std::shared_ptr<const SymbolicNode> point,
27 : body_(std::move(body)), variable_(std::move(variable)),
28 point_(std::move(point)), direction_(direction) {
29 if (!body_ || !point_) {
30 throw std::invalid_argument("limit body and point cannot be null");
31 }
32 if (variable_.empty()) {
33 throw std::invalid_argument("limit variable cannot be empty");
34 }
35 }
36
37public:
38 const auto& body() const noexcept { return body_; }
39 const std::string& variable() const noexcept { return variable_; }
40 const auto& point() const noexcept { return point_; }
41 LimitDirection direction() const noexcept { return direction_; }
42 int type_priority() const override { return 109; }
43
44protected:
45 std::size_t compute_hash() const override {
46 std::size_t seed = static_cast<std::size_t>(type_priority());
47 hash_combine(seed, body_->hash());
48 hash_combine(seed, std::hash<std::string>{}(variable_));
49 hash_combine(seed, point_->hash());
50 hash_combine(seed, static_cast<std::size_t>(direction_));
51 return seed;
52 }
53
54 int compare_same_type(const SymbolicNode& other) const override {
55 const auto& limit = static_cast<const LimitNode&>(other);
56 int comparison = variable_.compare(limit.variable_);
57 if (comparison != 0) return comparison;
58 if (direction_ != limit.direction_) {
59 return static_cast<int>(direction_) < static_cast<int>(limit.direction_) ? -1 : 1;
60 }
61 comparison = point_->compare(*limit.point_);
62 return comparison != 0 ? comparison : body_->compare(*limit.body_);
63 }
64
65public:
66 void accept(LMCAS::detail::SymbolicVisitor& visitor) const override {
68 visitor.visit(*this);
69 }
70
71 std::shared_ptr<const SymbolicNode> clone() const override {
73 body_->clone(), variable_, point_->clone(), direction_);
74 }
75};
76class RootOfNode : public SymbolicNode {
77private:
78 template <typename Node, typename... Args>
79 friend std::shared_ptr<const Node>
80 LMCAS::detail::make_node(Args&&... args);
81
83 const std::string display_variable_;
84
85 explicit RootOfNode(
87 std::string display_variable = "_root")
88 : id_(std::move(id)),
89 display_variable_(std::move(display_variable)) {
90 if (id_.polynomial.degree() <= 0 ||
91 id_.index >= static_cast<std::size_t>(id_.polynomial.degree()) ||
92 display_variable_.empty()) {
93 throw std::invalid_argument("RootOf identity is invalid");
94 }
95 }
96
97public:
98 const LMCAS::detail::ExactRootId& exact_id() const noexcept { return id_; }
99 std::size_t index() const noexcept { return id_.index; }
100 const std::string& variable() const noexcept {
101 return display_variable_;
102 }
103 std::shared_ptr<const SymbolicNode> polynomial() const {
104 const auto variable_node =
106 std::vector<std::shared_ptr<const SymbolicNode>> terms;
107 for (std::size_t degree = 0;
108 degree < id_.polynomial.coeffs.size(); ++degree) {
109 const auto& coefficient = id_.polynomial.coeffs[degree];
110 if (coefficient == Rational(0)) continue;
111 auto coefficient_node =
113 if (degree == 0) {
114 terms.push_back(coefficient_node);
115 continue;
116 }
117 auto variable_power = degree == 1
118 ? variable_node
120 variable_node,
121 SymbolicFactory::create_number(BigInt(degree)));
122 terms.push_back(
123 coefficient == Rational(1)
124 ? variable_power
126 {coefficient_node, variable_power}));
127 }
128 return SymbolicFactory::create_add(std::move(terms));
129 }
130 int type_priority() const override { return 110; }
131
132protected:
133 std::size_t compute_hash() const override {
134 std::size_t seed = static_cast<std::size_t>(type_priority());
135 hash_combine(seed, id_.hash());
136 return seed;
137 }
138
139 int compare_same_type(const SymbolicNode& other) const override {
140 return id_.compare(static_cast<const RootOfNode&>(other).id_);
141 }
142
143public:
144 void accept(LMCAS::detail::SymbolicVisitor& visitor) const override {
146 visitor.visit(*this);
147 }
148
149 std::shared_ptr<const SymbolicNode> clone() const override {
152 }
153};
154
155}
int type_priority() const override
const std::string & variable() const noexcept
const std::shared_ptr< const SymbolicNode > point_
const LimitDirection direction_
std::size_t compute_hash() const override
int compare_same_type(const SymbolicNode &other) const override
LimitNode(std::shared_ptr< const SymbolicNode > body, std::string variable, std::shared_ptr< const SymbolicNode > point, LimitDirection direction)
const std::string variable_
const auto & point() const noexcept
const auto & body() const noexcept
std::shared_ptr< const SymbolicNode > clone() const override
void accept(LMCAS::detail::SymbolicVisitor &visitor) const override
const std::shared_ptr< const SymbolicNode > body_
LimitDirection direction() const noexcept
std::vector< CoeffType > coeffs
系数数组,coeffs[i] 为 x^i 的系数
int degree() const
获取多项式的次数
std::size_t compute_hash() const override
const std::string display_variable_
int type_priority() const override
const std::string & variable() const noexcept
std::shared_ptr< const SymbolicNode > clone() const override
void accept(LMCAS::detail::SymbolicVisitor &visitor) const override
std::size_t index() const noexcept
RootOfNode(LMCAS::detail::ExactRootId id, std::string display_variable="_root")
const LMCAS::detail::ExactRootId id_
const LMCAS::detail::ExactRootId & exact_id() const noexcept
int compare_same_type(const SymbolicNode &other) const override
std::shared_ptr< const SymbolicNode > polynomial() const
static std::shared_ptr< const SymbolicNode > create_add(std::vector< std::shared_ptr< const SymbolicNode > > ops, detail::RewriteBudget *budget=nullptr)
创建加法节点,自动扁平化嵌套加法并消除零项.
static std::shared_ptr< const SymbolicNode > create_variable(const std::string &name)
static std::shared_ptr< const SymbolicNode > create_power(std::shared_ptr< const SymbolicNode > base, std::shared_ptr< const SymbolicNode > exponent)
创建幂运算节点,自动处理指数为 0/1 及底数为 0/1 的情况.
static std::shared_ptr< const SymbolicNode > create_multiply(std::vector< std::shared_ptr< const SymbolicNode > > ops, detail::RewriteBudget *budget=nullptr)
创建乘法节点,自动扁平化嵌套乘法并消除单位元.
static std::shared_ptr< const SymbolicNode > create_number(const ::LMCAS::BigInt &v)
SymbolicNode()=default
virtual void visit(const NumberNode &node)=0
std::shared_ptr< const Node > make_node(Args &&... args)
void hash_combine(std::size_t &seed, std::size_t value)
将一个哈希值混合到种子中,用于组合多个字段的哈希.
LimitDirection
Direction from which a limit approaches its point.
Polynomial< Rational > polynomial
int compare(const ExactRootId &other) const