-
Notifications
You must be signed in to change notification settings - Fork 344
/
matrix.c
166 lines (122 loc) · 4.23 KB
/
matrix.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
#include "osqp.h"
#include "lin_alg.h"
#include "algebra_impl.h"
#include "csc_math.h"
#include "csc_utils.h"
/* logical test functions ----------------------------------------------------*/
c_int OSQPMatrix_is_eq(OSQPMatrix *A, OSQPMatrix* B, c_float tol){
return (A->symmetry == B->symmetry &&
csc_is_eq(A->csc, B->csc, tol) );
}
/* Non-embeddable functions (using malloc) ----------------------------------*/
#ifndef EMBEDDED
//Make a copy from a csc matrix. Returns OSQP_NULL on failure
OSQPMatrix* OSQPMatrix_new_from_csc(const csc* A, c_int is_triu){
OSQPMatrix* out = c_malloc(sizeof(OSQPMatrix));
if(!out) return OSQP_NULL;
if(is_triu) out->symmetry = TRIU;
else out->symmetry = NONE;
out->csc = csc_copy(A);
if(!out->csc){
c_free(out);
return OSQP_NULL;
}
else{
return out;
}
}
#endif //EMBEDDED
/* direct data access functions ---------------------------------------------*/
void OSQPMatrix_update_values(OSQPMatrix *M,
const c_float *Mx_new,
const c_int *Mx_new_idx,
c_int M_new_n){
csc_update_values(M->csc, Mx_new, Mx_new_idx, M_new_n);
}
/* Matrix dimensions and data access */
c_int OSQPMatrix_get_m(const OSQPMatrix *M){return M->csc->m;}
c_int OSQPMatrix_get_n(const OSQPMatrix *M){return M->csc->n;}
c_float* OSQPMatrix_get_x(const OSQPMatrix *M){return M->csc->x;}
c_int* OSQPMatrix_get_i(const OSQPMatrix *M){return M->csc->i;}
c_int* OSQPMatrix_get_p(const OSQPMatrix *M){return M->csc->p;}
c_int OSQPMatrix_get_nz(const OSQPMatrix *M){return M->csc->p[M->csc->n];}
/* math functions ----------------------------------------------------------*/
//A = sc*A
void OSQPMatrix_mult_scalar(OSQPMatrix *A, c_float sc){
csc_scale(A->csc,sc);
}
void OSQPMatrix_lmult_diag(OSQPMatrix *A, const OSQPVectorf *L) {
csc_lmult_diag(A->csc, OSQPVectorf_data(L));
}
void OSQPMatrix_rmult_diag(OSQPMatrix *A, const OSQPVectorf *R) {
csc_rmult_diag(A->csc, OSQPVectorf_data(R));
}
//y = alpha*A*x + beta*y
void OSQPMatrix_Axpy(const OSQPMatrix *A,
const OSQPVectorf *x,
OSQPVectorf *y,
c_float alpha,
c_float beta) {
c_float* xf = OSQPVectorf_data(x);
c_float* yf = OSQPVectorf_data(y);
if(A->symmetry == NONE){
//full matrix
csc_Axpy(A->csc, xf, yf, alpha, beta);
}
else{
//should be TRIU here, but not directly checked
csc_Axpy_sym_triu(A->csc, xf, yf, alpha, beta);
}
}
void OSQPMatrix_Atxpy(const OSQPMatrix *A,
const OSQPVectorf *x,
OSQPVectorf *y,
c_float alpha,
c_float beta) {
if(A->symmetry == NONE) csc_Atxpy(A->csc, OSQPVectorf_data(x), OSQPVectorf_data(y), alpha, beta);
else csc_Axpy_sym_triu(A->csc, OSQPVectorf_data(x), OSQPVectorf_data(y), alpha, beta);
}
c_float OSQPMatrix_quad_form(const OSQPMatrix *P, const OSQPVectorf *x) {
if(P->symmetry == TRIU) return csc_quad_form(P->csc, OSQPVectorf_data(x));
else {
#ifdef PRINTING
c_eprint("quad_form matrix is not upper triangular");
#endif /* ifdef PRINTING */
return -1.0;
}
}
#if EMBEDDED != 1
void OSQPMatrix_col_norm_inf(const OSQPMatrix *M, OSQPVectorf *E) {
csc_col_norm_inf(M->csc, OSQPVectorf_data(E));
}
void OSQPMatrix_row_norm_inf(const OSQPMatrix *M, OSQPVectorf *E) {
if(M->symmetry == NONE) csc_row_norm_inf(M->csc, OSQPVectorf_data(E));
else csc_row_norm_inf_sym_triu(M->csc, OSQPVectorf_data(E));
}
#ifndef EMBEDDED
void OSQPMatrix_free(OSQPMatrix *M){
if (M) csc_spfree(M->csc);
c_free(M);
}
OSQPMatrix* OSQPMatrix_submatrix_byrows(const OSQPMatrix* A, const OSQPVectori* rows){
csc *M;
OSQPMatrix *out;
#ifdef PRINTING
if(A->symmetry == TRIU){
c_eprint("row selection not implemented for partially filled matrices");
return OSQP_NULL;
}
#endif
M = csc_submatrix_byrows(A->csc, OSQPVectori_data(rows));
if(!M) return OSQP_NULL;
out = c_malloc(sizeof(OSQPMatrix));
if(!out){
csc_spfree(M);
return OSQP_NULL;
}
out->symmetry = NONE;
out->csc = M;
return out;
}
#endif // ndef EMBEDDED
#endif /* if EMBEDDED != 1 */