Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino
Contents of /trunk/src/results.c
Parent Directory
|
Revision Log
Revision 228 -
(show annotations)
(download)
(as text)
Sun Jul 12 09:01:48 2009 UTC (15 years, 8 months ago) by amb
File MIME type: text/x-csrc
File size: 9254 byte(s)
Sun Jul 12 09:01:48 2009 UTC (15 years, 8 months ago) by amb
File MIME type: text/x-csrc
File size: 9254 byte(s)
Tidy up and fix comments and include files.
1 | /*************************************** |
2 | $Header: /home/amb/CVS/routino/src/results.c,v 1.17 2009-07-12 09:01:48 amb Exp $ |
3 | |
4 | Result data type functions. |
5 | |
6 | Part of the Routino routing software. |
7 | ******************/ /****************** |
8 | This file Copyright 2008,2009 Andrew M. Bishop |
9 | |
10 | This program is free software: you can redistribute it and/or modify |
11 | it under the terms of the GNU Affero General Public License as published by |
12 | the Free Software Foundation, either version 3 of the License, or |
13 | (at your option) any later version. |
14 | |
15 | This program is distributed in the hope that it will be useful, |
16 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
18 | GNU Affero General Public License for more details. |
19 | |
20 | You should have received a copy of the GNU Affero General Public License |
21 | along with this program. If not, see <http://www.gnu.org/licenses/>. |
22 | ***************************************/ |
23 | |
24 | |
25 | #include <sys/types.h> |
26 | #include <string.h> |
27 | #include <stdlib.h> |
28 | |
29 | #include "results.h" |
30 | |
31 | /*+ The size of the increment for the Results data structure. +*/ |
32 | #define RESULTS_INCREMENT 16 |
33 | |
34 | /*+ The size of the increment for the Queue data structure. +*/ |
35 | #define QUEUE_INCREMENT 10240 |
36 | |
37 | |
38 | /*+ A queue of results. +*/ |
39 | typedef struct _Queue |
40 | { |
41 | uint32_t alloced; /*+ The amount of space allocated for results in the array. +*/ |
42 | uint32_t number; /*+ The number of occupied results in the array. +*/ |
43 | Result **xqueue; /*+ An array of pointers to parts of the results structure. +*/ |
44 | } |
45 | Queue; |
46 | |
47 | /*+ The queue of nodes. +*/ |
48 | static Queue queue={0,0,NULL}; |
49 | |
50 | |
51 | /*++++++++++++++++++++++++++++++++++++++ |
52 | Allocate a new results list. |
53 | |
54 | Results *NewResultsList Returns the results list. |
55 | |
56 | int nbins The number of bins in the results array. |
57 | ++++++++++++++++++++++++++++++++++++++*/ |
58 | |
59 | Results *NewResultsList(int nbins) |
60 | { |
61 | Results *results; |
62 | uint32_t i; |
63 | |
64 | results=(Results*)malloc(sizeof(Results)); |
65 | |
66 | results->nbins=1; |
67 | results->mask=~0; |
68 | |
69 | while(nbins>>=1) |
70 | { |
71 | results->mask<<=1; |
72 | results->nbins<<=1; |
73 | } |
74 | |
75 | results->mask=~results->mask; |
76 | |
77 | results->alloced=RESULTS_INCREMENT; |
78 | results->number=0; |
79 | |
80 | results->count=(uint32_t*)malloc(results->nbins*sizeof(uint32_t)); |
81 | results->point=(Result***)malloc(results->nbins*sizeof(Result**)); |
82 | |
83 | for(i=0;i<results->nbins;i++) |
84 | { |
85 | results->count[i]=0; |
86 | |
87 | results->point[i]=(Result**)malloc(results->alloced*sizeof(Result*)); |
88 | } |
89 | |
90 | results->data=(Result**)malloc(1*sizeof(Result*)); |
91 | results->data[0]=(Result*)malloc(results->nbins*RESULTS_INCREMENT*sizeof(Result)); |
92 | |
93 | results->start=NO_NODE; |
94 | results->finish=NO_NODE; |
95 | |
96 | return(results); |
97 | } |
98 | |
99 | |
100 | /*++++++++++++++++++++++++++++++++++++++ |
101 | Allocate a new results list. |
102 | |
103 | Results *results The results list to be destroyed. |
104 | ++++++++++++++++++++++++++++++++++++++*/ |
105 | |
106 | void FreeResultsList(Results *results) |
107 | { |
108 | int i,c=(results->number-1)/(results->nbins*RESULTS_INCREMENT); |
109 | |
110 | for(i=c;i>=0;i--) |
111 | free(results->data[i]); |
112 | |
113 | free(results->data); |
114 | |
115 | for(i=0;i<results->nbins;i++) |
116 | free(results->point[i]); |
117 | |
118 | free(results->point); |
119 | |
120 | free(results->count); |
121 | |
122 | free(results); |
123 | } |
124 | |
125 | |
126 | /*++++++++++++++++++++++++++++++++++++++ |
127 | Insert a new result into the results data structure in the right order. |
128 | |
129 | Result *InsertResult Returns the result that has been inserted. |
130 | |
131 | Results *results The results structure to insert into. |
132 | |
133 | index_t node The node that is to be inserted into the results. |
134 | ++++++++++++++++++++++++++++++++++++++*/ |
135 | |
136 | Result *InsertResult(Results *results,index_t node) |
137 | { |
138 | int bin=node&results->mask; |
139 | uint32_t i; |
140 | |
141 | /* Check that the arrays have enough space. */ |
142 | |
143 | if(results->count[bin]==results->alloced) |
144 | { |
145 | results->alloced+=RESULTS_INCREMENT; |
146 | |
147 | for(i=0;i<results->nbins;i++) |
148 | results->point[i]=(Result**)realloc((void*)results->point[i],results->alloced*sizeof(Result*)); |
149 | } |
150 | |
151 | if(results->number && (results->number%RESULTS_INCREMENT)==0 && (results->number%(RESULTS_INCREMENT*results->nbins))==0) |
152 | { |
153 | int c=results->number/(results->nbins*RESULTS_INCREMENT); |
154 | |
155 | results->data=(Result**)realloc((void*)results->data,(c+1)*sizeof(Result*)); |
156 | results->data[c]=(Result*)malloc(results->nbins*RESULTS_INCREMENT*sizeof(Result)); |
157 | } |
158 | |
159 | /* Insert the new entry */ |
160 | |
161 | results->point[bin][results->count[bin]]=&results->data[results->number/(results->nbins*RESULTS_INCREMENT)][results->number%(results->nbins*RESULTS_INCREMENT)]; |
162 | |
163 | results->number++; |
164 | |
165 | results->count[bin]++; |
166 | |
167 | results->point[bin][results->count[bin]-1]->node=node; |
168 | |
169 | return(results->point[bin][results->count[bin]-1]); |
170 | } |
171 | |
172 | |
173 | /*++++++++++++++++++++++++++++++++++++++ |
174 | Zero the values in a result structure. |
175 | |
176 | Result *result The result to modify. |
177 | ++++++++++++++++++++++++++++++++++++++*/ |
178 | |
179 | void ZeroResult(Result *result) |
180 | { |
181 | result->prev=NO_NODE; |
182 | result->next=NO_NODE; |
183 | |
184 | result->score=0; |
185 | result->sortby=0; |
186 | |
187 | result->segment=NULL; |
188 | } |
189 | |
190 | |
191 | /*++++++++++++++++++++++++++++++++++++++ |
192 | Find a result; search by node. |
193 | |
194 | Result *FindResult Returns the result that has been found. |
195 | |
196 | Results *results The results structure to search. |
197 | |
198 | index_t node The node that is to be found. |
199 | ++++++++++++++++++++++++++++++++++++++*/ |
200 | |
201 | Result *FindResult(Results *results,index_t node) |
202 | { |
203 | int bin=node&results->mask; |
204 | int i; |
205 | |
206 | for(i=results->count[bin]-1;i>=0;i--) |
207 | if(results->point[bin][i]->node==node) |
208 | return(results->point[bin][i]); |
209 | |
210 | return(NULL); |
211 | } |
212 | |
213 | |
214 | /*++++++++++++++++++++++++++++++++++++++ |
215 | Find a result from a set of results. |
216 | |
217 | Result *FirstResult Returns the first results from a set of results. |
218 | |
219 | Results *results The set of results. |
220 | ++++++++++++++++++++++++++++++++++++++*/ |
221 | |
222 | Result *FirstResult(Results *results) |
223 | { |
224 | return(&results->data[0][0]); |
225 | } |
226 | |
227 | |
228 | /*++++++++++++++++++++++++++++++++++++++ |
229 | Find a result from a set of results. |
230 | |
231 | Result *NextResult Returns the next result from a set of results. |
232 | |
233 | Results *results The set of results. |
234 | |
235 | Result *result The previous result. |
236 | ++++++++++++++++++++++++++++++++++++++*/ |
237 | |
238 | Result *NextResult(Results *results,Result *result) |
239 | { |
240 | int i,j=0,c=(results->number-1)/(results->nbins*RESULTS_INCREMENT); |
241 | |
242 | for(i=0;i<=c;i++) |
243 | { |
244 | j=result-results->data[i]; |
245 | |
246 | if(j>=0 && j<(results->nbins*RESULTS_INCREMENT)) |
247 | break; |
248 | } |
249 | |
250 | if(++j>=(results->nbins*RESULTS_INCREMENT)) |
251 | {i++;j=0;} |
252 | |
253 | if((i*(results->nbins*RESULTS_INCREMENT)+j)>=results->number) |
254 | return(NULL); |
255 | |
256 | return(&results->data[i][j]); |
257 | } |
258 | |
259 | |
260 | /*++++++++++++++++++++++++++++++++++++++ |
261 | Insert an item into the queue in the right order. |
262 | |
263 | Result *result The result to insert into the queue. |
264 | ++++++++++++++++++++++++++++++++++++++*/ |
265 | |
266 | void insert_in_queue(Result *result) |
267 | { |
268 | int start=0; |
269 | int end=queue.number-1; |
270 | int mid; |
271 | int insert=-1; |
272 | |
273 | /* Check that the array is allocated. */ |
274 | |
275 | if(!queue.xqueue) |
276 | { |
277 | queue.alloced=QUEUE_INCREMENT; |
278 | queue.number=0; |
279 | queue.xqueue=(Result**)malloc(queue.alloced*sizeof(Result*)); |
280 | } |
281 | |
282 | /* Check that the arrays have enough space. */ |
283 | |
284 | if(queue.number==queue.alloced) |
285 | { |
286 | queue.alloced+=QUEUE_INCREMENT; |
287 | queue.xqueue=(Result**)realloc((void*)queue.xqueue,queue.alloced*sizeof(Result*)); |
288 | } |
289 | |
290 | /* Binary search - search key may not match, new insertion point required |
291 | * |
292 | * # <- start | Check mid and move start or end if it doesn't match |
293 | * # | |
294 | * # | Since there may not be an exact match we must set end=mid |
295 | * # <- mid | or start=mid because we know that mid doesn't match. |
296 | * # | |
297 | * # | Eventually end=start+1 and the insertion point is before |
298 | * # <- end | end (since it cannot be before the initial start or end). |
299 | */ |
300 | |
301 | if(queue.number==0) /* There is nothing in the queue */ |
302 | insert=0; |
303 | else if(result->sortby>queue.xqueue[start]->sortby) /* Check key is not before start */ |
304 | insert=start; |
305 | else if(result->sortby<queue.xqueue[end]->sortby) /* Check key is not after end */ |
306 | insert=end+1; |
307 | else if(queue.number==2) /* Must be between them */ |
308 | insert=1; |
309 | else |
310 | { |
311 | do |
312 | { |
313 | mid=(start+end)/2; /* Choose mid point */ |
314 | |
315 | if(queue.xqueue[mid]->sortby>result->sortby) /* Mid point is too low */ |
316 | start=mid; |
317 | else if(queue.xqueue[mid]->sortby<result->sortby) /* Mid point is too high */ |
318 | end=mid; |
319 | else /* Mid point is correct */ |
320 | { |
321 | if(queue.xqueue[mid]==result) |
322 | return; |
323 | |
324 | insert=mid; |
325 | break; |
326 | } |
327 | } |
328 | while((end-start)>1); |
329 | |
330 | if(insert==-1) |
331 | insert=end; |
332 | } |
333 | |
334 | /* Shuffle the array up */ |
335 | |
336 | if(insert!=queue.number) |
337 | memmove(&queue.xqueue[insert+1],&queue.xqueue[insert],(queue.number-insert)*sizeof(Result*)); |
338 | |
339 | /* Insert the new entry */ |
340 | |
341 | queue.xqueue[insert]=result; |
342 | |
343 | queue.number++; |
344 | } |
345 | |
346 | |
347 | /*++++++++++++++++++++++++++++++++++++++ |
348 | Pop an item from the end of the queue. |
349 | |
350 | Result *pop_from_queue Returns the top item. |
351 | |
352 | Results *results The set of results that the queue is processing. |
353 | ++++++++++++++++++++++++++++++++++++++*/ |
354 | |
355 | Result *pop_from_queue() |
356 | { |
357 | if(queue.number) |
358 | return(queue.xqueue[--queue.number]); |
359 | else |
360 | return(NULL); |
361 | } |
Properties
Name | Value |
---|---|
cvs:description | Results data type. |