File:  [Research Unix] / researchv10dc / cmd / icon / src / iconx / oset.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:21:34 2018 UTC (8 years, 3 months ago) by root
Branches: belllabs, MAIN
CVS tags: researchv10, HEAD
researchv10 Dan Cross

/*
 * File: oset.c
 *  Contents: compl, diff, inter, unions
 */

#include "../h/rt.h"

/*
 * ~x - complement cset x.
 */

/* >compl */
OpDcl(compl,1,"~")
   {
   register int i, j;
   union block *bp;
   int *cs, csbuf[CsetSize];
   extern struct b_cset *alccset();

   blkreq((word)sizeof(struct b_cset));

   /*
    * Arg1 must be a cset.
    */
   if (cvcset(&Arg1, &cs, csbuf) == NULL)
      runerr(104, &Arg1);

   /*
    * Allocate a new cset and then copy each cset word from Arg1 
    *  itno the new cset words, complementing each.
    */
   bp = (union block *) alccset(0);
   for (i = 0; i < CsetSize; i++) {
       bp->cset.bits[i] = ~cs[i];
       }
      j = 0;
      for (i = 0; i < CsetSize * CIntSize; i++) {
         if (Testb(i, bp->cset.bits))
            j++;
         }
   bp->cset.size = j;

   Arg0.dword = D_Cset;
   BlkLoc(Arg0) = bp;
   Return;
   }
/* <compl */


/*
 * x -- y - difference of csets x and y or of sets x and y.
 */

OpDcl(diff,2,"--")
   {
   register word i, j;
   register union block *bp;
   int *cs1, *cs2, csbuf1[CsetSize], csbuf2[CsetSize];
   extern struct b_cset *alccset();
   struct descrip *dp;
   struct b_set *srcp, *dstp, *tstp;
   struct b_selem *sep;
   extern struct b_set *alcset();
   extern struct b_selem *alcselem();

   if (Qual(Arg1) || Qual(Arg2))
      goto skipsets;
   if (Arg1.dword == D_Set && Arg2.dword != D_Set)
      runerr(119,&Arg2);
   if (Arg2.dword == D_Set && Arg1.dword != D_Set)
      runerr(119,&Arg1);
   if (Arg1.dword == D_Set && Arg2.dword == D_Set) {
      /*
       * Both x and y are sets - do set difference
       *  get enough space for a new set the size of x.
       */
      blkreq(sizeof(struct b_set) + BlkLoc(Arg1)->set.size *
	 sizeof(struct b_selem));
      /*
       * For each element in set x if it isn't in set y
       *  copy it directly into the result set.
       */
      srcp = (struct b_set *) BlkLoc(Arg1);
      tstp = (struct b_set *) BlkLoc(Arg2);
      Arg0.dword = D_Set;
      dstp = alcset();
      BlkLoc(Arg0) = (union block *) dstp;
      for (i = 0; i < SSlots; i++) {
	 sep = (struct b_selem *) BlkLoc(srcp->sbucks[i]);
	 dp = &dstp->sbucks[i];
	 while (sep != NULL) {
	    if ( !locate((struct b_selem *)BlkLoc(tstp->sbucks[i]), sep) ) {
	       dp->dword = D_Selem;
	       BlkLoc(*dp) = (union block *) alcselem(&sep->setmem, sep->hashnum);
	       dp = &BlkLoc(*dp)->selem.clink;
	       dstp->size++;
	       }
	    sep = (struct b_selem *) BlkLoc(sep->clink);
	    }
	 }
      }
   else {
      skipsets:
   blkreq((word)sizeof(struct b_cset));

   /*
    * x and y must be csets.
    */
   if (cvcset(&Arg1, &cs1, csbuf1) == NULL)
      runerr(104, &Arg1);
   if (cvcset(&Arg2, &cs2, csbuf2) == NULL)
      runerr(104, &Arg2);

   /*
    * Allocate a new cset and in each word of it, compute the value
    *  of the bitwise difference of the corresponding words in the
    *  x and y csets.
    */
   bp = (union block *) alccset(0);
   for (i = 0; i < CsetSize; i++) {
      bp->cset.bits[i] = cs1[i] & ~cs2[i];
      }
      j = 0;
      for (i = 0; i < CsetSize*CIntSize; i++) {
	 if (Testb(i,bp->cset.bits))
	    j++;
	 }
   bp->cset.size = j;

   Arg0.dword = D_Cset;
   BlkLoc(Arg0) = bp;
   }
   Return;
   }


/*
 * x ** y - intersection of csets x and y or of sets x and y.
 */

OpDcl(inter,2,"**")
   {
   register word i, j;
   union block *bp;
   int *cs1, csbuf1[CsetSize], *cs2, csbuf2[CsetSize];
   extern struct b_cset *alccset();
   struct descrip *dp;
   struct b_set *srcp, *tstp, *dstp;
   struct b_selem *sep;
   extern struct b_set *alcset();
   extern struct b_selem *alcselem();

   if (Qual(Arg1) || Qual(Arg2))
      goto skipsets;
   if (Arg1.dword == D_Set && Arg2.dword != D_Set)
      runerr(119,&Arg2);
   if (Arg2.dword == D_Set && Arg1.dword != D_Set)
      runerr(119,&Arg1);
   if (Arg1.dword == D_Set && Arg2.dword == D_Set) {
      /*
       * Both x and y are sets - do set intersection
       *  get enough space for a new set the size of the smaller
       *  of the two sets.
       */
      blkreq(sizeof(struct b_set) + Min(BlkLoc(Arg1)->set.size,
	 BlkLoc(Arg2)->set.size) * sizeof(struct b_selem));
      /*
       * Using the smaller of the two sets as the source
       *  copy directly into the result each of its elements
       *  that are also members of the other set.
       */
      if (BlkLoc(Arg1)->set.size <= BlkLoc(Arg2)->set.size) {
	 srcp = (struct b_set *) BlkLoc(Arg1);
	 tstp = (struct b_set *) BlkLoc(Arg2);
	 }
      else {
	 srcp = (struct b_set *) BlkLoc(Arg2);
	 tstp = (struct b_set *) BlkLoc(Arg1);
	 }
      Arg0.dword = D_Set;
      dstp = alcset();
      BlkLoc(Arg0) = (union block *) dstp;
      for (i = 0; i < SSlots; i++) {
	 sep = (struct b_selem *) BlkLoc(srcp->sbucks[i]);
	 dp = &dstp->sbucks[i];
	 while (sep != NULL) {
	    if (locate((struct b_selem *)BlkLoc(tstp->sbucks[i]), sep)) {
	       dp->dword = D_Selem;
	       BlkLoc(*dp) = (union block *) alcselem(&sep->setmem, sep->hashnum);
	       dp = &BlkLoc(*dp)->selem.clink;
	       dstp->size++;
	       }
	    sep = (struct b_selem *) BlkLoc(sep->clink);
	    }
	 }
      }
      else {
	 skipsets:
   blkreq((word)sizeof(struct b_cset));

   /*
    * x and y must be csets.
    */
   if (cvcset(&Arg1, &cs1, csbuf1) == NULL)
      runerr(104, &Arg1);
   if (cvcset(&Arg2, &cs2, csbuf2) == NULL)
      runerr(104, &Arg2);

   /*
    * Allocate a new cset and in each word of it, compute the value
    *  of the bitwise intersection of the corresponding words in the
    *  x and y csets.
    */
   bp = (union block *) alccset(0);
   for (i = 0; i < CsetSize; i++) {
      bp->cset.bits[i] = cs1[i] & cs2[i];
      }
      j = 0;
      for (i = 0; i < CsetSize*CIntSize; i++) {
	 if (Testb(i,bp->cset.bits))
	    j++;
	 }
   bp->cset.size = j;

   Arg0.dword = D_Cset;
   BlkLoc(Arg0) = bp;
   }
   Return;
   }


/*
 * x ++ y - union of csets x and y or of sets x and y.
 */

OpDcl(unions,2,"++")
   {
   register word i, j;
   union block *bp;
   int *cs1, *cs2, csbuf1[CsetSize], csbuf2[CsetSize];
   extern struct b_cset *alccset();
   int res;
   struct b_set *srcp, *tstp, *dstp;
   struct b_selem *ep;
   struct descrip *dp, *hook;
   extern struct b_set *alcset();
   extern struct b_selem *alcselem();
   extern struct descrip *memb();

   if (Qual(Arg1) || Qual(Arg2))
      goto skipsets;
   if (Arg1.dword == D_Set && Arg2.dword != D_Set)
      runerr(119,&Arg2);
   if (Arg2.dword == D_Set && Arg1.dword != D_Set)
      runerr(119,&Arg1);
   if (Arg1.dword == D_Set && Arg2.dword == D_Set) {
      /*
       *  Both x and y are sets - do set union
       *  get enough space for a set as big as x + y.
       */
	 blkreq(sizeof(struct b_set) + (BlkLoc(Arg1)->set.size +
	    BlkLoc(Arg2)->set.size) * sizeof(struct b_selem));
	 /*
	  *  Select the larger of the two sets as the source
	  *  copy each element to a new set for the result
	  *  then insert each member of the second set into the
	  *  result set if it is not already there.
	  */
	 if (BlkLoc(Arg1)->set.size >= BlkLoc(Arg2)->set.size) {
	    srcp = (struct b_set *) BlkLoc(Arg1);
	    tstp = (struct b_set *) BlkLoc(Arg2);
	    }
	 else {
	    srcp = (struct b_set *) BlkLoc(Arg2);
	    tstp = (struct b_set *) BlkLoc(Arg1);
	    }
	 Arg0.dword = D_Set;
	 dstp = alcset();
	 BlkLoc(Arg0) = (union block *) dstp;
	 for (i = 0; i < SSlots; i++) {
	    ep = (struct b_selem *) BlkLoc(srcp->sbucks[i]);
	    dp = &dstp->sbucks[i];
	    while (ep != NULL) {
	       dp->dword = D_Selem;
	       BlkLoc(*dp) = (union block *) alcselem(&ep->setmem, ep->hashnum);
	       dp = &BlkLoc(*dp)->selem.clink;
	       dstp->size++;
	       ep = (struct b_selem *) BlkLoc(ep->clink);
	       }
	    }
	 for (i = 0; i < SSlots; i++) {
	    ep = (struct b_selem *) BlkLoc(tstp->sbucks[i]);
	    while (ep != NULL) {
	       hook = memb(dstp, &ep->setmem, ep->hashnum, &res);
	       if (res == 0)
		  addmem(dstp, alcselem(&ep->setmem,  ep->hashnum), hook);
	       ep = (struct b_selem *) BlkLoc(ep->clink);
	       }
	    }
	 }
      else {
      skipsets:

   blkreq((word)sizeof(struct b_cset));

   /*
    * x and y must be csets.
    */
   if (cvcset(&Arg1, &cs1, csbuf1) == NULL)
      runerr(104, &Arg1);
   if (cvcset(&Arg2, &cs2, csbuf2) == NULL)
      runerr(104, &Arg2);

   /*
    * Allocate a new cset and in each word of it, compute the value
    *  of the bitwise union of the corresponding words in the
    *  x and y csets.
    */
   bp = (union block *) alccset(0);
   for (i = 0; i < CsetSize; i++) {
      bp->cset.bits[i] = cs1[i] | cs2[i];
      }
      j = 0;
      for (i = 0; i < CsetSize*CIntSize; i++) {
	 if (Testb(i,bp->cset.bits))
	    j++;
	 }
   bp->cset.size = j;

   Arg0.dword = D_Cset;
   BlkLoc(Arg0) = bp;
   }
   Return;
   }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.