#ifdef ABC_JUST_ONE_FACTORIZATION
#include "CoinAbcCommonFactorization.hpp"
#define CoinAbcTypeFactorization CoinAbcBaseFactorization
#define ABC_SMALL -1
#include "CoinAbcBaseFactorization.hpp"
#endif
#ifdef CoinAbcTypeFactorization
#include "CoinIndexedVector.hpp"
#include "CoinHelperFunctions.hpp"
#include "CoinAbcHelperFunctions.hpp"
#include "CoinPackedMatrix.hpp"
#include "CoinFinite.hpp"
#define _mm256_broadcast_sd(x) static_cast< __m256d >(__builtin_ia32_vbroadcastsd256(x))
#define _mm256_load_pd(x) *(__m256d *)(x)
#define _mm256_store_pd (s, x) * ((__m256d *)s) = x

CoinAbcTypeFactorization::CoinAbcTypeFactorization()
  : CoinAbcAnyFactorization()
{
  gutsOfInitialize(7);
}

CoinAbcTypeFactorization::CoinAbcTypeFactorization(const CoinAbcTypeFactorization &other)
  : CoinAbcAnyFactorization(other)
{
  gutsOfInitialize(3);
  gutsOfCopy(other);
}

CoinAbcAnyFactorization *
CoinAbcTypeFactorization::clone() const
{
  return new CoinAbcTypeFactorization(*this);
}

CoinAbcTypeFactorization::CoinAbcTypeFactorization(const CoinFactorization & )
  : CoinAbcAnyFactorization()
{
  gutsOfInitialize(3);

  abort();
}

void CoinAbcTypeFactorization::gutsOfDestructor(CoinSimplexInt)
{
  numberCompressions_ = 0;
  numberRows_ = 0;
  numberRowsExtra_ = 0;
  maximumRowsExtra_ = 0;
  numberGoodU_ = 0;
  numberGoodL_ = 0;
  totalElements_ = 0;
  factorElements_ = 0;
  status_ = -1;
  numberSlacks_ = 0;
  lastSlack_ = 0;
  numberU_ = 0;
  maximumU_ = 0;
  lengthU_ = 0;
  lastEntryByColumnU_ = 0;
  lastEntryByRowU_ = 0;
  lengthAreaU_ = 0;
  numberL_ = 0;
  baseL_ = 0;
  lengthL_ = 0;
  lengthAreaL_ = 0;
  numberR_ = 0;
  lengthR_ = 0;
  lengthAreaR_ = 0;
#if ABC_SMALL < 4
  numberDense_ = 0;
#endif
}
#if FACTORIZATION_STATISTICS
extern double denseThresholdX;
#endif

void CoinAbcTypeFactorization::gutsOfInitialize(CoinSimplexInt type)
{
  if ((type & 2) != 0) {
    numberCompressions_ = 0;
    numberRows_ = 0;
    numberRowsExtra_ = 0;
    maximumRowsExtra_ = 0;
    numberGoodU_ = 0;
    numberGoodL_ = 0;
    totalElements_ = 0;
    factorElements_ = 0;
    status_ = -1;
    numberPivots_ = 0;
    numberSlacks_ = 0;
    lastSlack_ = 0;
    numberU_ = 0;
    maximumU_ = 0;
    lengthU_ = 0;
    lastEntryByColumnU_ = 0;
    lastEntryByRowU_ = 0;
    lengthAreaU_ = 0;
#ifdef ABC_USE_FUNCTION_POINTERS
    lengthAreaUPlus_ = 0;
#endif
    numberL_ = 0;
    baseL_ = 0;
    lengthL_ = 0;
    lengthAreaL_ = 0;
    numberR_ = 0;
    lengthR_ = 0;
    lengthAreaR_ = 0;
    elementRAddress_ = NULL;
    indexRowRAddress_ = NULL;
#if ABC_SMALL < 2

    sparseThreshold_ = 0;
#endif
    state_ = 0;

    maximumRows_ = 0;

    initialNumberRows_ = 0;

    maximumMaximumPivots_ = 0;
#if ABC_SMALL < 4
    numberDense_ = 0;
#endif
  }

  if ((type & 1) != 0) {
    areaFactor_ = 0.0;
    pivotTolerance_ = 1.0e-1;
    numberDense_ = 0;
#ifndef USE_FIXED_ZERO_TOLERANCE
    zeroTolerance_ = 1.0e-13;
#else
    zeroTolerance_ = pow(0.5, 43);
#endif
    messageLevel_ = 0;
    maximumPivots_ = 200;
    maximumMaximumPivots_ = 200;
    numberTrials_ = 4;
    relaxCheck_ = 1.0;
#if ABC_SMALL < 4
#if ABC_DENSE_CODE > 0

    denseThreshold_ = 71;
#else
    denseThreshold_ = -16;
#endif
#if FACTORIZATION_STATISTICS
    denseThreshold_ = denseThresholdX;
#endif

#endif
  }
#if ABC_SMALL < 4

#endif
  if ((type & 4) != 0) {
#if COIN_BIG_DOUBLE == 1
    for (int i = 0; i < FACTOR_CPU; i++) {
      longArray_[i].switchOn(4);
      associatedVector_[i] = NULL;
    }
#endif
    pivotColumn_.switchOn();
    permute_.switchOn();
    startRowU_.switchOn();
    numberInRow_.switchOn();
    numberInColumn_.switchOn();
    numberInColumnPlus_.switchOn();
#ifdef ABC_USE_FUNCTION_POINTERS
    scatterUColumn_.switchOn();
#endif
    firstCount_.switchOn();
    nextColumn_.switchOn();
    lastColumn_.switchOn();
    nextRow_.switchOn();
    lastRow_.switchOn();
    saveColumn_.switchOn();
    markRow_.switchOn();
    indexColumnU_.switchOn();
    pivotRegion_.switchOn();
    elementU_.switchOn();
    indexRowU_.switchOn();
    startColumnU_.switchOn();
#if CONVERTROW
    convertRowToColumnU_.switchOn();
#if CONVERTROW > 1
    convertColumnToRowU_.switchOn();
#endif
#endif
#if ABC_SMALL < 2
    elementRowU_.switchOn();
#endif
    elementL_.switchOn();
    indexRowL_.switchOn();
    startColumnL_.switchOn();
#if ABC_SMALL < 4
    denseArea_.switchOn(7);
#endif
    workArea_.switchOn();
    workArea2_.switchOn();
#if ABC_SMALL < 2
    startRowL_.switchOn();
    indexColumnL_.switchOn();
    elementByRowL_.switchOn();
    sparse_.switchOn();

    ftranCountInput_ = 0.0;
    ftranCountAfterL_ = 0.0;
    ftranCountAfterR_ = 0.0;
    ftranCountAfterU_ = 0.0;
    ftranFTCountInput_ = 0.0;
    ftranFTCountAfterL_ = 0.0;
    ftranFTCountAfterR_ = 0.0;
    ftranFTCountAfterU_ = 0.0;
    btranCountInput_ = 0.0;
    btranCountAfterU_ = 0.0;
    btranCountAfterR_ = 0.0;
    btranCountAfterL_ = 0.0;
    ftranFullCountInput_ = 0.0;
    ftranFullCountAfterL_ = 0.0;
    ftranFullCountAfterR_ = 0.0;
    ftranFullCountAfterU_ = 0.0;
    btranFullCountInput_ = 0.0;
    btranFullCountAfterL_ = 0.0;
    btranFullCountAfterR_ = 0.0;
    btranFullCountAfterU_ = 0.0;
#if FACTORIZATION_STATISTICS
    ftranTwiddleFactor1_ = 1.0;
    ftranFTTwiddleFactor1_ = 1.0;
    btranTwiddleFactor1_ = 1.0;
    ftranFullTwiddleFactor1_ = 1.0;
    btranFullTwiddleFactor1_ = 1.0;
    ftranTwiddleFactor2_ = 1.0;
    ftranFTTwiddleFactor2_ = 1.0;
    btranTwiddleFactor2_ = 1.0;
    ftranFullTwiddleFactor2_ = 1.0;
    btranFullTwiddleFactor2_ = 1.0;
#endif

    numberFtranCounts_ = 0;
    numberFtranFTCounts_ = 0;
    numberBtranCounts_ = 0;
    numberFtranFullCounts_ = 0;
    numberFtranFullCounts_ = 0;

    ftranAverageAfterL_ = INITIAL_AVERAGE;
    ftranAverageAfterR_ = INITIAL_AVERAGE;
    ftranAverageAfterU_ = INITIAL_AVERAGE;
    ftranFTAverageAfterL_ = INITIAL_AVERAGE;
    ftranFTAverageAfterR_ = INITIAL_AVERAGE;
    ftranFTAverageAfterU_ = INITIAL_AVERAGE;
    btranAverageAfterU_ = INITIAL_AVERAGE;
    btranAverageAfterR_ = INITIAL_AVERAGE;
    btranAverageAfterL_ = INITIAL_AVERAGE;
    ftranFullAverageAfterL_ = INITIAL_AVERAGE;
    ftranFullAverageAfterR_ = INITIAL_AVERAGE;
    ftranFullAverageAfterU_ = INITIAL_AVERAGE;
    btranFullAverageAfterL_ = INITIAL_AVERAGE;
    btranFullAverageAfterR_ = INITIAL_AVERAGE;
    btranFullAverageAfterU_ = INITIAL_AVERAGE;
#endif
  }
}

CoinAbcTypeFactorization::~CoinAbcTypeFactorization()
{
  gutsOfDestructor();
}

CoinAbcTypeFactorization &CoinAbcTypeFactorization::operator=(const CoinAbcTypeFactorization &other)
{
  if (this != &other) {
    gutsOfDestructor();
    CoinAbcAnyFactorization::operator=(other);
    gutsOfInitialize(3);
    gutsOfCopy(other);
  }
  return *this;
}
void CoinAbcTypeFactorization::gutsOfCopy(const CoinAbcTypeFactorization &other)
{
#ifdef ABC_USE_FUNCTION_POINTERS
  elementU_.allocate(other.elementU_, other.lengthAreaUPlus_ * CoinSizeofAsInt(CoinFactorizationDouble));
#else
  elementU_.allocate(other.elementU_, other.lengthAreaU_ * CoinSizeofAsInt(CoinFactorizationDouble));
#endif
  indexRowU_.allocate(other.indexRowU_, (other.lengthAreaU_ + 1) * CoinSizeofAsInt(CoinSimplexInt));
  elementL_.allocate(other.elementL_, other.lengthAreaL_ * CoinSizeofAsInt(CoinFactorizationDouble));
  indexRowL_.allocate(other.indexRowL_, other.lengthAreaL_ * CoinSizeofAsInt(CoinSimplexInt));
  startColumnL_.allocate(other.startColumnL_, (other.numberRows_ + 1) * CoinSizeofAsInt(CoinBigIndex));
  pivotRegion_.allocate(other.pivotRegion_, (other.numberRows_ + 2) * CoinSizeofAsInt(CoinFactorizationDouble));
#ifndef ABC_ORDERED_FACTORIZATION
  permute_.allocate(other.permute_, (other.maximumRowsExtra_ + 1) * CoinSizeofAsInt(CoinSimplexInt));
#else

  permute_.allocate(other.permute_, (other.maximumRowsExtra_ + 2 * numberRows_ + 1) * CoinSizeofAsInt(CoinSimplexInt));
#endif
  firstCount_.allocate(other.firstCount_,
    (CoinMax(5 * numberRows_, 4 * numberRows_ + 2 * maximumPivots_ + 4) + 2)
      * CoinSizeofAsInt(CoinSimplexInt));
  nextCountAddress_ = nextCount();
  lastCountAddress_ = lastCount();
  startColumnU_.allocate(other.startColumnU_, (other.numberRows_ + 1) * CoinSizeofAsInt(CoinBigIndex));
  numberInColumn_.allocate(other.numberInColumn_, (other.numberRows_ + 1) * CoinSizeofAsInt(CoinSimplexInt));
#if COIN_BIG_DOUBLE == 1
  for (int i = 0; i < FACTOR_CPU; i++)
    longArray_[i].allocate(other.longArray_[i], (other.maximumRowsExtra_ + 1) * CoinSizeofAsInt(long double));
#endif
  pivotColumn_.allocate(other.pivotColumn_, (other.maximumRowsExtra_ + 1) * CoinSizeofAsInt(CoinSimplexInt));
  nextColumn_.allocate(other.nextColumn_, (other.maximumRowsExtra_ + 1) * CoinSizeofAsInt(CoinSimplexInt));
  lastColumn_.allocate(other.lastColumn_, (other.maximumRowsExtra_ + 1) * CoinSizeofAsInt(CoinSimplexInt));
  nextRow_.allocate(other.nextRow_, (other.numberRows_ + 1) * CoinSizeofAsInt(CoinSimplexInt));
  lastRow_.allocate(other.lastRow_, (other.numberRows_ + 1) * CoinSizeofAsInt(CoinSimplexInt));
  indexColumnU_.allocate(other.indexColumnU_, (other.lengthAreaU_ + 1) * CoinSizeofAsInt(CoinSimplexInt));
#if CONVERTROW
  convertRowToColumnU_.allocate(other.convertRowToColumnU_, other.lengthAreaU_ * CoinSizeofAsInt(CoinBigIndex));
  const CoinBigIndex *convertUOther = other.convertRowToColumnUAddress_;
#if CONVERTROW > 1
  convertColumnToRowU_.allocate(other.convertColumnToRowU_, other.lengthAreaU_ * CoinSizeofAsInt(CoinBigIndex));
#if CONVERTROW > 2
  const CoinBigIndex *convertUOther2 = other.convertColumnToRowUAddress_;
#endif
#endif
#endif
#if ABC_SMALL < 2
  const CoinFactorizationDouble *elementRowUOther = other.elementRowUAddress_;
#if COIN_ONE_ETA_COPY
  if (elementRowUOther) {
#endif
#ifdef ABC_USE_FUNCTION_POINTERS
    elementRowU_.allocate(other.elementRowU_, other.lengthAreaUPlus_ * CoinSizeofAsInt(CoinFactorizationDouble));
#else
  elementRowU_.allocate(other.elementRowU_, other.lengthAreaU_ * CoinSizeofAsInt(CoinFactorizationDouble));
#endif
    startRowU_.allocate(other.startRowU_, (other.numberRows_ + 1) * CoinSizeofAsInt(CoinBigIndex));
    numberInRow_.allocate(other.numberInRow_, (other.numberRows_ + 1) * CoinSizeofAsInt(CoinSimplexInt));
#if COIN_ONE_ETA_COPY
  }
#endif
  if (other.sparseThreshold_) {
    elementByRowL_.allocate(other.elementByRowL_, other.lengthAreaL_);
    indexColumnL_.allocate(other.indexColumnL_, other.lengthAreaL_);
    startRowL_.allocate(other.startRowL_, other.numberRows_ + 1);
  }
#endif
  numberTrials_ = other.numberTrials_;
  relaxCheck_ = other.relaxCheck_;
  numberSlacks_ = other.numberSlacks_;
  lastSlack_ = other.lastSlack_;
  numberU_ = other.numberU_;
  maximumU_ = other.maximumU_;
  lengthU_ = other.lengthU_;
  lastEntryByColumnU_ = other.lastEntryByColumnU_;
  lastEntryByRowU_ = other.lastEntryByRowU_;
  lengthAreaU_ = other.lengthAreaU_;
#ifdef ABC_USE_FUNCTION_POINTERS
  lengthAreaUPlus_ = other.lengthAreaUPlus_;
#endif
  numberL_ = other.numberL_;
  baseL_ = other.baseL_;
  lengthL_ = other.lengthL_;
  lengthAreaL_ = other.lengthAreaL_;
  numberR_ = other.numberR_;
  lengthR_ = other.lengthR_;
  lengthAreaR_ = other.lengthAreaR_;
  pivotTolerance_ = other.pivotTolerance_;
  zeroTolerance_ = other.zeroTolerance_;
  areaFactor_ = other.areaFactor_;
  numberRows_ = other.numberRows_;
  numberRowsExtra_ = other.numberRowsExtra_;
  maximumRowsExtra_ = other.maximumRowsExtra_;
  maximumPivots_ = other.maximumPivots_;
  numberGoodU_ = other.numberGoodU_;
  numberGoodL_ = other.numberGoodL_;
  numberPivots_ = other.numberPivots_;
  messageLevel_ = other.messageLevel_;
  totalElements_ = other.totalElements_;
  factorElements_ = other.factorElements_;
  status_ = other.status_;
#if ABC_SMALL < 2

  ftranCountInput_ = other.ftranCountInput_;
  ftranCountAfterL_ = other.ftranCountAfterL_;
  ftranCountAfterR_ = other.ftranCountAfterR_;
  ftranCountAfterU_ = other.ftranCountAfterU_;
  ftranFTCountInput_ = other.ftranFTCountInput_;
  ftranFTCountAfterL_ = other.ftranFTCountAfterL_;
  ftranFTCountAfterR_ = other.ftranFTCountAfterR_;
  ftranFTCountAfterU_ = other.ftranFTCountAfterU_;
  btranCountInput_ = other.btranCountInput_;
  btranCountAfterU_ = other.btranCountAfterU_;
  btranCountAfterR_ = other.btranCountAfterR_;
  btranCountAfterL_ = other.btranCountAfterL_;
  ftranFullCountInput_ = other.ftranFullCountInput_;
  ftranFullCountAfterL_ = other.ftranFullCountAfterL_;
  ftranFullCountAfterR_ = other.ftranFullCountAfterR_;
  ftranFullCountAfterU_ = other.ftranFullCountAfterU_;
  btranFullCountInput_ = other.btranFullCountInput_;
  btranFullCountAfterL_ = other.btranFullCountAfterL_;
  btranFullCountAfterR_ = other.btranFullCountAfterR_;
  btranFullCountAfterU_ = other.btranFullCountAfterU_;
  numberFtranCounts_ = other.numberFtranCounts_;
  numberFtranFTCounts_ = other.numberFtranFTCounts_;
  numberBtranCounts_ = other.numberBtranCounts_;
  numberFtranFullCounts_ = other.numberFtranFullCounts_;
  numberFtranFullCounts_ = other.numberFtranFullCounts_;
  ftranAverageAfterL_ = other.ftranAverageAfterL_;
  ftranAverageAfterR_ = other.ftranAverageAfterR_;
  ftranAverageAfterU_ = other.ftranAverageAfterU_;
  ftranFTAverageAfterL_ = other.ftranFTAverageAfterL_;
  ftranFTAverageAfterR_ = other.ftranFTAverageAfterR_;
  ftranFTAverageAfterU_ = other.ftranFTAverageAfterU_;
  btranAverageAfterU_ = other.btranAverageAfterU_;
  btranAverageAfterR_ = other.btranAverageAfterR_;
  btranAverageAfterL_ = other.btranAverageAfterL_;
  ftranFullAverageAfterL_ = other.ftranFullAverageAfterL_;
  ftranFullAverageAfterR_ = other.ftranFullAverageAfterR_;
  ftranFullAverageAfterU_ = other.ftranFullAverageAfterU_;
  btranFullAverageAfterL_ = other.btranFullAverageAfterL_;
  btranFullAverageAfterR_ = other.btranFullAverageAfterR_;
  btranFullAverageAfterU_ = other.btranFullAverageAfterU_;
#if FACTORIZATION_STATISTICS
  ftranTwiddleFactor1_ = other.ftranTwiddleFactor1_;
  ftranFTTwiddleFactor1_ = other.ftranFTTwiddleFactor1_;
  btranTwiddleFactor1_ = other.btranTwiddleFactor1_;
  ftranFullTwiddleFactor1_ = other.ftranFullTwiddleFactor1_;
  btranFullTwiddleFactor1_ = other.btranFullTwiddleFactor1_;
  ftranTwiddleFactor2_ = other.ftranTwiddleFactor2_;
  ftranFTTwiddleFactor2_ = other.ftranFTTwiddleFactor2_;
  btranTwiddleFactor2_ = other.btranTwiddleFactor2_;
  ftranFullTwiddleFactor2_ = other.ftranFullTwiddleFactor2_;
  btranFullTwiddleFactor2_ = other.btranFullTwiddleFactor2_;
#endif
  sparseThreshold_ = other.sparseThreshold_;
#endif
  state_ = other.state_;

  maximumRows_ = other.maximumRows_;

  initialNumberRows_ = other.initialNumberRows_;

  maximumMaximumPivots_ = other.maximumMaximumPivots_;
  CoinBigIndex space = lengthAreaL_ - lengthL_;

#if ABC_SMALL < 4
  numberDense_ = other.numberDense_;
  denseThreshold_ = other.denseThreshold_;
#endif
  lengthAreaR_ = space;
  elementRAddress_ = elementL_.array() + lengthL_;
  indexRowRAddress_ = indexRowL_.array() + lengthL_;
  workArea_ = other.workArea_;
  workArea2_ = other.workArea2_;

  if (numberRowsExtra_) {
    if (startRowU_.array()) {
      CoinAbcMemcpy(startRowU_.array(), other.startRowU_.array(), numberRows_ + 1);
      CoinAbcMemcpy(numberInRow_.array(), other.numberInRow_.array(), numberRows_ + 1);

    }
    CoinAbcMemcpy(pivotRegion_.array(), other.pivotRegion_.array(), numberRows_ + 2);
#ifndef ABC_ORDERED_FACTORIZATION
    CoinAbcMemcpy(permute_.array(), other.permute_.array(), numberRowsExtra_ + 1);
#else

    CoinAbcMemcpy(permute_.array(), other.permute_.array(), maximumRowsExtra_ + 2 * numberRows_ + 1);
#endif
    CoinAbcMemcpy(firstCount_.array(), other.firstCount_.array(), CoinMax(5 * numberRows_, 4 * numberRows_ + 2 * maximumPivots_ + 4) + 2);
    CoinAbcMemcpy(startColumnU_.array(), other.startColumnU_.array(), numberRows_ + 1);
    CoinAbcMemcpy(numberInColumn_.array(), other.numberInColumn_.array(), numberRows_ + 1);
    CoinAbcMemcpy(pivotColumn_.array(), other.pivotColumn_.array(), numberRowsExtra_ + 1);
    CoinAbcMemcpy(nextColumn_.array(), other.nextColumn_.array(), numberRowsExtra_ + 1);
    CoinAbcMemcpy(lastColumn_.array(), other.lastColumn_.array(), numberRowsExtra_ + 1);
    CoinAbcMemcpy(startColumnR(), other.startColumnR(), numberRowsExtra_ - numberRows_ + 1);

    nextColumn_.array()[maximumRowsExtra_] = other.nextColumn_.array()[maximumRowsExtra_];
    lastColumn_.array()[maximumRowsExtra_] = other.lastColumn_.array()[maximumRowsExtra_];
    CoinAbcMemcpy(nextRow_.array(), other.nextRow_.array(), numberRows_ + 1);
    CoinAbcMemcpy(lastRow_.array(), other.lastRow_.array(), numberRows_ + 1);
    nextRow_.array()[numberRows_] = other.nextRow_.array()[numberRows_];
    lastRow_.array()[numberRows_] = other.lastRow_.array()[numberRows_];
  }
  CoinAbcMemcpy(elementRAddress_, other.elementRAddress_, lengthR_);
  CoinAbcMemcpy(indexRowRAddress_, other.indexRowRAddress_, lengthR_);

  const CoinBigIndex *COIN_RESTRICT startColumnU = startColumnU_.array();
  const CoinSimplexInt *COIN_RESTRICT numberInColumn = numberInColumn_.array();
#ifndef NDEBUG
  CoinSimplexInt maxU = 0;
  for (CoinSimplexInt iRow = 0; iRow < numberRows_; iRow++) {
    CoinBigIndex start = startColumnU[iRow];
    CoinSimplexInt numberIn = numberInColumn[iRow];
    maxU = CoinMax(maxU, start + numberIn);
  }

#endif
  CoinAbcMemcpy(elementU_.array(), other.elementU_.array(), maximumU_);
#if ABC_SMALL < 2
#if COIN_ONE_ETA_COPY
  if (elementRowUOther) {
#endif
    const CoinSimplexInt *COIN_RESTRICT indexColumnUOther = other.indexColumnU_.array();
#if CONVERTROW
    CoinBigIndex *COIN_RESTRICT convertU = convertRowToColumnU_.array();
#if CONVERTROW > 2
    CoinBigIndex *COIN_RESTRICT convertU2 = convertColumnToRowU_.array();
#endif
#endif
    CoinFactorizationDouble *COIN_RESTRICT elementRowU = elementRowU_.array();
    CoinSimplexInt *COIN_RESTRICT indexColumnU = indexColumnU_.array();
    const CoinBigIndex *COIN_RESTRICT startRowU = startRowU_.array();
    const CoinSimplexInt *COIN_RESTRICT numberInRow = numberInRow_.array();
    for (CoinSimplexInt iRow = 0; iRow < numberRows_; iRow++) {

      CoinBigIndex start = startRowU[iRow];
      CoinSimplexInt numberIn = numberInRow[iRow];

      CoinAbcMemcpy(indexColumnU + start, indexColumnUOther + start, numberIn);
#if CONVERTROW
      CoinAbcMemcpy(convertU + start, convertUOther + start, numberIn);
#if CONVERTROW > 2
      CoinAbcMemcpy(convertU2 + start, convertUOther2 + start, numberIn);
#endif
#endif
      CoinAbcMemcpy(elementRowU + start, elementRowUOther + start, numberIn);
    }
#if COIN_ONE_ETA_COPY
  }
#endif
#endif
  const CoinSimplexInt *COIN_RESTRICT indexRowUOther = other.indexRowU_.array();
  CoinSimplexInt *COIN_RESTRICT indexRowU = indexRowU_.array();
  for (CoinSimplexInt iRow = 0; iRow < numberRows_; iRow++) {

    CoinBigIndex start = startColumnU[iRow];
    CoinSimplexInt numberIn = numberInColumn[iRow];
    if (numberIn > 0)
      CoinAbcMemcpy(indexRowU + start, indexRowUOther + start, numberIn);
  }

  if (numberRows_)
    CoinAbcMemcpy(startColumnL_.array(), other.startColumnL_.array(), numberRows_ + 1);
  CoinAbcMemcpy(elementL_.array(), other.elementL_.array(), lengthL_);
  CoinAbcMemcpy(indexRowL_.array(), other.indexRowL_.array(), lengthL_);
#if ABC_SMALL < 2
  if (other.sparseThreshold_) {
    goSparse();
  }
#endif
  doAddresses();
}

void CoinAbcTypeFactorization::getAreas(CoinSimplexInt numberOfRows,
  CoinSimplexInt ,
  CoinBigIndex maximumL,
  CoinBigIndex maximumU)
{
  gutsOfInitialize(2);

  numberRows_ = numberOfRows;
  numberRowsSmall_ = numberOfRows;
  maximumRows_ = CoinMax(maximumRows_, numberRows_);
  maximumRowsExtra_ = numberRows_ + maximumPivots_;
  numberRowsExtra_ = numberRows_;
  lengthAreaU_ = maximumU;
  lengthAreaL_ = maximumL;
  if (!areaFactor_) {
    areaFactor_ = 1.0;
  }
  if (areaFactor_ != 1.0) {
    if ((messageLevel_ & 16) != 0)
      printf("Increasing factorization areas by %g\n", areaFactor_);
    lengthAreaU_ = static_cast< CoinBigIndex >(areaFactor_ * lengthAreaU_);
    lengthAreaL_ = static_cast< CoinBigIndex >(areaFactor_ * lengthAreaL_);
  }
#ifdef ABC_USE_FUNCTION_POINTERS
  lengthAreaUPlus_ = (lengthAreaU_ * 3) / 2 + maximumRowsExtra_;
  elementU_.conditionalNew(lengthAreaUPlus_);
#else
  elementU_.conditionalNew(lengthAreaU_);
#endif
  indexRowU_.conditionalNew(lengthAreaU_ + 1);
  indexColumnU_.conditionalNew(lengthAreaU_ + 1);
  elementL_.conditionalNew(lengthAreaL_);
  indexRowL_.conditionalNew(lengthAreaL_);

  CoinBigIndex length;
  length = CoinMin(elementU_.getSize(), indexRowU_.getSize());
  if (length > lengthAreaU_) {
    lengthAreaU_ = length;
    assert(indexColumnU_.getSize() == indexRowU_.getSize());
  }
  length = CoinMin(elementL_.getSize(), indexRowL_.getSize());
  if (length > lengthAreaL_) {
    lengthAreaL_ = length;
  }
  startColumnL_.conditionalNew(numberRows_ + 1);
  startColumnL_.array()[0] = 0;
  startRowU_.conditionalNew(maximumRowsExtra_ + 1);

  startRowU_.array()[maximumRowsExtra_] = 0;
  lastEntryByRowU_ = 0;
  numberInRow_.conditionalNew(maximumRowsExtra_ + 1);
  markRow_.conditionalNew(numberRows_);
  nextRow_.conditionalNew(maximumRowsExtra_ + 1);
  lastRow_.conditionalNew(maximumRowsExtra_ + 1);
#ifndef ABC_ORDERED_FACTORIZATION
  permute_.conditionalNew(maximumRowsExtra_ + 1);
#else

  permute_.conditionalNew(maximumRowsExtra_ + 2 * numberRows_ + 1);
#endif
  permuteAddress_ = permute_.array();
  pivotRegion_.conditionalNew(maximumRows_ + 2);
  startColumnU_.conditionalNew(maximumRowsExtra_ + 1);
  numberInColumn_.conditionalNew(maximumRowsExtra_ + 1);
  numberInColumnPlus_.conditionalNew(maximumRowsExtra_ + 1);
#ifdef ABC_USE_FUNCTION_POINTERS
  scatterUColumn_.conditionalNew(sizeof(scatterStruct), maximumRowsExtra_ + 1);
  elementRowU_.conditionalNew(lengthAreaUPlus_);
  elementRowUAddress_ = elementRowU_.array();
  firstZeroed_ = 0;
#elif ABC_SMALL < 2
  elementRowU_.conditionalNew(lengthAreaU_);
  elementRowUAddress_ = elementRowU_.array();
#endif
#if COIN_BIG_DOUBLE == 1
  for (int i = 0; i < FACTOR_CPU; i++) {
    longArray_[i].conditionalNew(maximumRowsExtra_ + 1);
    longArray_[i].clear();
  }
#endif
  pivotColumn_.conditionalNew(maximumRowsExtra_ + 1);
  nextColumn_.conditionalNew(maximumRowsExtra_ + 1);
  lastColumn_.conditionalNew(maximumRowsExtra_ + 1);
  saveColumn_.conditionalNew( numberRows_);
  assert(sizeof(CoinSimplexInt) == sizeof(CoinBigIndex)); 
  firstCount_.conditionalNew(CoinMax(5 * numberRows_, 4 * numberRows_ + 2 * maximumPivots_ + 4) + 2);
#if CONVERTROW

  convertRowToColumnU_.conditionalNew(lengthAreaU_);
  convertRowToColumnUAddress_ = convertRowToColumnU_.array();
#if CONVERTROW > 1
  convertColumnToRowU_.conditionalNew(lengthAreaU_);
  convertColumnToRowUAddress_ = convertColumnToRowU_.array();
#endif
#endif
#ifdef SMALL_PERMUTE
  assert(sizeof(CoinFactorizationDouble) >= 2 * sizeof(int));
  denseArea_.conditionalNew(numberRows_ + maximumRowsExtra_ + 2);
  fromSmallToBigRow_ = reinterpret_cast< CoinSimplexInt * >(denseArea_.array());
  fromSmallToBigColumn_ = fromSmallToBigRow_ + numberRows_;
#endif
  doAddresses();
#if ABC_SMALL < 2

  sparseThreshold_ = 0;
#endif
}

#include "AbcSimplex.hpp"
#include "ClpMessage.hpp"

CoinSimplexInt
CoinAbcTypeFactorization::factor(AbcSimplex *model)
{
#if ABC_DENSE_CODE
  int saveDense = denseThreshold_;
  if ((solveMode_ & 1) == 0)
    denseThreshold_ = 0;
#endif

  status_ = factorSparse();
  switch (status_) {
  case 0: 
    totalElements_ = 0;
    if (numberGoodU_ < numberRows_)
      status_ = -1;
    break;
#if ABC_DENSE_CODE
#if ABC_SMALL < 4

  case 2:
    status_ = factorDense();
    if (!status_)
      break;
#endif
#endif
  default:

    if ((messageLevel_ & 4) != 0)
      std::cout << "Error " << status_ << std::endl;
    if (status_ == -99) {
      if (numberRows_ - numberGoodU_ < 1000) {
        areaFactor_ *= 1.5;
      } else {
        double denseArea = (numberRows_ - numberGoodU_) * (numberRows_ - numberGoodU_);
        if (denseArea > 1.5 * lengthAreaU_) {
          areaFactor_ *= CoinMin(2.5, denseArea / 1.5);
        } else {
          areaFactor_ *= 1.5;
        }
      }
      if (model->logLevel() > 1) {
        char line[100];
        sprintf(line, "need more memory lengthArea %d number %d done %d areaFactor %g",
          lengthAreaL_ + lengthAreaU_, lengthU_ + lengthL_, numberGoodU_, areaFactor_);
        model->messageHandler()->message(CLP_GENERAL2, *model->messagesPointer())
          << line << CoinMessageEol;
      }
    } else if (status_ == -97) {

      status_ = -99;
      char line[100];
      sprintf(line, "Bad pivot values - increasing pivot tolerance to %g",
        pivotTolerance_);
      model->messageHandler()->message(CLP_GENERAL2, *model->messagesPointer())
        << line << CoinMessageEol;
    }
    break;
  } 

  if (!status_) {
    if ((messageLevel_ & 16) && numberCompressions_)
      std::cout << "        Factorization did " << numberCompressions_
                << " compressions" << std::endl;
    if (numberCompressions_ > 10) {

      if (lengthAreaL_ + lengthAreaU_ < 10 * (lengthU_ + lengthL_)) {
        areaFactor_ *= 1.1;
        if (model->logLevel() > 1) {
          char line[100];
          sprintf(line, "%d factorization compressions, lengthArea %d number %d new areaFactor %g",
            numberCompressions_, lengthAreaL_ + lengthAreaU_, lengthU_ + lengthL_, areaFactor_);
          model->messageHandler()->message(CLP_GENERAL2, *model->messagesPointer())
            << line << CoinMessageEol;
        }
      }
    }
    numberCompressions_ = 0;
    cleanup();
  }
  numberPivots_ = 0;
#if ABC_DENSE_CODE
  denseThreshold_ = saveDense;
#endif
  return status_;
}
#define ALWAYS_GIVE_UP 0 
#ifdef ABC_USE_FUNCTION_POINTERS
#define DENSE_TRY
#ifdef DENSE_TRY
static void pivotStartup(int first, int last, int numberInPivotColumn, int lengthArea, int giveUp,
  CoinFactorizationDouble *COIN_RESTRICT eArea, const int *COIN_RESTRICT saveColumn,
  const int *COIN_RESTRICT startColumnU, int *COIN_RESTRICT tempColumnCount,
  const CoinFactorizationDouble *COIN_RESTRICT elementU,
  const int *COIN_RESTRICT numberInColumn,
  const int *COIN_RESTRICT indexRowU)
{
  if (last - first > giveUp && !ALWAYS_GIVE_UP) {
    int mid = (last + first) >> 1;
    cilk_spawn pivotStartup(first, mid, numberInPivotColumn, lengthArea, giveUp,
      eArea, saveColumn, startColumnU, tempColumnCount,
      elementU, numberInColumn, indexRowU);
    pivotStartup(mid, last, numberInPivotColumn, lengthArea, giveUp,
      eArea, saveColumn, startColumnU, tempColumnCount,
      elementU, numberInColumn, indexRowU);
    cilk_sync;
  } else {
    CoinFactorizationDouble *COIN_RESTRICT area = eArea + first * lengthArea;
    for (int jColumn = first; jColumn < last; jColumn++) {
      CoinSimplexInt iColumn = saveColumn[jColumn];
      CoinBigIndex startColumn = startColumnU[iColumn];
      int numberNow = tempColumnCount[jColumn];
      int start = startColumn + numberNow;
      int end = startColumn + numberInColumn[iColumn];
      CoinFactorizationDouble thisPivotValue = elementU[startColumn - 1];
      for (CoinBigIndex j = start; j < end; j++) {
        CoinFactorizationDouble value = elementU[j];
        int iPut = indexRowU[j];
        assert(iPut < lengthArea);
        area[iPut] = value;
      }
      area[numberInPivotColumn] = thisPivotValue;
      area += lengthArea;
    }
  }
}
static void pivotWhile(int first, int last, int numberInPivotColumn, int lengthArea, int giveUp,
  CoinFactorizationDouble *COIN_RESTRICT eArea, const CoinFactorizationDouble *COIN_RESTRICT multipliersL)
{
  if (last - first > giveUp && !ALWAYS_GIVE_UP) {
    int mid = (last + first) >> 1;
    cilk_spawn pivotWhile(first, mid, numberInPivotColumn, lengthArea, giveUp,
      eArea, multipliersL);
    pivotWhile(mid, last, numberInPivotColumn, lengthArea, giveUp,
      eArea, multipliersL);
    cilk_sync;
  } else {
    CoinFactorizationDouble *COIN_RESTRICT area = eArea + first * lengthArea;
    int nDo = last - first;
#if AVX2 == 0
    for (int jColumn = 0; jColumn < nDo; jColumn++) {
      CoinFactorizationDouble thisPivotValue = area[numberInPivotColumn];
      area[numberInPivotColumn] = 0.0;
      for (CoinSimplexInt j = 0; j < numberInPivotColumn; j++) {
        area[j] -= thisPivotValue * multipliersL[j];
      }
      area += lengthArea;
    }
#else
    int n = (numberInPivotColumn + 3) & (~3);

    CoinFactorizationDouble *multipliers = const_cast< CoinFactorizationDouble * >(multipliersL);
    for (int jColumn = 0; jColumn < nDo; jColumn++) {

      __m256d pivot = _mm256_broadcast_sd(area + numberInPivotColumn);
      area[numberInPivotColumn] = 0.0;
      for (CoinSimplexInt j = 0; j < n; j += 4) {
        __m256d a = _mm256_load_pd(area + j);
        __m256d m = _mm256_load_pd(multipliers + j);
        a -= pivot * m;
        *reinterpret_cast< __m256d * >(area + j) = a; 

      }
      area += lengthArea;
    }
#endif
  }
}
static void pivotSomeAfter(int first, int last, int numberInPivotColumn, int lengthArea, int giveUp,
  CoinFactorizationDouble *COIN_RESTRICT eArea, const int *COIN_RESTRICT saveColumn,
  const int *COIN_RESTRICT startColumnU, int *COIN_RESTRICT tempColumnCount,
  CoinFactorizationDouble *COIN_RESTRICT elementU, int *COIN_RESTRICT numberInColumn,
  int *COIN_RESTRICT indexRowU, unsigned int *aBits,
  const int *COIN_RESTRICT indexL,
  const CoinFactorizationDouble *COIN_RESTRICT multipliersL, double tolerance)
{
  if (last - first > giveUp && !ALWAYS_GIVE_UP) {
    int mid = (last + first) >> 1;
    cilk_spawn pivotSomeAfter(first, mid, numberInPivotColumn, lengthArea, giveUp,
      eArea, saveColumn, startColumnU, tempColumnCount,
      elementU, numberInColumn, indexRowU, aBits, indexL,
      multipliersL, tolerance);
    pivotSomeAfter(mid, last, numberInPivotColumn, lengthArea, giveUp,
      eArea, saveColumn, startColumnU, tempColumnCount,
      elementU, numberInColumn, indexRowU, aBits, indexL,
      multipliersL, tolerance);
    cilk_sync;
  } else {
    int intsPerColumn = (lengthArea + 31) >> 5;
    CoinFactorizationDouble *COIN_RESTRICT area = eArea + first * lengthArea;
    for (int jColumn = first; jColumn < last; jColumn++) {
      CoinSimplexInt iColumn = saveColumn[jColumn];
      CoinBigIndex startColumn = startColumnU[iColumn];
      int numberNow = tempColumnCount[jColumn];
      CoinFactorizationDouble thisPivotValue = area[numberInPivotColumn];
      area[numberInPivotColumn] = 0.0;
      int n = 0;
      int positionLargest = -1;
      double largest = numberNow ? fabs(elementU[startColumn]) : 0.0;
      unsigned int *aBitsThis = aBits + jColumn * intsPerColumn;
#if AVX2 == 0
      for (CoinSimplexInt j = 0; j < numberInPivotColumn; j++) {
        CoinFactorizationDouble value = area[j] - thisPivotValue * multipliersL[j];
        CoinSimplexDouble absValue = fabs(value);
        area[j] = 0.0;
        if (absValue > tolerance) {
          area[n] = value;
          if (absValue > largest) {
            largest = absValue;
            positionLargest = n;
          }
          n++;
        } else {

          int word = j >> 5;
          int unsetBit = j - (word << 5);
          aBitsThis[word] &= ~(1 << unsetBit);
        }
      }
#else

      CoinFactorizationDouble *multipliers = const_cast< CoinFactorizationDouble * >(multipliersL);
      int nDo = (numberInPivotColumn + 3) & (~3);

      __m256d pivot = _mm256_broadcast_sd(&thisPivotValue);
      for (CoinSimplexInt j = 0; j < nDo; j += 4) {
        __m256d a = _mm256_load_pd(area + j);
        __m256d m = _mm256_load_pd(multipliers + j);
        a -= pivot * m;
        *reinterpret_cast< __m256d * >(area + j) = a; 
      }
      for (CoinSimplexInt j = 0; j < numberInPivotColumn; j++) {
        CoinFactorizationDouble value = area[j];
        CoinSimplexDouble absValue = fabs(value);
        area[j] = 0.0;
        if (absValue > tolerance) {
          area[n] = value;
          if (absValue > largest) {
            largest = absValue;
            positionLargest = n;
          }
          n++;
        } else {

          int word = j >> 5;
          int unsetBit = j - (word << 5);
          aBitsThis[word] &= ~(1 << unsetBit);
        }
      }
#endif
      int put = startColumn;
      if (positionLargest >= 0)
        positionLargest += put + numberNow;
      put += numberNow;
      int iA = 0;
      for (int jj = 0; jj < numberInPivotColumn; jj += 32) {
        unsigned int aThis = *aBitsThis;
        aBitsThis++;
        for (int i = jj; i < CoinMin(jj + 32, numberInPivotColumn); i++) {
          if ((aThis & 1) != 0) {
            indexRowU[put] = indexL[i];
            elementU[put++] = area[iA];
            area[iA++] = 0.0;
          }
          aThis = aThis >> 1;
        }
      }
      int numberNeeded = put - startColumn;
      if (positionLargest >= 0) {

        CoinBigIndex start = startColumn;
        int firstIndex = indexRowU[start];
        CoinFactorizationDouble firstValue = elementU[start];
        indexRowU[start] = indexRowU[positionLargest];
        elementU[start] = elementU[positionLargest];
        indexRowU[positionLargest] = firstIndex;
        elementU[positionLargest] = firstValue;
      }
      tempColumnCount[jColumn] = numberNeeded - numberInColumn[iColumn];
      assert(numberNeeded >= 0);
      numberInColumn[iColumn] = numberNeeded;
      area += lengthArea;
    }
  }
}
#endif
static void pivotSome(int first, int last, int numberInPivotColumn, int lengthArea, int giveUp,
  CoinFactorizationDouble *COIN_RESTRICT eArea, const int *COIN_RESTRICT saveColumn,
  const int *COIN_RESTRICT startColumnU, int *COIN_RESTRICT tempColumnCount,
  CoinFactorizationDouble *COIN_RESTRICT elementU, int *COIN_RESTRICT numberInColumn,
  int *COIN_RESTRICT indexRowU, unsigned int *aBits,
  const int *COIN_RESTRICT indexL,
  const CoinFactorizationDouble *COIN_RESTRICT multipliersL, double tolerance)
{
  if (last - first > giveUp && !ALWAYS_GIVE_UP) {
    int mid = (last + first) >> 1;
    cilk_spawn pivotSome(first, mid, numberInPivotColumn, lengthArea, giveUp,
      eArea, saveColumn, startColumnU, tempColumnCount,
      elementU, numberInColumn, indexRowU, aBits, indexL,
      multipliersL, tolerance);
    pivotSome(mid, last, numberInPivotColumn, lengthArea, giveUp,
      eArea, saveColumn, startColumnU, tempColumnCount,
      elementU, numberInColumn, indexRowU, aBits, indexL,
      multipliersL, tolerance);
    cilk_sync;
  } else {
    int intsPerColumn = (lengthArea + 31) >> 5;
    CoinFactorizationDouble *COIN_RESTRICT area = eArea + first * lengthArea;
    for (int jColumn = first; jColumn < last; jColumn++) {
      CoinSimplexInt iColumn = saveColumn[jColumn];
      CoinBigIndex startColumn = startColumnU[iColumn];
      int numberNow = tempColumnCount[jColumn];
      CoinFactorizationDouble thisPivotValue = elementU[startColumn - 1];
      int start = startColumn + numberNow;
      int end = startColumn + numberInColumn[iColumn];
      for (CoinBigIndex j = start; j < end; j++) {
        CoinFactorizationDouble value = elementU[j];
        int iPut = indexRowU[j];
        assert(iPut < lengthArea);
        area[iPut] = value;
      }
      int n = 0;
      int positionLargest = -1;
      double largest = numberNow ? fabs(elementU[startColumn]) : 0.0;
      unsigned int *aBitsThis = aBits + jColumn * intsPerColumn;
#if AVX2 == 0
      for (CoinSimplexInt j = 0; j < numberInPivotColumn; j++) {
        CoinFactorizationDouble value = area[j] - thisPivotValue * multipliersL[j];
        CoinSimplexDouble absValue = fabs(value);
        area[j] = 0.0;
        if (absValue > tolerance) {
          area[n] = value;
          if (absValue > largest) {
            largest = absValue;
            positionLargest = n;
          }
          n++;
        } else {

          int word = j >> 5;
          int unsetBit = j - (word << 5);
          aBitsThis[word] &= ~(1 << unsetBit);
        }
      }
#else
      int nDo = (numberInPivotColumn + 3) & (~3);

      CoinFactorizationDouble *multipliers = const_cast< CoinFactorizationDouble * >(multipliersL);

      __m256d pivot = _mm256_broadcast_sd(&thisPivotValue);
      for (CoinSimplexInt j = 0; j < nDo; j += 4) {
        __m256d a = _mm256_load_pd(area + j);
        __m256d m = _mm256_load_pd(multipliers + j);
        a -= pivot * m;
        *reinterpret_cast< __m256d * >(area + j) = a; 
      }
      for (CoinSimplexInt j = 0; j < numberInPivotColumn; j++) {
        CoinFactorizationDouble value = area[j];
        CoinSimplexDouble absValue = fabs(value);
        area[j] = 0.0;
        if (absValue > tolerance) {
          area[n] = value;
          if (absValue > largest) {
            largest = absValue;
            positionLargest = n;
          }
          n++;
        } else {

          int word = j >> 5;
          int unsetBit = j - (word << 5);
          aBitsThis[word] &= ~(1 << unsetBit);
        }
      }
#endif
      int put = startColumn;
      if (positionLargest >= 0)
        positionLargest += put + numberNow;
      put += numberNow;
      int iA = 0;
      for (int jj = 0; jj < numberInPivotColumn; jj += 32) {
        unsigned int aThis = *aBitsThis;
        aBitsThis++;
        for (int i = jj; i < CoinMin(jj + 32, numberInPivotColumn); i++) {
          if ((aThis & 1) != 0) {
            indexRowU[put] = indexL[i];
            elementU[put++] = area[iA];
            area[iA++] = 0.0;
          }
          aThis = aThis >> 1;
        }
      }
      int numberNeeded = put - startColumn;
      if (positionLargest >= 0) {

        CoinBigIndex start = startColumn;
        int firstIndex = indexRowU[start];
        CoinFactorizationDouble firstValue = elementU[start];
        indexRowU[start] = indexRowU[positionLargest];
        elementU[start] = elementU[positionLargest];
        indexRowU[positionLargest] = firstIndex;
        elementU[positionLargest] = firstValue;
      }
      tempColumnCount[jColumn] = numberNeeded - numberInColumn[iColumn];
      assert(numberNeeded >= 0);
      numberInColumn[iColumn] = numberNeeded;
    }
  }
}
int CoinAbcTypeFactorization::pivot(CoinSimplexInt &pivotRow,
  CoinSimplexInt &pivotColumn,
  CoinBigIndex pivotRowPosition,
  CoinBigIndex pivotColumnPosition,
  int *COIN_RESTRICT markRow)
{
  CoinSimplexInt *COIN_RESTRICT indexColumnU = indexColumnU_.array();
  CoinBigIndex *COIN_RESTRICT startColumnU = startColumnU_.array();
  CoinSimplexInt *COIN_RESTRICT numberInColumn = numberInColumn_.array();
  CoinFactorizationDouble *COIN_RESTRICT elementU = elementU_.array();
  CoinSimplexInt *COIN_RESTRICT indexRowU = indexRowU_.array();
  CoinBigIndex *COIN_RESTRICT startRowU = startRowU_.array();
  CoinSimplexInt *COIN_RESTRICT numberInRow = numberInRow_.array();
  CoinFactorizationDouble *COIN_RESTRICT elementL = elementL_.array();
  CoinSimplexInt *COIN_RESTRICT indexRowL = indexRowL_.array();
  CoinSimplexInt *COIN_RESTRICT saveColumn = saveColumn_.array();
  CoinSimplexInt *COIN_RESTRICT nextRow = nextRow_.array();
  CoinSimplexInt *COIN_RESTRICT lastRow = lastRow_.array();
  int realPivotRow = fromSmallToBigRow_[pivotRow];

  CoinSimplexInt numberInPivotRow = numberInRow[pivotRow] - 1;
  CoinBigIndex startColumn = startColumnU[pivotColumn];
  CoinSimplexInt numberInPivotColumn = numberInColumn[pivotColumn] - 1;

  CoinBigIndex endColumn = startColumn + numberInPivotColumn + 1;
  CoinBigIndex put = 0;
  CoinBigIndex startRow = startRowU[pivotRow];
  CoinBigIndex endRow = startRow + numberInPivotRow + 1;
#if ABC_SMALL < 2

  sparseThreshold_ = -1;
#endif

  if (pivotColumnPosition < 0) {
    for (pivotColumnPosition = startRow; pivotColumnPosition < endRow; pivotColumnPosition++) {
      CoinSimplexInt iColumn = indexColumnU[pivotColumnPosition];
      if (iColumn != pivotColumn) {
        saveColumn[put++] = iColumn;
      } else {
        break;
      }
    }
  } else {
    for (CoinBigIndex i = startRow; i < pivotColumnPosition; i++) {
      saveColumn[put++] = indexColumnU[i];
    }
  }
  assert(pivotColumnPosition < endRow);
  assert(indexColumnU[pivotColumnPosition] == pivotColumn);
  pivotColumnPosition++;
  for (; pivotColumnPosition < endRow; pivotColumnPosition++) {
    saveColumn[put++] = indexColumnU[pivotColumnPosition];
  }

  CoinSimplexInt next = nextRow[pivotRow];
  CoinSimplexInt last = lastRow[pivotRow];

  nextRow[last] = next;
  lastRow[next] = last;
#ifdef SMALL_PERMUTE
  permuteAddress_[realPivotRow] = numberGoodU_; 
#else
  permuteAddress_[pivotRow] = numberGoodU_; 
#endif
  lastRow[pivotRow] = -2;
  numberInRow[pivotRow] = 0;

  CoinBigIndex l = lengthL_;

  if (l + numberInPivotColumn > lengthAreaL_) {

    if ((messageLevel_ & 4) != 0)
      printf("more memory needed in middle of invert\n");
    return -99;
  }

  CoinBigIndex lSave = l;
  CoinSimplexInt saveGoodL = numberGoodL_;
  CoinBigIndex *COIN_RESTRICT startColumnL = startColumnL_.array();
  startColumnL[numberGoodL_] = l; 
  numberGoodL_++;
  if (pivotRowPosition < 0) {
    for (pivotRowPosition = startColumn; pivotRowPosition < endColumn; pivotRowPosition++) {
      CoinSimplexInt iRow = indexRowU[pivotRowPosition];
      if (iRow == pivotRow)
        break;
    }
  }
  assert(pivotRowPosition < endColumn);
  assert(indexRowU[pivotRowPosition] == pivotRow);
  CoinFactorizationDouble pivotElement = elementU[pivotRowPosition];
  CoinFactorizationDouble pivotMultiplier = 1.0 / pivotElement;
  endColumn--;
  indexRowU[pivotRowPosition] = indexRowU[endColumn];
  elementU[pivotRowPosition] = elementU[endColumn];
  double tolerance = zeroTolerance_;
  numberInPivotColumn = endColumn - startColumn;
  pivotRegionAddress_[numberGoodU_] = pivotMultiplier;
  markRow[pivotRow] = LARGE_SET;

  numberInColumn[pivotColumn] = 0;

  CoinBigIndex added = numberInPivotRow * (numberInPivotColumn + 4);
  CoinBigIndex spaceZeroed = added + ((numberRowsSmall_ + 3) >> 2);
  spaceZeroed = CoinMax(spaceZeroed, firstZeroed_);
  int maxBoth = CoinMax(numberInPivotRow, numberInPivotColumn);
  CoinBigIndex spaceOther = numberInPivotRow + maxBoth + numberInPivotRow * ((numberInPivotColumn + 31) >> 5);

  spaceOther += 2 * numberInPivotColumn + 8; 
  CoinBigIndex spaceNeeded = spaceZeroed + ((spaceOther + 1) >> 1) + 32;
#ifdef INT_IS_8
  abort();
#endif
  if (spaceNeeded >= lengthAreaUPlus_ - lastEntryByColumnUPlus_)
    return -99;

  CoinFactorizationDouble *COIN_RESTRICT eArea = elementUColumnPlusAddress_ + lengthAreaUPlus_ - spaceZeroed;
  CoinInt64 xx = reinterpret_cast< CoinInt64 >(eArea);
  int iBottom = static_cast< int >(xx & 255);
  int offset = iBottom >> 3;
  eArea -= offset;
  spaceZeroed = (elementUColumnPlusAddress_ + lengthAreaUPlus_) - eArea;
  char *COIN_RESTRICT mark = reinterpret_cast< char * >(eArea + added);
  CoinFactorizationDouble *COIN_RESTRICT multipliersL = eArea - numberInPivotColumn;

  xx = reinterpret_cast< CoinInt64 >(multipliersL);
  iBottom = static_cast< int >(xx & 31);
  offset = iBottom >> 3;
  multipliersL -= offset;
  int *COIN_RESTRICT tempColumnCount = reinterpret_cast< int * >(multipliersL) - numberInPivotRow;
  int *COIN_RESTRICT tempCount = tempColumnCount - maxBoth;
  int *COIN_RESTRICT others = tempCount - numberInPivotRow;
  for (CoinBigIndex i = startColumn; i < endColumn; i++) {
    CoinSimplexInt iRow = indexRowU[i];

    markRow[iRow] = l - lSave;
    indexRowL[l] = iRow;
    multipliersL[l - lSave] = elementU[i];
    l++;
  }
  startColumnL[numberGoodL_] = l;
  lengthL_ = l;

  CoinSimplexInt *COIN_RESTRICT indexL = &indexRowL[lSave];

  for (int i = 0; i < numberInPivotColumn; i++)
    multipliersL[i] *= pivotMultiplier;

  int lengthArea = ((numberInPivotColumn + 4) >> 2) << 2;

  memset(multipliersL + numberInPivotColumn, 0, (lengthArea - numberInPivotColumn) * sizeof(CoinFactorizationDouble));
  int intsPerColumn = (lengthArea + 31) >> 5;
  unsigned int *COIN_RESTRICT aBits = reinterpret_cast< unsigned int * >(others - intsPerColumn * numberInPivotRow);
  memset(aBits, 0xff, intsPerColumn * 4 * numberInPivotRow);
  if (spaceZeroed > firstZeroed_) {
    CoinAbcMemset0(eArea, spaceZeroed - firstZeroed_);
    firstZeroed_ = spaceZeroed;
  }
#ifndef NDEBUG
  for (int i = 0; i < added; i++)
    assert(!eArea[i]);
  for (int i = 0; i < firstZeroed_; i++)
    assert(!elementUColumnPlusAddress_[lengthAreaUPlus_ - firstZeroed_ + i]);
  for (int i = 0; i < numberRowsSmall_; i++)
    assert(!mark[i]);
#endif

  int status = 0;
  CoinSimplexInt *COIN_RESTRICT numberInColumnPlus = numberInColumnPlus_.array();
  for (int jColumn = 0; jColumn < numberInPivotRow; jColumn++) {
    CoinSimplexInt iColumn = saveColumn[jColumn];
    mark[iColumn] = 1;
  }

  CoinSimplexInt *COIN_RESTRICT nextColumn = nextColumn_.array();
#define ABC_PARALLEL_PIVOT
#ifdef ABC_PARALLEL_PIVOT
#define cilk_for_query cilk_for
#else
#define cilk_for_query for
#endif
#if 0
  for (int i=0;i<numberRowsSmall_;i++)
    assert (numberInColumn[i]>=0);
#endif
  cilk_for_query(int jColumn = 0; jColumn < numberInPivotRow; jColumn++)
  {
    CoinSimplexInt iColumn = saveColumn[jColumn];
    CoinBigIndex startColumn = startColumnU[iColumn];
    CoinBigIndex endColumn = startColumn + numberInColumn[iColumn];
    CoinFactorizationDouble thisPivotValue = 0.0;
    CoinBigIndex put = startColumn;
    CoinBigIndex positionLargest = -1;
    double largest = 0.0;
    CoinBigIndex position = startColumn;
    int iRow = indexRowU[position];
    CoinFactorizationDouble value = elementU[position];
    CoinSimplexInt mark = markRow[iRow];
    CoinBigIndex end = endColumn - 1;
    while (position < end) {
      if (mark == LARGE_UNSET) {

        if (fabs(value) > largest) {
          positionLargest = put;
          largest = fabs(value);
        }
        indexRowU[put] = iRow;
        elementU[put++] = value;
      } else if (mark != LARGE_SET) {

        CoinFactorizationDouble value2 = value;
        int mark2 = mark;
        iRow = indexRowU[end];
        value = elementU[end];
        mark = markRow[iRow];
        indexRowU[end] = mark2;
        elementU[end] = value2;
        end--;
        continue;
      } else {
        thisPivotValue = value;
      }
      position++;
      iRow = indexRowU[position];
      value = elementU[position];
      mark = markRow[iRow];
    }

    if (mark == LARGE_UNSET) {

      if (fabs(value) > largest) {
        positionLargest = put;
        largest = fabs(value);
      }
      indexRowU[put] = iRow;
      elementU[put++] = value;
    } else if (mark != LARGE_SET) {

      indexRowU[end] = mark;
      elementU[end] = value;
    } else {
      thisPivotValue = value;
    }

    if (positionLargest >= 0) {
      double largestValue = elementU[positionLargest];
      int largestIndex = indexRowU[positionLargest];
      if (positionLargest != startColumn + 1 && put > startColumn + 1) {
        elementU[positionLargest] = elementU[startColumn + 1];
        indexRowU[positionLargest] = indexRowU[startColumn + 1];
        elementU[startColumn + 1] = largestValue;
        indexRowU[startColumn + 1] = largestIndex;
      }
      int firstIndex = indexRowU[startColumn];
      CoinFactorizationDouble firstValue = elementU[startColumn];

      elementU[put] = firstValue;
      indexRowU[put++] = firstIndex;
    } else {
      put++;
    }
    elementU[startColumn] = thisPivotValue;
    indexRowU[startColumn] = realPivotRow;
    startColumn++;
    startColumnU[iColumn] = startColumn;
    numberInColumnPlus[iColumn]++;
    int numberNow = put - startColumn;
    tempColumnCount[jColumn] = numberNow;
    numberInColumn[iColumn]--;
#ifndef NDEBUG
    for (int i = startColumn + numberNow; i < startColumn + numberInColumn[iColumn]; i++)
      assert(indexRowU[i] < numberInPivotColumn);
#endif
  }

#if 0
  for (int i=0;i<numberRowsSmall_;i++)
    assert (numberInColumn[i]>=0);
#endif

  mark[pivotColumn] = 1;
  cilk_for_query(int jRow = 0; jRow < numberInPivotColumn; jRow++)
  {
    CoinSimplexInt iRow = indexL[jRow];
    CoinBigIndex startRow = startRowU[iRow];
    CoinBigIndex endRow = startRow + numberInRow[iRow];
    CoinBigIndex put = startRow;

    for (CoinBigIndex i = startRow; i < endRow; i++) {
      int iColumn = indexColumnU[i];
      if (!mark[iColumn])
        indexColumnU[put++] = iColumn;
    }
    numberInRow[iRow] = put - startRow;
  }
  mark[pivotColumn] = 0;
#ifdef DENSE_TRY
  int numberZeroOther = 0;
  for (int jRow = 0; jRow < numberInPivotColumn; jRow++) {
    CoinSimplexInt iRow = indexL[jRow];
    if (numberInRow[iRow]) {

      numberZeroOther = -1;
      break;
    }
  }
  if (!numberZeroOther) {
    for (int jColumn = 0; jColumn < numberInPivotRow; jColumn++) {
      if (!tempColumnCount[jColumn])
        others[numberZeroOther++] = jColumn;
    }
  }
#endif

  for (int jColumn = 0; jColumn < numberInPivotRow; jColumn++) {
    CoinSimplexInt iColumn = saveColumn[jColumn];
    CoinBigIndex startColumn = startColumnU[iColumn];
    int numberNow = tempColumnCount[jColumn];
    int numberNeeded = numberNow + numberInPivotColumn;
    tempCount[jColumn] = numberInColumn[iColumn];

    CoinSimplexInt next = nextColumn[iColumn];
    CoinBigIndex space = startColumnU[next] - startColumn - numberInColumnPlus[next];

    if (numberNeeded > space) {

      if (!getColumnSpace(iColumn, numberNeeded)) {
        return -99;
      }
    }
    numberInColumn[iColumn] = numberNeeded;
  }

  for (int jColumn = 0; jColumn < numberInPivotRow; jColumn++) {
    CoinSimplexInt iColumn = saveColumn[jColumn];
    numberInColumn[iColumn] = tempCount[jColumn];
  }

#if ABC_PARALLEL == 2
  int giveUp = CoinMax(numberInPivotRow / (parallelMode_ + 1 + (parallelMode_ >> 1)), 16);
#else
  int giveUp = numberInPivotRow;
#endif
#ifdef DENSE_TRY

  bool inAreaAlready = false;
  if (numberZeroOther > 4) {

    int numberRowsTest = (numberRowsLeft_ - numberZeroOther + 0) & ~7;
    if (numberRowsLeft_ - numberZeroOther <= numberRowsTest) {

      int numberSubtracted = 0;

      for (int jColumn = 0; jColumn < numberInPivotRow; jColumn++) {
        CoinSimplexInt iColumn = saveColumn[jColumn];
        numberSubtracted += numberInColumn[iColumn] - tempColumnCount[jColumn];
      }

      CoinBigIndex saveTotalElements = totalElements_;
      int saveNumberRowsLeft = numberRowsLeft_;
      int numberOut = numberRowsLeft_ - numberRowsTest - 1;
      numberRowsLeft_ = numberRowsTest;
      CoinBigIndex total = totalElements_ - numberSubtracted;
      int bestGoDense = -1;
      for (; numberRowsLeft_ < saveNumberRowsLeft; numberRowsLeft_ += 8) {
        totalElements_ = total + (numberInPivotColumn - numberOut) * (numberInPivotRow - numberOut);
        int goDense = wantToGoDense();
        if (goDense == 2)
          bestGoDense = numberRowsLeft_;
        else
          break;
        numberOut -= 8;
      }
      totalElements_ = saveTotalElements;
      numberRowsLeft_ = saveNumberRowsLeft;

      if (bestGoDense > numberRowsLeft_ - numberZeroOther)
        numberZeroOther = numberRowsLeft_ - bestGoDense;
      ;
    }
  } else {
    numberZeroOther = -1;
  }
  if (numberZeroOther > 0) {

    pivotStartup(0, numberInPivotRow, numberInPivotColumn, lengthArea, giveUp,
      eArea, saveColumn, startColumnU, tempColumnCount,
      elementU, numberInColumn, indexRowU);
    assert(tempColumnCount[0] >= 0);
    for (int iTry = numberZeroOther - 1; iTry >= 0; iTry--) {
      pivotWhile(0, numberInPivotRow, numberInPivotColumn, lengthArea, giveUp,
        eArea, multipliersL);
      assert(tempColumnCount[0] >= 0);

      int jPivotColumn = others[iTry];
      CoinFactorizationDouble *COIN_RESTRICT area = eArea + jPivotColumn * lengthArea;
      double largest = tolerance;
      int jPivotRow = -1;
      for (CoinSimplexInt j = 0; j < numberInPivotColumn; j++) {
        CoinFactorizationDouble value = area[j];
        CoinSimplexDouble absValue = fabs(value);
        if (absValue > largest) {
          largest = absValue;
          jPivotRow = j;
        }
      }
      if (jPivotRow >= 0) {
        markRow[pivotRow] = LARGE_UNSET;

        deleteLink(pivotRow);
        deleteLink(pivotColumn + numberRows_);

        afterPivot(pivotRow, pivotColumn);
        if (reinterpret_cast< unsigned int * >(elementUColumnPlusAddress_ + lastEntryByColumnUPlus_) > aBits) {
#ifndef NDEBUG
          printf("? dense\n");
#endif
          return -99;
        }

        pivotRow = indexL[jPivotRow];
        pivotColumn = saveColumn[jPivotColumn];

        realPivotRow = fromSmallToBigRow_[pivotRow];

        CoinBigIndex startColumn = startColumnU[pivotColumn];
        CoinBigIndex endColumn = startColumn + tempColumnCount[jPivotColumn];
        CoinSimplexInt next = nextRow[pivotRow];
        CoinSimplexInt last = lastRow[pivotRow];

        nextRow[last] = next;
        lastRow[next] = last;
#ifdef SMALL_PERMUTE
        permuteAddress_[realPivotRow] = numberGoodU_; 
#else
        permuteAddress_[pivotRow] = numberGoodU_; 
#endif
        lastRow[pivotRow] = -2;
        numberInRow[pivotRow] = 0;
        assert(tempColumnCount[0] >= 0);

        CoinBigIndex l = lengthL_;
        if (l + numberInPivotColumn > lengthAreaL_) {

          if ((messageLevel_ & 4) != 0)
            printf("more memory needed in middle of invert\n");
          return -99;
        }

        numberGoodL_++;

        numberInPivotColumn--;
        assert(tempColumnCount[0] >= 0);
        if (jPivotRow != numberInPivotColumn) {

          for (int jColumn = 0; jColumn < numberInPivotRow; jColumn++) {
            CoinFactorizationDouble *COIN_RESTRICT area = eArea + jColumn * lengthArea;
            CoinFactorizationDouble thisValue = area[jPivotRow];
            area[jPivotRow] = area[numberInPivotColumn];
            area[numberInPivotColumn] = thisValue;
          }

          int tempI = indexL[numberInPivotColumn];
          CoinFactorizationDouble tempD = multipliersL[numberInPivotColumn];
          indexL[numberInPivotColumn] = indexL[jPivotRow];
          multipliersL[numberInPivotColumn] = multipliersL[jPivotRow];
          indexL[jPivotRow] = tempI;
          multipliersL[jPivotRow] = tempD;
          jPivotRow = numberInPivotColumn;
        }
        assert(tempColumnCount[0] >= 0);
        numberInPivotRow--;
        CoinFactorizationDouble pivotElement = area[numberInPivotColumn];
        area[numberInPivotColumn] = 0.0;

        CoinFactorizationDouble *COIN_RESTRICT areaLast = eArea + numberInPivotRow * lengthArea;

        saveColumn[jPivotColumn] = saveColumn[numberInPivotRow];
        saveColumn[numberInPivotRow] = pivotColumn;

        tempColumnCount[jPivotColumn] = tempColumnCount[numberInPivotRow];
        totalElements_ -= numberInColumn[pivotColumn];
        mark[pivotColumn] = 0;
        assert(tempColumnCount[0] >= 0);
        for (int jRow = 0; jRow < numberInPivotColumn + 1; jRow++) {
          CoinFactorizationDouble temp = areaLast[jRow];
          areaLast[jRow] = area[jRow];
          area[jRow] = temp;
        }
        areaLast[numberInPivotColumn] = 0.0;

        for (int jColumn = 0; jColumn < numberInPivotRow; jColumn++) {
          CoinFactorizationDouble *COIN_RESTRICT area = eArea + jColumn * lengthArea;
          CoinFactorizationDouble thisPivotValue = area[numberInPivotColumn];
          assert(tempColumnCount[0] >= 0);
          area[numberInPivotColumn] = thisPivotValue;
          if (fabs(thisPivotValue) > tolerance) {
            CoinSimplexInt iColumn = saveColumn[jColumn];
            CoinBigIndex startColumn = startColumnU[iColumn];
            int nKeep = tempColumnCount[jColumn];
            if (nKeep) {
              if (nKeep > 1) {

                elementU[startColumn + nKeep] = elementU[startColumn + 1];
                indexRowU[startColumn + nKeep] = indexRowU[startColumn + 1];
              }

              elementU[startColumn + 1] = elementU[startColumn];
              indexRowU[startColumn + 1] = indexRowU[startColumn];
            }
            elementU[startColumn] = thisPivotValue;
            indexRowU[startColumn] = realPivotRow;
            startColumn++;
            startColumnU[iColumn] = startColumn;
            numberInColumnPlus[iColumn]++;

          }
        }
        assert(tempColumnCount[0] >= 0);

        CoinAbcMemcpy(elementL + lSave, multipliersL, numberInPivotColumn + 1);
        lSave = l;
        for (int i = 0; i < numberInPivotColumn; i++) {
          CoinFactorizationDouble value = areaLast[i];
          areaLast[i] = 0.0;
          int iRow = indexL[i];
          indexRowL[l] = iRow;
          assert(iRow >= 0);
          multipliersL[l - lSave] = value;
          l++;
        }
        startColumnL[numberGoodL_] = l;
        lengthL_ = l;
        CoinFactorizationDouble pivotMultiplier = 1.0 / pivotElement;
        pivotRegionAddress_[numberGoodU_] = pivotMultiplier;
        numberInColumn[pivotColumn] = 0;
        indexL = &indexRowL[lSave];

        for (CoinSimplexInt j = 0; j < numberInPivotColumn; j++) {
          multipliersL[j] *= pivotMultiplier;
        }

        multipliersL[numberInPivotColumn] = 0.0;
      } else {

        break;
      }
    }
    assert(tempColumnCount[0] >= 0);
#if 0

    int add1=numberInPivotColumn>>5;
    unsigned int * aBitsThis = aBits;
    int left=numberInPivotColumn-(add1<<5);
    unsigned int mark1 = (1<<(left-1)-1);

    int jColumn;
    for (jColumn = 0; jColumn < numberInPivotRow; jColumn++ ) {
      memset(aBitsThis+add1,0,(intsPerColumn-add1)*sizeof(int));
      aBitsThis += intsPerColumn;
    }
    for (; jColumn < numberInPivotRow+numberZeroOther; jColumn++ ) {
      memset(aBitsThis,0,intsPerColumn*sizeof(int));
      aBitsThis += intsPerColumn;
    }
#endif

    inAreaAlready = true;
  }
#endif
#if 0
  for (int i=0;i<numberRowsSmall_;i++)
    assert (numberInColumn[i]>=0);
#endif

#ifdef DENSE_TRY
  if (!inAreaAlready) {
#endif
    pivotSome(0, numberInPivotRow, numberInPivotColumn, lengthArea, giveUp,
      eArea, saveColumn, startColumnU, tempColumnCount,
      elementU, numberInColumn, indexRowU, aBits, indexL,
      multipliersL, tolerance);
#ifdef DENSE_TRY
  } else {
    pivotSomeAfter(0, numberInPivotRow, numberInPivotColumn, lengthArea, giveUp,
      eArea, saveColumn, startColumnU, tempColumnCount,
      elementU, numberInColumn, indexRowU, aBits, indexL,
      multipliersL, tolerance);
  }
#endif
#if 0
  for (int i=0;i<numberRowsSmall_;i++)
    assert (numberInColumn[i]>=0);
#endif

  for (int jRow = 0; jRow < numberInPivotColumn; jRow++) {
    CoinSimplexInt iRow = indexL[jRow];
    CoinSimplexInt next = nextRow[iRow];
    CoinBigIndex space = startRowU[next] - startRowU[iRow];

    int numberNeeded = numberInPivotRow + numberInRow[iRow];
    tempCount[jRow] = numberInRow[iRow];
    numberInRow[iRow] = numberNeeded;
    if (space < numberNeeded) {
      if (!getRowSpace(iRow, numberNeeded)) {
        return -99;
      }
    }
    lastEntryByRowU_ = CoinMax(startRowU[iRow] + numberNeeded, lastEntryByRowU_);

    if (lastEntryByRowU_ > lengthAreaU_) {
      return -99;
    }
  }

  for (int jRow = 0; jRow < numberInPivotColumn; jRow++) {
    CoinSimplexInt iRow = indexL[jRow];
    numberInRow[iRow] = tempCount[jRow];
  }

  cilk_for_query(int jRow = 0; jRow < numberInPivotColumn; jRow++)
  {
    CoinSimplexInt iRow = indexL[jRow];
    CoinBigIndex startRow = startRowU[iRow];
    CoinBigIndex put = startRow + numberInRow[iRow];
    int iWord = jRow >> 5;
    unsigned int setBit = 1 << (jRow & 31);
    unsigned int *aBitsThis = aBits + iWord;
    for (int i = 0; i < numberInPivotRow; i++) {
      if ((aBitsThis[0] & setBit) != 0) {
        indexColumnU[put++] = saveColumn[i];
      }
      aBitsThis += intsPerColumn;
    }
    markRow[iRow] = LARGE_UNSET;
    numberInRow[iRow] = put - startRow;
  }

  added = 0;

  for (int jColumn = 0; jColumn < numberInPivotRow; jColumn++) {
    CoinSimplexInt iColumn = saveColumn[jColumn];
    for (int i = startColumnU[iColumn]; i < startColumnU[iColumn] + numberInColumn[iColumn]; i++)
      assert(indexRowU[i] >= 0 && indexRowU[i] < numberRowsSmall_);
    mark[iColumn] = 0;
    added += tempColumnCount[jColumn];
    modifyLink(iColumn + numberRows_, numberInColumn[iColumn]);

  }
#ifndef NDEBUG
  for (int i = 0; i < added; i++)
    assert(!eArea[i]);
  for (int i = 0; i < firstZeroed_; i++)
    assert(!elementUColumnPlusAddress_[lengthAreaUPlus_ - firstZeroed_ + i]);
  for (int i = 0; i < numberRowsSmall_; i++)
    assert(!mark[i]);
#endif

#if 0 
  if (numberZeroOther>10000)
    printf("INrow %d incolumn %d nzero %d\n",
	   numberInPivotRow,numberInPivotColumn,numberZeroOther);
#endif

  for (int i = 0; i < numberInPivotColumn; i++) {
    int iRow = indexL[i];
    modifyLink(iRow, numberInRow[iRow]);
  }
  CoinAbcMemcpy(elementL + lSave, multipliersL, numberInPivotColumn);
#ifdef DENSE_TRY
  int iLBad = saveGoodL;
  put = startColumnL[iLBad];
  for (int iL = iLBad; iL < numberGoodL_; iL++) {
    CoinBigIndex start = startColumnL[iL];
    startColumnL[iL] = put;
    for (CoinBigIndex j = start; j < startColumnL[iL + 1]; j++) {
      if (elementL[j]) {
        elementL[put] = elementL[j];
        indexRowL[put++] = fromSmallToBigRow_[indexRowL[j]];
      }
    }
  }
  startColumnL[numberGoodL_] = put;
  lengthL_ = put;
#else

  for (CoinBigIndex j = lSave; j < startColumnL[numberGoodL_]; j++) {

    int iRow = indexRowL[j];
    indexRowL[j] = fromSmallToBigRow_[iRow];
  }
#endif
  markRow[pivotRow] = LARGE_UNSET;

  deleteLink(pivotRow);
  deleteLink(pivotColumn + numberRows_);
  totalElements_ += added;
  return status;
}
#endif

int CoinAbcTypeFactorization::pivot(CoinSimplexInt pivotRow,
  CoinSimplexInt pivotColumn,
  CoinBigIndex pivotRowPosition,
  CoinBigIndex pivotColumnPosition,
  CoinFactorizationDouble *COIN_RESTRICT work,
  CoinSimplexUnsignedInt *COIN_RESTRICT workArea2,
  CoinSimplexInt increment2,
  int *COIN_RESTRICT markRow)
{
  CoinSimplexInt *COIN_RESTRICT indexColumnU = indexColumnU_.array();
  CoinBigIndex *COIN_RESTRICT startColumnU = startColumnU_.array();
  CoinSimplexInt *COIN_RESTRICT numberInColumn = numberInColumn_.array();
  CoinFactorizationDouble *COIN_RESTRICT elementU = elementU_.array();
  CoinSimplexInt *COIN_RESTRICT indexRowU = indexRowU_.array();
  CoinBigIndex *COIN_RESTRICT startRowU = startRowU_.array();
  CoinSimplexInt *COIN_RESTRICT numberInRow = numberInRow_.array();
  CoinFactorizationDouble *COIN_RESTRICT elementL = elementL_.array();
  CoinSimplexInt *COIN_RESTRICT indexRowL = indexRowL_.array();
  CoinSimplexInt *COIN_RESTRICT saveColumn = saveColumn_.array();
  CoinSimplexInt *COIN_RESTRICT nextRow = nextRow_.array();
  CoinSimplexInt *COIN_RESTRICT lastRow = lastRow_.array();
#ifdef SMALL_PERMUTE
  int realPivotRow = fromSmallToBigRow_[pivotRow];

#endif

  CoinSimplexInt numberInPivotRow = numberInRow[pivotRow] - 1;
  CoinBigIndex startColumn = startColumnU[pivotColumn];
  CoinSimplexInt numberInPivotColumn = numberInColumn[pivotColumn] - 1;

  CoinBigIndex endColumn = startColumn + numberInPivotColumn + 1;
  CoinBigIndex put = 0;
  CoinBigIndex startRow = startRowU[pivotRow];
  CoinBigIndex endRow = startRow + numberInPivotRow + 1;
#if ABC_SMALL < 2

  sparseThreshold_ = -1;
#endif

  if (pivotColumnPosition < 0) {
    for (pivotColumnPosition = startRow; pivotColumnPosition < endRow; pivotColumnPosition++) {
      CoinSimplexInt iColumn = indexColumnU[pivotColumnPosition];
      if (iColumn != pivotColumn) {
        saveColumn[put++] = iColumn;
      } else {
#if BOTH_WAYS
#endif
        break;
      }
    }
  } else {
    for (CoinBigIndex i = startRow; i < pivotColumnPosition; i++) {
      saveColumn[put++] = indexColumnU[i];
    }
  }
  assert(pivotColumnPosition < endRow);
  assert(indexColumnU[pivotColumnPosition] == pivotColumn);
  pivotColumnPosition++;
  for (; pivotColumnPosition < endRow; pivotColumnPosition++) {
    saveColumn[put++] = indexColumnU[pivotColumnPosition];
  }

  CoinSimplexInt next = nextRow[pivotRow];
  CoinSimplexInt last = lastRow[pivotRow];

  nextRow[last] = next;
  lastRow[next] = last;
#ifdef SMALL_PERMUTE
  permuteAddress_[realPivotRow] = numberGoodU_; 
#else
  permuteAddress_[pivotRow] = numberGoodU_; 
#endif
  lastRow[pivotRow] = -2;
  numberInRow[pivotRow] = 0;

  CoinBigIndex l = lengthL_;

  if (l + numberInPivotColumn > lengthAreaL_) {

    if ((messageLevel_ & 4) != 0)
      printf("more memory needed in middle of invert\n");
    return -99;
  }

  CoinBigIndex lSave = l;

  CoinBigIndex *COIN_RESTRICT startColumnL = startColumnL_.array();
  startColumnL[numberGoodL_] = l; 
  numberGoodL_++;
  startColumnL[numberGoodL_] = l + numberInPivotColumn;
  lengthL_ += numberInPivotColumn;
  if (pivotRowPosition < 0) {
    for (pivotRowPosition = startColumn; pivotRowPosition < endColumn; pivotRowPosition++) {
      CoinSimplexInt iRow = indexRowU[pivotRowPosition];
      if (iRow != pivotRow) {
        indexRowL[l] = iRow;
        elementL[l] = elementU[pivotRowPosition];
        markRow[iRow] = l - lSave;
        l++;

        CoinBigIndex start = startRowU[iRow];
        CoinBigIndex end = start + numberInRow[iRow];
        CoinBigIndex where = start;

        while (indexColumnU[where] != pivotColumn) {
          where++;
        } 
#if DEBUG_COIN
        if (where >= end) {
          abort();
        }
#endif
#if BOTH_WAYS
#endif
        indexColumnU[where] = indexColumnU[end - 1];
        numberInRow[iRow]--;
      } else {
        break;
      }
    }
  } else {
    CoinBigIndex i;

    for (i = startColumn; i < pivotRowPosition; i++) {
      CoinSimplexInt iRow = indexRowU[i];

      markRow[iRow] = l - lSave;
      indexRowL[l] = iRow;
      elementL[l] = elementU[i];
      l++;

      CoinBigIndex start = startRowU[iRow];
      CoinBigIndex end = start + numberInRow[iRow];
      CoinBigIndex where = start;

      while (indexColumnU[where] != pivotColumn) {
        where++;
      } 
#if DEBUG_COIN
      if (where >= end) {
        abort();
      }
#endif
#if BOTH_WAYS
#endif
      indexColumnU[where] = indexColumnU[end - 1];
      numberInRow[iRow]--;
      assert(numberInRow[iRow] >= 0);
    }
  }
  assert(pivotRowPosition < endColumn);
  assert(indexRowU[pivotRowPosition] == pivotRow);
  CoinFactorizationDouble pivotElement = elementU[pivotRowPosition];
  CoinFactorizationDouble pivotMultiplier = 1.0 / pivotElement;

  pivotRegionAddress_[numberGoodU_] = pivotMultiplier;
  pivotRowPosition++;
  for (; pivotRowPosition < endColumn; pivotRowPosition++) {
    CoinSimplexInt iRow = indexRowU[pivotRowPosition];

    markRow[iRow] = l - lSave;
    indexRowL[l] = iRow;
    elementL[l] = elementU[pivotRowPosition];
    l++;

    CoinBigIndex start = startRowU[iRow];
    CoinBigIndex end = start + numberInRow[iRow];
    CoinBigIndex where = start;

    while (indexColumnU[where] != pivotColumn) {
      where++;
    } 
#if DEBUG_COIN
    if (where >= end) {
      abort();
    }
#endif
#if BOTH_WAYS
#endif
    indexColumnU[where] = indexColumnU[end - 1];
    numberInRow[iRow]--;
    assert(numberInRow[iRow] >= 0);
  }
  markRow[pivotRow] = LARGE_SET;

  numberInColumn[pivotColumn] = 0;

  CoinSimplexInt *COIN_RESTRICT indexL = &indexRowL[lSave];
  CoinFactorizationDouble *COIN_RESTRICT multipliersL = &elementL[lSave];

  CoinSimplexInt j;

  for (j = 0; j < numberInPivotColumn; j++) {
    multipliersL[j] *= pivotMultiplier;
  }
  CoinBigIndex added = numberInPivotRow * numberInPivotColumn;

  CoinBigIndex iErase;
  for (iErase = 0; iErase < increment2 * numberInPivotRow;
       iErase++) {
    workArea2[iErase] = 0;
  }
  CoinSimplexUnsignedInt *COIN_RESTRICT temp2 = workArea2;
  CoinSimplexInt *COIN_RESTRICT nextColumn = nextColumn_.array();

  CoinSimplexInt jColumn;
  for (jColumn = 0; jColumn < numberInPivotRow; jColumn++) {
    CoinSimplexInt iColumn = saveColumn[jColumn];
    CoinBigIndex startColumn = startColumnU[iColumn];
    CoinBigIndex endColumn = startColumn + numberInColumn[iColumn];
    CoinSimplexInt iRow = indexRowU[startColumn];
    CoinFactorizationDouble value = elementU[startColumn];
    CoinSimplexDouble largest;
    CoinBigIndex put = startColumn;
    CoinBigIndex positionLargest = -1;
    CoinFactorizationDouble thisPivotValue = 0.0;

    bool checkLargest;
    CoinSimplexInt mark = markRow[iRow];

    if (mark == LARGE_UNSET) {
      largest = fabs(value);
      positionLargest = put;
      put++;
      checkLargest = false;
    } else {

      largest = 0.0;
      checkLargest = true;
      if (mark != LARGE_SET) {

        work[mark] = value;
        CoinSimplexInt word = mark >> COINFACTORIZATION_SHIFT_PER_INT;
        CoinSimplexInt bit = mark & COINFACTORIZATION_MASK_PER_INT;

        temp2[word] = temp2[word] | (1 << bit); 
        added--;
      } else {
        thisPivotValue = value;
      }
    }
    CoinBigIndex i;
    for (i = startColumn + 1; i < endColumn; i++) {
      iRow = indexRowU[i];
      value = elementU[i];
      CoinSimplexInt mark = markRow[iRow];

      if (mark == LARGE_UNSET) {

        indexRowU[put] = iRow;
#if BOTH_WAYS
#endif
        elementU[put] = value;
        if (checkLargest) {
          CoinSimplexDouble absValue = fabs(value);

          if (absValue > largest) {
            largest = absValue;
            positionLargest = put;
          }
        }
        put++;
      } else if (mark != LARGE_SET) {

        work[mark] = value;
        CoinSimplexInt word = mark >> COINFACTORIZATION_SHIFT_PER_INT;
        CoinSimplexInt bit = mark & COINFACTORIZATION_MASK_PER_INT;

        temp2[word] = temp2[word] | (1 << bit); 
        added--;
      } else {
        thisPivotValue = value;
      }
    }

    elementU[put] = elementU[startColumn];
    indexRowU[put] = indexRowU[startColumn];
#if BOTH_WAYS
#endif
    if (positionLargest == startColumn) {
      positionLargest = put; 
    }
    put++;
    elementU[startColumn] = thisPivotValue;
#ifdef SMALL_PERMUTE
    indexRowU[startColumn] = realPivotRow;
#else
    indexRowU[startColumn] = pivotRow;
#endif
#if BOTH_WAYS
#endif

    startColumn++;
    numberInColumn[iColumn] = put - startColumn;
    CoinSimplexInt *COIN_RESTRICT numberInColumnPlus = numberInColumnPlus_.array();
    numberInColumnPlus[iColumn]++;
    startColumnU[iColumn]++;

    CoinSimplexInt next = nextColumn[iColumn];
    CoinBigIndex space;

    space = startColumnU[next] - put - numberInColumnPlus[next];

    if (numberInPivotColumn > space) {

      if (!getColumnSpace(iColumn, numberInPivotColumn)) {
        return -99;
      }

      positionLargest = positionLargest + startColumnU[iColumn] - startColumn;
      startColumn = startColumnU[iColumn];
      put = startColumn + numberInColumn[iColumn];
    }
    CoinSimplexDouble tolerance = zeroTolerance_;

    for (j = 0; j < numberInPivotColumn; j++) {
      value = work[j] - thisPivotValue * multipliersL[j];
      CoinSimplexDouble absValue = fabs(value);

      if (absValue > tolerance) {
        work[j] = 0.0;
        assert(put < lengthAreaU_);
        elementU[put] = value;
        indexRowU[put] = indexL[j];
#if BOTH_WAYS
#endif
        if (absValue > largest) {
          largest = absValue;
          positionLargest = put;
        }
        put++;
      } else {
        work[j] = 0.0;
        added--;
        CoinSimplexInt word = j >> COINFACTORIZATION_SHIFT_PER_INT;
        CoinSimplexInt bit = j & COINFACTORIZATION_MASK_PER_INT;

        if (temp2[word] & (1 << bit)) {

          iRow = indexL[j];
          CoinBigIndex start = startRowU[iRow];
          CoinBigIndex end = start + numberInRow[iRow];
          CoinBigIndex where = start;

          while (indexColumnU[where] != iColumn) {
            where++;
          } 
#if DEBUG_COIN
          if (where >= end) {
            abort();
          }
#endif
#if BOTH_WAYS
#endif
          indexColumnU[where] = indexColumnU[end - 1];
          numberInRow[iRow]--;
        } else {

          CoinSimplexInt word = j >> COINFACTORIZATION_SHIFT_PER_INT;
          CoinSimplexInt bit = j & COINFACTORIZATION_MASK_PER_INT;

          temp2[word] = temp2[word] | (1 << bit); 
        }
      }
    }
    numberInColumn[iColumn] = put - startColumn;

    if (positionLargest >= 0) {
      value = elementU[positionLargest];
      iRow = indexRowU[positionLargest];
      elementU[positionLargest] = elementU[startColumn];
      indexRowU[positionLargest] = indexRowU[startColumn];
      elementU[startColumn] = value;
      indexRowU[startColumn] = iRow;
#if BOTH_WAYS
#endif
    }

    temp2 += increment2;
  }

  CoinSimplexUnsignedInt *COIN_RESTRICT putBase = workArea2;
  CoinSimplexInt bigLoops = numberInPivotColumn >> COINFACTORIZATION_SHIFT_PER_INT;
  CoinSimplexInt i = 0;

  while (bigLoops) {
    bigLoops--;
    CoinSimplexInt bit;
    for (bit = 0; bit < COINFACTORIZATION_BITS_PER_INT; i++, bit++) {
      CoinSimplexUnsignedInt *putThis = putBase;
      CoinSimplexInt iRow = indexL[i];

      CoinSimplexInt number = 0;
      CoinSimplexInt jColumn;

      for (jColumn = 0; jColumn < numberInPivotRow; jColumn++) {
        CoinSimplexUnsignedInt test = *putThis;

        putThis += increment2;
        test = 1 - ((test >> bit) & 1);
        number += test;
      }
      CoinSimplexInt next = nextRow[iRow];
      CoinBigIndex space;

      space = startRowU[next] - startRowU[iRow];
      number += numberInRow[iRow];
      if (space < number) {
        if (!getRowSpace(iRow, number)) {
          return -99;
        }
      }

      putThis = putBase;
      next = nextRow[iRow];
      number = numberInRow[iRow];
      CoinBigIndex end = startRowU[iRow] + number;
      CoinSimplexInt saveIndex = indexColumnU[startRowU[next]];

      for (jColumn = 0; jColumn < numberInPivotRow; jColumn++) {
        CoinSimplexUnsignedInt test = *putThis;

        putThis += increment2;
        test = 1 - ((test >> bit) & 1);
        indexColumnU[end] = saveColumn[jColumn];
#if BOTH_WAYS
#endif
        end += test;
      }
      lastEntryByRowU_ = CoinMax(end, lastEntryByRowU_);
      assert(lastEntryByRowU_ <= lengthAreaU_);

      indexColumnU[startRowU[next]] = saveIndex;
#if BOTH_WAYS
#endif
      markRow[iRow] = LARGE_UNSET;
      number = end - startRowU[iRow];
      numberInRow[iRow] = number;

    }
    putBase++;
  } 
  CoinSimplexInt bit;

  for (bit = 0; i < numberInPivotColumn; i++, bit++) {
    CoinSimplexUnsignedInt *putThis = putBase;
    CoinSimplexInt iRow = indexL[i];

    CoinSimplexInt number = 0;
    CoinSimplexInt jColumn;

    for (jColumn = 0; jColumn < numberInPivotRow; jColumn++) {
      CoinSimplexUnsignedInt test = *putThis;

      putThis += increment2;
      test = 1 - ((test >> bit) & 1);
      number += test;
    }
    CoinSimplexInt next = nextRow[iRow];
    CoinBigIndex space;

    space = startRowU[next] - startRowU[iRow];
    number += numberInRow[iRow];
    if (space < number) {
      if (!getRowSpace(iRow, number)) {
        return -99;
      }
    }

    putThis = putBase;
    next = nextRow[iRow];
    number = numberInRow[iRow];
    CoinBigIndex end = startRowU[iRow] + number;
    CoinSimplexInt saveIndex;

    saveIndex = indexColumnU[startRowU[next]];

    for (jColumn = 0; jColumn < numberInPivotRow; jColumn++) {
      CoinSimplexUnsignedInt test = *putThis;

      putThis += increment2;
      test = 1 - ((test >> bit) & 1);

      indexColumnU[end] = saveColumn[jColumn];
#if BOTH_WAYS
#endif
      end += test;

    }
    indexColumnU[startRowU[next]] = saveIndex;
    lastEntryByRowU_ = CoinMax(end, lastEntryByRowU_);
    assert(lastEntryByRowU_ <= lengthAreaU_);
#if BOTH_WAYS
#endif
    markRow[iRow] = LARGE_UNSET;
    number = end - startRowU[iRow];
    numberInRow[iRow] = number;

  }
  for (jColumn = 0; jColumn < numberInPivotRow; jColumn++) {
    CoinSimplexInt iColumn = saveColumn[jColumn];
    modifyLink(iColumn + numberRows_, numberInColumn[iColumn]);
  }
  for (int i = 0; i < numberInPivotColumn; i++) {
    int iRow = indexL[i];
    modifyLink(iRow, numberInRow[iRow]);
  }
#ifdef SMALL_PERMUTE

  for (CoinBigIndex j = lSave; j < startColumnL[numberGoodL_]; j++) {
    int iRow = indexRowL[j];
    indexRowL[j] = fromSmallToBigRow_[iRow];
  }
#endif
  markRow[pivotRow] = LARGE_UNSET;

  deleteLink(pivotRow);
  deleteLink(pivotColumn + numberRows_);
  totalElements_ += added;
  return 0;
}

void CoinAbcTypeFactorization::afterPivot(CoinSimplexInt pivotRow,
  CoinSimplexInt pivotColumn)
{
#ifdef SMALL_PERMUTE
  int realPivotRow = fromSmallToBigRow_[pivotRow];
  int realPivotColumn = fromSmallToBigColumn_[pivotColumn];
  assert(permuteAddress_[realPivotRow] == numberGoodU_);
  pivotColumnAddress_[numberGoodU_] = realPivotColumn;
#else
  assert(permuteAddress_[pivotRow] == numberGoodU_);
  pivotColumnAddress_[numberGoodU_] = pivotColumn;
#endif
#ifdef ABC_USE_FUNCTION_POINTERS
  int number = numberInColumnPlusAddress_[pivotColumn];
  scatterStruct *COIN_RESTRICT scatter = scatterUColumn();
#ifdef SMALL_PERMUTE
#if ABC_USE_FUNCTION_POINTERS
  if (number < 9) {
    scatter[realPivotRow].functionPointer = AbcScatterLowSubtract[number];
  } else {
    scatter[realPivotRow].functionPointer = AbcScatterHighSubtract[number & 3];
  }
#endif
  scatter[realPivotRow].offset = lastEntryByColumnUPlus_;
  scatter[realPivotRow].number = number;
#else
#if ABC_USE_FUNCTION_POINTERS
  if (number < 9) {
    scatter[pivotRow].functionPointer = AbcScatterLowSubtract[number];
  } else {
    scatter[pivotRow].functionPointer = AbcScatterHighSubtract[number & 3];
  }
#endif
  scatter[pivotRow].offset = lastEntryByColumnUPlus_;
  scatter[pivotRow].number = number;
#endif

  CoinSimplexInt *COIN_RESTRICT indexRow = indexRowUAddress_;
  CoinFactorizationDouble *COIN_RESTRICT element = elementUAddress_;
  CoinBigIndex *COIN_RESTRICT startColumnU = startColumnUAddress_;
  CoinBigIndex startC = startColumnU[pivotColumn] - number;
  CoinFactorizationDouble pivotMultiplier = pivotRegionAddress_[numberGoodU_];
  for (int i = startC; i < startC + number; i++)
    elementUColumnPlusAddress_[lastEntryByColumnUPlus_++] = element[i] * pivotMultiplier;
  CoinAbcMemcpy(reinterpret_cast< CoinSimplexInt * >(elementUColumnPlusAddress_ + lastEntryByColumnUPlus_), indexRow + startC, number);
  lastEntryByColumnUPlus_ += (number + 1) >> 1;
#ifdef ABC_USE_FUNCTION_POINTERS
  if (!numberInColumnAddress_[pivotColumn]) {
    int iNext = nextColumnAddress_[pivotColumn];
    int iLast = lastColumnAddress_[pivotColumn];
    lastColumnAddress_[iNext] = iLast;
    assert(iLast >= 0);
    nextColumnAddress_[iLast] = iNext;
  }
#endif
#endif
  numberGoodU_++;
  numberRowsLeft_--;
#if COIN_DEBUG == 2
  checkConsistency();
#endif
}
#if ABC_DENSE_CODE

int CoinAbcTypeFactorization::wantToGoDense()
{
  int status = 0;
  if (denseThreshold_) {

    if ((numberRowsLeft_ & 7) == 0) {
      CoinSimplexDouble full = numberRowsLeft_;
      full *= full;
      assert(full >= 0.0);
      CoinSimplexDouble leftElements = totalElements_;

      CoinSimplexDouble ratio;
      if (numberRowsLeft_ > 2000)
        ratio = 3.5;
      else if (numberRowsLeft_ > 800)
        ratio = 2.75; 
      else if (numberRowsLeft_ > 256)
        ratio = 2.0; 

      else
        ratio = 1.5;

      if ((ratio * leftElements > full && numberRowsLeft_ > abs(denseThreshold_))) {
#if 0 

	CoinSimplexInt check=0;
	for (CoinSimplexInt iColumn=0;iColumn<numberRowsSmall_;iColumn++) {
	  if (numberInColumnAddress_[iColumn]) 
	    check++;
	}
	if (check!=numberRowsLeft_) {
	  printf("** mismatch %d columns left, %d rows\n",check,numberRowsLeft_);

	} else {
	  status=2;
	  if ((messageLevel_&4)!=0) 
	    std::cout<<"      Went dense at "<<numberRowsLeft_<<" rows "<<
	      totalElements_<<" "<<full<<" "<<leftElements<<std::endl;
	}
#else
        status = 2;
#if ABC_NORMAL_DEBUG > 1
        std::cout << "      Went dense at " << numberRowsLeft_ << " rows " << totalElements_ << " " << full << " " << leftElements << std::endl;
#endif
#endif
      }
    }
  }
  return status;
}
#endif

bool CoinAbcTypeFactorization::pivotRowSingleton(CoinSimplexInt pivotRow,
  CoinSimplexInt pivotColumn)
{

  CoinBigIndex *COIN_RESTRICT startColumnU = startColumnUAddress_;
  CoinBigIndex COIN_RESTRICT startColumn = startColumnU[pivotColumn];
  CoinSimplexInt *COIN_RESTRICT numberInRow = numberInRowAddress_;
  CoinSimplexInt *COIN_RESTRICT numberInColumn = numberInColumnAddress_;
  CoinSimplexInt numberDoColumn = numberInColumn[pivotColumn] - 1;
  CoinBigIndex endColumn = startColumn + numberDoColumn + 1;
  CoinBigIndex pivotRowPosition = startColumn;
  CoinSimplexInt *COIN_RESTRICT indexRowU = indexRowUAddress_;
  CoinSimplexInt iRow = indexRowU[pivotRowPosition];
  CoinBigIndex *COIN_RESTRICT startRowU = startRowUAddress_;
  CoinSimplexInt *COIN_RESTRICT nextRow = nextRowAddress_;
  CoinSimplexInt *COIN_RESTRICT lastRow = lastRowAddress_;

  while (iRow != pivotRow) {
    pivotRowPosition++;
    iRow = indexRowU[pivotRowPosition];
  } 
  assert(pivotRowPosition < endColumn);

  CoinBigIndex l = lengthL_;

  if (l + numberDoColumn > lengthAreaL_) {

    if ((messageLevel_ & 4) != 0)
      std::cout << "more memory needed in middle of invert" << std::endl;
    return false;
  }
  CoinBigIndex *COIN_RESTRICT startColumnL = startColumnLAddress_;
  CoinFactorizationDouble *COIN_RESTRICT elementL = elementLAddress_;
  CoinSimplexInt *COIN_RESTRICT indexRowL = indexRowLAddress_;
  startColumnL[numberGoodL_] = l; 
  numberGoodL_++;
  startColumnL[numberGoodL_] = l + numberDoColumn;
  lengthL_ += numberDoColumn;
  CoinFactorizationDouble *COIN_RESTRICT elementU = elementUAddress_;
  CoinFactorizationDouble pivotElement = elementU[pivotRowPosition];
  CoinFactorizationDouble pivotMultiplier = 1.0 / pivotElement;

  pivotRegionAddress_[numberGoodU_] = pivotMultiplier;
  CoinBigIndex i;

  CoinSimplexInt *COIN_RESTRICT indexColumnU = indexColumnUAddress_;
#ifdef SMALL_PERMUTE
  int realPivotRow = fromSmallToBigRow_[pivotRow];
#endif
  for (i = startColumn; i < pivotRowPosition; i++) {
    CoinSimplexInt iRow = indexRowU[i];

#ifdef SMALL_PERMUTE
    indexRowL[l] = fromSmallToBigRow_[iRow];
#else
    indexRowL[l] = iRow;
#endif
    elementL[l] = elementU[i] * pivotMultiplier;
    l++;

    CoinBigIndex start = startRowU[iRow];
    CoinSimplexInt iNumberInRow = numberInRow[iRow];
    CoinBigIndex end = start + iNumberInRow;
    CoinBigIndex where = start;

    while (indexColumnU[where] != pivotColumn) {
      where++;
    } 
    assert(where < end);
#if BOTH_WAYS
#endif
    indexColumnU[where] = indexColumnU[end - 1];
    iNumberInRow--;
    numberInRow[iRow] = iNumberInRow;
    modifyLink(iRow, iNumberInRow);
  }
  for (i = pivotRowPosition + 1; i < endColumn; i++) {
    CoinSimplexInt iRow = indexRowU[i];

#ifdef SMALL_PERMUTE
    indexRowL[l] = fromSmallToBigRow_[iRow];
#else
    indexRowL[l] = iRow;
#endif
    elementL[l] = elementU[i] * pivotMultiplier;
    l++;

    CoinBigIndex start = startRowU[iRow];
    CoinSimplexInt iNumberInRow = numberInRow[iRow];
    CoinBigIndex end = start + iNumberInRow;
    CoinBigIndex where = start;

    while (indexColumnU[where] != pivotColumn) {
      where++;
    } 
    assert(where < end);
#if BOTH_WAYS
#endif
    indexColumnU[where] = indexColumnU[end - 1];
    iNumberInRow--;
    numberInRow[iRow] = iNumberInRow;
    modifyLink(iRow, iNumberInRow);
  }
  numberInColumn[pivotColumn] = 0;

  numberInRow[pivotRow] = 0;
  deleteLink(pivotRow);
  deleteLink(pivotColumn + numberRows_);

  CoinSimplexInt next = nextRow[pivotRow];
  CoinSimplexInt last = lastRow[pivotRow];

  nextRow[last] = next;
  lastRow[next] = last;
  lastRow[pivotRow] = -2;
#ifdef SMALL_PERMUTE
  permuteAddress_[realPivotRow] = numberGoodU_;
#else
  permuteAddress_[pivotRow] = numberGoodU_;
#endif
  return true;
}

void CoinAbcTypeFactorization::pivotColumnSingleton(CoinSimplexInt pivotRow,
  CoinSimplexInt pivotColumn)
{
  CoinSimplexInt *COIN_RESTRICT numberInRow = numberInRowAddress_;
  CoinSimplexInt *COIN_RESTRICT numberInColumn = numberInColumnAddress_;
  CoinSimplexInt *COIN_RESTRICT numberInColumnPlus = numberInColumnPlusAddress_;

  CoinSimplexInt numberDoRow = numberInRow[pivotRow] - 1;
  CoinBigIndex *COIN_RESTRICT startColumnU = startColumnUAddress_;
  CoinBigIndex startColumn = startColumnU[pivotColumn];
  CoinBigIndex *COIN_RESTRICT startRowU = startRowUAddress_;
  CoinBigIndex startRow = startRowU[pivotRow];
  CoinBigIndex endRow = startRow + numberDoRow + 1;
  CoinSimplexInt *COIN_RESTRICT nextRow = nextRowAddress_;
  CoinSimplexInt *COIN_RESTRICT lastRow = lastRowAddress_;

  CoinSimplexInt next = nextRow[pivotRow];
  CoinSimplexInt last = lastRow[pivotRow];

  nextRow[last] = next;
  lastRow[next] = last;
  lastRow[pivotRow] = -2; 
#ifdef SMALL_PERMUTE
  int realPivotRow = fromSmallToBigRow_[pivotRow];
  permuteAddress_[realPivotRow] = numberGoodU_;
#else
  permuteAddress_[pivotRow] = numberGoodU_;
#endif

  CoinFactorizationDouble *COIN_RESTRICT elementU = elementUAddress_;
  CoinFactorizationDouble pivotElement = elementU[startColumn];

  pivotRegionAddress_[numberGoodU_] = 1.0 / pivotElement;
  numberInColumn[pivotColumn] = 0;
  CoinSimplexInt *COIN_RESTRICT indexColumnU = indexColumnUAddress_;
  CoinSimplexInt *COIN_RESTRICT indexRowU = indexRowUAddress_;

  CoinBigIndex i;

  for (i = startRow; i < endRow; i++) {
    CoinSimplexInt iColumn = indexColumnU[i];
    if (numberInColumn[iColumn]) {
      CoinSimplexInt number = numberInColumn[iColumn] - 1;

      modifyLink(iColumn + numberRows_, number);

#ifdef SMALL_PERMUTE
      CoinBigIndex start = startColumnU[iColumn];
#endif
      if (number) {
#ifndef SMALL_PERMUTE
        CoinBigIndex start = startColumnU[iColumn];
#endif
        CoinBigIndex pivot = start;
        CoinSimplexInt iRow = indexRowU[pivot];
        while (iRow != pivotRow) {
          pivot++;
          iRow = indexRowU[pivot];
        }
        assert(pivot < startColumnU[iColumn] + numberInColumn[iColumn]);
#if BOTH_WAYS
#endif
        if (pivot != start) {

          CoinFactorizationDouble value = elementU[start];

          iRow = indexRowU[start];
          elementU[start] = elementU[pivot];
          assert(indexRowU[pivot] == pivotRow);
          indexRowU[start] = indexRowU[pivot];
          elementU[pivot] = elementU[start + 1];
          indexRowU[pivot] = indexRowU[start + 1];
          elementU[start + 1] = value;
          indexRowU[start + 1] = iRow;
#if BOTH_WAYS
#endif
        } else {

          CoinSimplexInt iRowSave = indexRowU[start + 1];
          CoinFactorizationDouble valueSave = elementU[start + 1];
          CoinFactorizationDouble valueLargest = fabs(valueSave);
          CoinBigIndex end = start + numberInColumn[iColumn];
          CoinBigIndex largest = start + 1;

          CoinBigIndex k;
          for (k = start + 2; k < end; k++) {
            CoinFactorizationDouble value = elementU[k];
            CoinFactorizationDouble valueAbs = fabs(value);

            if (valueAbs > valueLargest) {
              valueLargest = valueAbs;
              largest = k;
            }
          }
          indexRowU[start + 1] = indexRowU[largest];
          elementU[start + 1] = elementU[largest];
          indexRowU[largest] = iRowSave;
          elementU[largest] = valueSave;
#if BOTH_WAYS
#endif
        }
      }
#ifdef SMALL_PERMUTE
      indexRowU[start] = realPivotRow;
#endif

      numberInColumn[iColumn]--;
      numberInColumnPlus[iColumn]++;
      startColumnU[iColumn]++;

    }
  }

  deleteLink(pivotRow);
  deleteLink(pivotColumn + numberRows_);
  numberInRow[pivotRow] = 0;

  CoinBigIndex l = lengthL_;

  CoinBigIndex *startColumnL = startColumnLAddress_;
  startColumnL[numberGoodL_] = l; 
  numberGoodL_++;
  startColumnL[numberGoodL_] = l;
}

bool CoinAbcTypeFactorization::getColumnSpace(CoinSimplexInt iColumn,
  CoinSimplexInt extraNeeded)
{
  CoinSimplexInt *COIN_RESTRICT numberInColumn = numberInColumnAddress_;
  CoinSimplexInt *COIN_RESTRICT numberInColumnPlus = numberInColumnPlusAddress_;
  CoinSimplexInt *COIN_RESTRICT nextColumn = nextColumnAddress_;
  CoinSimplexInt *COIN_RESTRICT lastColumn = lastColumnAddress_;
  CoinSimplexInt number = numberInColumnPlus[iColumn] + numberInColumn[iColumn];
  CoinBigIndex *COIN_RESTRICT startColumnU = startColumnUAddress_;
  CoinBigIndex space = lengthAreaU_ - lastEntryByColumnU_;
  CoinFactorizationDouble *COIN_RESTRICT elementU = elementUAddress_;
  CoinSimplexInt *COIN_RESTRICT indexRowU = indexRowUAddress_;

  if (space < extraNeeded + number + 4) {

    CoinSimplexInt iColumn = nextColumn[maximumRowsExtra_];
    CoinBigIndex put = 0;

    while (iColumn != maximumRowsExtra_) {

      CoinBigIndex get;
      CoinBigIndex getEnd;

      if (startColumnU[iColumn] >= 0) {
        get = startColumnU[iColumn]
          - numberInColumnPlus[iColumn];
        getEnd = startColumnU[iColumn] + numberInColumn[iColumn];
        startColumnU[iColumn] = put + numberInColumnPlus[iColumn];
      } else {
        get = -startColumnU[iColumn];
        getEnd = get + numberInColumn[iColumn];
        startColumnU[iColumn] = -put;
      }
      assert(put <= get);
      for (CoinBigIndex i = get; i < getEnd; i++) {
        indexRowU[put] = indexRowU[i];
        elementU[put] = elementU[i];
#if BOTH_WAYS
#endif
        put++;
      }
      iColumn = nextColumn[iColumn];
    } 
    numberCompressions_++;
    lastEntryByColumnU_ = put;
    space = lengthAreaU_ - put;
    if (extraNeeded == COIN_INT_MAX >> 1) {
      return true;
    }
    if (space < extraNeeded + number + 2) {

      status_ = -99;
      return false;
    }
  }
  CoinBigIndex put = lastEntryByColumnU_;
  CoinSimplexInt next = nextColumn[iColumn];
  CoinSimplexInt last = lastColumn[iColumn];

  if (extraNeeded || next != maximumRowsExtra_) {

    nextColumn[last] = next;
    lastColumn[next] = last;

    last = lastColumn[maximumRowsExtra_];
    nextColumn[last] = iColumn;
    lastColumn[maximumRowsExtra_] = iColumn;
    lastColumn[iColumn] = last;
    nextColumn[iColumn] = maximumRowsExtra_;

    CoinBigIndex get = startColumnU[iColumn]
      - numberInColumnPlus[iColumn];

    startColumnU[iColumn] = put + numberInColumnPlus[iColumn];
    CoinSimplexInt *indexRow = indexRowU;
    CoinFactorizationDouble *element = elementU;
    CoinSimplexInt i = 0;

    if ((number & 1) != 0) {
      element[put] = element[get];
      indexRow[put] = indexRow[get];
#if BOTH_WAYS
#endif
      i = 1;
    }
    for (; i < number; i += 2) {
      CoinFactorizationDouble value0 = element[get + i];
      CoinFactorizationDouble value1 = element[get + i + 1];
      CoinSimplexInt index0 = indexRow[get + i];
      CoinSimplexInt index1 = indexRow[get + i + 1];

      element[put + i] = value0;
      element[put + i + 1] = value1;
      indexRow[put + i] = index0;
      indexRow[put + i + 1] = index1;
#if BOTH_WAYS
#endif
    }
    put += number;
    get += number;

    lastEntryByColumnU_ = put + extraNeeded + 2;
    if (lastEntryByColumnU_ > lengthAreaU_) {

#ifdef CLP_DEVELOP
      printf("put %d, needed %d, start %d, length %d\n",
        put, extraNeeded, lastEntryByColumnU_,
        lengthAreaU_);
#endif
      return false;
    }
  } else {

    lastEntryByColumnU_ = startColumnU[last] + numberInColumn[last];
  }
  startColumnU[maximumRowsExtra_] = lastEntryByColumnU_;
  return true;
}

bool CoinAbcTypeFactorization::getRowSpace(CoinSimplexInt iRow,
  CoinSimplexInt extraNeeded)
{
  CoinSimplexInt *COIN_RESTRICT numberInRow = numberInRowAddress_;
  CoinSimplexInt number = numberInRow[iRow];
  CoinBigIndex *COIN_RESTRICT startRowU = startRowUAddress_;
  CoinBigIndex space = lengthAreaU_ - lastEntryByRowU_;
  CoinSimplexInt *COIN_RESTRICT nextRow = nextRowAddress_;
  CoinSimplexInt *COIN_RESTRICT lastRow = lastRowAddress_;
  CoinSimplexInt *COIN_RESTRICT indexColumnU = indexColumnUAddress_;

  if (space < extraNeeded + number + 2) {

    CoinSimplexInt iRow = nextRow[numberRows_];
    CoinBigIndex put = 0;

    while (iRow != numberRows_) {

      CoinBigIndex get = startRowU[iRow];
      CoinBigIndex getEnd = startRowU[iRow] + numberInRow[iRow];

      startRowU[iRow] = put;
      if (put > get) {

        status_ = -99;
        return false;
        ;
      }
      CoinBigIndex i;
      for (i = get; i < getEnd; i++) {
        indexColumnU[put] = indexColumnU[i];
#if BOTH_WAYS
#endif
        put++;
      }
      iRow = nextRow[iRow];
    } 
    numberCompressions_++;
    lastEntryByRowU_ = put;
    space = lengthAreaU_ - put;
    if (space < extraNeeded + number + 2) {

      status_ = -99;
      return false;
      ;
    }
  }
  CoinBigIndex put = lastEntryByRowU_;
  CoinSimplexInt next = nextRow[iRow];
  CoinSimplexInt last = lastRow[iRow];

  nextRow[last] = next;
  lastRow[next] = last;

  last = lastRow[numberRows_];
  nextRow[last] = iRow;
  lastRow[numberRows_] = iRow;
  lastRow[iRow] = last;
  nextRow[iRow] = numberRows_;

  CoinBigIndex get = startRowU[iRow];

  startRowU[iRow] = put;
  while (number) {
    number--;
    indexColumnU[put] = indexColumnU[get];
#if BOTH_WAYS
#endif
    put++;
    get++;
  } 

  lastEntryByRowU_ = put + extraNeeded + 4;
  return true;
}

void CoinAbcTypeFactorization::cleanup()
{
#ifdef ABC_USE_FUNCTION_POINTERS
#define PRINT_LEVEL 0
  if (PRINT_LEVEL) {
    printf("----------Start---------\n");
#if PRINT_LEVEL < 2
    double smallestP = COIN_DBL_MAX;
    int iPs = -1;
    double largestP = 0.0;
    int iP = -1;
    double largestL = 0.0;
    int iL = -1;
    double largestU = 0.0;
    int iU = -1;
#endif
    for (int i = 0; i < numberRows_; i++) {
#if PRINT_LEVEL > 1
      printf("%d permute %d pivotColumn %d pivotRegion %g\n", i, permuteAddress_[i],
        pivotColumnAddress_[i], pivotRegionAddress_[i]);
#else
      if (fabs(pivotRegionAddress_[i]) > largestP) {
        iP = i;
        largestP = fabs(pivotRegionAddress_[i]);
      }
      if (fabs(pivotRegionAddress_[i]) < smallestP) {
        iPs = i;
        smallestP = fabs(pivotRegionAddress_[i]);
      }
#endif
    }
    scatterStruct *COIN_RESTRICT scatterPointer = scatterUColumn();
    CoinFactorizationDouble *COIN_RESTRICT elementUColumnPlus = elementUColumnPlusAddress_;
    for (int i = 0; i < numberRows_; i++) {
      scatterStruct &COIN_RESTRICT scatter = scatterPointer[i];
      CoinSimplexInt number = scatter.number;
#if PRINT_LEVEL > 1
      printf("pivot %d offset %d number %d\n", i, scatter.offset, number);
#endif
      const CoinFactorizationDouble *COIN_RESTRICT area = elementUColumnPlus + scatter.offset;
      const CoinBigIndex *COIN_RESTRICT indices = reinterpret_cast< const CoinBigIndex * >(area + number);
#if PRINT_LEVEL > 1
      for (int j1 = 0; j1 < number; j1 += 5) {
        for (int j = j1; j < CoinMin(number, j1 + 5); j++)
          printf("(%d,%g) ", indices[j], area[j]);
        printf("\n");
      }
#else
      for (int j = 0; j < number; j++)
        if (fabs(area[j]) > largestU) {
          iU = i;
          largestU = fabs(area[j]);
        }
#endif
    }
    printf("----------LLL---------\n");
    CoinBigIndex *COIN_RESTRICT startColumnL = startColumnLAddress_;
    CoinSimplexInt *COIN_RESTRICT indexRowL = indexRowLAddress_;
    CoinFactorizationDouble *COIN_RESTRICT elementL = elementLAddress_;
    for (int i = 0; i < numberRows_; i++) {
      int number = startColumnL[i + 1] - startColumnL[i];
      if (number) {
#if PRINT_LEVEL > 1
        int *indices = indexRowL + startColumnL[i];
        printf("%d has %d elements\n", i, number);
        for (int j1 = 0; j1 < number; j1 += 5) {
          for (int j = j1; j < CoinMin(number, j1 + 5); j++)
            printf("(%d,%g) ", indices[j], elementL[j + startColumnL[i]]);
          printf("\n");
        }
#else
        for (int j = 0; j < number; j++) {
          if (fabs(elementL[j + startColumnL[i]]) > largestL) {
            iL = i;
            largestL = fabs(elementL[j + startColumnL[i]]);
          }
        }
#endif
      }
    }
#if PRINT_LEVEL < 2
    printf("smallest pivot %g at %d, largest %g at %d - largestL %g at %d largestU %g at %d\n", smallestP, iPs, largestP, iP, largestL, iL, largestU, iU);
#endif
    printf("----------End---------\n");
  }
#endif
#ifdef ABC_ORDERED_FACTORIZATION
  {

    CoinSimplexInt *COIN_RESTRICT permuteA = permuteAddress_ + maximumRowsExtra_ + 1;
    CoinSimplexInt *COIN_RESTRICT permuteB = permuteA + numberRows_;

    for (int i = 0; i < numberRows_; i++) {
      int iPermute = permuteAddress_[i];
      permuteA[i] = iPermute;
      permuteB[iPermute] = i;
      permuteAddress_[i] = i;
    }
    scatterStruct *COIN_RESTRICT scatterPointer = scatterUColumn();
    CoinFactorizationDouble *COIN_RESTRICT elementUColumnPlus = elementUColumnPlusAddress_;
    for (int i = 0; i < numberRows_; i++) {
      scatterStruct &COIN_RESTRICT scatter = scatterPointer[i];
      CoinSimplexInt number = scatter.number;

      CoinFactorizationDouble *COIN_RESTRICT area = elementUColumnPlus + scatter.offset;
      CoinBigIndex *COIN_RESTRICT indices = reinterpret_cast< CoinBigIndex * >(area + number);
      for (int j = 0; j < number; j++) {
        int iRow = indices[j];
        indices[j] = permuteA[iRow];
      }
    }
    CoinBigIndex *COIN_RESTRICT startColumnL = startColumnLAddress_;
    CoinSimplexInt *COIN_RESTRICT indexRowL = indexRowLAddress_;
    CoinFactorizationDouble *COIN_RESTRICT elementL = elementLAddress_;
    for (int i = 0; i < numberRows_; i++) {
      int number = startColumnL[i + 1] - startColumnL[i];
      if (number) {

        int *indices = indexRowL + startColumnL[i];
        for (int j = 0; j < number; j++) {
          int iRow = indices[j];
          indices[j] = permuteA[iRow];
        }
      }
    }

  }
#elif 0
#ifdef ABC_USE_FUNCTION_POINTERS
  {
    int sizeL = 0;
    int sizeU = 0;
    scatterStruct *COIN_RESTRICT scatterPointer = scatterUColumn();
    for (int i = 0; i < numberRows_; i++) {
      scatterStruct &COIN_RESTRICT scatter = scatterPointer[i];
      CoinSimplexInt number = scatter.number;
      sizeU += number;
    }
    CoinBigIndex *COIN_RESTRICT startColumnL = startColumnLAddress_;
    for (int i = 0; i < numberRows_; i++) {
      int number = startColumnL[i + 1] - startColumnL[i];
      if (number)
        sizeL += number;
    }
    printf("Unordered says %d L %d U\n", sizeL, sizeU);
  }
#endif
#endif

  markRow_.conditionalDelete();
  nextRowAddress_ = nextRow_.array();

  CoinSimplexInt *COIN_RESTRICT permute = permuteAddress_;
  permute[numberRows_] = 0;
#ifndef NDEBUG
  {
    if (numberGoodU_ < numberRows_)
      abort();
    char *mark = new char[numberRows_];
    memset(mark, 0, numberRows_);
    for (int i = 0; i < numberRows_; i++) {
      assert(permute[i] >= 0 && permute[i] < numberRows_);
      CoinSimplexInt k = permute[i];
      if (k < 0 || k >= numberRows_)
        printf("Bad a %d %d\n", i, k);
      assert(k >= 0 && k < numberRows_);
      if (mark[k] == 1)
        printf("Bad a %d %d\n", i, k);
      mark[k] = 1;
    }
    for (int i = 0; i < numberRows_; i++) {
      assert(mark[i] == 1);
      if (mark[i] != 1)
        printf("Bad b %d\n", i);
    }
    delete[] mark;
  }
#endif
  CoinSimplexInt *COIN_RESTRICT numberInColumnPlus = numberInColumnPlusAddress_;
  const CoinSimplexInt *COIN_RESTRICT pivotColumn = pivotColumnAddress_;
  CoinSimplexInt *COIN_RESTRICT pivotLOrder = firstCountAddress_; 
  CoinBigIndex *COIN_RESTRICT startColumnU = startColumnUAddress_;
  bool cleanCopy = false;
#if ABC_SMALL < 2
  assert(numberGoodU_ == numberRows_);
  if (numberGoodU_ == numberRows_) {
#ifndef ABC_USE_FUNCTION_POINTERS
    const CoinSimplexInt *COIN_RESTRICT numberInColumn = numberInColumnPlusAddress_;
    CoinFactorizationDouble *elementU = elementUAddress_;
    CoinFactorizationDouble *elementU2 = elementRowUAddress_;
    CoinSimplexInt *COIN_RESTRICT indexRowU = indexRowUAddress_;
    CoinSimplexInt *COIN_RESTRICT indexRowU2 = indexColumnUAddress_;

    CoinBigIndex size = 1;
    for (int i = 0; i < numberSlacks_; i++) {
      CoinSimplexInt iNext = pivotColumn[i];
      startColumnU[iNext] = 0;
      assert(!numberInColumn[iNext]);
    }
    for (int i = numberSlacks_; i < numberRows_; i++) {
      CoinSimplexInt iNext = pivotColumn[i];
      CoinSimplexInt number = numberInColumn[iNext];
      CoinBigIndex start = startColumnU[iNext] - number;
      startColumnU[iNext] = size;
      CoinAbcMemcpy(elementU2 + size, elementU + start, number);
      CoinAbcMemcpy(indexRowU2 + size, indexRowU + start, number);
      size += number;
    }

    elementU_.swap(elementRowU_);
    elementUAddress_ = elementU_.array();
    elementRowUAddress_ = elementRowU_.array();
    indexColumnU_.swap(indexRowU_);
    indexRowUAddress_ = indexRowU_.array();
    indexColumnUAddress_ = indexColumnU_.array();

    totalElements_ = size;
#else

    elementU_.swap(elementRowU_);
    elementUAddress_ = elementU_.array();
    elementRowUAddress_ = elementRowU_.array();
    totalElements_ = lastEntryByColumnUPlus_;
#endif
    cleanCopy = true;
  }
#endif
#ifndef ABC_USE_FUNCTION_POINTERS
  if (!cleanCopy) {
    getColumnSpace(0, COIN_INT_MAX >> 1); 

    totalElements_ = 0;
    for (int i = 0; i < numberRows_; i++) {
      CoinSimplexInt number = numberInColumnPlus[i];
      totalElements_ += number;
      startColumnU[i] -= number;
    }
  }
#endif

  numberInColumn_.swap(numberInColumnPlus_);
  numberInColumnAddress_ = numberInColumn_.array();
  numberInColumnPlusAddress_ = numberInColumnPlus_.array();
  CoinSimplexInt *COIN_RESTRICT numberInRow = numberInRowAddress_;
  CoinSimplexInt *COIN_RESTRICT numberInColumn = numberInColumnAddress_;
#if ABC_SMALL < 2
  numberInColumnPlus = numberInColumnPlusAddress_;
#endif

  lastEntryByRowU_ = totalElements_;

  CoinSimplexInt *COIN_RESTRICT back = firstCountAddress_ + numberRows_;
  CoinBigIndex *COIN_RESTRICT startRow = startRowUAddress_;
#ifndef ABC_USE_FUNCTION_POINTERS
  maximumU_ = startColumnU[numberRows_ - 1] + numberInColumn[numberRows_ - 1];
#else
  maximumU_ = lastEntryByColumnUPlus_;
#endif
#ifndef ABC_ORDERED_FACTORIZATION
  CoinFactorizationDouble *COIN_RESTRICT workArea = workAreaAddress_;
  CoinFactorizationDouble *COIN_RESTRICT pivotRegion = pivotRegionAddress_;
#else
  CoinSimplexInt *COIN_RESTRICT permuteA = permuteAddress_ + maximumRowsExtra_ + 1;

  scatterStruct *COIN_RESTRICT scatterPointer = scatterUColumn();
  scatterStruct *COIN_RESTRICT scatterPointerTemp = reinterpret_cast< scatterStruct * >(workAreaAddress_);
#endif
  for (CoinSimplexInt i = 0; i < numberRows_; i++) {
#ifndef ABC_ORDERED_FACTORIZATION
    CoinSimplexInt pivotOrder = permute[i];
    CoinSimplexInt columnOrder = pivotColumn[pivotOrder];
    workArea[i] = pivotRegion[pivotOrder];
    back[columnOrder] = i;
#else
    CoinSimplexInt pivotOrder = i;
    CoinSimplexInt columnOrder = pivotColumn[pivotOrder];
    int pivotOrder2 = permuteA[i];
    scatterPointerTemp[pivotOrder2] = scatterPointer[i];
    back[columnOrder] = i;
#endif
#ifndef ABC_USE_FUNCTION_POINTERS
    startRow[i] = startColumnU[columnOrder];
    numberInRow[i] = numberInColumn[columnOrder];
#endif
    pivotLOrder[pivotOrder] = i;
  }
#ifndef ABC_ORDERED_FACTORIZATION
  CoinAbcMemcpy(pivotRegion, workArea, numberRows_); 
#else
  CoinAbcMemcpy(scatterPointer, scatterPointerTemp, numberRows_);
#endif
#ifndef EARLY_FACTORIZE
  workArea_.conditionalDelete();
  workAreaAddress_ = NULL;
#endif
#ifndef ABC_USE_FUNCTION_POINTERS

  CoinAbcMemcpy(startColumnU, startRow, numberRows_);
  CoinAbcMemcpy(numberInColumn, numberInRow, numberRows_);
#endif
#if ABC_DENSE_CODE == 2
  if (numberDense_) {
    assert(numberDense_ < 30000);
    CoinFactorizationDouble *COIN_RESTRICT denseArea = denseAreaAddress_;
    CoinFactorizationDouble *COIN_RESTRICT denseRegion = denseArea + leadingDimension_ * numberDense_;
    CoinSimplexInt *COIN_RESTRICT densePermute = reinterpret_cast< CoinSimplexInt * >(denseRegion + FACTOR_CPU * numberDense_);
    short *COIN_RESTRICT forFtran = reinterpret_cast< short * >(densePermute + numberDense_);
    short *COIN_RESTRICT forBtran = forFtran + numberDense_;
    short *COIN_RESTRICT forFtran2 = forBtran + numberDense_;

    for (int i = 0; i < numberDense_; i++) {
      forBtran[i] = static_cast< short >(i);
      forFtran[i] = static_cast< short >(i);
    }
    for (int i = 0; i < numberDense_; i++) {
      int ip = densePermute[i];
      short temp = forBtran[i];
      forBtran[i] = forBtran[ip];
      forBtran[ip] = temp;
    }
    for (int i = numberDense_ - 1; i >= 0; i--) {
      int ip = densePermute[i];
      short temp = forFtran[i];
      forFtran[i] = forFtran[ip];
      forFtran[ip] = temp;
    }
#if ABC_SMALL < 3
    const CoinSimplexInt *COIN_RESTRICT pivotLBackwardOrder = permuteAddress_;
    int lastSparse = numberRows_ - numberDense_;
    forFtran -= lastSparse; 
    CoinFillN(forFtran2, numberRows_, static_cast< short >(-1));
    for (int i = 0; i < numberRows_; i++) {
      int jRow = pivotLBackwardOrder[i];
      if (jRow >= lastSparse) {
        short kRow = static_cast< short >(forFtran[jRow]);
        forFtran2[i] = kRow;
      }
    }
#endif
  }
#endif
  CoinAbcMemset0(numberInRow, numberRows_ + 1);
  if ((messageLevel_ & 8)) {
    std::cout << "        length of U " << totalElements_ << ", length of L " << lengthL_;
#if ABC_SMALL < 4
    if (numberDense_)
      std::cout << " plus " << numberDense_ * numberDense_ << " from " << numberDense_ << " dense rows";
#endif
    std::cout << std::endl;
  }
#if ABC_SMALL < 4

  totalElements_ += numberDense_ * numberDense_ + lengthL_;
#endif
#if ABC_SMALL < 2
  CoinSimplexInt *COIN_RESTRICT nextColumn = nextColumnAddress_;
  CoinSimplexInt *COIN_RESTRICT lastColumn = lastColumnAddress_;

#if ABC_SMALL >= 0
  if (maximumU_ > 10 * numberRows_ || numberRows_ < 200) {

    numberInColumnPlus_.conditionalDelete();
    numberInColumnPlusAddress_ = NULL;
    setNoGotRCopy();
  } else {
#endif
    setYesGotRCopy();
    for (int i = 0; i < numberRows_; i++) {
      lastColumn[i] = i - 1;
      nextColumn[i] = i + 1;
      numberInColumnPlus[i] = 0;
#if ABC_SMALL >= 0
    }
#endif
    nextColumn[numberRows_ - 1] = maximumRowsExtra_;
    lastColumn[maximumRowsExtra_] = numberRows_ - 1;
    nextColumn[maximumRowsExtra_] = 0;
    lastColumn[0] = maximumRowsExtra_;
  }
#endif
  numberU_ = numberGoodU_;
  numberL_ = numberGoodL_;

  CoinSimplexInt firstReal = numberSlacks_;

  CoinBigIndex *COIN_RESTRICT startColumnL = startColumnLAddress_;

  for (firstReal = numberSlacks_; firstReal < numberRows_; firstReal++) {
    if (startColumnL[firstReal + 1])
      break;
  }
  totalElements_ += startColumnL[numberRows_];
  baseL_ = firstReal;
  numberL_ -= firstReal;
  factorElements_ = totalElements_;

  CoinBigIndex space = lengthAreaL_ - lengthL_;
  CoinBigIndex spaceUsed = lengthL_ + lengthU_;

  CoinSimplexInt needed = (spaceUsed + numberRows_ - 1) / numberRows_;

  needed = needed * 2 * maximumPivots_;
  if (needed < 2 * numberRows_) {
    needed = 2 * numberRows_;
  }
  if (gotRCopy()) {

    space = space / 2;
  }
  elementRAddress_ = elementLAddress_ + lengthL_;
  indexRowRAddress_ = indexRowLAddress_ + lengthL_;
  if (space >= needed) {
    lengthR_ = 0;
    lengthAreaR_ = space;
  } else {
    lengthR_ = 0;
    lengthAreaR_ = space;
    if ((messageLevel_ & 4))
      std::cout << "Factorization may need some increasing area space"
                << std::endl;
    if (areaFactor_) {
      areaFactor_ *= 1.1;
    } else {
      areaFactor_ = 1.1;
    }
  }
  numberR_ = 0;
}

double
CoinAbcTypeFactorization::adjustedAreaFactor() const
{
  double factor = areaFactor_;
#if ABC_SMALL < 4
  if (numberDense_ && areaFactor_ > 1.0) {
    double dense = numberDense_;
    dense *= dense;
    double withoutDense = totalElements_ - dense + 1.0;
    factor *= 1.0 + dense / withoutDense;
  }
#endif
  return factor;
}

void CoinAbcTypeFactorization::checkConsistency()
{
  bool bad = false;

  CoinSimplexInt iRow;
  CoinBigIndex *startRowU = startRowUAddress_;
  CoinSimplexInt *numberInRow = numberInRowAddress_;
  CoinSimplexInt *numberInColumn = numberInColumnAddress_;
  CoinSimplexInt *indexColumnU = indexColumnUAddress_;
  CoinSimplexInt *indexRowU = indexRowUAddress_;
  CoinBigIndex *startColumnU = startColumnUAddress_;
  for (iRow = 0; iRow < numberRows_; iRow++) {
    if (numberInRow[iRow]) {
      CoinBigIndex startRow = startRowU[iRow];
      CoinBigIndex endRow = startRow + numberInRow[iRow];

      CoinBigIndex j;
      for (j = startRow; j < endRow; j++) {
        CoinSimplexInt iColumn = indexColumnU[j];
        CoinBigIndex startColumn = startColumnU[iColumn];
        CoinBigIndex endColumn = startColumn + numberInColumn[iColumn];
        bool found = false;

        CoinBigIndex k;
        for (k = startColumn; k < endColumn; k++) {
          if (indexRowU[k] == iRow) {
            found = true;
            break;
          }
        }
        if (!found) {
          bad = true;
          std::cout << "row " << iRow << " column " << iColumn << " Rows" << std::endl;
        }
      }
    }
  }
  CoinSimplexInt iColumn;
  for (iColumn = 0; iColumn < numberRows_; iColumn++) {
    if (numberInColumn[iColumn]) {
      CoinBigIndex startColumn = startColumnU[iColumn];
      CoinBigIndex endColumn = startColumn + numberInColumn[iColumn];

      CoinBigIndex j;
      for (j = startColumn; j < endColumn; j++) {
        CoinSimplexInt iRow = indexRowU[j];
        CoinBigIndex startRow = startRowU[iRow];
        CoinBigIndex endRow = startRow + numberInRow[iRow];
        bool found = false;

        CoinBigIndex k;
        for (k = startRow; k < endRow; k++) {
          if (indexColumnU[k] == iColumn) {
            found = true;
            break;
          }
        }
        if (!found) {
          bad = true;
          std::cout << "row " << iRow << " column " << iColumn << " Columns" << std::endl;
        }
      }
    }
  }
  if (bad) {
    abort();
  }
}

bool CoinAbcTypeFactorization::pivotOneOtherRow(CoinSimplexInt pivotRow,
  CoinSimplexInt pivotColumn)
{
  CoinSimplexInt *COIN_RESTRICT numberInRow = numberInRowAddress_;
  CoinSimplexInt *COIN_RESTRICT numberInColumn = numberInColumnAddress_;
  CoinSimplexInt *COIN_RESTRICT numberInColumnPlus = numberInColumnPlusAddress_;
  CoinSimplexInt COIN_RESTRICT numberInPivotRow = numberInRow[pivotRow] - 1;
  CoinBigIndex *COIN_RESTRICT startRowU = startRowUAddress_;
  CoinBigIndex *COIN_RESTRICT startColumnU = startColumnUAddress_;
  CoinBigIndex startColumn = startColumnU[pivotColumn];
  CoinBigIndex startRow = startRowU[pivotRow];
  CoinBigIndex endRow = startRow + numberInPivotRow + 1;

  CoinSimplexInt *COIN_RESTRICT nextRow = nextRowAddress_;
  CoinSimplexInt *COIN_RESTRICT lastRow = lastRowAddress_;
  CoinSimplexInt next = nextRow[pivotRow];
  CoinSimplexInt last = lastRow[pivotRow];

  nextRow[last] = next;
  lastRow[next] = last;
  lastRow[pivotRow] = -2;
#ifdef SMALL_PERMUTE
  int realPivotRow = fromSmallToBigRow_[pivotRow];

#endif
#ifdef SMALL_PERMUTE
  permuteAddress_[realPivotRow] = numberGoodU_;
#else
  permuteAddress_[pivotRow] = numberGoodU_;
#endif
  numberInRow[pivotRow] = 0;
#if ABC_SMALL < 2

  sparseThreshold_ = -2;
#endif

  CoinBigIndex l = lengthL_;

  if (l + 1 > lengthAreaL_) {

    if ((messageLevel_ & 4) != 0)
      std::cout << "more memory needed in middle of invert" << std::endl;
    return false;
  }

  CoinBigIndex *COIN_RESTRICT startColumnL = startColumnLAddress_;
  CoinFactorizationDouble *COIN_RESTRICT elementL = elementLAddress_;
  CoinSimplexInt *COIN_RESTRICT indexRowL = indexRowLAddress_;
  startColumnL[numberGoodL_] = l; 
  numberGoodL_++;
  startColumnL[numberGoodL_] = l + 1;
  lengthL_++;
  CoinFactorizationDouble pivotElement;
  CoinFactorizationDouble otherMultiplier;
  CoinSimplexInt otherRow;
  CoinSimplexInt *COIN_RESTRICT saveColumn = saveColumnAddress_;
  CoinFactorizationDouble *COIN_RESTRICT elementU = elementUAddress_;
  CoinSimplexInt *COIN_RESTRICT indexRowU = indexRowUAddress_;

  if (indexRowU[startColumn] == pivotRow) {
    pivotElement = elementU[startColumn];
    otherMultiplier = elementU[startColumn + 1];
    otherRow = indexRowU[startColumn + 1];
  } else {
    pivotElement = elementU[startColumn + 1];
    otherMultiplier = elementU[startColumn];
    otherRow = indexRowU[startColumn];
  }
  CoinSimplexInt numberSave = numberInRow[otherRow];
  CoinFactorizationDouble pivotMultiplier = 1.0 / pivotElement;

  CoinFactorizationDouble *COIN_RESTRICT pivotRegion = pivotRegionAddress_;
  pivotRegion[numberGoodU_] = pivotMultiplier;
  numberInColumn[pivotColumn] = 0;
  otherMultiplier = otherMultiplier * pivotMultiplier;
#ifdef SMALL_PERMUTE
  indexRowL[l] = fromSmallToBigRow_[otherRow];
#else
  indexRowL[l] = otherRow;
#endif
  elementL[l] = otherMultiplier;

  CoinBigIndex start = startRowU[otherRow];
  CoinBigIndex end = start + numberSave;
  CoinBigIndex where = start;
  CoinSimplexInt *COIN_RESTRICT indexColumnU = indexColumnUAddress_;

  while (indexColumnU[where] != pivotColumn) {
    where++;
  } 
  assert(where < end);
#if BOTH_WAYS
#endif
  end--;
  indexColumnU[where] = indexColumnU[end];
  CoinSimplexInt numberAdded = 0;
  CoinSimplexInt numberDeleted = 0;

  CoinSimplexInt j;
  const CoinSimplexInt *COIN_RESTRICT nextCount = this->nextCountAddress_;
  CoinSimplexInt *COIN_RESTRICT nextColumn = nextColumnAddress_;
  for (j = startRow; j < endRow; j++) {
    CoinSimplexInt iColumn = indexColumnU[j];

    if (iColumn != pivotColumn) {
      CoinBigIndex startColumn = startColumnU[iColumn];
      CoinSimplexInt numberInColumnIn = numberInColumn[iColumn];
      CoinBigIndex endColumn = startColumn + numberInColumnIn;
      CoinSimplexInt iRow = indexRowU[startColumn];
      CoinFactorizationDouble value = elementU[startColumn];
      CoinFactorizationDouble largest;
      bool foundOther = false;

      CoinBigIndex put = startColumn + 1;
      CoinBigIndex positionLargest = -1;
      CoinFactorizationDouble thisPivotValue = 0.0;
      CoinFactorizationDouble otherElement = 0.0;
      CoinFactorizationDouble nextValue = elementU[put];
      ;
      CoinSimplexInt nextIRow = indexRowU[put];

      if (iRow != pivotRow) {
        if (iRow != otherRow) {
          largest = fabs(value);
          elementU[put] = value;
          indexRowU[put] = iRow;
          positionLargest = put;
#if BOTH_WAYS
#endif
          put++;
          CoinBigIndex i;
          for (i = startColumn + 1; i < endColumn; i++) {
            iRow = nextIRow;
            value = nextValue;
            nextIRow = indexRowU[i + 1];
            nextValue = elementU[i + 1];
            if (iRow != pivotRow) {
              if (iRow != otherRow) {

                indexRowU[put] = iRow;
                elementU[put] = value;
                ;
#if BOTH_WAYS
#endif
                put++;
              } else {
                otherElement = value;
                foundOther = true;
              }
            } else {
              thisPivotValue = value;
            }
          }
        } else {
          otherElement = value;
          foundOther = true;

          largest = 0.0;
          CoinBigIndex i;
          for (i = startColumn + 1; i < endColumn; i++) {
            iRow = nextIRow;
            value = nextValue;
            nextIRow = indexRowU[i + 1];
            nextValue = elementU[i + 1];
            if (iRow != pivotRow) {

              indexRowU[put] = iRow;
              elementU[put] = value;
              ;
#if BOTH_WAYS
#endif
              CoinFactorizationDouble absValue = fabs(value);

              if (absValue > largest) {
                largest = absValue;
                positionLargest = put;
              }
              put++;
            } else {
              thisPivotValue = value;
            }
          }
        }
      } else {

        largest = 0.0;
        thisPivotValue = value;
        CoinBigIndex i;
        for (i = startColumn + 1; i < endColumn; i++) {
          iRow = nextIRow;
          value = nextValue;
          nextIRow = indexRowU[i + 1];
          nextValue = elementU[i + 1];
          if (iRow != otherRow) {

            indexRowU[put] = iRow;
            elementU[put] = value;
            ;
#if BOTH_WAYS
#endif
            CoinFactorizationDouble absValue = fabs(value);

            if (absValue > largest) {
              largest = absValue;
              positionLargest = put;
            }
            put++;
          } else {
            otherElement = value;
            foundOther = true;
          }
        }
      }

      elementU[startColumn] = thisPivotValue;
#ifdef SMALL_PERMUTE
      indexRowU[startColumn] = realPivotRow;
#else
      indexRowU[startColumn] = pivotRow;
#endif

      startColumn++;
      numberInColumn[iColumn] = put - startColumn;
      numberInColumnPlus[iColumn]++;
      startColumnU[iColumn]++;
      otherElement = otherElement - thisPivotValue * otherMultiplier;
      CoinFactorizationDouble absValue = fabs(otherElement);

      if (!TEST_LESS_THAN_TOLERANCE_REGISTER(absValue)) {
        if (!foundOther) {

          saveColumn[numberAdded++] = iColumn;
          CoinSimplexInt next = nextColumn[iColumn];
          CoinBigIndex space;

          space = startColumnU[next] - put - numberInColumnPlus[next];
          if (space <= 0) {

            CoinSimplexInt number = numberInColumn[iColumn];

            if (!getColumnSpace(iColumn, number + 1)) {
              return false;
            }

            positionLargest = positionLargest + startColumnU[iColumn] - startColumn;
            startColumn = startColumnU[iColumn];
            put = startColumn + number;
          }
        }
        elementU[put] = otherElement;
        indexRowU[put] = otherRow;
#if BOTH_WAYS
#endif
        if (absValue > largest) {
          largest = absValue;
          positionLargest = put;
        }
        put++;
      } else {
        if (foundOther) {
          numberDeleted++;

          CoinBigIndex where = start;

          while (indexColumnU[where] != iColumn) {
            where++;
          } 
          assert(where < end);
#if BOTH_WAYS
#endif
          end--;
          indexColumnU[where] = indexColumnU[end];
        }
      }
      CoinSimplexInt numberInColumnOut = put - startColumn;
      numberInColumn[iColumn] = numberInColumnOut;

      if (positionLargest >= 0) {
        value = elementU[positionLargest];
        iRow = indexRowU[positionLargest];
        elementU[positionLargest] = elementU[startColumn];
        indexRowU[positionLargest] = indexRowU[startColumn];
        elementU[startColumn] = value;
        indexRowU[startColumn] = iRow;
#if BOTH_WAYS
#endif
      }

      if (numberInColumnIn != numberInColumnOut && nextCount[iColumn + numberRows_] != -2) {

        modifyLink(iColumn + numberRows_, numberInColumnOut);
      }
    }
  }

  next = nextRow[otherRow];
  CoinBigIndex space;

  space = startRowU[next] - end;
  totalElements_ += numberAdded - numberDeleted;
  CoinSimplexInt number = numberAdded + (end - start);

  if (space < numberAdded) {
    numberInRow[otherRow] = end - start;
    if (!getRowSpace(otherRow, number)) {
      return false;
    }
    end = startRowU[otherRow] + end - start;
  }

  numberInRow[otherRow] = number;
  if (number != numberSave) {
    modifyLink(otherRow, number);
  }
  for (j = 0; j < numberAdded; j++) {
#if BOTH_WAYS
#endif
    indexColumnU[end++] = saveColumn[j];
  }
  lastEntryByRowU_ = CoinMax(end, lastEntryByRowU_);
  assert(lastEntryByRowU_ <= lengthAreaU_);

  deleteLink(pivotRow);
  deleteLink(pivotColumn + numberRows_);
  return true;
}

void CoinAbcTypeFactorization::almostDestructor()
{
  gutsOfDestructor(1);
}

void CoinAbcTypeFactorization::preProcess()
{
  CoinBigIndex numberElements = startColumnUAddress_[numberRows_ - 1]
    + numberInColumnAddress_[numberRows_ - 1];
  setNumberElementsU(numberElements);
}

double
CoinAbcTypeFactorization::preProcess3()
{
  CoinSimplexInt *COIN_RESTRICT numberInRow = numberInRowAddress_;
  CoinSimplexInt *COIN_RESTRICT numberInColumn = numberInColumnAddress_;
  CoinSimplexInt *COIN_RESTRICT numberInColumnPlus = numberInColumnPlusAddress_;
  CoinBigIndex *COIN_RESTRICT startRow = startRowUAddress_;
  CoinBigIndex *COIN_RESTRICT startColumn = startColumnUAddress_;

  totalElements_ = lengthU_;

  CoinZeroN(numberInColumn + numberRows_, maximumRowsExtra_ + 1 - numberRows_);
  CoinSimplexInt *COIN_RESTRICT lastRow = lastRowAddress_;
  CoinSimplexInt *COIN_RESTRICT nextRow = nextRowAddress_;

  CoinFillN(pivotColumnAddress_, numberRows_, -1);
  CoinZeroN(numberInColumnPlus, maximumRowsExtra_ + 1);
  CoinZeroN(lastRow, numberRows_);
  startColumn[maximumRowsExtra_] = lengthU_;
  lastEntryByColumnU_ = lengthU_;
  lastEntryByRowU_ = lengthU_;

  CoinBigIndex *COIN_RESTRICT startColumnL = startColumnLAddress_;
  CoinSimplexInt *COIN_RESTRICT indexRow = indexRowUAddress_;

  CoinFactorizationDouble *COIN_RESTRICT element = elementUAddress_;
  CoinFactorizationDouble *COIN_RESTRICT pivotRegion = pivotRegionAddress_;
  CoinSimplexInt *COIN_RESTRICT pivotColumn = pivotColumnAddress_;

  CoinFillN(pivotRegion, numberSlacks_, static_cast< CoinFactorizationDouble >(1.0));
  CoinZeroN(startColumnL, numberSlacks_ + 1);
  CoinZeroN(numberInColumn, numberSlacks_);
  CoinZeroN(numberInColumnPlus, numberSlacks_);
#ifdef ABC_USE_FUNCTION_POINTERS

  elementUColumnPlusAddress_ = elementRowU_.array();
  scatterStruct *COIN_RESTRICT scatter = scatterUColumn();
#if ABC_USE_FUNCTION_POINTERS
  extern scatterUpdate AbcScatterLowSubtract[9];
#endif
  lastEntryByColumnUPlus_ = 1;

#endif
  CoinSimplexInt *COIN_RESTRICT permute = permuteAddress_;
  CoinFillN(permute, numberRows_, -1);
  for (CoinSimplexInt iSlack = 0; iSlack < numberSlacks_; iSlack++) {

    CoinSimplexInt iRow = indexRow[iSlack];
    lastRow[iRow] = -2;

    permute[iRow] = iSlack;
    numberInRow[iRow] = 0;
    pivotColumn[iSlack] = iSlack;
#ifdef ABC_USE_FUNCTION_POINTERS
#if ABC_USE_FUNCTION_POINTERS
    scatter[iRow].functionPointer = AbcScatterLowSubtract[0];
#endif
    scatter[iRow].offset = 0;
    scatter[iRow].number = 0;
#endif
  }
  totalElements_ -= numberSlacks_;
  numberGoodU_ = numberSlacks_;
  numberGoodL_ = numberSlacks_;
#if CONVERTROW > 1
  CoinBigIndex *COIN_RESTRICT convertRowToColumn = convertRowToColumnUAddress_;
  CoinBigIndex *COIN_RESTRICT convertColumnToRow = convertColumnToRowUAddress_;
#endif
#ifdef SMALL_PERMUTE
  CoinSimplexInt *COIN_RESTRICT fromBigToSmallRow = reinterpret_cast< CoinSimplexInt * >(saveColumn_.array());
  CoinSimplexInt *COIN_RESTRICT indexColumn = indexColumnUAddress_;

  CoinSimplexInt *COIN_RESTRICT tempIndex = firstCountAddress_; 
  CoinFactorizationDouble *COIN_RESTRICT workArea = workAreaAddress_;

  int nSmall = 0;

  for (int i = 0; i < numberRows_; i++) {
    if (permute[i] >= 0) {

      fromBigToSmallRow[i] = -1;
    } else {

      fromBigToSmallRow[i] = nSmall;
      numberInRow[nSmall] = numberInRow[i];
      lastRow[nSmall] = lastRow[i];
      fromSmallToBigRow_[nSmall++] = i;
    }
  }
  nSmall = 0;
  for (CoinSimplexInt iColumn = numberSlacks_; iColumn < numberRows_; iColumn++) {
    CoinSimplexInt number = numberInColumn[iColumn];

    CoinBigIndex first = startColumn[iColumn];
    int saveFirst = first;
    fromSmallToBigColumn_[nSmall] = iColumn;
    CoinBigIndex largest = -1;
    CoinFactorizationDouble valueLargest = -1.0;
    CoinSimplexInt nOther = 0;
    CoinBigIndex end = first + number;
    for (CoinBigIndex k = first; k < end; k++) {
      CoinSimplexInt iRow = indexRow[k];
      assert(iRow < numberRowsSmall_);
      CoinFactorizationDouble value = element[k];
      if (permute[iRow] < 0) {
        CoinFactorizationDouble valueAbs = fabs(value);
        if (valueAbs > valueLargest) {
          valueLargest = valueAbs;
          largest = nOther;
        }
        iRow = fromBigToSmallRow[iRow];
        assert(iRow >= 0);
        tempIndex[nOther] = iRow;
        workArea[nOther++] = value;
      } else {
        indexRow[first] = iRow;
        element[first++] = value;
      }
    }
    CoinSimplexInt nMoved = first - saveFirst;
    numberInColumnPlus[nSmall] = nMoved;
    totalElements_ -= nMoved;
    startColumn[nSmall] = first;

    if (largest >= 0) {
      indexRow[first] = tempIndex[largest];
      element[first++] = workArea[largest];
    }
    for (CoinBigIndex k = 0; k < nOther; k++) {
      if (k != largest) {
        indexRow[first] = tempIndex[k];
        element[first++] = workArea[k];
      }
    }
    numberInColumn[nSmall] = first - startColumn[nSmall];
    nSmall++;
  }
  numberRowsSmall_ = nSmall;
  CoinAbcMemset0(numberInRow + nSmall, numberRows_ - nSmall);
  CoinAbcMemset0(numberInColumn + nSmall, numberRows_ - nSmall);
#endif

  CoinBigIndex i = 0;
  for (CoinSimplexInt iRow = 0; iRow < numberRowsSmall_; iRow++) {
    startRow[iRow] = i;
    CoinSimplexInt n = numberInRow[iRow];
#ifndef SMALL_PERMUTE
    numberInRow[iRow] = 0;
#endif
    i += n;
  }
  startRow[numberRows_] = lengthAreaU_; 
  double overallLargest = 1.0;
#ifndef SMALL_PERMUTE
  CoinSimplexInt *COIN_RESTRICT indexColumn = indexColumnUAddress_;

  CoinSimplexInt *COIN_RESTRICT tempIndex = firstCountAddress_; 
  CoinFactorizationDouble *COIN_RESTRICT workArea = workAreaAddress_;
  for (CoinSimplexInt iColumn = numberSlacks_; iColumn < numberRows_; iColumn++) {
    CoinSimplexInt number = numberInColumn[iColumn];

    CoinBigIndex first = startColumn[iColumn];
    CoinBigIndex largest = -1;
    CoinFactorizationDouble valueLargest = -1.0;
    CoinSimplexInt nOther = 0;
    CoinBigIndex end = first + number;
    for (CoinBigIndex k = first; k < end; k++) {
      CoinSimplexInt iRow = indexRow[k];
      assert(iRow < numberRowsSmall_);
      CoinFactorizationDouble value = element[k];
      if (!lastRow[iRow]) {
        numberInRow[iRow]++;
        CoinFactorizationDouble valueAbs = fabs(value);
        if (valueAbs > valueLargest) {
          valueLargest = valueAbs;
          largest = nOther;
        }
        tempIndex[nOther] = iRow;
        workArea[nOther++] = value;
#if CONVERTROW < 2
        CoinSimplexInt iLook = startRow[iRow];
        startRow[iRow] = iLook + 1;
        indexColumn[iLook] = iColumn;
#endif
#if BOTH_WAYS
#endif
      } else {
        indexRow[first] = iRow;
#if BOTH_WAYS
#endif
        element[first++] = value;
      }
    }
    overallLargest = CoinMax(overallLargest, valueLargest);
    CoinSimplexInt nMoved = first - startColumn[iColumn];
    numberInColumnPlus[iColumn] = nMoved;
    totalElements_ -= nMoved;
    startColumn[iColumn] = first;

    if (largest >= 0) {
#if CONVERTROW > 1
      int iRow = tempIndex[largest];
      indexRow[first] = iRow;
      CoinSimplexInt iLook = startRow[iRow];
      startRow[iRow] = iLook + 1;
      indexColumn[iLook] = iColumn;
      convertRowToColumn[iLook] = first;
      convertColumnToRow[first] = iLook;
#else
      indexRow[first] = tempIndex[largest];
#endif
#if BOTH_WAYS
#endif
      element[first++] = workArea[largest];
    }
    for (CoinBigIndex k = 0; k < nOther; k++) {
      if (k != largest) {
#if CONVERTROW > 1
        int iRow = tempIndex[k];
        indexRow[first] = iRow;
        CoinSimplexInt iLook = startRow[iRow];
        startRow[iRow] = iLook + 1;
        indexColumn[iLook] = iColumn;
        convertRowToColumn[iLook] = first;
        convertColumnToRow[first] = iLook;
#else
        indexRow[first] = tempIndex[k];
#endif
#if BOTH_WAYS
#endif
        element[first++] = workArea[k];
      }
    }
    numberInColumn[iColumn] = first - startColumn[iColumn];
  }
#else
#if CONVERTROW > 1
  for (CoinSimplexInt iColumn = 0; iColumn < numberRowsSmall_; iColumn++) {
    CoinSimplexInt number = numberInColumn[iColumn];
    CoinBigIndex first = startColumn[iColumn];
    CoinBigIndex end = first + number;
    for (CoinBigIndex k = first; k < end; k++) {
      CoinSimplexInt iRow = indexRow[k];
      CoinSimplexInt iLook = startRow[iRow];
      startRow[iRow] = iLook + 1;
      indexColumn[iLook] = iColumn;
      convertRowToColumn[iLook] = k;
      convertColumnToRow[k] = iLook;
    }
  }
#endif
#endif
  for (CoinSimplexInt iRow = numberRowsSmall_ - 1; iRow > 0; iRow--)
    startRow[iRow] = startRow[iRow - 1];
  startRow[0] = 0;

  CoinSimplexInt *firstCount = tempIndex;
  for (int i = 0; i < numberRows_ + 2; i++) {
    firstCount[i] = i - numberRows_ - 2;

  }
  startColumnLAddress_[0] = 0; 
  CoinSimplexInt *lastColumn = lastColumnAddress_;
  CoinSimplexInt *nextColumn = nextColumnAddress_;
#ifdef SMALL_PERMUTE

  for (CoinSimplexInt iColumn = 0; iColumn < numberRowsSmall_; iColumn++) {
    lastColumn[iColumn] = iColumn - 1;
    nextColumn[iColumn] = iColumn + 1;
    CoinSimplexInt number = numberInColumn[iColumn];
    addLink(iColumn + numberRows_, number);
  }
  lastColumn[maximumRowsExtra_] = numberRowsSmall_ - 1;
  nextColumn[maximumRowsExtra_] = 0;
  lastColumn[0] = maximumRowsExtra_;
  if (numberRowsSmall_)
    nextColumn[numberRowsSmall_ - 1] = maximumRowsExtra_;
#else
  lastColumn[maximumRowsExtra_] = numberRows_ - 1;
  for (CoinSimplexInt iColumn = 0; iColumn < numberRows_; iColumn++) {
    lastColumn[iColumn] = iColumn - 1;
    nextColumn[iColumn] = iColumn + 1;
    CoinSimplexInt number = numberInColumn[iColumn];
    addLink(iColumn + numberRows_, number);
  }
  nextColumn[maximumRowsExtra_] = 0;
  lastColumn[0] = maximumRowsExtra_;
  if (numberRows_)
    nextColumn[numberRows_ - 1] = maximumRowsExtra_;
#endif
  startColumn[maximumRowsExtra_] = lengthU_;
  lastEntryByColumnU_ = lengthU_;
  CoinSimplexInt jRow = numberRows_;
  for (CoinSimplexInt iRow = 0; iRow < numberRowsSmall_; iRow++) {
    CoinSimplexInt number = numberInRow[iRow];
    if (!lastRow[iRow]) {
      lastRow[iRow] = jRow;
      nextRow[jRow] = iRow;
      jRow = iRow;
      addLink(iRow, number);
    }
  }

  lastRow[numberRows_] = jRow;
  nextRow[jRow] = numberRows_;

  return overallLargest;
}

void CoinAbcTypeFactorization::postProcess(const CoinSimplexInt *sequence, CoinSimplexInt *pivotVariable)
{
  const CoinSimplexInt *COIN_RESTRICT back = firstCountAddress_ + numberRows_;
  if (pivotVariable) {
#ifndef NDEBUG
    CoinFillN(pivotVariable, numberRows_, -1);
#endif

    for (CoinSimplexInt i = 0; i < numberRows_; i++) {
      CoinSimplexInt k = sequence[i];
      CoinSimplexInt j = back[i];
      assert(pivotVariable[j] == -1);
      pivotVariable[j] = k;
    }
  }

  CoinAbcMemcpy(pivotColumnAddress_, permuteAddress_, numberRows_);

  checkSparse();

  pivotRegionAddress_[-1] = 0.0;
  pivotRegionAddress_[numberRows_] = 0.0;
  const CoinSimplexInt *COIN_RESTRICT pivotLOrder = this->pivotLOrderAddress_;
  CoinSimplexInt *COIN_RESTRICT pivotLinkedForwards = this->pivotLinkedForwardsAddress_;
  CoinSimplexInt *COIN_RESTRICT pivotLinkedBackwards = this->pivotLinkedBackwardsAddress_;
  CoinSimplexInt iThis = -1;
  for (int i = 0; i < numberSlacks_; i++) {
#ifndef ABC_ORDERED_FACTORIZATION
    CoinSimplexInt iNext = pivotLOrder[i];
#else
    CoinSimplexInt iNext = i;
#endif
    pivotLinkedForwards[iThis] = iNext;
    iThis = iNext;
  }
  lastSlack_ = iThis;
  for (int i = numberSlacks_; i < numberRows_; i++) {
#ifndef ABC_ORDERED_FACTORIZATION
    CoinSimplexInt iNext = pivotLOrder[i];
#else
    CoinSimplexInt iNext = i;
#endif
    pivotLinkedForwards[iThis] = iNext;
    iThis = iNext;
  }
  pivotLinkedForwards[iThis] = numberRows_;
  pivotLinkedForwards[numberRows_] = -1;
  iThis = numberRows_;
  for (int i = numberRows_ - 1; i >= 0; i--) {
#ifndef ABC_ORDERED_FACTORIZATION
    CoinSimplexInt iNext = pivotLOrder[i];
#else
    CoinSimplexInt iNext = i;
#endif
    pivotLinkedBackwards[iThis] = iNext;
    iThis = iNext;
  }
  pivotLinkedBackwards[iThis] = -1;
  pivotLinkedBackwards[-1] = -2;
#if 0 
  {
    char * test = new char[numberRows_];
    memset(test,0,numberRows_);
    CoinBigIndex *  COIN_RESTRICT startColumnL = startColumnLAddress_;
    CoinSimplexInt *  COIN_RESTRICT indexRowL = indexRowLAddress_;
    const CoinSimplexInt * COIN_RESTRICT pivotLOrder = pivotLOrderAddress_;

    for (int i=0;i<numberRows_;i++) {

#ifndef ABC_ORDERED_FACTORIZATION
      CoinSimplexInt iRow=pivotLOrder[i];
#else
      CoinSimplexInt iRow=i;
#endif
      assert(iRow>=0&&iRow<numberRows_);
      test[iRow]=1;
      CoinBigIndex start=startColumnL[i];
      CoinBigIndex end=startColumnL[i+1];
      for (CoinBigIndex j = start;j < end; j ++ ) {
	CoinSimplexInt jRow = indexRowL[j];
	assert (test[jRow]==0);
      }
    }
    delete [] test;
  }
#endif

  if (gotRCopy()) {

    CoinBigIndex *COIN_RESTRICT startR = startColumnRAddress_ + maximumPivots_ + 1;

    assert(startR + maximumRowsExtra_ + 1 <= firstCountAddress_ + CoinMax(5 * numberRows_, 4 * numberRows_ + 2 * maximumPivots_ + 4) + 2);
    CoinZeroN(startR, (maximumRowsExtra_ + 1));
  }
  goSparse2();
#ifndef ABC_USE_FUNCTION_POINTERS
  CoinSimplexInt *COIN_RESTRICT numberInColumn = numberInColumnAddress_;
  CoinBigIndex *COIN_RESTRICT startColumnU = startColumnUAddress_;
  CoinFactorizationDouble *COIN_RESTRICT elementU = elementUAddress_;
  CoinFactorizationDouble *COIN_RESTRICT pivotRegion = pivotRegionAddress_;
#else
  scatterStruct *COIN_RESTRICT scatterPointer = scatterUColumn();
  CoinFactorizationDouble *COIN_RESTRICT elementUColumnPlus = elementUColumnPlusAddress_;
#endif

#if ABC_SMALL < 2
  CoinSimplexInt *COIN_RESTRICT indexRowU = indexRowUAddress_;
  if (gotUCopy()) {
    CoinSimplexInt *COIN_RESTRICT numberInRow = numberInRowAddress_;
    CoinBigIndex *COIN_RESTRICT startRow = startRowUAddress_;
    CoinSimplexInt *COIN_RESTRICT nextRow = nextRowAddress_;
    CoinSimplexInt *COIN_RESTRICT lastRow = lastRowAddress_;
    CoinSimplexInt *COIN_RESTRICT indexColumnU = indexColumnUAddress_;
#ifndef ABC_USE_FUNCTION_POINTERS
    for (CoinSimplexInt i = 0; i < numberU_; i++) {
      CoinBigIndex start = startColumnU[i];
      CoinBigIndex end = start + numberInColumn[i];
      CoinBigIndex j;

      for (j = start; j < end; j++) {
        CoinSimplexInt iRow = indexRowU[j];
        numberInRow[iRow]++;
      }
    }
#else
    for (CoinSimplexInt i = 0; i < numberU_; i++) {
      scatterStruct &COIN_RESTRICT scatter = scatterPointer[i];
      CoinSimplexInt number = scatter.number;
      const CoinFactorizationDouble *COIN_RESTRICT area = elementUColumnPlus + scatter.offset;
      const CoinBigIndex *COIN_RESTRICT indices = reinterpret_cast< const CoinBigIndex * >(area + number);
      for (int j = 0; j < number; j++) {
        CoinSimplexInt iRow = indices[j];
        assert(iRow >= 0 && iRow < numberRows_);
        numberInRow[iRow]++;
      }
    }
#endif
    CoinFactorizationDouble *COIN_RESTRICT elementRow = elementRowUAddress_;
    CoinBigIndex j = 0;

    CoinSimplexInt iRow;
    for (iRow = 0; iRow < numberRows_; iRow++) {
      startRow[iRow] = j;
      j += numberInRow[iRow];
    }
    lastEntryByRowU_ = j;

#if CONVERTROW
    CoinBigIndex *COIN_RESTRICT convertRowToColumn = convertRowToColumnUAddress_;
#if CONVERTROW > 2
    CoinBigIndex *COIN_RESTRICT convertColumnToRow = convertColumnToRowUAddress_;
#endif
#endif
#ifndef ABC_USE_FUNCTION_POINTERS
    CoinZeroN(numberInRow, numberRows_ + 1);
    for (CoinSimplexInt i = 0; i < numberRows_; i++) {
      CoinBigIndex start = startColumnU[i];
      CoinBigIndex end = start + numberInColumn[i];
      CoinFactorizationDouble pivotValue = pivotRegion[i];
      CoinBigIndex j;
      for (j = start; j < end; j++) {
        CoinSimplexInt iRow = indexRowU[j];
        CoinSimplexInt iLook = numberInRow[iRow];
        numberInRow[iRow] = iLook + 1;
        CoinBigIndex k = startRow[iRow] + iLook;
        indexColumnU[k] = i;
#if CONVERTROW
        convertRowToColumn[k] = j - start;
#if CONVERTROW > 2
        convertColumnToRow[j] = k;
#endif
#endif

        elementU[j] *= pivotValue;
        elementRow[k] = elementU[j];
      }
    }
#else
    for (CoinSimplexInt i = 0; i < numberRows_; i++) {
      scatterStruct &COIN_RESTRICT scatter = scatterPointer[i];
      CoinSimplexInt number = scatter.number;
      const CoinFactorizationDouble *COIN_RESTRICT area = elementUColumnPlus + scatter.offset;
      const CoinBigIndex *COIN_RESTRICT indices = reinterpret_cast< const CoinBigIndex * >(area + number);
      for (int j = 0; j < number; j++) {
        CoinSimplexInt iRow = indices[j];
        CoinBigIndex k = startRow[iRow];
        startRow[iRow] = k + 1;
        indexColumnU[k] = i;
#if CONVERTROW
        convertRowToColumn[k] = j;
#if CONVERTROW > 2
        convertColumnToRow[j + startColumnU[i]] = k;
        abort(); 
#endif
#endif

        elementRow[k] = area[j];
      }
    }
#endif

    for (int j = numberRows_ - 1; j >= 0; j--) {
      lastRow[j] = j - 1;
      nextRow[j] = j + 1;
#ifdef ABC_USE_FUNCTION_POINTERS
      startRow[j + 1] = startRow[j];
#endif
    }
    startRow[0] = 0;
    nextRow[numberRows_ - 1] = numberRows_;
    lastRow[numberRows_] = numberRows_ - 1;
    nextRow[numberRows_] = 0;
    lastRow[0] = numberRows_;

  } else {
#endif
#ifndef ABC_USE_FUNCTION_POINTERS
    for (CoinSimplexInt i = 0; i < numberRows_; i++) {
      CoinBigIndex start = startColumnU[i];
      CoinBigIndex end = start + numberInColumn[i];
      CoinFactorizationDouble pivotValue = pivotRegion[i];
      CoinBigIndex j;
      for (j = start; j < end; j++) {

        elementU[j] *= pivotValue;
      }
    }
#endif
#if ABC_SMALL < 2
  }
#endif
#ifdef ABC_USE_FUNCTION_POINTERS
#if 0
  {
    CoinFactorizationDouble *  COIN_RESTRICT elementUColumnPlus = elementUColumnPlusAddress_;
    CoinSimplexInt * COIN_RESTRICT indexRow = indexRowUAddress_;
    CoinFactorizationDouble * COIN_RESTRICT element = elementUAddress_;
    CoinSimplexInt *  COIN_RESTRICT numberInColumn = numberInColumnAddress_;
    CoinBigIndex *  COIN_RESTRICT startColumnU = startColumnUAddress_;
    scatterStruct * COIN_RESTRICT scatter = scatterUColumn();
    extern scatterUpdate AbcScatterLowSubtract[9];
    extern scatterUpdate AbcScatterHighSubtract[4];
    for (int iRow=0;iRow<numberRows_;iRow++) {
      int number=scatter[iRow].number;
      CoinBigIndex offset = scatter[iRow].offset;
      CoinFactorizationDouble * COIN_RESTRICT area = elementUColumnPlus+offset;
      CoinSimplexInt * COIN_RESTRICT indices = reinterpret_cast<CoinSimplexInt *>(area+number);
      CoinSimplexInt * COIN_RESTRICT indices2 = indexRow+startColumnU[iRow];
      CoinFactorizationDouble * COIN_RESTRICT area2 = element+startColumnU[iRow];
      assert (number==numberInColumn[iRow]);
      if (number<9)
	assert (scatter[iRow].functionPointer==AbcScatterLowSubtract[number]);
      else
	assert (scatter[iRow].functionPointer==AbcScatterHighSubtract[number&3]);
      for (int i=0;i<number;i++) {
	assert (indices[i]==indices2[i]);
	assert (area[i]==area2[i]);
      }
    }
  }
#endif
#endif
}

void CoinAbcTypeFactorization::makeNonSingular(CoinSimplexInt *COIN_RESTRICT sequence)
{

  CoinSimplexInt *COIN_RESTRICT workArea = indexRowUAddress_;
  for (CoinSimplexInt i = 0; i < numberRows_; i++)
    workArea[i] = -1;
  const CoinSimplexInt *COIN_RESTRICT pivotColumn = pivotColumnAddress_;
  const CoinSimplexInt *COIN_RESTRICT permute = permuteAddress_;
  for (CoinSimplexInt i = 0; i < numberGoodU_; i++) {
    CoinSimplexInt iOriginal = pivotColumn[i];
    assert(iOriginal >= 0);
    workArea[iOriginal] = i;
  }
  CoinSimplexInt iRow = 0;
  for (CoinSimplexInt i = 0; i < numberRows_; i++) {
    if (workArea[i] == -1) {
      while (permute[iRow] >= 0)
        iRow++;
      assert(iRow < numberRows_);

      sequence[i] = iRow;
      iRow++;
    }
  }
}

void CoinAbcTypeFactorization::show_self() const
{
  CoinSimplexInt i;

  const CoinSimplexInt *pivotColumn = pivotColumnAddress_;
  for (i = 0; i < numberRows_; i++) {
    std::cout << "r " << i << " " << pivotColumn[i];
    std::cout << " " << permuteAddress_[i];
    std::cout << " " << pivotRegionAddress_[i];
    std::cout << std::endl;
  }
  for (i = 0; i < numberRows_; i++) {
    std::cout << "u " << i << " " << numberInColumnAddress_[i] << std::endl;
    CoinSimplexInt j;
    CoinSort_2(indexRowUAddress_ + startColumnUAddress_[i],
      indexRowUAddress_ + startColumnUAddress_[i] + numberInColumnAddress_[i],
      elementUAddress_ + startColumnUAddress_[i]);
    for (j = startColumnUAddress_[i]; j < startColumnUAddress_[i] + numberInColumnAddress_[i];
         j++) {
      assert(indexRowUAddress_[j] >= 0 && indexRowUAddress_[j] < numberRows_);
      assert(elementUAddress_[j] > -1.0e50 && elementUAddress_[j] < 1.0e50);
      std::cout << indexRowUAddress_[j] << " " << elementUAddress_[j] << std::endl;
    }
  }
  for (i = 0; i < numberRows_; i++) {
    std::cout << "l " << i << " " << startColumnLAddress_[i + 1] - startColumnLAddress_[i] << std::endl;
    CoinSort_2(indexRowLAddress_ + startColumnLAddress_[i],
      indexRowLAddress_ + startColumnLAddress_[i + 1],
      elementLAddress_ + startColumnLAddress_[i]);
    CoinSimplexInt j;
    for (j = startColumnLAddress_[i]; j < startColumnLAddress_[i + 1]; j++) {
      std::cout << indexRowLAddress_[j] << " " << elementLAddress_[j] << std::endl;
    }
  }
}

void CoinAbcTypeFactorization::sort() const
{
  CoinSimplexInt i;

  for (i = 0; i < numberRows_; i++) {
    CoinSort_2(indexRowUAddress_ + startColumnUAddress_[i],
      indexRowUAddress_ + startColumnUAddress_[i] + numberInColumnAddress_[i],
      elementUAddress_ + startColumnUAddress_[i]);
  }
  for (i = 0; i < numberRows_; i++) {
    CoinSort_2(indexRowLAddress_ + startColumnLAddress_[i],
      indexRowLAddress_ + startColumnLAddress_[i + 1],
      elementLAddress_ + startColumnLAddress_[i]);
  }
}
#ifdef CHECK_LINKS

void CoinAbcTypeFactorization::checkLinks(int type)
{

  return;
#if 0 
  if (numberRowsSmall_!=5698)
    return;
  ixxxxxx++;
  if (fromSmallToBigRow_[3195]==3581) {
    if (permuteAddress_[3581]>=0) {
      assert (numberInRowAddress_[3195]==0);
      CoinSimplexInt * numberInColumn = numberInColumnAddress_;
      CoinSimplexInt * COIN_RESTRICT indexRow = indexRowUAddress_;
      CoinBigIndex *  COIN_RESTRICT startColumn = startColumnUAddress_;
      for (int i=startColumn[1523];i<startColumn[1523]+numberInColumn[1523];i++)
	assert (indexRow[i]!=3195);
    }
    CoinSimplexInt *  COIN_RESTRICT numberInColumn = numberInColumnAddress_;
    CoinSimplexInt *  COIN_RESTRICT numberInColumnPlus = numberInColumnPlusAddress_;
    CoinSimplexInt *  COIN_RESTRICT nextColumn = nextColumnAddress_;
    CoinBigIndex *  COIN_RESTRICT startColumnU = startColumnUAddress_;
    CoinSimplexInt iColumn = nextColumn[maximumRowsExtra_];

    CoinBigIndex putEnd = -1;
    while ( iColumn != maximumRowsExtra_ ) {
      CoinBigIndex get;
      CoinBigIndex getEnd;
      get = startColumnU[iColumn] - numberInColumnPlus[iColumn];
      getEnd = startColumnU[iColumn] + numberInColumn[iColumn];
      assert (putEnd<=get);
      putEnd=getEnd;
      iColumn = nextColumn[iColumn];
    }
  }
  if (ixxxxxx>=7615900) {
    printf("trouble ahead\n");
  }
  return;
  if (ixxxxxx<406245)
    return;
#endif
  CoinSimplexInt *COIN_RESTRICT nextCount = this->nextCount();
  CoinSimplexInt *COIN_RESTRICT firstCount = this->firstCount();
  CoinSimplexInt *COIN_RESTRICT lastCount = this->lastCount();
  CoinSimplexInt *numberInColumn = numberInColumnAddress_;
  CoinSimplexInt *numberInRow = numberInRowAddress_;
  if (type) {
    int nBad = 0;
    CoinSimplexInt *COIN_RESTRICT indexRow = indexRowUAddress_;
    CoinSimplexInt *COIN_RESTRICT indexColumn = indexColumnUAddress_;
    CoinBigIndex *COIN_RESTRICT startColumn = startColumnUAddress_;
    CoinBigIndex *COIN_RESTRICT startRow = startRowUAddress_;
    for (int i = 0; i < numberRowsSmall_; i++) {
      assert(startRow[i] + numberInRow[i] <= lastEntryByRowU_);
    }
    return;
    CoinSimplexInt *COIN_RESTRICT nextRow = nextRow_.array();
    CoinSimplexInt *COIN_RESTRICT lastRow = lastRow_.array();
    int *counts = new int[3 * numberRows_ + 2];
    int *list1 = counts + numberRows_;
    int *list2 = list1 + numberRows_ + 1;
    {
      int lastStart = -1;
      int iRow = nextRow[numberRows_];
      memset(list1, 0, numberRowsSmall_ * sizeof(int));
      while (iRow >= 0 && iRow < numberRowsSmall_) {
        int iStart = startRow[iRow];
        assert(iStart >= lastStart);
        lastStart = iStart;
        list1[iRow] = 1;
        iRow = nextRow[iRow];
      }
      for (int i = 0; i < numberRowsSmall_; i++) {
        assert(list1[i] || !numberInRow[i]);
        assert(!list1[i] || numberInRow[i]);
      }
      memset(list1, 0, numberRowsSmall_ * sizeof(int));
#if 1
      CoinSimplexInt *COIN_RESTRICT nextColumn = nextColumn_.array();
      CoinSimplexInt *COIN_RESTRICT lastColumn = lastColumn_.array();
      lastStart = -1;
      int iColumn = nextColumn[maximumRowsExtra_];
      int nDone = 0;
      while (iColumn >= 0 && iColumn < numberRowsSmall_) {
        nDone++;
        int iStart = startColumn[iColumn];
        assert(iStart >= lastStart);
        lastStart = iStart;
        list1[iColumn] = 1;
        iColumn = nextColumn[iColumn];
      }
      int nEnd = 0;
      for (int i = 0; i < numberRowsSmall_; i++) {
        if (numberInColumn[i] && nEnd == maximumRowsExtra_)
          nEnd++;
      }
      if (nEnd > 1) {
        for (int i = 0; i < numberRowsSmall_; i++) {
          if (numberInColumn[i] && nEnd == maximumRowsExtra_)
            printf("%d points to end\n", i);
        }
        assert(nEnd <= 1);
      }

#endif
#if 0
      for (int i=0;i<numberRowsSmall_;i++) {
	assert (list1[i]||!numberInColumn[i]);
	assert (!list1[i]||numberInColumn[i]);

      }
#endif
    }
    CoinAbcMemset0(counts, numberRows_);
    for (int iColumn = 0; iColumn < numberRows_; iColumn++) {
      for (CoinBigIndex j = startColumn[iColumn]; j < startColumn[iColumn] + numberInColumn[iColumn]; j++) {
        int iRow = indexRow[j];
        counts[iRow]++;
      }
    }
    int nTotal1 = 0;
    for (int i = 0; i < numberRows_; i++) {
      if (numberInRow[i] != counts[i]) {
        printf("Row %d numberInRow %d counts %d\n", i, numberInRow[i], counts[i]);
        int n1 = 0;
        int n2 = 0;
        for (int j = startRow[i]; j < startRow[i] + numberInRow[i]; j++)
          list1[n1++] = indexColumn[j];
        for (int iColumn = 0; iColumn < numberRows_; iColumn++) {
          for (CoinBigIndex j = startColumn[iColumn]; j < startColumn[iColumn] + numberInColumn[iColumn]; j++) {
            int iRow = indexRow[j];
            if (i == iRow)
              list2[n2++] = iColumn;
          }
        }
        std::sort(list1, list1 + n1);
        std::sort(list2, list2 + n2);
        list1[n1] = numberRows_;
        list2[n2] = numberRows_;
        n1 = 1;
        n2 = 1;
        int iLook1 = list1[0];
        int iLook2 = list2[0];
        int xx = 0;
        while (iLook1 != numberRows_ || iLook2 != numberRows_) {
          if (iLook1 == iLook2) {
            printf(" (rc %d)", iLook1);
            iLook1 = list1[n1++];
            iLook2 = list2[n2++];
          } else if (iLook1 < iLook2) {
            printf(" (r %d)", iLook1);
            iLook1 = list1[n1++];
          } else {
            printf(" (c %d)", iLook2);
            iLook2 = list2[n2++];
          }
          xx++;
          if (xx == 10) {
            printf("\n");
            xx = 0;
          }
        }
        if (xx)
          printf("\n");
        nBad++;
      }
      nTotal1 += counts[i];
    }
    CoinAbcMemset0(counts, numberRows_);
    int nTotal2 = 0;
    for (int iRow = 0; iRow < numberRows_; iRow++) {
      for (CoinBigIndex j = startRow[iRow]; j < startRow[iRow] + numberInRow[iRow]; j++) {
        int iColumn = indexColumn[j];
        counts[iColumn]++;
      }
    }
    for (int i = 0; i < numberRows_; i++) {
      if (numberInColumn[i] != counts[i]) {
        printf("Column %d numberInColumn %d counts %d\n", i, numberInColumn[i], counts[i]);
        int n1 = 0;
        int n2 = 0;
        for (int j = startColumn[i]; j < startColumn[i] + numberInColumn[i]; j++)
          list1[n1++] = indexRow[j];
        for (int iRow = 0; iRow < numberRows_; iRow++) {
          for (CoinBigIndex j = startRow[iRow]; j < startRow[iRow] + numberInRow[iRow]; j++) {
            int iColumn = indexColumn[j];
            if (i == iColumn)
              list2[n2++] = iRow;
          }
        }
        std::sort(list1, list1 + n1);
        std::sort(list2, list2 + n2);
        list1[n1] = numberRows_;
        list2[n2] = numberRows_;
        n1 = 1;
        n2 = 1;
        int iLook1 = list1[0];
        int iLook2 = list2[0];
        int xx = 0;
        while (iLook1 != numberRows_ || iLook2 != numberRows_) {
          if (iLook1 == iLook2) {
            printf(" (rc %d)", iLook1);
            iLook1 = list1[n1++];
            iLook2 = list2[n2++];
          } else if (iLook1 < iLook2) {
            printf(" (c %d)", iLook1);
            iLook1 = list1[n1++];
          } else {
            printf(" (r %d)", iLook2);
            iLook2 = list2[n2++];
          }
          xx++;
          if (xx == 10) {
            printf("\n");
            xx = 0;
          }
        }
        if (xx)
          printf("\n");
        nBad++;
      }
      nTotal2 += counts[i];
    }
    delete[] counts;
    assert(!nBad);
  }
  char *mark = new char[2 * numberRows_];
  memset(mark, 0, 2 * numberRows_);
  for (int iCount = 0; iCount < numberRowsSmall_ + 1; iCount++) {
    int next = firstCount[iCount];
#define VERBOSE 0
#if VERBOSE
    int count = 0;
#endif
    while (next >= 0) {
#if VERBOSE
      count++;
      if (iCount <= VERBOSE) {
        if (next < numberRows_)
#ifdef SMALL_PERMUTE
          printf("R%d\n", fromSmallToBigRow_[next]);
#else
          printf("R%d\n", next);
#endif
        else
          printf("C%d\n", next - numberRows_);
      }
#endif
      assert(!mark[next]);
      mark[next] = 1;
      if (next < numberRows_)
        assert(numberInRow[next] == iCount);
      else
        assert(numberInColumn[next - numberRows_] == iCount);
      int next2 = next;
      assert(next != nextCount[next]);
      next = nextCount[next];
      if (next >= 0)
        assert(next2 == lastCount[next]);
    }
#if VERBOSE
    if (count)
      printf("%d items have count %d\n", count, iCount);
#endif
  }
  delete[] mark;
}
#endif
#endif
// Copyright (C) 2002, International Business Machines
// Corporation and others, Copyright (C) 2012, FasterCoin.  All Rights Reserved.
// This code is licensed under the terms of the Eclipse Public License (EPL).
#ifdef ABC_JUST_ONE_FACTORIZATION
#include "CoinAbcCommonFactorization.hpp"
#define CoinAbcTypeFactorization CoinAbcBaseFactorization
#define ABC_SMALL -1
#include "CoinAbcBaseFactorization.hpp"
#endif
#ifdef CoinAbcTypeFactorization
#include "CoinIndexedVector.hpp"
#include "CoinHelperFunctions.hpp"
#include "CoinAbcHelperFunctions.hpp"
#include "CoinPackedMatrix.hpp"
#include "CoinFinite.hpp"
#define _mm256_broadcast_sd(x) static_cast< __m256d >(__builtin_ia32_vbroadcastsd256(x))
#define _mm256_load_pd(x) *(__m256d *)(x)
#define _mm256_store_pd (s, x) * ((__m256d *)s) = x
//:class CoinAbcTypeFactorization.  Deals with Factorization and Updates
//  CoinAbcTypeFactorization.  Constructor
CoinAbcTypeFactorization::CoinAbcTypeFactorization()
  : CoinAbcAnyFactorization()
{
  gutsOfInitialize(7);
}

/// Copy constructor
CoinAbcTypeFactorization::CoinAbcTypeFactorization(const CoinAbcTypeFactorization &other)
  : CoinAbcAnyFactorization(other)
{
  gutsOfInitialize(3);
  gutsOfCopy(other);
}
/// Clone
CoinAbcAnyFactorization *
CoinAbcTypeFactorization::clone() const
{
  return new CoinAbcTypeFactorization(*this);
}
/// Copy constructor
CoinAbcTypeFactorization::CoinAbcTypeFactorization(const CoinFactorization & /*other*/)
  : CoinAbcAnyFactorization()
{
  gutsOfInitialize(3);
  //gutsOfCopy(other);
  abort();
}
/// The real work of constructors etc
void CoinAbcTypeFactorization::gutsOfDestructor(CoinSimplexInt)
{
  numberCompressions_ = 0;
  numberRows_ = 0;
  numberRowsExtra_ = 0;
  maximumRowsExtra_ = 0;
  numberGoodU_ = 0;
  numberGoodL_ = 0;
  totalElements_ = 0;
  factorElements_ = 0;
  status_ = -1;
  numberSlacks_ = 0;
  lastSlack_ = 0;
  numberU_ = 0;
  maximumU_ = 0;
  lengthU_ = 0;
  lastEntryByColumnU_ = 0;
  lastEntryByRowU_ = 0;
  lengthAreaU_ = 0;
  numberL_ = 0;
  baseL_ = 0;
  lengthL_ = 0;
  lengthAreaL_ = 0;
  numberR_ = 0;
  lengthR_ = 0;
  lengthAreaR_ = 0;
#if ABC_SMALL < 4
  numberDense_ = 0;
#endif
}
#if FACTORIZATION_STATISTICS
extern double denseThresholdX;
#endif
// type - 1 bit tolerances etc, 2 rest
void CoinAbcTypeFactorization::gutsOfInitialize(CoinSimplexInt type)
{
  if ((type & 2) != 0) {
    numberCompressions_ = 0;
    numberRows_ = 0;
    numberRowsExtra_ = 0;
    maximumRowsExtra_ = 0;
    numberGoodU_ = 0;
    numberGoodL_ = 0;
    totalElements_ = 0;
    factorElements_ = 0;
    status_ = -1;
    numberPivots_ = 0;
    numberSlacks_ = 0;
    lastSlack_ = 0;
    numberU_ = 0;
    maximumU_ = 0;
    lengthU_ = 0;
    lastEntryByColumnU_ = 0;
    lastEntryByRowU_ = 0;
    lengthAreaU_ = 0;
#ifdef ABC_USE_FUNCTION_POINTERS
    lengthAreaUPlus_ = 0;
#endif
    numberL_ = 0;
    baseL_ = 0;
    lengthL_ = 0;
    lengthAreaL_ = 0;
    numberR_ = 0;
    lengthR_ = 0;
    lengthAreaR_ = 0;
    elementRAddress_ = NULL;
    indexRowRAddress_ = NULL;
#if ABC_SMALL < 2
    // always switch off sparse
    sparseThreshold_ = 0;
#endif
    state_ = 0;
    // Maximum rows (ever)
    maximumRows_ = 0;
    // Rows first time nonzero
    initialNumberRows_ = 0;
    // Maximum maximum pivots
    maximumMaximumPivots_ = 0;
#if ABC_SMALL < 4
    numberDense_ = 0;
#endif
  }
  // after 2
  if ((type & 1) != 0) {
    areaFactor_ = 0.0;
    pivotTolerance_ = 1.0e-1;
    numberDense_ = 0;
#ifndef USE_FIXED_ZERO_TOLERANCE
    zeroTolerance_ = 1.0e-13;
#else
    zeroTolerance_ = pow(0.5, 43);
#endif
    messageLevel_ = 0;
    maximumPivots_ = 200;
    maximumMaximumPivots_ = 200;
    numberTrials_ = 4;
    relaxCheck_ = 1.0;
#if ABC_SMALL < 4
#if ABC_DENSE_CODE > 0
    //denseThreshold_=4;//16; //31;
    denseThreshold_ = 71;
#else
    denseThreshold_ = -16;
#endif
#if FACTORIZATION_STATISTICS
    denseThreshold_ = denseThresholdX;
#endif
    //denseThreshold_=0; // temp (? ABC_PARALLEL)
#endif
  }
#if ABC_SMALL < 4
  //denseThreshold_=10000;
#endif
  if ((type & 4) != 0) {
#if COIN_BIG_DOUBLE == 1
    for (int i = 0; i < FACTOR_CPU; i++) {
      longArray_[i].switchOn(4);
      associatedVector_[i] = NULL;
    }
#endif
    pivotColumn_.switchOn();
    permute_.switchOn();
    startRowU_.switchOn();
    numberInRow_.switchOn();
    numberInColumn_.switchOn();
    numberInColumnPlus_.switchOn();
#ifdef ABC_USE_FUNCTION_POINTERS
    scatterUColumn_.switchOn();
#endif
    firstCount_.switchOn();
    nextColumn_.switchOn();
    lastColumn_.switchOn();
    nextRow_.switchOn();
    lastRow_.switchOn();
    saveColumn_.switchOn();
    markRow_.switchOn();
    indexColumnU_.switchOn();
    pivotRegion_.switchOn();
    elementU_.switchOn();
    indexRowU_.switchOn();
    startColumnU_.switchOn();
#if CONVERTROW
    convertRowToColumnU_.switchOn();
#if CONVERTROW > 1
    convertColumnToRowU_.switchOn();
#endif
#endif
#if ABC_SMALL < 2
    elementRowU_.switchOn();
#endif
    elementL_.switchOn();
    indexRowL_.switchOn();
    startColumnL_.switchOn();
#if ABC_SMALL < 4
    denseArea_.switchOn(7);
#endif
    workArea_.switchOn();
    workArea2_.switchOn();
#if ABC_SMALL < 2
    startRowL_.switchOn();
    indexColumnL_.switchOn();
    elementByRowL_.switchOn();
    sparse_.switchOn();

    // Below are all to collect
    ftranCountInput_ = 0.0;
    ftranCountAfterL_ = 0.0;
    ftranCountAfterR_ = 0.0;
    ftranCountAfterU_ = 0.0;
    ftranFTCountInput_ = 0.0;
    ftranFTCountAfterL_ = 0.0;
    ftranFTCountAfterR_ = 0.0;
    ftranFTCountAfterU_ = 0.0;
    btranCountInput_ = 0.0;
    btranCountAfterU_ = 0.0;
    btranCountAfterR_ = 0.0;
    btranCountAfterL_ = 0.0;
    ftranFullCountInput_ = 0.0;
    ftranFullCountAfterL_ = 0.0;
    ftranFullCountAfterR_ = 0.0;
    ftranFullCountAfterU_ = 0.0;
    btranFullCountInput_ = 0.0;
    btranFullCountAfterL_ = 0.0;
    btranFullCountAfterR_ = 0.0;
    btranFullCountAfterU_ = 0.0;
#if FACTORIZATION_STATISTICS
    ftranTwiddleFactor1_ = 1.0;
    ftranFTTwiddleFactor1_ = 1.0;
    btranTwiddleFactor1_ = 1.0;
    ftranFullTwiddleFactor1_ = 1.0;
    btranFullTwiddleFactor1_ = 1.0;
    ftranTwiddleFactor2_ = 1.0;
    ftranFTTwiddleFactor2_ = 1.0;
    btranTwiddleFactor2_ = 1.0;
    ftranFullTwiddleFactor2_ = 1.0;
    btranFullTwiddleFactor2_ = 1.0;
#endif
    // We can roll over factorizations
    numberFtranCounts_ = 0;
    numberFtranFTCounts_ = 0;
    numberBtranCounts_ = 0;
    numberFtranFullCounts_ = 0;
    numberFtranFullCounts_ = 0;

    // While these are averages collected over last
    ftranAverageAfterL_ = INITIAL_AVERAGE;
    ftranAverageAfterR_ = INITIAL_AVERAGE;
    ftranAverageAfterU_ = INITIAL_AVERAGE;
    ftranFTAverageAfterL_ = INITIAL_AVERAGE;
    ftranFTAverageAfterR_ = INITIAL_AVERAGE;
    ftranFTAverageAfterU_ = INITIAL_AVERAGE;
    btranAverageAfterU_ = INITIAL_AVERAGE;
    btranAverageAfterR_ = INITIAL_AVERAGE;
    btranAverageAfterL_ = INITIAL_AVERAGE;
    ftranFullAverageAfterL_ = INITIAL_AVERAGE;
    ftranFullAverageAfterR_ = INITIAL_AVERAGE;
    ftranFullAverageAfterU_ = INITIAL_AVERAGE;
    btranFullAverageAfterL_ = INITIAL_AVERAGE;
    btranFullAverageAfterR_ = INITIAL_AVERAGE;
    btranFullAverageAfterU_ = INITIAL_AVERAGE;
#endif
  }
}

//  ~CoinAbcTypeFactorization.  Destructor
CoinAbcTypeFactorization::~CoinAbcTypeFactorization()
{
  gutsOfDestructor();
}
//  =
CoinAbcTypeFactorization &CoinAbcTypeFactorization::operator=(const CoinAbcTypeFactorization &other)
{
  if (this != &other) {
    gutsOfDestructor();
    CoinAbcAnyFactorization::operator=(other);
    gutsOfInitialize(3);
    gutsOfCopy(other);
  }
  return *this;
}
void CoinAbcTypeFactorization::gutsOfCopy(const CoinAbcTypeFactorization &other)
{
#ifdef ABC_USE_FUNCTION_POINTERS
  elementU_.allocate(other.elementU_, other.lengthAreaUPlus_ * CoinSizeofAsInt(CoinFactorizationDouble));
#else
  elementU_.allocate(other.elementU_, other.lengthAreaU_ * CoinSizeofAsInt(CoinFactorizationDouble));
#endif
  indexRowU_.allocate(other.indexRowU_, (other.lengthAreaU_ + 1) * CoinSizeofAsInt(CoinSimplexInt));
  elementL_.allocate(other.elementL_, other.lengthAreaL_ * CoinSizeofAsInt(CoinFactorizationDouble));
  indexRowL_.allocate(other.indexRowL_, other.lengthAreaL_ * CoinSizeofAsInt(CoinSimplexInt));
  startColumnL_.allocate(other.startColumnL_, (other.numberRows_ + 1) * CoinSizeofAsInt(CoinBigIndex));
  pivotRegion_.allocate(other.pivotRegion_, (other.numberRows_ + 2) * CoinSizeofAsInt(CoinFactorizationDouble));
#ifndef ABC_ORDERED_FACTORIZATION
  permute_.allocate(other.permute_, (other.maximumRowsExtra_ + 1) * CoinSizeofAsInt(CoinSimplexInt));
#else
  //temp
  permute_.allocate(other.permute_, (other.maximumRowsExtra_ + 2 * numberRows_ + 1) * CoinSizeofAsInt(CoinSimplexInt));
#endif
  firstCount_.allocate(other.firstCount_,
    (CoinMax(5 * numberRows_, 4 * numberRows_ + 2 * maximumPivots_ + 4) + 2)
      * CoinSizeofAsInt(CoinSimplexInt));
  nextCountAddress_ = nextCount();
  lastCountAddress_ = lastCount();
  startColumnU_.allocate(other.startColumnU_, (other.numberRows_ + 1) * CoinSizeofAsInt(CoinBigIndex));
  numberInColumn_.allocate(other.numberInColumn_, (other.numberRows_ + 1) * CoinSizeofAsInt(CoinSimplexInt));
#if COIN_BIG_DOUBLE == 1
  for (int i = 0; i < FACTOR_CPU; i++)
    longArray_[i].allocate(other.longArray_[i], (other.maximumRowsExtra_ + 1) * CoinSizeofAsInt(long double));
#endif
  pivotColumn_.allocate(other.pivotColumn_, (other.maximumRowsExtra_ + 1) * CoinSizeofAsInt(CoinSimplexInt));
  nextColumn_.allocate(other.nextColumn_, (other.maximumRowsExtra_ + 1) * CoinSizeofAsInt(CoinSimplexInt));
  lastColumn_.allocate(other.lastColumn_, (other.maximumRowsExtra_ + 1) * CoinSizeofAsInt(CoinSimplexInt));
  nextRow_.allocate(other.nextRow_, (other.numberRows_ + 1) * CoinSizeofAsInt(CoinSimplexInt));
  lastRow_.allocate(other.lastRow_, (other.numberRows_ + 1) * CoinSizeofAsInt(CoinSimplexInt));
  indexColumnU_.allocate(other.indexColumnU_, (other.lengthAreaU_ + 1) * CoinSizeofAsInt(CoinSimplexInt));
#if CONVERTROW
  convertRowToColumnU_.allocate(other.convertRowToColumnU_, other.lengthAreaU_ * CoinSizeofAsInt(CoinBigIndex));
  const CoinBigIndex *convertUOther = other.convertRowToColumnUAddress_;
#if CONVERTROW > 1
  convertColumnToRowU_.allocate(other.convertColumnToRowU_, other.lengthAreaU_ * CoinSizeofAsInt(CoinBigIndex));
#if CONVERTROW > 2
  const CoinBigIndex *convertUOther2 = other.convertColumnToRowUAddress_;
#endif
#endif
#endif
#if ABC_SMALL < 2
  const CoinFactorizationDouble *elementRowUOther = other.elementRowUAddress_;
#if COIN_ONE_ETA_COPY
  if (elementRowUOther) {
#endif
#ifdef ABC_USE_FUNCTION_POINTERS
    elementRowU_.allocate(other.elementRowU_, other.lengthAreaUPlus_ * CoinSizeofAsInt(CoinFactorizationDouble));
#else
  elementRowU_.allocate(other.elementRowU_, other.lengthAreaU_ * CoinSizeofAsInt(CoinFactorizationDouble));
#endif
    startRowU_.allocate(other.startRowU_, (other.numberRows_ + 1) * CoinSizeofAsInt(CoinBigIndex));
    numberInRow_.allocate(other.numberInRow_, (other.numberRows_ + 1) * CoinSizeofAsInt(CoinSimplexInt));
#if COIN_ONE_ETA_COPY
  }
#endif
  if (other.sparseThreshold_) {
    elementByRowL_.allocate(other.elementByRowL_, other.lengthAreaL_);
    indexColumnL_.allocate(other.indexColumnL_, other.lengthAreaL_);
    startRowL_.allocate(other.startRowL_, other.numberRows_ + 1);
  }
#endif
  numberTrials_ = other.numberTrials_;
  relaxCheck_ = other.relaxCheck_;
  numberSlacks_ = other.numberSlacks_;
  lastSlack_ = other.lastSlack_;
  numberU_ = other.numberU_;
  maximumU_ = other.maximumU_;
  lengthU_ = other.lengthU_;
  lastEntryByColumnU_ = other.lastEntryByColumnU_;
  lastEntryByRowU_ = other.lastEntryByRowU_;
  lengthAreaU_ = other.lengthAreaU_;
#ifdef ABC_USE_FUNCTION_POINTERS
  lengthAreaUPlus_ = other.lengthAreaUPlus_;
#endif
  numberL_ = other.numberL_;
  baseL_ = other.baseL_;
  lengthL_ = other.lengthL_;
  lengthAreaL_ = other.lengthAreaL_;
  numberR_ = other.numberR_;
  lengthR_ = other.lengthR_;
  lengthAreaR_ = other.lengthAreaR_;
  pivotTolerance_ = other.pivotTolerance_;
  zeroTolerance_ = other.zeroTolerance_;
  areaFactor_ = other.areaFactor_;
  numberRows_ = other.numberRows_;
  numberRowsExtra_ = other.numberRowsExtra_;
  maximumRowsExtra_ = other.maximumRowsExtra_;
  maximumPivots_ = other.maximumPivots_;
  numberGoodU_ = other.numberGoodU_;
  numberGoodL_ = other.numberGoodL_;
  numberPivots_ = other.numberPivots_;
  messageLevel_ = other.messageLevel_;
  totalElements_ = other.totalElements_;
  factorElements_ = other.factorElements_;
  status_ = other.status_;
#if ABC_SMALL < 2
  //doForrestTomlin_ = other.doForrestTomlin_;
  ftranCountInput_ = other.ftranCountInput_;
  ftranCountAfterL_ = other.ftranCountAfterL_;
  ftranCountAfterR_ = other.ftranCountAfterR_;
  ftranCountAfterU_ = other.ftranCountAfterU_;
  ftranFTCountInput_ = other.ftranFTCountInput_;
  ftranFTCountAfterL_ = other.ftranFTCountAfterL_;
  ftranFTCountAfterR_ = other.ftranFTCountAfterR_;
  ftranFTCountAfterU_ = other.ftranFTCountAfterU_;
  btranCountInput_ = other.btranCountInput_;
  btranCountAfterU_ = other.btranCountAfterU_;
  btranCountAfterR_ = other.btranCountAfterR_;
  btranCountAfterL_ = other.btranCountAfterL_;
  ftranFullCountInput_ = other.ftranFullCountInput_;
  ftranFullCountAfterL_ = other.ftranFullCountAfterL_;
  ftranFullCountAfterR_ = other.ftranFullCountAfterR_;
  ftranFullCountAfterU_ = other.ftranFullCountAfterU_;
  btranFullCountInput_ = other.btranFullCountInput_;
  btranFullCountAfterL_ = other.btranFullCountAfterL_;
  btranFullCountAfterR_ = other.btranFullCountAfterR_;
  btranFullCountAfterU_ = other.btranFullCountAfterU_;
  numberFtranCounts_ = other.numberFtranCounts_;
  numberFtranFTCounts_ = other.numberFtranFTCounts_;
  numberBtranCounts_ = other.numberBtranCounts_;
  numberFtranFullCounts_ = other.numberFtranFullCounts_;
  numberFtranFullCounts_ = other.numberFtranFullCounts_;
  ftranAverageAfterL_ = other.ftranAverageAfterL_;
  ftranAverageAfterR_ = other.ftranAverageAfterR_;
  ftranAverageAfterU_ = other.ftranAverageAfterU_;
  ftranFTAverageAfterL_ = other.ftranFTAverageAfterL_;
  ftranFTAverageAfterR_ = other.ftranFTAverageAfterR_;
  ftranFTAverageAfterU_ = other.ftranFTAverageAfterU_;
  btranAverageAfterU_ = other.btranAverageAfterU_;
  btranAverageAfterR_ = other.btranAverageAfterR_;
  btranAverageAfterL_ = other.btranAverageAfterL_;
  ftranFullAverageAfterL_ = other.ftranFullAverageAfterL_;
  ftranFullAverageAfterR_ = other.ftranFullAverageAfterR_;
  ftranFullAverageAfterU_ = other.ftranFullAverageAfterU_;
  btranFullAverageAfterL_ = other.btranFullAverageAfterL_;
  btranFullAverageAfterR_ = other.btranFullAverageAfterR_;
  btranFullAverageAfterU_ = other.btranFullAverageAfterU_;
#if FACTORIZATION_STATISTICS
  ftranTwiddleFactor1_ = other.ftranTwiddleFactor1_;
  ftranFTTwiddleFactor1_ = other.ftranFTTwiddleFactor1_;
  btranTwiddleFactor1_ = other.btranTwiddleFactor1_;
  ftranFullTwiddleFactor1_ = other.ftranFullTwiddleFactor1_;
  btranFullTwiddleFactor1_ = other.btranFullTwiddleFactor1_;
  ftranTwiddleFactor2_ = other.ftranTwiddleFactor2_;
  ftranFTTwiddleFactor2_ = other.ftranFTTwiddleFactor2_;
  btranTwiddleFactor2_ = other.btranTwiddleFactor2_;
  ftranFullTwiddleFactor2_ = other.ftranFullTwiddleFactor2_;
  btranFullTwiddleFactor2_ = other.btranFullTwiddleFactor2_;
#endif
  sparseThreshold_ = other.sparseThreshold_;
#endif
  state_ = other.state_;
  // Maximum rows (ever)
  maximumRows_ = other.maximumRows_;
  // Rows first time nonzero
  initialNumberRows_ = other.initialNumberRows_;
  // Maximum maximum pivots
  maximumMaximumPivots_ = other.maximumMaximumPivots_;
  CoinBigIndex space = lengthAreaL_ - lengthL_;

#if ABC_SMALL < 4
  numberDense_ = other.numberDense_;
  denseThreshold_ = other.denseThreshold_;
#endif
  lengthAreaR_ = space;
  elementRAddress_ = elementL_.array() + lengthL_;
  indexRowRAddress_ = indexRowL_.array() + lengthL_;
  workArea_ = other.workArea_;
  workArea2_ = other.workArea2_;
  //now copy everything
  //assuming numberRowsExtra==numberColumnsExtra
  if (numberRowsExtra_) {
    if (startRowU_.array()) {
      CoinAbcMemcpy(startRowU_.array(), other.startRowU_.array(), numberRows_ + 1);
      CoinAbcMemcpy(numberInRow_.array(), other.numberInRow_.array(), numberRows_ + 1);
      //startRowU_.array()[maximumRowsExtra_] = other.startRowU_.array()[maximumRowsExtra_];
    }
    CoinAbcMemcpy(pivotRegion_.array(), other.pivotRegion_.array(), numberRows_ + 2);
#ifndef ABC_ORDERED_FACTORIZATION
    CoinAbcMemcpy(permute_.array(), other.permute_.array(), numberRowsExtra_ + 1);
#else
    //temp
    CoinAbcMemcpy(permute_.array(), other.permute_.array(), maximumRowsExtra_ + 2 * numberRows_ + 1);
#endif
    CoinAbcMemcpy(firstCount_.array(), other.firstCount_.array(), CoinMax(5 * numberRows_, 4 * numberRows_ + 2 * maximumPivots_ + 4) + 2);
    CoinAbcMemcpy(startColumnU_.array(), other.startColumnU_.array(), numberRows_ + 1);
    CoinAbcMemcpy(numberInColumn_.array(), other.numberInColumn_.array(), numberRows_ + 1);
    CoinAbcMemcpy(pivotColumn_.array(), other.pivotColumn_.array(), numberRowsExtra_ + 1);
    CoinAbcMemcpy(nextColumn_.array(), other.nextColumn_.array(), numberRowsExtra_ + 1);
    CoinAbcMemcpy(lastColumn_.array(), other.lastColumn_.array(), numberRowsExtra_ + 1);
    CoinAbcMemcpy(startColumnR(), other.startColumnR(), numberRowsExtra_ - numberRows_ + 1);

    //extra one at end
    //startColumnU_.array()[maximumRowsExtra_] =
    //other.startColumnU_.array()[maximumRowsExtra_];
    nextColumn_.array()[maximumRowsExtra_] = other.nextColumn_.array()[maximumRowsExtra_];
    lastColumn_.array()[maximumRowsExtra_] = other.lastColumn_.array()[maximumRowsExtra_];
    CoinAbcMemcpy(nextRow_.array(), other.nextRow_.array(), numberRows_ + 1);
    CoinAbcMemcpy(lastRow_.array(), other.lastRow_.array(), numberRows_ + 1);
    nextRow_.array()[numberRows_] = other.nextRow_.array()[numberRows_];
    lastRow_.array()[numberRows_] = other.lastRow_.array()[numberRows_];
  }
  CoinAbcMemcpy(elementRAddress_, other.elementRAddress_, lengthR_);
  CoinAbcMemcpy(indexRowRAddress_, other.indexRowRAddress_, lengthR_);
  //row and column copies of U
  /* as elements of U may have been zeroed but column counts zero
     copy all elements */
  const CoinBigIndex *COIN_RESTRICT startColumnU = startColumnU_.array();
  const CoinSimplexInt *COIN_RESTRICT numberInColumn = numberInColumn_.array();
#ifndef NDEBUG
  CoinSimplexInt maxU = 0;
  for (CoinSimplexInt iRow = 0; iRow < numberRows_; iRow++) {
    CoinBigIndex start = startColumnU[iRow];
    CoinSimplexInt numberIn = numberInColumn[iRow];
    maxU = CoinMax(maxU, start + numberIn);
  }
  //assert (maximumU_>=maxU);
#endif
  CoinAbcMemcpy(elementU_.array(), other.elementU_.array(), maximumU_);
#if ABC_SMALL < 2
#if COIN_ONE_ETA_COPY
  if (elementRowUOther) {
#endif
    const CoinSimplexInt *COIN_RESTRICT indexColumnUOther = other.indexColumnU_.array();
#if CONVERTROW
    CoinBigIndex *COIN_RESTRICT convertU = convertRowToColumnU_.array();
#if CONVERTROW > 2
    CoinBigIndex *COIN_RESTRICT convertU2 = convertColumnToRowU_.array();
#endif
#endif
    CoinFactorizationDouble *COIN_RESTRICT elementRowU = elementRowU_.array();
    CoinSimplexInt *COIN_RESTRICT indexColumnU = indexColumnU_.array();
    const CoinBigIndex *COIN_RESTRICT startRowU = startRowU_.array();
    const CoinSimplexInt *COIN_RESTRICT numberInRow = numberInRow_.array();
    for (CoinSimplexInt iRow = 0; iRow < numberRows_; iRow++) {
      //row
      CoinBigIndex start = startRowU[iRow];
      CoinSimplexInt numberIn = numberInRow[iRow];

      CoinAbcMemcpy(indexColumnU + start, indexColumnUOther + start, numberIn);
#if CONVERTROW
      CoinAbcMemcpy(convertU + start, convertUOther + start, numberIn);
#if CONVERTROW > 2
      CoinAbcMemcpy(convertU2 + start, convertUOther2 + start, numberIn);
#endif
#endif
      CoinAbcMemcpy(elementRowU + start, elementRowUOther + start, numberIn);
    }
#if COIN_ONE_ETA_COPY
  }
#endif
#endif
  const CoinSimplexInt *COIN_RESTRICT indexRowUOther = other.indexRowU_.array();
  CoinSimplexInt *COIN_RESTRICT indexRowU = indexRowU_.array();
  for (CoinSimplexInt iRow = 0; iRow < numberRows_; iRow++) {
    //column
    CoinBigIndex start = startColumnU[iRow];
    CoinSimplexInt numberIn = numberInColumn[iRow];
    if (numberIn > 0)
      CoinAbcMemcpy(indexRowU + start, indexRowUOther + start, numberIn);
  }
  // L is contiguous
  if (numberRows_)
    CoinAbcMemcpy(startColumnL_.array(), other.startColumnL_.array(), numberRows_ + 1);
  CoinAbcMemcpy(elementL_.array(), other.elementL_.array(), lengthL_);
  CoinAbcMemcpy(indexRowL_.array(), other.indexRowL_.array(), lengthL_);
#if ABC_SMALL < 2
  if (other.sparseThreshold_) {
    goSparse();
  }
#endif
  doAddresses();
}

//  getAreas.  Gets space for a factorization
//called by constructors
void CoinAbcTypeFactorization::getAreas(CoinSimplexInt numberOfRows,
  CoinSimplexInt /*numberOfColumns*/,
  CoinBigIndex maximumL,
  CoinBigIndex maximumU)
{
  gutsOfInitialize(2);

  numberRows_ = numberOfRows;
  numberRowsSmall_ = numberOfRows;
  maximumRows_ = CoinMax(maximumRows_, numberRows_);
  maximumRowsExtra_ = numberRows_ + maximumPivots_;
  numberRowsExtra_ = numberRows_;
  lengthAreaU_ = maximumU;
  lengthAreaL_ = maximumL;
  if (!areaFactor_) {
    areaFactor_ = 1.0;
  }
  if (areaFactor_ != 1.0) {
    if ((messageLevel_ & 16) != 0)
      printf("Increasing factorization areas by %g\n", areaFactor_);
    lengthAreaU_ = static_cast< CoinBigIndex >(areaFactor_ * lengthAreaU_);
    lengthAreaL_ = static_cast< CoinBigIndex >(areaFactor_ * lengthAreaL_);
  }
#ifdef ABC_USE_FUNCTION_POINTERS
  lengthAreaUPlus_ = (lengthAreaU_ * 3) / 2 + maximumRowsExtra_;
  elementU_.conditionalNew(lengthAreaUPlus_);
#else
  elementU_.conditionalNew(lengthAreaU_);
#endif
  indexRowU_.conditionalNew(lengthAreaU_ + 1);
  indexColumnU_.conditionalNew(lengthAreaU_ + 1);
  elementL_.conditionalNew(lengthAreaL_);
  indexRowL_.conditionalNew(lengthAreaL_);
  // But we can use all we have if bigger
  CoinBigIndex length;
  length = CoinMin(elementU_.getSize(), indexRowU_.getSize());
  if (length > lengthAreaU_) {
    lengthAreaU_ = length;
    assert(indexColumnU_.getSize() == indexRowU_.getSize());
  }
  length = CoinMin(elementL_.getSize(), indexRowL_.getSize());
  if (length > lengthAreaL_) {
    lengthAreaL_ = length;
  }
  startColumnL_.conditionalNew(numberRows_ + 1);
  startColumnL_.array()[0] = 0;
  startRowU_.conditionalNew(maximumRowsExtra_ + 1);
  // make sure this is valid (Needed for row links????)
  startRowU_.array()[maximumRowsExtra_] = 0;
  lastEntryByRowU_ = 0;
  numberInRow_.conditionalNew(maximumRowsExtra_ + 1);
  markRow_.conditionalNew(numberRows_);
  nextRow_.conditionalNew(maximumRowsExtra_ + 1);
  lastRow_.conditionalNew(maximumRowsExtra_ + 1);
#ifndef ABC_ORDERED_FACTORIZATION
  permute_.conditionalNew(maximumRowsExtra_ + 1);
#else
  //temp
  permute_.conditionalNew(maximumRowsExtra_ + 2 * numberRows_ + 1);
#endif
  permuteAddress_ = permute_.array();
  pivotRegion_.conditionalNew(maximumRows_ + 2);
  startColumnU_.conditionalNew(maximumRowsExtra_ + 1);
  numberInColumn_.conditionalNew(maximumRowsExtra_ + 1);
  numberInColumnPlus_.conditionalNew(maximumRowsExtra_ + 1);
#ifdef ABC_USE_FUNCTION_POINTERS
  scatterUColumn_.conditionalNew(sizeof(scatterStruct), maximumRowsExtra_ + 1);
  elementRowU_.conditionalNew(lengthAreaUPlus_);
  elementRowUAddress_ = elementRowU_.array();
  firstZeroed_ = 0;
#elif ABC_SMALL < 2
  elementRowU_.conditionalNew(lengthAreaU_);
  elementRowUAddress_ = elementRowU_.array();
#endif
#if COIN_BIG_DOUBLE == 1
  for (int i = 0; i < FACTOR_CPU; i++) {
    longArray_[i].conditionalNew(maximumRowsExtra_ + 1);
    longArray_[i].clear();
  }
#endif
  pivotColumn_.conditionalNew(maximumRowsExtra_ + 1);
  nextColumn_.conditionalNew(maximumRowsExtra_ + 1);
  lastColumn_.conditionalNew(maximumRowsExtra_ + 1);
  saveColumn_.conditionalNew(/*2*  */ numberRows_);
  assert(sizeof(CoinSimplexInt) == sizeof(CoinBigIndex)); // would need to redo
  firstCount_.conditionalNew(CoinMax(5 * numberRows_, 4 * numberRows_ + 2 * maximumPivots_ + 4) + 2);
#if CONVERTROW
  //space for cross reference
  convertRowToColumnU_.conditionalNew(lengthAreaU_);
  convertRowToColumnUAddress_ = convertRowToColumnU_.array();
#if CONVERTROW > 1
  convertColumnToRowU_.conditionalNew(lengthAreaU_);
  convertColumnToRowUAddress_ = convertColumnToRowU_.array();
#endif
#endif
#ifdef SMALL_PERMUTE
  assert(sizeof(CoinFactorizationDouble) >= 2 * sizeof(int));
  denseArea_.conditionalNew(numberRows_ + maximumRowsExtra_ + 2);
  fromSmallToBigRow_ = reinterpret_cast< CoinSimplexInt * >(denseArea_.array());
  fromSmallToBigColumn_ = fromSmallToBigRow_ + numberRows_;
#endif
  doAddresses();
#if ABC_SMALL < 2
  // temp - use as marker for valid row/column lookup
  sparseThreshold_ = 0;
#endif
}

#include "AbcSimplex.hpp"
#include "ClpMessage.hpp"

//Does most of factorization
CoinSimplexInt
CoinAbcTypeFactorization::factor(AbcSimplex *model)
{
#if ABC_DENSE_CODE
  int saveDense = denseThreshold_;
  if ((solveMode_ & 1) == 0)
    denseThreshold_ = 0;
#endif
  //sparse
  status_ = factorSparse();
  switch (status_) {
  case 0: //finished
    totalElements_ = 0;
    if (numberGoodU_ < numberRows_)
      status_ = -1;
    break;
#if ABC_DENSE_CODE
#if ABC_SMALL < 4
    // dense
  case 2:
    status_ = factorDense();
    if (!status_)
      break;
#endif
#endif
  default:
    //singular ? or some error
    if ((messageLevel_ & 4) != 0)
      std::cout << "Error " << status_ << std::endl;
    if (status_ == -99) {
      if (numberRows_ - numberGoodU_ < 1000) {
        areaFactor_ *= 1.5;
      } else {
        double denseArea = (numberRows_ - numberGoodU_) * (numberRows_ - numberGoodU_);
        if (denseArea > 1.5 * lengthAreaU_) {
          areaFactor_ *= CoinMin(2.5, denseArea / 1.5);
        } else {
          areaFactor_ *= 1.5;
        }
      }
      if (model->logLevel() > 1) {
        char line[100];
        sprintf(line, "need more memory lengthArea %d number %d done %d areaFactor %g",
          lengthAreaL_ + lengthAreaU_, lengthU_ + lengthL_, numberGoodU_, areaFactor_);
        model->messageHandler()->message(CLP_GENERAL2, *model->messagesPointer())
          << line << CoinMessageEol;
      }
    } else if (status_ == -97) {
      // just pivot tolerance issue
      status_ = -99;
      char line[100];
      sprintf(line, "Bad pivot values - increasing pivot tolerance to %g",
        pivotTolerance_);
      model->messageHandler()->message(CLP_GENERAL2, *model->messagesPointer())
        << line << CoinMessageEol;
    }
    break;
  } /* endswitch */
  //clean up
  if (!status_) {
    if ((messageLevel_ & 16) && numberCompressions_)
      std::cout << "        Factorization did " << numberCompressions_
                << " compressions" << std::endl;
    if (numberCompressions_ > 10) {
      // but not more than 5 times final
      if (lengthAreaL_ + lengthAreaU_ < 10 * (lengthU_ + lengthL_)) {
        areaFactor_ *= 1.1;
        if (model->logLevel() > 1) {
          char line[100];
          sprintf(line, "%d factorization compressions, lengthArea %d number %d new areaFactor %g",
            numberCompressions_, lengthAreaL_ + lengthAreaU_, lengthU_ + lengthL_, areaFactor_);
          model->messageHandler()->message(CLP_GENERAL2, *model->messagesPointer())
            << line << CoinMessageEol;
        }
      }
    }
    numberCompressions_ = 0;
    cleanup();
  }
  numberPivots_ = 0;
#if ABC_DENSE_CODE
  denseThreshold_ = saveDense;
#endif
  return status_;
}
#define ALWAYS_GIVE_UP 0 //1
#ifdef ABC_USE_FUNCTION_POINTERS
#define DENSE_TRY
#ifdef DENSE_TRY
static void pivotStartup(int first, int last, int numberInPivotColumn, int lengthArea, int giveUp,
  CoinFactorizationDouble *COIN_RESTRICT eArea, const int *COIN_RESTRICT saveColumn,
  const int *COIN_RESTRICT startColumnU, int *COIN_RESTRICT tempColumnCount,
  const CoinFactorizationDouble *COIN_RESTRICT elementU,
  const int *COIN_RESTRICT numberInColumn,
  const int *COIN_RESTRICT indexRowU)
{
  if (last - first > giveUp && !ALWAYS_GIVE_UP) {
    int mid = (last + first) >> 1;
    cilk_spawn pivotStartup(first, mid, numberInPivotColumn, lengthArea, giveUp,
      eArea, saveColumn, startColumnU, tempColumnCount,
      elementU, numberInColumn, indexRowU);
    pivotStartup(mid, last, numberInPivotColumn, lengthArea, giveUp,
      eArea, saveColumn, startColumnU, tempColumnCount,
      elementU, numberInColumn, indexRowU);
    cilk_sync;
  } else {
    CoinFactorizationDouble *COIN_RESTRICT area = eArea + first * lengthArea;
    for (int jColumn = first; jColumn < last; jColumn++) {
      CoinSimplexInt iColumn = saveColumn[jColumn];
      CoinBigIndex startColumn = startColumnU[iColumn];
      int numberNow = tempColumnCount[jColumn];
      int start = startColumn + numberNow;
      int end = startColumn + numberInColumn[iColumn];
      CoinFactorizationDouble thisPivotValue = elementU[startColumn - 1];
      for (CoinBigIndex j = start; j < end; j++) {
        CoinFactorizationDouble value = elementU[j];
        int iPut = indexRowU[j];
        assert(iPut < lengthArea);
        area[iPut] = value;
      }
      area[numberInPivotColumn] = thisPivotValue;
      area += lengthArea;
    }
  }
}
static void pivotWhile(int first, int last, int numberInPivotColumn, int lengthArea, int giveUp,
  CoinFactorizationDouble *COIN_RESTRICT eArea, const CoinFactorizationDouble *COIN_RESTRICT multipliersL)
{
  if (last - first > giveUp && !ALWAYS_GIVE_UP) {
    int mid = (last + first) >> 1;
    cilk_spawn pivotWhile(first, mid, numberInPivotColumn, lengthArea, giveUp,
      eArea, multipliersL);
    pivotWhile(mid, last, numberInPivotColumn, lengthArea, giveUp,
      eArea, multipliersL);
    cilk_sync;
  } else {
    CoinFactorizationDouble *COIN_RESTRICT area = eArea + first * lengthArea;
    int nDo = last - first;
#if AVX2 == 0
    for (int jColumn = 0; jColumn < nDo; jColumn++) {
      CoinFactorizationDouble thisPivotValue = area[numberInPivotColumn];
      area[numberInPivotColumn] = 0.0;
      for (CoinSimplexInt j = 0; j < numberInPivotColumn; j++) {
        area[j] -= thisPivotValue * multipliersL[j];
      }
      area += lengthArea;
    }
#else
    int n = (numberInPivotColumn + 3) & (~3);
    // for compiler error
    CoinFactorizationDouble *multipliers = const_cast< CoinFactorizationDouble * >(multipliersL);
    for (int jColumn = 0; jColumn < nDo; jColumn++) {
      //CoinFactorizationDouble thisPivotValue = area[numberInPivotColumn];
      __m256d pivot = _mm256_broadcast_sd(area + numberInPivotColumn);
      area[numberInPivotColumn] = 0.0;
      for (CoinSimplexInt j = 0; j < n; j += 4) {
        __m256d a = _mm256_load_pd(area + j);
        __m256d m = _mm256_load_pd(multipliers + j);
        a -= pivot * m;
        *reinterpret_cast< __m256d * >(area + j) = a; //_mm256_store_pd ((area+j), a);
        //area[j] -= thisPivotValue * multipliersL[j];
        //area[j+1] -= thisPivotValue * multipliersL[j+1];
        //area[j+2] -= thisPivotValue * multipliersL[j+2];
        //area[j+3] -= thisPivotValue * multipliersL[j+3];
      }
      area += lengthArea;
    }
#endif
  }
}
static void pivotSomeAfter(int first, int last, int numberInPivotColumn, int lengthArea, int giveUp,
  CoinFactorizationDouble *COIN_RESTRICT eArea, const int *COIN_RESTRICT saveColumn,
  const int *COIN_RESTRICT startColumnU, int *COIN_RESTRICT tempColumnCount,
  CoinFactorizationDouble *COIN_RESTRICT elementU, int *COIN_RESTRICT numberInColumn,
  int *COIN_RESTRICT indexRowU, unsigned int *aBits,
  const int *COIN_RESTRICT indexL,
  const CoinFactorizationDouble *COIN_RESTRICT multipliersL, double tolerance)
{
  if (last - first > giveUp && !ALWAYS_GIVE_UP) {
    int mid = (last + first) >> 1;
    cilk_spawn pivotSomeAfter(first, mid, numberInPivotColumn, lengthArea, giveUp,
      eArea, saveColumn, startColumnU, tempColumnCount,
      elementU, numberInColumn, indexRowU, aBits, indexL,
      multipliersL, tolerance);
    pivotSomeAfter(mid, last, numberInPivotColumn, lengthArea, giveUp,
      eArea, saveColumn, startColumnU, tempColumnCount,
      elementU, numberInColumn, indexRowU, aBits, indexL,
      multipliersL, tolerance);
    cilk_sync;
  } else {
    int intsPerColumn = (lengthArea + 31) >> 5;
    CoinFactorizationDouble *COIN_RESTRICT area = eArea + first * lengthArea;
    for (int jColumn = first; jColumn < last; jColumn++) {
      CoinSimplexInt iColumn = saveColumn[jColumn];
      CoinBigIndex startColumn = startColumnU[iColumn];
      int numberNow = tempColumnCount[jColumn];
      CoinFactorizationDouble thisPivotValue = area[numberInPivotColumn];
      area[numberInPivotColumn] = 0.0;
      int n = 0;
      int positionLargest = -1;
      double largest = numberNow ? fabs(elementU[startColumn]) : 0.0;
      unsigned int *aBitsThis = aBits + jColumn * intsPerColumn;
#if AVX2 == 0
      for (CoinSimplexInt j = 0; j < numberInPivotColumn; j++) {
        CoinFactorizationDouble value = area[j] - thisPivotValue * multipliersL[j];
        CoinSimplexDouble absValue = fabs(value);
        area[j] = 0.0;
        if (absValue > tolerance) {
          area[n] = value;
          if (absValue > largest) {
            largest = absValue;
            positionLargest = n;
          }
          n++;
        } else {
          // say zero
          int word = j >> 5;
          int unsetBit = j - (word << 5);
          aBitsThis[word] &= ~(1 << unsetBit);
        }
      }
#else
      // for compiler error
      CoinFactorizationDouble *multipliers = const_cast< CoinFactorizationDouble * >(multipliersL);
      int nDo = (numberInPivotColumn + 3) & (~3);
      //double temp[4] __attribute__ ((aligned (32)));
      __m256d pivot = _mm256_broadcast_sd(&thisPivotValue);
      for (CoinSimplexInt j = 0; j < nDo; j += 4) {
        __m256d a = _mm256_load_pd(area + j);
        __m256d m = _mm256_load_pd(multipliers + j);
        a -= pivot * m;
        *reinterpret_cast< __m256d * >(area + j) = a; //_mm256_store_pd ((area+j), a);
      }
      for (CoinSimplexInt j = 0; j < numberInPivotColumn; j++) {
        CoinFactorizationDouble value = area[j];
        CoinSimplexDouble absValue = fabs(value);
        area[j] = 0.0;
        if (absValue > tolerance) {
          area[n] = value;
          if (absValue > largest) {
            largest = absValue;
            positionLargest = n;
          }
          n++;
        } else {
          // say zero
          int word = j >> 5;
          int unsetBit = j - (word << 5);
          aBitsThis[word] &= ~(1 << unsetBit);
        }
      }
#endif
      int put = startColumn;
      if (positionLargest >= 0)
        positionLargest += put + numberNow;
      put += numberNow;
      int iA = 0;
      for (int jj = 0; jj < numberInPivotColumn; jj += 32) {
        unsigned int aThis = *aBitsThis;
        aBitsThis++;
        for (int i = jj; i < CoinMin(jj + 32, numberInPivotColumn); i++) {
          if ((aThis & 1) != 0) {
            indexRowU[put] = indexL[i];
            elementU[put++] = area[iA];
            area[iA++] = 0.0;
          }
          aThis = aThis >> 1;
        }
      }
      int numberNeeded = put - startColumn;
      if (positionLargest >= 0) {
        //swap first and largest
        CoinBigIndex start = startColumn;
        int firstIndex = indexRowU[start];
        CoinFactorizationDouble firstValue = elementU[start];
        indexRowU[start] = indexRowU[positionLargest];
        elementU[start] = elementU[positionLargest];
        indexRowU[positionLargest] = firstIndex;
        elementU[positionLargest] = firstValue;
      }
      tempColumnCount[jColumn] = numberNeeded - numberInColumn[iColumn];
      assert(numberNeeded >= 0);
      numberInColumn[iColumn] = numberNeeded;
      area += lengthArea;
    }
  }
}
#endif
static void pivotSome(int first, int last, int numberInPivotColumn, int lengthArea, int giveUp,
  CoinFactorizationDouble *COIN_RESTRICT eArea, const int *COIN_RESTRICT saveColumn,
  const int *COIN_RESTRICT startColumnU, int *COIN_RESTRICT tempColumnCount,
  CoinFactorizationDouble *COIN_RESTRICT elementU, int *COIN_RESTRICT numberInColumn,
  int *COIN_RESTRICT indexRowU, unsigned int *aBits,
  const int *COIN_RESTRICT indexL,
  const CoinFactorizationDouble *COIN_RESTRICT multipliersL, double tolerance)
{
  if (last - first > giveUp && !ALWAYS_GIVE_UP) {
    int mid = (last + first) >> 1;
    cilk_spawn pivotSome(first, mid, numberInPivotColumn, lengthArea, giveUp,
      eArea, saveColumn, startColumnU, tempColumnCount,
      elementU, numberInColumn, indexRowU, aBits, indexL,
      multipliersL, tolerance);
    pivotSome(mid, last, numberInPivotColumn, lengthArea, giveUp,
      eArea, saveColumn, startColumnU, tempColumnCount,
      elementU, numberInColumn, indexRowU, aBits, indexL,
      multipliersL, tolerance);
    cilk_sync;
  } else {
    int intsPerColumn = (lengthArea + 31) >> 5;
    CoinFactorizationDouble *COIN_RESTRICT area = eArea + first * lengthArea;
    for (int jColumn = first; jColumn < last; jColumn++) {
      CoinSimplexInt iColumn = saveColumn[jColumn];
      CoinBigIndex startColumn = startColumnU[iColumn];
      int numberNow = tempColumnCount[jColumn];
      CoinFactorizationDouble thisPivotValue = elementU[startColumn - 1];
      int start = startColumn + numberNow;
      int end = startColumn + numberInColumn[iColumn];
      for (CoinBigIndex j = start; j < end; j++) {
        CoinFactorizationDouble value = elementU[j];
        int iPut = indexRowU[j];
        assert(iPut < lengthArea);
        area[iPut] = value;
      }
      int n = 0;
      int positionLargest = -1;
      double largest = numberNow ? fabs(elementU[startColumn]) : 0.0;
      unsigned int *aBitsThis = aBits + jColumn * intsPerColumn;
#if AVX2 == 0
      for (CoinSimplexInt j = 0; j < numberInPivotColumn; j++) {
        CoinFactorizationDouble value = area[j] - thisPivotValue * multipliersL[j];
        CoinSimplexDouble absValue = fabs(value);
        area[j] = 0.0;
        if (absValue > tolerance) {
          area[n] = value;
          if (absValue > largest) {
            largest = absValue;
            positionLargest = n;
          }
          n++;
        } else {
          // say zero
          int word = j >> 5;
          int unsetBit = j - (word << 5);
          aBitsThis[word] &= ~(1 << unsetBit);
        }
      }
#else
      int nDo = (numberInPivotColumn + 3) & (~3);
      // for compiler error
      CoinFactorizationDouble *multipliers = const_cast< CoinFactorizationDouble * >(multipliersL);
      //double temp[4] __attribute__ ((aligned (32)));
      __m256d pivot = _mm256_broadcast_sd(&thisPivotValue);
      for (CoinSimplexInt j = 0; j < nDo; j += 4) {
        __m256d a = _mm256_load_pd(area + j);
        __m256d m = _mm256_load_pd(multipliers + j);
        a -= pivot * m;
        *reinterpret_cast< __m256d * >(area + j) = a; //_mm256_store_pd ((area+j), a);
      }
      for (CoinSimplexInt j = 0; j < numberInPivotColumn; j++) {
        CoinFactorizationDouble value = area[j];
        CoinSimplexDouble absValue = fabs(value);
        area[j] = 0.0;
        if (absValue > tolerance) {
          area[n] = value;
          if (absValue > largest) {
            largest = absValue;
            positionLargest = n;
          }
          n++;
        } else {
          // say zero
          int word = j >> 5;
          int unsetBit = j - (word << 5);
          aBitsThis[word] &= ~(1 << unsetBit);
        }
      }
#endif
      int put = startColumn;
      if (positionLargest >= 0)
        positionLargest += put + numberNow;
      put += numberNow;
      int iA = 0;
      for (int jj = 0; jj < numberInPivotColumn; jj += 32) {
        unsigned int aThis = *aBitsThis;
        aBitsThis++;
        for (int i = jj; i < CoinMin(jj + 32, numberInPivotColumn); i++) {
          if ((aThis & 1) != 0) {
            indexRowU[put] = indexL[i];
            elementU[put++] = area[iA];
            area[iA++] = 0.0;
          }
          aThis = aThis >> 1;
        }
      }
      int numberNeeded = put - startColumn;
      if (positionLargest >= 0) {
        //swap first and largest
        CoinBigIndex start = startColumn;
        int firstIndex = indexRowU[start];
        CoinFactorizationDouble firstValue = elementU[start];
        indexRowU[start] = indexRowU[positionLargest];
        elementU[start] = elementU[positionLargest];
        indexRowU[positionLargest] = firstIndex;
        elementU[positionLargest] = firstValue;
      }
      tempColumnCount[jColumn] = numberNeeded - numberInColumn[iColumn];
      assert(numberNeeded >= 0);
      numberInColumn[iColumn] = numberNeeded;
    }
  }
}
int CoinAbcTypeFactorization::pivot(CoinSimplexInt &pivotRow,
  CoinSimplexInt &pivotColumn,
  CoinBigIndex pivotRowPosition,
  CoinBigIndex pivotColumnPosition,
  int *COIN_RESTRICT markRow)
{
  CoinSimplexInt *COIN_RESTRICT indexColumnU = indexColumnU_.array();
  CoinBigIndex *COIN_RESTRICT startColumnU = startColumnU_.array();
  CoinSimplexInt *COIN_RESTRICT numberInColumn = numberInColumn_.array();
  CoinFactorizationDouble *COIN_RESTRICT elementU = elementU_.array();
  CoinSimplexInt *COIN_RESTRICT indexRowU = indexRowU_.array();
  CoinBigIndex *COIN_RESTRICT startRowU = startRowU_.array();
  CoinSimplexInt *COIN_RESTRICT numberInRow = numberInRow_.array();
  CoinFactorizationDouble *COIN_RESTRICT elementL = elementL_.array();
  CoinSimplexInt *COIN_RESTRICT indexRowL = indexRowL_.array();
  CoinSimplexInt *COIN_RESTRICT saveColumn = saveColumn_.array();
  CoinSimplexInt *COIN_RESTRICT nextRow = nextRow_.array();
  CoinSimplexInt *COIN_RESTRICT lastRow = lastRow_.array();
  int realPivotRow = fromSmallToBigRow_[pivotRow];
  //int realPivotColumn=fromSmallToBigColumn[pivotColumn];
  //store pivot columns (so can easily compress)
  CoinSimplexInt numberInPivotRow = numberInRow[pivotRow] - 1;
  CoinBigIndex startColumn = startColumnU[pivotColumn];
  CoinSimplexInt numberInPivotColumn = numberInColumn[pivotColumn] - 1;
  // temp
  CoinBigIndex endColumn = startColumn + numberInPivotColumn + 1;
  CoinBigIndex put = 0;
  CoinBigIndex startRow = startRowU[pivotRow];
  CoinBigIndex endRow = startRow + numberInPivotRow + 1;
#if ABC_SMALL < 2
  // temp - switch off marker for valid row/column lookup
  sparseThreshold_ = -1;
#endif

  if (pivotColumnPosition < 0) {
    for (pivotColumnPosition = startRow; pivotColumnPosition < endRow; pivotColumnPosition++) {
      CoinSimplexInt iColumn = indexColumnU[pivotColumnPosition];
      if (iColumn != pivotColumn) {
        saveColumn[put++] = iColumn;
      } else {
        break;
      }
    }
  } else {
    for (CoinBigIndex i = startRow; i < pivotColumnPosition; i++) {
      saveColumn[put++] = indexColumnU[i];
    }
  }
  assert(pivotColumnPosition < endRow);
  assert(indexColumnU[pivotColumnPosition] == pivotColumn);
  pivotColumnPosition++;
  for (; pivotColumnPosition < endRow; pivotColumnPosition++) {
    saveColumn[put++] = indexColumnU[pivotColumnPosition];
  }
  //take out this bit of indexColumnU
  CoinSimplexInt next = nextRow[pivotRow];
  CoinSimplexInt last = lastRow[pivotRow];

  nextRow[last] = next;
  lastRow[next] = last;
#ifdef SMALL_PERMUTE
  permuteAddress_[realPivotRow] = numberGoodU_; //use for permute
#else
  permuteAddress_[pivotRow] = numberGoodU_; //use for permute
#endif
  lastRow[pivotRow] = -2;
  numberInRow[pivotRow] = 0;
  //store column in L, compress in U and take column out
  CoinBigIndex l = lengthL_;

  if (l + numberInPivotColumn > lengthAreaL_) {
    //need more memory
    if ((messageLevel_ & 4) != 0)
      printf("more memory needed in middle of invert\n");
    return -99;
  }
  //l+=currentAreaL_->elementByColumn-elementL;
  CoinBigIndex lSave = l;
  CoinSimplexInt saveGoodL = numberGoodL_;
  CoinBigIndex *COIN_RESTRICT startColumnL = startColumnL_.array();
  startColumnL[numberGoodL_] = l; //for luck and first time
  numberGoodL_++;
  if (pivotRowPosition < 0) {
    for (pivotRowPosition = startColumn; pivotRowPosition < endColumn; pivotRowPosition++) {
      CoinSimplexInt iRow = indexRowU[pivotRowPosition];
      if (iRow == pivotRow)
        break;
    }
  }
  assert(pivotRowPosition < endColumn);
  assert(indexRowU[pivotRowPosition] == pivotRow);
  CoinFactorizationDouble pivotElement = elementU[pivotRowPosition];
  CoinFactorizationDouble pivotMultiplier = 1.0 / pivotElement;
  endColumn--;
  indexRowU[pivotRowPosition] = indexRowU[endColumn];
  elementU[pivotRowPosition] = elementU[endColumn];
  double tolerance = zeroTolerance_;
  numberInPivotColumn = endColumn - startColumn;
  pivotRegionAddress_[numberGoodU_] = pivotMultiplier;
  markRow[pivotRow] = LARGE_SET;
  //compress pivot column (move pivot to front including saved)
  numberInColumn[pivotColumn] = 0;
  // modify so eArea aligned on 256 bytes boundary
  // also allow for numberInPivotColumn rounded to multiple of four
  CoinBigIndex added = numberInPivotRow * (numberInPivotColumn + 4);
  CoinBigIndex spaceZeroed = added + ((numberRowsSmall_ + 3) >> 2);
  spaceZeroed = CoinMax(spaceZeroed, firstZeroed_);
  int maxBoth = CoinMax(numberInPivotRow, numberInPivotColumn);
  CoinBigIndex spaceOther = numberInPivotRow + maxBoth + numberInPivotRow * ((numberInPivotColumn + 31) >> 5);
  // allow for new multipliersL
  spaceOther += 2 * numberInPivotColumn + 8; // 32 byte alignment wanted
  CoinBigIndex spaceNeeded = spaceZeroed + ((spaceOther + 1) >> 1) + 32;
#ifdef INT_IS_8
  abort();
#endif
  if (spaceNeeded >= lengthAreaUPlus_ - lastEntryByColumnUPlus_)
    return -99;
  // see if need to zero out
  CoinFactorizationDouble *COIN_RESTRICT eArea = elementUColumnPlusAddress_ + lengthAreaUPlus_ - spaceZeroed;
  CoinInt64 xx = reinterpret_cast< CoinInt64 >(eArea);
  int iBottom = static_cast< int >(xx & 255);
  int offset = iBottom >> 3;
  eArea -= offset;
  spaceZeroed = (elementUColumnPlusAddress_ + lengthAreaUPlus_) - eArea;
  char *COIN_RESTRICT mark = reinterpret_cast< char * >(eArea + added);
  CoinFactorizationDouble *COIN_RESTRICT multipliersL = eArea - numberInPivotColumn;
  // adjust
  xx = reinterpret_cast< CoinInt64 >(multipliersL);
  iBottom = static_cast< int >(xx & 31);
  offset = iBottom >> 3;
  multipliersL -= offset;
  int *COIN_RESTRICT tempColumnCount = reinterpret_cast< int * >(multipliersL) - numberInPivotRow;
  int *COIN_RESTRICT tempCount = tempColumnCount - maxBoth;
  int *COIN_RESTRICT others = tempCount - numberInPivotRow;
  for (CoinBigIndex i = startColumn; i < endColumn; i++) {
    CoinSimplexInt iRow = indexRowU[i];
    //double value=elementU[i]*pivotMultiplier;
    markRow[iRow] = l - lSave;
    indexRowL[l] = iRow;
    multipliersL[l - lSave] = elementU[i];
    l++;
  }
  startColumnL[numberGoodL_] = l;
  lengthL_ = l;
  //use end of L for temporary space BUT AVX
  CoinSimplexInt *COIN_RESTRICT indexL = &indexRowL[lSave];
  //CoinFactorizationDouble * COIN_RESTRICT multipliersL = &elementL[lSave];
  for (int i = 0; i < numberInPivotColumn; i++)
    multipliersL[i] *= pivotMultiplier;
  // could make multiple of 4 for AVX (then adjust previous computation)
  int lengthArea = ((numberInPivotColumn + 4) >> 2) << 2;
  // zero out rest
  memset(multipliersL + numberInPivotColumn, 0, (lengthArea - numberInPivotColumn) * sizeof(CoinFactorizationDouble));
  int intsPerColumn = (lengthArea + 31) >> 5;
  unsigned int *COIN_RESTRICT aBits = reinterpret_cast< unsigned int * >(others - intsPerColumn * numberInPivotRow);
  memset(aBits, 0xff, intsPerColumn * 4 * numberInPivotRow);
  if (spaceZeroed > firstZeroed_) {
    CoinAbcMemset0(eArea, spaceZeroed - firstZeroed_);
    firstZeroed_ = spaceZeroed;
  }
#ifndef NDEBUG
  for (int i = 0; i < added; i++)
    assert(!eArea[i]);
  for (int i = 0; i < firstZeroed_; i++)
    assert(!elementUColumnPlusAddress_[lengthAreaUPlus_ - firstZeroed_ + i]);
  for (int i = 0; i < numberRowsSmall_; i++)
    assert(!mark[i]);
#endif
  // could be 2 if dense
  int status = 0;
  CoinSimplexInt *COIN_RESTRICT numberInColumnPlus = numberInColumnPlus_.array();
  for (int jColumn = 0; jColumn < numberInPivotRow; jColumn++) {
    CoinSimplexInt iColumn = saveColumn[jColumn];
    mark[iColumn] = 1;
  }
  // can go parallel
  // make two versions (or use other way for one) and choose serial if small added?
  CoinSimplexInt *COIN_RESTRICT nextColumn = nextColumn_.array();
#define ABC_PARALLEL_PIVOT
#ifdef ABC_PARALLEL_PIVOT
#define cilk_for_query cilk_for
#else
#define cilk_for_query for
#endif
#if 0
  for (int i=0;i<numberRowsSmall_;i++)
    assert (numberInColumn[i]>=0);
#endif
  cilk_for_query(int jColumn = 0; jColumn < numberInPivotRow; jColumn++)
  {
    CoinSimplexInt iColumn = saveColumn[jColumn];
    CoinBigIndex startColumn = startColumnU[iColumn];
    CoinBigIndex endColumn = startColumn + numberInColumn[iColumn];
    CoinFactorizationDouble thisPivotValue = 0.0;
    CoinBigIndex put = startColumn;
    CoinBigIndex positionLargest = -1;
    double largest = 0.0;
    CoinBigIndex position = startColumn;
    int iRow = indexRowU[position];
    CoinFactorizationDouble value = elementU[position];
    CoinSimplexInt mark = markRow[iRow];
    CoinBigIndex end = endColumn - 1;
    while (position < end) {
      if (mark == LARGE_UNSET) {
        //keep
        if (fabs(value) > largest) {
          positionLargest = put;
          largest = fabs(value);
        }
        indexRowU[put] = iRow;
        elementU[put++] = value;
      } else if (mark != LARGE_SET) {
        //will be updated - move to end
        CoinFactorizationDouble value2 = value;
        int mark2 = mark;
        iRow = indexRowU[end];
        value = elementU[end];
        mark = markRow[iRow];
        indexRowU[end] = mark2;
        elementU[end] = value2;
        end--;
        continue;
      } else {
        thisPivotValue = value;
      }
      position++;
      iRow = indexRowU[position];
      value = elementU[position];
      mark = markRow[iRow];
    }
    // now last in column
    if (mark == LARGE_UNSET) {
      //keep
      if (fabs(value) > largest) {
        positionLargest = put;
        largest = fabs(value);
      }
      indexRowU[put] = iRow;
      elementU[put++] = value;
    } else if (mark != LARGE_SET) {
      //will be updated - move to end
      indexRowU[end] = mark;
      elementU[end] = value;
    } else {
      thisPivotValue = value;
    }
    //swap largest
    if (positionLargest >= 0) {
      double largestValue = elementU[positionLargest];
      int largestIndex = indexRowU[positionLargest];
      if (positionLargest != startColumn + 1 && put > startColumn + 1) {
        elementU[positionLargest] = elementU[startColumn + 1];
        indexRowU[positionLargest] = indexRowU[startColumn + 1];
        elementU[startColumn + 1] = largestValue;
        indexRowU[startColumn + 1] = largestIndex;
      }
      int firstIndex = indexRowU[startColumn];
      CoinFactorizationDouble firstValue = elementU[startColumn];
      // move first to end
      elementU[put] = firstValue;
      indexRowU[put++] = firstIndex;
    } else {
      put++;
    }
    elementU[startColumn] = thisPivotValue;
    indexRowU[startColumn] = realPivotRow;
    startColumn++;
    startColumnU[iColumn] = startColumn;
    numberInColumnPlus[iColumn]++;
    int numberNow = put - startColumn;
    tempColumnCount[jColumn] = numberNow;
    numberInColumn[iColumn]--;
#ifndef NDEBUG
    for (int i = startColumn + numberNow; i < startColumn + numberInColumn[iColumn]; i++)
      assert(indexRowU[i] < numberInPivotColumn);
#endif
  }
  //int tempxx[1000];
  //memcpy(tempxx,tempColumnCount,numberInPivotRow*sizeof(int));
#if 0
  for (int i=0;i<numberRowsSmall_;i++)
    assert (numberInColumn[i]>=0);
#endif
  //parallel
  mark[pivotColumn] = 1;
  cilk_for_query(int jRow = 0; jRow < numberInPivotColumn; jRow++)
  {
    CoinSimplexInt iRow = indexL[jRow];
    CoinBigIndex startRow = startRowU[iRow];
    CoinBigIndex endRow = startRow + numberInRow[iRow];
    CoinBigIndex put = startRow;
    // move earlier but set numberInRow to final
    for (CoinBigIndex i = startRow; i < endRow; i++) {
      int iColumn = indexColumnU[i];
      if (!mark[iColumn])
        indexColumnU[put++] = iColumn;
    }
    numberInRow[iRow] = put - startRow;
  }
  mark[pivotColumn] = 0;
#ifdef DENSE_TRY
  int numberZeroOther = 0;
  for (int jRow = 0; jRow < numberInPivotColumn; jRow++) {
    CoinSimplexInt iRow = indexL[jRow];
    if (numberInRow[iRow]) {
      //printf("Cantdo INrow %d incolumn %d nother %d\n",
      //     numberInPivotRow,numberInPivotColumn,numberZeroOther);
      numberZeroOther = -1;
      break;
    }
  }
  if (!numberZeroOther) {
    for (int jColumn = 0; jColumn < numberInPivotRow; jColumn++) {
      if (!tempColumnCount[jColumn])
        others[numberZeroOther++] = jColumn;
    }
  }
#endif
  // serial
  for (int jColumn = 0; jColumn < numberInPivotRow; jColumn++) {
    CoinSimplexInt iColumn = saveColumn[jColumn];
    CoinBigIndex startColumn = startColumnU[iColumn];
    int numberNow = tempColumnCount[jColumn];
    int numberNeeded = numberNow + numberInPivotColumn;
    tempCount[jColumn] = numberInColumn[iColumn];
    //how much space have we got
    CoinSimplexInt next = nextColumn[iColumn];
    CoinBigIndex space = startColumnU[next] - startColumn - numberInColumnPlus[next];
    // do moves serially but fill in in parallel!
    if (numberNeeded > space) {
      //getColumnSpace also moves fixed part
      if (!getColumnSpace(iColumn, numberNeeded)) {
        return -99;
      }
    }
    numberInColumn[iColumn] = numberNeeded;
  }
  // move counts back
  for (int jColumn = 0; jColumn < numberInPivotRow; jColumn++) {
    CoinSimplexInt iColumn = saveColumn[jColumn];
    numberInColumn[iColumn] = tempCount[jColumn];
  }
  // giveUp should be more sophisticated and also vary in next three
#if ABC_PARALLEL == 2
  int giveUp = CoinMax(numberInPivotRow / (parallelMode_ + 1 + (parallelMode_ >> 1)), 16);
#else
  int giveUp = numberInPivotRow;
#endif
#ifdef DENSE_TRY
  // If we keep full area - then can try doing many pivots in this function
  // Go round if there are any others just in this block
  bool inAreaAlready = false;
  if (numberZeroOther > 4) {
    //printf("Cando INrow %d incolumn %d nother %d\n",
    //	   numberInPivotRow,numberInPivotColumn,numberZeroOther);
    int numberRowsTest = (numberRowsLeft_ - numberZeroOther + 0) & ~7;
    if (numberRowsLeft_ - numberZeroOther <= numberRowsTest) {
      //see if would go dense
      int numberSubtracted = 0;
      // would have to be very big for parallel
      for (int jColumn = 0; jColumn < numberInPivotRow; jColumn++) {
        CoinSimplexInt iColumn = saveColumn[jColumn];
        numberSubtracted += numberInColumn[iColumn] - tempColumnCount[jColumn];
      }
      // could do formula? - work backwards
      CoinBigIndex saveTotalElements = totalElements_;
      int saveNumberRowsLeft = numberRowsLeft_;
      int numberOut = numberRowsLeft_ - numberRowsTest - 1;
      numberRowsLeft_ = numberRowsTest;
      CoinBigIndex total = totalElements_ - numberSubtracted;
      int bestGoDense = -1;
      for (; numberRowsLeft_ < saveNumberRowsLeft; numberRowsLeft_ += 8) {
        totalElements_ = total + (numberInPivotColumn - numberOut) * (numberInPivotRow - numberOut);
        int goDense = wantToGoDense();
        if (goDense == 2)
          bestGoDense = numberRowsLeft_;
        else
          break;
        numberOut -= 8;
      }
      totalElements_ = saveTotalElements;
      numberRowsLeft_ = saveNumberRowsLeft;
      // see if we need to stop early
      if (bestGoDense > numberRowsLeft_ - numberZeroOther)
        numberZeroOther = numberRowsLeft_ - bestGoDense;
      ;
    }
  } else {
    numberZeroOther = -1;
  }
  if (numberZeroOther > 0) {
    // do all except last
    pivotStartup(0, numberInPivotRow, numberInPivotColumn, lengthArea, giveUp,
      eArea, saveColumn, startColumnU, tempColumnCount,
      elementU, numberInColumn, indexRowU);
    assert(tempColumnCount[0] >= 0);
    for (int iTry = numberZeroOther - 1; iTry >= 0; iTry--) {
      pivotWhile(0, numberInPivotRow, numberInPivotColumn, lengthArea, giveUp,
        eArea, multipliersL);
      assert(tempColumnCount[0] >= 0);
      // find new pivot row
      int jPivotColumn = others[iTry];
      CoinFactorizationDouble *COIN_RESTRICT area = eArea + jPivotColumn * lengthArea;
      double largest = tolerance;
      int jPivotRow = -1;
      for (CoinSimplexInt j = 0; j < numberInPivotColumn; j++) {
        CoinFactorizationDouble value = area[j];
        CoinSimplexDouble absValue = fabs(value);
        if (absValue > largest) {
          largest = absValue;
          jPivotRow = j;
        }
      }
      if (jPivotRow >= 0) {
        markRow[pivotRow] = LARGE_UNSET;
        //modify linked list for pivots
        deleteLink(pivotRow);
        deleteLink(pivotColumn + numberRows_);
        // put away last
        afterPivot(pivotRow, pivotColumn);
        if (reinterpret_cast< unsigned int * >(elementUColumnPlusAddress_ + lastEntryByColumnUPlus_) > aBits) {
#ifndef NDEBUG
          printf("? dense\n");
#endif
          return -99;
        }
        // new ones
        pivotRow = indexL[jPivotRow];
        pivotColumn = saveColumn[jPivotColumn];
        // now do stuff for pivot
        realPivotRow = fromSmallToBigRow_[pivotRow];
        //int realPivotColumn=fromSmallToBigColumn[pivotColumn];
        //store pivot columns (so can easily compress)
        CoinBigIndex startColumn = startColumnU[pivotColumn];
        CoinBigIndex endColumn = startColumn + tempColumnCount[jPivotColumn];
        CoinSimplexInt next = nextRow[pivotRow];
        CoinSimplexInt last = lastRow[pivotRow];

        nextRow[last] = next;
        lastRow[next] = last;
#ifdef SMALL_PERMUTE
        permuteAddress_[realPivotRow] = numberGoodU_; //use for permute
#else
        permuteAddress_[pivotRow] = numberGoodU_; //use for permute
#endif
        lastRow[pivotRow] = -2;
        numberInRow[pivotRow] = 0;
        assert(tempColumnCount[0] >= 0);
        //store column in L, compress in U and take column out
        CoinBigIndex l = lengthL_;
        if (l + numberInPivotColumn > lengthAreaL_) {
          //need more memory
          if ((messageLevel_ & 4) != 0)
            printf("more memory needed in middle of invert\n");
          return -99;
        }
        //CoinBigIndex *  COIN_RESTRICT startColumnL = startColumnL_.array();
        numberGoodL_++;
        // move to L and move last
        numberInPivotColumn--;
        assert(tempColumnCount[0] >= 0);
        if (jPivotRow != numberInPivotColumn) {
          // swap
          for (int jColumn = 0; jColumn < numberInPivotRow; jColumn++) {
            CoinFactorizationDouble *COIN_RESTRICT area = eArea + jColumn * lengthArea;
            CoinFactorizationDouble thisValue = area[jPivotRow];
            area[jPivotRow] = area[numberInPivotColumn];
            area[numberInPivotColumn] = thisValue;
          }
          // do indexL in last one
          int tempI = indexL[numberInPivotColumn];
          CoinFactorizationDouble tempD = multipliersL[numberInPivotColumn];
          indexL[numberInPivotColumn] = indexL[jPivotRow];
          multipliersL[numberInPivotColumn] = multipliersL[jPivotRow];
          indexL[jPivotRow] = tempI;
          multipliersL[jPivotRow] = tempD;
          jPivotRow = numberInPivotColumn;
        }
        assert(tempColumnCount[0] >= 0);
        numberInPivotRow--;
        CoinFactorizationDouble pivotElement = area[numberInPivotColumn];
        area[numberInPivotColumn] = 0.0;
        // put last one in now
        CoinFactorizationDouble *COIN_RESTRICT areaLast = eArea + numberInPivotRow * lengthArea;
        // swap columns
        saveColumn[jPivotColumn] = saveColumn[numberInPivotRow];
        saveColumn[numberInPivotRow] = pivotColumn;
        //int temp=tempColumnCount[jPivotColumn];
        tempColumnCount[jPivotColumn] = tempColumnCount[numberInPivotRow];
        totalElements_ -= numberInColumn[pivotColumn];
        mark[pivotColumn] = 0;
        assert(tempColumnCount[0] >= 0);
        for (int jRow = 0; jRow < numberInPivotColumn + 1; jRow++) {
          CoinFactorizationDouble temp = areaLast[jRow];
          areaLast[jRow] = area[jRow];
          area[jRow] = temp;
        }
        areaLast[numberInPivotColumn] = 0.0;
        // swap rows in area and save
        for (int jColumn = 0; jColumn < numberInPivotRow; jColumn++) {
          CoinFactorizationDouble *COIN_RESTRICT area = eArea + jColumn * lengthArea;
          CoinFactorizationDouble thisPivotValue = area[numberInPivotColumn];
          assert(tempColumnCount[0] >= 0);
          area[numberInPivotColumn] = thisPivotValue;
          if (fabs(thisPivotValue) > tolerance) {
            CoinSimplexInt iColumn = saveColumn[jColumn];
            CoinBigIndex startColumn = startColumnU[iColumn];
            int nKeep = tempColumnCount[jColumn];
            if (nKeep) {
              if (nKeep > 1) {
                // need to move one to end
                elementU[startColumn + nKeep] = elementU[startColumn + 1];
                indexRowU[startColumn + nKeep] = indexRowU[startColumn + 1];
              }
              // move largest
              elementU[startColumn + 1] = elementU[startColumn];
              indexRowU[startColumn + 1] = indexRowU[startColumn];
            }
            elementU[startColumn] = thisPivotValue;
            indexRowU[startColumn] = realPivotRow;
            startColumn++;
            startColumnU[iColumn] = startColumn;
            numberInColumnPlus[iColumn]++;
            //numberInColumn[iColumn]--;
          }
        }
        assert(tempColumnCount[0] >= 0);
        // put away last (but remember count is one out)
        CoinAbcMemcpy(elementL + lSave, multipliersL, numberInPivotColumn + 1);
        lSave = l;
        for (int i = 0; i < numberInPivotColumn; i++) {
          CoinFactorizationDouble value = areaLast[i];
          areaLast[i] = 0.0;
          int iRow = indexL[i];
          indexRowL[l] = iRow;
          assert(iRow >= 0);
          multipliersL[l - lSave] = value;
          l++;
        }
        startColumnL[numberGoodL_] = l;
        lengthL_ = l;
        CoinFactorizationDouble pivotMultiplier = 1.0 / pivotElement;
        pivotRegionAddress_[numberGoodU_] = pivotMultiplier;
        numberInColumn[pivotColumn] = 0;
        indexL = &indexRowL[lSave];
        //adjust
        for (CoinSimplexInt j = 0; j < numberInPivotColumn; j++) {
          multipliersL[j] *= pivotMultiplier;
        }
        // zero out last
        multipliersL[numberInPivotColumn] = 0.0;
      } else {
        // singular
        // give up
        break;
      }
    }
    assert(tempColumnCount[0] >= 0);
#if 0
    // zero out extra bits
    int add1=numberInPivotColumn>>5;
    unsigned int * aBitsThis = aBits;
    int left=numberInPivotColumn-(add1<<5);
    unsigned int mark1 = (1<<(left-1)-1);

    int jColumn;
    for (jColumn = 0; jColumn < numberInPivotRow; jColumn++ ) {
      memset(aBitsThis+add1,0,(intsPerColumn-add1)*sizeof(int));
      aBitsThis += intsPerColumn;
    }
    for (; jColumn < numberInPivotRow+numberZeroOther; jColumn++ ) {
      memset(aBitsThis,0,intsPerColumn*sizeof(int));
      aBitsThis += intsPerColumn;
    }
#endif
    // last bit
    inAreaAlready = true;
  }
#endif
#if 0
  for (int i=0;i<numberRowsSmall_;i++)
    assert (numberInColumn[i]>=0);
#endif
  //if (added<1000)
  //giveUp=CoinMax(); //??
#ifdef DENSE_TRY
  if (!inAreaAlready) {
#endif
    pivotSome(0, numberInPivotRow, numberInPivotColumn, lengthArea, giveUp,
      eArea, saveColumn, startColumnU, tempColumnCount,
      elementU, numberInColumn, indexRowU, aBits, indexL,
      multipliersL, tolerance);
#ifdef DENSE_TRY
  } else {
    pivotSomeAfter(0, numberInPivotRow, numberInPivotColumn, lengthArea, giveUp,
      eArea, saveColumn, startColumnU, tempColumnCount,
      elementU, numberInColumn, indexRowU, aBits, indexL,
      multipliersL, tolerance);
  }
#endif
#if 0
  for (int i=0;i<numberRowsSmall_;i++)
    assert (numberInColumn[i]>=0);
#endif
  //serial
  for (int jRow = 0; jRow < numberInPivotColumn; jRow++) {
    CoinSimplexInt iRow = indexL[jRow];
    CoinSimplexInt next = nextRow[iRow];
    CoinBigIndex space = startRowU[next] - startRowU[iRow];
    // assume full
    int numberNeeded = numberInPivotRow + numberInRow[iRow];
    tempCount[jRow] = numberInRow[iRow];
    numberInRow[iRow] = numberNeeded;
    if (space < numberNeeded) {
      if (!getRowSpace(iRow, numberNeeded)) {
        return -99;
      }
    }
    lastEntryByRowU_ = CoinMax(startRowU[iRow] + numberNeeded, lastEntryByRowU_);
    // in case I got it wrong!
    if (lastEntryByRowU_ > lengthAreaU_) {
      return -99;
    }
  }
  // move counts back
  for (int jRow = 0; jRow < numberInPivotColumn; jRow++) {
    CoinSimplexInt iRow = indexL[jRow];
    numberInRow[iRow] = tempCount[jRow];
  }
  // parallel
  cilk_for_query(int jRow = 0; jRow < numberInPivotColumn; jRow++)
  {
    CoinSimplexInt iRow = indexL[jRow];
    CoinBigIndex startRow = startRowU[iRow];
    CoinBigIndex put = startRow + numberInRow[iRow];
    int iWord = jRow >> 5;
    unsigned int setBit = 1 << (jRow & 31);
    unsigned int *aBitsThis = aBits + iWord;
    for (int i = 0; i < numberInPivotRow; i++) {
      if ((aBitsThis[0] & setBit) != 0) {
        indexColumnU[put++] = saveColumn[i];
      }
      aBitsThis += intsPerColumn;
    }
    markRow[iRow] = LARGE_UNSET;
    numberInRow[iRow] = put - startRow;
  }
  //memset(aBits,0x00,intsPerColumn*4*(numberInPivotRow+numberZeroOther));
  added = 0;
  //int addedX=0;
  for (int jColumn = 0; jColumn < numberInPivotRow; jColumn++) {
    CoinSimplexInt iColumn = saveColumn[jColumn];
    for (int i = startColumnU[iColumn]; i < startColumnU[iColumn] + numberInColumn[iColumn]; i++)
      assert(indexRowU[i] >= 0 && indexRowU[i] < numberRowsSmall_);
    mark[iColumn] = 0;
    added += tempColumnCount[jColumn];
    modifyLink(iColumn + numberRows_, numberInColumn[iColumn]);
    //addedX += numberInColumn[iColumn]-tempxx[jColumn];
  }
#ifndef NDEBUG
  for (int i = 0; i < added; i++)
    assert(!eArea[i]);
  for (int i = 0; i < firstZeroed_; i++)
    assert(!elementUColumnPlusAddress_[lengthAreaUPlus_ - firstZeroed_ + i]);
  for (int i = 0; i < numberRowsSmall_; i++)
    assert(!mark[i]);
#endif
    //double ratio=((double)addedX)/((double)(numberInPivotRow*numberInPivotColumn));
#if 0 //def DENSE_TRY
  if (numberZeroOther>10000)
    printf("INrow %d incolumn %d nzero %d\n",
	   numberInPivotRow,numberInPivotColumn,numberZeroOther);
#endif
  //printf("INrow %d incolumn %d nzero %d ratio %g\n",
  //	 numberInPivotRow,numberInPivotColumn,numberZeroOther,ratio);
  for (int i = 0; i < numberInPivotColumn; i++) {
    int iRow = indexL[i];
    modifyLink(iRow, numberInRow[iRow]);
  }
  CoinAbcMemcpy(elementL + lSave, multipliersL, numberInPivotColumn);
#ifdef DENSE_TRY
  int iLBad = saveGoodL;
  put = startColumnL[iLBad];
  for (int iL = iLBad; iL < numberGoodL_; iL++) {
    CoinBigIndex start = startColumnL[iL];
    startColumnL[iL] = put;
    for (CoinBigIndex j = start; j < startColumnL[iL + 1]; j++) {
      if (elementL[j]) {
        elementL[put] = elementL[j];
        indexRowL[put++] = fromSmallToBigRow_[indexRowL[j]];
      }
    }
  }
  startColumnL[numberGoodL_] = put;
  lengthL_ = put;
#else
  // redo L indices
  for (CoinBigIndex j = lSave; j < startColumnL[numberGoodL_]; j++) {
    //assert (fabs(elementL[j])>=tolerance) ;
    int iRow = indexRowL[j];
    indexRowL[j] = fromSmallToBigRow_[iRow];
  }
#endif
  markRow[pivotRow] = LARGE_UNSET;
  //modify linked list for pivots
  deleteLink(pivotRow);
  deleteLink(pivotColumn + numberRows_);
  totalElements_ += added;
  return status;
}
#endif
// nonparallel pivot
int CoinAbcTypeFactorization::pivot(CoinSimplexInt pivotRow,
  CoinSimplexInt pivotColumn,
  CoinBigIndex pivotRowPosition,
  CoinBigIndex pivotColumnPosition,
  CoinFactorizationDouble *COIN_RESTRICT work,
  CoinSimplexUnsignedInt *COIN_RESTRICT workArea2,
  CoinSimplexInt increment2,
  int *COIN_RESTRICT markRow)
{
  CoinSimplexInt *COIN_RESTRICT indexColumnU = indexColumnU_.array();
  CoinBigIndex *COIN_RESTRICT startColumnU = startColumnU_.array();
  CoinSimplexInt *COIN_RESTRICT numberInColumn = numberInColumn_.array();
  CoinFactorizationDouble *COIN_RESTRICT elementU = elementU_.array();
  CoinSimplexInt *COIN_RESTRICT indexRowU = indexRowU_.array();
  CoinBigIndex *COIN_RESTRICT startRowU = startRowU_.array();
  CoinSimplexInt *COIN_RESTRICT numberInRow = numberInRow_.array();
  CoinFactorizationDouble *COIN_RESTRICT elementL = elementL_.array();
  CoinSimplexInt *COIN_RESTRICT indexRowL = indexRowL_.array();
  CoinSimplexInt *COIN_RESTRICT saveColumn = saveColumn_.array();
  CoinSimplexInt *COIN_RESTRICT nextRow = nextRow_.array();
  CoinSimplexInt *COIN_RESTRICT lastRow = lastRow_.array();
#ifdef SMALL_PERMUTE
  int realPivotRow = fromSmallToBigRow_[pivotRow];
  //int realPivotColumn=fromSmallToBigColumn[pivotColumn];
#endif
  //store pivot columns (so can easily compress)
  CoinSimplexInt numberInPivotRow = numberInRow[pivotRow] - 1;
  CoinBigIndex startColumn = startColumnU[pivotColumn];
  CoinSimplexInt numberInPivotColumn = numberInColumn[pivotColumn] - 1;
  // temp
  CoinBigIndex endColumn = startColumn + numberInPivotColumn + 1;
  CoinBigIndex put = 0;
  CoinBigIndex startRow = startRowU[pivotRow];
  CoinBigIndex endRow = startRow + numberInPivotRow + 1;
#if ABC_SMALL < 2
  // temp - switch off marker for valid row/column lookup
  sparseThreshold_ = -1;
#endif

  if (pivotColumnPosition < 0) {
    for (pivotColumnPosition = startRow; pivotColumnPosition < endRow; pivotColumnPosition++) {
      CoinSimplexInt iColumn = indexColumnU[pivotColumnPosition];
      if (iColumn != pivotColumn) {
        saveColumn[put++] = iColumn;
      } else {
#if BOTH_WAYS
#endif
        break;
      }
    }
  } else {
    for (CoinBigIndex i = startRow; i < pivotColumnPosition; i++) {
      saveColumn[put++] = indexColumnU[i];
    }
  }
  assert(pivotColumnPosition < endRow);
  assert(indexColumnU[pivotColumnPosition] == pivotColumn);
  pivotColumnPosition++;
  for (; pivotColumnPosition < endRow; pivotColumnPosition++) {
    saveColumn[put++] = indexColumnU[pivotColumnPosition];
  }
  //take out this bit of indexColumnU
  CoinSimplexInt next = nextRow[pivotRow];
  CoinSimplexInt last = lastRow[pivotRow];

  nextRow[last] = next;
  lastRow[next] = last;
#ifdef SMALL_PERMUTE
  permuteAddress_[realPivotRow] = numberGoodU_; //use for permute
#else
  permuteAddress_[pivotRow] = numberGoodU_; //use for permute
#endif
  lastRow[pivotRow] = -2;
  numberInRow[pivotRow] = 0;
  //store column in L, compress in U and take column out
  CoinBigIndex l = lengthL_;

  if (l + numberInPivotColumn > lengthAreaL_) {
    //need more memory
    if ((messageLevel_ & 4) != 0)
      printf("more memory needed in middle of invert\n");
    return -99;
  }
  //l+=currentAreaL_->elementByColumn-elementL;
  CoinBigIndex lSave = l;

  CoinBigIndex *COIN_RESTRICT startColumnL = startColumnL_.array();
  startColumnL[numberGoodL_] = l; //for luck and first time
  numberGoodL_++;
  startColumnL[numberGoodL_] = l + numberInPivotColumn;
  lengthL_ += numberInPivotColumn;
  if (pivotRowPosition < 0) {
    for (pivotRowPosition = startColumn; pivotRowPosition < endColumn; pivotRowPosition++) {
      CoinSimplexInt iRow = indexRowU[pivotRowPosition];
      if (iRow != pivotRow) {
        indexRowL[l] = iRow;
        elementL[l] = elementU[pivotRowPosition];
        markRow[iRow] = l - lSave;
        l++;
        //take out of row list
        CoinBigIndex start = startRowU[iRow];
        CoinBigIndex end = start + numberInRow[iRow];
        CoinBigIndex where = start;

        while (indexColumnU[where] != pivotColumn) {
          where++;
        } /* endwhile */
#if DEBUG_COIN
        if (where >= end) {
          abort();
        }
#endif
#if BOTH_WAYS
#endif
        indexColumnU[where] = indexColumnU[end - 1];
        numberInRow[iRow]--;
      } else {
        break;
      }
    }
  } else {
    CoinBigIndex i;

    for (i = startColumn; i < pivotRowPosition; i++) {
      CoinSimplexInt iRow = indexRowU[i];

      markRow[iRow] = l - lSave;
      indexRowL[l] = iRow;
      elementL[l] = elementU[i];
      l++;
      //take out of row list
      CoinBigIndex start = startRowU[iRow];
      CoinBigIndex end = start + numberInRow[iRow];
      CoinBigIndex where = start;

      while (indexColumnU[where] != pivotColumn) {
        where++;
      } /* endwhile */
#if DEBUG_COIN
      if (where >= end) {
        abort();
      }
#endif
#if BOTH_WAYS
#endif
      indexColumnU[where] = indexColumnU[end - 1];
      numberInRow[iRow]--;
      assert(numberInRow[iRow] >= 0);
    }
  }
  assert(pivotRowPosition < endColumn);
  assert(indexRowU[pivotRowPosition] == pivotRow);
  CoinFactorizationDouble pivotElement = elementU[pivotRowPosition];
  CoinFactorizationDouble pivotMultiplier = 1.0 / pivotElement;

  pivotRegionAddress_[numberGoodU_] = pivotMultiplier;
  pivotRowPosition++;
  for (; pivotRowPosition < endColumn; pivotRowPosition++) {
    CoinSimplexInt iRow = indexRowU[pivotRowPosition];

    markRow[iRow] = l - lSave;
    indexRowL[l] = iRow;
    elementL[l] = elementU[pivotRowPosition];
    l++;
    //take out of row list
    CoinBigIndex start = startRowU[iRow];
    CoinBigIndex end = start + numberInRow[iRow];
    CoinBigIndex where = start;
    // could vectorize?
    while (indexColumnU[where] != pivotColumn) {
      where++;
    } /* endwhile */
#if DEBUG_COIN
    if (where >= end) {
      abort();
    }
#endif
#if BOTH_WAYS
#endif
    indexColumnU[where] = indexColumnU[end - 1];
    numberInRow[iRow]--;
    assert(numberInRow[iRow] >= 0);
  }
  markRow[pivotRow] = LARGE_SET;
  //compress pivot column (move pivot to front including saved)
  numberInColumn[pivotColumn] = 0;
  //use end of L for temporary space
  CoinSimplexInt *COIN_RESTRICT indexL = &indexRowL[lSave];
  CoinFactorizationDouble *COIN_RESTRICT multipliersL = &elementL[lSave];

  //adjust
  CoinSimplexInt j;

  for (j = 0; j < numberInPivotColumn; j++) {
    multipliersL[j] *= pivotMultiplier;
  }
  CoinBigIndex added = numberInPivotRow * numberInPivotColumn;
  //zero out fill
  CoinBigIndex iErase;
  for (iErase = 0; iErase < increment2 * numberInPivotRow;
       iErase++) {
    workArea2[iErase] = 0;
  }
  CoinSimplexUnsignedInt *COIN_RESTRICT temp2 = workArea2;
  CoinSimplexInt *COIN_RESTRICT nextColumn = nextColumn_.array();

  //pack down and move to work
  CoinSimplexInt jColumn;
  for (jColumn = 0; jColumn < numberInPivotRow; jColumn++) {
    CoinSimplexInt iColumn = saveColumn[jColumn];
    CoinBigIndex startColumn = startColumnU[iColumn];
    CoinBigIndex endColumn = startColumn + numberInColumn[iColumn];
    CoinSimplexInt iRow = indexRowU[startColumn];
    CoinFactorizationDouble value = elementU[startColumn];
    CoinSimplexDouble largest;
    CoinBigIndex put = startColumn;
    CoinBigIndex positionLargest = -1;
    CoinFactorizationDouble thisPivotValue = 0.0;

    //compress column and find largest not updated
    bool checkLargest;
    CoinSimplexInt mark = markRow[iRow];

    if (mark == LARGE_UNSET) {
      largest = fabs(value);
      positionLargest = put;
      put++;
      checkLargest = false;
    } else {
      //need to find largest
      largest = 0.0;
      checkLargest = true;
      if (mark != LARGE_SET) {
        //will be updated
        work[mark] = value;
        CoinSimplexInt word = mark >> COINFACTORIZATION_SHIFT_PER_INT;
        CoinSimplexInt bit = mark & COINFACTORIZATION_MASK_PER_INT;

        temp2[word] = temp2[word] | (1 << bit); //say already in counts
        added--;
      } else {
        thisPivotValue = value;
      }
    }
    CoinBigIndex i;
    for (i = startColumn + 1; i < endColumn; i++) {
      iRow = indexRowU[i];
      value = elementU[i];
      CoinSimplexInt mark = markRow[iRow];

      if (mark == LARGE_UNSET) {
        //keep
        indexRowU[put] = iRow;
#if BOTH_WAYS
#endif
        elementU[put] = value;
        if (checkLargest) {
          CoinSimplexDouble absValue = fabs(value);

          if (absValue > largest) {
            largest = absValue;
            positionLargest = put;
          }
        }
        put++;
      } else if (mark != LARGE_SET) {
        //will be updated
        work[mark] = value;
        CoinSimplexInt word = mark >> COINFACTORIZATION_SHIFT_PER_INT;
        CoinSimplexInt bit = mark & COINFACTORIZATION_MASK_PER_INT;

        temp2[word] = temp2[word] | (1 << bit); //say already in counts
        added--;
      } else {
        thisPivotValue = value;
      }
    }
    //slot in pivot
    elementU[put] = elementU[startColumn];
    indexRowU[put] = indexRowU[startColumn];
#if BOTH_WAYS
#endif
    if (positionLargest == startColumn) {
      positionLargest = put; //follow if was largest
    }
    put++;
    elementU[startColumn] = thisPivotValue;
#ifdef SMALL_PERMUTE
    indexRowU[startColumn] = realPivotRow;
#else
    indexRowU[startColumn] = pivotRow;
#endif
#if BOTH_WAYS
#endif
    //clean up counts
    startColumn++;
    numberInColumn[iColumn] = put - startColumn;
    CoinSimplexInt *COIN_RESTRICT numberInColumnPlus = numberInColumnPlus_.array();
    numberInColumnPlus[iColumn]++;
    startColumnU[iColumn]++;
    //how much space have we got
    CoinSimplexInt next = nextColumn[iColumn];
    CoinBigIndex space;

    space = startColumnU[next] - put - numberInColumnPlus[next];
    //assume no zero elements
    if (numberInPivotColumn > space) {
      //getColumnSpace also moves fixed part
      if (!getColumnSpace(iColumn, numberInPivotColumn)) {
        return -99;
      }
      //redo starts
      positionLargest = positionLargest + startColumnU[iColumn] - startColumn;
      startColumn = startColumnU[iColumn];
      put = startColumn + numberInColumn[iColumn];
    }
    CoinSimplexDouble tolerance = zeroTolerance_;

    //CoinSimplexInt * COIN_RESTRICT nextCount = this->nextCount();
    for (j = 0; j < numberInPivotColumn; j++) {
      value = work[j] - thisPivotValue * multipliersL[j];
      CoinSimplexDouble absValue = fabs(value);

      if (absValue > tolerance) {
        work[j] = 0.0;
        assert(put < lengthAreaU_);
        elementU[put] = value;
        indexRowU[put] = indexL[j];
#if BOTH_WAYS
#endif
        if (absValue > largest) {
          largest = absValue;
          positionLargest = put;
        }
        put++;
      } else {
        work[j] = 0.0;
        added--;
        CoinSimplexInt word = j >> COINFACTORIZATION_SHIFT_PER_INT;
        CoinSimplexInt bit = j & COINFACTORIZATION_MASK_PER_INT;

        if (temp2[word] & (1 << bit)) {
          //take out of row list
          iRow = indexL[j];
          CoinBigIndex start = startRowU[iRow];
          CoinBigIndex end = start + numberInRow[iRow];
          CoinBigIndex where = start;

          while (indexColumnU[where] != iColumn) {
            where++;
          } /* endwhile */
#if DEBUG_COIN
          if (where >= end) {
            abort();
          }
#endif
#if BOTH_WAYS
#endif
          indexColumnU[where] = indexColumnU[end - 1];
          numberInRow[iRow]--;
        } else {
          //make sure won't be added
          CoinSimplexInt word = j >> COINFACTORIZATION_SHIFT_PER_INT;
          CoinSimplexInt bit = j & COINFACTORIZATION_MASK_PER_INT;

          temp2[word] = temp2[word] | (1 << bit); //say already in counts
        }
      }
    }
    numberInColumn[iColumn] = put - startColumn;
    //move largest
    if (positionLargest >= 0) {
      value = elementU[positionLargest];
      iRow = indexRowU[positionLargest];
      elementU[positionLargest] = elementU[startColumn];
      indexRowU[positionLargest] = indexRowU[startColumn];
      elementU[startColumn] = value;
      indexRowU[startColumn] = iRow;
#if BOTH_WAYS
#endif
    }
    //linked list for column
    //if ( nextCount[iColumn + numberRows_] != -2 ) {
    //modify linked list
    //deleteLink ( iColumn + numberRows_ );
    //modifyLink ( iColumn + numberRows_, numberInColumn[iColumn] );
    //}
    temp2 += increment2;
  }
  //get space for row list
  CoinSimplexUnsignedInt *COIN_RESTRICT putBase = workArea2;
  CoinSimplexInt bigLoops = numberInPivotColumn >> COINFACTORIZATION_SHIFT_PER_INT;
  CoinSimplexInt i = 0;

  // do linked lists and update counts
  while (bigLoops) {
    bigLoops--;
    CoinSimplexInt bit;
    for (bit = 0; bit < COINFACTORIZATION_BITS_PER_INT; i++, bit++) {
      CoinSimplexUnsignedInt *putThis = putBase;
      CoinSimplexInt iRow = indexL[i];

      //get space
      CoinSimplexInt number = 0;
      CoinSimplexInt jColumn;

      for (jColumn = 0; jColumn < numberInPivotRow; jColumn++) {
        CoinSimplexUnsignedInt test = *putThis;

        putThis += increment2;
        test = 1 - ((test >> bit) & 1);
        number += test;
      }
      CoinSimplexInt next = nextRow[iRow];
      CoinBigIndex space;

      space = startRowU[next] - startRowU[iRow];
      number += numberInRow[iRow];
      if (space < number) {
        if (!getRowSpace(iRow, number)) {
          return -99;
        }
      }
      // now do
      putThis = putBase;
      next = nextRow[iRow];
      number = numberInRow[iRow];
      CoinBigIndex end = startRowU[iRow] + number;
      CoinSimplexInt saveIndex = indexColumnU[startRowU[next]];

      //add in
      for (jColumn = 0; jColumn < numberInPivotRow; jColumn++) {
        CoinSimplexUnsignedInt test = *putThis;

        putThis += increment2;
        test = 1 - ((test >> bit) & 1);
        indexColumnU[end] = saveColumn[jColumn];
#if BOTH_WAYS
#endif
        end += test;
      }
      lastEntryByRowU_ = CoinMax(end, lastEntryByRowU_);
      assert(lastEntryByRowU_ <= lengthAreaU_);
      //put back next one in case zapped
      indexColumnU[startRowU[next]] = saveIndex;
#if BOTH_WAYS
#endif
      markRow[iRow] = LARGE_UNSET;
      number = end - startRowU[iRow];
      numberInRow[iRow] = number;
      //deleteLink ( iRow );
      //modifyLink ( iRow, number );
    }
    putBase++;
  } /* endwhile */
  CoinSimplexInt bit;

  for (bit = 0; i < numberInPivotColumn; i++, bit++) {
    CoinSimplexUnsignedInt *putThis = putBase;
    CoinSimplexInt iRow = indexL[i];

    //get space
    CoinSimplexInt number = 0;
    CoinSimplexInt jColumn;

    for (jColumn = 0; jColumn < numberInPivotRow; jColumn++) {
      CoinSimplexUnsignedInt test = *putThis;

      putThis += increment2;
      test = 1 - ((test >> bit) & 1);
      number += test;
    }
    CoinSimplexInt next = nextRow[iRow];
    CoinBigIndex space;

    space = startRowU[next] - startRowU[iRow];
    number += numberInRow[iRow];
    if (space < number) {
      if (!getRowSpace(iRow, number)) {
        return -99;
      }
    }
    // now do
    putThis = putBase;
    next = nextRow[iRow];
    number = numberInRow[iRow];
    CoinBigIndex end = startRowU[iRow] + number;
    CoinSimplexInt saveIndex;

    saveIndex = indexColumnU[startRowU[next]];
    //if (numberRowsSmall_==2791&&iRow==1160)
    //printf("start %d end %d\n",startRowU[iRow],end);
    //add in
    for (jColumn = 0; jColumn < numberInPivotRow; jColumn++) {
      CoinSimplexUnsignedInt test = *putThis;

      putThis += increment2;
      test = 1 - ((test >> bit) & 1);

      indexColumnU[end] = saveColumn[jColumn];
#if BOTH_WAYS
#endif
      end += test;
      //if (numberRowsSmall_==2791&&iRow==1160)
      //printf("start %d end %d test %d col %d\n",startRowU[iRow],end,test,saveColumn[jColumn]);
    }
    indexColumnU[startRowU[next]] = saveIndex;
    lastEntryByRowU_ = CoinMax(end, lastEntryByRowU_);
    assert(lastEntryByRowU_ <= lengthAreaU_);
#if BOTH_WAYS
#endif
    markRow[iRow] = LARGE_UNSET;
    number = end - startRowU[iRow];
    numberInRow[iRow] = number;
    //deleteLink ( iRow );
    //modifyLink ( iRow, number );
  }
  for (jColumn = 0; jColumn < numberInPivotRow; jColumn++) {
    CoinSimplexInt iColumn = saveColumn[jColumn];
    modifyLink(iColumn + numberRows_, numberInColumn[iColumn]);
  }
  for (int i = 0; i < numberInPivotColumn; i++) {
    int iRow = indexL[i];
    modifyLink(iRow, numberInRow[iRow]);
  }
#ifdef SMALL_PERMUTE
  // redo L indices
  for (CoinBigIndex j = lSave; j < startColumnL[numberGoodL_]; j++) {
    int iRow = indexRowL[j];
    indexRowL[j] = fromSmallToBigRow_[iRow];
  }
#endif
  markRow[pivotRow] = LARGE_UNSET;
  //modify linked list for pivots
  deleteLink(pivotRow);
  deleteLink(pivotColumn + numberRows_);
  totalElements_ += added;
  return 0;
}
// After pivoting
void CoinAbcTypeFactorization::afterPivot(CoinSimplexInt pivotRow,
  CoinSimplexInt pivotColumn)
{
#ifdef SMALL_PERMUTE
  int realPivotRow = fromSmallToBigRow_[pivotRow];
  int realPivotColumn = fromSmallToBigColumn_[pivotColumn];
  assert(permuteAddress_[realPivotRow] == numberGoodU_);
  pivotColumnAddress_[numberGoodU_] = realPivotColumn;
#else
  assert(permuteAddress_[pivotRow] == numberGoodU_);
  pivotColumnAddress_[numberGoodU_] = pivotColumn;
#endif
#ifdef ABC_USE_FUNCTION_POINTERS
  int number = numberInColumnPlusAddress_[pivotColumn];
  scatterStruct *COIN_RESTRICT scatter = scatterUColumn();
#ifdef SMALL_PERMUTE
#if ABC_USE_FUNCTION_POINTERS
  if (number < 9) {
    scatter[realPivotRow].functionPointer = AbcScatterLowSubtract[number];
  } else {
    scatter[realPivotRow].functionPointer = AbcScatterHighSubtract[number & 3];
  }
#endif
  scatter[realPivotRow].offset = lastEntryByColumnUPlus_;
  scatter[realPivotRow].number = number;
#else
#if ABC_USE_FUNCTION_POINTERS
  if (number < 9) {
    scatter[pivotRow].functionPointer = AbcScatterLowSubtract[number];
  } else {
    scatter[pivotRow].functionPointer = AbcScatterHighSubtract[number & 3];
  }
#endif
  scatter[pivotRow].offset = lastEntryByColumnUPlus_;
  scatter[pivotRow].number = number;
#endif
  // if scatter could move from inside pivot etc rather than indexRow
  CoinSimplexInt *COIN_RESTRICT indexRow = indexRowUAddress_;
  CoinFactorizationDouble *COIN_RESTRICT element = elementUAddress_;
  CoinBigIndex *COIN_RESTRICT startColumnU = startColumnUAddress_;
  CoinBigIndex startC = startColumnU[pivotColumn] - number;
  CoinFactorizationDouble pivotMultiplier = pivotRegionAddress_[numberGoodU_];
  for (int i = startC; i < startC + number; i++)
    elementUColumnPlusAddress_[lastEntryByColumnUPlus_++] = element[i] * pivotMultiplier;
  CoinAbcMemcpy(reinterpret_cast< CoinSimplexInt * >(elementUColumnPlusAddress_ + lastEntryByColumnUPlus_), indexRow + startC, number);
  lastEntryByColumnUPlus_ += (number + 1) >> 1;
#ifdef ABC_USE_FUNCTION_POINTERS
  if (!numberInColumnAddress_[pivotColumn]) {
    int iNext = nextColumnAddress_[pivotColumn];
    int iLast = lastColumnAddress_[pivotColumn];
    lastColumnAddress_[iNext] = iLast;
    assert(iLast >= 0);
    nextColumnAddress_[iLast] = iNext;
  }
#endif
#endif
  numberGoodU_++;
  numberRowsLeft_--;
#if COIN_DEBUG == 2
  checkConsistency();
#endif
}
#if ABC_DENSE_CODE
// After pivoting - returns true if need to go dense
int CoinAbcTypeFactorization::wantToGoDense()
{
  int status = 0;
  if (denseThreshold_) {
    // see whether to go dense
    // only if exact multiple
    if ((numberRowsLeft_ & 7) == 0) {
      CoinSimplexDouble full = numberRowsLeft_;
      full *= full;
      assert(full >= 0.0);
      CoinSimplexDouble leftElements = totalElements_;
      //if (numberRowsLeft_==100)
      //printf("at 100 %d elements\n",totalElements_);
      CoinSimplexDouble ratio;
      if (numberRowsLeft_ > 2000)
        ratio = 3.5;
      else if (numberRowsLeft_ > 800)
        ratio = 2.75; //3.5;
      else if (numberRowsLeft_ > 256)
        ratio = 2.0; //2.5;
      //else if (numberRowsLeft_==8)
      //ratio=200.0;
      else
        ratio = 1.5;
      //ratio=200.0;
      //ratio *=0.75;
      if ((ratio * leftElements > full && numberRowsLeft_ > abs(denseThreshold_))) {
#if 0 //ndef NDEBUG \
  //return to do dense
	CoinSimplexInt check=0;
	for (CoinSimplexInt iColumn=0;iColumn<numberRowsSmall_;iColumn++) {
	  if (numberInColumnAddress_[iColumn]) 
	    check++;
	}
	if (check!=numberRowsLeft_) {
	  printf("** mismatch %d columns left, %d rows\n",check,numberRowsLeft_);
	  //denseThreshold_=0;
	} else {
	  status=2;
	  if ((messageLevel_&4)!=0) 
	    std::cout<<"      Went dense at "<<numberRowsLeft_<<" rows "<<
	      totalElements_<<" "<<full<<" "<<leftElements<<std::endl;
	}
#else
        status = 2;
#if ABC_NORMAL_DEBUG > 1
        std::cout << "      Went dense at " << numberRowsLeft_ << " rows " << totalElements_ << " " << full << " " << leftElements << std::endl;
#endif
#endif
      }
    }
  }
  return status;
}
#endif
//  pivotRowSingleton.  Does one pivot on Row Singleton in factorization
bool CoinAbcTypeFactorization::pivotRowSingleton(CoinSimplexInt pivotRow,
  CoinSimplexInt pivotColumn)
{
  //store pivot columns (so can easily compress)
  CoinBigIndex *COIN_RESTRICT startColumnU = startColumnUAddress_;
  CoinBigIndex COIN_RESTRICT startColumn = startColumnU[pivotColumn];
  CoinSimplexInt *COIN_RESTRICT numberInRow = numberInRowAddress_;
  CoinSimplexInt *COIN_RESTRICT numberInColumn = numberInColumnAddress_;
  CoinSimplexInt numberDoColumn = numberInColumn[pivotColumn] - 1;
  CoinBigIndex endColumn = startColumn + numberDoColumn + 1;
  CoinBigIndex pivotRowPosition = startColumn;
  CoinSimplexInt *COIN_RESTRICT indexRowU = indexRowUAddress_;
  CoinSimplexInt iRow = indexRowU[pivotRowPosition];
  CoinBigIndex *COIN_RESTRICT startRowU = startRowUAddress_;
  CoinSimplexInt *COIN_RESTRICT nextRow = nextRowAddress_;
  CoinSimplexInt *COIN_RESTRICT lastRow = lastRowAddress_;

  while (iRow != pivotRow) {
    pivotRowPosition++;
    iRow = indexRowU[pivotRowPosition];
  } /* endwhile */
  assert(pivotRowPosition < endColumn);
  //store column in L, compress in U and take column out
  CoinBigIndex l = lengthL_;

  if (l + numberDoColumn > lengthAreaL_) {
    //need more memory
    if ((messageLevel_ & 4) != 0)
      std::cout << "more memory needed in middle of invert" << std::endl;
    return false;
  }
  CoinBigIndex *COIN_RESTRICT startColumnL = startColumnLAddress_;
  CoinFactorizationDouble *COIN_RESTRICT elementL = elementLAddress_;
  CoinSimplexInt *COIN_RESTRICT indexRowL = indexRowLAddress_;
  startColumnL[numberGoodL_] = l; //for luck and first time
  numberGoodL_++;
  startColumnL[numberGoodL_] = l + numberDoColumn;
  lengthL_ += numberDoColumn;
  CoinFactorizationDouble *COIN_RESTRICT elementU = elementUAddress_;
  CoinFactorizationDouble pivotElement = elementU[pivotRowPosition];
  CoinFactorizationDouble pivotMultiplier = 1.0 / pivotElement;

  pivotRegionAddress_[numberGoodU_] = pivotMultiplier;
  CoinBigIndex i;

  CoinSimplexInt *COIN_RESTRICT indexColumnU = indexColumnUAddress_;
#ifdef SMALL_PERMUTE
  int realPivotRow = fromSmallToBigRow_[pivotRow];
#endif
  for (i = startColumn; i < pivotRowPosition; i++) {
    CoinSimplexInt iRow = indexRowU[i];

#ifdef SMALL_PERMUTE
    indexRowL[l] = fromSmallToBigRow_[iRow];
#else
    indexRowL[l] = iRow;
#endif
    elementL[l] = elementU[i] * pivotMultiplier;
    l++;
    //take out of row list
    CoinBigIndex start = startRowU[iRow];
    CoinSimplexInt iNumberInRow = numberInRow[iRow];
    CoinBigIndex end = start + iNumberInRow;
    CoinBigIndex where = start;

    while (indexColumnU[where] != pivotColumn) {
      where++;
    } /* endwhile */
    assert(where < end);
#if BOTH_WAYS
#endif
    indexColumnU[where] = indexColumnU[end - 1];
    iNumberInRow--;
    numberInRow[iRow] = iNumberInRow;
    modifyLink(iRow, iNumberInRow);
  }
  for (i = pivotRowPosition + 1; i < endColumn; i++) {
    CoinSimplexInt iRow = indexRowU[i];

#ifdef SMALL_PERMUTE
    indexRowL[l] = fromSmallToBigRow_[iRow];
#else
    indexRowL[l] = iRow;
#endif
    elementL[l] = elementU[i] * pivotMultiplier;
    l++;
    //take out of row list
    CoinBigIndex start = startRowU[iRow];
    CoinSimplexInt iNumberInRow = numberInRow[iRow];
    CoinBigIndex end = start + iNumberInRow;
    CoinBigIndex where = start;

    while (indexColumnU[where] != pivotColumn) {
      where++;
    } /* endwhile */
    assert(where < end);
#if BOTH_WAYS
#endif
    indexColumnU[where] = indexColumnU[end - 1];
    iNumberInRow--;
    numberInRow[iRow] = iNumberInRow;
    modifyLink(iRow, iNumberInRow);
  }
  numberInColumn[pivotColumn] = 0;
  //modify linked list for pivots
  numberInRow[pivotRow] = 0;
  deleteLink(pivotRow);
  deleteLink(pivotColumn + numberRows_);
  //take out this bit of indexColumnU
  CoinSimplexInt next = nextRow[pivotRow];
  CoinSimplexInt last = lastRow[pivotRow];

  nextRow[last] = next;
  lastRow[next] = last;
  lastRow[pivotRow] = -2;
#ifdef SMALL_PERMUTE
  permuteAddress_[realPivotRow] = numberGoodU_;
#else
  permuteAddress_[pivotRow] = numberGoodU_;
#endif
  return true;
}

//  pivotColumnSingleton.  Does one pivot on Column Singleton in factorization
void CoinAbcTypeFactorization::pivotColumnSingleton(CoinSimplexInt pivotRow,
  CoinSimplexInt pivotColumn)
{
  CoinSimplexInt *COIN_RESTRICT numberInRow = numberInRowAddress_;
  CoinSimplexInt *COIN_RESTRICT numberInColumn = numberInColumnAddress_;
  CoinSimplexInt *COIN_RESTRICT numberInColumnPlus = numberInColumnPlusAddress_;
  //store pivot columns (so can easily compress)
  CoinSimplexInt numberDoRow = numberInRow[pivotRow] - 1;
  CoinBigIndex *COIN_RESTRICT startColumnU = startColumnUAddress_;
  CoinBigIndex startColumn = startColumnU[pivotColumn];
  CoinBigIndex *COIN_RESTRICT startRowU = startRowUAddress_;
  CoinBigIndex startRow = startRowU[pivotRow];
  CoinBigIndex endRow = startRow + numberDoRow + 1;
  CoinSimplexInt *COIN_RESTRICT nextRow = nextRowAddress_;
  CoinSimplexInt *COIN_RESTRICT lastRow = lastRowAddress_;
  //take out this bit of indexColumnU
  CoinSimplexInt next = nextRow[pivotRow];
  CoinSimplexInt last = lastRow[pivotRow];

  nextRow[last] = next;
  lastRow[next] = last;
  lastRow[pivotRow] = -2; //mark
#ifdef SMALL_PERMUTE
  int realPivotRow = fromSmallToBigRow_[pivotRow];
  permuteAddress_[realPivotRow] = numberGoodU_;
#else
  permuteAddress_[pivotRow] = numberGoodU_;
#endif
  //clean up counts
  CoinFactorizationDouble *COIN_RESTRICT elementU = elementUAddress_;
  CoinFactorizationDouble pivotElement = elementU[startColumn];

  pivotRegionAddress_[numberGoodU_] = 1.0 / pivotElement;
  numberInColumn[pivotColumn] = 0;
  CoinSimplexInt *COIN_RESTRICT indexColumnU = indexColumnUAddress_;
  CoinSimplexInt *COIN_RESTRICT indexRowU = indexRowUAddress_;
  //CoinSimplexInt *  COIN_RESTRICT saveColumn = saveColumnAddress_;
  CoinBigIndex i;
  // would I be better off doing other way first??
  for (i = startRow; i < endRow; i++) {
    CoinSimplexInt iColumn = indexColumnU[i];
    if (numberInColumn[iColumn]) {
      CoinSimplexInt number = numberInColumn[iColumn] - 1;
      //modify linked list
      modifyLink(iColumn + numberRows_, number);
      //move pivot row element
#ifdef SMALL_PERMUTE
      CoinBigIndex start = startColumnU[iColumn];
#endif
      if (number) {
#ifndef SMALL_PERMUTE
        CoinBigIndex start = startColumnU[iColumn];
#endif
        CoinBigIndex pivot = start;
        CoinSimplexInt iRow = indexRowU[pivot];
        while (iRow != pivotRow) {
          pivot++;
          iRow = indexRowU[pivot];
        }
        assert(pivot < startColumnU[iColumn] + numberInColumn[iColumn]);
#if BOTH_WAYS
#endif
        if (pivot != start) {
          //move largest one up
          CoinFactorizationDouble value = elementU[start];

          iRow = indexRowU[start];
          elementU[start] = elementU[pivot];
          assert(indexRowU[pivot] == pivotRow);
          indexRowU[start] = indexRowU[pivot];
          elementU[pivot] = elementU[start + 1];
          indexRowU[pivot] = indexRowU[start + 1];
          elementU[start + 1] = value;
          indexRowU[start + 1] = iRow;
#if BOTH_WAYS
#endif
        } else {
          //find new largest element
          CoinSimplexInt iRowSave = indexRowU[start + 1];
          CoinFactorizationDouble valueSave = elementU[start + 1];
          CoinFactorizationDouble valueLargest = fabs(valueSave);
          CoinBigIndex end = start + numberInColumn[iColumn];
          CoinBigIndex largest = start + 1;

          CoinBigIndex k;
          for (k = start + 2; k < end; k++) {
            CoinFactorizationDouble value = elementU[k];
            CoinFactorizationDouble valueAbs = fabs(value);

            if (valueAbs > valueLargest) {
              valueLargest = valueAbs;
              largest = k;
            }
          }
          indexRowU[start + 1] = indexRowU[largest];
          elementU[start + 1] = elementU[largest];
          indexRowU[largest] = iRowSave;
          elementU[largest] = valueSave;
#if BOTH_WAYS
#endif
        }
      }
#ifdef SMALL_PERMUTE
      indexRowU[start] = realPivotRow;
#endif
      //clean up counts
      numberInColumn[iColumn]--;
      numberInColumnPlus[iColumn]++;
      startColumnU[iColumn]++;
      //totalElements_--;
    }
  }
  //modify linked list for pivots
  deleteLink(pivotRow);
  deleteLink(pivotColumn + numberRows_);
  numberInRow[pivotRow] = 0;
  //put in dummy pivot in L
  CoinBigIndex l = lengthL_;

  CoinBigIndex *startColumnL = startColumnLAddress_;
  startColumnL[numberGoodL_] = l; //for luck and first time
  numberGoodL_++;
  startColumnL[numberGoodL_] = l;
}

//  getColumnSpace.  Gets space for one Column with given length
//may have to do compression  (returns true)
//also moves existing vector
bool CoinAbcTypeFactorization::getColumnSpace(CoinSimplexInt iColumn,
  CoinSimplexInt extraNeeded)
{
  CoinSimplexInt *COIN_RESTRICT numberInColumn = numberInColumnAddress_;
  CoinSimplexInt *COIN_RESTRICT numberInColumnPlus = numberInColumnPlusAddress_;
  CoinSimplexInt *COIN_RESTRICT nextColumn = nextColumnAddress_;
  CoinSimplexInt *COIN_RESTRICT lastColumn = lastColumnAddress_;
  CoinSimplexInt number = numberInColumnPlus[iColumn] + numberInColumn[iColumn];
  CoinBigIndex *COIN_RESTRICT startColumnU = startColumnUAddress_;
  CoinBigIndex space = lengthAreaU_ - lastEntryByColumnU_;
  CoinFactorizationDouble *COIN_RESTRICT elementU = elementUAddress_;
  CoinSimplexInt *COIN_RESTRICT indexRowU = indexRowUAddress_;

  if (space < extraNeeded + number + 4) {
    //compression
    CoinSimplexInt iColumn = nextColumn[maximumRowsExtra_];
    CoinBigIndex put = 0;

    while (iColumn != maximumRowsExtra_) {
      //move
      CoinBigIndex get;
      CoinBigIndex getEnd;

      if (startColumnU[iColumn] >= 0) {
        get = startColumnU[iColumn]
          - numberInColumnPlus[iColumn];
        getEnd = startColumnU[iColumn] + numberInColumn[iColumn];
        startColumnU[iColumn] = put + numberInColumnPlus[iColumn];
      } else {
        get = -startColumnU[iColumn];
        getEnd = get + numberInColumn[iColumn];
        startColumnU[iColumn] = -put;
      }
      assert(put <= get);
      for (CoinBigIndex i = get; i < getEnd; i++) {
        indexRowU[put] = indexRowU[i];
        elementU[put] = elementU[i];
#if BOTH_WAYS
#endif
        put++;
      }
      iColumn = nextColumn[iColumn];
    } /* endwhile */
    numberCompressions_++;
    lastEntryByColumnU_ = put;
    space = lengthAreaU_ - put;
    if (extraNeeded == COIN_INT_MAX >> 1) {
      return true;
    }
    if (space < extraNeeded + number + 2) {
      //need more space
      //if we can allocate bigger then do so and copy
      //if not then return so code can start again
      status_ = -99;
      return false;
    }
  }
  CoinBigIndex put = lastEntryByColumnU_;
  CoinSimplexInt next = nextColumn[iColumn];
  CoinSimplexInt last = lastColumn[iColumn];

  if (extraNeeded || next != maximumRowsExtra_) {
    //out
    nextColumn[last] = next;
    lastColumn[next] = last;
    //in at end
    last = lastColumn[maximumRowsExtra_];
    nextColumn[last] = iColumn;
    lastColumn[maximumRowsExtra_] = iColumn;
    lastColumn[iColumn] = last;
    nextColumn[iColumn] = maximumRowsExtra_;
    //move
    CoinBigIndex get = startColumnU[iColumn]
      - numberInColumnPlus[iColumn];

    startColumnU[iColumn] = put + numberInColumnPlus[iColumn];
    CoinSimplexInt *indexRow = indexRowU;
    CoinFactorizationDouble *element = elementU;
    CoinSimplexInt i = 0;

    if ((number & 1) != 0) {
      element[put] = element[get];
      indexRow[put] = indexRow[get];
#if BOTH_WAYS
#endif
      i = 1;
    }
    for (; i < number; i += 2) {
      CoinFactorizationDouble value0 = element[get + i];
      CoinFactorizationDouble value1 = element[get + i + 1];
      CoinSimplexInt index0 = indexRow[get + i];
      CoinSimplexInt index1 = indexRow[get + i + 1];

      element[put + i] = value0;
      element[put + i + 1] = value1;
      indexRow[put + i] = index0;
      indexRow[put + i + 1] = index1;
#if BOTH_WAYS
#endif
    }
    put += number;
    get += number;
    //add 2 for luck
    lastEntryByColumnU_ = put + extraNeeded + 2;
    if (lastEntryByColumnU_ > lengthAreaU_) {
      // get more memory
#ifdef CLP_DEVELOP
      printf("put %d, needed %d, start %d, length %d\n",
        put, extraNeeded, lastEntryByColumnU_,
        lengthAreaU_);
#endif
      return false;
    }
  } else {
    //take off space
    lastEntryByColumnU_ = startColumnU[last] + numberInColumn[last];
  }
  startColumnU[maximumRowsExtra_] = lastEntryByColumnU_;
  return true;
}

//  getRowSpace.  Gets space for one Row with given length
//may have to do compression  (returns true)
//also moves existing vector
bool CoinAbcTypeFactorization::getRowSpace(CoinSimplexInt iRow,
  CoinSimplexInt extraNeeded)
{
  CoinSimplexInt *COIN_RESTRICT numberInRow = numberInRowAddress_;
  CoinSimplexInt number = numberInRow[iRow];
  CoinBigIndex *COIN_RESTRICT startRowU = startRowUAddress_;
  CoinBigIndex space = lengthAreaU_ - lastEntryByRowU_;
  CoinSimplexInt *COIN_RESTRICT nextRow = nextRowAddress_;
  CoinSimplexInt *COIN_RESTRICT lastRow = lastRowAddress_;
  CoinSimplexInt *COIN_RESTRICT indexColumnU = indexColumnUAddress_;

  if (space < extraNeeded + number + 2) {
    //compression
    CoinSimplexInt iRow = nextRow[numberRows_];
    CoinBigIndex put = 0;

    while (iRow != numberRows_) {
      //move
      CoinBigIndex get = startRowU[iRow];
      CoinBigIndex getEnd = startRowU[iRow] + numberInRow[iRow];

      startRowU[iRow] = put;
      if (put > get) {
        //need more space
        //if we can allocate bigger then do so and copy
        //if not then return so code can start again
        status_ = -99;
        return false;
        ;
      }
      CoinBigIndex i;
      for (i = get; i < getEnd; i++) {
        indexColumnU[put] = indexColumnU[i];
#if BOTH_WAYS
#endif
        put++;
      }
      iRow = nextRow[iRow];
    } /* endwhile */
    numberCompressions_++;
    lastEntryByRowU_ = put;
    space = lengthAreaU_ - put;
    if (space < extraNeeded + number + 2) {
      //need more space
      //if we can allocate bigger then do so and copy
      //if not then return so code can start again
      status_ = -99;
      return false;
      ;
    }
  }
  CoinBigIndex put = lastEntryByRowU_;
  CoinSimplexInt next = nextRow[iRow];
  CoinSimplexInt last = lastRow[iRow];

  //out
  nextRow[last] = next;
  lastRow[next] = last;
  //in at end
  last = lastRow[numberRows_];
  nextRow[last] = iRow;
  lastRow[numberRows_] = iRow;
  lastRow[iRow] = last;
  nextRow[iRow] = numberRows_;
  //move
  CoinBigIndex get = startRowU[iRow];

  startRowU[iRow] = put;
  while (number) {
    number--;
    indexColumnU[put] = indexColumnU[get];
#if BOTH_WAYS
#endif
    put++;
    get++;
  } /* endwhile */
  //add 4 for luck
  lastEntryByRowU_ = put + extraNeeded + 4;
  return true;
}

//  cleanup.  End of factorization
void CoinAbcTypeFactorization::cleanup()
{
#ifdef ABC_USE_FUNCTION_POINTERS
#define PRINT_LEVEL 0
  if (PRINT_LEVEL) {
    printf("----------Start---------\n");
#if PRINT_LEVEL < 2
    double smallestP = COIN_DBL_MAX;
    int iPs = -1;
    double largestP = 0.0;
    int iP = -1;
    double largestL = 0.0;
    int iL = -1;
    double largestU = 0.0;
    int iU = -1;
#endif
    for (int i = 0; i < numberRows_; i++) {
#if PRINT_LEVEL > 1
      printf("%d permute %d pivotColumn %d pivotRegion %g\n", i, permuteAddress_[i],
        pivotColumnAddress_[i], pivotRegionAddress_[i]);
#else
      if (fabs(pivotRegionAddress_[i]) > largestP) {
        iP = i;
        largestP = fabs(pivotRegionAddress_[i]);
      }
      if (fabs(pivotRegionAddress_[i]) < smallestP) {
        iPs = i;
        smallestP = fabs(pivotRegionAddress_[i]);
      }
#endif
    }
    scatterStruct *COIN_RESTRICT scatterPointer = scatterUColumn();
    CoinFactorizationDouble *COIN_RESTRICT elementUColumnPlus = elementUColumnPlusAddress_;
    for (int i = 0; i < numberRows_; i++) {
      scatterStruct &COIN_RESTRICT scatter = scatterPointer[i];
      CoinSimplexInt number = scatter.number;
#if PRINT_LEVEL > 1
      printf("pivot %d offset %d number %d\n", i, scatter.offset, number);
#endif
      const CoinFactorizationDouble *COIN_RESTRICT area = elementUColumnPlus + scatter.offset;
      const CoinBigIndex *COIN_RESTRICT indices = reinterpret_cast< const CoinBigIndex * >(area + number);
#if PRINT_LEVEL > 1
      for (int j1 = 0; j1 < number; j1 += 5) {
        for (int j = j1; j < CoinMin(number, j1 + 5); j++)
          printf("(%d,%g) ", indices[j], area[j]);
        printf("\n");
      }
#else
      for (int j = 0; j < number; j++)
        if (fabs(area[j]) > largestU) {
          iU = i;
          largestU = fabs(area[j]);
        }
#endif
    }
    printf("----------LLL---------\n");
    CoinBigIndex *COIN_RESTRICT startColumnL = startColumnLAddress_;
    CoinSimplexInt *COIN_RESTRICT indexRowL = indexRowLAddress_;
    CoinFactorizationDouble *COIN_RESTRICT elementL = elementLAddress_;
    for (int i = 0; i < numberRows_; i++) {
      int number = startColumnL[i + 1] - startColumnL[i];
      if (number) {
#if PRINT_LEVEL > 1
        int *indices = indexRowL + startColumnL[i];
        printf("%d has %d elements\n", i, number);
        for (int j1 = 0; j1 < number; j1 += 5) {
          for (int j = j1; j < CoinMin(number, j1 + 5); j++)
            printf("(%d,%g) ", indices[j], elementL[j + startColumnL[i]]);
          printf("\n");
        }
#else
        for (int j = 0; j < number; j++) {
          if (fabs(elementL[j + startColumnL[i]]) > largestL) {
            iL = i;
            largestL = fabs(elementL[j + startColumnL[i]]);
          }
        }
#endif
      }
    }
#if PRINT_LEVEL < 2
    printf("smallest pivot %g at %d, largest %g at %d - largestL %g at %d largestU %g at %d\n", smallestP, iPs, largestP, iP, largestL, iL, largestU, iU);
#endif
    printf("----------End---------\n");
  }
#endif
#ifdef ABC_ORDERED_FACTORIZATION
  {
    //int sizeL=0;
    //int sizeU=0;
    CoinSimplexInt *COIN_RESTRICT permuteA = permuteAddress_ + maximumRowsExtra_ + 1;
    CoinSimplexInt *COIN_RESTRICT permuteB = permuteA + numberRows_;
    // one may be correct
    for (int i = 0; i < numberRows_; i++) {
      int iPermute = permuteAddress_[i];
      permuteA[i] = iPermute;
      permuteB[iPermute] = i;
      permuteAddress_[i] = i;
    }
    scatterStruct *COIN_RESTRICT scatterPointer = scatterUColumn();
    CoinFactorizationDouble *COIN_RESTRICT elementUColumnPlus = elementUColumnPlusAddress_;
    for (int i = 0; i < numberRows_; i++) {
      scatterStruct &COIN_RESTRICT scatter = scatterPointer[i];
      CoinSimplexInt number = scatter.number;
      //sizeU+=number;
      CoinFactorizationDouble *COIN_RESTRICT area = elementUColumnPlus + scatter.offset;
      CoinBigIndex *COIN_RESTRICT indices = reinterpret_cast< CoinBigIndex * >(area + number);
      for (int j = 0; j < number; j++) {
        int iRow = indices[j];
        indices[j] = permuteA[iRow];
      }
    }
    CoinBigIndex *COIN_RESTRICT startColumnL = startColumnLAddress_;
    CoinSimplexInt *COIN_RESTRICT indexRowL = indexRowLAddress_;
    CoinFactorizationDouble *COIN_RESTRICT elementL = elementLAddress_;
    for (int i = 0; i < numberRows_; i++) {
      int number = startColumnL[i + 1] - startColumnL[i];
      if (number) {
        //sizeL+=number;
        int *indices = indexRowL + startColumnL[i];
        for (int j = 0; j < number; j++) {
          int iRow = indices[j];
          indices[j] = permuteA[iRow];
        }
      }
    }
    //printf("Ordered says %d L %d U\n",sizeL,sizeU);
  }
#elif 0
#ifdef ABC_USE_FUNCTION_POINTERS
  {
    int sizeL = 0;
    int sizeU = 0;
    scatterStruct *COIN_RESTRICT scatterPointer = scatterUColumn();
    for (int i = 0; i < numberRows_; i++) {
      scatterStruct &COIN_RESTRICT scatter = scatterPointer[i];
      CoinSimplexInt number = scatter.number;
      sizeU += number;
    }
    CoinBigIndex *COIN_RESTRICT startColumnL = startColumnLAddress_;
    for (int i = 0; i < numberRows_; i++) {
      int number = startColumnL[i + 1] - startColumnL[i];
      if (number)
        sizeL += number;
    }
    printf("Unordered says %d L %d U\n", sizeL, sizeU);
  }
#endif
#endif
  //free some memory here
  markRow_.conditionalDelete();
  nextRowAddress_ = nextRow_.array();
  //safety feature
  CoinSimplexInt *COIN_RESTRICT permute = permuteAddress_;
  permute[numberRows_] = 0;
#ifndef NDEBUG
  {
    if (numberGoodU_ < numberRows_)
      abort();
    char *mark = new char[numberRows_];
    memset(mark, 0, numberRows_);
    for (int i = 0; i < numberRows_; i++) {
      assert(permute[i] >= 0 && permute[i] < numberRows_);
      CoinSimplexInt k = permute[i];
      if (k < 0 || k >= numberRows_)
        printf("Bad a %d %d\n", i, k);
      assert(k >= 0 && k < numberRows_);
      if (mark[k] == 1)
        printf("Bad a %d %d\n", i, k);
      mark[k] = 1;
    }
    for (int i = 0; i < numberRows_; i++) {
      assert(mark[i] == 1);
      if (mark[i] != 1)
        printf("Bad b %d\n", i);
    }
    delete[] mark;
  }
#endif
  CoinSimplexInt *COIN_RESTRICT numberInColumnPlus = numberInColumnPlusAddress_;
  const CoinSimplexInt *COIN_RESTRICT pivotColumn = pivotColumnAddress_;
  CoinSimplexInt *COIN_RESTRICT pivotLOrder = firstCountAddress_; //tttt;//this->pivotLOrder();
  CoinBigIndex *COIN_RESTRICT startColumnU = startColumnUAddress_;
  bool cleanCopy = false;
#if ABC_SMALL < 2
  assert(numberGoodU_ == numberRows_);
  if (numberGoodU_ == numberRows_) {
#ifndef ABC_USE_FUNCTION_POINTERS
    const CoinSimplexInt *COIN_RESTRICT numberInColumn = numberInColumnPlusAddress_;
    CoinFactorizationDouble *elementU = elementUAddress_;
    CoinFactorizationDouble *elementU2 = elementRowUAddress_;
    CoinSimplexInt *COIN_RESTRICT indexRowU = indexRowUAddress_;
    CoinSimplexInt *COIN_RESTRICT indexRowU2 = indexColumnUAddress_;
    // so that just slacks will have start of 0
    CoinBigIndex size = 1;
    for (int i = 0; i < numberSlacks_; i++) {
      CoinSimplexInt iNext = pivotColumn[i];
      startColumnU[iNext] = 0;
      assert(!numberInColumn[iNext]);
    }
    for (int i = numberSlacks_; i < numberRows_; i++) {
      CoinSimplexInt iNext = pivotColumn[i];
      CoinSimplexInt number = numberInColumn[iNext];
      CoinBigIndex start = startColumnU[iNext] - number;
      startColumnU[iNext] = size;
      CoinAbcMemcpy(elementU2 + size, elementU + start, number);
      CoinAbcMemcpy(indexRowU2 + size, indexRowU + start, number);
      size += number;
    }
    // swap arrays
    elementU_.swap(elementRowU_);
    elementUAddress_ = elementU_.array();
    elementRowUAddress_ = elementRowU_.array();
    indexColumnU_.swap(indexRowU_);
    indexRowUAddress_ = indexRowU_.array();
    indexColumnUAddress_ = indexColumnU_.array();
    // Redo total elements
    totalElements_ = size;
#else
    // swap arrays
    elementU_.swap(elementRowU_);
    elementUAddress_ = elementU_.array();
    elementRowUAddress_ = elementRowU_.array();
    totalElements_ = lastEntryByColumnUPlus_;
#endif
    cleanCopy = true;
  }
#endif
#ifndef ABC_USE_FUNCTION_POINTERS
  if (!cleanCopy) {
    getColumnSpace(0, COIN_INT_MAX >> 1); //compress
    // Redo total elements
    totalElements_ = 0;
    for (int i = 0; i < numberRows_; i++) {
      CoinSimplexInt number = numberInColumnPlus[i];
      totalElements_ += number;
      startColumnU[i] -= number;
    }
  }
#endif
  // swap arrays
  numberInColumn_.swap(numberInColumnPlus_);
  numberInColumnAddress_ = numberInColumn_.array();
  numberInColumnPlusAddress_ = numberInColumnPlus_.array();
  CoinSimplexInt *COIN_RESTRICT numberInRow = numberInRowAddress_;
  CoinSimplexInt *COIN_RESTRICT numberInColumn = numberInColumnAddress_;
#if ABC_SMALL < 2
  numberInColumnPlus = numberInColumnPlusAddress_;
#endif
  //make column starts OK
  //for best cache behavior get in order (last pivot at bottom of space)
  //that will need thinking about

  lastEntryByRowU_ = totalElements_;

  CoinSimplexInt *COIN_RESTRICT back = firstCountAddress_ + numberRows_;
  CoinBigIndex *COIN_RESTRICT startRow = startRowUAddress_;
#ifndef ABC_USE_FUNCTION_POINTERS
  maximumU_ = startColumnU[numberRows_ - 1] + numberInColumn[numberRows_ - 1];
#else
  maximumU_ = lastEntryByColumnUPlus_;
#endif
#ifndef ABC_ORDERED_FACTORIZATION
  CoinFactorizationDouble *COIN_RESTRICT workArea = workAreaAddress_;
  CoinFactorizationDouble *COIN_RESTRICT pivotRegion = pivotRegionAddress_;
#else
  CoinSimplexInt *COIN_RESTRICT permuteA = permuteAddress_ + maximumRowsExtra_ + 1;
  // use work area for scatter
  scatterStruct *COIN_RESTRICT scatterPointer = scatterUColumn();
  scatterStruct *COIN_RESTRICT scatterPointerTemp = reinterpret_cast< scatterStruct * >(workAreaAddress_);
#endif
  for (CoinSimplexInt i = 0; i < numberRows_; i++) {
#ifndef ABC_ORDERED_FACTORIZATION
    CoinSimplexInt pivotOrder = permute[i];
    CoinSimplexInt columnOrder = pivotColumn[pivotOrder];
    workArea[i] = pivotRegion[pivotOrder];
    back[columnOrder] = i;
#else
    CoinSimplexInt pivotOrder = i;
    CoinSimplexInt columnOrder = pivotColumn[pivotOrder];
    int pivotOrder2 = permuteA[i];
    scatterPointerTemp[pivotOrder2] = scatterPointer[i];
    back[columnOrder] = i;
#endif
#ifndef ABC_USE_FUNCTION_POINTERS
    startRow[i] = startColumnU[columnOrder];
    numberInRow[i] = numberInColumn[columnOrder];
#endif
    pivotLOrder[pivotOrder] = i;
  }
#ifndef ABC_ORDERED_FACTORIZATION
  CoinAbcMemcpy(pivotRegion, workArea, numberRows_); // could swap
#else
  CoinAbcMemcpy(scatterPointer, scatterPointerTemp, numberRows_);
#endif
#ifndef EARLY_FACTORIZE
  workArea_.conditionalDelete();
  workAreaAddress_ = NULL;
#endif
#ifndef ABC_USE_FUNCTION_POINTERS
  //memcpy(this->pivotLOrder(),pivotLOrder,numberRows_*sizeof(int));
  // swap later
  CoinAbcMemcpy(startColumnU, startRow, numberRows_);
  CoinAbcMemcpy(numberInColumn, numberInRow, numberRows_);
#endif
#if ABC_DENSE_CODE == 2
  if (numberDense_) {
    assert(numberDense_ < 30000);
    CoinFactorizationDouble *COIN_RESTRICT denseArea = denseAreaAddress_;
    CoinFactorizationDouble *COIN_RESTRICT denseRegion = denseArea + leadingDimension_ * numberDense_;
    CoinSimplexInt *COIN_RESTRICT densePermute = reinterpret_cast< CoinSimplexInt * >(denseRegion + FACTOR_CPU * numberDense_);
    short *COIN_RESTRICT forFtran = reinterpret_cast< short * >(densePermute + numberDense_);
    short *COIN_RESTRICT forBtran = forFtran + numberDense_;
    short *COIN_RESTRICT forFtran2 = forBtran + numberDense_;
    // maybe could do inside dgetrf
    //CoinAbcMemcpy(forBtran,pivotLOrder+numberRows_-numberDense_,numberDense_);
    //CoinAbcMemcpy(forFtran,pivotLOrder+numberRows_-numberDense_,numberDense_);
    for (int i = 0; i < numberDense_; i++) {
      forBtran[i] = static_cast< short >(i);
      forFtran[i] = static_cast< short >(i);
    }
    for (int i = 0; i < numberDense_; i++) {
      int ip = densePermute[i];
      short temp = forBtran[i];
      forBtran[i] = forBtran[ip];
      forBtran[ip] = temp;
    }
    for (int i = numberDense_ - 1; i >= 0; i--) {
      int ip = densePermute[i];
      short temp = forFtran[i];
      forFtran[i] = forFtran[ip];
      forFtran[ip] = temp;
    }
#if ABC_SMALL < 3
    const CoinSimplexInt *COIN_RESTRICT pivotLBackwardOrder = permuteAddress_;
    int lastSparse = numberRows_ - numberDense_;
    forFtran -= lastSparse; // adjust
    CoinFillN(forFtran2, numberRows_, static_cast< short >(-1));
    for (int i = 0; i < numberRows_; i++) {
      int jRow = pivotLBackwardOrder[i];
      if (jRow >= lastSparse) {
        short kRow = static_cast< short >(forFtran[jRow]);
        forFtran2[i] = kRow;
      }
    }
#endif
  }
#endif
  CoinAbcMemset0(numberInRow, numberRows_ + 1);
  if ((messageLevel_ & 8)) {
    std::cout << "        length of U " << totalElements_ << ", length of L " << lengthL_;
#if ABC_SMALL < 4
    if (numberDense_)
      std::cout << " plus " << numberDense_ * numberDense_ << " from " << numberDense_ << " dense rows";
#endif
    std::cout << std::endl;
  }
#if ABC_SMALL < 4
  // and add L and dense
  totalElements_ += numberDense_ * numberDense_ + lengthL_;
#endif
#if ABC_SMALL < 2
  CoinSimplexInt *COIN_RESTRICT nextColumn = nextColumnAddress_;
  CoinSimplexInt *COIN_RESTRICT lastColumn = lastColumnAddress_;
  //goSparse2();
  // See whether to have extra copy of R
#if ABC_SMALL >= 0
  if (maximumU_ > 10 * numberRows_ || numberRows_ < 200) {
    // NO
    numberInColumnPlus_.conditionalDelete();
    numberInColumnPlusAddress_ = NULL;
    setNoGotRCopy();
  } else {
#endif
    setYesGotRCopy();
    for (int i = 0; i < numberRows_; i++) {
      lastColumn[i] = i - 1;
      nextColumn[i] = i + 1;
      numberInColumnPlus[i] = 0;
#if ABC_SMALL >= 0
    }
#endif
    nextColumn[numberRows_ - 1] = maximumRowsExtra_;
    lastColumn[maximumRowsExtra_] = numberRows_ - 1;
    nextColumn[maximumRowsExtra_] = 0;
    lastColumn[0] = maximumRowsExtra_;
  }
#endif
  numberU_ = numberGoodU_;
  numberL_ = numberGoodL_;

  CoinSimplexInt firstReal = numberSlacks_;

  CoinBigIndex *COIN_RESTRICT startColumnL = startColumnLAddress_;
  // We should know how many in L
  //CoinSimplexInt *  COIN_RESTRICT indexRowL = indexRowLAddress_;
  for (firstReal = numberSlacks_; firstReal < numberRows_; firstReal++) {
    if (startColumnL[firstReal + 1])
      break;
  }
  totalElements_ += startColumnL[numberRows_];
  baseL_ = firstReal;
  numberL_ -= firstReal;
  factorElements_ = totalElements_;
  //use L for R if room
  CoinBigIndex space = lengthAreaL_ - lengthL_;
  CoinBigIndex spaceUsed = lengthL_ + lengthU_;

  CoinSimplexInt needed = (spaceUsed + numberRows_ - 1) / numberRows_;

  needed = needed * 2 * maximumPivots_;
  if (needed < 2 * numberRows_) {
    needed = 2 * numberRows_;
  }
  if (gotRCopy()) {
    //if (numberInColumnPlusAddress_) {
    // Need double the space for R
    space = space / 2;
  }
  elementRAddress_ = elementLAddress_ + lengthL_;
  indexRowRAddress_ = indexRowLAddress_ + lengthL_;
  if (space >= needed) {
    lengthR_ = 0;
    lengthAreaR_ = space;
  } else {
    lengthR_ = 0;
    lengthAreaR_ = space;
    if ((messageLevel_ & 4))
      std::cout << "Factorization may need some increasing area space"
                << std::endl;
    if (areaFactor_) {
      areaFactor_ *= 1.1;
    } else {
      areaFactor_ = 1.1;
    }
  }
  numberR_ = 0;
}
// Returns areaFactor but adjusted for dense
double
CoinAbcTypeFactorization::adjustedAreaFactor() const
{
  double factor = areaFactor_;
#if ABC_SMALL < 4
  if (numberDense_ && areaFactor_ > 1.0) {
    double dense = numberDense_;
    dense *= dense;
    double withoutDense = totalElements_ - dense + 1.0;
    factor *= 1.0 + dense / withoutDense;
  }
#endif
  return factor;
}

//  checkConsistency.  Checks that row and column copies look OK
void CoinAbcTypeFactorization::checkConsistency()
{
  bool bad = false;

  CoinSimplexInt iRow;
  CoinBigIndex *startRowU = startRowUAddress_;
  CoinSimplexInt *numberInRow = numberInRowAddress_;
  CoinSimplexInt *numberInColumn = numberInColumnAddress_;
  CoinSimplexInt *indexColumnU = indexColumnUAddress_;
  CoinSimplexInt *indexRowU = indexRowUAddress_;
  CoinBigIndex *startColumnU = startColumnUAddress_;
  for (iRow = 0; iRow < numberRows_; iRow++) {
    if (numberInRow[iRow]) {
      CoinBigIndex startRow = startRowU[iRow];
      CoinBigIndex endRow = startRow + numberInRow[iRow];

      CoinBigIndex j;
      for (j = startRow; j < endRow; j++) {
        CoinSimplexInt iColumn = indexColumnU[j];
        CoinBigIndex startColumn = startColumnU[iColumn];
        CoinBigIndex endColumn = startColumn + numberInColumn[iColumn];
        bool found = false;

        CoinBigIndex k;
        for (k = startColumn; k < endColumn; k++) {
          if (indexRowU[k] == iRow) {
            found = true;
            break;
          }
        }
        if (!found) {
          bad = true;
          std::cout << "row " << iRow << " column " << iColumn << " Rows" << std::endl;
        }
      }
    }
  }
  CoinSimplexInt iColumn;
  for (iColumn = 0; iColumn < numberRows_; iColumn++) {
    if (numberInColumn[iColumn]) {
      CoinBigIndex startColumn = startColumnU[iColumn];
      CoinBigIndex endColumn = startColumn + numberInColumn[iColumn];

      CoinBigIndex j;
      for (j = startColumn; j < endColumn; j++) {
        CoinSimplexInt iRow = indexRowU[j];
        CoinBigIndex startRow = startRowU[iRow];
        CoinBigIndex endRow = startRow + numberInRow[iRow];
        bool found = false;

        CoinBigIndex k;
        for (k = startRow; k < endRow; k++) {
          if (indexColumnU[k] == iColumn) {
            found = true;
            break;
          }
        }
        if (!found) {
          bad = true;
          std::cout << "row " << iRow << " column " << iColumn << " Columns" << std::endl;
        }
      }
    }
  }
  if (bad) {
    abort();
  }
}
//  pivotOneOtherRow.  When just one other row so faster
bool CoinAbcTypeFactorization::pivotOneOtherRow(CoinSimplexInt pivotRow,
  CoinSimplexInt pivotColumn)
{
  CoinSimplexInt *COIN_RESTRICT numberInRow = numberInRowAddress_;
  CoinSimplexInt *COIN_RESTRICT numberInColumn = numberInColumnAddress_;
  CoinSimplexInt *COIN_RESTRICT numberInColumnPlus = numberInColumnPlusAddress_;
  CoinSimplexInt COIN_RESTRICT numberInPivotRow = numberInRow[pivotRow] - 1;
  CoinBigIndex *COIN_RESTRICT startRowU = startRowUAddress_;
  CoinBigIndex *COIN_RESTRICT startColumnU = startColumnUAddress_;
  CoinBigIndex startColumn = startColumnU[pivotColumn];
  CoinBigIndex startRow = startRowU[pivotRow];
  CoinBigIndex endRow = startRow + numberInPivotRow + 1;

  //take out this bit of indexColumnU
  CoinSimplexInt *COIN_RESTRICT nextRow = nextRowAddress_;
  CoinSimplexInt *COIN_RESTRICT lastRow = lastRowAddress_;
  CoinSimplexInt next = nextRow[pivotRow];
  CoinSimplexInt last = lastRow[pivotRow];

  nextRow[last] = next;
  lastRow[next] = last;
  lastRow[pivotRow] = -2;
#ifdef SMALL_PERMUTE
  int realPivotRow = fromSmallToBigRow_[pivotRow];
  //int realPivotColumn=fromSmallToBigColumn[pivotColumn];
#endif
#ifdef SMALL_PERMUTE
  permuteAddress_[realPivotRow] = numberGoodU_;
#else
  permuteAddress_[pivotRow] = numberGoodU_;
#endif
  numberInRow[pivotRow] = 0;
#if ABC_SMALL < 2
  // temp - switch off marker for valid row/column lookup
  sparseThreshold_ = -2;
#endif
  //store column in L, compress in U and take column out
  CoinBigIndex l = lengthL_;

  if (l + 1 > lengthAreaL_) {
    //need more memory
    if ((messageLevel_ & 4) != 0)
      std::cout << "more memory needed in middle of invert" << std::endl;
    return false;
  }
  //l+=currentAreaL_->elementByColumn-elementL_;
  //CoinBigIndex lSave=l;
  CoinBigIndex *COIN_RESTRICT startColumnL = startColumnLAddress_;
  CoinFactorizationDouble *COIN_RESTRICT elementL = elementLAddress_;
  CoinSimplexInt *COIN_RESTRICT indexRowL = indexRowLAddress_;
  startColumnL[numberGoodL_] = l; //for luck and first time
  numberGoodL_++;
  startColumnL[numberGoodL_] = l + 1;
  lengthL_++;
  CoinFactorizationDouble pivotElement;
  CoinFactorizationDouble otherMultiplier;
  CoinSimplexInt otherRow;
  CoinSimplexInt *COIN_RESTRICT saveColumn = saveColumnAddress_;
  CoinFactorizationDouble *COIN_RESTRICT elementU = elementUAddress_;
  CoinSimplexInt *COIN_RESTRICT indexRowU = indexRowUAddress_;

  if (indexRowU[startColumn] == pivotRow) {
    pivotElement = elementU[startColumn];
    otherMultiplier = elementU[startColumn + 1];
    otherRow = indexRowU[startColumn + 1];
  } else {
    pivotElement = elementU[startColumn + 1];
    otherMultiplier = elementU[startColumn];
    otherRow = indexRowU[startColumn];
  }
  CoinSimplexInt numberSave = numberInRow[otherRow];
  CoinFactorizationDouble pivotMultiplier = 1.0 / pivotElement;

  CoinFactorizationDouble *COIN_RESTRICT pivotRegion = pivotRegionAddress_;
  pivotRegion[numberGoodU_] = pivotMultiplier;
  numberInColumn[pivotColumn] = 0;
  otherMultiplier = otherMultiplier * pivotMultiplier;
#ifdef SMALL_PERMUTE
  indexRowL[l] = fromSmallToBigRow_[otherRow];
#else
  indexRowL[l] = otherRow;
#endif
  elementL[l] = otherMultiplier;
  //take out of row list
  CoinBigIndex start = startRowU[otherRow];
  CoinBigIndex end = start + numberSave;
  CoinBigIndex where = start;
  CoinSimplexInt *COIN_RESTRICT indexColumnU = indexColumnUAddress_;

  while (indexColumnU[where] != pivotColumn) {
    where++;
  } /* endwhile */
  assert(where < end);
#if BOTH_WAYS
#endif
  end--;
  indexColumnU[where] = indexColumnU[end];
  CoinSimplexInt numberAdded = 0;
  CoinSimplexInt numberDeleted = 0;

  //pack down and move to work
  CoinSimplexInt j;
  const CoinSimplexInt *COIN_RESTRICT nextCount = this->nextCountAddress_;
  CoinSimplexInt *COIN_RESTRICT nextColumn = nextColumnAddress_;
  for (j = startRow; j < endRow; j++) {
    CoinSimplexInt iColumn = indexColumnU[j];

    if (iColumn != pivotColumn) {
      CoinBigIndex startColumn = startColumnU[iColumn];
      CoinSimplexInt numberInColumnIn = numberInColumn[iColumn];
      CoinBigIndex endColumn = startColumn + numberInColumnIn;
      CoinSimplexInt iRow = indexRowU[startColumn];
      CoinFactorizationDouble value = elementU[startColumn];
      CoinFactorizationDouble largest;
      bool foundOther = false;

      //leave room for pivot
      CoinBigIndex put = startColumn + 1;
      CoinBigIndex positionLargest = -1;
      CoinFactorizationDouble thisPivotValue = 0.0;
      CoinFactorizationDouble otherElement = 0.0;
      CoinFactorizationDouble nextValue = elementU[put];
      ;
      CoinSimplexInt nextIRow = indexRowU[put];

      //compress column and find largest not updated
      if (iRow != pivotRow) {
        if (iRow != otherRow) {
          largest = fabs(value);
          elementU[put] = value;
          indexRowU[put] = iRow;
          positionLargest = put;
#if BOTH_WAYS
#endif
          put++;
          CoinBigIndex i;
          for (i = startColumn + 1; i < endColumn; i++) {
            iRow = nextIRow;
            value = nextValue;
            nextIRow = indexRowU[i + 1];
            nextValue = elementU[i + 1];
            if (iRow != pivotRow) {
              if (iRow != otherRow) {
                //keep
                indexRowU[put] = iRow;
                elementU[put] = value;
                ;
#if BOTH_WAYS
#endif
                put++;
              } else {
                otherElement = value;
                foundOther = true;
              }
            } else {
              thisPivotValue = value;
            }
          }
        } else {
          otherElement = value;
          foundOther = true;
          //need to find largest
          largest = 0.0;
          CoinBigIndex i;
          for (i = startColumn + 1; i < endColumn; i++) {
            iRow = nextIRow;
            value = nextValue;
            nextIRow = indexRowU[i + 1];
            nextValue = elementU[i + 1];
            if (iRow != pivotRow) {
              //keep
              indexRowU[put] = iRow;
              elementU[put] = value;
              ;
#if BOTH_WAYS
#endif
              CoinFactorizationDouble absValue = fabs(value);

              if (absValue > largest) {
                largest = absValue;
                positionLargest = put;
              }
              put++;
            } else {
              thisPivotValue = value;
            }
          }
        }
      } else {
        //need to find largest
        largest = 0.0;
        thisPivotValue = value;
        CoinBigIndex i;
        for (i = startColumn + 1; i < endColumn; i++) {
          iRow = nextIRow;
          value = nextValue;
          nextIRow = indexRowU[i + 1];
          nextValue = elementU[i + 1];
          if (iRow != otherRow) {
            //keep
            indexRowU[put] = iRow;
            elementU[put] = value;
            ;
#if BOTH_WAYS
#endif
            CoinFactorizationDouble absValue = fabs(value);

            if (absValue > largest) {
              largest = absValue;
              positionLargest = put;
            }
            put++;
          } else {
            otherElement = value;
            foundOther = true;
          }
        }
      }
      //slot in pivot
      elementU[startColumn] = thisPivotValue;
#ifdef SMALL_PERMUTE
      indexRowU[startColumn] = realPivotRow;
#else
      indexRowU[startColumn] = pivotRow;
#endif
      //clean up counts
      startColumn++;
      numberInColumn[iColumn] = put - startColumn;
      numberInColumnPlus[iColumn]++;
      startColumnU[iColumn]++;
      otherElement = otherElement - thisPivotValue * otherMultiplier;
      CoinFactorizationDouble absValue = fabs(otherElement);

      if (!TEST_LESS_THAN_TOLERANCE_REGISTER(absValue)) {
        if (!foundOther) {
          //have we space
          saveColumn[numberAdded++] = iColumn;
          CoinSimplexInt next = nextColumn[iColumn];
          CoinBigIndex space;

          space = startColumnU[next] - put - numberInColumnPlus[next];
          if (space <= 0) {
            //getColumnSpace also moves fixed part
            CoinSimplexInt number = numberInColumn[iColumn];

            if (!getColumnSpace(iColumn, number + 1)) {
              return false;
            }
            //redo starts
            positionLargest = positionLargest + startColumnU[iColumn] - startColumn;
            startColumn = startColumnU[iColumn];
            put = startColumn + number;
          }
        }
        elementU[put] = otherElement;
        indexRowU[put] = otherRow;
#if BOTH_WAYS
#endif
        if (absValue > largest) {
          largest = absValue;
          positionLargest = put;
        }
        put++;
      } else {
        if (foundOther) {
          numberDeleted++;
          //take out of row list
          CoinBigIndex where = start;

          while (indexColumnU[where] != iColumn) {
            where++;
          } /* endwhile */
          assert(where < end);
#if BOTH_WAYS
#endif
          end--;
          indexColumnU[where] = indexColumnU[end];
        }
      }
      CoinSimplexInt numberInColumnOut = put - startColumn;
      numberInColumn[iColumn] = numberInColumnOut;
      //move largest
      if (positionLargest >= 0) {
        value = elementU[positionLargest];
        iRow = indexRowU[positionLargest];
        elementU[positionLargest] = elementU[startColumn];
        indexRowU[positionLargest] = indexRowU[startColumn];
        elementU[startColumn] = value;
        indexRowU[startColumn] = iRow;
#if BOTH_WAYS
#endif
      }
      //linked list for column
      if (numberInColumnIn != numberInColumnOut && nextCount[iColumn + numberRows_] != -2) {
        //modify linked list
        modifyLink(iColumn + numberRows_, numberInColumnOut);
      }
    }
  }
  //get space for row list
  next = nextRow[otherRow];
  CoinBigIndex space;

  space = startRowU[next] - end;
  totalElements_ += numberAdded - numberDeleted;
  CoinSimplexInt number = numberAdded + (end - start);

  if (space < numberAdded) {
    numberInRow[otherRow] = end - start;
    if (!getRowSpace(otherRow, number)) {
      return false;
    }
    end = startRowU[otherRow] + end - start;
  }
  // do linked lists and update counts
  numberInRow[otherRow] = number;
  if (number != numberSave) {
    modifyLink(otherRow, number);
  }
  for (j = 0; j < numberAdded; j++) {
#if BOTH_WAYS
#endif
    indexColumnU[end++] = saveColumn[j];
  }
  lastEntryByRowU_ = CoinMax(end, lastEntryByRowU_);
  assert(lastEntryByRowU_ <= lengthAreaU_);
  //modify linked list for pivots
  deleteLink(pivotRow);
  deleteLink(pivotColumn + numberRows_);
  return true;
}
// Delete all stuff
void CoinAbcTypeFactorization::almostDestructor()
{
  gutsOfDestructor(1);
}
// PreProcesses column ordered copy of basis
void CoinAbcTypeFactorization::preProcess()
{
  CoinBigIndex numberElements = startColumnUAddress_[numberRows_ - 1]
    + numberInColumnAddress_[numberRows_ - 1];
  setNumberElementsU(numberElements);
}
// Return largest
double
CoinAbcTypeFactorization::preProcess3()
{
  CoinSimplexInt *COIN_RESTRICT numberInRow = numberInRowAddress_;
  CoinSimplexInt *COIN_RESTRICT numberInColumn = numberInColumnAddress_;
  CoinSimplexInt *COIN_RESTRICT numberInColumnPlus = numberInColumnPlusAddress_;
  CoinBigIndex *COIN_RESTRICT startRow = startRowUAddress_;
  CoinBigIndex *COIN_RESTRICT startColumn = startColumnUAddress_;

  totalElements_ = lengthU_;
  //links and initialize pivots
  CoinZeroN(numberInColumn + numberRows_, maximumRowsExtra_ + 1 - numberRows_);
  CoinSimplexInt *COIN_RESTRICT lastRow = lastRowAddress_;
  CoinSimplexInt *COIN_RESTRICT nextRow = nextRowAddress_;

  CoinFillN(pivotColumnAddress_, numberRows_, -1);
  CoinZeroN(numberInColumnPlus, maximumRowsExtra_ + 1);
  CoinZeroN(lastRow, numberRows_);
  startColumn[maximumRowsExtra_] = lengthU_;
  lastEntryByColumnU_ = lengthU_;
  lastEntryByRowU_ = lengthU_;

  //do slacks first
  //CoinBigIndex * startColumnU = startColumnUAddress_;
  CoinBigIndex *COIN_RESTRICT startColumnL = startColumnLAddress_;
  CoinSimplexInt *COIN_RESTRICT indexRow = indexRowUAddress_;
  //CoinSimplexInt * COIN_RESTRICT indexColumn = indexColumnUAddress_;
  CoinFactorizationDouble *COIN_RESTRICT element = elementUAddress_;
  CoinFactorizationDouble *COIN_RESTRICT pivotRegion = pivotRegionAddress_;
  CoinSimplexInt *COIN_RESTRICT pivotColumn = pivotColumnAddress_;
  //CoinFillN(pivotRegion,numberSlacks_,static_cast<double>(SLACK_VALUE));
  // **************** TEMP *********************
  CoinFillN(pivotRegion, numberSlacks_, static_cast< CoinFactorizationDouble >(1.0));
  CoinZeroN(startColumnL, numberSlacks_ + 1);
  CoinZeroN(numberInColumn, numberSlacks_);
  CoinZeroN(numberInColumnPlus, numberSlacks_);
#ifdef ABC_USE_FUNCTION_POINTERS
  // Use row copy
  elementUColumnPlusAddress_ = elementRowU_.array();
  scatterStruct *COIN_RESTRICT scatter = scatterUColumn();
#if ABC_USE_FUNCTION_POINTERS
  extern scatterUpdate AbcScatterLowSubtract[9];
#endif
  lastEntryByColumnUPlus_ = 1;
  //for (int i=0;i<numberRows_;i++) {
  //scatter[iRow].functionPointer=AbcScatterLow[0];
  //scatter[iRow].offset=1;
  //scatter[iRow].number=0;
  //}
  //extern scatterUpdate AbcScatterHigh[4];
#endif
  CoinSimplexInt *COIN_RESTRICT permute = permuteAddress_;
  CoinFillN(permute, numberRows_, -1);
  for (CoinSimplexInt iSlack = 0; iSlack < numberSlacks_; iSlack++) {
    // slack
    CoinSimplexInt iRow = indexRow[iSlack];
    lastRow[iRow] = -2;
    //nextRow[iRow] = numberGoodU_;	//use for permute
    permute[iRow] = iSlack;
    numberInRow[iRow] = 0;
    pivotColumn[iSlack] = iSlack;
#ifdef ABC_USE_FUNCTION_POINTERS
#if ABC_USE_FUNCTION_POINTERS
    scatter[iRow].functionPointer = AbcScatterLowSubtract[0];
#endif
    scatter[iRow].offset = 0;
    scatter[iRow].number = 0;
#endif
  }
  totalElements_ -= numberSlacks_;
  numberGoodU_ = numberSlacks_;
  numberGoodL_ = numberSlacks_;
#if CONVERTROW > 1
  CoinBigIndex *COIN_RESTRICT convertRowToColumn = convertRowToColumnUAddress_;
  CoinBigIndex *COIN_RESTRICT convertColumnToRow = convertColumnToRowUAddress_;
#endif
#ifdef SMALL_PERMUTE
  CoinSimplexInt *COIN_RESTRICT fromBigToSmallRow = reinterpret_cast< CoinSimplexInt * >(saveColumn_.array());
  CoinSimplexInt *COIN_RESTRICT indexColumn = indexColumnUAddress_;
  //move largest in column to beginning
  // If we always compress then can combine
  CoinSimplexInt *COIN_RESTRICT tempIndex = firstCountAddress_; //saveColumnAddress_;
  CoinFactorizationDouble *COIN_RESTRICT workArea = workAreaAddress_;
  // Compress
  int nSmall = 0;
  // fromBig is only used at setup time
  for (int i = 0; i < numberRows_; i++) {
    if (permute[i] >= 0) {
      // out
      fromBigToSmallRow[i] = -1;
    } else {
      // in
      fromBigToSmallRow[i] = nSmall;
      numberInRow[nSmall] = numberInRow[i];
      lastRow[nSmall] = lastRow[i];
      fromSmallToBigRow_[nSmall++] = i;
    }
  }
  nSmall = 0;
  for (CoinSimplexInt iColumn = numberSlacks_; iColumn < numberRows_; iColumn++) {
    CoinSimplexInt number = numberInColumn[iColumn];
    // use workArea and tempIndex for remaining elements
    CoinBigIndex first = startColumn[iColumn];
    int saveFirst = first;
    fromSmallToBigColumn_[nSmall] = iColumn;
    CoinBigIndex largest = -1;
    CoinFactorizationDouble valueLargest = -1.0;
    CoinSimplexInt nOther = 0;
    CoinBigIndex end = first + number;
    for (CoinBigIndex k = first; k < end; k++) {
      CoinSimplexInt iRow = indexRow[k];
      assert(iRow < numberRowsSmall_);
      CoinFactorizationDouble value = element[k];
      if (permute[iRow] < 0) {
        CoinFactorizationDouble valueAbs = fabs(value);
        if (valueAbs > valueLargest) {
          valueLargest = valueAbs;
          largest = nOther;
        }
        iRow = fromBigToSmallRow[iRow];
        assert(iRow >= 0);
        tempIndex[nOther] = iRow;
        workArea[nOther++] = value;
      } else {
        indexRow[first] = iRow;
        element[first++] = value;
      }
    }
    CoinSimplexInt nMoved = first - saveFirst;
    numberInColumnPlus[nSmall] = nMoved;
    totalElements_ -= nMoved;
    startColumn[nSmall] = first;
    //largest
    if (largest >= 0) {
      indexRow[first] = tempIndex[largest];
      element[first++] = workArea[largest];
    }
    for (CoinBigIndex k = 0; k < nOther; k++) {
      if (k != largest) {
        indexRow[first] = tempIndex[k];
        element[first++] = workArea[k];
      }
    }
    numberInColumn[nSmall] = first - startColumn[nSmall];
    nSmall++;
  }
  numberRowsSmall_ = nSmall;
  CoinAbcMemset0(numberInRow + nSmall, numberRows_ - nSmall);
  CoinAbcMemset0(numberInColumn + nSmall, numberRows_ - nSmall);
#endif
  //row part
  CoinBigIndex i = 0;
  for (CoinSimplexInt iRow = 0; iRow < numberRowsSmall_; iRow++) {
    startRow[iRow] = i;
    CoinSimplexInt n = numberInRow[iRow];
#ifndef SMALL_PERMUTE
    numberInRow[iRow] = 0;
#endif
    i += n;
  }
  startRow[numberRows_] = lengthAreaU_; //i;
  double overallLargest = 1.0;
#ifndef SMALL_PERMUTE
  CoinSimplexInt *COIN_RESTRICT indexColumn = indexColumnUAddress_;
  //move largest in column to beginning
  CoinSimplexInt *COIN_RESTRICT tempIndex = firstCountAddress_; //saveColumnAddress_;
  CoinFactorizationDouble *COIN_RESTRICT workArea = workAreaAddress_;
  for (CoinSimplexInt iColumn = numberSlacks_; iColumn < numberRows_; iColumn++) {
    CoinSimplexInt number = numberInColumn[iColumn];
    // use workArea and tempIndex for remaining elements
    CoinBigIndex first = startColumn[iColumn];
    CoinBigIndex largest = -1;
    CoinFactorizationDouble valueLargest = -1.0;
    CoinSimplexInt nOther = 0;
    CoinBigIndex end = first + number;
    for (CoinBigIndex k = first; k < end; k++) {
      CoinSimplexInt iRow = indexRow[k];
      assert(iRow < numberRowsSmall_);
      CoinFactorizationDouble value = element[k];
      if (!lastRow[iRow]) {
        numberInRow[iRow]++;
        CoinFactorizationDouble valueAbs = fabs(value);
        if (valueAbs > valueLargest) {
          valueLargest = valueAbs;
          largest = nOther;
        }
        tempIndex[nOther] = iRow;
        workArea[nOther++] = value;
#if CONVERTROW < 2
        CoinSimplexInt iLook = startRow[iRow];
        startRow[iRow] = iLook + 1;
        indexColumn[iLook] = iColumn;
#endif
#if BOTH_WAYS
#endif
      } else {
        indexRow[first] = iRow;
#if BOTH_WAYS
#endif
        element[first++] = value;
      }
    }
    overallLargest = CoinMax(overallLargest, valueLargest);
    CoinSimplexInt nMoved = first - startColumn[iColumn];
    numberInColumnPlus[iColumn] = nMoved;
    totalElements_ -= nMoved;
    startColumn[iColumn] = first;
    //largest
    if (largest >= 0) {
#if CONVERTROW > 1
      int iRow = tempIndex[largest];
      indexRow[first] = iRow;
      CoinSimplexInt iLook = startRow[iRow];
      startRow[iRow] = iLook + 1;
      indexColumn[iLook] = iColumn;
      convertRowToColumn[iLook] = first;
      convertColumnToRow[first] = iLook;
#else
      indexRow[first] = tempIndex[largest];
#endif
#if BOTH_WAYS
#endif
      element[first++] = workArea[largest];
    }
    for (CoinBigIndex k = 0; k < nOther; k++) {
      if (k != largest) {
#if CONVERTROW > 1
        int iRow = tempIndex[k];
        indexRow[first] = iRow;
        CoinSimplexInt iLook = startRow[iRow];
        startRow[iRow] = iLook + 1;
        indexColumn[iLook] = iColumn;
        convertRowToColumn[iLook] = first;
        convertColumnToRow[first] = iLook;
#else
        indexRow[first] = tempIndex[k];
#endif
#if BOTH_WAYS
#endif
        element[first++] = workArea[k];
      }
    }
    numberInColumn[iColumn] = first - startColumn[iColumn];
  }
#else
#if CONVERTROW > 1
  for (CoinSimplexInt iColumn = 0; iColumn < numberRowsSmall_; iColumn++) {
    CoinSimplexInt number = numberInColumn[iColumn];
    CoinBigIndex first = startColumn[iColumn];
    CoinBigIndex end = first + number;
    for (CoinBigIndex k = first; k < end; k++) {
      CoinSimplexInt iRow = indexRow[k];
      CoinSimplexInt iLook = startRow[iRow];
      startRow[iRow] = iLook + 1;
      indexColumn[iLook] = iColumn;
      convertRowToColumn[iLook] = k;
      convertColumnToRow[k] = iLook;
    }
  }
#endif
#endif
  for (CoinSimplexInt iRow = numberRowsSmall_ - 1; iRow > 0; iRow--)
    startRow[iRow] = startRow[iRow - 1];
  startRow[0] = 0;
  // Do links (do backwards to get rows first?)
  CoinSimplexInt *firstCount = tempIndex;
  for (int i = 0; i < numberRows_ + 2; i++) {
    firstCount[i] = i - numberRows_ - 2;
    //assert (&nextCount_[firstCount[i]]==firstCount+i);
  }
  startColumnLAddress_[0] = 0; //for luck
  CoinSimplexInt *lastColumn = lastColumnAddress_;
  CoinSimplexInt *nextColumn = nextColumnAddress_;
#ifdef SMALL_PERMUTE
  // ? do I need to do slacks (and if so can I do faster)
  for (CoinSimplexInt iColumn = 0; iColumn < numberRowsSmall_; iColumn++) {
    lastColumn[iColumn] = iColumn - 1;
    nextColumn[iColumn] = iColumn + 1;
    CoinSimplexInt number = numberInColumn[iColumn];
    addLink(iColumn + numberRows_, number);
  }
  lastColumn[maximumRowsExtra_] = numberRowsSmall_ - 1;
  nextColumn[maximumRowsExtra_] = 0;
  lastColumn[0] = maximumRowsExtra_;
  if (numberRowsSmall_)
    nextColumn[numberRowsSmall_ - 1] = maximumRowsExtra_;
#else
  lastColumn[maximumRowsExtra_] = numberRows_ - 1;
  for (CoinSimplexInt iColumn = 0; iColumn < numberRows_; iColumn++) {
    lastColumn[iColumn] = iColumn - 1;
    nextColumn[iColumn] = iColumn + 1;
    CoinSimplexInt number = numberInColumn[iColumn];
    addLink(iColumn + numberRows_, number);
  }
  nextColumn[maximumRowsExtra_] = 0;
  lastColumn[0] = maximumRowsExtra_;
  if (numberRows_)
    nextColumn[numberRows_ - 1] = maximumRowsExtra_;
#endif
  startColumn[maximumRowsExtra_] = lengthU_;
  lastEntryByColumnU_ = lengthU_;
  CoinSimplexInt jRow = numberRows_;
  for (CoinSimplexInt iRow = 0; iRow < numberRowsSmall_; iRow++) {
    CoinSimplexInt number = numberInRow[iRow];
    if (!lastRow[iRow]) {
      lastRow[iRow] = jRow;
      nextRow[jRow] = iRow;
      jRow = iRow;
      addLink(iRow, number);
    }
  }
  // Is this why startRow[max] must be 0
  lastRow[numberRows_] = jRow;
  nextRow[jRow] = numberRows_;
  //checkLinks(999);
  return overallLargest;
}
// Does post processing on valid factorization - putting variables on correct rows
void CoinAbcTypeFactorization::postProcess(const CoinSimplexInt *sequence, CoinSimplexInt *pivotVariable)
{
  const CoinSimplexInt *COIN_RESTRICT back = firstCountAddress_ + numberRows_;
  if (pivotVariable) {
#ifndef NDEBUG
    CoinFillN(pivotVariable, numberRows_, -1);
#endif
    // Redo pivot order
    for (CoinSimplexInt i = 0; i < numberRows_; i++) {
      CoinSimplexInt k = sequence[i];
      CoinSimplexInt j = back[i];
      assert(pivotVariable[j] == -1);
      pivotVariable[j] = k;
    }
  }
  // Set up permutation vector
  // these arrays start off as copies of permute
  // (and we could use permute_ instead of pivotColumn (not back though))
  CoinAbcMemcpy(pivotColumnAddress_, permuteAddress_, numberRows_);
  // See if worth going sparse and when
  checkSparse();
  // Set pivotRegion in case we go off end
  pivotRegionAddress_[-1] = 0.0;
  pivotRegionAddress_[numberRows_] = 0.0;
  const CoinSimplexInt *COIN_RESTRICT pivotLOrder = this->pivotLOrderAddress_;
  CoinSimplexInt *COIN_RESTRICT pivotLinkedForwards = this->pivotLinkedForwardsAddress_;
  CoinSimplexInt *COIN_RESTRICT pivotLinkedBackwards = this->pivotLinkedBackwardsAddress_;
  CoinSimplexInt iThis = -1;
  for (int i = 0; i < numberSlacks_; i++) {
#ifndef ABC_ORDERED_FACTORIZATION
    CoinSimplexInt iNext = pivotLOrder[i];
#else
    CoinSimplexInt iNext = i;
#endif
    pivotLinkedForwards[iThis] = iNext;
    iThis = iNext;
  }
  lastSlack_ = iThis;
  for (int i = numberSlacks_; i < numberRows_; i++) {
#ifndef ABC_ORDERED_FACTORIZATION
    CoinSimplexInt iNext = pivotLOrder[i];
#else
    CoinSimplexInt iNext = i;
#endif
    pivotLinkedForwards[iThis] = iNext;
    iThis = iNext;
  }
  pivotLinkedForwards[iThis] = numberRows_;
  pivotLinkedForwards[numberRows_] = -1;
  iThis = numberRows_;
  for (int i = numberRows_ - 1; i >= 0; i--) {
#ifndef ABC_ORDERED_FACTORIZATION
    CoinSimplexInt iNext = pivotLOrder[i];
#else
    CoinSimplexInt iNext = i;
#endif
    pivotLinkedBackwards[iThis] = iNext;
    iThis = iNext;
  }
  pivotLinkedBackwards[iThis] = -1;
  pivotLinkedBackwards[-1] = -2;
#if 0 //ndef NDEBUG
  {
    char * test = new char[numberRows_];
    memset(test,0,numberRows_);
    CoinBigIndex *  COIN_RESTRICT startColumnL = startColumnLAddress_;
    CoinSimplexInt *  COIN_RESTRICT indexRowL = indexRowLAddress_;
    const CoinSimplexInt * COIN_RESTRICT pivotLOrder = pivotLOrderAddress_;
    //CoinSimplexInt *  COIN_RESTRICT pivotLOrder = firstCountAddress_;
    //const CoinSimplexInt * COIN_RESTRICT pivotLBackwardOrder = permuteAddress_;
    for (int i=0;i<numberRows_;i++) {
      //CoinSimplexInt pivotOrder=permuteAddress_[i];
#ifndef ABC_ORDERED_FACTORIZATION
      CoinSimplexInt iRow=pivotLOrder[i];
#else
      CoinSimplexInt iRow=i;
#endif
      assert(iRow>=0&&iRow<numberRows_);
      test[iRow]=1;
      CoinBigIndex start=startColumnL[i];
      CoinBigIndex end=startColumnL[i+1];
      for (CoinBigIndex j = start;j < end; j ++ ) {
	CoinSimplexInt jRow = indexRowL[j];
	assert (test[jRow]==0);
      }
    }
    delete [] test;
  }
#endif
  //memcpy(pivotColumnAddress_,pivotLOrder,numberRows_*sizeof(CoinSimplexInt));
  if (gotRCopy()) {
    //if (numberInColumnPlusAddress_) {
    CoinBigIndex *COIN_RESTRICT startR = startColumnRAddress_ + maximumPivots_ + 1;
    // do I need to zero
    assert(startR + maximumRowsExtra_ + 1 <= firstCountAddress_ + CoinMax(5 * numberRows_, 4 * numberRows_ + 2 * maximumPivots_ + 4) + 2);
    CoinZeroN(startR, (maximumRowsExtra_ + 1));
  }
  goSparse2();
#ifndef ABC_USE_FUNCTION_POINTERS
  CoinSimplexInt *COIN_RESTRICT numberInColumn = numberInColumnAddress_;
  CoinBigIndex *COIN_RESTRICT startColumnU = startColumnUAddress_;
  CoinFactorizationDouble *COIN_RESTRICT elementU = elementUAddress_;
  CoinFactorizationDouble *COIN_RESTRICT pivotRegion = pivotRegionAddress_;
#else
  scatterStruct *COIN_RESTRICT scatterPointer = scatterUColumn();
  CoinFactorizationDouble *COIN_RESTRICT elementUColumnPlus = elementUColumnPlusAddress_;
#endif
  //lastEntryByRowU_ = totalElements_;
#if ABC_SMALL < 2
  CoinSimplexInt *COIN_RESTRICT indexRowU = indexRowUAddress_;
  if (gotUCopy()) {
    CoinSimplexInt *COIN_RESTRICT numberInRow = numberInRowAddress_;
    CoinBigIndex *COIN_RESTRICT startRow = startRowUAddress_;
    CoinSimplexInt *COIN_RESTRICT nextRow = nextRowAddress_;
    CoinSimplexInt *COIN_RESTRICT lastRow = lastRowAddress_;
    CoinSimplexInt *COIN_RESTRICT indexColumnU = indexColumnUAddress_;
#ifndef ABC_USE_FUNCTION_POINTERS
    for (CoinSimplexInt i = 0; i < numberU_; i++) {
      CoinBigIndex start = startColumnU[i];
      CoinBigIndex end = start + numberInColumn[i];
      CoinBigIndex j;
      // only needed if row copy
      for (j = start; j < end; j++) {
        CoinSimplexInt iRow = indexRowU[j];
        numberInRow[iRow]++;
      }
    }
#else
    for (CoinSimplexInt i = 0; i < numberU_; i++) {
      scatterStruct &COIN_RESTRICT scatter = scatterPointer[i];
      CoinSimplexInt number = scatter.number;
      const CoinFactorizationDouble *COIN_RESTRICT area = elementUColumnPlus + scatter.offset;
      const CoinBigIndex *COIN_RESTRICT indices = reinterpret_cast< const CoinBigIndex * >(area + number);
      for (int j = 0; j < number; j++) {
        CoinSimplexInt iRow = indices[j];
        assert(iRow >= 0 && iRow < numberRows_);
        numberInRow[iRow]++;
      }
    }
#endif
    CoinFactorizationDouble *COIN_RESTRICT elementRow = elementRowUAddress_;
    CoinBigIndex j = 0;

    CoinSimplexInt iRow;
    for (iRow = 0; iRow < numberRows_; iRow++) {
      startRow[iRow] = j;
      j += numberInRow[iRow];
    }
    lastEntryByRowU_ = j;

#if CONVERTROW
    CoinBigIndex *COIN_RESTRICT convertRowToColumn = convertRowToColumnUAddress_;
#if CONVERTROW > 2
    CoinBigIndex *COIN_RESTRICT convertColumnToRow = convertColumnToRowUAddress_;
#endif
#endif
#ifndef ABC_USE_FUNCTION_POINTERS
    CoinZeroN(numberInRow, numberRows_ + 1);
    for (CoinSimplexInt i = 0; i < numberRows_; i++) {
      CoinBigIndex start = startColumnU[i];
      CoinBigIndex end = start + numberInColumn[i];
      CoinFactorizationDouble pivotValue = pivotRegion[i];
      CoinBigIndex j;
      for (j = start; j < end; j++) {
        CoinSimplexInt iRow = indexRowU[j];
        CoinSimplexInt iLook = numberInRow[iRow];
        numberInRow[iRow] = iLook + 1;
        CoinBigIndex k = startRow[iRow] + iLook;
        indexColumnU[k] = i;
#if CONVERTROW
        convertRowToColumn[k] = j - start;
#if CONVERTROW > 2
        convertColumnToRow[j] = k;
#endif
#endif
        //multiply by pivot
        elementU[j] *= pivotValue;
        elementRow[k] = elementU[j];
      }
    }
#else
    for (CoinSimplexInt i = 0; i < numberRows_; i++) {
      scatterStruct &COIN_RESTRICT scatter = scatterPointer[i];
      CoinSimplexInt number = scatter.number;
      const CoinFactorizationDouble *COIN_RESTRICT area = elementUColumnPlus + scatter.offset;
      const CoinBigIndex *COIN_RESTRICT indices = reinterpret_cast< const CoinBigIndex * >(area + number);
      for (int j = 0; j < number; j++) {
        CoinSimplexInt iRow = indices[j];
        CoinBigIndex k = startRow[iRow];
        startRow[iRow] = k + 1;
        indexColumnU[k] = i;
#if CONVERTROW
        convertRowToColumn[k] = j;
#if CONVERTROW > 2
        convertColumnToRow[j + startColumnU[i]] = k;
        abort(); // fix
#endif
#endif
        //CoinFactorizationDouble pivotValue = pivotRegion[i];
        //multiply by pivot
        //elementU[j+startColumnU[i]] *= pivotValue;
        elementRow[k] = area[j];
      }
    }
#endif
    //CoinSimplexInt *  COIN_RESTRICT nextRow = nextRowAddress_;
    //CoinSimplexInt *  COIN_RESTRICT lastRow = lastRowAddress_;
    for (int j = numberRows_ - 1; j >= 0; j--) {
      lastRow[j] = j - 1;
      nextRow[j] = j + 1;
#ifdef ABC_USE_FUNCTION_POINTERS
      startRow[j + 1] = startRow[j];
#endif
    }
    startRow[0] = 0;
    nextRow[numberRows_ - 1] = numberRows_;
    lastRow[numberRows_] = numberRows_ - 1;
    nextRow[numberRows_] = 0;
    lastRow[0] = numberRows_;
    //memcpy(firstCountAddress_+numberRows_+1,pivotLinkedBackwards-1,(numberRows_+2)*sizeof(int));
  } else {
#endif
#ifndef ABC_USE_FUNCTION_POINTERS
    for (CoinSimplexInt i = 0; i < numberRows_; i++) {
      CoinBigIndex start = startColumnU[i];
      CoinBigIndex end = start + numberInColumn[i];
      CoinFactorizationDouble pivotValue = pivotRegion[i];
      CoinBigIndex j;
      for (j = start; j < end; j++) {
        //multiply by pivot
        elementU[j] *= pivotValue;
      }
    }
#endif
#if ABC_SMALL < 2
  }
#endif
#ifdef ABC_USE_FUNCTION_POINTERS
#if 0
  {
    CoinFactorizationDouble *  COIN_RESTRICT elementUColumnPlus = elementUColumnPlusAddress_;
    CoinSimplexInt * COIN_RESTRICT indexRow = indexRowUAddress_;
    CoinFactorizationDouble * COIN_RESTRICT element = elementUAddress_;
    CoinSimplexInt *  COIN_RESTRICT numberInColumn = numberInColumnAddress_;
    CoinBigIndex *  COIN_RESTRICT startColumnU = startColumnUAddress_;
    scatterStruct * COIN_RESTRICT scatter = scatterUColumn();
    extern scatterUpdate AbcScatterLowSubtract[9];
    extern scatterUpdate AbcScatterHighSubtract[4];
    for (int iRow=0;iRow<numberRows_;iRow++) {
      int number=scatter[iRow].number;
      CoinBigIndex offset = scatter[iRow].offset;
      CoinFactorizationDouble * COIN_RESTRICT area = elementUColumnPlus+offset;
      CoinSimplexInt * COIN_RESTRICT indices = reinterpret_cast<CoinSimplexInt *>(area+number);
      CoinSimplexInt * COIN_RESTRICT indices2 = indexRow+startColumnU[iRow];
      CoinFactorizationDouble * COIN_RESTRICT area2 = element+startColumnU[iRow];
      assert (number==numberInColumn[iRow]);
      if (number<9)
	assert (scatter[iRow].functionPointer==AbcScatterLowSubtract[number]);
      else
	assert (scatter[iRow].functionPointer==AbcScatterHighSubtract[number&3]);
      for (int i=0;i<number;i++) {
	assert (indices[i]==indices2[i]);
	assert (area[i]==area2[i]);
      }
    }
  }
#endif
#endif
}
// Makes a non-singular basis by replacing variables
void CoinAbcTypeFactorization::makeNonSingular(CoinSimplexInt *COIN_RESTRICT sequence)
{
  // Replace bad ones by correct slack
  CoinSimplexInt *COIN_RESTRICT workArea = indexRowUAddress_;
  for (CoinSimplexInt i = 0; i < numberRows_; i++)
    workArea[i] = -1;
  const CoinSimplexInt *COIN_RESTRICT pivotColumn = pivotColumnAddress_;
  const CoinSimplexInt *COIN_RESTRICT permute = permuteAddress_;
  for (CoinSimplexInt i = 0; i < numberGoodU_; i++) {
    CoinSimplexInt iOriginal = pivotColumn[i];
    assert(iOriginal >= 0);
    workArea[iOriginal] = i;
  }
  CoinSimplexInt iRow = 0;
  for (CoinSimplexInt i = 0; i < numberRows_; i++) {
    if (workArea[i] == -1) {
      while (permute[iRow] >= 0)
        iRow++;
      assert(iRow < numberRows_);
      // Put slack in basis
      sequence[i] = iRow;
      iRow++;
    }
  }
}

//  show_self.  Debug show object
void CoinAbcTypeFactorization::show_self() const
{
  CoinSimplexInt i;

  const CoinSimplexInt *pivotColumn = pivotColumnAddress_;
  for (i = 0; i < numberRows_; i++) {
    std::cout << "r " << i << " " << pivotColumn[i];
    std::cout << " " << permuteAddress_[i];
    std::cout << " " << pivotRegionAddress_[i];
    std::cout << std::endl;
  }
  for (i = 0; i < numberRows_; i++) {
    std::cout << "u " << i << " " << numberInColumnAddress_[i] << std::endl;
    CoinSimplexInt j;
    CoinSort_2(indexRowUAddress_ + startColumnUAddress_[i],
      indexRowUAddress_ + startColumnUAddress_[i] + numberInColumnAddress_[i],
      elementUAddress_ + startColumnUAddress_[i]);
    for (j = startColumnUAddress_[i]; j < startColumnUAddress_[i] + numberInColumnAddress_[i];
         j++) {
      assert(indexRowUAddress_[j] >= 0 && indexRowUAddress_[j] < numberRows_);
      assert(elementUAddress_[j] > -1.0e50 && elementUAddress_[j] < 1.0e50);
      std::cout << indexRowUAddress_[j] << " " << elementUAddress_[j] << std::endl;
    }
  }
  for (i = 0; i < numberRows_; i++) {
    std::cout << "l " << i << " " << startColumnLAddress_[i + 1] - startColumnLAddress_[i] << std::endl;
    CoinSort_2(indexRowLAddress_ + startColumnLAddress_[i],
      indexRowLAddress_ + startColumnLAddress_[i + 1],
      elementLAddress_ + startColumnLAddress_[i]);
    CoinSimplexInt j;
    for (j = startColumnLAddress_[i]; j < startColumnLAddress_[i + 1]; j++) {
      std::cout << indexRowLAddress_[j] << " " << elementLAddress_[j] << std::endl;
    }
  }
}
//  sort so can compare
void CoinAbcTypeFactorization::sort() const
{
  CoinSimplexInt i;

  for (i = 0; i < numberRows_; i++) {
    CoinSort_2(indexRowUAddress_ + startColumnUAddress_[i],
      indexRowUAddress_ + startColumnUAddress_[i] + numberInColumnAddress_[i],
      elementUAddress_ + startColumnUAddress_[i]);
  }
  for (i = 0; i < numberRows_; i++) {
    CoinSort_2(indexRowLAddress_ + startColumnLAddress_[i],
      indexRowLAddress_ + startColumnLAddress_[i + 1],
      elementLAddress_ + startColumnLAddress_[i]);
  }
}
#ifdef CHECK_LINKS
//static int ixxxxxx=0;
void CoinAbcTypeFactorization::checkLinks(int type)
{
  //if (type<1)
  return;
#if 0 //ABC_SMALL<2
  if (numberRowsSmall_!=5698)
    return;
  ixxxxxx++;
  if (fromSmallToBigRow_[3195]==3581) {
    if (permuteAddress_[3581]>=0) {
      assert (numberInRowAddress_[3195]==0);
      CoinSimplexInt * numberInColumn = numberInColumnAddress_;
      CoinSimplexInt * COIN_RESTRICT indexRow = indexRowUAddress_;
      CoinBigIndex *  COIN_RESTRICT startColumn = startColumnUAddress_;
      for (int i=startColumn[1523];i<startColumn[1523]+numberInColumn[1523];i++)
	assert (indexRow[i]!=3195);
    }
    CoinSimplexInt *  COIN_RESTRICT numberInColumn = numberInColumnAddress_;
    CoinSimplexInt *  COIN_RESTRICT numberInColumnPlus = numberInColumnPlusAddress_;
    CoinSimplexInt *  COIN_RESTRICT nextColumn = nextColumnAddress_;
    CoinBigIndex *  COIN_RESTRICT startColumnU = startColumnUAddress_;
    CoinSimplexInt iColumn = nextColumn[maximumRowsExtra_];
    //CoinBigIndex put = startColumnU[iColumn] - numberInColumnPlus[iColumn];
    //CoinBigIndex putEnd = startColumnU[iColumn] + numberInColumn[iColumn];
    CoinBigIndex putEnd = -1;
    while ( iColumn != maximumRowsExtra_ ) {
      CoinBigIndex get;
      CoinBigIndex getEnd;
      get = startColumnU[iColumn] - numberInColumnPlus[iColumn];
      getEnd = startColumnU[iColumn] + numberInColumn[iColumn];
      assert (putEnd<=get);
      putEnd=getEnd;
      iColumn = nextColumn[iColumn];
    }
  }
  if (ixxxxxx>=7615900) {
    printf("trouble ahead\n");
  }
  return;
  if (ixxxxxx<406245)
    return;
#endif
  CoinSimplexInt *COIN_RESTRICT nextCount = this->nextCount();
  CoinSimplexInt *COIN_RESTRICT firstCount = this->firstCount();
  CoinSimplexInt *COIN_RESTRICT lastCount = this->lastCount();
  CoinSimplexInt *numberInColumn = numberInColumnAddress_;
  CoinSimplexInt *numberInRow = numberInRowAddress_;
  if (type) {
    int nBad = 0;
    CoinSimplexInt *COIN_RESTRICT indexRow = indexRowUAddress_;
    CoinSimplexInt *COIN_RESTRICT indexColumn = indexColumnUAddress_;
    CoinBigIndex *COIN_RESTRICT startColumn = startColumnUAddress_;
    CoinBigIndex *COIN_RESTRICT startRow = startRowUAddress_;
    for (int i = 0; i < numberRowsSmall_; i++) {
      assert(startRow[i] + numberInRow[i] <= lastEntryByRowU_);
    }
    return;
    CoinSimplexInt *COIN_RESTRICT nextRow = nextRow_.array();
    CoinSimplexInt *COIN_RESTRICT lastRow = lastRow_.array();
    int *counts = new int[3 * numberRows_ + 2];
    int *list1 = counts + numberRows_;
    int *list2 = list1 + numberRows_ + 1;
    {
      int lastStart = -1;
      int iRow = nextRow[numberRows_];
      memset(list1, 0, numberRowsSmall_ * sizeof(int));
      while (iRow >= 0 && iRow < numberRowsSmall_) {
        int iStart = startRow[iRow];
        assert(iStart >= lastStart);
        lastStart = iStart;
        list1[iRow] = 1;
        iRow = nextRow[iRow];
      }
      for (int i = 0; i < numberRowsSmall_; i++) {
        assert(list1[i] || !numberInRow[i]);
        assert(!list1[i] || numberInRow[i]);
      }
      memset(list1, 0, numberRowsSmall_ * sizeof(int));
#if 1
      CoinSimplexInt *COIN_RESTRICT nextColumn = nextColumn_.array();
      CoinSimplexInt *COIN_RESTRICT lastColumn = lastColumn_.array();
      lastStart = -1;
      int iColumn = nextColumn[maximumRowsExtra_];
      int nDone = 0;
      while (iColumn >= 0 && iColumn < numberRowsSmall_) {
        nDone++;
        int iStart = startColumn[iColumn];
        assert(iStart >= lastStart);
        lastStart = iStart;
        list1[iColumn] = 1;
        iColumn = nextColumn[iColumn];
      }
      int nEnd = 0;
      for (int i = 0; i < numberRowsSmall_; i++) {
        if (numberInColumn[i] && nEnd == maximumRowsExtra_)
          nEnd++;
      }
      if (nEnd > 1) {
        for (int i = 0; i < numberRowsSmall_; i++) {
          if (numberInColumn[i] && nEnd == maximumRowsExtra_)
            printf("%d points to end\n", i);
        }
        assert(nEnd <= 1);
      }
      //printf("rows %d goodU %d done %d iColumn %d\n",numberRowsSmall_,numberGoodU_,nDone,iColumn);
#endif
#if 0
      for (int i=0;i<numberRowsSmall_;i++) {
	assert (list1[i]||!numberInColumn[i]);
	assert (!list1[i]||numberInColumn[i]);
	//assert (list1[i]||!numberInColumn[fromSmallToBigColumn[i]]);
	//assert (!list1[i]||numberInColumn[fromSmallToBigColumn[i]]);
      }
#endif
    }
    CoinAbcMemset0(counts, numberRows_);
    for (int iColumn = 0; iColumn < numberRows_; iColumn++) {
      for (CoinBigIndex j = startColumn[iColumn]; j < startColumn[iColumn] + numberInColumn[iColumn]; j++) {
        int iRow = indexRow[j];
        counts[iRow]++;
      }
    }
    int nTotal1 = 0;
    for (int i = 0; i < numberRows_; i++) {
      if (numberInRow[i] != counts[i]) {
        printf("Row %d numberInRow %d counts %d\n", i, numberInRow[i], counts[i]);
        int n1 = 0;
        int n2 = 0;
        for (int j = startRow[i]; j < startRow[i] + numberInRow[i]; j++)
          list1[n1++] = indexColumn[j];
        for (int iColumn = 0; iColumn < numberRows_; iColumn++) {
          for (CoinBigIndex j = startColumn[iColumn]; j < startColumn[iColumn] + numberInColumn[iColumn]; j++) {
            int iRow = indexRow[j];
            if (i == iRow)
              list2[n2++] = iColumn;
          }
        }
        std::sort(list1, list1 + n1);
        std::sort(list2, list2 + n2);
        list1[n1] = numberRows_;
        list2[n2] = numberRows_;
        n1 = 1;
        n2 = 1;
        int iLook1 = list1[0];
        int iLook2 = list2[0];
        int xx = 0;
        while (iLook1 != numberRows_ || iLook2 != numberRows_) {
          if (iLook1 == iLook2) {
            printf(" (rc %d)", iLook1);
            iLook1 = list1[n1++];
            iLook2 = list2[n2++];
          } else if (iLook1 < iLook2) {
            printf(" (r %d)", iLook1);
            iLook1 = list1[n1++];
          } else {
            printf(" (c %d)", iLook2);
            iLook2 = list2[n2++];
          }
          xx++;
          if (xx == 10) {
            printf("\n");
            xx = 0;
          }
        }
        if (xx)
          printf("\n");
        nBad++;
      }
      nTotal1 += counts[i];
    }
    CoinAbcMemset0(counts, numberRows_);
    int nTotal2 = 0;
    for (int iRow = 0; iRow < numberRows_; iRow++) {
      for (CoinBigIndex j = startRow[iRow]; j < startRow[iRow] + numberInRow[iRow]; j++) {
        int iColumn = indexColumn[j];
        counts[iColumn]++;
      }
    }
    for (int i = 0; i < numberRows_; i++) {
      if (numberInColumn[i] != counts[i]) {
        printf("Column %d numberInColumn %d counts %d\n", i, numberInColumn[i], counts[i]);
        int n1 = 0;
        int n2 = 0;
        for (int j = startColumn[i]; j < startColumn[i] + numberInColumn[i]; j++)
          list1[n1++] = indexRow[j];
        for (int iRow = 0; iRow < numberRows_; iRow++) {
          for (CoinBigIndex j = startRow[iRow]; j < startRow[iRow] + numberInRow[iRow]; j++) {
            int iColumn = indexColumn[j];
            if (i == iColumn)
              list2[n2++] = iRow;
          }
        }
        std::sort(list1, list1 + n1);
        std::sort(list2, list2 + n2);
        list1[n1] = numberRows_;
        list2[n2] = numberRows_;
        n1 = 1;
        n2 = 1;
        int iLook1 = list1[0];
        int iLook2 = list2[0];
        int xx = 0;
        while (iLook1 != numberRows_ || iLook2 != numberRows_) {
          if (iLook1 == iLook2) {
            printf(" (rc %d)", iLook1);
            iLook1 = list1[n1++];
            iLook2 = list2[n2++];
          } else if (iLook1 < iLook2) {
            printf(" (c %d)", iLook1);
            iLook1 = list1[n1++];
          } else {
            printf(" (r %d)", iLook2);
            iLook2 = list2[n2++];
          }
          xx++;
          if (xx == 10) {
            printf("\n");
            xx = 0;
          }
        }
        if (xx)
          printf("\n");
        nBad++;
      }
      nTotal2 += counts[i];
    }
    delete[] counts;
    assert(!nBad);
  }
  char *mark = new char[2 * numberRows_];
  memset(mark, 0, 2 * numberRows_);
  for (int iCount = 0; iCount < numberRowsSmall_ + 1; iCount++) {
    int next = firstCount[iCount];
#define VERBOSE 0
#if VERBOSE
    int count = 0;
#endif
    while (next >= 0) {
#if VERBOSE
      count++;
      if (iCount <= VERBOSE) {
        if (next < numberRows_)
#ifdef SMALL_PERMUTE
          printf("R%d\n", fromSmallToBigRow_[next]);
#else
          printf("R%d\n", next);
#endif
        else
          printf("C%d\n", next - numberRows_);
      }
#endif
      assert(!mark[next]);
      mark[next] = 1;
      if (next < numberRows_)
        assert(numberInRow[next] == iCount);
      else
        assert(numberInColumn[next - numberRows_] == iCount);
      int next2 = next;
      assert(next != nextCount[next]);
      next = nextCount[next];
      if (next >= 0)
        assert(next2 == lastCount[next]);
    }
#if VERBOSE
    if (count)
      printf("%d items have count %d\n", count, iCount);
#endif
  }
  delete[] mark;
}
#endif
#endif

/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2
*/
