fast_matrix 0.2.0 → 0.3.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/README.md +5 -3
- data/ext/fast_matrix/Helper/c_array_opeartions.c +24 -0
- data/ext/fast_matrix/Helper/c_array_operations.h +3 -0
- data/ext/fast_matrix/Helper/errors.c +2 -0
- data/ext/fast_matrix/Helper/errors.h +1 -0
- data/ext/fast_matrix/LUPDecomposition/c_lup.c +97 -0
- data/ext/fast_matrix/LUPDecomposition/c_lup.h +22 -0
- data/ext/fast_matrix/LUPDecomposition/helper.h +14 -0
- data/ext/fast_matrix/LUPDecomposition/lup.c +124 -0
- data/ext/fast_matrix/LUPDecomposition/lup.h +10 -0
- data/ext/fast_matrix/Matrix/c_matrix.c +131 -0
- data/ext/fast_matrix/Matrix/c_matrix.h +5 -0
- data/ext/fast_matrix/Matrix/errors.h +7 -0
- data/ext/fast_matrix/Matrix/matrix.c +205 -11
- data/ext/fast_matrix/Vector/c_vector.h +2 -0
- data/ext/fast_matrix/Vector/errors.h +7 -0
- data/ext/fast_matrix/Vector/vector.c +94 -10
- data/ext/fast_matrix/c_include.c +3 -0
- data/ext/fast_matrix/fast_matrix.c +6 -2
- data/ext/fast_matrix/fast_matrix.h +0 -4
- data/lib/errors.rb +1 -1
- data/lib/fast_matrix.rb +1 -0
- data/lib/fast_matrix/version.rb +1 -1
- data/lib/lup_decomposition/lup_decomposition.rb +24 -0
- data/lib/matrix/matrix.rb +88 -0
- data/lib/scalar.rb +55 -4
- data/lib/vector/vector.rb +8 -1
- metadata +8 -2
@@ -16,6 +16,8 @@ struct matrix
|
|
16
16
|
int n;
|
17
17
|
|
18
18
|
double* data;
|
19
|
+
|
20
|
+
bool frozen;
|
19
21
|
};
|
20
22
|
|
21
23
|
double c_matrix_trace(int n, const double* A);
|
@@ -30,6 +32,7 @@ void c_matrix_column_vector(int m, int n, const double* M, double* V, int idx);
|
|
30
32
|
void c_matrix_scalar(int n, double* C, double v);
|
31
33
|
void c_matrix_minor(int m, int n, const double* A, double* B, int m_idx, int n_idx);
|
32
34
|
void c_matrix_vstack(int argc, struct matrix** mtrs, double* C);
|
35
|
+
void c_matrix_lup(int n, const double* A, double* LU, int* V, int* sign, bool* singular);
|
33
36
|
|
34
37
|
bool c_matrix_symmetric(int n, const double* C);
|
35
38
|
bool c_matrix_antisymmetric(int n, const double* C);
|
@@ -41,6 +44,8 @@ bool c_matrix_identity(int n, const double* A);
|
|
41
44
|
bool c_matrix_equal_by_m(int argc, struct matrix** mtrs);
|
42
45
|
bool c_matrix_equal_by_n(int argc, struct matrix** mtrs);
|
43
46
|
bool c_matrix_inverse(int n, const double* A, double* B);
|
47
|
+
bool c_matrix_adjugate(int n, const double* A, double* B);
|
48
|
+
bool c_matrix_exponentiation(int m, int n, const double* A, double* B, int d);
|
44
49
|
|
45
50
|
int c_matrix_sum_by_m(int argc, struct matrix** mtrs);
|
46
51
|
int c_matrix_sum_by_n(int argc, struct matrix** mtrs);
|
@@ -18,6 +18,13 @@ inline void raise_check_square_matrix(struct matrix* A)
|
|
18
18
|
rb_raise(fm_eIndexError, "Expected square matrix");
|
19
19
|
}
|
20
20
|
|
21
|
+
// check if the matrix is frozen and raise an error if not
|
22
|
+
inline void raise_check_frozen_matrix(struct matrix* A)
|
23
|
+
{
|
24
|
+
if(A->frozen)
|
25
|
+
rb_raise(fm_eFrozenError, "Can't modify frozen Matrix");
|
26
|
+
}
|
27
|
+
|
21
28
|
// check if the value is zero and raise an error if not
|
22
29
|
inline void raise_check_no_arguments(int argc)
|
23
30
|
{
|
@@ -5,6 +5,8 @@
|
|
5
5
|
#include "Matrix/errors.h"
|
6
6
|
#include "Matrix/helper.h"
|
7
7
|
#include "Vector/helper.h"
|
8
|
+
#include "LUPDecomposition/c_lup.h"
|
9
|
+
#include "LUPDecomposition/lup.h"
|
8
10
|
|
9
11
|
VALUE cMatrix;
|
10
12
|
|
@@ -39,6 +41,7 @@ VALUE matrix_alloc(VALUE self)
|
|
39
41
|
{
|
40
42
|
struct matrix* mtx = malloc(sizeof(struct matrix));
|
41
43
|
mtx->data = NULL;
|
44
|
+
mtx->frozen = false;
|
42
45
|
return TypedData_Wrap_Struct(self, &matrix_type, mtx);
|
43
46
|
}
|
44
47
|
|
@@ -46,7 +49,7 @@ VALUE matrix_initialize(VALUE self, VALUE rows_count, VALUE columns_count)
|
|
46
49
|
{
|
47
50
|
int m = raise_rb_value_to_int(columns_count);
|
48
51
|
int n = raise_rb_value_to_int(rows_count);
|
49
|
-
|
52
|
+
|
50
53
|
if(m <= 0 || n <= 0)
|
51
54
|
rb_raise(fm_eIndexError, "Size cannot be negative or zero");
|
52
55
|
|
@@ -58,11 +61,13 @@ VALUE matrix_initialize(VALUE self, VALUE rows_count, VALUE columns_count)
|
|
58
61
|
// []=
|
59
62
|
VALUE matrix_set(VALUE self, VALUE row, VALUE column, VALUE v)
|
60
63
|
{
|
64
|
+
struct matrix* data = get_matrix_from_rb_value(self);
|
65
|
+
raise_check_frozen_matrix(data);
|
66
|
+
|
61
67
|
int m = raise_rb_value_to_int(column);
|
62
68
|
int n = raise_rb_value_to_int(row);
|
63
69
|
double x = raise_rb_value_to_double(v);
|
64
|
-
|
65
|
-
|
70
|
+
|
66
71
|
m = (m < 0) ? data->m + m : m;
|
67
72
|
n = (n < 0) ? data->n + n : n;
|
68
73
|
|
@@ -158,11 +163,53 @@ VALUE matrix_multiply(VALUE self, VALUE v)
|
|
158
163
|
return matrix_multiply_mn(self, v);
|
159
164
|
if(RBASIC_CLASS(v) == cMatrix)
|
160
165
|
return matrix_strassen(self, v);
|
161
|
-
if(RBASIC_CLASS(v) == cVector)
|
166
|
+
if(RBASIC_CLASS(v) == cVector)
|
162
167
|
return matrix_multiply_mv(self, v);
|
163
168
|
rb_raise(fm_eTypeError, "Invalid klass for multiply");
|
164
169
|
}
|
165
170
|
|
171
|
+
VALUE matrix_division_mn(VALUE self, VALUE value)
|
172
|
+
{
|
173
|
+
double d = NUM2DBL(value);
|
174
|
+
struct matrix* A = get_matrix_from_rb_value(self);
|
175
|
+
|
176
|
+
MAKE_MATRIX_AND_RB_VALUE(R, result, A->m, A->n);
|
177
|
+
copy_d_array(A->m * A->n, A->data, R->data);
|
178
|
+
multiply_d_array(R->m * R->n, R->data, 1 / d);
|
179
|
+
|
180
|
+
return result;
|
181
|
+
}
|
182
|
+
|
183
|
+
VALUE matrix_division_mm(VALUE self, VALUE other)
|
184
|
+
{
|
185
|
+
struct matrix* A = get_matrix_from_rb_value(self);
|
186
|
+
struct matrix* B = get_matrix_from_rb_value(other);
|
187
|
+
|
188
|
+
if(A->m != B->n)
|
189
|
+
rb_raise(fm_eIndexError, "First columns differs from second rows");
|
190
|
+
raise_check_square_matrix(B);
|
191
|
+
|
192
|
+
int n = B->n;
|
193
|
+
double* M = malloc(n * n * sizeof(double));
|
194
|
+
c_matrix_inverse(n, B->data, M);
|
195
|
+
|
196
|
+
MAKE_MATRIX_AND_RB_VALUE(C, result, n, n);
|
197
|
+
c_matrix_strassen(n, n, n, A->data, M, C->data);
|
198
|
+
|
199
|
+
free(M);
|
200
|
+
return result;
|
201
|
+
}
|
202
|
+
|
203
|
+
VALUE matrix_division(VALUE self, VALUE v)
|
204
|
+
{
|
205
|
+
if(RB_FLOAT_TYPE_P(v) || FIXNUM_P(v)
|
206
|
+
|| RB_TYPE_P(v, T_BIGNUM))
|
207
|
+
return matrix_division_mn(self, v);
|
208
|
+
if(RBASIC_CLASS(v) == cMatrix)
|
209
|
+
return matrix_division_mm(self, v);
|
210
|
+
rb_raise(fm_eTypeError, "Invalid klass for division");
|
211
|
+
}
|
212
|
+
|
166
213
|
VALUE matrix_copy(VALUE self)
|
167
214
|
{
|
168
215
|
struct matrix* M = get_matrix_from_rb_value(self);
|
@@ -207,8 +254,9 @@ VALUE matrix_add_with(VALUE self, VALUE other)
|
|
207
254
|
|
208
255
|
VALUE matrix_add_from(VALUE self, VALUE other)
|
209
256
|
{
|
210
|
-
raise_check_rbasic(other, cMatrix, "matrix");
|
211
257
|
struct matrix* A = get_matrix_from_rb_value(self);
|
258
|
+
raise_check_frozen_matrix(A);
|
259
|
+
raise_check_rbasic(other, cMatrix, "matrix");
|
212
260
|
struct matrix* B = get_matrix_from_rb_value(other);
|
213
261
|
|
214
262
|
raise_check_equal_size_matrix(A, B);
|
@@ -232,8 +280,9 @@ VALUE matrix_sub_with(VALUE self, VALUE other)
|
|
232
280
|
|
233
281
|
VALUE matrix_sub_from(VALUE self, VALUE other)
|
234
282
|
{
|
235
|
-
raise_check_rbasic(other, cMatrix, "matrix");
|
236
283
|
struct matrix* A = get_matrix_from_rb_value(self);
|
284
|
+
raise_check_frozen_matrix(A);
|
285
|
+
raise_check_rbasic(other, cMatrix, "matrix");
|
237
286
|
struct matrix* B = get_matrix_from_rb_value(other);
|
238
287
|
|
239
288
|
raise_check_equal_size_matrix(A, B);
|
@@ -251,8 +300,9 @@ VALUE matrix_determinant(VALUE self)
|
|
251
300
|
|
252
301
|
VALUE matrix_fill(VALUE self, VALUE value)
|
253
302
|
{
|
254
|
-
double d = raise_rb_value_to_double(value);
|
255
303
|
struct matrix* A = get_matrix_from_rb_value(self);
|
304
|
+
raise_check_frozen_matrix(A);
|
305
|
+
double d = raise_rb_value_to_double(value);
|
256
306
|
fill_d_array(A->m * A->n, A->data, d);
|
257
307
|
return self;
|
258
308
|
}
|
@@ -293,7 +343,46 @@ VALUE matrix_greater_or_equal(VALUE self, VALUE other)
|
|
293
343
|
return Qfalse;
|
294
344
|
}
|
295
345
|
|
296
|
-
|
346
|
+
VALUE matrix_less_or_equal(VALUE self, VALUE other)
|
347
|
+
{
|
348
|
+
raise_check_rbasic(other, cMatrix, "matrix");
|
349
|
+
struct matrix* A = get_matrix_from_rb_value(self);
|
350
|
+
struct matrix* B = get_matrix_from_rb_value(other);
|
351
|
+
|
352
|
+
raise_check_equal_size_matrix(A, B);
|
353
|
+
|
354
|
+
if(less_or_equal_d_array(A->n * A->m, A->data, B->data))
|
355
|
+
return Qtrue;
|
356
|
+
return Qfalse;
|
357
|
+
}
|
358
|
+
|
359
|
+
VALUE matrix_greater(VALUE self, VALUE other)
|
360
|
+
{
|
361
|
+
raise_check_rbasic(other, cMatrix, "matrix");
|
362
|
+
struct matrix* A = get_matrix_from_rb_value(self);
|
363
|
+
struct matrix* B = get_matrix_from_rb_value(other);
|
364
|
+
|
365
|
+
raise_check_equal_size_matrix(A, B);
|
366
|
+
|
367
|
+
if(greater_d_array(A->n * A->m, A->data, B->data))
|
368
|
+
return Qtrue;
|
369
|
+
return Qfalse;
|
370
|
+
}
|
371
|
+
|
372
|
+
VALUE matrix_less(VALUE self, VALUE other)
|
373
|
+
{
|
374
|
+
raise_check_rbasic(other, cMatrix, "matrix");
|
375
|
+
struct matrix* A = get_matrix_from_rb_value(self);
|
376
|
+
struct matrix* B = get_matrix_from_rb_value(other);
|
377
|
+
|
378
|
+
raise_check_equal_size_matrix(A, B);
|
379
|
+
|
380
|
+
if(less_d_array(A->n * A->m, A->data, B->data))
|
381
|
+
return Qtrue;
|
382
|
+
return Qfalse;
|
383
|
+
}
|
384
|
+
|
385
|
+
void convert_matrix_array(int argc, VALUE *argv, struct matrix*** mtrs)
|
297
386
|
{
|
298
387
|
for(int i = 0; i < argc; ++i)
|
299
388
|
raise_check_rbasic(argv[i], cMatrix, "matrix");
|
@@ -517,7 +606,7 @@ VALUE matrix_round(int argc, VALUE *argv, VALUE self)
|
|
517
606
|
else
|
518
607
|
d = 0;
|
519
608
|
|
520
|
-
|
609
|
+
struct matrix* A = get_matrix_from_rb_value(self);
|
521
610
|
MAKE_MATRIX_AND_RB_VALUE(R, result, A->m, A->n);
|
522
611
|
round_d_array(A->m * A->n, A->data, R->data, d);
|
523
612
|
return result;
|
@@ -584,6 +673,101 @@ VALUE matrix_inverse(VALUE self)
|
|
584
673
|
return result;
|
585
674
|
}
|
586
675
|
|
676
|
+
VALUE matrix_adjugate(VALUE self)
|
677
|
+
{
|
678
|
+
struct matrix* A = get_matrix_from_rb_value(self);
|
679
|
+
raise_check_square_matrix(A);
|
680
|
+
MAKE_MATRIX_AND_RB_VALUE(R, result, A->n, A->n);
|
681
|
+
if(!c_matrix_adjugate(R->n, A->data, R->data))
|
682
|
+
rb_raise(fm_eIndexError, "The discriminant is zero");
|
683
|
+
return result;
|
684
|
+
}
|
685
|
+
|
686
|
+
VALUE matrix_exponentiation(VALUE self, VALUE value)
|
687
|
+
{
|
688
|
+
struct matrix* A = get_matrix_from_rb_value(self);
|
689
|
+
int d = raise_rb_value_to_int(value);
|
690
|
+
|
691
|
+
MAKE_MATRIX_AND_RB_VALUE(C, result, A->m, A->n);
|
692
|
+
if(!c_matrix_exponentiation(A->m, A->n, A->data, C->data, d))
|
693
|
+
rb_raise(fm_eIndexError, "Invalid exponentiation");
|
694
|
+
return result;
|
695
|
+
}
|
696
|
+
|
697
|
+
VALUE matrix_normal(VALUE self)
|
698
|
+
{
|
699
|
+
struct matrix* A = get_matrix_from_rb_value(self);
|
700
|
+
if(A->m != A-> n)
|
701
|
+
return Qfalse;
|
702
|
+
|
703
|
+
int n = A->n;
|
704
|
+
double* B = malloc(n * n * sizeof(double));
|
705
|
+
double* C = malloc(n * n * sizeof(double));
|
706
|
+
double* D = malloc(n * n * sizeof(double));
|
707
|
+
|
708
|
+
c_matrix_transpose(n, n, A->data, B);
|
709
|
+
c_matrix_strassen(n, n, n, A->data, B, C);
|
710
|
+
c_matrix_strassen(n, n, n, B, A->data, D);
|
711
|
+
|
712
|
+
VALUE res = Qfalse;
|
713
|
+
if(equal_d_arrays(n * n, C, D))
|
714
|
+
res = Qtrue;
|
715
|
+
|
716
|
+
free(B);
|
717
|
+
free(C);
|
718
|
+
free(D);
|
719
|
+
return res;
|
720
|
+
}
|
721
|
+
|
722
|
+
VALUE matrix_unitary(VALUE self)
|
723
|
+
{
|
724
|
+
struct matrix* A = get_matrix_from_rb_value(self);
|
725
|
+
if(A->m != A-> n)
|
726
|
+
return Qfalse;
|
727
|
+
|
728
|
+
int n = A->n;
|
729
|
+
double* B = malloc(n * n * sizeof(double));
|
730
|
+
double* C = malloc(n * n * sizeof(double));
|
731
|
+
|
732
|
+
c_matrix_transpose(n, n, A->data, B);
|
733
|
+
c_matrix_strassen(n, n, n, A->data, B, C);
|
734
|
+
|
735
|
+
VALUE res = Qfalse;
|
736
|
+
if(c_matrix_identity(n, C))
|
737
|
+
res = Qtrue;
|
738
|
+
|
739
|
+
free(B);
|
740
|
+
free(C);
|
741
|
+
return res;
|
742
|
+
}
|
743
|
+
|
744
|
+
VALUE matrix_freeze(VALUE self)
|
745
|
+
{
|
746
|
+
struct matrix* A = get_matrix_from_rb_value(self);
|
747
|
+
A->frozen = true;
|
748
|
+
return self;
|
749
|
+
}
|
750
|
+
|
751
|
+
VALUE matrix_lup(VALUE self)
|
752
|
+
{
|
753
|
+
struct matrix* A = get_matrix_from_rb_value(self);
|
754
|
+
raise_check_square_matrix(A);
|
755
|
+
|
756
|
+
int n = A->n;
|
757
|
+
|
758
|
+
struct lupdecomposition lp;
|
759
|
+
lp.n = n;
|
760
|
+
lp.data = malloc(n * n * sizeof(double));
|
761
|
+
lp.permutation = malloc(n * sizeof(double));
|
762
|
+
c_matrix_lup(n, A->data, lp.data, lp.permutation, &(lp.pivot_sign), &(lp.singular));
|
763
|
+
|
764
|
+
struct lupdecomposition* p_lp;
|
765
|
+
VALUE result = TypedData_Make_Struct(cLUPDecomposition, struct lupdecomposition, &lup_type, p_lp);
|
766
|
+
*p_lp = lp;
|
767
|
+
|
768
|
+
return result;
|
769
|
+
}
|
770
|
+
|
587
771
|
void init_fm_matrix()
|
588
772
|
{
|
589
773
|
VALUE mod = rb_define_module("FastMatrix");
|
@@ -600,12 +784,15 @@ void init_fm_matrix()
|
|
600
784
|
rb_define_method(cMatrix, "clone", matrix_copy, 0);
|
601
785
|
rb_define_method(cMatrix, "transpose", matrix_transpose, 0);
|
602
786
|
rb_define_method(cMatrix, "+", matrix_add_with, 1);
|
603
|
-
rb_define_method(cMatrix, "
|
787
|
+
rb_define_method(cMatrix, "add!", matrix_add_from, 1);
|
604
788
|
rb_define_method(cMatrix, "-", matrix_sub_with, 1);
|
605
|
-
rb_define_method(cMatrix, "
|
789
|
+
rb_define_method(cMatrix, "sub!", matrix_sub_from, 1);
|
606
790
|
rb_define_method(cMatrix, "fill!", matrix_fill, 1);
|
607
791
|
rb_define_method(cMatrix, "abs", matrix_abs, 0);
|
608
792
|
rb_define_method(cMatrix, ">=", matrix_greater_or_equal, 1);
|
793
|
+
rb_define_method(cMatrix, "<=", matrix_less_or_equal, 1);
|
794
|
+
rb_define_method(cMatrix, ">", matrix_greater, 1);
|
795
|
+
rb_define_method(cMatrix, "<", matrix_less, 1);
|
609
796
|
rb_define_method(cMatrix, "determinant", matrix_determinant, 0);
|
610
797
|
rb_define_method(cMatrix, "eql?", matrix_equal, 1);
|
611
798
|
rb_define_method(cMatrix, "antisymmetric?", matrix_antisymmetric, 0);
|
@@ -627,6 +814,13 @@ void init_fm_matrix()
|
|
627
814
|
rb_define_method(cMatrix, "permutation?", matrix_permutation, 0);
|
628
815
|
rb_define_method(cMatrix, "orthogonal?", matrix_orthogonal, 0);
|
629
816
|
rb_define_method(cMatrix, "inverse", matrix_inverse, 0);
|
817
|
+
rb_define_method(cMatrix, "adjugate", matrix_adjugate, 0);
|
818
|
+
rb_define_method(cMatrix, "/", matrix_division, 1);
|
819
|
+
rb_define_method(cMatrix, "**", matrix_exponentiation, 1);
|
820
|
+
rb_define_method(cMatrix, "normal?", matrix_normal, 0);
|
821
|
+
rb_define_method(cMatrix, "unitary?", matrix_unitary, 0);
|
822
|
+
rb_define_method(cMatrix, "freeze", matrix_freeze, 0);
|
823
|
+
rb_define_method(cMatrix, "lup", matrix_lup, 0);
|
630
824
|
rb_define_module_function(cMatrix, "vstack", matrix_vstack, -1);
|
631
825
|
rb_define_module_function(cMatrix, "hstack", matrix_hstack, -1);
|
632
826
|
rb_define_module_function(cMatrix, "scalar", matrix_scalar, 2);
|
@@ -11,4 +11,11 @@ inline void raise_check_equal_size_vectors(struct vector* A, struct vector* B)
|
|
11
11
|
rb_raise(fm_eIndexError, "Different sizes vectors");
|
12
12
|
}
|
13
13
|
|
14
|
+
// check if the vector is frozen and raise an error if not
|
15
|
+
inline void raise_check_frozen_vector(struct vector* A)
|
16
|
+
{
|
17
|
+
if(A->frozen)
|
18
|
+
rb_raise(fm_eFrozenError, "Can't modify frozen Vector");
|
19
|
+
}
|
20
|
+
|
14
21
|
#endif /* FAST_MATRIX_VECTOR_ERRORS_H */
|
@@ -41,6 +41,7 @@ VALUE vector_alloc(VALUE self)
|
|
41
41
|
{
|
42
42
|
struct vector* vct = malloc(sizeof(struct vector));
|
43
43
|
vct->data = NULL;
|
44
|
+
vct->frozen = false;
|
44
45
|
return TypedData_Wrap_Struct(self, &vector_type, vct);
|
45
46
|
}
|
46
47
|
|
@@ -51,7 +52,7 @@ VALUE vector_initialize(VALUE self, VALUE size)
|
|
51
52
|
if(n <= 0)
|
52
53
|
rb_raise(fm_eIndexError, "Size cannot be negative or zero");
|
53
54
|
|
54
|
-
|
55
|
+
struct vector* data = get_vector_from_rb_value(self);
|
55
56
|
c_vector_init(data, n);
|
56
57
|
|
57
58
|
return self;
|
@@ -60,9 +61,10 @@ VALUE vector_initialize(VALUE self, VALUE size)
|
|
60
61
|
// []=
|
61
62
|
VALUE vector_set(VALUE self, VALUE idx, VALUE v)
|
62
63
|
{
|
64
|
+
struct vector* data = get_vector_from_rb_value(self);
|
65
|
+
raise_check_frozen_vector(data);
|
63
66
|
int i = raise_rb_value_to_int(idx);
|
64
67
|
double x = raise_rb_value_to_double(v);
|
65
|
-
struct vector* data = get_vector_from_rb_value(self);
|
66
68
|
|
67
69
|
i = (i < 0) ? data->n + i : i;
|
68
70
|
raise_check_range(i, 0, data->n);
|
@@ -113,8 +115,9 @@ VALUE vector_add_with(VALUE self, VALUE other)
|
|
113
115
|
|
114
116
|
VALUE vector_add_from(VALUE self, VALUE other)
|
115
117
|
{
|
116
|
-
raise_check_rbasic(other, cVector, "vector");
|
117
118
|
struct vector* A = get_vector_from_rb_value(self);
|
119
|
+
raise_check_frozen_vector(A);
|
120
|
+
raise_check_rbasic(other, cVector, "vector");
|
118
121
|
struct vector* B = get_vector_from_rb_value(other);
|
119
122
|
raise_check_equal_size_vectors(A, B);
|
120
123
|
|
@@ -162,8 +165,9 @@ VALUE vector_equal(VALUE self, VALUE other)
|
|
162
165
|
{
|
163
166
|
if(RBASIC_CLASS(other) != cVector)
|
164
167
|
return Qfalse;
|
165
|
-
|
166
|
-
|
168
|
+
|
169
|
+
struct vector* A = get_vector_from_rb_value(self);
|
170
|
+
struct vector* B = get_vector_from_rb_value(other);
|
167
171
|
|
168
172
|
if(A->n != B->n)
|
169
173
|
return Qfalse;
|
@@ -297,7 +301,7 @@ VALUE vector_plus(VALUE self)
|
|
297
301
|
return self;
|
298
302
|
}
|
299
303
|
|
300
|
-
|
304
|
+
void convert_vector_array(int argc, VALUE *argv, struct vector*** vcts)
|
301
305
|
{
|
302
306
|
for(int i = 0; i < argc; ++i)
|
303
307
|
raise_check_rbasic(argv[i], cVector, "vector");
|
@@ -367,8 +371,9 @@ VALUE vector_zero(VALUE self)
|
|
367
371
|
|
368
372
|
VALUE vector_fill(VALUE self, VALUE value)
|
369
373
|
{
|
370
|
-
double d = raise_rb_value_to_double(value);
|
371
374
|
struct vector* A = get_vector_from_rb_value(self);
|
375
|
+
raise_check_frozen_vector(A);
|
376
|
+
double d = raise_rb_value_to_double(value);
|
372
377
|
fill_d_array(A->n, A->data, d);
|
373
378
|
return self;
|
374
379
|
}
|
@@ -383,7 +388,7 @@ VALUE vector_round(int argc, VALUE *argv, VALUE self)
|
|
383
388
|
else
|
384
389
|
d = 0;
|
385
390
|
|
386
|
-
|
391
|
+
struct vector* A = get_vector_from_rb_value(self);
|
387
392
|
|
388
393
|
struct vector* R;
|
389
394
|
VALUE result = TypedData_Make_Struct(cVector, struct vector, &vector_type, R);
|
@@ -441,6 +446,79 @@ VALUE vector_cross_product(int argc, VALUE* argv, VALUE obj)
|
|
441
446
|
return result;
|
442
447
|
}
|
443
448
|
|
449
|
+
VALUE vector_greater_or_equal(VALUE self, VALUE other)
|
450
|
+
{
|
451
|
+
raise_check_rbasic(other, cVector, "vector");
|
452
|
+
struct vector* A = get_vector_from_rb_value(self);
|
453
|
+
struct vector* B = get_vector_from_rb_value(other);
|
454
|
+
|
455
|
+
raise_check_equal_size_vectors(A, B);
|
456
|
+
|
457
|
+
if(greater_or_equal_d_array(A->n, A->data, B->data))
|
458
|
+
return Qtrue;
|
459
|
+
return Qfalse;
|
460
|
+
}
|
461
|
+
|
462
|
+
VALUE vector_less_or_equal(VALUE self, VALUE other)
|
463
|
+
{
|
464
|
+
raise_check_rbasic(other, cVector, "vector");
|
465
|
+
struct vector* A = get_vector_from_rb_value(self);
|
466
|
+
struct vector* B = get_vector_from_rb_value(other);
|
467
|
+
|
468
|
+
raise_check_equal_size_vectors(A, B);
|
469
|
+
|
470
|
+
if(less_or_equal_d_array(A->n, A->data, B->data))
|
471
|
+
return Qtrue;
|
472
|
+
return Qfalse;
|
473
|
+
}
|
474
|
+
|
475
|
+
VALUE vector_greater(VALUE self, VALUE other)
|
476
|
+
{
|
477
|
+
raise_check_rbasic(other, cVector, "vector");
|
478
|
+
struct vector* A = get_vector_from_rb_value(self);
|
479
|
+
struct vector* B = get_vector_from_rb_value(other);
|
480
|
+
|
481
|
+
raise_check_equal_size_vectors(A, B);
|
482
|
+
|
483
|
+
if(greater_d_array(A->n, A->data, B->data))
|
484
|
+
return Qtrue;
|
485
|
+
return Qfalse;
|
486
|
+
}
|
487
|
+
|
488
|
+
VALUE vector_less(VALUE self, VALUE other)
|
489
|
+
{
|
490
|
+
raise_check_rbasic(other, cVector, "vector");
|
491
|
+
struct vector* A = get_vector_from_rb_value(self);
|
492
|
+
struct vector* B = get_vector_from_rb_value(other);
|
493
|
+
|
494
|
+
raise_check_equal_size_vectors(A, B);
|
495
|
+
|
496
|
+
if(less_d_array(A->n, A->data, B->data))
|
497
|
+
return Qtrue;
|
498
|
+
return Qfalse;
|
499
|
+
}
|
500
|
+
|
501
|
+
VALUE vector_freeze(VALUE self)
|
502
|
+
{
|
503
|
+
struct vector* A = get_vector_from_rb_value(self);
|
504
|
+
A->frozen = true;
|
505
|
+
return self;
|
506
|
+
}
|
507
|
+
|
508
|
+
VALUE vector_division(VALUE self, VALUE v)
|
509
|
+
{
|
510
|
+
double d = raise_rb_value_to_double(v);
|
511
|
+
struct vector* A = get_vector_from_rb_value(self);
|
512
|
+
|
513
|
+
struct vector* R;
|
514
|
+
VALUE result = TypedData_Make_Struct(cVector, struct vector, &vector_type, R);
|
515
|
+
c_vector_init(R, A->n);
|
516
|
+
|
517
|
+
multiply_d_array_to_result(A->n, A->data, 1/d, R->data);
|
518
|
+
|
519
|
+
return result;
|
520
|
+
}
|
521
|
+
|
444
522
|
void init_fm_vector()
|
445
523
|
{
|
446
524
|
VALUE mod = rb_define_module("FastMatrix");
|
@@ -453,9 +531,9 @@ void init_fm_vector()
|
|
453
531
|
rb_define_method(cVector, "[]=", vector_set, 2);
|
454
532
|
rb_define_method(cVector, "size", vector_length, 0);
|
455
533
|
rb_define_method(cVector, "+", vector_add_with, 1);
|
456
|
-
rb_define_method(cVector, "
|
534
|
+
rb_define_method(cVector, "add!", vector_add_from, 1);
|
457
535
|
rb_define_method(cVector, "-", vector_sub_with, 1);
|
458
|
-
rb_define_method(cVector, "
|
536
|
+
rb_define_method(cVector, "sub!", vector_sub_from, 1);
|
459
537
|
rb_define_method(cVector, "eql?", vector_equal, 1);
|
460
538
|
rb_define_method(cVector, "clone", vector_copy, 0);
|
461
539
|
rb_define_method(cVector, "magnitude", vector_magnitude, 0);
|
@@ -471,6 +549,12 @@ void init_fm_vector()
|
|
471
549
|
rb_define_method(cVector, "round", vector_round, -1);
|
472
550
|
rb_define_method(cVector, "inner_product", vector_inner_product, 1);
|
473
551
|
rb_define_method(cVector, "angle_with", vector_angle_with, 1);
|
552
|
+
rb_define_method(cVector, ">=", vector_greater_or_equal, 1);
|
553
|
+
rb_define_method(cVector, "<=", vector_less_or_equal, 1);
|
554
|
+
rb_define_method(cVector, ">", vector_greater, 1);
|
555
|
+
rb_define_method(cVector, "<", vector_less, 1);
|
556
|
+
rb_define_method(cVector, "/", vector_division, 1);
|
557
|
+
rb_define_method(cVector, "freeze", vector_freeze, 0);
|
474
558
|
rb_define_module_function(cVector, "independent?", vector_independent, -1);
|
475
559
|
rb_define_module_function(cVector, "cross_product", vector_cross_product, -1);
|
476
560
|
}
|