1 /* $Id: CoinAbcBaseFactorization.hpp 2385 2019-01-06 19:43:06Z unxusr $ */
2 // Copyright (C) 2002, International Business Machines
3 // Corporation and others, Copyright (C) 2012, FasterCoin.  All Rights Reserved.
4 // This code is licensed under the terms of the Eclipse Public License (EPL).
5 
6 /*
7    Authors
8 
9    John Forrest
10 
11  */
12 /** This deals with Factorization and Updates
13 
14     I am assuming that 32 bits is enough for number of rows or columns, but CoinBigIndex
15     may be redefined to get 64 bits.
16  */
17 
18 #include "AbcCommon.hpp"
19 #include "CoinAbcHelperFunctions.hpp"
20 #if ABC_PARALLEL
21 #define FACTOR_CPU 4
22 #else
23 #define FACTOR_CPU 1
24 #endif
25 #define LARGE_SET COIN_INT_MAX - 10
26 #define LARGE_UNSET (LARGE_SET + 1)
27 
28 class CoinAbcTypeFactorization : public CoinAbcAnyFactorization {
29   friend void CoinAbcFactorizationUnitTest(const std::string &mpsDir);
30 
31 public:
32   /**@name Constructors and destructor and copy */
33   //@{
34   /// Default constructor
35   CoinAbcTypeFactorization();
36   /// Copy constructor
37   CoinAbcTypeFactorization(const CoinAbcTypeFactorization &other);
38   /// Copy constructor
39   CoinAbcTypeFactorization(const CoinFactorization &other);
40 
41   /// Destructor
42   virtual ~CoinAbcTypeFactorization();
43   /// Clone
44   virtual CoinAbcAnyFactorization *clone() const;
45   /// Delete all stuff (leaves as after CoinAbcFactorization())
46   void almostDestructor();
47   /// Debug show object (shows one representation)
48   void show_self() const;
49   /// Debug - sort so can compare
50   void sort() const;
51   /// = copy
52   CoinAbcTypeFactorization &operator=(const CoinAbcTypeFactorization &other);
53   //@}
54 
55   /**@name Do factorization */
56   //@{
57   /// Condition number - product of pivots after factorization
58   CoinSimplexDouble conditionNumber() const;
59 
60   //@}
61 
62   /**@name general stuff such as permutation or status */
63   //@{
64   /// Returns address of permute region
permute() const65   inline CoinSimplexInt *permute() const
66   {
67     return NULL; //permute_.array();
68   }
69   /// Returns array to put basis indices in
indices() const70   virtual inline CoinSimplexInt *indices() const
71   {
72     return indexRowU_.array();
73   }
74   /// Returns address of pivotColumn region (also used for permuting)
pivotColumn() const75   virtual inline CoinSimplexInt *pivotColumn() const
76   {
77     return pivotColumn_.array();
78   }
79   /// Returns address of pivot region
pivotRegion() const80   virtual inline CoinFactorizationDouble *pivotRegion() const
81   {
82     return pivotRegionAddress_;
83   }
84 #if ABC_SMALL < 2
85   /// Start of each row in L
startRowL() const86   inline CoinBigIndex *startRowL() const
87   {
88     return startRowL_.array();
89   }
90 #endif
91 
92   /// Start of each column in L
startColumnL() const93   inline CoinBigIndex *startColumnL() const
94   {
95     return startColumnL_.array();
96   }
97 
98 #if ABC_SMALL < 2
99   /// Index of column in row for L
indexColumnL() const100   inline CoinSimplexInt *indexColumnL() const
101   {
102     return indexColumnL_.array();
103   }
104 #endif
105 
106   /// Row indices of L
indexRowL() const107   inline CoinSimplexInt *indexRowL() const
108   {
109     return indexRowL_.array();
110   }
111 
112 #if ABC_SMALL < 2
113   /// Elements in L (row copy)
elementByRowL() const114   inline CoinFactorizationDouble *elementByRowL() const
115   {
116     return elementByRowL_.array();
117   }
118 #endif
119   /**
120      Forward and backward linked lists (numberRows_+2)
121    **/
pivotLinkedBackwards() const122   inline CoinSimplexInt *pivotLinkedBackwards() const
123   {
124     return firstCount_.array() + numberRows_ + 1;
125   }
pivotLinkedForwards() const126   inline CoinSimplexInt *pivotLinkedForwards() const
127   {
128     return firstCount_.array() + 2 * numberRows_ + 3;
129   }
pivotLOrder() const130   inline CoinSimplexInt *pivotLOrder() const
131   {
132     return firstCount_.array();
133   }
134 #if ABC_SMALL < 0
135 #define ABC_USE_FUNCTION_POINTERS 0
136 #define SMALL_PERMUTE
137 #endif
138 #ifdef ABC_USE_FUNCTION_POINTERS
139   typedef void (*scatterUpdate)(int, CoinFactorizationDouble, const CoinFactorizationDouble *, CoinFactorizationDouble *);
140 #if ABC_USE_FUNCTION_POINTERS
141   typedef struct {
142     scatterUpdate functionPointer;
143     CoinBigIndex offset;
144     int number;
145   } scatterStruct;
146 #else
147   typedef struct {
148     CoinBigIndex offset;
149     int number;
150   } scatterStruct;
151 #endif
152   /// Array of function pointers PLUS for U Column
scatterUColumn() const153   inline scatterStruct *scatterUColumn() const
154   {
155     return scatterPointersUColumnAddress_;
156   }
157 #endif
158 
159   /// For equal counts in factorization
160   /** First Row/Column with count of k,
161       can tell which by offset - Rows then Columns
162       actually comes before nextCount*/
firstCount() const163   inline CoinSimplexInt *firstCount() const
164   {
165     return firstCount_.array();
166   }
167 
168   /// Next Row/Column with count
nextCount() const169   inline CoinSimplexInt *nextCount() const
170   {
171     return firstCount_.array() + numberRows_ + 2;
172   }
173 
174   /// Previous Row/Column with count
lastCount() const175   inline CoinSimplexInt *lastCount() const
176   {
177     return firstCount_.array() + 3 * numberRows_ + 2;
178   }
179 
180   /// Number of Rows after iterating
numberRowsExtra() const181   inline CoinSimplexInt numberRowsExtra() const
182   {
183     return numberRowsExtra_;
184   }
185   /// Number in L
numberL() const186   inline CoinBigIndex numberL() const
187   {
188     return numberL_;
189   }
190 
191   /// Base of L
baseL() const192   inline CoinBigIndex baseL() const
193   {
194     return baseL_;
195   }
196   /// Maximum of Rows after iterating
maximumRowsExtra() const197   inline CoinSimplexInt maximumRowsExtra() const
198   {
199     return maximumRowsExtra_;
200   }
201   /// Total number of elements in factorization
numberElements() const202   virtual inline CoinBigIndex numberElements() const
203   {
204     return totalElements_;
205   }
206   /// Length of FT vector
numberForrestTomlin() const207   inline CoinSimplexInt numberForrestTomlin() const
208   {
209     return numberInColumn_.array()[numberRowsExtra_];
210   }
211   /// Returns areaFactor but adjusted for dense
212   CoinSimplexDouble adjustedAreaFactor() const;
213   /// Level of detail of messages
messageLevel() const214   inline CoinSimplexInt messageLevel() const
215   {
216     return messageLevel_;
217   }
218   void messageLevel(CoinSimplexInt value);
219   /// Set maximum pivots
220   virtual void maximumPivots(CoinSimplexInt value);
221 
222 #if ABC_SMALL < 4
223   /// Gets dense threshold
denseThreshold() const224   inline CoinSimplexInt denseThreshold() const
225   {
226     return denseThreshold_;
227   }
228   /// Sets dense threshold
setDenseThreshold(CoinSimplexInt value)229   inline void setDenseThreshold(CoinSimplexInt value)
230   {
231     denseThreshold_ = value;
232   }
233 #endif
234   /// Returns maximum absolute value in factorization
235   CoinSimplexDouble maximumCoefficient() const;
236 #if 0
237   /// true if Forrest Tomlin update, false if PFI
238   inline bool forrestTomlin() const
239   { return doForrestTomlin_;}
240   inline void setForrestTomlin(bool value)
241   { doForrestTomlin_=value;}
242 #endif
243   /// True if FT update and space
spaceForForrestTomlin() const244   inline bool spaceForForrestTomlin() const
245   {
246     CoinBigIndex start = lastEntryByColumnU_;
247     CoinBigIndex space = lengthAreaU_ - (start + numberRowsExtra_);
248     return (space >= 0); //&&doForrestTomlin_;
249   }
250   //@}
251 
252   /**@name some simple stuff */
253   //@{
254 
255   /// Returns number in U area
numberElementsU() const256   inline CoinBigIndex numberElementsU() const
257   {
258     return lengthU_;
259   }
260   /// Setss number in U area
setNumberElementsU(CoinBigIndex value)261   inline void setNumberElementsU(CoinBigIndex value)
262   {
263     lengthU_ = value;
264   }
265   /// Returns length of U area
lengthAreaU() const266   inline CoinBigIndex lengthAreaU() const
267   {
268     return lengthAreaU_;
269   }
270   /// Returns number in L area
numberElementsL() const271   inline CoinBigIndex numberElementsL() const
272   {
273     return lengthL_;
274   }
275   /// Returns length of L area
lengthAreaL() const276   inline CoinBigIndex lengthAreaL() const
277   {
278     return lengthAreaL_;
279   }
280   /// Returns number in R area
numberElementsR() const281   inline CoinBigIndex numberElementsR() const
282   {
283     return lengthR_;
284   }
285   /// Number of compressions done
numberCompressions() const286   inline CoinBigIndex numberCompressions() const
287   {
288     return numberCompressions_;
289   }
290   /// Returns pivot row
291   //virtual CoinSimplexInt * pivotRow() const;
292   /// Returns work area
293   //virtual CoinFactorizationDouble * workArea() const;
294   /// Returns CoinSimplexInt work area
295   //virtual CoinSimplexInt * intWorkArea() const;
296   /// Returns array to put basis starts in
starts() const297   virtual inline CoinBigIndex *starts() const
298   {
299     return startColumnU_.array();
300   }
301   /// Number of entries in each row
numberInRow() const302   virtual inline CoinSimplexInt *numberInRow() const
303   {
304     return numberInRow_.array();
305   }
306   /// Number of entries in each column
numberInColumn() const307   virtual inline CoinSimplexInt *numberInColumn() const
308   {
309     return numberInColumn_.array();
310   }
311   /// Returns array to put basis elements in
elements() const312   virtual inline CoinFactorizationDouble *elements() const
313   {
314     return elementU_.array();
315   }
316   /// Start of columns for R
startColumnR() const317   inline CoinBigIndex *startColumnR() const
318   {
319     return reinterpret_cast< CoinBigIndex * >(firstCount_.array() + 3 * numberRows_ + 4);
320   }
321   /// Elements of U
elementU() const322   inline CoinFactorizationDouble *elementU() const
323   {
324     return elementU_.array();
325   }
326   /// Row indices of U
indexRowU() const327   inline CoinSimplexInt *indexRowU() const
328   {
329     return indexRowU_.array();
330   }
331   /// Start of each column in U
startColumnU() const332   inline CoinBigIndex *startColumnU() const
333   {
334     return startColumnU_.array();
335   }
336 #if COIN_BIG_DOUBLE == 1
337   /// To a work array and associate vector
338   void toLongArray(CoinIndexedVector *vector, int which) const;
339   /// From a work array and dis-associate vector
340   void fromLongArray(CoinIndexedVector *vector) const;
341   /// From a work array and dis-associate vector
342   void fromLongArray(int which) const;
343   /// Returns long double * associated with vector
344   long double *denseVector(CoinIndexedVector *vector) const;
345   /// Returns long double * associated with vector
346   long double *denseVector(CoinIndexedVector &vector) const;
347   /// Returns long double * associated with vector
348   const long double *denseVector(const CoinIndexedVector *vector) const;
349   /// Returns long double * associated with vector
350   const long double *denseVector(const CoinIndexedVector &vector) const;
351   /// Scans region to find nonzeros
352   void scan(CoinIndexedVector *vector) const;
353   /// Clear all hidden arrays
354   void clearHiddenArrays();
355 #else
356   /// Returns double * associated with vector
denseVector(CoinIndexedVector * vector) const357   inline double *denseVector(CoinIndexedVector *vector) const
358   {
359     return vector->denseVector();
360   }
denseVector(CoinIndexedVector & vector) const361   inline double *denseVector(CoinIndexedVector &vector) const
362   {
363     return vector.denseVector();
364   }
365   /// Returns double * associated with vector
denseVector(const CoinIndexedVector * vector) const366   inline const double *denseVector(const CoinIndexedVector *vector) const
367   {
368     return vector->denseVector();
369   }
denseVector(const CoinIndexedVector & vector) const370   inline const double *denseVector(const CoinIndexedVector &vector) const
371   {
372     return vector.denseVector();
373   }
374   /// To a work array and associate vector
toLongArray(CoinIndexedVector * vector,int which) const375   inline void toLongArray(CoinIndexedVector *vector, int which) const {}
376   /// From a work array and dis-associate vector
fromLongArray(CoinIndexedVector * vector) const377   inline void fromLongArray(CoinIndexedVector *vector) const {}
378   /// From a work array and dis-associate vector
fromLongArray(int which) const379   inline void fromLongArray(int which) const {}
380   /// Scans region to find nonzeros
scan(CoinIndexedVector * vector) const381   inline void scan(CoinIndexedVector *vector) const
382   {
383     vector->scan(0, numberRows_, zeroTolerance_);
384   }
385 #endif
386 #ifdef ABC_ORDERED_FACTORIZATION
387   /// Permute in for Ftran
388   void permuteInForFtran(CoinIndexedVector &regionSparse, bool full = false) const;
389   /// Permute in for Btran and multiply by pivot Region
390   void permuteInForBtranAndMultiply(CoinIndexedVector &regionSparse, bool full = false) const;
391   /// Permute out for Btran
392   void permuteOutForBtran(CoinIndexedVector &regionSparse) const;
393 #endif
394   /** Array persistence flag
395       If 0 then as now (delete/new)
396       1 then only do arrays if bigger needed
397       2 as 1 but give a bit extra if bigger needed
398   */
399   //inline CoinSimplexInt persistenceFlag() const
400   //{ return persistenceFlag_;}
401   //@}
402 
403   /**@name rank one updates which do exist */
404   //@{
405 #if 0
406   /** Checks if can replace one Column to basis,
407       returns 0=OK, 1=Probably OK, 2=singular, 3=no room, 5 max pivots
408       Fills in region for use later
409       partial update already in U */
410   virtual int checkReplace ( const AbcSimplex * model,
411 		      CoinIndexedVector * regionSparse,
412 		      int pivotRow,
413 		      CoinSimplexDouble & pivotCheck,
414 			     double acceptablePivot = 1.0e-8);
415   /** Replaces one Column to basis,
416    returns 0=OK, 1=Probably OK, 2=singular, 3=no room
417       If skipBtranU is false will do btran part
418    partial update already in U */
419   virtual CoinSimplexInt replaceColumn ( CoinIndexedVector * regionSparse,
420 		      CoinSimplexInt pivotRow,
421 		      CoinSimplexDouble pivotCheck ,
422 		      bool skipBtranU=false,
423 		      CoinSimplexDouble acceptablePivot=1.0e-8);
424 #endif
425   /** Checks if can replace one Column to basis,
426       returns update alpha
427       Fills in region for use later
428       partial update already in U */
429   virtual
430 #ifdef ABC_LONG_FACTORIZATION
431     long
432 #endif
433     double
434     checkReplacePart1(CoinIndexedVector *regionSparse,
435       int pivotRow);
436   /** Checks if can replace one Column to basis,
437       returns update alpha
438       Fills in region for use later
439       partial update in vector */
440   virtual
441 #ifdef ABC_LONG_FACTORIZATION
442     long
443 #endif
444     double
445     checkReplacePart1(CoinIndexedVector *regionSparse,
446       CoinIndexedVector *partialUpdate,
447       int pivotRow);
448 #ifdef MOVE_REPLACE_PART1A
449   /** Checks if can replace one Column to basis,
450       returns update alpha
451       Fills in region for use later
452       partial update already in U */
453   virtual void checkReplacePart1a(CoinIndexedVector *regionSparse,
454     int pivotRow);
455   virtual
456 #ifdef ABC_LONG_FACTORIZATION
457     long
458 #endif
459     double
460     checkReplacePart1b(CoinIndexedVector *regionSparse,
461       int pivotRow);
462 #endif
463   /** Checks if can replace one Column to basis,
464       returns 0=OK, 1=Probably OK, 2=singular, 3=no room, 5 max pivots */
465   virtual int checkReplacePart2(int pivotRow,
466     CoinSimplexDouble btranAlpha,
467     double ftranAlpha,
468 #ifdef ABC_LONG_FACTORIZATION
469     long
470 #endif
471     double ftAlpha,
472     double acceptablePivot = 1.0e-8);
473   /** Replaces one Column to basis,
474       partial update already in U */
475   virtual void replaceColumnPart3(const AbcSimplex *model,
476     CoinIndexedVector *regionSparse,
477     CoinIndexedVector *tableauColumn,
478     int pivotRow,
479 #ifdef ABC_LONG_FACTORIZATION
480     long
481 #endif
482     double alpha);
483   /** Replaces one Column to basis,
484       partial update in vector */
485   virtual void replaceColumnPart3(const AbcSimplex *model,
486     CoinIndexedVector *regionSparse,
487     CoinIndexedVector *tableauColumn,
488     CoinIndexedVector *partialUpdate,
489     int pivotRow,
490 #ifdef ABC_LONG_FACTORIZATION
491     long
492 #endif
493     double alpha);
494 #ifdef EARLY_FACTORIZE
495   /// 0 success, -1 can't +1 accuracy problems
496   virtual int replaceColumns(const AbcSimplex *model,
497     CoinIndexedVector &stuff,
498     int firstPivot, int lastPivot, bool cleanUp);
499 #endif
500   /// Update partial Ftran by R update
501   void updatePartialUpdate(CoinIndexedVector &partialUpdate);
502   /// Returns true if wants tableauColumn in replaceColumn
wantsTableauColumn() const503   inline virtual bool wantsTableauColumn() const
504   {
505     return false;
506   }
507   /** Combines BtranU and store which elements are to be deleted
508       returns number to be deleted
509   */
510   int replaceColumnU(CoinIndexedVector *regionSparse,
511     CoinBigIndex *deletedPosition,
512     CoinSimplexInt *deletedColumns,
513     CoinSimplexInt pivotRow);
514   //@}
515 
516   /**@name various uses of factorization (return code number elements)
517    which user may want to know about */
518   /// Later take out return codes (apart from +- 1 on FT)
519   //@{
520   /** Updates one column (FTRAN) from regionSparse2
521       Tries to do FT update
522       number returned is negative if no room
523       regionSparse starts as zero and is zero at end.
524       Note - if regionSparse2 packed on input - will be packed on output
525   */
526   virtual CoinSimplexInt updateColumnFT(CoinIndexedVector &regionSparse);
527   virtual int updateColumnFTPart1(CoinIndexedVector &regionSparse);
528   virtual void updateColumnFTPart2(CoinIndexedVector &regionSparse);
529   /** Updates one column (FTRAN)
530       Tries to do FT update
531       puts partial update in vector */
532   virtual void updateColumnFT(CoinIndexedVector &regionSparseFT,
533     CoinIndexedVector &partialUpdate,
534     int which);
535   /** This version has same effect as above with FTUpdate==false
536       so number returned is always >=0 */
537   virtual CoinSimplexInt updateColumn(CoinIndexedVector &regionSparse) const;
538   /** Updates one column (FTRAN) from region2
539       Tries to do FT update
540       number returned is negative if no room.
541       Also updates region3
542       region1 starts as zero and is zero at end */
543   virtual CoinSimplexInt updateTwoColumnsFT(CoinIndexedVector &regionFT,
544     CoinIndexedVector &regionOther);
545   /** Updates one column (BTRAN) from regionSparse2
546       regionSparse starts as zero and is zero at end
547       Note - if regionSparse2 packed on input - will be packed on output
548   */
549   virtual CoinSimplexInt updateColumnTranspose(CoinIndexedVector &regionSparse) const;
550   /** Updates one full column (FTRAN) */
551   virtual void updateFullColumn(CoinIndexedVector &regionSparse) const;
552   /** Updates one full column (BTRAN) */
553   virtual void updateFullColumnTranspose(CoinIndexedVector &regionSparse) const;
554   /** Updates one column for dual steepest edge weights (FTRAN) */
555   virtual void updateWeights(CoinIndexedVector &regionSparse) const;
556   /** Updates one column (FTRAN) */
557   virtual void updateColumnCpu(CoinIndexedVector &regionSparse, int whichCpu) const;
558   /** Updates one column (BTRAN) */
559   virtual void updateColumnTransposeCpu(CoinIndexedVector &regionSparse, int whichCpu) const;
560   void unpack(CoinIndexedVector *regionFrom,
561     CoinIndexedVector *regionTo) const;
562   void pack(CoinIndexedVector *regionFrom,
563     CoinIndexedVector *regionTo) const;
564   /** makes a row copy of L for speed and to allow very sparse problems */
goSparse()565   inline void goSparse() {}
566   void goSparse2();
567 #ifndef NDEBUG
568   virtual void checkMarkArrays() const;
569 #endif
570 #if ABC_SMALL < 2
571   /**  get sparse threshold */
sparseThreshold() const572   inline CoinSimplexInt sparseThreshold() const
573   {
574     return sparseThreshold_;
575   }
576 #endif
577   /**  set sparse threshold */
578   void sparseThreshold(CoinSimplexInt value);
579   //@}
580   /// *** Below this user may not want to know about
581 
582   /**@name various uses of factorization (return code number elements)
583    which user may not want to know about (left over from my LP code) */
584   //@{
585   /// Get rid of all memory
clearArrays()586   inline void clearArrays()
587   {
588     gutsOfDestructor();
589   }
590   //@}
591   /**@name used by ClpFactorization */
592   /// See if worth going sparse
593   void checkSparse();
594   /// The real work of constructors etc 0 just scalars, 1 bit normal
595   void gutsOfDestructor(CoinSimplexInt type = 1);
596   /// 1 bit - tolerances etc, 2 more, 4 dummy arrays
597   void gutsOfInitialize(CoinSimplexInt type);
598   void gutsOfCopy(const CoinAbcTypeFactorization &other);
599 
600   /// Reset all sparsity etc statistics
601   void resetStatistics();
602   void printRegion(const CoinIndexedVector &vector, const char *where) const;
603 
604   //@}
605 
606   /**@name used by factorization */
607   /// Gets space for a factorization, called by constructors
608   virtual void getAreas(CoinSimplexInt numberRows,
609     CoinSimplexInt numberColumns,
610     CoinBigIndex maximumL,
611     CoinBigIndex maximumU);
612 
613   /// PreProcesses column ordered copy of basis
614   virtual void preProcess();
615   void preProcess(CoinSimplexInt);
616   /// Return largest element
617   double preProcess3();
618   void preProcess4();
619   /// Does most of factorization
620   virtual CoinSimplexInt factor(AbcSimplex *model);
621 #ifdef EARLY_FACTORIZE
622   /// Returns -2 if can't, -1 if singular, -99 memory, 0 OK
623   virtual int factorize(AbcSimplex *model, CoinIndexedVector &stuff);
624 #endif
625   /// Does post processing on valid factorization - putting variables on correct rows
626   virtual void postProcess(const CoinSimplexInt *sequence, CoinSimplexInt *pivotVariable);
627   /// Makes a non-singular basis by replacing variables
628   virtual void makeNonSingular(CoinSimplexInt *sequence);
629 
630 protected:
631   /** Does sparse phase of factorization
632       return code is <0 error, 0= finished */
633   CoinSimplexInt factorSparse();
634   /** Does dense phase of factorization
635       return code is <0 error, 0= finished */
636   CoinSimplexInt factorDense();
637 
638   /// Pivots when just one other row so faster?
639   bool pivotOneOtherRow(CoinSimplexInt pivotRow,
640     CoinSimplexInt pivotColumn);
641   /// Does one pivot on Row Singleton in factorization
642   bool pivotRowSingleton(CoinSimplexInt pivotRow,
643     CoinSimplexInt pivotColumn);
644   /// Does one pivot on Column Singleton in factorization (can't return false)
645   void pivotColumnSingleton(CoinSimplexInt pivotRow,
646     CoinSimplexInt pivotColumn);
647   /// After pivoting
648   void afterPivot(CoinSimplexInt pivotRow,
649     CoinSimplexInt pivotColumn);
650   /// After pivoting - returns true if need to go dense
651   int wantToGoDense();
652 
653   /** Gets space for one Column with given length,
654    may have to do compression  (returns True if successful),
655    also moves existing vector,
656    extraNeeded is over and above present */
657   bool getColumnSpace(CoinSimplexInt iColumn,
658     CoinSimplexInt extraNeeded);
659 
660   /** Reorders U so contiguous and in order (if there is space)
661       Returns true if it could */
662   bool reorderU();
663   /**  getColumnSpaceIterateR.  Gets space for one extra R element in Column
664        may have to do compression  (returns true)
665        also moves existing vector */
666   bool getColumnSpaceIterateR(CoinSimplexInt iColumn, CoinFactorizationDouble value,
667     CoinSimplexInt iRow);
668   /**  getColumnSpaceIterate.  Gets space for one extra U element in Column
669        may have to do compression  (returns true)
670        also moves existing vector.
671        Returns -1 if no memory or where element was put
672        Used by replaceRow (turns off R version) */
673   CoinBigIndex getColumnSpaceIterate(CoinSimplexInt iColumn, CoinFactorizationDouble value,
674     CoinSimplexInt iRow);
675   /** Gets space for one Row with given length,
676   may have to do compression  (returns True if successful),
677   also moves existing vector */
678   bool getRowSpace(CoinSimplexInt iRow, CoinSimplexInt extraNeeded);
679 
680   /** Gets space for one Row with given length while iterating,
681   may have to do compression  (returns True if successful),
682   also moves existing vector */
683   bool getRowSpaceIterate(CoinSimplexInt iRow,
684     CoinSimplexInt extraNeeded);
685   /// Checks that row and column copies look OK
686   void checkConsistency();
687 //#define CHECK_LINKS
688 #ifdef CHECK_LINKS
689   void checkLinks(int x = 0);
690 #else
691 #define checkLinks(x)
692 #endif
693   /// Adds a link in chain of equal counts
addLink(CoinSimplexInt index,CoinSimplexInt count)694   inline void addLink(CoinSimplexInt index, CoinSimplexInt count)
695   {
696     CoinSimplexInt *COIN_RESTRICT nextCount = nextCountAddress_;
697     CoinSimplexInt *COIN_RESTRICT firstCount = this->firstCount();
698     CoinSimplexInt *COIN_RESTRICT lastCount = lastCountAddress_;
699     CoinSimplexInt next = firstCount[count];
700     firstCount[count] = index;
701     nextCount[index] = next;
702     lastCount[index] = count - numberRows_ - 2; // points to firstCount[count]
703     if (next >= 0)
704       lastCount[next] = index;
705   }
706   /// Deletes a link in chain of equal counts
deleteLink(CoinSimplexInt index)707   inline void deleteLink(CoinSimplexInt index)
708   {
709     CoinSimplexInt *COIN_RESTRICT nextCount = nextCountAddress_;
710     CoinSimplexInt *COIN_RESTRICT lastCount = lastCountAddress_;
711     CoinSimplexInt next = nextCount[index];
712     CoinSimplexInt last = lastCount[index];
713     assert(next != index);
714     assert(last != index);
715     if (next >= 0)
716       lastCount[next] = last;
717     if (last >= 0) {
718       nextCount[last] = next;
719     } else {
720       int count = last + numberRows_ + 2;
721       CoinSimplexInt *COIN_RESTRICT firstCount = this->firstCount();
722       firstCount[count] = next;
723     }
724   }
725   /// Modifies links in chain of equal counts
modifyLink(CoinSimplexInt index,CoinSimplexInt count)726   inline void modifyLink(CoinSimplexInt index, CoinSimplexInt count)
727   {
728     CoinSimplexInt *COIN_RESTRICT nextCount = nextCountAddress_;
729     CoinSimplexInt *COIN_RESTRICT lastCount = lastCountAddress_;
730     CoinSimplexInt *COIN_RESTRICT firstCount = this->firstCount();
731     CoinSimplexInt next2 = firstCount[count];
732     if (next2 == index)
733       return;
734     firstCount[count] = index;
735     CoinSimplexInt next = nextCount[index];
736     CoinSimplexInt last = lastCount[index];
737     assert(next != index);
738     assert(last != index);
739     nextCount[index] = next2;
740     lastCount[index] = count - numberRows_ - 2; // points to firstCount[count]
741     if (next >= 0)
742       lastCount[next] = last;
743     if (next2 >= 0)
744       lastCount[next2] = index;
745     if (last >= 0) {
746       nextCount[last] = next;
747     } else {
748       int count = last + numberRows_ + 2;
749       firstCount[count] = next;
750     }
751   }
752   /// Separate out links with same row/column count
753   void separateLinks();
754   void separateLinks(CoinSimplexInt, CoinSimplexInt);
755   /// Cleans up at end of factorization
756   void cleanup();
757   /// Set up addresses from arrays
758   void doAddresses();
759 
760   /// Updates part of column (FTRANL)
761   void updateColumnL(CoinIndexedVector *region
762 #if ABC_SMALL < 2
763     ,
764     CoinAbcStatistics &statistics
765 #endif
766 #if ABC_PARALLEL
767     ,
768     int whichSparse = 0
769 #endif
770     ) const;
771   /// Updates part of column (FTRANL) when densish
772   void updateColumnLDensish(CoinIndexedVector *region) const;
773   /// Updates part of column (FTRANL) when dense (i.e. do as inner products)
774   void updateColumnLDense(CoinIndexedVector *region) const;
775   /// Updates part of column (FTRANL) when sparse
776   void updateColumnLSparse(CoinIndexedVector *region
777 #if ABC_PARALLEL
778     ,
779     int whichSparse
780 #endif
781     ) const;
782 
783   /// Updates part of column (FTRANR) without FT update
784   void updateColumnR(CoinIndexedVector *region
785 #if ABC_SMALL < 2
786     ,
787     CoinAbcStatistics &statistics
788 #endif
789 #if ABC_PARALLEL
790     ,
791     int whichSparse = 0
792 #endif
793     ) const;
794   /// Store update after doing L and R - retuns false if no room
795   bool storeFT(
796 #if ABC_SMALL < 3
797     const
798 #endif
799     CoinIndexedVector *regionFT);
800   /// Updates part of column (FTRANU)
801   void updateColumnU(CoinIndexedVector *region
802 #if ABC_SMALL < 2
803     ,
804     CoinAbcStatistics &statistics
805 #endif
806 #if ABC_PARALLEL
807     ,
808     int whichSparse = 0
809 #endif
810     ) const;
811 
812   /// Updates part of column (FTRANU) when sparse
813   void updateColumnUSparse(CoinIndexedVector *regionSparse
814 #if ABC_PARALLEL
815     ,
816     int whichSparse
817 #endif
818     ) const;
819   /// Updates part of column (FTRANU)
820   void updateColumnUDensish(CoinIndexedVector *regionSparse) const;
821   /// Updates part of column (FTRANU) when dense (i.e. do as inner products)
822   void updateColumnUDense(CoinIndexedVector *regionSparse) const;
823   /// Updates part of 2 columns (FTRANU) real work
824   void updateTwoColumnsUDensish(
825     CoinSimplexInt &numberNonZero1,
826     CoinFactorizationDouble *COIN_RESTRICT region1,
827     CoinSimplexInt *COIN_RESTRICT index1,
828     CoinSimplexInt &numberNonZero2,
829     CoinFactorizationDouble *COIN_RESTRICT region2,
830     CoinSimplexInt *COIN_RESTRICT index2) const;
831   /// Updates part of column PFI (FTRAN) (after rest)
832   void updateColumnPFI(CoinIndexedVector *regionSparse) const;
833   /// Updates part of column transpose PFI (BTRAN) (before rest)
834   void updateColumnTransposePFI(CoinIndexedVector *region) const;
835   /** Updates part of column transpose (BTRANU),
836       assumes index is sorted i.e. region is correct */
837   void updateColumnTransposeU(CoinIndexedVector *region,
838     CoinSimplexInt smallestIndex
839 #if ABC_SMALL < 2
840     ,
841     CoinAbcStatistics &statistics
842 #endif
843 #if ABC_PARALLEL
844     ,
845     int whichCpu
846 #endif
847     ) const;
848   /** Updates part of column transpose (BTRANU) when densish,
849       assumes index is sorted i.e. region is correct */
850   void updateColumnTransposeUDensish(CoinIndexedVector *region,
851     CoinSimplexInt smallestIndex) const;
852   /** Updates part of column transpose (BTRANU) when sparse,
853       assumes index is sorted i.e. region is correct */
854   void updateColumnTransposeUSparse(CoinIndexedVector *region
855 #if ABC_PARALLEL
856     ,
857     int whichSparse
858 #endif
859     ) const;
860   /** Updates part of column transpose (BTRANU) by column
861       assumes index is sorted i.e. region is correct */
862   void updateColumnTransposeUByColumn(CoinIndexedVector *region,
863     CoinSimplexInt smallestIndex) const;
864 
865   /// Updates part of column transpose (BTRANR)
866   void updateColumnTransposeR(CoinIndexedVector *region
867 #if ABC_SMALL < 2
868     ,
869     CoinAbcStatistics &statistics
870 #endif
871     ) const;
872   /// Updates part of column transpose (BTRANR) when dense
873   void updateColumnTransposeRDensish(CoinIndexedVector *region) const;
874   /// Updates part of column transpose (BTRANR) when sparse
875   void updateColumnTransposeRSparse(CoinIndexedVector *region) const;
876 
877   /// Updates part of column transpose (BTRANL)
878   void updateColumnTransposeL(CoinIndexedVector *region
879 #if ABC_SMALL < 2
880     ,
881     CoinAbcStatistics &statistics
882 #endif
883 #if ABC_PARALLEL
884     ,
885     int whichSparse
886 #endif
887     ) const;
888   /// Updates part of column transpose (BTRANL) when densish by column
889   void updateColumnTransposeLDensish(CoinIndexedVector *region) const;
890   /// Updates part of column transpose (BTRANL) when densish by row
891   void updateColumnTransposeLByRow(CoinIndexedVector *region) const;
892   /// Updates part of column transpose (BTRANL) when sparse (by Row)
893   void updateColumnTransposeLSparse(CoinIndexedVector *region
894 #if ABC_PARALLEL
895     ,
896     int whichSparse
897 #endif
898     ) const;
899 public:
900   /** Replaces one Column to basis for PFI
901    returns 0=OK, 1=Probably OK, 2=singular, 3=no room.
902    In this case region is not empty - it is incoming variable (updated)
903   */
904   CoinSimplexInt replaceColumnPFI(CoinIndexedVector *regionSparse,
905     CoinSimplexInt pivotRow, CoinSimplexDouble alpha);
906 
907 protected:
908   /** Returns accuracy status of replaceColumn
909       returns 0=OK, 1=Probably OK, 2=singular */
910   CoinSimplexInt checkPivot(CoinSimplexDouble saveFromU, CoinSimplexDouble oldPivot) const;
911   /// 0 fine, -99 singular, 2 dense
912   int pivot(CoinSimplexInt pivotRow,
913     CoinSimplexInt pivotColumn,
914     CoinBigIndex pivotRowPosition,
915     CoinBigIndex pivotColumnPosition,
916     CoinFactorizationDouble *COIN_RESTRICT work,
917     CoinSimplexUnsignedInt *COIN_RESTRICT workArea2,
918     CoinSimplexInt increment2,
919     int *COIN_RESTRICT markRow);
920   int pivot(CoinSimplexInt &pivotRow,
921     CoinSimplexInt &pivotColumn,
922     CoinBigIndex pivotRowPosition,
923     CoinBigIndex pivotColumnPosition,
924     int *COIN_RESTRICT markRow);
925 #if ABC_SMALL < 2
926 #define CONVERTROW 2
927 #elif ABC_SMALL < 4
928 #else
929 #undef ABC_DENSE_CODE
930 #define ABC_DENSE_CODE 0
931 #endif
932 
933   //@}
934   ////////////////// data //////////////////
935 protected:
936   /**@name data */
937   //@{
938   CoinSimplexInt *pivotColumnAddress_;
939   CoinSimplexInt *permuteAddress_;
940   CoinFactorizationDouble *pivotRegionAddress_;
941   CoinFactorizationDouble *elementUAddress_;
942   CoinSimplexInt *indexRowUAddress_;
943   CoinSimplexInt *numberInColumnAddress_;
944   CoinSimplexInt *numberInColumnPlusAddress_;
945 #ifdef ABC_USE_FUNCTION_POINTERS
946   /// Array of function pointers
947   scatterStruct *scatterPointersUColumnAddress_;
948   CoinFactorizationDouble *elementUColumnPlusAddress_;
949 #endif
950   CoinBigIndex *startColumnUAddress_;
951 #if CONVERTROW
952   CoinBigIndex *convertRowToColumnUAddress_;
953 #if CONVERTROW > 1
954   CoinBigIndex *convertColumnToRowUAddress_;
955 #endif
956 #endif
957 #if ABC_SMALL < 2
958   CoinFactorizationDouble *elementRowUAddress_;
959 #endif
960   CoinBigIndex *startRowUAddress_;
961   CoinSimplexInt *numberInRowAddress_;
962   CoinSimplexInt *indexColumnUAddress_;
963   CoinSimplexInt *firstCountAddress_;
964   /// Next Row/Column with count
965   CoinSimplexInt *nextCountAddress_;
966   /// Previous Row/Column with count
967   CoinSimplexInt *lastCountAddress_;
968   CoinSimplexInt *nextColumnAddress_;
969   CoinSimplexInt *lastColumnAddress_;
970   CoinSimplexInt *nextRowAddress_;
971   CoinSimplexInt *lastRowAddress_;
972   CoinSimplexInt *saveColumnAddress_;
973   //CoinSimplexInt * saveColumnAddress2_;
974   CoinCheckZero *markRowAddress_;
975   CoinSimplexInt *listAddress_;
976   CoinFactorizationDouble *elementLAddress_;
977   CoinSimplexInt *indexRowLAddress_;
978   CoinBigIndex *startColumnLAddress_;
979 #if ABC_SMALL < 2
980   CoinBigIndex *startRowLAddress_;
981 #endif
982   CoinSimplexInt *pivotLinkedBackwardsAddress_;
983   CoinSimplexInt *pivotLinkedForwardsAddress_;
984   CoinSimplexInt *pivotLOrderAddress_;
985   CoinBigIndex *startColumnRAddress_;
986   /// Elements of R
987   CoinFactorizationDouble *elementRAddress_;
988   /// Row indices for R
989   CoinSimplexInt *indexRowRAddress_;
990   CoinSimplexInt *indexColumnLAddress_;
991   CoinFactorizationDouble *elementByRowLAddress_;
992 #if ABC_SMALL < 4
993   CoinFactorizationDouble *denseAreaAddress_;
994 #endif
995   CoinFactorizationDouble *workAreaAddress_;
996   CoinSimplexUnsignedInt *workArea2Address_;
997   mutable CoinSimplexInt *sparseAddress_;
998 #ifdef SMALL_PERMUTE
999   CoinSimplexInt *fromSmallToBigRow_;
1000   CoinSimplexInt *fromSmallToBigColumn_;
1001 #endif
1002   /// Number of Rows after iterating
1003   CoinSimplexInt numberRowsExtra_;
1004   /// Maximum number of Rows after iterating
1005   CoinSimplexInt maximumRowsExtra_;
1006   /// Size of small inverse
1007   CoinSimplexInt numberRowsSmall_;
1008   /// Number factorized in L
1009   CoinSimplexInt numberGoodL_;
1010   /// Number Rows left (numberRows-numberGood)
1011   CoinSimplexInt numberRowsLeft_;
1012   /// Number of elements in U (to go)
1013   ///       or while iterating total overall
1014   CoinBigIndex totalElements_;
1015   /// First place in funny copy zeroed out
1016   CoinBigIndex firstZeroed_;
1017 #if ABC_SMALL < 2
1018   /// Below this use sparse technology - if 0 then no L row copy
1019   CoinSimplexInt sparseThreshold_;
1020 #endif
1021   /// Number in R
1022   CoinSimplexInt numberR_;
1023   /// Length of R stuff
1024   CoinBigIndex lengthR_;
1025   /// length of area reserved for R
1026   CoinBigIndex lengthAreaR_;
1027   /// Number in L
1028   CoinBigIndex numberL_;
1029   /// Base of L
1030   CoinBigIndex baseL_;
1031   /// Length of L
1032   CoinBigIndex lengthL_;
1033   /// Length of area reserved for L
1034   CoinBigIndex lengthAreaL_;
1035   /// Number in U
1036   CoinSimplexInt numberU_;
1037   /// Maximum space used in U
1038   CoinBigIndex maximumU_;
1039   /// Length of U
1040   CoinBigIndex lengthU_;
1041   /// Length of area reserved for U
1042   CoinBigIndex lengthAreaU_;
1043   /// Last entry by column for U
1044   CoinBigIndex lastEntryByColumnU_;
1045 #ifdef ABC_USE_FUNCTION_POINTERS
1046   /// Last entry by column for U
1047   CoinBigIndex lastEntryByColumnUPlus_;
1048   /// Length of U
1049   CoinBigIndex lengthAreaUPlus_;
1050 #endif
1051   /// Last entry by row for U
1052   CoinBigIndex lastEntryByRowU_;
1053   /// Number of trials before rejection
1054   CoinSimplexInt numberTrials_;
1055 #if ABC_SMALL < 4
1056   /// Leading dimension for dense
1057   CoinSimplexInt leadingDimension_;
1058 #endif
1059 #if COIN_BIG_DOUBLE == 1
1060   /// Work arrays
1061   mutable CoinFactorizationLongDoubleArrayWithLength longArray_[FACTOR_CPU];
1062   /// Associated CoinIndexedVector
1063   mutable CoinIndexedVector *associatedVector_[FACTOR_CPU];
1064 #endif
1065   /// Pivot order for each Column
1066   CoinIntArrayWithLength pivotColumn_;
1067   /// Permutation vector for pivot row order
1068   CoinIntArrayWithLength permute_;
1069   /// Start of each Row as pointer
1070   CoinBigIndexArrayWithLength startRowU_;
1071   /// Number in each Row
1072   CoinIntArrayWithLength numberInRow_;
1073   /// Number in each Column
1074   CoinIntArrayWithLength numberInColumn_;
1075   /// Number in each Column including pivoted
1076   CoinIntArrayWithLength numberInColumnPlus_;
1077   /** First Row/Column with count of k,
1078       can tell which by offset - Rows then Columns */
1079   CoinIntArrayWithLength firstCount_;
1080   /// Next Column in memory order
1081   CoinIntArrayWithLength nextColumn_;
1082   /// Previous Column in memory order
1083   CoinIntArrayWithLength lastColumn_;
1084   /// Next Row in memory order
1085   CoinIntArrayWithLength nextRow_;
1086   /// Previous Row in memory order
1087   CoinIntArrayWithLength lastRow_;
1088   /// Columns left to do in a single pivot
1089   CoinIntArrayWithLength saveColumn_;
1090   /// Marks rows to be updated
1091   CoinIntArrayWithLength markRow_;
1092   /// Base address for U (may change)
1093   CoinIntArrayWithLength indexColumnU_;
1094   /// Inverses of pivot values
1095   CoinFactorizationDoubleArrayWithLength pivotRegion_;
1096   /// Elements of U
1097   CoinFactorizationDoubleArrayWithLength elementU_;
1098   /// Row indices of U
1099   CoinIntArrayWithLength indexRowU_;
1100   /// Start of each column in U
1101   CoinBigIndexArrayWithLength startColumnU_;
1102 #ifdef ABC_USE_FUNCTION_POINTERS
1103   /// Array of structs for U Column
1104   CoinArbitraryArrayWithLength scatterUColumn_;
1105 #endif
1106 #if CONVERTROW
1107   /// Converts rows to columns in U
1108   CoinBigIndexArrayWithLength convertRowToColumnU_;
1109 #if CONVERTROW > 1
1110   /// Converts columns to rows in U
1111   CoinBigIndexArrayWithLength convertColumnToRowU_;
1112 #endif
1113 #endif
1114 #if ABC_SMALL < 2
1115   /// Elements of U by row
1116   CoinFactorizationDoubleArrayWithLength elementRowU_;
1117 #endif
1118   /// Elements of L
1119   CoinFactorizationDoubleArrayWithLength elementL_;
1120   /// Row indices of L
1121   CoinIntArrayWithLength indexRowL_;
1122   /// Start of each column in L
1123   CoinBigIndexArrayWithLength startColumnL_;
1124 #if ABC_SMALL < 4
1125   /// Dense area
1126   CoinFactorizationDoubleArrayWithLength denseArea_;
1127 #endif
1128   /// First work area
1129   CoinFactorizationDoubleArrayWithLength workArea_;
1130   /// Second work area
1131   CoinUnsignedIntArrayWithLength workArea2_;
1132 #if ABC_SMALL < 2
1133   /// Start of each row in L
1134   CoinBigIndexArrayWithLength startRowL_;
1135   /// Index of column in row for L
1136   CoinIntArrayWithLength indexColumnL_;
1137   /// Elements in L (row copy)
1138   CoinFactorizationDoubleArrayWithLength elementByRowL_;
1139   /// Sparse regions
1140   mutable CoinIntArrayWithLength sparse_;
1141 #endif
1142   /// Detail in messages
1143   CoinSimplexInt messageLevel_;
1144   /// Number of compressions done
1145   CoinBigIndex numberCompressions_;
1146   // last slack pivot row
1147   CoinSimplexInt lastSlack_;
1148 #if ABC_SMALL < 2
1149   /// To decide how to solve
1150   mutable double ftranCountInput_;
1151   mutable double ftranCountAfterL_;
1152   mutable double ftranCountAfterR_;
1153   mutable double ftranCountAfterU_;
1154   double ftranAverageAfterL_;
1155   double ftranAverageAfterR_;
1156   double ftranAverageAfterU_;
1157 #if FACTORIZATION_STATISTICS
1158   double ftranTwiddleFactor1_;
1159   double ftranTwiddleFactor2_;
1160 #endif
1161   mutable CoinSimplexInt numberFtranCounts_;
1162 #endif
1163   /// Maximum rows (ever) (here to use double alignment)
1164   CoinSimplexInt maximumRows_;
1165 #if ABC_SMALL < 2
1166   mutable double ftranFTCountInput_;
1167   mutable double ftranFTCountAfterL_;
1168   mutable double ftranFTCountAfterR_;
1169   mutable double ftranFTCountAfterU_;
1170   double ftranFTAverageAfterL_;
1171   double ftranFTAverageAfterR_;
1172   double ftranFTAverageAfterU_;
1173 #if FACTORIZATION_STATISTICS
1174   double ftranFTTwiddleFactor1_;
1175   double ftranFTTwiddleFactor2_;
1176 #endif
1177   mutable CoinSimplexInt numberFtranFTCounts_;
1178 #endif
1179 #if ABC_SMALL < 4
1180   /// Dense threshold (here to use double alignment)
1181   CoinSimplexInt denseThreshold_;
1182 #endif
1183 #if ABC_SMALL < 2
1184   mutable double btranCountInput_;
1185   mutable double btranCountAfterU_;
1186   mutable double btranCountAfterR_;
1187   mutable double btranCountAfterL_;
1188   double btranAverageAfterU_;
1189   double btranAverageAfterR_;
1190   double btranAverageAfterL_;
1191 #if FACTORIZATION_STATISTICS
1192   double btranTwiddleFactor1_;
1193   double btranTwiddleFactor2_;
1194 #endif
1195   mutable CoinSimplexInt numberBtranCounts_;
1196 #endif
1197   /// Maximum maximum pivots
1198   CoinSimplexInt maximumMaximumPivots_;
1199 #if ABC_SMALL < 2
1200   /// To decide how to solve
1201   mutable double ftranFullCountInput_;
1202   mutable double ftranFullCountAfterL_;
1203   mutable double ftranFullCountAfterR_;
1204   mutable double ftranFullCountAfterU_;
1205   double ftranFullAverageAfterL_;
1206   double ftranFullAverageAfterR_;
1207   double ftranFullAverageAfterU_;
1208 #if FACTORIZATION_STATISTICS
1209   double ftranFullTwiddleFactor1_;
1210   double ftranFullTwiddleFactor2_;
1211 #endif
1212   mutable CoinSimplexInt numberFtranFullCounts_;
1213 #endif
1214   /// Rows first time nonzero
1215   CoinSimplexInt initialNumberRows_;
1216 #if ABC_SMALL < 2
1217   /// To decide how to solve
1218   mutable double btranFullCountInput_;
1219   mutable double btranFullCountAfterL_;
1220   mutable double btranFullCountAfterR_;
1221   mutable double btranFullCountAfterU_;
1222   double btranFullAverageAfterL_;
1223   double btranFullAverageAfterR_;
1224   double btranFullAverageAfterU_;
1225 #if FACTORIZATION_STATISTICS
1226   double btranFullTwiddleFactor1_;
1227   double btranFullTwiddleFactor2_;
1228 #endif
1229   mutable CoinSimplexInt numberBtranFullCounts_;
1230 #endif
1231   /** State of saved version and what can be done
1232       0 - nothing saved
1233       1 - saved and can go back to previous save by unwinding
1234       2 - saved - getting on for a full copy
1235       higher bits - see ABC_FAC....
1236   */
1237   CoinSimplexInt state_;
1238   /// Size in bytes of a sparseArray
1239   CoinBigIndex sizeSparseArray_;
1240 
1241 public:
1242 #if ABC_SMALL < 2
1243 #if ABC_SMALL >= 0
gotLCopy() const1244   inline bool gotLCopy() const
1245   {
1246     return ((state_ & ABC_FAC_GOT_LCOPY) != 0);
1247   }
setNoGotLCopy()1248   inline void setNoGotLCopy() { state_ &= ~ABC_FAC_GOT_LCOPY; }
setYesGotLCopy()1249   inline void setYesGotLCopy() { state_ |= ABC_FAC_GOT_LCOPY; }
gotRCopy() const1250   inline bool gotRCopy() const { return ((state_ & ABC_FAC_GOT_RCOPY) != 0); }
setNoGotRCopy()1251   inline void setNoGotRCopy() { state_ &= ~ABC_FAC_GOT_RCOPY; }
setYesGotRCopy()1252   inline void setYesGotRCopy() { state_ |= ABC_FAC_GOT_RCOPY; }
gotUCopy() const1253   inline bool gotUCopy() const { return ((state_ & ABC_FAC_GOT_UCOPY) != 0); }
setNoGotUCopy()1254   inline void setNoGotUCopy() { state_ &= ~ABC_FAC_GOT_UCOPY; }
setYesGotUCopy()1255   inline void setYesGotUCopy() { state_ |= ABC_FAC_GOT_UCOPY; }
gotSparse() const1256   inline bool gotSparse() const { return ((state_ & ABC_FAC_GOT_SPARSE) != 0); }
setNoGotSparse()1257   inline void setNoGotSparse() { state_ &= ~ABC_FAC_GOT_SPARSE; }
setYesGotSparse()1258   inline void setYesGotSparse() { state_ |= ABC_FAC_GOT_SPARSE; }
1259 #else
1260   // force use of copies
1261   inline bool gotLCopy() const { return true; }
1262   inline void setNoGotLCopy() {}
1263   inline void setYesGotLCopy() {}
1264   inline bool gotRCopy() const { return true; }
1265   inline void setNoGotRCopy() {}
1266   inline void setYesGotRCopy() {}
1267   inline bool gotUCopy() const { return true; }
1268   inline void setNoGotUCopy() {}
1269   inline void setYesGotUCopy() {}
1270   inline bool gotSparse() const { return true; }
1271   inline void setNoGotSparse() {}
1272   inline void setYesGotSparse() {}
1273 #endif
1274 #else
1275   // force no use of copies
1276   inline bool gotLCopy() const { return false; }
1277   inline void setNoGotLCopy() {}
1278   inline void setYesGotLCopy() {}
1279   inline bool gotRCopy() const { return false; }
1280   inline void setNoGotRCopy() {}
1281   inline void setYesGotRCopy() {}
1282   inline bool gotUCopy() const { return false; }
1283   inline void setNoGotUCopy() {}
1284   inline void setYesGotUCopy() {}
1285   inline bool gotSparse() const { return false; }
1286   inline void setNoGotSparse() {}
1287   inline void setYesGotSparse() {}
1288 #endif
1289   /** Array persistence flag
1290       If 0 then as now (delete/new)
1291       1 then only do arrays if bigger needed
1292       2 as 1 but give a bit extra if bigger needed
1293   */
1294   //CoinSimplexInt persistenceFlag_;
1295   //@}
1296 };
1297 
1298 /* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2
1299 */
1300