larb 0.1.0 → 1.0.1
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/CHANGELOG.md +13 -1
- data/README.md +63 -1
- data/ext/larb/color.c +449 -0
- data/ext/larb/color.h +35 -0
- data/ext/larb/extconf.rb +11 -0
- data/ext/larb/larb.c +27 -0
- data/ext/larb/larb.h +31 -0
- data/ext/larb/mat2.c +303 -0
- data/ext/larb/mat2.h +30 -0
- data/ext/larb/mat2d.c +397 -0
- data/ext/larb/mat2d.h +35 -0
- data/ext/larb/mat3.c +455 -0
- data/ext/larb/mat3.h +33 -0
- data/ext/larb/mat4.c +651 -0
- data/ext/larb/mat4.h +31 -0
- data/ext/larb/matrix_utils.h +97 -0
- data/ext/larb/quat.c +567 -0
- data/ext/larb/quat.h +39 -0
- data/ext/larb/quat2.c +511 -0
- data/ext/larb/quat2.h +39 -0
- data/ext/larb/vec2.c +365 -0
- data/ext/larb/vec2.h +43 -0
- data/ext/larb/vec3.c +538 -0
- data/ext/larb/vec3.h +52 -0
- data/ext/larb/vec4.c +361 -0
- data/ext/larb/vec4.h +38 -0
- data/lib/larb/version.rb +5 -0
- data/lib/larb.rb +2 -14
- data/test/larb/color_test.rb +299 -0
- data/test/larb/mat2_test.rb +144 -0
- data/test/larb/mat2d_test.rb +197 -0
- data/test/larb/mat3_test.rb +147 -0
- data/test/larb/mat4_test.rb +347 -0
- data/test/larb/matrix_test.rb +135 -0
- data/test/larb/native_value_test.rb +157 -0
- data/test/larb/quat2_test.rb +254 -0
- data/test/larb/quat_test.rb +284 -0
- data/test/larb/vec2_test.rb +274 -0
- data/test/larb/vec3_test.rb +373 -0
- data/test/larb/vec4_test.rb +196 -0
- data/test/test_helper.rb +4 -0
- metadata +60 -18
- data/Rakefile +0 -11
- data/lib/larb/color.rb +0 -148
- data/lib/larb/mat2.rb +0 -119
- data/lib/larb/mat2d.rb +0 -180
- data/lib/larb/mat3.rb +0 -238
- data/lib/larb/mat4.rb +0 -329
- data/lib/larb/quat.rb +0 -238
- data/lib/larb/quat2.rb +0 -193
- data/lib/larb/vec2.rb +0 -150
- data/lib/larb/vec3.rb +0 -218
- data/lib/larb/vec4.rb +0 -125
data/ext/larb/mat2.c
ADDED
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
#include "mat2.h"
|
|
2
|
+
#include "matrix_utils.h"
|
|
3
|
+
|
|
4
|
+
#include <math.h>
|
|
5
|
+
|
|
6
|
+
static void mat2_free(void *ptr) {
|
|
7
|
+
xfree(ptr);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
static size_t mat2_memsize(const void *ptr) {
|
|
11
|
+
return sizeof(Mat2Data);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
static const rb_data_type_t mat2_type = {
|
|
15
|
+
"Mat2",
|
|
16
|
+
{0, mat2_free, mat2_memsize},
|
|
17
|
+
0,
|
|
18
|
+
0,
|
|
19
|
+
RUBY_TYPED_FREE_IMMEDIATELY,
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
static VALUE cMat2 = Qnil;
|
|
23
|
+
static VALUE cVec2 = Qnil;
|
|
24
|
+
|
|
25
|
+
static Mat2Data *mat2_get(VALUE obj) {
|
|
26
|
+
Mat2Data *data = NULL;
|
|
27
|
+
TypedData_Get_Struct(obj, Mat2Data, &mat2_type, data);
|
|
28
|
+
return data;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
static VALUE mat2_build(VALUE klass, double a0, double a1, double a2,
|
|
32
|
+
double a3) {
|
|
33
|
+
VALUE obj = mat2_alloc(klass);
|
|
34
|
+
Mat2Data *data = mat2_get(obj);
|
|
35
|
+
data->data[0] = a0;
|
|
36
|
+
data->data[1] = a1;
|
|
37
|
+
data->data[2] = a2;
|
|
38
|
+
data->data[3] = a3;
|
|
39
|
+
return obj;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
VALUE mat2_alloc(VALUE klass) {
|
|
43
|
+
Mat2Data *data = ALLOC(Mat2Data);
|
|
44
|
+
data->data[0] = 1.0;
|
|
45
|
+
data->data[1] = 0.0;
|
|
46
|
+
data->data[2] = 0.0;
|
|
47
|
+
data->data[3] = 1.0;
|
|
48
|
+
return TypedData_Wrap_Struct(klass, &mat2_type, data);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
VALUE mat2_initialize(int argc, VALUE *argv, VALUE self) {
|
|
52
|
+
rb_check_frozen(self);
|
|
53
|
+
VALUE data_arg = Qnil;
|
|
54
|
+
Mat2Data values = {{1.0, 0.0, 0.0, 1.0}};
|
|
55
|
+
rb_scan_args(argc, argv, "01", &data_arg);
|
|
56
|
+
if (argc != 0) {
|
|
57
|
+
VALUE ary = rb_check_array_type(data_arg);
|
|
58
|
+
if (NIL_P(ary)) {
|
|
59
|
+
rb_raise(rb_eTypeError, "expected Array");
|
|
60
|
+
}
|
|
61
|
+
if (RARRAY_LEN(ary) != 4) {
|
|
62
|
+
rb_raise(rb_eArgError, "expected 4 elements");
|
|
63
|
+
}
|
|
64
|
+
for (int i = 0; i < 4; i++) {
|
|
65
|
+
values.data[i] = NUM2DBL(rb_ary_entry(ary, i));
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
rb_check_frozen(self);
|
|
69
|
+
*mat2_get(self) = values;
|
|
70
|
+
return self;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
static VALUE mat2_initialize_copy(VALUE self, VALUE other) {
|
|
74
|
+
if (self == other) return self;
|
|
75
|
+
rb_obj_init_copy(self, other);
|
|
76
|
+
*mat2_get(self) = *mat2_get(other);
|
|
77
|
+
return self;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
static VALUE mat2_class_identity(VALUE klass) {
|
|
81
|
+
return mat2_build(klass, 1.0, 0.0, 0.0, 1.0);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
static VALUE mat2_class_zero(VALUE klass) {
|
|
85
|
+
return mat2_build(klass, 0.0, 0.0, 0.0, 0.0);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
static VALUE mat2_class_rotation(VALUE klass, VALUE radians) {
|
|
89
|
+
double r = NUM2DBL(radians);
|
|
90
|
+
double c = cos(r);
|
|
91
|
+
double s = sin(r);
|
|
92
|
+
return mat2_build(klass, c, s, -s, c);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
static VALUE mat2_class_scaling(VALUE klass, VALUE x, VALUE y) {
|
|
96
|
+
return mat2_build(klass, NUM2DBL(x), 0.0, 0.0, NUM2DBL(y));
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
static VALUE mat2_class_from_vec2(VALUE klass, VALUE v1, VALUE v2) {
|
|
100
|
+
double x1 = NUM2DBL(rb_funcall(v1, rb_intern("x"), 0));
|
|
101
|
+
double y1 = NUM2DBL(rb_funcall(v1, rb_intern("y"), 0));
|
|
102
|
+
double x2 = NUM2DBL(rb_funcall(v2, rb_intern("x"), 0));
|
|
103
|
+
double y2 = NUM2DBL(rb_funcall(v2, rb_intern("y"), 0));
|
|
104
|
+
return mat2_build(klass, x1, y1, x2, y2);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
VALUE mat2_aref(VALUE self, VALUE index) {
|
|
108
|
+
Mat2Data *data = mat2_get(self);
|
|
109
|
+
long idx = NUM2LONG(index);
|
|
110
|
+
if (idx < 0 || idx > 3) {
|
|
111
|
+
return Qnil;
|
|
112
|
+
}
|
|
113
|
+
return DBL2NUM(data->data[idx]);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
VALUE mat2_aset(VALUE self, VALUE index, VALUE value) {
|
|
117
|
+
rb_check_frozen(self);
|
|
118
|
+
Mat2Data *data = mat2_get(self);
|
|
119
|
+
long idx = NUM2LONG(index);
|
|
120
|
+
if (idx < 0 || idx > 3) {
|
|
121
|
+
rb_raise(rb_eIndexError, "index %ld out of range", idx);
|
|
122
|
+
}
|
|
123
|
+
double component = NUM2DBL(value);
|
|
124
|
+
rb_check_frozen(self);
|
|
125
|
+
data->data[idx] = component;
|
|
126
|
+
return value;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
VALUE mat2_mul(VALUE self, VALUE other) {
|
|
130
|
+
Mat2Data *a = mat2_get(self);
|
|
131
|
+
|
|
132
|
+
if (rb_obj_is_kind_of(other, cMat2)) {
|
|
133
|
+
Mat2Data *b = mat2_get(other);
|
|
134
|
+
return mat2_build(rb_obj_class(self),
|
|
135
|
+
a->data[0] * b->data[0] + a->data[2] * b->data[1],
|
|
136
|
+
a->data[1] * b->data[0] + a->data[3] * b->data[1],
|
|
137
|
+
a->data[0] * b->data[2] + a->data[2] * b->data[3],
|
|
138
|
+
a->data[1] * b->data[2] + a->data[3] * b->data[3]);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (rb_obj_is_kind_of(other, cVec2)) {
|
|
142
|
+
double x = NUM2DBL(rb_funcall(other, rb_intern("x"), 0));
|
|
143
|
+
double y = NUM2DBL(rb_funcall(other, rb_intern("y"), 0));
|
|
144
|
+
VALUE vec2_class = rb_const_get(mLarb, rb_intern("Vec2"));
|
|
145
|
+
return rb_funcall(vec2_class, rb_intern("new"), 2,
|
|
146
|
+
DBL2NUM(a->data[0] * x + a->data[2] * y),
|
|
147
|
+
DBL2NUM(a->data[1] * x + a->data[3] * y));
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (rb_obj_is_kind_of(other, rb_cNumeric)) {
|
|
151
|
+
double s = NUM2DBL(other);
|
|
152
|
+
return mat2_build(rb_obj_class(self), a->data[0] * s, a->data[1] * s,
|
|
153
|
+
a->data[2] * s, a->data[3] * s);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
rb_raise(rb_eTypeError, "unsupported operand for Mat2 multiplication");
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
VALUE mat2_add(VALUE self, VALUE other) {
|
|
160
|
+
Mat2Data *a = mat2_get(self);
|
|
161
|
+
Mat2Data *b = mat2_get(other);
|
|
162
|
+
return mat2_build(rb_obj_class(self), a->data[0] + b->data[0],
|
|
163
|
+
a->data[1] + b->data[1], a->data[2] + b->data[2],
|
|
164
|
+
a->data[3] + b->data[3]);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
VALUE mat2_sub(VALUE self, VALUE other) {
|
|
168
|
+
Mat2Data *a = mat2_get(self);
|
|
169
|
+
Mat2Data *b = mat2_get(other);
|
|
170
|
+
return mat2_build(rb_obj_class(self), a->data[0] - b->data[0],
|
|
171
|
+
a->data[1] - b->data[1], a->data[2] - b->data[2],
|
|
172
|
+
a->data[3] - b->data[3]);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
VALUE mat2_determinant(VALUE self) {
|
|
176
|
+
Mat2Data *a = mat2_get(self);
|
|
177
|
+
return DBL2NUM(a->data[0] * a->data[3] - a->data[2] * a->data[1]);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
VALUE mat2_inverse(VALUE self) {
|
|
181
|
+
double inverse[4];
|
|
182
|
+
larb_matrix_inverse(mat2_get(self)->data, inverse, 2);
|
|
183
|
+
return mat2_build(rb_obj_class(self), inverse[0], inverse[1], inverse[2],
|
|
184
|
+
inverse[3]);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
VALUE mat2_transpose(VALUE self) {
|
|
188
|
+
Mat2Data *a = mat2_get(self);
|
|
189
|
+
return mat2_build(rb_obj_class(self), a->data[0], a->data[2], a->data[1],
|
|
190
|
+
a->data[3]);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
VALUE mat2_adjoint(VALUE self) {
|
|
194
|
+
Mat2Data *a = mat2_get(self);
|
|
195
|
+
return mat2_build(rb_obj_class(self), a->data[3], -a->data[1], -a->data[2],
|
|
196
|
+
a->data[0]);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
VALUE mat2_frobenius_norm(VALUE self) {
|
|
200
|
+
Mat2Data *a = mat2_get(self);
|
|
201
|
+
double norm = 0.0;
|
|
202
|
+
for (int i = 0; i < 4; i++) {
|
|
203
|
+
norm = hypot(norm, a->data[i]);
|
|
204
|
+
}
|
|
205
|
+
return DBL2NUM(norm);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
VALUE mat2_to_a(VALUE self) {
|
|
209
|
+
Mat2Data *a = mat2_get(self);
|
|
210
|
+
VALUE ary = rb_ary_new_capa(4);
|
|
211
|
+
rb_ary_push(ary, DBL2NUM(a->data[0]));
|
|
212
|
+
rb_ary_push(ary, DBL2NUM(a->data[1]));
|
|
213
|
+
rb_ary_push(ary, DBL2NUM(a->data[2]));
|
|
214
|
+
rb_ary_push(ary, DBL2NUM(a->data[3]));
|
|
215
|
+
return ary;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
VALUE mat2_data(VALUE self) {
|
|
219
|
+
return mat2_to_a(self);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
VALUE mat2_equal(VALUE self, VALUE other) {
|
|
223
|
+
if (!rb_obj_is_kind_of(other, cMat2)) {
|
|
224
|
+
return Qfalse;
|
|
225
|
+
}
|
|
226
|
+
Mat2Data *a = mat2_get(self);
|
|
227
|
+
Mat2Data *b = mat2_get(other);
|
|
228
|
+
return (a->data[0] == b->data[0] && a->data[1] == b->data[1] &&
|
|
229
|
+
a->data[2] == b->data[2] && a->data[3] == b->data[3])
|
|
230
|
+
? Qtrue
|
|
231
|
+
: Qfalse;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
VALUE mat2_near(int argc, VALUE *argv, VALUE self) {
|
|
235
|
+
VALUE other = Qnil;
|
|
236
|
+
VALUE epsilon = Qnil;
|
|
237
|
+
|
|
238
|
+
rb_scan_args(argc, argv, "11", &other, &epsilon);
|
|
239
|
+
Mat2Data *a = mat2_get(self);
|
|
240
|
+
Mat2Data *b = mat2_get(other);
|
|
241
|
+
double eps = argc < 2 ? 1e-6 : NUM2DBL(epsilon);
|
|
242
|
+
if (!isfinite(eps) || eps <= 0.0) {
|
|
243
|
+
rb_raise(rb_eArgError, "epsilon must be finite and positive");
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
if (fabs(a->data[0] - b->data[0]) < eps &&
|
|
247
|
+
fabs(a->data[1] - b->data[1]) < eps &&
|
|
248
|
+
fabs(a->data[2] - b->data[2]) < eps &&
|
|
249
|
+
fabs(a->data[3] - b->data[3]) < eps) {
|
|
250
|
+
return Qtrue;
|
|
251
|
+
}
|
|
252
|
+
return Qfalse;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
VALUE mat2_inspect(VALUE self) {
|
|
256
|
+
Mat2Data *a = mat2_get(self);
|
|
257
|
+
VALUE s0 = rb_funcall(DBL2NUM(a->data[0]), rb_intern("to_s"), 0);
|
|
258
|
+
VALUE s1 = rb_funcall(DBL2NUM(a->data[1]), rb_intern("to_s"), 0);
|
|
259
|
+
VALUE s2 = rb_funcall(DBL2NUM(a->data[2]), rb_intern("to_s"), 0);
|
|
260
|
+
VALUE s3 = rb_funcall(DBL2NUM(a->data[3]), rb_intern("to_s"), 0);
|
|
261
|
+
VALUE str = rb_str_new_cstr("Mat2[");
|
|
262
|
+
rb_str_concat(str, s0);
|
|
263
|
+
rb_str_cat_cstr(str, ", ");
|
|
264
|
+
rb_str_concat(str, s1);
|
|
265
|
+
rb_str_cat_cstr(str, ", ");
|
|
266
|
+
rb_str_concat(str, s2);
|
|
267
|
+
rb_str_cat_cstr(str, ", ");
|
|
268
|
+
rb_str_concat(str, s3);
|
|
269
|
+
rb_str_cat_cstr(str, "]");
|
|
270
|
+
return str;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
void Init_mat2(VALUE module) {
|
|
274
|
+
cMat2 = rb_define_class_under(module, "Mat2", rb_cObject);
|
|
275
|
+
cVec2 = rb_const_get(mLarb, rb_intern("Vec2"));
|
|
276
|
+
|
|
277
|
+
rb_define_alloc_func(cMat2, mat2_alloc);
|
|
278
|
+
rb_define_method(cMat2, "initialize", mat2_initialize, -1);
|
|
279
|
+
rb_define_method(cMat2, "initialize_copy", mat2_initialize_copy, 1);
|
|
280
|
+
|
|
281
|
+
rb_define_singleton_method(cMat2, "identity", mat2_class_identity, 0);
|
|
282
|
+
rb_define_singleton_method(cMat2, "zero", mat2_class_zero, 0);
|
|
283
|
+
rb_define_singleton_method(cMat2, "rotation", mat2_class_rotation, 1);
|
|
284
|
+
rb_define_singleton_method(cMat2, "scaling", mat2_class_scaling, 2);
|
|
285
|
+
rb_define_singleton_method(cMat2, "from_vec2", mat2_class_from_vec2, 2);
|
|
286
|
+
|
|
287
|
+
rb_define_method(cMat2, "data", mat2_data, 0);
|
|
288
|
+
rb_define_method(cMat2, "[]", mat2_aref, 1);
|
|
289
|
+
rb_define_method(cMat2, "[]=", mat2_aset, 2);
|
|
290
|
+
rb_define_method(cMat2, "*", mat2_mul, 1);
|
|
291
|
+
rb_define_method(cMat2, "+", mat2_add, 1);
|
|
292
|
+
rb_define_method(cMat2, "-", mat2_sub, 1);
|
|
293
|
+
rb_define_method(cMat2, "determinant", mat2_determinant, 0);
|
|
294
|
+
rb_define_method(cMat2, "inverse", mat2_inverse, 0);
|
|
295
|
+
rb_define_method(cMat2, "transpose", mat2_transpose, 0);
|
|
296
|
+
rb_define_method(cMat2, "adjoint", mat2_adjoint, 0);
|
|
297
|
+
rb_define_method(cMat2, "frobenius_norm", mat2_frobenius_norm, 0);
|
|
298
|
+
rb_define_method(cMat2, "to_a", mat2_to_a, 0);
|
|
299
|
+
rb_define_method(cMat2, "==", mat2_equal, 1);
|
|
300
|
+
rb_define_method(cMat2, "near?", mat2_near, -1);
|
|
301
|
+
rb_define_method(cMat2, "inspect", mat2_inspect, 0);
|
|
302
|
+
rb_define_alias(cMat2, "to_s", "inspect");
|
|
303
|
+
}
|
data/ext/larb/mat2.h
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
#ifndef MAT2_H
|
|
2
|
+
#define MAT2_H
|
|
3
|
+
|
|
4
|
+
#include "larb.h"
|
|
5
|
+
|
|
6
|
+
typedef struct {
|
|
7
|
+
double data[4];
|
|
8
|
+
} Mat2Data;
|
|
9
|
+
|
|
10
|
+
void Init_mat2(VALUE module);
|
|
11
|
+
VALUE mat2_alloc(VALUE klass);
|
|
12
|
+
VALUE mat2_initialize(int argc, VALUE *argv, VALUE self);
|
|
13
|
+
|
|
14
|
+
VALUE mat2_aref(VALUE self, VALUE index);
|
|
15
|
+
VALUE mat2_aset(VALUE self, VALUE index, VALUE value);
|
|
16
|
+
VALUE mat2_mul(VALUE self, VALUE other);
|
|
17
|
+
VALUE mat2_add(VALUE self, VALUE other);
|
|
18
|
+
VALUE mat2_sub(VALUE self, VALUE other);
|
|
19
|
+
VALUE mat2_determinant(VALUE self);
|
|
20
|
+
VALUE mat2_inverse(VALUE self);
|
|
21
|
+
VALUE mat2_transpose(VALUE self);
|
|
22
|
+
VALUE mat2_adjoint(VALUE self);
|
|
23
|
+
VALUE mat2_frobenius_norm(VALUE self);
|
|
24
|
+
VALUE mat2_to_a(VALUE self);
|
|
25
|
+
VALUE mat2_equal(VALUE self, VALUE other);
|
|
26
|
+
VALUE mat2_near(int argc, VALUE *argv, VALUE self);
|
|
27
|
+
VALUE mat2_inspect(VALUE self);
|
|
28
|
+
VALUE mat2_data(VALUE self);
|
|
29
|
+
|
|
30
|
+
#endif
|