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
@@ -27,8 +27,8 @@ module Hornetseye
|
|
27
27
|
retval = block.pointer_type.new
|
28
28
|
retval_keys, retval_values, retval_term = retval.strip
|
29
29
|
method_name = '_' + term.descriptor( labels ).
|
30
|
-
tr( '()
|
31
|
-
'0123\
|
30
|
+
tr( '(),+\-*/.@?~&|^<=>',
|
31
|
+
'0123\456789ABCDEFG' )
|
32
32
|
unless GCCCache.respond_to? method_name
|
33
33
|
GCCContext.build do |context|
|
34
34
|
function = new context, method_name,
|
@@ -39,14 +39,16 @@ module Hornetseye
|
|
39
39
|
retval_subst = ( 0 ... retval_keys.size ).collect do |i|
|
40
40
|
{ retval_keys[ i ] => function.param( i ) }
|
41
41
|
end.inject( {} ) { |a,b| a.merge b }
|
42
|
+
Thread.current[ :function ] = function
|
42
43
|
Hornetseye::lazy do
|
43
44
|
retval_term.subst( retval_subst ).store term.subst( term_subst )
|
44
45
|
end
|
46
|
+
Thread.current[ :function ] = nil
|
45
47
|
function.insn_return
|
46
48
|
function.compile
|
47
49
|
end
|
48
50
|
end
|
49
|
-
args = ( retval_values + values ).collect { |arg| arg.
|
51
|
+
args = ( retval_values + values ).collect { |arg| arg.values }.flatten
|
50
52
|
GCCCache.send method_name, *args
|
51
53
|
retval.simplify
|
52
54
|
end
|
@@ -74,9 +76,19 @@ module Hornetseye
|
|
74
76
|
end
|
75
77
|
|
76
78
|
def variable( typecode, prefix )
|
77
|
-
|
78
|
-
|
79
|
-
|
79
|
+
#if typecode == INTRGB
|
80
|
+
# r = GCCValue.new( self, id( prefix ) )
|
81
|
+
# g = GCCValue.new( self, id( prefix ) )
|
82
|
+
# b = GCCValue.new( self, id( prefix ) )
|
83
|
+
# self << "#{indent}#{GCCType.new( INT ).identifier} #{r};\n"
|
84
|
+
# self << "#{indent}#{GCCType.new( INT ).identifier} #{g};\n"
|
85
|
+
# self << "#{indent}#{GCCType.new( INT ).identifier} #{b};\n"
|
86
|
+
# INTRGB.new RGB.new( r, g, b )
|
87
|
+
#else
|
88
|
+
retval = typecode.new GCCValue.new( self, id( prefix ) )
|
89
|
+
self << "#{indent}#{GCCType.new( typecode ).identifiers.first} #{retval.get};\n" # !!!
|
90
|
+
retval
|
91
|
+
#end
|
80
92
|
end
|
81
93
|
|
82
94
|
def indent
|
@@ -88,7 +100,12 @@ module Hornetseye
|
|
88
100
|
end
|
89
101
|
|
90
102
|
def param( i )
|
91
|
-
|
103
|
+
offset = ( 0 ... i ).inject( 0 ) do |s,idx|
|
104
|
+
s + GCCType.new( @param_types[ idx ] ).identifiers.size
|
105
|
+
end
|
106
|
+
args = ( 0 ... GCCType.new( @param_types[ i ] ).identifiers.size ).
|
107
|
+
collect { |idx| GCCValue.new self, "param#{ offset + idx }" }
|
108
|
+
@param_types[ i ].construct *args
|
92
109
|
end
|
93
110
|
|
94
111
|
def call( *args )
|
data/lib/multiarray/gcctype.rb
CHANGED
@@ -23,44 +23,54 @@ module Hornetseye
|
|
23
23
|
@typecode = typecode
|
24
24
|
end
|
25
25
|
|
26
|
-
def
|
26
|
+
def identifiers
|
27
27
|
case @typecode
|
28
28
|
when nil
|
29
|
-
'void'
|
29
|
+
[ 'void' ]
|
30
30
|
when BOOL
|
31
|
-
'char'
|
31
|
+
[ 'char' ]
|
32
32
|
when BYTE
|
33
|
-
'char'
|
33
|
+
[ 'char' ]
|
34
34
|
when UBYTE
|
35
|
-
'unsigned char'
|
35
|
+
[ 'unsigned char' ]
|
36
36
|
when SINT
|
37
|
-
'short int'
|
37
|
+
[ 'short int' ]
|
38
38
|
when USINT
|
39
|
-
'unsigned short int'
|
39
|
+
[ 'unsigned short int' ]
|
40
40
|
when INT
|
41
|
-
'int'
|
41
|
+
[ 'int' ]
|
42
42
|
when UINT
|
43
|
-
'unsigned int'
|
43
|
+
[ 'unsigned int' ]
|
44
|
+
when SFLOAT
|
45
|
+
[ 'float' ]
|
46
|
+
when DFLOAT
|
47
|
+
[ 'double' ]
|
44
48
|
else
|
45
49
|
if @typecode < Pointer_
|
46
|
-
'void *'
|
50
|
+
[ 'void *' ]
|
47
51
|
elsif @typecode < INDEX_
|
48
|
-
'int'
|
52
|
+
[ 'int' ]
|
53
|
+
elsif @typecode < RGB_
|
54
|
+
GCCType.new( @typecode.element_type ).identifiers * 3
|
49
55
|
else
|
50
56
|
raise "No identifier available for #{@typecode.inspect}"
|
51
57
|
end
|
52
58
|
end
|
53
59
|
end
|
54
60
|
|
55
|
-
def r2c
|
61
|
+
def r2c
|
56
62
|
case @typecode
|
57
63
|
when BOOL
|
58
|
-
"( #{expr} ) != Qfalse"
|
64
|
+
[ proc { |expr| "( #{expr} ) != Qfalse" } ]
|
59
65
|
when BYTE, UBYTE, SINT, USINT, INT, UINT
|
60
|
-
"NUM2INT( #{expr} )"
|
66
|
+
[ proc { |expr| "NUM2INT( #{expr} )" } ]
|
67
|
+
when SFLOAT, DFLOAT
|
68
|
+
[ proc { |expr| "NUM2DBL( #{expr} )" } ]
|
61
69
|
else
|
62
70
|
if @typecode < Pointer_
|
63
|
-
"(#{
|
71
|
+
[ proc { |expr| "(#{identifiers.first})mallocToPtr( #{expr} )" } ] # !!!
|
72
|
+
elsif @typecode < RGB_
|
73
|
+
GCCType.new( @typecode.element_type ).r2c * 3
|
64
74
|
else
|
65
75
|
raise "No conversion available for #{@typecode.inspect}"
|
66
76
|
end
|
@@ -70,4 +80,4 @@ module Hornetseye
|
|
70
80
|
end
|
71
81
|
|
72
82
|
end
|
73
|
-
|
83
|
+
|
data/lib/multiarray/gccvalue.rb
CHANGED
@@ -19,6 +19,64 @@ module Hornetseye
|
|
19
19
|
|
20
20
|
class GCCValue
|
21
21
|
|
22
|
+
class << self
|
23
|
+
|
24
|
+
def generic?( value )
|
25
|
+
value.is_a?( GCCValue ) or value.is_a?( Fixnum ) or
|
26
|
+
value.is_a?( Float )
|
27
|
+
end
|
28
|
+
|
29
|
+
def define_unary_op( op, opcode = op )
|
30
|
+
define_method( op ) do
|
31
|
+
GCCValue.new @function, "#{opcode}( #{self} )"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def define_unary_method( mod, op, opcode = op )
|
36
|
+
mod.module_eval do
|
37
|
+
define_method( "#{op}_with_gcc" ) do |a|
|
38
|
+
if a.is_a? GCCValue
|
39
|
+
GCCValue.new a.function, "#{opcode}( #{a} )"
|
40
|
+
else
|
41
|
+
send "#{op}_without_gcc", a
|
42
|
+
end
|
43
|
+
end
|
44
|
+
alias_method_chain op, :gcc
|
45
|
+
module_function "#{op}_without_gcc"
|
46
|
+
module_function op
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def define_binary_op( op, opcode = op )
|
51
|
+
define_method( op ) do |other|
|
52
|
+
if GCCValue.generic? other
|
53
|
+
GCCValue.new @function, "( #{self} ) #{opcode} ( #{other} )"
|
54
|
+
else
|
55
|
+
x, y = other.coerce self
|
56
|
+
x.send op, y
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def define_binary_method( mod, op, opcode = op )
|
62
|
+
mod.module_eval do
|
63
|
+
define_method( "#{op}_with_gcc" ) do |a,b|
|
64
|
+
if a.is_a? GCCValue or b.is_a? GCCValue
|
65
|
+
GCCValue.new a.function, "#{opcode}( #{a}, #{b} )"
|
66
|
+
else
|
67
|
+
send "#{op}_without_gcc", a, b
|
68
|
+
end
|
69
|
+
end
|
70
|
+
alias_method_chain op, :gcc
|
71
|
+
module_function "#{op}_without_gcc"
|
72
|
+
module_function op
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
|
78
|
+
attr_reader :function
|
79
|
+
|
22
80
|
def initialize( function, descriptor )
|
23
81
|
@function = function
|
24
82
|
@descriptor = descriptor
|
@@ -32,19 +90,6 @@ module Hornetseye
|
|
32
90
|
@descriptor
|
33
91
|
end
|
34
92
|
|
35
|
-
# Store result of computation in new variable
|
36
|
-
#
|
37
|
-
# @return [Node,Object] Result of computation
|
38
|
-
#
|
39
|
-
# @see #force
|
40
|
-
#
|
41
|
-
# @private
|
42
|
-
def duplicate( typecode )
|
43
|
-
result = @function.variable( typecode, 'v' ).get
|
44
|
-
result.store self
|
45
|
-
result
|
46
|
-
end
|
47
|
-
|
48
93
|
def store( value )
|
49
94
|
@function << "#{@function.indent}#{self} = #{value};\n"
|
50
95
|
value
|
@@ -55,79 +100,83 @@ module Hornetseye
|
|
55
100
|
end
|
56
101
|
|
57
102
|
def load( typecode )
|
58
|
-
|
103
|
+
offset = 0
|
104
|
+
typecode.typecodes.collect do |t|
|
105
|
+
value = GCCValue.new @function,
|
106
|
+
"*(#{GCCType.new( t ).identifiers.first} *)( #{self} + #{offset} )" # !!!
|
107
|
+
offset += t.storage_size
|
108
|
+
value
|
109
|
+
end
|
59
110
|
end
|
60
111
|
|
61
112
|
def save( value )
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
end
|
68
|
-
|
69
|
-
def ne( other )
|
70
|
-
GCCValue.new @function, "( #{self} ) != ( #{other} )"
|
71
|
-
end
|
72
|
-
|
73
|
-
def conditional( a, b )
|
74
|
-
GCCValue.new @function, "( #{self} ) ? ( #{a} ) : ( #{b} )"
|
75
|
-
end
|
76
|
-
|
77
|
-
def not
|
78
|
-
GCCValue.new @function, "!( #{self} )"
|
79
|
-
end
|
80
|
-
|
81
|
-
def ~
|
82
|
-
GCCValue.new @function, "~( #{self} )"
|
83
|
-
end
|
84
|
-
|
85
|
-
def and( other )
|
86
|
-
GCCValue.new @function, "( #{self} ) && ( #{other} )"
|
87
|
-
end
|
88
|
-
|
89
|
-
def or( other )
|
90
|
-
GCCValue.new @function, "( #{self} ) || ( #{other} )"
|
91
|
-
end
|
92
|
-
|
93
|
-
def &( other )
|
94
|
-
GCCValue.new @function, "( #{self} ) & ( #{other} )"
|
95
|
-
end
|
96
|
-
|
97
|
-
def |( other )
|
98
|
-
GCCValue.new @function, "( #{self} ) | ( #{other} )"
|
99
|
-
end
|
100
|
-
|
101
|
-
def ^( other )
|
102
|
-
GCCValue.new @function, "( #{self} ) ^ ( #{other} )"
|
113
|
+
offset = 0
|
114
|
+
value.class.typecodes.zip( value.values ).each do |t,v|
|
115
|
+
@function << "#{@function.indent}*(#{GCCType.new( t ).identifiers.first} *)( #{self} + #{offset} ) = #{v};\n" # !!!
|
116
|
+
offset += t.storage_size
|
117
|
+
end
|
103
118
|
end
|
104
119
|
|
105
|
-
def
|
106
|
-
|
120
|
+
def r
|
121
|
+
self
|
107
122
|
end
|
108
123
|
|
109
|
-
def
|
110
|
-
|
124
|
+
def g
|
125
|
+
self
|
111
126
|
end
|
112
127
|
|
113
|
-
def
|
114
|
-
|
128
|
+
def b
|
129
|
+
self
|
115
130
|
end
|
116
131
|
|
117
|
-
def
|
118
|
-
GCCValue.new @function, "( #{self} )
|
119
|
-
end
|
120
|
-
|
121
|
-
def -( other )
|
122
|
-
GCCValue.new @function, "( #{self} ) - ( #{other} )"
|
123
|
-
end
|
124
|
-
|
125
|
-
def *( other )
|
126
|
-
GCCValue.new @function, "( #{self} ) * ( #{other} )"
|
132
|
+
def conditional( a, b )
|
133
|
+
GCCValue.new @function, "( #{self} ) ? ( #{a} ) : ( #{b} )"
|
127
134
|
end
|
128
135
|
|
129
|
-
|
130
|
-
|
136
|
+
define_unary_op :not, '!'
|
137
|
+
define_unary_op :~
|
138
|
+
define_unary_op :-@, :-
|
139
|
+
define_binary_op :and, '&&'
|
140
|
+
define_binary_op :or, '||'
|
141
|
+
define_binary_op :&
|
142
|
+
define_binary_op :|
|
143
|
+
define_binary_op :^
|
144
|
+
define_binary_op :<<
|
145
|
+
define_binary_op :>>
|
146
|
+
define_binary_op :+
|
147
|
+
define_binary_op :-
|
148
|
+
define_binary_op :*
|
149
|
+
define_binary_op :/
|
150
|
+
define_binary_op :eq, :==
|
151
|
+
define_binary_op :ne, '!='
|
152
|
+
define_binary_op :<
|
153
|
+
define_binary_op :<=
|
154
|
+
define_binary_op :>
|
155
|
+
define_binary_op :>=
|
156
|
+
define_unary_method Math, :sqrt
|
157
|
+
define_unary_method Math, :log
|
158
|
+
define_unary_method Math, :exp
|
159
|
+
define_unary_method Math, :cos
|
160
|
+
define_unary_method Math, :sin
|
161
|
+
define_unary_method Math, :tan
|
162
|
+
define_unary_method Math, :acos
|
163
|
+
define_unary_method Math, :asin
|
164
|
+
define_unary_method Math, :atan
|
165
|
+
define_unary_method Math, :cosh
|
166
|
+
define_unary_method Math, :sinh
|
167
|
+
define_unary_method Math, :tanh
|
168
|
+
define_binary_method Math, :atan2
|
169
|
+
define_binary_method Math, :hypot
|
170
|
+
|
171
|
+
|
172
|
+
def major( other )
|
173
|
+
GCCValue.new @function,
|
174
|
+
"( ( #{self} ) >= ( #{other} ) ) ? ( #{self} ) : ( #{other} )"
|
175
|
+
end
|
176
|
+
|
177
|
+
def minor( other )
|
178
|
+
GCCValue.new @function,
|
179
|
+
"( ( #{self} ) <= ( #{other} ) ) ? ( #{self} ) : ( #{other} )"
|
131
180
|
end
|
132
181
|
|
133
182
|
def zero?
|
@@ -140,11 +189,32 @@ module Hornetseye
|
|
140
189
|
|
141
190
|
def times( &action )
|
142
191
|
i = @function.variable INT, 'i'
|
143
|
-
@function << "#{@function.indent}for ( #{i.get} = 0;
|
192
|
+
@function << "#{@function.indent}for ( #{i.get} = 0; " +
|
193
|
+
"#{i.get} != #{self}; #{i.get}++ ) {\n"
|
194
|
+
@function.indent_offset +1
|
195
|
+
action.call i.get
|
196
|
+
@function.indent_offset -1
|
197
|
+
@function << "#{@function.indent}};\n"
|
198
|
+
self
|
199
|
+
end
|
200
|
+
|
201
|
+
def upto( other, &action )
|
202
|
+
i = @function.variable INT, 'i'
|
203
|
+
@function << "#{@function.indent}for ( #{i.get} = #{self}; " +
|
204
|
+
"#{i.get} != #{ other + 1 }; #{i.get}++ ) {\n"
|
144
205
|
@function.indent_offset +1
|
145
206
|
action.call i.get
|
146
207
|
@function.indent_offset -1
|
147
208
|
@function << "#{@function.indent}};\n"
|
209
|
+
self
|
210
|
+
end
|
211
|
+
|
212
|
+
def coerce( other )
|
213
|
+
if other.is_a? GCCValue
|
214
|
+
return other, self
|
215
|
+
else
|
216
|
+
return GCCValue.new( @function, "( #{other} )" ), self
|
217
|
+
end
|
148
218
|
end
|
149
219
|
|
150
220
|
end
|
data/lib/multiarray/inject.rb
CHANGED
@@ -35,7 +35,9 @@ module Hornetseye
|
|
35
35
|
hash = hash.merge @index => ( ( hash.values.max || 0 ) + 1 )
|
36
36
|
hash = hash.merge @var1 => ( ( hash.values.max || 0 ) + 1 )
|
37
37
|
hash = hash.merge @var2 => ( ( hash.values.max || 0 ) + 1 )
|
38
|
-
"Inject(#{@value.descriptor( hash )}
|
38
|
+
"Inject(#{@value.descriptor( hash )}," +
|
39
|
+
"#{@initial ? @initial.descriptor( hash ) : 'nil'}," +
|
40
|
+
"#{@index.descriptor( hash )},#{@block.descriptor( hash )})"
|
39
41
|
end
|
40
42
|
|
41
43
|
def array_type
|
@@ -52,18 +54,14 @@ module Hornetseye
|
|
52
54
|
def demand
|
53
55
|
if @initial
|
54
56
|
retval = @initial.simplify # !!!
|
55
|
-
|
56
|
-
sub = @value.subst( @index => INT.new( i ) ).simplify # !!!
|
57
|
-
retval.store @block.subst( @var1 => retval,
|
58
|
-
@var2 => sub ).simplify
|
59
|
-
end
|
57
|
+
offset = INT.new 0
|
60
58
|
else
|
61
59
|
retval = @value.subst( @index => INT.new( 0 ) ).simplify # !!!
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
60
|
+
offset = INT.new 1
|
61
|
+
end
|
62
|
+
offset.upto @index.size - 1 do |i|
|
63
|
+
sub = @value.subst @index => INT.new( i )
|
64
|
+
retval.store @block.subst( @var1 => retval, @var2 => sub )
|
67
65
|
end
|
68
66
|
retval
|
69
67
|
end
|
@@ -97,18 +95,17 @@ module Hornetseye
|
|
97
95
|
#
|
98
96
|
# @private
|
99
97
|
def strip
|
100
|
-
|
98
|
+
meta_vars, meta_values, var = @index.strip
|
99
|
+
vars1, values1, term1 = @value.subst( @index => var ).strip
|
101
100
|
if @initial
|
102
101
|
vars2, values2, term2 = @initial.strip
|
103
102
|
else
|
104
103
|
vars2, values2 = [], [], nil
|
105
104
|
end
|
106
105
|
vars3, values3, term3 = @block.strip
|
107
|
-
meta_vars, meta_values, var = @index.strip
|
108
106
|
return vars1 + vars2 + vars3 + meta_vars,
|
109
107
|
values1 + values2 + values3 + meta_values,
|
110
|
-
Inject.new( term1
|
111
|
-
var, term2, term3, @var1, @var2 )
|
108
|
+
Inject.new( term1, var, term2, term3, @var1, @var2 )
|
112
109
|
end
|
113
110
|
|
114
111
|
# Substitute variables
|