///|
// =====================================================================
// euclid.mbt — 標準歐幾里得空間 R^n(Array[Double] 實作)
// =====================================================================

/// E-1 零向量
pub fn euc_zero(n : Int) -> Array[Double] {
  Array::make(n, 0.0)
}

/// E-2 逐點加法
pub fn euc_add(a : Array[Double], b : Array[Double]) -> Array[Double] {
  let out = Array::make(a.length(), 0.0)
  for i = 0; i < a.length(); i = i + 1 {
    out[i] = a[i] + b[i]
  }
  out
}

/// E-3 負元
pub fn euc_neg(a : Array[Double]) -> Array[Double] {
  let out = Array::make(a.length(), 0.0)
  for i = 0; i < a.length(); i = i + 1 {
    out[i] = -a[i]
  }
  out
}

/// E-4 純量乘法
pub fn euc_scale(c : Double, a : Array[Double]) -> Array[Double] {
  let out = Array::make(a.length(), 0.0)
  for i = 0; i < a.length(); i = i + 1 {
    out[i] = c * a[i]
  }
  out
}

/// E-5 標準內積(點積)Σ aᵢbᵢ
pub fn euc_inner(a : Array[Double], b : Array[Double]) -> Double {
  let mut s = 0.0
  for i = 0; i < a.length(); i = i + 1 {
    s = s + a[i] * b[i]
  }
  s
}

/// E-6 R^n 向量空間字典
pub fn euc_sp(n : Int) -> VecSp[Array[Double]] {
  {
    zero: euc_zero(n),
    add: euc_add,
    neg: euc_neg,
    scale: euc_scale,
  }
}

/// E-7 R^n 內積空間字典
pub fn euc_ip(n : Int) -> IPSp[Array[Double]] {
  ips_make(euc_sp(n), euc_inner)
}

/// E-8 標準基 {e_0, ..., e_{n-1}}
pub fn euc_basis(n : Int) -> Array[Array[Double]] {
  let out : Array[Array[Double]] = []
  for i = 0; i < n; i = i + 1 {
    out.push(evec(n, i))
  }
  out
}

/// E-9 第 i 個標準基向量
pub fn evec(n : Int, i : Int) -> Array[Double] {
  let v = euc_zero(n)
  v[i] = 1.0
  v
}

/// E-10 三維叉積
pub fn euc_cross3(a : Array[Double], b : Array[Double]) -> Array[Double] {
  [
    a[1] * b[2] - a[2] * b[1],
    a[2] * b[0] - a[0] * b[2],
    a[0] * b[1] - a[1] * b[0],
  ]
}

/// E-11 Hadamard 逐點積
pub fn euc_hadamard(a : Array[Double], b : Array[Double]) -> Array[Double] {
  let out = Array::make(a.length(), 0.0)
  for i = 0; i < a.length(); i = i + 1 {
    out[i] = a[i] * b[i]
  }
  out
}

/// E-12 分量總和(線性泛函)
pub fn euc_sum(a : Array[Double]) -> Double {
  let mut s = 0.0
  for x in a {
    s = s + x
  }
  s
}

/// E-13 均值
pub fn euc_mean(a : Array[Double]) -> Double {
  euc_sum(a) / a.length().to_double()
}

/// E-14 近似相等
pub fn euc_eq_eps(a : Array[Double], b : Array[Double], eps : Double) -> Bool {
  if a.length() != b.length() {
    false
  } else {
    let mut ok = true
    for i = 0; i < a.length(); i = i + 1 {
      if (a[i] - b[i]).abs() >= eps {
        ok = false
      }
    }
    ok
  }
}

/// E-15 最大值分量
pub fn euc_max_component(a : Array[Double]) -> Double {
  let mut m = a[0]
  for x in a {
    if x > m {
      m = x
    }
  }
  m
}

/// E-16 最大絕對值分量(∞-範數)
pub fn euc_inf_norm(a : Array[Double]) -> Double {
  let mut m = a[0].abs()
  for x in a {
    if x.abs() > m {
      m = x.abs()
    }
  }
  m
}