Permalink
Browse files

Break up sieve into separate functions

  • Loading branch information...
1 parent 17a5181 commit 3469a4f93c70a9297388a0fd20353f23cf974328 @joshuaclayton committed Nov 13, 2011
Showing with 77 additions and 27 deletions.
  1. +56 −20 ext/sieve/sieve.c
  2. +14 −0 ext/sieve/sieve.h
  3. +5 −5 features/sieve.feature
  4. +2 −2 features/step_definitions/sieve_steps.rb
View
@@ -10,37 +10,73 @@ void Init_sieve() {
}
static VALUE sieve(const VALUE self) {
- if(NUM2LONG(self) < 2) { return Qnil; }
- long number = NUM2LONG(self) + 1;
+ if(NUM2LONG(self) < 2) { return rb_ary_new(); }
- char* results = malloc((long)(number/8));
+ sieve_data* data = initialize_sieve_data(self);
- if(results == NULL) {
- rb_raise(rb_eNoMemError, "Can't allocate enough memory.");
- }
+ default_sieve_data(data);
+ remove_non_primes(data);
+ VALUE primes_array = primes_array_from_sieve_data(data);
- CLEARBIT(results, 0);
- CLEARBIT(results, 1);
- long i;
- for(i = 2; i < number; i++) { SETBIT(results, i); }
+ destroy_sieve_data(data);
+
+ return primes_array;
+}
+
+static sieve_data* initialize_sieve_data(const VALUE self) {
+ sieve_data* data = (sieve_data*)malloc(sizeof(sieve_data));
- long current_square;
- for(i = 0; i < number; i++) {
- if(BITNOTSET(results, i)) { continue; }
+ data->number = NUM2LONG(self) + 1;
+ data->results = malloc((long)(data->number/8));
+
+ ensure_memory_allocated(data->results);
+
+ return data;
+}
+
+static void remove_non_primes(sieve_data* data) {
+ long current_square, i, n;
+
+ for(i = 0; i < data->number; i++) {
+ if(BITNOTSET(data->results, i)) { continue; }
current_square = powl(i, 2);
- if(current_square > number) { break; }
+ if(current_square > data->number) { break; }
- long n;
- for(n = current_square; n < number; n += i) { CLEARBIT(results, n); }
+ for(n = current_square; n < data->number; n += i) { CLEARBIT(data->results, n); }
}
+ return;
+}
+
+static void default_sieve_data(sieve_data* data) {
+ CLEARBIT(data->results, 0);
+ CLEARBIT(data->results, 1);
+
+ long i;
+ for(i = 2; i < data->number; i++) { SETBIT(data->results, i); }
+ return;
+}
+
+static VALUE primes_array_from_sieve_data(sieve_data* data) {
VALUE primes_array = rb_ary_new();
- for(i = 0; i < number; i++) {
- if(BITSET(results, i)) { rb_ary_push(primes_array, LONG2FIX(i)); }
- }
- free(results);
+ long i;
+ for(i = 0; i < data->number; i++) {
+ if(BITSET(data->results, i)) { rb_ary_push(primes_array, LONG2FIX(i)); }
+ }
return primes_array;
}
+
+static void ensure_memory_allocated(void* data) {
+ if(NULL == data) {
+ rb_raise(rb_eNoMemError, "Can't allocate enough memory.");
+ }
+}
+
+static void destroy_sieve_data(sieve_data* data) {
+ free(data->results);
+ free(data);
+ return;
+}
View
@@ -6,5 +6,19 @@
#define SETBIT(x,i) ((x)[(i)>>3] |= (1<<((i)&7)))
#define CLEARBIT(x,i) ((x)[(i)>>3] &= (1<<((i)&7))^0xFF)
+typedef struct {
+ char* results;
+ long number;
+} sieve_data;
+
static VALUE sieve(VALUE);
+
+static sieve_data* initialize_sieve_data(const VALUE);
+static void destroy_sieve_data(sieve_data*);
+static void default_sieve_data(sieve_data*);
+static void initialize_results(sieve_data*);
+static void remove_non_primes(sieve_data*);
+static VALUE primes_array_from_sieve_data(sieve_data*);
+static void ensure_memory_allocated(void*);
+
#endif
View
@@ -8,11 +8,11 @@ Feature: Sieve of Eratosthenes
Then I should have the primes <primes>
Examples:
| number | primes |
- | -12345 | nil |
- | -5 | nil |
- | -1 | nil |
- | 0 | nil |
- | 1 | nil |
+ | -12345 | |
+ | -5 | |
+ | -1 | |
+ | 0 | |
+ | 1 | |
| 2 | 2 |
| 3 | 2,3 |
| 4 | 2,3 |
@@ -7,8 +7,8 @@
Then /^I should have the primes (.*)$/ do |primes|
case primes
- when "nil"
- @result.should be_nil
+ when ""
+ @result.should == []
else
@primes = primes.split(",").map {|prime| prime.to_i }
@result.should == @primes

0 comments on commit 3469a4f

Please sign in to comment.