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
@@ -1,10 +1,10 @@
1
1
  #include "cones.h"
2
- // #include "scs.h"
2
+ /* #include "scs.h" */
3
3
  #include "linalg.h"
4
4
  #include "scs_blas.h"
5
5
  #include "scs_types.h"
6
6
  #include "util_spectral_cones.h"
7
- #include <stdlib.h> // qsort
7
+ #include <stdlib.h> /* qsort */
8
8
 
9
9
  #define TOL_LARGEST_CONE 1e-9
10
10
 
@@ -30,7 +30,8 @@ static void compute_cone_residuals(scs_float t, const scs_float *x,
30
30
  #endif
31
31
 
32
32
  scs_int assert_sorted(scs_float *x, scs_int n) {
33
- for (scs_int i = 0; i < n - 1; ++i) {
33
+ scs_int i;
34
+ for (i = 0; i < n - 1; ++i) {
34
35
  if (x[i] < x[i + 1]) {
35
36
  return -1;
36
37
  }
@@ -40,53 +41,64 @@ scs_int assert_sorted(scs_float *x, scs_int n) {
40
41
 
41
42
  scs_int proj_sum_largest_cone_sorted(scs_float *t, scs_float *x, scs_int n,
42
43
  scs_int k) {
44
+ scs_int nu, nt;
45
+ scs_float eta;
46
+ scs_float t0;
47
+ scs_float S;
48
+ scs_float a_u, a_t;
49
+ scs_float ratio, s1, s3, s;
50
+ scs_float val;
51
+ scs_int i;
52
+
43
53
  #ifdef SPECTRAL_DEBUG
44
54
  scs_float t00 = *t;
45
55
  scs_float *x0 = scs_malloc(n * sizeof(*x0));
56
+ scs_int status;
46
57
  memcpy(x0, x, n * sizeof(*x0));
47
- scs_int status = assert_sorted(x, n);
58
+ status = assert_sorted(x, n);
48
59
  if (status < 0) {
49
60
  scs_printf("NOT SORTED! \n");
50
61
  return status;
51
62
  }
52
63
  #endif
53
64
 
54
- // -------------------------------
55
- // Initialize state variables
56
- // -------------------------------
65
+ /* -------------------------------
66
+ * Initialize state variables
67
+ * ------------------------------- */
57
68
  assert(k < n && k > 0);
58
- scs_int nu = k, nt = 0;
59
- scs_float eta = 0.0;
60
- scs_float t0 = *t;
61
- scs_float S = x[0];
62
- for (scs_int i = 1; i < k; ++i) {
69
+ nu = k;
70
+ nt = 0;
71
+ eta = 0.0;
72
+ t0 = *t;
73
+ S = x[0];
74
+ for (i = 1; i < k; ++i) {
63
75
  S += x[i];
64
76
  }
65
77
 
66
- scs_float a_u = x[nu - 1], a_t = x[nu];
78
+ a_u = x[nu - 1];
79
+ a_t = x[nu];
67
80
 
68
- // ---------------------------------
69
- // main loop
70
- // ---------------------------------
71
- scs_float ratio, s1, s3, s;
81
+ /* ---------------------------------
82
+ * main loop
83
+ * --------------------------------- */
72
84
  while (S > *t + TOL_LARGEST_CONE) {
73
85
  ratio = (nu == k) ? 1.0 : (scs_float)(nt) / (k - nu);
74
86
 
75
- // ------------------------------------------------------
76
- // compute step size
77
- // ------------------------------------------------------
87
+ /* ------------------------------------------------------
88
+ * compute step size
89
+ * ------------------------------------------------------ */
78
90
  s1 = (nu == k) ? a_u - a_t : (a_u - a_t) / (ratio - 1);
79
91
  s3 = (S - *t) / (ratio * (nu + 1) + (k - nu));
80
92
  s = (nu == 0) ? s3 : MIN(s3, s1);
81
93
 
82
94
  if (!(nu + nt == n || nt == 0)) {
83
- scs_float val = a_t - x[nu + nt];
95
+ val = a_t - x[nu + nt];
84
96
  s = MIN(s, val);
85
97
  }
86
98
 
87
- // --------------------------
88
- // update state
89
- // --------------------------
99
+ /* --------------------------
100
+ * update state
101
+ * -------------------------- */
90
102
  eta += s * ratio;
91
103
  S -= s * (ratio * nu + k - nu);
92
104
  *t = t0 + eta;
@@ -110,8 +122,7 @@ scs_int proj_sum_largest_cone_sorted(scs_float *t, scs_float *x, scs_int n,
110
122
 
111
123
  nt -= 1;
112
124
 
113
- // update projection
114
- scs_int i;
125
+ /* update projection */
115
126
  for (i = 0; i < nu; ++i) {
116
127
  x[i] -= eta;
117
128
  }
@@ -121,12 +132,14 @@ scs_int proj_sum_largest_cone_sorted(scs_float *t, scs_float *x, scs_int n,
121
132
  }
122
133
 
123
134
  #ifdef SPECTRAL_DEBUG
124
- scs_float residuals[3];
125
- compute_cone_residuals(*t, x, t00, x0, residuals, n, k);
126
- scs_free(x0);
127
- if (residuals[0] > 1e-10 || residuals[1] > 1e-10 ||
128
- fabs(residuals[2]) > 1e-10) {
129
- return -1;
135
+ {
136
+ scs_float residuals[3];
137
+ compute_cone_residuals(*t, x, t00, x0, residuals, n, k);
138
+ scs_free(x0);
139
+ if (residuals[0] > 1e-10 || residuals[1] > 1e-10 ||
140
+ fabs(residuals[2]) > 1e-10) {
141
+ return -1;
142
+ }
130
143
  }
131
144
  #endif
132
145
 
@@ -144,14 +157,15 @@ scs_int cmp_desc(const void *a, const void *b) {
144
157
  }
145
158
 
146
159
  #ifdef SPECTRAL_DEBUG
147
- // this function is not used in production so fine to allocate memory
160
+ /* this function is not used in production so fine to allocate memory */
148
161
  static scs_float sum_largest_val(const scs_float *x, scs_int n, scs_int k) {
149
162
  scs_float *x_temp = scs_malloc(n * sizeof(*x));
163
+ scs_float val = 0.0;
164
+ scs_int i;
150
165
  memcpy(x_temp, x, n * sizeof(*x));
151
166
  qsort(x_temp, n, sizeof(*x_temp), cmp_desc);
152
167
 
153
- scs_float val = 0.0;
154
- for (scs_int i = 0; i < k; ++i) {
168
+ for (i = 0; i < k; ++i) {
155
169
  val += x_temp[i];
156
170
  }
157
171
  scs_free(x_temp);
@@ -165,18 +179,23 @@ static void compute_cone_residuals(scs_float t, const scs_float *x,
165
179
  scs_float lmbda_t = t - t0;
166
180
  scs_float *lmbda_x = scs_malloc(n * sizeof(*x));
167
181
  scs_float sum_lmbda_x = 0.0;
168
- for (scs_int i = 0; i < n; ++i) {
182
+ scs_int i;
183
+ scs_float comp;
184
+ scs_float pri_res;
185
+ scs_float dual_res;
186
+
187
+ for (i = 0; i < n; ++i) {
169
188
  lmbda_x[i] = x[i] - x0[i];
170
189
  sum_lmbda_x += lmbda_x[i];
171
190
  }
172
191
 
173
- scs_float comp = lmbda_t * t + SCS(dot)(lmbda_x, x, n);
174
- scs_float pri_res = sum_largest_val(x, n, k) - t;
192
+ comp = lmbda_t * t + SCS(dot)(lmbda_x, x, n);
193
+ pri_res = sum_largest_val(x, n, k) - t;
175
194
 
176
- scs_float dual_res = fabs(sum_lmbda_x + lmbda_t * k);
195
+ dual_res = fabs(sum_lmbda_x + lmbda_t * k);
177
196
  dual_res *= dual_res;
178
197
 
179
- for (scs_int i = 0; i < n; ++i) {
198
+ for (i = 0; i < n; ++i) {
180
199
  if (lmbda_x[i] > 0) {
181
200
  dual_res += lmbda_x[i] * lmbda_x[i];
182
201
  }
@@ -2,7 +2,9 @@
2
2
  #include "linalg.h"
3
3
  #include "scs_blas.h"
4
4
  #include "scs_types.h"
5
- #include "util.h" // just for timer
5
+ #include "util.h"
6
+
7
+ #include <string.h>
6
8
 
7
9
  /*
8
10
  * Spectral matrix cone projections, from "Projection onto Spectral Matrix
@@ -37,13 +39,14 @@ void BLAS(gemm)(const char *transa, const char *transb, blas_int *m,
37
39
  }
38
40
  #endif
39
41
 
40
- // forward declaration
42
+ /* forward declaration */
41
43
  scs_int proj_sum_largest_cone_sorted(scs_float *t, scs_float *x, scs_int n,
42
44
  scs_int k);
43
45
 
44
46
  void flip(scs_float *x, int n) {
45
47
  scs_float temp;
46
- for (int i = 0; i < n / 2; i++) {
48
+ int i;
49
+ for (i = 0; i < n / 2; i++) {
47
50
  temp = x[i];
48
51
  x[i] = x[n - i - 1];
49
52
  x[n - i - 1] = temp;
@@ -52,19 +55,19 @@ void flip(scs_float *x, int n) {
52
55
 
53
56
  scs_int SCS(proj_sum_largest_evals)(scs_float *tX, scs_int n, scs_int k,
54
57
  ScsConeWork *c) {
55
- // tvX = [t, X], where X represents the lower triangular part of a matrix
56
- // stored in a compact form and off-diagonal elements have been scaled by
57
- // sqrt(2)
58
+ /*
59
+ * tvX = [t, X], where X represents the lower triangular part of a matrix
60
+ * stored in a compact form and off-diagonal elements have been scaled by
61
+ * sqrt(2)
62
+ */
58
63
  scs_float *X = tX + 1;
59
64
 
60
- // ----------------------------------------------------------------------
61
- // compute eigendecomposition
62
- // ----------------------------------------------------------------------
65
+ /* compute eigendecomposition */
63
66
  scs_int i;
64
67
  blas_int nb = (blas_int)n;
65
68
  blas_int nb_plus_one = (blas_int)(n + 1);
66
69
  blas_int one_int = 1;
67
- scs_float sqrt2 = sqrt(2.0);
70
+ scs_float sqrt2 = SQRTF(2.0);
68
71
  scs_float sqrt2_inv = 1.0 / sqrt2;
69
72
  scs_float *Xs = c->Xs;
70
73
  scs_float *e = c->e;
@@ -72,19 +75,26 @@ scs_int SCS(proj_sum_largest_evals)(scs_float *tX, scs_int n, scs_int k,
72
75
  scs_float *work = c->work;
73
76
  blas_int lwork = c->lwork;
74
77
  blas_int info = 0;
78
+ scs_int status;
79
+ char transN;
80
+ char transY;
81
+ scs_float one;
82
+ scs_float zero;
75
83
 
76
- // copy lower triangular matrix into full matrix
84
+ /* copy lower triangular matrix into full matrix */
77
85
  for (i = 0; i < n; ++i) {
78
86
  memcpy(&(Xs[i * (n + 1)]), &(X[i * n - ((i - 1) * i) / 2]),
79
87
  (n - i) * sizeof(scs_float));
80
88
  }
81
89
 
82
- // rescale diags by sqrt(2)
90
+ /* rescale diags by sqrt(2) */
83
91
  BLAS(scal)(&nb, &sqrt2, Xs, &nb_plus_one);
84
92
 
85
- // Eigendecomposition. On exit, the lower triangular part of Xs stores
86
- // the eigenvectors. The vector e stores the eigenvalues in ascending
87
- // order (smallest eigenvalue first) */
93
+ /*
94
+ * Eigendecomposition. On exit, the lower triangular part of Xs stores
95
+ * the eigenvectors. The vector e stores the eigenvalues in ascending
96
+ * order (smallest eigenvalue first)
97
+ */
88
98
  BLAS(syev)("Vectors", "Lower", &nb, Xs, &nb, e, work, &lwork, &info);
89
99
  if (info != 0) {
90
100
  scs_printf("WARN: LAPACK syev error, info = %i\n", (int)info);
@@ -93,15 +103,15 @@ scs_int SCS(proj_sum_largest_evals)(scs_float *tX, scs_int n, scs_int k,
93
103
  }
94
104
  }
95
105
 
96
- // ----------------------------------------------------------------------
97
- // Project onto spectral *vector* cone. Note that e is sqrt(2) times
98
- // the eigenvalue vector we want to project. We therefore multiply
99
- // tvX[0] by sqrt(2).
100
- // ----------------------------------------------------------------------
106
+ /*
107
+ * Project onto spectral *vector* cone. Note that e is sqrt(2) times
108
+ * the eigenvalue vector we want to project. We therefore multiply
109
+ * tvX[0] by sqrt(2).
110
+ */
101
111
  tX[0] *= sqrt2;
102
112
  SPECTRAL_TIMING(SCS(timer) _timer; SCS(tic)(&_timer);)
103
113
  flip(e, n);
104
- scs_int status = proj_sum_largest_cone_sorted(&tX[0], e, n, k);
114
+ status = proj_sum_largest_cone_sorted(&tX[0], e, n, k);
105
115
  flip(e, n);
106
116
  SPECTRAL_TIMING(c->tot_time_vec_cone_proj += SCS(tocq)(&_timer);)
107
117
 
@@ -109,20 +119,18 @@ scs_int SCS(proj_sum_largest_evals)(scs_float *tX, scs_int n, scs_int k,
109
119
  return status;
110
120
  }
111
121
 
112
- // ----------------------------------------------------------------------
113
- // recover projection onto spectral *matrix* cone
114
- // ----------------------------------------------------------------------
122
+ /* recover projection onto spectral *matrix* cone */
115
123
  memcpy(c->work_sum_of_largest, Xs, n * n * sizeof(*Xs));
116
124
  for (i = 0; i < n; ++i) {
117
125
  BLAS(scal)(&nb, &e[i], &Xs[i * n], &one_int);
118
126
  }
119
127
 
120
- char transN = 'N';
121
- char transY = 'T';
122
- scs_float one = 1.0;
123
- scs_float zero = 0.0;
128
+ transN = 'N';
129
+ transY = 'T';
130
+ one = 1.0;
131
+ zero = 0.0;
124
132
 
125
- // it is not safe to have overlapping matrices for dgemm_.
133
+ /* it is not safe to have overlapping matrices for dgemm_. */
126
134
  BLAS(gemm)(&transN, &transY, &nb, &nb, &nb, &one, Xs, &nb,
127
135
  c->work_sum_of_largest, &nb, &zero, Z, &nb);
128
136
 
@@ -1,7 +1,8 @@
1
1
  #include "util_spectral_cones.h"
2
2
 
3
3
  bool is_pos(const scs_float *x, scs_int n) {
4
- for (scs_int i = 0; i < n; ++i) {
4
+ scs_int i;
5
+ for (i = 0; i < n; ++i) {
5
6
  if (x[i] <= 0.0) {
6
7
  return false;
7
8
  }
@@ -10,7 +11,8 @@ bool is_pos(const scs_float *x, scs_int n) {
10
11
  }
11
12
 
12
13
  bool is_negative(const scs_float *x, scs_int n) {
13
- for (scs_int i = 0; i < n; ++i) {
14
+ scs_int i;
15
+ for (i = 0; i < n; ++i) {
14
16
  if (x[i] >= 0.0) {
15
17
  return false;
16
18
  }
@@ -19,13 +21,15 @@ bool is_negative(const scs_float *x, scs_int n) {
19
21
  }
20
22
 
21
23
  void non_neg_proj(const scs_float *src, scs_float *dst, scs_int n) {
22
- for (scs_int i = 0; i < n; ++i) {
24
+ scs_int i;
25
+ for (i = 0; i < n; ++i) {
23
26
  dst[i] = (src[i] > 0.0) ? src[i] : 0.0;
24
27
  }
25
28
  }
26
29
 
27
30
  void print_vector(const scs_float *x, scs_int n) {
28
- for (scs_int i = 0; i < n; ++i) {
31
+ scs_int i;
32
+ for (i = 0; i < n; ++i) {
29
33
  printf("%f ", x[i]);
30
34
  }
31
35
  printf("\n");
@@ -33,8 +37,9 @@ void print_vector(const scs_float *x, scs_int n) {
33
37
 
34
38
  scs_float min_vec(const scs_float *vec, scs_int n) {
35
39
  scs_float minVal = vec[0];
40
+ scs_int i;
36
41
 
37
- for (scs_int i = 1; i < n; ++i) {
42
+ for (i = 1; i < n; ++i) {
38
43
  if (vec[i] < minVal) {
39
44
  minVal = vec[i];
40
45
  }
@@ -45,7 +50,8 @@ scs_float min_vec(const scs_float *vec, scs_int n) {
45
50
 
46
51
  scs_float sum_log(const scs_float *x, scs_int n) {
47
52
  scs_float sum = 0.0;
48
- for (scs_int i = 0; i < n; ++i) {
53
+ scs_int i;
54
+ for (i = 0; i < n; ++i) {
49
55
  sum += log(x[i]);
50
56
  }
51
57
  return sum;
@@ -1,6 +1,12 @@
1
+ /*
2
+ * Utility functions: platform-specific timers, deep copy helpers for
3
+ * ScsData/ScsSettings, memory deallocation, and default settings.
4
+ */
5
+
1
6
  #include "util.h"
2
7
 
3
8
  #include "glbopts.h"
9
+ #include <string.h>
4
10
  #include "linsys.h"
5
11
  #include "scs_matrix.h"
6
12
 
@@ -71,25 +77,38 @@ scs_float SCS(tocq)(SCS(timer) * t) {
71
77
 
72
78
  #endif
73
79
 
74
- void SCS(deep_copy_data)(ScsData *dest, const ScsData *src) {
80
+ scs_int SCS(deep_copy_data)(ScsData *dest, const ScsData *src) {
81
+ memset(dest, 0, sizeof(*dest));
75
82
  dest->n = src->n;
76
83
  dest->m = src->m;
77
- SCS(copy_matrix)(&(dest->A), src->A);
78
- SCS(copy_matrix)(&(dest->P), src->P);
84
+ if (!SCS(copy_matrix)(&(dest->A), src->A) ||
85
+ !SCS(copy_matrix)(&(dest->P), src->P)) {
86
+ return 0;
87
+ }
79
88
  dest->b = (scs_float *)scs_calloc(dest->m, sizeof(scs_float));
80
- memcpy(dest->b, src->b, dest->m * sizeof(scs_float));
81
89
  dest->c = (scs_float *)scs_calloc(dest->n, sizeof(scs_float));
90
+ if (!dest->b || !dest->c) {
91
+ return 0;
92
+ }
93
+ memcpy(dest->b, src->b, dest->m * sizeof(scs_float));
82
94
  memcpy(dest->c, src->c, dest->n * sizeof(scs_float));
95
+ return 1;
83
96
  }
84
97
 
85
- void SCS(deep_copy_stgs)(ScsSettings *dest, const ScsSettings *src) {
98
+ scs_int SCS(deep_copy_stgs)(ScsSettings *dest, const ScsSettings *src) {
86
99
  memcpy(dest, src, sizeof(ScsSettings));
87
100
  /* MATLAB does something weird with strdup, so use strcpy instead */
88
101
  char *tmp;
89
102
  if (src->write_data_filename) {
90
103
  /* sizeof(char) = 1 */
91
104
  tmp = (char *)scs_malloc(strlen(src->write_data_filename) + 1);
92
- strcpy(tmp, src->write_data_filename);
105
+ if (tmp) {
106
+ strcpy(tmp, src->write_data_filename);
107
+ }
108
+ if (!tmp) {
109
+ dest->write_data_filename = SCS_NULL;
110
+ return 0;
111
+ }
93
112
  dest->write_data_filename = tmp;
94
113
  } else {
95
114
  dest->write_data_filename = SCS_NULL;
@@ -98,11 +117,18 @@ void SCS(deep_copy_stgs)(ScsSettings *dest, const ScsSettings *src) {
98
117
  if (src->log_csv_filename) {
99
118
  /* sizeof(char) = 1 */
100
119
  tmp = (char *)scs_malloc(strlen(src->log_csv_filename) + 1);
101
- strcpy(tmp, src->log_csv_filename);
120
+ if (tmp) {
121
+ strcpy(tmp, src->log_csv_filename);
122
+ }
123
+ if (!tmp) {
124
+ dest->log_csv_filename = SCS_NULL;
125
+ return 0;
126
+ }
102
127
  dest->log_csv_filename = tmp;
103
128
  } else {
104
129
  dest->log_csv_filename = SCS_NULL;
105
130
  }
131
+ return 1;
106
132
  }
107
133
 
108
134
  void SCS(free_data)(ScsData *d) {
@@ -143,7 +169,11 @@ void scs_set_default_settings(ScsSettings *stgs) {
143
169
  stgs->warm_start = WARM_START;
144
170
  stgs->acceleration_lookback = ACCELERATION_LOOKBACK;
145
171
  stgs->acceleration_interval = ACCELERATION_INTERVAL;
172
+ stgs->acceleration_type_1 = ACCELERATION_TYPE_1;
173
+ stgs->acceleration_regularization = AA_REGULARIZATION;
174
+ stgs->acceleration_relaxation = AA_RELAXATION;
146
175
  stgs->adaptive_scale = ADAPTIVE_SCALE;
176
+ stgs->adaptive_diag_scale = ADAPTIVE_DIAG_SCALE;
147
177
  stgs->write_data_filename = WRITE_DATA_FILENAME;
148
178
  stgs->log_csv_filename = LOG_CSV_FILENAME;
149
179
  stgs->time_limit_secs = TIME_LIMIT_SECS;
@@ -0,0 +1,97 @@
1
+ #include "scs.h"
2
+
3
+ #include <stdio.h>
4
+ #include <stdlib.h>
5
+ #include <string.h>
6
+
7
+ /* Two modes, selected by argv[1]:
8
+ *
9
+ * mismatch (default): preset the WRONG integer width before scs_init;
10
+ * initialization must fail fast with the interface-layer diagnostic.
11
+ *
12
+ * gnu: preset the GNU Fortran calling-convention flag together with the
13
+ * CORRECT integer width (values 2 = LP64|GNU or 3 = ILP64|GNU, as an
14
+ * MKL-backed NumPy does when it initializes MKL first); initialization
15
+ * and a full solve must succeed, proving the runtime guard compares
16
+ * only the width bit. */
17
+
18
+ #define MKL_INTERFACE_LP64 0
19
+ #define MKL_INTERFACE_ILP64 1
20
+ #define MKL_INTERFACE_GNU 2
21
+
22
+ int MKL_Set_Interface_Layer(int);
23
+
24
+ int main(int argc, char **argv) {
25
+ scs_float P_x[3] = {3., -1., 2.};
26
+ scs_int P_i[3] = {0, 0, 1};
27
+ scs_int P_p[3] = {0, 1, 3};
28
+ scs_float A_x[4] = {-1., 1., 1., 1.};
29
+ scs_int A_i[4] = {0, 1, 0, 2};
30
+ scs_int A_p[3] = {0, 2, 4};
31
+ scs_float b[3] = {-1., 0.3, -0.5};
32
+ scs_float c[2] = {-1., -1.};
33
+ ScsCone k = {0};
34
+ ScsData d = {0};
35
+ ScsSettings stgs = {0};
36
+ ScsSolution sol = {0};
37
+ ScsInfo info;
38
+ ScsWork *w;
39
+ int gnu_mode = argc > 1 && strcmp(argv[1], "gnu") == 0;
40
+ int layer;
41
+ int actual;
42
+ scs_int exitflag;
43
+
44
+ #ifdef BLAS64
45
+ layer = gnu_mode ? (MKL_INTERFACE_ILP64 | MKL_INTERFACE_GNU)
46
+ : MKL_INTERFACE_LP64;
47
+ #else
48
+ layer = gnu_mode ? (MKL_INTERFACE_LP64 | MKL_INTERFACE_GNU)
49
+ : MKL_INTERFACE_ILP64;
50
+ #endif
51
+
52
+ actual = MKL_Set_Interface_Layer(layer);
53
+ if (actual != layer) {
54
+ fprintf(stderr,
55
+ "failed to pre-set MKL interface layer to %d, actual layer is %d\n",
56
+ layer, actual);
57
+ return 2;
58
+ }
59
+
60
+ d.m = 3;
61
+ d.n = 2;
62
+ d.b = b;
63
+ d.c = c;
64
+ d.A = &(ScsMatrix){A_x, A_i, A_p, 3, 2};
65
+ d.P = &(ScsMatrix){P_x, P_i, P_p, 2, 2};
66
+
67
+ k.z = 1;
68
+ k.l = 2;
69
+
70
+ scs_set_default_settings(&stgs);
71
+ stgs.verbose = 1;
72
+
73
+ if (gnu_mode) {
74
+ exitflag = scs(&d, &k, &stgs, &sol, &info);
75
+ if (exitflag != SCS_SOLVED) {
76
+ fprintf(stderr, "gnu-layer solve failed with exitflag %d\n",
77
+ (int)exitflag);
78
+ return 4;
79
+ }
80
+ printf("gnu-layer solve succeeded (layer %d)\n", layer);
81
+ free(sol.x);
82
+ free(sol.y);
83
+ free(sol.s);
84
+ return 0;
85
+ }
86
+
87
+ w = scs_init(&d, &k, &stgs);
88
+ if (w != SCS_NULL) {
89
+ fprintf(stderr,
90
+ "expected scs_init to fail after forcing the wrong MKL interface "
91
+ "layer\n");
92
+ scs_finish(w);
93
+ return 3;
94
+ }
95
+
96
+ return 0;
97
+ }
@@ -0,0 +1,21 @@
1
+ # Consumes an INSTALLED scs package (see .github/workflows/cmake_consume.yml).
2
+ # The installed package, not this fixture, must enforce its consumer floor.
3
+ cmake_minimum_required(VERSION 3.18)
4
+ project(scs_consume C)
5
+
6
+ set(SCS_COMPONENT scsdir CACHE STRING "scs library to consume (scsdir, scsmkl, ...)")
7
+
8
+ # CI: a consumer that resolved LAPACK at the wrong integer width before scs
9
+ # must be refused by a static package.
10
+ option(PREFIND_LAPACK_WRONG_WIDTH "find LAPACK with 4-byte integers first" OFF)
11
+ if(PREFIND_LAPACK_WRONG_WIDTH)
12
+ set(BLA_SIZEOF_INTEGER 4)
13
+ find_package(LAPACK REQUIRED)
14
+ endif()
15
+
16
+ find_package(scs CONFIG REQUIRED)
17
+ if(NOT scs::${SCS_COMPONENT} IN_LIST scs_LIBRARIES)
18
+ message(FATAL_ERROR "scs_LIBRARIES=${scs_LIBRARIES} lacks scs::${SCS_COMPONENT}")
19
+ endif()
20
+ add_executable(consume consume.c)
21
+ target_link_libraries(consume PRIVATE scs::${SCS_COMPONENT})
@@ -0,0 +1,50 @@
1
+ /* Minimal consumer of an *installed* SCS package: links scs::scsdir via
2
+ * find_package(scs) and solves a tiny QP. Used by the cmake_consume CI
3
+ * workflow to prove installed packages are usable for both shared and
4
+ * static builds (and that shared installs demand no private build deps). */
5
+ #include "scs.h"
6
+
7
+ #include <stdio.h>
8
+ #include <stdlib.h>
9
+
10
+ int main(void) {
11
+ scs_float P_x[3] = {3., -1., 2.};
12
+ scs_int P_i[3] = {0, 0, 1};
13
+ scs_int P_p[3] = {0, 1, 3};
14
+ scs_float A_x[4] = {-1., 1., 1., 1.};
15
+ scs_int A_i[4] = {0, 1, 0, 2};
16
+ scs_int A_p[3] = {0, 2, 4};
17
+ scs_float b[3] = {-1., 0.3, -0.5};
18
+ scs_float c[2] = {-1., -1.};
19
+ ScsCone k = {0};
20
+ ScsData d = {0};
21
+ ScsSettings stgs = {0};
22
+ ScsSolution sol = {0};
23
+ ScsInfo info;
24
+ scs_int exitflag;
25
+
26
+ printf("consuming scs %s\n", scs_version());
27
+
28
+ d.m = 3;
29
+ d.n = 2;
30
+ d.b = b;
31
+ d.c = c;
32
+ d.A = &(ScsMatrix){A_x, A_i, A_p, 3, 2};
33
+ d.P = &(ScsMatrix){P_x, P_i, P_p, 2, 2};
34
+ k.z = 1;
35
+ k.l = 2;
36
+
37
+ scs_set_default_settings(&stgs);
38
+ stgs.verbose = 1;
39
+
40
+ exitflag = scs(&d, &k, &stgs, &sol, &info);
41
+ if (exitflag != SCS_SOLVED) {
42
+ fprintf(stderr, "consume: solve failed with exitflag %d\n", (int)exitflag);
43
+ return 1;
44
+ }
45
+ printf("consume: solved, objective %f\n", info.pobj);
46
+ free(sol.x);
47
+ free(sol.y);
48
+ free(sol.s);
49
+ return 0;
50
+ }
@@ -10,6 +10,8 @@
10
10
  #include "scs_matrix.h"
11
11
  #include "util.h"
12
12
 
13
+ #include <string.h>
14
+
13
15
  #define _MAX_RAND_VAL (1073741823) /* 2^30 - 1 */
14
16
 
15
17
  /* uniform random number in [-1,1] */
@@ -205,10 +207,15 @@ const char *verify_solution_correct(ScsData *d, ScsCone *k, ScsSettings *stgs,
205
207
 
206
208
  /**************** ASSERTS *****************/
207
209
  if (status == SCS_SOLVED) {
210
+ /* reported-vs-recomputed consistency: the recomputation here uses a
211
+ * different BLAS summation order than the solver's internal pipeline,
212
+ * so the discrepancy scales with the magnitude of the accumulated
213
+ * quantities (~ the objective scale), like the gap and objective
214
+ * checks below already do */
208
215
  mu_assert_less("Primal residual ERROR", ABS(res_pri - info->res_pri),
209
- 1e-10);
216
+ 1e-10 * (1 + ABS(pobj)));
210
217
  mu_assert_less("Dual residual ERROR", ABS(res_dual - info->res_dual),
211
- 1e-10);
218
+ 1e-10 * (1 + ABS(pobj)));
212
219
  mu_assert_less("Gap ERROR", ABS(gap - info->gap), 1e-7 * (1 + ABS(gap)));
213
220
  mu_assert_less("Primal obj ERROR", ABS(pobj - info->pobj),
214
221
  1e-9 * (1 + ABS(pobj)));