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*/
28struct 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//-------------------------------------------------------------------
46CoinBuild::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//-------------------------------------------------------------------
59CoinBuild::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//-------------------------------------------------------------------
75CoinBuild::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//-------------------------------------------------------------------
115CoinBuild::~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//-------------------------------------------------------------------
128CoinBuild &
129CoinBuild::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
174void
175CoinBuild::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 */
190int
191CoinBuild::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*/
202int
203CoinBuild::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
211void
212CoinBuild::setCurrentRow(int whichRow)
213{
214 assert (type_==0);
215 setMutableCurrent(whichRow);
216}
217// Returns current row number
218int
219CoinBuild::currentRow() const
220{
221 assert (type_==0);
222 return currentItem();
223}
224// add a column
225void
226CoinBuild::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 */
242int
243CoinBuild::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*/
254int
255CoinBuild::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
262void
263CoinBuild::setCurrentColumn(int whichColumn)
264{
265 assert (type_==1);
266 setMutableCurrent(whichColumn);
267}
268// Returns current column number
269int
270CoinBuild::currentColumn() const
271{
272 assert (type_==1);
273 return currentItem();
274}
275// add a item
276void
277CoinBuild::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 */
316int
317CoinBuild::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*/
327int
328CoinBuild::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
346void
347CoinBuild::setCurrentItem(int whichItem)
348{
349 setMutableCurrent(whichItem);
350}
351// Set current item
352void
353CoinBuild::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
372int
373CoinBuild::currentItem() const
374{
375 buildFormat * item = reinterpret_cast<buildFormat *> ( currentItem_);
376 if (item)
377 return item->itemNumber;
378 else
379 return -1;
380}
381