// MoonFluid - 工具函数

// ==================== 基本数学运算 ====================

///|
/// 计算平方
pub fn square(x : Double) -> Double {
  x * x
}

///|
/// 计算立方
pub fn cube(x : Double) -> Double {
  x * x * x
}

///|
/// 计算四次方
pub fn pow4(x : Double) -> Double {
  let x2 = x * x
  x2 * x2
}

///|
/// 计算绝对值
pub fn abs(x : Double) -> Double {
  if x < 0.0 {
    -x
  } else {
    x
  }
}

///|
/// 计算最大值
pub fn max(a : Double, b : Double) -> Double {
  if a > b {
    a
  } else {
    b
  }
}

///|
/// 计算最小值
pub fn min(a : Double, b : Double) -> Double {
  if a < b {
    a
  } else {
    b
  }
}

///|
/// 安全除法,分母为零时返回默认值
pub fn safe_div(num : Double, den : Double, fallback : Double) -> Double {
  if abs(den) <= EPSILON {
    fallback
  } else {
    num / den
  }
}

///|
/// 判断两个浮点数是否近似相等
pub fn approx_equal(a : Double, b : Double, tolerance : Double) -> Bool {
  abs(a - b) < tolerance
}

///|
/// 判断浮点数是否接近零
pub fn is_zero(x : Double) -> Bool {
  abs(x) < EPSILON
}

///|
/// 符号函数
pub fn sign(x : Double) -> Double {
  if x > EPSILON {
    1.0
  } else if x < -EPSILON {
    -1.0
  } else {
    0.0
  }
}

///|
/// 限制值在范围内
pub fn clamp(value : Double, min_val : Double, max_val : Double) -> Double {
  if value < min_val {
    min_val
  } else if value > max_val {
    max_val
  } else {
    value
  }
}

///|
/// 线性插值
pub fn lerp(a : Double, b : Double, t : Double) -> Double {
  a + (b - a) * t
}

// ==================== 幂函数 ====================

///|
/// 计算 x 的 n 次方 (n 为整数)
pub fn pow_int(x : Double, n : Int) -> Double {
  if n == 0 {
    1.0
  } else if n < 0 {
    1.0 / pow_int(x, -n)
  } else {
    let mut result = 1.0
    let mut base = x
    let mut exp = n
    while exp > 0 {
      if exp % 2 == 1 {
        result = result * base
      }
      base = base * base
      exp = exp / 2
    }
    result
  }
}

///|
/// 计算 x 的 1/n 次方 (n 次根)
pub fn root(x : Double, n : Int) -> Double {
  if n <= 0 {
    0.0
  } else if n == 1 {
    x
  } else if n == 2 {
    x.sqrt()
    // 使用牛顿法: x^(1/n) = y, 其中 y^n = x
    // 迭代: y_new = y - (y^n - x) / (n * y^(n-1))
  } else if x <= 0.0 {
    0.0
  } else {
    let mut y = x
    let mut i = 0
    while i < 20 {
      let yn = pow_int(y, n)
      let dydn = n.to_double() * pow_int(y, n - 1)
      let y_new = y - (yn - x) / dydn
      if abs(y_new - y) < EPSILON {
        return y_new
      }
      y = y_new
      i = i + 1
    }
    y
  }
}

// ==================== 几何计算 ====================

///|
/// 圆形面积
pub fn circle_area(r : Double) -> Double {
  PI * square(r)
}

///|
/// 圆形周长
pub fn circle_perimeter(r : Double) -> Double {
  2.0 * PI * r
}

///|
/// 矩形面积
pub fn rect_area(width : Double, height : Double) -> Double {
  width * height
}

///|
/// 梯形面积
pub fn trapezoid_area(a : Double, b : Double, h : Double) -> Double {
  (a + b) * h / 2.0
}

///|
/// 圆环面积
pub fn ring_area(r_outer : Double, r_inner : Double) -> Double {
  PI * (square(r_outer) - square(r_inner))
}

// ==================== 统计工具 ====================

///|
/// 数组求和
pub fn array_sum(arr : Array[Double]) -> Double {
  let mut sum = 0.0
  for i = 0; i < arr.length(); i = i + 1 {
    sum = sum + arr[i]
  }
  sum
}

///|
/// 数组平均值
pub fn array_mean(arr : Array[Double]) -> Double {
  if arr.length() == 0 {
    0.0
  } else {
    array_sum(arr) / arr.length().to_double()
  }
}

///|
/// 数组最大值
pub fn array_max(arr : Array[Double]) -> Double {
  if arr.length() == 0 {
    return 0.0
  }
  let mut max_val = arr[0]
  for i = 1; i < arr.length(); i = i + 1 {
    if arr[i] > max_val {
      max_val = arr[i]
    }
  }
  max_val
}

///|
/// 数组最小值
pub fn array_min(arr : Array[Double]) -> Double {
  if arr.length() == 0 {
    return 0.0
  }
  let mut min_val = arr[0]
  for i = 1; i < arr.length(); i = i + 1 {
    if arr[i] < min_val {
      min_val = arr[i]
    }
  }
  min_val
}

// ==================== 数值方法 ====================

///|
/// 二分法求根 (f(x) = 0)
/// 函数 f 在 [a, b] 上连续,且 f(a)*f(b) < 0
pub fn bisection(
  f : (Double) -> Double,
  a : Double,
  b : Double,
  tolerance : Double,
) -> Double {
  let mut left = a
  let mut right = b
  let mut mid = (left + right) / 2.0
  let mut i = 0
  while abs(right - left) > tolerance && i < 100 {
    mid = (left + right) / 2.0
    let f_mid = f(mid)
    let f_left = f(left)
    if f_mid * f_left < 0.0 {
      right = mid
    } else {
      left = mid
    }
    i = i + 1
  }
  mid
}

///|
/// 牛顿法求根
/// f: 函数, df: 导数, x0: 初始值
pub fn newton_method(
  f : (Double) -> Double,
  df : (Double) -> Double,
  x0 : Double,
  tolerance : Double,
) -> Double {
  let mut x = x0
  let mut i = 0
  while i < 50 {
    let fx = f(x)
    if abs(fx) < tolerance {
      return x
    }
    let dfx = df(x)
    if abs(dfx) < EPSILON {
      return x
    }
    x = x - fx / dfx
    i = i + 1
  }
  x
}

// ==================== 插值 ====================

///|
/// 自然对数近似 (使用级数展开)
pub fn ln_approx(x : Double) -> Double {
  if x <= 0.0 {
    return 0.0
  }
  if x == 1.0 {
    return 0.0
  }
  // 对于 x > 1,使用 ln(x) = -ln(1/x)
  if x > 1.0 {
    return -ln_approx(1.0 / x)
  }
  // 对于 0 < x < 1,使用级数: ln(1+u) = u - u²/2 + u³/3 - ...
  let u = x - 1.0
  let mut sum = u
  let mut term = u
  let mut i = 2
  while i < 50 {
    term = term * -u
    sum = sum + term / i.to_double()
    if abs(term) < EPSILON {
      break
    }
    i = i + 1
  }
  sum
}

///|
/// 以10为底的对数
pub fn log10_approx(x : Double) -> Double {
  if x <= 0.0 {
    return 0.0
  }
  ln_approx(x) / 2.302585092994046 // ln(10)
}

///|
/// 立方根
pub fn cbrt(x : Double) -> Double {
  if x == 0.0 {
    0.0
  } else if x < 0.0 {
    -cbrt(-x)
  } else {
    // 使用牛顿法: y = x^(1/3), y^3 = x
    // 迭代: y_new = y - (y^3 - x) / (3*y^2)
    let mut y = x
    let mut i = 0
    while i < 20 {
      let y3 = y * y * y
      let y2 = y * y
      let y_new = y - (y3 - x) / (3.0 * y2)
      if abs(y_new - y) < EPSILON {
        return y_new
      }
      y = y_new
      i = i + 1
    }
    y
  }
}

///|
/// 线性插值表查找
/// x_values: 自变量数组 (需单调递增)
/// y_values: 因变量数组
/// x: 待插值的自变量
pub fn linear_interpolate(
  x_values : Array[Double],
  y_values : Array[Double],
  x : Double,
) -> Double {
  let n = x_values.length()
  if n == 0 {
    return 0.0
  }
  if n == 1 {
    return y_values[0]
  }
  if x <= x_values[0] {
    return y_values[0]
  }
  if x >= x_values[n - 1] {
    return y_values[n - 1]
  }
  // 找到 x 所在区间
  let mut i = 0
  while i < n - 1 {
    if x >= x_values[i] && x <= x_values[i + 1] {
      let t = (x - x_values[i]) / (x_values[i + 1] - x_values[i])
      return lerp(y_values[i], y_values[i + 1], t)
    }
    i = i + 1
  }
  y_values[n - 1]
}