Source code for general_python.maths

"""Mathematical helper package with statistics and random tools.

This package collects utility functions used by physics, algebra, and ML modules.
Submodules are lazy-loaded to keep top-level import overhead low.

Scope
-----
* ``math_utils``: numerical helper routines.
* ``statistics``: smoothing, aggregation, and summary statistics.
* ``random``: random-matrix-oriented helpers; for backend-wide RNG streams use
  ``general_python.algebra.ran_wrapper``.

Input/output, dtype, and shape guidance
---------------------------------------
Most routines accept NumPy array-like inputs and return NumPy arrays or scalars.
APIs typically operate on 1D or 2D arrays where axis conventions are documented
per function. Use floating dtypes for interpolation and filtering paths.

Determinism and stability
-------------------------
Pure algebraic or statistical transforms are deterministic for fixed inputs.
Randomized routines require explicit seeding to be reproducible.
"""

import  sys
import  importlib
from    typing import TYPE_CHECKING, List

# Description used by general_python.registry
MODULE_DESCRIPTION = (
    "Mathematical utilities, random number generators, and statistical analysis tools."
)

# -----------------------------------------------------------------------------------------------
# Lazy Import Configuration
# -----------------------------------------------------------------------------------------------

# Mapping of attribute names to (module_relative_path, attribute_name_in_module)
_LAZY_IMPORTS = {
    # Modules
    "math_utils"    : (".math_utils",   None),
    "random"        : (".random",       None),
    "statistics"    : (".statistics",   None),
    
    # Aliases for backward compatibility or convenience (optional)
    "MathMod"       : (".math_utils",   None),
    "RandomMod"     : (".random",       None),
    "StatisticsMod" : (".statistics",   None),
}

# Cache for lazily loaded modules/attributes
_LAZY_CACHE = {}

if TYPE_CHECKING:
    from . import math_utils
    from . import random
    from . import statistics
    # Aliases
    from . import math_utils as MathMod
    from . import random as RandomMod
    from . import statistics as StatisticsMod

# -----------------------------------------------------------------------------------------------
# Lazy Import Implementation
# -----------------------------------------------------------------------------------------------

def _lazy_import(name: str):
    """
    Lazily import a module or attribute based on _LAZY_IMPORTS configuration.
    """
    if name in _LAZY_CACHE:
        return _LAZY_CACHE[name]
    
    if name not in _LAZY_IMPORTS:
        raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
    
    module_path, attr_name = _LAZY_IMPORTS[name]
    
    try:
        module = importlib.import_module(module_path, package=__name__)
        
        if attr_name is None:
            result = module
        else:
            result = getattr(module, attr_name)
        
        _LAZY_CACHE[name] = result
        return result
    except ImportError as e:
        raise ImportError(f"Failed to import lazy module '{name}' from '{module_path}': {e}") from e

def __getattr__(name: str):
    return _lazy_import(name)

def __dir__() -> List[str]:
    return sorted(list(globals().keys()) + list(_LAZY_IMPORTS.keys()))

[docs] def get_module_description(module_name: str) -> str: """Return a description for a maths submodule.""" _descriptions = { "math_utils": "General mathematical functions and utilities.", "random": "High-quality pseudorandom number generators and CUE matrices.", "statistics": "Statistical functions and data analysis utilities.", } # Handle aliases real_name = _LAZY_IMPORTS.get(module_name, (None, None))[0] if real_name: real_name = real_name.lstrip(".") return _descriptions.get(real_name, "Module not found.") return "Module not found."
[docs] def list_available_modules() -> List[str]: """Return the list of available maths submodules.""" return sorted([k for k in _LAZY_IMPORTS.keys() if not k.endswith("Mod")])
__all__ = list(_LAZY_IMPORTS.keys()) + ["get_module_description", "list_available_modules"] # ------------------------------------------------------------------------- #! EOF # -------------------------------------------------------------------------