1 /* markup.cc
2 *
3 * copyright (c) 2019 Luka Marohnić
4 *
5 * This program is free software;you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation;either version 3 of the License,or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY;without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not,see <http://www.gnu.org/licenses/>.
17 */
18
19 #include "giacPCH.h"
20 #include "giac.h"
21 #include "markup.h"
22 #include "signalprocessing.h"
23 #include "tex.h"
24 #include "mathml.h"
25 #ifdef __ANDROID__
26 using std::vector;
27 #endif
28 #if defined GIAC_HAS_STO_38 || defined NSPIRE || defined NSPIRE_NEWLIB || defined KHICAS || \
29 defined FXCG || defined GIAC_GGB || defined USE_GMP_REPLACEMENTS
is_graphe(const giac::gen & g,std::string & disp_out,const giac::context *)30 inline bool is_graphe(const giac::gen &g,std::string &disp_out,
31 const giac::context *) {
32 return false;
33 }
34 #else
35 #include "graphtheory.h"
36 #endif
37
38 using namespace std;
39
40 #ifndef NO_NAMESPACE_GIAC
41 namespace giac {
42 #endif // ndef NO_NAMESPACE_GIAC
43
44 const string mml_itimes="<mo>⁢</mo>";
45 const string mml_cdot="<mo>·</mo>";
46 const string mml_dot="<mo>.</mo>";
47 const string mml_times="<mo>×</mo>";
48 const string mml_plus="<mo>+</mo>";
49 const string mml_minus="<mo>−</mo>";
50 const string mml_apply="<mo>⁡</mo>";
51 const string mml_icomma="<mo>⁣</mo>";
52 const string mml_i="<mi mathvariant='normal'>i</mi>";
53 const string mml_e="<mi mathvariant='normal'>e</mi>";
54 const string mml_d="<mi mathvariant='normal'>d</mi>";
55 const string mml_re="<mi>ℜ</mi>";
56 const string mml_im="<mi>ℑ</mi>";
57
58 string tex_itimes=" ";
59 string tex_mathi="\\mathrm{i}";
60 string tex_mathe="\\mathrm{e}";
61 string tex_mathd="\\mathrm{d}";
62
63 const string tm_Dirac="\\operatorname{\\updelta}";
64 const string tm_Heaviside="\\operatorname{\\uptheta}";
65 const string tm_Zeta="\\operatorname{\\upzeta}";
66
67 bool is_texmacs_compatible_latex_export=false;
68 bool force_legacy_conversion_to_latex=false;
69
70 enum OperatorPrecedence {
71 _PRIORITY_APPLY=1, // function application, array access
72 _PRIORITY_UNARY=2, // unary operator
73 _PRIORITY_EXP=3, // power or exponential
74 _PRIORITY_MUL=4, // multiplication, division, modulo
75 _PRIORITY_ADD=5, // addition, subtraction
76 _PRIORITY_SET=6, // set operator
77 _PRIORITY_INEQ=7, // inequality
78 _PRIORITY_EQ=8, // equation
79 _PRIORITY_COMP=9, // comparison operator == or !=
80 _PRIORITY_NOT=10, // logical negation
81 _PRIORITY_AND=11, // logical conjunction
82 _PRIORITY_XOR=12, // logical exclusive or
83 _PRIORITY_OR=13, // logical disjunction
84 _PRIORITY_COND=14, // conditional expression
85 _PRIORITY_ASSGN=15,// assignment operator
86 _PRIORITY_OTHER=100
87 };
88
89 enum MarkupBlockTypeFlags {
90 _MLBLOCK_GENERAL=0,
91 _MLBLOCK_NUMERIC_EXACT=1,
92 _MLBLOCK_NUMERIC_APPROX=2,
93 _MLBLOCK_SUBTYPE_IDNT=4,
94 _MLBLOCK_FRACTION=8,
95 _MLBLOCK_ROOT=16,
96 _MLBLOCK_NEG=32,
97 _MLBLOCK_SUMPROD=64,
98 _MLBLOCK_FACTORIAL=128,
99 _MLBLOCK_MATRIX=256,
100 _MLBLOCK_ELEMAPP=512,
101 _MLBLOCK_FUNC=1024,
102 _MLBLOCK_POWER=2048,
103 _MLBLOCK_DERIVATIVE=4096,
104 _MLBLOCK_HAS_SUBSCRIPT=8192,
105 _MLBLOCK_LEADING_DIGIT=16384
106 };
107
108 enum MarkupFlags {
109 _MARKUP_LATEX=1,
110 _MARKUP_TOPLEVEL=2,
111 _MARKUP_UNIT=4,
112 _MARKUP_MATHML_PRESENTATION=8,
113 _MARKUP_MATHML_CONTENT=16,
114 _MARKUP_ELEMPOW=32,
115 _MARKUP_FACTOR=64,
116 _MARKUP_CODE=128,
117 _MARKUP_QUOTE=256,
118 _MARKUP_ERROR=512,
119 _MARKUP_SCHEME=1024
120 };
121
scm_quote(const string & s)122 string scm_quote(const string &s) {
123 if (s.length()==0 || s[0]=='(')
124 return s;
125 return "\""+s+"\"";
126 }
127
scm_concat(const string & s)128 string scm_concat(const string &s) {
129 return "(concat "+s+")";
130 }
131
is_substr(const string & s,const string & needle)132 bool is_substr(const string &s,const string &needle) {
133 return s.find(needle)!=string::npos;
134 }
135
is_prefix(const string & s,const string & p)136 bool is_prefix(const string &s,const string &p) {
137 return s.find(p)==0;
138 }
139
is_suffix(const string & s,const string & p)140 bool is_suffix(const string &s,const string &p) {
141 return s.rfind(p)+p.length()==s.length();
142 }
143
is_greek_letter(const string & s)144 bool is_greek_letter(const string &s) {
145 switch (s.size()) {
146 case 2:
147 return s=="mu" || s=="nu" || s=="pi" || s=="Pi" || s=="xi" ||
148 s=="Xi";
149 case 3:
150 return s=="chi" || s=="phi" || s=="Phi" || s=="eta" || s=="rho" ||
151 s=="tau" || s=="psi" || s=="Psi";
152 case 4:
153 return s=="beta" || s=="zeta";
154 case 5:
155 return s=="alpha" || s=="delta" || s=="Delta" || s=="gamma" ||
156 s=="Gamma" || s=="kappa" || s=="theta" || s=="Theta" ||
157 s=="sigma" || s=="Sigma" || s=="Omega" || s=="omega";
158 case 6:
159 return s=="lambda" || s=="Lambda";
160 case 7:
161 return s=="epsilon";
162 default:
163 break;
164 }
165 return false;
166 }
167
is_double_letter(const string & s)168 bool is_double_letter(const string &s) {
169 return s.length()==2 && isalpha(s.at(0)) && s.at(0)==s.at(1);
170 }
171
172 typedef struct {
173 int priority;
174 int type;
175 bool neg;
176 string latex;
177 string scheme;
178 string markup;
179 string content;
180 int split_pos;
181 int split_pos_tex;
182 int split_pos_scm;
183 bool appl;
ctypegiac::__anona0e007b30108184 bool ctype(int t) const { return (type & t)!=0; }
185 } MarkupBlock;
186
187 extern MarkupBlock gen2markup(const gen &g,int flags,int &idc,GIAC_CONTEXT);
188
189 #ifndef KHICAS
enable_texmacs_compatible_latex_export(bool yes)190 void enable_texmacs_compatible_latex_export(bool yes) {
191 is_texmacs_compatible_latex_export=yes;
192 tex_itimes=(yes?"\\*":" ");
193 tex_mathi=(yes?"\\mathi ":"\\mathrm{i}");
194 tex_mathe=(yes?"\\mathe ":"\\mathrm{e}");
195 tex_mathd=(yes?"\\mathd ":"\\mathrm{d}");
196 }
197 #endif
198
199 #define NUM_MATHML_CONTENT_ELEMENTS 31
200 const string mathml_content_elements[NUM_MATHML_CONTENT_ELEMENTS]={
201 "cn",
202 "ci",
203 "cs",
204 "csymbol",
205 "cerror",
206 "share",
207 "bind",
208 "bvar",
209 "semantics",
210 "apply",
211 "domainofapplication",
212 "interval",
213 "condition",
214 "lowlimit",
215 "uplimit",
216 "degree",
217 "momentabout",
218 "logbase",
219 "inverse",
220 "lambda",
221 "piecewise",
222 "piece",
223 "otherwise",
224 "set",
225 "list",
226 "vector",
227 "matrix",
228 "matrixrow",
229 "declare",
230 "reln",
231 "fn"
232 };
233
is_mathml_content_element(const string & s)234 bool is_mathml_content_element(const string &s) {
235 for (int i=0;i<NUM_MATHML_CONTENT_ELEMENTS;++i) {
236 if (mathml_content_elements[i]==s) return true;
237 }
238 return false;
239 }
240
mml_tag(const string & tag,const string & str,int idc=0,const string & attr_key1="",const string & attr_val1="",const string & attr_key2="",const string & attr_val2="",const string & attr_key3="",const string & attr_val3="",const string & attr_key4="",const string & attr_val4="")241 string mml_tag(const string &tag,const string &str,int idc=0,
242 const string &attr_key1="",const string &attr_val1="",
243 const string &attr_key2="",const string &attr_val2="",
244 const string &attr_key3="",const string &attr_val3="",
245 const string &attr_key4="",const string &attr_val4="") {
246 string r,attr1,attr2,attr3,attr4;
247 if (tag[0]=='c' || is_mathml_content_element(tag))
248 r="id";
249 else if (tag[0]=='m')
250 r="xref";
251 assert(!r.empty());
252 if (!attr_key1.empty() && !attr_val1.empty())
253 attr1=" "+attr_key1+"='"+attr_val1+"'";
254 if (!attr_key2.empty() && !attr_val2.empty())
255 attr2=" "+attr_key2+"='"+attr_val2+"'";
256 if (!attr_key3.empty() && !attr_val3.empty())
257 attr3=" "+attr_key3+"='"+attr_val3+"'";
258 if (!attr_key4.empty() && !attr_val4.empty())
259 attr4=" "+attr_key4+"='"+attr_val4+"'";
260 if (idc==0)
261 return "<"+tag+attr1+attr2+attr3+attr4+">"+str+"</"+tag+">";
262 return "<"+tag+" "+r+"='id"+gen(idc).print(context0)+"'"+attr1+attr2+attr3+attr4+">"+str+"</"+tag+">";
263 }
264
mml_csymbol(const string & s,const string & cd)265 string mml_csymbol(const string &s,const string &cd) {
266 string attr=(cd.empty()?"":"cd");
267 return mml_tag("csymbol",s,0,attr,cd);
268 }
269
extract_id(MarkupBlock & ml,bool content)270 string extract_id(MarkupBlock &ml,bool content) {
271 size_t pos_id_start,pos_gt,pos_id_end;
272 string &str=(content?ml.content:ml.markup);
273 string attr=(content?" id='":" xref='");
274 pos_gt=str.find(">");
275 pos_id_start=str.find(attr);
276 if (pos_id_start==string::npos || pos_id_start>pos_gt)
277 return "";
278 pos_id_end=str.find("'",pos_id_start+attr.length());
279 assert(pos_id_end!=string::npos);
280 string ret=str.substr(pos_id_start+attr.length(),
281 pos_id_end-pos_id_start-attr.length());
282 str=str.substr(0,pos_id_start)+str.substr(pos_id_end+1);
283 return ret;
284 }
285
insert_id(const string & str,int idc,bool content)286 string insert_id(const string &str,int idc,bool content) {
287 if (idc==0)
288 return str;
289 size_t pos=str.find(">");
290 if (pos==string::npos || pos==0)
291 return str;
292 if (str[pos-1]=='/') pos--;
293 string r=(content?" id='id":" xref='id");
294 return str.substr(0,pos)+r+gen(idc).print(context0)+"'"+str.substr(pos);
295 }
296
trim_string(const string & s_orig,int & indent)297 string trim_string(const string &s_orig,int &indent) {
298 string s=s_orig;
299 size_t i,j;
300 indent=0;
301 for (i=0;i<s.length();++i) {
302 char c=s.at(i);
303 if (c==' ')
304 indent++;
305 else if (c!='\n' && c!='\t')
306 break;
307 }
308 for (j=s.length();j-->0;) {
309 char c=s.at(j);
310 if (c!=' ' && c!='\n' && c!='\t')
311 break;
312 }
313 return s.substr(i,j-i+1);
314 }
315
str_to_tex(const string & s_orig,bool quote,bool ind)316 string str_to_tex(const string &s_orig,bool quote,bool ind) {
317 int indent;
318 string s=trim_string(s_orig,indent),ret;
319 for (string::const_iterator it=s.begin();it!=s.end();++it) {
320 switch (*it) {
321 case '\\': case '%': case '_': case '$': case '{': case '}': case '^':
322 ret+="\\";
323 ret+=string(1,*it);
324 break;
325 default:
326 ret+=string(1,*it);
327 break;
328 }
329 }
330 if (ind && indent>0)
331 for (int i=0;i<indent;++i) ret="\\ "+ret;
332 if (quote)
333 return "\""+ret+"\"";
334 return ret;
335 }
336
str_to_scm(const string & s_orig,bool quote,bool ind)337 string str_to_scm(const string &s_orig,bool quote,bool ind) {
338 int indent;
339 string s=trim_string(s_orig,indent),ret;
340 for (string::const_iterator it=s.begin();it!=s.end();++it) {
341 switch (*it) {
342 case '\\': case '"':
343 ret+="\\\\\\";
344 ret+=string(1,*it);
345 break;
346 default:
347 ret+=string(1,*it);
348 break;
349 }
350 }
351 if (ind && indent>0)
352 for (int i=0;i<indent;++i) ret=" "+ret;
353 if (quote)
354 return "``"+ret+"''";
355 return ret;
356 }
357
str_to_mml(const string & s_orig,bool ind,const string & tag="",int idc=0)358 string str_to_mml(const string &s_orig,bool ind,const string &tag="",int idc=0) {
359 int indent;
360 string s=trim_string(s_orig,indent),ret;
361 for (string::const_iterator it=s.begin();it!=s.end();++it) {
362 switch (*it) {
363 case '&':
364 ret+="&";
365 break;
366 case '<':
367 ret+="<";
368 break;
369 case '>':
370 ret+=">";
371 break;
372 default:
373 ret+=string(1,*it);
374 break;
375 }
376 }
377 if (!tag.empty())
378 ret=mml_tag(tag,ret,idc);
379 if (ind && indent>0)
380 ret=mml_tag("mphantom",mml_tag("mtext",string(indent,'x')))+ret;
381 return ret;
382 }
383
string2markup(MarkupBlock & ml,const string & s_orig,int flags,int & idc)384 void string2markup(MarkupBlock &ml,const string &s_orig,int flags,int &idc) {
385 bool tex=(flags & _MARKUP_LATEX)!=0;
386 bool content=(flags & _MARKUP_MATHML_CONTENT)!=0;
387 bool presentation=(flags & _MARKUP_MATHML_PRESENTATION)!=0;
388 bool scm=(flags & _MARKUP_SCHEME)!=0;
389 bool code=(flags & _MARKUP_CODE)!=0;
390 bool quote=(flags & _MARKUP_QUOTE)!=0;
391 bool err=(flags & _MARKUP_ERROR)!=0;
392 vector<string> lines;
393 size_t pos,last_pos=0,p;
394 string s;
395 while ((pos=s_orig.find("\n",last_pos))!=string::npos) {
396 s=s_orig.substr(last_pos,pos-last_pos);
397 for (p=0;p<s.length() && s.at(p)==' ';++p);
398 if (p<s.length())
399 lines.push_back(s);
400 last_pos=pos+1;
401 }
402 lines.push_back(s_orig.substr(last_pos));
403 if (tex) {
404 string textext=code?"\\texttt":"\\text";
405 for (vector<string>::const_iterator it=lines.begin();it!=lines.end();++it) {
406 ml.latex+=(it!=lines.begin()?"\\\\":"")+textext+"{"+str_to_tex(*it,quote,code)+"}";
407 }
408 if (lines.size()>1)
409 ml.latex="\\begin{array}{l}"+ml.latex+"\\end{array}";
410 }
411 if (scm) {
412 if (lines.size()==1)
413 ml.scheme="(text "+string(code?"(with \"font-family\" \"tt\" \"":"\"")+
414 str_to_scm(lines.front(),quote,code)+"\")"+(code?")":"");
415 else {
416 ml.scheme="(text "+string(code?"(with \"font-family\" \"tt\" ":"")+"(tabular (tformat (table";
417 for (vector<string>::const_iterator it=lines.begin();it!=lines.end();++it) {
418 ml.scheme+=" (row (cell \""+str_to_scm(*it,quote,code)+"\"))";
419 }
420 ml.scheme+="))))"+string(code?")":"");
421 }
422 }
423 if (content) {
424 if (err)
425 ml.content=mml_tag("cerror",str_to_mml(s_orig,false,"cs"),++idc);
426 else
427 ml.content=str_to_mml(s_orig,false,"cs",++idc);
428 }
429 if (presentation) {
430 string mtag=quote?"ms":"mtext";
431 if (lines.size()==1)
432 ml.markup=mml_tag(mtag,str_to_mml(lines.front(),false),err?0:idc,
433 code?"mathvariant":"","monospace");
434 else {
435 for (vector<string>::const_iterator it=lines.begin();it!=lines.end();++it) {
436 ml.markup+="<mtr><mtd>"+str_to_mml(*it,code,mtag)+"</mtd></mtr>";
437 }
438 ml.markup=mml_tag("mtable",ml.markup,err?0:idc,
439 "columnalign","left",code?"mathvariant":"","monospace");
440 }
441 if (err)
442 ml.markup=mml_tag("merror",ml.markup,idc);
443 }
444 }
445
446 #define NUM_UNIT_PAIRS 48
447 const string unit_pairs[NUM_UNIT_PAIRS][2]={
448 /* "units_imperial1" */
449 { "acre","acre" },
450 { "bar","bar" },
451 { "degree_Fahrenheit","degreeF" },
452 { "foot","ft" },
453 { "mile","mile" },
454 { "pint","ptUK" },
455 { "pound_force","lbf" },
456 { "pound_mass","lb" },
457 { "yard","yd" },
458 /* "units_metric1" */
459 { "Coulomb","C" },
460 { "Joule","J" },
461 { "Newton","N" },
462 { "Pascal","Pa" },
463 { "Watt","W" },
464 { "amp","A" },
465 { "degree_Kelvin","K" },
466 { "gramme","g" },
467 { "litre","l" },
468 { "metre","m" },
469 { "second","s" },
470 { "volt","V" },
471 /* "units_time1" */
472 { "calendar_year","yr" },
473 { "day","d" },
474 { "hour","h" },
475 { "minute","mn" },
476 /* "units_us1" */
477 { "foot_us_survey","ftUS" },
478 { "mile_us_survey","miUS" },
479 /* "SI_BaseUnits1" */
480 { "candela","cd" },
481 { "mole","mol" },
482 /* "SI_NamedDerivedUnits1" */
483 { "becquerel","Bq" },
484 { "farad","F" },
485 { "gray","Gy" },
486 { "henry","H" },
487 { "hertz","Hz" },
488 { "lumen","lm" },
489 { "lux","lx" },
490 { "ohm","Ohm" },
491 { "radian","rad" },
492 { "siemens","S" },
493 { "sievert","Sv" },
494 { "steradian","sr" },
495 { "tesla","T" },
496 { "weber","Wb" },
497 /* "SIUsed_OffSystemMeasuredUnits1" */
498 { "electronvolt","eV" },
499 /* "SIUsed_OffSystemUnits1" */
500 { "degree-of-arc","deg" },
501 { "minute-of-arc","arcmin" },
502 { "second-of-arc","arcs" },
503 { "tonne","t" }
504 };
505
506 #define NUM_SI_PREFIX_PAIRS 20
507 const string si_prefix_pairs[NUM_SI_PREFIX_PAIRS][2]={
508 { "yotta","Y" },
509 { "zetta","Z" },
510 { "exa","E" },
511 { "peta","P" },
512 { "tera","T" },
513 { "giga","G" },
514 { "mega","M" },
515 { "kilo","kK" },
516 { "hecto","hH" },
517 { "deka","D" },
518 { "deci","d" },
519 { "centi","c" },
520 { "milli","m" },
521 { "micro","µ" },
522 { "nano","n" },
523 { "pico","p" },
524 { "femto","f" },
525 { "atto","a" },
526 { "zepto","z" },
527 { "yocto","y" }
528 };
529
unit2content(const string & s,int idc)530 string unit2content(const string &s,int idc) {
531 string ret,p,cd;
532 bool has_prefix=false;
533 int i,j;
534 for (i=0;i<NUM_UNIT_PAIRS;++i) {
535 if (s==unit_pairs[i][1]) {
536 ret=unit_pairs[i][0];
537 break;
538 }
539 }
540 if (ret.empty()) {
541 int ofs=(s.substr(0,2)=="µ"?2:1);
542 p=s.substr(0,ofs);
543 for (j=0;j<NUM_SI_PREFIX_PAIRS;++j) {
544 if (si_prefix_pairs[j][1].find(p)!=string::npos) {
545 has_prefix=true;
546 break;
547 }
548 }
549 if (has_prefix) {
550 for (i=0;i<NUM_UNIT_PAIRS;++i) {
551 if (s==unit_pairs[i][1].substr(ofs)) {
552 ret=unit_pairs[i][0];
553 break;
554 }
555 }
556 }
557 }
558 if (ret.empty())
559 return mml_tag("ci",s,idc);
560 if (i<9)
561 cd="units_imperial1";
562 else if (i<21)
563 cd="units_metric1";
564 else if (i<25)
565 cd="units_time1";
566 else if (i<27)
567 cd="units_us1";
568 else if (i<29)
569 cd="SI_BaseUnits1";
570 else if (i<43)
571 cd="SI_NamedDerivedUnits1";
572 else if (i<44)
573 cd="SIUsed_OffSystemMeasuredUnits1";
574 else
575 cd="SIUsed_OffSystemUnits1";
576 if (!has_prefix)
577 return mml_tag("csymbol",ret,idc,"cd",cd);
578 return mml_tag("apply",mml_tag("csymbol","prefix",0,"cd","units_ops1")+
579 mml_tag("csymbol",si_prefix_pairs[j][0],0,"cd","units_siprefix1")+ret,
580 idc);
581 }
582
constant2content(const string & s,int idc)583 string constant2content(const string &s,int idc) {
584 string ret;
585 if (s=="NA") ret="Avogadros_constant";
586 else if (s=="k") ret="Boltzmann_constant";
587 else if (s=="F") ret="Faradays_constant";
588 else if (s=="h") ret="Planck_constant";
589 else if (s=="R") ret="gas_constant";
590 else if (s=="G") ret="gravitational_constant";
591 else if (s=="mu0") ret="magnetic_constant";
592 else if (s=="c") ret="speed_of_light";
593 else return mml_tag("ci",s,idc);
594 return mml_tag("csymbol",ret,idc,"cd","physical_consts1");
595 }
596
idnt2markup(const string & s_orig,int typ,bool unit=false,int idc=0)597 string idnt2markup(const string &s_orig,int typ,bool unit=false,int idc=0) {
598 bool tex=typ==0;
599 bool scm=typ==1;
600 if (unit && !s_orig.empty() && s_orig[0]=='_') {
601 string s=s_orig.substr(1);
602 if (s=="a0_")
603 return tex?"a_0":(scm?"(concat \"<space><nosymbol>a\" (rsub \"0\") \"<nosymbol>\")"
604 :mml_tag("msub","<mi>a</mi><mn>0</mn>",idc));
605 else if (s=="alpha_")
606 return tex?"\\alpha ":(scm?"<space><nosymbol><alpha><nosymbol>":mml_tag("mi","α",idc));
607 else if (s=="c_")
608 return tex || scm?"<space><nosymbol>c<nosymbol>":mml_tag("mi","c",idc);
609 else if (s=="c3_")
610 return tex || scm?"<space><nosymbol>b<nosymbol>":mml_tag("mi","b",idc);
611 else if (s=="epsilon0_")
612 return tex?"\\varepsilon_0"
613 :(scm?"(concat \"<space><nosymbol><varepsilon>\" (rsub \"0\") \"<nosymbol>\")"
614 :mml_tag("msub","<mi>ε</mi><mn>0</mn>",idc));
615 else if (s=="epsilonox_")
616 return tex?"\\varepsilon_{\\mathrm{SiO}_2}"
617 :(scm?"(concat \"<space><nosymbol><varepsilon>\" (rsub (concat \"SiO\" (rsub \"2\"))) \"<nosymbol>\")"
618 :mml_tag("msub","<mi>ε</mi><msub><mi>SiO</mi><mn>2</mn></msub>",idc));
619 else if (s=="epsilonsi_")
620 return tex?"\\varepsilon_\\mathrm{Si}"
621 :(scm?"(concat \"<space><nosymbol><varepsilon>\" (rsub \"Si\") \"<nosymbol>\")"
622 :mml_tag("msub","<mi>ε</mi><mi>Si<mi>",idc));
623 else if (s=="F_")
624 return tex || scm?"<space><nosymbol>F<nosymbol>":mml_tag("mi","F",idc);
625 else if (s=="f0_")
626 return tex?"f_0":(scm?"(concat \"<space><nosymbol>f\" (rsub \"0\") \"<nosymbol>\")"
627 :mml_tag("msub","<mi>f</mi><mn>0</mn>",idc));
628 else if (s=="g_")
629 return tex || scm?"<space><nosymbol>g<nosymbol>":mml_tag("mi","g",idc);
630 else if (s=="G_")
631 return tex || scm?"<space><nosymbol>G<nosymbol>":mml_tag("mi","G",idc);
632 else if (s=="h_")
633 return tex || scm?"<space><nosymbol>h<nosymbol>":mml_tag("mi","h",idc);
634 else if (s=="hbar_")
635 return tex?"\\hslash ":(scm?"<space><nosymbol><hbar><nosymbol>":mml_tag("mi","ℏ",idc));
636 else if (s=="I0_")
637 return tex?"I_0":(scm?"(concat \"<space><nosymbol>I\" (rsub \"0\") \"<nosymbol>\")"
638 :mml_tag("msub","<mi>I</mi><mn>0</mn>",idc));
639 else if (s=="k_")
640 return tex || scm?"<space><nosymbol>k<nosymbol>":mml_tag("mi","k",idc);
641 else if (s=="lambda0_")
642 return tex?"\\lambda_0":(scm?"(concat \"<space><nosymbol><lambda>\" (rsub \"0\") \"<nosymbol>\")"
643 :mml_tag("msub","<mi>λ</mi><mn>0</mn>",idc));
644 else if (s=="lambdac_")
645 return tex?"\\lambda ":(scm?"<space><nosymbol><lambda><nosymbol>":mml_tag("mi","λ",idc));
646 else if (s=="me_")
647 return tex?"m_\\mathrm{e}"
648 :(scm?"(concat \"<space><nosymbol>m\" (rsub (math-up \"e\")) \"<nosymbol>\")"
649 :mml_tag("msub","<mi>m</mi><mi mathvariant='normal'>e</mi>",idc));
650 else if (s=="mEarth_")
651 return tex?"M_\\oplus "
652 :(scm?"(concat \"<space><nosymbol>M\" (rsub \"<oplus>\") \"<nosymbol>\")"
653 :mml_tag("msub","<mi>M</mi><mi>⊕</mi>",idc));
654 else if (s=="mp_")
655 return tex?"m_\\mathrm{p}"
656 :(scm?"(concat \"<space><nosymbol>m\" (rsub (math-up \"p\")) \"<nosymbol>\")"
657 :mml_tag("msub","<mi>m</mi><mi mathvariant='normal'>p</mi>",idc));
658 else if (s=="mu0_")
659 return tex?"\\mu_0":(scm?"(concat \"<space><nosymbol><mu>\" (rsub \"0\") \"<nosymbol>\")"
660 :mml_tag("msub","<mi>μ</mi><mn>0</mn>",idc));
661 else if (s=="muB_")
662 return tex?"\\mu_\\mathrm{B}"
663 :(scm?"(concat \"<space><nosymbol><mu>\" (rsub (math-up \"B\")) \"<nosymbol>\")"
664 :mml_tag("msub","<mi>μ</mi><mi mathvariant='normal'>B</mi>",idc));
665 else if (s=="muN_")
666 return tex?"\\mu_\\mathrm{N}"
667 :(scm?"(concat \"<space><nosymbol><mu>\" (rsub (text \"N\")) \"<nosymbol>\")"
668 :mml_tag("msub","<mi>μ</mi><mi mathvariant='normal'>N</mi>",idc));
669 else if (s=="NA_")
670 return tex?"N_A":(scm?"(concat \"<space><nosymbol>N\" (rsub \"A\") \"<nosymbol>\")"
671 :mml_tag("msub","<mi>N</mi><mi>A</mi>",idc));
672 else if (s=="phi_")
673 return tex?"\\Phi_0":(scm?"(concat \"<space><nosymbol><Phi>\" (rsub \"0\") \"<nosymbol>\")"
674 :mml_tag("msub","<mi>Φ</mi><mn>0</mn>",idc));
675 else if (s=="PSun_")
676 return tex?"P_\\odot "
677 :(scm?"(concat \"<space><nosymbol>P\" (rsub \"<odot>\") \"<nosymbol>\")"
678 :mml_tag("msub","<mi>P</mi><mi>⊙</mi>",idc));
679 else if (s=="q_")
680 return tex || scm?"<space><nosymbol>q<nosymbol>":mml_tag("mi","q",idc);
681 else if (s=="R_")
682 return tex || scm?"<space><nosymbol>R<nosymbol>":mml_tag("mi","R",idc);
683 else if (s=="REarth_")
684 return tex?"R_\\oplus "
685 :(scm?"(concat \"<space><nosymbol>R\" (rsub \"<oplus>\") \"<nosymbol>\")"
686 :mml_tag("msub","<mi>R</mi><mi>⊕</mi>",idc));
687 else if (s=="Rinfinity_")
688 return tex?"R_\\infty "
689 :(scm?"(concat \"<space><nosymbol>R\" (rsub \"<infty>\") \"<nosymbol>\")"
690 :mml_tag("msub","<mi>R</mi><mi>∞</mi>",idc));
691 else if (s=="RSun_")
692 return tex?"R_\\odot "
693 :(scm?"(concat \"<space><nosymbol>R\" (rsub \"<odot>\") \"<nosymbol>\")"
694 :mml_tag("msub","<mi>R</mi><mi>⊙</mi>",idc));
695 else if (s=="sigma_")
696 return tex?"\\sigma ":(scm?"<space><nosymbol><sigma><nosymbol>":mml_tag("mi","σ",idc));
697 else if (s=="StdP_")
698 return tex?"P_\\mathrm{std}"
699 :(scm?"(concat \"<space>P\" (rsub \"std\"))":mml_tag("msub","<mi>P</mi><mi>std</mi>",idc));
700 else if (s=="StdT_")
701 return tex?"T_\\mathrm{std}"
702 :(scm?"(concat \"<space>T\" (rsub \"std\"))":mml_tag("msub","<mi>T</mi><mi>std</mi>",idc));
703 else if (s=="Vm_")
704 return tex?"V_\\mathrm{m}"
705 :(scm?"(concat \"<space><nosymbol>V\" (rsub (text \"m\")) \"<nosymbol>\")"
706 :mml_tag("msub","<mi>V</mi><mi mathvariant='normal'>m</mi>",idc));
707 else if (s=="degreeF")
708 return tex?"{}^\\circ\\mathrm{F}"
709 :(scm?"(math-up (concat (degreesign) \"F\"))"
710 :mml_tag("mi","℉",idc,"class","MathML-Unit","mathvariant","normal"));
711 else if (s=="ozfl")
712 return tex?"\\mathrm{oz}_\\mathrm{fl}"
713 :(scm?"(concat \"<space><nosymbol>oz\" (rsub \"fl\"))"
714 :mml_tag("msub","<mi>oz</mi><mi>fl</mi>",idc,"class","MathML-Unit"));
715 else if (s=="fermi")
716 return tex?"\\mathrm{fm}"
717 :(scm?"<space><nosymbol>fm":mml_tag("mi","fm",idc,"class","MathML-Unit"));
718 else if (s=="flam")
719 return tex?"\\mathrm{fL}"
720 :(scm?"<space><nosymbol>fL":mml_tag("mi","fL",idc,"class","MathML-Unit"));
721 else if (s=="deg")
722 return tex?"{}^\\circ "
723 :(scm?"(concat \"<nosymbol>\" (degreesign))"
724 :mml_tag("mi","°",idc,"class","MathML-Unit"));
725 else if (s=="arcmin")
726 return tex?"'":(scm?"(rprime \"'\")":mml_tag("mi","′",idc,"class","MathML-Unit"));
727 else if (s=="arcs")
728 return tex?"''":(scm?"(rprime \"''\")":mml_tag("mi","″",idc,"class","MathML-Unit"));
729 else if (s=="Rankine")
730 return tex?"{}^\\circ\\mathrm{R}"
731 :(scm?"(math-up (concat (degreesign) \"R\"))"
732 :mml_tag("mi","°R",idc,"class","MathML-Unit"));
733 else if (s=="lam")
734 return tex?"\\mathrm{L}"
735 :(scm?"(math-up \"<space><nosymbol>L\")":mml_tag("mi","L",idc,"class","MathML-Unit","mathvariant","normal"));
736 else if (s=="inH2O")
737 return tex?"\\mathrm{in}_\\mathrm{H_2O}"
738 :(scm?"(concat \"<space><nosymbol>in\" (rsub (math-up (concat \"H\" (rsub \"2\") \"O\"))))"
739 :mml_tag("msub","<mi>in</mi><mrow><msub><mn>H</mn><mn>2</mn></msub><mn>O</mn></mrow>",
740 idc,"class","MathML-Unit"));
741 else if (s=="buUS")
742 return tex?"\\mathrm{bu}_\\mathrm{US}"
743 :(scm?"(concat \"<space><nosymbol>bu\" (rsub \"US\"))"
744 :mml_tag("msub","<mi>bu</mi><mi>US</mi>",idc,"class","MathML-Unit"));
745 else if (s=="ftUS")
746 return tex?"\\mathrm{ft}_\\mathrm{US}"
747 :(scm?"(concat \"<space><nosymbol>ft\" (rsub \"US\"))"
748 :mml_tag("msub","<mi>ft</mi><mi>US</mi>",idc,"class","MathML-Unit"));
749 else if (s=="galC")
750 return tex?"\\mathrm{gal}_\\mathrm{C}"
751 :(scm?"(concat \"<space><nosymbol>gal\" (rsub (text \"C\")))"
752 :mml_tag("msub","<mi>gal</mi><mi>C</mi>",idc,"class","MathML-Unit"));
753 else if (s=="galUK")
754 return tex?"\\mathrm{gal}_\\mathrm{UK}"
755 :(scm?"(concat \"<space><nosymbol>gal\" (rsub \"UK\"))"
756 :mml_tag("msub","<mi>gal</mi><mi>UK</mi>",idc,"class","MathML-Unit"));
757 else if (s=="galUS")
758 return tex?"\\mathrm{gal}_\\mathrm{US}"
759 :(scm?"(concat \"<space><nosymbol>gal\" (rsub \"US\"))"
760 :mml_tag("msub","<mi>gal</mi><mi>US</mi>",idc,"class","MathML-Unit"));
761 else if (s=="inHg")
762 return tex?"\\mathrm{in}_\\mathrm{Hg}"
763 :(scm?"(concat \"<space><nosymbol>in\" (rsub \"Hg\"))"
764 :mml_tag("msub","<mi>in</mi><mi>Hg</mi>",idc,"class","MathML-Unit"));
765 else if (s=="miUS")
766 return tex?"\\mathrm{mi}_\\mathrm{US}"
767 :(scm?"(concat \"<space><nosymbol>mi\" (rsub \"US\"))"
768 :mml_tag("msub","<mi>mi</mi><mi>US</mi>",idc,"class","MathML-Unit"));
769 else if (s=="mmHg")
770 return tex?"\\mathrm{mm}_\\mathrm{Hg}"
771 :(scm?"(concat \"<space><nosymbol>mm\" (rsub \"Hg\"))"
772 :mml_tag("msub","<mi>mm</mi><mi>Hg</mi>",idc,"class","MathML-Unit"));
773 else if (s=="ozUK")
774 return tex?"\\mathrm{oz}_\\mathrm{UK}"
775 :(scm?"(concat \"<space><nosymbol>oz\" (rsub \"UK\"))"
776 :mml_tag("msub","<mi>oz</mi><mi>UK</mi>",idc,"class","MathML-Unit"));
777 else if (s=="ptUK")
778 return tex?"\\mathrm{pt}_\\mathrm{UK}"
779 :(scm?"(concat \"<space><nosymbol>pt\" (rsub \"UK\"))"
780 :mml_tag("msub","<mi>pt</mi><mi>UK</mi>",idc,"class","MathML-Unit"));
781 else if (s=="tonUK")
782 return tex?"\\mathrm{ton}_\\mathrm{UK}"
783 :(scm?"(concat \"<space><nosymbol>ton\" (rsub \"UK\"))"
784 :mml_tag("msub","<mi>ton</mi><mi>UK</mi>",idc,"class","MathML-Unit"));
785 else if (!s.empty() && s[s.size()-1]!='_') {
786 string p;
787 if (s.substr(0,2)=="µ") {
788 p=tex?"\\mu ":(scm?"<up-mu>":"μ");
789 s=s.substr(2);
790 }
791 if (s=="Angstrom")
792 return tex?"\\mathrm{"+p+"\\AA}"
793 :(scm?p+"<space><nosymbol><AA>"
794 :mml_tag("mi",p+"Å",idc,"class","MathML-Unit"));
795 else if (s.substr(1)=="Angstrom") {
796 string pr(s.substr(0,1));
797 return tex?"\\mathrm{"+pr+"\\AA}"
798 :(scm?"(concat \"<space>\" (math-up \"<nosymbol>"+pr+"<AA>\"))"
799 :mml_tag("mi",pr+"Å",idc,"class","MathML-Unit"));
800 } else if (s=="Ohm")
801 return tex?p+"\\Omega "
802 :(scm?p+"<space><nosymbol><Omega>":mml_tag("mi",p+"Ω",idc,"class","MathML-Unit"));
803 else if (s.substr(1)=="Ohm") {
804 string pr(s.substr(0,1));
805 return tex?"\\mathrm{"+pr+"}\\Omega "
806 :(scm?"(concat \"<space>\" (math-up \"<nosymbol>"+pr+"<Omega>\"))"
807 :mml_tag("mi",pr+"Ω",idc,"class","MathML-Unit"));
808 } else
809 return tex?"\\mathrm{"+p+s+"}"
810 :(scm?"(concat \"<space>\" (math-up \"<nosymbol>"+p+s+"\"))"
811 :mml_tag("mi",p+s,idc,(p+s).length()<2?" mathvariant":"","normal"));
812 }
813 }
814 /*
815 if (s_orig=="i")
816 return tex?"\\mathrm{i}":insert_id(mml_i,idc);
817 */
818 size_t i,len,len_sub;
819 string s,ssub,mdf="";
820 if (s_orig.rfind("_")==s_orig.size()-1 && is_greek_letter(s=s_orig.substr(0,s_orig.size()-1)))
821 return tex?"\\"+s+"\\_":(scm?"<"+s+">_":"&"+s+";_");
822 for (i=s_orig.size();i-->0;) {
823 if (!isdigit(s_orig[i]))
824 break;
825 }
826 s=s_orig.substr(0,i+1);
827 bool cnct=false;
828 if (i<s_orig.size()-1 && (s=="log" || s.size()==1 || is_greek_letter(s) || is_double_letter(s))) {
829 ssub=s_orig.substr(i+1);
830 cnct=true;
831 }
832 if (ssub.empty()) {
833 size_t pos=s_orig.find("_");
834 if (pos!=string::npos) {
835 s=s_orig.substr(0,pos);
836 if (s.size()==1 || is_greek_letter(s) || is_double_letter(s))
837 ssub=s_orig.substr(pos+1);
838 }
839 }
840 if (ssub.empty())
841 s=s_orig;
842 len=s.size();
843 if (is_greek_letter(s)) {
844 if ((tex || scm) && s=="phi")
845 s="varphi";
846 s=tex?"\\"+s:(scm?"<"+s+">":"&"+s+";");
847 len=1;
848 }
849 len_sub=ssub.size();
850 if (!ssub.empty() && is_greek_letter(ssub)) {
851 if ((tex || scm) && ssub=="phi")
852 ssub="varphi";
853 ssub=tex?"\\"+ssub:(scm?"<"+ssub+">":"&"+ssub+";");
854 len_sub=1;
855 }
856 if (is_double_letter(s)) {
857 s=s.substr(0,1);
858 if (tex) {
859 s="\\mathbf{"+s+"}";
860 len=1;
861 } else if (scm) {
862 s="<b-up-"+s+">";
863 len=1;
864 } else mdf="mathvariant";
865 }
866 if (len>3 && s[0]=='`' && s.at(1)==32 && s[s.size()-1]=='`')
867 s=s.substr(2,len-3);
868 string ret=(len==1?(tex || scm?s:mml_tag("mi",s,ssub.empty()?idc:0))
869 :(tex?"\\mathrm{"+s+"}":(scm?s:mml_tag("mi",s,ssub.empty()?idc:0,mdf,"bold"))));
870 if (!ssub.empty()) {
871 if (tex)
872 ret+="_{"+((len_sub==1 || atof(ssub.c_str())!=0)?ssub:"\\mathrm{"+ssub+"}")+"}";
873 else if (scm)
874 ret="(concat \""+ret+"\" "+(cnct?"":"\"<nosymbol>\" ")+"(rsub \""+ssub+"\"))";
875 else
876 ret=mml_tag("msub",ret+(ssub=="0" || atof(ssub.c_str())!=0?
877 "<mn>"+ssub+"</mn>":"<mi>"+ssub+"</mi>"),idc);
878 } else if (tex) {
879 int i=0;
880 while (i<(int)ret.length()) {
881 if (ret.at(i)=='_') {
882 ret.replace(i,1,"\\_");
883 i+=2;
884 } else ++i;
885 }
886 }
887 return ret;
888 }
889
flatten_operands(const gen & g)890 vecteur flatten_operands(const gen &g) {
891 assert(g.type==_SYMB);
892 vecteur ops;
893 gen &arg=g._SYMBptr->feuille;
894 if (arg.type!=_VECT)
895 ops.push_back(arg);
896 else {
897 vecteur &args=*arg._VECTptr;
898 for (int i=0;i<int(args.size());++i) {
899 gen op=args[i];
900 const_iterateur it;
901 if (op.type==_SYMB && op._SYMBptr->sommet==g._SYMBptr->sommet) {
902 vecteur subops=flatten_operands(op);
903 for (it=subops.begin();it!=subops.end();++it)
904 ops.push_back(*it);
905 } else
906 ops.push_back(op);
907 }
908 }
909 return ops;
910 }
911
parenthesize(MarkupBlock & ml,int flags)912 void parenthesize(MarkupBlock &ml,int flags) {
913 if ((flags & _MARKUP_LATEX)!=0)
914 ml.latex="\\left("+ml.latex+"\\right)";
915 if ((flags & _MARKUP_MATHML_PRESENTATION)!=0)
916 ml.markup="<mfenced>"+ml.markup+"</mfenced>";
917 if ((flags & _MARKUP_SCHEME)!=0)
918 ml.scheme="(around* \"(\" "+ml.scheme+" \")\")";
919 ml.priority=0;
920 }
921
scm_nobrackets(const string & s)922 string scm_nobrackets(const string &s) {
923 return "(around* \"<nobracket>\" "+s+" \"<nobracket>\")";
924 }
925
prepend_minus(MarkupBlock & ml,int flags,bool circled=false,bool mrow=true)926 void prepend_minus(MarkupBlock &ml,int flags,bool circled=false,bool mrow=true) {
927 if (!ml.neg)
928 return;
929 string id;
930 if (ml.priority>_PRIORITY_MUL)
931 parenthesize(ml,flags);
932 if ((flags & _MARKUP_LATEX)!=0)
933 ml.latex=(circled?"\\ominus ":"-")+ml.latex;
934 if ((flags & _MARKUP_SCHEME)!=0)
935 ml.scheme=scm_concat((circled?"\"<ominus>\" ":"\"-\" ")+ml.scheme);
936 if ((flags & _MARKUP_MATHML_CONTENT)!=0) {
937 if (mrow) {
938 id=extract_id(ml,true);
939 ml.content=mml_tag("apply","<minus/>"+ml.content,0,id.empty()?"":"id",id);
940 } else
941 ml.content="<apply><minus/>"+ml.content+"</apply>";
942 }
943 if ((flags & _MARKUP_MATHML_PRESENTATION)!=0) {
944 if (mrow) {
945 id=extract_id(ml,false);
946 ml.markup=mml_tag("mrow",(circled?"<mo>⊖</mo>":mml_minus)+ml.markup,
947 0,id.empty()?"":"xref",id);
948 } else ml.markup=(circled?"<mo>⊖</mo>":mml_minus)+ml.markup;
949 }
950 ml.neg=false;
951 ml.priority=_PRIORITY_MUL;
952 ml.type=_MLBLOCK_NEG;
953 }
954
assoc2markup(const vecteur & args,MarkupBlock & ml,const string & op,const string & opc,const string & opt,const string & ops,int flags,int & idc,GIAC_CONTEXT)955 void assoc2markup(const vecteur &args,MarkupBlock &ml,const string &op,
956 const string &opc,const string &opt,const string &ops,int flags,int &idc,
957 GIAC_CONTEXT) {
958 MarkupBlock tmp;
959 bool tex=(flags & _MARKUP_LATEX)!=0,
960 mml=(flags & _MARKUP_MATHML_PRESENTATION)!=0,
961 scm=(flags & _MARKUP_SCHEME)!=0,
962 cont=(flags & _MARKUP_MATHML_CONTENT)!=0;
963 for (const_iterateur it=args.begin();it!=args.end();++it) {
964 tmp=gen2markup(*it,flags,idc,contextptr);
965 prepend_minus(tmp,flags);
966 if ((tex || mml) && tmp.priority>=ml.priority)
967 parenthesize(tmp,flags);
968 if (it!=args.begin()) {
969 if (mml)
970 ml.markup+="<mo>"+op+"</mo>";
971 if (tex)
972 ml.latex+=opt;
973 if (scm)
974 ml.scheme+=" \""+ops+"\" ";
975 }
976 if (cont)
977 ml.content+=tmp.content;
978 if (mml)
979 ml.markup+=tmp.markup;
980 if (tex)
981 ml.latex+=tmp.latex;
982 if (scm)
983 ml.scheme+=tmp.scheme;
984 }
985 if (cont)
986 ml.content=mml_tag("apply",opc+ml.content,++idc);
987 if (mml)
988 ml.markup=mml_tag("mrow",ml.markup,idc);
989 if (scm)
990 ml.scheme=scm_concat(ml.scheme);
991 }
992
get_leftright(const gen & arg,MarkupBlock * ml,MarkupBlock & left,MarkupBlock & right,int flags,int & idc,GIAC_CONTEXT)993 void get_leftright(const gen &arg,MarkupBlock *ml,MarkupBlock &left,
994 MarkupBlock &right,int flags,int &idc,GIAC_CONTEXT) {
995 assert(arg.type==_VECT);
996 vecteur &args=*arg._VECTptr;
997 left=gen2markup(args.front(),flags,idc,contextptr);
998 prepend_minus(left,flags);
999 if (ml!=NULL && left.priority>=ml->priority)
1000 parenthesize(left,flags);
1001 right=gen2markup(args.back(),flags,idc,contextptr);
1002 prepend_minus(right,flags);
1003 if (ml!=NULL && right.priority>=ml->priority)
1004 parenthesize(right,flags);
1005 }
1006
is_partialdiff(const gen & g,identificateur & f,vecteur & deg,GIAC_CONTEXT)1007 bool is_partialdiff(const gen &g,identificateur &f,vecteur °,GIAC_CONTEXT) {
1008 gen df=g;
1009 deg.clear();
1010 while (df.is_symb_of_sommet(at_derive) && df._SYMBptr->feuille.type==_VECT) {
1011 const vecteur &args=*df._SYMBptr->feuille._VECTptr;
1012 if (args.size()!=2 || !args.back().is_integer() || !is_positive(args.back(),contextptr))
1013 return false;
1014 deg.push_back(args.back()+1);
1015 df=args.front();
1016 }
1017 if (df.type!=_IDNT || deg.empty()) return false;
1018 f=*df._IDNTptr;
1019 std::reverse(deg.begin(),deg.end());
1020 return true;
1021 }
1022
get_derive_vars(const vecteur & args,vecteur & vars)1023 bool get_derive_vars(const vecteur &args,vecteur &vars) {
1024 int n=args.size(),k;
1025 if (n==3 && args[1].type==_IDNT && args.back().is_integer() &&
1026 (k=args.back().val)>0) {
1027 if (!vars.empty() && vars.back()._VECTptr->front()==args[1])
1028 vars.back()._VECTptr->back()+=k;
1029 else vars.push_back(makevecteur(args[1],k));
1030 return true;
1031 }
1032 for (int i=1;i<n;++i) {
1033 const gen &g=args[i];
1034 if (g.is_symb_of_sommet(at_dollar)) {
1035 const gen &h=g._SYMBptr->feuille._VECTptr->front();
1036 const gen &m=g._SYMBptr->feuille._VECTptr->back();
1037 if (h.type!=_IDNT || !m.is_integer() || m.val<=0)
1038 return false;
1039 if (!vars.empty() && vars.back()._VECTptr->front()==h)
1040 vars.back()._VECTptr->back()+=m;
1041 vars.push_back(makevecteur(h,m));
1042 } else
1043 switch (g.type) {
1044 case _IDNT:
1045 if (!vars.empty() && vars.back()._VECTptr->front()==g)
1046 vars.back()._VECTptr->back()+=1;
1047 else vars.push_back(makevecteur(g,1));
1048 break;
1049 case _VECT:
1050 if (!get_derive_vars(*g._VECTptr,vars))
1051 return false;
1052 break;
1053 default:
1054 return false;
1055 }
1056 }
1057 return true;
1058 }
1059
is_elemfunc(const gen & g)1060 bool is_elemfunc(const gen &g) {
1061 return g.is_symb_of_sommet(at_ln) || g.is_symb_of_sommet(at_LN) ||
1062 g.is_symb_of_sommet(at_sin) || g.is_symb_of_sommet(at_SIN) ||
1063 g.is_symb_of_sommet(at_cos) || g.is_symb_of_sommet(at_COS) ||
1064 g.is_symb_of_sommet(at_sec) || g.is_symb_of_sommet(at_SEC) ||
1065 g.is_symb_of_sommet(at_csc) || g.is_symb_of_sommet(at_CSC) ||
1066 g.is_symb_of_sommet(at_tan) || g.is_symb_of_sommet(at_TAN) ||
1067 g.is_symb_of_sommet(at_cot) || g.is_symb_of_sommet(at_COT) ||
1068 g.is_symb_of_sommet(at_asec) || g.is_symb_of_sommet(at_ASEC) ||
1069 g.is_symb_of_sommet(at_acsc) || g.is_symb_of_sommet(at_ACSC) ||
1070 g.is_symb_of_sommet(at_asin) || g.is_symb_of_sommet(at_ASIN) ||
1071 g.is_symb_of_sommet(at_acos) || g.is_symb_of_sommet(at_ACOS) ||
1072 g.is_symb_of_sommet(at_atan) || g.is_symb_of_sommet(at_ATAN) ||
1073 g.is_symb_of_sommet(at_acot) || g.is_symb_of_sommet(at_ACOT) ||
1074 g.is_symb_of_sommet(at_sinh) || g.is_symb_of_sommet(at_SINH) ||
1075 g.is_symb_of_sommet(at_cosh) || g.is_symb_of_sommet(at_COSH) ||
1076 g.is_symb_of_sommet(at_tanh) || g.is_symb_of_sommet(at_TANH) ||
1077 g.is_symb_of_sommet(at_asinh) || g.is_symb_of_sommet(at_ASINH) ||
1078 g.is_symb_of_sommet(at_acosh) || g.is_symb_of_sommet(at_ACOSH) ||
1079 g.is_symb_of_sommet(at_atanh) || g.is_symb_of_sommet(at_ATANH);
1080 }
1081
func2markup(const gen & g,int typ,int idc=0)1082 string func2markup(const gen &g,int typ,int idc=0) {
1083 if (g.type==_FUNC) return func2markup(symbolic(*g._FUNCptr,vecteur(0)),typ,idc);
1084 bool tex=typ==0,scm=typ==1,content=typ==2;
1085 string ret;
1086 bool has_id=false;
1087 if (g.is_symb_of_sommet(at_ln) || g.is_symb_of_sommet(at_LN))
1088 ret=tex?"\\ln ":(scm?"ln":(content? "<ln/>":"<mi>ln</mi>"));
1089 else if (g.is_symb_of_sommet(at_sin) || g.is_symb_of_sommet(at_SIN))
1090 ret=tex?"\\sin ":(scm?"sin":(content? "<sin/>":"<mi>sin</mi>"));
1091 else if (g.is_symb_of_sommet(at_cos) || g.is_symb_of_sommet(at_COS))
1092 ret=tex?"\\cos ":(scm?"cos":(content? "<cos/>":"<mi>cos</mi>"));
1093 else if (g.is_symb_of_sommet(at_tan) || g.is_symb_of_sommet(at_TAN))
1094 ret=tex?"\\tan ":(scm?"tan":(content? "<tan/>":"<mi>tan</mi>"));
1095 else if (g.is_symb_of_sommet(at_cot) || g.is_symb_of_sommet(at_COT))
1096 ret=tex?"\\cot ":(scm?"cot":(content? "<cot/>":"<mi>cot</mi>"));
1097 else if (g.is_symb_of_sommet(at_sinh) || g.is_symb_of_sommet(at_SINH))
1098 ret=tex?"\\sinh ":(scm?"sinh":(content? "<sinh/>":"<mi>sinh</mi>"));
1099 else if (g.is_symb_of_sommet(at_cosh) || g.is_symb_of_sommet(at_COSH))
1100 ret=tex?"\\cosh ":(scm?"cosh":(content? "<cosh/>":"<mi>cosh</mi>"));
1101 else if (g.is_symb_of_sommet(at_tanh) || g.is_symb_of_sommet(at_TANH))
1102 ret=tex?"\\tanh ":(scm?"tanh":(content? "<tanh/>":"<mi>tanh</mi>"));
1103 else if (g.is_symb_of_sommet(at_asin) || g.is_symb_of_sommet(at_ASIN))
1104 ret=tex?"\\arcsin ":(scm?"arcsin":(content? "<arcsin/>":"<mi>arcsin</mi>"));
1105 else if (g.is_symb_of_sommet(at_acos) || g.is_symb_of_sommet(at_ACOS))
1106 ret=tex?"\\arccos ":(scm?"arccos":(content? "<arccos/>":"<mi>arccos</mi>"));
1107 else if (g.is_symb_of_sommet(at_atan) || g.is_symb_of_sommet(at_ATAN))
1108 ret=tex?"\\arctan ":(scm?"arctan":(content? "<arctan/>":"<mi>arctan</mi>"));
1109 else if (g.is_symb_of_sommet(at_acot) || g.is_symb_of_sommet(at_ACOT))
1110 ret=tex?"\\operatorname{arccot}":(scm?"arccot":(content? "<arccot/>":"<mi>arccot</mi>"));
1111 else if (g.is_symb_of_sommet(at_sec) || g.is_symb_of_sommet(at_SEC))
1112 ret=tex?"\\sec ":(scm?"sec":(content? "<sec/>":"<mi>sec</mi>"));
1113 else if (g.is_symb_of_sommet(at_csc) || g.is_symb_of_sommet(at_CSC))
1114 ret=tex?"\\csc ":(scm?"csc":(content? "<csc/>":"<mi>csc</mi>"));
1115 else if (g.is_symb_of_sommet(at_asec) || g.is_symb_of_sommet(at_ASEC))
1116 ret=tex?"\\operatorname{arcsec}"
1117 :(scm?"arcsec":(content? "<arcsec/>":"<mi>arcsec</mi>"));
1118 else if (g.is_symb_of_sommet(at_acsc) || g.is_symb_of_sommet(at_ACSC))
1119 ret=tex?"\\operatorname{arccsc}"
1120 :(scm?"arccsc":(content? "<arccsc/>":"<mi>arccsc</mi>"));
1121 else if (g.is_symb_of_sommet(at_asinh) || g.is_symb_of_sommet(at_ASINH))
1122 ret=tex?"\\operatorname{arsinh}"
1123 :(scm?"arsinh":(content? "<arcsinh/>":"<mi>arsinh</mi>"));
1124 else if (g.is_symb_of_sommet(at_acosh) || g.is_symb_of_sommet(at_ACOSH))
1125 ret=tex?"\\operatorname{arcosh}"
1126 :(scm?"arcosh":(content? "<arccosh/>":"<mi>arcosh</mi>"));
1127 else if (g.is_symb_of_sommet(at_atanh) || g.is_symb_of_sommet(at_ATANH))
1128 ret=tex?"\\operatorname{artanh}"
1129 :(scm?"artanh":(content? "<arctanh/>":"<mi>artanh</mi>"));
1130 else {
1131 if (g.is_symb_of_sommet(at_id) && content) ret="<ident/>";
1132 else if (g.is_symb_of_sommet(at_gcd) && content) ret="<gcd/>";
1133 else if (g.is_symb_of_sommet(at_lcm) && content) ret="<lcm/>";
1134 else if ((g.is_symb_of_sommet(at_irem) || g.is_symb_of_sommet(at_rem)) && content) ret="<rem/>";
1135 else if ((g.is_symb_of_sommet(at_iquo) || g.is_symb_of_sommet(at_quo)) && content) ret="<quotient/>";
1136 else if (g.is_symb_of_sommet(at_arg) && content) ret="<arg/>";
1137 else if (g.is_symb_of_sommet(at_max) && content) ret="<max/>";
1138 else if (g.is_symb_of_sommet(at_min) && content) ret="<min/>";
1139 else if (g.is_symb_of_sommet(at_det) && content) ret="<determinant/>";
1140 else if (g.is_symb_of_sommet(at_Dirac) && !content)
1141 ret=tex?(is_texmacs_compatible_latex_export?tm_Dirac:"\\operatorname{\\delta}")
1142 :(scm?"<up-delta>":"<mi>δ</mi>");
1143 else if (g.is_symb_of_sommet(at_Heaviside) && !content)
1144 ret=tex?(is_texmacs_compatible_latex_export?tm_Heaviside:"\\operatorname{\\theta}")
1145 :(scm?"<up-theta>":"<mi>θ</mi>");
1146 else if (g.is_symb_of_sommet(at_Gamma))
1147 ret=tex?"\\Gamma":(scm?"<Gamma>":(content?mml_csymbol("gamma","hypergeo0")
1148 :"<mi mathvariant='normal'>Γ</mi>"));
1149 else if (g.is_symb_of_sommet(at_Beta))
1150 ret=tex?"\\Beta":(scm?"<Beta>":(content?mml_csymbol("beta","hypergeo0")
1151 :"<mi mathvariant='normal'>Β</mi>"));
1152 else if (g.is_symb_of_sommet(at_euler))
1153 ret=tex?"\\phi":(content?mml_csymbol("euler","integer2")
1154 :"<mi mathvariant='normal'>φ</mi>");
1155 else if (g.is_symb_of_sommet(at_Airy_Ai))
1156 ret=tex?"\\operatorname{Ai}"
1157 :(scm?"Airy_Ai":(content?mml_csymbol("Ai","airy"):"<mi>Ai</mi>"));
1158 else if (g.is_symb_of_sommet(at_Airy_Bi))
1159 ret=tex?"\\operatorname{Bi}"
1160 :(scm?"Airy_Bi":(content?mml_csymbol("Bi","airy"):"<mi>Bi</mi>"));
1161 else if (g.is_symb_of_sommet(at_Psi) && !content)
1162 ret=tex?"\\Psi":(scm?"<Psi>":"<mi mathvariant='normal'>Ψ</mi>");
1163 else if (g.is_symb_of_sommet(at_Zeta) && !content)
1164 ret=tex?(is_texmacs_compatible_latex_export?tm_Zeta:"\\zeta")
1165 :(scm?"<up-zeta>":"<mi mathvariant='normal'>ζ</mi>");
1166 else {
1167 if (content)
1168 ret=mml_tag("ci",g._SYMBptr->sommet.ptr()->s,idc,"type","function");
1169 else
1170 ret=idnt2markup(g._SYMBptr->sommet.ptr()->s,typ,false,idc);
1171 has_id=true;
1172 }
1173 if (tex && ret.length()>1 && isalpha(ret.at(0)))
1174 ret="\\operatorname{"+ret+"}";
1175 }
1176 if (!tex && !scm && !has_id)
1177 ret=insert_id(ret,idc,content);
1178 return ret;
1179 }
1180
is_set_or_ident(const gen & g)1181 bool is_set_or_ident(const gen &g) {
1182 return (g.type==_VECT && g.subtype==_SEQ__VECT) || g.type==_IDNT ||
1183 (g.type==_INT_ && g.subtype==_INT_TYPE && (g.val==_ZINT || g.val==_CPLX ||
1184 g.val==_DOUBLE_ || g.val==_FRAC));
1185 }
1186
gen2markup(const gen & g,int flags_orig,int & idc,GIAC_CONTEXT)1187 MarkupBlock gen2markup(const gen &g,int flags_orig,int &idc,GIAC_CONTEXT) {
1188 int flags=flags_orig;
1189 bool toplevel=(flags & _MARKUP_TOPLEVEL)!=0;
1190 bool tex=(flags & _MARKUP_LATEX)!=0;
1191 bool scm=(flags & _MARKUP_SCHEME)!=0;
1192 bool isunit=(flags & _MARKUP_UNIT)!=0;
1193 bool mml_presentation=(flags & _MARKUP_MATHML_PRESENTATION)!=0;
1194 bool mml_content=(flags & _MARKUP_MATHML_CONTENT)!=0;
1195 bool isfactor=(flags & _MARKUP_FACTOR)!=0;
1196 bool vectarg,isbinary,isone;
1197 flags &= ~_MARKUP_TOPLEVEL;
1198 flags &= ~_MARKUP_FACTOR;
1199 string ld,rd,ld_tex,rd_tex,ld_scm,rd_scm,str;
1200 gen h;
1201 const gen *gp;
1202 MarkupBlock ml,tmp,left,right;
1203 size_t cpos;
1204 ml.priority=0;
1205 ml.type=_MLBLOCK_GENERAL;
1206 ml.neg=ml.appl=false;
1207 ml.markup.clear();
1208 ml.split_pos=-1;
1209 int st=g.subtype;
1210 switch (g.type) {
1211 case _INT_:
1212 case _ZINT:
1213 if (g.type==_INT_ && g.subtype!=0) {
1214 bool success=false;
1215 if (g.subtype==_INT_TYPE) {
1216 success=g.val==_ZINT || g.val==_FRAC || g.val==_CPLX || g.val==_DOUBLE_;
1217 if (success) {
1218 switch (g.val) {
1219 case _ZINT:
1220 if (mml_content)
1221 ml.content=insert_id("<integers/>",++idc,true);
1222 if (mml_presentation)
1223 ml.markup=mml_tag("mi","ℤ",idc);
1224 if (tex)
1225 ml.latex="\\mathbb{Z}";
1226 if (scm)
1227 ml.scheme="\"<bbb-Z>\"";
1228 break;
1229 case _FRAC:
1230 if (mml_content)
1231 ml.content=insert_id("<rationals/>",++idc,true);
1232 if (mml_presentation)
1233 ml.markup=mml_tag("mi","ℚ",idc);
1234 if (tex)
1235 ml.latex="\\mathbb{Q}";
1236 if (scm)
1237 ml.scheme="\"<bbb-Q>\"";
1238 break;
1239 case _CPLX:
1240 if (mml_content)
1241 ml.content=insert_id("<complexes/>",++idc,true);
1242 if (mml_presentation)
1243 ml.markup=mml_tag("mi","ℂ",idc);
1244 if (tex)
1245 ml.latex="\\mathbb{C}";
1246 if (scm)
1247 ml.scheme="\"<bbb-C>\"";
1248 break;
1249 case _DOUBLE_:
1250 if (mml_content)
1251 ml.content=insert_id("<reals/>",++idc,true);
1252 if (mml_presentation)
1253 ml.markup=mml_tag("mi","ℝ",idc);
1254 if (tex)
1255 ml.latex="\\mathbb{R}";
1256 if (scm)
1257 ml.scheme="\"<bbb-R>\"";
1258 break;
1259 }
1260 }
1261 }
1262 if (!success) {
1263 if (mml_content) {
1264 if (g.type==_INT_ && g.subtype==_INT_BOOLEAN)
1265 ml.content=insert_id((bool)g.val?"<true>":"<false>",++idc,true);
1266 else
1267 ml.content=mml_tag("ci",g.print(contextptr),++idc);
1268 }
1269 if (mml_presentation)
1270 ml.markup=idnt2markup(g.print(contextptr),2,false,idc);
1271 if (tex)
1272 ml.latex=idnt2markup(g.print(contextptr),0);
1273 if (scm)
1274 ml.scheme=scm_quote(idnt2markup(g.print(contextptr),1));
1275 ml.type=_MLBLOCK_SUBTYPE_IDNT;
1276 }
1277 } else {
1278 ml.type=_MLBLOCK_NUMERIC_EXACT;
1279 ml.neg=!is_positive(g,contextptr);
1280 str=_abs(g,contextptr).print(contextptr);
1281 if (mml_content)
1282 ml.content=mml_tag("cn",str,++idc,"type","integer");
1283 if (mml_presentation)
1284 ml.markup=mml_tag("mn",str,idc);
1285 if (tex)
1286 ml.latex=str;
1287 if (scm)
1288 ml.scheme=scm_quote(str);
1289 }
1290 ml.type|=_MLBLOCK_LEADING_DIGIT;
1291 return ml;
1292 case _DOUBLE_:
1293 case _REAL:
1294 case _FLOAT_:
1295 ml.type=_MLBLOCK_NUMERIC_APPROX;
1296 ml.neg=!is_positive(g,contextptr);
1297 if (isunit && is_zero(fPart(g,contextptr))) {
1298 ml.type=_MLBLOCK_NUMERIC_EXACT;
1299 str=_round(_abs(g,contextptr),contextptr).print(contextptr);
1300 if (mml_content)
1301 ml.content=mml_tag("cn",str,++idc,"type","integer");
1302 if (mml_presentation)
1303 ml.markup=mml_tag("mn",str,idc);
1304 if (tex)
1305 ml.latex=str;
1306 if (scm)
1307 ml.scheme=scm_quote(str);
1308 } else {
1309 str=_abs(g,contextptr).print(contextptr);
1310 if (mml_content)
1311 ml.content=mml_tag("cn",str,++idc,"type","double");
1312 if ((cpos=str.find('e'))!=string::npos &&
1313 atof(str.substr(0,cpos).c_str())!=0 && atof(str.substr(cpos+2).c_str())!=0) {
1314 ml.priority=_PRIORITY_MUL;
1315 string ex=str.substr(cpos+2);
1316 while (ex[0]=='0')
1317 ex.erase(ex.begin());
1318 string mant=str.substr(0,cpos);
1319 if (mant.find('.')==string::npos)
1320 mant+=".0";
1321 if (mml_presentation)
1322 ml.markup=mml_tag("mrow","<mn>"+mant+
1323 "</mn><mo>×</mo><msup><mn>10</mn><mrow>"+
1324 string(str[cpos+1]=='-'?mml_minus:"")+"<mn>"+ex+"</mn></mrow></msup>",idc);
1325 if (tex)
1326 ml.latex=mant+"\\times10^{"+string(str[cpos+1]=='-'?"-":"")+ex+"}";
1327 if (scm)
1328 ml.scheme="(concat \""+mant+"<times>10\" (rsup \""+string(str[cpos+1]=='-'?"-":"")+ex+"\"))";
1329 } else {
1330 if (mml_presentation)
1331 ml.markup=mml_tag("mn",str,idc);
1332 if (tex)
1333 ml.latex=str;
1334 if (scm)
1335 ml.scheme=scm_quote(str);
1336 }
1337 }
1338 ml.type|=_MLBLOCK_LEADING_DIGIT;
1339 return ml;
1340 case _CPLX:
1341 if (is_zero(im(g,contextptr)))
1342 return gen2markup(re(g,contextptr),flags,idc,contextptr);
1343 isone=is_one(_abs(im(g,contextptr),contextptr));
1344 if (is_zero(re(g,contextptr))) {
1345 if (isone) {
1346 if (mml_content)
1347 ml.content=insert_id("<imaginaryi/>",idc,true);
1348 if (mml_presentation)
1349 ml.markup=insert_id(mml_i,idc,false);
1350 if (tex)
1351 ml.latex=tex_mathi;
1352 if (scm)
1353 ml.scheme=scm_quote("<mathi>");
1354 ml.neg=is_minus_one(im(g,contextptr));
1355 } else {
1356 tmp=gen2markup(im(g,contextptr),flags | _MARKUP_FACTOR,idc,contextptr);
1357 ml.neg=tmp.neg;
1358 ml.priority=_PRIORITY_MUL;
1359 if (tmp.priority>=ml.priority)
1360 parenthesize(tmp,flags);
1361 if (mml_content)
1362 ml.content=mml_tag("apply","<times/><imaginaryi/>"+tmp.markup,++idc);
1363 if (mml_presentation)
1364 ml.markup=mml_tag("mrow",tmp.markup+mml_itimes+mml_i,idc);
1365 if (tex)
1366 ml.latex=tmp.latex+tex_itimes+tex_mathi;
1367 if (scm)
1368 ml.scheme=scm_concat(tmp.scheme+" \"*<mathi>\"");
1369 }
1370 return ml;
1371 }
1372 ml.priority=_PRIORITY_ADD;
1373 left=gen2markup(re(g,contextptr),flags,idc,contextptr);
1374 prepend_minus(left,flags);
1375 if (left.priority>=ml.priority)
1376 parenthesize(left,flags);
1377 right=gen2markup(im(g,contextptr),flags,idc,contextptr);
1378 if (right.priority>=_PRIORITY_MUL)
1379 parenthesize(right,flags);
1380 if (mml_content)
1381 ml.content=mml_tag("apply",(right.neg?"<minus/>":"<plus/>")+left.content+
1382 (isone?"<imaginaryi/>"
1383 :mml_tag("apply","<times/><imaginaryi/>"+right.content)),
1384 ++idc);
1385 if (mml_presentation)
1386 ml.markup=mml_tag("mrow",left.markup+(right.neg?mml_minus:mml_plus)+
1387 (isone?"":right.markup+mml_itimes)+mml_i,
1388 idc);
1389 if (tex)
1390 ml.latex=left.latex+(right.neg?"-":"+")+(isone?"":right.latex+tex_itimes)+tex_mathi;
1391 if (scm)
1392 ml.scheme=scm_concat(left.scheme+(right.neg?" \"-\" ":" \"+\" ")
1393 +(isone?"":right.scheme+" \"*\" ")+"\"<mathi>\"");
1394 return ml;
1395 case _FRAC:
1396 ml.type=_MLBLOCK_FRACTION;
1397 ml.priority=_PRIORITY_MUL;
1398 if (!is_zero(im(g._FRACptr->num,contextptr)))
1399 return gen2markup(symbolic(at_division,makesequence(g._FRACptr->num,g._FRACptr->den)),
1400 flags,idc,contextptr);
1401 ml.neg=!is_positive(g,contextptr);
1402 ld=_abs(g._FRACptr->num,contextptr).print(contextptr);
1403 rd=_abs(g._FRACptr->den,contextptr).print(contextptr);
1404 if (mml_content)
1405 ml.content=mml_tag("cn",ld+"<sep/>"+rd,++idc,"type","rational");
1406 if (mml_presentation)
1407 ml.markup=mml_tag("mfrac","<mn>"+ld+"</mn><mn>"+rd+"</mn>",idc);
1408 if (tex)
1409 ml.latex="\\frac{"+ld+"}{"+rd+"}";
1410 if (scm)
1411 ml.scheme="(frac \""+ld+"\" \""+rd+"\")";
1412 return ml;
1413 case _STRNG:
1414 if (g.subtype==-1)
1415 flags|=_MARKUP_ERROR;
1416 string2markup(ml,*g._STRNGptr,flags | _MARKUP_QUOTE,idc);
1417 return ml;
1418 case _IDNT:
1419 if (is_inf(g)) {
1420 if (mml_content)
1421 ml.content=insert_id("<infinity/>",++idc,true);
1422 if (mml_presentation)
1423 ml.markup=mml_tag("mi","∞",idc);
1424 if (tex)
1425 ml.latex="\\infty ";
1426 if (scm)
1427 ml.scheme=scm_quote("<infty>");
1428 } else if (g==cst_pi) {
1429 if (mml_content)
1430 ml.content=insert_id("<pi/>",++idc,true);
1431 if (mml_presentation)
1432 ml.markup=mml_tag("mi","π",idc);
1433 if (tex)
1434 ml.latex=(is_texmacs_compatible_latex_export?"\\mathpi ":"\\pi ");
1435 if (scm)
1436 ml.scheme=scm_quote("<mathpi>");
1437 } else if (g==cst_euler_gamma) {
1438 if (mml_content)
1439 ml.content=insert_id("<eulergamma/>",++idc,true);
1440 if (mml_presentation)
1441 ml.markup=mml_tag("mi","γ",idc);
1442 if (tex)
1443 ml.latex=(is_texmacs_compatible_latex_export?"\\matheuler ":"\\gamma ");
1444 if (scm)
1445 ml.scheme=scm_quote("<matheuler>");
1446 } else {
1447 if (mml_content) {
1448 str=g.print(contextptr);
1449 if (isunit && str.length()>2 && str[0]=='_' && str[str.size()-1]=='_')
1450 ml.content=constant2content(str.substr(1,str.length()-2),++idc);
1451 else if (isunit && str.length()>1 && str[0]=='_')
1452 ml.content=unit2content(str.substr(1),++idc);
1453 else
1454 ml.content=mml_tag("ci",str,++idc);
1455 }
1456 bool has_subscript=false;
1457 if (mml_presentation) {
1458 ml.markup=idnt2markup(g.print(contextptr),2,isunit,idc);
1459 has_subscript=is_substr(ml.markup,"<msub>");
1460 }
1461 if (tex) {
1462 ml.latex=idnt2markup(g.print(contextptr),0,isunit);
1463 has_subscript=is_substr(ml.latex,"_{");
1464 }
1465 if (scm) {
1466 ml.scheme=scm_quote(idnt2markup(g.print(contextptr),1,isunit));
1467 has_subscript=is_substr(ml.scheme,"(rsub ");
1468 }
1469 if (has_subscript)
1470 ml.type|=_MLBLOCK_HAS_SUBSCRIPT;
1471 }
1472 return ml;
1473 /*
1474 case _SPOL1:
1475 return gen2markup(spol12gen(*g._SPOL1ptr,contextptr),flags,idc,contextptr);
1476 */
1477 case _MAP:
1478 if (mml_presentation)
1479 ml.markup="<mtr style='background:lightgray'><mtd><mtext "
1480 "mathvariant='bold'>Key</mtext></mtd><mtd><mtext "
1481 "mathvariant='bold'>Value</mtext></mtd></mtr>";
1482 if (tex)
1483 ml.latex="\\begin{array}{|c|c|}\\hline\\mathbf{Key}&\\mathbf{Value}\\\\\\hline ";
1484 if (scm)
1485 ml.scheme="(block (tformat (cwith \"1\" \"1\" \"1\" \"-1\" \"cell-background\" \"pastel grey\")"
1486 "(table (row (cell (text (with \"font-series\" \"bold\" \"Key\")))"
1487 "(cell (text (with \"font-series\" \"bold\" \"Value\"))))";
1488 for (gen_map::const_iterator it=g._MAPptr->begin();
1489 it!=g._MAPptr->end();++it) {
1490 get_leftright(makevecteur(it->first,it->second),NULL,left,right,flags,idc,contextptr);
1491 if (mml_content)
1492 ml.content+=mml_tag("list",left.content+right.content);
1493 if (mml_presentation)
1494 ml.markup+="<mtr><mtd>"+left.markup+"</mtd><mtd>"+right.markup+"</mtd></mtr>";
1495 if (tex)
1496 ml.latex+=left.latex+"&"+right.latex+"\\\\\\hline ";
1497 if (scm)
1498 ml.scheme+=" (row (cell "+left.scheme+") (cell "+right.scheme+"))";
1499 }
1500 if (mml_content)
1501 ml.content=mml_tag("apply",mml_tag("ci","table")+ml.content,++idc);
1502 if (mml_presentation)
1503 ml.markup=mml_tag("mtable",ml.markup,idc,"frame","solid","rowlines",
1504 "solid","columnlines","solid","rowalign","center");
1505 if (tex)
1506 ml.latex+="\\end{array}";
1507 if (scm)
1508 ml.scheme+=")))";
1509 return ml;
1510 case _MOD:
1511 ml.priority=_PRIORITY_MUL;
1512 get_leftright(makevecteur(*g._MODptr,*(g._MODptr+1)),
1513 &ml,left,right,flags,idc,contextptr);
1514 if (mml_content)
1515 ml.content=mml_tag("apply","<ci>%</ci>"+left.content+right.content,++idc);
1516 if (mml_presentation)
1517 ml.markup=mml_tag("mrow",left.markup+"<mo>%</mo>"+right.markup,idc);
1518 if (tex)
1519 ml.latex=left.latex+"\\mathbin{\\%}"+right.latex;
1520 if (scm)
1521 ml.scheme=scm_concat(left.scheme+" \"%\" "+right.scheme);
1522 return ml;
1523 case _FUNC:
1524 if (mml_content)
1525 ml.content=func2markup(*g._FUNCptr,2,++idc);
1526 if (mml_presentation)
1527 ml.markup=func2markup(*g._FUNCptr,3,idc);
1528 if (tex)
1529 ml.latex=func2markup(*g._FUNCptr,0);
1530 if (scm)
1531 ml.scheme=scm_quote(func2markup(*g._FUNCptr,1));
1532 ml.type=_MLBLOCK_FUNC;
1533 return ml;
1534 case _VECT:
1535 if (st==_GRAPH__VECT && is_graphe(g,str,contextptr)) {
1536 if (mml_content)
1537 ml.content=mml_tag("cs",str,++idc);
1538 if (mml_presentation)
1539 ml.markup=mml_tag("mtext",str,idc);
1540 if (tex)
1541 ml.latex="\\text{"+str+"}";
1542 if (scm)
1543 ml.scheme="(text \""+str+"\")";
1544 return ml;
1545 }
1546 if (ckmatrix(*g._VECTptr) && (st==0 || st==_MATRIX__VECT)) {
1547 ml.type=_MLBLOCK_MATRIX;
1548 for (const_iterateur it=g._VECTptr->begin();it!=g._VECTptr->end();++it) {
1549 if (mml_content)
1550 ml.content+="<matrixrow>";
1551 if (mml_presentation)
1552 ml.markup+="<mtr>";
1553 if (tex)
1554 ml.latex+=(it==g._VECTptr->begin()?"":"\\\\");
1555 if (scm)
1556 ml.scheme+=" (row";
1557 for (const_iterateur jt=it->_VECTptr->begin();jt!=it->_VECTptr->end();++jt) {
1558 tmp=gen2markup(*jt,flags,idc,contextptr);
1559 prepend_minus(tmp,flags);
1560 if (mml_content)
1561 ml.content+=tmp.content;
1562 if (mml_presentation)
1563 ml.markup+="<mtd>"+tmp.markup+"</mtd>";
1564 if (tex)
1565 ml.latex+=(jt==it->_VECTptr->begin()?"":"&")+tmp.latex;
1566 if (scm)
1567 ml.scheme+=" (cell "+tmp.scheme+")";
1568 }
1569 if (mml_content)
1570 ml.content+="</matrixrow>";
1571 if (mml_presentation)
1572 ml.markup+="</mtr>";
1573 if (scm)
1574 ml.scheme+=")";
1575 }
1576 if (mml_content)
1577 ml.content=mml_tag("matrix",ml.content,++idc);
1578 if (st==0) {
1579 ld="[";
1580 rd="]";
1581 } else {
1582 ld="(";
1583 rd=")";
1584 }
1585 if (mml_presentation)
1586 ml.markup=mml_tag("mfenced","<mtable>"+ml.markup+"</mtable>",
1587 idc,"open",ld,"close",rd);
1588 if (tex)
1589 ml.latex="\\left"+ld+"\\begin{array}{"+string(g._VECTptr->front()._VECTptr->size(),'c')+"}"+
1590 ml.latex+"\\end{array}\\right"+rd;
1591 if (scm)
1592 ml.scheme="(matrix (tformat (table"+ml.scheme+")))";
1593 return ml;
1594 }
1595 for (const_iterateur it=g._VECTptr->begin();it!=g._VECTptr->end();++it) {
1596 tmp=gen2markup(*it,flags,idc,contextptr);
1597 prepend_minus(tmp,flags);
1598 if (mml_content)
1599 ml.content+=tmp.content;
1600 if (mml_presentation)
1601 ml.markup+=tmp.markup;
1602 if (tex)
1603 ml.latex+=(it==g._VECTptr->begin()?"":",")+tmp.latex;
1604 if (scm)
1605 ml.scheme+=(it==g._VECTptr->begin()?"":" \",\" ")+tmp.scheme;
1606 }
1607 switch (st) {
1608 case _SEQ__VECT:
1609 if (mml_content)
1610 ml.content=mml_tag("list",ml.content,++idc);
1611 ld_scm=ld_tex=ld=toplevel?"":"(";
1612 rd_scm=rd_tex=rd=toplevel?"":")";
1613 break;
1614 case _SET__VECT:
1615 if (g._VECTptr->empty()) {
1616 if (mml_content)
1617 ml.content=insert_id("<emptyset/>",++idc,true);
1618 if (mml_presentation)
1619 ml.markup=mml_tag("mi","∅",idc);
1620 if (tex)
1621 ml.latex="\\emptyset ";
1622 if (scm)
1623 ml.scheme=scm_quote("<emptyset>");
1624 return ml;
1625 }
1626 if (mml_content)
1627 ml.content=mml_tag("set",ml.content,++idc);
1628 ld=ld_scm="{";
1629 rd=rd_scm="}";
1630 ld_tex="\\{";
1631 rd_tex="\\}";
1632 break;
1633 case _POLY1__VECT:
1634 if (mml_content)
1635 ml.content=mml_tag("vector",ml.content,++idc);
1636 ld_tex=ld="[";
1637 rd_tex=rd="]";
1638 ld_scm="<llbracket>";
1639 rd_scm="<rrbracket>";
1640 break;
1641 default:
1642 if (mml_content)
1643 ml.content=mml_tag("vector",ml.content,++idc);
1644 ld_tex=ld_scm=ld="[";
1645 rd_tex=rd_scm=rd="]";
1646 break;
1647 }
1648 if (mml_presentation)
1649 ml.markup=mml_tag("mfenced",ml.markup,idc,"open",ld,"close",rd);
1650 if (tex)
1651 ml.latex=(ld_tex.empty()?"":"\\left"+ld_tex)+ml.latex+(rd_tex.empty()?"":"\\right"+rd_tex);
1652 if (scm) {
1653 if (g._VECTptr->size()>1)
1654 ml.scheme=scm_concat(ml.scheme);
1655 else if (g._VECTptr->empty())
1656 ml.scheme="\"\"";
1657 if (!ld_scm.empty() && !rd_scm.empty())
1658 ml.scheme="(around* \""+ld_scm+"\" "+ml.scheme+" \""+rd_scm+"\")";
1659 }
1660 return ml;
1661 case _SYMB:
1662 vectarg=g._SYMBptr->feuille.type==_VECT;
1663 isbinary=(vectarg && g._SYMBptr->feuille._VECTptr->size()==2);
1664 if (g.is_symb_of_sommet(at_neg)) {
1665 ml=gen2markup(g._SYMBptr->feuille,flags,idc,contextptr);
1666 ml.neg=!ml.neg;
1667 return ml;
1668 }
1669 if (g.is_symb_of_sommet(at_epsilon)) {
1670 if (tex)
1671 ml.latex="\\varepsilon ";
1672 if (mml_presentation)
1673 ml.markup="ε";
1674 if (mml_content)
1675 ml.content=mml_tag("ci",g.print(contextptr),++idc);
1676 if (scm)
1677 ml.scheme=scm_quote("<varepsilon>");
1678 return ml;
1679 }
1680 if (g.is_symb_of_sommet(at_plus) || g.is_symb_of_sommet(at_pointplus)) {
1681 const gen &arg=g._SYMBptr->feuille;
1682 if (vectarg) {
1683 ml.priority=_PRIORITY_ADD;
1684 vecteur args=flatten_operands(g);
1685 for (const_iterateur it=args.begin();it!=args.end();++it) {
1686 tmp=gen2markup(*it,flags,idc,contextptr);
1687 if (!tmp.neg && it!=args.begin()) {
1688 if (mml_presentation)
1689 ml.markup+=(g.is_symb_of_sommet(at_plus)?mml_plus:"<mo>⊕</mo>");
1690 if (tex)
1691 ml.latex+=(g.is_symb_of_sommet(at_plus)?"+":"\\oplus ");
1692 if (scm)
1693 ml.scheme+=(g.is_symb_of_sommet(at_plus)?" \"+\" ":" \"<oplus>\" ");
1694 }
1695 prepend_minus(tmp,flags,g.is_symb_of_sommet(at_pointplus),false);
1696 if (tmp.priority>=ml.priority)
1697 parenthesize(tmp,flags);
1698 if (mml_content)
1699 ml.content+=tmp.content;
1700 if (mml_presentation)
1701 ml.markup+=tmp.markup;
1702 if (tex)
1703 ml.latex+=tmp.latex;
1704 if (scm)
1705 ml.scheme+=tmp.scheme;
1706 }
1707 if (mml_content)
1708 ml.content=mml_tag(
1709 "apply",(g.is_symb_of_sommet(at_plus)?"<plus/>":"<ci>.+</ci>")+ml.content,++idc);
1710 if (mml_presentation)
1711 ml.markup=mml_tag("mrow",ml.markup,idc);
1712 if (scm)
1713 ml.scheme=scm_concat(ml.scheme);
1714 } else if (g.is_symb_of_sommet(at_plus)) {
1715 ml=gen2markup(arg,flags,idc,contextptr);
1716 if (!ml.neg && ml.priority==0) {
1717 string id;
1718 if (mml_content) {
1719 id=extract_id(ml,true);
1720 ml.content=mml_tag("apply","<plus/>"+ml.content,0,"id",id);
1721 }
1722 if (mml_presentation) {
1723 id=extract_id(ml,false);
1724 ml.markup=mml_tag("mrow",mml_plus+ml.markup,0,"xref",id);
1725 }
1726 if (tex)
1727 ml.latex="+"+ml.latex;
1728 if (scm)
1729 ml.scheme="(concat \"+\" "+ml.scheme+")";
1730 ml.priority=_PRIORITY_ADD;
1731 }
1732 }
1733 return ml;
1734 }
1735 if (g.is_symb_of_sommet(at_pointminus) && vectarg && isbinary) {
1736 ml.priority=_PRIORITY_ADD;
1737 get_leftright(g._SYMBptr->feuille,NULL,left,right,flags,idc,contextptr);
1738 prepend_minus(left,flags);
1739 if (left.priority>=ml.priority)
1740 parenthesize(left,flags);
1741 if (mml_content)
1742 ml.content=mml_tag("apply","<ci>"+string(right.neg?".+":".-")+"</ci>"+
1743 left.content+right.content,
1744 ++idc);
1745 if (right.priority>=ml.priority)
1746 parenthesize(right,flags);
1747 if (mml_presentation)
1748 ml.markup=mml_tag("mrow",left.markup+(right.neg?"<mo>⊕</mo>":"<mo>⊖</mo>")
1749 +right.markup,idc);
1750 if (tex)
1751 ml.latex=left.latex+(right.neg?"\\oplus ":"\\ominus ")+right.latex;
1752 if (scm)
1753 ml.scheme=scm_concat(left.scheme+(right.neg?" \"<oplus>\" ":" \"<ominus>\" ")+right.scheme);
1754 return ml;
1755 }
1756 if ((g.is_symb_of_sommet(at_prod) || g.is_symb_of_sommet(at_ampersand_times)) && vectarg) {
1757 int neg_count=0,num_count=0,den_count=0,nc=0,dc=0;
1758 MarkupBlock pden,pnum,prev;
1759 string num,numc,numt,nums,den,denc,dent,dens,prod_sign,prod_sign_tex,prod_sign_scm;
1760 vecteur args=flatten_operands(g),ncnst,cnsts;
1761 for (int i=args.size();i-->0;) {
1762 if (args[i].is_integer() || args[i].type==_FRAC) {
1763 ncnst.push_back(args[i]);
1764 args.erase(args.begin()+i);
1765 } else if (args[i]==cst_pi || args[i]==cst_euler_gamma) {
1766 cnsts.push_back(args[i]);
1767 args.erase(args.begin()+i);
1768 } else if (args[i].type==_CPLX && is_zero(re(args[i],contextptr)) &&
1769 !is_one(im(args[i],contextptr))) {
1770 if (is_minus_one(im(args[i],contextptr)))
1771 ml.neg=!ml.neg;
1772 else cnsts.push_back(im(args[i],contextptr));
1773 args[i]=cst_i;
1774 }
1775 }
1776 args=mergevecteur(mergevecteur(ncnst,cnsts),args);
1777 ml.priority=_PRIORITY_MUL;
1778 pden.type=_MLBLOCK_GENERAL;
1779 pden.appl=false;
1780 pden.priority=0;
1781 pnum.type=_MLBLOCK_GENERAL;
1782 pnum.appl=false;
1783 pnum.priority=0;
1784 bool isinv,hasleadingfrac=true,is_cdot;
1785 int ni,di,np=-1,dp=-1;
1786 for (iterateur it=args.begin();it!=args.end();++it) {
1787 if (it->is_symb_of_sommet(at_inv)) {
1788 den_count++;
1789 if (!hasleadingfrac)
1790 continue;
1791 if (it->_SYMBptr->feuille.type==_INT_ && dp<0)
1792 dp=it-args.begin();
1793 else {
1794 dp=-1;
1795 hasleadingfrac=false;
1796 }
1797 } else {
1798 num_count++;
1799 if (hasleadingfrac && np<0 && it->type==_INT_)
1800 np=it-args.begin();
1801 }
1802 }
1803 if (num_count==1 || dp<0)
1804 hasleadingfrac=false;
1805 if (hasleadingfrac) {
1806 di=args[dp]._SYMBptr->feuille.val;
1807 args.erase(args.begin()+dp);
1808 if (np>dp)
1809 np--;
1810 if (np<0)
1811 args.insert(args.begin(),fraction(1,di));
1812 else {
1813 ni=args[np].val;
1814 args.erase(args.begin()+np);
1815 args.insert(args.begin(),fraction(ni,di));
1816 }
1817 num_count=den_count=0;
1818 for (const_iterateur it=args.begin();it!=args.end();++it) {
1819 if (it->is_symb_of_sommet(at_inv))
1820 den_count++;
1821 else
1822 num_count++;
1823 }
1824 }
1825 for (const_iterateur it=args.begin();it!=args.end();++it) {
1826 isinv=it->is_symb_of_sommet(at_inv);
1827 int flg=flags;
1828 if ((isinv && den_count>1) || (!isinv && num_count>1))
1829 flg|=_MARKUP_FACTOR;
1830 gen fc=isinv?it->_SYMBptr->feuille:*it;
1831 tmp=gen2markup(fc,flg,idc,contextptr);
1832 if (tmp.neg)
1833 neg_count++;
1834 if (isinv) {
1835 dc++;
1836 prev=pden;
1837 } else {
1838 nc++;
1839 prev=pnum;
1840 }
1841 if (((!isinv && num_count>1) || (isinv && den_count>1)) &&
1842 (tmp.priority>ml.priority || (tmp.priority==ml.priority && fc.type!=_CPLX)) &&
1843 (!tmp.ctype(_MLBLOCK_FRACTION) &&
1844 (!tmp.ctype(_MLBLOCK_SUMPROD) || (!isinv && nc<num_count) ||
1845 (isinv && dc<den_count))))
1846 parenthesize(tmp,flags);
1847 is_cdot=
1848 tmp.ctype(_MLBLOCK_LEADING_DIGIT) || tmp.ctype(_MLBLOCK_SUBTYPE_IDNT) ||
1849 tmp.ctype(_MLBLOCK_FACTORIAL) || prev.ctype(_MLBLOCK_SUBTYPE_IDNT) ||
1850 (tmp.ctype(_MLBLOCK_FRACTION) && prev.ctype(_MLBLOCK_FRACTION)) ||
1851 (prev.ctype(_MLBLOCK_ELEMAPP) && prev.appl);
1852 prod_sign=is_cdot?mml_cdot:mml_itimes;
1853 prod_sign_tex=is_cdot?"\\cdot ":tex_itimes;
1854 prod_sign_scm=is_cdot?" \"<cdot>\" ":" \"*\" ";
1855 if (isinv) {
1856 pden=tmp;
1857 if (mml_content)
1858 denc+=tmp.content;
1859 if (mml_presentation)
1860 den+=(den.empty()?"":prod_sign)+tmp.markup;
1861 if (tex)
1862 dent+=(dent.empty()?"":prod_sign_tex)+tmp.latex;
1863 if (scm)
1864 dens+=(dens.empty()?"":prod_sign_scm)+tmp.scheme;
1865 } else {
1866 pnum=tmp;
1867 if (mml_content)
1868 numc+=tmp.content;
1869 if (mml_presentation)
1870 num+=(num.empty()?"":prod_sign)+tmp.markup;
1871 if (tex)
1872 numt+=(numt.empty()?"":prod_sign_tex)+tmp.latex;
1873 if (scm)
1874 nums+=(nums.empty()?"":prod_sign_scm)+tmp.scheme;
1875 }
1876 }
1877 if (neg_count % 2) ml.neg=!ml.neg;
1878 if (mml_content && numc.empty())
1879 numc="<cn type='integer'>1</cn>";
1880 if (mml_presentation && num.empty())
1881 num="<mn>1</mn>";
1882 if (tex && numt.empty())
1883 numt="1";
1884 if (scm && nums.empty())
1885 nums=scm_quote("1");
1886 if (mml_content && denc.empty())
1887 ml.content=mml_tag("apply","<times/>"+numc,++idc);
1888 else if (mml_content) {
1889 ml.type=_MLBLOCK_FRACTION;
1890 ml.content=mml_tag("apply","<divide/>"+numc+denc,++idc);
1891 }
1892 if (mml_presentation && den.empty())
1893 ml.markup=mml_tag("mrow",num,idc);
1894 else if (mml_presentation) {
1895 ml.type=_MLBLOCK_FRACTION;
1896 ml.markup=mml_tag("mfrac",num+den,idc);
1897 }
1898 if (tex && dent.empty())
1899 ml.latex=numt;
1900 else if (tex) {
1901 ml.type=_MLBLOCK_FRACTION;
1902 ml.latex="\\frac{"+numt+"}{"+dent+"}";
1903 }
1904 if (scm) {
1905 if (nc>1)
1906 nums=scm_concat(nums);
1907 if (dens.empty())
1908 ml.scheme=nums;
1909 else {
1910 if (dc>1)
1911 dens=scm_concat(dens);
1912 ml.type=_MLBLOCK_FRACTION;
1913 ml.scheme="(frac "+nums+" "+dens+")";
1914 }
1915 }
1916 return ml;
1917 }
1918 if (g.is_symb_of_sommet(at_pointprod) && vectarg) {
1919 ml.priority=_PRIORITY_MUL;
1920 vecteur args=flatten_operands(g);
1921 for (const_iterateur it=args.begin();it!=args.end();++it) {
1922 tmp=gen2markup(*it,flags,idc,contextptr);
1923 prepend_minus(tmp,flags);
1924 if (tmp.priority>=ml.priority)
1925 parenthesize(tmp,flags);
1926 if (mml_content)
1927 ml.content+=tmp.content;
1928 if (mml_presentation)
1929 ml.markup+=(it==args.begin()?"":"<mo>⊙</mo>")+tmp.markup;
1930 if (tex)
1931 ml.latex+=(it==args.begin()?"":"\\odot ")+tmp.latex;
1932 if (scm)
1933 ml.scheme+=(it==args.begin()?"":" \"<odot>\" ")+tmp.scheme;
1934 }
1935 if (mml_content)
1936 ml.content=mml_tag("apply","<ci>.*</ci>"+ml.content,++idc);
1937 if (mml_presentation)
1938 ml.markup=mml_tag("mrow",ml.markup,idc);
1939 if (scm && args.size()>1)
1940 ml.scheme=scm_concat(ml.scheme);
1941 return ml;
1942 }
1943 if ((g.is_symb_of_sommet(at_dot) || g.is_symb_of_sommet(at_dotP) ||
1944 g.is_symb_of_sommet(at_scalarProduct) ||
1945 g.is_symb_of_sommet(at_scalar_product) || g.is_symb_of_sommet(at_dotprod) ||
1946 g.is_symb_of_sommet(at_cross) ||
1947 g.is_symb_of_sommet(at_crossP) || g.is_symb_of_sommet(at_crossproduct)) &&
1948 vectarg && isbinary) {
1949 ml.priority=_PRIORITY_MUL;
1950 get_leftright(g._SYMBptr->feuille,&ml,left,right,flags,idc,
1951 contextptr);
1952 bool is_cross=(g.is_symb_of_sommet(at_cross) || g.is_symb_of_sommet(at_crossP) ||
1953 g.is_symb_of_sommet(at_crossproduct));
1954 if (mml_content)
1955 ml.content=mml_tag("apply",(is_cross?"<vectorproduct/>":"<scalarproduct/>")+
1956 left.content+right.content,
1957 ++idc);
1958 if (mml_presentation)
1959 ml.markup=mml_tag(
1960 "mrow",left.markup+(is_cross?mml_times:mml_dot)+right.markup,idc);
1961 if (tex)
1962 ml.latex=left.latex+(is_cross?"\\times ":"\\cdot ")+right.latex;
1963 if (scm)
1964 ml.scheme=scm_concat(left.scheme+(is_cross?" \"<times>\" ":" \"<cdot>\" ")+right.scheme);
1965 return ml;
1966 }
1967 if (g.is_symb_of_sommet(at_inv)) {
1968 tmp=gen2markup(g._SYMBptr->feuille,flags,idc,contextptr);
1969 ml.neg=tmp.neg;
1970 ml.type=_MLBLOCK_FRACTION;
1971 ml.priority=_PRIORITY_MUL;
1972 if (mml_content)
1973 ml.content=mml_tag("apply","<divide/><cn type='integer'>1</cn>"+tmp.content,++idc);
1974 if (mml_presentation)
1975 ml.markup=mml_tag("mfrac","<mn>1</mn>"+tmp.markup,idc);
1976 if (tex)
1977 ml.latex="\\frac1{"+tmp.latex+"}";
1978 if (scm)
1979 ml.scheme="(frac \"1\" "+tmp.scheme+")";
1980 return ml;
1981 }
1982 if ((g.is_symb_of_sommet(at_division) || g.is_symb_of_sommet(at_rdiv)) && vectarg && isbinary) {
1983 const vecteur &args=*g._SYMBptr->feuille._VECTptr;
1984 MarkupBlock num,den;
1985 ml.type=_MLBLOCK_FRACTION;
1986 ml.priority=_PRIORITY_MUL;
1987 num=gen2markup(args.front(),flags,idc,contextptr);
1988 den=gen2markup(args.back(),flags,idc,contextptr);
1989 ml.neg=(num.neg!=den.neg);
1990 if (mml_content)
1991 ml.content=mml_tag("apply","<divide/>"+num.content+den.content,++idc);
1992 if (mml_presentation)
1993 ml.markup=mml_tag("mfrac",num.markup+den.markup,idc);
1994 if (tex)
1995 ml.latex="\\frac{"+num.latex+"}{"+den.latex+"}";
1996 if (scm)
1997 ml.scheme="(frac "+num.scheme+" "+den.scheme+")";
1998 return ml;
1999 }
2000 if (g.is_symb_of_sommet(at_pointdivision) && vectarg && isbinary) {
2001 ml.priority=_PRIORITY_MUL;
2002 get_leftright(g._SYMBptr->feuille,&ml,left,right,flags,idc,contextptr);
2003 if (mml_content)
2004 ml.content=mml_tag(
2005 "apply","<ci>./</ci>"+left.content+right.content,++idc);
2006 if (mml_presentation)
2007 ml.markup=mml_tag(
2008 "mrow",left.markup+"<mo>ø</mo>"+right.markup,idc);
2009 if (tex)
2010 ml.latex=left.latex+"\\oslash "+right.latex;
2011 if (scm)
2012 ml.scheme=scm_concat(left.scheme+" \"<oslash>\" "+right.scheme);
2013 return ml;
2014 }
2015 if (g.is_symb_of_sommet(at_conj)) {
2016 tmp=gen2markup(g._SYMBptr->feuille,flags,idc,contextptr);
2017 if (isfactor && tmp.priority>_PRIORITY_MUL)
2018 parenthesize(tmp,flags);
2019 if (tmp.ctype(_MLBLOCK_LEADING_DIGIT))
2020 ml.type=_MLBLOCK_LEADING_DIGIT;
2021 ml.priority=_PRIORITY_UNARY;
2022 ml.neg=tmp.neg;
2023 if (mml_content)
2024 ml.content=mml_tag("apply","<conjugate/>"+tmp.content,++idc);
2025 if (mml_presentation)
2026 ml.markup=mml_tag("mover",tmp.markup+"<mo>¯</mo>",idc);
2027 if (tex)
2028 ml.latex="\\overline{"+tmp.latex+"}";
2029 if (scm)
2030 ml.scheme="(wide "+tmp.scheme+" \"<bar>\")";
2031 return ml;
2032 }
2033 if (g.is_symb_of_sommet(at_exp) || g.is_symb_of_sommet(at_EXP)) {
2034 if (is_one(g._SYMBptr->feuille)) {
2035 ml.priority=0;
2036 if (mml_content)
2037 ml.content=insert_id("<exponentiale/>",++idc,true);
2038 if (mml_presentation)
2039 ml.markup=insert_id(mml_e,idc,false);
2040 if (tex)
2041 ml.latex=tex_mathe;
2042 if (scm)
2043 ml.scheme=scm_quote("<mathe>");
2044 } else {
2045 tmp=gen2markup(g._SYMBptr->feuille,flags,idc,contextptr);
2046 prepend_minus(tmp,flags);
2047 ml.priority=_PRIORITY_EXP;
2048 ml.type=_MLBLOCK_POWER;
2049 if (mml_content)
2050 ml.content=mml_tag("apply","<exp/>"+tmp.content,++idc);
2051 if (mml_presentation)
2052 ml.markup=mml_tag("msup",mml_e+tmp.markup,idc);
2053 if (tex)
2054 ml.latex=tex_mathe+"^{"+tmp.latex+"}";
2055 if (scm)
2056 ml.scheme="(concat \"<mathe>\" (rsup "+tmp.scheme+"))";
2057 }
2058 return ml;
2059 }
2060 if (g.is_symb_of_sommet(at_sq)) {
2061 ml.priority=_PRIORITY_EXP;
2062 ml.type=_MLBLOCK_POWER;
2063 tmp=gen2markup(g._SYMBptr->feuille,flags,idc,contextptr);
2064 if (tmp.priority>=ml.priority)
2065 parenthesize(tmp,flags);
2066 if (mml_content)
2067 ml.content=mml_tag("apply","<power/>"+tmp.content+"<cn type='integer'>2</cn>",++idc);
2068 if (mml_presentation)
2069 ml.markup=mml_tag("msup",tmp.markup+"<mn>2</mn>",idc);
2070 if (tex)
2071 ml.latex=tmp.latex+"^{2}";
2072 if (scm)
2073 ml.scheme=scm_concat(tmp.scheme+" (rsup \"2\")");
2074 return ml;
2075 }
2076 if (g.is_symb_of_sommet(at_sqrt)) {
2077 ml.priority=_PRIORITY_UNARY;
2078 ml.type=_MLBLOCK_ROOT;
2079 tmp=gen2markup(g._SYMBptr->feuille,flags,idc,contextptr);
2080 prepend_minus(tmp,flags);
2081 if (mml_content)
2082 ml.content=mml_tag("apply","<root/>"+tmp.content,++idc);
2083 if (mml_presentation)
2084 ml.markup=mml_tag("msqrt",tmp.markup,idc);
2085 if (tex)
2086 ml.latex="\\sqrt{"+tmp.latex+"}";
2087 if (scm)
2088 ml.scheme="(sqrt "+tmp.scheme+")";
2089 return ml;
2090 }
2091 if (g.is_symb_of_sommet(at_maple_root) && vectarg) {
2092 ml.priority=_PRIORITY_UNARY;
2093 ml.type=_MLBLOCK_ROOT;
2094 const vecteur &args=*g._SYMBptr->feuille._VECTptr;
2095 right=gen2markup(args.front(),flags,idc,contextptr);
2096 prepend_minus(right,flags);
2097 left=gen2markup(args.back(),flags,idc,contextptr);
2098 prepend_minus(left,flags);
2099 if (mml_content)
2100 ml.content=mml_tag("apply","<root/><degree>"+right.content+"</degree>"+left.content,++idc);
2101 if (mml_presentation)
2102 ml.markup=mml_tag("mroot",left.markup+right.markup,idc);
2103 if (tex)
2104 ml.latex="\\sqrt["+right.latex+"]{"+left.latex+"}";
2105 if (scm)
2106 ml.scheme="(sqrt "+left.scheme+" "+right.scheme+")";
2107 return ml;
2108 }
2109 if ((g.is_symb_of_sommet(at_pow) || g.is_symb_of_sommet(at_matpow) ||
2110 g.is_symb_of_sommet(at_pointpow)) && vectarg && isbinary) {
2111 ml.priority=_PRIORITY_EXP;
2112 const vecteur &args=*g._SYMBptr->feuille._VECTptr;
2113 left=gen2markup(args.front(),flags,idc,contextptr);
2114 prepend_minus(left,flags);
2115 if (g.is_symb_of_sommet(at_pow) && is_one(2*args.back())) {
2116 ml.type=_MLBLOCK_ROOT;
2117 ml.priority=_PRIORITY_UNARY;
2118 if (mml_content)
2119 ml.content=mml_tag("apply","<root/>"+left.content,++idc);
2120 if (mml_presentation)
2121 ml.markup=mml_tag("msqrt",left.markup,idc);
2122 if (tex)
2123 ml.latex="\\sqrt{"+left.latex+"}";
2124 if (scm)
2125 ml.scheme="(sqrt "+left.scheme+")";
2126 } else {
2127 right=gen2markup(args.back(),flags,idc,contextptr);
2128 prepend_minus(right,flags);
2129 if (mml_content)
2130 ml.content=mml_tag("apply",(g.is_symb_of_sommet(at_pointpow)?"<ci>.^</ci>":"<power/>")+
2131 left.content+right.content,
2132 ++idc);
2133 if ((flags & _MARKUP_ELEMPOW)!=0 && g.is_symb_of_sommet(at_pow) &&
2134 right.priority==0 && !is_one(_abs(args.back(),contextptr)) &&
2135 left.ctype(_MLBLOCK_ELEMAPP) && left.split_pos>=0) {
2136 ml.type=_MLBLOCK_ELEMAPP;
2137 ml.appl=left.appl;
2138 if (mml_presentation) {
2139 size_t pos=left.markup.find(">");
2140 assert(pos!=string::npos);
2141 ml.markup=left.markup.substr(0,pos+1)+"<msup>"+left.markup.substr(pos+1,left.split_pos)+
2142 right.markup+"</msup>"+left.markup.substr(left.split_pos+pos+1);
2143 }
2144 if (tex)
2145 ml.latex=left.latex.substr(0,left.split_pos_tex)+"^{"+right.latex+"}"+
2146 left.latex.substr(left.split_pos_tex);
2147 if (scm)
2148 ml.scheme=scm_concat(left.scheme.substr(0,left.split_pos_scm)+
2149 " (rsup "+right.scheme+") "+left.scheme.substr(left.split_pos_scm));
2150 } else {
2151 ml.type=_MLBLOCK_POWER;
2152 if (left.ctype(_MLBLOCK_LEADING_DIGIT))
2153 ml.type|=_MLBLOCK_LEADING_DIGIT;
2154 if (left.appl || left.priority>=ml.priority)
2155 parenthesize(left,flags);
2156 if (mml_presentation)
2157 ml.markup=mml_tag("msup",left.markup+right.markup,idc);
2158 if (tex)
2159 ml.latex=left.latex+"^{"+right.latex+"}";
2160 if (scm)
2161 ml.scheme=scm_concat(left.scheme+" (rsup "+right.scheme+")");
2162 }
2163 }
2164 return ml;
2165 }
2166 if (g.is_symb_of_sommet(at_abs) || g.is_symb_of_sommet(at_floor) || g.is_symb_of_sommet(at_ceil)) {
2167 tmp=gen2markup(g._SYMBptr->feuille,flags,idc,contextptr);
2168 if (!g.is_symb_of_sommet(at_abs))
2169 prepend_minus(tmp,flags);
2170 ld=(g.is_symb_of_sommet(at_abs)?"|":(g.is_symb_of_sommet(at_floor)?"⌊":"⌈"));
2171 rd=(g.is_symb_of_sommet(at_abs)?"|":(g.is_symb_of_sommet(at_floor)?"⌋":"⌉"));
2172 ld_tex=(g.is_symb_of_sommet(at_abs)?"|":(g.is_symb_of_sommet(at_floor)?"\\lfloor ":"\\lceil "));
2173 rd_tex=(g.is_symb_of_sommet(at_abs)?"|":(g.is_symb_of_sommet(at_floor)?"\\rfloor ":"\\rceil "));
2174 ld_scm=(g.is_symb_of_sommet(at_abs)?"|":(g.is_symb_of_sommet(at_floor)?"<lfloor>":"<lceil>"));
2175 rd_scm=(g.is_symb_of_sommet(at_abs)?"|":(g.is_symb_of_sommet(at_floor)?"<rfloor>":"<rceil>"));
2176 if (mml_content)
2177 ml.content=mml_tag(
2178 "apply",(g.is_symb_of_sommet(at_abs)?"<abs/>" :
2179 (g.is_symb_of_sommet(at_floor)?"<floor/>":"<ceiling/>"))+tmp.content,++idc);
2180 if (mml_presentation)
2181 ml.markup=mml_tag("mfenced",tmp.markup,idc,"open",ld,"close",rd);
2182 if (tex)
2183 ml.latex="\\left"+ld_tex+tmp.latex+"\\right"+rd_tex;
2184 if (scm)
2185 ml.scheme="(around* \""+ld_scm+"\" "+tmp.scheme+" \""+rd_scm+"\")";
2186 return ml;
2187 }
2188 if (g.is_symb_of_sommet(at_laplace) || g.is_symb_of_sommet(at_ilaplace) ||
2189 g.is_symb_of_sommet(at_invlaplace) || g.is_symb_of_sommet(at_fourier) ||
2190 g.is_symb_of_sommet(at_ifourier) ||
2191 g.is_symb_of_sommet(at_ztrans) || g.is_symb_of_sommet(at_invztrans)) {
2192 const gen &arg=g._SYMBptr->feuille;
2193 bool has_func=true,has_var1=false,has_var2=false;
2194 if (arg.type==_VECT && !arg._VECTptr->empty()) {
2195 const vecteur &args=*arg._VECTptr;
2196 tmp=gen2markup(args.front(),flags,idc,contextptr);
2197 if (args.size()>1) {
2198 left=gen2markup(args[1],flags,idc,contextptr);
2199 prepend_minus(left,flags);
2200 has_var1=true;
2201 }
2202 if (args.size()>2) {
2203 right=gen2markup(args[2],flags,idc,contextptr);
2204 prepend_minus(right,flags);
2205 has_var2=true;
2206 }
2207 } else if (arg.type!=_VECT)
2208 tmp=gen2markup(arg,flags,idc,contextptr);
2209 else
2210 has_func=false;
2211 if (has_func) {
2212 ml.neg=tmp.neg;
2213 ml.priority=_PRIORITY_APPLY;
2214 str=g._SYMBptr->sommet.ptr()->s;
2215 string L=(is_substr(str,"laplace")?"L":(is_substr(str,"ztrans")?"Z" :
2216 (is_substr(str,"fourier")?"F":"?")));
2217 if (mml_content)
2218 ml.content=mml_tag("apply",mml_tag("ci",str)+tmp.content+left.content+right.content,++idc);
2219 string lap=mml_tag("mi",L,0,"mathvariant","script");
2220 string lap_tex="\\mathcal{"+L+"}";
2221 string lap_scm="\"<cal-L>\"";
2222 str="<mrow><mo>−</mo><mn>1</mn></mrow>";
2223 if (g.is_symb_of_sommet(at_ilaplace) || g.is_symb_of_sommet(at_invlaplace) ||
2224 g.is_symb_of_sommet(at_invztrans) || g.is_symb_of_sommet(at_ifourier)) {
2225 if (has_var1) {
2226 lap=mml_tag("msubsup",lap+left.markup+str);
2227 lap_tex=lap_tex+"_{"+left.latex+"}^{-1}";
2228 lap_scm=scm_concat(lap_scm+" (rsub "+left.scheme+") (rsup \"-1\")");
2229 } else {
2230 lap=mml_tag("msup",lap+str);
2231 lap_tex=lap_tex+"^{-1}";
2232 lap_scm=scm_concat(lap_scm+" (rsup \"-1\")");
2233 }
2234 } else if (has_var1) {
2235 lap=mml_tag("msub",lap+left.markup);
2236 lap_tex=lap_tex+"_{"+left.latex+"}";
2237 lap_scm=scm_concat(lap_scm+" (rsub "+left.scheme+")");
2238 }
2239 if (mml_presentation)
2240 ml.markup=lap+mml_tag("mfenced",tmp.markup,0,"open","{","close","}");
2241 if (tex)
2242 ml.latex=lap_tex+"\\left\\{"+tmp.latex+"\\right\\}";
2243 if (scm)
2244 ml.scheme=scm_concat(lap_scm+" (around* \"{\" "+tmp.scheme+" \"}\")");
2245 if (has_var2) {
2246 parenthesize(right,flags);
2247 if (mml_presentation)
2248 ml.markup=ml.markup+right.markup;
2249 if (tex)
2250 ml.latex=ml.latex+right.latex;
2251 if (scm)
2252 ml.scheme=scm_concat(ml.scheme+" "+right.scheme);
2253 }
2254 if (mml_presentation)
2255 ml.markup=mml_tag("mrow",ml.markup,idc);
2256 return ml;
2257 }
2258 }
2259 if (g.is_symb_of_sommet(at_integrate) || g.is_symb_of_sommet(at_int) ||
2260 g.is_symb_of_sommet(at_Int) || g.is_symb_of_sommet(at_sum) || g.is_symb_of_sommet(at_somme) ||
2261 g.is_symb_of_sommet(at_add) || g.is_symb_of_sommet(at_product) || g.is_symb_of_sommet(at_mul)) {
2262 bool has_ub=false,has_lb=false;
2263 bool isint=(g.is_symb_of_sommet(at_integrate) || g.is_symb_of_sommet(at_int)),
2264 issum=(g.is_symb_of_sommet(at_sum) || g.is_symb_of_sommet(at_somme) ||
2265 g.is_symb_of_sommet(at_add)),
2266 isprod=(g.is_symb_of_sommet(at_product) || g.is_symb_of_sommet(at_mul));
2267 string big="<mo>"+string(isint?"∫":(issum?"∑":"∏"))+"</mo>";
2268 string big_tex=(isint?"\\int ":(issum?"\\sum ":"\\prod "));
2269 string big_scm="(big "+string(isint?"\"int\"":(issum?"\"sum\"":"\"prod\""))+")";
2270 MarkupBlock lb,ub,var,e;
2271 ml.priority=_PRIORITY_MUL;
2272 ml.type=_MLBLOCK_SUMPROD;
2273 if (vectarg) {
2274 const vecteur &args=*g._SYMBptr->feuille._VECTptr;
2275 e=gen2markup(args[0],flags,idc,contextptr);
2276 if (args.size()>1) {
2277 if (args[1].is_symb_of_sommet(at_equal) &&
2278 args[1]._SYMBptr->feuille._VECTptr->back().is_symb_of_sommet(
2279 at_interval)) {
2280 gen &lh=args[1]._SYMBptr->feuille._VECTptr->front();
2281 gen &low=args[1]
2282 ._SYMBptr->feuille._VECTptr->back()
2283 ._SYMBptr->feuille._VECTptr->front();
2284 gen &up=args[1]
2285 ._SYMBptr->feuille._VECTptr->back()
2286 ._SYMBptr->feuille._VECTptr->back();
2287 lb=gen2markup(low,flags,idc,contextptr);
2288 has_lb=true;
2289 ub=gen2markup(up,flags,idc,contextptr);
2290 has_ub=true;
2291 var=gen2markup(lh,flags,idc,contextptr);
2292 } else
2293 var=gen2markup(args[1],flags,idc,contextptr);
2294 prepend_minus(var,flags);
2295 if (isint) {
2296 if (var.priority!=0)
2297 parenthesize(var,flags);
2298 if (mml_presentation)
2299 var.markup=mml_itimes+mml_d+var.markup;
2300 if (tex)
2301 var.latex=(is_texmacs_compatible_latex_export?tex_itimes:"\\,")+tex_mathd+var.latex;
2302 if (scm)
2303 var.scheme="\"*<mathd> \" "+var.scheme;
2304 }
2305 }
2306 if (!has_lb && args.size()>2) {
2307 lb=gen2markup(args[2],flags,idc,contextptr);
2308 has_lb=true;
2309 }
2310 if (!has_ub && args.size()>3) {
2311 ub=gen2markup(args[3],flags,idc,contextptr);
2312 has_ub=true;
2313 }
2314 if (has_lb)
2315 prepend_minus(lb,flags);
2316 if (has_ub)
2317 prepend_minus(ub,flags);
2318 if (has_lb && !isint) {
2319 if (mml_presentation)
2320 lb.markup=mml_tag("mrow",var.markup+"<mo>=</mo>"+lb.markup);
2321 if (tex)
2322 lb.latex=var.latex+"="+lb.latex;
2323 if (scm)
2324 lb.scheme=scm_concat(var.scheme+" \"=\" "+lb.scheme);
2325 }
2326 if (!has_lb && !isint) {
2327 lb=var;
2328 has_lb=true;
2329 }
2330 if (has_lb && !has_ub) {
2331 big=mml_tag("munder",big+lb.markup);
2332 big_tex+="_{"+lb.latex+"}";
2333 big_scm+=" (rsub "+lb.scheme+")";
2334 } else if (has_lb && has_ub) {
2335 big=mml_tag("munderover",big+lb.markup+ub.markup);
2336 big_tex+="_{"+lb.latex+"}^{"+ub.latex+"}";
2337 big_scm+=" (rsub "+lb.scheme+") (rsup "+ub.scheme+")";
2338 }
2339 } else
2340 e=gen2markup(g._SYMBptr->feuille,flags,idc,contextptr);
2341 if (isprod)
2342 prepend_minus(e,flags);
2343 else
2344 ml.neg=e.neg;
2345 if ((isprod && !e.ctype(_MLBLOCK_FRACTION) && e.priority>=ml.priority) ||
2346 (!isprod && (e.ctype(_MLBLOCK_NEG) || e.priority>ml.priority)))
2347 parenthesize(e,flags);
2348 if (mml_content) {
2349 str.clear();
2350 if (!var.content.empty())
2351 str+=mml_tag("bvar",var.content);
2352 if (has_lb && !has_ub)
2353 str+=mml_tag(isint?"domainofapplication":"condition",lb.content);
2354 else if (has_lb && has_ub)
2355 str+=mml_tag("lowlimit",lb.content)+mml_tag("uplimit",ub.content);
2356 str+=e.content;
2357 ml.content=mml_tag("apply",(isint?"<int/>":(issum?"<sum/>":"<product/>"))+str,++idc);
2358 }
2359 if (mml_presentation)
2360 ml.markup=mml_tag("mrow",big+e.markup+(isint?var.markup:""),idc);
2361 if (tex) {
2362 ml.latex=big_tex+e.latex+(isint?var.latex:"");
2363 /*
2364 if (is_texmacs_compatible_latex_export)
2365 ml.latex+="\\bignone ";
2366 */
2367 }
2368 if (scm)
2369 ml.scheme=scm_concat(big_scm+" "+e.scheme+(isint?" "+var.scheme:""));
2370 return ml;
2371 }
2372 if ((g.is_symb_of_sommet(at_limit) || g.is_symb_of_sommet(at_limite)) &&
2373 vectarg && g._SYMBptr->feuille._VECTptr->size()>1) {
2374 const vecteur &args=*g._SYMBptr->feuille._VECTptr;
2375 ml.priority=_PRIORITY_MUL;
2376 ml.type=_MLBLOCK_SUMPROD;
2377 MarkupBlock e,var,dest;
2378 int dir=0;
2379 e=gen2markup(args[0],flags,idc,contextptr);
2380 ml.neg=e.neg;
2381 if (e.priority>ml.priority)
2382 parenthesize(e,flags);
2383 else {
2384 if (mml_presentation)
2385 e.markup=mml_apply+e.markup;
2386 if (scm)
2387 e.scheme=scm_nobrackets(e.scheme);
2388 }
2389 if (args.size()>=2) {
2390 if (args[1].is_symb_of_sommet(at_equal)) {
2391 var=gen2markup(args[1]._SYMBptr->feuille._VECTptr->front(),flags,idc,contextptr);
2392 dest=gen2markup(args[1]._SYMBptr->feuille._VECTptr->back(),flags,idc,contextptr);
2393 if (args.size()==3 && args[2].type==_INT_)
2394 dir=args[2].val;
2395 } else if (args.size()>=3) {
2396 var=gen2markup(args[1],flags,idc,contextptr);
2397 dest=gen2markup(args[2],flags,idc,contextptr);
2398 if (args.size()==4 && args[3].type==_INT_)
2399 dir=args[3].val;
2400 }
2401 prepend_minus(var,flags);
2402 prepend_minus(dest,flags);
2403 if (mml_content) {
2404 str.clear();
2405 if (!var.content.empty()) {
2406 str+=mml_tag("bvar",var.content);
2407 if (!dest.content.empty())
2408 str+=mml_tag("condition",mml_tag("tendsto",var.content+dest.content,0,
2409 dir==0?"":"type",
2410 dir<0?"below":"above"));
2411 }
2412 str+=e.content;
2413 ml.content=mml_tag("apply","<limit/>"+str,++idc);
2414 }
2415 if (mml_presentation) {
2416 ml.markup="<munder><mi>lim</mi><mrow>"+var.markup+"<mo>→</mo>";
2417 if (dir==0)
2418 ml.markup+=dest.markup;
2419 else
2420 ml.markup+="<msup>"+dest.markup+string(dir<0?mml_minus:mml_plus)+"</msup>";
2421 ml.markup+="</mrow></munder>"+e.markup;
2422 ml.markup=mml_tag("mrow",ml.markup,idc);
2423 }
2424 if (tex)
2425 ml.latex="\\lim_{"+var.latex+"\\to "+dest.latex+
2426 string(dir==0?"":(dir<0?"^{-}":"^{+}"))+"}"+e.latex;
2427 if (scm)
2428 ml.scheme="(concat \"lim\" (rsub (concat "+var.scheme+" \"<rightarrow>\" "+dest.scheme+
2429 (dir==0?"":(dir<0?" (rsup \"-\")":" (rsup \"+\")"))+")) \" \" "+e.scheme+")";
2430 return ml;
2431 }
2432 }
2433 if (g.is_symb_of_sommet(at_sum_riemann) && vectarg && isbinary) {
2434 const vecteur &args=*g._SYMBptr->feuille._VECTptr;
2435 if (args.back().type==_VECT && args.back()._VECTptr->size()==2) {
2436 const vecteur &vars=*args.back()._VECTptr;
2437 ml=gen2markup(symbolic(at_limit,makevecteur(symbolic(at_sum,
2438 makevecteur(args.front(),vars.back(),1,vars.front())),
2439 vars.front(),unsigned_inf)),
2440 flags,idc,contextptr);
2441 return ml;
2442 }
2443 }
2444 if (g.is_symb_of_sommet(at_derive) || g.is_symb_of_sommet(at_deriver)) {
2445 identificateur f;
2446 vecteur deg;
2447 if (is_partialdiff(g,f,deg,contextptr)) {
2448 ml.priority=_PRIORITY_EXP;
2449 ml.type=_MLBLOCK_POWER | _MLBLOCK_DERIVATIVE;
2450 left=gen2markup(f,flags,idc,contextptr);
2451 right=gen2markup(gen(deg,_SEQ__VECT),flags,idc,contextptr);
2452 if (tex)
2453 ml.latex=left.latex+"^{"+right.latex+"}";
2454 if (scm)
2455 ml.scheme=scm_concat(left.scheme+" (rsup "+right.scheme+")");
2456 if (mml_content)
2457 ml.content=mml_tag("apply","<partialdiff/>"+right.content+left.content,++idc);
2458 if (mml_presentation)
2459 ml.markup=mml_tag("msup",left.markup+right.markup,idc);
2460 return ml;
2461 }
2462 gen arg=g._SYMBptr->feuille;
2463 int n=0;
2464 while (arg.is_symb_of_sommet(at_derive) || arg.is_symb_of_sommet(at_deriver)) {
2465 arg=arg._SYMBptr->feuille;
2466 ++n;
2467 }
2468 if (n==0 || !vectarg) {
2469 ml.type=_MLBLOCK_DERIVATIVE;
2470 if (vectarg)
2471 tmp=gen2markup(arg._VECTptr->front(),flags,idc,contextptr);
2472 else
2473 tmp=gen2markup(arg,flags,idc,contextptr);
2474 bool simp=(tmp.priority==0);
2475 if (tmp.priority>_PRIORITY_APPLY)
2476 parenthesize(tmp,flags);
2477 else if (scm)
2478 tmp.scheme=scm_nobrackets(tmp.scheme);
2479 ml.neg=tmp.neg;
2480 if (n>0) {
2481 ml.priority=_PRIORITY_EXP;
2482 ml.type|=_MLBLOCK_POWER;
2483 ++n;
2484 string N=gen(n).print(contextptr);
2485 if (mml_content)
2486 ml.content=mml_tag("apply",mml_csymbol("nthdiff","calculus1")+"<cn>"+N+"</cn>"+tmp.content,
2487 ++idc);
2488 switch (n) {
2489 case 2:
2490 if (mml_presentation)
2491 ml.markup=mml_tag("msup",tmp.markup+"<mo>″</mo>",idc);
2492 if (tex)
2493 ml.latex=tmp.latex+"''";
2494 if (scm)
2495 ml.scheme=scm_concat(tmp.scheme+" (rprime \"''\")");
2496 break;
2497 case 3:
2498 if (mml_presentation)
2499 ml.markup=mml_tag("msup",tmp.markup+"<mo>‴</mo>",idc);
2500 if (tex)
2501 ml.latex=tmp.latex+"'''";
2502 if (scm)
2503 ml.scheme=scm_concat(tmp.scheme+" (rprime \"'''\")");
2504 break;
2505 default:
2506 if (mml_presentation)
2507 ml.markup=mml_tag("msup",tmp.markup+mml_tag("mfenced","<mn>"+N+"</mn>"),idc);
2508 if (tex)
2509 ml.latex=tmp.latex+"^{("+N+")}";
2510 if (scm)
2511 ml.scheme=scm_concat(tmp.scheme+" (rsup (around* \"(\" \""+N+"\" \")\"))");
2512 break;
2513 }
2514 return ml;
2515 }
2516 if (n==0 && !vectarg) {
2517 ml.priority=_PRIORITY_EXP;
2518 if (mml_content)
2519 ml.content=mml_tag("apply","<diff/>"+tmp.content,++idc);
2520 if (mml_presentation)
2521 ml.markup=mml_tag("msup",tmp.markup+"<mo>′</mo>",idc);
2522 if (tex)
2523 ml.latex=tmp.latex+"'";
2524 if (scm)
2525 ml.scheme=scm_concat(tmp.scheme+" (rprime \"'\")");
2526 return ml;
2527 }
2528 if (vectarg && arg._VECTptr->size()>1) {
2529 vecteur vars;
2530 MarkupBlock var;
2531 if (get_derive_vars(*arg._VECTptr,vars)) {
2532 int n=vars.size();
2533 ml.priority=_PRIORITY_MUL;
2534 ml.type|=_MLBLOCK_FRACTION;
2535 if (n==1 && is_one(vars.front()._VECTptr->back())) {
2536 var=gen2markup(vars.front()._VECTptr->front(),flags,idc,contextptr);
2537 if (mml_content)
2538 ml.content=mml_tag("apply","<diff/><bvar>"+var.content+"</bvar>"+tmp.content,++idc);
2539 if (mml_presentation)
2540 ml.markup=simp?mml_tag("mfrac","<mrow>"+mml_d+tmp.markup+
2541 "</mrow><mrow>"+mml_d+var.markup+"</mrow>",idc)
2542 :mml_tag("mrow",mml_tag("mfrac",mml_d+mml_tag("mrow",var.markup))+
2543 mml_apply+tmp.markup,idc);
2544 if (tex)
2545 ml.latex=simp?"\\frac{"+tex_mathd+tmp.latex+"}{"+tex_mathd+var.latex+"}"
2546 :"\\frac{"+tex_mathd+"}{"+tex_mathd+var.latex+"}"+tmp.latex;
2547 if (scm)
2548 ml.scheme=simp?"(frac (concat \"<mathd> \" "+tmp.scheme+
2549 ") (concat \"<mathd> \" "+var.scheme+"))"
2550 :"(concat (frac \"<mathd>\" (concat \"<mathd> \" "+
2551 var.scheme+")) \" \" "+tmp.scheme+")";
2552 return ml;
2553 }
2554 string ds(n>1?"<mo>∂</mo>":mml_d);
2555 string ds_tex(n>1?"\\partial ":tex_mathd);
2556 string ds_scm(n>1?"<partial>":"<mathd>");
2557 int c=0;
2558 gen N(0);
2559 for (const_iterateur it=vars.begin();it!=vars.end();++it) {
2560 var=gen2markup(it->_VECTptr->front(),flags,idc,contextptr);
2561 str=it->_VECTptr->back().print(contextptr);
2562 N+=it->_VECTptr->back();
2563 if (mml_content)
2564 ml.content+=mml_tag(
2565 "bvar",var.content+(is_one(it->_VECTptr->back())?
2566 "":"<degree><cn>"+str+"</cn></degree>"),idc);
2567 if (mml_presentation)
2568 ml.markup+=is_one(it->_VECTptr->back())?ds+var.markup
2569 :mml_tag("msup","<mrow>"+ds+var.markup+
2570 "</mrow><mn>"+str+"</mn>");
2571 if (tex)
2572 ml.latex+=ds_tex+var.latex+(is_one(it->_VECTptr->back())?"":"^{"+str+"}");
2573 if (scm)
2574 ml.scheme+=is_one(it->_VECTptr->back())?scm_concat("\""+ds_scm+" \" "+var.scheme)
2575 :scm_concat("\""+ds_scm+" \" "+var.scheme+" (rsup \""+str+"\")");
2576 if (++c<n) {
2577 if (mml_presentation)
2578 ml.markup+=mml_itimes;
2579 if (tex)
2580 ml.latex+=tex_itimes;
2581 if (scm)
2582 ml.scheme+=" \"*\" ";
2583 }
2584 }
2585 string Ns=N.print(contextptr);
2586 if (mml_content)
2587 ml.content=mml_tag("apply",(n>1?"<partialdiff/>":"<diff/>")+
2588 ml.content+"<degree><cn type='integer'>"+Ns+
2589 "</cn></degree>"+tmp.content,
2590 ++idc);
2591 if (mml_presentation)
2592 ml.markup=simp?mml_tag("mfrac","<mrow><msup>"+ds+"<mn>"+Ns+"</mn></msup>"+
2593 tmp.markup+"</mrow><mrow>"+ml.markup+"</mrow>",idc)
2594 :mml_tag("mrow",mml_tag("mfrac","<msup>"+ds+"<mn>"+Ns+"</mn></msup>"+
2595 "<mrow>"+ml.markup+"</mrow>")+mml_apply+tmp.markup,idc);
2596 if (tex)
2597 ml.latex=simp?"\\frac{"+ds_tex+"^{"+Ns+"}"+tmp.latex+"}{"+ml.latex+"}"
2598 :"\\frac{"+ds_tex+"^{"+Ns+"}}{"+ml.latex+"}"+tmp.latex;
2599 if (scm) {
2600 if (n>1)
2601 ml.scheme=scm_concat(ml.scheme);
2602 ml.scheme=simp?"(frac (concat \""+ds_scm+"\" (rsup \""+Ns+"\") \" \" "+tmp.scheme+
2603 ") (concat "+ml.scheme+"))"
2604 :"(concat (frac (concat \""+ds_scm+"\" (rsup \""+Ns+"\")) (concat "+ml.scheme+
2605 ")) \" \" "+tmp.scheme+")";
2606 }
2607 return ml;
2608 }
2609 }
2610 }
2611 }
2612 if ((g.is_symb_of_sommet(at_same) || g.is_symb_of_sommet(at_different) ||
2613 g.is_symb_of_sommet(at_sto) || g.is_symb_of_sommet(at_array_sto) ||
2614 g.is_symb_of_sommet(at_equal)) && isbinary) {
2615 ml.priority=(g.is_symb_of_sommet(at_sto) || g.is_symb_of_sommet(at_array_sto)
2616 ?_PRIORITY_ASSGN
2617 :(g.is_symb_of_sommet(at_equal)?_PRIORITY_EQ:_PRIORITY_COMP));
2618 if (g.is_symb_of_sommet(at_sto) || g.is_symb_of_sommet(at_array_sto))
2619 get_leftright(g._SYMBptr->feuille,&ml,right,left,flags,idc,contextptr);
2620 else
2621 get_leftright(g._SYMBptr->feuille,&ml,left,right,flags,idc,contextptr);
2622 string op(g.is_symb_of_sommet(at_same)
2623 ?"⩵"
2624 :(g.is_symb_of_sommet(at_different)
2625 ?"≠"
2626 :(g.is_symb_of_sommet(at_equal)?"=":(g.is_symb_of_sommet(at_sto)?"≔":"←"))));
2627 string op_tex(
2628 g.is_symb_of_sommet(at_same)
2629 ?"==":(g.is_symb_of_sommet(at_different)?"\\neq "
2630 :(g.is_symb_of_sommet(at_equal)?"="
2631 :(g.is_symb_of_sommet(at_sto)?":=":"\\leftarrow"))));
2632 string op_scm(
2633 g.is_symb_of_sommet(at_same)
2634 ?"<longequal>":(g.is_symb_of_sommet(at_different)?"<neq>"
2635 :(g.is_symb_of_sommet(at_equal)?"="
2636 :(g.is_symb_of_sommet(at_sto)?"<assign>":"<leftarrow>"))));
2637 string csymb(
2638 g.is_symb_of_sommet(at_same)
2639 ?"==":(g.is_symb_of_sommet(at_different)?"<neq/>"
2640 :(g.is_symb_of_sommet(at_equal)?"<eq/>"
2641 :(g.is_symb_of_sommet(at_sto)?":=":"=<"))));
2642 if (csymb[0]!='<')
2643 csymb=mml_tag("ci",csymb);
2644 if (mml_content)
2645 ml.content=mml_tag("apply",csymb+left.content+right.content,++idc);
2646 if (mml_presentation)
2647 ml.markup=mml_tag("mrow",left.markup+"<mo>"+op+"</mo>"+right.markup,idc);
2648 if (tex)
2649 ml.latex=left.latex+op_tex+right.latex;
2650 if (scm)
2651 ml.scheme=scm_concat(left.scheme+" \""+op_scm+"\" "+right.scheme);
2652 return ml;
2653 }
2654 if ((g.is_symb_of_sommet(at_inferieur_strict) || g.is_symb_of_sommet(at_inferieur_egal) ||
2655 g.is_symb_of_sommet(at_superieur_strict) || g.is_symb_of_sommet(at_superieur_egal)) &&
2656 vectarg && isbinary) {
2657 ml.priority=_PRIORITY_INEQ;
2658 get_leftright(g._SYMBptr->feuille,&ml,left,right,flags,idc,contextptr);
2659 string op,op_tex,op_scm,csymb;
2660 if (g.is_symb_of_sommet(at_inferieur_strict)) {
2661 op="<";
2662 op_tex="<";
2663 op_scm="<less>";
2664 csymb="<lt/>";
2665 } else if (g.is_symb_of_sommet(at_inferieur_egal)) {
2666 op="≤";
2667 op_tex="\\leq ";
2668 op_scm="<leqslant>";
2669 csymb="<leq/>";
2670 } else if (g.is_symb_of_sommet(at_superieur_strict)) {
2671 op=">";
2672 op_tex=">";
2673 op_scm="<gtr>";
2674 csymb="<gt/>";
2675 } else if (g.is_symb_of_sommet(at_superieur_egal)) {
2676 op="≥";
2677 op_tex="\\geq ";
2678 op_scm="<geqslant>";
2679 csymb="<geq/>";
2680 }
2681 if (mml_content)
2682 ml.content=mml_tag("apply",csymb+left.content+right.content,++idc);
2683 if (mml_presentation)
2684 ml.markup=mml_tag("mrow",left.markup+"<mo>"+op+"</mo>"+right.markup,idc);
2685 if (tex)
2686 ml.latex=left.latex+op_tex+right.latex;
2687 if (scm)
2688 ml.scheme=scm_concat(left.scheme+" \""+op_scm+"\" "+right.scheme);
2689 return ml;
2690 }
2691 if (g.is_symb_of_sommet(at_tilocal) && vectarg && g._SYMBptr->feuille._VECTptr->size()>1) {
2692 const vecteur &args=*g._SYMBptr->feuille._VECTptr;
2693 ml.priority=_PRIORITY_OTHER;
2694 tmp=gen2markup(args.front(),flags,idc,contextptr);
2695 ml.neg=tmp.neg;
2696 MarkupBlock sub;
2697 for (const_iterateur it=args.begin()+1;it!=args.end();++it) {
2698 sub=gen2markup(*it,flags | _MARKUP_TOPLEVEL,idc,contextptr);
2699 prepend_minus(sub,flags);
2700 if (mml_content)
2701 ml.content+=sub.content;
2702 if (mml_presentation)
2703 ml.markup+=sub.markup;
2704 if (tex)
2705 ml.latex+=(it==args.begin()+1?"":",")+sub.latex;
2706 if (scm)
2707 ml.scheme+=(it==args.begin()+1?"":",")+sub.scheme;
2708 }
2709 if (args.size()>2 && scm)
2710 ml.scheme=scm_concat(ml.scheme);
2711 if (mml_content)
2712 ml.content=mml_tag("apply","<ci>subst</ci>"+ml.content,++idc);
2713 if (mml_presentation)
2714 ml.markup=mml_tag(
2715 "msub",mml_tag("mfenced",tmp.markup,0,"open","","close","|")+
2716 mml_tag("mfenced",ml.markup,0,"open","","close",""),
2717 idc);
2718 if (tex)
2719 ml.latex="\\left."+tmp.latex+"\\right|_{"+ml.latex+"}";
2720 if (scm)
2721 ml.scheme="(concat (around* \"<nobracket>\" "+tmp.scheme+" \"|\") (rsub "+ml.scheme+"))";
2722 return ml;
2723 }
2724 if ((g.is_symb_of_sommet(at_union) || g.is_symb_of_sommet(at_intersect)) && vectarg) {
2725 ml.priority=_PRIORITY_SET;
2726 string op=(g.is_symb_of_sommet(at_union)?"∪":"∩");
2727 string opc=(g.is_symb_of_sommet(at_union)?"<union/>":"<intersect/>");
2728 string opt=(g.is_symb_of_sommet(at_union)?"\\cup ":"\\cap ");
2729 string ops=(g.is_symb_of_sommet(at_union)?"<cup>":"<cap>");
2730 assoc2markup(flatten_operands(g),ml,op,opc,opt,ops,flags,idc,contextptr);
2731 return ml;
2732 }
2733 if (g.is_symb_of_sommet(at_minus) && vectarg && isbinary) {
2734 ml.priority=_PRIORITY_SET;
2735 get_leftright(g._SYMBptr->feuille,&ml,left,right,flags,idc,contextptr);
2736 if (mml_content)
2737 ml.content=mml_tag(
2738 "apply","<setdiff/>"+left.content+right.content,++idc);
2739 if (mml_presentation)
2740 ml.markup=mml_tag(
2741 "mrow",left.markup+"<mo>∖</mo>"+right.markup,idc);
2742 if (tex)
2743 ml.latex=left.latex+"\\setminus "+right.latex;
2744 if (scm)
2745 ml.scheme=scm_concat(left.scheme+" \"<setminus>\" "+right.scheme);
2746 return ml;
2747 }
2748 if (g.is_symb_of_sommet(at_member) && vectarg && isbinary &&
2749 is_set_or_ident(g._SYMBptr->feuille._VECTptr->back())) {
2750 ml.priority=_PRIORITY_INEQ;
2751 get_leftright(g._SYMBptr->feuille,&ml,left,right,flags,idc,contextptr);
2752 if (mml_content)
2753 ml.content=mml_tag("apply","<in/>"+left.content+right.content,++idc);
2754 if (mml_presentation)
2755 ml.markup=mml_tag("mrow",left.markup+"<mo>∈</mo>"+right.markup,idc);
2756 if (tex)
2757 ml.latex=left.latex+"\\in "+right.latex;
2758 if (scm)
2759 ml.scheme=scm_concat(left.scheme+" \"<in>\" "+right.scheme);
2760 return ml;
2761 }
2762 if (g.is_symb_of_sommet(at_is_included) && vectarg && isbinary &&
2763 is_set_or_ident(g._SYMBptr->feuille._VECTptr->front()) &&
2764 is_set_or_ident(g._SYMBptr->feuille._VECTptr->back())) {
2765 ml.priority=_PRIORITY_INEQ;
2766 get_leftright(g._SYMBptr->feuille,&ml,left,right,flags,idc,contextptr);
2767 if (mml_content)
2768 ml.content=mml_tag("apply","<subset/>"+left.content+right.content,++idc);
2769 if (mml_presentation)
2770 ml.markup=mml_tag("mrow",left.markup+"<mo>⊆</mo>"+right.markup,idc);
2771 if (tex)
2772 ml.latex=left.latex+"\\subseteq "+right.latex;
2773 if (scm)
2774 ml.scheme=scm_concat(left.scheme+" \"<subseteq>\" "+right.scheme);
2775 return ml;
2776 }
2777 if (g.is_symb_of_sommet(at_not)) {
2778 ml.priority=_PRIORITY_NOT;
2779 tmp=gen2markup(g._SYMBptr->feuille,flags,idc,contextptr);
2780 prepend_minus(tmp,flags);
2781 if (tmp.priority>=ml.priority)
2782 parenthesize(tmp,flags);
2783 if (mml_content)
2784 ml.content=mml_tag("apply","<not/>"+tmp.content,++idc);
2785 if (mml_presentation)
2786 ml.markup=mml_tag("mrow","<mo>¬</mo>"+tmp.markup,idc);
2787 if (tex)
2788 ml.latex="\\neg "+tmp.latex;
2789 if (scm)
2790 ml.scheme="(concat \"<neg>\" "+tmp.scheme+")";
2791 return ml;
2792 }
2793 if ((g.is_symb_of_sommet(at_and) || g.is_symb_of_sommet(at_et) || g.is_symb_of_sommet(at_ou) ||
2794 g.is_symb_of_sommet(at_xor)) && vectarg) {
2795 ml.priority=(g.is_symb_of_sommet(at_xor)?_PRIORITY_XOR:(g.is_symb_of_sommet(at_ou)?_PRIORITY_OR:_PRIORITY_AND));
2796 string op=(g.is_symb_of_sommet(at_xor)?"⊻":(g.is_symb_of_sommet(at_ou)?"∨":"∧"));
2797 string opc=(g.is_symb_of_sommet(at_xor)?"<xor/>":(g.is_symb_of_sommet(at_ou)?"<or/>":"<and/>"));
2798 string opt=(g.is_symb_of_sommet(at_xor)?"\\veebar ":(g.is_symb_of_sommet(at_ou)?"\\vee ":"\\wedge "));
2799 string ops=(g.is_symb_of_sommet(at_xor)?"<veebar>":(g.is_symb_of_sommet(at_ou)?"<vee>":"<wedge>"));
2800 assoc2markup(flatten_operands(g),ml,op,opc,opt,ops,flags,idc,contextptr);
2801 return ml;
2802 }
2803 if (g.is_symb_of_sommet(at_interval) && vectarg && isbinary) {
2804 ml.priority=_PRIORITY_SET;
2805 get_leftright(g._SYMBptr->feuille,&ml,left,right,flags,idc,contextptr);
2806 if (mml_content)
2807 ml.content=mml_tag("interval",left.content+right.content,++idc);
2808 if (mml_presentation)
2809 ml.markup=mml_tag("mrow",left.markup+"<mo>‥</mo>"+right.markup,idc);
2810 if (tex)
2811 ml.latex=left.latex+"\\ldots "+right.latex;
2812 if (scm)
2813 ml.scheme=scm_concat(left.scheme+" \"<ldots>\" "+right.scheme);
2814 return ml;
2815 }
2816 if (g.is_symb_of_sommet(at_dollar) && vectarg && isbinary) {
2817 const vecteur &args=*g._SYMBptr->feuille._VECTptr;
2818 ml.priority=_PRIORITY_EXP;
2819 get_leftright(args,NULL,left,right,flags,idc,contextptr);
2820 if (left.priority>ml.priority)
2821 parenthesize(left,flags);
2822 if (right.priority>ml.priority)
2823 parenthesize(right,flags);
2824 if (mml_content)
2825 ml.content=mml_tag("apply","<ci>$</ci>"+left.content+right.content,++idc);
2826 if (mml_presentation)
2827 ml.markup=mml_tag("mrow",left.markup+"<mo>|</mo>"+right.markup,idc);
2828 if (tex)
2829 ml.latex=left.latex+"\\middle|"+right.latex;
2830 if (scm)
2831 ml.scheme=scm_concat(left.scheme+" (mid \"|\") "+right.scheme);
2832 return ml;
2833 }
2834 if (g.is_symb_of_sommet(at_re) || g.is_symb_of_sommet(at_im)) {
2835 tmp=gen2markup(g._SYMBptr->feuille,flags,idc,contextptr);
2836 parenthesize(tmp,flags);
2837 ml.neg=tmp.neg;
2838 ml.priority=_PRIORITY_APPLY;
2839 if (mml_content)
2840 ml.content=mml_tag("apply",(g.is_symb_of_sommet(at_re)?"<real/>":"<imaginary/>")+tmp.content,++idc);
2841 if (mml_presentation)
2842 ml.markup=mml_tag("mrow",(g.is_symb_of_sommet(at_re)?mml_re:mml_im)+tmp.markup,idc);
2843 if (tex)
2844 ml.latex=(g.is_symb_of_sommet(at_re)?"\\Re ":"\\Im ")+tmp.latex;
2845 if (scm)
2846 ml.scheme=scm_concat((g.is_symb_of_sommet(at_re)?" \"<Re> \" ":" \"<Im> \" ")+tmp.scheme);
2847 return ml;
2848 }
2849 if (g.is_symb_of_sommet(at_besselJ) || g.is_symb_of_sommet(at_BesselJ) ||
2850 g.is_symb_of_sommet(at_besselY) || g.is_symb_of_sommet(at_BesselY)) {
2851 ml.priority=_PRIORITY_APPLY;
2852 int k=(g.is_symb_of_sommet(at_besselJ) || g.is_symb_of_sommet(at_BesselJ)?1:2);
2853 str=(k==1?"J":"Y");
2854 if (g.is_symb_of_sommet(at_BesselJ) || g.is_symb_of_sommet(at_BesselY))
2855 get_leftright(g._SYMBptr->feuille,NULL,left,right,flags,idc,contextptr);
2856 else
2857 get_leftright(g._SYMBptr->feuille,NULL,right,left,flags,idc,contextptr);
2858 parenthesize(right,flags);
2859 if (mml_content)
2860 ml.content=mml_tag("apply",mml_csymbol(k==1?"besselJ":"besselY","hypergeo2")+
2861 left.content+right.content,++idc);
2862 if (mml_presentation)
2863 ml.markup=mml_tag("mrow","<msub><mi>"+str+"</mi>"+left.markup+"</msub>"+
2864 mml_apply+right.markup,idc);
2865 if (tex)
2866 ml.latex=str+"_{"+left.latex+"}"+right.latex;
2867 if (scm)
2868 ml.scheme="(concat \""+str+"\" (rsub "+left.scheme+") \" \" "+right.scheme+")";
2869 return ml;
2870 }
2871 if (g.is_symb_of_sommet(at_grad) || g.is_symb_of_sommet(at_curl) ||
2872 g.is_symb_of_sommet(at_divergence) ||
2873 (g.is_symb_of_sommet(at_laplacian) && _evalf(g._SYMBptr->feuille,contextptr).type!=_DOUBLE_)) {
2874 ml.priority=(g.is_symb_of_sommet(at_grad) || g.is_symb_of_sommet(at_laplacian)?_PRIORITY_APPLY:_PRIORITY_MUL);
2875 string op=(g.is_symb_of_sommet(at_laplacian)?"<mi>Δ</mi>":"<mi>∇</mi>");
2876 string opc=(g.is_symb_of_sommet(at_grad)?"<grad/>"
2877 :(g.is_symb_of_sommet(at_curl)?"<curl/>"
2878 :(g.is_symb_of_sommet(at_divergence)?"<divergence/>"
2879 :"<laplacian/>")));
2880 string opt=(g.is_symb_of_sommet(at_laplacian)?"\\Delta ":"\\nabla ");
2881 string ops=(g.is_symb_of_sommet(at_laplacian)?"<Delta>":"<nabla>");
2882 const gen &arg=g._SYMBptr->feuille;
2883 if (arg.type!=_VECT) {
2884 tmp=gen2markup(arg,flags,idc,contextptr);
2885 ml.neg=tmp.neg;
2886 if ((ml.priority==_PRIORITY_APPLY && tmp.priority>ml.priority) ||
2887 (ml.priority==_PRIORITY_MUL && tmp.priority>=ml.priority))
2888 parenthesize(tmp,flags);
2889 if (mml_content)
2890 ml.content=mml_tag("apply",opc+tmp.content,++idc);
2891 if (g.is_symb_of_sommet(at_grad) || g.is_symb_of_sommet(at_laplacian)) opc+=mml_apply;
2892 if (g.is_symb_of_sommet(at_divergence)) { opc+=mml_cdot;opt+="\\cdot ";}
2893 if (g.is_symb_of_sommet(at_curl)) { opc+=mml_times;opt+="\\times ";}
2894 if (mml_presentation)
2895 ml.markup=mml_tag("mrow",opc+tmp.markup,idc);
2896 if (tex)
2897 ml.latex=opt+tmp.latex;
2898 if (scm)
2899 ml.scheme="(concat \""+ops+" \" "+tmp.scheme+")";
2900 return ml;
2901 }
2902 if (vectarg && isbinary) {
2903 const vecteur &args=*arg._VECTptr;
2904 tmp=gen2markup(args.front(),flags,idc,contextptr);
2905 if ((ml.priority==_PRIORITY_APPLY && tmp.priority>ml.priority) ||
2906 (ml.priority==_PRIORITY_MUL && tmp.priority>=ml.priority))
2907 parenthesize(tmp,flags);
2908 if (args.back().type!=_VECT) {
2909 right=gen2markup(args.back(),flags,idc,contextptr);
2910 if (mml_content)
2911 ml.content=mml_tag("apply",opc+mml_tag("bvar",right.content)+tmp.content,++idc);
2912 if (mml_presentation)
2913 ml.markup=mml_tag(
2914 "mrow",mml_tag("msub",op+right.markup)+(g.is_symb_of_sommet(at_divergence)?
2915 mml_cdot:(g.is_symb_of_sommet(at_curl)?mml_times:""))+tmp.markup,idc);
2916 if (tex)
2917 ml.latex=opt+"_{"+right.latex+"}"+(g.is_symb_of_sommet(at_divergence)?
2918 "\\cdot ":(g.is_symb_of_sommet(at_curl)?"\\times ":""))+tmp.latex;
2919 if (scm)
2920 ml.scheme="(concat \""+ops+"\" (rsub "+right.scheme+") "+
2921 (g.is_symb_of_sommet(at_divergence)?
2922 "\"<cdot>\" ":(g.is_symb_of_sommet(at_curl)?"\"<times>\" ":" \" \" "))+
2923 tmp.scheme+")";
2924 } else {
2925 MarkupBlock var;
2926 const vecteur &vars=*args.back()._VECTptr;
2927 for (const_iterateur it=vars.begin();it!=vars.end();++it) {
2928 var=gen2markup(*it,flags,idc,contextptr);
2929 prepend_minus(var,flags);
2930 if (mml_content)
2931 ml.content+=mml_tag("bvar",var.content);
2932 if (mml_presentation)
2933 ml.markup+=(it!=vars.begin()?mml_icomma:"")+var.markup;
2934 if (tex)
2935 ml.latex+=(it!=vars.begin()?" ":"")+var.latex;
2936 if (scm)
2937 ml.scheme+=(it!=vars.begin()?" \"<nocomma>\" ":"")+var.scheme;
2938 }
2939 if (vars.size()>1 && scm)
2940 ml.scheme=scm_concat(ml.scheme);
2941 if (mml_content)
2942 ml.content=mml_tag("apply",opc+ml.content+tmp.content,++idc);
2943 if (mml_presentation) {
2944 ml.markup=mml_tag("mrow",ml.markup);
2945 ml.markup=mml_tag(
2946 "mrow",mml_tag("msub",op+ml.markup)+(g.is_symb_of_sommet(at_divergence)?
2947 mml_cdot:(g.is_symb_of_sommet(at_curl)?mml_times:""))+tmp.markup,idc);
2948 }
2949 if (tex)
2950 ml.latex=opt+"_{"+ml.latex+"}"+(g.is_symb_of_sommet(at_divergence)?
2951 "\\cdot ":(g.is_symb_of_sommet(at_curl)?"\\times ":""))+tmp.latex;
2952 if (scm)
2953 ml.scheme="(concat \""+ops+"\" (rsub "+ml.scheme+") "+
2954 (g.is_symb_of_sommet(at_divergence)?
2955 "\"<cdot>\" ":(g.is_symb_of_sommet(at_curl)?"\"<times>\" ":" \" \" "))+
2956 tmp.scheme+")";
2957 }
2958 return ml;
2959 }
2960 }
2961 if ((g.is_symb_of_sommet(at_mean) || g.is_symb_of_sommet(at_moyenne) ||
2962 g.is_symb_of_sommet(at_stddev) || g.is_symb_of_sommet(at_ecart_type) ||
2963 g.is_symb_of_sommet(at_variance) || g.is_symb_of_sommet(at_median)) &&
2964 (!vectarg || (g._SYMBptr->feuille.subtype!=_SEQ__VECT &&
2965 !ckmatrix(g._SYMBptr->feuille)))) {
2966 ml.priority=_PRIORITY_APPLY;
2967 int f=(g.is_symb_of_sommet(at_variance)?3:(g.is_symb_of_sommet(at_median)?4:
2968 (g.is_symb_of_sommet(at_mean) || g.is_symb_of_sommet(at_moyenne)?1:2)));
2969 string op_orig=(f==1?"Mean":(f==2?"SD":(f==3?"Var":"Med")));
2970 string opc=(f==1?"<mean/>":(f==2?"<sdev/>":(f==3?"<variance/>":"<median/>")));
2971 string opt="\\operatorname{\\mathrm{"+op_orig+"}}";
2972 string op=mml_tag("mi",op_orig)+mml_apply;
2973 if (vectarg) {
2974 const vecteur &args=*g._SYMBptr->feuille._VECTptr;
2975 for (const_iterateur it=args.begin();it!=args.end();++it) {
2976 tmp=gen2markup(*it,flags,idc,contextptr);
2977 prepend_minus(tmp,flags);
2978 if (mml_content)
2979 ml.content+=tmp.content;
2980 if (mml_presentation)
2981 ml.markup+=tmp.markup;
2982 if (tex)
2983 ml.latex+=(it!=args.begin()?",":"")+tmp.latex;
2984 if (scm)
2985 ml.scheme+=(it!=args.begin()?" \",\" ":"")+tmp.scheme;
2986 }
2987 if (args.size()>1 && scm)
2988 ml.scheme=scm_concat(ml.scheme);
2989 if (mml_content)
2990 ml.content=mml_tag("apply",opc+ml.content,++idc);
2991 if (mml_presentation)
2992 ml.markup=mml_tag("mrow",op+mml_tag("mfenced",ml.markup,0,"open","[","close","]"),idc);
2993 if (tex)
2994 ml.latex=opt+"\\left["+ml.latex+"\\right]";
2995 if (scm)
2996 ml.scheme="(concat \""+op_orig+" \" (around* \"[\" "+ml.scheme+" \"]\"))";
2997 } else {
2998 tmp=gen2markup(g._SYMBptr->feuille,flags,idc,contextptr);
2999 prepend_minus(tmp,flags);
3000 if (mml_content)
3001 ml.content=mml_tag("apply",opc+tmp.content,++idc);
3002 if (mml_presentation)
3003 ml.markup=mml_tag("mrow",op+mml_tag("mfenced",tmp.markup,0,"open","[","close","]"),idc);
3004 if (tex)
3005 ml.latex=opt+"\\left["+tmp.latex+"\\right]";
3006 if (scm)
3007 ml.scheme="(concat \""+op_orig+" \" (around* \"[\" "+tmp.scheme+" \"]\"))";
3008 }
3009 return ml;
3010 }
3011 if (g.is_symb_of_sommet(at_normalmod) && vectarg && isbinary) {
3012 ml.priority=_PRIORITY_MUL;
3013 get_leftright(g._SYMBptr->feuille,&ml,left,right,flags,idc,contextptr);
3014 if (mml_content)
3015 ml.content=mml_tag("apply","<ci>%</ci>"+left.content+right.content,++idc);
3016 if (mml_presentation)
3017 ml.markup=mml_tag(
3018 "mrow",left.markup+"<mo lspace='thickmathspace' rspace='thickmathspace'>mod</mo>"+
3019 right.markup,idc);
3020 if (tex)
3021 ml.latex=left.latex+"\\;\\mathrm{mod}\\;"+right.latex;
3022 if (scm)
3023 ml.scheme=scm_concat(left.scheme+" \"<space>mod<space>\" "+right.scheme);
3024 return ml;
3025 }
3026 if (g.is_symb_of_sommet(at_compose) && vectarg && isbinary) {
3027 ml.priority=_PRIORITY_APPLY;
3028 string op="∘",opc="<compose/>",opt="\\circ ",ops="<circ>";
3029 assoc2markup(flatten_operands(g),ml,op,opc,opt,ops,flags,idc,contextptr);
3030 return ml;
3031 }
3032 if (g.is_symb_of_sommet(at_composepow) && vectarg && isbinary) {
3033 const vecteur &args=*g._SYMBptr->feuille._VECTptr;
3034 ml.priority=_PRIORITY_EXP;
3035 left=gen2markup(args.front(),flags,idc,contextptr);
3036 prepend_minus(left,flags);
3037 if (left.priority>=ml.priority)
3038 parenthesize(left,flags);
3039 right=gen2markup(args.back(),flags,idc,contextptr);
3040 prepend_minus(right,flags);
3041 if (mml_content)
3042 ml.content=mml_tag("apply","<ci>@@</ci>"+left.content+right.content,++idc);
3043 if (mml_presentation)
3044 ml.markup=mml_tag("msup",left.markup+"<mrow><mo>∘</mo>"+right.markup+"</mrow>",idc);
3045 if (tex)
3046 ml.latex=left.latex+"^{\\circ "+right.latex+"}";
3047 if (scm)
3048 ml.scheme=scm_concat(left.scheme+" (rsup (concat \"<circ>\" "+right.scheme+"))");
3049 return ml;
3050 }
3051 if (g.is_symb_of_sommet(at_program) && vectarg && g._SYMBptr->feuille._VECTptr->size()==3) {
3052 const vecteur &args=*g._SYMBptr->feuille._VECTptr;
3053 ml.priority=_PRIORITY_ASSGN;
3054 if (args[0].type==_VECT && args[0].subtype==_SEQ__VECT && args[0]._VECTptr->size()>1) {
3055 const vecteur &vars=*args[0]._VECTptr;
3056 for (const_iterateur it=vars.begin();it!=vars.end();++it) {
3057 tmp=gen2markup(*it,flags,idc,contextptr);
3058 prepend_minus(tmp,flags);
3059 if (mml_content)
3060 ml.content+=mml_tag("bvar",tmp.content);
3061 if (mml_presentation)
3062 ml.markup+=tmp.markup;
3063 if (tex)
3064 ml.latex+=(it!=vars.begin()?",":"")+tmp.latex;
3065 if (scm)
3066 ml.scheme+=(it!=vars.begin()?" \",\" ":"")+tmp.scheme;
3067 }
3068 tmp=gen2markup(args[2],flags,idc,contextptr);
3069 prepend_minus(tmp,flags);
3070 if (tmp.priority>=ml.priority)
3071 parenthesize(tmp,flags);
3072 if (mml_content)
3073 ml.content=mml_tag("lambda",ml.content+tmp.content,++idc);
3074 if (mml_presentation)
3075 ml.markup=mml_tag("mrow",mml_tag("mfenced",ml.markup)+"<mo>↦</mo>"+tmp.markup,idc);
3076 if (tex)
3077 ml.latex="\\left("+ml.latex+"\\right)\\mapsto "+tmp.latex;
3078 if (scm)
3079 ml.scheme="(concat (around* \"(\" (concat "+ml.scheme+") \")\") \"<mapsto>\" "+tmp.scheme+")";
3080 } else {
3081 get_leftright(
3082 makevecteur(args[0].type==_VECT && !args[0]._VECTptr->empty()?args[0]._VECTptr->front():args[0],args[2]),
3083 &ml,left,right,flags,idc,contextptr);
3084 if (mml_content)
3085 ml.content=mml_tag("lambda","<bvar>"+left.content+"</bvar>"+right.content,++idc);
3086 if (mml_presentation)
3087 ml.markup=mml_tag("mrow",left.markup+"<mo>↦</mo>"+right.markup,idc);
3088 if (tex)
3089 ml.latex=left.latex+"\\mapsto "+right.latex;
3090 if (scm)
3091 ml.scheme=scm_concat(left.scheme+" \"<mapsto>\" "+right.scheme);
3092 }
3093 return ml;
3094 }
3095 if (g.is_symb_of_sommet(at_tran) || g.is_symb_of_sommet(at_transpose) || g.is_symb_of_sommet(at_trn)){
3096 ml.priority=_PRIORITY_EXP;
3097 tmp=gen2markup(g._SYMBptr->feuille,flags,idc,contextptr);
3098 ml.neg=tmp.neg;
3099 if (tmp.priority>=ml.priority)
3100 parenthesize(tmp,flags);
3101 if (mml_content)
3102 ml.content=mml_tag("apply",(g.is_symb_of_sommet(at_trn)?mml_tag("ci","trn",0,"type","function")
3103 :"<transpose/>")+tmp.content,++idc);
3104 if (mml_presentation)
3105 ml.markup=mml_tag(
3106 "msup",tmp.markup+(g.is_symb_of_sommet(at_trn)?"<mi>∗</mi>"
3107 :"<mi mathvariant='sans-serif'>T</mi>"),idc);
3108 if (tex)
3109 ml.latex=tmp.latex+"^{"+(g.is_symb_of_sommet(at_trn)?"\\ast":"\\mathsf{T}")+"}";
3110 if (scm)
3111 ml.scheme=scm_concat(tmp.scheme+" (rsup "+(g.is_symb_of_sommet(at_trn)?"\"<ast>\")":"(math-ss \"T\"))"));
3112 return ml;
3113 }
3114 if (g.is_symb_of_sommet(at_increment) || g.is_symb_of_sommet(at_decrement)) {
3115 ml.priority=_PRIORITY_UNARY;
3116 tmp=gen2markup(g._SYMBptr->feuille,flags,idc,contextptr);
3117 prepend_minus(tmp,flags);
3118 if (tmp.priority>=ml.priority)
3119 parenthesize(tmp,flags);
3120 if (mml_content)
3121 ml.content=mml_tag(
3122 "apply",(g.is_symb_of_sommet(at_increment)?"<ci>++</ci>":"<ci>--</ci>")+tmp.content,++idc);
3123 if (mml_presentation)
3124 ml.markup=mml_tag(
3125 "mrow",tmp.markup+"<mo mathsize='small'>"+
3126 string(g.is_symb_of_sommet(at_increment)?"++":"−−")+"</mo>",idc);
3127 if (tex)
3128 ml.latex=tmp.latex+"\\mathclose{"+string(g.is_symb_of_sommet(at_increment)?"++}":"--}");
3129 if (scm)
3130 ml.scheme=scm_concat(tmp.scheme+" \""+string(g.is_symb_of_sommet(at_increment)?"++":"--")+"\"");
3131 return ml;
3132 }
3133 if ((g.is_symb_of_sommet(at_when) || g.is_symb_of_sommet(at_piecewise)) &&
3134 vectarg && g._SYMBptr->feuille._VECTptr->size()>=3) {
3135 const vecteur &args=*g._SYMBptr->feuille._VECTptr;
3136 ml.priority=_PRIORITY_COND;
3137 MarkupBlock otw;
3138 int nargs=args.size();
3139 bool has_otherwise=(nargs%2)!=0;
3140 if (has_otherwise) {
3141 otw=gen2markup(args.back(),flags,idc,contextptr);
3142 prepend_minus(otw,flags);
3143 }
3144 for (int i=0;i<nargs/2;++i) {
3145 get_leftright(makevecteur(args[2*i+1],args[2*i]),&ml,left,right,flags,idc,contextptr);
3146 if (mml_content)
3147 ml.content+=mml_tag("piece",left.content+right.content);
3148 if (mml_presentation)
3149 ml.markup+=mml_tag("mtr",mml_tag("mtd",left.markup+"<mo>,</mo>")+
3150 mml_tag("mtd",right.markup));
3151 if (tex)
3152 ml.latex+=left.latex+",&"+right.latex+"\\\\";
3153 if (scm)
3154 ml.scheme+=" (row (cell (concat "+left.scheme+" \",\")) (cell "+right.scheme+"))";
3155 }
3156 if (has_otherwise) {
3157 if (mml_content)
3158 ml.content+=mml_tag("otherwise",otw.content);
3159 if (mml_presentation)
3160 ml.markup+=mml_tag("mtr",mml_tag("mtd",otw.markup+"<mo>,</mo>")+
3161 mml_tag("mtd","<mi mathvariant='normal'>otherwise</mi>"));
3162 if (tex)
3163 ml.latex+=otw.latex+",&\\text{otherwise}";
3164 if (scm)
3165 ml.scheme+=" (row (cell (concat "+otw.scheme+" \",\")) (cell (text \"otherwise\")))";
3166 }
3167 if (mml_content)
3168 ml.content=mml_tag("piecewise",ml.content,++idc);
3169 if (mml_presentation)
3170 ml.markup=mml_tag("mfenced",mml_tag("mtable",ml.markup,0,"columnalign","left"),
3171 idc,"open","{","close"," ");
3172 if (tex)
3173 ml.latex="\\begin{cases}"+ml.latex+"\\end{cases}";
3174 if (scm)
3175 ml.scheme="(choice (tformat (table"+ml.scheme+")))";
3176 return ml;
3177 }
3178 if (g.is_symb_of_sommet(at_factorial)) {
3179 ml.priority=_PRIORITY_UNARY;
3180 ml.type=_MLBLOCK_FACTORIAL;
3181 tmp=gen2markup(g._SYMBptr->feuille,flags,idc,contextptr);
3182 prepend_minus(tmp,flags);
3183 if (tmp.priority>=ml.priority)
3184 parenthesize(tmp,flags);
3185 if (mml_content)
3186 ml.content=mml_tag("apply","<factorial/>"+tmp.content,++idc);
3187 if (mml_presentation)
3188 ml.markup=mml_tag("mrow",tmp.markup+"<mo>!</mo>",idc);
3189 if (tex)
3190 ml.latex=tmp.latex+"\\mathclose{!}";
3191 if (scm)
3192 ml.scheme=scm_concat(tmp.scheme+" \"!\"");
3193 return ml;
3194 }
3195 if ((g.is_symb_of_sommet(at_binomial) || g.is_symb_of_sommet(at_nCr) ||
3196 g.is_symb_of_sommet(at_comb)) && vectarg &&
3197 isbinary) {
3198 const vecteur &args=*g._SYMBptr->feuille._VECTptr;
3199 left=gen2markup(args.front(),flags,idc,contextptr);
3200 prepend_minus(left,flags);
3201 right=gen2markup(args.back(),flags,idc,contextptr);
3202 prepend_minus(right,flags);
3203 if (mml_content)
3204 ml.content=mml_tag("apply",mml_csymbol("binomial","combinat1")+left.content+right.content,++idc);
3205 if (mml_presentation)
3206 ml.markup=mml_tag("mfenced","<mfrac linethickness='0'>"+left.markup+right.markup+"</mfrac>",idc);
3207 if (tex)
3208 ml.latex="\\binom{"+left.latex+"}{"+right.latex+"}";
3209 if (scm)
3210 ml.scheme="(binom "+left.scheme+" "+right.scheme+")";
3211 return ml;
3212 }
3213 if (g.is_symb_of_sommet(at_l1norm) || g.is_symb_of_sommet(at_l2norm) ||
3214 g.is_symb_of_sommet(at_norm) || g.is_symb_of_sommet(at_maxnorm) ||
3215 g.is_symb_of_sommet(at_matrix_norm)) {
3216 tmp=gen2markup(vectarg?g._SYMBptr->feuille._VECTptr->front():g._SYMBptr->feuille,
3217 flags,idc,contextptr);
3218 prepend_minus(tmp,flags);
3219 MarkupBlock d;
3220 int n=-2;
3221 if (g.is_symb_of_sommet(at_maxnorm) || (g.is_symb_of_sommet(at_matrix_norm) && vectarg &&
3222 g._SYMBptr->feuille._VECTptr->size()>1)) {
3223 if (g.is_symb_of_sommet(at_maxnorm) || is_inf(g._SYMBptr->feuille._VECTptr->at(1)))
3224 n=0;
3225 else {
3226 d=gen2markup(g._SYMBptr->feuille._VECTptr->at(1),flags,idc,contextptr);
3227 n=-1;
3228 }
3229 } else if (g.is_symb_of_sommet(at_l1norm))
3230 n=1;
3231 else if (g.is_symb_of_sommet(at_l2norm) || g.is_symb_of_sommet(at_norm))
3232 n=2;
3233 if (mml_content) {
3234 if (n<0 || n==1)
3235 ml.content=mml_tag("apply",mml_csymbol("L_norm","norm1")+
3236 (n<0?d.content:mml_tag("ci","1",0,"type","integer"))+tmp.content,
3237 ++idc);
3238 else
3239 ml.content=mml_tag("apply",mml_csymbol(n<1?
3240 "L_infinity_norm":"Euclidean_norm","norm1")+tmp.content,
3241 ++idc);
3242 }
3243 if (mml_presentation)
3244 ml.markup="<mo>‖</mo>"+tmp.markup+"<mo>‖</mo>";
3245 if (tex)
3246 ml.latex="\\left\\|"+tmp.latex+"\\right\\|";
3247 if (scm)
3248 ml.scheme="(around* \"||\" "+tmp.scheme+" \"||\")";
3249 if (n>-2) {
3250 string N=gen(n).print(contextptr);
3251 if (mml_presentation)
3252 ml.markup=mml_tag("msub","<mrow>"+ml.markup+"</mrow>"+
3253 (n<0?d.markup:(n<1?"<mi>∞</mi>":mml_tag("mn",N))),idc);
3254 if (tex)
3255 ml.latex+="_{"+(n<0?d.latex:(n<1?"\\infty":N))+"}";
3256 if (scm)
3257 ml.scheme=scm_concat(ml.scheme+" (rsub "+(n<0?d.scheme:(n<1?"\"<infty>\"":scm_quote(N)))+")");
3258 } else if (mml_presentation)
3259 ml.markup=mml_tag("mrow",ml.markup,idc);
3260 return ml;
3261 }
3262 if (g.is_symb_of_sommet(at_logb) && vectarg && isbinary) {
3263 get_leftright(g._SYMBptr->feuille,NULL,left,right,flags,idc,contextptr);
3264 parenthesize(left,flags);
3265 ml.priority=_PRIORITY_APPLY;
3266 if (mml_content)
3267 ml.content=mml_tag(
3268 "apply","<log/>"+mml_tag("logbase",right.content)+left.content,++idc);
3269 if (mml_presentation)
3270 ml.markup=mml_tag(
3271 "mrow",mml_tag("msub","<mi>log</mi>"+right.markup)+left.markup,idc);
3272 if (tex)
3273 ml.latex="\\mathop{\\log_{"+right.latex+"}}"+left.latex;
3274 if (scm)
3275 ml.scheme="(concat \"log\" (rsub "+right.scheme+") \" \" "+left.scheme+")";
3276 return ml;
3277 }
3278 if (g.is_symb_of_sommet(at_unit) && vectarg && isbinary) {
3279 const vecteur &args=*g._SYMBptr->feuille._VECTptr;
3280 left=gen2markup(args.front(),flags,idc,contextptr);
3281 right=gen2markup(args.back(),flags | _MARKUP_UNIT,idc,contextptr);
3282 ml.priority=_PRIORITY_MUL;
3283 ml.neg=(left.neg!=right.neg);
3284 if (mml_content)
3285 ml.content=mml_tag("apply","<times/>"+left.content+right.content,++idc);
3286 if (mml_presentation)
3287 ml.markup=mml_tag("mrow",
3288 left.markup+mml_tag("mo",mml_itimes,0,"rspace","thickmathspace")+right.markup,idc);
3289 if (tex)
3290 ml.latex=left.latex+"\\;"+right.latex;
3291 if (scm)
3292 ml.scheme=scm_concat(left.scheme+" \"<space>\" "+right.scheme);
3293 return ml;
3294 }
3295 if (g.is_symb_of_sommet(at_at) && vectarg && isbinary) {
3296 const vecteur &args=*g._SYMBptr->feuille._VECTptr;
3297 ml.priority=_PRIORITY_APPLY;
3298 ml.type=_MLBLOCK_HAS_SUBSCRIPT;
3299 tmp=gen2markup(args.front(),flags,idc,contextptr);
3300 prepend_minus(tmp,flags);
3301 if (tmp.priority>ml.priority || tmp.ctype(_MLBLOCK_HAS_SUBSCRIPT))
3302 parenthesize(tmp,flags);
3303 MarkupBlock sub;
3304 if (args.back().type==_VECT && args.back().subtype==_SEQ__VECT) {
3305 const vecteur &idx=*args.back()._VECTptr;
3306 string sep=mml_icomma,sept=" ",seps="<nocomma>";
3307 for (const_iterateur it=idx.begin();it!=idx.end();++it) {
3308 if ((!it->is_integer() || it->val<1 || it->val>9) &&
3309 (it->type!=_IDNT ||
3310 (((str=it->print(contextptr)).length()!=1 || !isalpha(str[0])) &&
3311 !is_greek_letter(str)))) {
3312 sep="<mo>,</mo>";
3313 sept=seps=",";
3314 break;
3315 }
3316 }
3317 for (const_iterateur it=idx.begin();it!=idx.end();++it) {
3318 sub=gen2markup(*it,flags,idc,contextptr);
3319 prepend_minus(sub,flags);
3320 if (mml_content)
3321 ml.content+=sub.content;
3322 if (mml_presentation)
3323 ml.markup+=(it!=idx.begin()?sep:"")+sub.markup;
3324 if (tex)
3325 ml.latex+=(it!=idx.begin()?sept:"")+sub.latex;
3326 if (scm)
3327 ml.scheme+=(it!=idx.begin()?" \""+seps+"\" ":"")+sub.scheme;
3328 }
3329 if (idx.size()>1 && scm)
3330 ml.scheme=scm_concat(ml.scheme);
3331 if (mml_content)
3332 ml.content=mml_tag("apply","<selector/>"+tmp.content+ml.content,++idc);
3333 if (mml_presentation)
3334 ml.markup=mml_tag("msub",tmp.markup+mml_tag("mrow",ml.markup),idc);
3335 if (tex)
3336 ml.latex=tmp.latex+"_{"+ml.latex+"}";
3337 if (scm)
3338 ml.scheme=scm_concat(tmp.scheme+" (rsub "+scm_nobrackets(ml.scheme)+")");
3339 } else {
3340 sub=gen2markup(args.back(),flags,idc,contextptr);
3341 prepend_minus(sub,flags);
3342 if (mml_content)
3343 ml.content=mml_tag("apply","<selector/>"+tmp.content+sub.content,++idc);
3344 if (mml_presentation)
3345 ml.markup=mml_tag("msub",tmp.markup+sub.markup,idc);
3346 if (tex)
3347 ml.latex=tmp.latex+"_{"+sub.latex+"}";
3348 if (scm)
3349 ml.scheme=scm_concat(tmp.scheme+" (rsub "+scm_nobrackets(sub.scheme)+")");
3350 }
3351 return ml;
3352 }
3353 if (dynamic_cast<const unary_function_user *>(g._SYMBptr->sommet.ptr())!=0 && vectarg &&
3354 isbinary) {
3355 ml.priority=_PRIORITY_APPLY;
3356 get_leftright(g._SYMBptr->feuille,&ml,left,right,flags,idc,contextptr);
3357 string op(g._SYMBptr->sommet.ptr()->s),opt,ops;
3358 if (mml_content)
3359 ml.content=mml_tag("apply",mml_tag("ci",op)+left.content+right.content,++idc);
3360 if (op.length()==1 && !isalpha(op[0]) && op[0]!='_') {
3361 op="<mo>"+op+"</mo>";
3362 opt="\\mathbin{"+op+"}";
3363 ops=scm_quote(op);
3364 } else {
3365 op="<mspace width='thickmathspace'/>"+idnt2markup(op,2,false,idc)+
3366 "<mspace width='thickmathspace'/>";
3367 opt="\\;"+idnt2markup(op,0)+"\\;";
3368 ops="\"<space>\" "+idnt2markup(op,1)+" \"<space>\"";
3369 }
3370 if (mml_presentation)
3371 ml.markup=mml_tag("mrow",left.markup+op+right.markup,idc);
3372 if (tex)
3373 ml.latex=left.latex+opt+right.latex;
3374 if (scm)
3375 ml.scheme=scm_concat(left.scheme+" "+ops+" "+right.scheme);
3376 return ml;
3377 }
3378 if (g.is_symb_of_sommet(at_local) || g.is_symb_of_sommet(at_ifte) ||
3379 g.is_symb_of_sommet(at_evalb) || g.is_symb_of_sommet(at_maple_if) ||
3380 g.is_symb_of_sommet(at_for) || g.is_symb_of_sommet(at_return) ||
3381 g.is_symb_of_sommet(at_try_catch) || g.is_symb_of_sommet(at_case) ||
3382 g.is_symb_of_sommet(at_throw) || g.is_symb_of_sommet(at_halt) ||
3383 g.is_symb_of_sommet(at_break) || g.is_symb_of_sommet(at_continue) ||
3384 g.is_symb_of_sommet(at_goto) || g.is_symb_of_sommet(at_si) ||
3385 g.is_symb_of_sommet(at_pour) || g.is_symb_of_sommet(at_tantque)) {
3386 flags|=_MARKUP_CODE;
3387 string2markup(ml,g.print(contextptr),flags,idc);
3388 ml.priority=_PRIORITY_OTHER;
3389 return ml;
3390 }
3391 if (g.is_symb_of_sommet(at_pnt))
3392 break;
3393 // general SYMB
3394 ml.priority=_PRIORITY_APPLY;
3395 if (g.is_symb_of_sommet(at_of)) {
3396 const vecteur &args=*g._SYMBptr->feuille._VECTptr;
3397 tmp=gen2markup(args.front(),flags,idc,contextptr);
3398 prepend_minus(tmp,flags);
3399 if (!tmp.ctype(_MLBLOCK_DERIVATIVE) && tmp.priority>=ml.priority)
3400 parenthesize(tmp,flags);
3401 if (mml_content)
3402 ml.content=tmp.content;
3403 if (mml_presentation)
3404 ml.markup=tmp.markup+mml_apply;
3405 if (tex)
3406 ml.latex=tmp.latex;
3407 if (scm)
3408 ml.scheme=tmp.scheme;
3409 gp=&args.back();
3410 } else {
3411 gp=&g._SYMBptr->feuille;
3412 if (mml_content)
3413 ml.content=func2markup(g,2,++idc);
3414 if (mml_presentation)
3415 ml.markup=func2markup(g,3,idc);
3416 if (tex)
3417 ml.latex=func2markup(g,0);
3418 if (scm)
3419 ml.scheme=func2markup(g,1);
3420 }
3421 if (gp->type==_VECT && gp->subtype==_SEQ__VECT) {
3422 string vs,vsc,vst,vss;
3423 for (const_iterateur it=gp->_VECTptr->begin();it!=gp->_VECTptr->end();++it) {
3424 tmp=gen2markup(*it,flags,idc,contextptr);
3425 if (mml_content)
3426 vsc+=tmp.content;
3427 if (mml_presentation)
3428 vs+=tmp.markup;
3429 if (tex)
3430 vst+=(it!=gp->_VECTptr->begin()?",":"")+tmp.latex;
3431 if (scm)
3432 vss+=(it!=gp->_VECTptr->begin()?" \",\" ":"")+tmp.scheme;
3433 }
3434 if (mml_content)
3435 ml.content=mml_tag("apply",ml.content+vsc,++idc);
3436 if (mml_presentation)
3437 ml.markup=mml_tag("mrow",ml.markup+mml_tag("mfenced",vs),idc);
3438 if (tex)
3439 ml.latex+="\\left("+vst+"\\right)";
3440 if (scm) {
3441 if (gp->_VECTptr->size()>1)
3442 vss=scm_concat(vss);
3443 ml.scheme=scm_concat(ml.scheme+" \" \" (around* \"(\" "+vss+" \")\")");
3444 }
3445 } else {
3446 tmp=gen2markup(*gp,flags,idc,contextptr);
3447 prepend_minus(tmp,flags);
3448 if (is_elemfunc(g)) {
3449 ml.type=_MLBLOCK_ELEMAPP;
3450 ml.split_pos=ml.markup.length();
3451 ml.split_pos_tex=ml.latex.length();
3452 ml.split_pos_scm=ml.scheme.length()+8;
3453 ml.appl=(tmp.priority==0 && !tmp.ctype(_MLBLOCK_NUMERIC_EXACT) &&
3454 !tmp.ctype(_MLBLOCK_NUMERIC_APPROX) && !tmp.ctype(_MLBLOCK_SUBTYPE_IDNT));
3455 }
3456 if (!ml.appl)
3457 parenthesize(tmp,flags);
3458 if (mml_content)
3459 ml.content=mml_tag("apply",ml.content+tmp.content,++idc);
3460 if (mml_presentation)
3461 ml.markup=mml_tag("mrow",ml.markup+mml_apply+tmp.markup,idc);
3462 if (tex)
3463 ml.latex+=tmp.latex;
3464 if (scm) {
3465 if (ml.appl)
3466 tmp.scheme=scm_nobrackets(tmp.scheme);
3467 ml.scheme=scm_concat(ml.scheme+" \" \" "+tmp.scheme);
3468 }
3469 }
3470 return ml;
3471 default:
3472 break;
3473 }
3474 // unsupported gen, call legacy conversion routines
3475 ml.priority=_PRIORITY_OTHER;
3476 if (tex)
3477 ml.latex=gen2tex(g,contextptr);
3478 if (scm)
3479 ml.scheme="(text (with \"color\" \"red\" "+
3480 str_to_scm(g.print(contextptr),false,false)+"))";
3481 if (mml_content)
3482 ml.content=mml_tag("cerror",mml_tag("csymbol","ExpressionNotSupported"),++idc);
3483 if (mml_presentation)
3484 ml.markup=insert_id(gen2mathml(g,contextptr),idc,false);
3485 return ml;
3486 }
3487
export_latex(const gen & g,GIAC_CONTEXT)3488 string export_latex(const gen &g,GIAC_CONTEXT) {
3489 MarkupBlock ml;
3490 int idc=0,flags=_MARKUP_TOPLEVEL | _MARKUP_ELEMPOW | _MARKUP_LATEX;
3491 ml=gen2markup(g,flags,idc,contextptr);
3492 prepend_minus(ml,flags);
3493 return ml.latex;
3494 }
3495
gen2scm(const gen & g,GIAC_CONTEXT)3496 string gen2scm(const gen &g,GIAC_CONTEXT) {
3497 MarkupBlock ml;
3498 int idc=0,flags=_MARKUP_TOPLEVEL | _MARKUP_ELEMPOW | _MARKUP_SCHEME;
3499 ml=gen2markup(g,flags,idc,contextptr);
3500 prepend_minus(ml,flags);
3501 return ml.scheme;
3502 }
3503
3504 // XML pretty printing
3505 #define XML_INDENT 2
3506 const string xml_element_name_end=" \t\n\r>";
trim_string(const string & s)3507 string trim_string(const string &s) {
3508 size_t start,end;
3509 for (start=0;start<s.size() && isspace(s[start]);start++);
3510 for (end=s.size();end-->0 && isspace(s[end]););
3511 return s.substr(start,end-start+1);
3512 }
xml_read_element(const string & xml,size_t & pos,string & element,string & attrib,string & content)3513 bool xml_read_element(const string &xml,size_t &pos,string &element,string &attrib,string &content) {
3514 while (pos<xml.size() && isspace(xml[pos])) ++pos;
3515 if (pos==xml.size()) {
3516 element=attrib=content="";
3517 return true;
3518 }
3519 if (xml[pos]!='<') return false;
3520 size_t start=pos+1;
3521 if (is_prefix(xml.substr(start),"--!")) {
3522 pos=xml.find("-->",start);
3523 if (pos==string::npos) return false;
3524 element="";
3525 content=xml.substr(start+3,pos-start-3);
3526 pos+=3;
3527 return true;
3528 }
3529 while (xml_element_name_end.find(xml[++pos])==string::npos) {
3530 if (pos+1==xml.size()) return false;
3531 }
3532 string e=xml.substr(start,pos-start);
3533 size_t astart=pos;
3534 while (xml[pos++]!='>') {
3535 if (pos==xml.size()) return false;
3536 }
3537 if (xml[pos-2]=='/') {
3538 content=attrib="";
3539 if (is_suffix(e,"/"))
3540 e="/"+e.substr(0,e.size()-1);
3541 else {
3542 attrib=trim_string(xml.substr(astart,pos-astart-2));
3543 e="/"+e;
3544 }
3545 } else if (xml[pos-2]=='?' && e=="?xml" && pos-astart-2>0)
3546 attrib=trim_string(xml.substr(astart,pos-astart-2));
3547 else {
3548 size_t p=pos,cstart=pos,q;
3549 int level=1;
3550 while(p<xml.size()) {
3551 if (xml[p]=='<') {
3552 q=xml.find(">",p+1);
3553 if (q==string::npos) return false;
3554 if (xml[q-1]=='/') {
3555 p=q+1;
3556 continue;
3557 }
3558 if (xml[p+1]=='/') {
3559 level--;
3560 if (level==0 && is_prefix(xml.substr(p+2),e) &&
3561 xml_element_name_end.find(xml[p+2+e.size()])!=string::npos) {
3562 pos=q+1;
3563 break;
3564 }
3565 } else level++;
3566 p=q;
3567 }
3568 ++p;
3569 }
3570 if(p==xml.size()) return false;
3571 attrib=trim_string(xml.substr(astart,cstart-astart-1));
3572 content=trim_string(xml.substr(cstart,p-cstart));
3573 }
3574 element=e;
3575 return true;
3576 }
xml_pretty_print(const string & xml,int level=0)3577 string xml_pretty_print(const string &xml,int level=0) {
3578 size_t pos=0;
3579 string element,attrib,content,indent=string(level*XML_INDENT,32),ret="";
3580 while(pos!=xml.size()) {
3581 if (!xml_read_element(xml,pos,element,attrib,content)) return xml;
3582 if (!attrib.empty()) attrib=" "+attrib;
3583 if (element.empty() && content.empty()) continue;
3584 if (element.empty()) // the "element" is actually a comment
3585 ret+=indent+"<--!"+content+"-->\n";
3586 else if (element[0]=='?')
3587 ret+=indent+"<"+element+attrib+"?>\n";
3588 else if (element[0]=='/')
3589 ret+=indent+"<"+element.substr(1)+attrib+"/>\n";
3590 else
3591 ret+=indent+"<"+element+attrib+">"+xml_pretty_print(content,level+1)+"</"+element+">\n";
3592 }
3593 if (trim_string(ret).empty())
3594 return "";
3595 if (level==0 && ret.size()>0 && ret[ret.size()-1]=='\n')
3596 ret=ret.substr(0,ret.size()-1);
3597 return (level>0?"\n":"")+ret+(level>1?string((level-1)*XML_INDENT,32):"");
3598 }
3599
3600 const string mathml_header_attributes="mode='display' xmlns='http://www.w3.org/1998/Math/MathML'";
3601
export_mathml_content(const gen & g,GIAC_CONTEXT)3602 string export_mathml_content(const gen &g,GIAC_CONTEXT) {
3603 MarkupBlock ml;
3604 int idc=0,flags=_MARKUP_TOPLEVEL | _MARKUP_MATHML_CONTENT;
3605 ml=gen2markup(g,flags,idc,contextptr);
3606 prepend_minus(ml,flags);
3607 return "<math "+mathml_header_attributes+">"+ml.content+"</math>";
3608 }
3609
export_mathml_presentation(const gen & g,GIAC_CONTEXT)3610 string export_mathml_presentation(const gen &g,GIAC_CONTEXT) {
3611 MarkupBlock ml;
3612 int idc=0,flags=_MARKUP_TOPLEVEL | _MARKUP_ELEMPOW | _MARKUP_MATHML_PRESENTATION;
3613 ml=gen2markup(g,flags,idc,contextptr);
3614 prepend_minus(ml,flags);
3615 return "<math "+mathml_header_attributes+">"+ml.markup+"</math>";
3616 }
3617
export_mathml(const gen & g,GIAC_CONTEXT)3618 string export_mathml(const gen &g,GIAC_CONTEXT) {
3619 MarkupBlock ml;
3620 int idc=0,flags=_MARKUP_TOPLEVEL | _MARKUP_MATHML_PRESENTATION | _MARKUP_MATHML_CONTENT;
3621 ml=gen2markup(g,flags,idc,contextptr);
3622 prepend_minus(ml,flags);
3623 return "<math "+mathml_header_attributes+"><semantics>"+ml.markup+
3624 "<annotation-xml encoding='MathML-Content'>"+ml.content+"</annotation-xml>"+
3625 "<annotation encoding='Giac'>"+str_to_mml(g.print(contextptr),false)+
3626 "</annotation></semantics></math>";
3627 }
3628
3629 #ifndef KHICAS
has_improved_latex_export(const gen & g,string & s,bool override_texmacs,GIAC_CONTEXT)3630 bool has_improved_latex_export(const gen &g,string &s,bool override_texmacs,GIAC_CONTEXT) {
3631 if (force_legacy_conversion_to_latex || g.is_symb_of_sommet(at_pnt))
3632 return false;
3633 switch (g.type) {
3634 case _POLY: case _SPOL1: case _EXT: case _ROOT:
3635 case _USER: case _EQW: case _GROB: case _POINTER_:
3636 return false;
3637 default:
3638 break;
3639 }
3640 bool use_texmacs_compatibility=is_texmacs_compatible_latex_export;
3641 if (override_texmacs)
3642 enable_texmacs_compatible_latex_export(false);
3643 force_legacy_conversion_to_latex=true;
3644 s=export_latex(g,contextptr);
3645 force_legacy_conversion_to_latex=false;
3646 if (override_texmacs)
3647 enable_texmacs_compatible_latex_export(use_texmacs_compatibility);
3648 return true;
3649 }
3650 #endif
3651
_export_mathml(const gen & g,GIAC_CONTEXT)3652 gen _export_mathml(const gen &g,GIAC_CONTEXT) {
3653 if (g.type==_STRNG && g.subtype==-1) return g;
3654 gen e;
3655 int extype=0;
3656 if (g.type==_VECT && g.subtype==_SEQ__VECT) {
3657 const vecteur &args=*g._VECTptr;
3658 if (args.size()!=2) return gensizeerr(contextptr);
3659 e=args.front();
3660 if (args.back()==at_display)
3661 extype=1;
3662 else if (args.back()==at_content)
3663 extype=2;
3664 else return gensizeerr(contextptr);
3665 } else e=g;
3666 string ret;
3667 switch (extype) {
3668 case 0:
3669 ret=export_mathml(e,contextptr);
3670 break;
3671 case 1:
3672 ret=export_mathml_presentation(e,contextptr);
3673 break;
3674 case 2:
3675 ret=export_mathml_content(e,contextptr);
3676 break;
3677 default:
3678 assert(false); // unreachable
3679 }
3680 return string2gen(ret,false);
3681 }
3682 static const char _export_mathml_s[]="export_mathml";
3683 static define_unary_function_eval(__export_mathml,&_export_mathml,_export_mathml_s);
3684 define_unary_function_ptr5(at_export_mathml,alias_at_export_mathml,&__export_mathml,0,true)
3685
_xml_print(const gen & g,GIAC_CONTEXT)3686 gen _xml_print(const gen &g,GIAC_CONTEXT) {
3687 if (g.type!=_STRNG)
3688 return gentypeerr(contextptr);
3689 if (g.subtype==-1)
3690 return g;
3691 string s=g.print(contextptr);
3692 s=s.substr(1,s.size()-2);
3693 return string2gen(xml_pretty_print(s),false);
3694 }
3695 static const char _xml_print_s[]="xml_print";
3696 static define_unary_function_eval(__xml_print,&_xml_print,_xml_print_s);
3697 define_unary_function_ptr5(at_xml_print,alias_at_xml_print,&__xml_print,0,true)
3698
3699 #ifndef NO_NAMESPACE_GIAC
3700 } // namespace giac
3701 #endif // ndef NO_NAMESPACE_GIAC
3702