278 lines
4.3 KiB
C
278 lines
4.3 KiB
C
|
/* 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;
|
||
|
}
|