Skip to content
Merged
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
2 changes: 1 addition & 1 deletion .github/workflows/pyodide.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,5 +58,5 @@ jobs:
python -m pip install --no-build-isolation -e git+https://github.com/Mathics3/mathics-scanner#egg=Mathics-Scanner

pip install --no-build-isolation -e .
make mathics/data/op-tables.json mathics/data/operator-tables.json
make mathics/data/character-tables.json mathics/data/operator-tables.json
make -j3 check
10 changes: 5 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -69,17 +69,17 @@ build:
# because pip install doesn't handle
# INSTALL_REQUIRES properly
#: Set up to run from the source tree
develop: mathics/data/op-tables.json mathics/data/operator-tables.json
develop: mathics/data/character-tables.json mathics/data/operator-tables.json
$(PIP) install -e .[dev]

# See note above on ./setup.py
#: Set up to run from the source tree with full dependencies
develop-full: mathics/data/op-tables.json mathics/data/operators.json
develop-full: mathics/data/character-tables.json mathics/data/operators.json
$(PIP) install -e .[dev,full]

# See note above on ./setup.py
#: Set up to run from the source tree with full dependencies and Cython
develop-full-cython: mathics/data/op-tables.json mathics/data/operators.json
develop-full-cython: mathics/data/character-tables.json mathics/data/operators.json
$(PIP) install -e .[dev,full,cython]


Expand Down Expand Up @@ -126,7 +126,7 @@ clean: clean-cython clean-cache
($(MAKE) -C "$$dir" clean); \
done; \
rm -f factorials || true; \
rm -f mathics/data/op-tables || true; \
rm -f mathics/data/character-tables.json || true; \
rm -rf build || true

mypy:
Expand Down Expand Up @@ -166,7 +166,7 @@ latexdoc texdoc doc:
(cd mathics/doc/latex && $(MAKE) doc)

#: Build JSON ASCII to unicode opcode table and operator table
mathics/data/operator-tables.json mathics/data/op-tables.json mathics/data/operators.json:
mathics/data/operator-tables.json mathics/data/character-tables.json mathics/data/operators.json:
$(BASH) ./admin-tools/make-JSON-tables.sh

#: Remove ChangeLog
Expand Down
11 changes: 1 addition & 10 deletions admin-tools/make-JSON-tables.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,7 @@ mydir=$(dirname $bs)
PYTHON=${PYTHON:-python}

cd $mydir/../mathics/data
mathics3-generate-json-table \
--field=latex-named-characters \
--field=unicode-to-latex \
--field=ascii-operator-to-symbol \
--field=ascii-operator-to-unicode \
--field=ascii-operator-to-wl-unicode \
--field=operator-to-ascii \
--field=operator-to-amslatex \
--field=operator-to-unicode \
-o op-tables.json
mathics3-generate-json-table -o character-tables.json
mathics3-generate-operator-json-table -o operator-tables.json
# tokenizer looks for the table in the default place...
mathics3-generate-operator-json-table
2 changes: 1 addition & 1 deletion mathics/builtin/atomic/strings.py
Original file line number Diff line number Diff line change
Expand Up @@ -876,7 +876,7 @@ class ToString(Builtin):
>> "U" <> ToString[2]
= U2
>> ToString[Integrate[f[x],x], TeXForm]
= \\int f\\left(x\\right) \\, dx
= \\int f(x) \\, dx

"""

Expand Down
2 changes: 1 addition & 1 deletion mathics/builtin/layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ class Format(Builtin):

Format can be used to specify the request format:
>> Format[Integrate[F[x], x], TeXForm]
= \\int F\\left(x\\right) \\, dx
= \\int F(x) \\, dx

Format evaluates its first element before applying the format:
>> Format[Integrate[Cos[x], x], TeXForm]
Expand Down
4 changes: 2 additions & 2 deletions mathics/builtin/list/associations.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ class Association(Builtin):
>> <|a -> x, b -> y|>
= <|a -> x, b -> y|>

>> Association[{a -> x, b -> y}]
= <|a -> x, b -> y|>
>> Association[{a -> x^2, b -> y}]
= <|a -> x ^ 2, b -> y|>

Associations can be nested:
>> <|a -> x, b -> y, <|a -> z, d -> t|>|>
Expand Down
4 changes: 2 additions & 2 deletions mathics/builtin/numbers/calculus.py
Original file line number Diff line number Diff line change
Expand Up @@ -1007,8 +1007,8 @@ class Integrate(SympyFunction):
= Integrate[1, {x, Infinity, 0}]

Here how is an example of converting integral equation to TeX:
>> Integrate[f[x], {x, a, b}] // TeXForm
= \int_a^b f\left(x\right) \, dx
>> Integrate[f[x^2], {x, a, b}] // TeXForm
= \int_a^b f\left(x^2\right) \, dx

Sometimes there is a loss of precision during integration.
You can check the precision of your result with the following sequence \
Expand Down
3 changes: 2 additions & 1 deletion mathics/core/convert/op.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@


# Load the conversion tables from disk
characters_path = osp.join(ROOT_DIR, "data", "op-tables.json")
characters_path = osp.join(ROOT_DIR, "data", "character-tables.json")
assert osp.exists(
characters_path
), f"ASCII operator to Unicode tables are missing from {characters_path}"
Expand All @@ -24,6 +24,7 @@

ascii_operator_to_symbol = OPERATOR_CONVERSION_TABLES["ascii-operator-to-symbol"]
builtin_constants = OPERATOR_CONVERSION_TABLES["builtin-constants"]
named_characters = OPERATOR_CONVERSION_TABLES["named-characters"]
operator_to_unicode = OPERATOR_CONVERSION_TABLES["operator-to-unicode"]
operator_to_ascii = OPERATOR_CONVERSION_TABLES["operator-to-ascii"]
unicode_operator_to_ascii = {
Expand Down
2 changes: 1 addition & 1 deletion mathics/data/.gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/.python-version
/doc_latex_data.pcl
/doctest_latex_data.pcl
/op-tables.json
/character-tables.json
/operator-tables.json
6 changes: 3 additions & 3 deletions mathics/doc/documentation/1-Manual.mdoc
Original file line number Diff line number Diff line change
Expand Up @@ -942,7 +942,7 @@ For instance, you can override 'MakeBoxes' to format lists in a different way:
= {1, 2, 3}

>> {1, 2, 3} // TeXForm
= \left[1 2 3\right]
= [1 2 3]

However, this will not be accepted as input to \Mathics anymore:
>> [1 2 3]
Expand Down Expand Up @@ -970,7 +970,7 @@ The desired effect can be achieved in the following way:
= squared[1, 2]

#> squared[1, 2] // TeXForm
= \text{squared}\left[1, 2\right]^2
= \text{squared}[1, 2]^2

You can view the box structure of a formatted expression using 'ToBoxes':

Expand Down Expand Up @@ -1115,7 +1115,7 @@ Three-dimensional plots are supported as well:
Here are some examples written by Jan Pöschko that come from the very first version.

<section title="Curve Sketching">
Let\'s sketch the function
Let's sketch the function
>> f[x_] := 4 x / (x ^ 2 + 3 x + 5)

The derivatives are:
Expand Down
2 changes: 1 addition & 1 deletion mathics/docpipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ def create_output(test_pipeline, tests):
if output_format in ("latex", "xml"):

def out_wrapper(expr):
return f"{expr} // StandardForm"
return f"StandardForm[{expr}]"

else:

Expand Down
119 changes: 111 additions & 8 deletions mathics/format/render/latex.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
LaTeX formatting is usually initiated in Mathics via TeXForm[].

TeXForm in WMA is slightly vague or misleading since the output is
typically LaTeX rather than Plain TeX. In Mathics, we also assume AMS
typically LaTeX rather than Plain TeX. In Mathics3, we also assume AMS
LaTeX or more specifically that we the additional AMS Mathematical
Symbols exist.
"""
Expand Down Expand Up @@ -37,6 +37,7 @@
UNICODE_TO_AMSLATEX,
UNICODE_TO_LATEX,
get_latex_operator,
named_characters,
)
from mathics.core.exceptions import BoxConstructError
from mathics.core.formatter import (
Expand All @@ -50,6 +51,71 @@
# mathics_scanner does not generates this table in a way that we can load it here.
# When it get fixed, we can use that table instead of this one:

BRACKET_INFO = {
(
String("("),
String(")"),
): {
"latex_open": "(",
"latex_closing": ")",
"latex_open_large": r"\left(",
"latex_closing_large": r"\right)",
},
(
String("{"),
String("}"),
): {
"latex_open": r"\{",
"latex_closing": r"\}",
"latex_open_large": r"\left\{",
"latex_closing_large": r"\right\}",
},
(
String("["),
String("]"),
): {
"latex_open": "[",
"latex_closing": "]",
"latex_open_large": r"\left[",
"latex_closing_large": r"\right]",
},
(
String(named_characters["LeftDoubleBracket"]),
String(named_characters["RightDoubleBracket"]),
): {
"latex_open": r"[[",
"latex_closing": "]]",
"latex_open_large": r"\left[\left[",
"latex_closing_large": r"\right]\right]",
},
(
String(named_characters["LeftAngleBracket"]),
String(named_characters["RightAngleBracket"]),
): {
"latex_open": "\\langle",
"latex_closing": "\\rangle",
"latex_open_large": r"\left\langle ",
"latex_closing_large": r"\right\rangle ",
},
(
String(named_characters["LeftDoubleBracketingBar"]),
String(named_characters["RightDoubleBracketingBar"]),
): {
"latex_open": r"\|",
"latex_closing": r"\|",
"latex_open_large": r"\left\|",
"latex_closing_large": r"\right\| ",
},
(
String("<|"),
String("|>"),
): {
"latex_open": r"\langle\vert ",
"latex_closing": r"\vert\rangle ",
"latex_open_large": r"\left\langle\left\vert ",
"latex_closing_large": r"\right\vert\right\rangle ",
},
}

TEX_REPLACE = {
"{": r"\{",
Expand Down Expand Up @@ -293,9 +359,9 @@ def superscriptbox(self, **options):

sup_string = self.superindex.get_string_value()
# Handle derivatives
if sup_string == "\u2032":
if sup_string == named_characters["Prime"]:
return "%s'" % tex1
if sup_string == "\u2032\u2032":
if sup_string == named_characters["Prime"] * 2:
return "%s''" % tex1
base = self.tex_block(tex1, True)
superidx_to_tex = lookup_conversion_method(self.superindex, "latex")
Expand Down Expand Up @@ -347,13 +413,10 @@ def subsuperscriptbox(self, **options):
add_conversion_fn(SubsuperscriptBox, subsuperscriptbox)


def rowbox(self, **options) -> str:
_options = self.box_options.copy()
_options.update(options)
options = _options
def rowbox_sequence(items, **options):
parts_str = [
lookup_conversion_method(element, "latex")(element, **options)
for element in self.items
for element in items
]
if len(parts_str) == 0:
return ""
Expand All @@ -378,6 +441,46 @@ def rowbox(self, **options) -> str:
return result


def rowbox_parenthesized(items, **options):
if len(items) < 2:
return None
key = (
items[0],
items[-1],
)
items = items[1:-1]
try:
bracket_data = BRACKET_INFO[key]
except KeyError:
return None

contain = rowbox_sequence(items, **options) if len(items) > 0 else ""

if any(item.is_multiline for item in items):
return f'{bracket_data["latex_open_large"]}{contain}{bracket_data["latex_closing_large"]}'
return f'{bracket_data["latex_open"]}{contain}{bracket_data["latex_closing"]}'


def rowbox(self, **options) -> str:
_options = self.box_options.copy()
_options.update(options)
options = _options
items = self.items
# Handle special cases
if len(items) >= 3:
head, *rest = items
rest_latex = rowbox_parenthesized(rest, **options)
if rest_latex is not None:
# Must be a function-like expression f[]
head_latex = lookup_conversion_method(head, "latex")(head, **options)
return head_latex + rest_latex
if len(items) >= 2:
parenthesized_latex = rowbox_parenthesized(items, **options)
if parenthesized_latex is not None:
return parenthesized_latex
return rowbox_sequence(items, **options)


add_conversion_fn(RowBox, rowbox)


Expand Down
12 changes: 3 additions & 9 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,21 +109,15 @@ def get_srcdir():

class build_py(setuptools_build_py):
def run(self):
if not os.path.exists("mathics/data/op-tables.json"):
if not os.path.exists("mathics/data/character-tables.json"):
os.system(
"mathics3-generate-json-table"
" --field=ascii-operator-to-symbol"
" --field=ascii-operator-to-unicode"
" --field=ascii-operator-to-wl-unicode"
" --field=operator-to-ascii"
" --field=operator-to-unicode"
" -o mathics/data/op-tables.json"
"mathics3-generate-json-table" " -o mathics/data/character-tables.json"
)
if not os.path.exists("mathics/data/operator-tables.json"):
os.system(
"mathics3-generate-operator-json-table" " -o operator-tables.json"
)
self.distribution.package_data["mathics"].append("data/op-tables.json")
self.distribution.package_data["mathics"].append("data/character-tables.json")
setuptools_build_py.run(self)


Expand Down
4 changes: 2 additions & 2 deletions test/doc/test_latex.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,8 @@ def test_load_latex_documentation():
r"\begin{testresult}o\end{testresult}\end{testcase}"
)
assert (
doc_in_section.latex(doc_data)[:40]
).strip() == "Let\\'s sketch the function\n\\begin{tests}"
doc_in_section.latex(doc_data)[:39]
).strip() == "Let's sketch the function\n\\begin{tests}"
assert (
first_section.latex(doc_data)[:30]
).strip() == "\\section{Curve Sketching}{}"
Expand Down
Loading
Loading