scs 0.4.0 → 0.4.1

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.
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