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