/// Returns the dot product of two sorted CoinPackedVector objects. /// The vectors should be sorted in ascending order of indices. inline double sortedSparseDotProduct(const CoinPackedVectorBase& op1, const CoinPackedVectorBase& op2){ int i, j, len1, len2; double acc = 0.0; const double* v1val = op1.getElements(); const double* v2val = op2.getElements(); const int* v1ind = op1.getIndices(); const int* v2ind = op2.getIndices(); len1 = op1.getNumElements(); len2 = op2.getNumElements(); i = 0; j = 0; while(i < len1 && j < len2){ if(v1ind[i] == v2ind[j]){ acc += v1val[i] * v2val[j]; i++; j++; } else if(v2ind[j] < v1ind[i]){ j++; } else{ i++; } // end if-else-elseif } // end while return acc; }
void CoinPackedVector::append(const CoinPackedVectorBase & caboose) { const int cs = caboose.getNumElements(); if (cs == 0) { return; } if (testForDuplicateIndex()) { // Just to initialize the index heap indexSet("append (1st call)", "CoinPackedVector"); } const int s = nElements_; // Make sure there is enough room for the caboose if ( capacity_ < s + cs) reserve(CoinMax(s + cs, 2 * capacity_)); const int * cind = caboose.getIndices(); const double * celem = caboose.getElements(); CoinDisjointCopyN(cind, cs, indices_ + s); CoinDisjointCopyN(celem, cs, elements_ + s); CoinIotaN(origIndices_ + s, cs, s); nElements_ += cs; if (testForDuplicateIndex()) { std::set<int>& is = *indexSet("append (2nd call)", "CoinPackedVector"); for (int i = 0; i < cs; ++i) { if (!is.insert(cind[i]).second) throw CoinError("duplicate index", "append", "CoinPackedVector"); } } }
template <class BinaryFunction> void binaryOp(CoinPackedVector& retVal, const CoinPackedVectorBase& op1, const CoinPackedVectorBase& op2, BinaryFunction bf) { retVal.clear(); const int s1 = op1.getNumElements(); const int s2 = op2.getNumElements(); /* Replaced || with &&, in response to complaint from Sven deVries, who rightly points out || is not appropriate for additive operations. && should be ok as long as binaryOp is understood not to create something from nothing. -- lh, 04.06.11 */ if (s1 == 0 && s2 == 0) return; retVal.reserve(s1+s2); const int * inds1 = op1.getIndices(); const double * elems1 = op1.getElements(); const int * inds2 = op2.getIndices(); const double * elems2 = op2.getElements(); int i; // loop once for each element in op1 for ( i=0; i<s1; ++i ) { const int index = inds1[i]; const int pos2 = op2.findIndex(index); const double val = bf(elems1[i], pos2 == -1 ? 0.0 : elems2[pos2]); // if (val != 0.0) // *THINK* : should we put in only nonzeros? retVal.insert(index, val); } // loop once for each element in operand2 for ( i=0; i<s2; ++i ) { const int index = inds2[i]; // if index exists in op1, then element was processed in prior loop if ( op1.isExistingIndex(index) ) continue; // Index does not exist in op1, so the element value must be zero const double val = bf(0.0, elems2[i]); // if (val != 0.0) // *THINK* : should we put in only nonzeros? retVal.insert(index, val); } }
CoinPackedVector::CoinPackedVector(const CoinPackedVectorBase & rhs) : CoinPackedVectorBase(), indices_(NULL), elements_(NULL), nElements_(0), origIndices_(NULL), capacity_(0) { gutsOfSetVector(rhs.getNumElements(), rhs.getIndices(), rhs.getElements(), rhs.testForDuplicateIndex(), "copy constructor from base"); }
int CoinPackedVectorBase::compare(const CoinPackedVectorBase &rhs) const { const int size = getNumElements(); int itmp = size - rhs.getNumElements(); if (itmp != 0) { return itmp; } itmp = memcmp(getIndices(), rhs.getIndices(), size * sizeof(int)); if (itmp != 0) { return itmp; } return memcmp(getElements(), rhs.getElements(), size * sizeof(double)); }
void CoinIndexedVector::append(const CoinPackedVectorBase & caboose) { const int cs = caboose.getNumElements(); const int * cind = caboose.getIndices(); const double * celem = caboose.getElements(); int maxIndex=-1; int i; for (i=0; i<cs; i++) { int indexValue = cind[i]; if (indexValue<0) throw CoinError("negative index", "append", "CoinIndexedVector"); if (maxIndex<indexValue) maxIndex = indexValue; } reserve(maxIndex+1); bool needClean=false; int numberDuplicates=0; for (i=0; i<cs; i++) { int indexValue=cind[i]; if (elements_[indexValue]) { numberDuplicates++; elements_[indexValue] += celem[i] ; if (fabs(elements_[indexValue])<COIN_INDEXED_TINY_ELEMENT) needClean=true; // need to go through again } else { if (fabs(celem[i])>=COIN_INDEXED_TINY_ELEMENT) { elements_[indexValue]=celem[i]; indices_[nElements_++]=indexValue; } } } if (needClean) { // go through again int size=nElements_; nElements_=0; for (i=0; i<size; i++) { int indexValue=indices_[i]; double value=elements_[indexValue]; if (fabs(value)>=COIN_INDEXED_TINY_ELEMENT) { indices_[nElements_++]=indexValue; } else { elements_[indexValue]=0.0; } } } if (numberDuplicates) throw CoinError("duplicate index", "append", "CoinIndexedVector"); }
//------------------------------------------------------------------- // Copy //------------------------------------------------------------------- CoinShallowPackedVector::CoinShallowPackedVector(const CoinPackedVectorBase &x) : CoinPackedVectorBase() , indices_(x.getIndices()) , elements_(x.getElements()) , nElements_(x.getNumElements()) { CoinPackedVectorBase::copyMaxMinIndex(x); try { CoinPackedVectorBase::setTestForDuplicateIndex(x.testForDuplicateIndex()); } catch (CoinError &e) { throw CoinError("duplicate index", "copy constructor from base", "CoinShallowPackedVector"); } }
bool CoinPackedVectorBase::operator==(const CoinPackedVectorBase& rhs) const { if (getNumElements() == 0 || rhs.getNumElements() == 0) { if (getNumElements() == 0 && rhs.getNumElements() == 0) return (true) ; else return (false) ; } else { return (getNumElements()==rhs.getNumElements() && std::equal(getIndices(),getIndices()+getNumElements(), rhs.getIndices()) && std::equal(getElements(),getElements()+getNumElements(), rhs.getElements())) ; } }
//@{ template <class BinaryFunction> void binaryOp(CoinPackedVector& retVal, const CoinPackedVectorBase& op1, double value, BinaryFunction bf) { retVal.clear(); const int s = op1.getNumElements(); if (s > 0) { retVal.reserve(s); const int * inds = op1.getIndices(); const double * elems = op1.getElements(); for (int i=0; i<s; ++i ) { retVal.insert(inds[i], bf(value, elems[i])); } } }