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; }
13 ? Precedence::Equality : Precedence::Relation;
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; }
20 if (
const auto*
integer = std::get_if<BigInt>(&number->value())) {
21 if (
integer->is_negative()) {
return Precedence::Unary; }
24 return Precedence::Atom;
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 <<
"("; }
35 if (parentheses) { buffer <<
")"; }
38void PrintVisitor::visit(
const NumberNode& node) {
39 if (std::holds_alternative<BigInt>(
node.value())) {
40 buffer << std::get<BigInt>(
node.value()).to_string();
42 buffer << std::get<Rational>(
node.value()).to_string();
47 buffer <<
node.name();
50void PrintVisitor::visit(
const AddNode& node) {
51 if (
node.operands().empty()) {
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);
62 if (
node.operands().empty()) {
66 for (
size_t i = 0; i <
node.operands().size(); ++i) {
67 if (i > 0) buffer <<
"*";
69 print_operand(*
node.operands()[i], Precedence::Multiply,
true);
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";
117 const auto index =
static_cast<std::size_t
>(type);
118 return index < names.size() && names[index] ? names[index] :
"";
123void PrintVisitor::visit(
const PowerNode& node) {
124 print_operand(*node.base(), Precedence::Power,
true);
126 print_operand(*node.exponent(), Precedence::Power);
137 for (
size_t i = 0; i <
node.arguments().size(); ++i) {
139 if (i <
node.arguments().size() - 1) {
147 buffer <<
node.name() <<
"(";
148 for (std::size_t index = 0; index <
node.arguments().size(); ++index) {
149 if (index != 0) buffer <<
", ";
155void PrintVisitor::visit(
const MatrixNode& node) {
157 for (
size_t i = 0; i <
node.rows(); ++i) {
159 for (
size_t j = 0; j <
node.cols(); ++j) {
166 if (j <
node.cols() - 1) {
171 if (i <
node.rows() - 1) {
179 print_operand(*
node.left(), precedence(node),
true);
182 print_operand(*
node.right(), precedence(node),
true);
188 print_operand(*
node.left(), Precedence::Not,
true);
193 buffer <<
" implies ";
199 ? Precedence::And : Precedence::Or,
true);
202 ? Precedence::And : Precedence::Or,
true);
208 buffer <<
"piecewise(";
209 for (
size_t i = 0; i <
node.branches().size(); ++i) {
210 if (i > 0) buffer <<
", ";
215 if (
node.default_expr()) {
216 buffer <<
", default: ";
223 buffer <<
"\xce\xa3(";
225 buffer <<
", " <<
node.index_var() <<
"=";
233 buffer <<
"\xce\xa0(";
235 buffer <<
", " <<
node.index_var() <<
"=";
243 switch (
node.transform_type()) {
252 buffer <<
"L\xe2\x81\xbb\xc2\xb9{";
266 buffer <<
"F\xe2\x81\xbb\xc2\xb9{";
284 buffer <<
"\xe2\x88\x80";
286 buffer <<
"\xe2\x88\x83";
288 buffer <<
node.bound_var() <<
"\xe2\x88\x88";
295 buffer <<
"{" <<
node.element_var() <<
" \xe2\x88\x88 ";
304 for (std::size_t index = 0; index <
node.elements().size(); ++index) {
305 if (index != 0) buffer <<
", ";
312 buffer << (
node.lower_closed() ?
"[" :
"(");
316 buffer << (
node.upper_closed() ?
"]" :
")");
320 print_operand(*
node.element(), Precedence::Membership,
true);
322 print_operand(*
node.set(), Precedence::Membership,
true);
328 buffer << (
node.display_unit().empty()
329 ?
node.dimension().to_string()
330 :
node.display_unit());
336 print_operand(*
node.real(), Precedence::Add,
true);
338 print_operand(*
node.imag(), Precedence::Multiply,
true);
343 buffer <<
"Integral(";
345 buffer <<
", " <<
node.variable();
346 if (
node.is_definite()) {
355void PrintVisitor::visit(
const LimitNode& node) {
358 buffer <<
", " <<
node.variable() <<
", ";
360 switch (
node.direction()) {
367void PrintVisitor::visit(
const RootOfNode& node) {
370 buffer <<
", " <<
node.variable() <<
", " <<
node.index() <<
")";
函数节点,表示数学函数调用(三角函数、对数、特殊函数等)。
@ Not
一元逻辑非,right 为 nullptr。
连乘节点,表示符号有限/无限连乘 prod_{k=a}^{b} f(k).
static std::string op_to_string(Op op)
将关系运算符转换为字符串表示。
求和节点,表示符号有限/无限求和 sum_{k=a}^{b} f(k).
virtual void accept(LMCAS::detail::SymbolicVisitor &visitor) const =0
const char * function_name(FunctionNode::FuncType type)
const SymbolicNodePtr & node(const ::LMCAS::SymbolicExpr &expression) noexcept
ExprResult integer(Integer)=delete
@ Rational
Rational numbers
ExprResult relation(const ExprPtr &lhs, const ExprPtr &rhs, RelationOp op)
ExprResult rational(const Rational &value)