📄 t-jac.c
字号:
default: /* 0, 2, 4, 6 */ answer_two = 0; break; } for (i = 0; i < 3 * BITS_PER_MP_LIMB; i++) { answer *= answer_two; mpz_mul_2exp (b, b, 1); try_pn (a, b, answer); } mpz_clear (b);}/* Try (a*2^k/b) for various k. If it happens mpz_ui_kronecker() gets (2/b) wrong it will show up as wrong answers demanded. */voidtry_2num (mpz_srcptr a_orig, mpz_srcptr b, int answer){ mpz_t a; int i; int answer_twos; /* don't bother when a==0 */ if (mpz_sgn (a_orig) == 0) return; mpz_init_set (a, a_orig); answer_twos = mpz_ui_kronecker (2, b); for (i = 0; i < 3 * BITS_PER_MP_LIMB; i++) { answer *= answer_twos; mpz_mul_2exp (a, a, 1); try_pn (a, b, answer); } mpz_clear (a);}/* The try_2num() and try_2den() routines don't in turn call try_periodic_num() and try_periodic_den() because it hugely increases the number of tests performed, without obviously increasing coverage. Useful extra derived cases can be added here. */voidtry_all (mpz_t a, mpz_t b, int answer){ try_pn (a, b, answer); try_periodic_num (a, b, answer); try_periodic_den (a, b, answer); try_2num (a, b, answer); try_2den (a, b, answer);}voidcheck_data (void){ static const struct { const char *a; const char *b; int answer; } data[] = { /* Note that the various derived checks in try_all() reduce the cases that need to be given here. */ /* some zeros */ { "0", "0", 0 }, { "0", "2", 0 }, { "0", "6", 0 }, { "5", "0", 0 }, { "24", "60", 0 }, /* (a/1) = 1, any a In particular note (0/1)=1 so that (a/b)=(a mod b/b). */ { "0", "1", 1 }, { "1", "1", 1 }, { "2", "1", 1 }, { "3", "1", 1 }, { "4", "1", 1 }, { "5", "1", 1 }, /* (0/b) = 0, b != 1 */ { "0", "3", 0 }, { "0", "5", 0 }, { "0", "7", 0 }, { "0", "9", 0 }, { "0", "11", 0 }, { "0", "13", 0 }, { "0", "15", 0 }, /* (1/b) = 1 */ { "1", "1", 1 }, { "1", "3", 1 }, { "1", "5", 1 }, { "1", "7", 1 }, { "1", "9", 1 }, { "1", "11", 1 }, /* (-1/b) = (-1)^((b-1)/2) which is -1 for b==3 mod 4 */ { "-1", "1", 1 }, { "-1", "3", -1 }, { "-1", "5", 1 }, { "-1", "7", -1 }, { "-1", "9", 1 }, { "-1", "11", -1 }, { "-1", "13", 1 }, { "-1", "15", -1 }, { "-1", "17", 1 }, { "-1", "19", -1 }, /* (2/b) = (-1)^((b^2-1)/8) which is -1 for b==3,5 mod 8. try_2num() will exercise multiple powers of 2 in the numerator. */ { "2", "1", 1 }, { "2", "3", -1 }, { "2", "5", -1 }, { "2", "7", 1 }, { "2", "9", 1 }, { "2", "11", -1 }, { "2", "13", -1 }, { "2", "15", 1 }, { "2", "17", 1 }, /* (-2/b) = (-1)^((b^2-1)/8)*(-1)^((b-1)/2) which is -1 for b==5,7mod8. try_2num() will exercise multiple powers of 2 in the numerator, which will test that the shift in mpz_si_kronecker() uses unsigned not signed. */ { "-2", "1", 1 }, { "-2", "3", 1 }, { "-2", "5", -1 }, { "-2", "7", -1 }, { "-2", "9", 1 }, { "-2", "11", 1 }, { "-2", "13", -1 }, { "-2", "15", -1 }, { "-2", "17", 1 }, /* (a/2)=(2/a). try_2den() will exercise multiple powers of 2 in the denominator. */ { "3", "2", -1 }, { "5", "2", -1 }, { "7", "2", 1 }, { "9", "2", 1 }, { "11", "2", -1 }, /* Harriet Griffin, "Elementary Theory of Numbers", page 155, various examples. */ { "2", "135", 1 }, { "135", "19", -1 }, { "2", "19", -1 }, { "19", "135", 1 }, { "173", "135", 1 }, { "38", "135", 1 }, { "135", "173", 1 }, { "173", "5", -1 }, { "3", "5", -1 }, { "5", "173", -1 }, { "173", "3", -1 }, { "2", "3", -1 }, { "3", "173", -1 }, { "253", "21", 1 }, { "1", "21", 1 }, { "21", "253", 1 }, { "21", "11", -1 }, { "-1", "11", -1 }, /* Griffin page 147 */ { "-1", "17", 1 }, { "2", "17", 1 }, { "-2", "17", 1 }, { "-1", "89", 1 }, { "2", "89", 1 }, /* Griffin page 148 */ { "89", "11", 1 }, { "1", "11", 1 }, { "89", "3", -1 }, { "2", "3", -1 }, { "3", "89", -1 }, { "11", "89", 1 }, { "33", "89", -1 }, /* H. Davenport, "The Higher Arithmetic", page 65, the quadratic residues and non-residues mod 19. */ { "1", "19", 1 }, { "4", "19", 1 }, { "5", "19", 1 }, { "6", "19", 1 }, { "7", "19", 1 }, { "9", "19", 1 }, { "11", "19", 1 }, { "16", "19", 1 }, { "17", "19", 1 }, { "2", "19", -1 }, { "3", "19", -1 }, { "8", "19", -1 }, { "10", "19", -1 }, { "12", "19", -1 }, { "13", "19", -1 }, { "14", "19", -1 }, { "15", "19", -1 }, { "18", "19", -1 }, /* Residues and non-residues mod 13 */ { "0", "13", 0 }, { "1", "13", 1 }, { "2", "13", -1 }, { "3", "13", 1 }, { "4", "13", 1 }, { "5", "13", -1 }, { "6", "13", -1 }, { "7", "13", -1 }, { "8", "13", -1 }, { "9", "13", 1 }, { "10", "13", 1 }, { "11", "13", -1 }, { "12", "13", 1 }, /* various */ { "5", "7", -1 }, { "15", "17", 1 }, { "67", "89", 1 }, /* special values inducing a==b==1 at the end of jac_or_kron() */ { "0x10000000000000000000000000000000000000000000000001", "0x10000000000000000000000000000000000000000000000003", 1 }, }; int i, answer; mpz_t a, b; mpz_init (a); mpz_init (b); for (i = 0; i < numberof (data); i++) { mpz_set_str_or_abort (a, data[i].a, 0); mpz_set_str_or_abort (b, data[i].b, 0); answer = data[i].answer; try_all (a, b, data[i].answer); } mpz_clear (a); mpz_clear (b);}/* (a^2/b)=1 if gcd(a,b)=1, or (a^2/b)=0 if gcd(a,b)!=1. This includes when a=0 or b=0. */voidcheck_squares_zi (void){ gmp_randstate_ptr rands = RANDS; mpz_t a, b, g; int i, answer; mp_size_t size_range, an, bn; mpz_t bs; mpz_init (bs); mpz_init (a); mpz_init (b); mpz_init (g); for (i = 0; i < 200; i++) { mpz_urandomb (bs, rands, 32); size_range = mpz_get_ui (bs) % 10 + 2; mpz_urandomb (bs, rands, size_range); an = mpz_get_ui (bs); mpz_rrandomb (a, rands, an); mpz_urandomb (bs, rands, size_range); bn = mpz_get_ui (bs); mpz_rrandomb (b, rands, bn); mpz_gcd (g, a, b); if (mpz_cmp_ui (g, 1L) == 0) answer = 1; else answer = 0; mpz_mul (a, a, a); try_all (a, b, answer); } mpz_clear (bs); mpz_clear (a); mpz_clear (b); mpz_clear (g);}/* Check the handling of asize==0, make sure it isn't affected by the low limb. */voidcheck_a_zero (void){ mpz_t a, b; mpz_init_set_ui (a, 0); mpz_init (b); mpz_set_ui (b, 1L); PTR(a)[0] = 0; try_all (a, b, 1); /* (0/1)=1 */ PTR(a)[0] = 1; try_all (a, b, 1); /* (0/1)=1 */ mpz_set_si (b, -1L); PTR(a)[0] = 0; try_all (a, b, 1); /* (0/-1)=1 */ PTR(a)[0] = 1; try_all (a, b, 1); /* (0/-1)=1 */ mpz_set_ui (b, 0); PTR(a)[0] = 0; try_all (a, b, 0); /* (0/0)=0 */ PTR(a)[0] = 1; try_all (a, b, 0); /* (0/0)=0 */ mpz_set_ui (b, 2); PTR(a)[0] = 0; try_all (a, b, 0); /* (0/2)=0 */ PTR(a)[0] = 1; try_all (a, b, 0); /* (0/2)=0 */ mpz_clear (a); mpz_clear (b);}intmain (int argc, char *argv[]){ tests_start (); if (argc >= 2 && strcmp (argv[1], "-p") == 0) { option_pari = 1; printf ("\try(a,b,answer) =\n\{\n\ if (kronecker(a,b) != answer,\n\ print(\"wrong at \", a, \",\", b,\n\ \" expected \", answer,\n\ \" pari says \", kronecker(a,b)))\n\}\n"); } check_data (); check_squares_zi (); check_a_zero (); tests_end (); exit (0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -