namespace KyberDotnet
{
	public class Poly
	{
		public int[] Data;

		public Poly()
		{
			Data = new int[Kyber.n];
		}

		public Poly(int[] data)
		{
			Data = data;
		}

		/// <summary>
		/// Adds specified polynomial to this object. Doesn't reduce result.
		/// </summary>
		/// <param name="B">Polynomial to add.</param>
		public void Add(Poly B)
		{
			for (int i = 0; i < Kyber.n; i++)
			{
				Data[i] += B.Data[i];
			}
		}

		/// <summary>
		/// Subtracts specified polynomial from this object. Doesn't reduce result.
		/// </summary>
		/// <param name="B">Polynomial to subtract.</param>
		public void Sub(Poly B)
		{
			for (int i = 0; i < Kyber.n; i++)
			{
				Data[i] -= B.Data[i];
			}
		}

		/// <summary>
		/// In-place polynomial vector addition. Saves into A.
		/// </summary>
		/// <param name="A">Augend. Gets modified.</param>
		/// <param name="B">Addend.</param>
		public static void Add(Poly[] A, Poly[] B)
		{
			for (int i = 0; i < A.Length; i++)
			{
				A[i].Add(B[i]);
			}
		}

		/// <summary>
		/// Reduces all elements in this polynomial by 3329.
		/// </summary>
		public void Reduce()
		{
			for (int i = 0; i < Data.Length; i++)
			{
				Data[i] = Utils.PosMod(Data[i]);
			}
		}

		/// <summary>
		/// Reduces all polynomials in the provided vector.
		/// </summary>
		/// <param name="vec">Vector of polynomials to reduce.</param>
		public static void Reduce(Poly[] vec)
		{
			foreach (Poly poly in vec) poly.Reduce();
		}

		public override string ToString()
		{
			return string.Join(' ', Data);
		}
	}
}
