// Copyright (C) 2000, International Business Machines // Corporation and others. All Rights Reserved. #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include #include "CoinFinite.hpp" #include "CoinHelperFunctions.hpp" #include "CoinPackedVectorBase.hpp" //############################################################################# double * CoinPackedVectorBase::denseVector(int denseSize) const { if (getMaxIndex() >= denseSize) throw CoinError("Dense vector size is less than max index", "denseVector", "CoinPackedVectorBase"); double * dv = new double[denseSize]; CoinFillN(dv, denseSize, 0.0); const int s = getNumElements(); const int * inds = getIndices(); const double * elems = getElements(); for (int i = 0; i < s; ++i) dv[inds[i]] = elems[i]; return dv; } //----------------------------------------------------------------------------- double CoinPackedVectorBase::operator[](int i) const { if (! testedDuplicateIndex_) duplicateIndex("operator[]", "CoinPackedVectorBase"); // Get a reference to a map of full storage indices to // packed storage location. const std::set & sv = *indexSet("operator[]", "CoinPackedVectorBase"); #if 1 if (sv.find(i) == sv.end()) return 0.0; return getElements()[findIndex(i)]; #else // LL: suggested change, somthing is wrong with this const size_t ind = std::distance(sv.begin(), sv.find(i)); return (ind == sv.size()) ? 0.0 : getElements()[ind]; #endif } //############################################################################# void CoinPackedVectorBase::setTestForDuplicateIndex(bool test) const { if (test == true) { testForDuplicateIndex_ = true; duplicateIndex("setTestForDuplicateIndex", "CoinPackedVectorBase"); } else { testForDuplicateIndex_ = false; testedDuplicateIndex_ = false; } } //############################################################################# void CoinPackedVectorBase::setTestForDuplicateIndexWhenTrue(bool test) const { // We know everything is okay so let's not test (e.g. full array) testForDuplicateIndex_ = test; testedDuplicateIndex_ = test; } //############################################################################# int CoinPackedVectorBase::getMaxIndex() const { findMaxMinIndices(); return maxIndex_; } //----------------------------------------------------------------------------- int CoinPackedVectorBase::getMinIndex() const { findMaxMinIndices(); return minIndex_; } //----------------------------------------------------------------------------- void CoinPackedVectorBase::duplicateIndex(const char* methodName, const char * className) const { if (testForDuplicateIndex()) indexSet(methodName, className); testedDuplicateIndex_ = true; } //----------------------------------------------------------------------------- bool CoinPackedVectorBase::isExistingIndex(int i) const { if (! testedDuplicateIndex_) duplicateIndex("indexExists", "CoinPackedVectorBase"); const std::set & sv = *indexSet("indexExists", "CoinPackedVectorBase"); return sv.find(i) != sv.end(); } int CoinPackedVectorBase::findIndex(int i) const { const int * inds = getIndices(); int retVal = std::find(inds, inds + getNumElements(), i) - inds; if (retVal == getNumElements() ) retVal = -1; return retVal; } //############################################################################# bool CoinPackedVectorBase::operator==(const CoinPackedVectorBase& rhs) const { return (getNumElements()==rhs.getNumElements() && std::equal(getIndices(), getIndices() + getNumElements(), rhs.getIndices()) && std::equal(getElements(), getElements() + getNumElements(), rhs.getElements())); } //----------------------------------------------------------------------------- bool CoinPackedVectorBase::operator!=(const CoinPackedVectorBase& rhs) const { return !( (*this)==rhs ); } //----------------------------------------------------------------------------- double CoinPackedVectorBase::dotProduct(const double* dense) const { const double * elems = getElements(); const int * inds = getIndices(); double dp = 0.0; for (int i = getNumElements() - 1; i >= 0; --i) dp += elems[i] * dense[inds[i]]; return dp; } //----------------------------------------------------------------------------- double CoinPackedVectorBase::oneNorm() const { register double norm = 0.0; register const double* elements = getElements(); for (int i = getNumElements() - 1; i >= 0; --i) { norm += fabs(elements[i]); } return norm; } //----------------------------------------------------------------------------- double CoinPackedVectorBase::normSquare() const { return std::inner_product(getElements(), getElements() + getNumElements(), getElements(), 0.0); } //----------------------------------------------------------------------------- double CoinPackedVectorBase::infNorm() const { register double norm = 0.0; register const double* elements = getElements(); for (int i = getNumElements() - 1; i >= 0; --i) { norm = CoinMax(norm, fabs(elements[i])); } return norm; } //----------------------------------------------------------------------------- double CoinPackedVectorBase::sum() const { return std::accumulate(getElements(), getElements() + getNumElements(), 0.0); } //############################################################################# CoinPackedVectorBase::CoinPackedVectorBase() : maxIndex_(-COIN_INT_MAX/*0*/), minIndex_(COIN_INT_MAX/*0*/), indexSetPtr_(NULL), testForDuplicateIndex_(true), testedDuplicateIndex_(false) {} //----------------------------------------------------------------------------- CoinPackedVectorBase::~CoinPackedVectorBase() { delete indexSetPtr_; } //############################################################################# //############################################################################# void CoinPackedVectorBase::findMaxMinIndices() const { if ( getNumElements()==0 ) return; // if indexSet exists then grab begin and rend to get min & max indices else if ( indexSetPtr_ != NULL ) { maxIndex_ = *indexSetPtr_->rbegin(); minIndex_ = *indexSetPtr_-> begin(); } else { // Have to scan through vector to find min and max. maxIndex_ = *(std::max_element(getIndices(), getIndices() + getNumElements())); minIndex_ = *(std::min_element(getIndices(), getIndices() + getNumElements())); } } //------------------------------------------------------------------- std::set * CoinPackedVectorBase::indexSet(const char* methodName, const char * className) const { testedDuplicateIndex_ = true; if ( indexSetPtr_ == NULL ) { // create a set of the indices indexSetPtr_ = new std::set; const int s = getNumElements(); const int * inds = getIndices(); for (int j=0; j < s; ++j) { if (!indexSetPtr_->insert(inds[j]).second) { testedDuplicateIndex_ = false; delete indexSetPtr_; indexSetPtr_ = NULL; if (methodName != NULL) { throw CoinError("Duplicate index found", methodName, className); } else { throw CoinError("Duplicate index found", "indexSet", "CoinPackedVectorBase"); } } } } return indexSetPtr_; } //----------------------------------------------------------------------------- void CoinPackedVectorBase::clearIndexSet() const { delete indexSetPtr_; indexSetPtr_ = NULL; } //----------------------------------------------------------------------------- void CoinPackedVectorBase::clearBase() const { clearIndexSet(); maxIndex_ = -COIN_INT_MAX/*0*/; minIndex_ = COIN_INT_MAX/*0*/; testedDuplicateIndex_ = false; } //#############################################################################