/* $Id: ClpPredictorCorrector.cpp 1951 2013-05-01 13:32:24Z forrest $ */
// Copyright (C) 2003, International Business Machines
// Corporation and others.  All Rights Reserved.
// This code is licensed under the terms of the Eclipse Public License (EPL).

/*
   Implements crude primal dual predictor corrector algorithm

 */
//#define SOME_DEBUG

#include "CoinPragma.hpp"
#include <math.h>

#include "CoinHelperFunctions.hpp"
#include "ClpPredictorCorrector.hpp"
#include "ClpEventHandler.hpp"
#include "CoinPackedMatrix.hpp"
#include "ClpMessage.hpp"
#include "ClpCholeskyBase.hpp"
#include "ClpHelperFunctions.hpp"
#include "ClpQuadraticObjective.hpp"
#include <cfloat>
#include <cassert>
#include <string>
#include <cstdio>
#include <iostream>
#if 0
static int yyyyyy = 0;
void ClpPredictorCorrector::saveSolution(std::string fileName)
{
     FILE * fp = fopen(fileName.c_str(), "wb");
     if (fp) {
          int numberRows = numberRows_;
          int numberColumns = numberColumns_;
          fwrite(&numberRows, sizeof(int), 1, fp);
          fwrite(&numberColumns, sizeof(int), 1, fp);
          CoinWorkDouble dsave[20];
          memset(dsave, 0, sizeof(dsave));
          fwrite(dsave, sizeof(CoinWorkDouble), 20, fp);
          int msave[20];
          memset(msave, 0, sizeof(msave));
          msave[0] = numberIterations_;
          fwrite(msave, sizeof(int), 20, fp);
          fwrite(dual_, sizeof(CoinWorkDouble), numberRows, fp);
          fwrite(errorRegion_, sizeof(CoinWorkDouble), numberRows, fp);
          fwrite(rhsFixRegion_, sizeof(CoinWorkDouble), numberRows, fp);
          fwrite(solution_, sizeof(CoinWorkDouble), numberColumns, fp);
          fwrite(solution_ + numberColumns, sizeof(CoinWorkDouble), numberRows, fp);
          fwrite(diagonal_, sizeof(CoinWorkDouble), numberColumns, fp);
          fwrite(diagonal_ + numberColumns, sizeof(CoinWorkDouble), numberRows, fp);
          fwrite(wVec_, sizeof(CoinWorkDouble), numberColumns, fp);
          fwrite(wVec_ + numberColumns, sizeof(CoinWorkDouble), numberRows, fp);
          fwrite(zVec_, sizeof(CoinWorkDouble), numberColumns, fp);
          fwrite(zVec_ + numberColumns, sizeof(CoinWorkDouble), numberRows, fp);
          fwrite(upperSlack_, sizeof(CoinWorkDouble), numberColumns, fp);
          fwrite(upperSlack_ + numberColumns, sizeof(CoinWorkDouble), numberRows, fp);
          fwrite(lowerSlack_, sizeof(CoinWorkDouble), numberColumns, fp);
          fwrite(lowerSlack_ + numberColumns, sizeof(CoinWorkDouble), numberRows, fp);
          fclose(fp);
     } else {
          std::cout << "Unable to open file " << fileName << std::endl;
     }
}
#endif
// Could change on CLP_LONG_CHOLESKY or COIN_LONG_WORK?
static CoinWorkDouble eScale = 1.0e27;
static CoinWorkDouble eBaseCaution = 1.0e-12;
static CoinWorkDouble eBase = 1.0e-12;
static CoinWorkDouble eDiagonal = 1.0e25;
static CoinWorkDouble eDiagonalCaution = 1.0e18;
static CoinWorkDouble eExtra = 1.0e-12;

// main function

int ClpPredictorCorrector::solve ( )
{
     problemStatus_ = -1;
     algorithm_ = 1;
     //create all regions
     if (!createWorkingData()) {
          problemStatus_ = 4;
          return 2;
     }
#if COIN_LONG_WORK
     // reallocate some regions
     double * dualSave = dual_;
     dual_ = reinterpret_cast<double *>(new CoinWorkDouble[numberRows_]);
     double * reducedCostSave = reducedCost_;
     reducedCost_ = reinterpret_cast<double *>(new CoinWorkDouble[numberColumns_]);
#endif
     //diagonalPerturbation_=1.0e-25;
     ClpMatrixBase * saveMatrix = NULL;
     // If quadratic then make copy so we can actually scale or normalize
#ifndef NO_RTTI
     ClpQuadraticObjective * quadraticObj = (dynamic_cast< ClpQuadraticObjective*>(objective_));
#else
     ClpQuadraticObjective * quadraticObj = NULL;
     if (objective_->type() == 2)
          quadraticObj = (static_cast< ClpQuadraticObjective*>(objective_));
#endif
     /* If modeSwitch is :
        0 - normal
        1 - bit switch off centering
        2 - bit always do type 2
        4 - accept corrector nearly always
     */
     int modeSwitch = 0;
     //if (quadraticObj)
     //modeSwitch |= 1; // switch off centring for now
     //if (quadraticObj)
     //modeSwitch |=4;
     ClpObjective * saveObjective = NULL;
     if (quadraticObj) {
          // check KKT is on
          if (!cholesky_->kkt()) {
               //No!
               handler_->message(CLP_BARRIER_KKT, messages_)
                         << CoinMessageEol;
               return -1;
          }
          saveObjective = objective_;
          // We are going to make matrix full rather half
          objective_ = new ClpQuadraticObjective(*quadraticObj, 1);
     }
     bool allowIncreasingGap = (modeSwitch & 4) != 0;
     // If scaled then really scale matrix
     if (scalingFlag_ > 0 && rowScale_) {
          saveMatrix = matrix_;
          matrix_ = matrix_->scaledColumnCopy(this);
     }
     //initializeFeasible(); - this just set fixed flag
     smallestInfeasibility_ = COIN_DBL_MAX;
     int i;
     for (i = 0; i < LENGTH_HISTORY; i++)
          historyInfeasibility_[i] = COIN_DBL_MAX;

     //bool firstTime=true;
     //firstFactorization(true);
     int returnCode = cholesky_->order(this);
     if (returnCode || cholesky_->symbolic()) {
       COIN_DETAIL_PRINT(printf("Error return from symbolic - probably not enough memory\n"));
          problemStatus_ = 4;
          //delete all temporary regions
          deleteWorkingData();
          if (saveMatrix) {
               // restore normal copy
               delete matrix_;
               matrix_ = saveMatrix;
          }
          // Restore quadratic objective if necessary
          if (saveObjective) {
               delete objective_;
               objective_ = saveObjective;
          }
          return -1;
     }
     mu_ = 1.0e10;
     diagonalScaleFactor_ = 1.0;
     //set iterations
     numberIterations_ = -1;
     int numberTotal = numberRows_ + numberColumns_;
     //initialize solution here
     if(createSolution() < 0) {
       COIN_DETAIL_PRINT(printf("Not enough memory\n"));
          problemStatus_ = 4;
          //delete all temporary regions
          deleteWorkingData();
          if (saveMatrix) {
               // restore normal copy
               delete matrix_;
               matrix_ = saveMatrix;
          }
          return -1;
     }
     CoinWorkDouble * dualArray = reinterpret_cast<CoinWorkDouble *>(dual_);
     // Could try centering steps without any original step i.e. just center
     //firstFactorization(false);
     CoinZeroN(dualArray, numberRows_);
     multiplyAdd(solution_ + numberColumns_, numberRows_, -1.0, errorRegion_, 0.0);
     matrix_->times(1.0, solution_, errorRegion_);
     maximumRHSError_ = maximumAbsElement(errorRegion_, numberRows_);
     maximumBoundInfeasibility_ = maximumRHSError_;
     //CoinWorkDouble maximumDualError_=COIN_DBL_MAX;
     //initialize
     actualDualStep_ = 0.0;
     actualPrimalStep_ = 0.0;
     gonePrimalFeasible_ = false;
     goneDualFeasible_ = false;
     //bool hadGoodSolution=false;
     diagonalNorm_ = solutionNorm_;
     mu_ = solutionNorm_;
     int numberFixed = updateSolution(-COIN_DBL_MAX);
     int numberFixedTotal = numberFixed;
     //int numberRows_DroppedBefore=0;
     //CoinWorkDouble extra=eExtra;
     //CoinWorkDouble maximumPerturbation=COIN_DBL_MAX;
     //constants for infeas interior point
     const CoinWorkDouble beta2 = 0.99995;
     const CoinWorkDouble tau   = 0.00002;
     CoinWorkDouble lastComplementarityGap = COIN_DBL_MAX * 1.0e-20;
     CoinWorkDouble lastStep = 1.0;
     // use to see if to take affine
     CoinWorkDouble checkGap = COIN_DBL_MAX;
     int lastGoodIteration = 0;
     CoinWorkDouble bestObjectiveGap = COIN_DBL_MAX;
     CoinWorkDouble bestObjective = COIN_DBL_MAX;
     int bestKilled = -1;
     int saveIteration = -1;
     int saveIteration2 = -1;
     bool sloppyOptimal = false;
     // this just to be used to exit
     bool sloppyOptimal2 = false;
     CoinWorkDouble * savePi = NULL;
     CoinWorkDouble * savePrimal = NULL;
     CoinWorkDouble * savePi2 = NULL;
     CoinWorkDouble * savePrimal2 = NULL;
     // Extra regions for centering
     CoinWorkDouble * saveX = new CoinWorkDouble[numberTotal];
     CoinWorkDouble * saveY = new CoinWorkDouble[numberRows_];
     CoinWorkDouble * saveZ = new CoinWorkDouble[numberTotal];
     CoinWorkDouble * saveW = new CoinWorkDouble[numberTotal];
     CoinWorkDouble * saveSL = new CoinWorkDouble[numberTotal];
     CoinWorkDouble * saveSU = new CoinWorkDouble[numberTotal];
     // Save smallest mu used in primal dual moves
     CoinWorkDouble objScale = optimizationDirection_ /
                               (rhsScale_ * objectiveScale_);
     while (problemStatus_ < 0) {
          //#define FULL_DEBUG
#ifdef FULL_DEBUG
          {
               int i;
               printf("row    pi          artvec       rhsfx\n");
               for (i = 0; i < numberRows_; i++) {
                    printf("%d %g %g %g\n", i, dual_[i], errorRegion_[i], rhsFixRegion_[i]);
               }
               printf(" col  dsol  ddiag  dwvec  dzvec dbdslu dbdsll\n");
               for (i = 0; i < numberColumns_ + numberRows_; i++) {
                    printf(" %d %g %g %g %g %g %g\n", i, solution_[i], diagonal_[i], wVec_[i],
                           zVec_[i], upperSlack_[i], lowerSlack_[i]);
               }
          }
#endif
          complementarityGap_ = complementarityGap(numberComplementarityPairs_,
                                numberComplementarityItems_, 0);
          handler_->message(CLP_BARRIER_ITERATION, messages_)
                    << numberIterations_
                    << static_cast<double>(primalObjective_ * objScale - dblParam_[ClpObjOffset])
                    << static_cast<double>(dualObjective_ * objScale - dblParam_[ClpObjOffset])
                    << static_cast<double>(complementarityGap_)
                    << numberFixedTotal
                    << cholesky_->rank()
                    << CoinMessageEol;
	  // Check event
	  {
	    int status = eventHandler_->event(ClpEventHandler::endOfIteration);
	    if (status >= 0) {
	      problemStatus_ = 5;
	      secondaryStatus_ = ClpEventHandler::endOfIteration;
	      break;
	    }
	  }
#if 0
          if (numberIterations_ == -1) {
               saveSolution("xxx.sav");
               if (yyyyyy)
                    exit(99);
          }
#endif
          // move up history
          for (i = 1; i < LENGTH_HISTORY; i++)
               historyInfeasibility_[i-1] = historyInfeasibility_[i];
          historyInfeasibility_[LENGTH_HISTORY-1] = complementarityGap_;
          // switch off saved if changes
          //if (saveIteration+10<numberIterations_&&
          //complementarityGap_*2.0<historyInfeasibility_[0])
          //saveIteration=-1;
          lastStep = CoinMin(actualPrimalStep_, actualDualStep_);
          CoinWorkDouble goodGapChange;
          //#define KEEP_GOING_IF_FIXED 5
#ifndef KEEP_GOING_IF_FIXED
#define KEEP_GOING_IF_FIXED 10000
#endif
          if (!sloppyOptimal) {
               goodGapChange = 0.93;
          } else {
               goodGapChange = 0.7;
               if (numberFixed > KEEP_GOING_IF_FIXED)
                    goodGapChange = 0.99; // make more likely to carry on
          }
          CoinWorkDouble gapO;
          CoinWorkDouble lastGood = bestObjectiveGap;
          if (gonePrimalFeasible_ && goneDualFeasible_) {
               CoinWorkDouble largestObjective;
               if (CoinAbs(primalObjective_) > CoinAbs(dualObjective_)) {
                    largestObjective = CoinAbs(primalObjective_);
               } else {
                    largestObjective = CoinAbs(dualObjective_);
               }
               if (largestObjective < 1.0) {
                    largestObjective = 1.0;
               }
               gapO = CoinAbs(primalObjective_ - dualObjective_) / largestObjective;
               handler_->message(CLP_BARRIER_OBJECTIVE_GAP, messages_)
                         << static_cast<double>(gapO)
                         << CoinMessageEol;
               //start saving best
               bool saveIt = false;
               if (gapO < bestObjectiveGap) {
                    bestObjectiveGap = gapO;
#ifndef SAVE_ON_OBJ
                    saveIt = true;
#endif
               }
               if (primalObjective_ < bestObjective) {
                    bestObjective = primalObjective_;
#ifdef SAVE_ON_OBJ
                    saveIt = true;
#endif
               }
               if (numberFixedTotal > bestKilled) {
                    bestKilled = numberFixedTotal;
#if KEEP_GOING_IF_FIXED<10
                    saveIt = true;
#endif
               }
               if (saveIt) {
#if KEEP_GOING_IF_FIXED<10
		 COIN_DETAIL_PRINT(printf("saving\n"));
#endif
                    saveIteration = numberIterations_;
                    if (!savePi) {
                         savePi = new CoinWorkDouble[numberRows_];
                         savePrimal = new CoinWorkDouble [numberTotal];
                    }
                    CoinMemcpyN(dualArray, numberRows_, savePi);
                    CoinMemcpyN(solution_, numberTotal, savePrimal);
               } else if(gapO > 2.0 * bestObjectiveGap) {
                    //maybe be more sophisticated e.g. re-initialize having
                    //fixed variables and dropped rows
                    //std::cout <<" gap increasing "<<std::endl;
               }
               //std::cout <<"could stop"<<std::endl;
               //gapO=0.0;
               if (CoinAbs(primalObjective_ - dualObjective_) < dualTolerance()) {
                    gapO = 0.0;
               }
          } else {
               gapO = COIN_DBL_MAX;
               if (saveIteration >= 0) {
                    handler_->message(CLP_BARRIER_GONE_INFEASIBLE, messages_)
                              << CoinMessageEol;
                    CoinWorkDouble scaledRHSError = maximumRHSError_ / (solutionNorm_ + 10.0);
                    // save alternate
                    if (numberFixedTotal > bestKilled &&
                              maximumBoundInfeasibility_ < 1.0e-6 &&
                              scaledRHSError < 1.0e-2) {
                         bestKilled = numberFixedTotal;
#if KEEP_GOING_IF_FIXED<10
                         COIN_DETAIL_PRINT(printf("saving alternate\n"));
#endif
                         saveIteration2 = numberIterations_;
                         if (!savePi2) {
                              savePi2 = new CoinWorkDouble[numberRows_];
                              savePrimal2 = new CoinWorkDouble [numberTotal];
                         }
                         CoinMemcpyN(dualArray, numberRows_, savePi2);
                         CoinMemcpyN(solution_, numberTotal, savePrimal2);
                    }
                    if (sloppyOptimal2) {
                         // vaguely optimal
                         if (maximumBoundInfeasibility_ > 1.0e-2 ||
                                   scaledRHSError > 1.0e-2 ||
                                   maximumDualError_ > objectiveNorm_ * 1.0e-2) {
                              handler_->message(CLP_BARRIER_EXIT2, messages_)
                                        << saveIteration
                                        << CoinMessageEol;
                              problemStatus_ = 0; // benefit of doubt
                              break;
                         }
                    } else {
                         // not close to optimal but check if getting bad
                         CoinWorkDouble scaledRHSError = maximumRHSError_ / (solutionNorm_ + 10.0);
                         if ((maximumBoundInfeasibility_ > 1.0e-1 ||
                                   scaledRHSError > 1.0e-1 ||
                                   maximumDualError_ > objectiveNorm_ * 1.0e-1)
                                   && (numberIterations_ > 50
                                       && complementarityGap_ > 0.9 * historyInfeasibility_[0])) {
                              handler_->message(CLP_BARRIER_EXIT2, messages_)
                                        << saveIteration
                                        << CoinMessageEol;
                              break;
                         }
                         if (complementarityGap_ > 0.95 * checkGap && bestObjectiveGap < 1.0e-3 &&
                                   (numberIterations_ > saveIteration + 5 || numberIterations_ > 100)) {
                              handler_->message(CLP_BARRIER_EXIT2, messages_)
                                        << saveIteration
                                        << CoinMessageEol;
                              break;
                         }
                    }
               }
               if (complementarityGap_ > 0.5 * checkGap && primalObjective_ >
                         bestObjective + 1.0e-9 &&
                         (numberIterations_ > saveIteration + 5 || numberIterations_ > 100)) {
                    handler_->message(CLP_BARRIER_EXIT2, messages_)
                              << saveIteration
                              << CoinMessageEol;
                    break;
               }
          }
	  // See if we should be thinking about exit if diverging
	  double relativeMultiplier = 1.0 + fabs(primalObjective_) + fabs(dualObjective_);
	  // Quadratic coding is rubbish so be more forgiving?
	  if (quadraticObj)
	    relativeMultiplier *= 5.0;
	  if (gapO < 1.0e-5 + 1.0e-9 * relativeMultiplier
	      || complementarityGap_ < 0.1 + 1.0e-9 * relativeMultiplier)
	      sloppyOptimal2 = true;
          if ((gapO < 1.0e-6 || (gapO < 1.0e-4 && complementarityGap_ < 0.1)) && !sloppyOptimal) {
               sloppyOptimal = true;
               sloppyOptimal2 = true;
               handler_->message(CLP_BARRIER_CLOSE_TO_OPTIMAL, messages_)
                         << numberIterations_ << static_cast<double>(complementarityGap_)
                         << CoinMessageEol;
          }
          int numberBack = quadraticObj ? 10 : 5;
          //tryJustPredictor=true;
          //printf("trying just predictor\n");
          //}
          if (complementarityGap_ >= 1.05 * lastComplementarityGap) {
               handler_->message(CLP_BARRIER_COMPLEMENTARITY, messages_)
                         << static_cast<double>(complementarityGap_) << "increasing"
                         << CoinMessageEol;
               if (saveIteration >= 0 && sloppyOptimal2) {
                    handler_->message(CLP_BARRIER_EXIT2, messages_)
                              << saveIteration
                              << CoinMessageEol;
                    break;
               } else if (numberIterations_ - lastGoodIteration >= numberBack &&
                          complementarityGap_ < 1.0e-6) {
                    break; // not doing very well - give up
               }
          } else if (complementarityGap_ < goodGapChange * lastComplementarityGap) {
               lastGoodIteration = numberIterations_;
               lastComplementarityGap = complementarityGap_;
          } else if (numberIterations_ - lastGoodIteration >= numberBack &&
                     complementarityGap_ < 1.0e-3) {
               handler_->message(CLP_BARRIER_COMPLEMENTARITY, messages_)
                         << static_cast<double>(complementarityGap_) << "not decreasing"
                         << CoinMessageEol;
               if (gapO > 0.75 * lastGood && numberFixed < KEEP_GOING_IF_FIXED) {
                    break;
               }
          } else if (numberIterations_ - lastGoodIteration >= 2 &&
                     complementarityGap_ < 1.0e-6) {
               handler_->message(CLP_BARRIER_COMPLEMENTARITY, messages_)
                         << static_cast<double>(complementarityGap_) << "not decreasing"
                         << CoinMessageEol;
               break;
          }
          if (numberIterations_ > maximumBarrierIterations_ || hitMaximumIterations()) {
               handler_->message(CLP_BARRIER_STOPPING, messages_)
                         << CoinMessageEol;
               problemStatus_ = 3;
               onStopped(); // set secondary status
               break;
          }
          if (gapO < targetGap_) {
               problemStatus_ = 0;
               handler_->message(CLP_BARRIER_EXIT, messages_)
                         << " "
                         << CoinMessageEol;
               break;//finished
          }
          if (complementarityGap_ < 1.0e-12) {
               problemStatus_ = 0;
               handler_->message(CLP_BARRIER_EXIT, messages_)
                         << "- small complementarity gap"
                         << CoinMessageEol;
               break;//finished
          }
          if (complementarityGap_ < 1.0e-10 && gapO < 1.0e-10) {
               problemStatus_ = 0;
               handler_->message(CLP_BARRIER_EXIT, messages_)
                         << "- objective gap and complementarity gap both small"
                         << CoinMessageEol;
               break;//finished
          }
          if (gapO < 1.0e-9) {
               CoinWorkDouble value = gapO * complementarityGap_;
               value *= actualPrimalStep_;
               value *= actualDualStep_;
               //std::cout<<value<<std::endl;
               if (value < 1.0e-17 && numberIterations_ > lastGoodIteration) {
                    problemStatus_ = 0;
                    handler_->message(CLP_BARRIER_EXIT, messages_)
                              << "- objective gap and complementarity gap both smallish and small steps"
                              << CoinMessageEol;
                    break;//finished
               }
          }
          CoinWorkDouble nextGap = COIN_DBL_MAX;
          int nextNumber = 0;
          int nextNumberItems = 0;
          worstDirectionAccuracy_ = 0.0;
          int newDropped = 0;
          //Predictor step
          //prepare for cholesky.  Set up scaled diagonal in deltaX
          //  ** for efficiency may be better if scale factor known before
          CoinWorkDouble norm2 = 0.0;
          CoinWorkDouble maximumValue;
          getNorms(diagonal_, numberTotal, maximumValue, norm2);
          diagonalNorm_ = CoinSqrt(norm2 / numberComplementarityPairs_);
          diagonalScaleFactor_ = 1.0;
          CoinWorkDouble maximumAllowable = eScale;
          //scale so largest is less than allowable ? could do better
          CoinWorkDouble factor = 0.5;
          while (maximumValue > maximumAllowable) {
               diagonalScaleFactor_ *= factor;
               maximumValue *= factor;
          } /* endwhile */
          if (diagonalScaleFactor_ != 1.0) {
               handler_->message(CLP_BARRIER_SCALING, messages_)
                         << "diagonal" << static_cast<double>(diagonalScaleFactor_)
                         << CoinMessageEol;
               diagonalNorm_ *= diagonalScaleFactor_;
          }
          multiplyAdd(NULL, numberTotal, 0.0, diagonal_,
                      diagonalScaleFactor_);
          int * rowsDroppedThisTime = new int [numberRows_];
          newDropped = cholesky_->factorize(diagonal_, rowsDroppedThisTime);
          if (newDropped) {
               if (newDropped == -1) {
		 COIN_DETAIL_PRINT(printf("Out of memory\n"));
                    problemStatus_ = 4;
                    //delete all temporary regions
                    deleteWorkingData();
                    if (saveMatrix) {
                         // restore normal copy
                         delete matrix_;
                         matrix_ = saveMatrix;
                    }
                    return -1;
               } else {
#ifndef NDEBUG
                    //int newDropped2=cholesky_->factorize(diagonal_,rowsDroppedThisTime);
                    //assert(!newDropped2);
#endif
                    if (newDropped < 0 && 0) {
                         //replace dropped
                         newDropped = -newDropped;
                         //off 1 to allow for reset all
                         newDropped--;
                         //set all bits false
                         cholesky_->resetRowsDropped();
                    }
               }
          }
          delete [] rowsDroppedThisTime;
          if (cholesky_->status()) {
               std::cout << "bad cholesky?" << std::endl;
               abort();
          }
          int phase = 0; // predictor, corrector , primal dual
          CoinWorkDouble directionAccuracy = 0.0;
          bool doCorrector = true;
          bool goodMove = true;
          //set up for affine direction
          setupForSolve(phase);
          if ((modeSwitch & 2) == 0) {
               directionAccuracy = findDirectionVector(phase);
               if (directionAccuracy > worstDirectionAccuracy_) {
                    worstDirectionAccuracy_ = directionAccuracy;
               }
               if (saveIteration > 0 && directionAccuracy > 1.0) {
                    handler_->message(CLP_BARRIER_EXIT2, messages_)
                              << saveIteration
                              << CoinMessageEol;
                    break;
               }
               findStepLength(phase);
               nextGap = complementarityGap(nextNumber, nextNumberItems, 1);
               debugMove(0, actualPrimalStep_, actualDualStep_);
               debugMove(0, 1.0e-2, 1.0e-2);
          }
          CoinWorkDouble affineGap = nextGap;
          int bestPhase = 0;
          CoinWorkDouble bestNextGap = nextGap;
          // ?
          bestNextGap = CoinMax(nextGap, 0.8 * complementarityGap_);
          if (quadraticObj)
               bestNextGap = CoinMax(nextGap, 0.99 * complementarityGap_);
          if (complementarityGap_ > 1.0e-4 * numberComplementarityPairs_) {
               //std::cout <<"predicted duality gap "<<nextGap<<std::endl;
               CoinWorkDouble part1 = nextGap / numberComplementarityPairs_;
               part1 = nextGap / numberComplementarityItems_;
               CoinWorkDouble part2 = nextGap / complementarityGap_;
               mu_ = part1 * part2 * part2;
#if 0
               CoinWorkDouble papermu = complementarityGap_ / numberComplementarityPairs_;
               CoinWorkDouble affmu = nextGap / nextNumber;
               CoinWorkDouble sigma = pow(affmu / papermu, 3);
               printf("mu %g, papermu %g, affmu %g, sigma %g sigmamu %g\n",
                      mu_, papermu, affmu, sigma, sigma * papermu);
#endif
               //printf("paper mu %g\n",(nextGap*nextGap*nextGap)/(complementarityGap_*complementarityGap_*
               //					    (CoinWorkDouble) numberComplementarityPairs_));
          } else {
               CoinWorkDouble phi;
               if (numberComplementarityPairs_ <= 5000) {
                    phi = pow(static_cast<CoinWorkDouble> (numberComplementarityPairs_), 2.0);
               } else {
                    phi = pow(static_cast<CoinWorkDouble> (numberComplementarityPairs_), 1.5);
                    if (phi < 500.0 * 500.0) {
                         phi = 500.0 * 500.0;
                    }
               }
               mu_ = complementarityGap_ / phi;
          }
          //save information
          CoinWorkDouble product = affineProduct();
#if 0
          //can we do corrector step?
          CoinWorkDouble xx = complementarityGap_ * (beta2 - tau) + product;
          if (xx > 0.0) {
               CoinWorkDouble saveMu = mu_;
               CoinWorkDouble mu2 = numberComplementarityPairs_;
               mu2 = xx / mu2;
               if (mu2 > mu_) {
                    //std::cout<<" could increase to "<<mu2<<std::endl;
                    //was mu2=mu2*0.25;
                    mu2 = mu2 * 0.99;
                    if (mu2 < mu_) {
                         mu_ = mu2;
                         //std::cout<<" changing mu to "<<mu_<<std::endl;
                    } else {
                         //std::cout<<std::endl;
                    }
               } else {
                    //std::cout<<" should decrease to "<<mu2<<std::endl;
                    mu_ = 0.5 * mu2;
                    //std::cout<<" changing mu to "<<mu_<<std::endl;
               }
               handler_->message(CLP_BARRIER_MU, messages_)
                         << saveMu << mu_
                         << CoinMessageEol;
          } else {
               //std::cout<<" bad by any standards"<<std::endl;
          }
#endif
          if (complementarityGap_*(beta2 - tau) + product - mu_ * numberComplementarityPairs_ < 0.0 && 0) {
#ifdef SOME_DEBUG
               printf("failed 1 product %.18g mu %.18g - %.18g < 0.0, nextGap %.18g\n", product, mu_,
                      complementarityGap_*(beta2 - tau) + product - mu_ * numberComplementarityPairs_,
                      nextGap);
#endif
               doCorrector = false;
               if (nextGap > 0.9 * complementarityGap_ || 1) {
                    goodMove = false;
                    bestNextGap = COIN_DBL_MAX;
               }
               //CoinWorkDouble floatNumber = 2.0*numberComplementarityPairs_;
               //floatNumber = 1.0*numberComplementarityItems_;
               //mu_=nextGap/floatNumber;
               handler_->message(CLP_BARRIER_INFO, messages_)
                         << "no corrector step"
                         << CoinMessageEol;
          } else {
               phase = 1;
          }
          // If bad gap - try standard primal dual
          if (nextGap > complementarityGap_ * 1.001)
               goodMove = false;
          if ((modeSwitch & 2) != 0)
               goodMove = false;
          if (goodMove && doCorrector) {
               CoinMemcpyN(deltaX_, numberTotal, saveX);
               CoinMemcpyN(deltaY_, numberRows_, saveY);
               CoinMemcpyN(deltaZ_, numberTotal, saveZ);
               CoinMemcpyN(deltaW_, numberTotal, saveW);
               CoinMemcpyN(deltaSL_, numberTotal, saveSL);
               CoinMemcpyN(deltaSU_, numberTotal, saveSU);
#ifdef HALVE
               CoinWorkDouble savePrimalStep = actualPrimalStep_;
               CoinWorkDouble saveDualStep = actualDualStep_;
               CoinWorkDouble saveMu = mu_;
#endif
               //set up for next step
               setupForSolve(phase);
               CoinWorkDouble directionAccuracy2 = findDirectionVector(phase);
               if (directionAccuracy2 > worstDirectionAccuracy_) {
                    worstDirectionAccuracy_ = directionAccuracy2;
               }
               CoinWorkDouble testValue = 1.0e2 * directionAccuracy;
               if (1.0e2 * projectionTolerance_ > testValue) {
                    testValue = 1.0e2 * projectionTolerance_;
               }
               if (primalTolerance() > testValue) {
                    testValue = primalTolerance();
               }
               if (maximumRHSError_ > testValue) {
                    testValue = maximumRHSError_;
               }
               if (directionAccuracy2 > testValue && numberIterations_ >= -77) {
                    goodMove = false;
#ifdef SOME_DEBUG
                    printf("accuracy %g phase 1 failed, test value %g\n",
                           directionAccuracy2, testValue);
#endif
               }
               if (goodMove) {
                    phase = 1;
                    CoinWorkDouble norm = findStepLength(phase);
                    nextGap = complementarityGap(nextNumber, nextNumberItems, 1);
                    debugMove(1, actualPrimalStep_, actualDualStep_);
                    //debugMove(1,1.0e-7,1.0e-7);
                    goodMove = checkGoodMove(true, bestNextGap, allowIncreasingGap);
                    if (norm < 0)
                         goodMove = false;
                    if (!goodMove) {
#ifdef SOME_DEBUG
                         printf("checkGoodMove failed\n");
#endif
                    }
               }
#ifdef HALVE
               int nHalve = 0;
               // relax test
               bestNextGap = CoinMax(bestNextGap, 0.9 * complementarityGap_);
               while (!goodMove) {
                    mu_ = saveMu;
                    actualPrimalStep_ = savePrimalStep;
                    actualDualStep_ = saveDualStep;
                    int i;
                    //printf("halve %d\n",nHalve);
                    nHalve++;
                    const CoinWorkDouble lambda = 0.5;
                    for (i = 0; i < numberRows_; i++)
                         deltaY_[i] = lambda * deltaY_[i] + (1.0 - lambda) * saveY[i];
                    for (i = 0; i < numberTotal; i++) {
                         deltaX_[i] = lambda * deltaX_[i] + (1.0 - lambda) * saveX[i];
                         deltaZ_[i] = lambda * deltaZ_[i] + (1.0 - lambda) * saveZ[i];
                         deltaW_[i] = lambda * deltaW_[i] + (1.0 - lambda) * saveW[i];
                         deltaSL_[i] = lambda * deltaSL_[i] + (1.0 - lambda) * saveSL[i];
                         deltaSU_[i] = lambda * deltaSU_[i] + (1.0 - lambda) * saveSU[i];
                    }
                    CoinMemcpyN(saveX, numberTotal, deltaX_);
                    CoinMemcpyN(saveY, numberRows_, deltaY_);
                    CoinMemcpyN(saveZ, numberTotal, deltaZ_);
                    CoinMemcpyN(saveW, numberTotal, deltaW_);
                    CoinMemcpyN(saveSL, numberTotal, deltaSL_);
                    CoinMemcpyN(saveSU, numberTotal, deltaSU_);
                    findStepLength(1);
                    nextGap = complementarityGap(nextNumber, nextNumberItems, 1);
                    goodMove = checkGoodMove(true, bestNextGap, allowIncreasingGap);
                    if (nHalve > 10)
                         break;
                    //assert (goodMove);
               }
               if (nHalve && handler_->logLevel() > 2)
                    printf("halved %d times\n", nHalve);
#endif
          }
          //bestPhase=-1;
          //goodMove=false;
          if (!goodMove) {
               // Just primal dual step
               CoinWorkDouble floatNumber;
               floatNumber = 2.0 * numberComplementarityPairs_;
               //floatNumber = numberComplementarityItems_;
               CoinWorkDouble saveMu = mu_; // use one from predictor corrector
               mu_ = complementarityGap_ / floatNumber;
               // If going well try small mu
               mu_ *= CoinSqrt((1.0 - lastStep) / (1.0 + 10.0 * lastStep));
               CoinWorkDouble mu1 = mu_;
               CoinWorkDouble phi;
               if (numberComplementarityPairs_ <= 500) {
                    phi = pow(static_cast<CoinWorkDouble> (numberComplementarityPairs_), 2.0);
               } else {
                    phi = pow(static_cast<CoinWorkDouble> (numberComplementarityPairs_), 1.5);
                    if (phi < 500.0 * 500.0) {
                         phi = 500.0 * 500.0;
                    }
               }
               mu_ = complementarityGap_ / phi;
               //printf("pd mu %g, alternate %g, smallest\n",mu_,mu1);
               mu_ = CoinSqrt(mu_ * mu1);
               mu_ = mu1;
               if ((numberIterations_ & 1) == 0 || numberIterations_ < 10)
                    mu_ = saveMu;
               // Try simpler
               floatNumber = numberComplementarityItems_;
               mu_ = 0.5 * complementarityGap_ / floatNumber;
               //if ((modeSwitch&2)==0) {
               //if ((numberIterations_&1)==0)
               //  mu_ *= 0.5;
               //} else {
               //mu_ *= 0.8;
               //}
               //set up for next step
               setupForSolve(2);
               findDirectionVector(2);
               CoinWorkDouble norm = findStepLength(2);
               // just for debug
               bestNextGap = complementarityGap_ * 1.0005;
               //bestNextGap=COIN_DBL_MAX;
               nextGap = complementarityGap(nextNumber, nextNumberItems, 2);
               debugMove(2, actualPrimalStep_, actualDualStep_);
               //debugMove(2,1.0e-7,1.0e-7);
               checkGoodMove(false, bestNextGap, allowIncreasingGap);
               if ((nextGap > 0.9 * complementarityGap_ && bestPhase == 0 && affineGap < nextGap
                         && (numberIterations_ > 80 || (numberIterations_ > 20 && quadraticObj))) || norm < 0.0) {
                    // Back to affine
                    phase = 0;
                    setupForSolve(phase);
                    directionAccuracy = findDirectionVector(phase);
                    findStepLength(phase);
                    nextGap = complementarityGap(nextNumber, nextNumberItems, 1);
                    bestNextGap = complementarityGap_;
                    //checkGoodMove(false, bestNextGap,allowIncreasingGap);
               }
          }
          if (!goodMove)
               mu_ = nextGap / (static_cast<CoinWorkDouble> (nextNumber) * 1.1);
          //if (quadraticObj)
          //goodMove=true;
          //goodMove=false; //TEMP
          // Do centering steps
          int numberTries = 0;
          int numberGoodTries = 0;
#ifdef COIN_DETAIL
          CoinWorkDouble nextCenterGap = 0.0;
          CoinWorkDouble originalDualStep = actualDualStep_;
          CoinWorkDouble originalPrimalStep = actualPrimalStep_;
#endif
          if (actualDualStep_ > 0.9 && actualPrimalStep_ > 0.9)
               goodMove = false; // don't bother
          if ((modeSwitch & 1) != 0)
               goodMove = false;
          while (goodMove && numberTries < 5) {
               goodMove = false;
               numberTries++;
               CoinMemcpyN(deltaX_, numberTotal, saveX);
               CoinMemcpyN(deltaY_, numberRows_, saveY);
               CoinMemcpyN(deltaZ_, numberTotal, saveZ);
               CoinMemcpyN(deltaW_, numberTotal, saveW);
               CoinWorkDouble savePrimalStep = actualPrimalStep_;
               CoinWorkDouble saveDualStep = actualDualStep_;
               CoinWorkDouble saveMu = mu_;
               setupForSolve(3);
               findDirectionVector(3);
               findStepLength(3);
               debugMove(3, actualPrimalStep_, actualDualStep_);
               //debugMove(3,1.0e-7,1.0e-7);
               CoinWorkDouble xGap = complementarityGap(nextNumber, nextNumberItems, 3);
               // If one small then that's the one that counts
               CoinWorkDouble checkDual = saveDualStep;
               CoinWorkDouble checkPrimal = savePrimalStep;
               if (checkDual > 5.0 * checkPrimal) {
                    checkDual = 2.0 * checkPrimal;
               } else if (checkPrimal > 5.0 * checkDual) {
                    checkPrimal = 2.0 * checkDual;
               }
               if (actualPrimalStep_ < checkPrimal ||
                         actualDualStep_ < checkDual ||
                         (xGap > nextGap && xGap > 0.9 * complementarityGap_)) {
                    //if (actualPrimalStep_<=checkPrimal||
                    //actualDualStep_<=checkDual) {
#ifdef SOME_DEBUG
                    printf("PP rejected gap %.18g, steps %.18g %.18g, 2 gap %.18g, steps %.18g %.18g\n", xGap,
                           actualPrimalStep_, actualDualStep_, nextGap, savePrimalStep, saveDualStep);
#endif
                    mu_ = saveMu;
                    actualPrimalStep_ = savePrimalStep;
                    actualDualStep_ = saveDualStep;
                    CoinMemcpyN(saveX, numberTotal, deltaX_);
                    CoinMemcpyN(saveY, numberRows_, deltaY_);
                    CoinMemcpyN(saveZ, numberTotal, deltaZ_);
                    CoinMemcpyN(saveW, numberTotal, deltaW_);
               } else {
#ifdef SOME_DEBUG
                    printf("PPphase 3 gap %.18g, steps %.18g %.18g, 2 gap %.18g, steps %.18g %.18g\n", xGap,
                           actualPrimalStep_, actualDualStep_, nextGap, savePrimalStep, saveDualStep);
#endif
                    numberGoodTries++;
#ifdef COIN_DETAIL
                    nextCenterGap = xGap;
#endif
                    // See if big enough change
                    if (actualPrimalStep_ < 1.01 * checkPrimal ||
                              actualDualStep_ < 1.01 * checkDual) {
                         // stop now
                    } else {
                         // carry on
                         goodMove = true;
                    }
               }
          }
          if (numberGoodTries && handler_->logLevel() > 1) {
               COIN_DETAIL_PRINT(printf("%d centering steps moved from (gap %.18g, dual %.18g, primal %.18g) to (gap %.18g, dual %.18g, primal %.18g)\n",
                      numberGoodTries, static_cast<double>(nextGap), static_cast<double>(originalDualStep),
                      static_cast<double>(originalPrimalStep),
                      static_cast<double>(nextCenterGap), static_cast<double>(actualDualStep_),
					static_cast<double>(actualPrimalStep_)));
          }
          // save last gap
          checkGap = complementarityGap_;
          numberFixed = updateSolution(nextGap);
          numberFixedTotal += numberFixed;
     } /* endwhile */
     delete [] saveX;
     delete [] saveY;
     delete [] saveZ;
     delete [] saveW;
     delete [] saveSL;
     delete [] saveSU;
     if (savePi) {
          if (numberIterations_ - saveIteration > 20 &&
                    numberIterations_ - saveIteration2 < 5) {
#if KEEP_GOING_IF_FIXED<10
               std::cout << "Restoring2 from iteration " << saveIteration2 << std::endl;
#endif
               CoinMemcpyN(savePi2, numberRows_, dualArray);
               CoinMemcpyN(savePrimal2, numberTotal, solution_);
          } else {
#if KEEP_GOING_IF_FIXED<10
               std::cout << "Restoring from iteration " << saveIteration << std::endl;
#endif
               CoinMemcpyN(savePi, numberRows_, dualArray);
               CoinMemcpyN(savePrimal, numberTotal, solution_);
          }
          delete [] savePi;
          delete [] savePrimal;
     }
     delete [] savePi2;
     delete [] savePrimal2;
     //recompute slacks
     // Split out solution
     CoinZeroN(rowActivity_, numberRows_);
     CoinMemcpyN(solution_, numberColumns_, columnActivity_);
     matrix_->times(1.0, columnActivity_, rowActivity_);
     //unscale objective
     multiplyAdd(NULL, numberTotal, 0.0, cost_, scaleFactor_);
     multiplyAdd(NULL, numberRows_, 0, dualArray, scaleFactor_);
     checkSolution();
     //CoinMemcpyN(reducedCost_,numberColumns_,dj_);
     // If quadratic use last solution
     // Restore quadratic objective if necessary
     if (saveObjective) {
          delete objective_;
          objective_ = saveObjective;
          objectiveValue_ = 0.5 * (primalObjective_ + dualObjective_);
     }
     handler_->message(CLP_BARRIER_END, messages_)
               << static_cast<double>(sumPrimalInfeasibilities_)
               << static_cast<double>(sumDualInfeasibilities_)
               << static_cast<double>(complementarityGap_)
               << static_cast<double>(objectiveValue())
               << CoinMessageEol;
     //#ifdef SOME_DEBUG
     if (handler_->logLevel() > 1)
       COIN_DETAIL_PRINT(printf("ENDRUN status %d after %d iterations\n", problemStatus_, numberIterations_));
     //#endif
     //std::cout<<"Absolute primal infeasibility at end "<<sumPrimalInfeasibilities_<<std::endl;
     //std::cout<<"Absolute dual infeasibility at end "<<sumDualInfeasibilities_<<std::endl;
     //std::cout<<"Absolute complementarity at end "<<complementarityGap_<<std::endl;
     //std::cout<<"Primal objective "<<objectiveValue()<<std::endl;
     //std::cout<<"maximum complementarity "<<worstComplementarity_<<std::endl;
#if COIN_LONG_WORK
     // put back dual
     delete [] dual_;
     delete [] reducedCost_;
     dual_ = dualSave;
     reducedCost_ = reducedCostSave;
#endif
     //delete all temporary regions
     deleteWorkingData();
#if KEEP_GOING_IF_FIXED<10
#if 0 //ndef NDEBUG
     {
          static int kk = 0;
          char name[20];
          sprintf(name, "save.sol.%d", kk);
          kk++;
          printf("saving to file %s\n", name);
          FILE * fp = fopen(name, "wb");
          int numberWritten;
          numberWritten = fwrite(&numberColumns_, sizeof(int), 1, fp);
          assert (numberWritten == 1);
          numberWritten = fwrite(columnActivity_, sizeof(double), numberColumns_, fp);
          assert (numberWritten == numberColumns_);
          fclose(fp);
     }
#endif
#endif
     if (saveMatrix) {
          // restore normal copy
          delete matrix_;
          matrix_ = saveMatrix;
     }
     return problemStatus_;
}
// findStepLength.
//phase  - 0 predictor
//         1 corrector
//         2 primal dual
CoinWorkDouble ClpPredictorCorrector::findStepLength( int phase)
{
     CoinWorkDouble directionNorm = 0.0;
     CoinWorkDouble maximumPrimalStep = COIN_DBL_MAX * 1.0e-20;
     CoinWorkDouble maximumDualStep = COIN_DBL_MAX;
     int numberTotal = numberRows_ + numberColumns_;
     CoinWorkDouble tolerance = 1.0e-12;
#ifdef SOME_DEBUG
     int chosenPrimalSequence = -1;
     int chosenDualSequence = -1;
     bool lowPrimal = false;
     bool lowDual = false;
#endif
     // If done many iterations then allow to hit boundary
     CoinWorkDouble hitTolerance;
     //printf("objective norm %g\n",objectiveNorm_);
     if (numberIterations_ < 80 || !gonePrimalFeasible_)
          hitTolerance = COIN_DBL_MAX;
     else
          hitTolerance = CoinMax(1.0e3, 1.0e-3 * objectiveNorm_);
     int iColumn;
     //printf("dual value %g\n",dual_[0]);
     //printf("     X     dX      lS     dlS     uS     dUs    dj    Z dZ     t   dT\n");
     for (iColumn = 0; iColumn < numberTotal; iColumn++) {
          if (!flagged(iColumn)) {
               CoinWorkDouble directionElement = deltaX_[iColumn];
               if (directionNorm < CoinAbs(directionElement)) {
                    directionNorm = CoinAbs(directionElement);
               }
               if (lowerBound(iColumn)) {
                    CoinWorkDouble delta = - deltaSL_[iColumn];
                    CoinWorkDouble z1 = deltaZ_[iColumn];
                    CoinWorkDouble newZ = zVec_[iColumn] + z1;
                    if (zVec_[iColumn] > tolerance) {
                         if (zVec_[iColumn] < -z1 * maximumDualStep) {
                              maximumDualStep = -zVec_[iColumn] / z1;
#ifdef SOME_DEBUG
                              chosenDualSequence = iColumn;
                              lowDual = true;
#endif
                         }
                    }
                    if (lowerSlack_[iColumn] < maximumPrimalStep * delta) {
                         CoinWorkDouble newStep = lowerSlack_[iColumn] / delta;
                         if (newStep > 0.2 || newZ < hitTolerance || delta > 1.0e3 || delta <= 1.0e-6 || dj_[iColumn] < hitTolerance) {
                              maximumPrimalStep = newStep;
#ifdef SOME_DEBUG
                              chosenPrimalSequence = iColumn;
                              lowPrimal = true;
#endif
                         } else {
                              //printf("small %d delta %g newZ %g step %g\n",iColumn,delta,newZ,newStep);
                         }
                    }
               }
               if (upperBound(iColumn)) {
                    CoinWorkDouble delta = - deltaSU_[iColumn];;
                    CoinWorkDouble w1 = deltaW_[iColumn];
                    CoinWorkDouble newT = wVec_[iColumn] + w1;
                    if (wVec_[iColumn] > tolerance) {
                         if (wVec_[iColumn] < -w1 * maximumDualStep) {
                              maximumDualStep = -wVec_[iColumn] / w1;
#ifdef SOME_DEBUG
                              chosenDualSequence = iColumn;
                              lowDual = false;
#endif
                         }
                    }
                    if (upperSlack_[iColumn] < maximumPrimalStep * delta) {
                         CoinWorkDouble newStep = upperSlack_[iColumn] / delta;
                         if (newStep > 0.2 || newT < hitTolerance || delta > 1.0e3 || delta <= 1.0e-6 || dj_[iColumn] > -hitTolerance) {
                              maximumPrimalStep = newStep;
#ifdef SOME_DEBUG
                              chosenPrimalSequence = iColumn;
                              lowPrimal = false;
#endif
                         } else {
                              //printf("small %d delta %g newT %g step %g\n",iColumn,delta,newT,newStep);
                         }
                    }
               }
          }
     }
#ifdef SOME_DEBUG
     printf("new step - phase %d, norm %.18g, dual step %.18g, primal step %.18g\n",
            phase, directionNorm, maximumDualStep, maximumPrimalStep);
     if (lowDual)
          printf("ld %d %g %g => %g (dj %g,sol %g) ",
                 chosenDualSequence, zVec_[chosenDualSequence],
                 deltaZ_[chosenDualSequence], zVec_[chosenDualSequence] +
                 maximumDualStep * deltaZ_[chosenDualSequence], dj_[chosenDualSequence],
                 solution_[chosenDualSequence]);
     else
          printf("ud %d %g %g => %g (dj %g,sol %g) ",
                 chosenDualSequence, wVec_[chosenDualSequence],
                 deltaW_[chosenDualSequence], wVec_[chosenDualSequence] +
                 maximumDualStep * deltaW_[chosenDualSequence], dj_[chosenDualSequence],
                 solution_[chosenDualSequence]);
     if (lowPrimal)
          printf("lp %d %g %g => %g (dj %g,sol %g)\n",
                 chosenPrimalSequence, lowerSlack_[chosenPrimalSequence],
                 deltaSL_[chosenPrimalSequence], lowerSlack_[chosenPrimalSequence] +
                 maximumPrimalStep * deltaSL_[chosenPrimalSequence],
                 dj_[chosenPrimalSequence], solution_[chosenPrimalSequence]);
     else
          printf("up %d %g %g => %g (dj %g,sol %g)\n",
                 chosenPrimalSequence, upperSlack_[chosenPrimalSequence],
                 deltaSU_[chosenPrimalSequence], upperSlack_[chosenPrimalSequence] +
                 maximumPrimalStep * deltaSU_[chosenPrimalSequence],
                 dj_[chosenPrimalSequence], solution_[chosenPrimalSequence]);
#endif
     actualPrimalStep_ = stepLength_ * maximumPrimalStep;
     if (phase >= 0 && actualPrimalStep_ > 1.0) {
          actualPrimalStep_ = 1.0;
     }
     actualDualStep_ = stepLength_ * maximumDualStep;
     if (phase >= 0 && actualDualStep_ > 1.0) {
          actualDualStep_ = 1.0;
     }
     // See if quadratic objective
#ifndef NO_RTTI
     ClpQuadraticObjective * quadraticObj = (dynamic_cast< ClpQuadraticObjective*>(objective_));
#else
     ClpQuadraticObjective * quadraticObj = NULL;
     if (objective_->type() == 2)
          quadraticObj = (static_cast< ClpQuadraticObjective*>(objective_));
#endif
     if (quadraticObj) {
          // Use smaller unless very small
          CoinWorkDouble smallerStep = CoinMin(actualDualStep_, actualPrimalStep_);
          if (smallerStep > 0.0001) {
               actualDualStep_ = smallerStep;
               actualPrimalStep_ = smallerStep;
          }
     }
#define OFFQ
#ifndef OFFQ
     if (quadraticObj) {
          // Don't bother if phase 0 or 3 or large gap
          //if ((phase==1||phase==2||phase==0)&&maximumDualError_>0.1*complementarityGap_
          //&&smallerStep>0.001) {
          if ((phase == 1 || phase == 2 || phase == 0 || phase == 3)) {
               // minimize complementarity + norm*dual inf ? primal inf
               // at first - just check better - if not
               // Complementarity gap will be a*change*change + b*change +c
               CoinWorkDouble a = 0.0;
               CoinWorkDouble b = 0.0;
               CoinWorkDouble c = 0.0;
               /* SQUARE of dual infeasibility will be:
               square of dj - ......
               */
               CoinWorkDouble aq = 0.0;
               CoinWorkDouble bq = 0.0;
               CoinWorkDouble cq = 0.0;
               CoinWorkDouble gamma2 = gamma_ * gamma_; // gamma*gamma will be added to diagonal
               CoinWorkDouble * linearDjChange = new CoinWorkDouble[numberTotal];
               CoinZeroN(linearDjChange, numberColumns_);
               multiplyAdd(deltaY_, numberRows_, 1.0, linearDjChange + numberColumns_, 0.0);
               matrix_->transposeTimes(-1.0, deltaY_, linearDjChange);
               CoinPackedMatrix * quadratic = quadraticObj->quadraticObjective();
               const int * columnQuadratic = quadratic->getIndices();
               const CoinBigIndex * columnQuadraticStart = quadratic->getVectorStarts();
               const int * columnQuadraticLength = quadratic->getVectorLengths();
               CoinWorkDouble * quadraticElement = quadratic->getMutableElements();
               for (iColumn = 0; iColumn < numberTotal; iColumn++) {
                    CoinWorkDouble oldPrimal = solution_[iColumn];
                    if (!flagged(iColumn)) {
                         if (lowerBound(iColumn)) {
                              CoinWorkDouble change = oldPrimal + deltaX_[iColumn] - lowerSlack_[iColumn] - lower_[iColumn];
                              c += lowerSlack_[iColumn] * zVec_[iColumn];
                              b += lowerSlack_[iColumn] * deltaZ_[iColumn] + zVec_[iColumn] * change;
                              a += deltaZ_[iColumn] * change;
                         }
                         if (upperBound(iColumn)) {
                              CoinWorkDouble change = upper_[iColumn] - oldPrimal - deltaX_[iColumn] - upperSlack_[iColumn];
                              c += upperSlack_[iColumn] * wVec_[iColumn];
                              b += upperSlack_[iColumn] * deltaW_[iColumn] + wVec_[iColumn] * change;
                              a += deltaW_[iColumn] * change;
                         }
                         // new djs are dj_ + change*value
                         CoinWorkDouble djChange = linearDjChange[iColumn];
                         if (iColumn < numberColumns_) {
                              for (CoinBigIndex j = columnQuadraticStart[iColumn];
                                        j < columnQuadraticStart[iColumn] + columnQuadraticLength[iColumn]; j++) {
                                   int jColumn = columnQuadratic[j];
                                   CoinWorkDouble changeJ = deltaX_[jColumn];
                                   CoinWorkDouble elementValue = quadraticElement[j];
                                   djChange += changeJ * elementValue;
                              }
                         }
                         CoinWorkDouble gammaTerm = gamma2;
                         if (primalR_) {
                              gammaTerm += primalR_[iColumn];
                         }
                         djChange += gammaTerm;
                         // and dual infeasibility
                         CoinWorkDouble oldInf = dj_[iColumn] - zVec_[iColumn] + wVec_[iColumn] +
                                                 gammaTerm * solution_[iColumn];
                         CoinWorkDouble changeInf = djChange - deltaZ_[iColumn] + deltaW_[iColumn];
                         cq += oldInf * oldInf;
                         bq += 2.0 * oldInf * changeInf;
                         aq += changeInf * changeInf;
                    } else {
                         // fixed
                         if (lowerBound(iColumn)) {
                              c += lowerSlack_[iColumn] * zVec_[iColumn];
                         }
                         if (upperBound(iColumn)) {
                              c += upperSlack_[iColumn] * wVec_[iColumn];
                         }
                         // new djs are dj_ + change*value
                         CoinWorkDouble djChange = linearDjChange[iColumn];
                         if (iColumn < numberColumns_) {
                              for (CoinBigIndex j = columnQuadraticStart[iColumn];
                                        j < columnQuadraticStart[iColumn] + columnQuadraticLength[iColumn]; j++) {
                                   int jColumn = columnQuadratic[j];
                                   CoinWorkDouble changeJ = deltaX_[jColumn];
                                   CoinWorkDouble elementValue = quadraticElement[j];
                                   djChange += changeJ * elementValue;
                              }
                         }
                         CoinWorkDouble gammaTerm = gamma2;
                         if (primalR_) {
                              gammaTerm += primalR_[iColumn];
                         }
                         djChange += gammaTerm;
                         // and dual infeasibility
                         CoinWorkDouble oldInf = dj_[iColumn] - zVec_[iColumn] + wVec_[iColumn] +
                                                 gammaTerm * solution_[iColumn];
                         CoinWorkDouble changeInf = djChange - deltaZ_[iColumn] + deltaW_[iColumn];
                         cq += oldInf * oldInf;
                         bq += 2.0 * oldInf * changeInf;
                         aq += changeInf * changeInf;
                    }
               }
               delete [] linearDjChange;
               // ? We want to minimize complementarityGap + solutionNorm_*square of inf ??
               // maybe use inf and do line search
               // To check see if matches at current step
               CoinWorkDouble step = actualPrimalStep_;
               //Current gap + solutionNorm_ * CoinSqrt (sum square inf)
               CoinWorkDouble multiplier = solutionNorm_;
               multiplier *= 0.01;
               multiplier = 1.0;
               CoinWorkDouble currentInf =  multiplier * CoinSqrt(cq);
               CoinWorkDouble nextInf = 	multiplier * CoinSqrt(CoinMax(cq + step * bq + step * step * aq, 0.0));
               CoinWorkDouble allowedIncrease = 1.4;
#ifdef SOME_DEBUG
               printf("lin %g %g %g -> %g\n", a, b, c,
                      c + b * step + a * step * step);
               printf("quad %g %g %g -> %g\n", aq, bq, cq,
                      cq + bq * step + aq * step * step);
               debugMove(7, step, step);
               printf ("current dualInf %g, with step of %g is %g\n",
                       currentInf, step, nextInf);
#endif
               if (b > -1.0e-6) {
                    if (phase != 0)
                         directionNorm = -1.0;
               }
               if ((phase == 1 || phase == 2 || phase == 0 || phase == 3) && nextInf > 0.1 * complementarityGap_ &&
                         nextInf > currentInf * allowedIncrease) {
                    //cq = CoinMax(cq,10.0);
                    // convert to (x+q)*(x+q) = w
                    CoinWorkDouble q = bq / (1.0 * aq);
                    CoinWorkDouble w = CoinMax(q * q + (cq / aq) * (allowedIncrease - 1.0), 0.0);
                    w = CoinSqrt(w);
                    CoinWorkDouble stepX = w - q;
                    step = stepX;
                    nextInf =
                         multiplier * CoinSqrt(CoinMax(cq + step * bq + step * step * aq, 0.0));
#ifdef SOME_DEBUG
                    printf ("with step of %g dualInf is %g\n",
                            step, nextInf);
#endif
                    actualDualStep_ = CoinMin(step, actualDualStep_);
                    actualPrimalStep_ = CoinMin(step, actualPrimalStep_);
               }
          }
     } else {
          // probably pointless as linear
          // minimize complementarity
          // Complementarity gap will be a*change*change + b*change +c
          CoinWorkDouble a = 0.0;
          CoinWorkDouble b = 0.0;
          CoinWorkDouble c = 0.0;
          for (iColumn = 0; iColumn < numberTotal; iColumn++) {
               CoinWorkDouble oldPrimal = solution_[iColumn];
               if (!flagged(iColumn)) {
                    if (lowerBound(iColumn)) {
                         CoinWorkDouble change = oldPrimal + deltaX_[iColumn] - lowerSlack_[iColumn] - lower_[iColumn];
                         c += lowerSlack_[iColumn] * zVec_[iColumn];
                         b += lowerSlack_[iColumn] * deltaZ_[iColumn] + zVec_[iColumn] * change;
                         a += deltaZ_[iColumn] * change;
                    }
                    if (upperBound(iColumn)) {
                         CoinWorkDouble change = upper_[iColumn] - oldPrimal - deltaX_[iColumn] - upperSlack_[iColumn];
                         c += upperSlack_[iColumn] * wVec_[iColumn];
                         b += upperSlack_[iColumn] * deltaW_[iColumn] + wVec_[iColumn] * change;
                         a += deltaW_[iColumn] * change;
                    }
               } else {
                    // fixed
                    if (lowerBound(iColumn)) {
                         c += lowerSlack_[iColumn] * zVec_[iColumn];
                    }
                    if (upperBound(iColumn)) {
                         c += upperSlack_[iColumn] * wVec_[iColumn];
                    }
               }
          }
          // ? We want to minimize complementarityGap;
          // maybe use inf and do line search
          // To check see if matches at current step
          CoinWorkDouble step = CoinMin(actualPrimalStep_, actualDualStep_);
          CoinWorkDouble next = c + b * step + a * step * step;
#ifdef SOME_DEBUG
          printf("lin %g %g %g -> %g\n", a, b, c,
                 c + b * step + a * step * step);
          debugMove(7, step, step);
#endif
          if (b > -1.0e-6) {
               if (phase == 0) {
#ifdef SOME_DEBUG
                    printf("*** odd phase 0 direction\n");
#endif
               } else {
                    directionNorm = -1.0;
               }
          }
          // and with ratio
          a = 0.0;
          b = 0.0;
          CoinWorkDouble ratio = actualDualStep_ / actualPrimalStep_;
          for (iColumn = 0; iColumn < numberTotal; iColumn++) {
               CoinWorkDouble oldPrimal = solution_[iColumn];
               if (!flagged(iColumn)) {
                    if (lowerBound(iColumn)) {
                         CoinWorkDouble change = oldPrimal + deltaX_[iColumn] - lowerSlack_[iColumn] - lower_[iColumn];
                         b += lowerSlack_[iColumn] * deltaZ_[iColumn] * ratio + zVec_[iColumn] * change;
                         a += deltaZ_[iColumn] * change * ratio;
                    }
                    if (upperBound(iColumn)) {
                         CoinWorkDouble change = upper_[iColumn] - oldPrimal - deltaX_[iColumn] - upperSlack_[iColumn];
                         b += upperSlack_[iColumn] * deltaW_[iColumn] * ratio + wVec_[iColumn] * change;
                         a += deltaW_[iColumn] * change * ratio;
                    }
               }
          }
          // ? We want to minimize complementarityGap;
          // maybe use inf and do line search
          // To check see if matches at current step
          step = actualPrimalStep_;
          CoinWorkDouble next2 = c + b * step + a * step * step;
          if (next2 > next) {
               actualPrimalStep_ = CoinMin(actualPrimalStep_, actualDualStep_);
               actualDualStep_ = actualPrimalStep_;
          }
#ifdef SOME_DEBUG
          printf("linb %g %g %g -> %g\n", a, b, c,
                 c + b * step + a * step * step);
          debugMove(7, actualPrimalStep_, actualDualStep_);
#endif
          if (b > -1.0e-6) {
               if (phase == 0) {
#ifdef SOME_DEBUG
                    printf("*** odd phase 0 direction\n");
#endif
               } else {
                    directionNorm = -1.0;
               }
          }
     }
#else
     //actualPrimalStep_ =0.5*actualDualStep_;
#endif
#ifdef FULL_DEBUG
     if (phase == 3) {
          CoinWorkDouble minBeta = 0.1 * mu_;
          CoinWorkDouble maxBeta = 10.0 * mu_;
          for (iColumn = 0; iColumn < numberRows_ + numberColumns_; iColumn++) {
               if (!flagged(iColumn)) {
                    if (lowerBound(iColumn)) {
                         CoinWorkDouble change = -rhsL_[iColumn] + deltaX_[iColumn];
                         CoinWorkDouble dualValue = zVec_[iColumn] + actualDualStep_ * deltaZ_[iColumn];
                         CoinWorkDouble primalValue = lowerSlack_[iColumn] + actualPrimalStep_ * change;
                         CoinWorkDouble gapProduct = dualValue * primalValue;
                         if (delta2Z_[iColumn] < minBeta || delta2Z_[iColumn] > maxBeta)
                              printf("3lower %d primal %g, dual %g, gap %g, old gap %g\n",
                                     iColumn, primalValue, dualValue, gapProduct, delta2Z_[iColumn]);
                    }
                    if (upperBound(iColumn)) {
                         CoinWorkDouble change = rhsU_[iColumn] - deltaX_[iColumn];
                         CoinWorkDouble dualValue = wVec_[iColumn] + actualDualStep_ * deltaW_[iColumn];
                         CoinWorkDouble primalValue = upperSlack_[iColumn] + actualPrimalStep_ * change;
                         CoinWorkDouble gapProduct = dualValue * primalValue;
                         if (delta2W_[iColumn] < minBeta || delta2W_[iColumn] > maxBeta)
                              printf("3upper %d primal %g, dual %g, gap %g, old gap %g\n",
                                     iColumn, primalValue, dualValue, gapProduct, delta2W_[iColumn]);
                    }
               }
          }
     }
#endif
#ifdef SOME_DEBUG_not
     {
          CoinWorkDouble largestL = 0.0;
          CoinWorkDouble smallestL = COIN_DBL_MAX;
          CoinWorkDouble largestU = 0.0;
          CoinWorkDouble smallestU = COIN_DBL_MAX;
          CoinWorkDouble sumL = 0.0;
          CoinWorkDouble sumU = 0.0;
          int nL = 0;
          int nU = 0;
          for (iColumn = 0; iColumn < numberRows_ + numberColumns_; iColumn++) {
               if (!flagged(iColumn)) {
                    if (lowerBound(iColumn)) {
                         CoinWorkDouble change = -rhsL_[iColumn] + deltaX_[iColumn];
                         CoinWorkDouble dualValue = zVec_[iColumn] + actualDualStep_ * deltaZ_[iColumn];
                         CoinWorkDouble primalValue = lowerSlack_[iColumn] + actualPrimalStep_ * change;
                         CoinWorkDouble gapProduct = dualValue * primalValue;
                         largestL = CoinMax(largestL, gapProduct);
                         smallestL = CoinMin(smallestL, gapProduct);
                         nL++;
                         sumL += gapProduct;
                    }
                    if (upperBound(iColumn)) {
                         CoinWorkDouble change = rhsU_[iColumn] - deltaX_[iColumn];
                         CoinWorkDouble dualValue = wVec_[iColumn] + actualDualStep_ * deltaW_[iColumn];
                         CoinWorkDouble primalValue = upperSlack_[iColumn] + actualPrimalStep_ * change;
                         CoinWorkDouble gapProduct = dualValue * primalValue;
                         largestU = CoinMax(largestU, gapProduct);
                         smallestU = CoinMin(smallestU, gapProduct);
                         nU++;
                         sumU += gapProduct;
                    }
               }
          }
          CoinWorkDouble mu = (sumL + sumU) / (static_cast<CoinWorkDouble> (nL + nU));

          CoinWorkDouble minBeta = 0.1 * mu;
          CoinWorkDouble maxBeta = 10.0 * mu;
          int nBL = 0;
          int nAL = 0;
          int nBU = 0;
          int nAU = 0;
          for (iColumn = 0; iColumn < numberRows_ + numberColumns_; iColumn++) {
               if (!flagged(iColumn)) {
                    if (lowerBound(iColumn)) {
                         CoinWorkDouble change = -rhsL_[iColumn] + deltaX_[iColumn];
                         CoinWorkDouble dualValue = zVec_[iColumn] + actualDualStep_ * deltaZ_[iColumn];
                         CoinWorkDouble primalValue = lowerSlack_[iColumn] + actualPrimalStep_ * change;
                         CoinWorkDouble gapProduct = dualValue * primalValue;
                         if (gapProduct < minBeta)
                              nBL++;
                         else if (gapProduct > maxBeta)
                              nAL++;
                         //if (gapProduct<0.1*minBeta)
                         //printf("Lsmall one %d dual %g primal %g\n",iColumn,
                         //   dualValue,primalValue);
                    }
                    if (upperBound(iColumn)) {
                         CoinWorkDouble change = rhsU_[iColumn] - deltaX_[iColumn];
                         CoinWorkDouble dualValue = wVec_[iColumn] + actualDualStep_ * deltaW_[iColumn];
                         CoinWorkDouble primalValue = upperSlack_[iColumn] + actualPrimalStep_ * change;
                         CoinWorkDouble gapProduct = dualValue * primalValue;
                         if (gapProduct < minBeta)
                              nBU++;
                         else if (gapProduct > maxBeta)
                              nAU++;
                         //if (gapProduct<0.1*minBeta)
                         //printf("Usmall one %d dual %g primal %g\n",iColumn,
                         //   dualValue,primalValue);
                    }
               }
          }
          printf("phase %d new mu %.18g new gap %.18g\n", phase, mu, sumL + sumU);
          printf("          %d lower, smallest %.18g, %d below - largest %.18g, %d above\n",
                 nL, smallestL, nBL, largestL, nAL);
          printf("          %d upper, smallest %.18g, %d below - largest %.18g, %d above\n",
                 nU, smallestU, nBU, largestU, nAU);
     }
#endif
     return directionNorm;
}
/* Does solve. region1 is for deltaX (columns+rows), region2 for deltaPi (rows) */
void
ClpPredictorCorrector::solveSystem(CoinWorkDouble * region1, CoinWorkDouble * region2,
                                   const CoinWorkDouble * region1In, const CoinWorkDouble * region2In,
                                   const CoinWorkDouble * saveRegion1, const CoinWorkDouble * saveRegion2,
                                   bool gentleRefine)
{
     int iRow;
     int numberTotal = numberRows_ + numberColumns_;
     if (region2In) {
          // normal
          for (iRow = 0; iRow < numberRows_; iRow++)
               region2[iRow] = region2In[iRow];
     } else {
          // initial solution - (diagonal is 1 or 0)
          CoinZeroN(region2, numberRows_);
     }
     int iColumn;
     if (cholesky_->type() < 20) {
          // not KKT
          for (iColumn = 0; iColumn < numberTotal; iColumn++)
               region1[iColumn] = region1In[iColumn] * diagonal_[iColumn];
          multiplyAdd(region1 + numberColumns_, numberRows_, -1.0, region2, 1.0);
          matrix_->times(1.0, region1, region2);
          CoinWorkDouble maximumRHS = maximumAbsElement(region2, numberRows_);
          CoinWorkDouble scale = 1.0;
          CoinWorkDouble unscale = 1.0;
          if (maximumRHS > 1.0e-30) {
               if (maximumRHS <= 0.5) {
                    CoinWorkDouble factor = 2.0;
                    while (maximumRHS <= 0.5) {
                         maximumRHS *= factor;
                         scale *= factor;
                    } /* endwhile */
               } else if (maximumRHS >= 2.0 && maximumRHS <= COIN_DBL_MAX) {
                    CoinWorkDouble factor = 0.5;
                    while (maximumRHS >= 2.0) {
                         maximumRHS *= factor;
                         scale *= factor;
                    } /* endwhile */
               }
               unscale = diagonalScaleFactor_ / scale;
          } else {
               //effectively zero
               scale = 0.0;
               unscale = 0.0;
          }
          multiplyAdd(NULL, numberRows_, 0.0, region2, scale);
          cholesky_->solve(region2);
          multiplyAdd(NULL, numberRows_, 0.0, region2, unscale);
          multiplyAdd(region2, numberRows_, -1.0, region1 + numberColumns_, 0.0);
          CoinZeroN(region1, numberColumns_);
          matrix_->transposeTimes(1.0, region2, region1);
          for (iColumn = 0; iColumn < numberTotal; iColumn++)
               region1[iColumn] = (region1[iColumn] - region1In[iColumn]) * diagonal_[iColumn];
     } else {
          for (iColumn = 0; iColumn < numberTotal; iColumn++)
               region1[iColumn] = region1In[iColumn];
          cholesky_->solveKKT(region1, region2, diagonal_, diagonalScaleFactor_);
     }
     if (saveRegion2) {
          //refine?
          CoinWorkDouble scaleX = 1.0;
          if (gentleRefine)
               scaleX = 0.8;
          multiplyAdd(saveRegion2, numberRows_, 1.0, region2, scaleX);
          assert (saveRegion1);
          multiplyAdd(saveRegion1, numberTotal, 1.0, region1, scaleX);
     }
}
// findDirectionVector.
CoinWorkDouble ClpPredictorCorrector::findDirectionVector(const int phase)
{
     CoinWorkDouble projectionTolerance = projectionTolerance_;
     //temporary
     //projectionTolerance=1.0e-15;
     CoinWorkDouble errorCheck = 0.9 * maximumRHSError_ / solutionNorm_;
     if (errorCheck > primalTolerance()) {
          if (errorCheck < projectionTolerance) {
               projectionTolerance = errorCheck;
          }
     } else {
          if (primalTolerance() < projectionTolerance) {
               projectionTolerance = primalTolerance();
          }
     }
     CoinWorkDouble * newError = new CoinWorkDouble [numberRows_];
     int numberTotal = numberRows_ + numberColumns_;
     //if flagged then entries zero so can do
     // For KKT separate out
     CoinWorkDouble * region1Save = NULL; //for refinement
     int iColumn;
     if (cholesky_->type() < 20) {
          int iColumn;
          for (iColumn = 0; iColumn < numberTotal; iColumn++)
               deltaX_[iColumn] = workArray_[iColumn] - solution_[iColumn];
          multiplyAdd(deltaX_ + numberColumns_, numberRows_, -1.0, deltaY_, 0.0);
          matrix_->times(1.0, deltaX_, deltaY_);
     } else {
          // regions in will be workArray and newError
          // regions out deltaX_ and deltaY_
          multiplyAdd(solution_ + numberColumns_, numberRows_, 1.0, newError, 0.0);
          matrix_->times(-1.0, solution_, newError);
          // This is inefficient but just for now get values which will be in deltay
          int iColumn;
          for (iColumn = 0; iColumn < numberTotal; iColumn++)
               deltaX_[iColumn] = workArray_[iColumn] - solution_[iColumn];
          multiplyAdd(deltaX_ + numberColumns_, numberRows_, -1.0, deltaY_, 0.0);
          matrix_->times(1.0, deltaX_, deltaY_);
     }
     bool goodSolve = false;
     CoinWorkDouble * regionSave = NULL; //for refinement
     int numberTries = 0;
     CoinWorkDouble relativeError = COIN_DBL_MAX;
     CoinWorkDouble tryError = 1.0e31;
     CoinWorkDouble saveMaximum = 0.0;
     double firstError = 0.0;
     double lastError2 = 0.0;
     while (!goodSolve && numberTries < 30) {
          CoinWorkDouble lastError = relativeError;
          goodSolve = true;
          CoinWorkDouble maximumRHS;
          maximumRHS = CoinMax(maximumAbsElement(deltaY_, numberRows_), 1.0e-12);
          if (!numberTries)
               saveMaximum = maximumRHS;
          if (cholesky_->type() < 20) {
               // no kkt
               CoinWorkDouble scale = 1.0;
               CoinWorkDouble unscale = 1.0;
               if (maximumRHS > 1.0e-30) {
                    if (maximumRHS <= 0.5) {
                         CoinWorkDouble factor = 2.0;
                         while (maximumRHS <= 0.5) {
                              maximumRHS *= factor;
                              scale *= factor;
                         } /* endwhile */
                    } else if (maximumRHS >= 2.0 && maximumRHS <= COIN_DBL_MAX) {
                         CoinWorkDouble factor = 0.5;
                         while (maximumRHS >= 2.0) {
                              maximumRHS *= factor;
                              scale *= factor;
                         } /* endwhile */
                    }
                    unscale = diagonalScaleFactor_ / scale;
               } else {
                    //effectively zero
                    scale = 0.0;
                    unscale = 0.0;
               }
               //printf("--putting scales to 1.0\n");
               //scale=1.0;
               //unscale=1.0;
               multiplyAdd(NULL, numberRows_, 0.0, deltaY_, scale);
               cholesky_->solve(deltaY_);
               multiplyAdd(NULL, numberRows_, 0.0, deltaY_, unscale);
#if 0
               {
                    printf("deltay\n");
                    for (int i = 0; i < numberRows_; i++)
                         printf("%d %.18g\n", i, deltaY_[i]);
               }
               exit(66);
#endif
               if (numberTries) {
                    //refine?
                    CoinWorkDouble scaleX = 1.0;
                    if (lastError > 1.0e-5)
                         scaleX = 0.8;
                    multiplyAdd(regionSave, numberRows_, 1.0, deltaY_, scaleX);
               }
               //CoinZeroN(newError,numberRows_);
               multiplyAdd(deltaY_, numberRows_, -1.0, deltaX_ + numberColumns_, 0.0);
               CoinZeroN(deltaX_, numberColumns_);
               matrix_->transposeTimes(1.0, deltaY_, deltaX_);
               //if flagged then entries zero so can do
               for (iColumn = 0; iColumn < numberTotal; iColumn++)
                    deltaX_[iColumn] = deltaX_[iColumn] * diagonal_[iColumn]
                                       - workArray_[iColumn];
          } else {
               // KKT
               solveSystem(deltaX_, deltaY_,
                           workArray_, newError, region1Save, regionSave, lastError > 1.0e-5);
          }
          multiplyAdd(deltaX_ + numberColumns_, numberRows_, -1.0, newError, 0.0);
          matrix_->times(1.0, deltaX_, newError);
          numberTries++;

          //now add in old Ax - doing extra checking
          CoinWorkDouble maximumRHSError = 0.0;
          CoinWorkDouble maximumRHSChange = 0.0;
          int iRow;
          char * dropped = cholesky_->rowsDropped();
          for (iRow = 0; iRow < numberRows_; iRow++) {
               if (!dropped[iRow]) {
                    CoinWorkDouble newValue = newError[iRow];
                    CoinWorkDouble oldValue = errorRegion_[iRow];
                    //severity of errors depend on signs
                    //**later                                                             */
                    if (CoinAbs(newValue) > maximumRHSChange) {
                         maximumRHSChange = CoinAbs(newValue);
                    }
                    CoinWorkDouble result = newValue + oldValue;
                    if (CoinAbs(result) > maximumRHSError) {
                         maximumRHSError = CoinAbs(result);
                    }
                    newError[iRow] = result;
               } else {
                    CoinWorkDouble newValue = newError[iRow];
                    CoinWorkDouble oldValue = errorRegion_[iRow];
                    if (CoinAbs(newValue) > maximumRHSChange) {
                         maximumRHSChange = CoinAbs(newValue);
                    }
                    CoinWorkDouble result = newValue + oldValue;
                    newError[iRow] = result;
                    //newError[iRow]=0.0;
                    //assert(deltaY_[iRow]==0.0);
                    deltaY_[iRow] = 0.0;
               }
          }
          relativeError = maximumRHSError / solutionNorm_;
          relativeError = maximumRHSError / saveMaximum;
          if (relativeError > tryError)
               relativeError = tryError;
          if (numberTries == 1)
               firstError = relativeError;
          if (relativeError < lastError) {
               lastError2 = relativeError;
               maximumRHSChange_ = maximumRHSChange;
               if (relativeError > projectionTolerance && numberTries <= 3) {
                    //try and refine
                    goodSolve = false;
               }
               //*** extra test here
               if (!goodSolve) {
                    if (!regionSave) {
                         regionSave = new CoinWorkDouble [numberRows_];
                         if (cholesky_->type() >= 20)
                              region1Save = new CoinWorkDouble [numberTotal];
                    }
                    CoinMemcpyN(deltaY_, numberRows_, regionSave);
                    if (cholesky_->type() < 20) {
                         // not KKT
                         multiplyAdd(newError, numberRows_, -1.0, deltaY_, 0.0);
                    } else {
                         // KKT
                         CoinMemcpyN(deltaX_, numberTotal, region1Save);
                         // and back to input region
                         CoinMemcpyN(deltaY_, numberRows_, newError);
                    }
               }
          } else {
               //std::cout <<" worse residual = "<<relativeError;
               //bring back previous
               relativeError = lastError;
               if (regionSave) {
                    CoinMemcpyN(regionSave, numberRows_, deltaY_);
                    if (cholesky_->type() < 20) {
                         // not KKT
                         multiplyAdd(deltaY_, numberRows_, -1.0, deltaX_ + numberColumns_, 0.0);
                         CoinZeroN(deltaX_, numberColumns_);
                         matrix_->transposeTimes(1.0, deltaY_, deltaX_);
                         //if flagged then entries zero so can do
                         for (iColumn = 0; iColumn < numberTotal; iColumn++)
                              deltaX_[iColumn] = deltaX_[iColumn] * diagonal_[iColumn]
                                                 - workArray_[iColumn];
                    } else {
                         // KKT
                         CoinMemcpyN(region1Save, numberTotal, deltaX_);
                    }
               } else {
                    // disaster
                    CoinFillN(deltaX_, numberTotal, static_cast<CoinWorkDouble>(1.0));
                    CoinFillN(deltaY_, numberRows_, static_cast<CoinWorkDouble>(1.0));
                    COIN_DETAIL_PRINT(printf("bad cholesky\n"));
               }
          }
     } /* endwhile */
     if (firstError > 1.0e-8 || numberTries > 1) {
          handler_->message(CLP_BARRIER_ACCURACY, messages_)
                    << phase << numberTries << static_cast<double>(firstError)
                    << static_cast<double>(lastError2)
                    << CoinMessageEol;
     }
     delete [] regionSave;
     delete [] region1Save;
     delete [] newError;
     // now rest
     CoinWorkDouble extra = eExtra;
     //multiplyAdd(deltaY_,numberRows_,1.0,deltaW_+numberColumns_,0.0);
     //CoinZeroN(deltaW_,numberColumns_);
     //matrix_->transposeTimes(-1.0,deltaY_,deltaW_);

     for (iColumn = 0; iColumn < numberRows_ + numberColumns_; iColumn++) {
          deltaSU_[iColumn] = 0.0;
          deltaSL_[iColumn] = 0.0;
          deltaZ_[iColumn] = 0.0;
          CoinWorkDouble dd = deltaW_[iColumn];
          deltaW_[iColumn] = 0.0;
          if (!flagged(iColumn)) {
               CoinWorkDouble deltaX = deltaX_[iColumn];
               if (lowerBound(iColumn)) {
                    CoinWorkDouble zValue = rhsZ_[iColumn];
                    CoinWorkDouble gHat = zValue + zVec_[iColumn] * rhsL_[iColumn];
                    CoinWorkDouble slack = lowerSlack_[iColumn] + extra;
                    deltaSL_[iColumn] = -rhsL_[iColumn] + deltaX;
                    deltaZ_[iColumn] = (gHat - zVec_[iColumn] * deltaX) / slack;
               }
               if (upperBound(iColumn)) {
                    CoinWorkDouble wValue = rhsW_[iColumn];
                    CoinWorkDouble hHat = wValue - wVec_[iColumn] * rhsU_[iColumn];
                    CoinWorkDouble slack = upperSlack_[iColumn] + extra;
                    deltaSU_[iColumn] = rhsU_[iColumn] - deltaX;
                    deltaW_[iColumn] = (hHat + wVec_[iColumn] * deltaX) / slack;
               }
               if (0) {
                    // different way of calculating
                    CoinWorkDouble gamma2 = gamma_ * gamma_;
                    CoinWorkDouble dZ = 0.0;
                    CoinWorkDouble dW = 0.0;
                    CoinWorkDouble zValue = rhsZ_[iColumn];
                    CoinWorkDouble gHat = zValue + zVec_[iColumn] * rhsL_[iColumn];
                    CoinWorkDouble slackL = lowerSlack_[iColumn] + extra;
                    CoinWorkDouble wValue = rhsW_[iColumn];
                    CoinWorkDouble hHat = wValue - wVec_[iColumn] * rhsU_[iColumn];
                    CoinWorkDouble slackU = upperSlack_[iColumn] + extra;
                    CoinWorkDouble q = rhsC_[iColumn] + gamma2 * deltaX + dd;
                    if (primalR_)
                         q += deltaX * primalR_[iColumn];
                    dW = (gHat + hHat - slackL * q + (wValue - zValue) * deltaX) / (slackL + slackU);
                    dZ = dW + q;
                    //printf("B %d old %g %g new %g %g\n",iColumn,deltaZ_[iColumn],
                    //deltaW_[iColumn],dZ,dW);
                    if (lowerBound(iColumn)) {
                         if (upperBound(iColumn)) {
                              //printf("B %d old %g %g new %g %g\n",iColumn,deltaZ_[iColumn],
                              //deltaW_[iColumn],dZ,dW);
                              deltaW_[iColumn] = dW;
                              deltaZ_[iColumn] = dZ;
                         } else {
                              // just lower
                              //printf("L %d old %g new %g\n",iColumn,deltaZ_[iColumn],
                              //dZ);
                         }
                    } else {
                         assert (upperBound(iColumn));
                         //printf("U %d old %g new %g\n",iColumn,deltaW_[iColumn],
                         //dW);
                    }
               }
          }
     }
#if 0
     CoinWorkDouble * check = new CoinWorkDouble[numberTotal];
     // Check out rhsC_
     multiplyAdd(deltaY_, numberRows_, -1.0, check + numberColumns_, 0.0);
     CoinZeroN(check, numberColumns_);
     matrix_->transposeTimes(1.0, deltaY_, check);
     quadraticDjs(check, deltaX_, -1.0);
     for (iColumn = 0; iColumn < numberTotal; iColumn++) {
          check[iColumn] += deltaZ_[iColumn] - deltaW_[iColumn];
          if (CoinAbs(check[iColumn] - rhsC_[iColumn]) > 1.0e-3)
               printf("rhsC %d %g %g\n", iColumn, check[iColumn], rhsC_[iColumn]);
     }
     // Check out rhsZ_
     for (iColumn = 0; iColumn < numberTotal; iColumn++) {
          check[iColumn] += lowerSlack_[iColumn] * deltaZ_[iColumn] +
                            zVec_[iColumn] * deltaSL_[iColumn];
          if (CoinAbs(check[iColumn] - rhsZ_[iColumn]) > 1.0e-3)
               printf("rhsZ %d %g %g\n", iColumn, check[iColumn], rhsZ_[iColumn]);
     }
     // Check out rhsW_
     for (iColumn = 0; iColumn < numberTotal; iColumn++) {
          check[iColumn] += upperSlack_[iColumn] * deltaW_[iColumn] +
                            wVec_[iColumn] * deltaSU_[iColumn];
          if (CoinAbs(check[iColumn] - rhsW_[iColumn]) > 1.0e-3)
               printf("rhsW %d %g %g\n", iColumn, check[iColumn], rhsW_[iColumn]);
     }
     delete [] check;
#endif
     return relativeError;
}
// createSolution.  Creates solution from scratch
int ClpPredictorCorrector::createSolution()
{
     int numberTotal = numberRows_ + numberColumns_;
     int iColumn;
     CoinWorkDouble tolerance = primalTolerance();
     // See if quadratic objective
#ifndef NO_RTTI
     ClpQuadraticObjective * quadraticObj = (dynamic_cast< ClpQuadraticObjective*>(objective_));
#else
     ClpQuadraticObjective * quadraticObj = NULL;
     if (objective_->type() == 2)
          quadraticObj = (static_cast< ClpQuadraticObjective*>(objective_));
#endif
     if (!quadraticObj) {
          for (iColumn = 0; iColumn < numberTotal; iColumn++) {
               if (upper_[iColumn] - lower_[iColumn] > tolerance)
                    clearFixed(iColumn);
               else
                    setFixed(iColumn);
          }
     } else {
          // try leaving fixed
          for (iColumn = 0; iColumn < numberTotal; iColumn++)
               clearFixed(iColumn);
     }

     CoinWorkDouble maximumObjective = 0.0;
     CoinWorkDouble objectiveNorm2 = 0.0;
     getNorms(cost_, numberTotal, maximumObjective, objectiveNorm2);
     if (!maximumObjective) {
          maximumObjective = 1.0; // objective all zero
     }
     objectiveNorm2 = CoinSqrt(objectiveNorm2) / static_cast<CoinWorkDouble> (numberTotal);
     objectiveNorm_ = maximumObjective;
     scaleFactor_ = 1.0;
     if (maximumObjective > 0.0) {
          if (maximumObjective < 1.0) {
               scaleFactor_ = maximumObjective;
          } else if (maximumObjective > 1.0e4) {
               scaleFactor_ = maximumObjective / 1.0e4;
          }
     }
     if (scaleFactor_ != 1.0) {
          objectiveNorm2 *= scaleFactor_;
          multiplyAdd(NULL, numberTotal, 0.0, cost_, 1.0 / scaleFactor_);
          objectiveNorm_ = maximumObjective / scaleFactor_;
     }
     // See if quadratic objective
     if (quadraticObj) {
          // If scaled then really scale matrix
          CoinWorkDouble scaleFactor =
               scaleFactor_ * optimizationDirection_ * objectiveScale_ *
               rhsScale_;
          if ((scalingFlag_ > 0 && rowScale_) || scaleFactor != 1.0) {
               CoinPackedMatrix * quadratic = quadraticObj->quadraticObjective();
               const int * columnQuadratic = quadratic->getIndices();
               const CoinBigIndex * columnQuadraticStart = quadratic->getVectorStarts();
               const int * columnQuadraticLength = quadratic->getVectorLengths();
               double * quadraticElement = quadratic->getMutableElements();
               int numberColumns = quadratic->getNumCols();
               CoinWorkDouble scale = 1.0 / scaleFactor;
               if (scalingFlag_ > 0 && rowScale_) {
                    for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
                         CoinWorkDouble scaleI = columnScale_[iColumn] * scale;
                         for (CoinBigIndex j = columnQuadraticStart[iColumn];
                                   j < columnQuadraticStart[iColumn] + columnQuadraticLength[iColumn]; j++) {
                              int jColumn = columnQuadratic[j];
                              CoinWorkDouble scaleJ = columnScale_[jColumn];
                              quadraticElement[j] *= scaleI * scaleJ;
                              objectiveNorm_ = CoinMax(objectiveNorm_, CoinAbs(quadraticElement[j]));
                         }
                    }
               } else {
                    // not scaled
                    for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
                         for (CoinBigIndex j = columnQuadraticStart[iColumn];
                                   j < columnQuadraticStart[iColumn] + columnQuadraticLength[iColumn]; j++) {
                              quadraticElement[j] *= scale;
                              objectiveNorm_ = CoinMax(objectiveNorm_, CoinAbs(quadraticElement[j]));
                         }
                    }
               }
          }
     }
     baseObjectiveNorm_ = objectiveNorm_;
     //accumulate fixed in dj region (as spare)
     //accumulate primal solution in primal region
     //DZ in lowerDual
     //DW in upperDual
     CoinWorkDouble infiniteCheck = 1.0e40;
     //CoinWorkDouble     fakeCheck=1.0e10;
     //use deltaX region for work region
     for (iColumn = 0; iColumn < numberTotal; iColumn++) {
          CoinWorkDouble primalValue = solution_[iColumn];
          clearFlagged(iColumn);
          clearFixedOrFree(iColumn);
          clearLowerBound(iColumn);
          clearUpperBound(iColumn);
          clearFakeLower(iColumn);
          clearFakeUpper(iColumn);
          if (!fixed(iColumn)) {
               dj_[iColumn] = 0.0;
               diagonal_[iColumn] = 1.0;
               deltaX_[iColumn] = 1.0;
               CoinWorkDouble lowerValue = lower_[iColumn];
               CoinWorkDouble upperValue = upper_[iColumn];
               if (lowerValue > -infiniteCheck) {
                    if (upperValue < infiniteCheck) {
                         //upper and lower bounds
                         setLowerBound(iColumn);
                         setUpperBound(iColumn);
                         if (lowerValue >= 0.0) {
                              solution_[iColumn] = lowerValue;
                         } else if (upperValue <= 0.0) {
                              solution_[iColumn] = upperValue;
                         } else {
                              solution_[iColumn] = 0.0;
                         }
                    } else {
                         //just lower bound
                         setLowerBound(iColumn);
                         if (lowerValue >= 0.0) {
                              solution_[iColumn] = lowerValue;
                         } else {
                              solution_[iColumn] = 0.0;
                         }
                    }
               } else {
                    if (upperValue < infiniteCheck) {
                         //just upper bound
                         setUpperBound(iColumn);
                         if (upperValue <= 0.0) {
                              solution_[iColumn] = upperValue;
                         } else {
                              solution_[iColumn] = 0.0;
                         }
                    } else {
                         //free
                         setFixedOrFree(iColumn);
                         solution_[iColumn] = 0.0;
                         //std::cout<<" free "<<i<<std::endl;
                    }
               }
          } else {
               setFlagged(iColumn);
               setFixedOrFree(iColumn);
               setLowerBound(iColumn);
               setUpperBound(iColumn);
               dj_[iColumn] = primalValue;;
               solution_[iColumn] = lower_[iColumn];
               diagonal_[iColumn] = 0.0;
               deltaX_[iColumn] = 0.0;
          }
     }
     //   modify fixed RHS
     multiplyAdd(dj_ + numberColumns_, numberRows_, -1.0, rhsFixRegion_, 0.0);
     //   create plausible RHS?
     matrix_->times(-1.0, dj_, rhsFixRegion_);
     multiplyAdd(solution_ + numberColumns_, numberRows_, 1.0, errorRegion_, 0.0);
     matrix_->times(-1.0, solution_, errorRegion_);
     rhsNorm_ = maximumAbsElement(errorRegion_, numberRows_);
     if (rhsNorm_ < 1.0) {
          rhsNorm_ = 1.0;
     }
     int * rowsDropped = new int [numberRows_];
     int returnCode = cholesky_->factorize(diagonal_, rowsDropped);
     if (returnCode == -1) {
       COIN_DETAIL_PRINT(printf("Out of memory\n"));
          problemStatus_ = 4;
          return -1;
     }
     if (cholesky_->status()) {
          std::cout << "singular on initial cholesky?" << std::endl;
          cholesky_->resetRowsDropped();
          //cholesky_->factorize(rowDropped_);
          //if (cholesky_->status()) {
          //std::cout << "bad cholesky??? (after retry)" <<std::endl;
          //abort();
          //}
     }
     delete [] rowsDropped;
     if (cholesky_->type() < 20) {
          // not KKT
          cholesky_->solve(errorRegion_);
          //create information for solution
          multiplyAdd(errorRegion_, numberRows_, -1.0, deltaX_ + numberColumns_, 0.0);
          CoinZeroN(deltaX_, numberColumns_);
          matrix_->transposeTimes(1.0, errorRegion_, deltaX_);
     } else {
          // KKT
          // reverse sign on solution
          multiplyAdd(NULL, numberRows_ + numberColumns_, 0.0, solution_, -1.0);
          solveSystem(deltaX_, errorRegion_, solution_, NULL, NULL, NULL, false);
     }
     CoinWorkDouble initialValue = 1.0e2;
     if (rhsNorm_ * 1.0e-2 > initialValue) {
          initialValue = rhsNorm_ * 1.0e-2;
     }
     //initialValue = CoinMax(1.0,rhsNorm_);
     CoinWorkDouble smallestBoundDifference = COIN_DBL_MAX;
     CoinWorkDouble * fakeSolution = deltaX_;
     for ( iColumn = 0; iColumn < numberTotal; iColumn++) {
          if (!flagged(iColumn)) {
               if (lower_[iColumn] - fakeSolution[iColumn] > initialValue) {
                    initialValue = lower_[iColumn] - fakeSolution[iColumn];
               }
               if (fakeSolution[iColumn] - upper_[iColumn] > initialValue) {
                    initialValue = fakeSolution[iColumn] - upper_[iColumn];
               }
               if (upper_[iColumn] - lower_[iColumn] < smallestBoundDifference) {
                    smallestBoundDifference = upper_[iColumn] - lower_[iColumn];
               }
          }
     }
     solutionNorm_ = 1.0e-12;
     handler_->message(CLP_BARRIER_SAFE, messages_)
               << static_cast<double>(initialValue) << static_cast<double>(objectiveNorm_)
               << CoinMessageEol;
     CoinWorkDouble extra = 1.0e-10;
     CoinWorkDouble largeGap = 1.0e15;
     //CoinWorkDouble safeObjectiveValue=2.0*objectiveNorm_;
     CoinWorkDouble safeObjectiveValue = objectiveNorm_ + 1.0;
     CoinWorkDouble safeFree = 1.0e-1 * initialValue;
     //printf("normal safe dual value of %g, primal value of %g\n",
     // safeObjectiveValue,initialValue);
     //safeObjectiveValue=CoinMax(2.0,1.0e-1*safeObjectiveValue);
     //initialValue=CoinMax(100.0,1.0e-1*initialValue);;
     //printf("temp safe dual value of %g, primal value of %g\n",
     // safeObjectiveValue,initialValue);
     CoinWorkDouble zwLarge = 1.0e2 * initialValue;
     //zwLarge=1.0e40;
     if (cholesky_->choleskyCondition() < 0.0 && cholesky_->type() < 20) {
          // looks bad - play safe
          initialValue *= 10.0;
          safeObjectiveValue *= 10.0;
          safeFree *= 10.0;
     }
     CoinWorkDouble gamma2 = gamma_ * gamma_; // gamma*gamma will be added to diagonal
     // First do primal side
     for ( iColumn = 0; iColumn < numberTotal; iColumn++) {
          if (!flagged(iColumn)) {
               CoinWorkDouble lowerValue = lower_[iColumn];
               CoinWorkDouble upperValue = upper_[iColumn];
               CoinWorkDouble newValue;
               CoinWorkDouble setPrimal = initialValue;
               if (quadraticObj) {
                    // perturb primal solution a bit
                    //fakeSolution[iColumn]  *= 0.002*CoinDrand48()+0.999;
               }
               if (lowerBound(iColumn)) {
                    if (upperBound(iColumn)) {
                         //upper and lower bounds
                         if (upperValue - lowerValue > 2.0 * setPrimal) {
                              CoinWorkDouble fakeValue = fakeSolution[iColumn];
                              if (fakeValue < lowerValue + setPrimal) {
                                   fakeValue = lowerValue + setPrimal;
                              }
                              if (fakeValue > upperValue - setPrimal) {
                                   fakeValue = upperValue - setPrimal;
                              }
                              newValue = fakeValue;
                         } else {
                              newValue = 0.5 * (upperValue + lowerValue);
                         }
                    } else {
                         //just lower bound
                         CoinWorkDouble fakeValue = fakeSolution[iColumn];
                         if (fakeValue < lowerValue + setPrimal) {
                              fakeValue = lowerValue + setPrimal;
                         }
                         newValue = fakeValue;
                    }
               } else {
                    if (upperBound(iColumn)) {
                         //just upper bound
                         CoinWorkDouble fakeValue = fakeSolution[iColumn];
                         if (fakeValue > upperValue - setPrimal) {
                              fakeValue = upperValue - setPrimal;
                         }
                         newValue = fakeValue;
                    } else {
                         //free
                         newValue = fakeSolution[iColumn];
                         if (newValue >= 0.0) {
                              if (newValue < safeFree) {
                                   newValue = safeFree;
                              }
                         } else {
                              if (newValue > -safeFree) {
                                   newValue = -safeFree;
                              }
                         }
                    }
               }
               solution_[iColumn] = newValue;
          } else {
               // fixed
               lowerSlack_[iColumn] = 0.0;
               upperSlack_[iColumn] = 0.0;
               solution_[iColumn] = lower_[iColumn];
               zVec_[iColumn] = 0.0;
               wVec_[iColumn] = 0.0;
               diagonal_[iColumn] = 0.0;
          }
     }
     solutionNorm_ =  maximumAbsElement(solution_, numberTotal);
     // Set bounds and do dj including quadratic
     largeGap = CoinMax(1.0e7, 1.02 * solutionNorm_);
     CoinPackedMatrix * quadratic = NULL;
     const int * columnQuadratic = NULL;
     const CoinBigIndex * columnQuadraticStart = NULL;
     const int * columnQuadraticLength = NULL;
     const double * quadraticElement = NULL;
     if (quadraticObj) {
          quadratic = quadraticObj->quadraticObjective();
          columnQuadratic = quadratic->getIndices();
          columnQuadraticStart = quadratic->getVectorStarts();
          columnQuadraticLength = quadratic->getVectorLengths();
          quadraticElement = quadratic->getElements();
     }
     CoinWorkDouble quadraticNorm = 0.0;
     for ( iColumn = 0; iColumn < numberTotal; iColumn++) {
          if (!flagged(iColumn)) {
               CoinWorkDouble primalValue = solution_[iColumn];
               CoinWorkDouble lowerValue = lower_[iColumn];
               CoinWorkDouble upperValue = upper_[iColumn];
               // Do dj
               CoinWorkDouble reducedCost = cost_[iColumn];
               if (lowerBound(iColumn)) {
                    reducedCost += linearPerturbation_;
               }
               if (upperBound(iColumn)) {
                    reducedCost -= linearPerturbation_;
               }
               if (quadraticObj && iColumn < numberColumns_) {
                    for (CoinBigIndex j = columnQuadraticStart[iColumn];
                              j < columnQuadraticStart[iColumn] + columnQuadraticLength[iColumn]; j++) {
                         int jColumn = columnQuadratic[j];
                         CoinWorkDouble valueJ = solution_[jColumn];
                         CoinWorkDouble elementValue = quadraticElement[j];
                         reducedCost += valueJ * elementValue;
                    }
                    quadraticNorm = CoinMax(quadraticNorm, CoinAbs(reducedCost));
               }
               dj_[iColumn] = reducedCost;
               if (primalValue > lowerValue + largeGap && primalValue < upperValue - largeGap) {
                    clearFixedOrFree(iColumn);
                    setLowerBound(iColumn);
                    setUpperBound(iColumn);
                    lowerValue = CoinMax(lowerValue, primalValue - largeGap);
                    upperValue = CoinMin(upperValue, primalValue + largeGap);
                    lower_[iColumn] = lowerValue;
                    upper_[iColumn] = upperValue;
               }
          }
     }
     safeObjectiveValue = CoinMax(safeObjectiveValue, quadraticNorm);
     for ( iColumn = 0; iColumn < numberTotal; iColumn++) {
          if (!flagged(iColumn)) {
               CoinWorkDouble primalValue = solution_[iColumn];
               CoinWorkDouble lowerValue = lower_[iColumn];
               CoinWorkDouble upperValue = upper_[iColumn];
               CoinWorkDouble reducedCost = dj_[iColumn];
               CoinWorkDouble low = 0.0;
               CoinWorkDouble high = 0.0;
               if (lowerBound(iColumn)) {
                    if (upperBound(iColumn)) {
                         //upper and lower bounds
                         if (upperValue - lowerValue > 2.0 * initialValue) {
                              low = primalValue - lowerValue;
                              high = upperValue - primalValue;
                         } else {
                              low = initialValue;
                              high = initialValue;
                         }
                         CoinWorkDouble s = low + extra;
                         CoinWorkDouble ratioZ;
                         if (s < zwLarge) {
                              ratioZ = 1.0;
                         } else {
                              ratioZ = CoinSqrt(zwLarge / s);
                         }
                         CoinWorkDouble t = high + extra;
                         CoinWorkDouble ratioT;
                         if (t < zwLarge) {
                              ratioT = 1.0;
                         } else {
                              ratioT = CoinSqrt(zwLarge / t);
                         }
                         //modify s and t
                         if (s > largeGap) {
                              s = largeGap;
                         }
                         if (t > largeGap) {
                              t = largeGap;
                         }
                         //modify if long long way away from bound
                         if (reducedCost >= 0.0) {
                              zVec_[iColumn] = reducedCost + safeObjectiveValue * ratioZ;
                              zVec_[iColumn] = CoinMax(reducedCost, safeObjectiveValue * ratioZ);
                              wVec_[iColumn] = safeObjectiveValue * ratioT;
                         } else {
                              zVec_[iColumn] = safeObjectiveValue * ratioZ;
                              wVec_[iColumn] = -reducedCost + safeObjectiveValue * ratioT;
                              wVec_[iColumn] = CoinMax(-reducedCost , safeObjectiveValue * ratioT);
                         }
                         CoinWorkDouble gammaTerm = gamma2;
                         if (primalR_)
                              gammaTerm += primalR_[iColumn];
                         diagonal_[iColumn] = (t * s) /
                                              (s * wVec_[iColumn] + t * zVec_[iColumn] + gammaTerm * t * s);
                    } else {
                         //just lower bound
                         low = primalValue - lowerValue;
                         high = 0.0;
                         CoinWorkDouble s = low + extra;
                         CoinWorkDouble ratioZ;
                         if (s < zwLarge) {
                              ratioZ = 1.0;
                         } else {
                              ratioZ = CoinSqrt(zwLarge / s);
                         }
                         //modify s
                         if (s > largeGap) {
                              s = largeGap;
                         }
                         if (reducedCost >= 0.0) {
                              zVec_[iColumn] = reducedCost + safeObjectiveValue * ratioZ;
                              zVec_[iColumn] = CoinMax(reducedCost , safeObjectiveValue * ratioZ);
                              wVec_[iColumn] = 0.0;
                         } else {
                              zVec_[iColumn] = safeObjectiveValue * ratioZ;
                              wVec_[iColumn] = 0.0;
                         }
                         CoinWorkDouble gammaTerm = gamma2;
                         if (primalR_)
                              gammaTerm += primalR_[iColumn];
                         diagonal_[iColumn] = s / (zVec_[iColumn] + s * gammaTerm);
                    }
               } else {
                    if (upperBound(iColumn)) {
                         //just upper bound
                         low = 0.0;
                         high = upperValue - primalValue;
                         CoinWorkDouble t = high + extra;
                         CoinWorkDouble ratioT;
                         if (t < zwLarge) {
                              ratioT = 1.0;
                         } else {
                              ratioT = CoinSqrt(zwLarge / t);
                         }
                         //modify t
                         if (t > largeGap) {
                              t = largeGap;
                         }
                         if (reducedCost >= 0.0) {
                              zVec_[iColumn] = 0.0;
                              wVec_[iColumn] = safeObjectiveValue * ratioT;
                         } else {
                              zVec_[iColumn] = 0.0;
                              wVec_[iColumn] = -reducedCost + safeObjectiveValue * ratioT;
                              wVec_[iColumn] = CoinMax(-reducedCost , safeObjectiveValue * ratioT);
                         }
                         CoinWorkDouble gammaTerm = gamma2;
                         if (primalR_)
                              gammaTerm += primalR_[iColumn];
                         diagonal_[iColumn] =  t / (wVec_[iColumn] + t * gammaTerm);
                    }
               }
               lowerSlack_[iColumn] = low;
               upperSlack_[iColumn] = high;
          }
     }
#if 0
     if (solution_[0] > 0.0) {
          for (int i = 0; i < numberTotal; i++)
               printf("%d %.18g %.18g %.18g %.18g %.18g %.18g %.18g\n", i, CoinAbs(solution_[i]),
                      diagonal_[i], CoinAbs(dj_[i]),
                      lowerSlack_[i], zVec_[i],
                      upperSlack_[i], wVec_[i]);
     } else {
          for (int i = 0; i < numberTotal; i++)
               printf("%d %.18g %.18g %.18g %.18g %.18g %.18g %.18g\n", i, CoinAbs(solution_[i]),
                      diagonal_[i], CoinAbs(dj_[i]),
                      upperSlack_[i], wVec_[i],
                      lowerSlack_[i], zVec_[i] );
     }
     exit(66);
#endif
     return 0;
}
// complementarityGap.  Computes gap
//phase 0=as is , 1 = after predictor , 2 after corrector
CoinWorkDouble ClpPredictorCorrector::complementarityGap(int & numberComplementarityPairs,
          int & numberComplementarityItems,
          const int phase)
{
     CoinWorkDouble gap = 0.0;
     //seems to be same coding for phase = 1 or 2
     numberComplementarityPairs = 0;
     numberComplementarityItems = 0;
     int numberTotal = numberRows_ + numberColumns_;
     CoinWorkDouble toleranceGap = 0.0;
     CoinWorkDouble largestGap = 0.0;
     CoinWorkDouble smallestGap = COIN_DBL_MAX;
     //seems to be same coding for phase = 1 or 2
     int numberNegativeGaps = 0;
     CoinWorkDouble sumNegativeGap = 0.0;
     CoinWorkDouble largeGap = 1.0e2 * solutionNorm_;
     if (largeGap < 1.0e10) {
          largeGap = 1.0e10;
     }
     largeGap = 1.0e30;
     CoinWorkDouble dualTolerance =  dblParam_[ClpDualTolerance];
     CoinWorkDouble primalTolerance =  dblParam_[ClpPrimalTolerance];
     dualTolerance = dualTolerance / scaleFactor_;
     for (int iColumn = 0; iColumn < numberTotal; iColumn++) {
          if (!fixedOrFree(iColumn)) {
               numberComplementarityPairs++;
               //can collapse as if no lower bound both zVec and deltaZ 0.0
               if (lowerBound(iColumn)) {
                    numberComplementarityItems++;
                    CoinWorkDouble dualValue;
                    CoinWorkDouble primalValue;
                    if (!phase) {
                         dualValue = zVec_[iColumn];
                         primalValue = lowerSlack_[iColumn];
                    } else {
                         CoinWorkDouble change;
                         change = solution_[iColumn] + deltaX_[iColumn] - lowerSlack_[iColumn] - lower_[iColumn];
                         dualValue = zVec_[iColumn] + actualDualStep_ * deltaZ_[iColumn];
                         primalValue = lowerSlack_[iColumn] + actualPrimalStep_ * change;
                    }
                    //reduce primalValue
                    if (primalValue > largeGap) {
                         primalValue = largeGap;
                    }
                    CoinWorkDouble gapProduct = dualValue * primalValue;
                    if (gapProduct < 0.0) {
                         //cout<<"negative gap component "<<iColumn<<" "<<dualValue<<" "<<
                         //primalValue<<endl;
                         numberNegativeGaps++;
                         sumNegativeGap -= gapProduct;
                         gapProduct = 0.0;
                    }
                    gap += gapProduct;
                    //printf("l %d prim %g dual %g totalGap %g\n",
                    //   iColumn,primalValue,dualValue,gap);
                    if (gapProduct > largestGap) {
                         largestGap = gapProduct;
                    }
                    smallestGap = CoinMin(smallestGap, gapProduct);
                    if (dualValue > dualTolerance && primalValue > primalTolerance) {
                         toleranceGap += dualValue * primalValue;
                    }
               }
               if (upperBound(iColumn)) {
                    numberComplementarityItems++;
                    CoinWorkDouble dualValue;
                    CoinWorkDouble primalValue;
                    if (!phase) {
                         dualValue = wVec_[iColumn];
                         primalValue = upperSlack_[iColumn];
                    } else {
                         CoinWorkDouble change;
                         change = upper_[iColumn] - solution_[iColumn] - deltaX_[iColumn] - upperSlack_[iColumn];
                         dualValue = wVec_[iColumn] + actualDualStep_ * deltaW_[iColumn];
                         primalValue = upperSlack_[iColumn] + actualPrimalStep_ * change;
                    }
                    //reduce primalValue
                    if (primalValue > largeGap) {
                         primalValue = largeGap;
                    }
                    CoinWorkDouble gapProduct = dualValue * primalValue;
                    if (gapProduct < 0.0) {
                         //cout<<"negative gap component "<<iColumn<<" "<<dualValue<<" "<<
                         //primalValue<<endl;
                         numberNegativeGaps++;
                         sumNegativeGap -= gapProduct;
                         gapProduct = 0.0;
                    }
                    gap += gapProduct;
                    //printf("u %d prim %g dual %g totalGap %g\n",
                    //   iColumn,primalValue,dualValue,gap);
                    if (gapProduct > largestGap) {
                         largestGap = gapProduct;
                    }
                    if (dualValue > dualTolerance && primalValue > primalTolerance) {
                         toleranceGap += dualValue * primalValue;
                    }
               }
          }
     }
     //if (numberIterations_>4)
     //exit(9);
     if (!phase && numberNegativeGaps) {
          handler_->message(CLP_BARRIER_NEGATIVE_GAPS, messages_)
                    << numberNegativeGaps << static_cast<double>(sumNegativeGap)
                    << CoinMessageEol;
     }

     //in case all free!
     if (!numberComplementarityPairs) {
          numberComplementarityPairs = 1;
     }
#ifdef SOME_DEBUG
     printf("with d,p steps %g,%g gap %g - smallest %g, largest %g, pairs %d\n",
            actualDualStep_, actualPrimalStep_,
            gap, smallestGap, largestGap, numberComplementarityPairs);
#endif
     return gap;
}
// setupForSolve.
//phase 0=affine , 1 = corrector , 2 = primal-dual
void ClpPredictorCorrector::setupForSolve(const int phase)
{
     CoinWorkDouble extra = eExtra;
     int numberTotal = numberRows_ + numberColumns_;
     int iColumn;
#ifdef SOME_DEBUG
     printf("phase %d in setupForSolve, mu %.18g\n", phase, mu_);
#endif
     CoinWorkDouble gamma2 = gamma_ * gamma_; // gamma*gamma will be added to diagonal
     CoinWorkDouble * dualArray = reinterpret_cast<CoinWorkDouble *>(dual_);
     switch (phase) {
     case 0:
          CoinMemcpyN(errorRegion_, numberRows_, rhsB_);
          if (delta_ || dualR_) {
               // add in regularization
               CoinWorkDouble delta2 = delta_ * delta_;
               for (int iRow = 0; iRow < numberRows_; iRow++) {
                    rhsB_[iRow] -= delta2 * dualArray[iRow];
                    if (dualR_)
                         rhsB_[iRow] -= dualR_[iRow] * dualArray[iRow];
               }
          }
          for (iColumn = 0; iColumn < numberTotal; iColumn++) {
               rhsC_[iColumn] = 0.0;
               rhsU_[iColumn] = 0.0;
               rhsL_[iColumn] = 0.0;
               rhsZ_[iColumn] = 0.0;
               rhsW_[iColumn] = 0.0;
               if (!flagged(iColumn)) {
                    rhsC_[iColumn] = dj_[iColumn] - zVec_[iColumn] + wVec_[iColumn];
                    rhsC_[iColumn] += gamma2 * solution_[iColumn];
                    if (primalR_)
                         rhsC_[iColumn] += primalR_[iColumn] * solution_[iColumn];
                    if (lowerBound(iColumn)) {
                         rhsZ_[iColumn] = -zVec_[iColumn] * (lowerSlack_[iColumn] + extra);
                         rhsL_[iColumn] = CoinMax(0.0, (lower_[iColumn] + lowerSlack_[iColumn]) - solution_[iColumn]);
                    }
                    if (upperBound(iColumn)) {
                         rhsW_[iColumn] = -wVec_[iColumn] * (upperSlack_[iColumn] + extra);
                         rhsU_[iColumn] = CoinMin(0.0, (upper_[iColumn] - upperSlack_[iColumn]) - solution_[iColumn]);
                    }
               }
          }
#if 0
          for (int i = 0; i < 3; i++) {
               if (!CoinAbs(rhsZ_[i]))
                    rhsZ_[i] = 0.0;
               if (!CoinAbs(rhsW_[i]))
                    rhsW_[i] = 0.0;
               if (!CoinAbs(rhsU_[i]))
                    rhsU_[i] = 0.0;
               if (!CoinAbs(rhsL_[i]))
                    rhsL_[i] = 0.0;
          }
          if (solution_[0] > 0.0) {
               for (int i = 0; i < 3; i++)
                    printf("%d %.18g %.18g %.18g %.18g %.18g %.18g %.18g\n", i, solution_[i],
                           diagonal_[i], dj_[i],
                           lowerSlack_[i], zVec_[i],
                           upperSlack_[i], wVec_[i]);
               for (int i = 0; i < 3; i++)
                    printf("%d %.18g %.18g %.18g %.18g %.18g\n", i, rhsC_[i],
                           rhsZ_[i], rhsL_[i],
                           rhsW_[i], rhsU_[i]);
          } else {
               for (int i = 0; i < 3; i++)
                    printf("%d %.18g %.18g %.18g %.18g %.18g %.18g %.18g\n", i, solution_[i],
                           diagonal_[i], dj_[i],
                           lowerSlack_[i], zVec_[i],
                           upperSlack_[i], wVec_[i]);
               for (int i = 0; i < 3; i++)
                    printf("%d %.18g %.18g %.18g %.18g %.18g\n", i, rhsC_[i],
                           rhsZ_[i], rhsL_[i],
                           rhsW_[i], rhsU_[i]);
          }
#endif
          break;
     case 1:
          // could be stored in delta2?
          for (iColumn = 0; iColumn < numberTotal; iColumn++) {
               rhsZ_[iColumn] = 0.0;
               rhsW_[iColumn] = 0.0;
               if (!flagged(iColumn)) {
                    if (lowerBound(iColumn)) {
                         rhsZ_[iColumn] = mu_ - zVec_[iColumn] * (lowerSlack_[iColumn] + extra)
                                          - deltaZ_[iColumn] * deltaX_[iColumn];
                         // To bring in line with OSL
                         rhsZ_[iColumn] += deltaZ_[iColumn] * rhsL_[iColumn];
                    }
                    if (upperBound(iColumn)) {
                         rhsW_[iColumn] = mu_ - wVec_[iColumn] * (upperSlack_[iColumn] + extra)
                                          + deltaW_[iColumn] * deltaX_[iColumn];
                         // To bring in line with OSL
                         rhsW_[iColumn] -= deltaW_[iColumn] * rhsU_[iColumn];
                    }
               }
          }
#if 0
          for (int i = 0; i < numberTotal; i++) {
               if (!CoinAbs(rhsZ_[i]))
                    rhsZ_[i] = 0.0;
               if (!CoinAbs(rhsW_[i]))
                    rhsW_[i] = 0.0;
               if (!CoinAbs(rhsU_[i]))
                    rhsU_[i] = 0.0;
               if (!CoinAbs(rhsL_[i]))
                    rhsL_[i] = 0.0;
          }
          if (solution_[0] > 0.0) {
               for (int i = 0; i < numberTotal; i++)
                    printf("%d %.18g %.18g %.18g %.18g %.18g %.18g %.18g\n", i, CoinAbs(solution_[i]),
                           diagonal_[i], CoinAbs(dj_[i]),
                           lowerSlack_[i], zVec_[i],
                           upperSlack_[i], wVec_[i]);
               for (int i = 0; i < numberTotal; i++)
                    printf("%d %.18g %.18g %.18g %.18g %.18g\n", i, CoinAbs(rhsC_[i]),
                           rhsZ_[i], rhsL_[i],
                           rhsW_[i], rhsU_[i]);
          } else {
               for (int i = 0; i < numberTotal; i++)
                    printf("%d %.18g %.18g %.18g %.18g %.18g %.18g %.18g\n", i, CoinAbs(solution_[i]),
                           diagonal_[i], CoinAbs(dj_[i]),
                           upperSlack_[i], wVec_[i],
                           lowerSlack_[i], zVec_[i] );
               for (int i = 0; i < numberTotal; i++)
                    printf("%d %.18g %.18g %.18g %.18g %.18g\n", i, CoinAbs(rhsC_[i]),
                           rhsW_[i], rhsU_[i],
                           rhsZ_[i], rhsL_[i]);
          }
          exit(66);
#endif
          break;
     case 2:
          CoinMemcpyN(errorRegion_, numberRows_, rhsB_);
          for (iColumn = 0; iColumn < numberTotal; iColumn++) {
               rhsZ_[iColumn] = 0.0;
               rhsW_[iColumn] = 0.0;
               if (!flagged(iColumn)) {
                    if (lowerBound(iColumn)) {
                         rhsZ_[iColumn] = mu_ - zVec_[iColumn] * (lowerSlack_[iColumn] + extra);
                    }
                    if (upperBound(iColumn)) {
                         rhsW_[iColumn] = mu_ - wVec_[iColumn] * (upperSlack_[iColumn] + extra);
                    }
               }
          }
          break;
     case 3: {
          CoinWorkDouble minBeta = 0.1 * mu_;
          CoinWorkDouble maxBeta = 10.0 * mu_;
          CoinWorkDouble dualStep = CoinMin(1.0, actualDualStep_ + 0.1);
          CoinWorkDouble primalStep = CoinMin(1.0, actualPrimalStep_ + 0.1);
#ifdef SOME_DEBUG
          printf("good complementarity range %g to %g\n", minBeta, maxBeta);
#endif
          //minBeta=0.0;
          //maxBeta=COIN_DBL_MAX;
          for (iColumn = 0; iColumn < numberTotal; iColumn++) {
               if (!flagged(iColumn)) {
                    if (lowerBound(iColumn)) {
                         CoinWorkDouble change = -rhsL_[iColumn] + deltaX_[iColumn];
                         CoinWorkDouble dualValue = zVec_[iColumn] + dualStep * deltaZ_[iColumn];
                         CoinWorkDouble primalValue = lowerSlack_[iColumn] + primalStep * change;
                         CoinWorkDouble gapProduct = dualValue * primalValue;
                         if (gapProduct > 0.0 && dualValue < 0.0)
                              gapProduct = - gapProduct;
#ifdef FULL_DEBUG
                         delta2Z_[iColumn] = gapProduct;
                         if (delta2Z_[iColumn] < minBeta || delta2Z_[iColumn] > maxBeta)
                              printf("lower %d primal %g, dual %g, gap %g\n",
                                     iColumn, primalValue, dualValue, gapProduct);
#endif
                         CoinWorkDouble value = 0.0;
                         if (gapProduct < minBeta) {
                              value = 2.0 * (minBeta - gapProduct);
                              value = (mu_ - gapProduct);
                              value = (minBeta - gapProduct);
                              assert (value > 0.0);
                         } else if (gapProduct > maxBeta) {
                              value = CoinMax(maxBeta - gapProduct, -maxBeta);
                              assert (value < 0.0);
                         }
                         rhsZ_[iColumn] += value;
                    }
                    if (upperBound(iColumn)) {
                         CoinWorkDouble change = rhsU_[iColumn] - deltaX_[iColumn];
                         CoinWorkDouble dualValue = wVec_[iColumn] + dualStep * deltaW_[iColumn];
                         CoinWorkDouble primalValue = upperSlack_[iColumn] + primalStep * change;
                         CoinWorkDouble gapProduct = dualValue * primalValue;
                         if (gapProduct > 0.0 && dualValue < 0.0)
                              gapProduct = - gapProduct;
#ifdef FULL_DEBUG
                         delta2W_[iColumn] = gapProduct;
                         if (delta2W_[iColumn] < minBeta || delta2W_[iColumn] > maxBeta)
                              printf("upper %d primal %g, dual %g, gap %g\n",
                                     iColumn, primalValue, dualValue, gapProduct);
#endif
                         CoinWorkDouble value = 0.0;
                         if (gapProduct < minBeta) {
                              value = (minBeta - gapProduct);
                              assert (value > 0.0);
                         } else if (gapProduct > maxBeta) {
                              value = CoinMax(maxBeta - gapProduct, -maxBeta);
                              assert (value < 0.0);
                         }
                         rhsW_[iColumn] += value;
                    }
               }
          }
     }
     break;
     } /* endswitch */
     if (cholesky_->type() < 20) {
          for (iColumn = 0; iColumn < numberTotal; iColumn++) {
               CoinWorkDouble value = rhsC_[iColumn];
               CoinWorkDouble zValue = rhsZ_[iColumn];
               CoinWorkDouble wValue = rhsW_[iColumn];
#if 0
#if 1
               if (phase == 0) {
                    // more accurate
                    value = dj[iColumn];
                    zValue = 0.0;
                    wValue = 0.0;
               } else if (phase == 2) {
                    // more accurate
                    value = dj[iColumn];
                    zValue = mu_;
                    wValue = mu_;
               }
#endif
               assert (rhsL_[iColumn] >= 0.0);
               assert (rhsU_[iColumn] <= 0.0);
               if (lowerBound(iColumn)) {
                    value += (-zVec_[iColumn] * rhsL_[iColumn] - zValue) /
                             (lowerSlack_[iColumn] + extra);
               }
               if (upperBound(iColumn)) {
                    value += (wValue - wVec_[iColumn] * rhsU_[iColumn]) /
                             (upperSlack_[iColumn] + extra);
               }
#else
               if (lowerBound(iColumn)) {
                    CoinWorkDouble gHat = zValue + zVec_[iColumn] * rhsL_[iColumn];
                    value -= gHat / (lowerSlack_[iColumn] + extra);
               }
               if (upperBound(iColumn)) {
                    CoinWorkDouble hHat = wValue - wVec_[iColumn] * rhsU_[iColumn];
                    value += hHat / (upperSlack_[iColumn] + extra);
               }
#endif
               workArray_[iColumn] = diagonal_[iColumn] * value;
          }
#if 0
          if (solution_[0] > 0.0) {
               for (int i = 0; i < numberTotal; i++)
                    printf("%d %.18g\n", i, workArray_[i]);
          } else {
               for (int i = 0; i < numberTotal; i++)
                    printf("%d %.18g\n", i, workArray_[i]);
          }
          exit(66);
#endif
     } else {
          // KKT
          for (iColumn = 0; iColumn < numberTotal; iColumn++) {
               CoinWorkDouble value = rhsC_[iColumn];
               CoinWorkDouble zValue = rhsZ_[iColumn];
               CoinWorkDouble wValue = rhsW_[iColumn];
               if (lowerBound(iColumn)) {
                    CoinWorkDouble gHat = zValue + zVec_[iColumn] * rhsL_[iColumn];
                    value -= gHat / (lowerSlack_[iColumn] + extra);
               }
               if (upperBound(iColumn)) {
                    CoinWorkDouble hHat = wValue - wVec_[iColumn] * rhsU_[iColumn];
                    value += hHat / (upperSlack_[iColumn] + extra);
               }
               workArray_[iColumn] = value;
          }
     }
}
//method: sees if looks plausible change in complementarity
bool ClpPredictorCorrector::checkGoodMove(const bool doCorrector,
          CoinWorkDouble & bestNextGap,
          bool allowIncreasingGap)
{
     const CoinWorkDouble beta3 = 0.99997;
     bool goodMove = false;
     int nextNumber;
     int nextNumberItems;
     int numberTotal = numberRows_ + numberColumns_;
     CoinWorkDouble returnGap = bestNextGap;
     CoinWorkDouble nextGap = complementarityGap(nextNumber, nextNumberItems, 2);
#ifndef NO_RTTI
     ClpQuadraticObjective * quadraticObj = (dynamic_cast< ClpQuadraticObjective*>(objective_));
#else
     ClpQuadraticObjective * quadraticObj = NULL;
     if (objective_->type() == 2)
          quadraticObj = (static_cast< ClpQuadraticObjective*>(objective_));
#endif
     if (nextGap > bestNextGap && nextGap > 0.9 * complementarityGap_ && doCorrector
               && !quadraticObj && !allowIncreasingGap) {
#ifdef SOME_DEBUG
          printf("checkGood phase 1 next gap %.18g, phase 0 %.18g, old gap %.18g\n",
                 nextGap, bestNextGap, complementarityGap_);
#endif
          return false;
     } else {
          returnGap = nextGap;
     }
     CoinWorkDouble step;
     if (actualDualStep_ > actualPrimalStep_) {
          step = actualDualStep_;
     } else {
          step = actualPrimalStep_;
     }
     CoinWorkDouble testValue = 1.0 - step * (1.0 - beta3);
     //testValue=0.0;
     testValue *= complementarityGap_;
     if (nextGap < testValue) {
          //std::cout <<"predicted duality gap "<<nextGap<<std::endl;
          goodMove = true;
     } else if(doCorrector) {
          //if (actualDualStep_<actualPrimalStep_) {
          //step=actualDualStep_;
          //} else {
          //step=actualPrimalStep_;
          //}
          CoinWorkDouble gap = bestNextGap;
          goodMove = checkGoodMove2(step, gap, allowIncreasingGap);
          if (goodMove)
               returnGap = gap;
     } else {
          goodMove = true;
     }
     if (goodMove)
          goodMove = checkGoodMove2(step, bestNextGap, allowIncreasingGap);
     // Say good if small
     //if (quadraticObj) {
     if (CoinMax(actualDualStep_, actualPrimalStep_) < 1.0e-6)
          goodMove = true;
     if (!goodMove) {
          //try smaller of two
          if (actualDualStep_ < actualPrimalStep_) {
               step = actualDualStep_;
          } else {
               step = actualPrimalStep_;
          }
          if (step > 1.0) {
               step = 1.0;
          }
          actualPrimalStep_ = step;
          //if (quadraticObj)
          //actualPrimalStep_ *=0.5;
          actualDualStep_ = step;
          goodMove = checkGoodMove2(step, bestNextGap, allowIncreasingGap);
          int pass = 0;
          while (!goodMove) {
               pass++;
               CoinWorkDouble gap = bestNextGap;
               goodMove = checkGoodMove2(step, gap, allowIncreasingGap);
               if (goodMove || pass > 3) {
                    returnGap = gap;
                    break;
               }
               if (step < 1.0e-4) {
                    break;
               }
               step *= 0.5;
               actualPrimalStep_ = step;
               //if (quadraticObj)
               //actualPrimalStep_ *=0.5;
               actualDualStep_ = step;
          } /* endwhile */
          if (doCorrector) {
               //say bad move if both small
               if (numberIterations_ & 1) {
                    if (actualPrimalStep_ < 1.0e-2 && actualDualStep_ < 1.0e-2) {
                         goodMove = false;
                    }
               } else {
                    if (actualPrimalStep_ < 1.0e-5 && actualDualStep_ < 1.0e-5) {
                         goodMove = false;
                    }
                    if (actualPrimalStep_ * actualDualStep_ < 1.0e-20) {
                         goodMove = false;
                    }
               }
          }
     }
     if (goodMove) {
          //compute delta in objectives
          CoinWorkDouble deltaObjectivePrimal = 0.0;
          CoinWorkDouble deltaObjectiveDual =
               innerProduct(deltaY_, numberRows_,
                            rhsFixRegion_);
          CoinWorkDouble error = 0.0;
          CoinWorkDouble * workArray = workArray_;
          CoinZeroN(workArray, numberColumns_);
          CoinMemcpyN(deltaY_, numberRows_, workArray + numberColumns_);
          matrix_->transposeTimes(-1.0, deltaY_, workArray);
          //CoinWorkDouble sumPerturbCost=0.0;
          for (int iColumn = 0; iColumn < numberTotal; iColumn++) {
               if (!flagged(iColumn)) {
                    if (lowerBound(iColumn)) {
                         //sumPerturbCost+=deltaX_[iColumn];
                         deltaObjectiveDual += deltaZ_[iColumn] * lower_[iColumn];
                    }
                    if (upperBound(iColumn)) {
                         //sumPerturbCost-=deltaX_[iColumn];
                         deltaObjectiveDual -= deltaW_[iColumn] * upper_[iColumn];
                    }
                    CoinWorkDouble change = CoinAbs(workArray_[iColumn] - deltaZ_[iColumn] + deltaW_[iColumn]);
                    error = CoinMax(change, error);
               }
               deltaObjectivePrimal += cost_[iColumn] * deltaX_[iColumn];
          }
          //deltaObjectivePrimal+=sumPerturbCost*linearPerturbation_;
          CoinWorkDouble testValue;
          if (error > 0.0) {
               testValue = 1.0e1 * CoinMax(maximumDualError_, 1.0e-12) / error;
          } else {
               testValue = 1.0e1;
          }
          // If quadratic then primal step may compensate
          if (testValue < actualDualStep_ && !quadraticObj) {
               handler_->message(CLP_BARRIER_REDUCING, messages_)
                         << "dual" << static_cast<double>(actualDualStep_)
                         << static_cast<double>(testValue)
                         << CoinMessageEol;
               actualDualStep_ = testValue;
          }
     }
     if (maximumRHSError_ < 1.0e1 * solutionNorm_ * primalTolerance()
               && maximumRHSChange_ > 1.0e-16 * solutionNorm_) {
          //check change in AX not too much
          //??? could be dropped row going infeasible
          CoinWorkDouble ratio = 1.0e1 * CoinMax(maximumRHSError_, 1.0e-12) / maximumRHSChange_;
          if (ratio < actualPrimalStep_) {
               handler_->message(CLP_BARRIER_REDUCING, messages_)
                         << "primal" << static_cast<double>(actualPrimalStep_)
                         << static_cast<double>(ratio)
                         << CoinMessageEol;
               if (ratio > 1.0e-6) {
                    actualPrimalStep_ = ratio;
               } else {
                    actualPrimalStep_ = ratio;
                    //std::cout <<"sign we should be stopping"<<std::endl;
               }
          }
     }
     if (goodMove)
          bestNextGap = returnGap;
     return goodMove;
}
//:  checks for one step size
bool ClpPredictorCorrector::checkGoodMove2(CoinWorkDouble move,
          CoinWorkDouble & bestNextGap,
          bool allowIncreasingGap)
{
     CoinWorkDouble complementarityMultiplier = 1.0 / numberComplementarityPairs_;
     const CoinWorkDouble gamma = 1.0e-8;
     const CoinWorkDouble gammap = 1.0e-8;
     CoinWorkDouble gammad = 1.0e-8;
     int nextNumber;
     int nextNumberItems;
     CoinWorkDouble nextGap = complementarityGap(nextNumber, nextNumberItems, 2);
     if (nextGap > bestNextGap && !allowIncreasingGap)
          return false;
     CoinWorkDouble lowerBoundGap = gamma * nextGap * complementarityMultiplier;
     bool goodMove = true;
     int iColumn;
     for ( iColumn = 0; iColumn < numberRows_ + numberColumns_; iColumn++) {
          if (!flagged(iColumn)) {
               if (lowerBound(iColumn)) {
                    CoinWorkDouble part1 = lowerSlack_[iColumn] + actualPrimalStep_ * deltaSL_[iColumn];
                    CoinWorkDouble part2 = zVec_[iColumn] + actualDualStep_ * deltaZ_[iColumn];
                    if (part1 * part2 < lowerBoundGap) {
                         goodMove = false;
                         break;
                    }
               }
               if (upperBound(iColumn)) {
                    CoinWorkDouble part1 = upperSlack_[iColumn] + actualPrimalStep_ * deltaSU_[iColumn];
                    CoinWorkDouble part2 = wVec_[iColumn] + actualDualStep_ * deltaW_[iColumn];
                    if (part1 * part2 < lowerBoundGap) {
                         goodMove = false;
                         break;
                    }
               }
          }
     }
     CoinWorkDouble * nextDj = NULL;
     CoinWorkDouble maximumDualError = maximumDualError_;
#ifndef NO_RTTI
     ClpQuadraticObjective * quadraticObj = (dynamic_cast< ClpQuadraticObjective*>(objective_));
#else
     ClpQuadraticObjective * quadraticObj = NULL;
     if (objective_->type() == 2)
          quadraticObj = (static_cast< ClpQuadraticObjective*>(objective_));
#endif
     CoinWorkDouble * dualArray = reinterpret_cast<CoinWorkDouble *>(dual_);
     if (quadraticObj) {
          // change gammad
          gammad = 1.0e-4;
          CoinWorkDouble gamma2 = gamma_ * gamma_;
          nextDj = new CoinWorkDouble [numberColumns_];
          CoinWorkDouble * nextSolution = new CoinWorkDouble [numberColumns_];
          // put next primal into nextSolution
          for ( iColumn = 0; iColumn < numberColumns_; iColumn++) {
               if (!flagged(iColumn)) {
                    nextSolution[iColumn] = solution_[iColumn] +
                                            actualPrimalStep_ * deltaX_[iColumn];
               } else {
                    nextSolution[iColumn] = solution_[iColumn];
               }
          }
          // do reduced costs
          CoinMemcpyN(cost_, numberColumns_, nextDj);
          matrix_->transposeTimes(-1.0, dualArray, nextDj);
          matrix_->transposeTimes(-actualDualStep_, deltaY_, nextDj);
          quadraticDjs(nextDj, nextSolution, 1.0);
          delete [] nextSolution;
          CoinPackedMatrix * quadratic = quadraticObj->quadraticObjective();
          const int * columnQuadraticLength = quadratic->getVectorLengths();
          for (int iColumn = 0; iColumn < numberColumns_; iColumn++) {
               if (!fixedOrFree(iColumn)) {
                    CoinWorkDouble newZ = 0.0;
                    CoinWorkDouble newW = 0.0;
                    if (lowerBound(iColumn)) {
                         newZ = zVec_[iColumn] + actualDualStep_ * deltaZ_[iColumn];
                    }
                    if (upperBound(iColumn)) {
                         newW = wVec_[iColumn] + actualDualStep_ * deltaW_[iColumn];
                    }
                    if (columnQuadraticLength[iColumn]) {
                         CoinWorkDouble gammaTerm = gamma2;
                         if (primalR_)
                              gammaTerm += primalR_[iColumn];
                         //CoinWorkDouble dualInfeasibility=
                         //dj_[iColumn]-zVec_[iColumn]+wVec_[iColumn]
                         //+gammaTerm*solution_[iColumn];
                         CoinWorkDouble newInfeasibility =
                              nextDj[iColumn] - newZ + newW
                              + gammaTerm * (solution_[iColumn] + actualPrimalStep_ * deltaX_[iColumn]);
                         maximumDualError = CoinMax(maximumDualError, newInfeasibility);
                         //if (CoinAbs(newInfeasibility)>CoinMax(2000.0*maximumDualError_,1.0e-2)) {
                         //if (dualInfeasibility*newInfeasibility<0.0) {
                         //  printf("%d current %g next %g\n",iColumn,dualInfeasibility,
                         //       newInfeasibility);
                         //  goodMove=false;
                         //}
                         //}
                    }
               }
          }
          delete [] nextDj;
     }
//      Satisfy g_p(alpha)?
     if (rhsNorm_ > solutionNorm_) {
          solutionNorm_ = rhsNorm_;
     }
     CoinWorkDouble errorCheck = maximumRHSError_ / solutionNorm_;
     if (errorCheck < maximumBoundInfeasibility_) {
          errorCheck = maximumBoundInfeasibility_;
     }
     // scale back move
     move = CoinMin(move, 0.95);
     //scale
     if ((1.0 - move)*errorCheck > primalTolerance()) {
          if (nextGap < gammap*(1.0 - move)*errorCheck) {
               goodMove = false;
          }
     }
     //      Satisfy g_d(alpha)?
     errorCheck = maximumDualError / objectiveNorm_;
     if ((1.0 - move)*errorCheck > dualTolerance()) {
          if (nextGap < gammad*(1.0 - move)*errorCheck) {
               goodMove = false;
          }
     }
     if (goodMove)
          bestNextGap = nextGap;
     return goodMove;
}
// updateSolution.  Updates solution at end of iteration
//returns number fixed
int ClpPredictorCorrector::updateSolution(CoinWorkDouble /*nextGap*/)
{
     CoinWorkDouble * dualArray = reinterpret_cast<CoinWorkDouble *>(dual_);
     int numberTotal = numberRows_ + numberColumns_;
     //update pi
     multiplyAdd(deltaY_, numberRows_, actualDualStep_, dualArray, 1.0);
     CoinZeroN(errorRegion_, numberRows_);
     CoinZeroN(rhsFixRegion_, numberRows_);
     CoinWorkDouble maximumRhsInfeasibility = 0.0;
     CoinWorkDouble maximumBoundInfeasibility = 0.0;
     CoinWorkDouble maximumDualError = 1.0e-12;
     CoinWorkDouble primalObjectiveValue = 0.0;
     CoinWorkDouble dualObjectiveValue = 0.0;
     CoinWorkDouble solutionNorm = 1.0e-12;
     int numberKilled = 0;
     CoinWorkDouble freeMultiplier = 1.0e6;
     CoinWorkDouble trueNorm = diagonalNorm_ / diagonalScaleFactor_;
     if (freeMultiplier < trueNorm) {
          freeMultiplier = trueNorm;
     }
     if (freeMultiplier > 1.0e12) {
          freeMultiplier = 1.0e12;
     }
     freeMultiplier = 0.5 / freeMultiplier;
     CoinWorkDouble condition = CoinAbs(cholesky_->choleskyCondition());
     bool caution;
     if ((condition < 1.0e10 && trueNorm < 1.0e12) || numberIterations_ < 20) {
          caution = false;
     } else {
          caution = true;
     }
     CoinWorkDouble extra = eExtra;
     const CoinWorkDouble largeFactor = 1.0e2;
     CoinWorkDouble largeGap = largeFactor * solutionNorm_;
     if (largeGap < largeFactor) {
          largeGap = largeFactor;
     }
     CoinWorkDouble dualFake = 0.0;
     CoinWorkDouble dualTolerance =  dblParam_[ClpDualTolerance];
     dualTolerance = dualTolerance / scaleFactor_;
     if (dualTolerance < 1.0e-12) {
          dualTolerance = 1.0e-12;
     }
     CoinWorkDouble offsetObjective = 0.0;
     CoinWorkDouble killTolerance = primalTolerance();
     //CoinWorkDouble nextMu = nextGap/(static_cast<CoinWorkDouble>(2*numberComplementarityPairs_));
     //printf("using gap of %g\n",nextMu);
     //largest allowable ratio of lowerSlack/zVec (etc)
     CoinWorkDouble epsilonBase;
     CoinWorkDouble diagonalLimit;
     if (!caution) {
          epsilonBase = eBase;
          diagonalLimit = eDiagonal;
     } else {
          epsilonBase = eBaseCaution;
          diagonalLimit = eDiagonalCaution;
     }
     CoinWorkDouble maximumDJInfeasibility = 0.0;
     int numberIncreased = 0;
     int numberDecreased = 0;
     CoinWorkDouble largestDiagonal = 0.0;
     CoinWorkDouble smallestDiagonal = 1.0e50;
     CoinWorkDouble largeGap2 = CoinMax(1.0e7, 1.0e2 * solutionNorm_);
     //largeGap2 = 1.0e9;
     // When to start looking at killing (factor0
     CoinWorkDouble killFactor;
#ifndef NO_RTTI
     ClpQuadraticObjective * quadraticObj = (dynamic_cast< ClpQuadraticObjective*>(objective_));
#else
     ClpQuadraticObjective * quadraticObj = NULL;
     if (objective_->type() == 2)
          quadraticObj = (static_cast< ClpQuadraticObjective*>(objective_));
#endif
#ifndef CLP_CAUTION
#define KILL_ITERATION 50
#else
#if CLP_CAUTION < 1
#define KILL_ITERATION 50
#else
#define KILL_ITERATION 100
#endif
#endif
     if (!quadraticObj || 1) {
          if (numberIterations_ < KILL_ITERATION) {
               killFactor = 1.0;
          } else if (numberIterations_ < 2 * KILL_ITERATION) {
               killFactor = 5.0;
               stepLength_ = CoinMax(stepLength_, 0.9995);
          } else if (numberIterations_ < 4 * KILL_ITERATION) {
               killFactor = 20.0;
               stepLength_ = CoinMax(stepLength_, 0.99995);
          } else {
               killFactor = 1.0e2;
               stepLength_ = CoinMax(stepLength_, 0.999995);
          }
     } else {
          killFactor = 1.0;
     }
     // put next primal into deltaSL_
     int iColumn;
     int iRow;
     for (iColumn = 0; iColumn < numberTotal; iColumn++) {
          CoinWorkDouble thisWeight = deltaX_[iColumn];
          CoinWorkDouble newPrimal = solution_[iColumn] + 1.0 * actualPrimalStep_ * thisWeight;
          deltaSL_[iColumn] = newPrimal;
     }
#if 0
     // nice idea but doesn't work
     multiplyAdd(solution_ + numberColumns_, numberRows_, -1.0, errorRegion_, 0.0);
     matrix_->times(1.0, solution_, errorRegion_);
     multiplyAdd(deltaSL_ + numberColumns_, numberRows_, -1.0, rhsFixRegion_, 0.0);
     matrix_->times(1.0, deltaSL_, rhsFixRegion_);
     CoinWorkDouble newNorm =  maximumAbsElement(deltaSL_, numberTotal);
     CoinWorkDouble tol = newNorm * primalTolerance();
     bool goneInf = false;
     for (iRow = 0; iRow < numberRows_; iRow++) {
          CoinWorkDouble value = errorRegion_[iRow];
          CoinWorkDouble valueNew = rhsFixRegion_[iRow];
          if (CoinAbs(value) < tol && CoinAbs(valueNew) > tol) {
               printf("row %d old %g new %g\n", iRow, value, valueNew);
               goneInf = true;
          }
     }
     if (goneInf) {
          actualPrimalStep_ *= 0.5;
          for (iColumn = 0; iColumn < numberTotal; iColumn++) {
               CoinWorkDouble thisWeight = deltaX_[iColumn];
               CoinWorkDouble newPrimal = solution_[iColumn] + 1.0 * actualPrimalStep_ * thisWeight;
               deltaSL_[iColumn] = newPrimal;
          }
     }
     CoinZeroN(errorRegion_, numberRows_);
     CoinZeroN(rhsFixRegion_, numberRows_);
#endif
     // do reduced costs
     CoinMemcpyN(dualArray, numberRows_, dj_ + numberColumns_);
     CoinMemcpyN(cost_, numberColumns_, dj_);
     CoinWorkDouble quadraticOffset = quadraticDjs(dj_, deltaSL_, 1.0);
     // Save modified costs for fixed variables
     CoinMemcpyN(dj_, numberColumns_, deltaSU_);
     matrix_->transposeTimes(-1.0, dualArray, dj_);
     CoinWorkDouble gamma2 = gamma_ * gamma_; // gamma*gamma will be added to diagonal
     CoinWorkDouble gammaOffset = 0.0;
#if 0
     const CoinBigIndex * columnStart = matrix_->getVectorStarts();
     const int * columnLength = matrix_->getVectorLengths();
     const int * row = matrix_->getIndices();
     const double * element = matrix_->getElements();
#endif
     for (iColumn = 0; iColumn < numberTotal; iColumn++) {
          if (!flagged(iColumn)) {
               CoinWorkDouble reducedCost = dj_[iColumn];
               bool thisKilled = false;
               CoinWorkDouble zValue = zVec_[iColumn] + actualDualStep_ * deltaZ_[iColumn];
               CoinWorkDouble wValue = wVec_[iColumn] + actualDualStep_ * deltaW_[iColumn];
               zVec_[iColumn] = zValue;
               wVec_[iColumn] = wValue;
               CoinWorkDouble thisWeight = deltaX_[iColumn];
               CoinWorkDouble oldPrimal = solution_[iColumn];
               CoinWorkDouble newPrimal = solution_[iColumn] + actualPrimalStep_ * thisWeight;
               CoinWorkDouble dualObjectiveThis = 0.0;
               CoinWorkDouble sUpper = extra;
               CoinWorkDouble sLower = extra;
               CoinWorkDouble kill;
               if (CoinAbs(newPrimal) > 1.0e4) {
                    kill = killTolerance * 1.0e-4 * newPrimal;
               } else {
                    kill = killTolerance;
               }
               kill *= 1.0e-3; //be conservative
               CoinWorkDouble smallerSlack = COIN_DBL_MAX;
               bool fakeOldBounds = false;
               bool fakeNewBounds = false;
               CoinWorkDouble trueLower;
               CoinWorkDouble trueUpper;
               if (iColumn < numberColumns_) {
                    trueLower = columnLower_[iColumn];
                    trueUpper = columnUpper_[iColumn];
               } else {
                    trueLower = rowLower_[iColumn-numberColumns_];
                    trueUpper = rowUpper_[iColumn-numberColumns_];
               }
               if (oldPrimal > trueLower + largeGap2 &&
                         oldPrimal < trueUpper - largeGap2)
                    fakeOldBounds = true;
               if (newPrimal > trueLower + largeGap2 &&
                         newPrimal < trueUpper - largeGap2)
                    fakeNewBounds = true;
               if (fakeOldBounds) {
                    if (fakeNewBounds) {
                         lower_[iColumn] = newPrimal - largeGap2;
                         lowerSlack_[iColumn] = largeGap2;
                         upper_[iColumn] = newPrimal + largeGap2;
                         upperSlack_[iColumn] = largeGap2;
                    } else {
                         lower_[iColumn] = trueLower;
                         setLowerBound(iColumn);
                         lowerSlack_[iColumn] = CoinMax(newPrimal - trueLower, 1.0);
                         upper_[iColumn] = trueUpper;
                         setUpperBound(iColumn);
                         upperSlack_[iColumn] = CoinMax(trueUpper - newPrimal, 1.0);
                    }
               } else if (fakeNewBounds) {
                    lower_[iColumn] = newPrimal - largeGap2;
                    lowerSlack_[iColumn] = largeGap2;
                    upper_[iColumn] = newPrimal + largeGap2;
                    upperSlack_[iColumn] = largeGap2;
                    // so we can just have one test
                    fakeOldBounds = true;
               }
               CoinWorkDouble lowerBoundInfeasibility = 0.0;
               CoinWorkDouble upperBoundInfeasibility = 0.0;
               //double saveNewPrimal = newPrimal;
               if (lowerBound(iColumn)) {
                    CoinWorkDouble oldSlack = lowerSlack_[iColumn];
                    CoinWorkDouble newSlack;
                    newSlack =
                         lowerSlack_[iColumn] + actualPrimalStep_ * (oldPrimal - oldSlack
                                   + thisWeight - lower_[iColumn]);
                    if (fakeOldBounds)
                         newSlack = lowerSlack_[iColumn];
                    CoinWorkDouble epsilon = CoinAbs(newSlack) * epsilonBase;
                    epsilon = CoinMin(epsilon, 1.0e-5);
                    //epsilon=1.0e-14;
                    //make sure reasonable
                    if (zValue < epsilon) {
                         zValue = epsilon;
                    }
                    CoinWorkDouble feasibleSlack = newPrimal - lower_[iColumn];
                    if (feasibleSlack > 0.0 && newSlack > 0.0) {
                         CoinWorkDouble larger;
                         if (newSlack > feasibleSlack) {
                              larger = newSlack;
                         } else {
                              larger = feasibleSlack;
                         }
                         if (CoinAbs(feasibleSlack - newSlack) < 1.0e-6 * larger) {
                              newSlack = feasibleSlack;
                         }
                    }
                    if (zVec_[iColumn] > dualTolerance) {
                         dualObjectiveThis += lower_[iColumn] * zVec_[iColumn];
                    }
                    lowerSlack_[iColumn] = newSlack;
                    if (newSlack < smallerSlack) {
                         smallerSlack = newSlack;
                    }
                    lowerBoundInfeasibility = CoinAbs(newPrimal - lowerSlack_[iColumn] - lower_[iColumn]);
                    if (lowerSlack_[iColumn] <= kill * killFactor && CoinAbs(newPrimal - lower_[iColumn]) <= kill * killFactor) {
                         CoinWorkDouble step = CoinMin(actualPrimalStep_ * 1.1, 1.0);
                         CoinWorkDouble newPrimal2 = solution_[iColumn] + step * thisWeight;
                         if (newPrimal2 < newPrimal && dj_[iColumn] > 1.0e-5 && numberIterations_ > 50 - 40) {
                              newPrimal = lower_[iColumn];
                              lowerSlack_[iColumn] = 0.0;
                              //printf("fixing %d to lower\n",iColumn);
                         }
                    }
                    if (lowerSlack_[iColumn] <= kill && CoinAbs(newPrimal - lower_[iColumn]) <= kill) {
                         //may be better to leave at value?
                         newPrimal = lower_[iColumn];
                         lowerSlack_[iColumn] = 0.0;
                         thisKilled = true;
                         //cout<<j<<" l "<<reducedCost<<" "<<zVec_[iColumn]<<endl;
                    } else {
                         sLower += lowerSlack_[iColumn];
                    }
               }
               if (upperBound(iColumn)) {
                    CoinWorkDouble oldSlack = upperSlack_[iColumn];
                    CoinWorkDouble newSlack;
                    newSlack =
                         upperSlack_[iColumn] + actualPrimalStep_ * (-oldPrimal - oldSlack
                                   - thisWeight + upper_[iColumn]);
                    if (fakeOldBounds)
                         newSlack = upperSlack_[iColumn];
                    CoinWorkDouble epsilon = CoinAbs(newSlack) * epsilonBase;
                    epsilon = CoinMin(epsilon, 1.0e-5);
                    //make sure reasonable
                    //epsilon=1.0e-14;
                    if (wValue < epsilon) {
                         wValue = epsilon;
                    }
                    CoinWorkDouble feasibleSlack = upper_[iColumn] - newPrimal;
                    if (feasibleSlack > 0.0 && newSlack > 0.0) {
                         CoinWorkDouble larger;
                         if (newSlack > feasibleSlack) {
                              larger = newSlack;
                         } else {
                              larger = feasibleSlack;
                         }
                         if (CoinAbs(feasibleSlack - newSlack) < 1.0e-6 * larger) {
                              newSlack = feasibleSlack;
                         }
                    }
                    if (wVec_[iColumn] > dualTolerance) {
                         dualObjectiveThis -= upper_[iColumn] * wVec_[iColumn];
                    }
                    upperSlack_[iColumn] = newSlack;
                    if (newSlack < smallerSlack) {
                         smallerSlack = newSlack;
                    }
                    upperBoundInfeasibility = CoinAbs(newPrimal + upperSlack_[iColumn] - upper_[iColumn]);
                    if (upperSlack_[iColumn] <= kill * killFactor && CoinAbs(newPrimal - upper_[iColumn]) <= kill * killFactor) {
                         CoinWorkDouble step = CoinMin(actualPrimalStep_ * 1.1, 1.0);
                         CoinWorkDouble newPrimal2 = solution_[iColumn] + step * thisWeight;
                         if (newPrimal2 > newPrimal && dj_[iColumn] < -1.0e-5 && numberIterations_ > 50 - 40) {
                              newPrimal = upper_[iColumn];
                              upperSlack_[iColumn] = 0.0;
                              //printf("fixing %d to upper\n",iColumn);
                         }
                    }
                    if (upperSlack_[iColumn] <= kill && CoinAbs(newPrimal - upper_[iColumn]) <= kill) {
                         //may be better to leave at value?
                         newPrimal = upper_[iColumn];
                         upperSlack_[iColumn] = 0.0;
                         thisKilled = true;
                    } else {
                         sUpper += upperSlack_[iColumn];
                    }
               }
#if 0
               if (newPrimal != saveNewPrimal && iColumn < numberColumns_) {
                    // adjust slacks
                    double movement = newPrimal - saveNewPrimal;
                    for (CoinBigIndex j = columnStart[iColumn];
                              j < columnStart[iColumn] + columnLength[iColumn]; j++) {
                         int iRow = row[j];
                         double slackMovement = element[j] * movement;
                         solution_[iRow+numberColumns_] += slackMovement; // sign?
                    }
               }
#endif
               solution_[iColumn] = newPrimal;
               if (CoinAbs(newPrimal) > solutionNorm) {
                    solutionNorm = CoinAbs(newPrimal);
               }
               if (!thisKilled) {
                    CoinWorkDouble gammaTerm = gamma2;
                    if (primalR_) {
                         gammaTerm += primalR_[iColumn];
                         quadraticOffset += newPrimal * newPrimal * primalR_[iColumn];
                    }
                    CoinWorkDouble dualInfeasibility =
                         reducedCost - zVec_[iColumn] + wVec_[iColumn] + gammaTerm * newPrimal;
                    if (CoinAbs(dualInfeasibility) > dualTolerance) {
#if 0
                         if (dualInfeasibility > 0.0) {
                              // To improve we could reduce t and/or increase z
                              if (lowerBound(iColumn)) {
                                   CoinWorkDouble complementarity = zVec_[iColumn] * lowerSlack_[iColumn];
                                   if (complementarity < nextMu) {
                                        CoinWorkDouble change =
                                             CoinMin(dualInfeasibility,
                                                     (nextMu - complementarity) / lowerSlack_[iColumn]);
                                        dualInfeasibility -= change;
                                        COIN_DETAIL_PRINT(printf("%d lb locomp %g - dual inf from %g to %g\n",
                                               iColumn, complementarity, dualInfeasibility + change,
								 dualInfeasibility));
                                        zVec_[iColumn] += change;
                                        zValue = CoinMax(zVec_[iColumn], 1.0e-12);
                                   }
                              }
                              if (upperBound(iColumn)) {
                                   CoinWorkDouble complementarity = wVec_[iColumn] * upperSlack_[iColumn];
                                   if (complementarity > nextMu) {
                                        CoinWorkDouble change =
                                             CoinMin(dualInfeasibility,
                                                     (complementarity - nextMu) / upperSlack_[iColumn]);
                                        dualInfeasibility -= change;
                                        COIN_DETAIL_PRINT(printf("%d ub hicomp %g - dual inf from %g to %g\n",
                                               iColumn, complementarity, dualInfeasibility + change,
								 dualInfeasibility));
                                        wVec_[iColumn] -= change;
                                        wValue = CoinMax(wVec_[iColumn], 1.0e-12);
                                   }
                              }
                         } else {
                              // To improve we could reduce z and/or increase t
                              if (lowerBound(iColumn)) {
                                   CoinWorkDouble complementarity = zVec_[iColumn] * lowerSlack_[iColumn];
                                   if (complementarity > nextMu) {
                                        CoinWorkDouble change =
                                             CoinMax(dualInfeasibility,
                                                     (nextMu - complementarity) / lowerSlack_[iColumn]);
                                        dualInfeasibility -= change;
                                        COIN_DETAIL_PRINT(printf("%d lb hicomp %g - dual inf from %g to %g\n",
                                               iColumn, complementarity, dualInfeasibility + change,
								 dualInfeasibility));
                                        zVec_[iColumn] += change;
                                        zValue = CoinMax(zVec_[iColumn], 1.0e-12);
                                   }
                              }
                              if (upperBound(iColumn)) {
                                   CoinWorkDouble complementarity = wVec_[iColumn] * upperSlack_[iColumn];
                                   if (complementarity < nextMu) {
                                        CoinWorkDouble change =
                                             CoinMax(dualInfeasibility,
                                                     (complementarity - nextMu) / upperSlack_[iColumn]);
                                        dualInfeasibility -= change;
                                        COIN_DETAIL_PRINT(printf("%d ub locomp %g - dual inf from %g to %g\n",
                                               iColumn, complementarity, dualInfeasibility + change,
								 dualInfeasibility));
                                        wVec_[iColumn] -= change;
                                        wValue = CoinMax(wVec_[iColumn], 1.0e-12);
                                   }
                              }
                         }
#endif
                         dualFake += newPrimal * dualInfeasibility;
                    }
                    if (lowerBoundInfeasibility > maximumBoundInfeasibility) {
                         maximumBoundInfeasibility = lowerBoundInfeasibility;
                    }
                    if (upperBoundInfeasibility > maximumBoundInfeasibility) {
                         maximumBoundInfeasibility = upperBoundInfeasibility;
                    }
                    dualInfeasibility = CoinAbs(dualInfeasibility);
                    if (dualInfeasibility > maximumDualError) {
                         //printf("bad dual %d %g\n",iColumn,
                         // reducedCost-zVec_[iColumn]+wVec_[iColumn]+gammaTerm*newPrimal);
                         maximumDualError = dualInfeasibility;
                    }
                    dualObjectiveValue += dualObjectiveThis;
                    gammaOffset += newPrimal * newPrimal;
                    if (sLower > largeGap) {
                         sLower = largeGap;
                    }
                    if (sUpper > largeGap) {
                         sUpper = largeGap;
                    }
#if 1
                    CoinWorkDouble divisor = sLower * wValue + sUpper * zValue + gammaTerm * sLower * sUpper;
                    CoinWorkDouble diagonalValue = (sUpper * sLower) / divisor;
#else
                    CoinWorkDouble divisor = sLower * wValue + sUpper * zValue + gammaTerm * sLower * sUpper;
                    CoinWorkDouble diagonalValue2 = (sUpper * sLower) / divisor;
                    CoinWorkDouble diagonalValue;
                    if (!lowerBound(iColumn)) {
                         diagonalValue = wValue / sUpper + gammaTerm;
                    } else if (!upperBound(iColumn)) {
                         diagonalValue = zValue / sLower + gammaTerm;
                    } else {
                         diagonalValue = zValue / sLower + wValue / sUpper + gammaTerm;
                    }
                    diagonalValue = 1.0 / diagonalValue;
#endif
                    diagonal_[iColumn] = diagonalValue;
                    //FUDGE
                    if (diagonalValue > diagonalLimit) {
#ifdef COIN_DEVELOP
                         std::cout << "large diagonal " << diagonalValue << std::endl;
#endif
                         diagonal_[iColumn] = diagonalLimit;
                    }
#ifdef COIN_DEVELOP
                    if (diagonalValue < 1.0e-10) {
                         //std::cout<<"small diagonal "<<diagonalValue<<std::endl;
                    }
#endif
                    if (diagonalValue > largestDiagonal) {
                         largestDiagonal = diagonalValue;
                    }
                    if (diagonalValue < smallestDiagonal) {
                         smallestDiagonal = diagonalValue;
                    }
                    deltaX_[iColumn] = 0.0;
               } else {
                    numberKilled++;
                    if (solution_[iColumn] != lower_[iColumn] &&
                              solution_[iColumn] != upper_[iColumn]) {
                         COIN_DETAIL_PRINT(printf("%d %g %g %g\n", iColumn, static_cast<double>(lower_[iColumn]),
						  static_cast<double>(solution_[iColumn]), static_cast<double>(upper_[iColumn])));
                    }
                    diagonal_[iColumn] = 0.0;
                    zVec_[iColumn] = 0.0;
                    wVec_[iColumn] = 0.0;
                    setFlagged(iColumn);
                    setFixedOrFree(iColumn);
                    deltaX_[iColumn] = newPrimal;
                    offsetObjective += newPrimal * deltaSU_[iColumn];
               }
          } else {
               deltaX_[iColumn] = solution_[iColumn];
               diagonal_[iColumn] = 0.0;
               offsetObjective += solution_[iColumn] * deltaSU_[iColumn];
               if (upper_[iColumn] - lower_[iColumn] > 1.0e-5) {
                    if (solution_[iColumn] < lower_[iColumn] + 1.0e-8 && dj_[iColumn] < -1.0e-8) {
                         if (-dj_[iColumn] > maximumDJInfeasibility) {
                              maximumDJInfeasibility = -dj_[iColumn];
                         }
                    }
                    if (solution_[iColumn] > upper_[iColumn] - 1.0e-8 && dj_[iColumn] > 1.0e-8) {
                         if (dj_[iColumn] > maximumDJInfeasibility) {
                              maximumDJInfeasibility = dj_[iColumn];
                         }
                    }
               }
          }
          primalObjectiveValue += solution_[iColumn] * cost_[iColumn];
     }
     handler_->message(CLP_BARRIER_DIAGONAL, messages_)
               << static_cast<double>(largestDiagonal) << static_cast<double>(smallestDiagonal)
               << CoinMessageEol;
#if 0
     // If diagonal wild - kill some
     if (largestDiagonal > 1.0e17 * smallestDiagonal) {
          CoinWorkDouble killValue = largestDiagonal * 1.0e-17;
          for (int iColumn = 0; iColumn < numberTotal; iColumn++) {
               if (CoinAbs(diagonal_[iColumn]) < killValue)
                    diagonal_[iolumn] = 0.0;
          }
     }
#endif
     // update rhs region
     multiplyAdd(deltaX_ + numberColumns_, numberRows_, -1.0, rhsFixRegion_, 1.0);
     matrix_->times(1.0, deltaX_, rhsFixRegion_);
     primalObjectiveValue += 0.5 * gamma2 * gammaOffset + 0.5 * quadraticOffset;
     if (quadraticOffset) {
          //  printf("gamma offset %g %g, quadoffset %g\n",gammaOffset,gamma2*gammaOffset,quadraticOffset);
     }

     dualObjectiveValue += offsetObjective + dualFake;
     dualObjectiveValue -= 0.5 * gamma2 * gammaOffset + 0.5 * quadraticOffset;
     if (numberIncreased || numberDecreased) {
          handler_->message(CLP_BARRIER_SLACKS, messages_)
                    << numberIncreased << numberDecreased
                    << CoinMessageEol;
     }
     if (maximumDJInfeasibility) {
          handler_->message(CLP_BARRIER_DUALINF, messages_)
                    << static_cast<double>(maximumDJInfeasibility)
                    << CoinMessageEol;
     }
     // Need to rethink (but it is only for printing)
     sumPrimalInfeasibilities_ = maximumRhsInfeasibility;
     sumDualInfeasibilities_ = maximumDualError;
     maximumBoundInfeasibility_ = maximumBoundInfeasibility;
     //compute error and fixed RHS
     multiplyAdd(solution_ + numberColumns_, numberRows_, -1.0, errorRegion_, 0.0);
     matrix_->times(1.0, solution_, errorRegion_);
     maximumDualError_ = maximumDualError;
     maximumBoundInfeasibility_ = maximumBoundInfeasibility;
     solutionNorm_ = solutionNorm;
     //finish off objective computation
     primalObjective_ = primalObjectiveValue * scaleFactor_;
     CoinWorkDouble dualValue2 = innerProduct(dualArray, numberRows_,
                                 rhsFixRegion_);
     dualObjectiveValue -= dualValue2;
     dualObjective_ = dualObjectiveValue * scaleFactor_;
     if (numberKilled) {
          handler_->message(CLP_BARRIER_KILLED, messages_)
                    << numberKilled
                    << CoinMessageEol;
     }
     CoinWorkDouble maximumRHSError1 = 0.0;
     CoinWorkDouble maximumRHSError2 = 0.0;
     CoinWorkDouble primalOffset = 0.0;
     char * dropped = cholesky_->rowsDropped();
     for (iRow = 0; iRow < numberRows_; iRow++) {
          CoinWorkDouble value = errorRegion_[iRow];
          if (!dropped[iRow]) {
               if (CoinAbs(value) > maximumRHSError1) {
                    maximumRHSError1 = CoinAbs(value);
               }
          } else {
               if (CoinAbs(value) > maximumRHSError2) {
                    maximumRHSError2 = CoinAbs(value);
               }
               primalOffset += value * dualArray[iRow];
          }
     }
     primalObjective_ -= primalOffset * scaleFactor_;
     if (maximumRHSError1 > maximumRHSError2) {
          maximumRHSError_ = maximumRHSError1;
     } else {
          maximumRHSError_ = maximumRHSError1; //note change
          if (maximumRHSError2 > primalTolerance()) {
               handler_->message(CLP_BARRIER_ABS_DROPPED, messages_)
                         << static_cast<double>(maximumRHSError2)
                         << CoinMessageEol;
          }
     }
     objectiveNorm_ = maximumAbsElement(dualArray, numberRows_);
     if (objectiveNorm_ < 1.0e-12) {
          objectiveNorm_ = 1.0e-12;
     }
     if (objectiveNorm_ < baseObjectiveNorm_) {
          //std::cout<<" base "<<baseObjectiveNorm_<<" "<<objectiveNorm_<<std::endl;
          if (objectiveNorm_ < baseObjectiveNorm_ * 1.0e-4) {
               objectiveNorm_ = baseObjectiveNorm_ * 1.0e-4;
          }
     }
     bool primalFeasible = true;
     if (maximumRHSError_ > primalTolerance() ||
               maximumDualError_ > dualTolerance / scaleFactor_) {
          handler_->message(CLP_BARRIER_ABS_ERROR, messages_)
                    << static_cast<double>(maximumRHSError_) << static_cast<double>(maximumDualError_)
                    << CoinMessageEol;
     }
     if (rhsNorm_ > solutionNorm_) {
          solutionNorm_ = rhsNorm_;
     }
     CoinWorkDouble scaledRHSError = maximumRHSError_ / (solutionNorm_ + 10.0);
     bool dualFeasible = true;
#if KEEP_GOING_IF_FIXED > 5
     if (maximumBoundInfeasibility_ > primalTolerance() ||
               scaledRHSError > primalTolerance())
          primalFeasible = false;
#else
     if (maximumBoundInfeasibility_ > primalTolerance() ||
               scaledRHSError > CoinMax(CoinMin(100.0 * primalTolerance(), 1.0e-5),
                                        primalTolerance()))
          primalFeasible = false;
#endif
     // relax dual test if obj big and gap smallish
     CoinWorkDouble gap = CoinAbs(primalObjective_ - dualObjective_);
     CoinWorkDouble sizeObj = CoinMin(CoinAbs(primalObjective_), CoinAbs(dualObjective_)) + 1.0e-50;
     //printf("gap %g sizeObj %g ratio %g comp %g\n",
     //     gap,sizeObj,gap/sizeObj,complementarityGap_);
     if (numberIterations_ > 100 && gap / sizeObj < 1.0e-9 && complementarityGap_ < 1.0e-7 * sizeObj)
          dualTolerance *= 1.0e2;
     if (maximumDualError_ > objectiveNorm_ * dualTolerance)
          dualFeasible = false;
     if (!primalFeasible || !dualFeasible) {
          handler_->message(CLP_BARRIER_FEASIBLE, messages_)
                    << static_cast<double>(maximumBoundInfeasibility_) << static_cast<double>(scaledRHSError)
                    << static_cast<double>(maximumDualError_ / objectiveNorm_)
                    << CoinMessageEol;
     }
     if (!gonePrimalFeasible_) {
          gonePrimalFeasible_ = primalFeasible;
     } else if (!primalFeasible) {
          gonePrimalFeasible_ = primalFeasible;
          if (!numberKilled) {
               handler_->message(CLP_BARRIER_GONE_INFEASIBLE, messages_)
                         << CoinMessageEol;
          }
     }
     if (!goneDualFeasible_) {
          goneDualFeasible_ = dualFeasible;
     } else if (!dualFeasible) {
          handler_->message(CLP_BARRIER_GONE_INFEASIBLE, messages_)
                    << CoinMessageEol;
          goneDualFeasible_ = dualFeasible;
     }
     //objectiveValue();
     if (solutionNorm_ > 1.0e40) {
          std::cout << "primal off to infinity" << std::endl;
          abort();
     }
     if (objectiveNorm_ > 1.0e40) {
          std::cout << "dual off to infinity" << std::endl;
          abort();
     }
     handler_->message(CLP_BARRIER_STEP, messages_)
               << static_cast<double>(actualPrimalStep_)
               << static_cast<double>(actualDualStep_)
               << static_cast<double>(mu_)
               << CoinMessageEol;
     numberIterations_++;
     return numberKilled;
}
//  Save info on products of affine deltaSU*deltaW and deltaSL*deltaZ
CoinWorkDouble
ClpPredictorCorrector::affineProduct()
{
     CoinWorkDouble product = 0.0;
     //IF zVec starts as 0 then deltaZ always zero
     //(remember if free then zVec not 0)
     //I think free can be done with careful use of boundSlacks to zero
     //out all we want
     for (int iColumn = 0; iColumn < numberRows_ + numberColumns_; iColumn++) {
          CoinWorkDouble w3 = deltaZ_[iColumn] * deltaX_[iColumn];
          CoinWorkDouble w4 = -deltaW_[iColumn] * deltaX_[iColumn];
          if (lowerBound(iColumn)) {
               w3 += deltaZ_[iColumn] * (solution_[iColumn] - lowerSlack_[iColumn] - lower_[iColumn]);
               product += w3;
          }
          if (upperBound(iColumn)) {
               w4 += deltaW_[iColumn] * (-solution_[iColumn] - upperSlack_[iColumn] + upper_[iColumn]);
               product += w4;
          }
     }
     return product;
}
//See exactly what would happen given current deltas
void
ClpPredictorCorrector::debugMove(int /*phase*/,
                                 CoinWorkDouble primalStep, CoinWorkDouble dualStep)
{
#ifndef SOME_DEBUG
     return;
#endif
     CoinWorkDouble * dualArray = reinterpret_cast<CoinWorkDouble *>(dual_);
     int numberTotal = numberRows_ + numberColumns_;
     CoinWorkDouble * dualNew = ClpCopyOfArray(dualArray, numberRows_);
     CoinWorkDouble * errorRegionNew = new CoinWorkDouble [numberRows_];
     CoinWorkDouble * rhsFixRegionNew = new CoinWorkDouble [numberRows_];
     CoinWorkDouble * primalNew = ClpCopyOfArray(solution_, numberTotal);
     CoinWorkDouble * djNew = new CoinWorkDouble[numberTotal];
     //update pi
     multiplyAdd(deltaY_, numberRows_, dualStep, dualNew, 1.0);
     // do reduced costs
     CoinMemcpyN(dualNew, numberRows_, djNew + numberColumns_);
     CoinMemcpyN(cost_, numberColumns_, djNew);
     matrix_->transposeTimes(-1.0, dualNew, djNew);
     // update x
     int iColumn;
     for (iColumn = 0; iColumn < numberTotal; iColumn++) {
          if (!flagged(iColumn))
               primalNew[iColumn] += primalStep * deltaX_[iColumn];
     }
     CoinWorkDouble quadraticOffset = quadraticDjs(djNew, primalNew, 1.0);
     CoinZeroN(errorRegionNew, numberRows_);
     CoinZeroN(rhsFixRegionNew, numberRows_);
     CoinWorkDouble maximumBoundInfeasibility = 0.0;
     CoinWorkDouble maximumDualError = 1.0e-12;
     CoinWorkDouble primalObjectiveValue = 0.0;
     CoinWorkDouble dualObjectiveValue = 0.0;
     CoinWorkDouble solutionNorm = 1.0e-12;
     const CoinWorkDouble largeFactor = 1.0e2;
     CoinWorkDouble largeGap = largeFactor * solutionNorm_;
     if (largeGap < largeFactor) {
          largeGap = largeFactor;
     }
     CoinWorkDouble dualFake = 0.0;
     CoinWorkDouble dualTolerance =  dblParam_[ClpDualTolerance];
     dualTolerance = dualTolerance / scaleFactor_;
     if (dualTolerance < 1.0e-12) {
          dualTolerance = 1.0e-12;
     }
     CoinWorkDouble newGap = 0.0;
     CoinWorkDouble offsetObjective = 0.0;
     CoinWorkDouble gamma2 = gamma_ * gamma_; // gamma*gamma will be added to diagonal
     CoinWorkDouble gammaOffset = 0.0;
     CoinWorkDouble maximumDjInfeasibility = 0.0;
     for ( iColumn = 0; iColumn < numberTotal; iColumn++) {
          if (!flagged(iColumn)) {
               CoinWorkDouble reducedCost = djNew[iColumn];
               CoinWorkDouble zValue = zVec_[iColumn] + dualStep * deltaZ_[iColumn];
               CoinWorkDouble wValue = wVec_[iColumn] + dualStep * deltaW_[iColumn];
               CoinWorkDouble thisWeight = deltaX_[iColumn];
               CoinWorkDouble oldPrimal = solution_[iColumn];
               CoinWorkDouble newPrimal = primalNew[iColumn];
               CoinWorkDouble lowerBoundInfeasibility = 0.0;
               CoinWorkDouble upperBoundInfeasibility = 0.0;
               if (lowerBound(iColumn)) {
                    CoinWorkDouble oldSlack = lowerSlack_[iColumn];
                    CoinWorkDouble newSlack =
                         lowerSlack_[iColumn] + primalStep * (oldPrimal - oldSlack
                                   + thisWeight - lower_[iColumn]);
                    if (zValue > dualTolerance) {
                         dualObjectiveValue += lower_[iColumn] * zVec_[iColumn];
                    }
                    lowerBoundInfeasibility = CoinAbs(newPrimal - newSlack - lower_[iColumn]);
                    newGap += newSlack * zValue;
               }
               if (upperBound(iColumn)) {
                    CoinWorkDouble oldSlack = upperSlack_[iColumn];
                    CoinWorkDouble newSlack =
                         upperSlack_[iColumn] + primalStep * (-oldPrimal - oldSlack
                                   - thisWeight + upper_[iColumn]);
                    if (wValue > dualTolerance) {
                         dualObjectiveValue -= upper_[iColumn] * wVec_[iColumn];
                    }
                    upperBoundInfeasibility = CoinAbs(newPrimal + newSlack - upper_[iColumn]);
                    newGap += newSlack * wValue;
               }
               if (CoinAbs(newPrimal) > solutionNorm) {
                    solutionNorm = CoinAbs(newPrimal);
               }
               CoinWorkDouble gammaTerm = gamma2;
               if (primalR_) {
                    gammaTerm += primalR_[iColumn];
                    quadraticOffset += newPrimal * newPrimal * primalR_[iColumn];
               }
               CoinWorkDouble dualInfeasibility =
                    reducedCost - zValue + wValue + gammaTerm * newPrimal;
               if (CoinAbs(dualInfeasibility) > dualTolerance) {
                    dualFake += newPrimal * dualInfeasibility;
               }
               if (lowerBoundInfeasibility > maximumBoundInfeasibility) {
                    maximumBoundInfeasibility = lowerBoundInfeasibility;
               }
               if (upperBoundInfeasibility > maximumBoundInfeasibility) {
                    maximumBoundInfeasibility = upperBoundInfeasibility;
               }
               dualInfeasibility = CoinAbs(dualInfeasibility);
               if (dualInfeasibility > maximumDualError) {
                    //printf("bad dual %d %g\n",iColumn,
                    // reducedCost-zVec_[iColumn]+wVec_[iColumn]+gammaTerm*newPrimal);
                    maximumDualError = dualInfeasibility;
               }
               gammaOffset += newPrimal * newPrimal;
               djNew[iColumn] = 0.0;
          } else {
               offsetObjective += primalNew[iColumn] * cost_[iColumn];
               if (upper_[iColumn] - lower_[iColumn] > 1.0e-5) {
                    if (primalNew[iColumn] < lower_[iColumn] + 1.0e-8 && djNew[iColumn] < -1.0e-8) {
                         if (-djNew[iColumn] > maximumDjInfeasibility) {
                              maximumDjInfeasibility = -djNew[iColumn];
                         }
                    }
                    if (primalNew[iColumn] > upper_[iColumn] - 1.0e-8 && djNew[iColumn] > 1.0e-8) {
                         if (djNew[iColumn] > maximumDjInfeasibility) {
                              maximumDjInfeasibility = djNew[iColumn];
                         }
                    }
               }
               djNew[iColumn] = primalNew[iColumn];
          }
          primalObjectiveValue += solution_[iColumn] * cost_[iColumn];
     }
     // update rhs region
     multiplyAdd(djNew + numberColumns_, numberRows_, -1.0, rhsFixRegionNew, 1.0);
     matrix_->times(1.0, djNew, rhsFixRegionNew);
     primalObjectiveValue += 0.5 * gamma2 * gammaOffset + 0.5 * quadraticOffset;
     dualObjectiveValue += offsetObjective + dualFake;
     dualObjectiveValue -= 0.5 * gamma2 * gammaOffset + 0.5 * quadraticOffset;
     // Need to rethink (but it is only for printing)
     //compute error and fixed RHS
     multiplyAdd(primalNew + numberColumns_, numberRows_, -1.0, errorRegionNew, 0.0);
     matrix_->times(1.0, primalNew, errorRegionNew);
     //finish off objective computation
     CoinWorkDouble primalObjectiveNew = primalObjectiveValue * scaleFactor_;
     CoinWorkDouble dualValue2 = innerProduct(dualNew, numberRows_,
                                 rhsFixRegionNew);
     dualObjectiveValue -= dualValue2;
     //CoinWorkDouble dualObjectiveNew=dualObjectiveValue*scaleFactor_;
     CoinWorkDouble maximumRHSError1 = 0.0;
     CoinWorkDouble maximumRHSError2 = 0.0;
     CoinWorkDouble primalOffset = 0.0;
     char * dropped = cholesky_->rowsDropped();
     int iRow;
     for (iRow = 0; iRow < numberRows_; iRow++) {
          CoinWorkDouble value = errorRegionNew[iRow];
          if (!dropped[iRow]) {
               if (CoinAbs(value) > maximumRHSError1) {
                    maximumRHSError1 = CoinAbs(value);
               }
          } else {
               if (CoinAbs(value) > maximumRHSError2) {
                    maximumRHSError2 = CoinAbs(value);
               }
               primalOffset += value * dualNew[iRow];
          }
     }
     primalObjectiveNew -= primalOffset * scaleFactor_;
     //CoinWorkDouble maximumRHSError;
     if (maximumRHSError1 > maximumRHSError2) {
          ;//maximumRHSError = maximumRHSError1;
     } else {
          //maximumRHSError = maximumRHSError1; //note change
          if (maximumRHSError2 > primalTolerance()) {
               handler_->message(CLP_BARRIER_ABS_DROPPED, messages_)
                         << static_cast<double>(maximumRHSError2)
                         << CoinMessageEol;
          }
     }
     /*printf("PH %d %g, %g new comp %g, b %g, p %g, d %g\n",phase,
      primalStep,dualStep,newGap,maximumBoundInfeasibility,
      maximumRHSError,maximumDualError);
     if (handler_->logLevel()>1)
       printf("       objs %g %g\n",
        primalObjectiveNew,dualObjectiveNew);
     if (maximumDjInfeasibility) {
       printf(" max dj error on fixed %g\n",
        maximumDjInfeasibility);
        } */
     delete [] dualNew;
     delete [] errorRegionNew;
     delete [] rhsFixRegionNew;
     delete [] primalNew;
     delete [] djNew;
}
