1 /* $Id: CoinOslFactorization2.cpp 2083 2019-01-06 19:38:09Z unxusr $ */
2 /*
3 Copyright (C) 1987, 2009, International Business Machines
4 Corporation and others. All Rights Reserved.
5
6 This code is licensed under the terms of the Eclipse Public License (EPL).
7 */
8 #if COIN_BIG_INDEX == 0
9 /*
10 CLP_OSL - if defined use osl
11 0 - don't unroll 2 and 3 - don't use in Gomory
12 1 - don't unroll - do use in Gomory
13 2 - unroll - don't use in Gomory
14 3 - unroll and use in Gomory
15 */
16 #include "CoinOslFactorization.hpp"
17 #include "CoinOslC.h"
18 #include "CoinFinite.hpp"
19
20 #ifndef NDEBUG
21 extern int ets_count;
22 extern int ets_check;
23 #endif
24 #define COIN_REGISTER register
25 #define COIN_REGISTER2
26 #define COIN_REGISTER3 register
27 #ifdef COIN_USE_RESTRICT
28 #define COIN_RESTRICT2 __restrict
29 #else
30 #define COIN_RESTRICT2
31 #endif
c_ekkshfpo_scan2zero(COIN_REGISTER const EKKfactinfo * COIN_RESTRICT2 fact,const int * COIN_RESTRICT mpermu,double * COIN_RESTRICT worki,double * COIN_RESTRICT worko,int * COIN_RESTRICT mptr)32 static int c_ekkshfpo_scan2zero(COIN_REGISTER const EKKfactinfo *COIN_RESTRICT2 fact, const int *COIN_RESTRICT mpermu,
33 double *COIN_RESTRICT worki, double *COIN_RESTRICT worko, int *COIN_RESTRICT mptr)
34 {
35
36 /* Local variables */
37 int irow;
38 double tolerance = fact->zeroTolerance;
39 int nin = fact->nrow;
40 int *COIN_RESTRICT mptrX = mptr;
41 if ((nin & 1) != 0) {
42 irow = 1;
43 if (fact->packedMode) {
44 int irow0 = *mpermu;
45 double dval;
46 assert(irow0 >= 1 && irow0 <= nin);
47 mpermu++;
48 dval = worki[irow0];
49 if (NOT_ZERO(dval)) {
50 worki[irow0] = 0.0;
51 if (fabs(dval) >= tolerance) {
52 *(worko++) = dval;
53 *(mptrX++) = 0;
54 }
55 }
56 } else {
57 int irow0 = *mpermu;
58 double dval;
59 assert(irow0 >= 1 && irow0 <= nin);
60 mpermu++;
61 dval = worki[irow0];
62 if (NOT_ZERO(dval)) {
63 worki[irow0] = 0.0;
64 if (fabs(dval) >= tolerance) {
65 *worko = dval;
66 *(mptrX++) = 0;
67 }
68 }
69 worko++;
70 }
71 } else {
72 irow = 0;
73 }
74 if (fact->packedMode) {
75 for (; irow < nin; irow += 2) {
76 int irow0, irow1;
77 double dval0, dval1;
78 irow0 = mpermu[0];
79 irow1 = mpermu[1];
80 assert(irow0 >= 1 && irow0 <= nin);
81 assert(irow1 >= 1 && irow1 <= nin);
82 dval0 = worki[irow0];
83 dval1 = worki[irow1];
84 if (NOT_ZERO(dval0)) {
85 worki[irow0] = 0.0;
86 if (fabs(dval0) >= tolerance) {
87 *(worko++) = dval0;
88 *(mptrX++) = irow + 0;
89 }
90 }
91 if (NOT_ZERO(dval1)) {
92 worki[irow1] = 0.0;
93 if (fabs(dval1) >= tolerance) {
94 *(worko++) = dval1;
95 *(mptrX++) = irow + 1;
96 }
97 }
98 mpermu += 2;
99 }
100 } else {
101 for (; irow < nin; irow += 2) {
102 int irow0, irow1;
103 double dval0, dval1;
104 irow0 = mpermu[0];
105 irow1 = mpermu[1];
106 assert(irow0 >= 1 && irow0 <= nin);
107 assert(irow1 >= 1 && irow1 <= nin);
108 dval0 = worki[irow0];
109 dval1 = worki[irow1];
110 if (NOT_ZERO(dval0)) {
111 worki[irow0] = 0.0;
112 if (fabs(dval0) >= tolerance) {
113 worko[0] = dval0;
114 *(mptrX++) = irow + 0;
115 }
116 }
117 if (NOT_ZERO(dval1)) {
118 worki[irow1] = 0.0;
119 if (fabs(dval1) >= tolerance) {
120 worko[1] = dval1;
121 *(mptrX++) = irow + 1;
122 }
123 }
124 mpermu += 2;
125 worko += 2;
126 }
127 }
128 return static_cast< int >(mptrX - mptr);
129 }
130 /*
131 * c_ekkshfpi_list executes the following loop:
132 *
133 * for (k=nincol, i=1; k; k--, i++) {
134 * int ipt = mptr[i];
135 * int irow = mpermu[ipt];
136 * worko[mpermu[irow]] = worki[i];
137 * worki[i] = 0.0;
138 * }
139 */
c_ekkshfpi_list(const int * COIN_RESTRICT mpermu,double * COIN_RESTRICT worki,double * COIN_RESTRICT worko,const int * COIN_RESTRICT mptr,int nincol,int * lastNonZero)140 static int c_ekkshfpi_list(const int *COIN_RESTRICT mpermu,
141 double *COIN_RESTRICT worki,
142 double *COIN_RESTRICT worko,
143 const int *COIN_RESTRICT mptr, int nincol,
144 int *lastNonZero)
145 {
146 int i, k, irow0, irow1;
147 int first = COIN_INT_MAX;
148 int last = 0;
149 /* worko was zeroed out outside */
150 k = nincol;
151 i = 0;
152 if ((k & 1) != 0) {
153 int ipt = mptr[i];
154 irow0 = mpermu[ipt];
155 first = CoinMin(irow0, first);
156 last = CoinMax(irow0, last);
157 i++;
158 worko[irow0] = *worki;
159 *worki++ = 0.0;
160 }
161 k = k >> 1;
162 for (; k; k--) {
163 int ipt0 = mptr[i];
164 int ipt1 = mptr[i + 1];
165 irow0 = mpermu[ipt0];
166 irow1 = mpermu[ipt1];
167 i += 2;
168 first = CoinMin(irow0, first);
169 last = CoinMax(irow0, last);
170 first = CoinMin(irow1, first);
171 last = CoinMax(irow1, last);
172 worko[irow0] = worki[0];
173 worko[irow1] = worki[1];
174 worki[0] = 0.0;
175 worki[1] = 0.0;
176 worki += 2;
177 }
178 *lastNonZero = last;
179 return first;
180 }
181 /*
182 * c_ekkshfpi_list2 executes the following loop:
183 *
184 * for (k=nincol, i=1; k; k--, i++) {
185 * int ipt = mptr[i];
186 * int irow = mpermu[ipt];
187 * worko[mpermu[irow]] = worki[ipt];
188 * worki[ipt] = 0.0;
189 * }
190 */
c_ekkshfpi_list2(const int * COIN_RESTRICT mpermu,double * COIN_RESTRICT worki,double * COIN_RESTRICT worko,const int * COIN_RESTRICT mptr,int nincol,int * lastNonZero)191 static int c_ekkshfpi_list2(const int *COIN_RESTRICT mpermu, double *COIN_RESTRICT worki, double *COIN_RESTRICT worko,
192 const int *COIN_RESTRICT mptr, int nincol,
193 int *lastNonZero)
194 {
195 #if 1
196 int i, k, irow0, irow1;
197 int first = COIN_INT_MAX;
198 int last = 0;
199 /* worko was zeroed out outside */
200 k = nincol;
201 i = 0;
202 if ((k & 1) != 0) {
203 int ipt = mptr[i];
204 irow0 = mpermu[ipt];
205 first = CoinMin(irow0, first);
206 last = CoinMax(irow0, last);
207 i++;
208 worko[irow0] = worki[ipt];
209 worki[ipt] = 0.0;
210 }
211 k = k >> 1;
212 for (; k; k--) {
213 int ipt0 = mptr[i];
214 int ipt1 = mptr[i + 1];
215 irow0 = mpermu[ipt0];
216 irow1 = mpermu[ipt1];
217 i += 2;
218 first = CoinMin(irow0, first);
219 last = CoinMax(irow0, last);
220 first = CoinMin(irow1, first);
221 last = CoinMax(irow1, last);
222 worko[irow0] = worki[ipt0];
223 worko[irow1] = worki[ipt1];
224 worki[ipt0] = 0.0;
225 worki[ipt1] = 0.0;
226 }
227 #else
228 int first = COIN_INT_MAX;
229 int last = 0;
230 /* worko was zeroed out outside */
231 for (int i = 0; i < nincol; i++) {
232 int ipt = mptr[i];
233 int irow = mpermu[ipt];
234 first = CoinMin(irow, first);
235 last = CoinMax(irow, last);
236 worko[irow] = worki[ipt];
237 worki[ipt] = 0.0;
238 }
239 #endif
240 *lastNonZero = last;
241 return first;
242 }
243 /*
244 * c_ekkshfpi_list3 executes the following loop:
245 *
246 * for (k=nincol, i=1; k; k--, i++) {
247 * int ipt = mptr[i];
248 * int irow = mpermu[ipt];
249 * worko[irow] = worki[i];
250 * worki[i] = 0.0;
251 * mptr[i] = mpermu[ipt];
252 * }
253 */
c_ekkshfpi_list3(const int * COIN_RESTRICT mpermu,double * COIN_RESTRICT worki,double * COIN_RESTRICT worko,int * COIN_RESTRICT mptr,int nincol)254 static void c_ekkshfpi_list3(const int *COIN_RESTRICT mpermu,
255 double *COIN_RESTRICT worki, double *COIN_RESTRICT worko,
256 int *COIN_RESTRICT mptr, int nincol)
257 {
258 int i, k, irow0, irow1;
259 /* worko was zeroed out outside */
260 k = nincol;
261 i = 0;
262 if ((k & 1) != 0) {
263 int ipt = mptr[i];
264 irow0 = mpermu[ipt];
265 mptr[i] = irow0;
266 i++;
267 worko[irow0] = *worki;
268 *worki++ = 0.0;
269 }
270 k = k >> 1;
271 for (; k; k--) {
272 int ipt0 = mptr[i];
273 int ipt1 = mptr[i + 1];
274 irow0 = mpermu[ipt0];
275 irow1 = mpermu[ipt1];
276 mptr[i] = irow0;
277 mptr[i + 1] = irow1;
278 i += 2;
279 worko[irow0] = worki[0];
280 worko[irow1] = worki[1];
281 worki[0] = 0.0;
282 worki[1] = 0.0;
283 worki += 2;
284 }
285 }
c_ekkscmv(COIN_REGISTER const EKKfactinfo * COIN_RESTRICT2 fact,int n,double * COIN_RESTRICT dwork,int * COIN_RESTRICT mptr,double * COIN_RESTRICT dwork2)286 static int c_ekkscmv(COIN_REGISTER const EKKfactinfo *COIN_RESTRICT2 fact, int n, double *COIN_RESTRICT dwork, int *COIN_RESTRICT mptr,
287 double *COIN_RESTRICT dwork2)
288 {
289 double tolerance = fact->zeroTolerance;
290 int irow;
291 const int *COIN_RESTRICT mptrsave = mptr;
292 double *COIN_RESTRICT dwhere = dwork + 1;
293 if ((n & 1) != 0) {
294 if (NOT_ZERO(*dwhere)) {
295 if (fabs(*dwhere) >= tolerance) {
296 *++dwork2 = *dwhere;
297 *++mptr = SHIFT_INDEX(1);
298 } else {
299 *dwhere = 0.0;
300 }
301 }
302 dwhere++;
303 irow = 2;
304 } else {
305 irow = 1;
306 }
307 for (n = n >> 1; n; n--) {
308 int second = NOT_ZERO(*(dwhere + 1));
309 if (NOT_ZERO(*dwhere)) {
310 if (fabs(*dwhere) >= tolerance) {
311 *++dwork2 = *dwhere;
312 *++mptr = SHIFT_INDEX(irow);
313 } else {
314 *dwhere = 0.0;
315 }
316 }
317 if (second) {
318 if (fabs(*(dwhere + 1)) >= tolerance) {
319 *++dwork2 = *(dwhere + 1);
320 *++mptr = SHIFT_INDEX(irow + 1);
321 } else {
322 *(dwhere + 1) = 0.0;
323 }
324 }
325 dwhere += 2;
326 irow += 2;
327 }
328
329 return static_cast< int >(mptr - mptrsave);
330 } /* c_ekkscmv */
c_ekkputl(const EKKfactinfo * COIN_RESTRICT2 fact,const int * COIN_RESTRICT mpt2,double * COIN_RESTRICT dwork1,double del3,int nincol,int nuspik)331 double c_ekkputl(const EKKfactinfo *COIN_RESTRICT2 fact,
332 const int *COIN_RESTRICT mpt2,
333 double *COIN_RESTRICT dwork1,
334 double del3,
335 int nincol, int nuspik)
336 {
337 double *COIN_RESTRICT dwork3 = fact->xeeadr + fact->nnentu;
338 int *COIN_RESTRICT hrowi = fact->xeradr + fact->nnentu;
339 int offset = fact->R_etas_start[fact->nR_etas + 1];
340 int *COIN_RESTRICT hrowiR = fact->R_etas_index + offset;
341 double *COIN_RESTRICT dluval = fact->R_etas_element + offset;
342 int i, j;
343
344 /* dwork1 is r', the new R transform
345 * dwork3 is the updated incoming column, alpha_p
346 * del3 apparently has the pivot of the incoming column (???).
347 * Here, we compute the p'th element of R^-1 alpha_p
348 * (as described on p. 273), which is just a dot product.
349 * I don't know why we subtract.
350 */
351 for (i = 1; i <= nuspik; ++i) {
352 j = UNSHIFT_INDEX(hrowi[i]);
353 del3 -= dwork3[i] * dwork1[j];
354 }
355
356 /* here we finally copy the r' to where we want it, the end */
357 /* also take into account that the p'th row of R^-1 is -(p'th row of R). */
358 /* also zero out dwork1 as we go */
359 for (i = 0; i < nincol; ++i) {
360 j = mpt2[i];
361 hrowiR[-i] = SHIFT_INDEX(j);
362 dluval[-i] = -dwork1[j];
363 dwork1[j] = 0.;
364 }
365
366 return del3;
367 } /* c_ekkputl */
368 /* making this static seems to slow code down!
369 may be being inlined
370 */
c_ekkputl2(const EKKfactinfo * COIN_RESTRICT2 fact,double * COIN_RESTRICT dwork1,double * del3p,int nuspik)371 int c_ekkputl2(const EKKfactinfo *COIN_RESTRICT2 fact,
372 double *COIN_RESTRICT dwork1,
373 double *del3p,
374 int nuspik)
375 {
376 double *COIN_RESTRICT dwork3 = fact->xeeadr + fact->nnentu;
377 int *COIN_RESTRICT hrowi = fact->xeradr + fact->nnentu;
378 int offset = fact->R_etas_start[fact->nR_etas + 1];
379 int *COIN_RESTRICT hrowiR = fact->R_etas_index + offset;
380 double *COIN_RESTRICT dluval = fact->R_etas_element + offset;
381 int i, j;
382 #if 0
383 int nincol=c_ekksczr(fact,fact->nrow,dwork1,hrowiR);
384 #else
385 int nrow = fact->nrow;
386 const double tolerance = fact->zeroTolerance;
387 int *COIN_RESTRICT mptrX = hrowiR;
388 for (i = 1; i <= nrow; ++i) {
389 if (dwork1[i] != 0.) {
390 if (fabs(dwork1[i]) >= tolerance) {
391 *(mptrX--) = SHIFT_INDEX(i);
392 } else {
393 dwork1[i] = 0.0;
394 }
395 }
396 }
397 int nincol = static_cast< int >(hrowiR - mptrX);
398 #endif
399 double del3 = *del3p;
400 /* dwork1 is r', the new R transform
401 * dwork3 is the updated incoming column, alpha_p
402 * del3 apparently has the pivot of the incoming column (???).
403 * Here, we compute the p'th element of R^-1 alpha_p
404 * (as described on p. 273), which is just a dot product.
405 * I don't know why we subtract.
406 */
407 for (i = 1; i <= nuspik; ++i) {
408 j = UNSHIFT_INDEX(hrowi[i]);
409 del3 -= dwork3[i] * dwork1[j];
410 }
411
412 /* here we finally copy the r' to where we want it, the end */
413 /* also take into account that the p'th row of R^-1 is -(p'th row of R). */
414 /* also zero out dwork1 as we go */
415 for (i = 0; i < nincol; ++i) {
416 j = UNSHIFT_INDEX(hrowiR[-i]);
417 dluval[-i] = -dwork1[j];
418 dwork1[j] = 0.;
419 }
420
421 *del3p = del3;
422 return nincol;
423 } /* c_ekkputl */
c_ekkbtj4p_no_dense(const int nrow,const double * COIN_RESTRICT dluval,const int * COIN_RESTRICT hrowi,const int * COIN_RESTRICT mcstrt,double * COIN_RESTRICT dwork1,int ndo,int jpiv)424 static void c_ekkbtj4p_no_dense(const int nrow, const double *COIN_RESTRICT dluval,
425 const int *COIN_RESTRICT hrowi,
426 const int *COIN_RESTRICT mcstrt,
427 double *COIN_RESTRICT dwork1, int ndo, int jpiv)
428 {
429 int i;
430 double dv1;
431 int iel;
432 int irow;
433 int i1, i2;
434
435 /* count down to first nonzero */
436 for (i = nrow; i >= 1; i--) {
437 if (dwork1[i]) {
438 break;
439 }
440 }
441 i--; /* as pivot is just 1.0 */
442 if (i > ndo + jpiv) {
443 i = ndo + jpiv;
444 }
445 mcstrt -= jpiv;
446 i2 = mcstrt[i + 1];
447 for (; i > jpiv; --i) {
448 double dv1b = 0.0;
449 int nel;
450 i1 = mcstrt[i];
451 nel = i1 - i2;
452 dv1 = dwork1[i];
453 iel = i2;
454 if ((nel & 1) != 0) {
455 irow = hrowi[iel];
456 dv1b = SHIFT_REF(dwork1, irow) * dluval[iel];
457 iel++;
458 }
459 for (; iel < i1; iel += 2) {
460 int irow = hrowi[iel];
461 int irowb = hrowi[iel + 1];
462 dv1 += SHIFT_REF(dwork1, irow) * dluval[iel];
463 dv1b += SHIFT_REF(dwork1, irowb) * dluval[iel + 1];
464 }
465 i2 = i1;
466 dwork1[i] = dv1 + dv1b;
467 }
468 } /* c_ekkbtj4 */
469
c_ekkbtj4p_dense(const int nrow,const double * COIN_RESTRICT dluval,const int * COIN_RESTRICT hrowi,const int * COIN_RESTRICT mcstrt,double * COIN_RESTRICT dwork1,int ndenuc,int ndo,int jpiv)470 static int c_ekkbtj4p_dense(const int nrow, const double *COIN_RESTRICT dluval,
471 const int *COIN_RESTRICT hrowi,
472 const int *COIN_RESTRICT mcstrt, double *COIN_RESTRICT dwork1,
473 int ndenuc,
474 int ndo, int jpiv)
475 {
476 int i;
477 int i2;
478
479 int last = ndo - ndenuc + 1;
480 double *COIN_RESTRICT densew = &dwork1[nrow - 1];
481 int nincol = 0;
482 const double *COIN_RESTRICT dlu1;
483 dluval--;
484 hrowi--;
485 /* count down to first nonzero */
486 for (i = nrow; i >= 1; i--) {
487 if (dwork1[i]) {
488 break;
489 }
490 }
491 if (i < ndo + jpiv) {
492 int diff = ndo + jpiv - i;
493 ndo -= diff;
494 densew -= diff;
495 nincol = diff;
496 }
497 i2 = mcstrt[ndo + 1];
498 dlu1 = &dluval[i2 + 1];
499 for (i = ndo; i > last; i -= 2) {
500 int k;
501 double dv1, dv2;
502 const double *COIN_RESTRICT dlu2;
503 dv1 = densew[1];
504 dlu2 = dlu1 + nincol;
505 dv2 = densew[0];
506 for (k = 0; k < nincol; k++) {
507 #ifdef DEBUG
508 int kk = dlu1 - dluval;
509 int jj = (densew + (nincol - k + 1)) - dwork1;
510 int ll = hrowi[k + kk];
511 if (ll != jj)
512 abort();
513 #endif
514 dv1 += densew[nincol - k + 1] * dlu1[k];
515 dv2 += densew[nincol - k + 1] * dlu2[k];
516 }
517 densew[1] = dv1;
518 dlu1 = dlu2 + nincol;
519 dv2 += dv1 * dlu1[0];
520 dlu1++;
521 nincol += 2;
522 densew[0] = dv2;
523 densew -= 2;
524 }
525 return i;
526 } /* c_ekkbtj4 */
527
c_ekkbtj4p_after_dense(const double * COIN_RESTRICT dluval,const int * COIN_RESTRICT hrowi,const int * COIN_RESTRICT mcstrt,double * COIN_RESTRICT dwork1,int i,int jpiv)528 static void c_ekkbtj4p_after_dense(const double *COIN_RESTRICT dluval,
529 const int *COIN_RESTRICT hrowi,
530 const int *COIN_RESTRICT mcstrt,
531 double *COIN_RESTRICT dwork1, int i, int jpiv)
532 {
533 int iel;
534 mcstrt -= jpiv;
535 i += jpiv;
536 iel = mcstrt[i + 1];
537 for (; i > jpiv + 1; i -= 2) {
538 int i1 = mcstrt[i];
539 double dv1 = dwork1[i];
540 double dv2;
541 for (; iel < i1; iel++) {
542 int irow = hrowi[iel];
543 dv1 += SHIFT_REF(dwork1, irow) * dluval[iel];
544 }
545 i1 = mcstrt[i - 1];
546 dv2 = dwork1[i - 1];
547 dwork1[i] = dv1;
548 for (; iel < i1; iel++) {
549 int irow = hrowi[iel];
550 dv2 += SHIFT_REF(dwork1, irow) * dluval[iel];
551 }
552 dwork1[i - 1] = dv2;
553 }
554 if (i > jpiv) {
555 int i1 = mcstrt[i];
556 double dv1 = dwork1[i];
557 for (; iel < i1; iel++) {
558 int irow = hrowi[iel];
559 dv1 += SHIFT_REF(dwork1, irow) * dluval[iel];
560 }
561 dwork1[i] = dv1;
562 }
563 }
564
c_ekkbtj4p(COIN_REGISTER const EKKfactinfo * COIN_RESTRICT2 fact,double * COIN_RESTRICT dwork1)565 static void c_ekkbtj4p(COIN_REGISTER const EKKfactinfo *COIN_RESTRICT2 fact,
566 double *COIN_RESTRICT dwork1)
567 {
568 int lstart = fact->lstart;
569 const int *COIN_RESTRICT hpivco = fact->kcpadr;
570 const double *COIN_RESTRICT dluval = fact->xeeadr + 1;
571 const int *COIN_RESTRICT hrowi = fact->xeradr + 1;
572 const int *COIN_RESTRICT mcstrt = fact->xcsadr + lstart - 1;
573 int jpiv = hpivco[lstart] - 1;
574 int ndo = fact->xnetalval;
575 /* see if dense enough to unroll */
576 if (fact->ndenuc < 5) {
577 c_ekkbtj4p_no_dense(fact->nrow, dluval, hrowi, mcstrt, dwork1, ndo, jpiv);
578 } else {
579 int i = c_ekkbtj4p_dense(fact->nrow, dluval, hrowi, mcstrt, dwork1,
580 fact->ndenuc, ndo, jpiv);
581 c_ekkbtj4p_after_dense(dluval, hrowi, mcstrt, dwork1, i, jpiv);
582 }
583 } /* c_ekkbtj4p */
584
c_ekkbtj4_sparse(COIN_REGISTER2 const EKKfactinfo * COIN_RESTRICT2 fact,double * COIN_RESTRICT dwork1,int * COIN_RESTRICT mpt,double * COIN_RESTRICT dworko,int nincol,int * COIN_RESTRICT spare)585 static int c_ekkbtj4_sparse(COIN_REGISTER2 const EKKfactinfo *COIN_RESTRICT2 fact,
586 double *COIN_RESTRICT dwork1,
587 int *COIN_RESTRICT mpt, /* C style */
588 double *COIN_RESTRICT dworko,
589 int nincol, int *COIN_RESTRICT spare)
590 {
591 const int nrow = fact->nrow;
592 const int *COIN_RESTRICT hcoli = fact->xecadr;
593 const int *COIN_RESTRICT mrstrt = fact->xrsadr + nrow;
594 char *COIN_RESTRICT nonzero = fact->nonzero;
595 const int *COIN_RESTRICT hpivro = fact->krpadr;
596 const double *COIN_RESTRICT de2val = fact->xe2adr - 1;
597 double tolerance = fact->zeroTolerance;
598 double dv;
599 int iel;
600
601 int k, nStack, kx;
602 int nList = 0;
603 int *COIN_RESTRICT list = spare;
604 int *COIN_RESTRICT stack = spare + nrow;
605 int *COIN_RESTRICT next = stack + nrow;
606 int iPivot, kPivot;
607 int iput, nput = 0, kput = nrow;
608 int j;
609 int firstDoRow = fact->firstDoRow;
610
611 for (k = 0; k < nincol; k++) {
612 nStack = 1;
613 iPivot = mpt[k];
614 if (nonzero[iPivot] != 1 && iPivot >= firstDoRow) {
615 stack[0] = iPivot;
616 next[0] = mrstrt[iPivot];
617 while (nStack) {
618 /* take off stack */
619 kPivot = stack[--nStack];
620 if (nonzero[kPivot] != 1 && kPivot >= firstDoRow) {
621 j = next[nStack];
622 if (j == mrstrt[kPivot + 1]) {
623 /* finished so mark */
624 list[nList++] = kPivot;
625 nonzero[kPivot] = 1;
626 } else {
627 kPivot = hcoli[j];
628 /* put back on stack */
629 next[nStack++]++;
630 if (!nonzero[kPivot]) {
631 /* and new one */
632 stack[nStack] = kPivot;
633 nonzero[kPivot] = 2;
634 next[nStack++] = mrstrt[kPivot];
635 }
636 }
637 } else if (kPivot < firstDoRow) {
638 list[--kput] = kPivot;
639 nonzero[kPivot] = 1;
640 }
641 }
642 } else if (nonzero[iPivot] != 1) {
643 /* nothing to do (except check size at end) */
644 list[--kput] = iPivot;
645 nonzero[iPivot] = 1;
646 }
647 }
648 if (fact->packedMode) {
649 dworko++;
650 for (k = nList - 1; k >= 0; k--) {
651 double dv;
652 iPivot = list[k];
653 dv = dwork1[iPivot];
654 dwork1[iPivot] = 0.0;
655 nonzero[iPivot] = 0;
656 if (fabs(dv) > tolerance) {
657 iput = hpivro[iPivot];
658 kx = mrstrt[iPivot];
659 dworko[nput] = dv;
660 for (iel = kx; iel < mrstrt[iPivot + 1]; iel++) {
661 double dval;
662 int irow = hcoli[iel];
663 dval = de2val[iel];
664 dwork1[irow] += dv * dval;
665 }
666 mpt[nput++] = iput - 1;
667 } else {
668 dwork1[iPivot] = 0.0; /* force to zero, not just near zero */
669 }
670 }
671 /* check remainder */
672 for (k = kput; k < nrow; k++) {
673 iPivot = list[k];
674 nonzero[iPivot] = 0;
675 dv = dwork1[iPivot];
676 dwork1[iPivot] = 0.0;
677 iput = hpivro[iPivot];
678 if (fabs(dv) > tolerance) {
679 dworko[nput] = dv;
680 mpt[nput++] = iput - 1;
681 }
682 }
683 } else {
684 /* not packed */
685 for (k = nList - 1; k >= 0; k--) {
686 double dv;
687 iPivot = list[k];
688 dv = dwork1[iPivot];
689 dwork1[iPivot] = 0.0;
690 nonzero[iPivot] = 0;
691 if (fabs(dv) > tolerance) {
692 iput = hpivro[iPivot];
693 kx = mrstrt[iPivot];
694 dworko[iput] = dv;
695 for (iel = kx; iel < mrstrt[iPivot + 1]; iel++) {
696 double dval;
697 int irow = hcoli[iel];
698 dval = de2val[iel];
699 dwork1[irow] += dv * dval;
700 }
701 mpt[nput++] = iput - 1;
702 } else {
703 dwork1[iPivot] = 0.0; /* force to zero, not just near zero */
704 }
705 }
706 /* check remainder */
707 for (k = kput; k < nrow; k++) {
708 iPivot = list[k];
709 nonzero[iPivot] = 0;
710 dv = dwork1[iPivot];
711 dwork1[iPivot] = 0.0;
712 iput = hpivro[iPivot];
713 if (fabs(dv) > tolerance) {
714 dworko[iput] = dv;
715 mpt[nput++] = iput - 1;
716 }
717 }
718 }
719
720 return (nput);
721 } /* c_ekkbtj4 */
722
c_ekkbtjl(COIN_REGISTER2 const EKKfactinfo * COIN_RESTRICT2 fact,double * COIN_RESTRICT dwork1)723 static void c_ekkbtjl(COIN_REGISTER2 const EKKfactinfo *COIN_RESTRICT2 fact,
724 double *COIN_RESTRICT dwork1)
725 {
726 int i, j, k, k1;
727 int l1;
728 const double *COIN_RESTRICT dluval = fact->R_etas_element;
729 const int *COIN_RESTRICT hrowi = fact->R_etas_index;
730 const int *COIN_RESTRICT mcstrt = fact->R_etas_start;
731 const int *COIN_RESTRICT hpivco = fact->hpivcoR;
732 int ndo = fact->nR_etas;
733 #ifndef UNROLL1
734 #define UNROLL1 4
735 #endif
736 #if UNROLL1 > 2
737 int l2;
738 #endif
739 int kn;
740 double dv;
741 int iel;
742 int ipiv;
743 int knext;
744
745 knext = mcstrt[ndo + 1];
746 #if UNROLL1 > 2
747 for (i = ndo; i > 0; --i) {
748 k1 = knext;
749 knext = mcstrt[i];
750 ipiv = hpivco[i];
751 dv = dwork1[ipiv];
752 /* fast floating */
753 k = knext - k1;
754 kn = k >> 2;
755 iel = k1 + 1;
756 if (dv != 0.) {
757 l1 = (k & 1) != 0;
758 l2 = (k & 2) != 0;
759 for (j = 1; j <= kn; j++) {
760 int irow0 = hrowi[iel + 0];
761 int irow1 = hrowi[iel + 1];
762 int irow2 = hrowi[iel + 2];
763 int irow3 = hrowi[iel + 3];
764 double dval0 = dv * dluval[iel + 0] + SHIFT_REF(dwork1, irow0);
765 double dval1 = dv * dluval[iel + 1] + SHIFT_REF(dwork1, irow1);
766 double dval2 = dv * dluval[iel + 2] + SHIFT_REF(dwork1, irow2);
767 double dval3 = dv * dluval[iel + 3] + SHIFT_REF(dwork1, irow3);
768 SHIFT_REF(dwork1, irow0) = dval0;
769 SHIFT_REF(dwork1, irow1) = dval1;
770 SHIFT_REF(dwork1, irow2) = dval2;
771 SHIFT_REF(dwork1, irow3) = dval3;
772 iel += 4;
773 }
774 if (l1) {
775 int irow0 = hrowi[iel];
776 SHIFT_REF(dwork1, irow0) += dv * dluval[iel];
777 ++iel;
778 }
779 if (l2) {
780 int irow0 = hrowi[iel + 0];
781 int irow1 = hrowi[iel + 1];
782 SHIFT_REF(dwork1, irow0) += dv * dluval[iel];
783 SHIFT_REF(dwork1, irow1) += dv * dluval[iel + 1];
784 }
785 }
786 }
787 #else
788 for (i = ndo; i > 0; --i) {
789 k1 = knext;
790 knext = mcstrt[i];
791 ipiv = hpivco[i];
792 dv = dwork1[ipiv];
793 k = knext - k1;
794 kn = k >> 1;
795 iel = k1 + 1;
796 if (dv != 0.) {
797 l1 = (k & 1) != 0;
798 for (j = 1; j <= kn; j++) {
799 int irow0 = hrowi[iel + 0];
800 int irow1 = hrowi[iel + 1];
801 double dval0 = dv * dluval[iel + 0] + SHIFT_REF(dwork1, irow0);
802 double dval1 = dv * dluval[iel + 1] + SHIFT_REF(dwork1, irow1);
803 SHIFT_REF(dwork1, irow0) = dval0;
804 SHIFT_REF(dwork1, irow1) = dval1;
805 iel += 2;
806 }
807 if (l1) {
808 int irow0 = hrowi[iel];
809 SHIFT_REF(dwork1, irow0) += dv * dluval[iel];
810 ++iel;
811 }
812 }
813 }
814 #endif
815 } /* c_ekkbtjl */
816
c_ekkbtjl_sparse(COIN_REGISTER2 const EKKfactinfo * COIN_RESTRICT2 fact,double * COIN_RESTRICT dwork1,int * COIN_RESTRICT mpt,int nincol)817 static int c_ekkbtjl_sparse(COIN_REGISTER2 const EKKfactinfo *COIN_RESTRICT2 fact,
818 double *COIN_RESTRICT dwork1,
819 int *COIN_RESTRICT mpt, int nincol)
820 {
821 const double *COIN_RESTRICT dluval = fact->R_etas_element;
822 const int *COIN_RESTRICT hrowi = fact->R_etas_index;
823 const int *COIN_RESTRICT mcstrt = fact->R_etas_start;
824 const int *COIN_RESTRICT hpivco = fact->hpivcoR;
825 char *COIN_RESTRICT nonzero = fact->nonzero;
826 int ndo = fact->nR_etas;
827 int i, j, k1;
828 double dv;
829 int ipiv;
830 int irow0, irow1;
831 int knext;
832 int number = nincol;
833
834 /* ------------------------------------------- */
835 /* adjust back */
836 hrowi++;
837 dluval++;
838
839 /* DO ANY ROW TRANSFORMATIONS */
840
841 /* Function Body */
842 knext = mcstrt[ndo + 1];
843 for (i = ndo; i > 0; --i) {
844 k1 = knext;
845 knext = mcstrt[i];
846 ipiv = hpivco[i];
847 dv = dwork1[ipiv];
848 if (dv) {
849 for (j = k1; j < knext - 1; j += 2) {
850 irow0 = hrowi[j];
851 irow1 = hrowi[j + 1];
852 SHIFT_REF(dwork1, irow0) += dv * dluval[j];
853 SHIFT_REF(dwork1, irow1) += dv * dluval[j + 1];
854 if (!nonzero[irow0]) {
855 nonzero[irow0] = 1;
856 mpt[++number] = UNSHIFT_INDEX(irow0);
857 }
858 if (!nonzero[irow1]) {
859 nonzero[irow1] = 1;
860 mpt[++number] = UNSHIFT_INDEX(irow1);
861 }
862 }
863 if (j < knext) {
864 irow0 = hrowi[j];
865 SHIFT_REF(dwork1, irow0) += dv * dluval[j];
866 if (!nonzero[irow0]) {
867 nonzero[irow0] = 1;
868 mpt[++number] = UNSHIFT_INDEX(irow0);
869 }
870 }
871 }
872 }
873 return (number);
874 } /* c_ekkbtjl */
875
c_ekkbtju_dense(const int nrow,const double * COIN_RESTRICT dluval,const int * COIN_RESTRICT hrowi,const int * COIN_RESTRICT mcstrt,int * COIN_RESTRICT hpivco,double * COIN_RESTRICT dwork1,int * COIN_RESTRICT start,int last,int offset,double * COIN_RESTRICT densew)876 static void c_ekkbtju_dense(const int nrow,
877 const double *COIN_RESTRICT dluval,
878 const int *COIN_RESTRICT hrowi,
879 const int *COIN_RESTRICT mcstrt,
880 int *COIN_RESTRICT hpivco,
881 double *COIN_RESTRICT dwork1,
882 int *COIN_RESTRICT start, int last, int offset,
883 double *COIN_RESTRICT densew)
884 {
885 /* Local variables */
886 int ipiv1, ipiv2;
887 int save = hpivco[last];
888
889 hpivco[last] = nrow + 1;
890
891 ipiv1 = *start;
892 ipiv2 = hpivco[ipiv1];
893 while (ipiv2 < last) {
894 int iel, k;
895 const int kx1 = mcstrt[ipiv1];
896 const int kx2 = mcstrt[ipiv2];
897 const int nel1 = hrowi[kx1 - 1];
898 const int nel2 = hrowi[kx2 - 1];
899 const double dpiv1 = dluval[kx1 - 1];
900 const double dpiv2 = dluval[kx2 - 1];
901 const int n1 = offset + ipiv1; /* number in dense part */
902 const int nsparse1 = nel1 - n1;
903 const int nsparse2 = nel2 - n1 - (ipiv2 - ipiv1);
904 const int k1 = kx1 + nsparse1;
905 const int k2 = kx2 + nsparse2;
906 const double *dlu1 = &dluval[k1];
907 const double *dlu2 = &dluval[k2];
908
909 double dv1 = dwork1[ipiv1];
910 double dv2 = dwork1[ipiv2];
911
912 for (iel = kx1; iel < k1; ++iel) {
913 dv1 -= SHIFT_REF(dwork1, hrowi[iel]) * dluval[iel];
914 }
915 for (iel = kx2; iel < k2; ++iel) {
916 dv2 -= SHIFT_REF(dwork1, hrowi[iel]) * dluval[iel];
917 }
918 for (k = 0; k < n1; k++) {
919 dv1 -= dlu1[k] * densew[k];
920 dv2 -= dlu2[k] * densew[k];
921 }
922 dv1 *= dpiv1;
923 dv2 -= dlu2[n1] * dv1;
924 dwork1[ipiv1] = dv1;
925 dwork1[ipiv2] = dv2 * dpiv2;
926 ipiv1 = hpivco[ipiv2];
927 ipiv2 = hpivco[ipiv1];
928 }
929 hpivco[last] = save;
930
931 *start = ipiv1;
932 return;
933 }
934 /* about 8-10% of execution time is spent in this routine */
c_ekkbtju_aux(const double * COIN_RESTRICT dluval,const int * COIN_RESTRICT hrowi,const int * COIN_RESTRICT mcstrt,const int * COIN_RESTRICT hpivco,double * COIN_RESTRICT dwork1,int ipiv,int loop_end)935 static int c_ekkbtju_aux(const double *COIN_RESTRICT dluval,
936 const int *COIN_RESTRICT hrowi,
937 const int *COIN_RESTRICT mcstrt,
938 const int *COIN_RESTRICT hpivco,
939 double *COIN_RESTRICT dwork1,
940 int ipiv, int loop_end)
941 {
942 #define UNROLL2 2
943 #ifndef UNROLL2
944 #if CLP_OSL == 2 || CLP_OSL == 3
945 #define UNROLL2 2
946 #else
947 #define UNROLL2 1
948 #endif
949 #endif
950 while (ipiv <= loop_end) {
951 int kx = mcstrt[ipiv];
952 const int nel = hrowi[kx - 1];
953 #if UNROLL2 < 2
954 const int kxe = kx + nel;
955 #endif
956
957 double dv = dwork1[ipiv]; /* rhs */
958 #if UNROLL2 > 1
959 const int *hrowi2 = hrowi + kx;
960 const int *hrowi2end = hrowi2 + nel;
961 const double *dluval2 = dluval + kx;
962 #else
963 int iel;
964 #endif
965 const double dpiv = dluval[kx - 1]; /* inverse of pivot */
966
967 /* subtract terms whose unknowns have been solved for */
968
969 /* a significant proportion of these loops may not modify dv at all.
970 * However, it seems to be just as expensive to check if the loop
971 * would modify dv as it is to just do it.
972 * The only difference would be that dluval wouldn't be referenced
973 * for those loops, would might save some cache paging,
974 * but unfortunately the code generated to search for zeros (on AIX)
975 * is *worse* than code that just multiplies by dval.
976 */
977 #if UNROLL2 < 2
978 for (iel = kx; iel < kxe; ++iel) {
979 const int irow = hrowi[iel];
980 const double dval = dluval[iel];
981 dv -= SHIFT_REF(dwork1, irow) * dval;
982 }
983
984 dwork1[ipiv] = dv * dpiv; /* divide by the pivot */
985 #else
986 if ((nel & 1) != 0) {
987 int irow = *hrowi2;
988 double dval = *dluval2;
989 dv -= SHIFT_REF(dwork1, irow) * dval;
990 hrowi2++;
991 dluval2++;
992 }
993 for (; hrowi2 < hrowi2end; hrowi2 += 2, dluval2 += 2) {
994 int irow0 = hrowi2[0];
995 int irow1 = hrowi2[1];
996 double dval0 = dluval2[0];
997 double dval1 = dluval2[1];
998 double d0 = SHIFT_REF(dwork1, irow0);
999 double d1 = SHIFT_REF(dwork1, irow1);
1000 dv -= d0 * dval0;
1001 dv -= d1 * dval1;
1002 }
1003 dwork1[ipiv] = dv * dpiv; /* divide by the pivot */
1004 #endif
1005
1006 ipiv = hpivco[ipiv];
1007 }
1008
1009 return (ipiv);
1010 }
1011
1012 /*
1013 * We are given the upper diagonal matrix U from the LU factorization
1014 * and a rhs dwork1.
1015 * This solves the system U x = dwork1
1016 * by back substitution, overwriting dwork1 with the solution x.
1017 *
1018 * It does this in textbook style by solving the equations "bottom" up,
1019 * so for each equation one new unknown is solved for by subtracting
1020 * from the rhs the sum of the terms whose unknowns have been solved for,
1021 * then dividing by the coefficient of the new unknown.
1022 *
1023 * Since we update the U matrix using F-T, the order of the columns
1024 * changes slightly each iteration. Initially, hpivco[i] == i+1,
1025 * and each iteration (generally) introduces one element where this
1026 * is no longer true. However, because we periodically refactorize,
1027 * it is much more common for hpivco[i] == i+1 than not.
1028 *
1029 * The one quirk is that value referred to as the pivot is actually
1030 * the reciprocal of the pivot, to avoid a division.
1031 *
1032 * Solving in this fashion is inappropriate if there are frequently
1033 * cases where all unknowns in an equation have value zero.
1034 * This seems to happen frequently if the sparsity of the rhs is, say, 10%.
1035 */
c_ekkbtju(COIN_REGISTER2 const EKKfactinfo * COIN_RESTRICT2 fact,double * COIN_RESTRICT dwork1,int ipiv)1036 static void c_ekkbtju(COIN_REGISTER2 const EKKfactinfo *COIN_RESTRICT2 fact,
1037 double *COIN_RESTRICT dwork1,
1038 int ipiv)
1039 {
1040 const int nrow = fact->nrow;
1041 double *COIN_RESTRICT dluval = fact->xeeadr;
1042 int *COIN_RESTRICT hrowi = fact->xeradr;
1043 int *COIN_RESTRICT mcstrt = fact->xcsadr;
1044 int *COIN_RESTRICT hpivco_new = fact->kcpadr + 1;
1045 int ndenuc = fact->ndenuc;
1046 int first_dense = fact->first_dense;
1047 int last_dense = fact->last_dense;
1048
1049 const int has_dense = (first_dense < last_dense && mcstrt[ipiv] <= mcstrt[last_dense]);
1050
1051 /* Parameter adjustments */
1052 /* dluval and hrowi were NOT decremented here.
1053 I believe that they are used as C-style arrays below.
1054 At this point, I am going to convert them from Fortran- to C-style
1055 here by incrementing them; at some later time, I will convert their
1056 uses in this file to Fortran-style.
1057 */
1058 dluval++;
1059 hrowi++;
1060
1061 if (has_dense)
1062 ipiv = c_ekkbtju_aux(dluval, hrowi, mcstrt, hpivco_new, dwork1, ipiv,
1063 first_dense - 1);
1064
1065 if (has_dense) {
1066 int n = 0;
1067 int firstDense = nrow - ndenuc + 1;
1068 double *densew = &dwork1[firstDense];
1069
1070 /* check first dense to see where in triangle it is */
1071 int last = first_dense;
1072 int j = mcstrt[last] - 1;
1073 int k1 = j;
1074 int k2 = j + hrowi[j];
1075
1076 for (j = k2; j > k1; j--) {
1077 int irow = UNSHIFT_INDEX(hrowi[j]);
1078 if (irow < firstDense) {
1079 break;
1080 } else {
1081 #ifdef DEBUG
1082 if (irow != last - 1) {
1083 abort();
1084 }
1085 #endif
1086 last = irow;
1087 n++;
1088 }
1089 }
1090 c_ekkbtju_dense(nrow, dluval, hrowi, mcstrt, const_cast< int * >(hpivco_new),
1091 dwork1, &ipiv, last_dense, n - first_dense, densew);
1092 }
1093
1094 (void)c_ekkbtju_aux(dluval, hrowi, mcstrt, hpivco_new, dwork1, ipiv, nrow);
1095 } /* c_ekkbtju */
1096
1097 /*
1098 * mpt / *nincolp contain the indices of nonzeros in dwork1.
1099 * nonzero contains the same information as a byte-mask.
1100 *
1101 * currently, erase_nonzero is true iff this is called from c_ekketsj.
1102 */
c_ekkbtju_sparse(COIN_REGISTER2 const EKKfactinfo * COIN_RESTRICT2 fact,double * COIN_RESTRICT dwork1,int * COIN_RESTRICT mpt,int nincol,int * COIN_RESTRICT spare)1103 static int c_ekkbtju_sparse(COIN_REGISTER2 const EKKfactinfo *COIN_RESTRICT2 fact,
1104 double *COIN_RESTRICT dwork1,
1105 int *COIN_RESTRICT mpt, int nincol,
1106 int *COIN_RESTRICT spare)
1107 {
1108 const double *COIN_RESTRICT dluval = fact->xeeadr + 1;
1109 const int *COIN_RESTRICT mcstrt = fact->xcsadr;
1110 char *COIN_RESTRICT nonzero = fact->nonzero;
1111 const int *COIN_RESTRICT hcoli = fact->xecadr;
1112 const int *COIN_RESTRICT mrstrt = fact->xrsadr;
1113 const int *COIN_RESTRICT hinrow = fact->xrnadr;
1114 const double *COIN_RESTRICT de2val = fact->xe2adr - 1;
1115 int i;
1116 int iPivot;
1117 int nList = 0;
1118 int nStack, k, kx;
1119 const int nrow = fact->nrow;
1120 const double tolerance = fact->zeroTolerance;
1121 int *COIN_RESTRICT list = spare;
1122 int *COIN_RESTRICT stack = spare + nrow;
1123 int *COIN_RESTRICT next = stack + nrow;
1124 /*
1125 * Examine all nonzero elements and determine which elements may be
1126 * nonzero in the result.
1127 * Any row in U that contains terms that may have nonzero variable values
1128 * may produce a nonzero value.
1129 */
1130 for (k = 0; k < nincol; k++) {
1131 nStack = 1;
1132 iPivot = mpt[k];
1133 stack[0] = iPivot;
1134 next[0] = 0;
1135 while (nStack) {
1136 int kPivot, ninrow, j;
1137 /* take off stack */
1138 kPivot = stack[--nStack];
1139 /*printf("nStack %d kPivot %d, ninrow %d, j %d, nList %d\n",
1140 nStack,kPivot,hinrow[kPivot],
1141 next[nStack],nList);*/
1142 if (nonzero[kPivot] != 1) {
1143 ninrow = hinrow[kPivot];
1144 j = next[nStack];
1145 if (j != ninrow) {
1146 kx = mrstrt[kPivot];
1147 kPivot = hcoli[kx + j];
1148 /* put back on stack */
1149 next[nStack++]++;
1150 if (!nonzero[kPivot]) {
1151 /* and new one */
1152 stack[nStack] = kPivot;
1153 nonzero[kPivot] = 2;
1154 next[nStack++] = 0;
1155 }
1156 } else {
1157 /* finished so mark */
1158 list[nList++] = kPivot;
1159 nonzero[kPivot] = 1;
1160 }
1161 }
1162 }
1163 }
1164
1165 i = nList - 1;
1166 nList = 0;
1167 for (; i >= 0; i--) {
1168 double dpiv;
1169 double dv;
1170 iPivot = list[i];
1171 kx = mcstrt[iPivot];
1172 dpiv = dluval[kx - 1];
1173 dv = dpiv * dwork1[iPivot];
1174 nonzero[iPivot] = 0;
1175 if (fabs(dv) >= tolerance) {
1176 int iel;
1177 int krx = mrstrt[iPivot];
1178 int krxe = krx + hinrow[iPivot];
1179 dwork1[iPivot] = dv;
1180 mpt[nList++] = iPivot;
1181 for (iel = krx; iel < krxe; iel++) {
1182 int irow0 = hcoli[iel];
1183 double dval = de2val[iel];
1184 dwork1[irow0] -= dv * dval;
1185 }
1186 } else {
1187 dwork1[iPivot] = 0.0;
1188 }
1189 }
1190
1191 return (nList);
1192 } /* c_ekkbtjuRow */
1193
1194 /*
1195 * dpermu is supposed to be zeroed on entry to this routine.
1196 * It is used as a working buffer.
1197 * The input vector dwork1 is permuted into dpermu, operated on,
1198 * and the answer is permuted back into dwork1, zeroing dpermu in
1199 * the process.
1200 */
1201 /*
1202 * nincol > 0 ==> mpt contains indices of non-zeros in dpermu
1203 *
1204 * first_nonzero contains index of first (last??)nonzero;
1205 * only used if nincol==0.
1206 *
1207 * dpermu contains permuted input; dwork1 is now zero
1208 */
c_ekkbtrn(COIN_REGISTER3 const EKKfactinfo * COIN_RESTRICT2 fact,double * COIN_RESTRICT dwork1,int * COIN_RESTRICT mpt,int first_nonzero)1209 int c_ekkbtrn(COIN_REGISTER3 const EKKfactinfo *COIN_RESTRICT2 fact,
1210 double *COIN_RESTRICT dwork1,
1211 int *COIN_RESTRICT mpt, int first_nonzero)
1212 {
1213 double *COIN_RESTRICT dpermu = fact->kadrpm;
1214 const int *COIN_RESTRICT mpermu = fact->mpermu;
1215 const int *COIN_RESTRICT hpivco_new = fact->kcpadr + 1;
1216
1217 const int nrow = fact->nrow;
1218 int i;
1219 int nincol;
1220 /* find the first non-zero input */
1221 int ipiv;
1222 if (first_nonzero) {
1223 ipiv = first_nonzero;
1224 #if 1
1225 if (c_ekk_IsSet(fact->bitArray, ipiv)) {
1226 /* slack */
1227 int lastSlack = fact->lastSlack;
1228 int firstDo = hpivco_new[lastSlack];
1229 assert(dpermu[ipiv]);
1230 while (ipiv != firstDo) {
1231 assert(c_ekk_IsSet(fact->bitArray, ipiv));
1232 if (dpermu[ipiv])
1233 dpermu[ipiv] = -dpermu[ipiv];
1234 ipiv = hpivco_new[ipiv];
1235 }
1236 }
1237 #endif
1238 } else {
1239 int lastSlack = fact->numberSlacks;
1240 ipiv = hpivco_new[0];
1241 for (i = 0; i < lastSlack; i++) {
1242 int next_piv = hpivco_new[ipiv];
1243 assert(c_ekk_IsSet(fact->bitArray, ipiv));
1244 if (dpermu[ipiv]) {
1245 break;
1246 } else {
1247 ipiv = next_piv;
1248 }
1249 }
1250
1251 /* usually, there is a non-zero slack entry... */
1252 if (i == lastSlack) {
1253 /* but if there isn't... */
1254 for (; i < nrow; i++) {
1255 if (!dpermu[ipiv]) {
1256 ipiv = hpivco_new[ipiv];
1257 } else {
1258 break;
1259 }
1260 }
1261 } else {
1262 /* reverse signs for slacks */
1263 for (; i < lastSlack; i++) {
1264 assert(c_ekk_IsSet(fact->bitArray, ipiv));
1265 if (dpermu[ipiv])
1266 dpermu[ipiv] = -dpermu[ipiv];
1267 ipiv = hpivco_new[ipiv];
1268 }
1269 assert(!c_ekk_IsSet(fact->bitArray, ipiv) || ipiv > fact->nrow);
1270
1271 /* this is presumably the first non-zero non slack */
1272 /*ipiv=firstDo;*/
1273 }
1274 }
1275 if (ipiv <= fact->nrow) {
1276 /* skipBtju is always (?) 0 first the first call,
1277 * ipiv tends to be >nrow for the second */
1278
1279 /* DO U */
1280 c_ekkbtju(fact, dpermu,
1281 ipiv);
1282 }
1283
1284 /* DO ROW ETAS IN L */
1285 c_ekkbtjl(fact, dpermu);
1286 c_ekkbtj4p(fact, dpermu);
1287
1288 /* dwork1[mpermu] = dpermu; dpermu = 0; mpt = indices of non-zeros */
1289 nincol = c_ekkshfpo_scan2zero(fact, &mpermu[1], dpermu, &dwork1[1], &mpt[1]);
1290
1291 /* dpermu should be zero now */
1292 #ifdef DEBUG
1293 for (i = 1; i <= nrow; i++) {
1294 if (dpermu[i]) {
1295 abort();
1296 } /* endif */
1297 } /* endfor */
1298 #endif
1299 return (nincol);
1300 } /* c_ekkbtrn */
1301
c_ekkbtrn0_new(COIN_REGISTER3 const EKKfactinfo * COIN_RESTRICT2 fact,double * COIN_RESTRICT dwork1,int * COIN_RESTRICT mpt,int nincol,int * COIN_RESTRICT spare)1302 static int c_ekkbtrn0_new(COIN_REGISTER3 const EKKfactinfo *COIN_RESTRICT2 fact,
1303 double *COIN_RESTRICT dwork1,
1304 int *COIN_RESTRICT mpt, int nincol,
1305 int *COIN_RESTRICT spare)
1306 {
1307 double *COIN_RESTRICT dpermu = fact->kadrpm;
1308 const int *COIN_RESTRICT mpermu = fact->mpermu;
1309 const int *COIN_RESTRICT hpivro = fact->krpadr;
1310
1311 const int nrow = fact->nrow;
1312
1313 int i;
1314 char *nonzero = fact->nonzero;
1315 int doSparse = 1;
1316
1317 /* so: dpermu must contain room for:
1318 * nrow doubles, followed by
1319 * nrow ints (mpermu), followed by
1320 * nrow ints (the inverse permutation), followed by
1321 * an unused area (?) of nrow ints, followed by
1322 * nrow chars (this non-zero array).
1323 *
1324 * and apparently the first nrow elements of nonzero are expected
1325 * to already be zero.
1326 */
1327 #ifdef DEBUG
1328 for (i = 1; i <= nrow; i++) {
1329 if (nonzero[i]) {
1330 abort();
1331 } /* endif */
1332 } /* endfor */
1333 #endif
1334 /* now nonzero[i]==1 iff there is an entry for i in mpt */
1335
1336 nincol = c_ekkbtju_sparse(fact, dpermu,
1337 &mpt[1], nincol,
1338 spare);
1339
1340 /* the vector may have more nonzero elements now */
1341 /* DO ROW ETAS IN L */
1342 #define DENSE_THRESHOLD (nincol * 10 + 100)
1343 if (DENSE_THRESHOLD > nrow) {
1344 doSparse = 0;
1345 c_ekkbtjl(fact, dpermu);
1346 } else {
1347 /* set nonzero */
1348 for (i = 0; i < nincol; i++) {
1349 int j = mpt[i + 1];
1350 nonzero[j] = 1;
1351 }
1352 nincol = c_ekkbtjl_sparse(fact,
1353 dpermu,
1354 mpt,
1355 nincol);
1356 for (i = 0; i < nincol; i++) {
1357 int j = mpt[i + 1];
1358 nonzero[j] = 0;
1359 }
1360 if (DENSE_THRESHOLD > nrow) {
1361 doSparse = 0;
1362 #ifdef DEBUG
1363 for (i = 1; i <= nrow; i++) {
1364 if (nonzero[i]) {
1365 abort();
1366 }
1367 }
1368 #endif
1369 }
1370 }
1371 if (!doSparse) {
1372 c_ekkbtj4p(fact, dpermu);
1373 /* dwork1[mpermu] = dpermu; dpermu = 0; mpt = indices of non-zeros */
1374 nincol = c_ekkshfpo_scan2zero(fact, &mpermu[1], dpermu, &dwork1[1], &mpt[1]);
1375
1376 /* dpermu should be zero now */
1377 #ifdef DEBUG
1378 for (i = 1; i <= nrow; i++) {
1379 if (dpermu[i]) {
1380 abort();
1381 } /* endif */
1382 } /* endfor */
1383 #endif
1384 } else {
1385 /* still sparse */
1386 if (fact->nnentl) {
1387 nincol = c_ekkbtj4_sparse(fact,
1388 dpermu,
1389 &mpt[1],
1390 dwork1,
1391 nincol, spare);
1392 } else {
1393 double tolerance = fact->zeroTolerance;
1394 int irow;
1395 int nput = 0;
1396 if (fact->packedMode) {
1397 for (i = 0; i < nincol; i++) {
1398 int irow0;
1399 double dval;
1400 irow = mpt[i + 1];
1401 dval = dpermu[irow];
1402 if (NOT_ZERO(dval)) {
1403 if (fabs(dval) >= tolerance) {
1404 irow0 = hpivro[irow];
1405 dwork1[1 + nput] = dval;
1406 mpt[1 + nput++] = irow0 - 1;
1407 }
1408 dpermu[irow] = 0.0;
1409 }
1410 }
1411 } else {
1412 for (i = 0; i < nincol; i++) {
1413 int irow0;
1414 double dval;
1415 irow = mpt[i + 1];
1416 dval = dpermu[irow];
1417 if (NOT_ZERO(dval)) {
1418 if (fabs(dval) >= tolerance) {
1419 irow0 = hpivro[irow];
1420 dwork1[irow0] = dval;
1421 mpt[1 + nput++] = irow0 - 1;
1422 }
1423 dpermu[irow] = 0.0;
1424 }
1425 }
1426 }
1427 nincol = nput;
1428 }
1429 }
1430
1431 return (nincol);
1432 } /* c_ekkbtrn */
1433
1434 /* returns c_ekkbtrn(fact, dwork1, mpt)
1435 *
1436 * but since mpt[1..nincol] contains the indices of non-zeros in dwork1,
1437 * we can do faster.
1438 */
c_ekkbtrn_mpt(COIN_REGISTER3 const EKKfactinfo * COIN_RESTRICT2 fact,double * COIN_RESTRICT dwork1,int * COIN_RESTRICT mpt,int nincol,int * COIN_RESTRICT spare)1439 static int c_ekkbtrn_mpt(COIN_REGISTER3 const EKKfactinfo *COIN_RESTRICT2 fact,
1440 double *COIN_RESTRICT dwork1,
1441 int *COIN_RESTRICT mpt, int nincol, int *COIN_RESTRICT spare)
1442 {
1443 double *COIN_RESTRICT dpermu = fact->kadrpm;
1444 const int nrow = fact->nrow;
1445
1446 const int *COIN_RESTRICT mpermu = fact->mpermu;
1447 /*const int *mrstrt = fact->xrsadr;*/
1448
1449 #ifdef DEBUG
1450 int i;
1451 memset(spare, 'A', 3 * nrow * sizeof(int));
1452 {
1453
1454 for (i = 1; i <= nrow; i++) {
1455 if (dpermu[i]) {
1456 abort();
1457 }
1458 }
1459 }
1460 #endif
1461
1462 int i;
1463 #ifdef DEBUG
1464 for (i = 1; i <= nrow; i++) {
1465 if (fact->nonzero[i] || dpermu[i]) {
1466 abort();
1467 }
1468 }
1469 #endif
1470 assert(fact->if_sparse_update > 0 && mpt && fact->rows_ok);
1471
1472 /* read the input vector from mpt/dwork1;
1473 * permute it into dpermu;
1474 * construct a nonzero mask in nonzero;
1475 * overwrite mpt with the permuted indices;
1476 * clear the dwork1 vector.
1477 */
1478 for (i = 0; i < nincol; i++) {
1479 int irow = mpt[i + 1];
1480 int jrow = mpermu[irow];
1481 dpermu[jrow] = dwork1[irow];
1482 /*nonzero[jrow-1]=1; this is done in btrn0 */
1483 mpt[i + 1] = jrow;
1484 dwork1[irow] = 0.0;
1485 }
1486
1487 if (DENSE_THRESHOLD < nrow) {
1488 nincol = c_ekkbtrn0_new(fact, dwork1, mpt, nincol, spare);
1489 } else {
1490 nincol = c_ekkbtrn(fact, dwork1, mpt, 0);
1491 }
1492 #ifdef DEBUG
1493 {
1494
1495 for (i = 1; i <= nrow; i++) {
1496 if (dpermu[i]) {
1497 abort();
1498 }
1499 }
1500 if (fact->if_sparse_update > 0) {
1501 for (i = 1; i <= nrow; i++) {
1502 if (fact->nonzero[i]) {
1503 abort();
1504 }
1505 }
1506 }
1507 }
1508 #endif
1509 return nincol;
1510 }
1511
1512 /* returns c_ekkbtrn(fact, dwork1, mpt)
1513 *
1514 * but since (dwork1[i]!=0) == (i==ipivrw),
1515 * we can do faster.
1516 */
c_ekkbtrn_ipivrw(COIN_REGISTER3 const EKKfactinfo * COIN_RESTRICT2 fact,double * COIN_RESTRICT dwork1,int * COIN_RESTRICT mpt,int ipivrw,int * COIN_RESTRICT spare)1517 int c_ekkbtrn_ipivrw(COIN_REGISTER3 const EKKfactinfo *COIN_RESTRICT2 fact,
1518 double *COIN_RESTRICT dwork1,
1519 int *COIN_RESTRICT mpt, int ipivrw, int *COIN_RESTRICT spare)
1520 {
1521 double *COIN_RESTRICT dpermu = fact->kadrpm;
1522 const int nrow = fact->nrow;
1523
1524 const int *COIN_RESTRICT mpermu = fact->mpermu;
1525 const double *COIN_RESTRICT dluval = fact->xeeadr;
1526 const int *COIN_RESTRICT mrstrt = fact->xrsadr;
1527 const int *COIN_RESTRICT hinrow = fact->xrnadr;
1528 const int *COIN_RESTRICT hcoli = fact->xecadr;
1529 const int *COIN_RESTRICT mcstrt = fact->xcsadr;
1530
1531 int nincol;
1532
1533 #ifdef DEBUG
1534 int i;
1535 for (i = 1; i <= nrow; i++) {
1536 if (dpermu[i]) {
1537 abort();
1538 } /* endif */
1539 } /* endfor */
1540 #endif
1541
1542 if (fact->if_sparse_update > 0 && mpt && fact->rows_ok) {
1543 mpt[1] = ipivrw;
1544 nincol = c_ekkbtrn_mpt(fact, dwork1, mpt, 1, spare);
1545 } else {
1546 int ipiv;
1547 int kpivrw = mpermu[ipivrw];
1548 dpermu[kpivrw] = dwork1[ipivrw];
1549 dwork1[ipivrw] = 0.0;
1550
1551 if (fact->rows_ok) {
1552 /* !fact->if_sparse_update
1553 * but we still have rowwise info,
1554 * so we may as well use it to do the slack row
1555 */
1556 int iipivrw = nrow + 1;
1557 int itest = fact->nnentu + 1;
1558 int k = mrstrt[kpivrw];
1559 int lastInRow = k + hinrow[kpivrw];
1560 double dpiv, dv;
1561 for (; k < lastInRow; k++) {
1562 int icol = hcoli[k];
1563 int start = mcstrt[icol];
1564 if (start < itest) {
1565 iipivrw = icol;
1566 itest = start;
1567 }
1568 }
1569 /* do missed pivot */
1570 itest = mcstrt[kpivrw];
1571 dpiv = dluval[itest];
1572 dv = dpermu[kpivrw];
1573 dv *= dpiv;
1574 dpermu[kpivrw] = dv;
1575 ipiv = iipivrw;
1576 } else {
1577 /* no luck - c_ekkbtju will slog through slacks (?) */
1578 ipiv = kpivrw;
1579 }
1580 /* nincol not read */
1581 /* not sparse */
1582 /* do slacks */
1583 if (ipiv <= fact->nrow) {
1584 if (c_ekk_IsSet(fact->bitArray, ipiv)) {
1585 const int *hpivco_new = fact->kcpadr + 1;
1586 int lastSlack = fact->lastSlack;
1587 int firstDo = hpivco_new[lastSlack];
1588 /* slack */
1589 /* need pivot row of first nonslack */
1590 dpermu[ipiv] = -dpermu[ipiv];
1591 #ifndef NDEBUG
1592 while (1) {
1593 assert(c_ekk_IsSet(fact->bitArray, ipiv));
1594 ipiv = hpivco_new[ipiv];
1595 if (ipiv > fact->nrow || ipiv == firstDo)
1596 break;
1597 }
1598 assert(!c_ekk_IsSet(fact->bitArray, ipiv) || ipiv > fact->nrow);
1599 assert(ipiv == firstDo);
1600 #endif
1601 ipiv = firstDo;
1602 }
1603 }
1604 nincol = c_ekkbtrn(fact, dwork1, mpt, ipiv);
1605 }
1606
1607 return nincol;
1608 }
1609 /*
1610 * Does work associated with eq. 3.7:
1611 * r' = u' U^-1
1612 *
1613 * where u' (can't write the overbar) is the p'th row of U, without
1614 * the entry for column p. (here, jpivrw is p).
1615 * We solve this as for btju. We know
1616 * r' U = u'
1617 *
1618 * so we solve from low index to hi, determining the next value u_i'
1619 * by doing the dot-product of r' and the i'th column of U (excluding
1620 * element i itself), subtracting that from u'_i, and dividing by
1621 * U_ii (we store the reciprocal, so here we multiply).
1622 *
1623 * Now, in principle dwork1 should be initialized to the p'th row of U.
1624 * Instead, it is initially zeroed and filled in as we go along.
1625 * Of the entries in u' that we reference during a dot product with
1626 * a column of U, either
1627 * the entry is 0 by definition, since it is < p, or
1628 * it has already been set by a previous iteration, or
1629 * it is p.
1630 *
1631 * Because of this, we know that all elements < p will be zero;
1632 * that's why we start with p (kpivrw).
1633
1634 * While we do this product, we also zero out the p'th row.
1635 */
c_ekketju_aux(COIN_REGISTER2 EKKfactinfo * COIN_RESTRICT2 fact,int sparse,double * COIN_RESTRICT dluval,int * COIN_RESTRICT hrowi,const int * COIN_RESTRICT mcstrt,const int * COIN_RESTRICT hpivco,double * COIN_RESTRICT dwork1,int * ipivp,int jpivrw,int stop_col)1636 static void c_ekketju_aux(COIN_REGISTER2 EKKfactinfo *COIN_RESTRICT2 fact, int sparse,
1637 double *COIN_RESTRICT dluval, int *COIN_RESTRICT hrowi,
1638 const int *COIN_RESTRICT mcstrt, const int *COIN_RESTRICT hpivco,
1639 double *COIN_RESTRICT dwork1,
1640 int *ipivp, int jpivrw, int stop_col)
1641 {
1642 int ipiv = *ipivp;
1643 if (1 && ipiv < stop_col && c_ekk_IsSet(fact->bitArray, ipiv)) {
1644 /* slack */
1645 int lastSlack = fact->lastSlack;
1646 int firstDo = hpivco[lastSlack];
1647 while (1) {
1648 assert(c_ekk_IsSet(fact->bitArray, ipiv));
1649 dwork1[ipiv] = -dwork1[ipiv];
1650 ipiv = hpivco[ipiv]; /* next column - generally ipiv+1 */
1651 if (ipiv == firstDo || ipiv >= stop_col)
1652 break;
1653 }
1654 }
1655
1656 while (ipiv < stop_col) {
1657 double dv = dwork1[ipiv];
1658 int kx = mcstrt[ipiv];
1659 int nel = hrowi[kx];
1660 double dpiv = dluval[kx];
1661 int kcs = kx + 1;
1662 int kce = kx + nel;
1663 int iel;
1664
1665 for (iel = kcs; iel <= kce; ++iel) {
1666 int irow = hrowi[iel];
1667 irow = UNSHIFT_INDEX(irow);
1668 dv -= dwork1[irow] * dluval[iel];
1669 if (irow == jpivrw) {
1670 break;
1671 }
1672 }
1673
1674 /* assuming the p'th row is sparse,
1675 * this branch will be infrequently taken */
1676 if (iel <= kce) {
1677 int irow = hrowi[iel];
1678 /* irow == jpivrw */
1679 dv += dluval[iel];
1680
1681 if (sparse) {
1682 /* delete this entry by overwriting it with the last */
1683 --nel;
1684 hrowi[kx] = nel;
1685 hrowi[iel] = hrowi[kce];
1686 #ifdef CLP_REUSE_ETAS
1687 double temp = dluval[iel];
1688 dluval[iel] = dluval[kce];
1689 hrowi[kce] = jpivrw;
1690 dluval[kce] = temp;
1691 #else
1692 dluval[iel] = dluval[kce];
1693 #endif
1694 kce--;
1695 } else {
1696 /* we can't delete an entry from a dense column,
1697 * so we just zero it out */
1698 dluval[iel] = 0.0;
1699 iel++;
1700 }
1701
1702 /* finish up the remaining entries; same as above loop, but no check */
1703 for (; iel <= kce; ++iel) {
1704 irow = UNSHIFT_INDEX(hrowi[iel]);
1705 dv -= dwork1[irow] * dluval[iel];
1706 }
1707 }
1708 dwork1[ipiv] = dv * dpiv; /* divide by pivot */
1709 ipiv = hpivco[ipiv]; /* next column - generally ipiv+1 */
1710 }
1711
1712 /* ? is it guaranteed that ipiv==stop_col at this point?? */
1713 *ipivp = ipiv;
1714 }
1715
1716 /* dwork1 is assumed to be zeroed on entry */
c_ekketju(COIN_REGISTER EKKfactinfo * COIN_RESTRICT2 fact,double * dluval,int * hrowi,const int * COIN_RESTRICT mcstrt,const int * COIN_RESTRICT hpivco,double * COIN_RESTRICT dwork1,int kpivrw,int first_dense,int last_dense)1717 static void c_ekketju(COIN_REGISTER EKKfactinfo *COIN_RESTRICT2 fact, double *dluval, int *hrowi,
1718 const int *COIN_RESTRICT mcstrt, const int *COIN_RESTRICT hpivco,
1719 double *COIN_RESTRICT dwork1,
1720 int kpivrw, int first_dense, int last_dense)
1721 {
1722 int ipiv = hpivco[kpivrw];
1723 int jpivrw = SHIFT_INDEX(kpivrw);
1724
1725 const int nrow = fact->nrow;
1726
1727 if (first_dense < last_dense && mcstrt[ipiv] <= mcstrt[last_dense]) {
1728 /* There are dense columns, and
1729 * some dense columns precede the pivot column */
1730
1731 /* first do any sparse columns "on the left" */
1732 c_ekketju_aux(fact, true, dluval, hrowi, mcstrt, hpivco, dwork1,
1733 &ipiv, jpivrw, first_dense);
1734
1735 /* then do dense columns */
1736 c_ekketju_aux(fact, false, dluval, hrowi, mcstrt, hpivco, dwork1,
1737 &ipiv, jpivrw, last_dense + 1);
1738
1739 /* final sparse columns "on the right" ...*/
1740 }
1741 /* ...are the same as sparse columns if there are no dense */
1742 c_ekketju_aux(fact, true, dluval, hrowi, mcstrt, hpivco, dwork1,
1743 &ipiv, jpivrw, nrow + 1);
1744 } /* c_ekketju */
1745
1746 /*#define PRINT_DEBUG*/
1747 /* dwork1 is assumed to be zeroed on entry */
c_ekketsj(COIN_REGISTER2 EKKfactinfo * COIN_RESTRICT2 fact,double * COIN_RESTRICT dwork1,int * COIN_RESTRICT mpt2,double dalpha,int orig_nincol,int npivot,int * nuspikp,const int ipivrw,int * spare)1748 int c_ekketsj(COIN_REGISTER2 /*const*/ EKKfactinfo *COIN_RESTRICT2 fact,
1749 double *COIN_RESTRICT dwork1,
1750 int *COIN_RESTRICT mpt2, double dalpha, int orig_nincol,
1751 int npivot, int *nuspikp,
1752 const int ipivrw, int *spare)
1753 {
1754 int nuspik = *nuspikp;
1755
1756 int *COIN_RESTRICT mpermu = fact->mpermu;
1757
1758 int *COIN_RESTRICT hcoli = fact->xecadr;
1759 double *COIN_RESTRICT dluval = fact->xeeadr;
1760 int *COIN_RESTRICT mrstrt = fact->xrsadr;
1761 int *COIN_RESTRICT hrowi = fact->xeradr;
1762 int *COIN_RESTRICT mcstrt = fact->xcsadr;
1763 int *COIN_RESTRICT hinrow = fact->xrnadr;
1764 /*int *hincol = fact->xcnadr;
1765 int *hpivro = fact->krpadr;*/
1766 int *COIN_RESTRICT hpivco = fact->kcpadr;
1767 double *COIN_RESTRICT de2val = fact->xe2adr;
1768
1769 const int nrow = fact->nrow;
1770 const int ifRowCopy = fact->rows_ok;
1771
1772 int i, j = -1, k, i1, i2, k1;
1773 int kc, iel;
1774 double del3;
1775 int nroom;
1776 bool ifrows = (mrstrt[1] != 0);
1777 int kpivrw, jpivrw;
1778 int first_dense_mcstrt, last_dense_mcstrt;
1779 int nnentl; /* includes row stuff */
1780 int doSparse = (fact->if_sparse_update > 0);
1781 #ifdef MORE_DEBUG
1782 {
1783 const int *COIN_RESTRICT hrowi = fact->R_etas_index;
1784 const int *COIN_RESTRICT mcstrt = fact->R_etas_start;
1785 int ndo = fact->nR_etas;
1786 int knext;
1787
1788 knext = mcstrt[ndo + 1];
1789 for (int i = ndo; i > 0; --i) {
1790 int k1 = knext;
1791 knext = mcstrt[i];
1792 for (int j = k1 + 1; j < knext; j++) {
1793 assert(hrowi[j] > 0 && hrowi[j] < 100000);
1794 }
1795 }
1796 }
1797 #endif
1798
1799 int mcstrt_piv;
1800 int nincol = 0;
1801 int *COIN_RESTRICT hpivco_new = fact->kcpadr + 1;
1802 int *COIN_RESTRICT back = fact->back;
1803 int irtcod = 0;
1804
1805 /* Parameter adjustments */
1806 de2val--;
1807
1808 /* Function Body */
1809 if (!ifRowCopy) {
1810 doSparse = 0;
1811 fact->if_sparse_update = -abs(fact->if_sparse_update);
1812 }
1813 if (npivot == 1) {
1814 fact->num_resets = 0;
1815 }
1816 kpivrw = mpermu[ipivrw];
1817 #if 0 //ndef NDEBUG
1818 ets_count++;
1819 if (ets_check>=0&&ets_count>=ets_check) {
1820 printf("trouble\n");
1821 }
1822 #endif
1823 mcstrt_piv = mcstrt[kpivrw];
1824 /* ndenuc - top has number deleted */
1825 if (fact->ndenuc) {
1826 first_dense_mcstrt = mcstrt[fact->first_dense];
1827 last_dense_mcstrt = mcstrt[fact->last_dense];
1828 } else {
1829 first_dense_mcstrt = 0;
1830 last_dense_mcstrt = 0;
1831 }
1832 {
1833 int kdnspt = fact->nnetas - fact->nnentl;
1834
1835 i1 = ((kdnspt - 1) + fact->R_etas_start[fact->nR_etas + 1]);
1836 /*i1 = -99999999;*/
1837
1838 /* fact->R_etas_start[fact->nR_etas + 1] is -(the number of els in R) */
1839 nnentl = fact->nnetas - ((kdnspt - 1) + fact->R_etas_start[fact->nR_etas + 1]);
1840 }
1841 fact->demark = fact->nnentu + nnentl;
1842 jpivrw = SHIFT_INDEX(kpivrw);
1843
1844 #ifdef CLP_REUSE_ETAS
1845 double del3Orig = 0.0;
1846 #endif
1847 if (nuspik < 0) {
1848 goto L7000;
1849 } else if (nuspik == 0) {
1850 del3 = 0.;
1851 } else {
1852 del3 = 0.;
1853 i1 = fact->nnentu + 1;
1854 i2 = fact->nnentu + nuspik;
1855 if (fact->sortedEta) {
1856 /* binary search */
1857 if (hrowi[i2] == jpivrw) {
1858 /* sitting right on the end - easy */
1859 del3 = dluval[i2];
1860 --nuspik;
1861 } else {
1862 bool foundit = true;
1863
1864 /* binary search - sort of implies hrowi is sorted */
1865 i = i1;
1866 if (hrowi[i] != jpivrw) {
1867 while (1) {
1868 i = (i1 + i2) >> 1;
1869 if (i == i1) {
1870 foundit = false;
1871 break;
1872 }
1873 if (hrowi[i] < jpivrw) {
1874 i1 = i;
1875 } else if (hrowi[i] > jpivrw) {
1876 i2 = i;
1877 } else
1878 break;
1879 }
1880 }
1881 /* ??? what if we didn't find it? */
1882
1883 if (foundit) {
1884 del3 = dluval[i];
1885 --nuspik;
1886 /* remove it and move the last element into its place */
1887 hrowi[i] = hrowi[nuspik + fact->nnentu + 1];
1888 dluval[i] = dluval[nuspik + fact->nnentu + 1];
1889 }
1890 }
1891 } else {
1892 /* search */
1893 for (i = i1; i <= i2; i++) {
1894 if (hrowi[i] == jpivrw) {
1895 del3 = dluval[i];
1896 --nuspik;
1897 /* remove it and move the last element into its place */
1898 hrowi[i] = hrowi[i2];
1899 dluval[i] = dluval[i2];
1900 break;
1901 }
1902 }
1903 }
1904 }
1905 #ifdef CLP_REUSE_ETAS
1906 del3Orig = del3;
1907 #endif
1908
1909 /* OLD COLUMN POINTERS */
1910 /* **************************************************************** */
1911 if (!ifRowCopy) {
1912 /* old method */
1913 /* DO U */
1914 c_ekketju(fact, dluval, hrowi, mcstrt, hpivco_new,
1915 dwork1, kpivrw, fact->first_dense,
1916 fact->last_dense);
1917 } else {
1918
1919 /* could take out of old column but lets try being crude */
1920 /* try taking out */
1921 if (fact->xe2adr != 0 && doSparse) {
1922
1923 /*
1924 * There is both a column and row representation of U.
1925 * For each row in the kpivrw'th column of the col U rep,
1926 * find its position in the U row rep and remove it
1927 * by overwriting it with the last element.
1928 */
1929 int k1x = mcstrt[kpivrw];
1930 int nel = hrowi[k1x]; /* yes, this is the nel, for the pivot */
1931 int k2x = k1x + nel;
1932
1933 for (k = k1x + 1; k <= k2x; ++k) {
1934 int irow = UNSHIFT_INDEX(hrowi[k]);
1935 int kx = mrstrt[irow];
1936 int nel = hinrow[irow] - 1;
1937 hinrow[irow] = nel;
1938
1939 int jlast = kx + nel;
1940 for (int iel = kx; iel < jlast; iel++) {
1941 if (kpivrw == hcoli[iel]) {
1942 hcoli[iel] = hcoli[jlast];
1943 de2val[iel] = de2val[jlast];
1944 break;
1945 }
1946 }
1947 }
1948 } else if (ifRowCopy) {
1949 /* still take out */
1950 int k1x = mcstrt[kpivrw];
1951 int nel = hrowi[k1x]; /* yes, this is the nel, for the pivot */
1952 int k2x = k1x + nel;
1953
1954 for (k = k1x + 1; k <= k2x; ++k) {
1955 int irow = UNSHIFT_INDEX(hrowi[k]);
1956 int kx = mrstrt[irow];
1957 int nel = hinrow[irow] - 1;
1958 hinrow[irow] = nel;
1959 int jlast = kx + nel;
1960 for (; kx < jlast; kx++) {
1961 if (kpivrw == hcoli[kx]) {
1962 hcoli[kx] = hcoli[jlast];
1963 break;
1964 }
1965 }
1966 }
1967 }
1968
1969 /* add to row version */
1970 /* the updated column (alpha_p) was written to entries
1971 * nnentu+1..nnentu+nuspik by routine c_ekkftrn_ft.
1972 * That was just an intermediate value of the usual ftrn.
1973 */
1974 i1 = fact->nnentu + 1;
1975 i2 = fact->nnentu + nuspik;
1976 int *COIN_RESTRICT eta_last = mpermu + nrow * 2 + 3;
1977 int *COIN_RESTRICT eta_next = eta_last + nrow + 2;
1978 if (fact->xe2adr == 0 || !doSparse) {
1979 /* we have column indices by row, but not the actual values */
1980 for (iel = i1; iel <= i2; ++iel) {
1981 int irow = UNSHIFT_INDEX(hrowi[iel]);
1982 int iput = hinrow[irow];
1983 int kput = mrstrt[irow];
1984 int nextRow = eta_next[irow];
1985 assert(kput > 0);
1986 kput += iput;
1987 if (kput < mrstrt[nextRow]) {
1988 /* there is room - append the pivot column;
1989 * this corresponds making alpha_p the rightmost column of U (p. 268)*/
1990 hinrow[irow] = iput + 1;
1991 hcoli[kput] = kpivrw;
1992 } else {
1993 /* no room - switch off */
1994 doSparse = 0;
1995 /* possible kpivrw 1 */
1996 k1 = mrstrt[kpivrw];
1997 mrstrt[1] = -1;
1998 fact->rows_ok = false;
1999 goto L1226;
2000 }
2001 }
2002 } else {
2003 if (!doSparse) {
2004 /* we have both column indices and values by row */
2005 /* just like loop above, but with extra assign to de2val */
2006 for (iel = i1; iel <= i2; ++iel) {
2007 int irow = UNSHIFT_INDEX(hrowi[iel]);
2008 int iput = hinrow[irow];
2009 int kput = mrstrt[irow];
2010 int nextRow = eta_next[irow];
2011 assert(kput > 0);
2012 kput += iput;
2013 if (kput < mrstrt[nextRow]) {
2014 hinrow[irow] = iput + 1;
2015 hcoli[kput] = kpivrw;
2016 de2val[kput] = dluval[iel];
2017 } else {
2018 /* no room - switch off */
2019 doSparse = 0;
2020 /* possible kpivrw 1 */
2021 k1 = mrstrt[kpivrw];
2022 mrstrt[1] = -1;
2023 fact->rows_ok = false;
2024 goto L1226;
2025 }
2026 }
2027 } else {
2028 for (iel = i1; iel <= i2; ++iel) {
2029 int j, k;
2030 int irow = UNSHIFT_INDEX(hrowi[iel]);
2031 int iput = hinrow[irow];
2032 k = mrstrt[irow] + iput;
2033 j = eta_next[irow];
2034 if (k >= mrstrt[j]) {
2035 /* no room - can we make some? */
2036 int klast = eta_last[nrow + 1];
2037 int jput = mrstrt[klast] + hinrow[klast] + 2;
2038 int distance = mrstrt[nrow + 1] - jput;
2039 if (iput + 1 < distance) {
2040 /* this presumably copies the row to the end */
2041 int jn, jl;
2042 int kstart = mrstrt[irow];
2043 int nin = hinrow[irow];
2044 /* out */
2045 jn = eta_next[irow];
2046 jl = eta_last[irow];
2047 eta_next[jl] = jn;
2048 eta_last[jn] = jl;
2049 /* in */
2050 eta_next[klast] = irow;
2051 eta_last[nrow + 1] = irow;
2052 eta_last[irow] = klast;
2053 eta_next[irow] = nrow + 1;
2054 mrstrt[irow] = jput;
2055 #if 0
2056 memcpy(&hcoli[jput],&hcoli[kstart],nin*sizeof(int));
2057 memcpy(&de2val[jput],&de2val[kstart],nin*sizeof(double));
2058 #else
2059 c_ekkscpy(nin, hcoli + kstart, hcoli + jput);
2060 c_ekkdcpy(nin,
2061 (de2val + kstart), (de2val + jput));
2062 #endif
2063 k = jput + iput;
2064 } else {
2065 /* shuffle down */
2066 int spare = (fact->nnetas - fact->nnentu - fact->nnentl - 3);
2067 if (spare > nrow << 1) {
2068 /* presumbly, this compacts the rows */
2069 int jrow, jput;
2070 if (1) {
2071 if (fact->num_resets < 1000000) {
2072 int etasize = CoinMax(4 * fact->nnentu + (fact->nnetas - fact->nnentl) + 1000, fact->eta_size);
2073 if (ifrows) {
2074 fact->num_resets++;
2075 if (npivot > 40 && fact->num_resets << 4 > npivot) {
2076 fact->eta_size = static_cast< int >(1.05 * fact->eta_size);
2077 fact->num_resets = 1000000;
2078 }
2079 } else {
2080 fact->eta_size = static_cast< int >(1.1 * fact->eta_size);
2081 fact->num_resets = 1000000;
2082 }
2083 fact->eta_size = CoinMin(fact->eta_size, etasize);
2084 if (fact->maxNNetas > 0 && fact->eta_size > fact->maxNNetas) {
2085 fact->eta_size = fact->maxNNetas;
2086 }
2087 }
2088 }
2089 jrow = eta_next[0];
2090 jput = 1;
2091 for (j = 0; j < nrow; j++) {
2092 int k, nin = hinrow[jrow];
2093 k = mrstrt[jrow];
2094 mrstrt[jrow] = jput;
2095 for (; nin; nin--) {
2096 hcoli[jput] = hcoli[k];
2097 de2val[jput++] = de2val[k++];
2098 }
2099 jrow = eta_next[jrow];
2100 }
2101 if (spare > nrow << 3) {
2102 spare = 3;
2103 } else if (spare > nrow << 2) {
2104 spare = 1;
2105 } else {
2106 spare = 0;
2107 }
2108 jput += nrow * spare;
2109 ;
2110 jrow = eta_last[nrow + 1];
2111 for (j = 0; j < nrow; j++) {
2112 int k, nin = hinrow[jrow];
2113 k = mrstrt[jrow] + nin;
2114 jput -= spare;
2115 for (; nin; nin--) {
2116 hcoli[--jput] = hcoli[--k];
2117 de2val[jput] = de2val[k];
2118 }
2119 mrstrt[jrow] = jput;
2120 jrow = eta_last[jrow];
2121 }
2122 /* set up for copy below */
2123 k = mrstrt[irow] + iput;
2124 } else {
2125 /* no room - switch off */
2126 doSparse = 0;
2127 /* possible kpivrw 1 */
2128 k1 = mrstrt[kpivrw];
2129 mrstrt[1] = -1;
2130 fact->rows_ok = false;
2131 goto L1226;
2132 }
2133 }
2134 }
2135 /* now we have room - append the new value */
2136 hinrow[irow] = iput + 1;
2137 hcoli[k] = kpivrw;
2138 de2val[k] = dluval[iel];
2139 }
2140 }
2141 }
2142
2143 /* TAKE OUT ALL ELEMENTS IN PIVOT ROW */
2144 k1 = mrstrt[kpivrw];
2145
2146 L1226 : {
2147 int k2 = k1 + hinrow[kpivrw] - 1;
2148
2149 /* "delete" the row */
2150 hinrow[kpivrw] = 0;
2151 j = 0;
2152 if (doSparse) {
2153 /* remove pivot row entries from the corresponding columns */
2154 for (k = k1; k <= k2; ++k) {
2155 int icol = hcoli[k];
2156 int kx = mcstrt[icol];
2157 int nel = hrowi[kx];
2158 for (iel = kx + 1; iel <= kx + nel; iel++) {
2159 if (hrowi[iel] == jpivrw) {
2160 break;
2161 }
2162 }
2163 if (iel <= kx + nel) {
2164 /* this has to happen, right?? */
2165
2166 /* copy the element into a temporary */
2167 dwork1[icol] = dluval[iel];
2168 mpt2[nincol++] = icol;
2169 /*nonzero[icol-1]=1;*/
2170
2171 hrowi[kx] = nel - 1; /* column is shorter by one */
2172 j = 1;
2173 hrowi[iel] = hrowi[kx + nel];
2174 dluval[iel] = dluval[kx + nel];
2175 #ifdef CLP_REUSE_ETAS
2176 hrowi[kx + nel] = jpivrw;
2177 dluval[kx + nel] = dwork1[icol];
2178 #endif
2179 }
2180 }
2181 if (j != 0) {
2182 /* now compute r', the new R transform */
2183 orig_nincol = c_ekkbtju_sparse(fact, dwork1,
2184 mpt2, nincol,
2185 spare);
2186 dwork1[kpivrw] = 0.0;
2187 }
2188 } else {
2189 /* row version isn't ok (?) */
2190 for (k = k1; k <= k2; ++k) {
2191 int icol = hcoli[k];
2192 int kx = mcstrt[icol];
2193 int nel = hrowi[kx];
2194 j = kx + nel;
2195 int iel;
2196 for (iel = kx + 1; iel <= j; iel++) {
2197 if (hrowi[iel] == jpivrw)
2198 break;
2199 }
2200 dwork1[icol] = dluval[iel];
2201 if (kx < first_dense_mcstrt || kx > last_dense_mcstrt) {
2202 hrowi[kx] = nel - 1; /* shorten column */
2203 /* not packing - presumably column isn't sorted */
2204 hrowi[iel] = hrowi[j];
2205 dluval[iel] = dluval[j];
2206 #ifdef CLP_REUSE_ETAS
2207 hrowi[j] = jpivrw;
2208 dluval[j] = dwork1[icol];
2209 #endif
2210 } else {
2211 /* dense element - just zero it */
2212 dluval[iel] = 0.0;
2213 }
2214 }
2215 if (j != 0) {
2216 /* Find first nonzero */
2217 int ipiv = hpivco_new[kpivrw];
2218 while (ipiv <= nrow) {
2219 if (!dwork1[ipiv]) {
2220 ipiv = hpivco_new[ipiv];
2221 } else {
2222 break;
2223 }
2224 }
2225 if (ipiv <= nrow) {
2226 /* DO U */
2227 /* now compute r', the new R transform */
2228 c_ekkbtju(fact, dwork1,
2229 ipiv);
2230 }
2231 }
2232 }
2233 }
2234 }
2235
2236 if (kpivrw == fact->first_dense) {
2237 /* increase until valid pivot */
2238 fact->first_dense = hpivco_new[fact->first_dense];
2239 } else if (kpivrw == fact->last_dense) {
2240 fact->last_dense = back[fact->last_dense];
2241 }
2242 if (fact->first_dense == fact->last_dense) {
2243 fact->ndenuc = 0;
2244 fact->first_dense = 0;
2245 fact->last_dense = -1;
2246 }
2247 if (!(ifRowCopy && j == 0)) {
2248
2249 /* increase amount of work on Etas */
2250
2251 /* **************************************************************** */
2252 /* DO ROW ETAS IN L */
2253 {
2254 if (!doSparse) {
2255 dwork1[kpivrw] = 0.;
2256 #if 0
2257 orig_nincol=c_ekksczr(fact,nrow, dwork1, mpt2);
2258 del3=c_ekkputl(fact, mpt2, dwork1, del3,
2259 orig_nincol, nuspik);
2260 #else
2261 orig_nincol = c_ekkputl2(fact,
2262 dwork1, &del3,
2263 nuspik);
2264 #endif
2265 } else {
2266 del3 = c_ekkputl(fact, mpt2,
2267 dwork1, del3,
2268 orig_nincol, nuspik);
2269 }
2270 }
2271 if (orig_nincol != 0) {
2272 /* STORE AS A ROW VECTOR */
2273 int n = fact->nR_etas + 1;
2274 int i1 = fact->R_etas_start[n];
2275 fact->nR_etas = n;
2276 fact->R_etas_start[n + 1] = i1 - orig_nincol;
2277 hpivco[fact->nR_etas + nrow + 3] = kpivrw;
2278 }
2279 }
2280
2281 /* CHECK DEL3 AGAINST DALPHA/DOUT */
2282 {
2283 int kx = mcstrt[kpivrw];
2284 double dout = dluval[kx];
2285 double dcheck = fabs(dalpha / dout);
2286 double difference = 0.0;
2287 if (fabs(del3) > CoinMin(1.0e-8, fact->drtpiv * 0.99999)) {
2288 double checkTolerance;
2289 if (fact->npivots < 2) {
2290 checkTolerance = 1.0e-5;
2291 } else if (fact->npivots < 10) {
2292 checkTolerance = 1.0e-6;
2293 } else if (fact->npivots < 50) {
2294 checkTolerance = 1.0e-8;
2295 } else {
2296 checkTolerance = 1.0e-9;
2297 }
2298 difference = fabs(1.0 - fabs(del3) / dcheck);
2299 if (difference > 0.1 * checkTolerance) {
2300 if (difference < checkTolerance || (difference < 1.0e-7 && fact->npivots >= 50)) {
2301 irtcod = 1;
2302 #ifdef PRINT_DEBUG
2303 printf("mildly bad %g after %d pivots, etsj %g ftncheck %g ftnalpha %g\n",
2304 difference, fact->npivots, del3, dcheck, dalpha);
2305 #endif
2306 } else {
2307 irtcod = 2;
2308 #ifdef PRINT_DEBUG
2309 printf("bad %g after %d pivots, etsj %g ftncheck %g ftnalpha %g\n",
2310 difference, fact->npivots, del3, dcheck, dalpha);
2311 #endif
2312 }
2313 }
2314 } else {
2315 irtcod = 2;
2316 #ifdef PRINT_DEBUG
2317 printf("bad small %g after %d pivots, etsj %g ftncheck %g ftnalpha %g\n",
2318 difference, fact->npivots, del3, dcheck, dalpha);
2319 #endif
2320 }
2321 if (irtcod > 1)
2322 goto L8000;
2323 fact->npivots++;
2324 }
2325
2326 mcstrt[kpivrw] = fact->nnentu;
2327 #ifdef CLP_REUSE_ETAS
2328 {
2329 int *putSeq = fact->xrsadr + 2 * fact->nrowmx + 2;
2330 int *position = putSeq + fact->maxinv;
2331 int *putStart = position + fact->maxinv;
2332 putStart[fact->nrow + fact->npivots - 1] = fact->nnentu;
2333 }
2334 #endif
2335 dluval[fact->nnentu] = 1. / del3; /* new pivot */
2336 hrowi[fact->nnentu] = nuspik; /* new nelems */
2337 #ifndef NDEBUG
2338 {
2339 int lastSlack = fact->lastSlack;
2340 int firstDo = hpivco_new[lastSlack];
2341 int ipiv = hpivco_new[0];
2342 int now = fact->numberSlacks;
2343 if (now) {
2344 while (1) {
2345 if (ipiv > fact->nrow || ipiv == firstDo)
2346 break;
2347 assert(c_ekk_IsSet(fact->bitArray, ipiv));
2348 ipiv = hpivco_new[ipiv];
2349 }
2350 if (ipiv <= fact->nrow) {
2351 while (1) {
2352 if (ipiv > fact->nrow)
2353 break;
2354 assert(!c_ekk_IsSet(fact->bitArray, ipiv));
2355 ipiv = hpivco_new[ipiv];
2356 }
2357 }
2358 }
2359 }
2360 #endif
2361 {
2362 /* do new hpivco */
2363 int inext = hpivco_new[kpivrw];
2364 int iback = back[kpivrw];
2365 if (inext != nrow + 1) {
2366 int ilast = back[nrow + 1];
2367 hpivco_new[iback] = inext;
2368 back[inext] = iback;
2369 assert(hpivco_new[ilast] == nrow + 1);
2370 hpivco_new[ilast] = kpivrw;
2371 back[kpivrw] = ilast;
2372 hpivco_new[kpivrw] = nrow + 1;
2373 back[nrow + 1] = kpivrw;
2374 }
2375 }
2376 {
2377 int lastSlack = fact->lastSlack;
2378 int now = fact->numberSlacks;
2379 if (now && mcstrt_piv <= mcstrt[lastSlack]) {
2380 if (c_ekk_IsSet(fact->bitArray, kpivrw)) {
2381 /*printf("piv %d lastSlack %d\n",mcstrt_piv,lastSlack);*/
2382 fact->numberSlacks--;
2383 now--;
2384 /* one less slack */
2385 c_ekk_Unset(fact->bitArray, kpivrw);
2386 if (now && kpivrw == lastSlack) {
2387 int i;
2388 int ipiv;
2389 ipiv = hpivco_new[0];
2390 for (i = 0; i < now - 1; i++)
2391 ipiv = hpivco_new[ipiv];
2392 lastSlack = ipiv;
2393 assert(c_ekk_IsSet(fact->bitArray, ipiv));
2394 assert(!c_ekk_IsSet(fact->bitArray, hpivco_new[ipiv]) || hpivco_new[ipiv] > fact->nrow);
2395 fact->lastSlack = lastSlack;
2396 } else if (!now) {
2397 fact->lastSlack = 0;
2398 }
2399 }
2400 }
2401 fact->firstNonSlack = hpivco_new[lastSlack];
2402 #ifndef NDEBUG
2403 {
2404 int lastSlack = fact->lastSlack;
2405 int firstDo = hpivco_new[lastSlack];
2406 int ipiv = hpivco_new[0];
2407 int now = fact->numberSlacks;
2408 if (now) {
2409 while (1) {
2410 if (ipiv > fact->nrow || ipiv == firstDo)
2411 break;
2412 assert(c_ekk_IsSet(fact->bitArray, ipiv));
2413 ipiv = hpivco_new[ipiv];
2414 }
2415 if (ipiv <= fact->nrow) {
2416 while (1) {
2417 if (ipiv > fact->nrow)
2418 break;
2419 assert(!c_ekk_IsSet(fact->bitArray, ipiv));
2420 ipiv = hpivco_new[ipiv];
2421 }
2422 }
2423 }
2424 }
2425 #endif
2426 }
2427 fact->nnentu += nuspik;
2428 #ifdef CLP_REUSE_ETAS
2429 if (fact->first_dense >= fact->last_dense) {
2430 // save
2431 fact->nnentu++;
2432 dluval[fact->nnentu] = del3Orig;
2433 hrowi[fact->nnentu] = kpivrw;
2434 int *putSeq = fact->xrsadr + 2 * fact->nrowmx + 2;
2435 int *position = putSeq + fact->maxinv;
2436 int *putStart = position + fact->maxinv;
2437 int nnentu_at_factor = putStart[fact->nrow] & 0x7fffffff;
2438 //putStart[fact->nrow+fact->npivots]=fact->nnentu+1;
2439 int where;
2440 if (mcstrt_piv < nnentu_at_factor) {
2441 // original LU
2442 where = kpivrw - 1;
2443 } else {
2444 // could do binary search
2445 int *look = putStart + fact->nrow;
2446 for (where = fact->npivots - 1; where >= 0; where--) {
2447 if (mcstrt_piv == (look[where] & 0x7fffffff))
2448 break;
2449 }
2450 assert(where >= 0);
2451 where += fact->nrow;
2452 }
2453 position[fact->npivots - 1] = where;
2454 if (orig_nincol == 0) {
2455 // flag
2456 putStart[fact->nrow + fact->npivots - 1] |= 0x80000000;
2457 }
2458 }
2459 #endif
2460 {
2461 int kdnspt = fact->nnetas - fact->nnentl;
2462
2463 /* fact->R_etas_start[fact->nR_etas + 1] is -(the number of els in R) */
2464 nnentl = fact->nnetas - ((kdnspt - 1) + fact->R_etas_start[fact->nR_etas + 1]);
2465 }
2466 fact->demark = (fact->nnentu + nnentl) - fact->demark;
2467
2468 /* if need to redo row version */
2469 if (!fact->rows_ok && fact->first_dense >= fact->last_dense) {
2470 int extraSpace = 10000;
2471 int spareSpace;
2472 if (fact->if_sparse_update > 0) {
2473 spareSpace = (fact->nnetas - fact->nnentu - fact->nnentl);
2474 } else {
2475 /* missing out nnentl stuff */
2476 spareSpace = fact->nnetas - fact->nnentu;
2477 }
2478 /* save clean row copy if enough room */
2479 nroom = spareSpace / nrow;
2480
2481 if ((fact->nnentu << 3) > 150 * fact->maxinv) {
2482 extraSpace = 150 * fact->maxinv;
2483 } else {
2484 extraSpace = fact->nnentu << 3;
2485 }
2486
2487 ifrows = false;
2488 if (fact->nnetas > fact->nnentu + fact->nnentl + extraSpace) {
2489 ifrows = true;
2490 }
2491 if (nroom < 5) {
2492 ifrows = false;
2493 }
2494
2495 if (nroom > CoinMin(50, fact->maxinv - (fact->iterno - fact->iterin))) {
2496 ifrows = true;
2497 }
2498
2499 #ifdef PRINT_DEBUGx
2500 printf(" redoing row copy %d %d %d\n", ifrows, nroom, spareSpace);
2501 #endif
2502 if (1) {
2503 if (fact->num_resets < 1000000) {
2504 if (ifrows) {
2505 fact->num_resets++;
2506 if (npivot > 40 && fact->num_resets << 4 > npivot) {
2507 fact->eta_size = static_cast< int >(1.05 * fact->eta_size);
2508 fact->num_resets = 1000000;
2509 }
2510 } else {
2511 fact->eta_size = static_cast< int >(1.1 * fact->eta_size);
2512 fact->num_resets = 1000000;
2513 }
2514 if (fact->maxNNetas > 0 && fact->eta_size > fact->maxNNetas) {
2515 fact->eta_size = fact->maxNNetas;
2516 }
2517 }
2518 }
2519 fact->rows_ok = ifrows;
2520 if (ifrows) {
2521 int ibase = 1;
2522 c_ekkizero(nrow, &hinrow[1]);
2523 for (i = 1; i <= nrow; ++i) {
2524 int kx = mcstrt[i];
2525 int nel = hrowi[kx];
2526 int kcs = kx + 1;
2527 int kce = kx + nel;
2528 for (kc = kcs; kc <= kce; ++kc) {
2529 int irow = UNSHIFT_INDEX(hrowi[kc]);
2530 if (dluval[kc]) {
2531 hinrow[irow]++;
2532 }
2533 }
2534 }
2535 int *eta_last = mpermu + nrow * 2 + 3;
2536 int *eta_next = eta_last + nrow + 2;
2537 eta_next[0] = 1;
2538 for (i = 1; i <= nrow; ++i) {
2539 eta_next[i] = i + 1;
2540 eta_last[i] = i - 1;
2541 mrstrt[i] = ibase;
2542 ibase = ibase + hinrow[i] + nroom;
2543 hinrow[i] = 0;
2544 }
2545 eta_last[nrow + 1] = nrow;
2546 //eta_next[nrow+1]=nrow+2;
2547 mrstrt[nrow + 1] = ibase;
2548 if (fact->xe2adr == 0) {
2549 for (i = 1; i <= nrow; ++i) {
2550 int kx = mcstrt[i];
2551 int nel = hrowi[kx];
2552 int kcs = kx + 1;
2553 int kce = kx + nel;
2554 for (kc = kcs; kc <= kce; ++kc) {
2555 if (dluval[kc]) {
2556 int irow = UNSHIFT_INDEX(hrowi[kc]);
2557 int iput = hinrow[irow];
2558 assert(irow);
2559 hcoli[mrstrt[irow] + iput] = i;
2560 hinrow[irow] = iput + 1;
2561 }
2562 }
2563 }
2564 } else {
2565 for (i = 1; i <= nrow; ++i) {
2566 int kx = mcstrt[i];
2567 int nel = hrowi[kx];
2568 int kcs = kx + 1;
2569 int kce = kx + nel;
2570 for (kc = kcs; kc <= kce; ++kc) {
2571 int irow = UNSHIFT_INDEX(hrowi[kc]);
2572 int iput = hinrow[irow];
2573 hcoli[mrstrt[irow] + iput] = i;
2574 de2val[mrstrt[irow] + iput] = dluval[kc];
2575 hinrow[irow] = iput + 1;
2576 }
2577 }
2578 }
2579 } else {
2580 mrstrt[1] = 0;
2581 if (fact->if_sparse_update > 0 && fact->iterno - fact->iterin > 100) {
2582 goto L7000;
2583 }
2584 }
2585 }
2586 goto L8000;
2587
2588 /* OUT OF SPACE - COULD PACK DOWN */
2589 L7000:
2590 irtcod = 1;
2591 #ifdef PRINT_DEBUG
2592 printf(" out of space\n");
2593 #endif
2594 if (1) {
2595 if ((npivot << 3) < fact->nbfinv) {
2596 /* low on space */
2597 if (npivot < 10) {
2598 fact->eta_size = fact->eta_size << 1;
2599 } else {
2600 double ratio = fact->nbfinv;
2601 double ratio2 = npivot << 3;
2602 ratio = ratio / ratio2;
2603 if (ratio > 2.0) {
2604 ratio = 2.0;
2605 } /* endif */
2606 fact->eta_size = static_cast< int >(ratio * fact->eta_size);
2607 } /* endif */
2608 } else {
2609 fact->eta_size = static_cast< int >(1.05 * fact->eta_size);
2610 } /* endif */
2611 if (fact->maxNNetas > 0 && fact->eta_size > fact->maxNNetas) {
2612 fact->eta_size = fact->maxNNetas;
2613 }
2614 }
2615
2616 /* ================= IF ERROR SHOULD WE GET RID OF LAST ITERATION??? */
2617 L8000:
2618
2619 *nuspikp = nuspik;
2620 #ifdef MORE_DEBUG
2621 for (int i = 1; i <= fact->nrow; i++) {
2622 int kx = mcstrt[i];
2623 int nel = hrowi[kx];
2624 for (int j = 0; j < nel; j++) {
2625 assert(i != hrowi[j + kx + 1]);
2626 }
2627 }
2628 #endif
2629 #ifdef CLP_REUSE_ETAS
2630 fact->save_nnentu = fact->nnentu;
2631 #endif
2632 return (irtcod);
2633 } /* c_ekketsj */
c_ekkftj4p(COIN_REGISTER2 const EKKfactinfo * COIN_RESTRICT2 fact,double * COIN_RESTRICT dwork1,int firstNonZero)2634 static void c_ekkftj4p(COIN_REGISTER2 const EKKfactinfo *COIN_RESTRICT2 fact,
2635 double *COIN_RESTRICT dwork1, int firstNonZero)
2636 {
2637 /* this is where the L factors start, because this is the place
2638 * where c_ekktria starts laying them down (see initialization of xnetal).
2639 */
2640 int lstart = fact->lstart;
2641 const int *COIN_RESTRICT hpivco = fact->kcpadr;
2642 int firstLRow = hpivco[lstart];
2643 if (firstNonZero > firstLRow) {
2644 lstart += firstNonZero - firstLRow;
2645 }
2646 assert(firstLRow == fact->firstLRow);
2647 int jpiv = hpivco[lstart];
2648 const double *COIN_RESTRICT dluval = fact->xeeadr;
2649 const int *COIN_RESTRICT hrowi = fact->xeradr;
2650 const int *COIN_RESTRICT mcstrt = fact->xcsadr + lstart;
2651 int ndo = fact->xnetal - lstart;
2652 int i, iel;
2653
2654 /* find first non-zero */
2655 for (i = 0; i < ndo; i++) {
2656 if (dwork1[i + jpiv] != 0.0)
2657 break;
2658 }
2659 for (; i < ndo; ++i) {
2660 double dv = dwork1[i + jpiv];
2661
2662 if (dv != 0.) {
2663 int kce1 = mcstrt[i + 1];
2664
2665 for (iel = mcstrt[i]; iel > kce1; --iel) {
2666 int irow0 = hrowi[iel];
2667 SHIFT_REF(dwork1, irow0) += dv * dluval[iel];
2668 }
2669 }
2670 }
2671
2672 } /* c_ekkftj4p */
2673
2674 /*
2675 * This version is more efficient for input columns that are sparse.
2676 * It is instructive to consider the case of an especially sparse column,
2677 * which is a slack. The slack for row r has exactly one non-zero element,
2678 * in row r, which is +-1.0. Let pr = mpermu[r].
2679 * In this case, nincol==1 and mpt[0] == pr on entry.
2680 * if mpt[0] == pr <= jpiv
2681 * then this slack is completely unaffected by L;
2682 * this is reflected by the fact that save_where = last
2683 * after the first loop, so none of the remaining loops
2684 * ever execute,
2685 * else if mpt[0] == pr > jpiv, but pr-jpiv > ndo
2686 * then the slack is also unaffected by L, this time because
2687 * its row is "after" L. During factorization, it may
2688 * be the case that the first part of the basis is upper
2689 * triangular (c_ekktria), but it may also be the case that the
2690 * last part of the basis is upper triangular (in which case the
2691 * L triangle gets "chopped off" on the right). In both cases,
2692 * no L entries are required. Since in this case the tests
2693 * (i<=ndo) will fail (and dwork1[ipiv]==1.0), the code will
2694 * do nothing.
2695 * else if mpt[0] == pr > jpiv and pr-jpiv <= ndo
2696 * then the slack *is* affected by L.
2697 * the for-loop inside the second while-loop will discover
2698 * that none of the factors for the corresponding column of L
2699 * are non-zero in the slack column, so last will not be incremented.
2700 * We multiply the eta-vector, and the last loop does nothing.
2701 */
c_ekkftj4_sparse(COIN_REGISTER2 const EKKfactinfo * COIN_RESTRICT2 fact,double * COIN_RESTRICT dwork1,int * COIN_RESTRICT mpt,int nincol,int * COIN_RESTRICT spare)2702 static int c_ekkftj4_sparse(COIN_REGISTER2 const EKKfactinfo *COIN_RESTRICT2 fact,
2703 double *COIN_RESTRICT dwork1, int *COIN_RESTRICT mpt,
2704 int nincol, int *COIN_RESTRICT spare)
2705 {
2706 const int nrow = fact->nrow;
2707 /* this is where the L factors start, because this is the place
2708 * where c_ekktria starts laying them down (see initialization of xnetal).
2709 */
2710 int lstart = fact->lstart;
2711 const int *COIN_RESTRICT hpivco = fact->kcpadr;
2712 const double *COIN_RESTRICT dluval = fact->xeeadr;
2713 const int *COIN_RESTRICT hrowi = fact->xeradr;
2714 const int *COIN_RESTRICT mcstrt = fact->xcsadr + lstart - 1;
2715 double tolerance = fact->zeroTolerance;
2716 int jpiv = hpivco[lstart] - 1;
2717 char *COIN_RESTRICT nonzero = fact->nonzero;
2718 int ndo = fact->xnetalval;
2719 int k, nStack;
2720 int nList = 0;
2721 int iPivot;
2722 int *COIN_RESTRICT list = spare;
2723 int *COIN_RESTRICT stack = spare + nrow;
2724 int *COIN_RESTRICT next = stack + nrow;
2725 double dv;
2726 int iel;
2727 int nput = 0, kput = nrow;
2728 int check = jpiv + ndo + 1;
2729 const int *COIN_RESTRICT mcstrt2 = mcstrt - jpiv;
2730
2731 for (k = 0; k < nincol; k++) {
2732 nStack = 1;
2733 iPivot = mpt[k];
2734 if (nonzero[iPivot] != 1 && iPivot > jpiv && iPivot < check) {
2735 stack[0] = iPivot;
2736 next[0] = mcstrt2[iPivot + 1] + 1;
2737 while (nStack) {
2738 int kPivot, j;
2739 /* take off stack */
2740 kPivot = stack[--nStack];
2741 if (nonzero[kPivot] != 1 && kPivot > jpiv && kPivot < check) {
2742 j = next[nStack];
2743 if (j > mcstrt2[kPivot]) {
2744 /* finished so mark */
2745 list[nList++] = kPivot;
2746 nonzero[kPivot] = 1;
2747 } else {
2748 kPivot = UNSHIFT_INDEX(hrowi[j]);
2749 /* put back on stack */
2750 next[nStack++]++;
2751 if (!nonzero[kPivot]) {
2752 /* and new one */
2753 stack[nStack] = kPivot;
2754 nonzero[kPivot] = 2;
2755 next[nStack++] = mcstrt2[kPivot + 1] + 1;
2756 }
2757 }
2758 } else if (kPivot >= check) {
2759 list[--kput] = kPivot;
2760 nonzero[kPivot] = 1;
2761 }
2762 }
2763 } else if (nonzero[iPivot] != 1) {
2764 /* nothing to do (except check size at end) */
2765 list[--kput] = iPivot;
2766 nonzero[iPivot] = 1;
2767 }
2768 }
2769 for (k = nList - 1; k >= 0; k--) {
2770 double dv;
2771 iPivot = list[k];
2772 dv = dwork1[iPivot];
2773 nonzero[iPivot] = 0;
2774 if (fabs(dv) > tolerance) {
2775 /* the same code as in c_ekkftj4p */
2776 int kce1 = mcstrt2[iPivot + 1];
2777 for (iel = mcstrt2[iPivot]; iel > kce1; --iel) {
2778 int irow0 = hrowi[iel];
2779 SHIFT_REF(dwork1, irow0) += dv * dluval[iel];
2780 }
2781 mpt[nput++] = iPivot;
2782 } else {
2783 dwork1[iPivot] = 0.0; /* force to zero, not just near zero */
2784 }
2785 }
2786 /* check remainder */
2787 for (k = kput; k < nrow; k++) {
2788 iPivot = list[k];
2789 nonzero[iPivot] = 0;
2790 dv = dwork1[iPivot];
2791 if (fabs(dv) > tolerance) {
2792 mpt[nput++] = iPivot;
2793 } else {
2794 dwork1[iPivot] = 0.0; /* force to zero, not just near zero */
2795 }
2796 }
2797
2798 return (nput);
2799 } /* c_ekkftj4 */
2800 /*
2801 * This applies the R transformations of the F-T LU update procedure,
2802 * equation 3.11 on p. 270 in the 1972 Math Programming paper.
2803 * Note that since the non-zero off-diagonal elements are in a row,
2804 * multiplying an R by a column is a reduction, not like applying
2805 * L or U.
2806 *
2807 * Note that this may introduce new non-zeros in dwork1,
2808 * since an hpivco entry may correspond to a zero element,
2809 * and that some non-zeros in dwork1 may be cancelled.
2810 */
c_ekkftjl_sparse3(COIN_REGISTER2 const EKKfactinfo * COIN_RESTRICT2 fact,double * COIN_RESTRICT dwork1,int * COIN_RESTRICT mpt,int * COIN_RESTRICT hput,double * COIN_RESTRICT dluput,int nincol)2811 static int c_ekkftjl_sparse3(COIN_REGISTER2 const EKKfactinfo *COIN_RESTRICT2 fact,
2812 double *COIN_RESTRICT dwork1,
2813 int *COIN_RESTRICT mpt,
2814 int *COIN_RESTRICT hput, double *COIN_RESTRICT dluput,
2815 int nincol)
2816 {
2817 int i;
2818 int knext;
2819 int ipiv;
2820 double dv;
2821 const double *COIN_RESTRICT dluval = fact->R_etas_element + 1;
2822 const int *COIN_RESTRICT hrowi = fact->R_etas_index + 1;
2823 const int *COIN_RESTRICT mcstrt = fact->R_etas_start;
2824 int ndo = fact->nR_etas;
2825 double tolerance = fact->zeroTolerance;
2826 const int *COIN_RESTRICT hpivco = fact->hpivcoR;
2827 /* and make cleaner */
2828 hput++;
2829 dluput++;
2830
2831 /* DO ANY ROW TRANSFORMATIONS */
2832
2833 /* Function Body */
2834 /* mpt has correct list of nonzeros */
2835 if (ndo != 0) {
2836 knext = mcstrt[1];
2837 for (i = 1; i <= ndo; ++i) {
2838 int k1 = knext; /* == mcstrt[i] */
2839 int iel;
2840 ipiv = hpivco[i];
2841 dv = dwork1[ipiv];
2842 bool onList = (dv != 0.0);
2843 knext = mcstrt[i + 1];
2844
2845 for (iel = knext; iel < k1; ++iel) {
2846 int irow = hrowi[iel];
2847 dv += SHIFT_REF(dwork1, irow) * dluval[iel];
2848 }
2849 /* (1) if dwork[ipiv] == 0.0, then this may add a non-zero.
2850 * (2) if dwork[ipiv] != 0.0, then this may cancel out a non-zero.
2851 */
2852 if (onList) {
2853 if (fabs(dv) > tolerance) {
2854 dwork1[ipiv] = dv;
2855 } else {
2856 dwork1[ipiv] = 1.0e-128;
2857 }
2858 } else {
2859 if (fabs(dv) > tolerance) {
2860 /* put on list if not there */
2861 mpt[nincol++] = ipiv;
2862 dwork1[ipiv] = dv;
2863 }
2864 }
2865 }
2866 }
2867 knext = 0;
2868 for (i = 0; i < nincol; i++) {
2869 ipiv = mpt[i];
2870 dv = dwork1[ipiv];
2871 if (fabs(dv) > tolerance) {
2872 hput[knext] = SHIFT_INDEX(ipiv);
2873 dluput[knext] = dv;
2874 mpt[knext++] = ipiv;
2875 } else {
2876 dwork1[ipiv] = 0.0;
2877 }
2878 }
2879 return knext;
2880 } /* c_ekkftjl */
2881
c_ekkftjl_sparse2(COIN_REGISTER2 const EKKfactinfo * COIN_RESTRICT2 fact,double * COIN_RESTRICT dwork1,int * COIN_RESTRICT mpt,int nincol)2882 static int c_ekkftjl_sparse2(COIN_REGISTER2 const EKKfactinfo *COIN_RESTRICT2 fact,
2883 double *COIN_RESTRICT dwork1,
2884 int *COIN_RESTRICT mpt,
2885 int nincol)
2886 {
2887 double tolerance = fact->zeroTolerance;
2888 const double *COIN_RESTRICT dluval = fact->R_etas_element + 1;
2889 const int *COIN_RESTRICT hrowi = fact->R_etas_index + 1;
2890 const int *COIN_RESTRICT mcstrt = fact->R_etas_start;
2891 int ndo = fact->nR_etas;
2892 const int *COIN_RESTRICT hpivco = fact->hpivcoR;
2893 int i;
2894 int knext;
2895 int ipiv;
2896 double dv;
2897
2898 /* DO ANY ROW TRANSFORMATIONS */
2899
2900 /* Function Body */
2901 /* mpt has correct list of nonzeros */
2902 if (ndo != 0) {
2903 knext = mcstrt[1];
2904 for (i = 1; i <= ndo; ++i) {
2905 int k1 = knext; /* == mcstrt[i] */
2906 int iel;
2907 ipiv = hpivco[i];
2908 dv = dwork1[ipiv];
2909 bool onList = (dv != 0.0);
2910 knext = mcstrt[i + 1];
2911
2912 for (iel = knext; iel < k1; ++iel) {
2913 int irow = hrowi[iel];
2914 dv += SHIFT_REF(dwork1, irow) * dluval[iel];
2915 }
2916 /* (1) if dwork[ipiv] == 0.0, then this may add a non-zero.
2917 * (2) if dwork[ipiv] != 0.0, then this may cancel out a non-zero.
2918 */
2919 if (onList) {
2920 if (fabs(dv) > tolerance) {
2921 dwork1[ipiv] = dv;
2922 } else {
2923 dwork1[ipiv] = 1.0e-128;
2924 }
2925 } else {
2926 if (fabs(dv) > tolerance) {
2927 /* put on list if not there */
2928 mpt[nincol++] = ipiv;
2929 dwork1[ipiv] = dv;
2930 }
2931 }
2932 }
2933 }
2934 knext = 0;
2935 for (i = 0; i < nincol; i++) {
2936 ipiv = mpt[i];
2937 dv = dwork1[ipiv];
2938 if (fabs(dv) > tolerance) {
2939 mpt[knext++] = ipiv;
2940 } else {
2941 dwork1[ipiv] = 0.0;
2942 }
2943 }
2944 return knext;
2945 } /* c_ekkftjl */
2946
c_ekkftjl(COIN_REGISTER2 const EKKfactinfo * COIN_RESTRICT2 fact,double * COIN_RESTRICT dwork1)2947 static void c_ekkftjl(COIN_REGISTER2 const EKKfactinfo *COIN_RESTRICT2 fact,
2948 double *COIN_RESTRICT dwork1)
2949 {
2950 double tolerance = fact->zeroTolerance;
2951 const double *COIN_RESTRICT dluval = fact->R_etas_element + 1;
2952 const int *COIN_RESTRICT hrowi = fact->R_etas_index + 1;
2953 const int *COIN_RESTRICT mcstrt = fact->R_etas_start;
2954 int ndo = fact->nR_etas;
2955 const int *COIN_RESTRICT hpivco = fact->hpivcoR;
2956 int i;
2957 int knext;
2958
2959 /* DO ANY ROW TRANSFORMATIONS */
2960
2961 /* Function Body */
2962 if (ndo != 0) {
2963 /*
2964 * The following three lines are here just to ensure that this
2965 * new formulation of the loop has exactly the same effect
2966 * as the original.
2967 */
2968 {
2969 int ipiv = hpivco[1];
2970 double dv = dwork1[ipiv];
2971 dwork1[ipiv] = (fabs(dv) > tolerance) ? dv : 0.0;
2972 }
2973
2974 knext = mcstrt[1];
2975 for (i = 1; i <= ndo; ++i) {
2976 int k1 = knext; /* == mcstrt[i] */
2977 int ipiv = hpivco[i];
2978 double dv = dwork1[ipiv];
2979 int iel;
2980 //#define UNROLL3 2
2981 #ifndef UNROLL3
2982 #if CLP_OSL == 2 || CLP_OSL == 3
2983 #define UNROLL3 2
2984 #else
2985 #define UNROLL3 1
2986 #endif
2987 #endif
2988 knext = mcstrt[i + 1];
2989
2990 #if UNROLL3 < 2
2991 for (iel = knext; iel < k1; ++iel) {
2992 int irow = hrowi[iel];
2993 dv += SHIFT_REF(dwork1, irow) * dluval[iel];
2994 }
2995 #else
2996 iel = knext;
2997 if (((k1 - knext) & 1) != 0) {
2998 int irow = hrowi[iel];
2999 dv += SHIFT_REF(dwork1, irow) * dluval[iel];
3000 iel++;
3001 }
3002 for (; iel < k1; iel += 2) {
3003 int irow0 = hrowi[iel];
3004 double dval0 = dluval[iel];
3005 int irow1 = hrowi[iel + 1];
3006 double dval1 = dluval[iel + 1];
3007 dv += SHIFT_REF(dwork1, irow0) * dval0;
3008 dv += SHIFT_REF(dwork1, irow1) * dval1;
3009 }
3010 #endif
3011 /* (1) if dwork[ipiv] == 0.0, then this may add a non-zero.
3012 * (2) if dwork[ipiv] != 0.0, then this may cancel out a non-zero.
3013 */
3014 dwork1[ipiv] = (fabs(dv) > tolerance) ? dv : 0.0;
3015 }
3016 }
3017 } /* c_ekkftjl */
3018 /* this assumes it is ok to reference back[loop_limit] */
3019 /* another 3 seconds from a ~570 second run can be trimmed
3020 * by using two routines, one with scan==true and the other false,
3021 * since that eliminates the branch instructions involving them
3022 * entirely. This was how the code was originally written.
3023 * However, I'm still hoping that eventually we can use
3024 * C++ templates to do that for us automatically.
3025 */
3026 static void
c_ekkftjup_scan_aux(COIN_REGISTER2 const EKKfactinfo * COIN_RESTRICT2 fact,double * COIN_RESTRICT dwork1,double * COIN_RESTRICT dworko,int loop_limit,int * ip,int ** mptp)3027 c_ekkftjup_scan_aux(COIN_REGISTER2 const EKKfactinfo *COIN_RESTRICT2 fact,
3028 double *COIN_RESTRICT dwork1, double *COIN_RESTRICT dworko,
3029 int loop_limit, int *ip, int **mptp)
3030 {
3031 const double *COIN_RESTRICT dluval = fact->xeeadr + 1;
3032 const int *COIN_RESTRICT hrowi = fact->xeradr + 1;
3033 const int *COIN_RESTRICT mcstrt = fact->xcsadr;
3034 const int *COIN_RESTRICT hpivro = fact->krpadr;
3035 const int *COIN_RESTRICT back = fact->back;
3036 double tolerance = fact->zeroTolerance;
3037 int ipiv = *ip;
3038 double dv = dwork1[ipiv];
3039
3040 int *mptX = *mptp;
3041 assert(mptX);
3042 while (ipiv != loop_limit) {
3043 int next_ipiv = back[ipiv];
3044
3045 dwork1[ipiv] = 0.0;
3046 #ifndef UNROLL4
3047 #define UNROLL4 2
3048 #endif
3049 /* invariant: dv == dwork1[ipiv] */
3050
3051 /* in the case of world.mps with dual, this condition is true
3052 * only 20-60% of the time. */
3053 if (fabs(dv) > tolerance) {
3054 const int kx = mcstrt[ipiv];
3055 const int nel = hrowi[kx - 1];
3056 const double dpiv = dluval[kx - 1];
3057 #if UNROLL4 > 1
3058 const int *hrowi2 = hrowi + kx;
3059 const int *hrowi2end = hrowi2 + nel;
3060 const double *dluval2 = dluval + kx;
3061 #else
3062 int iel;
3063 #endif
3064
3065 dv *= dpiv;
3066
3067 /*
3068 * The following loop is the unrolled version of this:
3069 *
3070 * for (iel = kx+1; iel <= kx + nel; iel++) {
3071 * SHIFT_REF(dwork1, hrowi[iel]) -= dv * dluval[iel];
3072 * }
3073 */
3074 #if UNROLL4 < 2
3075 iel = kx;
3076 if (nel & 1) {
3077 int irow = hrowi[iel];
3078 double dval = dluval[iel];
3079 SHIFT_REF(dwork1, irow) -= dv * dval;
3080 iel++;
3081 }
3082 for (; iel < kx + nel; iel += 2) {
3083 int irow0 = hrowi[iel];
3084 int irow1 = hrowi[iel + 1];
3085 double dval0 = dluval[iel];
3086 double dval1 = dluval[iel + 1];
3087 double d0 = SHIFT_REF(dwork1, irow0);
3088 double d1 = SHIFT_REF(dwork1, irow1);
3089
3090 d0 -= dv * dval0;
3091 d1 -= dv * dval1;
3092 SHIFT_REF(dwork1, irow0) = d0;
3093 SHIFT_REF(dwork1, irow1) = d1;
3094 } /* end loop */
3095 #else
3096 if ((nel & 1) != 0) {
3097 int irow = *hrowi2;
3098 double dval = *dluval2;
3099 SHIFT_REF(dwork1, irow) -= dv * dval;
3100 hrowi2++;
3101 dluval2++;
3102 }
3103 for (; hrowi2 < hrowi2end; hrowi2 += 2, dluval2 += 2) {
3104 int irow0 = hrowi2[0];
3105 int irow1 = hrowi2[1];
3106 double dval0 = dluval2[0];
3107 double dval1 = dluval2[1];
3108 double d0 = SHIFT_REF(dwork1, irow0);
3109 double d1 = SHIFT_REF(dwork1, irow1);
3110
3111 d0 -= dv * dval0;
3112 d1 -= dv * dval1;
3113 SHIFT_REF(dwork1, irow0) = d0;
3114 SHIFT_REF(dwork1, irow1) = d1;
3115 }
3116 #endif
3117 /* put this down here so that dv is less likely to cause a stall */
3118 if (fabs(dv) >= tolerance) {
3119 int iput = hpivro[ipiv];
3120 dworko[iput] = dv;
3121 *mptX++ = iput - 1;
3122 }
3123 }
3124
3125 dv = dwork1[next_ipiv];
3126 ipiv = next_ipiv;
3127 } /* endwhile */
3128
3129 *mptp = mptX;
3130 *ip = ipiv;
3131 }
c_ekkftjup_aux3(COIN_REGISTER2 const EKKfactinfo * COIN_RESTRICT2 fact,double * COIN_RESTRICT dwork1,double * COIN_RESTRICT dworko,const int * COIN_RESTRICT back,const int * COIN_RESTRICT hpivro,int * ipivp,int loop_limit,int ** mptXp)3132 static void c_ekkftjup_aux3(COIN_REGISTER2 const EKKfactinfo *COIN_RESTRICT2 fact,
3133 double *COIN_RESTRICT dwork1, double *COIN_RESTRICT dworko,
3134 const int *COIN_RESTRICT back,
3135 const int *COIN_RESTRICT hpivro,
3136 int *ipivp, int loop_limit,
3137 int **mptXp)
3138
3139 {
3140 double tolerance = fact->zeroTolerance;
3141 int ipiv = *ipivp;
3142 if (ipiv != loop_limit) {
3143 int *mptX = *mptXp;
3144
3145 double dv = dwork1[ipiv];
3146
3147 do {
3148 int next_ipiv = back[ipiv];
3149 double next_dv = dwork1[next_ipiv];
3150
3151 dwork1[ipiv] = 0.0;
3152
3153 if (fabs(dv) >= tolerance) {
3154 int iput = hpivro[ipiv];
3155 dworko[iput] = dv;
3156 *mptX++ = iput - 1;
3157 }
3158
3159 ipiv = next_ipiv;
3160 dv = next_dv;
3161 } while (ipiv != loop_limit);
3162
3163 *mptXp = mptX;
3164 *ipivp = ipiv;
3165 }
3166 }
c_ekkftju_dense(const double * dluval,const int * COIN_RESTRICT hrowi,const int * COIN_RESTRICT mcstrt,const int * COIN_RESTRICT back,double * COIN_RESTRICT dwork1,int * start,int last,int offset,double * densew)3167 static void c_ekkftju_dense(const double *dluval,
3168 const int *COIN_RESTRICT hrowi,
3169 const int *COIN_RESTRICT mcstrt,
3170 const int *COIN_RESTRICT back,
3171 double *COIN_RESTRICT dwork1,
3172 int *start, int last,
3173 int offset, double *densew)
3174 {
3175 int ipiv = *start;
3176
3177 while (ipiv > last) {
3178 const int ipiv1 = ipiv;
3179 double dv1 = dwork1[ipiv1];
3180 ipiv = back[ipiv];
3181 if (fabs(dv1) > 1.0e-14) {
3182 const int kx1 = mcstrt[ipiv1];
3183 const int nel1 = hrowi[kx1 - 1];
3184 const double dpiv1 = dluval[kx1 - 1];
3185
3186 int iel, k;
3187 const int n1 = offset + ipiv1; /* number in dense part */
3188
3189 const int nsparse1 = nel1 - n1;
3190 const int k1 = kx1 + nsparse1;
3191 const double *dlu1 = &dluval[k1];
3192
3193 int ipiv2 = back[ipiv1];
3194 const int nskip = ipiv1 - ipiv2;
3195
3196 dv1 *= dpiv1;
3197
3198 dwork1[ipiv1] = dv1;
3199
3200 for (k = n1 - (nskip - 1) - 1; k >= 0; k--) {
3201 const double dval = dv1 * dlu1[k];
3202 double dv2 = densew[k] - dval;
3203 ipiv = back[ipiv];
3204 if (fabs(dv2) > 1.0e-14) {
3205 const int kx2 = mcstrt[ipiv2];
3206 const int nel2 = hrowi[kx2 - 1];
3207 const double dpiv2 = dluval[kx2 - 1];
3208
3209 /* number in dense part is k */
3210 const int nsparse2 = nel2 - k;
3211
3212 const int k2 = kx2 + nsparse2;
3213 const double *dlu2 = &dluval[k2];
3214
3215 dv2 *= dpiv2;
3216 densew[k] = dv2; /* was dwork1[ipiv2]=dv2; */
3217
3218 k--;
3219
3220 /*
3221 * The following loop is the unrolled version of:
3222 *
3223 * for (; k >= 0; k--) {
3224 * densew[k]-=dv1*dlu1[k]+dv2*dlu2[k];
3225 * }
3226 */
3227 if ((k & 1) == 0) {
3228 densew[k] -= dv1 * dlu1[k] + dv2 * dlu2[k];
3229 k--;
3230 }
3231 for (; k >= 0; k -= 2) {
3232 double da, db;
3233 da = densew[k];
3234 db = densew[k - 1];
3235 da -= dv1 * dlu1[k];
3236 db -= dv1 * dlu1[k - 1];
3237 da -= dv2 * dlu2[k];
3238 db -= dv2 * dlu2[k - 1];
3239 densew[k] = da;
3240 densew[k - 1] = db;
3241 }
3242 /* end loop */
3243
3244 /*
3245 * The following loop is the unrolled version of:
3246 *
3247 * for (iel=kx2+nsparse2-1; iel >= kx2; iel--) {
3248 * SHIFT_REF(dwork1, hrowi[iel]) -= dv2*dluval[iel];
3249 * }
3250 */
3251 iel = kx2 + nsparse2 - 1;
3252 if ((nsparse2 & 1) != 0) {
3253 int irow0 = hrowi[iel];
3254 double dval = dluval[iel];
3255 SHIFT_REF(dwork1, irow0) -= dv2 * dval;
3256 iel--;
3257 }
3258 for (; iel >= kx2; iel -= 2) {
3259 double dval0 = dluval[iel];
3260 double dval1 = dluval[iel - 1];
3261 int irow0 = hrowi[iel];
3262 int irow1 = hrowi[iel - 1];
3263 double d0 = SHIFT_REF(dwork1, irow0);
3264 double d1 = SHIFT_REF(dwork1, irow1);
3265
3266 d0 -= dv2 * dval0;
3267 d1 -= dv2 * dval1;
3268 SHIFT_REF(dwork1, irow0) = d0;
3269 SHIFT_REF(dwork1, irow1) = d1;
3270 }
3271 /* end loop */
3272
3273 } else {
3274 densew[k] = 0.0;
3275 /* skip if next deleted */
3276 k -= ipiv2 - ipiv - 1;
3277 ipiv2 = ipiv;
3278 if (ipiv < last) {
3279 k--;
3280 for (; k >= 0; k--) {
3281 double dval;
3282 dval = dv1 * dlu1[k];
3283 densew[k] = densew[k] - dval;
3284 }
3285 }
3286 }
3287 }
3288
3289 /*
3290 * The following loop is the unrolled version of:
3291 *
3292 * for (iel=kx1+nsparse1-1; iel >= kx1; iel--) {
3293 * SHIFT_REF(dwork1, hrowi[iel]) -= dv1*dluval[iel];
3294 * }
3295 */
3296 iel = kx1 + nsparse1 - 1;
3297 if ((nsparse1 & 1) != 0) {
3298 int irow0 = hrowi[iel];
3299 double dval = dluval[iel];
3300 SHIFT_REF(dwork1, irow0) -= dv1 * dval;
3301 iel--;
3302 }
3303 for (; iel >= kx1; iel -= 2) {
3304 double dval0 = dluval[iel];
3305 double dval1 = dluval[iel - 1];
3306 int irow0 = hrowi[iel];
3307 int irow1 = hrowi[iel - 1];
3308 double d0 = SHIFT_REF(dwork1, irow0);
3309 double d1 = SHIFT_REF(dwork1, irow1);
3310
3311 d0 -= dv1 * dval0;
3312 d1 -= dv1 * dval1;
3313 SHIFT_REF(dwork1, irow0) = d0;
3314 SHIFT_REF(dwork1, irow1) = d1;
3315 }
3316 /* end loop */
3317 } else {
3318 dwork1[ipiv1] = 0.0;
3319 } /* endif */
3320 } /* endwhile */
3321 *start = ipiv;
3322 }
3323
3324 /* do not use return value if mpt==0 */
3325 /* using dual, this is usually called via c_ekkftrn_ft, from c_ekksdul
3326 * (so mpt is non-null).
3327 * it is generally called every iteration, but sometimes several iterations
3328 * are skipped (null moves?).
3329 *
3330 * generally, back[i] == i-1 (initialized in c_ekkshfv towards the end).
3331 */
c_ekkftjup(COIN_REGISTER3 const EKKfactinfo * COIN_RESTRICT2 fact,double * COIN_RESTRICT dwork1,int last,double * COIN_RESTRICT dworko,int * COIN_RESTRICT mpt)3332 static int c_ekkftjup(COIN_REGISTER3 const EKKfactinfo *COIN_RESTRICT2 fact,
3333 double *COIN_RESTRICT dwork1, int last,
3334 double *COIN_RESTRICT dworko, int *COIN_RESTRICT mpt)
3335 {
3336 const double *COIN_RESTRICT dluval = fact->xeeadr;
3337 const int *COIN_RESTRICT hrowi = fact->xeradr;
3338 const int *COIN_RESTRICT mcstrt = fact->xcsadr;
3339 const int *COIN_RESTRICT hpivro = fact->krpadr;
3340 double tolerance = fact->zeroTolerance;
3341 int ndenuc = fact->ndenuc;
3342 const int first_dense = fact->first_dense;
3343 const int last_dense = fact->last_dense;
3344 int i;
3345 int *mptX = mpt;
3346
3347 const int nrow = fact->nrow;
3348 const int *COIN_RESTRICT back = fact->back;
3349 int ipiv = back[nrow + 1];
3350
3351 if (last_dense > first_dense && mcstrt[ipiv] >= mcstrt[last_dense]) {
3352 c_ekkftjup_scan_aux(fact,
3353 dwork1, dworko, last_dense, &ipiv,
3354 &mptX);
3355
3356 {
3357 int j;
3358 int n = 0;
3359 const int firstDense = nrow - ndenuc + 1;
3360 double *densew = &dwork1[firstDense];
3361 int offset;
3362
3363 /* check first dense to see where in triangle it is */
3364 int last = first_dense;
3365 const int k1 = mcstrt[last];
3366 const int k2 = k1 + hrowi[k1];
3367
3368 for (j = k2; j > k1; j--) {
3369 int irow = UNSHIFT_INDEX(hrowi[j]);
3370 if (irow < firstDense) {
3371 break;
3372 } else {
3373 #ifdef DEBUG
3374 if (irow != last - 1) {
3375 abort();
3376 }
3377 #endif
3378 last = irow;
3379 n++;
3380 }
3381 }
3382 offset = n - first_dense;
3383 i = ipiv;
3384 /* loop counter i may be modified by this call */
3385 c_ekkftju_dense(&dluval[1], &hrowi[1], mcstrt, back,
3386 dwork1, &i, first_dense, offset, densew);
3387
3388 c_ekkftjup_aux3(fact, dwork1, dworko, back, hpivro, &ipiv, i, &mptX);
3389 }
3390 }
3391
3392 c_ekkftjup_scan_aux(fact,
3393 dwork1, dworko, last, &ipiv,
3394 &mptX);
3395
3396 if (ipiv != 0) {
3397 double dv = dwork1[ipiv];
3398
3399 do {
3400 int next_ipiv = back[ipiv];
3401 double next_dv = dwork1[next_ipiv];
3402
3403 dwork1[ipiv] = 0.0;
3404
3405 if (fabs(dv) >= tolerance) {
3406 int iput = hpivro[ipiv];
3407 dworko[iput] = -dv;
3408 *mptX++ = iput - 1;
3409 }
3410
3411 ipiv = next_ipiv;
3412 dv = next_dv;
3413 } while (ipiv != 0);
3414 }
3415 return static_cast< int >(mptX - mpt);
3416 }
3417 /* this assumes it is ok to reference back[loop_limit] */
3418 /* another 3 seconds from a ~570 second run can be trimmed
3419 * by using two routines, one with scan==true and the other false,
3420 * since that eliminates the branch instructions involving them
3421 * entirely. This was how the code was originally written.
3422 * However, I'm still hoping that eventually we can use
3423 * C++ templates to do that for us automatically.
3424 */
3425 static void
c_ekkftjup_scan_aux_pack(COIN_REGISTER2 const EKKfactinfo * COIN_RESTRICT2 fact,double * COIN_RESTRICT dwork1,double * COIN_RESTRICT dworko,int loop_limit,int * ip,int ** mptp)3426 c_ekkftjup_scan_aux_pack(COIN_REGISTER2 const EKKfactinfo *COIN_RESTRICT2 fact,
3427 double *COIN_RESTRICT dwork1, double *COIN_RESTRICT dworko,
3428 int loop_limit, int *ip, int **mptp)
3429 {
3430 double tolerance = fact->zeroTolerance;
3431 const double *dluval = fact->xeeadr + 1;
3432 const int *hrowi = fact->xeradr + 1;
3433 const int *mcstrt = fact->xcsadr;
3434 const int *hpivro = fact->krpadr;
3435 const int *back = fact->back;
3436 int ipiv = *ip;
3437 double dv = dwork1[ipiv];
3438
3439 int *mptX = *mptp;
3440 #if 0
3441 int inSlacks=0;
3442 int lastSlack;
3443 if (fact->numberSlacks!=0)
3444 lastSlack=fact->lastSlack;
3445 else
3446 lastSlack=0;
3447 if (c_ekk_IsSet(fact->bitArray,ipiv)) {
3448 printf("already in slacks - ipiv %d\n",ipiv);
3449 inSlacks=1;
3450 return;
3451 }
3452 #endif
3453 assert(mptX);
3454 while (ipiv != loop_limit) {
3455 int next_ipiv = back[ipiv];
3456 #if 0
3457 if (ipiv==lastSlack) {
3458 printf("now in slacks - ipiv %d\n",ipiv);
3459 inSlacks=1;
3460 break;
3461 }
3462 if (inSlacks) {
3463 assert (c_ekk_IsSet(fact->bitArray,ipiv));
3464 assert (dluval[mcstrt[ipiv]-1]==-1.0);
3465 assert (hrowi[mcstrt[ipiv]-1]==0);
3466 }
3467 #endif
3468 dwork1[ipiv] = 0.0;
3469 /* invariant: dv == dwork1[ipiv] */
3470
3471 /* in the case of world.mps with dual, this condition is true
3472 * only 20-60% of the time. */
3473 if (fabs(dv) > tolerance) {
3474 const int kx = mcstrt[ipiv];
3475 const int nel = hrowi[kx - 1];
3476 const double dpiv = dluval[kx - 1];
3477 #ifndef UNROLL5
3478 #define UNROLL5 2
3479 #endif
3480 #if UNROLL5 > 1
3481 const int *hrowi2 = hrowi + kx;
3482 const int *hrowi2end = hrowi2 + nel;
3483 const double *dluval2 = dluval + kx;
3484 #else
3485 int iel;
3486 #endif
3487
3488 dv *= dpiv;
3489
3490 /*
3491 * The following loop is the unrolled version of this:
3492 *
3493 * for (iel = kx+1; iel <= kx + nel; iel++) {
3494 * SHIFT_REF(dwork1, hrowi[iel]) -= dv * dluval[iel];
3495 * }
3496 */
3497 #if UNROLL5 < 2
3498 iel = kx;
3499 if (nel & 1) {
3500 int irow = hrowi[iel];
3501 double dval = dluval[iel];
3502 SHIFT_REF(dwork1, irow) -= dv * dval;
3503 iel++;
3504 }
3505 for (; iel < kx + nel; iel += 2) {
3506 int irow0 = hrowi[iel];
3507 int irow1 = hrowi[iel + 1];
3508 double dval0 = dluval[iel];
3509 double dval1 = dluval[iel + 1];
3510 double d0 = SHIFT_REF(dwork1, irow0);
3511 double d1 = SHIFT_REF(dwork1, irow1);
3512
3513 d0 -= dv * dval0;
3514 d1 -= dv * dval1;
3515 SHIFT_REF(dwork1, irow0) = d0;
3516 SHIFT_REF(dwork1, irow1) = d1;
3517 } /* end loop */
3518 #else
3519 if ((nel & 1) != 0) {
3520 int irow = *hrowi2;
3521 double dval = *dluval2;
3522 SHIFT_REF(dwork1, irow) -= dv * dval;
3523 hrowi2++;
3524 dluval2++;
3525 }
3526 for (; hrowi2 < hrowi2end; hrowi2 += 2, dluval2 += 2) {
3527 int irow0 = hrowi2[0];
3528 int irow1 = hrowi2[1];
3529 double dval0 = dluval2[0];
3530 double dval1 = dluval2[1];
3531 double d0 = SHIFT_REF(dwork1, irow0);
3532 double d1 = SHIFT_REF(dwork1, irow1);
3533
3534 d0 -= dv * dval0;
3535 d1 -= dv * dval1;
3536 SHIFT_REF(dwork1, irow0) = d0;
3537 SHIFT_REF(dwork1, irow1) = d1;
3538 }
3539 #endif
3540 /* put this down here so that dv is less likely to cause a stall */
3541 if (fabs(dv) >= tolerance) {
3542 int iput = hpivro[ipiv];
3543 *dworko++ = dv;
3544 *mptX++ = iput - 1;
3545 }
3546 }
3547
3548 dv = dwork1[next_ipiv];
3549 ipiv = next_ipiv;
3550 } /* endwhile */
3551
3552 *mptp = mptX;
3553 *ip = ipiv;
3554 }
c_ekkftjup_aux3_pack(COIN_REGISTER2 const EKKfactinfo * COIN_RESTRICT2 fact,double * COIN_RESTRICT dwork1,double * COIN_RESTRICT dworko,const int * COIN_RESTRICT back,const int * COIN_RESTRICT hpivro,int * ipivp,int loop_limit,int ** mptXp)3555 static void c_ekkftjup_aux3_pack(COIN_REGISTER2 const EKKfactinfo *COIN_RESTRICT2 fact,
3556 double *COIN_RESTRICT dwork1, double *COIN_RESTRICT dworko,
3557 const int *COIN_RESTRICT back,
3558 const int *COIN_RESTRICT hpivro,
3559 int *ipivp, int loop_limit,
3560 int **mptXp)
3561
3562 {
3563 double tolerance = fact->zeroTolerance;
3564 int ipiv = *ipivp;
3565 if (ipiv != loop_limit) {
3566 int *mptX = *mptXp;
3567
3568 double dv = dwork1[ipiv];
3569 do {
3570 int next_ipiv = back[ipiv];
3571 double next_dv = dwork1[next_ipiv];
3572
3573 dwork1[ipiv] = 0.0;
3574
3575 if (fabs(dv) >= tolerance) {
3576 int iput = hpivro[ipiv];
3577 *dworko++ = dv;
3578 *mptX++ = iput - 1;
3579 }
3580
3581 ipiv = next_ipiv;
3582 dv = next_dv;
3583 } while (ipiv != loop_limit);
3584
3585 *mptXp = mptX;
3586
3587 *ipivp = ipiv;
3588 }
3589 }
3590
3591 /* do not use return value if mpt==0 */
3592 /* using dual, this is usually called via c_ekkftrn_ft, from c_ekksdul
3593 * (so mpt is non-null).
3594 * it is generally called every iteration, but sometimes several iterations
3595 * are skipped (null moves?).
3596 *
3597 * generally, back[i] == i-1 (initialized in c_ekkshfv towards the end).
3598 */
c_ekkftjup_pack(COIN_REGISTER3 const EKKfactinfo * COIN_RESTRICT2 fact,double * COIN_RESTRICT dwork1,int last,double * COIN_RESTRICT dworko,int * COIN_RESTRICT mpt)3599 static int c_ekkftjup_pack(COIN_REGISTER3 const EKKfactinfo *COIN_RESTRICT2 fact,
3600 double *COIN_RESTRICT dwork1, int last,
3601 double *COIN_RESTRICT dworko, int *COIN_RESTRICT mpt)
3602 {
3603 const double *COIN_RESTRICT dluval = fact->xeeadr;
3604 const int *COIN_RESTRICT hrowi = fact->xeradr;
3605 const int *COIN_RESTRICT mcstrt = fact->xcsadr;
3606 const int *COIN_RESTRICT hpivro = fact->krpadr;
3607 double tolerance = fact->zeroTolerance;
3608 int ndenuc = fact->ndenuc;
3609 const int first_dense = fact->first_dense;
3610 const int last_dense = fact->last_dense;
3611 int *mptX = mpt;
3612 int *mptY = mpt;
3613
3614 const int nrow = fact->nrow;
3615 const int *COIN_RESTRICT back = fact->back;
3616 int ipiv = back[nrow + 1];
3617 assert(mpt);
3618
3619 if (last_dense > first_dense && mcstrt[ipiv] >= mcstrt[last_dense]) {
3620 c_ekkftjup_scan_aux_pack(fact,
3621 dwork1, dworko, last_dense, &ipiv,
3622 &mptX);
3623 /* adjust */
3624 dworko += (mptX - mpt);
3625 mpt = mptX;
3626 {
3627 int j;
3628 int n = 0;
3629 const int firstDense = nrow - ndenuc + 1;
3630 double *densew = &dwork1[firstDense];
3631 int offset;
3632
3633 /* check first dense to see where in triangle it is */
3634 int last = first_dense;
3635 const int k1 = mcstrt[last];
3636 const int k2 = k1 + hrowi[k1];
3637
3638 for (j = k2; j > k1; j--) {
3639 int irow = UNSHIFT_INDEX(hrowi[j]);
3640 if (irow < firstDense) {
3641 break;
3642 } else {
3643 #ifdef DEBUG
3644 if (irow != last - 1) {
3645 abort();
3646 }
3647 #endif
3648 last = irow;
3649 n++;
3650 }
3651 }
3652 offset = n - first_dense;
3653 int ipiv2 = ipiv;
3654 /* loop counter i may be modified by this call */
3655 c_ekkftju_dense(&dluval[1], &hrowi[1], mcstrt, back,
3656 dwork1, &ipiv2, first_dense, offset, densew);
3657
3658 c_ekkftjup_aux3_pack(fact, dwork1, dworko, back, hpivro, &ipiv, ipiv2, &mptX);
3659 /* adjust dworko */
3660 dworko += (mptX - mpt);
3661 mpt = mptX;
3662 }
3663 }
3664
3665 c_ekkftjup_scan_aux_pack(fact,
3666 dwork1, dworko, last, &ipiv,
3667 &mptX);
3668 /* adjust dworko */
3669 dworko += (mptX - mpt);
3670 while (ipiv != 0) {
3671 double dv = dwork1[ipiv];
3672 int next_ipiv = back[ipiv];
3673
3674 dwork1[ipiv] = 0.0;
3675
3676 if (fabs(dv) >= tolerance) {
3677 int iput = hpivro[ipiv];
3678 *dworko++ = -dv;
3679 *mptX++ = iput - 1;
3680 }
3681
3682 ipiv = next_ipiv;
3683 }
3684
3685 return static_cast< int >(mptX - mptY);
3686 }
c_ekkftju_sparse_a(COIN_REGISTER2 const EKKfactinfo * COIN_RESTRICT2 fact,int * COIN_RESTRICT mpt,int nincol,int * COIN_RESTRICT spare)3687 static int c_ekkftju_sparse_a(COIN_REGISTER2 const EKKfactinfo *COIN_RESTRICT2 fact,
3688 int *COIN_RESTRICT mpt,
3689 int nincol, int *COIN_RESTRICT spare)
3690 {
3691 const int *COIN_RESTRICT hrowi = fact->xeradr + 1;
3692 const int *COIN_RESTRICT mcstrt = fact->xcsadr;
3693 const int nrow = fact->nrow;
3694 char *COIN_RESTRICT nonzero = fact->nonzero;
3695
3696 int k, nStack, kx, nel;
3697 int nList = 0;
3698 int iPivot;
3699 /*int kkk=nincol;*/
3700 int *COIN_RESTRICT list = spare;
3701 int *COIN_RESTRICT stack = spare + nrow;
3702 int *COIN_RESTRICT next = stack + nrow;
3703 for (k = 0; k < nincol; k++) {
3704 nStack = 1;
3705 iPivot = mpt[k];
3706 stack[0] = iPivot;
3707 next[0] = 0;
3708 while (nStack) {
3709 int kPivot, j;
3710 /* take off stack */
3711 kPivot = stack[--nStack];
3712 if (nonzero[kPivot] != 1) {
3713 kx = mcstrt[kPivot];
3714 nel = hrowi[kx - 1];
3715 j = next[nStack];
3716 if (j == nel) {
3717 /* finished so mark */
3718 list[nList++] = kPivot;
3719 nonzero[kPivot] = 1;
3720 } else {
3721 kPivot = hrowi[kx + j];
3722 /* put back on stack */
3723 next[nStack++]++;
3724 if (!nonzero[kPivot]) {
3725 /* and new one */
3726 stack[nStack] = kPivot;
3727 nonzero[kPivot] = 2;
3728 next[nStack++] = 0;
3729 /*kkk++;*/
3730 }
3731 }
3732 }
3733 }
3734 }
3735 return (nList);
3736 }
c_ekkftju_sparse_b(COIN_REGISTER2 const EKKfactinfo * COIN_RESTRICT2 fact,double * COIN_RESTRICT dwork1,double * COIN_RESTRICT dworko,int * COIN_RESTRICT mpt,int nList,int * COIN_RESTRICT spare)3737 static int c_ekkftju_sparse_b(COIN_REGISTER2 const EKKfactinfo *COIN_RESTRICT2 fact,
3738 double *COIN_RESTRICT dwork1,
3739 double *COIN_RESTRICT dworko, int *COIN_RESTRICT mpt,
3740 int nList, int *COIN_RESTRICT spare)
3741 {
3742
3743 const double *COIN_RESTRICT dluval = fact->xeeadr + 1;
3744 const int *COIN_RESTRICT hrowi = fact->xeradr + 1;
3745 const int *COIN_RESTRICT mcstrt = fact->xcsadr;
3746 const int *COIN_RESTRICT hpivro = fact->krpadr;
3747 double tolerance = fact->zeroTolerance;
3748 char *COIN_RESTRICT nonzero = fact->nonzero;
3749 int i, k, kx, nel;
3750 int iPivot;
3751 /*int kkk=nincol;*/
3752 int *COIN_RESTRICT list = spare;
3753 i = nList - 1;
3754 nList = 0;
3755 for (; i >= 0; i--) {
3756 double dpiv;
3757 double dv;
3758 iPivot = list[i];
3759 /*printf("pivot %d %d\n",i,iPivot);*/
3760 dv = dwork1[iPivot];
3761 kx = mcstrt[iPivot];
3762 nel = hrowi[kx - 1];
3763 dwork1[iPivot] = 0.0;
3764 dpiv = dluval[kx - 1];
3765 dv *= dpiv;
3766 nonzero[iPivot] = 0;
3767 iPivot = hpivro[iPivot];
3768 if (fabs(dv) >= tolerance) {
3769 *dworko++ = dv;
3770 mpt[nList++] = iPivot - 1;
3771 for (k = kx; k < kx + nel; k++) {
3772 double dval;
3773 double dd;
3774 int irow = hrowi[k];
3775 dval = dluval[k];
3776 dd = dwork1[irow];
3777 dd -= dv * dval;
3778 dwork1[irow] = dd;
3779 }
3780 }
3781 }
3782 return (nList);
3783 }
3784 /* dwork1 = (B^-1)dwork1;
3785 * I think dpermu[1..nrow+1] is zeroed on exit (?)
3786 * I don't think it is expected to have any particular value on entry (?)
3787 */
c_ekkftrn(COIN_REGISTER const EKKfactinfo * COIN_RESTRICT2 fact,double * COIN_RESTRICT dwork1,double * COIN_RESTRICT dpermu,int * COIN_RESTRICT mpt,int numberNonZero)3788 int c_ekkftrn(COIN_REGISTER const EKKfactinfo *COIN_RESTRICT2 fact,
3789 double *COIN_RESTRICT dwork1,
3790 double *COIN_RESTRICT dpermu, int *COIN_RESTRICT mpt, int numberNonZero)
3791 {
3792 const int *COIN_RESTRICT mpermu = fact->mpermu;
3793 int lastNonZero;
3794 int firstNonZero = c_ekkshfpi_list2(mpermu + 1, dwork1 + 1, dpermu, mpt,
3795 numberNonZero, &lastNonZero);
3796 if (fact->nnentl && lastNonZero >= fact->firstLRow) {
3797 /* dpermu = (L^-1)dpermu */
3798 c_ekkftj4p(fact, dpermu, firstNonZero);
3799 }
3800
3801 int lastSlack;
3802
3803 /* dpermu = (R^-1) dpermu */
3804 c_ekkftjl(fact, dpermu);
3805
3806 assert(fact->numberSlacks != 0 || !fact->lastSlack);
3807 lastSlack = fact->lastSlack;
3808
3809 /* dwork1 = (U^-1)dpermu; dpermu zeroed (?) */
3810 return c_ekkftjup(fact,
3811 dpermu, lastSlack, dwork1, mpt);
3812
3813 } /* c_ekkftrn */
3814
c_ekkftrn_ft(COIN_REGISTER EKKfactinfo * COIN_RESTRICT2 fact,double * COIN_RESTRICT dwork1_ft,int * COIN_RESTRICT mpt_ft,int * nincolp_ft)3815 int c_ekkftrn_ft(COIN_REGISTER EKKfactinfo *COIN_RESTRICT2 fact,
3816 double *COIN_RESTRICT dwork1_ft, int *COIN_RESTRICT mpt_ft, int *nincolp_ft)
3817 {
3818 double *COIN_RESTRICT dpermu_ft = fact->kadrpm;
3819 int *COIN_RESTRICT spare = reinterpret_cast< int * >(fact->kp1adr);
3820 int nincol = *nincolp_ft;
3821
3822 int nuspik;
3823 double *COIN_RESTRICT dluvalPut = fact->xeeadr + fact->nnentu + 1;
3824 int *COIN_RESTRICT hrowiPut = fact->xeradr + fact->nnentu + 1;
3825
3826 const int nrow = fact->nrow;
3827 /* mpermu contains the permutation */
3828 const int *COIN_RESTRICT mpermu = fact->mpermu;
3829
3830 int lastSlack;
3831
3832 int kdnspt = fact->nnetas - fact->nnentl;
3833 bool isRoom = (fact->nnentu + (nrow << 1) < (kdnspt - 2)
3834 + fact->R_etas_start[fact->nR_etas + 1]);
3835
3836 /* say F-T will be sorted */
3837 fact->sortedEta = 1;
3838
3839 assert(fact->numberSlacks != 0 || !fact->lastSlack);
3840 lastSlack = fact->lastSlack;
3841 #ifdef CLP_REUSE_ETAS
3842 bool skipStuff = (fact->reintro >= 0);
3843
3844 int save_nR_etas = fact->nR_etas;
3845 int *save_hpivcoR = fact->hpivcoR;
3846 int *save_R_etas_start = fact->R_etas_start;
3847 if (skipStuff) {
3848 // just move
3849 int *putSeq = fact->xrsadr + 2 * fact->nrowmx + 2;
3850 int *position = putSeq + fact->maxinv;
3851 int *putStart = position + fact->maxinv;
3852 memset(dwork1_ft, 0, nincol * sizeof(double));
3853 int iPiv = fact->reintro;
3854 int start = putStart[iPiv] & 0x7fffffff;
3855 int end = putStart[iPiv + 1] & 0x7fffffff;
3856 double *COIN_RESTRICT dluval = fact->xeeadr;
3857 int *COIN_RESTRICT hrowi = fact->xeradr;
3858 double dValue;
3859 if (fact->reintro < fact->nrow) {
3860 iPiv++;
3861 dValue = 1.0 / dluval[start++];
3862 } else {
3863 iPiv = hrowi[--end];
3864 dValue = dluval[end];
3865 start++;
3866 int ndoSkip = 0;
3867 for (int i = fact->nrow; i < fact->reintro; i++) {
3868 if ((putStart[i] & 0x80000000) == 0)
3869 ndoSkip++;
3870 }
3871 fact->nR_etas -= ndoSkip;
3872 fact->hpivcoR += ndoSkip;
3873 fact->R_etas_start += ndoSkip;
3874 }
3875 dpermu_ft[iPiv] = dValue;
3876 if (fact->if_sparse_update > 0 && DENSE_THRESHOLD < nrow) {
3877 nincol = 0;
3878 if (dValue)
3879 mpt_ft[nincol++] = iPiv;
3880 for (int i = start; i < end; i++) {
3881 int iRow = hrowi[i];
3882 dpermu_ft[iRow] = dluval[i];
3883 mpt_ft[nincol++] = iRow;
3884 }
3885 } else {
3886 for (int i = start; i < end; i++) {
3887 int iRow = hrowi[i];
3888 dpermu_ft[iRow] = dluval[i];
3889 }
3890 }
3891 }
3892 #else
3893 bool skipStuff = false;
3894 #endif
3895 if (fact->if_sparse_update > 0 && DENSE_THRESHOLD < nrow) {
3896 if (!skipStuff) {
3897 /* iterating so c_ekkgtcl will have list */
3898 /* in order for this to make sense, nonzero[1..nrow] must already be zeroed */
3899 c_ekkshfpi_list3(mpermu + 1, dwork1_ft, dpermu_ft, mpt_ft, nincol);
3900
3901 /* it may be the case that the basis was entirely upper-triangular */
3902 if (fact->nnentl) {
3903 nincol = c_ekkftj4_sparse(fact,
3904 dpermu_ft, mpt_ft,
3905 nincol, spare);
3906 }
3907 }
3908 /* DO ROW ETAS IN L */
3909 if (isRoom) {
3910 ++fact->nnentu;
3911 nincol = c_ekkftjl_sparse3(fact,
3912 dpermu_ft,
3913 mpt_ft, hrowiPut,
3914 dluvalPut, nincol);
3915 nuspik = nincol;
3916 /* temporary */
3917 /* say not sorted */
3918 fact->sortedEta = 0;
3919 } else {
3920 /* no room */
3921 nuspik = -3;
3922 nincol = c_ekkftjl_sparse2(fact,
3923 dpermu_ft,
3924 mpt_ft, nincol);
3925 }
3926 /* DO U */
3927 if (DENSE_THRESHOLD > nrow - fact->numberSlacks) {
3928 nincol = c_ekkftjup_pack(fact,
3929 dpermu_ft, lastSlack, dwork1_ft,
3930 mpt_ft);
3931 } else {
3932 nincol = c_ekkftju_sparse_a(fact,
3933 mpt_ft,
3934 nincol, spare);
3935 nincol = c_ekkftju_sparse_b(fact,
3936 dpermu_ft,
3937 dwork1_ft, mpt_ft,
3938 nincol, spare);
3939 }
3940 } else {
3941 if (!skipStuff) {
3942 int lastNonZero;
3943 int firstNonZero = c_ekkshfpi_list(mpermu + 1, dwork1_ft, dpermu_ft,
3944 mpt_ft, nincol, &lastNonZero);
3945 if (fact->nnentl && lastNonZero >= fact->firstLRow) {
3946 /* dpermu_ft = (L^-1)dpermu_ft */
3947 c_ekkftj4p(fact, dpermu_ft, firstNonZero);
3948 }
3949 }
3950
3951 /* dpermu_ft = (R^-1) dpermu_ft */
3952 c_ekkftjl(fact, dpermu_ft);
3953
3954 if (isRoom) {
3955
3956 /* fake start to allow room for pivot */
3957 /* dluval[fact->nnentu...] = non-zeros of dpermu_ft;
3958 * hrowi[fact->nnentu..] = indices of these non-zeros;
3959 * near-zeros in dluval flattened
3960 */
3961 ++fact->nnentu;
3962 nincol = c_ekkscmv(fact, fact->nrow, dpermu_ft, hrowiPut,
3963 dluvalPut);
3964
3965 /*
3966 * note that this is not the value of nincol determined by c_ekkftjup.
3967 * For Forrest-Tomlin update we want vector before U
3968 * this vector will replace one in U
3969 */
3970 nuspik = nincol;
3971 } else {
3972 /* no room */
3973 nuspik = -3;
3974 }
3975
3976 /* dwork1_ft = (U^-1)dpermu_ft; dpermu_ft zeroed (?) */
3977 nincol = c_ekkftjup_pack(fact,
3978 dpermu_ft, lastSlack, dwork1_ft, mpt_ft);
3979 }
3980 #ifdef CLP_REUSE_ETAS
3981 fact->nR_etas = save_nR_etas;
3982 fact->hpivcoR = save_hpivcoR;
3983 fact->R_etas_start = save_R_etas_start;
3984 #endif
3985
3986 *nincolp_ft = nincol;
3987 return (nuspik);
3988 } /* c_ekkftrn */
c_ekkftrn2(COIN_REGISTER EKKfactinfo * COIN_RESTRICT2 fact,double * COIN_RESTRICT dwork1,double * COIN_RESTRICT dpermu1,int * COIN_RESTRICT mpt1,int * nincolp,double * COIN_RESTRICT dwork1_ft,int * COIN_RESTRICT mpt_ft,int * nincolp_ft)3989 void c_ekkftrn2(COIN_REGISTER EKKfactinfo *COIN_RESTRICT2 fact, double *COIN_RESTRICT dwork1,
3990 double *COIN_RESTRICT dpermu1, int *COIN_RESTRICT mpt1, int *nincolp,
3991 double *COIN_RESTRICT dwork1_ft, int *COIN_RESTRICT mpt_ft, int *nincolp_ft)
3992 {
3993 double *COIN_RESTRICT dluvalPut = fact->xeeadr + fact->nnentu + 1;
3994 int *COIN_RESTRICT hrowiPut = fact->xeradr + fact->nnentu + 1;
3995
3996 const int nrow = fact->nrow;
3997 /* mpermu contains the permutation */
3998 const int *COIN_RESTRICT mpermu = fact->mpermu;
3999
4000 int lastSlack;
4001 assert(fact->numberSlacks != 0 || !fact->lastSlack);
4002 lastSlack = fact->lastSlack;
4003
4004 int nincol = *nincolp_ft;
4005
4006 /* using dwork1 instead double *dpermu_ft = fact->kadrpm; */
4007 int *spare = reinterpret_cast< int * >(fact->kp1adr);
4008
4009 int kdnspt = fact->nnetas - fact->nnentl;
4010 bool isRoom = (fact->nnentu + (nrow << 1) < (kdnspt - 2)
4011 + fact->R_etas_start[fact->nR_etas + 1]);
4012 /* say F-T will be sorted */
4013 fact->sortedEta = 1;
4014 int lastNonZero;
4015 int firstNonZero = c_ekkshfpi_list2(mpermu + 1, dwork1 + 1, dpermu1,
4016 mpt1, *nincolp, &lastNonZero);
4017 if (fact->nnentl && lastNonZero >= fact->firstLRow) {
4018 /* dpermu1 = (L^-1)dpermu1 */
4019 c_ekkftj4p(fact, dpermu1, firstNonZero);
4020 }
4021
4022 #ifdef CLP_REUSE_ETAS
4023 bool skipStuff = (fact->reintro >= 0);
4024 int save_nR_etas = fact->nR_etas;
4025 int *save_hpivcoR = fact->hpivcoR;
4026 int *save_R_etas_start = fact->R_etas_start;
4027 if (skipStuff) {
4028 // just move
4029 int *putSeq = fact->xrsadr + 2 * fact->nrowmx + 2;
4030 int *position = putSeq + fact->maxinv;
4031 int *putStart = position + fact->maxinv;
4032 memset(dwork1_ft, 0, nincol * sizeof(double));
4033 int iPiv = fact->reintro;
4034 int start = putStart[iPiv] & 0x7fffffff;
4035 int end = putStart[iPiv + 1] & 0x7fffffff;
4036 double *COIN_RESTRICT dluval = fact->xeeadr;
4037 int *COIN_RESTRICT hrowi = fact->xeradr;
4038 double dValue;
4039 if (fact->reintro < fact->nrow) {
4040 iPiv++;
4041 dValue = 1.0 / dluval[start++];
4042 } else {
4043 iPiv = hrowi[--end];
4044 dValue = dluval[end];
4045 start++;
4046 int ndoSkip = 0;
4047 for (int i = fact->nrow; i < fact->reintro; i++) {
4048 if ((putStart[i] & 0x80000000) == 0)
4049 ndoSkip++;
4050 }
4051 fact->nR_etas -= ndoSkip;
4052 fact->hpivcoR += ndoSkip;
4053 fact->R_etas_start += ndoSkip;
4054 }
4055 dwork1[iPiv] = dValue;
4056 if (fact->if_sparse_update > 0 && DENSE_THRESHOLD < nrow) {
4057 nincol = 0;
4058 if (dValue)
4059 mpt_ft[nincol++] = iPiv;
4060 for (int i = start; i < end; i++) {
4061 int iRow = hrowi[i];
4062 dwork1[iRow] = dluval[i];
4063 mpt_ft[nincol++] = iRow;
4064 }
4065 } else {
4066 for (int i = start; i < end; i++) {
4067 int iRow = hrowi[i];
4068 dwork1[iRow] = dluval[i];
4069 }
4070 }
4071 }
4072 #else
4073 bool skipStuff = false;
4074 #endif
4075 if (fact->if_sparse_update > 0 && DENSE_THRESHOLD < nrow) {
4076 if (!skipStuff) {
4077 /* iterating so c_ekkgtcl will have list */
4078 /* in order for this to make sense, nonzero[1..nrow] must already be zeroed */
4079 c_ekkshfpi_list3(mpermu + 1, dwork1_ft, dwork1, mpt_ft, nincol);
4080
4081 /* it may be the case that the basis was entirely upper-triangular */
4082 if (fact->nnentl) {
4083 nincol = c_ekkftj4_sparse(fact,
4084 dwork1, mpt_ft,
4085 nincol, spare);
4086 }
4087 }
4088 /* DO ROW ETAS IN L */
4089 if (isRoom) {
4090 ++fact->nnentu;
4091 nincol = c_ekkftjl_sparse3(fact,
4092 dwork1,
4093 mpt_ft, hrowiPut,
4094 dluvalPut,
4095 nincol);
4096 fact->nuspike = nincol;
4097 /* say not sorted */
4098 fact->sortedEta = 0;
4099 } else {
4100 /* no room */
4101 fact->nuspike = -3;
4102 nincol = c_ekkftjl_sparse2(fact,
4103 dwork1,
4104 mpt_ft, nincol);
4105 }
4106 } else {
4107 if (!skipStuff) {
4108 int lastNonZero;
4109 int firstNonZero = c_ekkshfpi_list(mpermu + 1, dwork1_ft, dwork1,
4110 mpt_ft, nincol, &lastNonZero);
4111 if (fact->nnentl && lastNonZero >= fact->firstLRow) {
4112 /* dpermu_ft = (L^-1)dpermu_ft */
4113 c_ekkftj4p(fact, dwork1, firstNonZero);
4114 }
4115 }
4116 c_ekkftjl(fact, dwork1);
4117
4118 if (isRoom) {
4119
4120 /* fake start to allow room for pivot */
4121 /* dluval[fact->nnentu...] = non-zeros of dpermu_ft;
4122 * hrowi[fact->nnentu..] = indices of these non-zeros;
4123 * near-zeros in dluval flattened
4124 */
4125 ++fact->nnentu;
4126 nincol = c_ekkscmv(fact, fact->nrow, dwork1,
4127 hrowiPut,
4128 dluvalPut);
4129
4130 /*
4131 * note that this is not the value of nincol determined by c_ekkftjup.
4132 * For Forrest-Tomlin update we want vector before U
4133 * this vector will replace one in U
4134 */
4135 fact->nuspike = nincol;
4136 } else {
4137 /* no room */
4138 fact->nuspike = -3;
4139 }
4140 }
4141 #ifdef CLP_REUSE_ETAS
4142 fact->nR_etas = save_nR_etas;
4143 fact->hpivcoR = save_hpivcoR;
4144 fact->R_etas_start = save_R_etas_start;
4145 #endif
4146
4147 /* dpermu1 = (R^-1) dpermu1 */
4148 c_ekkftjl(fact, dpermu1);
4149
4150 /* DO U */
4151 if (fact->if_sparse_update <= 0 || DENSE_THRESHOLD > nrow - fact->numberSlacks) {
4152 nincol = c_ekkftjup_pack(fact,
4153 dwork1, lastSlack, dwork1_ft, mpt_ft);
4154 } else {
4155 nincol = c_ekkftju_sparse_a(fact,
4156 mpt_ft,
4157 nincol, spare);
4158 nincol = c_ekkftju_sparse_b(fact,
4159 dwork1,
4160 dwork1_ft, mpt_ft,
4161 nincol, spare);
4162 }
4163 *nincolp_ft = nincol;
4164 /* dwork1 = (U^-1)dpermu1; dpermu1 zeroed (?) */
4165 *nincolp = c_ekkftjup(fact,
4166 dpermu1, lastSlack, dwork1, mpt1);
4167 }
4168 #endif
4169
4170 /* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2
4171 */
4172