# HG changeset patch
# User Leif Leonhardy
# Date 1261670894 28800
# Node ID 0ca12d759af10c5bb8ba0b59d2c46857fb04d30e
# Parent  906f05c99ca779a4e0756e972b5ff834353dc164
first patch of Leif_attachment1.zip, i.e. Silva.c.diff0

diff -r 906f05c99ca7 -r 0ca12d759af1 Silva.c
--- a/Silva.c
+++ b/Silva.c
@@ -22,7 +22,7 @@
 //   approximately 8*pi(sqrt(N)), where N is the last number of the interval, and pi(x) is
 //   the usual prime counting function.
 //
-// Assumptions: pointers have 4 bytes, gcc compiler
+// Assumptions: pointers have either 4 or 8 bytes, gcc compiler
 //
 // Modifications made by Kevin Stueve 2009-09-04
 //            kstueve@uw.edu
@@ -50,6 +50,8 @@
 #include <time.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <stdint.h>
+#include <inttypes.h>
 
 
 //
@@ -86,9 +88,9 @@
 // basic type definitions
 //
 
-typedef unsigned char      u08;
-typedef unsigned int       u32;
-typedef unsigned long long u64;
+typedef uint8_t		u08;
+typedef uint32_t	u32;
+typedef uint64_t	u64;
 
 
 //
@@ -97,9 +99,9 @@
 
 static void *get_memory(u32 size)
 {
-  u32 m;
+  uintptr_t m;
 
-  m = (u32)malloc(size + 255); // this assumes that sizeof(void *) = sizeof(u32)
+  m = (uintptr_t)malloc((size_t)(size + 255));
   if((void *)m == NULL)
     exit(1);
   m = (m + 255) & ~255;
@@ -113,7 +115,7 @@
 
 static u32 count_zero_bits(u08 *addr,u32 size)
 {
-  static u32 data[256];
+  static u32 data[256];	// NYI: use uint_fast8_t rather than u32 (at most 8 zero bits per byte)
   u32 i,j;
 
   if(data[1] == 0)
@@ -132,7 +134,7 @@
 // generation of the (small) primes used by the main sieve
 //
 
-#define number_of_small_primes 6541
+#define number_of_small_primes 6541	// less than 2^16, excluding 2
 static u32 small_primes[number_of_small_primes];
 static u32 small_sieve[1024];
 static u32 small_base;
@@ -220,12 +222,21 @@
 //   be small (and a multiple of the L1 or L2 data cache line size)
 //
 
+#if	__SIZEOF_POINTER__ == 4
 #define primes_per_bucket ((1 << (_bucket_size_log2_ - 3)) - 1)
+#elif	__SIZEOF_POINTER__ == 8
+#define primes_per_bucket ((1 << (_bucket_size_log2_ - 3)) - 2)
+#else
+#error	"sizeof(void*) neither 4 nor 8"
+#endif
 
 typedef struct bucket
 {
   struct bucket *next; // pointer to next bucket
   u32 count;           // count of the number of primes in this bucket
+#if	__SIZEOF_POINTER__ == 8
+  u32 pad;		// dummy word to align next structure element
+#endif
   struct
   {
     u32 p; // prime
@@ -247,11 +258,11 @@
 #endif
 
 #if _implementation_ == 0
-# define new_bucket() do { bucket *b; b = get_memory(sizeof(bucket)); \
+# define new_bucket() do { bucket *b; b = get_memory((u32)sizeof(bucket)); \
     b->next = main_list; b->count = 0; main_list = b; } while(0)
 #else
 # define more_buckets() do { u32 i,j; i = 1 << (20 - _bucket_size_log2_); \
-    available_buckets = (bucket *)get_memory(i * sizeof(bucket)); for(j = 0;j < i;j++) \
+    available_buckets = (bucket *)get_memory(i * (u32)sizeof(bucket)); for(j = 0;j < i;j++) \
     available_buckets[j].next = (j < i - 1) ? &available_buckets[j + 1] : NULL; } while(0)
 # define new_bucket(k) do { bucket *b; if(available_buckets == NULL) more_buckets(); \
     b = available_buckets; available_buckets = available_buckets->next; \
@@ -278,7 +289,7 @@
       ;
     current_list = 0;
     available_buckets = NULL;
-    main_lists = (bucket **)get_memory((1 << list_size_log2) * sizeof(bucket *));
+    main_lists = (bucket **)get_memory((1 << list_size_log2) * (u32)sizeof(bucket *));
     for(k = 0;k < (1 << list_size_log2);k++)
     {
       main_lists[k] = NULL;
@@ -435,6 +446,15 @@
   double t;
   u32 i,j;
   u64 pi;
+  const u32 bytes_per_segment = 1 << (_sieve_bits_log2_ - 3);
+  u64 bytes_remaining;	// u32 overflows on large intervals
+
+#ifdef	DEBUG
+  fprintf(stderr,"log2(bucket_size)=%u\n",(unsigned)_bucket_size_log2_);
+  fprintf(stderr,"primes_per_bucket=%u\n",(unsigned)primes_per_bucket);
+  fprintf(stderr,"sizeof(bucket)=%u\n",(unsigned)sizeof(bucket));
+  fprintf(stderr,"log2(sieve_bits)=%u\n",(unsigned)_sieve_bits_log2_);
+#endif
 
 #if 0//#ifdef _test_small_sieve_
   test_small_sieve();
@@ -443,14 +463,32 @@
   test_main_sieve();
 #endif
 
+#if	0
   main_base = atoll(argv[1]);
   main_limit = atoll(argv[2]);
   //printf("%d\n",main_base);
-  //printf("%d\n",main_limit);  
+  //printf("%d\n",main_limit);
+#else
+  if(argc==3)	// progname <lower bound> <upper bound>
+  {
+    if(sscanf(argv[1],"%"SCNu64,&main_base)!=1 || sscanf(argv[2],"%"SCNu64,&main_limit)!=1
+      || main_limit<=main_base)
+    { // handle bad parameters...
+      // (could check if main_base%64==0 and main_limit%64==0 here, too)
+      fprintf(stderr,"%s: Bad parameters\n",argv[0]);
+      exit(1);
+    }
+  }
+  else
+  { // handle usage/command line syntax error...
+    fprintf(stderr,"Usage: %s <lower bound> <upper bound>\n",argv[0]);
+    exit(1);
+  }
+#endif
 
   next_prime = 0;
-  j = 1 << (_sieve_bits_log2_ - 3);
-  pi = 0ull;
+  // j = 1 << (_sieve_bits_log2_ - 3);
+  pi = 0;
   if(((u32)main_base | (u32)main_limit) & 63)
   {
     fprintf(stderr,"Warning: prime number counts may be incorrect\n");
@@ -460,28 +498,32 @@
   for(;;)
   {
     do_main_sieve();
-    i = (u32)(main_limit - main_base) >> 4;
-    if(i <= j)
+    bytes_remaining = (main_limit - main_base) >> 4;
+    if(bytes_remaining <= bytes_per_segment)
       break;
-    pi += (u64)count_zero_bits((u08 *)main_sieve,j);
+    pi += (u64)count_zero_bits((u08 *)main_sieve,bytes_per_segment);
 #if 0
     //
     // example code to print the prime numbers between
-    // main_base and main_base+2*j
+    // main_base and main_base+2*8*bytes_per_segment
     //
     {
       u32 k;
 
-      for(k = 0;k < (j << 3);k++)
+      for(k = 0;k < (bytes_per_segment << 3);k++)
         if((main_sieve[k >> 5] & (1 << (k & 31))) == 0)
-          printf("%llu\n",main_base + (u32)(2 * k + 1));
+          printf("%"PRIu64"\n",main_base + (u32)(2 * k + 1));
     }
 #endif
-    main_base += (u64)j << 4;
+    main_base += (u64)bytes_per_segment << 4;
   }
-  pi += (u64)count_zero_bits((u08 *)main_sieve,i);
+  pi += (u64)count_zero_bits((u08 *)main_sieve,(u32)bytes_remaining);
  // t = ((double)clock() - t) / (double)CLOCKS_PER_SEC;
+#if	0
   printf("%d\n",pi);
+#else
+  printf("%"PRIu64"\n",pi);
+#endif
   return 0;
 }
 
