1use std::collections::HashMap;
2
3use crate::error::ParseResult;
4use crate::functions::{define_function_full, FunctionContext, FunctionSpec};
5use crate::parse_node::ParseNode;
6
7pub fn register(map: &mut HashMap<&'static str, FunctionSpec>) {
8 define_function_full(
10 map,
11 &[
12 "\\coprod", "\\bigvee", "\\bigwedge", "\\biguplus", "\\bigcap",
13 "\\bigcup", "\\intop", "\\prod", "\\sum", "\\bigotimes",
14 "\\bigoplus", "\\bigodot", "\\bigsqcup", "\\smallint",
15 "\u{220F}", "\u{2210}", "\u{2211}", "\u{22C0}", "\u{22C1}",
16 "\u{22C2}", "\u{22C3}", "\u{2A00}", "\u{2A01}", "\u{2A02}",
17 "\u{2A04}", "\u{2A06}",
18 ],
19 "op",
20 0, 0, None,
21 false, false, true, false, false,
22 handle_op_symbol_limits,
23 );
24
25 define_function_full(
27 map,
28 &[
29 "\\arcsin", "\\arccos", "\\arctan", "\\arctg", "\\arcctg",
30 "\\arg", "\\ch", "\\cos", "\\cosec", "\\cosh", "\\cot", "\\cotg",
31 "\\coth", "\\csc", "\\ctg", "\\cth", "\\deg", "\\dim", "\\exp",
32 "\\hom", "\\ker", "\\lg", "\\ln", "\\log", "\\sec", "\\sin",
33 "\\sinh", "\\sh", "\\tan", "\\tanh", "\\tg", "\\th",
34 ],
35 "op",
36 0, 0, None,
37 false, false, true, false, false,
38 handle_op_text_nolimits,
39 );
40
41 define_function_full(
43 map,
44 &[
45 "\\det", "\\gcd", "\\inf", "\\lim", "\\max", "\\min", "\\Pr", "\\sup",
46 ],
47 "op",
48 0, 0, None,
49 false, false, true, false, false,
50 handle_op_text_limits,
51 );
52
53 define_function_full(
55 map,
56 &[
57 "\\int", "\\iint", "\\iiint", "\\oint", "\\oiint", "\\oiiint",
58 "\u{222B}", "\u{222C}", "\u{222D}", "\u{222E}", "\u{222F}", "\u{2230}",
59 ],
60 "op",
61 0, 0, None,
62 true, false, true, false, false,
64 handle_op_symbol_nolimits,
65 );
66
67 define_function_full(
69 map,
70 &["\\mathop"],
71 "op",
72 1, 0, None,
73 false, false, true, false,
74 true, handle_mathop,
76 );
77}
78
79fn single_char_big_op(c: &str) -> Option<&'static str> {
80 match c {
81 "\u{220F}" => Some("\\prod"),
82 "\u{2210}" => Some("\\coprod"),
83 "\u{2211}" => Some("\\sum"),
84 "\u{22C0}" => Some("\\bigwedge"),
85 "\u{22C1}" => Some("\\bigvee"),
86 "\u{22C2}" => Some("\\bigcap"),
87 "\u{22C3}" => Some("\\bigcup"),
88 "\u{2A00}" => Some("\\bigodot"),
89 "\u{2A01}" => Some("\\bigoplus"),
90 "\u{2A02}" => Some("\\bigotimes"),
91 "\u{2A04}" => Some("\\biguplus"),
92 "\u{2A06}" => Some("\\bigsqcup"),
93 _ => None,
94 }
95}
96
97fn single_char_integral(c: &str) -> Option<&'static str> {
98 match c {
99 "\u{222B}" => Some("\\int"),
100 "\u{222C}" => Some("\\iint"),
101 "\u{222D}" => Some("\\iiint"),
102 "\u{222E}" => Some("\\oint"),
103 "\u{222F}" => Some("\\oiint"),
104 "\u{2230}" => Some("\\oiiint"),
105 _ => None,
106 }
107}
108
109fn handle_op_symbol_limits(
110 ctx: &mut FunctionContext,
111 _args: Vec<ParseNode>,
112 _opt_args: Vec<Option<ParseNode>>,
113) -> ParseResult<ParseNode> {
114 let name = single_char_big_op(&ctx.func_name)
115 .map(|s| s.to_string())
116 .unwrap_or_else(|| ctx.func_name.clone());
117 Ok(ParseNode::Op {
118 mode: ctx.parser.mode,
119 limits: true,
120 always_handle_sup_sub: None,
121 suppress_base_shift: None,
122 parent_is_sup_sub: false,
123 symbol: true,
124 name: Some(name),
125 body: None,
126 loc: None,
127 })
128}
129
130fn handle_op_text_nolimits(
131 ctx: &mut FunctionContext,
132 _args: Vec<ParseNode>,
133 _opt_args: Vec<Option<ParseNode>>,
134) -> ParseResult<ParseNode> {
135 Ok(ParseNode::Op {
136 mode: ctx.parser.mode,
137 limits: false,
138 always_handle_sup_sub: None,
139 suppress_base_shift: None,
140 parent_is_sup_sub: false,
141 symbol: false,
142 name: Some(ctx.func_name.clone()),
143 body: None,
144 loc: None,
145 })
146}
147
148fn handle_op_text_limits(
149 ctx: &mut FunctionContext,
150 _args: Vec<ParseNode>,
151 _opt_args: Vec<Option<ParseNode>>,
152) -> ParseResult<ParseNode> {
153 Ok(ParseNode::Op {
154 mode: ctx.parser.mode,
155 limits: true,
156 always_handle_sup_sub: None,
157 suppress_base_shift: None,
158 parent_is_sup_sub: false,
159 symbol: false,
160 name: Some(ctx.func_name.clone()),
161 body: None,
162 loc: None,
163 })
164}
165
166fn handle_op_symbol_nolimits(
167 ctx: &mut FunctionContext,
168 _args: Vec<ParseNode>,
169 _opt_args: Vec<Option<ParseNode>>,
170) -> ParseResult<ParseNode> {
171 let name = single_char_integral(&ctx.func_name)
172 .map(|s| s.to_string())
173 .unwrap_or_else(|| ctx.func_name.clone());
174 Ok(ParseNode::Op {
175 mode: ctx.parser.mode,
176 limits: false,
177 always_handle_sup_sub: None,
178 suppress_base_shift: None,
179 parent_is_sup_sub: false,
180 symbol: true,
181 name: Some(name),
182 body: None,
183 loc: None,
184 })
185}
186
187fn handle_mathop(
188 ctx: &mut FunctionContext,
189 args: Vec<ParseNode>,
190 _opt_args: Vec<Option<ParseNode>>,
191) -> ParseResult<ParseNode> {
192 let body = ParseNode::ord_argument(args.into_iter().next().unwrap());
193 Ok(ParseNode::Op {
194 mode: ctx.parser.mode,
195 limits: false,
196 always_handle_sup_sub: None,
197 suppress_base_shift: None,
198 parent_is_sup_sub: false,
199 symbol: false,
200 name: None,
201 body: Some(body),
202 loc: None,
203 })
204}