| 1 | #include <iostream> |
|---|
| 2 | #include <sstream> |
|---|
| 3 | using namespace std; |
|---|
| 4 | |
|---|
| 5 | #include "ntl_wrap.h" |
|---|
| 6 | #include <NTL/mat_poly_ZZ.h> |
|---|
| 7 | #include <NTL/LLL.h> |
|---|
| 8 | |
|---|
| 9 | void del_charstar(char* a) { |
|---|
| 10 | delete[] a; |
|---|
| 11 | } |
|---|
| 12 | |
|---|
| 13 | //////// ZZ ////////// |
|---|
| 14 | |
|---|
| 15 | /* Return value is only valid if the result should fit into an int. |
|---|
| 16 | AUTHOR: David Harvey (2008-06-08) */ |
|---|
| 17 | int ZZ_to_int(const ZZ* x) |
|---|
| 18 | { |
|---|
| 19 | return to_int(*x); |
|---|
| 20 | } |
|---|
| 21 | |
|---|
| 22 | /* Returns a *new* ZZ object. |
|---|
| 23 | AUTHOR: David Harvey (2008-06-08) */ |
|---|
| 24 | struct ZZ* int_to_ZZ(int value) |
|---|
| 25 | { |
|---|
| 26 | ZZ* output = new ZZ(); |
|---|
| 27 | conv(*output, value); |
|---|
| 28 | return output; |
|---|
| 29 | } |
|---|
| 30 | |
|---|
| 31 | /* Copies the ZZ into the mpz_t |
|---|
| 32 | Assumes output has been mpz_init'd. |
|---|
| 33 | AUTHOR: David Harvey |
|---|
| 34 | Joel B. Mohler moved the ZZX_getitem_as_mpz code out to this function (2007-03-13) */ |
|---|
| 35 | void ZZ_to_mpz(mpz_t* output, const struct ZZ* x) |
|---|
| 36 | { |
|---|
| 37 | unsigned char stack_bytes[4096]; |
|---|
| 38 | int use_heap; |
|---|
| 39 | unsigned long size = NumBytes(*x); |
|---|
| 40 | use_heap = (size > sizeof(stack_bytes)); |
|---|
| 41 | unsigned char* bytes = use_heap ? (unsigned char*) malloc(size) : stack_bytes; |
|---|
| 42 | BytesFromZZ(bytes, *x, size); |
|---|
| 43 | mpz_import(*output, size, -1, 1, 0, 0, bytes); |
|---|
| 44 | if (sign(*x) < 0) |
|---|
| 45 | mpz_neg(*output, *output); |
|---|
| 46 | if (use_heap) |
|---|
| 47 | free(bytes); |
|---|
| 48 | } |
|---|
| 49 | |
|---|
| 50 | // Ok, I know that this is obvious |
|---|
| 51 | // I just wanted to document the appearance of the magic number 8 in the code below |
|---|
| 52 | #define bits_in_byte 8 |
|---|
| 53 | |
|---|
| 54 | /* Copies the mpz_t into the ZZ |
|---|
| 55 | AUTHOR: Joel B. Mohler (2007-03-15) */ |
|---|
| 56 | // This should be changed to an mpz_t not an mpz_t* |
|---|
| 57 | void mpz_to_ZZ(struct ZZ* output, const mpz_t *x) |
|---|
| 58 | { |
|---|
| 59 | unsigned char stack_bytes[4096]; |
|---|
| 60 | int use_heap; |
|---|
| 61 | size_t size = (mpz_sizeinbase(*x, 2) + bits_in_byte-1) / bits_in_byte; |
|---|
| 62 | use_heap = (size > sizeof(stack_bytes)); |
|---|
| 63 | void* bytes = use_heap ? malloc(size) : stack_bytes; |
|---|
| 64 | size_t words_written; |
|---|
| 65 | mpz_export(bytes, &words_written, -1, 1, 0, 0, *x); |
|---|
| 66 | clear(*output); |
|---|
| 67 | ZZFromBytes(*output, (unsigned char *)bytes, words_written); |
|---|
| 68 | if (mpz_sgn(*x) < 0) |
|---|
| 69 | NTL::negate(*output, *output); |
|---|
| 70 | if (use_heap) |
|---|
| 71 | free(bytes); |
|---|
| 72 | } |
|---|
| 73 | |
|---|
| 74 | /* Sets given ZZ to value |
|---|
| 75 | AUTHOR: David Harvey (2008-06-08) */ |
|---|
| 76 | void ZZ_set_from_int(ZZ* x, int value) |
|---|
| 77 | { |
|---|
| 78 | conv(*x, value); |
|---|
| 79 | } |
|---|
| 80 | |
|---|
| 81 | long ZZ_remove(struct ZZ &dest, const struct ZZ &src, const struct ZZ &f) |
|---|
| 82 | { |
|---|
| 83 | // Based on the code for mpz_remove |
|---|
| 84 | ZZ fpow[40]; // inexaustible...until year 2020 or so |
|---|
| 85 | ZZ x, rem; |
|---|
| 86 | long pwr; |
|---|
| 87 | int p; |
|---|
| 88 | |
|---|
| 89 | if (compare(f, 1) <= 0 && compare(f, -1) >= 0) |
|---|
| 90 | Error("Division by zero"); |
|---|
| 91 | |
|---|
| 92 | if (compare(src, 0) == 0) |
|---|
| 93 | { |
|---|
| 94 | if (src != dest) |
|---|
| 95 | dest = src; |
|---|
| 96 | return 0; |
|---|
| 97 | } |
|---|
| 98 | |
|---|
| 99 | if (compare(f, 2) == 0) |
|---|
| 100 | { |
|---|
| 101 | dest = src; |
|---|
| 102 | return MakeOdd(dest); |
|---|
| 103 | } |
|---|
| 104 | |
|---|
| 105 | /* We could perhaps compute mpz_scan1(src,0)/mpz_scan1(f,0). It is an |
|---|
| 106 | upper bound of the result we're seeking. We could also shift down the |
|---|
| 107 | operands so that they become odd, to make intermediate values smaller. */ |
|---|
| 108 | |
|---|
| 109 | pwr = 0; |
|---|
| 110 | fpow[0] = ZZ(f); |
|---|
| 111 | dest = src; |
|---|
| 112 | rem = ZZ(); |
|---|
| 113 | x = ZZ(); |
|---|
| 114 | |
|---|
| 115 | /* Divide by f, f^2, ..., f^(2^k) until we get a remainder for f^(2^k). */ |
|---|
| 116 | for (p = 0;;p++) |
|---|
| 117 | { |
|---|
| 118 | DivRem(x, rem, dest, fpow[p]); |
|---|
| 119 | if (compare(rem, 0) != 0) |
|---|
| 120 | break; |
|---|
| 121 | fpow[p+1] = ZZ(); |
|---|
| 122 | mul(fpow[p+1], fpow[p], fpow[p]); |
|---|
| 123 | dest = x; |
|---|
| 124 | } |
|---|
| 125 | |
|---|
| 126 | pwr = (1 << p) - 1; |
|---|
| 127 | |
|---|
| 128 | /* Divide by f^(2^(k-1)), f^(2^(k-2)), ..., f for all divisors that give a |
|---|
| 129 | zero remainder. */ |
|---|
| 130 | while (--p >= 0) |
|---|
| 131 | { |
|---|
| 132 | DivRem(x, rem, dest, fpow[p]); |
|---|
| 133 | if (compare(rem, 0) == 0) |
|---|
| 134 | { |
|---|
| 135 | pwr += 1 << p; |
|---|
| 136 | dest = x; |
|---|
| 137 | } |
|---|
| 138 | } |
|---|
| 139 | return pwr; |
|---|
| 140 | } |
|---|
| 141 | |
|---|
| 142 | //////// ZZ_p ////////// |
|---|
| 143 | |
|---|
| 144 | /* Return value is only valid if the result should fit into an int. |
|---|
| 145 | AUTHOR: David Harvey (2008-06-08) */ |
|---|
| 146 | int ZZ_p_to_int(const ZZ_p& x ) |
|---|
| 147 | { |
|---|
| 148 | return ZZ_to_int(&rep(x)); |
|---|
| 149 | } |
|---|
| 150 | |
|---|
| 151 | /* Returns a *new* ZZ_p object. |
|---|
| 152 | AUTHOR: David Harvey (2008-06-08) */ |
|---|
| 153 | ZZ_p int_to_ZZ_p(int value) |
|---|
| 154 | { |
|---|
| 155 | ZZ_p r; |
|---|
| 156 | r = value; |
|---|
| 157 | return r; |
|---|
| 158 | } |
|---|
| 159 | |
|---|
| 160 | /* Sets given ZZ_p to value |
|---|
| 161 | AUTHOR: David Harvey (2008-06-08) */ |
|---|
| 162 | void ZZ_p_set_from_int(ZZ_p* x, int value) |
|---|
| 163 | { |
|---|
| 164 | conv(*x, value); |
|---|
| 165 | } |
|---|
| 166 | |
|---|
| 167 | void ZZ_p_modulus(struct ZZ* mod, const struct ZZ_p* x) |
|---|
| 168 | { |
|---|
| 169 | (*mod) = x->modulus(); |
|---|
| 170 | } |
|---|
| 171 | |
|---|
| 172 | struct ZZ_p* ZZ_p_pow(const struct ZZ_p* x, long e) |
|---|
| 173 | { |
|---|
| 174 | ZZ_p *z = new ZZ_p(); |
|---|
| 175 | power(*z, *x, e); |
|---|
| 176 | return z; |
|---|
| 177 | } |
|---|
| 178 | |
|---|
| 179 | void ntl_ZZ_set_modulus(ZZ* x) |
|---|
| 180 | { |
|---|
| 181 | ZZ_p::init(*x); |
|---|
| 182 | } |
|---|
| 183 | |
|---|
| 184 | ZZ_p* ZZ_p_inv(ZZ_p* x) |
|---|
| 185 | { |
|---|
| 186 | ZZ_p *z = new ZZ_p(); |
|---|
| 187 | inv(*z, *x); |
|---|
| 188 | return z; |
|---|
| 189 | } |
|---|
| 190 | |
|---|
| 191 | ZZ_p* ZZ_p_random(void) |
|---|
| 192 | { |
|---|
| 193 | ZZ_p *z = new ZZ_p(); |
|---|
| 194 | random(*z); |
|---|
| 195 | return z; |
|---|
| 196 | } |
|---|
| 197 | |
|---|
| 198 | struct ZZ_p* ZZ_p_neg(struct ZZ_p* x) |
|---|
| 199 | { |
|---|
| 200 | return new ZZ_p(-(*x)); |
|---|
| 201 | } |
|---|
| 202 | |
|---|
| 203 | |
|---|
| 204 | |
|---|
| 205 | /////////////////////////////////////////////// |
|---|
| 206 | //////// ZZX ////////// |
|---|
| 207 | /////////////////////////////////////////////// |
|---|
| 208 | |
|---|
| 209 | char* ZZX_repr(struct ZZX* x) |
|---|
| 210 | { |
|---|
| 211 | ostringstream instore; |
|---|
| 212 | instore << (*x); |
|---|
| 213 | int n = strlen(instore.str().data()); |
|---|
| 214 | char* buf = new char[n+1]; |
|---|
| 215 | strcpy(buf, instore.str().data()); |
|---|
| 216 | return buf; |
|---|
| 217 | } |
|---|
| 218 | |
|---|
| 219 | struct ZZX* ZZX_copy(struct ZZX* x) { |
|---|
| 220 | return new ZZX(*x); |
|---|
| 221 | } |
|---|
| 222 | |
|---|
| 223 | /* Sets ith coefficient of x to value. |
|---|
| 224 | AUTHOR: David Harvey (2006-06-08) */ |
|---|
| 225 | void ZZX_setitem_from_int(struct ZZX* x, long i, int value) |
|---|
| 226 | { |
|---|
| 227 | SetCoeff(*x, i, value); |
|---|
| 228 | } |
|---|
| 229 | |
|---|
| 230 | /* Returns ith coefficient of x. |
|---|
| 231 | Return value is only valid if the result should fit into an int. |
|---|
| 232 | AUTHOR: David Harvey (2006-06-08) */ |
|---|
| 233 | int ZZX_getitem_as_int(struct ZZX* x, long i) |
|---|
| 234 | { |
|---|
| 235 | return ZZ_to_int(&coeff(*x, i)); |
|---|
| 236 | } |
|---|
| 237 | |
|---|
| 238 | /* Copies ith coefficient of x to output. |
|---|
| 239 | Assumes output has been mpz_init'd. |
|---|
| 240 | AUTHOR: David Harvey (2007-02) */ |
|---|
| 241 | void ZZX_getitem_as_mpz(mpz_t* output, struct ZZX* x, long i) |
|---|
| 242 | { |
|---|
| 243 | const ZZ& z = coeff(*x, i); |
|---|
| 244 | ZZ_to_mpz(output, &z); |
|---|
| 245 | } |
|---|
| 246 | |
|---|
| 247 | struct ZZX* ZZX_div(struct ZZX* x, struct ZZX* y, int* divisible) |
|---|
| 248 | { |
|---|
| 249 | struct ZZX* z = new ZZX(); |
|---|
| 250 | *divisible = divide(*z, *x, *y); |
|---|
| 251 | return z; |
|---|
| 252 | } |
|---|
| 253 | |
|---|
| 254 | |
|---|
| 255 | |
|---|
| 256 | void ZZX_quo_rem(struct ZZX* x, struct ZZX* other, struct ZZX** r, struct ZZX** q) |
|---|
| 257 | { |
|---|
| 258 | struct ZZX *qq = new ZZX(), *rr = new ZZX(); |
|---|
| 259 | DivRem(*qq, *rr, *x, *other); |
|---|
| 260 | *r = rr; *q = qq; |
|---|
| 261 | } |
|---|
| 262 | |
|---|
| 263 | |
|---|
| 264 | struct ZZX* ZZX_square(struct ZZX* x) |
|---|
| 265 | { |
|---|
| 266 | struct ZZX* s = new ZZX(); |
|---|
| 267 | sqr(*s, *x); |
|---|
| 268 | return s; |
|---|
| 269 | } |
|---|
| 270 | |
|---|
| 271 | |
|---|
| 272 | int ZZX_is_monic(struct ZZX* x) |
|---|
| 273 | { |
|---|
| 274 | IsOne(LeadCoeff(*x)); |
|---|
| 275 | } |
|---|
| 276 | |
|---|
| 277 | |
|---|
| 278 | struct ZZX* ZZX_neg(struct ZZX* x) |
|---|
| 279 | { |
|---|
| 280 | struct ZZX* y = new ZZX(); |
|---|
| 281 | *y = -*x; |
|---|
| 282 | return y; |
|---|
| 283 | } |
|---|
| 284 | |
|---|
| 285 | |
|---|
| 286 | struct ZZX* ZZX_left_shift(struct ZZX* x, long n) |
|---|
| 287 | { |
|---|
| 288 | struct ZZX* y = new ZZX(); |
|---|
| 289 | LeftShift(*y, *x, n); |
|---|
| 290 | return y; |
|---|
| 291 | } |
|---|
| 292 | |
|---|
| 293 | |
|---|
| 294 | struct ZZX* ZZX_right_shift(struct ZZX* x, long n) |
|---|
| 295 | { |
|---|
| 296 | struct ZZX* y = new ZZX(); |
|---|
| 297 | RightShift(*y, *x, n); |
|---|
| 298 | return y; |
|---|
| 299 | } |
|---|
| 300 | |
|---|
| 301 | struct ZZX* ZZX_primitive_part(struct ZZX* x) |
|---|
| 302 | { |
|---|
| 303 | struct ZZX* p = new ZZX(); |
|---|
| 304 | PrimitivePart(*p, *x); |
|---|
| 305 | return p; |
|---|
| 306 | } |
|---|
| 307 | |
|---|
| 308 | |
|---|
| 309 | void ZZX_pseudo_quo_rem(struct ZZX* x, struct ZZX* y, struct ZZX** r, struct ZZX** q) |
|---|
| 310 | { |
|---|
| 311 | *r = new ZZX(); |
|---|
| 312 | *q = new ZZX(); |
|---|
| 313 | PseudoDivRem(**q, **r, *x, *y); |
|---|
| 314 | } |
|---|
| 315 | |
|---|
| 316 | |
|---|
| 317 | struct ZZX* ZZX_gcd(struct ZZX* x, struct ZZX* y) |
|---|
| 318 | { |
|---|
| 319 | struct ZZX* g = new ZZX(); |
|---|
| 320 | GCD(*g, *x, *y); |
|---|
| 321 | return g; |
|---|
| 322 | } |
|---|
| 323 | |
|---|
| 324 | |
|---|
| 325 | void ZZX_xgcd(struct ZZX* x, struct ZZX* y, struct ZZ** r, struct ZZX** s, \ |
|---|
| 326 | struct ZZX** t, int proof) |
|---|
| 327 | { |
|---|
| 328 | *r = new ZZ(); |
|---|
| 329 | *s = new ZZX(); |
|---|
| 330 | *t = new ZZX(); |
|---|
| 331 | XGCD(**r, **s, **t, *x, *y, proof); |
|---|
| 332 | } |
|---|
| 333 | |
|---|
| 334 | |
|---|
| 335 | long ZZX_degree(struct ZZX* x) |
|---|
| 336 | { |
|---|
| 337 | return deg(*x); |
|---|
| 338 | } |
|---|
| 339 | |
|---|
| 340 | void ZZX_set_x(struct ZZX* x) |
|---|
| 341 | { |
|---|
| 342 | SetX(*x); |
|---|
| 343 | } |
|---|
| 344 | |
|---|
| 345 | |
|---|
| 346 | int ZZX_is_x(struct ZZX* x) |
|---|
| 347 | { |
|---|
| 348 | return IsX(*x); |
|---|
| 349 | } |
|---|
| 350 | |
|---|
| 351 | |
|---|
| 352 | struct ZZX* ZZX_derivative(struct ZZX* x) |
|---|
| 353 | { |
|---|
| 354 | ZZX* d = new ZZX(); |
|---|
| 355 | diff(*d, *x); |
|---|
| 356 | return d; |
|---|
| 357 | } |
|---|
| 358 | |
|---|
| 359 | |
|---|
| 360 | struct ZZX* ZZX_reverse(struct ZZX* x) |
|---|
| 361 | { |
|---|
| 362 | ZZX* r = new ZZX(); |
|---|
| 363 | reverse(*r, *x); |
|---|
| 364 | return r; |
|---|
| 365 | } |
|---|
| 366 | |
|---|
| 367 | struct ZZX* ZZX_reverse_hi(struct ZZX* x, int hi) |
|---|
| 368 | { |
|---|
| 369 | ZZX* r = new ZZX(); |
|---|
| 370 | reverse(*r, *x, hi); |
|---|
| 371 | return r; |
|---|
| 372 | } |
|---|
| 373 | |
|---|
| 374 | |
|---|
| 375 | struct ZZX* ZZX_truncate(struct ZZX* x, long m) |
|---|
| 376 | { |
|---|
| 377 | ZZX* t = new ZZX(); |
|---|
| 378 | trunc(*t, *x, m); |
|---|
| 379 | return t; |
|---|
| 380 | } |
|---|
| 381 | |
|---|
| 382 | |
|---|
| 383 | struct ZZX* ZZX_multiply_and_truncate(struct ZZX* x, struct ZZX* y, long m) |
|---|
| 384 | { |
|---|
| 385 | ZZX* t = new ZZX(); |
|---|
| 386 | MulTrunc(*t, *x, *y, m); |
|---|
| 387 | return t; |
|---|
| 388 | } |
|---|
| 389 | |
|---|
| 390 | |
|---|
| 391 | struct ZZX* ZZX_square_and_truncate(struct ZZX* x, long m) |
|---|
| 392 | { |
|---|
| 393 | ZZX* t = new ZZX(); |
|---|
| 394 | SqrTrunc(*t, *x, m); |
|---|
| 395 | return t; |
|---|
| 396 | } |
|---|
| 397 | |
|---|
| 398 | |
|---|
| 399 | struct ZZX* ZZX_invert_and_truncate(struct ZZX* x, long m) |
|---|
| 400 | { |
|---|
| 401 | ZZX* t = new ZZX(); |
|---|
| 402 | InvTrunc(*t, *x, m); |
|---|
| 403 | return t; |
|---|
| 404 | } |
|---|
| 405 | |
|---|
| 406 | |
|---|
| 407 | struct ZZX* ZZX_multiply_mod(struct ZZX* x, struct ZZX* y, struct ZZX* modulus) |
|---|
| 408 | { |
|---|
| 409 | ZZX* p = new ZZX(); |
|---|
| 410 | MulMod(*p, *x, *y, *modulus); |
|---|
| 411 | return p; |
|---|
| 412 | } |
|---|
| 413 | |
|---|
| 414 | |
|---|
| 415 | struct ZZ* ZZX_trace_mod(struct ZZX* x, struct ZZX* y) |
|---|
| 416 | { |
|---|
| 417 | ZZ* p = new ZZ(); |
|---|
| 418 | TraceMod(*p, *x, *y); |
|---|
| 419 | return p; |
|---|
| 420 | } |
|---|
| 421 | |
|---|
| 422 | |
|---|
| 423 | char* ZZX_trace_list(struct ZZX* x) |
|---|
| 424 | { |
|---|
| 425 | vec_ZZ v; |
|---|
| 426 | TraceVec(v, *x); |
|---|
| 427 | ostringstream instore; |
|---|
| 428 | instore << v; |
|---|
| 429 | int n = strlen(instore.str().data()); |
|---|
| 430 | char* buf = new char[n+1]; |
|---|
| 431 | strcpy(buf, instore.str().data()); |
|---|
| 432 | return buf; |
|---|
| 433 | } |
|---|
| 434 | |
|---|
| 435 | |
|---|
| 436 | struct ZZ* ZZX_resultant(struct ZZX* x, struct ZZX* y, int proof) |
|---|
| 437 | { |
|---|
| 438 | ZZ* res = new ZZ(); |
|---|
| 439 | resultant(*res, *x, *y, proof); |
|---|
| 440 | return res; |
|---|
| 441 | } |
|---|
| 442 | |
|---|
| 443 | |
|---|
| 444 | struct ZZ* ZZX_norm_mod(struct ZZX* x, struct ZZX* y, int proof) |
|---|
| 445 | { |
|---|
| 446 | ZZ* res = new ZZ(); |
|---|
| 447 | NormMod(*res, *x, *y, proof); |
|---|
| 448 | return res; |
|---|
| 449 | } |
|---|
| 450 | |
|---|
| 451 | |
|---|
| 452 | struct ZZ* ZZX_discriminant(struct ZZX* x, int proof) |
|---|
| 453 | { |
|---|
| 454 | ZZ* d = new ZZ(); |
|---|
| 455 | discriminant(*d, *x, proof); |
|---|
| 456 | return d; |
|---|
| 457 | } |
|---|
| 458 | |
|---|
| 459 | |
|---|
| 460 | struct ZZX* ZZX_charpoly_mod(struct ZZX* x, struct ZZX* y, int proof) |
|---|
| 461 | { |
|---|
| 462 | ZZX* f = new ZZX(); |
|---|
| 463 | CharPolyMod(*f, *x, *y, proof); |
|---|
| 464 | return f; |
|---|
| 465 | } |
|---|
| 466 | |
|---|
| 467 | |
|---|
| 468 | struct ZZX* ZZX_minpoly_mod(struct ZZX* x, struct ZZX* y) |
|---|
| 469 | { |
|---|
| 470 | ZZX* f = new ZZX(); |
|---|
| 471 | MinPolyMod(*f, *x, *y); |
|---|
| 472 | return f; |
|---|
| 473 | } |
|---|
| 474 | |
|---|
| 475 | |
|---|
| 476 | void ZZX_clear(struct ZZX* x) |
|---|
| 477 | { |
|---|
| 478 | clear(*x); |
|---|
| 479 | } |
|---|
| 480 | |
|---|
| 481 | |
|---|
| 482 | void ZZX_preallocate_space(struct ZZX* x, long n) |
|---|
| 483 | { |
|---|
| 484 | x->SetMaxLength(n); |
|---|
| 485 | } |
|---|
| 486 | |
|---|
| 487 | /* |
|---|
| 488 | EXTERN struct ZZ* ZZX_polyeval(struct ZZX* f, struct ZZ* a) |
|---|
| 489 | { |
|---|
| 490 | ZZ* b = new ZZ(); |
|---|
| 491 | *b = PolyEval(*f, *a); |
|---|
| 492 | return b; |
|---|
| 493 | } |
|---|
| 494 | */ |
|---|
| 495 | |
|---|
| 496 | void ZZX_squarefree_decomposition(struct ZZX*** v, long** e, long* n, struct ZZX* x) |
|---|
| 497 | { |
|---|
| 498 | vec_pair_ZZX_long factors; |
|---|
| 499 | SquareFreeDecomp(factors, *x); |
|---|
| 500 | *n = factors.length(); |
|---|
| 501 | *v = (ZZX**) malloc(sizeof(ZZX*) * (*n)); |
|---|
| 502 | *e = (long*) malloc(sizeof(long) * (*n)); |
|---|
| 503 | for (long i = 0; i < (*n); i++) { |
|---|
| 504 | (*v)[i] = new ZZX(factors[i].a); |
|---|
| 505 | (*e)[i] = factors[i].b; |
|---|
| 506 | } |
|---|
| 507 | } |
|---|
| 508 | |
|---|
| 509 | /////////////////////////////////////////////// |
|---|
| 510 | //////// ZZ_pX ////////// |
|---|
| 511 | /////////////////////////////////////////////// |
|---|
| 512 | |
|---|
| 513 | // char* ZZ_pX_repr(struct ZZ_pX* x) |
|---|
| 514 | // { |
|---|
| 515 | // ostringstream instore; |
|---|
| 516 | // instore << (*x); |
|---|
| 517 | // int n = strlen(instore.str().data()); |
|---|
| 518 | // char* buf = new char[n+1]; |
|---|
| 519 | // strcpy(buf, instore.str().data()); |
|---|
| 520 | // return buf; |
|---|
| 521 | // } |
|---|
| 522 | |
|---|
| 523 | // void ZZ_pX_dealloc(struct ZZ_pX* x) { |
|---|
| 524 | // delete x; |
|---|
| 525 | // } |
|---|
| 526 | |
|---|
| 527 | // struct ZZ_pX* ZZ_pX_copy(struct ZZ_pX* x) { |
|---|
| 528 | // return new ZZ_pX(*x); |
|---|
| 529 | // } |
|---|
| 530 | |
|---|
| 531 | // /* Sets ith coefficient of x to value. |
|---|
| 532 | // AUTHOR: David Harvey (2008-06-08) */ |
|---|
| 533 | // void ZZ_pX_setitem_from_int(struct ZZ_pX* x, long i, int value) |
|---|
| 534 | // { |
|---|
| 535 | // SetCoeff(*x, i, value); |
|---|
| 536 | // } |
|---|
| 537 | |
|---|
| 538 | // /* Returns ith coefficient of x. |
|---|
| 539 | // Return value is only valid if the result should fit into an int. |
|---|
| 540 | // AUTHOR: David Harvey (2008-06-08) */ |
|---|
| 541 | // int ZZ_pX_getitem_as_int(struct ZZ_pX* x, long i) |
|---|
| 542 | // { |
|---|
| 543 | // return ZZ_to_int(&rep(coeff(*x, i))); |
|---|
| 544 | // } |
|---|
| 545 | |
|---|
| 546 | // struct ZZ_pX* ZZ_pX_add(struct ZZ_pX* x, struct ZZ_pX* y) |
|---|
| 547 | // { |
|---|
| 548 | // ZZ_pX *z = new ZZ_pX(); |
|---|
| 549 | // add(*z, *x, *y); |
|---|
| 550 | // return z; |
|---|
| 551 | // } |
|---|
| 552 | |
|---|
| 553 | // struct ZZ_pX* ZZ_pX_sub(struct ZZ_pX* x, struct ZZ_pX* y) |
|---|
| 554 | // { |
|---|
| 555 | // ZZ_pX *z = new ZZ_pX(); |
|---|
| 556 | // sub(*z, *x, *y); |
|---|
| 557 | // return z; |
|---|
| 558 | // } |
|---|
| 559 | |
|---|
| 560 | // struct ZZ_pX* ZZ_pX_mul(struct ZZ_pX* x, struct ZZ_pX* y) |
|---|
| 561 | // { |
|---|
| 562 | // ZZ_pX *z = new ZZ_pX(); |
|---|
| 563 | // mul(*z, *x, *y); |
|---|
| 564 | // return z; |
|---|
| 565 | // } |
|---|
| 566 | |
|---|
| 567 | |
|---|
| 568 | // struct ZZ_pX* ZZ_pX_div(struct ZZ_pX* x, struct ZZ_pX* y, int* divisible) |
|---|
| 569 | // { |
|---|
| 570 | // struct ZZ_pX* z = new ZZ_pX(); |
|---|
| 571 | // *divisible = divide(*z, *x, *y); |
|---|
| 572 | // return z; |
|---|
| 573 | // } |
|---|
| 574 | |
|---|
| 575 | |
|---|
| 576 | // struct ZZ_pX* ZZ_pX_mod(struct ZZ_pX* x, struct ZZ_pX* y) |
|---|
| 577 | // { |
|---|
| 578 | // struct ZZ_pX* z = new ZZ_pX(); |
|---|
| 579 | // rem(*z, *x, *y); |
|---|
| 580 | // return z; |
|---|
| 581 | // } |
|---|
| 582 | |
|---|
| 583 | |
|---|
| 584 | |
|---|
| 585 | // void ZZ_pX_quo_rem(struct ZZ_pX* x, struct ZZ_pX* y, struct ZZ_pX** r, struct ZZ_pX** q) |
|---|
| 586 | // { |
|---|
| 587 | // *r = new ZZ_pX(); |
|---|
| 588 | // *q = new ZZ_pX(); |
|---|
| 589 | // DivRem(**q, **r, *x, *y); |
|---|
| 590 | // } |
|---|
| 591 | |
|---|
| 592 | |
|---|
| 593 | // struct ZZ_pX* ZZ_pX_square(struct ZZ_pX* x) |
|---|
| 594 | // { |
|---|
| 595 | // struct ZZ_pX* s = new ZZ_pX(); |
|---|
| 596 | // sqr(*s, *x); |
|---|
| 597 | // return s; |
|---|
| 598 | // } |
|---|
| 599 | |
|---|
| 600 | |
|---|
| 601 | |
|---|
| 602 | // int ZZ_pX_is_monic(struct ZZ_pX* x) |
|---|
| 603 | // { |
|---|
| 604 | // IsOne(LeadCoeff(*x)); |
|---|
| 605 | // } |
|---|
| 606 | |
|---|
| 607 | |
|---|
| 608 | // struct ZZ_pX* ZZ_pX_neg(struct ZZ_pX* x) |
|---|
| 609 | // { |
|---|
| 610 | // struct ZZ_pX* y = new ZZ_pX(); |
|---|
| 611 | // *y = -*x; |
|---|
| 612 | // return y; |
|---|
| 613 | // } |
|---|
| 614 | |
|---|
| 615 | |
|---|
| 616 | // struct ZZ_pX* ZZ_pX_left_shift(struct ZZ_pX* x, long n) |
|---|
| 617 | // { |
|---|
| 618 | // struct ZZ_pX* y = new ZZ_pX(); |
|---|
| 619 | // LeftShift(*y, *x, n); |
|---|
| 620 | // return y; |
|---|
| 621 | // } |
|---|
| 622 | |
|---|
| 623 | |
|---|
| 624 | // struct ZZ_pX* ZZ_pX_right_shift(struct ZZ_pX* x, long n) |
|---|
| 625 | // { |
|---|
| 626 | // struct ZZ_pX* y = new ZZ_pX(); |
|---|
| 627 | // RightShift(*y, *x, n); |
|---|
| 628 | // return y; |
|---|
| 629 | // } |
|---|
| 630 | |
|---|
| 631 | |
|---|
| 632 | |
|---|
| 633 | // struct ZZ_pX* ZZ_pX_gcd(struct ZZ_pX* x, struct ZZ_pX* y) |
|---|
| 634 | // { |
|---|
| 635 | // struct ZZ_pX* g = new ZZ_pX(); |
|---|
| 636 | // GCD(*g, *x, *y); |
|---|
| 637 | // return g; |
|---|
| 638 | // } |
|---|
| 639 | |
|---|
| 640 | |
|---|
| 641 | // void ZZ_pX_xgcd(struct ZZ_pX** d, struct ZZ_pX** s, struct ZZ_pX** t, struct ZZ_pX* a, struct ZZ_pX* b) |
|---|
| 642 | // { |
|---|
| 643 | // *d = new ZZ_pX(); |
|---|
| 644 | // *s = new ZZ_pX(); |
|---|
| 645 | // *t = new ZZ_pX(); |
|---|
| 646 | // XGCD(**d, **s, **t, *a, *b); |
|---|
| 647 | // } |
|---|
| 648 | |
|---|
| 649 | // void ZZ_pX_plain_xgcd(struct ZZ_pX** d, struct ZZ_pX** s, struct ZZ_pX** t, struct ZZ_pX* a, struct ZZ_pX* b) |
|---|
| 650 | // { |
|---|
| 651 | // *d = new ZZ_pX(); |
|---|
| 652 | // *s = new ZZ_pX(); |
|---|
| 653 | // *t = new ZZ_pX(); |
|---|
| 654 | // PlainXGCD(**d, **s, **t, *a, *b); |
|---|
| 655 | // } |
|---|
| 656 | |
|---|
| 657 | // ZZ_p* ZZ_pX_leading_coefficient(struct ZZ_pX* x) |
|---|
| 658 | // { |
|---|
| 659 | // return new ZZ_p(LeadCoeff(*x)); |
|---|
| 660 | // } |
|---|
| 661 | |
|---|
| 662 | |
|---|
| 663 | // void ZZ_pX_set_x(struct ZZ_pX* x) |
|---|
| 664 | // { |
|---|
| 665 | // SetX(*x); |
|---|
| 666 | // } |
|---|
| 667 | |
|---|
| 668 | |
|---|
| 669 | // int ZZ_pX_is_x(struct ZZ_pX* x) |
|---|
| 670 | // { |
|---|
| 671 | // return IsX(*x); |
|---|
| 672 | // } |
|---|
| 673 | |
|---|
| 674 | |
|---|
| 675 | // struct ZZ_pX* ZZ_pX_derivative(struct ZZ_pX* x) |
|---|
| 676 | // { |
|---|
| 677 | // ZZ_pX* d = new ZZ_pX(); |
|---|
| 678 | // diff(*d, *x); |
|---|
| 679 | // return d; |
|---|
| 680 | // } |
|---|
| 681 | |
|---|
| 682 | |
|---|
| 683 | // struct ZZ_pX* ZZ_pX_reverse(struct ZZ_pX* x) |
|---|
| 684 | // { |
|---|
| 685 | // ZZ_pX* r = new ZZ_pX(); |
|---|
| 686 | // reverse(*r, *x); |
|---|
| 687 | // return r; |
|---|
| 688 | // } |
|---|
| 689 | |
|---|
| 690 | // struct ZZ_pX* ZZ_pX_reverse_hi(struct ZZ_pX* x, int hi) |
|---|
| 691 | // { |
|---|
| 692 | // ZZ_pX* r = new ZZ_pX(); |
|---|
| 693 | // reverse(*r, *x, hi); |
|---|
| 694 | // return r; |
|---|
| 695 | // } |
|---|
| 696 | |
|---|
| 697 | |
|---|
| 698 | // struct ZZ_pX* ZZ_pX_truncate(struct ZZ_pX* x, long m) |
|---|
| 699 | // { |
|---|
| 700 | // ZZ_pX* t = new ZZ_pX(); |
|---|
| 701 | // trunc(*t, *x, m); |
|---|
| 702 | // return t; |
|---|
| 703 | // } |
|---|
| 704 | |
|---|
| 705 | |
|---|
| 706 | // struct ZZ_pX* ZZ_pX_multiply_and_truncate(struct ZZ_pX* x, struct ZZ_pX* y, long m) |
|---|
| 707 | // { |
|---|
| 708 | // ZZ_pX* t = new ZZ_pX(); |
|---|
| 709 | // MulTrunc(*t, *x, *y, m); |
|---|
| 710 | // return t; |
|---|
| 711 | // } |
|---|
| 712 | |
|---|
| 713 | |
|---|
| 714 | // struct ZZ_pX* ZZ_pX_square_and_truncate(struct ZZ_pX* x, long m) |
|---|
| 715 | // { |
|---|
| 716 | // ZZ_pX* t = new ZZ_pX(); |
|---|
| 717 | // SqrTrunc(*t, *x, m); |
|---|
| 718 | // return t; |
|---|
| 719 | // } |
|---|
| 720 | |
|---|
| 721 | |
|---|
| 722 | // struct ZZ_pX* ZZ_pX_invert_and_truncate(struct ZZ_pX* x, long m) |
|---|
| 723 | // { |
|---|
| 724 | // ZZ_pX* t = new ZZ_pX(); |
|---|
| 725 | // InvTrunc(*t, *x, m); |
|---|
| 726 | // return t; |
|---|
| 727 | // } |
|---|
| 728 | |
|---|
| 729 | |
|---|
| 730 | // struct ZZ_pX* ZZ_pX_multiply_mod(struct ZZ_pX* x, struct ZZ_pX* y, struct ZZ_pX* modulus) |
|---|
| 731 | // { |
|---|
| 732 | // ZZ_pX* p = new ZZ_pX(); |
|---|
| 733 | // MulMod(*p, *x, *y, *modulus); |
|---|
| 734 | // return p; |
|---|
| 735 | // } |
|---|
| 736 | |
|---|
| 737 | |
|---|
| 738 | // struct ZZ_p* ZZ_pX_trace_mod(struct ZZ_pX* x, struct ZZ_pX* y) |
|---|
| 739 | // { |
|---|
| 740 | // ZZ_p* p = new ZZ_p(); |
|---|
| 741 | // TraceMod(*p, *x, *y); |
|---|
| 742 | // return p; |
|---|
| 743 | // } |
|---|
| 744 | |
|---|
| 745 | |
|---|
| 746 | char* ZZ_pX_trace_list(struct ZZ_pX* x) |
|---|
| 747 | { |
|---|
| 748 | vec_ZZ_p v; |
|---|
| 749 | TraceVec(v, *x); |
|---|
| 750 | ostringstream instore; |
|---|
| 751 | instore << v; |
|---|
| 752 | int n = strlen(instore.str().data()); |
|---|
| 753 | char* buf = new char[n+1]; |
|---|
| 754 | strcpy(buf, instore.str().data()); |
|---|
| 755 | return buf; |
|---|
| 756 | } |
|---|
| 757 | |
|---|
| 758 | |
|---|
| 759 | // struct ZZ_p* ZZ_pX_resultant(struct ZZ_pX* x, struct ZZ_pX* y) |
|---|
| 760 | // { |
|---|
| 761 | // ZZ_p* res = new ZZ_p(); |
|---|
| 762 | // resultant(*res, *x, *y); |
|---|
| 763 | // return res; |
|---|
| 764 | // } |
|---|
| 765 | |
|---|
| 766 | |
|---|
| 767 | // struct ZZ_p* ZZ_pX_norm_mod(struct ZZ_pX* x, struct ZZ_pX* y) |
|---|
| 768 | // { |
|---|
| 769 | // ZZ_p* res = new ZZ_p(); |
|---|
| 770 | // NormMod(*res, *x, *y); |
|---|
| 771 | // return res; |
|---|
| 772 | // } |
|---|
| 773 | |
|---|
| 774 | |
|---|
| 775 | |
|---|
| 776 | // struct ZZ_pX* ZZ_pX_charpoly_mod(struct ZZ_pX* x, struct ZZ_pX* y) |
|---|
| 777 | // { |
|---|
| 778 | // ZZ_pX* f = new ZZ_pX(); |
|---|
| 779 | // CharPolyMod(*f, *x, *y); |
|---|
| 780 | // return f; |
|---|
| 781 | // } |
|---|
| 782 | |
|---|
| 783 | |
|---|
| 784 | // struct ZZ_pX* ZZ_pX_minpoly_mod(struct ZZ_pX* x, struct ZZ_pX* y) |
|---|
| 785 | // { |
|---|
| 786 | // ZZ_pX* f = new ZZ_pX(); |
|---|
| 787 | // MinPolyMod(*f, *x, *y); |
|---|
| 788 | // return f; |
|---|
| 789 | // } |
|---|
| 790 | |
|---|
| 791 | |
|---|
| 792 | // void ZZ_pX_clear(struct ZZ_pX* x) |
|---|
| 793 | // { |
|---|
| 794 | // clear(*x); |
|---|
| 795 | // } |
|---|
| 796 | |
|---|
| 797 | |
|---|
| 798 | // void ZZ_pX_preallocate_space(struct ZZ_pX* x, long n) |
|---|
| 799 | // { |
|---|
| 800 | // x->SetMaxLength(n); |
|---|
| 801 | // } |
|---|
| 802 | |
|---|
| 803 | void ZZ_pX_factor(struct ZZ_pX*** v, long** e, long* n, struct ZZ_pX* x, long verbose) |
|---|
| 804 | { |
|---|
| 805 | long i; |
|---|
| 806 | vec_pair_ZZ_pX_long factors; |
|---|
| 807 | berlekamp(factors, *x, verbose); |
|---|
| 808 | *n = factors.length(); |
|---|
| 809 | *v = (ZZ_pX**) malloc(sizeof(ZZ_pX*) * (*n)); |
|---|
| 810 | *e = (long*) malloc(sizeof(long)*(*n)); |
|---|
| 811 | for (i=0; i<(*n); i++) { |
|---|
| 812 | (*v)[i] = new ZZ_pX(factors[i].a); |
|---|
| 813 | (*e)[i] = factors[i].b; |
|---|
| 814 | } |
|---|
| 815 | } |
|---|
| 816 | |
|---|
| 817 | void ZZ_pX_linear_roots(struct ZZ_p*** v, long* n, struct ZZ_pX* f) |
|---|
| 818 | { |
|---|
| 819 | long i; |
|---|
| 820 | // printf("1\n"); |
|---|
| 821 | vec_ZZ_p w; |
|---|
| 822 | FindRoots(w, *f); |
|---|
| 823 | // printf("2\n"); |
|---|
| 824 | *n = w.length(); |
|---|
| 825 | // printf("3 %d\n",*n); |
|---|
| 826 | (*v) = (ZZ_p**) malloc(sizeof(ZZ_p*)*(*n)); |
|---|
| 827 | for (i=0; i<(*n); i++) { |
|---|
| 828 | (*v)[i] = new ZZ_p(w[i]); |
|---|
| 829 | } |
|---|
| 830 | } |
|---|
| 831 | |
|---|
| 832 | /////////// ZZ_pE ////////////// |
|---|
| 833 | |
|---|
| 834 | struct ZZ_pX ZZ_pE_to_ZZ_pX(struct ZZ_pE x) |
|---|
| 835 | { |
|---|
| 836 | return ZZ_pX(rep(x)); |
|---|
| 837 | } |
|---|
| 838 | |
|---|
| 839 | |
|---|
| 840 | |
|---|
| 841 | //////// mat_ZZ ////////// |
|---|
| 842 | |
|---|
| 843 | void mat_ZZ_SetDims(struct mat_ZZ* mZZ, long nrows, long ncols){ |
|---|
| 844 | mZZ->SetDims(nrows, ncols); |
|---|
| 845 | } |
|---|
| 846 | |
|---|
| 847 | struct mat_ZZ* mat_ZZ_pow(const struct mat_ZZ* x, long e) |
|---|
| 848 | { |
|---|
| 849 | mat_ZZ *z = new mat_ZZ(); |
|---|
| 850 | power(*z, *x, e); |
|---|
| 851 | return z; |
|---|
| 852 | } |
|---|
| 853 | |
|---|
| 854 | long mat_ZZ_nrows(const struct mat_ZZ* x) |
|---|
| 855 | { |
|---|
| 856 | return x->NumRows(); |
|---|
| 857 | } |
|---|
| 858 | |
|---|
| 859 | |
|---|
| 860 | long mat_ZZ_ncols(const struct mat_ZZ* x) |
|---|
| 861 | { |
|---|
| 862 | return x->NumCols(); |
|---|
| 863 | } |
|---|
| 864 | |
|---|
| 865 | void mat_ZZ_setitem(struct mat_ZZ* x, int i, int j, const struct ZZ* z) |
|---|
| 866 | { |
|---|
| 867 | (*x)[i][j] = *z; |
|---|
| 868 | |
|---|
| 869 | } |
|---|
| 870 | |
|---|
| 871 | struct ZZ* mat_ZZ_getitem(const struct mat_ZZ* x, int i, int j) |
|---|
| 872 | { |
|---|
| 873 | return new ZZ((*x)(i,j)); |
|---|
| 874 | } |
|---|
| 875 | |
|---|
| 876 | struct ZZ* mat_ZZ_determinant(const struct mat_ZZ* x, long deterministic) |
|---|
| 877 | { |
|---|
| 878 | ZZ* d = new ZZ(); |
|---|
| 879 | determinant(*d, *x, deterministic); |
|---|
| 880 | return d; |
|---|
| 881 | } |
|---|
| 882 | |
|---|
| 883 | struct mat_ZZ* mat_ZZ_HNF(const struct mat_ZZ* A, const struct ZZ* D) |
|---|
| 884 | { |
|---|
| 885 | struct mat_ZZ* W = new mat_ZZ(); |
|---|
| 886 | HNF(*W, *A, *D); |
|---|
| 887 | return W; |
|---|
| 888 | } |
|---|
| 889 | |
|---|
| 890 | long mat_ZZ_LLL(struct ZZ **det, struct mat_ZZ *x, long a, long b, long verbose) |
|---|
| 891 | { |
|---|
| 892 | *det = new ZZ(); |
|---|
| 893 | return LLL(**det,*x,a,b,verbose); |
|---|
| 894 | } |
|---|
| 895 | |
|---|
| 896 | long mat_ZZ_LLL_U(struct ZZ **det, struct mat_ZZ *x, struct mat_ZZ *U, long a, long b, long verbose) |
|---|
| 897 | { |
|---|
| 898 | *det = new ZZ(); |
|---|
| 899 | return LLL(**det,*x,*U,a,b,verbose); |
|---|
| 900 | } |
|---|
| 901 | |
|---|
| 902 | |
|---|
| 903 | struct ZZX* mat_ZZ_charpoly(const struct mat_ZZ* A) |
|---|
| 904 | { |
|---|
| 905 | ZZX* f = new ZZX(); |
|---|
| 906 | CharPoly(*f, *A); |
|---|
| 907 | return f; |
|---|
| 908 | } |
|---|
| 909 | |
|---|
| 910 | |
|---|
| 911 | |
|---|
| 912 | /** |
|---|
| 913 | * GF2X |
|---|
| 914 | * |
|---|
| 915 | * @author Martin Albrecht <malb@informatik.uni-bremen.de> |
|---|
| 916 | * |
|---|
| 917 | * @versions 2006-01 malb |
|---|
| 918 | * initial version (based on code by William Stein) |
|---|
| 919 | */ |
|---|
| 920 | |
|---|
| 921 | struct GF2X* GF2X_pow(const struct GF2X* x, long e) |
|---|
| 922 | { |
|---|
| 923 | GF2X *z = new GF2X(); |
|---|
| 924 | power(*z, *x, e); |
|---|
| 925 | return z; |
|---|
| 926 | } |
|---|
| 927 | |
|---|
| 928 | struct GF2X* GF2X_neg(struct GF2X* x) |
|---|
| 929 | { |
|---|
| 930 | return new GF2X(-(*x)); |
|---|
| 931 | } |
|---|
| 932 | |
|---|
| 933 | struct GF2X* GF2X_copy(struct GF2X* x) |
|---|
| 934 | { |
|---|
| 935 | GF2X *z = new GF2X(*x); |
|---|
| 936 | return z; |
|---|
| 937 | } |
|---|
| 938 | |
|---|
| 939 | long GF2X_deg(struct GF2X* x) |
|---|
| 940 | { |
|---|
| 941 | return deg(*x); |
|---|
| 942 | } |
|---|
| 943 | |
|---|
| 944 | void GF2X_hex(long h) |
|---|
| 945 | { |
|---|
| 946 | GF2X::HexOutput=h; |
|---|
| 947 | } |
|---|
| 948 | |
|---|
| 949 | |
|---|
| 950 | |
|---|
| 951 | PyObject* GF2X_to_bin(const struct GF2X* x) |
|---|
| 952 | { |
|---|
| 953 | long hex; |
|---|
| 954 | hex = GF2X::HexOutput; |
|---|
| 955 | GF2X::HexOutput=0; |
|---|
| 956 | std::ostringstream instore; |
|---|
| 957 | instore << (*x); |
|---|
| 958 | GF2X::HexOutput=hex; |
|---|
| 959 | return PyString_FromString(instore.str().data()); |
|---|
| 960 | } |
|---|
| 961 | |
|---|
| 962 | PyObject* GF2X_to_hex(const struct GF2X* x) |
|---|
| 963 | { |
|---|
| 964 | long hex; |
|---|
| 965 | hex = GF2X::HexOutput; |
|---|
| 966 | GF2X::HexOutput=1; |
|---|
| 967 | std::ostringstream instore; |
|---|
| 968 | instore << (*x); |
|---|
| 969 | GF2X::HexOutput=hex; |
|---|
| 970 | return PyString_FromString(instore.str().data()); |
|---|
| 971 | } |
|---|
| 972 | |
|---|
| 973 | |
|---|
| 974 | |
|---|
| 975 | /** |
|---|
| 976 | * GF2E |
|---|
| 977 | * |
|---|
| 978 | * @author Martin Albrecht <malb@informatik.uni-bremen.de> |
|---|
| 979 | * |
|---|
| 980 | * @versions 2006-01 malb |
|---|
| 981 | * initial version (based on code by William Stein) |
|---|
| 982 | */ |
|---|
| 983 | |
|---|
| 984 | |
|---|
| 985 | void ntl_GF2E_set_modulus(GF2X* x) |
|---|
| 986 | { |
|---|
| 987 | GF2E::init(*x); |
|---|
| 988 | } |
|---|
| 989 | |
|---|
| 990 | |
|---|
| 991 | struct GF2E* GF2E_pow(const struct GF2E* x, long e) |
|---|
| 992 | { |
|---|
| 993 | GF2E *z = new GF2E(); |
|---|
| 994 | power(*z, *x, e); |
|---|
| 995 | return z; |
|---|
| 996 | } |
|---|
| 997 | |
|---|
| 998 | |
|---|
| 999 | struct GF2E* GF2E_neg(struct GF2E* x) |
|---|
| 1000 | { |
|---|
| 1001 | return new GF2E(-(*x)); |
|---|
| 1002 | } |
|---|
| 1003 | |
|---|
| 1004 | struct GF2E* GF2E_copy(struct GF2E* x) |
|---|
| 1005 | { |
|---|
| 1006 | GF2E *z = new GF2E(*x); |
|---|
| 1007 | return z; |
|---|
| 1008 | } |
|---|
| 1009 | |
|---|
| 1010 | long GF2E_trace(struct GF2E* x) |
|---|
| 1011 | { |
|---|
| 1012 | return rep(trace(*x)); |
|---|
| 1013 | } |
|---|
| 1014 | |
|---|
| 1015 | |
|---|
| 1016 | long GF2E_degree() |
|---|
| 1017 | { |
|---|
| 1018 | return GF2E::degree(); |
|---|
| 1019 | } |
|---|
| 1020 | |
|---|
| 1021 | const struct GF2X* GF2E_modulus() |
|---|
| 1022 | { |
|---|
| 1023 | GF2XModulus mod = GF2E::modulus(); |
|---|
| 1024 | GF2X *z = new GF2X(mod.val()); |
|---|
| 1025 | return z; |
|---|
| 1026 | } |
|---|
| 1027 | |
|---|
| 1028 | struct GF2E *GF2E_random(void) |
|---|
| 1029 | { |
|---|
| 1030 | GF2E *z = new GF2E(); |
|---|
| 1031 | random(*z); |
|---|
| 1032 | return z; |
|---|
| 1033 | } |
|---|
| 1034 | |
|---|
| 1035 | const struct GF2X *GF2E_ntl_GF2X(struct GF2E *x) { |
|---|
| 1036 | GF2X *r = new GF2X(rep(*x)); |
|---|
| 1037 | return r; |
|---|
| 1038 | } |
|---|
| 1039 | |
|---|
| 1040 | |
|---|
| 1041 | /** |
|---|
| 1042 | * mat_GF2E |
|---|
| 1043 | * |
|---|
| 1044 | * @author Martin Albrecht <malb@informatik.uni-bremen.de> |
|---|
| 1045 | * |
|---|
| 1046 | * @versions 2006-01 malb |
|---|
| 1047 | * initial version (based on code by William Stein) |
|---|
| 1048 | */ |
|---|
| 1049 | |
|---|
| 1050 | void mat_GF2E_SetDims(struct mat_GF2E* m, long nrows, long ncols){ |
|---|
| 1051 | m->SetDims(nrows, ncols); |
|---|
| 1052 | } |
|---|
| 1053 | |
|---|
| 1054 | struct mat_GF2E* mat_GF2E_pow(const struct mat_GF2E* x, long e) |
|---|
| 1055 | { |
|---|
| 1056 | mat_GF2E *z = new mat_GF2E(); |
|---|
| 1057 | power(*z, *x, e); |
|---|
| 1058 | return z; |
|---|
| 1059 | } |
|---|
| 1060 | |
|---|
| 1061 | long mat_GF2E_nrows(const struct mat_GF2E* x) |
|---|
| 1062 | { |
|---|
| 1063 | return x->NumRows(); |
|---|
| 1064 | } |
|---|
| 1065 | |
|---|
| 1066 | |
|---|
| 1067 | long mat_GF2E_ncols(const struct mat_GF2E* x) |
|---|
| 1068 | { |
|---|
| 1069 | return x->NumCols(); |
|---|
| 1070 | } |
|---|
| 1071 | |
|---|
| 1072 | void mat_GF2E_setitem(struct mat_GF2E* x, int i, int j, const struct GF2E* z) |
|---|
| 1073 | { |
|---|
| 1074 | (*x)[i][j] = *z; |
|---|
| 1075 | } |
|---|
| 1076 | |
|---|
| 1077 | struct GF2E* mat_GF2E_getitem(const struct mat_GF2E* x, int i, int j) |
|---|
| 1078 | { |
|---|
| 1079 | return new GF2E((*x)(i,j)); |
|---|
| 1080 | } |
|---|
| 1081 | |
|---|
| 1082 | struct GF2E* mat_GF2E_determinant(const struct mat_GF2E* x) |
|---|
| 1083 | { |
|---|
| 1084 | GF2E* d = new GF2E(); |
|---|
| 1085 | determinant(*d, *x); |
|---|
| 1086 | return d; |
|---|
| 1087 | } |
|---|
| 1088 | |
|---|
| 1089 | long mat_GF2E_gauss(struct mat_GF2E *x, long w) |
|---|
| 1090 | { |
|---|
| 1091 | if(w==0) { |
|---|
| 1092 | return gauss(*x); |
|---|
| 1093 | } else { |
|---|
| 1094 | return gauss(*x, w); |
|---|
| 1095 | } |
|---|
| 1096 | } |
|---|
| 1097 | |
|---|
| 1098 | struct mat_GF2E* mat_GF2E_transpose(const struct mat_GF2E* x) { |
|---|
| 1099 | mat_GF2E *y = new mat_GF2E(); |
|---|
| 1100 | transpose(*y,*x); |
|---|
| 1101 | return y; |
|---|
| 1102 | } |
|---|
| 1103 | |
|---|
| 1104 | |
|---|
| 1105 | |
|---|
| 1106 | ZZ_pContext* ZZ_pContext_new(ZZ *p) |
|---|
| 1107 | { |
|---|
| 1108 | return new ZZ_pContext(*p); |
|---|
| 1109 | } |
|---|
| 1110 | |
|---|
| 1111 | ZZ_pContext* ZZ_pContext_construct(void *mem, ZZ *p) |
|---|
| 1112 | { |
|---|
| 1113 | return new(mem) ZZ_pContext(*p); |
|---|
| 1114 | } |
|---|
| 1115 | |
|---|
| 1116 | void ZZ_pContext_restore(ZZ_pContext *ctx) |
|---|
| 1117 | { |
|---|
| 1118 | ctx->restore(); |
|---|
| 1119 | } |
|---|
| 1120 | |
|---|
| 1121 | // Functions for using ZZ_pX's for p-adic extensions |
|---|
| 1122 | |
|---|
| 1123 | void ZZ_pX_conv_modulus(ZZ_pX &fout, const ZZ_pX &fin, const ZZ_pContext &modout) |
|---|
| 1124 | { |
|---|
| 1125 | // Changes the modulus of fin to modout, and puts the result in fout. |
|---|
| 1126 | long i, n; |
|---|
| 1127 | |
|---|
| 1128 | n = fin.rep.length(); |
|---|
| 1129 | fout.rep.SetLength(n); |
|---|
| 1130 | |
|---|
| 1131 | ZZ_p* xp = fout.rep.elts(); |
|---|
| 1132 | const ZZ_p* ap = fin.rep.elts(); |
|---|
| 1133 | |
|---|
| 1134 | // I think it's enough to just restore modout once. |
|---|
| 1135 | // This should be true as long as the function rep taking a ZZ_p as an argument |
|---|
| 1136 | // and returning a ZZ works when the ZZ_p::modulus is incorrect. |
|---|
| 1137 | modout.restore(); |
|---|
| 1138 | |
|---|
| 1139 | for (i = 0; i < n; i++) |
|---|
| 1140 | { |
|---|
| 1141 | conv(xp[i], rep(ap[i])); |
|---|
| 1142 | } |
|---|
| 1143 | |
|---|
| 1144 | // We may have set a leading coefficient to 0, so we have to normalize |
|---|
| 1145 | fout.normalize(); |
|---|
| 1146 | } |
|---|
| 1147 | |
|---|
| 1148 | void ZZ_pEX_conv_modulus(ZZ_pEX &fout, const ZZ_pEX &fin, const ZZ_pContext &modout) |
|---|
| 1149 | { |
|---|
| 1150 | // Changes the modulus of fin to modout, and puts the result in fout. |
|---|
| 1151 | long i, n, j, m; |
|---|
| 1152 | |
|---|
| 1153 | n = fin.rep.length(); |
|---|
| 1154 | fout.rep.SetLength(n); |
|---|
| 1155 | |
|---|
| 1156 | ZZ_pE* outpe = fout.rep.elts(); |
|---|
| 1157 | const ZZ_pE* inpe = fin.rep.elts(); |
|---|
| 1158 | |
|---|
| 1159 | ZZ_p* xp; |
|---|
| 1160 | const ZZ_p* ap; |
|---|
| 1161 | // I think it's enough to just restore modout once |
|---|
| 1162 | // This should be true as long as Loophole() offers access to |
|---|
| 1163 | // the underlying ZZ_pX representations of ZZ_pEs, |
|---|
| 1164 | // and rep of a ZZ_p (giving a ZZ) works even if the ZZ_p::modulus is |
|---|
| 1165 | // incorrect |
|---|
| 1166 | modout.restore(); |
|---|
| 1167 | |
|---|
| 1168 | for (i = 0; i < n; i++) |
|---|
| 1169 | { |
|---|
| 1170 | m = rep(inpe[i]).rep.length(); |
|---|
| 1171 | outpe[i]._ZZ_pE__rep.rep.SetLength(m); |
|---|
| 1172 | |
|---|
| 1173 | xp = outpe[i]._ZZ_pE__rep.rep.elts(); |
|---|
| 1174 | ap = rep(inpe[i]).rep.elts(); |
|---|
| 1175 | |
|---|
| 1176 | for (j = 0; j < m; j++) |
|---|
| 1177 | conv(xp[j], rep(ap[j])); |
|---|
| 1178 | |
|---|
| 1179 | // We may have set a leading coefficient to 0, so we have to normalize |
|---|
| 1180 | outpe[i]._ZZ_pE__rep.normalize(); |
|---|
| 1181 | } |
|---|
| 1182 | // We may have set a leading coefficient to 0, so we have to normalize |
|---|
| 1183 | fout.normalize(); |
|---|
| 1184 | } |
|---|
| 1185 | |
|---|
| 1186 | void ZZ_pX_min_val_coeff(long & valuation, long &index, const struct ZZ_pX &f, const struct ZZ &p) |
|---|
| 1187 | { |
|---|
| 1188 | // Sets index, where the indexth coefficient of f has the minimum p-adic valuation. |
|---|
| 1189 | // Sets valuation to be this valuation. |
|---|
| 1190 | // If there are ties, index will be the lowest of the tied indices |
|---|
| 1191 | // This only makes mathematical sense when p divides the modulus of f. |
|---|
| 1192 | long i, n, v; |
|---|
| 1193 | |
|---|
| 1194 | n = f.rep.length(); |
|---|
| 1195 | if (n == 0) |
|---|
| 1196 | { |
|---|
| 1197 | index = -1; |
|---|
| 1198 | return; |
|---|
| 1199 | } |
|---|
| 1200 | |
|---|
| 1201 | const ZZ_p* fp = f.rep.elts(); |
|---|
| 1202 | ZZ *u = new ZZ(); |
|---|
| 1203 | |
|---|
| 1204 | valuation = -1; |
|---|
| 1205 | i = 0; |
|---|
| 1206 | |
|---|
| 1207 | while (valuation == -1) |
|---|
| 1208 | { |
|---|
| 1209 | if (rep(fp[i]) != 0) |
|---|
| 1210 | { |
|---|
| 1211 | index = i; |
|---|
| 1212 | valuation = ZZ_remove(*u, rep(fp[i]), p); |
|---|
| 1213 | } |
|---|
| 1214 | i++; |
|---|
| 1215 | } |
|---|
| 1216 | for (; i < n; i++) |
|---|
| 1217 | { |
|---|
| 1218 | if (rep(fp[i]) != 0) |
|---|
| 1219 | { |
|---|
| 1220 | v = ZZ_remove(*u, rep(fp[i]), p); |
|---|
| 1221 | if (v < valuation) |
|---|
| 1222 | { |
|---|
| 1223 | valuation = v; |
|---|
| 1224 | index = i; |
|---|
| 1225 | } |
|---|
| 1226 | } |
|---|
| 1227 | } |
|---|
| 1228 | delete u; |
|---|
| 1229 | } |
|---|
| 1230 | |
|---|
| 1231 | long ZZ_pX_get_val_coeff(const struct ZZ_pX &f, const struct ZZ &p, long i) |
|---|
| 1232 | { |
|---|
| 1233 | // Gets the p-adic valuation of the ith coefficient of f. |
|---|
| 1234 | ZZ *u = new ZZ(); |
|---|
| 1235 | long ans = ZZ_remove(*u, rep(coeff(f, i)), p); |
|---|
| 1236 | delete u; |
|---|
| 1237 | } |
|---|
| 1238 | |
|---|
| 1239 | void ZZ_pX_left_pshift(struct ZZ_pX &x, const struct ZZ_pX &a, const struct ZZ &pn, const struct ZZ_pContext &c) |
|---|
| 1240 | { |
|---|
| 1241 | // Multiplies each coefficient by pn, and sets the context of the answer to c. |
|---|
| 1242 | |
|---|
| 1243 | long i, n; |
|---|
| 1244 | |
|---|
| 1245 | n = a.rep.length(); |
|---|
| 1246 | x.rep.SetLength(n); |
|---|
| 1247 | |
|---|
| 1248 | ZZ_p* xp = x.rep.elts(); |
|---|
| 1249 | const ZZ_p* ap = a.rep.elts(); |
|---|
| 1250 | |
|---|
| 1251 | // I think it's enough to just restore modout once. |
|---|
| 1252 | // This should be true as long as the function rep taking a ZZ_p as an argument |
|---|
| 1253 | // and returning a ZZ works when the ZZ_p::modulus is incorrect. |
|---|
| 1254 | c.restore(); |
|---|
| 1255 | |
|---|
| 1256 | for (i = 0; i < n; i++) |
|---|
| 1257 | { |
|---|
| 1258 | conv(xp[i], rep(ap[i]) * pn); |
|---|
| 1259 | } |
|---|
| 1260 | |
|---|
| 1261 | // We may have set a leading coefficient to 0, so we have to normalize |
|---|
| 1262 | x.normalize(); |
|---|
| 1263 | } |
|---|
| 1264 | |
|---|
| 1265 | void ZZ_pX_right_pshift(struct ZZ_pX &x, const struct ZZ_pX &a, const struct ZZ &pn, const struct ZZ_pContext &c) |
|---|
| 1266 | { |
|---|
| 1267 | // Divides each coefficient by pn, and sets the context of the answer to c. |
|---|
| 1268 | |
|---|
| 1269 | long i, n; |
|---|
| 1270 | |
|---|
| 1271 | n = a.rep.length(); |
|---|
| 1272 | x.rep.SetLength(n); |
|---|
| 1273 | |
|---|
| 1274 | ZZ_p* xp = x.rep.elts(); |
|---|
| 1275 | const ZZ_p* ap = a.rep.elts(); |
|---|
| 1276 | |
|---|
| 1277 | // I think it's enough to just restore modout once. |
|---|
| 1278 | // This should be true as long as the function rep taking a ZZ_p as an argument |
|---|
| 1279 | // and returning a ZZ works when the ZZ_p::modulus is incorrect. |
|---|
| 1280 | c.restore(); |
|---|
| 1281 | |
|---|
| 1282 | for (i = 0; i < n; i++) |
|---|
| 1283 | { |
|---|
| 1284 | conv(xp[i], rep(ap[i]) / pn); |
|---|
| 1285 | } |
|---|
| 1286 | |
|---|
| 1287 | // We may have set a leading coefficient to 0, so we have to normalize |
|---|
| 1288 | x.normalize(); |
|---|
| 1289 | } |
|---|
| 1290 | |
|---|
| 1291 | void ZZ_pX_InvMod_newton(struct ZZ_pX &x, const struct ZZ_pX &a, const struct ZZ_pXModulus &F, const struct ZZ_pContext &cpn, const struct ZZ_pContext &cp) |
|---|
| 1292 | { |
|---|
| 1293 | int j; |
|---|
| 1294 | cp.restore(); |
|---|
| 1295 | ZZ_pX *amodp = new ZZ_pX(); |
|---|
| 1296 | ZZ_pX *xmodp = new ZZ_pX(); |
|---|
| 1297 | ZZ_pX *fmodp = new ZZ_pX(); |
|---|
| 1298 | ZZ_pX_conv_modulus(*amodp, a, cp); |
|---|
| 1299 | ZZ_pX_conv_modulus(*fmodp, F.val(), cp); |
|---|
| 1300 | InvMod(*xmodp, *amodp, *fmodp); |
|---|
| 1301 | //cout << "xmodp: " << *xmodp << "\namodp: " << *amodp << "\nfmodp: " << *fmodp << "\n"; |
|---|
| 1302 | cpn.restore(); |
|---|
| 1303 | ZZ_pX *minusa = new ZZ_pX(); |
|---|
| 1304 | ZZ_pX *xn = new ZZ_pX(); |
|---|
| 1305 | ZZ_pX_conv_modulus(*xn, *xmodp, cpn); |
|---|
| 1306 | negate(*minusa, a); |
|---|
| 1307 | do |
|---|
| 1308 | { |
|---|
| 1309 | *xn = x; |
|---|
| 1310 | // x_n = 2*x_{n-1} - a*x_{n-1}^2 = (2 - a*x_{n-1})*x_{n-1} |
|---|
| 1311 | MulMod(x, *minusa, *xn, F); |
|---|
| 1312 | SetCoeff(x, 0, ConstTerm(x) + 2); |
|---|
| 1313 | MulMod(x, x, *xn, F); |
|---|
| 1314 | //cout << "x: " << x << "\nxn: " << *xn << "\n"; |
|---|
| 1315 | //cin >> j; |
|---|
| 1316 | } while (x != (*xn)); |
|---|
| 1317 | delete amodp; |
|---|
| 1318 | delete xmodp; |
|---|
| 1319 | delete fmodp; |
|---|
| 1320 | delete minusa; |
|---|
| 1321 | delete xn; |
|---|
| 1322 | } |
|---|
| 1323 | |
|---|
| 1324 | void ZZ_pX_eis_shift(struct ZZ_pX &x, const struct ZZ_pX &a, long n, const struct ZZ_pXMultiplier* low_shifter, const struct ZZ_pXMultiplier* high_shifter, const struct ZZ_pXModulus &modulus, const struct ZZ &p, const struct ZZ_pContext &cupper, const struct ZZ_pContext &clower) |
|---|
| 1325 | { |
|---|
| 1326 | long degree = deg(modulus); |
|---|
| 1327 | long pshift = n / degree; |
|---|
| 1328 | long eis_part = n % degree; |
|---|
| 1329 | long two_shift = 1; |
|---|
| 1330 | int i; |
|---|
| 1331 | |
|---|
| 1332 | cupper.restore(); |
|---|
| 1333 | //cout << "eis_part: " << eis_part << "\n"; |
|---|
| 1334 | //cout << "pshift: " << pshift << "\n"; |
|---|
| 1335 | ZZ_pX low_part; // = new ZZ_pX(); |
|---|
| 1336 | ZZ_pX shifted_high_part; // = new ZZ_pX(); |
|---|
| 1337 | x = a; |
|---|
| 1338 | //cout << "beginning: a = " << a << "\n"; |
|---|
| 1339 | if (pshift) |
|---|
| 1340 | { |
|---|
| 1341 | i = 0; |
|---|
| 1342 | two_shift = 1; |
|---|
| 1343 | ZZ *pn = new ZZ(); |
|---|
| 1344 | power(*pn, p, pshift); |
|---|
| 1345 | ZZ_pX_right_pshift(x, x, *pn, clower); |
|---|
| 1346 | delete pn; |
|---|
| 1347 | while (pshift > 0) |
|---|
| 1348 | { |
|---|
| 1349 | if (pshift & 1) |
|---|
| 1350 | { |
|---|
| 1351 | MulMod(x, x, high_shifter[i], modulus); |
|---|
| 1352 | } |
|---|
| 1353 | i++; |
|---|
| 1354 | two_shift <<= 1; |
|---|
| 1355 | pshift >>= 1; |
|---|
| 1356 | } |
|---|
| 1357 | } |
|---|
| 1358 | i = 0; |
|---|
| 1359 | two_shift = 1; |
|---|
| 1360 | while (eis_part > 0) |
|---|
| 1361 | { |
|---|
| 1362 | //cout << "eis_part = " << eis_part << "\n"; |
|---|
| 1363 | if (eis_part & 1) |
|---|
| 1364 | { |
|---|
| 1365 | //cout << "i = " << i << "\n"; |
|---|
| 1366 | //cout << "two_shift = " << two_shift << "\n"; |
|---|
| 1367 | shifted_high_part = x >> two_shift; |
|---|
| 1368 | //cout << "shifted_high_part = " << shifted_high_part << "\n"; |
|---|
| 1369 | low_part = x - (shifted_high_part << two_shift); |
|---|
| 1370 | //cout << "low_part = " << low_part << "\n"; |
|---|
| 1371 | ZZ_pX_right_pshift(low_part, low_part, p, cupper); |
|---|
| 1372 | //cout << "low_part = " << low_part << "\n"; |
|---|
| 1373 | MulMod(low_part, low_part, low_shifter[i], modulus); |
|---|
| 1374 | //cout << "low_part = " << low_part << "\n"; |
|---|
| 1375 | x = low_part + shifted_high_part; |
|---|
| 1376 | //cout << "x = " << x << "\n"; |
|---|
| 1377 | } |
|---|
| 1378 | i++; |
|---|
| 1379 | two_shift <<= 1; |
|---|
| 1380 | eis_part >>= 1; |
|---|
| 1381 | } |
|---|
| 1382 | //delete low_part; |
|---|
| 1383 | //delete shifted_high_part; |
|---|
| 1384 | } |
|---|
| 1385 | |
|---|
| 1386 | // Functions for using ZZ_pX's for p-adic extensions |
|---|
| 1387 | |
|---|
| 1388 | void ZZ_pX_conv_modulus(ZZ_pX &fout, const ZZ_pX &fin, const ZZ_pContext &modout) |
|---|
| 1389 | { |
|---|
| 1390 | // Changes the modulus of fin to modout, and puts the result in fout. |
|---|
| 1391 | long i, n; |
|---|
| 1392 | |
|---|
| 1393 | n = fin.rep.length(); |
|---|
| 1394 | fout.rep.SetLength(n); |
|---|
| 1395 | |
|---|
| 1396 | ZZ_p* xp = fout.rep.elts(); |
|---|
| 1397 | const ZZ_p* ap = fin.rep.elts(); |
|---|
| 1398 | |
|---|
| 1399 | // I think it's enough to just restore modout once. |
|---|
| 1400 | // This should be true as long as the function rep taking a ZZ_p as an argument |
|---|
| 1401 | // and returning a ZZ works when the ZZ_p::modulus is incorrect. |
|---|
| 1402 | modout.restore(); |
|---|
| 1403 | |
|---|
| 1404 | for (i = 0; i < n; i++) |
|---|
| 1405 | { |
|---|
| 1406 | conv(xp[i], rep(ap[i])); |
|---|
| 1407 | } |
|---|
| 1408 | |
|---|
| 1409 | // We may have set a leading coefficient to 0, so we have to normalize |
|---|
| 1410 | fout.normalize(); |
|---|
| 1411 | } |
|---|
| 1412 | |
|---|
| 1413 | void ZZ_pEX_conv_modulus(ZZ_pEX &fout, const ZZ_pEX &fin, const ZZ_pContext &modout) |
|---|
| 1414 | { |
|---|
| 1415 | // Changes the modulus of fin to modout, and puts the result in fout. |
|---|
| 1416 | long i, n, j, m; |
|---|
| 1417 | |
|---|
| 1418 | n = fin.rep.length(); |
|---|
| 1419 | fout.rep.SetLength(n); |
|---|
| 1420 | |
|---|
| 1421 | ZZ_pE* outpe = fout.rep.elts(); |
|---|
| 1422 | const ZZ_pE* inpe = fin.rep.elts(); |
|---|
| 1423 | |
|---|
| 1424 | ZZ_p* xp; |
|---|
| 1425 | const ZZ_p* ap; |
|---|
| 1426 | // I think it's enough to just restore modout once |
|---|
| 1427 | // This should be true as long as Loophole() offers access to |
|---|
| 1428 | // the underlying ZZ_pX representations of ZZ_pEs, |
|---|
| 1429 | // and rep of a ZZ_p (giving a ZZ) works even if the ZZ_p::modulus is |
|---|
| 1430 | // incorrect |
|---|
| 1431 | modout.restore(); |
|---|
| 1432 | |
|---|
| 1433 | for (i = 0; i < n; i++) |
|---|
| 1434 | { |
|---|
| 1435 | m = rep(inpe[i]).rep.length(); |
|---|
| 1436 | outpe[i]._ZZ_pE__rep.rep.SetLength(m); |
|---|
| 1437 | |
|---|
| 1438 | xp = outpe[i]._ZZ_pE__rep.rep.elts(); |
|---|
| 1439 | ap = rep(inpe[i]).rep.elts(); |
|---|
| 1440 | |
|---|
| 1441 | for (j = 0; j < m; j++) |
|---|
| 1442 | conv(xp[j], rep(ap[j])); |
|---|
| 1443 | |
|---|
| 1444 | // We may have set a leading coefficient to 0, so we have to normalize |
|---|
| 1445 | outpe[i]._ZZ_pE__rep.normalize(); |
|---|
| 1446 | } |
|---|
| 1447 | // We may have set a leading coefficient to 0, so we have to normalize |
|---|
| 1448 | fout.normalize(); |
|---|
| 1449 | } |
|---|
| 1450 | |
|---|
| 1451 | void ZZ_pX_min_val_coeff(long & valuation, long &index, const struct ZZ_pX &f, const struct ZZ &p) |
|---|
| 1452 | { |
|---|
| 1453 | // Sets index, where the indexth coefficient of f has the minimum p-adic valuation. |
|---|
| 1454 | // Sets valuation to be this valuation. |
|---|
| 1455 | // If there are ties, index will be the lowest of the tied indices |
|---|
| 1456 | // This only makes mathematical sense when p divides the modulus of f. |
|---|
| 1457 | long i, n, v; |
|---|
| 1458 | |
|---|
| 1459 | n = f.rep.length(); |
|---|
| 1460 | if (n == 0) |
|---|
| 1461 | { |
|---|
| 1462 | index = -1; |
|---|
| 1463 | return; |
|---|
| 1464 | } |
|---|
| 1465 | |
|---|
| 1466 | const ZZ_p* fp = f.rep.elts(); |
|---|
| 1467 | ZZ *u = new ZZ(); |
|---|
| 1468 | |
|---|
| 1469 | valuation = -1; |
|---|
| 1470 | i = 0; |
|---|
| 1471 | |
|---|
| 1472 | while (valuation == -1) |
|---|
| 1473 | { |
|---|
| 1474 | if (rep(fp[i]) != 0) |
|---|
| 1475 | { |
|---|
| 1476 | index = i; |
|---|
| 1477 | valuation = ZZ_remove(*u, rep(fp[i]), p); |
|---|
| 1478 | } |
|---|
| 1479 | i++; |
|---|
| 1480 | } |
|---|
| 1481 | for (; i < n; i++) |
|---|
| 1482 | { |
|---|
| 1483 | if (rep(fp[i]) != 0) |
|---|
| 1484 | { |
|---|
| 1485 | v = ZZ_remove(*u, rep(fp[i]), p); |
|---|
| 1486 | if (v < valuation) |
|---|
| 1487 | { |
|---|
| 1488 | valuation = v; |
|---|
| 1489 | index = i; |
|---|
| 1490 | } |
|---|
| 1491 | } |
|---|
| 1492 | } |
|---|
| 1493 | delete u; |
|---|
| 1494 | } |
|---|
| 1495 | |
|---|
| 1496 | long ZZ_pX_get_val_coeff(const struct ZZ_pX &f, const struct ZZ &p, long i) |
|---|
| 1497 | { |
|---|
| 1498 | // Gets the p-adic valuation of the ith coefficient of f. |
|---|
| 1499 | ZZ *u = new ZZ(); |
|---|
| 1500 | long ans = ZZ_remove(*u, rep(coeff(f, i)), p); |
|---|
| 1501 | delete u; |
|---|
| 1502 | } |
|---|
| 1503 | |
|---|
| 1504 | void ZZ_pX_left_pshift(struct ZZ_pX &x, const struct ZZ_pX &a, const struct ZZ &pn, const struct ZZ_pContext &c) |
|---|
| 1505 | { |
|---|
| 1506 | // Multiplies each coefficient by pn, and sets the context of the answer to c. |
|---|
| 1507 | |
|---|
| 1508 | long i, n; |
|---|
| 1509 | |
|---|
| 1510 | n = a.rep.length(); |
|---|
| 1511 | x.rep.SetLength(n); |
|---|
| 1512 | |
|---|
| 1513 | ZZ_p* xp = x.rep.elts(); |
|---|
| 1514 | const ZZ_p* ap = a.rep.elts(); |
|---|
| 1515 | |
|---|
| 1516 | // I think it's enough to just restore modout once. |
|---|
| 1517 | // This should be true as long as the function rep taking a ZZ_p as an argument |
|---|
| 1518 | // and returning a ZZ works when the ZZ_p::modulus is incorrect. |
|---|
| 1519 | c.restore(); |
|---|
| 1520 | |
|---|
| 1521 | for (i = 0; i < n; i++) |
|---|
| 1522 | { |
|---|
| 1523 | conv(xp[i], rep(ap[i]) * pn); |
|---|
| 1524 | } |
|---|
| 1525 | |
|---|
| 1526 | // We may have set a leading coefficient to 0, so we have to normalize |
|---|
| 1527 | x.normalize(); |
|---|
| 1528 | } |
|---|
| 1529 | |
|---|
| 1530 | void ZZ_pX_right_pshift(struct ZZ_pX &x, const struct ZZ_pX &a, const struct ZZ &pn, const struct ZZ_pContext &c) |
|---|
| 1531 | { |
|---|
| 1532 | // Divides each coefficient by pn, and sets the context of the answer to c. |
|---|
| 1533 | |
|---|
| 1534 | long i, n; |
|---|
| 1535 | |
|---|
| 1536 | n = a.rep.length(); |
|---|
| 1537 | x.rep.SetLength(n); |
|---|
| 1538 | |
|---|
| 1539 | ZZ_p* xp = x.rep.elts(); |
|---|
| 1540 | const ZZ_p* ap = a.rep.elts(); |
|---|
| 1541 | |
|---|
| 1542 | // I think it's enough to just restore modout once. |
|---|
| 1543 | // This should be true as long as the function rep taking a ZZ_p as an argument |
|---|
| 1544 | // and returning a ZZ works when the ZZ_p::modulus is incorrect. |
|---|
| 1545 | c.restore(); |
|---|
| 1546 | |
|---|
| 1547 | for (i = 0; i < n; i++) |
|---|
| 1548 | { |
|---|
| 1549 | conv(xp[i], rep(ap[i]) / pn); |
|---|
| 1550 | } |
|---|
| 1551 | |
|---|
| 1552 | // We may have set a leading coefficient to 0, so we have to normalize |
|---|
| 1553 | x.normalize(); |
|---|
| 1554 | } |
|---|
| 1555 | |
|---|
| 1556 | void ZZ_pX_InvMod_newton(struct ZZ_pX &x, const struct ZZ_pX &a, const struct ZZ_pXModulus &F, const struct ZZ_pContext &cpn, const struct ZZ_pContext &cp) |
|---|
| 1557 | { |
|---|
| 1558 | int j; |
|---|
| 1559 | cp.restore(); |
|---|
| 1560 | ZZ_pX *amodp = new ZZ_pX(); |
|---|
| 1561 | ZZ_pX *xmodp = new ZZ_pX(); |
|---|
| 1562 | ZZ_pX *fmodp = new ZZ_pX(); |
|---|
| 1563 | ZZ_pX_conv_modulus(*amodp, a, cp); |
|---|
| 1564 | ZZ_pX_conv_modulus(*fmodp, F.val(), cp); |
|---|
| 1565 | InvMod(*xmodp, *amodp, *fmodp); |
|---|
| 1566 | //cout << "xmodp: " << *xmodp << "\namodp: " << *amodp << "\nfmodp: " << *fmodp << "\n"; |
|---|
| 1567 | cpn.restore(); |
|---|
| 1568 | ZZ_pX *minusa = new ZZ_pX(); |
|---|
| 1569 | ZZ_pX *xn = new ZZ_pX(); |
|---|
| 1570 | ZZ_pX_conv_modulus(*xn, *xmodp, cpn); |
|---|
| 1571 | negate(*minusa, a); |
|---|
| 1572 | do |
|---|
| 1573 | { |
|---|
| 1574 | *xn = x; |
|---|
| 1575 | // x_n = 2*x_{n-1} - a*x_{n-1}^2 = (2 - a*x_{n-1})*x_{n-1} |
|---|
| 1576 | MulMod(x, *minusa, *xn, F); |
|---|
| 1577 | SetCoeff(x, 0, ConstTerm(x) + 2); |
|---|
| 1578 | MulMod(x, x, *xn, F); |
|---|
| 1579 | //cout << "x: " << x << "\nxn: " << *xn << "\n"; |
|---|
| 1580 | //cin >> j; |
|---|
| 1581 | } while (x != (*xn)); |
|---|
| 1582 | delete amodp; |
|---|
| 1583 | delete xmodp; |
|---|
| 1584 | delete fmodp; |
|---|
| 1585 | delete minusa; |
|---|
| 1586 | delete xn; |
|---|
| 1587 | } |
|---|
| 1588 | |
|---|
| 1589 | void ZZ_pX_eis_shift(struct ZZ_pX &x, const struct ZZ_pX &a, long n, const struct ZZ_pXMultiplier* low_shifter, const struct ZZ_pXMultiplier* high_shifter, const struct ZZ_pXModulus &modulus, const struct ZZ &p, const struct ZZ_pContext &cupper, const struct ZZ_pContext &clower) |
|---|
| 1590 | { |
|---|
| 1591 | long degree = deg(modulus); |
|---|
| 1592 | long pshift = n / degree; |
|---|
| 1593 | long eis_part = n % degree; |
|---|
| 1594 | long two_shift = 1; |
|---|
| 1595 | int i; |
|---|
| 1596 | |
|---|
| 1597 | cupper.restore(); |
|---|
| 1598 | //cout << "eis_part: " << eis_part << "\n"; |
|---|
| 1599 | //cout << "pshift: " << pshift << "\n"; |
|---|
| 1600 | ZZ_pX low_part; // = new ZZ_pX(); |
|---|
| 1601 | ZZ_pX shifted_high_part; // = new ZZ_pX(); |
|---|
| 1602 | x = a; |
|---|
| 1603 | //cout << "beginning: a = " << a << "\n"; |
|---|
| 1604 | if (pshift) |
|---|
| 1605 | { |
|---|
| 1606 | i = 0; |
|---|
| 1607 | two_shift = 1; |
|---|
| 1608 | ZZ *pn = new ZZ(); |
|---|
| 1609 | power(*pn, p, pshift); |
|---|
| 1610 | ZZ_pX_right_pshift(x, x, *pn, clower); |
|---|
| 1611 | delete pn; |
|---|
| 1612 | while (pshift > 0) |
|---|
| 1613 | { |
|---|
| 1614 | if (pshift & 1) |
|---|
| 1615 | { |
|---|
| 1616 | MulMod(x, x, high_shifter[i], modulus); |
|---|
| 1617 | } |
|---|
| 1618 | i++; |
|---|
| 1619 | two_shift <<= 1; |
|---|
| 1620 | pshift >>= 1; |
|---|
| 1621 | } |
|---|
| 1622 | } |
|---|
| 1623 | i = 0; |
|---|
| 1624 | two_shift = 1; |
|---|
| 1625 | while (eis_part > 0) |
|---|
| 1626 | { |
|---|
| 1627 | //cout << "eis_part = " << eis_part << "\n"; |
|---|
| 1628 | if (eis_part & 1) |
|---|
| 1629 | { |
|---|
| 1630 | //cout << "i = " << i << "\n"; |
|---|
| 1631 | //cout << "two_shift = " << two_shift << "\n"; |
|---|
| 1632 | shifted_high_part = x >> two_shift; |
|---|
| 1633 | //cout << "shifted_high_part = " << shifted_high_part << "\n"; |
|---|
| 1634 | low_part = x - (shifted_high_part << two_shift); |
|---|
| 1635 | //cout << "low_part = " << low_part << "\n"; |
|---|
| 1636 | ZZ_pX_right_pshift(low_part, low_part, p, cupper); |
|---|
| 1637 | //cout << "low_part = " << low_part << "\n"; |
|---|
| 1638 | MulMod(low_part, low_part, low_shifter[i], modulus); |
|---|
| 1639 | //cout << "low_part = " << low_part << "\n"; |
|---|
| 1640 | x = low_part + shifted_high_part; |
|---|
| 1641 | //cout << "x = " << x << "\n"; |
|---|
| 1642 | } |
|---|
| 1643 | i++; |
|---|
| 1644 | two_shift <<= 1; |
|---|
| 1645 | eis_part >>= 1; |
|---|
| 1646 | } |
|---|
| 1647 | //delete low_part; |
|---|
| 1648 | //delete shifted_high_part; |
|---|
| 1649 | } |
|---|
| 1650 | |
|---|
| 1651 | ZZ_pEContext* ZZ_pEContext_new(ZZ_pX *f) |
|---|
| 1652 | { |
|---|
| 1653 | return new ZZ_pEContext(*f); |
|---|
| 1654 | } |
|---|
| 1655 | |
|---|
| 1656 | ZZ_pEContext* ZZ_pEContext_construct(void *mem, ZZ_pX *f) |
|---|
| 1657 | { |
|---|
| 1658 | return new(mem) ZZ_pEContext(*f); |
|---|
| 1659 | } |
|---|
| 1660 | |
|---|
| 1661 | void ZZ_pEContext_restore(ZZ_pEContext *ctx) |
|---|
| 1662 | { |
|---|
| 1663 | ctx->restore(); |
|---|
| 1664 | } |
|---|
| 1665 | |
|---|
| 1666 | zz_pContext* zz_pContext_new(long p) |
|---|
| 1667 | { |
|---|
| 1668 | return new zz_pContext(p); |
|---|
| 1669 | } |
|---|
| 1670 | |
|---|
| 1671 | zz_pContext* zz_pContext_construct(void *mem, long p) |
|---|
| 1672 | { |
|---|
| 1673 | return new(mem) zz_pContext(p); |
|---|
| 1674 | } |
|---|
| 1675 | |
|---|
| 1676 | void zz_pContext_restore(zz_pContext *ctx) |
|---|
| 1677 | { |
|---|
| 1678 | ctx->restore(); |
|---|
| 1679 | } |
|---|