vector_sse 0.0.1.pre

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,43 @@
1
+ //
2
+ // Copyright (c) 2015, Robert Glissmann
3
+ // All rights reserved.
4
+ //
5
+ // Redistribution and use in source and binary forms, with or without
6
+ // modification, are permitted provided that the following conditions are met:
7
+ //
8
+ // * Redistributions of source code must retain the above copyright notice, this
9
+ // list of conditions and the following disclaimer.
10
+ //
11
+ // * Redistributions in binary form must reproduce the above copyright notice,
12
+ // this list of conditions and the following disclaimer in the documentation
13
+ // and/or other materials provided with the distribution.
14
+ //
15
+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16
+ // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
+ // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
+ // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19
+ // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
+ // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21
+ // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22
+ // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23
+ // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24
+ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
+ //
26
+
27
+ // %% license-end-token %%
28
+ //
29
+ // Author: Robert.Glissmann@gmail.com (Robert Glissmann)
30
+ //
31
+ //
32
+
33
+ #ifndef VECTOR_SSE_VEC_MUL_H
34
+ #define VECTOR_SSE_VEC_MUL_H
35
+
36
+ #include <ruby.h>
37
+
38
+ VALUE method_vec_mul_s32( VALUE self, VALUE left, VALUE right );
39
+ VALUE method_vec_mul_s64( VALUE self, VALUE left, VALUE right );
40
+ VALUE method_vec_mul_f32( VALUE self, VALUE left, VALUE right );
41
+ VALUE method_vec_mul_f64( VALUE self, VALUE left, VALUE right );
42
+
43
+ #endif // VECTOR_SSE_VEC_MUL_H
data/lib/.gitignore ADDED
@@ -0,0 +1 @@
1
+ vector_sse/
data/lib/vector_sse.rb ADDED
@@ -0,0 +1,475 @@
1
+ #
2
+ # Copyright (c) 2015, Robert Glissmann
3
+ # All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions are met:
7
+ #
8
+ # * Redistributions of source code must retain the above copyright notice, this
9
+ # list of conditions and the following disclaimer.
10
+ #
11
+ # * Redistributions in binary form must reproduce the above copyright notice,
12
+ # this list of conditions and the following disclaimer in the documentation
13
+ # and/or other materials provided with the distribution.
14
+ #
15
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
+ #
26
+
27
+ # %% license-end-token %%
28
+ #
29
+ # Author: Robert.Glissmann@gmail.com (Robert Glissmann)
30
+ #
31
+ #
32
+
33
+ bin_root = File.join( File.dirname( __FILE__ ), 'vector_sse' )
34
+ require File.join( bin_root, 'vector_sse.so' )
35
+
36
+
37
+ module VectorSSE
38
+
39
+ VERSION = "0.0.1.pre"
40
+
41
+ module Type
42
+ S32 = 0
43
+ S64 = 1
44
+ F32 = 4
45
+ F64 = 5
46
+ INVALID = -1
47
+ end
48
+
49
+ def self.valid_type( type )
50
+ [ Type::S32, Type::S64, Type::F32, Type::F64 ].include?( type )
51
+ end
52
+
53
+
54
+ class Mat
55
+
56
+ MIN_ROW_COL_COUNT = 1
57
+
58
+ attr_reader :type
59
+ attr_reader :rows
60
+ attr_reader :cols
61
+
62
+ def initialize( type, rows, cols, data=nil )
63
+
64
+ if VectorSSE::valid_type( type )
65
+ @type = type
66
+ else
67
+ raise ArgumentError.new( "invalid SSE matrix type for argument 0" )
68
+ end
69
+
70
+ if rows < MIN_ROW_COL_COUNT
71
+ raise ArgumentError.new( "row count must be greater than zero for argument 1" )
72
+ end
73
+
74
+ if cols < MIN_ROW_COL_COUNT
75
+ raise ArgumentError.new( "column count must be greater than zero for argument 2" )
76
+ end
77
+
78
+ if data && ( data.class != ::Array )
79
+ raise ArgumentError.new( "expected value of type Array for argument 3" )
80
+ end
81
+
82
+ @rows = rows
83
+ @cols = cols
84
+ @linear_size = @rows * @cols
85
+
86
+ @data = ::Array.new( @linear_size, 0 )
87
+
88
+ fill( data ) if data
89
+ end
90
+
91
+ def at( row, col )
92
+ valid_row_col( row, col )
93
+ @data[ linear_index( row, col ) ]
94
+ end
95
+
96
+ def set( row, col, val )
97
+ valid_row_col( row, col )
98
+ valid_data_type( val )
99
+ @data[ linear_index( row, col ) ] = val
100
+ end
101
+
102
+ def fill( data )
103
+ if data.length != @rows * @cols
104
+ raise ArgumentError.new( "size does not match matrix size" )
105
+ end
106
+
107
+ data.each do |value|
108
+ valid_data_type( value )
109
+ end
110
+
111
+ @data = data
112
+ end
113
+
114
+ def []( pos )
115
+ valid_linear_index( pos )
116
+ @data[ pos ]
117
+ end
118
+
119
+ def []=( pos, val )
120
+ valid_linear_index( pos )
121
+ valid_data_type( val )
122
+ @data[ pos ] = val
123
+ end
124
+
125
+ def to_s
126
+ text = ""
127
+ @rows.times do |r|
128
+ vals = []
129
+ @cols.times do |c|
130
+ vals << @data[r*@cols + c]
131
+ end
132
+ text << "|#{vals.join(' ')}|\n"
133
+ end
134
+ text
135
+ end
136
+
137
+ def *( other )
138
+
139
+ scalar_mul = false
140
+
141
+ if [ Fixnum, Float ].include? other.class
142
+
143
+ scalar_mul = true
144
+ scalar_value = other
145
+ other = Mat.new( @type, @rows, @cols )
146
+ other.data.replace( ::Array.new( @linear_size, scalar_value ) )
147
+
148
+ elsif other.class == self.class
149
+
150
+ if @cols != other.rows
151
+ raise "invalid matrix dimensions"
152
+ end
153
+
154
+ else
155
+ raise ArgumentError.new(
156
+ "expected argument of type #{self.class} for argument 0" )
157
+ end
158
+
159
+
160
+ result = Mat.new( @type, @rows, other.cols )
161
+
162
+ case @type
163
+ when Type::S32
164
+ if scalar_mul
165
+ result.data.replace( VectorSSE::vec_mul_s32( self.data, other.data ) )
166
+ else
167
+ result.data.replace( VectorSSE::mul_s32(
168
+ @data, @rows, @cols, other.data, other.rows, other.cols ) )
169
+ end
170
+ when Type::S64
171
+ if scalar_mul
172
+ result.data.replace( VectorSSE::vec_mul_s32( self.data, other.data ) )
173
+ else
174
+ result.data.replace( VectorSSE::mul_s64(
175
+ @data, @rows, @cols, other.data, other.rows, other.cols ) )
176
+ end
177
+ when Type::F32
178
+ if scalar_mul
179
+ result.data.replace( VectorSSE::vec_mul_f32( self.data, other.data ) )
180
+ else
181
+ result.data.replace( VectorSSE::mul_f32(
182
+ @data, @rows, @cols, other.data, other.rows, other.cols ) )
183
+ end
184
+ when Type::F64
185
+ if scalar_mul
186
+ result.data.replace( VectorSSE::vec_mul_f64( self.data, other.data ) )
187
+ else
188
+ result.data.replace( VectorSSE::mul_f64(
189
+ @data, @rows, @cols, other.data, other.rows, other.cols ) )
190
+ end
191
+ end
192
+
193
+ result
194
+ end
195
+
196
+ def +( other )
197
+
198
+ if [ Fixnum, Float ].include? other.class
199
+
200
+ scalar_value = other
201
+ other = Mat.new( @type, @rows, @cols )
202
+ other.data.replace( ::Array.new( @linear_size, scalar_value ) )
203
+
204
+ elsif other.class == self.class
205
+
206
+ if ( @rows != other.rows ) || ( @cols != other.cols )
207
+ raise ArgumentError.new(
208
+ "matrix addition requires operands of equal size")
209
+ end
210
+
211
+ else
212
+
213
+ raise ArgumentError.new(
214
+ "expect argument of type #{self.class}, Fixnum, or Float for argument 0" )
215
+
216
+ end
217
+
218
+ result = Mat.new( @type, @rows, @cols )
219
+
220
+ case @type
221
+ when Type::S32
222
+ result.data.replace( VectorSSE::add_s32( self.data, other.data ) )
223
+ when Type::S64
224
+ result.data.replace( VectorSSE::add_s64( self.data, other.data ) )
225
+ when Type::F32
226
+ result.data.replace( VectorSSE::add_f32( self.data, other.data ) )
227
+ when Type::F64
228
+ result.data.replace( VectorSSE::add_f64( self.data, other.data ) )
229
+ end
230
+
231
+ result
232
+ end
233
+
234
+ def -( other )
235
+
236
+ if [ Fixnum, Float ].include? other.class
237
+
238
+ scalar_value = other
239
+ other = Mat.new( @type, @rows, @cols )
240
+ other.data = ::Array.new( @linear_size, scalar_value )
241
+
242
+ elsif other.class == self.class
243
+
244
+ if ( @rows != other.rows ) || ( @cols != other.cols )
245
+ raise ArgumentError.new(
246
+ "matrix subtraction requires operands of equal size")
247
+ end
248
+
249
+ else
250
+
251
+ raise ArgumentError.new(
252
+ "expect argument of type #{self.class}, Fixnum, or Float for argument 0" )
253
+
254
+ end
255
+
256
+ result = Mat.new( @type, @rows, @cols )
257
+
258
+ case @type
259
+ when Type::S32
260
+ result.data.replace( VectorSSE::sub_s32( self.data, other.data ) )
261
+ when Type::S64
262
+ result.data.replace( VectorSSE::sub_s64( self.data, other.data ) )
263
+ when Type::F32
264
+ result.data.replace( VectorSSE::sub_f32( self.data, other.data ) )
265
+ when Type::F64
266
+ result.data.replace( VectorSSE::sub_f64( self.data, other.data ) )
267
+ end
268
+
269
+ result
270
+ end
271
+
272
+ def transpose
273
+ raise "unimplemented"
274
+ end
275
+
276
+ def reshape( rows, cols )
277
+ raise "unimplemented"
278
+ end
279
+
280
+
281
+ protected
282
+
283
+
284
+ def linear_index( row, col )
285
+
286
+ row * @cols + col
287
+
288
+ end
289
+
290
+ def valid_linear_index( pos )
291
+
292
+ if ( pos < 0 ) || ( pos >= @linear_size )
293
+ raise IndexError.new( "index out of bounds" )
294
+ end
295
+
296
+ end
297
+
298
+ def valid_row_col( row, col )
299
+
300
+ if ( row < 0 ) || ( row >= @rows )
301
+ raise IndexError.new( "row index out of bounds" )
302
+ end
303
+
304
+ if ( col < 0 ) || ( col >= @cols )
305
+ raise IndexError.new( "column index out of bounds" )
306
+ end
307
+
308
+ end
309
+
310
+ def valid_data_type( value )
311
+
312
+ unless [ Fixnum, Float ].include? value.class
313
+ raise ArgumentError.new( "expected argument of type Fixnum or Float" )
314
+ end
315
+
316
+ end
317
+
318
+ attr_accessor :data
319
+
320
+ end
321
+ Matrix = Mat
322
+
323
+
324
+ class Array < Array
325
+
326
+ attr_reader :type
327
+
328
+ def initialize( type, size=0, val=nil )
329
+ super( size, val )
330
+
331
+ if VectorSSE::valid_type( type )
332
+ @type = type
333
+ else
334
+ raise "invalid SSE vector type"
335
+ end
336
+ end
337
+
338
+ def <<( value )
339
+ unless [ Fixnum, Float ].include? value.class
340
+ raise ArgumentError.new(
341
+ "expected argument of type Fixnum or Float for argument 0" )
342
+ end
343
+ super( value )
344
+ end
345
+
346
+ def insert( index, *values )
347
+ values.each_with_index do |value,arg_index|
348
+ unless [ Fixnum, Float ].include? value.class
349
+ raise ArgumentError.new(
350
+ "expected argument of type Fixnum or Float for argument #{arg_index}" )
351
+ end
352
+ end
353
+ super( index, values )
354
+ end
355
+
356
+ def []=( index, value )
357
+ unless [ Fixnum, Float ].include? value.class
358
+ raise ArgumentError.new(
359
+ "expected argument of type Fixnum or Float for argument 1" )
360
+ end
361
+ super( index, value )
362
+ end
363
+
364
+ # Note:
365
+ # This method replaces the base class implementation of '+', which
366
+ # performs concatenation. To concatenate, see #concat.
367
+ #
368
+ def +( other )
369
+
370
+ if [ Fixnum, Float ].include? other.class
371
+
372
+ other = ::Array.new( self.length, other )
373
+
374
+ elsif other.class != self.class
375
+
376
+ raise ArgumentError.new(
377
+ "expect argument of type #{self.class}, Fixnum, or Float for argument 0" )
378
+
379
+ end
380
+
381
+ result = self.class.new( @type )
382
+
383
+ case @type
384
+ when Type::S32
385
+ result.replace( VectorSSE::add_s32( self, other ) )
386
+ when Type::S64
387
+ result.replace( VectorSSE::add_s64( self, other ) )
388
+ when Type::F32
389
+ result.replace( VectorSSE::add_f32( self, other ) )
390
+ when Type::F64
391
+ result.replace( VectorSSE::add_f64( self, other ) )
392
+ end
393
+
394
+ result
395
+ end
396
+
397
+ # Note:
398
+ # This method replaces the base class implementation of '-', which
399
+ # removes items that are found in 'other'.
400
+ #
401
+ def -( other )
402
+
403
+ if [ Fixnum, Float ].include? other.class
404
+ other = ::Array.new( self.length, other )
405
+ elsif other.class != self.class
406
+ raise ArgumentError.new(
407
+ "expected argument of type #{self.class}, Fixnum, or Float for argument 0" )
408
+ end
409
+
410
+ result = self.class.new( @type )
411
+
412
+ case @type
413
+ when Type::S32
414
+ result.replace( VectorSSE::sub_s32( self, other ) )
415
+ when Type::S64
416
+ result.replace( VectorSSE::sub_s64( self, other ) )
417
+ when Type::F32
418
+ result.replace( VectorSSE::sub_f32( self, other ) )
419
+ when Type::F64
420
+ result.replace( VectorSSE::sub_f64( self, other ) )
421
+ end
422
+
423
+ result
424
+ end
425
+
426
+ def sum
427
+ sum_result = 0
428
+
429
+ case @type
430
+ when Type::S32
431
+ sum_result = VectorSSE::sum_s32( self )
432
+ when Type::S64
433
+ sum_result = VectorSSE::sum_s64( self )
434
+ when Type::F32
435
+ sum_result = VectorSSE::sum_f32( self )
436
+ when Type::F64
437
+ sum_result = VectorSSE::sum_f64( self )
438
+ else
439
+ raise "invalid SSE vector type"
440
+ end
441
+
442
+ sum_result
443
+ end
444
+
445
+ def *( other )
446
+
447
+ unless [ Fixnum, Float ].include? other.class
448
+
449
+ raise ArgumentError.new( "expected argument of type Float or Fixnum for argument 0" )
450
+
451
+ end
452
+
453
+ other = self.class.new( @type, self.length, other )
454
+ result = self.class.new( @type )
455
+
456
+ case @type
457
+ when Type::S32
458
+ result.replace( VectorSSE::vec_mul_s32( self, other ) )
459
+ when Type::S64
460
+ result.replace( VectorSSE::vec_mul_s64( self, other ) )
461
+ when Type::F32
462
+ result.replace( VectorSSE::vec_mul_f32( self, other ) )
463
+ when Type::F64
464
+ result.replace( VectorSSE::vec_mul_f64( self, other ) )
465
+ end
466
+
467
+ result
468
+ end
469
+
470
+ end
471
+ Arr = Array
472
+
473
+
474
+ end # module VectorSSE
475
+