prime_sieve

Marco Bodrato bodrato at mail.dm.unipi.it
Sun Jan 3 14:58:07 UTC 2016


Ciao,

Il Dom, 3 Gennaio 2016 3:42 pm, Marco Bodrato ha scritto:
> I attach the code.

The list does not like my attachments...

-----8<-----------8<----------
/* gmp_numberofprimesupto_ui (N) -- Returns the number the primes in
   the range [0..N].
   gmp_prime_sieve (S, E, *c, F) -- Calls F(c,p) for each prime p in
   the range [S..E]; when the range is over or F returns a non-zero
   value, it returns the number of used primes.

THE FUNCTION IN THIS FILE USE INTERNAL FUNCTIONS OF GMP, WITH A
MUTABLE INTERFACE.  IT WAS ONLY TESTED WITH GMP-6.1; IT IS ALMOST
GUARANTEED THAT IT WILL NOT WORK WITH A FUTURE GNU MP RELEASE.

Copyright 2012, 2015, 2016 Marco Bodrato.

This file is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 3 of the License, or (at your
option) any later version.

see https://www.gnu.org/licenses/.  */

#include "gmp.h"
#include "gmp-impl.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/*********************************************************/
/* Section sieve: sieving functions and tools for primes */
/*********************************************************/

static mp_limb_t
n_to_bit (mp_limb_t n) { return ((n-5)|1)/3U; }

/* id_to_n (x) = bit_to_n (x-1) = (id*3+1)|1*/
static mp_limb_t
id_to_n  (mp_limb_t id)  { return id*3+1+(id&1); }

static mp_size_t
primesieve_size (mp_limb_t n) { return n_to_bit(n) / GMP_LIMB_BITS + 1; }

/*************************************************************/
/* Section macros: common macros, for swing/fac/bin (&sieve) */
/*************************************************************/

#define LOOP_ON_SIEVE_CONTINUE(prime,end,sieve)			\
    __max_i = (end);						\
								\
    do {							\
      ++__i;							\
      if (((sieve)[__index] & __mask) == 0)			\
	{							\
          mp_limb_t prime;					\
	  prime = id_to_n(__i)

#define LOOP_ON_SIEVE_BEGIN(prime,start,end,off,sieve)		\
  do {								\
    mp_limb_t __mask, __index, __max_i, __i;			\
								\
    __i = (start)-(off);					\
    __index = __i / GMP_LIMB_BITS;				\
    __mask = CNST_LIMB(1) << (__i % GMP_LIMB_BITS);		\
    __i += (off);						\
								\
    LOOP_ON_SIEVE_CONTINUE(prime,end,sieve)

#define LOOP_ON_SIEVE_STOP					\
	}							\
      __mask = __mask << 1 | __mask >> (GMP_LIMB_BITS-1);	\
      __index += __mask & 1;					\
    }  while (__i <= __max_i)

#define LOOP_ON_SIEVE_END					\
    LOOP_ON_SIEVE_STOP;						\
  } while (0)

typedef int prime_callback_func (void *ctx, unsigned long prime);

unsigned long
gmp_prime_sieve (unsigned long start, unsigned long end,
		 void *ctx, prime_callback_func *f)
{
  unsigned long ret;

  ret = (start <= 2) & (2 <= end);
  if ((ret) && (*f) (ctx, 2))
    return 1;
  if ((start <= 3) & (3 <= end))
    {
      ++ret;
      if ((*f) (ctx, 3))
	return ret;
    }
  if (end > 4)
    {
      mp_limb_t *sieve;
      mp_size_t size;

      size = primesieve_size (end);

      sieve = __GMP_ALLOCATE_FUNC_LIMBS (size);
      gmp_primesieve (sieve, end);
      start = MAX (start, 5) | 1;
      LOOP_ON_SIEVE_BEGIN (prime, n_to_bit(start) + (start % 3 == 0),
n_to_bit (end), 0, sieve);
      ++ret;
      if ((*f) (ctx, prime)) break;
      LOOP_ON_SIEVE_END;

      __GMP_FREE_FUNC_LIMBS (sieve, size);
    }
  return ret;
}

unsigned long
gmp_numberofprimesupto_ui (unsigned long n)
{
  static const unsigned table[] = { 0, 0, 1, 2, 2 };

  if (n < numberof (table))
    return table[n];
  else
    {
      mp_limb_t *sieve;
      mp_size_t size;
      unsigned int ret;

      size = primesieve_size (n);

      sieve = __GMP_ALLOCATE_FUNC_LIMBS (size);
      ret = gmp_primesieve (sieve, n);
      __GMP_FREE_FUNC_LIMBS (sieve, size);

      return table[numberof (table)-1] + ret;
    }
}

#ifdef MAIN
int
count3mod4 (void *ctx, unsigned long prime)
{
  *(unsigned long*) ctx += (prime > 2) & (prime >> 1);
  return 0;
}

int
main (int argc, char *argv[])
{
  unsigned long s, N, c;

  s = 0;
  N = strtoul (argv[1], NULL, 0);
  if (argc > 2)
    {
      s = N;
      N = strtoul (argv[2], NULL, 0);
    }

  c = 0;
  printf ("pi(%lu .. %lu)=%lu\n", s, N, gmp_prime_sieve (s, N, &c,
&count3mod4));
  printf ("pi(%lu .. %lu,=3 mod 4)=%lu\n", s, N, c);

  return 0;
}
#endif

#ifdef MAINPI
int
main (int argc, char *argv[])
{
  unsigned long N;

  N = strtoul (argv[1], NULL, 0);

  printf ("pi(0 .. %lu)=%lu\n", N, gmp_numberofprimesupto_ui (N));

  return 0;
}
#endif


-----8<-----------8<----------



-- 
http://bodrato.it/



More information about the gmp-discuss mailing list