LCOV - code coverage report
Current view: top level - ecm - rho.c (source / functions) Hit Total Coverage
Test: unnamed Lines: 164 179 91.6 %
Date: 2022-03-21 11:19:20 Functions: 15 16 93.8 %

          Line data    Source code
       1             : /* Dickman's rho function (to compute probability of success of ecm).
       2             : 
       3             : Copyright 2004, 2005, 2006, 2008, 2009, 2010, 2011, 2012, 2013
       4             : Alexander Kruppa, Paul Zimmermann.
       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             : /* define TESTDRIVE to compile rho as a stand-alone program, in which case
      24             :    you need to have libgsl installed */
      25             : 
      26             : #include "config.h"
      27             : #if defined(TESTDRIVE)
      28             : #define _ISOC99_SOURCE 1
      29             : #endif
      30             : #if defined(DEBUG_NUMINTEGRATE) || defined(TESTDRIVE)
      31             : # include <stdio.h>
      32             : #endif
      33             : #include <stdlib.h>
      34             : #include <math.h>
      35             : #if defined(TESTDRIVE)
      36             : #include <string.h>
      37             : #include <primesieve.h>
      38             : #endif
      39             : #if defined(TESTDRIVE)
      40             : #include <gsl/gsl_math.h>
      41             : #include <gsl/gsl_sf_expint.h>
      42             : #include <gsl/gsl_integration.h>
      43             : #endif
      44             : #include "ecm-impl.h"
      45             : 
      46             : /* For Suyama's curves, we have a known torsion factor of 12 = 2^2*3^1, and
      47             :    an average extra exponent of 1/2 for 2, and 1/3 for 3 due to the probability
      48             :    that the group order divided by 12 is divisible by 2 or 3, thus on average
      49             :    we should have 2^2.5*3^1.333 ~ 24.5, however experimentally we have
      50             :    2^3.323*3^1.687 ~ 63.9 (see Alexander Kruppa's thesis, Table 5.1 page 96,
      51             :    row sigma=2, http://tel.archives-ouvertes.fr/tel-00477005/en/).
      52             :    The exp(ECM_EXTRA_SMOOTHNESS) value takes into account the extra
      53             :    smoothness with respect to a random number. */
      54             : #ifndef ECM_EXTRA_SMOOTHNESS
      55             : #define ECM_EXTRA_SMOOTHNESS 3.134
      56             : #endif
      57             : 
      58             : #define M_PI_SQR   9.869604401089358619 /* Pi^2 */
      59             : #define M_PI_SQR_6 1.644934066848226436 /* Pi^2/6 */
      60             : /* gsl_math.h defines M_EULER */
      61             : #ifndef M_EULER
      62             : #define M_EULER    0.577215664901532861
      63             : #endif
      64             : #define M_EULER_1   0.422784335098467139 /* 1 - Euler */
      65             : 
      66             : #ifndef MAX
      67             : #define MAX(x,y) ((x) > (y) ? (x) : (y))
      68             : #endif
      69             : #ifndef MIN
      70             : #define MIN(x,y) ((x) < (y) ? (x) : (y))
      71             : #endif
      72             : 
      73             : void rhoinit (int, int); /* used in stage2.c */
      74             : 
      75             : static double *rhotable = NULL;
      76             : static int invh = 0;
      77             : static double h = 0.;
      78             : static int tablemax = 0;
      79             : #if defined(TESTDRIVE)
      80             : #define PRIME_PI_MAX 10000
      81             : #define PRIME_PI_MAP(x) (((x)+1)/2)
      82             : /* The number of primes up to i. Use prime_pi[PRIME_PI_MAP(i)].
      83             :    Only correct for i >= 2. */
      84             : static unsigned int prime_pi[PRIME_PI_MAP(PRIME_PI_MAX)+1];
      85             : #endif
      86             : 
      87             : /* Fixme: need prime generating funcion without static state variables */
      88             : const unsigned char primemap[667] = {
      89             :   254, 223, 239, 126, 182, 219, 61, 249, 213, 79, 30, 243, 234, 166, 237, 158, 
      90             :   230, 12, 211, 211, 59, 221, 89, 165, 106, 103, 146, 189, 120, 30, 166, 86, 
      91             :   86, 227, 173, 45, 222, 42, 76, 85, 217, 163, 240, 159, 3, 84, 161, 248, 46, 
      92             :   253, 68, 233, 102, 246, 19, 58, 184, 76, 43, 58, 69, 17, 191, 84, 140, 193, 
      93             :   122, 179, 200, 188, 140, 79, 33, 88, 113, 113, 155, 193, 23, 239, 84, 150, 
      94             :   26, 8, 229, 131, 140, 70, 114, 251, 174, 101, 146, 143, 88, 135, 210, 146, 
      95             :   216, 129, 101, 38, 227, 160, 17, 56, 199, 38, 60, 129, 235, 153, 141, 81, 
      96             :   136, 62, 36, 243, 51, 77, 90, 139, 28, 167, 42, 180, 88, 76, 78, 38, 246, 
      97             :   25, 130, 220, 131, 195, 44, 241, 56, 2, 181, 205, 205, 2, 178, 74, 148, 12, 
      98             :   87, 76, 122, 48, 67, 11, 241, 203, 68, 108, 36, 248, 25, 1, 149, 168, 92, 
      99             :   115, 234, 141, 36, 150, 43, 80, 166, 34, 30, 196, 209, 72, 6, 212, 58, 47, 
     100             :   116, 156, 7, 106, 5, 136, 191, 104, 21, 46, 96, 85, 227, 183, 81, 152, 8, 
     101             :   20, 134, 90, 170, 69, 77, 73, 112, 39, 210, 147, 213, 202, 171, 2, 131, 97, 
     102             :   5, 36, 206, 135, 34, 194, 169, 173, 24, 140, 77, 120, 209, 137, 22, 176, 87, 
     103             :   199, 98, 162, 192, 52, 36, 82, 174, 90, 64, 50, 141, 33, 8, 67, 52, 182, 
     104             :   210, 182, 217, 25, 225, 96, 103, 26, 57, 96, 208, 68, 122, 148, 154, 9, 136, 
     105             :   131, 168, 116, 85, 16, 39, 161, 93, 104, 30, 35, 200, 50, 224, 25, 3, 68, 
     106             :   115, 72, 177, 56, 195, 230, 42, 87, 97, 152, 181, 28, 10, 104, 197, 129, 
     107             :   143, 172, 2, 41, 26, 71, 227, 148, 17, 78, 100, 46, 20, 203, 61, 220, 20, 
     108             :   197, 6, 16, 233, 41, 177, 130, 233, 48, 71, 227, 52, 25, 195, 37, 10, 48, 
     109             :   48, 180, 108, 193, 229, 70, 68, 216, 142, 76, 93, 34, 36, 112, 120, 146, 
     110             :   137, 129, 130, 86, 38, 27, 134, 233, 8, 165, 0, 211, 195, 41, 176, 194, 74, 
     111             :   16, 178, 89, 56, 161, 29, 66, 96, 199, 34, 39, 140, 200, 68, 26, 198, 139, 
     112             :   130, 129, 26, 70, 16, 166, 49, 9, 240, 84, 47, 24, 210, 216, 169, 21, 6, 46, 
     113             :   12, 246, 192, 14, 80, 145, 205, 38, 193, 24, 56, 101, 25, 195, 86, 147, 139, 
     114             :   42, 45, 214, 132, 74, 97, 10, 165, 44, 9, 224, 118, 196, 106, 60, 216, 8, 
     115             :   232, 20, 102, 27, 176, 164, 2, 99, 54, 16, 49, 7, 213, 146, 72, 66, 18, 195, 
     116             :   138, 160, 159, 45, 116, 164, 130, 133, 120, 92, 13, 24, 176, 97, 20, 29, 2, 
     117             :   232, 24, 18, 193, 1, 73, 28, 131, 48, 103, 51, 161, 136, 216, 15, 12, 244, 
     118             :   152, 136, 88, 215, 102, 66, 71, 177, 22, 168, 150, 8, 24, 65, 89, 21, 181, 
     119             :   68, 42, 82, 225, 179, 170, 161, 89, 69, 98, 85, 24, 17, 165, 12, 163, 60, 
     120             :   103, 0, 190, 84, 214, 10, 32, 54, 107, 130, 12, 21, 8, 126, 86, 145, 1, 120, 
     121             :   208, 97, 10, 132, 168, 44, 1, 87, 14, 86, 160, 80, 11, 152, 140, 71, 108, 
     122             :   32, 99, 16, 196, 9, 228, 12, 87, 136, 11, 117, 11, 194, 82, 130, 194, 57, 
     123             :   36, 2, 44, 86, 37, 122, 49, 41, 214, 163, 32, 225, 177, 24, 176, 12, 138, 
     124             :   50, 193, 17, 50, 9, 197, 173, 48, 55, 8, 188, 145, 130, 207, 32, 37, 107, 
     125             :   156, 48, 143, 68, 38, 70, 106, 7, 73, 142, 9, 88, 16, 2, 37, 197, 196, 66, 
     126             :   90, 128, 160, 128, 60, 144, 40, 100, 20, 225, 3, 132, 81, 12, 46, 163, 138, 
     127             :   164, 8, 192, 71, 126, 211, 43, 3, 205, 84, 42, 0, 4, 179, 146, 108, 66, 41, 
     128             :   76, 131, 193, 146, 204, 28};
     129             : 
     130             : #ifdef TESTDRIVE
     131             : unsigned long
     132             : gcd (unsigned long a, unsigned long b)
     133             : {
     134             :   unsigned long t;
     135             : 
     136             :   while (b != 0)
     137             :     {
     138             :       t = a % b;
     139             :       a = b;
     140             :       b = t;
     141             :     }
     142             : 
     143             :   return a;
     144             : }
     145             : 
     146             : unsigned long
     147             : eulerphi (unsigned long n)
     148             : {
     149             :   unsigned long phi = 1, p;
     150             : 
     151             :   for (p = 2; p * p <= n; p += 2)
     152             :     {
     153             :       if (n % p == 0)
     154             :         {
     155             :           phi *= p - 1;
     156             :           n /= p;
     157             :           while (n % p == 0)
     158             :             {
     159             :               phi *= p;
     160             :               n /= p;
     161             :             }
     162             :         }
     163             : 
     164             :       if (p == 2)
     165             :         p--;
     166             :     }
     167             : 
     168             :   /* now n is prime */
     169             : 
     170             :   return (n == 1) ? phi : phi * (n - 1);
     171             : }
     172             : 
     173             : 
     174             : /* The number of positive integers up to x that have no prime factor <= y,
     175             :    for x >= y >= 2. Uses Buchstab's identity */
     176             : unsigned long
     177             : Buchstab_Phi(unsigned long x, unsigned long y) 
     178             : {
     179             :   unsigned long p, s;
     180             :   primesieve_iterator pg[1];
     181             : 
     182             :   if (x < 1)
     183             :     return 0;
     184             :   if (x <= y)
     185             :     return 1;
     186             : #if 0
     187             :   if (x < y^2)
     188             :     return(1 + primepi(x) - primepi (y)));
     189             : #endif
     190             : 
     191             :   s = 1;
     192             :   primesieve_init (pg);
     193             :   primesieve_skipto (pg, y, x+1);
     194             :   for (p = primesieve_next_prime (pg); p <= x; p = primesieve_next_prime (pg))
     195             :     s += Buchstab_Phi(x / p, p - 1);
     196             :   return (s);
     197             : }
     198             : 
     199             : 
     200             : /* The number of positive integers up to x that have no prime factor
     201             :    greter than y, for x >= y >= 2. Uses Buchstab's identity */
     202             : unsigned long 
     203             : Buchstab_Psi(const unsigned long x, const unsigned long y) 
     204             : {
     205             :   unsigned long r, p;
     206             :   primesieve_iterator pg[1];
     207             : 
     208             :   if (x <= y)
     209             :     return (x);
     210             : 
     211             :   if (y == 1UL)
     212             :     return (1);
     213             : 
     214             :   /* If y^2 > x, then
     215             :      Psi(x,y) = x - \sum_{y < p < x, p prime} floor(x/p)
     216             : 
     217             :      We separate the sum into ranges where floor(x/p) = k,
     218             :      which is x/(k+1) < p <= x/k.
     219             :      We also need to satisfy y < p, so we need k < x/y - 1,
     220             :      or k_max = ceil (x/y) - 2.
     221             :      The primes y < p <= x/(k_max + 1) are summed separately. */
     222             :   if (x <= PRIME_PI_MAX && x < y * y)
     223             :     {
     224             :       unsigned long kmax = x / y - 1;
     225             :       unsigned long s1, s2, k;
     226             :       
     227             :         s1 = (kmax + 1) * (prime_pi [PRIME_PI_MAP(x / (kmax + 1))] - 
     228             :                            prime_pi [PRIME_PI_MAP(y)]);
     229             :         s2 = 0;
     230             :         for (k = 1; k <= kmax; k++)
     231             :           s2 += prime_pi[PRIME_PI_MAP(x / k)];
     232             :         s2 -= kmax * prime_pi [PRIME_PI_MAP(x / (kmax+1))];
     233             :         return (x - s1 - s2);
     234             :     }
     235             : 
     236             :   r = 1;
     237             :   primesieve_init (pg);
     238             :   for (p = primesieve_next_prime (pg); p <= y; p = primesieve_next_prime (pg))
     239             :     r += Buchstab_Psi (x / p, p);
     240             :   return (r);
     241             : }
     242             : 
     243             : #endif /* TESTDRIVE */
     244             : 
     245             : 
     246             : #if defined(TESTDRIVE)
     247             : static double
     248             : Li (const double x)
     249             : {
     250             :   return (- gsl_sf_expint_E1 (- log(x)));
     251             : }
     252             : #endif
     253             : 
     254             : /*
     255             :   Evaluate dilogarithm via the sum 
     256             :   \Li_{2}(z)=\sum_{k=1}^{\infty} \frac{z^k}{k^2}, 
     257             :   see http://mathworld.wolfram.com/Dilogarithm.html
     258             :   Assumes |z| <= 0.5, for which the sum converges quickly.
     259             :  */
     260             : 
     261             : static double
     262       36620 : dilog_series (const double z)
     263             : {
     264       36620 :   double r = 0.0, zk; /* zk = z^k */
     265             :   int k, k2; /* k2 = k^2 */
     266             :   /* Doubles have 53 bits in significand, with |z| <= 0.5 the k+1-st term
     267             :      is <= 1/(2^k k^2) of the result, so 44 terms should do */
     268     1647900 :   for (k = 1, k2 = 1, zk = z; k <= 44; k2 += 2 * k + 1, k++, zk *= z)
     269     1611280 :     r += zk / (double) k2;
     270             : 
     271       36620 :   return r;
     272             : }
     273             : 
     274             : static double
     275       36620 : dilog (double x)
     276             : {
     277             :   ASSERT(x <= -1.0); /* dilog(1-x) is called from rhoexact for 2 < x <= 3 */
     278             : 
     279       36620 :   if (x <= -2.0)
     280           0 :     return -dilog_series (1./x) - M_PI_SQR_6 - 0.5 * log(-1./x) * log(-1./x);
     281             :   else /* x <= -1.0 */
     282             :     {
     283             :       /* L2(z) = -L2(1 - z) + 1/6 * Pi^2 - ln(1 - z)*ln(z) 
     284             :          L2(z) = -L2(1/z) - 1/6 * Pi^2 - 0.5*ln^2(-1/z)
     285             :          ->
     286             :          L2(z) = -(-L2(1/(1-z)) - 1/6 * Pi^2 - 0.5*ln^2(-1/(1-z))) + 1/6 * Pi^2 - ln(1 - z)*ln(z)
     287             :                = L2(1/(1-z)) - 1/6 * Pi^2 + 0.5*ln(1 - z)^2 - ln(1 - z)*ln(-z)
     288             :          z in [-1, -2) -> 1/(1-z) in [1/2, 1/3)
     289             :       */
     290       36620 :       double log1x = log (1. - x);
     291       36620 :       return dilog_series (1. / (1. - x)) 
     292       36620 :              - M_PI_SQR_6 + log1x * (0.5 * log1x - log (-x));
     293             :     }
     294             : }
     295             : 
     296             : #if 0
     297             : static double 
     298             : L2 (double x)
     299             : {
     300             :   return log (x) * (1 - log (x-1)) + M_PI_SQR_6 - dilog (1 - x);
     301             : }
     302             : #endif
     303             : 
     304             : static double
     305       99321 : rhoexact (double x)
     306             : {
     307             :   ASSERT(x <= 3.);
     308       99321 :   if (x <= 0.)
     309         122 :     return 0.;
     310       99199 :   else if (x <= 1.)
     311       31237 :     return 1.;
     312       67962 :   else if (x <= 2.)
     313       31342 :     return 1. - log (x);
     314             :   else /* 2 < x <= 3 thus -2 <= 1-x < -1 */
     315       36620 :     return 1. - log (x) * (1. - log (x - 1.)) + dilog (1. - x) + 0.5 * M_PI_SQR_6;
     316             : }
     317             : 
     318             : 
     319             : #if defined(TESTDRIVE)
     320             : 
     321             : /* The Buchstab omega(x) function, exact for x <= 4 where it can be 
     322             :    evaluated without numerical integration, and approximated by 
     323             :    exp(gamma) for larger x. */
     324             : 
     325             : static double
     326             : Buchstab_omega (const double x)
     327             : {
     328             :   /* magic = dilog(-1) + 1  = Pi^2/12 + 1 */
     329             :   const double magic = 1.82246703342411321824; 
     330             : 
     331             :   if (x < 1.) return (0.);
     332             :   if (x <= 2.) return (1. / x);
     333             :   if (x <= 3.) return ((log (x - 1.) + 1.) / x);
     334             :   if (x <= 4.)
     335             :     return ((dilog(2. - x) + (1. + log(x - 2.)) * log(x - 1.) + magic) / x);
     336             : 
     337             :   /* If argument is out of range, return the limiting value for 
     338             :      $x->\infty$: e^-gamma. 
     339             :      For x only a little larger than 4., this has relative error 2.2e-6,
     340             :      for larger x the error rapidly drops further */
     341             : 
     342             :   return 0.56145948356688516982;
     343             : }
     344             : 
     345             : #endif
     346             : 
     347             : void 
     348         214 : rhoinit (int parm_invh, int parm_tablemax)
     349             : {
     350             :   int i;
     351             : 
     352         214 :   if (parm_invh == invh && parm_tablemax == tablemax)
     353           0 :     return;
     354             : 
     355         214 :   if (rhotable != NULL)
     356             :     {
     357          92 :       free (rhotable);
     358          92 :       rhotable = NULL;
     359          92 :       invh = 0;
     360          92 :       h = 0.;
     361          92 :       tablemax = 0;
     362             :     }
     363             :   
     364             :   /* The integration below expects 3 * invh > 4 */
     365         214 :   if (parm_tablemax == 0 || parm_invh < 2)
     366          92 :     return;
     367             :     
     368         122 :   invh = parm_invh;
     369         122 :   h = 1. / (double) invh;
     370         122 :   tablemax = parm_tablemax;
     371             :   
     372         122 :   rhotable = (double *) malloc (parm_invh * parm_tablemax * sizeof (double));
     373         122 :   ASSERT_ALWAYS(rhotable != NULL);
     374             :   
     375       93818 :   for (i = 0; i < (3 < parm_tablemax ? 3 : parm_tablemax) * invh; i++)
     376       93696 :     rhotable[i] = rhoexact (i * h);
     377             :   
     378      218746 :   for (i = 3 * invh; i < parm_tablemax * invh; i++)
     379             :     {
     380             :       /* rho(i*h) = 1 - \int_{1}^{i*h} rho(x-1)/x dx
     381             :                   = rho((i-4)*h) - \int_{(i-4)*h}^{i*h} rho(x-1)/x dx */
     382             :       
     383      218624 :       rhotable[i] = rhotable[i - 4] - 2. / 45. * (
     384      218624 :           7. * rhotable[i - invh - 4] / (double)(i - 4)
     385      218624 :         + 32. * rhotable[i - invh - 3] / (double)(i - 3)
     386      218624 :         + 12. * rhotable[i - invh - 2] / (double)(i - 2)
     387      218624 :         + 32. * rhotable[i - invh - 1] / (double)(i - 1)
     388      218624 :         + 7. * rhotable[i - invh]  / (double)i );
     389      218624 :       if (rhotable[i] < 0.)
     390             :         {
     391             : #ifndef DEBUG_NUMINTEGRATE
     392        2928 :           rhotable[i] = 0.;
     393             : #else
     394             :           printf (stderr, "rhoinit: rhotable[%d] = %.16f\n", i, 
     395             :                    rhotable[i]);
     396             :           exit (EXIT_FAILURE);
     397             : #endif
     398             :         }
     399             :     }
     400             : }
     401             : 
     402             : /* assumes alpha < tablemax */
     403             : static double
     404      207846 : dickmanrho (double alpha)
     405             : {
     406             :   ASSERT(alpha < tablemax);
     407             : 
     408      207846 :   if (alpha <= 3.)
     409        5625 :      return rhoexact (alpha);
     410             :   {
     411      202221 :     int a = floor (alpha * invh);
     412      202221 :     double rho1 = rhotable[a];
     413      202221 :     double rho2 = (a + 1) < tablemax * invh ? rhotable[a + 1] : 0;
     414      202221 :     return rho1 + (rho2 - rho1) * (alpha * invh - (double) a);
     415             :   }
     416             : }
     417             : 
     418             : #if 0
     419             : static double 
     420             : dickmanrhosigma (double alpha, double x)
     421             : {
     422             :   if (alpha <= 0.)
     423             :     return 0.;
     424             :   if (alpha <= 1.)
     425             :     return 1.;
     426             :   if (alpha < tablemax)
     427             :     return dickmanrho (alpha) + M_EULER_1 * dickmanrho (alpha - 1.) / log (x);
     428             :   
     429             :   return 0.;
     430             : }
     431             : 
     432             : static double
     433             : dickmanrhosigma_i (int ai, double x)
     434             : {
     435             :   if (ai <= 0)
     436             :     return 0.;
     437             :   if (ai <= invh)
     438             :     return 1.;
     439             :   if (ai < tablemax * invh)
     440             :     return rhotable[ai] - M_EULER * rhotable[ai - invh] / log(x);
     441             :   
     442             :   return 0.;
     443             : }
     444             : #endif
     445             : 
     446             : /* return the value of the "local" Dickman rho function, for numbers near x
     447             :    (as opposed to numbers <= x for the original Dickman rho function).
     448             :    Reference: PhD thesis of Alexander Kruppa,
     449             :    http://docnum.univ-lorraine.fr/public/SCD_T_2010_0054_KRUPPA.pdf,
     450             :    equation (5.6) page 100 */
     451             : static double
     452     1138430 : dickmanlocal (double alpha, double x)
     453             : {
     454     1138430 :   if (alpha <= 1.)
     455           0 :     return rhoexact (alpha);
     456     1138430 :   if (alpha < tablemax)
     457      103923 :     return dickmanrho (alpha) - M_EULER * dickmanrho (alpha - 1.) / log (x);
     458     1034507 :   return 0.;
     459             : }
     460             : 
     461             : static double
     462      665319 : dickmanlocal_i (int ai, double x)
     463             : {
     464      665319 :   if (ai <= 0)
     465           0 :     return 0.;
     466      665319 :   if (ai <= invh)
     467       76800 :     return 1.;
     468      588519 :   if (ai <= 2 * invh && ai < tablemax * invh)
     469       77090 :     return rhotable[ai] - M_EULER / log (x);
     470      511429 :   if (ai < tablemax * invh)
     471             :     {
     472      508665 :       double logx = log (x);
     473      508665 :       return rhotable[ai] - (M_EULER * rhotable[ai - invh]
     474      508665 :              + M_EULER_1 * rhotable[ai - 2 * invh] / logx) / logx;
     475             :     }
     476             : 
     477        2764 :   return 0.;
     478             : }
     479             : 
     480             : static int 
     481    10208050 : isprime(unsigned long n)
     482             : {
     483             :   unsigned int r;
     484             : 
     485    10208050 :   if (n % 2 == 0)
     486     5104050 :     return (n == 2);
     487     5104000 :   if (n % 3 == 0)
     488     1701200 :     return (n == 3);
     489     3402800 :   if (n % 5 == 0)
     490      680400 :     return (n == 5);
     491             : 
     492     2722400 :   if (n / 30 >= sizeof (primemap))
     493           0 :     abort();
     494             :   
     495     2722400 :   r = n % 30; /* 8 possible values: 1,7,11,13,17,19,23,29 */
     496     2722400 :   r = (r * 16 + r) / 64; /* maps the 8 values onto 0, ..., 7 */
     497             : 
     498     2722400 :   return ((primemap[n / 30] & (1 << r)) != 0);
     499             : }
     500             : 
     501             : /* return the sum in Equation (5.10) page 102 of Alexander Kruppa's
     502             :    PhD thesis */
     503             : static double
     504         630 : dickmanmu_sum (const unsigned long B1, const unsigned long B2, 
     505             :                const double x)
     506             : {
     507         630 :   double s = 0.;
     508         630 :   const double inv_logB1 = 1. / log(B1);
     509         630 :   const double logx = log(x); 
     510             :   unsigned long p;
     511             : 
     512    10208680 :   for (p = B1 + 1; p <= B2; p++)
     513    10208050 :     if (isprime(p))
     514     1134260 :       s += dickmanlocal ((logx - log(p)) * inv_logB1, x / p) / p;
     515             : 
     516         630 :   return s;
     517             : }
     518             : 
     519             : /* return the probability that a number < x has its 2nd largest prime factor
     520             :    less than x^(1/alpha) and its largest prime factor less than x^(beta/alpha)
     521             : */
     522             : static double
     523        1290 : dickmanmu (double alpha, double beta, double x)
     524             : {
     525             :   double a, b, sum;
     526             :   int ai, bi, i;
     527        1290 :   ai = ceil ((alpha - beta) * invh);
     528        1290 :   if (ai > tablemax * invh)
     529         648 :     ai = tablemax * invh;
     530        1290 :   a = (double) ai * h;
     531        1290 :   bi = floor ((alpha - 1.) * invh);
     532        1290 :   if (bi > tablemax * invh)
     533         674 :     bi = tablemax * invh;
     534        1290 :   b = (double) bi * h;
     535        1290 :   sum = 0.;
     536       77543 :   for (i = ai + 1; i < bi; i++)
     537       76253 :     sum += dickmanlocal_i (i, x) / (alpha - i * h);
     538        1290 :   sum += 0.5 * dickmanlocal_i (ai, x) / (alpha - a);
     539        1290 :   sum += 0.5 * dickmanlocal_i (bi, x) / (alpha - b);
     540        1290 :   sum *= h;
     541        1290 :   sum += (a - alpha + beta) * 0.5 * (dickmanlocal_i (ai, x) / (alpha - a) + dickmanlocal (alpha - beta, x) / beta);
     542        1290 :   sum += (alpha - 1. - b) * 0.5 * (dickmanlocal (alpha - 1., x) + dickmanlocal_i (bi, x) / (alpha - b));
     543             : 
     544        1290 :   return sum;
     545             : }
     546             : 
     547             : static double
     548         300 : brentsuyama (double B1, double B2, double N, double nr)
     549             : {
     550             :   double a, alpha, beta, sum;
     551             :   int ai, i;
     552         300 :   alpha = log (N) / log (B1);
     553         300 :   beta = log (B2) / log (B1);
     554         300 :   ai = floor ((alpha - beta) * invh);
     555         300 :   if (ai > tablemax * invh)
     556          60 :     ai = tablemax * invh;
     557         300 :   a = (double) ai * h;
     558         300 :    sum = 0.;
     559      583606 :   for (i = 1; i < ai; i++)
     560      583306 :     sum += dickmanlocal_i (i, N) / (alpha - i * h) * (1 - exp (-nr * pow (B1, (-alpha + i * h))));
     561         300 :   sum += 0.5 * (1 - exp(-nr / pow (B1, alpha)));
     562         300 :   sum += 0.5 * dickmanlocal_i (ai, N) / (alpha - a) * (1 - exp(-nr * pow (B1, (-alpha + a))));
     563         300 :   sum *= h;
     564         300 :   sum += 0.5 * (alpha - beta - a) * (dickmanlocal_i (ai, N) / (alpha - a) + dickmanlocal (alpha - beta, N) / beta);
     565             : 
     566         300 :   return sum;
     567             : }
     568             : 
     569             : static double 
     570         160 : brsudickson (double B1, double B2, double N, double nr, int S)
     571             : {
     572             :   int i, f;
     573             :   double sum;
     574         160 :   sum = 0;
     575         160 :   f = eulerphi (S) / 2;
     576        1060 :   for (i = 1; i <= S / 2; i++)
     577         900 :       if (gcd (i, S) == 1)
     578         300 :         sum += brentsuyama (B1, B2, N, nr * (gcd (i - 1, S) + gcd (i + 1, S) - 4) / 2);
     579             :   
     580         160 :   return sum / (double)f;
     581             : }
     582             : 
     583             : static double
     584           0 : brsupower (double B1, double B2, double N, double nr, int S)
     585             : {
     586             :   int i, f;
     587             :   double sum;
     588           0 :   sum = 0;
     589           0 :   f = eulerphi (S);
     590           0 :   for (i = 1; i < S; i++)
     591           0 :       if (gcd (i, S) == 1)
     592           0 :         sum += brentsuyama (B1, B2, N, nr * (gcd (i - 1, S) - 2));
     593             :   
     594           0 :   return sum / (double)f;
     595             : }
     596             : 
     597             : /* Assume N is as likely smooth as a number around N/exp(delta) */
     598             : 
     599             : static double
     600        1310 : prob (double B1, double B2, double N, double nr, int S, double delta)
     601             : {
     602        1310 :   const double sumthresh = 20000.;
     603             :   double alpha, beta, stage1, stage2, brsu;
     604        1310 :   const double effN = N / exp (delta);
     605             : 
     606             :   ASSERT(rhotable != NULL);
     607             :   
     608             :   /* What to do if rhotable is not initialised and asserting is not enabled?
     609             :      For now, bail out with 0. result. Not really pretty, either */
     610        1310 :   if (rhotable == NULL)
     611           0 :     return 0.;
     612             : 
     613        1310 :   if (B1 < 2. || N <= 1.)
     614          20 :     return 0.;
     615             :   
     616        1290 :   if (effN <= B1)
     617           0 :     return 1.;
     618             : 
     619             : #ifdef TESTDRIVE
     620             :   printf ("B1 = %f, B2 = %f, N = %.0f, nr = %f, S = %d\n", B1, B2, N, nr, S);
     621             : #endif
     622             :   
     623        1290 :   alpha = log (effN) / log (B1);
     624        1290 :   stage1 = dickmanlocal (alpha, effN);
     625        1290 :   stage2 = 0.;
     626        1290 :   if (B2 > B1)
     627             :     {
     628        1290 :       if (B1 < sumthresh)
     629             :         {
     630         630 :           stage2 += dickmanmu_sum (B1, MIN(B2, sumthresh), effN);
     631         630 :           beta = log (B2) / log (MIN(B2, sumthresh));
     632             :         }
     633             :       else
     634         660 :         beta = log (B2) / log (B1);
     635             : 
     636        1290 :       if (beta > 1.)
     637        1290 :         stage2 += dickmanmu (alpha, beta, effN);
     638             :     }
     639        1290 :   brsu = 0.;
     640        1290 :   if (S < -1)
     641         160 :     brsu = brsudickson (B1, B2, effN, nr, -S * 2);
     642        1290 :   if (S > 1)
     643           0 :     brsu = brsupower (B1, B2, effN, nr, S * 2);
     644             : 
     645             : #ifdef TESTDRIVE
     646             :   printf ("stage 1 : %f, stage 2 : %f, Brent-Suyama : %f\n", stage1, stage2, brsu);
     647             : #endif
     648             : 
     649        1290 :   return (stage1 + stage2 + brsu) > 0. ? (stage1 + stage2 + brsu) : 0.;
     650             : }
     651             : 
     652             : double
     653         660 : ecmprob (double B1, double B2, double N, double nr, int S)
     654             : {
     655         660 :   return prob (B1, B2, N, nr, S, ECM_EXTRA_SMOOTHNESS);
     656             : }
     657             : 
     658             : /* see Willemien Ekkelkamp's Phd thesis:
     659             :    https://openaccess.leidenuniv.nl/bitstream/handle/1887/14567/proefschrift_041109.pdf?sequence=2:
     660             :    Bach-Peralta formula page 12
     661             :    Corollary 4 page 18 with a 2nd-order term */
     662             : double
     663         650 : pm1prob (double B1, double B2, double N, double nr, int S, const mpz_t go)
     664             : {
     665             :   mpz_t cof;
     666             :   /* A prime power q^k divides p-1, p prime, with probability 1/(q^k-q^(k-1))
     667             :      not with probability 1/q^k as for random numbers. This is taken into 
     668             :      account by the "smoothness" value here; a prime p-1 is about as likely
     669             :      smooth as a random number around (p-1)/exp(smoothness).
     670             :      smoothness = \sum_{q in Primes} log(q)/(q-1)^2 */
     671             :   /* Note that this routine is also called for P+1, where we assume the same
     672             :      behaviour as with P-1. However, if x0=6/5, Kruppa writes in his PhD
     673             :      thesis that we get smoothness = 1.92012; with x0=2/7, we get
     674             :      smoothness = 2.05093. */
     675         650 :   double smoothness = 1.2269688;
     676             :   unsigned long i;
     677             :   
     678         650 :   if (go != NULL && mpz_cmp_ui (go, 1UL) > 0)
     679             :     {
     680             :       double res;
     681          50 :       mpz_init (cof);
     682          50 :       mpz_set (cof, go);
     683        4950 :       for (i = 2; i < 100; i++)
     684        4900 :         if (mpz_divisible_ui_p (cof, i))
     685             :           {
     686             :             /* If we know that q divides p-1 with probability 1, we need to
     687             :                adjust the smoothness parameter */
     688          50 :             smoothness -= log ((double) i) / (double) ((i-1)*(i-1));
     689             :             /* printf ("pm1prob: Dividing out %lu\n", i); */
     690         100 :             while (mpz_divisible_ui_p (cof, i))
     691          50 :               mpz_tdiv_q_ui (cof, cof, i);
     692             :           }
     693             :       /* printf ("pm1prob: smoothness after dividing out go primes < 100: %f\n", 
     694             :                smoothness); */
     695          50 :       res = prob (B1, B2, N, nr, S, smoothness + log(mpz_get_d (cof)));
     696          50 :       mpz_clear (cof);
     697          50 :       return res;
     698             :     }
     699             : 
     700         600 :   return prob (B1, B2, N, nr, S, smoothness);
     701             : }
     702             : 
     703             : #if defined(TESTDRIVE)
     704             : 
     705             : /* Compute probability for primes p == r (mod m) */
     706             : 
     707             : static double
     708             : pm1prob_rm (double B1, double B2, double N, double nr, int S, unsigned long r,
     709             :             unsigned long m)
     710             : {
     711             :   unsigned long cof;
     712             :   double smoothness = 1.2269688;
     713             :   unsigned long p;
     714             :   
     715             :   cof = m;
     716             :   
     717             :   for (p = 2UL; p < 100UL; p++)
     718             :     if (cof % p == 0UL) /* For each prime in m */
     719             :       {
     720             :         unsigned long cof_r, k, i;
     721             :         /* Divisibility by i is determined by r and m. We need to
     722             :            adjust the smoothness parameter. In P-1, we had estimated the 
     723             :            expected value for the exponent of p as p/(p-1)^2. Undo that. */
     724             :         smoothness -= (double)p / ((p-1)*(p-1)) * log ((double) p);
     725             :         /* The expected value for the exponent of this prime is k s.t.
     726             :            p^k || r, plus 1/(p-1) if p^k || m as well */
     727             :         cof_r = gcd (r - 1UL, m);
     728             :         for (k = 0UL; cof_r % p == 0UL; k++)
     729             :           cof_r /= p;
     730             :         smoothness += k * log ((double) p);
     731             : 
     732             :         cof_r = m;
     733             :         for (i = 0UL; cof_r % p == 0UL; i++)
     734             :           cof_r /= p;
     735             : 
     736             :         if (i == k)
     737             :           smoothness += (1./(p - 1.) * log ((double) p));
     738             :         
     739             :         while (cof % p == 0UL)
     740             :           cof /= p;
     741             :         printf ("pm1prob_rm: p = %lu, k = %lu, i = %lu, new smoothness = %f\n", 
     742             :                 p, i, k, smoothness); 
     743             :       }
     744             : 
     745             :   return prob (B1, B2, N, nr, S, smoothness);
     746             : }
     747             : 
     748             : 
     749             : /* The \Phi(x,y) function gives the number of natural numbers <= x 
     750             :    that have no prime factor <= y, see Tenenbaum, 
     751             :    "Introduction the analytical and probabilistic number theory", III.6.
     752             :    This function estimates the \Phi(x,y) function via eq. (48) of the 1st
     753             :    edition resp. equation (6.49) of the 3rd edition of Tenenbaum's book. */
     754             : 
     755             : static double 
     756             : integrand1 (double x, double *y)
     757             : {
     758             :   return pow (*y, x) / x * log(x-1.);
     759             : }
     760             : 
     761             : 
     762             : static double 
     763             : integrand2 (double v, double *y)
     764             : {
     765             :   return Buchstab_omega (v) * pow (*y, v);
     766             : }
     767             : 
     768             : 
     769             : /* Return approximate number of integers n with x1 < n <= x2
     770             :    that have no prime factor <= y */
     771             : 
     772             : double 
     773             : no_small_prime (double x1, double x2, double y)
     774             : {
     775             :   double u1, u2;
     776             :   ASSERT (x1 >= 2.);
     777             :   ASSERT (x2 >= x1);
     778             :   ASSERT (y >= 2.);
     779             :   if (x1 == x2 || x2 <= y)
     780             :     return 0.;
     781             :   if (x1 < y)
     782             :     x1 = y;
     783             :   
     784             :   u1 = log(x1)/log(y);
     785             :   u2 = log(x2)/log(y);
     786             : 
     787             :    /* If no prime factors <= sqrt(x2), numbers must be a primes > y */
     788             :   if (x2 <= y*y)
     789             :     return (Li(x2) - Li(x1));
     790             :   
     791             :   if (u2 <= 3)
     792             :     {
     793             :       double r, abserr;
     794             :       size_t neval;
     795             :       gsl_function f;
     796             : 
     797             :       f.function = (double (*) (double, void *)) &integrand1;
     798             :       f.params = &y;
     799             : 
     800             :       /* intnum(v=1,u,buchstab(v)*y^v) */
     801             : 
     802             :       /* First part: intnum(v=u1, u, y^v/v*log(v-1.)) */
     803             :       gsl_integration_qng (&f, MAX(u1, 2.) , u2, 0., 0.001, &r, &abserr, &neval);
     804             : 
     805             :       /* Second part: intnum(v=u1, u2, y^v/v) = Li(x2) - Li(x1) */
     806             :       r += Li (x2) - Li (x1);
     807             :       
     808             :       return r;
     809             :     }
     810             :     
     811             :   {
     812             :     double r, abserr;
     813             :     size_t neval;
     814             :     gsl_function f;
     815             :   
     816             :     f.function = (double (*) (double, void *)) &integrand2;
     817             :     f.params = &y;
     818             :     
     819             :     gsl_integration_qng (&f, u1, u2, 0., 0.001, &r, &abserr, &neval);
     820             :     return r;
     821             :   }
     822             : }
     823             : 
     824             : 
     825             : static double 
     826             : integrand3 (double p, double *param)
     827             : {
     828             :   const double x1 = param[0];
     829             :   const double x2 = param[1];
     830             :   const double y = param[2];
     831             :   
     832             :   return no_small_prime (x1 / p, x2 / p, y) / log(p);
     833             : }
     834             : 
     835             : 
     836             : double 
     837             : no_small_prime_factor (const double x1, const double x2, const double y, 
     838             :                        const double z1, const double z2)
     839             : {
     840             :   double r, abserr, param[3];
     841             :   size_t neval;
     842             :   gsl_function f;
     843             : 
     844             :   param[0] = x1;
     845             :   param[1] = x2;
     846             :   param[2] = y;
     847             :   f.function = (double (*) (double, void *)) &integrand3;
     848             :   f.params = &param;
     849             :   
     850             :   gsl_integration_qng (&f, z1, z2, 0., 0.01, &r, &abserr, &neval);
     851             :   
     852             :   return r;
     853             : }
     854             : 
     855             : #endif
     856             : 
     857             : 
     858             : #ifdef TESTDRIVE
     859             : int
     860             : main (int argc, char **argv)
     861             : {
     862             :   double B1, B2, N, nr, r, m;
     863             :   int S;
     864             :   unsigned long p, i, pi;
     865             :   primesieve_iterator pg[1];
     866             : 
     867             :   primesieve_init (pg);
     868             :   i = pi = 0;
     869             :   for (p = primesieve_next_prime (pg); p <= PRIME_PI_MAX; p = primesieve_next_prime (pg))
     870             :     {
     871             :       for ( ; i < p; i++)
     872             :         prime_pi[PRIME_PI_MAP(i)] = pi;
     873             :       pi++;
     874             :     }
     875             :   for ( ; i < p; i++)
     876             :     prime_pi[PRIME_PI_MAP(i)] = pi;
     877             :   
     878             : 
     879             :   if (argc < 2)
     880             :     {
     881             :       printf ("Usage: rho <B1> <B2> <N> <nr> <S> [<r> <m>]\n\n\n");
     882             :       printf (" Calculate the probability of ECM/P-1 finding a factor near N\n"
     883             :               " with B1/B2, evaluating nr random distinct points in stage 2,\n"
     884             :               " with a degree -S Dickson polynomial (if S < 0) or\n"
     885             :               " S'th power as the Brent-Suyama function\n\n");
     886             :       printf (" <B1>        B1 limit.\n");
     887             :       printf (" <B2>        B2 limit.\n");
     888             :       printf (" <N>         N of similiar size, or number of bits in factor (if < 50).\n");
     889             :       printf (" <nr>        Number of random points evaluated in stage 2.\n");
     890             :       printf (" <S>         Degree of Brent-Suyama polynomial in stage 2.\n");
     891             :       printf (" [<r> <m>]   Limit P-1 to primes p == r (mod m).\n");
     892             :       return 1;
     893             :     }
     894             :   
     895             :   if (strcmp (argv[1], "-Buchstab_Phi") == 0)
     896             :     {
     897             :       unsigned long x, y, r;
     898             :       if (argc < 4)
     899             :         {
     900             :           printf ("-Buchstab_Phi needs x and y paramters\n");
     901             :           exit (EXIT_FAILURE);
     902             :         }
     903             :       x = strtoul (argv[2], NULL, 10);
     904             :       y = strtoul (argv[3], NULL, 10);
     905             :       r = Buchstab_Phi (x, y);
     906             :       printf ("Buchstab_Phi (%lu, %lu) = %lu\n", x, y, r);
     907             :       exit (EXIT_SUCCESS);
     908             :     }
     909             :   else if (strcmp (argv[1], "-Buchstab_Psi") == 0)
     910             :     {
     911             :       unsigned long x, y, r;
     912             :       if (argc < 4)
     913             :         {
     914             :           printf ("-Buchstab_Psi needs x and y paramters\n");
     915             :           exit (EXIT_FAILURE);
     916             :         }
     917             :       x = strtoul (argv[2], NULL, 10);
     918             :       y = strtoul (argv[3], NULL, 10);
     919             :       r = Buchstab_Psi (x, y);
     920             :       printf ("Buchstab_Psi (%lu, %lu) = %lu\n", x, y, r);
     921             :       exit (EXIT_SUCCESS);
     922             :     }
     923             :   else if (strcmp (argv[1], "-nsp") == 0)
     924             :     {
     925             :       double x1, x2, y, r;
     926             :       
     927             :       if (argc < 5)
     928             :         {
     929             :           printf ("-nsp needs x1, x2, and y paramters\n");
     930             :           exit (EXIT_FAILURE);
     931             :         }
     932             :       x1 = atof (argv[2]);
     933             :       x2 = atof (argv[3]);
     934             :       y = atof (argv[4]);
     935             :       r = no_small_prime (x1, x2, y);
     936             :       printf ("no_small_prime(%f, %f, %f) = %f\n", x1, x2, y, r);
     937             :       exit (EXIT_SUCCESS);
     938             :     }
     939             :   else if (strcmp (argv[1], "-nspf") == 0)
     940             :     {
     941             :       double x1, x2, y, z1, z2, r;
     942             :       
     943             :       if (argc < 7)
     944             :         {
     945             :           printf ("-nspf needs x1, x2, y, z1, and z2 paramters\n");
     946             :           exit (EXIT_FAILURE);
     947             :         }
     948             :       x1 = atof (argv[2]);
     949             :       x2 = atof (argv[3]);
     950             :       y = atof (argv[4]);
     951             :       z1 = atof (argv[5]);
     952             :       z2 = atof (argv[6]);
     953             :       r = no_small_prime_factor (x1, x2, y, z1, z2);
     954             :       printf ("no_small_prime(%f, %f, %f, %f, %f) = %f\n", x1, x2, y, z1, z2, r);
     955             :       exit (EXIT_SUCCESS);
     956             :     }
     957             : 
     958             : 
     959             :   if (argc < 6)
     960             :     {
     961             :       printf ("Need 5 or 7 arguments: B1 B2 N nr S [r m]\n");
     962             :       exit (EXIT_FAILURE);
     963             :     }
     964             :   
     965             :   B1 = atof (argv[1]);
     966             :   B2 = atof (argv[2]);
     967             :   N = atof (argv[3]);
     968             :   nr = atof (argv[4]);
     969             :   S = atoi (argv[5]);
     970             :   r = 0; m = 1;
     971             :   if (argc > 7)
     972             :     {
     973             :       r = atoi (argv[6]);
     974             :       m = atoi (argv[7]);
     975             :     }
     976             : 
     977             :   rhoinit (256, 10);
     978             :   if (N < 50.)
     979             :     {
     980             :       double sum;
     981             :       sum = ecmprob(B1, B2, exp2 (N), nr, S);
     982             :       sum += 4. * ecmprob(B1, B2, 3./2. * exp2 (N), nr, S);
     983             :       sum += ecmprob(B1, B2, 2. * exp2 (N), nr, S);
     984             :       sum *= 1./6.;
     985             :       printf ("ECM: %.16f\n", sum);
     986             : 
     987             :       sum = pm1prob_rm (B1, B2, exp2 (N), nr, S, r, m);
     988             :       sum += 4. * pm1prob_rm (B1, B2, 3./2. * exp2 (N), nr, S, r, m);
     989             :       sum += pm1prob_rm (B1, B2, 2. * exp2 (N), nr, S, r, m);
     990             :       sum *= 1./6.;
     991             :       printf ("P-1: %.16f\n", sum);
     992             :     }
     993             :   else
     994             :     {
     995             :       printf ("ECM: %.16f\n", ecmprob(B1, B2, N, nr, S));
     996             :       printf ("P-1: %.16f\n", pm1prob_rm (B1, B2, N, nr, S, r, m));
     997             :     }
     998             :   rhoinit (0, 0);
     999             :   return 0;
    1000             : }
    1001             : #endif

Generated by: LCOV version 1.14