/* $Id$ */ // Copyright (C) 2002, International Business Machines // Corporation and others, Copyright (C) 2012, FasterCoin. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifdef ABC_JUST_ONE_FACTORIZATION #include "CoinAbcCommonFactorization.hpp" #define CoinAbcTypeFactorization CoinAbcBaseFactorization #define ABC_SMALL -1 #include "CoinAbcBaseFactorization.hpp" #endif #ifdef CoinAbcTypeFactorization #include "CoinIndexedVector.hpp" #include "CoinHelperFunctions.hpp" #include "CoinAbcHelperFunctions.hpp" #if ABC_NORMAL_DEBUG > 0 // for conflicts extern int cilk_conflict; #endif #define UNROLL 1 #define INLINE_IT //#define INLINE_IT2 inline void scatterUpdateInline(CoinSimplexInt number, CoinFactorizationDouble pivotValue, const CoinFactorizationDouble *COIN_RESTRICT thisElement, const CoinSimplexInt *COIN_RESTRICT thisIndex, CoinFactorizationDouble *COIN_RESTRICT region) { #if UNROLL == 0 for (CoinBigIndex j = number - 1; j >= 0; j--) { CoinSimplexInt iRow = thisIndex[j]; CoinFactorizationDouble regionValue = region[iRow]; CoinFactorizationDouble value = thisElement[j]; assert(value); region[iRow] = regionValue - value * pivotValue; } #elif UNROLL == 1 if ((number & 1) != 0) { number--; CoinSimplexInt iRow = thisIndex[number]; CoinFactorizationDouble regionValue = region[iRow]; CoinFactorizationDouble value = thisElement[number]; region[iRow] = regionValue - value * pivotValue; } for (CoinBigIndex j = number - 1; j >= 0; j -= 2) { CoinSimplexInt iRow0 = thisIndex[j]; CoinSimplexInt iRow1 = thisIndex[j - 1]; CoinFactorizationDouble regionValue0 = region[iRow0]; CoinFactorizationDouble regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[j] * pivotValue; region[iRow1] = regionValue1 - thisElement[j - 1] * pivotValue; } #elif UNROLL == 2 CoinSimplexInt iRow0; CoinSimplexInt iRow1; CoinFactorizationDouble regionValue0; CoinFactorizationDouble regionValue1; switch (static_cast< unsigned int >(number)) { case 0: break; case 1: iRow0 = thisIndex[0]; regionValue0 = region[iRow0]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; break; case 2: iRow0 = thisIndex[0]; iRow1 = thisIndex[1]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; region[iRow1] = regionValue1 - thisElement[1] * pivotValue; break; case 3: iRow0 = thisIndex[0]; iRow1 = thisIndex[1]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; region[iRow1] = regionValue1 - thisElement[1] * pivotValue; iRow0 = thisIndex[2]; regionValue0 = region[iRow0]; region[iRow0] = regionValue0 - thisElement[2] * pivotValue; break; case 4: iRow0 = thisIndex[0]; iRow1 = thisIndex[1]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; region[iRow1] = regionValue1 - thisElement[1] * pivotValue; iRow0 = thisIndex[2]; iRow1 = thisIndex[3]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[2] * pivotValue; region[iRow1] = regionValue1 - thisElement[3] * pivotValue; break; case 5: iRow0 = thisIndex[0]; iRow1 = thisIndex[1]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; region[iRow1] = regionValue1 - thisElement[1] * pivotValue; iRow0 = thisIndex[2]; iRow1 = thisIndex[3]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[2] * pivotValue; region[iRow1] = regionValue1 - thisElement[3] * pivotValue; iRow0 = thisIndex[4]; regionValue0 = region[iRow0]; region[iRow0] = regionValue0 - thisElement[4] * pivotValue; break; case 6: iRow0 = thisIndex[0]; iRow1 = thisIndex[1]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; region[iRow1] = regionValue1 - thisElement[1] * pivotValue; iRow0 = thisIndex[2]; iRow1 = thisIndex[3]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[2] * pivotValue; region[iRow1] = regionValue1 - thisElement[3] * pivotValue; iRow0 = thisIndex[4]; iRow1 = thisIndex[5]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[4] * pivotValue; region[iRow1] = regionValue1 - thisElement[5] * pivotValue; break; case 7: iRow0 = thisIndex[0]; iRow1 = thisIndex[1]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; region[iRow1] = regionValue1 - thisElement[1] * pivotValue; iRow0 = thisIndex[2]; iRow1 = thisIndex[3]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[2] * pivotValue; region[iRow1] = regionValue1 - thisElement[3] * pivotValue; iRow0 = thisIndex[4]; iRow1 = thisIndex[5]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[4] * pivotValue; region[iRow1] = regionValue1 - thisElement[5] * pivotValue; iRow0 = thisIndex[6]; regionValue0 = region[iRow0]; region[iRow0] = regionValue0 - thisElement[6] * pivotValue; break; case 8: iRow0 = thisIndex[0]; iRow1 = thisIndex[1]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; region[iRow1] = regionValue1 - thisElement[1] * pivotValue; iRow0 = thisIndex[2]; iRow1 = thisIndex[3]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[2] * pivotValue; region[iRow1] = regionValue1 - thisElement[3] * pivotValue; iRow0 = thisIndex[4]; iRow1 = thisIndex[5]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[4] * pivotValue; region[iRow1] = regionValue1 - thisElement[5] * pivotValue; iRow0 = thisIndex[6]; iRow1 = thisIndex[7]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[6] * pivotValue; region[iRow1] = regionValue1 - thisElement[7] * pivotValue; break; default: if ((number & 1) != 0) { number--; CoinSimplexInt iRow = thisIndex[number]; CoinFactorizationDouble regionValue = region[iRow]; CoinFactorizationDouble value = thisElement[number]; region[iRow] = regionValue - value * pivotValue; } for (CoinBigIndex j = number - 1; j >= 0; j -= 2) { CoinSimplexInt iRow0 = thisIndex[j]; CoinSimplexInt iRow1 = thisIndex[j - 1]; CoinFactorizationDouble regionValue0 = region[iRow0]; CoinFactorizationDouble regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[j] * pivotValue; region[iRow1] = regionValue1 - thisElement[j - 1] * pivotValue; } break; } #endif } inline CoinFactorizationDouble gatherUpdate(CoinSimplexInt number, const CoinFactorizationDouble *COIN_RESTRICT thisElement, const CoinSimplexInt *COIN_RESTRICT thisIndex, CoinFactorizationDouble *COIN_RESTRICT region) { CoinFactorizationDouble pivotValue = 0.0; for (CoinBigIndex j = 0; j < number; j++) { CoinFactorizationDouble value = thisElement[j]; CoinSimplexInt jRow = thisIndex[j]; value *= region[jRow]; pivotValue -= value; } return pivotValue; } #undef INLINE_IT // updateColumnR. Updates part of column (FTRANR) void CoinAbcTypeFactorization::updateColumnR(CoinIndexedVector *regionSparse #if ABC_SMALL < 2 , CoinAbcStatistics &statistics #endif #if ABC_PARALLEL , int whichSparse #endif ) const { if (numberR_) { CoinSimplexDouble *COIN_RESTRICT region = regionSparse->denseVector(); #if ABC_SMALL < 3 CoinSimplexInt *COIN_RESTRICT regionIndex = regionSparse->getIndices(); CoinSimplexInt numberNonZero = regionSparse->getNumElements(); #endif const CoinBigIndex *COIN_RESTRICT startColumn = startColumnRAddress_ - numberRows_; const CoinSimplexInt *COIN_RESTRICT indexRow = indexRowRAddress_; CoinSimplexInt *COIN_RESTRICT indexRowR2 = indexRowRAddress_ + lengthAreaR_; if (gotRCopy()) indexRowR2 += lengthAreaR_; const CoinFactorizationDouble *COIN_RESTRICT element = elementRAddress_; const CoinSimplexInt *COIN_RESTRICT permute = permuteAddress_; instrument_do("CoinAbcFactorizationUpdateR", sizeR); #if ABC_SMALL < 2 // Size of R CoinSimplexDouble sizeR = startColumnRAddress_[numberR_]; // Work out very dubious idea of what would be fastest // Average CoinSimplexDouble averageR = sizeR / (static_cast< CoinSimplexDouble >(numberRowsExtra_)); // weights (relative to actual work) CoinSimplexDouble setMark = 0.1; // setting mark CoinSimplexDouble test1 = 1.0; // starting ftran (without testPivot) CoinSimplexDouble testPivot = 2.0; // Seeing if zero etc CoinSimplexDouble startDot = 2.0; // For starting dot product version // For final scan CoinSimplexDouble final = numberNonZero * 1.0; CoinSimplexDouble methodTime0; // For first type methodTime0 = numberPivots_ * (testPivot + ((static_cast< double >(numberNonZero)) / (static_cast< double >(numberRows_)) * averageR)); methodTime0 += numberNonZero * (test1 + averageR); methodTime0 += (numberNonZero + numberPivots_) * setMark; // third CoinSimplexDouble methodTime2 = sizeR + numberPivots_ * startDot + numberNonZero * final; // switch off if necessary CoinSimplexInt method = 0; if (!gotRCopy() || !gotSparse() || methodTime2 < methodTime0) { method = 2; } /* IF we have row copy of R then always store in old way - otherwise unpermuted way. */ #endif #if ABC_SMALL < 2 const CoinSimplexInt *numberInColumnPlus = numberInColumnPlusAddress_; #endif const CoinSimplexInt *pivotRowBack = pivotColumnAddress_; #if ABC_SMALL < 2 switch (method) { case 0: { instrument_start("CoinAbcFactorizationUpdateRSparse1", numberRows_); // mark known to be zero CoinCheckZero *COIN_RESTRICT mark = markRowAddress_; #if ABC_PARALLEL if (whichSparse) { mark = reinterpret_cast< CoinCheckZero * >(reinterpret_cast< char * >(mark) + whichSparse * sizeSparseArray_); } #endif // mark all rows which will be permuted for (CoinSimplexInt i = numberRows_; i < numberRowsExtra_; i++) { CoinSimplexInt iRow = permute[i]; mark[iRow] = 1; } // we have another copy of R in R const CoinFactorizationDouble *COIN_RESTRICT elementR = elementRAddress_ + lengthAreaR_; const CoinSimplexInt *COIN_RESTRICT indexRowR = indexRowRAddress_ + lengthAreaR_; const CoinBigIndex *COIN_RESTRICT startR = startColumnRAddress_ + maximumPivots_ + 1; // For current list order does not matter as // only affects end CoinSimplexInt newNumber = 0; for (CoinSimplexInt i = 0; i < numberNonZero; i++) { CoinSimplexInt iRow = regionIndex[i]; CoinFactorizationDouble pivotValue = region[iRow]; assert(region[iRow]); if (!mark[iRow]) { regionIndex[newNumber++] = iRow; } CoinSimplexInt kRow = permute[iRow]; CoinSimplexInt number = numberInColumnPlus[kRow]; instrument_add(number); if (TEST_INT_NONZERO(number)) { CoinBigIndex start = startR[kRow]; #ifndef INLINE_IT CoinBigIndex end = start + number; for (CoinBigIndex j = start; j < end; j++) { CoinFactorizationDouble value = elementR[j]; CoinSimplexInt jRow = indexRowR[j]; region[jRow] -= pivotValue * value; } #else CoinAbcScatterUpdate(number, pivotValue, elementR + start, indexRowR + start, region); #endif } } instrument_start("CoinAbcFactorizationUpdateRSparse2", numberRows_); numberNonZero = newNumber; for (CoinSimplexInt i = numberRows_; i < numberRowsExtra_; i++) { //move using permute_ (stored in inverse fashion) CoinSimplexInt iRow = permute[i]; CoinFactorizationDouble pivotValue = region[iRow] + region[i]; //zero out pre-permuted region[iRow] = 0.0; region[i] = 0.0; if (!TEST_LESS_THAN_TOLERANCE_REGISTER(pivotValue)) { int jRow = pivotRowBack[i]; assert(!region[jRow]); region[jRow] = pivotValue; CoinSimplexInt number = numberInColumnPlus[i]; instrument_add(number); if (TEST_INT_NONZERO(number)) { CoinBigIndex start = startR[i]; #ifndef INLINE_IT CoinBigIndex end = start + number; for (CoinBigIndex j = start; j < end; j++) { CoinFactorizationDouble value = elementR[j]; CoinSimplexInt jRow = indexRowR[j]; region[jRow] -= pivotValue * value; } #else CoinAbcScatterUpdate(number, pivotValue, elementR + start, indexRowR + start, region); #endif } } } instrument_end(); for (CoinSimplexInt i = numberRows_; i < numberRowsExtra_; i++) { CoinSimplexInt iRow = permute[i]; assert(iRow < numberRows_); if (mark[iRow]) { mark[iRow] = 0; CoinExponent expValue = ABC_EXPONENT(region[iRow]); if (expValue) { if (!TEST_EXPONENT_LESS_THAN_TOLERANCE(expValue)) { regionIndex[numberNonZero++] = iRow; } else { region[iRow] = 0.0; } } } } } break; case 2: #endif { instrument_start("CoinAbcFactorizationUpdateRDense", numberRows_); CoinBigIndex start = startColumn[numberRows_]; for (CoinSimplexInt i = numberRows_; i < numberRowsExtra_; i++) { //move using permute_ (stored in inverse fashion) CoinBigIndex end = startColumn[i + 1]; CoinSimplexInt iRow = pivotRowBack[i]; assert(iRow < numberRows_); CoinFactorizationDouble pivotValue = region[iRow]; instrument_add(end - start); if (TEST_INT_NONZERO(end - start)) { #ifndef INLINE_IT2 for (CoinBigIndex j = start; j < end; j++) { CoinFactorizationDouble value = element[j]; CoinSimplexInt jRow = indexRow[j]; value *= region[jRow]; pivotValue -= value; } #else pivotValue += CoinAbcGatherUpdate(end - start, element + start, indexRow + start, region); #endif start = end; } #if ABC_SMALL < 3 if (!TEST_LESS_THAN_TOLERANCE_REGISTER(pivotValue)) { if (!region[iRow]) regionIndex[numberNonZero++] = iRow; region[iRow] = pivotValue; } else { if (region[iRow]) region[iRow] = COIN_INDEXED_REALLY_TINY_ELEMENT; } #else region[iRow] = pivotValue; #endif } instrument_end(); #if ABC_SMALL < 3 // pack down CoinSimplexInt n = numberNonZero; numberNonZero = 0; for (CoinSimplexInt i = 0; i < n; i++) { CoinSimplexInt indexValue = regionIndex[i]; CoinExponent expValue = ABC_EXPONENT(region[indexValue]); if (expValue) { if (!TEST_EXPONENT_LESS_THAN_TOLERANCE(expValue)) { regionIndex[numberNonZero++] = indexValue; // needed? is region used } else { region[indexValue] = 0.0; } } } #endif } #if ABC_SMALL < 2 break; } #endif #if ABC_SMALL < 3 //set counts regionSparse->setNumElements(numberNonZero); #endif } #if ABC_SMALL < 2 if (factorizationStatistics()) statistics.countAfterR_ += regionSparse->getNumElements(); #endif } #ifdef EARLY_FACTORIZE #include "AbcSimplex.hpp" #include "AbcMatrix.hpp" // Returns -2 if can't, -1 if singular, -99 memory, 0 OK int CoinAbcTypeFactorization::factorize(AbcSimplex *model, CoinIndexedVector &stuff) { AbcMatrix *matrix = model->abcMatrix(); setStatus(-99); int *COIN_RESTRICT pivotTemp = stuff.getIndices(); int numberColumnBasic = stuff.getNumElements(); // compute how much in basis int numberSlacks = numberRows_ - numberColumnBasic; CoinBigIndex numberElements = numberSlacks + matrix->countBasis(pivotTemp + numberSlacks, numberColumnBasic); // Not needed for dense numberElements = 3 * numberRows_ + 3 * numberElements + 20000; getAreas(numberRows_, numberSlacks + numberColumnBasic, numberElements, 2 * numberElements); numberSlacks_ = numberSlacks; // Fill in counts so we can skip part of preProcess // This is NOT needed for dense but would be needed for later versions CoinFactorizationDouble *COIN_RESTRICT elementU; int *COIN_RESTRICT indexRowU; CoinBigIndex *COIN_RESTRICT startColumnU; int *COIN_RESTRICT numberInRow; int *COIN_RESTRICT numberInColumn; elementU = this->elements(); indexRowU = this->indices(); startColumnU = this->starts(); numberInRow = this->numberInRow(); numberInColumn = this->numberInColumn(); CoinZeroN(numberInRow, numberRows_ + 1); CoinZeroN(numberInColumn, numberRows_); for (int i = 0; i < numberSlacks_; i++) { int iRow = pivotTemp[i]; indexRowU[i] = iRow; startColumnU[i] = i; elementU[i] = 1.0; numberInRow[iRow] = 1; numberInColumn[i] = 1; } startColumnU[numberSlacks_] = numberSlacks_; matrix->fillBasis(pivotTemp + numberSlacks_, numberColumnBasic, indexRowU, startColumnU + numberSlacks_, numberInRow, numberInColumn + numberSlacks_, elementU); numberElements = startColumnU[numberRows_ - 1] + numberInColumn[numberRows_ - 1]; preProcess(); factor(model); if (status() == 0) { // Put sequence numbers in workArea int *savePivots = reinterpret_cast< int * >(workAreaAddress_); CoinAbcMemcpy(savePivots, pivotTemp, numberRows_); postProcess(pivotTemp, savePivots); return 0; } else { return -2; } } // 0 success, -1 can't +1 accuracy problems int CoinAbcTypeFactorization::replaceColumns(const AbcSimplex *model, CoinIndexedVector &stuff, int firstPivot, int lastPivot, bool cleanUp) { // Could skip some if goes in and out (only if easy as then no alpha check) // Put sequence numbers in workArea int *savePivots = reinterpret_cast< int * >(workAreaAddress_); const int *pivotIndices = stuff.getIndices(); CoinSimplexDouble *pivotValues = stuff.denseVector(); int savePivot = stuff.capacity(); savePivot--; savePivot -= 2 * firstPivot; int numberDo = lastPivot - firstPivot; // Say clear stuff.setNumElements(0); bool badUpdates = false; for (int iPivot = 0; iPivot < numberDo; iPivot++) { int sequenceOut = pivotIndices[--savePivot]; CoinSimplexDouble alpha = pivotValues[savePivot]; int sequenceIn = pivotIndices[--savePivot]; CoinSimplexDouble btranAlpha = pivotValues[savePivot]; int pivotRow; for (pivotRow = 0; pivotRow < numberRows_; pivotRow++) { if (sequenceOut == savePivots[pivotRow]) break; } assert(pivotRow < numberRows_); savePivots[pivotRow] = sequenceIn; model->unpack(stuff, sequenceIn); updateColumnFTPart1(stuff); stuff.clear(); //checkReplacePart1a(&stuff,pivotRow); CoinSimplexDouble ftAlpha = checkReplacePart1(&stuff, pivotRow); // may need better check if (checkReplacePart2(pivotRow, btranAlpha, alpha, ftAlpha) > 1) { badUpdates = true; printf("Inaccuracy ? btranAlpha %g ftranAlpha %g ftAlpha %g\n", btranAlpha, alpha, ftAlpha); break; } replaceColumnPart3(model, &stuff, NULL, pivotRow, ftAlpha); } int flag; if (!badUpdates) { flag = 1; if (cleanUp) { CoinAbcMemcpy(model->pivotVariable(), savePivots, numberRows_); } } else { flag = -1; } stuff.setNumElements(flag); return flag > 0 ? 0 : flag; } #endif #ifdef ABC_ORDERED_FACTORIZATION // Permute in for Ftran void CoinAbcTypeFactorization::permuteInForFtran(CoinIndexedVector ®ionSparse, bool full) const { int numberNonZero = regionSparse.getNumElements(); const int *COIN_RESTRICT permuteIn = permuteAddress_ + maximumRowsExtra_ + 1; double *COIN_RESTRICT region = regionSparse.denseVector(); double *COIN_RESTRICT tempRegion = region + numberRows_; int *COIN_RESTRICT index = regionSparse.getIndices(); if ((numberNonZero << 1) > numberRows_ || full) { CoinAbcMemcpy(tempRegion, region, numberRows_); CoinAbcMemset0(region, numberRows_); numberNonZero = 0; for (int i = 0; i < numberRows_; i++) { double value = tempRegion[i]; if (value) { tempRegion[i] = 0.0; int iRow = permuteIn[i]; region[iRow] = value; index[numberNonZero++] = iRow; } } regionSparse.setNumElements(numberNonZero); } else { for (int i = 0; i < numberNonZero; i++) { int iRow = index[i]; double value = region[iRow]; region[iRow] = 0.0; iRow = permuteIn[iRow]; tempRegion[iRow] = value; index[i] = iRow; } // and back for (int i = 0; i < numberNonZero; i++) { int iRow = index[i]; double value = tempRegion[iRow]; tempRegion[iRow] = 0.0; region[iRow] = value; } } } // Permute in for Btran and multiply by pivot Region void CoinAbcTypeFactorization::permuteInForBtranAndMultiply(CoinIndexedVector ®ionSparse, bool full) const { int numberNonZero = regionSparse.getNumElements(); double *COIN_RESTRICT region = regionSparse.denseVector(); double *COIN_RESTRICT tempRegion = region + numberRows_; int *COIN_RESTRICT index = regionSparse.getIndices(); const CoinFactorizationDouble *COIN_RESTRICT pivotRegion = pivotRegionAddress_; if (full) { numberNonZero = 0; for (int iRow = 0; iRow < numberRows_; iRow++) { double value = region[iRow]; if (value) { region[iRow] = 0.0; tempRegion[iRow] = value * pivotRegion[iRow]; index[numberNonZero++] = iRow; } } regionSparse.setNumElements(numberNonZero); } else { for (int i = 0; i < numberNonZero; i++) { int iRow = index[i]; double value = region[iRow]; region[iRow] = 0.0; tempRegion[iRow] = value * pivotRegion[iRow]; } } regionSparse.setDenseVector(tempRegion); #if 0 if (numberNonZero) printf("BtranIn vector %p region %p regionTemp %p\n", ®ionSparse,region,tempRegion); else printf("BtranIn no els! vector %p region %p regionTemp %p\n", ®ionSparse,region,tempRegion); #endif } // Permute out for Btran void CoinAbcTypeFactorization::permuteOutForBtran(CoinIndexedVector ®ionSparse) const { int numberNonZero = regionSparse.getNumElements(); const int *COIN_RESTRICT permuteIn = permuteAddress_ + maximumRowsExtra_ + 1; const int *COIN_RESTRICT permuteOut = permuteIn + numberRows_; CoinFactorizationDouble *COIN_RESTRICT tempRegion = denseVector(regionSparse); CoinFactorizationDouble *COIN_RESTRICT region = tempRegion - numberRows_; CoinSimplexInt *COIN_RESTRICT index = regionSparse.getIndices(); regionSparse.setDenseVector(region); //printf("BtranOut vector %p region %p regionTemp %p\n", // ®ionSparse,region,tempRegion); for (int i = 0; i < numberNonZero; i++) { int iRow = index[i]; double value = tempRegion[iRow]; tempRegion[iRow] = 0.0; iRow = permuteOut[iRow]; region[iRow] = value; index[i] = iRow; } } #endif #if COIN_BIG_DOUBLE == 1 // To a work array and associate vector void CoinAbcTypeFactorization::toLongArray(CoinIndexedVector *vector, int which) const { assert(which >= 0 && which < FACTOR_CPU); assert(!associatedVector_[which]); associatedVector_[which] = vector; CoinSimplexDouble *COIN_RESTRICT region = vector->denseVector(); CoinSimplexInt *COIN_RESTRICT regionIndex = vector->getIndices(); CoinSimplexInt numberNonZero = vector->getNumElements(); long double *COIN_RESTRICT longRegion = longArray_[which].array(); assert(!vector->packedMode()); // could check all of longRegion for zero but this should trap most errors for (int i = 0; i < numberNonZero; i++) { int iRow = regionIndex[i]; assert(!longRegion[iRow]); longRegion[iRow] = region[iRow]; region[iRow] = 0.0; } } // From a work array and dis-associate vector void CoinAbcTypeFactorization::fromLongArray(CoinIndexedVector *vector) const { int which; for (which = 0; which < FACTOR_CPU; which++) if (vector == associatedVector_[which]) break; assert(which < FACTOR_CPU); associatedVector_[which] = NULL; CoinSimplexDouble *COIN_RESTRICT region = vector->denseVector(); CoinSimplexInt *COIN_RESTRICT regionIndex = vector->getIndices(); CoinSimplexInt numberNonZero = vector->getNumElements(); long double *COIN_RESTRICT longRegion = longArray_[which].array(); assert(!vector->packedMode()); // could check all of region for zero but this should trap most errors for (int i = 0; i < numberNonZero; i++) { int iRow = regionIndex[i]; assert(!region[iRow]); region[iRow] = longRegion[iRow]; longRegion[iRow] = 0.0; } } // From a work array and dis-associate vector void CoinAbcTypeFactorization::fromLongArray(int which) const { assert(which < FACTOR_CPU); CoinIndexedVector *vector = associatedVector_[which]; associatedVector_[which] = NULL; CoinSimplexDouble *COIN_RESTRICT region = vector->denseVector(); CoinSimplexInt *COIN_RESTRICT regionIndex = vector->getIndices(); CoinSimplexInt numberNonZero = vector->getNumElements(); long double *COIN_RESTRICT longRegion = longArray_[which].array(); assert(!vector->packedMode()); // could check all of region for zero but this should trap most errors for (int i = 0; i < numberNonZero; i++) { int iRow = regionIndex[i]; assert(!region[iRow]); region[iRow] = longRegion[iRow]; longRegion[iRow] = 0.0; } } // Returns long double * associated with vector long double * CoinAbcTypeFactorization::denseVector(CoinIndexedVector *vector) const { int which; for (which = 0; which < FACTOR_CPU; which++) if (vector == associatedVector_[which]) break; assert(which < FACTOR_CPU); return longArray_[which].array(); } // Returns long double * associated with vector long double * CoinAbcTypeFactorization::denseVector(CoinIndexedVector &vector) const { int which; for (which = 0; which < FACTOR_CPU; which++) if (&vector == associatedVector_[which]) break; assert(which < FACTOR_CPU); return longArray_[which].array(); } // Returns long double * associated with vector const long double * CoinAbcTypeFactorization::denseVector(const CoinIndexedVector *vector) const { int which; for (which = 0; which < FACTOR_CPU; which++) if (vector == associatedVector_[which]) break; assert(which < FACTOR_CPU); return longArray_[which].array(); } void CoinAbcTypeFactorization::scan(CoinIndexedVector *vector) const { int numberNonZero = 0; int *COIN_RESTRICT index = vector->getIndices(); CoinFactorizationDouble *COIN_RESTRICT region = denseVector(vector); for (int i = 0; i < numberRows_; i++) { if (fabs(region[i]) > zeroTolerance_) index[numberNonZero++] = i; else region[i] = 0.0; } vector->setNumElements(numberNonZero); } // Clear all hidden arrays void CoinAbcTypeFactorization::clearHiddenArrays() { for (int which = 0; which < FACTOR_CPU; which++) { if (associatedVector_[which]) { CoinIndexedVector *vector = associatedVector_[which]; associatedVector_[which] = NULL; CoinFactorizationDouble *COIN_RESTRICT region = longArray_[which].array(); CoinSimplexInt *COIN_RESTRICT regionIndex = vector->getIndices(); CoinSimplexInt numberNonZero = vector->getNumElements(); } } } #endif #endif /* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 */