# ============================================================
# KRONX :: utils.R
# Numeric helpers shared across the KRONX pipeline.
# ============================================================

# Numerically stable log(sum(exp(x))).
log_sum_exp <- function(x) {
  m <- max(x)
  m + log(sum(exp(x - m)))
}

# Normalize a vector into probabilities, flooring each element at eps.
safe_normalize <- function(x, eps = 1e-12) {
  x <- pmax(x, eps)
  x / sum(x)
}

# Normalize each row of a matrix so rows sum to one.
row_normalize <- function(M, eps = 1e-12) {
  M <- pmax(M, eps)
  M / rowSums(M)
}

# Weighted mean with a fallback to ordinary mean when weights are zero.
weighted_mean_safe <- function(x, w) {
  sw <- sum(w)
  if (sw <= 0) return(mean(x))
  sum(w * x) / sw
}

# Weighted variance with a floor of 1e-10 and a fallback to ordinary var.
weighted_var_safe <- function(x, w, mu = NULL) {
  if (is.null(mu)) mu <- weighted_mean_safe(x, w)
  sw <- sum(w)
  if (sw <= 0) return(stats::var(x))
  max(sum(w * (x - mu)^2) / sw, 1e-10)
}
