///|
/// Polynomial vector operations for the Dilithium signature scheme.
///
/// This module implements operations on vectors of polynomials, which are
/// fundamental data structures in the Dilithium signature scheme. These vectors
/// represent elements in the module lattice used by the underlying cryptographic
/// construction.
///
/// # Mathematical Structure
///
/// The module implements two types of polynomial vectors:
/// - `Polyvecl`: Vectors of length l (typically l = k or l = k+1)
/// - `Polyveck`: Vectors of length k
///
/// Both types operate in the polynomial ring Z_q[X]/(X^N + 1) where:
/// - q = 8380417 (the modulus)
/// - N = 256 (the polynomial degree)
///
/// # Vector Operations
///
/// The module provides essential operations including:
/// - Vector addition and subtraction
/// - Pointwise polynomial multiplication
/// - Norm checking for security bounds
/// - NTT transformations for efficient multiplication
/// - Specialized packing/unpacking for keys and signatures
///
/// # Examples
///
/// ```moonbit
/// // Create polynomial vectors
/// let v1 = @ruifeng/moondsa.Polyveck::default()
/// let v2 = @ruifeng/moondsa.Polyveck::default()
/// 
/// // Vector operations
/// v1.add(v2)  // v1 = v1 + v2
/// let norm = v1.chknorm(1000)  // Check if coefficients are within bounds
/// ```

///|
/// Vector of polynomials with length k, where k is determined by the Dilithium
/// parameter set.
///
/// This structure represents one of the core data types in the Dilithium
/// post-quantum cryptographic scheme. The length k corresponds to the security
/// parameter that defines the dimensions of the underlying lattice problem.
/// Each polynomial in the vector operates in the ring Z\_q\[X]/(X^256 + 1)
/// where q is the modulus used in Dilithium.
///
/// Fields:
///
/// * `vec` : Array containing k polynomials, where each polynomial represents a
///   vector component in the lattice-based operations.
pub struct Polyveck {
  vec : Array[Poly]
} derive(Show)

///|
/// Creates a deep copy of the polynomial vector.
///
/// Parameters:
///
/// * `self` : The polynomial vector to copy.
///
/// Returns a new `Polyveck` instance with deeply copied polynomials, ensuring
/// that modifications to the returned vector or its polynomials do not affect
/// the original.
///
pub fn Polyveck::copy(self : Polyveck) -> Polyveck {
  let new_vec = Array::new()
  for poly in self.vec {
    new_vec.push(poly.copy())
  }
  { vec: new_vec }
}

///|
/// Creates a default `Polyveck` instance with a vector of `k` polynomials,
/// where `k` is determined by the current Dilithium parameter set.
///
/// Returns a new `Polyveck` with each polynomial initialized using
/// `Poly::new()`.
///
/// Example:
///
/// ```moonbit
/// let polyveck = Polyveck::default()
/// println(polyveck.vec.length()) // prints the value of k from current parameter set
/// ```
///
pub impl Default for Polyveck with default() -> Polyveck {
  let k = dilithium_context.get_params_set().k
  let vec = Array::new()
  for _i in 0.. Polyvecl {
  let new_vec = Array::new()
  for poly in self.vec {
    new_vec.push(poly.copy())
  }
  { vec: new_vec }
}

///|
/// Creates a default `Polyvecl` instance with polynomials initialized to zero.
///
/// Returns a new `Polyvecl` containing `l` zero-initialized polynomials, where
/// `l` is obtained from the current Dilithium parameter set.
///
pub impl Default for Polyvecl with default() -> Polyvecl {
  let l = dilithium_context.get_params_set().l
  let vec = Array::new()
  for _i in 0.. Unit {
  let k = dilithium_context.get_params_set().k
  let l = dilithium_context.get_params_set().l
  for i in 0.. Unit {
  let k = dilithium_context.get_params_set().k
  for i in 0.. Unit {
  let l = dilithium_context.get_params_set().l
  let mut nonce = nonce
  for i in 0.. Unit {
  let l = dilithium_context.get_params_set().l
  let l_u16 = l.to_uint16()
  for i in 0.. Unit {
  let l = dilithium_context.get_params_set().l
  for i in 0.. Unit {
  let l = dilithium_context.get_params_set().l
  for i in 0.. Unit {
  let l = dilithium_context.get_params_set().l
  for i in 0.. Unit {
  let l = dilithium_context.get_params_set().l
  for i in 0.. Unit {
  let l = dilithium_context.get_params_set().l
  for i in 0.. Unit {
  let l = dilithium_context.get_params_set().l
  let t = Poly::default()
  w.pointwise_montgomery(u.vec[0], v.vec[0])
  for i in 1.. Byte {
  let l = dilithium_context.get_params_set().l
  for i in 0.. 0 {
      return 1
    }
  }
  return 0
}

//*********** Vectors of polynomials of length K ****************************

///|
/// Generates uniform random polynomials with coefficients in the range \[-eta,
/// eta] for all polynomials in the vector.
///
/// Parameters:
///
/// * `v` : The polynomial vector of length K to be filled with uniform random
///   coefficients.
/// * `seed` : The random seed bytes used for generating the uniform
///   distribution.
/// * `nonce` : The starting nonce value used for randomness generation,
///   incremented for each polynomial.
pub fn Polyveck::uniform_eta(
  v : Polyveck,
  seed : Array[Byte],
  nonce : UInt16,
) -> Unit {
  let k = dilithium_context.get_params_set().k
  let mut nonce = nonce
  for i in 0.. Unit {
  let k = dilithium_context.get_params_set().k
  for i in 0.. Unit {
  let k = dilithium_context.get_params_set().k
  for i in 0.. Unit {
  let k = dilithium_context.get_params_set().k
  for i in 0.. Unit {
  let k = dilithium_context.get_params_set().k
  for i in 0.. Unit {
  let k = dilithium_context.get_params_set().k
  for i in 0.. Unit {
  let k = dilithium_context.get_params_set().k
  for i in 0.. Unit {
  let k = dilithium_context.get_params_set().k
  for i in 0.. Unit {
  let k = dilithium_context.get_params_set().k
  for i in 0.. Byte {
  let k = dilithium_context.get_params_set().k
  for i in 0.. 0 {
      return 1
    }
  }
  return 0
}

///| For all coefficients a of polynomials in vector of length K,
/// compute a0, a1 such that a mod Q = a1*2^D + a0
/// with -2^{D-1} < a0 <= 2^{D-1}. Assumes coefficients to be
/// standard representatives.
pub fn Polyveck::power2round(v1 : Polyveck, v0 : Polyveck) -> Unit {
  let k = dilithium_context.get_params_set().k
  for i in 0.. Unit {
  let k = dilithium_context.get_params_set().k
  for i in 0.. Int {
  let k = dilithium_context.get_params_set().k
  let mut s = 0
  for i in 0.. Unit {
  let k = dilithium_context.get_params_set().k
  for i in 0.. Unit {
  let k = dilithium_context.get_params_set().k
  let mut idx = 0
  for i in 0..