gem_with_extension_example 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,44 @@
1
+ // Include the Ruby headers and goodies
2
+ #include "ruby.h"
3
+ #include "math.h"
4
+ #include "complex.h"
5
+
6
+ // Defining a space for information and references about the module to be stored internally
7
+ VALUE InfinityCheckC = Qnil;
8
+
9
+ // Prototype for the initialization method - Ruby calls this, not you
10
+ void Init_infinity_check_c();
11
+
12
+ // Prototype for our method - methods are prefixed by 'method_' here
13
+ VALUE method_infinity_check_c(VALUE self, VALUE limit, VALUE cr, VALUE ci, VALUE zr, VALUE zi);
14
+
15
+ // The initialization method for this module
16
+ void Init_infinity_check_c()
17
+ {
18
+ InfinityCheckC = rb_define_module("InfinityCheckC");
19
+ rb_define_method(InfinityCheckC, "infinity_check_c", method_infinity_check_c, 5);
20
+ }
21
+
22
+ VALUE method_infinity_check_c(VALUE self, VALUE limit, VALUE cr, VALUE ci, VALUE zr, VALUE zi)
23
+ {
24
+ float complex c = NUM2DBL(cr) + NUM2DBL(ci) * I;
25
+ float complex z = NUM2DBL(zr) + NUM2DBL(zi) * I;
26
+ int iteration_limit = FIX2INT(limit);
27
+ int i = -1;
28
+ int j;
29
+
30
+ for (j = 0; j < iteration_limit; j++)
31
+ {
32
+ z = z * z + c;
33
+ double a = cabs(z);
34
+
35
+ if (a > 4.0f)
36
+ {
37
+ break;
38
+ }
39
+
40
+ i++;
41
+ }
42
+
43
+ return INT2FIX(i);
44
+ }
@@ -0,0 +1,5 @@
1
+ require 'mkmf' # for generating makefiles for Ruby extensions
2
+
3
+ extension_name = 'infinity_check_c'
4
+ dir_config(extension_name)
5
+ create_makefile(extension_name)
@@ -0,0 +1,4 @@
1
+ require 'gem_with_extension_example/base'
2
+ require 'gem_with_extension_example/grid'
3
+ require 'gem_with_extension_example/timer'
4
+ require 'gem_with_extension_example/util'
@@ -0,0 +1,111 @@
1
+ # encoding: utf-8
2
+ $:.push File.expand_path("..", __FILE__)
3
+
4
+ require "version"
5
+ require 'complex'
6
+
7
+ # C extensions
8
+ require "infinity_check_c"
9
+ include InfinityCheckC
10
+
11
+ module GemWithExtensionExample
12
+ class PlotFractal
13
+ PRETTY_PLOT = false
14
+
15
+ if PRETTY_PLOT
16
+ MAX_ITERATION_COUNT = 10
17
+ else
18
+ MAX_ITERATION_COUNT = 10000
19
+ end
20
+
21
+ DIVERGE_LIMIT = 4.0
22
+ DIVERGE_LIMIT_SQUARED = DIVERGE_LIMIT * DIVERGE_LIMIT
23
+
24
+ CLASSIC_JULIA_SET = Complex(-1.0,-0.25)
25
+
26
+ if PRETTY_PLOT
27
+ MAP_SET = " ·::++++xxxxxx "
28
+ else
29
+ MAP_SET = " · "
30
+ end
31
+
32
+ def self.mandelbrot(grid)
33
+ (0...grid.height).each do |y|
34
+ (0...grid.width).each do |x|
35
+ z = grid[x,y]
36
+ count = infinity_check_ruby(MAX_ITERATION_COUNT, z, z)
37
+ print get_render_character(count)
38
+ end
39
+ puts ""
40
+ end
41
+ end
42
+ def self.mandelbrot_C(grid)
43
+ (0...grid.height).each do |y|
44
+ (0...grid.width).each do |x|
45
+ z = grid[x,y]
46
+ i = z.imaginary
47
+ r = z.real
48
+ count = infinity_check_c(MAX_ITERATION_COUNT, r, i, r, i)
49
+ print get_render_character(count)
50
+ end
51
+ puts ""
52
+ end
53
+ end
54
+ def self.julia(grid)
55
+ (0...grid.height).each do |y|
56
+ (0...grid.width).each do |x|
57
+ z = grid[x,y]
58
+ i = infinity_check_ruby(MAX_ITERATION_COUNT, CLASSIC_JULIA_SET, z)
59
+ print get_render_character(i)
60
+ end
61
+ puts ""
62
+ end
63
+ end
64
+ def self.julia_C(grid)
65
+ (0...grid.height).each do |y|
66
+ (0...grid.width).each do |x|
67
+ z = grid[x,y]
68
+ count = infinity_check_c(MAX_ITERATION_COUNT, CLASSIC_JULIA_SET.real, CLASSIC_JULIA_SET.imaginary, z.real, z.imaginary)
69
+ print get_render_character(count)
70
+ end
71
+ puts ""
72
+ end
73
+ end
74
+
75
+ private
76
+ @@lookup = []
77
+
78
+ def self.build_lookup
79
+ limit = MAX_ITERATION_COUNT
80
+ step = Float(MAX_ITERATION_COUNT) / MAP_SET.length
81
+ MAP_SET.length.times do
82
+ @@lookup << Integer(limit)
83
+ limit -= step
84
+ end
85
+ end
86
+
87
+ self.build_lookup # populate limit table
88
+
89
+ def self.get_render_character(a)
90
+ c = nil
91
+ i = 0
92
+ a = MAX_ITERATION_COUNT - a
93
+ @@lookup.each do |limit|
94
+ c = MAP_SET[i]
95
+ i += 1
96
+ break if a > limit
97
+ end
98
+ return c
99
+ end
100
+
101
+ def self.infinity_check_ruby(limit, c, z)
102
+ i = -1
103
+ limit.times do
104
+ z = z * z + c
105
+ break if z.abs > DIVERGE_LIMIT
106
+ i += 1
107
+ end
108
+ return i
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,178 @@
1
+ require 'complex'
2
+
3
+ class Grid
4
+ attr_reader :width, :height
5
+
6
+ def initialize(width, height, default_value = nil)
7
+ @width = width
8
+ @height = height
9
+ @default_value = default_value
10
+ @grid = create(width, height, default_value)
11
+ end
12
+
13
+ def [](x,y)
14
+ if (x < 0 or x >= @width) or (y < 0 or y >= @height)
15
+ throw Error("Grid index out of bounds. [%d][%d] not in range ([0 through %d][0 through %d])" % [x, y, width - 1, height - 1])
16
+ end
17
+ @grid[x][y]
18
+ end
19
+
20
+ def []=(x,y,a)
21
+ if (x < 0 or x >= @width) or (y < 0 or y >= @height)
22
+ throw Error("Grid index out of bounds. [%d][%d] not in range ([0 through %d][0 through %d])" % [x, y, width - 1, height - 1])
23
+ end
24
+ @grid[x][y] = a
25
+ end
26
+
27
+ def clear(value=nil)
28
+ (0...@width).each do |xi|
29
+ (0...@height).each do |yi|
30
+ @grid[xi][yi] = value
31
+ end
32
+ end
33
+ end
34
+
35
+ def to_s
36
+ s = ""
37
+ @grid.each{|c| s << c.to_s << "\n"}
38
+ return s
39
+ end
40
+
41
+ def each_col
42
+ @grid.each{|c| yield c.dup}
43
+ end
44
+
45
+ def each
46
+ @grid.each do |c|
47
+ c.each{|i| yield i}
48
+ end
49
+ end
50
+
51
+ # Generate a two dimensional grid of float pairs, evenly
52
+ # distributed across width x height samples
53
+ # ranging from x0 to x1 and y0 to y1
54
+ def fill_complex(x0, y0, x1, y1)
55
+ x_range = x1 - x0
56
+ y_range = y1 - y0
57
+
58
+ width_limit = Float(@width - 1)
59
+ height_limit = Float(@height - 1)
60
+
61
+ (0...@width).each do |xi|
62
+ x_unit = Float(xi) / width_limit
63
+ x = x0 + (x_unit * x_range)
64
+
65
+ (0...@height).each do |yi|
66
+ y_unit = Float(yi) / height_limit
67
+ y = y0 + (y_unit * y_range)
68
+ @grid[xi][yi] = Complex(x,y)
69
+ #@grid[xi][yi] = [x,y]
70
+ end
71
+ end
72
+ end
73
+
74
+ def fill_test()
75
+ t = 0
76
+ @grid.each_with_index do |c, x|
77
+ c.each_with_index{|i, y| @grid[x][y] = t; t += 1}
78
+ end
79
+ end
80
+
81
+ #------------------------------------------
82
+ private
83
+
84
+ def create(width, height, default_value)
85
+ grid = Array.new(width){[]}
86
+ (0...width).each do |xi|
87
+ grid[xi] = Array.new(height, default_value)
88
+ end
89
+ return grid
90
+ end
91
+
92
+ end
93
+
94
+ RUN_TEST = false
95
+
96
+ if RUN_TEST
97
+ grid = Grid.new(4, 5, [0.0,0.0])
98
+
99
+ puts "-" * 9
100
+ p grid
101
+
102
+ puts "-" * 9
103
+ p grid[0,0]
104
+ p grid[1,1]
105
+
106
+ puts "-" * 9
107
+ grid[0,0] = [5.0,2.0]
108
+ grid[1,1] = [7.0,9.0]
109
+
110
+ p grid[0,0]
111
+ p grid[1,1]
112
+
113
+ puts "-" * 9
114
+ p grid
115
+
116
+ puts "-" * 9
117
+ grid.fill_complex(-2.0, -1.0, 1.0, 1.0)
118
+ puts "-" * 9
119
+ p grid
120
+
121
+ grid.clear(0)
122
+ puts "-" * 9
123
+ p grid
124
+
125
+ grid.fill_test
126
+ puts "-" * 9
127
+ p grid
128
+
129
+ puts "-" * 9
130
+ grid.each{|c| p c}
131
+
132
+ puts "-" * 9
133
+ grid.each_col{|c| p c}
134
+
135
+ puts "-" * 9
136
+ p grid
137
+
138
+ end
139
+
140
+
141
+
142
+
143
+
144
+
145
+
146
+
147
+
148
+
149
+
150
+
151
+
152
+
153
+
154
+
155
+
156
+
157
+
158
+
159
+
160
+
161
+
162
+
163
+
164
+
165
+
166
+
167
+
168
+
169
+
170
+
171
+
172
+
173
+
174
+
175
+
176
+
177
+
178
+
@@ -0,0 +1,169 @@
1
+ $:.push File.expand_path("..", __FILE__)
2
+ #require 'util'
3
+ #require File.expand_path('../util', __FILE__)
4
+ #require '/Users/sean/dev/gems/gem_with_extension_example/lib/gem_with_extension_example/util.rb'
5
+
6
+ class Timer
7
+ # ToDo
8
+ # Mode Flags:
9
+ # :side_by_side (on by default)
10
+ # :consecutive_runs (using redis)(off by default)
11
+
12
+ DIGITS_OF_PRESCISION = 6
13
+ @@max_name_length = 0
14
+ @@max_whole_digits = 1
15
+ @@timer_list = []
16
+ @@mode = :side_by_side
17
+ attr_reader :elapsed
18
+
19
+ #private :digits, :update_digit_count
20
+
21
+ def initialize(name)
22
+ @name = name
23
+ clear
24
+ @@max_name_length = name.length if name.length > @@max_name_length
25
+ @@timer_list << self
26
+ end
27
+ class << self
28
+ def set_mode(mode)
29
+ @@mode = mode #:side_by_side, :simple
30
+ end
31
+ def to_s
32
+ # Process pair comparison
33
+ pair_comparison = @@timer_list.count == 2
34
+ speed_multiple = nil
35
+ greater_index = nil
36
+ if pair_comparison
37
+ if @@timer_list[0].elapsed > @@timer_list[1].elapsed
38
+ greater_index = 1
39
+ speed_multiple = @@timer_list[0].elapsed / @@timer_list[1].elapsed
40
+ else
41
+ greater_index = 0
42
+ speed_multiple = @@timer_list[1].elapsed / @@timer_list[0].elapsed
43
+ end
44
+ end
45
+ total_time = @@timer_list.inject(0.0) { |result, t| result + t.elapsed }
46
+
47
+ # construct output string
48
+ s = ""
49
+ @@timer_list.each_with_index do |t, i|
50
+ s << t.to_s
51
+ s << "%8.3f%s" % [((t.elapsed) / total_time * 100.0), '%'] if @@timer_list.count > 1
52
+ if pair_comparison and (@@mode == :side_by_side) and (i == greater_index)
53
+ s << ", %.1f times faster." % speed_multiple
54
+ end
55
+ s << "\n"
56
+ end
57
+ if !(@@mode == :side_by_side and pair_comparison) and @@timer_list.count > 1
58
+ total_whole_digits = digits(total_time.to_i)
59
+ digit_overflow = total_whole_digits - @@max_whole_digits
60
+ leading_spaces = (@@max_name_length + 2) - digit_overflow
61
+
62
+ s << (" " * (@@max_name_length + 2))
63
+ s << ("-" * (DIGITS_OF_PRESCISION + @@max_whole_digits + 2))
64
+ s << "\n"
65
+ s << (" " * leading_spaces) if leading_spaces > 0
66
+ s << "%#{DIGITS_OF_PRESCISION + total_whole_digits + 1}.#{DIGITS_OF_PRESCISION}fs" % total_time
67
+ s << "\n"
68
+ end
69
+ s
70
+ end
71
+ def digits(n)
72
+ if n > 9
73
+ d = Math.log10(n).to_i + 1
74
+ elsif n < -9
75
+ d = Math.log10(n * -1).to_i + 1
76
+ else
77
+ d = 1
78
+ end
79
+ d
80
+ end
81
+ end
82
+ def clear
83
+ @state = :stopped
84
+ @time = []
85
+ @elapsed = 0.0
86
+ end
87
+ def self.clear
88
+ @@max_name_length = 0
89
+ @@max_whole_digits = 1
90
+ @@timer_list = []
91
+ end
92
+ def digits(n)
93
+ self.class.digits(n)
94
+ end
95
+ def update_digit_count
96
+ whole_digits = digits(@elapsed.to_i)
97
+ @@max_whole_digits = whole_digits if whole_digits > @@max_whole_digits
98
+ end
99
+ def to_s
100
+ "% #{@@max_name_length}s: %#{DIGITS_OF_PRESCISION + @@max_whole_digits + 1}.#{DIGITS_OF_PRESCISION}fs" % [@name, @elapsed]
101
+ end
102
+ def +(o)
103
+ o = o.elapsed if o.is_a?(self.class)
104
+ @elapsed += o
105
+ update_digit_count
106
+ end
107
+ def /(o)
108
+ o = o.elapsed if o.is_a?(self.class)
109
+ @elapsed /= o
110
+ update_digit_count
111
+ end
112
+ def start
113
+ if @state == :stopped
114
+ @state = :running
115
+ @start = Time.now
116
+ end
117
+ end
118
+ def stop
119
+ if @state == :running
120
+ stop = Time.now
121
+ @elapsed += (stop - @start)
122
+ update_digit_count
123
+ @state = :stopped
124
+ end
125
+ end
126
+ end
127
+
128
+ if __FILE__ == $0
129
+ #Timer.set_mode(:simple)
130
+ 19.times do
131
+ test_count = Random.rand(4) + 1
132
+ timer_list = []
133
+
134
+ # Allocate Timers
135
+ test_count.times do |n|
136
+ timer_name = ("A".ord + n).chr
137
+ timer_list[n] = Timer.new(timer_name)
138
+ end
139
+
140
+ # Use Timers
141
+ test_count.times do |n|
142
+ timer_list[n].start
143
+ timer_list[n].stop
144
+ timer_list[n] += Random.rand * 133 # fake out the timer
145
+ end
146
+
147
+ # Show Timers
148
+ puts ""
149
+ puts Timer
150
+ Timer.clear
151
+ end
152
+ end
153
+
154
+
155
+
156
+
157
+
158
+
159
+
160
+
161
+
162
+
163
+
164
+
165
+
166
+
167
+
168
+
169
+
@@ -0,0 +1,9 @@
1
+ module GemWithExtensionExample
2
+ # Use semantic versioning: http://semver.org/
3
+
4
+ # PATCH 0.0.x level changes for implementation level detail changes, such as small bug fixes
5
+ # MINOR 0.x.0 level changes for any backwards compatible API changes, such as new functionality/features
6
+ # MAJOR x.0.0 level changes for backwards incompatible
7
+
8
+ VERSION = "0.0.0"
9
+ end
metadata ADDED
@@ -0,0 +1,65 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gem_with_extension_example
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Sean Vikoren
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-11-10 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rake-compiler
16
+ requirement: &2165428740 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: *2165428740
25
+ description: This gem is intended to function as a starting point for developing gems
26
+ that contain C optimizations.
27
+ email:
28
+ - sean@vikoren.com
29
+ executables: []
30
+ extensions: []
31
+ extra_rdoc_files: []
32
+ files:
33
+ - ext/infinity_check_c/InfinityCheckC.c
34
+ - ext/infinity_check_c/extconf.rb
35
+ - lib/gem_with_extension_example/base.rb
36
+ - lib/gem_with_extension_example/grid.rb
37
+ - lib/gem_with_extension_example/timer.rb
38
+ - lib/gem_with_extension_example/version.rb
39
+ - lib/gem_with_extension_example.rb
40
+ - lib/gem_with_extension_example/infinity_check_c.bundle
41
+ homepage: ''
42
+ licenses: []
43
+ post_install_message:
44
+ rdoc_options: []
45
+ require_paths:
46
+ - lib
47
+ required_ruby_version: !ruby/object:Gem::Requirement
48
+ none: false
49
+ requirements:
50
+ - - ! '>='
51
+ - !ruby/object:Gem::Version
52
+ version: '0'
53
+ required_rubygems_version: !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ! '>='
57
+ - !ruby/object:Gem::Version
58
+ version: '0'
59
+ requirements: []
60
+ rubyforge_project: gem_with_extension_example
61
+ rubygems_version: 1.8.11
62
+ signing_key:
63
+ specification_version: 3
64
+ summary: An example gem with a C extention.
65
+ test_files: []