gem_with_extension_example 0.0.0

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.
@@ -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: []