// Copyright (C) 2005, International Business Machines // Corporation and others. All Rights Reserved. #include #include #include #include #include #include "CoinPragma.hpp" #include "CoinHelperFunctions.hpp" #include "CoinBuild.hpp" /* Format of each item is a bit sleazy. First we have pointer to next item Then we have two ints giving item number and number of elements Then we have three double for objective lower and upper Then we have elements Then indices */ struct buildFormat { buildFormat * next; int itemNumber; int numberElements; double objective; double lower; double upper; double restDouble[1]; int restInt[1]; // just to make correct size } ; //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- CoinBuild::CoinBuild () : numberItems_(0), numberOther_(0), numberElements_(0), currentItem_(NULL), firstItem_(NULL), lastItem_(NULL), type_(-1) { } //------------------------------------------------------------------- // Constructor with type //------------------------------------------------------------------- CoinBuild::CoinBuild (int type) : numberItems_(0), numberOther_(0), numberElements_(0), currentItem_(NULL), firstItem_(NULL), lastItem_(NULL), type_(type) { if (type<0||type>1) type_=-1; // unset } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- CoinBuild::CoinBuild (const CoinBuild & rhs) : numberItems_(rhs.numberItems_), numberOther_(rhs.numberOther_), numberElements_(rhs.numberElements_), type_(rhs.type_) { if (numberItems_) { firstItem_=NULL; buildFormat * lastItem = NULL; buildFormat * currentItem = (buildFormat *) rhs.firstItem_; for (int iItem=0;iItemnumberElements; int length = sizeof(buildFormat)+(numberElements-1)*(sizeof(double)+sizeof(int)); int doubles = (length + sizeof(double)-1)/sizeof(double); double * copyOfItem = new double [doubles]; memcpy(copyOfItem,item,length); if (!firstItem_) { firstItem_ = copyOfItem; } else { // update pointer lastItem->next = (buildFormat *) copyOfItem; } currentItem = currentItem->next; // on to next lastItem = (buildFormat *) copyOfItem; } currentItem_=firstItem_; lastItem_=(double *) lastItem; } else { currentItem_=NULL; firstItem_=NULL; lastItem_=NULL; } } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- CoinBuild::~CoinBuild () { buildFormat * item = (buildFormat *) firstItem_; for (int iItem=0;iItemnext; delete [] array; } } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- CoinBuild & CoinBuild::operator=(const CoinBuild& rhs) { if (this != &rhs) { buildFormat * item = (buildFormat *) firstItem_; for (int iItem=0;iItemnext; delete [] array; } numberItems_=rhs.numberItems_; numberOther_=rhs.numberOther_; numberElements_=rhs.numberElements_; type_=rhs.type_; if (numberItems_) { firstItem_=NULL; buildFormat * lastItem = NULL; buildFormat * currentItem = (buildFormat *) rhs.firstItem_; for (int iItem=0;iItemnumberElements; int length = sizeof(buildFormat)+(numberElements-1)*(sizeof(double)+sizeof(int)); int doubles = (length + sizeof(double)-1)/sizeof(double); double * copyOfItem = new double [doubles]; memcpy(copyOfItem,item,length); if (!firstItem_) { firstItem_ = copyOfItem; } else { // update pointer lastItem->next = (buildFormat *) copyOfItem; } currentItem = currentItem->next; // on to next lastItem = (buildFormat *) copyOfItem; } currentItem_=firstItem_; lastItem_=(double *) lastItem; } else { currentItem_=NULL; firstItem_=NULL; lastItem_=NULL; } } return *this; } // add a row void CoinBuild::addRow(int numberInRow, const int * columns, const double * elements, double rowLower, double rowUpper) { if (type_<0) { type_=0; } else if (type_==1) { printf("CoinBuild:: unable to add a row in column mode\n"); abort(); } addItem(numberInRow, columns, elements, rowLower,rowUpper,0.0); } /* Returns number of elements in a row and information in row */ int CoinBuild::row(int whichRow, double & rowLower, double & rowUpper, const int * & indices, const double * & elements) const { assert (type_==0); setMutableCurrent(whichRow); double dummyObjective; return currentItem(rowLower,rowUpper,dummyObjective,indices,elements); } /* Returns number of elements in current row and information in row Used as rows may be stored in a chain */ int CoinBuild::currentRow(double & rowLower, double & rowUpper, const int * & indices, const double * & elements) const { assert (type_==0); double dummyObjective; return currentItem(rowLower,rowUpper,dummyObjective,indices,elements); } // Set current row void CoinBuild::setCurrentRow(int whichRow) { assert (type_==0); setMutableCurrent(whichRow); } // Returns current row number int CoinBuild::currentRow() const { assert (type_==0); return currentItem(); } // add a column void CoinBuild::addColumn(int numberInColumn, const int * rows, const double * elements, double columnLower, double columnUpper, double objectiveValue) { if (type_<0) { type_=1; } else if (type_==0) { printf("CoinBuild:: unable to add a column in row mode\n"); abort(); } addItem(numberInColumn, rows, elements, columnLower,columnUpper, objectiveValue); } /* Returns number of elements in a column and information in column */ int CoinBuild::column(int whichColumn, double & columnLower, double & columnUpper, double & objectiveValue, const int * & indices, const double * & elements) const { assert (type_==1); setMutableCurrent(whichColumn); return currentItem(columnLower,columnUpper,objectiveValue,indices,elements); } /* Returns number of elements in current column and information in column Used as columns may be stored in a chain */ int CoinBuild::currentColumn( double & columnLower, double & columnUpper, double & objectiveValue, const int * & indices, const double * & elements) const { assert (type_==1); return currentItem(columnLower,columnUpper,objectiveValue,indices,elements); } // Set current column void CoinBuild::setCurrentColumn(int whichColumn) { assert (type_==1); setMutableCurrent(whichColumn); } // Returns current column number int CoinBuild::currentColumn() const { assert (type_==1); return currentItem(); } // add a item void CoinBuild::addItem(int numberInItem, const int * indices, const double * elements, double itemLower, double itemUpper, double objectiveValue) { buildFormat * lastItem = (buildFormat *) lastItem_; int length = sizeof(buildFormat)+(numberInItem-1)*(sizeof(double)+sizeof(int)); int doubles = (length + sizeof(double)-1)/sizeof(double); double * newItem = new double [doubles]; if (!firstItem_) { firstItem_ = newItem; } else { // update pointer lastItem->next = (buildFormat *) newItem; } lastItem_=newItem; currentItem_=newItem; // now fill in buildFormat * item = (buildFormat *) newItem; double * els = &item->restDouble[0]; int * cols = (int *) (els+numberInItem); item->next=NULL; item->itemNumber=numberItems_; numberItems_++; item->numberElements=numberInItem; numberElements_ += numberInItem; item->objective=objectiveValue; item->lower=itemLower; item->upper=itemUpper; for (int k=0;k=0); numberOther_ = CoinMax(numberOther_,iColumn+1); els[k]=elements[k]; cols[k]=iColumn; } } /* Returns number of elements in a item and information in item */ int CoinBuild::item(int whichItem, double & itemLower, double & itemUpper, double & objectiveValue, const int * & indices, const double * & elements) const { setMutableCurrent(whichItem); return currentItem(itemLower,itemUpper,objectiveValue,indices,elements); } /* Returns number of elements in current item and information in item Used as items may be stored in a chain */ int CoinBuild::currentItem(double & itemLower, double & itemUpper, double & objectiveValue, const int * & indices, const double * & elements) const { buildFormat * item = (buildFormat *) currentItem_; if (item) { int numberElements = item->numberElements; elements = &item->restDouble[0]; indices = (const int *) (elements+numberElements); objectiveValue=item->objective; itemLower = item->lower; itemUpper=item->upper; return numberElements; } else { return -1; } } // Set current item void CoinBuild::setCurrentItem(int whichItem) { setMutableCurrent(whichItem); } // Set current item void CoinBuild::setMutableCurrent(int whichItem) const { if (whichItem>=0&&whichItemitemNumber<=whichItem) { item=current; nSkip = whichItem-current->itemNumber; } for (int iItem=0;iItemnext; } assert (whichItem==item->itemNumber); currentItem_ = (double *) item; } } // Returns current item number int CoinBuild::currentItem() const { buildFormat * item = (buildFormat *) currentItem_; if (item) return item->itemNumber; else return -1; }