1 /*****************************************************************************
2 /
3 / SPACE (SPArse Cholesky Elimination) Library: bucket.c
4 /
5 / author        J"urgen Schulze, University of Paderborn
6 / created       12/06/00
7 /
8 / This file contains functions dealing with buckets.
9 /
10 ******************************************************************************
11 
12 Data type:  struct bucket
13               int maxbin;   maximal bin in bucket
14               int maxitem;  maximal item that can be stored in bucket
15               int offset;   to store items with negative key-value
16               int nobj;     number of items in bucket
17               int minbin;   leftmost non-empty bin
18               int *bin;     there are maxbin+1 bins (bin[0]...bin[maxbin])
19               int *next;    next[item] points to next item in bin
20               int *last;    last[item] points to previous item in bin
21               int *key;     holds key of item (MAX_INT if item not in bucket)
22 Comments:
23   o Any implementation of a bucket should enable insert/remove operations in
24     constant time
25   o There a two special bins:
26     bin[0] contains all items u with key[u] + offset < 0
27     bin[maxbin] contains all items u with key[u] + offset > maxbin
28 Methods in lib/bucket.c:
29 - bucket = newBucket(int maxbin, int maxitem, int offset);
30     o Initial: nobj = 0 and minbin = MAX_INT
31 - void freeBucket(bucket_t *bucket);
32 - bucket = setupBucket(int maxbin, int maxitem, int offset);
33     o allocates memory for the bucket by calling newBucket and initializes
34       the vectors, i.e. bin[i] = -1 for all 0 <= i <= maxbin,
35       next[u] = last[u] = -1, and key[u] = MAX_INT for all 0 <= u <= maxitem
36 - int minBucket(bucket_t *bucket);
37     o returns the item whose key-value is minimal; this item is stored in
38       bin[minbin]; if minbin = 0 or minbin = maxbin, the whole bin must be
39       searched, since the items stored herein may have different keys
40     o if nobj = 0, the function returns -1
41 - void insertBucket(bucket_t *bucket, int k, int item);
42     o insert item with key k in bucket; if key[item] != MAX_INT (i.e. item
43       already in bucket) or if item > maxitem the program terminates
44 - void removeBucket(bucket_t *bucket, int item);
45     o removes item from bucket; if key[item] == MAX_INT (i.e. item not in
46       bucket) the program terminates
47 
48 ******************************************************************************/
49 
50 #include <space.h>
51 
52 
53 /******************************************************************************
54 ******************************************************************************/
55 bucket_t*
newBucket(PORD_INT maxbin,PORD_INT maxitem,PORD_INT offset)56 newBucket(PORD_INT maxbin, PORD_INT maxitem, PORD_INT offset)
57 { bucket_t *bucket;
58 
59   mymalloc(bucket, 1, bucket_t);
60   mymalloc(bucket->bin, (maxbin+1), PORD_INT);
61   mymalloc(bucket->next, (maxitem+1), PORD_INT);
62   mymalloc(bucket->last, (maxitem+1), PORD_INT);
63   mymalloc(bucket->key, (maxitem+1), PORD_INT);
64 
65   bucket->maxbin = maxbin;
66   bucket->maxitem = maxitem;
67   bucket->offset = offset;
68   bucket->nobj = 0;
69   bucket->minbin = MAX_INT;
70 
71   return(bucket);
72 }
73 
74 
75 /******************************************************************************
76 ******************************************************************************/
77 void
freeBucket(bucket_t * bucket)78 freeBucket(bucket_t *bucket)
79 {
80   free(bucket->bin);
81   free(bucket->next);
82   free(bucket->last);
83   free(bucket->key);
84   free(bucket);
85 }
86 
87 
88 /******************************************************************************
89 ******************************************************************************/
90 bucket_t*
setupBucket(PORD_INT maxbin,PORD_INT maxitem,PORD_INT offset)91 setupBucket(PORD_INT maxbin, PORD_INT maxitem, PORD_INT offset)
92 { bucket_t *bucket;
93   PORD_INT      i, u;
94 
95   if (offset < 0)
96    { fprintf(stderr, "\nError in function setupBucket\n"
97           "  offset must be >= 0\n");
98      quit();
99    }
100 
101   bucket = newBucket(maxbin, maxitem, offset);
102 
103   for (i = 0; i <= maxbin; i++)
104     bucket->bin[i] = -1;
105   for (u = 0; u <= maxitem; u++)
106     { bucket->next[u] = bucket->last[u] = -1;
107       bucket->key[u] = MAX_INT;
108     }
109 
110   return(bucket);
111 }
112 
113 
114 /******************************************************************************
115 ******************************************************************************/
116 PORD_INT
minBucket(bucket_t * bucket)117 minBucket(bucket_t *bucket)
118 { PORD_INT *bin, *next, *key, maxbin, minbin, nobj;
119   PORD_INT item, bestitem, bestkey;
120 
121   maxbin = bucket->maxbin;
122   nobj = bucket->nobj;
123   minbin = bucket->minbin;
124   bin = bucket->bin;
125   next = bucket->next;
126   key = bucket->key;
127 
128   if (nobj > 0)
129    { /* ---------------------------------------------
130         get the first item from leftmost nonempty bin
131         --------------------------------------------- */
132      while (bin[minbin] == -1) minbin++;
133      bucket->minbin = minbin;
134      bestitem = bin[minbin];
135      bestkey = minbin;
136 
137      /* --------------------------------------------------
138         items in bins 0 and maxbin can have different keys
139         => search for item with smallest key
140         -------------------------------------------------- */
141      if ((minbin == 0) || (minbin == maxbin))
142       { item = next[bestitem];
143         while (item != -1)
144          { if (key[item] < bestkey)
145             { bestitem = item;
146               bestkey = key[item];
147             }
148            item = next[item];
149          }
150       }
151      /* ---------------------------------
152         return the item with smallest key
153         --------------------------------- */
154      return(bestitem);
155    }
156   else return(-1);
157 }
158 
159 
160 /******************************************************************************
161 ******************************************************************************/
162 void
insertBucket(bucket_t * bucket,PORD_INT k,PORD_INT item)163 insertBucket(bucket_t *bucket, PORD_INT k, PORD_INT item)
164 { PORD_INT s, nextitem;
165 
166   /* ------------------------------------
167      check whether there are any problems
168      ------------------------------------ */
169   if (abs(k) >= MAX_INT - bucket->offset - 1)
170    { fprintf(stderr, "\nError in function insertBucket\n"
171           "  key %d too large/small for bucket\n", k);
172      quit();
173    }
174   if (item > bucket->maxitem)
175    { fprintf(stderr, "\nError in function insertBucket\n"
176           "  item %d too large for bucket (maxitem is %d)\n", item,
177           bucket->maxitem);
178      quit();
179    }
180   if (bucket->key[item] != MAX_INT)
181    { fprintf(stderr, "\nError in function insertBucket\n"
182           "  item %d already in bucket\n", item);
183      quit();
184    }
185 
186   /* -------------------------------------
187      determine the bin that holds the item
188      ------------------------------------- */
189   s = max(0, (k + bucket->offset));
190   s = min(s, bucket->maxbin);
191 
192   /* --------------------------------------------------------------
193      adjust minbin, increase nobj, and mark item as being in bucket
194      -------------------------------------------------------------- */
195   bucket->minbin = min(bucket->minbin, s);
196   bucket->nobj++;
197   bucket->key[item] = k;
198 
199   /* -----------------------------
200      finally, insert item in bin s
201      ----------------------------- */
202   nextitem = bucket->bin[s];
203   if (nextitem != -1)
204     bucket->last[nextitem] = item;
205   bucket->next[item] = nextitem;
206   bucket->last[item] = -1;
207   bucket->bin[s] = item;
208 }
209 
210 
211 /******************************************************************************
212 ******************************************************************************/
213 void
removeBucket(bucket_t * bucket,PORD_INT item)214 removeBucket(bucket_t *bucket, PORD_INT item)
215 { PORD_INT s, nextitem, lastitem;
216 
217   /* ----------------------------
218      check whether item in bucket
219      ---------------------------- */
220   if (bucket->key[item] == MAX_INT)
221    { fprintf(stderr, "\nError in function removeBucket\n"
222           "  item %d is not in bucket\n", item);
223      quit();
224    }
225 
226   /* -----------------------
227      remove item from bucket
228      ----------------------- */
229   nextitem = bucket->next[item];
230   lastitem = bucket->last[item];
231   if (nextitem != -1)
232     bucket->last[nextitem] = lastitem;
233   if (lastitem != -1)
234     bucket->next[lastitem] = nextitem;
235   else
236    { s = max(0, (bucket->key[item] + bucket->offset));
237      s = min(s, bucket->maxbin);
238      bucket->bin[s] = nextitem;
239    }
240 
241   /* --------------------------------------------
242      decrease nobj and mark item as being removed
243      -------------------------------------------- */
244   bucket->nobj--;
245   bucket->key[item] = MAX_INT;
246 }
247