multiarray 0.11.3 → 0.11.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -103,6 +103,13 @@ module Hornetseye
103
103
 
104
104
  end
105
105
 
106
+ # Decompose composite number
107
+ #
108
+ # This method decomposes the composite number.
109
+ #
110
+ # @return [Node] Returns the requested component.
111
+ #
112
+ # @private
106
113
  def decompose( i )
107
114
  self.class.element_type.new @value.decompose( i )
108
115
  end
@@ -35,8 +35,18 @@ module Hornetseye
35
35
 
36
36
  # Constructor
37
37
  #
38
- # @param [Node] value Initial value of injection
39
- # @param [Node] index0 Index for
38
+ # @param [Node] value Initial value of injection.
39
+ # @param [Node] index0 Index to select starting point of injection.
40
+ # @param [Node] index1 Index to diagonally iterate over +value+.
41
+ # @param [Node] index2 Index to diagonally iterate over +value+.
42
+ # @param [Node,NilClass] initial Initial value for injection.
43
+ # @param [Node] block Expression with body of injection.
44
+ # @param [Variable] var1 Variable for performing substitutions on body of
45
+ # injection.
46
+ # @param [Variable] var2 Variable for performing substitutions on body of
47
+ # injection.
48
+ #
49
+ # @private
40
50
  def initialize( value, index0, index1, index2, initial, block, var1,
41
51
  var2 )
42
52
  @value, @index0, @index1, @index2, @initial, @block, @var1, @var2 =
@@ -67,7 +77,11 @@ module Hornetseye
67
77
  #
68
78
  # @private
69
79
  def array_type
70
- Hornetseye::MultiArray @block.typecode, *@value.shape
80
+ retval = Hornetseye::MultiArray @block.typecode, *@value.shape
81
+ ( class << self; self; end ).instance_eval do
82
+ define_method( :array_type ) { retval }
83
+ end
84
+ retval
71
85
  end
72
86
 
73
87
  # Reevaluate computation
@@ -179,3 +193,4 @@ module Hornetseye
179
193
  end
180
194
 
181
195
  end
196
+
@@ -17,6 +17,7 @@
17
17
  # Namespace of Hornetseye computer vision library
18
18
  module Hornetseye
19
19
 
20
+ # Class for representing element-wise operations
20
21
  class ElementWise_ < Node
21
22
 
22
23
  class << self
@@ -26,7 +27,7 @@ module Hornetseye
26
27
  # @return [Proc] A closure with the operation.
27
28
  attr_accessor :operation
28
29
 
29
- # Unique key to identify operation.
30
+ # Unique key to identify operation
30
31
  #
31
32
  # @return [Symbol,String] A unique key to identify this operation.
32
33
  attr_accessor :key
@@ -92,7 +93,11 @@ module Hornetseye
92
93
  # @private
93
94
  def array_type
94
95
  array_types = @values.collect { |value| value.array_type }
95
- self.class.conversion.call *array_types
96
+ retval = self.class.conversion.call *array_types
97
+ ( class << self; self; end ).instance_eval do
98
+ define_method( :array_type ) { retval }
99
+ end
100
+ retval
96
101
  end
97
102
 
98
103
  # Reevaluate computation
@@ -17,10 +17,16 @@
17
17
  # Namespace of Hornetseye computer vision library
18
18
  module Hornetseye
19
19
 
20
+ # Class for representing native floating point numbers
20
21
  class FLOAT_ < Element
21
22
 
22
23
  class << self
23
24
 
25
+ # Boolean indicating whether this number is single or double precision
26
+ #
27
+ # @return [Boolean] +true+ for double precision, +false+ for single precision.
28
+ #
29
+ # @private
24
30
  attr_accessor :double
25
31
 
26
32
  # Memory type required to store elements of this type
@@ -102,11 +108,15 @@ module Hornetseye
102
108
  double ? 'd' : 'f'
103
109
  end
104
110
 
105
- # Return string with information about this class.
111
+ # Return string with information about this class
106
112
  #
107
113
  # @return [String] Returns a string (e.g. "SFLOAT").
108
114
  def inspect
109
- "#{ double ? 'D' : 'S' }FLOAT"
115
+ retval = "#{ double ? 'D' : 'S' }FLOAT"
116
+ ( class << self; self; end ).instance_eval do
117
+ define_method( :inspect ) { retval }
118
+ end
119
+ retval
110
120
  end
111
121
 
112
122
  # Get unique descriptor of this class
@@ -129,7 +139,7 @@ module Hornetseye
129
139
  other.is_a? Class and other < FLOAT_ and double == other.double
130
140
  end
131
141
 
132
- # Compute hash value for this class.
142
+ # Compute hash value for this class
133
143
  #
134
144
  # @return [Fixnum] Hash value
135
145
  #
@@ -151,6 +161,11 @@ module Hornetseye
151
161
 
152
162
  end
153
163
 
164
+ # Namespace containing method for matching elements of type FLOAT_
165
+ #
166
+ # @see FLOAT_
167
+ #
168
+ # @private
154
169
  module Match
155
170
 
156
171
  # Method for matching elements of type FLOAT_
@@ -197,9 +212,31 @@ module Hornetseye
197
212
 
198
213
  end
199
214
 
215
+ # Boolean constant to use as a parameter for creating floating point classes
216
+ #
217
+ # The value is +false+.
218
+ #
219
+ # @see #FLOAT
200
220
  SINGLE = false
221
+
222
+ # Boolean constant to use as a parameter for creating floating point classes
223
+ #
224
+ # The value is +true+.
225
+ #
226
+ # @see #FLOAT
201
227
  DOUBLE = true
202
228
 
229
+ # Create a class deriving from +FLOAT_+
230
+ #
231
+ # Create a class deriving from +FLOAT_+. The parameters +double+ is assigned to the
232
+ # corresponding attributes of the resulting class.
233
+ #
234
+ # @param [Boolean] double Specify +SINGLE+ or +DOUBLE+ here.
235
+ #
236
+ # @return [Class] A class deriving from +FLOAT_+.
237
+ #
238
+ # @see FLOAT_
239
+ # @see FLOAT_.double
203
240
  def FLOAT( double )
204
241
  retval = Class.new FLOAT_
205
242
  retval.double = double
@@ -208,7 +245,10 @@ module Hornetseye
208
245
 
209
246
  module_function :FLOAT
210
247
 
248
+ # Single-precision floating-point number
211
249
  SFLOAT = FLOAT SINGLE
250
+
251
+ # Double-precision floating-point number
212
252
  DFLOAT = FLOAT DOUBLE
213
253
 
214
254
  # Shortcut for constructor
@@ -16,7 +16,10 @@
16
16
 
17
17
  # Namespace of Hornetseye computer vision library
18
18
  module Hornetseye
19
-
19
+
20
+ # Class for holding methods compiled during runtime
21
+ #
22
+ # @private
20
23
  class GCCCache
21
24
  end
22
25
 
@@ -16,30 +16,68 @@
16
16
 
17
17
  # Namespace of Hornetseye computer vision library
18
18
  module Hornetseye
19
-
19
+
20
+ # Context object for creating a Ruby extension
21
+ #
22
+ # @private
20
23
  class GCCContext
21
24
 
25
+ # Ruby configuration
26
+ #
27
+ # @private
22
28
  CFG = RbConfig::CONFIG
29
+
23
30
  if CFG[ 'rubyhdrdir' ]
31
+ # GCC compiler flags
32
+ #
33
+ # @private
24
34
  CFLAGS = "-DNDEBUG #{CFG[ 'CFLAGS' ]} " +
25
35
  "-I#{CFG['rubyhdrdir']} -I#{CFG['rubyhdrdir']}/#{CFG['arch']}"
26
36
  else
27
37
  CFLAGS = "-DNDEBUG #{CFG[ 'CFLAGS' ]} " +
28
38
  "-I#{CFG['archdir']}"
29
39
  end
40
+
41
+ # Arguments for linking the Ruby extension
42
+ #
43
+ # @private
30
44
  LIBRUBYARG = "-L#{CFG[ 'libdir' ]} #{CFG[ 'LIBRUBYARG' ]} #{CFG[ 'LDFLAGS' ]} "
31
45
  "#{CFG[ 'SOLIBS' ]} #{CFG[ 'DLDLIBS' ]}"
46
+
47
+ # Command for linking the Ruby extension
48
+ #
49
+ # @private
32
50
  LDSHARED = CFG[ 'LDSHARED' ]
51
+
52
+ # Shared library file extension under current operating system
53
+ #
54
+ # @private
33
55
  DLEXT = CFG[ 'DLEXT' ]
56
+
57
+ # Directory for storing the Ruby extensions
58
+ #
59
+ # @private
34
60
  DIRNAME = "#{Dir.tmpdir}/hornetseye-ruby#{RUBY_VERSION}-" +
35
61
  "#{ENV[ 'USER' ] || ENV[ 'USERNAME' ]}"
62
+
63
+ # Lock file to prevent conflicts
64
+ #
65
+ # @private
36
66
  LOCKFILE = "#{DIRNAME}/lock"
67
+
37
68
  Dir.mkdir DIRNAME, 0700 unless File.exist? DIRNAME
69
+
70
+ # The actual file lock
71
+ #
72
+ # @private
38
73
  @@lock = File.new LOCKFILE, 'w', 0600
39
74
  unless @@lock.flock File::LOCK_EX | File::LOCK_NB
40
75
  raise "Could not lock file \"#{LOCKFILE}\""
41
76
  end
42
77
 
78
+ # Next available base name for a Ruby extension
79
+ #
80
+ # @private
43
81
  @@lib_name = 'hornetseye_aaaaaaaa'
44
82
 
45
83
  if ENV[ 'HORNETSEYE_PRELOAD_CACHE' ]
@@ -51,6 +89,15 @@ module Hornetseye
51
89
 
52
90
  class << self
53
91
 
92
+ # Method for compiling Ruby to C
93
+ #
94
+ # @param [Proc] action The code block needs to accept a GCCContext object.
95
+ #
96
+ # @return [Object] Returns result of code block.
97
+ #
98
+ # @see GCCFunction.run
99
+ #
100
+ # @private
54
101
  def build( &action )
55
102
  lib_name, @@lib_name = @@lib_name, @@lib_name.succ
56
103
  new( lib_name ).build &action
@@ -58,6 +105,11 @@ module Hornetseye
58
105
 
59
106
  end
60
107
 
108
+ # Initialises an empty Ruby extension
109
+ #
110
+ # @param [String] lib_name Base name of library to create later.
111
+ #
112
+ # @private
61
113
  def initialize( lib_name )
62
114
  @lib_name = lib_name
63
115
  @instructions = ''
@@ -65,39 +117,67 @@ module Hornetseye
65
117
  @registrations = ''
66
118
  end
67
119
 
120
+ # Create Ruby extension
121
+ #
122
+ # @param [Proc] action Code block accepting a GCCContext object.
123
+ #
124
+ # @return [Object] Returns result of code block.
125
+ #
126
+ # @private
68
127
  def build( &action )
69
128
  action.call self
70
129
  end
71
130
 
131
+ # Add a new function to the Ruby extension
132
+ #
133
+ # @param [String] descriptor Method name of function.
134
+ # @param [Array<GCCType>] param_types Array with parameter types.
135
+ #
136
+ # @return [GCCFunction] Object representing the function.
137
+ #
138
+ # @private
72
139
  def function( descriptor, *param_types )
73
140
  @instructions << <<EOS
74
- void #{descriptor}(#{
75
- if param_types.empty?
76
- ''
77
- else
78
- ' ' + param_types.collect do |t|
79
- t.identifiers
80
- end.flatten.collect_with_index do |ident,i|
81
- "#{ident} param#{i}"
82
- end.join( ', ' ) + ' '
83
- end
84
- }) {
141
+ struct Arguments
142
+ {
143
+ #{
144
+ param_types.collect do |t|
145
+ t.identifiers
146
+ end.flatten.collect_with_index do |ident,i|
147
+ " #{ident} param#{i};"
148
+ end.join( "\n" )
149
+ }
150
+ };
151
+
152
+ VALUE #{descriptor}( void *args )
153
+ {
154
+ #{
155
+ param_types.collect do |t|
156
+ t.identifiers
157
+ end.flatten.collect_with_index do |ident,i|
158
+ " #{ident} param#{i} = ((struct Arguments *)args)->param#{i};"
159
+ end.join( "\n" )
160
+ }
85
161
  EOS
86
162
 
87
163
  @wrappers << <<EOS
88
164
  VALUE wrap#{descriptor.capitalize}( int argc, VALUE *argv, VALUE rbSelf )
89
165
  {
90
- #{descriptor}(#{
91
- if param_types.empty?
92
- ''
166
+ struct Arguments args;
167
+ #{
168
+ param_types.collect do |t|
169
+ t.r2c
170
+ end.flatten.collect_with_index do |conv,i|
171
+ " args.param#{i} = #{conv.call "argv[ #{i} ]"};"
172
+ end.join( "\n" )
173
+ }
174
+ #{
175
+ if RUBY_VERSION < '1.9.0'
176
+ " #{descriptor}( &args );"
93
177
  else
94
- s = ' ' + param_types.collect do |t|
95
- t.r2c
96
- end.flatten.collect_with_index do |conv,i|
97
- conv.call "argv[ #{i} ]"
98
- end.join( ', ' ) + ' '
178
+ " rb_thread_blocking_region( &#{descriptor}, &args, RUBY_UBF_PROCESS, NULL );"
99
179
  end
100
- });
180
+ }
101
181
  return Qnil;
102
182
  }
103
183
  EOS
@@ -107,6 +187,15 @@ EOS
107
187
  RUBY_METHOD_FUNC( wrap#{descriptor.capitalize} ), -1 );
108
188
  EOS
109
189
  end
190
+
191
+ # Compile the Ruby extension
192
+ #
193
+ # This method writes the source code to a file and calls GCC to compile it.
194
+ # Finally the Ruby extension is loaded.
195
+ #
196
+ # @return [Boolean] Returns of loading the Ruby extension.
197
+ #
198
+ # @private
110
199
  def compile
111
200
  template = <<EOS
112
201
  #include <ruby.h>
@@ -140,6 +229,15 @@ EOS
140
229
  require "#{DIRNAME}/#{@lib_name}"
141
230
  end
142
231
 
232
+ # Add instructions to Ruby extension
233
+ #
234
+ # The given string is appended to the source code of the Ruby extension.
235
+ #
236
+ # @param [String] str String with source code fragment of Ruby extension.
237
+ #
238
+ # @return [GCCContext] Returns +self+.
239
+ #
240
+ # @private
143
241
  def <<( str )
144
242
  @instructions << str
145
243
  self
@@ -16,17 +16,41 @@
16
16
 
17
17
  # Namespace of Hornetseye computer vision library
18
18
  module Hornetseye
19
-
19
+
20
+ # Class representing a compiled function
20
21
  class GCCFunction
21
22
 
22
23
  class << self
23
24
 
25
+ # Compile a block of Ruby code if not compiled already and run it
26
+ #
27
+ # @param [Node] block Expression to compile and run.
28
+ #
29
+ # @return [Object] Result returned by the compiled function.
30
+ #
31
+ # @private
24
32
  def run( block )
25
33
  keys, values, term = block.strip
26
34
  labels = Hash[ *keys.zip( ( 0 ... keys.size ).to_a ).flatten ]
27
35
  method_name = ( '_' + term.descriptor( labels ) ).
28
36
  tr( '(),+\-*/%.@?~&|^<=>',
29
37
  '0123\456789ABCDEFGH' )
38
+ compile method_name, term, *keys
39
+ args = values.collect { |arg| arg.values }.flatten
40
+ GCCCache.send method_name, *args
41
+ end
42
+
43
+ # Compile a block of Ruby code if not compiled already
44
+ #
45
+ # @param [String] method_name Unique method name of function.
46
+ # @param [Node] term Stripped expression to compile.
47
+ # @param [Array<Variable>] keys Variables for performing substitutions on
48
+ # +term+.
49
+ #
50
+ # @return [Object] The return value should be ignored.
51
+ #
52
+ # @private
53
+ def compile( method_name, term, *keys )
30
54
  unless GCCCache.respond_to? method_name
31
55
  GCCContext.build do |context|
32
56
  function = GCCFunction.new context, method_name,
@@ -43,12 +67,17 @@ module Hornetseye
43
67
  function.compile
44
68
  end
45
69
  end
46
- args = values.collect { |arg| arg.values }.flatten
47
- GCCCache.send method_name, *args
48
70
  end
49
71
 
50
72
  end
51
73
 
74
+ # Constructor
75
+ #
76
+ # @param [GCContext] context Context object for compiling function.
77
+ # @param [String] method_name Unique method name.
78
+ # @param [Array<Class>] param_types Native types of parameters.
79
+ #
80
+ # @private
52
81
  def initialize( context, method_name, *param_types )
53
82
  context.function method_name, *param_types.collect { |t| GCCType.new t }
54
83
  @context = context
@@ -58,31 +87,70 @@ module Hornetseye
58
87
  @ids = 0
59
88
  end
60
89
 
90
+ # Close the function and compile it
91
+ #
92
+ # @return [GCCFunction] Returns +self+.
93
+ #
94
+ # @private
61
95
  def compile
62
96
  self << '}'
63
97
  @context.compile
64
98
  self
65
99
  end
66
100
 
101
+ # Create a new identifier unique to this function
102
+ #
103
+ # @param [String] prefix Prefix for constructing the identifier.
104
+ #
105
+ # @return [String] A new identifier.
106
+ #
107
+ # @private
67
108
  def id( prefix )
68
109
  @ids += 1
69
110
  "%s%02d"% [ prefix, @ids ]
70
111
  end
71
112
 
113
+ # Create a new C variable of given type
114
+ #
115
+ # @param [Class] typecode Native type of variable.
116
+ # @param [String] prefix Prefix for creating variable name.
117
+ #
118
+ # @return [GCCValue] GCC value object refering to the C variable.
119
+ #
120
+ # @private
72
121
  def variable( typecode, prefix )
73
122
  retval = GCCValue.new( self, id( prefix ) )
74
123
  self << "#{indent}#{GCCType.new( typecode ).identifier} #{retval};\n"
75
124
  retval
76
125
  end
77
126
 
127
+ # Auxiliary method for code intendation
128
+ #
129
+ # @return [String] String to use for indentation.
130
+ #
131
+ # @private
78
132
  def indent
79
133
  ' ' * @indent
80
134
  end
81
135
 
136
+ # Increase/decrease amount of indentation
137
+ #
138
+ # @param [Integer] offset Offset to add to current amount of indentation.
139
+ #
140
+ # @return [Integer] Resulting amount of indentation.
141
+ #
142
+ # @private
82
143
  def indent_offset( offset )
83
144
  @indent += offset
84
145
  end
85
146
 
147
+ # Retrieve a parameter
148
+ #
149
+ # @param [Integer] i Parameter to retrieve.
150
+ #
151
+ # @return [Node] Object for handling the parameter.
152
+ #
153
+ # @private
86
154
  def param( i )
87
155
  offset = ( 0 ... i ).inject( 0 ) do |s,idx|
88
156
  s + GCCType.new( @param_types[ idx ] ).identifiers.size
@@ -92,14 +160,35 @@ module Hornetseye
92
160
  @param_types[ i ].construct *args
93
161
  end
94
162
 
163
+ # Call the native method
164
+ #
165
+ # @param [Array<Node>] args Arguments of method call.
166
+ #
167
+ # @return The return value of the native method.
168
+ #
169
+ # @private
95
170
  def call( *args )
96
171
  @context.send @method_name, *args.collect { |v| v.get }
97
172
  end
98
173
 
174
+ # Add return instruction to native method
175
+ #
176
+ # @param [Object,NilClass] value Return value or +nil+.
177
+ #
178
+ # @return [GCCFunction] Returns +self+.
179
+ #
180
+ # @private
99
181
  def insn_return( value = nil )
100
182
  self << "#{indent}return#{ value ? ' ' + value.get.to_s : '' };\n"
101
183
  end
102
184
 
185
+ # Add instructions to C function
186
+ #
187
+ # @param [String] str C code fragment.
188
+ #
189
+ # @return [GCCFunction] Returns +self+.
190
+ #
191
+ # @private
103
192
  def <<( str )
104
193
  @context << str
105
194
  self