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