def numbafy(fn, args, compiler="<STR_LIT>", **nbkws):
kwargs = {}    <EOL>if not isinstance(args, (tuple, list)):<EOL><INDENT>args = (args, )<EOL><DEDENT>if isinstance(compiler, six.string_types):<EOL><INDENT>compiler_ = getattr(nb, compiler, None)<EOL>if compiler is None:<EOL><INDENT>raise AttributeError("<STR_LIT>".format(compiler))<EOL><DEDENT>compiler = compiler_<EOL><DEDENT>if compiler in (nb.jit, nb.njit, nb.autojit):<EOL><INDENT>kwargs.update(jitkwargs)<EOL>sig = nbkws.pop("<STR_LIT>", None)<EOL><DEDENT>else:<EOL><INDENT>kwargs.update(veckwargs)<EOL>sig = nbkws.pop("<STR_LIT>", None)<EOL>if sig is None:<EOL><INDENT>warn("<STR_LIT>")<EOL><DEDENT><DEDENT>kwargs.update(nbkws)<EOL>if isinstance(fn, sy.Expr):<EOL><INDENT>fn = sy.expand_func(fn)<EOL><DEDENT>func = sy.lambdify(args, fn, modules='<STR_LIT>')<EOL>if sig is None:<EOL><INDENT>try:<EOL><INDENT>func = compiler(**kwargs)(func)<EOL><DEDENT>except RuntimeError:<EOL><INDENT>kwargs['<STR_LIT>'] = False<EOL>func = compiler(**kwargs)(func)<EOL><DEDENT><DEDENT>else:<EOL><INDENT>try:<EOL><INDENT>func = compiler(sig, **kwargs)(func)<EOL><DEDENT>except RuntimeError:<EOL><INDENT>kwargs['<STR_LIT>'] = False<EOL>func = compiler(sig, **kwargs)(func)<EOL><DEDENT><DEDENT>return func<EOL>
Compile a string, sympy expression or symengine expression using numba.

Not all functions are supported by Python's numerical package (numpy). For
difficult cases, valid Python code (as string) may be more suitable than
symbolic expressions coming from sympy, symengine, etc. When compiling
vectorized functions, include valid signatures (see `numba`_ documentation).

Args:
    fn: Symbolic expression as sympy/symengine expression or string
    args (iterable): Symbolic arguments
    compiler: String name or callable numba compiler
    nbkws: Compiler keyword arguments (if none provided, smart defaults are used)

Returns:
    func: Compiled function

Warning:
    For vectorized functions, valid signatures are (almost always) required.