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