simd 0.1.0 → 0.2.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.c +1 -0
- data/ext/simd/simd.h +1 -0
- data/ext/simd/simd_common.c +76 -0
- data/ext/simd/simd_common.h +12 -0
- data/ext/simd/simd_floatarray.c +34 -96
- data/ext/simd/simd_floatarray.h +5 -2
- data/ext/simd/simd_smallfloatarray.c +173 -0
- data/ext/simd/simd_smallfloatarray.h +25 -0
- data/ext/simd/simd_types.h +20 -3
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3acc0dcd98951246c84b35036f47dedd69d798cb
|
4
|
+
data.tar.gz: 323dbca8597e5993d0bd48ebb8805febdf064c47
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e05f61501a47ad89bf55a6a25fcda70add8aa004701336e0543c4421ca0b4a9628aab30281e0aa9c30bb79a994fad2152c7da853dc6989adea400a79c9ada05c
|
7
|
+
data.tar.gz: 45f06b3ead4a140d992f34c2135724f649143e58035945e9e8f8de9e0595b8fda54538cab233a494ddcb0eb1e6e1a6d0f5948084b6e29e91d461c34d901eb8ef
|
data/ext/simd/simd.c
CHANGED
data/ext/simd/simd.h
CHANGED
@@ -0,0 +1,76 @@
|
|
1
|
+
#include "simd_common.h"
|
2
|
+
|
3
|
+
/* Internal: Allocate memory for the vector container. */
|
4
|
+
VALUE allocate(VALUE klass)
|
5
|
+
{
|
6
|
+
vector_t *vector = malloc(sizeof(vector_t));
|
7
|
+
if(vector == NULL)
|
8
|
+
{
|
9
|
+
rb_raise(rb_eNoMemError, "Unable to allocate memory");
|
10
|
+
}
|
11
|
+
|
12
|
+
vector->data = NULL; /* Avoid potentially freeing unitialized memory. */
|
13
|
+
return(Data_Wrap_Struct(klass, NULL, deallocate, vector));
|
14
|
+
}
|
15
|
+
|
16
|
+
/* Internal: Free memory from the vector container and the data array. */
|
17
|
+
void deallocate(vector_t *vector)
|
18
|
+
{
|
19
|
+
if(vector)
|
20
|
+
{
|
21
|
+
if(vector->data)
|
22
|
+
{
|
23
|
+
free(vector->data);
|
24
|
+
}
|
25
|
+
free(vector);
|
26
|
+
}
|
27
|
+
}
|
28
|
+
|
29
|
+
/* Public: Return the number of elements in the Array. */
|
30
|
+
VALUE method_length(VALUE self)
|
31
|
+
{
|
32
|
+
vector_t *vector;
|
33
|
+
Data_Get_Struct(self, vector_t, vector);
|
34
|
+
|
35
|
+
return(INT2NUM(vector->len));
|
36
|
+
}
|
37
|
+
|
38
|
+
/* Internal: Allocate memory for the data array. */
|
39
|
+
void *internal_allocate_vector_array(unsigned long count, size_t size)
|
40
|
+
{
|
41
|
+
unsigned int modulo = 16 / size;
|
42
|
+
void *vector = malloc(((count + (count % modulo)) / modulo + 1) * size);
|
43
|
+
if(vector == NULL)
|
44
|
+
{
|
45
|
+
rb_raise(rb_eNoMemError, "Unable to allocate memory");
|
46
|
+
}
|
47
|
+
|
48
|
+
return(vector);
|
49
|
+
}
|
50
|
+
|
51
|
+
/* Internal: Determine if two arrays can be acted upon, by being of equal
|
52
|
+
* lengths or with the operand's length being a multiple of the data array's. */
|
53
|
+
int internal_align_vectors(unsigned long v1, unsigned long v2, unsigned int modulo)
|
54
|
+
{
|
55
|
+
if((v1 % modulo) != (v2 % modulo))
|
56
|
+
{
|
57
|
+
rb_raise(rb_eArgError, "Both Vectors must be of even or odd length.");
|
58
|
+
}
|
59
|
+
|
60
|
+
if(v1 == v2)
|
61
|
+
{
|
62
|
+
return(0);
|
63
|
+
}
|
64
|
+
if(v2 == modulo)
|
65
|
+
{
|
66
|
+
return(1);
|
67
|
+
}
|
68
|
+
if(v1 % v2 == 0 && v2 % modulo == 0)
|
69
|
+
{
|
70
|
+
return(2);
|
71
|
+
}
|
72
|
+
|
73
|
+
rb_raise(rb_eArgError, "Vector lengths misaligned.");
|
74
|
+
/* Never reached */
|
75
|
+
return(-1);
|
76
|
+
}
|
@@ -0,0 +1,12 @@
|
|
1
|
+
#pragma once
|
2
|
+
|
3
|
+
#include "ruby.h"
|
4
|
+
#include "simd_types.h"
|
5
|
+
|
6
|
+
VALUE allocate(VALUE klass);
|
7
|
+
void deallocate(vector_t *vector);
|
8
|
+
|
9
|
+
VALUE method_length(VALUE self);
|
10
|
+
|
11
|
+
void *internal_allocate_vector_array(unsigned long count, size_t size);
|
12
|
+
int internal_align_vectors(unsigned long v1, unsigned long v2, unsigned int modulo);
|
data/ext/simd/simd_floatarray.c
CHANGED
@@ -16,59 +16,37 @@ void Init_SIMD_FloatArray(VALUE parent)
|
|
16
16
|
rb_define_method(SIMD_FloatArray, "to_a", method_to_a, 0);
|
17
17
|
}
|
18
18
|
|
19
|
-
/* Internal: Allocate memory for the vector container. */
|
20
|
-
static VALUE allocate(VALUE klass)
|
21
|
-
{
|
22
|
-
d2v_container *vector = malloc(sizeof(d2v_container));
|
23
|
-
if(vector == NULL)
|
24
|
-
{
|
25
|
-
rb_raise(rb_eNoMemError, "Unable to allocate memory");
|
26
|
-
}
|
27
|
-
|
28
|
-
vector->data = NULL; /* Avoid potentially freeing unitialized memory. */
|
29
|
-
return(Data_Wrap_Struct(klass, NULL, deallocate, vector));
|
30
|
-
}
|
31
|
-
|
32
|
-
/* Internal: Free memory from the vector container and the data array. */
|
33
|
-
static void deallocate(d2v_container *vector)
|
34
|
-
{
|
35
|
-
if(vector)
|
36
|
-
{
|
37
|
-
if(vector->data)
|
38
|
-
{
|
39
|
-
free(vector->data);
|
40
|
-
}
|
41
|
-
free(vector);
|
42
|
-
}
|
43
|
-
}
|
44
|
-
|
45
19
|
/* Public: Initialize the FloatArray object given a Ruby Array of values
|
46
20
|
* which can be cast to a double. */
|
47
21
|
static VALUE method_initialize(VALUE self, VALUE rb_array)
|
48
22
|
{
|
49
|
-
|
23
|
+
vector_t *vector;
|
24
|
+
d2v_t *data;
|
50
25
|
unsigned long n,m,i;
|
51
26
|
|
52
27
|
Check_Type(rb_array, T_ARRAY);
|
53
|
-
Data_Get_Struct(self,
|
28
|
+
Data_Get_Struct(self, vector_t, vector);
|
54
29
|
|
55
30
|
vector->len = n = RARRAY_LEN(rb_array);
|
56
31
|
|
57
32
|
if(vector->len < 2)
|
58
33
|
{
|
59
|
-
rb_raise(rb_eArgError, "Vectors must be at least
|
34
|
+
rb_raise(rb_eArgError, "Vectors must be at least 4 long");
|
60
35
|
}
|
61
36
|
|
62
|
-
vector->data = internal_allocate_vector_array(vector->len);
|
37
|
+
vector->data = internal_allocate_vector_array(vector->len, sizeof(d2v_t));
|
63
38
|
|
64
|
-
|
65
|
-
|
39
|
+
data = (d2v_t *)vector->data;
|
40
|
+
for(i = 0; i < vector->len; i++)
|
41
|
+
{
|
42
|
+
data[i/2].f[i%2] = NUM2DBL(rb_ary_entry(rb_array, i));
|
43
|
+
}
|
66
44
|
|
67
45
|
/* If the array is an odd number of elements, set the final element to 1 */
|
68
46
|
m = n + (n % 2);
|
69
|
-
|
47
|
+
for(i = n % 4; i > 0; i--)
|
70
48
|
{
|
71
|
-
|
49
|
+
data[m/2].f[1] = 1.0;
|
72
50
|
}
|
73
51
|
|
74
52
|
return(self);
|
@@ -102,26 +80,19 @@ static VALUE method_subtract(VALUE self, VALUE obj)
|
|
102
80
|
return(internal_apply_operation(self, obj, func_subtract));
|
103
81
|
}
|
104
82
|
|
105
|
-
/* Public: Return the number of elements in the Array. */
|
106
|
-
static VALUE method_length(VALUE self)
|
107
|
-
{
|
108
|
-
d2v_container *vector;
|
109
|
-
Data_Get_Struct(self, d2v_container, vector);
|
110
|
-
|
111
|
-
return(INT2NUM(vector->len));
|
112
|
-
}
|
113
|
-
|
114
83
|
/* Public: Return a Ruby Array containing the doubles within the data array. */
|
115
84
|
static VALUE method_to_a(VALUE self)
|
116
85
|
{
|
117
86
|
unsigned long i;
|
118
|
-
|
87
|
+
vector_t *vector;
|
88
|
+
d2v_t *data;
|
119
89
|
VALUE rb_array = rb_ary_new();
|
120
90
|
|
121
|
-
Data_Get_Struct(self,
|
91
|
+
Data_Get_Struct(self, vector_t, vector);
|
92
|
+
data = (d2v_t *)vector->data;
|
122
93
|
for(i = 0; i < vector->len; i++)
|
123
94
|
{
|
124
|
-
rb_ary_store(rb_array, i, DBL2NUM(
|
95
|
+
rb_ary_store(rb_array, i, DBL2NUM(data[i/2].f[i%2]));
|
125
96
|
}
|
126
97
|
|
127
98
|
return(rb_array);
|
@@ -133,83 +104,50 @@ static VALUE internal_apply_operation(VALUE self, VALUE obj, b_operation func)
|
|
133
104
|
{
|
134
105
|
unsigned long size, i;
|
135
106
|
int align;
|
136
|
-
|
107
|
+
vector_t *v1, *v2, *rv;
|
108
|
+
d2v_t *d1, *d2, *r;
|
137
109
|
VALUE result_obj = allocate(SIMD_FloatArray);
|
138
110
|
|
139
|
-
Data_Get_Struct(self,
|
140
|
-
Data_Get_Struct(obj,
|
141
|
-
Data_Get_Struct(result_obj,
|
111
|
+
Data_Get_Struct(self, vector_t, v1);
|
112
|
+
Data_Get_Struct(obj, vector_t, v2);
|
113
|
+
Data_Get_Struct(result_obj, vector_t, rv);
|
114
|
+
rv->data = internal_allocate_vector_array(v1->len, sizeof(d2v_t));
|
142
115
|
|
143
|
-
align = internal_align_vectors(v1->len, v2->len);
|
116
|
+
align = internal_align_vectors(v1->len, v2->len, 2);
|
144
117
|
|
145
|
-
/* Ensure that size will be the result of ceil(len /
|
118
|
+
/* Ensure that size will be the result of ceil(len / 4.0) */
|
146
119
|
size = (v1->len + 1) / 2;
|
147
|
-
|
148
|
-
|
120
|
+
|
121
|
+
d1 = (d2v_t *)v1->data;
|
122
|
+
d2 = (d2v_t *)v2->data;
|
123
|
+
r = (d2v_t *)rv->data;
|
124
|
+
|
125
|
+
rv->len = v1->len;
|
149
126
|
|
150
127
|
switch(align)
|
151
128
|
{
|
152
129
|
case 0: /* Same size arrays */
|
153
130
|
for(i = 0; i < size; i++)
|
154
131
|
{
|
155
|
-
r
|
132
|
+
r[i].v = func(d1[i].v, d2[i].v);
|
156
133
|
}
|
157
134
|
break;
|
158
135
|
case 1: /* Operand is exactly 2 long (size of 1 sse register) */
|
159
136
|
for(i = 0; i < size; i++)
|
160
137
|
{
|
161
|
-
r
|
138
|
+
r[i].v = func(d1[i].v, d2[0].v);
|
162
139
|
}
|
163
140
|
break;
|
164
141
|
default: /* Self is a multiple of operand's length long */
|
165
142
|
for(i = 0; i < size; i++)
|
166
143
|
{
|
167
|
-
r
|
144
|
+
r[i].v = func(d1[i].v, d2[i % v2->len].v);
|
168
145
|
}
|
169
146
|
}
|
170
147
|
|
171
148
|
return(result_obj);
|
172
149
|
}
|
173
150
|
|
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
151
|
/* Function: Multiply two vectors. */
|
214
152
|
static d2v func_multiply(d2v v1, d2v v2)
|
215
153
|
{
|
data/ext/simd/simd_floatarray.h
CHANGED
@@ -1,19 +1,22 @@
|
|
1
1
|
#include "ruby.h"
|
2
|
-
#include "
|
2
|
+
#include "simd_common.h"
|
3
3
|
|
4
|
+
/*
|
4
5
|
static VALUE allocate(VALUE klass);
|
5
6
|
static void deallocate(d2v_container *floatarray);
|
7
|
+
*/
|
6
8
|
|
7
9
|
static VALUE method_initialize(VALUE self, VALUE rb_array);
|
8
10
|
static VALUE method_multiply(VALUE self, VALUE obj);
|
9
11
|
static VALUE method_divide(VALUE self, VALUE obj);
|
10
12
|
static VALUE method_add(VALUE self, VALUE obj);
|
11
13
|
static VALUE method_subtract(VALUE self, VALUE obj);
|
12
|
-
static VALUE method_length(VALUE self);
|
13
14
|
static VALUE method_to_a(VALUE self);
|
14
15
|
|
16
|
+
/*
|
15
17
|
static d2v_t *internal_allocate_vector_array(unsigned long size);
|
16
18
|
static int internal_align_vectors(unsigned long v1, unsigned long v2);
|
19
|
+
*/
|
17
20
|
static VALUE internal_apply_operation(VALUE self, VALUE obj, b_operation func);
|
18
21
|
|
19
22
|
static d2v func_multiply(d2v v1, d2v v2);
|
@@ -0,0 +1,173 @@
|
|
1
|
+
#include "simd_smallfloatarray.h"
|
2
|
+
|
3
|
+
VALUE SIMD_SmallFloatArray = Qnil;
|
4
|
+
|
5
|
+
/* Internal: Create the SIMD::FloatArray class. */
|
6
|
+
void Init_SIMD_SmallFloatArray(VALUE parent)
|
7
|
+
{
|
8
|
+
SIMD_SmallFloatArray = rb_define_class_under(parent, "SmallFloatArray", rb_cObject);
|
9
|
+
rb_define_alloc_func(SIMD_SmallFloatArray, allocate);
|
10
|
+
rb_define_method(SIMD_SmallFloatArray, "initialize", method_initialize, 1);
|
11
|
+
rb_define_method(SIMD_SmallFloatArray, "*", method_multiply, 1);
|
12
|
+
rb_define_method(SIMD_SmallFloatArray, "/", method_divide, 1);
|
13
|
+
rb_define_method(SIMD_SmallFloatArray, "+", method_add, 1);
|
14
|
+
rb_define_method(SIMD_SmallFloatArray, "-", method_subtract, 1);
|
15
|
+
rb_define_method(SIMD_SmallFloatArray, "length", method_length, 0);
|
16
|
+
rb_define_method(SIMD_SmallFloatArray, "to_a", method_to_a, 0);
|
17
|
+
}
|
18
|
+
|
19
|
+
/* Public: Initialize the FloatArray object given a Ruby Array of values
|
20
|
+
* which can be cast to a double. */
|
21
|
+
static VALUE method_initialize(VALUE self, VALUE rb_array)
|
22
|
+
{
|
23
|
+
vector_t *vector;
|
24
|
+
f4v_t *data;
|
25
|
+
unsigned long n,m,i;
|
26
|
+
|
27
|
+
Check_Type(rb_array, T_ARRAY);
|
28
|
+
Data_Get_Struct(self, vector_t, vector);
|
29
|
+
|
30
|
+
vector->len = n = RARRAY_LEN(rb_array);
|
31
|
+
|
32
|
+
if(vector->len < 4)
|
33
|
+
{
|
34
|
+
rb_raise(rb_eArgError, "Vectors must be at least 4 long");
|
35
|
+
}
|
36
|
+
|
37
|
+
vector->data = internal_allocate_vector_array(vector->len, sizeof(f4v_t));
|
38
|
+
|
39
|
+
data = (f4v_t *)vector->data;
|
40
|
+
for(i = 0; i < vector->len; i++)
|
41
|
+
{
|
42
|
+
data[i/4].f[i%4] = (float)NUM2DBL(rb_ary_entry(rb_array, i));
|
43
|
+
}
|
44
|
+
|
45
|
+
/* If the array is an odd number of elements, set the final element to 1 */
|
46
|
+
m = n + (n % 4);
|
47
|
+
for(i = n % 4; i > 0; i--)
|
48
|
+
{
|
49
|
+
data[m/4].f[i] = 1.0;
|
50
|
+
}
|
51
|
+
|
52
|
+
return(self);
|
53
|
+
}
|
54
|
+
|
55
|
+
/* Public: Multiply values contained in the data array with those contained in
|
56
|
+
* another FloatArray object, returning a new FloatArray. */
|
57
|
+
static VALUE method_multiply(VALUE self, VALUE obj)
|
58
|
+
{
|
59
|
+
return(internal_apply_operation(self, obj, func_multiply));
|
60
|
+
}
|
61
|
+
|
62
|
+
/* Public: Divide values contained in the data array by those contained in
|
63
|
+
* another FloatArray object, returning a new FloatArray. */
|
64
|
+
static VALUE method_divide(VALUE self, VALUE obj)
|
65
|
+
{
|
66
|
+
return(internal_apply_operation(self, obj, func_divide));
|
67
|
+
}
|
68
|
+
|
69
|
+
/* Public: add values contained in the data array with those contained in
|
70
|
+
* another FloatArray object, returning a new FloatArray. */
|
71
|
+
static VALUE method_add(VALUE self, VALUE obj)
|
72
|
+
{
|
73
|
+
return(internal_apply_operation(self, obj, func_add));
|
74
|
+
}
|
75
|
+
|
76
|
+
/* Public: Subtract values contained in another FloatArray object from those
|
77
|
+
* contained in the current data array object, returning a new FloatArray. */
|
78
|
+
static VALUE method_subtract(VALUE self, VALUE obj)
|
79
|
+
{
|
80
|
+
return(internal_apply_operation(self, obj, func_subtract));
|
81
|
+
}
|
82
|
+
|
83
|
+
/* Public: Return a Ruby Array containing the doubles within the data array. */
|
84
|
+
static VALUE method_to_a(VALUE self)
|
85
|
+
{
|
86
|
+
unsigned long i;
|
87
|
+
vector_t *vector;
|
88
|
+
f4v_t *data;
|
89
|
+
VALUE rb_array = rb_ary_new();
|
90
|
+
|
91
|
+
Data_Get_Struct(self, vector_t, vector);
|
92
|
+
data = (f4v_t *)vector->data;
|
93
|
+
for(i = 0; i < vector->len; i++)
|
94
|
+
{
|
95
|
+
rb_ary_store(rb_array, i, DBL2NUM(data[i/4].f[i%4]));
|
96
|
+
}
|
97
|
+
|
98
|
+
return(rb_array);
|
99
|
+
}
|
100
|
+
|
101
|
+
/* Internal: Given another FloatArray object, perform an action specified via a
|
102
|
+
* function pointer against both. */
|
103
|
+
static VALUE internal_apply_operation(VALUE self, VALUE obj, bf_operation func)
|
104
|
+
{
|
105
|
+
unsigned long size, i;
|
106
|
+
int align;
|
107
|
+
vector_t *v1, *v2, *rv;
|
108
|
+
f4v_t *d1, *d2, *r;
|
109
|
+
VALUE result_obj = allocate(SIMD_SmallFloatArray);
|
110
|
+
|
111
|
+
Data_Get_Struct(self, vector_t, v1);
|
112
|
+
Data_Get_Struct(obj, vector_t, v2);
|
113
|
+
Data_Get_Struct(result_obj, vector_t, rv);
|
114
|
+
rv->data = internal_allocate_vector_array(v1->len, sizeof(f4v_t));
|
115
|
+
|
116
|
+
align = internal_align_vectors(v1->len, v2->len, 4);
|
117
|
+
|
118
|
+
/* Ensure that size will be the result of ceil(len / 4.0) */
|
119
|
+
size = (v1->len + 3) / 4;
|
120
|
+
|
121
|
+
d1 = (f4v_t *)v1->data;
|
122
|
+
d2 = (f4v_t *)v2->data;
|
123
|
+
r = (f4v_t *)rv->data;
|
124
|
+
|
125
|
+
rv->len = v1->len;
|
126
|
+
|
127
|
+
switch(align)
|
128
|
+
{
|
129
|
+
case 0: /* Same size arrays */
|
130
|
+
for(i = 0; i < size; i++)
|
131
|
+
{
|
132
|
+
r[i].v = func(d1[i].v, d2[i].v);
|
133
|
+
}
|
134
|
+
break;
|
135
|
+
case 1: /* Operand is exactly 4 long (size of 1 sse register) */
|
136
|
+
for(i = 0; i < size; i++)
|
137
|
+
{
|
138
|
+
r[i].v = func(d1[i].v, d2[0].v);
|
139
|
+
}
|
140
|
+
break;
|
141
|
+
default: /* Self is a multiple of operand's length long */
|
142
|
+
for(i = 0; i < size; i++)
|
143
|
+
{
|
144
|
+
r[i].v = func(d1[i].v, d2[i % v2->len].v);
|
145
|
+
}
|
146
|
+
}
|
147
|
+
|
148
|
+
return(result_obj);
|
149
|
+
}
|
150
|
+
|
151
|
+
/* Function: Multiply two vectors. */
|
152
|
+
static f4v func_multiply(f4v v1, f4v v2)
|
153
|
+
{
|
154
|
+
return(v1 * v2);
|
155
|
+
}
|
156
|
+
|
157
|
+
/* Function: Divide two vectors. */
|
158
|
+
static f4v func_divide(f4v v1, f4v v2)
|
159
|
+
{
|
160
|
+
return(v1 / v2);
|
161
|
+
}
|
162
|
+
|
163
|
+
/* Function: Add two vectors. */
|
164
|
+
static f4v func_add(f4v v1, f4v v2)
|
165
|
+
{
|
166
|
+
return(v1 + v2);
|
167
|
+
}
|
168
|
+
|
169
|
+
/* Function: Subtract two vectors. */
|
170
|
+
static f4v func_subtract(f4v v1, f4v v2)
|
171
|
+
{
|
172
|
+
return(v1 - v2);
|
173
|
+
}
|
@@ -0,0 +1,25 @@
|
|
1
|
+
#include "ruby.h"
|
2
|
+
#include "simd_common.h"
|
3
|
+
|
4
|
+
/*
|
5
|
+
static VALUE allocate(VALUE klass);
|
6
|
+
static void deallocate(vector_t *vector);
|
7
|
+
*/
|
8
|
+
|
9
|
+
static VALUE method_initialize(VALUE self, VALUE rb_array);
|
10
|
+
static VALUE method_multiply(VALUE self, VALUE obj);
|
11
|
+
static VALUE method_divide(VALUE self, VALUE obj);
|
12
|
+
static VALUE method_add(VALUE self, VALUE obj);
|
13
|
+
static VALUE method_subtract(VALUE self, VALUE obj);
|
14
|
+
static VALUE method_to_a(VALUE self);
|
15
|
+
|
16
|
+
/*
|
17
|
+
static f4v_t *internal_allocate_vector_array(unsigned long size);
|
18
|
+
static int internal_align_vectors(unsigned long v1, unsigned long v2);
|
19
|
+
*/
|
20
|
+
static VALUE internal_apply_operation(VALUE self, VALUE obj, bf_operation func);
|
21
|
+
|
22
|
+
static f4v func_multiply(f4v v1, f4v v2);
|
23
|
+
static f4v func_divide(f4v v1, f4v v2);
|
24
|
+
static f4v func_add(f4v v1, f4v v2);
|
25
|
+
static f4v func_subtract(f4v v1, f4v v2);
|
data/ext/simd/simd_types.h
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
#pragma once
|
2
|
+
|
1
3
|
/*
|
2
4
|
* Types for FloatArray
|
3
5
|
*
|
@@ -11,10 +13,25 @@ typedef union d2v_t
|
|
11
13
|
double f[2];
|
12
14
|
} d2v_t;
|
13
15
|
|
14
|
-
|
16
|
+
/*
|
17
|
+
* Types for SmallFloatArray
|
18
|
+
*
|
19
|
+
* Since ruby internally uses doubles for the Float type, SIMD::SmallFloatArray
|
20
|
+
* provides reduced-size floats for faster operation when it's known that the
|
21
|
+
* lack of precision and range will not be a detriment.
|
22
|
+
*/
|
23
|
+
typedef float __attribute__ ((vector_size (16))) f4v;
|
24
|
+
typedef union f4v_t
|
25
|
+
{
|
26
|
+
f4v v;
|
27
|
+
float f[4];
|
28
|
+
} f4v_t;
|
29
|
+
|
30
|
+
typedef struct vector_t
|
15
31
|
{
|
16
|
-
|
32
|
+
void *data;
|
17
33
|
unsigned long len;
|
18
|
-
}
|
34
|
+
} vector_t;
|
19
35
|
|
20
36
|
typedef d2v (*b_operation)(d2v v1, d2v v2);
|
37
|
+
typedef f4v (*bf_operation)(f4v v1, f4v 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.
|
4
|
+
version: 0.2.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-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake-compiler
|
@@ -34,8 +34,12 @@ files:
|
|
34
34
|
- ext/simd/extconf.rb
|
35
35
|
- ext/simd/simd.c
|
36
36
|
- ext/simd/simd.h
|
37
|
+
- ext/simd/simd_common.c
|
38
|
+
- ext/simd/simd_common.h
|
37
39
|
- ext/simd/simd_floatarray.c
|
38
40
|
- ext/simd/simd_floatarray.h
|
41
|
+
- ext/simd/simd_smallfloatarray.c
|
42
|
+
- ext/simd/simd_smallfloatarray.h
|
39
43
|
- ext/simd/simd_types.h
|
40
44
|
homepage: https://gitlab.com/wuest/simd-ruby
|
41
45
|
licenses: []
|