1 /* $Id: CoinFactorization1.cpp 2084 2019-01-09 14:17:08Z forrest $ */
2 // Copyright (C) 2002, International Business Machines
3 // Corporation and others.  All Rights Reserved.
4 // This code is licensed under the terms of the Eclipse Public License (EPL).
5 
6 #if defined(_MSC_VER)
7 // Turn off compiler warning about long names
8 #pragma warning(disable : 4786)
9 #endif
10 
11 #include "CoinUtilsConfig.h"
12 
13 #include <cassert>
14 #include "CoinFactorization.hpp"
15 #include "CoinIndexedVector.hpp"
16 #include "CoinHelperFunctions.hpp"
17 #include "CoinPackedMatrix.hpp"
18 #include "CoinFinite.hpp"
19 #include "CoinTime.hpp"
20 #include <stdio.h>
21 /*
22   Somehow with some BLAS we get multithreaded by default
23   For 99.99% of problems this is not a good idea.
24   The openblas_set_num_threads(1) seems to work even with other blas
25  */
26 #if CLP_USE_OPENBLAS
27 static int blas_initialized = 0;
28 extern "C" {
29 void openblas_set_num_threads(int num_threads);
30 }
31 #endif
32 //:class CoinFactorization.  Deals with Factorization and Updates
33 //  CoinFactorization.  Constructor
CoinFactorization()34 CoinFactorization::CoinFactorization()
35 {
36   persistenceFlag_ = 0;
37   gutsOfInitialize(7);
38 }
39 
40 /// Copy constructor
CoinFactorization(const CoinFactorization & other)41 CoinFactorization::CoinFactorization(const CoinFactorization &other)
42 {
43   persistenceFlag_ = 0;
44   gutsOfInitialize(3);
45   persistenceFlag_ = other.persistenceFlag_;
46   gutsOfCopy(other);
47 }
48 /// The real work of constructors etc
49 /// Really really delete if type 2
gutsOfDestructor(int type)50 void CoinFactorization::gutsOfDestructor(int type)
51 {
52   delete[] denseArea_;
53   delete[] densePermute_;
54   if (type == 2) {
55     elementU_.switchOff();
56     startRowU_.switchOff();
57     convertRowToColumnU_.switchOff();
58     indexRowU_.switchOff();
59     indexColumnU_.switchOff();
60     startColumnU_.switchOff();
61     elementL_.switchOff();
62     indexRowL_.switchOff();
63     startColumnL_.switchOff();
64     startColumnR_.switchOff();
65     numberInRow_.switchOff();
66     numberInColumn_.switchOff();
67     numberInColumnPlus_.switchOff();
68     pivotColumn_.switchOff();
69     pivotColumnBack_.switchOff();
70     firstCount_.switchOff();
71     nextCount_.switchOff();
72     lastCount_.switchOff();
73     permute_.switchOff();
74     permuteBack_.switchOff();
75     nextColumn_.switchOff();
76     lastColumn_.switchOff();
77     nextRow_.switchOff();
78     lastRow_.switchOff();
79     saveColumn_.switchOff();
80     markRow_.switchOff();
81     pivotRowL_.switchOff();
82     pivotRegion_.switchOff();
83     elementByRowL_.switchOff();
84     startRowL_.switchOff();
85     indexColumnL_.switchOff();
86     sparse_.switchOff();
87     workArea_.switchOff();
88     workArea2_.switchOff();
89   }
90   elementU_.conditionalDelete();
91   startRowU_.conditionalDelete();
92   convertRowToColumnU_.conditionalDelete();
93   indexRowU_.conditionalDelete();
94   indexColumnU_.conditionalDelete();
95   startColumnU_.conditionalDelete();
96   elementL_.conditionalDelete();
97   indexRowL_.conditionalDelete();
98   startColumnL_.conditionalDelete();
99   startColumnR_.conditionalDelete();
100   numberInRow_.conditionalDelete();
101   numberInColumn_.conditionalDelete();
102   numberInColumnPlus_.conditionalDelete();
103   pivotColumn_.conditionalDelete();
104   pivotColumnBack_.conditionalDelete();
105   firstCount_.conditionalDelete();
106   nextCount_.conditionalDelete();
107   lastCount_.conditionalDelete();
108   permute_.conditionalDelete();
109   permuteBack_.conditionalDelete();
110   nextColumn_.conditionalDelete();
111   lastColumn_.conditionalDelete();
112   nextRow_.conditionalDelete();
113   lastRow_.conditionalDelete();
114   saveColumn_.conditionalDelete();
115   markRow_.conditionalDelete();
116   pivotRowL_.conditionalDelete();
117   pivotRegion_.conditionalDelete();
118   elementByRowL_.conditionalDelete();
119   startRowL_.conditionalDelete();
120   indexColumnL_.conditionalDelete();
121   sparse_.conditionalDelete();
122   workArea_.conditionalDelete();
123   workArea2_.conditionalDelete();
124   numberCompressions_ = 0;
125   biggerDimension_ = 0;
126   numberRows_ = 0;
127   numberRowsExtra_ = 0;
128   maximumRowsExtra_ = 0;
129   numberColumns_ = 0;
130   numberColumnsExtra_ = 0;
131   maximumColumnsExtra_ = 0;
132   numberGoodU_ = 0;
133   numberGoodL_ = 0;
134   totalElements_ = 0;
135   factorElements_ = 0;
136   status_ = -1;
137   numberSlacks_ = 0;
138   numberU_ = 0;
139   maximumU_ = 0;
140   lengthU_ = 0;
141   lengthAreaU_ = 0;
142   numberL_ = 0;
143   baseL_ = 0;
144   lengthL_ = 0;
145   lengthAreaL_ = 0;
146   numberR_ = 0;
147   lengthR_ = 0;
148   lengthAreaR_ = 0;
149   denseArea_ = NULL;
150   densePermute_ = NULL;
151   // next two offsets but this makes cleaner
152   elementR_ = NULL;
153   indexRowR_ = NULL;
154   numberDense_ = 0;
155   //persistenceFlag_=0;
156   ////denseThreshold_=0;
157 }
158 // type - 1 bit tolerances etc, 2 rest
gutsOfInitialize(int type)159 void CoinFactorization::gutsOfInitialize(int type)
160 {
161 #if CLP_USE_OPENBLAS
162   if (!blas_initialized) {
163     blas_initialized = 1;
164     openblas_set_num_threads(CLP_USE_OPENBLAS);
165   }
166 #endif
167   if ((type & 2) != 0) {
168     numberCompressions_ = 0;
169     biggerDimension_ = 0;
170     numberRows_ = 0;
171     numberRowsExtra_ = 0;
172     maximumRowsExtra_ = 0;
173     numberColumns_ = 0;
174     numberColumnsExtra_ = 0;
175     maximumColumnsExtra_ = 0;
176     numberGoodU_ = 0;
177     numberGoodL_ = 0;
178     totalElements_ = 0;
179     factorElements_ = 0;
180     status_ = -1;
181     numberPivots_ = 0;
182     numberSlacks_ = 0;
183     numberU_ = 0;
184     maximumU_ = 0;
185     lengthU_ = 0;
186     lengthAreaU_ = 0;
187     numberL_ = 0;
188     baseL_ = 0;
189     lengthL_ = 0;
190     lengthAreaL_ = 0;
191     numberR_ = 0;
192     lengthR_ = 0;
193     lengthAreaR_ = 0;
194     elementR_ = NULL;
195     indexRowR_ = NULL;
196     // always switch off sparse
197     sparseThreshold_ = 0;
198     sparseThreshold2_ = 0;
199     denseArea_ = NULL;
200     densePermute_ = NULL;
201     numberDense_ = 0;
202     if (!persistenceFlag_) {
203       workArea_ = CoinFactorizationDoubleArrayWithLength();
204       workArea2_ = CoinUnsignedIntArrayWithLength();
205       pivotColumn_ = CoinIntArrayWithLength();
206     }
207   }
208   // after 2 because of persistenceFlag_
209   if ((type & 1) != 0) {
210     areaFactor_ = 0.0;
211     pivotTolerance_ = 1.0e-1;
212     zeroTolerance_ = 1.0e-13;
213 #ifndef COIN_FAST_CODE
214     slackValue_ = -1.0;
215 #endif
216     messageLevel_ = 0;
217     maximumPivots_ = 200;
218     numberTrials_ = 4;
219     relaxCheck_ = 1.0;
220 #if COIN_FACTORIZATION_DENSE_CODE
221     denseThreshold_ = 31;
222     denseThreshold_ = 71;
223 #else
224     denseThreshold_ = 0;
225 #endif
226     biasLU_ = 2;
227     doForrestTomlin_ = true;
228     persistenceFlag_ = 0;
229   }
230   if ((type & 4) != 0) {
231     // we need to get 1 element arrays for any with length n+1 !!
232     startColumnL_.conditionalNew(1);
233     startColumnR_.conditionalNew(1);
234     startRowU_.conditionalNew(1);
235     numberInRow_.conditionalNew(1);
236     nextRow_.conditionalNew(1);
237     lastRow_.conditionalNew(1);
238     pivotRegion_.conditionalNew(1);
239     permuteBack_.conditionalNew(1);
240     permute_.conditionalNew(1);
241     pivotColumnBack_.conditionalNew(1);
242     startColumnU_.conditionalNew(1);
243     numberInColumn_.conditionalNew(1);
244     numberInColumnPlus_.conditionalNew(1);
245     pivotColumn_.conditionalNew(1);
246     nextColumn_.conditionalNew(1);
247     lastColumn_.conditionalNew(1);
248 #if 0
249     collectStatistics_=false;
250 #endif
251 
252     // Below are all to collect
253     ftranCountInput_ = 0.0;
254     ftranCountAfterL_ = 0.0;
255     ftranCountAfterR_ = 0.0;
256     ftranCountAfterU_ = 0.0;
257     btranCountInput_ = 0.0;
258     btranCountAfterU_ = 0.0;
259     btranCountAfterR_ = 0.0;
260     btranCountAfterL_ = 0.0;
261 
262     // We can roll over factorizations
263     numberFtranCounts_ = 0;
264     numberBtranCounts_ = 0;
265 
266     // While these are averages collected over last
267     ftranAverageAfterL_ = 0;
268     ftranAverageAfterR_ = 0;
269     ftranAverageAfterU_ = 0;
270     btranAverageAfterU_ = 0;
271     btranAverageAfterR_ = 0;
272     btranAverageAfterL_ = 0;
273 #ifdef ZEROFAULT
274     startColumnL_.array()[0] = 0;
275     startColumnR_.array()[0] = 0;
276     startRowU_.array()[0] = 0;
277     numberInRow_.array()[0] = 0;
278     nextRow_.array()[0] = 0;
279     lastRow_.array()[0] = 0;
280     pivotRegion_.array()[0] = 0.0;
281     permuteBack_.array()[0] = 0;
282     permute_.array()[0] = 0;
283     pivotColumnBack_.array()[0] = 0;
284     startColumnU_.array()[0] = 0;
285     numberInColumn_.array()[0] = 0;
286     numberInColumnPlus_.array()[0] = 0;
287     pivotColumn_.array()[0] = 0;
288     nextColumn_.array()[0] = 0;
289     lastColumn_.array()[0] = 0;
290 #endif
291   }
292 }
293 //Part of LP
factorize(const CoinPackedMatrix & matrix,int rowIsBasic[],int columnIsBasic[],double areaFactor)294 int CoinFactorization::factorize(
295   const CoinPackedMatrix &matrix,
296   int rowIsBasic[],
297   int columnIsBasic[],
298   double areaFactor)
299 {
300   // maybe for speed will be better to leave as many regions as possible
301   gutsOfDestructor();
302   gutsOfInitialize(2);
303   // ? is this correct
304   //if (biasLU_==2)
305   //biasLU_=3;
306   if (areaFactor)
307     areaFactor_ = areaFactor;
308   const int *row = matrix.getIndices();
309   const CoinBigIndex *columnStart = matrix.getVectorStarts();
310   const int *columnLength = matrix.getVectorLengths();
311   const double *element = matrix.getElements();
312   int numberRows = matrix.getNumRows();
313   if (!numberRows)
314     return 0;
315   int numberColumns = matrix.getNumCols();
316   int numberBasic = 0;
317   int numberElements = 0;
318   int numberRowBasic = 0;
319 
320   // compute how much in basis
321 
322   int i;
323 
324   for (i = 0; i < numberRows; i++) {
325     if (rowIsBasic[i] >= 0)
326       numberRowBasic++;
327   }
328 
329   numberBasic = numberRowBasic;
330 
331   for (i = 0; i < numberColumns; i++) {
332     if (columnIsBasic[i] >= 0) {
333       numberBasic++;
334       numberElements += columnLength[i];
335     }
336   }
337   if (numberBasic > numberRows) {
338     return -2; // say too many in basis
339   }
340   numberElements = 3 * numberBasic + 3 * numberElements + 20000;
341   getAreas(numberRows, numberBasic, numberElements,
342     2 * numberElements);
343   //fill
344   //copy
345   numberBasic = 0;
346   numberElements = 0;
347   int *indexColumnU = indexColumnU_.array();
348   int *indexRowU = indexRowU_.array();
349   CoinFactorizationDouble *elementU = elementU_.array();
350   for (i = 0; i < numberRows; i++) {
351     if (rowIsBasic[i] >= 0) {
352       indexRowU[numberElements] = i;
353       indexColumnU[numberElements] = numberBasic;
354       elementU[numberElements++] = slackValue_;
355       numberBasic++;
356     }
357   }
358   for (i = 0; i < numberColumns; i++) {
359     if (columnIsBasic[i] >= 0) {
360       CoinBigIndex j;
361       for (j = columnStart[i]; j < columnStart[i] + columnLength[i]; j++) {
362         indexRowU[numberElements] = row[j];
363         indexColumnU[numberElements] = numberBasic;
364         elementU[numberElements++] = element[j];
365       }
366       numberBasic++;
367     }
368   }
369   lengthU_ = numberElements;
370   maximumU_ = numberElements;
371 
372   preProcess(0);
373   factor();
374   numberBasic = 0;
375   if (status_ == 0) {
376     int *permuteBack = permuteBack_.array();
377     int *back = pivotColumnBack();
378     for (i = 0; i < numberRows; i++) {
379       if (rowIsBasic[i] >= 0) {
380         rowIsBasic[i] = permuteBack[back[numberBasic++]];
381       }
382     }
383     for (i = 0; i < numberColumns; i++) {
384       if (columnIsBasic[i] >= 0) {
385         columnIsBasic[i] = permuteBack[back[numberBasic++]];
386       }
387     }
388     // Set up permutation vector
389     // these arrays start off as copies of permute
390     // (and we could use permute_ instead of pivotColumn (not back though))
391     CoinMemcpyN(permute_.array(), numberRows_, pivotColumn_.array());
392     CoinMemcpyN(permuteBack_.array(), numberRows_, pivotColumnBack());
393   } else if (status_ == -1) {
394     const int *pivotColumn = pivotColumn_.array();
395     // mark as basic or non basic
396     for (i = 0; i < numberRows_; i++) {
397       if (rowIsBasic[i] >= 0) {
398         if (pivotColumn[numberBasic] >= 0)
399           rowIsBasic[i] = pivotColumn[numberBasic];
400         else
401           rowIsBasic[i] = -1;
402         numberBasic++;
403       }
404     }
405     for (i = 0; i < numberColumns; i++) {
406       if (columnIsBasic[i] >= 0) {
407         if (pivotColumn[numberBasic] >= 0)
408           columnIsBasic[i] = pivotColumn[numberBasic];
409         else
410           columnIsBasic[i] = -1;
411         numberBasic++;
412       }
413     }
414   }
415 
416   return status_;
417 }
418 //Given as triplets
factorize(int numberOfRows,int numberOfColumns,int numberOfElements,int maximumL,int maximumU,const int indicesRow[],const int indicesColumn[],const double elements[],int permutation[],double areaFactor)419 int CoinFactorization::factorize(
420   int numberOfRows,
421   int numberOfColumns,
422   int numberOfElements,
423   int maximumL,
424   int maximumU,
425   const int indicesRow[],
426   const int indicesColumn[],
427   const double elements[],
428   int permutation[],
429   double areaFactor)
430 {
431   gutsOfDestructor();
432   gutsOfInitialize(2);
433   if (areaFactor)
434     areaFactor_ = areaFactor;
435   getAreas(numberOfRows, numberOfColumns, maximumL, maximumU);
436   //copy
437   CoinMemcpyN(indicesRow, numberOfElements, indexRowU_.array());
438   CoinMemcpyN(indicesColumn, numberOfElements, indexColumnU_.array());
439   int i;
440   CoinFactorizationDouble *elementU = elementU_.array();
441   for (i = 0; i < numberOfElements; i++)
442     elementU[i] = elements[i];
443   lengthU_ = numberOfElements;
444   maximumU_ = numberOfElements;
445   preProcess(0);
446   factor();
447   //say which column is pivoting on which row
448   if (status_ == 0) {
449     int *permuteBack = permuteBack_.array();
450     int *back = pivotColumnBack();
451     // permute so slacks on own rows etc
452     for (i = 0; i < numberOfColumns; i++) {
453       permutation[i] = permuteBack[back[i]];
454     }
455     // Set up permutation vector
456     // these arrays start off as copies of permute
457     // (and we could use permute_ instead of pivotColumn (not back though))
458     CoinMemcpyN(permute_.array(), numberRows_, pivotColumn_.array());
459     CoinMemcpyN(permuteBack_.array(), numberRows_, pivotColumnBack());
460   } else if (status_ == -1) {
461     const int *pivotColumn = pivotColumn_.array();
462     // mark as basic or non basic
463     for (i = 0; i < numberOfColumns; i++) {
464       if (pivotColumn[i] >= 0) {
465         permutation[i] = pivotColumn[i];
466       } else {
467         permutation[i] = -1;
468       }
469     }
470   }
471 
472   return status_;
473 }
474 /* Two part version for flexibility
475    This part creates arrays for user to fill.
476    maximumL is guessed maximum size of L part of
477    final factorization, maximumU of U part.  These are multiplied by
478    areaFactor which can be computed by user or internally.
479    returns 0 -okay, -99 memory */
factorizePart1(int numberOfRows,int,int numberOfElements,int * indicesRow[],int * indicesColumn[],CoinFactorizationDouble * elements[],double areaFactor)480 int CoinFactorization::factorizePart1(int numberOfRows,
481   int,
482   int numberOfElements,
483   int *indicesRow[],
484   int *indicesColumn[],
485   CoinFactorizationDouble *elements[],
486   double areaFactor)
487 {
488   // maybe for speed will be better to leave as many regions as possible
489   gutsOfDestructor();
490   gutsOfInitialize(2);
491   if (areaFactor)
492     areaFactor_ = areaFactor;
493   int numberElements = 3 * numberOfRows + 3 * numberOfElements + 20000;
494   getAreas(numberOfRows, numberOfRows, numberElements,
495     2 * numberElements);
496   // need to trap memory for -99 code
497   *indicesRow = indexRowU_.array();
498   *indicesColumn = indexColumnU_.array();
499   *elements = elementU_.array();
500   lengthU_ = numberOfElements;
501   maximumU_ = numberElements;
502   return 0;
503 }
504 /* This is part two of factorization
505    Arrays belong to factorization and were returned by part 1
506    If status okay, permutation has pivot rows.
507    If status is singular, then basic variables have +1 and ones thrown out have -COIN_INT_MAX
508    to say thrown out.
509    returns 0 -okay, -1 singular, -99 memory */
factorizePart2(int permutation[],int exactNumberElements)510 int CoinFactorization::factorizePart2(int permutation[], int exactNumberElements)
511 {
512   lengthU_ = exactNumberElements;
513   preProcess(0);
514   factor();
515   //say which column is pivoting on which row
516   int i;
517   int *permuteBack = permuteBack_.array();
518   int *back = pivotColumnBack();
519   // permute so slacks on own rows etc
520   for (i = 0; i < numberColumns_; i++) {
521     permutation[i] = permuteBack[back[i]];
522   }
523   if (status_ == 0) {
524     // Set up permutation vector
525     // these arrays start off as copies of permute
526     // (and we could use permute_ instead of pivotColumn (not back though))
527     CoinMemcpyN(permute_.array(), numberRows_, pivotColumn_.array());
528     CoinMemcpyN(permuteBack_.array(), numberRows_, pivotColumnBack());
529   } else if (status_ == -1) {
530     const int *pivotColumn = pivotColumn_.array();
531     // mark as basic or non basic
532     for (i = 0; i < numberColumns_; i++) {
533       if (pivotColumn[i] >= 0) {
534         permutation[i] = pivotColumn[i];
535       } else {
536         permutation[i] = -1;
537       }
538     }
539   }
540 
541   return status_;
542 }
543 
544 //  ~CoinFactorization.  Destructor
~CoinFactorization()545 CoinFactorization::~CoinFactorization()
546 {
547   gutsOfDestructor(2);
548 }
549 
550 //  show_self.  Debug show object
show_self() const551 void CoinFactorization::show_self() const
552 {
553   int i;
554 
555   const int *pivotColumn = pivotColumn_.array();
556   for (i = 0; i < numberRows_; i++) {
557     std::cout << "r " << i << " " << pivotColumn[i];
558     if (pivotColumnBack())
559       std::cout << " " << pivotColumnBack()[i];
560     std::cout << " " << permute_.array()[i];
561     if (permuteBack_.array())
562       std::cout << " " << permuteBack_.array()[i];
563     std::cout << " " << pivotRegion_.array()[i];
564     std::cout << std::endl;
565   }
566   for (i = 0; i < numberRows_; i++) {
567     std::cout << "u " << i << " " << numberInColumn_.array()[i] << std::endl;
568     int j;
569     CoinSort_2(indexRowU_.array() + startColumnU_.array()[i],
570       indexRowU_.array() + startColumnU_.array()[i] + numberInColumn_.array()[i],
571       elementU_.array() + startColumnU_.array()[i]);
572     for (j = startColumnU_.array()[i]; j < startColumnU_.array()[i] + numberInColumn_.array()[i];
573          j++) {
574       assert(indexRowU_.array()[j] >= 0 && indexRowU_.array()[j] < numberRows_);
575       assert(elementU_.array()[j] > -1.0e50 && elementU_.array()[j] < 1.0e50);
576       std::cout << indexRowU_.array()[j] << " " << elementU_.array()[j] << std::endl;
577     }
578   }
579   for (i = 0; i < numberRows_; i++) {
580     std::cout << "l " << i << " " << startColumnL_.array()[i + 1] - startColumnL_.array()[i] << std::endl;
581     CoinSort_2(indexRowL_.array() + startColumnL_.array()[i],
582       indexRowL_.array() + startColumnL_.array()[i + 1],
583       elementL_.array() + startColumnL_.array()[i]);
584     int j;
585     for (j = startColumnL_.array()[i]; j < startColumnL_.array()[i + 1]; j++) {
586       std::cout << indexRowL_.array()[j] << " " << elementL_.array()[j] << std::endl;
587     }
588   }
589 }
590 //  sort so can compare
sort() const591 void CoinFactorization::sort() const
592 {
593   int i;
594 
595   for (i = 0; i < numberRows_; i++) {
596     CoinSort_2(indexRowU_.array() + startColumnU_.array()[i],
597       indexRowU_.array() + startColumnU_.array()[i] + numberInColumn_.array()[i],
598       elementU_.array() + startColumnU_.array()[i]);
599   }
600   for (i = 0; i < numberRows_; i++) {
601     CoinSort_2(indexRowL_.array() + startColumnL_.array()[i],
602       indexRowL_.array() + startColumnL_.array()[i + 1],
603       elementL_.array() + startColumnL_.array()[i]);
604   }
605 }
606 
607 //  getAreas.  Gets space for a factorization
608 //called by constructors
getAreas(int numberOfRows,int numberOfColumns,int maximumL,int maximumU)609 void CoinFactorization::getAreas(int numberOfRows,
610   int numberOfColumns,
611   int maximumL,
612   int maximumU)
613 {
614 
615   numberRows_ = numberOfRows;
616   numberColumns_ = numberOfColumns;
617   maximumRowsExtra_ = numberRows_ + maximumPivots_;
618   numberRowsExtra_ = numberRows_;
619   maximumColumnsExtra_ = numberColumns_ + maximumPivots_;
620   numberColumnsExtra_ = numberColumns_;
621   lengthAreaU_ = maximumU;
622   lengthAreaL_ = maximumL;
623   if (!areaFactor_) {
624     areaFactor_ = 1.0;
625   }
626   if (areaFactor_ != 1.0) {
627     if ((messageLevel_ & 16) != 0)
628       printf("Increasing factorization areas by %g\n", areaFactor_);
629     // but keep reasonable
630     if (areaFactor_ * lengthAreaU_ < COIN_INT_MAX)
631       lengthAreaU_ = static_cast< int >(areaFactor_ * lengthAreaU_);
632     else
633       lengthAreaU_ = COIN_INT_MAX;
634     if (areaFactor_ * lengthAreaL_ < COIN_INT_MAX)
635       lengthAreaL_ = static_cast< int >(areaFactor_ * lengthAreaL_);
636     else
637       lengthAreaL_ = COIN_INT_MAX;
638   }
639   int lengthU = lengthAreaU_ + EXTRA_U_SPACE;
640   elementU_.conditionalNew(lengthU);
641   indexRowU_.conditionalNew(lengthU);
642   indexColumnU_.conditionalNew(lengthU);
643   elementL_.conditionalNew(lengthAreaL_);
644   indexRowL_.conditionalNew(lengthAreaL_);
645   if (persistenceFlag_) {
646     // But we can use all we have if bigger
647     int length;
648     length = static_cast< int >(CoinMin(elementU_.getSize(), indexRowU_.getSize())) - lengthU;
649     if (length > lengthAreaU_) {
650       lengthAreaU_ = length;
651       assert(indexColumnU_.getSize() == indexRowU_.getSize());
652     }
653     length = static_cast< int >(CoinMin(elementL_.getSize(), indexRowL_.getSize()));
654     if (length > lengthAreaL_) {
655       lengthAreaL_ = length;
656     }
657   }
658   startColumnL_.conditionalNew(numberRows_ + 1);
659   startColumnL_.array()[0] = 0;
660   startRowU_.conditionalNew(maximumRowsExtra_ + 1);
661   // make sure this is valid
662   startRowU_.array()[maximumRowsExtra_] = 0;
663   numberInRow_.conditionalNew(maximumRowsExtra_ + 1);
664   markRow_.conditionalNew(numberRows_);
665   pivotRowL_.conditionalNew(numberRows_ + 1);
666   nextRow_.conditionalNew(maximumRowsExtra_ + 1);
667   lastRow_.conditionalNew(maximumRowsExtra_ + 1);
668   permute_.conditionalNew(maximumRowsExtra_ + 1);
669   pivotRegion_.conditionalNew(maximumRowsExtra_ + 1);
670 #ifdef ZEROFAULT
671   memset(elementU_.array(), 'a', lengthAreaU_ * sizeof(CoinFactorizationDouble));
672   memset(indexRowU_.array(), 'b', lengthAreaU_ * sizeof(int));
673   memset(indexColumnU_.array(), 'c', lengthAreaU_ * sizeof(int));
674   memset(elementL_.array(), 'd', lengthAreaL_ * sizeof(CoinFactorizationDouble));
675   memset(indexRowL_.array(), 'e', lengthAreaL_ * sizeof(int));
676   memset(startColumnL_.array() + 1, 'f', numberRows_ * sizeof(int));
677   memset(startRowU_.array(), 'g', maximumRowsExtra_ * sizeof(int));
678   memset(numberInRow_.array(), 'h', (maximumRowsExtra_ + 1) * sizeof(int));
679   memset(markRow_.array(), 'i', numberRows_ * sizeof(int));
680   memset(pivotRowL_.array(), 'j', (numberRows_ + 1) * sizeof(int));
681   memset(nextRow_.array(), 'k', (maximumRowsExtra_ + 1) * sizeof(int));
682   memset(lastRow_.array(), 'l', (maximumRowsExtra_ + 1) * sizeof(int));
683   memset(permute_.array(), 'l', (maximumRowsExtra_ + 1) * sizeof(int));
684   memset(pivotRegion_.array(), 'm', (maximumRowsExtra_ + 1) * sizeof(CoinFactorizationDouble));
685 #endif
686   startColumnU_.conditionalNew(maximumColumnsExtra_ + 1);
687   numberInColumn_.conditionalNew(maximumColumnsExtra_ + 1);
688   numberInColumnPlus_.conditionalNew(maximumColumnsExtra_ + 1);
689   pivotColumn_.conditionalNew(maximumColumnsExtra_ + 1);
690   nextColumn_.conditionalNew(maximumColumnsExtra_ + 1);
691   lastColumn_.conditionalNew(maximumColumnsExtra_ + 1);
692   saveColumn_.conditionalNew(numberColumns_);
693 #ifdef ZEROFAULT
694   memset(startColumnU_.array(), 'a', (maximumColumnsExtra_ + 1) * sizeof(int));
695   memset(numberInColumn_.array(), 'b', (maximumColumnsExtra_ + 1) * sizeof(int));
696   memset(numberInColumnPlus_.array(), 'c', (maximumColumnsExtra_ + 1) * sizeof(int));
697   memset(pivotColumn_.array(), 'd', (maximumColumnsExtra_ + 1) * sizeof(int));
698   memset(nextColumn_.array(), 'e', (maximumColumnsExtra_ + 1) * sizeof(int));
699   memset(lastColumn_.array(), 'f', (maximumColumnsExtra_ + 1) * sizeof(int));
700 #endif
701   if (numberRows_ + numberColumns_) {
702     if (numberRows_ > numberColumns_) {
703       biggerDimension_ = numberRows_;
704     } else {
705       biggerDimension_ = numberColumns_;
706     }
707     firstCount_.conditionalNew(CoinMax(biggerDimension_ + 2, maximumRowsExtra_ + 1));
708     nextCount_.conditionalNew(numberRows_ + numberColumns_);
709     lastCount_.conditionalNew(numberRows_ + numberColumns_);
710 #ifdef ZEROFAULT
711     memset(firstCount_.array(), 'g', (biggerDimension_ + 2) * sizeof(int));
712     memset(nextCount_.array(), 'h', (numberRows_ + numberColumns_) * sizeof(int));
713     memset(lastCount_.array(), 'i', (numberRows_ + numberColumns_) * sizeof(int));
714 #endif
715   } else {
716     firstCount_.conditionalNew(2);
717     nextCount_.conditionalNew(0);
718     lastCount_.conditionalNew(0);
719 #ifdef ZEROFAULT
720     memset(firstCount_.array(), 'g', 2 * sizeof(int));
721 #endif
722     biggerDimension_ = 0;
723   }
724 }
725 
726 //  preProcess.  PreProcesses raw triplet data
727 //state is 0 - triplets, 1 - some counts etc , 2 - ..
preProcess(int state,int)728 void CoinFactorization::preProcess(int state,
729   int)
730 {
731   int *indexRow = indexRowU_.array();
732   int *indexColumn = indexColumnU_.array();
733   CoinFactorizationDouble *element = elementU_.array();
734   int numberElements = lengthU_;
735   int *numberInRow = numberInRow_.array();
736   int *numberInColumn = numberInColumn_.array();
737   int *numberInColumnPlus = numberInColumnPlus_.array();
738   int *startRow = startRowU_.array();
739   int *startColumn = startColumnU_.array();
740   int numberRows = numberRows_;
741   int numberColumns = numberColumns_;
742 
743   if (state < 4)
744     totalElements_ = numberElements;
745   //state falls through to next state
746   switch (state) {
747   case 0: //counts
748   {
749     CoinZeroN(numberInRow, numberRows + 1);
750     CoinZeroN(numberInColumn, maximumColumnsExtra_ + 1);
751     int i;
752     for (i = 0; i < numberElements; i++) {
753       int iRow = indexRow[i];
754       int iColumn = indexColumn[i];
755 
756       numberInRow[iRow]++;
757       numberInColumn[iColumn]++;
758     }
759   }
760   case -1: //sort
761   case 1: //sort
762   {
763     int i, k;
764 
765     i = 0;
766     int iColumn;
767     for (iColumn = 0; iColumn < numberColumns; iColumn++) {
768       //position after end of Column
769       i += numberInColumn[iColumn];
770       startColumn[iColumn] = i;
771     }
772     for (k = numberElements - 1; k >= 0; k--) {
773       int iColumn = indexColumn[k];
774 
775       if (iColumn >= 0) {
776         CoinFactorizationDouble value = element[k];
777         int iRow = indexRow[k];
778 
779         indexColumn[k] = -1;
780         while (true) {
781           int iLook = startColumn[iColumn] - 1;
782 
783           startColumn[iColumn] = iLook;
784           CoinFactorizationDouble valueSave = element[iLook];
785           int iColumnSave = indexColumn[iLook];
786           int iRowSave = indexRow[iLook];
787 
788           element[iLook] = value;
789           indexRow[iLook] = iRow;
790           indexColumn[iLook] = -1;
791           if (iColumnSave >= 0) {
792             iColumn = iColumnSave;
793             value = valueSave;
794             iRow = iRowSave;
795           } else {
796             break;
797           }
798         } /* endwhile */
799       }
800     }
801   }
802   case 2: //move largest in column to beginning
803     //and do row part
804     {
805       int i, k;
806 
807       i = 0;
808       int iRow;
809       for (iRow = 0; iRow < numberRows; iRow++) {
810         startRow[iRow] = i;
811         i += numberInRow[iRow];
812       }
813       CoinZeroN(numberInRow, numberRows);
814       int iColumn;
815       for (iColumn = 0; iColumn < numberColumns; iColumn++) {
816         int number = numberInColumn[iColumn];
817 
818         if (number) {
819           int first = startColumn[iColumn];
820           int largest = first;
821           int iRowSave = indexRow[first];
822           CoinFactorizationDouble valueSave = element[first];
823           double valueLargest = fabs(valueSave);
824           int iLook = numberInRow[iRowSave];
825 
826           numberInRow[iRowSave] = iLook + 1;
827           indexColumn[startRow[iRowSave] + iLook] = iColumn;
828           for (k = first + 1; k < first + number; k++) {
829             int iRow = indexRow[k];
830             int iLook = numberInRow[iRow];
831 
832             numberInRow[iRow] = iLook + 1;
833             indexColumn[startRow[iRow] + iLook] = iColumn;
834             CoinFactorizationDouble value = element[k];
835             double valueAbs = fabs(value);
836 
837             if (valueAbs > valueLargest) {
838               valueLargest = valueAbs;
839               largest = k;
840             }
841           }
842           indexRow[first] = indexRow[largest];
843           element[first] = element[largest];
844           indexRow[largest] = iRowSave;
845           element[largest] = valueSave;
846         }
847       }
848     }
849   case 3: //links and initialize pivots
850   {
851     int *lastRow = lastRow_.array();
852     int *nextRow = nextRow_.array();
853     int *lastColumn = lastColumn_.array();
854     int *nextColumn = nextColumn_.array();
855 
856     CoinFillN(firstCount_.array(), biggerDimension_ + 2, -1);
857     CoinFillN(pivotColumn_.array(), numberColumns_, -1);
858     CoinZeroN(numberInColumnPlus, maximumColumnsExtra_ + 1);
859     int iRow;
860     for (iRow = 0; iRow < numberRows; iRow++) {
861       lastRow[iRow] = iRow - 1;
862       nextRow[iRow] = iRow + 1;
863       int number = numberInRow[iRow];
864 
865       addLink(iRow, number);
866     }
867     lastRow[maximumRowsExtra_] = numberRows - 1;
868     nextRow[maximumRowsExtra_] = 0;
869     lastRow[0] = maximumRowsExtra_;
870     nextRow[numberRows - 1] = maximumRowsExtra_;
871     startRow[maximumRowsExtra_] = numberElements;
872     int iColumn;
873     for (iColumn = 0; iColumn < numberColumns; iColumn++) {
874       lastColumn[iColumn] = iColumn - 1;
875       nextColumn[iColumn] = iColumn + 1;
876       int number = numberInColumn[iColumn];
877 
878       addLink(iColumn + numberRows, number);
879     }
880     lastColumn[maximumColumnsExtra_] = numberColumns - 1;
881     nextColumn[maximumColumnsExtra_] = 0;
882     lastColumn[0] = maximumColumnsExtra_;
883     if (numberColumns)
884       nextColumn[numberColumns - 1] = maximumColumnsExtra_;
885     startColumn[maximumColumnsExtra_] = numberElements;
886   } break;
887   case 4: //move largest in column to beginning
888   {
889     int i, k;
890     CoinFactorizationDouble *pivotRegion = pivotRegion_.array();
891     int iColumn;
892     int iRow;
893     for (iRow = 0; iRow < numberRows; iRow++) {
894       if (numberInRow[iRow] >= 0) {
895         // zero count
896         numberInRow[iRow] = 0;
897       } else {
898         // empty
899         //numberInRow[iRow]=-1; already that
900       }
901     }
902     //CoinZeroN ( numberInColumnPlus, maximumColumnsExtra_ + 1 );
903     for (iColumn = 0; iColumn < numberColumns; iColumn++) {
904       int number = numberInColumn[iColumn];
905 
906       if (number) {
907         // use pivotRegion and startRow for remaining elements
908         int first = startColumn[iColumn];
909         int largest = -1;
910 
911         double valueLargest = -1.0;
912         int nOther = 0;
913         k = first;
914         int end = first + number;
915         for (; k < end; k++) {
916           int iRow = indexRow[k];
917           assert(iRow < numberRows_);
918           CoinFactorizationDouble value = element[k];
919           if (numberInRow[iRow] >= 0) {
920             numberInRow[iRow]++;
921             double valueAbs = fabs(value);
922             if (valueAbs > valueLargest) {
923               valueLargest = valueAbs;
924               largest = nOther;
925             }
926             startRow[nOther] = iRow;
927             pivotRegion[nOther++] = value;
928           } else {
929             indexRow[first] = iRow;
930             element[first++] = value;
931           }
932         }
933         numberInColumnPlus[iColumn] = first - startColumn[iColumn];
934         startColumn[iColumn] = first;
935         //largest
936         if (largest >= 0) {
937           indexRow[first] = startRow[largest];
938           element[first++] = pivotRegion[largest];
939         }
940         for (k = 0; k < nOther; k++) {
941           if (k != largest) {
942             indexRow[first] = startRow[k];
943             element[first++] = pivotRegion[k];
944           }
945         }
946         numberInColumn[iColumn] = first - startColumn[iColumn];
947       }
948     }
949     //and do row part
950     i = 0;
951     for (iRow = 0; iRow < numberRows; iRow++) {
952       startRow[iRow] = i;
953       int n = numberInRow[iRow];
954       if (n > 0) {
955         numberInRow[iRow] = 0;
956         i += n;
957       }
958     }
959     for (iColumn = 0; iColumn < numberColumns; iColumn++) {
960       int number = numberInColumn[iColumn];
961 
962       if (number) {
963         int first = startColumn[iColumn];
964         for (k = first; k < first + number; k++) {
965           int iRow = indexRow[k];
966           int iLook = numberInRow[iRow];
967 
968           numberInRow[iRow] = iLook + 1;
969           indexColumn[startRow[iRow] + iLook] = iColumn;
970         }
971       }
972     }
973   }
974     // modified 3
975     {
976       //set markRow so no rows updated
977       //CoinFillN ( markRow_.array(), numberRows_, -1 );
978       int *lastColumn = lastColumn_.array();
979       int *nextColumn = nextColumn_.array();
980       CoinFactorizationDouble *pivotRegion = pivotRegion_.array();
981 
982       int iRow;
983       int numberGood = 0;
984       startColumnL_.array()[0] = 0; //for luck
985       for (iRow = 0; iRow < numberRows; iRow++) {
986         int number = numberInRow[iRow];
987         if (number < 0) {
988           numberInRow[iRow] = 0;
989           pivotRegion[numberGood++] = slackValue_;
990         }
991       }
992       int iColumn;
993       for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
994         lastColumn[iColumn] = iColumn - 1;
995         nextColumn[iColumn] = iColumn + 1;
996         int number = numberInColumn[iColumn];
997         deleteLink(iColumn + numberRows);
998         addLink(iColumn + numberRows, number);
999       }
1000       lastColumn[maximumColumnsExtra_] = numberColumns - 1;
1001       nextColumn[maximumColumnsExtra_] = 0;
1002       lastColumn[0] = maximumColumnsExtra_;
1003       if (numberColumns)
1004         nextColumn[numberColumns - 1] = maximumColumnsExtra_;
1005       startColumn[maximumColumnsExtra_] = numberElements;
1006     }
1007   } /* endswitch */
1008 }
1009 #ifdef CLP_FACTORIZATION_INSTRUMENT
1010 double externalTimeStart = 0.0;
1011 double timeInFactorize = 0.0;
1012 double timeInUpdate = 0.0;
1013 double timeInFactorizeFake = 0.0;
1014 double timeInUpdateFake1 = 0.0;
1015 double timeInUpdateFake2 = 0.0;
1016 double timeInUpdateTranspose = 0.0;
1017 double timeInUpdateFT = 0.0;
1018 double timeInUpdateTwoFT = 0.0;
1019 double timeInReplace = 0.0;
1020 double averageLengthR = 0.0;
1021 double averageLengthL = 0.0;
1022 double averageLengthU = 0.0;
1023 double scaledLengthDense = 0.0;
1024 double scaledLengthDenseSquared = 0.0;
1025 double scaledLengthL = 0.0;
1026 double scaledLengthR = 0.0;
1027 double scaledLengthU = 0.0;
1028 int numberUpdate = 1;
1029 int numberUpdateTranspose = 0;
1030 int numberUpdateFT = 0;
1031 int numberUpdateTwoFT = 0;
1032 int numberReplace = 0;
1033 int numberAdded = 0;
1034 int currentLengthR = 0;
1035 int currentLengthU = 0;
1036 int currentTakeoutU = 0;
1037 int startLengthU = 0;
1038 int endLengthU = 0;
1039 int endLengthU2 = 0;
1040 #endif
1041 
1042 //Does most of factorization
factor()1043 int CoinFactorization::factor()
1044 {
1045 #ifdef CLP_FACTORIZATION_INSTRUMENT
1046   int nUse = numberUpdate + numberUpdateTranspose + numberUpdateFT + 2 * numberUpdateTwoFT + numberReplace;
1047   double dUse = timeInUpdate + timeInUpdateTranspose + timeInUpdateFT + timeInUpdateTwoFT + timeInReplace;
1048   printf("%.18g time in factorization, using %.18g (%d) -average %.18g\n",
1049     timeInFactorize, dUse, nUse, dUse / static_cast< double >(nUse));
1050   //collectStatistics_=true;
1051   int *startColumnU = startColumnU_.array();
1052   int numberSlacksX = 0;
1053   for (int i = 0; i < numberRows_; i++) {
1054     if (startColumnU[i + 1] != startColumnU[i] + 1)
1055       break;
1056     numberSlacksX++;
1057   }
1058   int numberInUX = startColumnU[numberRows_];
1059   printf("numberCompressions %d ftranInput %g ftranAfterL %g \
1060     ftranAfterR %g ftranAfterU %g btranInput %g \
1061     btranAfterU %g btranAfterR %g btranAfterL %g \
1062     numberFtrans %d numberBtrans %d ftranAvAfterL %g \
1063     ftranAvAfterR %g ftranAvAfterU %g btranAvAfterU %g \
1064     btranAvAfterR %g btranAvAfterL %g\n",
1065     numberCompressions_, ftranCountInput_, ftranCountAfterL_,
1066     ftranCountAfterR_, ftranCountAfterU_, btranCountInput_,
1067     btranCountAfterU_, btranCountAfterR_, btranCountAfterL_,
1068     numberFtranCounts_, numberBtranCounts_, ftranAverageAfterL_,
1069     ftranAverageAfterR_, ftranAverageAfterU_, btranAverageAfterU_,
1070     btranAverageAfterR_, btranAverageAfterL_);
1071   printf("lengthRend %d lengthUend %d takeoutU %d\n",
1072     currentLengthR, currentLengthU, currentTakeoutU);
1073   double timeStart = externalTimeStart;
1074   timeInFactorize = 0.0;
1075   timeInUpdate = 0.0;
1076   timeInUpdateTranspose = 0.0;
1077   timeInUpdateFT = 0.0;
1078   timeInUpdateTwoFT = 0.0;
1079   timeInReplace = 0.0;
1080   numberUpdate = 1;
1081   numberUpdateTranspose = 0;
1082   numberUpdateFT = 0;
1083   numberUpdateTwoFT = 0;
1084   numberReplace = 0;
1085   numberAdded = 0;
1086   currentLengthR = 0;
1087   currentLengthU = 0;
1088   currentTakeoutU = 0;
1089 #endif
1090   int *lastColumn = lastColumn_.array();
1091   int *lastRow = lastRow_.array();
1092   //sparse
1093   status_ = factorSparse();
1094   switch (status_) {
1095   case 0: //finished
1096     totalElements_ = 0;
1097     {
1098       int *pivotColumn = pivotColumn_.array();
1099       if (numberGoodU_ < numberRows_) {
1100         int i, k;
1101         // Clean out unset nextRow
1102         int *nextRow = nextRow_.array();
1103         //int nSing =0;
1104         k = nextRow[maximumRowsExtra_];
1105         while (k != maximumRowsExtra_ && k >= 0) {
1106           int iRow = k;
1107           k = nextRow[k];
1108           //nSing++;
1109           nextRow[iRow] = -1;
1110         }
1111         //assert (nSing);
1112         //printf("%d singularities - good %d rows %d\n",nSing,
1113         //     numberGoodU_,numberRows_);
1114         // Now nextRow has -1 or sequence into numberGoodU_;
1115         int *permuteA = permute_.array();
1116         for (i = 0; i < numberRows_; i++) {
1117           int iGood = nextRow[i];
1118           if (iGood >= 0)
1119             permuteA[iGood] = i;
1120         }
1121 
1122         // swap arrays
1123         permute_.swap(nextRow_);
1124         int *permute = permute_.array();
1125         for (i = 0; i < numberRows_; i++) {
1126           lastRow[i] = -1;
1127         }
1128         for (i = 0; i < numberColumns_; i++) {
1129           lastColumn[i] = -1;
1130         }
1131         for (i = 0; i < numberGoodU_; i++) {
1132           int goodRow = permuteA[i]; //valid pivot row
1133           int goodColumn = pivotColumn[i];
1134 
1135           lastRow[goodRow] = goodColumn; //will now have -1 or column sequence
1136           lastColumn[goodColumn] = goodRow; //will now have -1 or row sequence
1137         }
1138         nextRow_.conditionalDelete();
1139         k = 0;
1140         //copy back and count
1141         for (i = 0; i < numberRows_; i++) {
1142           permute[i] = lastRow[i];
1143           if (permute[i] < 0) {
1144             //std::cout << i << " " <<permute[i] << std::endl;
1145           } else {
1146             k++;
1147           }
1148         }
1149         for (i = 0; i < numberColumns_; i++) {
1150           pivotColumn[i] = lastColumn[i];
1151         }
1152         if ((messageLevel_ & 4) != 0)
1153           std::cout << "Factorization has " << numberRows_ - k
1154                     << " singularities" << std::endl;
1155         status_ = -1;
1156       }
1157     }
1158     break;
1159     // dense
1160   case 2:
1161     status_ = factorDense();
1162     if (!status_)
1163       break;
1164   default:
1165     //singular ? or some error
1166     if ((messageLevel_ & 4) != 0)
1167       std::cout << "Error " << status_ << std::endl;
1168     break;
1169   } /* endswitch */
1170   //clean up
1171   if (!status_) {
1172     if ((messageLevel_ & 16) && numberCompressions_)
1173       std::cout << "        Factorization did " << numberCompressions_
1174                 << " compressions" << std::endl;
1175     if (numberCompressions_ > 10) {
1176       areaFactor_ *= 1.1;
1177     }
1178     numberCompressions_ = 0;
1179     cleanup();
1180   }
1181 #ifdef CLP_FACTORIZATION_INSTRUMENT
1182   timeInFactorize = CoinCpuTime() - timeStart;
1183   printf("%d slacks, startU %d, endL %d, endU %d + %d dense (squared)\n",
1184     numberSlacksX, numberInUX, lengthL_, lengthU_,
1185     numberDense_ * numberDense_);
1186   currentLengthR = 0;
1187   // remember pivots not included in counts
1188   endLengthU = totalElements_ - numberDense_ * numberDense_ - lengthL_;
1189   endLengthU2 = lengthU_;
1190   currentLengthU = lengthU_;
1191   currentTakeoutU = 0;
1192 #endif
1193   return status_;
1194 }
1195 
1196 //  pivotRowSingleton.  Does one pivot on Row Singleton in factorization
pivotRowSingleton(int pivotRow,int pivotColumn)1197 bool CoinFactorization::pivotRowSingleton(int pivotRow,
1198   int pivotColumn)
1199 {
1200   //store pivot columns (so can easily compress)
1201   int *startColumnU = startColumnU_.array();
1202   int startColumn = startColumnU[pivotColumn];
1203   int *numberInRow = numberInRow_.array();
1204   int *numberInColumn = numberInColumn_.array();
1205   int numberDoColumn = numberInColumn[pivotColumn] - 1;
1206   int endColumn = startColumn + numberDoColumn + 1;
1207   int pivotRowPosition = startColumn;
1208   int *indexRowU = indexRowU_.array();
1209   int iRow = indexRowU[pivotRowPosition];
1210   int *startRowU = startRowU_.array();
1211   int *nextRow = nextRow_.array();
1212   int *lastRow = lastRow_.array();
1213 
1214   while (iRow != pivotRow) {
1215     pivotRowPosition++;
1216     iRow = indexRowU[pivotRowPosition];
1217   } /* endwhile */
1218   assert(pivotRowPosition < endColumn);
1219   //store column in L, compress in U and take column out
1220   int l = lengthL_;
1221 
1222   if (l + numberDoColumn > lengthAreaL_) {
1223     //need more memory
1224     if ((messageLevel_ & 4) != 0)
1225       std::cout << "more memory needed in middle of invert" << std::endl;
1226     return false;
1227   }
1228   int *startColumnL = startColumnL_.array();
1229   CoinFactorizationDouble *elementL = elementL_.array();
1230   int *indexRowL = indexRowL_.array();
1231   startColumnL[numberGoodL_] = l; //for luck and first time
1232   numberGoodL_++;
1233   startColumnL[numberGoodL_] = l + numberDoColumn;
1234   lengthL_ += numberDoColumn;
1235   CoinFactorizationDouble *elementU = elementU_.array();
1236   CoinFactorizationDouble pivotElement = elementU[pivotRowPosition];
1237   CoinFactorizationDouble pivotMultiplier = 1.0 / pivotElement;
1238 
1239   pivotRegion_.array()[numberGoodU_] = pivotMultiplier;
1240   int i;
1241 
1242   int *indexColumnU = indexColumnU_.array();
1243   for (i = startColumn; i < pivotRowPosition; i++) {
1244     int iRow = indexRowU[i];
1245 
1246     indexRowL[l] = iRow;
1247     elementL[l] = elementU[i] * pivotMultiplier;
1248     l++;
1249     //take out of row list
1250     int start = startRowU[iRow];
1251     int iNumberInRow = numberInRow[iRow];
1252     int end = start + iNumberInRow;
1253     int where = start;
1254 
1255     while (indexColumnU[where] != pivotColumn) {
1256       where++;
1257     } /* endwhile */
1258     assert(where < end);
1259     indexColumnU[where] = indexColumnU[end - 1];
1260     iNumberInRow--;
1261     numberInRow[iRow] = iNumberInRow;
1262     deleteLink(iRow);
1263     addLink(iRow, iNumberInRow);
1264   }
1265   for (i = pivotRowPosition + 1; i < endColumn; i++) {
1266     int iRow = indexRowU[i];
1267 
1268     indexRowL[l] = iRow;
1269     elementL[l] = elementU[i] * pivotMultiplier;
1270     l++;
1271     //take out of row list
1272     int start = startRowU[iRow];
1273     int iNumberInRow = numberInRow[iRow];
1274     int end = start + iNumberInRow;
1275     int where = start;
1276 
1277     while (indexColumnU[where] != pivotColumn) {
1278       where++;
1279     } /* endwhile */
1280     assert(where < end);
1281     indexColumnU[where] = indexColumnU[end - 1];
1282     iNumberInRow--;
1283     numberInRow[iRow] = iNumberInRow;
1284     deleteLink(iRow);
1285     addLink(iRow, iNumberInRow);
1286   }
1287   numberInColumn[pivotColumn] = 0;
1288   //modify linked list for pivots
1289   numberInRow[pivotRow] = 0;
1290   deleteLink(pivotRow);
1291   deleteLink(pivotColumn + numberRows_);
1292   //take out this bit of indexColumnU
1293   int next = nextRow[pivotRow];
1294   int last = lastRow[pivotRow];
1295 
1296   nextRow[last] = next;
1297   lastRow[next] = last;
1298   lastRow[pivotRow] = -2;
1299   nextRow[pivotRow] = numberGoodU_; //use for permute
1300   return true;
1301 }
1302 
1303 //  pivotColumnSingleton.  Does one pivot on Column Singleton in factorization
pivotColumnSingleton(int pivotRow,int pivotColumn)1304 bool CoinFactorization::pivotColumnSingleton(int pivotRow,
1305   int pivotColumn)
1306 {
1307   int *numberInRow = numberInRow_.array();
1308   int *numberInColumn = numberInColumn_.array();
1309   int *numberInColumnPlus = numberInColumnPlus_.array();
1310   //store pivot columns (so can easily compress)
1311   int numberDoRow = numberInRow[pivotRow] - 1;
1312   int *startColumnU = startColumnU_.array();
1313   int startColumn = startColumnU[pivotColumn];
1314   int put = 0;
1315   int *startRowU = startRowU_.array();
1316   int startRow = startRowU[pivotRow];
1317   int endRow = startRow + numberDoRow + 1;
1318   int *indexColumnU = indexColumnU_.array();
1319   int *indexRowU = indexRowU_.array();
1320   int *saveColumn = saveColumn_.array();
1321   int i;
1322 
1323   for (i = startRow; i < endRow; i++) {
1324     int iColumn = indexColumnU[i];
1325 
1326     if (iColumn != pivotColumn) {
1327       saveColumn[put++] = iColumn;
1328     }
1329   }
1330   int *nextRow = nextRow_.array();
1331   int *lastRow = lastRow_.array();
1332   //take out this bit of indexColumnU
1333   int next = nextRow[pivotRow];
1334   int last = lastRow[pivotRow];
1335 
1336   nextRow[last] = next;
1337   lastRow[next] = last;
1338   nextRow[pivotRow] = numberGoodU_; //use for permute
1339   lastRow[pivotRow] = -2; //mark
1340   //clean up counts
1341   CoinFactorizationDouble *elementU = elementU_.array();
1342   CoinFactorizationDouble pivotElement = elementU[startColumn];
1343 
1344   pivotRegion_.array()[numberGoodU_] = 1.0 / pivotElement;
1345   numberInColumn[pivotColumn] = 0;
1346   //totalElements_ --;
1347   //numberInColumnPlus[pivotColumn]++;
1348   //move pivot row in other columns to safe zone
1349   for (i = 0; i < numberDoRow; i++) {
1350     int iColumn = saveColumn[i];
1351 
1352     if (numberInColumn[iColumn]) {
1353       int number = numberInColumn[iColumn] - 1;
1354 
1355       //modify linked list
1356       deleteLink(iColumn + numberRows_);
1357       addLink(iColumn + numberRows_, number);
1358       //move pivot row element
1359       if (number) {
1360         int start = startColumnU[iColumn];
1361         int pivot = start;
1362         int iRow = indexRowU[pivot];
1363         while (iRow != pivotRow) {
1364           pivot++;
1365           iRow = indexRowU[pivot];
1366         }
1367         assert(pivot < startColumnU[iColumn] + numberInColumn[iColumn]);
1368         if (pivot != start) {
1369           //move largest one up
1370           CoinFactorizationDouble value = elementU[start];
1371 
1372           iRow = indexRowU[start];
1373           elementU[start] = elementU[pivot];
1374           indexRowU[start] = indexRowU[pivot];
1375           elementU[pivot] = elementU[start + 1];
1376           indexRowU[pivot] = indexRowU[start + 1];
1377           elementU[start + 1] = value;
1378           indexRowU[start + 1] = iRow;
1379         } else {
1380           //find new largest element
1381           int iRowSave = indexRowU[start + 1];
1382           CoinFactorizationDouble valueSave = elementU[start + 1];
1383           double valueLargest = fabs(valueSave);
1384           int end = start + numberInColumn[iColumn];
1385           int largest = start + 1;
1386 
1387           int k;
1388           for (k = start + 2; k < end; k++) {
1389             CoinFactorizationDouble value = elementU[k];
1390             double valueAbs = fabs(value);
1391 
1392             if (valueAbs > valueLargest) {
1393               valueLargest = valueAbs;
1394               largest = k;
1395             }
1396           }
1397           indexRowU[start + 1] = indexRowU[largest];
1398           elementU[start + 1] = elementU[largest];
1399           indexRowU[largest] = iRowSave;
1400           elementU[largest] = valueSave;
1401         }
1402       }
1403       //clean up counts
1404       numberInColumn[iColumn]--;
1405       numberInColumnPlus[iColumn]++;
1406       startColumnU[iColumn]++;
1407       //totalElements_--;
1408     }
1409   }
1410   //modify linked list for pivots
1411   deleteLink(pivotRow);
1412   deleteLink(pivotColumn + numberRows_);
1413   numberInRow[pivotRow] = 0;
1414   //put in dummy pivot in L
1415   int l = lengthL_;
1416 
1417   int *startColumnL = startColumnL_.array();
1418   startColumnL[numberGoodL_] = l; //for luck and first time
1419   numberGoodL_++;
1420   startColumnL[numberGoodL_] = l;
1421   return true;
1422 }
1423 
1424 //  getColumnSpace.  Gets space for one Column with given length
1425 //may have to do compression  (returns true)
1426 //also moves existing vector
getColumnSpace(int iColumn,int extraNeeded)1427 bool CoinFactorization::getColumnSpace(int iColumn,
1428   int extraNeeded)
1429 {
1430   int *numberInColumn = numberInColumn_.array();
1431   int *numberInColumnPlus = numberInColumnPlus_.array();
1432   int *nextColumn = nextColumn_.array();
1433   int *lastColumn = lastColumn_.array();
1434   int number = numberInColumnPlus[iColumn] + numberInColumn[iColumn];
1435   int *startColumnU = startColumnU_.array();
1436   int space = lengthAreaU_ - startColumnU[maximumColumnsExtra_];
1437   CoinFactorizationDouble *elementU = elementU_.array();
1438   int *indexRowU = indexRowU_.array();
1439 
1440   if (space < extraNeeded + number + 4) {
1441     //compression
1442     int iColumn = nextColumn[maximumColumnsExtra_];
1443     int put = 0;
1444 
1445     while (iColumn != maximumColumnsExtra_) {
1446       //move
1447       int get;
1448       int getEnd;
1449 
1450       if (startColumnU[iColumn] >= 0) {
1451         get = startColumnU[iColumn]
1452           - numberInColumnPlus[iColumn];
1453         getEnd = startColumnU[iColumn] + numberInColumn[iColumn];
1454         startColumnU[iColumn] = put + numberInColumnPlus[iColumn];
1455       } else {
1456         get = -startColumnU[iColumn];
1457         getEnd = get + numberInColumn[iColumn];
1458         startColumnU[iColumn] = -put;
1459       }
1460       int i;
1461       for (i = get; i < getEnd; i++) {
1462         indexRowU[put] = indexRowU[i];
1463         elementU[put] = elementU[i];
1464         put++;
1465       }
1466       iColumn = nextColumn[iColumn];
1467     } /* endwhile */
1468     numberCompressions_++;
1469     startColumnU[maximumColumnsExtra_] = put;
1470     space = lengthAreaU_ - put;
1471     if (extraNeeded == COIN_INT_MAX >> 1) {
1472       return true;
1473     }
1474     if (space < extraNeeded + number + 2) {
1475       //need more space
1476       //if we can allocate bigger then do so and copy
1477       //if not then return so code can start again
1478       status_ = -99;
1479       return false;
1480     }
1481   }
1482   int put = startColumnU[maximumColumnsExtra_];
1483   int next = nextColumn[iColumn];
1484   int last = lastColumn[iColumn];
1485 
1486   if (extraNeeded || next != maximumColumnsExtra_) {
1487     //out
1488     nextColumn[last] = next;
1489     lastColumn[next] = last;
1490     //in at end
1491     last = lastColumn[maximumColumnsExtra_];
1492     nextColumn[last] = iColumn;
1493     lastColumn[maximumColumnsExtra_] = iColumn;
1494     lastColumn[iColumn] = last;
1495     nextColumn[iColumn] = maximumColumnsExtra_;
1496     //move
1497     int get = startColumnU[iColumn]
1498       - numberInColumnPlus[iColumn];
1499 
1500     startColumnU[iColumn] = put + numberInColumnPlus[iColumn];
1501     if (number < 50) {
1502       int *indexRow = indexRowU;
1503       CoinFactorizationDouble *element = elementU;
1504       int i = 0;
1505 
1506       if ((number & 1) != 0) {
1507         element[put] = element[get];
1508         indexRow[put] = indexRow[get];
1509         i = 1;
1510       }
1511       for (; i < number; i += 2) {
1512         CoinFactorizationDouble value0 = element[get + i];
1513         CoinFactorizationDouble value1 = element[get + i + 1];
1514         int index0 = indexRow[get + i];
1515         int index1 = indexRow[get + i + 1];
1516 
1517         element[put + i] = value0;
1518         element[put + i + 1] = value1;
1519         indexRow[put + i] = index0;
1520         indexRow[put + i + 1] = index1;
1521       }
1522     } else {
1523       CoinMemcpyN(&indexRowU[get], number, &indexRowU[put]);
1524       CoinMemcpyN(&elementU[get], number, &elementU[put]);
1525     }
1526     put += number;
1527     get += number;
1528     //add 2 for luck
1529     startColumnU[maximumColumnsExtra_] = put + extraNeeded + 2;
1530     if (startColumnU[maximumColumnsExtra_] > lengthAreaU_) {
1531       // get more memory
1532 #ifdef CLP_DEVELOP
1533       printf("put %d, needed %d, start %d, length %d\n",
1534         put, extraNeeded, startColumnU[maximumColumnsExtra_],
1535         lengthAreaU_);
1536 #endif
1537       return false;
1538     }
1539   } else {
1540     //take off space
1541     startColumnU[maximumColumnsExtra_] = startColumnU[last] + numberInColumn[last];
1542   }
1543   return true;
1544 }
1545 
1546 //  getRowSpace.  Gets space for one Row with given length
1547 //may have to do compression  (returns true)
1548 //also moves existing vector
getRowSpace(int iRow,int extraNeeded)1549 bool CoinFactorization::getRowSpace(int iRow,
1550   int extraNeeded)
1551 {
1552   int *numberInRow = numberInRow_.array();
1553   int number = numberInRow[iRow];
1554   int *startRowU = startRowU_.array();
1555   int space = lengthAreaU_ - startRowU[maximumRowsExtra_];
1556   int *nextRow = nextRow_.array();
1557   int *lastRow = lastRow_.array();
1558   int *indexColumnU = indexColumnU_.array();
1559 
1560   if (space < extraNeeded + number + 2) {
1561     //compression
1562     int iRow = nextRow[maximumRowsExtra_];
1563     int put = 0;
1564 
1565     while (iRow != maximumRowsExtra_) {
1566       //move
1567       int get = startRowU[iRow];
1568       int getEnd = startRowU[iRow] + numberInRow[iRow];
1569 
1570       startRowU[iRow] = put;
1571       int i;
1572       for (i = get; i < getEnd; i++) {
1573         indexColumnU[put] = indexColumnU[i];
1574         put++;
1575       }
1576       iRow = nextRow[iRow];
1577     } /* endwhile */
1578     numberCompressions_++;
1579     startRowU[maximumRowsExtra_] = put;
1580     space = lengthAreaU_ - put;
1581     if (space < extraNeeded + number + 2) {
1582       //need more space
1583       //if we can allocate bigger then do so and copy
1584       //if not then return so code can start again
1585       status_ = -99;
1586       return false;
1587       ;
1588     }
1589   }
1590   int put = startRowU[maximumRowsExtra_];
1591   int next = nextRow[iRow];
1592   int last = lastRow[iRow];
1593 
1594   //out
1595   nextRow[last] = next;
1596   lastRow[next] = last;
1597   //in at end
1598   last = lastRow[maximumRowsExtra_];
1599   nextRow[last] = iRow;
1600   lastRow[maximumRowsExtra_] = iRow;
1601   lastRow[iRow] = last;
1602   nextRow[iRow] = maximumRowsExtra_;
1603   //move
1604   int get = startRowU[iRow];
1605 
1606   startRowU[iRow] = put;
1607   while (number) {
1608     number--;
1609     indexColumnU[put] = indexColumnU[get];
1610     put++;
1611     get++;
1612   } /* endwhile */
1613   //add 4 for luck
1614   startRowU[maximumRowsExtra_] = put + extraNeeded + 4;
1615   return true;
1616 }
1617 
1618 #if COIN_ONE_ETA_COPY
1619 /* Reorders U so contiguous and in order (if there is space)
1620    Returns true if it could */
reorderU()1621 bool CoinFactorization::reorderU()
1622 {
1623 #if 1
1624   return false;
1625 #else
1626   if (numberRows_ != numberColumns_)
1627     return false;
1628   int *startColumnU = startColumnU_.array();
1629   int *numberInColumn = numberInColumn_.array();
1630   int *numberInColumnPlus = numberInColumnPlus_.array();
1631   int iColumn;
1632   int put = 0;
1633   for (iColumn = 0; iColumn < numberRows_; iColumn++)
1634     put += numberInColumnPlus[iColumn];
1635   int space = lengthAreaU_ - startColumnU[maximumColumnsExtra_];
1636   if (space < put) {
1637     //printf("Space %d out of %d - needed %d\n",
1638     //   space,lengthAreaU_,put);
1639     return false;
1640   }
1641   int *indexRowU = indexRowU_.array();
1642   CoinFactorizationDouble *elementU = elementU_.array();
1643   int *pivotColumn = pivotColumn_.array();
1644   put = startColumnU[maximumColumnsExtra_];
1645   for (int jColumn = 0; jColumn < numberRows_; jColumn++) {
1646     iColumn = pivotColumn[jColumn];
1647     int n = numberInColumnPlus[iColumn];
1648     int getEnd = startColumnU[iColumn];
1649     int get = getEnd - n;
1650     startColumnU[iColumn] = put;
1651     numberInColumn[jColumn] = n;
1652     int i;
1653     for (i = get; i < getEnd; i++) {
1654       indexRowU[put] = indexRowU[i];
1655       elementU[put] = elementU[i];
1656       put++;
1657     }
1658   }
1659   // and pack down
1660   put = 0;
1661   for (int jColumn = 0; jColumn < numberRows_; jColumn++) {
1662     iColumn = pivotColumn[jColumn];
1663     int n = numberInColumn[jColumn];
1664     int get = startColumnU[iColumn];
1665     int getEnd = get + n;
1666     int i;
1667     for (i = get; i < getEnd; i++) {
1668       indexRowU[put] = indexRowU[i];
1669       elementU[put] = elementU[i];
1670       put++;
1671     }
1672   }
1673   put = 0;
1674   for (iColumn = 0; iColumn < numberRows_; iColumn++) {
1675     int n = numberInColumn[iColumn];
1676     startColumnU[iColumn] = put;
1677     put += n;
1678     //numberInColumnPlus[iColumn]=n;
1679     //numberInColumn[iColumn]=0; // necessary?
1680     //pivotColumn[iColumn]=iColumn;
1681   }
1682 #if 0
1683   // reset nextColumn - probably not necessary
1684   int * nextColumn = nextColumn_.array();
1685   nextColumn[maximumColumnsExtra_]=0;
1686   nextColumn[numberRows_-1] = maximumColumnsExtra_;
1687   for (iColumn=0;iColumn<numberRows_-1;iColumn++)
1688     nextColumn[iColumn]=iColumn+1;
1689   // swap arrays
1690   numberInColumn_.swap(numberInColumnPlus_);
1691 #endif
1692   //return false;
1693   return true;
1694 #endif
1695 }
1696 #endif
1697 //  cleanup.  End of factorization
cleanup()1698 void CoinFactorization::cleanup()
1699 {
1700 #if COIN_ONE_ETA_COPY
1701   bool compressDone = reorderU();
1702   if (!compressDone) {
1703     getColumnSpace(0, COIN_INT_MAX >> 1); //compress
1704     // swap arrays
1705     numberInColumn_.swap(numberInColumnPlus_);
1706   }
1707 #else
1708   getColumnSpace(0, COIN_INT_MAX >> 1); //compress
1709   // swap arrays
1710   numberInColumn_.swap(numberInColumnPlus_);
1711 #endif
1712   int *startColumnU = startColumnU_.array();
1713   int lastU = startColumnU[maximumColumnsExtra_];
1714 
1715   //free some memory here
1716   saveColumn_.conditionalDelete();
1717   markRow_.conditionalDelete();
1718   //firstCount_.conditionalDelete() ;
1719   nextCount_.conditionalDelete();
1720   lastCount_.conditionalDelete();
1721   int *numberInRow = numberInRow_.array();
1722   int *numberInColumn = numberInColumn_.array();
1723   int *numberInColumnPlus = numberInColumnPlus_.array();
1724   //make column starts OK
1725   //for best cache behavior get in order (last pivot at bottom of space)
1726   //that will need thinking about
1727   //use nextRow for permutation  (as that is what it is)
1728   int i;
1729 
1730 #ifndef NDEBUG
1731   {
1732     if (numberGoodU_ < numberRows_)
1733       abort();
1734     char *mark = new char[numberRows_];
1735     memset(mark, 0, numberRows_);
1736     int *array;
1737     array = nextRow_.array();
1738     for (i = 0; i < numberRows_; i++) {
1739       int k = array[i];
1740       if (k < 0 || k >= numberRows_)
1741         printf("Bad a %d %d\n", i, k);
1742       assert(k >= 0 && k < numberRows_);
1743       if (mark[k] == 1)
1744         printf("Bad a %d %d\n", i, k);
1745       mark[k] = 1;
1746     }
1747     for (i = 0; i < numberRows_; i++) {
1748       assert(mark[i] == 1);
1749       if (mark[i] != 1)
1750         printf("Bad b %d\n", i);
1751     }
1752     delete[] mark;
1753   }
1754 #endif
1755   // swap arrays
1756   permute_.swap(nextRow_);
1757   //safety feature
1758   int *permute = permute_.array();
1759   permute[numberRows_] = 0;
1760   permuteBack_.conditionalNew(maximumRowsExtra_ + 1);
1761   int *permuteBack = permuteBack_.array();
1762 #ifdef ZEROFAULT
1763   memset(permuteBack_.array(), 'w', (maximumRowsExtra_ + 1) * sizeof(int));
1764 #endif
1765   for (i = 0; i < numberRows_; i++) {
1766     int iRow = permute[i];
1767 
1768     permuteBack[iRow] = i;
1769   }
1770   //redo nextRow_
1771 
1772 #ifndef NDEBUG
1773   for (i = 0; i < numberRows_; i++) {
1774     assert(permute[i] >= 0 && permute[i] < numberRows_);
1775     assert(permuteBack[i] >= 0 && permuteBack[i] < numberRows_);
1776   }
1777 #endif
1778 #if COIN_ONE_ETA_COPY
1779   if (!compressDone) {
1780 #endif
1781     // Redo total elements
1782     totalElements_ = 0;
1783     for (i = 0; i < numberColumns_; i++) {
1784       int number = numberInColumn[i];
1785       totalElements_ += number;
1786       startColumnU[i] -= number;
1787     }
1788 #if COIN_ONE_ETA_COPY
1789   }
1790 #endif
1791   int numberU = 0;
1792 
1793   pivotColumnBack_.conditionalNew(maximumRowsExtra_ + 1);
1794 #ifdef ZEROFAULT
1795   memset(pivotColumnBack(), 'q', (maximumRowsExtra_ + 1) * sizeof(int));
1796 #endif
1797   const int *pivotColumn = pivotColumn_.array();
1798   int *pivotColumnB = pivotColumnBack();
1799   int *indexColumnU = indexColumnU_.array();
1800   int *startColumn = startColumnU;
1801   int *indexRowU = indexRowU_.array();
1802   CoinFactorizationDouble *elementU = elementU_.array();
1803 #if COIN_ONE_ETA_COPY
1804   if (!compressDone) {
1805 #endif
1806     for (i = 0; i < numberColumns_; i++) {
1807       int iColumn = pivotColumn[i];
1808 
1809       pivotColumnB[iColumn] = i;
1810       if (iColumn >= 0) {
1811         //wanted
1812         if (numberU != iColumn) {
1813           numberInColumnPlus[iColumn] = numberU;
1814         } else {
1815           numberInColumnPlus[iColumn] = -1; //already in correct place
1816         }
1817         numberU++;
1818       }
1819     }
1820     for (i = 0; i < numberColumns_; i++) {
1821       int number = numberInColumn[i]; //always 0?
1822       int where = numberInColumnPlus[i];
1823 
1824       numberInColumnPlus[i] = -1;
1825       int start = startColumnU[i];
1826 
1827       while (where >= 0) {
1828         //put where it should be
1829         int numberNext = numberInColumn[where]; //always 0?
1830         int whereNext = numberInColumnPlus[where];
1831         int startNext = startColumnU[where];
1832 
1833         numberInColumn[where] = number;
1834         numberInColumnPlus[where] = -1;
1835         startColumnU[where] = start;
1836         number = numberNext;
1837         where = whereNext;
1838         start = startNext;
1839       } /* endwhile */
1840     }
1841     //sort - using indexColumn
1842     CoinFillN(indexColumnU_.array(), lastU, -1);
1843     int k = 0;
1844 
1845     for (i = numberSlacks_; i < numberRows_; i++) {
1846       int start = startColumn[i];
1847       int end = start + numberInColumn[i];
1848 
1849       int j;
1850       for (j = start; j < end; j++) {
1851         indexColumnU[j] = k++;
1852       }
1853     }
1854     for (i = numberSlacks_; i < numberRows_; i++) {
1855       int start = startColumn[i];
1856       int end = start + numberInColumn[i];
1857 
1858       int j;
1859       for (j = start; j < end; j++) {
1860         int k = indexColumnU[j];
1861         int iRow = indexRowU[j];
1862         CoinFactorizationDouble element = elementU[j];
1863 
1864         while (k != -1) {
1865           int kNext = indexColumnU[k];
1866           int iRowNext = indexRowU[k];
1867           CoinFactorizationDouble elementNext = elementU[k];
1868 
1869           indexColumnU[k] = -1;
1870           indexRowU[k] = iRow;
1871           elementU[k] = element;
1872           k = kNext;
1873           iRow = iRowNext;
1874           element = elementNext;
1875         } /* endwhile */
1876       }
1877     }
1878     CoinZeroN(startColumnU, numberSlacks_);
1879     k = 0;
1880     for (i = numberSlacks_; i < numberRows_; i++) {
1881       startColumnU[i] = k;
1882       k += numberInColumn[i];
1883     }
1884     maximumU_ = k;
1885 #if COIN_ONE_ETA_COPY
1886   } else {
1887     // U already OK
1888     for (i = 0; i < numberColumns_; i++) {
1889       int iColumn = pivotColumn[i];
1890       pivotColumnB[iColumn] = i;
1891     }
1892     maximumU_ = startColumnU[numberRows_ - 1] + numberInColumn[numberRows_ - 1];
1893     numberU = numberRows_;
1894   }
1895 #endif
1896   if ((messageLevel_ & 8)) {
1897     std::cout << "        length of U " << totalElements_ << ", length of L " << lengthL_;
1898     if (numberDense_)
1899       std::cout << " plus " << numberDense_ * numberDense_ << " from " << numberDense_ << " dense rows";
1900     std::cout << std::endl;
1901   }
1902   // and add L and dense
1903   totalElements_ += numberDense_ * numberDense_ + lengthL_;
1904   int *nextColumn = nextColumn_.array();
1905   int *lastColumn = lastColumn_.array();
1906   // See whether to have extra copy of R
1907 #ifndef ABC_USE_COIN_FACTORIZATION
1908   if (maximumU_ > 10 * numberRows_ || numberRows_ < 200) {
1909     // NO
1910     numberInColumnPlus_.conditionalDelete();
1911   } else {
1912 #endif
1913     for (i = 0; i < numberColumns_; i++) {
1914       lastColumn[i] = i - 1;
1915       nextColumn[i] = i + 1;
1916       numberInColumnPlus[i] = 0;
1917     }
1918     nextColumn[numberColumns_ - 1] = maximumColumnsExtra_;
1919     lastColumn[maximumColumnsExtra_] = numberColumns_ - 1;
1920     nextColumn[maximumColumnsExtra_] = 0;
1921     lastColumn[0] = maximumColumnsExtra_;
1922 #ifndef ABC_USE_COIN_FACTORIZATION
1923   }
1924 #endif
1925   numberU_ = numberU;
1926   numberGoodU_ = numberU;
1927   numberL_ = numberGoodL_;
1928 #if COIN_DEBUG
1929   for (i = 0; i < numberRows_; i++) {
1930     if (permute[i] < 0) {
1931       std::cout << i << std::endl;
1932       abort();
1933     }
1934   }
1935 #endif
1936   CoinFactorizationDouble *pivotRegion = pivotRegion_.array();
1937   for (i = numberSlacks_; i < numberU; i++) {
1938     int start = startColumnU[i];
1939     int end = start + numberInColumn[i];
1940 
1941     totalElements_ += numberInColumn[i];
1942     int j;
1943 
1944     for (j = start; j < end; j++) {
1945       int iRow = indexRowU[j];
1946       iRow = permute[iRow];
1947       indexRowU[j] = iRow;
1948       numberInRow[iRow]++;
1949     }
1950   }
1951 #if COIN_ONE_ETA_COPY
1952   if (numberRows_ >= COIN_ONE_ETA_COPY) {
1953 #endif
1954     //space for cross reference
1955     int lengthU = lengthAreaU_ + EXTRA_U_SPACE;
1956     convertRowToColumnU_.conditionalNew(lengthU);
1957     int *convertRowToColumn = convertRowToColumnU_.array();
1958     int j = 0;
1959     int *startRow = startRowU_.array();
1960 
1961     int iRow;
1962     for (iRow = 0; iRow < numberRows_; iRow++) {
1963       startRow[iRow] = j;
1964       j += numberInRow[iRow];
1965     }
1966     int numberInU = j;
1967 
1968     CoinZeroN(numberInRow_.array(), numberRows_);
1969 
1970     for (i = numberSlacks_; i < numberRows_; i++) {
1971       int start = startColumnU[i];
1972       int end = start + numberInColumn[i];
1973 
1974       CoinFactorizationDouble pivotValue = pivotRegion[i];
1975 
1976       int j;
1977       for (j = start; j < end; j++) {
1978         int iRow = indexRowU[j];
1979         int iLook = numberInRow[iRow];
1980 
1981         numberInRow[iRow] = iLook + 1;
1982         int k = startRow[iRow] + iLook;
1983 
1984         indexColumnU[k] = i;
1985         convertRowToColumn[k] = j;
1986         //multiply by pivot
1987         elementU[j] *= pivotValue;
1988       }
1989     }
1990     int *nextRow = nextRow_.array();
1991     int *lastRow = lastRow_.array();
1992     for (j = 0; j < numberRows_; j++) {
1993       lastRow[j] = j - 1;
1994       nextRow[j] = j + 1;
1995     }
1996     nextRow[numberRows_ - 1] = maximumRowsExtra_;
1997     lastRow[maximumRowsExtra_] = numberRows_ - 1;
1998     nextRow[maximumRowsExtra_] = 0;
1999     lastRow[0] = maximumRowsExtra_;
2000     startRow[maximumRowsExtra_] = numberInU;
2001 #if COIN_ONE_ETA_COPY
2002   } else {
2003     // no row copy
2004     for (i = numberSlacks_; i < numberU; i++) {
2005       int start = startColumnU[i];
2006       int end = start + numberInColumn[i];
2007 
2008       int j;
2009       CoinFactorizationDouble pivotValue = pivotRegion[i];
2010 
2011       for (j = start; j < end; j++) {
2012         //multiply by pivot
2013         elementU[j] *= pivotValue;
2014       }
2015     }
2016   }
2017 #endif
2018 
2019   int firstReal = numberRows_;
2020 
2021   int *startColumnL = startColumnL_.array();
2022   int *indexRowL = indexRowL_.array();
2023   for (i = numberRows_ - 1; i >= 0; i--) {
2024     int start = startColumnL[i];
2025     int end = startColumnL[i + 1];
2026 
2027     totalElements_ += end - start;
2028     if (end > start) {
2029       firstReal = i;
2030       int j;
2031       for (j = start; j < end; j++) {
2032         int iRow = indexRowL[j];
2033         iRow = permute[iRow];
2034         assert(iRow > firstReal);
2035         indexRowL[j] = iRow;
2036       }
2037     }
2038   }
2039   baseL_ = firstReal;
2040   numberL_ -= firstReal;
2041   factorElements_ = totalElements_;
2042   //can delete pivotRowL_ as not used
2043   pivotRowL_.conditionalDelete();
2044   //use L for R if room
2045   int space = lengthAreaL_ - lengthL_;
2046   int spaceUsed = lengthL_ + lengthU_;
2047 
2048   int needed = (spaceUsed + numberRows_ - 1) / numberRows_;
2049 
2050   needed = needed * 2 * maximumPivots_;
2051   if (needed < 2 * numberRows_) {
2052     needed = 2 * numberRows_;
2053   }
2054   if (numberInColumnPlus_.array()) {
2055     // Need double the space for R
2056     space = space / 2;
2057     startColumnR_.conditionalNew(maximumPivots_ + 1 + maximumColumnsExtra_ + 1);
2058     int *startR = startColumnR_.array() + maximumPivots_ + 1;
2059     CoinZeroN(startR, (maximumColumnsExtra_ + 1));
2060   } else {
2061     startColumnR_.conditionalNew(maximumPivots_ + 1);
2062   }
2063 #ifdef ZEROFAULT
2064   memset(startColumnR_.array(), 'z', (maximumPivots_ + 1) * sizeof(int));
2065 #endif
2066   if (space >= needed) {
2067     lengthR_ = 0;
2068     lengthAreaR_ = space;
2069     elementR_ = elementL_.array() + lengthL_;
2070     indexRowR_ = indexRowL_.array() + lengthL_;
2071   } else {
2072     lengthR_ = 0;
2073     lengthAreaR_ = space;
2074     elementR_ = elementL_.array() + lengthL_;
2075     indexRowR_ = indexRowL_.array() + lengthL_;
2076     if ((messageLevel_ & 4))
2077       std::cout << "Factorization may need some increasing area space"
2078                 << std::endl;
2079     if (areaFactor_) {
2080       areaFactor_ *= 1.1;
2081     } else {
2082       areaFactor_ = 1.1;
2083     }
2084   }
2085   numberR_ = 0;
2086 }
2087 // Returns areaFactor but adjusted for dense
2088 double
adjustedAreaFactor() const2089 CoinFactorization::adjustedAreaFactor() const
2090 {
2091   double factor = areaFactor_;
2092   if (numberDense_ && areaFactor_ > 1.0) {
2093     double dense = numberDense_;
2094     dense *= dense;
2095     double withoutDense = totalElements_ - dense + 1.0;
2096     factor *= 1.0 + dense / withoutDense;
2097   }
2098   return factor;
2099 }
2100 
2101 //  checkConsistency.  Checks that row and column copies look OK
checkConsistency()2102 void CoinFactorization::checkConsistency()
2103 {
2104   bool bad = false;
2105 
2106   int iRow;
2107   int *startRowU = startRowU_.array();
2108   int *numberInRow = numberInRow_.array();
2109   int *numberInColumn = numberInColumn_.array();
2110   int *indexColumnU = indexColumnU_.array();
2111   int *indexRowU = indexRowU_.array();
2112   int *startColumnU = startColumnU_.array();
2113   for (iRow = 0; iRow < numberRows_; iRow++) {
2114     if (numberInRow[iRow]) {
2115       int startRow = startRowU[iRow];
2116       int endRow = startRow + numberInRow[iRow];
2117 
2118       int j;
2119       for (j = startRow; j < endRow; j++) {
2120         int iColumn = indexColumnU[j];
2121         int startColumn = startColumnU[iColumn];
2122         int endColumn = startColumn + numberInColumn[iColumn];
2123         bool found = false;
2124 
2125         int k;
2126         for (k = startColumn; k < endColumn; k++) {
2127           if (indexRowU[k] == iRow) {
2128             found = true;
2129             break;
2130           }
2131         }
2132         if (!found) {
2133           bad = true;
2134           std::cout << "row " << iRow << " column " << iColumn << " Rows" << std::endl;
2135         }
2136       }
2137     }
2138   }
2139   int iColumn;
2140   for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
2141     if (numberInColumn[iColumn]) {
2142       int startColumn = startColumnU[iColumn];
2143       int endColumn = startColumn + numberInColumn[iColumn];
2144 
2145       int j;
2146       for (j = startColumn; j < endColumn; j++) {
2147         int iRow = indexRowU[j];
2148         int startRow = startRowU[iRow];
2149         int endRow = startRow + numberInRow[iRow];
2150         bool found = false;
2151 
2152         int k;
2153         for (k = startRow; k < endRow; k++) {
2154           if (indexColumnU[k] == iColumn) {
2155             found = true;
2156             break;
2157           }
2158         }
2159         if (!found) {
2160           bad = true;
2161           std::cout << "row " << iRow << " column " << iColumn << " Columns" << std::endl;
2162         }
2163       }
2164     }
2165   }
2166   if (bad) {
2167     abort();
2168   }
2169 }
2170 //  pivotOneOtherRow.  When just one other row so faster
pivotOneOtherRow(int pivotRow,int pivotColumn)2171 bool CoinFactorization::pivotOneOtherRow(int pivotRow,
2172   int pivotColumn)
2173 {
2174   int *numberInRow = numberInRow_.array();
2175   int *numberInColumn = numberInColumn_.array();
2176   int *numberInColumnPlus = numberInColumnPlus_.array();
2177   int numberInPivotRow = numberInRow[pivotRow] - 1;
2178   int *startRowU = startRowU_.array();
2179   int *startColumnU = startColumnU_.array();
2180   int startColumn = startColumnU[pivotColumn];
2181   int startRow = startRowU[pivotRow];
2182   int endRow = startRow + numberInPivotRow + 1;
2183 
2184   //take out this bit of indexColumnU
2185   int *nextRow = nextRow_.array();
2186   int *lastRow = lastRow_.array();
2187   int next = nextRow[pivotRow];
2188   int last = lastRow[pivotRow];
2189 
2190   nextRow[last] = next;
2191   lastRow[next] = last;
2192   nextRow[pivotRow] = numberGoodU_; //use for permute
2193   lastRow[pivotRow] = -2;
2194   numberInRow[pivotRow] = 0;
2195   //store column in L, compress in U and take column out
2196   int l = lengthL_;
2197 
2198   if (l + 1 > lengthAreaL_) {
2199     //need more memory
2200     if ((messageLevel_ & 4) != 0)
2201       std::cout << "more memory needed in middle of invert" << std::endl;
2202     return false;
2203   }
2204   //l+=currentAreaL_->elementByColumn-elementL_;
2205   //int lSave=l;
2206   int *startColumnL = startColumnL_.array();
2207   CoinFactorizationDouble *elementL = elementL_.array();
2208   int *indexRowL = indexRowL_.array();
2209   startColumnL[numberGoodL_] = l; //for luck and first time
2210   numberGoodL_++;
2211   startColumnL[numberGoodL_] = l + 1;
2212   lengthL_++;
2213   CoinFactorizationDouble pivotElement;
2214   CoinFactorizationDouble otherMultiplier;
2215   int otherRow;
2216   int *saveColumn = saveColumn_.array();
2217   CoinFactorizationDouble *elementU = elementU_.array();
2218   int *indexRowU = indexRowU_.array();
2219 
2220   if (indexRowU[startColumn] == pivotRow) {
2221     pivotElement = elementU[startColumn];
2222     otherMultiplier = elementU[startColumn + 1];
2223     otherRow = indexRowU[startColumn + 1];
2224   } else {
2225     pivotElement = elementU[startColumn + 1];
2226     otherMultiplier = elementU[startColumn];
2227     otherRow = indexRowU[startColumn];
2228   }
2229   int numberSave = numberInRow[otherRow];
2230   CoinFactorizationDouble pivotMultiplier = 1.0 / pivotElement;
2231 
2232   CoinFactorizationDouble *pivotRegion = pivotRegion_.array();
2233   pivotRegion[numberGoodU_] = pivotMultiplier;
2234   numberInColumn[pivotColumn] = 0;
2235   otherMultiplier = otherMultiplier * pivotMultiplier;
2236   indexRowL[l] = otherRow;
2237   elementL[l] = otherMultiplier;
2238   //take out of row list
2239   int start = startRowU[otherRow];
2240   int end = start + numberSave;
2241   int where = start;
2242   int *indexColumnU = indexColumnU_.array();
2243 
2244   while (indexColumnU[where] != pivotColumn) {
2245     where++;
2246   } /* endwhile */
2247   assert(where < end);
2248   end--;
2249   indexColumnU[where] = indexColumnU[end];
2250   int numberAdded = 0;
2251   int numberDeleted = 0;
2252 
2253   //pack down and move to work
2254   int j;
2255   const int *nextCount = nextCount_.array();
2256   int *nextColumn = nextColumn_.array();
2257 
2258   for (j = startRow; j < endRow; j++) {
2259     int iColumn = indexColumnU[j];
2260 
2261     if (iColumn != pivotColumn) {
2262       int startColumn = startColumnU[iColumn];
2263       int endColumn = startColumn + numberInColumn[iColumn];
2264       int iRow = indexRowU[startColumn];
2265       CoinFactorizationDouble value = elementU[startColumn];
2266       double largest;
2267       bool foundOther = false;
2268 
2269       //leave room for pivot
2270       int put = startColumn + 1;
2271       int positionLargest = -1;
2272       CoinFactorizationDouble thisPivotValue = 0.0;
2273       CoinFactorizationDouble otherElement = 0.0;
2274       CoinFactorizationDouble nextValue = elementU[put];
2275       ;
2276       int nextIRow = indexRowU[put];
2277 
2278       //compress column and find largest not updated
2279       if (iRow != pivotRow) {
2280         if (iRow != otherRow) {
2281           largest = fabs(value);
2282           elementU[put] = value;
2283           indexRowU[put] = iRow;
2284           positionLargest = put;
2285           put++;
2286           int i;
2287           for (i = startColumn + 1; i < endColumn; i++) {
2288             iRow = nextIRow;
2289             value = nextValue;
2290 #ifdef ZEROFAULT
2291             // doesn't matter reading uninitialized but annoys checking
2292             if (i + 1 < endColumn) {
2293 #endif
2294               nextIRow = indexRowU[i + 1];
2295               nextValue = elementU[i + 1];
2296 #ifdef ZEROFAULT
2297             }
2298 #endif
2299             if (iRow != pivotRow) {
2300               if (iRow != otherRow) {
2301                 //keep
2302                 indexRowU[put] = iRow;
2303                 elementU[put] = value;
2304                 ;
2305                 put++;
2306               } else {
2307                 otherElement = value;
2308                 foundOther = true;
2309               }
2310             } else {
2311               thisPivotValue = value;
2312             }
2313           }
2314         } else {
2315           otherElement = value;
2316           foundOther = true;
2317           //need to find largest
2318           largest = 0.0;
2319           int i;
2320           for (i = startColumn + 1; i < endColumn; i++) {
2321             iRow = nextIRow;
2322             value = nextValue;
2323 #ifdef ZEROFAULT
2324             // doesn't matter reading uninitialized but annoys checking
2325             if (i + 1 < endColumn) {
2326 #endif
2327               nextIRow = indexRowU[i + 1];
2328               nextValue = elementU[i + 1];
2329 #ifdef ZEROFAULT
2330             }
2331 #endif
2332             if (iRow != pivotRow) {
2333               //keep
2334               indexRowU[put] = iRow;
2335               elementU[put] = value;
2336               ;
2337               double absValue = fabs(value);
2338 
2339               if (absValue > largest) {
2340                 largest = absValue;
2341                 positionLargest = put;
2342               }
2343               put++;
2344             } else {
2345               thisPivotValue = value;
2346             }
2347           }
2348         }
2349       } else {
2350         //need to find largest
2351         largest = 0.0;
2352         thisPivotValue = value;
2353         int i;
2354         for (i = startColumn + 1; i < endColumn; i++) {
2355           iRow = nextIRow;
2356           value = nextValue;
2357 #ifdef ZEROFAULT
2358           // doesn't matter reading uninitialized but annoys checking
2359           if (i + 1 < endColumn) {
2360 #endif
2361             nextIRow = indexRowU[i + 1];
2362             nextValue = elementU[i + 1];
2363 #ifdef ZEROFAULT
2364           }
2365 #endif
2366           if (iRow != otherRow) {
2367             //keep
2368             indexRowU[put] = iRow;
2369             elementU[put] = value;
2370             ;
2371             double absValue = fabs(value);
2372 
2373             if (absValue > largest) {
2374               largest = absValue;
2375               positionLargest = put;
2376             }
2377             put++;
2378           } else {
2379             otherElement = value;
2380             foundOther = true;
2381           }
2382         }
2383       }
2384       //slot in pivot
2385       elementU[startColumn] = thisPivotValue;
2386       indexRowU[startColumn] = pivotRow;
2387       //clean up counts
2388       startColumn++;
2389       numberInColumn[iColumn] = put - startColumn;
2390       numberInColumnPlus[iColumn]++;
2391       startColumnU[iColumn]++;
2392       otherElement = otherElement - thisPivotValue * otherMultiplier;
2393       double absValue = fabs(otherElement);
2394 
2395       if (absValue > zeroTolerance_) {
2396         if (!foundOther) {
2397           //have we space
2398           saveColumn[numberAdded++] = iColumn;
2399           int next = nextColumn[iColumn];
2400           int space;
2401 
2402           space = startColumnU[next] - put - numberInColumnPlus[next];
2403           if (space <= 0) {
2404             //getColumnSpace also moves fixed part
2405             int number = numberInColumn[iColumn];
2406 
2407             if (!getColumnSpace(iColumn, number + 1)) {
2408               return false;
2409             }
2410             //redo starts
2411             positionLargest = positionLargest + startColumnU[iColumn] - startColumn;
2412             startColumn = startColumnU[iColumn];
2413             put = startColumn + number;
2414           }
2415         }
2416         elementU[put] = otherElement;
2417         indexRowU[put] = otherRow;
2418         if (absValue > largest) {
2419           largest = absValue;
2420           positionLargest = put;
2421         }
2422         put++;
2423       } else {
2424         if (foundOther) {
2425           numberDeleted++;
2426           //take out of row list
2427           int where = start;
2428 
2429           while (indexColumnU[where] != iColumn) {
2430             where++;
2431           } /* endwhile */
2432           assert(where < end);
2433           end--;
2434           indexColumnU[where] = indexColumnU[end];
2435         }
2436       }
2437       numberInColumn[iColumn] = put - startColumn;
2438       //move largest
2439       if (positionLargest >= 0) {
2440         value = elementU[positionLargest];
2441         iRow = indexRowU[positionLargest];
2442         elementU[positionLargest] = elementU[startColumn];
2443         indexRowU[positionLargest] = indexRowU[startColumn];
2444         elementU[startColumn] = value;
2445         indexRowU[startColumn] = iRow;
2446       }
2447       //linked list for column
2448       if (nextCount[iColumn + numberRows_] != -2) {
2449         //modify linked list
2450         deleteLink(iColumn + numberRows_);
2451         addLink(iColumn + numberRows_, numberInColumn[iColumn]);
2452       }
2453     }
2454   }
2455   //get space for row list
2456   next = nextRow[otherRow];
2457   int space;
2458 
2459   space = startRowU[next] - end;
2460   totalElements_ += numberAdded - numberDeleted;
2461   int number = numberAdded + (end - start);
2462 
2463   if (space < numberAdded) {
2464     numberInRow[otherRow] = end - start;
2465     if (!getRowSpace(otherRow, number)) {
2466       return false;
2467     }
2468     end = startRowU[otherRow] + end - start;
2469   }
2470   // do linked lists and update counts
2471   numberInRow[otherRow] = number;
2472   if (number != numberSave) {
2473     deleteLink(otherRow);
2474     addLink(otherRow, number);
2475   }
2476   for (j = 0; j < numberAdded; j++) {
2477     indexColumnU[end++] = saveColumn[j];
2478   }
2479   //modify linked list for pivots
2480   deleteLink(pivotRow);
2481   deleteLink(pivotColumn + numberRows_);
2482   return true;
2483 }
setPersistenceFlag(int flag)2484 void CoinFactorization::setPersistenceFlag(int flag)
2485 {
2486   persistenceFlag_ = flag;
2487   workArea_.setPersistence(flag, maximumRowsExtra_ + 1);
2488   workArea2_.setPersistence(flag, maximumRowsExtra_ + 1);
2489   pivotColumn_.setPersistence(flag, maximumColumnsExtra_ + 1);
2490   permute_.setPersistence(flag, maximumRowsExtra_ + 1);
2491   pivotColumnBack_.setPersistence(flag, maximumRowsExtra_ + 1);
2492   permuteBack_.setPersistence(flag, maximumRowsExtra_ + 1);
2493   nextRow_.setPersistence(flag, maximumRowsExtra_ + 1);
2494   startRowU_.setPersistence(flag, maximumRowsExtra_ + 1);
2495   numberInRow_.setPersistence(flag, maximumRowsExtra_ + 1);
2496   numberInColumn_.setPersistence(flag, maximumColumnsExtra_ + 1);
2497   numberInColumnPlus_.setPersistence(flag, maximumColumnsExtra_ + 1);
2498   firstCount_.setPersistence(flag, CoinMax(biggerDimension_ + 2, maximumRowsExtra_ + 1));
2499   nextCount_.setPersistence(flag, numberRows_ + numberColumns_);
2500   lastCount_.setPersistence(flag, numberRows_ + numberColumns_);
2501   nextColumn_.setPersistence(flag, maximumColumnsExtra_ + 1);
2502   lastColumn_.setPersistence(flag, maximumColumnsExtra_ + 1);
2503   lastRow_.setPersistence(flag, maximumRowsExtra_ + 1);
2504   markRow_.setPersistence(flag, numberRows_);
2505   saveColumn_.setPersistence(flag, numberColumns_);
2506   indexColumnU_.setPersistence(flag, lengthAreaU_);
2507   pivotRowL_.setPersistence(flag, numberRows_ + 1);
2508   pivotRegion_.setPersistence(flag, maximumRowsExtra_ + 1);
2509   elementU_.setPersistence(flag, lengthAreaU_);
2510   indexRowU_.setPersistence(flag, lengthAreaU_);
2511   startColumnU_.setPersistence(flag, maximumColumnsExtra_ + 1);
2512   convertRowToColumnU_.setPersistence(flag, lengthAreaU_);
2513   elementL_.setPersistence(flag, lengthAreaL_);
2514   indexRowL_.setPersistence(flag, lengthAreaL_);
2515   startColumnL_.setPersistence(flag, numberRows_ + 1);
2516   startColumnR_.setPersistence(flag, maximumPivots_ + 1 + maximumColumnsExtra_ + 1);
2517   startRowL_.setPersistence(flag, 0);
2518   indexColumnL_.setPersistence(flag, 0);
2519   elementByRowL_.setPersistence(flag, 0);
2520   sparse_.setPersistence(flag, 0);
2521 }
2522 // Delete all stuff
almostDestructor()2523 void CoinFactorization::almostDestructor()
2524 {
2525   gutsOfDestructor(2);
2526 }
2527 
2528 /* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2
2529 */
2530