//
// $Source: /cvsroot/gambit/gambit/sources/tools/enumpoly/odometer.cc,v $
// $Date: 2006/07/20 16:23:15 $
// $Revision: 1.4 $
//
// DESCRIPTION:
// Implementation of class gIndexOdometer
//
// This file is part of Gambit
// Copyright (c) 2002, The Gambit Project
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
#include "odometer.h"
//---------------------------------------------------------------
// gIndexOdometer
//---------------------------------------------------------------
//---------------------------
// Constructors / Destructors
//---------------------------
gIndexOdometer::gIndexOdometer(const Gambit::Array<int> IndexUpperBounds)
: MinIndices(IndexUpperBounds.Length()),
MaxIndices(IndexUpperBounds),
CurIndices(IndexUpperBounds.Length())
{
int i;
for (i = 1; i <= NoIndices(); i++) MinIndices[i] = 1;
CurIndices[1] = 0;
for (i = 2; i <= NoIndices(); i++) CurIndices[i] = 1;
}
gIndexOdometer::gIndexOdometer(const Gambit::Array<int> IndexLowerBounds,
const Gambit::Array<int> IndexUpperBounds)
: MinIndices(IndexLowerBounds),
MaxIndices(IndexUpperBounds),
CurIndices(IndexUpperBounds.Length())
{
CurIndices[1] = MinIndices[1] - 1;;
for (int i = 2; i <= NoIndices(); i++) CurIndices[i] = MinIndices[i];
}
gIndexOdometer::gIndexOdometer(const int* IndexUpperBounds, const int NoInd)
: MinIndices(NoInd),
MaxIndices(NoInd),
CurIndices(NoInd)
{
int i;
for (i = 1; i <= NoIndices(); i++) MinIndices[i] = 1;
for (i = 1; i <= NoIndices(); i++) {
MaxIndices[i] = IndexUpperBounds[i-1];
CurIndices[i] = 1;
}
CurIndices[1] = 0;
}
gIndexOdometer::gIndexOdometer(const gIndexOdometer & odo)
: MaxIndices(odo.MaxIndices), CurIndices(odo.CurIndices)
{
}
gIndexOdometer::~gIndexOdometer()
{
}
//----------------------------------
// Operators
//----------------------------------
gIndexOdometer& gIndexOdometer::operator=(const gIndexOdometer & rhs)
{
if (*this != rhs) {
MinIndices = rhs.MinIndices;
MaxIndices = rhs.MaxIndices;
CurIndices = rhs.CurIndices;
}
return *this;
}
bool gIndexOdometer::operator==(const gIndexOdometer & rhs) const
{
if (MinIndices != rhs.MinIndices) return false;
if (MaxIndices != rhs.MaxIndices) return false;
if (CurIndices != rhs.CurIndices) return false;
return true;
}
bool gIndexOdometer::operator!=(const gIndexOdometer & rhs) const
{
return !(*this == rhs);
}
int gIndexOdometer::operator[](const int place) const
{
//assert(1 <= place && place <= NoIndices());
return CurIndices[place];
}
//----------------------------------
// Manipulate
//----------------------------------
void gIndexOdometer::SetIndex(const int& place, const int& newind)
{
CurIndices[place] = newind;
}
bool gIndexOdometer::Turn()
{
if (CurIndices[1] == MinIndices[1]-1) {
CurIndices[1] = MinIndices[1];
return true;
}
int turn_index = 1;
while ( turn_index <= NoIndices() &&
CurIndices[turn_index] == MaxIndices[turn_index]) turn_index++;
if (turn_index > NoIndices()) return false;
for (int j = 1; j < turn_index; j++) CurIndices[j] = MinIndices[j];
CurIndices[turn_index]++;
return true;
}
//----------------------------------
// Information
//----------------------------------
int gIndexOdometer::NoIndices() const
{
return MaxIndices.Length();
}
int gIndexOdometer::LinearIndex() const
{
int index = (*this)[1];
int factor = 1;
for (int i = 2; i <= NoIndices(); i++) {
factor *= MaxIndices[i-1] - MinIndices[i-1] + 1;
index += factor * (CurIndices[i] - 1);
}
return index;
}
Gambit::Array<int> gIndexOdometer::CurrentIndices() const
{
return CurIndices;
}
gIndexOdometer gIndexOdometer::AfterExcisionOf(int& to_be_zapped) const
{
Gambit::Array<int> NewMins, NewMaxs;
int i;
for (i = 1; i < to_be_zapped; i++)
{ NewMins.Append(MinIndices[i]); NewMaxs.Append(MaxIndices[i]); }
for (i = to_be_zapped+1; i <= NoIndices(); i++)
{ NewMins.Append(MinIndices[i]); NewMaxs.Append(MaxIndices[i]); }
gIndexOdometer NewOdo(NewMins,NewMaxs);
for (i = 1; i < to_be_zapped; i++)
NewOdo.SetIndex(i ,CurIndices[i]);
for (i = to_be_zapped+1; i <= NoIndices(); i++)
NewOdo.SetIndex(i-1,CurIndices[i]);
return NewOdo;
}
//---------------------------------------------------------------
// gPermutationOdometer
//---------------------------------------------------------------
//---------------------------
// Constructors / Destructors
//---------------------------
gPermutationOdometer::gPermutationOdometer(const int& given_n)
: n(given_n), CurIndices(n), CurSign(0)
{
CurIndices[1] = 0; // Codes for virginity - see Turn() below
for (int i = 2; i <= n; i++) CurIndices[i] = i;
}
gPermutationOdometer::gPermutationOdometer(const gPermutationOdometer & odo)
: n(odo.n), CurIndices(odo.CurIndices), CurSign(odo.CurSign)
{
}
gPermutationOdometer::~gPermutationOdometer()
{ }
//----------------------------------
// Operators
//----------------------------------
bool gPermutationOdometer::operator==(const gPermutationOdometer & rhs) const
{
if (n != rhs.n) return false;
for (int i = 1; i <= n; i++)
if (CurIndices[i] != rhs.CurIndices[i]) return false;
if (CurSign != rhs.CurSign) {
//gout << "Error in gPermutationOdometer\n";
exit(1);
}
return true;
}
bool gPermutationOdometer::operator!=(const gPermutationOdometer & rhs) const
{
return !(*this == rhs);
}
int gPermutationOdometer::operator[](const int place) const
{
//assert(1 <= place && place <= n);
return CurIndices[place];
}
//----------------------------------
// Manipulate
//----------------------------------
bool gPermutationOdometer::Turn()
{
if (CurIndices[1] == 0) { // First turn gives identity permutation
CurIndices[1] = 1;
CurSign = 1;
return true;
}
if (n ==1) return false;
int cursor1 = n-1;
while (cursor1 >= 1 && CurIndices[cursor1] > CurIndices[cursor1 + 1]) cursor1--;
if (cursor1 == 0) return false;
int cursor2 = cursor1 + 1;
while (cursor2 < n && CurIndices[cursor2 + 1] > CurIndices[cursor1]) cursor2++;
int tmp = CurIndices[cursor2];
CurIndices[cursor2] = CurIndices[cursor1];
CurIndices[cursor1] = tmp;
CurSign *= -1;
cursor1++; cursor2 = n;
while (cursor1 < cursor2) {
int tmp = CurIndices[cursor2];
CurIndices[cursor2] = CurIndices[cursor1];
CurIndices[cursor1] = tmp;
CurSign *= -1;
cursor1++; cursor2--;
}
return true;
}
//----------------------------------
// Information
//----------------------------------
int gPermutationOdometer::NoIndices() const
{
return n;
}
Gambit::Array<int> gPermutationOdometer::CurrentIndices() const
{
return CurIndices;
}
int gPermutationOdometer::CurrentSign() const
{
return CurSign;
}
syntax highlighted by Code2HTML, v. 0.9.1