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>&it;</mo>";
45 const string mml_cdot="<mo>&middot;</mo>";
46 const string mml_dot="<mo>.</mo>";
47 const string mml_times="<mo>&times;</mo>";
48 const string mml_plus="<mo>+</mo>";
49 const string mml_minus="<mo>&minus;</mo>";
50 const string mml_apply="<mo>&af;</mo>";
51 const string mml_icomma="<mo>&ic;</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>&realpart;</mi>";
56 const string mml_im="<mi>&imagpart;</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+="&amp;";
365       break;
366     case '<':
367       ret+="&lt;";
368       break;
369     case '>':
370       ret+="&gt;";
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","&alpha;",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>&epsilon;</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>&epsilon;</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>&epsilon;</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","&#x210f;",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>&lambda;</mi><mn>0</mn>",idc));
644     else if (s=="lambdac_")
645       return tex?"\\lambda ":(scm?"<space><nosymbol><lambda><nosymbol>":mml_tag("mi","&lambda;",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>&oplus;</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>&mu;</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>&mu;</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>&mu;</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>&Phi;</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>&odot;</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>&oplus;</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>&infin;</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>&odot;</mi>",idc));
695     else if (s=="sigma_")
696       return tex?"\\sigma ":(scm?"<space><nosymbol><sigma><nosymbol>":mml_tag("mi","&sigma;",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","&#x2109;",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","&#x00b0;",idc,"class","MathML-Unit"));
725     else if (s=="arcmin")
726       return tex?"'":(scm?"(rprime \"'\")":mml_tag("mi","&prime;",idc,"class","MathML-Unit"));
727     else if (s=="arcs")
728       return tex?"''":(scm?"(rprime \"''\")":mml_tag("mi","&Prime;",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","&#x00b0;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>":"&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+"&#x00c5;",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+"&#x00c5;",idc,"class","MathML-Unit"));
800       } else if (s=="Ohm")
801         return tex?p+"\\Omega "
802                   :(scm?p+"<space><nosymbol><Omega>":mml_tag("mi",p+"&Omega;",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+"&Omega;",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>&ominus;</mo>":mml_minus)+ml.markup,
947                         0,id.empty()?"":"xref",id);
948     } else ml.markup=(circled?"<mo>&ominus;</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 &deg,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>&delta;</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>&theta;</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'>&Gamma;</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'>&Beta;</mi>"));
1152     else if (g.is_symb_of_sommet(at_euler))
1153       ret=tex?"\\phi":(content?mml_csymbol("euler","integer2")
1154                                      :"<mi mathvariant='normal'>&phi;</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'>&Psi;</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'>&zeta;</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","&integers;",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","&rationals;",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","&complexes;",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","&reals;",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>&times;</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","&infin;",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","&pi;",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","&gamma;",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","&empty;",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="&epsilon;";
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>&oplus;</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>&oplus;</mo>":"<mo>&ominus;</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>&odot;</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>&oslash;</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>&#xaf;</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)?"&lfloor;":"&lceil;"));
2171       rd=(g.is_symb_of_sommet(at_abs)?"|":(g.is_symb_of_sommet(at_floor)?"&rfloor;":"&rceil;"));
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>&minus;</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?"&int;":(issum?"&sum;":"&prod;"))+"</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>&rarr;</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>&Prime;</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>&tprime;</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>&prime;</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>&part;</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                    ?"&#x2a75;"
2624                    :(g.is_symb_of_sommet(at_different)
2625                           ?"&#x2260;"
2626                           :(g.is_symb_of_sommet(at_equal)?"=":(g.is_symb_of_sommet(at_sto)?"&#x2254;":"&larr;"))));
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)?":=":"=&lt;"))));
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="&lt;";
2662         op_tex="<";
2663         op_scm="<less>";
2664         csymb="<lt/>";
2665       } else if (g.is_symb_of_sommet(at_inferieur_egal)) {
2666         op="&leq;";
2667         op_tex="\\leq ";
2668         op_scm="<leqslant>";
2669         csymb="<leq/>";
2670       } else if (g.is_symb_of_sommet(at_superieur_strict)) {
2671         op="&gt;";
2672         op_tex=">";
2673         op_scm="<gtr>";
2674         csymb="<gt/>";
2675       } else if (g.is_symb_of_sommet(at_superieur_egal)) {
2676         op="&geq;";
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)?"&cup;":"&cap;");
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>&setminus;</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>&isin;</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>&sube;</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>&not;</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)?"&veebar;":(g.is_symb_of_sommet(at_ou)?"&or;":"&and;"));
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>&#x2025;</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>&Delta;</mi>":"<mi>&nabla;</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="&compfn;",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>&compfn;</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>&mapsto;</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>&mapsto;</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>&#x2217;</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)?"++":"&minus;&minus;")+"</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>&#x2016;</mo>"+tmp.markup+"<mo>&#x2016;</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>&infin;</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