set.c

来自「SRI international 发布的OAA框架软件」· C语言 代码 · 共 817 行 · 第 1/2 页

C
817
字号
/*	set.c

	The following is a general-purpose set library originally developed
	by Hank Dietz and enhanced by Terence Parr to allow dynamic sets.
	
	Sets are now structs containing the #words in the set and
	a pointer to the actual set words.
	
	Generally, sets need not be explicitly allocated.  They are
	created/extended/shrunk when appropriate (e.g. in set_of()).
	HOWEVER, sets need to be destroyed (free()ed) when they go out of scope
	or are otherwise no longer needed.  A routine is provided to
	free a set.
	
	Sets can be explicitly created with set_new(s, max_elem).
	
	Sets can be declared to have minimum size to reduce realloc traffic.
	Default minimum size = 1.
	
	Sets can be explicitly initialized to have no elements (set.n == 0)
	by using the 'empty' initializer:
	
	Examples:
		set a = empty;	-- set_deg(a) == 0
		
		return( empty );
	
	Example set creation and destruction:
	
	set
	set_of2(e,g)
	unsigned e,g;
	{
		set a,b,c;
		
		b = set_of(e);		-- Creates space for b and sticks in e
		set_new(c, g);		-- set_new(); set_orel() ==> set_of()
		set_orel(g, &c);
		a = set_or(b, c);
		.
		.
		.
		set_free(b);
		set_free(c);
		return( a );
	}

	1987 by Hank Dietz
	
	Modified by:
		Terence Parr
		Purdue University
		October 1989

	Made it smell less bad to C++ 7/31/93 -- TJP
*/

#include <stdio.h>
#include "pcctscfg.h"
#ifdef __STDC__
#include <stdlib.h>
#else
#include <malloc.h>
#endif
#include <string.h>

#include "set.h"

#define MIN(i,j) ( (i) > (j) ? (j) : (i))
#define MAX(i,j) ( (i) < (j) ? (j) : (i))

/* elems can be a maximum of 32 bits */
static unsigned bitmask[] = {
	0x00000001, 0x00000002, 0x00000004, 0x00000008,
	0x00000010, 0x00000020, 0x00000040, 0x00000080,
	0x00000100, 0x00000200, 0x00000400, 0x00000800,
	0x00001000, 0x00002000, 0x00004000, 0x00008000,
#if !defined(PC) || defined(PC32)
	0x00010000, 0x00020000, 0x00040000, 0x00080000,
	0x00100000, 0x00200000, 0x00400000, 0x00800000,
	0x01000000, 0x02000000, 0x04000000, 0x08000000,
	0x10000000, 0x20000000, 0x40000000, 0x80000000
#endif
};

set empty = set_init;
static unsigned min=1;

#define StrSize		200

#ifdef MEMCHK
#define CHK(a)					\
	if ( a.setword != NULL )	\
	  if ( !valid(a.setword) )	\
		{fprintf(stderr, "%s(%d): invalid set\n",__FILE__,__LINE__); exit(-1);}
#else
#define CHK(a)
#endif

/*
 * Set the minimum size (in words) of a set to reduce realloc calls
 */
void
#ifdef __USE_PROTOS
set_size( unsigned n )
#else
set_size( n )
unsigned n;
#endif
{
	min = n;
}

unsigned int
#ifdef __USE_PROTOS
set_deg( set a )
#else
set_deg( a )
set a;
#endif
{
	/* Fast compute degree of a set... the number
	   of elements present in the set.  Assumes
	   that all word bits are used in the set
	   and that SETSIZE(a) is a multiple of WORDSIZE.
	*/
	register unsigned *p = &(a.setword[0]);
	register unsigned *endp = NULL; /* MR27 Avoid false memory check report */
	register unsigned degree = 0;

	CHK(a);
	if ( a.n == 0 ) return(0);
	endp = &(a.setword[a.n]);
	while ( p < endp )
	{
		register unsigned t = *p;
		register unsigned *b = &(bitmask[0]);
		do {
			if (t & *b) ++degree;
		} while (++b < &(bitmask[WORDSIZE]));
		p++;
	}

	return(degree);
}

set
#ifdef __USE_PROTOS
set_or( set b, set c )
#else
set_or( b, c )
set b;
set c;
#endif
{
	/* Fast set union operation */
	/* resultant set size is max(b, c); */
	set *big;
	set t;
	unsigned int m,n;
	register unsigned *r, *p, *q, *endp;

	CHK(b); CHK(c);
	t = empty;
	if (b.n > c.n) {big= &b; m=b.n; n=c.n;} else {big= &c; m=c.n; n=b.n;}
	set_ext(&t, m);
	r = t.setword;

	/* Or b,c until max of smaller set */
	q = c.setword;
	p = b.setword;
	endp = &(b.setword[n]);
	while ( p < endp ) *r++ = *p++ | *q++;	

	/* Copy rest of bigger set into result */
	p = &(big->setword[n]);
	endp = &(big->setword[m]);
	while ( p < endp ) *r++ = *p++;

	return(t);
}

set
#ifdef __USE_PROTOS
set_and( set b, set c )
#else
set_and( b, c )
set b;
set c;
#endif
{
	/* Fast set intersection operation */
	/* resultant set size is min(b, c); */
	set t;
	unsigned int n;
	register unsigned *r, *p, *q, *endp;

	CHK(b); CHK(c);
	t = empty;
	n = (b.n > c.n) ? c.n : b.n;
	if ( n == 0 ) return t;		/* TJP 4-27-92 fixed for empty set */
	set_ext(&t, n);
	r = t.setword;

	/* & b,c until max of smaller set */
	q = c.setword;
	p = b.setword;
	endp = &(b.setword[n]);
	while ( p < endp ) *r++ = *p++ & *q++;	

	return(t);
}

set
#ifdef __USE_PROTOS
set_dif( set b, set c )
#else
set_dif( b, c )
set b;
set c;
#endif
{
	/* Fast set difference operation b - c */
	/* resultant set size is size(b) */
	set t;
	unsigned int n;
	register unsigned *r, *p, *q, *endp;

	CHK(b); CHK(c);
	t = empty;
	n = (b.n <= c.n) ? b.n : c.n ;
	if ( b.n == 0 ) return t;		/* TJP 4-27-92 fixed for empty set */
									/* WEC 12-1-92 fixed for c.n = 0 */
	set_ext(&t, b.n);
	r = t.setword;

	/* Dif b,c until smaller set size */
	q = c.setword;
	p = b.setword;
	endp = &(b.setword[n]);
	while ( p < endp ) *r++ = *p++ & (~ *q++);	

	/* Copy rest of b into result if size(b) > c */
	if ( b.n > n )
	{
		p = &(b.setword[n]);
		endp = &(b.setword[b.n]);
		while ( p < endp ) *r++ = *p++;
	}

	return(t);
}

set
#ifdef __USE_PROTOS
set_of( unsigned b )
#else
set_of( b )
unsigned b;
#endif
{
	/* Fast singleton set constructor operation */
	static set a;

	if ( b == nil ) return( empty );
	set_new(a, b);
	a.setword[DIVWORD(b)] = bitmask[MODWORD(b)];

	return(a);
}

/*
 * Extend (or shrink) the set passed in to have n words.
 *
 * if n is smaller than the minimum, boost n to have the minimum.
 * if the new set size is the same as the old one, do nothing.
 *
 * TJP 4-27-92 Fixed so won't try to alloc 0 bytes
 */
void
#ifdef __USE_PROTOS
set_ext( set *a, unsigned int n )
#else
set_ext( a, n )
set *a;
unsigned int n;
#endif
{
	register unsigned *p;
	register unsigned *endp;
	unsigned int size;
	
	CHK((*a));
    if ( a->n == 0 )
    {
		if ( n == 0 ) return;
		if (a->setword != NULL) {
			free (a->setword);	/* MR20 */
		}
        a->setword = (unsigned *) calloc(n, BytesPerWord);
        if ( a->setword == NULL )
        {
            fprintf(stderr, "set_ext(%d words): cannot allocate set\n", n);
            exit(-1);
        }
        a->n = n;
        return;
    }
	if ( n < min ) n = min;
	if ( a->n == n || n == 0 ) return;
	size = a->n;
	a->n = n;
	a->setword = (unsigned *) realloc( (char *)a->setword, (n*BytesPerWord) );
	if ( a->setword == NULL )
	{
		fprintf(stderr, "set_ext(%d words): cannot allocate set\n", n);
		exit(-1);
	}

	p    = &(a->setword[size]);		/* clear from old size to new size */
	endp = &(a->setword[a->n]);
	do {
		*p++ = 0;
	} while ( p < endp );
}

set
#ifdef __USE_PROTOS
set_not( set a )
#else
set_not( a )
set a;
#endif
{
	/* Fast not of set a (assumes all bits used) */
	/* size of resultant set is size(a) */
	/* ~empty = empty cause we don't know how bit to make set */
	set t;
	register unsigned *r;
	register unsigned *p = a.setword;
	register unsigned *endp = &(a.setword[a.n]);

	CHK(a);
	t = empty;
	if ( a.n == 0 ) return( empty );
	set_ext(&t, a.n);
	r = t.setword;
	
	do {
		*r++ = (~ *p++);
	} while ( p < endp );

	return(t);
}

int
#ifdef __USE_PROTOS
set_equ( set a, set b )
#else
set_equ( a, b )
set a;
set b;
#endif
{
/* 8-Nov-97     Make it work with sets of different sizes       */
/*              Easy to understand, too.  Probably faster.      */
/*              Check for a equal to b                          */

    unsigned int    count;      /* MR11 */
    unsigned int    i;          /* MR11 */

	CHK(a); CHK(b);

    count=MIN(a.n,b.n);
    if (count == 0) return 1;
    for (i=0; i < count; i++) {
      if (a.setword[i] != b.setword[i]) return 0;
    };
    if (a.n < b.n) {
      for (i=count; i < b.n; i++) {
        if (b.setword[i] != 0) return 0;
      }
      return 1;
    } else if (a.n > b.n) {
      for (i=count; i < a.n; i++) {
        if (a.setword[i] != 0) return 0;
      }
      return 1;
    } else {
      return 1;
    };
}

int
#ifdef __USE_PROTOS
set_sub( set a, set b )
#else
set_sub( a, b )
set a;
set b;
#endif
{

/* 8-Nov-97     Make it work with sets of different sizes       */
/*              Easy to understand, too.  Probably faster.      */
/*              Check for a is a PROPER subset of b             */

    unsigned int    count;
    unsigned int    i;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?