1 /* $Id: CoinIndexedVector.cpp 2084 2019-01-09 14:17:08Z forrest $ */
2 // Copyright (C) 2000, International Business Machines
3 // Corporation and others.  All Rights Reserved.
4 // This code is licensed under the terms of the Eclipse Public License (EPL).
5 
6 #if defined(_MSC_VER)
7 // Turn off compiler warning about long names
8 #pragma warning(disable : 4786)
9 #endif
10 
11 #include <cassert>
12 #include <cstdio>
13 
14 #include "CoinTypes.hpp"
15 #include "CoinFloatEqual.hpp"
16 #include "CoinHelperFunctions.hpp"
17 #include "CoinIndexedVector.hpp"
18 #include "CoinTypes.hpp"
19 //#############################################################################
20 #define WARN_USELESS 0
clear()21 void CoinIndexedVector::clear()
22 {
23 #if WARN_USELESS
24   int nNonZero = 0;
25   for (int i = 0; i < capacity_; i++) {
26     if (elements_[i])
27       nNonZero++;
28   }
29   assert(nNonZero <= nElements_);
30 #if WARN_USELESS > 1
31   if (nNonZero != nElements_)
32     printf("Vector said it had %d nonzeros - only had %d\n",
33       nElements_, nNonZero);
34 #endif
35   if (!nNonZero && nElements_)
36     printf("Vector said it had %d nonzeros - but is already empty\n",
37       nElements_);
38 #endif
39   assert(nElements_ <= capacity_);
40   if (!packedMode_) {
41 #ifndef NDEBUG
42     for (int i = 0; i < nElements_; i++)
43       assert(indices_[i] >= 0 && indices_[i] < capacity_);
44 #endif
45     if (3 * nElements_ < capacity_) {
46       int i = 0;
47       if ((nElements_ & 1) != 0) {
48         elements_[indices_[0]] = 0.0;
49         i = 1;
50       }
51       for (; i < nElements_; i += 2) {
52         int i0 = indices_[i];
53         int i1 = indices_[i + 1];
54         elements_[i0] = 0.0;
55         elements_[i1] = 0.0;
56       }
57     } else {
58       CoinZeroN(elements_, capacity_);
59     }
60   } else {
61     CoinZeroN(elements_, nElements_);
62   }
63   nElements_ = 0;
64   packedMode_ = false;
65   //checkClear();
66 }
reallyClear()67 void CoinIndexedVector::reallyClear()
68 {
69   CoinZeroN(elements_, capacity_);
70   nElements_ = 0;
71   packedMode_ = false;
72 }
73 //#############################################################################
74 
empty()75 void CoinIndexedVector::empty()
76 {
77   delete[] indices_;
78   indices_ = NULL;
79   if (elements_)
80     delete[](elements_ - offset_);
81   elements_ = NULL;
82   nElements_ = 0;
83   capacity_ = 0;
84   packedMode_ = false;
85 }
86 
87 //#############################################################################
88 
89 CoinIndexedVector &
operator =(const CoinIndexedVector & rhs)90 CoinIndexedVector::operator=(const CoinIndexedVector &rhs)
91 {
92   if (this != &rhs) {
93     clear();
94     packedMode_ = rhs.packedMode_;
95     if (!packedMode_)
96       gutsOfSetVector(rhs.capacity_, rhs.nElements_,
97         rhs.indices_, rhs.elements_);
98     else
99       gutsOfSetPackedVector(rhs.capacity_, rhs.nElements_,
100         rhs.indices_, rhs.elements_);
101   }
102   return *this;
103 }
104 /* Copy the contents of one vector into another.  If multiplier is 1
105    It is the equivalent of = but if vectors are same size does
106    not re-allocate memory just clears and copies */
copy(const CoinIndexedVector & rhs,double multiplier)107 void CoinIndexedVector::copy(const CoinIndexedVector &rhs, double multiplier)
108 {
109   if (capacity_ == rhs.capacity_) {
110     // can do fast
111     clear();
112     packedMode_ = rhs.packedMode_;
113     nElements_ = 0;
114     if (!packedMode_) {
115       for (int i = 0; i < rhs.nElements_; i++) {
116         int index = rhs.indices_[i];
117         double value = rhs.elements_[index] * multiplier;
118         if (fabs(value) < COIN_INDEXED_TINY_ELEMENT)
119           value = COIN_INDEXED_REALLY_TINY_ELEMENT;
120         elements_[index] = value;
121         indices_[nElements_++] = index;
122       }
123     } else {
124       for (int i = 0; i < rhs.nElements_; i++) {
125         int index = rhs.indices_[i];
126         double value = rhs.elements_[i] * multiplier;
127         if (fabs(value) < COIN_INDEXED_TINY_ELEMENT)
128           value = COIN_INDEXED_REALLY_TINY_ELEMENT;
129         elements_[nElements_] = value;
130         indices_[nElements_++] = index;
131       }
132     }
133   } else {
134     // do as two operations
135     *this = rhs;
136     (*this) *= multiplier;
137   }
138 }
139 
140 //#############################################################################
141 #ifndef CLP_NO_VECTOR
142 CoinIndexedVector &
operator =(const CoinPackedVectorBase & rhs)143 CoinIndexedVector::operator=(const CoinPackedVectorBase &rhs)
144 {
145   clear();
146   packedMode_ = false;
147   gutsOfSetVector(rhs.getNumElements(),
148     rhs.getIndices(), rhs.getElements());
149   return *this;
150 }
151 #endif
152 //#############################################################################
153 
borrowVector(int size,int numberIndices,int * inds,double * elems)154 void CoinIndexedVector::borrowVector(int size, int numberIndices, int *inds, double *elems)
155 {
156   empty();
157   capacity_ = size;
158   nElements_ = numberIndices;
159   indices_ = inds;
160   elements_ = elems;
161 
162   // whole point about borrowvector is that it is lightweight so no testing is done
163 }
164 
165 //#############################################################################
166 
returnVector()167 void CoinIndexedVector::returnVector()
168 {
169   indices_ = NULL;
170   elements_ = NULL;
171   nElements_ = 0;
172   capacity_ = 0;
173   packedMode_ = false;
174 }
175 
176 //#############################################################################
177 
setVector(int size,const int * inds,const double * elems)178 void CoinIndexedVector::setVector(int size, const int *inds, const double *elems)
179 {
180   clear();
181   gutsOfSetVector(size, inds, elems);
182 }
183 //#############################################################################
184 
setVector(int size,int numberIndices,const int * inds,const double * elems)185 void CoinIndexedVector::setVector(int size, int numberIndices, const int *inds, const double *elems)
186 {
187   clear();
188   gutsOfSetVector(size, numberIndices, inds, elems);
189 }
190 //#############################################################################
191 
setConstant(int size,const int * inds,double value)192 void CoinIndexedVector::setConstant(int size, const int *inds, double value)
193 {
194   clear();
195   gutsOfSetConstant(size, inds, value);
196 }
197 
198 //#############################################################################
199 
setFull(int size,const double * elems)200 void CoinIndexedVector::setFull(int size, const double *elems)
201 {
202   // Clear out any values presently stored
203   clear();
204 
205 #ifndef COIN_FAST_CODE
206   if (size < 0)
207     throw CoinError("negative number of indices", "setFull", "CoinIndexedVector");
208 #endif
209   reserve(size);
210   nElements_ = 0;
211   // elements_ array is all zero
212   int i;
213   for (i = 0; i < size; i++) {
214     int indexValue = i;
215     if (fabs(elems[i]) >= COIN_INDEXED_TINY_ELEMENT) {
216       elements_[indexValue] = elems[i];
217       indices_[nElements_++] = indexValue;
218     }
219   }
220 }
221 //#############################################################################
222 
223 /** Access the i'th element of the full storage vector.  */
224 double &
operator [](int index) const225   CoinIndexedVector::operator[](int index) const
226 {
227   assert(!packedMode_);
228 #ifndef COIN_FAST_CODE
229   if (index >= capacity_)
230     throw CoinError("index >= capacity()", "[]", "CoinIndexedVector");
231   if (index < 0)
232     throw CoinError("index < 0", "[]", "CoinIndexedVector");
233 #endif
234   double *where = elements_ + index;
235   return *where;
236 }
237 //#############################################################################
238 
setElement(int index,double element)239 void CoinIndexedVector::setElement(int index, double element)
240 {
241 #ifndef COIN_FAST_CODE
242   if (index >= nElements_)
243     throw CoinError("index >= size()", "setElement", "CoinIndexedVector");
244   if (index < 0)
245     throw CoinError("index < 0", "setElement", "CoinIndexedVector");
246 #endif
247   elements_[indices_[index]] = element;
248 }
249 
250 //#############################################################################
251 
insert(int index,double element)252 void CoinIndexedVector::insert(int index, double element)
253 {
254 #ifndef COIN_FAST_CODE
255   if (index < 0)
256     throw CoinError("index < 0", "setElement", "CoinIndexedVector");
257 #endif
258   if (index >= capacity_)
259     reserve(index + 1);
260 #ifndef COIN_FAST_CODE
261   if (elements_[index])
262     throw CoinError("Index already exists", "insert", "CoinIndexedVector");
263 #endif
264   indices_[nElements_++] = index;
265   elements_[index] = element;
266 }
267 
268 //#############################################################################
269 
add(int index,double element)270 void CoinIndexedVector::add(int index, double element)
271 {
272 #ifndef COIN_FAST_CODE
273   if (index < 0)
274     throw CoinError("index < 0", "setElement", "CoinIndexedVector");
275 #endif
276   if (index >= capacity_)
277     reserve(index + 1);
278   if (elements_[index]) {
279     element += elements_[index];
280     if (fabs(element) >= COIN_INDEXED_TINY_ELEMENT) {
281       elements_[index] = element;
282     } else {
283       elements_[index] = COIN_INDEXED_REALLY_TINY_ELEMENT;
284     }
285   } else if (fabs(element) >= COIN_INDEXED_TINY_ELEMENT) {
286     indices_[nElements_++] = index;
287     assert(nElements_ <= capacity_);
288     elements_[index] = element;
289   }
290 }
291 
292 //#############################################################################
293 
clean(double tolerance)294 int CoinIndexedVector::clean(double tolerance)
295 {
296   int number = nElements_;
297   int i;
298   nElements_ = 0;
299   assert(!packedMode_);
300   for (i = 0; i < number; i++) {
301     int indexValue = indices_[i];
302     if (fabs(elements_[indexValue]) >= tolerance) {
303       indices_[nElements_++] = indexValue;
304     } else {
305       elements_[indexValue] = 0.0;
306     }
307   }
308   return nElements_;
309 }
310 #ifndef NDEBUG
311 //#############################################################################
312 // For debug check vector is clear i.e. no elements
checkClear()313 void CoinIndexedVector::checkClear()
314 {
315 #ifndef NDEBUG
316   //printf("checkClear %p\n",this);
317   assert(!nElements_);
318   //assert(!packedMode_);
319   int i;
320   for (i = 0; i < capacity_; i++) {
321     assert(!elements_[i]);
322   }
323   // check mark array zeroed
324   char *mark = reinterpret_cast< char * >(indices_ + capacity_);
325   for (i = 0; i < capacity_; i++) {
326     assert(!mark[i]);
327   }
328 #else
329   if (nElements_) {
330     printf("%d nElements_ - checkClear\n", nElements_);
331     abort();
332   }
333   if (packedMode_) {
334     printf("packed mode when empty - checkClear\n");
335     abort();
336   }
337   int i;
338   int n = 0;
339   int k = -1;
340   for (i = 0; i < capacity_; i++) {
341     if (elements_[i]) {
342       n++;
343       if (k < 0)
344         k = i;
345     }
346   }
347   if (n) {
348     printf("%d elements, first %d - checkClear\n", n, k);
349     abort();
350   }
351 #endif
352 }
353 // For debug check vector is clean i.e. elements match indices
checkClean()354 void CoinIndexedVector::checkClean()
355 {
356   //printf("checkClean %p\n",this);
357   int i;
358   if (packedMode_) {
359     for (i = 0; i < nElements_; i++)
360       assert(elements_[i]);
361     for (; i < capacity_; i++)
362       assert(!elements_[i]);
363   } else {
364     double *copy = new double[capacity_];
365     CoinMemcpyN(elements_, capacity_, copy);
366     for (i = 0; i < nElements_; i++) {
367       int indexValue = indices_[i];
368       assert(copy[indexValue]);
369       copy[indexValue] = 0.0;
370     }
371     for (i = 0; i < capacity_; i++)
372       assert(!copy[i]);
373     delete[] copy;
374   }
375 #ifndef NDEBUG
376   // check mark array zeroed
377   char *mark = reinterpret_cast< char * >(indices_ + capacity_);
378   for (i = 0; i < capacity_; i++) {
379     assert(!mark[i]);
380   }
381 #endif
382 }
383 #endif
384 //#############################################################################
385 #ifndef CLP_NO_VECTOR
append(const CoinPackedVectorBase & caboose)386 void CoinIndexedVector::append(const CoinPackedVectorBase &caboose)
387 {
388   const int cs = caboose.getNumElements();
389 
390   const int *cind = caboose.getIndices();
391   const double *celem = caboose.getElements();
392   int maxIndex = -1;
393   int i;
394   for (i = 0; i < cs; i++) {
395     int indexValue = cind[i];
396     if (indexValue < 0)
397       throw CoinError("negative index", "append", "CoinIndexedVector");
398     if (maxIndex < indexValue)
399       maxIndex = indexValue;
400   }
401   reserve(maxIndex + 1);
402   bool needClean = false;
403   int numberDuplicates = 0;
404   for (i = 0; i < cs; i++) {
405     int indexValue = cind[i];
406     if (elements_[indexValue]) {
407       numberDuplicates++;
408       elements_[indexValue] += celem[i];
409       if (fabs(elements_[indexValue]) < COIN_INDEXED_TINY_ELEMENT)
410         needClean = true; // need to go through again
411     } else {
412       if (fabs(celem[i]) >= COIN_INDEXED_TINY_ELEMENT) {
413         elements_[indexValue] = celem[i];
414         indices_[nElements_++] = indexValue;
415       }
416     }
417   }
418   if (needClean) {
419     // go through again
420     int size = nElements_;
421     nElements_ = 0;
422     for (i = 0; i < size; i++) {
423       int indexValue = indices_[i];
424       double value = elements_[indexValue];
425       if (fabs(value) >= COIN_INDEXED_TINY_ELEMENT) {
426         indices_[nElements_++] = indexValue;
427       } else {
428         elements_[indexValue] = 0.0;
429       }
430     }
431   }
432   if (numberDuplicates)
433     throw CoinError("duplicate index", "append", "CoinIndexedVector");
434 }
435 #endif
436 //#############################################################################
437 
swap(int i,int j)438 void CoinIndexedVector::swap(int i, int j)
439 {
440   if (i >= nElements_)
441     throw CoinError("index i >= size()", "swap", "CoinIndexedVector");
442   if (i < 0)
443     throw CoinError("index i < 0", "swap", "CoinIndexedVector");
444   if (j >= nElements_)
445     throw CoinError("index j >= size()", "swap", "CoinIndexedVector");
446   if (j < 0)
447     throw CoinError("index j < 0", "swap", "CoinIndexedVector");
448 
449   // Swap positions i and j of the
450   // indices array
451 
452   int isave = indices_[i];
453   indices_[i] = indices_[j];
454   indices_[j] = isave;
455 }
456 
457 //#############################################################################
458 
truncate(int n)459 void CoinIndexedVector::truncate(int n)
460 {
461   reserve(n);
462 }
463 
464 //#############################################################################
465 
operator +=(double value)466 void CoinIndexedVector::operator+=(double value)
467 {
468   assert(!packedMode_);
469   int i, indexValue;
470   for (i = 0; i < nElements_; i++) {
471     indexValue = indices_[i];
472     double newValue = elements_[indexValue] + value;
473     if (fabs(newValue) >= COIN_INDEXED_TINY_ELEMENT)
474       elements_[indexValue] = newValue;
475     else
476       elements_[indexValue] = COIN_INDEXED_REALLY_TINY_ELEMENT;
477   }
478 }
479 
480 //-----------------------------------------------------------------------------
481 
operator -=(double value)482 void CoinIndexedVector::operator-=(double value)
483 {
484   assert(!packedMode_);
485   int i, indexValue;
486   for (i = 0; i < nElements_; i++) {
487     indexValue = indices_[i];
488     double newValue = elements_[indexValue] - value;
489     if (fabs(newValue) >= COIN_INDEXED_TINY_ELEMENT)
490       elements_[indexValue] = newValue;
491     else
492       elements_[indexValue] = COIN_INDEXED_REALLY_TINY_ELEMENT;
493   }
494 }
495 
496 //-----------------------------------------------------------------------------
497 
operator *=(double value)498 void CoinIndexedVector::operator*=(double value)
499 {
500   assert(!packedMode_);
501   int i, indexValue;
502   for (i = 0; i < nElements_; i++) {
503     indexValue = indices_[i];
504     double newValue = elements_[indexValue] * value;
505     if (fabs(newValue) >= COIN_INDEXED_TINY_ELEMENT)
506       elements_[indexValue] = newValue;
507     else
508       elements_[indexValue] = COIN_INDEXED_REALLY_TINY_ELEMENT;
509   }
510 }
511 
512 //-----------------------------------------------------------------------------
513 
operator /=(double value)514 void CoinIndexedVector::operator/=(double value)
515 {
516   assert(!packedMode_);
517   int i, indexValue;
518   for (i = 0; i < nElements_; i++) {
519     indexValue = indices_[i];
520     double newValue = elements_[indexValue] / value;
521     if (fabs(newValue) >= COIN_INDEXED_TINY_ELEMENT)
522       elements_[indexValue] = newValue;
523     else
524       elements_[indexValue] = COIN_INDEXED_REALLY_TINY_ELEMENT;
525   }
526 }
527 //#############################################################################
528 
reserve(int n)529 void CoinIndexedVector::reserve(int n)
530 {
531   int i;
532   int nPlus;
533   if (sizeof(int) == 4 * sizeof(char))
534     nPlus = (n + 3) >> 2;
535   else
536     nPlus = (n + 7) >> 4;
537 #ifdef COIN_AVX2
538   nPlus += 16;
539 #endif
540   // don't make allocated space smaller but do take off values
541   if (n + nPlus < capacity_) {
542 #ifndef COIN_FAST_CODE
543     if (n < 0)
544       throw CoinError("negative capacity", "reserve", "CoinIndexedVector");
545 #endif
546     int nNew = 0;
547     for (i = 0; i < nElements_; i++) {
548       int indexValue = indices_[i];
549       if (indexValue < n) {
550         indices_[nNew++] = indexValue;
551       } else {
552         elements_[indexValue] = 0.0;
553       }
554     }
555     nElements_ = nNew;
556   } else if (n > capacity_) {
557 
558     // save pointers to existing data
559     int *tempIndices = indices_;
560     double *tempElements = elements_;
561     double *delTemp = elements_ - offset_;
562 
563     // allocate new space
564     indices_ = new int[n + nPlus];
565     CoinZeroN(indices_ + n, nPlus);
566     // align on 64 byte boundary
567     double *temp = new double[n + 9 + nPlus];
568     offset_ = 0;
569     CoinInt64 xx = reinterpret_cast< CoinInt64 >(temp);
570     int iBottom = static_cast< int >(xx & 63);
571     //if (iBottom)
572     offset_ = (64 - iBottom) >> 3;
573     elements_ = temp + offset_;
574     ;
575 
576     // copy data to new space
577     // and zero out part of array
578     if (nElements_ > 0) {
579       CoinMemcpyN(tempIndices, nElements_, indices_);
580       CoinMemcpyN(tempElements, capacity_, elements_);
581       CoinZeroN(elements_ + capacity_, n - capacity_);
582     } else {
583       CoinZeroN(elements_, n);
584     }
585     capacity_ = n;
586 
587     // free old data
588     if (tempElements)
589       delete[] delTemp;
590     delete[] tempIndices;
591   }
592 }
593 
594 //#############################################################################
595 
CoinIndexedVector()596 CoinIndexedVector::CoinIndexedVector()
597   : indices_(NULL)
598   , elements_(NULL)
599   , nElements_(0)
600   , capacity_(0)
601   , offset_(0)
602   , packedMode_(false)
603 {
604 }
605 
CoinIndexedVector(int size)606 CoinIndexedVector::CoinIndexedVector(int size)
607   : indices_(NULL)
608   , elements_(NULL)
609   , nElements_(0)
610   , capacity_(0)
611   , offset_(0)
612   , packedMode_(false)
613 {
614   // Get space
615   reserve(size);
616 }
617 
618 //-----------------------------------------------------------------------------
619 
CoinIndexedVector(int size,const int * inds,const double * elems)620 CoinIndexedVector::CoinIndexedVector(int size,
621   const int *inds, const double *elems)
622   : indices_(NULL)
623   , elements_(NULL)
624   , nElements_(0)
625   , capacity_(0)
626   , offset_(0)
627   , packedMode_(false)
628 {
629   gutsOfSetVector(size, inds, elems);
630 }
631 
632 //-----------------------------------------------------------------------------
633 
CoinIndexedVector(int size,const int * inds,double value)634 CoinIndexedVector::CoinIndexedVector(int size,
635   const int *inds, double value)
636   : indices_(NULL)
637   , elements_(NULL)
638   , nElements_(0)
639   , capacity_(0)
640   , offset_(0)
641   , packedMode_(false)
642 {
643   gutsOfSetConstant(size, inds, value);
644 }
645 
646 //-----------------------------------------------------------------------------
647 
CoinIndexedVector(int size,const double * element)648 CoinIndexedVector::CoinIndexedVector(int size, const double *element)
649   : indices_(NULL)
650   , elements_(NULL)
651   , nElements_(0)
652   , capacity_(0)
653   , offset_(0)
654   , packedMode_(false)
655 {
656   setFull(size, element);
657 }
658 
659 //-----------------------------------------------------------------------------
660 #ifndef CLP_NO_VECTOR
CoinIndexedVector(const CoinPackedVectorBase & rhs)661 CoinIndexedVector::CoinIndexedVector(const CoinPackedVectorBase &rhs)
662   : indices_(NULL)
663   , elements_(NULL)
664   , nElements_(0)
665   , capacity_(0)
666   , offset_(0)
667   , packedMode_(false)
668 {
669   gutsOfSetVector(rhs.getNumElements(),
670     rhs.getIndices(), rhs.getElements());
671 }
672 #endif
673 //-----------------------------------------------------------------------------
674 
CoinIndexedVector(const CoinIndexedVector & rhs)675 CoinIndexedVector::CoinIndexedVector(const CoinIndexedVector &rhs)
676   : indices_(NULL)
677   , elements_(NULL)
678   , nElements_(0)
679   , capacity_(0)
680   , offset_(0)
681   , packedMode_(false)
682 {
683   if (!rhs.packedMode_)
684     gutsOfSetVector(rhs.capacity_, rhs.nElements_, rhs.indices_, rhs.elements_);
685   else
686     gutsOfSetPackedVector(rhs.capacity_, rhs.nElements_, rhs.indices_, rhs.elements_);
687 }
688 
689 //-----------------------------------------------------------------------------
690 
CoinIndexedVector(const CoinIndexedVector * rhs)691 CoinIndexedVector::CoinIndexedVector(const CoinIndexedVector *rhs)
692   : indices_(NULL)
693   , elements_(NULL)
694   , nElements_(0)
695   , capacity_(0)
696   , offset_(0)
697   , packedMode_(false)
698 {
699   if (!rhs->packedMode_)
700     gutsOfSetVector(rhs->capacity_, rhs->nElements_, rhs->indices_, rhs->elements_);
701   else
702     gutsOfSetPackedVector(rhs->capacity_, rhs->nElements_, rhs->indices_, rhs->elements_);
703 }
704 
705 //-----------------------------------------------------------------------------
706 
~CoinIndexedVector()707 CoinIndexedVector::~CoinIndexedVector()
708 {
709   delete[] indices_;
710   if (elements_)
711     delete[](elements_ - offset_);
712 }
713 //#############################################################################
714 //#############################################################################
715 
716 /// Return the sum of two indexed vectors
717 CoinIndexedVector
operator +(const CoinIndexedVector & op2)718 CoinIndexedVector::operator+(
719   const CoinIndexedVector &op2)
720 {
721   assert(!packedMode_);
722   int i;
723   int nElements = nElements_;
724   int capacity = CoinMax(capacity_, op2.capacity_);
725   CoinIndexedVector newOne(*this);
726   newOne.reserve(capacity);
727   bool needClean = false;
728   // new one now can hold everything so just modify old and add new
729   for (i = 0; i < op2.nElements_; i++) {
730     int indexValue = op2.indices_[i];
731     double value = op2.elements_[indexValue];
732     double oldValue = elements_[indexValue];
733     if (!oldValue) {
734       if (fabs(value) >= COIN_INDEXED_TINY_ELEMENT) {
735         newOne.elements_[indexValue] = value;
736         newOne.indices_[nElements++] = indexValue;
737       }
738     } else {
739       value += oldValue;
740       newOne.elements_[indexValue] = value;
741       if (fabs(value) < COIN_INDEXED_TINY_ELEMENT) {
742         needClean = true;
743       }
744     }
745   }
746   newOne.nElements_ = nElements;
747   if (needClean) {
748     // go through again
749     newOne.nElements_ = 0;
750     for (i = 0; i < nElements; i++) {
751       int indexValue = newOne.indices_[i];
752       double value = newOne.elements_[indexValue];
753       if (fabs(value) >= COIN_INDEXED_TINY_ELEMENT) {
754         newOne.indices_[newOne.nElements_++] = indexValue;
755       } else {
756         newOne.elements_[indexValue] = 0.0;
757       }
758     }
759   }
760   return newOne;
761 }
762 
763 /// Return the difference of two indexed vectors
764 CoinIndexedVector
operator -(const CoinIndexedVector & op2)765 CoinIndexedVector::operator-(
766   const CoinIndexedVector &op2)
767 {
768   assert(!packedMode_);
769   int i;
770   int nElements = nElements_;
771   int capacity = CoinMax(capacity_, op2.capacity_);
772   CoinIndexedVector newOne(*this);
773   newOne.reserve(capacity);
774   bool needClean = false;
775   // new one now can hold everything so just modify old and add new
776   for (i = 0; i < op2.nElements_; i++) {
777     int indexValue = op2.indices_[i];
778     double value = op2.elements_[indexValue];
779     double oldValue = elements_[indexValue];
780     if (!oldValue) {
781       if (fabs(value) >= COIN_INDEXED_TINY_ELEMENT) {
782         newOne.elements_[indexValue] = -value;
783         newOne.indices_[nElements++] = indexValue;
784       }
785     } else {
786       value = oldValue - value;
787       newOne.elements_[indexValue] = value;
788       if (fabs(value) < COIN_INDEXED_TINY_ELEMENT) {
789         needClean = true;
790       }
791     }
792   }
793   newOne.nElements_ = nElements;
794   if (needClean) {
795     // go through again
796     newOne.nElements_ = 0;
797     for (i = 0; i < nElements; i++) {
798       int indexValue = newOne.indices_[i];
799       double value = newOne.elements_[indexValue];
800       if (fabs(value) >= COIN_INDEXED_TINY_ELEMENT) {
801         newOne.indices_[newOne.nElements_++] = indexValue;
802       } else {
803         newOne.elements_[indexValue] = 0.0;
804       }
805     }
806   }
807   return newOne;
808 }
809 
810 /// Return the element-wise product of two indexed vectors
811 CoinIndexedVector
operator *(const CoinIndexedVector & op2)812   CoinIndexedVector::operator*(
813     const CoinIndexedVector &op2)
814 {
815   assert(!packedMode_);
816   int i;
817   int nElements = nElements_;
818   int capacity = CoinMax(capacity_, op2.capacity_);
819   CoinIndexedVector newOne(*this);
820   newOne.reserve(capacity);
821   bool needClean = false;
822   // new one now can hold everything so just modify old and add new
823   for (i = 0; i < op2.nElements_; i++) {
824     int indexValue = op2.indices_[i];
825     double value = op2.elements_[indexValue];
826     double oldValue = elements_[indexValue];
827     if (oldValue) {
828       value *= oldValue;
829       newOne.elements_[indexValue] = value;
830       if (fabs(value) < COIN_INDEXED_TINY_ELEMENT) {
831         needClean = true;
832       }
833     }
834   }
835 
836   newOne.nElements_ = nElements;
837 
838   if (needClean) {
839     // go through again
840     newOne.nElements_ = 0;
841     for (i = 0; i < nElements; i++) {
842       int indexValue = newOne.indices_[i];
843       double value = newOne.elements_[indexValue];
844       if (fabs(value) >= COIN_INDEXED_TINY_ELEMENT) {
845         newOne.indices_[newOne.nElements_++] = indexValue;
846       } else {
847         newOne.elements_[indexValue] = 0.0;
848       }
849     }
850   }
851   return newOne;
852 }
853 
854 /// Return the element-wise ratio of two indexed vectors
855 CoinIndexedVector
operator /(const CoinIndexedVector & op2)856 CoinIndexedVector::operator/(const CoinIndexedVector &op2)
857 {
858   assert(!packedMode_);
859   // I am treating 0.0/0.0 as 0.0
860   int i;
861   int nElements = nElements_;
862   int capacity = CoinMax(capacity_, op2.capacity_);
863   CoinIndexedVector newOne(*this);
864   newOne.reserve(capacity);
865   bool needClean = false;
866   // new one now can hold everything so just modify old and add new
867   for (i = 0; i < op2.nElements_; i++) {
868     int indexValue = op2.indices_[i];
869     double value = op2.elements_[indexValue];
870     double oldValue = elements_[indexValue];
871     if (oldValue) {
872       if (!value)
873         throw CoinError("zero divisor", "/", "CoinIndexedVector");
874       value = oldValue / value;
875       newOne.elements_[indexValue] = value;
876       if (fabs(value) < COIN_INDEXED_TINY_ELEMENT) {
877         needClean = true;
878       }
879     }
880   }
881 
882   newOne.nElements_ = nElements;
883 
884   if (needClean) {
885     // go through again
886     newOne.nElements_ = 0;
887     for (i = 0; i < nElements; i++) {
888       int indexValue = newOne.indices_[i];
889       double value = newOne.elements_[indexValue];
890       if (fabs(value) >= COIN_INDEXED_TINY_ELEMENT) {
891         newOne.indices_[newOne.nElements_++] = indexValue;
892       } else {
893         newOne.elements_[indexValue] = 0.0;
894       }
895     }
896   }
897   return newOne;
898 }
899 // The sum of two indexed vectors
operator +=(const CoinIndexedVector & op2)900 void CoinIndexedVector::operator+=(const CoinIndexedVector &op2)
901 {
902   // do slowly at first
903   *this = *this + op2;
904 }
905 
906 // The difference of two indexed vectors
operator -=(const CoinIndexedVector & op2)907 void CoinIndexedVector::operator-=(const CoinIndexedVector &op2)
908 {
909   // do slowly at first
910   *this = *this - op2;
911 }
912 
913 // The element-wise product of two indexed vectors
operator *=(const CoinIndexedVector & op2)914 void CoinIndexedVector::operator*=(const CoinIndexedVector &op2)
915 {
916   // do slowly at first
917   *this = *this * op2;
918 }
919 
920 // The element-wise ratio of two indexed vectors (0.0/0.0 => 0.0) (0 vanishes)
operator /=(const CoinIndexedVector & op2)921 void CoinIndexedVector::operator/=(const CoinIndexedVector &op2)
922 {
923   // do slowly at first
924   *this = *this / op2;
925 }
926 //#############################################################################
sortDecrIndex()927 void CoinIndexedVector::sortDecrIndex()
928 {
929   // Should replace with std sort
930   double *elements = new double[nElements_];
931   CoinZeroN(elements, nElements_);
932   CoinSort_2(indices_, indices_ + nElements_, elements,
933     CoinFirstGreater_2< int, double >());
934   delete[] elements;
935 }
936 
sortPacked()937 void CoinIndexedVector::sortPacked()
938 {
939   assert(packedMode_);
940   CoinSort_2(indices_, indices_ + nElements_, elements_);
941 }
942 
sortIncrElement()943 void CoinIndexedVector::sortIncrElement()
944 {
945   double *elements = new double[nElements_];
946   int i;
947   for (i = 0; i < nElements_; i++)
948     elements[i] = elements_[indices_[i]];
949   CoinSort_2(elements, elements + nElements_, indices_,
950     CoinFirstLess_2< double, int >());
951   delete[] elements;
952 }
953 
sortDecrElement()954 void CoinIndexedVector::sortDecrElement()
955 {
956   double *elements = new double[nElements_];
957   int i;
958   for (i = 0; i < nElements_; i++)
959     elements[i] = elements_[indices_[i]];
960   CoinSort_2(elements, elements + nElements_, indices_,
961     CoinFirstGreater_2< double, int >());
962   delete[] elements;
963 }
964 //#############################################################################
965 
gutsOfSetVector(int size,const int * inds,const double * elems)966 void CoinIndexedVector::gutsOfSetVector(int size,
967   const int *inds, const double *elems)
968 {
969 #ifndef COIN_FAST_CODE
970   if (size < 0)
971     throw CoinError("negative number of indices", "setVector", "CoinIndexedVector");
972 #endif
973   assert(!packedMode_);
974   // find largest
975   int i;
976   int maxIndex = -1;
977   for (i = 0; i < size; i++) {
978     int indexValue = inds[i];
979 #ifndef COIN_FAST_CODE
980     if (indexValue < 0)
981       throw CoinError("negative index", "setVector", "CoinIndexedVector");
982 #endif
983     if (maxIndex < indexValue)
984       maxIndex = indexValue;
985   }
986   reserve(maxIndex + 1);
987   nElements_ = 0;
988   // elements_ array is all zero
989   bool needClean = false;
990   int numberDuplicates = 0;
991   for (i = 0; i < size; i++) {
992     int indexValue = inds[i];
993     if (elements_[indexValue] == 0) {
994       if (fabs(elems[i]) >= COIN_INDEXED_TINY_ELEMENT) {
995         indices_[nElements_++] = indexValue;
996         elements_[indexValue] = elems[i];
997       }
998     } else {
999       numberDuplicates++;
1000       elements_[indexValue] += elems[i];
1001       if (fabs(elements_[indexValue]) < COIN_INDEXED_TINY_ELEMENT)
1002         needClean = true; // need to go through again
1003     }
1004   }
1005   if (needClean) {
1006     // go through again
1007     size = nElements_;
1008     nElements_ = 0;
1009     for (i = 0; i < size; i++) {
1010       int indexValue = indices_[i];
1011       double value = elements_[indexValue];
1012       if (fabs(value) >= COIN_INDEXED_TINY_ELEMENT) {
1013         indices_[nElements_++] = indexValue;
1014       } else {
1015         elements_[indexValue] = 0.0;
1016       }
1017     }
1018   }
1019   if (numberDuplicates)
1020     throw CoinError("duplicate index", "setVector", "CoinIndexedVector");
1021 }
1022 
1023 //#############################################################################
1024 
gutsOfSetVector(int size,int numberIndices,const int * inds,const double * elems)1025 void CoinIndexedVector::gutsOfSetVector(int size, int numberIndices,
1026   const int *inds, const double *elems)
1027 {
1028   assert(!packedMode_);
1029 
1030   int i;
1031   reserve(size);
1032 #ifndef COIN_FAST_CODE
1033   if (numberIndices < 0)
1034     throw CoinError("negative number of indices", "setVector", "CoinIndexedVector");
1035 #endif
1036   nElements_ = 0;
1037   // elements_ array is all zero
1038   bool needClean = false;
1039   int numberDuplicates = 0;
1040   for (i = 0; i < numberIndices; i++) {
1041     int indexValue = inds[i];
1042 #ifndef COIN_FAST_CODE
1043     if (indexValue < 0)
1044       throw CoinError("negative index", "setVector", "CoinIndexedVector");
1045     else if (indexValue >= size)
1046       throw CoinError("too large an index", "setVector", "CoinIndexedVector");
1047 #endif
1048     if (elements_[indexValue]) {
1049       numberDuplicates++;
1050       elements_[indexValue] += elems[indexValue];
1051       if (fabs(elements_[indexValue]) < COIN_INDEXED_TINY_ELEMENT)
1052         needClean = true; // need to go through again
1053     } else {
1054 #ifndef COIN_FAC_NEW
1055       if (fabs(elems[indexValue]) >= COIN_INDEXED_TINY_ELEMENT) {
1056 #endif
1057         elements_[indexValue] = elems[indexValue];
1058         indices_[nElements_++] = indexValue;
1059 #ifndef COIN_FAC_NEW
1060       }
1061 #endif
1062     }
1063   }
1064   if (needClean) {
1065     // go through again
1066     size = nElements_;
1067     nElements_ = 0;
1068     for (i = 0; i < size; i++) {
1069       int indexValue = indices_[i];
1070       double value = elements_[indexValue];
1071       if (fabs(value) >= COIN_INDEXED_TINY_ELEMENT) {
1072         indices_[nElements_++] = indexValue;
1073       } else {
1074         elements_[indexValue] = 0.0;
1075       }
1076     }
1077   }
1078   if (numberDuplicates)
1079     throw CoinError("duplicate index", "setVector", "CoinIndexedVector");
1080 }
1081 
1082 //-----------------------------------------------------------------------------
1083 
gutsOfSetPackedVector(int size,int numberIndices,const int * inds,const double * elems)1084 void CoinIndexedVector::gutsOfSetPackedVector(int size, int numberIndices,
1085   const int *inds, const double *elems)
1086 {
1087   packedMode_ = true;
1088 
1089   int i;
1090   reserve(size);
1091 #ifndef COIN_FAST_CODE
1092   if (numberIndices < 0)
1093     throw CoinError("negative number of indices", "setVector", "CoinIndexedVector");
1094 #endif
1095   nElements_ = 0;
1096   // elements_ array is all zero
1097   // Does not check for duplicates
1098   for (i = 0; i < numberIndices; i++) {
1099     int indexValue = inds[i];
1100 #ifndef COIN_FAST_CODE
1101     if (indexValue < 0)
1102       throw CoinError("negative index", "setVector", "CoinIndexedVector");
1103       //else if (indexValue>=size)
1104       //throw CoinError("too large an index", "setVector", "CoinIndexedVector");
1105 #endif
1106     if (fabs(elems[i]) >= COIN_INDEXED_TINY_ELEMENT) {
1107       elements_[nElements_] = elems[i];
1108       indices_[nElements_++] = indexValue;
1109     }
1110   }
1111 }
1112 
1113 //-----------------------------------------------------------------------------
1114 
gutsOfSetConstant(int size,const int * inds,double value)1115 void CoinIndexedVector::gutsOfSetConstant(int size,
1116   const int *inds, double value)
1117 {
1118 
1119   assert(!packedMode_);
1120 #ifndef COIN_FAST_CODE
1121   if (size < 0)
1122     throw CoinError("negative number of indices", "setConstant", "CoinIndexedVector");
1123 #endif
1124   // find largest
1125   int i;
1126   int maxIndex = -1;
1127   for (i = 0; i < size; i++) {
1128     int indexValue = inds[i];
1129 #ifndef COIN_FAST_CODE
1130     if (indexValue < 0)
1131       throw CoinError("negative index", "setConstant", "CoinIndexedVector");
1132 #endif
1133     if (maxIndex < indexValue)
1134       maxIndex = indexValue;
1135   }
1136 
1137   reserve(maxIndex + 1);
1138   nElements_ = 0;
1139   int numberDuplicates = 0;
1140   // elements_ array is all zero
1141   bool needClean = false;
1142   for (i = 0; i < size; i++) {
1143     int indexValue = inds[i];
1144     if (elements_[indexValue] == 0) {
1145       if (fabs(value) >= COIN_INDEXED_TINY_ELEMENT) {
1146         elements_[indexValue] += value;
1147         indices_[nElements_++] = indexValue;
1148       }
1149     } else {
1150       numberDuplicates++;
1151       elements_[indexValue] += value;
1152       if (fabs(elements_[indexValue]) < COIN_INDEXED_TINY_ELEMENT)
1153         needClean = true; // need to go through again
1154     }
1155   }
1156   if (needClean) {
1157     // go through again
1158     size = nElements_;
1159     nElements_ = 0;
1160     for (i = 0; i < size; i++) {
1161       int indexValue = indices_[i];
1162       double value = elements_[indexValue];
1163       if (fabs(value) >= COIN_INDEXED_TINY_ELEMENT) {
1164         indices_[nElements_++] = indexValue;
1165       } else {
1166         elements_[indexValue] = 0.0;
1167       }
1168     }
1169   }
1170   if (numberDuplicates)
1171     throw CoinError("duplicate index", "setConstant", "CoinIndexedVector");
1172 }
1173 
1174 //#############################################################################
1175 // Append a CoinIndexedVector to the end
append(const CoinIndexedVector & caboose)1176 void CoinIndexedVector::append(const CoinIndexedVector &caboose)
1177 {
1178   const int cs = caboose.getNumElements();
1179 
1180   const int *cind = caboose.getIndices();
1181   const double *celem = caboose.denseVector();
1182   int maxIndex = -1;
1183   int i;
1184   for (i = 0; i < cs; i++) {
1185     int indexValue = cind[i];
1186 #ifndef COIN_FAST_CODE
1187     if (indexValue < 0)
1188       throw CoinError("negative index", "append", "CoinIndexedVector");
1189 #endif
1190     if (maxIndex < indexValue)
1191       maxIndex = indexValue;
1192   }
1193   reserve(maxIndex + 1);
1194   bool needClean = false;
1195   int numberDuplicates = 0;
1196   for (i = 0; i < cs; i++) {
1197     int indexValue = cind[i];
1198     if (elements_[indexValue]) {
1199       numberDuplicates++;
1200       elements_[indexValue] += celem[indexValue];
1201       if (fabs(elements_[indexValue]) < COIN_INDEXED_TINY_ELEMENT)
1202         needClean = true; // need to go through again
1203     } else {
1204       if (fabs(celem[indexValue]) >= COIN_INDEXED_TINY_ELEMENT) {
1205         elements_[indexValue] = celem[indexValue];
1206         indices_[nElements_++] = indexValue;
1207       }
1208     }
1209   }
1210   if (needClean) {
1211     // go through again
1212     int size = nElements_;
1213     nElements_ = 0;
1214     for (i = 0; i < size; i++) {
1215       int indexValue = indices_[i];
1216       double value = elements_[indexValue];
1217       if (fabs(value) >= COIN_INDEXED_TINY_ELEMENT) {
1218         indices_[nElements_++] = indexValue;
1219       } else {
1220         elements_[indexValue] = 0.0;
1221       }
1222     }
1223   }
1224   if (numberDuplicates)
1225     throw CoinError("duplicate index", "append", "CoinIndexedVector");
1226 }
1227 // Append a CoinIndexedVector to the end and modify indices
append(CoinIndexedVector & other,int adjustIndex,bool zapElements)1228 void CoinIndexedVector::append(CoinIndexedVector &other, int adjustIndex, bool zapElements /*,double multiplier*/)
1229 {
1230   const int cs = other.nElements_;
1231   const int *cind = other.indices_;
1232   double *celem = other.elements_;
1233   int *newInd = indices_ + nElements_;
1234   if (packedMode_) {
1235     double *newEls = elements_ + nElements_;
1236     if (zapElements) {
1237       if (other.packedMode_) {
1238         for (int i = 0; i < cs; i++) {
1239           newInd[i] = cind[i] + adjustIndex;
1240           newEls[i] = celem[i] /* *multiplier*/;
1241           celem[i] = 0.0;
1242         }
1243       } else {
1244         for (int i = 0; i < cs; i++) {
1245           int k = cind[i];
1246           newInd[i] = k + adjustIndex;
1247           newEls[i] = celem[k] /* *multiplier*/;
1248           celem[k] = 0.0;
1249         }
1250       }
1251     } else {
1252       if (other.packedMode_) {
1253         for (int i = 0; i < cs; i++) {
1254           newEls[i] = celem[i] /* *multiplier*/;
1255           newInd[i] = cind[i] + adjustIndex;
1256         }
1257       } else {
1258         for (int i = 0; i < cs; i++) {
1259           int k = cind[i];
1260           newInd[i] = k + adjustIndex;
1261           newEls[i] = celem[k] /* *multiplier*/;
1262         }
1263       }
1264     }
1265   } else {
1266     double *newEls = elements_ + adjustIndex;
1267     if (zapElements) {
1268       if (other.packedMode_) {
1269         for (int i = 0; i < cs; i++) {
1270           int k = cind[i];
1271           newInd[i] = k + adjustIndex;
1272           newEls[k] = celem[i] /* *multiplier*/;
1273           celem[i] = 0.0;
1274         }
1275       } else {
1276         for (int i = 0; i < cs; i++) {
1277           int k = cind[i];
1278           newInd[i] = k + adjustIndex;
1279           newEls[k] = celem[k] /* *multiplier*/;
1280           celem[k] = 0.0;
1281         }
1282       }
1283     } else {
1284       if (other.packedMode_) {
1285         for (int i = 0; i < cs; i++) {
1286           int k = cind[i];
1287           newInd[i] = k + adjustIndex;
1288           newEls[k] = celem[i] /* *multiplier*/;
1289         }
1290       } else {
1291         for (int i = 0; i < cs; i++) {
1292           int k = cind[i];
1293           newInd[i] = k + adjustIndex;
1294           newEls[k] = celem[k] /* *multiplier*/;
1295         }
1296       }
1297     }
1298   }
1299   nElements_ += cs;
1300   if (zapElements)
1301     other.nElements_ = 0;
1302 }
1303 #ifndef CLP_NO_VECTOR
1304 /* Equal. Returns true if vectors have same length and corresponding
1305    element of each vector is equal. */
operator ==(const CoinPackedVectorBase & rhs) const1306 bool CoinIndexedVector::operator==(const CoinPackedVectorBase &rhs) const
1307 {
1308   const int cs = rhs.getNumElements();
1309 
1310   const int *cind = rhs.getIndices();
1311   const double *celem = rhs.getElements();
1312   if (nElements_ != cs)
1313     return false;
1314   int i;
1315   bool okay = true;
1316   for (i = 0; i < cs; i++) {
1317     int iRow = cind[i];
1318     if (celem[i] != elements_[iRow]) {
1319       okay = false;
1320       break;
1321     }
1322   }
1323   return okay;
1324 }
1325 // Not equal
operator !=(const CoinPackedVectorBase & rhs) const1326 bool CoinIndexedVector::operator!=(const CoinPackedVectorBase &rhs) const
1327 {
1328   const int cs = rhs.getNumElements();
1329 
1330   const int *cind = rhs.getIndices();
1331   const double *celem = rhs.getElements();
1332   if (nElements_ != cs)
1333     return true;
1334   int i;
1335   bool okay = false;
1336   for (i = 0; i < cs; i++) {
1337     int iRow = cind[i];
1338     if (celem[i] != elements_[iRow]) {
1339       okay = true;
1340       break;
1341     }
1342   }
1343   return okay;
1344 }
1345 #endif
1346 // Equal with a tolerance (returns -1 or position of inequality).
isApproximatelyEqual(const CoinIndexedVector & rhs,double tolerance) const1347 int CoinIndexedVector::isApproximatelyEqual(const CoinIndexedVector &rhs, double tolerance) const
1348 {
1349   CoinIndexedVector tempA(*this);
1350   CoinIndexedVector tempB(rhs);
1351   int *cind = tempB.indices_;
1352   double *celem = tempB.elements_;
1353   double *elem = tempA.elements_;
1354   int cs = tempB.nElements_;
1355   int bad = -1;
1356   CoinRelFltEq eq(tolerance);
1357   if (!packedMode_ && !tempB.packedMode_) {
1358     for (int i = 0; i < cs; i++) {
1359       int iRow = cind[i];
1360       if (!eq(celem[iRow], elem[iRow])) {
1361         bad = iRow;
1362         break;
1363       } else {
1364         celem[iRow] = elem[iRow] = 0.0;
1365       }
1366     }
1367     cs = tempA.nElements_;
1368     cind = tempA.indices_;
1369     for (int i = 0; i < cs; i++) {
1370       int iRow = cind[i];
1371       if (!eq(celem[iRow], elem[iRow])) {
1372         bad = iRow;
1373         break;
1374       } else {
1375         celem[iRow] = elem[iRow] = 0.0;
1376       }
1377     }
1378   } else if (packedMode_ && tempB.packedMode_) {
1379     double *celem2 = rhs.elements_;
1380     memset(celem, 0, CoinMin(capacity_, tempB.capacity_) * sizeof(double));
1381     for (int i = 0; i < cs; i++) {
1382       int iRow = cind[i];
1383       celem[iRow] = celem2[i];
1384     }
1385     for (int i = 0; i < cs; i++) {
1386       int iRow = cind[i];
1387       if (!eq(celem[iRow], elem[i])) {
1388         bad = iRow;
1389         break;
1390       } else {
1391         celem[iRow] = elem[i] = 0.0;
1392       }
1393     }
1394   } else {
1395     double *celem2 = elem;
1396     double *celem3 = celem;
1397     if (packedMode_) {
1398       celem2 = celem;
1399       celem3 = elem;
1400     }
1401     for (int i = 0; i < cs; i++) {
1402       int iRow = cind[i];
1403       if (!eq(celem2[iRow], celem3[i])) {
1404         bad = iRow;
1405         break;
1406       } else {
1407         celem2[iRow] = celem3[i] = 0.0;
1408       }
1409     }
1410   }
1411   if (bad < 0) {
1412     for (int i = 0; i < tempA.capacity_; i++) {
1413       if (elem[i]) {
1414         if (fabs(elem[i]) > tolerance) {
1415           bad = i;
1416           break;
1417         }
1418       }
1419     }
1420     for (int i = 0; i < tempB.capacity_; i++) {
1421       if (celem[i]) {
1422         if (fabs(celem[i]) > tolerance) {
1423           bad = i;
1424           break;
1425         }
1426       }
1427     }
1428   }
1429   return bad;
1430 }
1431 /* Equal. Returns true if vectors have same length and corresponding
1432    element of each vector is equal. */
operator ==(const CoinIndexedVector & rhs) const1433 bool CoinIndexedVector::operator==(const CoinIndexedVector &rhs) const
1434 {
1435   const int cs = rhs.nElements_;
1436 
1437   const int *cind = rhs.indices_;
1438   const double *celem = rhs.elements_;
1439   if (nElements_ != cs)
1440     return false;
1441   bool okay = true;
1442   CoinRelFltEq eq(1.0e-8);
1443   if (!packedMode_ && !rhs.packedMode_) {
1444     for (int i = 0; i < cs; i++) {
1445       int iRow = cind[i];
1446       if (!eq(celem[iRow], elements_[iRow])) {
1447         okay = false;
1448         break;
1449       }
1450     }
1451   } else if (packedMode_ && rhs.packedMode_) {
1452     double *temp = new double[CoinMax(capacity_, rhs.capacity_)];
1453     memset(temp, 0, CoinMax(capacity_, rhs.capacity_) * sizeof(double));
1454     for (int i = 0; i < cs; i++) {
1455       int iRow = cind[i];
1456       temp[iRow] = celem[i];
1457     }
1458     for (int i = 0; i < cs; i++) {
1459       int iRow = cind[i];
1460       if (!eq(temp[iRow], elements_[i])) {
1461         okay = false;
1462         break;
1463       }
1464     }
1465   } else {
1466     const double *celem2 = elements_;
1467     if (packedMode_) {
1468       celem2 = celem;
1469       celem = elements_;
1470     }
1471     for (int i = 0; i < cs; i++) {
1472       int iRow = cind[i];
1473       if (!eq(celem2[iRow], celem[i])) {
1474         okay = false;
1475         break;
1476       }
1477     }
1478   }
1479   return okay;
1480 }
1481 /// Not equal
operator !=(const CoinIndexedVector & rhs) const1482 bool CoinIndexedVector::operator!=(const CoinIndexedVector &rhs) const
1483 {
1484   const int cs = rhs.nElements_;
1485 
1486   const int *cind = rhs.indices_;
1487   const double *celem = rhs.elements_;
1488   if (nElements_ != cs)
1489     return true;
1490   int i;
1491   bool okay = false;
1492   for (i = 0; i < cs; i++) {
1493     int iRow = cind[i];
1494     if (celem[iRow] != elements_[iRow]) {
1495       okay = true;
1496       break;
1497     }
1498   }
1499   return okay;
1500 }
1501 // Get value of maximum index
getMaxIndex() const1502 int CoinIndexedVector::getMaxIndex() const
1503 {
1504   int maxIndex = -COIN_INT_MAX;
1505   int i;
1506   for (i = 0; i < nElements_; i++)
1507     maxIndex = CoinMax(maxIndex, indices_[i]);
1508   return maxIndex;
1509 }
1510 // Get value of minimum index
getMinIndex() const1511 int CoinIndexedVector::getMinIndex() const
1512 {
1513   int minIndex = COIN_INT_MAX;
1514   int i;
1515   for (i = 0; i < nElements_; i++)
1516     minIndex = CoinMin(minIndex, indices_[i]);
1517   return minIndex;
1518 }
1519 // Scan dense region and set up indices
scan()1520 int CoinIndexedVector::scan()
1521 {
1522   nElements_ = 0;
1523   return scan(0, capacity_);
1524 }
1525 // Scan dense region from start to < end and set up indices
scan(int start,int end)1526 int CoinIndexedVector::scan(int start, int end)
1527 {
1528   assert(!packedMode_);
1529   end = CoinMin(end, capacity_);
1530   start = CoinMax(start, 0);
1531   int i;
1532   int number = 0;
1533   int *indices = indices_ + nElements_;
1534   for (i = start; i < end; i++)
1535     if (elements_[i])
1536       indices[number++] = i;
1537   nElements_ += number;
1538   return number;
1539 }
1540 // Scan dense region and set up indices with tolerance
scan(double tolerance)1541 int CoinIndexedVector::scan(double tolerance)
1542 {
1543   nElements_ = 0;
1544 #if ABOCA_LITE_FACTORIZATION == 0
1545   return scan(0, capacity_, tolerance);
1546 #else
1547   return scan(0, capacity_ & 0x7fffffff, tolerance);
1548 #endif
1549 }
1550 // Scan dense region from start to < end and set up indices with tolerance
scan(int start,int end,double tolerance)1551 int CoinIndexedVector::scan(int start, int end, double tolerance)
1552 {
1553   assert(!packedMode_);
1554 #if ABOCA_LITE_FACTORIZATION == 0
1555   end = CoinMin(end, capacity_);
1556 #else
1557   end = CoinMin(end, capacity_ & 0x7fffffff);
1558 #endif
1559   start = CoinMax(start, 0);
1560   int i;
1561   int number = 0;
1562   int *indices = indices_ + nElements_;
1563   for (i = start; i < end; i++) {
1564     double value = elements_[i];
1565     if (value) {
1566       if (fabs(value) >= tolerance)
1567         indices[number++] = i;
1568       else
1569         elements_[i] = 0.0;
1570     }
1571   }
1572   nElements_ += number;
1573   return number;
1574 }
1575 // These pack down
cleanAndPack(double tolerance)1576 int CoinIndexedVector::cleanAndPack(double tolerance)
1577 {
1578   if (!packedMode_) {
1579     int number = nElements_;
1580     int i;
1581     nElements_ = 0;
1582     for (i = 0; i < number; i++) {
1583       int indexValue = indices_[i];
1584       double value = elements_[indexValue];
1585       elements_[indexValue] = 0.0;
1586       if (fabs(value) >= tolerance) {
1587         elements_[nElements_] = value;
1588         indices_[nElements_++] = indexValue;
1589       }
1590     }
1591     packedMode_ = true;
1592   }
1593   return nElements_;
1594 }
1595 // These pack down
cleanAndPackSafe(double tolerance)1596 int CoinIndexedVector::cleanAndPackSafe(double tolerance)
1597 {
1598   int number = nElements_;
1599   if (number) {
1600     int i;
1601     nElements_ = 0;
1602     assert(!packedMode_);
1603     double *temp = NULL;
1604     bool gotMemory;
1605     if (number * 3 < capacity_ - 3 - 9999999) {
1606       // can find room without new
1607       gotMemory = false;
1608       // But may need to align on 8 byte boundary
1609       char *tempC = reinterpret_cast< char * >(indices_ + number);
1610       CoinInt64 xx = reinterpret_cast< CoinInt64 >(tempC);
1611       CoinInt64 iBottom = xx & 7;
1612       if (iBottom)
1613         tempC += 8 - iBottom;
1614       temp = reinterpret_cast< double * >(tempC);
1615       xx = reinterpret_cast< CoinInt64 >(temp);
1616       iBottom = xx & 7;
1617       assert(!iBottom);
1618     } else {
1619       // might be better to do complete scan
1620       gotMemory = true;
1621       temp = new double[number];
1622     }
1623     for (i = 0; i < number; i++) {
1624       int indexValue = indices_[i];
1625       double value = elements_[indexValue];
1626       elements_[indexValue] = 0.0;
1627       if (fabs(value) >= tolerance) {
1628         temp[nElements_] = value;
1629         indices_[nElements_++] = indexValue;
1630       }
1631     }
1632     CoinMemcpyN(temp, nElements_, elements_);
1633     if (gotMemory)
1634       delete[] temp;
1635     packedMode_ = true;
1636   }
1637   return nElements_;
1638 }
1639 // Scan dense region and set up indices
scanAndPack()1640 int CoinIndexedVector::scanAndPack()
1641 {
1642   nElements_ = 0;
1643   return scanAndPack(0, capacity_);
1644 }
1645 // Scan dense region from start to < end and set up indices
scanAndPack(int start,int end)1646 int CoinIndexedVector::scanAndPack(int start, int end)
1647 {
1648   assert(!packedMode_);
1649   end = CoinMin(end, capacity_);
1650   start = CoinMax(start, 0);
1651   int i;
1652   int number = 0;
1653   int *indices = indices_ + nElements_;
1654   for (i = start; i < end; i++) {
1655     double value = elements_[i];
1656     elements_[i] = 0.0;
1657     if (value) {
1658       elements_[number] = value;
1659       indices[number++] = i;
1660     }
1661   }
1662   nElements_ += number;
1663   packedMode_ = true;
1664   return number;
1665 }
1666 // Scan dense region and set up indices with tolerance
scanAndPack(double tolerance)1667 int CoinIndexedVector::scanAndPack(double tolerance)
1668 {
1669   nElements_ = 0;
1670   return scanAndPack(0, capacity_, tolerance);
1671 }
1672 // Scan dense region from start to < end and set up indices with tolerance
scanAndPack(int start,int end,double tolerance)1673 int CoinIndexedVector::scanAndPack(int start, int end, double tolerance)
1674 {
1675   assert(!packedMode_);
1676   end = CoinMin(end, capacity_);
1677   start = CoinMax(start, 0);
1678   int i;
1679   int number = 0;
1680   int *indices = indices_ + nElements_;
1681   for (i = start; i < end; i++) {
1682     double value = elements_[i];
1683     elements_[i] = 0.0;
1684     if (fabs(value) >= tolerance) {
1685       elements_[number] = value;
1686       indices[number++] = i;
1687     }
1688   }
1689   nElements_ += number;
1690   packedMode_ = true;
1691   return number;
1692 }
1693 // This is mainly for testing - goes from packed to indexed
expand()1694 void CoinIndexedVector::expand()
1695 {
1696   if (nElements_ && packedMode_) {
1697     double *temp = new double[capacity_];
1698     int i;
1699     for (i = 0; i < nElements_; i++)
1700       temp[indices_[i]] = elements_[i];
1701     CoinZeroN(elements_, nElements_);
1702     for (i = 0; i < nElements_; i++) {
1703       int iRow = indices_[i];
1704       elements_[iRow] = temp[iRow];
1705     }
1706     delete[] temp;
1707   }
1708   packedMode_ = false;
1709 }
1710 // Create packed array
createPacked(int number,const int * indices,const double * elements)1711 void CoinIndexedVector::createPacked(int number, const int *indices,
1712   const double *elements)
1713 {
1714   nElements_ = number;
1715   packedMode_ = true;
1716   CoinMemcpyN(indices, number, indices_);
1717   CoinMemcpyN(elements, number, elements_);
1718 }
1719 // Create packed array
createUnpacked(int number,const int * indices,const double * elements)1720 void CoinIndexedVector::createUnpacked(int number, const int *indices,
1721   const double *elements)
1722 {
1723   nElements_ = number;
1724   packedMode_ = false;
1725   for (int i = 0; i < nElements_; i++) {
1726     int iRow = indices[i];
1727     indices_[i] = iRow;
1728     elements_[iRow] = elements[i];
1729   }
1730 }
1731 // Create unpacked singleton
createOneUnpackedElement(int index,double element)1732 void CoinIndexedVector::createOneUnpackedElement(int index, double element)
1733 {
1734   nElements_ = 1;
1735   packedMode_ = false;
1736   indices_[0] = index;
1737   elements_[index] = element;
1738 }
1739 //  Print out
print() const1740 void CoinIndexedVector::print() const
1741 {
1742   printf("Vector has %d elements (%spacked mode)\n", nElements_, packedMode_ ? "" : "un");
1743   for (int i = 0; i < nElements_; i++) {
1744     if (i && (i % 5 == 0))
1745       printf("\n");
1746     int index = indices_[i];
1747     double value = packedMode_ ? elements_[i] : elements_[index];
1748     printf(" (%d,%g)", index, value);
1749   }
1750   printf("\n");
1751 }
1752 
1753 // Zero out array
clear()1754 void CoinArrayWithLength::clear()
1755 {
1756   assert((size_ > 0 && array_) || !array_);
1757   memset(array_, 0, size_);
1758 }
1759 // Get array with alignment
getArray(CoinBigIndex size)1760 void CoinArrayWithLength::getArray(CoinBigIndex size)
1761 {
1762   if (size > 0) {
1763     if (alignment_ > 2) {
1764       offset_ = 1 << alignment_;
1765     } else {
1766       offset_ = 0;
1767     }
1768     assert(size > 0);
1769     char *array = new char[size + offset_];
1770     if (offset_) {
1771       // need offset
1772       CoinInt64 xx = reinterpret_cast< CoinInt64 >(array);
1773       int iBottom = static_cast< int >(xx & ((offset_ - 1)));
1774       if (iBottom)
1775         offset_ = offset_ - iBottom;
1776       else
1777         offset_ = 0;
1778       array_ = array + offset_;
1779       ;
1780     } else {
1781       array_ = array;
1782     }
1783     if (size_ != -1)
1784       size_ = size;
1785   } else {
1786     array_ = NULL;
1787   }
1788 }
1789 // Get rid of array with alignment
conditionalDelete()1790 void CoinArrayWithLength::conditionalDelete()
1791 {
1792   if (size_ == -1) {
1793     char *charArray = reinterpret_cast< char * >(array_);
1794     if (charArray)
1795       delete[](charArray - offset_);
1796     array_ = NULL;
1797   } else if (size_ >= 0) {
1798     size_ = -size_ - 2;
1799   }
1800 }
1801 // Really get rid of array with alignment
reallyFreeArray()1802 void CoinArrayWithLength::reallyFreeArray()
1803 {
1804   char *charArray = reinterpret_cast< char * >(array_);
1805   if (charArray)
1806     delete[](charArray - offset_);
1807   array_ = NULL;
1808   size_ = -1;
1809 }
1810 // Get enough space
getCapacity(CoinBigIndex numberBytes,CoinBigIndex numberNeeded)1811 void CoinArrayWithLength::getCapacity(CoinBigIndex numberBytes, CoinBigIndex numberNeeded)
1812 {
1813   CoinBigIndex k = capacity();
1814   if (k < numberBytes) {
1815     CoinBigIndex saveSize = size_;
1816     reallyFreeArray();
1817     size_ = saveSize;
1818     getArray(CoinMax(numberBytes, numberNeeded));
1819   } else if (size_ < 0) {
1820     size_ = -size_ - 2;
1821   }
1822 }
1823 /* Alternate Constructor - length in bytes
1824    mode -  0 size_ set to size
1825    >0 size_ set to size and zeroed
1826    if size<=0 just does alignment
1827    If abs(mode) >2 then align on that as power of 2
1828 */
CoinArrayWithLength(CoinBigIndex size,int mode)1829 CoinArrayWithLength::CoinArrayWithLength(CoinBigIndex size, int mode)
1830 {
1831   alignment_ = abs(mode);
1832   size_ = size;
1833   getArray(size);
1834   if (mode > 0 && array_)
1835     memset(array_, 0, size);
1836 }
~CoinArrayWithLength()1837 CoinArrayWithLength::~CoinArrayWithLength()
1838 {
1839   if (array_)
1840     delete[](array_ - offset_);
1841 }
1842 // Conditionally gets new array
1843 char *
conditionalNew(CoinBigIndex sizeWanted)1844 CoinArrayWithLength::conditionalNew(CoinBigIndex sizeWanted)
1845 {
1846   if (size_ == -1) {
1847     getCapacity(static_cast< int >(sizeWanted));
1848   } else {
1849     int newSize = static_cast< int >(sizeWanted * 101 / 100) + 64;
1850     // round to multiple of 16
1851     newSize -= newSize & 15;
1852     getCapacity(static_cast< int >(sizeWanted), newSize);
1853   }
1854   return array_;
1855 }
1856 /* Copy constructor. */
CoinArrayWithLength(const CoinArrayWithLength & rhs)1857 CoinArrayWithLength::CoinArrayWithLength(const CoinArrayWithLength &rhs)
1858 {
1859   assert(capacity() >= 0);
1860   getArray(rhs.capacity());
1861   if (size_ > 0)
1862     CoinMemcpyN(rhs.array_, size_, array_);
1863 }
1864 
1865 /* Copy constructor.2 */
CoinArrayWithLength(const CoinArrayWithLength * rhs)1866 CoinArrayWithLength::CoinArrayWithLength(const CoinArrayWithLength *rhs)
1867 {
1868   assert(rhs->capacity() >= 0);
1869   size_ = rhs->size_;
1870   getArray(rhs->capacity());
1871   if (size_ > 0)
1872     CoinMemcpyN(rhs->array_, size_, array_);
1873 }
1874 /* Assignment operator. */
1875 CoinArrayWithLength &
operator =(const CoinArrayWithLength & rhs)1876 CoinArrayWithLength::operator=(const CoinArrayWithLength &rhs)
1877 {
1878   if (this != &rhs) {
1879     assert(rhs.size_ != -1 || !rhs.array_);
1880     if (rhs.size_ == -1) {
1881       reallyFreeArray();
1882     } else {
1883       getCapacity(rhs.size_);
1884       if (size_ > 0)
1885         CoinMemcpyN(rhs.array_, size_, array_);
1886     }
1887   }
1888   return *this;
1889 }
1890 /* Assignment with length (if -1 use internal length) */
copy(const CoinArrayWithLength & rhs,int numberBytes)1891 void CoinArrayWithLength::copy(const CoinArrayWithLength &rhs, int numberBytes)
1892 {
1893   if (numberBytes == -1 || numberBytes <= rhs.capacity()) {
1894     CoinArrayWithLength::operator=(rhs);
1895   } else {
1896     assert(numberBytes >= 0);
1897     getCapacity(numberBytes);
1898     if (rhs.array_)
1899       CoinMemcpyN(rhs.array_, numberBytes, array_);
1900   }
1901 }
1902 /* Assignment with length - does not copy */
allocate(const CoinArrayWithLength & rhs,CoinBigIndex numberBytes)1903 void CoinArrayWithLength::allocate(const CoinArrayWithLength &rhs, CoinBigIndex numberBytes)
1904 {
1905   if (numberBytes == -1 || numberBytes <= rhs.capacity()) {
1906     assert(rhs.size_ != -1 || !rhs.array_);
1907     if (rhs.size_ == -1) {
1908       reallyFreeArray();
1909     } else {
1910       getCapacity(rhs.size_);
1911     }
1912   } else {
1913     assert(numberBytes >= 0);
1914     if (size_ == -1) {
1915       delete[] array_;
1916       array_ = NULL;
1917     } else {
1918       size_ = -1;
1919     }
1920     if (rhs.size_ >= 0)
1921       size_ = numberBytes;
1922     assert(numberBytes >= 0);
1923     assert(!array_);
1924     if (numberBytes)
1925       array_ = new char[numberBytes];
1926   }
1927 }
1928 // Does what is needed to set persistence
setPersistence(int flag,int currentLength)1929 void CoinArrayWithLength::setPersistence(int flag, int currentLength)
1930 {
1931   if (flag) {
1932     if (size_ == -1) {
1933       if (currentLength && array_) {
1934         size_ = currentLength;
1935       } else {
1936         conditionalDelete();
1937         size_ = 0;
1938         array_ = NULL;
1939       }
1940     }
1941   } else {
1942     size_ = -1;
1943   }
1944 }
1945 // Swaps memory between two members
swap(CoinArrayWithLength & other)1946 void CoinArrayWithLength::swap(CoinArrayWithLength &other)
1947 {
1948 #ifdef COIN_DEVELOP
1949   if (!(size_ == other.size_ || size_ == -1 || other.size_ == -1))
1950     printf("Two arrays have sizes - %d and %d\n", size_, other.size_);
1951 #endif
1952   assert(alignment_ == other.alignment_);
1953   char *swapArray = other.array_;
1954   other.array_ = array_;
1955   array_ = swapArray;
1956   CoinBigIndex swapSize = other.size_;
1957   other.size_ = size_;
1958   size_ = swapSize;
1959   int swapOffset = other.offset_;
1960   other.offset_ = offset_;
1961   offset_ = swapOffset;
1962 }
1963 // Extend a persistent array keeping data (size in bytes)
extend(int newSize)1964 void CoinArrayWithLength::extend(int newSize)
1965 {
1966   //assert (newSize>=capacity()&&capacity()>=0);
1967   assert(size_ >= 0); // not much point otherwise
1968   if (newSize > size_) {
1969     char *temp = array_;
1970     getArray(newSize);
1971     if (temp) {
1972       CoinMemcpyN(array_, size_, temp);
1973       delete[](temp - offset_);
1974     }
1975     size_ = newSize;
1976   }
1977 }
1978 
1979 /* Default constructor */
CoinPartitionedVector()1980 CoinPartitionedVector::CoinPartitionedVector()
1981   : CoinIndexedVector()
1982 {
1983   memset(startPartition_, 0, ((&numberPartitions_ - startPartition_) + 1) * sizeof(int));
1984 }
1985 /* Copy constructor. */
CoinPartitionedVector(const CoinPartitionedVector & rhs)1986 CoinPartitionedVector::CoinPartitionedVector(const CoinPartitionedVector &rhs)
1987   : CoinIndexedVector(rhs)
1988 {
1989   memcpy(startPartition_, rhs.startPartition_, ((&numberPartitions_ - startPartition_) + 1) * sizeof(int));
1990 }
1991 /* Copy constructor.2 */
CoinPartitionedVector(const CoinPartitionedVector * rhs)1992 CoinPartitionedVector::CoinPartitionedVector(const CoinPartitionedVector *rhs)
1993   : CoinIndexedVector(rhs)
1994 {
1995   memcpy(startPartition_, rhs->startPartition_, ((&numberPartitions_ - startPartition_) + 1) * sizeof(int));
1996 }
1997 /* Assignment operator. */
operator =(const CoinPartitionedVector & rhs)1998 CoinPartitionedVector &CoinPartitionedVector::operator=(const CoinPartitionedVector &rhs)
1999 {
2000   if (this != &rhs) {
2001     CoinIndexedVector::operator=(rhs);
2002     memcpy(startPartition_, rhs.startPartition_, ((&numberPartitions_ - startPartition_) + 1) * sizeof(int));
2003   }
2004   return *this;
2005 }
2006 /* Destructor */
~CoinPartitionedVector()2007 CoinPartitionedVector::~CoinPartitionedVector()
2008 {
2009 }
2010 // Add up number of elements in partitions
computeNumberElements()2011 void CoinPartitionedVector::computeNumberElements()
2012 {
2013   if (numberPartitions_) {
2014     assert(packedMode_);
2015     int n = 0;
2016     for (int i = 0; i < numberPartitions_; i++)
2017       n += numberElementsPartition_[i];
2018     nElements_ = n;
2019   }
2020 }
2021 // Add up number of elements in partitions and pack and get rid of partitions
compact()2022 void CoinPartitionedVector::compact()
2023 {
2024   if (numberPartitions_) {
2025     int n = numberElementsPartition_[0];
2026     numberElementsPartition_[0] = 0;
2027     for (int i = 1; i < numberPartitions_; i++) {
2028       int nThis = numberElementsPartition_[i];
2029       int start = startPartition_[i];
2030       memmove(indices_ + n, indices_ + start, nThis * sizeof(int));
2031       memmove(elements_ + n, elements_ + start, nThis * sizeof(double));
2032       n += nThis;
2033     }
2034     nElements_ = n;
2035     // clean up
2036     for (int i = 1; i < numberPartitions_; i++) {
2037       int nThis = numberElementsPartition_[i];
2038       int start = startPartition_[i];
2039       numberElementsPartition_[i] = 0;
2040       int end = nThis + start;
2041       if (nElements_ < end) {
2042         int offset = CoinMax(nElements_ - start, 0);
2043         start += offset;
2044         nThis -= offset;
2045         memset(elements_ + start, 0, nThis * sizeof(double));
2046       }
2047     }
2048     packedMode_ = true;
2049     numberPartitions_ = 0;
2050   }
2051 }
2052 /* Reserve space.
2053  */
reserve(int n)2054 void CoinPartitionedVector::reserve(int n)
2055 {
2056   CoinIndexedVector::reserve(n);
2057   memset(startPartition_, 0, ((&numberPartitions_ - startPartition_) + 1) * sizeof(int));
2058   startPartition_[1] = capacity_; // for safety
2059 }
2060 // Setup partitions (needs end as well)
setPartitions(int number,const int * starts)2061 void CoinPartitionedVector::setPartitions(int number, const int *starts)
2062 {
2063   if (number) {
2064     packedMode_ = true;
2065     assert(number <= COIN_PARTITIONS);
2066     memcpy(startPartition_, starts, (number + 1) * sizeof(int));
2067     numberPartitions_ = number;
2068 #ifndef NDEBUG
2069     assert(startPartition_[0] == 0);
2070     int last = -1;
2071     for (int i = 0; i < numberPartitions_; i++) {
2072       assert(startPartition_[i] >= last);
2073       assert(numberElementsPartition_[i] == 0);
2074       last = startPartition_[i];
2075     }
2076     assert(startPartition_[numberPartitions_] >= last && startPartition_[numberPartitions_] <= capacity_);
2077 #endif
2078   } else {
2079     clearAndReset();
2080   }
2081 }
2082 // Reset the vector (as if were just created an empty vector). Gets rid of partitions
clearAndReset()2083 void CoinPartitionedVector::clearAndReset()
2084 {
2085   if (numberPartitions_) {
2086     assert(packedMode_ || !nElements_);
2087     for (int i = 0; i < numberPartitions_; i++) {
2088       int n = numberElementsPartition_[i];
2089       memset(elements_ + startPartition_[i], 0, n * sizeof(double));
2090       numberElementsPartition_[i] = 0;
2091     }
2092   } else {
2093     memset(elements_, 0, nElements_ * sizeof(double));
2094   }
2095   nElements_ = 0;
2096   numberPartitions_ = 0;
2097   startPartition_[1] = capacity_;
2098   packedMode_ = false;
2099 }
2100 // Reset the vector (as if were just created an empty vector). Keeps partitions
clearAndKeep()2101 void CoinPartitionedVector::clearAndKeep()
2102 {
2103   assert(packedMode_);
2104   for (int i = 0; i < numberPartitions_; i++) {
2105     int n = numberElementsPartition_[i];
2106     memset(elements_ + startPartition_[i], 0, n * sizeof(double));
2107     numberElementsPartition_[i] = 0;
2108   }
2109   nElements_ = 0;
2110 }
2111 // Clear a partition.
clearPartition(int partition)2112 void CoinPartitionedVector::clearPartition(int partition)
2113 {
2114   assert(packedMode_);
2115   assert(partition < COIN_PARTITIONS);
2116   int n = numberElementsPartition_[partition];
2117   memset(elements_ + startPartition_[partition], 0, n * sizeof(double));
2118   numberElementsPartition_[partition] = 0;
2119 }
2120 #ifndef NDEBUG
2121 // For debug check vector is clear i.e. no elements
checkClear()2122 void CoinPartitionedVector::checkClear()
2123 {
2124 #ifndef NDEBUG
2125   //printf("checkClear %p\n",this);
2126   assert(!nElements_);
2127   //assert(!packedMode_);
2128   int i;
2129   for (i = 0; i < capacity_; i++) {
2130     assert(!elements_[i]);
2131   }
2132 #else
2133   if (nElements_) {
2134     printf("%d nElements_ - checkClear\n", nElements_);
2135     abort();
2136   }
2137   int i;
2138   int n = 0;
2139   int k = -1;
2140   for (i = 0; i < capacity_; i++) {
2141     if (elements_[i]) {
2142       n++;
2143       if (k < 0)
2144         k = i;
2145     }
2146   }
2147   if (n) {
2148     printf("%d elements, first %d - checkClear\n", n, k);
2149     abort();
2150   }
2151 #endif
2152 }
2153 // For debug check vector is clean i.e. elements match indices
checkClean()2154 void CoinPartitionedVector::checkClean()
2155 {
2156   //printf("checkClean %p\n",this);
2157   int i;
2158   if (!nElements_) {
2159     checkClear();
2160   } else {
2161     if (packedMode_) {
2162       for (i = 0; i < nElements_; i++)
2163         assert(elements_[i]);
2164       for (; i < capacity_; i++)
2165         assert(!elements_[i]);
2166     } else {
2167       double *copy = new double[capacity_];
2168       CoinMemcpyN(elements_, capacity_, copy);
2169       for (i = 0; i < nElements_; i++) {
2170         int indexValue = indices_[i];
2171         assert(copy[indexValue]);
2172         copy[indexValue] = 0.0;
2173       }
2174       for (i = 0; i < capacity_; i++)
2175         assert(!copy[i]);
2176       delete[] copy;
2177     }
2178 #ifndef NDEBUG
2179     // check mark array zeroed
2180     char *mark = reinterpret_cast< char * >(indices_ + capacity_);
2181     for (i = 0; i < capacity_; i++) {
2182       assert(!mark[i]);
2183     }
2184 #endif
2185   }
2186 }
2187 #endif
2188 // Scan dense region and set up indices (returns number found)
scan(int partition,double tolerance)2189 int CoinPartitionedVector::scan(int partition, double tolerance)
2190 {
2191   assert(packedMode_);
2192   assert(partition < COIN_PARTITIONS);
2193   int n = 0;
2194   int start = startPartition_[partition];
2195   double *COIN_RESTRICT elements = elements_ + start;
2196   int *COIN_RESTRICT indices = indices_ + start;
2197   int sizePartition = startPartition_[partition + 1] - start;
2198   if (!tolerance) {
2199     for (int i = 0; i < sizePartition; i++) {
2200       double value = elements[i];
2201       if (value) {
2202         elements[i] = 0.0;
2203         elements[n] = value;
2204         indices[n++] = i + start;
2205       }
2206     }
2207   } else {
2208     for (int i = 0; i < sizePartition; i++) {
2209       double value = elements[i];
2210       if (value) {
2211         elements[i] = 0.0;
2212         if (fabs(value) > tolerance) {
2213           elements[n] = value;
2214           indices[n++] = i + start;
2215         }
2216       }
2217     }
2218   }
2219   numberElementsPartition_[partition] = n;
2220   return n;
2221 }
2222 //  Print out
print() const2223 void CoinPartitionedVector::print() const
2224 {
2225   printf("Vector has %d elements (%d partitions)\n", nElements_, numberPartitions_);
2226   if (!numberPartitions_) {
2227     CoinIndexedVector::print();
2228     return;
2229   }
2230   double *tempElements = CoinCopyOfArray(elements_, capacity_);
2231   int *tempIndices = CoinCopyOfArray(indices_, capacity_);
2232   for (int partition = 0; partition < numberPartitions_; partition++) {
2233     printf("Partition %d has %d elements\n", partition, numberElementsPartition_[partition]);
2234     int start = startPartition_[partition];
2235     double *COIN_RESTRICT elements = tempElements + start;
2236     int *COIN_RESTRICT indices = tempIndices + start;
2237     CoinSort_2(indices, indices + numberElementsPartition_[partition], elements);
2238     for (int i = 0; i < numberElementsPartition_[partition]; i++) {
2239       if (i && (i % 5 == 0))
2240         printf("\n");
2241       int index = indices[i];
2242       double value = elements[i];
2243       printf(" (%d,%g)", index, value);
2244     }
2245     printf("\n");
2246   }
2247 }
2248 /* Sort the indexed storage vector (increasing indices). */
sort()2249 void CoinPartitionedVector::sort()
2250 {
2251   assert(packedMode_);
2252   for (int partition = 0; partition < numberPartitions_; partition++) {
2253     int start = startPartition_[partition];
2254     double *COIN_RESTRICT elements = elements_ + start;
2255     int *COIN_RESTRICT indices = indices_ + start;
2256     CoinSort_2(indices, indices + numberElementsPartition_[partition], elements);
2257   }
2258 }
2259 
2260 /* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2
2261 */
2262