LCOV - code coverage report
Current view: top level - ecm - ecm.c (source / functions) Hit Total Coverage
Test: unnamed Lines: 654 728 89.8 %
Date: 2022-03-21 11:19:20 Functions: 14 14 100.0 %

          Line data    Source code
       1             : /* Elliptic Curve Method: toplevel and stage 1 routines.
       2             : 
       3             : Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011,
       4             : 2012, 2016 Paul Zimmermann, Alexander Kruppa, Cyril Bouvier, David Cleaver.
       5             : 
       6             : This file is part of the ECM Library.
       7             : 
       8             : The ECM Library is free software; you can redistribute it and/or modify
       9             : it under the terms of the GNU Lesser General Public License as published by
      10             : the Free Software Foundation; either version 3 of the License, or (at your
      11             : option) any later version.
      12             : 
      13             : The ECM Library is distributed in the hope that it will be useful, but
      14             : WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
      15             : or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
      16             : License for more details.
      17             : 
      18             : You should have received a copy of the GNU Lesser General Public License
      19             : along with the ECM Library; see the file COPYING.LIB.  If not, see
      20             : http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
      21             : 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
      22             : 
      23             : #include <stdio.h>
      24             : #include <stdlib.h>
      25             : #include <string.h>
      26             : #include "ecm-impl.h"
      27             : #include "getprime_r.h"
      28             : #include <math.h>
      29             : 
      30             : #ifdef HAVE_ADDLAWS
      31             : #include "addlaws.h"
      32             : #endif
      33             : 
      34             : #ifdef HAVE_LIMITS_H
      35             : # include <limits.h>
      36             : #else
      37             : # define ULONG_MAX __GMP_ULONG_MAX
      38             : #endif
      39             : 
      40             : #ifdef TIMING_CRT
      41             : extern int mpzspv_from_mpzv_slow_time, mpzspv_to_mpzv_time,
      42             :   mpzspv_normalise_time;
      43             : #endif
      44             : 
      45             : /* the following factor takes into account the smaller expected smoothness
      46             :    for Montgomery's curves (batch mode) with respect to Suyama's curves */
      47             : /* For param 1 we use A=4d-2 with d a square (see main.c). In that
      48             :    case, Cyril Bouvier and Razvan Barbulescu have shown that the average
      49             :    expected torsion is that of a generic Suyama curve multiplied by the
      50             :    constant 2^(1/3)/(3*3^(1/128)) */
      51             : #define EXTRA_SMOOTHNESS_SQUARE 0.416384512396064
      52             : /* For A=4d-2 (param 3) for d a random integer, the average expected torsion 
      53             :    is that of a generic Suyama curve multiplied by the constant 
      54             :    1/(3*3^(1/128)) */
      55             : #define EXTRA_SMOOTHNESS_32BITS_D 0.330484606500389
      56             : /******************************************************************************
      57             : *                                                                             *
      58             : *                            Elliptic Curve Method                            *
      59             : *                                                                             *
      60             : ******************************************************************************/
      61             : 
      62             : void duplicate (mpres_t, mpres_t, mpres_t, mpres_t, mpmod_t, mpres_t, 
      63             :                 mpres_t, mpres_t, mpres_t) ATTRIBUTE_HOT;
      64             : void add3 (mpres_t, mpres_t, mpres_t, mpres_t, mpres_t, mpres_t, mpres_t, 
      65             :            mpres_t, mpmod_t, mpres_t, mpres_t, mpres_t) ATTRIBUTE_HOT;
      66             : 
      67             : #define mpz_mulmod5(r,s1,s2,m,t) { mpz_mul(t,s1,s2); mpz_mod(r, t, m); }
      68             : 
      69             : /* switch from Montgomery's form g*y^2 = x^3 + a*x^2 + x
      70             :    to Weierstrass' form          Y^2 = X^3 + A*X + B
      71             :    by change of variables x -> g*X-a/3, y -> g*Y.
      72             :    We have A = (3-a^2)/(3g^2), X = (3x+a)/(3g), Y = y/g.
      73             :    If a factor is found during the modular inverse, returns 
      74             :    ECM_FACTOR_FOUND_STEP1 and the factor in f, otherwise returns
      75             :    ECM_NO_FACTOR_FOUND.
      76             : 
      77             :    The input value of y is the y0 value in the initial equation:
      78             :    g*y0^2 = x0^3 + a*x0^2 + x0.
      79             : */
      80             : int 
      81         978 : montgomery_to_weierstrass (mpz_t f, mpres_t x, mpres_t y, mpres_t A, mpmod_t n)
      82             : {
      83             :   mpres_t g;
      84             : 
      85         978 :   mpres_init (g, n);
      86         978 :   mpres_add (g, x, A, n);
      87         978 :   mpres_mul (g, g, x, n);
      88         978 :   mpres_add_ui (g, g, 1, n);
      89         978 :   mpres_mul (g, g, x, n);    /* g = x^3+a*x^2+x (y=1) */
      90         978 :   mpres_mul_ui (y, g, 3, n);
      91         978 :   mpres_mul (y, y, g, n);    /* y = 3g^2 */
      92         978 :   if (!mpres_invert (y, y, n)) /* y = 1/(3g^2) temporarily */
      93             :     {
      94           0 :       mpres_gcd (f, y, n);
      95           0 :       mpres_clear (g, n);
      96           0 :       return ECM_FACTOR_FOUND_STEP1;
      97             :     }
      98             :   
      99             :   /* update x */
     100         978 :   mpres_mul_ui (x, x, 3, n); /* 3x */
     101         978 :   mpres_add (x, x, A, n);    /* 3x+a */
     102         978 :   mpres_mul (x, x, g, n);    /* (3x+a)*g */
     103         978 :   mpres_mul (x, x, y, n);    /* (3x+a)/(3g) */
     104             : 
     105             :   /* update A */
     106         978 :   mpres_sqr (A, A, n);    /* a^2 */
     107         978 :   mpres_sub_ui (A, A, 3, n);
     108         978 :   mpres_neg (A, A, n);       /* 3-a^2 */
     109         978 :   mpres_mul (A, A, y, n);    /* (3-a^2)/(3g^2) */
     110             : 
     111             :   /* update y */
     112         978 :   mpres_mul_ui (g, g, 3, n); /* 3g */
     113         978 :   mpres_mul (y, y, g, n);    /* (3g)/(3g^2) = 1/g */
     114             :   
     115         978 :   mpres_clear (g, n);
     116         978 :   return ECM_NO_FACTOR_FOUND;
     117             : }
     118             : 
     119             : /* adds Q=(x2:z2) and R=(x1:z1) and puts the result in (x3:z3),
     120             :      using 6 muls (4 muls and 2 squares), and 6 add/sub.
     121             :    One assumes that Q-R=P or R-Q=P where P=(x:z).
     122             :      - n : number to factor
     123             :      - u, v, w : auxiliary variables
     124             :    Modifies: x3, z3, u, v, w.
     125             :    (x3,z3) may be identical to (x2,z2) and to (x,z)
     126             : */
     127             : void
     128   474034543 : add3 (mpres_t x3, mpres_t z3, mpres_t x2, mpres_t z2, mpres_t x1, mpres_t z1, 
     129             :       mpres_t x, mpres_t z, mpmod_t n, mpres_t u, mpres_t v, mpres_t w)
     130             : {
     131   474034543 :   mpres_sub (u, x2, z2, n);
     132   474034543 :   mpres_add (v, x1, z1, n);      /* u = x2-z2, v = x1+z1 */
     133             : 
     134   474034543 :   mpres_mul (u, u, v, n);        /* u = (x2-z2)*(x1+z1) */
     135             : 
     136   474034543 :   mpres_add (w, x2, z2, n);
     137   474034543 :   mpres_sub (v, x1, z1, n);      /* w = x2+z2, v = x1-z1 */
     138             : 
     139   474034543 :   mpres_mul (v, w, v, n);        /* v = (x2+z2)*(x1-z1) */
     140             : 
     141   474034543 :   mpres_add (w, u, v, n);        /* w = 2*(x1*x2-z1*z2) */
     142   474034543 :   mpres_sub (v, u, v, n);        /* v = 2*(x2*z1-x1*z2) */
     143             : 
     144   474034543 :   mpres_sqr (w, w, n);           /* w = 4*(x1*x2-z1*z2)^2 */
     145   474034543 :   mpres_sqr (v, v, n);           /* v = 4*(x2*z1-x1*z2)^2 */
     146             : 
     147   474034543 :   if (x == x3) /* same variable: in-place variant */
     148             :     {
     149             :       /* x3 <- w * z mod n
     150             :          z3 <- x * v mod n */
     151     1494556 :       mpres_mul (z3, w, z, n);
     152     1494556 :       mpres_mul (x3, x, v, n);
     153     1494556 :       mpres_swap (x3, z3, n);
     154             :     }
     155             :   else
     156             :     {
     157   472539987 :       mpres_mul (x3, w, z, n);   /* x3 = 4*z*(x1*x2-z1*z2)^2 mod n */
     158   472539987 :       mpres_mul (z3, x, v, n);   /* z3 = 4*x*(x2*z1-x1*z2)^2 mod n */
     159             :     }
     160             :   /* mul += 6; */
     161   474034543 : }
     162             : 
     163             : /* computes 2P=(x2:z2) from P=(x1:z1), with 5 muls (3 muls and 2 squares)
     164             :    and 4 add/sub.
     165             :      - n : number to factor
     166             :      - b : (a+2)/4 mod n
     167             :      - t, u, v, w : auxiliary variables
     168             : */
     169             : void
     170    45066559 : duplicate (mpres_t x2, mpres_t z2, mpres_t x1, mpres_t z1, mpmod_t n, 
     171             :            mpres_t b, mpres_t u, mpres_t v, mpres_t w)
     172             : {
     173    45066559 :   mpres_add (u, x1, z1, n);
     174    45066559 :   mpres_sqr (u, u, n);      /* u = (x1+z1)^2 mod n */
     175    45066559 :   mpres_sub (v, x1, z1, n);
     176    45066559 :   mpres_sqr (v, v, n);      /* v = (x1-z1)^2 mod n */
     177    45066559 :   mpres_mul (x2, u, v, n);  /* x2 = u*v = (x1^2 - z1^2)^2 mod n */
     178    45066559 :   mpres_sub (w, u, v, n);   /* w = u-v = 4*x1*z1 */
     179    45066559 :   mpres_mul (u, w, b, n);   /* u = w*b = ((A+2)/4*(4*x1*z1)) mod n */
     180    45066559 :   mpres_add (u, u, v, n);   /* u = (x1-z1)^2+(A+2)/4*(4*x1*z1) */
     181    45066559 :   mpres_mul (z2, w, u, n);  /* z2 = ((4*x1*z1)*((x1-z1)^2+(A+2)/4*(4*x1*z1))) mod n */
     182    45066559 : }
     183             : 
     184             : /* multiply P=(x:z) by e and puts the result in (x:z). */
     185             : void
     186         975 : ecm_mul (mpres_t x, mpres_t z, mpz_t e, mpmod_t n, mpres_t b)
     187             : {
     188             :   size_t l;
     189         975 :   int negated = 0;
     190             :   mpres_t x0, z0, x1, z1, u, v, w;
     191             : 
     192             :   /* In Montgomery coordinates, the point at infinity is (0::0) */
     193         975 :   if (mpz_sgn (e) == 0)
     194             :     {
     195           0 :       mpz_set_ui (x, 0);
     196           0 :       mpz_set_ui (z, 0);
     197           0 :       return;
     198             :     }
     199             : 
     200             :   /* The negative of a point (x:y:z) is (x:-y:u). Since we do not compute
     201             :      y, e*(x::z) == (-e)*(x::z). */
     202         975 :   if (mpz_sgn (e) < 0)
     203             :     {
     204           0 :       negated = 1;
     205           0 :       mpz_neg (e, e);
     206             :     }
     207             : 
     208         975 :   if (mpz_cmp_ui (e, 1) == 0)
     209         850 :     goto ecm_mul_end;
     210             : 
     211         125 :   mpres_init (x0, n);
     212         125 :   mpres_init (z0, n);
     213         125 :   mpres_init (x1, n);
     214         125 :   mpres_init (z1, n);
     215         125 :   mpres_init (u, n);
     216         125 :   mpres_init (v, n);
     217         125 :   mpres_init (w, n);
     218             : 
     219         125 :   l = mpz_sizeinbase (e, 2) - 1; /* l >= 1 */
     220             : 
     221         125 :   mpres_set (x0, x, n);
     222         125 :   mpres_set (z0, z, n);
     223         125 :   duplicate (x1, z1, x0, z0, n, b, u, v, w);
     224             : 
     225             :   /* invariant: (P1,P0) = ((k+1)P, kP) where k = floor(e/2^l) */
     226             : 
     227        4117 :   while (l-- > 0)
     228             :     {
     229        3992 :       if (ecm_tstbit (e, l)) /* k, k+1 -> 2k+1, 2k+2 */
     230             :         {
     231        1957 :           add3 (x0, z0, x0, z0, x1, z1, x, z, n, u, v, w); /* 2k+1 */
     232        1957 :           duplicate (x1, z1, x1, z1, n, b, u, v, w); /* 2k+2 */
     233             :         }
     234             :       else /* k, k+1 -> 2k, 2k+1 */
     235             :         {
     236        2035 :           add3 (x1, z1, x1, z1, x0, z0, x, z, n, u, v, w); /* 2k+1 */
     237        2035 :           duplicate (x0, z0, x0, z0, n, b, u, v, w); /* 2k */
     238             :         }
     239             :     }
     240             : 
     241         125 :   mpres_set (x, x0, n);
     242         125 :   mpres_set (z, z0, n);
     243             : 
     244         125 :   mpres_clear (x0, n);
     245         125 :   mpres_clear (z0, n);
     246         125 :   mpres_clear (x1, n);
     247         125 :   mpres_clear (z1, n);
     248         125 :   mpres_clear (u, n);
     249         125 :   mpres_clear (v, n);
     250         125 :   mpres_clear (w, n);
     251             : 
     252         975 : ecm_mul_end:
     253             : 
     254             :   /* Undo negation to avoid changing the caller's e value */
     255         975 :   if (negated)
     256           0 :     mpz_neg (e, e);
     257             : }
     258             : 
     259             : #define ADD 6.0 /* number of multiplications in an addition */
     260             : #define DUP 5.0 /* number of multiplications in a duplicate */
     261             : 
     262             : /* returns the number of modular multiplications for computing
     263             :    V_n from V_r * V_{n-r} - V_{n-2r}.
     264             :    ADD is the cost of an addition
     265             :    DUP is the cost of a duplicate
     266             : */
     267             : static double
     268   174398870 : lucas_cost (ecm_uint n, double v)
     269             : {
     270             :   ecm_uint d, e, r;
     271             :   double c; /* cost */
     272             : 
     273   174398870 :   d = n;
     274   174398870 :   r = (ecm_uint) ((double) d * v + 0.5);
     275   174398870 :   if (r >= n)
     276           0 :     return (ADD * (double) n);
     277   174398870 :   d = n - r;
     278   174398870 :   e = 2 * r - n;
     279   174398870 :   c = DUP + ADD; /* initial duplicate and final addition */
     280  4501529164 :   while (d != e)
     281             :     {
     282  4327130294 :       if (d < e)
     283             :         {
     284  2913599944 :           r = d;
     285  2913599944 :           d = e;
     286  2913599944 :           e = r;
     287             :         }
     288  4327130294 :       if (d - e <= e / 4 && ((d + e) % 3) == 0)
     289             :         { /* condition 1 */
     290    98320044 :           d = (2 * d - e) / 3;
     291    98320044 :           e = (e - d) / 2;
     292    98320044 :           c += 3.0 * ADD; /* 3 additions */
     293             :         }
     294  4228810250 :       else if (d - e <= e / 4 && (d - e) % 6 == 0)
     295             :         { /* condition 2 */
     296    16810291 :           d = (d - e) / 2;
     297    16810291 :           c += ADD + DUP; /* one addition, one duplicate */
     298             :         }
     299  4211999959 :       else if ((d + 3) / 4 <= e)
     300             :         { /* condition 3 */
     301  3801244637 :           d -= e;
     302  3801244637 :           c += ADD; /* one addition */
     303             :         }
     304   410755322 :       else if ((d + e) % 2 == 0)
     305             :         { /* condition 4 */
     306   180017362 :           d = (d - e) / 2;
     307   180017362 :           c += ADD + DUP; /* one addition, one duplicate */
     308             :         }
     309             :       /* now d+e is odd */
     310   230737960 :       else if (d % 2 == 0)
     311             :         { /* condition 5 */
     312   152315821 :           d /= 2;
     313   152315821 :           c += ADD + DUP; /* one addition, one duplicate */
     314             :         }
     315             :       /* now d is odd and e is even */
     316    78422139 :       else if (d % 3 == 0)
     317             :         { /* condition 6 */
     318    32058854 :           d = d / 3 - e;
     319    32058854 :           c += 3.0 * ADD + DUP; /* three additions, one duplicate */
     320             :         }
     321    46363285 :       else if ((d + e) % 3 == 0)
     322             :         { /* condition 7 */
     323    29927311 :           d = (d - 2 * e) / 3;
     324    29927311 :           c += 3.0 * ADD + DUP; /* three additions, one duplicate */
     325             :         }
     326    16435974 :       else if ((d - e) % 3 == 0)
     327             :         { /* condition 8 */
     328     5057068 :           d = (d - e) / 3;
     329     5057068 :           c += 3.0 * ADD + DUP; /* three additions, one duplicate */
     330             :         }
     331             :       else /* necessarily e is even: catches all cases */
     332             :         { /* condition 9 */
     333    11378906 :           e /= 2;
     334    11378906 :           c += ADD + DUP; /* one addition, one duplicate */
     335             :         }
     336             :     }
     337             :   
     338   174398870 :   return c;
     339             : }
     340             : 
     341             : 
     342             : /* computes kP from P=(xA:zA) and puts the result in (xA:zA). Assumes k>2. 
     343             :    WARNING! The calls to add3() assume that the two input points are distinct,
     344             :    which is not neccessarily satisfied. The result can be that in rare cases
     345             :    the point at infinity (z==0) results when it shouldn't. A test case is 
     346             :    echo 33554520197234177 | ./ecm -sigma 2046841451 373 1
     347             :    which finds the prime even though it shouldn't (23^2=529 divides order).
     348             :    This is not a problem for ECM since at worst we'll find a factor we 
     349             :    shouldn't have found. For other purposes (i.e. primality proving) this 
     350             :    would have to be fixed first.
     351             : */
     352             : 
     353             : static void
     354    17439887 : prac (mpres_t xA, mpres_t zA, ecm_uint k, mpmod_t n, mpres_t b,
     355             :       mpres_t u, mpres_t v, mpres_t w, mpres_t xB, mpres_t zB, mpres_t xC, 
     356             :       mpres_t zC, mpres_t xT, mpres_t zT, mpres_t xT2, mpres_t zT2)
     357             : {
     358    17439887 :   ecm_uint d, e, r, i = 0, nv;
     359             :   double c, cmin;
     360             :   __mpz_struct *tmp;
     361             : #define NV 10  
     362             :   /* 1/val[0] = the golden ratio (1+sqrt(5))/2, and 1/val[i] for i>0
     363             :      is the real number whose continued fraction expansion is all 1s
     364             :      except for a 2 in i+1-st place */
     365             :   static double val[NV] =
     366             :     { 0.61803398874989485, 0.72360679774997897, 0.58017872829546410,
     367             :       0.63283980608870629, 0.61242994950949500, 0.62018198080741576,
     368             :       0.61721461653440386, 0.61834711965622806, 0.61791440652881789,
     369             :       0.61807966846989581};
     370             : 
     371             :   /* for small n, it makes no sense to try 10 different Lucas chains */
     372    17439887 :   nv = mpz_size ((mpz_ptr) n);
     373    17439887 :   if (nv > NV)
     374    17439887 :     nv = NV;
     375             : 
     376    17439887 :   if (nv > 1)
     377             :     {
     378             :       /* chooses the best value of v */
     379   191838757 :       for (d = 0, cmin = ADD * (double) k; d < nv; d++)
     380             :         {
     381   174398870 :           c = lucas_cost (k, val[d]);
     382   174398870 :           if (c < cmin)
     383             :             {
     384    42406179 :               cmin = c;
     385    42406179 :               i = d;
     386             :             }
     387             :         }
     388             :     }
     389             : 
     390    17439887 :   d = k;
     391    17439887 :   r = (ecm_uint) ((double) d * val[i] + 0.5);
     392             :   
     393             :   /* first iteration always begins by Condition 3, then a swap */
     394    17439887 :   d = k - r;
     395    17439887 :   e = 2 * r - k;
     396    17439887 :   mpres_set (xB, xA, n);
     397    17439887 :   mpres_set (zB, zA, n); /* B=A */
     398    17439887 :   mpres_set (xC, xA, n);
     399    17439887 :   mpres_set (zC, zA, n); /* C=A */
     400    17439887 :   duplicate (xA, zA, xA, zA, n, b, u, v, w); /* A = 2*A */
     401   463036741 :   while (d != e)
     402             :     {
     403   445596854 :       if (d < e)
     404             :         {
     405   327365332 :           r = d;
     406   327365332 :           d = e;
     407   327365332 :           e = r;
     408   327365332 :           mpres_swap (xA, xB, n);
     409   327365332 :           mpres_swap (zA, zB, n);
     410             :         }
     411             :       /* do the first line of Table 4 whose condition qualifies */
     412   445596854 :       if (d - e <= e / 4 && ((d + e) % 3) == 0)
     413             :         { /* condition 1 */
     414     4251087 :           d = (2 * d - e) / 3;
     415     4251087 :           e = (e - d) / 2;
     416     4251087 :           add3 (xT, zT, xA, zA, xB, zB, xC, zC, n, u, v, w); /* T = f(A,B,C) */
     417     4251087 :           add3 (xT2, zT2, xT, zT, xA, zA, xB, zB, n, u, v, w); /* T2 = f(T,A,B) */
     418     4251087 :           add3 (xB, zB, xB, zB, xT, zT, xA, zA, n, u, v, w); /* B = f(B,T,A) */
     419     4251087 :           mpres_swap (xA, xT2, n);
     420     4251087 :           mpres_swap (zA, zT2, n); /* swap A and T2 */
     421             :         }
     422   441345767 :       else if (d - e <= e / 4 && (d - e) % 6 == 0)
     423             :         { /* condition 2 */
     424      121314 :           d = (d - e) / 2;
     425      121314 :           add3 (xB, zB, xA, zA, xB, zB, xC, zC, n, u, v, w); /* B = f(A,B,C) */
     426      121314 :           duplicate (xA, zA, xA, zA, n, b, u, v, w); /* A = 2*A */
     427             :         }
     428   441224453 :       else if ((d + 3) / 4 <= e)
     429             :         { /* condition 3 */
     430   413741080 :           d -= e;
     431   413741080 :           add3 (xT, zT, xB, zB, xA, zA, xC, zC, n, u, v, w); /* T = f(B,A,C) */
     432             :           /* circular permutation (B,T,C) */
     433   413741080 :           tmp = xB;
     434   413741080 :           xB = xT;
     435   413741080 :           xT = xC;
     436   413741080 :           xC = tmp;
     437   413741080 :           tmp = zB;
     438   413741080 :           zB = zT;
     439   413741080 :           zT = zC;
     440   413741080 :           zC = tmp;
     441             :         }
     442    27483373 :       else if ((d + e) % 2 == 0)
     443             :         { /* condition 4 */
     444    19842261 :           d = (d - e) / 2;
     445    19842261 :           add3 (xB, zB, xB, zB, xA, zA, xC, zC, n, u, v, w); /* B = f(B,A,C) */
     446    19842261 :           duplicate (xA, zA, xA, zA, n, b, u, v, w); /* A = 2*A */
     447             :         }
     448             :       /* now d+e is odd */
     449     7641112 :       else if (d % 2 == 0)
     450             :         { /* condition 5 */
     451     6398731 :           d /= 2;
     452     6398731 :           add3 (xC, zC, xC, zC, xA, zA, xB, zB, n, u, v, w); /* C = f(C,A,B) */
     453     6398731 :           duplicate (xA, zA, xA, zA, n, b, u, v, w); /* A = 2*A */
     454             :         }
     455             :       /* now d is odd, e is even */
     456     1242381 :       else if (d % 3 == 0)
     457             :         { /* condition 6 */
     458      997070 :           d = d / 3 - e;
     459      997070 :           duplicate (xT, zT, xA, zA, n, b, u, v, w); /* T = 2*A */
     460      997070 :           add3 (xT2, zT2, xA, zA, xB, zB, xC, zC, n, u, v, w); /* T2 = f(A,B,C) */
     461      997070 :           add3 (xA, zA, xT, zT, xA, zA, xA, zA, n, u, v, w); /* A = f(T,A,A) */
     462      997070 :           add3 (xT, zT, xT, zT, xT2, zT2, xC, zC, n, u, v, w); /* T = f(T,T2,C) */
     463             :           /* circular permutation (C,B,T) */
     464      997070 :           tmp = xC;
     465      997070 :           xC = xB;
     466      997070 :           xB = xT;
     467      997070 :           xT = tmp;
     468      997070 :           tmp = zC;
     469      997070 :           zC = zB;
     470      997070 :           zB = zT;
     471      997070 :           zT = tmp;
     472             :         }
     473      245311 :       else if ((d + e) % 3 == 0)
     474             :         { /* condition 7 */
     475      245301 :           d = (d - 2 * e) / 3;
     476      245301 :           add3 (xT, zT, xA, zA, xB, zB, xC, zC, n, u, v, w); /* T = f(A,B,C) */
     477      245301 :           add3 (xB, zB, xT, zT, xA, zA, xB, zB, n, u, v, w); /* B = f(T,A,B) */
     478      245301 :           duplicate (xT, zT, xA, zA, n, b, u, v, w);
     479      245301 :           add3 (xA, zA, xA, zA, xT, zT, xA, zA, n, u, v, w); /* A = 3*A */
     480             :         }
     481          10 :       else if ((d - e) % 3 == 0)
     482             :         { /* condition 8 */
     483          10 :           d = (d - e) / 3;
     484          10 :           add3 (xT, zT, xA, zA, xB, zB, xC, zC, n, u, v, w); /* T = f(A,B,C) */
     485          10 :           add3 (xC, zC, xC, zC, xA, zA, xB, zB, n, u, v, w); /* C = f(A,C,B) */
     486          10 :           mpres_swap (xB, xT, n);
     487          10 :           mpres_swap (zB, zT, n); /* swap B and T */
     488          10 :           duplicate (xT, zT, xA, zA, n, b, u, v, w);
     489          10 :           add3 (xA, zA, xA, zA, xT, zT, xA, zA, n, u, v, w); /* A = 3*A */
     490             :         }
     491             :       else /* necessarily e is even here */
     492             :         { /* condition 9 */
     493           0 :           e /= 2;
     494           0 :           add3 (xC, zC, xC, zC, xB, zB, xA, zA, n, u, v, w); /* C = f(C,B,A) */
     495           0 :           duplicate (xB, zB, xB, zB, n, b, u, v, w); /* B = 2*B */
     496             :         }
     497             :     }
     498             :   
     499    17439887 :   add3 (xA, zA, xA, zA, xB, zB, xC, zC, n, u, v, w);
     500             : 
     501             :   ASSERT(d == 1);
     502    17439887 : }
     503             : 
     504             : /* Input: x is initial point
     505             :           A is curve parameter in Montgomery's form:
     506             :           g*y^2*z = x^3 + a*x^2*z + x*z^2
     507             :           n is the number to factor
     508             :           B1 is the stage 1 bound
     509             :    Output: If a factor is found, it is returned in f.
     510             :            Otherwise, x contains the x-coordinate of the point computed
     511             :            in stage 1 (with z coordinate normalized to 1).
     512             :            B1done is set to B1 if stage 1 completed normally,
     513             :            or to the largest prime processed if interrupted, but never
     514             :            to a smaller value than B1done was upon function entry.
     515             :    Return value: ECM_FACTOR_FOUND_STEP1 if a factor, otherwise 
     516             :            ECM_NO_FACTOR_FOUND
     517             : */
     518             : static int
     519         975 : ecm_stage1 (mpz_t f, mpres_t x, mpres_t A, mpmod_t n, double B1, 
     520             :             double *B1done, mpz_t go, int (*stop_asap)(void), 
     521             :             char *chkfilename)
     522             : {
     523             :   mpres_t b, z, u, v, w, xB, zB, xC, zC, xT, zT, xT2, zT2;
     524             :   uint64_t p, r, last_chkpnt_p;
     525         975 :   int ret = ECM_NO_FACTOR_FOUND;
     526             :   long last_chkpnt_time;
     527             :   prime_info_t prime_info;
     528             : 
     529         975 :   prime_info_init (prime_info);
     530             : 
     531         975 :   mpres_init (b, n);
     532         975 :   mpres_init (z, n);
     533         975 :   mpres_init (u, n);
     534         975 :   mpres_init (v, n);
     535         975 :   mpres_init (w, n);
     536         975 :   mpres_init (xB, n);
     537         975 :   mpres_init (zB, n);
     538         975 :   mpres_init (xC, n);
     539         975 :   mpres_init (zC, n);
     540         975 :   mpres_init (xT, n);
     541         975 :   mpres_init (zT, n);
     542         975 :   mpres_init (xT2, n);
     543         975 :   mpres_init (zT2, n);
     544             :   
     545         975 :   last_chkpnt_time = cputime ();
     546             : 
     547         975 :   mpres_set_ui (z, 1, n);
     548             : 
     549         975 :   mpres_add_ui (b, A, 2, n);
     550         975 :   mpres_div_2exp (b, b, 2, n); /* b == (A0+2)*B/4 */
     551             : 
     552             :   /* preload group order */
     553         975 :   if (go != NULL)
     554         975 :     ecm_mul (x, z, go, n, b);
     555             : 
     556             :   /* prac() wants multiplicands > 2 */
     557       11969 :   for (r = 2; r <= B1; r *= 2)
     558       10994 :     if (r > *B1done)
     559       10994 :       duplicate (x, z, x, z, n, b, u, v, w);
     560             :   
     561             :   /* We'll do 3 manually, too (that's what ecm4 did..) */
     562        7849 :   for (r = 3; r <= B1; r *= 3)
     563        6874 :     if (r > *B1done)
     564             :       {
     565        6874 :         duplicate (xB, zB, x, z, n, b, u, v, w);
     566        6874 :         add3 (x, z, x, z, xB, zB, x, z, n, u, v, w);
     567             :       }
     568             :   
     569         975 :   last_chkpnt_p = 3;
     570         975 :   p = getprime_mt (prime_info); /* Puts 3 into p. Next call gives 5 */
     571    17391227 :   for (p = getprime_mt (prime_info); p <= B1; p = getprime_mt (prime_info))
     572             :     {
     573    34830199 :       for (r = p; r <= B1; r *= p)
     574    17439887 :         if (r > *B1done)
     575    17439887 :           prac (x, z, (ecm_uint) p, n, b, u, v, w, xB, zB, xC, zC, xT,
     576             :                 zT, xT2, zT2);
     577             : 
     578    17390312 :       if (mpres_is_zero (z, n))
     579             :         {
     580          60 :           outputf (OUTPUT_VERBOSE, "Reached point at infinity, %.0f divides "
     581             :                    "group orders\n", p);
     582          60 :           break;
     583             :         }
     584             : 
     585    17390252 :       if (stop_asap != NULL && (*stop_asap) ())
     586             :         {
     587           0 :           outputf (OUTPUT_NORMAL, "Interrupted at prime %.0f\n", p);
     588           0 :           break;
     589             :         }
     590             : 
     591    17390252 :       if (chkfilename != NULL && p > last_chkpnt_p + 10000 && 
     592           0 :           elltime (last_chkpnt_time, cputime ()) > CHKPNT_PERIOD)
     593             :         {
     594           0 :           writechkfile (chkfilename, ECM_ECM, MAX(p, *B1done), n, A, x, NULL, z);
     595           0 :           last_chkpnt_p = p;
     596           0 :           last_chkpnt_time = cputime ();
     597             :         }
     598             :     }
     599             :   
     600             :   /* If stage 1 finished normally, p is the smallest prime >B1 here.
     601             :      In that case, set to B1 */
     602         975 :   if (p > B1)
     603         915 :       p = B1;
     604             :   
     605         975 :   if (p > *B1done)
     606         975 :       *B1done = p;
     607             : 
     608         975 :   if (chkfilename != NULL)
     609          10 :     writechkfile (chkfilename, ECM_ECM, *B1done, n, A, x, NULL, z);
     610             : 
     611         975 :   prime_info_clear (prime_info);
     612             : 
     613         975 :   if (!mpres_invert (u, z, n)) /* Factor found? */
     614             :     {
     615         222 :       mpres_gcd (f, z, n);
     616         222 :       ret = ECM_FACTOR_FOUND_STEP1;
     617             :     }
     618         975 :   mpres_mul (x, x, u, n);
     619             : 
     620         975 :   mpres_clear (zT2, n);
     621         975 :   mpres_clear (xT2, n);
     622         975 :   mpres_clear (zT, n);
     623         975 :   mpres_clear (xT, n);
     624         975 :   mpres_clear (zC, n);
     625         975 :   mpres_clear (xC, n);
     626         975 :   mpres_clear (zB, n);
     627         975 :   mpres_clear (xB, n);
     628         975 :   mpres_clear (w, n);
     629         975 :   mpres_clear (v, n);
     630         975 :   mpres_clear (u, n);
     631         975 :   mpres_clear (z, n);
     632         975 :   mpres_clear (b, n);
     633             : 
     634         975 :   return ret;
     635             : }
     636             : 
     637             : #define DEBUG_EC_W 0
     638             : 
     639             : #ifdef HAVE_ADDLAWS
     640             : /* Input: when Etype == ECM_EC_TYPE_WEIERSTRASS*:
     641             :             (x, y) is initial point
     642             :             A is curve parameter in Weierstrass's form:
     643             :             Y^2 = X^3 + A*X + B, where B = y^2-(x^3+A*x) is implicit
     644             :           when Etype == ECM_EC_TYPE_TWISTED_HESSIAN:
     645             :             (x, y) is initial point
     646             :             A=a/d is curve parameter in Hessian form: a*X^3+Y^3+Z^3=d*X*Y*Z
     647             :           n is the number to factor
     648             :           B1 is the stage 1 bound
     649             :           batch_s = prod(p^e <= B1) if != 1
     650             :    Output: If a factor is found, it is returned in f.
     651             :            Otherwise, (x, y) contains the point computed in stage 1.
     652             :            B1done is set to B1 if stage 1 completed normally,
     653             :            or to the largest prime processed if interrupted, but never
     654             :            to a smaller value than B1done was upon function entry.
     655             :    Return value: ECM_FACTOR_FOUND_STEP1 if a factor is found, otherwise 
     656             :            ECM_NO_FACTOR_FOUND
     657             : */
     658             : static int
     659         280 : ecm_stage1_W (mpz_t f, ell_curve_t E, ell_point_t P, mpmod_t n, 
     660             :               double B1, double *B1done, mpz_t batch_s, mpz_t go, 
     661             :               int (*stop_asap)(void), char *chkfilename)
     662             : {
     663             :     mpres_t xB;
     664             :     ell_point_t Q;
     665         280 :     uint64_t p = 0, r, last_chkpnt_p;
     666         280 :     int ret = ECM_NO_FACTOR_FOUND, status;
     667             :     long last_chkpnt_time;
     668             :     prime_info_t prime_info;
     669             : 
     670         280 :     prime_info_init (prime_info);
     671             :     
     672         280 :     mpres_init (xB, n);
     673             : 
     674         280 :     ell_point_init(Q, E, n);
     675             :     
     676         280 :     last_chkpnt_time = cputime ();
     677             : 
     678             : #if DEBUG_EC_W >= 2
     679             :     gmp_printf("N:=%Zd;\n", n->orig_modulus);
     680             :     printf("E:="); ell_curve_print(E, n);
     681             :     printf("E:=[E[4], E[5]];\n");
     682             :     printf("P:="); ell_point_print(P, E, n); printf("; Q:=P;\n");
     683             : #endif
     684             :     /* preload group order */
     685         280 :     if (go != NULL){
     686         280 :         if (ell_point_mul (f, Q, go, P, E, n) == 0){
     687           0 :             ret = ECM_FACTOR_FOUND_STEP1;
     688           0 :             goto end_of_stage1_w;
     689             :         }
     690         280 :         ell_point_set(P, Q, E, n);
     691             :     }
     692             : #if DEBUG_EC_W >= 1
     693             :     gmp_printf("go:=%Zd;\n", go);
     694             :     printf("goP:="); ell_point_print(P, E, n); printf(";\n");
     695             : #endif
     696         280 :     if(mpz_cmp_ui(batch_s, 1) == 0){
     697         280 :         outputf (OUTPUT_VERBOSE, "Using traditional approach to Step 1\n");
     698        3600 :         for (r = 2; r <= B1; r *= 2)
     699        3320 :             if (r > *B1done){
     700        3320 :                 if(ell_point_duplicate (f, Q, P, E, n) == 0){
     701           0 :                     ret = ECM_FACTOR_FOUND_STEP1;
     702           0 :                     goto end_of_stage1_w;
     703             :                 }
     704        3320 :                 ell_point_set(P, Q, E, n);
     705             : #if DEBUG_EC_W >= 2
     706             :                 printf("P%ld:=", (long)r); ell_point_print(P, E, n); printf(";\n");
     707             :                 printf("Q:=EcmMult(2, Q, E, N);\n");
     708             :                 printf("(Q[1]*P%ld[3]-Q[3]*P%ld[1]) mod N;\n",(long)r,(long)r);
     709             : #endif
     710             :             }
     711             :         
     712         280 :         last_chkpnt_p = 3;
     713      364210 :         for (p = getprime_mt (prime_info); p <= B1; p = getprime_mt (prime_info)){
     714      739250 :             for (r = p; r <= B1; r *= p){
     715      375280 :                 if (r > *B1done){
     716      375280 :                     mpz_set_ui(f, (ecm_uint)p);
     717      375280 :                     status = ell_point_mul (f, Q, f, P, E, n);
     718      375280 :                     if(status == 0){
     719             :                     }
     720      375240 :                     else if(E->law == ECM_LAW_HOMOGENEOUS){
     721      257570 :                         if(E->type == ECM_EC_TYPE_TWISTED_HESSIAN)
     722       79430 :                             mpres_gcd(f, Q->x, n);
     723             :                         else
     724      178140 :                             mpres_gcd(f, Q->z, n);
     725             :                         //                      gmp_printf("gcd=%Zd\n", f);
     726      257570 :                         if(mpz_cmp(f, n->orig_modulus) < 0 
     727      257260 :                            && mpz_cmp_ui(f, 1) > 0)
     728         110 :                             status = 0;
     729             :                     }
     730      375280 :                     if(status == 0){
     731         150 :                         ret = ECM_FACTOR_FOUND_STEP1;
     732         150 :                         goto end_of_stage1_w;
     733             :                     }
     734             : #if DEBUG_EC_W >= 2
     735             :                     printf("R%ld:=", (long)r); ell_point_print(Q, E, n);
     736             :                     printf(";\nQ:=EcmMult(%ld, Q, E, N);\n", (long)p);
     737             :                     printf("(Q[1]*R%ld[3]-Q[3]*R%ld[1]) mod N;\n",(long)r,(long)r);
     738             : #endif
     739      375130 :                     ell_point_set(P, Q, E, n);
     740             :                 }
     741             :             }
     742      363970 :             if (ell_point_is_zero (P, E, n)){
     743          40 :                 outputf (OUTPUT_VERBOSE, "Reached point at infinity, "
     744             :                          "%.0f divides group orders\n", p);
     745          40 :                 break;
     746             :             }
     747             :             
     748      363930 :             if (stop_asap != NULL && (*stop_asap) ()){
     749           0 :                 outputf (OUTPUT_NORMAL, "Interrupted at prime %.0f\n", p);
     750           0 :                 break;
     751             :             }
     752             :             
     753      363930 :             if (chkfilename != NULL && p > last_chkpnt_p + 10000 && 
     754           0 :                 elltime (last_chkpnt_time, cputime ()) > CHKPNT_PERIOD){
     755           0 :                 writechkfile (chkfilename, ECM_ECM, MAX(p, *B1done), 
     756           0 :                               n, E->a4, P->x, P->y, P->z);
     757           0 :                 last_chkpnt_p = p;
     758           0 :                 last_chkpnt_time = cputime ();
     759             :             }
     760             :         }
     761             :     }
     762             :     else{
     763             : #if USE_ADD_SUB_CHAINS == 0 /* keeping it simple */
     764           0 :         if (ell_point_mul (f, Q, batch_s, P, E, n) == 0){
     765           0 :             ret = ECM_FACTOR_FOUND_STEP1;
     766           0 :             goto end_of_stage1_w;
     767             :         }
     768             : #else
     769             :         /* batch mode and special coding... */
     770             :         short *S = NULL;
     771             :         size_t iS;
     772             :         int w;
     773             :         add_sub_unpack(&w, &S, &iS, batch_s);
     774             :         if (ell_point_mul_add_sub_with_S(f, Q, P, E, n, w, S, iS) == 0){
     775             :             ret = ECM_FACTOR_FOUND_STEP1;
     776             :         }
     777             : #endif
     778           0 :         ell_point_set(P, Q, E, n);
     779           0 :         p = B1;
     780             :     }
     781         280 :  end_of_stage1_w:
     782             :     /* If stage 1 finished normally, p is the smallest prime > B1 here.
     783             :        In that case, set to B1 */
     784         280 :     if (p > B1)
     785          90 :         p = B1;
     786             :     
     787         280 :     if (p > *B1done)
     788         280 :         *B1done = p;
     789             :     
     790         280 :     if (chkfilename != NULL)
     791           0 :         writechkfile (chkfilename, ECM_ECM, *B1done, n, E->a4, P->x, P->y,P->z);
     792         280 :     prime_info_clear (prime_info);
     793             : #if DEBUG_EC_W >= 2
     794             :     printf("lastP="); ell_point_print(P, E, n); printf("\n");
     795             : #endif
     796         280 :     if(ret != ECM_FACTOR_FOUND_STEP1){
     797         130 :         if(ell_point_is_zero(P, E, n) == 1){
     798             :             /* too bad */
     799          40 :             ell_point_set_to_zero(P, E, n);
     800          40 :             mpz_set(f, n->orig_modulus);
     801          40 :             ret = ECM_FACTOR_FOUND_STEP1;
     802             :         }
     803             :         else{
     804             :             /* for affine case, z = 1 anyway */
     805          90 :             if(E->law == ECM_LAW_HOMOGENEOUS){
     806          60 :                 if (!mpres_invert (xB, P->z, n)){ /* Factor found? */
     807           0 :                     mpres_gcd (f, P->z, n);
     808           0 :                     gmp_printf("# factor found during normalization: %Zd\n", f);
     809           0 :                     ret = ECM_FACTOR_FOUND_STEP1;
     810             :                 }
     811             :                 else{
     812             :                     /* normalize to get (x:y:1) valid in W or H form... */
     813             : #if DEBUG_EC_W >= 2
     814             :                     mpres_get_z(f, xB, n); gmp_printf("1/z=%Zd\n", f);
     815             : #endif
     816          60 :                     mpres_mul (P->x, P->x, xB, n);
     817          60 :                     mpres_mul (P->y, P->y, xB, n);
     818             : #if DEBUG_EC_W >= 2
     819             :                     mpres_get_z(f, P->x, n); gmp_printf("x/z=%Zd\n", f);
     820             :                     mpres_get_z(f, P->y, n); gmp_printf("y/z=%Zd\n", f);
     821             : #endif
     822          60 :                     mpres_set_ui (P->z, 1, n);
     823             :                 }
     824             :             }
     825             :         }
     826             :     }
     827             : 
     828         280 :     mpres_clear (xB, n);
     829         280 :     ell_point_clear(Q, E, n);
     830             :     
     831         280 :     return ret;
     832             : }
     833             : #endif
     834             : 
     835             : /* choose "optimal" S according to step 2 range B2 */
     836             : int
     837        1524 : choose_S (mpz_t B2len)
     838             : {
     839        1524 :   if (mpz_cmp_d (B2len, 1e7) < 0)
     840        1133 :     return 1;   /* x^1 */
     841         391 :   else if (mpz_cmp_d (B2len, 1e8) < 0)
     842         281 :     return 2;   /* x^2 */
     843         110 :   else if (mpz_cmp_d (B2len, 1e9) < 0)
     844          53 :     return -3;  /* Dickson(3) */
     845          57 :   else if (mpz_cmp_d (B2len, 1e10) < 0)
     846          46 :     return -6;  /* Dickson(6) */
     847          11 :   else if (mpz_cmp_d (B2len, 3e11) < 0)
     848          10 :     return -12; /* Dickson(12) */
     849             :   else
     850           1 :     return -30; /* Dickson(30) */
     851             : }
     852             : 
     853             : #define DIGITS_START 35
     854             : #define DIGITS_INCR   5
     855             : #define DIGITS_END   80
     856             : 
     857             : void
     858          57 : print_expcurves (double B1, const mpz_t B2, unsigned long dF, unsigned long k, 
     859             :                  int S, int param)
     860             : {
     861             :   double prob;
     862             :   int i, j;
     863             :   char sep, outs[128], flt[16];
     864             :   double smoothness_correction;
     865             : 
     866          57 :   if (param == ECM_PARAM_SUYAMA || param == ECM_PARAM_BATCH_2)
     867          40 :       smoothness_correction = 1.0; 
     868          17 :   else if (param == ECM_PARAM_BATCH_SQUARE)
     869          17 :       smoothness_correction = EXTRA_SMOOTHNESS_SQUARE;
     870           0 :   else if (param == ECM_PARAM_BATCH_32BITS_D)
     871           0 :       smoothness_correction = EXTRA_SMOOTHNESS_32BITS_D;
     872             :   else /* This case should never happen */
     873           0 :       smoothness_correction = 0.0; 
     874             : 
     875         627 :   for (i = DIGITS_START, j = 0; i <= DIGITS_END; i += DIGITS_INCR)
     876         570 :     j += sprintf (outs + j, "%u%c", i, (i < DIGITS_END) ? '\t' : '\n');
     877          57 :   outs[j] = '\0';
     878          57 :   outputf (OUTPUT_VERBOSE, "Expected number of curves to find a factor "
     879             :            "of n digits (assuming one exists):\n%s", outs);
     880         627 :   for (i = DIGITS_START; i <= DIGITS_END; i += DIGITS_INCR)
     881             :     {
     882         570 :       sep = (i < DIGITS_END) ? '\t' : '\n';
     883         570 :       prob = ecmprob (B1, mpz_get_d (B2),
     884             :                       /* smoothness depends on the parametrization */
     885         570 :                       pow (10., i - .5) / smoothness_correction,
     886         570 :                       (double) dF * dF * k, S);
     887         570 :       if (prob > 1. / 10000000)
     888          40 :         outputf (OUTPUT_VERBOSE, "%.0f%c", floor (1. / prob + .5), sep);
     889         530 :       else if (prob > 0.)
     890             :         {
     891             :           /* on Windows: 2.6e+009   or   2.6e+025  (8 characters in string) */
     892             :           /* on Linux  : 2.6e+09    or   2.6e+25   (7 characters in string) */
     893             :           /* This will normalize the output so that the Windows ouptut will match the Linux output */
     894          64 :           if (sprintf (flt, "%.2g", floor (1. / prob + .5)) == 8)
     895           0 :             memmove (&flt[5], &flt[6], strlen(flt) - 5);
     896          64 :           outputf (OUTPUT_VERBOSE, "%s%c", flt, sep);
     897             :         }
     898             :       else
     899         466 :         outputf (OUTPUT_VERBOSE, "Inf%c", sep);
     900             :     }
     901          57 : }
     902             : 
     903             : void
     904           9 : print_exptime (double B1, const mpz_t B2, unsigned long dF, unsigned long k, 
     905             :                int S, double tottime, int param)
     906             : {
     907             :   double prob, exptime;
     908             :   int i, j;
     909             :   char sep, outs[128];
     910             :   double smoothness_correction;
     911             : 
     912           9 :   if (param == ECM_PARAM_SUYAMA || param == ECM_PARAM_BATCH_2)
     913           0 :       smoothness_correction = 1.0; 
     914           9 :   else if (param == ECM_PARAM_BATCH_SQUARE)
     915           9 :       smoothness_correction = EXTRA_SMOOTHNESS_SQUARE;
     916           0 :   else if (param == ECM_PARAM_BATCH_32BITS_D)
     917           0 :       smoothness_correction = EXTRA_SMOOTHNESS_32BITS_D;
     918             :   else /* This case should never happen */
     919           0 :       smoothness_correction = 0.0; 
     920             :   
     921          99 :   for (i = DIGITS_START, j = 0; i <= DIGITS_END; i += DIGITS_INCR)
     922          90 :     j += sprintf (outs + j, "%u%c", i, (i < DIGITS_END) ? '\t' : '\n');
     923           9 :   outs[j] = '\0';
     924           9 :   outputf (OUTPUT_VERBOSE, "Expected time to find a factor of n digits:\n%s",
     925             :            outs);
     926          99 :   for (i = DIGITS_START; i <= DIGITS_END; i += DIGITS_INCR)
     927             :     {
     928          90 :       sep = (i < DIGITS_END) ? '\t' : '\n';
     929          90 :       prob = ecmprob (B1, mpz_get_d (B2),
     930             :                       /* in batch mode, the extra smoothness is smaller */
     931          90 :                       pow (10., i - .5) / smoothness_correction,
     932          90 :                       (double) dF * dF * k, S);
     933          90 :       exptime = (prob > 0.) ? tottime / prob : HUGE_VAL;
     934          90 :       outputf (OUTPUT_TRACE, "Digits: %d, Total time: %.0f, probability: "
     935             :                "%g, expected time: %.0f\n", i, tottime, prob, exptime);
     936          90 :       if (exptime < 1000.)
     937           0 :         outputf (OUTPUT_VERBOSE, "%.0fms%c", exptime, sep);
     938          90 :       else if (exptime < 60000.) /* One minute */
     939           0 :         outputf (OUTPUT_VERBOSE, "%.2fs%c", exptime / 1000., sep);
     940          90 :       else if (exptime < 3600000.) /* One hour */
     941           0 :         outputf (OUTPUT_VERBOSE, "%.2fm%c", exptime / 60000., sep);
     942          90 :       else if (exptime < 86400000.) /* One day */
     943           9 :         outputf (OUTPUT_VERBOSE, "%.2fh%c", exptime / 3600000., sep);
     944          81 :       else if (exptime < 31536000000.) /* One year */
     945          23 :         outputf (OUTPUT_VERBOSE, "%.2fd%c", exptime / 86400000., sep);
     946          58 :       else if (exptime < 31536000000000.) /* One thousand years */
     947          16 :         outputf (OUTPUT_VERBOSE, "%.2fy%c", exptime / 31536000000., sep);
     948          42 :       else if (exptime < 31536000000000000.) /* One million years */
     949          16 :         outputf (OUTPUT_VERBOSE, "%.0fy%c", exptime / 31536000000., sep);
     950          26 :       else if (prob > 0.)
     951          16 :         outputf (OUTPUT_VERBOSE, "%.1gy%c", exptime / 31536000000., sep);
     952             :       else 
     953          10 :         outputf (OUTPUT_VERBOSE, "Inf%c", sep);
     954             :     }
     955           9 : }
     956             : 
     957             : /* y should be NULL for P+1, and P-1, it contains the y coordinate for the
     958             :    Weierstrass form for ECM (when sigma_is_A = -1). */
     959             : void
     960        2021 : print_B1_B2_poly (int verbosity, int method, double B1, double B1done, 
     961             :                   mpz_t B2min_param, mpz_t B2min, mpz_t B2, int S, mpz_t sigma,
     962             :                   int sigma_is_A, int Etype, 
     963             :                   mpz_t y, int param, unsigned int nb_curves)
     964             : {
     965             :   ASSERT ((method == ECM_ECM) || (y == NULL));
     966             :   ASSERT ((-1 <= sigma_is_A) && (sigma_is_A <= 1));
     967             :   ASSERT (param != ECM_PARAM_DEFAULT || sigma_is_A == 1 || sigma_is_A == -1);
     968             : 
     969        2021 :   if (test_verbose (verbosity))
     970             :   {
     971        2001 :       outputf (verbosity, "Using ");
     972        2001 :       if (ECM_IS_DEFAULT_B1_DONE(B1done))
     973        1906 :           outputf (verbosity, "B1=%1.0f, ", B1);
     974             :       else
     975          95 :           outputf (verbosity, "B1=%1.0f-%1.0f, ", B1done, B1);
     976        2001 :       if (mpz_sgn (B2min_param) < 0)
     977        1825 :           outputf (verbosity, "B2=%Zd", B2);
     978             :       else
     979         176 :           outputf (verbosity, "B2=%Zd-%Zd", B2min, B2);
     980             :       
     981        2001 :       if (S > 0)
     982        1891 :           outputf (verbosity, ", polynomial x^%u", S);
     983         110 :       else if (S < 0)
     984         110 :           outputf (verbosity, ", polynomial Dickson(%u)", -S);
     985             :       
     986             :       /* don't print in resume case, since x0 is saved in resume file */
     987        2001 :       if (method == ECM_ECM)
     988             :         {
     989        1470 :             if (sigma_is_A == 1)
     990          86 :                 outputf (verbosity, ", A=%Zd", sigma);
     991        1384 :             else if (sigma_is_A == 0)
     992             :               {
     993        1074 :                 if (nb_curves > 1) 
     994             :                   {
     995           0 :                     outputf (verbosity, ", sigma=%d:%Zd", param, sigma);
     996           0 :                     mpz_add_ui (sigma, sigma, nb_curves-1);
     997           0 :                     outputf (verbosity, "-%d:%Zd", param, sigma);
     998           0 :                     mpz_sub_ui (sigma, sigma, nb_curves-1);
     999           0 :                     outputf (verbosity, " (%u curves)", nb_curves);
    1000             :                   }
    1001             :                 else
    1002        1074 :                     outputf (verbosity, ", sigma=%d:%Zd", param, sigma);
    1003             :               }
    1004             :             else{
    1005         310 :                 if (Etype == ECM_EC_TYPE_WEIERSTRASS)
    1006         190 :                   outputf (verbosity, ", Weierstrass(A=%Zd,y=%Zd)", sigma, y);
    1007         120 :                 else if (Etype == ECM_EC_TYPE_HESSIAN)
    1008          70 :                   outputf (verbosity, ", Hessian(D=%Zd,y=%Zd)", sigma, y);
    1009          50 :                 else if (Etype == ECM_EC_TYPE_TWISTED_HESSIAN)
    1010          30 :                     outputf (verbosity, ", twisted Hessian(y=%Zd)", y);
    1011             :             }
    1012             :         }
    1013         531 :       else if (ECM_IS_DEFAULT_B1_DONE(B1done))
    1014             :         /* in case of P-1 or P+1, we store the initial point in sigma */
    1015         486 :         outputf (verbosity, ", x0=%Zd", sigma);
    1016             :       
    1017        2001 :       outputf (verbosity, "\n");
    1018             :   }
    1019        2021 : }
    1020             : 
    1021             : /* Compute parameters for stage 2 */
    1022             : int
    1023        1566 : set_stage_2_params (mpz_t B2, mpz_t B2_parm, mpz_t B2min, mpz_t B2min_parm, 
    1024             :                     root_params_t *root_params, double B1,
    1025             :                     unsigned long *k, const int S, int use_ntt, int *po2,
    1026             :                     unsigned long *dF, char *TreeFilename, double maxmem, 
    1027             :                     int Fermat, mpmod_t modulus)
    1028             : {
    1029        1566 :   mpz_set (B2min, B2min_parm);
    1030        1566 :   mpz_set (B2, B2_parm);
    1031             :   
    1032        1566 :   mpz_init (root_params->i0);
    1033             : 
    1034             :   /* set second stage bound B2: when using polynomial multiplication of
    1035             :      complexity n^alpha, stage 2 has complexity about B2^(alpha/2), and
    1036             :      we want stage 2 to take about half of stage 1, thus we choose
    1037             :      B2 = (c*B1)^(2/alpha). Experimentally, c=1/4 seems to work well.
    1038             :      For Toom-Cook 3, this gives alpha=log(5)/log(3), and B2 ~ (c*B1)^1.365.
    1039             :      For Toom-Cook 4, this gives alpha=log(7)/log(4), and B2 ~ (c*B1)^1.424. */
    1040             : 
    1041             :   /* We take the cost of P+1 stage 1 to be about twice that of P-1.
    1042             :      Since nai"ve P+1 and ECM cost respectively 2 and 11 multiplies per
    1043             :      addition and duplicate, and both are optimized with PRAC, we can
    1044             :      assume the ratio remains about 11/2. */
    1045             : 
    1046             :   /* Also scale B2 by what the user said (or by the default scaling of 1.0) */
    1047             : 
    1048        1566 :   if (ECM_IS_DEFAULT_B2(B2))
    1049         939 :     mpz_set_d (B2, pow (ECM_COST * B1, DEFAULT_B2_EXPONENT));
    1050             : 
    1051             :   /* set B2min */
    1052        1566 :   if (mpz_sgn (B2min) < 0)
    1053        1430 :     mpz_set_d (B2min, B1);
    1054             : 
    1055             :   /* Let bestD determine parameters for root generation and the 
    1056             :      effective B2 */
    1057             : 
    1058        1566 :   if (use_ntt)
    1059        1393 :     *po2 = 1;
    1060             : 
    1061        1566 :   root_params->d2 = 0; /* Enable automatic choice of d2 */
    1062        1566 :   if (bestD (root_params, k, dF, B2min, B2, *po2, use_ntt, maxmem, 
    1063             :              (TreeFilename != NULL), modulus) == ECM_ERROR)
    1064          20 :     return ECM_ERROR;
    1065             : 
    1066             :   /* Set default degree for Brent-Suyama extension */
    1067             :   /* We try to keep the time used by the Brent-Suyama extension
    1068             :      at about 10% of the stage 2 time */
    1069             :   /* Degree S Dickson polys and x^S are equally fast for ECM, so we go for
    1070             :      the better Dickson polys whenever possible. For S == 1, 2, they behave
    1071             :      identically. */
    1072             : 
    1073        1546 :   root_params->S = S;
    1074        1546 :   if (root_params->S == ECM_DEFAULT_S)
    1075             :     {
    1076        1536 :       if (Fermat > 0)
    1077             :         {
    1078             :           /* For Fermat numbers, default is 1 (no Brent-Suyama) */
    1079          12 :           root_params->S = 1;
    1080             :         }
    1081             :       else
    1082             :         {
    1083             :           mpz_t t;
    1084        1524 :           mpz_init (t);
    1085        1524 :           mpz_sub (t, B2, B2min);
    1086        1524 :           root_params->S = choose_S (t);
    1087        1524 :           mpz_clear (t);
    1088             :         }
    1089             :     }
    1090        1546 :   return ECM_NO_FACTOR_FOUND;
    1091             : }
    1092             : 
    1093             : /* Input: x is starting point or zero
    1094             :           y is used for Weierstrass curves (even in Step1)
    1095             :           sigma is sigma value (if x is set to zero) or 
    1096             :             A parameter (if x is non-zero) of curve
    1097             :           n is the number to factor
    1098             :           go is the initial group order to preload  
    1099             :           B1, B2 are the stage 1/stage 2 bounds, respectively
    1100             :           B2min the lower bound for stage 2
    1101             :           k is the number of blocks to do in stage 2
    1102             :           S is the degree of the Suyama-Brent extension for stage 2
    1103             :           verbose is verbosity level: 0 no output, 1 normal output,
    1104             :             2 diagnostic output.
    1105             :           sigma_is_A: If true, the sigma parameter contains the curve's A value
    1106             :           Etype
    1107             :           zE is a curve that is used when a special torsion group was used; in
    1108             :             that case, (x, y) must be a point on E.
    1109             :    Output: f is the factor found.
    1110             :    Return value: ECM_FACTOR_FOUND_STEPn if a factor was found,
    1111             :                  ECM_NO_FACTOR_FOUND if no factor was found,
    1112             :                  ECM_ERROR in case of error.
    1113             :    (x, y) contains the new point at the end of Stage 1.
    1114             : */
    1115             : int
    1116        1588 : ecm (mpz_t f, mpz_t x, mpz_t y, int param, mpz_t sigma, mpz_t n, mpz_t go, 
    1117             :      double *B1done, double B1, mpz_t B2min_parm, mpz_t B2_parm,
    1118             :      unsigned long k, const int S, int verbose, int repr, int nobase2step2, 
    1119             :      int use_ntt, int sigma_is_A, ell_curve_t zE,
    1120             :      FILE *os, FILE* es, char *chkfilename, char
    1121             :      *TreeFilename, double maxmem, double stage1time, gmp_randstate_t rng, int
    1122             :      (*stop_asap)(void), mpz_t batch_s, double *batch_last_B1_used,
    1123             :      ATTRIBUTE_UNUSED double gw_k, ATTRIBUTE_UNUSED unsigned long gw_b,
    1124             :      ATTRIBUTE_UNUSED unsigned long gw_n, ATTRIBUTE_UNUSED signed long gw_c)
    1125             : {
    1126        1588 :   int youpi = ECM_NO_FACTOR_FOUND;
    1127        1588 :   int base2 = 0;  /* If n is of form 2^n[+-]1, set base to [+-]n */
    1128        1588 :   int Fermat = 0; /* If base2 > 0 is a power of 2, set Fermat to base2 */
    1129        1588 :   int po2 = 0;    /* Whether we should use power-of-2 poly degree */
    1130             :   long st;
    1131             :   mpmod_t modulus;
    1132             :   curve P;
    1133             :   ell_curve_t E;
    1134             : #ifdef HAVE_ADDLAWS
    1135             :   ell_point_t PE;
    1136             : #endif
    1137             :   mpz_t B2min, B2; /* Local B2, B2min to avoid changing caller's values */
    1138             :   unsigned long dF;
    1139             :   root_params_t root_params;
    1140             : 
    1141             :   /*  1: sigma contains A from Montgomery form By^2 = x^3 + Ax^2 + x
    1142             :       0: sigma contains sigma
    1143             :      -1: sigma contains A from Weierstrass form y^2 = x^3 + Ax + B,
    1144             :          and y contains y */
    1145             :   ASSERT((-1 <= sigma_is_A) && (sigma_is_A <= 1));
    1146             :   ASSERT((GMP_NUMB_BITS == 32) || (GMP_NUMB_BITS == 64));
    1147             : 
    1148        1588 :   set_verbose (verbose);
    1149        1588 :   ECM_STDOUT = (os == NULL) ? stdout : os;
    1150        1588 :   ECM_STDERR = (es == NULL) ? stdout : es;
    1151             : 
    1152             : #ifdef MPRESN_NO_ADJUSTMENT
    1153             :   /* When no adjustment is made in mpresn_ functions, N should be smaller
    1154             :      than B^n/16 */
    1155             :   if (mpz_sizeinbase (n, 2) > mpz_size (n) * GMP_NUMB_BITS - 4)
    1156             :     {
    1157             :       outputf (OUTPUT_ERROR, "Error, N should be smaller than B^n/16\n");
    1158             :       return ECM_ERROR;
    1159             :     }
    1160             : #endif
    1161             : 
    1162             :   /* if a batch mode is requested by the user, this implies ECM_MOD_MODMULN */
    1163        1588 :   if (repr == ECM_MOD_DEFAULT && IS_BATCH_MODE(param))
    1164         154 :     repr = ECM_MOD_MODMULN;
    1165             : 
    1166             :   /* choose the arithmetic used before the parametrization, since for divisors
    1167             :      of 2^n+/-1 the default choice param=1 might not be optimal */
    1168        1588 :   if (mpmod_init (modulus, n, repr) != 0)
    1169          10 :     return ECM_ERROR;
    1170             : 
    1171        1578 :   repr = modulus->repr;
    1172             : 
    1173             :   /* If the parametrization is not given, choose it. */
    1174        1578 :   if (param == ECM_PARAM_DEFAULT)
    1175          41 :     param = get_default_param (sigma_is_A, *B1done, repr);
    1176             :   /* when dealing with several input numbers, if we had already computed
    1177             :      batch_s, but the new number uses the base-2 representation, then we
    1178             :      are forced to use ECM_PARAM_SUYAMA, and we reset batch_s to 1 to avoid
    1179             :      the error "-bsaves/-bloads makes sense in batch mode only" below */
    1180        1578 :   if (param == ECM_PARAM_SUYAMA)
    1181        1065 :     mpz_set_ui (batch_s, 1);
    1182             : 
    1183             :   /* In batch mode, 
    1184             :         we force repr=MODMULN, 
    1185             :         B1done should be either the default value or greater than B1 
    1186             :         x should be either 0 (undetermined) or 2 */
    1187        1578 :   if (IS_BATCH_MODE(param))
    1188             :     {
    1189         183 :       if (repr != ECM_MOD_MODMULN)
    1190             :         {
    1191           4 :           outputf (OUTPUT_ERROR, "Error, with param %d, repr should be " 
    1192             :                                  "ECM_MOD_MODMULN.\n", param);
    1193           4 :           return ECM_ERROR;
    1194             :         }
    1195             : 
    1196         179 :       if (!ECM_IS_DEFAULT_B1_DONE(*B1done) && *B1done < B1)
    1197             :         {
    1198           0 :           outputf (OUTPUT_ERROR, "Error, cannot resume with param %d, except " 
    1199             :                                  "for doing only stage 2\n", param);
    1200           0 :           return ECM_ERROR;
    1201             :         }
    1202             : 
    1203         179 :       if (sigma_is_A >= 0 && mpz_sgn (x) != 0 && mpz_cmp_ui (x, 2) != 0)
    1204             :         {
    1205           8 :           if (ECM_IS_DEFAULT_B1_DONE(*B1done))
    1206             :             {
    1207           8 :               outputf (OUTPUT_ERROR, "Error, x0 should be equal to 2 with this "
    1208             :                                      "parametrization\n");
    1209           8 :               return ECM_ERROR;
    1210             :             }
    1211             :         }
    1212             :     }
    1213             : 
    1214             :   /* check that if ECM_PARAM_BATCH_SQUARE is used, GMP_NUMB_BITS == 64 */
    1215             :   if (param == ECM_PARAM_BATCH_SQUARE && GMP_NUMB_BITS == 32)
    1216             :     {
    1217             :       outputf (OUTPUT_ERROR, "Error, parametrization ECM_PARAM_BATCH_SQUARE "
    1218             :                              "works only with GMP_NUMB_BITS=64\n");
    1219             :       return ECM_ERROR;
    1220             :     }
    1221             : 
    1222             :   /* check that B1 is not too large */
    1223        1566 :   if (B1 > (double) ECM_UINT_MAX)
    1224             :     {
    1225           0 :       outputf (OUTPUT_ERROR, "Error, maximal step 1 bound for ECM is %lu.\n", 
    1226             :                ECM_UINT_MAX);
    1227           0 :       return ECM_ERROR;
    1228             :     }
    1229             : 
    1230             :   /* See what kind of number we have as that may influence optimal parameter 
    1231             :      selection. Test for base 2 number. Note: this was already done by
    1232             :      mpmod_init. */
    1233             : 
    1234        1566 :   if (modulus->repr == ECM_MOD_BASE2)
    1235         161 :     base2 = modulus->bits;
    1236             : 
    1237             :   /* For a Fermat number (base2 a positive power of 2) */
    1238        1663 :   for (Fermat = base2; Fermat > 0 && (Fermat & 1) == 0; Fermat >>= 1);
    1239        1566 :   if (Fermat == 1) 
    1240             :     {
    1241          12 :       Fermat = base2;
    1242          12 :       po2 = 1;
    1243             :     }
    1244             :   else
    1245        1554 :       Fermat = 0;
    1246             : 
    1247        1566 :   mpres_init (P.x, modulus);
    1248        1566 :   mpres_init (P.y, modulus);
    1249        1566 :   mpres_init (P.A, modulus);
    1250             : 
    1251             : #ifdef HAVE_ADDLAWS
    1252        1566 :   ell_curve_set_z (E, zE, modulus);
    1253             : #else
    1254             :   E->type = ECM_EC_TYPE_MONTGOMERY;
    1255             : #endif
    1256             : 
    1257        1566 :   mpz_init (B2);
    1258        1566 :   mpz_init (B2min);
    1259        1566 :   youpi = set_stage_2_params (B2, B2_parm, B2min, B2min_parm,
    1260             :                               &root_params, B1, &k, S, use_ntt,
    1261             :                               &po2, &dF, TreeFilename, maxmem, Fermat,modulus);
    1262             : 
    1263             :   /* if the user gave B2, print that B2 on the Using B1=..., B2=... line */
    1264        1566 :   if(!ECM_IS_DEFAULT_B2(B2_parm))
    1265         627 :     mpz_set (B2, B2_parm);
    1266             : 
    1267        1566 :   if (youpi == ECM_ERROR)
    1268          20 :       goto end_of_ecm;
    1269             : 
    1270        1546 :   if (sigma_is_A == 0)
    1271             :     {
    1272        1140 :       if (mpz_sgn (sigma) == 0)
    1273             :         {
    1274          29 :           youpi = get_curve_from_random_parameter (f, P.A, P.x, sigma, param,
    1275             :                                                    modulus, rng);
    1276             : 
    1277          29 :           if (youpi == ECM_ERROR)
    1278             :             {
    1279          10 :               outputf (OUTPUT_ERROR, "Error, invalid parametrization.\n");
    1280          10 :                     goto end_of_ecm;
    1281             :             }
    1282             :         }
    1283             :       else /* Compute A and x0 from given sigma values */
    1284             :         {
    1285        1111 :           if (param == ECM_PARAM_SUYAMA)
    1286        1007 :               youpi = get_curve_from_param0 (f, P.A, P.x, sigma, modulus);
    1287         104 :           else if (param == ECM_PARAM_BATCH_SQUARE)
    1288          16 :               youpi = get_curve_from_param1 (P.A, P.x, sigma, modulus);
    1289          88 :           else if (param == ECM_PARAM_BATCH_2)
    1290          56 :               youpi = get_curve_from_param2 (f, P.A, P.x, sigma, modulus);
    1291          32 :           else if (param == ECM_PARAM_BATCH_32BITS_D)
    1292          32 :               youpi = get_curve_from_param3 (P.A, P.x, sigma, modulus);
    1293             :           else
    1294             :             {
    1295           0 :               outputf (OUTPUT_ERROR, "Error, invalid parametrization.\n");
    1296           0 :               youpi = ECM_ERROR;
    1297           0 :                     goto end_of_ecm;
    1298             :             }
    1299             :       
    1300        1111 :           if (youpi != ECM_NO_FACTOR_FOUND)
    1301             :             {
    1302          36 :               if (youpi == ECM_ERROR)
    1303           0 :                   outputf (OUTPUT_ERROR, "Error, invalid value of sigma.\n");
    1304             : 
    1305          36 :                     goto end_of_ecm;
    1306             :             }
    1307             :         }
    1308             :     }
    1309         406 :   else if (sigma_is_A == 1)
    1310             :     {
    1311             :       /* sigma contains the A value */
    1312          96 :       mpres_set_z (P.A, sigma, modulus);
    1313             :       /* TODO: make a valid, random starting point in case none was given */
    1314             :       /* Problem: this may be as hard as factoring as we'd need to determine
    1315             :          whether x^3 + a*x^2 + x is a quadratic residue or not */
    1316             :       /* For now, we'll just chicken out. */
    1317             :       /* Except for batch mode where we know that x0=2 */
    1318          96 :       if (mpz_sgn (x) == 0)
    1319             :         {
    1320          66 :           if (IS_BATCH_MODE(param))
    1321          56 :             mpres_set_ui (P.x, 2, modulus);
    1322             :           else
    1323             :             {
    1324          10 :               outputf (OUTPUT_ERROR, 
    1325             :                           "Error, -A requires a starting point (-x0 x).\n");
    1326          10 :               youpi = ECM_ERROR;
    1327          10 :                     goto end_of_ecm;
    1328             :             }
    1329             :         }
    1330             :       else
    1331          30 :           mpres_set_z (P.x, x, modulus);
    1332             :     }
    1333             : 
    1334             :   /* Print B1, B2, polynomial and sigma */
    1335        1490 :   print_B1_B2_poly (OUTPUT_NORMAL, ECM_ECM, B1, *B1done, B2min_parm, B2min, 
    1336             :                     B2, root_params.S, sigma, sigma_is_A, E->type,
    1337             :                     y, param, 0);
    1338             : 
    1339             : #if 0
    1340             :   outputf (OUTPUT_VERBOSE, "b2=%1.0f, dF=%lu, k=%lu, d=%lu, d2=%lu, i0=%Zd\n", 
    1341             :            b2, dF, k, root_params.d1, root_params.d2, root_params.i0);
    1342             : #else
    1343        1490 :   outputf (OUTPUT_VERBOSE, "dF=%lu, k=%lu, d=%lu, d2=%lu, i0=%Zd\n", 
    1344             :            dF, k, root_params.d1, root_params.d2, root_params.i0);
    1345             : #endif
    1346             : 
    1347        1490 :   if (sigma_is_A == -1) /* Weierstrass or Hessian form. 
    1348             :                            It is known that all curves in Weierstrass form do
    1349             :                            not admit a Montgomery form. However, we could
    1350             :                            be interested in performing some plain Step 1
    1351             :                            on some special curves.
    1352             :                         */
    1353             :     {
    1354         310 :         if (param != ECM_PARAM_TORSION)
    1355             :           {
    1356         180 :               mpres_set_z (P.A, sigma, modulus); /* sigma contains A */
    1357         180 :               mpres_set_z (P.x, x,    modulus);
    1358         180 :               mpres_set_z (P.y, y,    modulus);
    1359             :           }
    1360             :         else
    1361             :           {
    1362             : #ifdef HAVE_ADDLAWS
    1363         130 :               if(E->type == ECM_EC_TYPE_WEIERSTRASS)
    1364             : #endif
    1365          70 :               mpres_set_z(P.A, zE->a4, modulus);
    1366             : #ifdef HAVE_ADDLAWS
    1367          60 :               else if(E->type == ECM_EC_TYPE_MONTGOMERY)
    1368          20 :                   mpres_set_z(P.A, zE->a2, modulus);
    1369             : #endif
    1370         130 :               mpres_set_z (P.x, x, modulus);
    1371         130 :               mpres_set_z (P.y, y, modulus);
    1372             :           }
    1373             :     }
    1374             : 
    1375        1490 :   if (test_verbose (OUTPUT_RESVERBOSE))
    1376             :     {
    1377             :       mpz_t t;
    1378             : 
    1379          30 :       mpz_init (t);
    1380          30 :       mpres_get_z (t, P.A, modulus);
    1381          30 :       outputf (OUTPUT_RESVERBOSE, "A=%Zd\n", t);
    1382          30 :       mpres_get_z (t, P.x, modulus);
    1383          30 :       outputf (OUTPUT_RESVERBOSE, "starting point: x0=%Zd\n", t);
    1384             : #ifdef HAVE_ADDLAWS
    1385          30 :       if (E->type == ECM_EC_TYPE_WEIERSTRASS)
    1386             :         {
    1387           0 :           mpres_get_z (t, P.y, modulus);
    1388           0 :           outputf (OUTPUT_RESVERBOSE, " y0=%Zd\n", t);
    1389             :         }
    1390             : #endif
    1391          30 :       mpz_clear (t);
    1392             :     }
    1393             : 
    1394        1490 :   if (go != NULL && mpz_cmp_ui (go, 1) > 0)
    1395         135 :     outputf (OUTPUT_VERBOSE, "initial group order: %Zd\n", go);
    1396             : 
    1397        1490 :   if (test_verbose (OUTPUT_VERBOSE))
    1398             :     {
    1399          57 :       if (mpz_cmp_d (B2min, B1) != 0)
    1400             :         {
    1401           0 :           outputf (OUTPUT_VERBOSE, 
    1402             :             "Can't compute success probabilities for B1 <> B2min\n");
    1403             :         }
    1404          57 :       else if (param == ECM_PARAM_DEFAULT)
    1405             :         {
    1406           0 :           outputf (OUTPUT_VERBOSE, "Can't compute success probabilities " 
    1407             :                                    "for this parametrization.\n");
    1408             :         }
    1409             :       else
    1410             :         {
    1411          57 :           rhoinit (256, 10);
    1412          57 :           print_expcurves (B1, B2, dF, k, root_params.S, param);
    1413             :         }
    1414             :     }
    1415             : 
    1416             :   /* Compute s for the batch mode */
    1417        1490 :   if (IS_BATCH_MODE(param) && ECM_IS_DEFAULT_B1_DONE(*B1done) &&
    1418         153 :       (B1 != *batch_last_B1_used || mpz_cmp_ui (batch_s, 1) <= 0))
    1419             :     {
    1420         137 :       *batch_last_B1_used = B1;
    1421             : 
    1422         137 :       st = cputime ();
    1423             :       /* construct the batch exponent */
    1424         137 :       compute_s (batch_s, B1, NULL);
    1425         137 :       outputf (OUTPUT_VERBOSE, "Computing batch product (of %" PRIu64
    1426             :                                " bits) of primes up to B1=%1.0f took %ldms\n",
    1427             :                                mpz_sizeinbase (batch_s, 2), B1,
    1428             :                                elltime (st, cputime ()));
    1429             :     }
    1430             : 
    1431        1490 :   st = cputime ();
    1432             : 
    1433             : #ifdef HAVE_GWNUM
    1434             :   /* We will only use GWNUM for numbers of the form k*b^n+c */
    1435             : 
    1436             :   if (gw_b != 0 && B1 >= *B1done && param == ECM_PARAM_SUYAMA)
    1437             :       youpi = gw_ecm_stage1 (f, &P, modulus, B1, B1done, go, gw_k, gw_b, gw_n, gw_c);
    1438             : 
    1439             :   /* At this point B1 == *B1done unless interrupted, or no GWNUM ecm_stage1
    1440             :      is available */
    1441             : 
    1442             :   if (youpi != ECM_NO_FACTOR_FOUND)
    1443             :     goto end_of_ecm_rhotable;
    1444             : #endif /* HAVE_GWNUM */
    1445             : 
    1446        1490 :   if (B1 > *B1done || mpz_cmp_ui (go, 1) > 0)
    1447             :     {
    1448        1407 :         if (IS_BATCH_MODE(param))
    1449             :         /* FIXME: go, stop_asap and chkfilename are ignored in batch mode */
    1450         152 :             youpi = ecm_stage1_batch (f, P.x, P.A, modulus, B1, B1done, 
    1451             :                                       param, batch_s);
    1452             :         else{
    1453             : #ifdef HAVE_ADDLAWS
    1454        1255 :             if(E->type == ECM_EC_TYPE_MONTGOMERY)
    1455             : #endif
    1456         975 :             youpi = ecm_stage1 (f, P.x, P.A, modulus, B1, B1done, go, 
    1457             :                                 stop_asap, chkfilename);
    1458             : #ifdef HAVE_ADDLAWS
    1459             :             else{
    1460         280 :                 ell_point_init(PE, E, modulus);
    1461         280 :                 mpres_set(PE->x, P.x, modulus);
    1462         280 :                 mpres_set(PE->y, P.y, modulus);
    1463         280 :                 youpi = ecm_stage1_W (f, E, PE, modulus, B1, B1done, batch_s,
    1464             :                                       go, stop_asap, chkfilename);
    1465         280 :                 mpres_set(P.x, PE->x, modulus);
    1466         280 :                 mpres_set(P.y, PE->y, modulus);
    1467             :             }
    1468             : #endif
    1469             :         }
    1470             :     }
    1471          83 :   else if (mpz_sgn (x) != 0)
    1472             :     {
    1473             :         /* when x <> 0, we initialize P to (x:y) */
    1474          62 :         mpres_set_z (P.x, x, modulus);
    1475          62 :         mpres_set_z (P.y, y, modulus);
    1476             :     }
    1477             : 
    1478        1490 :   if (stage1time > 0.)
    1479             :     {
    1480          10 :       const long st2 = elltime (st, cputime ());
    1481          10 :       const long s1t = (long) (stage1time * 1000.);
    1482          10 :       outputf (OUTPUT_NORMAL, 
    1483             :                "Step 1 took %ldms (%ld in this run, %ld from previous runs)\n", 
    1484             :                st2 + s1t, st2, s1t);
    1485             :     }
    1486             :   else
    1487        1480 :     outputf (OUTPUT_NORMAL, "Step 1 took %ldms\n", elltime (st, cputime ()));
    1488             : 
    1489             :   /* Store end-of-stage-1 residue in x in case we write it to a save file, 
    1490             :      before P.x is (perhaps) converted to Weierstrass form */
    1491             :   
    1492        1490 :   mpres_get_z (x, P.x, modulus);
    1493             : #ifdef HAVE_ADDLAWS
    1494        1490 :   if (E->type == ECM_EC_TYPE_WEIERSTRASS 
    1495        1300 :       || E->type == ECM_EC_TYPE_HESSIAN 
    1496        1230 :       || E->type == ECM_EC_TYPE_TWISTED_HESSIAN)
    1497         290 :     mpres_get_z (y, P.y, modulus);  
    1498             : #endif
    1499             : 
    1500        1490 :   if (youpi != ECM_NO_FACTOR_FOUND)
    1501         412 :     goto end_of_ecm_rhotable;
    1502             : 
    1503        1078 :   if (test_verbose (OUTPUT_RESVERBOSE)) 
    1504             :     {
    1505             :       mpz_t t;
    1506             :       
    1507          30 :       mpz_init (t);
    1508          30 :       mpres_get_z (t, P.x, modulus);
    1509          30 :       outputf (OUTPUT_RESVERBOSE, "x=%Zd\n", t);
    1510             : #ifdef HAVE_ADDLAWS
    1511          30 :       if (E->type == ECM_EC_TYPE_WEIERSTRASS)
    1512             :         {
    1513           0 :           mpres_get_z (t, P.y, modulus);
    1514           0 :           outputf (OUTPUT_RESVERBOSE, "y=%Zd\n", t);
    1515             :         }
    1516             : #endif
    1517          30 :       mpz_clear (t);
    1518             :     }
    1519             : 
    1520             :   /* In case of a signal, we'll exit after the residue is printed. If no save
    1521             :      file is specified, the user may still resume from the residue */
    1522        1078 :   if (stop_asap != NULL && (*stop_asap) ())
    1523           0 :     goto end_of_ecm_rhotable;
    1524             : 
    1525             :   /* If using 2^k +/-1 modulus and 'nobase2step2' flag is set,
    1526             :      set default (-nobase2) modular method and remap P.x, P.y, and P.A */
    1527        1078 :   if (modulus->repr == ECM_MOD_BASE2 && nobase2step2)
    1528             :     {
    1529             :       mpz_t x_t, y_t, A_t;
    1530             : 
    1531           7 :       mpz_init (x_t);
    1532           7 :       mpz_init (y_t);
    1533           7 :       mpz_init (A_t);
    1534             : 
    1535           7 :       mpz_mod (x_t, P.x, modulus->orig_modulus);
    1536           7 :       mpz_mod (y_t, P.y, modulus->orig_modulus);
    1537           7 :       mpz_mod (A_t, P.A, modulus->orig_modulus);
    1538             : 
    1539           7 :       mpmod_clear (modulus);
    1540             : 
    1541           7 :       repr = ECM_MOD_NOBASE2;
    1542           7 :       if (mpmod_init (modulus, n, repr) != 0) /* reset modulus for nobase2 */
    1543           0 :         return ECM_ERROR;
    1544             : 
    1545             :       /* remap x, y, and A for new modular method */
    1546           7 :       mpres_set_z (P.x, x_t, modulus);
    1547           7 :       mpres_set_z (P.y, y_t, modulus);
    1548           7 :       mpres_set_z (P.A, A_t, modulus);
    1549             : 
    1550           7 :       mpz_clear (x_t);
    1551           7 :       mpz_clear (y_t);
    1552           7 :       mpz_clear (A_t);
    1553             :     }
    1554             : 
    1555             : #ifdef HAVE_ADDLAWS
    1556        1078 :   if (E->type == ECM_EC_TYPE_MONTGOMERY)
    1557             : #endif
    1558         978 :   youpi = montgomery_to_weierstrass (f, P.x, P.y, P.A, modulus);
    1559             : #ifdef HAVE_ADDLAWS
    1560         100 :   else if (E->type == ECM_EC_TYPE_HESSIAN)
    1561             :     {
    1562          20 :       youpi = hessian_to_weierstrass (f, P.x, P.y, P.A, modulus);
    1563          20 :       if(youpi == ECM_NO_FACTOR_FOUND)
    1564             :         /* due to that non-trivial kernel(?) */
    1565          20 :         youpi = mult_by_3(f, P.x, P.y, P.A, modulus);
    1566             :     }
    1567          80 :   else if (E->type == ECM_EC_TYPE_TWISTED_HESSIAN)
    1568             :     {
    1569             :         mpz_t c, rm;
    1570          10 :         mpz_init(c);
    1571          10 :         mpz_init(rm);
    1572          10 :         mpres_get_z(rm, E->a4, modulus);
    1573          10 :         mpz_rootrem(c, rm, rm, 3);
    1574          10 :         if(mpz_sgn(rm) != 0){
    1575           0 :             printf("ECM_EC_TYPE_TWISTED_HESSIAN: not a cube!\n");
    1576           0 :             exit(-1);
    1577             :         }
    1578          10 :         mpres_set_z(P.A, c, modulus);
    1579          10 :         mpz_clear(c);
    1580          10 :         mpz_clear(rm);
    1581          10 :         youpi = twisted_hessian_to_weierstrass (f, P.x, P.y, P.A, E->a6, modulus);
    1582          10 :         if(youpi == ECM_NO_FACTOR_FOUND){
    1583             :             /* due to that non-trivial kernel(?) */
    1584          10 :             youpi = mult_by_3(f, P.x, P.y, P.A, modulus);
    1585             :         }
    1586             :     }
    1587             : #endif
    1588             :   
    1589        1078 :   if (test_verbose (OUTPUT_RESVERBOSE) && youpi == ECM_NO_FACTOR_FOUND && 
    1590          30 :       mpz_cmp (B2, B2min) >= 0)
    1591             :     {
    1592             :       mpz_t t;
    1593             : 
    1594          30 :       mpz_init (t);
    1595          30 :       mpres_get_z (t, P.x, modulus);
    1596          30 :       outputf (OUTPUT_RESVERBOSE, "After switch to Weierstrass form, "
    1597             :       "P=(%Zd", t);
    1598          30 :       mpres_get_z (t, P.y, modulus);
    1599          30 :       outputf (OUTPUT_RESVERBOSE, ", %Zd)\n", t);
    1600          30 :       mpres_get_z (t, P.A, modulus);
    1601          30 :       outputf (OUTPUT_RESVERBOSE, "on curve Y^2 = X^3 + %Zd * X + b\n", t);
    1602          30 :       mpz_clear (t);
    1603             :     }
    1604             : 
    1605        1078 :   P.disc = 0; /* FIXME: should disappear one day */
    1606             :   
    1607        1078 :   if (youpi == ECM_NO_FACTOR_FOUND && mpz_cmp (B2, B2min) >= 0)
    1608        1048 :     youpi = stage2 (f, &P, modulus, dF, k, &root_params, use_ntt, 
    1609             :                     TreeFilename, 0, stop_asap);
    1610             : #ifdef TIMING_CRT
    1611             :   printf ("mpzspv_from_mpzv_slow: %dms\n", mpzspv_from_mpzv_slow_time);
    1612             :   printf ("mpzspv_to_mpzv: %dms\n", mpzspv_to_mpzv_time);
    1613             :   printf ("mpzspv_normalise: %dms\n", mpzspv_normalise_time);
    1614             : #endif
    1615             :   
    1616          30 : end_of_ecm_rhotable:
    1617        1490 :   if (test_verbose (OUTPUT_VERBOSE))
    1618             :     {
    1619          57 :       if (mpz_cmp_d (B2min, B1) == 0 && param != ECM_PARAM_DEFAULT)
    1620             :         {
    1621          57 :           if (youpi == ECM_NO_FACTOR_FOUND && 
    1622           0 :               (stop_asap == NULL || !(*stop_asap)()))
    1623           9 :             print_exptime (B1, B2, dF, k, root_params.S, 
    1624           9 :                            (long) (stage1time * 1000.) + 
    1625           9 :                            elltime (st, cputime ()), param);
    1626          57 :           rhoinit (1, 0); /* Free memory of rhotable */
    1627             :         }
    1628             :     }
    1629             : 
    1630        1433 : end_of_ecm:
    1631             : #ifdef HAVE_ADDLAWS
    1632        1566 :   ell_curve_clear(E, modulus);
    1633             : #endif
    1634        1566 :   mpres_clear (P.A, modulus);
    1635        1566 :   mpres_clear (P.y, modulus);
    1636        1566 :   mpres_clear (P.x, modulus);
    1637        1566 :   mpz_clear (root_params.i0);
    1638        1566 :   mpz_clear (B2);
    1639        1566 :   mpz_clear (B2min);
    1640        1566 :   mpmod_clear (modulus);
    1641        1566 :   return youpi;
    1642             : }

Generated by: LCOV version 1.14