LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
arithmetic.hpp
浏览该文件的文档.
1/** @file internal/symbolic_ast/arithmetic.hpp */
2#pragma once
4
5namespace LMCAS {
6
7/**
8 * @brief 变量节点,表示一个符号变量。
9 */
10class VariableNode : public SymbolicNode {
11private:
13
14 const std::string name_;
15 const bool constant_;
16
17 explicit VariableNode(std::string n, bool constant = false)
18 : name_(std::move(n)), constant_(constant) {
19 if (constant_ && name_ != "pi" && name_ != "π" &&
20 name_ != "e" && name_ != "phi") {
21 throw std::invalid_argument("unknown mathematical constant");
22 }
23 }
24
25public:
26 const std::string& name() const noexcept { return name_; }
27 bool is_constant() const noexcept { return constant_; }
28
29 int type_priority() const override { return 10; }
30
31protected:
32 std::size_t compute_hash() const override {
33 std::size_t hash = std::hash<std::string>{}(name_);
35 return hash;
36 }
37
38 int compare_same_type(const SymbolicNode& other) const override {
39 const auto& o = static_cast<const VariableNode&>(other);
40 const int cmp = name_.compare(o.name_);
41 if (cmp != 0) return cmp;
42 return constant_ == o.constant_ ? 0 : (constant_ ? 1 : -1);
43 }
44
45public:
46 void accept(LMCAS::detail::SymbolicVisitor& visitor) const override { LMCAS::detail::SymbolicVisitor::DepthGuard guard(visitor); visitor.visit(*this); }
47 std::shared_ptr<const SymbolicNode> clone() const override { return LMCAS::detail::make_node<VariableNode>(name_, constant_); }
48};
49
50/**
51 * @brief 加法节点,表示多个操作数的求和。
52 *
53 * 构造时自动扁平化嵌套的 AddNode,并按规范顺序排序操作数。
54 */
55class AddNode : public SymbolicNode {
56private:
58
59 static std::vector<std::shared_ptr<const SymbolicNode>> normalize_operands(
60 std::vector<std::shared_ptr<const SymbolicNode>> ops) {
61 if (ops.empty()) {
62 throw std::invalid_argument("AddNode requires at least one operand");
63 }
64 std::vector<std::shared_ptr<const SymbolicNode>> flattened;
65 for (const auto& op : ops) {
66 if (!op) {
67 throw std::invalid_argument("AddNode operand cannot be null");
68 }
69 if (auto add = std::dynamic_pointer_cast<const AddNode>(op)) {
70 flattened.insert(flattened.end(), add->operands_.begin(), add->operands_.end());
71 } else {
72 flattened.push_back(op);
73 }
74 }
75 std::sort(flattened.begin(), flattened.end(), [](const auto& a, const auto& b) {
76 bool a_num = a->is_number();
77 bool b_num = b->is_number();
78 if (a_num != b_num) return !a_num;
79 return a->compare(*b) < 0;
80 });
81 return flattened;
82 }
83
84 const std::vector<std::shared_ptr<const SymbolicNode>> operands_;
85
86 explicit AddNode(std::vector<std::shared_ptr<const SymbolicNode>> ops)
87 : operands_(normalize_operands(std::move(ops))) {}
88
89public:
90 const std::vector<std::shared_ptr<const SymbolicNode>>& operands() const noexcept {
91 return operands_;
92 }
93
94 int type_priority() const override { return 5; }
95
96protected:
97 std::size_t compute_hash() const override {
98 std::size_t seed = 0;
100 for (const auto& op : operands_) {
101 hash_combine(seed, op->hash());
102 }
103 return seed;
104 }
105
106 int compare_same_type(const SymbolicNode& other) const override {
107 const auto& o = static_cast<const AddNode&>(other);
108 if (operands_.size() != o.operands_.size()) {
109 return operands_.size() < o.operands_.size() ? -1 : 1;
110 }
111 for (size_t i = 0; i < operands_.size(); ++i) {
112 int cmp = operands_[i]->compare(*o.operands_[i]);
113 if (cmp != 0) return cmp;
114 }
115 return 0;
116 }
117
118public:
119 void accept(LMCAS::detail::SymbolicVisitor& visitor) const override { LMCAS::detail::SymbolicVisitor::DepthGuard guard(visitor); visitor.visit(*this); }
120 std::shared_ptr<const SymbolicNode> clone() const override {
121 std::vector<std::shared_ptr<const SymbolicNode>> new_ops;
122 new_ops.reserve(operands_.size());
123 for (const auto& op : operands_) new_ops.push_back(op->clone());
124 return LMCAS::detail::make_node<AddNode>(std::move(new_ops));
125 }
126};
127
128/**
129 * @brief 乘法节点,表示多个操作数的乘积。
130 *
131 * 构造时扁平化嵌套乘积;纯标量因子按规范顺序排序,
132 * 包含矩阵的乘积保留因子的输入顺序。
133 */
135private:
137
138 static bool contains_matrix(const SymbolicNode& node);
139 static bool compare_operands(
140 const std::shared_ptr<const SymbolicNode>& lhs,
141 const std::shared_ptr<const SymbolicNode>& rhs) {
142 return lhs->compare(*rhs) < 0;
143 }
144
145 static std::vector<std::shared_ptr<const SymbolicNode>> normalize_operands(
146 std::vector<std::shared_ptr<const SymbolicNode>> ops) {
147 if (ops.empty()) {
148 throw std::invalid_argument("MultiplyNode requires at least one operand");
149 }
150 std::vector<std::shared_ptr<const SymbolicNode>> flattened;
151 for (const auto& op : ops) {
152 if (!op) {
153 throw std::invalid_argument("MultiplyNode operand cannot be null");
154 }
155 if (auto mul = std::dynamic_pointer_cast<const MultiplyNode>(op)) {
156 flattened.insert(flattened.end(), mul->operands_.begin(), mul->operands_.end());
157 } else {
158 flattened.push_back(op);
159 }
160 }
161 const bool scalar_product = std::none_of(
162 flattened.begin(), flattened.end(),
163 [](const auto& factor) { return contains_matrix(*factor); });
164 if (scalar_product) {
165 std::sort(
166 flattened.begin(), flattened.end(), compare_operands);
167 }
168 return flattened;
169 }
170
171 const std::vector<std::shared_ptr<const SymbolicNode>> operands_;
172
173 explicit MultiplyNode(std::vector<std::shared_ptr<const SymbolicNode>> ops)
174 : operands_(normalize_operands(std::move(ops))) {}
175
176public:
177 const std::vector<std::shared_ptr<const SymbolicNode>>& operands() const noexcept {
178 return operands_;
179 }
180
181 int type_priority() const override { return 4; }
182
183protected:
184 std::size_t compute_hash() const override {
185 std::size_t seed = 0;
187 for (const auto& op : operands_) {
188 hash_combine(seed, op->hash());
189 }
190 return seed;
191 }
192
193 int compare_same_type(const SymbolicNode& other) const override {
194 const auto& o = static_cast<const MultiplyNode&>(other);
195 if (operands_.size() != o.operands_.size()) {
196 return operands_.size() < o.operands_.size() ? -1 : 1;
197 }
198 for (size_t i = 0; i < operands_.size(); ++i) {
199 int cmp = operands_[i]->compare(*o.operands_[i]);
200 if (cmp != 0) return cmp;
201 }
202 return 0;
203 }
204
205public:
206 void accept(LMCAS::detail::SymbolicVisitor& visitor) const override { LMCAS::detail::SymbolicVisitor::DepthGuard guard(visitor); visitor.visit(*this); }
207 std::shared_ptr<const SymbolicNode> clone() const override {
208 std::vector<std::shared_ptr<const SymbolicNode>> new_ops;
209 new_ops.reserve(operands_.size());
210 for (const auto& op : operands_) new_ops.push_back(op->clone());
211 return LMCAS::detail::make_node<MultiplyNode>(std::move(new_ops));
212 }
213};
214
215/**
216 * @brief 幂运算节点,表示 base^exponent。
217 */
218class PowerNode : public SymbolicNode {
219private:
221
222 const std::shared_ptr<const SymbolicNode> base_;
223 const std::shared_ptr<const SymbolicNode> exponent_;
224
225 PowerNode(std::shared_ptr<const SymbolicNode> b, std::shared_ptr<const SymbolicNode> e)
226 : base_(std::move(b)), exponent_(std::move(e)) {
227 if (!base_ || !exponent_) {
228 throw std::invalid_argument("PowerNode base and exponent cannot be null");
229 }
230 }
231
232public:
233 const std::shared_ptr<const SymbolicNode>& base() const noexcept { return base_; }
234 const std::shared_ptr<const SymbolicNode>& exponent() const noexcept {
235 return exponent_;
236 }
237
238 int type_priority() const override { return 0; }
239
240protected:
241 std::size_t compute_hash() const override {
242 std::size_t seed = 0;
244 hash_combine(seed, base_->hash());
245 hash_combine(seed, exponent_->hash());
246 return seed;
247 }
248
249 int compare_same_type(const SymbolicNode& other) const override {
250 const auto& o = static_cast<const PowerNode&>(other);
251
252 int cmp_exp = exponent_->compare(*o.exponent_);
253 if (cmp_exp != 0) return cmp_exp > 0 ? -1 : 1;
254
255 return base_->compare(*o.base_);
256 }
257
258public:
259 void accept(LMCAS::detail::SymbolicVisitor& visitor) const override { LMCAS::detail::SymbolicVisitor::DepthGuard guard(visitor); visitor.visit(*this); }
260 std::shared_ptr<const SymbolicNode> clone() const override {
261 return LMCAS::detail::make_node<PowerNode>(base_->clone(), exponent_->clone());
262 }
263};
264
265}
std::shared_ptr< const SymbolicNode > clone() const override
const std::vector< std::shared_ptr< const SymbolicNode > > operands_
int type_priority() const override
std::size_t compute_hash() const override
static std::vector< std::shared_ptr< const SymbolicNode > > normalize_operands(std::vector< std::shared_ptr< const SymbolicNode > > ops)
int compare_same_type(const SymbolicNode &other) const override
const std::vector< std::shared_ptr< const SymbolicNode > > & operands() const noexcept
void accept(LMCAS::detail::SymbolicVisitor &visitor) const override
AddNode(std::vector< std::shared_ptr< const SymbolicNode > > ops)
static std::vector< std::shared_ptr< const SymbolicNode > > normalize_operands(std::vector< std::shared_ptr< const SymbolicNode > > ops)
std::size_t compute_hash() const override
MultiplyNode(std::vector< std::shared_ptr< const SymbolicNode > > ops)
std::shared_ptr< const SymbolicNode > clone() const override
int type_priority() const override
int compare_same_type(const SymbolicNode &other) const override
const std::vector< std::shared_ptr< const SymbolicNode > > & operands() const noexcept
static bool compare_operands(const std::shared_ptr< const SymbolicNode > &lhs, const std::shared_ptr< const SymbolicNode > &rhs)
static bool contains_matrix(const SymbolicNode &node)
const std::vector< std::shared_ptr< const SymbolicNode > > operands_
void accept(LMCAS::detail::SymbolicVisitor &visitor) const override
const std::shared_ptr< const SymbolicNode > exponent_
int type_priority() const override
std::size_t compute_hash() const override
std::shared_ptr< const SymbolicNode > clone() const override
void accept(LMCAS::detail::SymbolicVisitor &visitor) const override
PowerNode(std::shared_ptr< const SymbolicNode > b, std::shared_ptr< const SymbolicNode > e)
const std::shared_ptr< const SymbolicNode > base_
int compare_same_type(const SymbolicNode &other) const override
const std::shared_ptr< const SymbolicNode > & exponent() const noexcept
const std::shared_ptr< const SymbolicNode > & base() const noexcept
std::size_t hash() const
获取节点哈希值(带缓存).
SymbolicNode()=default
bool is_constant() const noexcept
void accept(LMCAS::detail::SymbolicVisitor &visitor) const override
int type_priority() const override
VariableNode(std::string n, bool constant=false)
std::shared_ptr< const SymbolicNode > clone() const override
int compare_same_type(const SymbolicNode &other) const override
const std::string & name() const noexcept
const std::string name_
std::size_t compute_hash() const override
virtual void visit(const NumberNode &node)=0
std::shared_ptr< const Node > make_node(Args &&... args)
ExprResult e()
void hash_combine(std::size_t &seed, std::size_t value)
将一个哈希值混合到种子中,用于组合多个字段的哈希.
ExprResult mul(const ExprPtr &lhs, const ExprPtr &rhs, ComputationContext &context)
ExprResult add(const ExprPtr &lhs, const ExprPtr &rhs, ComputationContext &context)
const MultiPoly & b
const ExprPtr RelationOp op
__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
const ExprPtr & rhs