mdarray 0.5.0.pre-java → 0.5.3-java

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 (42) hide show
  1. data/README.md +89 -90
  2. data/Rakefile +6 -1
  3. data/lib/colt/cern_double_functions.rb +193 -0
  4. data/lib/colt/cern_float_functions.rb +193 -0
  5. data/lib/colt/cern_int_functions.rb +152 -0
  6. data/lib/colt/cern_long_functions.rb +152 -0
  7. data/lib/colt/colt.rb +103 -1
  8. data/lib/mdarray.rb +71 -23
  9. data/lib/mdarray/access.rb +8 -0
  10. data/lib/mdarray/counter.rb +43 -1
  11. data/lib/mdarray/creation.rb +5 -10
  12. data/lib/mdarray/fast_operators.rb +17 -13
  13. data/lib/mdarray/function_creation.rb +11 -45
  14. data/lib/mdarray/function_map.rb +16 -8
  15. data/lib/mdarray/lazy_mdarray.rb +311 -0
  16. data/lib/mdarray/lazy_operators.rb +166 -0
  17. data/lib/mdarray/operators.rb +38 -9
  18. data/lib/mdarray/proc_util.rb +2 -0
  19. data/lib/mdarray/ruby_boolean_functions.rb +24 -0
  20. data/lib/mdarray/ruby_functions.rb +76 -2
  21. data/lib/mdarray/ruby_generic_functions.rb +12 -4
  22. data/lib/mdarray/ruby_math.rb +180 -2
  23. data/lib/mdarray/ruby_numeric_functions.rb +198 -7
  24. data/target/helper.jar +0 -0
  25. data/test/colt/ColtMethods.xlsx +0 -0
  26. data/test/colt/test_complete.rb +1 -0
  27. data/test/colt/test_math.rb +249 -0
  28. data/test/complete.rb +1 -0
  29. data/test/env.rb +17 -4
  30. data/test/mdarray/arithmetic_casting.rb +3 -0
  31. data/test/mdarray/test_boolean.rb +1 -1
  32. data/test/mdarray/test_complete.rb +1 -0
  33. data/test/mdarray/test_error.rb +13 -13
  34. data/test/mdarray/test_lazy.rb +306 -0
  35. data/test/mdarray/test_operator.rb +1 -1
  36. data/test/mdarray/test_performance.rb +57 -4
  37. data/test/mdarray/test_trigonometry.rb +5 -1
  38. data/vendor/commons-compiler.jar +0 -0
  39. data/vendor/janino.jar +0 -0
  40. data/version.rb +1 -1
  41. metadata +47 -10
  42. data/test/mdarray/test_statistics.rb +0 -80
@@ -70,6 +70,14 @@ class MDArray
70
70
  @local_index.get(index)
71
71
  end
72
72
 
73
+ #------------------------------------------------------------------------------------
74
+ #
75
+ #------------------------------------------------------------------------------------
76
+
77
+ def jget(index = nil)
78
+ @local_index.jget(index)
79
+ end
80
+
73
81
  #------------------------------------------------------------------------------------
74
82
  # Gets the next element of the local iterator
75
83
  #------------------------------------------------------------------------------------
@@ -178,6 +178,16 @@ class MDArray
178
178
  get_at_counter
179
179
  end
180
180
 
181
+ #------------------------------------------------------------------------------------
182
+ # Gets the element at the given counter. Assumes that the counter is of the proper
183
+ # shape. Also, counter should be an int java array
184
+ #------------------------------------------------------------------------------------
185
+
186
+ def jget(counter)
187
+ jset_counter_fast(counter)
188
+ get_at_counter
189
+ end
190
+
181
191
  #------------------------------------------------------------------------------------
182
192
  # Gets element at current counter. Can be done fast, as counter is always of the
183
193
  # proper shape.
@@ -328,6 +338,21 @@ class MDArray
328
338
 
329
339
  end
330
340
 
341
+ #-------------------------------------------------------------------------------------
342
+ # Sets this index to point to the given counter. Assumes that the counter respects
343
+ # the shape constraints. Also, in this case, the counter should be an int java array.
344
+ #-------------------------------------------------------------------------------------
345
+
346
+ def jset_counter_fast(counter)
347
+
348
+ begin
349
+ @nc_index.set(counter)
350
+ rescue java.lang.ArrayIndexOutOfBoundsException
351
+ raise RangeError, "Invalid counter: #{counter}"
352
+ end
353
+
354
+ end
355
+
331
356
  #-------------------------------------------------------------------------------------
332
357
  # Sets this index to point to the given counter. If given counter has negative values
333
358
  # then convert them to positive values, making sure that the counter respects the
@@ -500,6 +525,15 @@ class MDArray
500
525
  @nc_index.getCurrentCounter().to_a
501
526
  end
502
527
 
528
+ #-------------------------------------------------------------------------------------
529
+ # Returns the current counter as a java array. This is for performance improvement.
530
+ # Should be used carefully so that it doesn't permeate ruby code.
531
+ #-------------------------------------------------------------------------------------
532
+
533
+ def jget_current_counter
534
+ @nc_index.getCurrentCounter()
535
+ end
536
+
503
537
  end # Counter
504
538
 
505
539
 
@@ -545,6 +579,15 @@ class MDArray
545
579
  @iterator.getCurrentCounter().to_a
546
580
  end
547
581
 
582
+ #-------------------------------------------------------------------------------------
583
+ # Returns the current counter as a java array. This is for performance improvement.
584
+ # Should be used carefully so that it doesn't permeate ruby code.
585
+ #-------------------------------------------------------------------------------------
586
+
587
+ def jget_current_counter
588
+ @iterator.getCurrentCounter()
589
+ end
590
+
548
591
  #------------------------------------------------------------------------------------
549
592
  #
550
593
  #------------------------------------------------------------------------------------
@@ -611,7 +654,6 @@ class MDArray
611
654
  #
612
655
  #---------------------------------------------------------------------------------------
613
656
 
614
-
615
657
  class IteratorFastByte < IteratorFast
616
658
 
617
659
  def get_current
@@ -25,13 +25,6 @@
25
25
 
26
26
  class MDArray
27
27
 
28
- class << self
29
-
30
- attr_accessor :binary_operator
31
- attr_accessor :unary_operator
32
-
33
- end
34
-
35
28
  #------------------------------------------------------------------------------------
36
29
  # Given two types returns the upcasted one
37
30
  #------------------------------------------------------------------------------------
@@ -356,15 +349,17 @@ class MDArray
356
349
  end
357
350
 
358
351
  #------------------------------------------------------------------------------------
359
- #
352
+ # fmap is an array with the following data: long_name, scope, function, return_type,
353
+ # input1_type, input2_type
360
354
  #------------------------------------------------------------------------------------
361
355
 
362
- def self.register_function(name, func)
356
+ def self.register_function(name, fmap, arity, helper_class)
363
357
 
364
358
  if ((list = MDArray.function_map[name]) == nil)
365
359
  list = (MDArray.function_map[name] = Array.new)
366
360
  end
367
- list << FunctionMap.new(name, func[0], func[1], func[2], func[3], func[4], func[5])
361
+ list << FunctionMap.new(name, fmap[0], fmap[1], fmap[2], fmap[3], fmap[4], fmap[5],
362
+ arity, helper_class)
368
363
 
369
364
  end
370
365
 
@@ -69,7 +69,9 @@ class FastBinaryOperator < BinaryOperator
69
69
  end
70
70
 
71
71
  #---------------------------------------------------------------------------------------
72
- #
72
+ # A default binary operator takes two arrays where one array can be degenerated (a
73
+ # number and loops through all elements of the arrays applying a given method to them.
74
+ # For instance, operator '+' in a + b is a default binary operator.
73
75
  #---------------------------------------------------------------------------------------
74
76
 
75
77
  def default(*args)
@@ -78,13 +80,13 @@ class FastBinaryOperator < BinaryOperator
78
80
  get_args(*args) do |op1, op2, shape, *other_args|
79
81
  calc = MDArray.build(@type, shape)
80
82
  if (@coerced)
81
- helper = Java::RbMdarrayLoopsBinops::CoerceBinaryOperator
83
+ helper = @helper::CoerceBinaryOperator
82
84
  helper.send("apply", calc.nc_array, op1, op2, @do_func)
83
85
  elsif (@op1.is_a? NumericalMDArray)
84
- helper = Java::RbMdarrayLoopsBinops::DefaultBinaryOperator
86
+ helper = @helper::DefaultBinaryOperator
85
87
  helper.send("apply", calc.nc_array, op1, op2, @do_func)
86
88
  else
87
- helper = Java::RbMdarrayLoopsBinops::DefaultBinaryOperator
89
+ helper = @helper::DefaultBinaryOperator
88
90
  helper.send("apply#{@op1.class}", calc.nc_array, op1, op2, @do_func)
89
91
  end
90
92
  end
@@ -93,13 +95,15 @@ class FastBinaryOperator < BinaryOperator
93
95
  end
94
96
 
95
97
  #---------------------------------------------------------------------------------------
96
- #
98
+ # A fill binary operator takes two arrays where one array can be degenerated (a number)
99
+ # and loops through all elements of the arrays, setting the value of the first array
100
+ # to the values of the second.
97
101
  #---------------------------------------------------------------------------------------
98
102
 
99
103
  def fill(*args)
100
104
 
101
105
  get_args(*args) do |op1, op2, shape, *other_args|
102
- helper = Java::RbMdarrayLoopsBinops::FillBinaryOperator
106
+ helper = @helper::FillBinaryOperator
103
107
  helper.send("apply", op1, op2)
104
108
  end
105
109
 
@@ -112,7 +116,7 @@ class FastBinaryOperator < BinaryOperator
112
116
  def in_place(*args)
113
117
 
114
118
  get_args(*args) do |op1, op2, shape, *other_args|
115
- helper = Java::RbMdarrayLoopsBinops::InplaceBinaryOperator
119
+ helper = @helper::InplaceBinaryOperator
116
120
  helper.send("apply", op1, op2, @do_func)
117
121
  end
118
122
 
@@ -127,7 +131,7 @@ class FastBinaryOperator < BinaryOperator
127
131
  calc = nil
128
132
 
129
133
  get_args(*args) do |op1, op2, shape, *other_args|
130
- helper = Java::RbMdarrayLoopsBinops::ReduceBinaryOperator
134
+ helper = @helper::ReduceBinaryOperator
131
135
  calc = @pre_condition_result
132
136
  calc = helper.send("apply", calc, op1, op2, @do_func)
133
137
  end
@@ -145,7 +149,7 @@ class FastBinaryOperator < BinaryOperator
145
149
  calc = nil
146
150
 
147
151
  get_args(*args) do |op1, op2, shape, *other_args|
148
- helper = Java::RbMdarrayLoopsBinops::ComplexReduceBinaryOperator
152
+ helper = @helper::ComplexReduceBinaryOperator
149
153
  calc = @pre_condition_result
150
154
  calc = helper.send("apply", calc, op1, op2, @do_func)
151
155
  end
@@ -181,7 +185,7 @@ class FastUnaryOperator < UnaryOperator
181
185
 
182
186
  get_args(*args) do |op1, shape, *other_args|
183
187
  block = other_args[0]
184
- helper = Java::RbMdarrayLoopsUnops::SetAll
188
+ helper = @helper::SetAll
185
189
  func = (shape.size <= 7)? "apply#{shape.size}" : "apply"
186
190
  helper.send(func, op1, &block) if block
187
191
  end
@@ -197,7 +201,7 @@ class FastUnaryOperator < UnaryOperator
197
201
  calc = nil
198
202
  get_args(*args) do |op1, shape, *other_args|
199
203
  calc = MDArray.build(@type, shape)
200
- helper = Java::RbMdarrayLoopsUnops::DefaultUnaryOperator
204
+ helper = @helper::DefaultUnaryOperator
201
205
  helper.send("apply", calc.nc_array, op1, @do_func)
202
206
  end
203
207
  return calc
@@ -211,7 +215,7 @@ class FastUnaryOperator < UnaryOperator
211
215
  def in_place(*args)
212
216
 
213
217
  get_args(*args) do |op1, shape, *other_args|
214
- helper = Java::RbMdarrayLoopsUnops::InplaceUnaryOperator
218
+ helper = @helper::InplaceUnaryOperator
215
219
  helper.send("apply", op1, @do_func)
216
220
  end
217
221
 
@@ -226,7 +230,7 @@ class FastUnaryOperator < UnaryOperator
226
230
  calc = nil
227
231
 
228
232
  get_args(*args) do |op1, shape, *other_args|
229
- helper = Java::RbMdarrayLoopsUnops::ReduceUnaryOperator
233
+ helper = @helper::ReduceUnaryOperator
230
234
  calc = @pre_condition_result
231
235
  calc = helper.send("apply", calc, op1, @do_func)
232
236
  end
@@ -29,16 +29,20 @@ module FunctionCreation
29
29
  #
30
30
  #------------------------------------------------------------------------------------
31
31
 
32
- def make_binary_op(name, exec_type, func, force_type = nil, pre_condition = nil,
33
- post_condition = nil)
32
+ def make_binary_op(name, exec_type, func, helper_class, force_type = nil,
33
+ pre_condition = nil, post_condition = nil)
34
34
 
35
35
  define_method(name) do |op2, requested_type = nil, *args|
36
- binary_op = get_binary_op
36
+ if (@type == "lazy" || ((op2.is_a? MDArray) && op2.type == "lazy"))
37
+ binary_op = LazyBinaryOperator
38
+ else
39
+ binary_op = get_binary_op
40
+ end
37
41
  op = binary_op.new(name, exec_type, force_type, pre_condition, post_condition)
38
42
  op.exec(self, op2, requested_type, *args)
39
43
  end
40
44
 
41
- MDArray.register_function(name, func)
45
+ MDArray.register_function(name, func, 2, helper_class)
42
46
 
43
47
  end
44
48
 
@@ -46,23 +50,8 @@ module FunctionCreation
46
50
  #
47
51
  #------------------------------------------------------------------------------------
48
52
 
49
- def make_binary_operators(name, func, default = true, in_place = true)
50
-
51
- if (default)
52
- make_binary_op(name, "default", func)
53
- end
54
- if (in_place)
55
- make_binary_op(name + "!", "in_place", func)
56
- end
57
-
58
- end
59
-
60
- #------------------------------------------------------------------------------------
61
- #
62
- #------------------------------------------------------------------------------------
63
-
64
- def make_unary_op(name, exec_type, func, force_type = nil, pre_condition = nil,
65
- post_condition = nil)
53
+ def make_unary_op(name, exec_type, func, helper_class, force_type = nil,
54
+ pre_condition = nil, post_condition = nil)
66
55
 
67
56
  define_method(name) do |requested_type = nil, *args|
68
57
  unary_op = get_unary_op
@@ -70,31 +59,8 @@ module FunctionCreation
70
59
  op.exec(self, requested_type, *args)
71
60
  end
72
61
 
73
- MDArray.register_function(name, func)
74
-
75
- end
76
-
77
- #------------------------------------------------------------------------------------
78
- #
79
- #------------------------------------------------------------------------------------
80
-
81
- def make_unary_operators(name, func, default = true, in_place = true)
82
-
83
- if (default)
84
- make_unary_op(name, "default", func)
85
- end
86
- if (in_place)
87
- make_unary_op(name + "!", "in_place", func)
88
- end
89
-
90
- end
91
-
92
- #------------------------------------------------------------------------------------
93
- #
94
- #------------------------------------------------------------------------------------
62
+ MDArray.register_function(name, func, 1, helper_class)
95
63
 
96
- def make_comparison_op(name, func)
97
- make_binary_op(name, "default", func, "boolean")
98
64
  end
99
65
 
100
66
  end # FunctionCreation
@@ -25,30 +25,38 @@
25
25
 
26
26
  class FunctionMap
27
27
 
28
- attr_reader :short_name
29
- attr_reader :long_name
30
- attr_reader :scope
31
- attr_reader :function
28
+ attr_reader :short_name # short name of the function
29
+ attr_reader :long_name # long name of the function
30
+ attr_reader :package # package where the function was implemented
31
+ attr_reader :function # function to be applied to elmts
32
32
  attr_reader :return_type
33
33
  attr_reader :input1_type
34
34
  attr_reader :input2_type
35
-
35
+ attr_reader :arity # arity of the function: 1 or 2
36
+ attr_reader :helper # Helper method to perform the function
37
+ attr_reader :is_global # set to true if function applies to all elmts of the
38
+ # array. By default set to false
39
+ attr_reader :elmtwise # works elementwise
36
40
  attr_accessor :description
37
41
 
38
42
  #------------------------------------------------------------------------------------
39
43
  #
40
44
  #------------------------------------------------------------------------------------
41
45
 
42
- def initialize(short_name, long_name, scope, function, return_type, input1_type,
43
- input2_type)
46
+ def initialize(short_name, long_name, package, function, return_type, input1_type,
47
+ input2_type, arity, helper, elmtwise = true, is_global = false)
44
48
 
45
49
  @short_name = short_name
46
50
  @long_name = long_name
47
- @scope = scope
51
+ @package = package
48
52
  @function = function
49
53
  @return_type = return_type
50
54
  @input1_type = input1_type
51
55
  @input2_type = input2_type
56
+ @arity = arity
57
+ @helper = helper
58
+ @elmtwise = elmtwise
59
+ @is_global = is_global
52
60
 
53
61
  end # initialize
54
62
 
@@ -0,0 +1,311 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ ##########################################################################################
4
+ # Copyright © 2013 Rodrigo Botafogo. All Rights Reserved. Permission to use, copy, modify,
5
+ # and distribute this software and its documentation for educational, research, and
6
+ # not-for-profit purposes, without fee and without a signed licensing agreement, is hereby
7
+ # granted, provided that the above copyright notice, this paragraph and the following two
8
+ # paragraphs appear in all copies, modifications, and distributions. Contact Rodrigo
9
+ # Botafogo - rodrigo.a.botafogo@gmail.com for commercial licensing opportunities.
10
+ #
11
+ # IN NO EVENT SHALL RODRIGO BOTAFOGO BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL,
12
+ # INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF
13
+ # THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF RODRIGO BOTAFOGO HAS BEEN ADVISED OF THE
14
+ # POSSIBILITY OF SUCH DAMAGE.
15
+ #
16
+ # RODRIGO BOTAFOGO SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
17
+ # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
18
+ # SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS".
19
+ # RODRIGO BOTAFOGO HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
20
+ # OR MODIFICATIONS.
21
+ ##########################################################################################
22
+
23
+
24
+ ##########################################################################################
25
+ #
26
+ ##########################################################################################
27
+
28
+ class LazyMDArray < ByteMDArray
29
+ include_package "ucar.ma2"
30
+ include_package "org.codehaus.janino"
31
+
32
+ attr_reader :stack
33
+
34
+ #=======================================================================================
35
+ # Class BinaryComp applies a function f to two arguments. The arguments can be
36
+ # functions on their own right
37
+ #=======================================================================================
38
+
39
+ class BinaryComp
40
+
41
+ def initialize(f, x, y, *args)
42
+ @x = x
43
+ @y = y
44
+ @f = f
45
+ @other_args = args
46
+ end
47
+
48
+ def apply
49
+ @f.apply(@x.apply, @y.apply)
50
+ end
51
+
52
+ end # BinaryComp
53
+
54
+ #=======================================================================================
55
+ # Class UnaryComp applies a function f to one arguments. The arguments can be a
56
+ # function on its own right
57
+ #=======================================================================================
58
+
59
+ class UnaryComp
60
+
61
+ def initialize(f, x, *args)
62
+ @x = x
63
+ @f = f
64
+ @other_args = args
65
+ end
66
+
67
+ def apply
68
+ @f.apply(@x.apply)
69
+ end
70
+
71
+ end # UnaryComp
72
+
73
+ #=======================================================================================
74
+ #
75
+ #=======================================================================================
76
+
77
+
78
+ #---------------------------------------------------------------------------------------
79
+ #
80
+ #---------------------------------------------------------------------------------------
81
+
82
+ def initialize
83
+
84
+ @stack = Array.new
85
+ @type = "lazy"
86
+ @previous_binary_operator = nil
87
+ @previous_unary_operator = nil
88
+
89
+ end
90
+
91
+ #---------------------------------------------------------------------------------------
92
+ #
93
+ #---------------------------------------------------------------------------------------
94
+
95
+ def push(elmt)
96
+ @stack << elmt
97
+ end
98
+
99
+ #---------------------------------------------------------------------------------------
100
+ #
101
+ #---------------------------------------------------------------------------------------
102
+
103
+ def pop
104
+ @stack.pop
105
+ end
106
+
107
+ #---------------------------------------------------------------------------------------
108
+ #
109
+ #---------------------------------------------------------------------------------------
110
+
111
+ def test_janino_function
112
+ $exp = ExpressionEvaluator.new
113
+ $exp.setExpressionType(Java::CernColtFunctionTdouble::DoubleFunction.java_class)
114
+ class_type = Java::JavaLang::Class.forName("java.lang.Class")
115
+ array = Java::JavaLangReflect::Array.newInstance(class_type, 2)
116
+ array[0] = Java::double.java_class
117
+ array[1] = Java::double.java_class
118
+ $exp.setParameters(["a", "b"].to_java(:string),
119
+ array)
120
+ $exp.cook("a + b")
121
+ end
122
+
123
+ #---------------------------------------------------------------------------------------
124
+ #
125
+ #---------------------------------------------------------------------------------------
126
+
127
+ def apply(*args)
128
+
129
+ type, shape, function = validate_fast(args)
130
+
131
+ result = MDArray.build(type, shape)
132
+ helper = Java::RbMdarrayLoopsLazy::DefaultLazyOperator
133
+ helper.send("apply", result.nc_array, function)
134
+ result
135
+
136
+ end
137
+
138
+ alias :[] :apply
139
+
140
+ #---------------------------------------------------------------------------------------
141
+ # Shows this LazyMDArray in Reverse Polish Notation. Mainly for debugging purposes.
142
+ #---------------------------------------------------------------------------------------
143
+
144
+ def rpn(nl = true)
145
+
146
+ exp = String.new
147
+
148
+ @stack.each do |elmt|
149
+
150
+ if (elmt.is_a? LazyMDArray)
151
+ exp << elmt.rpn(false)
152
+ elsif (elmt.is_a? Numeric)
153
+ exp << elmt << " "
154
+ elsif (elmt.is_a? Operator)
155
+ exp << elmt.name << " "
156
+ elsif (elmt.is_a? MDArray)
157
+ exp << elmt.type << " "
158
+ else
159
+ raise "Wrong element type in Array"
160
+ end
161
+
162
+ end
163
+
164
+ exp
165
+
166
+ end
167
+
168
+ #---------------------------------------------------------------------------------------
169
+ #
170
+ #---------------------------------------------------------------------------------------
171
+
172
+ def print
173
+ Kernel.print "[Lazy MDArray]\n"
174
+ p rpn
175
+ end
176
+
177
+ #---------------------------------------------------------------------------------------
178
+ # Validates the expression checking if it can be performed: all dimensions need to be
179
+ # compatible
180
+ #---------------------------------------------------------------------------------------
181
+
182
+ protected
183
+
184
+ def validate_fast(*args)
185
+
186
+ # test_janino_function
187
+ # p "validade_fast compile janino expression:"
188
+ # $exp.apply(100, 100)
189
+
190
+ helper_stack = Array.new
191
+
192
+ @stack.each do |elmt|
193
+
194
+ if (elmt.is_a? LazyMDArray)
195
+ helper_stack << elmt.validate_fast(*args)
196
+ elsif (elmt.is_a? MDArray)
197
+ # helper_stack << [elmt.type, elmt.shape, index_func(elmt)]
198
+ # iterator = elmt.nc_array.getIndexIterator
199
+ java_proc = Java::RbMdarrayUtil::Util.getIterator(elmt.nc_array)
200
+ helper_stack << [elmt.type, elmt.shape, java_proc]
201
+ elsif (elmt.is_a? Numeric)
202
+ # const_func is inefficient... fix!!!
203
+ helper_stack << ["numeric", 1, const_func(elmt)]
204
+ elsif (elmt.is_a? Operator)
205
+ case elmt.arity
206
+ when 1
207
+ top = helper_stack.pop
208
+ fmap = MDArray.select_function(elmt.name, MDArray.functions, top[0],
209
+ top[0], "void")
210
+ helper_stack <<
211
+ [top[0], top[1],
212
+ # UnaryComp.new(top[2], fmap.function, elmt.other_args)]
213
+ Java::RbMdarrayUtil::Util.compose(fmap.function, top[2])]
214
+ when 2
215
+ top1, top2 = helper_stack.pop(2)
216
+ if (top1[1] != top2[1] && top1[0] != "numeric" && top2[0] != "numeric")
217
+ raise "Expression involves incopatible arrays. #{top1[1]} != #{top2[1]}"
218
+ end
219
+ type = MDArray.upcast(top1[0], top2[0])
220
+ fmap = MDArray.select_function(elmt.name, MDArray.functions, type, type, type)
221
+ helper_stack <<
222
+ [type, top1[1],
223
+ Java::RbMdarrayUtil::Util.compose(fmap.function, top1[2], top2[2])]
224
+ end
225
+ else
226
+ raise "Expression is invalid: element #{elmt} is not valid in this position."
227
+ end
228
+
229
+ end
230
+
231
+ helper_stack[0]
232
+
233
+ end
234
+
235
+ #---------------------------------------------------------------------------------------
236
+ #
237
+ #---------------------------------------------------------------------------------------
238
+
239
+ private
240
+
241
+ #---------------------------------------------------------------------------------------
242
+ #
243
+ #---------------------------------------------------------------------------------------
244
+
245
+ def const_func(val)
246
+ Proc.new { |index| val }
247
+ end
248
+
249
+ #---------------------------------------------------------------------------------------
250
+ #
251
+ #---------------------------------------------------------------------------------------
252
+
253
+ def index_func(a)
254
+ Proc.new { |index| a.jget(index) }
255
+ end
256
+
257
+ #---------------------------------------------------------------------------------------
258
+ #
259
+ #---------------------------------------------------------------------------------------
260
+
261
+ def get_next_func(a)
262
+ Proc.new { a.getObjectNext() }
263
+ end
264
+
265
+ #---------------------------------------------------------------------------------------
266
+ #
267
+ #---------------------------------------------------------------------------------------
268
+
269
+ def binary_function_next(proc1, proc2, f, *args)
270
+ Proc.new { f.call(proc1.apply, proc2.apply, *args) }
271
+ end
272
+
273
+ end # LazyMDArray
274
+
275
+ ##########################################################################################
276
+ #
277
+ ##########################################################################################
278
+
279
+ class MDArray
280
+
281
+ #---------------------------------------------------------------------------------------
282
+ #
283
+ #---------------------------------------------------------------------------------------
284
+
285
+ def self.set_lazy(flag = true)
286
+
287
+ if (flag)
288
+ if (MDArray.binary_operator != LazyBinaryOperator)
289
+ MDArray.previous_binary_operator = MDArray.binary_operator
290
+ MDArray.previous_unary_operator = MDArray.unary_operator
291
+ end
292
+ MDArray.binary_operator = LazyBinaryOperator
293
+ MDArray.unary_operator = LazyUnaryOperator
294
+ else
295
+ MDArray.binary_operator = MDArray.previous_binary_operator if MDArray.previous_binary_operator != nil
296
+ MDArray.unary_operator = MDArray.previous_unary_operator if MDArray.previous_unary_operator != nil
297
+ end
298
+
299
+ end
300
+
301
+ #---------------------------------------------------------------------------------------
302
+ #
303
+ #---------------------------------------------------------------------------------------
304
+
305
+ def self.lazy=(flag)
306
+ set_lazy(flag)
307
+ end
308
+
309
+ end
310
+
311
+ require_relative 'lazy_operators'