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.
@@ -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
- struct matrix* data = get_matrix_from_rb_value(self);
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
- struct matrix** convert_matrix_array(int argc, VALUE *argv, struct matrix*** mtrs)
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
- struct matrix* A = get_matrix_from_rb_value(self);
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, "+=", matrix_add_from, 1);
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, "-=", matrix_sub_from, 1);
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);
@@ -8,6 +8,8 @@ struct vector
8
8
  {
9
9
  int n;
10
10
  double* data;
11
+
12
+ bool frozen;
11
13
  };
12
14
 
13
15
  double c_vector_magnitude(int n, const double* A);
@@ -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
- struct vector* data = get_vector_from_rb_value(self);
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
- struct vector* A = get_vector_from_rb_value(self);
166
- struct vector* B = get_vector_from_rb_value(other);
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
- struct vector** convert_vector_array(int argc, VALUE *argv, struct vector*** vcts)
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
- struct vector* A = get_vector_from_rb_value(self);
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, "+=", vector_add_from, 1);
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, "-=", vector_sub_from, 1);
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
  }