sieve 0.1.2 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/Gemfile +3 -0
- data/LICENSE +22 -0
- data/README.markdown +4 -0
- data/Rakefile +5 -7
- data/ext/sieve/extconf.rb +1 -0
- data/ext/sieve/sieve.c +56 -24
- data/ext/sieve/sieve.h +14 -0
- data/features/sieve.feature +5 -5
- data/features/step_definitions/sieve_steps.rb +2 -2
- data/features/support/env.rb +1 -2
- data/lib/sieve.rb +3 -3
- data/lib/sieve/version.rb +3 -0
- data/sieve.gemspec +27 -0
- metadata +41 -13
data/.gitignore
CHANGED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2010 Josh Clayton
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person
|
4
|
+
obtaining a copy of this software and associated documentation
|
5
|
+
files (the "Software"), to deal in the Software without
|
6
|
+
restriction, including without limitation the rights to use,
|
7
|
+
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
copies of the Software, and to permit persons to whom the
|
9
|
+
Software is furnished to do so, subject to the following
|
10
|
+
conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be
|
13
|
+
included in all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
17
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
19
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
20
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
21
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
22
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
data/README.markdown
CHANGED
data/Rakefile
CHANGED
@@ -2,9 +2,6 @@ require "rubygems"
|
|
2
2
|
require "rake"
|
3
3
|
require "benchmark"
|
4
4
|
|
5
|
-
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "lib"))
|
6
|
-
require "sieve"
|
7
|
-
|
8
5
|
require "rake/extensiontask"
|
9
6
|
Rake::ExtensionTask.new("sieve") do |extension|
|
10
7
|
extension.lib_dir = "lib/sieve"
|
@@ -13,16 +10,17 @@ end
|
|
13
10
|
task :build => [:clean, :compile]
|
14
11
|
|
15
12
|
require "cucumber/rake/task"
|
16
|
-
Cucumber::Rake::Task.new(:cucumber => :build)
|
17
|
-
t.rcov = true
|
18
|
-
end
|
13
|
+
Cucumber::Rake::Task.new(:cucumber => :build)
|
19
14
|
|
20
15
|
task :default => :cucumber
|
21
16
|
|
22
17
|
desc "Benchmark C implementation against pure Ruby implementation of the Sieve"
|
23
18
|
task(:benchmark => :build) do
|
19
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "lib"))
|
20
|
+
require "sieve"
|
21
|
+
|
24
22
|
def sieve(n)
|
25
|
-
numbers = (0..n).
|
23
|
+
numbers = (0..n).to_a
|
26
24
|
numbers[0] = numbers[1] = nil
|
27
25
|
numbers.each do |num|
|
28
26
|
next unless num
|
data/ext/sieve/extconf.rb
CHANGED
data/ext/sieve/sieve.c
CHANGED
@@ -10,41 +10,73 @@ void Init_sieve() {
|
|
10
10
|
}
|
11
11
|
|
12
12
|
static VALUE sieve(const VALUE self) {
|
13
|
-
if(NUM2LONG(self) < 2) { return
|
14
|
-
long number = NUM2LONG(self) + 1;
|
13
|
+
if(NUM2LONG(self) < 2) { return rb_ary_new(); }
|
15
14
|
|
16
|
-
|
15
|
+
sieve_data* data = initialize_sieve_data(self);
|
17
16
|
|
18
|
-
|
19
|
-
|
20
|
-
|
17
|
+
default_sieve_data(data);
|
18
|
+
remove_non_primes(data);
|
19
|
+
VALUE primes_array = primes_array_from_sieve_data(data);
|
21
20
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
21
|
+
destroy_sieve_data(data);
|
22
|
+
|
23
|
+
return primes_array;
|
24
|
+
}
|
25
|
+
|
26
|
+
static sieve_data* initialize_sieve_data(const VALUE self) {
|
27
|
+
sieve_data* data = (sieve_data*)malloc(sizeof(sieve_data));
|
26
28
|
|
27
|
-
|
28
|
-
|
29
|
-
|
29
|
+
data->number = NUM2LONG(self) + 1;
|
30
|
+
data->results = malloc((long)(data->number/8));
|
31
|
+
|
32
|
+
ensure_memory_allocated(data->results);
|
33
|
+
|
34
|
+
return data;
|
35
|
+
}
|
36
|
+
|
37
|
+
static void remove_non_primes(sieve_data* data) {
|
38
|
+
long current_square, i, n;
|
39
|
+
|
40
|
+
for(i = 0; i < data->number; i++) {
|
41
|
+
if(BITNOTSET(data->results, i)) { continue; }
|
30
42
|
|
31
43
|
current_square = powl(i, 2);
|
32
|
-
if(current_square > number) { break; }
|
44
|
+
if(current_square > data->number) { break; }
|
33
45
|
|
34
|
-
|
35
|
-
for(n = current_square; n < number; n += i) {
|
36
|
-
CLEARBIT(results, n);
|
37
|
-
}
|
46
|
+
for(n = current_square; n < data->number; n += i) { CLEARBIT(data->results, n); }
|
38
47
|
}
|
39
48
|
|
49
|
+
return;
|
50
|
+
}
|
51
|
+
|
52
|
+
static void default_sieve_data(sieve_data* data) {
|
53
|
+
CLEARBIT(data->results, 0);
|
54
|
+
CLEARBIT(data->results, 1);
|
55
|
+
|
56
|
+
long i;
|
57
|
+
for(i = 2; i < data->number; i++) { SETBIT(data->results, i); }
|
58
|
+
return;
|
59
|
+
}
|
60
|
+
|
61
|
+
static VALUE primes_array_from_sieve_data(sieve_data* data) {
|
40
62
|
VALUE primes_array = rb_ary_new();
|
41
|
-
for(i = 0; i < number; i++) {
|
42
|
-
if(BITSET(results, i)) {
|
43
|
-
rb_ary_push(primes_array, LONG2FIX(i));
|
44
|
-
}
|
45
|
-
}
|
46
63
|
|
47
|
-
|
64
|
+
long i;
|
65
|
+
for(i = 0; i < data->number; i++) {
|
66
|
+
if(BITSET(data->results, i)) { rb_ary_push(primes_array, LONG2FIX(i)); }
|
67
|
+
}
|
48
68
|
|
49
69
|
return primes_array;
|
50
70
|
}
|
71
|
+
|
72
|
+
static void ensure_memory_allocated(void* data) {
|
73
|
+
if(NULL == data) {
|
74
|
+
rb_raise(rb_eNoMemError, "Can't allocate enough memory.");
|
75
|
+
}
|
76
|
+
}
|
77
|
+
|
78
|
+
static void destroy_sieve_data(sieve_data* data) {
|
79
|
+
free(data->results);
|
80
|
+
free(data);
|
81
|
+
return;
|
82
|
+
}
|
data/ext/sieve/sieve.h
CHANGED
@@ -6,5 +6,19 @@
|
|
6
6
|
#define SETBIT(x,i) ((x)[(i)>>3] |= (1<<((i)&7)))
|
7
7
|
#define CLEARBIT(x,i) ((x)[(i)>>3] &= (1<<((i)&7))^0xFF)
|
8
8
|
|
9
|
+
typedef struct {
|
10
|
+
char* results;
|
11
|
+
long number;
|
12
|
+
} sieve_data;
|
13
|
+
|
9
14
|
static VALUE sieve(VALUE);
|
15
|
+
|
16
|
+
static sieve_data* initialize_sieve_data(const VALUE);
|
17
|
+
static void destroy_sieve_data(sieve_data*);
|
18
|
+
static void default_sieve_data(sieve_data*);
|
19
|
+
static void initialize_results(sieve_data*);
|
20
|
+
static void remove_non_primes(sieve_data*);
|
21
|
+
static VALUE primes_array_from_sieve_data(sieve_data*);
|
22
|
+
static void ensure_memory_allocated(void*);
|
23
|
+
|
10
24
|
#endif
|
data/features/sieve.feature
CHANGED
@@ -8,11 +8,11 @@ Feature: Sieve of Eratosthenes
|
|
8
8
|
Then I should have the primes <primes>
|
9
9
|
Examples:
|
10
10
|
| number | primes |
|
11
|
-
| -12345 |
|
12
|
-
| -5 |
|
13
|
-
| -1 |
|
14
|
-
| 0 |
|
15
|
-
| 1 |
|
11
|
+
| -12345 | |
|
12
|
+
| -5 | |
|
13
|
+
| -1 | |
|
14
|
+
| 0 | |
|
15
|
+
| 1 | |
|
16
16
|
| 2 | 2 |
|
17
17
|
| 3 | 2,3 |
|
18
18
|
| 4 | 2,3 |
|
data/features/support/env.rb
CHANGED
data/lib/sieve.rb
CHANGED
data/sieve.gemspec
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path("../lib/", __FILE__)
|
3
|
+
$:.unshift(lib) unless $:.include?(lib)
|
4
|
+
|
5
|
+
require "sieve/version"
|
6
|
+
|
7
|
+
Gem::Specification.new do |s|
|
8
|
+
s.name = %q{sieve}
|
9
|
+
s.summary = %q{Sieve of Eratosthenes}
|
10
|
+
s.description = %q{Ruby C Extension for the Sieve of Eratosthenes}
|
11
|
+
s.homepage = %q{http://github.com/joshuaclayton/sieve}
|
12
|
+
s.version = Sieve::VERSION
|
13
|
+
s.authors = ["Josh Clayton"]
|
14
|
+
s.email = %q{joshua.clayton@gmail.com}
|
15
|
+
|
16
|
+
s.rubygems_version = %q{1.3.7}
|
17
|
+
s.date = %q{2010-09-12}
|
18
|
+
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
s.extensions = ["ext/sieve/extconf.rb"]
|
21
|
+
s.files = %x{git ls-files}.split("\n").reject {|file| file =~ /^(features|cucumber)/ }
|
22
|
+
s.test_files = %x{git ls-files}.split("\n").select {|file| file =~ /^(features|cucumber)/ }
|
23
|
+
|
24
|
+
s.add_dependency "rake-compiler", "0.7.9"
|
25
|
+
s.add_development_dependency "rspec", "2.7.0"
|
26
|
+
s.add_development_dependency "cucumber", "1.1.0"
|
27
|
+
end
|
metadata
CHANGED
@@ -1,12 +1,8 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sieve
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
prerelease:
|
5
|
-
|
6
|
-
- 0
|
7
|
-
- 1
|
8
|
-
- 2
|
9
|
-
version: 0.1.2
|
4
|
+
prerelease:
|
5
|
+
version: 1.0.0
|
10
6
|
platform: ruby
|
11
7
|
authors:
|
12
8
|
- Josh Clayton
|
@@ -16,8 +12,40 @@ cert_chain: []
|
|
16
12
|
|
17
13
|
date: 2010-09-12 00:00:00 -04:00
|
18
14
|
default_executable:
|
19
|
-
dependencies:
|
20
|
-
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
17
|
+
name: rake-compiler
|
18
|
+
prerelease: false
|
19
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
20
|
+
none: false
|
21
|
+
requirements:
|
22
|
+
- - "="
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: 0.7.9
|
25
|
+
type: :runtime
|
26
|
+
version_requirements: *id001
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rspec
|
29
|
+
prerelease: false
|
30
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
31
|
+
none: false
|
32
|
+
requirements:
|
33
|
+
- - "="
|
34
|
+
- !ruby/object:Gem::Version
|
35
|
+
version: 2.7.0
|
36
|
+
type: :development
|
37
|
+
version_requirements: *id002
|
38
|
+
- !ruby/object:Gem::Dependency
|
39
|
+
name: cucumber
|
40
|
+
prerelease: false
|
41
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
43
|
+
requirements:
|
44
|
+
- - "="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 1.1.0
|
47
|
+
type: :development
|
48
|
+
version_requirements: *id003
|
21
49
|
description: Ruby C Extension for the Sieve of Eratosthenes
|
22
50
|
email: joshua.clayton@gmail.com
|
23
51
|
executables: []
|
@@ -28,6 +56,8 @@ extra_rdoc_files: []
|
|
28
56
|
|
29
57
|
files:
|
30
58
|
- .gitignore
|
59
|
+
- Gemfile
|
60
|
+
- LICENSE
|
31
61
|
- MIT-LICENSE
|
32
62
|
- README.markdown
|
33
63
|
- Rakefile
|
@@ -35,6 +65,8 @@ files:
|
|
35
65
|
- ext/sieve/sieve.c
|
36
66
|
- ext/sieve/sieve.h
|
37
67
|
- lib/sieve.rb
|
68
|
+
- lib/sieve/version.rb
|
69
|
+
- sieve.gemspec
|
38
70
|
- cucumber.yml
|
39
71
|
- features/sieve.feature
|
40
72
|
- features/step_definitions/sieve_steps.rb
|
@@ -54,21 +86,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
54
86
|
requirements:
|
55
87
|
- - ">="
|
56
88
|
- !ruby/object:Gem::Version
|
57
|
-
segments:
|
58
|
-
- 0
|
59
89
|
version: "0"
|
60
90
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
61
91
|
none: false
|
62
92
|
requirements:
|
63
93
|
- - ">="
|
64
94
|
- !ruby/object:Gem::Version
|
65
|
-
segments:
|
66
|
-
- 0
|
67
95
|
version: "0"
|
68
96
|
requirements: []
|
69
97
|
|
70
98
|
rubyforge_project:
|
71
|
-
rubygems_version: 1.
|
99
|
+
rubygems_version: 1.6.2
|
72
100
|
signing_key:
|
73
101
|
specification_version: 3
|
74
102
|
summary: Sieve of Eratosthenes
|