import numpy                as    np
import sympy                as    sp
from   sympy                import latex
from IPython.display import Math, display as ipy_display

def display(obj, name=None, evalf=False, prec=5, mathrm=False):
    """
    Converts vectors/numbers/matrices to LaTeX with optional simplification using internal helpers.

    Parameters:
        obj     : Input (SymPy or NumPy object)
        name    : Name used for display
        evalf   : If True, evaluates to decimal form before display (default: False)
        prec    : Evaluate the given formula to an accuracy of prec digits (default: 5)
        mathrm  : Boolean to display as Roman text.

    Returns:
        None
    """

    # Safe Rounding Helper
    def _safe_round(x):
        try:
            x = sp.sympify(x)
            val = x.evalf(prec)

            return val.replace(
                lambda a: isinstance(a, sp.Float),
                lambda a: sp.Float(round(float(a), prec))
            ).evalf(prec)
        except (TypeError, ValueError):
            return x

    # Object Preparation
    def _prepare_object(raw_obj):
        # 1. Standardization: Convert to SymPy types
        if isinstance(raw_obj, np.ndarray):
            sym_obj = sp.Matrix(raw_obj)
        elif isinstance(raw_obj, (sp.Matrix, list)):
            sym_obj = sp.Matrix(raw_obj)
        elif isinstance(raw_obj, sp.NDimArray):
            sym_obj = raw_obj
        else:
            sym_obj = sp.sympify(raw_obj)

        # 2. Evaluation: Apply rounding if requested
        if evalf:
            if hasattr(sym_obj, 'applyfunc'):
                return sym_obj.applyfunc(_safe_round)
            return _safe_round(sym_obj)
        
        return sym_obj

    # Rendering
    def _render(processed_obj):
        expr = latex(processed_obj).replace(r'\\', r'\\[5pt]')

        if mathrm:
            expr = rf"\mathrm{{{expr}}}"

        if name is None:
            ipy_display(Math(rf"\large {expr}"))
        else:
            ipy_display(Math(rf"\large {name} = {expr}"))

    # Main Execution
    final_obj = _prepare_object(obj)
    _render(final_obj)