1 /* $Id: CoinModelUseful.cpp 1543 2012-07-27 22:48:29Z unxusr $ */
2 // Copyright (C) 2005, 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 #include "CoinPragma.hpp"
7
8 #include <cstdlib>
9 #include <cmath>
10 #include <cassert>
11 #include <cfloat>
12 #include <string>
13 #include <cstdio>
14 #include <iostream>
15
16 #include "CoinHelperFunctions.hpp"
17
18 #include "CoinModelUseful.hpp"
19
20
21 //#############################################################################
22 // Constructors / Destructor / Assignment
23 //#############################################################################
24
25 //-------------------------------------------------------------------
26 // Default Constructor
27 //-------------------------------------------------------------------
CoinModelLink()28 CoinModelLink::CoinModelLink ()
29 : row_(-1),
30 column_(-1),
31 value_(0.0),
32 position_(-1),
33 onRow_(true)
34 {
35 }
36
37 //-------------------------------------------------------------------
38 // Copy constructor
39 //-------------------------------------------------------------------
CoinModelLink(const CoinModelLink & rhs)40 CoinModelLink::CoinModelLink (const CoinModelLink & rhs)
41 : row_(rhs.row_),
42 column_(rhs.column_),
43 value_(rhs.value_),
44 position_(rhs.position_),
45 onRow_(rhs.onRow_)
46 {
47 }
48
49 //-------------------------------------------------------------------
50 // Destructor
51 //-------------------------------------------------------------------
~CoinModelLink()52 CoinModelLink::~CoinModelLink ()
53 {
54 }
55
56 //----------------------------------------------------------------
57 // Assignment operator
58 //-------------------------------------------------------------------
59 CoinModelLink &
operator =(const CoinModelLink & rhs)60 CoinModelLink::operator=(const CoinModelLink& rhs)
61 {
62 if (this != &rhs) {
63 row_ = rhs.row_;
64 column_ = rhs.column_;
65 value_ = rhs.value_;
66 position_ = rhs.position_;
67 onRow_ = rhs.onRow_;
68 }
69 return *this;
70 }
71
72 namespace {
73 const int mmult[] = {
74 262139, 259459, 256889, 254291, 251701, 249133, 246709, 244247,
75 241667, 239179, 236609, 233983, 231289, 228859, 226357, 223829,
76 221281, 218849, 216319, 213721, 211093, 208673, 206263, 203773,
77 201233, 198637, 196159, 193603, 191161, 188701, 186149, 183761,
78 181303, 178873, 176389, 173897, 171469, 169049, 166471, 163871,
79 161387, 158941, 156437, 153949, 151531, 149159, 146749, 144299,
80 141709, 139369, 136889, 134591, 132169, 129641, 127343, 124853,
81 122477, 120163, 117757, 115361, 112979, 110567, 108179, 105727,
82 103387, 101021, 98639, 96179, 93911, 91583, 89317, 86939, 84521,
83 82183, 79939, 77587, 75307, 72959, 70793, 68447, 66103
84 };
85 const int lengthMult = static_cast<int> (sizeof(mmult) / sizeof(int));
86 }
87
88 //#############################################################################
89 // Constructors / Destructor / Assignment
90 //#############################################################################
91
92 //-------------------------------------------------------------------
93 // Default Constructor
94 //-------------------------------------------------------------------
CoinModelHash()95 CoinModelHash::CoinModelHash ()
96 : names_(NULL),
97 hash_(NULL),
98 numberItems_(0),
99 maximumItems_(0),
100 lastSlot_(-1)
101 {
102 }
103
104 //-------------------------------------------------------------------
105 // Copy constructor
106 //-------------------------------------------------------------------
CoinModelHash(const CoinModelHash & rhs)107 CoinModelHash::CoinModelHash (const CoinModelHash & rhs)
108 : names_(NULL),
109 hash_(NULL),
110 numberItems_(rhs.numberItems_),
111 maximumItems_(rhs.maximumItems_),
112 lastSlot_(rhs.lastSlot_)
113 {
114 if (maximumItems_) {
115 names_ = new char * [maximumItems_];
116 for (int i=0;i<maximumItems_;i++) {
117 names_[i]=CoinStrdup(rhs.names_[i]);
118 }
119 hash_ = CoinCopyOfArray(rhs.hash_,4*maximumItems_);
120 }
121 }
122
123 //-------------------------------------------------------------------
124 // Destructor
125 //-------------------------------------------------------------------
~CoinModelHash()126 CoinModelHash::~CoinModelHash ()
127 {
128 for (int i=0;i<maximumItems_;i++)
129 free(names_[i]);
130 delete [] names_;
131 delete [] hash_;
132 }
133
134 //----------------------------------------------------------------
135 // Assignment operator
136 //-------------------------------------------------------------------
137 CoinModelHash &
operator =(const CoinModelHash & rhs)138 CoinModelHash::operator=(const CoinModelHash& rhs)
139 {
140 if (this != &rhs) {
141 for (int i=0;i<maximumItems_;i++)
142 free(names_[i]);
143 delete [] names_;
144 delete [] hash_;
145 numberItems_ = rhs.numberItems_;
146 maximumItems_ = rhs.maximumItems_;
147 lastSlot_ = rhs.lastSlot_;
148 if (maximumItems_) {
149 names_ = new char * [maximumItems_];
150 for (int i=0;i<maximumItems_;i++) {
151 names_[i]=CoinStrdup(rhs.names_[i]);
152 }
153 hash_ = CoinCopyOfArray(rhs.hash_,4*maximumItems_);
154 } else {
155 names_ = NULL;
156 hash_ = NULL;
157 }
158 }
159 return *this;
160 }
161 // Set number of items
162 void
setNumberItems(int number)163 CoinModelHash::setNumberItems(int number)
164 {
165 assert (number>=0&&number<=numberItems_);
166 numberItems_=number;
167 }
168 // Resize hash (also re-hashs)
169 void
resize(int maxItems,bool forceReHash)170 CoinModelHash::resize(int maxItems,bool forceReHash)
171 {
172 assert (numberItems_<=maximumItems_);
173 if (maxItems<=maximumItems_&&!forceReHash)
174 return;
175 int n=maximumItems_;
176 maximumItems_=maxItems;
177 char ** names = new char * [maximumItems_];
178 int i;
179 for ( i=0;i<n;i++)
180 names[i]=names_[i];
181 for ( ;i<maximumItems_;i++)
182 names[i]=NULL;
183 delete [] names_;
184 names_ = names;
185 delete [] hash_;
186 int maxHash = 4 * maximumItems_;
187 hash_ = new CoinModelHashLink [maxHash];
188 int ipos;
189
190 for ( i = 0; i < maxHash; i++ ) {
191 hash_[i].index = -1;
192 hash_[i].next = -1;
193 }
194
195 /*
196 * Initialize the hash table. Only the index of the first name that
197 * hashes to a value is entered in the table; subsequent names that
198 * collide with it are not entered.
199 */
200 for ( i = 0; i < numberItems_; ++i ) {
201 if (names_[i]) {
202 ipos = hashValue ( names_[i]);
203 if ( hash_[ipos].index == -1 ) {
204 hash_[ipos].index = i;
205 }
206 }
207 }
208
209 /*
210 * Now take care of the names that collided in the preceding loop,
211 * by finding some other entry in the table for them.
212 * Since there are as many entries in the table as there are names,
213 * there must be room for them.
214 */
215 lastSlot_ = -1;
216 for ( i = 0; i < numberItems_; ++i ) {
217 if (!names_[i])
218 continue;
219 char *thisName = names[i];
220 ipos = hashValue ( thisName);
221
222 while ( true ) {
223 int j1 = hash_[ipos].index;
224
225 if ( j1 == i )
226 break;
227 else {
228 char *thisName2 = names[j1];
229
230 if ( strcmp ( thisName, thisName2 ) == 0 ) {
231 printf ( "** duplicate name %s\n", names[i] );
232 abort();
233 break;
234 } else {
235 int k = hash_[ipos].next;
236
237 if ( k == -1 ) {
238 while ( true ) {
239 ++lastSlot_;
240 if ( lastSlot_ > numberItems_ ) {
241 printf ( "** too many names\n" );
242 abort();
243 break;
244 }
245 if ( hash_[lastSlot_].index == -1 ) {
246 break;
247 }
248 }
249 hash_[ipos].next = lastSlot_;
250 hash_[lastSlot_].index = i;
251 break;
252 } else {
253 ipos = k;
254 /* nothing worked - try it again */
255 }
256 }
257 }
258 }
259 }
260
261 }
262 // validate
263 void
validateHash() const264 CoinModelHash::validateHash() const
265 {
266 for (int i = 0; i < numberItems_; ++i ) {
267 if (names_[i]) {
268 assert (hash( names_[i])>=0);
269 }
270 }
271 }
272 // Returns index or -1
273 int
hash(const char * name) const274 CoinModelHash::hash(const char * name) const
275 {
276 int found = -1;
277
278 int ipos;
279
280 /* default if we don't find anything */
281 if ( !numberItems_ )
282 return -1;
283
284 ipos = hashValue ( name );
285 while ( true ) {
286 int j1 = hash_[ipos].index;
287
288 if ( j1 >= 0 ) {
289 char *thisName2 = names_[j1];
290
291 if ( strcmp ( name, thisName2 ) != 0 ) {
292 int k = hash_[ipos].next;
293
294 if ( k != -1 )
295 ipos = k;
296 else
297 break;
298 } else {
299 found = j1;
300 break;
301 }
302 } else {
303 int k = hash_[ipos].next;
304
305 if ( k != -1 )
306 ipos = k;
307 else
308 break;
309 }
310 }
311 return found;
312 }
313 // Adds to hash
314 void
addHash(int index,const char * name)315 CoinModelHash::addHash(int index, const char * name)
316 {
317 // resize if necessary
318 if (numberItems_>=maximumItems_)
319 resize(1000+3*numberItems_/2);
320 assert (!names_[index]);
321 names_[index]=CoinStrdup(name);
322 int ipos = hashValue ( name);
323 numberItems_ = CoinMax(numberItems_,index+1);
324 if ( hash_[ipos].index <0 ) {
325 hash_[ipos].index = index;
326 } else {
327 while ( true ) {
328 int j1 = hash_[ipos].index;
329
330 if ( j1 == index )
331 break; // duplicate?
332 else {
333 if (j1>=0) {
334 char *thisName2 = names_[j1];
335 if ( strcmp ( name, thisName2 ) == 0 ) {
336 printf ( "** duplicate name %s\n", names_[index] );
337 abort();
338 break;
339 } else {
340 int k = hash_[ipos].next;
341
342 if ( k == -1 ) {
343 while ( true ) {
344 ++lastSlot_;
345 if ( lastSlot_ > numberItems_ ) {
346 printf ( "** too many names\n" );
347 abort();
348 break;
349 }
350 if ( hash_[lastSlot_].index <0 && hash_[lastSlot_].next<0) {
351 break;
352 }
353 }
354 hash_[ipos].next = lastSlot_;
355 hash_[lastSlot_].index = index;
356 hash_[lastSlot_].next=-1;
357 break;
358 } else {
359 ipos = k;
360 }
361 }
362 } else {
363 //slot available
364 hash_[ipos].index = index;
365 }
366 }
367 }
368 }
369 }
370 // Deletes from hash
371 void
deleteHash(int index)372 CoinModelHash::deleteHash(int index)
373 {
374 if (index<numberItems_&&names_[index]) {
375
376 int ipos = hashValue ( names_[index] );
377
378 while ( ipos>=0 ) {
379 int j1 = hash_[ipos].index;
380 if ( j1!=index) {
381 ipos = hash_[ipos].next;
382 } else {
383 hash_[ipos].index=-1; // available
384 break;
385 }
386 }
387 assert (ipos>=0);
388 free(names_[index]);
389 names_[index]=NULL;
390 }
391 }
392 // Returns name at position (or NULL)
393 const char *
name(int which) const394 CoinModelHash::name(int which) const
395 {
396 if (which<numberItems_)
397 return names_[which];
398 else
399 return NULL;
400 }
401 // Returns non const name at position (or NULL)
402 char *
getName(int which) const403 CoinModelHash::getName(int which) const
404 {
405 if (which<numberItems_)
406 return names_[which];
407 else
408 return NULL;
409 }
410 // Sets name at position (does not create)
411 void
setName(int which,char * name)412 CoinModelHash::setName(int which,char * name )
413 {
414 if (which<numberItems_)
415 names_[which]=name;
416 }
417 // Returns a hash value
418 int
hashValue(const char * name) const419 CoinModelHash::hashValue(const char * name) const
420 {
421
422 int n = 0;
423 int j;
424 int length = static_cast<int> (strlen(name));
425 // may get better spread with unsigned
426 const unsigned char * name2 = reinterpret_cast<const unsigned char *> (name);
427 while (length) {
428 int length2 = CoinMin( length,lengthMult);
429 for ( j = 0; j < length2; ++j ) {
430 n += mmult[j] * name2[j];
431 }
432 name+=length2;
433 length-=length2;
434 }
435 int maxHash = 4 * maximumItems_;
436 return ( abs ( n ) % maxHash ); /* integer abs */
437 }
438 //#############################################################################
439 // Constructors / Destructor / Assignment
440 //#############################################################################
441 //-------------------------------------------------------------------
442 // Default Constructor
443 //-------------------------------------------------------------------
CoinModelHash2()444 CoinModelHash2::CoinModelHash2 ()
445 : hash_(NULL),
446 numberItems_(0),
447 maximumItems_(0),
448 lastSlot_(-1)
449 {
450 }
451
452 //-------------------------------------------------------------------
453 // Copy constructor
454 //-------------------------------------------------------------------
CoinModelHash2(const CoinModelHash2 & rhs)455 CoinModelHash2::CoinModelHash2 (const CoinModelHash2 & rhs)
456 : hash_(NULL),
457 numberItems_(rhs.numberItems_),
458 maximumItems_(rhs.maximumItems_),
459 lastSlot_(rhs.lastSlot_)
460 {
461 if (maximumItems_) {
462 hash_ = CoinCopyOfArray(rhs.hash_,4*maximumItems_);
463 }
464 }
465
466 //-------------------------------------------------------------------
467 // Destructor
468 //-------------------------------------------------------------------
~CoinModelHash2()469 CoinModelHash2::~CoinModelHash2 ()
470 {
471 delete [] hash_;
472 }
473
474 //----------------------------------------------------------------
475 // Assignment operator
476 //-------------------------------------------------------------------
477 CoinModelHash2 &
operator =(const CoinModelHash2 & rhs)478 CoinModelHash2::operator=(const CoinModelHash2& rhs)
479 {
480 if (this != &rhs) {
481 delete [] hash_;
482 numberItems_ = rhs.numberItems_;
483 maximumItems_ = rhs.maximumItems_;
484 lastSlot_ = rhs.lastSlot_;
485 if (maximumItems_) {
486 hash_ = CoinCopyOfArray(rhs.hash_,4*maximumItems_);
487 } else {
488 hash_ = NULL;
489 }
490 }
491 return *this;
492 }
493 // Set number of items
494 void
setNumberItems(int number)495 CoinModelHash2::setNumberItems(int number)
496 {
497 assert (number>=0&&(number<=numberItems_||!numberItems_));
498 numberItems_=number;
499 }
500 // Resize hash (also re-hashs)
501 void
resize(int maxItems,const CoinModelTriple * triples,bool forceReHash)502 CoinModelHash2::resize(int maxItems, const CoinModelTriple * triples,bool forceReHash)
503 {
504 assert (numberItems_<=maximumItems_||!maximumItems_);
505 if (maxItems<=maximumItems_&&!forceReHash)
506 return;
507 if (maxItems>maximumItems_) {
508 maximumItems_=maxItems;
509 delete [] hash_;
510 hash_ = new CoinModelHashLink [4*maximumItems_];
511 }
512 int maxHash = 4 * maximumItems_;
513 int ipos;
514 int i;
515 for ( i = 0; i < maxHash; i++ ) {
516 hash_[i].index = -1;
517 hash_[i].next = -1;
518 }
519
520 /*
521 * Initialize the hash table. Only the index of the first name that
522 * hashes to a value is entered in the table; subsequent names that
523 * collide with it are not entered.
524 */
525 for ( i = 0; i < numberItems_; ++i ) {
526 int row = static_cast<int> (rowInTriple(triples[i]));
527 int column = triples[i].column;
528 if (column>=0) {
529 ipos = hashValue ( row, column);
530 if ( hash_[ipos].index == -1 ) {
531 hash_[ipos].index = i;
532 }
533 }
534 }
535
536 /*
537 * Now take care of the entries that collided in the preceding loop,
538 * by finding some other entry in the table for them.
539 * Since there are as many entries in the table as there are entries,
540 * there must be room for them.
541 */
542 lastSlot_ = -1;
543 for ( i = 0; i < numberItems_; ++i ) {
544 int row = static_cast<int> (rowInTriple(triples[i]));
545 int column = triples[i].column;
546 if (column>=0) {
547 ipos = hashValue ( row, column);
548
549 while ( true ) {
550 int j1 = hash_[ipos].index;
551
552 if ( j1 == i )
553 break;
554 else {
555 int row2 = static_cast<int> (rowInTriple(triples[j1]));
556 int column2 = triples[j1].column;
557 if ( row==row2&&column==column2 ) {
558 printf ( "** duplicate entry %d %d\n", row,column );
559 abort();
560 break;
561 } else {
562 int k = hash_[ipos].next;
563
564 if ( k == -1 ) {
565 while ( true ) {
566 ++lastSlot_;
567 if ( lastSlot_ > numberItems_ ) {
568 printf ( "** too many entries\n" );
569 abort();
570 break;
571 }
572 if ( hash_[lastSlot_].index == -1 ) {
573 break;
574 }
575 }
576 hash_[ipos].next = lastSlot_;
577 hash_[lastSlot_].index = i;
578 break;
579 } else {
580 ipos = k;
581 }
582 }
583 }
584 }
585 }
586 }
587
588 }
589 // Returns index or -1
590 int
hash(int row,int column,const CoinModelTriple * triples) const591 CoinModelHash2::hash(int row, int column, const CoinModelTriple * triples) const
592 {
593 int found = -1;
594
595 int ipos;
596
597 /* default if we don't find anything */
598 if ( !numberItems_ )
599 return -1;
600
601 ipos = hashValue ( row, column );
602 while ( true ) {
603 int j1 = hash_[ipos].index;
604
605 if ( j1 >= 0 ) {
606 int row2 = static_cast<int> (rowInTriple(triples[j1]));
607 int column2 = triples[j1].column;
608 if ( row!=row2||column!=column2 ) {
609 int k = hash_[ipos].next;
610
611 if ( k != -1 )
612 ipos = k;
613 else
614 break;
615 } else {
616 found = j1;
617 break;
618 }
619 } else {
620 int k = hash_[ipos].next;
621
622 if ( k != -1 )
623 ipos = k;
624 else
625 break;
626 }
627 }
628 return found;
629 }
630 // Adds to hash
631 void
addHash(int index,int row,int column,const CoinModelTriple * triples)632 CoinModelHash2::addHash(int index, int row, int column, const CoinModelTriple * triples)
633 {
634 // resize if necessary
635 if (numberItems_>=maximumItems_||index+1>=maximumItems_)
636 resize(CoinMax(1000+3*numberItems_/2,index+1), triples);
637 int ipos = hashValue ( row, column);
638 numberItems_ = CoinMax(numberItems_,index+1);
639 assert (numberItems_<=maximumItems_);
640 if ( hash_[ipos].index <0 ) {
641 hash_[ipos].index = index;
642 } else {
643 while ( true ) {
644 int j1 = hash_[ipos].index;
645
646 if ( j1 == index ) {
647 break; // duplicate??
648 } else {
649 if (j1 >=0 ) {
650 int row2 = static_cast<int> (rowInTriple(triples[j1]));
651 int column2 = triples[j1].column;
652 if ( row==row2&&column==column2 ) {
653 printf ( "** duplicate entry %d %d\n", row, column );
654 abort();
655 break;
656 } else {
657 int k = hash_[ipos].next;
658
659 if ( k ==-1 ) {
660 while ( true ) {
661 ++lastSlot_;
662 if ( lastSlot_ > numberItems_ ) {
663 printf ( "** too many entrys\n" );
664 abort();
665 break;
666 }
667 if ( hash_[lastSlot_].index <0 ) {
668 break;
669 }
670 }
671 hash_[ipos].next = lastSlot_;
672 hash_[lastSlot_].index = index;
673 hash_[lastSlot_].next=-1;
674 break;
675 } else {
676 ipos = k;
677 }
678 }
679 } else {
680 // slot available
681 hash_[ipos].index = index;
682 }
683 }
684 }
685 }
686 }
687 // Deletes from hash
688 void
deleteHash(int index,int row,int column)689 CoinModelHash2::deleteHash(int index,int row, int column)
690 {
691 if (index<numberItems_) {
692
693 int ipos = hashValue ( row, column );
694
695 while ( ipos>=0 ) {
696 int j1 = hash_[ipos].index;
697 if ( j1!=index) {
698 ipos = hash_[ipos].next;
699 } else {
700 hash_[ipos].index=-1; // available
701 break;
702 }
703 }
704 }
705 }
706 namespace {
707 const int mmult2[] = {
708 262139, 259459, 256889, 254291, 251701, 249133, 246709, 244247,
709 241667, 239179, 236609, 233983, 231289, 228859, 226357, 223829
710 };
711 }
712 // Returns a hash value
713 int
hashValue(int row,int column) const714 CoinModelHash2::hashValue(int row, int column) const
715 {
716
717 // Optimizer should take out one side of if
718 if (sizeof(int)==4*sizeof(char)) {
719 unsigned char tempChar[4];
720
721 unsigned int n = 0;
722 int * temp = reinterpret_cast<int *> (tempChar);
723 *temp=row;
724 n += mmult2[0] * tempChar[0];
725 n += mmult2[1] * tempChar[1];
726 n += mmult2[2] * tempChar[2];
727 n += mmult[3] * tempChar[3];
728 *temp=column;
729 n += mmult2[0+8] * tempChar[0];
730 n += mmult2[1+8] * tempChar[1];
731 n += mmult2[2+8] * tempChar[2];
732 n += mmult2[3+8] * tempChar[3];
733 return n % (maximumItems_<<1);
734 } else {
735 // ints are 8
736 unsigned char tempChar[8];
737
738 int n = 0;
739 unsigned int j;
740 int * temp = reinterpret_cast<int *> (tempChar);
741 *temp=row;
742 for ( j = 0; j < sizeof(int); ++j ) {
743 int itemp = tempChar[j];
744 n += mmult2[j] * itemp;
745 }
746 *temp=column;
747 for ( j = 0; j < sizeof(int); ++j ) {
748 int itemp = tempChar[j];
749 n += mmult2[j+8] * itemp;
750 }
751 int maxHash = 4 * maximumItems_;
752 int absN = abs(n);
753 int returnValue = absN % maxHash;
754 return returnValue;
755 }
756 }
757 //#############################################################################
758 // Constructors / Destructor / Assignment
759 //#############################################################################
760
761 //-------------------------------------------------------------------
762 // Default Constructor
763 //-------------------------------------------------------------------
CoinModelLinkedList()764 CoinModelLinkedList::CoinModelLinkedList ()
765 : previous_(NULL),
766 next_(NULL),
767 first_(NULL),
768 last_(NULL),
769 numberMajor_(0),
770 maximumMajor_(0),
771 numberElements_(0),
772 maximumElements_(0),
773 type_(-1)
774 {
775 }
776
777 //-------------------------------------------------------------------
778 // Copy constructor
779 //-------------------------------------------------------------------
CoinModelLinkedList(const CoinModelLinkedList & rhs)780 CoinModelLinkedList::CoinModelLinkedList (const CoinModelLinkedList & rhs)
781 : numberMajor_(rhs.numberMajor_),
782 maximumMajor_(rhs.maximumMajor_),
783 numberElements_(rhs.numberElements_),
784 maximumElements_(rhs.maximumElements_),
785 type_(rhs.type_)
786 {
787 if (maximumMajor_) {
788 previous_ = CoinCopyOfArray(rhs.previous_,maximumElements_);
789 next_ = CoinCopyOfArray(rhs.next_,maximumElements_);
790 first_ = CoinCopyOfArray(rhs.first_,maximumMajor_+1);
791 last_ = CoinCopyOfArray(rhs.last_,maximumMajor_+1);
792 } else {
793 previous_ = NULL;
794 next_ = NULL;
795 first_ = NULL;
796 last_ = NULL;
797 }
798 }
799
800 //-------------------------------------------------------------------
801 // Destructor
802 //-------------------------------------------------------------------
~CoinModelLinkedList()803 CoinModelLinkedList::~CoinModelLinkedList ()
804 {
805 delete [] previous_;
806 delete [] next_;
807 delete [] first_;
808 delete [] last_;
809 }
810
811 //----------------------------------------------------------------
812 // Assignment operator
813 //-------------------------------------------------------------------
814 CoinModelLinkedList &
operator =(const CoinModelLinkedList & rhs)815 CoinModelLinkedList::operator=(const CoinModelLinkedList& rhs)
816 {
817 if (this != &rhs) {
818 delete [] previous_;
819 delete [] next_;
820 delete [] first_;
821 delete [] last_;
822 numberMajor_ = rhs.numberMajor_;
823 maximumMajor_ = rhs.maximumMajor_;
824 numberElements_ = rhs.numberElements_;
825 maximumElements_ = rhs.maximumElements_;
826 type_ = rhs.type_;
827 if (maximumMajor_) {
828 previous_ = CoinCopyOfArray(rhs.previous_,maximumElements_);
829 next_ = CoinCopyOfArray(rhs.next_,maximumElements_);
830 first_ = CoinCopyOfArray(rhs.first_,maximumMajor_+1);
831 last_ = CoinCopyOfArray(rhs.last_,maximumMajor_+1);
832 } else {
833 previous_ = NULL;
834 next_ = NULL;
835 first_ = NULL;
836 last_ = NULL;
837 }
838 }
839 return *this;
840 }
841 // Resize list - for row list maxMajor is maximum rows
842 void
resize(int maxMajor,int maxElements)843 CoinModelLinkedList::resize(int maxMajor,int maxElements)
844 {
845 maxMajor=CoinMax(maxMajor,maximumMajor_);
846 maxElements=CoinMax(maxElements,maximumElements_);
847 if (maxMajor>maximumMajor_) {
848 int * first = new int [maxMajor+1];
849 int free;
850 if (maximumMajor_) {
851 CoinMemcpyN(first_,maximumMajor_,first);
852 # ifdef ZEROFAULT
853 memset(first+maximumMajor_,0,(maxMajor-maximumMajor_)*sizeof(int)) ;
854 # endif
855 free = first_[maximumMajor_];
856 first[maximumMajor_]=-1;
857 } else {
858 free=-1;
859 }
860 first[maxMajor]=free;
861 delete [] first_;
862 first_=first;
863 int * last = new int [maxMajor+1];
864 if (maximumMajor_) {
865 CoinMemcpyN(last_,maximumMajor_,last);
866 # ifdef ZEROFAULT
867 memset(last+maximumMajor_,0,(maxMajor-maximumMajor_)*sizeof(int)) ;
868 # endif
869 free = last_[maximumMajor_];
870 last[maximumMajor_]=-1;
871 } else {
872 free=-1;
873 }
874 last[maxMajor]=free;
875 delete [] last_;
876 last_=last;
877 maximumMajor_ = maxMajor;
878 }
879 if ( maxElements>maximumElements_) {
880 int * previous = new int [maxElements];
881 CoinMemcpyN(previous_,numberElements_,previous);
882 # ifdef ZEROFAULT
883 memset(previous+numberElements_,0,
884 (maxElements-numberElements_)*sizeof(int)) ;
885 # endif
886 delete [] previous_;
887 previous_=previous;
888 int * next = new int [maxElements];
889 CoinMemcpyN(next_,numberElements_,next);
890 # ifdef ZEROFAULT
891 memset(next+numberElements_,0,(maxElements-numberElements_)*sizeof(int)) ;
892 # endif
893 delete [] next_;
894 next_=next;
895 maximumElements_=maxElements;
896 }
897 }
898 // Create list - for row list maxMajor is maximum rows
899 void
create(int maxMajor,int maxElements,int numberMajor,int,int type,int numberElements,const CoinModelTriple * triples)900 CoinModelLinkedList::create(int maxMajor,int maxElements,
901 int numberMajor,int /*numberMinor*/, int type,
902 int numberElements, const CoinModelTriple * triples)
903 {
904 maxMajor=CoinMax(maxMajor,maximumMajor_);
905 maxMajor=CoinMax(maxMajor,numberMajor);
906 maxElements=CoinMax(maxElements,maximumElements_);
907 maxElements=CoinMax(maxElements,numberElements);
908 type_=type;
909 assert (!previous_);
910 previous_ = new int [maxElements];
911 next_ = new int [maxElements];
912 maximumElements_=maxElements;
913 assert (maxElements>=numberElements);
914 assert (maxMajor>0&&!maximumMajor_);
915 first_ = new int[maxMajor+1];
916 last_ = new int[maxMajor+1];
917 # ifdef ZEROFAULT
918 memset(previous_,0,maxElements*sizeof(int)) ;
919 memset(next_,0,maxElements*sizeof(int)) ;
920 memset(first_,0,(maxMajor+1)*sizeof(int)) ;
921 memset(last_,0,(maxMajor+1)*sizeof(int)) ;
922 # endif
923 assert (numberElements>=0);
924 numberElements_=numberElements;
925 maximumMajor_ = maxMajor;
926 // do lists
927 int i;
928 for (i=0;i<numberMajor;i++) {
929 first_[i]=-1;
930 last_[i]=-1;
931 }
932 first_[maximumMajor_]=-1;
933 last_[maximumMajor_]=-1;
934 int freeChain=-1;
935 for (i=0;i<numberElements;i++) {
936 if (triples[i].column>=0) {
937 int iMajor;
938 int iMinor;
939 if (!type_) {
940 // for rows
941 iMajor=static_cast<int> (rowInTriple(triples[i]));
942 iMinor=triples[i].column;
943 } else {
944 iMinor=static_cast<int> (rowInTriple(triples[i]));
945 iMajor=triples[i].column;
946 }
947 assert (iMajor<numberMajor);
948 if (first_[iMajor]>=0) {
949 // not first
950 int j=last_[iMajor];
951 next_[j]=i;
952 previous_[i]=j;
953 } else {
954 // first
955 first_[iMajor]=i;
956 previous_[i]=-1;
957 }
958 last_[iMajor]=i;
959 } else {
960 // on deleted list
961 if (freeChain>=0) {
962 next_[freeChain]=i;
963 previous_[i]=freeChain;
964 } else {
965 first_[maximumMajor_]=i;
966 previous_[i]=-1;
967 }
968 freeChain=i;
969 }
970 }
971 // Now clean up
972 if (freeChain>=0) {
973 next_[freeChain]=-1;
974 last_[maximumMajor_]=freeChain;
975 }
976 for (i=0;i<numberMajor;i++) {
977 int k=last_[i];
978 if (k>=0) {
979 next_[k]=-1;
980 last_[i]=k;
981 }
982 }
983 numberMajor_=numberMajor;
984 }
985 /* Adds to list - easy case i.e. add row to row list
986 Returns where chain starts
987 */
988 int
addEasy(int majorIndex,int numberOfElements,const int * indices,const double * elements,CoinModelTriple * triples,CoinModelHash2 & hash)989 CoinModelLinkedList::addEasy(int majorIndex, int numberOfElements, const int * indices,
990 const double * elements, CoinModelTriple * triples,
991 CoinModelHash2 & hash)
992 {
993 assert (majorIndex<maximumMajor_);
994 if (numberOfElements+numberElements_>maximumElements_) {
995 resize(maximumMajor_,(3*(numberElements_+numberOfElements))/2+1000);
996 }
997 int first=-1;
998 if (majorIndex>=numberMajor_) {
999 for (int i=numberMajor_;i<=majorIndex;i++) {
1000 first_[i]=-1;
1001 last_[i]=-1;
1002 }
1003 }
1004 if (numberOfElements) {
1005 bool doHash = hash.maximumItems()!=0;
1006 int lastFree=last_[maximumMajor_];
1007 int last=last_[majorIndex];
1008 for (int i=0;i<numberOfElements;i++) {
1009 int put;
1010 if (lastFree>=0) {
1011 put=lastFree;
1012 lastFree=previous_[lastFree];
1013 } else {
1014 put=numberElements_;
1015 assert (put<maximumElements_);
1016 numberElements_++;
1017 }
1018 if (type_==0) {
1019 // row
1020 setRowAndStringInTriple(triples[put],majorIndex,false);
1021 triples[put].column=indices[i];
1022 } else {
1023 // column
1024 setRowAndStringInTriple(triples[put],indices[i],false);
1025 triples[put].column=majorIndex;
1026 }
1027 triples[put].value=elements[i];
1028 if (doHash)
1029 hash.addHash(put,static_cast<int> (rowInTriple(triples[put])),triples[put].column,triples);
1030 if (last>=0) {
1031 next_[last]=put;
1032 } else {
1033 first_[majorIndex]=put;
1034 }
1035 previous_[put]=last;
1036 last=put;
1037 }
1038 next_[last]=-1;
1039 if (last_[majorIndex]<0) {
1040 // first in row
1041 first = first_[majorIndex];
1042 } else {
1043 first = next_[last_[majorIndex]];
1044 }
1045 last_[majorIndex]=last;
1046 if (lastFree>=0) {
1047 next_[lastFree]=-1;
1048 last_[maximumMajor_]=lastFree;
1049 } else {
1050 first_[maximumMajor_]=-1;
1051 last_[maximumMajor_]=-1;
1052 }
1053 }
1054 numberMajor_=CoinMax(numberMajor_,majorIndex+1);
1055 return first;
1056 }
1057 /* Adds to list - hard case i.e. add row to column list
1058 */
1059 void
addHard(int minorIndex,int numberOfElements,const int * indices,const double * elements,CoinModelTriple * triples,CoinModelHash2 & hash)1060 CoinModelLinkedList::addHard(int minorIndex, int numberOfElements, const int * indices,
1061 const double * elements, CoinModelTriple * triples,
1062 CoinModelHash2 & hash)
1063 {
1064 int lastFree=last_[maximumMajor_];
1065 bool doHash = hash.maximumItems()!=0;
1066 for (int i=0;i<numberOfElements;i++) {
1067 int put;
1068 if (lastFree>=0) {
1069 put=lastFree;
1070 lastFree=previous_[lastFree];
1071 } else {
1072 put=numberElements_;
1073 assert (put<maximumElements_);
1074 numberElements_++;
1075 }
1076 int other=indices[i];
1077 if (type_==0) {
1078 // row
1079 setRowAndStringInTriple(triples[put],other,false);
1080 triples[put].column=minorIndex;
1081 } else {
1082 // column
1083 setRowAndStringInTriple(triples[put],minorIndex,false);
1084 triples[put].column=other;
1085 }
1086 triples[put].value=elements[i];
1087 if (doHash)
1088 hash.addHash(put,static_cast<int> (rowInTriple(triples[put])),triples[put].column,triples);
1089 if (other>=numberMajor_) {
1090 // Need to fill in null values
1091 fill(numberMajor_,other+1);
1092 numberMajor_=other+1;
1093 }
1094 int last=last_[other];
1095 if (last>=0) {
1096 next_[last]=put;
1097 } else {
1098 first_[other]=put;
1099 }
1100 previous_[put]=last;
1101 next_[put]=-1;
1102 last_[other]=put;
1103 }
1104 if (lastFree>=0) {
1105 next_[lastFree]=-1;
1106 last_[maximumMajor_]=lastFree;
1107 } else {
1108 first_[maximumMajor_]=-1;
1109 last_[maximumMajor_]=-1;
1110 }
1111 }
1112 /* Adds to list - hard case i.e. add row to column list
1113 This is when elements have been added to other copy
1114 */
1115 void
addHard(int first,const CoinModelTriple * triples,int firstFree,int lastFree,const int * next)1116 CoinModelLinkedList::addHard(int first, const CoinModelTriple * triples,
1117 int firstFree, int lastFree,const int * next)
1118 {
1119 first_[maximumMajor_]=firstFree;
1120 last_[maximumMajor_]=lastFree;
1121 int put=first;
1122 int minorIndex=-1;
1123 while (put>=0) {
1124 assert (put<maximumElements_);
1125 numberElements_=CoinMax(numberElements_,put+1);
1126 int other;
1127 if (type_==0) {
1128 // row
1129 other=rowInTriple(triples[put]);
1130 if (minorIndex>=0)
1131 assert(triples[put].column==minorIndex);
1132 else
1133 minorIndex=triples[put].column;
1134 } else {
1135 // column
1136 other=triples[put].column;
1137 if (minorIndex>=0)
1138 assert(static_cast<int> (rowInTriple(triples[put]))==minorIndex);
1139 else
1140 minorIndex=rowInTriple(triples[put]);
1141 }
1142 assert (other<maximumMajor_);
1143 if (other>=numberMajor_) {
1144 // Need to fill in null values
1145 fill (numberMajor_,other+1);
1146 numberMajor_=other+1;
1147 }
1148 int last=last_[other];
1149 if (last>=0) {
1150 next_[last]=put;
1151 } else {
1152 first_[other]=put;
1153 }
1154 previous_[put]=last;
1155 next_[put]=-1;
1156 last_[other]=put;
1157 put = next[put];
1158 }
1159 }
1160 /* Deletes from list - same case i.e. delete row from row list
1161 */
1162 void
deleteSame(int which,CoinModelTriple * triples,CoinModelHash2 & hash,bool zapTriples)1163 CoinModelLinkedList::deleteSame(int which, CoinModelTriple * triples,
1164 CoinModelHash2 & hash, bool zapTriples)
1165 {
1166 assert (which>=0);
1167 if (which<numberMajor_) {
1168 int lastFree=last_[maximumMajor_];
1169 int put=first_[which];
1170 first_[which]=-1;
1171 while (put>=0) {
1172 if (hash.numberItems()) {
1173 // take out of hash
1174 hash.deleteHash(put, static_cast<int> (rowInTriple(triples[put])),triples[put].column);
1175 }
1176 if (zapTriples) {
1177 triples[put].column=-1;
1178 triples[put].value=0.0;
1179 }
1180 if (lastFree>=0) {
1181 next_[lastFree]=put;
1182 } else {
1183 first_[maximumMajor_]=put;
1184 }
1185 previous_[put]=lastFree;
1186 lastFree=put;
1187 put=next_[put];
1188 }
1189 if (lastFree>=0) {
1190 next_[lastFree]=-1;
1191 last_[maximumMajor_]=lastFree;
1192 } else {
1193 assert (last_[maximumMajor_]==-1);
1194 }
1195 last_[which]=-1;
1196 }
1197 }
1198 /* Deletes from list - other case i.e. delete row from column list
1199 This is when elements have been deleted from other copy
1200 */
1201 void
updateDeleted(int,CoinModelTriple * triples,CoinModelLinkedList & otherList)1202 CoinModelLinkedList::updateDeleted(int /*which*/, CoinModelTriple * triples,
1203 CoinModelLinkedList & otherList)
1204 {
1205 int firstFree = otherList.firstFree();
1206 int lastFree = otherList.lastFree();
1207 const int * previousOther = otherList.previous();
1208 assert (maximumMajor_);
1209 if (lastFree>=0) {
1210 // First free should be same
1211 if (first_[maximumMajor_]>=0)
1212 assert (firstFree==first_[maximumMajor_]);
1213 int last = last_[maximumMajor_];
1214 first_[maximumMajor_]=firstFree;
1215 // Maybe nothing to do
1216 if (last_[maximumMajor_]==lastFree)
1217 return;
1218 last_[maximumMajor_]=lastFree;
1219 int iMajor;
1220 if (!type_) {
1221 // for rows
1222 iMajor=static_cast<int> (rowInTriple(triples[lastFree]));
1223 } else {
1224 iMajor=triples[lastFree].column;
1225 }
1226 if (first_[iMajor]>=0) {
1227 // take out
1228 int previousThis = previous_[lastFree];
1229 int nextThis = next_[lastFree];
1230 if (previousThis>=0&&previousThis!=last) {
1231 next_[previousThis]=nextThis;
1232 int iTest;
1233 if (!type_) {
1234 // for rows
1235 iTest=static_cast<int> (rowInTriple(triples[previousThis]));
1236 } else {
1237 iTest=triples[previousThis].column;
1238 }
1239 assert (triples[previousThis].column>=0);
1240 assert (iTest==iMajor);
1241 } else {
1242 first_[iMajor]=nextThis;
1243 }
1244 if (nextThis>=0) {
1245 previous_[nextThis]=previousThis;
1246 int iTest;
1247 if (!type_) {
1248 // for rows
1249 iTest=static_cast<int> (rowInTriple(triples[nextThis]));
1250 } else {
1251 iTest=triples[nextThis].column;
1252 }
1253 assert (triples[nextThis].column>=0);
1254 assert (iTest==iMajor);
1255 } else {
1256 last_[iMajor]=previousThis;
1257 }
1258 }
1259 triples[lastFree].column=-1;
1260 triples[lastFree].value=0.0;
1261 // Do first (by which I mean last)
1262 next_[lastFree]=-1;
1263 int previous = previousOther[lastFree];
1264 while (previous!=last) {
1265 if (previous>=0) {
1266 if (!type_) {
1267 // for rows
1268 iMajor=static_cast<int> (rowInTriple(triples[previous]));
1269 } else {
1270 iMajor=triples[previous].column;
1271 }
1272 if (first_[iMajor]>=0) {
1273 // take out
1274 int previousThis = previous_[previous];
1275 int nextThis = next_[previous];
1276 if (previousThis>=0&&previousThis!=last) {
1277 next_[previousThis]=nextThis;
1278 int iTest;
1279 if (!type_) {
1280 // for rows
1281 iTest=static_cast<int> (rowInTriple(triples[previousThis]));
1282 } else {
1283 iTest=triples[previousThis].column;
1284 }
1285 assert (triples[previousThis].column>=0);
1286 assert (iTest==iMajor);
1287 } else {
1288 first_[iMajor]=nextThis;
1289 }
1290 if (nextThis>=0) {
1291 previous_[nextThis]=previousThis;
1292 int iTest;
1293 if (!type_) {
1294 // for rows
1295 iTest=static_cast<int> (rowInTriple(triples[nextThis]));
1296 } else {
1297 iTest=triples[nextThis].column;
1298 }
1299 assert (triples[nextThis].column>=0);
1300 assert (iTest==iMajor);
1301 } else {
1302 last_[iMajor]=previousThis;
1303 }
1304 }
1305 triples[previous].column=-1;
1306 triples[previous].value=0.0;
1307 next_[previous]=lastFree;
1308 } else {
1309 assert (lastFree==firstFree);
1310 }
1311 previous_[lastFree]=previous;
1312 lastFree=previous;
1313 previous = previousOther[lastFree];
1314 }
1315 if (last>=0) {
1316 next_[previous]=lastFree;
1317 } else {
1318 assert (firstFree==lastFree);
1319 }
1320 previous_[lastFree]=previous;
1321 }
1322 }
1323 /* Deletes one element from Row list
1324 */
1325 void
deleteRowOne(int position,CoinModelTriple * triples,CoinModelHash2 & hash)1326 CoinModelLinkedList::deleteRowOne(int position, CoinModelTriple * triples,
1327 CoinModelHash2 & hash)
1328 {
1329 int row=rowInTriple(triples[position]);
1330 assert (row<numberMajor_);
1331 if (hash.numberItems()) {
1332 // take out of hash
1333 hash.deleteHash(position, static_cast<int> (rowInTriple(triples[position])),triples[position].column);
1334 }
1335 int previous = previous_[position];
1336 int next = next_[position];
1337 // put on free list
1338 int lastFree=last_[maximumMajor_];
1339 if (lastFree>=0) {
1340 next_[lastFree]=position;
1341 } else {
1342 first_[maximumMajor_]=position;
1343 assert (last_[maximumMajor_]==-1);
1344 }
1345 last_[maximumMajor_]=position;
1346 previous_[position]=lastFree;
1347 next_[position]=-1;
1348 // Now take out of row
1349 if (previous>=0) {
1350 next_[previous]=next;
1351 } else {
1352 first_[row]=next;
1353 }
1354 if (next>=0) {
1355 previous_[next]=previous;
1356 } else {
1357 last_[row]=previous;
1358 }
1359 }
1360 /* Update column list for one element when
1361 one element deleted from row copy
1362 */
1363 void
updateDeletedOne(int position,const CoinModelTriple * triples)1364 CoinModelLinkedList::updateDeletedOne(int position, const CoinModelTriple * triples)
1365 {
1366 assert (maximumMajor_);
1367 int column=triples[position].column;
1368 assert (column>=0&&column<numberMajor_);
1369 int previous = previous_[position];
1370 int next = next_[position];
1371 // put on free list
1372 int lastFree=last_[maximumMajor_];
1373 if (lastFree>=0) {
1374 next_[lastFree]=position;
1375 } else {
1376 first_[maximumMajor_]=position;
1377 assert (last_[maximumMajor_]==-1);
1378 }
1379 last_[maximumMajor_]=position;
1380 previous_[position]=lastFree;
1381 next_[position]=-1;
1382 // Now take out of column
1383 if (previous>=0) {
1384 next_[previous]=next;
1385 } else {
1386 first_[column]=next;
1387 }
1388 if (next>=0) {
1389 previous_[next]=previous;
1390 } else {
1391 last_[column]=previous;
1392 }
1393 }
1394 // Fills first,last with -1
1395 void
fill(int first,int last)1396 CoinModelLinkedList::fill(int first,int last)
1397 {
1398 for (int i=first;i<last;i++) {
1399 first_[i]=-1;
1400 last_[i]=-1;
1401 }
1402 }
1403 /* Puts in free list from other list */
1404 void
synchronize(CoinModelLinkedList & other)1405 CoinModelLinkedList::synchronize(CoinModelLinkedList & other)
1406 {
1407 int first = other.first_[other.maximumMajor_];
1408 first_[maximumMajor_]=first;
1409 int last = other.last_[other.maximumMajor_];
1410 last_[maximumMajor_]=last;
1411 int put=first;
1412 while (put>=0) {
1413 previous_[put]=other.previous_[put];
1414 next_[put]=other.next_[put];
1415 put = next_[put];
1416 }
1417 }
1418 // Checks that links are consistent
1419 void
validateLinks(const CoinModelTriple * triples) const1420 CoinModelLinkedList::validateLinks(const CoinModelTriple * triples) const
1421 {
1422 char * mark = new char[maximumElements_];
1423 memset(mark,0,maximumElements_);
1424 int lastElement=-1;
1425 int i;
1426 for ( i=0;i<numberMajor_;i++) {
1427 int position = first_[i];
1428 int lastPosition=-1;
1429 while (position>=0) {
1430 int iMajor;
1431 if (position!=first_[i])
1432 assert (next_[previous_[position]]==position);
1433 if (!type_) {
1434 // for rows
1435 iMajor=static_cast<int> (rowInTriple(triples[position]));
1436 } else {
1437 iMajor=triples[position].column;
1438 }
1439 assert (triples[position].column>=0);
1440 mark[position]=1;
1441 lastElement = CoinMax(lastElement,position);
1442 assert (i==iMajor);
1443 lastPosition=position;
1444 position = next_[position];
1445 }
1446 assert (lastPosition==last_[i]);
1447 }
1448 for (i=0;i<=lastElement;i++) {
1449 if (!mark[i])
1450 assert(triples[i].column==-1);
1451 }
1452 delete [] mark;
1453 }
1454