LCOV - code coverage report
Current view: top level - ecm - bestd.c (source / functions) Hit Total Coverage
Test: unnamed Lines: 96 99 97.0 %
Date: 2022-03-21 11:19:20 Functions: 1 1 100.0 %

          Line data    Source code
       1             : /* Choice of best parameters for stage 2.
       2             : 
       3             : Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2010 Paul Zimmermann,
       4             : Alexander Kruppa, Dave Newman.
       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 <gmp.h>
      25             : #include "ecm-impl.h"
      26             : 
      27             : /*
      28             :   Compute (d, d2, k) such that:
      29             :   (0) k >= k0
      30             :   (1) d is a multiple of 6
      31             :   (2) k * d * (eulerphi(d)/2) * d2 / eulerphi(d2) >= B2 - B2min
      32             :   (3) gcd(d, d2) == 1
      33             :   (4) k is minimal, subject to previous conditions
      34             :   (5) if parameter po2 is != 0, rounds dF up to a power of 2
      35             :   Return non-zero iff an error occurred (too large step 2 bound).
      36             :  */
      37             : 
      38             : /* How we test whether given d,d2,dF,k,i0 parameters cover the desired 
      39             :    B2min-B2 range:
      40             : 
      41             :    In stage 2 we generate all values  p = f(i * d) +- f(j * d2)  with 
      42             : 
      43             :      1. gcd (i, d2) == 1, 
      44             :      2. gcd (j, d) == 1,
      45             :      3. j == 1 (mod 6),
      46             :      4. 6|d
      47             :      5. 1 <= j <= d - 5, (it's -5, not just -1, because of 3. and 4.)
      48             :      6. i0 <= i <= i1
      49             :      7. gcd (d, d2) == 1
      50             :    
      51             :    where f(x) is x^S or the S-th Dickson polynomial g_{S,-1}(x). Extra 
      52             :    factors included by S>1 are not considered in this analysis, we assume 
      53             :    S=1, f(x)=x so that  p = i * d +- j * d2.
      54             : 
      55             :    (Note: i values greater than stated in 3. may be generated if we have 
      56             :     to round up dF, for example to a power of 2. However, the root generation
      57             :     code can put anything it likes in those extra roots, so we make no 
      58             :     assumption here that this will extend the range of the i values.)
      59             :    
      60             :    Hence the values at the high end of the stage 2 range that are not 
      61             :    generated are
      62             :    
      63             :      p = (i1 + n) * d +- j * d2, n > 0
      64             : 
      65             :    and the smallest one of those is
      66             :    
      67             :      p = (i1 + 1) * d - (d - 5) * d2
      68             :        = d * (i1 - d2 + 1) + 5 * d2
      69             :    
      70             :    At the low end of stage 2, values not generated are
      71             :    
      72             :      p = (i0 - n) * d +- j * d2, n > 0   
      73             : 
      74             :    the largest one being
      75             :    
      76             :      p = (i0 - 1) * d + (d - 5) * d2
      77             :        = d * (i0 + d2 - 1) - 5*d2
      78             : 
      79             :    Thus, values p that are coprime do d*d2 and 
      80             :      d * (i0 + d2 - 1) - 5*d2 + 1 <= p <= d * (i1 - d2 + 1) + 5 * d2 - 1 
      81             :    are included in stage 2.
      82             : 
      83             :    
      84             :    The number of roots of G we compute is k * dF. For d2 == 1, this means 
      85             :    i1 = i0 + k * dF - 1  (-1 because both i0 and i1 are included).
      86             : 
      87             :    For d2 > 1, values j not coprime to d2 are skipped (see condition 1).
      88             :    The number of values in [1, i0] that are not coprime to d2 (with d2 prime) 
      89             :    is floor (i0 / d2); in [1, i1] it is floor (i1 / d2). 
      90             :    So we require that
      91             :    k * dF >= i1 - i0 + 1 - (floor (i1 / d2) - floor (i0 / d2))
      92             :    
      93             :    
      94             : */
      95             : 
      96             : int
      97        1566 : bestD (root_params_t *root_params, unsigned long *finalk, 
      98             :        unsigned long *finaldF, mpz_t B2min, mpz_t B2, int po2, int use_ntt, 
      99             :        double maxmem, int treefile, mpmod_t modulus)
     100             : {
     101             : /* the following list contains successive values of b with
     102             :    increasing values of eulerphi(b). It was generated by the following 
     103             :    Maple program:
     104             : l := [[1,1]]:
     105             : for b from 12 by 6 do
     106             :    d:=numtheory[phi](b)/2;
     107             :    while d <= l[nops(l)][2] do l:=subsop(nops(l)=NULL, l) od;
     108             :    n := nops(l);
     109             :    if b>1.1*l[n][1] then l := [op(l), [b,d]]; lprint(l) fi;
     110             : od:
     111             : */
     112             : #define N 109
     113             :   static unsigned int l[N] = {12, 18, 30, 42, 60, 90, 120, 150, 210, 240, 270, 330, 420, 510, 630, 840, 1050, 1260, 1470, 1680, 1890, 2310, 2730, 3150, 3570, 3990, 4620, 5460, 6090, 6930, 8190, 9240, 10920, 12180, 13860, 16170, 18480, 20790, 23100, 30030, 34650, 39270, 43890, 48510, 60060, 66990, 78540, 90090, 99330, 120120, 133980, 150150, 180180, 210210, 240240, 270270, 300300, 334950, 371280, 420420, 510510, 570570, 600600, 630630, 746130, 870870, 1021020, 1141140, 1291290, 1531530, 1711710, 1891890, 2081310, 2312310, 2552550, 2852850, 3183180, 3573570, 3993990, 4594590, 5105100, 5705700, 6322470, 7147140, 7987980, 8978970, 10210200, 11741730, 13123110, 14804790, 16546530, 19399380, 21411390, 23993970, 26816790, 29609580, 33093060, 36606570, 40330290, 44414370, 49639590, 54624570, 60090030, 67897830, 77597520, 87297210, 96996900, 107056950, 118107990};
     114             : #define Npo2 23
     115             :   static unsigned int lpo2[Npo2] = {12, 30, 60, 120, 240, 510, 1020, 2310, 
     116             :                                  4620, 9240, 19110, 39270, 79170, 158340, 
     117             :                                  324870, 690690, 1345890, 2852850, 5705700, 
     118             :                                  11741730, 23130030, 48498450, 96996900};
     119             : 
     120        1566 :   unsigned long i, d1 = 0, d2 = 0, dF = 0, phid, k, maxN;
     121             :   mpz_t j, t, i0, i1;
     122        1566 :   int r = 0;
     123             : 
     124        1566 :   if (mpz_cmp (B2, B2min) < 0)
     125             :     {
     126             :       /* No stage 2. Set relevant parameters to 0. Leave B2, B2min the same */
     127         100 :       *finalk = 0;
     128         100 :       *finaldF = 0;
     129         100 :       return 0;
     130             :     }
     131             :   
     132        1466 :   mpz_init (i0);
     133        1466 :   mpz_init (i1);
     134        1466 :   mpz_init (j);
     135        1466 :   mpz_init (t);
     136        1466 :   k = *finalk; /* User specified k value passed in via finalk */
     137             : 
     138             :   /* Look for largest dF we can use while satisfying the maxmem parameter */
     139        1466 :   maxN = (po2) ? Npo2 : N;
     140        1466 :   if (maxmem != 0.)
     141             :   {
     142         283 :     for (i = 0; i < maxN; i++)
     143             :       {
     144         283 :         int lg_dF, sp_num = 0;
     145             :         double memory;
     146             :         
     147         283 :         d1 = (po2) ? lpo2[i] : l[i];
     148         283 :         phid = eulerphi (d1) / 2;
     149         283 :         dF = (po2) ? 1U << ceil_log2 (phid) : phid;
     150         283 :         lg_dF = ceil_log2 (dF);
     151             :         
     152         283 :         if (use_ntt)
     153         200 :           sp_num = (2 * mpz_sizeinbase (modulus->orig_modulus, 2) + lg_dF) / 
     154         200 :                  SP_NUMB_BITS + 4;
     155             :         
     156         283 :         memory = memory_use (dF, sp_num, (treefile) ? 0 : lg_dF, modulus);
     157         283 :         outputf (OUTPUT_DEVVERBOSE, 
     158             :                  "Estimated mem for dF = %.0d, sp_num = %d: %.0f\n", 
     159             :                  dF, sp_num, memory);
     160         283 :         if (memory > maxmem)
     161          21 :           break;
     162             :       }
     163          21 :     maxN = i;
     164             :   }      
     165             :   
     166       13254 :   for (i = 0; i < maxN; i++)
     167             :     {
     168       13233 :       d1 = (po2) ? lpo2[i] : l[i];
     169       13233 :       phid = eulerphi (d1) / 2;
     170       13233 :       dF = (po2) ? 1U << ceil_log2 (phid) : phid;
     171             :       /* Look for smallest prime < 25 that does not divide d1 */
     172             :       /* The caller can force d2 = 1 by setting root_params->d2 != 0 */
     173       13233 :       d2 = 1;
     174       13233 :       if (root_params->d2 == 0)
     175       34539 :         for (d2 = 5; d2 < 25; d2 += 2)
     176             :           {
     177       34539 :             if (d2 % 3 == 0)
     178        3848 :               continue;
     179       30691 :             if (d1 % d2 > 0)
     180       13233 :               break;
     181             :           }
     182             : 
     183       13233 :       if (d2 >= 25 || d2 - 1 > dF)
     184        3007 :         d2 = 1;
     185             : 
     186             : #if 0
     187             :       /* The code to init roots of G can handle negative i0 now. */
     188             :       if (d2 > 1 && mpz_cmp_ui (B2min, (d1 - 1) * d2 - d1) <= 0) 
     189             :         d2 = 1; /* Would make i0 < 0 */
     190             : #endif
     191             :       
     192       13233 :       mpz_set_ui (i0, d1 - 1);
     193       13233 :       mpz_mul_ui (i0, i0, d2);
     194       13233 :       mpz_set (j, B2);
     195       13233 :       mpz_add (i1, j, i0); /* i1 = B2 + (d1 - 1) * d2 */
     196       13233 :       mpz_set (j, B2min);
     197       13233 :       mpz_sub (i0, j, i0); /* i0 = B2min - (d1 - 1) * d2 */
     198       13233 :       mpz_cdiv_q_ui (i0, i0, d1); /* i0 = ceil ((B2min - (d1 - 1) * d2) / d1) */
     199       13233 :       mpz_fdiv_q_ui (i1, i1, d1); /* i1 = floor ((B2 + (d1 - 1) * d2) / d1) */
     200             :       
     201             :       /* How many roots of G will we need ? */
     202       13233 :       mpz_sub (j, i1, i0);
     203       13233 :       mpz_add_ui (j, j, 1);
     204             : 
     205             :       /* Integer multiples of d2 are skipped (if d2 > 1) */
     206       13233 :       if (d2 > 1)
     207             :         {
     208       10226 :           mpz_fdiv_q_ui (t, i1, d2);
     209       10226 :           mpz_sub (j, j, t);
     210       10226 :           mpz_fdiv_q_ui (t, i0, d2);
     211       10226 :           mpz_add (j, j, t); /* j -= floor (i1 / d2) - floor (i0 / d2) */
     212             :         }
     213             :       
     214             :       /* How many blocks will we need ? Divide lines by dF, rounding up */
     215       13233 :       mpz_cdiv_q_ui (j, j, dF);
     216             :       
     217       13233 :       if ((k != ECM_DEFAULT_K && mpz_cmp_ui (j, k) <= 0) || 
     218       11830 :           (k == ECM_DEFAULT_K && mpz_cmp_ui (j, (po2) ? 6 : 2) <= 0))
     219             :         break;
     220             :     }
     221             : 
     222        1466 :   if (i == maxN)
     223             :     {
     224          21 :       if (k != ECM_DEFAULT_K)
     225             :         {
     226             :           /* The user asked for a specific k and we couldn't satisfy the
     227             :              condition. Nothing we can do ... */
     228          10 :           outputf (OUTPUT_ERROR, "Error: too large step 2 bound, increase -k\n");
     229          10 :           r = ECM_ERROR;
     230          10 :           goto clear_and_exit;
     231             :         }
     232          11 :       else if (!mpz_fits_ulong_p (j))
     233             :         {
     234             :           /* Can't fit the number of blocks in an unsigned long. Nothing we
     235             :              can do ... */
     236          10 :           outputf (OUTPUT_ERROR, "Error: stage 2 interval too large, cannot "
     237             :                    "generate suitable parameters.\nTry a smaller B2 value.\n");
     238          10 :           r = ECM_ERROR;
     239          10 :           goto clear_and_exit;
     240             :         }
     241           1 :       if (maxN == 0)
     242             :         {
     243             :           /* We can't do a stage 2 at all with the memory the user allowed.
     244             :              Nothing we can do ... */
     245           0 :           outputf (OUTPUT_ERROR, "Error: stage 2 not possible with memory "
     246             :                    "allowed by -maxmem.\n");
     247           0 :           r = ECM_ERROR;
     248           0 :           goto clear_and_exit;
     249             :         }
     250             :       /* else: We can fit the number of blocks into an unsigned int, so we use 
     251             :          it. This may be a very large value for huge B2-B2min, the user
     252             :          is going to notice sooner or later */
     253             :     }
     254             :   
     255             :   /* If the user specified a number of blocks, we'll use that no matter what.
     256             :      Since j may be smaller than k, this may increase the B2 limit */
     257        1446 :   if (k == ECM_DEFAULT_K)
     258        1325 :     k = mpz_get_ui (j);
     259             : 
     260             :   /* Now that we have the number of blocks, compute real i1. There will be
     261             :      k * dF roots of G computed, starting at i0, skipping all that are not
     262             :      coprime to d2. While d2 is prime, that means: are not multiples of d2.
     263             :      Hence we want i1 so that 
     264             :        i1 - floor(i1 / d2) - i0 + ceil((i0 / d2) == k * dF
     265             :        i1 - floor(i1 / d2) == k * dF + i0 - ceil((i0 / d2)
     266             :   */
     267             :   
     268        1446 :   mpz_set_ui (j, k);
     269        1446 :   mpz_mul_ui (j, j, dF);
     270        1446 :   if (d2 == 1)
     271             :     {
     272         103 :       mpz_add (i1, i0, j);
     273         103 :       mpz_sub_ui (i1, i1, 1);
     274             :     }
     275             :   else
     276             :     {
     277        1343 :       mpz_add (j, j, i0);
     278        1343 :       mpz_cdiv_q_ui (t, i0, d2);
     279        1343 :       mpz_sub (j, j, t); /* j = k * dF + i0 - ceil((i0 / d2) */
     280        1343 :       mpz_fdiv_qr_ui (j, t, j, d2 - 1);
     281        1343 :       mpz_mul_ui (j, j, d2);
     282        1343 :       mpz_add (i1, j, t);
     283             :     }
     284             : 
     285        1446 :   root_params->d1 = d1;
     286        1446 :   root_params->d2 = d2;
     287        1446 :   mpz_set (root_params->i0, i0);
     288        1446 :   *finaldF = dF;
     289        1446 :   *finalk = k;
     290             : 
     291             :   /* We want B2' the largest integer that satisfies 
     292             :      i1 = floor ((B2' + (d1 - 1) * d2) / d1)
     293             :         = floor ((B2'-d2)/d1) + d2
     294             :      i1 - d2 = floor ((B2'-d2)/d1)
     295             :      (B2'-d2)/d1 < i1-d2+1
     296             :      B2'-d2 < (i1-d2+1) * d1
     297             :      B2' < (i1-d2+1) * d1 + d2
     298             :      B2' = (i1-d2+1) * d1 + d2 - 1
     299             :   */
     300             :   
     301        1446 :   mpz_sub_ui (i1, i1, d2 - 1);
     302        1446 :   mpz_mul_ui (B2, i1, d1);
     303        1446 :   mpz_add_ui (B2, B2, d2 - 1);
     304             : 
     305        1466 : clear_and_exit:
     306        1466 :   mpz_clear (t);
     307        1466 :   mpz_clear (j);
     308        1466 :   mpz_clear (i1);
     309        1466 :   mpz_clear (i0);
     310             : 
     311        1466 :   return r;
     312             : }

Generated by: LCOV version 1.14