Files
sqisign_new/src/quaternion/ref/generic/test/ideal.c
SQIsign team 28ff420dd0 initial version of SQIsign
Co-authored-by: Jorge Chavez-Saab <jorgechavezsaab@gmail.com>
Co-authored-by: Maria Corte-Real Santos <36373796+mariascrs@users.noreply.github.com>
Co-authored-by: Luca De Feo <github@defeo.lu>
Co-authored-by: Jonathan Komada Eriksen <jonathan.eriksen97@gmail.com>
Co-authored-by: Basil Hess <bhe@zurich.ibm.com>
Co-authored-by: Antonin Leroux <18654258+tonioecto@users.noreply.github.com>
Co-authored-by: Patrick Longa <plonga@microsoft.com>
Co-authored-by: Lorenz Panny <lorenz@yx7.cc>
Co-authored-by: Francisco Rodríguez-Henríquez <francisco.rodriguez@tii.ae>
Co-authored-by: Sina Schaeffler <108983332+syndrakon@users.noreply.github.com>
Co-authored-by: Benjamin Wesolowski <19474926+Calodeon@users.noreply.github.com>
2023-07-09 12:48:54 +02:00

968 lines
33 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "quaternion_tests.h"
//void quat_lideal_create_principal(quat_left_ideal_t *lideal, const quat_alg_elem_t *x, const quat_order_t *order, const quat_alg_t *alg);
int quat_test_lideal_create_principal(){
int res = 0;
// Example from https://github.com/SQISign/sqisign-nist/issues/38#issuecomment-1554585079
quat_alg_t alg;
quat_order_t lat;
quat_alg_elem_t gamma;
quat_left_ideal_t I;
quat_alg_init_set_ui(&alg, 367);
quat_order_init(&lat);
quat_alg_elem_init(&gamma);
quat_left_ideal_init(&I);
ibz_set(&lat.denom, 2);
ibz_set(&lat.basis[0][0], 2);
ibz_set(&lat.basis[1][1], 2);
ibz_set(&lat.basis[1][2], 1);
ibz_set(&lat.basis[2][2], 1);
ibz_set(&lat.basis[3][3], 1);
ibz_set(&lat.basis[0][3], 1);
ibz_set(&gamma.coord[0], 219);
ibz_set(&gamma.coord[1], 200);
ibz_set(&gamma.coord[2], 78);
ibz_set(&gamma.coord[3], -1);
quat_lideal_create_principal(&I, &gamma, &lat, &alg);
res |= I.parent_order != &lat;
res |= ibz_cmp_si(&I.norm, 2321156);
res |= ibz_cmp(&I.lattice.denom, &ibz_const_one);
res |= ibz_cmp_si(&I.lattice.basis[0][0], 1160578);
res |= ibz_cmp_si(&I.lattice.basis[1][0], 0);
res |= ibz_cmp_si(&I.lattice.basis[2][0], 0);
res |= ibz_cmp_si(&I.lattice.basis[3][0], 0);
res |= ibz_cmp_si(&I.lattice.basis[0][1], 0);
res |= ibz_cmp_si(&I.lattice.basis[1][1], 1160578);
res |= ibz_cmp_si(&I.lattice.basis[2][1], 0);
res |= ibz_cmp_si(&I.lattice.basis[3][1], 0);
res |= ibz_cmp_si(&I.lattice.basis[0][2], 310126);
res |= ibz_cmp_si(&I.lattice.basis[1][2], 182529);
res |= ibz_cmp_si(&I.lattice.basis[2][2], 1);
res |= ibz_cmp_si(&I.lattice.basis[3][2], 0);
res |= ibz_cmp_si(&I.lattice.basis[0][3], 978049);
res |= ibz_cmp_si(&I.lattice.basis[1][3], 310126);
res |= ibz_cmp_si(&I.lattice.basis[2][3], 0);
res |= ibz_cmp_si(&I.lattice.basis[3][3], 1);
// same test, just with gamma not reduced
ibz_set(&gamma.coord[0], 438);
ibz_set(&gamma.coord[1], 400);
ibz_set(&gamma.coord[2], 156);
ibz_set(&gamma.coord[3], -2);
ibz_set(&gamma.denom, 2);
quat_lideal_create_principal(&I, &gamma, &lat, &alg);
res |= I.parent_order != &lat;
res |= ibz_cmp_si(&I.norm, 2321156);
res |= ibz_cmp(&I.lattice.denom, &ibz_const_one);
res |= ibz_cmp_si(&I.lattice.basis[0][0], 1160578);
res |= ibz_cmp_si(&I.lattice.basis[1][0], 0);
res |= ibz_cmp_si(&I.lattice.basis[2][0], 0);
res |= ibz_cmp_si(&I.lattice.basis[3][0], 0);
res |= ibz_cmp_si(&I.lattice.basis[0][1], 0);
res |= ibz_cmp_si(&I.lattice.basis[1][1], 1160578);
res |= ibz_cmp_si(&I.lattice.basis[2][1], 0);
res |= ibz_cmp_si(&I.lattice.basis[3][1], 0);
res |= ibz_cmp_si(&I.lattice.basis[0][2], 310126);
res |= ibz_cmp_si(&I.lattice.basis[1][2], 182529);
res |= ibz_cmp_si(&I.lattice.basis[2][2], 1);
res |= ibz_cmp_si(&I.lattice.basis[3][2], 0);
res |= ibz_cmp_si(&I.lattice.basis[0][3], 978049);
res |= ibz_cmp_si(&I.lattice.basis[1][3], 310126);
res |= ibz_cmp_si(&I.lattice.basis[2][3], 0);
res |= ibz_cmp_si(&I.lattice.basis[3][3], 1);
// same test, just with gamma and basis not reduced
ibz_set(&lat.denom, 6);
ibz_set(&lat.basis[0][0], 6);
ibz_set(&lat.basis[1][1], 6);
ibz_set(&lat.basis[1][2], 3);
ibz_set(&lat.basis[2][2], 3);
ibz_set(&lat.basis[3][3], 3);
ibz_set(&lat.basis[0][3], 3);
ibz_set(&gamma.coord[0], 438);
ibz_set(&gamma.coord[1], 400);
ibz_set(&gamma.coord[2], 156);
ibz_set(&gamma.coord[3], -2);
ibz_set(&gamma.denom, 2);
quat_lideal_create_principal(&I, &gamma, &lat, &alg);
res |= I.parent_order != &lat;
res |= ibz_cmp_si(&I.norm, 2321156);
res |= ibz_cmp(&I.lattice.denom, &ibz_const_one);
res |= ibz_cmp_si(&I.lattice.basis[0][0], 1160578);
res |= ibz_cmp_si(&I.lattice.basis[1][0], 0);
res |= ibz_cmp_si(&I.lattice.basis[2][0], 0);
res |= ibz_cmp_si(&I.lattice.basis[3][0], 0);
res |= ibz_cmp_si(&I.lattice.basis[0][1], 0);
res |= ibz_cmp_si(&I.lattice.basis[1][1], 1160578);
res |= ibz_cmp_si(&I.lattice.basis[2][1], 0);
res |= ibz_cmp_si(&I.lattice.basis[3][1], 0);
res |= ibz_cmp_si(&I.lattice.basis[0][2], 310126);
res |= ibz_cmp_si(&I.lattice.basis[1][2], 182529);
res |= ibz_cmp_si(&I.lattice.basis[2][2], 1);
res |= ibz_cmp_si(&I.lattice.basis[3][2], 0);
res |= ibz_cmp_si(&I.lattice.basis[0][3], 978049);
res |= ibz_cmp_si(&I.lattice.basis[1][3], 310126);
res |= ibz_cmp_si(&I.lattice.basis[2][3], 0);
res |= ibz_cmp_si(&I.lattice.basis[3][3], 1);
quat_alg_finalize(&alg);
quat_order_finalize(&lat);
quat_alg_elem_finalize(&gamma);
quat_left_ideal_finalize(&I);
if (res != 0){
printf("Quaternion unit test lideal_create_principal failed\n");
}
return(res);
}
//void quat_lideal_create_from_primitive(quat_left_ideal_t *lideal, const quat_alg_elem_t *x, const ibz_t *N, const quat_order_t *order, const quat_alg_t *alg);
int quat_test_lideal_create_from_primitive(){
int res = 0;
// Example from https://github.com/SQISign/sqisign-nist/issues/38#issuecomment-1554585079
quat_alg_t alg;
quat_order_t lat;
quat_alg_elem_t gamma;
ibz_t N;
quat_left_ideal_t I;
quat_alg_init_set_ui(&alg, 367);
quat_order_init(&lat);
quat_alg_elem_init(&gamma);
ibz_init(&N);
quat_left_ideal_init(&I);
ibz_set(&lat.denom, 2);
ibz_set(&lat.basis[0][0], 2);
ibz_set(&lat.basis[1][1], 2);
ibz_set(&lat.basis[1][2], 1);
ibz_set(&lat.basis[2][2], 1);
ibz_set(&lat.basis[3][3], 1);
ibz_set(&lat.basis[0][3], 1);
ibz_set(&gamma.coord[0], 219);
ibz_set(&gamma.coord[1], 200);
ibz_set(&gamma.coord[2], 78);
ibz_set(&gamma.coord[3], -1);
ibz_set(&N, 31);
quat_lideal_create_from_primitive(&I, &gamma, &N, &lat, &alg);
res |= I.parent_order != &lat;
res |= ibz_cmp(&I.norm, &N);
res |= ibz_cmp(&I.lattice.denom, &ibz_const_two);
res |= ibz_cmp_si(&I.lattice.basis[0][0], 62);
res |= ibz_cmp_si(&I.lattice.basis[1][0], 0);
res |= ibz_cmp_si(&I.lattice.basis[2][0], 0);
res |= ibz_cmp_si(&I.lattice.basis[3][0], 0);
res |= ibz_cmp_si(&I.lattice.basis[0][1], 0);
res |= ibz_cmp_si(&I.lattice.basis[1][1], 62);
res |= ibz_cmp_si(&I.lattice.basis[2][1], 0);
res |= ibz_cmp_si(&I.lattice.basis[3][1], 0);
res |= ibz_cmp_si(&I.lattice.basis[0][2], 2);
res |= ibz_cmp_si(&I.lattice.basis[1][2], 1);
res |= ibz_cmp_si(&I.lattice.basis[2][2], 1);
res |= ibz_cmp_si(&I.lattice.basis[3][2], 0);
res |= ibz_cmp_si(&I.lattice.basis[0][3], 61);
res |= ibz_cmp_si(&I.lattice.basis[1][3], 2);
res |= ibz_cmp_si(&I.lattice.basis[2][3], 0);
res |= ibz_cmp_si(&I.lattice.basis[3][3], 1);
quat_alg_finalize(&alg);
quat_order_finalize(&lat);
quat_alg_elem_finalize(&gamma);
ibz_finalize(&N);
quat_left_ideal_finalize(&I);
if (res != 0){
printf("Quaternion unit test lideal_create_from_primitive failed\n");
}
return(res);
}
//void quat_lideal_make_primitive_then_create(quat_left_ideal_t *lideal, const quat_alg_elem_t *x, const ibz_t *N, const quat_order_t *order, const quat_alg_t *alg);
int quat_test_lideal_make_primitive_then_create(){
int res = 0;
ibz_t n, cnt;
quat_alg_t alg;
quat_alg_elem_t gen, x;
quat_alg_coord_t prim;
quat_order_t order;
quat_left_ideal_t lideal,cmp;
quat_left_ideal_init(&lideal);
quat_left_ideal_init(&cmp);
quat_alg_init_set_ui(&alg, 103);
quat_alg_elem_init(&gen);
quat_alg_elem_init(&x);
quat_alg_coord_init(&prim);
quat_order_init(&order);
ibz_init(&n);
ibz_init(&cnt);
ibz_set(&order.denom, 2);
ibz_set(&order.basis[0][0], 2);
ibz_set(&order.basis[1][1], 2);
ibz_set(&order.basis[1][2], 1);
ibz_set(&order.basis[2][2], 1);
ibz_set(&order.basis[3][3], 1);
ibz_set(&order.basis[0][3], 1);
ibz_set(&x.coord[0], 6);
ibz_set(&x.coord[1], 10);
ibz_set(&x.coord[2], 14);
ibz_set(&x.coord[3], 22);
ibz_set(&n, 17);
quat_lideal_make_primitive_then_create(&lideal,&x,&n,&order,&alg);
quat_alg_make_primitive(&prim,&cnt,&x,&order,&alg);
ibz_mat_4x4_eval(&(gen.coord),&(order.basis),&prim);
ibz_copy(&gen.denom,&order.denom);
quat_lideal_create_from_primitive(&cmp,&gen,&n,&order,&alg);
res = res || !quat_lideal_equals(&lideal,&cmp,&alg);
if (res != 0){
printf("Quaternion unit test lideal_make_primitive_then_create failed\n");
}
quat_alg_finalize(&alg);
quat_alg_elem_finalize(&gen);
quat_alg_elem_finalize(&x);
quat_alg_coord_finalize(&prim);
quat_order_finalize(&order);
ibz_finalize(&n);
ibz_finalize(&cnt);
quat_left_ideal_finalize(&lideal);
quat_left_ideal_finalize(&cmp);
return(res);
}
//void quat_lideal_random_2e(quat_left_ideal_t *lideal, const quat_order_t *order, const quat_alg_t *alg, int64_t e, unsigned char n);
int quat_test_lideal_random_2e(){
int res = 0;
quat_alg_t alg;
quat_order_t order;
quat_left_ideal_t lideal;
quat_alg_init_set_ui(&alg, 103);
quat_order_init(&order);
quat_left_ideal_init(&lideal);
ibz_set(&order.denom, 2);
ibz_set(&order.basis[0][0], 2);
ibz_set(&order.basis[1][1], 2);
ibz_set(&order.basis[1][2], 1);
ibz_set(&order.basis[2][2], 1);
ibz_set(&order.basis[3][3], 1);
ibz_set(&order.basis[0][3], 1);
// Pretty much self-testing (thanks to embedded asserts)
res |= quat_lideal_random_2e(&lideal, &order, &alg, 100, 10) == 0;
quat_alg_finalize(&alg);
quat_order_finalize(&order);
quat_left_ideal_finalize(&lideal);
if (res != 0){
printf("Quaternion unit test lideal_random_2e failed\n");
}
return(res);
}
//int quat_lideal_generator(quat_alg_elem_t *gen, const quat_left_ideal_t *lideal, const quat_alg_t *alg, int bound)
int quat_test_lideal_generator(){
int res = 0;
quat_alg_t alg;
quat_order_t order;
quat_alg_elem_t gen;
ibz_t N;
quat_left_ideal_t lideal, lideal2;
quat_alg_init_set_ui(&alg, 103);
quat_order_init(&order);
quat_alg_elem_init(&gen);
ibz_init(&N);
quat_left_ideal_init(&lideal);
quat_left_ideal_init(&lideal2);
ibz_set(&order.denom, 2);
ibz_set(&order.basis[0][0], 2);
ibz_set(&order.basis[1][1], 2);
ibz_set(&order.basis[1][2], 1);
ibz_set(&order.basis[2][2], 1);
ibz_set(&order.basis[3][3], 1);
ibz_set(&order.basis[0][3], 1);
ibz_set(&gen.coord[0], 3);
ibz_set(&gen.coord[1], 5);
ibz_set(&gen.coord[2], 7);
ibz_set(&gen.coord[3], 11);
ibz_set(&N, 17);
quat_lideal_create_from_primitive(&lideal, &gen, &N, &order, &alg);
// Try to regenerate the same ideal
for (int i = 0; i <= 10; i++) {
res |= !quat_lideal_generator(&gen, &lideal, &alg,0);
quat_lideal_create_from_primitive(&lideal2, &gen, &N, &order, &alg);
res |= !quat_lideal_equals(&lideal, &lideal2, &alg);
}
quat_alg_finalize(&alg);
quat_order_finalize(&order);
quat_alg_elem_finalize(&gen);
ibz_finalize(&N);
quat_left_ideal_finalize(&lideal);
quat_left_ideal_finalize(&lideal2);
if (res != 0){
printf("Quaternion unit test lideal_generator failed\n");
}
return(res);
}
//int quat_lideal_generator_coprime(quat_alg_elem_t *gen, const quat_left_ideal_t *lideal, const ibz_t *n, const quat_alg_t *alg, int bound);
int quat_test_lideal_generator_coprime(){
int res = 0;
quat_alg_t alg;
quat_order_t order, order2;
quat_alg_elem_t gen;
ibz_t N, M, gcd, norm_int, prod;
ibq_t norm;
quat_left_ideal_t lideal, lideal2;
quat_alg_init_set_ui(&alg, 103);
quat_order_init(&order);
quat_order_init(&order2);
quat_alg_elem_init(&gen);
ibz_init(&N);
ibz_init(&M);
ibz_init(&norm_int);
ibz_init(&prod);
ibz_init(&gcd);
ibq_init(&norm);
quat_left_ideal_init(&lideal);
quat_left_ideal_init(&lideal2);
ibz_set(&order.denom, 2);
ibz_set(&order.basis[0][0], 2);
ibz_set(&order.basis[1][1], 2);
ibz_set(&order.basis[1][2], 1);
ibz_set(&order.basis[2][2], 1);
ibz_set(&order.basis[3][3], 1);
ibz_set(&order.basis[0][3], 1);
ibz_set(&gen.coord[0], 3);
ibz_set(&gen.coord[1], 5);
ibz_set(&gen.coord[2], 7);
ibz_set(&gen.coord[3], 11);
ibz_set(&N, 5);
// product of primes < 50
ibz_set(&M, 614889782588491410l);
quat_lideal_create_from_primitive(&lideal, &gen, &N, &order, &alg);
res |= !quat_lideal_generator_coprime(&gen, &lideal, &M, &alg,0);
quat_alg_norm(&norm, &gen, &alg);
res |= !ibq_to_ibz(&norm_int, &norm);
// case with coprimality
ibz_gcd(&gcd, &norm_int, &M);
res |= !ibz_is_one(&gcd);
// test other formula
ibz_mul(&prod,&M,&M);
ibz_gcd(&prod,&prod,&norm_int);
ibz_gcd(&gcd, &(lideal.norm), &M);
res |= ibz_cmp(&gcd,&prod);
quat_lideal_create_from_primitive(&lideal2, &gen, &N, &order, &alg);
res |= !quat_lideal_equals(&lideal, &lideal2, &alg);
res |= !quat_alg_is_primitive(&gen,&(lideal.lattice), &alg);
ibz_set(&(order.denom),1);
quat_alg_elem_set(&gen,1,2,4,2,6);
quat_lideal_create_from_primitive(&lideal, &gen, &N, &order, &alg);
ibz_set(&M,15);
res |= !quat_lideal_generator_coprime(&gen, &lideal, &M, &alg,0);
quat_alg_norm(&norm, &gen, &alg);
res |= !ibq_to_ibz(&norm_int, &norm);
// test other formula
ibz_mul(&prod,&M,&M);
ibz_gcd(&prod,&prod,&norm_int);
ibz_gcd(&gcd, &(lideal.norm), &M);
res |= ibz_cmp(&gcd,&prod);
quat_lideal_create_from_primitive(&lideal2, &gen, &N, &order, &alg);
res |= !quat_lideal_equals(&lideal, &lideal2, &alg);
res |= !quat_alg_is_primitive(&gen,&(lideal.lattice), &alg);
quat_alg_finalize(&alg);
quat_order_finalize(&order);
quat_order_finalize(&order2);
quat_alg_elem_finalize(&gen);
ibz_finalize(&N);
ibz_finalize(&M);
ibz_finalize(&norm_int);
ibz_finalize(&prod);
ibz_finalize(&gcd);
ibq_finalize(&norm);
quat_left_ideal_finalize(&lideal);
quat_left_ideal_finalize(&lideal2);
if (res != 0){
printf("Quaternion unit test lideal_generator_coprime failed\n");
}
return(res);
}
//int quat_lideal_mul(quat_left_ideal_t *product, const quat_left_ideal_t *lideal, const quat_alg_elem_t *alpha, const quat_alg_t *alg, int bound);
int quat_test_lideal_mul(){
int res = 0;
quat_alg_t alg;
quat_order_t order;
quat_alg_elem_t gen1, gen2, gen_prod;
quat_left_ideal_t lideal, lideal2;
quat_alg_init_set_ui(&alg, 103);
quat_order_init(&order);
quat_alg_elem_init(&gen1);
quat_alg_elem_init(&gen2);
quat_alg_elem_init(&gen_prod);
quat_left_ideal_init(&lideal);
quat_left_ideal_init(&lideal2);
ibz_set(&order.denom, 2);
ibz_set(&order.basis[0][0], 2);
ibz_set(&order.basis[1][1], 2);
ibz_set(&order.basis[1][2], 1);
ibz_set(&order.basis[2][2], 1);
ibz_set(&order.basis[3][3], 1);
ibz_set(&order.basis[0][3], 1);
ibz_set(&gen1.coord[0], 3);
ibz_set(&gen1.coord[1], 5);
ibz_set(&gen1.coord[2], 7);
ibz_set(&gen1.coord[3], 11);
ibz_set(&gen2.coord[0], -2);
ibz_set(&gen2.coord[1], 13);
ibz_set(&gen2.coord[2], -17);
ibz_set(&gen2.coord[3], 19);
// Check that (O·gen1)·gen2 == O·(gen1·gen2)
quat_lideal_create_principal(&lideal, &gen1, &order, &alg);
res |= !quat_lideal_mul(&lideal, &lideal, &gen2, &alg,0);
quat_alg_mul(&gen_prod, &gen1, &gen2, &alg);
quat_lideal_create_principal(&lideal2, &gen_prod, &order, &alg);
res |= !quat_lideal_equals(&lideal, &lideal2, &alg);
// Same test, but with non-integral gen2
ibz_set(&(gen2.denom),2);
quat_lideal_create_principal(&lideal, &gen1, &order, &alg);
res |= !quat_lideal_mul(&lideal, &lideal, &gen2, &alg,0);
quat_alg_mul(&gen_prod, &gen1, &gen2, &alg);
quat_lideal_create_principal(&lideal2, &gen_prod, &order, &alg);
res |= !quat_lideal_equals(&lideal, &lideal2, &alg);
quat_alg_finalize(&alg);
quat_order_finalize(&order);
quat_alg_elem_finalize(&gen1);
quat_alg_elem_finalize(&gen2);
quat_alg_elem_finalize(&gen_prod);
quat_left_ideal_finalize(&lideal);
quat_left_ideal_finalize(&lideal2);
if (res != 0){
printf("Quaternion unit test lideal_mul failed\n");
}
return(res);
}
//void quat_lideal_add(quat_left_ideal_t *sum, const quat_left_ideal_t *I1, const quat_left_ideal_t *I2, const quat_alg_t *alg);
//void quat_lideal_inter(quat_left_ideal_t *intersection, const quat_left_ideal_t *I1, const quat_left_ideal_t *I2, const quat_alg_t *alg);
//int quat_lideal_equals(const quat_left_ideal_t *I1, const quat_left_ideal_t *I2, const quat_alg_t *alg);
int quat_test_lideal_add_intersect_equals(){
int res = 0;
quat_alg_t alg;
quat_order_t order;
quat_alg_elem_t gen1, gen2, gen3;
ibz_t N1, N2, N3;
quat_left_ideal_t lideal1, lideal2, lideal3, lideal4, lideal5;
quat_alg_init_set_ui(&alg, 103);
quat_order_init(&order);
quat_alg_elem_init(&gen1);
quat_alg_elem_init(&gen2);
quat_alg_elem_init(&gen3);
ibz_init(&N1);
ibz_init(&N2);
ibz_init(&N3);
quat_left_ideal_init(&lideal1);
quat_left_ideal_init(&lideal2);
quat_left_ideal_init(&lideal3);
quat_left_ideal_init(&lideal4);
quat_left_ideal_init(&lideal5);
ibz_set(&order.denom, 2);
ibz_set(&order.basis[0][0], 2);
ibz_set(&order.basis[1][1], 2);
ibz_set(&order.basis[1][2], 1);
ibz_set(&order.basis[2][2], 1);
ibz_set(&order.basis[3][3], 1);
ibz_set(&order.basis[0][3], 1);
ibz_set(&gen1.coord[0], 3);
ibz_set(&gen1.coord[1], 5);
ibz_set(&gen1.coord[2], 7);
ibz_set(&gen1.coord[3], 11);
ibz_set(&N1, 17);
quat_lideal_create_from_primitive(&lideal1, &gen1, &N1, &order, &alg);
ibz_set(&gen2.coord[0], -2);
ibz_set(&gen2.coord[1], 13);
ibz_set(&gen2.coord[2], -17);
ibz_set(&gen2.coord[3], 19);
ibz_set(&N2, 43);
quat_lideal_create_from_primitive(&lideal2, &gen2, &N2, &order, &alg);
quat_alg_mul(&gen3, &gen2, &gen1, &alg);
quat_lideal_create_principal(&lideal3, &gen3, &order, &alg);
// Union should be the whole ring
quat_lideal_add(&lideal4, &lideal1, &lideal2, &alg);
res |= !ibz_is_one(&lideal4.norm);
res |= !quat_lattice_equal(&lideal4.lattice, &order);
// Self-intersection should be stable
quat_lideal_inter(&lideal4, &lideal1, &lideal1, &alg);
res |= !quat_lideal_equals(&lideal4, &lideal1, &alg);
// Self-union should be stable
quat_lideal_add(&lideal4, &lideal1, &lideal1, &alg);
res |= !quat_lideal_equals(&lideal4, &lideal1, &alg);
// lideal3 ⊂ lideal1
quat_lideal_add(&lideal4, &lideal1, &lideal3, &alg);
res |= !quat_lideal_equals(&lideal4, &lideal1, &alg);
quat_lideal_inter(&lideal4, &lideal1, &lideal3, &alg);
res |= !quat_lideal_equals(&lideal4, &lideal3, &alg);
// Intersection then union should be stable
quat_lideal_inter(&lideal4, &lideal1, &lideal2, &alg);
quat_lideal_add(&lideal4, &lideal4, &lideal2, &alg);
res |= !quat_lideal_equals(&lideal4, &lideal2, &alg);
// (A ∩ B) (A ∩ C) == A ∩ (B C)
quat_lideal_inter(&lideal4, &lideal1, &lideal2, &alg);
quat_lideal_inter(&lideal5, &lideal1, &lideal3, &alg);
quat_lideal_add(&lideal4, &lideal4, &lideal5, &alg);
quat_lideal_add(&lideal5, &lideal2, &lideal3, &alg);
quat_lideal_inter(&lideal5, &lideal1, &lideal5, &alg);
res |= !quat_lideal_equals(&lideal4, &lideal5, &alg);
res |= ibz_cmp_si(&lideal4.norm, 17);
quat_alg_finalize(&alg);
quat_order_finalize(&order);
quat_alg_elem_finalize(&gen1);
quat_alg_elem_finalize(&gen2);
quat_alg_elem_finalize(&gen3);
ibz_finalize(&N1);
ibz_finalize(&N2);
ibz_finalize(&N3);
quat_left_ideal_finalize(&lideal1);
quat_left_ideal_finalize(&lideal2);
quat_left_ideal_finalize(&lideal3);
quat_left_ideal_finalize(&lideal4);
quat_left_ideal_finalize(&lideal5);
if (res != 0){
printf("Quaternion unit test lideal_add_intersect_equals failed\n");
}
return(res);
}
//int quat_lideal_isom(quat_alg_elem_t *iso, const quat_left_ideal_t *I1, const quat_left_ideal_t *I2, const quat_alg_t *alg);
int quat_test_lideal_isom(){
int res = 0;
quat_left_ideal_t lideal1,lideal2,prod;
ibz_t norm;
quat_alg_elem_t init_helper, isom;
quat_order_t order, order2;
quat_alg_t alg;
ibz_init(&norm);
quat_left_ideal_init(&lideal1);
quat_left_ideal_init(&lideal2);
quat_left_ideal_init(&prod);
quat_alg_init_set_ui(&alg,19);
quat_order_init(&order);
quat_order_init(&order2);
quat_alg_elem_init(&isom);
quat_alg_elem_init(&init_helper);
ibz_set(&(order.basis[0][0]),4);
ibz_set(&(order.basis[0][1]),0);
ibz_set(&(order.basis[0][2]),2);
ibz_set(&(order.basis[0][3]),2);
ibz_set(&(order.basis[1][0]),0);
ibz_set(&(order.basis[1][1]),8);
ibz_set(&(order.basis[1][2]),4);
ibz_set(&(order.basis[1][3]),3);
ibz_set(&(order.basis[2][0]),0);
ibz_set(&(order.basis[2][1]),0);
ibz_set(&(order.basis[2][2]),2);
ibz_set(&(order.basis[2][3]),0);
ibz_set(&(order.basis[3][0]),0);
ibz_set(&(order.basis[3][1]),0);
ibz_set(&(order.basis[3][2]),0);
ibz_set(&(order.basis[3][3]),1);
ibz_set(&(order.denom),4);
quat_alg_elem_set(&init_helper,1,2,6,2,1);
quat_lideal_create_principal(&lideal1,&init_helper,&order,&alg);
quat_alg_elem_set(&init_helper,3,1,6,5,1);
res |= !quat_lideal_mul(&lideal2,&lideal1,&init_helper,&alg,0);
res = res || !quat_lideal_isom(&isom,&lideal1,&lideal2,&alg);
if(!res){
res |= !quat_lideal_mul(&prod,&lideal1,&isom,&alg,0);
res = res || !quat_lideal_equals(&prod,&lideal2,&alg);
}
// not same order
ibz_set(&(order2.basis[0][0]),2);
ibz_set(&(order2.basis[0][1]),0);
ibz_set(&(order2.basis[0][2]),1);
ibz_set(&(order2.basis[0][3]),0);
ibz_set(&(order2.basis[1][0]),0);
ibz_set(&(order2.basis[1][1]),2);
ibz_set(&(order2.basis[1][2]),0);
ibz_set(&(order2.basis[1][3]),1);
ibz_set(&(order2.basis[2][0]),0);
ibz_set(&(order2.basis[2][1]),0);
ibz_set(&(order2.basis[2][2]),1);
ibz_set(&(order2.basis[2][3]),0);
ibz_set(&(order2.basis[3][0]),0);
ibz_set(&(order2.basis[3][1]),0);
ibz_set(&(order2.basis[3][2]),0);
ibz_set(&(order2.basis[3][3]),1);
ibz_set(&(order2.denom),2);
quat_alg_elem_set(&init_helper,1,2,6,2,1);
quat_lideal_create_principal(&lideal2,&init_helper,&order2,&alg);
res = res || quat_lideal_isom(&isom,&lideal1,&lideal2,&alg);
// should add test for not isomorphic ideals
if (res != 0){
printf("Quaternion unit test lideal_isom failed\n");
}
quat_left_ideal_finalize(&lideal1);
quat_left_ideal_finalize(&lideal2);
quat_left_ideal_finalize(&prod);
ibz_finalize(&norm);
quat_alg_finalize(&alg);
quat_order_finalize(&order);
quat_order_finalize(&order2);
quat_alg_elem_finalize(&isom);
quat_alg_elem_finalize(&init_helper);
return(res);
}
//void quat_lideal_right_order(quat_order_t *order, const quat_left_ideal_t *lideal, const quat_alg_t *alg);
int quat_test_lideal_right_order(){
int res = 0;
ibz_t norm;
quat_alg_t alg;
quat_alg_elem_t gen;
quat_order_t order,rorder;
quat_lattice_t prod;
quat_alg_elem_t test;
quat_left_ideal_t lideal, cmp;
quat_order_init(&order);
quat_order_init(&rorder);
quat_lattice_init(&prod);
quat_alg_init_set_ui(&alg,19);
quat_left_ideal_init(&lideal);
quat_alg_elem_init(&test);
quat_alg_elem_init(&gen);
ibz_set(&(order.basis[0][0]),4);
ibz_set(&(order.basis[0][1]),0);
ibz_set(&(order.basis[0][2]),2);
ibz_set(&(order.basis[0][3]),2);
ibz_set(&(order.basis[1][0]),0);
ibz_set(&(order.basis[1][1]),8);
ibz_set(&(order.basis[1][2]),4);
ibz_set(&(order.basis[1][3]),3);
ibz_set(&(order.basis[2][0]),0);
ibz_set(&(order.basis[2][1]),0);
ibz_set(&(order.basis[2][2]),2);
ibz_set(&(order.basis[2][3]),0);
ibz_set(&(order.basis[3][0]),0);
ibz_set(&(order.basis[3][1]),0);
ibz_set(&(order.basis[3][2]),0);
ibz_set(&(order.basis[3][3]),1);
ibz_set(&(order.denom),4);
quat_alg_elem_set(&gen,1,2,1,8,-8);
quat_lideal_create_principal(&lideal,&gen,&order,&alg);
quat_lideal_right_order(&rorder,&lideal,&alg);
// test order is in HNF
res = res || !ibz_mat_4x4_is_hnf(&(rorder.basis));
// test order is of dimension 4 (assuming HNF)
for(int i = 0; i < 4; i++){
quat_alg_elem_copy_ibz(&test,&(rorder.denom),&(rorder.basis[0][i]),&(rorder.basis[1][i]),&(rorder.basis[2][i]),&(rorder.basis[3][i]));
res = res || quat_alg_elem_is_zero(&test);
}
// test order contains 1
quat_alg_elem_set(&test,1,1,0,0,0);
res = res || !quat_lattice_contains(NULL,&rorder,&test,&alg);
// test it is right order of ideal
quat_lattice_mul(&prod,&(lideal.lattice),&rorder,&alg);
for(int i = 0; i < 4; i++){
quat_alg_elem_copy_ibz(&test,&(prod.denom),&(prod.basis[0][i]),&(prod.basis[1][i]),&(prod.basis[2][i]),&(prod.basis[3][i]));
res = res || !quat_lattice_contains(NULL,&(lideal.lattice),&test,&alg);
}
ibz_set(&(order.basis[0][0]),2);
ibz_set(&(order.basis[0][1]),0);
ibz_set(&(order.basis[0][2]),1);
ibz_set(&(order.basis[0][3]),0);
ibz_set(&(order.basis[1][0]),0);
ibz_set(&(order.basis[1][1]),2);
ibz_set(&(order.basis[1][2]),0);
ibz_set(&(order.basis[1][3]),1);
ibz_set(&(order.basis[2][0]),0);
ibz_set(&(order.basis[2][1]),0);
ibz_set(&(order.basis[2][2]),1);
ibz_set(&(order.basis[2][3]),0);
ibz_set(&(order.basis[3][0]),0);
ibz_set(&(order.basis[3][1]),0);
ibz_set(&(order.basis[3][2]),0);
ibz_set(&(order.basis[3][3]),1);
ibz_set(&(order.denom),2);
quat_alg_elem_set(&gen,1,1,2,8,8);
quat_lideal_create_principal(&lideal,&gen,&order,&alg);
quat_lideal_right_order(&rorder,&lideal,&alg);
quat_lattice_mul(&prod,&(lideal.lattice),&rorder,&alg);
// test order is in HNF
res = res || !ibz_mat_4x4_is_hnf(&(rorder.basis));
// test order is of dimension 4 (assuming HNF)
for(int i = 0; i < 4; i++){
quat_alg_elem_copy_ibz(&test,&(rorder.denom),&(rorder.basis[0][i]),&(rorder.basis[1][i]),&(rorder.basis[2][i]),&(rorder.basis[3][i]));
res = res || quat_alg_elem_is_zero(&test);
}
// test order contains 1
quat_alg_elem_set(&test,1,1,0,0,0);
res = res || !quat_lattice_contains(NULL,&rorder,&test,&alg);
// test it is right order of ideal
quat_lattice_mul(&prod,&(lideal.lattice),&rorder,&alg);
for(int i = 0; i < 4; i++){
quat_alg_elem_copy_ibz(&test,&(prod.denom),&(prod.basis[0][i]),&(prod.basis[1][i]),&(prod.basis[2][i]),&(prod.basis[3][i]));
res = res || !quat_lattice_contains(NULL,&(lideal.lattice),&test,&alg);
}
if (res != 0){
printf("Quaternion unit test lideal_right_order failed\n");
}
quat_alg_elem_finalize(&test);
quat_order_finalize(&order);
quat_order_finalize(&rorder);
quat_lattice_finalize(&prod);
quat_left_ideal_finalize(&lideal);
quat_alg_finalize(&alg);
quat_alg_elem_finalize(&gen);
return(res);
}
//void quat_lideal_reduce_basis(ibz_mat_4x4_t *reduced, ibz_mat_4x4_t *gram, const quat_left_ideal_t *lideal, const quat_alg_t *alg); //replaces lideal_lll
int quat_test_lideal_reduce_basis(){
int res = 0;
ibz_mat_4x4_t red, gram, prod;
quat_left_ideal_t lideal;
quat_lattice_t test;
quat_alg_t alg;
quat_alg_elem_t init_helper;
quat_order_t order;
ibq_t coeff;
ibz_t num,denom;
ibz_init(&num);
ibz_init(&denom);
ibq_init(&coeff);
ibz_mat_4x4_init(&prod);
quat_lattice_init(&test);
quat_alg_elem_init(&init_helper);
quat_order_init(&order);
quat_alg_init_set_ui(&alg,19);
ibz_mat_4x4_init(&gram);
ibz_mat_4x4_init(&red);
quat_left_ideal_init(&lideal);
ibz_mat_4x4_identity(&(order.basis));
ibz_set(&(order.denom),2);
quat_alg_elem_set(&init_helper,1,1,2,8,8);
quat_lideal_create_principal(&lideal,&init_helper,&order,&alg);
quat_lattice_reduce_denom(&(lideal.lattice),&(lideal.lattice));
quat_lideal_reduce_basis(&red,&gram,&lideal,&alg);
// test if red is lll-reduced, assuming he used coeff was at least 3/4
ibz_set(&num,99);
ibz_set(&denom,100);
ibq_set(&coeff,&num,&denom);
res = res || !quat_dim4_lll_verify(&red,&coeff,&(alg.p));
// test reduced and lideal generate same lattice
ibz_mat_4x4_copy(&(test.basis),&red);
ibz_copy(&(test.denom),&(lideal.lattice.denom));
quat_lattice_hnf(&test);
res = res || !quat_lattice_equal(&(lideal.lattice),&test);
// test gram matrix is gram matrix
ibz_mat_4x4_transpose(&prod,&red);
ibz_mat_4x4_mul(&prod,&prod,&(alg.gram));
ibz_mat_4x4_mul(&prod,&prod,&red);
res = res || !ibz_mat_4x4_equal(&prod,&gram);
if (res != 0){
printf("Quaternion unit test lideal_reduce_basis failed\n");
}
ibz_finalize(&num);
ibz_finalize(&denom);
ibq_finalize(&coeff);
quat_lattice_finalize(&test);
quat_alg_elem_finalize(&init_helper);
ibz_mat_4x4_finalize(&prod);
quat_order_finalize(&order);
quat_alg_finalize(&alg);
ibz_mat_4x4_finalize(&gram);
ibz_mat_4x4_finalize(&red);
quat_left_ideal_finalize(&lideal);
return(res);
}
/***************************** Functions from quaternion_tools.c ***************************************/
//void quat_connecting_ideal(quat_left_ideal_t *connecting_ideal, const quat_order_t *O1, const quat_order_t *O2, const quat_alg_t *alg);
int quat_test_lideal_connecting_ideal(){
int res = 0;
ibz_t norm;
quat_alg_t alg;
quat_alg_elem_t gen;
quat_order_t o1, o2;
quat_lattice_t prod;
quat_alg_elem_t test;
quat_left_ideal_t lideal, cmp;
quat_order_init(&o1);
quat_order_init(&o2);
quat_lattice_init(&prod);
quat_alg_init_set_ui(&alg,19);
quat_left_ideal_init(&lideal);
quat_alg_elem_init(&test);
ibz_set(&(o1.basis[0][0]),4);
ibz_set(&(o1.basis[0][1]),0);
ibz_set(&(o1.basis[0][2]),2);
ibz_set(&(o1.basis[0][3]),2);
ibz_set(&(o1.basis[1][0]),0);
ibz_set(&(o1.basis[1][1]),8);
ibz_set(&(o1.basis[1][2]),4);
ibz_set(&(o1.basis[1][3]),3);
ibz_set(&(o1.basis[2][0]),0);
ibz_set(&(o1.basis[2][1]),0);
ibz_set(&(o1.basis[2][2]),2);
ibz_set(&(o1.basis[2][3]),0);
ibz_set(&(o1.basis[3][0]),0);
ibz_set(&(o1.basis[3][1]),0);
ibz_set(&(o1.basis[3][2]),0);
ibz_set(&(o1.basis[3][3]),1);
ibz_set(&(o1.denom),4);
ibz_set(&(o2.basis[0][0]),2);
ibz_set(&(o2.basis[0][1]),0);
ibz_set(&(o2.basis[0][2]),1);
ibz_set(&(o2.basis[0][3]),0);
ibz_set(&(o2.basis[1][0]),0);
ibz_set(&(o2.basis[1][1]),2);
ibz_set(&(o2.basis[1][2]),0);
ibz_set(&(o2.basis[1][3]),1);
ibz_set(&(o2.basis[2][0]),0);
ibz_set(&(o2.basis[2][1]),0);
ibz_set(&(o2.basis[2][2]),1);
ibz_set(&(o2.basis[2][3]),0);
ibz_set(&(o2.basis[3][0]),0);
ibz_set(&(o2.basis[3][1]),0);
ibz_set(&(o2.basis[3][2]),0);
ibz_set(&(o2.basis[3][3]),1);
ibz_set(&(o2.denom),2);
quat_connecting_ideal(&lideal,&o1,&o2,&alg);
quat_lattice_mul(&prod,&o1,&(lideal.lattice),&alg);
for(int i = 0; i < 4; i++){
quat_alg_elem_copy_ibz(&test,&(prod.denom),&(prod.basis[0][i]),&(prod.basis[1][i]),&(prod.basis[2][i]),&(prod.basis[3][i]));
res = res || !quat_lattice_contains(NULL,&(lideal.lattice),&test,&alg);
}
quat_lattice_mul(&prod,&(lideal.lattice),&o2,&alg);
for(int i = 0; i < 4; i++){
quat_alg_elem_copy_ibz(&test,&(prod.denom),&(prod.basis[0][i]),&(prod.basis[1][i]),&(prod.basis[2][i]),&(prod.basis[3][i]));
res = res || !quat_lattice_contains(NULL,&(lideal.lattice),&test,&alg);
}
quat_connecting_ideal(&lideal,&o2,&o2,&alg);
quat_lattice_mul(&prod,&o2,&(lideal.lattice),&alg);
for(int i = 0; i < 4; i++){
quat_alg_elem_copy_ibz(&test,&(prod.denom),&(prod.basis[0][i]),&(prod.basis[1][i]),&(prod.basis[2][i]),&(prod.basis[3][i]));
res = res || !quat_lattice_contains(NULL,&(lideal.lattice),&test,&alg);
}
quat_lattice_mul(&prod,&(lideal.lattice),&o2,&alg);
for(int i = 0; i < 4; i++){
quat_alg_elem_copy_ibz(&test,&(prod.denom),&(prod.basis[0][i]),&(prod.basis[1][i]),&(prod.basis[2][i]),&(prod.basis[3][i]));
res = res || !quat_lattice_contains(NULL,&(lideal.lattice),&test,&alg);
}
if (res != 0){
printf("Quaternion unit test lideal_connecting_ideal failed\n");
}
quat_alg_elem_finalize(&test);
quat_order_finalize(&o1);
quat_order_finalize(&o2);
quat_lattice_finalize(&prod);
quat_left_ideal_finalize(&lideal);
quat_alg_finalize(&alg);
return(res);
}
// run all previous tests
int quat_test_lideal(){
int res = 0;
printf("\nRunning quaternion tests of ideal and order functions\n");
res = res | quat_test_lideal_create_principal();
res = res | quat_test_lideal_create_from_primitive();
res = res | quat_test_lideal_make_primitive_then_create();
res = res | quat_test_lideal_random_2e();
res = res | quat_test_lideal_generator();
res = res | quat_test_lideal_generator_coprime();
res = res | quat_test_lideal_mul();
res = res | quat_test_lideal_add_intersect_equals();
res = res | quat_test_lideal_isom();
res = res | quat_test_lideal_right_order();
res = res | quat_test_lideal_reduce_basis();
res = res | quat_test_lideal_connecting_ideal();
return(res);
}