fast_matrix 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 34d254515edd7b453efe7fdedb7b360c462faa53c9ec13de7f4beb5cf989e536
|
4
|
+
data.tar.gz: 5b9c35116c61a67f498badf12980d71d275e8020900ab48eb710aa74cd17ed71
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a011340ce71b58856512df1b6da78af5f510ae6789a8cdfd69f3793370533f66d6c2a6647abde1c5ef42a2928f8118528d976f6402be3ff3a81f16e519ec700a
|
7
|
+
data.tar.gz: f618591f305fb3d9d2b97819833398e571fa99e0fcf43ad74fc8152e9fb3e6c7d97a1128933cbbc9b8b4b8bda642e1d6f5e7be4a04abc1c47d994981f43ac560
|
data/README.md
CHANGED
@@ -1,6 +1,8 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
[![
|
1
|
+
|Gem|Activity|Code|Issue|Statistic|
|
2
|
+
|--:|--:|--:|--:|--:|
|
3
|
+
|![Gem](https://img.shields.io/gem/v/fast_matrix?color=light)|![GitHub last commit](https://img.shields.io/github/last-commit/mmcs-ruby/fast_matrix)|[![Build Status](https://travis-ci.org/mmcs-ruby/fast_matrix.svg?branch=master)](https://travis-ci.org/mmcs-ruby/fast_matrix)|![GitHub issues](https://img.shields.io/github/issues-raw/mmcs-ruby/fast_matrix)|[![Top language](https://img.shields.io/github/languages/top/mmcs-ruby/fast_matrix.svg)](https://img.shields.io/github/languages/top/mmcs-ruby/fast_matrix.svg)
|
4
|
+
|[![Downloads](https://img.shields.io/gem/dt/fast_matrix.svg)]((https://img.shields.io/gem/dt/fast_matrix.svg))|![GitHub commits since tagged version](https://img.shields.io/github/commits-since/mmcs-ruby/fast_matrix/v0.2.0/develop?color=light)|[![Maintainability](https://api.codeclimate.com/v1/badges/fd171bae2ca444aaca29/maintainability)](https://codeclimate.com/github/mmcs-ruby/fast_matrix/maintainability)|![GitHub closed issues](https://img.shields.io/github/issues-closed-raw/mmcs-ruby/fast_matrix)|[![Languages](https://img.shields.io/github/languages/count/mmcs-ruby/fast_matrix.svg)](https://img.shields.io/github/languages/count/mmcs-ruby/fast_matrix.svg)
|
5
|
+
|[![Downloads Latest](https://img.shields.io/gem/dtv/fast_matrix.svg)](https://badge.fury.io/rb/fast_matrix.svg)|![GitHub commit activity](https://img.shields.io/github/commit-activity/m/mmcs-ruby/fast_matrix?color=light)|[![Test Coverage](https://api.codeclimate.com/v1/badges/fd171bae2ca444aaca29/test_coverage)](https://codeclimate.com/github/mmcs-ruby/fast_matrix/test_coverage)|![GitHub issues by-label](https://img.shields.io/github/issues-raw/mmcs-ruby/fast_matrix/bug)|![GitHub code size in bytes](https://img.shields.io/github/languages/code-size/mmcs-ruby/fast_matrix)
|
4
6
|
|
5
7
|
# FastMatrix
|
6
8
|
|
@@ -78,6 +78,30 @@ bool greater_or_equal_d_array(int len, const double* A, const double* B)
|
|
78
78
|
return true;
|
79
79
|
}
|
80
80
|
|
81
|
+
bool less_or_equal_d_array(int len, const double* A, const double* B)
|
82
|
+
{
|
83
|
+
for(int i = 0; i < len; ++i)
|
84
|
+
if(A[i] > B[i])
|
85
|
+
return false;
|
86
|
+
return true;
|
87
|
+
}
|
88
|
+
|
89
|
+
bool greater_d_array(int len, const double* A, const double* B)
|
90
|
+
{
|
91
|
+
for(int i = 0; i < len; ++i)
|
92
|
+
if(A[i] <= B[i])
|
93
|
+
return false;
|
94
|
+
return true;
|
95
|
+
}
|
96
|
+
|
97
|
+
bool less_d_array(int len, const double* A, const double* B)
|
98
|
+
{
|
99
|
+
for(int i = 0; i < len; ++i)
|
100
|
+
if(A[i] >= B[i])
|
101
|
+
return false;
|
102
|
+
return true;
|
103
|
+
}
|
104
|
+
|
81
105
|
bool zero_d_array(int len, const double* A)
|
82
106
|
{
|
83
107
|
for(int i = 0; i < len; ++i)
|
@@ -15,6 +15,9 @@ void sub_d_arrays_to_first(int len, double* dif, const double* sub);
|
|
15
15
|
bool equal_d_arrays(int len, const double* A, const double* B);
|
16
16
|
void abs_d_array(int len, const double* A, double* B);
|
17
17
|
bool greater_or_equal_d_array(int len, const double* A, const double* B);
|
18
|
+
bool less_or_equal_d_array(int len, const double* A, const double* B);
|
19
|
+
bool greater_d_array(int len, const double* A, const double* B);
|
20
|
+
bool less_d_array(int len, const double* A, const double* B);
|
18
21
|
bool zero_d_array(int len, const double* A);
|
19
22
|
void swap_d_arrays(int len, double* A, double* B);
|
20
23
|
void round_d_array(int len, const double* Input, double* Output, int acc);
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
VALUE fm_eTypeError;
|
4
4
|
VALUE fm_eIndexError;
|
5
|
+
VALUE fm_eFrozenError;
|
5
6
|
|
6
7
|
double raise_rb_value_to_double(VALUE v)
|
7
8
|
{
|
@@ -40,4 +41,5 @@ void init_fm_errors()
|
|
40
41
|
|
41
42
|
fm_eTypeError = rb_define_class_under(mod, "TypeError", rb_eTypeError);
|
42
43
|
fm_eIndexError = rb_define_class_under(mod, "IndexError", rb_eIndexError);
|
44
|
+
fm_eFrozenError = rb_define_class_under(mod, "FrozenError", rb_eFrozenError);
|
43
45
|
}
|
@@ -0,0 +1,97 @@
|
|
1
|
+
#include "LUPDecomposition/c_lup.h"
|
2
|
+
#include "Helper/c_array_operations.h"
|
3
|
+
|
4
|
+
void c_lup_l(int n, const double* LUP, double* L)
|
5
|
+
{
|
6
|
+
for(int i = 0; i < n; ++i)
|
7
|
+
{
|
8
|
+
double* l_line = L + n * i;
|
9
|
+
const double* lup_line = LUP + n * i;
|
10
|
+
for(int j = 0; j < n; ++j)
|
11
|
+
{
|
12
|
+
if(i < j)
|
13
|
+
l_line[j] = 0;
|
14
|
+
else if(i == j)
|
15
|
+
l_line[j] = 1;
|
16
|
+
else
|
17
|
+
l_line[j] = lup_line[j];
|
18
|
+
}
|
19
|
+
}
|
20
|
+
}
|
21
|
+
|
22
|
+
void c_lup_u(int n, const double* LUP, double* U)
|
23
|
+
{
|
24
|
+
for(int i = 0; i < n; ++i)
|
25
|
+
{
|
26
|
+
double* u_line = U + n * i;
|
27
|
+
const double* lup_line = LUP + n * i;
|
28
|
+
for(int j = 0; j < n; ++j)
|
29
|
+
{
|
30
|
+
if(i > j)
|
31
|
+
u_line[j] = 0;
|
32
|
+
else
|
33
|
+
u_line[j] = lup_line[j];
|
34
|
+
}
|
35
|
+
}
|
36
|
+
}
|
37
|
+
|
38
|
+
void c_lup_p(int n, const int* prm, double* P)
|
39
|
+
{
|
40
|
+
for(int i = 0; i < n; ++i)
|
41
|
+
{
|
42
|
+
double* p_line = P + n * i;
|
43
|
+
int current = prm[i];
|
44
|
+
for(int j = 0; j < current; ++j)
|
45
|
+
p_line[j] = 0;
|
46
|
+
p_line[current] = 1;
|
47
|
+
for(int j = current + 1; j < n; ++j)
|
48
|
+
p_line[j] = 0;
|
49
|
+
}
|
50
|
+
}
|
51
|
+
|
52
|
+
double c_lup_determinant(int n, double* LUP, int sign)
|
53
|
+
{
|
54
|
+
double res = sign;
|
55
|
+
for(int i = 0; i < n; ++i)
|
56
|
+
res *= LUP[i + i * n];
|
57
|
+
return res;
|
58
|
+
}
|
59
|
+
|
60
|
+
void c_lup_apply_permutation(int m, int n, const double* A, const int* permutation, double* R)
|
61
|
+
{
|
62
|
+
for(int i = 0; i < n; ++i)
|
63
|
+
copy_d_array(m, A + m * permutation[i], R + m * i);
|
64
|
+
}
|
65
|
+
|
66
|
+
void c_lup_solve(int m, int n, const double* lp, const double* B, const int* permutation, double* R)
|
67
|
+
{
|
68
|
+
c_lup_apply_permutation(m, n, B, permutation, R);
|
69
|
+
|
70
|
+
for(int k = 0; k < n; ++k)
|
71
|
+
for(int i = k + 1; i < n; ++i)
|
72
|
+
{
|
73
|
+
double* line = R + i * m;
|
74
|
+
int mul = lp[i * n + k];
|
75
|
+
|
76
|
+
for(int j = 0; j < m; ++j)
|
77
|
+
line[j] -= line[j] * mul;
|
78
|
+
}
|
79
|
+
|
80
|
+
for(int k = n - 1; k >= 0; --k)
|
81
|
+
{
|
82
|
+
double* line = R + k * m;
|
83
|
+
int div = lp[k * n + k];
|
84
|
+
|
85
|
+
for(int j = 0; j < m; ++j)
|
86
|
+
line[j] /= div;
|
87
|
+
|
88
|
+
for(int i = 0; i < k; ++i)
|
89
|
+
{
|
90
|
+
double* line_out = R + i * m;
|
91
|
+
int mul = lp[i * n + k];
|
92
|
+
|
93
|
+
for(int j = 0; j < m; ++j)
|
94
|
+
line_out[j] -= line[j] * mul;
|
95
|
+
}
|
96
|
+
}
|
97
|
+
}
|
@@ -0,0 +1,22 @@
|
|
1
|
+
#ifndef FAST_MATRIX_MATRIX_C_LUPDECOMPOSITION_H
|
2
|
+
#define FAST_MATRIX_MATRIX_C_LUPDECOMPOSITION_H 1
|
3
|
+
|
4
|
+
#include <stdbool.h>
|
5
|
+
|
6
|
+
struct lupdecomposition
|
7
|
+
{
|
8
|
+
int n;
|
9
|
+
double* data;
|
10
|
+
int* permutation;
|
11
|
+
int pivot_sign;
|
12
|
+
bool singular;
|
13
|
+
};
|
14
|
+
|
15
|
+
double c_lup_determinant(int n, double* LUP, int sign);
|
16
|
+
|
17
|
+
void c_lup_l(int n, const double* LUP, double* L);
|
18
|
+
void c_lup_u(int n, const double* LUP, double* U);
|
19
|
+
void c_lup_p(int n, const int* prm, double* P);
|
20
|
+
void c_lup_solve(int m, int n, const double* lp, const double* B, const int* permutation, double* R);
|
21
|
+
|
22
|
+
#endif /* FAST_MATRIX_MATRIX_C_LUPDECOMPOSITION_H */
|
@@ -0,0 +1,14 @@
|
|
1
|
+
#ifndef FAST_MATRIX_LUPDECOMPOSITION_HELPER_H
|
2
|
+
#define FAST_MATRIX_LUPDECOMPOSITION_HELPER_H 1
|
3
|
+
|
4
|
+
#include "ruby.h"
|
5
|
+
#include "Matrix/c_matrix.h"
|
6
|
+
|
7
|
+
inline struct lupdecomposition* get_lup_from_rb_value(VALUE lp)
|
8
|
+
{
|
9
|
+
struct lupdecomposition* data;
|
10
|
+
TypedData_Get_Struct(lp, struct lupdecomposition, &lup_type, data);
|
11
|
+
return data;
|
12
|
+
}
|
13
|
+
|
14
|
+
#endif /* FAST_MATRIX_LUPDECOMPOSITION_HELPER_H */
|
@@ -0,0 +1,124 @@
|
|
1
|
+
#include "LUPDecomposition/lup.h"
|
2
|
+
#include "LUPDecomposition/c_lup.h"
|
3
|
+
#include "LUPDecomposition/helper.h"
|
4
|
+
#include "Matrix/matrix.h"
|
5
|
+
#include "Matrix/helper.h"
|
6
|
+
#include "Helper/errors.h"
|
7
|
+
|
8
|
+
VALUE cLUPDecomposition;
|
9
|
+
|
10
|
+
void lup_free(void* data);
|
11
|
+
size_t lup_size(const void* data);
|
12
|
+
|
13
|
+
const rb_data_type_t lup_type =
|
14
|
+
{
|
15
|
+
.wrap_struct_name = "lupdecomposition",
|
16
|
+
.function =
|
17
|
+
{
|
18
|
+
.dmark = NULL,
|
19
|
+
.dfree = lup_free,
|
20
|
+
.dsize = lup_size,
|
21
|
+
},
|
22
|
+
.data = NULL,
|
23
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY,
|
24
|
+
};
|
25
|
+
|
26
|
+
void lup_free(void* data)
|
27
|
+
{
|
28
|
+
free(((*(struct lupdecomposition*)data)).data);
|
29
|
+
free(((*(struct lupdecomposition*)data)).permutation);
|
30
|
+
free(data);
|
31
|
+
}
|
32
|
+
|
33
|
+
size_t lup_size(const void* data)
|
34
|
+
{
|
35
|
+
return sizeof(struct lupdecomposition);
|
36
|
+
}
|
37
|
+
|
38
|
+
VALUE lup_alloc(VALUE self)
|
39
|
+
{
|
40
|
+
struct lupdecomposition* lp = malloc(sizeof(struct lupdecomposition));
|
41
|
+
lp->data = NULL;
|
42
|
+
lp->permutation = NULL;
|
43
|
+
lp->pivot_sign = 1;
|
44
|
+
lp->singular = false;
|
45
|
+
return TypedData_Wrap_Struct(self, &lup_type, lp);
|
46
|
+
}
|
47
|
+
|
48
|
+
VALUE lup_l(VALUE self)
|
49
|
+
{
|
50
|
+
struct lupdecomposition* lp = get_lup_from_rb_value(self);
|
51
|
+
MAKE_MATRIX_AND_RB_VALUE(R, result, lp->n, lp->n);
|
52
|
+
c_lup_l(lp->n, lp->data, R->data);
|
53
|
+
return result;
|
54
|
+
}
|
55
|
+
|
56
|
+
VALUE lup_u(VALUE self)
|
57
|
+
{
|
58
|
+
struct lupdecomposition* lp = get_lup_from_rb_value(self);
|
59
|
+
MAKE_MATRIX_AND_RB_VALUE(R, result, lp->n, lp->n);
|
60
|
+
c_lup_u(lp->n, lp->data, R->data);
|
61
|
+
return result;
|
62
|
+
}
|
63
|
+
|
64
|
+
VALUE lup_p(VALUE self)
|
65
|
+
{
|
66
|
+
struct lupdecomposition* lp = get_lup_from_rb_value(self);
|
67
|
+
MAKE_MATRIX_AND_RB_VALUE(R, result, lp->n, lp->n);
|
68
|
+
c_lup_p(lp->n, lp->permutation, R->data);
|
69
|
+
return result;
|
70
|
+
}
|
71
|
+
|
72
|
+
VALUE lup_determinant(VALUE self)
|
73
|
+
{
|
74
|
+
struct lupdecomposition* lp = get_lup_from_rb_value(self);
|
75
|
+
return DBL2NUM(c_lup_determinant(lp->n, lp->data, lp->pivot_sign));
|
76
|
+
}
|
77
|
+
|
78
|
+
VALUE lup_singular(VALUE self)
|
79
|
+
{
|
80
|
+
struct lupdecomposition* lp = get_lup_from_rb_value(self);
|
81
|
+
if(lp->singular)
|
82
|
+
return Qtrue;
|
83
|
+
return Qfalse;
|
84
|
+
}
|
85
|
+
|
86
|
+
VALUE lup_pivots(VALUE self)
|
87
|
+
{
|
88
|
+
struct lupdecomposition* lp = get_lup_from_rb_value(self);
|
89
|
+
VALUE* v = malloc(lp->n * sizeof(VALUE));
|
90
|
+
for(int i = 0; i < lp->n; ++i)
|
91
|
+
v[i] = INT2NUM(lp->permutation[i]);
|
92
|
+
VALUE res = rb_ary_new_from_values(lp->n, v);
|
93
|
+
free(v);
|
94
|
+
return res;
|
95
|
+
}
|
96
|
+
|
97
|
+
VALUE lup_solve(VALUE self, VALUE mtrx)
|
98
|
+
{
|
99
|
+
raise_check_rbasic(mtrx, cMatrix, "matrix");
|
100
|
+
struct lupdecomposition* lp = get_lup_from_rb_value(self);
|
101
|
+
struct matrix* M = get_matrix_from_rb_value(mtrx);
|
102
|
+
if(lp->singular)
|
103
|
+
rb_raise(fm_eIndexError, "Matrix is singular");
|
104
|
+
if(lp->n != M->n)
|
105
|
+
rb_raise(fm_eIndexError, "Columns of different size");
|
106
|
+
|
107
|
+
MAKE_MATRIX_AND_RB_VALUE(C, result, M->m, lp->n);
|
108
|
+
c_lup_solve(M->m, lp->n, lp->data, M->data, lp->permutation, C->data);
|
109
|
+
return result;
|
110
|
+
}
|
111
|
+
|
112
|
+
void init_fm_lup()
|
113
|
+
{
|
114
|
+
cLUPDecomposition = rb_define_class_under(cMatrix, "LUPDecomposition", rb_cData);
|
115
|
+
rb_define_alloc_func(cLUPDecomposition, lup_alloc);
|
116
|
+
|
117
|
+
rb_define_method(cLUPDecomposition, "l", lup_l, 0);
|
118
|
+
rb_define_method(cLUPDecomposition, "u", lup_u, 0);
|
119
|
+
rb_define_method(cLUPDecomposition, "p", lup_p, 0);
|
120
|
+
rb_define_method(cLUPDecomposition, "det", lup_determinant, 0);
|
121
|
+
rb_define_method(cLUPDecomposition, "singular?", lup_singular, 0);
|
122
|
+
rb_define_method(cLUPDecomposition, "pivots", lup_pivots, 0);
|
123
|
+
rb_define_method(cLUPDecomposition, "solve", lup_solve, 1);
|
124
|
+
}
|
@@ -1,4 +1,5 @@
|
|
1
1
|
#include "c_matrix.h"
|
2
|
+
#include "Helper/c_array_operations.h"
|
2
3
|
|
3
4
|
// in - matrix m x n
|
4
5
|
// out - matrix n x m
|
@@ -604,3 +605,133 @@ bool c_matrix_inverse(int n, const double* A, double* B)
|
|
604
605
|
free(M);
|
605
606
|
return true;
|
606
607
|
}
|
608
|
+
|
609
|
+
bool c_matrix_adjugate(int n, const double* A, double* B)
|
610
|
+
{
|
611
|
+
if(!c_matrix_inverse(n, A, B))
|
612
|
+
return false;
|
613
|
+
double d = c_matrix_determinant(n, A);
|
614
|
+
multiply_d_array(n * n, B, d);
|
615
|
+
return true;
|
616
|
+
}
|
617
|
+
|
618
|
+
void c_matrix_recursive_exponentiation(int n, const double* A, double* B, int d)
|
619
|
+
{
|
620
|
+
if(d == 2)
|
621
|
+
return c_matrix_strassen(n, n, n, A, A, B);
|
622
|
+
|
623
|
+
double* C = malloc(n * n * sizeof(double));
|
624
|
+
|
625
|
+
if(d == 3)
|
626
|
+
{
|
627
|
+
c_matrix_strassen(n, n, n, A, A, C);
|
628
|
+
c_matrix_strassen(n, n, n, A, C, B);
|
629
|
+
free(C);
|
630
|
+
return;
|
631
|
+
}
|
632
|
+
|
633
|
+
c_matrix_recursive_exponentiation(n, A, C, d / 2);
|
634
|
+
|
635
|
+
if(d % 2 == 0)
|
636
|
+
{
|
637
|
+
c_matrix_strassen(n, n, n, C, C, B);
|
638
|
+
free(C);
|
639
|
+
return;
|
640
|
+
}
|
641
|
+
|
642
|
+
double* D = malloc(n * n * sizeof(double));
|
643
|
+
|
644
|
+
c_matrix_strassen(n, n, n, C, C, D);
|
645
|
+
c_matrix_strassen(n, n, n, A, D, B);
|
646
|
+
free(C);
|
647
|
+
free(D);
|
648
|
+
}
|
649
|
+
|
650
|
+
bool c_matrix_exponentiation(int m, int n, const double* A, double* B, int d)
|
651
|
+
{
|
652
|
+
if(d == 1)
|
653
|
+
{
|
654
|
+
copy_d_array(m * n, A, B);
|
655
|
+
return true;
|
656
|
+
}
|
657
|
+
|
658
|
+
if(m != n)
|
659
|
+
return false;
|
660
|
+
|
661
|
+
if(d == 0)
|
662
|
+
{
|
663
|
+
c_matrix_shift_identity(n, B, n);
|
664
|
+
return true;
|
665
|
+
}
|
666
|
+
|
667
|
+
if(d > 0)
|
668
|
+
{
|
669
|
+
c_matrix_recursive_exponentiation(n, A, B, d);
|
670
|
+
return true;
|
671
|
+
}
|
672
|
+
|
673
|
+
if(d == -1)
|
674
|
+
{
|
675
|
+
c_matrix_inverse(n, A, B);
|
676
|
+
return true;
|
677
|
+
}
|
678
|
+
|
679
|
+
double* C = malloc(n * n * sizeof(double));
|
680
|
+
c_matrix_inverse(n, A, C);
|
681
|
+
c_matrix_recursive_exponentiation(n, C, B, -d);
|
682
|
+
free(C);
|
683
|
+
|
684
|
+
return true;
|
685
|
+
}
|
686
|
+
|
687
|
+
void c_matrix_fill_range_array(int n, int* V)
|
688
|
+
{
|
689
|
+
for(int i = 0; i < n; ++i)
|
690
|
+
V[i] = i;
|
691
|
+
}
|
692
|
+
|
693
|
+
void c_matrix_lup(int n, const double* A, double* LU, int* V, int* sign, bool* singular)
|
694
|
+
{
|
695
|
+
copy_d_array(n * n, A, LU);
|
696
|
+
c_matrix_fill_range_array(n, V);
|
697
|
+
*sign = 1;
|
698
|
+
*singular = false;
|
699
|
+
|
700
|
+
for(int i = 0; i < n; ++i)
|
701
|
+
{
|
702
|
+
double* line = LU + n * i;
|
703
|
+
double current = 0;
|
704
|
+
int swap_line = -1;
|
705
|
+
for(int j = i; j < n; ++j)
|
706
|
+
if(fabs(LU[j * n + i]) > current)
|
707
|
+
{
|
708
|
+
swap_line = j;
|
709
|
+
current = fabs(LU[j * n + i]);
|
710
|
+
}
|
711
|
+
|
712
|
+
if(swap_line == -1)
|
713
|
+
{
|
714
|
+
*singular = true;
|
715
|
+
continue;
|
716
|
+
}
|
717
|
+
|
718
|
+
if(swap_line != i)
|
719
|
+
{
|
720
|
+
swap_d_arrays(n, LU + swap_line * n, line);
|
721
|
+
int buf = V[i];
|
722
|
+
V[i] = V[swap_line];
|
723
|
+
V[swap_line] = buf;
|
724
|
+
*sign = -*sign;
|
725
|
+
}
|
726
|
+
|
727
|
+
current = line[i];
|
728
|
+
for(int j = i + 1; j < n; ++j)
|
729
|
+
{
|
730
|
+
double* w_line = LU + j * n;
|
731
|
+
w_line[i] = w_line[i] / current;
|
732
|
+
double start = w_line[i];
|
733
|
+
for(int k = i + 1; k < n; ++k)
|
734
|
+
w_line[k] -= start * line[k];
|
735
|
+
}
|
736
|
+
}
|
737
|
+
}
|