Annotation of OpenXM_contrib/pari/src/modules/mpqs.c, Revision 1.1
1.1 ! maekawa 1: /* COPYRIGHT (c) 1998 Thomas Papanikolaou and Xavier Roblot
! 2: * All rights reserved. (papanik,roblot@math.u-bordeaux.fr)
! 3: *
! 4: * FILE: pari-x.y.z/src/modules/mpqs.c (thereafter called Software)
! 5: * (NOTE: the exact position of the file within PARI may vary).
! 6: *
! 7: * DESCRIPTION: Implementation of the Self-Initializing Multi-Polynomial
! 8: * Quadratic Sieve based on code developed as part of the LiDIA project
! 9: * (http://www.informatik.tu-darmstadt.de/TI/LiDIA/Welcome.html)
! 10: *
! 11: * LEGALESE: This Software is intended as a service to the PARI user
! 12: * community, but the authors cannot be held responsible for any
! 13: * consequences, either direct or indirect, which the use of this
! 14: * package may have. It can be freely copied and spread for non
! 15: * commercial purposes, as long as it is not modified and this
! 16: * copyright notice stays attached. A free, exclusive license to
! 17: * distribute the Software is herewith granted to the authors of PARI,
! 18: * as stated in the PARI copyright file. However, modified versions and
! 19: * derivatives of this Software do not become eligible for commercial
! 20: * use, i.e. all commercial rights remain with the original authors.
! 21: * Especially, including PARI into commercial code (either as text or
! 22: * by linking the PARI library) does not allow the use of the Software.
! 23: * If you want to use this Software, modified versions or derivatives of
! 24: * this Software for commercial purposes, you have to contact the original
! 25: * authors for a commercial license.
! 26: *
! 27: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
! 28: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
! 29: * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
! 30: */
! 31: /* $Id: mpqs.c,v 1.2 1999/09/20 14:09:59 karim Exp $ */
! 32: #include "pari.h"
! 33:
! 34: #ifndef SEEK_SET
! 35: # define SEEK_SET 0
! 36: #endif
! 37:
! 38: #ifdef __CYGWIN32__
! 39: /* otherwise fseek() goes crazy due to silent \n <--> LF translations */
! 40: # define WRITE "wb"
! 41: # define READ "rb"
! 42: #else
! 43: # define WRITE "w"
! 44: # define READ "r"
! 45: #endif
! 46:
! 47: #ifdef MPQS_DEBUG_VERYVERBOSE
! 48: # ifndef MPQS_DEBUG_VERBOSE
! 49: # define MPQS_DEBUG_VERBOSE
! 50: # endif
! 51: #endif
! 52:
! 53: #ifdef MPQS_DEBUG_VERBOSE
! 54: # ifndef MPQS_DEBUG
! 55: # define MPQS_DEBUG
! 56: # endif
! 57: #endif
! 58:
! 59: #define MPQS_STRING_LENGTH (4 * 1024)
! 60: #define MPQS_CANDIDATE_ARRAY_SIZE 2000
! 61: #define MPQS_PRIMES_FOR_MULTIPLIER 5
! 62: /* `large primes' must be smaller than
! 63: * max(MPQS_LP_BOUND, largest_prime_in_FB) * MPQS_LP_FACTOR
! 64: */
! 65: #define MPQS_LP_BOUND 125000 /* works for 32 and 64bit */
! 66: #define MPQS_LP_FACTOR 80
! 67:
! 68: typedef ulong *mpqs_gauss_row;
! 69: typedef long *mpqs_gauss_indices;
! 70: typedef mpqs_gauss_row *mpqs_gauss_matrix;
! 71:
! 72: /* BEGIN: global variables to disappear as soon as possible */
! 73: /* names for temp. files, set in mpqs_get_filename */
! 74: static char *FREL_str;
! 75: static char *FNEW_str;
! 76: static char *LPREL_str;
! 77: static char *LPNEW_str;
! 78: static char *TMP_str;
! 79: static char *COMB_str;
! 80:
! 81: /* our own pointer to PARI's or to our own prime diffs table.
! 82: * NB the latter is never freed, unless we need to replace it with
! 83: * an even larger one. */
! 84: static byteptr mpqs_diffptr = NULL;
! 85: static long mpqs_prime_count = 0;
! 86:
! 87: /* state flags for cleanup if we get interrupted --GN */
! 88: static char all_clean = 1; /* set to 0 while mpqs() is busy */
! 89: /* END: global variables to disappear as soon as possible */
! 90:
! 91: /******************************/
! 92:
! 93: /**
! 94: ** determines a unique name for a file based on a short nickname
! 95: **/
! 96:
! 97: /* name is allocated on the stack */
! 98: static char *
! 99: mpqs_get_filename(char *s)
! 100: {
! 101: char *buf;
! 102:
! 103: s = pari_unique_filename(s);
! 104: buf = (char*) new_chunk((strlen(s) / sizeof(long)) + 2);
! 105: return strcpy(buf, s);
! 106: }
! 107:
! 108: /**
! 109: ** compares two `large prime' relations according to their
! 110: ** first element (the large prime itself).
! 111: **/
! 112:
! 113: static int
! 114: mpqs_relations_cmp(const void *a, const void *b)
! 115: {
! 116: char **sa = (char **) a;
! 117: char **sb = (char **) b;
! 118: long qa = strtol(*sa, NULL, 10);
! 119: long qb = strtol(*sb, NULL, 10);
! 120: /* atol() isn't entirely portable for the Full Relations case where the
! 121: strings of digits are too long to fit into a long --GN */
! 122: if (qa < qb) return -1;
! 123: else if (qa > qb) return 1;
! 124: else return strcmp(*sa, *sb);
! 125: }
! 126:
! 127: /**
! 128: ** Given a file "filename" containing full or `large prime' relations,
! 129: ** this function rearranges the file so that relations are sorted by
! 130: ** their first elements. Works also for sorting full relations.
! 131: ** Works in memory, discards duplicate lines, and overwrites the
! 132: ** original file.
! 133: **/
! 134:
! 135: #define bummer(fn) err(talker, "error whilst writing to file %s", fn)
! 136: #define min_bufspace 120 /* use new buffer when < min_bufspace left */
! 137: #define buflist_size 1024 /* size of list-of-buffers blocks */
! 138:
! 139: static long
! 140: mpqs_sort_lp_file(char *filename)
! 141: {
! 142: pariFILE *pTMP;
! 143: FILE *TMP;
! 144: char *old_s, **sort_table = (char**)avma, *buf, *cur_line;
! 145: static char **buflist_head = NULL;
! 146: char **buflist, **next_buflist;
! 147: long i, j, bufspace, length, count, av=avma;
! 148:
! 149: if (!buflist_head)
! 150: {
! 151: buflist_head = (char **) gpmalloc(buflist_size * sizeof(char *));
! 152: buflist = buflist_head;
! 153: *buflist++ = NULL; /* flag this as last and only buflist block */
! 154: }
! 155: else
! 156: buflist = buflist_head + 1;
! 157: /* this block will never be freed, and extra blocks may be allocated as
! 158: needed and linked ahead of it. NB it turns out that whilst extra
! 159: buflist blocks might have been needed when we were still sorting
! 160: entire FREL files (more than 1023 buffers, corresponding to about
! 161: 20000 lines of c.200 characters), they should never be touched now
! 162: that we only sort LPNEW and FNEW files, which are rather shorter.
! 163: But the code might as well stay around for paranoia, or for future
! 164: upgrades to handling even larger numbers (and factor bases and thus
! 165: relations files). It only costs one comparison per buffer allocation.
! 166: --GN */
! 167:
! 168: pTMP = pari_fopen(filename, READ);
! 169: TMP = pTMP->file;
! 170: /* get first buffer and read first line, if any, into it */
! 171: buf = (char *) gpmalloc(MPQS_STRING_LENGTH * sizeof(char));
! 172: cur_line = buf;
! 173: bufspace = MPQS_STRING_LENGTH;
! 174:
! 175: if (fgets(cur_line, bufspace, TMP) == NULL)
! 176: { /* file empty */
! 177: avma = av;
! 178: free(buf);
! 179: pari_fclose(pTMP);
! 180: return 0;
! 181: }
! 182: /* enter first buffer into buflist */
! 183: *buflist++ = buf; /* can't overflow the buflist block */
! 184: length = strlen(cur_line) + 1; /* count the \0 byte as well */
! 185: bufspace -= length;
! 186:
! 187: /* at start of loop, one line from the file is sitting in cur_line inside
! 188: buf, the next will go into cur_line + length, and there's room for
! 189: bufspace further characters in buf.
! 190: The loop reads another line if one exists, and if this overruns the
! 191: current buffer, it allocates a fresh one --GN */
! 192:
! 193: for (i=0, sort_table--; /* until end of file */; i++, sort_table--)
! 194: {
! 195: /* sort_table is allocated on the stack, 0x100 cells at a time. Hence the
! 196: * stack must be left alone in the rest of the loop to keep the array
! 197: * connected. In particular, buffers can't be new_chunk'ed --KB */
! 198: if ((i & 0xff) == 0) new_chunk(0x100);
! 199: *sort_table = cur_line;
! 200: cur_line += length;
! 201:
! 202: /* if very little room is left, allocate a fresh buffer before
! 203: attempting to read a line, and remember to free it if no
! 204: further line is forthcoming. This avoids some copying of
! 205: partial lines --GN */
! 206: if (bufspace < min_bufspace)
! 207: {
! 208: if (
! 209: #ifdef MPQS_DEBUG
! 210: 1 ||
! 211: #endif
! 212: DEBUGLEVEL >= 7)
! 213: fprintferr("MQPS: short of space -- another buffer for sorting\n");
! 214: buf = (char *) gpmalloc(MPQS_STRING_LENGTH * sizeof(char));
! 215: cur_line = buf;
! 216: bufspace = MPQS_STRING_LENGTH;
! 217: if (fgets(cur_line, bufspace, TMP) == NULL)
! 218: {
! 219: free(buf); break;
! 220: }
! 221: else
! 222: {
! 223: /* remember buffer for later deallocation */
! 224: if (buflist - buflist_head >= buflist_size)
! 225: {
! 226: /* need another buflist block */
! 227: next_buflist =
! 228: (char **) gpmalloc(buflist_size * sizeof(char *));
! 229: *next_buflist = (char *)buflist_head; /* link */
! 230: buflist_head = next_buflist;
! 231: buflist = buflist_head + 1;
! 232: }
! 233: *buflist++ = buf;
! 234: length = strlen(cur_line) + 1;
! 235: bufspace -= length;
! 236: continue;
! 237: }
! 238: }
! 239:
! 240: /* normal case: try fitting another line into the current buffer,
! 241: break if none exists */
! 242: if (fgets(cur_line, bufspace, TMP) == NULL) break;
! 243: length = strlen(cur_line) + 1;
! 244: bufspace -= length;
! 245:
! 246: /* check whether we got the entire line or only part of it */
! 247: if (bufspace == 0 && cur_line[length-2] != '\n')
! 248: {
! 249: long lg1;
! 250: if (
! 251: #ifdef MPQS_DEBUG
! 252: 1 ||
! 253: #endif
! 254: DEBUGLEVEL >= 7)
! 255: fprintferr("MQPS: line wrap -- another buffer for sorting\n");
! 256: buf = (char *) gpmalloc(MPQS_STRING_LENGTH * sizeof(char));
! 257: /* remember buffer for later deallocation */
! 258: if (buflist - buflist_head >= buflist_size)
! 259: {
! 260: /* need another buflist block */
! 261: next_buflist =
! 262: (char **) gpmalloc(buflist_size * sizeof(char *));
! 263: *next_buflist = (char *)buflist_head; /* link */
! 264: buflist_head = next_buflist;
! 265: buflist = buflist_head + 1;
! 266: }
! 267: *buflist++ = buf;
! 268:
! 269: /* copy what we've got to the new buffer */
! 270: (void)strcpy(buf, cur_line); /* cannot overflow */
! 271: cur_line = buf + length - 1; /* point at the \0 byte */
! 272: bufspace = MPQS_STRING_LENGTH - length + 1;
! 273: /* read remainder of line */
! 274: if (fgets(cur_line, bufspace, TMP) == NULL)
! 275: err(talker,"MPQS: relations file truncated?!\n");
! 276: lg1 = strlen(cur_line);
! 277: length += lg1; /* we already counted the \0 once */
! 278: bufspace -= (lg1 + 1); /* but here we must take it into account */
! 279: cur_line = buf; /* back up to the beginning of the line */
! 280: }
! 281: } /* for */
! 282:
! 283: pari_fclose(pTMP);
! 284:
! 285: #if 0 /* caught above, can no longer happen */
! 286: if (i == 0)
! 287: {
! 288: avma = av; return 0;
! 289: }
! 290: #endif
! 291:
! 292: /* sort the whole lot in place by swapping pointers */
! 293: qsort(sort_table, i, sizeof(char *), mpqs_relations_cmp);
! 294:
! 295: /* copy results back to the original file, skipping exact duplicates */
! 296: pTMP = pari_fopen(filename, WRITE);
! 297: TMP = pTMP->file;
! 298: old_s = sort_table[0];
! 299: if (fputs(sort_table[0], TMP) < 0)
! 300: bummer(filename);
! 301: count = 1;
! 302: for(j = 1; j < i; j++)
! 303: {
! 304: if (strcmp(old_s, sort_table[j]) != 0)
! 305: {
! 306: if (fputs(sort_table[j], TMP) < 0)
! 307: bummer(filename);
! 308: count++;
! 309: }
! 310: old_s = sort_table[j];
! 311: }
! 312: pari_fclose(pTMP);
! 313: if (
! 314: #ifdef MPQS_DEBUG
! 315: 1 ||
! 316: #endif
! 317: DEBUGLEVEL >= 6)
! 318: fprintferr("MPQS: done sorting one file.\n");
! 319:
! 320: /* deallocate buffers and any extraneous buflist blocks except the first */
! 321: while (*--buflist)
! 322: {
! 323: if (buflist != buflist_head) /* not a linkage pointer */
! 324: free((void *) *buflist); /* free a buffer */
! 325: else /* linkage pointer */
! 326: {
! 327: next_buflist = (char **)(*buflist);
! 328: free((void *)buflist_head); /* free a buflist block */
! 329: buflist_head = next_buflist;
! 330: buflist = buflist_head + buflist_size;
! 331: }
! 332: }
! 333: #if 0
! 334: for (j = 0; j < i; j++)
! 335: {
! 336: buf = (char *)(sort_table[j]) - 1;
! 337: if (*buf) /* check: deallocation flag or \0 ? */
! 338: free(buf);
! 339: }
! 340: #endif
! 341: avma = av; return count;
! 342: }
! 343:
! 344: /**
! 345: ** appends contents of file fp1 to file fp of name filename
! 346: ** (auxiliary routine for merge sort) and returns number of
! 347: ** lines copied.
! 348: ** fp assumed open for appending and fp1 for reading; fp will
! 349: ** be closed afterwards.
! 350: **/
! 351:
! 352: static long
! 353: mpqs_append_file(pariFILE *f, FILE *fp1)
! 354: {
! 355: FILE *fp = f->file;
! 356: char line[MPQS_STRING_LENGTH];
! 357: long c = 0;
! 358: while (fgets(line, MPQS_STRING_LENGTH, fp1) != NULL)
! 359: {
! 360: if (fputs(line, fp) < 0)
! 361: err(talker, "error whilst appending to file %s", f->name);
! 362: c++;
! 363: }
! 364: if (fflush(fp))
! 365: err(warner, "error whilst flushing file %s", f->name);
! 366: pari_fclose(f);
! 367: return c;
! 368: }
! 369:
! 370: /**
! 371: ** Does a merge-sort on the files LPREL and LPNEW;
! 372: ** assumes that LPREL and LPNEW are already sorted.
! 373: ** Creates/truncates the TMP file, writes result to it and closes it
! 374: ** (via a call to mpqs_append_file()).
! 375: ** Instead of LPREL, LPNEW we may also call this with FREL, FNEW.
! 376: ** In the latter case mode should be 1 (and we return the count of
! 377: ** all full relations), in the former 0 (and we return the count
! 378: ** of frels we expect to be able to combine out of the present lprels).
! 379: ** Moreover, if mode is 0, the combinable lprels are written out to a
! 380: ** separate file (COMB) which we also create and close (the caller
! 381: ** will find it exists iff our return value is nonzero), and we keep
! 382: ** only one occurrence of each `large prime' in TMP (i.e. in the future
! 383: ** LPREL file). --GN
! 384: **/
! 385:
! 386: #define swap_lines { \
! 387: line_tmp = line_new_old; \
! 388: line_new_old = line_new; \
! 389: line_new = line_tmp; \
! 390: }
! 391:
! 392: static long
! 393: mpqs_mergesort_lp_file0(FILE *LPREL, FILE *LPNEW, long mode)
! 394: {
! 395: pariFILE *pTMP = pari_fopen(TMP_str, WRITE);
! 396: FILE *TMP = pTMP->file;
! 397: pariFILE *pCOMB = NULL;
! 398: FILE *COMB;
! 399: char line1[MPQS_STRING_LENGTH], line2[MPQS_STRING_LENGTH];
! 400: char line[MPQS_STRING_LENGTH];
! 401: char *line_new = line1, *line_new_old = line2, *line_tmp;
! 402: long q_new, q_new_old = -1, q, i = 0, c = 0;
! 403: long comb_in_progress;
! 404:
! 405: /* if LPNEW is empty, copy LPREL to TMP. Could be done by a rename
! 406: if we didn't want to count the lines (again)... however, this
! 407: case will not normally happen */
! 408:
! 409: if (fgets(line_new, MPQS_STRING_LENGTH, LPNEW) == NULL)
! 410: {
! 411: i = mpqs_append_file(pTMP, LPREL);
! 412: return (mode ? i : 0);
! 413: }
! 414: /* we now have a line_new from LPNEW */
! 415:
! 416: /* if LPREL is empty, copy LPNEW to TMP... almost. */
! 417:
! 418: if (fgets(line, MPQS_STRING_LENGTH, LPREL) == NULL)
! 419: {
! 420: if (fputs(line_new, TMP) < 0)
! 421: bummer(TMP_str);
! 422: if (mode) /* full relations mode */
! 423: {
! 424: i = mpqs_append_file(pTMP, LPNEW);
! 425: return i + 1; /* COMB cannot be open here */
! 426: }
! 427:
! 428: /* LP mode: check for combinable relations */
! 429: q_new_old = atol(line_new);
! 430: /* we need to retain a copy of the old line just for a moment, because
! 431: we may yet have to write it to COMB, too. Do this simply by swapping
! 432: the two buffers */
! 433: swap_lines;
! 434: comb_in_progress = 0;
! 435: i = 0;
! 436:
! 437: while (fgets(line_new, MPQS_STRING_LENGTH, LPNEW) != NULL)
! 438: {
! 439: q_new = atol(line_new);
! 440: if (q_new_old == q_new)
! 441: {
! 442: /* found combinables, check whether we're already busy on this
! 443: particular `large prime' */
! 444: if (!comb_in_progress)
! 445: {
! 446: /* if not, write first line to COMB, creating and opening the
! 447: file first if it isn't open yet */
! 448: if (!pCOMB)
! 449: {
! 450: pCOMB = pari_fopen(COMB_str, WRITE);
! 451: COMB = pCOMB->file;
! 452: }
! 453: if (fputs(line_new_old, COMB) < 0)
! 454: bummer(COMB_str);
! 455: comb_in_progress = 1;
! 456: }
! 457: /* in any case, write the current line, and count it */
! 458: if (fputs(line_new, COMB) < 0)
! 459: bummer(COMB_str);
! 460: i++;
! 461: }
! 462: else
! 463: { /* not combinable */
! 464: q_new_old = q_new;
! 465: comb_in_progress = 0;
! 466: /* and dump it to the TMP file */
! 467: if (fputs(line_new, TMP) < 0)
! 468: bummer(TMP_str);
! 469: /* and stash it away for a moment */
! 470: swap_lines;
! 471: comb_in_progress = 0;
! 472: }
! 473: } /* while */
! 474: if (pCOMB) pari_fclose(pCOMB);
! 475: pari_fclose(pTMP);
! 476: return i;
! 477: }
! 478:
! 479: /* normal case: both LPNEW and LPREL are not empty */
! 480: q_new = atol(line_new);
! 481: q = atol(line);
! 482:
! 483: for(;;) /* main merging loop */
! 484: {
! 485: comb_in_progress = 0;
! 486: i = 0;
! 487:
! 488: /* first the harder case: let LPNEW catch up with LPREL, and possibly
! 489: overtake it, checking for combinables coming from LPNEW alone */
! 490:
! 491: while (q > q_new)
! 492: {
! 493: if (mode || !comb_in_progress)
! 494: {
! 495: if (fputs(line_new, TMP) < 0)
! 496: bummer(TMP_str);
! 497: }
! 498: if (mode)
! 499: c++; /* in FREL mode, count lines written */
! 500: else if (!comb_in_progress)
! 501: {
! 502: q_new_old = q_new;
! 503: swap_lines;
! 504: }
! 505: if (fgets(line_new, MPQS_STRING_LENGTH, LPNEW) == NULL)
! 506: {
! 507: if (fputs(line, TMP) < 0)
! 508: bummer(TMP_str);
! 509: if (mode) c++; else c += i;
! 510: i = mpqs_append_file(pTMP, LPREL);
! 511: if (pCOMB) pari_fclose(pCOMB);
! 512: return (mode ? c + i : c);
! 513: }
! 514: q_new = atol(line_new);
! 515: if (mode) continue;
! 516: /* LP mode only: */
! 517: if (q_new_old != q_new)
! 518: { /* not combinable */
! 519: comb_in_progress = 0;
! 520: /* next loop iteration will deal with it, or the loop may end */
! 521: }
! 522: else
! 523: {
! 524: /* found combinables, check whether we're already busy on this
! 525: `large prime' */
! 526: if (!comb_in_progress)
! 527: {
! 528: if (!pCOMB)
! 529: {
! 530: pCOMB = pari_fopen(COMB_str, WRITE);
! 531: COMB = pCOMB->file;
! 532: }
! 533: if (fputs(line_new_old, COMB) < 0)
! 534: bummer(COMB_str);
! 535: comb_in_progress = 1;
! 536: }
! 537: /* in any case, write the current line, and count it */
! 538: if (fputs(line_new, COMB) < 0)
! 539: bummer(COMB_str);
! 540: i++;
! 541: }
! 542: } /* while q > q_new */
! 543:
! 544: /* q <= q_new */
! 545:
! 546: if (!mode) c += i; /* accumulate count of combinables */
! 547: i = 0; /* and clear it */
! 548: comb_in_progress = 0; /* redundant */
! 549:
! 550: /* now let LPREL catch up with LPNEW, and possibly overtake it */
! 551:
! 552: while (q < q_new)
! 553: {
! 554: if (fputs(line, TMP) < 0)
! 555: bummer(TMP_str);
! 556: if (mode) c++;
! 557: if (fgets(line, MPQS_STRING_LENGTH, LPREL) == NULL)
! 558: {
! 559: if (fputs(line_new, TMP) < 0)
! 560: bummer(TMP_str);
! 561: i = mpqs_append_file(pTMP, LPNEW);
! 562: if (pCOMB) pari_fclose(pCOMB);
! 563: return (mode ? c + i + 1 : c);
! 564: }
! 565: else
! 566: q = atol(line);
! 567: }
! 568:
! 569: /* q >= q_new */
! 570:
! 571: /* Finally, it may happen that q == q_new, indicating combinables whose
! 572: `large prime' is already represented in LPREL, and appears now once
! 573: or more often in LPNEW. Thus in this sub-loop we advance LPNEW.
! 574: The `line' from LPREL is left alone, and will be written to TMP the
! 575: next time around the main for loop; we only write it to COMB here --
! 576: unless all we find is an exact duplicate of the line we already have,
! 577: that is. (There can be at most one such, and if so it will simply be
! 578: discarded, whether we are in LP or full relations mode.) */
! 579:
! 580: while (q == q_new)
! 581: {
! 582: if (strcmp(line_new, line) == 0)
! 583: {
! 584: /* duplicate -- move right ahead to the next LPNEW line */
! 585: ; /* do nothing here */
! 586: } /* end duplicate case */
! 587: else if (mode)
! 588: {
! 589: /* full relations mode: write line_new out first, keep line */
! 590: if (fputs(line_new, TMP) < 0)
! 591: bummer(TMP_str);
! 592: c++;
! 593: } /* end full relations case */
! 594: else
! 595: {
! 596: /* LP mode, and combinable relation */
! 597: if (!comb_in_progress)
! 598: {
! 599: if (!pCOMB)
! 600: {
! 601: pCOMB = pari_fopen(COMB_str, WRITE);
! 602: COMB = pCOMB->file;
! 603: }
! 604: if (fputs(line, COMB) < 0)
! 605: bummer(COMB_str);
! 606: comb_in_progress = 1;
! 607: }
! 608: if (fputs(line_new, COMB) < 0)
! 609: bummer(COMB_str);
! 610: i++;
! 611: } /* end combinable LP case */
! 612: /* NB comb_in_progress is cleared by q_new becoming bigger than q,
! 613: and thus the current while loop terminating, the next time through
! 614: the main for loop */
! 615:
! 616: /* common ending: get another line_new, if any */
! 617: if (fgets(line_new, MPQS_STRING_LENGTH, LPNEW) == NULL)
! 618: {
! 619: if (fputs(line, TMP) < 0)
! 620: bummer(TMP_str);
! 621: if (mode) c++; else c += i;
! 622: i = mpqs_append_file(pTMP, LPREL);
! 623: if (pCOMB) pari_fclose(pCOMB);
! 624: return (mode ? c + i : c);
! 625: }
! 626: else
! 627: q_new = atol(line_new);
! 628: } /* while */
! 629:
! 630: if (!mode) c += i; /* accumulate count of combinables */
! 631: } /* for */
! 632: }
! 633:
! 634: static long
! 635: mpqs_mergesort_lp_file(char *REL_str, char *NEW_str, long mode)
! 636: {
! 637: pariFILE *pREL = pari_fopen(REL_str, READ);
! 638: pariFILE *pNEW = pari_fopen(NEW_str, READ);
! 639: long tp = mpqs_mergesort_lp_file0(pREL->file, pNEW->file, mode);
! 640:
! 641: pari_fclose(pREL);
! 642: pari_fclose(pNEW);
! 643: pari_unlink(REL_str);
! 644: if (rename(TMP_str,REL_str))
! 645: err(talker, "can\'t rename file %s to %s", TMP_str, REL_str);
! 646: if (
! 647: #ifdef MPQS_DEBUG
! 648: 1 ||
! 649: #endif
! 650: DEBUGLEVEL >= 6)
! 651: fprintferr("MPQS: renamed file %s to %s\n", TMP_str, REL_str);
! 652: return tp;
! 653: }
! 654:
! 655: /******************************/
! 656: /**
! 657: ** return next prime larger than p, using *primes_ptr on the
! 658: ** diffptr table first and pari's other wits after that
! 659: **/
! 660:
! 661: static byteptr
! 662: mpqs_iterate_primes(long *p, byteptr primes_ptr)
! 663: {
! 664: long prime = *p;
! 665: if (*primes_ptr)
! 666: prime += *primes_ptr++;
! 667: else
! 668: {
! 669: long av = avma;
! 670: prime = itos(nextprime(stoi(prime + 1)));
! 671: avma = av;
! 672: }
! 673: *p = prime;
! 674: return primes_ptr;
! 675: }
! 676:
! 677:
! 678: /**
! 679: ** return the multiplier k for N to use in MPQS
! 680: **/
! 681:
! 682: long
! 683: mpqs_find_k(GEN N, long tries)
! 684: {
! 685: static long cand_table[] = { 1,3,5,7,11,13,15,17,19,21,23,
! 686: 29,31,33,35,37,39,41,43,47,51,53,
! 687: 55,57,59,61,65,67,69,71,73,79,83,
! 688: 85,89,91,93,95,97,101,103,105,107,
! 689: 109,113,127,131,137,139};
! 690: long av = avma;
! 691: long best_k = 1, k, p, N_mod_4 = smodis(N, 4), x;
! 692: GEN kN;
! 693: double best_value = 1, value, dp;
! 694: long i, j;
! 695: byteptr primes_ptr;
! 696:
! 697: for (i = 0; i < MPQS_PRIMES_FOR_MULTIPLIER; i++)
! 698: {
! 699: k = cand_table[i];
! 700: x = (k * N_mod_4) % 4;
! 701: if (x == 1)
! 702: {
! 703: value = -0.7 * log2 ((double) k);
! 704: kN = mulis(N, k);
! 705: if (smodis(kN, 8) == 1)
! 706: value += 1.38629;
! 707:
! 708: j = 0; p = 0;
! 709: primes_ptr = diffptr;
! 710: while (j <= tries)
! 711: {
! 712: primes_ptr = mpqs_iterate_primes(&p, primes_ptr);
! 713: if (kross(smodis(kN, p), p) == 1)
! 714: {
! 715: j++;
! 716: dp = log2((double) p) / p;
! 717: value += (k % p == 0) ? dp : 2 * dp;
! 718: }
! 719: }
! 720:
! 721: if (value > best_value)
! 722: {
! 723: best_value = value;
! 724: best_k = k;
! 725: }
! 726: }
! 727: }
! 728: avma = av; return best_k;
! 729: }
! 730:
! 731: /******************************/
! 732: /**
! 733: ** guesstimate up to what size we're going to need precomputed
! 734: ** small primes
! 735: **/
! 736:
! 737: static long
! 738: mpqs_find_maxprime(long size)
! 739: {
! 740: double x;
! 741:
! 742: if (size < 16000)
! 743: return 176000;
! 744:
! 745: x = log((double)size);
! 746: x += log(x);
! 747: x -= 0.9427;
! 748: x *= size;
! 749:
! 750: return (long)x;
! 751: }
! 752:
! 753: /**
! 754: ** return the number of primes initialized in PARI
! 755: **/
! 756:
! 757: static long
! 758: mpqs_count_primes()
! 759: {
! 760: byteptr p = mpqs_diffptr;
! 761:
! 762: for ( ; *p; p++) /* empty */;
! 763: return (p - mpqs_diffptr);
! 764: }
! 765:
! 766: /**
! 767: ** create a factor base of size primes p_i with the
! 768: ** property that legendre(k*N, p_i) == 0, 1
! 769: ** FB[0] contains the size of the factor base; FB[FB[0]+1] is the
! 770: ** last prime p_i.
! 771: ** FB[1] contains -1 which allows to handle negative values of Q(x).
! 772: ** If a prime factor of N is found during the construction, it
! 773: ** is returned in f, otherwise f = 0 (such a factor will necessarily
! 774: ** fit into a C long).
! 775: **/
! 776:
! 777: static long*
! 778: mpqs_create_FB(long size, GEN kN, long k, long *f)
! 779: {
! 780: long i, kr, p = 0;
! 781: long *FB;
! 782: byteptr primes_ptr;
! 783:
! 784: FB = (long *) calloc(size + 3, sizeof(long));
! 785: if (!FB) err(memer);
! 786: FB[0] = size;
! 787: FB[1] = -1;
! 788: /* pick up PARI's current differences-of-small-primes array */
! 789: /* unless we already have our own. We must then reset it to NULL */
! 790: /* so we will not use a stale one the next time we are called */
! 791: if (!mpqs_diffptr) mpqs_diffptr = diffptr;
! 792:
! 793: if ((mpqs_prime_count ? mpqs_prime_count : mpqs_count_primes())
! 794: < 3 * size)
! 795: {
! 796: long newsize = 3 * mpqs_find_maxprime(size);
! 797: if (mpqs_diffptr != diffptr) free((void *) mpqs_diffptr);
! 798: if (DEBUGLEVEL >= 2)
! 799: {
! 800: fprintferr("MPQS: precomputing auxiliary primes up to %ld\n",
! 801: newsize);
! 802: }
! 803: mpqs_diffptr = initprimes(newsize);
! 804: /* count 'em once and remember the result */
! 805: mpqs_prime_count = mpqs_count_primes();
! 806: }
! 807:
! 808: if (
! 809: #ifdef MPQS_DEBUG
! 810: 1 ||
! 811: #endif
! 812: DEBUGLEVEL >= 7)
! 813: fprintferr("MPQS: FB [-1");
! 814: primes_ptr = mpqs_diffptr;
! 815: for (i = 2; i < size + 2; )
! 816: {
! 817: primes_ptr = mpqs_iterate_primes(&p, primes_ptr);
! 818:
! 819: /* testing p!=k was only correct because MPQS_PRIMES_FOR_MULTIPLIER
! 820: is so small that the composite values k > 1 will never be chosen.
! 821: Fixing this just in case someone increases that parameter one day...
! 822: --GN */
! 823: if (p > k || k%p)
! 824: {
! 825: kr = kross(smodis(kN, p), p);
! 826: if (kr != -1)
! 827: {
! 828: if (kr == 0)
! 829: {
! 830: if (
! 831: #ifdef MPQS_DEBUG
! 832: 1 ||
! 833: #endif
! 834: DEBUGLEVEL >= 7)
! 835: fprintferr(",%ld...] Wait a second --\n", p);
! 836: *f = p;
! 837: return FB;
! 838: }
! 839: if (
! 840: #ifdef MPQS_DEBUG
! 841: 1 ||
! 842: #endif
! 843: DEBUGLEVEL >= 7)
! 844: fprintferr(",%ld", p);
! 845: FB[i] = p, i++;
! 846: }
! 847: }
! 848: }
! 849:
! 850: if (
! 851: #ifdef MPQS_DEBUG
! 852: 1 ||
! 853: #endif
! 854: DEBUGLEVEL >= 7)
! 855: {
! 856: fprintferr("]\n");
! 857: flusherr();
! 858: }
! 859:
! 860: FB[i] = 0;
! 861: if (DEBUGLEVEL >= 6)
! 862: fprintferr("MPQS: last available index in FB is %ld\n", i - 1);
! 863:
! 864: *f = 0;
! 865: return FB;
! 866: }
! 867:
! 868: /******************************/
! 869:
! 870: /**
! 871: ** see below for the format of the parameter table.
! 872: ** These values are somewhat experimental and can be improved by
! 873: ** further extensive testing.
! 874: ** Tentative entries for 9...14 digits by GN, entry for 15 changed
! 875: ** Tentative entries for 81...100 digits by GN, entry for 74 changed
! 876: ** total_no_of_primes_for_A (penultimate entries in each row) increased
! 877: ** throughout, partly so as to offset the effect of changed bin_index
! 878: ** increment strategy --GN
! 879: ** Added entries to govern sort intervals, commented out unused numbers
! 880: ** of digits --GN
! 881: **/
! 882:
! 883: static double
! 884: mpqs_parameters[99][8] =
! 885: {
! 886: { /*9*/ 0.8, 900, 20, 3, 13, 2, 70, 8},
! 887: { /*10*/ 0.8, 900, 21, 3, 12, 2, 70, 8},
! 888: { /*11*/ 0.8, 920, 22, 3, 12, 2, 70, 6},
! 889: { /*12*/ 0.8, 960, 24, 3, 12, 2, 70, 6},
! 890: { /*13*/ 0.8, 1020, 26, 3, 12, 2, 70, 6},
! 891: { /*14*/ 0.8, 1100, 29, 3, 12, 2, 70, 6},
! 892: { /*15*/ 0.8, 1200, 32, 3, 12, 2, 60, 8},
! 893: { /*16*/ 0.8, 1400, 35, 3, 12, 2, 60, 8},
! 894: { /*17*/ 0.8, 3000, 40, 3, 12, 2, 60, 8},
! 895: { /*18*/ 0.8, 3000, 60, 3, 12, 2, 50, 10},
! 896: { /*19*/ 0.8, 3600, 80, 3, 13, 2, 50, 10},
! 897: { /*20*/ 0.8, 4000, 100, 3, 13, 2, 40, 10},
! 898: { /*21*/ 0.8, 4300, 100, 3, 13, 2, 40, 10},
! 899: { /*22*/ 0.8, 4500, 120, 3, 13, 3, 40, 10},
! 900: { /*23*/ 0.8, 4800, 140, 3, 14, 3, 30, 10},
! 901: { /*24*/ 0.8, 5000, 160, 3, 14, 4, 30, 10},
! 902: { /*25*/ 0.8, 5000, 180, 3, 14, 4, 30, 10},
! 903: { /*26*/ 0.9, 6000, 200, 5, 10, 4, 30, 10},
! 904: { /*27*/ 1.17, 6000, 220, 5, 10, 5, 30, 10},
! 905: { /*28*/ 1.17, 6500, 240, 5, 10, 5, 30, 10},
! 906: { /*29*/ 1.17, 6500, 260, 5, 10, 5, 30, 10},
! 907: { /*30*/ 1.36, 7000, 325, 5, 10, 5, 20, 10},
! 908: { /*31*/ 1.36, 7000, 355, 5, 10, 5, 20, 10},
! 909: { /*32*/ 1.36, 7500, 375, 5, 10, 5, 20, 10},
! 910: { /*33*/ 1.43, 7500, 400, 6, 11, 6, 20, 10},
! 911: { /*34*/ 1.43, 7500, 425, 6, 11, 6, 20, 10},
! 912: { /*35*/ 1.43, 7500, 550, 6, 11, 6, 20, 10},
! 913: { /*36*/ 1.43, 8000, 650, 6, 11, 6, 20, 10},
! 914: { /*37*/ 1.69, 9000, 750, 6, 11, 7, 20, 10},
! 915: { /*38*/ 1.69, 10000, 850, 6, 11, 7, 20, 10},
! 916: { /*39*/ 1.69, 11000, 950, 6, 11, 7, 20, 10},
! 917: { /*40*/ 1.69, 14000, 1000, 6, 11, 7, 20, 10},
! 918: { /*41*/ 1.69, 14000, 1150, 6, 11, 8, 10, 10},
! 919: { /*42*/ 1.69, 15000, 1300, 6, 11, 8, 10, 10},
! 920: { /*43*/ 1.69, 15000, 1600, 6, 11, 8, 10, 10},
! 921: { /*44*/ 1.69, 15000, 1900, 7, 12, 9, 10, 10},
! 922: { /*45*/ 1.69, 15000, 2200, 7, 12, 9, 10, 10},
! 923: { /*46*/ 1.69, 20000, 2500, 7, 12, 9, 10, 10},
! 924: { /*47*/ 1.69, 25000, 2500, 7, 12, 10, 10, 10},
! 925: { /*48*/ 1.69, 27500, 2700, 7, 12, 10, 10, 10},
! 926: { /*49*/ 1.69, 30000, 2800, 7, 12, 10, 10, 10},
! 927: { /*50*/ 1.75, 35000, 2900, 7, 12, 10, 10, 10},
! 928: { /*51*/ 1.75, 40000, 3000, 7, 12, 10, 10, 10},
! 929: { /*52*/ 1.85, 50000, 3200, 7, 12, 11, 10, 10},
! 930: { /*53*/ 1.85, 50000, 3500, 7, 12, 11, 10, 10},
! 931: { /*54*/ 1.95, 80000, 3800, 7, 13, 11, 10, 10},
! 932: { /*55*/ 1.95, 90000, 4100, 7, 13, 11, 10, 10},
! 933: { /*56*/ 1.95, 100000, 4400, 7, 13, 11, 10, 10},
! 934: { /*57*/ 1.95, 80000, 4700, 8, 14, 12, 10, 10},
! 935: { /*58*/ 1.95, 80000, 5000, 8, 14, 12, 10, 10},
! 936: { /*59*/ 2.15, 130000, 5500, 8, 14, 12, 10, 8},
! 937: { /*60*/ 2.15, 140000, 5800, 8, 14, 12, 10, 8},
! 938: { /*61*/ 2.15, 150000, 6100, 8, 14, 13, 10, 8},
! 939: { /*62*/ 2.15, 160000, 6400, 8, 14, 13, 10, 8},
! 940: { /*63*/ 2.35, 170000, 6700, 8, 14, 13, 10, 8},
! 941: { /*64*/ 2.35, 180000, 7000, 8, 14, 13, 10, 8},
! 942: { /*65*/ 2.35, 190000, 7300, 8, 14, 13, 10, 8},
! 943: { /*66*/ 2.35, 200000, 7600, 8, 14, 13, 10, 8},
! 944: { /*67*/ 2.4, 150000, 7900, 8, 14, 13, 10, 8},
! 945: { /*68*/ 2.4, 150000, 8200, 8, 15, 13, 10, 8},
! 946: { /*69*/ 2.4, 130000, 8600, 8, 15, 13, 8, 6},
! 947: { /*70*/ 2.45, 130000, 8800, 8, 15, 13, 8, 6},
! 948: { /*71*/ 2.45, 130000, 8800, 9, 16, 13, 8, 6},
! 949: { /*72*/ 2.4, 260000, 9400, 9, 16, 13, 5, 5},
! 950: { /*73*/ 2.4, 270000, 9700, 9, 16, 13, 5, 5},
! 951: { /*74*/ 2.4, 280000, 9800, 9, 16, 13, 5, 5},
! 952: { /*75*/ 2.6, 140000, 9000, 9, 17, 13, 5, 5},
! 953: { /*76*/ 2.6, 160000, 9400, 9, 17, 13, 5, 5},
! 954: { /*77*/ 2.6, 180000, 9600, 9, 17, 13, 5, 5},
! 955: { /*78*/ 2.6, 200000, 9800, 9, 17, 13, 5, 5},
! 956: { /*79*/ 2.65, 220000, 10000, 9, 18, 13, 5, 5},
! 957: { /*80*/ 2.65, 250000, 10500, 9, 18, 13, 5, 5},
! 958: /* entries below due to Thomas Denny */
! 959: { /*81*/ 3.1, 1500000, 16000, 9, 18, 15, 4, 4},
! 960: { /*82*/ 3.1, 1500000, 17000, 9, 18, 15, 4, 4},
! 961: { /*83*/ 3.1, 1500000, 18500, 9, 19, 16, 4, 4},
! 962: { /*84*/ 3.2, 1500000, 20000, 9, 19, 16, 4, 4},
! 963: { /*85*/ 3.2, 1500000, 21500, 9, 19, 16, 4, 4},
! 964: { /*86*/ 3.2, 1500000, 23000, 9, 19, 16, 4, 4},
! 965: { /*87*/ 3.2, 1500000, 25000, 9, 20, 17, 4, 4},
! 966: { /*88*/ 3.3, 1500000, 27000, 9, 20, 17, 4, 4},
! 967: { /*89*/ 3.3, 1500000, 28000, 9, 20, 17, 4, 4},
! 968: { /*90*/ 3.5, 2000000, 30500, 9, 20, 17, 2, 2},
! 969: { /*91*/ 3.6, 2000000, 32000, 9, 21, 18, 2, 2},
! 970: { /*92*/ 3.6, 2000000, 35000, 9, 21, 18, 2, 2},
! 971: { /*93*/ 3.7, 2000000, 37000, 9, 21, 18, 2, 2},
! 972: { /*94*/ 3.7, 2000000, 39500, 9, 22, 18, 2, 2},
! 973: { /*95*/ 3.7, 2500000, 41500, 9, 22, 18, 2, 2},
! 974: { /*96*/ 3.8, 2500000, 45000, 10, 23, 18, 2, 2},
! 975: { /*97*/ 3.8, 2500000, 47500, 10, 23, 18, 2, 2},
! 976: { /*98*/ 3.7, 3000000, 51000, 10, 24, 18, 2, 2},
! 977: { /*99*/ 3.8, 3000000, 53000, 10, 24, 18, 2, 2},
! 978: {/*100*/ 3.8, 3500000, 51000, 10, 25, 18, 2, 2},
! 979: {/*101*/ 3.8, 3500000, 54000, 10, 25, 18, 2, 2},
! 980: {/*102*/ 3.8, 3500000, 57000, 10, 26, 18, 2, 2},
! 981: {/*103*/ 3.9, 4000000, 61000, 10, 26, 18, 2, 2},
! 982: {/*104*/ 3.9, 4000000, 66000, 10, 27, 18, 2, 2},
! 983: {/*105*/ 3.9, 4000000, 70000, 10, 27, 18, 2, 2},
! 984: {/*106*/ 3.9, 4000000, 75000, 10, 28, 18, 2, 2},
! 985: {/*107*/ 3.9, 4000000, 80000, 10, 30, 18, 2, 2},
! 986: };
! 987:
! 988: /**
! 989: ** Return the appropriate parameters for the initialization of MPQS
! 990: **
! 991: ** the parameter table for mpqs has the following format:
! 992: **
! 993: ** [d -- decimal digits -- commented out]
! 994: ** e -- approximation accuracy
! 995: ** M -- size sieving interval
! 996: ** s -- size FB,
! 997: ** fA -- # prime factors in A
! 998: ** pA -- total # primes for determination of A,
! 999: ** [maxB -- how many Bs to use before choosing a new A -- determined by fA]
! 1000: ** si -- initial sieving index
! 1001: ** isoi -- initial sorting interval
! 1002: ** fsoi -- followup sorting interval increment
! 1003: **/
! 1004:
! 1005: static void
! 1006: mpqs_read_parameters(ulong d, double *e, ulong *M, ulong *s, ulong *os,
! 1007: ulong *fA, ulong *pA, long *maxB, ulong *si,
! 1008: ulong *isoi, ulong *fsoi)
! 1009: {
! 1010: long i = d;
! 1011: if (i < 9) i = 9;
! 1012: if (i > 107) i = 107;
! 1013: i -= 9;
! 1014:
! 1015: *e = mpqs_parameters[i][0];
! 1016: *M = (ulong)mpqs_parameters[i][1];
! 1017: *s = (ulong)mpqs_parameters[i][2];
! 1018: if (*s >= 200) *os = *s + 70;
! 1019: else *os = (ulong)(*s * 1.35);
! 1020: *fA = (ulong)mpqs_parameters[i][3];
! 1021: *pA = (ulong)mpqs_parameters[i][4];
! 1022: #if 0
! 1023: *maxB = (long) pow(2.0, mpqs_parameters[i][3] - 1.0);
! 1024: #else
! 1025: *maxB = 1l << (*fA - 1);
! 1026: #endif
! 1027: *si = (ulong)mpqs_parameters[i][5];
! 1028: *isoi = 10 * (ulong)mpqs_parameters[i][6]; /* percentages scaled by 10 */
! 1029: *fsoi = 10 * (ulong)mpqs_parameters[i][7];
! 1030: }
! 1031:
! 1032: /******************************/
! 1033:
! 1034: /**
! 1035: ** increment *x (!=0) to a larger value which has the same number of 1s
! 1036: ** in its binary representation. Cases which wrap around can be detected
! 1037: ** by the caller afterwards as long as we keep total_no_of_primes_for_A
! 1038: ** strictly less than BITS_IN_LONG.
! 1039: **
! 1040: ** Switch for the fast cases moved into here --GN
! 1041: **
! 1042: ** Changed switch to increment *x in all cases to the next larger number
! 1043: ** which (a) has the same count of 1 bits and (b) does not arise from the
! 1044: ** old value by moving a single 1 bit one position to the left (which was
! 1045: ** undesirable for the sieve). --GN based on discussion with TP
! 1046: **/
! 1047: static void
! 1048: mpqs_increment(ulong *x)
! 1049: {
! 1050: ulong r1_mask, r01_mask, slider=1;
! 1051:
! 1052: /* ultra-fast 32-way computed jump handles 22 out of 32 cases */
! 1053: switch (*x & 0x1f)
! 1054: {
! 1055: case 29:
! 1056: (*x)++; break; /* this does shift a single bit, but we'll
! 1057: postprocess this case */
! 1058: case 26:
! 1059: (*x) += 2; break; /* again */
! 1060: case 1: case 3: case 6: case 9: case 11:
! 1061: case 17: case 19: case 22: case 25: case 27:
! 1062: (*x) += 3; return;
! 1063: case 20:
! 1064: (*x) += 4; break; /* again */
! 1065: case 5: case 12: case 14: case 21:
! 1066: (*x) += 5; return;
! 1067: case 2: case 7: case 13: case 18: case 23:
! 1068: (*x) += 6; return;
! 1069: case 10:
! 1070: (*x) += 7; return;
! 1071: case 8:
! 1072: (*x) += 8; break; /* and again */
! 1073: case 4: case 15:
! 1074: (*x) += 12; return;
! 1075: default: /* 0, 16, 24, 28, 30, 31 */
! 1076: /* isolate rightmost 1 */
! 1077: r1_mask = ((*x ^ (*x - 1)) + 1) >> 1;
! 1078: /* isolate rightmost 1 which has a 0 to its left */
! 1079: r01_mask = ((*x ^ (*x + r1_mask)) + r1_mask) >> 2;
! 1080: /* simple cases. Both of these shift a single bit one position to the
! 1081: left, and will need postprocessing */
! 1082: if (r1_mask == r01_mask) { *x += r1_mask; break; }
! 1083: if (r1_mask == 1) { *x += r01_mask; break; }
! 1084: /* general case -- idea:
! 1085: add r01_mask, kill off as many 1 bits as possible to its right
! 1086: while at the same time filling in 1 bits from the LSB. */
! 1087: if (r1_mask == 2) { *x += (r01_mask>>1) + 1; return; }
! 1088: while (r01_mask > r1_mask && slider < r1_mask)
! 1089: {
! 1090: r01_mask >>= 1; slider <<= 1;
! 1091: }
! 1092: *x += r01_mask + slider - 1;
! 1093: return;
! 1094: }
! 1095: /* post-process all cases which couldn't be finalized above. If we get
! 1096: here, slider still has its original value. */
! 1097: r1_mask = ((*x ^ (*x - 1)) + 1) >> 1;
! 1098: r01_mask = ((*x ^ (*x + r1_mask)) + r1_mask) >> 2;
! 1099: if (r1_mask == r01_mask) { *x += r1_mask; return; }
! 1100: if (r1_mask == 1) { *x += r01_mask; return; }
! 1101: if (r1_mask == 2) { *x += (r01_mask>>1) + 1; return; }
! 1102: while (r01_mask > r1_mask && slider < r1_mask)
! 1103: {
! 1104: r01_mask >>= 1; slider <<= 1;
! 1105: }
! 1106: *x += r01_mask + slider - 1;
! 1107: return;
! 1108: }
! 1109:
! 1110: static long
! 1111: mpqs_invsmod(long b, long p)
! 1112: {
! 1113: long v1 = 0, v2 = 1, v3, r, oldp = p;
! 1114:
! 1115: while (b > 1)
! 1116: {
! 1117: v3 = v1 - (p / b) * v2; v1 = v2; v2 = v3;
! 1118: r = p % b; p = b; b = r;
! 1119: }
! 1120:
! 1121: if (v2 < 0) v2 += oldp;
! 1122: return v2;
! 1123: }
! 1124:
! 1125: /**
! 1126: ** compute coefficients of the sieving polynomial for self initializing
! 1127: ** variant. Coefficients A and B are returned and several tables are
! 1128: ** updated. See Thomas Sosnowski's diploma thesis.
! 1129: **/
! 1130:
! 1131: static void
! 1132: mpqs_self_init(GEN A, GEN B, GEN N, GEN kN, long *FB, long *sqrt_mod_p_kN,
! 1133: long *start_1, long *start_2, ulong no_of_primes_in_A,
! 1134: ulong total_no_of_primes_for_A, ulong M, long **inv_A_H_i,
! 1135: long *Q_prime, long *Q_prime_glob, GEN* H_i, long index_i,
! 1136: long start_index_FB_for_A, long *inv_A2, GEN inv_A4,
! 1137: ulong *bin_index, GEN *f)
! 1138: {
! 1139: long av;
! 1140: GEN p1, p2;
! 1141: ulong size_of_FB, nu_2;
! 1142: long i, j, p, M_mod_p, tmp, tmp1, tmp2;
! 1143:
! 1144: *f = NULL;
! 1145: if (index_i == 0)
! 1146: {
! 1147: /* compute first polynomial with new A */
! 1148: if (!*bin_index)
! 1149: {
! 1150: *bin_index = (1ul << no_of_primes_in_A) - 1;
! 1151: }
! 1152: else
! 1153: mpqs_increment(bin_index);
! 1154: if (*bin_index >= (1ul << total_no_of_primes_for_A)) /* wraparound */
! 1155: {
! 1156: if (DEBUGLEVEL >= 2)
! 1157: fprintf(stderr, "MPQS: bin_index wraparound\n");
! 1158: /* complain: caller should increase some parameters... */
! 1159: return;
! 1160: /* caller should repeat the above test; if we simply increase the
! 1161: total_no_of_primes_for_A, then bin_index now contains something
! 1162: suitable for carrying on -- we'll probably end up not using
! 1163: that particular index and skipping ahead to the next one, but
! 1164: this isn't a problem. OTOH total_no_of_primes_for_A should now
! 1165: be so large that this should never happen except for ridiculous
! 1166: input, like asking mpqs to factor 27, in which case it will act
! 1167: as a safeguard against an infinite loop --GN */
! 1168: }
! 1169:
! 1170: /* determine primes used for A in this iteration */
! 1171: for (i = 0, j = 0; j < total_no_of_primes_for_A; j++)
! 1172: {
! 1173: if (*bin_index & (1 << j))
! 1174: {
! 1175: Q_prime[i] = Q_prime_glob[j];
! 1176: i++;
! 1177: }
! 1178: }
! 1179:
! 1180: /*
! 1181: * compute coefficient A using
! 1182: * A = prod (Q_prime[i], 0 < i < no_of_primes_in_A)
! 1183: */
! 1184:
! 1185: av = avma;
! 1186: p1 = stoi(Q_prime[0]);
! 1187: for (i = 1; i < no_of_primes_in_A; i++)
! 1188: p1 = mulis(p1, Q_prime[i]);
! 1189: affii(p1, A);
! 1190: avma = av;
! 1191:
! 1192: /*
! 1193: * let bound := no_of_primes_in_A. Compute H_i, 0 <= i < bound.
! 1194: */
! 1195:
! 1196: for (i = 0; i < no_of_primes_in_A; i++)
! 1197: {
! 1198: av = avma;
! 1199: p = Q_prime[i];
! 1200: p1 = divis(A, p);
! 1201: tmp = smodis(p1, p);
! 1202: p1 = mulis(p1, mpqs_invsmod(tmp, p));
! 1203: tmp = itos(mpsqrtmod(modis(kN, p), stoi(p)));
! 1204: p1 = mulis(p1, tmp);
! 1205: affii(modii(p1, A), H_i[i]);
! 1206: avma = av;
! 1207: }
! 1208:
! 1209: /*
! 1210: * Each B is of the form sum(v_i * H_i, 0 <= i < bound)
! 1211: * where each v_j is +1 or -1. This has to be done only once
! 1212: * (for index_i==0) for the coefficient A; if index_i > 0 then
! 1213: * there is a linear recursion for B
! 1214: */
! 1215:
! 1216: /* compute actual B coefficient, by taking all v_i == 1 */
! 1217: av = avma;
! 1218: p1 = H_i[0];
! 1219: for (i = 1; i < no_of_primes_in_A; i++)
! 1220: p1 = addii(p1, H_i[i]);
! 1221: affii(p1, B);
! 1222: avma = av;
! 1223:
! 1224: /* ensure B = 1 mod 4 */
! 1225: if (mod2(B) == 0)
! 1226: {
! 1227: /* B += (A % 4) * A; */
! 1228: av = avma;
! 1229: p1 = addii(B, mulsi(mod4(A), A));
! 1230: affii(p1, B);
! 1231: avma = av;
! 1232: }
! 1233:
! 1234: /* compute inv_A2[i] = 1/(2*A) mod p_i */
! 1235: av = avma;
! 1236: p1 = shifti(A, 1);
! 1237: size_of_FB = FB[0] + 1;
! 1238: for (i = 2; i <= size_of_FB; i++)
! 1239: inv_A2[i] = mpqs_invsmod(smodis(p1, FB[i]), FB[i]);
! 1240: avma = av;
! 1241:
! 1242: /* compute inv_A_H_i[i][j] = 1/A * H_i[i] mod p_j */
! 1243: for (i = 0; i < no_of_primes_in_A; i++)
! 1244: {
! 1245: for (j = 2; j <= size_of_FB; j++)
! 1246: {
! 1247: av = avma;
! 1248: p1 = mulis(H_i[i], inv_A2[j] << 1);
! 1249: inv_A_H_i[i][j] = smodis(p1, FB[j]);
! 1250: avma = av;
! 1251: }
! 1252: }
! 1253:
! 1254: /* compute the roots z1, z2, of the polynomial Q(x) mod p_j and
! 1255: * initialize start_1[i] with the first value p_i | Q(z1 + i p_j)
! 1256: * initialize start_2[i] with the first value p_i | Q(z2 + i p_j)
! 1257: */
! 1258: for (j = 2; j <= size_of_FB; j++)
! 1259: {
! 1260: p = FB[j];
! 1261: M_mod_p = M % p;
! 1262:
! 1263: tmp = p - smodis(B, p); /* tmp = -B mod p */
! 1264:
! 1265: tmp1 = (tmp - sqrt_mod_p_kN[j]) % p;
! 1266: if (tmp1 < 0) tmp1 += p;
! 1267: tmp1 = mulssmod(tmp1, inv_A2[j], p);
! 1268: tmp1 = (tmp1 + M_mod_p) % p;
! 1269:
! 1270: tmp2 = (tmp + sqrt_mod_p_kN[j]) % p;
! 1271: if (tmp2 < 0) tmp2 += p;
! 1272: tmp2 = mulssmod(tmp2, inv_A2[j], p);
! 1273: tmp2 = (tmp2 + M_mod_p) % p;
! 1274:
! 1275: start_1[j] = (tmp1 < 0) ? tmp1 + p : tmp1;
! 1276: start_2[j] = (tmp2 < 0) ? tmp2 + p : tmp2;
! 1277: }
! 1278:
! 1279: /* determine 1/(4A) mod kN */
! 1280: av = avma;
! 1281: if (!invmod(shifti(A,2), kN, &p1)) /* --GN */
! 1282: {
! 1283: /* inv_A4 is a factor > 1 of kN. This cannot actually happen.
! 1284: Catch it anyway, it doesn't cost more than two comparisons
! 1285: against 0 / NULL */
! 1286: p1 = mppgcd(p1, N);
! 1287: *f = gerepileupto(av, p1);
! 1288: return; /* we certainly can't use the current poly */
! 1289: }
! 1290: affii(p1, inv_A4);
! 1291: avma = av;
! 1292: }
! 1293: else
! 1294: {
! 1295: /* no "real" computation -- use recursive formula
! 1296: * first: update of B, compute B[index_i], index_i > 0
! 1297: */
! 1298:
! 1299: /* compute nu_2 = nu_2(index_i) */
! 1300: nu_2 = 0;
! 1301: j = index_i;
! 1302: while ((j & 1) == 0)
! 1303: {
! 1304: nu_2++;
! 1305: j >>= 1;
! 1306: }
! 1307:
! 1308: av = avma;
! 1309: p1 = shifti(H_i[nu_2], 1);
! 1310:
! 1311: if ((((j+1)/2) & 1) == 1)
! 1312: {
! 1313: i = -1;
! 1314: p1 = subii(B, p1);
! 1315: }
! 1316: else
! 1317: {
! 1318: i = 1;
! 1319: p1 = addii(B, p1);
! 1320: }
! 1321: affii(p1, B);
! 1322: avma = av;
! 1323:
! 1324: /* determine new starting positions for sieving */
! 1325: size_of_FB = FB[0] + 1;
! 1326:
! 1327: if (i == -1)
! 1328: {
! 1329: for (j = 2; j <= size_of_FB; j++)
! 1330: {
! 1331: p = FB[j];
! 1332: start_1[j] += inv_A_H_i[nu_2][j];
! 1333: if (start_1[j] >= p)
! 1334: start_1[j] -= p;
! 1335: start_2[j] += inv_A_H_i[nu_2][j];
! 1336: if (start_2[j] >= p)
! 1337: start_2[j] -= p;
! 1338: }
! 1339: }
! 1340: else
! 1341: {
! 1342: for (j = 2; j <= size_of_FB; j++)
! 1343: {
! 1344: p = FB[j];
! 1345: start_1[j] -= inv_A_H_i[nu_2][j];
! 1346: if (start_1[j] < 0)
! 1347: start_1[j] += p;
! 1348: start_2[j] -= inv_A_H_i[nu_2][j];
! 1349: if (start_2[j] < 0)
! 1350: start_2[j] += p;
! 1351: }
! 1352: }
! 1353: }
! 1354:
! 1355: /* p=2 is a special case */
! 1356: if (FB[2] == 2)
! 1357: {
! 1358: start_1[2] = 0; start_2[2] = 1;
! 1359: }
! 1360:
! 1361:
! 1362: /* now compute zeros of polynomials that have only one zero mod p
! 1363: because p divides the coefficient A */
! 1364:
! 1365: /* compute coefficient -C */
! 1366: av = avma;
! 1367: p1 = subii(kN, sqri(B));
! 1368: p2 = divii(p1, shifti(A, 2));
! 1369:
! 1370: for (j = 1; j <= total_no_of_primes_for_A; j++)
! 1371: if (*bin_index & (1 << (j-1)))
! 1372: {
! 1373: p = FB[start_index_FB_for_A + j];
! 1374: tmp = mpqs_invsmod(smodis(B, p), p);
! 1375: tmp2 = smodis (p2, p);
! 1376: tmp = mulssmod(tmp2, tmp, p);
! 1377: start_1[start_index_FB_for_A + j] =
! 1378: start_2[start_index_FB_for_A + j] = (tmp + M) % p;
! 1379: }
! 1380: avma = av;
! 1381:
! 1382: #ifdef MPQS_DEBUG
! 1383: {
! 1384: /*
! 1385: * check correctness of the roots z1, z2 mod p_i by evaluting
! 1386: * A * z1^2 + B * z1 + C mod p_i and checking against 0 mod p_i
! 1387: * C is written as (B*B-kN)/(4*A)
! 1388: */
! 1389: size_of_FB = FB[0] + 1;
! 1390: for (j = 3; j <= size_of_FB; j++)
! 1391: {
! 1392: av = avma;
! 1393: p = FB[j];
! 1394: M_mod_p = M % p;
! 1395:
! 1396: p1 = mulis(A, start_1[j] - M_mod_p);
! 1397: p1 = addii(p1, B);
! 1398: p1 = mulis(p1, start_1[j] - M_mod_p);
! 1399: p2 = divii(subii(sqri(B), kN), shifti(A, 2));
! 1400: p1 = addii(p1, p2);
! 1401: if (smodis(p1, p) != 0)
! 1402: {
! 1403: fprintferr("MPQS: (1) j = %ld p = %ld\n", j, p);
! 1404: fprintferr("MPQS: (1) index_i = %ld\n", index_i);
! 1405: fprintferr("MPQS: A = %Z\n", A);
! 1406: fprintferr("MPQS: B = %Z\n", B);
! 1407: fprintferr("MPQS: C = %Z\n", p1);
! 1408: fprintferr("MPQS: z1 = %ld\n", start_1[j] - M_mod_p);
! 1409: err(talker, "MPQS: self_init: found wrong polynomial in (1)");
! 1410: }
! 1411:
! 1412: p1 = mulis(A, start_2[j]-M_mod_p);
! 1413: p1 = addii(p1, B);
! 1414: p1 = mulis(p1, start_2[j]-M_mod_p);
! 1415: p2 = divii(subii(sqri(B), kN), shifti(A, 2));
! 1416: p1 = addii(p1, p2);
! 1417: if (smodis(p1, p) != 0)
! 1418: {
! 1419: fprintferr("MPQS: (2) j = %ld p = %ld\n", j, p);
! 1420: fprintferr("MPQS: (2) index_i = %ld\n", index_i);
! 1421: fprintferr("MPQS: A = %Z\n", A);
! 1422: fprintferr("MPQS: B = %Z\n", B);
! 1423: fprintferr("MPQS: C = %Z\n", p1);
! 1424: fprintferr("MPQS: z2 = %ld\n", start_2[j] - M_mod_p);
! 1425: err(talker, "MPQS: self_init: found wrong polynomial in (2)");
! 1426: }
! 1427: avma = av;
! 1428: }
! 1429: if (DEBUGLEVEL >= 4)
! 1430: fprintferr("MPQS: checking of roots of Q(x) was successful\n");
! 1431: }
! 1432: #endif
! 1433:
! 1434: }
! 1435:
! 1436: /******************************/
! 1437:
! 1438: /**
! 1439: ** Main sieving routine:
! 1440: **
! 1441: ** FB is a pointer to an array which holds the factor base
! 1442: ** log_FB is a pointer to an array which holds the approximations for
! 1443: ** the logarithms of the factor base elements
! 1444: ** start_1, start_2
! 1445: ** are arrays for starting points for different FB elements
! 1446: ** sieve_array
! 1447: ** points to a sieve array
! 1448: ** sieve_array_end
! 1449: ** points to the end of the sieve array
! 1450: ** M is the size of the sieving interval
! 1451: ** starting_sieving_index
! 1452: ** marks the first FB element which is used for sieving
! 1453: **
! 1454: **/
! 1455:
! 1456: #ifdef INLINE
! 1457: INLINE
! 1458: #endif
! 1459: void
! 1460: mpqs_sieve_p(unsigned char *begin, unsigned char *end,
! 1461: long p_times_4, long p, unsigned char log_p)
! 1462: {
! 1463: register unsigned char *e = end - p_times_4;
! 1464: while (begin <= e)
! 1465: {
! 1466: (*begin) += log_p, begin += p;
! 1467: (*begin) += log_p, begin += p;
! 1468: (*begin) += log_p, begin += p;
! 1469: (*begin) += log_p, begin += p;
! 1470: }
! 1471: while (begin <= end)
! 1472: (*begin) += log_p, begin += p;
! 1473: }
! 1474:
! 1475: static void
! 1476: mpqs_sieve(long *FB, unsigned char *log_FB, long *start_1, long *start_2,
! 1477: unsigned char *sieve_array, unsigned char *sieve_array_end,
! 1478: ulong M, ulong starting_sieving_index)
! 1479: {
! 1480: register long p_times_4, p, *ptr_FB, start1, start2, l;
! 1481: register unsigned char log_p;
! 1482:
! 1483: memset (sieve_array, 0, (M << 1) * sizeof (unsigned char));
! 1484:
! 1485: l = starting_sieving_index;
! 1486: ptr_FB = &FB[l];
! 1487:
! 1488: while ((p = *ptr_FB++) != 0)
! 1489: {
! 1490: p_times_4 = p * 4;
! 1491: log_p = log_FB[l];
! 1492: start1 = start_1[l];
! 1493: start2 = start_2[l];
! 1494:
! 1495: /* sieve with FB[l] from start_1[l] */
! 1496: /* if start1 != start2 sieve with FB[l] from start_2[l] */
! 1497: if (start1 == start2)
! 1498: mpqs_sieve_p(sieve_array + start1, sieve_array_end,
! 1499: p_times_4, p, log_p);
! 1500: else
! 1501: {
! 1502: mpqs_sieve_p(sieve_array + start1, sieve_array_end,
! 1503: p_times_4, p, log_p);
! 1504: mpqs_sieve_p(sieve_array + start2, sieve_array_end,
! 1505: p_times_4, p, log_p);
! 1506: }
! 1507:
! 1508: l++;
! 1509: }
! 1510: }
! 1511:
! 1512: /******************************/
! 1513:
! 1514: static long
! 1515: mpqs_eval_sieve(unsigned char *sieve_array, ulong M, long *candidates)
! 1516: {
! 1517: ulong M_2 = M << 1;
! 1518: int i = 0, count, q, r;
! 1519: unsigned char *ptr = sieve_array;
! 1520:
! 1521: r = M_2 % 4;
! 1522: q = M_2 - r;
! 1523: count = 0;
! 1524: for (i = 0; i < q; i += 4, ptr += 4)
! 1525: {
! 1526: if (*(ptr+0) > 128) { candidates[count] = i+0; count++; }
! 1527: if (*(ptr+1) > 128) { candidates[count] = i+1; count++; }
! 1528: if (*(ptr+2) > 128) { candidates[count] = i+2; count++; }
! 1529: if (*(ptr+3) > 128) { candidates[count] = i+3; count++; }
! 1530: }
! 1531: switch (r)
! 1532: {
! 1533: case 3:
! 1534: if (*(ptr+0) > 128) { candidates[count] = i+0; count++; }
! 1535: if (*(ptr+1) > 128) { candidates[count] = i+1; count++; }
! 1536: if (*(ptr+2) > 128) { candidates[count] = i+2; count++; }
! 1537: break;
! 1538: case 2:
! 1539: if (*(ptr+0) > 128) { candidates[count] = i+0; count++; }
! 1540: if (*(ptr+1) > 128) { candidates[count] = i+1; count++; }
! 1541: break;
! 1542: case 1:
! 1543: if (*(ptr+0) > 128) { candidates[count] = i+0; count++; }
! 1544: break;
! 1545: default:
! 1546: break;
! 1547: }
! 1548: candidates[count] = 0;
! 1549: return count;
! 1550: }
! 1551:
! 1552: /**
! 1553: ** Main relation routine:
! 1554: **
! 1555: ** FB is a pointer to an array which holds the factor base
! 1556: ** log_FB is a pointer to an array which holds the approximations for
! 1557: ** the logarithms of the factor base elements
! 1558: ** start_1, start_2
! 1559: ** are arrays for starting points for different FB elements
! 1560: ** M is the size of the sieving interval
! 1561: **
! 1562: **/
! 1563:
! 1564: #ifdef INLINE
! 1565: INLINE void
! 1566: mpqs_add_factor(char *s, ulong ei, ulong pi)
! 1567: {
! 1568: sprintf(s + strlen(s), " %lu %lu", ei, pi);
! 1569: }
! 1570: #else
! 1571: #define mpqs_add_factor(s,ei,pi) \
! 1572: sprintf(s + strlen(s), " %lu %lu", (ulong)ei, (ulong)pi)
! 1573: #endif
! 1574:
! 1575: /**
! 1576: ** divide and return the remainder. Leaves both the quotient and
! 1577: ** the remainder on the stack as GENs; the caller should clean up.
! 1578: **/
! 1579:
! 1580: #ifdef INLINE
! 1581: INLINE
! 1582: #else
! 1583: static
! 1584: #endif
! 1585: ulong
! 1586: mpqs_div_rem(GEN x, long y, GEN *q)
! 1587: {
! 1588: GEN r;
! 1589: *q = dvmdis(x, y, &r);
! 1590: if (signe(r)) return (ulong)(r[2]);
! 1591: return 0;
! 1592: }
! 1593:
! 1594: static long
! 1595: mpqs_eval_candidates(GEN A, GEN inv_A4, GEN B, GEN kN, long k,
! 1596: double sqrt_kN,
! 1597: long *FB, long *start_1, long *start_2,
! 1598: ulong M, long bin_index, long *candidates,
! 1599: long number_of_candidates, long lp_bound,
! 1600: long start_index_FB_for_A,
! 1601: FILE *FREL, FILE *LPREL)
! 1602: /* NB FREL, LPREL are actually FNEW, LPNEW when we get called */
! 1603: {
! 1604: GEN Qx, A_2x_plus_B, Y, Qx_div_p;
! 1605: double a, b, inv_2_a;
! 1606: long av, powers_of_2, p, tmp_p, remd_p, bi;
! 1607: long z1, z2, x, number_of_relations, x_minus_M;
! 1608: char *relations;
! 1609: ulong i, pi, ei, size_of_FB;
! 1610: int useless_cand;
! 1611: #ifdef MPQS_DEBUG_VERBOSE
! 1612: static char complaint[256], complaint0[256];
! 1613: #endif
! 1614:
! 1615: /* FIXME: this is probably right !!! */
! 1616:
! 1617: /*
! 1618: * compute the roots of Q(X); this will be used to find the sign of
! 1619: * Q(x) after reducing mod kN
! 1620: */
! 1621:
! 1622: a = gtodouble(A);
! 1623: inv_2_a = 1 / (2.0 * a);
! 1624: b = gtodouble(B);
! 1625: z1 = (long) ((-b - sqrt_kN) * inv_2_a);
! 1626: z2 = (long) ((-b + sqrt_kN) * inv_2_a);
! 1627:
! 1628: number_of_relations = 0;
! 1629: /* FIXME: this is definitely too loooooong ... */
! 1630: /* then take the size of the FB into account.
! 1631: We have in the worst case: a leading " 1 1", a trailing " 0\n" with
! 1632: the final NUL character, and in between up to size_of_FB pairs each
! 1633: consisting of an exponent, a subscript into FB, and two spaces.
! 1634: Moreover, subscripts into FB fit into 5 digits, and exponents fit
! 1635: into 3 digits with room to spare -- anything needing 3 or more digits
! 1636: for the subscript must come with an exponent of at most 2 digits.
! 1637: Moreover the product of the first 58 primes is larger than 10^110,
! 1638: so there cannot be more than 60 pairs in all, even if size_of_FB > 10^4.
! 1639: --GN */
! 1640: size_of_FB = FB[0]; /* one less than usually: don't count FB[1] */
! 1641: if (size_of_FB > 60) size_of_FB = 60;
! 1642: relations =
! 1643: (char *) gpmalloc((8 + size_of_FB * 9) * sizeof(char));
! 1644: #ifdef MPQS_DEBUG_VERBOSE
! 1645: complaint[0] = '\0';
! 1646: #endif
! 1647: #ifdef MPQS_DEBUG
! 1648: size_of_FB = FB[0] + 1; /* last useful subscript into FB */
! 1649: #endif
! 1650:
! 1651: i = 0;
! 1652: while (i < number_of_candidates)
! 1653: {
! 1654: #ifdef MPQS_DEBUG_VERYVERBOSE /* this one really fills the screen... */
! 1655: fprintferr("%c", (char)('0' + i%10));
! 1656: #endif
! 1657: x = candidates[i++];
! 1658: relations[0] = '\0';
! 1659: av = avma;
! 1660:
! 1661: /* A_2x_plus_B = (A*(2x)+B), Qx = (A*(2x)+B)^2/(4*A) = Q(x) */
! 1662: x_minus_M = x - M;
! 1663: A_2x_plus_B = modii(addii(mulis(A, x_minus_M << 1), B), kN);
! 1664: Y = subii(kN, A_2x_plus_B);
! 1665: if (absi_cmp(A_2x_plus_B, Y) < 0) Y = A_2x_plus_B;
! 1666: /* absolute value of smallest absolute residue of A_2x_plus_B mod kN */
! 1667:
! 1668: Qx = modii(sqri(Y), kN);
! 1669:
! 1670: /* Most of the time, gcd(Qx, kN) will be either 1 or k. However,
! 1671: it may happen that Qx is a multiple of N, especially when N
! 1672: is small, and this will lead to havoc below -- so we have to be
! 1673: a little bit careful. Of course we cannot possibly afford to
! 1674: compute the gcd each time through this loop unless we are
! 1675: debugging... --GN */
! 1676: #ifdef MPQS_DEBUG
! 1677: {
! 1678: long av1 = avma, ks;
! 1679: GEN g = mppgcd(Qx, kN);
! 1680: /* if ((ks = kronecker(divii(Qx, g), divii(kN, g))) != 1) */
! 1681: if (is_pm1(g))
! 1682: {
! 1683: if ((ks = kronecker(Qx, kN)) != 1)
! 1684: {
! 1685: fprintferr("\nMPQS: 4*A*Q(x) = %Z\n", Qx);
! 1686: fprintferr("\tKronecker symbol %ld\n", ks);
! 1687: err(talker, "MPQS: 4*A*Q(x) is not a square (mod kN)");
! 1688: }
! 1689: }
! 1690: #ifdef MPQS_DEBUG_VERBOSE
! 1691: else if (cmpis(g,k) /* != 0 */ )
! 1692: {
! 1693: char *gs = GENtostr(g);
! 1694: sprintf(complaint, "\nMPQS: gcd(4*A*Q(x), kN) = %s\n", gs);
! 1695: free(gs);
! 1696: if (strcmp(complaint, complaint0) != 0)
! 1697: {
! 1698: fprintferr(complaint);
! 1699: strcpy(complaint0, complaint);
! 1700: }
! 1701: }
! 1702: #endif
! 1703: avma = av1;
! 1704: }
! 1705: #endif
! 1706:
! 1707: Qx = modii(mulii(Qx, inv_A4), kN);
! 1708:
! 1709: /* check the sign of Qx */
! 1710: if (z1 < x_minus_M && x_minus_M < z2)
! 1711: {
! 1712: Qx = subii(kN, Qx);
! 1713: /* i = 1, ei = 1, pi */
! 1714: mpqs_add_factor(relations, 1, 1);
! 1715: }
! 1716: if (!signe(Qx))
! 1717: {
! 1718: #ifdef MPQS_DEBUG_VERBOSE
! 1719: fprintferr("<+>");
! 1720: #endif
! 1721: avma = av;
! 1722: continue;
! 1723: }
! 1724:
! 1725: /* divide by powers of 2; note that we're really dealing with
! 1726: 4*A*Q(x), so we remember an extra factor 2^2 */
! 1727: powers_of_2 = vali(Qx);
! 1728: Qx = shifti(Qx, -powers_of_2);
! 1729: mpqs_add_factor(relations, powers_of_2 + 2, 2);
! 1730: if (!signe(Qx)) /* this shouldn't happen */
! 1731: {
! 1732: #ifdef MPQS_DEBUG_VERBOSE
! 1733: fprintferr("<*>");
! 1734: #endif
! 1735: avma = av;
! 1736: continue;
! 1737: }
! 1738:
! 1739: /* we handled the case p = 2 already */
! 1740: pi = 3;
! 1741: bi = bin_index;
! 1742: useless_cand = 0;
! 1743: #ifdef MPQS_DEBUG_VERBOSE
! 1744: fprintferr("a");
! 1745: #endif
! 1746:
! 1747: /* FB[3] .. FB[start_index_FB_for_A] do not divide A .
! 1748: * p = FB[start_index_FB_for_A+j+1] divides A (to the first power)
! 1749: * iff the 2^j bit in bin_index is set */
! 1750: while ((p = FB[pi]) != 0 && !useless_cand)
! 1751: {
! 1752: tmp_p = x % p;
! 1753:
! 1754: ei = 0;
! 1755: if (bi && pi > start_index_FB_for_A)
! 1756: {
! 1757: ei = bi & 1; /* either 0 or 1 */
! 1758: bi >>= 1;
! 1759: }
! 1760:
! 1761: if (tmp_p == start_1[pi] || tmp_p == start_2[pi])
! 1762: {
! 1763: /* p divides Q(x) and possibly A */
! 1764: remd_p = mpqs_div_rem(Qx, p, &Qx_div_p);
! 1765: if (remd_p)
! 1766: {
! 1767: useless_cand = 1;
! 1768: break;
! 1769: }
! 1770: do
! 1771: {
! 1772: ei++;
! 1773: Qx = Qx_div_p;
! 1774: remd_p = mpqs_div_rem(Qx, p, &Qx_div_p);
! 1775: } while (remd_p == 0);
! 1776: }
! 1777: if (ei) /* p might divide A but not Q(x) */
! 1778: mpqs_add_factor(relations, ei, pi);
! 1779:
! 1780: pi++;
! 1781: }
! 1782:
! 1783: if (useless_cand)
! 1784: {
! 1785: #ifdef MPQS_DEBUG_VERBOSE
! 1786: fprintferr("\b<");
! 1787: #endif
! 1788: avma = av;
! 1789: continue;
! 1790: }
! 1791: #ifdef MPQS_DEBUG_VERBOSE
! 1792: fprintferr("\bb");
! 1793: #endif
! 1794:
! 1795: if (is_pm1(Qx))
! 1796: {
! 1797: char *Qxstring = GENtostr(Y);
! 1798: strcat(relations, " 0");
! 1799: fprintf(FREL, "%s :%s\n", Qxstring, relations);
! 1800: number_of_relations++;
! 1801:
! 1802: #ifdef MPQS_DEBUG
! 1803: {
! 1804: GEN Qx_2, prod_pi_ei, pi_ei;
! 1805: long lr = strlen(relations);
! 1806: char *s, *t = gpmalloc(lr+1);
! 1807: long pi, ei, av1 = avma;
! 1808:
! 1809: #ifdef MPQS_DEBUG_VERBOSE
! 1810: fprintferr("\b(");
! 1811: #endif
! 1812: Qx_2 = modii(sqri(Y), kN);
! 1813: prod_pi_ei = gun;
! 1814: strcpy(t, relations);
! 1815: s = strtok(relations, " \n");
! 1816: while (s != NULL)
! 1817: {
! 1818: ei = atol(s);
! 1819: if (ei == 0) break;
! 1820: s = strtok(NULL, " \n");
! 1821: pi = atol(s);
! 1822: pi_ei = powmodulo(stoi(FB[pi]), stoi(ei), kN);
! 1823: prod_pi_ei = modii(mulii(prod_pi_ei, pi_ei), kN);
! 1824: s = strtok(NULL, " \n");
! 1825: }
! 1826:
! 1827: if (!egalii(Qx_2, prod_pi_ei))
! 1828: {
! 1829: #ifdef MPQS_DEBUG_VERBOSE
! 1830: fprintferr("!)\n");
! 1831: #endif
! 1832: fprintferr("MPQS: %s :%s\n", Qxstring, t);
! 1833: fprintferr("\tQx_2 = %Z\n", Qx_2);
! 1834: fprintferr("\t rhs = %Z\n", prod_pi_ei);
! 1835: err(talker, "MPQS: wrong full relation found!!");
! 1836: }
! 1837: #ifdef MPQS_DEBUG_VERBOSE
! 1838: else
! 1839: fprintferr(":)");
! 1840: #endif
! 1841: avma = av1;
! 1842: free(t);
! 1843: }
! 1844: #endif
! 1845:
! 1846: free(Qxstring);
! 1847: }
! 1848: else if (cmpis(Qx, lp_bound) > 0)
! 1849: {
! 1850: /* TO BE DONE: check for double large prime */
! 1851: /* moved this else clause here where I think it belongs -- GN */
! 1852: #ifdef MPQS_DEBUG_VERBOSE
! 1853: fprintferr("\b.");
! 1854: #endif
! 1855: }
! 1856: else if (k==1 || cgcd(k, itos(Qx)) == 1)
! 1857: {
! 1858: /* if (mpqs_isprime(itos(Qx))) */
! 1859: char *Qxstring = GENtostr(Y);
! 1860: char *L1string = GENtostr(Qx);
! 1861: strcat(relations, " 0");
! 1862: fprintf(LPREL, "%s @ %s :%s\n", L1string, Qxstring, relations);
! 1863:
! 1864: #ifdef MPQS_DEBUG
! 1865: {
! 1866: GEN Qx_2, prod_pi_ei, pi_ei;
! 1867: long lr = strlen(relations);
! 1868: char *s, *t = gpmalloc(lr+1);
! 1869: long pi, ei, av1 = avma;
! 1870:
! 1871: #ifdef MPQS_DEBUG_VERBOSE
! 1872: fprintferr("\b(");
! 1873: #endif
! 1874: Qx_2 = modii(sqri(Y), kN);
! 1875: prod_pi_ei = gun;
! 1876: strcpy(t, relations);
! 1877: s = strtok(relations, " \n");
! 1878: while (s != NULL)
! 1879: {
! 1880: ei = atol(s);
! 1881: if (ei == 0) break;
! 1882: s = strtok(NULL, " \n");
! 1883: pi = atol(s);
! 1884: pi_ei = powmodulo(stoi(FB[pi]), stoi(ei), kN);
! 1885: prod_pi_ei = modii(mulii(prod_pi_ei, pi_ei), kN);
! 1886: s = strtok(NULL, " \n");
! 1887: }
! 1888: prod_pi_ei = modii(mulii(prod_pi_ei, Qx), kN);
! 1889:
! 1890: if (!egalii(Qx_2, prod_pi_ei))
! 1891: {
! 1892: #ifdef MPQS_DEBUG_VERBOSE
! 1893: fprintferr("!)\n");
! 1894: #endif
! 1895: fprintferr("MPQS: %s @ %s :%s\n",
! 1896: L1string, Qxstring, t);
! 1897: fprintferr("\tQx_2 = %Z\n", Qx_2);
! 1898: fprintferr("\t rhs = %Z\n", prod_pi_ei);
! 1899: err(talker, "MPQS: wrong large prime relation found!!");
! 1900: }
! 1901: #ifdef MPQS_DEBUG_VERBOSE
! 1902: else
! 1903: fprintferr(";)");
! 1904: #endif
! 1905: avma = av1;
! 1906: free(t);
! 1907: }
! 1908: #endif
! 1909:
! 1910: free(Qxstring);
! 1911: free(L1string);
! 1912: }
! 1913: #ifdef MPQS_DEBUG_VERBOSE
! 1914: else
! 1915: fprintferr("\b<k>");
! 1916: #endif
! 1917:
! 1918: avma = av;
! 1919: } /* while */
! 1920:
! 1921: #ifdef MPQS_DEBUG_VERBOSE
! 1922: fprintferr("\n");
! 1923: #endif
! 1924:
! 1925: free(relations);
! 1926: return number_of_relations;
! 1927: }
! 1928:
! 1929: /******************************/
! 1930:
! 1931: /**
! 1932: ** combines the large prime relations in COMB to full
! 1933: ** relations in FNEW. FNEW is assumed to be open for
! 1934: ** writing / appending.
! 1935: **/
! 1936:
! 1937: typedef struct
! 1938: {
! 1939: long q;
! 1940: char Y [MPQS_STRING_LENGTH];
! 1941: char ep [MPQS_STRING_LENGTH];
! 1942: } mpqs_lp_entry;
! 1943:
! 1944: static void
! 1945: mpqs_combine_exponents(long *ei, long ei_size, char *r1, char *r2)
! 1946: {
! 1947: char ej [MPQS_STRING_LENGTH], ek [MPQS_STRING_LENGTH];
! 1948: char *s;
! 1949: long e, p;
! 1950:
! 1951: memset(ei, 0, ei_size * sizeof(long));
! 1952: strcpy(ej, r1);
! 1953: strcpy(ek, r2);
! 1954:
! 1955: s = strtok(ej, " \n");
! 1956: while (s != NULL)
! 1957: {
! 1958: e = atol(s);
! 1959: if (e == 0)
! 1960: break;
! 1961: s = strtok(NULL, " \n");
! 1962: p = atol(s);
! 1963: ei[p] += e;
! 1964: s = strtok(NULL, " \n");
! 1965: }
! 1966:
! 1967: s = strtok(ek, " \n");
! 1968: while (s != NULL)
! 1969: {
! 1970: e = atol(s);
! 1971: if (e == 0)
! 1972: break;
! 1973: s = strtok(NULL, " \n");
! 1974: p = atol(s);
! 1975: ei[p] += e;
! 1976: s = strtok(NULL, " \n");
! 1977: }
! 1978:
! 1979: }
! 1980:
! 1981: static long
! 1982: mpqs_combine_large_primes(FILE *COMB, FILE *FNEW, long size_of_FB,
! 1983: GEN N, GEN kN, GEN *f
! 1984: #ifdef MPQS_DEBUG
! 1985: , long *FB
! 1986: #endif
! 1987: )
! 1988: {
! 1989: char buf [MPQS_STRING_LENGTH], *s1, *s2;
! 1990: char new_relation [MPQS_STRING_LENGTH];
! 1991: mpqs_lp_entry e[2]; /* we'll use the two alternatingly */
! 1992: long *ei, ei_size = size_of_FB + 2;
! 1993: long old_q;
! 1994: GEN inv_q, Y1, Y2, new_Y, new_Y1;
! 1995: long i, l, c = 0;
! 1996: long av = avma, av2;
! 1997:
! 1998: *f = NULL;
! 1999: if (fgets(buf, MPQS_STRING_LENGTH, COMB) == NULL)
! 2000: return 0; /* nothing there -- should not happen */
! 2001:
! 2002: /* put first lp relation in row 0 of e */
! 2003: s1 = buf; s2 = strchr(s1, ' '); *s2 = '\0';
! 2004: e[0].q = atol(s1);
! 2005: s1 = s2 + 3; s2 = strchr(s1, ' '); *s2 = '\0';
! 2006: strcpy(e[0].Y, s1);
! 2007: s1 = s2 + 3; s2 = strchr(s1, '\n'); *s2 = '\0';
! 2008: strcpy(e[0].ep, s1);
! 2009:
! 2010: i = 1; /* second relation will go into row 1 */
! 2011: old_q = e[0].q;
! 2012:
! 2013: while (!invmod(stoi(old_q), kN, &inv_q)) /* can happen --GN */
! 2014: {
! 2015: inv_q = mppgcd(inv_q, N);
! 2016: if (is_pm1(inv_q) || egalii(inv_q, N)) /* pity */
! 2017: {
! 2018: #ifdef MPQS_DEBUG
! 2019: fprintferr("MPQS: skipping relation with non-invertible q\n");
! 2020: #endif
! 2021: avma = av;
! 2022: if (fgets(buf, MPQS_STRING_LENGTH, COMB) == NULL)
! 2023: return 0;
! 2024: s1 = buf; s2 = strchr(s1, ' '); *s2 = '\0';
! 2025: e[0].q = atol(s1);
! 2026: s1 = s2 + 3; s2 = strchr(s1, ' '); *s2 = '\0';
! 2027: strcpy(e[0].Y, s1);
! 2028: s1 = s2 + 3; s2 = strchr(s1, '\n'); *s2 = '\0';
! 2029: strcpy(e[0].ep, s1);
! 2030: old_q = e[0].q;
! 2031: continue;
! 2032: }
! 2033: *f = gerepileupto(av, inv_q);
! 2034: return c;
! 2035: }
! 2036: Y1 = lisexpr(e[0].Y);
! 2037: av2 = avma; /* preserve inv_q and Y1 */
! 2038:
! 2039: ei = (long *) gpmalloc(ei_size * sizeof(long));
! 2040:
! 2041: while (fgets(buf, MPQS_STRING_LENGTH, COMB) != NULL)
! 2042: {
! 2043: s1 = buf; s2 = strchr(s1, ' '); *s2 = '\0';
! 2044: e[i].q = atol(s1);
! 2045: s1 = s2 + 3; s2 = strchr(s1, ' '); *s2 = '\0';
! 2046: strcpy(e[i].Y, s1);
! 2047: s1 = s2 + 3; s2 = strchr(s1, '\n'); *s2 = '\0';
! 2048: strcpy(e[i].ep, s1);
! 2049:
! 2050: if (e[i].q != old_q)
! 2051: {
! 2052: /* switch to combining a new bunch, swapping the rows */
! 2053: old_q = e[i].q;
! 2054: avma = av; /* discard old inv_q and Y1 */
! 2055: if (!invmod(stoi(old_q), kN, &inv_q)) /* can happen --GN */
! 2056: {
! 2057: inv_q = mppgcd(inv_q, N);
! 2058: if (is_pm1(inv_q) || egalii(inv_q, N)) /* pity */
! 2059: {
! 2060: #ifdef MPQS_DEBUG
! 2061: fprintferr("MPQS: skipping relation with non-invertible q\n");
! 2062: #endif
! 2063: avma = av;
! 2064: old_q = -1; /* sentinel */
! 2065: av2 = avma;
! 2066: continue; /* discard this combination */
! 2067: }
! 2068: *f = gerepileupto(av, inv_q);
! 2069: free (ei);
! 2070: return c;
! 2071: }
! 2072: Y1 = lisexpr(e[i].Y);
! 2073: i = 1 - i; /* subsequent relations go to other row */
! 2074: av2 = avma; /* preserve inv_q and Y1 */
! 2075: continue;
! 2076: }
! 2077: /* count and combine the two we've got, and continue in the same row */
! 2078: c++;
! 2079:
! 2080: mpqs_combine_exponents(ei, ei_size, e[1-i].ep, e[i].ep);
! 2081: if (DEBUGLEVEL >= 6)
! 2082: {
! 2083: fprintf(stderr, "MPQS: combining\n");
! 2084: fprintf(stderr, " {%ld @ %s : %s}\n",
! 2085: old_q, e[1-i].Y, e[1-i].ep);
! 2086: fprintf(stderr, " * {%ld @ %s : %s}\n",
! 2087: e[i].q, e[i].Y, e[i].ep);
! 2088: }
! 2089: Y2 = lisexpr(e[i].Y);
! 2090: new_Y = modii(mulii(mulii(Y1, Y2), inv_q), kN);
! 2091: new_Y1 = subii(kN, new_Y);
! 2092: if (absi_cmp(new_Y1, new_Y) < 0) new_Y = new_Y1;
! 2093: s1 = GENtostr(new_Y);
! 2094: strcpy(new_relation, s1);
! 2095: free(s1);
! 2096: strcat(new_relation, " :");
! 2097: if (ei[1] % 2)
! 2098: strcat(new_relation, " 1 1");
! 2099: for (l = 2; l < ei_size; l++)
! 2100: {
! 2101: if (ei[l])
! 2102: {
! 2103: sprintf(buf, " %ld %ld", ei[l], l);
! 2104: strcat(new_relation, buf);
! 2105: }
! 2106: }
! 2107: strcat(new_relation, " 0");
! 2108: if (DEBUGLEVEL >= 6)
! 2109: fprintf(stderr, " == {%s}\n", new_relation);
! 2110: strcat(new_relation, "\n");
! 2111:
! 2112: #ifdef MPQS_DEBUG
! 2113: {
! 2114: char ejk [MPQS_STRING_LENGTH];
! 2115: GEN Qx_2, prod_pi_ei, pi_ei;
! 2116: char *s;
! 2117: long pi, exi, av1 = avma;
! 2118: Qx_2 = modii(sqri(new_Y), kN);
! 2119:
! 2120: strcpy(ejk, new_relation);
! 2121: s = strchr(ejk, ':') + 2;
! 2122: s = strtok(s, " \n");
! 2123:
! 2124: prod_pi_ei = gun;
! 2125: while (s != NULL)
! 2126: {
! 2127: exi = atol(s);
! 2128: if (exi == 0) break;
! 2129: s = strtok(NULL, " \n");
! 2130: pi = atol(s);
! 2131: pi_ei = powmodulo(stoi(FB[pi]), stoi(exi), kN);
! 2132: prod_pi_ei = modii(mulii(prod_pi_ei, pi_ei), kN);
! 2133: s = strtok(NULL, " \n");
! 2134: }
! 2135: avma = av1;
! 2136:
! 2137: if (!egalii(Qx_2, prod_pi_ei))
! 2138: {
! 2139: free(ei);
! 2140: err(talker,
! 2141: "MPQS: combined large prime relation is false");
! 2142: }
! 2143: }
! 2144: #endif
! 2145:
! 2146: if (fputs(new_relation, FNEW) < 0)
! 2147: {
! 2148: free(ei);
! 2149: bummer(FNEW_str);
! 2150: }
! 2151: avma = av2;
! 2152: } /* while */
! 2153:
! 2154: free(ei);
! 2155:
! 2156: if (DEBUGLEVEL >= 4)
! 2157: fprintferr("MPQS: combined %ld full relation%s\n",
! 2158: c, (c!=1 ? "s" : ""));
! 2159: return c;
! 2160: }
! 2161:
! 2162: /******************************/
! 2163:
! 2164: #ifdef LONG_IS_64BIT
! 2165:
! 2166: #define MPQS_GAUSS_BITS 64
! 2167: static unsigned long mpqs_mask_bit[] =
! 2168: {
! 2169: 0x8000000000000000UL, 0x4000000000000000UL,
! 2170: 0x2000000000000000UL, 0x1000000000000000UL,
! 2171: 0x0800000000000000UL, 0x0400000000000000UL,
! 2172: 0x0200000000000000UL, 0x0100000000000000UL,
! 2173: 0x0080000000000000UL, 0x0040000000000000UL,
! 2174: 0x0020000000000000UL, 0x0010000000000000UL,
! 2175: 0x0008000000000000UL, 0x0004000000000000UL,
! 2176: 0x0002000000000000UL, 0x0001000000000000UL,
! 2177: 0x0000800000000000UL, 0x0000400000000000UL,
! 2178: 0x0000200000000000UL, 0x0000100000000000UL,
! 2179: 0x0000080000000000UL, 0x0000040000000000UL,
! 2180: 0x0000020000000000UL, 0x0000010000000000UL,
! 2181: 0x0000008000000000UL, 0x0000004000000000UL,
! 2182: 0x0000002000000000UL, 0x0000001000000000UL,
! 2183: 0x0000000800000000UL, 0x0000000400000000UL,
! 2184: 0x0000000200000000UL, 0x0000000100000000UL,
! 2185: 0x0000000080000000UL, 0x0000000040000000UL,
! 2186: 0x0000000020000000UL, 0x0000000010000000UL,
! 2187: 0x0000000008000000UL, 0x0000000004000000UL,
! 2188: 0x0000000002000000UL, 0x0000000001000000UL,
! 2189: 0x0000000000800000UL, 0x0000000000400000UL,
! 2190: 0x0000000000200000UL, 0x0000000000100000UL,
! 2191: 0x0000000000080000UL, 0x0000000000040000UL,
! 2192: 0x0000000000020000UL, 0x0000000000010000UL,
! 2193: 0x0000000000008000UL, 0x0000000000004000UL,
! 2194: 0x0000000000002000UL, 0x0000000000001000UL,
! 2195: 0x0000000000000800UL, 0x0000000000000400UL,
! 2196: 0x0000000000000200UL, 0x0000000000000100UL,
! 2197: 0x0000000000000080UL, 0x0000000000000040UL,
! 2198: 0x0000000000000020UL, 0x0000000000000010UL,
! 2199: 0x0000000000000008UL, 0x0000000000000004UL,
! 2200: 0x0000000000000002UL, 0x0000000000000001UL
! 2201: };
! 2202:
! 2203: #else
! 2204:
! 2205: #define MPQS_GAUSS_BITS 32
! 2206: static unsigned long mpqs_mask_bit[] =
! 2207: {
! 2208: 0x80000000UL, 0x40000000UL, 0x20000000UL, 0x10000000UL,
! 2209: 0x08000000UL, 0x04000000UL, 0x02000000UL, 0x01000000UL,
! 2210: 0x00800000UL, 0x00400000UL, 0x00200000UL, 0x00100000UL,
! 2211: 0x00080000UL, 0x00040000UL, 0x00020000UL, 0x00010000UL,
! 2212: 0x00008000UL, 0x00004000UL, 0x00002000UL, 0x00001000UL,
! 2213: 0x00000800UL, 0x00000400UL, 0x00000200UL, 0x00000100UL,
! 2214: 0x00000080UL, 0x00000040UL, 0x00000020UL, 0x00000010UL,
! 2215: 0x00000008UL, 0x00000004UL, 0x00000002UL, 0x00000001UL
! 2216: };
! 2217:
! 2218: #endif
! 2219:
! 2220: static mpqs_gauss_matrix
! 2221: mpqs_gauss_create_matrix(long rows, long cols)
! 2222: {
! 2223: mpqs_gauss_matrix m;
! 2224: long i, j, words = cols / MPQS_GAUSS_BITS;
! 2225: if (cols % MPQS_GAUSS_BITS)
! 2226: words++;
! 2227: m = (mpqs_gauss_row *) gpmalloc(rows * sizeof(mpqs_gauss_row));
! 2228: for (i = 0; i < rows; i++)
! 2229: {
! 2230: m[i] = (ulong *) gpmalloc(words * sizeof(ulong));
! 2231: for (j = 0; j < words; j++)
! 2232: m[i][j] = 0UL;
! 2233: }
! 2234: return m;
! 2235: }
! 2236:
! 2237: static void
! 2238: mpqs_gauss_destroy_matrix(mpqs_gauss_matrix m, long rows, long cols)
! 2239: {
! 2240: long i;
! 2241: (void) cols;
! 2242: for (i = 0; i < rows; i++)
! 2243: free(m[i]);
! 2244: free(m);
! 2245: }
! 2246:
! 2247: static ulong
! 2248: mpqs_gauss_get_bit(mpqs_gauss_matrix m, long i, long j)
! 2249: {
! 2250: return m[i][j / MPQS_GAUSS_BITS] & mpqs_mask_bit[j % MPQS_GAUSS_BITS];
! 2251: }
! 2252:
! 2253: static void
! 2254: mpqs_gauss_set_bit(mpqs_gauss_matrix m, long i, long j)
! 2255: {
! 2256: m[i][j / MPQS_GAUSS_BITS] |= mpqs_mask_bit[j % MPQS_GAUSS_BITS];
! 2257: }
! 2258:
! 2259: static void
! 2260: mpqs_gauss_clear_bit(mpqs_gauss_matrix m, long i, long j)
! 2261: {
! 2262: m[i][j / MPQS_GAUSS_BITS] &= ~mpqs_mask_bit[j % MPQS_GAUSS_BITS];
! 2263: }
! 2264:
! 2265: /* output an mpqs_gauss_matrix in PARI format */
! 2266: /* TODO -- this should do a little intelligent wrapping... GN */
! 2267: static void
! 2268: mpqs_gauss_print_matrix(mpqs_gauss_matrix m, long rows, long cols)
! 2269: {
! 2270: long i, j;
! 2271: fprintferr("\n[");
! 2272: for (i = 0; i < rows; i++)
! 2273: {
! 2274: for (j = 0; j < cols - 1; j++)
! 2275: {
! 2276: if (mpqs_gauss_get_bit(m, i, j))
! 2277: fprintferr("1, ");
! 2278: else
! 2279: fprintferr("0, ");
! 2280: }
! 2281:
! 2282: if (mpqs_gauss_get_bit(m, i, j))
! 2283: fprintferr("1");
! 2284: else
! 2285: fprintferr("0");
! 2286: if (i != rows - 1)
! 2287: fprintferr("; ");
! 2288: }
! 2289: fprintferr("]\n");
! 2290: }
! 2291:
! 2292: /* x ^= y : row addition over F_2 */
! 2293: static void
! 2294: mpqs_gauss_add_rows(mpqs_gauss_row y, mpqs_gauss_row x, long k, long n)
! 2295: {
! 2296: long i, q, r;
! 2297: n = n - k;
! 2298: r = n % 8; q = n - r + k; i = 0 + k;
! 2299: for (; i < q; i += 8)
! 2300: {
! 2301: x[0+i] ^= y[0+i]; x[1+i] ^= y[1+i];
! 2302: x[2+i] ^= y[2+i]; x[3+i] ^= y[3+i];
! 2303: x[4+i] ^= y[4+i]; x[5+i] ^= y[5+i];
! 2304: x[6+i] ^= y[6+i]; x[7+i] ^= y[7+i];
! 2305: }
! 2306: switch (r)
! 2307: {
! 2308: case 7: x[i] ^= y[i], i++;
! 2309: case 6: x[i] ^= y[i], i++;
! 2310: case 5: x[i] ^= y[i], i++;
! 2311: case 4: x[i] ^= y[i], i++;
! 2312: case 3: x[i] ^= y[i], i++;
! 2313: case 2: x[i] ^= y[i], i++;
! 2314: case 1: x[i] ^= y[i], i++;
! 2315: default: ;
! 2316: }
! 2317: }
! 2318:
! 2319: /* create and read an mpqs_gauss_matrix from a relation file FREL (opened
! 2320: by caller). Also record the position of each relation in the file for
! 2321: later use
! 2322: rows = size_of_FB+1, cols = rel */
! 2323: static mpqs_gauss_matrix
! 2324: mpqs_gauss_read_matrix(FILE *FREL, long rows, long cols, long *fpos)
! 2325: {
! 2326: mpqs_gauss_matrix m;
! 2327: long i = 0, e, p;
! 2328: char buf[MPQS_STRING_LENGTH], *s;
! 2329:
! 2330: m = mpqs_gauss_create_matrix(rows, cols);
! 2331: if ((fpos[0] = ftell(FREL)) < 0)
! 2332: err(talker, "ftell error on full relations file");
! 2333: while (fgets(buf, MPQS_STRING_LENGTH, FREL) != NULL)
! 2334: {
! 2335: s = strchr(buf, ':') + 2;
! 2336: s = strtok(s, " \n");
! 2337: while (s != NULL)
! 2338: {
! 2339: e = atol(s);
! 2340: if (e == 0)
! 2341: break;
! 2342: s = strtok(NULL, " \n");
! 2343: p = atol(s);
! 2344: if (e & 1)
! 2345: mpqs_gauss_set_bit(m, p - 1, i);
! 2346: s = strtok(NULL, " \n");
! 2347: }
! 2348: i++;
! 2349: if (i < cols && (fpos[i] = ftell(FREL)) < 0)
! 2350: err(talker, "ftell error on full relations file");
! 2351: }
! 2352: if (i != cols)
! 2353: {
! 2354: fprintferr("MPQS: full relations file %s than expected",
! 2355: i > cols ? "longer" : "shorter");
! 2356: err(talker, "MPQS panicking");
! 2357: }
! 2358: return m;
! 2359: }
! 2360:
! 2361: /* compute the kernel of an mpqs_gauss_matrix over F_2
! 2362: uses the algorithm described by Knuth, Vol. 2 as modified by Henri Cohen
! 2363: and optimized by Christian Batut, Thomas Papanikolaou and Xavier Roblot.
! 2364: m = rows, n = cols */
! 2365: static mpqs_gauss_matrix
! 2366: mpqs_kernel(mpqs_gauss_matrix x, long m, long n, long *rank)
! 2367: {
! 2368: long k, i, j, t, r;
! 2369: mpqs_gauss_matrix ker_x;
! 2370: mpqs_gauss_indices c, d;
! 2371: long words = n / MPQS_GAUSS_BITS;
! 2372: if (n % MPQS_GAUSS_BITS)
! 2373: words++;
! 2374:
! 2375: c = (long *) gpmalloc(m * sizeof(long));
! 2376: for (k = 0; k < m; k++) c[k] = -1;
! 2377:
! 2378: d = (long *) gpmalloc(n * sizeof(long));
! 2379: r = 0;
! 2380:
! 2381: for (k = 0; k < n; k++)
! 2382: {
! 2383: j = 0;
! 2384: while (j < m && (c[j] >= 0 || mpqs_gauss_get_bit(x, j, k) == 0))
! 2385: j++;
! 2386:
! 2387: if (j == m)
! 2388: {
! 2389: d[k] = -1; /* no pivot found in column k */
! 2390: r++; /* column k is a vector of the kernel */
! 2391: }
! 2392: else
! 2393: {
! 2394: d[k] = j; /* the pivot in column k is at row j */
! 2395: c[j] = k; /* a pivot at position j was found in column k */
! 2396: for (t = 0; t < m; t++)
! 2397: {
! 2398: if (t != j)
! 2399: {
! 2400: if (mpqs_gauss_get_bit(x, t, k))
! 2401: mpqs_gauss_add_rows(x[j], x[t], k / MPQS_GAUSS_BITS, words);
! 2402: }
! 2403: }
! 2404: }
! 2405: }
! 2406:
! 2407: ker_x = mpqs_gauss_create_matrix(n, r);
! 2408:
! 2409: for (j = k = 0; j < r; j++, k++)
! 2410: {
! 2411: while (d[k] != -1) k++;
! 2412: for (i = 0; i < k; i++)
! 2413: {
! 2414: if (d[i] != -1)
! 2415: {
! 2416: if (mpqs_gauss_get_bit(x, d[i], k))
! 2417: mpqs_gauss_set_bit(ker_x, i, j);
! 2418: else
! 2419: mpqs_gauss_clear_bit(ker_x, i, j);
! 2420: }
! 2421: else
! 2422: mpqs_gauss_clear_bit(ker_x, i, j);
! 2423: }
! 2424: mpqs_gauss_set_bit(ker_x, k, j);
! 2425: }
! 2426:
! 2427: free(c);
! 2428: free(d);
! 2429:
! 2430: *rank = r;
! 2431: return ker_x;
! 2432: }
! 2433:
! 2434: /******************************/
! 2435:
! 2436: static GEN
! 2437: mpqs_add_relation(GEN Y_prod, GEN N_or_kN, long *ei, char *r1)
! 2438: {
! 2439: GEN Y, res;
! 2440: char relation [MPQS_STRING_LENGTH];
! 2441: char *s;
! 2442: long av = avma, e, p;
! 2443:
! 2444: strcpy(relation, r1);
! 2445: s = strchr(relation, ':') - 1;
! 2446: *s = '\0';
! 2447: Y = lisexpr(relation);
! 2448: res = modii(mulii(Y_prod, Y), N_or_kN);
! 2449:
! 2450: s = s + 3;
! 2451: s = strtok(s, " \n");
! 2452: while (s != NULL)
! 2453: {
! 2454: e = atol(s);
! 2455: if (e == 0)
! 2456: break;
! 2457: s = strtok(NULL, " \n");
! 2458: p = atol(s);
! 2459: ei[p] += e;
! 2460: s = strtok(NULL, " \n");
! 2461: }
! 2462: return gerepileupto(av,res);
! 2463: }
! 2464:
! 2465: static char*
! 2466: mpqs_get_relation(long pos, FILE *FREL)
! 2467: {
! 2468: static char buf [MPQS_STRING_LENGTH];
! 2469: if (fseek(FREL, pos, SEEK_SET))
! 2470: err(talker, "can\'t seek full relations file");
! 2471: if (fgets(buf, MPQS_STRING_LENGTH, FREL) == NULL)
! 2472: err(talker, "full relations file truncated?!");
! 2473: return buf;
! 2474: }
! 2475:
! 2476: /* the following two reside in src/basemath/ifactor1.c */
! 2477: long is_odd_power(GEN x, GEN *pt, long *mask);
! 2478: int miller(GEN n, long k);
! 2479:
! 2480: #define isprobableprime(n) (miller((n),17))
! 2481:
! 2482: static GEN
! 2483: mpqs_solve_linear_system(GEN kN, GEN N, long rel, long *FB, long size_of_FB)
! 2484: {
! 2485: pariFILE *pFREL;
! 2486: FILE *FREL;
! 2487: GEN X, Y_prod, N_or_kN, D1, base, res, new_res;
! 2488: long av=avma, av2, av3, lim, lim3, tetpil;
! 2489: long *fpos, *ei;
! 2490: long i, j, H_cols, H_rows;
! 2491: long res_last, res_next, res_size, res_max;
! 2492: mpqs_gauss_matrix m, ker_m;
! 2493: long done, flag, mask, rank;
! 2494:
! 2495: #ifdef MPQS_DEBUG
! 2496: N_or_kN = kN;
! 2497: #else
! 2498: N_or_kN = (DEBUGLEVEL >= 4 ? kN : N);
! 2499: #endif /* --GN */
! 2500: pFREL = pari_fopen(FREL_str, READ);
! 2501: FREL = pFREL->file;
! 2502: fpos = (long *) gpmalloc(rel * sizeof(long));
! 2503:
! 2504: m = mpqs_gauss_read_matrix(FREL, size_of_FB+1, rel, fpos);
! 2505: if (DEBUGLEVEL >= 7)
! 2506: {
! 2507: fprintferr("\\\\ MATRIX READ BY MPQS\nFREL=");
! 2508: mpqs_gauss_print_matrix(m, size_of_FB+1, rel);
! 2509: fprintferr("\n");
! 2510: }
! 2511:
! 2512: ker_m = mpqs_kernel(m, size_of_FB+1, rel, &rank);
! 2513: if (DEBUGLEVEL >= 4)
! 2514: {
! 2515: if (DEBUGLEVEL >= 7)
! 2516: {
! 2517: fprintferr("\\\\ KERNEL COMPUTED BY MPQS\nKERNEL=");
! 2518: mpqs_gauss_print_matrix(ker_m, rel, rank);
! 2519: fprintferr("\n");
! 2520: }
! 2521: /* put this here where the poor user has a chance of seeing it: */
! 2522: fprintferr("MPQS: Gauss done: kernel has rank %ld, taking gcds...\n",
! 2523: rank);
! 2524: }
! 2525:
! 2526: H_rows = rel;
! 2527: H_cols = rank;
! 2528:
! 2529: /* If the computed kernel turns out to be trivial, fail gracefully;
! 2530: main loop may try to find some more relations --GN */
! 2531: if (H_cols == 0)
! 2532: {
! 2533: if (DEBUGLEVEL >= 3)
! 2534: err(warner, "MPQS: no solutions found from linear system solver");
! 2535: /* ei has not yet been allocated */
! 2536: mpqs_gauss_destroy_matrix(m, size_of_FB+1, rel);
! 2537: mpqs_gauss_destroy_matrix(ker_m, rel, rank);
! 2538: free(fpos);
! 2539: pari_fclose(pFREL);
! 2540: avma = av;
! 2541: return NULL; /* no factors found */
! 2542: }
! 2543:
! 2544: /* If the rank is r, we can expect up to 2^r pairwise coprime factors,
! 2545: but it may well happen that a kernel basis vector contributes nothing
! 2546: new to the decomposition. We will allocate room for up to eight factors
! 2547: initially (certainly adequate when one or two basis vectors work),
! 2548: adjusting this down at the end to what we actually found, or up if
! 2549: we are very lucky and find more factors. In the upper half of our
! 2550: vector, we store information about which factors we know to be composite
! 2551: (zero) or believe to be composite ((long)NULL which is just 0) or suspect
! 2552: to be prime (un), or an exponent (deux or some t_INT) if it is a proper
! 2553: power */
! 2554: av2 = avma; lim = stack_lim(av2,1);
! 2555: if (rank > BITS_IN_LONG - 2)
! 2556: res_max = VERYBIGINT; /* this, unfortunately, is the common case */
! 2557: else
! 2558: res_max = 1L<<rank; /* max number of factors we can hope for */
! 2559: res_size = 8; /* no. of factors we can store in this res */
! 2560: res = cgetg(2*res_size+1, t_VEC);
! 2561: for (i=2*res_size; i; i--) res[i] = 0;
! 2562: res_next = res_last = 1;
! 2563:
! 2564: ei = (long *) gpmalloc((size_of_FB + 2) * sizeof(long));
! 2565:
! 2566: for (i = 0; i < H_cols; i++) /* loop over basis of kernel */
! 2567: {
! 2568: X = Y_prod = gun;
! 2569: memset(ei, 0, (size_of_FB + 2) * sizeof(long));
! 2570:
! 2571: av3 = avma; lim3 = stack_lim(av3,1);
! 2572: for (j = 0; j < H_rows; j++)
! 2573: {
! 2574: if (mpqs_gauss_get_bit(ker_m, j, i))
! 2575: Y_prod = mpqs_add_relation(Y_prod, N_or_kN, ei,
! 2576: mpqs_get_relation(fpos[j], FREL));
! 2577: if (low_stack(lim3, stack_lim(av3,1)))
! 2578: {
! 2579: if(DEBUGMEM>1) err(warnmem,"[1]: mpqs_solve_linear_system");
! 2580: Y_prod = gerepileupto(av3, Y_prod);
! 2581: }
! 2582: }
! 2583: Y_prod = gerepileupto(av3, Y_prod); /* unconditionally */
! 2584:
! 2585: av3 = avma; lim3 = stack_lim(av3,1);
! 2586: for (j = 2; j <= (size_of_FB + 1); j++)
! 2587: {
! 2588: if (ei[j] & 1)
! 2589: { /* this cannot happen --GN */
! 2590: mpqs_gauss_destroy_matrix(m, size_of_FB+1, rel);
! 2591: mpqs_gauss_destroy_matrix(ker_m, rel, rank);
! 2592: free(ei); free(fpos);
! 2593: fprintferr("MPQS: the combination of the relations is a nonsquare\n");
! 2594: err(bugparier, "factoring (MPQS)");
! 2595: }
! 2596: if (ei[j])
! 2597: {
! 2598: X = modii(mulii(X, powmodulo(stoi(FB[j]), stoi(ei[j]>>1), N_or_kN)),
! 2599: N_or_kN);
! 2600: if (low_stack(lim3, stack_lim(av3,1)))
! 2601: {
! 2602: if(DEBUGMEM>1) err(warnmem,"[2]: mpqs_solve_linear_system");
! 2603: X = gerepileupto(av3, X);
! 2604: }
! 2605: }
! 2606: }
! 2607: X = gerepileupto(av3, X); /* unconditionally */
! 2608: if (
! 2609: #ifdef MPQS_DEBUG
! 2610: 1 ||
! 2611: #endif
! 2612: DEBUGLEVEL >= 1)
! 2613: { /* this shouldn't happen either --GN */
! 2614: if (signe(modii(subii(sqri(X), sqri(Y_prod)), N_or_kN)))
! 2615: {
! 2616: fprintferr("MPQS: X^2 - Y^2 != 0 mod %s\n",
! 2617: (N_or_kN == kN ? "kN" : "N"));
! 2618: fprintferr("\tindex i = %ld\n", i);
! 2619: err(warner, "MPQS: wrong relation found after Gauss");
! 2620: }
! 2621: }
! 2622: /* if res_next < 3, we still haven't decomposed the original N, and
! 2623: will want both a gcd and its cofactor, overwriting N. Note that
! 2624: gcd(X+Y_prod,N)==1 forces gcd(X-Y_prod,N)==N, so we can skip X-Y_prod
! 2625: in such cases */
! 2626: done = 0; /* (re-)counts probably-prime factors
! 2627: (or powers whose bases we don't want to
! 2628: handle any further) */
! 2629: if (res_next < 3)
! 2630: {
! 2631: D1 = mppgcd(addii(X,Y_prod),N);
! 2632: if (!is_pm1(D1))
! 2633: {
! 2634: if ((flag = egalii(D1, N))) /* assignment */
! 2635: /* this one's useless, try the other one */
! 2636: D1 = mppgcd(subii(X,Y_prod),N);
! 2637: if (!flag || (!is_pm1(D1) && !egalii(D1,N)))
! 2638: { /* got something that works */
! 2639: if (DEBUGLEVEL >= 5)
! 2640: fprintferr("MPQS: splitting N after %ld kernel vector%s\n",
! 2641: i+1, (i? "s" : ""));
! 2642: (void)mpdivis(N, D1, N); /* divide N in place */
! 2643: res[1] = (long)N; /* we'll gcopy this anyway before exiting */
! 2644: res[2] = (long)D1;
! 2645: res_last = res_next = 3;
! 2646: if (res_max == 2) break; /* two out of two possible factors seen */
! 2647: mask = 7;
! 2648: /* (actually, 5th/7th powers aren't really worth the trouble. OTOH
! 2649: once we have the hooks for dealing with cubes, higher powers can
! 2650: be handled essentially for free) */
! 2651: if (isprobableprime(N)) { done++; res[res_size+1] = un; }
! 2652: else if (carrecomplet(N, &base))
! 2653: { /* squares could cost us a lot of time */
! 2654: affii(base, N); done++; res[res_size+1] = deux;
! 2655: if (DEBUGLEVEL >= 5)
! 2656: fprintferr("MPQS: decomposed a square\n");
! 2657: }
! 2658: else if ((flag = is_odd_power(N, &base, &mask))) /* assignment */
! 2659: {
! 2660: affii(base, N); done++; res[res_size+1] = (long)(stoi(flag));
! 2661: if (DEBUGLEVEL >= 5)
! 2662: fprintferr("MPQS: decomposed a %s\n",
! 2663: (flag == 3 ? "cube" :
! 2664: (flag == 5 ? "5th power" : "7th power")));
! 2665: }
! 2666: else res[res_size+1] = zero; /* known composite */
! 2667: mask = 7;
! 2668: if (isprobableprime(D1)) { done++; res[res_size+2] = un; }
! 2669: else if (carrecomplet(D1, &base))
! 2670: {
! 2671: res[2] = (long)base;
! 2672: done++; res[res_size+2] = deux;
! 2673: if (DEBUGLEVEL >= 5)
! 2674: fprintferr("MPQS: decomposed a square\n");
! 2675: }
! 2676: else if ((flag = is_odd_power(D1, &base, &mask))) /* assignment */
! 2677: {
! 2678: res[2] = (long)base;
! 2679: done++; res[res_size+2] = (long)(stoi(flag));
! 2680: if (DEBUGLEVEL >= 5)
! 2681: fprintferr("MPQS: decomposed a %s\n",
! 2682: (flag == 3 ? "cube" :
! 2683: (flag == 5 ? "5th power" : "7th power")));
! 2684: }
! 2685: else res[res_size+2] = zero; /* known composite */
! 2686: if (done == 2) break; /* both factors look prime or were powers */
! 2687: if (DEBUGLEVEL >= 5)
! 2688: fprintferr("MPQS: got two factors, looking for more...\n");
! 2689: /* and loop (after collecting garbage if necessary) */
! 2690: } /* else loop to next kernel basis vector */
! 2691: } /* D1!=1, nothing to be done when ==1 */
! 2692: }
! 2693: else /* we already have factors */
! 2694: {
! 2695: GEN X_plus_Y = addii(X, Y_prod);
! 2696: GEN X_minus_Y = NULL; /* will only be computed when needed */
! 2697: for (j=1; j < res_next; j++)
! 2698: { /* loop over known-composite factors */
! 2699: if (res[res_size+j] && res[res_size+j] != zero)
! 2700: {
! 2701: done++; continue; /* skip probable primes etc */
! 2702: }
! 2703: /* (actually, also skip square roots of squares etc. They are
! 2704: necessarily a lot smaller than the original N, and should
! 2705: be easy to deal with later) */
! 2706: av3 = avma;
! 2707: D1 = mppgcd(X_plus_Y, (GEN)(res[j]));
! 2708: if (is_pm1(D1)) continue; /* this one doesn't help us */
! 2709: if ((flag = egalii(D1, (GEN)(res[j]))))
! 2710: { /* bad one, try the other */
! 2711: avma = av3;
! 2712: if (!X_minus_Y) X_minus_Y = subii(X, Y_prod);
! 2713: av3 = avma;
! 2714: D1 = mppgcd(X_minus_Y, (GEN)(res[j]));
! 2715: }
! 2716: if (!flag || (!is_pm1(D1) && !egalii(D1, (GEN)(res[j]))))
! 2717: { /* got one which splits this factor */
! 2718: if (DEBUGLEVEL >= 5)
! 2719: fprintferr("MPQS: resplitting a factor after %ld kernel vectors\n",
! 2720: i+1); /* always plural */
! 2721: /* first make sure there's room for another factor */
! 2722: if (res_next > res_size)
! 2723: { /* need to reallocate (_very_ rare case) */
! 2724: long i1, new_size = 2*res_size;
! 2725: GEN new_res;
! 2726: if (new_size > res_max) new_size = res_max;
! 2727: new_res = cgetg(2*new_size+1, t_VEC);
! 2728: for (i1=2*new_size; i1>=res_next; i1--) new_res[i1] = 0;
! 2729: for (i1=1; i1<res_next; i1++)
! 2730: {
! 2731: new_res[i1] = res[i1]; /* factors */
! 2732: new_res[new_size+i1] = res[res_size+i1]; /* primality tags */
! 2733: }
! 2734: res = new_res; res_size = new_size; /* res_next unchanged */
! 2735: }
! 2736: /* now there is room; divide into existing factor and store the
! 2737: new gcd. Remove the known-composite flag from the old entry */
! 2738: (void)mpdivis((GEN)(res[j]), D1, (GEN)(res[j]));
! 2739: res[res_next] = (long)D1; res[res_size+j] = 0;
! 2740: if (++res_next > res_max) break; /* all possible factors seen */
! 2741: mask = 7; /* check for 3rd and 5th powers */
! 2742: if (isprobableprime((GEN)(res[j])))
! 2743: {
! 2744: done++; res[res_size+j] = un;
! 2745: }
! 2746: else if (carrecomplet((GEN)(res[j]), &base))
! 2747: {
! 2748: /* we no longer bother preserving the cloned N or what is left
! 2749: of it when we hit it here */
! 2750: res[j] = (long)base;
! 2751: done++; res[res_size+j] = deux;
! 2752: if (DEBUGLEVEL >= 5)
! 2753: fprintferr("MPQS: decomposed a square\n");
! 2754: }
! 2755: else if ((flag = is_odd_power((GEN)(res[j]), &base, &mask))) /* = */
! 2756: {
! 2757: res[j] = (long)base;
! 2758: done++; res[res_size+j] = (long)stoi(flag);
! 2759: if (DEBUGLEVEL >= 5)
! 2760: fprintferr("MPQS: decomposed a %s\n",
! 2761: (flag == 3 ? "cube" :
! 2762: (flag == 5 ? "5th power" : "7th power")));
! 2763: }
! 2764: else res[res_size+j] = zero; /* known composite */
! 2765: mask = 7;
! 2766: if (isprobableprime(D1))
! 2767: {
! 2768: done++; res[res_size+res_last] = un;
! 2769: }
! 2770: else if (carrecomplet(D1, &base))
! 2771: {
! 2772: res[res_last] = (long)base;
! 2773: done++; res[res_size+res_last] = deux;
! 2774: if (DEBUGLEVEL >= 5)
! 2775: fprintferr("MPQS: decomposed a square\n");
! 2776: }
! 2777: else if ((flag = is_odd_power(D1, &base, &mask))) /* assignment */
! 2778: {
! 2779: res[res_last] = (long)base;
! 2780: done++; res[res_size+res_last] = (long)stoi(flag);
! 2781: if (DEBUGLEVEL >= 5)
! 2782: fprintferr("MPQS: decomposed a %s\n",
! 2783: (flag == 3 ? "cube" :
! 2784: (flag == 5 ? "5th power" : "7th power")));
! 2785: }
! 2786: else res[res_size+res_last] = zero; /* known composite */
! 2787: } /* else it didn't help on this factor, try the next one... */
! 2788: else avma = av3; /* ...after destroying the gcds */
! 2789: } /* loop over known composite factors */
! 2790: if (res_next > res_last)
! 2791: {
! 2792: if (DEBUGLEVEL >= 5 && done < res_last)
! 2793: fprintferr("MPQS: got %ld factors%s\n",
! 2794: res_last,
! 2795: (done < res_last ? ", looking for more..." : ""));
! 2796: res_last = res_next;
! 2797: }
! 2798: /* we should break out of the outer loop when we have seen res_max
! 2799: factors, and also when all current factors are probable primes */
! 2800: if (res_next > res_max || done == res_next - 1) break;
! 2801: /* else continue loop over kernel basis */
! 2802: } /* end case of further splitting of existing factors */
! 2803: /* garbage collection */
! 2804: if (low_stack(lim, stack_lim(av2,1)))
! 2805: {
! 2806: long i1;
! 2807: if(DEBUGMEM>1) err(warnmem,"[3]: mpqs_solve_linear_system");
! 2808: tetpil=avma;
! 2809: /* gcopy would have a problem with our NULL pointers... */
! 2810: new_res = cgetg(lg(res), t_VEC);
! 2811: for (i1=2*res_size; i1>=res_next; i1--) new_res[i1] = 0;
! 2812: for (i1=1; i1<res_next; i1++)
! 2813: {
! 2814: new_res[i1] =
! 2815: (isonstack((GEN)(res[i1])) ? licopy((GEN)(res[i1])) : res[i1]);
! 2816: new_res[res_size+i1] = res[res_size+i1];
! 2817: }
! 2818: res = gerepile(av2, tetpil, new_res);
! 2819: /* discard X and Y_prod */
! 2820: }
! 2821: } /* for (loop over kernel basis) */
! 2822:
! 2823: if (res_next < 3) /* still no factors seen */
! 2824: {
! 2825: pari_fclose(pFREL);
! 2826: mpqs_gauss_destroy_matrix(m, size_of_FB+1, rel);
! 2827: mpqs_gauss_destroy_matrix(ker_m, rel, rank);
! 2828: free(ei); free(fpos);
! 2829: avma = av;
! 2830: return NULL; /* no factors found */
! 2831: }
! 2832: /* normal case: convert internal format to ifac format as described in
! 2833: src/basemath/ifactor1.c (triples of components: value, exponent, class
! 2834: [unknown, known composite, known prime]), clean up and return result */
! 2835: pari_fclose(pFREL);
! 2836: mpqs_gauss_destroy_matrix(m, size_of_FB+1, rel);
! 2837: mpqs_gauss_destroy_matrix(ker_m, rel, rank);
! 2838: free(ei); free(fpos);
! 2839: res_last = res_next - 1; /* number of distinct factors found */
! 2840: new_res = cgetg(3*res_last + 1, t_VEC);
! 2841: if (DEBUGLEVEL >= 6)
! 2842: fprintferr("MPQS: wrapping up vector of %ld factors\n", res_last);
! 2843: for (i=1,j=1; i <= res_last; i++)
! 2844: {
! 2845: new_res[j++] = /* value of factor */
! 2846: isonstack((GEN)(res[i])) ? licopy((GEN)(res[i])) : res[i];
! 2847: flag = res[res_size+i];
! 2848: new_res[j++] = /* exponent */
! 2849: flag ? /* flag was zero or un or ... */
! 2850: (flag == zero ? un :
! 2851: (isonstack((GEN)flag) ? licopy((GEN)flag) : flag)
! 2852: ) :
! 2853: un; /* flag was (long)NULL */
! 2854: new_res[j++] = /* class */
! 2855: flag == zero ? zero : /* known composite */
! 2856: (long)NULL; /* base of power or suspected prime --
! 2857: mark as `unknown' */
! 2858: if (DEBUGLEVEL >= 6)
! 2859: fprintferr("\tpackaging %ld: %Z ^%ld (%s)\n", i, res[i],
! 2860: itos((GEN)(new_res[j-2])),
! 2861: (flag == zero ? "comp." : "unknown"));
! 2862: }
! 2863: return gerepileupto(av, new_res);
! 2864: }
! 2865:
! 2866: /******************************/
! 2867:
! 2868: /* All percentages below are actually fixed-point quantities scaled by 10
! 2869: (value of 1 means 0.1%, 1000 means 100%). --GN */
! 2870:
! 2871: #define max_percentage 1500 /* give up when nothing found after ~1.5
! 2872: times the required number of relations has
! 2873: been computed (n might be a prime power
! 2874: or the parameters might be exceptionally
! 2875: unfortunate for it) --GN */
! 2876:
! 2877: /**
! 2878: ** Factors N using the self-initializing multipolynomial quadratic sieve
! 2879: ** (SIMPQS). Returns one of the two factors, or (usually) a vector of
! 2880: ** factors and exponents and information about which ones are definitely
! 2881: ** still composite, or NULL when something goes wrong or when we can't
! 2882: ** seem to make any headway.
! 2883: **/
! 2884:
! 2885: /* TODO: this function to be renamed mpqs_main() with several extra para-
! 2886: meters, with mpqs() as a wrapper for the standard case, so we can do
! 2887: partial runs distributed across several machines etc. (not necessarily
! 2888: from gp, but certainly from a small dedicated C program). --GN */
! 2889:
! 2890: GEN
! 2891: mpqs(GEN N)
! 2892: {
! 2893: GEN fact; /* will in the end hold our factor(s) */
! 2894: ulong decimal_digits; /* number of decimals of N */
! 2895: long tc; /* number of candidates found in one
! 2896: iteration */
! 2897: long t; /* number of full relations found in one
! 2898: iteration */
! 2899: long tp; /* number of full relations found in one
! 2900: iteration after combining large prime
! 2901: relations */
! 2902: long k; /* the multiplier */
! 2903: GEN kN; /* k * N */
! 2904: double sqrt_kN; /* double approximation of sqrt(k*N) */
! 2905: long *FB; /* the factor base */
! 2906: ulong size_of_FB; /* the size of the factor base */
! 2907: ulong FB_overshoot; /* the number of relations aimed for */
! 2908: double log_multiplier; /* maps logarithms of FB elements to
! 2909: unsigned chars */
! 2910: double tolerance; /* used in sieving with logarithms */
! 2911: unsigned char *log_FB; /* logarithms of FB elements mapped to
! 2912: unsigned chars */
! 2913: unsigned char *sieve_array; /* the sieve array */
! 2914: unsigned char *sieve_array_end; /* the end of the sieve array */
! 2915: ulong M; /* the sieve interval size [-M, M] */
! 2916: ulong starting_sieving_index; /* the first element in the FB used for
! 2917: sieving */
! 2918: long last_prime_in_FB; /* the biggest prime in FB */
! 2919: long *sqrt_mod_p_kN; /* array containing sqrt(K*N) mod p_i,
! 2920: where p_i are FB elements */
! 2921: GEN A, B, inv_A4; /* coefficients of polynomials in (SI) */
! 2922: long *Q_prime_glob, *Q_prime; /* used for self initialization (SI) */
! 2923: GEN *H_i; /* will be used to compute the consecutive
! 2924: B during (SI) */
! 2925: long start_index_FB_for_A; /* the first index in the FB used for
! 2926: computing A during (SI), minus 1 */
! 2927: ulong no_of_primes_in_A; /* number of primes dividing A
! 2928: during (SI) */
! 2929: ulong total_no_of_primes_for_A; /* number of primes used for finding A
! 2930: during (SI) */
! 2931: long max_no_of_B; /* how many B's to use before choosing
! 2932: a new A during (SI) */
! 2933: long index_i; /* denotes the current pair of coeffs
! 2934: (A, B_i). If i == 0, a new A is
! 2935: generated */
! 2936: ulong bin_index; /* used for choosing the prime factors for
! 2937: for the A coeffs in mpqs_self_init() */
! 2938: long i, p; /* counters */
! 2939:
! 2940: /* Let (z0, z1) be the roots of Q(x) = A x^2 + Bx +C mod p_i;
! 2941: then we know that
! 2942: Q(z1 + i k) == 0 mod p_i and Q(z2 + i k) == 0 mod p_i */
! 2943:
! 2944: long *start_1; /* stores the position where p_i
! 2945: divides Q(x) for the first time,
! 2946: using z1 */
! 2947: long *start_2; /* same, but using z2 */
! 2948: long *inv_A2; /* inv_A2[i] = 1/(2*A) mod p_i */
! 2949: long **inv_A_H_i; /* inv_A_H_i[i][j] = 1/A H_i[i] mod p_j */
! 2950: long *candidates; /* positions in the sieve_array which
! 2951: probably factor over the FB */
! 2952: long lp_bound; /* size limit for large primes */
! 2953: ulong sort_interval; /* these determine when to sort and merge */
! 2954: ulong followup_sort_interval; /* the temporary files (scaled percentages) */
! 2955: long total_full_relations = 0;
! 2956: long total_partial_relations = 0;
! 2957: pariFILE *pFREL;
! 2958: pariFILE *pFNEW;
! 2959: pariFILE *pLPREL;
! 2960: pariFILE *pLPNEW;
! 2961: pariFILE *pCOMB;
! 2962: FILE *FNEW;
! 2963: FILE *LPNEW;
! 2964: long percentage = 0; /* scaled by 10, see comment above */
! 2965: long total_candidates_number = 0;
! 2966: long useless_candidates = 0; /* another scaled percentage */
! 2967: long vain_iterations = 0;
! 2968: long good_iterations = 0;
! 2969: long iterations = 0;
! 2970: long av = avma;
! 2971:
! 2972: if (DEBUGLEVEL >= 4)
! 2973: {
! 2974: (void) timer2(); /* clear timer */
! 2975: fprintferr("MPQS: number to factor N = %Z\n", N);
! 2976: }
! 2977:
! 2978: all_clean = 0; /* activate clean-up trap */
! 2979: {
! 2980: char *s = GENtostr(N);
! 2981: decimal_digits = strlen(s);
! 2982: free(s);
! 2983: }
! 2984:
! 2985: if (decimal_digits >= 108) /* changed to match Denny's parameters */
! 2986: {
! 2987: err(warner, "MPQS: number too big to be factored with MPQS, giving up");
! 2988: avma = av;
! 2989: all_clean = 1;
! 2990: return NULL;
! 2991: }
! 2992:
! 2993: if (DEBUGLEVEL >= 4)
! 2994: fprintferr("MPQS: factoring number of %ld decimal digits\n",
! 2995: decimal_digits);
! 2996:
! 2997: if (decimal_digits >= 70)
! 2998: err(warner,
! 2999: "MPQS: the factorization of this number will take %s hours",
! 3000: decimal_digits >= 84 ? "many" : "several");
! 3001:
! 3002: k = mpqs_find_k(N, 5);
! 3003: if (DEBUGLEVEL >= 5)
! 3004: fprintferr("MPQS: found multiplier %ld for N\n", k);
! 3005:
! 3006: kN = mulis(N, k);
! 3007: {
! 3008: char *s = GENtostr(kN);
! 3009: decimal_digits = strlen(s);
! 3010: free(s);
! 3011: }
! 3012:
! 3013: if (DEBUGLEVEL >= 5)
! 3014: {
! 3015: fprintferr("MPQS: kN = %Z\n", kN);
! 3016: fprintferr("MPQS: kN has %ld decimal digits\n",
! 3017: decimal_digits);
! 3018: }
! 3019:
! 3020: mpqs_read_parameters(decimal_digits, &tolerance, &M, &size_of_FB,
! 3021: &FB_overshoot,
! 3022: &no_of_primes_in_A, &total_no_of_primes_for_A,
! 3023: &max_no_of_B, &starting_sieving_index,
! 3024: &sort_interval, &followup_sort_interval);
! 3025: {
! 3026: double bytesize = (size_of_FB + 1)/(8.*1048576.);
! 3027: bytesize *= FB_overshoot;
! 3028: if (bytesize > 32.)
! 3029: {
! 3030: err(warner,
! 3031: "MPQS: Gauss elimination will require more than 32MBy of memory");
! 3032: if (DEBUGLEVEL >= 1)
! 3033: fprintferr("\t(estimated memory needed: %4.1fMBy)\n", bytesize);
! 3034: }
! 3035: }
! 3036:
! 3037: if (DEBUGLEVEL >= 4)
! 3038: {
! 3039: fprintferr("MPQS: sieving interval = [%ld, %ld]\n",
! 3040: -(long)M, M);
! 3041: fprintferr("MPQS: size of factor base = %ld\n",
! 3042: size_of_FB);
! 3043: fprintferr("MPQS: striving for %ld relations\n",
! 3044: FB_overshoot);
! 3045: fprintferr("MPQS: first sorting at %ld%%, then every %3.1f%% / %3.1f%%\n",
! 3046: sort_interval/10, followup_sort_interval/10.,
! 3047: followup_sort_interval/20.);
! 3048: fprintferr("MPQS: initial sieving index = %ld\n",
! 3049: starting_sieving_index);
! 3050: }
! 3051: sieve_array =
! 3052: (unsigned char *) gpmalloc((M << 1) * sizeof(unsigned char));
! 3053: sieve_array_end = sieve_array + (M << 1) - 1;
! 3054:
! 3055: if (DEBUGLEVEL >= 5)
! 3056: fprintferr("MPQS: creating factor base FB of size = %ld\n",
! 3057: size_of_FB);
! 3058:
! 3059: FB = mpqs_create_FB(size_of_FB, kN, k, &p);
! 3060:
! 3061: /* the following this way round to avoid overflow: --GN */
! 3062: lp_bound = FB[FB[0]+1];
! 3063: if (DEBUGLEVEL >= 4)
! 3064: fprintferr("MPQS: largest prime in FB = %ld\n",
! 3065: lp_bound);
! 3066: if (lp_bound > MPQS_LP_BOUND)
! 3067: lp_bound = MPQS_LP_BOUND;
! 3068: lp_bound *= MPQS_LP_FACTOR;
! 3069: if (DEBUGLEVEL >= 4)
! 3070: fprintferr("MPQS: bound for `large primes\' = %ld\n",
! 3071: lp_bound);
! 3072:
! 3073: if (p != 0)
! 3074: {
! 3075: free(FB);
! 3076: free(sieve_array);
! 3077: if (DEBUGLEVEL >= 4)
! 3078: fprintferr("\nMPQS: found factor = %ld whilst creating factor base\n",
! 3079: p);
! 3080: if (mpqs_diffptr == diffptr) mpqs_diffptr = NULL;
! 3081: avma = av;
! 3082: /* TODO: free the FB etc!!! */
! 3083: all_clean = 1;
! 3084: return stoi(p);
! 3085: }
! 3086:
! 3087: if (DEBUGLEVEL >= 5)
! 3088: {
! 3089: fprintferr("MPQS: computing logarithm approximations for p_i in FB\n");
! 3090: fprintferr("MPQS: computing sqrt(k*N) mod p_i\n");
! 3091: }
! 3092: last_prime_in_FB = FB[FB[0] + 1];
! 3093: log_multiplier = (2 * (unsigned char) (0.5 * log2 (gtodouble(kN)) +
! 3094: log2 ((double) M) - tolerance *
! 3095: log2 ((double) last_prime_in_FB)));
! 3096: log_multiplier = 127.0 / log_multiplier;
! 3097:
! 3098: log_FB =
! 3099: (unsigned char *) gpmalloc((size_of_FB + 2) * sizeof(unsigned char));
! 3100: sqrt_mod_p_kN =
! 3101: (long *) gpmalloc((size_of_FB + 2) * sizeof(long));
! 3102:
! 3103: for (i = 2; i < size_of_FB + 2; i++)
! 3104: {
! 3105: long av1 = avma;
! 3106: p = FB[i];
! 3107:
! 3108: /* compute the approximations of the logarithms of p_i */
! 3109: log_FB[i] =
! 3110: (unsigned char) (log_multiplier * log2 ((double) p) * 2);
! 3111:
! 3112: /* compute the x_i such that x_i^2 = (kN % p_i) mod p_i */
! 3113: sqrt_mod_p_kN[i] = itos(mpsqrtmod(modis(kN, p), stoi(p)));
! 3114: avma = av1;
! 3115: }
! 3116:
! 3117: if (DEBUGLEVEL >= 5)
! 3118: fprintferr("MPQS: allocating arrays for self-initialization\n");
! 3119:
! 3120: /* the size of coefficient A should be approximately */
! 3121: /* sqrt(kN)/M, so the size of the primes p dividing */
! 3122: /* A should be approximately (sqrt(kN/M))^(1/no_of_primes_in_A) */
! 3123:
! 3124: /* compute expected size of coefficients, which also defines the tolerance
! 3125: for the logarithmic sieve */
! 3126: sqrt_kN = sqrt(gtodouble(kN));
! 3127: tolerance = sqrt_kN / M;
! 3128: tolerance = pow(2.0, log2(tolerance) / no_of_primes_in_A);
! 3129: if (tolerance > FB[size_of_FB - 1]) /* ??? */
! 3130: err(talker, "MPQS: number of prime factors in A is too small");
! 3131:
! 3132: /* choose primes in FB to use for building the A coefficient */
! 3133: start_index_FB_for_A = 2;
! 3134: while (FB[start_index_FB_for_A] < tolerance)
! 3135: start_index_FB_for_A++;
! 3136:
! 3137: if (start_index_FB_for_A > 7)
! 3138: start_index_FB_for_A -= (no_of_primes_in_A >> 1);
! 3139:
! 3140: /* ensure that the primes to be used for A do occur in the FB */
! 3141: if (start_index_FB_for_A + total_no_of_primes_for_A >= size_of_FB)
! 3142: start_index_FB_for_A = size_of_FB - total_no_of_primes_for_A - 1;
! 3143:
! 3144: /* ensure that the multiplier k is smaller than the prime divisors of A */
! 3145: if (k >= FB[start_index_FB_for_A])
! 3146: {
! 3147: do
! 3148: start_index_FB_for_A++;
! 3149: while (k >= FB[start_index_FB_for_A]);
! 3150: if (start_index_FB_for_A + total_no_of_primes_for_A >= size_of_FB)
! 3151: err(talker,
! 3152: "MPQS: number of primes for A is too large, or FB too small");
! 3153: /* this shouldn't happen */
! 3154: }
! 3155:
! 3156: /* now a selection of total_no_of_primes_for_A consecutive primes
! 3157: * p = FB[start_index_FB_for_A+1], ... is chosen from the factor base */
! 3158:
! 3159: /* (no need to copy them around as long as they are consecutive entries
! 3160: in FB --GN) */
! 3161: Q_prime =
! 3162: (long *) gpmalloc(no_of_primes_in_A * sizeof(long));
! 3163: #if 1
! 3164: Q_prime_glob = &(FB[start_index_FB_for_A + 1]);
! 3165: #else
! 3166: Q_prime_glob =
! 3167: (long *) gpmalloc(total_no_of_primes_for_A * sizeof(long));
! 3168: for (i = 0; i < total_no_of_primes_for_A; i++)
! 3169: Q_prime_glob[i] = FB[start_index_FB_for_A + i + 1];
! 3170: #endif
! 3171:
! 3172: /* used for choosing the correct A coeffs in mpqs_self_init() */
! 3173: bin_index = 0;
! 3174:
! 3175: /* will be used to compute the consecutive B during
! 3176: self-initialization */
! 3177: H_i = (GEN *) gpmalloc(no_of_primes_in_A * sizeof(GEN));
! 3178: for (i = 0; i < no_of_primes_in_A; i++)
! 3179: H_i[i] = cgeti(2 * total_no_of_primes_for_A);
! 3180:
! 3181: inv_A_H_i =
! 3182: (long **) gpmalloc(total_no_of_primes_for_A * sizeof(long *));
! 3183: for (i = 0; i < total_no_of_primes_for_A; i++)
! 3184: inv_A_H_i[i] = (long *) gpmalloc((size_of_FB + 2) * sizeof(long));
! 3185:
! 3186: start_1 = (long *) gpmalloc((size_of_FB + 2) * sizeof(long));
! 3187: start_2 = (long *) gpmalloc((size_of_FB + 2) * sizeof(long));
! 3188:
! 3189: /* the next will hold 1/(2*A) mod p_i, p_i in FB */
! 3190: inv_A2 = (long *) gpmalloc((size_of_FB + 2) * sizeof(long));
! 3191:
! 3192: candidates = (long *) gpmalloc(MPQS_CANDIDATE_ARRAY_SIZE * sizeof(long));
! 3193:
! 3194: if (DEBUGLEVEL >= 5)
! 3195: {
! 3196: fprintferr("MPQS: index range of primes for A: [%ld, %ld]\n",
! 3197: start_index_FB_for_A + 1,
! 3198: start_index_FB_for_A + total_no_of_primes_for_A);
! 3199: fprintferr("MPQS: coefficients A will be built from %ld primes each\n",
! 3200: no_of_primes_in_A);
! 3201: }
! 3202:
! 3203: /* CLEAN UP define */
! 3204:
! 3205: #define CLEANUP() \
! 3206: free(FB); \
! 3207: free(sieve_array); \
! 3208: free(log_FB); \
! 3209: free(sqrt_mod_p_kN); \
! 3210: free(Q_prime); \
! 3211: /* free(Q_prime_glob); */ \
! 3212: free(H_i); \
! 3213: for (i = 0; i < total_no_of_primes_for_A; i++) \
! 3214: free(inv_A_H_i[i]); \
! 3215: free(inv_A_H_i); \
! 3216: free(start_1); \
! 3217: free(start_2); \
! 3218: free(inv_A2); \
! 3219: free(candidates);
! 3220:
! 3221: /*
! 3222: * main loop which
! 3223: * - computes polynomials and their zeros (self initialization)
! 3224: * - does the sieving
! 3225: * - tests candidates of the sieve array
! 3226: */
! 3227:
! 3228: /* denotes the current pair of coeffs (A, B_i). If i == 0 a new A is
! 3229: generated */
! 3230: index_i = -1;
! 3231:
! 3232: /* the coefficients of the polynomial currently used for sieving */
! 3233: /* A will be at most as long as the product of
! 3234: no_of_primes_in_A word-sized primes (was total_..., GN) */
! 3235: /* B needs at most total_no_of_primes_for_A + 1 words [CHECK] --GN */
! 3236: /* Take the double is just for safety ... */
! 3237: A = cgeti(2 * no_of_primes_in_A);
! 3238: B = cgeti(2 * total_no_of_primes_for_A + 1);
! 3239:
! 3240: /* 1/4A mod kN */
! 3241: inv_A4 = cgeti(lg(kN));
! 3242:
! 3243: if (DEBUGLEVEL >= 5)
! 3244: fprintferr("MPQS: starting main loop\n");
! 3245: /* compute names for the temp files we'll need */
! 3246: FREL_str = mpqs_get_filename("FREL");
! 3247: FNEW_str = mpqs_get_filename("FNEW");
! 3248: LPREL_str = mpqs_get_filename("LPREL");
! 3249: LPNEW_str = mpqs_get_filename("LPNEW");
! 3250: COMB_str = mpqs_get_filename("COMB");
! 3251: TMP_str = mpqs_get_filename("LPTMP");
! 3252:
! 3253: /* This was just for truncating */
! 3254: pFREL = pari_fopen(FREL_str, WRITE); pari_fclose(pFREL);
! 3255: pLPREL = pari_fopen(LPREL_str, WRITE); pari_fclose(pLPREL);
! 3256:
! 3257: pLPNEW = pari_fopen(LPNEW_str, WRITE);
! 3258: LPNEW = pLPNEW->file;
! 3259: pFNEW = pari_fopen(FNEW_str, WRITE);
! 3260: FNEW = pFNEW->file;
! 3261:
! 3262: for(;;)
! 3263: {
! 3264: /* at start of loop, FNEW and LPNEW are open for writing */
! 3265: iterations++;
! 3266: /* when all of the B's have already been used, choose new A ;
! 3267: this is indicated by setting index_i to 0 */
! 3268: if (index_i == (max_no_of_B - 1))
! 3269: index_i = 0;
! 3270: else
! 3271: index_i++;
! 3272:
! 3273: /* self initialization: compute polynomial and its zeros */
! 3274:
! 3275: mpqs_self_init(A, B, N, kN, FB, sqrt_mod_p_kN, start_1, start_2,
! 3276: no_of_primes_in_A, total_no_of_primes_for_A,
! 3277: M, inv_A_H_i, Q_prime, Q_prime_glob, H_i,
! 3278: index_i, start_index_FB_for_A, inv_A2, inv_A4,
! 3279: &bin_index, &fact);
! 3280: if (bin_index >= (1ul << total_no_of_primes_for_A)) /* wraparound */
! 3281: {
! 3282: /* TODO: increase some parameters. For the moment, simply give up */
! 3283: CLEANUP();
! 3284: pari_fclose(pFNEW);
! 3285: pari_fclose(pLPNEW);
! 3286: /* FREL, LPREL are closed at this point */
! 3287: pari_unlink(FREL_str);
! 3288: pari_unlink(FNEW_str);
! 3289: pari_unlink(LPREL_str);
! 3290: pari_unlink(LPNEW_str);
! 3291: if (mpqs_diffptr == diffptr) mpqs_diffptr = NULL;
! 3292: all_clean = 1;
! 3293: avma=av; return NULL;
! 3294: }
! 3295: if (fact) /* A4 not coprime to kN, fact divides N */
! 3296: { /* (cannot actually happen) */
! 3297: if (is_pm1(fact) || egalii(fact,N))
! 3298: continue; /* cannot use the current polynomial */
! 3299: CLEANUP();
! 3300: pari_fclose(pFNEW);
! 3301: pari_fclose(pLPNEW);
! 3302: pari_unlink(FREL_str);
! 3303: pari_unlink(FNEW_str);
! 3304: pari_unlink(LPREL_str);
! 3305: pari_unlink(LPNEW_str);
! 3306: if (mpqs_diffptr == diffptr) mpqs_diffptr = NULL;
! 3307: all_clean = 1;
! 3308: if (DEBUGLEVEL >= 4)
! 3309: {
! 3310: fprintferr("MPQS: whilst trying to invert A4 mod kN,\n");
! 3311: fprintferr("\tfound factor = %Z\n", fact);
! 3312: flusherr();
! 3313: }
! 3314: return gerepileupto(av, fact);
! 3315: }
! 3316:
! 3317: if (DEBUGLEVEL >= 6)
! 3318: {
! 3319: if (!index_i)
! 3320: fprintferr("MPQS: chose prime pattern 0x%lX for A\n",
! 3321: bin_index);
! 3322: if (signe(B) < 0)
! 3323: {
! 3324: setsigne(B,1);
! 3325: fprintferr("MPQS: chose Q_%ld(x) = %Z x^2 - %Z x + C\n",
! 3326: index_i, A, B);
! 3327: setsigne(B,-1);
! 3328: }
! 3329: else
! 3330: {
! 3331: fprintferr("MPQS: chose Q_%ld(x) = %Z x^2 + %Z x + C\n",
! 3332: index_i, A, B);
! 3333: }
! 3334: }
! 3335:
! 3336: mpqs_sieve(FB, log_FB, start_1, start_2, sieve_array,
! 3337: sieve_array_end, M, starting_sieving_index);
! 3338:
! 3339: tc = mpqs_eval_sieve(sieve_array, M, candidates);
! 3340: total_candidates_number += tc;
! 3341: if (DEBUGLEVEL >= 6)
! 3342: fprintferr("MPQS: found %lu candidate%s\n",
! 3343: tc, (tc==1? "" : "s"));
! 3344:
! 3345: if (tc)
! 3346: {
! 3347: good_iterations++;
! 3348: t = mpqs_eval_candidates(A, inv_A4, B, kN, k, sqrt_kN, FB,
! 3349: start_1, start_2,
! 3350: M, bin_index, candidates, tc, lp_bound,
! 3351: start_index_FB_for_A, FNEW, LPNEW);
! 3352: }
! 3353: else
! 3354: t = 0;
! 3355:
! 3356: total_full_relations += t;
! 3357: percentage =
! 3358: (long)((1000.0 * total_full_relations) / FB_overshoot);
! 3359: useless_candidates =
! 3360: (long)((1000.0 * (total_candidates_number - total_full_relations))
! 3361: / (total_candidates_number ? total_candidates_number : 1));
! 3362:
! 3363: if (percentage < sort_interval)
! 3364: continue; /* most main loops end here... */
! 3365:
! 3366: /* Extra processing when we have completed a sort interval: */
! 3367: if (DEBUGLEVEL >= 3)
! 3368: {
! 3369: if (DEBUGLEVEL >= 4)
! 3370: fprintferr("\nMPQS: passing the %3.1f%% checkpoint, time = %ld ms\n",
! 3371: sort_interval/10., timer2());
! 3372: else
! 3373: fprintferr("\nMPQS: passing the %3.1f%% checkpoint\n",
! 3374: sort_interval/10.);
! 3375: flusherr();
! 3376: }
! 3377: /* sort LPNEW and merge it into LPREL, diverting combinables into COMB */
! 3378: pari_fclose(pLPNEW);
! 3379: mpqs_sort_lp_file(LPNEW_str);
! 3380: tp = mpqs_mergesort_lp_file(LPREL_str, LPNEW_str, 0);
! 3381: pLPNEW = pari_fopen(LPNEW_str, WRITE);
! 3382: LPNEW = pLPNEW->file;
! 3383:
! 3384: /* combine whatever there is to be combined */
! 3385: if (tp > 0)
! 3386: {
! 3387: /* build full relations out of large prime relations */
! 3388: pCOMB = pari_fopen(COMB_str, READ);
! 3389: tp = mpqs_combine_large_primes(pCOMB->file, FNEW, size_of_FB, N, kN, &fact
! 3390: #ifdef MPQS_DEBUG
! 3391: , FB
! 3392: #endif
! 3393: );
! 3394: pari_fclose(pCOMB);
! 3395: pari_unlink(COMB_str);
! 3396: /* now FREL, LPREL are closed and FNEW, LPNEW are still open */
! 3397: if (fact) /* factor found during combining */
! 3398: {
! 3399: /* clean up */
! 3400: CLEANUP();
! 3401: pari_fclose(pLPNEW);
! 3402: pari_fclose(pFNEW);
! 3403: pari_unlink(FREL_str);
! 3404: pari_unlink(FNEW_str);
! 3405: pari_unlink(LPREL_str);
! 3406: pari_unlink(LPNEW_str);
! 3407: if (DEBUGLEVEL >= 4)
! 3408: {
! 3409: fprintferr("\nMPQS: split N whilst combining, time = %ld ms\n",
! 3410: timer2());
! 3411: fprintferr("MPQS: found factor = %Z\n", fact);
! 3412: }
! 3413: if (mpqs_diffptr == diffptr) mpqs_diffptr = NULL;
! 3414: all_clean = 1;
! 3415: return gerepileupto(av, fact);
! 3416: }
! 3417: }
! 3418:
! 3419: /* sort FNEW and merge it into FREL */
! 3420: pari_fclose(pFNEW);
! 3421: mpqs_sort_lp_file(FNEW_str);
! 3422: total_full_relations = mpqs_mergesort_lp_file(FREL_str, FNEW_str, 1);
! 3423: /* this being the definitive count (combinables combined, and
! 3424: duplicates removed) */
! 3425: /* FNEW stays closed until we know whether we need to reopen it for
! 3426: another iteration */
! 3427:
! 3428: total_partial_relations += tp;
! 3429:
! 3430: /* note that due to the removal of duplicates, percentage may actually
! 3431: decrease at this point. This may look funny in the diagnostics but
! 3432: is nothing to worry about, since we _are_ making progress neverthe-
! 3433: less. --GN */
! 3434: percentage =
! 3435: (long)((1000.0 * total_full_relations) / FB_overshoot);
! 3436: vain_iterations =
! 3437: (long)((1000.0 * (iterations - good_iterations))
! 3438: / iterations);
! 3439:
! 3440: /* TODO: the following could be improved (extrapolate from past
! 3441: experience how many combined full relations we can expect in
! 3442: addition to those we're finding directly) --GN */
! 3443: if (percentage >= 840)
! 3444: {
! 3445: if (percentage >= 980)
! 3446: sort_interval = percentage + 10;
! 3447: else
! 3448: sort_interval = percentage + (followup_sort_interval >> 1);
! 3449: if (sort_interval >= 1000 && percentage < 1000)
! 3450: sort_interval = 1000;
! 3451: }
! 3452: else
! 3453: {
! 3454: sort_interval = percentage + followup_sort_interval;
! 3455: }
! 3456:
! 3457: if (DEBUGLEVEL >= 4)
! 3458: {
! 3459: fprintferr("MPQS: done sorting%s, time = %ld ms\n",
! 3460: tp > 0 ? " and combining" : "",
! 3461: timer2());
! 3462: fprintferr("MPQS: found %3.1f%% of the required relations\n",
! 3463: percentage/10.);
! 3464: if (DEBUGLEVEL >= 5)
! 3465: {
! 3466: /* total_full_relations are always plural */
! 3467: fprintferr("MPQS: found %ld full relations\n",
! 3468: total_full_relations);
! 3469: fprintferr("MPQS: (%ld of these from partial relations)\n",
! 3470: total_partial_relations);
! 3471: fprintferr("MPQS: %4.1f%% useless candidates\n",
! 3472: useless_candidates/10.);
! 3473: fprintferr("MPQS: %4.1f%% of the iterations yielded no candidates\n",
! 3474: vain_iterations/10.);
! 3475: fprintferr("MPQS: next checkpoint at %3.1f%%\n",
! 3476: sort_interval/10.);
! 3477: }
! 3478: }
! 3479:
! 3480: if (percentage < 1000)
! 3481: {
! 3482: pFNEW = pari_fopen(FNEW_str, WRITE);
! 3483: FNEW = pFNEW->file;
! 3484: /* at this point, LPNEW and FNEW are again open for writing */
! 3485: continue; /* main loop */
! 3486: }
! 3487:
! 3488: /* percentage >= 1000, which implies total_full_relations > size_of_FB:
! 3489: try finishing it off */
! 3490:
! 3491: /* solve the system over F_2 */
! 3492: if (DEBUGLEVEL >= 4)
! 3493: fprintferr("\nMPQS: starting Gauss over F_2 on %ld distinct relations\n",
! 3494: total_full_relations);
! 3495: fact = mpqs_solve_linear_system(kN, N,
! 3496: total_full_relations,
! 3497: FB, size_of_FB);
! 3498:
! 3499: /* if solution found, clean up and return */
! 3500: if (fact)
! 3501: {
! 3502: /* clean up */
! 3503: CLEANUP();
! 3504: pari_fclose(pLPNEW);
! 3505: pari_unlink(FREL_str);
! 3506: pari_unlink(FNEW_str);
! 3507: pari_unlink(LPREL_str);
! 3508: pari_unlink(LPNEW_str);
! 3509: if (DEBUGLEVEL >= 4)
! 3510: {
! 3511: fprintferr("\nMPQS: time in Gauss and gcds = %ld ms\n",
! 3512: timer2());
! 3513: if (typ(fact) == t_INT)
! 3514: fprintferr("MPQS: found factor = %Z\n", fact);
! 3515: else
! 3516: {
! 3517: long j, nf=(lg(fact)-1)/3;
! 3518: if (nf==2)
! 3519: fprintferr("MPQS: found factors = %Z\n\tand %Z\n",
! 3520: fact[4], fact[1]);
! 3521: else
! 3522: {
! 3523: fprintferr("MPQS: found %ld factors =\n", nf);
! 3524: for (j=nf; j; j--)
! 3525: fprintferr("\t%Z%s\n", fact[3*j-2], (j>1? "," : ""));
! 3526: }
! 3527: }
! 3528: }
! 3529: if (mpqs_diffptr == diffptr) mpqs_diffptr = NULL;
! 3530: all_clean = 1;
! 3531: /* nuisance: fact may not be safe for a gcopy(), and thus
! 3532: gerepileupto(av, gcopy(fact)) will usually segfault on
! 3533: one of the NULL markers. However, it is already a nice
! 3534: connected object, and it resides already the top of the
! 3535: stack, so... :^) --GN */
! 3536: return gerepileupto(av, fact);
! 3537: }
! 3538: else
! 3539: {
! 3540: if (DEBUGLEVEL >= 4)
! 3541: {
! 3542: fprintferr("\nMPQS: time in Gauss and gcds = %ld ms\n",
! 3543: timer2());
! 3544: fprintferr("MPQS: no factors found.\n");
! 3545: if (percentage <= max_percentage)
! 3546: fprintferr("\nMPQS: restarting sieving ...\n");
! 3547: else
! 3548: fprintferr("\nMPQS: giving up.\n");
! 3549: }
! 3550: if (percentage > max_percentage)
! 3551: {
! 3552: /* clean up */
! 3553: CLEANUP();
! 3554: pari_fclose(pLPNEW);
! 3555: pari_unlink(FREL_str);
! 3556: pari_unlink(FNEW_str);
! 3557: pari_unlink(LPREL_str);
! 3558: pari_unlink(LPNEW_str);
! 3559: if (mpqs_diffptr == diffptr) mpqs_diffptr = NULL;
! 3560: all_clean = 1;
! 3561: avma=av; return NULL;
! 3562: }
! 3563: pFNEW = pari_fopen(FNEW_str, WRITE);
! 3564: FNEW = pFNEW->file;
! 3565: }
! 3566: } /* main loop */
! 3567: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>