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 | //------------------------------------------------------------------- |
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 | //------------------------------------------------------------------- |
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 | //------------------------------------------------------------------- |
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 | //------------------------------------------------------------------- |
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 & |
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 |
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 |
191 | 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 |
203 | 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 |
212 | CoinBuild::setCurrentRow(int whichRow) |
213 | { |
214 | assert (type_==0); |
215 | setMutableCurrent(whichRow); |
216 | } |
217 | // Returns current row number |
218 | int |
219 | CoinBuild::currentRow() const |
220 | { |
221 | assert (type_==0); |
222 | return currentItem(); |
223 | } |
224 | // add a column |
225 | void |
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 |
243 | 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 |
255 | 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 |
263 | CoinBuild::setCurrentColumn(int whichColumn) |
264 | { |
265 | assert (type_==1); |
266 | setMutableCurrent(whichColumn); |
267 | } |
268 | // Returns current column number |
269 | int |
270 | CoinBuild::currentColumn() const |
271 | { |
272 | assert (type_==1); |
273 | return currentItem(); |
274 | } |
275 | // add a item |
276 | void |
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 |
317 | 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 |
328 | 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 |
347 | CoinBuild::setCurrentItem(int whichItem) |
348 | { |
349 | setMutableCurrent(whichItem); |
350 | } |
351 | // Set current item |
352 | void |
353 | 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 |
373 | 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 | |