// High-dimensional tensor algebra and Kronecker matrix products.

///|
/// Compute Kronecker product of two 2x2 Complex matrices A x B -> 4x4 Complex matrix
pub fn kronecker_product_2x2(a : Matrix2x2, b : Matrix2x2) -> Matrix4x4Complex {
  {
    m00: a.m00.mul(b.m00),
    m01: a.m00.mul(b.m01),
    m02: a.m01.mul(b.m00),
    m03: a.m01.mul(b.m01),
    m10: a.m00.mul(b.m10),
    m11: a.m00.mul(b.m11),
    m12: a.m01.mul(b.m10),
    m13: a.m01.mul(b.m11),
    m20: a.m10.mul(b.m00),
    m21: a.m10.mul(b.m01),
    m22: a.m11.mul(b.m00),
    m23: a.m11.mul(b.m01),
    m30: a.m10.mul(b.m10),
    m31: a.m10.mul(b.m11),
    m32: a.m11.mul(b.m10),
    m33: a.m11.mul(b.m11),
  }
}

///|
/// Compute trace of 2x2 matrix
pub fn matrix2x2_trace(m : Matrix2x2) -> Complex {
  m.m00.add(m.m11)
}

///|
/// Compute determinant of 2x2 complex matrix det(M) = m00*m11 - m01*m10
pub fn matrix2x2_det(m : Matrix2x2) -> Complex {
  m.m00.mul(m.m11).sub(m.m01.mul(m.m10))
}

///|
/// Inverse of 2x2 complex matrix
pub fn matrix2x2_inv(m : Matrix2x2) -> Matrix2x2 {
  let d = matrix2x2_det(m)
  let inv_d = Complex::one().div(d)
  {
    m00: m.m11.mul(inv_d),
    m01: m.m01.neg().mul(inv_d),
    m10: m.m10.neg().mul(inv_d),
    m11: m.m00.mul(inv_d),
  }
}