numerix 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -0
  3. data/.travis.yml +5 -0
  4. data/.yardopts +5 -0
  5. data/CODE_OF_CONDUCT.md +74 -0
  6. data/Gemfile +6 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.md +66 -0
  9. data/Rakefile +18 -0
  10. data/TODO.txt +25 -0
  11. data/bin/console +14 -0
  12. data/bin/setup +8 -0
  13. data/ext/numerix/common.h +107 -0
  14. data/ext/numerix/extconf.rb +3 -0
  15. data/ext/numerix/matrix3x2.c +638 -0
  16. data/ext/numerix/matrix3x2.h +52 -0
  17. data/ext/numerix/matrix4x4.c +1807 -0
  18. data/ext/numerix/matrix4x4.h +90 -0
  19. data/ext/numerix/matrix_base.c +307 -0
  20. data/ext/numerix/matrix_base.h +70 -0
  21. data/ext/numerix/numerix.c +33 -0
  22. data/ext/numerix/numerix.h +19 -0
  23. data/ext/numerix/plane.c +311 -0
  24. data/ext/numerix/plane.h +34 -0
  25. data/ext/numerix/quaternion.c +712 -0
  26. data/ext/numerix/quaternion.h +53 -0
  27. data/ext/numerix/structure.c +154 -0
  28. data/ext/numerix/structure.h +24 -0
  29. data/ext/numerix/vector.c +326 -0
  30. data/ext/numerix/vector.h +57 -0
  31. data/ext/numerix/vector2.c +641 -0
  32. data/ext/numerix/vector2.h +64 -0
  33. data/ext/numerix/vector3.c +805 -0
  34. data/ext/numerix/vector3.h +68 -0
  35. data/ext/numerix/vector4.c +727 -0
  36. data/ext/numerix/vector4.h +63 -0
  37. data/ext/numerix/vector_base.c +94 -0
  38. data/ext/numerix/vector_base.h +30 -0
  39. data/extra/numerix128.png +0 -0
  40. data/extra/numerix24.png +0 -0
  41. data/extra/numerix32.png +0 -0
  42. data/extra/numerix320.png +0 -0
  43. data/extra/numerix48.png +0 -0
  44. data/extra/numerix96.png +0 -0
  45. data/lib/numerix/error.rb +36 -0
  46. data/lib/numerix/matrix3x2.rb +420 -0
  47. data/lib/numerix/matrix4x4.rb +676 -0
  48. data/lib/numerix/matrix_base.rb +14 -0
  49. data/lib/numerix/plane.rb +154 -0
  50. data/lib/numerix/quaternion.rb +355 -0
  51. data/lib/numerix/structure.rb +124 -0
  52. data/lib/numerix/vector.rb +13 -0
  53. data/lib/numerix/vector2.rb +534 -0
  54. data/lib/numerix/vector3.rb +572 -0
  55. data/lib/numerix/vector4.rb +551 -0
  56. data/lib/numerix/vector_base.rb +14 -0
  57. data/lib/numerix/version.rb +6 -0
  58. data/lib/numerix.rb +10 -0
  59. data/numerix.gemspec +30 -0
  60. metadata +167 -0
@@ -0,0 +1,53 @@
1
+ #ifndef NUMERIX_QUATERNION_H
2
+ #define NUMERIX_QUATERNION_H 1
3
+
4
+ #include "common.h"
5
+ #include "vector_base.h"
6
+
7
+ #define QUATERNION() \
8
+ Quaternion *q; \
9
+ Data_Get_Struct(self, Quaternion, q);
10
+
11
+ void Init_quaternion(VALUE outer);
12
+ VALUE rb_quaternion_alloc(VALUE klass);
13
+ VALUE rb_quaternion_initialize(int argc, VALUE *argv, VALUE self);
14
+
15
+ // Instance
16
+ VALUE rb_quaternion_identity_p(VALUE self);
17
+ VALUE rb_quaternion_length(VALUE self);
18
+ VALUE rb_quaternion_length_squared(VALUE self);
19
+ VALUE rb_quaternion_negate(VALUE self);
20
+ VALUE rb_quaternion_add(VALUE self, VALUE other);
21
+ VALUE rb_quaternion_subtract(VALUE self, VALUE other);
22
+ VALUE rb_quaternion_multiply(VALUE self, VALUE other);
23
+ VALUE rb_quaternion_divide(VALUE self, VALUE other);
24
+ VALUE rb_quaternion_equal(VALUE self, VALUE other);
25
+ VALUE rb_quaternion_normalize(VALUE self);
26
+ VALUE rb_quaternion_normalize_bang(VALUE self);
27
+ VALUE rb_quaternion_conjugate(VALUE self);
28
+ VALUE rb_quaternion_conjugate_bang(VALUE self);
29
+ VALUE rb_quaternion_inverse(VALUE self);
30
+ VALUE rb_quaternion_dot(VALUE self, VALUE other);
31
+ VALUE rb_quaternion_concatenate(VALUE self, VALUE other);
32
+ VALUE rb_quaternion_concatenate_bang(VALUE self, VALUE other);
33
+ VALUE rb_quaternion_lerp(VALUE self, VALUE other, VALUE amount);
34
+ VALUE rb_quaternion_lerp_bang(VALUE self, VALUE other, VALUE amount);
35
+ VALUE rb_quaternion_slerp(VALUE self, VALUE other, VALUE amount);
36
+ VALUE rb_quaternion_slerp_bang(VALUE self, VALUE other, VALUE amount);
37
+
38
+ // Conversion
39
+ VALUE rb_quaternion_to_s(VALUE self);
40
+ VALUE rb_quaternion_to_a(VALUE self);
41
+ VALUE rb_quaternion_to_h(VALUE self);
42
+ VALUE rb_quaternion_to_vec4(VALUE self);
43
+
44
+ // Class
45
+ VALUE rb_quaternion_identity(VALUE klass);
46
+ VALUE rb_quaternion_from_axis_angle(VALUE klass, VALUE vec3, VALUE angle);
47
+ VALUE rb_quaternion_from_yaw_pitch_roll(VALUE klass, VALUE yaw, VALUE pitch, VALUE roll);
48
+ VALUE rb_quaternion_from_rotation_matrix(VALUE klass, VALUE matrix);
49
+
50
+ static inline VALUE rb_quaternion_slerp_s(VALUE klass, VALUE quaternion1, VALUE quaternion2, VALUE amount);
51
+ static inline VALUE rb_quaternion_lerp_s(VALUE klass, VALUE quaternion1, VALUE quaternion2, VALUE amount);
52
+
53
+ #endif /* NUMERIX_QUATERNION_H */
@@ -0,0 +1,154 @@
1
+
2
+ #include "structure.h"
3
+
4
+ VALUE rb_cNumerixStruct;
5
+
6
+ #if RUBY_API_VERSION_MAJOR >= 2
7
+ VALUE rb_numerix_cFiddlePointer;
8
+ #endif
9
+
10
+ void Init_numerix_structure(VALUE outer) {
11
+ rb_cNumerixStruct = rb_define_class_under(outer, "Structure", rb_cObject);
12
+ rb_define_method(rb_cNumerixStruct, "initialize", rb_numerix_abstract_initialize, 0);
13
+
14
+ rb_define_method(rb_cNumerixStruct, "dup", rb_numerix_dup, 0);
15
+ rb_define_method(rb_cNumerixStruct, "address", rb_numerix_address, 0);
16
+ rb_define_method(rb_cNumerixStruct, "_dump", rb_numerix_dump, -1);
17
+ rb_define_method(rb_cNumerixStruct, "[]", rb_numerix_aref, 1);
18
+ rb_define_method(rb_cNumerixStruct, "[]=", rb_numerix_aset, 2);
19
+ rb_define_method(rb_cNumerixStruct, "each", rb_numerix_each, 0);
20
+
21
+ rb_define_singleton_method(rb_cNumerixStruct, "size", rb_numerix_size, 0);
22
+ rb_define_singleton_method(rb_cNumerixStruct, "_load", rb_numerix_load, 1);
23
+ rb_define_singleton_method(rb_cNumerixStruct, "unpack", rb_numerix_load, 1);
24
+
25
+ rb_define_alias(rb_cNumerixStruct, "pack", "_dump");
26
+
27
+ #if RUBY_API_VERSION_MAJOR >= 2
28
+ rb_require("fiddle");
29
+ VALUE fiddle = rb_const_get(rb_cObject, rb_intern("Fiddle"));
30
+ rb_numerix_cFiddlePointer = rb_const_get(fiddle, rb_intern("Pointer"));
31
+ rb_define_method(rb_cNumerixStruct, "ptr", rb_numerix_fiddle_ptr, 0);
32
+ #endif
33
+ }
34
+
35
+ #if RUBY_API_VERSION_MAJOR >= 2
36
+
37
+ VALUE rb_numerix_fiddle_ptr(VALUE self) {
38
+ // Get basic data about the struct
39
+ struct RData *rdata = RDATA(self);
40
+ VALUE *args = xmalloc(sizeof(VALUE) * 2);
41
+ // Set the platform pointer-size address
42
+ #if SIZEOF_INTPTR_T == 4
43
+ args[0] = LONG2NUM((long)rdata->data);
44
+ #elif SIZEOF_INTPTR_T == 8
45
+ args[0] = LL2NUM((long long)rdata->data);
46
+ #else
47
+ args[0] = INT2NUM(0);
48
+ #endif
49
+ // Get size of structure
50
+ int size = rb_numerix_isize(rdata->basic.klass);
51
+ args[1] = INT2NUM(size);
52
+ VALUE ptr = rb_class_new_instance(2, args, rb_numerix_cFiddlePointer);
53
+ xfree(args);
54
+ return ptr;
55
+ }
56
+
57
+ #endif
58
+
59
+ VALUE rb_numerix_each(VALUE self) {
60
+ struct RData *rdata = RDATA(self);
61
+ int count = rb_numerix_isize(rdata->basic.klass) / sizeof(float);
62
+
63
+ volatile VALUE str = self;
64
+
65
+ RETURN_SIZED_ENUMERATOR(str, 0, 0, count);
66
+
67
+ float *flt = (float *)rdata->data;
68
+ for (int i = 0; i < count; i++)
69
+ rb_yield(DBL2NUM(flt[i]));
70
+
71
+ return str;
72
+ }
73
+
74
+ VALUE rb_numerix_aref(VALUE self, VALUE index) {
75
+ struct RData *rdata = RDATA(self);
76
+ int max = rb_numerix_isize(rdata->basic.klass) / sizeof(float);
77
+ int i = NUM2INT(index);
78
+
79
+ if (i < 0 || i >= max)
80
+ return Qnil;
81
+
82
+ float *flt = (float *)rdata->data;
83
+ return DBL2NUM(flt[i]);
84
+ }
85
+
86
+ VALUE rb_numerix_aset(VALUE self, VALUE index, VALUE value) {
87
+ struct RData *rdata = RDATA(self);
88
+ int max = rb_numerix_isize(rdata->basic.klass) / sizeof(float);
89
+ int i = NUM2INT(index);
90
+
91
+ if (i >= 0 || i < max) {
92
+ float *flt = (float *)rdata->data;
93
+ flt[i] = NUM2FLT(value);
94
+ }
95
+
96
+ return value;
97
+ }
98
+
99
+ VALUE rb_numerix_dup(VALUE self) {
100
+ struct RData *rdata = RDATA(self);
101
+ int size = rb_numerix_isize(rdata->basic.klass);
102
+ void *data = ruby_xmalloc(size);
103
+ memcpy(data, rdata->data, size);
104
+ return NUMERIX_WRAP(rdata->basic.klass, data);
105
+ }
106
+
107
+ VALUE rb_numerix_address(VALUE self) {
108
+ void *address = RDATA(self)->data;
109
+ #if SIZEOF_INTPTR_T == 4
110
+ return LONG2NUM((long)address);
111
+ #elif SIZEOF_INTPTR_T == 8
112
+ return LL2NUM((long long)address);
113
+ #else
114
+ return INT2NUM(0);
115
+ #endif
116
+ }
117
+
118
+ static inline int rb_numerix_isize(VALUE klass) {
119
+ if (NUMERIX_INHERIT_P(klass, rb_cVector2))
120
+ return sizeof(Vector2);
121
+ if (NUMERIX_INHERIT_P(klass, rb_cVector3))
122
+ return sizeof(Vector3);
123
+ if (NUMERIX_INHERIT_P(klass, rb_cVector4))
124
+ return sizeof(Vector4);
125
+ if (NUMERIX_INHERIT_P(klass, rb_cMatrix3x2))
126
+ return sizeof(Matrix3x2);
127
+ if (NUMERIX_INHERIT_P(klass, rb_cMatrix4x4))
128
+ return sizeof(Matrix4x4);
129
+ if (NUMERIX_INHERIT_P(klass, rb_cPlane))
130
+ return sizeof(Plane);
131
+ if (NUMERIX_INHERIT_P(klass, rb_cQuaternion))
132
+ return sizeof(Quaternion);
133
+ return 0;
134
+ }
135
+
136
+ VALUE rb_numerix_size(VALUE klass) {
137
+ int size = rb_numerix_isize(klass);
138
+ return INT2NUM(size);
139
+ }
140
+
141
+ VALUE rb_numerix_dump(int arc, VALUE *argv, VALUE self) {
142
+ int size = rb_numerix_isize(CLASS_OF(self));
143
+ VALUE str = rb_str_new(NULL, size);
144
+ void *data = RDATA(self)->data;
145
+ memcpy(RSTRING_PTR(str), data, size);
146
+ return str;
147
+ }
148
+
149
+ VALUE rb_numerix_load(VALUE klass, VALUE str) {
150
+ int size = rb_numerix_isize(klass);
151
+ void *data = ruby_xmalloc(size);
152
+ memcpy(data, RSTRING_PTR(str), size);
153
+ return NUMERIX_WRAP(klass, data);
154
+ }
@@ -0,0 +1,24 @@
1
+ #ifndef NUMERIX_STRUCTURE_H
2
+ #define NUMERIX_STRUCTURE_H 1
3
+
4
+ #include "common.h"
5
+ #include "ruby/version.h"
6
+
7
+ void Init_numerix_structure(VALUE outer);
8
+
9
+ VALUE rb_numerix_address(VALUE self);
10
+ VALUE rb_numerix_dump(int arc, VALUE *argv, VALUE self);
11
+ VALUE rb_numerix_dup(VALUE self);
12
+ VALUE rb_numerix_aref(VALUE self, VALUE index);
13
+ VALUE rb_numerix_aset(VALUE self, VALUE index, VALUE value);
14
+ VALUE rb_numerix_each(VALUE self);
15
+
16
+ #if RUBY_API_VERSION_MAJOR >= 2
17
+ VALUE rb_numerix_fiddle_ptr(VALUE self);
18
+ #endif
19
+
20
+ static inline int rb_numerix_isize(VALUE klass);
21
+ VALUE rb_numerix_size(VALUE klass);
22
+ VALUE rb_numerix_load(VALUE klass, VALUE str);
23
+
24
+ #endif /* NUMERIX_STRUCTURE_H */
@@ -0,0 +1,326 @@
1
+
2
+ #include "vector.h"
3
+
4
+ VALUE rb_cBasicVector;
5
+
6
+ void Init_basic_vector(VALUE outer) {
7
+ rb_cBasicVector = rb_define_class_under(outer, "Vector", rb_cObject);
8
+ rb_define_alloc_func(rb_cBasicVector, rb_basic_vector_alloc);
9
+ rb_define_method(rb_cBasicVector, "initialize", rb_basic_vector_initialize, -1);
10
+
11
+ // Instance
12
+ rb_define_method(rb_cBasicVector, "size", rb_basic_vector_size, 0);
13
+ rb_define_method(rb_cBasicVector, "address", rb_basic_vector_address, 0);
14
+ rb_define_method(rb_cBasicVector, "count", rb_basic_vector_count, 0);
15
+ rb_define_method(rb_cBasicVector, "length", rb_basic_vector_length, 0);
16
+ rb_define_method(rb_cBasicVector, "length_squared", rb_basic_vector_length_squared, 0);
17
+ rb_define_method(rb_cBasicVector, "normalize", rb_basic_vector_normalize, 0);
18
+ rb_define_method(rb_cBasicVector, "normalize!", rb_basic_vector_normalize_bang, 0);
19
+ rb_define_method(rb_cBasicVector, "each", rb_basic_vector_each, 0);
20
+ rb_define_method(rb_cBasicVector, "dot", rb_basic_vector_dot, 1);
21
+
22
+ // Operators
23
+ rb_define_method(rb_cBasicVector, "+", rb_basic_vector_add, 1);
24
+ rb_define_method(rb_cBasicVector, "-", rb_basic_vector_subtract, 1);
25
+ rb_define_method(rb_cBasicVector, "*", rb_basic_vector_multiply, 1);
26
+ rb_define_method(rb_cBasicVector, "/", rb_basic_vector_divide, 1);
27
+ rb_define_method(rb_cBasicVector, "-@", rb_basic_vector_negate, 0);
28
+ rb_define_method(rb_cBasicVector, "==", rb_basic_vector_equal, 1);
29
+ rb_define_method(rb_cBasicVector, "[]", rb_basic_vector_aref, 1);
30
+ rb_define_method(rb_cBasicVector, "[]=", rb_basic_vector_aset, 2);
31
+ rb_define_method(rb_cBasicVector, "**", rb_basic_vector_pow, 1);
32
+
33
+ rb_define_method(rb_cBasicVector, "to_s", rb_basic_vector_to_s, 0);
34
+
35
+ // Alias
36
+ rb_define_alias(rb_cBasicVector, "magnitude", "length");
37
+
38
+ // Class
39
+ rb_define_singleton_method(rb_cBasicVector, "[]", rb_basic_vector_create, -1);
40
+
41
+ // Include
42
+ rb_include_module(rb_cBasicVector, rb_mEnumerable);
43
+ }
44
+
45
+ VALUE rb_basic_vector_alloc(VALUE klass) {
46
+ BasicVector *v = ALLOC(BasicVector);
47
+ v->count = 0;
48
+ v->values = NULL;
49
+ return NUMERIX_WRAP(klass, v);
50
+ }
51
+
52
+ VALUE rb_basic_vector_initialize(int argc, VALUE *argv, VALUE self) {
53
+ BASIC_VECTOR();
54
+ if (argc == 1) {
55
+ int count = NUM2INT(argv[0]);
56
+ if (count < 2) {
57
+ rb_raise(rb_eNumerixError, "vector size must be 2 or greater");
58
+ return Qnil;
59
+ }
60
+ v->count = count;
61
+ v->values = (float *)ruby_xmalloc(sizeof(float) * count);
62
+ memset(v->values, 0, count * sizeof(float));
63
+ } else if (argc > 1) {
64
+ v->count = argc;
65
+ v->values = (float *)ruby_xmalloc(sizeof(float) * argc);
66
+ for (int i = 0; i < argc; i++)
67
+ v->values[i] = NUM2FLT(argv[i]);
68
+ } else
69
+ rb_raise(rb_eArgError, "no arguments given");
70
+
71
+ return Qnil;
72
+ }
73
+
74
+ VALUE rb_basic_vector_create(int argc, VALUE *argv, VALUE klass) {
75
+ if (argc < 2)
76
+ rb_raise(rb_eArgError, "wrong number of arguments (given %d, expected 2 or more)", argc);
77
+
78
+ BasicVector *v = ALLOC(BasicVector);
79
+ v->count = argc;
80
+ v->values = ruby_xmalloc(sizeof(float) * argc);
81
+ for (int i = 0; i < argc; i++)
82
+ v->values[i] = NUM2FLT(argv[i]);
83
+ rb_basic_vector_create;
84
+
85
+ return NUMERIX_WRAP(klass, v);
86
+ }
87
+
88
+ VALUE rb_basic_vector_length(VALUE self) {
89
+ BASIC_VECTOR();
90
+ int c = v->count;
91
+ float length = 0.0f;
92
+ for (int i = 0; i < c; i++)
93
+ length += v->values[i] * v->values[i];
94
+
95
+ return DBL2NUM(sqrtf(length));
96
+ }
97
+
98
+ VALUE rb_basic_vector_length_squared(VALUE self) {
99
+ BASIC_VECTOR();
100
+ int c = v->count;
101
+ float length = 0.0f;
102
+ for (int i = 0; i < c; i++)
103
+ length += v->values[i] * v->values[i];
104
+
105
+ return DBL2NUM(length);
106
+ }
107
+
108
+ VALUE rb_basic_vector_normalize(VALUE self) {
109
+ BASIC_VECTOR_RESULT();
110
+
111
+ int c = v->count;
112
+ float length = 0.0f;
113
+ for (int i = 0; i < c; i++)
114
+ length += v->values[i] * v->values[i];
115
+
116
+ float inverse = 1.0f / sqrtf(length);
117
+ for (int i = 0; i < c; i++)
118
+ result->values[i] = v->values[i] * inverse;
119
+
120
+ return NUMERIX_WRAP(CLASS_OF(self), result);
121
+ }
122
+
123
+ VALUE rb_basic_vector_normalize_bang(VALUE self) {
124
+ BASIC_VECTOR();
125
+
126
+ int c = v->count;
127
+ float length = 0.0f;
128
+ for (int i = 0; i < c; i++)
129
+ length += v->values[i] * v->values[i];
130
+
131
+ float inverse = 1.0f / sqrtf(length);
132
+ for (int i = 0; i < c; i++)
133
+ v->values[i] *= inverse;
134
+
135
+ return self;
136
+ }
137
+
138
+ VALUE rb_basic_vector_add(VALUE self, VALUE other) {
139
+ BASIC_VECTOR_OTHER_RESULT();
140
+ for (int i = 0; i < count; i++)
141
+ result->values[i] = v1->values[i] + v2->values[i];
142
+
143
+ return NUMERIX_WRAP(CLASS_OF(self), result);
144
+ }
145
+
146
+ VALUE rb_basic_vector_subtract(VALUE self, VALUE other) {
147
+ BASIC_VECTOR_OTHER_RESULT();
148
+ for (int i = 0; i < count; i++)
149
+ result->values[i] = v1->values[i] - v2->values[i];
150
+
151
+ return NUMERIX_WRAP(CLASS_OF(self), result);
152
+ }
153
+
154
+ VALUE rb_basic_vector_multiply(VALUE self, VALUE other) {
155
+ BASIC_VECTOR_RESULT();
156
+ int count = v->count;
157
+ if (NUMERIX_TYPE_P(other, rb_cBasicVector)) {
158
+ BasicVector *v2;
159
+ Data_Get_Struct(other, BasicVector, v2);
160
+ if (count != v2->count)
161
+ rb_raise(rb_eNumerixError, "unequal length vectors");
162
+ for (int i = 0; i < count; i++)
163
+ result->values[i] = v->values[i] * v2->values[i];
164
+ } else {
165
+ float scalar = NUM2FLT(other);
166
+ for (int i = 0; i < count; i++)
167
+ result->values[i] = v->values[i] * scalar;
168
+ }
169
+
170
+ return NUMERIX_WRAP(CLASS_OF(self), result);
171
+ }
172
+
173
+ VALUE rb_basic_vector_divide(VALUE self, VALUE other) {
174
+ BASIC_VECTOR_RESULT();
175
+ int count = v->count;
176
+ if (NUMERIX_TYPE_P(other, rb_cBasicVector)) {
177
+ BasicVector *v2;
178
+ Data_Get_Struct(other, BasicVector, v2);
179
+ if (count != v2->count)
180
+ rb_raise(rb_eNumerixError, "unequal length vectors");
181
+ for (int i = 0; i < count; i++)
182
+ result->values[i] = v->values[i] / v2->values[i];
183
+ } else {
184
+ float scalar = 1.0f / NUM2FLT(other);
185
+ for (int i = 0; i < count; i++)
186
+ result->values[i] = v->values[i] * scalar;
187
+ }
188
+
189
+ return NUMERIX_WRAP(CLASS_OF(self), result);
190
+ }
191
+
192
+ VALUE rb_basic_vector_negate(VALUE self, VALUE other) {
193
+ BASIC_VECTOR_RESULT();
194
+
195
+ int c = v->count;
196
+ for (int i = 0; i < c; i++)
197
+ result->values[i] = -v->values[i];
198
+
199
+ return NUMERIX_WRAP(CLASS_OF(self), result);
200
+ }
201
+
202
+ VALUE rb_basic_vector_equal(VALUE self, VALUE other) {
203
+ if (CLASS_OF(self) != CLASS_OF(other))
204
+ return Qfalse;
205
+
206
+ BasicVector *v1, *v2;
207
+ Data_Get_Struct(self, BasicVector, v1);
208
+ Data_Get_Struct(other, BasicVector, v2);
209
+
210
+ int count = v1->count;
211
+
212
+ if (count != v2->count)
213
+ return Qfalse;
214
+
215
+ for (int i = 0; i < count; i++) {
216
+ if (!FLT_EQUAL(v1->values[i], v2->values[i]))
217
+ return Qfalse;
218
+ }
219
+
220
+ return Qtrue;
221
+ }
222
+
223
+ VALUE rb_basic_vector_size(VALUE self) {
224
+ BASIC_VECTOR();
225
+ return INT2NUM(v->count * sizeof(float));
226
+ }
227
+
228
+ VALUE rb_basic_vector_address(VALUE self) {
229
+ BASIC_VECTOR();
230
+ #if (SIZEOF_INTPTR_T == 4)
231
+ return LONG2NUM((long)v->values);
232
+ #elif (SIZEOF_INTPTR_T == 8)
233
+ return LL2NUM((long long)v->values)
234
+ #else
235
+ return INT2NUM(0);
236
+ #endif
237
+ }
238
+
239
+ VALUE rb_basic_vector_count(VALUE self) {
240
+ BASIC_VECTOR();
241
+ return INT2NUM(v->count);
242
+ }
243
+
244
+ VALUE rb_basic_vector_aref(VALUE self, VALUE index) {
245
+ BASIC_VECTOR();
246
+ int i = NUM2INT(index);
247
+
248
+ if (i < 0 || i >= v->count)
249
+ return Qnil;
250
+ return DBL2NUM(v->values[i]);
251
+ }
252
+
253
+ VALUE rb_basic_vector_aset(VALUE self, VALUE index, VALUE value) {
254
+ BASIC_VECTOR();
255
+ int i = NUM2INT(index);
256
+
257
+ if (i >= 0 && i < v->count)
258
+ v->values[i] = NUM2FLT(value);
259
+
260
+ return value;
261
+ }
262
+
263
+ VALUE rb_basic_vector_each(VALUE self) {
264
+ BASIC_VECTOR();
265
+ int count = v->count;
266
+
267
+ volatile VALUE vector = self;
268
+ RETURN_SIZED_ENUMERATOR(vector, 0, 0, count);
269
+
270
+ for (int i = 0; i < count; i++)
271
+ rb_yield(DBL2NUM(v->values[i]));
272
+
273
+ return vector;
274
+ }
275
+
276
+ VALUE rb_basic_vector_dot(VALUE self, VALUE other) {
277
+ BasicVector *v1, *v2;
278
+ Data_Get_Struct(self, BasicVector, v1);
279
+ Data_Get_Struct(self, BasicVector, v1);
280
+ int count = v1->count;
281
+ if (count != v2->count)
282
+ rb_raise(rb_eNumerixError, "unequal length vectors");
283
+
284
+ float dot = 0;
285
+ for (int i = 0; i < count; i++)
286
+ dot += v1->values[i] * v2->values[i];
287
+
288
+ return DBL2NUM(dot);
289
+ }
290
+
291
+ VALUE rb_basic_vector_to_s(VALUE self) {
292
+ VALUE ary = rb_funcall(self, rb_intern("to_a"), 0);
293
+ VALUE str = rb_ary_join(ary, rb_str_new_cstr(", "));
294
+ return rb_sprintf("<%" PRIsVALUE ">", str);
295
+ }
296
+
297
+ VALUE rb_basic_vector_abs(VALUE self) {
298
+ BASIC_VECTOR_RESULT();
299
+
300
+ int count = v->count;
301
+ for (int i = 0; i < count; i++)
302
+ result->values[i] = fabsf(v->values[i]);
303
+
304
+ return NUMERIX_WRAP(CLASS_OF(self), result);
305
+ }
306
+
307
+ VALUE rb_basic_vector_sqrt(VALUE self) {
308
+ BASIC_VECTOR_RESULT();
309
+
310
+ int count = v->count;
311
+ for (int i = 0; i < count; i++)
312
+ result->values[i] = sqrtf(v->values[i]);
313
+
314
+ return NUMERIX_WRAP(CLASS_OF(self), result);
315
+ }
316
+
317
+ VALUE rb_basic_vector_pow(VALUE self, VALUE exponent) {
318
+ BASIC_VECTOR_RESULT();
319
+
320
+ float e = fabsf(NUM2FLT(exponent));
321
+ int count = v->count;
322
+ for (int i = 0; i < count; i++)
323
+ result->values[i] = powf(v->values[i], e);
324
+
325
+ return NUMERIX_WRAP(CLASS_OF(self), result);
326
+ }
@@ -0,0 +1,57 @@
1
+ #ifndef NUMERIX_BASIC_VECTOR_H
2
+ #define NUMERIX_BASIC_VECTOR_H 1
3
+
4
+ #include "common.h"
5
+
6
+ #define BASIC_VECTOR() \
7
+ BasicVector *v; \
8
+ Data_Get_Struct(self, BasicVector, v)
9
+
10
+ #define BASIC_VECTOR_RESULT() \
11
+ BASIC_VECTOR(); \
12
+ BasicVector *result = ALLOC(BasicVector); \
13
+ result->count = v->count; \
14
+ result->values = ruby_xmalloc(sizeof(float) * v->count)
15
+
16
+ #define BASIC_VECTOR_OTHER_RESULT() \
17
+ BasicVector *v1, *v2, *result; \
18
+ Data_Get_Struct(self, BasicVector, v1); \
19
+ Data_Get_Struct(other, BasicVector, v2); \
20
+ result = ALLOC(BasicVector); \
21
+ int count = v1->count; \
22
+ if (count != v2->count) \
23
+ rb_raise(rb_eNumerixError, "unequal length vectors"); \
24
+ result->count = count; \
25
+ result->values = ruby_xmalloc(sizeof(float) * count)
26
+
27
+ void Init_basic_vector(VALUE outer);
28
+ VALUE rb_basic_vector_alloc(VALUE klass);
29
+ VALUE rb_basic_vector_initialize(int argc, VALUE *argv, VALUE self);
30
+
31
+ // Instance
32
+ VALUE rb_basic_vector_length(VALUE self);
33
+ VALUE rb_basic_vector_length_squared(VALUE self);
34
+ VALUE rb_basic_vector_normalize(VALUE self);
35
+ VALUE rb_basic_vector_normalize_bang(VALUE self);
36
+ VALUE rb_basic_vector_add(VALUE self, VALUE other);
37
+ VALUE rb_basic_vector_subtract(VALUE self, VALUE other);
38
+ VALUE rb_basic_vector_multiply(VALUE self, VALUE other);
39
+ VALUE rb_basic_vector_divide(VALUE self, VALUE other);
40
+ VALUE rb_basic_vector_negate(VALUE self, VALUE other);
41
+ VALUE rb_basic_vector_equal(VALUE self, VALUE other);
42
+ VALUE rb_basic_vector_size(VALUE self);
43
+ VALUE rb_basic_vector_address(VALUE self);
44
+ VALUE rb_basic_vector_count(VALUE self);
45
+ VALUE rb_basic_vector_each(VALUE self);
46
+ VALUE rb_basic_vector_aref(VALUE self, VALUE index);
47
+ VALUE rb_basic_vector_aset(VALUE self, VALUE index, VALUE value);
48
+ VALUE rb_basic_vector_dot(VALUE self, VALUE other);
49
+ VALUE rb_basic_vector_to_s(VALUE self);
50
+ VALUE rb_basic_vector_abs(VALUE self);
51
+ VALUE rb_basic_vector_sqrt(VALUE self);
52
+ VALUE rb_basic_vector_pow(VALUE self, VALUE exponent);
53
+
54
+ // Class
55
+ VALUE rb_basic_vector_create(int argc, VALUE *argv, VALUE klass);
56
+
57
+ #endif