blob: bde18a90c8ad3a9c139e1e9318deb735885d2375 [file] [log] [blame]
/**************************************************************/
/* ********************************************************** */
/* * * */
/* * PARTITION * */
/* * * */
/* * $Module: PARTITION * */
/* * * */
/* * Copyright (C) 1999, 2001 MPI fuer Informatik * */
/* * * */
/* * 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 * */
/* * * */
/* * * */
/* $Revision$ * */
/* $State$ * */
/* $Date$ * */
/* $Author$ * */
/* * * */
/* * Contact: * */
/* * Christoph Weidenbach * */
/* * MPI fuer Informatik * */
/* * Stuhlsatzenhausweg 85 * */
/* * 66123 Saarbruecken * */
/* * Email: weidenb@mpi-sb.mpg.de * */
/* * Germany * */
/* * * */
/* ********************************************************** */
/**************************************************************/
/**************************************************************/
/* Include */
/**************************************************************/
#include "partition.h"
/**************************************************************/
/* Inline functions */
/**************************************************************/
static __inline__ ECLASS part_GetClass(PARTITION p, ELEMENT e)
{
return p[e];
}
static __inline__ PARTITION part_SetClass(PARTITION p, ELEMENT e, ECLASS c)
{
p[e] = c;
return p;
}
static __inline__ int part_GetClassSize(PARTITION p, ELEMENT e)
{
return p[p[part_CARD] + e];
}
static __inline__ PARTITION part_SetClassSize(PARTITION p, ELEMENT e, int
classsize)
{
p[p[part_CARD] + e] = classsize;
return p;
}
static __inline__ int part_GetStamp(PARTITION p, ELEMENT e)
{
return p[-part_HEAD - 1 - e];
}
static __inline__ PARTITION part_SetStamp(PARTITION p, ELEMENT e, int stamp)
{
p[-part_HEAD - 1 - e] = stamp;
return p;
}
static __inline__ BOOL part_Stamped(PARTITION p, ELEMENT e)
{
return part_GetStamp(p, e) == p[part_STAMPCOUNTER];
}
static __inline__ ELEMENT part_DelayedInit(PARTITION p, ELEMENT e)
/***************************************************************
RETURNS: the (now stamped) element
EFFECT: establishes the equivalence class {e} in p, thus
partially initializing p
***************************************************************/
{
if (!part_Stamped(p, e)) {
part_SetClass(p, e, -e - 1); /* representative e (>= 0) of {e} is coded */
/* as -e - 1 (< 0) */
part_SetClassSize(p, e, 1);
part_SetStamp(p, e, p[part_STAMPCOUNTER]);
}
return e;
}
/**************************************************************/
/* Functions */
/**************************************************************/
PARTITION part_Create(int size)
/****************************************************************
RETURNS: the initial partition {{0}, {1}, {2}, ..., {size - 1}}
of the set {0, 1, 2, ..., size - 1}
****************************************************************/
{
PARTITION result;
#ifdef CHECK
if (size < 0) {
misc_StartErrorReport();
misc_ErrorReport("\n In part_Create: negative size %d.", size);
misc_FinishErrorReport();
}
#endif
result = (PARTITION) memory_Calloc(size * 3 + part_HEAD, sizeof(int))
+ size + part_HEAD; /* move pointer to the middle of the array */
/* to allow negative indices */
result[part_CARD] = size;
result[part_ALLOC] = size * 3 + part_HEAD;
result[part_STAMPCOUNTER] = 1;
return result;
}
PARTITION part_Init(PARTITION p, int size)
/****************************************************************
RETURNS: the initial partition {{0}, {1}, {2}, ..., {size - 1}}
of the set {0, 1, 2, ..., size - 1}
EFFECT: stores the initial partition to p if it's big enough,
otherwise creates a new partition, therefore
CAUTION: must be called inside an assignment like:
p = part_Init(p, ...)
****************************************************************/
{
int alloc, i;
#ifdef CHECK
if (size < 0) {
misc_StartErrorReport();
misc_ErrorReport("\n In part_Init: negative size %d.", size);
misc_FinishErrorReport();
}
#endif
alloc = (p[part_ALLOC] - part_HEAD) / 3;
if (size > alloc) {
part_Free(p);
p = part_Create(size);
}
else {
p[part_CARD] = size;
p[part_STAMPCOUNTER]++;
/* if a stamp overflow occurs, reinit stamps: */
if (p[part_STAMPCOUNTER] <= 0) {
for (i = 0; i < alloc; i++)
part_SetStamp(p, i, 0);
p[part_STAMPCOUNTER] = 1;
}
}
return p;
}
static ELEMENT part_NF(PARTITION p, ELEMENT e)
/***************************************************************
RETURNS: the normal form element of the class [e]; this is an
element of [e] that sometimes differ from the
representative
EFFECT: makes the normal form to the direct parent of all
elements visited on the search path from e to this
normal form ("path compression")
***************************************************************/
{
ELEMENT nf, aux;
#ifdef CHECK
if (!part_Element(p, e)) {
misc_StartErrorReport();
misc_ErrorReport("\n In part_NF: %d not in partitioned set.", e);
misc_FinishErrorReport();
}
#endif
nf = e;
while (part_GetClass(p, part_DelayedInit(p, nf)) >= 0)
nf = part_GetClass(p, nf);
/* path compression: */
while (e != nf) {
aux = part_GetClass(p, e);
part_SetClass(p, e, nf);
e = aux;
}
return nf;
}
ECLASS part_Find(PARTITION p, ELEMENT e)
/***************************************************************
RETURNS: (the representative of) class [e]
***************************************************************/
{
#ifdef CHECK
if (!part_Element(p, e)) {
misc_StartErrorReport();
misc_ErrorReport("\n In part_Find: %d not in partitioned set.", e);
misc_FinishErrorReport();
}
#endif
return -part_GetClass(p, part_NF(p, e)) - 1;
/* representative e is coded as -e - 1 (cf. part_DelayedInit) */
}
PARTITION part_Union(PARTITION p, ECLASS c1, ECLASS c2)
/***************************************************************
RETURNS: the union of the classes
EFFECT: the representative of c1 is the representative of the
union
***************************************************************/
{
ELEMENT nf1, nf2, aux;
#ifdef CHECK
if (!part_Element(p, c1)) {
misc_StartErrorReport();
misc_ErrorReport("\n In part_Union: first class %d not in partitioned set.",
c1);
misc_FinishErrorReport();
}
if (!part_Element(p, c2)) {
misc_StartErrorReport();
misc_ErrorReport
("\n In part_Union: second class %d not in partitioned set.", c2);
misc_FinishErrorReport();
}
#endif
nf1 = part_NF(p, c1);
nf2 = part_NF(p, c2);
if (nf1 != nf2) {
/* make [nf1] the bigger (or at least not smaller) class: */
if (part_GetClassSize(p, nf1) < part_GetClassSize(p, nf2)) {
aux = nf1;
nf1 = nf2;
nf2 = aux;
part_SetClass(p, nf1, part_GetClass(p, nf2));
part_SetClass(p, -part_GetClass(p, nf2) - 1, nf1);
}
part_SetClass(p, nf2, nf1);
part_SetClassSize(p, nf1,
part_GetClassSize(p, nf1) + part_GetClassSize(p, nf2));
}
return p;
}