[BACK]Return to mpqs.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / pari / src / modules

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>