#ifndef MLD_POLYVEC_H
#define MLD_POLYVEC_H
#include "cbmc.h"
#include "common.h"
#include "poly.h"
#include "poly_kl.h"
#define mld_polyvecl MLD_ADD_PARAM_SET(mld_polyvecl)
#define mld_polyveck MLD_ADD_PARAM_SET(mld_polyveck)
typedef struct
{
mld_poly vec[MLDSA_L];
} mld_polyvecl;
#if !defined(MLD_CONFIG_NO_SIGN_API) && \
(!defined(MLD_CONFIG_REDUCE_RAM) || defined(MLD_UNIT_TEST))
#define mld_polyvecl_uniform_gamma1 MLD_NAMESPACE_KL(polyvecl_uniform_gamma1)
MLD_INTERNAL_API
void mld_polyvecl_uniform_gamma1(mld_polyvecl *v,
const uint8_t seed[MLDSA_CRHBYTES],
uint16_t kappa)
__contract__(
requires(memory_no_alias(v, sizeof(mld_polyvecl)))
requires(memory_no_alias(seed, MLDSA_CRHBYTES))
requires(kappa <= UINT16_MAX - MLDSA_L)
assigns(memory_slice(v, sizeof(mld_polyvecl)))
ensures(forall(k0, 0, MLDSA_L,
array_bound(v->vec[k0].coeffs, 0, MLDSA_N, -(MLDSA_GAMMA1 - 1), MLDSA_GAMMA1 + 1)))
);
#endif
#if !defined(MLD_CONFIG_NO_KEYPAIR_API) || \
!defined(MLD_CONFIG_NO_VERIFY_API) || \
(!defined(MLD_CONFIG_NO_SIGN_API) && \
(!defined(MLD_CONFIG_REDUCE_RAM) || defined(MLD_UNIT_TEST)))
#define mld_polyvecl_ntt MLD_NAMESPACE_KL(polyvecl_ntt)
MLD_INTERNAL_API
void mld_polyvecl_ntt(mld_polyvecl *v)
__contract__(
requires(memory_no_alias(v, sizeof(mld_polyvecl)))
requires(forall(k0, 0, MLDSA_L, array_abs_bound(v->vec[k0].coeffs, 0, MLDSA_N, MLDSA_Q)))
assigns(memory_slice(v, sizeof(mld_polyvecl)))
ensures(forall(k1, 0, MLDSA_L, array_abs_bound(v->vec[k1].coeffs, 0, MLDSA_N, MLD_NTT_BOUND)))
);
#endif
#if !defined(MLD_CONFIG_REDUCE_RAM) || defined(MLD_UNIT_TEST)
#define mld_polyvecl_pointwise_acc_montgomery \
MLD_NAMESPACE_KL(polyvecl_pointwise_acc_montgomery)
MLD_INTERNAL_API
void mld_polyvecl_pointwise_acc_montgomery(mld_poly *w, const mld_polyvecl *u,
const mld_polyvecl *v)
__contract__(
requires(memory_no_alias(w, sizeof(mld_poly)))
requires(memory_no_alias(u, sizeof(mld_polyvecl)))
requires(memory_no_alias(v, sizeof(mld_polyvecl)))
requires(forall(l0, 0, MLDSA_L,
array_bound(u->vec[l0].coeffs, 0, MLDSA_N, 0, MLDSA_Q)))
requires(forall(l1, 0, MLDSA_L,
array_abs_bound(v->vec[l1].coeffs, 0, MLDSA_N, MLD_NTT_BOUND)))
assigns(memory_slice(w, sizeof(mld_poly)))
ensures(array_abs_bound(w->coeffs, 0, MLDSA_N, MLDSA_Q))
);
#endif
#if !defined(MLD_CONFIG_NO_KEYPAIR_API) || !defined(MLD_CONFIG_NO_VERIFY_API)
#define mld_polyvecl_chknorm MLD_NAMESPACE_KL(polyvecl_chknorm)
MLD_INTERNAL_API
MLD_MUST_CHECK_RETURN_VALUE
uint32_t mld_polyvecl_chknorm(const mld_polyvecl *v, int32_t B)
__contract__(
requires(memory_no_alias(v, sizeof(mld_polyvecl)))
requires(0 <= B && B <= (MLDSA_Q - 1) / 8)
requires(forall(k0, 0, MLDSA_L,
array_bound(v->vec[k0].coeffs, 0, MLDSA_N, -MLD_REDUCE32_RANGE_MAX, MLD_REDUCE32_RANGE_MAX)))
ensures(return_value == 0 || return_value == 0xFFFFFFFF)
ensures((return_value == 0) == forall(k1, 0, MLDSA_L, array_abs_bound(v->vec[k1].coeffs, 0, MLDSA_N, B)))
);
#endif
typedef struct
{
mld_poly vec[MLDSA_K];
} mld_polyveck;
#if (!defined(MLD_CONFIG_NO_SIGN_API) && defined(MLD_CONFIG_REDUCE_RAM)) || \
defined(MLD_UNIT_TEST)
#define mld_polyveck_reduce MLD_NAMESPACE_KL(polyveck_reduce)
MLD_INTERNAL_API
void mld_polyveck_reduce(mld_polyveck *v)
__contract__(
requires(memory_no_alias(v, sizeof(mld_polyveck)))
requires(forall(k0, 0, MLDSA_K,
array_bound(v->vec[k0].coeffs, 0, MLDSA_N, INT32_MIN, MLD_REDUCE32_DOMAIN_MAX)))
assigns(memory_slice(v, sizeof(mld_polyveck)))
ensures(forall(k1, 0, MLDSA_K,
array_bound(v->vec[k1].coeffs, 0, MLDSA_N, -MLD_REDUCE32_RANGE_MAX, MLD_REDUCE32_RANGE_MAX)))
);
#endif
#if !defined(MLD_CONFIG_NO_SIGN_API) || defined(MLD_UNIT_TEST)
#define mld_polyveck_caddq MLD_NAMESPACE_KL(polyveck_caddq)
MLD_INTERNAL_API
void mld_polyveck_caddq(mld_polyveck *v)
__contract__(
requires(memory_no_alias(v, sizeof(mld_polyveck)))
requires(forall(k0, 0, MLDSA_K,
array_abs_bound(v->vec[k0].coeffs, 0, MLDSA_N, MLDSA_Q)))
assigns(memory_slice(v, sizeof(mld_polyveck)))
ensures(forall(k1, 0, MLDSA_K,
array_bound(v->vec[k1].coeffs, 0, MLDSA_N, 0, MLDSA_Q)))
);
#endif
#if (!defined(MLD_CONFIG_NO_SIGN_API) || defined(MLD_UNIT_TEST)) && \
(!defined(MLD_CONFIG_REDUCE_RAM) || defined(MLD_UNIT_TEST))
#define mld_polyveck_ntt MLD_NAMESPACE_KL(polyveck_ntt)
MLD_INTERNAL_API
void mld_polyveck_ntt(mld_polyveck *v)
__contract__(
requires(memory_no_alias(v, sizeof(mld_polyveck)))
requires(forall(k0, 0, MLDSA_K, array_abs_bound(v->vec[k0].coeffs, 0, MLDSA_N, MLDSA_Q)))
assigns(memory_slice(v, sizeof(mld_polyveck)))
ensures(forall(k1, 0, MLDSA_K, array_abs_bound(v->vec[k1].coeffs, 0, MLDSA_N, MLD_NTT_BOUND)))
);
#endif
#if !defined(MLD_CONFIG_NO_SIGN_API) || defined(MLD_UNIT_TEST)
#define mld_polyveck_invntt_tomont MLD_NAMESPACE_KL(polyveck_invntt_tomont)
MLD_INTERNAL_API
void mld_polyveck_invntt_tomont(mld_polyveck *v)
__contract__(
requires(memory_no_alias(v, sizeof(mld_polyveck)))
requires(forall(k0, 0, MLDSA_K, array_abs_bound(v->vec[k0].coeffs, 0, MLDSA_N, MLDSA_Q)))
assigns(memory_slice(v, sizeof(mld_polyveck)))
ensures(forall(k1, 0, MLDSA_K, array_abs_bound(v->vec[k1].coeffs, 0, MLDSA_N, MLD_INTT_BOUND)))
);
#endif
#if !defined(MLD_CONFIG_NO_KEYPAIR_API)
#define mld_polyveck_chknorm MLD_NAMESPACE_KL(polyveck_chknorm)
MLD_INTERNAL_API
MLD_MUST_CHECK_RETURN_VALUE
uint32_t mld_polyveck_chknorm(const mld_polyveck *v, int32_t B)
__contract__(
requires(memory_no_alias(v, sizeof(mld_polyveck)))
requires(0 <= B && B <= (MLDSA_Q - 1) / 8)
requires(forall(k0, 0, MLDSA_K,
array_bound(v->vec[k0].coeffs, 0, MLDSA_N,
-MLD_REDUCE32_RANGE_MAX, MLD_REDUCE32_RANGE_MAX)))
ensures(return_value == 0 || return_value == 0xFFFFFFFF)
ensures((return_value == 0) == forall(k1, 0, MLDSA_K, array_abs_bound(v->vec[k1].coeffs, 0, MLDSA_N, B)))
);
#endif
#if !defined(MLD_CONFIG_NO_SIGN_API)
#define mld_polyveck_decompose MLD_NAMESPACE_KL(polyveck_decompose)
MLD_INTERNAL_API
void mld_polyveck_decompose(mld_polyveck *v1, mld_polyveck *v0)
__contract__(
requires(memory_no_alias(v1, sizeof(mld_polyveck)))
requires(memory_no_alias(v0, sizeof(mld_polyveck)))
requires(forall(k0, 0, MLDSA_K,
array_bound(v0->vec[k0].coeffs, 0, MLDSA_N, 0, MLDSA_Q)))
assigns(memory_slice(v1, sizeof(mld_polyveck)))
assigns(memory_slice(v0, sizeof(mld_polyveck)))
ensures(forall(k1, 0, MLDSA_K,
array_bound(v1->vec[k1].coeffs, 0, MLDSA_N, 0, (MLDSA_Q-1)/(2*MLDSA_GAMMA2))))
ensures(forall(k2, 0, MLDSA_K,
array_abs_bound(v0->vec[k2].coeffs, 0, MLDSA_N, MLDSA_GAMMA2+1)))
);
#endif
#if !defined(MLD_CONFIG_NO_SIGN_API)
#define mld_polyveck_pack_w1 MLD_NAMESPACE_KL(polyveck_pack_w1)
MLD_INTERNAL_API
void mld_polyveck_pack_w1(uint8_t r[MLDSA_K * MLDSA_POLYW1_PACKEDBYTES],
const mld_polyveck *w1)
__contract__(
requires(memory_no_alias(r, MLDSA_K * MLDSA_POLYW1_PACKEDBYTES))
requires(memory_no_alias(w1, sizeof(mld_polyveck)))
requires(forall(k1, 0, MLDSA_K,
array_bound(w1->vec[k1].coeffs, 0, MLDSA_N, 0, (MLDSA_Q-1)/(2*MLDSA_GAMMA2))))
assigns(memory_slice(r, MLDSA_K * MLDSA_POLYW1_PACKEDBYTES))
);
#endif
#if !defined(MLD_CONFIG_NO_KEYPAIR_API)
#define mld_polyveck_pack_eta MLD_NAMESPACE_KL(polyveck_pack_eta)
MLD_INTERNAL_API
void mld_polyveck_pack_eta(uint8_t r[MLDSA_K * MLDSA_POLYETA_PACKEDBYTES],
const mld_polyveck *p)
__contract__(
requires(memory_no_alias(r, MLDSA_K * MLDSA_POLYETA_PACKEDBYTES))
requires(memory_no_alias(p, sizeof(mld_polyveck)))
requires(forall(k1, 0, MLDSA_K,
array_abs_bound(p->vec[k1].coeffs, 0, MLDSA_N, MLDSA_ETA + 1)))
assigns(memory_slice(r, MLDSA_K * MLDSA_POLYETA_PACKEDBYTES))
);
#define mld_polyvecl_pack_eta MLD_NAMESPACE_KL(polyvecl_pack_eta)
MLD_INTERNAL_API
void mld_polyvecl_pack_eta(uint8_t r[MLDSA_L * MLDSA_POLYETA_PACKEDBYTES],
const mld_polyvecl *p)
__contract__(
requires(memory_no_alias(r, MLDSA_L * MLDSA_POLYETA_PACKEDBYTES))
requires(memory_no_alias(p, sizeof(mld_polyvecl)))
requires(forall(k1, 0, MLDSA_L,
array_abs_bound(p->vec[k1].coeffs, 0, MLDSA_N, MLDSA_ETA + 1)))
assigns(memory_slice(r, MLDSA_L * MLDSA_POLYETA_PACKEDBYTES))
);
#endif
#if !defined(MLD_CONFIG_NO_KEYPAIR_API) || \
(!defined(MLD_CONFIG_NO_SIGN_API) && \
(!defined(MLD_CONFIG_REDUCE_RAM) || defined(MLD_UNIT_TEST)))
#define mld_polyvecl_unpack_eta MLD_NAMESPACE_KL(polyvecl_unpack_eta)
MLD_INTERNAL_API
void mld_polyvecl_unpack_eta(
mld_polyvecl *p, const uint8_t r[MLDSA_L * MLDSA_POLYETA_PACKEDBYTES])
__contract__(
requires(memory_no_alias(r, MLDSA_L * MLDSA_POLYETA_PACKEDBYTES))
requires(memory_no_alias(p, sizeof(mld_polyvecl)))
assigns(memory_slice(p, sizeof(mld_polyvecl)))
ensures(forall(k1, 0, MLDSA_L,
array_bound(p->vec[k1].coeffs, 0, MLDSA_N, MLD_POLYETA_UNPACK_LOWER_BOUND, MLDSA_ETA + 1)))
);
#endif
#if !defined(MLD_CONFIG_NO_VERIFY_API)
#define mld_polyvecl_unpack_z MLD_NAMESPACE_KL(polyvecl_unpack_z)
MLD_INTERNAL_API
void mld_polyvecl_unpack_z(mld_polyvecl *z,
const uint8_t r[MLDSA_L * MLDSA_POLYZ_PACKEDBYTES])
__contract__(
requires(memory_no_alias(r, MLDSA_L * MLDSA_POLYZ_PACKEDBYTES))
requires(memory_no_alias(z, sizeof(mld_polyvecl)))
assigns(memory_slice(z, sizeof(mld_polyvecl)))
ensures(forall(k1, 0, MLDSA_L,
array_bound(z->vec[k1].coeffs, 0, MLDSA_N, -(MLDSA_GAMMA1 - 1), MLDSA_GAMMA1 + 1)))
);
#endif
#if !defined(MLD_CONFIG_NO_KEYPAIR_API) || \
(!defined(MLD_CONFIG_NO_SIGN_API) && \
(!defined(MLD_CONFIG_REDUCE_RAM) || defined(MLD_UNIT_TEST)))
#define mld_polyveck_unpack_eta MLD_NAMESPACE_KL(polyveck_unpack_eta)
MLD_INTERNAL_API
void mld_polyveck_unpack_eta(
mld_polyveck *p, const uint8_t r[MLDSA_K * MLDSA_POLYETA_PACKEDBYTES])
__contract__(
requires(memory_no_alias(r, MLDSA_K * MLDSA_POLYETA_PACKEDBYTES))
requires(memory_no_alias(p, sizeof(mld_polyveck)))
assigns(memory_slice(p, sizeof(mld_polyveck)))
ensures(forall(k1, 0, MLDSA_K,
array_bound(p->vec[k1].coeffs, 0, MLDSA_N, MLD_POLYETA_UNPACK_LOWER_BOUND, MLDSA_ETA + 1)))
);
#endif
#endif