home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast2.iso / ddjmag / ddj8611.zip / HOLUB.NOV next >
Text File  |  1986-12-01  |  14KB  |  394 lines

  1.                           Listing 1 -- set.h
  2.  ------------------------------------------------------------------------------
  3.   1 /* SET.H:       Header to use the set manipulation routiness in set.c
  4.   2  *
  5.   3  * Copyright (c) 1986, Allen I. Holub.  All rights reserved
  6.   4  */
  7.   5 
  8.   6 #define DEFBYTES        2               /* bytes in def set (>= 1)      */
  9.   7 #define DEFBITS         (DEFBYTES * 8)  /* bits in default set          */
  10.   8 
  11.   9 typedef struct
  12.  10 {
  13.  11         unsigned        nbytes : 13;      /* Number of bytes in map      */
  14.  12         unsigned        compl  : 1;       /* This is a negative true set */
  15.  13         int             nbits;            /* Number of bits in map       */
  16.  14         unsigned char   *map;             /* Pointer to the map          */
  17.  15         unsigned char   defmap[DEFBYTES]; /* The map itself              */
  18.  16 }
  19.  17 SET;
  20.  18 
  21.  19 extern  void    set_op  ( int,  SET*, SET*, SET*); /* Routines in set.c */
  22.  20 extern  int     set_cmp ( SET*, SET*    );
  23.  21 extern  int     subset  ( SET*, SET*    );
  24.  22 extern  int     num_ele ( SET*          );
  25.  23 extern  void    delset  ( SET*          );
  26.  24 extern  SET     *newset (               );
  27.  25 
  28.  26 #define UNION           0       /* x is in s1 or s2                     */
  29.  27 #define INTERSECT       1       /* x is in s1 and s2                    */
  30.  28 #define DIFFERENCE      2       /* x is in s1 but !s2 or in s2 but !s1  */
  31.  29 #define INVERT          3       /* ones complement                      */
  32.  30 #define ASSIGN          4       /* s1 = s2                              */
  33.  31 #define CLEAR           5       /* d = all bits cleared                 */
  34.  32 #define FILL            6       /* d = all bits set                     */
  35.  33 
  36.  34 #define union(d,s1,s2)          set_op( UNION,      d,     s1,     s2   )
  37.  35 #define intersection(d,s1,s2)   set_op( INTERSECT,  d,     s1,     s2   )
  38.  36 #define difference(d,s1,s2)     set_op( DIFFERENCE, d,     s1,     s2   )
  39.  37 #define assign(d,s1)            set_op( ASSIGN,     d,     s1,   NULL   )
  40.  38 #define invert(d,s1)            set_op( INVERT,     d,     s1,   NULL   )
  41.  39 #define clear(d)                set_op( CLEAR,      d,   NULL,   NULL   )
  42.  40 #define fill(d)                 set_op( FILL,       d,   NULL,   NULL   )
  43.  41 #define complement(d)           ( (d)->compl = ~(d)->compl)
  44.  42 
  45.  43 #define equivalent(s1,s2)       ( set_cmp(s1,s2) == 0 )
  46.  44 #define disjoint(s1,s2)         ( set_cmp(s1,s2) == 1 )
  47.  45 
  48.  46 #define GBIT(x,s,op)  ( ((s)->map)[(x) >> 3]  op  (1 << ((x) & 0x07))    )
  49.  47 
  50.  48 #define remove(x,s)   ( ((x) >= (s)->nbits) ? 0           : GBIT(x,s,&= ~) )
  51.  49 #define add(x,s)      ( ((x) >= (s)->nbits) ? addset(x,s) : GBIT(x,s,|=  ) )
  52.  50 #define ismember(x,s) ( ((x) >= (s)->nbits) ?  0          : GBIT(x,s,&   ) )
  53.  51 
  54.  52 #define test(x,s)     ( ( ismember(x,s) ) ?  !( (s)->compl ) : (s)->compl  )
  55.  
  56.                         Listing 2 -- set.c
  57.  ------------------------------------------------------------------------------
  58.   1 #include  <stdio.h>
  59.   2 #include  <ctype.h>
  60.   3 #include  <set.h>
  61.   4 
  62.   5 extern  char    *calloc ( int, int );
  63.   6 
  64.   7 /*----------------------------------------------------------------------*/
  65.   8 
  66.   9 #ifdef DIAG
  67.  10 #       define D(x) x
  68.  11 #else
  69.  12 #       define D(x)
  70.  13 #endif
  71.  14 
  72.  15 #define max(a,b)        ((a) > (b) ? (a) : (b))
  73.  16 
  74.  17 /*----------------------------------------------------------------------*/
  75.  18 
  76.  19 SET     *newset()
  77.  20 {
  78.  21         SET     *p;
  79.  22 
  80.  23         if( !(p=(SET *) calloc(sizeof(SET),1)) )
  81.  24         {
  82.  25                 fprintf(stderr,"Can't get memory for set\n");
  83.  26                 return NULL;
  84.  27         }
  85.  28         else
  86.  29         {
  87.  30                 p->map    = p->defmap;
  88.  31                 p->nbytes = DEFBYTES;
  89.  32                 p->nbits  = DEFBITS;
  90.  33         }
  91.  34         return p;
  92.  35 }
  93.  36 
  94.  37 /*----------------------------------------------------------------------*/
  95.  38 
  96.  39 void    delset( set )
  97.  40 SET     *set;
  98.  41 {
  99.  42         /* Delete a set created with a previous newset
  100.  43         */
  101.  44 
  102.  45         if( set->map != set->defmap )
  103.  46                 free( set->map );
  104.  47 
  105.  48         free( set );
  106.  49 }
  107.  50 
  108.  51 /*----------------------------------------------------------------------*/
  109.  52 
  110.  53 static  void    enlarge( need, set )
  111.  54 SET     *set;
  112.  55 {
  113.  56         /*      Enlarge the set to "need" bytes, filling in the extra
  114.  57          *      bytes with zeros.
  115.  58          */
  116.  59 
  117.  60         register char   *new;
  118.  61 
  119.  62         if( !set  ||  need <= set->nbytes )
  120.  63                 return;
  121.  64 
  122.  65         D( printf("enlarging %d byte map to %d bytes\n", set->nbytes,need);)
  123.  66 
  124.  67         if( !(new = calloc(need, 1)) )
  125.  68                 fprintf(stderr,"Can't get memory to expand set\n");
  126.  69         else
  127.  70         {
  128.  71                 memcpy( new, set->map, set->nbytes ); 
  129.  72 
  130.  73                 if( set->map != set->defmap )
  131.  74                         free( set->map );
  132.  75 
  133.  76                 set->map    = new;
  134.  77                 set->nbytes = need;
  135.  78                 set->nbits  = need * 8;
  136.  79         }
  137.  80 }
  138.  81 
  139.  82 /* ------------------------------------------------------------------- */
  140.  83 
  141.  84 int     addset( bit, set )
  142.  85 SET     *set;
  143.  86 {
  144.  87         /*      Addset is called by the add() macro when the set isn't
  145.  88          *      big enough. It expands the set to the necessary size
  146.  89          *      and sets the indicated bit.
  147.  90          */
  148.  91  
  149.  92         enlarge( (bit >> 3) + 1, set );
  150.  93         GBIT   (  bit, set, |= );
  151.  94 }
  152.  95 
  153.  96 /* ------------------------------------------------------------------- */
  154.  97 
  155.  98 int     num_ele( set )
  156.  99 SET     *set;
  157. 100 {
  158. 101         /*      Return the number of elements (set bits) in the set.
  159. 102          *      This routine depends on zero fill when an
  160. 103          *      unsigned quantity is shifted to the right.
  161. 104          */
  162. 105 
  163. 106         register unsigned j;
  164. 107         register unsigned count = 0;
  165. 108         unsigned char     *p;
  166. 109         int               i;
  167. 110 
  168. 111         p = set->map;
  169. 112         for( i = set->nbytes; --i >= 0 ; p++)
  170. 113                 for( j = *p;  j  ;  j >>= 1 )
  171. 114                         count += j & 0x1;
  172. 115 
  173. 116         return count;
  174. 117 }
  175. 118 
  176. 119 /* ------------------------------------------------------------------- */
  177. 120 
  178. 121 set_cmp( set1, set2 )
  179. 122 SET     *set1, *set2;
  180. 123 {
  181. 124         /* Compares two sets. Returns zero if they're equivalent, one if
  182. 125          * they're disjoint, 2 if they intersect but aren't equivalent,
  183. 126          * -1 is returned if the two sets are different sizes.
  184. 127          */
  185. 128 
  186. 129         register char   *p1, *p2;
  187. 130         register int    i, disj = 0 ;
  188. 131 
  189. 132         i = max( set1->nbytes, set2->nbytes);
  190. 133 
  191. 134         enlarge( i, set1 );             /* Make the sets the same size  */
  192. 135         enlarge( i, set2 );
  193. 136 
  194. 137         p1 = set1->map;
  195. 138         p2 = set2->map;
  196. 139 
  197. 140         for(; --i >= 0; p1++, p2++ )
  198. 141         {
  199. 142                 if( *p1 != *p2 )
  200. 143                 {
  201. 144                         if( *p1 ^ ~*p2 )
  202. 145                                 return 2;
  203. 146                         else
  204. 147                                 disj = 1;
  205. 148                 }
  206. 149         }
  207. 150 
  208. 151         return disj;            /* They're equivalent   */
  209. 152 }
  210. 153 
  211. 154 /* ------------------------------------------------------------------- */
  212. 155 
  213. 156 int     subset( a, b )
  214. 157 SET     *a, *b;
  215. 158 {
  216. 159         /*      Return 1 if A is a subset of B. Set A must be either smaller
  217. 160          *      than or the same size as B. 0 is returned if A is not a
  218. 161          *      subset or if A is larger than B.
  219. 162          */
  220. 163 
  221. 164         register int    i;
  222. 165         register char   *ap, *bp;
  223. 166 
  224. 167         if( (i = a->nbytes) > b->nbytes )
  225. 168                 return 0;
  226. 169 
  227. 170         ap = a->map;
  228. 171         bp = b->map;
  229. 172 
  230. 173         for(; --i >= 0; ap++, bp++ )
  231. 174                 if( (*ap & *bp) != *ap )
  232. 175                         return 0;
  233. 176         return 1;
  234. 177 }
  235. 178 
  236. 179 /* ------------------------------------------------------------------- */
  237. 180 
  238. 181 void    set_op( op, dest, set1, set2 )
  239. 182 int     op;
  240. 183 SET     *set1, *set2, *dest;
  241. 184 {
  242. 185         /*      Performs either the union or intersection of two sets
  243. 186          *      (depending on the value of "union"). Dest is the result.
  244. 187          *      The two source sets (set1 and set2) must be different,
  245. 188          *      however either of the sources may be used as a destination
  246. 189          *      if you like. If the sets are different sizes, the smaller
  247. 190          *      set is made larger. Unused arguments should be set to NULL.
  248. 191          */
  249. 192 
  250. 193         register char   *d;             /* Pointer to destiniation map  */
  251. 194         register char   *m1;            /* Pointer to map in set1       */
  252. 195         register char   *m2;            /* Pointer to map in set2       */
  253. 196         register int    i;              /* Number of bytes in map       */
  254. 197 
  255. 198 
  256. 199         i = dest->nbytes;
  257. 200         if( set1 )
  258. 201                 i = max( i, set1->nbytes );
  259. 202         if( set2 )
  260. 203                 i = max( i, set2->nbytes );
  261. 204 
  262. 205         enlarge( i, set1 );     /* Make all three sets the same size    */
  263. 206         enlarge( i, set2 );     /* if necessary. Enlarge() does nothing */
  264. 207         enlarge( i, dest );     /* if they're already the correct size. */
  265. 208 
  266. 209         d  = dest->map;
  267. 210         m1 = set1->map;
  268. 211         m2 = set2->map;
  269. 212 
  270. 213         while( --i >= 0 )
  271. 214         {
  272. 215                 D( printf("set_op: working on bit %d\n", i ); )
  273. 216 
  274. 217                 switch( op )
  275. 218                 {
  276. 219                 case UNION:       *d++ =  *m1++ | *m2++         ; break;
  277. 220                 case INTERSECT:   *d++ =  *m1++ & *m2++         ; break;
  278. 221                 case DIFFERENCE:  *d++ =  *m1++ ^ *m2++         ; break;
  279. 222                 case ASSIGN:      *d++ =  *m1++                 ; break;
  280. 223                 case INVERT:      *d++ =  ~*m1++                ; break;
  281. 224                 case CLEAR:       *d++ =  0                     ; break;
  282. 225                 case FILL:        *d++ = ~0                     ; break;
  283. 226                 }
  284. 227         }
  285. 228 }
  286. 229 
  287. 230 /* ------------------------------------------------------------------- */
  288. 231 #ifdef DEBUG
  289. 232 
  290. 233 pset( str, set )
  291. 234 char    *str;
  292. 235 SET     *set;
  293. 236 {
  294. 237         int     i;
  295. 238 
  296. 239         printf("+------------------------------------------------------\n");
  297. 240         printf("| %s\n", str );
  298. 241         printf("| Set at 0x%04x: %d bits, %d bytes, map (0x%04x) ",
  299. 242                                 set, set->nbits, set->nbytes, set->map);
  300. 243 
  301. 244         printf("%s TRUE\n", set->compl ? "NEGATIVE" : "POSITIVE" );
  302. 245         printf("| map = ");
  303. 246 
  304. 247         for( i = 0; i < set->nbytes; i++ ) 
  305. 248                 printf("0x%02x,", (set->map)[i] );
  306. 249 
  307. 250         printf("\n| bits= ");
  308. 251 
  309. 252         for( i = 0; i < set->nbits; i++ )
  310. 253                 printf( test(i, set) ? "%d," : "" ,  i );
  311. 254 
  312. 255         printf("\n| %d elements\n", num_ele(set) );
  313. 256 
  314. 257         printf("+------------------------------------------------------\n");
  315. 258 }
  316. 259 
  317. 260 /* ------------------------------------------------------------------- */
  318. 261 
  319. 262 test_stuff( a, b, d )
  320. 263 SET *a, *b, *d;
  321. 264 {
  322. 265         pset("set a", a );
  323. 266         pset("set b", b );
  324. 267 
  325. 268         union        (d,a,b);   pset("a union b",       d );
  326. 269         intersection (d,a,b);   pset("a intersect b",   d );
  327. 270         difference   (d,a,b);   pset("a difference b",  d );
  328. 271         assign       (d,a);     pset("d assign a",      d );
  329. 272         complement   (d);       pset("complement a",    d );
  330. 273         complement   (d);
  331. 274         invert       (d,a);     pset("invert a",        d );
  332. 275 
  333. 276         printf("a %s equivalent to b\n", equivalent(a,b) ? "IS" : "ISN'T" );
  334. 277         printf("a %s disjoint from b\n", disjoint(a,b)   ? "IS" : "ISN'T" );
  335. 278         printf("b %s a subset of a\n",   subset(b, a)    ? "IS" : "ISN'T" );
  336. 279         printf("a %s a subset of b\n",   subset(a, b)    ? "IS" : "ISN'T" );
  337. 280 
  338. 281         printf("-------------------------------------------------------\n");
  339. 282 }
  340. 283 
  341. 284 /* ------------------------------------------------------------------- */
  342. 285 
  343. 286 main()
  344. 287 {
  345. 288         SET     *a, *b, *d;
  346. 289         char    buf[80], *p;
  347. 290         int     num;
  348. 291 
  349. 292         a = newset();  pset( "initial a", a );
  350. 293         b = newset();  pset( "initial b", b );
  351. 294         d = newset();  pset( "initial d", d );
  352. 295 
  353. 296         add(0,a);
  354. 297         add(1,a);
  355. 298         add(3,a);
  356. 299         add(0,b);
  357. 300         add(3,b);
  358. 301 
  359. 302         test_stuff( a, b, d );
  360. 303 
  361. 304         remove(0,a); remove(1,a); remove(3,a); remove(0,b); remove(3,b);
  362. 305         add(0, a); add(2, a); add(2, b); add(3, b);
  363. 306 
  364. 307         test_stuff( a, b, d );
  365. 308 
  366. 309         clear( a ); clear( b ); test_stuff( a, b, d );
  367. 310         clear( a ); fill ( b ); test_stuff( a, b, d );
  368. 311 
  369. 312         delset( b );
  370. 313         delset( d );
  371. 314         delset( a );
  372. 315         a = newset();
  373. 316 
  374. 317         printf("enter <bitnum><s|c>:");
  375. 318 
  376. 319         while( gets(buf) )
  377. 320         {
  378. 321                 num = atoi(buf);
  379. 322                 for( p = buf; isdigit(*p) ; p++ )
  380. 323                         ;
  381. 324 
  382. 325                 if( *p == 's' )
  383. 326                         add(num ,a);
  384. 327                 else
  385. 328                         remove(num, a);
  386. 329 
  387. 330                 pset( "", a );
  388. 331                 printf("enter <bitnum><s|c>:");
  389. 332         }
  390. 333 }
  391. 334 
  392. 335 #endif
  393.                                 [EOF]
  394.