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.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +13 -1
  3. data/README.md +63 -1
  4. data/ext/larb/color.c +449 -0
  5. data/ext/larb/color.h +35 -0
  6. data/ext/larb/extconf.rb +11 -0
  7. data/ext/larb/larb.c +27 -0
  8. data/ext/larb/larb.h +31 -0
  9. data/ext/larb/mat2.c +303 -0
  10. data/ext/larb/mat2.h +30 -0
  11. data/ext/larb/mat2d.c +397 -0
  12. data/ext/larb/mat2d.h +35 -0
  13. data/ext/larb/mat3.c +455 -0
  14. data/ext/larb/mat3.h +33 -0
  15. data/ext/larb/mat4.c +651 -0
  16. data/ext/larb/mat4.h +31 -0
  17. data/ext/larb/matrix_utils.h +97 -0
  18. data/ext/larb/quat.c +567 -0
  19. data/ext/larb/quat.h +39 -0
  20. data/ext/larb/quat2.c +511 -0
  21. data/ext/larb/quat2.h +39 -0
  22. data/ext/larb/vec2.c +365 -0
  23. data/ext/larb/vec2.h +43 -0
  24. data/ext/larb/vec3.c +538 -0
  25. data/ext/larb/vec3.h +52 -0
  26. data/ext/larb/vec4.c +361 -0
  27. data/ext/larb/vec4.h +38 -0
  28. data/lib/larb/version.rb +5 -0
  29. data/lib/larb.rb +2 -14
  30. data/test/larb/color_test.rb +299 -0
  31. data/test/larb/mat2_test.rb +144 -0
  32. data/test/larb/mat2d_test.rb +197 -0
  33. data/test/larb/mat3_test.rb +147 -0
  34. data/test/larb/mat4_test.rb +347 -0
  35. data/test/larb/matrix_test.rb +135 -0
  36. data/test/larb/native_value_test.rb +157 -0
  37. data/test/larb/quat2_test.rb +254 -0
  38. data/test/larb/quat_test.rb +284 -0
  39. data/test/larb/vec2_test.rb +274 -0
  40. data/test/larb/vec3_test.rb +373 -0
  41. data/test/larb/vec4_test.rb +196 -0
  42. data/test/test_helper.rb +4 -0
  43. metadata +60 -18
  44. data/Rakefile +0 -11
  45. data/lib/larb/color.rb +0 -148
  46. data/lib/larb/mat2.rb +0 -119
  47. data/lib/larb/mat2d.rb +0 -180
  48. data/lib/larb/mat3.rb +0 -238
  49. data/lib/larb/mat4.rb +0 -329
  50. data/lib/larb/quat.rb +0 -238
  51. data/lib/larb/quat2.rb +0 -193
  52. data/lib/larb/vec2.rb +0 -150
  53. data/lib/larb/vec3.rb +0 -218
  54. data/lib/larb/vec4.rb +0 -125
data/ext/larb/mat3.c ADDED
@@ -0,0 +1,455 @@
1
+ #include "mat3.h"
2
+ #include "matrix_utils.h"
3
+
4
+ #include <math.h>
5
+
6
+ static void mat3_free(void *ptr) {
7
+ xfree(ptr);
8
+ }
9
+
10
+ static size_t mat3_memsize(const void *ptr) {
11
+ return sizeof(Mat3Data);
12
+ }
13
+
14
+ static const rb_data_type_t mat3_type = {
15
+ "Mat3",
16
+ {0, mat3_free, mat3_memsize},
17
+ 0,
18
+ 0,
19
+ RUBY_TYPED_FREE_IMMEDIATELY,
20
+ };
21
+
22
+ static VALUE cMat3 = Qnil;
23
+ static VALUE cVec3 = Qnil;
24
+
25
+ static Mat3Data *mat3_get(VALUE obj) {
26
+ Mat3Data *data = NULL;
27
+ TypedData_Get_Struct(obj, Mat3Data, &mat3_type, data);
28
+ return data;
29
+ }
30
+
31
+ static VALUE mat3_build(VALUE klass, const double *values) {
32
+ VALUE obj = mat3_alloc(klass);
33
+ Mat3Data *data = mat3_get(obj);
34
+ for (int i = 0; i < 9; i++) {
35
+ data->data[i] = values[i];
36
+ }
37
+ return obj;
38
+ }
39
+
40
+ static VALUE mat3_build9(VALUE klass, double v0, double v1, double v2,
41
+ double v3, double v4, double v5, double v6,
42
+ double v7, double v8) {
43
+ double values[9] = {v0, v1, v2, v3, v4, v5, v6, v7, v8};
44
+ return mat3_build(klass, values);
45
+ }
46
+
47
+ VALUE mat3_alloc(VALUE klass) {
48
+ Mat3Data *data = ALLOC(Mat3Data);
49
+ data->data[0] = 1.0;
50
+ data->data[1] = 0.0;
51
+ data->data[2] = 0.0;
52
+ data->data[3] = 0.0;
53
+ data->data[4] = 1.0;
54
+ data->data[5] = 0.0;
55
+ data->data[6] = 0.0;
56
+ data->data[7] = 0.0;
57
+ data->data[8] = 1.0;
58
+ return TypedData_Wrap_Struct(klass, &mat3_type, data);
59
+ }
60
+
61
+ VALUE mat3_initialize(int argc, VALUE *argv, VALUE self) {
62
+ rb_check_frozen(self);
63
+ VALUE data_arg = Qnil;
64
+ Mat3Data values = {{1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0}};
65
+ rb_scan_args(argc, argv, "01", &data_arg);
66
+ if (argc != 0) {
67
+ VALUE ary = rb_check_array_type(data_arg);
68
+ if (NIL_P(ary)) {
69
+ rb_raise(rb_eTypeError, "expected Array");
70
+ }
71
+ if (RARRAY_LEN(ary) != 9) {
72
+ rb_raise(rb_eArgError, "expected 9 elements");
73
+ }
74
+ for (int i = 0; i < 9; i++) {
75
+ values.data[i] = NUM2DBL(rb_ary_entry(ary, i));
76
+ }
77
+ }
78
+ rb_check_frozen(self);
79
+ *mat3_get(self) = values;
80
+ return self;
81
+ }
82
+
83
+ static VALUE mat3_initialize_copy(VALUE self, VALUE other) {
84
+ if (self == other) return self;
85
+ rb_obj_init_copy(self, other);
86
+ *mat3_get(self) = *mat3_get(other);
87
+ return self;
88
+ }
89
+
90
+ static VALUE mat3_class_identity(VALUE klass) {
91
+ return mat3_alloc(klass);
92
+ }
93
+
94
+ static VALUE mat3_class_zero(VALUE klass) {
95
+ return mat3_build9(klass, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
96
+ }
97
+
98
+ static VALUE mat3_class_from_mat4(VALUE klass, VALUE mat4) {
99
+ double values[9];
100
+ values[0] = NUM2DBL(rb_funcall(mat4, rb_intern("[]"), 1, INT2NUM(0)));
101
+ values[1] = NUM2DBL(rb_funcall(mat4, rb_intern("[]"), 1, INT2NUM(1)));
102
+ values[2] = NUM2DBL(rb_funcall(mat4, rb_intern("[]"), 1, INT2NUM(2)));
103
+ values[3] = NUM2DBL(rb_funcall(mat4, rb_intern("[]"), 1, INT2NUM(4)));
104
+ values[4] = NUM2DBL(rb_funcall(mat4, rb_intern("[]"), 1, INT2NUM(5)));
105
+ values[5] = NUM2DBL(rb_funcall(mat4, rb_intern("[]"), 1, INT2NUM(6)));
106
+ values[6] = NUM2DBL(rb_funcall(mat4, rb_intern("[]"), 1, INT2NUM(8)));
107
+ values[7] = NUM2DBL(rb_funcall(mat4, rb_intern("[]"), 1, INT2NUM(9)));
108
+ values[8] = NUM2DBL(rb_funcall(mat4, rb_intern("[]"), 1, INT2NUM(10)));
109
+ return mat3_build(klass, values);
110
+ }
111
+
112
+ static VALUE mat3_class_from_mat2d(VALUE klass, VALUE mat2d) {
113
+ double values[9];
114
+ values[0] = NUM2DBL(rb_funcall(mat2d, rb_intern("[]"), 1, INT2NUM(0)));
115
+ values[1] = NUM2DBL(rb_funcall(mat2d, rb_intern("[]"), 1, INT2NUM(1)));
116
+ values[2] = 0.0;
117
+ values[3] = NUM2DBL(rb_funcall(mat2d, rb_intern("[]"), 1, INT2NUM(2)));
118
+ values[4] = NUM2DBL(rb_funcall(mat2d, rb_intern("[]"), 1, INT2NUM(3)));
119
+ values[5] = 0.0;
120
+ values[6] = NUM2DBL(rb_funcall(mat2d, rb_intern("[]"), 1, INT2NUM(4)));
121
+ values[7] = NUM2DBL(rb_funcall(mat2d, rb_intern("[]"), 1, INT2NUM(5)));
122
+ values[8] = 1.0;
123
+ return mat3_build(klass, values);
124
+ }
125
+
126
+ static VALUE mat3_class_from_quaternion(VALUE klass, VALUE quat) {
127
+ double x = NUM2DBL(rb_funcall(quat, rb_intern("x"), 0));
128
+ double y = NUM2DBL(rb_funcall(quat, rb_intern("y"), 0));
129
+ double z = NUM2DBL(rb_funcall(quat, rb_intern("z"), 0));
130
+ double w = NUM2DBL(rb_funcall(quat, rb_intern("w"), 0));
131
+ double x2 = x + x;
132
+ double y2 = y + y;
133
+ double z2 = z + z;
134
+ double xx = x * x2;
135
+ double yx = y * x2;
136
+ double yy = y * y2;
137
+ double zx = z * x2;
138
+ double zy = z * y2;
139
+ double zz = z * z2;
140
+ double wx = w * x2;
141
+ double wy = w * y2;
142
+ double wz = w * z2;
143
+
144
+ return mat3_build9(klass, 1 - yy - zz, yx + wz, zx - wy, yx - wz,
145
+ 1 - xx - zz, zy + wx, zx + wy, zy - wx,
146
+ 1 - xx - yy);
147
+ }
148
+
149
+ static VALUE mat3_class_normal_from_mat4(VALUE klass, VALUE mat4) {
150
+ VALUE m3 = mat3_class_from_mat4(klass, mat4);
151
+ VALUE inv = rb_funcall(m3, rb_intern("inverse"), 0);
152
+ return rb_funcall(inv, rb_intern("transpose"), 0);
153
+ }
154
+
155
+ static VALUE mat3_class_projection(VALUE klass, VALUE width, VALUE height) {
156
+ double w = NUM2DBL(width);
157
+ double h = NUM2DBL(height);
158
+ return mat3_build9(klass, 2.0 / w, 0.0, 0.0, 0.0, -2.0 / h, 0.0, -1.0, 1.0,
159
+ 1.0);
160
+ }
161
+
162
+ static VALUE mat3_class_translation(VALUE klass, VALUE x, VALUE y) {
163
+ return mat3_build9(klass, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, NUM2DBL(x),
164
+ NUM2DBL(y), 1.0);
165
+ }
166
+
167
+ static VALUE mat3_class_rotation(VALUE klass, VALUE radians) {
168
+ double r = NUM2DBL(radians);
169
+ double c = cos(r);
170
+ double s = sin(r);
171
+ return mat3_build9(klass, c, s, 0.0, -s, c, 0.0, 0.0, 0.0, 1.0);
172
+ }
173
+
174
+ static VALUE mat3_class_scaling(VALUE klass, VALUE x, VALUE y) {
175
+ return mat3_build9(klass, NUM2DBL(x), 0.0, 0.0, 0.0,
176
+ NUM2DBL(y), 0.0, 0.0, 0.0, 1.0);
177
+ }
178
+
179
+ VALUE mat3_aref(VALUE self, VALUE index) {
180
+ Mat3Data *data = mat3_get(self);
181
+ long idx = NUM2LONG(index);
182
+ if (idx < 0 || idx > 8) {
183
+ return Qnil;
184
+ }
185
+ return DBL2NUM(data->data[idx]);
186
+ }
187
+
188
+ VALUE mat3_aset(VALUE self, VALUE index, VALUE value) {
189
+ rb_check_frozen(self);
190
+ Mat3Data *data = mat3_get(self);
191
+ long idx = NUM2LONG(index);
192
+ if (idx < 0 || idx > 8) {
193
+ rb_raise(rb_eIndexError, "index %ld out of range", idx);
194
+ }
195
+ double component = NUM2DBL(value);
196
+ rb_check_frozen(self);
197
+ data->data[idx] = component;
198
+ return value;
199
+ }
200
+
201
+ VALUE mat3_mul(VALUE self, VALUE other) {
202
+ Mat3Data *a = mat3_get(self);
203
+
204
+ if (rb_obj_is_kind_of(other, cMat3)) {
205
+ Mat3Data *b = mat3_get(other);
206
+ return mat3_build9(
207
+ rb_obj_class(self),
208
+ a->data[0] * b->data[0] + a->data[3] * b->data[1] +
209
+ a->data[6] * b->data[2],
210
+ a->data[1] * b->data[0] + a->data[4] * b->data[1] +
211
+ a->data[7] * b->data[2],
212
+ a->data[2] * b->data[0] + a->data[5] * b->data[1] +
213
+ a->data[8] * b->data[2],
214
+ a->data[0] * b->data[3] + a->data[3] * b->data[4] +
215
+ a->data[6] * b->data[5],
216
+ a->data[1] * b->data[3] + a->data[4] * b->data[4] +
217
+ a->data[7] * b->data[5],
218
+ a->data[2] * b->data[3] + a->data[5] * b->data[4] +
219
+ a->data[8] * b->data[5],
220
+ a->data[0] * b->data[6] + a->data[3] * b->data[7] +
221
+ a->data[6] * b->data[8],
222
+ a->data[1] * b->data[6] + a->data[4] * b->data[7] +
223
+ a->data[7] * b->data[8],
224
+ a->data[2] * b->data[6] + a->data[5] * b->data[7] +
225
+ a->data[8] * b->data[8]);
226
+ }
227
+
228
+ if (rb_obj_is_kind_of(other, cVec3)) {
229
+ double x = NUM2DBL(rb_funcall(other, rb_intern("x"), 0));
230
+ double y = NUM2DBL(rb_funcall(other, rb_intern("y"), 0));
231
+ double z = NUM2DBL(rb_funcall(other, rb_intern("z"), 0));
232
+ VALUE vec3_class = rb_const_get(mLarb, rb_intern("Vec3"));
233
+ return rb_funcall(vec3_class, rb_intern("new"), 3,
234
+ DBL2NUM(a->data[0] * x + a->data[3] * y +
235
+ a->data[6] * z),
236
+ DBL2NUM(a->data[1] * x + a->data[4] * y +
237
+ a->data[7] * z),
238
+ DBL2NUM(a->data[2] * x + a->data[5] * y +
239
+ a->data[8] * z));
240
+ }
241
+
242
+ if (rb_obj_is_kind_of(other, rb_cNumeric)) {
243
+ double s = NUM2DBL(other);
244
+ return mat3_build9(rb_obj_class(self), a->data[0] * s, a->data[1] * s,
245
+ a->data[2] * s, a->data[3] * s, a->data[4] * s,
246
+ a->data[5] * s, a->data[6] * s, a->data[7] * s,
247
+ a->data[8] * s);
248
+ }
249
+
250
+ rb_raise(rb_eTypeError, "unsupported operand for Mat3 multiplication");
251
+ }
252
+
253
+ VALUE mat3_add(VALUE self, VALUE other) {
254
+ Mat3Data *a = mat3_get(self);
255
+ Mat3Data *b = mat3_get(other);
256
+ return mat3_build9(rb_obj_class(self), a->data[0] + b->data[0],
257
+ a->data[1] + b->data[1], a->data[2] + b->data[2],
258
+ a->data[3] + b->data[3], a->data[4] + b->data[4],
259
+ a->data[5] + b->data[5], a->data[6] + b->data[6],
260
+ a->data[7] + b->data[7], a->data[8] + b->data[8]);
261
+ }
262
+
263
+ VALUE mat3_sub(VALUE self, VALUE other) {
264
+ Mat3Data *a = mat3_get(self);
265
+ Mat3Data *b = mat3_get(other);
266
+ return mat3_build9(rb_obj_class(self), a->data[0] - b->data[0],
267
+ a->data[1] - b->data[1], a->data[2] - b->data[2],
268
+ a->data[3] - b->data[3], a->data[4] - b->data[4],
269
+ a->data[5] - b->data[5], a->data[6] - b->data[6],
270
+ a->data[7] - b->data[7], a->data[8] - b->data[8]);
271
+ }
272
+
273
+ VALUE mat3_determinant(VALUE self) {
274
+ Mat3Data *a = mat3_get(self);
275
+ double det = a->data[0] * (a->data[4] * a->data[8] - a->data[5] * a->data[7]) -
276
+ a->data[3] * (a->data[1] * a->data[8] - a->data[2] * a->data[7]) +
277
+ a->data[6] * (a->data[1] * a->data[5] - a->data[2] * a->data[4]);
278
+ return DBL2NUM(det);
279
+ }
280
+
281
+ VALUE mat3_inverse(VALUE self) {
282
+ double inverse[9];
283
+ larb_matrix_inverse(mat3_get(self)->data, inverse, 3);
284
+ return mat3_build(rb_obj_class(self), inverse);
285
+ }
286
+
287
+ VALUE mat3_transpose(VALUE self) {
288
+ Mat3Data *a = mat3_get(self);
289
+ return mat3_build9(rb_obj_class(self), a->data[0], a->data[3], a->data[6],
290
+ a->data[1], a->data[4], a->data[7], a->data[2],
291
+ a->data[5], a->data[8]);
292
+ }
293
+
294
+ VALUE mat3_adjoint(VALUE self) {
295
+ Mat3Data *a = mat3_get(self);
296
+ return mat3_build9(
297
+ rb_obj_class(self), a->data[4] * a->data[8] - a->data[5] * a->data[7],
298
+ a->data[2] * a->data[7] - a->data[1] * a->data[8],
299
+ a->data[1] * a->data[5] - a->data[2] * a->data[4],
300
+ a->data[5] * a->data[6] - a->data[3] * a->data[8],
301
+ a->data[0] * a->data[8] - a->data[2] * a->data[6],
302
+ a->data[2] * a->data[3] - a->data[0] * a->data[5],
303
+ a->data[3] * a->data[7] - a->data[4] * a->data[6],
304
+ a->data[1] * a->data[6] - a->data[0] * a->data[7],
305
+ a->data[0] * a->data[4] - a->data[1] * a->data[3]);
306
+ }
307
+
308
+ VALUE mat3_frobenius_norm(VALUE self) {
309
+ Mat3Data *a = mat3_get(self);
310
+ double norm = 0.0;
311
+ for (int i = 0; i < 9; i++) {
312
+ norm = hypot(norm, a->data[i]);
313
+ }
314
+ return DBL2NUM(norm);
315
+ }
316
+
317
+ VALUE mat3_translate(VALUE self, VALUE x, VALUE y) {
318
+ Mat3Data *a = mat3_get(self);
319
+ double dx = NUM2DBL(x);
320
+ double dy = NUM2DBL(y);
321
+ return mat3_build9(rb_obj_class(self), a->data[0], a->data[1], a->data[2],
322
+ a->data[3], a->data[4], a->data[5],
323
+ dx * a->data[0] + dy * a->data[3] + a->data[6],
324
+ dx * a->data[1] + dy * a->data[4] + a->data[7],
325
+ dx * a->data[2] + dy * a->data[5] + a->data[8]);
326
+ }
327
+
328
+ VALUE mat3_rotate(VALUE self, VALUE radians) {
329
+ VALUE rot = mat3_class_rotation(cMat3, radians);
330
+ return mat3_mul(self, rot);
331
+ }
332
+
333
+ VALUE mat3_scale(VALUE self, VALUE x, VALUE y) {
334
+ Mat3Data *a = mat3_get(self);
335
+ double sx = NUM2DBL(x);
336
+ double sy = NUM2DBL(y);
337
+ return mat3_build9(rb_obj_class(self), a->data[0] * sx, a->data[1] * sx,
338
+ a->data[2] * sx, a->data[3] * sy, a->data[4] * sy,
339
+ a->data[5] * sy, a->data[6], a->data[7], a->data[8]);
340
+ }
341
+
342
+ VALUE mat3_to_a(VALUE self) {
343
+ Mat3Data *a = mat3_get(self);
344
+ VALUE ary = rb_ary_new_capa(9);
345
+ for (int i = 0; i < 9; i++) {
346
+ rb_ary_push(ary, DBL2NUM(a->data[i]));
347
+ }
348
+ return ary;
349
+ }
350
+
351
+ VALUE mat3_data(VALUE self) {
352
+ return mat3_to_a(self);
353
+ }
354
+
355
+ VALUE mat3_equal(VALUE self, VALUE other) {
356
+ if (!rb_obj_is_kind_of(other, cMat3)) {
357
+ return Qfalse;
358
+ }
359
+ Mat3Data *a = mat3_get(self);
360
+ Mat3Data *b = mat3_get(other);
361
+ for (int i = 0; i < 9; i++) {
362
+ if (a->data[i] != b->data[i]) {
363
+ return Qfalse;
364
+ }
365
+ }
366
+ return Qtrue;
367
+ }
368
+
369
+ VALUE mat3_near(int argc, VALUE *argv, VALUE self) {
370
+ VALUE other = Qnil;
371
+ VALUE epsilon = Qnil;
372
+
373
+ rb_scan_args(argc, argv, "11", &other, &epsilon);
374
+ Mat3Data *a = mat3_get(self);
375
+ Mat3Data *b = mat3_get(other);
376
+ double eps = argc < 2 ? 1e-6 : NUM2DBL(epsilon);
377
+ if (!isfinite(eps) || eps <= 0.0) {
378
+ rb_raise(rb_eArgError, "epsilon must be finite and positive");
379
+ }
380
+
381
+ for (int i = 0; i < 9; i++) {
382
+ if (!(fabs(a->data[i] - b->data[i]) < eps)) {
383
+ return Qfalse;
384
+ }
385
+ }
386
+ return Qtrue;
387
+ }
388
+
389
+ static VALUE mat3_format_value(double value) {
390
+ return rb_funcall(rb_mKernel, rb_intern("format"), 2,
391
+ rb_str_new_cstr("%8.4f"), DBL2NUM(value));
392
+ }
393
+
394
+ static VALUE mat3_row_string(const double *values, int offset) {
395
+ VALUE str = mat3_format_value(values[offset]);
396
+ for (int i = 1; i < 3; i++) {
397
+ rb_str_cat_cstr(str, ", ");
398
+ rb_str_concat(str, mat3_format_value(values[offset + i]));
399
+ }
400
+ return str;
401
+ }
402
+
403
+ VALUE mat3_inspect(VALUE self) {
404
+ Mat3Data *a = mat3_get(self);
405
+ VALUE str = rb_str_new_cstr("Mat3[\n ");
406
+ rb_str_concat(str, mat3_row_string(a->data, 0));
407
+ rb_str_cat_cstr(str, "\n ");
408
+ rb_str_concat(str, mat3_row_string(a->data, 3));
409
+ rb_str_cat_cstr(str, "\n ");
410
+ rb_str_concat(str, mat3_row_string(a->data, 6));
411
+ rb_str_cat_cstr(str, "\n]");
412
+ return str;
413
+ }
414
+
415
+ void Init_mat3(VALUE module) {
416
+ cMat3 = rb_define_class_under(module, "Mat3", rb_cObject);
417
+ cVec3 = rb_const_get(mLarb, rb_intern("Vec3"));
418
+
419
+ rb_define_alloc_func(cMat3, mat3_alloc);
420
+ rb_define_method(cMat3, "initialize", mat3_initialize, -1);
421
+ rb_define_method(cMat3, "initialize_copy", mat3_initialize_copy, 1);
422
+
423
+ rb_define_singleton_method(cMat3, "identity", mat3_class_identity, 0);
424
+ rb_define_singleton_method(cMat3, "zero", mat3_class_zero, 0);
425
+ rb_define_singleton_method(cMat3, "from_mat4", mat3_class_from_mat4, 1);
426
+ rb_define_singleton_method(cMat3, "from_mat2d", mat3_class_from_mat2d, 1);
427
+ rb_define_singleton_method(cMat3, "from_quaternion",
428
+ mat3_class_from_quaternion, 1);
429
+ rb_define_singleton_method(cMat3, "normal_from_mat4",
430
+ mat3_class_normal_from_mat4, 1);
431
+ rb_define_singleton_method(cMat3, "projection", mat3_class_projection, 2);
432
+ rb_define_singleton_method(cMat3, "translation", mat3_class_translation, 2);
433
+ rb_define_singleton_method(cMat3, "rotation", mat3_class_rotation, 1);
434
+ rb_define_singleton_method(cMat3, "scaling", mat3_class_scaling, 2);
435
+
436
+ rb_define_method(cMat3, "data", mat3_data, 0);
437
+ rb_define_method(cMat3, "[]", mat3_aref, 1);
438
+ rb_define_method(cMat3, "[]=", mat3_aset, 2);
439
+ rb_define_method(cMat3, "*", mat3_mul, 1);
440
+ rb_define_method(cMat3, "+", mat3_add, 1);
441
+ rb_define_method(cMat3, "-", mat3_sub, 1);
442
+ rb_define_method(cMat3, "determinant", mat3_determinant, 0);
443
+ rb_define_method(cMat3, "inverse", mat3_inverse, 0);
444
+ rb_define_method(cMat3, "transpose", mat3_transpose, 0);
445
+ rb_define_method(cMat3, "adjoint", mat3_adjoint, 0);
446
+ rb_define_method(cMat3, "frobenius_norm", mat3_frobenius_norm, 0);
447
+ rb_define_method(cMat3, "translate", mat3_translate, 2);
448
+ rb_define_method(cMat3, "rotate", mat3_rotate, 1);
449
+ rb_define_method(cMat3, "scale", mat3_scale, 2);
450
+ rb_define_method(cMat3, "to_a", mat3_to_a, 0);
451
+ rb_define_method(cMat3, "==", mat3_equal, 1);
452
+ rb_define_method(cMat3, "near?", mat3_near, -1);
453
+ rb_define_method(cMat3, "inspect", mat3_inspect, 0);
454
+ rb_define_alias(cMat3, "to_s", "inspect");
455
+ }
data/ext/larb/mat3.h ADDED
@@ -0,0 +1,33 @@
1
+ #ifndef MAT3_H
2
+ #define MAT3_H
3
+
4
+ #include "larb.h"
5
+
6
+ typedef struct {
7
+ double data[9];
8
+ } Mat3Data;
9
+
10
+ void Init_mat3(VALUE module);
11
+ VALUE mat3_alloc(VALUE klass);
12
+ VALUE mat3_initialize(int argc, VALUE *argv, VALUE self);
13
+
14
+ VALUE mat3_aref(VALUE self, VALUE index);
15
+ VALUE mat3_aset(VALUE self, VALUE index, VALUE value);
16
+ VALUE mat3_mul(VALUE self, VALUE other);
17
+ VALUE mat3_add(VALUE self, VALUE other);
18
+ VALUE mat3_sub(VALUE self, VALUE other);
19
+ VALUE mat3_determinant(VALUE self);
20
+ VALUE mat3_inverse(VALUE self);
21
+ VALUE mat3_transpose(VALUE self);
22
+ VALUE mat3_adjoint(VALUE self);
23
+ VALUE mat3_frobenius_norm(VALUE self);
24
+ VALUE mat3_translate(VALUE self, VALUE x, VALUE y);
25
+ VALUE mat3_rotate(VALUE self, VALUE radians);
26
+ VALUE mat3_scale(VALUE self, VALUE x, VALUE y);
27
+ VALUE mat3_to_a(VALUE self);
28
+ VALUE mat3_equal(VALUE self, VALUE other);
29
+ VALUE mat3_near(int argc, VALUE *argv, VALUE self);
30
+ VALUE mat3_inspect(VALUE self);
31
+ VALUE mat3_data(VALUE self);
32
+
33
+ #endif