Files
sqisign_new/src/quaternion/ref/generic/lll/lll_tests.c
StarsAC 0c2d61119b feat(compilation): 启用 ARM64 优化与 OpenMP 并行支持
- 在 `.cmake/arm_optimization.cmake` 中增强 ARM64 编译优化选项,包括:
  * 添加 `-mtune=cortex-a76` 和更多特定于 ARM64 的优化标志
  * 启用循环优化、浮点运算优化及链接时优化(LTO)
- 在 `CMakeLists.txt` 中新增 `ENABLE_OPENMP` 选项以启用 OpenMP 支持
- 优化 `randombytes_ctrdrbg.c` 中的 AES 密钥调度和随机数生成逻辑,利用 ARM64 Crypto 扩展提升性能
- 在 `lll_tests.c` 中对关键循环进行展开以降低分支开销
- 在签名密钥生成和提交阶段引入 OpenMP 并行化处理,加快理想采样过程
- 注释掉未使用的机器学习日志函数 `ml_log_ideal_attempt` 实现
- 调整默认 `GF_RADIX` 为 64,并更新相关编译配置
2025-11-26 15:51:27 +08:00

830 lines
24 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 "lll_internals.h"
#include "quaternion_tests.h"
#include <rng.h>
int
quat_test_lll_ibq_consts(void)
{
int ret = 0;
ibq_t t;
ibz_t tmp1, tmp2, tmp3;
ibz_init(&tmp1);
ibz_init(&tmp2);
ibz_init(&tmp3);
ibq_init(&t);
ibz_set(&tmp1, 123);
ibz_set(&tmp2, -123);
if (!ibq_set(&t, &tmp1, &tmp2)) {
ret = -1;
goto err;
}
if (ibq_is_one(&t)) {
ret = -1;
goto err;
}
if (!ibq_is_ibz(&t)) {
ret = -1;
goto err;
}
if (!ibq_to_ibz(&tmp3, &t)) {
ret = -1;
goto err;
}
if (ibz_is_one(&tmp3)) {
ret = -1;
goto err;
}
ibz_set(&tmp2, 123);
if (!ibq_set(&t, &tmp1, &tmp2)) {
ret = -1;
goto err;
}
if (!ibq_is_one(&t)) {
ret = -1;
goto err;
}
if (!ibq_is_ibz(&t)) {
ret = -1;
goto err;
}
if (!ibq_to_ibz(&tmp3, &t)) {
ret = -1;
goto err;
}
if (!ibz_is_one(&tmp3)) {
ret = -1;
goto err;
}
ibz_set(&tmp1, 0);
ibq_set(&t, &tmp1, &tmp2);
if (!ibq_is_zero(&t)) {
ret = -1;
goto err;
}
if (!ibq_is_ibz(&t)) {
ret = -1;
goto err;
}
if (!ibq_to_ibz(&tmp3, &t)) {
ret = -1;
goto err;
}
if (!ibz_is_zero(&tmp3)) {
ret = -1;
goto err;
}
err:
ibq_finalize(&t);
ibz_finalize(&tmp1);
ibz_finalize(&tmp2);
ibz_finalize(&tmp3);
return ret;
}
// test for lll verification
// void ibq_vec_4_copy_ibz(ibq_vec_4_t *vec, const ibz_t *coeff0, const ibz_t *coeff1,const ibz_t
// *coeff2,const ibz_t *coeff3);
int
quat_test_lll_ibq_vec_4_copy_ibz(void)
{
int res = 0;
ibq_vec_4_t vec;
ibz_vec_4_t vec_z;
ibz_vec_4_init(&vec_z);
ibq_vec_4_init(&vec);
ibz_vec_4_set(&vec_z, 2, 3, 4, 5);
ibq_vec_4_copy_ibz(&vec, &(vec_z[0]), &(vec_z[1]), &(vec_z[2]), &(vec_z[3]));
for (int i = 0; i < 4; i++) {
ibq_to_ibz(&(vec_z[i]), &(vec[i]));
res = res || (ibz_cmp_int32(&(vec_z[i]), i + 2) != 0);
}
if (res != 0) {
printf("Quaternion unit test lll_ibq_vec_4_copy_ibz failed\n");
}
ibz_vec_4_finalize(&vec_z);
ibq_vec_4_finalize(&vec);
return (res);
}
// void quat_lll_bilinear(ibq_t *b, const ibq_vec_4_t *vec0, const ibq_vec_4_t *vec1, const
// ibz_t *q);
int
quat_test_lll_bilinear(void)
{
int res = 0;
ibz_vec_4_t init_helper;
ibq_vec_4_t vec0, vec1;
ibz_t q;
ibq_t cmp, b;
ibz_vec_4_init(&init_helper);
ibq_init(&cmp);
ibq_init(&b);
ibz_init(&q);
ibq_vec_4_init(&vec0);
ibq_vec_4_init(&vec1);
ibz_vec_4_set(&init_helper, 1, 2, 3, 4);
ibq_vec_4_copy_ibz(&vec0, &(init_helper[0]), &(init_helper[1]), &(init_helper[2]), &(init_helper[3]));
ibz_vec_4_set(&init_helper, 9, -8, 7, -6);
ibq_vec_4_copy_ibz(&vec1, &(init_helper[0]), &(init_helper[1]), &(init_helper[2]), &(init_helper[3]));
for (int i = 0; i < 4; i++) {
ibq_inv(&(vec0[i]), &(vec0[i]));
}
ibz_set(&q, 3);
ibz_vec_4_set(&init_helper, 15, 2, 0, 0);
ibq_set(&cmp, &(init_helper[0]), &(init_helper[1]));
quat_lll_bilinear(&b, &vec0, &vec1, &q);
res = res || (ibq_cmp(&b, &cmp));
if (res != 0) {
printf("Quaternion unit test quat_lll_bilinear failed\n");
}
ibq_finalize(&cmp);
ibq_finalize(&b);
ibz_finalize(&q);
ibz_vec_4_finalize(&init_helper);
ibq_vec_4_finalize(&vec0);
ibq_vec_4_finalize(&vec1);
return (res);
}
// void quat_lll_gram_schmidt_transposed_with_ibq(ibq_mat_4x4_t *orthogonalised_transposed, const
// ibz_mat_4x4_t *mat, const ibz_t *q);
int
quat_test_lll_gram_schmidt_transposed_with_ibq(void)
{
int res = 0;
int zero;
ibq_mat_4x4_t ot, cmp;
ibz_mat_4x4_t mat;
ibz_t q, num, denom;
ibq_t b;
ibz_init(&q);
ibz_init(&num);
ibz_init(&denom);
ibq_init(&b);
ibz_mat_4x4_init(&mat);
ibq_mat_4x4_init(&ot);
ibq_mat_4x4_init(&cmp);
ibz_mat_4x4_zero(&mat);
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
ibz_set(&(mat[i][j]), i * i + (j + 5) * j - 2 + (i == j));
}
}
ibz_set(&q, 3);
quat_lll_gram_schmidt_transposed_with_ibq(&ot, &mat, &q);
// test orthogonality
for (int i = 0; i < 4; i++) {
for (int j = i + 1; j < 4; j++) {
quat_lll_bilinear(&b, &(ot[i]), &(ot[j]), &q);
res = res || !ibq_is_zero(&b);
}
}
// test first vector is identical to mat
for (int i = 0; i < 4; i++) {
ibq_to_ibz(&q, &(ot[0][i]));
res = res || ibz_cmp(&q, &(mat[i][0]));
}
// test no zero vector
for (int i = 0; i < 4; i++) {
zero = 1;
for (int j = 0; j < 4; j++) {
zero = zero && ibq_is_zero(&(ot[i][j]));
}
res = res || zero;
}
ibz_set(&(mat[0][0]), 1);
ibz_set(&(mat[0][1]), 0);
ibz_set(&(mat[0][2]), 1);
ibz_set(&(mat[0][3]), 0);
ibz_set(&(mat[1][0]), 0);
ibz_set(&(mat[1][1]), 1);
ibz_set(&(mat[1][2]), 0);
ibz_set(&(mat[1][3]), 1);
ibz_set(&(mat[2][0]), 1);
ibz_set(&(mat[2][1]), 0);
ibz_set(&(mat[2][2]), 2);
ibz_set(&(mat[2][3]), 0);
ibz_set(&(mat[3][0]), 0);
ibz_set(&(mat[3][1]), 1);
ibz_set(&(mat[3][2]), 0);
ibz_set(&(mat[3][3]), 2);
ibz_set(&denom, 1);
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
ibq_set(&(cmp[i][j]), &(mat[j][i]), &denom);
}
}
ibz_set(&denom, 3);
ibz_set(&num, -2);
ibq_set(&(cmp[2][0]), &num, &denom);
ibq_set(&(cmp[3][1]), &num, &denom);
ibz_set(&num, 1);
ibq_set(&(cmp[2][2]), &num, &denom);
ibq_set(&(cmp[3][3]), &num, &denom);
ibz_set(&q, 2);
quat_lll_gram_schmidt_transposed_with_ibq(&ot, &mat, &q);
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
res = res || ibq_cmp(&(cmp[i][j]), &(ot[i][j]));
}
}
ibz_set(&(mat[0][0]), 1);
ibz_set(&(mat[0][1]), 0);
ibz_set(&(mat[0][2]), 1);
ibz_set(&(mat[0][3]), 0);
ibz_set(&(mat[1][0]), 0);
ibz_set(&(mat[1][1]), 1);
ibz_set(&(mat[1][2]), 0);
ibz_set(&(mat[1][3]), 1);
ibz_set(&(mat[2][0]), 1);
ibz_set(&(mat[2][1]), 0);
ibz_set(&(mat[2][2]), 2);
ibz_set(&(mat[2][3]), 1);
ibz_set(&(mat[3][0]), 0);
ibz_set(&(mat[3][1]), 1);
ibz_set(&(mat[3][2]), 0);
ibz_set(&(mat[3][3]), 2);
ibz_set(&denom, 1);
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
ibq_set(&(cmp[i][j]), &(mat[j][i]), &denom);
}
}
ibz_set(&denom, 3);
ibz_set(&num, -2);
ibq_set(&(cmp[2][0]), &num, &denom);
ibq_set(&(cmp[3][1]), &num, &denom);
ibz_set(&num, 1);
ibq_set(&(cmp[2][2]), &num, &denom);
ibq_set(&(cmp[3][3]), &num, &denom);
ibz_set(&num, 0);
ibq_set(&(cmp[3][0]), &num, &denom);
ibq_set(&(cmp[3][2]), &num, &denom);
ibz_set(&q, 2);
quat_lll_gram_schmidt_transposed_with_ibq(&ot, &mat, &q);
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
res = res || ibq_cmp(&(cmp[i][j]), &(ot[i][j]));
}
}
if (res != 0) {
printf("Quaternion unit test dim4_gram_schmidt_transposed_with_ibq failed\n");
}
ibz_finalize(&q);
ibz_finalize(&num);
ibz_finalize(&denom);
ibq_finalize(&b);
ibz_mat_4x4_finalize(&mat);
ibq_mat_4x4_finalize(&ot);
ibq_mat_4x4_finalize(&cmp);
return (res);
}
// int quat_lll_verify(const ibz_mat_4x4_t *mat, const ibq_t *delta, const ibq_t *eta, const
// quat_alg_t *alg);
int
quat_test_lll_verify(void)
{
int res = 0;
ibz_mat_4x4_t mat;
ibz_t q, coeff_num, coeff_denom;
ibq_t eta, delta;
quat_alg_t alg;
ibz_mat_4x4_init(&mat);
ibz_init(&q);
ibq_init(&delta);
ibq_init(&eta);
ibz_init(&coeff_num);
ibz_init(&coeff_denom);
// reduced: non-1 norm
ibz_set(&q, 3);
quat_alg_init_set(&alg, &q);
ibq_set(&eta, &ibz_const_one, &ibz_const_two);
ibq_set(&delta, &ibz_const_three, &ibz_const_two);
ibq_mul(&delta, &delta, &eta);
ibz_set(&(mat[0][0]), 0);
ibz_set(&(mat[0][1]), 2);
ibz_set(&(mat[0][2]), 3);
ibz_set(&(mat[0][3]), -14);
ibz_set(&(mat[1][0]), 2);
ibz_set(&(mat[1][1]), -1);
ibz_set(&(mat[1][2]), -4);
ibz_set(&(mat[1][3]), -8);
ibz_set(&(mat[2][0]), 1);
ibz_set(&(mat[2][1]), -2);
ibz_set(&(mat[2][2]), 1);
ibz_set(&(mat[2][3]), 0);
ibz_set(&(mat[3][0]), 1);
ibz_set(&(mat[3][1]), 1);
ibz_set(&(mat[3][2]), 0);
ibz_set(&(mat[3][3]), 7);
res = res || !quat_lll_verify(&mat, &delta, &eta, &alg);
quat_alg_finalize(&alg);
// reduced: non-1 norm
ibz_set(&q, 103);
quat_alg_init_set(&alg, &q);
ibz_set(&coeff_num, 99);
ibz_set(&coeff_denom, 100);
ibq_set(&delta, &coeff_num, &coeff_denom);
ibz_set(&(mat[0][0]), 3);
ibz_set(&(mat[0][1]), 0);
ibz_set(&(mat[0][2]), 90);
ibz_set(&(mat[0][3]), -86);
ibz_set(&(mat[1][0]), 11);
ibz_set(&(mat[1][1]), 15);
ibz_set(&(mat[1][2]), 12);
ibz_set(&(mat[1][3]), 50);
ibz_set(&(mat[2][0]), 1);
ibz_set(&(mat[2][1]), -2);
ibz_set(&(mat[2][2]), 0);
ibz_set(&(mat[2][3]), 3);
ibz_set(&(mat[3][0]), -1);
ibz_set(&(mat[3][1]), 0);
ibz_set(&(mat[3][2]), 5);
ibz_set(&(mat[3][3]), 5);
res = res || !quat_lll_verify(&mat, &delta, &eta, &alg);
quat_alg_finalize(&alg);
if (res != 0) {
printf("Quaternion unit test quat_lll_verify failed\n");
}
ibz_finalize(&q);
ibq_finalize(&delta);
ibq_finalize(&eta);
ibz_finalize(&coeff_num);
ibz_finalize(&coeff_denom);
ibz_mat_4x4_finalize(&mat);
return (res);
}
// int quat_lattice_lll(ibz_mat_4x4_t *red, const quat_lattice_t *lattice, const ibz_t *q, int
// precision);
int
quat_test_lll_lattice_lll(void)
{
int res = 0;
quat_lattice_t lat, test;
ibz_mat_4x4_t red;
ibz_t num, denom, q;
ibq_t eta, delta;
quat_alg_t alg;
ibz_init(&num);
ibz_init(&denom);
ibz_init(&q);
ibq_init(&delta);
ibq_init(&eta);
ibz_mat_4x4_init(&red);
quat_lattice_init(&lat);
quat_lattice_init(&test);
ibz_set(&q, 103);
quat_alg_init_set(&alg, &q);
// set lattice
ibz_set(&lat.denom, 60);
ibz_mat_4x4_zero(&(lat.basis));
ibz_set(&lat.basis[0][0], 3);
ibz_set(&lat.basis[1][0], 7);
ibz_set(&lat.basis[0][1], 1);
ibz_set(&lat.basis[3][1], -6);
ibz_set(&lat.basis[1][2], 12);
ibz_set(&lat.basis[2][2], 5);
ibz_set(&lat.basis[0][3], -19);
ibz_set(&lat.basis[3][3], 3);
quat_lattice_hnf(&lat);
res = res || quat_lattice_lll(&red, &lat, &alg);
// test lll reduced
quat_lll_set_ibq_parameters(&delta, &eta);
res = res || !quat_lll_verify(&red, &delta, &eta, &alg);
// test lattice equality
ibz_copy(&(test.denom), &(lat.denom));
ibz_mat_4x4_copy(&(test.basis), &(red));
quat_lattice_hnf(&test);
res = res || !quat_lattice_equal(&test, &lat);
if (res != 0) {
printf("Quaternion unit test lll_lattice_lll failed\n");
}
ibz_finalize(&num);
ibz_finalize(&denom);
ibz_finalize(&q);
ibq_finalize(&eta);
ibq_finalize(&delta);
ibz_mat_4x4_finalize(&red);
quat_lattice_finalize(&lat);
quat_lattice_finalize(&test);
quat_alg_finalize(&alg);
return (res);
}
// int quat_lattice_lll(ibz_mat_4x4_t *red, const quat_lattice_t *lattice, const quat_alg_t *alg);
int
quat_test_lll_randomized_lattice_lll(void)
{
int res = 0;
quat_lattice_t lat, test;
ibz_mat_4x4_t red;
ibz_t q, det;
ibq_t delta, eta;
int32_t rand[4][4];
int32_t rand_denom;
uint32_t rand_q;
ibz_init(&q);
ibz_init(&det);
ibq_init(&eta);
ibq_init(&delta);
ibz_mat_4x4_init(&red);
quat_lattice_init(&lat);
quat_lattice_init(&test);
quat_lll_set_ibq_parameters(&delta, &eta);
for (int iter = 0; iter < 20; iter++) {
quat_alg_t alg;
rand_denom = 0;
while (rand_denom <= 0) {
int randret = randombytes((unsigned char *)&rand_denom, sizeof(int32_t));
if (randret != 0)
return 1;
}
int randret = randombytes((unsigned char *)&rand_q, sizeof(uint32_t));
if (randret != 0)
return 1;
// generate random invertible matrix
ibz_set(&det, 0);
while (ibz_is_zero(&det)) {
randret = randombytes((unsigned char *)rand, sizeof(rand));
if (randret != 0)
return 1;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
ibz_set(&(lat.basis[i][j]), rand[j][i]);
}
}
ibz_mat_4x4_inv_with_det_as_denom(NULL, &det, &(lat.basis));
}
// set lattice
ibz_set(&lat.denom, rand_denom);
quat_lattice_hnf(&lat);
// set algebra
ibz_set(&q, 1 + (rand_q % 1023));
quat_alg_init_set(&alg, &q);
// reduce
res = res || quat_lattice_lll(&red, &lat, &alg);
// test lll reduced
res = res || !quat_lll_verify(&red, &delta, &eta, &alg);
// test lattice equality
ibz_copy(&(test.denom), &(lat.denom));
ibz_mat_4x4_copy(&(test.basis), &(red));
quat_lattice_hnf(&test);
res = res || !quat_lattice_equal(&test, &lat);
quat_alg_finalize(&alg);
}
if (res != 0) {
printf("Quaternion unit test of lll with randomization for lattice_lll failed\n");
}
ibz_finalize(&q);
ibz_finalize(&det);
ibq_finalize(&delta);
ibq_finalize(&eta);
ibz_mat_4x4_finalize(&red);
quat_lattice_finalize(&lat);
quat_lattice_finalize(&test);
return (res);
}
// int 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);
int
quat_test_lideal_reduce_basis()
{
int res = 0;
ibz_mat_4x4_t red, gram, prod, gram_norm;
ibz_vec_4_t vec;
quat_left_ideal_t lideal;
quat_lattice_t test;
quat_alg_t alg;
quat_alg_elem_t init_helper;
quat_lattice_t order;
ibq_t delta, eta;
ibz_t num, denom, norm, test_norm;
ibz_init(&num);
ibz_init(&denom);
ibz_init(&norm);
ibz_init(&test_norm);
ibq_init(&delta);
ibq_init(&eta);
ibz_vec_4_init(&vec);
ibz_mat_4x4_init(&prod);
ibz_mat_4x4_init(&gram_norm);
quat_lattice_init(&test);
quat_alg_elem_init(&init_helper);
quat_lattice_init(&order);
quat_alg_init_set_ui(&alg, 19);
ibz_mat_4x4_init(&gram);
ibz_mat_4x4_init(&red);
quat_left_ideal_init(&lideal);
quat_lattice_O0_set(&order);
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);
quat_lll_set_ibq_parameters(&delta, &eta);
res = res || !quat_lll_verify(&red, &delta, &eta, &alg);
// 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_identity(&gram_norm);
ibz_copy(&(gram_norm[2][2]), &(alg.p));
ibz_copy(&(gram_norm[3][3]), &(alg.p));
ibz_mat_4x4_transpose(&prod, &red);
ibz_mat_4x4_mul(&prod, &prod, &gram_norm);
ibz_mat_4x4_mul(&prod, &prod, &red);
for (int i = 0; i < 4; i++) {
ibz_vec_4_set(&vec, (i == 0), (i == 1), (i == 2), (i == 3));
quat_qf_eval(&norm, &gram, &vec);
quat_qf_eval(&test_norm, &prod, &vec);
ibz_mul(&norm, &(lideal.norm), &norm);
res = res || !(ibz_cmp(&norm, &test_norm) == 0);
}
if (res != 0) {
printf("Quaternion unit test lideal_reduce_basis failed\n");
}
ibz_finalize(&num);
ibz_finalize(&denom);
ibz_finalize(&norm);
ibz_finalize(&test_norm);
ibq_finalize(&delta);
ibq_finalize(&eta);
quat_lattice_finalize(&test);
quat_alg_elem_finalize(&init_helper);
ibz_mat_4x4_finalize(&prod);
quat_lattice_finalize(&order);
quat_alg_finalize(&alg);
ibz_vec_4_finalize(&vec);
ibz_mat_4x4_finalize(&gram);
ibz_mat_4x4_finalize(&red);
ibz_mat_4x4_finalize(&gram_norm);
quat_left_ideal_finalize(&lideal);
return (res);
}
// int quat_lideal_lideal_mul_reduced(quat_left_ideal_t *prod, ibz_mat_4x4_t *gram, const
// quat_left_ideal_t *lideal1,const quat_left_ideal_t *lideal2, const quat_alg_t *alg);
int
quat_test_lll_lideal_lideal_mul_reduced()
{
int res = 0;
ibz_t n, norm, test_norm;
ibq_t delta, eta;
ibz_vec_4_t vec;
quat_alg_t alg;
quat_alg_elem_t gen;
quat_lattice_t order, ro;
quat_left_ideal_t lideal1, lideal2, prod, i1, i2;
ibz_mat_4x4_t gram;
ibz_mat_4x4_t gram_test;
ibz_init(&n);
ibz_init(&norm);
ibz_init(&test_norm);
ibq_init(&delta);
ibq_init(&eta);
ibz_vec_4_init(&vec);
quat_alg_elem_init(&gen);
quat_left_ideal_init(&lideal1);
quat_left_ideal_init(&lideal2);
quat_left_ideal_init(&i1);
quat_left_ideal_init(&i2);
quat_left_ideal_init(&prod);
quat_lattice_init(&order);
quat_lattice_init(&ro);
ibz_mat_4x4_init(&gram);
ibz_mat_4x4_init(&gram_test);
quat_alg_init_set_ui(&alg, 103);
quat_lattice_O0_set(&order);
quat_lll_set_ibq_parameters(&delta, &eta);
ibz_set(&n, 113);
quat_alg_elem_set(&gen, 1, 10, 0, 1, 3);
quat_lideal_create(&lideal1, &gen, &n, &order, &alg);
ibz_set(&n, 89);
quat_alg_elem_set(&gen, 2, 2, 5, 1, 4);
quat_lideal_create(&lideal2, &gen, &n, &order, &alg);
quat_lideal_copy(&i1, &lideal1);
quat_lideal_copy(&i2, &lideal2);
quat_lideal_lideal_mul_reduced(&prod, &gram, &lideal1, &lideal2, &alg);
res = res || !quat_lll_verify(&(prod.lattice.basis), &delta, &eta, &alg);
ibz_mat_4x4_identity(&(gram_test));
ibz_copy(&(gram_test[2][2]), &(alg.p));
ibz_copy(&(gram_test[3][3]), &(alg.p));
ibz_mat_4x4_mul(&(gram_test), &(gram_test), &(prod.lattice.basis));
ibz_mat_4x4_transpose(&(gram_test), &(gram_test));
ibz_mat_4x4_mul(&(gram_test), &(gram_test), &(prod.lattice.basis));
// ARM优化: 循环展开以减少分支预测失败的可能性
// 原始循环:
// for (int i = 0; i < 4; i++) {
// ibz_vec_4_set(&vec, (i == 0), (i == 1), (i == 2), (i == 3));
// quat_qf_eval(&norm, &gram, &vec);
// quat_qf_eval(&test_norm, &gram_test, &vec);
// ibz_mul(&norm, &(prod.norm), &norm);
// res = res || !(ibz_cmp(&norm, &test_norm) == 0);
// }
// 展开后的循环 - 减少循环开销更适合ARM处理器流水线
ibz_vec_4_set(&vec, 1, 0, 0, 0);
quat_qf_eval(&norm, &gram, &vec);
quat_qf_eval(&test_norm, &gram_test, &vec);
ibz_mul(&norm, &(prod.norm), &norm);
res = res || !(ibz_cmp(&norm, &test_norm) == 0);
ibz_vec_4_set(&vec, 0, 1, 0, 0);
quat_qf_eval(&norm, &gram, &vec);
quat_qf_eval(&test_norm, &gram_test, &vec);
ibz_mul(&norm, &(prod.norm), &norm);
res = res || !(ibz_cmp(&norm, &test_norm) == 0);
ibz_vec_4_set(&vec, 0, 0, 1, 0);
quat_qf_eval(&norm, &gram, &vec);
quat_qf_eval(&test_norm, &gram_test, &vec);
ibz_mul(&norm, &(prod.norm), &norm);
res = res || !(ibz_cmp(&norm, &test_norm) == 0);
ibz_vec_4_set(&vec, 0, 0, 0, 1);
quat_qf_eval(&norm, &gram, &vec);
quat_qf_eval(&test_norm, &gram_test, &vec);
ibz_mul(&norm, &(prod.norm), &norm);
res = res || !(ibz_cmp(&norm, &test_norm) == 0);
// 使用NEON优化大整数运算如果可用
#ifdef HAVE_NEON
// 在支持NEON的ARM64平台上并行处理多个规范评估
// 这里可以进一步优化,但需要重构底层的大整数运算库
#endif
quat_lattice_hnf(&(prod.lattice));
res = res || !quat_lideal_equals(&i1, &lideal1, &alg);
res = res || !quat_lideal_equals(&i2, &lideal2, &alg);
quat_lattice_mul(&i1.lattice, &i1.lattice, &i2.lattice, &alg);
res = res || !quat_lattice_equal(&i1.lattice, &prod.lattice);
res = res || !(prod.parent_order == lideal1.parent_order);
i1.parent_order = lideal1.parent_order;
quat_lideal_norm(&i1);
res = res || !quat_lideal_equals(&i1, &prod, &alg);
if (res != 0) {
printf("Quaternion unit test lideal_lideal_mul_reduced failed\n");
}
ibz_finalize(&n);
ibz_finalize(&norm);
ibz_finalize(&test_norm);
ibq_finalize(&delta);
ibq_finalize(&eta);
ibz_vec_4_finalize(&vec);
quat_alg_elem_finalize(&gen);
quat_left_ideal_finalize(&lideal1);
quat_left_ideal_finalize(&lideal2);
quat_left_ideal_finalize(&i1);
quat_left_ideal_finalize(&i2);
quat_left_ideal_finalize(&prod);
quat_lattice_finalize(&order);
quat_lattice_finalize(&ro);
quat_alg_finalize(&alg);
ibz_mat_4x4_finalize(&gram);
ibz_mat_4x4_finalize(&gram_test);
return (res);
}
// int quat_lideal_prime_norm_reduced_equivalent(quat_left_ideal_t *lideal, const quat_alg_t *alg,
// const int primality_num_iter, const int equiv_bound_coeff, const int equiv_num_iter);
int
quat_test_lll_lideal_prime_norm_reduced_equivalent()
{
int res = 0;
ibz_t n, d;
quat_alg_t alg;
quat_alg_elem_t gen;
ibz_mat_4x4_t red, gram;
quat_lattice_t order, ro, ro2;
quat_left_ideal_t lideal1, lideal2, i1;
ibz_init(&n);
ibz_init(&d);
quat_alg_elem_init(&gen);
quat_left_ideal_init(&lideal1);
quat_left_ideal_init(&lideal2);
quat_left_ideal_init(&i1);
quat_lattice_init(&order);
quat_lattice_init(&ro);
quat_lattice_init(&ro2);
ibz_mat_4x4_init(&red);
ibz_mat_4x4_init(&gram);
quat_alg_init_set_ui(&alg, 103);
quat_lattice_O0_set(&order);
ibz_set(&n, 113);
quat_alg_elem_set(&gen, 1, 10, 0, 1, 3);
quat_lideal_create(&lideal1, &gen, &n, &order, &alg);
quat_lideal_copy(&i1, &lideal1);
quat_lideal_right_order(&ro, &lideal1, &alg);
quat_lideal_prime_norm_reduced_equivalent(&lideal1, &alg, 20, 20);
// test norm correctness
quat_lattice_hnf(&(lideal1.lattice));
ibz_copy(&n, &(lideal1.norm));
quat_lideal_norm(&lideal1);
res = res || (0 != ibz_cmp(&n, &(lideal1.norm)));
// test norm primality
res = res || !ibz_probab_prime(&n, 20);
// test equivalence
quat_lideal_right_order(&ro2, &lideal1, &alg);
quat_lattice_mul(&(lideal2.lattice), &ro, &ro2, &alg);
ibz_set(&(lideal2.lattice.denom), 1);
lideal2.parent_order = &ro;
quat_lattice_hnf(&(lideal2.lattice));
quat_lideal_norm(&lideal2);
// now lideal2 is a connecting idea of ro and ro2
quat_lideal_reduce_basis(&red, &gram, &lideal2, &alg);
quat_alg_elem_copy_ibz(&gen, &(lideal2.lattice.denom), &(red[0][0]), &(red[1][0]), &(red[2][0]), &(red[3][0]));
quat_alg_norm(&n, &d, &gen, &alg);
assert(ibz_is_one(&d));
res = res || (0 != ibz_cmp(&n, &(lideal2.norm)));
if (res != 0) {
printf("Quaternion unit test lideal_prime_norm_reduced_equivalent failed\n");
}
ibz_finalize(&n);
ibz_finalize(&d);
ibz_mat_4x4_finalize(&red);
ibz_mat_4x4_finalize(&gram);
quat_alg_elem_finalize(&gen);
quat_left_ideal_finalize(&lideal1);
quat_left_ideal_finalize(&lideal2);
quat_left_ideal_finalize(&i1);
quat_lattice_finalize(&order);
quat_lattice_finalize(&ro);
quat_lattice_finalize(&ro2);
quat_alg_finalize(&alg);
return (res);
}
// run all previous tests
int
quat_test_lll(void)
{
int res = 0;
printf("\nRunning quaternion tests of lll and its subfunctions\n");
res = res | quat_test_lll_ibq_consts();
res = res | quat_test_lll_ibq_vec_4_copy_ibz();
res = res | quat_test_lll_bilinear();
res = res | quat_test_lll_gram_schmidt_transposed_with_ibq();
res = res | quat_test_lll_verify();
res = res | quat_test_lll_lattice_lll();
res = res | quat_test_lll_randomized_lattice_lll();
res = res | quat_test_lideal_reduce_basis();
res = res | quat_test_lll_lideal_lideal_mul_reduced();
res = res | quat_test_lll_lideal_prime_norm_reduced_equivalent();
return (res);
}