scs 0.5.6 → 0.6.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.
Files changed (95) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +5 -0
  3. data/LICENSE.txt +1 -1
  4. data/lib/scs/ffi.rb +18 -0
  5. data/lib/scs/version.rb +1 -1
  6. data/vendor/scs/CITATION.cff +2 -3
  7. data/vendor/scs/CLAUDE.md +115 -0
  8. data/vendor/scs/CMakeLists.txt +330 -201
  9. data/vendor/scs/CONTRIBUTING.md +49 -0
  10. data/vendor/scs/Makefile +90 -43
  11. data/vendor/scs/README.md +96 -2
  12. data/vendor/scs/include/aa.h +59 -11
  13. data/vendor/scs/include/aa_stats.h +47 -0
  14. data/vendor/scs/include/cones.h +16 -7
  15. data/vendor/scs/include/glbopts.h +113 -26
  16. data/vendor/scs/include/linalg.h +5 -1
  17. data/vendor/scs/include/linsys.h +1 -2
  18. data/vendor/scs/include/normalize.h +6 -2
  19. data/vendor/scs/include/rw.h +9 -3
  20. data/vendor/scs/include/scs.h +17 -1
  21. data/vendor/scs/include/scs_blas.h +8 -0
  22. data/vendor/scs/include/scs_types.h +2 -2
  23. data/vendor/scs/include/scs_work.h +22 -1
  24. data/vendor/scs/include/util.h +3 -6
  25. data/vendor/scs/include/util_spectral_cones.h +3 -3
  26. data/vendor/scs/linsys/accelerate/direct/private.c +126 -0
  27. data/vendor/scs/linsys/accelerate/direct/private.h +34 -0
  28. data/vendor/scs/linsys/cpu/dense/private.c +250 -0
  29. data/vendor/scs/linsys/cpu/dense/private.h +31 -0
  30. data/vendor/scs/linsys/cpu/direct/private.c +86 -44
  31. data/vendor/scs/linsys/cpu/indirect/private.c +647 -113
  32. data/vendor/scs/linsys/cpu/indirect/private.h +28 -0
  33. data/vendor/scs/linsys/csparse.c +9 -3
  34. data/vendor/scs/linsys/csparse.h +4 -2
  35. data/vendor/scs/linsys/cudss/direct/private.c +77 -43
  36. data/vendor/scs/linsys/cudss/direct/private.h +33 -7
  37. data/vendor/scs/linsys/gpu/indirect/private.c +6 -2
  38. data/vendor/scs/linsys/mkl/direct/private.c +63 -31
  39. data/vendor/scs/linsys/mkl/direct/private.h +0 -1
  40. data/vendor/scs/linsys/scs_matrix.c +291 -165
  41. data/vendor/scs/linsys/scs_matrix.h +7 -9
  42. data/vendor/scs/scs.mk +35 -13
  43. data/vendor/scs/src/aa.c +673 -166
  44. data/vendor/scs/src/cones.c +545 -223
  45. data/vendor/scs/src/ctrlc.c +59 -16
  46. data/vendor/scs/src/exp_cone.c +70 -50
  47. data/vendor/scs/src/linalg.c +21 -2
  48. data/vendor/scs/src/normalize.c +24 -26
  49. data/vendor/scs/src/rw.c +596 -124
  50. data/vendor/scs/src/scs.c +990 -513
  51. data/vendor/scs/src/spectral_cones/logdeterminant/log_cone_IPM.c +240 -187
  52. data/vendor/scs/src/spectral_cones/logdeterminant/log_cone_Newton.c +108 -85
  53. data/vendor/scs/src/spectral_cones/logdeterminant/log_cone_wrapper.c +62 -63
  54. data/vendor/scs/src/spectral_cones/logdeterminant/logdet_cone.c +85 -78
  55. data/vendor/scs/src/spectral_cones/nuclear/ell1_cone.c +92 -97
  56. data/vendor/scs/src/spectral_cones/nuclear/nuclear_cone.c +39 -28
  57. data/vendor/scs/src/spectral_cones/sum-largest/sum_largest_cone.c +59 -40
  58. data/vendor/scs/src/spectral_cones/sum-largest/sum_largest_eval_cone.c +37 -29
  59. data/vendor/scs/src/spectral_cones/util_spectral_cones.c +12 -6
  60. data/vendor/scs/src/util.c +37 -7
  61. data/vendor/scs/test/mkl_interface_mismatch.c +97 -0
  62. data/vendor/scs/test/packaging/CMakeLists.txt +21 -0
  63. data/vendor/scs/test/packaging/consume.c +50 -0
  64. data/vendor/scs/test/problem_utils.h +9 -2
  65. data/vendor/scs/test/problems/dense_qp.h +64 -0
  66. data/vendor/scs/test/problems/hs21_tiny_qp.h +6 -2
  67. data/vendor/scs/test/problems/hs21_tiny_qp_rw.h +10 -2
  68. data/vendor/scs/test/problems/infeasible_lp.h +66 -0
  69. data/vendor/scs/test/problems/infeasible_socp.h +75 -0
  70. data/vendor/scs/test/problems/lp_update.h +110 -0
  71. data/vendor/scs/test/problems/qafiro_tiny_qp.h +3 -1
  72. data/vendor/scs/test/problems/rob_gauss_cov_est.h +6 -3
  73. data/vendor/scs/test/problems/small_qp.h +5 -0
  74. data/vendor/scs/test/problems/test_box_cone.h +92 -0
  75. data/vendor/scs/test/problems/test_dual_exp_cone.h +96 -0
  76. data/vendor/scs/test/problems/test_inaccurate.h +212 -0
  77. data/vendor/scs/test/problems/test_mixed_cones.h +113 -0
  78. data/vendor/scs/test/problems/test_normalize_roundtrip.h +279 -0
  79. data/vendor/scs/test/problems/test_power_cone.h +414 -0
  80. data/vendor/scs/test/problems/test_psd_metric.h +109 -0
  81. data/vendor/scs/test/problems/test_psd_n1.h +84 -0
  82. data/vendor/scs/test/problems/test_root_plus.h +191 -0
  83. data/vendor/scs/test/problems/test_rw_settings.h +112 -0
  84. data/vendor/scs/test/problems/test_soc_sizes.h +393 -0
  85. data/vendor/scs/test/problems/test_solver_options.h +558 -0
  86. data/vendor/scs/test/problems/test_validation.h +263 -24
  87. data/vendor/scs/test/problems/test_zero_cone.h +81 -0
  88. data/vendor/scs/test/problems/unbounded_lp.h +66 -0
  89. data/vendor/scs/test/problems/unbounded_socp.h +71 -0
  90. data/vendor/scs/test/run_from_file.c +6 -0
  91. data/vendor/scs/test/run_tests.c +71 -0
  92. data/vendor/scs/test/rw_settings.c +7 -0
  93. data/vendor/scs/test/spectral_cones_problems/test_ell1_and_nuc.h +128 -0
  94. data/vendor/scs/test/spectral_cones_problems/test_ell1_cone.h +115 -0
  95. metadata +35 -3
data/vendor/scs/src/rw.c CHANGED
@@ -1,10 +1,17 @@
1
+ /*
2
+ * Read/write routines for serializing SCS problem data to binary files
3
+ * and logging solve progress to CSV. Compiled as no-ops when NO_READ_WRITE=1.
4
+ */
5
+
1
6
  #include "rw.h"
2
7
 
3
8
  #include <errno.h>
4
9
  #include <stdint.h>
5
10
  #include <stdio.h>
6
11
  #include <stdlib.h>
12
+ #include <string.h>
7
13
 
14
+ #include "cones.h"
8
15
  #include "linalg.h"
9
16
  #include "scs.h"
10
17
  #include "scs_matrix.h"
@@ -21,8 +28,13 @@ scs_int SCS(read_data)(const char *filename, ScsData **d, ScsCone **k,
21
28
  /* Failure */
22
29
  return -1;
23
30
  }
24
- void SCS(log_data_to_csv)(const ScsCone *k, const ScsSettings *stgs,
25
- const ScsWork *w, scs_int iter,
31
+ scs_int SCS(open_csv_log_file)(ScsWork *w) {
32
+ return 0;
33
+ }
34
+ void SCS(close_csv_log_file)(ScsWork *w) {
35
+ /* Do nothing */
36
+ }
37
+ void SCS(log_data_to_csv)(const ScsCone *k, const ScsWork *w, scs_int iter,
26
38
  SCS(timer) * solve_timer) {
27
39
  /* Do nothing */
28
40
  }
@@ -32,20 +44,82 @@ void SCS(log_data_to_csv)(const ScsCone *k, const ScsSettings *stgs,
32
44
  /* writes/reads problem data to/from filename */
33
45
  /* This is a VERY naive implementation, doesn't care about portability etc */
34
46
 
35
- static void write_scs_cone(const ScsCone *k, FILE *fout) {
36
- fwrite(&(k->z), sizeof(scs_int), 1, fout);
37
- fwrite(&(k->l), sizeof(scs_int), 1, fout);
38
- fwrite(&(k->bsize), sizeof(scs_int), 1, fout);
39
- fwrite(k->bl, sizeof(scs_float), MAX(k->bsize - 1, 0), fout);
40
- fwrite(k->bu, sizeof(scs_float), MAX(k->bsize - 1, 0), fout);
41
- fwrite(&(k->qsize), sizeof(scs_int), 1, fout);
42
- fwrite(k->q, sizeof(scs_int), k->qsize, fout);
43
- fwrite(&(k->ssize), sizeof(scs_int), 1, fout);
44
- fwrite(k->s, sizeof(scs_int), k->ssize, fout);
45
- fwrite(&(k->ep), sizeof(scs_int), 1, fout);
46
- fwrite(&(k->ed), sizeof(scs_int), 1, fout);
47
- fwrite(&(k->psize), sizeof(scs_int), 1, fout);
48
- fwrite(k->p, sizeof(scs_float), k->psize, fout);
47
+ #define RW_EXT_MAGIC ((uint32_t)0x53435345u) /* "SCSE" */
48
+ /* Extension-section schema version. Append-only: readers accept any
49
+ * version <= RW_EXT_VERSION, defaulting fields the file predates, and
50
+ * reject only files written by a NEWER schema than they understand.
51
+ * v1: cs/spectral cone arrays + time_limit_secs
52
+ * v2: + adaptive_diag_scale */
53
+ #define RW_EXT_VERSION ((uint32_t)2u)
54
+
55
+ static scs_int checked_fread(void *ptr, size_t size, size_t nmemb, FILE *fin) {
56
+ size_t ret;
57
+ if (nmemb == 0) {
58
+ return 0;
59
+ }
60
+ ret = fread(ptr, size, nmemb, fin);
61
+ if (ret != nmemb) {
62
+ scs_printf("Error: fread expected %lu items, got %lu\n",
63
+ (unsigned long)nmemb, (unsigned long)ret);
64
+ return -1;
65
+ }
66
+ return 0;
67
+ }
68
+
69
+ static scs_int checked_fwrite(const void *ptr, size_t size, size_t nmemb,
70
+ FILE *fout) {
71
+ size_t ret;
72
+ if (nmemb == 0) {
73
+ return 0;
74
+ }
75
+ if (!ptr) {
76
+ scs_printf("Error: fwrite passed NULL data for %lu items\n",
77
+ (unsigned long)nmemb);
78
+ return -1;
79
+ }
80
+ ret = fwrite(ptr, size, nmemb, fout);
81
+ if (ret != nmemb) {
82
+ scs_printf("Error: fwrite expected %lu items, wrote %lu\n",
83
+ (unsigned long)nmemb, (unsigned long)ret);
84
+ return -1;
85
+ }
86
+ return 0;
87
+ }
88
+
89
+ static scs_int write_int_array(const scs_int *x, scs_int n, FILE *fout) {
90
+ if (n < 0) {
91
+ scs_printf("Error: cannot write negative array length %li\n", (long)n);
92
+ return -1;
93
+ }
94
+ return checked_fwrite(x, sizeof(scs_int), (size_t)n, fout);
95
+ }
96
+
97
+ static scs_int write_float_array(const scs_float *x, scs_int n, FILE *fout) {
98
+ if (n < 0) {
99
+ scs_printf("Error: cannot write negative array length %li\n", (long)n);
100
+ return -1;
101
+ }
102
+ return checked_fwrite(x, sizeof(scs_float), (size_t)n, fout);
103
+ }
104
+
105
+ static scs_int write_scs_cone(const ScsCone *k, FILE *fout) {
106
+ scs_int box_len = MAX(k->bsize - 1, 0);
107
+ if (checked_fwrite(&(k->z), sizeof(scs_int), 1, fout) < 0 ||
108
+ checked_fwrite(&(k->l), sizeof(scs_int), 1, fout) < 0 ||
109
+ checked_fwrite(&(k->bsize), sizeof(scs_int), 1, fout) < 0 ||
110
+ write_float_array(k->bl, box_len, fout) < 0 ||
111
+ write_float_array(k->bu, box_len, fout) < 0 ||
112
+ checked_fwrite(&(k->qsize), sizeof(scs_int), 1, fout) < 0 ||
113
+ write_int_array(k->q, k->qsize, fout) < 0 ||
114
+ checked_fwrite(&(k->ssize), sizeof(scs_int), 1, fout) < 0 ||
115
+ write_int_array(k->s, k->ssize, fout) < 0 ||
116
+ checked_fwrite(&(k->ep), sizeof(scs_int), 1, fout) < 0 ||
117
+ checked_fwrite(&(k->ed), sizeof(scs_int), 1, fout) < 0 ||
118
+ checked_fwrite(&(k->psize), sizeof(scs_int), 1, fout) < 0 ||
119
+ write_float_array(k->p, k->psize, fout) < 0) {
120
+ return -1;
121
+ }
122
+ return 0;
49
123
  }
50
124
 
51
125
  /*
@@ -53,14 +127,26 @@ static void write_scs_cone(const ScsCone *k, FILE *fout) {
53
127
  * different to scs_int then it will cast the ints after reading
54
128
  * to be compatible with the SCS data types.
55
129
  */
56
- static size_t read_int(scs_int *dest, size_t file_int_sz, size_t nitems,
57
- FILE *fin) {
130
+ static scs_int read_int(scs_int *dest, size_t file_int_sz, size_t nitems,
131
+ FILE *fin) {
132
+ size_t val;
133
+ size_t i;
134
+ if (nitems == 0) {
135
+ return 0;
136
+ }
58
137
  if (file_int_sz == sizeof(scs_int)) {
59
- return fread(dest, sizeof(scs_int), nitems, fin);
138
+ return checked_fread(dest, sizeof(scs_int), nitems, fin);
60
139
  }
61
140
  void *ptr = scs_calloc(nitems, file_int_sz);
62
- size_t val = fread(ptr, file_int_sz, nitems, fin);
63
- size_t i;
141
+ if (!ptr)
142
+ return -1;
143
+ val = fread(ptr, file_int_sz, nitems, fin);
144
+ if (val != nitems) {
145
+ scs_printf("Error: fread expected %lu integer items, got %lu\n",
146
+ (unsigned long)nitems, (unsigned long)val);
147
+ scs_free(ptr);
148
+ return -1;
149
+ }
64
150
  switch (file_int_sz) {
65
151
  case 4:
66
152
  for (i = 0; i < nitems; ++i) {
@@ -72,152 +158,488 @@ static size_t read_int(scs_int *dest, size_t file_int_sz, size_t nitems,
72
158
  dest[i] = (scs_int)(((long long *)ptr)[i]);
73
159
  }
74
160
  break;
75
- }
76
- if (ptr) {
161
+ default:
162
+ scs_printf("Error: unsupported integer size %lu in data file\n",
163
+ (unsigned long)file_int_sz);
77
164
  scs_free(ptr);
165
+ return -1;
166
+ }
167
+ scs_free(ptr);
168
+ return 0;
169
+ }
170
+
171
+ static scs_int read_int_array(scs_int **dest, scs_int n, size_t file_int_sz,
172
+ FILE *fin) {
173
+ *dest = SCS_NULL;
174
+ if (n < 0) {
175
+ scs_printf("Error: negative array length %li in data file\n", (long)n);
176
+ return -1;
177
+ }
178
+ if (n == 0) {
179
+ return 0;
180
+ }
181
+ *dest = (scs_int *)scs_calloc(n, sizeof(scs_int));
182
+ if (!*dest) {
183
+ return -1;
184
+ }
185
+ if (read_int(*dest, file_int_sz, (size_t)n, fin) < 0) {
186
+ scs_free(*dest);
187
+ *dest = SCS_NULL;
188
+ return -1;
78
189
  }
79
- return val;
190
+ return 0;
191
+ }
192
+
193
+ static scs_int read_float_array(scs_float **dest, scs_int n, FILE *fin) {
194
+ *dest = SCS_NULL;
195
+ if (n < 0) {
196
+ scs_printf("Error: negative array length %li in data file\n", (long)n);
197
+ return -1;
198
+ }
199
+ if (n == 0) {
200
+ return 0;
201
+ }
202
+ *dest = (scs_float *)scs_calloc(n, sizeof(scs_float));
203
+ if (!*dest) {
204
+ return -1;
205
+ }
206
+ if (checked_fread(*dest, sizeof(scs_float), (size_t)n, fin) < 0) {
207
+ scs_free(*dest);
208
+ *dest = SCS_NULL;
209
+ return -1;
210
+ }
211
+ return 0;
212
+ }
213
+
214
+ #ifndef USE_SPECTRAL_CONES
215
+ /* skipping helpers: a non-spectral build must step over spectral data */
216
+ static scs_int skip_bytes(FILE *fin, uint64_t bytes) {
217
+ unsigned char buf[4096];
218
+ while (bytes > 0) {
219
+ size_t chunk = bytes < sizeof(buf) ? (size_t)bytes : sizeof(buf);
220
+ if (checked_fread(buf, 1, chunk, fin) < 0) {
221
+ return -1;
222
+ }
223
+ bytes -= chunk;
224
+ }
225
+ return 0;
226
+ }
227
+
228
+ static scs_int skip_int_array(FILE *fin, size_t file_int_sz, scs_int n) {
229
+ if (n < 0) {
230
+ scs_printf("Error: negative array length %li in data file\n", (long)n);
231
+ return -1;
232
+ }
233
+ return skip_bytes(fin, (uint64_t)n * (uint64_t)file_int_sz);
234
+ }
235
+ #endif
236
+
237
+ static ScsCone *free_cone_null(ScsCone *k) {
238
+ SCS(free_cone)(k);
239
+ return SCS_NULL;
240
+ }
241
+
242
+ static ScsSettings *free_stgs_null(ScsSettings *s) {
243
+ scs_free(s);
244
+ return SCS_NULL;
245
+ }
246
+
247
+ static ScsMatrix *free_matrix_null(ScsMatrix *A) {
248
+ SCS(free_scs_matrix)(A);
249
+ return SCS_NULL;
250
+ }
251
+
252
+ static ScsData *free_data_null(ScsData *d) {
253
+ SCS(free_data)(d);
254
+ return SCS_NULL;
255
+ }
256
+
257
+ static scs_int read_data_cleanup(FILE *fin, ScsData **d, ScsCone **k,
258
+ ScsSettings **stgs) {
259
+ fclose(fin);
260
+ SCS(free_data)(*d);
261
+ SCS(free_cone)(*k);
262
+ scs_free(*stgs);
263
+ *d = SCS_NULL;
264
+ *k = SCS_NULL;
265
+ *stgs = SCS_NULL;
266
+ return -1;
80
267
  }
81
268
 
82
269
  static ScsCone *read_scs_cone(FILE *fin, size_t file_int_sz) {
270
+ scs_int box_len;
83
271
  ScsCone *k = (ScsCone *)scs_calloc(1, sizeof(ScsCone));
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);
87
- if (k->bsize > 1) {
88
- k->bl = (scs_float *)scs_calloc(MAX(k->bsize - 1, 0), sizeof(scs_float));
89
- k->bu = (scs_float *)scs_calloc(MAX(k->bsize - 1, 0), sizeof(scs_float));
90
- fread(k->bl, sizeof(scs_float), MAX(k->bsize - 1, 0), fin);
91
- fread(k->bu, sizeof(scs_float), MAX(k->bsize - 1, 0), fin);
92
- }
93
- read_int(&(k->qsize), file_int_sz, 1, fin);
94
- if (k->qsize) {
95
- k->q = (scs_int *)scs_calloc(k->qsize, sizeof(scs_int));
96
- read_int(k->q, file_int_sz, k->qsize, fin);
97
- }
98
- read_int(&(k->ssize), file_int_sz, 1, fin);
99
- if (k->ssize) {
100
- k->s = (scs_int *)scs_calloc(k->ssize, sizeof(scs_int));
101
- read_int(k->s, file_int_sz, k->ssize, fin);
102
- }
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);
106
- if (k->psize) {
107
- k->p = (scs_float *)scs_calloc(k->psize, sizeof(scs_float));
108
- fread(k->p, sizeof(scs_float), k->psize, fin);
272
+ if (!k)
273
+ return SCS_NULL;
274
+ if (read_int(&(k->z), file_int_sz, 1, fin) < 0 ||
275
+ read_int(&(k->l), file_int_sz, 1, fin) < 0 ||
276
+ read_int(&(k->bsize), file_int_sz, 1, fin) < 0) {
277
+ return free_cone_null(k);
278
+ }
279
+ if (k->bsize < 0) {
280
+ scs_printf("Error: negative box cone size in data file\n");
281
+ return free_cone_null(k);
282
+ }
283
+ box_len = MAX(k->bsize - 1, 0);
284
+ if (read_float_array(&(k->bl), box_len, fin) < 0 ||
285
+ read_float_array(&(k->bu), box_len, fin) < 0 ||
286
+ read_int(&(k->qsize), file_int_sz, 1, fin) < 0 ||
287
+ read_int_array(&(k->q), k->qsize, file_int_sz, fin) < 0 ||
288
+ read_int(&(k->ssize), file_int_sz, 1, fin) < 0 ||
289
+ read_int_array(&(k->s), k->ssize, file_int_sz, fin) < 0 ||
290
+ read_int(&(k->ep), file_int_sz, 1, fin) < 0 ||
291
+ read_int(&(k->ed), file_int_sz, 1, fin) < 0 ||
292
+ read_int(&(k->psize), file_int_sz, 1, fin) < 0 ||
293
+ read_float_array(&(k->p), k->psize, fin) < 0) {
294
+ return free_cone_null(k);
109
295
  }
110
296
  return k;
111
297
  }
112
298
 
113
- static void write_scs_stgs(const ScsSettings *s, FILE *fout) {
299
+ static scs_int write_scs_stgs(const ScsSettings *s, FILE *fout) {
114
300
  /* Warm start to false for now */
115
301
  scs_int warm_start = 0;
116
- fwrite(&(s->normalize), sizeof(scs_int), 1, fout);
117
- fwrite(&(s->scale), sizeof(scs_float), 1, fout);
118
- fwrite(&(s->rho_x), sizeof(scs_float), 1, fout);
119
- fwrite(&(s->max_iters), sizeof(scs_int), 1, fout);
120
- fwrite(&(s->eps_abs), sizeof(scs_float), 1, fout);
121
- fwrite(&(s->eps_rel), sizeof(scs_float), 1, fout);
122
- fwrite(&(s->eps_infeas), sizeof(scs_float), 1, fout);
123
- fwrite(&(s->alpha), sizeof(scs_float), 1, fout);
124
- fwrite(&(s->verbose), sizeof(scs_int), 1, fout);
125
- fwrite(&warm_start, sizeof(scs_int), 1, fout);
126
- fwrite(&(s->acceleration_lookback), sizeof(scs_int), 1, fout);
127
- fwrite(&(s->acceleration_interval), sizeof(scs_int), 1, fout);
128
- fwrite(&(s->adaptive_scale), sizeof(scs_int), 1, fout);
302
+ if (checked_fwrite(&(s->normalize), sizeof(scs_int), 1, fout) < 0 ||
303
+ checked_fwrite(&(s->scale), sizeof(scs_float), 1, fout) < 0 ||
304
+ checked_fwrite(&(s->rho_x), sizeof(scs_float), 1, fout) < 0 ||
305
+ checked_fwrite(&(s->max_iters), sizeof(scs_int), 1, fout) < 0 ||
306
+ checked_fwrite(&(s->eps_abs), sizeof(scs_float), 1, fout) < 0 ||
307
+ checked_fwrite(&(s->eps_rel), sizeof(scs_float), 1, fout) < 0 ||
308
+ checked_fwrite(&(s->eps_infeas), sizeof(scs_float), 1, fout) < 0 ||
309
+ checked_fwrite(&(s->alpha), sizeof(scs_float), 1, fout) < 0 ||
310
+ checked_fwrite(&(s->verbose), sizeof(scs_int), 1, fout) < 0 ||
311
+ checked_fwrite(&warm_start, sizeof(scs_int), 1, fout) < 0 ||
312
+ checked_fwrite(&(s->acceleration_lookback), sizeof(scs_int), 1, fout) <
313
+ 0 ||
314
+ checked_fwrite(&(s->acceleration_interval), sizeof(scs_int), 1, fout) <
315
+ 0 ||
316
+ checked_fwrite(&(s->acceleration_type_1), sizeof(scs_int), 1, fout) <
317
+ 0 ||
318
+ checked_fwrite(&(s->acceleration_regularization), sizeof(scs_float), 1,
319
+ fout) < 0 ||
320
+ checked_fwrite(&(s->acceleration_relaxation), sizeof(scs_float), 1,
321
+ fout) < 0 ||
322
+ checked_fwrite(&(s->adaptive_scale), sizeof(scs_int), 1, fout) < 0) {
323
+ return -1;
324
+ }
129
325
  /* Do not write the write_data_filename */
130
326
  /* Do not write the log_csv_filename */
327
+ return 0;
328
+ }
329
+
330
+ /* Return 1 if `ver` (e.g. "3.2.11") sorts before 3.3.0, using the
331
+ * numeric major/minor prefix. Unparseable strings are treated as old
332
+ * (the conservative choice: the legacy layout reads fewer bytes). */
333
+ static scs_int rw_version_before_330(const char *ver) {
334
+ long major, minor;
335
+ char *end;
336
+ major = strtol(ver, &end, 10);
337
+ if (end == ver || *end != '.') {
338
+ return 1;
339
+ }
340
+ minor = strtol(end + 1, &end, 10);
341
+ return (major < 3) || (major == 3 && minor < 3);
131
342
  }
132
343
 
133
- static ScsSettings *read_scs_stgs(FILE *fin, size_t file_int_sz) {
344
+ static ScsSettings *read_scs_stgs(FILE *fin, size_t file_int_sz,
345
+ scs_int legacy_settings) {
134
346
  ScsSettings *s = (ScsSettings *)scs_calloc(1, sizeof(ScsSettings));
135
- read_int(&(s->normalize), file_int_sz, 1, fin);
136
- fread(&(s->scale), sizeof(scs_float), 1, fin);
137
- fread(&(s->rho_x), sizeof(scs_float), 1, fin);
138
- read_int(&(s->max_iters), file_int_sz, 1, fin);
139
- fread(&(s->eps_abs), sizeof(scs_float), 1, fin);
140
- fread(&(s->eps_rel), sizeof(scs_float), 1, fin);
141
- fread(&(s->eps_infeas), sizeof(scs_float), 1, fin);
142
- fread(&(s->alpha), sizeof(scs_float), 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);
347
+ if (!s)
348
+ return SCS_NULL;
349
+ scs_set_default_settings(s);
350
+ if (read_int(&(s->normalize), file_int_sz, 1, fin) < 0 ||
351
+ checked_fread(&(s->scale), sizeof(scs_float), 1, fin) < 0 ||
352
+ checked_fread(&(s->rho_x), sizeof(scs_float), 1, fin) < 0 ||
353
+ read_int(&(s->max_iters), file_int_sz, 1, fin) < 0 ||
354
+ checked_fread(&(s->eps_abs), sizeof(scs_float), 1, fin) < 0 ||
355
+ checked_fread(&(s->eps_rel), sizeof(scs_float), 1, fin) < 0 ||
356
+ checked_fread(&(s->eps_infeas), sizeof(scs_float), 1, fin) < 0 ||
357
+ checked_fread(&(s->alpha), sizeof(scs_float), 1, fin) < 0 ||
358
+ read_int(&(s->verbose), file_int_sz, 1, fin) < 0 ||
359
+ read_int(&(s->warm_start), file_int_sz, 1, fin) < 0 ||
360
+ read_int(&(s->acceleration_lookback), file_int_sz, 1, fin) < 0 ||
361
+ read_int(&(s->acceleration_interval), file_int_sz, 1, fin) < 0) {
362
+ return free_stgs_null(s);
363
+ }
364
+ if (legacy_settings) {
365
+ if (read_int(&(s->adaptive_scale), file_int_sz, 1, fin) < 0) {
366
+ return free_stgs_null(s);
367
+ }
368
+ } else if (read_int(&(s->acceleration_type_1), file_int_sz, 1, fin) < 0 ||
369
+ checked_fread(&(s->acceleration_regularization),
370
+ sizeof(scs_float), 1, fin) < 0 ||
371
+ checked_fread(&(s->acceleration_relaxation), sizeof(scs_float), 1,
372
+ fin) < 0 ||
373
+ read_int(&(s->adaptive_scale), file_int_sz, 1, fin) < 0) {
374
+ return free_stgs_null(s);
375
+ }
148
376
  return s;
149
377
  }
150
378
 
151
- static void write_amatrix(const ScsMatrix *A, FILE *fout) {
379
+ static scs_int write_amatrix(const ScsMatrix *A, FILE *fout) {
152
380
  scs_int Anz = A->p[A->n];
153
- fwrite(&(A->m), sizeof(scs_int), 1, fout);
154
- fwrite(&(A->n), sizeof(scs_int), 1, fout);
155
- fwrite(A->p, sizeof(scs_int), A->n + 1, fout);
156
- fwrite(A->x, sizeof(scs_float), Anz, fout);
157
- fwrite(A->i, sizeof(scs_int), Anz, fout);
381
+ if (Anz < 0) {
382
+ scs_printf("Error: matrix has negative nonzero count %li\n", (long)Anz);
383
+ return -1;
384
+ }
385
+ if (checked_fwrite(&(A->m), sizeof(scs_int), 1, fout) < 0 ||
386
+ checked_fwrite(&(A->n), sizeof(scs_int), 1, fout) < 0 ||
387
+ write_int_array(A->p, A->n + 1, fout) < 0 ||
388
+ write_float_array(A->x, Anz, fout) < 0 ||
389
+ write_int_array(A->i, Anz, fout) < 0) {
390
+ return -1;
391
+ }
392
+ return 0;
158
393
  }
159
394
 
160
395
  static ScsMatrix *read_amatrix(FILE *fin, size_t file_int_sz) {
161
396
  scs_int Anz;
162
397
  ScsMatrix *A = (ScsMatrix *)scs_calloc(1, sizeof(ScsMatrix));
163
- read_int(&(A->m), file_int_sz, 1, fin);
164
- read_int(&(A->n), file_int_sz, 1, fin);
398
+ if (!A)
399
+ return SCS_NULL;
400
+ if (read_int(&(A->m), file_int_sz, 1, fin) < 0 ||
401
+ read_int(&(A->n), file_int_sz, 1, fin) < 0) {
402
+ return free_matrix_null(A);
403
+ }
404
+ if (A->m < 0 || A->n < 0) {
405
+ scs_printf("Error: negative matrix dimensions in data file\n");
406
+ return free_matrix_null(A);
407
+ }
165
408
  A->p = (scs_int *)scs_calloc(A->n + 1, sizeof(scs_int));
166
- read_int(A->p, file_int_sz, A->n + 1, fin);
409
+ if (!A->p || read_int(A->p, file_int_sz, A->n + 1, fin) < 0) {
410
+ return free_matrix_null(A);
411
+ }
167
412
  Anz = A->p[A->n];
413
+ if (Anz < 0) {
414
+ scs_printf("Error: negative matrix nonzero count in data file\n");
415
+ return free_matrix_null(A);
416
+ }
168
417
  A->x = (scs_float *)scs_calloc(Anz, sizeof(scs_float));
169
418
  A->i = (scs_int *)scs_calloc(Anz, sizeof(scs_int));
170
- fread(A->x, sizeof(scs_float), Anz, fin);
171
- read_int(A->i, file_int_sz, Anz, fin);
419
+ if (!A->x || !A->i ||
420
+ checked_fread(A->x, sizeof(scs_float), Anz, fin) < 0 ||
421
+ read_int(A->i, file_int_sz, Anz, fin) < 0) {
422
+ return free_matrix_null(A);
423
+ }
172
424
  return A;
173
425
  }
174
426
 
175
- static void write_scs_data(const ScsData *d, FILE *fout) {
427
+ static scs_int write_scs_data(const ScsData *d, FILE *fout) {
176
428
  scs_int has_p = d->P ? 1 : 0;
177
- fwrite(&(d->m), sizeof(scs_int), 1, fout);
178
- fwrite(&(d->n), sizeof(scs_int), 1, fout);
179
- fwrite(d->b, sizeof(scs_float), d->m, fout);
180
- fwrite(d->c, sizeof(scs_float), d->n, fout);
181
- write_amatrix(d->A, fout);
429
+ if (checked_fwrite(&(d->m), sizeof(scs_int), 1, fout) < 0 ||
430
+ checked_fwrite(&(d->n), sizeof(scs_int), 1, fout) < 0 ||
431
+ write_float_array(d->b, d->m, fout) < 0 ||
432
+ write_float_array(d->c, d->n, fout) < 0 ||
433
+ write_amatrix(d->A, fout) < 0) {
434
+ return -1;
435
+ }
182
436
  /* write has P bit */
183
- fwrite(&has_p, sizeof(scs_int), 1, fout);
437
+ if (checked_fwrite(&has_p, sizeof(scs_int), 1, fout) < 0) {
438
+ return -1;
439
+ }
184
440
  if (d->P) {
185
- write_amatrix(d->P, fout);
441
+ return write_amatrix(d->P, fout);
186
442
  }
443
+ return 0;
187
444
  }
188
445
 
189
446
  static ScsData *read_scs_data(FILE *fin, size_t file_int_sz) {
190
447
  scs_int has_p = 0;
191
448
  ScsData *d = (ScsData *)scs_calloc(1, sizeof(ScsData));
192
-
193
- read_int(&(d->m), file_int_sz, 1, fin);
194
- read_int(&(d->n), file_int_sz, 1, fin);
449
+ if (!d)
450
+ return SCS_NULL;
451
+ if (read_int(&(d->m), file_int_sz, 1, fin) < 0 ||
452
+ read_int(&(d->n), file_int_sz, 1, fin) < 0) {
453
+ return free_data_null(d);
454
+ }
455
+ if (d->m < 0 || d->n < 0) {
456
+ scs_printf("Error: negative problem dimensions in data file\n");
457
+ return free_data_null(d);
458
+ }
195
459
  d->b = (scs_float *)scs_calloc(d->m, sizeof(scs_float));
196
460
  d->c = (scs_float *)scs_calloc(d->n, sizeof(scs_float));
197
- fread(d->b, sizeof(scs_float), d->m, fin);
198
- fread(d->c, sizeof(scs_float), d->n, fin);
461
+ if (!d->b || !d->c ||
462
+ checked_fread(d->b, sizeof(scs_float), d->m, fin) < 0 ||
463
+ checked_fread(d->c, sizeof(scs_float), d->n, fin) < 0) {
464
+ return free_data_null(d);
465
+ }
199
466
  d->A = read_amatrix(fin, file_int_sz);
467
+ if (!d->A) {
468
+ return free_data_null(d);
469
+ }
200
470
  /* If has_p bit is not set or this hits end of file then has_p = 0 */
201
- has_p &= read_int(&has_p, file_int_sz, 1, fin);
471
+ if (read_int(&has_p, file_int_sz, 1, fin) < 0) {
472
+ return free_data_null(d);
473
+ }
202
474
  d->P = has_p ? read_amatrix(fin, file_int_sz) : SCS_NULL;
475
+ if (has_p && !d->P) {
476
+ return free_data_null(d);
477
+ }
203
478
  return d;
204
479
  }
205
480
 
481
+ static scs_int write_ext_int_array(const scs_int *x, scs_int n, FILE *fout) {
482
+ if (checked_fwrite(&n, sizeof(scs_int), 1, fout) < 0) {
483
+ return -1;
484
+ }
485
+ return write_int_array(x, n, fout);
486
+ }
487
+
488
+ static scs_int write_scs_extensions(const ScsCone *k, const ScsSettings *s,
489
+ FILE *fout) {
490
+ #ifndef USE_SPECTRAL_CONES
491
+ scs_int zero = 0;
492
+ #endif
493
+ uint32_t magic = RW_EXT_MAGIC;
494
+ uint32_t version = RW_EXT_VERSION;
495
+ if (checked_fwrite(&magic, sizeof(uint32_t), 1, fout) < 0 ||
496
+ checked_fwrite(&version, sizeof(uint32_t), 1, fout) < 0 ||
497
+ write_ext_int_array(k->cs, k->cssize, fout) < 0) {
498
+ return -1;
499
+ }
500
+ #ifdef USE_SPECTRAL_CONES
501
+ if (write_ext_int_array(k->d, k->dsize, fout) < 0 ||
502
+ checked_fwrite(&(k->nucsize), sizeof(scs_int), 1, fout) < 0 ||
503
+ write_int_array(k->nuc_m, k->nucsize, fout) < 0 ||
504
+ write_int_array(k->nuc_n, k->nucsize, fout) < 0 ||
505
+ write_ext_int_array(k->ell1, k->ell1_size, fout) < 0 ||
506
+ checked_fwrite(&(k->sl_size), sizeof(scs_int), 1, fout) < 0 ||
507
+ write_int_array(k->sl_n, k->sl_size, fout) < 0 ||
508
+ write_int_array(k->sl_k, k->sl_size, fout) < 0) {
509
+ return -1;
510
+ }
511
+ #else
512
+ if (write_ext_int_array(SCS_NULL, zero, fout) < 0 ||
513
+ checked_fwrite(&zero, sizeof(scs_int), 1, fout) < 0 ||
514
+ write_int_array(SCS_NULL, zero, fout) < 0 ||
515
+ write_int_array(SCS_NULL, zero, fout) < 0 ||
516
+ write_ext_int_array(SCS_NULL, zero, fout) < 0 ||
517
+ checked_fwrite(&zero, sizeof(scs_int), 1, fout) < 0 ||
518
+ write_int_array(SCS_NULL, zero, fout) < 0 ||
519
+ write_int_array(SCS_NULL, zero, fout) < 0) {
520
+ return -1;
521
+ }
522
+ #endif
523
+ if (checked_fwrite(&(s->time_limit_secs), sizeof(scs_float), 1, fout) < 0) {
524
+ return -1;
525
+ }
526
+ /* v2 fields */
527
+ return checked_fwrite(&(s->adaptive_diag_scale), sizeof(scs_int), 1, fout);
528
+ }
529
+
530
+ static scs_int read_ext_int_array(scs_int **dest, scs_int *n,
531
+ size_t file_int_sz, FILE *fin) {
532
+ if (read_int(n, file_int_sz, 1, fin) < 0) {
533
+ return -1;
534
+ }
535
+ return read_int_array(dest, *n, file_int_sz, fin);
536
+ }
537
+
538
+ static scs_int read_scs_extensions(FILE *fin, size_t file_int_sz, ScsCone *k,
539
+ ScsSettings *s) {
540
+ unsigned char magic_buf[sizeof(uint32_t)];
541
+ uint32_t magic, version;
542
+ scs_int dsize, nucsize, sl_size;
543
+ #ifndef USE_SPECTRAL_CONES
544
+ scs_int ell1_size; /* only the skipping path needs it */
545
+ #endif
546
+ size_t ret = fread(magic_buf, 1, sizeof(magic_buf), fin);
547
+ if (ret == 0 && feof(fin)) {
548
+ return 0;
549
+ }
550
+ if (ret != sizeof(magic_buf)) {
551
+ scs_printf("Error: incomplete read/write extension header\n");
552
+ return -1;
553
+ }
554
+ memcpy(&magic, magic_buf, sizeof(magic));
555
+ if (magic != RW_EXT_MAGIC) {
556
+ scs_printf("Warning: ignoring unrecognized trailing data in SCS file\n");
557
+ return 0;
558
+ }
559
+ if (checked_fread(&version, sizeof(uint32_t), 1, fin) < 0) {
560
+ return -1;
561
+ }
562
+ if (version > RW_EXT_VERSION) {
563
+ scs_printf("Error: SCS file uses read/write schema version %lu, this "
564
+ "build supports up to %lu\n",
565
+ (unsigned long)version, (unsigned long)RW_EXT_VERSION);
566
+ return -1;
567
+ }
568
+ if (read_ext_int_array(&(k->cs), &(k->cssize), file_int_sz, fin) < 0 ||
569
+ read_int(&dsize, file_int_sz, 1, fin) < 0) {
570
+ return -1;
571
+ }
572
+ #ifdef USE_SPECTRAL_CONES
573
+ k->dsize = dsize;
574
+ if (read_int_array(&(k->d), k->dsize, file_int_sz, fin) < 0 ||
575
+ read_int(&nucsize, file_int_sz, 1, fin) < 0) {
576
+ return -1;
577
+ }
578
+ k->nucsize = nucsize;
579
+ if (read_int_array(&(k->nuc_m), k->nucsize, file_int_sz, fin) < 0 ||
580
+ read_int_array(&(k->nuc_n), k->nucsize, file_int_sz, fin) < 0 ||
581
+ read_ext_int_array(&(k->ell1), &(k->ell1_size), file_int_sz, fin) < 0 ||
582
+ read_int(&sl_size, file_int_sz, 1, fin) < 0) {
583
+ return -1;
584
+ }
585
+ k->sl_size = sl_size;
586
+ if (read_int_array(&(k->sl_n), k->sl_size, file_int_sz, fin) < 0 ||
587
+ read_int_array(&(k->sl_k), k->sl_size, file_int_sz, fin) < 0) {
588
+ return -1;
589
+ }
590
+ #else
591
+ if (skip_int_array(fin, file_int_sz, dsize) < 0 ||
592
+ read_int(&nucsize, file_int_sz, 1, fin) < 0 ||
593
+ skip_int_array(fin, file_int_sz, nucsize) < 0 ||
594
+ skip_int_array(fin, file_int_sz, nucsize) < 0 ||
595
+ read_int(&ell1_size, file_int_sz, 1, fin) < 0 ||
596
+ skip_int_array(fin, file_int_sz, ell1_size) < 0 ||
597
+ read_int(&sl_size, file_int_sz, 1, fin) < 0 ||
598
+ skip_int_array(fin, file_int_sz, sl_size) < 0 ||
599
+ skip_int_array(fin, file_int_sz, sl_size) < 0) {
600
+ return -1;
601
+ }
602
+ #endif
603
+ if (checked_fread(&(s->time_limit_secs), sizeof(scs_float), 1, fin) < 0) {
604
+ return -1;
605
+ }
606
+ if (version >= 2) {
607
+ if (read_int(&(s->adaptive_diag_scale), file_int_sz, 1, fin) < 0) {
608
+ return -1;
609
+ }
610
+ } /* else: scs_set_default_settings value stands */
611
+ return 0;
612
+ }
613
+
206
614
  void SCS(write_data)(const ScsData *d, const ScsCone *k,
207
615
  const ScsSettings *stgs) {
208
616
  FILE *fout = fopen(stgs->write_data_filename, "wb");
617
+ scs_int status = 0;
618
+ if (!fout) {
619
+ scs_printf("Error: could not open %s for writing\n",
620
+ stgs->write_data_filename);
621
+ return;
622
+ }
209
623
  uint32_t scs_int_sz = (uint32_t)sizeof(scs_int);
210
624
  uint32_t scs_float_sz = (uint32_t)sizeof(scs_float);
211
625
  const char *scs_version = SCS_VERSION;
212
626
  uint32_t scs_version_sz = (uint32_t)strlen(scs_version);
213
- fwrite(&(scs_int_sz), sizeof(uint32_t), 1, fout);
214
- fwrite(&(scs_float_sz), sizeof(uint32_t), 1, fout);
215
- fwrite(&(scs_version_sz), sizeof(uint32_t), 1, fout);
216
- fwrite(scs_version, 1, scs_version_sz, fout);
217
- write_scs_cone(k, fout);
218
- write_scs_data(d, fout);
219
- write_scs_stgs(stgs, fout);
220
- fclose(fout);
627
+ if (checked_fwrite(&(scs_int_sz), sizeof(uint32_t), 1, fout) < 0 ||
628
+ checked_fwrite(&(scs_float_sz), sizeof(uint32_t), 1, fout) < 0 ||
629
+ checked_fwrite(&(scs_version_sz), sizeof(uint32_t), 1, fout) < 0 ||
630
+ checked_fwrite(scs_version, 1, scs_version_sz, fout) < 0 ||
631
+ write_scs_cone(k, fout) < 0 || write_scs_data(d, fout) < 0 ||
632
+ write_scs_stgs(stgs, fout) < 0 ||
633
+ write_scs_extensions(k, stgs, fout) < 0) {
634
+ status = -1;
635
+ }
636
+ if (fclose(fout) != 0) {
637
+ status = -1;
638
+ }
639
+ if (status < 0) {
640
+ scs_printf("Error: failed writing SCS data to %s\n",
641
+ stgs->write_data_filename);
642
+ }
221
643
  }
222
644
 
223
645
  scs_int SCS(read_data)(const char *filename, ScsData **d, ScsCone **k,
@@ -226,16 +648,27 @@ scs_int SCS(read_data)(const char *filename, ScsData **d, ScsCone **k,
226
648
  uint32_t file_float_sz;
227
649
  uint32_t file_version_sz;
228
650
  char file_version[16];
651
+ scs_int legacy_settings;
229
652
  errno = 0;
230
653
  FILE *fin = fopen(filename, "rb");
654
+ *d = SCS_NULL;
655
+ *k = SCS_NULL;
656
+ *stgs = SCS_NULL;
231
657
  if (!fin) {
232
658
  scs_printf("Error reading file %s\n", filename);
233
659
  scs_printf("errno:%i:%s\n", errno, strerror(errno));
234
660
  return -1;
235
661
  }
236
662
  scs_printf("Reading data from %s\n", filename);
237
- fread(&(file_int_sz), sizeof(uint32_t), 1, fin);
238
- fread(&(file_float_sz), sizeof(uint32_t), 1, fin);
663
+ if (checked_fread(&(file_int_sz), sizeof(uint32_t), 1, fin) < 0 ||
664
+ checked_fread(&(file_float_sz), sizeof(uint32_t), 1, fin) < 0) {
665
+ return read_data_cleanup(fin, d, k, stgs);
666
+ }
667
+ if (file_int_sz != 4 && file_int_sz != 8) {
668
+ scs_printf("Error: unsupported file integer size %lu\n",
669
+ (unsigned long)file_int_sz);
670
+ return read_data_cleanup(fin, d, k, stgs);
671
+ }
239
672
  if (file_int_sz != (uint32_t)sizeof(scs_int)) {
240
673
  scs_printf(
241
674
  "Warning, sizeof(file int) is %lu, but scs expects sizeof(int) %lu. "
@@ -248,12 +681,23 @@ scs_int SCS(read_data)(const char *filename, ScsData **d, ScsCone **k,
248
681
  "Error, sizeof(file float) is %lu, but scs expects sizeof(float) %lu, "
249
682
  "scs should be recompiled with the correct flags.\n",
250
683
  (unsigned long)file_float_sz, (unsigned long)sizeof(scs_float));
251
- fclose(fin);
252
- return -1;
684
+ return read_data_cleanup(fin, d, k, stgs);
685
+ }
686
+ if (checked_fread(&(file_version_sz), sizeof(uint32_t), 1, fin) < 0) {
687
+ return read_data_cleanup(fin, d, k, stgs);
688
+ }
689
+ if (file_version_sz >= sizeof(file_version)) {
690
+ scs_printf("Error: file version string length %lu exceeds buffer size\n",
691
+ (unsigned long)file_version_sz);
692
+ return read_data_cleanup(fin, d, k, stgs);
693
+ }
694
+ if (checked_fread(file_version, 1, file_version_sz, fin) < 0) {
695
+ return read_data_cleanup(fin, d, k, stgs);
253
696
  }
254
- fread(&(file_version_sz), sizeof(uint32_t), 1, fin);
255
- fread(file_version, 1, file_version_sz, fin);
256
697
  file_version[file_version_sz] = '\0';
698
+ /* the settings-block layout changed in 3.3.0; key it off major.minor so
699
+ * files from other 3.3.x builds parse */
700
+ legacy_settings = rw_version_before_330(file_version);
257
701
  if (strcmp(file_version, SCS_VERSION) != 0) {
258
702
  scs_printf("************************************************************\n"
259
703
  "Warning: SCS file version %s, this is SCS version %s.\n"
@@ -262,25 +706,54 @@ scs_int SCS(read_data)(const char *filename, ScsData **d, ScsCone **k,
262
706
  file_version, SCS_VERSION);
263
707
  }
264
708
  *k = read_scs_cone(fin, file_int_sz);
709
+ if (!*k) {
710
+ return read_data_cleanup(fin, d, k, stgs);
711
+ }
265
712
  *d = read_scs_data(fin, file_int_sz);
266
- *stgs = read_scs_stgs(fin, file_int_sz);
713
+ if (!*d) {
714
+ return read_data_cleanup(fin, d, k, stgs);
715
+ }
716
+ *stgs = read_scs_stgs(fin, file_int_sz, legacy_settings);
717
+ if (!*stgs) {
718
+ return read_data_cleanup(fin, d, k, stgs);
719
+ }
720
+ if (read_scs_extensions(fin, file_int_sz, *k, *stgs) < 0) {
721
+ return read_data_cleanup(fin, d, k, stgs);
722
+ }
267
723
  scs_printf("Finished reading data.\n");
268
724
  fclose(fin);
269
725
  return 0;
270
726
  }
271
727
 
272
- void SCS(log_data_to_csv)(const ScsCone *k, const ScsSettings *stgs,
273
- const ScsWork *w, scs_int iter,
728
+ scs_int SCS(open_csv_log_file)(ScsWork *w) {
729
+ if (!w || !w->stgs || !w->stgs->log_csv_filename) {
730
+ return 0;
731
+ }
732
+ SCS(close_csv_log_file)(w);
733
+ w->log_csv_fout = fopen(w->stgs->log_csv_filename, "w");
734
+ if (!w->log_csv_fout) {
735
+ scs_printf("Error: Could not open %s for writing\n",
736
+ w->stgs->log_csv_filename);
737
+ return -1;
738
+ }
739
+ return 0;
740
+ }
741
+
742
+ void SCS(close_csv_log_file)(ScsWork *w) {
743
+ if (w && w->log_csv_fout) {
744
+ fclose(w->log_csv_fout);
745
+ w->log_csv_fout = SCS_NULL;
746
+ }
747
+ }
748
+
749
+ void SCS(log_data_to_csv)(const ScsCone *k, const ScsWork *w, scs_int iter,
274
750
  SCS(timer) * solve_timer) {
275
751
  ScsResiduals *r = w->r_orig;
276
752
  ScsResiduals *r_n = w->r_normalized;
277
753
  ScsSolution *sol = w->xys_orig;
278
754
  ScsSolution *sol_n = w->xys_normalized;
279
- /* if iter 0 open to write, else open to append */
280
- FILE *fout = fopen(stgs->log_csv_filename, iter == 0 ? "w" : "a");
755
+ FILE *fout = w->log_csv_fout;
281
756
  if (!fout) {
282
- scs_printf("Error: Could not open %s for writing\n",
283
- stgs->log_csv_filename);
284
757
  return;
285
758
  }
286
759
  scs_int l = w->d->m + w->d->n + 1;
@@ -427,7 +900,6 @@ void SCS(log_data_to_csv)(const ScsCone *k, const ScsSettings *stgs,
427
900
  fprintf(fout, "%.16e,", w->cone_work->newton_stats.residuals[2]);
428
901
  #endif
429
902
  fprintf(fout, "\n");
430
- fclose(fout);
431
903
  }
432
904
 
433
905
  #endif