multiarray 0.11.3 → 0.11.4

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.
@@ -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