Files
sqisign_new/src/quaternion/ref/generic/hnf/hnf_internal.c
SQIsign team 91e9e464fe second-round version of SQIsign
Co-authored-by: Marius A. Aardal <marius.andre.aardal@gmail.com>
Co-authored-by: Gora Adj <gora.adj@tii.ae>
Co-authored-by: Diego F. Aranha <dfaranha@cs.au.dk>
Co-authored-by: Andrea Basso <sqisign@andreabasso.com>
Co-authored-by: Isaac Andrés Canales Martínez <icanalesm0500@gmail.com>
Co-authored-by: Jorge Chávez-Saab <jorgechavezsaab@gmail.com>
Co-authored-by: Maria Corte-Real Santos <mariascrsantos98@gmail.com>
Co-authored-by: Luca De Feo <github@defeo.lu>
Co-authored-by: Max Duparc <max.duparc@epfl.ch>
Co-authored-by: Jonathan Komada Eriksen <jonathan.eriksen97@gmail.com>
Co-authored-by: Décio Luiz Gazzoni Filho <decio@decpp.net>
Co-authored-by: Basil Hess <bhe@zurich.ibm.com>
Co-authored-by: Antonin Leroux <antonin.leroux@polytechnique.org>
Co-authored-by: Patrick Longa <plonga@microsoft.com>
Co-authored-by: Luciano Maino <mainoluciano.96@gmail.com>
Co-authored-by: Michael Meyer <michael@random-oracles.org>
Co-authored-by: Hiroshi Onuki <onuki@mist.i.u-tokyo.ac.jp>
Co-authored-by: Lorenz Panny <lorenz@yx7.cc>
Co-authored-by: Giacomo Pope <giacomopope@gmail.com>
Co-authored-by: Krijn Reijnders <reijnderskrijn@gmail.com>
Co-authored-by: Damien Robert <damien.robert@inria.fr>
Co-authored-by: Francisco Rodríguez-Henriquez <francisco.rodriguez@tii.ae>
Co-authored-by: Sina Schaeffler <sschaeffle@student.ethz.ch>
Co-authored-by: Benjamin Wesolowski <benjamin.wesolowski@ens-lyon.fr>
2025-04-03 23:31:37 +02:00

183 lines
4.9 KiB
C

#include "hnf_internal.h"
#include "internal.h"
// Small helper for integers
void
ibz_mod_not_zero(ibz_t *res, const ibz_t *x, const ibz_t *mod)
{
ibz_t m, t;
ibz_init(&m);
ibz_init(&t);
ibz_mod(&m, x, mod);
ibz_set(&t, ibz_is_zero(&m));
ibz_mul(&t, &t, mod);
ibz_add(res, &m, &t);
ibz_finalize(&m);
ibz_finalize(&t);
}
// centered and rather positive then negative
void
ibz_centered_mod(ibz_t *remainder, const ibz_t *a, const ibz_t *mod)
{
assert(ibz_cmp(mod, &ibz_const_zero) > 0);
ibz_t tmp, d, t;
ibz_init(&tmp);
ibz_init(&d);
ibz_init(&t);
ibz_div_floor(&d, &tmp, mod, &ibz_const_two);
ibz_mod_not_zero(&tmp, a, mod);
ibz_set(&t, ibz_cmp(&tmp, &d) > 0);
ibz_mul(&t, &t, mod);
ibz_sub(remainder, &tmp, &t);
ibz_finalize(&tmp);
ibz_finalize(&d);
ibz_finalize(&t);
}
// if c, res = x, else res = y
void
ibz_conditional_assign(ibz_t *res, const ibz_t *x, const ibz_t *y, int c)
{
ibz_t s, t, r;
ibz_init(&r);
ibz_init(&s);
ibz_init(&t);
ibz_set(&s, c != 0);
ibz_sub(&t, &ibz_const_one, &s);
ibz_mul(&r, &s, x);
ibz_mul(res, &t, y);
ibz_add(res, &r, res);
ibz_finalize(&r);
ibz_finalize(&s);
ibz_finalize(&t);
}
// mpz_gcdext specification specifies unique outputs used here
void
ibz_xgcd_with_u_not_0(ibz_t *d, ibz_t *u, ibz_t *v, const ibz_t *x, const ibz_t *y)
{
if (ibz_is_zero(x) & ibz_is_zero(y)) {
ibz_set(d, 1);
ibz_set(u, 1);
ibz_set(v, 0);
return;
}
ibz_t q, r, x1, y1;
ibz_init(&q);
ibz_init(&r);
ibz_init(&x1);
ibz_init(&y1);
ibz_copy(&x1, x);
ibz_copy(&y1, y);
// xgcd
ibz_xgcd(d, u, v, &x1, &y1);
// make sure u!=0 (v can be 0 if needed)
// following GMP specification, u == 0 implies y|x
if (ibz_is_zero(u)) {
if (!ibz_is_zero(&x1)) {
if (ibz_is_zero(&y1)) {
ibz_set(&y1, 1);
}
ibz_div(&q, &r, &x1, &y1);
assert(ibz_is_zero(&r));
ibz_sub(v, v, &q);
}
ibz_set(u, 1);
}
if (!ibz_is_zero(&x1)) {
// Make sure ux > 0 (and as small as possible)
assert(ibz_cmp(d, &ibz_const_zero) > 0);
ibz_mul(&r, &x1, &y1);
int neg = ibz_cmp(&r, &ibz_const_zero) < 0;
ibz_mul(&q, &x1, u);
while (ibz_cmp(&q, &ibz_const_zero) <= 0) {
ibz_div(&q, &r, &y1, d);
assert(ibz_is_zero(&r));
if (neg) {
ibz_neg(&q, &q);
}
ibz_add(u, u, &q);
ibz_div(&q, &r, &x1, d);
assert(ibz_is_zero(&r));
if (neg) {
ibz_neg(&q, &q);
}
ibz_sub(v, v, &q);
ibz_mul(&q, &x1, u);
}
}
#ifndef NDEBUG
int res = 0;
ibz_t sum, prod, test, cmp;
ibz_init(&sum);
ibz_init(&prod);
ibz_init(&cmp);
ibz_init(&test);
// sign correct
res = res | !(ibz_cmp(d, &ibz_const_zero) >= 0);
if (ibz_is_zero(&x1) && ibz_is_zero(&y1)) {
res = res | !(ibz_is_zero(v) && ibz_is_one(u) && ibz_is_one(d));
} else {
if (!ibz_is_zero(&x1) && !ibz_is_zero(&y1)) {
// GCD divides x
ibz_div(&sum, &prod, &x1, d);
res = res | !ibz_is_zero(&prod);
// Small enough
ibz_mul(&prod, &x1, u);
res = res | !(ibz_cmp(&prod, &ibz_const_zero) > 0);
ibz_mul(&sum, &sum, &y1);
ibz_abs(&sum, &sum);
res = res | !(ibz_cmp(&prod, &sum) <= 0);
// GCD divides y
ibz_div(&sum, &prod, &y1, d);
res = res | !ibz_is_zero(&prod);
// Small enough
ibz_mul(&prod, &y1, v);
res = res | !(ibz_cmp(&prod, &ibz_const_zero) <= 0);
ibz_mul(&sum, &sum, &x1);
ibz_abs(&sum, &sum);
res = res | !(ibz_cmp(&prod, &sum) < 0);
} else {
// GCD divides x
ibz_div(&sum, &prod, &x1, d);
res = res | !ibz_is_zero(&prod);
// GCD divides y
ibz_div(&sum, &prod, &y1, d);
res = res | !ibz_is_zero(&prod);
if (ibz_is_zero(&x1) && !ibz_is_zero(&y1)) {
ibz_abs(&prod, v);
res = res | !(ibz_is_one(&prod));
res = res | !(ibz_is_one(u));
} else {
ibz_abs(&prod, u);
res = res | !(ibz_is_one(&prod));
res = res | !(ibz_is_zero(v));
}
}
// Bezout coeffs
ibz_mul(&sum, &x1, u);
ibz_mul(&prod, &y1, v);
ibz_add(&sum, &sum, &prod);
res = res | !(ibz_cmp(&sum, d) == 0);
}
assert(!res);
ibz_finalize(&sum);
ibz_finalize(&prod);
ibz_finalize(&cmp);
ibz_finalize(&test);
#endif
ibz_finalize(&x1);
ibz_finalize(&y1);
ibz_finalize(&q);
ibz_finalize(&r);
}