#include "block.h" unsigned long *SET_BIT_BLOCKS=NULL; unsigned char *CARDINALITY_BLOCKS=NULL; unsigned char *BIT_NUMBER_BLOCKS=NULL; unsigned short *B1_list,*B2_list,*IB_list; unsigned char *B1_byte,*B2_byte,*IB_byte; void initialize_blocks(void) /* initialize lookup tables used for bitwise operations */ { long i,b,n; unsigned char bit; NEW(SET_BIT_BLOCKS,32,unsigned long); for(i=0,b=31;i<32;b--,i++) { SET_BIT_BLOCKS[i] = 1 << b; } NEW(CARDINALITY_BLOCKS,256,unsigned char); for(i=0;i<256;i++){ for(b=n=0;b<8;b++){ if(i & (1<=0;bit=(bit<<1),b--) BIT_NUMBER_BLOCKS[b]=bit; } /***************** List operations for blocks *********************/ void add_list_block(b_type B) /* add a list to block B */ { MEW(B->list,(B->nbyte+1),unsigned short); B->list[0] = END_BLOCK_LIST; } void update_list_block(b_type B) /* set all bytes in block B not on the list to zero */ { long i,a; for(i=0,a=0;inbyte;i++) { if(i==B->list[a]) a++; else B->b[i]=0; } } /*************** Create and Copy operations for blocks ********************/ b_type Block(long N) /* create and return the null Block B */ { b_type B; if(N > MAX_BLOCK_SIZE) blockerror("Too many segments."); if(CARDINALITY_BLOCKS == NULL) initialize_blocks(); MEW(B,1,block_type); B->list = NULL; B->N = N; B->list2 = NULL; B->nint = (long) ceil((double)N/(double)32.0); B->nbyte= 4*B->nint; NEW(B->i,B->nint,unsigned long); B->b = (unsigned char*) B->i; return (B); } b_type BlockL(long N) /* create and return a null block B with a list */ { b_type B; B=Block(N); MEW(B->list,(B->nbyte+1),unsigned short); B->list[0] = END_BLOCK_LIST; return (B); } void CopyBlock(b_type B1,b_type B2) /* copy block B2 into block B1 - block B2 is modified */ { long j; if(B1->N != B2->N) { fprintf(stderr,"N1=%ld N2=%ld\t",B1->N,B2->N); blockerror("incompatible sets!"); } if(B2->list != NULL) update_list_block(B2); for(j=0;jnint;j++) B1->i[j] = B2->i[j]; } void CopyBlockL(b_type B1,b_type B2) /* copy block B2 into block B1 maintaining a list - B1 is modified */ { long j,k; if(B2->N != B1->N) { fprintf(stderr,"N1=%ld N2=%ld\t",B1->N,B2->N); blockerror("incompatible sets!"); } if(B2->list != NULL) update_list_block(B2); if(B1->list == NULL) add_list_block(B1); for(j=0,k=0;jnbyte;j++) if((B1->b[j] = B2->b[j])) B1->list[k++]=j; B1->list[k]=END_BLOCK_LIST; } void CopyBlockL2(b_type B1, b_type B2) /* copy block B2 into block B1 maintaining a list - B1 is modified */ { register unsigned char *b1=B1->b,*b2=B2->b; register unsigned short *list1=B1->list,*list2=B2->list; register long i; for( ;(i= *list1= *list2) != END_BLOCK_LIST; list1++,list2++){ b1[i] = b2[i]; } } void CopyBlockLL(register b_type B1,register b_type B2) { register long i,e; for(i=0;(e=B1->list[i]=B2->list[i]) != END_BLOCK_LIST; i++){ B1->b[e] = B2->b[e]; } } /**************** Modify operations for blocks ********************/ void ClearBlock(b_type B) /* set block B equal to the empty set */ { long j; for(j=0;jnint;j++) B->i[j] = (unsigned long) 0; } void FillBlock(b_type B) /* set block B equal to the set of integers from 0 to N-1 */ { long j; for(j=0;jnbyte;j++) B->b[j] = (unsigned char) 0xff; for(j=B->N;j<8*B->nbyte;j++) DeleteBlock(j,B); } void DeleteBlock(long element,b_type B) /* delete an element from block B */ { long nbit,nint; if(element >= B->nbyte*8) blockerror("input numbers too large"); nbit = element & 0x1f; /* element mod 32 */ nint = element >> 5; /* element / 32 */ if(MemberBlock(element,B)) B->i[nint] ^= SET_BIT_BLOCKS[nbit]; } void AddBlock(long element,b_type B) /* add an element to block B */ { long nbit,nint; if(element >= B->N) blockerror("input numbers too large"); nbit = element & 0x1f; /* element mod 32 */ nint = element >> 5; /* element / 32 */ B->i[nint] |= SET_BIT_BLOCKS[nbit]; } unsigned long MemberBlock(register long element, register b_type B) /* return 0 if element is not a member of B; else return non-zero */ { register long nbit,nint; if(element >= B->nbyte*8) blockerror("input numbers too large"); nbit = element & 0x1f; nint = element >> 5; return (B->i[nint] & SET_BIT_BLOCKS[nbit]); } /**************** Union operations for blocks ********************/ void UnionBlock3(b_type B1, b_type B2, b_type UB) /* modifies B1 to equal B1 U B2; B1 is returned */ { long j; for(j=0;jnint;j++) UB->i[j] = B1->i[j] | B2->i[j]; } b_type UnionBlock(b_type B1, b_type B2) /* modifies B1 to equal B1 U B2; B1 is returned */ { long j; if(B1->N != B2->N) { fprintf(stderr,"N1=%ld, N2=%ld\n",B1->N,B2->N); blockerror("N1!=N2 for Union operation"); } if(B1->list != NULL) update_list_block(B1); if(B2->list != NULL) update_list_block(B2); for(j=0;jnint;j++) B1->i[j] = B1->i[j] | B2->i[j]; return B1; } long UnionBlockCL(b_type B1, b_type B2) /* modifies B1 to equal B1 U B2; B1 is returned; B1 uses a list */ { long b,k,n=0; unsigned short *list; if(B1->list2==NULL) MEW(B1->list2,(B1->nbyte+1),unsigned short); list = B1->list2; B1_byte = B1->b; B2_byte = B2->b; B2_list = B2->list; B1_list = B1->list; for(k=0; TRUE ; ){ if(*B1_list < *B2_list){ b= *B1_list; B1_list++; } else if(*B1_list > *B2_list){ b= *B2_list; B2_list++; B1_byte[b] = B2_byte[b]; } else if(*B1_list==END_BLOCK_LIST){ break; /* b1 == b2 */ } else { b= *B1_list; B1_list++; B2_list++; B1_byte[b] = B1_byte[b] | B2_byte[b]; } n+=CARDINALITY_BLOCKS[(B1_byte[b])]; list[k++]=b; } list[k]= END_BLOCK_LIST; B1->list2 = B1->list; B1->list = list; return n; } void UnionBlockLF(b_type B1, b_type B2, b_type UB) /* modifies UB to equal B1 U B2; B1 is returned; all use a list */ { register unsigned short *list=UB->list; register unsigned short *list1=B1->list; register unsigned short *list2=B2->list; register long b; register unsigned char *b1=B1->b,*b2=B2->b,*ub=UB->b; while(TRUE){ if(*list1 < *list2){ b= *list1; list1++; ub[b] = b1[b]; } else if(*list1 > *list2){ b= *list2; list2++; ub[b] = b2[b]; } else { /* b1 == b2 */ if(*list1==END_BLOCK_LIST) break; b= *list1; list1++; list2++; ub[b] = b1[b] | b2[b]; } *list=b; list++; } *list= END_BLOCK_LIST; } void UnionBlockL(b_type B1, b_type B2) /* modifies B1 to equal B1 U B2; B1 is returned; B1 uses a list */ { long b,k; unsigned short *list; if(B1->list2==NULL) MEW(B1->list2,(B1->nbyte+1),unsigned short); list = B1->list2; B1_byte = B1->b; B2_byte = B2->b; B2_list = B2->list; B1_list = B1->list; for(k=0; TRUE ; ){ if(*B1_list < *B2_list){ b= *B1_list; B1_list++; } else if(*B1_list > *B2_list){ b= *B2_list; B2_list++; B1_byte[b] = B2_byte[b]; } else if(*B1_list==END_BLOCK_LIST){ break; /* b1 == b2 */ } else { b= *B1_list; B1_list++; B2_list++; B1_byte[b] = B1_byte[b] | B2_byte[b]; } list[k++]=b; } list[k]= END_BLOCK_LIST; B1->list2 = B1->list; B1->list = list; } /*************** Intersect operations **********************/ void IntersectNotBlock(b_type B1, b_type B2) /* modifies B1 to equal B1 intersect not B2 */ { long j; if(B1->N != B2->N) blockerror("N1!=N2 for Intersection operation"); for(j=0;jnint;j++) B1->i[j] = B1->i[j] & ~(B2->i[j]); } void IntersectBlock1(b_type B1, b_type B2,b_type IB) /* modifies IB to equal B1 intersect B2 */ { long j; if(B1->N != B2->N || B1->N != IB->N) blockerror("N1!=N2 for Intersection operation"); for(j=0;jnint;j++) { IB->i[j] = B1->i[j] & B2->i[j]; } } long IntersectBlockList(long *L, b_type B1, b_type B2) /* returns a list of the elements in the intersect of B1 and B2 */ { long C,j,b,bit; unsigned char s; for(C=j=0; (b=B2->list[j]) != END_BLOCK_LIST; j++) { if((s=B1->b[b] & B2->b[b])) { for(bit=0;bit<8;bit++) { if(s & BIT_NUMBER_BLOCKS[bit]) { L[C++] = (b*8 + bit); } } } } L[C]= -1; return C; } void IntersectBlock3(b_type B1, b_type B2) /* modifies B1 to equal B1 intersect B2 */ { long j; if(B1->N != B2->N) blockerror("N1!=N2 for Intersection operation"); for(j=0;jnint;j++) B1->i[j] = B1->i[j] & B2->i[j]; } void IntersectBlockL(b_type B1, b_type B2) /* modifies B2 to equal B1 intersect B2 */ { long i,k,e; if(B1->list != NULL) update_list_block(B1); for(i=k=0;(e=B2->list[i]) != END_BLOCK_LIST; i++){ if((B2->b[e] = B1->b[e]) & B2->b[e]) {B2->list[k++]=e; } } B2->list[k]=END_BLOCK_LIST; } long IntersectBlockCF(b_type B1, b_type B2,b_type IB) /* modifies IB to equal B1 intersect B2; returns cardinality of IB */ { register unsigned char *b1=B1->b,*b2=B2->b,*ib=IB->b; register unsigned short *list=B2->list; register unsigned short *newlist=IB->list; register unsigned char *card = CARDINALITY_BLOCKS; register long i,k,a,n=0; /**if(B1->N != B2->N || B1->N != IB->N) { fprintf(stderr,"N1=%d, N2=%d; NIB=%d\n",B1->N,B2->N,IB->N); blockerror("N1!=N2 for Intersection operation"); } DEBUG*/ for(n=a=k=0; (i=list[a]) != END_BLOCK_LIST; a++){ if((ib[i]=b1[i]) & b2[i]) { newlist[k++]=i; n+=card[(ib[i])]; } } newlist[k]= END_BLOCK_LIST; return n; } void IntersectBlockF(b_type B1, b_type B2,b_type IB) /* modifies IB to equal B1 intersect B2 */ { register unsigned char *b1=B1->b,*b2=B2->b,*ib=IB->b; register unsigned short *list=B2->list; register unsigned short *newlist=IB->list; register long e; while((e= *list) != END_BLOCK_LIST){ if((ib[e] = b1[e]) & b2[e]) {*newlist=e; newlist++; } list++; } *newlist=END_BLOCK_LIST; } /*************** Cardinality operations **********************/ long CardInterBlockLF(b_type B1,b_type B2) /* return cardinality of the intersection of B1 and B2 - using lists */ { register unsigned char *b1=B1->b,*b2=B2->b; register unsigned short *list=B2->list; register unsigned char *card = CARDINALITY_BLOCKS; register long i,n=0; while((i= *list) != END_BLOCK_LIST) { n+=card[(b1[i] & b2[i])]; list++; } return n; } long CardInterBlock(b_type B1,b_type B2) /* return cardinality of the intersection of B1 and B2 */ { long i,b,byte,n=0; if(B1->N != B2->N) { fprintf(stderr,"N1=%ld; N2=%ld\n",B1->N,B2->N); blockerror("N1!=N2 for CardIntersect operation"); } for(i=0,byte=0; i < B1->nint; i++,byte+=4) { if(B1->i[i] & B2->i[i]) for(b=0;b<4;b++) { n+=CARDINALITY_BLOCKS[(B1->b[byte+b])& (B2->b[byte+b])]; } } return n; } long CardBlockL(b_type B) { register unsigned char *b=B->b, *card = CARDINALITY_BLOCKS; register unsigned short *list=B->list; register long i,n=0; while((i= *list) != END_BLOCK_LIST) { n+=card[b[i]]; list++; } return n; } long CardBlock(b_type B) /* return cardinality of block B */ { long i,b,byte,n=0; if(B->list != NULL) update_list_block(B); for(i=0,byte=0; i < B->nint; i++,byte+=4) { if(B->i[i]) for(b=0;b<4;b++) n+=CARDINALITY_BLOCKS[(B->b[byte+b])]; } return n; } /******************* List operations **********************/ long *ListBlock(b_type B) /* return list of elements in block B; list is terminated by -1 */ { long C,i,j=0,*L; if(B->list != NULL) update_list_block(B); C=CardBlock(B); NEW(L,C+1,long); for(i=0;iN;i++) if(MemberBlock(i,B)) { L[j]=i; j++; } L[j]= -1; return L; } long *ListBlockL(b_type B) /* return list of elements in block B; list is terminated by -1 */ { long C,p,b,bit,j=0,*L; C=CardBlockL(B); NEW(L,C+1,long); for(p=0,b=B->list[p]; b != END_BLOCK_LIST; p++,b=B->list[p]){ for(bit=0;bit<8;bit++) { if(B->b[b] & BIT_NUMBER_BLOCKS[bit]){ L[j]=b*8+bit;j++; } } } L[j]= -1; return L; } /******************* Output operations **********************/ b_type PutBlock(FILE *fptr,b_type B) /* print block B to file pointed to by fptr */ { long i,j=0,*m; if(B->list != NULL) update_list_block(B); m = ListBlock(B);/**/ /* m = ListBlockL(B);*/ fprintf(fptr," {"); for(i=0;m[i] != -1; i++) { if(m[i+1] != -1) fprintf(fptr,"%5ld,",m[i]); else fprintf(fptr,"%5ld",m[i]); if(i%10==9 && m[i+1] != -1) fprintf(fptr,"\n "); } if(j>0) fprintf(fptr,"%5ld }\n",m[i]); else fprintf(fptr," }\n"); free(m); return B; } b_type NilBlock(b_type B) /* destroy block B */ { if(B != NULL) { if(B->list !=NULL) free(B->list); if(B->list2 !=NULL) free(B->list2); free(B->i); free(B); } return (b_type) NULL; } void blockerror(char *s) { fprintf(stderr,"Block Error: %s\n",s); exit(1); } /*************** operations **********************/ long IntersectBlockLCXOR(b_type eB,b_type B, b_type IB) /* Sets IIB = eB intersect B and sets EOB = B xor IB */ { register unsigned char *eb=eB->b,*b=B->b,*ib=IB->b; register unsigned short *list=B->list,*eolist=B->list; register unsigned short *newlist=IB->list; register unsigned char *card = CARDINALITY_BLOCKS; register long e,k,ik,n; for(n=ik=k=0; (e= *list) != END_BLOCK_LIST; list++){ if((ib[e]=eb[e]) & b[e]) { newlist[ik++]=e; n+=card[(ib[e])]; if(b[e]^ib[e]){ eolist[k++] = e; } } else { eolist[k++] = e; } } eolist[k] = newlist[ik] = END_BLOCK_LIST; return n; }