#ifndef MLD_POLY_KL_H
#define MLD_POLY_KL_H
#include "cbmc.h"
#include "common.h"
#include "poly.h"
#if !defined(MLD_CONFIG_NO_SIGN_API)
#define mld_poly_decompose MLD_NAMESPACE_KL(poly_decompose)
MLD_INTERNAL_API
void mld_poly_decompose(mld_poly *a1, mld_poly *a0)
__contract__(
requires(memory_no_alias(a1, sizeof(mld_poly)))
requires(memory_no_alias(a0, sizeof(mld_poly)))
requires(array_bound(a0->coeffs, 0, MLDSA_N, 0, MLDSA_Q))
assigns(memory_slice(a1, sizeof(mld_poly)))
assigns(memory_slice(a0, sizeof(mld_poly)))
ensures(array_bound(a1->coeffs, 0, MLDSA_N, 0, (MLDSA_Q-1)/(2*MLDSA_GAMMA2)))
ensures(array_abs_bound(a0->coeffs, 0, MLDSA_N, MLDSA_GAMMA2+1))
);
#endif
#if !defined(MLD_CONFIG_NO_VERIFY_API)
#define mld_poly_use_hint MLD_NAMESPACE_KL(poly_use_hint)
MLD_INTERNAL_API
void mld_poly_use_hint(mld_poly *a, const mld_poly *h)
__contract__(
requires(memory_no_alias(a, sizeof(mld_poly)))
requires(memory_no_alias(h, sizeof(mld_poly)))
requires(array_bound(a->coeffs, 0, MLDSA_N, 0, MLDSA_Q))
requires(array_bound(h->coeffs, 0, MLDSA_N, 0, 2))
assigns(memory_slice(a, sizeof(mld_poly)))
ensures(array_bound(a->coeffs, 0, MLDSA_N, 0, (MLDSA_Q-1)/(2*MLDSA_GAMMA2)))
);
#endif
#if !defined(MLD_CONFIG_NO_KEYPAIR_API)
#if !defined(MLD_CONFIG_SERIAL_FIPS202_ONLY)
#define mld_poly_uniform_eta_4x MLD_NAMESPACE_KL(poly_uniform_eta_4x)
MLD_INTERNAL_API
void mld_poly_uniform_eta_4x(mld_poly *r0, mld_poly *r1, mld_poly *r2,
mld_poly *r3, const uint8_t seed[MLDSA_CRHBYTES],
uint8_t nonce0, uint8_t nonce1, uint8_t nonce2,
uint8_t nonce3)
__contract__(
requires(memory_no_alias(r0, sizeof(mld_poly)))
requires(memory_no_alias(r1, sizeof(mld_poly)))
requires(memory_no_alias(r2, sizeof(mld_poly)))
requires(memory_no_alias(r3, sizeof(mld_poly)))
requires(memory_no_alias(seed, MLDSA_CRHBYTES))
assigns(memory_slice(r0, sizeof(mld_poly)))
assigns(memory_slice(r1, sizeof(mld_poly)))
assigns(memory_slice(r2, sizeof(mld_poly)))
assigns(memory_slice(r3, sizeof(mld_poly)))
ensures(array_abs_bound(r0->coeffs, 0, MLDSA_N, MLDSA_ETA + 1))
ensures(array_abs_bound(r1->coeffs, 0, MLDSA_N, MLDSA_ETA + 1))
ensures(array_abs_bound(r2->coeffs, 0, MLDSA_N, MLDSA_ETA + 1))
ensures(array_abs_bound(r3->coeffs, 0, MLDSA_N, MLDSA_ETA + 1))
);
#endif
#if defined(MLD_CONFIG_SERIAL_FIPS202_ONLY)
#define mld_poly_uniform_eta MLD_NAMESPACE_KL(poly_uniform_eta)
MLD_INTERNAL_API
void mld_poly_uniform_eta(mld_poly *r, const uint8_t seed[MLDSA_CRHBYTES],
uint8_t nonce)
__contract__(
requires(memory_no_alias(r, sizeof(mld_poly)))
requires(memory_no_alias(seed, MLDSA_CRHBYTES))
assigns(memory_slice(r, sizeof(mld_poly)))
ensures(array_abs_bound(r->coeffs, 0, MLDSA_N, MLDSA_ETA + 1))
);
#endif
#endif
#if !defined(MLD_CONFIG_NO_SIGN_API)
#if MLD_CONFIG_PARAMETER_SET == 65 || \
defined(MLD_CONFIG_SERIAL_FIPS202_ONLY) || \
defined(MLD_CONFIG_REDUCE_RAM) || defined(MLD_UNIT_TEST)
#define mld_poly_uniform_gamma1 MLD_NAMESPACE_KL(poly_uniform_gamma1)
MLD_INTERNAL_API
void mld_poly_uniform_gamma1(mld_poly *a, const uint8_t seed[MLDSA_CRHBYTES],
uint16_t nonce)
__contract__(
requires(memory_no_alias(a, sizeof(mld_poly)))
requires(memory_no_alias(seed, MLDSA_CRHBYTES))
assigns(memory_slice(a, sizeof(mld_poly)))
ensures(array_bound(a->coeffs, 0, MLDSA_N, -(MLDSA_GAMMA1 - 1), MLDSA_GAMMA1 + 1))
);
#endif
#if !defined(MLD_CONFIG_SERIAL_FIPS202_ONLY) && \
(!defined(MLD_CONFIG_REDUCE_RAM) || defined(MLD_UNIT_TEST))
#define mld_poly_uniform_gamma1_4x MLD_NAMESPACE_KL(poly_uniform_gamma1_4x)
MLD_INTERNAL_API
void mld_poly_uniform_gamma1_4x(mld_poly *r0, mld_poly *r1, mld_poly *r2,
mld_poly *r3,
const uint8_t seed[MLDSA_CRHBYTES],
uint16_t nonce0, uint16_t nonce1,
uint16_t nonce2, uint16_t nonce3)
__contract__(
requires(memory_no_alias(r0, sizeof(mld_poly)))
requires(memory_no_alias(r1, sizeof(mld_poly)))
requires(memory_no_alias(r2, sizeof(mld_poly)))
requires(memory_no_alias(r3, sizeof(mld_poly)))
requires(memory_no_alias(seed, MLDSA_CRHBYTES))
assigns(memory_slice(r0, sizeof(mld_poly)))
assigns(memory_slice(r1, sizeof(mld_poly)))
assigns(memory_slice(r2, sizeof(mld_poly)))
assigns(memory_slice(r3, sizeof(mld_poly)))
ensures(array_bound(r0->coeffs, 0, MLDSA_N, -(MLDSA_GAMMA1 - 1), MLDSA_GAMMA1 + 1))
ensures(array_bound(r1->coeffs, 0, MLDSA_N, -(MLDSA_GAMMA1 - 1), MLDSA_GAMMA1 + 1))
ensures(array_bound(r2->coeffs, 0, MLDSA_N, -(MLDSA_GAMMA1 - 1), MLDSA_GAMMA1 + 1))
ensures(array_bound(r3->coeffs, 0, MLDSA_N, -(MLDSA_GAMMA1 - 1), MLDSA_GAMMA1 + 1))
);
#endif
#endif
#if !defined(MLD_CONFIG_NO_SIGN_API) || !defined(MLD_CONFIG_NO_VERIFY_API)
#define mld_poly_challenge MLD_NAMESPACE_KL(poly_challenge)
MLD_INTERNAL_API
void mld_poly_challenge(mld_poly *c, const uint8_t seed[MLDSA_CTILDEBYTES])
__contract__(
requires(memory_no_alias(c, sizeof(mld_poly)))
requires(memory_no_alias(seed, MLDSA_CTILDEBYTES))
assigns(memory_slice(c, sizeof(mld_poly)))
ensures(array_bound(c->coeffs, 0, MLDSA_N, -1, 2))
);
#endif
#if !defined(MLD_CONFIG_NO_KEYPAIR_API)
#define mld_polyeta_pack MLD_NAMESPACE_KL(polyeta_pack)
MLD_INTERNAL_API
void mld_polyeta_pack(uint8_t r[MLDSA_POLYETA_PACKEDBYTES], const mld_poly *a)
__contract__(
requires(memory_no_alias(r, MLDSA_POLYETA_PACKEDBYTES))
requires(memory_no_alias(a, sizeof(mld_poly)))
requires(array_abs_bound(a->coeffs, 0, MLDSA_N, MLDSA_ETA + 1))
assigns(memory_slice(r, MLDSA_POLYETA_PACKEDBYTES))
);
#endif
#if !defined(MLD_CONFIG_NO_KEYPAIR_API) || !defined(MLD_CONFIG_NO_SIGN_API)
#if MLDSA_ETA == 2
#define MLD_POLYETA_UNPACK_LOWER_BOUND (-5)
#elif MLDSA_ETA == 4
#define MLD_POLYETA_UNPACK_LOWER_BOUND (-11)
#else
#error "Invalid value of MLDSA_ETA"
#endif
#define mld_polyeta_unpack MLD_NAMESPACE_KL(polyeta_unpack)
MLD_INTERNAL_API
void mld_polyeta_unpack(mld_poly *r, const uint8_t a[MLDSA_POLYETA_PACKEDBYTES])
__contract__(
requires(memory_no_alias(r, sizeof(mld_poly)))
requires(memory_no_alias(a, MLDSA_POLYETA_PACKEDBYTES))
assigns(memory_slice(r, sizeof(mld_poly)))
ensures(array_bound(r->coeffs, 0, MLDSA_N, MLD_POLYETA_UNPACK_LOWER_BOUND, MLDSA_ETA + 1))
);
#endif
#if !defined(MLD_CONFIG_NO_SIGN_API)
#define mld_polyz_pack MLD_NAMESPACE_KL(polyz_pack)
MLD_INTERNAL_API
void mld_polyz_pack(uint8_t r[MLDSA_POLYZ_PACKEDBYTES], const mld_poly *a)
__contract__(
requires(memory_no_alias(r, MLDSA_POLYZ_PACKEDBYTES))
requires(memory_no_alias(a, sizeof(mld_poly)))
requires(array_bound(a->coeffs, 0, MLDSA_N, -(MLDSA_GAMMA1 - 1), MLDSA_GAMMA1 + 1))
assigns(memory_slice(r, MLDSA_POLYZ_PACKEDBYTES))
);
#endif
#if !defined(MLD_CONFIG_NO_SIGN_API) || !defined(MLD_CONFIG_NO_VERIFY_API)
#define mld_polyz_unpack MLD_NAMESPACE_KL(polyz_unpack)
MLD_INTERNAL_API
void mld_polyz_unpack(mld_poly *r, const uint8_t a[MLDSA_POLYZ_PACKEDBYTES])
__contract__(
requires(memory_no_alias(r, sizeof(mld_poly)))
requires(memory_no_alias(a, MLDSA_POLYZ_PACKEDBYTES))
assigns(memory_slice(r, sizeof(mld_poly)))
ensures(array_bound(r->coeffs, 0, MLDSA_N, -(MLDSA_GAMMA1 - 1), MLDSA_GAMMA1 + 1))
);
#define mld_polyw1_pack MLD_NAMESPACE_KL(polyw1_pack)
static MLD_INLINE void mld_polyw1_pack(uint8_t r[MLDSA_POLYW1_PACKEDBYTES],
const mld_poly *a)
__contract__(
requires(memory_no_alias(r, MLDSA_POLYW1_PACKEDBYTES))
requires(memory_no_alias(a, sizeof(mld_poly)))
requires(array_bound(a->coeffs, 0, MLDSA_N, 0, (MLDSA_Q-1)/(2*MLDSA_GAMMA2)))
assigns(memory_slice(r, MLDSA_POLYW1_PACKEDBYTES))
)
{
#if MLD_CONFIG_PARAMETER_SET == 44
mld_polyw1_pack_88(r, a);
#else
mld_polyw1_pack_32(r, a);
#endif
}
#endif
#endif