1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
|
/*
* 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 */
|