1 /* $Id: CoinBuild.cpp 1448 2011-06-19 15:34:41Z stefan $ */
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 
7 #include <cstdlib>
8 #include <cmath>
9 #include <cassert>
10 #include <cfloat>
11 #include <cstdio>
12 #include <iostream>
13 
14 
15 #include "CoinBuild.hpp"
16 
17 #include "CoinPragma.hpp"
18 #include "CoinHelperFunctions.hpp"
19 
20 /*
21   Format of each item is a bit sleazy.
22   First we have pointer to next item
23   Then we have two ints giving item number and number of elements
24   Then we have three double for objective lower and upper
25   Then we have elements
26   Then indices
27 */
28 struct buildFormat {
29   buildFormat * next;
30   int itemNumber;
31   int numberElements;
32   double objective;
33   double lower;
34   double upper;
35   double restDouble[1];
36   int restInt[1]; // just to make correct size
37 } ;
38 
39 //#############################################################################
40 // Constructors / Destructor / Assignment
41 //#############################################################################
42 
43 //-------------------------------------------------------------------
44 // Default Constructor
45 //-------------------------------------------------------------------
CoinBuild()46 CoinBuild::CoinBuild ()
47   : numberItems_(0),
48     numberOther_(0),
49     numberElements_(0),
50     currentItem_(NULL),
51     firstItem_(NULL),
52     lastItem_(NULL),
53     type_(-1)
54 {
55 }
56 //-------------------------------------------------------------------
57 // Constructor with type
58 //-------------------------------------------------------------------
CoinBuild(int type)59 CoinBuild::CoinBuild (int type)
60   : numberItems_(0),
61     numberOther_(0),
62     numberElements_(0),
63     currentItem_(NULL),
64     firstItem_(NULL),
65     lastItem_(NULL),
66     type_(type)
67 {
68   if (type<0||type>1)
69     type_=-1; // unset
70 }
71 
72 //-------------------------------------------------------------------
73 // Copy constructor
74 //-------------------------------------------------------------------
CoinBuild(const CoinBuild & rhs)75 CoinBuild::CoinBuild (const CoinBuild & rhs)
76   : numberItems_(rhs.numberItems_),
77     numberOther_(rhs.numberOther_),
78     numberElements_(rhs.numberElements_),
79     type_(rhs.type_)
80 {
81   if (numberItems_) {
82     firstItem_=NULL;
83     buildFormat * lastItem = NULL;
84     buildFormat * currentItem = reinterpret_cast<buildFormat *> ( rhs.firstItem_);
85     for (int iItem=0;iItem<numberItems_;iItem++) {
86       buildFormat * item = currentItem;
87       assert (item);
88       int numberElements = item->numberElements;
89       int length = ( CoinSizeofAsInt(buildFormat) + (numberElements-1) *
90                      (CoinSizeofAsInt(double)+CoinSizeofAsInt(int)) );
91       int doubles = (length + CoinSizeofAsInt(double)-1)/CoinSizeofAsInt(double);
92       double * copyOfItem = new double [doubles];
93       memcpy(copyOfItem,item,length);
94       if (!firstItem_) {
95         firstItem_ = copyOfItem;
96       } else {
97         // update pointer
98         lastItem->next = reinterpret_cast<buildFormat *> ( copyOfItem);
99       }
100       currentItem = currentItem->next; // on to next
101       lastItem = reinterpret_cast<buildFormat *> ( copyOfItem);
102     }
103     currentItem_=firstItem_;
104     lastItem_=reinterpret_cast<double *> ( lastItem);
105   } else {
106     currentItem_=NULL;
107     firstItem_=NULL;
108     lastItem_=NULL;
109   }
110 }
111 
112 //-------------------------------------------------------------------
113 // Destructor
114 //-------------------------------------------------------------------
~CoinBuild()115 CoinBuild::~CoinBuild ()
116 {
117   buildFormat * item = reinterpret_cast<buildFormat *> ( firstItem_);
118   for (int iItem=0;iItem<numberItems_;iItem++) {
119     double * array = reinterpret_cast<double *> ( item);
120     item = item->next;
121     delete [] array;
122   }
123 }
124 
125 //----------------------------------------------------------------
126 // Assignment operator
127 //-------------------------------------------------------------------
128 CoinBuild &
operator =(const CoinBuild & rhs)129 CoinBuild::operator=(const CoinBuild& rhs)
130 {
131   if (this != &rhs) {
132     buildFormat * item = reinterpret_cast<buildFormat *> ( firstItem_);
133     for (int iItem=0;iItem<numberItems_;iItem++) {
134       double * array = reinterpret_cast<double *> ( item);
135       item = item->next;
136       delete [] array;
137     }
138     numberItems_=rhs.numberItems_;
139     numberOther_=rhs.numberOther_;
140     numberElements_=rhs.numberElements_;
141     type_=rhs.type_;
142     if (numberItems_) {
143       firstItem_=NULL;
144       buildFormat * lastItem = NULL;
145       buildFormat * currentItem = reinterpret_cast<buildFormat *> ( rhs.firstItem_);
146       for (int iItem=0;iItem<numberItems_;iItem++) {
147         buildFormat * item = currentItem;
148         assert (item);
149         int numberElements = item->numberElements;
150         int length = CoinSizeofAsInt(buildFormat)+(numberElements-1)*(CoinSizeofAsInt(double)+CoinSizeofAsInt(int));
151         int doubles = (length + CoinSizeofAsInt(double)-1)/CoinSizeofAsInt(double);
152         double * copyOfItem = new double [doubles];
153         memcpy(copyOfItem,item,length);
154         if (!firstItem_) {
155           firstItem_ = copyOfItem;
156         } else {
157           // update pointer
158           lastItem->next = reinterpret_cast<buildFormat *> ( copyOfItem);
159         }
160         currentItem = currentItem->next; // on to next
161         lastItem = reinterpret_cast<buildFormat *> ( copyOfItem);
162       }
163       currentItem_=firstItem_;
164       lastItem_=reinterpret_cast<double *> ( lastItem);
165     } else {
166       currentItem_=NULL;
167       firstItem_=NULL;
168       lastItem_=NULL;
169     }
170   }
171   return *this;
172 }
173 // add a row
174 void
addRow(int numberInRow,const int * columns,const double * elements,double rowLower,double rowUpper)175 CoinBuild::addRow(int numberInRow, const int * columns,
176                  const double * elements, double rowLower,
177                  double rowUpper)
178 {
179   if (type_<0) {
180     type_=0;
181   } else if (type_==1) {
182     printf("CoinBuild:: unable to add a row in column mode\n");
183     abort();
184   }
185   addItem(numberInRow, columns, elements,
186           rowLower,rowUpper,0.0);
187 }
188 /*  Returns number of elements in a row and information in row
189  */
190 int
row(int whichRow,double & rowLower,double & rowUpper,const int * & indices,const double * & elements) const191 CoinBuild::row(int whichRow, double & rowLower, double & rowUpper,
192               const int * & indices, const double * & elements) const
193 {
194   assert (type_==0);
195   setMutableCurrent(whichRow);
196   double dummyObjective;
197   return currentItem(rowLower,rowUpper,dummyObjective,indices,elements);
198 }
199 /*  Returns number of elements in current row and information in row
200     Used as rows may be stored in a chain
201 */
202 int
currentRow(double & rowLower,double & rowUpper,const int * & indices,const double * & elements) const203 CoinBuild::currentRow(double & rowLower, double & rowUpper,
204                      const int * & indices, const double * & elements) const
205 {
206   assert (type_==0);
207   double dummyObjective;
208   return currentItem(rowLower,rowUpper,dummyObjective,indices,elements);
209 }
210 // Set current row
211 void
setCurrentRow(int whichRow)212 CoinBuild::setCurrentRow(int whichRow)
213 {
214   assert (type_==0);
215   setMutableCurrent(whichRow);
216 }
217 // Returns current row number
218 int
currentRow() const219 CoinBuild::currentRow() const
220 {
221   assert (type_==0);
222   return currentItem();
223 }
224 // add a column
225 void
addColumn(int numberInColumn,const int * rows,const double * elements,double columnLower,double columnUpper,double objectiveValue)226 CoinBuild::addColumn(int numberInColumn, const int * rows,
227                      const double * elements,
228                      double columnLower,
229                      double columnUpper, double objectiveValue)
230 {
231   if (type_<0) {
232     type_=1;
233   } else if (type_==0) {
234     printf("CoinBuild:: unable to add a column in row mode\n");
235     abort();
236   }
237   addItem(numberInColumn, rows, elements,
238           columnLower,columnUpper, objectiveValue);
239 }
240 /*  Returns number of elements in a column and information in column
241  */
242 int
column(int whichColumn,double & columnLower,double & columnUpper,double & objectiveValue,const int * & indices,const double * & elements) const243 CoinBuild::column(int whichColumn,
244                   double & columnLower, double & columnUpper, double & objectiveValue,
245                   const int * & indices, const double * & elements) const
246 {
247   assert (type_==1);
248   setMutableCurrent(whichColumn);
249   return currentItem(columnLower,columnUpper,objectiveValue,indices,elements);
250 }
251 /*  Returns number of elements in current column and information in column
252     Used as columns may be stored in a chain
253 */
254 int
currentColumn(double & columnLower,double & columnUpper,double & objectiveValue,const int * & indices,const double * & elements) const255 CoinBuild::currentColumn( double & columnLower, double & columnUpper, double & objectiveValue,
256                          const int * & indices, const double * & elements) const
257 {
258   assert (type_==1);
259   return currentItem(columnLower,columnUpper,objectiveValue,indices,elements);
260 }
261 // Set current column
262 void
setCurrentColumn(int whichColumn)263 CoinBuild::setCurrentColumn(int whichColumn)
264 {
265   assert (type_==1);
266   setMutableCurrent(whichColumn);
267 }
268 // Returns current column number
269 int
currentColumn() const270 CoinBuild::currentColumn() const
271 {
272   assert (type_==1);
273   return currentItem();
274 }
275 // add a item
276 void
addItem(int numberInItem,const int * indices,const double * elements,double itemLower,double itemUpper,double objectiveValue)277 CoinBuild::addItem(int numberInItem, const int * indices,
278                   const double * elements,
279                   double itemLower,
280                   double itemUpper, double objectiveValue)
281 {
282   buildFormat * lastItem = reinterpret_cast<buildFormat *> ( lastItem_);
283   int length = CoinSizeofAsInt(buildFormat)+(numberInItem-1)*(CoinSizeofAsInt(double)+CoinSizeofAsInt(int));
284   int doubles = (length + CoinSizeofAsInt(double)-1)/CoinSizeofAsInt(double);
285   double * newItem = new double [doubles];
286   if (!firstItem_) {
287     firstItem_ = newItem;
288   } else {
289     // update pointer
290     lastItem->next = reinterpret_cast<buildFormat *> ( newItem);
291   }
292   lastItem_=newItem;
293   currentItem_=newItem;
294   // now fill in
295   buildFormat * item = reinterpret_cast<buildFormat *> ( newItem);
296   double * els = &item->restDouble[0];
297   int * cols = reinterpret_cast<int *> (els+numberInItem);
298   item->next=NULL;
299   item->itemNumber=numberItems_;
300   numberItems_++;
301   item->numberElements=numberInItem;
302   numberElements_ += numberInItem;
303   item->objective=objectiveValue;
304   item->lower=itemLower;
305   item->upper=itemUpper;
306   for (int k=0;k<numberInItem;k++) {
307     int iColumn = indices[k];
308     assert (iColumn>=0);
309     numberOther_ = CoinMax(numberOther_,iColumn+1);
310     els[k]=elements[k];
311     cols[k]=iColumn;
312   }
313 }
314 /*  Returns number of elements in a item and information in item
315  */
316 int
item(int whichItem,double & itemLower,double & itemUpper,double & objectiveValue,const int * & indices,const double * & elements) const317 CoinBuild::item(int whichItem,
318                 double & itemLower, double & itemUpper, double & objectiveValue,
319                 const int * & indices, const double * & elements) const
320 {
321   setMutableCurrent(whichItem);
322   return currentItem(itemLower,itemUpper,objectiveValue,indices,elements);
323 }
324 /*  Returns number of elements in current item and information in item
325     Used as items may be stored in a chain
326 */
327 int
currentItem(double & itemLower,double & itemUpper,double & objectiveValue,const int * & indices,const double * & elements) const328 CoinBuild::currentItem(double & itemLower, double & itemUpper,
329                        double & objectiveValue,
330                        const int * & indices, const double * & elements) const
331 {
332   buildFormat * item = reinterpret_cast<buildFormat *> ( currentItem_);
333   if (item) {
334     int numberElements = item->numberElements;
335     elements = &item->restDouble[0];
336     indices = reinterpret_cast<const int *> (elements+numberElements);
337     objectiveValue=item->objective;
338     itemLower = item->lower;
339     itemUpper=item->upper;
340     return numberElements;
341   } else {
342     return -1;
343   }
344 }
345 // Set current item
346 void
setCurrentItem(int whichItem)347 CoinBuild::setCurrentItem(int whichItem)
348 {
349   setMutableCurrent(whichItem);
350 }
351 // Set current item
352 void
setMutableCurrent(int whichItem) const353 CoinBuild::setMutableCurrent(int whichItem) const
354 {
355   if (whichItem>=0&&whichItem<numberItems_) {
356     int nSkip = whichItem-1;
357     buildFormat * item = reinterpret_cast<buildFormat *> ( firstItem_);
358     // if further on then we can start from where we are
359     buildFormat * current = reinterpret_cast<buildFormat *> ( currentItem_);
360     if (current->itemNumber<=whichItem) {
361       item=current;
362       nSkip = whichItem-current->itemNumber;
363     }
364     for (int iItem=0;iItem<nSkip;iItem++) {
365       item = item->next;
366     }
367     assert (whichItem==item->itemNumber);
368     currentItem_ = reinterpret_cast<double *> ( item);
369   }
370 }
371 // Returns current item number
372 int
currentItem() const373 CoinBuild::currentItem() const
374 {
375   buildFormat * item = reinterpret_cast<buildFormat *> ( currentItem_);
376   if (item)
377     return item->itemNumber;
378   else
379     return -1;
380 }
381