multiarray 0.5.0 → 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +39 -5
- data/TODO +11 -66
- data/lib/multiarray.rb +59 -12
- data/lib/multiarray/binarymethod.rb +195 -0
- data/lib/multiarray/{binary.rb → binaryop.rb} +27 -12
- data/lib/multiarray/bool.rb +8 -2
- data/lib/multiarray/diagonal.rb +26 -27
- data/lib/multiarray/element.rb +23 -5
- data/lib/multiarray/float.rb +142 -0
- data/lib/multiarray/gcccontext.rb +29 -25
- data/lib/multiarray/gccfunction.rb +24 -7
- data/lib/multiarray/gcctype.rb +26 -16
- data/lib/multiarray/gccvalue.rb +144 -74
- data/lib/multiarray/inject.rb +12 -15
- data/lib/multiarray/int.rb +109 -82
- data/lib/multiarray/lambda.rb +23 -1
- data/lib/multiarray/lookup.rb +14 -1
- data/lib/multiarray/malloc.rb +2 -2
- data/lib/multiarray/methods.rb +93 -0
- data/lib/multiarray/multiarray.rb +2 -12
- data/lib/multiarray/node.rb +103 -173
- data/lib/multiarray/object.rb +19 -1
- data/lib/multiarray/operations.rb +189 -9
- data/lib/multiarray/pointer.rb +9 -1
- data/lib/multiarray/rgb.rb +401 -0
- data/lib/multiarray/sequence.rb +56 -14
- data/lib/multiarray/unarymethod.rb +185 -0
- data/lib/multiarray/{unary.rb → unaryop.rb} +20 -11
- data/lib/multiarray/variable.rb +8 -0
- data/test/tc_bool.rb +32 -20
- data/test/tc_float.rb +192 -0
- data/test/tc_int.rb +52 -24
- data/test/tc_lazy.rb +109 -0
- data/test/tc_multiarray.rb +136 -2
- data/test/tc_object.rb +29 -11
- data/test/tc_rgb.rb +217 -0
- data/test/tc_sequence.rb +184 -52
- data/test/ts_multiarray.rb +3 -0
- metadata +42 -15
data/Rakefile
CHANGED
@@ -6,12 +6,14 @@ require 'rake/packagetask'
|
|
6
6
|
require 'rbconfig'
|
7
7
|
|
8
8
|
PKG_NAME = 'multiarray'
|
9
|
-
PKG_VERSION = '0.5.
|
9
|
+
PKG_VERSION = '0.5.1'
|
10
10
|
RB_FILES = FileList[ 'lib/**/*.rb' ]
|
11
11
|
TC_FILES = FileList[ 'test/tc_*.rb' ]
|
12
12
|
TS_FILES = FileList[ 'test/ts_*.rb' ]
|
13
13
|
PKG_FILES = [ 'Rakefile', 'README.md', 'COPYING', 'TODO', '.document' ] +
|
14
14
|
RB_FILES + TS_FILES + TC_FILES
|
15
|
+
BIN_FILES = [ 'README.md', 'COPYING', '.document' ] +
|
16
|
+
RB_FILES + TS_FILES + TC_FILES
|
15
17
|
SUMMARY = %q{Multi-dimensional and uniform Ruby arrays}
|
16
18
|
DESCRIPTION = %q{This Ruby-extension defines Hornetseye::MultiArray and other native datatypes. Hornetseye::MultiArray provides multi-dimensional Ruby arrays with elements of same type. The extension is designed to be mostly compatible with Masahiro Tanaka's NArray. However it allows the definition of custom element types and operations on them. This work was also inspired by Ronald Garcia's boost::multi_array and by Todd Veldhuizen's Blitz++.}
|
17
19
|
AUTHOR = %q{Jan Wedekind}
|
@@ -88,16 +90,48 @@ begin
|
|
88
90
|
s.add_development_dependency %q{rake}
|
89
91
|
end
|
90
92
|
GEM_SOURCE = "#{PKG_NAME}-#{PKG_VERSION}.gem"
|
93
|
+
$BINSPEC = Gem::Specification.new do |s|
|
94
|
+
s.name = PKG_NAME
|
95
|
+
s.version = PKG_VERSION
|
96
|
+
s.platform = Gem::Platform::CURRENT
|
97
|
+
s.date = Date.today.to_s
|
98
|
+
s.summary = SUMMARY
|
99
|
+
s.description = DESCRIPTION
|
100
|
+
s.author = AUTHOR
|
101
|
+
s.email = EMAIL
|
102
|
+
s.homepage = HOMEPAGE
|
103
|
+
s.files = BIN_FILES
|
104
|
+
s.test_files = TC_FILES
|
105
|
+
s.require_paths = [ 'lib' ]
|
106
|
+
s.rubyforge_project = %q{hornetseye}
|
107
|
+
s.has_rdoc = 'yard'
|
108
|
+
s.extra_rdoc_files = []
|
109
|
+
s.rdoc_options = %w{--no-private}
|
110
|
+
s.add_dependency %q<malloc>, [ '~> 1.0' ]
|
111
|
+
end
|
112
|
+
GEM_BINARY = "#{PKG_NAME}-#{PKG_VERSION}-#{$BINSPEC.platform}.gem"
|
91
113
|
desc "Build the gem file #{GEM_SOURCE}"
|
92
114
|
task :gem => [ "pkg/#{GEM_SOURCE}" ]
|
93
115
|
file "pkg/#{GEM_SOURCE}" => [ 'pkg' ] + $SPEC.files do
|
94
|
-
|
95
|
-
|
96
|
-
|
116
|
+
when_writing 'Creating GEM' do
|
117
|
+
Gem::Builder.new( $SPEC ).build
|
118
|
+
verbose true do
|
119
|
+
FileUtils.mv GEM_SOURCE, "pkg/#{GEM_SOURCE}"
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
desc "Build the gem file #{GEM_BINARY}"
|
124
|
+
task :gem_binary => [ "pkg/#{GEM_BINARY}" ]
|
125
|
+
file "pkg/#{GEM_BINARY}" => [ 'pkg' ] + $BINSPEC.files do
|
126
|
+
when_writing 'Creating binary GEM' do
|
127
|
+
Gem::Builder.new( $BINSPEC ).build
|
128
|
+
verbose true do
|
129
|
+
FileUtils.mv GEM_BINARY, "pkg/#{GEM_BINARY}"
|
130
|
+
end
|
97
131
|
end
|
98
132
|
end
|
99
133
|
rescue LoadError
|
100
134
|
STDERR.puts 'Please install \'rubygems\' if you want to create Gem packages'
|
101
135
|
end
|
102
136
|
|
103
|
-
CLOBBER.include 'doc'
|
137
|
+
CLOBBER.include 'doc', '.yardoc'
|
data/TODO
CHANGED
@@ -1,25 +1,22 @@
|
|
1
|
-
#
|
2
|
-
#
|
3
|
-
#
|
4
|
-
#
|
5
|
-
#
|
6
|
-
# pointer-increments for better efficiency
|
7
|
-
#
|
8
|
-
#
|
9
|
-
# preload cache
|
10
|
-
# Sequence( UBYTE, 3 )[ ... ]
|
1
|
+
# type alignment for operators and methods, Math.sqrt( SFLOAT )
|
2
|
+
# test floor, ceil, ..., factor out common stuff of UnaryOp and UnaryMethod
|
3
|
+
# complex numbers, factor out composite numbers
|
4
|
+
# Fast filling of arrays, duplication, type conversions
|
5
|
+
# use descriptors ('c','f',...)?
|
6
|
+
# pointer-increments for better efficiency, optimize Node#diagonal
|
7
|
+
# implement typecasts, how does contiguous work here?
|
8
|
+
# documentation!
|
11
9
|
|
12
10
|
# histogram (implement using injection)
|
13
|
-
# inject:
|
11
|
+
# inject: n-d clips for warp
|
14
12
|
# block(var1,var2,...) with smart subst?
|
15
|
-
# lazy( 5 ) { |i| 0 } # but lazy { 0 }
|
16
|
-
# lazy( 3, 2 ) { |i,j| i }
|
17
13
|
# lazy( 3, 2 ) { |i,j| j.to_object }
|
18
14
|
|
19
15
|
# RSpec
|
20
16
|
|
21
17
|
# downsampling after correlation?
|
22
|
-
#
|
18
|
+
# YARD documentation with pictures, demo video
|
19
|
+
# CK_Thesis.pdf: tensor voting
|
23
20
|
|
24
21
|
# f(g(i)) # g(i), f(g(i)) all can be vectors and all can be lazy
|
25
22
|
# lut(g(i))
|
@@ -44,9 +41,6 @@
|
|
44
41
|
# binary operations, equality: ( a == b ).inject( true ) { |e,b| e && b }
|
45
42
|
# inject: min, max, equal, n-d clips for warp
|
46
43
|
# block(var1,var2,...) with smart subst?
|
47
|
-
# lazy( 5 ) { |i| 0 }
|
48
|
-
# lazy( 3, 2 ) { |i,j| i }
|
49
|
-
# lazy( 3, 2 ) { |i,j| j }
|
50
44
|
|
51
45
|
# downsampling after correlation?
|
52
46
|
# ruby -Ilib -rrubygems -rmultiarray -rtest test/tc_sequence.rb
|
@@ -61,45 +55,12 @@
|
|
61
55
|
# end
|
62
56
|
#end
|
63
57
|
|
64
|
-
|
65
|
-
lazy { a * b } -> lazy { |i,j| lazy { |i,j| a[i,j] * b[i,j] }[i,j] } # ?
|
66
|
-
lazy { s } -> s
|
67
|
-
lazy { -s } -> lazy { |i| -s[i] }
|
68
|
-
lazy { |i,j| s[i,j] }
|
69
|
-
lazy { |i| lazy { |j| s[i,j] } }
|
70
|
-
lazy( n ) { |i| i }
|
71
|
-
lazy( n, m ) { |i,j| i + j }
|
72
|
-
lazy( n ) { |i| lazy( m ) { |j| i + j } }
|
73
|
-
eager( n ) { |i| i }
|
74
|
-
...
|
75
|
-
|
76
|
-
tensor indices to enable transpose of lazy array
|
77
58
|
ranges (rolling, lazy rolling, lazy ranges)
|
78
|
-
test lazyness
|
79
|
-
sums/injections (equality for arrays)? nesting? tensors?
|
80
|
-
JIT?
|
81
59
|
test type conversions
|
82
|
-
fancy README
|
83
60
|
|
84
|
-
a = lazy( 16 ) { |i| i }
|
85
|
-
a = lazy( 16 ) { |i| i }[ 4 ... 12 ] # offsets: apply sel-operation to all
|
86
|
-
members; index array?
|
87
61
|
a = lazy( 16, 32 ) { |i,j| Sequence[ i, j ] } # ???
|
88
62
|
a = lazy( 8, 8 ) { |i,j| Sequence[ i, a[j] * sin( i + b[j] ) ] }.hist 8, 8
|
89
|
-
a = b.class.new.op { |x| set -x }
|
90
|
-
a = lazy { |i| -b[i] }
|
91
|
-
a = lazy { -b }
|
92
|
-
a = array { -b }
|
93
|
-
a = array { |i| -b[i] }
|
94
|
-
a = array( :dim => [ b.size ] ) { |i| -b[i] }
|
95
|
-
a = -b
|
96
|
-
array { |i| sum { |j| a[i,j] } }
|
97
|
-
lazy { |i| sum { |j| a[i,j] } }
|
98
63
|
parallel { ... }
|
99
|
-
lazy { |i| lazy { |j| a[i,j] } }
|
100
|
-
array { lazy { |i| sum { |j| a[i,j] } } }
|
101
|
-
|
102
|
-
correlate?
|
103
64
|
|
104
65
|
lines:
|
105
66
|
[ i, a[j] * sin( i + b[j] ) ].hist
|
@@ -122,19 +83,3 @@ Lazy( Sequence( INT, 3 ) )
|
|
122
83
|
|
123
84
|
interpretation: type coercion, actual operation, jit,
|
124
85
|
collection of jit arguments (e.g. tensor)
|
125
|
-
|
126
|
-
proc { |i| proc { |j| i+j } }.call( 5 ).call 3
|
127
|
-
|
128
|
-
gem install flay: http://ruby.sadi.st/Flay.html
|
129
|
-
|
130
|
-
# donate to yardoc
|
131
|
-
|
132
|
-
How to nest/cascade mode-environments?
|
133
|
-
(how to specify nested modes for recursive algorithms and called algorithms?)
|
134
|
-
ruby and jit compiles, lazy and parallel forwards
|
135
|
-
|
136
|
-
* Ruby
|
137
|
-
* Lazy (Lazy histogram -> hough transform, lazy transpose, unused indices?)
|
138
|
-
* Multithreading
|
139
|
-
* JIT
|
140
|
-
* GCC
|
data/lib/multiarray.rb
CHANGED
@@ -375,36 +375,36 @@ end
|
|
375
375
|
# +Range+ is extended with a few methods
|
376
376
|
class Range
|
377
377
|
|
378
|
-
alias_method :orig_min, :min
|
379
|
-
|
380
|
-
alias_method :orig_max, :max
|
381
|
-
|
382
378
|
# For performance reasons a specialised method for integers is added
|
383
379
|
#
|
384
380
|
# @return [Object] Minimum value of range.
|
385
381
|
#
|
386
382
|
# @private
|
387
|
-
def
|
383
|
+
def min_with_hornetseye
|
388
384
|
if self.begin.is_a? Integer
|
389
385
|
self.begin
|
390
386
|
else
|
391
|
-
|
387
|
+
min_without_hornetseye
|
392
388
|
end
|
393
389
|
end
|
394
390
|
|
391
|
+
alias_method_chain :min, :hornetseye
|
392
|
+
|
395
393
|
# For performance reasons a specialised method for integers is added
|
396
394
|
#
|
397
395
|
# @return [Object] Maximum value of range.
|
398
396
|
#
|
399
397
|
# @private
|
400
|
-
def
|
398
|
+
def max_with_hornetseye
|
401
399
|
if self.end.is_a? Integer
|
402
400
|
exclude_end? ? self.end - 1 : self.end
|
403
401
|
else
|
404
|
-
|
402
|
+
max_without_hornetseye
|
405
403
|
end
|
406
404
|
end
|
407
405
|
|
406
|
+
alias_method_chain :max, :hornetseye
|
407
|
+
|
408
408
|
# Compute the size of a range
|
409
409
|
#
|
410
410
|
# @return [Integer] Number of discrete values within range.
|
@@ -414,6 +414,48 @@ class Range
|
|
414
414
|
|
415
415
|
end
|
416
416
|
|
417
|
+
class Numeric
|
418
|
+
|
419
|
+
def r
|
420
|
+
self
|
421
|
+
end
|
422
|
+
|
423
|
+
def g
|
424
|
+
self
|
425
|
+
end
|
426
|
+
|
427
|
+
def b
|
428
|
+
self
|
429
|
+
end
|
430
|
+
|
431
|
+
def major( other )
|
432
|
+
if other.is_a? Numeric
|
433
|
+
( self >= other ).conditional self, other
|
434
|
+
else
|
435
|
+
x, y = other.coerce self
|
436
|
+
x.major other
|
437
|
+
end
|
438
|
+
end
|
439
|
+
|
440
|
+
def minor( other )
|
441
|
+
if other.is_a? Numeric
|
442
|
+
( self <= other ).conditional self, other
|
443
|
+
else
|
444
|
+
x, y = other.coerce self
|
445
|
+
x.minor other
|
446
|
+
end
|
447
|
+
end
|
448
|
+
|
449
|
+
end
|
450
|
+
|
451
|
+
class Array
|
452
|
+
|
453
|
+
def collect_with_index( &action )
|
454
|
+
zip( ( 0 ... size ).to_a ).collect &action
|
455
|
+
end
|
456
|
+
|
457
|
+
end
|
458
|
+
|
417
459
|
require 'malloc'
|
418
460
|
require 'rbconfig'
|
419
461
|
require 'set'
|
@@ -426,13 +468,18 @@ require 'multiarray/object'
|
|
426
468
|
require 'multiarray/index'
|
427
469
|
require 'multiarray/bool'
|
428
470
|
require 'multiarray/int'
|
471
|
+
require 'multiarray/float'
|
472
|
+
require 'multiarray/rgb'
|
429
473
|
require 'multiarray/pointer'
|
430
474
|
require 'multiarray/variable'
|
431
475
|
require 'multiarray/lambda'
|
432
476
|
require 'multiarray/lookup'
|
433
|
-
require 'multiarray/
|
434
|
-
require 'multiarray/
|
477
|
+
require 'multiarray/unaryop'
|
478
|
+
require 'multiarray/unarymethod'
|
479
|
+
require 'multiarray/binaryop'
|
480
|
+
require 'multiarray/binarymethod'
|
435
481
|
require 'multiarray/operations'
|
482
|
+
require 'multiarray/methods'
|
436
483
|
require 'multiarray/inject'
|
437
484
|
require 'multiarray/diagonal'
|
438
485
|
require 'multiarray/sequence'
|
@@ -458,7 +505,7 @@ module Hornetseye
|
|
458
505
|
Thread.current[ :lazy ] = true
|
459
506
|
begin
|
460
507
|
options = shape.last.is_a?( Hash ) ? shape.pop : {}
|
461
|
-
arity = options[ :arity ] || action.arity
|
508
|
+
arity = options[ :arity ] || [ action.arity, shape.size ].max
|
462
509
|
if arity <= 0
|
463
510
|
action.call
|
464
511
|
else
|
@@ -506,7 +553,7 @@ module Hornetseye
|
|
506
553
|
# @return [Object,Node] Sum of values.
|
507
554
|
def sum( *shape, &action )
|
508
555
|
options = shape.last.is_a?( Hash ) ? shape.pop : {}
|
509
|
-
arity = options[ :arity ] || action.arity
|
556
|
+
arity = options[ :arity ] || [ action.arity, shape.size ].max
|
510
557
|
if arity <= 0
|
511
558
|
action.call
|
512
559
|
else
|
@@ -0,0 +1,195 @@
|
|
1
|
+
# multiarray - Lazy multi-dimensional arrays for Ruby
|
2
|
+
# Copyright (C) 2010 Jan Wedekind
|
3
|
+
#
|
4
|
+
# This program is free software: you can redistribute it and/or modify
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
6
|
+
# the Free Software Foundation, either version 3 of the License, or
|
7
|
+
# (at your option) any later version.
|
8
|
+
#
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
# GNU General Public License for more details.
|
13
|
+
#
|
14
|
+
# You should have received a copy of the GNU General Public License
|
15
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
16
|
+
|
17
|
+
# Namespace of Hornetseye computer vision library
|
18
|
+
module Hornetseye
|
19
|
+
|
20
|
+
# Class for representing binary operations on scalars and arrays
|
21
|
+
class BinaryMethod_ < Node
|
22
|
+
|
23
|
+
class << self
|
24
|
+
|
25
|
+
# Name of module
|
26
|
+
#
|
27
|
+
# @return [Module] The module with the method.
|
28
|
+
attr_accessor :mod
|
29
|
+
|
30
|
+
# Name of operation
|
31
|
+
#
|
32
|
+
# @return [Symbol,String] The name of this operation.
|
33
|
+
attr_accessor :operation
|
34
|
+
|
35
|
+
# Name of method for type conversion
|
36
|
+
#
|
37
|
+
# @return [Symbol,String] The name of the method for type conversion.
|
38
|
+
attr_accessor :coercion
|
39
|
+
|
40
|
+
# Get string with information about this class
|
41
|
+
#
|
42
|
+
# @return [String] Return string with information about this class.
|
43
|
+
def inspect
|
44
|
+
"#{mod.to_s}.#{operation.to_s}"
|
45
|
+
end
|
46
|
+
|
47
|
+
# Get unique descriptor of this class
|
48
|
+
#
|
49
|
+
# @param [Hash] hash Labels for any variables.
|
50
|
+
#
|
51
|
+
# @return [String] Descriptor of this class.
|
52
|
+
#
|
53
|
+
# @private
|
54
|
+
def descriptor( hash )
|
55
|
+
inspect
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
# Initialise binary operation
|
61
|
+
#
|
62
|
+
# @param [Node] value1 First operand to apply operation to.
|
63
|
+
# @param [Node] value2 Second operand to apply operation to.
|
64
|
+
def initialize( value1, value2 )
|
65
|
+
@value1, @value2 = value1, value2
|
66
|
+
end
|
67
|
+
|
68
|
+
# Get unique descriptor of this object
|
69
|
+
#
|
70
|
+
# @param [Hash] hash Labels for any variables.
|
71
|
+
#
|
72
|
+
# @return [String] Descriptor of this object,
|
73
|
+
#
|
74
|
+
# @private
|
75
|
+
def descriptor( hash )
|
76
|
+
"#{self.class.descriptor( hash )}(#{@value1.descriptor( hash )})," +
|
77
|
+
"(#{@value2.descriptor( hash )})"
|
78
|
+
end
|
79
|
+
|
80
|
+
# Array type of this term
|
81
|
+
#
|
82
|
+
# @return [Class] Resulting array type.
|
83
|
+
#
|
84
|
+
# @private
|
85
|
+
def array_type
|
86
|
+
@value1.array_type.send self.class.coercion, @value2.array_type
|
87
|
+
end
|
88
|
+
|
89
|
+
# Substitute variables
|
90
|
+
#
|
91
|
+
# Substitute the variables with the values given in the hash.
|
92
|
+
#
|
93
|
+
# @param [Hash] hash Substitutions to apply.
|
94
|
+
#
|
95
|
+
# @return [Node] Term with substitutions applied.
|
96
|
+
#
|
97
|
+
# @private
|
98
|
+
def subst( hash )
|
99
|
+
self.class.new @value1.subst( hash ), @value2.subst( hash )
|
100
|
+
end
|
101
|
+
|
102
|
+
# Get variables contained in this term
|
103
|
+
#
|
104
|
+
# @return [Set] Returns set of variables.
|
105
|
+
#
|
106
|
+
# @private
|
107
|
+
def variables
|
108
|
+
@value1.variables + @value2.variables
|
109
|
+
end
|
110
|
+
|
111
|
+
# Strip of all values
|
112
|
+
#
|
113
|
+
# Split up into variables, values, and a term where all values have been
|
114
|
+
# replaced with variables.
|
115
|
+
#
|
116
|
+
# @return [Array<Array,Node>] Returns an array of variables, an array of
|
117
|
+
# values, and the term based on variables.
|
118
|
+
#
|
119
|
+
# @private
|
120
|
+
def strip
|
121
|
+
vars1, values1, term1 = @value1.strip
|
122
|
+
vars2, values2, term2 = @value2.strip
|
123
|
+
return vars1 + vars2, values1 + values2, self.class.new( term1, term2 )
|
124
|
+
end
|
125
|
+
|
126
|
+
# Reevaluate computation
|
127
|
+
#
|
128
|
+
# @return [Node,Object] Result of computation
|
129
|
+
#
|
130
|
+
# @see #force
|
131
|
+
#
|
132
|
+
# @private
|
133
|
+
def demand
|
134
|
+
self.class.mod.send self.class.operation, @value1, @value2
|
135
|
+
end
|
136
|
+
|
137
|
+
def skip( index, start )
|
138
|
+
element1 = @value1.skip( index, start )
|
139
|
+
element2 = @value2.skip( index, start )
|
140
|
+
self.class.new( element1, element2 ).demand
|
141
|
+
end
|
142
|
+
|
143
|
+
# Get element of unary operation
|
144
|
+
#
|
145
|
+
# @param [Integer,Node] i Index of desired element.
|
146
|
+
#
|
147
|
+
# @return [Node,Object] Element of unary operation.
|
148
|
+
def element( i )
|
149
|
+
element1 = @value1.dimension == 0 ? @value1 : @value1.element( i )
|
150
|
+
element2 = @value2.dimension == 0 ? @value2 : @value2.element( i )
|
151
|
+
self.class.new( element1, element2 ).demand
|
152
|
+
end
|
153
|
+
|
154
|
+
def slice( start, length )
|
155
|
+
element1 = @value1.dimension == 0 ? @value1 :
|
156
|
+
@value1.slice( start, length )
|
157
|
+
element2 = @value2.dimension == 0 ? @value2 :
|
158
|
+
@value2.slice( start, length )
|
159
|
+
self.class.new( element1, element2 ).demand
|
160
|
+
end
|
161
|
+
|
162
|
+
# Check whether this term is compilable
|
163
|
+
#
|
164
|
+
# @return [FalseClass,TrueClass] Returns whether this term is compilable.
|
165
|
+
#
|
166
|
+
# @private
|
167
|
+
def compilable?
|
168
|
+
@value1.compilable? and @value2.compilable?
|
169
|
+
end
|
170
|
+
|
171
|
+
end
|
172
|
+
|
173
|
+
# Create a class deriving from +BinaryMethod_+
|
174
|
+
#
|
175
|
+
# @param [Symbol,String] operation Name of operation.
|
176
|
+
# @param [Symbol,String] conversion Name of method for type conversion.
|
177
|
+
#
|
178
|
+
# @return [Class] A class deriving from +BinaryMethod_+.
|
179
|
+
#
|
180
|
+
# @see BinaryMethod_
|
181
|
+
# @see BinaryMethod_.operation
|
182
|
+
# @see BinaryMethod_.coercion
|
183
|
+
#
|
184
|
+
# @private
|
185
|
+
def BinaryMethod( mod, operation, coercion = :coercion )
|
186
|
+
retval = Class.new BinaryMethod_
|
187
|
+
retval.mod = mod
|
188
|
+
retval.operation = operation
|
189
|
+
retval.coercion = coercion
|
190
|
+
retval
|
191
|
+
end
|
192
|
+
|
193
|
+
module_function :BinaryMethod
|
194
|
+
|
195
|
+
end
|