Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino
Annotation of /trunk/src/results.c
Parent Directory
|
Revision Log
Revision 213 -
(hide annotations)
(download)
(as text)
Thu Jul 2 16:33:31 2009 UTC (15 years, 9 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, 9 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 | amb | 29 | /*************************************** |
2 | amb | 213 | $Header: /home/amb/CVS/routino/src/results.c,v 1.15 2009-07-02 16:33:31 amb Exp $ |
3 | amb | 29 | |
4 | Result data type functions. | ||
5 | amb | 151 | |
6 | Part of the Routino routing software. | ||
7 | amb | 29 | ******************/ /****************** |
8 | amb | 151 | This file Copyright 2008,2009 Andrew M. Bishop |
9 | amb | 29 | |
10 | amb | 151 | 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 | amb | 29 | ***************************************/ |
23 | |||
24 | |||
25 | #include <string.h> | ||
26 | #include <stdlib.h> | ||
27 | |||
28 | #include "results.h" | ||
29 | |||
30 | |||
31 | amb | 116 | #define RESULTS_INCREMENT 16 |
32 | #define QUEUE_INCREMENT 10240 | ||
33 | amb | 67 | |
34 | amb | 71 | |
35 | amb | 67 | /*+ A queue of results. +*/ |
36 | typedef struct _Queue | ||
37 | { | ||
38 | amb | 79 | 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 | amb | 67 | } |
42 | Queue; | ||
43 | |||
44 | /*+ The queue of nodes. +*/ | ||
45 | amb | 113 | static Queue queue={0,0,NULL}; |
46 | amb | 67 | |
47 | |||
48 | amb | 29 | /*++++++++++++++++++++++++++++++++++++++ |
49 | Allocate a new results list. | ||
50 | |||
51 | Results *NewResultsList Returns the results list. | ||
52 | amb | 71 | |
53 | int nbins The number of bins in the results array. | ||
54 | amb | 29 | ++++++++++++++++++++++++++++++++++++++*/ |
55 | |||
56 | amb | 71 | Results *NewResultsList(int nbins) |
57 | amb | 29 | { |
58 | Results *results; | ||
59 | int i; | ||
60 | |||
61 | results=(Results*)malloc(sizeof(Results)); | ||
62 | |||
63 | amb | 71 | 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 | amb | 45 | results->number=0; |
76 | amb | 29 | |
77 | amb | 79 | results->count=(uint32_t*)malloc(results->nbins*sizeof(uint32_t)); |
78 | results->point=(Result***)malloc(results->nbins*sizeof(Result**)); | ||
79 | amb | 71 | |
80 | for(i=0;i<results->nbins;i++) | ||
81 | amb | 29 | { |
82 | amb | 79 | results->count[i]=0; |
83 | amb | 45 | |
84 | amb | 79 | results->point[i]=(Result**)malloc(results->alloced*sizeof(Result*)); |
85 | amb | 29 | } |
86 | amb | 45 | |
87 | amb | 79 | results->data=(Result**)malloc(1*sizeof(Result*)); |
88 | results->data[0]=(Result*)malloc(results->nbins*RESULTS_INCREMENT*sizeof(Result)); | ||
89 | amb | 45 | |
90 | amb | 176 | results->start=NO_NODE; |
91 | results->finish=NO_NODE; | ||
92 | amb | 165 | |
93 | amb | 29 | 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 | amb | 79 | int c=(results->number-1)/(results->nbins*RESULTS_INCREMENT); |
106 | amb | 29 | int i; |
107 | |||
108 | amb | 79 | for(i=c;i>=0;i--) |
109 | free(results->data[i]); | ||
110 | amb | 71 | |
111 | amb | 79 | free(results->data); |
112 | |||
113 | amb | 71 | for(i=0;i<results->nbins;i++) |
114 | amb | 79 | free(results->point[i]); |
115 | amb | 71 | |
116 | amb | 79 | free(results->point); |
117 | amb | 29 | |
118 | amb | 79 | free(results->count); |
119 | |||
120 | amb | 29 | 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 | amb | 116 | index_t node The node that is to be inserted into the results. |
132 | amb | 29 | ++++++++++++++++++++++++++++++++++++++*/ |
133 | |||
134 | amb | 116 | Result *InsertResult(Results *results,index_t node) |
135 | amb | 29 | { |
136 | amb | 71 | int bin=node&results->mask; |
137 | amb | 29 | int i; |
138 | |||
139 | /* Check that the arrays have enough space. */ | ||
140 | |||
141 | amb | 79 | if(results->count[bin]==results->alloced) |
142 | amb | 29 | { |
143 | amb | 71 | results->alloced+=RESULTS_INCREMENT; |
144 | amb | 29 | |
145 | amb | 71 | for(i=0;i<results->nbins;i++) |
146 | amb | 79 | results->point[i]=(Result**)realloc((void*)results->point[i],results->alloced*sizeof(Result*)); |
147 | } | ||
148 | amb | 29 | |
149 | amb | 79 | 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 | amb | 45 | } |
156 | amb | 29 | |
157 | /* Insert the new entry */ | ||
158 | |||
159 | amb | 111 | results->point[bin][results->count[bin]]=&results->data[results->number/(results->nbins*RESULTS_INCREMENT)][results->number%(results->nbins*RESULTS_INCREMENT)]; |
160 | amb | 29 | |
161 | amb | 45 | results->number++; |
162 | amb | 29 | |
163 | amb | 79 | results->count[bin]++; |
164 | amb | 45 | |
165 | amb | 166 | results->point[bin][results->count[bin]-1]->node=node; |
166 | |||
167 | amb | 111 | return(results->point[bin][results->count[bin]-1]); |
168 | amb | 29 | } |
169 | |||
170 | |||
171 | /*++++++++++++++++++++++++++++++++++++++ | ||
172 | amb | 166 | Zero the values in a result structure. |
173 | |||
174 | Result *result The result to modify. | ||
175 | ++++++++++++++++++++++++++++++++++++++*/ | ||
176 | |||
177 | void ZeroResult(Result *result) | ||
178 | { | ||
179 | amb | 176 | result->prev=NO_NODE; |
180 | result->next=NO_NODE; | ||
181 | amb | 166 | |
182 | result->score=0; | ||
183 | amb | 170 | result->sortby=0; |
184 | amb | 166 | |
185 | amb | 170 | result->segment=NULL; |
186 | amb | 166 | } |
187 | |||
188 | |||
189 | /*++++++++++++++++++++++++++++++++++++++ | ||
190 | amb | 111 | Find a result; search by node. |
191 | amb | 29 | |
192 | Result *insert_result Returns the result that has been found. | ||
193 | |||
194 | Results *results The results structure to search. | ||
195 | |||
196 | amb | 116 | index_t node The node that is to be found. |
197 | amb | 29 | ++++++++++++++++++++++++++++++++++++++*/ |
198 | |||
199 | amb | 116 | Result *FindResult(Results *results,index_t node) |
200 | amb | 29 | { |
201 | amb | 71 | int bin=node&results->mask; |
202 | amb | 111 | int i; |
203 | amb | 29 | |
204 | amb | 111 | for(i=results->count[bin]-1;i>=0;i--) |
205 | if(results->point[bin][i]->node==node) | ||
206 | return(results->point[bin][i]); | ||
207 | amb | 29 | |
208 | return(NULL); | ||
209 | } | ||
210 | amb | 67 | |
211 | |||
212 | /*++++++++++++++++++++++++++++++++++++++ | ||
213 | amb | 79 | Find a result from a set of results. |
214 | amb | 67 | |
215 | amb | 79 | Result *FirstResult Returns the first results from a set of results. |
216 | |||
217 | amb | 67 | Results *results The set of results. |
218 | amb | 79 | ++++++++++++++++++++++++++++++++++++++*/ |
219 | amb | 67 | |
220 | amb | 79 | 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 | amb | 92 | int i,j=0; |
240 | amb | 79 | |
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 | amb | 67 | Result *result The result to insert into the queue. |
263 | ++++++++++++++++++++++++++++++++++++++*/ | ||
264 | |||
265 | amb | 79 | void insert_in_queue(Result *result) |
266 | amb | 67 | { |
267 | int start=0; | ||
268 | int end=queue.number-1; | ||
269 | int mid; | ||
270 | int insert=-1; | ||
271 | |||
272 | amb | 79 | /* Check that the array is allocated. */ |
273 | amb | 67 | |
274 | amb | 79 | if(!queue.xqueue) |
275 | amb | 67 | { |
276 | queue.alloced=QUEUE_INCREMENT; | ||
277 | queue.number=0; | ||
278 | amb | 79 | queue.xqueue=(Result**)malloc(queue.alloced*sizeof(Result*)); |
279 | amb | 67 | } |
280 | |||
281 | /* Check that the arrays have enough space. */ | ||
282 | |||
283 | if(queue.number==queue.alloced) | ||
284 | { | ||
285 | queue.alloced+=QUEUE_INCREMENT; | ||
286 | amb | 79 | queue.xqueue=(Result**)realloc((void*)queue.xqueue,queue.alloced*sizeof(Result*)); |
287 | amb | 67 | } |
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 | amb | 116 | if(queue.number==0) /* There is nothing in the queue */ |
301 | amb | 67 | insert=0; |
302 | amb | 116 | else if(result->sortby>queue.xqueue[start]->sortby) /* Check key is not before start */ |
303 | amb | 67 | insert=start; |
304 | amb | 116 | else if(result->sortby<queue.xqueue[end]->sortby) /* Check key is not after end */ |
305 | amb | 67 | insert=end+1; |
306 | amb | 116 | else if(queue.number==2) /* Must be between them */ |
307 | insert=1; | ||
308 | amb | 67 | else |
309 | { | ||
310 | do | ||
311 | { | ||
312 | amb | 116 | mid=(start+end)/2; /* Choose mid point */ |
313 | amb | 67 | |
314 | amb | 116 | if(queue.xqueue[mid]->sortby>result->sortby) /* Mid point is too low */ |
315 | amb | 67 | start=mid; |
316 | amb | 116 | else if(queue.xqueue[mid]->sortby<result->sortby) /* Mid point is too high */ |
317 | amb | 67 | end=mid; |
318 | amb | 116 | else /* Mid point is correct */ |
319 | amb | 67 | { |
320 | amb | 79 | if(queue.xqueue[mid]==result) |
321 | amb | 67 | 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 | amb | 79 | memmove(&queue.xqueue[insert+1],&queue.xqueue[insert],(queue.number-insert)*sizeof(Result*)); |
337 | amb | 67 | |
338 | /* Insert the new entry */ | ||
339 | |||
340 | amb | 79 | queue.xqueue[insert]=result; |
341 | amb | 67 | |
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 | amb | 79 | Result *pop_from_queue() |
355 | amb | 67 | { |
356 | if(queue.number) | ||
357 | amb | 79 | return(queue.xqueue[--queue.number]); |
358 | amb | 67 | else |
359 | amb | 79 | return(NULL); |
360 | amb | 67 | } |
Properties
Name | Value |
---|---|
cvs:description | Results data type. |