multiarray 0.22.0 → 0.23.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. data/Rakefile +1 -1
  2. data/lib/multiarray.rb +53 -16
  3. data/lib/multiarray/bool.rb +1 -1
  4. data/lib/multiarray/complex.rb +76 -68
  5. data/lib/multiarray/components.rb +11 -10
  6. data/lib/multiarray/composite.rb +1 -1
  7. data/lib/multiarray/diagonal.rb +11 -12
  8. data/lib/multiarray/element.rb +3 -3
  9. data/lib/multiarray/elementwise.rb +14 -14
  10. data/lib/multiarray/field.rb +380 -0
  11. data/lib/multiarray/float.rb +10 -10
  12. data/lib/multiarray/gcccache.rb +1 -1
  13. data/lib/multiarray/gcccontext.rb +35 -54
  14. data/lib/multiarray/gccfunction.rb +12 -19
  15. data/lib/multiarray/gcctype.rb +1 -1
  16. data/lib/multiarray/gccvalue.rb +63 -43
  17. data/lib/multiarray/histogram.rb +17 -19
  18. data/lib/multiarray/index.rb +7 -8
  19. data/lib/multiarray/inject.rb +11 -12
  20. data/lib/multiarray/int.rb +12 -11
  21. data/lib/multiarray/integral.rb +11 -12
  22. data/lib/multiarray/lambda.rb +23 -18
  23. data/lib/multiarray/list.rb +1 -1
  24. data/lib/multiarray/lookup.rb +18 -13
  25. data/lib/multiarray/lut.rb +13 -16
  26. data/lib/multiarray/malloc.rb +1 -1
  27. data/lib/multiarray/mask.rb +11 -8
  28. data/lib/multiarray/methods.rb +10 -10
  29. data/lib/multiarray/multiarray.rb +15 -44
  30. data/lib/multiarray/node.rb +64 -138
  31. data/lib/multiarray/object.rb +2 -6
  32. data/lib/multiarray/operations.rb +116 -134
  33. data/lib/multiarray/pointer.rb +7 -19
  34. data/lib/multiarray/random.rb +11 -8
  35. data/lib/multiarray/rgb.rb +53 -53
  36. data/lib/multiarray/sequence.rb +11 -496
  37. data/lib/multiarray/shortcuts.rb +4 -4
  38. data/lib/multiarray/store.rb +14 -11
  39. data/lib/multiarray/unmask.rb +10 -7
  40. data/lib/multiarray/variable.rb +11 -3
  41. data/test/tc_bool.rb +0 -8
  42. data/test/tc_compile.rb +72 -0
  43. data/test/tc_float.rb +0 -8
  44. data/test/tc_int.rb +0 -8
  45. data/test/tc_lazy.rb +22 -3
  46. data/test/tc_multiarray.rb +100 -126
  47. data/test/tc_object.rb +0 -16
  48. data/test/tc_rgb.rb +0 -16
  49. data/test/tc_sequence.rb +151 -165
  50. data/test/ts_multiarray.rb +2 -0
  51. metadata +7 -4
@@ -1,5 +1,5 @@
1
1
  # multiarray - Lazy multi-dimensional arrays for Ruby
2
- # Copyright (C) 2010 Jan Wedekind
2
+ # Copyright (C) 2010, 2011 Jan Wedekind
3
3
  #
4
4
  # This program is free software: you can redistribute it and/or modify
5
5
  # it under the terms of the GNU General Public License as published by
@@ -29,6 +29,12 @@ module Hornetseye
29
29
  # @private
30
30
  attr_accessor :double
31
31
 
32
+ def inherit(double)
33
+ retval = Class.new self
34
+ retval.double = double
35
+ retval
36
+ end
37
+
32
38
  # Memory type required to store elements of this type
33
39
  #
34
40
  # @return [Class] Returns +Malloc+.
@@ -112,11 +118,7 @@ module Hornetseye
112
118
  #
113
119
  # @return [String] Returns a string (e.g. "SFLOAT").
114
120
  def inspect
115
- retval = "#{ double ? 'D' : 'S' }FLOAT"
116
- ( class << self; self; end ).instance_eval do
117
- define_method( :inspect ) { retval }
118
- end
119
- retval
121
+ "#{ double ? 'D' : 'S' }FLOAT"
120
122
  end
121
123
 
122
124
  # Get unique descriptor of this class
@@ -237,10 +239,8 @@ module Hornetseye
237
239
  #
238
240
  # @see FLOAT_
239
241
  # @see FLOAT_.double
240
- def FLOAT( double )
241
- retval = Class.new FLOAT_
242
- retval.double = double
243
- retval
242
+ def FLOAT(double)
243
+ FLOAT_.inherit double
244
244
  end
245
245
 
246
246
  module_function :FLOAT
@@ -1,5 +1,5 @@
1
1
  # multiarray - Lazy multi-dimensional arrays for Ruby
2
- # Copyright (C) 2010 Jan Wedekind
2
+ # Copyright (C) 2010, 2011 Jan Wedekind
3
3
  #
4
4
  # This program is free software: you can redistribute it and/or modify
5
5
  # it under the terms of the GNU General Public License as published by
@@ -1,5 +1,5 @@
1
1
  # multiarray - Lazy multi-dimensional arrays for Ruby
2
- # Copyright (C) 2010 Jan Wedekind
2
+ # Copyright (C) 2010, 2011 Jan Wedekind
3
3
  #
4
4
  # This program is free software: you can redistribute it and/or modify
5
5
  # it under the terms of the GNU General Public License as published by
@@ -112,9 +112,9 @@ module Hornetseye
112
112
  # @private
113
113
  def initialize( lib_name )
114
114
  @lib_name = lib_name
115
- @instructions = ''
116
- @wrappers = ''
117
- @registrations = ''
115
+ @c_instructions = ''
116
+ @c_wrappers = ''
117
+ @c_registrations = ''
118
118
  end
119
119
 
120
120
  # Create Ruby extension
@@ -137,54 +137,34 @@ module Hornetseye
137
137
  #
138
138
  # @private
139
139
  def function( descriptor, *param_types )
140
- @instructions << <<EOS
141
- struct Arguments
142
- {
143
- #{
140
+ @c_instructions << <<EOS
141
+ VALUE #{descriptor}( #{
144
142
  param_types.collect do |t|
145
143
  t.identifiers
146
144
  end.flatten.collect_with_index do |ident,i|
147
- " #{ident} param#{i};"
148
- end.join( "\n" )
149
- }
150
- };
151
-
152
- VALUE #{descriptor}( void *args )
145
+ "#{ident} param#{i}"
146
+ end.join ', '
147
+ } )
153
148
  {
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
- }
161
149
  EOS
162
150
 
163
- @wrappers << <<EOS
151
+ @c_wrappers << <<EOS
164
152
  VALUE wrap#{descriptor.capitalize}( int argc, VALUE *argv, VALUE rbSelf )
165
153
  {
166
- struct Arguments args;
167
- #{
154
+ #{descriptor}( #{
168
155
  param_types.collect do |t|
169
156
  t.r2c
170
157
  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 );"
177
- else
178
- " rb_thread_blocking_region( &#{descriptor}, &args, RUBY_UBF_PROCESS, NULL );"
179
- end
180
- }
158
+ "#{conv.call "argv[#{i}]"}"
159
+ end.join ', '
160
+ } );
181
161
  return Qnil;
182
162
  }
183
163
  EOS
184
164
 
185
- @registrations << <<EOS
186
- rb_define_singleton_method( cGCCCache, "#{descriptor}",
187
- RUBY_METHOD_FUNC( wrap#{descriptor.capitalize} ), -1 );
165
+ @c_registrations << <<EOS
166
+ rb_define_singleton_method(cGCCCache, "#{descriptor}",
167
+ RUBY_METHOD_FUNC( wrap#{descriptor.capitalize} ), -1);
188
168
  EOS
189
169
  end
190
170
 
@@ -197,7 +177,8 @@ EOS
197
177
  #
198
178
  # @private
199
179
  def compile
200
- template = <<EOS
180
+ c_template = <<EOS
181
+ /* This file is generated automatically. It is pointless to edit this file. */
201
182
  #include <ruby.h>
202
183
  #include <math.h>
203
184
 
@@ -220,43 +201,43 @@ static unsigned long make_mask( unsigned long x )
220
201
  return x;
221
202
  }
222
203
 
223
- static unsigned long limited_rand( unsigned long limit )
204
+ static unsigned long limited_rand(unsigned long limit)
224
205
  {
225
206
  int i;
226
207
  unsigned long mask, val;
227
- if ( limit < 2 ) return 0;
228
- mask = make_mask( limit - 1 );
208
+ if (limit < 2) return 0;
209
+ mask = make_mask(limit - 1);
229
210
  retry:
230
211
  val = 0;
231
- for ( i = SIZEOF_LONG / 4 - 1; 0 <= i; i-- ) {
232
- if ( ( mask >> ( i * 32 ) ) & 0xffffffff ) {
233
- val |= (unsigned long)rb_genrand_int32() << ( i * 32 );
212
+ for (i = SIZEOF_LONG / 4 - 1; 0 <= i; i--) {
213
+ if ((mask >> (i * 32)) & 0xffffffff) {
214
+ val |= (unsigned long)rb_genrand_int32() << (i * 32);
234
215
  val &= mask;
235
- if ( limit <= val )
216
+ if (limit <= val)
236
217
  goto retry;
237
218
  };
238
219
  };
239
220
  return val;
240
221
  }
241
222
 
242
- #{@instructions}
223
+ #{@c_instructions}
243
224
 
244
- #{@wrappers}
225
+ #{@c_wrappers}
245
226
  void Init_#{@lib_name}(void)
246
227
  {
247
- VALUE mHornetseye = rb_define_module( "Hornetseye" );
248
- VALUE cGCCCache = rb_define_class_under( mHornetseye, "GCCCache",
249
- rb_cObject );
250
- #{@registrations}
228
+ VALUE mHornetseye = rb_define_module("Hornetseye");
229
+ VALUE cGCCCache = rb_define_class_under(mHornetseye, "GCCCache", rb_cObject);
230
+ #{@c_registrations}
251
231
  }
252
232
  EOS
253
233
  # File::EXCL no overwrite
254
234
  File.open "#{DIRNAME}/#{@lib_name}.c", 'w', 0600 do |f|
255
- f << template
235
+ f << c_template
256
236
  end
257
237
  gcc = "#{LDSHARED} #{CFLAGS} -o #{DIRNAME}/#{@lib_name}.#{DLEXT} " +
258
238
  "#{DIRNAME}/#{@lib_name}.c #{LIBRUBYARG}"
259
- # puts template
239
+ # puts c_template
240
+ # puts gcc
260
241
  raise "The following command failed: #{gcc}" unless system gcc
261
242
  require "#{DIRNAME}/#{@lib_name}"
262
243
  end
@@ -271,7 +252,7 @@ EOS
271
252
  #
272
253
  # @private
273
254
  def <<( str )
274
- @instructions << str
255
+ @c_instructions << str
275
256
  self
276
257
  end
277
258
 
@@ -1,5 +1,5 @@
1
1
  # multiarray - Lazy multi-dimensional arrays for Ruby
2
- # Copyright (C) 2010 Jan Wedekind
2
+ # Copyright (C) 2010, 2011 Jan Wedekind
3
3
  #
4
4
  # This program is free software: you can redistribute it and/or modify
5
5
  # it under the terms of the GNU General Public License as published by
@@ -31,40 +31,33 @@ module Hornetseye
31
31
  # @private
32
32
  def run( block )
33
33
  keys, values, term = block.strip
34
- labels = Hash[ *keys.zip( ( 0 ... keys.size ).to_a ).flatten ]
35
- method_name = ( '_' + term.descriptor( labels ) ).
36
- tr( '(),+\-*/%.@?~&|^<=>',
37
- '0123\456789ABCDEFGH' )
38
- compile method_name, term, *keys
39
- args = values.collect { |arg| arg.values }.flatten
40
- GCCCache.send method_name, *args
34
+ GCCCache.send compile(term, *keys), *values.collect { |arg| arg.values }.flatten
41
35
  end
42
36
 
43
37
  # Compile a block of Ruby code if not compiled already
44
38
  #
45
- # @param [String] method_name Unique method name of function.
46
39
  # @param [Node] term Stripped expression to compile.
47
- # @param [Array<Variable>] keys Variables for performing substitutions on
48
- # +term+.
40
+ # @param [Array<Variable>] keys Variables for performing substitutions on +term+.
49
41
  #
50
- # @return [Object] The return value should be ignored.
42
+ # @return [String] Unique method name of compiled function.
51
43
  #
52
44
  # @private
53
- def compile( method_name, term, *keys )
45
+ def compile(term, *keys)
46
+ labels = Hash[*keys.zip((0 ... keys.size).to_a).flatten]
47
+ method_name = ('_' + term.descriptor(labels)).method_name
54
48
  unless GCCCache.respond_to? method_name
55
49
  GCCContext.build do |context|
56
50
  function = GCCFunction.new context, method_name,
57
51
  *keys.collect { |var| var.meta }
58
- Thread.current[ :function ] = function
59
- term_subst = Hash[ *keys.zip( function.params ).flatten ]
60
- Hornetseye::lazy do
61
- term.subst( term_subst ).demand
62
- end
63
- Thread.current[ :function ] = nil
52
+ Thread.current[:function] = function
53
+ term_subst = Hash[ *keys.zip(function.params).flatten ]
54
+ Hornetseye::lazy { term.subst(term_subst).demand }
55
+ Thread.current[:function] = nil
64
56
  function.insn_return
65
57
  function.compile
66
58
  end
67
59
  end
60
+ method_name
68
61
  end
69
62
 
70
63
  end
@@ -1,5 +1,5 @@
1
1
  # multiarray - Lazy multi-dimensional arrays for Ruby
2
- # Copyright (C) 2010 Jan Wedekind
2
+ # Copyright (C) 2010, 2011 Jan Wedekind
3
3
  #
4
4
  # This program is free software: you can redistribute it and/or modify
5
5
  # it under the terms of the GNU General Public License as published by
@@ -1,5 +1,5 @@
1
1
  # multiarray - Lazy multi-dimensional arrays for Ruby
2
- # Copyright (C) 2010 Jan Wedekind
2
+ # Copyright (C) 2010, 2011 Jan Wedekind
3
3
  #
4
4
  # This program is free software: you can redistribute it and/or modify
5
5
  # it under the terms of the GNU General Public License as published by
@@ -47,7 +47,7 @@ module Hornetseye
47
47
  #
48
48
  # @private
49
49
  def define_unary_op( op, opcode = op )
50
- define_method( op ) do
50
+ define_method op do
51
51
  GCCValue.new @function, "#{opcode}( #{self} )"
52
52
  end
53
53
  end
@@ -62,7 +62,7 @@ module Hornetseye
62
62
  # @private
63
63
  def define_unary_method( mod, op, opcode = op )
64
64
  mod.module_eval do
65
- define_method( "#{op}_with_gcc" ) do |a|
65
+ define_method "#{op}_with_gcc" do |a|
66
66
  if a.is_a? GCCValue
67
67
  GCCValue.new a.function, "#{opcode}( #{a} )"
68
68
  else
@@ -84,7 +84,7 @@ module Hornetseye
84
84
  #
85
85
  # @private
86
86
  def define_binary_op( op, opcode = op )
87
- define_method( op ) do |other|
87
+ define_method op do |other|
88
88
  if GCCValue.generic? other
89
89
  GCCValue.new @function, "( #{self} ) #{opcode} ( #{other} )"
90
90
  else
@@ -104,7 +104,7 @@ module Hornetseye
104
104
  # @private
105
105
  def define_binary_method( mod, op, opcode = op )
106
106
  mod.module_eval do
107
- define_method( "#{op}_with_gcc" ) do |a,b|
107
+ define_method "#{op}_with_gcc" do |a,b|
108
108
  if a.is_a? GCCValue or b.is_a? GCCValue
109
109
  function = a.is_a?( GCCValue ) ? a.function : b.function
110
110
  GCCValue.new function, "#{opcode}( #{a}, #{b} )"
@@ -304,44 +304,6 @@ module Hornetseye
304
304
  end
305
305
  end
306
306
 
307
- # Create code for conditional selection of RGB value
308
- #
309
- # @param [GCCValue,Object] a First value.
310
- # @param [GCCValue,Object] b Second value.
311
- #
312
- # @return [GCCValue] C value referring to result.
313
- #
314
- # @private
315
- def conditional_with_rgb( a, b )
316
- if a.is_a?( RGB ) or b.is_a?( RGB )
317
- Hornetseye::RGB( conditional( a.r, b.r ), conditional( a.g, b.g ),
318
- conditional( a.b, b.b ) )
319
- else
320
- conditional_without_rgb a, b
321
- end
322
- end
323
-
324
- alias_method_chain :conditional, :rgb
325
-
326
- # Create code for conditional selection of complex value
327
- #
328
- # @param [GCCValue,Object] a First value.
329
- # @param [GCCValue,Object] b Second value.
330
- #
331
- # @return [GCCValue] C value referring to result.
332
- #
333
- # @private
334
- def conditional_with_complex( a, b )
335
- if a.is_a?( InternalComplex ) or b.is_a?( InternalComplex )
336
- InternalComplex.new conditional( a.real, b.real ),
337
- conditional( a.imag, b.imag )
338
- else
339
- conditional_without_complex a, b
340
- end
341
- end
342
-
343
- alias_method_chain :conditional, :complex
344
-
345
307
  # Generate code for conditional statement
346
308
  #
347
309
  # @param [Proc] action Block of conditional.
@@ -400,6 +362,7 @@ module Hornetseye
400
362
  define_binary_op :<=
401
363
  define_binary_op :>
402
364
  define_binary_op :>=
365
+ define_binary_op :>=
403
366
  define_unary_method Math, :sqrt
404
367
  define_unary_method Math, :log
405
368
  define_unary_method Math, :log10
@@ -522,6 +485,63 @@ module Hornetseye
522
485
  "( ( #{self} ) <= ( #{other} ) ) ? ( #{self} ) : ( #{other} )"
523
486
  end
524
487
 
488
+ # Create code for conditional selection of RGB value
489
+ #
490
+ # @param [GCCValue,Object] a First value.
491
+ # @param [GCCValue,Object] b Second value.
492
+ #
493
+ # @return [GCCValue] C value referring to result.
494
+ #
495
+ # @private
496
+ def conditional_with_rgb( a, b )
497
+ if a.is_a?(RGB) or b.is_a?(RGB)
498
+ Hornetseye::RGB conditional(a.r, b.r), conditional(a.g, b.g), conditional(a.b, b.b)
499
+ else
500
+ conditional_without_rgb a, b
501
+ end
502
+ end
503
+
504
+ alias_method_chain :conditional, :rgb
505
+
506
+ # Create code for conditional selection of complex value
507
+ #
508
+ # @param [GCCValue,Object] a First value.
509
+ # @param [GCCValue,Object] b Second value.
510
+ #
511
+ # @return [GCCValue] C value referring to result.
512
+ #
513
+ # @private
514
+ def conditional_with_complex( a, b )
515
+ if a.is_a?( InternalComplex ) or b.is_a?( InternalComplex )
516
+ InternalComplex.new conditional( a.real, b.real ),
517
+ conditional( a.imag, b.imag )
518
+ else
519
+ conditional_without_complex a, b
520
+ end
521
+ end
522
+
523
+ alias_method_chain :conditional, :complex
524
+
525
+ def major_with_rgb(other)
526
+ if other.is_a?(RGB)
527
+ Hornetseye::RGB r.major(other.r), g.major(other.g), b.major(other.b)
528
+ else
529
+ major_without_rgb other
530
+ end
531
+ end
532
+
533
+ alias_method_chain :major, :rgb
534
+
535
+ def minor_with_rgb(other)
536
+ if other.is_a?(RGB)
537
+ Hornetseye::RGB r.minor(other.r), g.minor(other.g), b.minor(other.b)
538
+ else
539
+ minor_without_rgb other
540
+ end
541
+ end
542
+
543
+ alias_method_chain :minor, :rgb
544
+
525
545
  # Generate a +for+ loop in C
526
546
  #
527
547
  # @param [Proc] action Code for generating loop body.
@@ -1,5 +1,5 @@
1
1
  # multiarray - Lazy multi-dimensional arrays for Ruby
2
- # Copyright (C) 2010 Jan Wedekind
2
+ # Copyright (C) 2010, 2011 Jan Wedekind
3
3
  #
4
4
  # This program is free software: you can redistribute it and/or modify
5
5
  # it under the terms of the GNU General Public License as published by
@@ -44,6 +44,10 @@ module Hornetseye
44
44
  @dest, @weight, @sources = dest, weight, sources
45
45
  end
46
46
 
47
+ def sexp?
48
+ true
49
+ end
50
+
47
51
  # Get unique descriptor of this object
48
52
  #
49
53
  # @param [Hash] hash Labels for any variables.
@@ -57,17 +61,12 @@ module Hornetseye
57
61
  "#{@sources.collect { |source| source.descriptor( hash ) }.join ','})"
58
62
  end
59
63
 
60
- # Get type of result of delayed operation
61
- #
62
- # @return [Class] Type of result.
63
- #
64
- # @private
65
- def array_type
66
- retval = @dest.array_type
67
- ( class << self; self; end ).instance_eval do
68
- define_method( :array_type ) { retval }
69
- end
70
- retval
64
+ def typecode
65
+ @dest.typecode
66
+ end
67
+
68
+ def shape
69
+ @dest.shape
71
70
  end
72
71
 
73
72
  # Reevaluate computation
@@ -80,19 +79,18 @@ module Hornetseye
80
79
  def demand
81
80
  if variables.empty?
82
81
  if @sources.any? { |source| source.dimension > 0 }
83
- source_type = @sources.
84
- collect { |source| source.array_type }.inject { |a,b| a.coercion b }
82
+ source_type = @sources.inject { |a,b| a.dimension > b.dimension ? a : b }
85
83
  source_type.shape.last.times do |i|
86
84
  sources = @sources.collect do |source|
87
- source.dimension > 0 ? source.element( INT.new( i ) ) : source
85
+ source.dimension > 0 ? source.element(INT.new(i)) : source
88
86
  end
89
- weight = @weight.dimension > 0 ? @weight.element( INT.new( i ) ) : @weight
90
- Histogram.new( @dest, weight, *sources ).demand
87
+ weight = @weight.dimension > 0 ? @weight.element(INT.new(i)) : @weight
88
+ Histogram.new(@dest, weight, *sources).demand
91
89
  end
92
90
  else
93
91
  dest = @dest
94
- ( @dest.dimension - 1 ).downto( 0 ) do |i|
95
- dest = dest.element @sources[ i ].demand
92
+ (@dest.dimension - 1).downto(0) do |i|
93
+ dest = dest.element @sources[i].demand
96
94
  end
97
95
  dest.store dest + @weight
98
96
  end