1 #include "lin_alg.h"
2 
3 
4 /* VECTOR FUNCTIONS ----------------------------------------------------------*/
5 
6 
vec_add_scaled(c_float * c,const c_float * a,const c_float * b,c_int n,c_float sc)7 void vec_add_scaled(c_float       *c,
8                     const c_float *a,
9                     const c_float *b,
10                     c_int          n,
11                     c_float        sc) {
12   c_int i;
13 
14   for (i = 0; i < n; i++) {
15     c[i] =  a[i] + sc * b[i];
16   }
17 }
18 
vec_scaled_norm_inf(const c_float * S,const c_float * v,c_int l)19 c_float vec_scaled_norm_inf(const c_float *S, const c_float *v, c_int l) {
20   c_int   i;
21   c_float abs_Sv_i;
22   c_float max = 0.0;
23 
24   for (i = 0; i < l; i++) {
25     abs_Sv_i = c_absval(S[i] * v[i]);
26 
27     if (abs_Sv_i > max) max = abs_Sv_i;
28   }
29   return max;
30 }
31 
vec_norm_inf(const c_float * v,c_int l)32 c_float vec_norm_inf(const c_float *v, c_int l) {
33   c_int   i;
34   c_float abs_v_i;
35   c_float max = 0.0;
36 
37   for (i = 0; i < l; i++) {
38     abs_v_i = c_absval(v[i]);
39 
40     if (abs_v_i > max) max = abs_v_i;
41   }
42   return max;
43 }
44 
vec_norm_inf_diff(const c_float * a,const c_float * b,c_int l)45 c_float vec_norm_inf_diff(const c_float *a, const c_float *b, c_int l) {
46   c_float nmDiff = 0.0, tmp;
47   c_int   i;
48 
49   for (i = 0; i < l; i++) {
50     tmp = c_absval(a[i] - b[i]);
51 
52     if (tmp > nmDiff) nmDiff = tmp;
53   }
54   return nmDiff;
55 }
56 
vec_mean(const c_float * a,c_int n)57 c_float vec_mean(const c_float *a, c_int n) {
58   c_float mean = 0.0;
59   c_int   i;
60 
61   for (i = 0; i < n; i++) {
62     mean += a[i];
63   }
64   mean /= (c_float)n;
65 
66   return mean;
67 }
68 
int_vec_set_scalar(c_int * a,c_int sc,c_int n)69 void int_vec_set_scalar(c_int *a, c_int sc, c_int n) {
70   c_int i;
71 
72   for (i = 0; i < n; i++) {
73     a[i] = sc;
74   }
75 }
76 
vec_set_scalar(c_float * a,c_float sc,c_int n)77 void vec_set_scalar(c_float *a, c_float sc, c_int n) {
78   c_int i;
79 
80   for (i = 0; i < n; i++) {
81     a[i] = sc;
82   }
83 }
84 
vec_add_scalar(c_float * a,c_float sc,c_int n)85 void vec_add_scalar(c_float *a, c_float sc, c_int n) {
86   c_int i;
87 
88   for (i = 0; i < n; i++) {
89     a[i] += sc;
90   }
91 }
92 
vec_mult_scalar(c_float * a,c_float sc,c_int n)93 void vec_mult_scalar(c_float *a, c_float sc, c_int n) {
94   c_int i;
95 
96   for (i = 0; i < n; i++) {
97     a[i] *= sc;
98   }
99 }
100 
101 #ifndef EMBEDDED
vec_copy(c_float * a,c_int n)102 c_float* vec_copy(c_float *a, c_int n) {
103   c_float *b;
104   c_int    i;
105 
106   b = c_malloc(n * sizeof(c_float));
107   if (!b) return OSQP_NULL;
108 
109   for (i = 0; i < n; i++) {
110     b[i] = a[i];
111   }
112 
113   return b;
114 }
115 
116 #endif // end EMBEDDED
117 
118 
prea_int_vec_copy(const c_int * a,c_int * b,c_int n)119 void prea_int_vec_copy(const c_int *a, c_int *b, c_int n) {
120   c_int i;
121 
122   for (i = 0; i < n; i++) {
123     b[i] = a[i];
124   }
125 }
126 
prea_vec_copy(const c_float * a,c_float * b,c_int n)127 void prea_vec_copy(const c_float *a, c_float *b, c_int n) {
128   c_int i;
129 
130   for (i = 0; i < n; i++) {
131     b[i] = a[i];
132   }
133 }
134 
vec_ew_recipr(const c_float * a,c_float * b,c_int n)135 void vec_ew_recipr(const c_float *a, c_float *b, c_int n) {
136   c_int i;
137 
138   for (i = 0; i < n; i++) {
139     b[i] = (c_float)1.0 / a[i];
140   }
141 }
142 
vec_prod(const c_float * a,const c_float * b,c_int n)143 c_float vec_prod(const c_float *a, const c_float *b, c_int n) {
144   c_float prod = 0.0;
145   c_int   i; // Index
146 
147   for (i = 0; i < n; i++) {
148     prod += a[i] * b[i];
149   }
150 
151   return prod;
152 }
153 
vec_ew_prod(const c_float * a,const c_float * b,c_float * c,c_int n)154 void vec_ew_prod(const c_float *a, const c_float *b, c_float *c, c_int n) {
155   c_int i;
156 
157   for (i = 0; i < n; i++) {
158     c[i] = b[i] * a[i];
159   }
160 }
161 
162 #if EMBEDDED != 1
vec_ew_sqrt(c_float * a,c_int n)163 void vec_ew_sqrt(c_float *a, c_int n) {
164   c_int i;
165 
166   for (i = 0; i < n; i++) {
167     a[i] = c_sqrt(a[i]);
168   }
169 }
170 
vec_ew_max(c_float * a,c_int n,c_float max_val)171 void vec_ew_max(c_float *a, c_int n, c_float max_val) {
172   c_int i;
173 
174   for (i = 0; i < n; i++) {
175     a[i] = c_max(a[i], max_val);
176   }
177 }
178 
vec_ew_min(c_float * a,c_int n,c_float min_val)179 void vec_ew_min(c_float *a, c_int n, c_float min_val) {
180   c_int i;
181 
182   for (i = 0; i < n; i++) {
183     a[i] = c_min(a[i], min_val);
184   }
185 }
186 
vec_ew_max_vec(const c_float * a,const c_float * b,c_float * c,c_int n)187 void vec_ew_max_vec(const c_float *a, const c_float *b, c_float *c, c_int n) {
188   c_int i;
189 
190   for (i = 0; i < n; i++) {
191     c[i] = c_max(a[i], b[i]);
192   }
193 }
194 
vec_ew_min_vec(const c_float * a,const c_float * b,c_float * c,c_int n)195 void vec_ew_min_vec(const c_float *a, const c_float *b, c_float *c, c_int n) {
196   c_int i;
197 
198   for (i = 0; i < n; i++) {
199     c[i] = c_min(a[i], b[i]);
200   }
201 }
202 
203 #endif // EMBEDDED != 1
204 
205 
206 /* MATRIX FUNCTIONS ----------------------------------------------------------*/
207 
208 /* multiply scalar to matrix */
mat_mult_scalar(csc * A,c_float sc)209 void mat_mult_scalar(csc *A, c_float sc) {
210   c_int i, nnzA;
211 
212   nnzA = A->p[A->n];
213 
214   for (i = 0; i < nnzA; i++) {
215     A->x[i] *= sc;
216   }
217 }
218 
mat_premult_diag(csc * A,const c_float * d)219 void mat_premult_diag(csc *A, const c_float *d) {
220   c_int j, i;
221 
222   for (j = 0; j < A->n; j++) {                // Cycle over columns
223     for (i = A->p[j]; i < A->p[j + 1]; i++) { // Cycle every row in the column
224       A->x[i] *= d[A->i[i]];                  // Scale by corresponding element
225                                               // of d for row i
226     }
227   }
228 }
229 
mat_postmult_diag(csc * A,const c_float * d)230 void mat_postmult_diag(csc *A, const c_float *d) {
231   c_int j, i;
232 
233   for (j = 0; j < A->n; j++) {                // Cycle over columns j
234     for (i = A->p[j]; i < A->p[j + 1]; i++) { // Cycle every row i in column j
235       A->x[i] *= d[j];                        // Scale by corresponding element
236                                               // of d for column j
237     }
238   }
239 }
240 
mat_vec(const csc * A,const c_float * x,c_float * y,c_int plus_eq)241 void mat_vec(const csc *A, const c_float *x, c_float *y, c_int plus_eq) {
242   c_int i, j;
243 
244   if (!plus_eq) {
245     // y = 0
246     for (i = 0; i < A->m; i++) {
247       y[i] = 0;
248     }
249   }
250 
251   // if A is empty
252   if (A->p[A->n] == 0) {
253     return;
254   }
255 
256   if (plus_eq == -1) {
257     // y -=  A*x
258     for (j = 0; j < A->n; j++) {
259       for (i = A->p[j]; i < A->p[j + 1]; i++) {
260         y[A->i[i]] -= A->x[i] * x[j];
261       }
262     }
263   } else {
264     // y +=  A*x
265     for (j = 0; j < A->n; j++) {
266       for (i = A->p[j]; i < A->p[j + 1]; i++) {
267         y[A->i[i]] += A->x[i] * x[j];
268       }
269     }
270   }
271 }
272 
mat_tpose_vec(const csc * A,const c_float * x,c_float * y,c_int plus_eq,c_int skip_diag)273 void mat_tpose_vec(const csc *A, const c_float *x, c_float *y,
274                    c_int plus_eq, c_int skip_diag) {
275   c_int i, j, k;
276 
277   if (!plus_eq) {
278     // y = 0
279     for (i = 0; i < A->n; i++) {
280       y[i] = 0;
281     }
282   }
283 
284   // if A is empty
285   if (A->p[A->n] == 0) {
286     return;
287   }
288 
289   if (plus_eq == -1) {
290     // y -=  A*x
291     if (skip_diag) {
292       for (j = 0; j < A->n; j++) {
293         for (k = A->p[j]; k < A->p[j + 1]; k++) {
294           i     = A->i[k];
295           y[j] -= i == j ? 0 : A->x[k] * x[i];
296         }
297       }
298     } else {
299       for (j = 0; j < A->n; j++) {
300         for (k = A->p[j]; k < A->p[j + 1]; k++) {
301           y[j] -= A->x[k] * x[A->i[k]];
302         }
303       }
304     }
305   } else {
306     // y +=  A*x
307     if (skip_diag) {
308       for (j = 0; j < A->n; j++) {
309         for (k = A->p[j]; k < A->p[j + 1]; k++) {
310           i     = A->i[k];
311           y[j] += i == j ? 0 : A->x[k] * x[i];
312         }
313       }
314     } else {
315       for (j = 0; j < A->n; j++) {
316         for (k = A->p[j]; k < A->p[j + 1]; k++) {
317           y[j] += A->x[k] * x[A->i[k]];
318         }
319       }
320     }
321   }
322 }
323 
324 #if EMBEDDED != 1
mat_inf_norm_cols(const csc * M,c_float * E)325 void mat_inf_norm_cols(const csc *M, c_float *E) {
326   c_int j, ptr;
327 
328   // Initialize zero max elements
329   for (j = 0; j < M->n; j++) {
330     E[j] = 0.;
331   }
332 
333   // Compute maximum across columns
334   for (j = 0; j < M->n; j++) {
335     for (ptr = M->p[j]; ptr < M->p[j + 1]; ptr++) {
336       E[j] = c_max(c_absval(M->x[ptr]), E[j]);
337     }
338   }
339 }
340 
mat_inf_norm_rows(const csc * M,c_float * E)341 void mat_inf_norm_rows(const csc *M, c_float *E) {
342   c_int i, j, ptr;
343 
344   // Initialize zero max elements
345   for (j = 0; j < M->m; j++) {
346     E[j] = 0.;
347   }
348 
349   // Compute maximum across rows
350   for (j = 0; j < M->n; j++) {
351     for (ptr = M->p[j]; ptr < M->p[j + 1]; ptr++) {
352       i    = M->i[ptr];
353       E[i] = c_max(c_absval(M->x[ptr]), E[i]);
354     }
355   }
356 }
357 
mat_inf_norm_cols_sym_triu(const csc * M,c_float * E)358 void mat_inf_norm_cols_sym_triu(const csc *M, c_float *E) {
359   c_int   i, j, ptr;
360   c_float abs_x;
361 
362   // Initialize zero max elements
363   for (j = 0; j < M->n; j++) {
364     E[j] = 0.;
365   }
366 
367   // Compute maximum across columns
368   // Note that element (i, j) contributes to
369   // -> Column j (as expected in any matrices)
370   // -> Column i (which is equal to row i for symmetric matrices)
371   for (j = 0; j < M->n; j++) {
372     for (ptr = M->p[j]; ptr < M->p[j + 1]; ptr++) {
373       i     = M->i[ptr];
374       abs_x = c_absval(M->x[ptr]);
375       E[j]  = c_max(abs_x, E[j]);
376 
377       if (i != j) {
378         E[i] = c_max(abs_x, E[i]);
379       }
380     }
381   }
382 }
383 
384 #endif /* if EMBEDDED != 1 */
385 
386 
quad_form(const csc * P,const c_float * x)387 c_float quad_form(const csc *P, const c_float *x) {
388   c_float quad_form = 0.;
389   c_int   i, j, ptr;                                // Pointers to iterate over
390                                                     // matrix: (i,j) a element
391                                                     // pointer
392 
393   for (j = 0; j < P->n; j++) {                      // Iterate over columns
394     for (ptr = P->p[j]; ptr < P->p[j + 1]; ptr++) { // Iterate over rows
395       i = P->i[ptr];                                // Row index
396 
397       if (i == j) {                                 // Diagonal element
398         quad_form += (c_float).5 * P->x[ptr] * x[i] * x[i];
399       }
400       else if (i < j) {                             // Off-diagonal element
401         quad_form += P->x[ptr] * x[i] * x[j];
402       }
403       else {                                        // Element in lower diagonal
404                                                     // part
405 #ifdef PRINTING
406         c_eprint("quad_form matrix is not upper triangular");
407 #endif /* ifdef PRINTING */
408         return OSQP_NULL;
409       }
410     }
411   }
412   return quad_form;
413 }
414