ronantakizawa/codereview-bench huggingface dataset:
Repository: sympy/sympy
File: sympy/functions/elementary/integers.py (Python)

Code before:
    >>> floor(-I/2)
    -I
    >>> floor(S(5)/2 + 5*I/2)
    2 + 2*I

    See Also
    ========

    sympy.functions.elementary.integers.ceiling

    References
    ==========

    .. [1] "Concrete mathematics" by Graham, pp. 87
    .. [2] https://mathworld.wolfram.com/FloorFunction.html

    """
    _dir = -1

    @classmethod
    def _eval_number(cls, arg):
        if arg.is_Number:
            return arg.floor()
        if (arg_eval := arg.evalf()).is_Float:
            if abs(arg_eval - (f := arg_eval.floor())) > 1e-10:
                return f
        if any(isinstance(i, j)
                for i in (arg, -arg) for j in (floor, ceiling)):
            return arg
        if arg.is_NumberSymbol:
            return arg.approximation_interval(Integer)[0]

    @classmethod
    def _eval_const_number(cls, arg):
        if arg.is_real:
            if arg.is_zero:
                return S.Zero
            if arg.is_positive:
                num, den = arg.as_numer_denom()
                s = den.is_negative
                if s is None:
                    return None
                if s:
                    num, den = -num, -den
                # 0 <= num/den < 1 -> 0
                if is_lt(num, den):
                    return S.Zero
                # 1 <= num/den < 2 -> 1
                if fuzzy_and([is_le(den, num), is_lt(num, 2*den)]):
                    return S.One
            if arg.is_negative:

Review comment (suggestion):
I think there should be a better way here rather than using an arbitrary `1e-10` threshold.

There is a function `evalf_floor` in evalf.py for doing this.

Code after:
    >>> floor(-I/2)
    -I
    >>> floor(S(5)/2 + 5*I/2)
    2 + 2*I

    See Also
    ========

    sympy.functions.elementary.integers.ceiling

    References
    ==========

    .. [1] "Concrete mathematics" by Graham, pp. 87
    .. [2] https://mathworld.wolfram.com/FloorFunction.html

    """
    _dir = -1

    @classmethod
    def _eval_number(cls, arg):
        if arg.is_Number:
            return arg.floor()
        if any(isinstance(i, j)
                for i in (arg, -arg) for j in (floor, ceiling)):
            return arg
        if arg.is_NumberSymbol:
            return arg.approximation_interval(Integer)[0]

    @classmethod
    def _eval_const_number(cls, arg):
        if arg.is_real:
            if arg.is_zero:
                return S.Zero
            if arg.is_positive:
                num, den = arg.as_numer_denom()
                s = den.is_negative
                if s is None:
                    return None
                if s:
                    num, den = -num, -den
                # 0 <= num/den < 1 -> 0
                if is_lt(num, den):
                    return S.Zero
                # 1 <= num/den < 2 -> 1
                if fuzzy_and([is_le(den, num), is_lt(num, 2*den)]):
                    return S.One
            if arg.is_negative:
                num, den = arg.as_numer_denom()
                s = den.is_negative
                if s is None:
Repository: sympy/sympy
File: sympy/simplify/fu.py (Python)

Code before:
from collections import defaultdict
try:
    from functools import cache
except ImportError:
    # Python 3.8
    from functools import lru_cache as cache

from sympy.core.add import Add
from sympy.core.expr import Expr
from sympy.core.exprtools import Factors, gcd_terms, factor_terms
from sympy.core.function import expand_mul
from sympy.core.mul import Mul
from sympy.core.numbers import pi, I
from sympy.core.power import Pow
from sympy.core.singleton import S
from sympy.core.sorting import ordered
from sympy.core.symbol import Dummy
from sympy.core.sympify import sympify
from sympy.core.traversal import bottom_up
from sympy.functions.combinatorial.factorials import binomial
from sympy.functions.elementary.hyperbolic import (
    cosh, sinh, tanh, coth, sech, csch, HyperbolicFunction)
from sympy.functions.elementary.trigonometric import (
    cos, sin, tan, cot, sec, csc, sqrt, TrigonometricFunction)
from sympy.ntheory.factor_ import perfect_power
from sympy.polys.polytools import factor
from sympy.strategies.tree import greedy
from sympy.strategies.core import identity, debug

Review comment (performance):
Wouldn't it be better to use `sympy.core.cache.cacheit`?

Code after:
from collections import defaultdict

from sympy.core.add import Add
from sympy.core.cache import cacheit
from sympy.core.expr import Expr
from sympy.core.exprtools import Factors, gcd_terms, factor_terms
from sympy.core.function import expand_mul
from sympy.core.mul import Mul
from sympy.core.numbers import pi, I
from sympy.core.power import Pow
from sympy.core.singleton import S
from sympy.core.sorting import ordered
from sympy.core.symbol import Dummy
from sympy.core.sympify import sympify
from sympy.core.traversal import bottom_up
from sympy.functions.combinatorial.factorials import binomial
from sympy.functions.elementary.hyperbolic import (
    cosh, sinh, tanh, coth, sech, csch, HyperbolicFunction)
from sympy.functions.elementary.trigonometric import (
    cos, sin, tan, cot, sec, csc, sqrt, TrigonometricFunction)
from sympy.ntheory.factor_ import perfect_power
from sympy.polys.polytools import factor
from sympy.strategies.tree import greedy
from sympy.strategies.core import identity, debug

from sympy import SYMPY_DEBUG
Repository: sympy/sympy
File: sympy/solvers/tests/test_solvers.py (Python)

Code before:
        (100 - 30*x, (x >= 2) & (x >= 4) & (x < 10)),
        (30*x - 3*(x - 6)**2/2 - 196, (x>= 0) & (x >= 4) & (x >= 6) & (x < 10)),
        (80 - 16*x, (x >= 0) & (x >= 4) & (x < 10)),
        (26*x - 3*(x - 6)**2/2 - 196, (x >= 4) & (x >= 6) & (x < 10)),
        (80 - 20*x, (x >= 4) & (x < 10)),
        (40*x - 3*(x - 6)**2/2 - 256, (x >= 0) & (x >= 2) & (x >= 6) & (x < 10)),
        (20 - 6*x, (x >= 0) & (x >= 2) & (x < 10)),
        (36*x - 3*(x - 6)**2/2 - 256, (x >= 2) & (x >= 6) & (x < 10)),
        (20 - 10*x, (x >= 2) & (x < 10)),
        (50*x - 3*(x - 6)**2/2 - 276, (x >= 0) & (x >= 6) & (x < 10)),
        (4*x, (x >= 0) & (x < 10)),
        (46*x - 3*(x - 6)**2/2 - 276, (x >= 6) & (x < 10)),
        (0, x < 10),  # this will simplify away
        (S.NaN,True)))


def test_issue_27854():
    # https://github.com/sympy/sympy/issues/27854
    m, n = symbols("m n")
    A = MatrixSymbol("A", m, n)
    x = MatrixSymbol("x", n, 1)
    b = MatrixSymbol('b', m, 1)
    r = A * x - b
    f = r.T * r
    grad_f = f.diff(x)
    raises(ValueError, lambda: grad_f.as_explicit())


Review comment (suggestion):
This should be testing what happens with `solve`. Ideally find where there are any existing tests for `solve` with a `Matrix` as input and then add a test for this along with the other tests.

Code after:
    s2 = Symbol('s2', integer=True, positive=True)
    f = floor(s2/2 - S(1)/2)
    raises(NotImplementedError, lambda: solve((Mod(f**2/(f + 1) + 2*f/(f + 1) + 1/(f + 1), 1))*f + Mod(f**2/(f + 1) + 2*f/(f + 1) + 1/(f + 1), 1), s2))


def test_solve_Piecewise():
    assert [S(10)/3] == solve(3*Piecewise(
        (S.NaN, x <= 0),
        (20*x - 3*(x - 6)**2/2 - 176, (x >= 0) & (x >= 2) & (x>= 4) & (x >= 6) & (x < 10)),
        (100 - 26*x, (x >= 0) & (x >= 2) & (x >= 4) & (x < 10)),
        (16*x - 3*(x - 6)**2/2 - 176, (x >= 2) & (x >= 4) & (x >= 6) & (x < 10)),
        (100 - 30*x, (x >= 2) & (x >= 4) & (x < 10)),
        (30*x - 3*(x - 6)**2/2 - 196, (x>= 0) & (x >= 4) & (x >= 6) & (x < 10)),
        (80 - 16*x, (x >= 0) & (x >= 4) & (x < 10)),
        (26*x - 3*(x - 6)**2/2 - 196, (x >= 4) & (x >= 6) & (x < 10)),
        (80 - 20*x, (x >= 4) & (x < 10)),
        (40*x - 3*(x - 6)**2/2 - 256, (x >= 0) & (x >= 2) & (x >= 6) & (x < 10)),
        (20 - 6*x, (x >= 0) & (x >= 2) & (x < 10)),
        (36*x - 3*(x - 6)**2/2 - 256, (x >= 2) & (x >= 6) & (x < 10)),
        (20 - 10*x, (x >= 2) & (x < 10)),
        (50*x - 3*(x - 6)**2/2 - 276, (x >= 0) & (x >= 6) & (x < 10)),
        (4*x, (x >= 0) & (x < 10)),
        (46*x - 3*(x - 6)**2/2 - 276, (x >= 6) & (x < 10)),
        (0, x < 10),  # this will simplify away
        (S.NaN,True)))
Repository: sympy/sympy
File: sympy/printing/aesaracode.py (Python)

Code before:
    ==========

    expr : sympy.core.expr.Expr
        SymPy expression object to convert.

    cache : dict
        Cached Aesara variables (see :class:`AesaraPrinter.cache
        <AesaraPrinter>`). Defaults to the module-level global cache.

    dtypes : dict
        Passed to :meth:`.AesaraPrinter.doprint`.

    broadcastables : dict
        Passed to :meth:`.AesaraPrinter.doprint`.

    Returns
    =======

    aesara.graph.basic.Variable
        A variable corresponding to the expression's value in a Aesara symbolic
        expression graph.

    """
    sympy_deprecation_warning(
        """
        The Aesara Code printing is deprecated.
        """,
        deprecated_since_version="1.14",
        active_deprecations_target='deprecated-aesaraprinter',
    )

    if not aesara:
        raise ImportError("aesara is required for aesara_code")

    if cache is None:
        cache = global_cache

    return AesaraPrinter(cache=cache, settings={}).doprint(expr, **kwargs)


def dim_handling(inputs, dim=None, dims=None, broadcastables=None):
    r"""
    Get value of ``broadcastables`` argument to :func:`.aesara_code` from
    keyword arguments to :func:`.aesara_function`.

    Included for backwards compatibility.

    Parameters
    ==========

    inputs

Review comment (suggestion):
This should say that the `aesara_code` function is deprecated.

Code after:
    ==========

    expr : sympy.core.expr.Expr
        SymPy expression object to convert.

    cache : dict
        Cached Aesara variables (see :class:`AesaraPrinter.cache
        <AesaraPrinter>`). Defaults to the module-level global cache.

    dtypes : dict
        Passed to :meth:`.AesaraPrinter.doprint`.

    broadcastables : dict
        Passed to :meth:`.AesaraPrinter.doprint`.

    Returns
    =======

    aesara.graph.basic.Variable
        A variable corresponding to the expression's value in a Aesara symbolic
        expression graph.

    """
    sympy_deprecation_warning(
        """
        The aesara_code function is deprecated.
        """,
        deprecated_since_version="1.14",
        active_deprecations_target='deprecated-aesaraprinter',
    )

    if not aesara:
        raise ImportError("aesara is required for aesara_code")

    if cache is None:
        cache = global_cache

    return AesaraPrinter(cache=cache, settings={}).doprint(expr, **kwargs)


def dim_handling(inputs, dim=None, dims=None, broadcastables=None):
    r"""
    Get value of ``broadcastables`` argument to :func:`.aesara_code` from
    keyword arguments to :func:`.aesara_function`.

    Included for backwards compatibility.

    Parameters
    ==========

    inputs
Repository: sympy/sympy
File: sympy/core/numbers.py (Python)

Code before:
            Q *= q.p
        else:
            Q *= int(q)
        q = Q

        if gcd is not None:
            sympy_deprecation_warning(
                "gcd is deprecated in Rational, use nsimplify instead",
                deprecated_since_version="1.11",
                active_deprecations_target="deprecated-rational-gcd",
                stacklevel=4,
            )
            return cls._new(p, q, gcd)

        # p and q are now ints
        return cls._new(p, q)

    @classmethod
    def _new(cls, p, q, gcd=None):
        if q == 0:
            if p == 0:
                if _errdict["divide"]:
                    raise ValueError("Indeterminate 0/0")
                else:
                    return S.NaN
            return S.ComplexInfinity

        if q < 0:
            q = -q
            p = -p

        if gcd is None:
            gcd = igcd(abs(p), q)

        if gcd > 1:
            p //= gcd
            q //= gcd
        if q == 1:
            return Integer(p)
        if p == 1 and q == 2:
            return S.Half

        obj = Expr.__new__(cls)
        obj.p = p
        obj.q = q
        return obj

    def limit_denominator(self, max_denominator=1000000):
        """Closest Rational to self with denominator at most max_denominator.

        Examples

Review comment (suggestion):
This nan/zoo handling is also something that needs to be cleaned up for e.g. static typing. This should be handled in Mul rather than in the Rational constructor which should only ever return a valid Rational or raise an error.

Code after:
            Q *= q.p
        else:
            Q *= int(q)
        q = Q

        if gcd is not None:
            sympy_deprecation_warning(
                "gcd is deprecated in Rational, use nsimplify instead",
                deprecated_since_version="1.11",
                active_deprecations_target="deprecated-rational-gcd",
                stacklevel=4,
            )
            return cls._new(p, q, gcd)

        # p and q are now ints
        return cls._new(p, q)

    @classmethod
    def _new(cls, p, q, gcd=None):
        if q == 0:
            if p == 0:
                if _errdict["divide"]:
                    raise ValueError("Indeterminate 0/0")
                else:
                    return S.NaN
            return S.ComplexInfinity

        if q < 0:
            q = -q
            p = -p

        if gcd is None:
            gcd = igcd(abs(p), q)

        if gcd > 1:
            p //= gcd
            q //= gcd

        return cls.from_coprime_ints(p, q)

    @classmethod
    def from_coprime_ints(cls, p: int, q: int) -> Rational:
        """Create a Rational from a pair of coprime integers.

        Both ``p`` and ``q`` should be strictly of type ``int``.

        The caller should ensure that ``gcd(p,q) == 1`` and ``q > 0``.

        This may be more efficient than ``Rational(p, q)``. The validity of the
        arguments may or may not be checked so it should not be relied upon to
        pass unvalidated or invalid arguments to this function.
Repository: sympy/sympy
File: sympy/physics/control/routh_table.py (Python)

Code before:
from sympy.matrices.dense import MutableDenseMatrix
from sympy.polys import Poly
from sympy.polys.polytools  import cancel
from sympy import symbols, Symbol
from sympy.logic.boolalg import false, true
from sympy.series import limit
from sympy.solvers.inequalities import reduce_inequalities

__all__ = ['RouthHurwitz', 'neg_roots_conds']

def neg_roots_conds(polynomial: Poly):
    """
    Returns the conditions for a polynomial to have all its roots with
    negative real parts.

    Examples
    ========

    >>> from sympy.physics.control import neg_roots_conds
    >>> from sympy import symbols, Poly
    >>> s = symbols('s')
    >>> p1 = Poly((s+1)*(s+2)*(s+2.5), s)
    >>> neg_roots_conds(p1)
    [True]
    >>> k = symbols('k')
    >>> p2 = Poly((s+1)*(s+k), s)
    >>> neg_roots_conds(p2)
    [k + 1 > 0, k > 0]
    >>> a = symbols('a', negative = True)
    >>> p3 = Poly((s+1)*(s+a), s)
    >>> neg_roots_conds(p3)
    [a + 1 > 0, False]

    """
    coeffs = polynomial.all_coeffs()


Review comment (suggestion):
Maybe this shouldn't be a public function if it requires a Poly. Poly objects are not used by the average user, but they are very likely to have an expression that happens to be a polynomial.

Code after:
from sympy.matrices.dense import MutableDenseMatrix
from sympy.polys import Poly
from sympy import Symbol
from sympy.logic.boolalg import true, false

__all__ = ['RouthHurwitz', 'negative_real_part_conditions']

def negative_real_part_conditions(polynomial, var, /, *, domain=None):
    """
    Returns a list of conditions for a polynomial to have all its roots with
    negative real parts.

    Note: This method assumes that the leading coefficient is non-zero.
    In the opposite case, additional verification is required.

    Parameters
    ==========

    polynomial : Expr, Number
        The polynomial whose roots are to be analyzed.
    var : Symbol, None, optional
        The symbol representing the variable in the polynomial.
    domain : None, Domain, optional
        The domain in which the polynomial is defined.

    Returns
    =======

    list[StrictGreaterThan | Boolean]
        A list of conditions that must be satisfied for the polynomial to
        have all its roots with negative real parts.

    Examples
    ========

    >>> from sympy.physics.control import negative_real_part_conditions
Repository: sympy/sympy
File: sympy/physics/continuum_mechanics/tests/test_beam.py (Python)

Code before:
from sympy.core.function import expand
from sympy.core.numbers import (Rational, pi)
from sympy.core.singleton import S
from sympy.core.symbol import (Symbol, symbols)
from sympy.sets.sets import Interval
from sympy.simplify.simplify import simplify
from sympy.physics.continuum_mechanics.beam import Beam
from sympy.functions import SingularityFunction, Piecewise, meijerg, Abs, log,sqrt,factorial
from sympy.testing.pytest import raises
from sympy.physics.units import meter, newton, kilo, giga, milli
from sympy.physics.continuum_mechanics.beam import Beam3D
from sympy.geometry import Circle, Polygon, Point2D, Triangle
from sympy.core.sympify import sympify

x = Symbol('x')
y = Symbol('y')
R1, R2 = symbols('R1, R2')


def test_Beam():
    E = Symbol('E')
    E_1 = Symbol('E_1')
    I = Symbol('I')
    I_1 = Symbol('I_1')
    A = Symbol('A')

    b = Beam(1, E, I)
    assert b.length == 1
    assert b.elastic_modulus == E
    assert b.second_moment == I
    assert b.variable == x

    # Test the length setter

Review comment (suggestion):
There should be a space after comma here. I don't know why you have deleted it. Please see PEP 8:
https://peps.python.org/pep-0008/

Code after:
from sympy.core.function import expand
from sympy.core.numbers import (Rational, pi)
from sympy.core.singleton import S
from sympy.core.symbol import (Symbol, symbols)
from sympy.sets.sets import Interval
from sympy.simplify.simplify import simplify
from sympy.physics.continuum_mechanics.beam import Beam
from sympy.functions import SingularityFunction, Piecewise, meijerg, Abs, log, sqrt, factorial
from sympy.testing.pytest import raises
from sympy.physics.units import meter, newton, kilo, giga, milli
from sympy.physics.continuum_mechanics.beam import Beam3D
from sympy.geometry import Circle, Polygon, Point2D, Triangle
from sympy.core.sympify import sympify

x = Symbol('x')
y = Symbol('y')
R1, R2 = symbols('R1, R2')


def test_Beam():
    E = Symbol('E')
    E_1 = Symbol('E_1')
    I = Symbol('I')
    I_1 = Symbol('I_1')
    A = Symbol('A')

    b = Beam(1, E, I)
    assert b.length == 1
    assert b.elastic_modulus == E
    assert b.second_moment == I
    assert b.variable == x

    # Test the length setter
Repository: sympy/sympy
File: sympy/matrices/expressions/blockmatrix.py (Python)

Code before:
    >>> n, m, l = symbols('n m l')
    >>> X = MatrixSymbol('X', n, n)
    >>> Y = MatrixSymbol('Y', m, m)
    >>> BlockDiagMatrix(X, Y)
    Matrix([
    [X, 0],
    [0, Y]])

    Notes
    =====

    If you want to get the individual diagonal blocks, use
    :meth:`get_diag_blocks`.

    See Also
    ========

    sympy.matrices.dense.diag
    """
    def __new__(cls, *mats):
        # Validate that all arguments are matrix-like objects
        for mat in mats:
            if not hasattr(mat, 'rows') or not hasattr(mat, 'cols'):
                raise ValueError(
                    f"BlockDiagMatrix requires matrix-like objects with 'rows' and 'cols' "
                    f"attributes. Got {type(mat).__name__} with value {mat}")
        return Basic.__new__(BlockDiagMatrix, *[_sympify(m) for m in mats])

    @property
    def diag(self):
        return self.args

    @property
    def blocks(self):
        from sympy.matrices.immutable import ImmutableDenseMatrix
        mats = self.args
        data = [[mats[i] if i == j else ZeroMatrix(mats[i].rows, mats[j].cols)
                        for j in range(len(mats))]
                        for i in range(len(mats))]
        return ImmutableDenseMatrix(data, evaluate=False)

    @property
    def shape(self):
        return (sum(block.rows for block in self.args),
                sum(block.cols for block in self.args))

    @property
    def blockshape(self):
        n = len(self.args)
        return (n, n)


Review comment (suggestion):
I think that we should check class instead of `hasattr`. You should first sympify input with `mats = [_sympify(m) for m in mats]` and use `isinstance(mat, MatrixExpr)`.

Code after:
    >>> n, m, l = symbols('n m l')
    >>> X = MatrixSymbol('X', n, n)
    >>> Y = MatrixSymbol('Y', m, m)
    >>> BlockDiagMatrix(X, Y)
    Matrix([
    [X, 0],
    [0, Y]])

    Notes
    =====

    If you want to get the individual diagonal blocks, use
    :meth:`get_diag_blocks`.

    See Also
    ========

    sympy.matrices.dense.diag
    """
    def __new__(cls, *mats):
        mats = [_sympify(m) for m in mats]
        for mat in mats:
            if not isinstance(mat, MatrixExpr):
                raise ValueError(
                    f"BlockDiagMatrix requires matrix-like objects. "
                    f"Got {type(mat).__name__} with value {mat}")
        return Basic.__new__(BlockDiagMatrix, *mats)

    @property
    def diag(self):
        return self.args

    @property
    def blocks(self):
        from sympy.matrices.immutable import ImmutableDenseMatrix
        mats = self.args
        data = [[mats[i] if i == j else ZeroMatrix(mats[i].rows, mats[j].cols)
                        for j in range(len(mats))]
                        for i in range(len(mats))]
        return ImmutableDenseMatrix(data, evaluate=False)

    @property
    def shape(self):
        return (sum(block.rows for block in self.args),
                sum(block.cols for block in self.args))

    @property
    def blockshape(self):
        n = len(self.args)
        return (n, n)
Repository: sympy/sympy
File: sympy/parsing/tests/test_latex.py (Python)

Code before:
    r"a // b",
    r"a +",
    r"1.1.1",
    r"1 +",
    r"a / b /",
]

@XFAIL
def test_failing_not_parseable():
    from sympy.parsing.latex import parse_latex, LaTeXParsingError
    for latex_str in FAILING_BAD_STRINGS:
        with raises(LaTeXParsingError):
            parse_latex(latex_str)

# In strict mode, FAILING_BAD_STRINGS would fail
def test_strict_mode():
    from sympy.parsing.latex import parse_latex, LaTeXParsingError
    for latex_str in FAILING_BAD_STRINGS:
        with raises(LaTeXParsingError):
            parse_latex(latex_str, strict=True)

def test_latex_cases_environment_error():
    from sympy.parsing.latex import parse_latex, LaTeXParsingError
    import pytest
    latex_string = r"\begin{cases} x=1 \\ y=2 \end{cases}"
    with pytest.raises(LaTeXParsingError, match="The 'cases' environment is not currently supported"):
        parse_latex(latex_string)


Review comment (suggestion):
I don't think we should be importing pytest like this. We should probably use the `sympy/testing/pytest.py` file.

Code after:
    r"a // b",
    r"a +",
    r"1.1.1",
    r"1 +",
    r"a / b /",
]

@XFAIL
def test_failing_not_parseable():
    from sympy.parsing.latex import parse_latex, LaTeXParsingError
    for latex_str in FAILING_BAD_STRINGS:
        with raises(LaTeXParsingError):
            parse_latex(latex_str)

# In strict mode, FAILING_BAD_STRINGS would fail
def test_strict_mode():
    from sympy.parsing.latex import parse_latex, LaTeXParsingError
    for latex_str in FAILING_BAD_STRINGS:
        with raises(LaTeXParsingError):
            parse_latex(latex_str, strict=True)

def test_latex_cases_environment_error():
    from sympy.parsing.latex import parse_latex, LaTeXParsingError
    from sympy.testing.pytest import raises
    latex_string = r"\begin{cases} x=1 \\ y=2 \end{cases}"
    with raises(LaTeXParsingError, match="The 'cases' environment is not currently supported"):
        parse_latex(latex_string)