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
@@ -0,0 +1,146 @@
|
|
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
|
+
# Base class for representing native elements
|
21
|
+
class Element < Node
|
22
|
+
|
23
|
+
class << self
|
24
|
+
|
25
|
+
# Retrieve element from memory
|
26
|
+
#
|
27
|
+
# @param [Malloc,List] ptr Memory to load element from.
|
28
|
+
#
|
29
|
+
# @see Malloc#load
|
30
|
+
# @see List#load
|
31
|
+
def fetch( ptr )
|
32
|
+
new ptr.load( self )
|
33
|
+
end
|
34
|
+
|
35
|
+
# Type coercion for native elements
|
36
|
+
#
|
37
|
+
# @param [Node] other Other native datatype to coerce with.
|
38
|
+
#
|
39
|
+
# @return [Array<Node>] Result of coercion.
|
40
|
+
def coercion( other )
|
41
|
+
if self == other
|
42
|
+
self
|
43
|
+
else
|
44
|
+
x, y = other.coerce self
|
45
|
+
x.coercion y
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
# Constructor initialising element with a value
|
52
|
+
#
|
53
|
+
# @param [Object] value Initial value for element.
|
54
|
+
def initialize( value = self.class.default )
|
55
|
+
@value = value
|
56
|
+
end
|
57
|
+
|
58
|
+
# Get unique descriptor of this object
|
59
|
+
#
|
60
|
+
# @param [Hash] hash Labels for any variables.
|
61
|
+
#
|
62
|
+
# @return [String] Descriptor of this object,
|
63
|
+
#
|
64
|
+
# @private
|
65
|
+
def descriptor( hash )
|
66
|
+
"#{self.class.to_s}(#{@value.to_s})"
|
67
|
+
end
|
68
|
+
|
69
|
+
# Reevaluate computation
|
70
|
+
#
|
71
|
+
# @return [Node,Object] Result of computation
|
72
|
+
#
|
73
|
+
# @see #force
|
74
|
+
#
|
75
|
+
# @private
|
76
|
+
def dup
|
77
|
+
if @value.respond_to? :duplicate
|
78
|
+
self.class.new @value.duplicate( self.class )
|
79
|
+
else
|
80
|
+
self.class.new @value
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# Strip of all values
|
85
|
+
#
|
86
|
+
# Split up into variables, values, and a term where all values have been
|
87
|
+
# replaced with variables.
|
88
|
+
#
|
89
|
+
# @return [Array<Array,Node>] Returns an array of variables, an array of
|
90
|
+
# values, and the term based on variables.
|
91
|
+
#
|
92
|
+
# @private
|
93
|
+
def strip
|
94
|
+
variable = Variable.new self.class
|
95
|
+
return [ variable ], [ self ], variable
|
96
|
+
end
|
97
|
+
|
98
|
+
# Check whether this term is compilable
|
99
|
+
#
|
100
|
+
# @return [FalseClass,TrueClass] Returns whether this term is compilable.
|
101
|
+
#
|
102
|
+
# @private
|
103
|
+
def compilable?
|
104
|
+
if @value.respond_to? :compilable?
|
105
|
+
@value.compilable?
|
106
|
+
else
|
107
|
+
super
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
# Get value of this native element
|
112
|
+
#
|
113
|
+
# @return [Object] Value of this native element.
|
114
|
+
def get
|
115
|
+
@value
|
116
|
+
end
|
117
|
+
|
118
|
+
# Store a value in this native element
|
119
|
+
#
|
120
|
+
# @param [Object] value New value for native element.
|
121
|
+
#
|
122
|
+
# @return [Object] Returns +value+.
|
123
|
+
def store( value )
|
124
|
+
if @value.respond_to? :store
|
125
|
+
@value.store value.simplify.get
|
126
|
+
else
|
127
|
+
@value = value.simplify.get
|
128
|
+
end
|
129
|
+
value
|
130
|
+
end
|
131
|
+
|
132
|
+
# Write element to memory
|
133
|
+
#
|
134
|
+
# @param [Malloc,List] ptr Memory to write element to.
|
135
|
+
#
|
136
|
+
# @see Malloc#save
|
137
|
+
# @see List#save
|
138
|
+
#
|
139
|
+
# @private
|
140
|
+
def write( ptr )
|
141
|
+
ptr.save self
|
142
|
+
end
|
143
|
+
|
144
|
+
end
|
145
|
+
|
146
|
+
end
|
@@ -0,0 +1,23 @@
|
|
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 GCCCache
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
@@ -0,0 +1,144 @@
|
|
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 GCCContext
|
21
|
+
|
22
|
+
LDSHARED = Config::CONFIG[ 'LDSHARED' ] # c:\mingw\bin\gcc
|
23
|
+
STRIP = Config::CONFIG[ 'STRIP' ]
|
24
|
+
RUBYHDRDIR = Config::CONFIG.member?( 'rubyhdrdir' ) ?
|
25
|
+
"-I#{Config::CONFIG['rubyhdrdir']} " +
|
26
|
+
"-I#{Config::CONFIG['rubyhdrdir']}/#{Config::CONFIG['arch']}" :
|
27
|
+
"-I#{Config::CONFIG['archdir']}"
|
28
|
+
LIBRUBYARG = Config::CONFIG[ 'LIBRUBYARG' ]
|
29
|
+
DIRNAME = "#{Dir.tmpdir}/hornetseye-ruby#{RUBY_VERSION}-#{ENV[ 'USER' ]}"
|
30
|
+
Dir.mkdir DIRNAME, 0700 unless File.exist? DIRNAME
|
31
|
+
@@dir = File.new DIRNAME
|
32
|
+
unless @@dir.flock File::LOCK_EX | File::LOCK_NB
|
33
|
+
raise "Could not lock directory #{DIRNAME}"
|
34
|
+
end
|
35
|
+
@@dir.chmod 0700
|
36
|
+
|
37
|
+
@@lib_name = 'hornetseye_aaaaaaaa'
|
38
|
+
|
39
|
+
# while File.exist? "#{DIRNAME}/#{@@lib_name}.so"
|
40
|
+
# require "#{DIRNAME}/#{@@lib_name}.so"
|
41
|
+
# @@lib_name = @@lib_name.succ
|
42
|
+
# end
|
43
|
+
|
44
|
+
class << self
|
45
|
+
|
46
|
+
def build( &action )
|
47
|
+
lib_name, @@lib_name = @@lib_name, @@lib_name.succ
|
48
|
+
new( lib_name ).build &action
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
def initialize( lib_name )
|
54
|
+
@lib_name = lib_name
|
55
|
+
@instructions = ''
|
56
|
+
@wrappers = ''
|
57
|
+
@registrations = ''
|
58
|
+
end
|
59
|
+
|
60
|
+
def build( &action )
|
61
|
+
action.call self
|
62
|
+
end
|
63
|
+
|
64
|
+
def function( descriptor, *param_types )
|
65
|
+
@instructions << <<EOS
|
66
|
+
void #{descriptor}(#{
|
67
|
+
if param_types.empty?
|
68
|
+
''
|
69
|
+
else
|
70
|
+
' ' + ( 0 ... param_types.size ).collect do |i|
|
71
|
+
"#{param_types[ i ].identifier} param#{i}"
|
72
|
+
end.join( ', ' ) + ' '
|
73
|
+
end
|
74
|
+
}) {
|
75
|
+
EOS
|
76
|
+
|
77
|
+
@wrappers << <<EOS
|
78
|
+
VALUE wrap#{descriptor.capitalize}( VALUE rbSelf#{
|
79
|
+
( 0 ... param_types.size ).inject '' do |s,i|
|
80
|
+
s << ", VALUE rbParam#{i}"
|
81
|
+
end
|
82
|
+
} )
|
83
|
+
{
|
84
|
+
#{descriptor}(#{
|
85
|
+
if param_types.empty?
|
86
|
+
''
|
87
|
+
else
|
88
|
+
s = ' ' + ( 0 ... param_types.size ).collect do |i|
|
89
|
+
param_types[ i ].r2c "rbParam#{i}"
|
90
|
+
end.join( ', ' ) + ' '
|
91
|
+
end
|
92
|
+
});
|
93
|
+
return Qnil;
|
94
|
+
}
|
95
|
+
EOS
|
96
|
+
|
97
|
+
@registrations << <<EOS
|
98
|
+
rb_define_singleton_method( cGCCCache, "#{descriptor}",
|
99
|
+
RUBY_METHOD_FUNC( wrap#{descriptor.capitalize} ),
|
100
|
+
#{param_types.size} );
|
101
|
+
EOS
|
102
|
+
end
|
103
|
+
def compile
|
104
|
+
template = <<EOS
|
105
|
+
#include <ruby.h>
|
106
|
+
|
107
|
+
inline void *mallocToPtr( VALUE rbMalloc )
|
108
|
+
{
|
109
|
+
VALUE rbValue = rb_iv_get( rbMalloc, "@value" );
|
110
|
+
void *retVal; Data_Get_Struct( rbValue, void, retVal );
|
111
|
+
return retVal;
|
112
|
+
}
|
113
|
+
|
114
|
+
#{@instructions}
|
115
|
+
|
116
|
+
#{@wrappers}
|
117
|
+
void Init_#{@lib_name}(void)
|
118
|
+
{
|
119
|
+
VALUE mHornetseye = rb_define_module( "Hornetseye" );
|
120
|
+
VALUE cGCCCache = rb_define_class_under( mHornetseye, "GCCCache", rb_cObject );
|
121
|
+
#{@registrations}
|
122
|
+
}
|
123
|
+
EOS
|
124
|
+
# File::EXCL no overwrite
|
125
|
+
File.open "#{DIRNAME}/#{@lib_name}.c", 'w', 0600 do |f|
|
126
|
+
f << template
|
127
|
+
end
|
128
|
+
gcc = "#{LDSHARED} -fPIC #{RUBYHDRDIR} -o #{DIRNAME}/#{@lib_name}.so " +
|
129
|
+
"#{DIRNAME}/#{@lib_name}.c #{LIBRUBYARG}"
|
130
|
+
strip = "#{STRIP} #{DIRNAME}/#{@lib_name}.so"
|
131
|
+
# puts template
|
132
|
+
raise "Error compiling #{DIRNAME}/#{@lib_name}.c" unless system gcc
|
133
|
+
raise "Error stripping #{DIRNAME}/#{@lib_name}.so" unless system strip
|
134
|
+
require "#{DIRNAME}/#{@lib_name}.so"
|
135
|
+
end
|
136
|
+
|
137
|
+
def <<( str )
|
138
|
+
@instructions << str
|
139
|
+
self
|
140
|
+
end
|
141
|
+
|
142
|
+
end
|
143
|
+
|
144
|
+
end
|
@@ -0,0 +1,109 @@
|
|
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 GCCFunction
|
21
|
+
|
22
|
+
class << self
|
23
|
+
|
24
|
+
def run( block )
|
25
|
+
keys, values, term = block.strip
|
26
|
+
labels = Hash[ *keys.zip( ( 0 ... keys.size ).to_a ).flatten ]
|
27
|
+
retval = block.pointer_type.new
|
28
|
+
retval_keys, retval_values, retval_term = retval.strip
|
29
|
+
method_name = '_' + term.descriptor( labels ).
|
30
|
+
tr( '(),+\-*/.@?~&|^<>',
|
31
|
+
'0123\456789ABCDEF' )
|
32
|
+
unless GCCCache.respond_to? method_name
|
33
|
+
GCCContext.build do |context|
|
34
|
+
function = new context, method_name,
|
35
|
+
*( retval_keys + keys ).collect { |var| var.meta }
|
36
|
+
term_subst = ( 0 ... keys.size ).collect do |i|
|
37
|
+
{ keys[i] => function.param( i + retval_keys.size ) }
|
38
|
+
end.inject( {} ) { |a,b| a.merge b }
|
39
|
+
retval_subst = ( 0 ... retval_keys.size ).collect do |i|
|
40
|
+
{ retval_keys[ i ] => function.param( i ) }
|
41
|
+
end.inject( {} ) { |a,b| a.merge b }
|
42
|
+
Hornetseye::lazy do
|
43
|
+
retval_term.subst( retval_subst ).store term.subst( term_subst )
|
44
|
+
end
|
45
|
+
function.insn_return
|
46
|
+
function.compile
|
47
|
+
end
|
48
|
+
end
|
49
|
+
args = ( retval_values + values ).collect { |arg| arg.get }
|
50
|
+
GCCCache.send method_name, *args
|
51
|
+
retval.simplify
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
def initialize( context, method_name, *param_types )
|
57
|
+
context.function method_name, *param_types.collect { |t| GCCType.new t }
|
58
|
+
@context = context
|
59
|
+
@method_name = method_name
|
60
|
+
@param_types = param_types
|
61
|
+
@indent = 1
|
62
|
+
@ids = 0
|
63
|
+
end
|
64
|
+
|
65
|
+
def compile
|
66
|
+
self << '}'
|
67
|
+
@context.compile
|
68
|
+
self
|
69
|
+
end
|
70
|
+
|
71
|
+
def id( prefix )
|
72
|
+
@ids += 1
|
73
|
+
"%s%02d"% [ prefix, @ids ]
|
74
|
+
end
|
75
|
+
|
76
|
+
def variable( typecode, prefix )
|
77
|
+
retval = typecode.new GCCValue.new( self, id( prefix ) )
|
78
|
+
self << "#{indent}#{GCCType.new( typecode ).identifier} #{retval.get};\n"
|
79
|
+
retval
|
80
|
+
end
|
81
|
+
|
82
|
+
def indent
|
83
|
+
' ' * @indent
|
84
|
+
end
|
85
|
+
|
86
|
+
def indent_offset( offset )
|
87
|
+
@indent += offset
|
88
|
+
end
|
89
|
+
|
90
|
+
def param( i )
|
91
|
+
@param_types[ i ].new GCCValue.new( self, "param#{i}" )
|
92
|
+
end
|
93
|
+
|
94
|
+
def call( *args )
|
95
|
+
@context.send @method_name, *args.collect { |v| v.get }
|
96
|
+
end
|
97
|
+
|
98
|
+
def insn_return( value = nil )
|
99
|
+
self << "#{indent}return#{ value ? ' ' + value.get.to_s : '' };\n"
|
100
|
+
end
|
101
|
+
|
102
|
+
def <<( str )
|
103
|
+
@context << str
|
104
|
+
self
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
@@ -0,0 +1,73 @@
|
|
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 GCCType
|
21
|
+
|
22
|
+
def initialize( typecode )
|
23
|
+
@typecode = typecode
|
24
|
+
end
|
25
|
+
|
26
|
+
def identifier
|
27
|
+
case @typecode
|
28
|
+
when nil
|
29
|
+
'void'
|
30
|
+
when BOOL
|
31
|
+
'char'
|
32
|
+
when BYTE
|
33
|
+
'char'
|
34
|
+
when UBYTE
|
35
|
+
'unsigned char'
|
36
|
+
when SINT
|
37
|
+
'short int'
|
38
|
+
when USINT
|
39
|
+
'unsigned short int'
|
40
|
+
when INT
|
41
|
+
'int'
|
42
|
+
when UINT
|
43
|
+
'unsigned int'
|
44
|
+
else
|
45
|
+
if @typecode < Pointer_
|
46
|
+
'void *'
|
47
|
+
elsif @typecode < INDEX_
|
48
|
+
'int'
|
49
|
+
else
|
50
|
+
raise "No identifier available for #{@typecode.inspect}"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def r2c( expr )
|
56
|
+
case @typecode
|
57
|
+
when BOOL
|
58
|
+
"( #{expr} ) != Qfalse"
|
59
|
+
when BYTE, UBYTE, SINT, USINT, INT, UINT
|
60
|
+
"NUM2INT( #{expr} )"
|
61
|
+
else
|
62
|
+
if @typecode < Pointer_
|
63
|
+
"(#{identifier})mallocToPtr( #{expr} )"
|
64
|
+
else
|
65
|
+
raise "No conversion available for #{@typecode.inspect}"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|