| 1373 | def latex_symbolic_function(fname, fstr, args): |
| 1374 | r""" |
| 1375 | Typeset a given symbolic function in LaTeX. |
| 1376 | |
| 1377 | EXAMPLES:: |
| 1378 | |
| 1379 | sage: import sage.misc.latex as latex_module |
| 1380 | sage: latex_sym_fn = latex_module.latex_symbolic_function |
| 1381 | sage: var('x,a,b,t,s') |
| 1382 | (x, a, b, t, s) |
| 1383 | sage: riemann(x) = function('riemann',x) |
| 1384 | sage: latex_sym_fn("riemann","\\mathcal{R}",(x,)) |
| 1385 | '\\mathcal{R}\\left(x\\right)' |
| 1386 | sage: psi(x) = function('psi',x) |
| 1387 | sage: latex_sym_fn("psi",False,(x,)) |
| 1388 | '\\psi\\left(x\\right)' |
| 1389 | sage: latex_sym_fn("conjugate",False,(psi(x))) |
| 1390 | '\\overline{\\psi\\left(x\\right)}' |
| 1391 | sage: latex_sym_fn("limit",False,(psi(x),x,a)) |
| 1392 | '\\lim_{x \\to a}\\, \\psi\\left(x\\right)' |
| 1393 | |
| 1394 | sage: f(t) = function('f',t) |
| 1395 | sage: latex_sym_fn("laplace",False,(f(t),t,s)) |
| 1396 | '\\mathcal{L}\\left(f\\left(t\\right), t, s\\right)' |
| 1397 | |
| 1398 | sage: F(s) = function('F',s) |
| 1399 | sage: latex_sym_fn("ilt",False,(F(s),s,t)) |
| 1400 | '\\mathcal{L}^{-1}\\left(F\\left(s\\right), s, t\\right)' |
| 1401 | |
| 1402 | sage: f(x) = function('f',x) |
| 1403 | sage: latex_sym_fn("integrate",False,(f(x),x)) |
| 1404 | '\\int f\\left(x\\right)\\,{d x}' |
| 1405 | sage: latex_sym_fn("integrate",False,(f(x),x,a,b)) |
| 1406 | '\\int_{a}^{b} f\\left(x\\right)\\,{d x}' |
| 1407 | |
| 1408 | sage: var('x,y') |
| 1409 | (x, y) |
| 1410 | sage: f(x) = function('f',x) |
| 1411 | sage: latex_sym_fn("diff",False,(f(x),x,1)) |
| 1412 | '\\frac{d f\\left(x\\right)}{d x}' |
| 1413 | sage: f(x,y) = function('f',x,y) |
| 1414 | sage: latex_sym_fn("diff",False,(f(x,y),x,1)) |
| 1415 | '\\frac{\\partial}{\\partial x}f\\left(x, y\\right)' |
| 1416 | |
| 1417 | sage: myfunc(x) = function('myfunc',x) |
| 1418 | sage: latex_sym_fn("myfunc",False,(x,)) |
| 1419 | '{\\it myfunc}\\left(x\\right)' |
| 1420 | |
| 1421 | AUTHORS: |
| 1422 | |
| 1423 | - Golam Mortuza Hossain (2009-04-05) |
| 1424 | """ |
| 1425 | # Use the latex_name if defined |
| 1426 | if fstr is not False: |
| 1427 | return "%s%s"%(fstr, _args_latex_(fname, args)) |
| 1428 | # Special handling of fname where specific processing is needed |
| 1429 | if fname == "conjugate": |
| 1430 | return _conjugate_latex_(fname, args) |
| 1431 | elif fname == "limit": |
| 1432 | return _limit_latex_(fname, args) |
| 1433 | elif fname == "laplace": |
| 1434 | return _laplace_latex_(fname, args) |
| 1435 | elif fname == "ilt": |
| 1436 | return _inverse_laplace_latex_(fname, args) |
| 1437 | elif fname == "integrate": |
| 1438 | return _integrate_latex_(fname, args) |
| 1439 | elif fname == "diff": |
| 1440 | f = args[0] |
| 1441 | fstr = latex(f) |
| 1442 | nvars = len(f.variables()) |
| 1443 | return _derivative_latex_(fstr, args, nvars) |
| 1444 | # Now check whether fname is a Greek letter |
| 1445 | name = latex_function_name(fname) |
| 1446 | if name is not False: |
| 1447 | return "%s%s"%(name, _args_latex_(fname, args)) |
| 1448 | # Use default typesetting scheme |
| 1449 | return _symbolic_function_default_latex_(fname, args) |
| 1450 | |
| 1451 | def _symbolic_function_default_latex_(fname, args): |
| 1452 | r""" |
| 1453 | Return LaTeX expression of a symbolic function using default scheme. |
| 1454 | |
| 1455 | EXAMPLES:: |
| 1456 | |
| 1457 | sage: import sage.misc.latex as latex_module |
| 1458 | sage: _sym_def_latex_ = latex_module._symbolic_function_default_latex_ |
| 1459 | sage: var('x') |
| 1460 | x |
| 1461 | sage: myfunc(x) = function('myfunc',x) |
| 1462 | sage: _sym_def_latex_("myfunc",(x,)) |
| 1463 | '{\\it myfunc}\\left(x\\right)' |
| 1464 | sage: my_func(x) = function('my_func',x) |
| 1465 | sage: _sym_def_latex_("my_func",(x,)) |
| 1466 | '{\\it my\\_func}\\left(x\\right)' |
| 1467 | |
| 1468 | AUTHORS: |
| 1469 | |
| 1470 | - Golam Mortuza Hossain (2009-04-05) |
| 1471 | """ |
| 1472 | # Prepend underscore by "\\" in fname |
| 1473 | fname = fname.replace("_", "\\_") |
| 1474 | # Default typesetting scheme (similar to Maxima scheme) |
| 1475 | return "{\\it %s}%s"%(fname, _args_latex_(fname, args)) |
| 1476 | |
| 1477 | def _args_latex_(fname, args): |
| 1478 | r""" |
| 1479 | Return LaTeX expression for the arguments of a symbolic function. |
| 1480 | |
| 1481 | EXAMPLES:: |
| 1482 | |
| 1483 | sage: import sage.misc.latex as latex_module |
| 1484 | sage: _args_latex_ = latex_module._args_latex_ |
| 1485 | sage: var('x') |
| 1486 | x |
| 1487 | sage: f(x) = function('f',x) |
| 1488 | sage: _args_latex_("f",(x,)) |
| 1489 | '\\left(x\\right)' |
| 1490 | |
| 1491 | AUTHORS: |
| 1492 | |
| 1493 | - Golam Mortuza Hossain (2009-04-06) |
| 1494 | """ |
| 1495 | # If all arguments are SymbolicVariables then the function should be |
| 1496 | # typeset as f(x) rather than f\left(x\right) |
| 1497 | use_left_right = True |
| 1498 | #from sage.calculus.calculus import SymbolicVariable |
| 1499 | #for x in self._args: |
| 1500 | # if not isinstance(x, SymbolicVariable): |
| 1501 | # use_left_right = True |
| 1502 | # break |
| 1503 | if use_left_right is True: |
| 1504 | return "\\left(%s\\right)"%(', '.join([latex(x) for x in args])) |
| 1505 | else: |
| 1506 | return "(%s)"%(', '.join([latex(x) for x in args])) |
| 1507 | |
| 1508 | def latex_d_derivative(fstr, params, args): |
| 1509 | r""" |
| 1510 | Return LaTeX expression for "D" format derivatives of a |
| 1511 | symbolic function. |
| 1512 | |
| 1513 | EXAMPLES:: |
| 1514 | |
| 1515 | sage: import sage.misc.latex as latex_module |
| 1516 | sage: latex_d_derivative = latex_module.latex_d_derivative |
| 1517 | sage: var('x,y') |
| 1518 | (x, y) |
| 1519 | sage: f(x) = function('f',x) |
| 1520 | sage: latex_d_derivative("f\\left(x\\right)",[0],(x,)) |
| 1521 | '\\frac{d f\\left(x\\right)}{d x}' |
| 1522 | sage: latex_d_derivative("f\\left(x\\right)",[0,0],(x,)) |
| 1523 | '\\frac{d^{2} f\\left(x\\right)}{d {x}^{2}}' |
| 1524 | |
| 1525 | sage: f(x,y) = function('f',x,y) |
| 1526 | sage: latex_d_derivative("f\\left(x, y\\right)",[0],(x,y)) |
| 1527 | '\\frac{\\partial}{\\partial x}f\\left(x, y\\right)' |
| 1528 | sage: latex_d_derivative("f\\left(x, y\\right)",[0,0,0],(x,y)) |
| 1529 | '\\frac{\\partial^{3}}{\\partial {x}^{3}}f\\left(x, y\\right)' |
| 1530 | sage: latex_d_derivative("f\\left(x, y\\right)",[0,1],(x,y)) |
| 1531 | '\\frac{\\partial^{2}}{\\partial y\\partial x}f\\left(x, y\\right)' |
| 1532 | |
| 1533 | AUTHORS: |
| 1534 | |
| 1535 | - Golam Mortuza Hossain (2009-06-11) |
| 1536 | """ |
| 1537 | # Following lines convert "D" format derivative into "diff" |
| 1538 | # format and then call the "diff" typesetting function |
| 1539 | varhash = {} |
| 1540 | for x in params: |
| 1541 | if args[x] in varhash: |
| 1542 | varhash[args[x]] = varhash[args[x]] + 1 |
| 1543 | else: |
| 1544 | varhash[args[x]] = 1 |
| 1545 | newargs = [fstr] |
| 1546 | for a in args: |
| 1547 | if a in varhash: |
| 1548 | newargs.append(a) |
| 1549 | newargs.append(varhash[a]) |
| 1550 | # No of variables |
| 1551 | nvars = len(args) |
| 1552 | return _derivative_latex_(fstr, newargs, nvars) |
| 1553 | |
| 1554 | def _derivative_latex_(fstr, args, nvars): |
| 1555 | r""" |
| 1556 | Return LaTeX expression for derivatives of a symbolic function. |
| 1557 | |
| 1558 | EXAMPLES:: |
| 1559 | |
| 1560 | sage: import sage.misc.latex as latex_module |
| 1561 | sage: _derivative_latex_ = latex_module._derivative_latex_ |
| 1562 | sage: var('x,y') |
| 1563 | (x, y) |
| 1564 | sage: f(x) = function('f',x) |
| 1565 | sage: _derivative_latex_("f\\left(x\\right)",(f(x),x,1),1) |
| 1566 | '\\frac{d f\\left(x\\right)}{d x}' |
| 1567 | sage: _derivative_latex_("f\\left(x\\right)",(f(x),x,2),1) |
| 1568 | '\\frac{d^{2} f\\left(x\\right)}{d {x}^{2}}' |
| 1569 | |
| 1570 | sage: f(x,y) = function('f',x,y) |
| 1571 | sage: _derivative_latex_("f\\left(x, y\\right)",(f(x,y),x,1),2) |
| 1572 | '\\frac{\\partial}{\\partial x}f\\left(x, y\\right)' |
| 1573 | sage: _derivative_latex_("f\\left(x, y\\right)",(f(x,y),x,3),2) |
| 1574 | '\\frac{\\partial^{3}}{\\partial {x}^{3}}f\\left(x, y\\right)' |
| 1575 | sage: _derivative_latex_("f\\left(x, y\\right)",(f(x,y),x,1,y,1),2) |
| 1576 | '\\frac{\\partial^{2}}{\\partial y\\partial x}f\\left(x, y\\right)' |
| 1577 | |
| 1578 | AUTHORS: |
| 1579 | |
| 1580 | - Golam Mortuza Hossain (2009-04-05) |
| 1581 | """ |
| 1582 | n = len(args) |
| 1583 | # We dont do any processing for n < 2 |
| 1584 | if n < 2: |
| 1585 | return _symbolic_function_default_latex_("diff", args) |
| 1586 | # Check whether it should be partial derivative |
| 1587 | # Logic taken from: http://trac.sagemath.org/sage_trac/ticket/4202 |
| 1588 | if nvars == 1: |
| 1589 | d_latex = "d" |
| 1590 | else: |
| 1591 | d_latex = "\\partial" |
| 1592 | |
| 1593 | # Read the variables |
| 1594 | diffstr = ""; total = 0 |
| 1595 | for i in range(1,n-1,2): |
| 1596 | x = args[i] # variable |
| 1597 | j = args[i+1] # no of times diff acts on f w.r.t. variable x |
| 1598 | total = total + j # total no of times diff acts |
| 1599 | if j == 1: |
| 1600 | diffstr = "%s %s"%(d_latex, latex(x)) + diffstr |
| 1601 | else: |
| 1602 | diffstr = "%s {%s}^{%s}"%(d_latex, latex(x), latex(j)) + diffstr |
| 1603 | # Return final expression |
| 1604 | if total == 1: |
| 1605 | if d_latex == "d": |
| 1606 | return "\\frac{%s %s}{%s}"%(d_latex, fstr, diffstr) |
| 1607 | else: |
| 1608 | return "\\frac{%s}{%s}%s"%(d_latex, diffstr, fstr) |
| 1609 | if d_latex == "d": |
| 1610 | return "\\frac{%s^{%d} %s}{%s}"%(d_latex, total, fstr, diffstr) |
| 1611 | else: |
| 1612 | return "\\frac{%s^{%d}}{%s}%s"%(d_latex, total, diffstr, fstr) |
| 1613 | |
| 1614 | def _integrate_latex_(fname, args): |
| 1615 | r""" |
| 1616 | Return LaTeX expression for integration of a symbolic function. |
| 1617 | |
| 1618 | EXAMPLES:: |
| 1619 | |
| 1620 | sage: import sage.misc.latex as latex_module |
| 1621 | sage: _integrate_latex_ = latex_module._integrate_latex_ |
| 1622 | sage: var('x,a,b') |
| 1623 | (x, a, b) |
| 1624 | sage: f(x) = function('f',x) |
| 1625 | sage: _integrate_latex_("integrate",(f(x),x)) |
| 1626 | '\\int f\\left(x\\right)\\,{d x}' |
| 1627 | sage: _integrate_latex_("integrate",(f(x),x,a,b)) |
| 1628 | '\\int_{a}^{b} f\\left(x\\right)\\,{d x}' |
| 1629 | |
| 1630 | AUTHORS: |
| 1631 | |
| 1632 | - Golam Mortuza Hossain (2009-04-05) |
| 1633 | """ |
| 1634 | n = len(args) |
| 1635 | # We dont process if number of arguments is neither 2 nor 4 |
| 1636 | if n != 2 and n != 4: |
| 1637 | # Return default typesetting |
| 1638 | return _symbolic_function_default_latex_(fname, args) |
| 1639 | f = args[0] |
| 1640 | x = args[1] |
| 1641 | # Check whether its a definite integral |
| 1642 | if n == 4: |
| 1643 | a = args[2] |
| 1644 | b = args[3] |
| 1645 | return "\\int_{%s}^{%s} %s\\,{d %s}"%(latex(a), latex(b), latex(f), latex(x)) |
| 1646 | # Typeset as indefinite integral |
| 1647 | return "\\int %s\\,{d %s}"%(latex(f), latex(x)) |
| 1648 | |
| 1649 | def _inverse_laplace_latex_(fname, args): |
| 1650 | r""" |
| 1651 | Return LaTeX expression for inverse Laplace transform of a symbolic function. |
| 1652 | |
| 1653 | EXAMPLES:: |
| 1654 | |
| 1655 | sage: import sage.misc.latex as latex_module |
| 1656 | sage: _inverse_laplace_latex_ = latex_module._inverse_laplace_latex_ |
| 1657 | sage: var('s,t') |
| 1658 | (s, t) |
| 1659 | sage: F(s) = function('F',s) |
| 1660 | sage: _inverse_laplace_latex_("ilt",(F(s),s,t)) |
| 1661 | '\\mathcal{L}^{-1}\\left(F\\left(s\\right), s, t\\right)' |
| 1662 | |
| 1663 | AUTHORS: |
| 1664 | |
| 1665 | - Golam Mortuza Hossain (2009-04-05) |
| 1666 | """ |
| 1667 | return "\\mathcal{L}^{-1}\\left(%s\\right)"%(', '.join([latex(x) for x in args])) |
| 1668 | |
| 1669 | def _laplace_latex_(fname, args): |
| 1670 | r""" |
| 1671 | Return LaTeX expression for Laplace transform of a symbolic function. |
| 1672 | |
| 1673 | EXAMPLES:: |
| 1674 | |
| 1675 | sage: import sage.misc.latex as latex_module |
| 1676 | sage: _laplace_latex_ = latex_module._laplace_latex_ |
| 1677 | sage: var('s,t') |
| 1678 | (s, t) |
| 1679 | sage: f(t) = function('f',t) |
| 1680 | sage: _laplace_latex_("laplace",(f(t),t,s)) |
| 1681 | '\\mathcal{L}\\left(f\\left(t\\right), t, s\\right)' |
| 1682 | |
| 1683 | AUTHORS: |
| 1684 | |
| 1685 | - Golam Mortuza Hossain (2009-04-05) |
| 1686 | """ |
| 1687 | return "\\mathcal{L}\\left(%s\\right)"%(', '.join([latex(x) for x in args])) |
| 1688 | |
| 1689 | def _limit_latex_(fname, args): |
| 1690 | r""" |
| 1691 | Return latex expression for limit of a symbolic function. |
| 1692 | |
| 1693 | EXAMPLES:: |
| 1694 | |
| 1695 | sage: import sage.misc.latex as latex_module |
| 1696 | sage: _limit_latex_ = latex_module._limit_latex_ |
| 1697 | sage: var('x,a') |
| 1698 | (x, a) |
| 1699 | sage: psi(x) = function('psi',x) |
| 1700 | sage: _limit_latex_("limit",(psi(x),x,a)) |
| 1701 | '\\lim_{x \\to a}\\, \\psi\\left(x\\right)' |
| 1702 | |
| 1703 | AUTHORS: |
| 1704 | |
| 1705 | - Golam Mortuza Hossain (2009-04-05) |
| 1706 | """ |
| 1707 | # We process only if there are precisely three arguments |
| 1708 | if len(args) == 3: |
| 1709 | # Read f,x,a from arguments |
| 1710 | f = args[0] |
| 1711 | x = args[1] |
| 1712 | a = args[2] |
| 1713 | return "\\lim_{%s \\to %s}\\, %s"%(latex(x), latex(a), latex(f)) |
| 1714 | # Return default typesetting |
| 1715 | return _symbolic_function_default_latex_(fname, args) |
| 1716 | |
| 1717 | def _conjugate_latex_(fname, args): |
| 1718 | r""" |
| 1719 | Return LaTeX expression for conjugate of a symbolic function. |
| 1720 | |
| 1721 | EXAMPLES:: |
| 1722 | |
| 1723 | sage: import sage.misc.latex as latex_module |
| 1724 | sage: _conjugate_latex_ = latex_module._conjugate_latex_ |
| 1725 | sage: var('x') |
| 1726 | x |
| 1727 | sage: psi(x) = function('psi',x) |
| 1728 | sage: _conjugate_latex_("conjugate",psi(x)) |
| 1729 | '\\overline{\\psi\\left(x\\right)}' |
| 1730 | |
| 1731 | AUTHORS: |
| 1732 | |
| 1733 | - Golam Mortuza Hossain (2009-06-11) |
| 1734 | """ |
| 1735 | # We process only if there is only one argument |
| 1736 | if len(args) == 1: |
| 1737 | return "\\overline{%s}"%(latex(args)) |
| 1738 | # Return default typesetting |
| 1739 | return _symbolic_function_default_latex_(fname, args) |
| 1740 | |
| 1741 | def latex_function_name(x): |
| 1742 | r""" |
| 1743 | Return common function names such as alpha, beta1, psi_00, R_mn, |
| 1744 | etc. as latex symbols, else return False. |
| 1745 | |
| 1746 | EXAMPLES:: |
| 1747 | |
| 1748 | sage: import sage.misc.latex as latex_module |
| 1749 | sage: latex_function_name = latex_module.latex_function_name |
| 1750 | sage: latex_function_name('psi') |
| 1751 | '\\psi' |
| 1752 | sage: latex_function_name('psi0') |
| 1753 | '\\psi_{0}' |
| 1754 | sage: latex_function_name('f1') |
| 1755 | 'f_{1}' |
| 1756 | sage: latex_function_name('psi_mu') |
| 1757 | '\\psi_{\\mu}' |
| 1758 | sage: latex_function_name('psi_11') |
| 1759 | '\\psi_{11}' |
| 1760 | sage: latex_function_name('R_ab') |
| 1761 | 'R_{ab}' |
| 1762 | sage: latex_function_name('R_nu') |
| 1763 | 'R_{\\nu}' |
| 1764 | sage: latex_function_name('myfunc') |
| 1765 | False |
| 1766 | sage: latex_function_name('psi_') |
| 1767 | False |
| 1768 | sage: latex_function_name('abc_xyz_psi') |
| 1769 | False |
| 1770 | sage: latex_function_name('abc_beta') |
| 1771 | False |
| 1772 | |
| 1773 | NOTES: |
| 1774 | |
| 1775 | This function is based largely on latex_variable_name function. |
| 1776 | |
| 1777 | AUTHORS: |
| 1778 | |
| 1779 | - Golam Mortuza Hossain (2009-04-05) |
| 1780 | """ |
| 1781 | # For known names return them after preprending with "\\" |
| 1782 | if x in common_varnames: |
| 1783 | return "\\" + x |
| 1784 | # Look for underscrore. If found then use its postion to |
| 1785 | # find the suffix |
| 1786 | underscore = x.find("_") |
| 1787 | if underscore == -1: |
| 1788 | import re |
| 1789 | # * The "\d|[.,]" means "decimal digit" or period or comma |
| 1790 | # * The "+" means "1 or more" |
| 1791 | # * The "$" means "at the end of the line" |
| 1792 | m = re.search('(\d|[.,])+$',x) |
| 1793 | if m is None: |
| 1794 | prefix = x |
| 1795 | suffix = None |
| 1796 | else: |
| 1797 | prefix = x[:m.start()] |
| 1798 | suffix = x[m.start():] |
| 1799 | else: |
| 1800 | prefix = x[:underscore] |
| 1801 | suffix = x[underscore+1:] |
| 1802 | if len(suffix)== 0: |
| 1803 | return False |
| 1804 | # If suffix contains underscores then don't process |
| 1805 | if suffix and suffix.find("_") != -1: |
| 1806 | return False |
| 1807 | # If prefix is not a common name or a more-than-one letters word |
| 1808 | # then don't process |
| 1809 | if prefix not in common_varnames and len(prefix) != 1: |
| 1810 | return False |
| 1811 | # Check if prefix or suffix is a common name |
| 1812 | if prefix in common_varnames: |
| 1813 | prefix = "\\" + prefix |
| 1814 | if suffix and len(suffix) > 0: |
| 1815 | if suffix in common_varnames: |
| 1816 | suffix = "\\" + suffix |
| 1817 | return '%s_{%s}'%(prefix, suffix) |
| 1818 | else: |
| 1819 | return '%s'%(prefix) |
| 1820 | |