multiarray 0.4.1 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/COPYING +1 -1
- data/README.md +3 -0
- data/Rakefile +7 -6
- data/TODO +79 -2
- data/lib/multiarray.rb +452 -31
- data/lib/multiarray/binary.rb +174 -0
- data/lib/multiarray/bool.rb +138 -0
- data/lib/multiarray/diagonal.rb +167 -0
- data/lib/multiarray/element.rb +146 -0
- data/lib/multiarray/gcccache.rb +23 -0
- data/lib/multiarray/gcccontext.rb +144 -0
- data/lib/multiarray/gccfunction.rb +109 -0
- data/lib/multiarray/gcctype.rb +73 -0
- data/lib/multiarray/gccvalue.rb +152 -0
- data/lib/multiarray/index.rb +91 -0
- data/lib/multiarray/inject.rb +143 -0
- data/lib/multiarray/int.rb +238 -13
- data/lib/multiarray/lambda.rb +100 -0
- data/lib/multiarray/list.rb +27 -50
- data/lib/multiarray/lookup.rb +85 -0
- data/lib/multiarray/malloc.rb +28 -2
- data/lib/multiarray/multiarray.rb +44 -30
- data/lib/multiarray/node.rb +596 -0
- data/lib/multiarray/object.rb +74 -31
- data/lib/multiarray/operations.rb +78 -0
- data/lib/multiarray/pointer.rb +134 -4
- data/lib/multiarray/sequence.rb +209 -38
- data/lib/multiarray/unary.rb +170 -0
- data/lib/multiarray/variable.rb +120 -0
- data/test/tc_bool.rb +117 -0
- data/test/tc_int.rb +122 -85
- data/test/tc_multiarray.rb +196 -55
- data/test/tc_object.rb +54 -49
- data/test/tc_sequence.rb +177 -83
- data/test/ts_multiarray.rb +17 -0
- metadata +40 -16
- data/README +0 -1
- data/lib/multiarray/int_.rb +0 -198
- data/lib/multiarray/lazy.rb +0 -81
- data/lib/multiarray/pointer_.rb +0 -260
- data/lib/multiarray/sequence_.rb +0 -155
- data/lib/multiarray/type.rb +0 -207
data/COPYING
CHANGED
data/README.md
ADDED
@@ -0,0 +1,3 @@
|
|
1
|
+
MultiArray
|
2
|
+
==========
|
3
|
+
This Ruby-extension defines the class {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++.
|
data/Rakefile
CHANGED
@@ -6,11 +6,11 @@ require 'rake/packagetask'
|
|
6
6
|
require 'rbconfig'
|
7
7
|
|
8
8
|
PKG_NAME = 'multiarray'
|
9
|
-
PKG_VERSION = '0.
|
9
|
+
PKG_VERSION = '0.5.0'
|
10
10
|
RB_FILES = FileList[ 'lib/**/*.rb' ]
|
11
11
|
TC_FILES = FileList[ 'test/tc_*.rb' ]
|
12
12
|
TS_FILES = FileList[ 'test/ts_*.rb' ]
|
13
|
-
PKG_FILES = [ 'Rakefile', 'README', 'COPYING', 'TODO', '.document' ] +
|
13
|
+
PKG_FILES = [ 'Rakefile', 'README.md', 'COPYING', 'TODO', '.document' ] +
|
14
14
|
RB_FILES + TS_FILES + TC_FILES
|
15
15
|
SUMMARY = %q{Multi-dimensional and uniform Ruby arrays}
|
16
16
|
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++.}
|
@@ -30,8 +30,8 @@ desc 'Install Ruby extension'
|
|
30
30
|
task :install do
|
31
31
|
verbose true do
|
32
32
|
for f in RB_FILES do
|
33
|
-
FileUtils.mkdir_p "#{$SITELIBDIR}/#{File.dirname
|
34
|
-
FileUtils.cp_r f, "#{$SITELIBDIR}/#{f
|
33
|
+
FileUtils.mkdir_p "#{$SITELIBDIR}/#{File.dirname f.gsub( /^lib\//, '' )}"
|
34
|
+
FileUtils.cp_r f, "#{$SITELIBDIR}/#{f.gsub /^lib\//, ''}"
|
35
35
|
end
|
36
36
|
end
|
37
37
|
end
|
@@ -40,7 +40,7 @@ desc 'Uninstall Ruby extension'
|
|
40
40
|
task :uninstall do
|
41
41
|
verbose true do
|
42
42
|
for f in RB_FILES do
|
43
|
-
FileUtils.rm_f "#{$SITELIBDIR}/#{f
|
43
|
+
FileUtils.rm_f "#{$SITELIBDIR}/#{f.gsub /^lib\//, ''}"
|
44
44
|
end
|
45
45
|
end
|
46
46
|
end
|
@@ -84,7 +84,8 @@ begin
|
|
84
84
|
s.has_rdoc = 'yard'
|
85
85
|
s.extra_rdoc_files = []
|
86
86
|
s.rdoc_options = %w{--no-private}
|
87
|
-
s.add_dependency %q<malloc>, [ '~> 0
|
87
|
+
s.add_dependency %q<malloc>, [ '~> 1.0' ]
|
88
|
+
s.add_development_dependency %q{rake}
|
88
89
|
end
|
89
90
|
GEM_SOURCE = "#{PKG_NAME}-#{PKG_VERSION}.gem"
|
90
91
|
desc "Build the gem file #{GEM_SOURCE}"
|
data/TODO
CHANGED
@@ -1,7 +1,82 @@
|
|
1
|
-
|
1
|
+
# test for multiarray-indgen
|
2
|
+
# accept ranges for element access
|
3
|
+
# compile Convolve#demand
|
4
|
+
# inject without initial is [ 1 .. -1 ].inject with [ 0 ] as initial value
|
5
|
+
# Composite numbers?
|
6
|
+
# pointer-increments for better efficiency
|
7
|
+
# How does contiguous work here? typecasts?
|
8
|
+
# separate secondary operations like equality
|
9
|
+
# preload cache
|
10
|
+
# Sequence( UBYTE, 3 )[ ... ]
|
11
|
+
|
12
|
+
# histogram (implement using injection)
|
13
|
+
# inject: min, max, equal, n-d clips for warp
|
14
|
+
# block(var1,var2,...) with smart subst?
|
15
|
+
# lazy( 5 ) { |i| 0 } # but lazy { 0 }
|
16
|
+
# lazy( 3, 2 ) { |i,j| i }
|
17
|
+
# lazy( 3, 2 ) { |i,j| j.to_object }
|
18
|
+
|
19
|
+
# RSpec
|
20
|
+
|
21
|
+
# downsampling after correlation?
|
22
|
+
# README.rdoc, YARD documentation with pictures, demo video
|
23
|
+
|
24
|
+
# f(g(i)) # g(i), f(g(i)) all can be vectors and all can be lazy
|
25
|
+
# lut(g(i))
|
26
|
+
# f(warp(i))
|
27
|
+
#class Node
|
28
|
+
# def map( lut, options = {} )
|
29
|
+
#
|
30
|
+
# end
|
31
|
+
#end
|
32
|
+
|
33
|
+
|
34
|
+
# cache <-> demand/get? what about store?
|
35
|
+
# Composite numbers?
|
36
|
+
# change Convolve#demand to generate GCC code
|
37
|
+
# inspect method (type method to get MultiArray( ... ) or Sequence( ... ))
|
38
|
+
# put JIT-calls into 'force'-method, don't call JIT for OBJECT
|
39
|
+
# -> multiarray gem
|
40
|
+
# pointer-increments for better efficiency
|
41
|
+
# use pid, allow creation of library for pre-loading cache
|
42
|
+
|
43
|
+
# histogram
|
44
|
+
# binary operations, equality: ( a == b ).inject( true ) { |e,b| e && b }
|
45
|
+
# inject: min, max, equal, n-d clips for warp
|
46
|
+
# 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
|
+
|
51
|
+
# downsampling after correlation?
|
52
|
+
# ruby -Ilib -rrubygems -rmultiarray -rtest test/tc_sequence.rb
|
53
|
+
# README.rdoc, demo video
|
54
|
+
|
55
|
+
# f(g(i)) # g(i), f(g(i)) all can be vectors and all can be lazy
|
56
|
+
# lut(g(i))
|
57
|
+
# f(warp(i))
|
58
|
+
#class Node
|
59
|
+
# def map( lut, options = {} ) # !!!
|
60
|
+
#
|
61
|
+
# end
|
62
|
+
#end
|
63
|
+
|
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
|
+
|
2
76
|
tensor indices to enable transpose of lazy array
|
77
|
+
ranges (rolling, lazy rolling, lazy ranges)
|
3
78
|
test lazyness
|
4
|
-
sums/injections? nesting? tensors?
|
79
|
+
sums/injections (equality for arrays)? nesting? tensors?
|
5
80
|
JIT?
|
6
81
|
test type conversions
|
7
82
|
fancy README
|
@@ -52,6 +127,8 @@ proc { |i| proc { |j| i+j } }.call( 5 ).call 3
|
|
52
127
|
|
53
128
|
gem install flay: http://ruby.sadi.st/Flay.html
|
54
129
|
|
130
|
+
# donate to yardoc
|
131
|
+
|
55
132
|
How to nest/cascade mode-environments?
|
56
133
|
(how to specify nested modes for recursive algorithms and called algorithms?)
|
57
134
|
ruby and jit compiles, lazy and parallel forwards
|
data/lib/multiarray.rb
CHANGED
@@ -1,10 +1,49 @@
|
|
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
|
+
# Module#alias_method_chain is defined.
|
18
|
+
#
|
19
|
+
# @private
|
20
|
+
class Module
|
21
|
+
|
22
|
+
unless method_defined? :alias_method_chain
|
23
|
+
|
24
|
+
# Method for creating alias chains.
|
25
|
+
#
|
26
|
+
# @private
|
27
|
+
def alias_method_chain( target, feature, vocalize = target )
|
28
|
+
alias_method "#{vocalize}_without_#{feature}", target
|
29
|
+
alias_method target, "#{vocalize}_with_#{feature}"
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
1
36
|
# Proc#bind is defined if it does not exist already
|
37
|
+
#
|
38
|
+
# @private
|
2
39
|
class Proc
|
3
40
|
|
4
41
|
unless method_defined? :bind
|
5
42
|
|
6
43
|
# Proc#bind is defined if it does not exist already
|
7
44
|
#
|
45
|
+
# @param [Object] object Object to bind this instance of +Proc+ to.
|
46
|
+
#
|
8
47
|
# @private
|
9
48
|
def bind( object )
|
10
49
|
block, time = self, Time.now
|
@@ -21,7 +60,7 @@ class Proc
|
|
21
60
|
|
22
61
|
end
|
23
62
|
|
24
|
-
# Object
|
63
|
+
# +Object+ is extended with a few methods
|
25
64
|
class Object
|
26
65
|
|
27
66
|
unless method_defined? :instance_exec
|
@@ -35,18 +74,316 @@ class Object
|
|
35
74
|
|
36
75
|
end
|
37
76
|
|
77
|
+
# Boolean negation
|
78
|
+
#
|
79
|
+
# @return [FalseClass] Returns +false+.
|
80
|
+
#
|
81
|
+
# @see NilClass#not
|
82
|
+
# @see FalseClass#not
|
83
|
+
def not
|
84
|
+
false
|
85
|
+
end
|
86
|
+
|
87
|
+
# Boolean 'and' operation
|
88
|
+
#
|
89
|
+
# @param [FalseClass,TrueClass,Object] other Other boolean object.
|
90
|
+
# @return [FalseClass,TrueClass] Returns +other+.
|
91
|
+
#
|
92
|
+
# @see FalseClass#and
|
93
|
+
# @see NilClass#and
|
94
|
+
def and( other )
|
95
|
+
unless other.is_a? Hornetseye::Node
|
96
|
+
other
|
97
|
+
else
|
98
|
+
x, y = other.coerce self
|
99
|
+
x.and y
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
# Boolean 'or' operation
|
104
|
+
#
|
105
|
+
# @param [FalseClass,TrueClass,Object] other Other boolean object.
|
106
|
+
# @return [TrueClass] Returns +true+.
|
107
|
+
#
|
108
|
+
# @see FalseClass#or
|
109
|
+
# @see NilClass#or
|
110
|
+
def or( other )
|
111
|
+
unless other.is_a? Hornetseye::Node
|
112
|
+
self
|
113
|
+
else
|
114
|
+
x, y = other.coerce self
|
115
|
+
x.or y
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
# Element-wise equal operator
|
120
|
+
#
|
121
|
+
# The method calls +self == other+ unless +other+ is of type
|
122
|
+
# Hornetseye::Node. In that case an element-wise comparison using
|
123
|
+
# Hornetseye::Node#eq is performed after coercion.
|
124
|
+
#
|
125
|
+
# @return [FalseClass,TrueClass,Hornetseye::Node] Result of comparison.
|
126
|
+
# @see Hornetseye::Node
|
127
|
+
# @see Hornetseye::Binary_
|
128
|
+
def eq( other )
|
129
|
+
unless other.is_a? Hornetseye::Node
|
130
|
+
self == other
|
131
|
+
else
|
132
|
+
x, y = other.coerce self
|
133
|
+
x.eq y
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
# Element-wise not-equal operator
|
138
|
+
#
|
139
|
+
# The method calls +( self == other ).not+ unless +other+ is of type
|
140
|
+
# Hornetseye::Node. In that case an element-wise comparison using
|
141
|
+
# Hornetseye::Node#ne is performed after coercion.
|
142
|
+
#
|
143
|
+
# @return [FalseClass,TrueClass,Hornetseye::Node] Result of comparison.
|
144
|
+
# @see Hornetseye::Node
|
145
|
+
# @see Hornetseye::Binary_
|
146
|
+
def ne( other )
|
147
|
+
unless other.is_a? Hornetseye::Node
|
148
|
+
( self == other ).not
|
149
|
+
else
|
150
|
+
x, y = other.coerce self
|
151
|
+
x.ne y
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
# Boolean select operation
|
156
|
+
#
|
157
|
+
# @param [Object] a Object to select if +self+ is neither +false+ nor +nil+.
|
158
|
+
# @param [Object] b Object to select if +self+ is +false+ or +nil+.
|
159
|
+
# @return [Object] Returns +a+.
|
160
|
+
#
|
161
|
+
# @see FalseClass#conditional
|
162
|
+
# @see NilClass#conditional
|
163
|
+
def conditional( a, b )
|
164
|
+
a
|
165
|
+
end
|
166
|
+
|
38
167
|
end
|
39
168
|
|
40
|
-
#
|
41
|
-
class
|
169
|
+
# +NilClass+ is extended with a few methods
|
170
|
+
class NilClass
|
171
|
+
|
172
|
+
# Boolean negation
|
173
|
+
#
|
174
|
+
# @return [FalseClass] Returns +false+.
|
175
|
+
#
|
176
|
+
# @see Object#not
|
177
|
+
# @see FalseClass#not
|
178
|
+
def not
|
179
|
+
true
|
180
|
+
end
|
181
|
+
|
182
|
+
# Boolean 'and' operation
|
183
|
+
#
|
184
|
+
# @param [FalseClass,TrueClass,Object] other Other boolean object.
|
185
|
+
# @return [FalseClass] Returns +false+.
|
186
|
+
#
|
187
|
+
# @see Object#and
|
188
|
+
# @see FalseClass#and
|
189
|
+
def and( other )
|
190
|
+
unless other.is_a? Hornetseye::Node
|
191
|
+
self
|
192
|
+
else
|
193
|
+
x, y = other.coerce self
|
194
|
+
x.and y
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
# Boolean 'or' operation
|
199
|
+
#
|
200
|
+
# @param [FalseClass,TrueClass,Object] other Other boolean object.
|
201
|
+
# @return [FalseClass,TrueClass] Returns +other+.
|
202
|
+
#
|
203
|
+
# @see Object#or
|
204
|
+
# @see FalseClass#or
|
205
|
+
def or( other )
|
206
|
+
unless other.is_a? Hornetseye::Node
|
207
|
+
other
|
208
|
+
else
|
209
|
+
x, y = other.coerce self
|
210
|
+
x.or y
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
# Boolean select operation
|
215
|
+
#
|
216
|
+
# @param [Object] a Object to select if +self+ is neither +false+ nor +nil+.
|
217
|
+
# @param [Object] b Object to select if +self+ is +false+ or +nil+.
|
218
|
+
# @return [Object] Returns +b+.
|
219
|
+
#
|
220
|
+
# @see Object#conditional
|
221
|
+
# @see FalseClass#conditional
|
222
|
+
def conditional( a, b )
|
223
|
+
b
|
224
|
+
end
|
225
|
+
|
226
|
+
# Check whether this term is compilable
|
227
|
+
#
|
228
|
+
# @return [FalseClass,TrueClass] Returns +false+
|
229
|
+
#
|
230
|
+
# @private
|
231
|
+
def compilable?
|
232
|
+
false
|
233
|
+
end
|
234
|
+
|
235
|
+
end
|
236
|
+
|
237
|
+
# +FalseClass+ is extended with a few methods
|
238
|
+
#
|
239
|
+
# @see TrueClass
|
240
|
+
class FalseClass
|
241
|
+
|
242
|
+
# Boolean negation
|
243
|
+
#
|
244
|
+
# @return [FalseClass] Returns +true+.
|
245
|
+
#
|
246
|
+
# @see Object#not
|
247
|
+
# @see NilClass#not
|
248
|
+
def not
|
249
|
+
true
|
250
|
+
end
|
251
|
+
|
252
|
+
# Boolean 'and' operation
|
253
|
+
#
|
254
|
+
# @param [FalseClass,TrueClass,Object] other Other boolean object.
|
255
|
+
# @return [FalseClass] Returns +false+.
|
256
|
+
#
|
257
|
+
# @see Object#and
|
258
|
+
# @see NilClass#and
|
259
|
+
def and( other )
|
260
|
+
unless other.is_a? Hornetseye::Node
|
261
|
+
self
|
262
|
+
else
|
263
|
+
x, y = other.coerce self
|
264
|
+
x.and y
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
# Boolean 'or' operation
|
269
|
+
#
|
270
|
+
# @param [FalseClass,TrueClass,Object] other Other boolean object.
|
271
|
+
# @return [FalseClass,TrueClass] Returns +other+.
|
272
|
+
#
|
273
|
+
# @see Object#or
|
274
|
+
# @see NilClass#or
|
275
|
+
def or( other )
|
276
|
+
unless other.is_a? Hornetseye::Node
|
277
|
+
other
|
278
|
+
else
|
279
|
+
x, y = other.coerce self
|
280
|
+
x.or y
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
# Boolean select operation
|
285
|
+
#
|
286
|
+
# @param [Object] a Object to select if +self+ is neither +false+ nor +nil+.
|
287
|
+
# @param [Object] b Object to select if +self+ is +false+ or +nil+.
|
288
|
+
# @return [Object] Returns +b+.
|
289
|
+
#
|
290
|
+
# @see Object#conditional
|
291
|
+
# @see NilClass#conditional
|
292
|
+
def conditional( a, b )
|
293
|
+
b
|
294
|
+
end
|
295
|
+
|
296
|
+
end
|
42
297
|
|
43
|
-
|
298
|
+
# Some methods of +Fixnum+ are modified
|
299
|
+
#
|
300
|
+
# @private
|
301
|
+
class Fixnum
|
302
|
+
|
303
|
+
# +&+ is modified to work with this library
|
304
|
+
#
|
305
|
+
# @private
|
306
|
+
def intand_with_hornetseye( other )
|
307
|
+
if other.is_a? Integer
|
308
|
+
intand_without_hornetseye other
|
309
|
+
else
|
310
|
+
x, y = other.coerce self
|
311
|
+
x & y
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
alias_method_chain :&, :hornetseye, :intand
|
316
|
+
|
317
|
+
# +|+ is modified to work with this library
|
318
|
+
#
|
319
|
+
# @private
|
320
|
+
def intor_with_hornetseye( other )
|
321
|
+
if other.is_a? Integer
|
322
|
+
intor_without_hornetseye other
|
323
|
+
else
|
324
|
+
x, y = other.coerce self
|
325
|
+
x | y
|
326
|
+
end
|
327
|
+
end
|
328
|
+
|
329
|
+
alias_method_chain :|, :hornetseye, :intor
|
330
|
+
|
331
|
+
# +^+ is modified to work with this library
|
332
|
+
#
|
333
|
+
# @private
|
334
|
+
def intxor_with_hornetseye( other )
|
335
|
+
if other.is_a? Integer
|
336
|
+
intxor_without_hornetseye other
|
337
|
+
else
|
338
|
+
x, y = other.coerce self
|
339
|
+
x ^ y
|
340
|
+
end
|
341
|
+
end
|
342
|
+
|
343
|
+
alias_method_chain :^, :hornetseye, :intxor
|
344
|
+
|
345
|
+
# +<<+ is modified to work with this library
|
346
|
+
#
|
347
|
+
# @private
|
348
|
+
def shl_with_hornetseye( other )
|
349
|
+
if other.is_a? Integer
|
350
|
+
shl_without_hornetseye other
|
351
|
+
else
|
352
|
+
x, y = other.coerce self
|
353
|
+
x << y
|
354
|
+
end
|
355
|
+
end
|
356
|
+
|
357
|
+
alias_method_chain :<<, :hornetseye, :shl
|
358
|
+
|
359
|
+
# +>>+ is modified to work with this library
|
360
|
+
#
|
361
|
+
# @private
|
362
|
+
def shr_with_hornetseye( other )
|
363
|
+
if other.is_a? Integer
|
364
|
+
shr_without_hornetseye other
|
365
|
+
else
|
366
|
+
x, y = other.coerce self
|
367
|
+
x >> y
|
368
|
+
end
|
369
|
+
end
|
370
|
+
|
371
|
+
alias_method_chain :>>, :hornetseye, :shr
|
372
|
+
|
373
|
+
end
|
374
|
+
|
375
|
+
# +Range+ is extended with a few methods
|
376
|
+
class Range
|
44
377
|
|
45
378
|
alias_method :orig_min, :min
|
46
379
|
|
47
380
|
alias_method :orig_max, :max
|
48
381
|
|
49
382
|
# For performance reasons a specialised method for integers is added
|
383
|
+
#
|
384
|
+
# @return [Object] Minimum value of range.
|
385
|
+
#
|
386
|
+
# @private
|
50
387
|
def min
|
51
388
|
if self.begin.is_a? Integer
|
52
389
|
self.begin
|
@@ -55,7 +392,11 @@ class Range
|
|
55
392
|
end
|
56
393
|
end
|
57
394
|
|
58
|
-
# For performance reasons a specialised method for integers is added
|
395
|
+
# For performance reasons a specialised method for integers is added
|
396
|
+
#
|
397
|
+
# @return [Object] Maximum value of range.
|
398
|
+
#
|
399
|
+
# @private
|
59
400
|
def max
|
60
401
|
if self.end.is_a? Integer
|
61
402
|
exclude_end? ? self.end - 1 : self.end
|
@@ -64,42 +405,122 @@ class Range
|
|
64
405
|
end
|
65
406
|
end
|
66
407
|
|
67
|
-
# Compute the size of a range
|
408
|
+
# Compute the size of a range
|
409
|
+
#
|
410
|
+
# @return [Integer] Number of discrete values within range.
|
68
411
|
def size
|
69
412
|
max + 1 - min
|
70
413
|
end
|
71
414
|
|
72
415
|
end
|
73
416
|
|
74
|
-
# Module#alias_method_chain is defined.
|
75
|
-
#
|
76
|
-
# @private
|
77
|
-
class Module
|
78
|
-
|
79
|
-
unless method_defined? :alias_method_chain
|
80
|
-
|
81
|
-
# Method for creating alias chains.
|
82
|
-
#
|
83
|
-
# @private
|
84
|
-
def alias_method_chain( target, feature, vocalize = target )
|
85
|
-
alias_method "#{vocalize}_without_#{feature}", target
|
86
|
-
alias_method target, "#{vocalize}_with_#{feature}"
|
87
|
-
end
|
88
|
-
|
89
|
-
end
|
90
|
-
|
91
|
-
end
|
92
|
-
|
93
417
|
require 'malloc'
|
94
|
-
require '
|
95
|
-
require '
|
418
|
+
require 'rbconfig'
|
419
|
+
require 'set'
|
420
|
+
require 'tmpdir'
|
96
421
|
require 'multiarray/malloc'
|
97
|
-
require 'multiarray/
|
422
|
+
require 'multiarray/list'
|
423
|
+
require 'multiarray/node'
|
424
|
+
require 'multiarray/element'
|
98
425
|
require 'multiarray/object'
|
99
|
-
require 'multiarray/
|
426
|
+
require 'multiarray/index'
|
427
|
+
require 'multiarray/bool'
|
100
428
|
require 'multiarray/int'
|
101
|
-
require 'multiarray/pointer_'
|
102
429
|
require 'multiarray/pointer'
|
103
|
-
require 'multiarray/
|
430
|
+
require 'multiarray/variable'
|
431
|
+
require 'multiarray/lambda'
|
432
|
+
require 'multiarray/lookup'
|
433
|
+
require 'multiarray/unary'
|
434
|
+
require 'multiarray/binary'
|
435
|
+
require 'multiarray/operations'
|
436
|
+
require 'multiarray/inject'
|
437
|
+
require 'multiarray/diagonal'
|
104
438
|
require 'multiarray/sequence'
|
105
439
|
require 'multiarray/multiarray'
|
440
|
+
require 'multiarray/gcctype'
|
441
|
+
require 'multiarray/gccvalue'
|
442
|
+
require 'multiarray/gcccontext'
|
443
|
+
require 'multiarray/gcccache'
|
444
|
+
require 'multiarray/gccfunction'
|
445
|
+
|
446
|
+
# Namespace of Hornetseye computer vision library
|
447
|
+
module Hornetseye
|
448
|
+
|
449
|
+
# Method for performing computations in lazy mode
|
450
|
+
#
|
451
|
+
# @param [Array<Integer>] *shape Optional shape of result. The method
|
452
|
+
# attempts to infer the shape if not specified.
|
453
|
+
# @yield Operation to compute array elements lazily.
|
454
|
+
#
|
455
|
+
# @return [Object,Node] Lazy term to compute later.
|
456
|
+
def lazy( *shape, &action )
|
457
|
+
previous = Thread.current[ :lazy ]
|
458
|
+
Thread.current[ :lazy ] = true
|
459
|
+
begin
|
460
|
+
options = shape.last.is_a?( Hash ) ? shape.pop : {}
|
461
|
+
arity = options[ :arity ] || action.arity
|
462
|
+
if arity <= 0
|
463
|
+
action.call
|
464
|
+
else
|
465
|
+
index = Variable.new shape.empty? ? Hornetseye::INDEX( nil ) :
|
466
|
+
Hornetseye::INDEX( shape.pop )
|
467
|
+
term = lazy *( shape + [ :arity => arity - 1 ] ) do |*args|
|
468
|
+
action.call *( args + [ index ] )
|
469
|
+
end
|
470
|
+
term = Node.match( term ).new term unless term.is_a? Node
|
471
|
+
Lambda.new index, term
|
472
|
+
end
|
473
|
+
ensure
|
474
|
+
Thread.current[ :lazy ] = previous
|
475
|
+
end
|
476
|
+
end
|
477
|
+
|
478
|
+
module_function :lazy
|
479
|
+
|
480
|
+
# Method for performing computations in eager mode
|
481
|
+
#
|
482
|
+
# @param [Array<Integer>] *shape Optional shape of result. The method
|
483
|
+
# attempts to infer the shape if not specified.
|
484
|
+
# @yield Operation computing array elements.
|
485
|
+
#
|
486
|
+
# @return [Object,Node] Result of computation.
|
487
|
+
def eager( *shape, &action )
|
488
|
+
previous = Thread.current[ :lazy ]
|
489
|
+
Thread.current[ :lazy ] = false
|
490
|
+
begin
|
491
|
+
retval = lazy *shape, &action
|
492
|
+
retval.is_a?( Node ) ? retval.force : retval
|
493
|
+
ensure
|
494
|
+
Thread.current[ :lazy ] = previous
|
495
|
+
end
|
496
|
+
end
|
497
|
+
|
498
|
+
module_function :eager
|
499
|
+
|
500
|
+
# Method for summing values
|
501
|
+
#
|
502
|
+
# @param [Array<Integer>] *shape Optional shape of result. The method
|
503
|
+
# attempts to infer the shape if not specified.
|
504
|
+
# @yield Operation returning array elements.
|
505
|
+
#
|
506
|
+
# @return [Object,Node] Sum of values.
|
507
|
+
def sum( *shape, &action )
|
508
|
+
options = shape.last.is_a?( Hash ) ? shape.pop : {}
|
509
|
+
arity = options[ :arity ] || action.arity
|
510
|
+
if arity <= 0
|
511
|
+
action.call
|
512
|
+
else
|
513
|
+
index = Variable.new shape.empty? ? Hornetseye::INDEX( nil ) :
|
514
|
+
Hornetseye::INDEX( shape.pop )
|
515
|
+
term = sum *( shape + [ :arity => arity - 1 ] ) do |*args|
|
516
|
+
action.call *( args + [ index ] )
|
517
|
+
end
|
518
|
+
var1 = Variable.new term.typecode
|
519
|
+
var2 = Variable.new term.typecode
|
520
|
+
Inject.new( term, index, nil, var1 + var2, var1, var2 ).force
|
521
|
+
end
|
522
|
+
end
|
523
|
+
|
524
|
+
module_function :sum
|
525
|
+
|
526
|
+
end
|