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.
- data/README.md +61 -0
- data/Rakefile +1 -1
- data/lib/multiarray.rb +28 -0
- data/lib/multiarray/complex.rb +310 -13
- data/lib/multiarray/composite.rb +7 -0
- data/lib/multiarray/diagonal.rb +18 -3
- data/lib/multiarray/elementwise.rb +7 -2
- data/lib/multiarray/float.rb +43 -3
- data/lib/multiarray/gcccache.rb +4 -1
- data/lib/multiarray/gcccontext.rb +119 -21
- data/lib/multiarray/gccfunction.rb +92 -3
- data/lib/multiarray/gcctype.rb +26 -0
- data/lib/multiarray/gccvalue.rb +204 -2
- data/lib/multiarray/histogram.rb +65 -1
- data/lib/multiarray/index.rb +11 -0
- data/lib/multiarray/inject.rb +18 -1
- data/lib/multiarray/int.rb +49 -18
- data/lib/multiarray/integral.rb +65 -1
- data/lib/multiarray/lambda.rb +19 -5
- data/lib/multiarray/list.rb +8 -0
- data/lib/multiarray/lookup.rb +8 -1
- data/lib/multiarray/lut.rb +96 -2
- data/lib/multiarray/methods.rb +13 -3
- data/lib/multiarray/multiarray.rb +11 -0
- data/lib/multiarray/node.rb +52 -9
- data/lib/multiarray/operations.rb +118 -15
- data/lib/multiarray/pointer.rb +35 -1
- data/lib/multiarray/rgb.rb +139 -14
- data/lib/multiarray/sequence.rb +140 -2
- data/lib/multiarray/shortcuts.rb +76 -30
- data/lib/multiarray/store.rb +54 -0
- data/lib/multiarray/variable.rb +19 -0
- data/test/tc_lazy.rb +9 -0
- metadata +3 -3
data/lib/multiarray/gcctype.rb
CHANGED
@@ -17,12 +17,25 @@
|
|
17
17
|
# Namespace of Hornetseye computer vision library
|
18
18
|
module Hornetseye
|
19
19
|
|
20
|
+
# Class for translating native types from Ruby to C
|
21
|
+
#
|
22
|
+
# @private
|
20
23
|
class GCCType
|
21
24
|
|
25
|
+
# Construct GCC type
|
26
|
+
#
|
27
|
+
# @param [Class] typecode Native type (e.g. +UBYTE+).
|
28
|
+
#
|
29
|
+
# @private
|
22
30
|
def initialize( typecode )
|
23
31
|
@typecode = typecode
|
24
32
|
end
|
25
33
|
|
34
|
+
# Get C identifier for native type
|
35
|
+
#
|
36
|
+
# @return [String] String with valid C syntax to declare type.
|
37
|
+
#
|
38
|
+
# @private
|
26
39
|
def identifier
|
27
40
|
case @typecode
|
28
41
|
when nil
|
@@ -56,6 +69,11 @@ module Hornetseye
|
|
56
69
|
end
|
57
70
|
end
|
58
71
|
|
72
|
+
# Get array of C identifiers for native type
|
73
|
+
#
|
74
|
+
# @return [Array<String>] Array of C declarations for the elements of the type.
|
75
|
+
#
|
76
|
+
# @private
|
59
77
|
def identifiers
|
60
78
|
if @typecode < Composite
|
61
79
|
GCCType.new( @typecode.element_type ).identifiers * @typecode.num_elements
|
@@ -64,6 +82,14 @@ module Hornetseye
|
|
64
82
|
end
|
65
83
|
end
|
66
84
|
|
85
|
+
# Get code for converting Ruby VALUE to C value
|
86
|
+
#
|
87
|
+
# This method returns a nameless function. The nameless function is used for
|
88
|
+
# getting the code to convert a given parameter to a C value of this type.
|
89
|
+
#
|
90
|
+
# @return [Proc] Nameless function accepting a C expression to be converted.
|
91
|
+
#
|
92
|
+
# @private
|
67
93
|
def r2c
|
68
94
|
case @typecode
|
69
95
|
when BOOL
|
data/lib/multiarray/gccvalue.rb
CHANGED
@@ -16,12 +16,14 @@
|
|
16
16
|
|
17
17
|
# Namespace of Hornetseye computer vision library
|
18
18
|
module Hornetseye
|
19
|
-
|
19
|
+
|
20
|
+
# Class for generating code handling C values
|
21
|
+
# @private
|
20
22
|
class GCCValue
|
21
23
|
|
22
24
|
class << self
|
23
25
|
|
24
|
-
# Check compatibility of other type
|
26
|
+
# Check compatibility of other type
|
25
27
|
#
|
26
28
|
# This method checks whether binary operations with the other Ruby object can
|
27
29
|
# be performed without requiring coercion.
|
@@ -29,17 +31,35 @@ module Hornetseye
|
|
29
31
|
# @param [Object] value The other Ruby object.
|
30
32
|
#
|
31
33
|
# @return [Boolean] Returns +false+ if Ruby object requires coercion.
|
34
|
+
#
|
35
|
+
# @private
|
32
36
|
def generic?( value )
|
33
37
|
value.is_a?( GCCValue ) or value.is_a?( Fixnum ) or
|
34
38
|
value.is_a?( Float )
|
35
39
|
end
|
36
40
|
|
41
|
+
# Meta-programming method used to define unary operations at the beginning
|
42
|
+
#
|
43
|
+
# @param [Symbol,String] op Name of unary operation.
|
44
|
+
# @param [Symbol,String] opcode Name of unary operation in C.
|
45
|
+
#
|
46
|
+
# @return [Proc] The new method.
|
47
|
+
#
|
48
|
+
# @private
|
37
49
|
def define_unary_op( op, opcode = op )
|
38
50
|
define_method( op ) do
|
39
51
|
GCCValue.new @function, "#{opcode}( #{self} )"
|
40
52
|
end
|
41
53
|
end
|
42
54
|
|
55
|
+
# Meta-programming method used to define unary methods at the beginning
|
56
|
+
#
|
57
|
+
# @param [Symbol,String] op Name of unary method.
|
58
|
+
# @param [Symbol,String] opcode Name of unary method in C.
|
59
|
+
#
|
60
|
+
# @return [Proc] The new method.
|
61
|
+
#
|
62
|
+
# @private
|
43
63
|
def define_unary_method( mod, op, opcode = op )
|
44
64
|
mod.module_eval do
|
45
65
|
define_method( "#{op}_with_gcc" ) do |a|
|
@@ -55,6 +75,14 @@ module Hornetseye
|
|
55
75
|
end
|
56
76
|
end
|
57
77
|
|
78
|
+
# Meta-programming method used to define unary methods at the beginning
|
79
|
+
#
|
80
|
+
# @param [Symbol,String] op Name of unary method.
|
81
|
+
# @param [Symbol,String] opcode Name of unary method in C.
|
82
|
+
#
|
83
|
+
# @return [Proc] The new method.
|
84
|
+
#
|
85
|
+
# @private
|
58
86
|
def define_binary_op( op, opcode = op )
|
59
87
|
define_method( op ) do |other|
|
60
88
|
if GCCValue.generic? other
|
@@ -66,6 +94,14 @@ module Hornetseye
|
|
66
94
|
end
|
67
95
|
end
|
68
96
|
|
97
|
+
# Meta-programming method used to define binary methods at the beginning
|
98
|
+
#
|
99
|
+
# @param [Symbol,String] op Name of binary method.
|
100
|
+
# @param [Symbol,String] opcode Name of binary method in C.
|
101
|
+
#
|
102
|
+
# @return [Proc] The new method.
|
103
|
+
#
|
104
|
+
# @private
|
69
105
|
def define_binary_method( mod, op, opcode = op )
|
70
106
|
mod.module_eval do
|
71
107
|
define_method( "#{op}_with_gcc" ) do |a,b|
|
@@ -84,8 +120,19 @@ module Hornetseye
|
|
84
120
|
|
85
121
|
end
|
86
122
|
|
123
|
+
# Get current function context
|
124
|
+
#
|
125
|
+
# @return [GCCFunction] The function this value is part of.
|
126
|
+
#
|
127
|
+
# @private
|
87
128
|
attr_reader :function
|
88
129
|
|
130
|
+
# Constructor for GCC value
|
131
|
+
#
|
132
|
+
# @param [GCCFunction] function The function context this value is part of.
|
133
|
+
# @param [String] descriptor C code to compute this value.
|
134
|
+
#
|
135
|
+
# @private
|
89
136
|
def initialize( function, descriptor )
|
90
137
|
@function = function
|
91
138
|
@descriptor = descriptor
|
@@ -94,6 +141,8 @@ module Hornetseye
|
|
94
141
|
# Display descriptor of this object
|
95
142
|
#
|
96
143
|
# @return [String] Returns the descriptor of this object.
|
144
|
+
#
|
145
|
+
# @private
|
97
146
|
def inspect
|
98
147
|
@descriptor
|
99
148
|
end
|
@@ -101,6 +150,8 @@ module Hornetseye
|
|
101
150
|
# Get descriptor of this object
|
102
151
|
#
|
103
152
|
# @return [String] Returns the descriptor of this object.
|
153
|
+
#
|
154
|
+
# @private
|
104
155
|
def to_s
|
105
156
|
@descriptor
|
106
157
|
end
|
@@ -110,15 +161,27 @@ module Hornetseye
|
|
110
161
|
# @param [Object] value The new value.
|
111
162
|
#
|
112
163
|
# @return [Object] Returns +value+.
|
164
|
+
#
|
165
|
+
# @private
|
113
166
|
def store( value )
|
114
167
|
@function << "#{@function.indent}#{self} = #{value};\n"
|
115
168
|
value
|
116
169
|
end
|
117
170
|
|
171
|
+
# Indicate whether this object can be compiled
|
172
|
+
#
|
173
|
+
# @return [Boolean] Returns +false+.
|
174
|
+
#
|
175
|
+
# @private
|
118
176
|
def compilable?
|
119
177
|
false
|
120
178
|
end
|
121
179
|
|
180
|
+
# Add code to read all components of a typed value from memory
|
181
|
+
#
|
182
|
+
# @return [Array<GCCValue>] An array of objects referencing values in C.
|
183
|
+
#
|
184
|
+
# @private
|
122
185
|
def load( typecode )
|
123
186
|
offset = 0
|
124
187
|
typecode.typecodes.collect do |t|
|
@@ -129,6 +192,13 @@ module Hornetseye
|
|
129
192
|
end
|
130
193
|
end
|
131
194
|
|
195
|
+
# Add code to write all components of a typed value to memory
|
196
|
+
#
|
197
|
+
# @param [Node] value Value to write to memory.
|
198
|
+
#
|
199
|
+
# @return [Object] The return value should be ignored.
|
200
|
+
#
|
201
|
+
# @private
|
132
202
|
def save( value )
|
133
203
|
offset = 0
|
134
204
|
value.class.typecodes.zip( value.values ).each do |t,v|
|
@@ -137,42 +207,98 @@ module Hornetseye
|
|
137
207
|
end
|
138
208
|
end
|
139
209
|
|
210
|
+
# Complex conjugate of real value
|
211
|
+
#
|
212
|
+
# @return [GCCValue] Returns +self+.
|
213
|
+
#
|
214
|
+
# @private
|
140
215
|
def conj
|
141
216
|
self
|
142
217
|
end
|
143
218
|
|
219
|
+
# Generate code for computing absolute value
|
220
|
+
#
|
221
|
+
# @return [GCCValue] C value referring to the result.
|
222
|
+
#
|
223
|
+
# @private
|
144
224
|
def abs
|
145
225
|
( self >= 0 ).conditional self, -self
|
146
226
|
end
|
147
227
|
|
228
|
+
# Generate code for computing complex argument of real value
|
229
|
+
#
|
230
|
+
# @return [GCCValue] C value referring to the result.
|
231
|
+
#
|
232
|
+
# @private
|
148
233
|
def arg
|
149
234
|
( self >= 0 ).conditional 0, Math::PI
|
150
235
|
end
|
151
236
|
|
237
|
+
# Red colour component of real value
|
238
|
+
#
|
239
|
+
# @return [GCCValue] Returns +self+.
|
240
|
+
#
|
241
|
+
# @private
|
152
242
|
def r
|
153
243
|
self
|
154
244
|
end
|
155
245
|
|
246
|
+
# Green colour component of real value
|
247
|
+
#
|
248
|
+
# @return [GCCValue] Returns +self+.
|
249
|
+
#
|
250
|
+
# @private
|
156
251
|
def g
|
157
252
|
self
|
158
253
|
end
|
159
254
|
|
255
|
+
# Blue colour component of real value
|
256
|
+
#
|
257
|
+
# @return [GCCValue] Returns +self+.
|
258
|
+
#
|
259
|
+
# @private
|
160
260
|
def b
|
161
261
|
self
|
162
262
|
end
|
163
263
|
|
264
|
+
# Real component of real value
|
265
|
+
#
|
266
|
+
# @return [GCCValue] Returns +self+.
|
267
|
+
#
|
268
|
+
# @private
|
164
269
|
def real
|
165
270
|
self
|
166
271
|
end
|
167
272
|
|
273
|
+
# Imaginary component of real value
|
274
|
+
#
|
275
|
+
# @return [Integer] Returns +0+.
|
276
|
+
#
|
277
|
+
# @private
|
168
278
|
def imag
|
169
279
|
0
|
170
280
|
end
|
171
281
|
|
282
|
+
# Create code for conditional selection of value
|
283
|
+
#
|
284
|
+
# @param [GCCValue,Object] a First value.
|
285
|
+
# @param [GCCValue,Object] b Second value.
|
286
|
+
#
|
287
|
+
# @return [GCCValue] C value referring to result.
|
288
|
+
#
|
289
|
+
# @private
|
172
290
|
def conditional( a, b )
|
173
291
|
GCCValue.new @function, "( #{self} ) ? ( #{a} ) : ( #{b} )"
|
174
292
|
end
|
175
293
|
|
294
|
+
# Create code for conditional selection of RGB value
|
295
|
+
#
|
296
|
+
# @param [GCCValue,Object] a First value.
|
297
|
+
# @param [GCCValue,Object] b Second value.
|
298
|
+
#
|
299
|
+
# @return [GCCValue] C value referring to result.
|
300
|
+
#
|
301
|
+
# @private
|
176
302
|
def conditional_with_rgb( a, b )
|
177
303
|
if a.is_a?( RGB ) or b.is_a?( RGB )
|
178
304
|
Hornetseye::RGB( conditional( a.r, b.r ), conditional( a.g, b.g ),
|
@@ -184,6 +310,14 @@ module Hornetseye
|
|
184
310
|
|
185
311
|
alias_method_chain :conditional, :rgb
|
186
312
|
|
313
|
+
# Create code for conditional selection of complex value
|
314
|
+
#
|
315
|
+
# @param [GCCValue,Object] a First value.
|
316
|
+
# @param [GCCValue,Object] b Second value.
|
317
|
+
#
|
318
|
+
# @return [GCCValue] C value referring to result.
|
319
|
+
#
|
320
|
+
# @private
|
187
321
|
def conditional_with_complex( a, b )
|
188
322
|
if a.is_a?( InternalComplex ) or b.is_a?( InternalComplex )
|
189
323
|
InternalComplex.new conditional( a.real, b.real ),
|
@@ -235,26 +369,58 @@ module Hornetseye
|
|
235
369
|
define_binary_method Math, :atan2
|
236
370
|
define_binary_method Math, :hypot
|
237
371
|
|
372
|
+
# Generate code for checking whether value is equal to zero
|
373
|
+
#
|
374
|
+
# @return [GCCValue] C value refering to the result.
|
375
|
+
#
|
376
|
+
# @private
|
238
377
|
def zero?
|
239
378
|
GCCValue.new @function, "( #{self} ) == 0"
|
240
379
|
end
|
241
380
|
|
381
|
+
# Generate code for checking whether value is not equal to zero
|
382
|
+
#
|
383
|
+
# @return [GCCValue] C value refering to the result.
|
384
|
+
#
|
385
|
+
# @private
|
242
386
|
def nonzero?
|
243
387
|
GCCValue.new @function, "( #{self} ) != 0"
|
244
388
|
end
|
245
389
|
|
390
|
+
# Generate code for computing largest integer value not greater than this value
|
391
|
+
#
|
392
|
+
# @return [GCCValue] C value refering to the result.
|
393
|
+
#
|
394
|
+
# @private
|
246
395
|
def floor
|
247
396
|
GCCValue.new @function, "floor( #{self} )"
|
248
397
|
end
|
249
398
|
|
399
|
+
# Generate code for computing smallest integer value not less than this value
|
400
|
+
#
|
401
|
+
# @return [GCCValue] C value refering to the result.
|
402
|
+
#
|
403
|
+
# @private
|
250
404
|
def ceil
|
251
405
|
GCCValue.new @function, "ceil( #{self} )"
|
252
406
|
end
|
253
407
|
|
408
|
+
# Generate code for rounding to nearest integer
|
409
|
+
#
|
410
|
+
# @return [GCCValue] C value refering to the result.
|
411
|
+
#
|
412
|
+
# @private
|
254
413
|
def round
|
255
414
|
GCCValue.new @function, "round( #{self} )"
|
256
415
|
end
|
257
416
|
|
417
|
+
# Generate code for computing exponentiation
|
418
|
+
#
|
419
|
+
# @param [Object,GCCValue] other Second operand for binary operation.
|
420
|
+
#
|
421
|
+
# @return [GCCValue] C value refering to the result.
|
422
|
+
#
|
423
|
+
# @private
|
258
424
|
def **( other )
|
259
425
|
if GCCValue.generic? other
|
260
426
|
GCCValue.new @function, "pow( #{self}, #{other} )"
|
@@ -264,16 +430,37 @@ module Hornetseye
|
|
264
430
|
end
|
265
431
|
end
|
266
432
|
|
433
|
+
# Generate code for selecting larger value
|
434
|
+
#
|
435
|
+
# @param [Object,GCCValue] other Second operand for binary operation.
|
436
|
+
#
|
437
|
+
# @return [GCCValue] C value refering to the result.
|
438
|
+
#
|
439
|
+
# @private
|
267
440
|
def major( other )
|
268
441
|
GCCValue.new @function,
|
269
442
|
"( ( #{self} ) >= ( #{other} ) ) ? ( #{self} ) : ( #{other} )"
|
270
443
|
end
|
271
444
|
|
445
|
+
# Generate code for selecting smaller value
|
446
|
+
#
|
447
|
+
# @param [Object,GCCValue] other Second operand for binary operation.
|
448
|
+
#
|
449
|
+
# @return [GCCValue] C value refering to the result.
|
450
|
+
#
|
451
|
+
# @private
|
272
452
|
def minor( other )
|
273
453
|
GCCValue.new @function,
|
274
454
|
"( ( #{self} ) <= ( #{other} ) ) ? ( #{self} ) : ( #{other} )"
|
275
455
|
end
|
276
456
|
|
457
|
+
# Generate a +for+ loop in C
|
458
|
+
#
|
459
|
+
# @param [Proc] action Code for generating loop body.
|
460
|
+
#
|
461
|
+
# @return [GCCValue] Returns +self+.
|
462
|
+
#
|
463
|
+
# @private
|
277
464
|
def times( &action )
|
278
465
|
i = @function.variable INT, 'i'
|
279
466
|
@function << "#{@function.indent}for ( #{i} = 0; " +
|
@@ -285,6 +472,14 @@ module Hornetseye
|
|
285
472
|
self
|
286
473
|
end
|
287
474
|
|
475
|
+
# Generate a +for+ loop in C
|
476
|
+
#
|
477
|
+
# @param [GCCValue,Object] other Upper limit for loop.
|
478
|
+
# @param [Proc] action Code for generating loop body.
|
479
|
+
#
|
480
|
+
# @return [GCCValue] Returns +self+.
|
481
|
+
#
|
482
|
+
# @private
|
288
483
|
def upto( other, &action )
|
289
484
|
i = @function.variable INT, 'i'
|
290
485
|
@function << "#{@function.indent}for ( #{i} = #{self}; " +
|
@@ -296,6 +491,13 @@ module Hornetseye
|
|
296
491
|
self
|
297
492
|
end
|
298
493
|
|
494
|
+
# Type coercion for GCC values
|
495
|
+
#
|
496
|
+
# @param [Object] other Other value to coerce with.
|
497
|
+
#
|
498
|
+
# @return [Array<GCCValue>] Result of coercion.
|
499
|
+
#
|
500
|
+
# @private
|
299
501
|
def coerce( other )
|
300
502
|
if other.is_a? GCCValue
|
301
503
|
return other, self
|
data/lib/multiarray/histogram.rb
CHANGED
@@ -14,30 +14,66 @@
|
|
14
14
|
# You should have received a copy of the GNU General Public License
|
15
15
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
16
16
|
|
17
|
+
# Namespace of Hornetseye computer vision library
|
17
18
|
module Hornetseye
|
18
19
|
|
20
|
+
# Class for representing histogram computations
|
19
21
|
class Histogram < Node
|
20
22
|
|
21
23
|
class << self
|
22
24
|
|
25
|
+
# Check whether objects of this class are finalised computations
|
26
|
+
#
|
27
|
+
# @return [Boolean] Returns +false+.
|
28
|
+
#
|
29
|
+
# @private
|
23
30
|
def finalised?
|
24
31
|
false
|
25
32
|
end
|
26
33
|
|
27
34
|
end
|
28
35
|
|
36
|
+
# Constructor
|
37
|
+
#
|
38
|
+
# @param [Node] dest Target array to write histogram to.
|
39
|
+
# @param [Node] source Expression to compute histogram of.
|
40
|
+
#
|
41
|
+
# @private
|
29
42
|
def initialize( dest, source )
|
30
43
|
@dest, @source = dest, source
|
31
44
|
end
|
32
45
|
|
46
|
+
# Get unique descriptor of this object
|
47
|
+
#
|
48
|
+
# @param [Hash] hash Labels for any variables.
|
49
|
+
#
|
50
|
+
# @return [String] Descriptor of this object,
|
51
|
+
#
|
52
|
+
# @private
|
33
53
|
def descriptor( hash )
|
34
54
|
"Histogram(#{@dest.descriptor( hash )},#{@source.descriptor( hash )})"
|
35
55
|
end
|
36
56
|
|
57
|
+
# Get type of result of delayed operation
|
58
|
+
#
|
59
|
+
# @return [Class] Type of result.
|
60
|
+
#
|
61
|
+
# @private
|
37
62
|
def array_type
|
38
|
-
@dest.array_type
|
63
|
+
retval = @dest.array_type
|
64
|
+
( class << self; self; end ).instance_eval do
|
65
|
+
define_method( :array_type ) { retval }
|
66
|
+
end
|
67
|
+
retval
|
39
68
|
end
|
40
69
|
|
70
|
+
# Reevaluate computation
|
71
|
+
#
|
72
|
+
# @return [Node,Object] Result of computation
|
73
|
+
#
|
74
|
+
# @see #force
|
75
|
+
#
|
76
|
+
# @private
|
41
77
|
def demand
|
42
78
|
if variables.empty?
|
43
79
|
if @source.dimension > 1
|
@@ -58,20 +94,48 @@ module Hornetseye
|
|
58
94
|
end
|
59
95
|
end
|
60
96
|
|
97
|
+
# Substitute variables
|
98
|
+
#
|
99
|
+
# Substitute the variables with the values given in the hash.
|
100
|
+
#
|
101
|
+
# @param [Hash] hash Substitutions to apply.
|
102
|
+
#
|
103
|
+
# @return [Node] Term with substitutions applied.
|
104
|
+
#
|
105
|
+
# @private
|
61
106
|
def subst( hash )
|
62
107
|
self.class.new @dest.subst( hash ), @source.subst( hash )
|
63
108
|
end
|
64
109
|
|
110
|
+
# Get variables contained in this term
|
111
|
+
#
|
112
|
+
# @return [Set] Returns list of variables.
|
113
|
+
#
|
114
|
+
# @private
|
65
115
|
def variables
|
66
116
|
@dest.variables + @source.variables
|
67
117
|
end
|
68
118
|
|
119
|
+
# Strip of all values
|
120
|
+
#
|
121
|
+
# Split up into variables, values, and a term where all values have been
|
122
|
+
# replaced with variables.
|
123
|
+
#
|
124
|
+
# @return [Array<Array,Node>] Returns an array of variables, an array of
|
125
|
+
# values, and the term based on variables.
|
126
|
+
#
|
127
|
+
# @private
|
69
128
|
def strip
|
70
129
|
vars1, values1, term1 = @dest.strip
|
71
130
|
vars2, values2, term2 = @source.strip
|
72
131
|
return vars1 + vars2, values1 + values2, self.class.new( term1, term2 )
|
73
132
|
end
|
74
133
|
|
134
|
+
# Check whether this term is compilable
|
135
|
+
#
|
136
|
+
# @return [Boolean] Returns whether this term is compilable.
|
137
|
+
#
|
138
|
+
# @private
|
75
139
|
def compilable?
|
76
140
|
@dest.compilable? and @source.compilable?
|
77
141
|
end
|