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,38 @@
1
+ #ifndef PRIV_H_GUARD
2
+ #define PRIV_H_GUARD
3
+
4
+ #ifdef __cplusplus
5
+ extern "C" {
6
+ #endif
7
+
8
+ #include "csparse.h"
9
+ #include "linsys.h"
10
+
11
+ struct SCS_LIN_SYS_WORK {
12
+ ScsMatrix *kkt; /* Upper triangular KKT matrix (in CSR format) */
13
+ scs_float *sol; /* solution to the KKT system */
14
+ scs_int n; /* number of QP variables */
15
+ scs_int m; /* number of QP constraints */
16
+
17
+ /* Pardiso variables */
18
+ void *pt[64]; /* internal solver memory pointer pt */
19
+ scs_int iparm[64]; /* Pardiso control parameters */
20
+ scs_int n_plus_m; /* dimension of the linear system */
21
+ scs_int mtype; /* matrix type (-2 for real and symmetric indefinite) */
22
+ scs_int nrhs; /* number of right-hand sides (1) */
23
+ scs_int maxfct; /* maximum number of factors (1) */
24
+ scs_int mnum; /* indicates matrix for the solution phase (1) */
25
+ scs_int phase; /* control the execution phases of the solver */
26
+ scs_int error; /* the error indicator (0 for no error) */
27
+ scs_int msglvl; /* Message level information (0 for no output) */
28
+
29
+ /* These are required for matrix updates */
30
+ scs_int *diag_r_idxs; /* indices where R appears */
31
+ scs_float *diag_p; /* Diagonal values of P */
32
+ };
33
+
34
+ #ifdef __cplusplus
35
+ }
36
+ #endif
37
+
38
+ #endif
@@ -117,6 +117,7 @@ static void compute_ruiz_mats(ScsMatrix *P, ScsMatrix *A, scs_float *Dt,
117
117
  scs_float *Et, ScsConeWork *cone) {
118
118
  scs_int i, j, kk;
119
119
  scs_float wrk;
120
+ scs_float nm_a_col;
120
121
 
121
122
  /**************************** D ****************************/
122
123
 
@@ -138,7 +139,8 @@ static void compute_ruiz_mats(ScsMatrix *P, ScsMatrix *A, scs_float *Dt,
138
139
 
139
140
  /* invert temporary vec to form D */
140
141
  for (i = 0; i < A->m; ++i) {
141
- Dt[i] = SAFEDIV_POS(1.0, SQRTF(apply_limit(Dt[i])));
142
+ Dt[i] = SQRTF(apply_limit(Dt[i]));
143
+ Dt[i] = SAFEDIV_POS(1.0, Dt[i]);
142
144
  }
143
145
 
144
146
  /**************************** E ****************************/
@@ -169,8 +171,10 @@ static void compute_ruiz_mats(ScsMatrix *P, ScsMatrix *A, scs_float *Dt,
169
171
 
170
172
  /* calculate col norms, E */
171
173
  for (i = 0; i < A->n; ++i) {
172
- Et[i] = MAX(Et[i], SCS(norm_inf)(&(A->x[A->p[i]]), A->p[i + 1] - A->p[i]));
173
- Et[i] = SAFEDIV_POS(1.0, SQRTF(apply_limit(Et[i])));
174
+ nm_a_col = SCS(norm_inf)(&(A->x[A->p[i]]), A->p[i + 1] - A->p[i]);
175
+ Et[i] = MAX(Et[i], nm_a_col);
176
+ Et[i] = SQRTF(apply_limit(Et[i]));
177
+ Et[i] = SAFEDIV_POS(1.0, Et[i]);
174
178
  }
175
179
  }
176
180
 
@@ -201,7 +205,8 @@ static void compute_l2_mats(ScsMatrix *P, ScsMatrix *A, scs_float *Dt,
201
205
  SCS(enforce_cone_boundaries)(cone, Dt, &SCS(mean));
202
206
 
203
207
  for (i = 0; i < A->m; ++i) {
204
- Dt[i] = SAFEDIV_POS(1.0, SQRTF(apply_limit(Dt[i])));
208
+ Dt[i] = SQRTF(apply_limit(Dt[i]));
209
+ Dt[i] = SAFEDIV_POS(1.0, Dt[i]);
205
210
  }
206
211
 
207
212
  /**************************** E ****************************/
@@ -233,7 +238,8 @@ static void compute_l2_mats(ScsMatrix *P, ScsMatrix *A, scs_float *Dt,
233
238
  /* calculate col norms, E */
234
239
  for (i = 0; i < A->n; ++i) {
235
240
  Et[i] += SCS(norm_sq)(&(A->x[A->p[i]]), A->p[i + 1] - A->p[i]);
236
- Et[i] = SAFEDIV_POS(1.0, SQRTF(apply_limit(SQRTF(Et[i]))));
241
+ Et[i] = SQRTF(apply_limit(SQRTF(Et[i])));
242
+ Et[i] = SAFEDIV_POS(1.0, Et[i]);
237
243
  }
238
244
  }
239
245
 
data/vendor/scs/scs.mk CHANGED
@@ -69,6 +69,7 @@ DIRSRC = $(LINSYS)/cpu/direct
69
69
  INDIRSRC = $(LINSYS)/cpu/indirect
70
70
  GPUDIR = $(LINSYS)/gpu/direct
71
71
  GPUINDIR = $(LINSYS)/gpu/indirect
72
+ MKLSRC = $(LINSYS)/mkl/direct
72
73
 
73
74
  EXTSRC = $(LINSYS)/external
74
75
 
@@ -83,44 +84,56 @@ ifeq ($(PREFIX),)
83
84
  PREFIX = /usr/local
84
85
  endif
85
86
 
86
- OPT_FLAGS =
87
- ########### OPTIONAL FLAGS ##########
87
+ ########### CUSTOM FLAGS ##########
88
88
  # these can all be override from the command line
89
+ CUSTOM_FLAGS =
89
90
  # e.g. make DLONG=1 will override the setting below
90
91
  DLONG = 0
91
92
  ifneq ($(DLONG), 0)
92
- OPT_FLAGS += -DDLONG=$(DLONG) # use longs rather than ints
93
+ CUSTOM_FLAGS += -DDLONG=$(DLONG) # use longs rather than ints
93
94
  endif
94
95
  CTRLC = 1
95
96
  ifneq ($(CTRLC), 0)
96
- OPT_FLAGS += -DCTRLC=$(CTRLC) # graceful interrupts with ctrl-c
97
+ CUSTOM_FLAGS += -DCTRLC=$(CTRLC) # graceful interrupts with ctrl-c
97
98
  endif
98
99
  SFLOAT = 0
99
100
  ifneq ($(SFLOAT), 0)
100
- OPT_FLAGS += -DSFLOAT=$(SFLOAT) # use floats rather than doubles
101
- endif
102
- NOTIMER = 0
103
- ifneq ($(NOTIMER), 0)
104
- OPT_FLAGS += -DNOTIMER=$(NOTIMER) # no timing, times reported as nan
101
+ CUSTOM_FLAGS += -DSFLOAT=$(SFLOAT) # use floats rather than doubles
105
102
  endif
106
103
  GPU_TRANSPOSE_MAT = 1
107
104
  ifneq ($(GPU_TRANSPOSE_MAT), 0)
108
- OPT_FLAGS += -DGPU_TRANSPOSE_MAT=$(GPU_TRANSPOSE_MAT) # tranpose A mat in GPU memory
105
+ CUSTOM_FLAGS += -DGPU_TRANSPOSE_MAT=$(GPU_TRANSPOSE_MAT) # transpose A mat in GPU memory
106
+ endif
107
+ NO_TIMER = 0
108
+ ifneq ($(NO_TIMER), 0)
109
+ CUSTOM_FLAGS += -DNO_TIMER=$(NO_TIMER) # no timing, times reported as nan
110
+ endif
111
+ NO_VALIDATE = 0
112
+ ifneq ($(NO_VALIDATE), 0)
113
+ CUSTOM_FLAGS += -DNO_VALIDATE=$(NO_VALIDATE) # perform problem validation or skip
114
+ endif
115
+ NO_PRINTING = 0
116
+ ifneq ($(NO_PRINTING), 0)
117
+ CUSTOM_FLAGS += -DNO_PRINTING=$(NO_PRINTING) # disable printing
109
118
  endif
110
- NOVALIDATE = 0
111
- ifneq ($(NOVALIDATE), 0)
112
- OPT_FLAGS += -DNOVALIDATE=$(NOVALIDATE) # perform problem validation or skip
119
+ NO_READ_WRITE = 0
120
+ ifneq ($(NO_READ_WRITE), 0)
121
+ CUSTOM_FLAGS += -DNO_READ_WRITE=$(NO_READ_WRITE) # disable printing
113
122
  endif
114
123
  ### VERBOSITY LEVELS: 0,1,2,...
115
124
  VERBOSITY = 0
116
125
  ifneq ($(VERBOSITY), 0)
117
- OPT_FLAGS += -DVERBOSITY=$(VERBOSITY) # verbosity level
126
+ CUSTOM_FLAGS += -DVERBOSITY=$(VERBOSITY) # verbosity level
118
127
  endif
119
128
  COVERAGE = 0
120
129
  ifneq ($(COVERAGE), 0)
121
- override CFLAGS += --coverage # generate test coverage data
130
+ CUSTOM_FLAGS += --coverage # generate test coverage data
122
131
  endif
123
132
 
133
+ # See: https://www.intel.com/content/www/us/en/developer/tools/oneapi/onemkl-link-line-advisor.html
134
+ # This is probably not correct for other systems. TODO: update this
135
+ # to work for all combinations of platform / compiler / threading options.
136
+ MKLFLAGS = -L$(MKLROOT) -L$(MKLROOT)/lib -Wl,--no-as-needed -lmkl_rt -lmkl_gnu_thread -lmkl_core -lgomp -lpthread -ldl
124
137
 
125
138
  ############ OPENMP: ############
126
139
  # set USE_OPENMP = 1 to allow openmp (multi-threaded matrix multiplies):
@@ -138,44 +151,44 @@ endif
138
151
  # NB: point the libraries to the locations where
139
152
  # you have blas and lapack installed
140
153
 
154
+ BLASLDFLAGS =
141
155
  USE_LAPACK = 1
142
156
  ifneq ($(USE_LAPACK), 0)
143
157
  # edit these for your setup:
144
- BLASLDFLAGS = -llapack -lblas # -lgfortran
145
- LDFLAGS += $(BLASLDFLAGS)
146
- OPT_FLAGS += -DUSE_LAPACK
158
+ BLASLDFLAGS += -llapack -lblas # -lgfortran
159
+ CUSTOM_FLAGS += -DUSE_LAPACK
147
160
 
148
161
  BLAS64 = 0
149
162
  ifneq ($(BLAS64), 0)
150
- OPT_FLAGS += -DBLAS64=$(BLAS64) # if blas/lapack lib uses 64 bit ints
163
+ CUSTOM_FLAGS += -DBLAS64=$(BLAS64) # if blas/lapack lib uses 64 bit ints
151
164
  endif
152
165
 
153
166
  NOBLASSUFFIX = 0
154
167
  ifneq ($(NOBLASSUFFIX), 0)
155
- OPT_FLAGS += -DNOBLASSUFFIX=$(NOBLASSUFFIX) # hack to strip blas suffix
168
+ CUSTOM_FLAGS += -DNOBLASSUFFIX=$(NOBLASSUFFIX) # hack to strip blas suffix
156
169
  endif
157
170
 
158
171
  BLASSUFFIX = "_"
159
172
  ifneq ($(BLASSUFFIX), "_")
160
- OPT_FLAGS += -DBLASSUFFIX=$(BLASSUFFIX) # blas suffix (underscore usually)
173
+ CUSTOM_FLAGS += -DBLASSUFFIX=$(BLASSUFFIX) # blas suffix (underscore usually)
161
174
  endif
162
175
  endif
163
176
 
164
177
  MATLAB_MEX_FILE = 0
165
178
  ifneq ($(MATLAB_MEX_FILE), 0)
166
- OPT_FLAGS += -DMATLAB_MEX_FILE=$(MATLAB_MEX_FILE) # matlab mex
179
+ CUSTOM_FLAGS += -DMATLAB_MEX_FILE=$(MATLAB_MEX_FILE) # matlab mex
167
180
  endif
168
181
  PYTHON = 0
169
182
  ifneq ($(PYTHON), 0)
170
- OPT_FLAGS += -DPYTHON=$(PYTHON) # python extension
183
+ CUSTOM_FLAGS += -DPYTHON=$(PYTHON) # python extension
171
184
  endif
172
185
  USING_R = 0
173
186
  ifneq ($(USING_R), 0)
174
- OPT_FLAGS += -DUSING_R=$(USING_R) # R extension
187
+ CUSTOM_FLAGS += -DUSING_R=$(USING_R) # R extension
175
188
  endif
176
189
 
177
190
  # debug to see var values, e.g. 'make print-OBJECTS' shows OBJECTS value
178
191
  print-%: ; @echo $*=$($*)
179
192
 
180
- override CFLAGS += $(OPT_FLAGS)
181
- CUDAFLAGS += $(OPT_FLAGS)
193
+ override CFLAGS += $(CUSTOM_FLAGS)
194
+ CUDAFLAGS += $(CUSTOM_FLAGS)
@@ -4,10 +4,8 @@
4
4
  #include "scs_blas.h" /* contains BLAS(X) macros and type info */
5
5
  #include "util.h"
6
6
 
7
- #define CONE_TOL (1e-9)
8
- #define CONE_THRESH (1e-8)
9
- #define EXP_CONE_MAX_ITERS (100)
10
7
  #define BOX_CONE_MAX_ITERS (25)
8
+ #define POW_CONE_TOL (1e-9)
11
9
  #define POW_CONE_MAX_ITERS (20)
12
10
 
13
11
  /* Box cone limits (+ or -) taken to be INF */
@@ -35,6 +33,11 @@ void BLAS(scal)(const blas_int *n, const scs_float *sa, scs_float *sx,
35
33
 
36
34
  #endif
37
35
 
36
+ /* Forward declare exponential cone projection routine.
37
+ * Implemented in exp_cone.c.
38
+ */
39
+ scs_float SCS(proj_pd_exp_cone)(scs_float *v0, scs_int primal);
40
+
38
41
  void SCS(free_cone)(ScsCone *k) {
39
42
  if (k) {
40
43
  if (k->bu)
@@ -285,7 +288,7 @@ void SCS(finish_cone)(ScsConeWork *c) {
285
288
  }
286
289
 
287
290
  char *SCS(get_cone_header)(const ScsCone *k) {
288
- char *tmp = (char *)scs_malloc(sizeof(char) * 512);
291
+ char *tmp = (char *)scs_malloc(512); /* sizeof(char) = 1 */
289
292
  scs_int i, soc_vars, sd_vars;
290
293
  sprintf(tmp, "cones: ");
291
294
  if (k->z) {
@@ -325,118 +328,6 @@ char *SCS(get_cone_header)(const ScsCone *k) {
325
328
  return tmp;
326
329
  }
327
330
 
328
- static scs_float exp_newton_one_d(scs_float rho, scs_float y_hat,
329
- scs_float z_hat, scs_float w) {
330
- scs_float t_prev, t = MAX(w - z_hat, MAX(-z_hat, 1e-9));
331
- scs_float f = 1., fp = 1.;
332
- scs_int i;
333
- for (i = 0; i < EXP_CONE_MAX_ITERS; ++i) {
334
- t_prev = t;
335
- f = t * (t + z_hat) / rho / rho - y_hat / rho + log(t / rho) + 1;
336
- fp = (2 * t + z_hat) / rho / rho + 1 / t;
337
-
338
- t = t - f / fp;
339
-
340
- if (t <= -z_hat) {
341
- t = -z_hat;
342
- break;
343
- } else if (t <= 0) {
344
- t = 0;
345
- break;
346
- } else if (ABS(t - t_prev) < CONE_TOL) {
347
- break;
348
- } else if (SQRTF(f * f / fp) < CONE_TOL) {
349
- break;
350
- }
351
- }
352
- if (i == EXP_CONE_MAX_ITERS) {
353
- scs_printf("warning: exp cone newton step hit maximum %i iters\n", (int)i);
354
- scs_printf("rho=%1.5e; y_hat=%1.5e; z_hat=%1.5e; w=%1.5e; f=%1.5e, "
355
- "fp=%1.5e, t=%1.5e, t_prev= %1.5e\n",
356
- rho, y_hat, z_hat, w, f, fp, t, t_prev);
357
- }
358
- return t + z_hat;
359
- }
360
-
361
- static void exp_solve_for_x_with_rho(const scs_float *v, scs_float *x,
362
- scs_float rho, scs_float w) {
363
- x[2] = exp_newton_one_d(rho, v[1], v[2], w);
364
- x[1] = (x[2] - v[2]) * x[2] / rho;
365
- x[0] = v[0] - rho;
366
- }
367
-
368
- static scs_float exp_calc_grad(const scs_float *v, scs_float *x, scs_float rho,
369
- scs_float w) {
370
- exp_solve_for_x_with_rho(v, x, rho, w);
371
- if (x[1] <= 1e-12) {
372
- return x[0];
373
- }
374
- return x[0] + x[1] * log(x[1] / x[2]);
375
- }
376
-
377
- static void exp_get_rho_ub(const scs_float *v, scs_float *x, scs_float *ub,
378
- scs_float *lb) {
379
- *lb = 0;
380
- *ub = 0.125;
381
- while (exp_calc_grad(v, x, *ub, v[1]) > 0) {
382
- *lb = *ub;
383
- (*ub) *= 2;
384
- }
385
- }
386
-
387
- /* project onto the exponential cone, v has dimension *exactly* 3 */
388
- static scs_int proj_exp_cone(scs_float *v) {
389
- scs_int i;
390
- scs_float ub, lb, rho, g, x[3];
391
- scs_float r = v[0], s = v[1], t = v[2];
392
-
393
- /* v in cl(Kexp) */
394
- if ((s * exp(r / s) - t <= CONE_THRESH && s > 0) ||
395
- (r <= 0 && s == 0 && t >= 0)) {
396
- return 0;
397
- }
398
-
399
- /* -v in Kexp^* */
400
- if ((r > 0 && r * exp(s / r) + exp(1) * t <= CONE_THRESH) ||
401
- (r == 0 && s <= 0 && t <= 0)) {
402
- memset(v, 0, 3 * sizeof(scs_float));
403
- return 0;
404
- }
405
-
406
- /* special case with analytical solution */
407
- if (r < 0 && s < 0) {
408
- v[1] = 0.0;
409
- v[2] = MAX(v[2], 0);
410
- return 0;
411
- }
412
-
413
- /* iterative procedure to find projection, bisects on dual variable: */
414
- exp_get_rho_ub(v, x, &ub, &lb); /* get starting upper and lower bounds */
415
- for (i = 0; i < EXP_CONE_MAX_ITERS; ++i) {
416
- rho = (ub + lb) / 2; /* halfway between upper and lower bounds */
417
- g = exp_calc_grad(v, x, rho, x[1]); /* calculates gradient wrt dual var */
418
- if (g > 0) {
419
- lb = rho;
420
- } else {
421
- ub = rho;
422
- }
423
- if (ub - lb < CONE_TOL) {
424
- break;
425
- }
426
- }
427
- #if VERBOSITY > 10
428
- scs_printf("exponential cone proj iters %i\n", (int)i);
429
- #endif
430
- if (i == EXP_CONE_MAX_ITERS) {
431
- scs_printf("warning: exp cone outer step hit maximum %i iters\n", (int)i);
432
- scs_printf("r=%1.5e; s=%1.5e; t=%1.5e\n", r, s, t);
433
- }
434
- v[0] = x[0];
435
- v[1] = x[1];
436
- v[2] = x[2];
437
- return 0;
438
- }
439
-
440
331
  static scs_int set_up_sd_cone_work_space(ScsConeWork *c, const ScsCone *k) {
441
332
  scs_int i;
442
333
  #ifdef USE_LAPACK
@@ -741,13 +632,13 @@ static void proj_power_cone(scs_float *v, scs_float a) {
741
632
  scs_int i;
742
633
  /* v in K_a */
743
634
  if (xh >= 0 && yh >= 0 &&
744
- CONE_THRESH + POWF(xh, a) * POWF(yh, (1 - a)) >= rh) {
635
+ POW_CONE_TOL + POWF(xh, a) * POWF(yh, (1 - a)) >= rh) {
745
636
  return;
746
637
  }
747
638
 
748
639
  /* -v in K_a^* */
749
640
  if (xh <= 0 && yh <= 0 &&
750
- CONE_THRESH + POWF(-xh, a) * POWF(-yh, 1 - a) >=
641
+ POW_CONE_TOL + POWF(-xh, a) * POWF(-yh, 1 - a) >=
751
642
  rh * POWF(a, a) * POWF(1 - a, 1 - a)) {
752
643
  v[0] = v[1] = v[2] = 0;
753
644
  return;
@@ -760,7 +651,7 @@ static void proj_power_cone(scs_float *v, scs_float a) {
760
651
  y = pow_calc_x(r, yh, rh, 1 - a);
761
652
 
762
653
  f = pow_calc_f(x, y, r, a);
763
- if (ABS(f) < CONE_TOL) {
654
+ if (ABS(f) < POW_CONE_TOL) {
764
655
  break;
765
656
  }
766
657
 
@@ -829,51 +720,16 @@ static scs_int proj_cone(scs_float *x, const ScsCone *k, ScsConeWork *c,
829
720
  }
830
721
  }
831
722
 
832
- if (k->ep) { /* doesn't use r_y */
833
- /*
834
- * exponential cone is not self dual, if s \in K
835
- * then y \in K^* and so if K is the primal cone
836
- * here we project onto K^*, via Moreau
837
- * \Pi_C^*(y) = y + \Pi_C(-y)
838
- */
723
+ if (k->ep || k->ed) { /* doesn't use r_y */
839
724
  #ifdef _OPENMP
840
725
  #pragma omp parallel for
841
726
  #endif
842
- for (i = 0; i < k->ep; ++i) {
843
- proj_exp_cone(&(x[count + 3 * i]));
727
+ for (i = 0; i < k->ep + k->ed; ++i) {
728
+ /* provided in exp_cone.c */
729
+ SCS(proj_pd_exp_cone)(&(x[count + 3 * i]), i < k->ep);
844
730
  }
845
- count += 3 * k->ep;
731
+ count += 3 * (k->ep + k->ed);
846
732
  }
847
-
848
- /* dual exponential cone */
849
- if (k->ed) { /* doesn't use r_y */
850
- /*
851
- * exponential cone is not self dual, if s \in K
852
- * then y \in K^* and so if K is the primal cone
853
- * here we project onto K^*, via Moreau
854
- * \Pi_C^*(y) = y + \Pi_C(-y)
855
- */
856
- scs_int idx;
857
- scs_float r, s, t;
858
- SCS(scale_array)(&(x[count]), -1, 3 * k->ed); /* x = -x; */
859
- #ifdef _OPENMP
860
- #pragma omp parallel for private(r, s, t, idx)
861
- #endif
862
- for (i = 0; i < k->ed; ++i) {
863
- idx = count + 3 * i;
864
- r = x[idx];
865
- s = x[idx + 1];
866
- t = x[idx + 2];
867
-
868
- proj_exp_cone(&(x[idx]));
869
-
870
- x[idx] -= r;
871
- x[idx + 1] -= s;
872
- x[idx + 2] -= t;
873
- }
874
- count += 3 * k->ed;
875
- }
876
-
877
733
  if (k->psize && k->p) { /* doesn't use r_y */
878
734
  scs_float v[3];
879
735
  scs_int idx;