⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sieve.c

📁 支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS #11, PKCS #12, S/MIME, X.509v3证书等安全协议或标准的开发库编译用到NSPR
💻 C
字号:
/* * sieve.c * * Finds prime numbers using the Sieve of Eratosthenes * * This implementation uses a bitmap to represent all odd integers in a * given range.  We iterate over this bitmap, crossing off the * multiples of each prime we find.  At the end, all the remaining set * bits correspond to prime integers. * * Here, we make two passes -- once we have generated a sieve-ful of * primes, we copy them out, reset the sieve using the highest * generated prime from the first pass as a base.  Then we cross out * all the multiples of all the primes we found the first time through, * and re-sieve.  In this way, we get double use of the memory we * allocated for the sieve the first time though.  Since we also * implicitly ignore multiples of 2, this amounts to 4 times the * values. * * This could (and probably will) be generalized to re-use the sieve a * few more times. * * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is the MPI Arbitrary Precision Integer Arithmetic * library. * * The Initial Developer of the Original Code is Michael J. Fromberger. * Portions created by Michael J. Fromberger are  * Copyright (C) 1998, 1999, 2000 Michael J. Fromberger.  * All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL"), in which case the provisions of the GPL are applicable * instead of those above.  If you wish to allow use of your * version of this file only under the terms of the GPL and not to * allow others to use your version of this file under the MPL, * indicate your decision by deleting the provisions above and * replace them with the notice and other provisions required by * the GPL.  If you do not delete the provisions above, a recipient * may use your version of this file under either the MPL or the GPL. * *  $Id: sieve.c,v 1.1 2000/07/14 00:45:02 nelsonb%netscape.com Exp $ */#include <stdio.h>#include <stdlib.h>#include <limits.h>typedef unsigned char  byte;typedef struct {  int   size;  byte *bits;  long  base;  int   next;  int   nbits;} sieve;void sieve_init(sieve *sp, long base, int nbits);void sieve_grow(sieve *sp, int nbits);long sieve_next(sieve *sp);void sieve_reset(sieve *sp, long base);void sieve_cross(sieve *sp, long val);void sieve_clear(sieve *sp);#define S_ISSET(S, B)  (((S)->bits[(B)/CHAR_BIT]>>((B)%CHAR_BIT))&1)#define S_SET(S, B)    ((S)->bits[(B)/CHAR_BIT]|=(1<<((B)%CHAR_BIT)))#define S_CLR(S, B)    ((S)->bits[(B)/CHAR_BIT]&=~(1<<((B)%CHAR_BIT)))#define S_VAL(S, B)    ((S)->base+(2*(B)))#define S_BIT(S, V)    (((V)-((S)->base))/2)int main(int argc, char *argv[]){  sieve   s;  long    pr, *p;  int     c, ix, cur = 0;  if(argc < 2) {    fprintf(stderr, "Usage: %s <width>\n", argv[0]);    return 1;  }  c = atoi(argv[1]);  if(c < 0) c = -c;  fprintf(stderr, "%s: sieving to %d positions\n", argv[0], c);  sieve_init(&s, 3, c);  c = 0;  while((pr = sieve_next(&s)) > 0) {    ++c;  }  p = calloc(c, sizeof(long));  if(!p) {    fprintf(stderr, "%s: out of memory after first half\n", argv[0]);    sieve_clear(&s);    exit(1);  }  fprintf(stderr, "%s: half done ... \n", argv[0]);  for(ix = 0; ix < s.nbits; ix++) {    if(S_ISSET(&s, ix)) {      p[cur] = S_VAL(&s, ix);      printf("%ld\n", p[cur]);      ++cur;    }  }  sieve_reset(&s, p[cur - 1]);  fprintf(stderr, "%s: crossing off %d found primes ... \n", argv[0], cur);  for(ix = 0; ix < cur; ix++) {    sieve_cross(&s, p[ix]);    if(!(ix % 1000))      fputc('.', stderr);  }  fputc('\n', stderr);  free(p);  fprintf(stderr, "%s: sieving again from %ld ... \n", argv[0], p[cur - 1]);  c = 0;  while((pr = sieve_next(&s)) > 0) {    ++c;  }    fprintf(stderr, "%s: done!\n", argv[0]);  for(ix = 0; ix < s.nbits; ix++) {    if(S_ISSET(&s, ix)) {      printf("%ld\n", S_VAL(&s, ix));    }  }  sieve_clear(&s);  return 0;}void sieve_init(sieve *sp, long base, int nbits){  sp->size = (nbits / CHAR_BIT);  if(nbits % CHAR_BIT)    ++sp->size;  sp->bits = calloc(sp->size, sizeof(byte));  memset(sp->bits, UCHAR_MAX, sp->size);  if(!(base & 1))    ++base;  sp->base = base;    sp->next = 0;  sp->nbits = sp->size * CHAR_BIT;}void sieve_grow(sieve *sp, int nbits){  int  ns = (nbits / CHAR_BIT);  if(nbits % CHAR_BIT)    ++ns;  if(ns > sp->size) {    byte   *tmp;    int     ix;    tmp = calloc(ns, sizeof(byte));    if(tmp == NULL) {      fprintf(stderr, "Error: out of memory in sieve_grow\n");      return;    }    memcpy(tmp, sp->bits, sp->size);    for(ix = sp->size; ix < ns; ix++) {      tmp[ix] = UCHAR_MAX;    }    free(sp->bits);    sp->bits = tmp;    sp->size = ns;    sp->nbits = sp->size * CHAR_BIT;  }}long sieve_next(sieve *sp){  long out;  int  ix = 0;  long val;  if(sp->next > sp->nbits)    return -1;  out = S_VAL(sp, sp->next);#ifdef DEBUG  fprintf(stderr, "Sieving %ld\n", out);#endif  /* Sieve out all multiples of the current prime */  val = out;  while(ix < sp->nbits) {    val += out;    ix = S_BIT(sp, val);    if((val & 1) && ix < sp->nbits) { /* && S_ISSET(sp, ix)) { */      S_CLR(sp, ix);#ifdef DEBUG      fprintf(stderr, "Crossing out %ld (bit %d)\n", val, ix);#endif    }  }  /* Scan ahead to the next prime */  ++sp->next;  while(sp->next < sp->nbits && !S_ISSET(sp, sp->next))    ++sp->next;  return out;}void sieve_cross(sieve *sp, long val){  int  ix = 0;  long cur = val;  while(cur < sp->base)    cur += val;  ix = S_BIT(sp, cur);  while(ix < sp->nbits) {    if(cur & 1)       S_CLR(sp, ix);    cur += val;    ix = S_BIT(sp, cur);  }}void sieve_reset(sieve *sp, long base){  memset(sp->bits, UCHAR_MAX, sp->size);  sp->base = base;  sp->next = 0;}void sieve_clear(sieve *sp){  if(sp->bits)     free(sp->bits);  sp->bits = NULL;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -