282 lines
		
	
	
	
		
			4.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			282 lines
		
	
	
	
		
			4.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* $Id$ */
 | 
						|
/*
 | 
						|
 * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
 | 
						|
 * See the copyright notice in the ACK home directory, in the file "Copyright".
 | 
						|
 */
 | 
						|
/*  S H A R E D   F I L E
 | 
						|
 *
 | 
						|
 *  C S E T . C
 | 
						|
 */
 | 
						|
 | 
						|
 | 
						|
#include "types.h"
 | 
						|
#include "cset.h"
 | 
						|
#include "alloc.h"
 | 
						|
#include "debug.h"
 | 
						|
#include "global.h"
 | 
						|
 | 
						|
 | 
						|
/* A set over a range of integers from 1 to N may be represented
 | 
						|
 * as a 'compact' set. Such a set is represented as a 'bitvector'
 | 
						|
 * record, containing the size of the set (i.e. N) and a row
 | 
						|
 * of words (the bitvector itself). An integer J (1 <= J  <= N) is
 | 
						|
 * an element of the set iff the J-th bit of the vector is a '1'.
 | 
						|
 * Any redundant bits in the last word are garanteed to be zero bits.
 | 
						|
 * This package implements the usual operations on sets.
 | 
						|
 * The name of every operation is preceede by a 'C' to
 | 
						|
 * distinguish it from the operation on 'long' (list) 
 | 
						|
 * sets whth a similar name.
 | 
						|
 */
 | 
						|
 | 
						|
 | 
						|
/* The two arithmetic operations 'divide by wordlength' and
 | 
						|
 * 'modulo wordlength' can be performed very efficiently
 | 
						|
 * if the word length (of the source machine) is 16.
 | 
						|
 */
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
cset Cempty_set(n)
 | 
						|
	short n;
 | 
						|
{
 | 
						|
	cset s;
 | 
						|
 | 
						|
	s = newbitvect(DIVWL(n-1) + 1);
 | 
						|
	s->v_size = n;
 | 
						|
	return s;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
bool Cis_elem(x,s)
 | 
						|
	Celem_t x;
 | 
						|
	cset    s;
 | 
						|
{
 | 
						|
	short n;
 | 
						|
	int mask;
 | 
						|
 | 
						|
	assert(x>0 && x <= s->v_size);
 | 
						|
	n = DIVWL(x-1);
 | 
						|
	mask = (1 << MODWL(x-1));
 | 
						|
	if ((s->v_bits[n] & mask) == 0) {
 | 
						|
		return FALSE;
 | 
						|
	} else {
 | 
						|
		return TRUE;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
Cadd(x,s_p)
 | 
						|
	Celem_t x;
 | 
						|
	cset    *s_p;
 | 
						|
{
 | 
						|
	cset s;
 | 
						|
	short n;
 | 
						|
	int mask;
 | 
						|
 | 
						|
	s = *s_p;
 | 
						|
	assert(x>0 && x <= s->v_size);
 | 
						|
	n = DIVWL(x-1);
 | 
						|
	mask = (1 << MODWL(x-1));
 | 
						|
	s->v_bits[n] |= mask;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
Cremove(x,s_p)
 | 
						|
	Celem_t x;
 | 
						|
	cset    *s_p;
 | 
						|
{
 | 
						|
	cset s;
 | 
						|
	short n;
 | 
						|
	int mask;
 | 
						|
 | 
						|
	s = *s_p;
 | 
						|
	assert(x>0 && x <= s->v_size);
 | 
						|
	n = DIVWL(x-1);
 | 
						|
	mask = (1 << MODWL(x-1));
 | 
						|
	s->v_bits[n] &= ~mask;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/* The operations first, next and elem can be used to iterate
 | 
						|
 * over a set. For example:
 | 
						|
 *	for (i = Cfirst(s); i != (Cindex) 0; i = Cnext(i,s) {
 | 
						|
 *		x = Celem(i);
 | 
						|
 *		use x
 | 
						|
 *	}
 | 
						|
 * which is like:
 | 
						|
 *      'for all elements x of s do'
 | 
						|
 *		use x
 | 
						|
 *
 | 
						|
 * The implementation of first and next is not very fast.
 | 
						|
 * It could be made much more efficient (at the price of a
 | 
						|
 * higher complexity) by not using 'is_elem'.
 | 
						|
 * Iteration over a bitvector, however, is not supposed to
 | 
						|
 * be used very often.
 | 
						|
 */
 | 
						|
 | 
						|
Cindex Cfirst(s)
 | 
						|
	cset s;
 | 
						|
{
 | 
						|
	return Cnext((Cindex) 0,s);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
Cindex Cnext(i,s)
 | 
						|
	Cindex i;
 | 
						|
	cset   s;
 | 
						|
{
 | 
						|
	register short n;
 | 
						|
 | 
						|
	for (n = i+1; n <= s->v_size; n++) {
 | 
						|
		if (Cis_elem(n,s)) {
 | 
						|
			return (Cindex) n;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return (Cindex) 0;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
Celem_t Celem(i)
 | 
						|
	Cindex i;
 | 
						|
{
 | 
						|
	return (Celem_t) i;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
Cjoin(s1,s2_p)
 | 
						|
	cset s1, *s2_p;
 | 
						|
{
 | 
						|
	/* Two sets are joined by or-ing their bitvectors,
 | 
						|
	 * word by word.
 | 
						|
	 */
 | 
						|
 | 
						|
	cset s2;
 | 
						|
	short n;
 | 
						|
	register short i;
 | 
						|
 | 
						|
	s2 = *s2_p;
 | 
						|
	assert(s1->v_size == s2->v_size);
 | 
						|
	n = DIVWL(s1->v_size -1);  /* #words -1 */
 | 
						|
	for (i = 0; i <= n; i++) {
 | 
						|
		s2->v_bits[i] |= s1->v_bits[i];
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
Cintersect(s1,s2_p)
 | 
						|
	cset s1, *s2_p;
 | 
						|
{
 | 
						|
	/* Two sets are intersected by and-ing their bitvectors,
 | 
						|
	 * word by word.
 | 
						|
	 */
 | 
						|
 | 
						|
	cset s2;
 | 
						|
	short n;
 | 
						|
	register short i;
 | 
						|
 | 
						|
	s2 = *s2_p;
 | 
						|
	assert(s1->v_size == s2->v_size);
 | 
						|
	n = DIVWL(s1->v_size -1);  /* #words -1 */
 | 
						|
	for (i = 0; i <= n; i++) {
 | 
						|
		s2->v_bits[i] &= s1->v_bits[i];
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
Cdeleteset(s)
 | 
						|
	cset s;
 | 
						|
{
 | 
						|
	oldbitvect(s,DIVWL(s->v_size - 1) + 1);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
bool Cis_subset(s1,s2)
 | 
						|
	cset s1,s2;
 | 
						|
{
 | 
						|
	/* See if s1 is a subset of s2 */
 | 
						|
 | 
						|
	register short i;
 | 
						|
 | 
						|
	assert(s1->v_size == s2->v_size);
 | 
						|
	if (s1->v_size == 0) return TRUE;
 | 
						|
	for (i = 0; i <= DIVWL(s1->v_size-1); i++) {
 | 
						|
		if ((s1->v_bits[i] & ~(s2->v_bits[i])) != 0) {
 | 
						|
			return FALSE;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
Cclear_set(s_p)
 | 
						|
	cset *s_p;
 | 
						|
{
 | 
						|
	cset s;
 | 
						|
	register short i;
 | 
						|
 | 
						|
	s = *s_p;
 | 
						|
	assert (s != (cset) 0);
 | 
						|
	for (i = 0; i <=  DIVWL(s->v_size-1); i++) {
 | 
						|
		s->v_bits[i] = 0;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
Ccopy_set(s1,s2_p)
 | 
						|
	cset s1, *s2_p;
 | 
						|
{
 | 
						|
	cset s2;
 | 
						|
	register short i;
 | 
						|
 | 
						|
	s2 = *s2_p;
 | 
						|
	assert (s1->v_size == s2->v_size);
 | 
						|
	for (i = 0; i <=  DIVWL(s1->v_size-1); i++) {
 | 
						|
		s2->v_bits[i] = s1->v_bits[i];
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
Csubtract(s1,s2_p)
 | 
						|
	cset s1, *s2_p;
 | 
						|
{
 | 
						|
	cset s2;
 | 
						|
	register short i;
 | 
						|
 | 
						|
	s2 = *s2_p;
 | 
						|
	assert (s1->v_size == s2->v_size);
 | 
						|
	for (i = 0; i <=  DIVWL(s1->v_size-1); i++) {
 | 
						|
		s2->v_bits[i] &= ~(s1->v_bits[i]);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
bool Cequal(s1,s2)
 | 
						|
	cset s1, s2;
 | 
						|
{
 | 
						|
	register short i;
 | 
						|
 | 
						|
	assert (s1->v_size == s2->v_size);
 | 
						|
	for (i = 0; i <=  DIVWL(s1->v_size-1); i++) {
 | 
						|
		if (s1->v_bits[i] != s2->v_bits[i]) return FALSE;
 | 
						|
	}
 | 
						|
	return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
short Cnrelems(s)
 | 
						|
	cset s;
 | 
						|
{
 | 
						|
	register short n, cnt;
 | 
						|
 | 
						|
	cnt = 0;
 | 
						|
	for (n = 1; n <= s->v_size; n++) {
 | 
						|
		if (Cis_elem(n,s)) {
 | 
						|
			cnt++;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return cnt;
 | 
						|
}
 |