// 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 "CoinHelperFunctions.hpp" #include "OsiIndexedVector.hpp" //############################################################################# void OsiIndexedVector::clear() { int i; for (i=0;i=OSI_INDEXED_TINY_ELEMENT) { elements_[indexValue]=elems[i]; indices_[nElements_++]=indexValue; } } } //############################################################################# /** Access the i'th element of the full storage vector. */ double & OsiIndexedVector::operator[](int index) const { if ( index >= capacity_ ) throw CoinError("index >= capacity()", "[]", "OsiIndexedVector"); if ( index < 0 ) throw CoinError("index < 0" , "[]", "OsiIndexedVector"); double * where = elements_ + index; return *where; } //############################################################################# void OsiIndexedVector::setElement(int index, double element) { if ( index >= nElements_ ) throw CoinError("index >= size()", "setElement", "OsiIndexedVector"); if ( index < 0 ) throw CoinError("index < 0" , "setElement", "OsiIndexedVector"); elements_[indices_[index]] = element; } //############################################################################# void OsiIndexedVector::insert( int index, double element ) { if ( index < 0 ) throw CoinError("index < 0" , "setElement", "OsiIndexedVector"); if (index >= capacity_) reserve(index+1); if (elements_[index]) throw CoinError("Index already exists", "insert", "OsiIndexedVector"); indices_[nElements_++] = index; elements_[index] = element; // and clear index set clearIndexSet(); delete [] packedElements_; packedElements_=NULL; } //############################################################################# void OsiIndexedVector::add( int index, double element ) { if ( index < 0 ) throw CoinError("index < 0" , "setElement", "OsiIndexedVector"); if (index >= capacity_) reserve(index+1); if (elements_[index]) { element += elements_[index]; if (fabs(element)>= OSI_INDEXED_TINY_ELEMENT) { elements_[index] = element; } else { elements_[index] = 1.0e-100; } } else if (fabs(element)>= OSI_INDEXED_TINY_ELEMENT) { indices_[nElements_++] = index; elements_[index] = element; } // and clear index set clearIndexSet(); delete [] packedElements_; packedElements_=NULL; } //############################################################################# void OsiIndexedVector::stopQuickAdd( ) { // clear index set clearIndexSet(); delete [] packedElements_; packedElements_=NULL; } //############################################################################# int OsiIndexedVector::clean( double tolerance ) { int number = nElements_; int i; nElements_=0; for (i=0;i=tolerance) { indices_[nElements_++]=indexValue; } else { elements_[indexValue]=0.0; } } // and clear index set clearIndexSet(); delete [] packedElements_; packedElements_=NULL; return nElements_; } //############################################################################# // For debug check vector is clear i.e. no elements void OsiIndexedVector::checkClear() { assert(!nElements_); int i; for (i=0;i=OSI_INDEXED_TINY_ELEMENT) { elements_[indexValue]=celem[i]; indices_[nElements_++]=indexValue; } } } if (needClean) { // go through again int size=nElements_; nElements_=0; for (i=0;i=OSI_INDEXED_TINY_ELEMENT) { indices_[nElements_++]=indexValue; } else { elements_[indexValue]=0.0; } } } // and clear index set clearIndexSet(); delete [] packedElements_; packedElements_=NULL; if (numberDuplicates && testForDuplicateIndex()) throw CoinError("duplicate index", "append", "OsiIndexedVector"); } //############################################################################# void OsiIndexedVector::swap(int i, int j) { if ( i >= nElements_ ) throw CoinError("index i >= size()","swap","OsiIndexedVector"); if ( i < 0 ) throw CoinError("index i < 0" ,"swap","OsiIndexedVector"); if ( j >= nElements_ ) throw CoinError("index j >= size()","swap","OsiIndexedVector"); if ( j < 0 ) throw CoinError("index j < 0" ,"swap","OsiIndexedVector"); // Swap positions i and j of the // indices array int isave = indices_[i]; indices_[i] = indices_[j]; indices_[j] = isave; } //############################################################################# void OsiIndexedVector::truncate( int n ) { reserve(n); } //############################################################################# void OsiIndexedVector::operator+=(double value) { int i,indexValue; for (i=0;icapacity_) { // save pointers to existing data int * tempIndices = indices_; double * tempElements = elements_; // allocate new space indices_ = new int [n]; elements_ = new double [n]; // copy data to new space // and zero out part of array if (nElements_ > 0) { CoinDisjointCopyN(tempIndices, nElements_, indices_); CoinDisjointCopyN(tempElements, capacity_, elements_); CoinFillN(elements_+capacity_,n-capacity_,0.0); } else { CoinFillN(elements_,n,0.0); } capacity_ = n; // free old data delete [] tempElements; delete [] tempIndices; } // and clear index set clearIndexSet(); delete [] packedElements_; packedElements_=NULL; } //############################################################################# OsiIndexedVector::OsiIndexedVector (bool testForDuplicateIndex) : OsiPackedVectorBase(), indices_(NULL), elements_(NULL), nElements_(0), packedElements_(NULL), capacity_(0) { // This won't fail, the indexed vector is empty. There can't be duplicate // indices. OsiPackedVectorBase::setTestForDuplicateIndex(testForDuplicateIndex); } //----------------------------------------------------------------------------- OsiIndexedVector::OsiIndexedVector(int size, const int * inds, const double * elems, bool testForDuplicateIndex) : OsiPackedVectorBase(), indices_(NULL), elements_(NULL), nElements_(0), packedElements_(NULL), capacity_(0) { gutsOfSetVector(size, inds, elems, testForDuplicateIndex, "constructor for array value"); } //----------------------------------------------------------------------------- OsiIndexedVector::OsiIndexedVector(int size, const int * inds, double value, bool testForDuplicateIndex) : OsiPackedVectorBase(), indices_(NULL), elements_(NULL), nElements_(0), packedElements_(NULL), capacity_(0) { gutsOfSetConstant(size, inds, value, testForDuplicateIndex, "constructor for constant value"); } //----------------------------------------------------------------------------- OsiIndexedVector::OsiIndexedVector(int size, const double * element, bool testForDuplicateIndex) : OsiPackedVectorBase(), indices_(NULL), elements_(NULL), nElements_(0), packedElements_(NULL), capacity_(0) { setFull(size, element, testForDuplicateIndex); } //----------------------------------------------------------------------------- OsiIndexedVector::OsiIndexedVector(const OsiPackedVectorBase & rhs) : OsiPackedVectorBase(), indices_(NULL), elements_(NULL), nElements_(0), packedElements_(NULL), capacity_(0) { gutsOfSetVector(rhs.getNumElements(), rhs.getIndices(), rhs.getElements(), rhs.testForDuplicateIndex(), "copy constructor from base"); } //----------------------------------------------------------------------------- OsiIndexedVector::OsiIndexedVector(const OsiIndexedVector & rhs) : OsiPackedVectorBase(), indices_(NULL), elements_(NULL), nElements_(0), packedElements_(NULL), capacity_(0) { gutsOfSetVector(rhs.capacity_,rhs.nElements_, rhs.indices_, rhs.elements_, rhs.testForDuplicateIndex(), "copy constructor"); } //----------------------------------------------------------------------------- OsiIndexedVector::~OsiIndexedVector () { delete [] indices_; delete [] packedElements_; delete [] elements_; } //############################################################################# // Get element values const double * OsiIndexedVector::getElements() const { if (!packedElements_) packedElements_ = new double[nElements_]; int i; for (i=0;i=OSI_INDEXED_TINY_ELEMENT) { newOne.elements_[indexValue]=value; newOne.indices_[nElements++]=indexValue; } } else { value += oldValue; newOne.elements_[indexValue]=value; if (fabs(value)=OSI_INDEXED_TINY_ELEMENT) { newOne.indices_[nElements_++]=indexValue; } else { newOne.elements_[indexValue]=0.0; } } } return newOne; } /// Return the difference of two indexed vectors OsiIndexedVector OsiIndexedVector::operator-( const OsiIndexedVector& op2) { int i; int nElements=nElements_; int capacity = CoinMax(capacity_,op2.capacity_); OsiIndexedVector newOne(*this); newOne.reserve(capacity); bool needClean=false; // new one now can hold everything so just modify old and add new for (i=0;i=OSI_INDEXED_TINY_ELEMENT) { newOne.elements_[indexValue]=-value; newOne.indices_[nElements++]=indexValue; } } else { value = oldValue-value; newOne.elements_[indexValue]=value; if (fabs(value)=OSI_INDEXED_TINY_ELEMENT) { newOne.indices_[nElements_++]=indexValue; } else { newOne.elements_[indexValue]=0.0; } } } return newOne; } /// Return the element-wise product of two indexed vectors OsiIndexedVector OsiIndexedVector::operator*( const OsiIndexedVector& op2) { int i; int nElements=nElements_; int capacity = CoinMax(capacity_,op2.capacity_); OsiIndexedVector newOne(*this); newOne.reserve(capacity); bool needClean=false; // new one now can hold everything so just modify old and add new for (i=0;i=OSI_INDEXED_TINY_ELEMENT) { newOne.indices_[nElements_++]=indexValue; } else { newOne.elements_[indexValue]=0.0; } } } return newOne; } /// Return the element-wise ratio of two indexed vectors OsiIndexedVector OsiIndexedVector::operator/ (const OsiIndexedVector& op2) { // I am treating 0.0/0.0 as 0.0 int i; int nElements=nElements_; int capacity = CoinMax(capacity_,op2.capacity_); OsiIndexedVector newOne(*this); newOne.reserve(capacity); bool needClean=false; // new one now can hold everything so just modify old and add new for (i=0;i=OSI_INDEXED_TINY_ELEMENT) { newOne.indices_[nElements_++]=indexValue; } else { newOne.elements_[indexValue]=0.0; } } } return newOne; } //############################################################################# void OsiIndexedVector::sortDecrIndex() { double * elements = getElements(); CoinSort_2(indices_, indices_ + nElements_, elements, CoinFirstGreater_2()); } void OsiIndexedVector::sortIncrElement() { double * elements = getElements(); CoinSort_2(elements, elements + nElements_, indices_, CoinFirstLess_2()); } void OsiIndexedVector::sortDecrElement() { double * elements = getElements(); CoinSort_2(elements, elements + nElements_, indices_, CoinFirstGreater_2()); } //############################################################################# void OsiIndexedVector::gutsOfSetVector(int size, const int * inds, const double * elems, bool testForDuplicateIndex, const char * method) { // we are going to do a faster test for duplicates so test base class when empty OsiPackedVectorBase::setTestForDuplicateIndex(testForDuplicateIndex); // and clear index set clearIndexSet(); if (size<0) throw CoinError("negative number of indices", method, "OsiIndexedVector"); // find largest int i; int maxIndex=-1; for (i=0;i=OSI_INDEXED_TINY_ELEMENT) { indices_[nElements_++]=indexValue; elements_[indexValue]=elems[i]; } } else { numberDuplicates++; elements_[indexValue] += elems[i] ; if (fabs(elements_[indexValue])=OSI_INDEXED_TINY_ELEMENT) { indices_[nElements_++]=indexValue; } else { elements_[indexValue]=0.0; } } } if (numberDuplicates && testForDuplicateIndex) throw CoinError("duplicate index", "setVector", "OsiIndexedVector"); } //############################################################################# void OsiIndexedVector::gutsOfSetVector(int size, int numberIndices, const int * inds, const double * elems, bool testForDuplicateIndex, const char * method) { // we are not going to test for duplicates so test base class when empty OsiPackedVectorBase::setTestForDuplicateIndex(testForDuplicateIndex); // and clear index set clearIndexSet(); int i; reserve(size); if (numberIndices<0) throw CoinError("negative number of indices", method, "OsiIndexedVector"); nElements_ = 0; // elements_ array is all zero bool needClean=false; int numberDuplicates=0; for (i=0;i=size) throw CoinError("too large an index", method, "OsiIndexedVector"); if (elements_[indexValue]) { numberDuplicates++; elements_[indexValue] += elems[indexValue] ; if (fabs(elements_[indexValue])=OSI_INDEXED_TINY_ELEMENT) { elements_[indexValue]=elems[indexValue]; indices_[nElements_++]=indexValue; } } } if (needClean) { // go through again size=nElements_; nElements_=0; for (i=0;i=OSI_INDEXED_TINY_ELEMENT) { indices_[nElements_++]=indexValue; } else { elements_[indexValue]=0.0; } } } if (numberDuplicates && testForDuplicateIndex) throw CoinError("duplicate index", "setVector", "OsiIndexedVector"); } //----------------------------------------------------------------------------- void OsiIndexedVector::gutsOfSetConstant(int size, const int * inds, double value, bool testForDuplicateIndex, const char * method) { // we are going to do a faster test for duplicates so test base class // when empty OsiPackedVectorBase::setTestForDuplicateIndex(testForDuplicateIndex); // and clear index set clearIndexSet(); if (size<0) throw CoinError("negative number of indices", method, "OsiIndexedVector"); // find largest int i; int maxIndex=-1; for (i=0;i=OSI_INDEXED_TINY_ELEMENT) { elements_[indexValue] += value; indices_[nElements_++]=indexValue; } } else { numberDuplicates++; elements_[indexValue] += value ; if (fabs(elements_[indexValue])=OSI_INDEXED_TINY_ELEMENT) { indices_[nElements_++]=indexValue; } else { elements_[indexValue]=0.0; } } } if (numberDuplicates && testForDuplicateIndex) throw CoinError("duplicate index", "setConstant", "OsiIndexedVector"); } //#############################################################################