9037d137f5
This uncovers a problem in il/il_aux.c: it passes 3 arguments to getlines(), but the function expects 4 arguments. I add FALSE as the 4th argument. TRUE would fill in the list of mesregs. IL uses mesregs during phase 1, but this call to getlines() is in phase 2. TRUE would leak memory unless I added a call to Ldeleteset(mesregs). So I pass FALSE. Functions passed to go() now have a `void *` parameter because no_action() now takes a `void *`.
263 lines
4.4 KiB
C
263 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(short n)
|
|
{
|
|
cset s;
|
|
|
|
s = newbitvect(DIVWL(n-1) + 1);
|
|
s->v_size = n;
|
|
return s;
|
|
}
|
|
|
|
|
|
bool Cis_elem(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;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void Cadd(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;
|
|
}
|
|
|
|
|
|
void Cremove(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(cset s)
|
|
{
|
|
return Cnext((Cindex) 0,s);
|
|
}
|
|
|
|
|
|
Cindex Cnext(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(Cindex i)
|
|
{
|
|
return (Celem_t) i;
|
|
}
|
|
|
|
|
|
|
|
void Cjoin(cset s1, cset *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];
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void Cintersect(cset s1, cset *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];
|
|
}
|
|
}
|
|
|
|
|
|
void Cdeleteset(cset s)
|
|
{
|
|
oldbitvect(s,DIVWL(s->v_size - 1) + 1);
|
|
}
|
|
|
|
|
|
bool Cis_subset(cset s1, cset 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;
|
|
}
|
|
|
|
|
|
void Cclear_set(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;
|
|
}
|
|
}
|
|
|
|
|
|
void Ccopy_set(cset s1, cset *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];
|
|
}
|
|
}
|
|
|
|
|
|
void Csubtract(cset s1, cset *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(cset s1, cset 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(cset s)
|
|
{
|
|
register short n, cnt;
|
|
|
|
cnt = 0;
|
|
for (n = 1; n <= s->v_size; n++) {
|
|
if (Cis_elem(n,s)) {
|
|
cnt++;
|
|
}
|
|
}
|
|
return cnt;
|
|
}
|