📄 set.c
字号:
/* 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>#ifdef __cplusplus#ifndef __STDC__#define __STDC__#endif#endif#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 __STDC__set_size( unsigned n )#elseset_size( n )unsigned n;#endif{ min = n;}unsigned int#ifdef __STDC__set_deg( set a )#elseset_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 = &(a.setword[a.n]); register unsigned degree = 0; CHK(a); if ( a.n == 0 ) return(0); 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 __STDC__set_or( set b, set c )#elseset_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 __STDC__set_and( set b, set c )#elseset_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 __STDC__set_dif( set b, set c )#elseset_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 __STDC__set_of( unsigned b )#elseset_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 __STDC__set_ext( set *a, unsigned int n )#elseset_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; 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 __STDC__set_not( set a )#elseset_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 __STDC__set_equ( set a, set b )#elseset_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 __STDC__set_sub( set a, set b )#elseset_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 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -