aboutsummaryrefslogtreecommitdiff
/*
 * SPDX-License-Identifier: CC0-1.0
 *
 * Copyright (C) 2024, 2025 W. Kosior <koszko@koszko.org>
 */

#ifndef PQCRYPTO_POLY_H
#define PQCRYPTO_POLY_H

#include <stdbool.h>

#include <flint/fmpz.h>
#include <flint/fmpz_poly.h>

#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 */