modified: makefile
[GalaxyCodeBases.git] / BGI / SOAPdenovo2 / standardPregraph / fib.c
blob999b28a79bd7d9741ec788682ce1629cef26ee2b
1 /*
2 * fib.c
4 * This file is part of SOAPdenovo.
6 */
8 /*-
9 * Copyright 1997-2003 John-Mark Gurney.
10 * All rights reserved.
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
33 * $Id: fib.c,v 1.10 2007/10/19 13:09:26 zerbino Exp $
36 #include <limits.h>
37 #include <stdlib.h>
38 #include "fib.h"
39 #include "fibpriv.h"
40 #include "extfunc2.h"
42 #define HEAPBLOCKSIZE 10000
44 static int fh_comparedata ( FibHeap * h, Coordinate key, unsigned int data, FibHeapNode * b );
45 unsigned int fh_replacekeydata ( FibHeap * h, FibHeapNode * x, Coordinate key, unsigned int data );
47 static FibHeapNode * allocateFibHeapEl ( FibHeap * heap )
49 return ( FibHeapNode * ) getItem ( heap->nodeMemory );
52 static void deallocateFibHeapEl ( FibHeapNode * a, FibHeap * heap )
54 returnItem ( heap->nodeMemory, a );
57 #define swap(type, a, b) \
58 do { \
59 type c; \
60 c = a; \
61 a = b; \
62 b = c; \
63 } while (0) \
65 #define INT_BITS (sizeof(IDnum) * 8)
67 static inline IDnum ceillog2 ( IDnum a )
69 IDnum oa;
70 IDnum i;
71 IDnum b;
72 IDnum cons;
73 oa = a;
74 b = INT_BITS / 2;
75 i = 0;
77 while ( b )
79 i = ( i << 1 );
80 cons = ( ( IDnum ) 1 ) << b;
82 if ( a >= cons )
84 a /= cons;
85 i = i | 1;
87 else
89 a &= cons - 1;
92 b /= 2;
95 if ( ( ( ( IDnum ) 1 << i ) ) == oa )
97 return i;
99 else
101 return i + 1;
106 * Private Heap Functions
108 static void fh_initheap ( FibHeap * new )
110 new->fh_cmp_fnct = NULL;
111 new->nodeMemory = createMem_manager ( sizeof ( FibHeapNode ), HEAPBLOCKSIZE );
112 new->fh_neginf = 0;
113 new->fh_n = 0;
114 new->fh_Dl = -1;
115 new->fh_cons = NULL;
116 new->fh_min = NULL;
117 new->fh_root = NULL;
118 new->fh_keys = 0;
121 static void fh_destroyheap ( FibHeap * h )
123 h->fh_cmp_fnct = NULL;
124 h->fh_neginf = 0;
126 if ( h->fh_cons != NULL )
128 free ( h->fh_cons );
131 h->fh_cons = NULL;
132 free ( h );
136 * Public Heap Functions
138 FibHeap * fh_makekeyheap ()
140 FibHeap * n;
142 if ( ( n = malloc ( sizeof * n ) ) == NULL )
144 return NULL;
147 fh_initheap ( n );
148 n->fh_keys = 1;
149 return n;
152 FibHeap * fh_makeheap ()
154 FibHeap * n;
156 if ( ( n = malloc ( sizeof * n ) ) == NULL )
158 return NULL;
161 fh_initheap ( n );
162 return n;
165 voidcmp fh_setcmp ( FibHeap * h, voidcmp fnct )
167 voidcmp oldfnct;
168 oldfnct = h->fh_cmp_fnct;
169 h->fh_cmp_fnct = fnct;
170 return oldfnct;
173 unsigned int fh_setneginf ( FibHeap * h, unsigned int data )
175 unsigned int old;
176 old = h->fh_neginf;
177 h->fh_neginf = data;
178 return old;
181 FibHeap * fh_union ( FibHeap * ha, FibHeap * hb )
183 FibHeapNode * x;
185 if ( ha->fh_root == NULL || hb->fh_root == NULL )
187 /* either one or both are empty */
188 if ( ha->fh_root == NULL )
190 fh_destroyheap ( ha );
191 return hb;
193 else
195 fh_destroyheap ( hb );
196 return ha;
200 ha->fh_root->fhe_left->fhe_right = hb->fh_root;
201 hb->fh_root->fhe_left->fhe_right = ha->fh_root;
202 x = ha->fh_root->fhe_left;
203 ha->fh_root->fhe_left = hb->fh_root->fhe_left;
204 hb->fh_root->fhe_left = x;
205 ha->fh_n += hb->fh_n;
207 * we probably should also keep stats on number of unions
210 /* set fh_min if necessary */
211 if ( fh_compare ( ha, hb->fh_min, ha->fh_min ) < 0 )
213 ha->fh_min = hb->fh_min;
216 fh_destroyheap ( hb );
217 return ha;
220 void fh_deleteheap ( FibHeap * h )
222 freeMem_manager ( h->nodeMemory );
223 h->nodeMemory = NULL;
224 fh_destroyheap ( h );
228 * Public Key Heap Functions
230 FibHeapNode * fh_insertkey ( FibHeap * h, Coordinate key, unsigned int data )
232 FibHeapNode * x;
234 if ( ( x = fhe_newelem ( h ) ) == NULL )
236 return NULL;
239 /* just insert on root list, and make sure it's not the new min */
240 x->fhe_data = data;
241 x->fhe_key = key;
242 fh_insertel ( h, x );
243 return x;
246 boolean fh_isempty ( FibHeap * h )
248 if ( h->fh_min == NULL )
250 return 1;
252 else
254 return 0;
258 Coordinate fh_minkey ( FibHeap * h )
260 if ( h->fh_min == NULL )
262 return INT_MIN;
265 return h->fh_min->fhe_key;
268 unsigned int fh_replacekeydata ( FibHeap * h, FibHeapNode * x, Coordinate key, unsigned int data )
270 unsigned int odata;
271 Coordinate okey;
272 FibHeapNode * y;
273 int r;
274 odata = x->fhe_data;
275 okey = x->fhe_key;
278 * we can increase a key by deleting and reinserting, that
279 * requires O(lgn) time.
281 if ( ( r = fh_comparedata ( h, key, data, x ) ) > 0 )
283 /* XXX - bad code! */
284 abort ();
287 x->fhe_data = data;
288 x->fhe_key = key;
290 /* because they are equal, we don't have to do anything */
291 if ( r == 0 )
293 return odata;
296 y = x->fhe_p;
298 if ( h->fh_keys && okey == key )
300 return odata;
303 if ( y != NULL && fh_compare ( h, x, y ) <= 0 )
305 fh_cut ( h, x, y );
306 fh_cascading_cut ( h, y );
310 * the = is so that the call from fh_delete will delete the proper
311 * element.
313 if ( fh_compare ( h, x, h->fh_min ) <= 0 )
315 h->fh_min = x;
318 return odata;
321 Coordinate fh_replacekey ( FibHeap * h, FibHeapNode * x, Coordinate key )
323 Coordinate ret;
324 ret = x->fhe_key;
325 ( void ) fh_replacekeydata ( h, x, key, x->fhe_data );
326 return ret;
330 * Public void * Heap Functions
333 * this will return these values:
334 * NULL failed for some reason
335 * ptr token to use for manipulation of data
337 FibHeapNode * fh_insert ( FibHeap * h, unsigned int data )
339 FibHeapNode * x;
341 if ( ( x = fhe_newelem ( h ) ) == NULL )
343 return NULL;
346 /* just insert on root list, and make sure it's not the new min */
347 x->fhe_data = data;
348 fh_insertel ( h, x );
349 return x;
352 unsigned int fh_min ( FibHeap * h )
354 if ( h->fh_min == NULL )
356 return 0;
359 return h->fh_min->fhe_data;
362 unsigned int fh_extractmin ( FibHeap * h )
364 FibHeapNode * z;
365 unsigned int ret = 0;
367 if ( h->fh_min != NULL )
369 z = fh_extractminel ( h );
370 ret = z->fhe_data;
371 #ifndef NO_FREE
372 deallocateFibHeapEl ( z, h );
373 #endif
376 return ret;
379 unsigned int fh_replacedata ( FibHeapNode * x, unsigned int data )
381 unsigned int odata = x->fhe_data;
382 x->fhe_data = data;
383 return odata;
386 unsigned int fh_delete ( FibHeap * h, FibHeapNode * x )
388 unsigned int k;
389 k = x->fhe_data;
391 if ( !h->fh_keys )
393 fh_replacedata ( x, h->fh_neginf );
395 else
397 fh_replacekey ( h, x, INT_MIN );
400 fh_extractmin ( h );
401 return k;
405 * begin of private element fuctions
407 static FibHeapNode * fh_extractminel ( FibHeap * h )
409 FibHeapNode * ret;
410 FibHeapNode * x, *y, *orig;
411 ret = h->fh_min;
412 orig = NULL;
414 /* put all the children on the root list */
415 /* for true consistancy, we should use fhe_remove */
416 for ( x = ret->fhe_child; x != orig && x != NULL; )
418 if ( orig == NULL )
420 orig = x;
423 y = x->fhe_right;
424 x->fhe_p = NULL;
425 fh_insertrootlist ( h, x );
426 x = y;
429 /* remove minimum from root list */
430 fh_removerootlist ( h, ret );
431 h->fh_n--;
433 /* if we aren't empty, consolidate the heap */
434 if ( h->fh_n == 0 )
436 h->fh_min = NULL;
438 else
440 h->fh_min = ret->fhe_right;
441 fh_consolidate ( h );
444 return ret;
447 static void fh_insertrootlist ( FibHeap * h, FibHeapNode * x )
449 if ( h->fh_root == NULL )
451 h->fh_root = x;
452 x->fhe_left = x;
453 x->fhe_right = x;
454 return;
457 fhe_insertafter ( h->fh_root, x );
460 static void fh_removerootlist ( FibHeap * h, FibHeapNode * x )
462 if ( x->fhe_left == x )
464 h->fh_root = NULL;
466 else
468 h->fh_root = fhe_remove ( x );
472 static void fh_consolidate ( FibHeap * h )
474 FibHeapNode ** a;
475 FibHeapNode * w;
476 FibHeapNode * y;
477 FibHeapNode * x;
478 IDnum i;
479 IDnum d;
480 IDnum D;
481 fh_checkcons ( h );
482 /* assign a the value of h->fh_cons so I don't have to rewrite code */
483 D = h->fh_Dl + 1;
484 a = h->fh_cons;
486 for ( i = 0; i < D; i++ )
488 a[i] = NULL;
491 while ( ( w = h->fh_root ) != NULL )
493 x = w;
494 fh_removerootlist ( h, w );
495 d = x->fhe_degree;
497 /* XXX - assert that d < D */
498 while ( a[d] != NULL )
500 y = a[d];
502 if ( fh_compare ( h, x, y ) > 0 )
504 swap ( FibHeapNode *, x, y );
507 fh_heaplink ( h, y, x );
508 a[d] = NULL;
509 d++;
512 a[d] = x;
515 h->fh_min = NULL;
517 for ( i = 0; i < D; i++ )
518 if ( a[i] != NULL )
520 fh_insertrootlist ( h, a[i] );
522 if ( h->fh_min == NULL || fh_compare ( h, a[i], h->fh_min ) < 0 )
524 h->fh_min = a[i];
529 static void fh_heaplink ( FibHeap * h, FibHeapNode * y, FibHeapNode * x )
531 /* make y a child of x */
532 if ( x->fhe_child == NULL )
534 x->fhe_child = y;
536 else
538 fhe_insertbefore ( x->fhe_child, y );
541 y->fhe_p = x;
542 x->fhe_degree++;
543 y->fhe_mark = 0;
546 static void fh_cut ( FibHeap * h, FibHeapNode * x, FibHeapNode * y )
548 fhe_remove ( x );
549 y->fhe_degree--;
550 fh_insertrootlist ( h, x );
551 x->fhe_p = NULL;
552 x->fhe_mark = 0;
555 static void fh_cascading_cut ( FibHeap * h, FibHeapNode * y )
557 FibHeapNode * z;
559 while ( ( z = y->fhe_p ) != NULL )
561 if ( y->fhe_mark == 0 )
563 y->fhe_mark = 1;
564 return;
566 else
568 fh_cut ( h, y, z );
569 y = z;
575 * begining of handling elements of fibheap
577 static FibHeapNode * fhe_newelem ( FibHeap * h )
579 FibHeapNode * e;
581 if ( ( e = allocateFibHeapEl ( h ) ) == NULL )
583 return NULL;
586 fhe_initelem ( e );
587 return e;
590 static void fhe_initelem ( FibHeapNode * e )
592 e->fhe_degree = 0;
593 e->fhe_mark = 0;
594 e->fhe_p = NULL;
595 e->fhe_child = NULL;
596 e->fhe_left = e;
597 e->fhe_right = e;
598 e->fhe_data = 0;
601 static void fhe_insertafter ( FibHeapNode * a, FibHeapNode * b )
603 if ( a == a->fhe_right )
605 a->fhe_right = b;
606 a->fhe_left = b;
607 b->fhe_right = a;
608 b->fhe_left = a;
610 else
612 b->fhe_right = a->fhe_right;
613 a->fhe_right->fhe_left = b;
614 a->fhe_right = b;
615 b->fhe_left = a;
619 static inline void fhe_insertbefore ( FibHeapNode * a, FibHeapNode * b )
621 fhe_insertafter ( a->fhe_left, b );
624 static FibHeapNode * fhe_remove ( FibHeapNode * x )
626 FibHeapNode * ret;
628 if ( x == x->fhe_left )
630 ret = NULL;
632 else
634 ret = x->fhe_left;
637 /* fix the parent pointer */
638 if ( x->fhe_p != NULL && x->fhe_p->fhe_child == x )
640 x->fhe_p->fhe_child = ret;
643 x->fhe_right->fhe_left = x->fhe_left;
644 x->fhe_left->fhe_right = x->fhe_right;
645 /* clear out hanging pointers */
646 x->fhe_p = NULL;
647 x->fhe_left = x;
648 x->fhe_right = x;
649 return ret;
652 static void fh_checkcons ( FibHeap * h )
654 IDnum oDl;
656 /* make sure we have enough memory allocated to "reorganize" */
657 if ( h->fh_Dl == -1 || h->fh_n > ( 1 << h->fh_Dl ) )
659 oDl = h->fh_Dl;
661 if ( ( h->fh_Dl = ceillog2 ( h->fh_n ) + 1 ) < 8 )
663 h->fh_Dl = 8;
666 if ( oDl != h->fh_Dl )
667 { h->fh_cons = ( FibHeapNode ** ) realloc ( h->fh_cons, sizeof * h->fh_cons * ( h->fh_Dl + 1 ) ); }
669 if ( h->fh_cons == NULL )
671 abort ();
676 static int fh_compare ( FibHeap * h, FibHeapNode * a, FibHeapNode * b )
678 if ( a->fhe_key < b->fhe_key )
680 return -1;
683 if ( a->fhe_key == b->fhe_key )
685 return 0;
688 return 1;
691 static int fh_comparedata ( FibHeap * h, Coordinate key, unsigned int data, FibHeapNode * b )
693 FibHeapNode a;
694 a.fhe_key = key;
695 a.fhe_data = data;
696 return fh_compare ( h, &a, b );
699 static void fh_insertel ( FibHeap * h, FibHeapNode * x )
701 fh_insertrootlist ( h, x );
703 if ( h->fh_min == NULL || ( h->fh_keys ? x->fhe_key < h->fh_min->fhe_key : h->fh_cmp_fnct ( x->fhe_data, h->fh_min->fhe_data ) < 0 ) )
705 h->fh_min = x;
708 h->fh_n++;