sieve.c
上传用户:lyxiangda
上传日期:2007-01-12
资源大小:3042k
文件大小:6k
源码类别:

CA认证

开发平台:

WINDOWS

  1. /*
  2.  * sieve.c
  3.  *
  4.  * Finds prime numbers using the Sieve of Eratosthenes
  5.  *
  6.  * This implementation uses a bitmap to represent all odd integers in a
  7.  * given range.  We iterate over this bitmap, crossing off the
  8.  * multiples of each prime we find.  At the end, all the remaining set
  9.  * bits correspond to prime integers.
  10.  *
  11.  * Here, we make two passes -- once we have generated a sieve-ful of
  12.  * primes, we copy them out, reset the sieve using the highest
  13.  * generated prime from the first pass as a base.  Then we cross out
  14.  * all the multiples of all the primes we found the first time through,
  15.  * and re-sieve.  In this way, we get double use of the memory we
  16.  * allocated for the sieve the first time though.  Since we also
  17.  * implicitly ignore multiples of 2, this amounts to 4 times the
  18.  * values.
  19.  *
  20.  * This could (and probably will) be generalized to re-use the sieve a
  21.  * few more times.
  22.  *
  23.  * The contents of this file are subject to the Mozilla Public
  24.  * License Version 1.1 (the "License"); you may not use this file
  25.  * except in compliance with the License. You may obtain a copy of
  26.  * the License at http://www.mozilla.org/MPL/
  27.  *
  28.  * Software distributed under the License is distributed on an "AS
  29.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  30.  * implied. See the License for the specific language governing
  31.  * rights and limitations under the License.
  32.  *
  33.  * The Original Code is the MPI Arbitrary Precision Integer Arithmetic
  34.  * library.
  35.  *
  36.  * The Initial Developer of the Original Code is Michael J. Fromberger.
  37.  * Portions created by Michael J. Fromberger are 
  38.  * Copyright (C) 1998, 1999, 2000 Michael J. Fromberger. 
  39.  * All Rights Reserved.
  40.  *
  41.  * Contributor(s):
  42.  *
  43.  * Alternatively, the contents of this file may be used under the
  44.  * terms of the GNU General Public License Version 2 or later (the
  45.  * "GPL"), in which case the provisions of the GPL are applicable
  46.  * instead of those above.  If you wish to allow use of your
  47.  * version of this file only under the terms of the GPL and not to
  48.  * allow others to use your version of this file under the MPL,
  49.  * indicate your decision by deleting the provisions above and
  50.  * replace them with the notice and other provisions required by
  51.  * the GPL.  If you do not delete the provisions above, a recipient
  52.  * may use your version of this file under either the MPL or the GPL.
  53.  *
  54.  *  $Id: sieve.c,v 1.1 2000/07/14 00:45:02 nelsonb%netscape.com Exp $
  55.  */
  56. #include <stdio.h>
  57. #include <stdlib.h>
  58. #include <limits.h>
  59. typedef unsigned char  byte;
  60. typedef struct {
  61.   int   size;
  62.   byte *bits;
  63.   long  base;
  64.   int   next;
  65.   int   nbits;
  66. } sieve;
  67. void sieve_init(sieve *sp, long base, int nbits);
  68. void sieve_grow(sieve *sp, int nbits);
  69. long sieve_next(sieve *sp);
  70. void sieve_reset(sieve *sp, long base);
  71. void sieve_cross(sieve *sp, long val);
  72. void sieve_clear(sieve *sp);
  73. #define S_ISSET(S, B)  (((S)->bits[(B)/CHAR_BIT]>>((B)%CHAR_BIT))&1)
  74. #define S_SET(S, B)    ((S)->bits[(B)/CHAR_BIT]|=(1<<((B)%CHAR_BIT)))
  75. #define S_CLR(S, B)    ((S)->bits[(B)/CHAR_BIT]&=~(1<<((B)%CHAR_BIT)))
  76. #define S_VAL(S, B)    ((S)->base+(2*(B)))
  77. #define S_BIT(S, V)    (((V)-((S)->base))/2)
  78. int main(int argc, char *argv[])
  79. {
  80.   sieve   s;
  81.   long    pr, *p;
  82.   int     c, ix, cur = 0;
  83.   if(argc < 2) {
  84.     fprintf(stderr, "Usage: %s <width>n", argv[0]);
  85.     return 1;
  86.   }
  87.   c = atoi(argv[1]);
  88.   if(c < 0) c = -c;
  89.   fprintf(stderr, "%s: sieving to %d positionsn", argv[0], c);
  90.   sieve_init(&s, 3, c);
  91.   c = 0;
  92.   while((pr = sieve_next(&s)) > 0) {
  93.     ++c;
  94.   }
  95.   p = calloc(c, sizeof(long));
  96.   if(!p) {
  97.     fprintf(stderr, "%s: out of memory after first halfn", argv[0]);
  98.     sieve_clear(&s);
  99.     exit(1);
  100.   }
  101.   fprintf(stderr, "%s: half done ... n", argv[0]);
  102.   for(ix = 0; ix < s.nbits; ix++) {
  103.     if(S_ISSET(&s, ix)) {
  104.       p[cur] = S_VAL(&s, ix);
  105.       printf("%ldn", p[cur]);
  106.       ++cur;
  107.     }
  108.   }
  109.   sieve_reset(&s, p[cur - 1]);
  110.   fprintf(stderr, "%s: crossing off %d found primes ... n", argv[0], cur);
  111.   for(ix = 0; ix < cur; ix++) {
  112.     sieve_cross(&s, p[ix]);
  113.     if(!(ix % 1000))
  114.       fputc('.', stderr);
  115.   }
  116.   fputc('n', stderr);
  117.   free(p);
  118.   fprintf(stderr, "%s: sieving again from %ld ... n", argv[0], p[cur - 1]);
  119.   c = 0;
  120.   while((pr = sieve_next(&s)) > 0) {
  121.     ++c;
  122.   }
  123.   
  124.   fprintf(stderr, "%s: done!n", argv[0]);
  125.   for(ix = 0; ix < s.nbits; ix++) {
  126.     if(S_ISSET(&s, ix)) {
  127.       printf("%ldn", S_VAL(&s, ix));
  128.     }
  129.   }
  130.   sieve_clear(&s);
  131.   return 0;
  132. }
  133. void sieve_init(sieve *sp, long base, int nbits)
  134. {
  135.   sp->size = (nbits / CHAR_BIT);
  136.   if(nbits % CHAR_BIT)
  137.     ++sp->size;
  138.   sp->bits = calloc(sp->size, sizeof(byte));
  139.   memset(sp->bits, UCHAR_MAX, sp->size);
  140.   if(!(base & 1))
  141.     ++base;
  142.   sp->base = base;
  143.   
  144.   sp->next = 0;
  145.   sp->nbits = sp->size * CHAR_BIT;
  146. }
  147. void sieve_grow(sieve *sp, int nbits)
  148. {
  149.   int  ns = (nbits / CHAR_BIT);
  150.   if(nbits % CHAR_BIT)
  151.     ++ns;
  152.   if(ns > sp->size) {
  153.     byte   *tmp;
  154.     int     ix;
  155.     tmp = calloc(ns, sizeof(byte));
  156.     if(tmp == NULL) {
  157.       fprintf(stderr, "Error: out of memory in sieve_grown");
  158.       return;
  159.     }
  160.     memcpy(tmp, sp->bits, sp->size);
  161.     for(ix = sp->size; ix < ns; ix++) {
  162.       tmp[ix] = UCHAR_MAX;
  163.     }
  164.     free(sp->bits);
  165.     sp->bits = tmp;
  166.     sp->size = ns;
  167.     sp->nbits = sp->size * CHAR_BIT;
  168.   }
  169. }
  170. long sieve_next(sieve *sp)
  171. {
  172.   long out;
  173.   int  ix = 0;
  174.   long val;
  175.   if(sp->next > sp->nbits)
  176.     return -1;
  177.   out = S_VAL(sp, sp->next);
  178. #ifdef DEBUG
  179.   fprintf(stderr, "Sieving %ldn", out);
  180. #endif
  181.   /* Sieve out all multiples of the current prime */
  182.   val = out;
  183.   while(ix < sp->nbits) {
  184.     val += out;
  185.     ix = S_BIT(sp, val);
  186.     if((val & 1) && ix < sp->nbits) { /* && S_ISSET(sp, ix)) { */
  187.       S_CLR(sp, ix);
  188. #ifdef DEBUG
  189.       fprintf(stderr, "Crossing out %ld (bit %d)n", val, ix);
  190. #endif
  191.     }
  192.   }
  193.   /* Scan ahead to the next prime */
  194.   ++sp->next;
  195.   while(sp->next < sp->nbits && !S_ISSET(sp, sp->next))
  196.     ++sp->next;
  197.   return out;
  198. }
  199. void sieve_cross(sieve *sp, long val)
  200. {
  201.   int  ix = 0;
  202.   long cur = val;
  203.   while(cur < sp->base)
  204.     cur += val;
  205.   ix = S_BIT(sp, cur);
  206.   while(ix < sp->nbits) {
  207.     if(cur & 1) 
  208.       S_CLR(sp, ix);
  209.     cur += val;
  210.     ix = S_BIT(sp, cur);
  211.   }
  212. }
  213. void sieve_reset(sieve *sp, long base)
  214. {
  215.   memset(sp->bits, UCHAR_MAX, sp->size);
  216.   sp->base = base;
  217.   sp->next = 0;
  218. }
  219. void sieve_clear(sieve *sp)
  220. {
  221.   if(sp->bits) 
  222.     free(sp->bits);
  223.   sp->bits = NULL;
  224. }