numerix 1.0.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.
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