scs 0.4.0 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -0
  3. data/LICENSE.txt +1 -1
  4. data/README.md +1 -1
  5. data/lib/scs/version.rb +1 -1
  6. data/vendor/scs/CITATION.cff +2 -2
  7. data/vendor/scs/CMakeLists.txt +284 -168
  8. data/vendor/scs/Makefile +43 -18
  9. data/vendor/scs/README.md +1 -1
  10. data/vendor/scs/include/glbopts.h +32 -13
  11. data/vendor/scs/include/linsys.h +8 -8
  12. data/vendor/scs/include/scs.h +6 -2
  13. data/vendor/scs/include/scs_types.h +3 -1
  14. data/vendor/scs/include/scs_work.h +9 -8
  15. data/vendor/scs/include/util.h +1 -1
  16. data/vendor/scs/linsys/cpu/direct/private.c +32 -153
  17. data/vendor/scs/linsys/cpu/direct/private.h +6 -6
  18. data/vendor/scs/linsys/cpu/indirect/private.c +9 -22
  19. data/vendor/scs/linsys/cpu/indirect/private.h +4 -2
  20. data/vendor/scs/linsys/csparse.c +140 -12
  21. data/vendor/scs/linsys/csparse.h +10 -17
  22. data/vendor/scs/linsys/gpu/gpu.c +4 -4
  23. data/vendor/scs/linsys/gpu/gpu.h +1 -1
  24. data/vendor/scs/linsys/gpu/indirect/private.c +15 -26
  25. data/vendor/scs/linsys/mkl/direct/private.c +182 -0
  26. data/vendor/scs/linsys/mkl/direct/private.h +38 -0
  27. data/vendor/scs/linsys/scs_matrix.c +11 -5
  28. data/vendor/scs/scs.mk +39 -26
  29. data/vendor/scs/src/cones.c +15 -159
  30. data/vendor/scs/src/exp_cone.c +399 -0
  31. data/vendor/scs/src/normalize.c +4 -2
  32. data/vendor/scs/src/rw.c +93 -38
  33. data/vendor/scs/src/scs.c +83 -52
  34. data/vendor/scs/src/util.c +12 -3
  35. data/vendor/scs/test/minunit.h +2 -1
  36. data/vendor/scs/test/problem_utils.h +2 -1
  37. data/vendor/scs/test/problems/hs21_tiny_qp.h +1 -1
  38. data/vendor/scs/test/problems/hs21_tiny_qp_rw.h +8 -3
  39. data/vendor/scs/test/problems/max_ent +0 -0
  40. data/vendor/scs/test/problems/max_ent.h +8 -0
  41. data/vendor/scs/test/problems/random_prob.h +2 -43
  42. data/vendor/scs/test/problems/rob_gauss_cov_est.h +7 -2
  43. data/vendor/scs/test/problems/test_exp_cone.h +84 -0
  44. data/vendor/scs/test/problems/test_prob_from_data_file.h +57 -0
  45. data/vendor/scs/test/run_from_file.c +7 -1
  46. data/vendor/scs/test/run_tests.c +22 -9
  47. metadata +10 -3
@@ -0,0 +1,399 @@
1
+ #include "cones.h"
2
+ #include "glbopts.h"
3
+ #include "linalg.h"
4
+ #include "scs.h"
5
+
6
+ #define EXP_CONE_INFINITY_VALUE (1E15)
7
+
8
+ /*
9
+ * Exponential cone projection routines, from:
10
+ *
11
+ * Projection onto the exponential cone: a univariate root-finding problem,
12
+ * by Henrik A. Friberg, 2021.
13
+ *
14
+ */
15
+
16
+ static inline scs_int _isfinite(scs_float x) {
17
+ return ABS(x) < EXP_CONE_INFINITY_VALUE;
18
+ }
19
+
20
+ static inline scs_float _clip(scs_float x, scs_float l, scs_float u) {
21
+ return MAX(l, MIN(u, x));
22
+ }
23
+
24
+ /* As defined in Friberg, 2021 (multiplied by positive polynomial) */
25
+ static void hfun(const scs_float *v0, scs_float rho, scs_float *f,
26
+ scs_float *df) {
27
+ scs_float t0 = v0[2], s0 = v0[1], r0 = v0[0];
28
+ scs_float exprho = exp(rho);
29
+ scs_float expnegrho = exp(-rho);
30
+ /* function value at v0 */
31
+ *f = ((rho - 1) * r0 + s0) * exprho - (r0 - rho * s0) * expnegrho -
32
+ (rho * (rho - 1) + 1) * t0;
33
+ /* gradient of function at v0 */
34
+ *df = (rho * r0 + s0) * exprho + (r0 - (rho - 1) * s0) * expnegrho -
35
+ (2 * rho - 1) * t0;
36
+ }
37
+
38
+ /* Binary search for the root of the hfun function */
39
+ static scs_float root_search_binary(const scs_float *v0, scs_float xl,
40
+ scs_float xu, scs_float x) {
41
+ #if VERBOSITY > 0
42
+ scs_printf("Exp cone: Newton method failed, resorting to binary search.\n");
43
+ #endif
44
+ const scs_float EPS = 1e-12; /* expensive so loosen tol */
45
+ const scs_int MAXITER = 40;
46
+ scs_int i;
47
+ scs_float x_plus = x, f, df;
48
+ for (i = 0; i < MAXITER; i++) {
49
+ hfun(v0, x, &f, &df);
50
+ if (f < 0.0) {
51
+ xl = x;
52
+ } else {
53
+ xu = x;
54
+ }
55
+ /* binary search step */
56
+ x_plus = 0.5 * (xl + xu);
57
+ if (ABS(x_plus - x) <= EPS * MAX(1., ABS(x_plus)) || (x_plus == xl) ||
58
+ (x_plus == xu)) {
59
+ break;
60
+ }
61
+ x = x_plus;
62
+ }
63
+ return x_plus;
64
+ }
65
+
66
+ /* Use damped Newton's to find the root of the hfun function */
67
+ static scs_float root_search_newton(const scs_float *v0, scs_float xl,
68
+ scs_float xu, scs_float x) {
69
+ /* params taken from Friberg code */
70
+ const scs_float EPS = 1e-15;
71
+ const scs_float DFTOL = 1e-13; /* pow(EPS, 6.0 / 7.0) */
72
+ const scs_int MAXITER = 20;
73
+ const scs_float LODAMP = 0.05;
74
+ const scs_float HIDAMP = 0.95;
75
+
76
+ scs_float x_plus, f, df;
77
+ scs_int i;
78
+
79
+ for (i = 0; i < MAXITER; i++) {
80
+ hfun(v0, x, &f, &df);
81
+
82
+ if (ABS(f) <= EPS) { /* root found */
83
+ break;
84
+ }
85
+
86
+ if (f < 0.0) {
87
+ xl = x;
88
+ } else {
89
+ xu = x;
90
+ }
91
+
92
+ if (xu <= xl) {
93
+ xu = 0.5 * (xu + xl);
94
+ xl = xu;
95
+ break;
96
+ }
97
+
98
+ if (!_isfinite(f) || df < DFTOL) {
99
+ break;
100
+ }
101
+
102
+ /* Newton step */
103
+ x_plus = x - f / df;
104
+
105
+ if (ABS(x_plus - x) <= EPS * MAX(1., ABS(x_plus))) {
106
+ break;
107
+ }
108
+
109
+ if (x_plus >= xu) {
110
+ x = MIN(LODAMP * x + HIDAMP * xu, xu);
111
+ } else if (x_plus <= xl) {
112
+ x = MAX(LODAMP * x + HIDAMP * xl, xl);
113
+ } else {
114
+ x = x_plus;
115
+ }
116
+ }
117
+ if (i < MAXITER) { /* Newton's method converged */
118
+ #if VERBOSITY > 0
119
+ scs_printf("Exp cone: Newton iters:%i, f:%.4e, df:%.4e\n", (int)i, f, df);
120
+ #endif
121
+ return _clip(x, xl, xu);
122
+ }
123
+ /* Fall back to binary search if Newton failed */
124
+ return root_search_binary(v0, xl, xu, x);
125
+ }
126
+
127
+ /* try heuristic (cheap) projection */
128
+ static scs_float proj_primal_exp_cone_heuristic(const scs_float *v0,
129
+ scs_float *vp) {
130
+ scs_float t0 = v0[2], s0 = v0[1], r0 = v0[0];
131
+ scs_float dist, tp, newdist;
132
+ /* perspective boundary */
133
+ vp[2] = MAX(t0, 0);
134
+ vp[1] = 0.0;
135
+ vp[0] = MIN(r0, 0);
136
+ dist = SCS(norm_diff)(v0, vp, 3);
137
+
138
+ /* perspective interior */
139
+ if (s0 > 0.0) {
140
+ tp = MAX(t0, s0 * exp(r0 / s0));
141
+ newdist = tp - t0;
142
+ if (newdist < dist) {
143
+ vp[2] = tp;
144
+ vp[1] = s0;
145
+ vp[0] = r0;
146
+ dist = newdist;
147
+ }
148
+ }
149
+ return dist;
150
+ }
151
+
152
+ /* try heuristic (cheap) projection */
153
+ static scs_float proj_polar_exp_cone_heuristic(const scs_float *v0,
154
+ scs_float *vd) {
155
+ scs_float t0 = v0[2], s0 = v0[1], r0 = v0[0];
156
+ scs_float dist, td, newdist;
157
+ /* perspective boundary */
158
+ vd[2] = MIN(t0, 0);
159
+ vd[1] = MIN(s0, 0);
160
+ vd[0] = 0.0;
161
+ dist = SCS(norm_diff)(v0, vd, 3);
162
+
163
+ /* perspective interior */
164
+ if (r0 > 0.0) {
165
+ td = MIN(t0, -r0 * exp(s0 / r0 - 1));
166
+ newdist = t0 - td;
167
+ if (newdist < dist) {
168
+ vd[2] = td;
169
+ vd[1] = s0;
170
+ vd[0] = r0;
171
+ dist = newdist;
172
+ }
173
+ }
174
+ return dist;
175
+ }
176
+
177
+ static scs_float ppsi(const scs_float *v0) {
178
+ scs_float s0 = v0[1], r0 = v0[0];
179
+ scs_float psi;
180
+
181
+ if (r0 > s0) {
182
+ psi = (r0 - s0 + sqrt(r0 * r0 + s0 * s0 - r0 * s0)) / r0;
183
+ } else {
184
+ psi = -s0 / (r0 - s0 - sqrt(r0 * r0 + s0 * s0 - r0 * s0));
185
+ }
186
+
187
+ return ((psi - 1) * r0 + s0) / (psi * (psi - 1) + 1);
188
+ }
189
+
190
+ static scs_float pomega(scs_float rho) {
191
+ scs_float val = exp(rho) / (rho * (rho - 1) + 1);
192
+
193
+ if (rho < 2.0) {
194
+ val = MIN(val, exp(2.0) / 3);
195
+ }
196
+
197
+ return val;
198
+ }
199
+
200
+ static scs_float dpsi(const scs_float *v0) {
201
+ scs_float s0 = v0[1], r0 = v0[0];
202
+ scs_float psi;
203
+
204
+ if (s0 > r0) {
205
+ psi = (r0 - sqrt(r0 * r0 + s0 * s0 - r0 * s0)) / s0;
206
+ } else {
207
+ psi = (r0 - s0) / (r0 + sqrt(r0 * r0 + s0 * s0 - r0 * s0));
208
+ }
209
+
210
+ return (r0 - psi * s0) / (psi * (psi - 1) + 1);
211
+ }
212
+
213
+ static scs_float domega(scs_float rho) {
214
+ scs_float val = -exp(-rho) / (rho * (rho - 1) + 1);
215
+
216
+ if (rho > -1.0) {
217
+ val = MAX(val, -exp(1.0) / 3);
218
+ }
219
+
220
+ return val;
221
+ }
222
+
223
+ /* Generate upper and lower search bounds for root of hfun */
224
+ static void exp_search_bracket(const scs_float *v0, scs_float pdist,
225
+ scs_float ddist, scs_float *low_out,
226
+ scs_float *upr_out) {
227
+ scs_float t0 = v0[2], s0 = v0[1], r0 = v0[0];
228
+ scs_float baselow = -EXP_CONE_INFINITY_VALUE,
229
+ baseupr = EXP_CONE_INFINITY_VALUE;
230
+ scs_float low = -EXP_CONE_INFINITY_VALUE, upr = EXP_CONE_INFINITY_VALUE;
231
+
232
+ scs_float Dp = SQRTF(pdist * pdist - MIN(s0, 0) * MIN(s0, 0));
233
+ scs_float Dd = SQRTF(ddist * ddist - MIN(r0, 0) * MIN(r0, 0));
234
+
235
+ scs_float curbnd, fl, fu, df, tpu, tdl;
236
+
237
+ if (t0 > 0) {
238
+ curbnd = log(t0 / ppsi(v0));
239
+ low = MAX(low, curbnd);
240
+ } else if (t0 < 0) {
241
+ curbnd = -log(-t0 / dpsi(v0));
242
+ upr = MIN(upr, curbnd);
243
+ }
244
+
245
+ if (r0 > 0) {
246
+ baselow = 1 - s0 / r0;
247
+ low = MAX(low, baselow);
248
+ tpu = MAX(1e-12, MIN(Dd, Dp + t0));
249
+ curbnd = MAX(low, baselow + tpu / r0 / pomega(low));
250
+ upr = MIN(upr, curbnd);
251
+ }
252
+
253
+ if (s0 > 0) {
254
+ baseupr = r0 / s0;
255
+ upr = MIN(upr, baseupr);
256
+ tdl = -MAX(1e-12, MIN(Dp, Dd - t0));
257
+ curbnd = MIN(upr, baseupr - tdl / s0 / domega(upr));
258
+ low = MAX(low, curbnd);
259
+ }
260
+
261
+ /* Guarantee valid bracket */
262
+ /* TODO do we need these 2 lines? */
263
+ low = _clip(MIN(low, upr), baselow, baseupr);
264
+ upr = _clip(MAX(low, upr), baselow, baseupr);
265
+
266
+ if (low != upr) {
267
+ hfun(v0, low, &fl, &df);
268
+ hfun(v0, upr, &fu, &df);
269
+
270
+ if (fl * fu > 0) {
271
+ if (ABS(fl) < ABS(fu)) {
272
+ upr = low;
273
+ } else {
274
+ low = upr;
275
+ }
276
+ }
277
+ }
278
+
279
+ *low_out = low;
280
+ *upr_out = upr;
281
+ }
282
+
283
+ /* convert from rho to primal projection */
284
+ static scs_float proj_sol_primal_exp_cone(const scs_float *v0, scs_float rho,
285
+ scs_float *vp) {
286
+ scs_float linrho = (rho - 1) * v0[0] + v0[1];
287
+ scs_float exprho = exp(rho);
288
+ scs_float quadrho, dist;
289
+ if (linrho > 0 && _isfinite(exprho)) {
290
+ quadrho = rho * (rho - 1) + 1;
291
+ vp[2] = exprho * linrho / quadrho;
292
+ vp[1] = linrho / quadrho;
293
+ vp[0] = rho * linrho / quadrho;
294
+ dist = SCS(norm_diff)(vp, v0, 3);
295
+ } else {
296
+ vp[2] = EXP_CONE_INFINITY_VALUE;
297
+ vp[1] = 0.0;
298
+ vp[0] = 0.0;
299
+ dist = EXP_CONE_INFINITY_VALUE;
300
+ }
301
+ return dist;
302
+ }
303
+
304
+ /* convert from rho to polar projection */
305
+ static scs_float proj_sol_polar_exp_cone(const scs_float *v0, scs_float rho,
306
+ scs_float *vd) {
307
+ scs_float linrho = v0[0] - rho * v0[1];
308
+ scs_float exprho = exp(-rho);
309
+ scs_float quadrho, dist;
310
+ if (linrho > 0 && _isfinite(exprho)) {
311
+ quadrho = rho * (rho - 1) + 1;
312
+ vd[2] = -exprho * linrho / quadrho;
313
+ vd[1] = (1 - rho) * linrho / quadrho;
314
+ vd[0] = linrho / quadrho;
315
+ dist = SCS(norm_diff)(v0, vd, 3);
316
+ } else {
317
+ vd[2] = -EXP_CONE_INFINITY_VALUE;
318
+ vd[1] = 0.0;
319
+ vd[0] = 0.0;
320
+ dist = EXP_CONE_INFINITY_VALUE;
321
+ }
322
+ return dist;
323
+ }
324
+
325
+ static inline void _copy(scs_float *dest, scs_float *src) {
326
+ dest[0] = src[0];
327
+ dest[1] = src[1];
328
+ dest[2] = src[2];
329
+ }
330
+
331
+ /* Project onto primal or dual exponential cone, performed in-place.
332
+ * If `primal=0` then project on the dual cone, otherwise project
333
+ * onto primal. Taken from algorithm in Friberg, 2021.
334
+ */
335
+ scs_float SCS(proj_pd_exp_cone)(scs_float *v0, scs_int primal) {
336
+ scs_float TOL = 1e-8; /* pow(1e-10, 2.0 / 3.0); */
337
+ scs_float xl, xh, pdist, ddist, err, rho, dist_hat;
338
+ scs_float vp[3], vd[3], v_hat[3];
339
+ scs_int opt;
340
+ if (!primal) {
341
+ /* This routine actually projects onto primal and polar cones
342
+ * simultaneously. So to make it project onto dual, use this:
343
+ * Pi_{C^*}(v0) = -Pi_{C^polar}(-v0)
344
+ */
345
+ v0[0] *= -1.;
346
+ v0[1] *= -1.;
347
+ v0[2] *= -1.;
348
+ }
349
+
350
+ pdist = proj_primal_exp_cone_heuristic(v0, vp);
351
+ ddist = proj_polar_exp_cone_heuristic(v0, vd);
352
+
353
+ err = ABS(vp[0] + vd[0] - v0[0]);
354
+ err = MAX(err, ABS(vp[1] + vd[1] - v0[1]));
355
+ err = MAX(err, ABS(vp[2] + vd[2] - v0[2]));
356
+
357
+ /* Skip root search if presolve rules apply
358
+ * or optimality conditions are satisfied
359
+ */
360
+ opt = (v0[1] <= 0 && v0[0] <= 0);
361
+ opt |= (MIN(pdist, ddist) <= TOL);
362
+ opt |= (err <= TOL && SCS(dot)(vp, vd, 3) <= TOL);
363
+ if (opt) {
364
+ if (primal) {
365
+ _copy(v0, vp);
366
+ return pdist;
367
+ }
368
+ /* polar cone -> dual cone */
369
+ v0[0] = -vd[0];
370
+ v0[1] = -vd[1];
371
+ v0[2] = -vd[2];
372
+ return ddist;
373
+ }
374
+
375
+ exp_search_bracket(v0, pdist, ddist, &xl, &xh);
376
+ rho = root_search_newton(v0, xl, xh, 0.5 * (xl + xh));
377
+
378
+ if (primal) {
379
+ /* primal cone projection */
380
+ dist_hat = proj_sol_primal_exp_cone(v0, rho, v_hat);
381
+ if (dist_hat <= pdist) {
382
+ _copy(vp, v_hat);
383
+ pdist = dist_hat;
384
+ }
385
+ _copy(v0, vp);
386
+ return pdist;
387
+ }
388
+ /* polar cone projection */
389
+ dist_hat = proj_sol_polar_exp_cone(v0, rho, v_hat);
390
+ if (dist_hat <= ddist) {
391
+ _copy(vd, v_hat);
392
+ ddist = dist_hat;
393
+ }
394
+ /* polar cone -> dual cone */
395
+ v0[0] = -vd[0];
396
+ v0[1] = -vd[1];
397
+ v0[2] = -vd[2];
398
+ return ddist;
399
+ }
@@ -26,7 +26,7 @@
26
26
  */
27
27
  void SCS(normalize_b_c)(ScsScaling *scal, scs_float *b, scs_float *c) {
28
28
  scs_int i;
29
- scs_float sigma;
29
+ scs_float sigma, nm_c, nm_b;
30
30
 
31
31
  /* scale c */
32
32
  for (i = 0; i < scal->n; ++i) {
@@ -38,7 +38,9 @@ void SCS(normalize_b_c)(ScsScaling *scal, scs_float *b, scs_float *c) {
38
38
  }
39
39
 
40
40
  /* calculate primal and dual scales */
41
- sigma = MAX(SCS(norm_inf)(c, scal->n), SCS(norm_inf)(b, scal->m));
41
+ nm_c = SCS(norm_inf)(c, scal->n);
42
+ nm_b = SCS(norm_inf)(b, scal->m);
43
+ sigma = MAX(nm_c, nm_b);
42
44
  sigma = sigma < MIN_NORMALIZATION_FACTOR ? 1.0 : sigma;
43
45
  sigma = sigma > MAX_NORMALIZATION_FACTOR ? MAX_NORMALIZATION_FACTOR : sigma;
44
46
  sigma = SAFEDIV_POS(1.0, sigma);
data/vendor/scs/src/rw.c CHANGED
@@ -1,5 +1,6 @@
1
1
  #include "rw.h"
2
2
 
3
+ #include <errno.h>
3
4
  #include <stdint.h>
4
5
  #include <stdio.h>
5
6
  #include <stdlib.h>
@@ -9,6 +10,25 @@
9
10
  #include "scs_matrix.h"
10
11
  #include "util.h"
11
12
 
13
+ #if NO_READ_WRITE > 0 /* Disables all read / write functionality */
14
+
15
+ void SCS(write_data)(const ScsData *d, const ScsCone *k,
16
+ const ScsSettings *stgs) {
17
+ /* Do nothing */
18
+ }
19
+ scs_int SCS(read_data)(const char *filename, ScsData **d, ScsCone **k,
20
+ ScsSettings **stgs) {
21
+ /* Failure */
22
+ return -1;
23
+ }
24
+ void SCS(log_data_to_csv)(const ScsCone *k, const ScsSettings *stgs,
25
+ const ScsWork *w, scs_int iter,
26
+ SCS(timer) * solve_timer) {
27
+ /* Do nothing */
28
+ }
29
+
30
+ #else
31
+
12
32
  /* writes/reads problem data to/from filename */
13
33
  /* This is a VERY naive implementation, doesn't care about portability etc */
14
34
 
@@ -28,30 +48,61 @@ static void write_scs_cone(const ScsCone *k, FILE *fout) {
28
48
  fwrite(k->p, sizeof(scs_float), k->psize, fout);
29
49
  }
30
50
 
31
- static ScsCone *read_scs_cone(FILE *fin) {
51
+ /*
52
+ * Read integer data from file. If the integer width on file is
53
+ * different to scs_int then it will cast the ints after reading
54
+ * to be compatible with the SCS data types.
55
+ */
56
+ static size_t read_int(scs_int *dest, size_t file_int_sz, size_t nitems,
57
+ FILE *fin) {
58
+ if (file_int_sz == sizeof(scs_int)) {
59
+ return fread(dest, sizeof(scs_int), nitems, fin);
60
+ }
61
+ void *ptr = scs_calloc(nitems, file_int_sz);
62
+ size_t val = fread(ptr, file_int_sz, nitems, fin);
63
+ scs_int i;
64
+ switch (file_int_sz) {
65
+ case 4:
66
+ for (i = 0; i < nitems; ++i) {
67
+ dest[i] = (scs_int)(((int *)ptr)[i]);
68
+ }
69
+ break;
70
+ case 8:
71
+ for (i = 0; i < nitems; ++i) {
72
+ dest[i] = (scs_int)(((long long *)ptr)[i]);
73
+ }
74
+ break;
75
+ }
76
+ if (ptr) {
77
+ scs_free(ptr);
78
+ }
79
+ return val;
80
+ }
81
+
82
+ static ScsCone *read_scs_cone(FILE *fin, size_t file_int_sz) {
32
83
  ScsCone *k = (ScsCone *)scs_calloc(1, sizeof(ScsCone));
33
- fread(&(k->z), sizeof(scs_int), 1, fin);
34
- fread(&(k->l), sizeof(scs_int), 1, fin);
35
- fread(&(k->bsize), sizeof(scs_int), 1, fin);
84
+ read_int(&(k->z), file_int_sz, 1, fin);
85
+ read_int(&(k->l), file_int_sz, 1, fin);
86
+ read_int(&(k->bsize), file_int_sz, 1, fin);
36
87
  if (k->bsize > 1) {
37
88
  k->bl = (scs_float *)scs_calloc(MAX(k->bsize - 1, 0), sizeof(scs_float));
38
89
  k->bu = (scs_float *)scs_calloc(MAX(k->bsize - 1, 0), sizeof(scs_float));
39
90
  fread(k->bl, sizeof(scs_float), MAX(k->bsize - 1, 0), fin);
40
91
  fread(k->bu, sizeof(scs_float), MAX(k->bsize - 1, 0), fin);
41
92
  }
42
- fread(&(k->qsize), sizeof(scs_int), 1, fin);
93
+ read_int(&(k->qsize), file_int_sz, 1, fin);
43
94
  if (k->qsize) {
44
95
  k->q = (scs_int *)scs_calloc(k->qsize, sizeof(scs_int));
45
- fread(k->q, sizeof(scs_int), k->qsize, fin);
96
+ read_int(k->q, file_int_sz, k->qsize, fin);
46
97
  }
47
- fread(&(k->ssize), sizeof(scs_int), 1, fin);
98
+ read_int(&(k->ssize), file_int_sz, 1, fin);
48
99
  if (k->ssize) {
49
100
  k->s = (scs_int *)scs_calloc(k->ssize, sizeof(scs_int));
50
- fread(k->s, sizeof(scs_int), k->ssize, fin);
101
+ read_int(k->s, file_int_sz, k->ssize, fin);
51
102
  }
52
- fread(&(k->ep), sizeof(scs_int), 1, fin);
53
- fread(&(k->ed), sizeof(scs_int), 1, fin);
54
- fread(&(k->psize), sizeof(scs_int), 1, fin);
103
+ read_int(&(k->ep), file_int_sz, 1, fin);
104
+ read_int(&(k->ed), file_int_sz, 1, fin);
105
+ read_int(&(k->psize), file_int_sz, 1, fin);
55
106
  if (k->psize) {
56
107
  k->p = (scs_float *)scs_calloc(k->psize, sizeof(scs_float));
57
108
  fread(k->p, sizeof(scs_float), k->psize, fin);
@@ -79,21 +130,21 @@ static void write_scs_stgs(const ScsSettings *s, FILE *fout) {
79
130
  /* Do not write the log_csv_filename */
80
131
  }
81
132
 
82
- static ScsSettings *read_scs_stgs(FILE *fin) {
133
+ static ScsSettings *read_scs_stgs(FILE *fin, size_t file_int_sz) {
83
134
  ScsSettings *s = (ScsSettings *)scs_calloc(1, sizeof(ScsSettings));
84
- fread(&(s->normalize), sizeof(scs_int), 1, fin);
135
+ read_int(&(s->normalize), file_int_sz, 1, fin);
85
136
  fread(&(s->scale), sizeof(scs_float), 1, fin);
86
137
  fread(&(s->rho_x), sizeof(scs_float), 1, fin);
87
- fread(&(s->max_iters), sizeof(scs_int), 1, fin);
138
+ read_int(&(s->max_iters), file_int_sz, 1, fin);
88
139
  fread(&(s->eps_abs), sizeof(scs_float), 1, fin);
89
140
  fread(&(s->eps_rel), sizeof(scs_float), 1, fin);
90
141
  fread(&(s->eps_infeas), sizeof(scs_float), 1, fin);
91
142
  fread(&(s->alpha), sizeof(scs_float), 1, fin);
92
- fread(&(s->verbose), sizeof(scs_int), 1, fin);
93
- fread(&(s->warm_start), sizeof(scs_int), 1, fin);
94
- fread(&(s->acceleration_lookback), sizeof(scs_int), 1, fin);
95
- fread(&(s->acceleration_interval), sizeof(scs_int), 1, fin);
96
- fread(&(s->adaptive_scale), sizeof(scs_int), 1, fin);
143
+ read_int(&(s->verbose), file_int_sz, 1, fin);
144
+ read_int(&(s->warm_start), file_int_sz, 1, fin);
145
+ read_int(&(s->acceleration_lookback), file_int_sz, 1, fin);
146
+ read_int(&(s->acceleration_interval), file_int_sz, 1, fin);
147
+ read_int(&(s->adaptive_scale), file_int_sz, 1, fin);
97
148
  return s;
98
149
  }
99
150
 
@@ -106,18 +157,18 @@ static void write_amatrix(const ScsMatrix *A, FILE *fout) {
106
157
  fwrite(A->i, sizeof(scs_int), Anz, fout);
107
158
  }
108
159
 
109
- static ScsMatrix *read_amatrix(FILE *fin) {
160
+ static ScsMatrix *read_amatrix(FILE *fin, size_t file_int_sz) {
110
161
  scs_int Anz;
111
162
  ScsMatrix *A = (ScsMatrix *)scs_calloc(1, sizeof(ScsMatrix));
112
- fread(&(A->m), sizeof(scs_int), 1, fin);
113
- fread(&(A->n), sizeof(scs_int), 1, fin);
163
+ read_int(&(A->m), file_int_sz, 1, fin);
164
+ read_int(&(A->n), file_int_sz, 1, fin);
114
165
  A->p = (scs_int *)scs_calloc(A->n + 1, sizeof(scs_int));
115
- fread(A->p, sizeof(scs_int), A->n + 1, fin);
166
+ read_int(A->p, file_int_sz, A->n + 1, fin);
116
167
  Anz = A->p[A->n];
117
168
  A->x = (scs_float *)scs_calloc(Anz, sizeof(scs_float));
118
169
  A->i = (scs_int *)scs_calloc(Anz, sizeof(scs_int));
119
170
  fread(A->x, sizeof(scs_float), Anz, fin);
120
- fread(A->i, sizeof(scs_int), Anz, fin);
171
+ read_int(A->i, file_int_sz, Anz, fin);
121
172
  return A;
122
173
  }
123
174
 
@@ -135,19 +186,20 @@ static void write_scs_data(const ScsData *d, FILE *fout) {
135
186
  }
136
187
  }
137
188
 
138
- static ScsData *read_scs_data(FILE *fin) {
189
+ static ScsData *read_scs_data(FILE *fin, size_t file_int_sz) {
139
190
  scs_int has_p = 0;
140
191
  ScsData *d = (ScsData *)scs_calloc(1, sizeof(ScsData));
141
- fread(&(d->m), sizeof(scs_int), 1, fin);
142
- fread(&(d->n), sizeof(scs_int), 1, fin);
192
+
193
+ read_int(&(d->m), file_int_sz, 1, fin);
194
+ read_int(&(d->n), file_int_sz, 1, fin);
143
195
  d->b = (scs_float *)scs_calloc(d->m, sizeof(scs_float));
144
196
  d->c = (scs_float *)scs_calloc(d->n, sizeof(scs_float));
145
197
  fread(d->b, sizeof(scs_float), d->m, fin);
146
198
  fread(d->c, sizeof(scs_float), d->n, fin);
147
- d->A = read_amatrix(fin);
199
+ d->A = read_amatrix(fin, file_int_sz);
148
200
  /* If has_p bit is not set or this hits end of file then has_p = 0 */
149
- has_p &= fread(&has_p, sizeof(scs_int), 1, fin);
150
- d->P = has_p ? read_amatrix(fin) : SCS_NULL;
201
+ has_p &= read_int(&has_p, file_int_sz, 1, fin);
202
+ d->P = has_p ? read_amatrix(fin, file_int_sz) : SCS_NULL;
151
203
  return d;
152
204
  }
153
205
 
@@ -158,7 +210,6 @@ void SCS(write_data)(const ScsData *d, const ScsCone *k,
158
210
  uint32_t scs_float_sz = (uint32_t)sizeof(scs_float);
159
211
  const char *scs_version = SCS_VERSION;
160
212
  uint32_t scs_version_sz = (uint32_t)strlen(scs_version);
161
- scs_printf("writing data to %s\n", stgs->write_data_filename);
162
213
  fwrite(&(scs_int_sz), sizeof(uint32_t), 1, fout);
163
214
  fwrite(&(scs_float_sz), sizeof(uint32_t), 1, fout);
164
215
  fwrite(&(scs_version_sz), sizeof(uint32_t), 1, fout);
@@ -175,9 +226,11 @@ scs_int SCS(read_data)(const char *filename, ScsData **d, ScsCone **k,
175
226
  uint32_t file_float_sz;
176
227
  uint32_t file_version_sz;
177
228
  char file_version[16];
229
+ errno = 0;
178
230
  FILE *fin = fopen(filename, "rb");
179
231
  if (!fin) {
180
232
  scs_printf("Error reading file %s\n", filename);
233
+ scs_printf("errno:%i:%s\n", errno, strerror(errno));
181
234
  return -1;
182
235
  }
183
236
  scs_printf("Reading data from %s\n", filename);
@@ -185,11 +238,10 @@ scs_int SCS(read_data)(const char *filename, ScsData **d, ScsCone **k,
185
238
  fread(&(file_float_sz), sizeof(uint32_t), 1, fin);
186
239
  if (file_int_sz != (uint32_t)sizeof(scs_int)) {
187
240
  scs_printf(
188
- "Error, sizeof(file int) is %lu, but scs expects sizeof(int) %lu, "
189
- "scs should be recompiled with correct flags.\n",
241
+ "Warning, sizeof(file int) is %lu, but scs expects sizeof(int) %lu. "
242
+ "SCS will attempt to cast the data, which may be slow. "
243
+ "This message can be avoided by recompiling with the correct flags.\n",
190
244
  (unsigned long)file_int_sz, (unsigned long)sizeof(scs_int));
191
- fclose(fin);
192
- return -1;
193
245
  }
194
246
  if (file_float_sz != (uint32_t)sizeof(scs_float)) {
195
247
  scs_printf(
@@ -209,9 +261,10 @@ scs_int SCS(read_data)(const char *filename, ScsData **d, ScsCone **k,
209
261
  "************************************************************\n",
210
262
  file_version, SCS_VERSION);
211
263
  }
212
- *k = read_scs_cone(fin);
213
- *d = read_scs_data(fin);
214
- *stgs = read_scs_stgs(fin);
264
+ *k = read_scs_cone(fin, file_int_sz);
265
+ *d = read_scs_data(fin, file_int_sz);
266
+ *stgs = read_scs_stgs(fin, file_int_sz);
267
+ scs_printf("Finished reading data.\n");
215
268
  fclose(fin);
216
269
  return 0;
217
270
  }
@@ -348,3 +401,5 @@ void SCS(log_data_to_csv)(const ScsCone *k, const ScsSettings *stgs,
348
401
  fprintf(fout, "\n");
349
402
  fclose(fout);
350
403
  }
404
+
405
+ #endif