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
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
|
-
[||[](https://travis-ci.org/mmcs-ruby/fast_matrix)||[](https://img.shields.io/github/languages/top/mmcs-ruby/fast_matrix.svg)
|
4
|
+
|[]((https://img.shields.io/gem/dt/fast_matrix.svg))||[](https://codeclimate.com/github/mmcs-ruby/fast_matrix/maintainability)||[](https://img.shields.io/github/languages/count/mmcs-ruby/fast_matrix.svg)
|
5
|
+
|[](https://badge.fury.io/rb/fast_matrix.svg)||[](https://codeclimate.com/github/mmcs-ruby/fast_matrix/test_coverage)||
|
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
|
+
}
|