sieve 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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"