LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
print_visitor.cpp
浏览该文件的文档.
2#include <array>
3
4namespace LMCAS {
5
6PrintVisitor::Precedence PrintVisitor::precedence(const SymbolicNode& node) {
7 if (dynamic_cast<const AddNode*>(&node)) { return Precedence::Add; }
8 if (dynamic_cast<const MultiplyNode*>(&node)) { return Precedence::Multiply; }
9 if (dynamic_cast<const PowerNode*>(&node)) { return Precedence::Power; }
10 if (dynamic_cast<const MembershipNode*>(&node)) { return Precedence::Membership; }
11 if (const auto* relation = dynamic_cast<const RelationalNode*>(&node)) {
12 return relation->op() == RelationOp::EQ || relation->op() == RelationOp::NEQ
13 ? Precedence::Equality : Precedence::Relation;
14 }
15 if (const auto* number = dynamic_cast<const NumberNode*>(&node)) {
16 if (const auto* rational = std::get_if<Rational>(&number->value())) {
17 if (!rational->is_integer()) { return Precedence::Multiply; }
18 if (*rational < Rational(0)) { return Precedence::Unary; }
19 }
20 if (const auto* integer = std::get_if<BigInt>(&number->value())) {
21 if (integer->is_negative()) { return Precedence::Unary; }
22 }
23 }
24 return Precedence::Atom;
25}
26
27void PrintVisitor::print_operand(const SymbolicNode& node, Precedence parent,
28 bool parenthesize_equal) {
29 const auto child = precedence(node);
30 const bool parentheses = child < parent ||
31 (parenthesize_equal && child == parent) ||
32 (parent == Precedence::Power && parenthesize_equal && child == Precedence::Unary);
33 if (parentheses) { buffer << "("; }
34 node.accept(*this);
35 if (parentheses) { buffer << ")"; }
36}
37
38void PrintVisitor::visit(const NumberNode& node) {
39 if (std::holds_alternative<BigInt>(node.value())) {
40 buffer << std::get<BigInt>(node.value()).to_string();
41 } else {
42 buffer << std::get<Rational>(node.value()).to_string();
43 }
44}
45
46void PrintVisitor::visit(const VariableNode& node) {
47 buffer << node.name();
48}
49
50void PrintVisitor::visit(const AddNode& node) {
51 if (node.operands().empty()) {
52 buffer << "0";
53 return;
54 }
55 for (size_t i = 0; i < node.operands().size(); ++i) {
56 if (i > 0) buffer << " + ";
57 print_operand(*node.operands()[i], Precedence::Add, true);
58 }
59}
60
61void PrintVisitor::visit(const MultiplyNode& node) {
62 if (node.operands().empty()) {
63 buffer << "1";
64 return;
65 }
66 for (size_t i = 0; i < node.operands().size(); ++i) {
67 if (i > 0) buffer << "*";
68
69 print_operand(*node.operands()[i], Precedence::Multiply, true);
70 }
71}
72
73namespace {
74
76 using Type = FunctionNode::FuncType;
77 static constexpr auto names = [] {
78 std::array<const char*, static_cast<std::size_t>(Type::ComplexArg) + 1> values{};
79 values[static_cast<std::size_t>(Type::Sin)] = "sin";
80 values[static_cast<std::size_t>(Type::Cos)] = "cos";
81 values[static_cast<std::size_t>(Type::Tan)] = "tan";
82 values[static_cast<std::size_t>(Type::Cot)] = "cot";
83 values[static_cast<std::size_t>(Type::Sec)] = "sec";
84 values[static_cast<std::size_t>(Type::Csc)] = "csc";
85 values[static_cast<std::size_t>(Type::ArcSin)] = "asin";
86 values[static_cast<std::size_t>(Type::ArcCos)] = "acos";
87 values[static_cast<std::size_t>(Type::ArcTan)] = "atan";
88 values[static_cast<std::size_t>(Type::Atan2)] = "atan2";
89 values[static_cast<std::size_t>(Type::Sinh)] = "sinh";
90 values[static_cast<std::size_t>(Type::Cosh)] = "cosh";
91 values[static_cast<std::size_t>(Type::Tanh)] = "tanh";
92 values[static_cast<std::size_t>(Type::Ln)] = "ln";
93 values[static_cast<std::size_t>(Type::Log)] = "log";
94 values[static_cast<std::size_t>(Type::Abs)] = "abs";
95 values[static_cast<std::size_t>(Type::Sqrt)] = "sqrt";
96 values[static_cast<std::size_t>(Type::Exp)] = "exp";
97 values[static_cast<std::size_t>(Type::LambertW)] = "lambertw";
98 values[static_cast<std::size_t>(Type::Infinity)] = "inf";
99 values[static_cast<std::size_t>(Type::Erf)] = "erf";
100 values[static_cast<std::size_t>(Type::Ei)] = "Ei";
101 values[static_cast<std::size_t>(Type::Si)] = "Si";
102 values[static_cast<std::size_t>(Type::Ci)] = "Ci";
103 values[static_cast<std::size_t>(Type::Li)] = "Li";
104 values[static_cast<std::size_t>(Type::Max)] = "max";
105 values[static_cast<std::size_t>(Type::Min)] = "min";
106 values[static_cast<std::size_t>(Type::Sgn)] = "sgn";
107 values[static_cast<std::size_t>(Type::Floor)] = "floor";
108 values[static_cast<std::size_t>(Type::Ceil)] = "ceil";
109 values[static_cast<std::size_t>(Type::Round)] = "round";
110 values[static_cast<std::size_t>(Type::RealPart)] = "re";
111 values[static_cast<std::size_t>(Type::ImagPart)] = "im";
112 values[static_cast<std::size_t>(Type::Conjugate)] = "conj";
113 values[static_cast<std::size_t>(Type::ComplexAbs)] = "cabs";
114 values[static_cast<std::size_t>(Type::ComplexArg)] = "carg";
115 return values;
116 }();
117 const auto index = static_cast<std::size_t>(type);
118 return index < names.size() && names[index] ? names[index] : "";
119}
120
121}
122
123void PrintVisitor::visit(const PowerNode& node) {
124 print_operand(*node.base(), Precedence::Power, true);
125 buffer << "^";
126 print_operand(*node.exponent(), Precedence::Power);
127}
128
129void PrintVisitor::visit(const FunctionNode& node) {
131 buffer << "inf";
132 return;
133 }
134
135 buffer << function_name(node.type());
136 buffer << "(";
137 for (size_t i = 0; i < node.arguments().size(); ++i) {
138 node.arguments()[i]->accept(*this);
139 if (i < node.arguments().size() - 1) {
140 buffer << ", ";
141 }
142 }
143 buffer << ")";
144}
145
146void PrintVisitor::visit(const UninterpretedFunctionNode& node) {
147 buffer << node.name() << "(";
148 for (std::size_t index = 0; index < node.arguments().size(); ++index) {
149 if (index != 0) buffer << ", ";
150 node.arguments()[index]->accept(*this);
151 }
152 buffer << ")";
153}
154
155void PrintVisitor::visit(const MatrixNode& node) {
156 buffer << "[";
157 for (size_t i = 0; i < node.rows(); ++i) {
158 buffer << "[";
159 for (size_t j = 0; j < node.cols(); ++j) {
160 auto element = node.get(i, j);
161 if (element) {
162 element->accept(*this);
163 } else {
164 buffer << "0";
165 }
166 if (j < node.cols() - 1) {
167 buffer << ", ";
168 }
169 }
170 buffer << "]";
171 if (i < node.rows() - 1) {
172 buffer << ", ";
173 }
174 }
175 buffer << "]";
176}
177
178void PrintVisitor::visit(const RelationalNode& node) {
179 print_operand(*node.left(), precedence(node), true);
180 buffer << " " << (node.op() == RelationOp::EQ ? "==" :
182 print_operand(*node.right(), precedence(node), true);
183}
184
185void PrintVisitor::visit(const LogicalNode& node) {
186 if (node.op() == LogicalNode::Op::Not) {
187 buffer << "(not ";
188 print_operand(*node.left(), Precedence::Not, true);
189 buffer << ")";
190 } else if (node.op() == LogicalNode::Op::Implies) {
191 buffer << "(";
192 node.left()->accept(*this);
193 buffer << " implies ";
194 node.right()->accept(*this);
195 buffer << ")";
196 } else {
197 buffer << "(";
198 print_operand(*node.left(), node.op() == LogicalNode::Op::And
199 ? Precedence::And : Precedence::Or, true);
200 buffer << " " << (node.op() == LogicalNode::Op::And ? "and" : "or") << " ";
201 print_operand(*node.right(), node.op() == LogicalNode::Op::And
202 ? Precedence::And : Precedence::Or, true);
203 buffer << ")";
204 }
205}
206
207void PrintVisitor::visit(const PiecewiseNode& node) {
208 buffer << "piecewise(";
209 for (size_t i = 0; i < node.branches().size(); ++i) {
210 if (i > 0) buffer << ", ";
211 node.branches()[i].expression->accept(*this);
212 buffer << " if ";
213 node.branches()[i].condition->accept(*this);
214 }
215 if (node.default_expr()) {
216 buffer << ", default: ";
217 node.default_expr()->accept(*this);
218 }
219 buffer << ")";
220}
221
222void PrintVisitor::visit(const SummationNode& node) {
223 buffer << "\xce\xa3(";
224 node.body()->accept(*this);
225 buffer << ", " << node.index_var() << "=";
226 node.lower_bound()->accept(*this);
227 buffer << "..";
228 node.upper_bound()->accept(*this);
229 buffer << ")";
230}
231
232void PrintVisitor::visit(const ProductNode& node) {
233 buffer << "\xce\xa0(";
234 node.body()->accept(*this);
235 buffer << ", " << node.index_var() << "=";
236 node.lower_bound()->accept(*this);
237 buffer << "..";
238 node.upper_bound()->accept(*this);
239 buffer << ")";
240}
241
242void PrintVisitor::visit(const TransformNode& node) {
243 switch (node.transform_type()) {
245 buffer << "L{";
246 node.body()->accept(*this);
247 buffer << "}(";
248 node.target()->accept(*this);
249 buffer << ")";
250 break;
252 buffer << "L\xe2\x81\xbb\xc2\xb9{";
253 node.body()->accept(*this);
254 buffer << "}(";
255 node.target()->accept(*this);
256 buffer << ")";
257 break;
259 buffer << "F{";
260 node.body()->accept(*this);
261 buffer << "}(";
262 node.target()->accept(*this);
263 buffer << ")";
264 break;
266 buffer << "F\xe2\x81\xbb\xc2\xb9{";
267 node.body()->accept(*this);
268 buffer << "}(";
269 node.target()->accept(*this);
270 buffer << ")";
271 break;
273 buffer << "Z{";
274 node.body()->accept(*this);
275 buffer << "}(";
276 node.target()->accept(*this);
277 buffer << ")";
278 break;
279 }
280}
281
282void PrintVisitor::visit(const QuantifierNode& node) {
283 if (node.quantifier_type() == QuantifierNode::Type::ForAll) {
284 buffer << "\xe2\x88\x80";
285 } else {
286 buffer << "\xe2\x88\x83";
287 }
288 buffer << node.bound_var() << "\xe2\x88\x88";
289 node.domain()->accept(*this);
290 buffer << ": ";
291 node.predicate()->accept(*this);
292}
293
294void PrintVisitor::visit(const SetBuilderNode& node) {
295 buffer << "{" << node.element_var() << " \xe2\x88\x88 ";
296 node.domain()->accept(*this);
297 buffer << " | ";
298 node.predicate()->accept(*this);
299 buffer << "}";
300}
301
302void PrintVisitor::visit(const FiniteSetNode& node) {
303 buffer << "{";
304 for (std::size_t index = 0; index < node.elements().size(); ++index) {
305 if (index != 0) buffer << ", ";
306 node.elements()[index]->accept(*this);
307 }
308 buffer << "}";
309}
310
311void PrintVisitor::visit(const IntervalNode& node) {
312 buffer << (node.lower_closed() ? "[" : "(");
313 node.lower()->accept(*this);
314 buffer << ", ";
315 node.upper()->accept(*this);
316 buffer << (node.upper_closed() ? "]" : ")");
317}
318
319void PrintVisitor::visit(const MembershipNode& node) {
320 print_operand(*node.element(), Precedence::Membership, true);
321 buffer << " in ";
322 print_operand(*node.set(), Precedence::Membership, true);
323}
324
325void PrintVisitor::visit(const QuantityNode& node) {
326 node.value()->accept(*this);
327 buffer << "<";
328 buffer << (node.display_unit().empty()
329 ? node.dimension().to_string()
330 : node.display_unit());
331 buffer << ">";
332}
333
334void PrintVisitor::visit(const ComplexNode& node) {
335 buffer << "(";
336 print_operand(*node.real(), Precedence::Add, true);
337 buffer << " + ";
338 print_operand(*node.imag(), Precedence::Multiply, true);
339 buffer << "*I)";
340}
341
342void PrintVisitor::visit(const IntegralNode& node) {
343 buffer << "Integral(";
344 node.body()->accept(*this);
345 buffer << ", " << node.variable();
346 if (node.is_definite()) {
347 buffer << ", ";
348 node.lower()->accept(*this);
349 buffer << ", ";
350 node.upper()->accept(*this);
351 }
352 buffer << ")";
353}
354
355void PrintVisitor::visit(const LimitNode& node) {
356 buffer << "limit(";
357 node.body()->accept(*this);
358 buffer << ", " << node.variable() << ", ";
359 node.point()->accept(*this);
360 switch (node.direction()) {
361 case LimitDirection::Both: buffer << ", both)"; break;
362 case LimitDirection::FromBelow: buffer << ", below)"; break;
363 case LimitDirection::FromAbove: buffer << ", above)"; break;
364 }
365}
366
367void PrintVisitor::visit(const RootOfNode& node) {
368 buffer << "rootof(";
369 node.polynomial()->accept(*this);
370 buffer << ", " << node.variable() << ", " << node.index() << ")";
371}
372
373} // namespace LMCAS
加法节点,表示多个操作数的求和。
复数节点,表示 real + imag * i。
函数节点,表示数学函数调用(三角函数、对数、特殊函数等)。
@ Not
一元逻辑非,right 为 nullptr。
@ Implies
逻辑蕴含 A ⇒ B。
矩阵节点,支持稠密和稀疏两种存储方式。
乘法节点,表示多个操作数的乘积。
分段函数节点,表示条件分支表达式.
幂运算节点,表示 base^exponent。
连乘节点,表示符号有限/无限连乘 prod_{k=a}^{b} f(k).
@ ForAll
全称量词 forall。
定义 sets.hpp:8
static std::string op_to_string(Op op)
将关系运算符转换为字符串表示。
求和节点,表示符号有限/无限求和 sum_{k=a}^{b} f(k).
virtual void accept(LMCAS::detail::SymbolicVisitor &visitor) const =0
积分变换节点,表示 Laplace,Fourier,Z 变换及其逆变换.
@ InverseLaplace
逆 Laplace 变换 L-¹{F(s)}(t)。
@ Laplace
Laplace 变换 L{f(t)}(s)。
@ Fourier
Fourier 变换 F{f(t)}(omega)。
@ InverseFourier
逆 Fourier 变换 F-¹{F(omega)}(t)。
变量节点,表示一个符号变量。
const char * function_name(FunctionNode::FuncType type)
const SymbolicNodePtr & node(const ::LMCAS::SymbolicExpr &expression) noexcept
const ExprPtr & element
ExprResult integer(Integer)=delete
@ Rational
Rational numbers
ExprResult relation(const ExprPtr &lhs, const ExprPtr &rhs, RelationOp op)
ExprResult rational(const Rational &value)
打印访问器,将 AST 转换为可读字符串。