Routino SVN Repository Browser

Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino

ViewVC logotype

Contents of /trunk/src/results.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 92 - (show annotations) (download) (as text)
Fri Jan 30 19:57:09 2009 UTC (16 years, 1 month ago) by amb
File MIME type: text/x-csrc
File size: 11096 byte(s)
Remove gcc warning.

1 /***************************************
2 $Header: /home/amb/CVS/routino/src/results.c,v 1.6 2009-01-30 19:57:09 amb Exp $
3
4 Result data type functions.
5 ******************/ /******************
6 Written by Andrew M. Bishop
7
8 This file Copyright 2008,2009 Andrew M. Bishop
9 It may be distributed under the GNU Public License, version 2, or
10 any higher version. See section COPYING of the GNU Public license
11 for conditions under which this file may be redistributed.
12 ***************************************/
13
14
15 #include <assert.h>
16 #include <string.h>
17 #include <stdlib.h>
18
19 #include "results.h"
20
21
22 #define RESULTS_INCREMENT 16
23 #define QUEUE_INCREMENT 1024
24
25
26 /*+ A queue of results. +*/
27 typedef struct _Queue
28 {
29 uint32_t alloced; /*+ The amount of space allocated for results in the array. +*/
30 uint32_t number; /*+ The number of occupied results in the array. +*/
31 Result **xqueue; /*+ An array of pointers to parts of the results structure. +*/
32 }
33 Queue;
34
35 /*+ The queue of nodes. +*/
36 static Queue queue={0,0,NULL};
37
38
39 /*++++++++++++++++++++++++++++++++++++++
40 Allocate a new results list.
41
42 Results *NewResultsList Returns the results list.
43
44 int nbins The number of bins in the results array.
45 ++++++++++++++++++++++++++++++++++++++*/
46
47 Results *NewResultsList(int nbins)
48 {
49 Results *results;
50 int i;
51
52 results=(Results*)malloc(sizeof(Results));
53
54 results->nbins=1;
55 results->mask=~0;
56
57 while(nbins>>=1)
58 {
59 results->mask<<=1;
60 results->nbins<<=1;
61 }
62
63 results->mask=~results->mask;
64
65 results->alloced=RESULTS_INCREMENT;
66 results->number=0;
67
68 results->count=(uint32_t*)malloc(results->nbins*sizeof(uint32_t));
69 results->point=(Result***)malloc(results->nbins*sizeof(Result**));
70
71 for(i=0;i<results->nbins;i++)
72 {
73 results->count[i]=0;
74
75 results->point[i]=(Result**)malloc(results->alloced*sizeof(Result*));
76 }
77
78 results->data=(Result**)malloc(1*sizeof(Result*));
79 results->data[0]=(Result*)malloc(results->nbins*RESULTS_INCREMENT*sizeof(Result));
80
81 return(results);
82 }
83
84
85 /*++++++++++++++++++++++++++++++++++++++
86 Allocate a new results list.
87
88 Results *results The results list to be destroyed.
89 ++++++++++++++++++++++++++++++++++++++*/
90
91 void FreeResultsList(Results *results)
92 {
93 int c=(results->number-1)/(results->nbins*RESULTS_INCREMENT);
94 int i;
95
96 for(i=c;i>=0;i--)
97 free(results->data[i]);
98
99 free(results->data);
100
101 for(i=0;i<results->nbins;i++)
102 free(results->point[i]);
103
104 free(results->point);
105
106 free(results->count);
107
108 free(results);
109 }
110
111
112 /*++++++++++++++++++++++++++++++++++++++
113 Insert a new result into the results data structure in the right order.
114
115 Result *insert_result Returns the result that has been inserted.
116
117 Results *results The results structure to insert into.
118
119 node_t node The node that is to be inserted into the results.
120 ++++++++++++++++++++++++++++++++++++++*/
121
122 Result *InsertResult(Results *results,node_t node)
123 {
124 int bin=node&results->mask;
125 int start=0;
126 int end=results->count[bin]-1;
127 int i;
128 int mid;
129 int insert=-1;
130
131 /* Check that the arrays have enough space. */
132
133 if(results->count[bin]==results->alloced)
134 {
135 results->alloced+=RESULTS_INCREMENT;
136
137 for(i=0;i<results->nbins;i++)
138 results->point[i]=(Result**)realloc((void*)results->point[i],results->alloced*sizeof(Result*));
139 }
140
141 if(results->number && (results->number%RESULTS_INCREMENT)==0 && (results->number%(RESULTS_INCREMENT*results->nbins))==0)
142 {
143 int c=results->number/(results->nbins*RESULTS_INCREMENT);
144
145 results->data=(Result**)realloc((void*)results->data,(c+1)*sizeof(Result*));
146 results->data[c]=(Result*)malloc(results->nbins*RESULTS_INCREMENT*sizeof(Result));
147 }
148
149 /* Binary search - search key may not match, if not then insertion point required
150 *
151 * # <- start | Check mid and move start or end if it doesn't match
152 * # |
153 * # | Since there may not be an exact match we must set end=mid
154 * # <- mid | or start=mid because we know that mid doesn't match.
155 * # |
156 * # | Eventually end=start+1 and the insertion point is before
157 * # <- end | end (since it cannot be before the initial start or end).
158 */
159
160 if(end<start) /* There are no results */
161 insert=start;
162 else if(node<results->point[bin][start]->node) /* Check key is not before start */
163 insert=start;
164 else if(node>results->point[bin][end]->node) /* Check key is not after end */
165 insert=end+1;
166 else
167 {
168 do
169 {
170 mid=(start+end)/2; /* Choose mid point */
171
172 if(results->point[bin][mid]->node<node) /* Mid point is too low */
173 start=mid;
174 else if(results->point[bin][mid]->node>node) /* Mid point is too high */
175 end=mid;
176 else
177 assert(0);
178 }
179 while((end-start)>1);
180
181 insert=end;
182 }
183
184 /* Shuffle the array up */
185
186 if(insert!=results->count[bin])
187 memmove(&results->point[bin][insert+1],&results->point[bin][insert],(results->count[bin]-insert)*sizeof(Result*));
188
189 /* Insert the new entry */
190
191 results->point[bin][insert]=&results->data[results->number/(results->nbins*RESULTS_INCREMENT)][results->number%(results->nbins*RESULTS_INCREMENT)];
192
193 results->number++;
194
195 results->count[bin]++;
196
197 return(results->point[bin][insert]);
198 }
199
200
201 /*++++++++++++++++++++++++++++++++++++++
202 Find a result, ordered by node.
203
204 Result *insert_result Returns the result that has been found.
205
206 Results *results The results structure to search.
207
208 node_t node The node that is to be found.
209 ++++++++++++++++++++++++++++++++++++++*/
210
211 Result *FindResult(Results *results,node_t node)
212 {
213 int bin=node&results->mask;
214 int start=0;
215 int end=results->count[bin]-1;
216 int mid;
217
218 /* Binary search - search key exact match only is required.
219 *
220 * # <- start | Check mid and move start or end if it doesn't match
221 * # |
222 * # | Since an exact match is wanted we can set end=mid-1
223 * # <- mid | or start=mid+1 because we know that mid doesn't match.
224 * # |
225 * # | Eventually either end=start or end=start+1 and one of
226 * # <- end | start or end is the wanted one.
227 */
228
229 if(end<start) /* There are no results */
230 return(NULL);
231 else if(node<results->point[bin][start]->node) /* Check key is not before start */
232 return(NULL);
233 else if(node>results->point[bin][end]->node) /* Check key is not after end */
234 return(NULL);
235 else
236 {
237 do
238 {
239 mid=(start+end)/2; /* Choose mid point */
240
241 if(results->point[bin][mid]->node<node) /* Mid point is too low */
242 start=mid+1;
243 else if(results->point[bin][mid]->node>node) /* Mid point is too high */
244 end=mid-1;
245 else /* Mid point is correct */
246 return(results->point[bin][mid]);
247 }
248 while((end-start)>1);
249
250 if(results->point[bin][start]->node==node) /* Start is correct */
251 return(results->point[bin][start]);
252
253 if(results->point[bin][end]->node==node) /* End is correct */
254 return(results->point[bin][end]);
255 }
256
257 return(NULL);
258 }
259
260
261 /*++++++++++++++++++++++++++++++++++++++
262 Find a result from a set of results.
263
264 Result *FirstResult Returns the first results from a set of results.
265
266 Results *results The set of results.
267 ++++++++++++++++++++++++++++++++++++++*/
268
269 Result *FirstResult(Results *results)
270 {
271 return(&results->data[0][0]);
272 }
273
274
275 /*++++++++++++++++++++++++++++++++++++++
276 Find a result from a set of results.
277
278 Result *NextResult Returns the next result from a set of results.
279
280 Results *results The set of results.
281
282 Result *result The previous result.
283 ++++++++++++++++++++++++++++++++++++++*/
284
285 Result *NextResult(Results *results,Result *result)
286 {
287 int c=(results->number-1)/(results->nbins*RESULTS_INCREMENT);
288 int i,j=0;
289
290 for(i=0;i<=c;i++)
291 {
292 j=(result-results->data[i]);
293
294 if(j>=0 && j<(results->nbins*RESULTS_INCREMENT))
295 break;
296 }
297
298 if(++j>=(results->nbins*RESULTS_INCREMENT))
299 {i++;j=0;}
300
301 if((i*(results->nbins*RESULTS_INCREMENT)+j)>=results->number)
302 return(NULL);
303
304 return(&results->data[i][j]);
305 }
306
307
308 /*++++++++++++++++++++++++++++++++++++++
309 Insert an item into the queue in the right order.
310
311 Result *result The result to insert into the queue.
312 ++++++++++++++++++++++++++++++++++++++*/
313
314 void insert_in_queue(Result *result)
315 {
316 int start=0;
317 int end=queue.number-1;
318 int mid;
319 int insert=-1;
320
321 /* Check that the array is allocated. */
322
323 if(!queue.xqueue)
324 {
325 queue.alloced=QUEUE_INCREMENT;
326 queue.number=0;
327 queue.xqueue=(Result**)malloc(queue.alloced*sizeof(Result*));
328 }
329
330 /* Check that the arrays have enough space. */
331
332 if(queue.number==queue.alloced)
333 {
334 queue.alloced+=QUEUE_INCREMENT;
335 queue.xqueue=(Result**)realloc((void*)queue.xqueue,queue.alloced*sizeof(Result*));
336 }
337
338 /* Binary search - search key may not match, new insertion point required
339 *
340 * # <- start | Check mid and move start or end if it doesn't match
341 * # |
342 * # | Since there may not be an exact match we must set end=mid
343 * # <- mid | or start=mid because we know that mid doesn't match.
344 * # |
345 * # | Eventually end=start+1 and the insertion point is before
346 * # <- end | end (since it cannot be before the initial start or end).
347 */
348
349 if(queue.number==0) /* There is nothing in the queue */
350 insert=0;
351 else if(result->shortest.distance>queue.xqueue[start]->shortest.distance) /* Check key is not before start */
352 insert=start;
353 else if(result->shortest.distance<queue.xqueue[end]->shortest.distance) /* Check key is not after end */
354 insert=end+1;
355 else
356 {
357 do
358 {
359 mid=(start+end)/2; /* Choose mid point */
360
361 if(queue.xqueue[mid]->shortest.distance>result->shortest.distance) /* Mid point is too low */
362 start=mid;
363 else if(queue.xqueue[mid]->shortest.distance<result->shortest.distance) /* Mid point is too high */
364 end=mid;
365 else /* Mid point is correct */
366 {
367 if(queue.xqueue[mid]==result)
368 return;
369
370 insert=mid;
371 break;
372 }
373 }
374 while((end-start)>1);
375
376 if(insert==-1)
377 insert=end;
378 }
379
380 /* Shuffle the array up */
381
382 if(insert!=queue.number)
383 memmove(&queue.xqueue[insert+1],&queue.xqueue[insert],(queue.number-insert)*sizeof(Result*));
384
385 /* Insert the new entry */
386
387 queue.xqueue[insert]=result;
388
389 queue.number++;
390 }
391
392
393 /*++++++++++++++++++++++++++++++++++++++
394 Pop an item from the end of the queue.
395
396 Result *pop_from_queue Returns the top item.
397
398 Results *results The set of results that the queue is processing.
399 ++++++++++++++++++++++++++++++++++++++*/
400
401 Result *pop_from_queue()
402 {
403 if(queue.number)
404 return(queue.xqueue[--queue.number]);
405 else
406 return(NULL);
407 }

Properties

Name Value
cvs:description Results data type.