1/* $Id: CoinIndexedVector.cpp 1448 2011-06-19 15:34:41Z stefan $ */
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
21void
22CoinIndexedVector::clear()
23{
24 if (!packedMode_) {
25 if (3*nElements_<capacity_) {
26 int i=0;
27 if ((nElements_&1)!=0) {
28 elements_[indices_[0]]=0.0;
29 i=1;
30 }
31 for (;i<nElements_;i+=2) {
32 int i0 = indices_[i];
33 int i1 = indices_[i+1];
34 elements_[i0]=0.0;
35 elements_[i1]=0.0;
36 }
37 } else {
38 CoinZeroN(elements_,capacity_);
39 }
40 } else {
41 CoinZeroN(elements_,nElements_);
42 }
43 nElements_ = 0;
44 packedMode_=false;
45 //checkClear();
46}
47
48//#############################################################################
49
50void
51CoinIndexedVector::empty()
52{
53 delete [] indices_;
54 indices_=NULL;
55 if (elements_)
56 delete [] (elements_-offset_);
57 elements_=NULL;
58 nElements_ = 0;
59 capacity_=0;
60 packedMode_=false;
61}
62
63//#############################################################################
64
65CoinIndexedVector &
66CoinIndexedVector::operator=(const CoinIndexedVector & rhs)
67{
68 if (this != &rhs) {
69 clear();
70 packedMode_=rhs.packedMode_;
71 if (!packedMode_)
72 gutsOfSetVector(rhs.capacity_,rhs.nElements_,
73 rhs.indices_, rhs.elements_);
74 else
75 gutsOfSetPackedVector(rhs.capacity_,rhs.nElements_,
76 rhs.indices_, rhs.elements_);
77 }
78 return *this;
79}
80/* Copy the contents of one vector into another. If multiplier is 1
81 It is the equivalent of = but if vectors are same size does
82 not re-allocate memory just clears and copies */
83void
84CoinIndexedVector::copy(const CoinIndexedVector & rhs, double multiplier)
85{
86 if (capacity_==rhs.capacity_) {
87 // can do fast
88 clear();
89 packedMode_=rhs.packedMode_;
90 nElements_=0;
91 if (!packedMode_) {
92 for (int i=0;i<rhs.nElements_;i++) {
93 int index = rhs.indices_[i];
94 double value = rhs.elements_[index]*multiplier;
95 if (fabs(value)<COIN_INDEXED_TINY_ELEMENT)
96 value = COIN_INDEXED_REALLY_TINY_ELEMENT;
97 elements_[index]=value;
98 indices_[nElements_++]=index;
99 }
100 } else {
101 for (int i=0;i<rhs.nElements_;i++) {
102 int index = rhs.indices_[i];
103 double value = rhs.elements_[i]*multiplier;
104 if (fabs(value)<COIN_INDEXED_TINY_ELEMENT)
105 value = COIN_INDEXED_REALLY_TINY_ELEMENT;
106 elements_[nElements_]=value;
107 indices_[nElements_++]=index;
108 }
109 }
110 } else {
111 // do as two operations
112 *this = rhs;
113 (*this) *= multiplier;
114 }
115}
116
117//#############################################################################
118#ifndef CLP_NO_VECTOR
119CoinIndexedVector &
120CoinIndexedVector::operator=(const CoinPackedVectorBase & rhs)
121{
122 clear();
123 packedMode_=false;
124 gutsOfSetVector(rhs.getNumElements(),
125 rhs.getIndices(), rhs.getElements());
126 return *this;
127}
128#endif
129//#############################################################################
130
131void
132CoinIndexedVector::borrowVector(int size, int numberIndices, int* inds, double* elems)
133{
134 empty();
135 capacity_=size;
136 nElements_ = numberIndices;
137 indices_ = inds;
138 elements_ = elems;
139
140 // whole point about borrowvector is that it is lightweight so no testing is done
141}
142
143//#############################################################################
144
145void
146CoinIndexedVector::returnVector()
147{
148 indices_=NULL;
149 elements_=NULL;
150 nElements_ = 0;
151 capacity_=0;
152 packedMode_=false;
153}
154
155//#############################################################################
156
157void
158CoinIndexedVector::setVector(int size, const int * inds, const double * elems)
159{
160 clear();
161 gutsOfSetVector(size, inds, elems);
162}
163//#############################################################################
164
165
166void
167CoinIndexedVector::setVector(int size, int numberIndices, const int * inds, const double * elems)
168{
169 clear();
170 gutsOfSetVector(size, numberIndices, inds, elems);
171}
172//#############################################################################
173
174void
175CoinIndexedVector::setConstant(int size, const int * inds, double value)
176{
177 clear();
178 gutsOfSetConstant(size, inds, value);
179}
180
181//#############################################################################
182
183void
184CoinIndexedVector::setFull(int size, const double * elems)
185{
186 // Clear out any values presently stored
187 clear();
188
189#ifndef COIN_FAST_CODE
190 if (size<0)
191 throw CoinError("negative number of indices", "setFull", "CoinIndexedVector");
192#endif
193 reserve(size);
194 nElements_ = 0;
195 // elements_ array is all zero
196 int i;
197 for (i=0;i<size;i++) {
198 int indexValue=i;
199 if (fabs(elems[i])>=COIN_INDEXED_TINY_ELEMENT) {
200 elements_[indexValue]=elems[i];
201 indices_[nElements_++]=indexValue;
202 }
203 }
204}
205//#############################################################################
206
207/** Access the i'th element of the full storage vector. */
208double &
209CoinIndexedVector::operator[](int index) const
210{
211 assert (!packedMode_);
212#ifndef COIN_FAST_CODE
213 if ( index >= capacity_ )
214 throw CoinError("index >= capacity()", "[]", "CoinIndexedVector");
215 if ( index < 0 )
216 throw CoinError("index < 0" , "[]", "CoinIndexedVector");
217#endif
218 double * where = elements_ + index;
219 return *where;
220
221}
222//#############################################################################
223
224void
225CoinIndexedVector::setElement(int index, double element)
226{
227#ifndef COIN_FAST_CODE
228 if ( index >= nElements_ )
229 throw CoinError("index >= size()", "setElement", "CoinIndexedVector");
230 if ( index < 0 )
231 throw CoinError("index < 0" , "setElement", "CoinIndexedVector");
232#endif
233 elements_[indices_[index]] = element;
234}
235
236//#############################################################################
237
238void
239CoinIndexedVector::insert( int index, double element )
240{
241#ifndef COIN_FAST_CODE
242 if ( index < 0 )
243 throw CoinError("index < 0" , "setElement", "CoinIndexedVector");
244#endif
245 if (index >= capacity_)
246 reserve(index+1);
247#ifndef COIN_FAST_CODE
248 if (elements_[index])
249 throw CoinError("Index already exists", "insert", "CoinIndexedVector");
250#endif
251 indices_[nElements_++] = index;
252 elements_[index] = element;
253}
254
255//#############################################################################
256
257void
258CoinIndexedVector::add( int index, double element )
259{
260#ifndef COIN_FAST_CODE
261 if ( index < 0 )
262 throw CoinError("index < 0" , "setElement", "CoinIndexedVector");
263#endif
264 if (index >= capacity_)
265 reserve(index+1);
266 if (elements_[index]) {
267 element += elements_[index];
268 if (fabs(element)>= COIN_INDEXED_TINY_ELEMENT) {
269 elements_[index] = element;
270 } else {
271 elements_[index] = COIN_INDEXED_REALLY_TINY_ELEMENT;
272 }
273 } else if (fabs(element)>= COIN_INDEXED_TINY_ELEMENT) {
274 indices_[nElements_++] = index;
275 assert (nElements_<=capacity_);
276 elements_[index] = element;
277 }
278}
279
280//#############################################################################
281
282int
283CoinIndexedVector::clean( double tolerance )
284{
285 int number = nElements_;
286 int i;
287 nElements_=0;
288 assert(!packedMode_);
289 for (i=0;i<number;i++) {
290 int indexValue = indices_[i];
291 if (fabs(elements_[indexValue])>=tolerance) {
292 indices_[nElements_++]=indexValue;
293 } else {
294 elements_[indexValue]=0.0;
295 }
296 }
297 return nElements_;
298}
299
300//#############################################################################
301// For debug check vector is clear i.e. no elements
302void CoinIndexedVector::checkClear()
303{
304#ifndef NDEBUG
305 assert(!nElements_);
306 assert(!packedMode_);
307 int i;
308 for (i=0;i<capacity_;i++) {
309 assert(!elements_[i]);
310 }
311 // check mark array zeroed
312 char * mark = reinterpret_cast<char *> (indices_+capacity_);
313 for (i=0;i<capacity_;i++) {
314 assert(!mark[i]);
315 }
316#else
317 if(nElements_) {
318 printf("%d nElements_ - checkClear\n",nElements_);
319 abort();
320 }
321 if(packedMode_) {
322 printf("packed mode when empty - checkClear\n");
323 abort();
324 }
325 int i;
326 int n=0;
327 int k=-1;
328 for (i=0;i<capacity_;i++) {
329 if(elements_[i]) {
330 n++;
331 if (k<0)
332 k=i;
333 }
334 }
335 if(n) {
336 printf("%d elements, first %d - checkClear\n",n,k);
337 abort();
338 }
339#endif
340}
341// For debug check vector is clean i.e. elements match indices
342void CoinIndexedVector::checkClean()
343{
344 int i;
345 if (packedMode_) {
346 for (i=0;i<nElements_;i++)
347 assert(elements_[i]);
348 for (;i<capacity_;i++)
349 assert(!elements_[i]);
350 } else {
351 double * copy = new double[capacity_];
352 CoinMemcpyN(elements_,capacity_,copy);
353 for (i=0;i<nElements_;i++) {
354 int indexValue = indices_[i];
355 copy[indexValue]=0.0;
356 }
357 for (i=0;i<capacity_;i++)
358 assert(!copy[i]);
359 delete [] copy;
360 }
361#ifndef NDEBUG
362 // check mark array zeroed
363 char * mark = reinterpret_cast<char *> (indices_+capacity_);
364 for (i=0;i<capacity_;i++) {
365 assert(!mark[i]);
366 }
367#endif
368}
369
370//#############################################################################
371#ifndef CLP_NO_VECTOR
372void
373CoinIndexedVector::append(const CoinPackedVectorBase & caboose)
374{
375 const int cs = caboose.getNumElements();
376
377 const int * cind = caboose.getIndices();
378 const double * celem = caboose.getElements();
379 int maxIndex=-1;
380 int i;
381 for (i=0;i<cs;i++) {
382 int indexValue = cind[i];
383 if (indexValue<0)
384 throw CoinError("negative index", "append", "CoinIndexedVector");
385 if (maxIndex<indexValue)
386 maxIndex = indexValue;
387 }
388 reserve(maxIndex+1);
389 bool needClean=false;
390 int numberDuplicates=0;
391 for (i=0;i<cs;i++) {
392 int indexValue=cind[i];
393 if (elements_[indexValue]) {
394 numberDuplicates++;
395 elements_[indexValue] += celem[i] ;
396 if (fabs(elements_[indexValue])<COIN_INDEXED_TINY_ELEMENT)
397 needClean=true; // need to go through again
398 } else {
399 if (fabs(celem[i])>=COIN_INDEXED_TINY_ELEMENT) {
400 elements_[indexValue]=celem[i];
401 indices_[nElements_++]=indexValue;
402 }
403 }
404 }
405 if (needClean) {
406 // go through again
407 int size=nElements_;
408 nElements_=0;
409 for (i=0;i<size;i++) {
410 int indexValue=indices_[i];
411 double value=elements_[indexValue];
412 if (fabs(value)>=COIN_INDEXED_TINY_ELEMENT) {
413 indices_[nElements_++]=indexValue;
414 } else {
415 elements_[indexValue]=0.0;
416 }
417 }
418 }
419 if (numberDuplicates)
420 throw CoinError("duplicate index", "append", "CoinIndexedVector");
421}
422#endif
423//#############################################################################
424
425void
426CoinIndexedVector::swap(int i, int j)
427{
428 if ( i >= nElements_ )
429 throw CoinError("index i >= size()","swap","CoinIndexedVector");
430 if ( i < 0 )
431 throw CoinError("index i < 0" ,"swap","CoinIndexedVector");
432 if ( j >= nElements_ )
433 throw CoinError("index j >= size()","swap","CoinIndexedVector");
434 if ( j < 0 )
435 throw CoinError("index j < 0" ,"swap","CoinIndexedVector");
436
437 // Swap positions i and j of the
438 // indices array
439
440 int isave = indices_[i];
441 indices_[i] = indices_[j];
442 indices_[j] = isave;
443}
444
445//#############################################################################
446
447void
448CoinIndexedVector::truncate( int n )
449{
450 reserve(n);
451}
452
453//#############################################################################
454
455void
456CoinIndexedVector::operator+=(double value)
457{
458 assert (!packedMode_);
459 int i,indexValue;
460 for (i=0;i<nElements_;i++) {
461 indexValue = indices_[i];
462 double newValue = elements_[indexValue] + value;
463 if (fabs(newValue)>=COIN_INDEXED_TINY_ELEMENT)
464 elements_[indexValue] = newValue;
465 else
466 elements_[indexValue] = COIN_INDEXED_REALLY_TINY_ELEMENT;
467 }
468}
469
470//-----------------------------------------------------------------------------
471
472void
473CoinIndexedVector::operator-=(double value)
474{
475 assert (!packedMode_);
476 int i,indexValue;
477 for (i=0;i<nElements_;i++) {
478 indexValue = indices_[i];
479 double newValue = elements_[indexValue] - value;
480 if (fabs(newValue)>=COIN_INDEXED_TINY_ELEMENT)
481 elements_[indexValue] = newValue;
482 else
483 elements_[indexValue] = COIN_INDEXED_REALLY_TINY_ELEMENT;
484 }
485}
486
487//-----------------------------------------------------------------------------
488
489void
490CoinIndexedVector::operator*=(double value)
491{
492 assert (!packedMode_);
493 int i,indexValue;
494 for (i=0;i<nElements_;i++) {
495 indexValue = indices_[i];
496 double newValue = elements_[indexValue] * value;
497 if (fabs(newValue)>=COIN_INDEXED_TINY_ELEMENT)
498 elements_[indexValue] = newValue;
499 else
500 elements_[indexValue] = COIN_INDEXED_REALLY_TINY_ELEMENT;
501 }
502}
503
504//-----------------------------------------------------------------------------
505
506void
507CoinIndexedVector::operator/=(double value)
508{
509 assert (!packedMode_);
510 int i,indexValue;
511 for (i=0;i<nElements_;i++) {
512 indexValue = indices_[i];
513 double newValue = elements_[indexValue] / value;
514 if (fabs(newValue)>=COIN_INDEXED_TINY_ELEMENT)
515 elements_[indexValue] = newValue;
516 else
517 elements_[indexValue] = COIN_INDEXED_REALLY_TINY_ELEMENT;
518 }
519}
520//#############################################################################
521
522void
523CoinIndexedVector::reserve(int n)
524{
525 int i;
526 // don't make allocated space smaller but do take off values
527 if ( n < capacity_ ) {
528#ifndef COIN_FAST_CODE
529 if (n<0)
530 throw CoinError("negative capacity", "reserve", "CoinIndexedVector");
531#endif
532 int nNew=0;
533 for (i=0;i<nElements_;i++) {
534 int indexValue=indices_[i];
535 if (indexValue<n) {
536 indices_[nNew++]=indexValue;
537 } else {
538 elements_[indexValue]=0.0;
539 }
540 }
541 nElements_=nNew;
542 } else if (n>capacity_) {
543
544 // save pointers to existing data
545 int * tempIndices = indices_;
546 double * tempElements = elements_;
547 double * delTemp = elements_-offset_;
548
549 // allocate new space
550 int nPlus;
551 if (sizeof(int)==4*sizeof(char))
552 nPlus=(n+3)>>2;
553 else
554 nPlus=(n+7)>>4;
555 indices_ = new int [n+nPlus];
556 CoinZeroN(indices_+n,nPlus);
557 // align on 64 byte boundary
558 double * temp = new double [n+7];
559 offset_ = 0;
560 CoinInt64 xx = reinterpret_cast<CoinInt64>(temp);
561 int iBottom = static_cast<int>(xx & 63);
562 if (iBottom)
563 offset_ = (64-iBottom)>>3;
564 elements_ = temp + offset_;
565
566 // copy data to new space
567 // and zero out part of array
568 if (nElements_ > 0) {
569 CoinMemcpyN(tempIndices, nElements_, indices_);
570 CoinMemcpyN(tempElements, capacity_, elements_);
571 CoinZeroN(elements_+capacity_,n-capacity_);
572 } else {
573 CoinZeroN(elements_,n);
574 }
575 capacity_ = n;
576
577 // free old data
578 if (tempElements)
579 delete [] delTemp;
580 delete [] tempIndices;
581 }
582}
583
584//#############################################################################
585
586CoinIndexedVector::CoinIndexedVector () :
587indices_(NULL),
588elements_(NULL),
589nElements_(0),
590capacity_(0),
591offset_(0),
592packedMode_(false)
593{
594}
595
596
597CoinIndexedVector::CoinIndexedVector (int size) :
598indices_(NULL),
599elements_(NULL),
600nElements_(0),
601capacity_(0),
602offset_(0),
603packedMode_(false)
604{
605 // Get space
606 reserve(size);
607}
608
609//-----------------------------------------------------------------------------
610
611CoinIndexedVector::CoinIndexedVector(int size,
612 const int * inds, const double * elems) :
613 indices_(NULL),
614 elements_(NULL),
615 nElements_(0),
616 capacity_(0),
617 offset_(0),
618 packedMode_(false)
619{
620 gutsOfSetVector(size, inds, elems);
621}
622
623//-----------------------------------------------------------------------------
624
625CoinIndexedVector::CoinIndexedVector(int size,
626 const int * inds, double value) :
627indices_(NULL),
628elements_(NULL),
629nElements_(0),
630capacity_(0),
631offset_(0),
632packedMode_(false)
633{
634gutsOfSetConstant(size, inds, value);
635}
636
637//-----------------------------------------------------------------------------
638
639CoinIndexedVector::CoinIndexedVector(int size, const double * element) :
640indices_(NULL),
641elements_(NULL),
642nElements_(0),
643capacity_(0),
644offset_(0),
645packedMode_(false)
646{
647 setFull(size, element);
648}
649
650//-----------------------------------------------------------------------------
651#ifndef CLP_NO_VECTOR
652CoinIndexedVector::CoinIndexedVector(const CoinPackedVectorBase & rhs) :
653indices_(NULL),
654elements_(NULL),
655nElements_(0),
656capacity_(0),
657offset_(0),
658packedMode_(false)
659{
660 gutsOfSetVector(rhs.getNumElements(),
661 rhs.getIndices(), rhs.getElements());
662}
663#endif
664//-----------------------------------------------------------------------------
665
666CoinIndexedVector::CoinIndexedVector(const CoinIndexedVector & rhs) :
667indices_(NULL),
668elements_(NULL),
669nElements_(0),
670capacity_(0),
671offset_(0),
672packedMode_(false)
673{
674 if (!rhs.packedMode_)
675 gutsOfSetVector(rhs.capacity_,rhs.nElements_, rhs.indices_, rhs.elements_);
676 else
677 gutsOfSetPackedVector(rhs.capacity_,rhs.nElements_, rhs.indices_, rhs.elements_);
678}
679
680//-----------------------------------------------------------------------------
681
682CoinIndexedVector::CoinIndexedVector(const CoinIndexedVector * rhs) :
683indices_(NULL),
684elements_(NULL),
685nElements_(0),
686capacity_(0),
687offset_(0),
688packedMode_(false)
689{
690 if (!rhs->packedMode_)
691 gutsOfSetVector(rhs->capacity_,rhs->nElements_, rhs->indices_, rhs->elements_);
692 else
693 gutsOfSetPackedVector(rhs->capacity_,rhs->nElements_, rhs->indices_, rhs->elements_);
694}
695
696//-----------------------------------------------------------------------------
697
698CoinIndexedVector::~CoinIndexedVector ()
699{
700 delete [] indices_;
701 if (elements_)
702 delete [] (elements_-offset_);
703}
704//#############################################################################
705//#############################################################################
706
707/// Return the sum of two indexed vectors
708CoinIndexedVector
709CoinIndexedVector::operator+(
710 const CoinIndexedVector& op2)
711{
712 assert (!packedMode_);
713 int i;
714 int nElements=nElements_;
715 int capacity = CoinMax(capacity_,op2.capacity_);
716 CoinIndexedVector newOne(*this);
717 newOne.reserve(capacity);
718 bool needClean=false;
719 // new one now can hold everything so just modify old and add new
720 for (i=0;i<op2.nElements_;i++) {
721 int indexValue=op2.indices_[i];
722 double value=op2.elements_[indexValue];
723 double oldValue=elements_[indexValue];
724 if (!oldValue) {
725 if (fabs(value)>=COIN_INDEXED_TINY_ELEMENT) {
726 newOne.elements_[indexValue]=value;
727 newOne.indices_[nElements++]=indexValue;
728 }
729 } else {
730 value += oldValue;
731 newOne.elements_[indexValue]=value;
732 if (fabs(value)<COIN_INDEXED_TINY_ELEMENT) {
733 needClean=true;
734 }
735 }
736 }
737 newOne.nElements_=nElements;
738 if (needClean) {
739 // go through again
740 newOne.nElements_=0;
741 for (i=0;i<nElements;i++) {
742 int indexValue=newOne.indices_[i];
743 double value=newOne.elements_[indexValue];
744 if (fabs(value)>=COIN_INDEXED_TINY_ELEMENT) {
745 newOne.indices_[newOne.nElements_++]=indexValue;
746 } else {
747 newOne.elements_[indexValue]=0.0;
748 }
749 }
750 }
751 return newOne;
752}
753
754/// Return the difference of two indexed vectors
755CoinIndexedVector
756CoinIndexedVector::operator-(
757 const CoinIndexedVector& op2)
758{
759 assert (!packedMode_);
760 int i;
761 int nElements=nElements_;
762 int capacity = CoinMax(capacity_,op2.capacity_);
763 CoinIndexedVector newOne(*this);
764 newOne.reserve(capacity);
765 bool needClean=false;
766 // new one now can hold everything so just modify old and add new
767 for (i=0;i<op2.nElements_;i++) {
768 int indexValue=op2.indices_[i];
769 double value=op2.elements_[indexValue];
770 double oldValue=elements_[indexValue];
771 if (!oldValue) {
772 if (fabs(value)>=COIN_INDEXED_TINY_ELEMENT) {
773 newOne.elements_[indexValue]=-value;
774 newOne.indices_[nElements++]=indexValue;
775 }
776 } else {
777 value = oldValue-value;
778 newOne.elements_[indexValue]=value;
779 if (fabs(value)<COIN_INDEXED_TINY_ELEMENT) {
780 needClean=true;
781 }
782 }
783 }
784 newOne.nElements_=nElements;
785 if (needClean) {
786 // go through again
787 newOne.nElements_=0;
788 for (i=0;i<nElements;i++) {
789 int indexValue=newOne.indices_[i];
790 double value=newOne.elements_[indexValue];
791 if (fabs(value)>=COIN_INDEXED_TINY_ELEMENT) {
792 newOne.indices_[newOne.nElements_++]=indexValue;
793 } else {
794 newOne.elements_[indexValue]=0.0;
795 }
796 }
797 }
798 return newOne;
799}
800
801/// Return the element-wise product of two indexed vectors
802CoinIndexedVector
803CoinIndexedVector::operator*(
804 const CoinIndexedVector& op2)
805{
806 assert (!packedMode_);
807 int i;
808 int nElements=nElements_;
809 int capacity = CoinMax(capacity_,op2.capacity_);
810 CoinIndexedVector newOne(*this);
811 newOne.reserve(capacity);
812 bool needClean=false;
813 // new one now can hold everything so just modify old and add new
814 for (i=0;i<op2.nElements_;i++) {
815 int indexValue=op2.indices_[i];
816 double value=op2.elements_[indexValue];
817 double oldValue=elements_[indexValue];
818 if (oldValue) {
819 value *= oldValue;
820 newOne.elements_[indexValue]=value;
821 if (fabs(value)<COIN_INDEXED_TINY_ELEMENT) {
822 needClean=true;
823 }
824 }
825 }
826
827 newOne.nElements_=nElements;
828
829 if (needClean) {
830 // go through again
831 newOne.nElements_=0;
832 for (i=0;i<nElements;i++) {
833 int indexValue=newOne.indices_[i];
834 double value=newOne.elements_[indexValue];
835 if (fabs(value)>=COIN_INDEXED_TINY_ELEMENT) {
836 newOne.indices_[newOne.nElements_++]=indexValue;
837 } else {
838 newOne.elements_[indexValue]=0.0;
839 }
840 }
841 }
842 return newOne;
843}
844
845/// Return the element-wise ratio of two indexed vectors
846CoinIndexedVector
847CoinIndexedVector::operator/ (const CoinIndexedVector& op2)
848{
849 assert (!packedMode_);
850 // I am treating 0.0/0.0 as 0.0
851 int i;
852 int nElements=nElements_;
853 int capacity = CoinMax(capacity_,op2.capacity_);
854 CoinIndexedVector newOne(*this);
855 newOne.reserve(capacity);
856 bool needClean=false;
857 // new one now can hold everything so just modify old and add new
858 for (i=0;i<op2.nElements_;i++) {
859 int indexValue=op2.indices_[i];
860 double value=op2.elements_[indexValue];
861 double oldValue=elements_[indexValue];
862 if (oldValue) {
863 if (!value)
864 throw CoinError("zero divisor", "/", "CoinIndexedVector");
865 value = oldValue/value;
866 newOne.elements_[indexValue]=value;
867 if (fabs(value)<COIN_INDEXED_TINY_ELEMENT) {
868 needClean=true;
869 }
870 }
871 }
872
873 newOne.nElements_=nElements;
874
875 if (needClean) {
876 // go through again
877 newOne.nElements_=0;
878 for (i=0;i<nElements;i++) {
879 int indexValue=newOne.indices_[i];
880 double value=newOne.elements_[indexValue];
881 if (fabs(value)>=COIN_INDEXED_TINY_ELEMENT) {
882 newOne.indices_[newOne.nElements_++]=indexValue;
883 } else {
884 newOne.elements_[indexValue]=0.0;
885 }
886 }
887 }
888 return newOne;
889}
890// The sum of two indexed vectors
891void
892CoinIndexedVector::operator+=(const CoinIndexedVector& op2)
893{
894 // do slowly at first
895 *this = *this + op2;
896}
897
898// The difference of two indexed vectors
899void
900CoinIndexedVector::operator-=( const CoinIndexedVector& op2)
901{
902 // do slowly at first
903 *this = *this - op2;
904}
905
906// The element-wise product of two indexed vectors
907void
908CoinIndexedVector::operator*=(const CoinIndexedVector& op2)
909{
910 // do slowly at first
911 *this = *this * op2;
912}
913
914// The element-wise ratio of two indexed vectors (0.0/0.0 => 0.0) (0 vanishes)
915void
916CoinIndexedVector::operator/=(const CoinIndexedVector& op2)
917{
918 // do slowly at first
919 *this = *this / op2;
920}
921//#############################################################################
922void
923CoinIndexedVector::sortDecrIndex()
924{
925 // Should replace with std sort
926 double * elements = new double [nElements_];
927 CoinZeroN (elements,nElements_);
928 CoinSort_2(indices_, indices_ + nElements_, elements,
929 CoinFirstGreater_2<int, double>());
930 delete [] elements;
931}
932
933void
934CoinIndexedVector::sortIncrElement()
935{
936 double * elements = new double [nElements_];
937 int i;
938 for (i=0;i<nElements_;i++)
939 elements[i] = elements_[indices_[i]];
940 CoinSort_2(elements, elements + nElements_, indices_,
941 CoinFirstLess_2<double, int>());
942 delete [] elements;
943}
944
945void
946CoinIndexedVector::sortDecrElement()
947{
948 double * elements = new double [nElements_];
949 int i;
950 for (i=0;i<nElements_;i++)
951 elements[i] = elements_[indices_[i]];
952 CoinSort_2(elements, elements + nElements_, indices_,
953 CoinFirstGreater_2<double, int>());
954 delete [] elements;
955}
956//#############################################################################
957
958void
959CoinIndexedVector::gutsOfSetVector(int size,
960 const int * inds, const double * elems)
961{
962#ifndef COIN_FAST_CODE
963 if (size<0)
964 throw CoinError("negative number of indices", "setVector", "CoinIndexedVector");
965#endif
966 assert(!packedMode_);
967 // find largest
968 int i;
969 int maxIndex=-1;
970 for (i=0;i<size;i++) {
971 int indexValue = inds[i];
972#ifndef COIN_FAST_CODE
973 if (indexValue<0)
974 throw CoinError("negative index", "setVector", "CoinIndexedVector");
975#endif
976 if (maxIndex<indexValue)
977 maxIndex = indexValue;
978 }
979 reserve(maxIndex+1);
980 nElements_ = 0;
981 // elements_ array is all zero
982 bool needClean=false;
983 int numberDuplicates=0;
984 for (i=0;i<size;i++) {
985 int indexValue=inds[i];
986 if (elements_[indexValue] == 0)
987 {
988 if (fabs(elems[i])>=COIN_INDEXED_TINY_ELEMENT) {
989 indices_[nElements_++]=indexValue;
990 elements_[indexValue]=elems[i];
991 }
992 }
993 else
994 {
995 numberDuplicates++;
996 elements_[indexValue] += elems[i] ;
997 if (fabs(elements_[indexValue])<COIN_INDEXED_TINY_ELEMENT)
998 needClean=true; // need to go through again
999 }
1000 }
1001 if (needClean) {
1002 // go through again
1003 size=nElements_;
1004 nElements_=0;
1005 for (i=0;i<size;i++) {
1006 int indexValue=indices_[i];
1007 double value=elements_[indexValue];
1008 if (fabs(value)>=COIN_INDEXED_TINY_ELEMENT) {
1009 indices_[nElements_++]=indexValue;
1010 } else {
1011 elements_[indexValue]=0.0;
1012 }
1013 }
1014 }
1015 if (numberDuplicates)
1016 throw CoinError("duplicate index", "setVector", "CoinIndexedVector");
1017}
1018
1019//#############################################################################
1020
1021void
1022CoinIndexedVector::gutsOfSetVector(int size, int numberIndices,
1023 const int * inds, const double * elems)
1024{
1025 assert(!packedMode_);
1026
1027 int i;
1028 reserve(size);
1029#ifndef COIN_FAST_CODE
1030 if (numberIndices<0)
1031 throw CoinError("negative number of indices", "setVector", "CoinIndexedVector");
1032#endif
1033 nElements_ = 0;
1034 // elements_ array is all zero
1035 bool needClean=false;
1036 int numberDuplicates=0;
1037 for (i=0;i<numberIndices;i++) {
1038 int indexValue=inds[i];
1039#ifndef COIN_FAST_CODE
1040 if (indexValue<0)
1041 throw CoinError("negative index", "setVector", "CoinIndexedVector");
1042 else if (indexValue>=size)
1043 throw CoinError("too large an index", "setVector", "CoinIndexedVector");
1044#endif
1045 if (elements_[indexValue]) {
1046 numberDuplicates++;
1047 elements_[indexValue] += elems[indexValue] ;
1048 if (fabs(elements_[indexValue])<COIN_INDEXED_TINY_ELEMENT)
1049 needClean=true; // need to go through again
1050 } else {
1051 if (fabs(elems[indexValue])>=COIN_INDEXED_TINY_ELEMENT) {
1052 elements_[indexValue]=elems[indexValue];
1053 indices_[nElements_++]=indexValue;
1054 }
1055 }
1056 }
1057 if (needClean) {
1058 // go through again
1059 size=nElements_;
1060 nElements_=0;
1061 for (i=0;i<size;i++) {
1062 int indexValue=indices_[i];
1063 double value=elements_[indexValue];
1064 if (fabs(value)>=COIN_INDEXED_TINY_ELEMENT) {
1065 indices_[nElements_++]=indexValue;
1066 } else {
1067 elements_[indexValue]=0.0;
1068 }
1069 }
1070 }
1071 if (numberDuplicates)
1072 throw CoinError("duplicate index", "setVector", "CoinIndexedVector");
1073}
1074
1075//-----------------------------------------------------------------------------
1076
1077void
1078CoinIndexedVector::gutsOfSetPackedVector(int size, int numberIndices,
1079 const int * inds, const double * elems)
1080{
1081 packedMode_=true;
1082
1083 int i;
1084 reserve(size);
1085#ifndef COIN_FAST_CODE
1086 if (numberIndices<0)
1087 throw CoinError("negative number of indices", "setVector", "CoinIndexedVector");
1088#endif
1089 nElements_ = 0;
1090 // elements_ array is all zero
1091 // Does not check for duplicates
1092 for (i=0;i<numberIndices;i++) {
1093 int indexValue=inds[i];
1094#ifndef COIN_FAST_CODE
1095 if (indexValue<0)
1096 throw CoinError("negative index", "setVector", "CoinIndexedVector");
1097 else if (indexValue>=size)
1098 throw CoinError("too large an index", "setVector", "CoinIndexedVector");
1099#endif
1100 if (fabs(elems[i])>=COIN_INDEXED_TINY_ELEMENT) {
1101 elements_[nElements_]=elems[i];
1102 indices_[nElements_++]=indexValue;
1103 }
1104 }
1105}
1106
1107//-----------------------------------------------------------------------------
1108
1109void
1110CoinIndexedVector::gutsOfSetConstant(int size,
1111 const int * inds, double value)
1112{
1113
1114 assert(!packedMode_);
1115#ifndef COIN_FAST_CODE
1116 if (size<0)
1117 throw CoinError("negative number of indices", "setConstant", "CoinIndexedVector");
1118#endif
1119 // find largest
1120 int i;
1121 int maxIndex=-1;
1122 for (i=0;i<size;i++) {
1123 int indexValue = inds[i];
1124#ifndef COIN_FAST_CODE
1125 if (indexValue<0)
1126 throw CoinError("negative index", "setConstant", "CoinIndexedVector");
1127#endif
1128 if (maxIndex<indexValue)
1129 maxIndex = indexValue;
1130 }
1131
1132 reserve(maxIndex+1);
1133 nElements_ = 0;
1134 int numberDuplicates=0;
1135 // elements_ array is all zero
1136 bool needClean=false;
1137 for (i=0;i<size;i++) {
1138 int indexValue=inds[i];
1139 if (elements_[indexValue] == 0)
1140 {
1141 if (fabs(value)>=COIN_INDEXED_TINY_ELEMENT) {
1142 elements_[indexValue] += value;
1143 indices_[nElements_++]=indexValue;
1144 }
1145 }
1146 else
1147 {
1148 numberDuplicates++;
1149 elements_[indexValue] += value ;
1150 if (fabs(elements_[indexValue])<COIN_INDEXED_TINY_ELEMENT)
1151 needClean=true; // need to go through again
1152 }
1153 }
1154 if (needClean) {
1155 // go through again
1156 size=nElements_;
1157 nElements_=0;
1158 for (i=0;i<size;i++) {
1159 int indexValue=indices_[i];
1160 double value=elements_[indexValue];
1161 if (fabs(value)>=COIN_INDEXED_TINY_ELEMENT) {
1162 indices_[nElements_++]=indexValue;
1163 } else {
1164 elements_[indexValue]=0.0;
1165 }
1166 }
1167 }
1168 if (numberDuplicates)
1169 throw CoinError("duplicate index", "setConstant", "CoinIndexedVector");
1170}
1171
1172//#############################################################################
1173// Append a CoinIndexedVector to the end
1174void
1175CoinIndexedVector::append(const CoinIndexedVector & caboose)
1176{
1177 const int cs = caboose.getNumElements();
1178
1179 const int * cind = caboose.getIndices();
1180 const double * celem = caboose.denseVector();
1181 int maxIndex=-1;
1182 int i;
1183 for (i=0;i<cs;i++) {
1184 int indexValue = cind[i];
1185#ifndef COIN_FAST_CODE
1186 if (indexValue<0)
1187 throw CoinError("negative index", "append", "CoinIndexedVector");
1188#endif
1189 if (maxIndex<indexValue)
1190 maxIndex = indexValue;
1191 }
1192 reserve(maxIndex+1);
1193 bool needClean=false;
1194 int numberDuplicates=0;
1195 for (i=0;i<cs;i++) {
1196 int indexValue=cind[i];
1197 if (elements_[indexValue]) {
1198 numberDuplicates++;
1199 elements_[indexValue] += celem[indexValue] ;
1200 if (fabs(elements_[indexValue])<COIN_INDEXED_TINY_ELEMENT)
1201 needClean=true; // need to go through again
1202 } else {
1203 if (fabs(celem[indexValue])>=COIN_INDEXED_TINY_ELEMENT) {
1204 elements_[indexValue]=celem[indexValue];
1205 indices_[nElements_++]=indexValue;
1206 }
1207 }
1208 }
1209 if (needClean) {
1210 // go through again
1211 int size=nElements_;
1212 nElements_=0;
1213 for (i=0;i<size;i++) {
1214 int indexValue=indices_[i];
1215 double value=elements_[indexValue];
1216 if (fabs(value)>=COIN_INDEXED_TINY_ELEMENT) {
1217 indices_[nElements_++]=indexValue;
1218 } else {
1219 elements_[indexValue]=0.0;
1220 }
1221 }
1222 }
1223 if (numberDuplicates)
1224 throw CoinError("duplicate index", "append", "CoinIndexedVector");
1225}
1226#ifndef CLP_NO_VECTOR
1227/* Equal. Returns true if vectors have same length and corresponding
1228 element of each vector is equal. */
1229bool
1230CoinIndexedVector::operator==(const CoinPackedVectorBase & rhs) const
1231{
1232 const int cs = rhs.getNumElements();
1233
1234 const int * cind = rhs.getIndices();
1235 const double * celem = rhs.getElements();
1236 if (nElements_!=cs)
1237 return false;
1238 int i;
1239 bool okay=true;
1240 for (i=0;i<cs;i++) {
1241 int iRow = cind[i];
1242 if (celem[i]!=elements_[iRow]) {
1243 okay=false;
1244 break;
1245 }
1246 }
1247 return okay;
1248}
1249// Not equal
1250bool
1251CoinIndexedVector::operator!=(const CoinPackedVectorBase & rhs) const
1252{
1253 const int cs = rhs.getNumElements();
1254
1255 const int * cind = rhs.getIndices();
1256 const double * celem = rhs.getElements();
1257 if (nElements_!=cs)
1258 return true;
1259 int i;
1260 bool okay=false;
1261 for (i=0;i<cs;i++) {
1262 int iRow = cind[i];
1263 if (celem[i]!=elements_[iRow]) {
1264 okay=true;
1265 break;
1266 }
1267 }
1268 return okay;
1269}
1270#endif
1271/* Equal. Returns true if vectors have same length and corresponding
1272 element of each vector is equal. */
1273bool
1274CoinIndexedVector::operator==(const CoinIndexedVector & rhs) const
1275{
1276 const int cs = rhs.nElements_;
1277
1278 const int * cind = rhs.indices_;
1279 const double * celem = rhs.elements_;
1280 if (nElements_!=cs)
1281 return false;
1282 int i;
1283 bool okay=true;
1284 CoinRelFltEq eq(1.0e-8);
1285 for (i=0;i<cs;i++) {
1286 int iRow = cind[i];
1287 if (!eq(celem[iRow],elements_[iRow])) {
1288 okay=false;
1289 break;
1290 }
1291 }
1292 return okay;
1293}
1294/// Not equal
1295bool
1296CoinIndexedVector::operator!=(const CoinIndexedVector & rhs) const
1297{
1298 const int cs = rhs.nElements_;
1299
1300 const int * cind = rhs.indices_;
1301 const double * celem = rhs.elements_;
1302 if (nElements_!=cs)
1303 return true;
1304 int i;
1305 bool okay=false;
1306 for (i=0;i<cs;i++) {
1307 int iRow = cind[i];
1308 if (celem[iRow]!=elements_[iRow]) {
1309 okay=true;
1310 break;
1311 }
1312 }
1313 return okay;
1314}
1315// Get value of maximum index
1316int
1317CoinIndexedVector::getMaxIndex() const
1318{
1319 int maxIndex = -COIN_INT_MAX;
1320 int i;
1321 for (i=0;i<nElements_;i++)
1322 maxIndex = CoinMax(maxIndex,indices_[i]);
1323 return maxIndex;
1324}
1325// Get value of minimum index
1326int
1327CoinIndexedVector::getMinIndex() const
1328{
1329 int minIndex = COIN_INT_MAX;
1330 int i;
1331 for (i=0;i<nElements_;i++)
1332 minIndex = CoinMin(minIndex,indices_[i]);
1333 return minIndex;
1334}
1335// Scan dense region and set up indices
1336int
1337CoinIndexedVector::scan()
1338{
1339 nElements_=0;
1340 return scan(0,capacity_);
1341}
1342// Scan dense region from start to < end and set up indices
1343int
1344CoinIndexedVector::scan(int start, int end)
1345{
1346 assert(!packedMode_);
1347 end = CoinMin(end,capacity_);
1348 start = CoinMax(start,0);
1349 int i;
1350 int number = 0;
1351 int * indices = indices_+nElements_;
1352 for (i=start;i<end;i++)
1353 if (elements_[i])
1354 indices[number++] = i;
1355 nElements_ += number;
1356 return number;
1357}
1358// Scan dense region and set up indices with tolerance
1359int
1360CoinIndexedVector::scan(double tolerance)
1361{
1362 nElements_=0;
1363 return scan(0,capacity_,tolerance);
1364}
1365// Scan dense region from start to < end and set up indices with tolerance
1366int
1367CoinIndexedVector::scan(int start, int end, double tolerance)
1368{
1369 assert(!packedMode_);
1370 end = CoinMin(end,capacity_);
1371 start = CoinMax(start,0);
1372 int i;
1373 int number = 0;
1374 int * indices = indices_+nElements_;
1375 for (i=start;i<end;i++) {
1376 double value = elements_[i];
1377 if (value) {
1378 if (fabs(value)>=tolerance)
1379 indices[number++] = i;
1380 else
1381 elements_[i]=0.0;
1382 }
1383 }
1384 nElements_ += number;
1385 return number;
1386}
1387// These pack down
1388int
1389CoinIndexedVector::cleanAndPack( double tolerance )
1390{
1391 int number = nElements_;
1392 int i;
1393 nElements_=0;
1394 assert(!packedMode_);
1395 for (i=0;i<number;i++) {
1396 int indexValue = indices_[i];
1397 double value = elements_[indexValue];
1398 elements_[indexValue]=0.0;
1399 if (fabs(value)>=tolerance) {
1400 elements_[nElements_]=value;
1401 indices_[nElements_++]=indexValue;
1402 }
1403 }
1404 packedMode_=true;
1405 return nElements_;
1406}
1407// These pack down
1408int
1409CoinIndexedVector::cleanAndPackSafe( double tolerance )
1410{
1411 int number = nElements_;
1412 if (number) {
1413 int i;
1414 nElements_=0;
1415 assert(!packedMode_);
1416 double * temp=NULL;
1417 bool gotMemory;
1418 if (number*3<capacity_-3-9999999) {
1419 // can find room without new
1420 gotMemory=false;
1421 // But may need to align on 8 byte boundary
1422 char * tempC = reinterpret_cast<char *> (indices_+number);
1423 CoinInt64 xx = reinterpret_cast<CoinInt64>(tempC);
1424 CoinInt64 iBottom = xx & 7;
1425 if (iBottom)
1426 tempC += 8-iBottom;
1427 temp = reinterpret_cast<double *> (tempC);
1428 xx = reinterpret_cast<CoinInt64>(temp);
1429 iBottom = xx & 7;
1430 assert(!iBottom);
1431 } else {
1432 // might be better to do complete scan
1433 gotMemory=true;
1434 temp = new double[number];
1435 }
1436 for (i=0;i<number;i++) {
1437 int indexValue = indices_[i];
1438 double value = elements_[indexValue];
1439 elements_[indexValue]=0.0;
1440 if (fabs(value)>=tolerance) {
1441 temp[nElements_]=value;
1442 indices_[nElements_++]=indexValue;
1443 }
1444 }
1445 CoinMemcpyN(temp,nElements_,elements_);
1446 if (gotMemory)
1447 delete [] temp;
1448 packedMode_=true;
1449 }
1450 return nElements_;
1451}
1452// Scan dense region and set up indices
1453int
1454CoinIndexedVector::scanAndPack()
1455{
1456 nElements_=0;
1457 return scanAndPack(0,capacity_);
1458}
1459// Scan dense region from start to < end and set up indices
1460int
1461CoinIndexedVector::scanAndPack(int start, int end)
1462{
1463 assert(!packedMode_);
1464 end = CoinMin(end,capacity_);
1465 start = CoinMax(start,0);
1466 int i;
1467 int number = 0;
1468 int * indices = indices_+nElements_;
1469 for (i=start;i<end;i++) {
1470 double value = elements_[i];
1471 elements_[i]=0.0;
1472 if (value) {
1473 elements_[number]=value;
1474 indices[number++] = i;
1475 }
1476 }
1477 nElements_ += number;
1478 packedMode_=true;
1479 return number;
1480}
1481// Scan dense region and set up indices with tolerance
1482int
1483CoinIndexedVector::scanAndPack(double tolerance)
1484{
1485 nElements_=0;
1486 return scanAndPack(0,capacity_,tolerance);
1487}
1488// Scan dense region from start to < end and set up indices with tolerance
1489int
1490CoinIndexedVector::scanAndPack(int start, int end, double tolerance)
1491{
1492 assert(!packedMode_);
1493 end = CoinMin(end,capacity_);
1494 start = CoinMax(start,0);
1495 int i;
1496 int number = 0;
1497 int * indices = indices_+nElements_;
1498 for (i=start;i<end;i++) {
1499 double value = elements_[i];
1500 elements_[i]=0.0;
1501 if (fabs(value)>=tolerance) {
1502 elements_[number]=value;
1503 indices[number++] = i;
1504 }
1505 }
1506 nElements_ += number;
1507 packedMode_=true;
1508 return number;
1509}
1510// This is mainly for testing - goes from packed to indexed
1511void
1512CoinIndexedVector::expand()
1513{
1514 if (nElements_&&packedMode_) {
1515 double * temp = new double[capacity_];
1516 int i;
1517 for (i=0;i<nElements_;i++)
1518 temp[indices_[i]]=elements_[i];
1519 CoinZeroN(elements_,nElements_);
1520 for (i=0;i<nElements_;i++) {
1521 int iRow = indices_[i];
1522 elements_[iRow]=temp[iRow];
1523 }
1524 delete [] temp;
1525 }
1526 packedMode_=false;
1527}
1528// Create packed array
1529void
1530CoinIndexedVector::createPacked(int number, const int * indices,
1531 const double * elements)
1532{
1533 nElements_=number;
1534 packedMode_=true;
1535 CoinMemcpyN(indices,number,indices_);
1536 CoinMemcpyN(elements,number,elements_);
1537}
1538// Print out
1539void
1540CoinIndexedVector::print() const
1541{
1542 printf("Vector has %d elements (%spacked mode)\n",nElements_,packedMode_ ? "" : "un");
1543 for (int i=0;i<nElements_;i++) {
1544 if (i&&(i%5==0))
1545 printf("\n");
1546 int index = indices_[i];
1547 double value = packedMode_ ? elements_[i] : elements_[index];
1548 printf(" (%d,%g)",index,value);
1549 }
1550 printf("\n");
1551}
1552
1553// Zero out array
1554void
1555CoinArrayWithLength::clear()
1556{
1557 assert ((size_>0&&array_)||!array_);
1558 memset (array_,0,size_);
1559}
1560static char * mallocArray(long size)
1561{
1562 if (size>0) {
1563 char * array = new char [size];
1564 return array;
1565 } else {
1566 return NULL;
1567 }
1568}
1569static void freeArray(void * array)
1570{
1571 char * charArray = reinterpret_cast<char *> (array);
1572 delete [] charArray;
1573}
1574// Conditionally gets new array
1575char *
1576CoinArrayWithLength::conditionalNew(long sizeWanted)
1577{
1578 if (size_==-1) {
1579 freeArray(array_);
1580 array_ = mallocArray(sizeWanted);
1581 } else {
1582 setCapacity();
1583 if (sizeWanted>size_) {
1584 freeArray(array_);
1585 size_ = static_cast<int> (sizeWanted*101/100)+64;
1586 // round to multiple of 16
1587 size_ -= size_%16;
1588 array_ = mallocArray(size_);
1589 }
1590 }
1591 return array_;
1592}
1593// Conditionally deletes
1594void
1595CoinArrayWithLength::conditionalDelete()
1596{
1597 if (size_==-1) {
1598 freeArray(array_);
1599 array_=NULL;
1600 } else if (size_>=0) {
1601 size_ = -size_-2;
1602 }
1603}
1604/* Copy constructor. */
1605CoinArrayWithLength::CoinArrayWithLength(const CoinArrayWithLength & rhs)
1606{
1607 assert (rhs.getCapacity()>=0);
1608 size_=rhs.size_;
1609 array_ = mallocArray(getCapacity());
1610 if (size_>0)
1611 CoinMemcpyN(rhs.array_,size_,array_);
1612}
1613
1614/* Copy constructor.2 */
1615CoinArrayWithLength::CoinArrayWithLength(const CoinArrayWithLength * rhs)
1616{
1617 assert (rhs->getCapacity()>=0);
1618 size_=rhs->size_;
1619 array_ = mallocArray(getCapacity());
1620 if (size_>0)
1621 CoinMemcpyN(rhs->array_,size_,array_);
1622}
1623/* Assignment operator. */
1624CoinArrayWithLength &
1625CoinArrayWithLength::operator=(const CoinArrayWithLength & rhs)
1626{
1627 if (this != &rhs) {
1628 assert (rhs.size_!=-1||!rhs.array_);
1629 if (rhs.size_==-1) {
1630 freeArray(array_);
1631 array_=NULL;
1632 size_=-1;
1633 } else {
1634 int capacity = getCapacity();
1635 int rhsCapacity = rhs.getCapacity();
1636 if (capacity<rhsCapacity) {
1637 freeArray(array_);
1638 array_ = mallocArray(rhsCapacity);
1639 }
1640 size_=rhs.size_;
1641 if (size_>0)
1642 CoinMemcpyN(rhs.array_,size_,array_);
1643 }
1644 }
1645 return *this;
1646}
1647/* Assignment with length (if -1 use internal length) */
1648void
1649CoinArrayWithLength::copy(const CoinArrayWithLength & rhs, int numberBytes)
1650{
1651 if (numberBytes==-1||numberBytes<=rhs.getCapacity()) {
1652 CoinArrayWithLength::operator=(rhs);
1653 } else {
1654 assert (numberBytes>=0);
1655 if (size_==-1) {
1656 freeArray(array_);
1657 array_=NULL;
1658 } else {
1659 size_=-1;
1660 }
1661 if (rhs.size_>=0)
1662 size_ = numberBytes;
1663 array_ = mallocArray(numberBytes);
1664 if (rhs.array_)
1665 CoinMemcpyN(rhs.array_,numberBytes,array_);
1666 }
1667}
1668/* Assignment with length - does not copy */
1669void
1670CoinArrayWithLength::allocate(const CoinArrayWithLength & rhs, int numberBytes)
1671{
1672 if (numberBytes==-1||numberBytes<=rhs.getCapacity()) {
1673 assert (rhs.size_!=-1||!rhs.array_);
1674 if (rhs.size_==-1) {
1675 freeArray(array_);
1676 array_=NULL;
1677 size_=-1;
1678 } else {
1679 int capacity = getCapacity();
1680 int rhsCapacity = rhs.getCapacity();
1681 if (capacity<rhsCapacity) {
1682 freeArray(array_);
1683 array_ = mallocArray(rhsCapacity);
1684 }
1685 size_=rhs.size_;
1686 }
1687 } else {
1688 assert (numberBytes>=0);
1689 if (size_==-1) {
1690 freeArray(array_);
1691 array_=NULL;
1692 } else {
1693 size_=-1;
1694 }
1695 if (rhs.size_>=0)
1696 size_ = numberBytes;
1697 array_ = mallocArray(numberBytes);
1698 }
1699}
1700// Does what is needed to set persistence
1701void
1702CoinArrayWithLength::setPersistence(int flag,int currentLength)
1703{
1704 if (flag) {
1705 if (size_==-1) {
1706 if (currentLength&&array_) {
1707 size_=currentLength;
1708 } else {
1709 size_=0;
1710 freeArray(array_);
1711 array_=NULL;
1712 }
1713 }
1714 } else {
1715 size_=-1;
1716 }
1717}
1718// Swaps memory between two members
1719void
1720CoinArrayWithLength::swap(CoinArrayWithLength & other)
1721{
1722#ifdef COIN_DEVELOP
1723 if (!(size_==other.size_||size_==-1||other.size_==-1))
1724 printf("Two arrays have sizes - %d and %d\n",size_,other.size_);
1725#endif
1726 char * swapArray = other.array_;
1727 other.array_=array_;
1728 array_=swapArray;
1729 int swapSize = other.size_;
1730 other.size_=size_;
1731 size_=swapSize;
1732}
1733// Extend a persistent array keeping data (size in bytes)
1734void
1735CoinArrayWithLength::extend(int newSize)
1736{
1737 //assert (newSize>=getCapacity()&&getCapacity()>=0);
1738 assert (size_>=0); // not much point otherwise
1739 if (newSize>size_) {
1740 char * temp = mallocArray(newSize);
1741 CoinMemcpyN(array_,size_,temp);
1742 freeArray(array_);
1743 array_=temp;
1744 size_=newSize;
1745 }
1746}
1747