home *** CD-ROM | disk | FTP | other *** search
/ APDL Public Domain 1 / APDL_PD1A.iso / program / language / icon / Source / Iconx / C / Oset < prev    next >
Encoding:
Text File  |  1990-07-19  |  8.0 KB  |  293 lines

  1. /*
  2.  * File: oset.c
  3.  *  Contents: compl, diff, inter, unions
  4.  */
  5.  
  6. #include "../h/config.h"
  7. #include "../h/rt.h"
  8. #include "rproto.h"
  9.  
  10.  
  11. /*
  12.  * ~x - complement cset x.
  13.  */
  14.  
  15. OpDcl(compl,1,"~")
  16.    {
  17.    register int i;
  18.    union block *bp;
  19.    int *cs, csbuf[CsetSize];
  20.  
  21.    if (blkreq((word)sizeof(struct b_cset)) == Error)
  22.       RunErr(0, NULL);
  23.  
  24.    /*
  25.     * Arg1 must be a cset.
  26.     */
  27.    if (cvcset(&Arg1, &cs, csbuf) == CvtFail) 
  28.       RunErr(104, &Arg1);
  29.  
  30.    /*
  31.     * Allocate a new cset and then copy each cset word from Arg1 
  32.     *  into the new cset words, complementing each bit.
  33.     */
  34.    bp = (union block *)alccset();
  35.    for (i = 0; i < CsetSize; i++) 
  36.        bp->cset.bits[i] = ~cs[i];
  37.    Arg0.dword = D_Cset;
  38.    BlkLoc(Arg0) = bp;
  39.    Return;
  40.    }
  41.  
  42. /*
  43.  * x -- y - difference of csets x and y or of sets x and y.
  44.  */
  45.  
  46. OpDcl(diff,2,"--")
  47.    {
  48.    register word i;
  49.    word slotnum;
  50.    register union block *srcp, *tstp, *dstp, **hook;
  51.    int *cs1, *cs2, csbuf1[CsetSize], csbuf2[CsetSize], res;
  52.    struct b_slots *seg;
  53.    struct b_selem *ep;
  54.  
  55.    if (Qual(Arg1) || Qual(Arg2))
  56.       goto skipsets;
  57.    if (Arg1.dword == D_Set && Arg2.dword != D_Set) 
  58.       RunErr(119, &Arg2);
  59.    if (Arg2.dword == D_Set && Arg1.dword != D_Set) 
  60.       RunErr(119, &Arg1);
  61.    if (Arg1.dword == D_Set && Arg2.dword == D_Set) {
  62.       /*
  63.        * Both Arg1 and Arg2 are sets - do set difference.  Make a new set
  64.        *  based on the size of Arg1.
  65.        */
  66.       dstp = hmake(T_Set, (word)0, BlkLoc(Arg1)->set.size);
  67.       if (dstp == NULL)
  68.          RunErr(0, NULL);
  69.       /*
  70.        * For each element in set Arg1 if it is not in set Arg2
  71.        *  copy it directly into the result set.
  72.        */
  73.       srcp = BlkLoc(Arg1);
  74.       tstp = BlkLoc(Arg2);
  75.       for (i = 0; i < HSegs && (seg = srcp->set.hdir[i]) != NULL; i++)
  76.          for (slotnum = segsize[i] - 1; slotnum >= 0; slotnum--) {
  77.             ep = (struct b_selem *)seg->hslots[slotnum];
  78.             while (ep != NULL) {
  79.                memb(tstp, &ep->setmem, ep->hashnum, &res);
  80.                if (res == 0) {
  81.                   hook = memb(dstp, &ep->setmem, ep->hashnum, &res);
  82.                   addmem(&dstp->set, alcselem(&ep->setmem, ep->hashnum), hook);
  83.                   }
  84.                ep = (struct b_selem *)ep->clink;
  85.                }
  86.             }
  87.       Arg0.dword = D_Set;
  88.       BlkLoc(Arg0) = dstp;
  89.       if (TooSparse(dstp))
  90.          hshrink(&Arg0);
  91.       }
  92.    else {
  93.       skipsets:
  94.    if (blkreq((word)sizeof(struct b_cset)) == Error)
  95.       RunErr(0, NULL);
  96.  
  97.    /*
  98.     * Arg1 and Arg2 must be csets.
  99.     */
  100.    if (cvcset(&Arg1, &cs1, csbuf1) == CvtFail) 
  101.       RunErr(120, &Arg1);
  102.    if (cvcset(&Arg2, &cs2, csbuf2) == CvtFail) 
  103.       RunErr(120, &Arg2);
  104.  
  105.    /*
  106.     * Allocate a new cset and in each word of it, compute the value
  107.     *  of the bitwise difference of the corresponding words in the
  108.     *  Arg1 and Arg2 csets.
  109.     */
  110.    dstp = (union block *)alccset();
  111.    for (i = 0; i < CsetSize; i++) {
  112.       dstp->cset.bits[i] = cs1[i] & ~cs2[i];
  113.       }
  114.  
  115.    Arg0.dword = D_Cset;
  116.    BlkLoc(Arg0) = dstp;
  117.    }
  118.    Return;
  119.    }
  120.  
  121. /*
  122.  * x ** y - intersection of csets x and y or of sets x and y.
  123.  */
  124.  
  125. OpDcl(inter,2,"**")
  126.    {
  127.    register word i;
  128.    word slotnum;
  129.    register union block *srcp, *tstp, *dstp, **hook;
  130.    int *cs1, *cs2, csbuf1[CsetSize], csbuf2[CsetSize], res;
  131.    struct b_slots *seg;
  132.    struct b_selem *ep;
  133.  
  134.    if (Qual(Arg1) || Qual(Arg2))
  135.       goto skipsets;
  136.    if (Arg1.dword == D_Set && Arg2.dword != D_Set) 
  137.       RunErr(119, &Arg2);
  138.    if (Arg2.dword == D_Set && Arg1.dword != D_Set) 
  139.       RunErr(119, &Arg1);
  140.    if (Arg1.dword == D_Set && Arg2.dword == D_Set) {
  141.       /*
  142.        * Both Arg1 and Arg2 are sets - do set intersection.
  143.        *  Make a new set the size of the smaller argument set.
  144.        */
  145.       dstp = hmake(T_Set, (word)0,
  146.          Min(BlkLoc(Arg1)->set.size, BlkLoc(Arg2)->set.size));
  147.       if (dstp == NULL)
  148.          RunErr(0, NULL);
  149.       /*
  150.        * Using the smaller of the two sets as the source
  151.        *  copy directly into the result each of its elements
  152.        *  that are also members of the other set.
  153.        */
  154.       if (BlkLoc(Arg1)->set.size <= BlkLoc(Arg2)->set.size) {
  155.          srcp = BlkLoc(Arg1);
  156.          tstp = BlkLoc(Arg2);
  157.          }
  158.       else {
  159.          srcp = BlkLoc(Arg2);
  160.          tstp = BlkLoc(Arg1);
  161.          }
  162.       for (i = 0; i < HSegs && (seg = srcp->set.hdir[i]) != NULL; i++)
  163.          for (slotnum = segsize[i] - 1; slotnum >= 0; slotnum--) {
  164.             ep = (struct b_selem *)seg->hslots[slotnum];
  165.             while (ep != NULL) {
  166.                memb(tstp, &ep->setmem, ep->hashnum, &res);
  167.                if (res != 0) {
  168.                   hook = memb(dstp, &ep->setmem, ep->hashnum, &res);
  169.                   addmem(&dstp->set, alcselem(&ep->setmem, ep->hashnum), hook);
  170.                   }
  171.                ep = (struct b_selem *)ep->clink;
  172.                }
  173.             }
  174.       Arg0.dword = D_Set;
  175.       BlkLoc(Arg0) = dstp;
  176.       if (TooSparse(dstp))
  177.          hshrink(&Arg0);
  178.       }
  179.    else {
  180.       skipsets:
  181.    if (blkreq((word)sizeof(struct b_cset)) == Error)
  182.       RunErr(0, NULL);
  183.  
  184.    /*
  185.     * Arg1 and Arg2 must be csets.
  186.     */
  187.    if (cvcset(&Arg1, &cs1, csbuf1) == CvtFail) 
  188.       RunErr(120, &Arg1);
  189.    if (cvcset(&Arg2, &cs2, csbuf2) == CvtFail) 
  190.       RunErr(120, &Arg2);
  191.  
  192.    /*
  193.     * Allocate a new cset and in each word of it, compute the value
  194.     *  of the bitwise intersection of the corresponding words in the
  195.     *  Arg1 and Arg2 csets.
  196.     */
  197.    dstp = (union block *)alccset();
  198.    for (i = 0; i < CsetSize; i++) {
  199.       dstp->cset.bits[i] = cs1[i] & cs2[i];
  200.       }
  201.  
  202.    Arg0.dword = D_Cset;
  203.    BlkLoc(Arg0) = dstp;
  204.    }
  205.    Return;
  206.    }
  207.  
  208. /*
  209.  * x ++ y - union of csets x and y or of sets x and y.
  210.  */
  211.  
  212. OpDcl(unions,2,"++")
  213.    {
  214.    register word i;
  215.    word slotnum;
  216.    register union block *srcp, *tstp, *dstp, **hook;
  217.    int *cs1, *cs2, csbuf1[CsetSize], csbuf2[CsetSize], res;
  218.    struct b_slots *seg;
  219.    struct b_selem *ep;
  220.    dptr srcd, tstd;
  221.  
  222.    if (Qual(Arg1) || Qual(Arg2))
  223.       goto skipsets;
  224.    if (Arg1.dword == D_Set && Arg2.dword != D_Set) 
  225.       RunErr(119, &Arg2);
  226.    if (Arg2.dword == D_Set && Arg1.dword != D_Set) 
  227.       RunErr(119, &Arg1);
  228.    if (Arg1.dword == D_Set && Arg2.dword == D_Set) {
  229.       /*
  230.        * Both Arg1 and Arg2 are sets - do set union.  Copy the larger set
  231.        *  and ensure there's room for *Arg1 + *Arg2 elements.
  232.        */
  233.       if (BlkLoc(Arg1)->set.size >= BlkLoc(Arg2)->set.size) {
  234.          srcd = &Arg1;
  235.          tstd = &Arg2;
  236.          }
  237.       else {
  238.          srcd = &Arg2;
  239.          tstd = &Arg1;
  240.          }
  241.       if (cpset(srcd, &Arg0, BlkLoc(Arg1)->set.size + BlkLoc(Arg2)->set.size)
  242.             == Error)
  243.          RunErr(0, NULL);
  244.       /*
  245.        * Copy each element from the smaller set into the result set,
  246.        *  if it is not already there.
  247.        */
  248.       srcp = BlkLoc(*srcd);
  249.       tstp = BlkLoc(*tstd);
  250.       dstp = BlkLoc(Arg0);
  251.       for (i = 0; i < HSegs && (seg = tstp->set.hdir[i]) != NULL; i++)
  252.          for (slotnum = segsize[i] - 1; slotnum >= 0; slotnum--) {
  253.             ep = (struct b_selem *)seg->hslots[slotnum];
  254.             while (ep != NULL) {
  255.                hook = memb(dstp, &ep->setmem, ep->hashnum, &res);
  256.                if (res == 0)
  257.                   addmem(&dstp->set, alcselem(&ep->setmem, ep->hashnum), hook);
  258.                ep = (struct b_selem *)ep->clink;
  259.             }
  260.          }
  261.       if (TooCrowded(dstp))        /* if the union got too big, enlarge */
  262.          hgrow(&Arg0);
  263.       }
  264.    else {
  265.       skipsets:
  266.  
  267.    if (blkreq((word)sizeof(struct b_cset)) == Error)
  268.       RunErr(0, NULL);
  269.  
  270.    /*
  271.     * Arg1 and Arg2 must be csets.
  272.     */
  273.    if (cvcset(&Arg1, &cs1, csbuf1) == CvtFail) 
  274.       RunErr(120, &Arg1);
  275.    if (cvcset(&Arg2, &cs2, csbuf2) == CvtFail) 
  276.       RunErr(120, &Arg2);
  277.  
  278.    /*
  279.     * Allocate a new cset and in each word of it, compute the value
  280.     *  of the bitwise union of the corresponding words in the
  281.     *  Arg1 and Arg2 csets.
  282.     */
  283.    dstp = (union block *)alccset();
  284.    for (i = 0; i < CsetSize; i++) {
  285.       dstp->cset.bits[i] = cs1[i] | cs2[i];
  286.       }
  287.  
  288.    Arg0.dword = D_Cset;
  289.    BlkLoc(Arg0) = dstp;
  290.    }
  291.    Return;
  292.    }
  293.