/* * SPDX-License-Identifier: CC0-1.0 * * Copyright (C) 2024, 2025 W. Kosior */ #ifndef PQCRYPTO_POLY_H #define PQCRYPTO_POLY_H #include #include #include #include "pqcrypto_prng.h" /*** *** Modulo operations. ***/ /* * FLINT seems to assume all modulo operations are performed on integers in * range [0, n-1]. Here we provide a facility for performing modulo operations * on big integers in range [-(n-1)/2, (n-1)/2]. */ struct mod_centered_0_ctx { fmpz_t divisor; fmpz_t range_max; }; typedef struct mod_centered_0_ctx mod_centered_0_ctx_t[1]; void mod_c0_ctx_init(mod_centered_0_ctx_t ctx, fmpz_t divisor); void mod_c0_ctx_clear(mod_centered_0_ctx_t ctx); void mod_c0(fmpz_t value, mod_centered_0_ctx_t const ctx); void mod_c0_ctx_init_set(mod_centered_0_ctx_t dst_ctx, mod_centered_0_ctx_t const src_ctx); void mod_c0_prng(fmpz_t value, mod_centered_0_ctx_t const ctx, prng_t prng, void * state); void mod_c0_rand(fmpz_t value, mod_centered_0_ctx_t const ctx); /*** *** Simple operations on polynomials. ***/ void poly_prng_mod_c0(fmpz_poly_t res, prng_t prng, void * prng_state, ulong coef_count, mod_centered_0_ctx_t const ctx); void poly_rand_mod_c0(fmpz_poly_t res, ulong coef_count, mod_centered_0_ctx_t const ctx); bool poly_all_abs_leq(fmpz_poly_struct const * poly, fmpz const * max_coef); bool poly_all_abs_leq_ui(fmpz_poly_struct const * poly, ulong max_coef); /*** *** Operations in polynomial rings. ***/ /* * Here we provide a facility for performing operations in polynomial rings * modulo X^m+1 over fields of integers modulo n shifted to range [-(n-1)/2, * (n-1)/2]. */ struct poly_ring_ctx { mod_centered_0_ctx_t mod_ctx; ulong divisor_degree; }; typedef struct poly_ring_ctx poly_ring_ctx_t[1]; void poly_ring_ctx_init(poly_ring_ctx_t ctx, mod_centered_0_ctx_t mod_ctx, ulong divisor_degree); void poly_ring_ctx_clear(poly_ring_ctx_t ctx); /* * Applies modulo operations to make poly a member of the ring designated by * ctx. */ void poly_to_ring(fmpz_poly_t poly, poly_ring_ctx_t const ctx); void poly_mul_in_ring(fmpz_poly_t res, fmpz_poly_t const poly1, fmpz_poly_t const poly2, poly_ring_ctx_t const ctx); void poly_add_in_ring(fmpz_poly_t res, fmpz_poly_t const poly1, fmpz_poly_t const poly2, poly_ring_ctx_t const ctx); void poly_sub_in_ring(fmpz_poly_t res, fmpz_poly_t const poly1, fmpz_poly_t const poly2, poly_ring_ctx_t const ctx); void poly_prng_in_ring(fmpz_poly_t res, prng_t prng, void * prng_state, poly_ring_ctx_t const ctx); void poly_rand_in_ring(fmpz_poly_t res, poly_ring_ctx_t const ctx); #endif /* PQCRYPTO_POLY_H */