Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions app/preview_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,47 @@ def test_laplace_transforms(self, response, is_latex, latex, sympy):
assert result["preview"]["latex"] == latex
assert result["preview"]["sympy"] == sympy

@pytest.mark.parametrize(
"response, latex, sympy", [
# summation() with explicit bounds — rendered correctly by SymPy
(
'summation((4/n**2)(-1)**n cos(nx), (n, 1, oo))',
r'\sum_{n=1}^{\infty} \frac{4 \cdot \left(-1\right)^{n} \cdot \cos{\left(n \cdot x \right)}}{n^{2}}',
'summation((4/n**2)(-1)**n cos(nx), (n, 1, oo))',
),
# infsum as a custom prefix symbol — content must appear inside the sum, not outside
(
'infsum((-1)^n / n^2)',
r'\sum_{n=1}^{\infty} \frac{\left(-1\right)^{n}}{n^{2}}',
'infsum((-1)^n / n^2)',
),
(
'infsum((4/n^2)*(-1)^n*cos(nx))',
r'\sum_{n=1}^{\infty} \frac{4 \cdot \left(-1\right)^{n} \cdot \cos{\left(n \cdot x \right)}}{n^{2}}',
'infsum((4/n^2)*(-1)^n* cos(nx))',
),
(
'((pi^2)/(3))+infsum((4/n^2)*(-1)^n*cos(nx))',
r'\frac{\pi^{2}}{3} + \sum_{n=1}^{\infty} \frac{4 \cdot \left(-1\right)^{n} \cdot \cos{\left(n \cdot x \right)}}{n^{2}}',
'(( pi^2)/(3))+infsum((4/n^2)*(-1)^n* cos(nx))',
),
]
)
def test_sum_preview(self, response, latex, sympy):
params = {
"is_latex": False,
"strict_syntax": False,
"elementary_functions": True,
"symbols": {
"infsum": {"aliases": [], "latex": "\\sum_{n=1}^{\\infty}"},
"pi": {"aliases": [], "latex": "\\pi"},
},
}

result = preview_function(response, params)
assert result["preview"]["latex"] == latex
assert result["preview"]["sympy"] == sympy



if __name__ == "__main__":
Expand Down
25 changes: 18 additions & 7 deletions app/utility/expression_utilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -561,22 +561,33 @@ class SymbolData(TypedDict):
r"(?P<start>\\\(|\$\$|\$)(?P<latex>.*?)(?P<end>\\\)|\$\$|\$)"
)

BIG_OPERATOR_PREFIXES = (r"\sum", r"\int", r"\prod", r"\lim", r"\bigcup", r"\bigcap")


def sympy_symbols(symbols):
"""Create a mapping of local variables for parsing sympy expressions.

Args:
symbols (SymbolDict): A dictionary of sympy symbol strings to LaTeX
symbol strings.

Note:
Only the sympy string is used in this function.
symbol strings, or an iterable of symbol name strings.

Returns:
Dict[str, Symbol]: A dictionary of sympy symbol strings to sympy
Symbol objects.
Dict[str, Symbol | type]: A dictionary mapping symbol names to SymPy
Symbol objects, or to Function subclasses for prefix operator symbols
(those whose latex begins with a big operator command like \\sum).
"""
return {k: Symbol(k) for k in symbols}
result = {}
for k in symbols:
symbol_def = symbols[k] if isinstance(symbols, dict) else None
if isinstance(symbol_def, dict):
latex = extract_latex(symbol_def.get("latex", "")).strip()
if any(latex.startswith(op) for op in BIG_OPERATOR_PREFIXES):
def _latex(self, printer, _l=latex):
return _l + " " + printer.doprint(self.args[0])
result[k] = type(k, (Function,), {"_latex": _latex})
continue
result[k] = Symbol(k)
return result


def extract_latex(symbol):
Expand Down
Loading