sieve 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -12,13 +12,18 @@ Install with Rubygems:
12
12
 
13
13
  A method is added to the Numeric class.
14
14
 
15
- 5.sieve # [2, 3, 5]
16
- 20.sieve # [2, 3, 5, 7, 11, 13, 17, 19]
15
+ >> require "sieve"
16
+ => true
17
+ >> 5.sieve
18
+ => [2, 3, 5]
19
+ >> 100.sieve
20
+ => [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
17
21
 
18
22
  ## Benchmarks
19
23
 
20
24
  This benchmark loops through a handful of numbers 0 to 1 million in steps of
21
- 100000 and runs a sieve on each number.
25
+ 100000 and runs a sieve on each number. I also include benchmarks for running
26
+ the sieve against 10 million and 100 million.
22
27
 
23
28
  The sieve method itself looks like this:
24
29
 
@@ -37,30 +42,41 @@ As far as I know, this is the most optimized pure Ruby sieve written.
37
42
 
38
43
  The benchmarks were run on a 2.8GHz Intel Core 2 Duo MacBook Pro with 8 GB memory.
39
44
 
40
- ruby 1.8.6 (2010-02-05 patchlevel 399) [i686-darwin10.4.0]
41
-
42
- user system total real
43
- sieve method 41.430000 0.600000 42.030000 ( 42.261872)
44
- Numeric#sieve 1.010000 0.250000 1.260000 ( 1.342326)
45
-
46
- ruby 1.8.7 (2010-08-16 patchlevel 302) [i686-darwin10.4.0]
47
-
48
- user system total real
49
- sieve method 41.720000 0.730000 42.450000 ( 43.640117)
50
- Numeric#sieve 0.960000 0.380000 1.340000 ( 1.385924)
51
-
52
- ruby 1.8.7 (2010-04-19 patchlevel 253) [i686-darwin10.4.0], MBARI 0x6770, Ruby Enterprise Edition 2010.02
53
-
54
- user system total real
55
- sieve method 42.800000 0.910000 43.710000 ( 45.105879)
56
- Numeric#sieve 1.090000 0.370000 1.460000 ( 1.517832)
57
-
58
-
59
- ruby 1.9.2p0 (2010-08-18 revision 29036) [x86_64-darwin10.4.0]
60
-
61
- user system total real
62
- sieve method 22.800000 0.670000 23.470000 ( 24.132390)
63
- Numeric#sieve 1.000000 0.380000 1.380000 ( 1.422877)
45
+ ### ruby 1.8.6 (2010-02-05 patchlevel 399) [i686-darwin10.4.0]
46
+
47
+ user system total real
48
+ sieve method 4.450000 0.060000 4.510000 ( 4.526172)
49
+ Numeric#sieve 0.040000 0.000000 0.040000 ( 0.046676)
50
+ sieve 10_000_000 8.780000 0.120000 8.900000 ( 9.010072)
51
+ 10_000_000.sieve 0.080000 0.000000 0.080000 ( 0.084518)
52
+ 100_000_000.sieve 2.050000 0.050000 2.100000 ( 2.128403)
53
+
54
+ ### ruby 1.8.7 (2010-08-16 patchlevel 302) [i686-darwin10.4.0]
55
+
56
+ user system total real
57
+ sieve method 4.460000 0.060000 4.520000 ( 4.522069)
58
+ Numeric#sieve 0.040000 0.000000 0.040000 ( 0.046349)
59
+ sieve 10_000_000 8.820000 0.120000 8.940000 ( 8.955888)
60
+ 10_000_000.sieve 0.080000 0.010000 0.090000 ( 0.083030)
61
+ 100_000_000.sieve 2.040000 0.040000 2.080000 ( 2.100103)
62
+
63
+ ### ruby 1.8.7 (2010-04-19 patchlevel 253) [i686-darwin10.4.0], MBARI 0x6770, Ruby Enterprise Edition 2010.02
64
+
65
+ user system total real
66
+ sieve method 4.610000 0.090000 4.700000 ( 4.730966)
67
+ Numeric#sieve 0.050000 0.010000 0.060000 ( 0.046442)
68
+ sieve 10_000_000 8.640000 0.060000 8.700000 ( 8.731662)
69
+ 10_000_000.sieve 0.100000 0.000000 0.100000 ( 0.104731)
70
+ 100_000_000.sieve 2.250000 0.050000 2.300000 ( 2.303147)
71
+
72
+ ### ruby 1.9.2p0 (2010-08-18 revision 29036) [x86_64-darwin10.4.0]
73
+
74
+ user system total real
75
+ sieve method 2.410000 0.060000 2.470000 ( 2.468430)
76
+ Numeric#sieve 0.050000 0.000000 0.050000 ( 0.049053)
77
+ sieve 10_000_000 4.770000 0.110000 4.880000 ( 4.888397)
78
+ 10_000_000.sieve 0.080000 0.000000 0.080000 ( 0.098229)
79
+ 100_000_000.sieve 2.090000 0.040000 2.130000 ( 2.137024)
64
80
 
65
81
  ## Author
66
82
 
data/Rakefile CHANGED
@@ -34,7 +34,7 @@ task(:benchmark => :build) do
34
34
 
35
35
  Benchmark.bmbm(15) do |benchmark|
36
36
  range = (0..1000000)
37
- step = 10000
37
+ step = 100000
38
38
 
39
39
  benchmark.report("sieve method") do
40
40
  range.step(step) do |i|
@@ -55,5 +55,9 @@ task(:benchmark => :build) do
55
55
  benchmark.report("10_000_000.sieve") do
56
56
  10_000_000.sieve
57
57
  end
58
+
59
+ benchmark.report("100_000_000.sieve") do
60
+ 100_000_000.sieve
61
+ end
58
62
  end
59
63
  end
@@ -12,37 +12,39 @@ void Init_sieve() {
12
12
  static VALUE sieve(const VALUE self) {
13
13
  if(NUM2LONG(self) < 2) { return Qnil; }
14
14
  long number = NUM2LONG(self) + 1;
15
- short* numbers = malloc(number * sizeof(short));
16
15
 
17
- if(numbers == NULL) {
16
+ char* results = malloc((long)(number/8));
17
+
18
+ if(results == NULL) {
18
19
  rb_raise(rb_eNoMemError, "Can't allocate enough memory.");
19
20
  }
20
21
 
21
- numbers[0] = numbers[1] = 0;
22
+ CLEARBIT(results, 0);
23
+ CLEARBIT(results, 1);
22
24
  long i;
23
- for(i = 2; i < number; i++) { numbers[i] = 1; }
25
+ for(i = 2; i < number; i++) { SETBIT(results, i); }
24
26
 
25
27
  long current_square;
26
28
  for(i = 0; i < number; i++) {
27
- if(numbers[i] == 0) { continue; }
29
+ if(BITNOTSET(results, i)) { continue; }
28
30
 
29
31
  current_square = powl(i, 2);
30
32
  if(current_square > number) { break; }
31
33
 
32
34
  long n;
33
35
  for(n = current_square; n < number; n += i) {
34
- numbers[n] = 0;
36
+ CLEARBIT(results, n);
35
37
  }
36
38
  }
37
39
 
38
40
  VALUE primes_array = rb_ary_new();
39
41
  for(i = 0; i < number; i++) {
40
- if(numbers[i] == 1) {
42
+ if(BITSET(results, i)) {
41
43
  rb_ary_push(primes_array, LONG2FIX(i));
42
44
  }
43
45
  }
44
46
 
45
- free(numbers);
47
+ free(results);
46
48
 
47
49
  return primes_array;
48
50
  }
@@ -1,4 +1,10 @@
1
1
  #ifndef __sieve_h__
2
2
  #define __sieve_h__
3
+
4
+ #define BITSET(x,i) ((x)[(i)>>3] & (1<<((i)&7))) != 0
5
+ #define BITNOTSET(x,i) ((x)[(i)>>3] & (1<<((i)&7))) == 0
6
+ #define SETBIT(x,i) ((x)[(i)>>3] |= (1<<((i)&7)))
7
+ #define CLEARBIT(x,i) ((x)[(i)>>3] &= (1<<((i)&7))^0xFF)
8
+
3
9
  static VALUE sieve(VALUE);
4
10
  #endif
@@ -17,6 +17,11 @@ Feature: Sieve of Eratosthenes
17
17
  | 3 | 2,3 |
18
18
  | 4 | 2,3 |
19
19
  | 5 | 2,3,5 |
20
+ | 8 | 2,3,5,7 |
21
+ | 9 | 2,3,5,7 |
22
+ | 15 | 2,3,5,7,11,13 |
23
+ | 16 | 2,3,5,7,11,13 |
24
+ | 17 | 2,3,5,7,11,13,17 |
20
25
  | 19 | 2,3,5,7,11,13,17,19 |
21
26
  | 20 | 2,3,5,7,11,13,17,19 |
22
27
  | 29 | 2,3,5,7,11,13,17,19,23,29 |
@@ -1,5 +1,5 @@
1
1
  require "sieve/sieve"
2
2
 
3
3
  module Sieve
4
- VERSION = "0.1.1"
4
+ VERSION = "0.1.2"
5
5
  end
metadata CHANGED
@@ -1,13 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sieve
3
3
  version: !ruby/object:Gem::Version
4
- hash: 25
5
4
  prerelease: false
6
5
  segments:
7
6
  - 0
8
7
  - 1
9
- - 1
10
- version: 0.1.1
8
+ - 2
9
+ version: 0.1.2
11
10
  platform: ruby
12
11
  authors:
13
12
  - Josh Clayton
@@ -55,7 +54,6 @@ required_ruby_version: !ruby/object:Gem::Requirement
55
54
  requirements:
56
55
  - - ">="
57
56
  - !ruby/object:Gem::Version
58
- hash: 3
59
57
  segments:
60
58
  - 0
61
59
  version: "0"
@@ -64,7 +62,6 @@ required_rubygems_version: !ruby/object:Gem::Requirement
64
62
  requirements:
65
63
  - - ">="
66
64
  - !ruby/object:Gem::Version
67
- hash: 3
68
65
  segments:
69
66
  - 0
70
67
  version: "0"