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