Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | Related Pages

CoinIndexedVector.cpp

00001 // Copyright (C) 2000, International Business Machines
00002 // Corporation and others.  All Rights Reserved.
00003 #if defined(_MSC_VER)
00004 // Turn off compiler warning about long names
00005 #  pragma warning(disable:4786)
00006 #endif
00007 
00008 #include <cassert>
00009 
00010 #include "CoinHelperFunctions.hpp"
00011 #include "CoinIndexedVector.hpp"
00012 //#############################################################################
00013 
00014 void
00015 CoinIndexedVector::clear()
00016 {
00017   if (!packedMode_) {
00018     if (3*nElements_<capacity_) {
00019       int i=0;
00020       if ((nElements_&1)!=0) {
00021         elements_[indices_[0]]=0.0;
00022         i=1;
00023       }
00024       for (;i<nElements_;i+=2) {
00025         int i0 = indices_[i];
00026         int i1 = indices_[i+1];
00027         elements_[i0]=0.0;
00028         elements_[i1]=0.0;
00029       }
00030     } else {
00031       memset(elements_,0,capacity_*sizeof(double));
00032     }
00033   } else {
00034     memset(elements_,0,nElements_*sizeof(double));
00035   }
00036   nElements_ = 0;
00037   packedMode_=false;
00038 }
00039 
00040 //#############################################################################
00041 
00042 void
00043 CoinIndexedVector::empty()
00044 {
00045   delete [] indices_;
00046   indices_=NULL;
00047   if (elements_)
00048     delete [] (elements_-offset_);
00049   elements_=NULL;
00050   nElements_ = 0;
00051   capacity_=0;
00052   packedMode_=false;
00053 }
00054 
00055 //#############################################################################
00056 
00057 CoinIndexedVector &
00058 CoinIndexedVector::operator=(const CoinIndexedVector & rhs)
00059 {
00060   if (this != &rhs) {
00061     clear();
00062     packedMode_=rhs.packedMode_;
00063     gutsOfSetVector(rhs.capacity_,rhs.nElements_, rhs.indices_, rhs.elements_);
00064   }
00065   return *this;
00066 }
00067 
00068 //#############################################################################
00069 
00070 CoinIndexedVector &
00071 CoinIndexedVector::operator=(const CoinPackedVectorBase & rhs)
00072 {
00073   clear();
00074   gutsOfSetVector(rhs.getNumElements(), 
00075                             rhs.getIndices(), rhs.getElements());
00076   return *this;
00077 }
00078 
00079 //#############################################################################
00080 
00081 void
00082 CoinIndexedVector::borrowVector(int size, int numberIndices, int* inds, double* elems)
00083 {
00084   empty();
00085   capacity_=size;
00086   nElements_ = numberIndices;
00087   indices_ = inds;  
00088   elements_ = elems;
00089   
00090   // whole point about borrowvector is that it is lightweight so no testing is done
00091 }
00092 
00093 //#############################################################################
00094 
00095 void
00096 CoinIndexedVector::returnVector()
00097 {
00098   indices_=NULL;
00099   elements_=NULL;
00100   nElements_ = 0;
00101   capacity_=0;
00102   packedMode_=false;
00103 }
00104 
00105 //#############################################################################
00106 
00107 void
00108 CoinIndexedVector::setVector(int size, const int * inds, const double * elems)
00109 {
00110   clear();
00111   gutsOfSetVector(size, inds, elems);
00112 }
00113 //#############################################################################
00114 
00115 
00116 void 
00117 CoinIndexedVector::setVector(int size, int numberIndices, const int * inds, const double * elems)
00118 {
00119   clear();
00120   gutsOfSetVector(size, numberIndices, inds, elems);
00121 }
00122 //#############################################################################
00123 
00124 void
00125 CoinIndexedVector::setConstant(int size, const int * inds, double value)
00126 {
00127   clear();
00128   gutsOfSetConstant(size, inds, value);
00129 }
00130 
00131 //#############################################################################
00132 
00133 void
00134 CoinIndexedVector::setFull(int size, const double * elems)
00135 {
00136   // Clear out any values presently stored
00137   clear();
00138   
00139   if (size<0)
00140     throw CoinError("negative number of indices", "setFull", "CoinIndexedVector");
00141   
00142   reserve(size);
00143   nElements_ = 0;
00144   // elements_ array is all zero
00145   int i;
00146   for (i=0;i<size;i++) {
00147     int indexValue=i;
00148     if (fabs(elems[i])>=COIN_INDEXED_TINY_ELEMENT) {
00149       elements_[indexValue]=elems[i];
00150       indices_[nElements_++]=indexValue;
00151     }
00152   }
00153 }
00154 //#############################################################################
00155 
00157 double &
00158 CoinIndexedVector::operator[](int index) const
00159 {
00160   if ( index >= capacity_ ) 
00161     throw CoinError("index >= capacity()", "[]", "CoinIndexedVector");
00162   if ( index < 0 ) 
00163     throw CoinError("index < 0" , "[]", "CoinIndexedVector");
00164   double * where = elements_ + index;
00165   return *where;
00166   
00167 }
00168 //#############################################################################
00169 
00170 void
00171 CoinIndexedVector::setElement(int index, double element)
00172 {
00173   if ( index >= nElements_ ) 
00174     throw CoinError("index >= size()", "setElement", "CoinIndexedVector");
00175   if ( index < 0 ) 
00176     throw CoinError("index < 0" , "setElement", "CoinIndexedVector");
00177   elements_[indices_[index]] = element;
00178 }
00179 
00180 //#############################################################################
00181 
00182 void
00183 CoinIndexedVector::insert( int index, double element )
00184 {
00185   if ( index < 0 ) 
00186     throw CoinError("index < 0" , "setElement", "CoinIndexedVector");
00187   if (index >= capacity_)
00188     reserve(index+1);
00189   if (elements_[index])
00190     throw CoinError("Index already exists", "insert", "CoinIndexedVector");
00191   indices_[nElements_++] = index;
00192   elements_[index] = element;
00193 }
00194 
00195 //#############################################################################
00196 
00197 void
00198 CoinIndexedVector::add( int index, double element )
00199 {
00200   if ( index < 0 ) 
00201     throw CoinError("index < 0" , "setElement", "CoinIndexedVector");
00202   if (index >= capacity_)
00203     reserve(index+1);
00204   if (elements_[index]) {
00205     element += elements_[index];
00206     if (fabs(element)>= COIN_INDEXED_TINY_ELEMENT) {
00207       elements_[index] = element;
00208     } else {
00209       elements_[index] = 1.0e-100;
00210     }
00211   } else if (fabs(element)>= COIN_INDEXED_TINY_ELEMENT) {
00212     indices_[nElements_++] = index;
00213     elements_[index] = element;
00214    }
00215 }
00216 
00217 //#############################################################################
00218 
00219 int
00220 CoinIndexedVector::clean( double tolerance )
00221 {
00222   int number = nElements_;
00223   int i;
00224   nElements_=0;
00225   assert(!packedMode_);
00226   for (i=0;i<number;i++) {
00227     int indexValue = indices_[i];
00228     if (fabs(elements_[indexValue])>=tolerance) {
00229       indices_[nElements_++]=indexValue;
00230     } else {
00231       elements_[indexValue]=0.0;
00232     }
00233   }
00234   return nElements_;
00235 }
00236 
00237 //#############################################################################
00238 // For debug check vector is clear i.e. no elements
00239 void CoinIndexedVector::checkClear()
00240 {
00241   assert(!nElements_);
00242   assert(!packedMode_);
00243   int i;
00244   for (i=0;i<capacity_;i++) {
00245     assert(!elements_[i]);
00246   }
00247 #ifndef NDEBUG
00248   // check mark array zeroed
00249   char * mark = (char *) (indices_+capacity_);
00250   for (i=0;i<capacity_;i++) {
00251     assert(!mark[i]);
00252   }
00253 #endif
00254 }
00255 // For debug check vector is clean i.e. elements match indices
00256 void CoinIndexedVector::checkClean()
00257 {
00258   int i;
00259   if (packedMode_) {
00260     for (i=0;i<nElements_;i++) 
00261       assert(elements_[i]);
00262     for (;i<capacity_;i++) 
00263       assert(!elements_[i]);
00264   } else {
00265     double * copy = new double[capacity_];
00266     CoinMemcpyN(elements_,capacity_,copy);
00267     for (i=0;i<nElements_;i++) {
00268       int indexValue = indices_[i];
00269       copy[indexValue]=0.0;
00270     }
00271     for (i=0;i<capacity_;i++) 
00272       assert(!copy[i]);
00273     delete [] copy;
00274   }
00275 #ifndef NDEBUG
00276   // check mark array zeroed
00277   char * mark = (char *) (indices_+capacity_);
00278   for (i=0;i<capacity_;i++) {
00279     assert(!mark[i]);
00280   }
00281 #endif
00282 }
00283 
00284 //#############################################################################
00285 
00286 void
00287 CoinIndexedVector::append(const CoinPackedVectorBase & caboose) 
00288 {
00289   const int cs = caboose.getNumElements();
00290   
00291   const int * cind = caboose.getIndices();
00292   const double * celem = caboose.getElements();
00293   int maxIndex=-1;
00294   int i;
00295   for (i=0;i<cs;i++) {
00296     int indexValue = cind[i];
00297     if (indexValue<0)
00298       throw CoinError("negative index", "append", "CoinIndexedVector");
00299     if (maxIndex<indexValue)
00300       maxIndex = indexValue;
00301   }
00302   reserve(maxIndex+1);
00303   bool needClean=false;
00304   int numberDuplicates=0;
00305   for (i=0;i<cs;i++) {
00306     int indexValue=cind[i];
00307     if (elements_[indexValue]) {
00308       numberDuplicates++;
00309       elements_[indexValue] += celem[i] ;
00310       if (fabs(elements_[indexValue])<COIN_INDEXED_TINY_ELEMENT) 
00311         needClean=true; // need to go through again
00312     } else {
00313       if (fabs(celem[i])>=COIN_INDEXED_TINY_ELEMENT) {
00314         elements_[indexValue]=celem[i];
00315         indices_[nElements_++]=indexValue;
00316       }
00317     }
00318   }
00319   if (needClean) {
00320     // go through again
00321     int size=nElements_;
00322     nElements_=0;
00323     for (i=0;i<size;i++) {
00324       int indexValue=indices_[i];
00325       double value=elements_[indexValue];
00326       if (fabs(value)>=COIN_INDEXED_TINY_ELEMENT) {
00327         indices_[nElements_++]=indexValue;
00328       } else {
00329         elements_[indexValue]=0.0;
00330       }
00331     }
00332   }
00333   if (numberDuplicates)
00334     throw CoinError("duplicate index", "append", "CoinIndexedVector");
00335 }
00336 
00337 //#############################################################################
00338 
00339 void
00340 CoinIndexedVector::swap(int i, int j) 
00341 {
00342   if ( i >= nElements_ ) 
00343     throw CoinError("index i >= size()","swap","CoinIndexedVector");
00344   if ( i < 0 ) 
00345     throw CoinError("index i < 0" ,"swap","CoinIndexedVector");
00346   if ( j >= nElements_ ) 
00347     throw CoinError("index j >= size()","swap","CoinIndexedVector");
00348   if ( j < 0 ) 
00349     throw CoinError("index j < 0" ,"swap","CoinIndexedVector");
00350   
00351   // Swap positions i and j of the
00352   // indices array
00353   
00354   int isave = indices_[i];
00355   indices_[i] = indices_[j];
00356   indices_[j] = isave;
00357 }
00358 
00359 //#############################################################################
00360 
00361 void
00362 CoinIndexedVector::truncate( int n ) 
00363 {
00364   reserve(n);
00365 }
00366 
00367 //#############################################################################
00368 
00369 void
00370 CoinIndexedVector::operator+=(double value) 
00371 {
00372   int i,indexValue;
00373   for (i=0;i<nElements_;i++) {
00374     indexValue = indices_[i];
00375     elements_[indexValue] += value;
00376   }
00377 }
00378 
00379 //-----------------------------------------------------------------------------
00380 
00381 void
00382 CoinIndexedVector::operator-=(double value) 
00383 {
00384   int i,indexValue;
00385   for (i=0;i<nElements_;i++) {
00386     indexValue = indices_[i];
00387     elements_[indexValue] -= value;
00388   }
00389 }
00390 
00391 //-----------------------------------------------------------------------------
00392 
00393 void
00394 CoinIndexedVector::operator*=(double value) 
00395 {
00396   int i,indexValue;
00397   for (i=0;i<nElements_;i++) {
00398     indexValue = indices_[i];
00399     elements_[indexValue] *= value;
00400   }
00401 }
00402 
00403 //-----------------------------------------------------------------------------
00404 
00405 void
00406 CoinIndexedVector::operator/=(double value) 
00407 {
00408   int i,indexValue;
00409   for (i=0;i<nElements_;i++) {
00410     indexValue = indices_[i];
00411     elements_[indexValue] /= value;
00412   }
00413 }
00414 //#############################################################################
00415 
00416 void
00417 CoinIndexedVector::reserve(int n) 
00418 {
00419   int i;
00420   // don't make allocated space smaller but do take off values
00421   if ( n < capacity_ ) {
00422     if (n<0) 
00423       throw CoinError("negative capacity", "reserve", "CoinIndexedVector");
00424     
00425     int nNew=0;
00426     for (i=0;i<nElements_;i++) {
00427       int indexValue=indices_[i];
00428       if (indexValue<n) {
00429         indices_[nNew++]=indexValue;
00430       } else {
00431         elements_[indexValue]=0.0;
00432       }
00433     }
00434     nElements_=nNew;
00435   } else if (n>capacity_) {
00436     
00437     // save pointers to existing data
00438     int * tempIndices = indices_;
00439     double * tempElements = elements_;
00440     double * delTemp = elements_-offset_;
00441     
00442     // allocate new space
00443     int nPlus;
00444     if (sizeof(int)==4*sizeof(char))
00445       nPlus=(n+3)>>2;
00446     else
00447       nPlus=(n+7)>>4;
00448     indices_ = new int [n+nPlus];
00449     memset(indices_+n,0,nPlus*sizeof(int));
00450     // align on 64 byte boundary
00451     double * temp = new double [n+7];
00452     offset_ = 0;
00453 #ifndef __64BIT__
00454     int xx = (int) temp;
00455     int iBottom = xx & 63;
00456     if (iBottom)
00457       offset_ = (64-iBottom)>>3;
00458 #else
00459     long xx = (long) temp;
00460     long iBottom = xx & 63;
00461     if (iBottom)
00462       offset_ = (64-iBottom)>>3;
00463 #endif
00464     elements_ = temp + offset_;;
00465     
00466     // copy data to new space
00467     // and zero out part of array
00468     if (nElements_ > 0) {
00469       CoinMemcpyN(tempIndices, nElements_, indices_);
00470       CoinMemcpyN(tempElements, capacity_, elements_);
00471       CoinZeroN(elements_+capacity_,n-capacity_);
00472     } else {
00473       CoinZeroN(elements_,n);
00474     }
00475     capacity_ = n;
00476     
00477     // free old data
00478     if (tempElements)
00479       delete [] delTemp;
00480     delete [] tempIndices;
00481   }
00482 }
00483 
00484 //#############################################################################
00485 
00486 CoinIndexedVector::CoinIndexedVector () :
00487 indices_(NULL),
00488 elements_(NULL),
00489 nElements_(0),
00490 capacity_(0),
00491 offset_(0),
00492 packedMode_(false)
00493 {
00494 }
00495 
00496 //-----------------------------------------------------------------------------
00497 
00498 CoinIndexedVector::CoinIndexedVector(int size,
00499                                      const int * inds, const double * elems)  :
00500   indices_(NULL),
00501   elements_(NULL),
00502   nElements_(0),
00503   capacity_(0),
00504   offset_(0),
00505   packedMode_(false)
00506 {
00507   gutsOfSetVector(size, inds, elems);
00508 }
00509 
00510 //-----------------------------------------------------------------------------
00511 
00512 CoinIndexedVector::CoinIndexedVector(int size,
00513   const int * inds, double value) :
00514 indices_(NULL),
00515 elements_(NULL),
00516 nElements_(0),
00517 capacity_(0),
00518 offset_(0),
00519 packedMode_(false)
00520 {
00521 gutsOfSetConstant(size, inds, value);
00522 }
00523 
00524 //-----------------------------------------------------------------------------
00525 
00526 CoinIndexedVector::CoinIndexedVector(int size, const double * element) :
00527 indices_(NULL),
00528 elements_(NULL),
00529 nElements_(0),
00530 capacity_(0),
00531 offset_(0),
00532 packedMode_(false)
00533 {
00534   setFull(size, element);
00535 }
00536 
00537 //-----------------------------------------------------------------------------
00538 
00539 CoinIndexedVector::CoinIndexedVector(const CoinPackedVectorBase & rhs) :
00540 indices_(NULL),
00541 elements_(NULL),
00542 nElements_(0),
00543 capacity_(0),
00544 offset_(0),
00545 packedMode_(false)
00546 {  
00547   gutsOfSetVector(rhs.getNumElements(), 
00548                             rhs.getIndices(), rhs.getElements());
00549 }
00550 
00551 //-----------------------------------------------------------------------------
00552 
00553 CoinIndexedVector::CoinIndexedVector(const CoinIndexedVector & rhs) :
00554 indices_(NULL),
00555 elements_(NULL),
00556 nElements_(0),
00557 capacity_(0),
00558 offset_(0),
00559 packedMode_(false)
00560 {  
00561   gutsOfSetVector(rhs.capacity_,rhs.nElements_, rhs.indices_, rhs.elements_);
00562 }
00563 
00564 //-----------------------------------------------------------------------------
00565 
00566 CoinIndexedVector::CoinIndexedVector(const CoinIndexedVector * rhs) :
00567 indices_(NULL),
00568 elements_(NULL),
00569 nElements_(0),
00570 capacity_(0),
00571 offset_(0),
00572 packedMode_(false)
00573 {  
00574   gutsOfSetVector(rhs->capacity_,rhs->nElements_, rhs->indices_, rhs->elements_);
00575 }
00576 
00577 //-----------------------------------------------------------------------------
00578 
00579 CoinIndexedVector::~CoinIndexedVector ()
00580 {
00581   delete [] indices_;
00582   if (elements_)
00583     delete [] (elements_-offset_);
00584 }
00585 //#############################################################################
00586 //#############################################################################
00587 
00589 CoinIndexedVector 
00590 CoinIndexedVector::operator+(
00591                             const CoinIndexedVector& op2)
00592 {
00593   int i;
00594   int nElements=nElements_;
00595   int capacity = CoinMax(capacity_,op2.capacity_);
00596   CoinIndexedVector newOne(*this);
00597   newOne.reserve(capacity);
00598   bool needClean=false;
00599   // new one now can hold everything so just modify old and add new
00600   for (i=0;i<op2.nElements_;i++) {
00601     int indexValue=op2.indices_[i];
00602     double value=op2.elements_[indexValue];
00603     double oldValue=elements_[indexValue];
00604     if (!oldValue) {
00605       if (fabs(value)>=COIN_INDEXED_TINY_ELEMENT) {
00606         newOne.elements_[indexValue]=value;
00607         newOne.indices_[nElements++]=indexValue;
00608       }
00609     } else {
00610       value += oldValue;
00611       newOne.elements_[indexValue]=value;
00612       if (fabs(value)<COIN_INDEXED_TINY_ELEMENT) {
00613         needClean=true;
00614       }
00615     }
00616   }
00617   newOne.nElements_=nElements;
00618   if (needClean) {
00619     // go through again
00620     nElements_=0;
00621     for (i=0;i<nElements;i++) {
00622       int indexValue=newOne.indices_[i];
00623       double value=newOne.elements_[indexValue];
00624       if (fabs(value)>=COIN_INDEXED_TINY_ELEMENT) {
00625         newOne.indices_[nElements_++]=indexValue;
00626       } else {
00627         newOne.elements_[indexValue]=0.0;
00628       }
00629     }
00630   }
00631   return newOne;
00632 }
00633 
00635 CoinIndexedVector 
00636 CoinIndexedVector::operator-(
00637                             const CoinIndexedVector& op2)
00638 {
00639   int i;
00640   int nElements=nElements_;
00641   int capacity = CoinMax(capacity_,op2.capacity_);
00642   CoinIndexedVector newOne(*this);
00643   newOne.reserve(capacity);
00644   bool needClean=false;
00645   // new one now can hold everything so just modify old and add new
00646   for (i=0;i<op2.nElements_;i++) {
00647     int indexValue=op2.indices_[i];
00648     double value=op2.elements_[indexValue];
00649     double oldValue=elements_[indexValue];
00650     if (!oldValue) {
00651       if (fabs(value)>=COIN_INDEXED_TINY_ELEMENT) {
00652         newOne.elements_[indexValue]=-value;
00653         newOne.indices_[nElements++]=indexValue;
00654       }
00655     } else {
00656       value = oldValue-value;
00657       newOne.elements_[indexValue]=value;
00658       if (fabs(value)<COIN_INDEXED_TINY_ELEMENT) {
00659         needClean=true;
00660       }
00661     }
00662   }
00663   newOne.nElements_=nElements;
00664   if (needClean) {
00665     // go through again
00666     nElements_=0;
00667     for (i=0;i<nElements;i++) {
00668       int indexValue=newOne.indices_[i];
00669       double value=newOne.elements_[indexValue];
00670       if (fabs(value)>=COIN_INDEXED_TINY_ELEMENT) {
00671         newOne.indices_[nElements_++]=indexValue;
00672       } else {
00673         newOne.elements_[indexValue]=0.0;
00674       }
00675     }
00676   }
00677   return newOne;
00678 }
00679 
00681 CoinIndexedVector 
00682 CoinIndexedVector::operator*(
00683                             const CoinIndexedVector& op2)
00684 {
00685   int i;
00686   int nElements=nElements_;
00687   int capacity = CoinMax(capacity_,op2.capacity_);
00688   CoinIndexedVector newOne(*this);
00689   newOne.reserve(capacity);
00690   bool needClean=false;
00691   // new one now can hold everything so just modify old and add new
00692   for (i=0;i<op2.nElements_;i++) {
00693     int indexValue=op2.indices_[i];
00694     double value=op2.elements_[indexValue];
00695     double oldValue=elements_[indexValue];
00696     if (oldValue) {
00697       value *= oldValue;
00698       newOne.elements_[indexValue]=value;
00699       if (fabs(value)<COIN_INDEXED_TINY_ELEMENT) {
00700         needClean=true;
00701       }
00702     }
00703   }
00704 
00705 // I don't see why this is necessary. Multiplication cannot add new values.
00706 //newOne.nElements_=nElements;
00707   assert(newOne.nElements_ == nElements) ;
00708 
00709   if (needClean) {
00710     // go through again
00711     nElements_=0;
00712     for (i=0;i<nElements;i++) {
00713       int indexValue=newOne.indices_[i];
00714       double value=newOne.elements_[indexValue];
00715       if (fabs(value)>=COIN_INDEXED_TINY_ELEMENT) {
00716         newOne.indices_[nElements_++]=indexValue;
00717       } else {
00718         newOne.elements_[indexValue]=0.0;
00719       }
00720     }
00721   }
00722   return newOne;
00723 }
00724 
00726 CoinIndexedVector 
00727 CoinIndexedVector::operator/ (const CoinIndexedVector& op2) 
00728 {
00729   // I am treating 0.0/0.0 as 0.0
00730   int i;
00731   int nElements=nElements_;
00732   int capacity = CoinMax(capacity_,op2.capacity_);
00733   CoinIndexedVector newOne(*this);
00734   newOne.reserve(capacity);
00735   bool needClean=false;
00736   // new one now can hold everything so just modify old and add new
00737   for (i=0;i<op2.nElements_;i++) {
00738     int indexValue=op2.indices_[i];
00739     double value=op2.elements_[indexValue];
00740     double oldValue=elements_[indexValue];
00741     if (oldValue) {
00742       if (!value)
00743         throw CoinError("zero divisor", "/", "CoinIndexedVector");
00744       value = oldValue/value;
00745       newOne.elements_[indexValue]=value;
00746       if (fabs(value)<COIN_INDEXED_TINY_ELEMENT) {
00747         needClean=true;
00748       }
00749     }
00750   }
00751 
00752 // I don't see why this is necessary. Division can only modify existing.
00753 //newOne.nElements_=nElements;
00754   assert(newOne.nElements_ == nElements) ;
00755 
00756   if (needClean) {
00757     // go through again
00758     nElements_=0;
00759     for (i=0;i<nElements;i++) {
00760       int indexValue=newOne.indices_[i];
00761       double value=newOne.elements_[indexValue];
00762       if (fabs(value)>=COIN_INDEXED_TINY_ELEMENT) {
00763         newOne.indices_[nElements_++]=indexValue;
00764       } else {
00765         newOne.elements_[indexValue]=0.0;
00766       }
00767     }
00768   }
00769   return newOne;
00770 }
00771 //#############################################################################
00772 void 
00773 CoinIndexedVector::sortDecrIndex()
00774 { 
00775   // Should replace with std sort
00776   double * elements = new double [nElements_];
00777   memset (elements,0,nElements_*sizeof(double));
00778   CoinSort_2(indices_, indices_ + nElements_, elements,
00779              CoinFirstGreater_2<int, double>());
00780   delete [] elements;
00781 }
00782 
00783 void 
00784 CoinIndexedVector::sortIncrElement()
00785 { 
00786   double * elements = new double [nElements_];
00787   int i;
00788   for (i=0;i<nElements_;i++) 
00789     elements[i] = elements_[indices_[i]];
00790   CoinSort_2(elements, elements + nElements_, indices_,
00791     CoinFirstLess_2<double, int>());
00792   delete [] elements;
00793 }
00794 
00795 void 
00796 CoinIndexedVector::sortDecrElement()
00797 { 
00798   double * elements = new double [nElements_];
00799   int i;
00800   for (i=0;i<nElements_;i++) 
00801     elements[i] = elements_[indices_[i]];
00802   CoinSort_2(elements, elements + nElements_, indices_,
00803     CoinFirstGreater_2<double, int>());
00804   delete [] elements;
00805 }
00806 //#############################################################################
00807 
00808 void
00809 CoinIndexedVector::gutsOfSetVector(int size,
00810                                    const int * inds, const double * elems)
00811 {
00812   if (size<0)
00813     throw CoinError("negative number of indices", "setVector", "CoinIndexedVector");
00814   assert(!packedMode_);  
00815   // find largest
00816   int i;
00817   int maxIndex=-1;
00818   for (i=0;i<size;i++) {
00819     int indexValue = inds[i];
00820     if (indexValue<0)
00821       throw CoinError("negative index", "setVector", "CoinIndexedVector");
00822     if (maxIndex<indexValue)
00823       maxIndex = indexValue;
00824   }
00825   reserve(maxIndex+1);
00826   nElements_ = 0;
00827   // elements_ array is all zero
00828   bool needClean=false;
00829   int numberDuplicates=0;
00830   for (i=0;i<size;i++) {
00831     int indexValue=inds[i];
00832     if (elements_[indexValue] == 0)
00833     {
00834       if (fabs(elems[i])>=COIN_INDEXED_TINY_ELEMENT) {
00835         indices_[nElements_++]=indexValue;
00836         elements_[indexValue]=elems[i];
00837       }
00838     }
00839     else
00840     {
00841       numberDuplicates++;
00842       elements_[indexValue] += elems[i] ;
00843       if (fabs(elements_[indexValue])<COIN_INDEXED_TINY_ELEMENT) 
00844         needClean=true; // need to go through again
00845     }
00846   }
00847   if (needClean) {
00848     // go through again
00849     size=nElements_;
00850     nElements_=0;
00851     for (i=0;i<size;i++) {
00852       int indexValue=indices_[i];
00853       double value=elements_[indexValue];
00854       if (fabs(value)>=COIN_INDEXED_TINY_ELEMENT) {
00855         indices_[nElements_++]=indexValue;
00856       } else {
00857         elements_[indexValue]=0.0;
00858       }
00859     }
00860   }
00861   if (numberDuplicates)
00862     throw CoinError("duplicate index", "setVector", "CoinIndexedVector");
00863 }
00864 
00865 //#############################################################################
00866 
00867 void
00868 CoinIndexedVector::gutsOfSetVector(int size, int numberIndices, 
00869                                    const int * inds, const double * elems)
00870 {
00871   assert(!packedMode_);  
00872   
00873   int i;
00874   reserve(size);
00875   if (numberIndices<0)
00876     throw CoinError("negative number of indices", "setVector", "CoinIndexedVector");
00877   nElements_ = 0;
00878   // elements_ array is all zero
00879   bool needClean=false;
00880   int numberDuplicates=0;
00881   for (i=0;i<numberIndices;i++) {
00882     int indexValue=inds[i];
00883     if (indexValue<0) 
00884       throw CoinError("negative index", "setVector", "CoinIndexedVector");
00885     else if (indexValue>=size) 
00886       throw CoinError("too large an index", "setVector", "CoinIndexedVector");
00887     if (elements_[indexValue]) {
00888       numberDuplicates++;
00889       elements_[indexValue] += elems[indexValue] ;
00890       if (fabs(elements_[indexValue])<COIN_INDEXED_TINY_ELEMENT) 
00891         needClean=true; // need to go through again
00892     } else {
00893       if (fabs(elems[indexValue])>=COIN_INDEXED_TINY_ELEMENT) {
00894         elements_[indexValue]=elems[indexValue];
00895         indices_[nElements_++]=indexValue;
00896       }
00897     }
00898   }
00899   if (needClean) {
00900     // go through again
00901     size=nElements_;
00902     nElements_=0;
00903     for (i=0;i<size;i++) {
00904       int indexValue=indices_[i];
00905       double value=elements_[indexValue];
00906       if (fabs(value)>=COIN_INDEXED_TINY_ELEMENT) {
00907         indices_[nElements_++]=indexValue;
00908       } else {
00909         elements_[indexValue]=0.0;
00910       }
00911     }
00912   }
00913   if (numberDuplicates)
00914     throw CoinError("duplicate index", "setVector", "CoinIndexedVector");
00915 }
00916 
00917 //-----------------------------------------------------------------------------
00918 
00919 void
00920 CoinIndexedVector::gutsOfSetConstant(int size,
00921                                      const int * inds, double value)
00922 {
00923 
00924   assert(!packedMode_);  
00925   if (size<0)
00926     throw CoinError("negative number of indices", "setConstant", "CoinIndexedVector");
00927   
00928   // find largest
00929   int i;
00930   int maxIndex=-1;
00931   for (i=0;i<size;i++) {
00932     int indexValue = inds[i];
00933     if (indexValue<0)
00934       throw CoinError("negative index", "setConstant", "CoinIndexedVector");
00935     if (maxIndex<indexValue)
00936       maxIndex = indexValue;
00937   }
00938   
00939   reserve(maxIndex+1);
00940   nElements_ = 0;
00941   int numberDuplicates=0;
00942   // elements_ array is all zero
00943   bool needClean=false;
00944   for (i=0;i<size;i++) {
00945     int indexValue=inds[i];
00946     if (elements_[indexValue] == 0)
00947     {
00948       if (fabs(value)>=COIN_INDEXED_TINY_ELEMENT) {
00949         elements_[indexValue] += value;
00950         indices_[nElements_++]=indexValue;
00951       }
00952     }
00953     else
00954     {
00955       numberDuplicates++;
00956       elements_[indexValue] += value ;
00957       if (fabs(elements_[indexValue])<COIN_INDEXED_TINY_ELEMENT) 
00958         needClean=true; // need to go through again
00959     }
00960   }
00961   if (needClean) {
00962     // go through again
00963     size=nElements_;
00964     nElements_=0;
00965     for (i=0;i<size;i++) {
00966       int indexValue=indices_[i];
00967       double value=elements_[indexValue];
00968       if (fabs(value)>=COIN_INDEXED_TINY_ELEMENT) {
00969         indices_[nElements_++]=indexValue;
00970       } else {
00971         elements_[indexValue]=0.0;
00972       }
00973     }
00974   }
00975   if (numberDuplicates)
00976     throw CoinError("duplicate index", "setConstant", "CoinIndexedVector");
00977 }
00978 
00979 //#############################################################################
00980 // Append a CoinIndexedVector to the end
00981 void 
00982 CoinIndexedVector::append(const CoinIndexedVector & caboose)
00983 {
00984   const int cs = caboose.getNumElements();
00985   
00986   const int * cind = caboose.getIndices();
00987   const double * celem = caboose.denseVector();
00988   int maxIndex=-1;
00989   int i;
00990   for (i=0;i<cs;i++) {
00991     int indexValue = cind[i];
00992     if (indexValue<0)
00993       throw CoinError("negative index", "append", "CoinIndexedVector");
00994     if (maxIndex<indexValue)
00995       maxIndex = indexValue;
00996   }
00997   reserve(maxIndex+1);
00998   bool needClean=false;
00999   int numberDuplicates=0;
01000   for (i=0;i<cs;i++) {
01001     int indexValue=cind[i];
01002     if (elements_[indexValue]) {
01003       numberDuplicates++;
01004       elements_[indexValue] += celem[indexValue] ;
01005       if (fabs(elements_[indexValue])<COIN_INDEXED_TINY_ELEMENT) 
01006         needClean=true; // need to go through again
01007     } else {
01008       if (fabs(celem[indexValue])>=COIN_INDEXED_TINY_ELEMENT) {
01009         elements_[indexValue]=celem[indexValue];
01010         indices_[nElements_++]=indexValue;
01011       }
01012     }
01013   }
01014   if (needClean) {
01015     // go through again
01016     int size=nElements_;
01017     nElements_=0;
01018     for (i=0;i<size;i++) {
01019       int indexValue=indices_[i];
01020       double value=elements_[indexValue];
01021       if (fabs(value)>=COIN_INDEXED_TINY_ELEMENT) {
01022         indices_[nElements_++]=indexValue;
01023       } else {
01024         elements_[indexValue]=0.0;
01025       }
01026     }
01027   }
01028   if (numberDuplicates)
01029     throw CoinError("duplicate index", "append", "CoinIndexedVector");
01030 }
01031 
01032 /* Equal. Returns true if vectors have same length and corresponding
01033    element of each vector is equal. */
01034 bool 
01035 CoinIndexedVector::operator==(const CoinPackedVectorBase & rhs) const
01036 {
01037   const int cs = rhs.getNumElements();
01038   
01039   const int * cind = rhs.getIndices();
01040   const double * celem = rhs.getElements();
01041   if (nElements_!=cs)
01042     return false;
01043   int i;
01044   bool okay=true;
01045   for (i=0;i<cs;i++) {
01046     int iRow = cind[i];
01047     if (celem[i]!=elements_[iRow]) {
01048       okay=false;
01049       break;
01050     }
01051   }
01052   return okay;
01053 }
01054 // Not equal
01055 bool 
01056 CoinIndexedVector::operator!=(const CoinPackedVectorBase & rhs) const
01057 {
01058   const int cs = rhs.getNumElements();
01059   
01060   const int * cind = rhs.getIndices();
01061   const double * celem = rhs.getElements();
01062   if (nElements_!=cs)
01063     return true;
01064   int i;
01065   bool okay=false;
01066   for (i=0;i<cs;i++) {
01067     int iRow = cind[i];
01068     if (celem[i]!=elements_[iRow]) {
01069       okay=true;
01070       break;
01071     }
01072   }
01073   return okay;
01074 }
01075 /* Equal. Returns true if vectors have same length and corresponding
01076    element of each vector is equal. */
01077 bool 
01078 CoinIndexedVector::operator==(const CoinIndexedVector & rhs) const
01079 {
01080   const int cs = rhs.nElements_;
01081   
01082   const int * cind = rhs.indices_;
01083   const double * celem = rhs.elements_;
01084   if (nElements_!=cs)
01085     return false;
01086   int i;
01087   bool okay=true;
01088   for (i=0;i<cs;i++) {
01089     int iRow = cind[i];
01090     if (celem[iRow]!=elements_[iRow]) {
01091       okay=false;
01092       break;
01093     }
01094   }
01095   return okay;
01096 }
01098 bool 
01099 CoinIndexedVector::operator!=(const CoinIndexedVector & rhs) const
01100 {
01101   const int cs = rhs.nElements_;
01102   
01103   const int * cind = rhs.indices_;
01104   const double * celem = rhs.elements_;
01105   if (nElements_!=cs)
01106     return true;
01107   int i;
01108   bool okay=false;
01109   for (i=0;i<cs;i++) {
01110     int iRow = cind[i];
01111     if (celem[iRow]!=elements_[iRow]) {
01112       okay=true;
01113       break;
01114     }
01115   }
01116   return okay;
01117 }
01118 // Get value of maximum index
01119 int 
01120 CoinIndexedVector::getMaxIndex() const
01121 {
01122   int maxIndex = INT_MIN;
01123   int i;
01124   for (i=0;i<nElements_;i++)
01125     maxIndex = max(maxIndex,indices_[i]);
01126   return maxIndex;
01127 }
01128 // Get value of minimum index
01129 int 
01130 CoinIndexedVector::getMinIndex() const
01131 {
01132   int minIndex = INT_MAX;
01133   int i;
01134   for (i=0;i<nElements_;i++)
01135     minIndex = min(minIndex,indices_[i]);
01136   return minIndex;
01137 }
01138 // Scan dense region and set up indices
01139 int
01140 CoinIndexedVector::scan()
01141 {
01142   nElements_=0;
01143   return scan(0,capacity_);
01144 }
01145 // Scan dense region from start to < end and set up indices
01146 int
01147 CoinIndexedVector::scan(int start, int end)
01148 {
01149   assert(!packedMode_);
01150   end = min(end,capacity_);
01151   start = max(start,0);
01152   int i;
01153   int number = 0;
01154   int * indices = indices_+nElements_;
01155   for (i=start;i<end;i++) 
01156     if (elements_[i])
01157       indices[number++] = i;
01158   nElements_ += number;
01159   return number;
01160 }
01161 // Scan dense region and set up indices with tolerance
01162 int
01163 CoinIndexedVector::scan(double tolerance)
01164 {
01165   nElements_=0;
01166   return scan(0,capacity_,tolerance);
01167 }
01168 // Scan dense region from start to < end and set up indices with tolerance
01169 int
01170 CoinIndexedVector::scan(int start, int end, double tolerance)
01171 {
01172   assert(!packedMode_);
01173   end = min(end,capacity_);
01174   start = max(start,0);
01175   int i;
01176   int number = 0;
01177   int * indices = indices_+nElements_;
01178   for (i=start;i<end;i++) {
01179     double value = elements_[i];
01180     if (value) {
01181       if (fabs(value)>=tolerance) 
01182         indices[number++] = i;
01183       else
01184         elements_[i]=0.0;
01185     }
01186   }
01187   nElements_ += number;
01188   return number;
01189 }
01190 // These pack down
01191 int
01192 CoinIndexedVector::cleanAndPack( double tolerance )
01193 {
01194   int number = nElements_;
01195   int i;
01196   nElements_=0;
01197   assert(!packedMode_);
01198   for (i=0;i<number;i++) {
01199     int indexValue = indices_[i];
01200     double value = elements_[indexValue];
01201     elements_[indexValue]=0.0;
01202     if (fabs(value)>=tolerance) {
01203       elements_[nElements_]=value;
01204       indices_[nElements_++]=indexValue;
01205     }
01206   }
01207   packedMode_=true;
01208   return nElements_;
01209 }
01210 // These pack down
01211 int
01212 CoinIndexedVector::cleanAndPackSafe( double tolerance )
01213 {
01214   int number = nElements_;
01215   if (number) {
01216     int i;
01217     nElements_=0;
01218     assert(!packedMode_);
01219     double * temp=NULL;
01220     bool gotMemory;
01221     if (number*3<capacity_-3-9999999) {
01222       // can find room without new
01223       gotMemory=false;
01224       // But may need to align on 8 byte boundary
01225       char * tempC = (char *) (indices_+number);
01226 #ifndef __64BIT__
01227       int xx = (int) tempC;
01228       int iBottom = xx & 7;
01229 #else
01230       long xx = (long) tempC;
01231       long iBottom = xx & 7;
01232 #endif
01233       if (iBottom)
01234         tempC += 8-iBottom;
01235       temp = (double *) tempC;
01236 #ifndef __64BIT__
01237       xx = (int) temp;
01238 #else
01239       xx = (long) temp;
01240 #endif
01241       iBottom = xx & 7;
01242       assert(!iBottom);
01243     } else {
01244       // might be better to do complete scan
01245       gotMemory=true;
01246       temp = new double[number];
01247     }
01248     for (i=0;i<number;i++) {
01249       int indexValue = indices_[i];
01250       double value = elements_[indexValue];
01251       elements_[indexValue]=0.0;
01252       if (fabs(value)>=tolerance) {
01253         temp[nElements_]=value;
01254         indices_[nElements_++]=indexValue;
01255       }
01256     }
01257     memcpy(elements_,temp,nElements_*sizeof(double));
01258     if (gotMemory)
01259       delete [] temp;
01260     packedMode_=true;
01261   }
01262   return nElements_;
01263 }
01264 // Scan dense region and set up indices
01265 int
01266 CoinIndexedVector::scanAndPack()
01267 {
01268   nElements_=0;
01269   return scanAndPack(0,capacity_);
01270 }
01271 // Scan dense region from start to < end and set up indices
01272 int
01273 CoinIndexedVector::scanAndPack(int start, int end)
01274 {
01275   assert(!packedMode_);
01276   end = min(end,capacity_);
01277   start = max(start,0);
01278   int i;
01279   int number = 0;
01280   int * indices = indices_+nElements_;
01281   for (i=start;i<end;i++) {
01282     double value = elements_[i];
01283     elements_[i]=0.0;
01284     if (value) {
01285       elements_[number]=value;
01286       indices[number++] = i;
01287     }
01288   }
01289   nElements_ += number;
01290   packedMode_=true;
01291   return number;
01292 }
01293 // Scan dense region and set up indices with tolerance
01294 int
01295 CoinIndexedVector::scanAndPack(double tolerance)
01296 {
01297   nElements_=0;
01298   return scanAndPack(0,capacity_,tolerance);
01299 }
01300 // Scan dense region from start to < end and set up indices with tolerance
01301 int
01302 CoinIndexedVector::scanAndPack(int start, int end, double tolerance)
01303 {
01304   assert(!packedMode_);
01305   end = min(end,capacity_);
01306   start = max(start,0);
01307   int i;
01308   int number = 0;
01309   int * indices = indices_+nElements_;
01310   for (i=start;i<end;i++) {
01311     double value = elements_[i];
01312     elements_[i]=0.0;
01313     if (fabs(value)>=tolerance) {
01314       elements_[number]=value;
01315         indices[number++] = i;
01316     }
01317   }
01318   nElements_ += number;
01319   packedMode_=true;
01320   return number;
01321 }
01322 // This is mainly for testing - goes from packed to indexed
01323 void 
01324 CoinIndexedVector::expand()
01325 {
01326   if (nElements_&&packedMode_) {
01327     double * temp = new double[capacity_];
01328     int i;
01329     for (i=0;i<nElements_;i++) 
01330       temp[indices_[i]]=elements_[i];
01331     memset(elements_,0,nElements_*sizeof(double));
01332     for (i=0;i<nElements_;i++) {
01333       int iRow = indices_[i];
01334       elements_[iRow]=temp[iRow];
01335     }
01336     delete [] temp;
01337   }
01338   packedMode_=false;
01339 }
01340 // Create packed array
01341 void 
01342 CoinIndexedVector::createPacked(int number, const int * indices, 
01343                     const double * elements)
01344 {
01345   nElements_=number;
01346   packedMode_=true;
01347   memcpy(indices_,indices,number*sizeof(int));
01348   memcpy(elements_,elements,number*sizeof(double));
01349 }
01350 

Generated on Wed Dec 3 14:34:18 2003 for Coin by doxygen 1.3.5