def linear_regression(values: list[float]) -> tuple[float, float]:
    """
    Linear Regression using matrix formula:
        beta = (X^T X)^-1 X^T y
    where X = [[1, 0], [1, 1], ..., [1, n-1]]

    returns:
        slope (beta_1), intercept (beta_0)
    """
    n = len(values)
    if n < 2:
        return 0.0, values[0] if values else 0.0

    # x = 0..n-1
    x = list(range(n))
    y = values

    # Compute matrix components
    sum_x = sum(x)
    sum_y = sum(y)
    sum_xx = sum(i * i for i in x)
    sum_xy = sum(i * j for i, j in zip(x, y))

    # Determinant of (X^T X)
    det = (n * sum_xx) - (sum_x * sum_x)
    if det == 0:
        # perfectly constant x axis (should never happen)
        return 0.0, y[0]

    # Using explicit inverse of 2x2 matrix:
    # beta1 (slope)
    slope = (n * sum_xy - sum_x * sum_y) / det

    # beta0 (intercept)
    intercept = (sum_y - slope * sum_x) / n

    return slope, intercept



def ema(values: list[float], alpha: float = 0.3) -> list[float]:
    if not values:
        return []

    result = [values[0]]

    for v in values[1:]:
        result.append(alpha * v + (1 - alpha) * result[-1])

    return result


def nearly_equal(
    a: float,
    b: float,
    abs_tol: float = 1e-3,
    rel_tol: float = 1e-4,
):
    return abs(a - b) <= max(
        abs_tol,
        rel_tol * max(abs(a), abs(b))
    )