simd 0.0.1 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ext/simd/simd_floatarray.c +172 -29
- data/ext/simd/simd_floatarray.h +14 -14
- data/ext/simd/simd_types.h +20 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8f0bff704f3580fee55205c32ada6a1844dde4ae
|
4
|
+
data.tar.gz: 9e4f9d097fa20a349b77279535d39ea695a881a4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ccaa110b5ff7708c5e14dd5355f4361544832b412c2d150e9849f8106c55e1183252cbe540163941b65968037369b8618b5e66c9267e75807553aa2e7e8ccda5
|
7
|
+
data.tar.gz: e107fe3e242f6baa6d93ab6edf2886f58499d70fd690f6f1c72d7bff165932ce953026d480b0ac3a41c5e35d1ec4dc8b96c19d38d19857f0fdc8c7e759c3fa44
|
data/ext/simd/simd_floatarray.c
CHANGED
@@ -2,87 +2,123 @@
|
|
2
2
|
|
3
3
|
VALUE SIMD_FloatArray = Qnil;
|
4
4
|
|
5
|
+
/* Internal: Create the SIMD::FloatArray class. */
|
5
6
|
void Init_SIMD_FloatArray(VALUE parent)
|
6
7
|
{
|
7
8
|
SIMD_FloatArray = rb_define_class_under(parent, "FloatArray", rb_cObject);
|
8
9
|
rb_define_alloc_func(SIMD_FloatArray, allocate);
|
9
10
|
rb_define_method(SIMD_FloatArray, "initialize", method_initialize, 1);
|
10
11
|
rb_define_method(SIMD_FloatArray, "*", method_multiply, 1);
|
12
|
+
rb_define_method(SIMD_FloatArray, "/", method_divide, 1);
|
13
|
+
rb_define_method(SIMD_FloatArray, "+", method_add, 1);
|
14
|
+
rb_define_method(SIMD_FloatArray, "-", method_subtract, 1);
|
11
15
|
rb_define_method(SIMD_FloatArray, "length", method_length, 0);
|
12
16
|
rb_define_method(SIMD_FloatArray, "to_a", method_to_a, 0);
|
13
17
|
}
|
14
18
|
|
19
|
+
/* Internal: Allocate memory for the vector container. */
|
15
20
|
static VALUE allocate(VALUE klass)
|
16
21
|
{
|
17
|
-
|
18
|
-
vector
|
22
|
+
d2v_container *vector = malloc(sizeof(d2v_container));
|
23
|
+
if(vector == NULL)
|
24
|
+
{
|
25
|
+
rb_raise(rb_eNoMemError, "Unable to allocate memory");
|
26
|
+
}
|
19
27
|
|
28
|
+
vector->data = NULL; /* Avoid potentially freeing unitialized memory. */
|
20
29
|
return(Data_Wrap_Struct(klass, NULL, deallocate, vector));
|
21
30
|
}
|
22
31
|
|
23
|
-
|
32
|
+
/* Internal: Free memory from the vector container and the data array. */
|
33
|
+
static void deallocate(d2v_container *vector)
|
24
34
|
{
|
25
|
-
|
35
|
+
if(vector)
|
36
|
+
{
|
37
|
+
if(vector->data)
|
38
|
+
{
|
39
|
+
free(vector->data);
|
40
|
+
}
|
41
|
+
free(vector);
|
42
|
+
}
|
26
43
|
}
|
27
44
|
|
45
|
+
/* Public: Initialize the FloatArray object given a Ruby Array of values
|
46
|
+
* which can be cast to a double. */
|
28
47
|
static VALUE method_initialize(VALUE self, VALUE rb_array)
|
29
48
|
{
|
30
|
-
|
31
|
-
long n,m,i;
|
49
|
+
d2v_container *vector;
|
50
|
+
unsigned long n,m,i;
|
32
51
|
|
33
52
|
Check_Type(rb_array, T_ARRAY);
|
53
|
+
Data_Get_Struct(self, d2v_container, vector);
|
34
54
|
|
35
|
-
Data_Get_Struct(self, double_vector_wrapper, vector);
|
36
55
|
vector->len = n = RARRAY_LEN(rb_array);
|
37
|
-
|
38
|
-
vector->
|
56
|
+
|
57
|
+
if(vector->len < 2)
|
58
|
+
{
|
59
|
+
rb_raise(rb_eArgError, "Vectors must be at least 2 long");
|
60
|
+
}
|
61
|
+
|
62
|
+
vector->data = internal_allocate_vector_array(vector->len);
|
39
63
|
|
40
64
|
for(i = 0; i < n; i++)
|
41
65
|
vector->data[i/2].f[i%2] = NUM2DBL(rb_ary_entry(rb_array, i));
|
42
66
|
|
67
|
+
/* If the array is an odd number of elements, set the final element to 1 */
|
68
|
+
m = n + (n % 2);
|
43
69
|
if(n < m)
|
70
|
+
{
|
44
71
|
vector->data[m/2].f[1] = 1.0;
|
72
|
+
}
|
45
73
|
|
46
74
|
return(self);
|
47
75
|
}
|
48
76
|
|
77
|
+
/* Public: Multiply values contained in the data array with those contained in
|
78
|
+
* another FloatArray object, returning a new FloatArray. */
|
49
79
|
static VALUE method_multiply(VALUE self, VALUE obj)
|
50
80
|
{
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
Data_Get_Struct(self, double_vector_wrapper, vector);
|
55
|
-
Data_Get_Struct(obj, double_vector_wrapper, vector2);
|
56
|
-
|
57
|
-
if(vector->len != vector2->len && vector2->len != 2)
|
58
|
-
rb_raise(rb_eArgError, "Vectors must be the same size, or 2.");
|
81
|
+
return(internal_apply_operation(self, obj, func_multiply));
|
82
|
+
}
|
59
83
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
84
|
+
/* Public: Divide values contained in the data array by those contained in
|
85
|
+
* another FloatArray object, returning a new FloatArray. */
|
86
|
+
static VALUE method_divide(VALUE self, VALUE obj)
|
87
|
+
{
|
88
|
+
return(internal_apply_operation(self, obj, func_divide));
|
89
|
+
}
|
64
90
|
|
65
|
-
|
66
|
-
|
91
|
+
/* Public: add values contained in the data array with those contained in
|
92
|
+
* another FloatArray object, returning a new FloatArray. */
|
93
|
+
static VALUE method_add(VALUE self, VALUE obj)
|
94
|
+
{
|
95
|
+
return(internal_apply_operation(self, obj, func_add));
|
96
|
+
}
|
67
97
|
|
68
|
-
|
98
|
+
/* Public: Subtract values contained in another FloatArray object from those
|
99
|
+
* contained in the current data array object, returning a new FloatArray. */
|
100
|
+
static VALUE method_subtract(VALUE self, VALUE obj)
|
101
|
+
{
|
102
|
+
return(internal_apply_operation(self, obj, func_subtract));
|
69
103
|
}
|
70
104
|
|
105
|
+
/* Public: Return the number of elements in the Array. */
|
71
106
|
static VALUE method_length(VALUE self)
|
72
107
|
{
|
73
|
-
|
74
|
-
Data_Get_Struct(self,
|
108
|
+
d2v_container *vector;
|
109
|
+
Data_Get_Struct(self, d2v_container, vector);
|
75
110
|
|
76
111
|
return(INT2NUM(vector->len));
|
77
112
|
}
|
78
113
|
|
114
|
+
/* Public: Return a Ruby Array containing the doubles within the data array. */
|
79
115
|
static VALUE method_to_a(VALUE self)
|
80
116
|
{
|
81
|
-
long i;
|
82
|
-
|
117
|
+
unsigned long i;
|
118
|
+
d2v_container *vector;
|
83
119
|
VALUE rb_array = rb_ary_new();
|
84
120
|
|
85
|
-
Data_Get_Struct(self,
|
121
|
+
Data_Get_Struct(self, d2v_container, vector);
|
86
122
|
for(i = 0; i < vector->len; i++)
|
87
123
|
{
|
88
124
|
rb_ary_store(rb_array, i, DBL2NUM(vector->data[i/2].f[i%2]));
|
@@ -90,3 +126,110 @@ static VALUE method_to_a(VALUE self)
|
|
90
126
|
|
91
127
|
return(rb_array);
|
92
128
|
}
|
129
|
+
|
130
|
+
/* Internal: Given another FloatArray object, perform an action specified via a
|
131
|
+
* function pointer against both. */
|
132
|
+
static VALUE internal_apply_operation(VALUE self, VALUE obj, b_operation func)
|
133
|
+
{
|
134
|
+
unsigned long size, i;
|
135
|
+
int align;
|
136
|
+
d2v_container *v1, *v2, *r;
|
137
|
+
VALUE result_obj = allocate(SIMD_FloatArray);
|
138
|
+
|
139
|
+
Data_Get_Struct(self, d2v_container, v1);
|
140
|
+
Data_Get_Struct(obj, d2v_container, v2);
|
141
|
+
Data_Get_Struct(result_obj, d2v_container, r);
|
142
|
+
|
143
|
+
align = internal_align_vectors(v1->len, v2->len);
|
144
|
+
|
145
|
+
/* Ensure that size will be the result of ceil(len / 2.0) */
|
146
|
+
size = (v1->len + 1) / 2;
|
147
|
+
r->data = internal_allocate_vector_array(v1->len);
|
148
|
+
r->len = v1->len;
|
149
|
+
|
150
|
+
switch(align)
|
151
|
+
{
|
152
|
+
case 0: /* Same size arrays */
|
153
|
+
for(i = 0; i < size; i++)
|
154
|
+
{
|
155
|
+
r->data[i].v = func(v1->data[i].v, v2->data[i].v);
|
156
|
+
}
|
157
|
+
break;
|
158
|
+
case 1: /* Operand is exactly 2 long (size of 1 sse register) */
|
159
|
+
for(i = 0; i < size; i++)
|
160
|
+
{
|
161
|
+
r->data[i].v = func(v1->data[i].v, v2->data[0].v);
|
162
|
+
}
|
163
|
+
break;
|
164
|
+
default: /* Self is a multiple of operand's length long */
|
165
|
+
for(i = 0; i < size; i++)
|
166
|
+
{
|
167
|
+
r->data[i].v = func(v1->data[i].v, v2->data[i % v2->len].v);
|
168
|
+
}
|
169
|
+
}
|
170
|
+
|
171
|
+
return(result_obj);
|
172
|
+
}
|
173
|
+
|
174
|
+
/* Internal: Allocate memory for the data array. */
|
175
|
+
static d2v_t *internal_allocate_vector_array(unsigned long size)
|
176
|
+
{
|
177
|
+
d2v_t *vector = malloc(((size + (size % 2)) / 2 + 1) * sizeof(d2v_t));
|
178
|
+
if(vector == NULL)
|
179
|
+
{
|
180
|
+
rb_raise(rb_eNoMemError, "Unable to allocate memory");
|
181
|
+
}
|
182
|
+
|
183
|
+
return(vector);
|
184
|
+
}
|
185
|
+
|
186
|
+
/* Internal: Determine if two arrays can be acted upon, by being of equal
|
187
|
+
* lengths or with the operand's length being a multiple of the data array's. */
|
188
|
+
static int internal_align_vectors(unsigned long v1, unsigned long v2)
|
189
|
+
{
|
190
|
+
if((v1 % 2) != (v2 % 2))
|
191
|
+
{
|
192
|
+
rb_raise(rb_eArgError, "Both Vectors must be of even or odd length.");
|
193
|
+
}
|
194
|
+
|
195
|
+
if(v1 == v2)
|
196
|
+
{
|
197
|
+
return(0);
|
198
|
+
}
|
199
|
+
if(v2 == 2)
|
200
|
+
{
|
201
|
+
return(1);
|
202
|
+
}
|
203
|
+
if(v1 % v2 == 0)
|
204
|
+
{
|
205
|
+
return(2);
|
206
|
+
}
|
207
|
+
|
208
|
+
rb_raise(rb_eArgError, "Vector length must be evenly divisible by operand.");
|
209
|
+
/* Never reached */
|
210
|
+
return(-1);
|
211
|
+
}
|
212
|
+
|
213
|
+
/* Function: Multiply two vectors. */
|
214
|
+
static d2v func_multiply(d2v v1, d2v v2)
|
215
|
+
{
|
216
|
+
return(v1 * v2);
|
217
|
+
}
|
218
|
+
|
219
|
+
/* Function: Divide two vectors. */
|
220
|
+
static d2v func_divide(d2v v1, d2v v2)
|
221
|
+
{
|
222
|
+
return(v1 / v2);
|
223
|
+
}
|
224
|
+
|
225
|
+
/* Function: Add two vectors. */
|
226
|
+
static d2v func_add(d2v v1, d2v v2)
|
227
|
+
{
|
228
|
+
return(v1 + v2);
|
229
|
+
}
|
230
|
+
|
231
|
+
/* Function: Subtract two vectors. */
|
232
|
+
static d2v func_subtract(d2v v1, d2v v2)
|
233
|
+
{
|
234
|
+
return(v1 - v2);
|
235
|
+
}
|
data/ext/simd/simd_floatarray.h
CHANGED
@@ -1,22 +1,22 @@
|
|
1
1
|
#include "ruby.h"
|
2
|
-
|
3
|
-
typedef double __attribute__ ((vector_size (16))) v2d;
|
4
|
-
typedef union d2v_t
|
5
|
-
{
|
6
|
-
v2d v;
|
7
|
-
double f[2];
|
8
|
-
} d2v_t;
|
9
|
-
|
10
|
-
typedef struct double_vector_wrapper
|
11
|
-
{
|
12
|
-
d2v_t *data;
|
13
|
-
long len;
|
14
|
-
} double_vector_wrapper;
|
2
|
+
#include "simd_types.h"
|
15
3
|
|
16
4
|
static VALUE allocate(VALUE klass);
|
17
|
-
static void deallocate(
|
5
|
+
static void deallocate(d2v_container *floatarray);
|
18
6
|
|
19
7
|
static VALUE method_initialize(VALUE self, VALUE rb_array);
|
20
8
|
static VALUE method_multiply(VALUE self, VALUE obj);
|
9
|
+
static VALUE method_divide(VALUE self, VALUE obj);
|
10
|
+
static VALUE method_add(VALUE self, VALUE obj);
|
11
|
+
static VALUE method_subtract(VALUE self, VALUE obj);
|
21
12
|
static VALUE method_length(VALUE self);
|
22
13
|
static VALUE method_to_a(VALUE self);
|
14
|
+
|
15
|
+
static d2v_t *internal_allocate_vector_array(unsigned long size);
|
16
|
+
static int internal_align_vectors(unsigned long v1, unsigned long v2);
|
17
|
+
static VALUE internal_apply_operation(VALUE self, VALUE obj, b_operation func);
|
18
|
+
|
19
|
+
static d2v func_multiply(d2v v1, d2v v2);
|
20
|
+
static d2v func_divide(d2v v1, d2v v2);
|
21
|
+
static d2v func_add(d2v v1, d2v v2);
|
22
|
+
static d2v func_subtract(d2v v1, d2v v2);
|
@@ -0,0 +1,20 @@
|
|
1
|
+
/*
|
2
|
+
* Types for FloatArray
|
3
|
+
*
|
4
|
+
* Since ruby internally uses doubles for the Float type, SIMD::FloatArray will
|
5
|
+
* use packed double operations by default.
|
6
|
+
*/
|
7
|
+
typedef double __attribute__ ((vector_size (16))) d2v;
|
8
|
+
typedef union d2v_t
|
9
|
+
{
|
10
|
+
d2v v;
|
11
|
+
double f[2];
|
12
|
+
} d2v_t;
|
13
|
+
|
14
|
+
typedef struct d2v_container
|
15
|
+
{
|
16
|
+
d2v_t *data;
|
17
|
+
unsigned long len;
|
18
|
+
} d2v_container;
|
19
|
+
|
20
|
+
typedef d2v (*b_operation)(d2v v1, d2v v2);
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: simd
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tina Wuest
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-12-
|
11
|
+
date: 2014-12-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake-compiler
|
@@ -36,6 +36,7 @@ files:
|
|
36
36
|
- ext/simd/simd.h
|
37
37
|
- ext/simd/simd_floatarray.c
|
38
38
|
- ext/simd/simd_floatarray.h
|
39
|
+
- ext/simd/simd_types.h
|
39
40
|
homepage: https://gitlab.com/wuest/simd-ruby
|
40
41
|
licenses: []
|
41
42
|
metadata: {}
|