///|
// =====================================================================
// field.mbt — 純量域實作:實數 Double 與複數域 C
// 域公理(自證於 field_wbtest.mbt):
//   加法交換群、乘法交換群(去0)、分配律、共軛對合、|zw|=|z||w|
// =====================================================================

/// 複數:re + im·i
pub struct C {
  re : Double
  im : Double
} derive(Debug, Eq)

/// 構造
pub fn cnew(re : Double, im : Double) -> C {
  { re, im }
}

/// 0
pub fn czero() -> C {
  { re: 0.0, im: 0.0 }
}

/// 1
pub fn cone() -> C {
  { re: 1.0, im: 0.0 }
}

/// i
pub fn ci() -> C {
  { re: 0.0, im: 1.0 }
}

/// 實數嵌入
pub fn cfrom_real(x : Double) -> C {
  { re: x, im: 0.0 }
}

/// 加法
pub fn cadd(a : C, b : C) -> C {
  { re: a.re + b.re, im: a.im + b.im }
}

/// 減法
pub fn csub(a : C, b : C) -> C {
  { re: a.re - b.re, im: a.im - b.im }
}

/// 負元
pub fn cneg(a : C) -> C {
  { re: -a.re, im: -a.im }
}

/// 實純量乘法
pub fn cscale(s : Double, a : C) -> C {
  { re: s * a.re, im: s * a.im }
}

/// 乘法 (a+bi)(c+di) = (ac−bd) + (ad+bc)i
pub fn cmul(a : C, b : C) -> C {
  { re: a.re * b.re - a.im * b.im, im: a.re * b.im + a.im * b.re }
}

/// 平方
pub fn csqr(a : C) -> C {
  cmul(a, a)
}

/// 共軛
pub fn cconj(a : C) -> C {
  { re: a.re, im: -a.im }
}

/// |z|²
pub fn cnorm2(a : C) -> Double {
  a.re * a.re + a.im * a.im
}

/// |z|
pub fn cabs(a : C) -> Double {
  cnorm2(a).sqrt()
}

/// 乘法逆元 z⁻¹ = z̄/|z|²
pub fn cinv(a : C) -> C {
  let d = cnorm2(a)
  { re: a.re / d, im: -a.im / d }
}

/// 除法
pub fn cdiv(a : C, b : C) -> C {
  cmul(a, cinv(b))
}

/// 極式 r·e^{iθ}
pub fn cpolar(r : Double, theta : Double) -> C {
  { re: r * @math.cos(theta), im: r * @math.sin(theta) }
}

/// 輻角主值
pub fn carg(a : C) -> Double {
  @math.atan2(a.im, a.re)
}

/// 指數函數 e^{a}
pub fn cexp(a : C) -> C {
  cscale(@math.exp(a.re), cpolar(1.0, a.im))
}

/// 主平方根
pub fn csqrt(a : C) -> C {
  let r = cabs(a)
  if r == 0.0 {
    czero()
  } else {
    let re = ((r + a.re) / 2.0).sqrt()
    let im = ((r - a.re) / 2.0).sqrt()
    if a.im >= 0.0 {
      { re, im }
    } else {
      { re, im: -im }
    }
  }
}

/// 近似相等
pub fn ceq_eps(a : C, b : C, eps : Double) -> Bool {
  (a.re - b.re).abs() < eps && (a.im - b.im).abs() < eps
}

/// 顯示
pub fn cstr(a : C) -> String {
  "\{a.re}+\{a.im}*i"
}