wiener.c (3150B)
1 #include "wiener.h" 2 3 static int 4 test_kd(fmpz_t r, const fmpz_t k, const fmpz_t d, const fmpz_t e, 5 const fmpz_t N, fmpz_t phi, fmpz_t t, fmpz_t it, fmpz_t tmp) 6 { 7 int res = 0; 8 9 if (fmpz_cmp_ui(k, 0) == 0) { 10 return 0; 11 } 12 13 fmpz_mul(phi, e, d); 14 fmpz_sub_ui(phi, phi, 1); 15 fmpz_fdiv_q(phi, phi, k); 16 17 fmpz_add_ui(t, N, 1); 18 fmpz_sub(t, t, phi); 19 fmpz_pow_ui(t, t, 2); 20 fmpz_mul_ui(tmp, N, 4); 21 fmpz_sub(t, t, tmp); 22 23 if (fmpz_cmp_ui(t, 0) >= 0) { 24 fmpz_sqrt(it, t); 25 fmpz_pow_ui(tmp, it, 2); 26 27 if (fmpz_cmp(tmp, t) == 0) { 28 fmpz_add_ui(tmp, N, 1); 29 fmpz_sub(tmp, tmp, phi); 30 fmpz_add(tmp, tmp, it); 31 fmpz_fdiv_q_ui(r, tmp, 2); 32 33 fmpz_mod(tmp, N, r); 34 35 if (fmpz_is_zero(tmp)) { 36 res = 1; 37 } 38 } 39 } 40 41 return res; 42 } 43 44 /* 45 static int 46 test_kd(fmpz_t r, const fmpz_t k, const fmpz_t d, const fmpz_t e, 47 const fmpz_t N) 48 { 49 int res = 0; 50 fmpz_t phi, t, it, tmp; 51 52 if (fmpz_cmp_ui(k, 0) == 0) { 53 return 0; 54 } 55 56 fmpz_init(phi); 57 fmpz_init(t); 58 fmpz_init(it); 59 fmpz_init(tmp); 60 61 fmpz_mul(phi, e, d); 62 fmpz_sub_ui(phi, phi, 1); 63 fmpz_fdiv_q(phi, phi, k); 64 65 fmpz_add_ui(t, N, 1); 66 fmpz_sub(t, t, phi); 67 fmpz_pow_ui(t, t, 2); 68 fmpz_mul_ui(tmp, N, 4); 69 fmpz_sub(t, t, tmp); 70 71 if (fmpz_cmp_ui(t, 0) >= 0) { 72 fmpz_sqrt(it, t); 73 fmpz_pow_ui(tmp, it, 2); 74 75 if (fmpz_cmp(tmp, t) == 0) { 76 fmpz_add_ui(tmp, N, 1); 77 fmpz_sub(tmp, tmp, phi); 78 fmpz_add(tmp, tmp, it); 79 fmpz_fdiv_q_ui(r, tmp, 2); 80 81 fmpz_mod(tmp, N, r); 82 83 if (fmpz_is_zero(tmp)) { 84 res = 1; 85 } 86 } 87 } 88 89 fmpz_clear(phi); 90 fmpz_clear(t); 91 fmpz_clear(it); 92 fmpz_clear(tmp); 93 94 return res; 95 } 96 */ 97 98 int 99 wiener_factor(ctx_t *ctx, fmpz_t res, const fmpq_t x, const fmpz_t e, 100 const fmpz_t N) 101 { 102 assert(ctx->zs_alloc >= 10); 103 assert(ctx->qs_alloc >= 4); 104 105 fmpq_t xn[2] = {{ctx->qs[0]}, {ctx->qs[1]}}; 106 fmpq_t tmp = {ctx->qs[2]}; 107 fmpq_t xp = {ctx->qs[3]}; 108 fmpz_t p[2] = {{ctx->zs[0]}, {ctx->zs[1]}}; 109 fmpz_t q[2] = {{ctx->zs[2]}, {ctx->zs[3]}}; 110 fmpz_t tmpz = {ctx->zs[4]}; 111 fmpz_t xpz = {ctx->zs[5]}; 112 int ret = 0; 113 114 fmpq_set(xn[0], x); 115 fmpq_one(xn[1]); 116 117 fmpz_set_ui(p[0], 0); 118 fmpz_set_ui(p[1], 1); 119 fmpz_set_ui(q[0], 1); 120 fmpz_set_ui(q[1], 0); 121 122 while (!fmpq_is_zero(xn[1])) { 123 fmpq_div(tmp, xn[0], xn[1]); 124 fmpz_fdiv_q(tmpz, fmpq_numref(tmp), fmpq_denref(tmp)); 125 126 fmpq_mul_fmpz(xp, xn[1], tmpz); 127 fmpq_sub(xp, xn[0], xp); 128 fmpq_set(xn[0], xn[1]); 129 fmpq_set(xn[1], xp); 130 131 fmpz_mul(xpz, tmpz, q[1]); 132 fmpz_add(xpz, xpz, q[0]); 133 fmpz_set(q[0], q[1]); 134 fmpz_set(q[1], xpz); 135 136 fmpz_mul(xpz, tmpz, p[1]); 137 fmpz_add(xpz, xpz, p[0]); 138 fmpz_set(p[0], p[1]); 139 fmpz_set(p[1], xpz); 140 141 ret = test_kd(res, p[1], q[1], e, N, &ctx->zs[6], &ctx->zs[7], 142 &ctx->zs[8], &ctx->zs[9]); 143 144 if (ret != 0) 145 break; 146 } 147 148 return ret; 149 } 150 151 int 152 wiener_factor_small_d(ctx_t* ctx, fmpz_t res, const fmpz_t e, const fmpz_t N) 153 { 154 assert(ctx->qs_alloc >= 5); 155 fmpq_t x = {ctx->qs[4]}; 156 int ret; 157 158 fmpq_set_fmpz_frac(x, e, N); 159 ret = wiener_factor(ctx, res, x, e, N); 160 161 return ret; 162 }