00001
00002
00003 #if defined(_MSC_VER)
00004
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
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
00137 clear();
00138
00139 if (size<0)
00140 throw CoinError("negative number of indices", "setFull", "CoinIndexedVector");
00141
00142 reserve(size);
00143 nElements_ = 0;
00144
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
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
00249 char * mark = (char *) (indices_+capacity_);
00250 for (i=0;i<capacity_;i++) {
00251 assert(!mark[i]);
00252 }
00253 #endif
00254 }
00255
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
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;
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
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
00352
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
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
00438 int * tempIndices = indices_;
00439 double * tempElements = elements_;
00440 double * delTemp = elements_-offset_;
00441
00442
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
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
00467
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
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
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
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
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
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
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
00706
00707 assert(newOne.nElements_ == nElements) ;
00708
00709 if (needClean) {
00710
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
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
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
00753
00754 assert(newOne.nElements_ == nElements) ;
00755
00756 if (needClean) {
00757
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
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
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
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;
00845 }
00846 }
00847 if (needClean) {
00848
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
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;
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
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
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
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;
00959 }
00960 }
00961 if (needClean) {
00962
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
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;
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
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
01033
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
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
01076
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
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
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
01139 int
01140 CoinIndexedVector::scan()
01141 {
01142 nElements_=0;
01143 return scan(0,capacity_);
01144 }
01145
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
01162 int
01163 CoinIndexedVector::scan(double tolerance)
01164 {
01165 nElements_=0;
01166 return scan(0,capacity_,tolerance);
01167 }
01168
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
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
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
01223 gotMemory=false;
01224
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
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
01265 int
01266 CoinIndexedVector::scanAndPack()
01267 {
01268 nElements_=0;
01269 return scanAndPack(0,capacity_);
01270 }
01271
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
01294 int
01295 CoinIndexedVector::scanAndPack(double tolerance)
01296 {
01297 nElements_=0;
01298 return scanAndPack(0,capacity_,tolerance);
01299 }
01300
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
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
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