Repository: sympy/sympy
File: sympy/codegen/tests/test_fnodes.py (Python)

Code before:

def test_literal_dp():
    assert fcode(literal_dp(0), source_format='free') == '0d0'


def test_reshape():
    """Test reshape function with keyword arguments and essential edge cases."""
    from sympy.codegen.ast import String

    array, shape, pad, order = symbols('array shape pad order')

    cases = [
        (reshape(array, shape), 'reshape(array, shape)'),
        (reshape(array, shape, pad), 'reshape(array, shape, pad=pad)'),
        (reshape(array, shape, None, order), 'reshape(array, shape, order=order)'),
        (reshape(array, shape, pad, order), 'reshape(array, shape, pad=pad, order=order)'),
        (reshape(Symbol('a') + Symbol('b'), [Symbol('n') * 2]), 'reshape(a + b, [2*n])'),
        (reshape(array, shape, None, String('F')), 'reshape(array, shape, order=F)'),
        (reshape(array, [Symbol('n'), 3]), 'reshape(array, [n, 3])'),
    ]

    for expr, expected in cases:
        assert fcode(expr, source_format='free') == expected


def test_function_call_override():
    """Test that _print_FunctionCall override enables custom String processing.
    Demonstrates Fortran intrinsic name conflict resolution - a realistic use case
    where self._print(expr.name) enables custom processing vs expr.name directly.
    """
    from sympy.codegen.ast import FunctionCall
    from sympy.printing.fortran import FCodePrinter

    class ConflictResolver(FCodePrinter):
        def _print_String(self, expr):
            return str(expr) + '_user' if str(expr) in ['sin', 'max'] else str(expr)

    printer = ConflictResolver({'source_format': 'free'})

    assert printer._print(FunctionCall('sin', [Symbol('x')])) == 'sin_user(x)'
    assert printer._print(FunctionCall('max', [Symbol('a'), Symbol('b')])) == 'max_user(a, b)'
    assert printer._print(FunctionCall('safe_func', [Symbol('x')])) == 'safe_func(x)'


@may_xfail
def test_bind_C():
    if not has_fortran():
        skip("No fortran compiler found.")
    if not cython:
        skip("Cython not found.")
    if not np:

Review comment (suggestion):
Sorry, I don't think this constitutes a plausible use case. I'm open for an overload, or a change to the method on the base class, but we need a test that makes use of the change and is not overly contrived.

Code after:

def test_literal_dp():
    assert fcode(literal_dp(0), source_format='free') == '0d0'


def test_reshape():
    """Test reshape function with keyword arguments and essential edge cases."""
    from sympy.codegen.ast import String

    array, shape, pad, order = symbols('array shape pad order')

    cases = [
        (reshape(array, shape), 'reshape(array, shape)'),
        (reshape(array, shape, pad), 'reshape(array, shape, pad=pad)'),
        (reshape(array, shape, None, order), 'reshape(array, shape, order=order)'),
        (reshape(array, shape, pad, order), 'reshape(array, shape, pad=pad, order=order)'),
        (reshape(Symbol('a') + Symbol('b'), [Symbol('n') * 2]), 'reshape(a + b, [2*n])'),
        (reshape(array, shape, None, String('F')), 'reshape(array, shape, order=F)'),
        (reshape(array, [Symbol('n'), 3]), 'reshape(array, [n, 3])'),
    ]

    for expr, expected in cases:
        assert fcode(expr, source_format='free') == expected


@may_xfail
def test_bind_C():
    if not has_fortran():
        skip("No fortran compiler found.")
    if not cython:
        skip("Cython not found.")
    if not np:
        skip("NumPy not found.")

    a = Symbol('a', real=True)
    s = Symbol('s', integer=True)
    body = [Return((sum_(a**2)/s)**.5)]
    arr = array(a, dim=[s], intent='in')
    fd = FunctionDefinition(real, 'rms', [arr, s], body, attrs=[bind_C('rms')])
    f_mod = render_as_module([fd], 'mod_rms')

    with tempfile.TemporaryDirectory() as folder:
        mod, info = compile_link_import_strings([
            ('rms.f90', f_mod),
            ('_rms.pyx', (
                "#cython: language_level={}\n".format("3") +
                "cdef extern double rms(double*, int*)\n"
                "def py_rms(double[::1] x):\n"
                "    cdef int s = x.size\n"
                "    return rms(&x[0], &s)\n"))
        ], build_dir=folder)