1:- module(mathml, [
    2    mathml/2,
    3    mathml/3,
    4    mml//1,
    5    mml//2,
    6    palette/2,
    7    op(400, yfx, invisible_times),
    8    op(180, xf, !),
    9    op(170, xf, '%'),
   10    op(200, xfy, '_'),
   11    op(500, yfx, '+-'),
   12    op(1050, xfy, '~>'),
   13    op(600, xfy, '~'),
   14    op(150, xfx, ...)]).
   15
   16:- op(180, xf, !).
   17:- op(170, xf, '%').
   18:- op(200, xfy, '_').
   19:- op(500, yfx, '+-').
   20:- op(400, yfx, invisible_times).
   21:- op(1050, xfy, '~>').
   22:- op(600, xfy, ~).
   23
   24:- discontiguous ml/3.
   25:- discontiguous paren/3.
   26:- discontiguous prec/3.
   27:- discontiguous math/4.
   28:- discontiguous example/0.
   29:- discontiguous denot/3.
   30
   31:- use_module(library(quantity)).
   32:- use_module(library(http/html_write)).
   33
   34%
   35% Interface
   36%
   37mml(A) -->
   38    mml([color-auto, highlight(all)], A).
   39    
   40mml(Flags, A) -->
   41    { select(color-auto, Flags, Removed),
   42      !, 
   43      palette(A, P),
   44      append(Removed, P, New)
   45    }, 
   46    mml(New, A).
   47
   48mml(Flags, A) -->
   49    { ml(Flags, A, M) },
   50    html(math(M)).
   51
   52mathml(A, M) :-
   53    mathml([color-auto, highlight(all)], A, M).
   54    
   55mathml(Flags, A, M) :-
   56    select(color-auto, Flags, Removed),
   57    !, 
   58    palette(A, P),
   59    append(Removed, P, New),
   60    mathml(New, A, M).
   61
   62mathml(Flags, A, Math) :-
   63    denoting(Flags, A, []),
   64    ml(Flags, A, M),
   65    !, Math = math(M).
   66
   67mathml(Flags, A, Math) :-
   68    denoting(Flags, A, [H | T]),
   69    ml(Flags, A, M),
   70    !, Math = p([math(M), " ", H | T]).
   71
   72mathml(Flags, A, Err) :-
   73    format(string(Err), "Conversion failed: ~k", mathml(Flags, A)).
   74    
   75%
   76% Show example
   77%
   78example(A) :-
   79    example([], A).
   80
   81example(Flags, A) :-
   82    mathml(Flags, A, M)
   83    -> writeln(math:A = ml:M)
   84     ; writeln(math:A = ml:failed).
   85
   86%
   87% For SWISH
   88%
   89% example(Flags, A) :-
   90%     ml(Flags, A, M) -> html(html(math(M))) ; writeln(failed).
   91
   92%
   93% Hook for custom definitions
   94%
   95% e.g., to replace s_D by sub(s, 'D'), use math_hook(_, s_D, sub(s, 'D')).
   96%
   97:- multifile ml_hook/3.
   98:- multifile math_hook/4.
   99
  100ml(Flags, A, M) :-
  101    ml_hook(Flags, A, M),
  102    !.
  103
  104math(Flags, A, New, M) :-
  105    math_hook(Flags, A, New, M),
  106    !.
  107
  108%
  109% Macros (e.g., red(X) for color("red", X)
  110%
  111ml(Flags, A, M) :-
  112    math(Flags, A, New, X),
  113    !, ml(New, X, M).
  114
  115paren(Flags, A, P) :-
  116    math(Flags, A, New, X),
  117    !, paren(New, X, P).
  118
  119%
  120% Precedence
  121%
  122% Macros
  123precedence(Flags, A, P) :-
  124    math(Flags, A, New, X),
  125    !, precedence(New, X, P).
  126
  127% Explicit definitions
  128precedence(Flags, A, P) :-
  129    prec(Flags, A, Prec),
  130    !, P = Prec.
  131
  132% Compounds
  133precedence(Flags, A, fun-P) :-
  134    compound(A),
  135    !, compound_name_arguments(A, _, Args),
  136    maplist({Flags}/[AX, F, PX] >> precedence(Flags, AX, F-PX), Args, _, Precs),
  137    max_list(Precs, P).
  138
  139% Otherwise, zero
  140precedence(_, _, atomic-0).
  141
  142%
  143% Punctuation
  144%
  145math(Flags, A, Flags, punct(A)) :-
  146    punctuation(A, _).
  147
  148punctuation(' ', mspace(width(thickmathspace), [])).
  149punctuation('_', &(nbsp)).
  150punctuation(ldots, mi(&(hellip))).
  151punctuation(cdots, mi(&(ctdot))).
  152
  153ml(_, punct(A), M) :-
  154    punctuation(A, M).
  155
  156paren(_, punct(_), 0).
  157
  158prec(_, punct(_), punct-0).
  159
  160example :- 
  161    example(' ').
  162    
  163example :- 
  164    example('_').
  165
  166%
  167% Operators
  168%
  169math(Flags, A, Flags, op(A)) :-
  170    operator(A, _).
  171
  172ml(_, op(A), mo(M)) :-
  173    operator(A, M).
  174
  175paren(_, op(_), 0).
  176
  177prec(_, op(_), op-0).
  178
  179operator(+, +).
  180operator(-, -).
  181operator(*, &(sdot)).
  182operator(/, /).
  183operator(=\=, &('#8203')).
  184operator(=, =).
  185operator(<, &(lt)).
  186operator(>, &(gt)).
  187operator(=<, &(le)).
  188operator(>=, &(ge)).
  189operator(\=, &(ne)).
  190operator(!, !).
  191operator('', '').
  192operator('+-', &('PlusMinus')).
  193operator('%', '%').
  194operator(',', &(comma)).
  195operator(';', &('#59')).
  196operator('|', '|').
  197operator(invisible_times, &('#x2062')).
  198operator(->, &(rArr)).
  199operator(~>, &(zigrarr)).
  200operator(~, ~).
  201operator(:, :).
  202operator(..., &(hellip)).
  203
  204example :- 
  205    example(/).
  206
  207%
  208% Greek letters
  209%
  210% Translate to clean representation
  211math(Flags, A, Flags, greek(A)) :-
  212    greek(A).
  213
  214% Non-italicized uppercase letters
  215math(Flags, A, Flags, greek(normal, A)) :-
  216    greek(normal, A).
  217
  218greek(alpha).
  219greek(beta).
  220greek(gamma).
  221greek(delta).
  222greek(epsilon).
  223greek(varepsilon).
  224greek(mu).
  225greek(pi).
  226greek(chi).
  227greek(sigma).
  228greek(phi).
  229greek(omega).
  230
  231greek(normal, 'Alpha').
  232greek(normal, 'Beta').
  233greek(normal, 'Gamma').
  234greek(normal, 'Delta').
  235greek(normal, 'Epsilon').
  236greek(normal, 'Mu').
  237greek(normal, 'Pi').
  238greek(normal, 'Sigma').
  239greek(normal, 'Chi').
  240greek(normal, 'Phi').
  241greek(normal, 'Omega').
  242
  243% Translate to mathml
  244ml(_, greek(A), mi(&(A))).
  245ml(_, greek(normal, A), mi([mathvariant(normal)], &(A))).
  246
  247% Level of parentheses
  248paren(_, greek(_), 0).
  249
  250% Precedence
  251prec(_, greek(_), greek-0).
  252
  253example :- 
  254    example(alpha).
  255
  256%
  257% General atoms ("identifiers")
  258%
  259% Translate to clean representation
  260math(Flags, A, Flags, atom(A)) :-
  261    atom(A).
  262
  263% Translate to mathml
  264ml(_, atom(A), mi(A)).
  265
  266% Level of parentheses
  267paren(_, atom(_), 0).
  268
  269% Precedence
  270prec(_, atom(_), atom-0).
  271
  272example :-
  273    example(k).
  274
  275%
  276% Strings (non-italicized)
  277%
  278% Translate to clean representation
  279math(Flags, A, Flags, string(A)) :-
  280    string(A).
  281
  282% Translate to mathml
  283ml(_, string(A), mtext(A)).
  284
  285% Level of parentheses
  286paren(_, string(_), 0).
  287
  288% Precedence
  289prec(_, string(_), string-0).
  290
  291example :- 
  292    example("text").
  293
  294%
  295% Parentheses: generic
  296%
  297ml(Flags, paren(A), M) :-
  298    paren(Flags, A, 1),
  299    !, ml(Flags, bracket(A), M).
  300
  301ml(Flags, paren(A), M) :-
  302    paren(Flags, A, 2),
  303    !, ml(Flags, curly(A), M).
  304
  305ml(Flags, paren(A), M) :-
  306    ml(Flags, parentheses(A), M).
  307
  308paren(Flags, paren(A), P) :-
  309    paren(Flags, A, P0),
  310    P is P0 + 1.
  311
  312prec(_, paren(_), paren-0).
  313
  314% specific
  315ml(Flags, parentheses(A), mrow([mo('('), X, mo(')')])) :-
  316    ml(Flags, A, X).
  317
  318paren(_, parentheses(_), 1).
  319
  320prec(_, parentheses(_), paren-0).
  321
  322ml(Flags, bracket(A), mrow([mo('['), X, mo(']')])) :-
  323    ml(Flags, A, X).
  324
  325paren(_, bracket(_), 2).
  326
  327prec(_, bracket(_), paren-0).
  328
  329ml(Flags, curly(A), mrow([mo('{'), X, mo('}')])) :-
  330    ml(Flags, A, X).
  331
  332paren(_, curly(_), 3).
  333
  334prec(_, curly(_), paren-0).
  335
  336ml(Flags, abs(A), mrow([mo('|'), X, mo('|')])) :-
  337    ml(Flags, A, X).
  338
  339paren(Flags, abs(A), P) :-
  340    paren(Flags, A, P).
  341
  342prec(_, abs(_), paren-0).
  343
  344example :- example(paren(x)).
  345example :- example(paren(bracket(x))).
  346example :- example(paren(paren(x))).
  347example :- example(paren(abs(x))).
  348
  349%
  350% Lists (e.g., function arguments)
  351%
  352math(Flags, [], Flags, '').
  353math(Flags, [H | T], Flags, list(Sep, [H | T])) :-
  354    member(sep-Sep, Flags).
  355
  356math(Flags, [H | T], Flags, list(',', [H | T])).
  357    
  358math(Flags, (H, T), Flags, list('', [H, T])).
  359math(Flags, (H; T), Flags, list(';', [H, T])).
  360math(Flags, (H| T), Flags, list('|', [H, T])).
  361
  362ml(Flags, list(Sep, List), M) :-
  363    exclude({Flags}/[add(Err, _)] >> correct(Flags, Err), List, List1),
  364    exclude({Sep}/[[]] >> (Sep=(+)), List1, New),
  365    ml(Flags, list_(Sep, New), M).
  366
  367ml(Flags, list_(Sep, [H | T]), mrow([HX | TX])) :-
  368    ml(Flags, H, HX),
  369    ml(Flags, tail(Sep, T), TX).
  370
  371ml(_, tail(_, []), []).
  372
  373ml(Flags, tail(Sep, [H | T]), [SX, HX | TX]) :-
  374    ml(Flags, Sep, SX),
  375    ml(Flags, H, HX),
  376    ml(Flags, tail(Sep, T), TX).
  377
  378paren(Flags, list(_, List), P) :-
  379    maplist({Flags}/[A, X] >> paren(Flags, A, X), List, PX),
  380    max_list(PX, P).
  381
  382prec(_, list(Sep, [_, _ | _]), P) :-
  383    current_op(Prec, _, Sep),
  384    !, P = list-Prec.
  385
  386prec(_, list(_, _), list-0).
  387
  388example :- 
  389    example([atom(x), atom(y), atom(z)]).
  390
  391example :- example((x, y, z)).
  392example :- example((x ; y, z)).
  393example :- example((x | y, z)).
  394example :- example(paren([paren(x), paren(y)])).
  395
  396%
  397% Colors
  398%
  399color(0, "red").
  400color(1, "blue").
  401color(2, "#00BF00").
  402color(3, "#9F5F00").
  403color(4, "#7F007F").
  404color(5, "#007F7F").
  405
  406color(Flags, Code, Color) :-
  407    member(color(Code, Color), Flags).
  408
  409palette(A, Flags) :-
  410    erroneous(A, Errs),
  411    sort(Errs, Errors),
  412    findall(color(E, C), (nth0(N, Errors, E), N6 is N mod 6, color(N6, C)), Flags).
  413    
  414math(Flags, red(A), Flags, color("red", A)).
  415math(Flags, green(A), Flags, color("green", A)).
  416math(Flags, blue(A), Flags, color("blue", A)).
  417math(Flags, black(A), Flags, color("black", A)).
  418math(Flags, grey(A), Flags, color("grey", A)).
  419math(Flags, lightred(A), Flags, color("#FFA0A0", A)).
  420
  421ml(Flags, color(String, A), mstyle(mathcolor(String), X)) :-
  422    string(String),
  423    ml([color(String) | Flags], A, X).
  424
  425ml(Flags, color(Num, A), X) :-
  426    number(Num),
  427    color(Num, String),
  428    ml(Flags, color(String, A), X).
  429    
  430ml(Flags, color(Atom, A), X) :-
  431    atom(Atom),
  432    member(color(Atom, String), Flags),
  433    ml(Flags, color(String, A), X).
  434    
  435paren(Flags, color(_, A), P) :-
  436    paren(Flags, A, P).
  437
  438prec(Flags, color(_, A), P) :-
  439    precedence(Flags, A, P).
  440
  441%
  442% Other decorations
  443%
  444ml(Flags, overline(A), mover(accent(true), [X, mo(&(macr))])) :-
  445    ml(Flags, A, X).
  446
  447paren(Flags, overline(A), P) :-
  448    paren(Flags, A, P).
  449
  450% Put average(x)^2 in parentheses
  451prec(Flags, overline(A), accent-P) :-
  452    precedence(Flags, atom(a)*A, _-P).
  453
  454% Proper average
  455math(Flags, mean(A), Flags, overline(A)).
  456
  457% Underbrace with text
  458ml(Flags, underbrace(A, Under),
  459    munder([accentunder(false)], [munder([accentunder(false)], [X, mo([stretchy(true), overflow(scale)], &('UnderBrace'))]), Y])) :-
  460    ml(Flags, A, X),
  461    ml(Flags, Under, Y).
  462
  463paren(Flags, underbrace(A, _), P) :-
  464    paren(Flags, A, P).
  465
  466prec(Flags, underbrace(A, _), P) :-
  467    precedence(Flags, A, P).
  468
  469% Strike through
  470math(Flags, cancel(Color, A), Flags, color(Color, strike(black(A)))).
  471
  472ml(Flags, strike(A), menclose(notation(updiagonalstrike), X)) :-
  473    ml(Flags, A, X).
  474
  475paren(Flags, strike(A), P) :-
  476    paren(Flags, A, P).
  477
  478% rounded box
  479ml(Flags, roundedbox(A), menclose(notation(roundedbox), X)) :-
  480    ml(Flags, A, X).
  481
  482paren(Flags, roundedbox(A), P) :-
  483    paren(Flags, A, P).
  484
  485% Colored or Box, depending on nested error
  486ml(Flags, color_or_box(Col, A), X) :-
  487    erroneous(A, [_ | _]),
  488    !, ml(Flags, color(Col, roundedbox(black(A))), X).
  489    
  490ml(Flags, color_or_box(Col, A), X) :-
  491    ml(Flags, color(Col, A), X).
  492    
  493paren(Flags, color_or_box(_, A), P) :-
  494    paren(Flags, A, P).
  495
  496prec(Flags, color_or_box(_, A), P) :-
  497    precedence(Flags, A, P).
  498
  499% invisible
  500ml(Flags, phantom(A), mphantom(X)) :-
  501    ml(Flags, A, X).
  502
  503paren(Flags, phantom(A), P) :-
  504    paren(Flags, A, P).
  505
  506% formatting numbers
  507math(Flags, tratio(A, _Df), Flags, A).
  508math(Flags, chi2ratio(A, _Df), Flags, A).
  509math(Flags, zratio(A), Flags, A).
  510math(Flags, prob(A), Flags, A).
  511math(Flags, perc(A), Flags, A).
  512math(Flags, natural(A), Flags, A).
  513math(Flags, pm(A, B), Flags, '+-'(A, B)).
  514math(Flags, paired_ci(D, S, N, Alpha), Flags, '+-'(D, fun(sub('T', 1-Alpha/2), (N-1, '_', "df")) * dfrac(S, sqrt(N)))).
  515
  516math(Flags, pvalue(A), Flags, p < 0.001) :-
  517    number(A),
  518    A < 0.001.
  519
  520math(Flags, pvalue(A), Flags, p = round3(A)) :-
  521    number(A),
  522    A < 0.10.
  523
  524math(Flags, pvalue(A), Flags, p = round2(A)) :-
  525    number(A).
  526
  527math(Flags, pvalue(A), Flags, A).
  528
  529math(Flags, fratio(A), Flags, A).
  530math(Flags, confint(A, _Digits), Flags, A).
  531
  532math(Flags, quote(A), Flags, A).
  533
  534example :- 
  535    example(cancel(red, atom('X'))).
  536    
  537example :- 
  538    example(paren([paren(red(x)), green(paren(y))])).
  539    
  540example :- 
  541    example(underbrace(s, list('', (string("instead of"), punct(' '), sigma)))).
  542
  543%
  544% Mistakes
  545%
  546erroneous(left_landed(Err, A), Errors) :-
  547    !, erroneous(A, T),
  548    Errors = [Err | T].
  549
  550erroneous(right_landed(Err, A), Errors) :-
  551    !, erroneous(A, T),
  552    Errors = [Err | T].
  553
  554erroneous(omit_left(Err, A), Errors) :-
  555    !, erroneous(A, T),
  556    Errors = [Err | T].
  557
  558erroneous(omit_right(Err, A), Errors) :-
  559    !, erroneous(A, T),
  560    Errors = [Err | T].
  561
  562erroneous(skip(Err, _Fn, A), Errors) :-
  563    !, erroneous(A, T),
  564    Errors = [Err | T].
  565
  566erroneous(buggy(Fb, A), Errors) :-
  567    !, compound_name_arguments(Fb, Err, _),
  568    erroneous(A, T),
  569    Errors = [Err | T].
  570
  571erroneous(instead_of(Err, Instead, Of), Errors) :-
  572    !, erroneous(Instead, I),
  573    erroneous(Of, O),
  574    append([Err | I], O, Errors).
  575
  576erroneous(instead_of(Err, Instead, _Instead, Of, _Of), Errors) :-
  577    !, erroneous(Instead, I),
  578    erroneous(Of, O),
  579    append([Err | I], O, Errors).
  580
  581erroneous(add(Err, A), Errors) :-
  582    !, erroneous(A, E),
  583    Errors = [Err | E].
  584
  585erroneous(omit(Err, A), Errors) :-
  586    !, erroneous(A, E),
  587    Errors = [Err | E].
  588
  589erroneous(color(Err, A), Errors) :-
  590    atom(Err),
  591    !, erroneous(A, E),
  592    Errors = [Err | E].
  593    
  594erroneous(A, Errors) :-
  595    compound(A),
  596    !, compound_name_arguments(A, _, Args),
  597    maplist(erroneous, Args, Errs),
  598    append(Errs, Errors).
  599
  600erroneous(_, []).
  601
  602fix(Flags, Err) :-
  603    member(fix(Err), Flags).
  604
  605fix(Flags, _) :-
  606    member(fix(all), Flags).
  607
  608highlight(Flags, Err) :-
  609    member(highlight(Err), Flags).
  610
  611highlight(Flags, _) :-
  612    member(highlight(all), Flags).
  613
  614show(Flags, Err) :-
  615    member(show(Err), Flags).
  616
  617show(Flags, _) :-
  618    member(show(all), Flags).
  619
  620correct(Flags, Err) :-
  621    member(correct(Err), Flags).
  622
  623correct(Flags, _) :-
  624    member(correct(all), Flags).
  625
  626math(Flags, expert(_Feedback, A), Flags, A).
  627math(Flags, buggy(_Feedback, A), Flags, A).
  628
  629paren(Flags, error(Err, Mode, A), P) :-
  630    C =.. [Err, Mode],
  631    paren([C | Flags], A, P).
  632
  633prec(Flags, error(Err, Mode, A), P) :-
  634    C =.. [Err, Mode],
  635    precedence([C | Flags], A, P).
  636
  637ml(Flags, error(Err, Mode, A), M) :-
  638    C =.. [Err, Mode],
  639    ml([C | Flags], A, M).
  640
  641paren(Flags, error(Err, Mode, A), P) :-
  642    C =.. [Err, Mode],
  643    paren([C | Flags], A, P).
  644
  645prec(Flags, error(Err, Mode, A), P) :-
  646    C =.. [Err, Mode],
  647    precedence([C | Flags], A, P).
  648
  649% No more errors within protect
  650ml(Flags, protect(X), M) :-
  651    !, ml(Flags, X, M).
  652
  653paren(Flags, protect(X), P) :-
  654    paren(Flags, X, P).
  655
  656prec(Flags, protect(X), P) :-
  657    precedence(Flags, X, P).
  658
  659% A instead of B
  660ml(Flags, instead_of(Err, Instead, _), M) :-
  661    show(Flags, Err),
  662    !, ml(Flags, color_or_box(Err, Instead), M).
  663
  664paren(Flags, instead_of(Err, Instead, _), P) :-
  665    show(Flags, Err),
  666    paren(Flags, Instead, P).
  667
  668prec(Flags, instead_of(Err, Instead, _), P) :-
  669    show(Flags, Err),
  670    precedence(Flags, Instead, P).
  671
  672ml(Flags, instead_of(Err, _, Of), M) :-
  673    fix(Flags, Err),
  674    !, ml(Flags, color_or_box(Err, Of), M).
  675
  676paren(Flags, instead_of(Err, _, Of), P) :-
  677    fix(Flags, Err),
  678    paren(Flags, Of, P).
  679
  680prec(Flags, instead_of(Err, _, Of), P) :-
  681    fix(Flags, Err),
  682    precedence(Flags, Of, P).
  683
  684ml(Flags, instead_of(Err, _, Of), M) :-
  685    correct(Flags, Err),
  686    !, ml(Flags, Of, M).
  687
  688paren(Flags, instead_of(Err, _, Of), P) :-
  689    correct(Flags, Err),
  690    paren(Flags, Of, P).
  691
  692prec(Flags, instead_of(Err, _, Of), P) :-
  693    correct(Flags, Err),
  694    precedence(Flags, Of, P).
  695
  696% ml(Flags, instead_of(Err, Instead, Of), M) :-
  697%     highlight(Flags, Err),
  698%     ml(Flags, underbrace(Instead, (string("instead of"), punct(' '), Of)), M).
  699
  700ml(Flags, instead_of(Err, Instead, Of), M) :-
  701    highlight(Flags, Err),
  702    !, ml(Flags, Instead, MInstead),
  703    % Fix errors in Of
  704    ml([fix(all) | Flags], (string("instead of"), punct(' '), Of), MOf),
  705    M = munder([accentunder(false)], [munder([accentunder(false)], [MInstead, mo([stretchy(true), overflow(scale)], &('UnderBrace'))]), MOf]).
  706
  707paren(Flags, instead_of(Err, Instead, _), P) :-
  708    highlight(Flags, Err),
  709    paren(Flags, Instead, P).
  710
  711prec(Flags, instead_of(Err, Instead, _), P) :-
  712    highlight(Flags, Err),
  713    precedence(Flags, Instead, P).
  714
  715% A instead of B
  716ml(Flags, instead_of(Err, Instead, _, _, _), M) :-
  717    show(Flags, Err),
  718    !, ml(Flags, color_or_box(Err, Instead), M).
  719
  720paren(Flags, instead_of(Err, Instead, _, _, _), P) :-
  721    show(Flags, Err),
  722    paren(Flags, Instead, P).
  723
  724prec(Flags, instead_of(Err, Instead, _, _, _), P) :-
  725    show(Flags, Err),
  726    precedence(Flags, Instead, P).
  727
  728ml(Flags, instead_of(Err, _, _, _, Of), M) :-
  729    fix(Flags, Err),
  730    !, ml(Flags, color_or_box(Err, Of), M).
  731
  732ml(Flags, instead_of(Err, _, _, Of, _), M) :-
  733    fix(Flags, Err),
  734    !, ml(Flags, color_or_box(Err, Of), M).
  735
  736paren(Flags, instead_of(Err, _, _, Of, _), P) :-
  737    fix(Flags, Err),
  738    paren(Flags, Of, P).
  739
  740prec(Flags, instead_of(Err, _, _, Of, _), P) :-
  741    fix(Flags, Err),
  742    precedence(Flags, Of, P).
  743
  744ml(Flags, instead_of(Err, _, _, Of, _), M) :-
  745    correct(Flags, Err),
  746    !, ml(Flags, Of, M).
  747
  748paren(Flags, instead_of(Err, _, _, Of, _), P) :-
  749    correct(Flags, Err),
  750    paren(Flags, Of, P).
  751
  752prec(Flags, instead_of(Err, _, _, Of, _), P) :-
  753    correct(Flags, Err),
  754    precedence(Flags, Of, P).
  755
  756ml(Flags, underbrace(A, Under),
  757    munder([accentunder(false)], [munder([accentunder(false)], [X, mo([stretchy(true), overflow(scale)], &('UnderBrace'))]), Y])) :-
  758    ml(Flags, A, X),
  759    ml(Flags, Under, Y).
  760
  761ml(Flags, instead_of(Err, Instead, Instead, _Of, Of), M) :-
  762    highlight(Flags, Err),
  763    !, ml(Flags, Instead, MInstead),
  764    % Fix errors in Of
  765    ml([fix(all) | Flags], (string("instead of"), punct(' '), Of), MOf),
  766    M = munder([accentunder(false)], [munder(accentunder(false), [MInstead, mo([stretchy(true), overflow(scale)], &('UnderBrace'))]), MOf]).
  767
  768ml(Flags, instead_of(Err, I, Instead, _Of, Of), M) :-
  769    highlight(Flags, Err),
  770    !, ml(Flags, I, MI),
  771    % Fix errors in Of
  772    ml([fix(all) | Flags], (Instead, punct(' '), string("instead of"), punct(' '), Of), MOf),
  773    M = munder([accentunder(false)], [munder([accentunder(false)], [MI, mo([stretchy(true), overflow(scale)], &('UnderBrace'))]), MOf]).
  774
  775
  776paren(Flags, instead_of(Err, Instead, _, _, _), P) :-
  777    highlight(Flags, Err),
  778    paren(Flags, Instead, P).
  779
  780prec(Flags, instead_of(Err, Instead, _, _, _), P) :-
  781    highlight(Flags, Err),
  782    precedence(Flags, Instead, P).
  783
  784% Omit element in list
  785ml(Flags, omit(Err, Elem), M) :-
  786    highlight(Flags, Err),
  787    ml(Flags, underbrace(Elem, '_', string("omitted")), M).
  788
  789ml(Flags, omit(Err, Elem), M) :-
  790    show(Flags, Err),
  791    ml(Flags, cancel(Err, Elem), M).
  792
  793ml(Flags, omit(Err, Elem), M) :-
  794    fix(Flags, Err),
  795    ml(Flags, color(Err, Elem), M).
  796
  797ml(Flags, omit(Err, Elem), M) :-
  798    correct(Flags, Err),
  799    ml(Flags, Elem, M).
  800
  801paren(Flags, omit(_Err, Elem), P) :-
  802    paren(Flags, Elem, P).
  803
  804% Skip function
  805ml(Flags, skip(Err, Fn, Elem), M) :-
  806    highlight(Flags, Err),
  807    Expr =.. [Fn, phantom(x)],
  808    ml(Flags, underbrace(Elem, (Expr, '_', string("omitted"))), M).
  809
  810ml(Flags, skip(Err, _Fn, Elem), M) :-
  811    show(Flags, Err),
  812    ml(Flags, color_or_box(Err, Elem), M).
  813
  814ml(Flags, skip(Err, Fn, Elem), M) :-
  815    fix(Flags, Err),
  816    Expr =.. [Fn, black(Elem)],
  817    ml(Flags, color_or_box(Err, Expr), M).
  818
  819ml(Flags, skip(Err, Fn, Elem), M) :-
  820    correct(Flags, Err),
  821    Expr =.. [Fn, Elem],
  822    ml(Flags, Expr, M).
  823
  824paren(Flags, skip(_Err, Fn, Elem), P) :-
  825    Expr =.. [Fn, Elem],
  826    paren(Flags, Expr, P).
  827
  828prec(Flags, skip(_Err, Fn, Elem), P) :-
  829    Expr =.. [Fn, Elem],
  830    precedence(Flags, Expr, P).
  831
  832% Add element to list
  833ml(Flags, add(Err, Elem), M) :-
  834    highlight(Flags, Err),
  835    ml(Flags, underbrace(Elem, string("added")), M).
  836
  837ml(Flags, add(Err, Elem), M) :-
  838    show(Flags, Err),
  839    ml(Flags, color(Err, Elem), M).
  840
  841ml(Flags, add(Err, Elem), M) :-
  842    fix(Flags, Err),
  843    ml(Flags, cancel(Err, Elem), M).
  844
  845ml(Flags, add(Err, Elem), M) :-
  846    correct(Flags, Err),
  847    ml(Flags, cancel(Err, Elem), M).
  848
  849paren(Flags, add(_Err, Elem), P) :-
  850    paren(Flags, Elem, P).
  851
  852prec(Flags, add(_Err, Elem), P) :-
  853    precedence(Flags, Elem, P).
  854
  855% Left part omitted
  856ml(Flags, omit_left(Err, Expr), M) :-
  857    highlight(Flags, Err),
  858    compound_name_arguments(Expr, Op, [L, R]),
  859    ml(Flags, (underbrace((L, ' ', Op), string("omitted")), ' ', R), M).
  860
  861ml(Flags, omit_left(Err, Expr), M) :-
  862    show(Flags, Err),
  863    compound_name_arguments(Expr, Op, [L, R]),
  864    ml(Flags, (cancel(Err, (L, ' ', Op)), ' ', R), M).
  865
  866ml(Flags, omit_left(Err, Expr), M) :-
  867    fix(Flags, Err),
  868    compound_name_arguments(Expr, Op, [L, R]),
  869    ml(Flags, (color(Err, (L, ' ', Op)), ' ', R), M).
  870
  871ml(Flags, omit_left(Err, Expr), M) :-
  872    correct(Flags, Err),
  873    ml(Flags, Expr, M).
  874
  875paren(Flags, omit_left(_Err, Expr), P) :-
  876    paren(Flags, Expr, P).
  877
  878ml(Flags, omit_right(Err, Expr), M) :-
  879    highlight(Flags, Err),
  880    compound_name_arguments(Expr, Op, [L, R]),
  881    ml(Flags, (L, underbrace((Op, ' ', R), string("omitted"))), M).
  882
  883ml(Flags, omit_right(Err, Expr), M) :-
  884    show(Flags, Err),
  885    compound_name_arguments(Expr, Op, [L, R]),
  886    ml(Flags, (L, ' ', cancel(Err, (Op, ' ', R))), M).
  887
  888ml(Flags, omit_right(Err, Expr), M) :-
  889    fix(Flags, Err),
  890    compound_name_arguments(Expr, Op, [L, R]),
  891    ml(Flags, (L, ' ', color(Err, (Op, ' ', R))), M).
  892
  893ml(Flags, omit_right(Err, Expr), M) :-
  894    correct(Flags, Err),
  895    ml(Flags, Expr, M).
  896
  897paren(Flags, omit_right(_Err, Expr), P) :-
  898    paren(Flags, Expr, P).
  899
  900ml(Flags, left_landed(Err, Expr), M) :-
  901    highlight(Flags, Err),
  902    precedence(Flags, Expr, _-Prec),
  903    compound_name_arguments(Expr, Op, [L, R]),
  904    ml(Flags, (color(Err, roundedbox(black((L, Op)))), operator(Prec, fy, '', R)), M).
  905
  906%ml(Flags, left_landed(Err, Expr), M) :-
  907%    show(Flags, Err),
  908%    precedence(Flags, Expr, _-Prec),
  909%    compound_name_arguments(Expr, Op, [L, R]),
  910%    ml(Flags, (color_or_box(Err, (L, Op)), operator(Prec, fy, '', R)), M).
  911
  912ml(Flags, left_landed(Err, Expr), M) :-
  913    show(Flags, Err),
  914    precedence(Flags, Expr, _-Prec),
  915    compound_name_arguments(Expr, Op, [L, R]),
  916    erroneous((L, Op), [_ | _]), % expression has error -> box
  917    !, ml(Flags, (color_or_box(Err, (L, Op)), operator(Prec, fy, '', R)), M).
  918
  919ml(Flags, left_landed(Err, Expr), M) :-
  920    show(Flags, Err),
  921    compound_name_arguments(Expr, Op, [L, R]),
  922    compound_name_arguments(New, Op, [L, black(R)]),
  923    ml(Flags, color(Err, New), M).
  924
  925ml(Flags, left_landed(Err, Expr), M) :-
  926    fix(Flags, Err),
  927    compound_name_arguments(Expr, _, [_, R]),
  928    ml(Flags, R, M).
  929
  930ml(Flags, left_landed(Err, Expr), M) :-
  931    correct(Flags, Err),
  932    compound_name_arguments(Expr, _, [_, R]),
  933    ml(Flags, R, M).
  934
  935paren(Flags, left_landed(_Err, Expr), P) :-
  936    paren(Flags, Expr, P).
  937
  938prec(Flags, left_landed(_Err, Expr), Prec) :-
  939    precedence(Flags, Expr, Prec).
  940
  941ml(Flags, right_landed(Err, Expr), M) :-
  942    highlight(Flags, Err),
  943    precedence(Flags, Expr, _-Prec),
  944    compound_name_arguments(Expr, Op, [L, R]),
  945    ml(Flags, (operator(Prec, yf, '', L), color(Err, roundedbox(black((Op, R))))), M).
  946
  947ml(Flags, right_landed(Err, Expr), M) :-
  948    show(Flags, Err),
  949    precedence(Flags, Expr, _-Prec),
  950    compound_name_arguments(Expr, Op, [L, R]),
  951    ml(Flags, (operator(Prec, yf, '', L), color_or_box(Err, operator(Prec, yfx, Op, '', R))), M).
  952
  953ml(Flags, right_landed(Err, Expr), M) :-
  954    fix(Flags, Err),
  955    compound_name_arguments(Expr, _Op, [L, _R]),
  956    ml(Flags, L, M).
  957
  958ml(Flags, right_landed(Err, Expr), M) :-
  959    correct(Flags, Err),
  960    compound_name_arguments(Expr, _Op, [L, _R]),
  961    ml(Flags, L, M).
  962
  963paren(Flags, right_landed(_Err, Expr), P) :-
  964    paren(Flags, Expr, P).
  965
  966prec(Flags, right_landed(_Err, Expr), Prec) :-
  967    precedence(Flags, Expr, Prec).
  968
  969ml(Flags, left_elsewhere(Err, Expr), M) :-
  970    highlight(Flags, Err),
  971    compound_name_arguments(Expr, Op, [L, R]),
  972    ml(Flags, (color(Err, roundedbox(strike(black((L, Op))))), R), M).
  973
  974ml(Flags, left_elsewhere(Err, Expr), M) :-
  975    show(Flags, Err),
  976    compound_name_arguments(Expr, _Op, [_L, R]),
  977    ml(Flags, R, M).
  978
  979ml(Flags, left_elsewhere(Err, Expr), M) :-
  980    fix(Flags, Err),
  981    compound_name_arguments(Expr, Op, [L, R]),
  982    ml(Flags, (color_or_box(Err, (L, Op)), R), M).
  983
  984ml(Flags, left_elsewhere(Err, Expr), M) :-
  985    correct(Flags, Err),
  986    ml(Flags, Expr, M).
  987
  988paren(Flags, left_elsewhere(Err, Expr), P) :-
  989    show(Flags, Err),
  990    !, compound_name_arguments(Expr, _Op, [_L, R]),
  991    paren(Flags, R, P).
  992
  993paren(Flags, left_elsewhere(_Err, Expr), P) :-
  994    paren(Flags, Expr, P).
  995
  996prec(Flags, left_elsewhere(Err, Expr), Prec) :-
  997    show(Flags, Err),
  998    compound_name_arguments(Expr, _Op, [_L, R]),
  999    precedence(Flags, R, Prec).
 1000
 1001ml(Flags, right_elsewhere(Err, Expr), M) :-
 1002    highlight(Flags, Err),
 1003    compound_name_arguments(Expr, Op, [L, R]),
 1004    ml(Flags, (L, color(Err, roundedbox(strike(black((Op, R)))))), M).
 1005
 1006ml(Flags, right_elsewhere(Err, Expr), M) :-
 1007    show(Flags, Err),
 1008    compound_name_arguments(Expr, _Op, [L, _R]),
 1009    ml(Flags, L, M).
 1010
 1011ml(Flags, right_elsewhere(Err, Expr), M) :-
 1012    fix(Flags, Err),
 1013    compound_name_arguments(Expr, Op, [L, R]),
 1014    ml(Flags, (L, color_or_box(Err, (Op, R))), M).
 1015
 1016ml(Flags, right_elsewhere(Err, Expr), M) :-
 1017    correct(Flags, Err),
 1018    ml(Flags, Expr, M).
 1019
 1020paren(Flags, right_elsewhere(Err, Expr), P) :-
 1021    show(Flags, Err),
 1022    !, compound_name_arguments(Expr, _Op, [L, _R]),
 1023    paren(Flags, L, P).
 1024
 1025paren(Flags, right_elsewhere(_Err, Expr), P) :-
 1026        paren(Flags, Expr, P).
 1027
 1028prec(Flags, right_elsewhere(Err, Expr), Prec) :-
 1029    show(Flags, Err),
 1030    compound_name_arguments(Expr, _Op, [L, _R]),
 1031    precedence(Flags, L, Prec).
 1032
 1033% Rounding errors
 1034math(Flags, dec(X, _D), Flags, X).
 1035
 1036example :- example([highlight(err1)], instead_of(err1, sigma, sigma, s)).
 1037example :- example([fix(err1)], instead_of(err1, sigma, sigma, s)).
 1038example :- example([show(err1)], instead_of(err1, sigma, sigma, s)).
 1039example :- example([correct(err1)], instead_of(err1, sigma, sigma, s)).
 1040
 1041% t-distribution
 1042math(Flags, tt(T, DF), Flags, fun(atom('P'), (abs(atom('T')) >= T ; [DF, punct('_'), string("df")]))).
 1043math(Flags, ut(T, DF), Flags, fun(atom('P'), (atom('T') >= T ; [DF, punct('_'), string("df")]))).
 1044math(Flags, 2 * pt(T, DF, 'lower.tail'='FALSE'), Flags, tt(T, DF)).
 1045math(Flags, pt(T, DF), Flags, fun(atom('P'), (atom('T') =< T ; [DF, punct('_'), string("df")]))).
 1046math(Flags, pt(T, DF, 'lower.tail'='FALSE'), Flags, ut(T, DF)).
 1047math(Flags, qt(P, DF), Flags, fun(subsup('T', "df"=DF, -1), P)).
 1048
 1049%
 1050% Units
 1051%
 1052is_unit(Flags, A) :-
 1053    unit(Flags, A, _, _).
 1054
 1055unit(_, A, Sep, M) :-
 1056    unit(A, Sep, M).
 1057
 1058unit('%', '', "%").
 1059unit('kg', punct('_'), "kg").
 1060
 1061ml(Flags, A, mrow([X, Sp, Unit])) :-
 1062    compound(A),
 1063    compound_name_arguments(A, U, [Num]),
 1064    is_unit(Flags, U),
 1065    unit(Flags, U, Sep, Unit),
 1066    ml(Flags, Num, X),
 1067    ml(Flags, Sep, Sp).
 1068
 1069math(Flags, P '%', Flags, (P, "%")).
 1070
 1071example :- example(10 '%').
 1072example :- example('100%'(0.1)).
 1073example :- example(kg(5)).
 1074
 1075%
 1076% Operators
 1077%
 1078ml(Flags, '100%'(A), X) :-
 1079    select_option(mult(M), Flags, New, 1),
 1080    _100M is 100 * M,
 1081    ml([mult(_100M) | New], round0(A) '%', X).
 1082
 1083paren(Flags, '100%'(A), P) :-
 1084    paren(Flags, A, P).
 1085
 1086prec(Flags, '100%'(A), atomic-P) :-
 1087    precedence(Flags, a*A, _-P).
 1088
 1089ml(Flags, sup(Sub, C), M) :-
 1090    precedence(Flags, Sub, sub-_),
 1091    member(color(Col), Flags),
 1092    !, ml([replace(sub(A, B), subsup(A, B, color(Col, C))) | Flags], Sub, M).
 1093
 1094ml(Flags, sup(Sub, C), M) :-
 1095    precedence(Flags, Sub, sub-_),
 1096    !, ml([replace(sub(A, B), subsup(A, B, C)) | Flags], Sub, M).
 1097
 1098paren(Flags, sup(Sub, C), P) :-
 1099    precedence(Flags, Sub, sub-_),
 1100    !, paren([replace(sub(A, B), subsup(A, B, C)) | Flags], Sub, P).
 1101
 1102prec(Flags, sup(Sub, C), P) :-
 1103    precedence(Flags, Sub, sub-_),
 1104    !, precedence([replace(sub(A, B), subsup(A, B, C)) | Flags], Sub, P).
 1105
 1106ml(Flags, sub(Sup, C), M) :-
 1107    precedence(Flags, Sup, sup-_),
 1108    !, ml([replace(sup(A, B), subsup(A, C, B)) | Flags], Sup, M).
 1109
 1110paren(Flags, sub(Sup, C), P) :-
 1111    precedence(Flags, Sup, sup-_),
 1112    !, paren([replace(sup(A, B), subsup(A, C, B)) | Flags], Sup, P).
 1113
 1114prec(Flags, sub(Sup, C), P) :-
 1115    precedence(Flags, Sup, sup-_),
 1116    !, precedence([replace(sup(A, B), subsup(A, C, B)) | Flags], Sup, P).
 1117
 1118ml(Flags, subsup(A, B, C), msubsup([X, Y, Z])) :-
 1119    precedence(Flags, subsup(A, B, C), _-P),
 1120    precedence(Flags, A, _-Inner),
 1121    ( P =< Inner
 1122      -> ml(Flags, paren(A), X)
 1123      ; ml(Flags, A, X)
 1124    ), ml(Flags, B, Y),
 1125    ml(Flags, C, Z).
 1126
 1127paren(Flags, subsup(A, _, _), P) :-
 1128    paren(Flags, A, P).
 1129
 1130prec(Flags, subsup(X, _, Z), P) :-
 1131    precedence(Flags, X^Z, P).
 1132
 1133math(Flags, A '_' B, Flags, sub(A, B)).
 1134
 1135ml(Flags, sub(A, B), M) :-
 1136    select_option(replace(sub(A, B), subsup(A, B, C)), Flags, New),
 1137    !, ml(New, subsup(A, B, C), M).
 1138
 1139paren(Flags, sub(A, B), P) :-
 1140    select_option(replace(sub(A, B), subsup(A, B, C)), Flags, New),
 1141    !, paren(New, subsup(A, B, C), P).
 1142
 1143prec(Flags, sub(A, B), P) :-
 1144    select_option(replace(sub(A, B), subsup(A, B, C)), Flags, New),
 1145    !, precedence(New, subsup(A, B, C), P).
 1146
 1147ml(Flags, sub(A, B), msub([X, Y])) :-
 1148    precedence(Flags, sub(A, B), _-P),
 1149    precedence(Flags, A, _-Inner),
 1150    ( P < Inner
 1151      -> ml(Flags, paren(A), X)
 1152      ; ml(Flags, A, X)
 1153    ), ml(Flags, B, Y).
 1154
 1155paren(Flags, sub(A, _), P) :-
 1156    paren(Flags, A, P).
 1157
 1158prec(Flags, sub(A, _), sub-P) :-
 1159    precedence(Flags, A, _-P).
 1160
 1161math(Flags, A^B, Flags, sup(A, B)).
 1162
 1163% experimental: sin^2 x for simple x
 1164ml(Flags, sup(Sin, X), M) :-
 1165    precedence(Flags, Sin, trig-_),
 1166    paren(Flags, X, 0),
 1167    precedence(Flags, X, _-0),
 1168    !, ml([replace(Sin^X, Sin)], Sin, M).
 1169
 1170ml(Flags, sup(A, B), M) :-
 1171    select_option(replace(sup(A, B), subsup(A, C, B)), Flags, New),
 1172    !, ml(New, subsup(A, C, B), M).
 1173
 1174paren(Flags, sup(A, B), P) :-
 1175    select_option(replace(sup(A, B), subsup(A, C, B)), Flags, New),
 1176    !, paren(New, subsup(A, C, B), P).
 1177
 1178prec(Flags, sup(A, B), P) :-
 1179    select_option(replace(sup(A, B), subsup(A, C, B)), Flags, New),
 1180    !, precedence(New, subsup(A, C, B), P).
 1181
 1182ml(Flags, sup(A, B), msup([X, Y])) :-
 1183    precedence(Flags, sup(A, B), _-P),
 1184    precedence(Flags, A, _-Inner),
 1185    ( P =< Inner
 1186      -> ml(Flags, paren(A), X)
 1187      ; ml(Flags, A, X)
 1188    ), ml(Flags, B, Y).
 1189
 1190paren(Flags, sup(A, _), Paren) :-
 1191    current_op(Prec, xfy, ^),
 1192    precedence(Flags, A, _-P),
 1193    Prec > P,
 1194    paren(Flags, A, Paren).
 1195
 1196paren(Flags, sup(A, _), Paren) :-
 1197    current_op(Prec, xfy, ^),
 1198    precedence(Flags, A, _-P),
 1199    Prec =< P,
 1200    paren(Flags, A, Inner),
 1201    Paren is Inner + 1.
 1202
 1203prec(_, sup(_, _), sup-P) :-
 1204    current_op(Prec, xfy, ^),
 1205    P = Prec.
 1206
 1207% Omit multiplication sign in simple products
 1208math(Flags, A * B, Flags, M) :-
 1209    current_op(Mult, yfx, *),
 1210    precedence(Flags, A, OpA-PrecA),
 1211    dif(OpA, frac),
 1212    dif(OpA, dfrac),
 1213    dif(OpA, /),
 1214    dif(OpA, fun),
 1215    PrecA =< Mult,
 1216    paren(Flags, A, 0),
 1217    precedence(Flags, B, OpB-PrecB),
 1218    dif(OpB, frac),
 1219    dif(OpB, dfrac),
 1220    dif(OpB, /),
 1221    dif(OpB, fun),
 1222    PrecB =< Mult,
 1223    paren(Flags, B, 0),
 1224    !, M = A invisible_times B.
 1225
 1226% Use plus as default separator for lists right to ~
 1227math(Flags, Dependent ~ Predictors, [sep-(+) | Flags], operator(Prec, xfy, ~, Dependent, Predictors)) :-
 1228    current_op(P, xfy, ','),
 1229    precedence(Flags, Predictors, list-P),
 1230    current_op(Prec, xfy, ~).
 1231
 1232% Negative sign has same precedence as binary minus
 1233math(Flags, -A, Flags, operator(P, fx, -, A)) :-
 1234    precedence(Flags, a-b, _-P).
 1235
 1236% Prefix and postfix operators (e.g., factorial)
 1237math(Flags, Comp, Flags, operator(Prec, Fix, Op, A)) :-
 1238    compound(Comp),
 1239    compound_name_arguments(Comp, Op, [A]),
 1240    current_op(P, Fix, Op), Prec = P,
 1241    member(Fix, [xf, yf, fx, fy]).
 1242
 1243ml(Flags, operator(P, fx, Op, A), mrow([F, X])) :-
 1244    precedence(Flags, A, _-Inner),
 1245    ( P =< Inner
 1246      -> ml(Flags, paren(A), X)
 1247      ; ml(Flags, A, X)
 1248    ), ml(Flags, op(Op), F).
 1249
 1250ml(Flags, operator(P, fy, Op, A), mrow([F, Y])) :-
 1251    precedence(Flags, A, _-Inner),
 1252    ( P < Inner
 1253      -> ml(Flags, paren(A), Y)
 1254      ; ml(Flags, A, Y)
 1255    ), ml(Flags, op(Op), F).
 1256
 1257ml(Flags, operator(P, xf, Op, A), mrow([X, F])) :-
 1258    precedence(Flags, A, _-Inner),
 1259    ( P =< Inner
 1260      -> ml(Flags, paren(A), X)
 1261      ; ml(Flags, A, X)
 1262    ), ml(Flags, op(Op), F).
 1263
 1264ml(Flags, operator(P, yf, Op, A), mrow([Y, F])) :-
 1265    precedence(Flags, A, _-Inner),
 1266    ( P < Inner
 1267      -> ml(Flags, paren(A), Y)
 1268      ; ml(Flags, A, Y)
 1269    ), ml(Flags, op(Op), F).
 1270
 1271paren(Flags, operator(Prec, Fix, _, A), Paren) :-
 1272    member(Fix, [xf, fx]),
 1273    paren(Flags, A, P),
 1274    precedence(Flags, A, _-Inner),
 1275    ( Prec =< Inner
 1276      -> Paren is P + 1
 1277      ; Paren = P
 1278    ).
 1279
 1280paren(Flags, operator(Prec, Fix, _, A), Paren) :-
 1281    member(Fix, [yf, fy]),
 1282    paren(Flags, A, P),
 1283    precedence(Flags, A, _-Inner),
 1284    ( Prec < Inner
 1285      -> Paren is P + 1
 1286      ; Paren = P
 1287    ).
 1288
 1289prec(_, operator(P, _, Op, _), Op-P).
 1290
 1291% Avoid unnecessary parentheses right to + in 1 + (2 - 3)
 1292math(Flags, A + B, Flags, operator(P, yfy, +, A, B)) :-
 1293    current_op(P, yfx, +).
 1294
 1295math(Flags, A * B, Flags, operator(P, yfy, *, A, B)) :-
 1296    current_op(P, yfx, *).
 1297
 1298math(Flags, A invisible_times B, Flags, operator(P, yfy, invisible_times, A, B)) :-
 1299    current_op(P, yfx, *).
 1300
 1301math(Flags, A : B, Flags, operator(P, yfy, :, A, B)) :-
 1302    current_op(P, xfy, :).
 1303
 1304math(Flags, A = B, Flags, operator(P, yfy, =, A, B)) :-
 1305    current_op(P, xfx, =).
 1306
 1307% General binary operators
 1308math(Flags, Comp, Flags, operator(Prec, Fix, Op, A, B)) :-
 1309    compound(Comp),
 1310    compound_name_arguments(Comp, Op, [A, B]),
 1311    current_op(P, Fix, Op), Prec = P,
 1312    member(Fix, [xfx, yfx, xfy]).
 1313
 1314ml(Flags, operator(P, xfx, Op, A, B), mrow([X, F, Y])) :-
 1315    precedence(Flags, A, _-PrecA),
 1316    ( P =< PrecA
 1317      -> ml(Flags, paren(A), X)
 1318      ; ml(Flags, A, X)
 1319    ), precedence(Flags, B, _-PrecB),
 1320    ( P =< PrecB
 1321      -> ml(Flags, paren(B), Y)
 1322      ; ml(Flags, B, Y)
 1323    ), ml(Flags, op(Op), F).
 1324
 1325ml(Flags, operator(P, xfy, Op, A, B), mrow([X, F, Y])) :-
 1326    precedence(Flags, A, _-PrecA),
 1327    ( P =< PrecA
 1328      -> ml(Flags, paren(A), X)
 1329      ; ml(Flags, A, X)
 1330    ), precedence(Flags, B, _-PrecB),
 1331    ( P < PrecB
 1332      -> ml(Flags, paren(B), Y)
 1333      ; ml(Flags, B, Y)
 1334    ), ml(Flags, op(Op), F).
 1335
 1336% yfy avoids parentheses around 1 + (2 + 3)
 1337ml(Flags, operator(P, yfy, Op, A, B), mrow([Y, F, X])) :-
 1338    precedence(Flags, A, _-PrecA),
 1339    ( P < PrecA
 1340      -> ml(Flags, paren(A), Y)
 1341      ; ml(Flags, A, Y)
 1342    ), precedence(Flags, B, _-PrecB),
 1343    ( P < PrecB
 1344      -> ml(Flags, paren(B), X)
 1345      ; ml(Flags, B, X)
 1346    ), ml(Flags, op(Op), F).
 1347
 1348ml(Flags, operator(P, yfx, Op, A, B), mrow([Y, F, X])) :-
 1349    precedence(Flags, A, _-PrecA),
 1350    ( P < PrecA
 1351      -> ml(Flags, paren(A), Y)
 1352      ; ml(Flags, A, Y)
 1353    ), precedence(Flags, B, _-PrecB),
 1354    ( P =< PrecB
 1355      -> ml(Flags, paren(B), X)
 1356      ; ml(Flags, B, X)
 1357    ), ml(Flags, op(Op), F).
 1358
 1359paren(Flags, operator(Prec, xfx, _, A, B), P) :-
 1360    paren(Flags, A, PA),
 1361    precedence(Flags, A, _-PrecA),
 1362    ( Prec =< PrecA
 1363      -> ParenA is PA + 1
 1364      ; ParenA = PA
 1365    ), paren(Flags, B, PB),
 1366    precedence(Flags, B, _-PrecB),
 1367    ( Prec =< PrecB
 1368      -> ParenB is PB + 1
 1369      ; ParenB = PB
 1370    ), P is max(ParenA, ParenB).
 1371
 1372paren(Flags, operator(Prec, yfx, _, A, B), P) :-
 1373    paren(Flags, A, PA),
 1374    precedence(Flags, A, _-PrecA),
 1375    ( Prec < PrecA
 1376      -> ParenA is PA + 1
 1377      ; ParenA = PA
 1378    ), paren(Flags, B, PB),
 1379    precedence(Flags, B, _-PrecB),
 1380    ( Prec =< PrecB
 1381      -> ParenB is PB + 1
 1382      ; ParenB = PB
 1383    ), P is max(ParenA, ParenB).
 1384
 1385paren(Flags, operator(Prec, xfy, _, A, B), P) :-
 1386    paren(Flags, A, PA),
 1387    precedence(Flags, A, _-PrecA),
 1388    ( Prec =< PrecA
 1389      -> ParenA is PA + 1
 1390      ; ParenA = PA
 1391    ), paren(Flags, B, PB),
 1392    precedence(Flags, B, _-PrecB),
 1393    ( Prec < PrecB
 1394      -> ParenB is PB + 1
 1395      ; ParenB = PB
 1396    ), P is max(ParenA, ParenB).
 1397
 1398paren(Flags, operator(Prec, yfy, _, A, B), P) :-
 1399    paren(Flags, A, PA),
 1400    precedence(Flags, A, _-PrecA),
 1401    ( Prec =< PrecA
 1402      -> ParenA is PA + 1
 1403      ; ParenA = PA
 1404    ), paren(Flags, B, PB),
 1405    precedence(Flags, B, _-PrecB),
 1406    ( Prec =< PrecB
 1407      -> ParenB is PB + 1
 1408      ; ParenB = PB
 1409    ), P is max(ParenA, ParenB).
 1410
 1411prec(_, operator(P, _, Op, _, _), Op-P).
 1412
 1413example :- example(a^3 + 3*a^2*b + 3*a*b^2 + b^3).
 1414example :- example(a^b).
 1415example :- example((s!)!).
 1416example :- example(a + b + c).
 1417example :- example(a + (b + c)).
 1418example :- example(a - b - c).
 1419example :- example(a - (b - c)).
 1420example :- example((a + b) * (a - b) = a^two - b^two).
 1421
 1422%
 1423% Numbers
 1424%
 1425is_positive(Flags, A) :-
 1426    positive(Flags, A, _).
 1427
 1428positive(Flags, A, X) :-
 1429    number(A), A >= 0,
 1430    select_option(mult(M), Flags, New),
 1431    !, AM is A*M,
 1432    ml(New, AM, X).
 1433
 1434positive(Flags, A, mn(N)) :-
 1435    number(A),
 1436    A >= 0,
 1437    option(round(3), Flags),
 1438    !, format(atom(N), '~3f', A).
 1439
 1440positive(Flags, A, mn(N)) :-
 1441    number(A),
 1442    A >= 0,
 1443    option(round(2), Flags),
 1444    !, format(atom(N), '~2f', A).
 1445
 1446positive(Flags, A, mn(N)) :-
 1447    number(A),
 1448    A >= 0,
 1449    option(round(1), Flags),
 1450    !, format(atom(N), '~1f', A).
 1451
 1452positive(Flags, A, mn(N)) :-
 1453    number(A),
 1454    A >= 0,
 1455    option(round(0), Flags),
 1456    !, format(atom(N), '~0f', A).
 1457
 1458positive(Flags, A, mn(N)) :-
 1459    number(A),
 1460    A >= 0,
 1461    option(round(g), Flags),
 1462    !, format(atom(N), '~g', A).
 1463
 1464positive(_, A, mn(A)) :-
 1465    number(A),
 1466    A >= 0.
 1467
 1468positive(Flags, A, X) :-
 1469    string(A),
 1470    number_string(N, A),
 1471    positive(Flags, N, X).
 1472
 1473ml(Flags, A, M) :-
 1474    is_positive(Flags, A),
 1475    positive(Flags, A, M).
 1476
 1477paren(Flags, A, 0) :-
 1478    is_positive(Flags, A).
 1479
 1480is_negative(Flags, A) :-
 1481    negative(Flags, A, _).
 1482
 1483negative(Flags, A, X) :-
 1484    number(A),
 1485    A < 0,
 1486    P is abs(A),
 1487    ml(Flags, -P, X).
 1488
 1489negative(Flags, A, X) :-
 1490    string(A),
 1491    number_string(N, A),
 1492    negative(Flags, N, X).
 1493
 1494ml(Flags, A, M) :-
 1495    is_negative(Flags, A),
 1496    negative(Flags, A, M).
 1497
 1498paren(Flags, A, 0) :-
 1499    is_negative(Flags, A).
 1500
 1501prec(Flags, A, P) :-
 1502    is_negative(Flags, A),
 1503    precedence(Flags, -A, P).
 1504
 1505% Force rendering string as number
 1506ml(_, quantity(S), M) :-
 1507    string(S),
 1508    quantity(Q, Options, S),
 1509    !, quantity_mathml(Q, Options, M).
 1510
 1511paren(_Flags, quantity(S), P) :-
 1512    string(S),
 1513    quantity(Q, Options, S),
 1514    !, quantity_paren(Q, Options, P).
 1515
 1516prec(_Flags, quantity(S), P) :-
 1517    string(S),
 1518    quantity(Q, Options, S),
 1519    !, quantity_prec(Q, Options, P).
 1520
 1521ml(_, quantity(Q, Options), M) :-
 1522    quantity_mathml(Q, Options, Mm),
 1523    !, M = Mm.
 1524
 1525paren(_Flags, quantity(Q, Options), P) :-
 1526    quantity_paren(Q, Options, P).
 1527
 1528prec(_Flags, quantity(Q, Options), P) :-
 1529    quantity_prec(Q, Options, P).
 1530
 1531ml(Flags, round(A), M) :-
 1532    ml([round(g) | Flags], A, M).
 1533
 1534paren(Flags, round(A), P) :-
 1535    paren(Flags, A, P).
 1536
 1537ml(Flags, round0(A), M) :-
 1538    ml([round(0) | Flags], A, M).
 1539
 1540paren(Flags, round0(A), P) :-
 1541    paren(Flags, A, P).
 1542
 1543ml(Flags, round1(A), M) :-
 1544    ml([round(1) | Flags], A, M).
 1545
 1546paren(Flags, round1(A), P) :-
 1547    paren(Flags, A, P).
 1548
 1549ml(Flags, round2(A), M) :-
 1550    ml([round(2) | Flags], A, M).
 1551
 1552paren(Flags, round2(A), P) :-
 1553    paren(Flags, A, P).
 1554
 1555ml(Flags, round3(A), M) :-
 1556    ml([round(3) | Flags], A, M).
 1557
 1558paren(Flags, round3(A), P) :-
 1559    paren(Flags, A, P).
 1560
 1561example :- example(5^2).
 1562example :- example((-5)^(-2)).
 1563example :- example((5!)!).
 1564example :- example(1 + 2 + (-3)).
 1565example :- example(1 + (-2 + 3)).
 1566example :- example(1 - (-2) - 3).
 1567example :- example(1 - ((-2) - 3)).
 1568example :- example((a + b) * (a - b) = a^2 - b^2).
 1569
 1570%
 1571% Fractions
 1572%
 1573ml(Flags, frac(A, B), mfrac([X, Y])) :-
 1574    ml(Flags, A, X),
 1575    ml(Flags, B, Y).
 1576
 1577paren(_, frac(_, _), 0).
 1578
 1579prec(Flags, frac(A, B), frac-Prec) :-
 1580    precedence(Flags, A/B, _-P),
 1581    Prec is P - 1.
 1582
 1583% Large fraction
 1584ml(Flags, dfrac(A, B), mstyle(displaystyle(true), X)) :-
 1585    ml(Flags, frac(A, B), X).
 1586
 1587paren(Flags, dfrac(A, B), P) :-
 1588    paren(Flags, frac(A, B), P).
 1589
 1590prec(Flags, dfrac(A, B), P) :-
 1591    precedence(Flags, frac(A, B), P).
 1592
 1593ml(Flags, choose(A, B),
 1594        mrow([mo('('), mfrac(linethickness(0), [X, Y]), mo(')')])) :-
 1595    ml(Flags, A, X),
 1596    ml(Flags, B, Y).
 1597
 1598paren(_, choose(_, _), 1).
 1599
 1600prec(Flags, choose(A, B), paren-P) :-
 1601    precedence(Flags, A^B, _-P).
 1602
 1603ml(Flags, dchoose(A, B),
 1604       mrow([mo('('), mfrac(mstyle([displaystyle(true), linethickness(0)]),
 1605                            [X, Y]), mo(')')])) :-
 1606    ml(Flags, A, X),
 1607    ml(Flags, B, Y).
 1608
 1609paren(Flags, dchoose(A, B), P) :-
 1610    paren(Flags, choose(A, B), P).
 1611
 1612prec(Flags, dchoose(A, B), P) :-
 1613    precedence(Flags, choose(A, B), P).
 1614
 1615example :- example(frac(1.5, 2)^2).
 1616example :- example(frac(small, small) = dfrac(large, large)).
 1617
 1618%
 1619% Trigonometric functions
 1620%
 1621math(Flags, sin(A), Flags, trig(sin, A)).
 1622math(Flags, cos(A), Flags, trig(cos, A)).
 1623math(Flags, tan(A), Flags, trig(tan, A)).
 1624
 1625ml(Flags, trig(Fun, Arg), M) :-
 1626    paren(Flags, Arg, 0),
 1627    precedence(Flags, Arg, _-0),
 1628    !, ( select_option(replace(Sin^N, Sin), Flags, New)
 1629      -> ml(New, Fun^N, F)
 1630      ; ml(Flags, Fun, F)
 1631    ), ml(Flags, Arg, X),
 1632    M = mrow([F, mo(&(af)), X]).
 1633
 1634ml(Flags, trig(Fun, Arg), mrow([F, mo(&(af)), X])) :-
 1635    ( select_option(replace(Sin^N, Sin), Flags, New)
 1636      -> ml(New, Fun^N, F)
 1637      ; ml(Flags, Fun, F)
 1638    ), ml(Flags, paren(Arg), X).
 1639
 1640paren(Flags, trig(_, Arg), P) :-
 1641    precedence(Flags, Arg, _-0),
 1642    !, paren(Flags, Arg, P).
 1643
 1644paren(Flags, trig(_, Arg), P) :-
 1645    paren(Flags, Arg, Paren),
 1646    P is Paren + 1.
 1647
 1648prec(Flags, trig(Fun, Arg), trig-P) :-
 1649    precedence(Flags, Fun*Arg, _-Prec),
 1650    P is Prec - 1.
 1651
 1652example :- example(sin(pi)).
 1653example :- example(sin(pi/2)).
 1654example :- example(sin(pi)^2).
 1655example :- example(sin(pi)*cos(pi)).
 1656example :- example(sin(a + b)).
 1657example :- example(sin(a!)^2).
 1658
 1659%
 1660% Special functions
 1661%
 1662math(Flags, baseline_fratio(_, _Primary, _Covariates, _Strata, _Other, _Interactions, _Exclude, Therapy), Flags, sub(atom('F'), Therapy)).
 1663
 1664math(Flags, ancova_f(_, _Primary, _Covariates, _Strata, _Other, _Interactions, _Exclude, Therapy), Flags, sub(atom('F'), Therapy)).
 1665math(Flags, ancova_ff(_, _Primary, _Covariates, _Strata, _Other, _Interactions, _Exclude, Therapy), Flags, sub(atom('F'), Therapy)).
 1666math(Flags, ancova_fff(_, _Primary, _Covariates, _Strata, _Other, _Interactions, _Exclude, Therapy), Flags, sub(atom('F'), Therapy)).
 1667math(Flags, ancova_ffff(_, _Primary, _Covariates, _Strata, _Other, _Interactions, _Exclude, Therapy), Flags, sub(atom('F'), Therapy)).
 1668math(Flags, ancova_fffff(_, _Primary, _Covariates, _Strata, _Other, _Interactions, _Exclude, Therapy), Flags, sub(atom('F'), Therapy)).
 1669math(Flags, ancova_ffffff(_, _Primary, _Covariates, _Strata, _Other, _Interactions, _Exclude, Therapy), Flags, sub(atom('F'), Therapy)).
 1670denot(Flags, ancova_ffffff(_, Primary, Covariates, Strata, Other, Interactions, Exclude, Therapy), W) :-
 1671    !, denot(Flags, Primary, T1),
 1672    denot(Flags, Covariates, T2),
 1673    denot(Flags, Strata, T3),
 1674    denot(Flags, Other, T4),
 1675    denot(Flags, Interactions, T5),
 1676    denot(Flags, Exclude, T6),
 1677    denot(Flags, Therapy, T7),
 1678    append([T1, T2, T3, T4, T5, T6, T7], T),
 1679    W = [denoting(tilde(Primary, [Covariates, Strata, Other, Interactions, Exclude, Therapy]), "the statistical model") | T].
 1680
 1681ml(Flags, Tilde, M) :-
 1682    compound(Tilde),
 1683    compound_name_arguments(Tilde, tilde, [Dependent | Predictors]),
 1684    subtract(Predictors, [[]], NonEmpty),
 1685    !, ml([sep-(+) | Flags], Dependent ~ NonEmpty, M).
 1686
 1687paren(Flags, Tilde, P) :-
 1688    compound(Tilde),
 1689    compound_name_arguments(Tilde, tilde, [Dependent | Predictors]),
 1690    subtract(Predictors, [[]], NonEmpty),
 1691    !, paren(Flags, Dependent ~ NonEmpty, P).
 1692    
 1693math(Flags, lm(Model, _Data), Flags, Model).
 1694
 1695math(Flags, anova_f(_, Therapy), Flags, sub(atom('F'), Therapy)).
 1696
 1697math(Flags, paired_t(D, Mu, S, N),
 1698     Flags, fun((string("paired"), punct('_'), atom(t), string("-test")), [D, S; N, Mu])).
 1699
 1700math(Flags, groups_t(M_A, S_A, N_A, M_B, S_B, N_B),
 1701     Flags, fun((string("independent"), punct('_'), atom(t), string("-test")), [M_A, S_A, M_B, S_B; N_A, N_B])).
 1702
 1703math(Flags, var_pool(V_A, N_A, V_B, N_B), Flags, var_pool1(V_A, N_A, V_B, N_B)).
 1704math(Flags, var_pool1(V_A, N_A, V_B, N_B), Flags, var_pool2(V_A, N_A, V_B, N_B)).
 1705math(Flags, var_pool2(V_A, N, V_B, N), Flags, dfrac(V_A + V_B, 2)).
 1706math(Flags, var_pool2(V_A, N_A, V_B, N_B), Flags, dfrac((N_A-1)*V_A + (N_B-1)*V_B, N_A + N_B - 2)).
 1707
 1708math(Flags, p_pool(S_A, N_A, S_B, N_B), Flags, p_pool1(S_A, N_A, S_B, N_B)).
 1709math(Flags, p_pool1(S_A, N, S_B, N), Flags, dfrac(S_A + S_B, 2)).
 1710math(Flags, p_pool1(S_A, N_A, S_B, N_B), Flags, dfrac(S_A + S_B, N_A + N_B)).
 1711
 1712ml(Flags, sum(I, From, To, A), mrow([munderover([\['&sum;'], XFrom, XTo]), X])) :-
 1713    ml(Flags, I = From, XFrom),
 1714    ml(Flags, To, XTo),
 1715    ml(Flags, A, X).
 1716
 1717paren(Flags, sum(_, _, _, A), P) :-
 1718    paren(Flags, A, P).
 1719
 1720prec(Flags, sum(_, _, _, _), P) :-
 1721    precedence(Flags, x + y, P).
 1722
 1723ml(Flags, argmin(I, A), M) :-
 1724    ml(Flags, fun(under(string("argmin"), I), A), M).
 1725
 1726paren(Flags, argmin(_, A), P) :-
 1727    paren(Flags, A, P).
 1728
 1729prec(Flags, argmin(_, A), P) :-
 1730    precedence(Flags, x + A, P).
 1731
 1732ml(Flags, argmax(I, A), M) :-
 1733    ml(Flags, fun(under(string("argmax"), I), A), M).
 1734
 1735paren(Flags, argmax(_, A), P) :-
 1736    paren(Flags, A, P).
 1737
 1738prec(Flags, argmax(_, A), P) :-
 1739    precedence(Flags, x + A, P).
 1740
 1741ml(Flags, under(A, B), munder([X, Y])) :-
 1742    ml(Flags, A, X),
 1743    ml(Flags, B, Y).
 1744
 1745paren(Flags, under(A, _), P) :-
 1746    paren(Flags, A, P).
 1747
 1748prec(Flags, under(A, _), accent-P) :-
 1749    precedence(Flags, A, _-P).
 1750
 1751ml(Flags, sqrt(A), msqrt(X)) :-
 1752    ml(Flags, A, X).
 1753
 1754paren(_, sqrt(_), 0).
 1755
 1756prec(Flags, sqrt(_), P) :-
 1757    precedence(Flags, x^y, P).
 1758
 1759math(Flags, square(X), Flags, X^2).
 1760
 1761math(Flags, dbinom(K, N, P), Flags, fun(sub(atom('P'), string("Bi")), [atom('X') = K ; [N, P]])).
 1762math(Flags, pbinom(K, N, P), Flags, fun(sub(atom('P'), string("Bi")), [atom('X') =< K ; [N, P]])).
 1763math(Flags, ubinom(K, N, P), Flags, fun(sub(atom('P'), string("Bi")), [atom('X') >= K ; [N, P]])).
 1764
 1765math(Flags, instead_of(Code, pbinom(K, N, P), ubinom(K, N, P)),
 1766     Flags, fun(sub(atom('P'), string("Bi")), [instead_of(Code, atom('X') =< K, atom('X') >= K) ; [N, P]])).
 1767
 1768math(Flags, instead_of(Code, dbinom(K, N, P), ubinom(K, N, P)),
 1769     Flags, fun(sub(atom('P'), string("Bi")), [instead_of(Code, atom('X') = K, atom('X') >= K) ; [N, P]])).
 1770
 1771% Lower and upper critical value
 1772math(Flags, lower(Alpha), Flags, Alpha).
 1773math(Flags, upper(Alpha), Flags, 1 - Alpha).
 1774
 1775math(Flags, uqbinom(Tail, Dist, Alpha, N, P), Flags, fun(Tail, fun(sub('P', "Bi"), [Dist ; [N, P]]) =< Alpha)).
 1776math(Flags, pwbinom(_K, Dist, N, P), Flags, fun(sub('P', "Bi"), [Dist ; [N, P]])).
 1777
 1778math(Flags, tail("upper"), Flags, under("argmin", k)).
 1779math(Flags, tail("lower"), Flags, under("argmax", k)).
 1780
 1781math(Flags, dist("upper"), Flags, 'X' >= k).
 1782math(Flags, dist("lower"), Flags, 'X' =< k).
 1783math(Flags, dist("density"), Flags, 'X' = k).
 1784
 1785math(Flags, dist("upper", K), Flags, 'X' >= K).
 1786math(Flags, dist("lower", K), Flags, 'X' =< K).
 1787math(Flags, dist("density", K), Flags, 'X' = K).
 1788
 1789math(Flags, dist1(Dist), Flags, dist(Dist)).
 1790
 1791math(Flags, bernoulli(Succ, N, Pi), Flags, successes(Succ, Pi) * failures(N-Succ, Pi)).
 1792math(Flags, successes(Succ, Pi), Flags, Pi^Succ).
 1793math(Flags, failures(Fail, Pi), Flags, (1-Pi)^Fail).
 1794
 1795% General functions
 1796ml(Flags, fun(Name, Args), mrow([N, &(af), A])) :-
 1797    ml(Flags, Name, N),
 1798    ml(Flags, paren(Args), A).
 1799
 1800paren(Flags, fun(_, Args), P) :-
 1801    paren(Flags, paren(Args), P).
 1802
 1803prec(Flags, fun(_, _), fun-P) :-
 1804    precedence(Flags, x^y, _-P).
 1805
 1806example :- example(sqrt(2)).
 1807example :- example(sqrt(2)^2).
 1808example :- example(dbinom(k, n, pi)).
 1809example :- example(pbinom(k, n, pi)).
 1810example :- example(ubinom(k, n, pi)).
 1811example :- example(qbinom(alpha, n, pi)).
 1812example :- example(uqbinom(alpha, n, pi)).
 1813example :- example(dbinom(k, n, pi) =
 1814                   choose(n, k) * successes(n, pi) * failures(n-k, pi)).
 1815example :- example(pbinom(k, 'N', pi) =
 1816                   sum(i, k, 'N', choose('N', k) * dbinom(i, 'N', k))).
 1817example :- example(sum(i, k, 'N', i) + sum(i, k, 'N', i)).
 1818
 1819%
 1820% Normal distribution
 1821%
 1822math(Flags, pnorm(Z), Flags, fun('Phi', Z)).
 1823math(Flags, unorm(Z), Flags, 1 - fun('Phi', Z)).
 1824
 1825%
 1826% Abbreviations
 1827%
 1828math(Flags, denoting(A, X, _), Flags, color_or_box(Err, A)) :-
 1829    erroneous(X, [Err | _]).
 1830
 1831math(Flags, denoting(A, _, _), Flags, A).
 1832
 1833math(Flags, denoting(_, _), Flags, '').
 1834
 1835math(Flags, abbrev(A, _), Flags, A).
 1836
 1837% Collect abbreviations
 1838abbreviations(Flags, A, W) :-
 1839    denot(Flags, A, X),
 1840    sort(2, @<, X, W).
 1841
 1842denot(_, A, []) :-
 1843    atomic(A).
 1844
 1845denot(Flags, denoting(Abbrev, Expr, Desc), W) :-
 1846    !, denot(Flags, Expr, T),
 1847    W = [denoting(Abbrev = Expr, Desc) | T].
 1848
 1849denot(Flags, denoting(Expr, Desc), W) :-
 1850    !, denot(Flags, Expr, T),
 1851    W = [denoting(Expr, Desc) | T].
 1852
 1853% See compound below
 1854%
 1855% denot(Flags, instead_of(Err, A, Instead, Of), W) :-
 1856%     option(error(highlight), Flags, highlight),
 1857%     !, denot(Flags, A, X),
 1858%     denot(Flags, Instead, Y),
 1859%     denot(Flags, Of, Z),
 1860%     append([X, Y, Z], W).
 1861
 1862denot(Flags, instead_of(Err, Instead, _), W) :-
 1863    show(Flags, Err),
 1864    !, denot(Flags, Instead, W).
 1865
 1866denot(Flags, instead_of(Err, _, Of), W) :-
 1867    fix(Flags, Err),
 1868    !, denot(Flags, Of, W).
 1869
 1870denot(Flags, instead_of(Err, _, Of), W) :-
 1871    correct(Flags, Err),
 1872    !, denot(Flags, Of, W).
 1873
 1874denot(Flags, instead_of(Err, Instead, _, _, _), W) :-
 1875    show(Flags, Err),
 1876    !, denot(Flags, Instead, W).
 1877
 1878denot(Flags, instead_of(Err, _, _, Of, _), W) :-
 1879    fix(Flags, Err),
 1880    !, denot(Flags, Of, W).
 1881
 1882denot(Flags, instead_of(Err, _, _, Of, _), W) :-
 1883    correct(Flags, Err),
 1884    !, denot(Flags, Of, W).
 1885
 1886denot(Flags, [H | T], With) :-
 1887    !, maplist(denot(Flags), [H | T], List),
 1888    append(List, With).
 1889
 1890%denot(Flags, A, W) :-
 1891%    math(Flags, A, New, B),
 1892%    !, denot(New, B, W).
 1893
 1894denot(Flags, Comp, With) :-
 1895    compound(Comp),
 1896    compound_name_arguments(Comp, _, Args),
 1897    maplist(denot(Flags), Args, List),
 1898    append(List, With).
 1899
 1900% Render abbreviations
 1901denoting(Flags, A, Empty) :-
 1902    abbreviations(Flags, A, []),
 1903    !, Empty = [].
 1904
 1905denoting(Flags, A, [M]) :-
 1906    abbreviations(Flags, A, [denoting(Expr, Des)]),
 1907    !, ml(Flags, Expr, MExpr),
 1908    M = span(["with", &(nbsp), math(MExpr), " denoting ", Des, "."]).
 1909    
 1910denoting(Flags, A, [M | MT]) :-
 1911    abbreviations(Flags, A, [denoting(Expr, Des) | T]),
 1912    !, ml(Flags, Expr, MExpr),
 1913    M = span(["with", &(nbsp), math(MExpr), " denoting ", Des, ", "]),
 1914    and(Flags, T, MT).
 1915
 1916and(Flags, [denoting(Expr, Des)], M) :-
 1917    !, ml(Flags, Expr, MExpr),
 1918    M = [span(["and", &(nbsp), math(MExpr), " denoting ", Des, "."])].
 1919    
 1920and(Flags, [denoting(Expr, Des) | T], [M | MT]) :-
 1921    ml(Flags, Expr, MExpr),
 1922    M = span(["and", &(nbsp), math(MExpr), " denoting ", Des, ", "]),
 1923    and(Flags, T, MT)