Coverage for /usr/lib/python3/dist-packages/sympy/printing/mathml.py: 12%

1577 statements  

« prev     ^ index     » next       coverage.py v7.9.1, created at 2025-06-14 15:55 +0200

1""" 

2A MathML printer. 

3""" 

4 

5from __future__ import annotations 

6from typing import Any 

7 

8from sympy.core.mul import Mul 

9from sympy.core.singleton import S 

10from sympy.core.sorting import default_sort_key 

11from sympy.core.sympify import sympify 

12from sympy.printing.conventions import split_super_sub, requires_partial 

13from sympy.printing.precedence import \ 

14 precedence_traditional, PRECEDENCE, PRECEDENCE_TRADITIONAL 

15from sympy.printing.pretty.pretty_symbology import greek_unicode 

16from sympy.printing.printer import Printer, print_function 

17 

18from mpmath.libmp import prec_to_dps, repr_dps, to_str as mlib_to_str 

19 

20 

21class MathMLPrinterBase(Printer): 

22 """Contains common code required for MathMLContentPrinter and 

23 MathMLPresentationPrinter. 

24 """ 

25 

26 _default_settings: dict[str, Any] = { 

27 "order": None, 

28 "encoding": "utf-8", 

29 "fold_frac_powers": False, 

30 "fold_func_brackets": False, 

31 "fold_short_frac": None, 

32 "inv_trig_style": "abbreviated", 

33 "ln_notation": False, 

34 "long_frac_ratio": None, 

35 "mat_delim": "[", 

36 "mat_symbol_style": "plain", 

37 "mul_symbol": None, 

38 "root_notation": True, 

39 "symbol_names": {}, 

40 "mul_symbol_mathml_numbers": '·', 

41 } 

42 

43 def __init__(self, settings=None): 

44 Printer.__init__(self, settings) 

45 from xml.dom.minidom import Document, Text 

46 

47 self.dom = Document() 

48 

49 # Workaround to allow strings to remain unescaped 

50 # Based on 

51 # https://stackoverflow.com/questions/38015864/python-xml-dom-minidom-\ 

52 # please-dont-escape-my-strings/38041194 

53 class RawText(Text): 

54 def writexml(self, writer, indent='', addindent='', newl=''): 

55 if self.data: 

56 writer.write('{}{}{}'.format(indent, self.data, newl)) 

57 

58 def createRawTextNode(data): 

59 r = RawText() 

60 r.data = data 

61 r.ownerDocument = self.dom 

62 return r 

63 

64 self.dom.createTextNode = createRawTextNode 

65 

66 def doprint(self, expr): 

67 """ 

68 Prints the expression as MathML. 

69 """ 

70 mathML = Printer._print(self, expr) 

71 unistr = mathML.toxml() 

72 xmlbstr = unistr.encode('ascii', 'xmlcharrefreplace') 

73 res = xmlbstr.decode() 

74 return res 

75 

76 def apply_patch(self): 

77 # Applying the patch of xml.dom.minidom bug 

78 # Date: 2011-11-18 

79 # Description: http://ronrothman.com/public/leftbraned/xml-dom-minidom\ 

80 # -toprettyxml-and-silly-whitespace/#best-solution 

81 # Issue: https://bugs.python.org/issue4147 

82 # Patch: https://hg.python.org/cpython/rev/7262f8f276ff/ 

83 

84 from xml.dom.minidom import Element, Text, Node, _write_data 

85 

86 def writexml(self, writer, indent="", addindent="", newl=""): 

87 # indent = current indentation 

88 # addindent = indentation to add to higher levels 

89 # newl = newline string 

90 writer.write(indent + "<" + self.tagName) 

91 

92 attrs = self._get_attributes() 

93 a_names = list(attrs.keys()) 

94 a_names.sort() 

95 

96 for a_name in a_names: 

97 writer.write(" %s=\"" % a_name) 

98 _write_data(writer, attrs[a_name].value) 

99 writer.write("\"") 

100 if self.childNodes: 

101 writer.write(">") 

102 if (len(self.childNodes) == 1 and 

103 self.childNodes[0].nodeType == Node.TEXT_NODE): 

104 self.childNodes[0].writexml(writer, '', '', '') 

105 else: 

106 writer.write(newl) 

107 for node in self.childNodes: 

108 node.writexml( 

109 writer, indent + addindent, addindent, newl) 

110 writer.write(indent) 

111 writer.write("</%s>%s" % (self.tagName, newl)) 

112 else: 

113 writer.write("/>%s" % (newl)) 

114 self._Element_writexml_old = Element.writexml 

115 Element.writexml = writexml 

116 

117 def writexml(self, writer, indent="", addindent="", newl=""): 

118 _write_data(writer, "%s%s%s" % (indent, self.data, newl)) 

119 self._Text_writexml_old = Text.writexml 

120 Text.writexml = writexml 

121 

122 def restore_patch(self): 

123 from xml.dom.minidom import Element, Text 

124 Element.writexml = self._Element_writexml_old 

125 Text.writexml = self._Text_writexml_old 

126 

127 

128class MathMLContentPrinter(MathMLPrinterBase): 

129 """Prints an expression to the Content MathML markup language. 

130 

131 References: https://www.w3.org/TR/MathML2/chapter4.html 

132 """ 

133 printmethod = "_mathml_content" 

134 

135 def mathml_tag(self, e): 

136 """Returns the MathML tag for an expression.""" 

137 translate = { 

138 'Add': 'plus', 

139 'Mul': 'times', 

140 'Derivative': 'diff', 

141 'Number': 'cn', 

142 'int': 'cn', 

143 'Pow': 'power', 

144 'Max': 'max', 

145 'Min': 'min', 

146 'Abs': 'abs', 

147 'And': 'and', 

148 'Or': 'or', 

149 'Xor': 'xor', 

150 'Not': 'not', 

151 'Implies': 'implies', 

152 'Symbol': 'ci', 

153 'MatrixSymbol': 'ci', 

154 'RandomSymbol': 'ci', 

155 'Integral': 'int', 

156 'Sum': 'sum', 

157 'sin': 'sin', 

158 'cos': 'cos', 

159 'tan': 'tan', 

160 'cot': 'cot', 

161 'csc': 'csc', 

162 'sec': 'sec', 

163 'sinh': 'sinh', 

164 'cosh': 'cosh', 

165 'tanh': 'tanh', 

166 'coth': 'coth', 

167 'csch': 'csch', 

168 'sech': 'sech', 

169 'asin': 'arcsin', 

170 'asinh': 'arcsinh', 

171 'acos': 'arccos', 

172 'acosh': 'arccosh', 

173 'atan': 'arctan', 

174 'atanh': 'arctanh', 

175 'atan2': 'arctan', 

176 'acot': 'arccot', 

177 'acoth': 'arccoth', 

178 'asec': 'arcsec', 

179 'asech': 'arcsech', 

180 'acsc': 'arccsc', 

181 'acsch': 'arccsch', 

182 'log': 'ln', 

183 'Equality': 'eq', 

184 'Unequality': 'neq', 

185 'GreaterThan': 'geq', 

186 'LessThan': 'leq', 

187 'StrictGreaterThan': 'gt', 

188 'StrictLessThan': 'lt', 

189 'Union': 'union', 

190 'Intersection': 'intersect', 

191 } 

192 

193 for cls in e.__class__.__mro__: 

194 n = cls.__name__ 

195 if n in translate: 

196 return translate[n] 

197 # Not found in the MRO set 

198 n = e.__class__.__name__ 

199 return n.lower() 

200 

201 def _print_Mul(self, expr): 

202 

203 if expr.could_extract_minus_sign(): 

204 x = self.dom.createElement('apply') 

205 x.appendChild(self.dom.createElement('minus')) 

206 x.appendChild(self._print_Mul(-expr)) 

207 return x 

208 

209 from sympy.simplify import fraction 

210 numer, denom = fraction(expr) 

211 

212 if denom is not S.One: 

213 x = self.dom.createElement('apply') 

214 x.appendChild(self.dom.createElement('divide')) 

215 x.appendChild(self._print(numer)) 

216 x.appendChild(self._print(denom)) 

217 return x 

218 

219 coeff, terms = expr.as_coeff_mul() 

220 if coeff is S.One and len(terms) == 1: 

221 # XXX since the negative coefficient has been handled, I don't 

222 # think a coeff of 1 can remain 

223 return self._print(terms[0]) 

224 

225 if self.order != 'old': 

226 terms = Mul._from_args(terms).as_ordered_factors() 

227 

228 x = self.dom.createElement('apply') 

229 x.appendChild(self.dom.createElement('times')) 

230 if coeff != 1: 

231 x.appendChild(self._print(coeff)) 

232 for term in terms: 

233 x.appendChild(self._print(term)) 

234 return x 

235 

236 def _print_Add(self, expr, order=None): 

237 args = self._as_ordered_terms(expr, order=order) 

238 lastProcessed = self._print(args[0]) 

239 plusNodes = [] 

240 for arg in args[1:]: 

241 if arg.could_extract_minus_sign(): 

242 # use minus 

243 x = self.dom.createElement('apply') 

244 x.appendChild(self.dom.createElement('minus')) 

245 x.appendChild(lastProcessed) 

246 x.appendChild(self._print(-arg)) 

247 # invert expression since this is now minused 

248 lastProcessed = x 

249 if arg == args[-1]: 

250 plusNodes.append(lastProcessed) 

251 else: 

252 plusNodes.append(lastProcessed) 

253 lastProcessed = self._print(arg) 

254 if arg == args[-1]: 

255 plusNodes.append(self._print(arg)) 

256 if len(plusNodes) == 1: 

257 return lastProcessed 

258 x = self.dom.createElement('apply') 

259 x.appendChild(self.dom.createElement('plus')) 

260 while plusNodes: 

261 x.appendChild(plusNodes.pop(0)) 

262 return x 

263 

264 def _print_Piecewise(self, expr): 

265 if expr.args[-1].cond != True: 

266 # We need the last conditional to be a True, otherwise the resulting 

267 # function may not return a result. 

268 raise ValueError("All Piecewise expressions must contain an " 

269 "(expr, True) statement to be used as a default " 

270 "condition. Without one, the generated " 

271 "expression may not evaluate to anything under " 

272 "some condition.") 

273 root = self.dom.createElement('piecewise') 

274 for i, (e, c) in enumerate(expr.args): 

275 if i == len(expr.args) - 1 and c == True: 

276 piece = self.dom.createElement('otherwise') 

277 piece.appendChild(self._print(e)) 

278 else: 

279 piece = self.dom.createElement('piece') 

280 piece.appendChild(self._print(e)) 

281 piece.appendChild(self._print(c)) 

282 root.appendChild(piece) 

283 return root 

284 

285 def _print_MatrixBase(self, m): 

286 x = self.dom.createElement('matrix') 

287 for i in range(m.rows): 

288 x_r = self.dom.createElement('matrixrow') 

289 for j in range(m.cols): 

290 x_r.appendChild(self._print(m[i, j])) 

291 x.appendChild(x_r) 

292 return x 

293 

294 def _print_Rational(self, e): 

295 if e.q == 1: 

296 # don't divide 

297 x = self.dom.createElement('cn') 

298 x.appendChild(self.dom.createTextNode(str(e.p))) 

299 return x 

300 x = self.dom.createElement('apply') 

301 x.appendChild(self.dom.createElement('divide')) 

302 # numerator 

303 xnum = self.dom.createElement('cn') 

304 xnum.appendChild(self.dom.createTextNode(str(e.p))) 

305 # denominator 

306 xdenom = self.dom.createElement('cn') 

307 xdenom.appendChild(self.dom.createTextNode(str(e.q))) 

308 x.appendChild(xnum) 

309 x.appendChild(xdenom) 

310 return x 

311 

312 def _print_Limit(self, e): 

313 x = self.dom.createElement('apply') 

314 x.appendChild(self.dom.createElement(self.mathml_tag(e))) 

315 

316 x_1 = self.dom.createElement('bvar') 

317 x_2 = self.dom.createElement('lowlimit') 

318 x_1.appendChild(self._print(e.args[1])) 

319 x_2.appendChild(self._print(e.args[2])) 

320 

321 x.appendChild(x_1) 

322 x.appendChild(x_2) 

323 x.appendChild(self._print(e.args[0])) 

324 return x 

325 

326 def _print_ImaginaryUnit(self, e): 

327 return self.dom.createElement('imaginaryi') 

328 

329 def _print_EulerGamma(self, e): 

330 return self.dom.createElement('eulergamma') 

331 

332 def _print_GoldenRatio(self, e): 

333 """We use unicode #x3c6 for Greek letter phi as defined here 

334 https://www.w3.org/2003/entities/2007doc/isogrk1.html""" 

335 x = self.dom.createElement('cn') 

336 x.appendChild(self.dom.createTextNode("\N{GREEK SMALL LETTER PHI}")) 

337 return x 

338 

339 def _print_Exp1(self, e): 

340 return self.dom.createElement('exponentiale') 

341 

342 def _print_Pi(self, e): 

343 return self.dom.createElement('pi') 

344 

345 def _print_Infinity(self, e): 

346 return self.dom.createElement('infinity') 

347 

348 def _print_NaN(self, e): 

349 return self.dom.createElement('notanumber') 

350 

351 def _print_EmptySet(self, e): 

352 return self.dom.createElement('emptyset') 

353 

354 def _print_BooleanTrue(self, e): 

355 return self.dom.createElement('true') 

356 

357 def _print_BooleanFalse(self, e): 

358 return self.dom.createElement('false') 

359 

360 def _print_NegativeInfinity(self, e): 

361 x = self.dom.createElement('apply') 

362 x.appendChild(self.dom.createElement('minus')) 

363 x.appendChild(self.dom.createElement('infinity')) 

364 return x 

365 

366 def _print_Integral(self, e): 

367 def lime_recur(limits): 

368 x = self.dom.createElement('apply') 

369 x.appendChild(self.dom.createElement(self.mathml_tag(e))) 

370 bvar_elem = self.dom.createElement('bvar') 

371 bvar_elem.appendChild(self._print(limits[0][0])) 

372 x.appendChild(bvar_elem) 

373 

374 if len(limits[0]) == 3: 

375 low_elem = self.dom.createElement('lowlimit') 

376 low_elem.appendChild(self._print(limits[0][1])) 

377 x.appendChild(low_elem) 

378 up_elem = self.dom.createElement('uplimit') 

379 up_elem.appendChild(self._print(limits[0][2])) 

380 x.appendChild(up_elem) 

381 if len(limits[0]) == 2: 

382 up_elem = self.dom.createElement('uplimit') 

383 up_elem.appendChild(self._print(limits[0][1])) 

384 x.appendChild(up_elem) 

385 if len(limits) == 1: 

386 x.appendChild(self._print(e.function)) 

387 else: 

388 x.appendChild(lime_recur(limits[1:])) 

389 return x 

390 

391 limits = list(e.limits) 

392 limits.reverse() 

393 return lime_recur(limits) 

394 

395 def _print_Sum(self, e): 

396 # Printer can be shared because Sum and Integral have the 

397 # same internal representation. 

398 return self._print_Integral(e) 

399 

400 def _print_Symbol(self, sym): 

401 ci = self.dom.createElement(self.mathml_tag(sym)) 

402 

403 def join(items): 

404 if len(items) > 1: 

405 mrow = self.dom.createElement('mml:mrow') 

406 for i, item in enumerate(items): 

407 if i > 0: 

408 mo = self.dom.createElement('mml:mo') 

409 mo.appendChild(self.dom.createTextNode(" ")) 

410 mrow.appendChild(mo) 

411 mi = self.dom.createElement('mml:mi') 

412 mi.appendChild(self.dom.createTextNode(item)) 

413 mrow.appendChild(mi) 

414 return mrow 

415 else: 

416 mi = self.dom.createElement('mml:mi') 

417 mi.appendChild(self.dom.createTextNode(items[0])) 

418 return mi 

419 

420 # translate name, supers and subs to unicode characters 

421 def translate(s): 

422 if s in greek_unicode: 

423 return greek_unicode.get(s) 

424 else: 

425 return s 

426 

427 name, supers, subs = split_super_sub(sym.name) 

428 name = translate(name) 

429 supers = [translate(sup) for sup in supers] 

430 subs = [translate(sub) for sub in subs] 

431 

432 mname = self.dom.createElement('mml:mi') 

433 mname.appendChild(self.dom.createTextNode(name)) 

434 if not supers: 

435 if not subs: 

436 ci.appendChild(self.dom.createTextNode(name)) 

437 else: 

438 msub = self.dom.createElement('mml:msub') 

439 msub.appendChild(mname) 

440 msub.appendChild(join(subs)) 

441 ci.appendChild(msub) 

442 else: 

443 if not subs: 

444 msup = self.dom.createElement('mml:msup') 

445 msup.appendChild(mname) 

446 msup.appendChild(join(supers)) 

447 ci.appendChild(msup) 

448 else: 

449 msubsup = self.dom.createElement('mml:msubsup') 

450 msubsup.appendChild(mname) 

451 msubsup.appendChild(join(subs)) 

452 msubsup.appendChild(join(supers)) 

453 ci.appendChild(msubsup) 

454 return ci 

455 

456 _print_MatrixSymbol = _print_Symbol 

457 _print_RandomSymbol = _print_Symbol 

458 

459 def _print_Pow(self, e): 

460 # Here we use root instead of power if the exponent is the reciprocal 

461 # of an integer 

462 if (self._settings['root_notation'] and e.exp.is_Rational 

463 and e.exp.p == 1): 

464 x = self.dom.createElement('apply') 

465 x.appendChild(self.dom.createElement('root')) 

466 if e.exp.q != 2: 

467 xmldeg = self.dom.createElement('degree') 

468 xmlcn = self.dom.createElement('cn') 

469 xmlcn.appendChild(self.dom.createTextNode(str(e.exp.q))) 

470 xmldeg.appendChild(xmlcn) 

471 x.appendChild(xmldeg) 

472 x.appendChild(self._print(e.base)) 

473 return x 

474 

475 x = self.dom.createElement('apply') 

476 x_1 = self.dom.createElement(self.mathml_tag(e)) 

477 x.appendChild(x_1) 

478 x.appendChild(self._print(e.base)) 

479 x.appendChild(self._print(e.exp)) 

480 return x 

481 

482 def _print_Number(self, e): 

483 x = self.dom.createElement(self.mathml_tag(e)) 

484 x.appendChild(self.dom.createTextNode(str(e))) 

485 return x 

486 

487 def _print_Float(self, e): 

488 x = self.dom.createElement(self.mathml_tag(e)) 

489 repr_e = mlib_to_str(e._mpf_, repr_dps(e._prec)) 

490 x.appendChild(self.dom.createTextNode(repr_e)) 

491 return x 

492 

493 def _print_Derivative(self, e): 

494 x = self.dom.createElement('apply') 

495 diff_symbol = self.mathml_tag(e) 

496 if requires_partial(e.expr): 

497 diff_symbol = 'partialdiff' 

498 x.appendChild(self.dom.createElement(diff_symbol)) 

499 x_1 = self.dom.createElement('bvar') 

500 

501 for sym, times in reversed(e.variable_count): 

502 x_1.appendChild(self._print(sym)) 

503 if times > 1: 

504 degree = self.dom.createElement('degree') 

505 degree.appendChild(self._print(sympify(times))) 

506 x_1.appendChild(degree) 

507 

508 x.appendChild(x_1) 

509 x.appendChild(self._print(e.expr)) 

510 return x 

511 

512 def _print_Function(self, e): 

513 x = self.dom.createElement("apply") 

514 x.appendChild(self.dom.createElement(self.mathml_tag(e))) 

515 for arg in e.args: 

516 x.appendChild(self._print(arg)) 

517 return x 

518 

519 def _print_Basic(self, e): 

520 x = self.dom.createElement(self.mathml_tag(e)) 

521 for arg in e.args: 

522 x.appendChild(self._print(arg)) 

523 return x 

524 

525 def _print_AssocOp(self, e): 

526 x = self.dom.createElement('apply') 

527 x_1 = self.dom.createElement(self.mathml_tag(e)) 

528 x.appendChild(x_1) 

529 for arg in e.args: 

530 x.appendChild(self._print(arg)) 

531 return x 

532 

533 def _print_Relational(self, e): 

534 x = self.dom.createElement('apply') 

535 x.appendChild(self.dom.createElement(self.mathml_tag(e))) 

536 x.appendChild(self._print(e.lhs)) 

537 x.appendChild(self._print(e.rhs)) 

538 return x 

539 

540 def _print_list(self, seq): 

541 """MathML reference for the <list> element: 

542 https://www.w3.org/TR/MathML2/chapter4.html#contm.list""" 

543 dom_element = self.dom.createElement('list') 

544 for item in seq: 

545 dom_element.appendChild(self._print(item)) 

546 return dom_element 

547 

548 def _print_int(self, p): 

549 dom_element = self.dom.createElement(self.mathml_tag(p)) 

550 dom_element.appendChild(self.dom.createTextNode(str(p))) 

551 return dom_element 

552 

553 _print_Implies = _print_AssocOp 

554 _print_Not = _print_AssocOp 

555 _print_Xor = _print_AssocOp 

556 

557 def _print_FiniteSet(self, e): 

558 x = self.dom.createElement('set') 

559 for arg in e.args: 

560 x.appendChild(self._print(arg)) 

561 return x 

562 

563 def _print_Complement(self, e): 

564 x = self.dom.createElement('apply') 

565 x.appendChild(self.dom.createElement('setdiff')) 

566 for arg in e.args: 

567 x.appendChild(self._print(arg)) 

568 return x 

569 

570 def _print_ProductSet(self, e): 

571 x = self.dom.createElement('apply') 

572 x.appendChild(self.dom.createElement('cartesianproduct')) 

573 for arg in e.args: 

574 x.appendChild(self._print(arg)) 

575 return x 

576 

577 # XXX Symmetric difference is not supported for MathML content printers. 

578 

579 

580class MathMLPresentationPrinter(MathMLPrinterBase): 

581 """Prints an expression to the Presentation MathML markup language. 

582 

583 References: https://www.w3.org/TR/MathML2/chapter3.html 

584 """ 

585 printmethod = "_mathml_presentation" 

586 

587 def mathml_tag(self, e): 

588 """Returns the MathML tag for an expression.""" 

589 translate = { 

590 'Number': 'mn', 

591 'Limit': '&#x2192;', 

592 'Derivative': '&dd;', 

593 'int': 'mn', 

594 'Symbol': 'mi', 

595 'Integral': '&int;', 

596 'Sum': '&#x2211;', 

597 'sin': 'sin', 

598 'cos': 'cos', 

599 'tan': 'tan', 

600 'cot': 'cot', 

601 'asin': 'arcsin', 

602 'asinh': 'arcsinh', 

603 'acos': 'arccos', 

604 'acosh': 'arccosh', 

605 'atan': 'arctan', 

606 'atanh': 'arctanh', 

607 'acot': 'arccot', 

608 'atan2': 'arctan', 

609 'Equality': '=', 

610 'Unequality': '&#x2260;', 

611 'GreaterThan': '&#x2265;', 

612 'LessThan': '&#x2264;', 

613 'StrictGreaterThan': '>', 

614 'StrictLessThan': '<', 

615 'lerchphi': '&#x3A6;', 

616 'zeta': '&#x3B6;', 

617 'dirichlet_eta': '&#x3B7;', 

618 'elliptic_k': '&#x39A;', 

619 'lowergamma': '&#x3B3;', 

620 'uppergamma': '&#x393;', 

621 'gamma': '&#x393;', 

622 'totient': '&#x3D5;', 

623 'reduced_totient': '&#x3BB;', 

624 'primenu': '&#x3BD;', 

625 'primeomega': '&#x3A9;', 

626 'fresnels': 'S', 

627 'fresnelc': 'C', 

628 'LambertW': 'W', 

629 'Heaviside': '&#x398;', 

630 'BooleanTrue': 'True', 

631 'BooleanFalse': 'False', 

632 'NoneType': 'None', 

633 'mathieus': 'S', 

634 'mathieuc': 'C', 

635 'mathieusprime': 'S&#x2032;', 

636 'mathieucprime': 'C&#x2032;', 

637 } 

638 

639 def mul_symbol_selection(): 

640 if (self._settings["mul_symbol"] is None or 

641 self._settings["mul_symbol"] == 'None'): 

642 return '&InvisibleTimes;' 

643 elif self._settings["mul_symbol"] == 'times': 

644 return '&#xD7;' 

645 elif self._settings["mul_symbol"] == 'dot': 

646 return '&#xB7;' 

647 elif self._settings["mul_symbol"] == 'ldot': 

648 return '&#x2024;' 

649 elif not isinstance(self._settings["mul_symbol"], str): 

650 raise TypeError 

651 else: 

652 return self._settings["mul_symbol"] 

653 for cls in e.__class__.__mro__: 

654 n = cls.__name__ 

655 if n in translate: 

656 return translate[n] 

657 # Not found in the MRO set 

658 if e.__class__.__name__ == "Mul": 

659 return mul_symbol_selection() 

660 n = e.__class__.__name__ 

661 return n.lower() 

662 

663 def parenthesize(self, item, level, strict=False): 

664 prec_val = precedence_traditional(item) 

665 if (prec_val < level) or ((not strict) and prec_val <= level): 

666 brac = self.dom.createElement('mfenced') 

667 brac.appendChild(self._print(item)) 

668 return brac 

669 else: 

670 return self._print(item) 

671 

672 def _print_Mul(self, expr): 

673 

674 def multiply(expr, mrow): 

675 from sympy.simplify import fraction 

676 numer, denom = fraction(expr) 

677 if denom is not S.One: 

678 frac = self.dom.createElement('mfrac') 

679 if self._settings["fold_short_frac"] and len(str(expr)) < 7: 

680 frac.setAttribute('bevelled', 'true') 

681 xnum = self._print(numer) 

682 xden = self._print(denom) 

683 frac.appendChild(xnum) 

684 frac.appendChild(xden) 

685 mrow.appendChild(frac) 

686 return mrow 

687 

688 coeff, terms = expr.as_coeff_mul() 

689 if coeff is S.One and len(terms) == 1: 

690 mrow.appendChild(self._print(terms[0])) 

691 return mrow 

692 if self.order != 'old': 

693 terms = Mul._from_args(terms).as_ordered_factors() 

694 

695 if coeff != 1: 

696 x = self._print(coeff) 

697 y = self.dom.createElement('mo') 

698 y.appendChild(self.dom.createTextNode(self.mathml_tag(expr))) 

699 mrow.appendChild(x) 

700 mrow.appendChild(y) 

701 for term in terms: 

702 mrow.appendChild(self.parenthesize(term, PRECEDENCE['Mul'])) 

703 if not term == terms[-1]: 

704 y = self.dom.createElement('mo') 

705 y.appendChild(self.dom.createTextNode(self.mathml_tag(expr))) 

706 mrow.appendChild(y) 

707 return mrow 

708 mrow = self.dom.createElement('mrow') 

709 if expr.could_extract_minus_sign(): 

710 x = self.dom.createElement('mo') 

711 x.appendChild(self.dom.createTextNode('-')) 

712 mrow.appendChild(x) 

713 mrow = multiply(-expr, mrow) 

714 else: 

715 mrow = multiply(expr, mrow) 

716 

717 return mrow 

718 

719 def _print_Add(self, expr, order=None): 

720 mrow = self.dom.createElement('mrow') 

721 args = self._as_ordered_terms(expr, order=order) 

722 mrow.appendChild(self._print(args[0])) 

723 for arg in args[1:]: 

724 if arg.could_extract_minus_sign(): 

725 # use minus 

726 x = self.dom.createElement('mo') 

727 x.appendChild(self.dom.createTextNode('-')) 

728 y = self._print(-arg) 

729 # invert expression since this is now minused 

730 else: 

731 x = self.dom.createElement('mo') 

732 x.appendChild(self.dom.createTextNode('+')) 

733 y = self._print(arg) 

734 mrow.appendChild(x) 

735 mrow.appendChild(y) 

736 

737 return mrow 

738 

739 def _print_MatrixBase(self, m): 

740 table = self.dom.createElement('mtable') 

741 for i in range(m.rows): 

742 x = self.dom.createElement('mtr') 

743 for j in range(m.cols): 

744 y = self.dom.createElement('mtd') 

745 y.appendChild(self._print(m[i, j])) 

746 x.appendChild(y) 

747 table.appendChild(x) 

748 if self._settings["mat_delim"] == '': 

749 return table 

750 brac = self.dom.createElement('mfenced') 

751 if self._settings["mat_delim"] == "[": 

752 brac.setAttribute('close', ']') 

753 brac.setAttribute('open', '[') 

754 brac.appendChild(table) 

755 return brac 

756 

757 def _get_printed_Rational(self, e, folded=None): 

758 if e.p < 0: 

759 p = -e.p 

760 else: 

761 p = e.p 

762 x = self.dom.createElement('mfrac') 

763 if folded or self._settings["fold_short_frac"]: 

764 x.setAttribute('bevelled', 'true') 

765 x.appendChild(self._print(p)) 

766 x.appendChild(self._print(e.q)) 

767 if e.p < 0: 

768 mrow = self.dom.createElement('mrow') 

769 mo = self.dom.createElement('mo') 

770 mo.appendChild(self.dom.createTextNode('-')) 

771 mrow.appendChild(mo) 

772 mrow.appendChild(x) 

773 return mrow 

774 else: 

775 return x 

776 

777 def _print_Rational(self, e): 

778 if e.q == 1: 

779 # don't divide 

780 return self._print(e.p) 

781 

782 return self._get_printed_Rational(e, self._settings["fold_short_frac"]) 

783 

784 def _print_Limit(self, e): 

785 mrow = self.dom.createElement('mrow') 

786 munder = self.dom.createElement('munder') 

787 mi = self.dom.createElement('mi') 

788 mi.appendChild(self.dom.createTextNode('lim')) 

789 

790 x = self.dom.createElement('mrow') 

791 x_1 = self._print(e.args[1]) 

792 arrow = self.dom.createElement('mo') 

793 arrow.appendChild(self.dom.createTextNode(self.mathml_tag(e))) 

794 x_2 = self._print(e.args[2]) 

795 x.appendChild(x_1) 

796 x.appendChild(arrow) 

797 x.appendChild(x_2) 

798 

799 munder.appendChild(mi) 

800 munder.appendChild(x) 

801 mrow.appendChild(munder) 

802 mrow.appendChild(self._print(e.args[0])) 

803 

804 return mrow 

805 

806 def _print_ImaginaryUnit(self, e): 

807 x = self.dom.createElement('mi') 

808 x.appendChild(self.dom.createTextNode('&ImaginaryI;')) 

809 return x 

810 

811 def _print_GoldenRatio(self, e): 

812 x = self.dom.createElement('mi') 

813 x.appendChild(self.dom.createTextNode('&#x3A6;')) 

814 return x 

815 

816 def _print_Exp1(self, e): 

817 x = self.dom.createElement('mi') 

818 x.appendChild(self.dom.createTextNode('&ExponentialE;')) 

819 return x 

820 

821 def _print_Pi(self, e): 

822 x = self.dom.createElement('mi') 

823 x.appendChild(self.dom.createTextNode('&pi;')) 

824 return x 

825 

826 def _print_Infinity(self, e): 

827 x = self.dom.createElement('mi') 

828 x.appendChild(self.dom.createTextNode('&#x221E;')) 

829 return x 

830 

831 def _print_NegativeInfinity(self, e): 

832 mrow = self.dom.createElement('mrow') 

833 y = self.dom.createElement('mo') 

834 y.appendChild(self.dom.createTextNode('-')) 

835 x = self._print_Infinity(e) 

836 mrow.appendChild(y) 

837 mrow.appendChild(x) 

838 return mrow 

839 

840 def _print_HBar(self, e): 

841 x = self.dom.createElement('mi') 

842 x.appendChild(self.dom.createTextNode('&#x210F;')) 

843 return x 

844 

845 def _print_EulerGamma(self, e): 

846 x = self.dom.createElement('mi') 

847 x.appendChild(self.dom.createTextNode('&#x3B3;')) 

848 return x 

849 

850 def _print_TribonacciConstant(self, e): 

851 x = self.dom.createElement('mi') 

852 x.appendChild(self.dom.createTextNode('TribonacciConstant')) 

853 return x 

854 

855 def _print_Dagger(self, e): 

856 msup = self.dom.createElement('msup') 

857 msup.appendChild(self._print(e.args[0])) 

858 msup.appendChild(self.dom.createTextNode('&#x2020;')) 

859 return msup 

860 

861 def _print_Contains(self, e): 

862 mrow = self.dom.createElement('mrow') 

863 mrow.appendChild(self._print(e.args[0])) 

864 mo = self.dom.createElement('mo') 

865 mo.appendChild(self.dom.createTextNode('&#x2208;')) 

866 mrow.appendChild(mo) 

867 mrow.appendChild(self._print(e.args[1])) 

868 return mrow 

869 

870 def _print_HilbertSpace(self, e): 

871 x = self.dom.createElement('mi') 

872 x.appendChild(self.dom.createTextNode('&#x210B;')) 

873 return x 

874 

875 def _print_ComplexSpace(self, e): 

876 msup = self.dom.createElement('msup') 

877 msup.appendChild(self.dom.createTextNode('&#x1D49E;')) 

878 msup.appendChild(self._print(e.args[0])) 

879 return msup 

880 

881 def _print_FockSpace(self, e): 

882 x = self.dom.createElement('mi') 

883 x.appendChild(self.dom.createTextNode('&#x2131;')) 

884 return x 

885 

886 

887 def _print_Integral(self, expr): 

888 intsymbols = {1: "&#x222B;", 2: "&#x222C;", 3: "&#x222D;"} 

889 

890 mrow = self.dom.createElement('mrow') 

891 if len(expr.limits) <= 3 and all(len(lim) == 1 for lim in expr.limits): 

892 # Only up to three-integral signs exists 

893 mo = self.dom.createElement('mo') 

894 mo.appendChild(self.dom.createTextNode(intsymbols[len(expr.limits)])) 

895 mrow.appendChild(mo) 

896 else: 

897 # Either more than three or limits provided 

898 for lim in reversed(expr.limits): 

899 mo = self.dom.createElement('mo') 

900 mo.appendChild(self.dom.createTextNode(intsymbols[1])) 

901 if len(lim) == 1: 

902 mrow.appendChild(mo) 

903 if len(lim) == 2: 

904 msup = self.dom.createElement('msup') 

905 msup.appendChild(mo) 

906 msup.appendChild(self._print(lim[1])) 

907 mrow.appendChild(msup) 

908 if len(lim) == 3: 

909 msubsup = self.dom.createElement('msubsup') 

910 msubsup.appendChild(mo) 

911 msubsup.appendChild(self._print(lim[1])) 

912 msubsup.appendChild(self._print(lim[2])) 

913 mrow.appendChild(msubsup) 

914 # print function 

915 mrow.appendChild(self.parenthesize(expr.function, PRECEDENCE["Mul"], 

916 strict=True)) 

917 # print integration variables 

918 for lim in reversed(expr.limits): 

919 d = self.dom.createElement('mo') 

920 d.appendChild(self.dom.createTextNode('&dd;')) 

921 mrow.appendChild(d) 

922 mrow.appendChild(self._print(lim[0])) 

923 return mrow 

924 

925 def _print_Sum(self, e): 

926 limits = list(e.limits) 

927 subsup = self.dom.createElement('munderover') 

928 low_elem = self._print(limits[0][1]) 

929 up_elem = self._print(limits[0][2]) 

930 summand = self.dom.createElement('mo') 

931 summand.appendChild(self.dom.createTextNode(self.mathml_tag(e))) 

932 

933 low = self.dom.createElement('mrow') 

934 var = self._print(limits[0][0]) 

935 equal = self.dom.createElement('mo') 

936 equal.appendChild(self.dom.createTextNode('=')) 

937 low.appendChild(var) 

938 low.appendChild(equal) 

939 low.appendChild(low_elem) 

940 

941 subsup.appendChild(summand) 

942 subsup.appendChild(low) 

943 subsup.appendChild(up_elem) 

944 

945 mrow = self.dom.createElement('mrow') 

946 mrow.appendChild(subsup) 

947 if len(str(e.function)) == 1: 

948 mrow.appendChild(self._print(e.function)) 

949 else: 

950 fence = self.dom.createElement('mfenced') 

951 fence.appendChild(self._print(e.function)) 

952 mrow.appendChild(fence) 

953 

954 return mrow 

955 

956 def _print_Symbol(self, sym, style='plain'): 

957 def join(items): 

958 if len(items) > 1: 

959 mrow = self.dom.createElement('mrow') 

960 for i, item in enumerate(items): 

961 if i > 0: 

962 mo = self.dom.createElement('mo') 

963 mo.appendChild(self.dom.createTextNode(" ")) 

964 mrow.appendChild(mo) 

965 mi = self.dom.createElement('mi') 

966 mi.appendChild(self.dom.createTextNode(item)) 

967 mrow.appendChild(mi) 

968 return mrow 

969 else: 

970 mi = self.dom.createElement('mi') 

971 mi.appendChild(self.dom.createTextNode(items[0])) 

972 return mi 

973 

974 # translate name, supers and subs to unicode characters 

975 def translate(s): 

976 if s in greek_unicode: 

977 return greek_unicode.get(s) 

978 else: 

979 return s 

980 

981 name, supers, subs = split_super_sub(sym.name) 

982 name = translate(name) 

983 supers = [translate(sup) for sup in supers] 

984 subs = [translate(sub) for sub in subs] 

985 

986 mname = self.dom.createElement('mi') 

987 mname.appendChild(self.dom.createTextNode(name)) 

988 if len(supers) == 0: 

989 if len(subs) == 0: 

990 x = mname 

991 else: 

992 x = self.dom.createElement('msub') 

993 x.appendChild(mname) 

994 x.appendChild(join(subs)) 

995 else: 

996 if len(subs) == 0: 

997 x = self.dom.createElement('msup') 

998 x.appendChild(mname) 

999 x.appendChild(join(supers)) 

1000 else: 

1001 x = self.dom.createElement('msubsup') 

1002 x.appendChild(mname) 

1003 x.appendChild(join(subs)) 

1004 x.appendChild(join(supers)) 

1005 # Set bold font? 

1006 if style == 'bold': 

1007 x.setAttribute('mathvariant', 'bold') 

1008 return x 

1009 

1010 def _print_MatrixSymbol(self, sym): 

1011 return self._print_Symbol(sym, 

1012 style=self._settings['mat_symbol_style']) 

1013 

1014 _print_RandomSymbol = _print_Symbol 

1015 

1016 def _print_conjugate(self, expr): 

1017 enc = self.dom.createElement('menclose') 

1018 enc.setAttribute('notation', 'top') 

1019 enc.appendChild(self._print(expr.args[0])) 

1020 return enc 

1021 

1022 def _print_operator_after(self, op, expr): 

1023 row = self.dom.createElement('mrow') 

1024 row.appendChild(self.parenthesize(expr, PRECEDENCE["Func"])) 

1025 mo = self.dom.createElement('mo') 

1026 mo.appendChild(self.dom.createTextNode(op)) 

1027 row.appendChild(mo) 

1028 return row 

1029 

1030 def _print_factorial(self, expr): 

1031 return self._print_operator_after('!', expr.args[0]) 

1032 

1033 def _print_factorial2(self, expr): 

1034 return self._print_operator_after('!!', expr.args[0]) 

1035 

1036 def _print_binomial(self, expr): 

1037 brac = self.dom.createElement('mfenced') 

1038 frac = self.dom.createElement('mfrac') 

1039 frac.setAttribute('linethickness', '0') 

1040 frac.appendChild(self._print(expr.args[0])) 

1041 frac.appendChild(self._print(expr.args[1])) 

1042 brac.appendChild(frac) 

1043 return brac 

1044 

1045 def _print_Pow(self, e): 

1046 # Here we use root instead of power if the exponent is the 

1047 # reciprocal of an integer 

1048 if (e.exp.is_Rational and abs(e.exp.p) == 1 and e.exp.q != 1 and 

1049 self._settings['root_notation']): 

1050 if e.exp.q == 2: 

1051 x = self.dom.createElement('msqrt') 

1052 x.appendChild(self._print(e.base)) 

1053 if e.exp.q != 2: 

1054 x = self.dom.createElement('mroot') 

1055 x.appendChild(self._print(e.base)) 

1056 x.appendChild(self._print(e.exp.q)) 

1057 if e.exp.p == -1: 

1058 frac = self.dom.createElement('mfrac') 

1059 frac.appendChild(self._print(1)) 

1060 frac.appendChild(x) 

1061 return frac 

1062 else: 

1063 return x 

1064 

1065 if e.exp.is_Rational and e.exp.q != 1: 

1066 if e.exp.is_negative: 

1067 top = self.dom.createElement('mfrac') 

1068 top.appendChild(self._print(1)) 

1069 x = self.dom.createElement('msup') 

1070 x.appendChild(self.parenthesize(e.base, PRECEDENCE['Pow'])) 

1071 x.appendChild(self._get_printed_Rational(-e.exp, 

1072 self._settings['fold_frac_powers'])) 

1073 top.appendChild(x) 

1074 return top 

1075 else: 

1076 x = self.dom.createElement('msup') 

1077 x.appendChild(self.parenthesize(e.base, PRECEDENCE['Pow'])) 

1078 x.appendChild(self._get_printed_Rational(e.exp, 

1079 self._settings['fold_frac_powers'])) 

1080 return x 

1081 

1082 if e.exp.is_negative: 

1083 top = self.dom.createElement('mfrac') 

1084 top.appendChild(self._print(1)) 

1085 if e.exp == -1: 

1086 top.appendChild(self._print(e.base)) 

1087 else: 

1088 x = self.dom.createElement('msup') 

1089 x.appendChild(self.parenthesize(e.base, PRECEDENCE['Pow'])) 

1090 x.appendChild(self._print(-e.exp)) 

1091 top.appendChild(x) 

1092 return top 

1093 

1094 x = self.dom.createElement('msup') 

1095 x.appendChild(self.parenthesize(e.base, PRECEDENCE['Pow'])) 

1096 x.appendChild(self._print(e.exp)) 

1097 return x 

1098 

1099 def _print_Number(self, e): 

1100 x = self.dom.createElement(self.mathml_tag(e)) 

1101 x.appendChild(self.dom.createTextNode(str(e))) 

1102 return x 

1103 

1104 def _print_AccumulationBounds(self, i): 

1105 brac = self.dom.createElement('mfenced') 

1106 brac.setAttribute('close', '\u27e9') 

1107 brac.setAttribute('open', '\u27e8') 

1108 brac.appendChild(self._print(i.min)) 

1109 brac.appendChild(self._print(i.max)) 

1110 return brac 

1111 

1112 def _print_Derivative(self, e): 

1113 

1114 if requires_partial(e.expr): 

1115 d = '&#x2202;' 

1116 else: 

1117 d = self.mathml_tag(e) 

1118 

1119 # Determine denominator 

1120 m = self.dom.createElement('mrow') 

1121 dim = 0 # Total diff dimension, for numerator 

1122 for sym, num in reversed(e.variable_count): 

1123 dim += num 

1124 if num >= 2: 

1125 x = self.dom.createElement('msup') 

1126 xx = self.dom.createElement('mo') 

1127 xx.appendChild(self.dom.createTextNode(d)) 

1128 x.appendChild(xx) 

1129 x.appendChild(self._print(num)) 

1130 else: 

1131 x = self.dom.createElement('mo') 

1132 x.appendChild(self.dom.createTextNode(d)) 

1133 m.appendChild(x) 

1134 y = self._print(sym) 

1135 m.appendChild(y) 

1136 

1137 mnum = self.dom.createElement('mrow') 

1138 if dim >= 2: 

1139 x = self.dom.createElement('msup') 

1140 xx = self.dom.createElement('mo') 

1141 xx.appendChild(self.dom.createTextNode(d)) 

1142 x.appendChild(xx) 

1143 x.appendChild(self._print(dim)) 

1144 else: 

1145 x = self.dom.createElement('mo') 

1146 x.appendChild(self.dom.createTextNode(d)) 

1147 

1148 mnum.appendChild(x) 

1149 mrow = self.dom.createElement('mrow') 

1150 frac = self.dom.createElement('mfrac') 

1151 frac.appendChild(mnum) 

1152 frac.appendChild(m) 

1153 mrow.appendChild(frac) 

1154 

1155 # Print function 

1156 mrow.appendChild(self._print(e.expr)) 

1157 

1158 return mrow 

1159 

1160 def _print_Function(self, e): 

1161 mrow = self.dom.createElement('mrow') 

1162 x = self.dom.createElement('mi') 

1163 if self.mathml_tag(e) == 'log' and self._settings["ln_notation"]: 

1164 x.appendChild(self.dom.createTextNode('ln')) 

1165 else: 

1166 x.appendChild(self.dom.createTextNode(self.mathml_tag(e))) 

1167 y = self.dom.createElement('mfenced') 

1168 for arg in e.args: 

1169 y.appendChild(self._print(arg)) 

1170 mrow.appendChild(x) 

1171 mrow.appendChild(y) 

1172 return mrow 

1173 

1174 def _print_Float(self, expr): 

1175 # Based off of that in StrPrinter 

1176 dps = prec_to_dps(expr._prec) 

1177 str_real = mlib_to_str(expr._mpf_, dps, strip_zeros=True) 

1178 

1179 # Must always have a mul symbol (as 2.5 10^{20} just looks odd) 

1180 # thus we use the number separator 

1181 separator = self._settings['mul_symbol_mathml_numbers'] 

1182 mrow = self.dom.createElement('mrow') 

1183 if 'e' in str_real: 

1184 (mant, exp) = str_real.split('e') 

1185 

1186 if exp[0] == '+': 

1187 exp = exp[1:] 

1188 

1189 mn = self.dom.createElement('mn') 

1190 mn.appendChild(self.dom.createTextNode(mant)) 

1191 mrow.appendChild(mn) 

1192 mo = self.dom.createElement('mo') 

1193 mo.appendChild(self.dom.createTextNode(separator)) 

1194 mrow.appendChild(mo) 

1195 msup = self.dom.createElement('msup') 

1196 mn = self.dom.createElement('mn') 

1197 mn.appendChild(self.dom.createTextNode("10")) 

1198 msup.appendChild(mn) 

1199 mn = self.dom.createElement('mn') 

1200 mn.appendChild(self.dom.createTextNode(exp)) 

1201 msup.appendChild(mn) 

1202 mrow.appendChild(msup) 

1203 return mrow 

1204 elif str_real == "+inf": 

1205 return self._print_Infinity(None) 

1206 elif str_real == "-inf": 

1207 return self._print_NegativeInfinity(None) 

1208 else: 

1209 mn = self.dom.createElement('mn') 

1210 mn.appendChild(self.dom.createTextNode(str_real)) 

1211 return mn 

1212 

1213 def _print_polylog(self, expr): 

1214 mrow = self.dom.createElement('mrow') 

1215 m = self.dom.createElement('msub') 

1216 

1217 mi = self.dom.createElement('mi') 

1218 mi.appendChild(self.dom.createTextNode('Li')) 

1219 m.appendChild(mi) 

1220 m.appendChild(self._print(expr.args[0])) 

1221 mrow.appendChild(m) 

1222 brac = self.dom.createElement('mfenced') 

1223 brac.appendChild(self._print(expr.args[1])) 

1224 mrow.appendChild(brac) 

1225 return mrow 

1226 

1227 def _print_Basic(self, e): 

1228 mrow = self.dom.createElement('mrow') 

1229 mi = self.dom.createElement('mi') 

1230 mi.appendChild(self.dom.createTextNode(self.mathml_tag(e))) 

1231 mrow.appendChild(mi) 

1232 brac = self.dom.createElement('mfenced') 

1233 for arg in e.args: 

1234 brac.appendChild(self._print(arg)) 

1235 mrow.appendChild(brac) 

1236 return mrow 

1237 

1238 def _print_Tuple(self, e): 

1239 mrow = self.dom.createElement('mrow') 

1240 x = self.dom.createElement('mfenced') 

1241 for arg in e.args: 

1242 x.appendChild(self._print(arg)) 

1243 mrow.appendChild(x) 

1244 return mrow 

1245 

1246 def _print_Interval(self, i): 

1247 mrow = self.dom.createElement('mrow') 

1248 brac = self.dom.createElement('mfenced') 

1249 if i.start == i.end: 

1250 # Most often, this type of Interval is converted to a FiniteSet 

1251 brac.setAttribute('close', '}') 

1252 brac.setAttribute('open', '{') 

1253 brac.appendChild(self._print(i.start)) 

1254 else: 

1255 if i.right_open: 

1256 brac.setAttribute('close', ')') 

1257 else: 

1258 brac.setAttribute('close', ']') 

1259 

1260 if i.left_open: 

1261 brac.setAttribute('open', '(') 

1262 else: 

1263 brac.setAttribute('open', '[') 

1264 brac.appendChild(self._print(i.start)) 

1265 brac.appendChild(self._print(i.end)) 

1266 

1267 mrow.appendChild(brac) 

1268 return mrow 

1269 

1270 def _print_Abs(self, expr, exp=None): 

1271 mrow = self.dom.createElement('mrow') 

1272 x = self.dom.createElement('mfenced') 

1273 x.setAttribute('close', '|') 

1274 x.setAttribute('open', '|') 

1275 x.appendChild(self._print(expr.args[0])) 

1276 mrow.appendChild(x) 

1277 return mrow 

1278 

1279 _print_Determinant = _print_Abs 

1280 

1281 def _print_re_im(self, c, expr): 

1282 mrow = self.dom.createElement('mrow') 

1283 mi = self.dom.createElement('mi') 

1284 mi.setAttribute('mathvariant', 'fraktur') 

1285 mi.appendChild(self.dom.createTextNode(c)) 

1286 mrow.appendChild(mi) 

1287 brac = self.dom.createElement('mfenced') 

1288 brac.appendChild(self._print(expr)) 

1289 mrow.appendChild(brac) 

1290 return mrow 

1291 

1292 def _print_re(self, expr, exp=None): 

1293 return self._print_re_im('R', expr.args[0]) 

1294 

1295 def _print_im(self, expr, exp=None): 

1296 return self._print_re_im('I', expr.args[0]) 

1297 

1298 def _print_AssocOp(self, e): 

1299 mrow = self.dom.createElement('mrow') 

1300 mi = self.dom.createElement('mi') 

1301 mi.appendChild(self.dom.createTextNode(self.mathml_tag(e))) 

1302 mrow.appendChild(mi) 

1303 for arg in e.args: 

1304 mrow.appendChild(self._print(arg)) 

1305 return mrow 

1306 

1307 def _print_SetOp(self, expr, symbol, prec): 

1308 mrow = self.dom.createElement('mrow') 

1309 mrow.appendChild(self.parenthesize(expr.args[0], prec)) 

1310 for arg in expr.args[1:]: 

1311 x = self.dom.createElement('mo') 

1312 x.appendChild(self.dom.createTextNode(symbol)) 

1313 y = self.parenthesize(arg, prec) 

1314 mrow.appendChild(x) 

1315 mrow.appendChild(y) 

1316 return mrow 

1317 

1318 def _print_Union(self, expr): 

1319 prec = PRECEDENCE_TRADITIONAL['Union'] 

1320 return self._print_SetOp(expr, '&#x222A;', prec) 

1321 

1322 def _print_Intersection(self, expr): 

1323 prec = PRECEDENCE_TRADITIONAL['Intersection'] 

1324 return self._print_SetOp(expr, '&#x2229;', prec) 

1325 

1326 def _print_Complement(self, expr): 

1327 prec = PRECEDENCE_TRADITIONAL['Complement'] 

1328 return self._print_SetOp(expr, '&#x2216;', prec) 

1329 

1330 def _print_SymmetricDifference(self, expr): 

1331 prec = PRECEDENCE_TRADITIONAL['SymmetricDifference'] 

1332 return self._print_SetOp(expr, '&#x2206;', prec) 

1333 

1334 def _print_ProductSet(self, expr): 

1335 prec = PRECEDENCE_TRADITIONAL['ProductSet'] 

1336 return self._print_SetOp(expr, '&#x00d7;', prec) 

1337 

1338 def _print_FiniteSet(self, s): 

1339 return self._print_set(s.args) 

1340 

1341 def _print_set(self, s): 

1342 items = sorted(s, key=default_sort_key) 

1343 brac = self.dom.createElement('mfenced') 

1344 brac.setAttribute('close', '}') 

1345 brac.setAttribute('open', '{') 

1346 for item in items: 

1347 brac.appendChild(self._print(item)) 

1348 return brac 

1349 

1350 _print_frozenset = _print_set 

1351 

1352 def _print_LogOp(self, args, symbol): 

1353 mrow = self.dom.createElement('mrow') 

1354 if args[0].is_Boolean and not args[0].is_Not: 

1355 brac = self.dom.createElement('mfenced') 

1356 brac.appendChild(self._print(args[0])) 

1357 mrow.appendChild(brac) 

1358 else: 

1359 mrow.appendChild(self._print(args[0])) 

1360 for arg in args[1:]: 

1361 x = self.dom.createElement('mo') 

1362 x.appendChild(self.dom.createTextNode(symbol)) 

1363 if arg.is_Boolean and not arg.is_Not: 

1364 y = self.dom.createElement('mfenced') 

1365 y.appendChild(self._print(arg)) 

1366 else: 

1367 y = self._print(arg) 

1368 mrow.appendChild(x) 

1369 mrow.appendChild(y) 

1370 return mrow 

1371 

1372 def _print_BasisDependent(self, expr): 

1373 from sympy.vector import Vector 

1374 

1375 if expr == expr.zero: 

1376 # Not clear if this is ever called 

1377 return self._print(expr.zero) 

1378 if isinstance(expr, Vector): 

1379 items = expr.separate().items() 

1380 else: 

1381 items = [(0, expr)] 

1382 

1383 mrow = self.dom.createElement('mrow') 

1384 for system, vect in items: 

1385 inneritems = list(vect.components.items()) 

1386 inneritems.sort(key = lambda x:x[0].__str__()) 

1387 for i, (k, v) in enumerate(inneritems): 

1388 if v == 1: 

1389 if i: # No + for first item 

1390 mo = self.dom.createElement('mo') 

1391 mo.appendChild(self.dom.createTextNode('+')) 

1392 mrow.appendChild(mo) 

1393 mrow.appendChild(self._print(k)) 

1394 elif v == -1: 

1395 mo = self.dom.createElement('mo') 

1396 mo.appendChild(self.dom.createTextNode('-')) 

1397 mrow.appendChild(mo) 

1398 mrow.appendChild(self._print(k)) 

1399 else: 

1400 if i: # No + for first item 

1401 mo = self.dom.createElement('mo') 

1402 mo.appendChild(self.dom.createTextNode('+')) 

1403 mrow.appendChild(mo) 

1404 mbrac = self.dom.createElement('mfenced') 

1405 mbrac.appendChild(self._print(v)) 

1406 mrow.appendChild(mbrac) 

1407 mo = self.dom.createElement('mo') 

1408 mo.appendChild(self.dom.createTextNode('&InvisibleTimes;')) 

1409 mrow.appendChild(mo) 

1410 mrow.appendChild(self._print(k)) 

1411 return mrow 

1412 

1413 

1414 def _print_And(self, expr): 

1415 args = sorted(expr.args, key=default_sort_key) 

1416 return self._print_LogOp(args, '&#x2227;') 

1417 

1418 def _print_Or(self, expr): 

1419 args = sorted(expr.args, key=default_sort_key) 

1420 return self._print_LogOp(args, '&#x2228;') 

1421 

1422 def _print_Xor(self, expr): 

1423 args = sorted(expr.args, key=default_sort_key) 

1424 return self._print_LogOp(args, '&#x22BB;') 

1425 

1426 def _print_Implies(self, expr): 

1427 return self._print_LogOp(expr.args, '&#x21D2;') 

1428 

1429 def _print_Equivalent(self, expr): 

1430 args = sorted(expr.args, key=default_sort_key) 

1431 return self._print_LogOp(args, '&#x21D4;') 

1432 

1433 def _print_Not(self, e): 

1434 mrow = self.dom.createElement('mrow') 

1435 mo = self.dom.createElement('mo') 

1436 mo.appendChild(self.dom.createTextNode('&#xAC;')) 

1437 mrow.appendChild(mo) 

1438 if (e.args[0].is_Boolean): 

1439 x = self.dom.createElement('mfenced') 

1440 x.appendChild(self._print(e.args[0])) 

1441 else: 

1442 x = self._print(e.args[0]) 

1443 mrow.appendChild(x) 

1444 return mrow 

1445 

1446 def _print_bool(self, e): 

1447 mi = self.dom.createElement('mi') 

1448 mi.appendChild(self.dom.createTextNode(self.mathml_tag(e))) 

1449 return mi 

1450 

1451 _print_BooleanTrue = _print_bool 

1452 _print_BooleanFalse = _print_bool 

1453 

1454 def _print_NoneType(self, e): 

1455 mi = self.dom.createElement('mi') 

1456 mi.appendChild(self.dom.createTextNode(self.mathml_tag(e))) 

1457 return mi 

1458 

1459 def _print_Range(self, s): 

1460 dots = "\u2026" 

1461 brac = self.dom.createElement('mfenced') 

1462 brac.setAttribute('close', '}') 

1463 brac.setAttribute('open', '{') 

1464 

1465 if s.start.is_infinite and s.stop.is_infinite: 

1466 if s.step.is_positive: 

1467 printset = dots, -1, 0, 1, dots 

1468 else: 

1469 printset = dots, 1, 0, -1, dots 

1470 elif s.start.is_infinite: 

1471 printset = dots, s[-1] - s.step, s[-1] 

1472 elif s.stop.is_infinite: 

1473 it = iter(s) 

1474 printset = next(it), next(it), dots 

1475 elif len(s) > 4: 

1476 it = iter(s) 

1477 printset = next(it), next(it), dots, s[-1] 

1478 else: 

1479 printset = tuple(s) 

1480 

1481 for el in printset: 

1482 if el == dots: 

1483 mi = self.dom.createElement('mi') 

1484 mi.appendChild(self.dom.createTextNode(dots)) 

1485 brac.appendChild(mi) 

1486 else: 

1487 brac.appendChild(self._print(el)) 

1488 

1489 return brac 

1490 

1491 def _hprint_variadic_function(self, expr): 

1492 args = sorted(expr.args, key=default_sort_key) 

1493 mrow = self.dom.createElement('mrow') 

1494 mo = self.dom.createElement('mo') 

1495 mo.appendChild(self.dom.createTextNode((str(expr.func)).lower())) 

1496 mrow.appendChild(mo) 

1497 brac = self.dom.createElement('mfenced') 

1498 for symbol in args: 

1499 brac.appendChild(self._print(symbol)) 

1500 mrow.appendChild(brac) 

1501 return mrow 

1502 

1503 _print_Min = _print_Max = _hprint_variadic_function 

1504 

1505 def _print_exp(self, expr): 

1506 msup = self.dom.createElement('msup') 

1507 msup.appendChild(self._print_Exp1(None)) 

1508 msup.appendChild(self._print(expr.args[0])) 

1509 return msup 

1510 

1511 def _print_Relational(self, e): 

1512 mrow = self.dom.createElement('mrow') 

1513 mrow.appendChild(self._print(e.lhs)) 

1514 x = self.dom.createElement('mo') 

1515 x.appendChild(self.dom.createTextNode(self.mathml_tag(e))) 

1516 mrow.appendChild(x) 

1517 mrow.appendChild(self._print(e.rhs)) 

1518 return mrow 

1519 

1520 def _print_int(self, p): 

1521 dom_element = self.dom.createElement(self.mathml_tag(p)) 

1522 dom_element.appendChild(self.dom.createTextNode(str(p))) 

1523 return dom_element 

1524 

1525 def _print_BaseScalar(self, e): 

1526 msub = self.dom.createElement('msub') 

1527 index, system = e._id 

1528 mi = self.dom.createElement('mi') 

1529 mi.setAttribute('mathvariant', 'bold') 

1530 mi.appendChild(self.dom.createTextNode(system._variable_names[index])) 

1531 msub.appendChild(mi) 

1532 mi = self.dom.createElement('mi') 

1533 mi.setAttribute('mathvariant', 'bold') 

1534 mi.appendChild(self.dom.createTextNode(system._name)) 

1535 msub.appendChild(mi) 

1536 return msub 

1537 

1538 def _print_BaseVector(self, e): 

1539 msub = self.dom.createElement('msub') 

1540 index, system = e._id 

1541 mover = self.dom.createElement('mover') 

1542 mi = self.dom.createElement('mi') 

1543 mi.setAttribute('mathvariant', 'bold') 

1544 mi.appendChild(self.dom.createTextNode(system._vector_names[index])) 

1545 mover.appendChild(mi) 

1546 mo = self.dom.createElement('mo') 

1547 mo.appendChild(self.dom.createTextNode('^')) 

1548 mover.appendChild(mo) 

1549 msub.appendChild(mover) 

1550 mi = self.dom.createElement('mi') 

1551 mi.setAttribute('mathvariant', 'bold') 

1552 mi.appendChild(self.dom.createTextNode(system._name)) 

1553 msub.appendChild(mi) 

1554 return msub 

1555 

1556 def _print_VectorZero(self, e): 

1557 mover = self.dom.createElement('mover') 

1558 mi = self.dom.createElement('mi') 

1559 mi.setAttribute('mathvariant', 'bold') 

1560 mi.appendChild(self.dom.createTextNode("0")) 

1561 mover.appendChild(mi) 

1562 mo = self.dom.createElement('mo') 

1563 mo.appendChild(self.dom.createTextNode('^')) 

1564 mover.appendChild(mo) 

1565 return mover 

1566 

1567 def _print_Cross(self, expr): 

1568 mrow = self.dom.createElement('mrow') 

1569 vec1 = expr._expr1 

1570 vec2 = expr._expr2 

1571 mrow.appendChild(self.parenthesize(vec1, PRECEDENCE['Mul'])) 

1572 mo = self.dom.createElement('mo') 

1573 mo.appendChild(self.dom.createTextNode('&#xD7;')) 

1574 mrow.appendChild(mo) 

1575 mrow.appendChild(self.parenthesize(vec2, PRECEDENCE['Mul'])) 

1576 return mrow 

1577 

1578 def _print_Curl(self, expr): 

1579 mrow = self.dom.createElement('mrow') 

1580 mo = self.dom.createElement('mo') 

1581 mo.appendChild(self.dom.createTextNode('&#x2207;')) 

1582 mrow.appendChild(mo) 

1583 mo = self.dom.createElement('mo') 

1584 mo.appendChild(self.dom.createTextNode('&#xD7;')) 

1585 mrow.appendChild(mo) 

1586 mrow.appendChild(self.parenthesize(expr._expr, PRECEDENCE['Mul'])) 

1587 return mrow 

1588 

1589 def _print_Divergence(self, expr): 

1590 mrow = self.dom.createElement('mrow') 

1591 mo = self.dom.createElement('mo') 

1592 mo.appendChild(self.dom.createTextNode('&#x2207;')) 

1593 mrow.appendChild(mo) 

1594 mo = self.dom.createElement('mo') 

1595 mo.appendChild(self.dom.createTextNode('&#xB7;')) 

1596 mrow.appendChild(mo) 

1597 mrow.appendChild(self.parenthesize(expr._expr, PRECEDENCE['Mul'])) 

1598 return mrow 

1599 

1600 def _print_Dot(self, expr): 

1601 mrow = self.dom.createElement('mrow') 

1602 vec1 = expr._expr1 

1603 vec2 = expr._expr2 

1604 mrow.appendChild(self.parenthesize(vec1, PRECEDENCE['Mul'])) 

1605 mo = self.dom.createElement('mo') 

1606 mo.appendChild(self.dom.createTextNode('&#xB7;')) 

1607 mrow.appendChild(mo) 

1608 mrow.appendChild(self.parenthesize(vec2, PRECEDENCE['Mul'])) 

1609 return mrow 

1610 

1611 def _print_Gradient(self, expr): 

1612 mrow = self.dom.createElement('mrow') 

1613 mo = self.dom.createElement('mo') 

1614 mo.appendChild(self.dom.createTextNode('&#x2207;')) 

1615 mrow.appendChild(mo) 

1616 mrow.appendChild(self.parenthesize(expr._expr, PRECEDENCE['Mul'])) 

1617 return mrow 

1618 

1619 def _print_Laplacian(self, expr): 

1620 mrow = self.dom.createElement('mrow') 

1621 mo = self.dom.createElement('mo') 

1622 mo.appendChild(self.dom.createTextNode('&#x2206;')) 

1623 mrow.appendChild(mo) 

1624 mrow.appendChild(self.parenthesize(expr._expr, PRECEDENCE['Mul'])) 

1625 return mrow 

1626 

1627 def _print_Integers(self, e): 

1628 x = self.dom.createElement('mi') 

1629 x.setAttribute('mathvariant', 'normal') 

1630 x.appendChild(self.dom.createTextNode('&#x2124;')) 

1631 return x 

1632 

1633 def _print_Complexes(self, e): 

1634 x = self.dom.createElement('mi') 

1635 x.setAttribute('mathvariant', 'normal') 

1636 x.appendChild(self.dom.createTextNode('&#x2102;')) 

1637 return x 

1638 

1639 def _print_Reals(self, e): 

1640 x = self.dom.createElement('mi') 

1641 x.setAttribute('mathvariant', 'normal') 

1642 x.appendChild(self.dom.createTextNode('&#x211D;')) 

1643 return x 

1644 

1645 def _print_Naturals(self, e): 

1646 x = self.dom.createElement('mi') 

1647 x.setAttribute('mathvariant', 'normal') 

1648 x.appendChild(self.dom.createTextNode('&#x2115;')) 

1649 return x 

1650 

1651 def _print_Naturals0(self, e): 

1652 sub = self.dom.createElement('msub') 

1653 x = self.dom.createElement('mi') 

1654 x.setAttribute('mathvariant', 'normal') 

1655 x.appendChild(self.dom.createTextNode('&#x2115;')) 

1656 sub.appendChild(x) 

1657 sub.appendChild(self._print(S.Zero)) 

1658 return sub 

1659 

1660 def _print_SingularityFunction(self, expr): 

1661 shift = expr.args[0] - expr.args[1] 

1662 power = expr.args[2] 

1663 sup = self.dom.createElement('msup') 

1664 brac = self.dom.createElement('mfenced') 

1665 brac.setAttribute('close', '\u27e9') 

1666 brac.setAttribute('open', '\u27e8') 

1667 brac.appendChild(self._print(shift)) 

1668 sup.appendChild(brac) 

1669 sup.appendChild(self._print(power)) 

1670 return sup 

1671 

1672 def _print_NaN(self, e): 

1673 x = self.dom.createElement('mi') 

1674 x.appendChild(self.dom.createTextNode('NaN')) 

1675 return x 

1676 

1677 def _print_number_function(self, e, name): 

1678 # Print name_arg[0] for one argument or name_arg[0](arg[1]) 

1679 # for more than one argument 

1680 sub = self.dom.createElement('msub') 

1681 mi = self.dom.createElement('mi') 

1682 mi.appendChild(self.dom.createTextNode(name)) 

1683 sub.appendChild(mi) 

1684 sub.appendChild(self._print(e.args[0])) 

1685 if len(e.args) == 1: 

1686 return sub 

1687 # TODO: copy-pasted from _print_Function: can we do better? 

1688 mrow = self.dom.createElement('mrow') 

1689 y = self.dom.createElement('mfenced') 

1690 for arg in e.args[1:]: 

1691 y.appendChild(self._print(arg)) 

1692 mrow.appendChild(sub) 

1693 mrow.appendChild(y) 

1694 return mrow 

1695 

1696 def _print_bernoulli(self, e): 

1697 return self._print_number_function(e, 'B') 

1698 

1699 _print_bell = _print_bernoulli 

1700 

1701 def _print_catalan(self, e): 

1702 return self._print_number_function(e, 'C') 

1703 

1704 def _print_euler(self, e): 

1705 return self._print_number_function(e, 'E') 

1706 

1707 def _print_fibonacci(self, e): 

1708 return self._print_number_function(e, 'F') 

1709 

1710 def _print_lucas(self, e): 

1711 return self._print_number_function(e, 'L') 

1712 

1713 def _print_stieltjes(self, e): 

1714 return self._print_number_function(e, '&#x03B3;') 

1715 

1716 def _print_tribonacci(self, e): 

1717 return self._print_number_function(e, 'T') 

1718 

1719 def _print_ComplexInfinity(self, e): 

1720 x = self.dom.createElement('mover') 

1721 mo = self.dom.createElement('mo') 

1722 mo.appendChild(self.dom.createTextNode('&#x221E;')) 

1723 x.appendChild(mo) 

1724 mo = self.dom.createElement('mo') 

1725 mo.appendChild(self.dom.createTextNode('~')) 

1726 x.appendChild(mo) 

1727 return x 

1728 

1729 def _print_EmptySet(self, e): 

1730 x = self.dom.createElement('mo') 

1731 x.appendChild(self.dom.createTextNode('&#x2205;')) 

1732 return x 

1733 

1734 def _print_UniversalSet(self, e): 

1735 x = self.dom.createElement('mo') 

1736 x.appendChild(self.dom.createTextNode('&#x1D54C;')) 

1737 return x 

1738 

1739 def _print_Adjoint(self, expr): 

1740 from sympy.matrices import MatrixSymbol 

1741 mat = expr.arg 

1742 sup = self.dom.createElement('msup') 

1743 if not isinstance(mat, MatrixSymbol): 

1744 brac = self.dom.createElement('mfenced') 

1745 brac.appendChild(self._print(mat)) 

1746 sup.appendChild(brac) 

1747 else: 

1748 sup.appendChild(self._print(mat)) 

1749 mo = self.dom.createElement('mo') 

1750 mo.appendChild(self.dom.createTextNode('&#x2020;')) 

1751 sup.appendChild(mo) 

1752 return sup 

1753 

1754 def _print_Transpose(self, expr): 

1755 from sympy.matrices import MatrixSymbol 

1756 mat = expr.arg 

1757 sup = self.dom.createElement('msup') 

1758 if not isinstance(mat, MatrixSymbol): 

1759 brac = self.dom.createElement('mfenced') 

1760 brac.appendChild(self._print(mat)) 

1761 sup.appendChild(brac) 

1762 else: 

1763 sup.appendChild(self._print(mat)) 

1764 mo = self.dom.createElement('mo') 

1765 mo.appendChild(self.dom.createTextNode('T')) 

1766 sup.appendChild(mo) 

1767 return sup 

1768 

1769 def _print_Inverse(self, expr): 

1770 from sympy.matrices import MatrixSymbol 

1771 mat = expr.arg 

1772 sup = self.dom.createElement('msup') 

1773 if not isinstance(mat, MatrixSymbol): 

1774 brac = self.dom.createElement('mfenced') 

1775 brac.appendChild(self._print(mat)) 

1776 sup.appendChild(brac) 

1777 else: 

1778 sup.appendChild(self._print(mat)) 

1779 sup.appendChild(self._print(-1)) 

1780 return sup 

1781 

1782 def _print_MatMul(self, expr): 

1783 from sympy.matrices.expressions.matmul import MatMul 

1784 

1785 x = self.dom.createElement('mrow') 

1786 args = expr.args 

1787 if isinstance(args[0], Mul): 

1788 args = args[0].as_ordered_factors() + list(args[1:]) 

1789 else: 

1790 args = list(args) 

1791 

1792 if isinstance(expr, MatMul) and expr.could_extract_minus_sign(): 

1793 if args[0] == -1: 

1794 args = args[1:] 

1795 else: 

1796 args[0] = -args[0] 

1797 mo = self.dom.createElement('mo') 

1798 mo.appendChild(self.dom.createTextNode('-')) 

1799 x.appendChild(mo) 

1800 

1801 for arg in args[:-1]: 

1802 x.appendChild(self.parenthesize(arg, precedence_traditional(expr), 

1803 False)) 

1804 mo = self.dom.createElement('mo') 

1805 mo.appendChild(self.dom.createTextNode('&InvisibleTimes;')) 

1806 x.appendChild(mo) 

1807 x.appendChild(self.parenthesize(args[-1], precedence_traditional(expr), 

1808 False)) 

1809 return x 

1810 

1811 def _print_MatPow(self, expr): 

1812 from sympy.matrices import MatrixSymbol 

1813 base, exp = expr.base, expr.exp 

1814 sup = self.dom.createElement('msup') 

1815 if not isinstance(base, MatrixSymbol): 

1816 brac = self.dom.createElement('mfenced') 

1817 brac.appendChild(self._print(base)) 

1818 sup.appendChild(brac) 

1819 else: 

1820 sup.appendChild(self._print(base)) 

1821 sup.appendChild(self._print(exp)) 

1822 return sup 

1823 

1824 def _print_HadamardProduct(self, expr): 

1825 x = self.dom.createElement('mrow') 

1826 args = expr.args 

1827 for arg in args[:-1]: 

1828 x.appendChild( 

1829 self.parenthesize(arg, precedence_traditional(expr), False)) 

1830 mo = self.dom.createElement('mo') 

1831 mo.appendChild(self.dom.createTextNode('&#x2218;')) 

1832 x.appendChild(mo) 

1833 x.appendChild( 

1834 self.parenthesize(args[-1], precedence_traditional(expr), False)) 

1835 return x 

1836 

1837 def _print_ZeroMatrix(self, Z): 

1838 x = self.dom.createElement('mn') 

1839 x.appendChild(self.dom.createTextNode('&#x1D7D8')) 

1840 return x 

1841 

1842 def _print_OneMatrix(self, Z): 

1843 x = self.dom.createElement('mn') 

1844 x.appendChild(self.dom.createTextNode('&#x1D7D9')) 

1845 return x 

1846 

1847 def _print_Identity(self, I): 

1848 x = self.dom.createElement('mi') 

1849 x.appendChild(self.dom.createTextNode('&#x1D540;')) 

1850 return x 

1851 

1852 def _print_floor(self, e): 

1853 mrow = self.dom.createElement('mrow') 

1854 x = self.dom.createElement('mfenced') 

1855 x.setAttribute('close', '\u230B') 

1856 x.setAttribute('open', '\u230A') 

1857 x.appendChild(self._print(e.args[0])) 

1858 mrow.appendChild(x) 

1859 return mrow 

1860 

1861 def _print_ceiling(self, e): 

1862 mrow = self.dom.createElement('mrow') 

1863 x = self.dom.createElement('mfenced') 

1864 x.setAttribute('close', '\u2309') 

1865 x.setAttribute('open', '\u2308') 

1866 x.appendChild(self._print(e.args[0])) 

1867 mrow.appendChild(x) 

1868 return mrow 

1869 

1870 def _print_Lambda(self, e): 

1871 x = self.dom.createElement('mfenced') 

1872 mrow = self.dom.createElement('mrow') 

1873 symbols = e.args[0] 

1874 if len(symbols) == 1: 

1875 symbols = self._print(symbols[0]) 

1876 else: 

1877 symbols = self._print(symbols) 

1878 mrow.appendChild(symbols) 

1879 mo = self.dom.createElement('mo') 

1880 mo.appendChild(self.dom.createTextNode('&#x21A6;')) 

1881 mrow.appendChild(mo) 

1882 mrow.appendChild(self._print(e.args[1])) 

1883 x.appendChild(mrow) 

1884 return x 

1885 

1886 def _print_tuple(self, e): 

1887 x = self.dom.createElement('mfenced') 

1888 for i in e: 

1889 x.appendChild(self._print(i)) 

1890 return x 

1891 

1892 def _print_IndexedBase(self, e): 

1893 return self._print(e.label) 

1894 

1895 def _print_Indexed(self, e): 

1896 x = self.dom.createElement('msub') 

1897 x.appendChild(self._print(e.base)) 

1898 if len(e.indices) == 1: 

1899 x.appendChild(self._print(e.indices[0])) 

1900 return x 

1901 x.appendChild(self._print(e.indices)) 

1902 return x 

1903 

1904 def _print_MatrixElement(self, e): 

1905 x = self.dom.createElement('msub') 

1906 x.appendChild(self.parenthesize(e.parent, PRECEDENCE["Atom"], strict = True)) 

1907 brac = self.dom.createElement('mfenced') 

1908 brac.setAttribute("close", "") 

1909 brac.setAttribute("open", "") 

1910 for i in e.indices: 

1911 brac.appendChild(self._print(i)) 

1912 x.appendChild(brac) 

1913 return x 

1914 

1915 def _print_elliptic_f(self, e): 

1916 x = self.dom.createElement('mrow') 

1917 mi = self.dom.createElement('mi') 

1918 mi.appendChild(self.dom.createTextNode('&#x1d5a5;')) 

1919 x.appendChild(mi) 

1920 y = self.dom.createElement('mfenced') 

1921 y.setAttribute("separators", "|") 

1922 for i in e.args: 

1923 y.appendChild(self._print(i)) 

1924 x.appendChild(y) 

1925 return x 

1926 

1927 def _print_elliptic_e(self, e): 

1928 x = self.dom.createElement('mrow') 

1929 mi = self.dom.createElement('mi') 

1930 mi.appendChild(self.dom.createTextNode('&#x1d5a4;')) 

1931 x.appendChild(mi) 

1932 y = self.dom.createElement('mfenced') 

1933 y.setAttribute("separators", "|") 

1934 for i in e.args: 

1935 y.appendChild(self._print(i)) 

1936 x.appendChild(y) 

1937 return x 

1938 

1939 def _print_elliptic_pi(self, e): 

1940 x = self.dom.createElement('mrow') 

1941 mi = self.dom.createElement('mi') 

1942 mi.appendChild(self.dom.createTextNode('&#x1d6f1;')) 

1943 x.appendChild(mi) 

1944 y = self.dom.createElement('mfenced') 

1945 if len(e.args) == 2: 

1946 y.setAttribute("separators", "|") 

1947 else: 

1948 y.setAttribute("separators", ";|") 

1949 for i in e.args: 

1950 y.appendChild(self._print(i)) 

1951 x.appendChild(y) 

1952 return x 

1953 

1954 def _print_Ei(self, e): 

1955 x = self.dom.createElement('mrow') 

1956 mi = self.dom.createElement('mi') 

1957 mi.appendChild(self.dom.createTextNode('Ei')) 

1958 x.appendChild(mi) 

1959 x.appendChild(self._print(e.args)) 

1960 return x 

1961 

1962 def _print_expint(self, e): 

1963 x = self.dom.createElement('mrow') 

1964 y = self.dom.createElement('msub') 

1965 mo = self.dom.createElement('mo') 

1966 mo.appendChild(self.dom.createTextNode('E')) 

1967 y.appendChild(mo) 

1968 y.appendChild(self._print(e.args[0])) 

1969 x.appendChild(y) 

1970 x.appendChild(self._print(e.args[1:])) 

1971 return x 

1972 

1973 def _print_jacobi(self, e): 

1974 x = self.dom.createElement('mrow') 

1975 y = self.dom.createElement('msubsup') 

1976 mo = self.dom.createElement('mo') 

1977 mo.appendChild(self.dom.createTextNode('P')) 

1978 y.appendChild(mo) 

1979 y.appendChild(self._print(e.args[0])) 

1980 y.appendChild(self._print(e.args[1:3])) 

1981 x.appendChild(y) 

1982 x.appendChild(self._print(e.args[3:])) 

1983 return x 

1984 

1985 def _print_gegenbauer(self, e): 

1986 x = self.dom.createElement('mrow') 

1987 y = self.dom.createElement('msubsup') 

1988 mo = self.dom.createElement('mo') 

1989 mo.appendChild(self.dom.createTextNode('C')) 

1990 y.appendChild(mo) 

1991 y.appendChild(self._print(e.args[0])) 

1992 y.appendChild(self._print(e.args[1:2])) 

1993 x.appendChild(y) 

1994 x.appendChild(self._print(e.args[2:])) 

1995 return x 

1996 

1997 def _print_chebyshevt(self, e): 

1998 x = self.dom.createElement('mrow') 

1999 y = self.dom.createElement('msub') 

2000 mo = self.dom.createElement('mo') 

2001 mo.appendChild(self.dom.createTextNode('T')) 

2002 y.appendChild(mo) 

2003 y.appendChild(self._print(e.args[0])) 

2004 x.appendChild(y) 

2005 x.appendChild(self._print(e.args[1:])) 

2006 return x 

2007 

2008 def _print_chebyshevu(self, e): 

2009 x = self.dom.createElement('mrow') 

2010 y = self.dom.createElement('msub') 

2011 mo = self.dom.createElement('mo') 

2012 mo.appendChild(self.dom.createTextNode('U')) 

2013 y.appendChild(mo) 

2014 y.appendChild(self._print(e.args[0])) 

2015 x.appendChild(y) 

2016 x.appendChild(self._print(e.args[1:])) 

2017 return x 

2018 

2019 def _print_legendre(self, e): 

2020 x = self.dom.createElement('mrow') 

2021 y = self.dom.createElement('msub') 

2022 mo = self.dom.createElement('mo') 

2023 mo.appendChild(self.dom.createTextNode('P')) 

2024 y.appendChild(mo) 

2025 y.appendChild(self._print(e.args[0])) 

2026 x.appendChild(y) 

2027 x.appendChild(self._print(e.args[1:])) 

2028 return x 

2029 

2030 def _print_assoc_legendre(self, e): 

2031 x = self.dom.createElement('mrow') 

2032 y = self.dom.createElement('msubsup') 

2033 mo = self.dom.createElement('mo') 

2034 mo.appendChild(self.dom.createTextNode('P')) 

2035 y.appendChild(mo) 

2036 y.appendChild(self._print(e.args[0])) 

2037 y.appendChild(self._print(e.args[1:2])) 

2038 x.appendChild(y) 

2039 x.appendChild(self._print(e.args[2:])) 

2040 return x 

2041 

2042 def _print_laguerre(self, e): 

2043 x = self.dom.createElement('mrow') 

2044 y = self.dom.createElement('msub') 

2045 mo = self.dom.createElement('mo') 

2046 mo.appendChild(self.dom.createTextNode('L')) 

2047 y.appendChild(mo) 

2048 y.appendChild(self._print(e.args[0])) 

2049 x.appendChild(y) 

2050 x.appendChild(self._print(e.args[1:])) 

2051 return x 

2052 

2053 def _print_assoc_laguerre(self, e): 

2054 x = self.dom.createElement('mrow') 

2055 y = self.dom.createElement('msubsup') 

2056 mo = self.dom.createElement('mo') 

2057 mo.appendChild(self.dom.createTextNode('L')) 

2058 y.appendChild(mo) 

2059 y.appendChild(self._print(e.args[0])) 

2060 y.appendChild(self._print(e.args[1:2])) 

2061 x.appendChild(y) 

2062 x.appendChild(self._print(e.args[2:])) 

2063 return x 

2064 

2065 def _print_hermite(self, e): 

2066 x = self.dom.createElement('mrow') 

2067 y = self.dom.createElement('msub') 

2068 mo = self.dom.createElement('mo') 

2069 mo.appendChild(self.dom.createTextNode('H')) 

2070 y.appendChild(mo) 

2071 y.appendChild(self._print(e.args[0])) 

2072 x.appendChild(y) 

2073 x.appendChild(self._print(e.args[1:])) 

2074 return x 

2075 

2076 

2077@print_function(MathMLPrinterBase) 

2078def mathml(expr, printer='content', **settings): 

2079 """Returns the MathML representation of expr. If printer is presentation 

2080 then prints Presentation MathML else prints content MathML. 

2081 """ 

2082 if printer == 'presentation': 

2083 return MathMLPresentationPrinter(settings).doprint(expr) 

2084 else: 

2085 return MathMLContentPrinter(settings).doprint(expr) 

2086 

2087 

2088def print_mathml(expr, printer='content', **settings): 

2089 """ 

2090 Prints a pretty representation of the MathML code for expr. If printer is 

2091 presentation then prints Presentation MathML else prints content MathML. 

2092 

2093 Examples 

2094 ======== 

2095 

2096 >>> ## 

2097 >>> from sympy import print_mathml 

2098 >>> from sympy.abc import x 

2099 >>> print_mathml(x+1) #doctest: +NORMALIZE_WHITESPACE 

2100 <apply> 

2101 <plus/> 

2102 <ci>x</ci> 

2103 <cn>1</cn> 

2104 </apply> 

2105 >>> print_mathml(x+1, printer='presentation') 

2106 <mrow> 

2107 <mi>x</mi> 

2108 <mo>+</mo> 

2109 <mn>1</mn> 

2110 </mrow> 

2111 

2112 """ 

2113 if printer == 'presentation': 

2114 s = MathMLPresentationPrinter(settings) 

2115 else: 

2116 s = MathMLContentPrinter(settings) 

2117 xml = s._print(sympify(expr)) 

2118 s.apply_patch() 

2119 pretty_xml = xml.toprettyxml() 

2120 s.restore_patch() 

2121 

2122 print(pretty_xml) 

2123 

2124 

2125# For backward compatibility 

2126MathMLPrinter = MathMLContentPrinter