// Copyright (C) 2005, International Business Machines
// Corporation and others. All Rights Reserved.
#include <cmath>
#include <cassert>
#include <cfloat>
#include <cstdio>
#include <iostream>
#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;iItem<numberItems_;iItem++) {
buildFormat * item = currentItem;
assert (item);
int numberElements = item->numberElements;
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;iItem<numberItems_;iItem++) {
double * array = (double *) item;
item = item->next;
delete [] array;
}
}
//----------------------------------------------------------------
// Assignment operator
//-------------------------------------------------------------------
CoinBuild &
CoinBuild::operator=(const CoinBuild& rhs)
{
if (this != &rhs) {
buildFormat * item = (buildFormat *) firstItem_;
for (int iItem=0;iItem<numberItems_;iItem++) {
double * array = (double *) item;
item = item->next;
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;iItem<numberItems_;iItem++) {
buildFormat * item = currentItem;
assert (item);
int numberElements = item->numberElements;
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<numberInItem;k++) {
int iColumn = indices[k];
assert (iColumn>=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&&whichItem<numberItems_) {
int nSkip = whichItem-1;
buildFormat * item = (buildFormat *) firstItem_;
// if further on then we can start from where we are
buildFormat * current = (buildFormat *) currentItem_;
if (current->itemNumber<=whichItem) {
item=current;
nSkip = whichItem-current->itemNumber;
}
for (int iItem=0;iItem<nSkip;iItem++) {
item = item->next;
}
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;
}
syntax highlighted by Code2HTML, v. 0.9.1