Annotation of OpenXM_contrib/pari/src/modules/mpqs.c, Revision 1.1.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>