multiarray 0.22.0 → 0.23.1

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