- fix quoted characters output - fix line position in read_term and friends - make messages look a bit better - CLP(BN) EM improvements.
		
			
				
	
	
		
			953 lines
		
	
	
		
			27 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			953 lines
		
	
	
		
			27 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*******************************************************************************************
 | |
| 
 | |
| Copyright (C) 2004,2005,2006,2007,2008 (Nuno A. Fonseca) <nuno.fonseca@gmail.com>
 | |
| 
 | |
| This program is free software; you can redistribute it and/or 
 | |
| modify it under the terms of the GNU General Public License 
 | |
| as published by the Free Software Foundation; either 
 | |
| version 2 of the License, or (at your option) any later 
 | |
| version.
 | |
| 
 | |
| This program is distributed in the hope that it will be useful,
 | |
| but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | |
| GNU General Public License for more details.
 | |
| 
 | |
| You should have received a copy of the GNU General Public License
 | |
| along with this program; if not, write to the Free Software
 | |
| Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 | |
| 
 | |
| 
 | |
| Last rev: $Id: range_list.c,v 1.1 2008-03-26 23:05:22 nunofonseca Exp $
 | |
| **************************************************************************/
 | |
| 
 | |
| #include <stdio.h>
 | |
| #include <stdlib.h>
 | |
| #include <string.h>
 | |
| #include "range_list.h"
 | |
| 
 | |
| /*****************************************************************************/
 | |
| 
 | |
| 
 | |
| 
 | |
| void set_num_bit(unsigned int number,char* storage,STATUS status);
 | |
| BOOLEAN is_num_bit(unsigned int number,char *storage,STATUS status);
 | |
| 
 | |
| static void set_quadrant(RL_Node* node,short quadrant,QUADRANT_STATUS status);
 | |
| static QUADRANT_STATUS quadrant_status(RL_Node* node,short quadrant);
 | |
| 
 | |
| static void quadrant_interval(RL_Tree *tree,short quadrant,NUM interval,NUM *quad_interval);
 | |
| static NUM get_quadrant_node(RL_Tree* tree,NUM node,short quadrant,NUM interval);
 | |
| static unsigned int tree_size(RL_Tree *tree,NUM node,NUM);
 | |
| 
 | |
| int get_location(RL_Tree* tree,NUM node,short quadrant,NUM interval);
 | |
| 
 | |
| long set_in(NUM number,NUM node, NUM node_num, NUM interval,NUM max,RL_Tree* tree,STATUS status);
 | |
| long compact_node(RL_Tree*,NUM node,NUM next_node,NUM node_interval,NUM next_node_interval,NUM next_node_num,short quadrant,NUM max);
 | |
| 
 | |
| BOOLEAN in_tree(NUM number,RL_Tree *tree,NUM node,NUM node_num,NUM interval);
 | |
| void display_tree(RL_Tree *tree);
 | |
| void idisplay_tree(RL_Tree *tree,NUM node,NUM node_num,NUM interval,NUM max);
 | |
| static void display_leaf(RL_Tree* tree,NUM node,NUM node_num,NUM max);
 | |
| 
 | |
| NUM new_node(RL_Tree* tree,NUM node_father,short quadrant,NUM node_num,NUM quad_min,NUM quad_max,STATUS);
 | |
| static void root_intervals(RL_Tree* tree);
 | |
| 
 | |
| NUM next_min(RL_Tree *tree,NUM node,NUM node_num,NUM interval,NUM max,NUM min);
 | |
| NUM tree_minus(RL_Tree *r1,RL_Tree *r2,NUM node1,NUM node2,NUM node_num,NUM interval,NUM max);
 | |
| 
 | |
| RL_Tree* minus_rl(RL_Tree* range1,RL_Tree* range2);
 | |
| void shift_right(RL_Tree *tree,const NUM idx,const long nnodes);
 | |
| void shift_left(RL_Tree *tree,const NUM idx, const long nnodes);
 | |
| void intersect_leafs(char *storage1,char *storage2);
 | |
| 
 | |
| static void print_nodes(RL_Tree* tree);
 | |
| 
 | |
| //
 | |
| RL_Buffer* buffer=NULL;
 | |
| unsigned int active_bits[16]={
 | |
|   1,
 | |
|   3,
 | |
|   7,
 | |
|   15,
 | |
|   31,
 | |
|   63,
 | |
|   127,
 | |
|   255,
 | |
|   511,
 | |
|   1023,
 | |
|   2047,
 | |
|   4095,
 | |
|   8191,
 | |
|   16383,
 | |
|   32767,
 | |
|   65535
 | |
| };
 | |
| 
 | |
| 
 | |
| /*****************************************************************************/
 | |
| /*
 | |
|  *
 | |
|  *
 | |
|  */
 | |
| RL_Tree* new_rl(NUM max_size) {
 | |
| 
 | |
|   RL_Tree *new;
 | |
|   RL_Node *buf_ptr;
 | |
|   short q;
 | |
|   NUM qi,tmp;
 | |
|   
 | |
|   if ( max_size <2 ) 
 | |
|     max_size=2; 
 | |
| 
 | |
|   new=(RL_Tree*)malloc(sizeof(RL_Tree));
 | |
|   if(new==NULL)
 | |
|     return NULL;
 | |
| 
 | |
|   new->range_max=max_size;
 | |
|   root_intervals(new);
 | |
| 
 | |
|   // alloc a block for the nodes
 | |
|   new->root=(RL_Node*)calloc(1,NODE_SIZE);
 | |
|   new->size=1;
 | |
|   new->mem_alloc=NODE_SIZE; // memory allocated
 | |
| 
 | |
|   // reset buffer
 | |
|   buf_ptr=new->root;//tree_buffer();
 | |
|   ALL_OUT(&buf_ptr[0]); // Initialize all numbers as being out of the range/interval
 | |
|   buf_ptr[0].i_node.num_subnodes=1;
 | |
|   new->root=buf_ptr;// pointer to the buffer
 | |
| 
 | |
|   buf_ptr->i_node.num_subnodes=1;
 | |
|   quadrant_interval(new,1,max_size,&qi);
 | |
|   tmp=qi+1;
 | |
|   for(q=2;q<=BRANCH_FACTOR;++q) {
 | |
|     if ( max_size < qi*(q-1)+1 )  // 16 32 48 64 - 32
 | |
|       set_quadrant(new->root,q,R_IGNORE);
 | |
|     tmp+=qi;  // max_size=16  16+1
 | |
|   }
 | |
| 
 | |
|   return new;
 | |
| }
 | |
| /*
 | |
|  *
 | |
|  *
 | |
|  */
 | |
| RL_Tree* copy_rl(RL_Tree *tree) {
 | |
| 
 | |
|   RL_Tree *new;
 | |
|   RL_Node *buf_ptr;
 | |
| 
 | |
|   new=(RL_Tree*)malloc(sizeof(RL_Tree));
 | |
|   buf_ptr=(RL_Node*)calloc(tree->size,NODE_SIZE);
 | |
|   if( new==NULL ) {
 | |
|     printf("new==NULL");
 | |
|     return NULL;
 | |
|   }
 | |
|   if( buf_ptr==NULL ) {
 | |
|     printf("buf_ptr==NULL---%lu",tree->size);
 | |
|     return NULL;
 | |
|   }
 | |
|   memcpy(new,tree,sizeof(RL_Tree));
 | |
|   memcpy(buf_ptr,&tree->root[0],tree->size*NODE_SIZE);
 | |
|   new->root=buf_ptr;
 | |
|   new->mem_alloc=tree->size*NODE_SIZE; 
 | |
|   return new;
 | |
| }
 | |
| /*
 | |
|  *
 | |
|  *
 | |
|  */
 | |
| void free_rl(RL_Tree* range) {
 | |
|   
 | |
|   // free nodes block
 | |
|   if(range->mem_alloc!=0)
 | |
|     free(range->root);
 | |
|   //
 | |
|   free(range);
 | |
| }
 | |
| /*
 | |
|  
 | |
|  */
 | |
| RL_Tree* set_in_rl(RL_Tree* tree,NUM number,STATUS status) {
 | |
| 
 | |
|   /* */
 | |
|   if ( number >0 && number <=tree->range_max)
 | |
|     set_in(number,ROOT(tree),1,ROOT_INTERVAL(tree),tree->range_max,tree,status);
 | |
| #ifdef DEBUG
 | |
|   printf("Setting: %d  size=%d\n",number,tree->size);
 | |
| #endif
 | |
|   /*if (status==IN && !in_rl(tree,number)) {
 | |
|     fprintf(stderr,"Error adding %lu to tree: size=%lu max=%lu\n",number,tree->size,tree->range_max);
 | |
|     display_tree(tree);
 | |
|     exit(1);
 | |
|     }*/
 | |
|   return tree;
 | |
| }
 | |
| /*
 | |
|  * Mark all examples in range IN/OUT
 | |
|  */
 | |
| void rl_all(RL_Tree* tree,STATUS status) {
 | |
|   int i;
 | |
| 
 | |
|   for(i=1;i<=BRANCH_FACTOR;++i)
 | |
|     if (quadrant_status(NODE(tree,ROOT(tree)),i)!=R_IGNORE) {
 | |
|       if(status==IN)
 | |
| 	set_quadrant(NODE(tree,ROOT(tree)),i,R_TOTALLY_IN_INTERVAL);
 | |
|       else
 | |
| 	set_quadrant(NODE(tree,ROOT(tree)),i,R_NOT_IN_INTERVAL);
 | |
|     }
 | |
|   tree->size=1;
 | |
| }
 | |
| /*
 | |
|  *
 | |
|  *
 | |
|  */
 | |
| BOOLEAN  in_rl(RL_Tree* tree,NUM number) { 
 | |
|   if ( number <1 && number >tree->range_max)
 | |
|     return FALSE;
 | |
|   return in_tree(number,tree,ROOT(tree),1,ROOT_INTERVAL(tree));
 | |
| }
 | |
| /*
 | |
|  *
 | |
|  *
 | |
|  */
 | |
| BOOLEAN  freeze_rl(RL_Tree* range) {
 | |
|   
 | |
|   //  reduce memory usage if possible
 | |
|   NUM s=range->size*NODE_SIZE;
 | |
|   if ( s < range->mem_alloc) {
 | |
|     range->root=(RL_Node*)realloc(range->root,s);
 | |
|     range->mem_alloc=s;
 | |
|   }
 | |
|   return TRUE;
 | |
| }
 | |
| /*
 | |
|  * Returns range1 without the numbers in range2
 | |
|  * Constraint:range1->max==range2->max
 | |
|  */
 | |
| RL_Tree* minus_rl(RL_Tree* range1,RL_Tree* range2) {
 | |
|   if (range1->range_max!=range1->range_max) 
 | |
|     return NULL;
 | |
|   //!!!!tree_minus(range1,range2,ROOT(range1),ROOT(range2),1,ROOT_INTERVAL(range1),range1->range_max);
 | |
|   return range1;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Returns next number in tree bigger than min 
 | |
|  */
 | |
| NUM rl_next_in_bigger(RL_Tree *tree,NUM min) {
 | |
|   if ( tree==NULL ) {
 | |
|     fprintf(stdout,"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!%lu\n",min);
 | |
|   }
 | |
|   return next_min(tree,ROOT(tree),1,ROOT_INTERVAL(tree),tree->range_max,min+1);
 | |
| }
 | |
| /* ****************************************************************************** 
 | |
|    Private Functions
 | |
|    ****************************************************************************** */
 | |
| static void print_nodes(RL_Tree* tree) {
 | |
|   RL_Node* nodes=tree->root;
 | |
|   int j;
 | |
|   
 | |
|   for(j=0;j<tree->size;++j) 
 | |
|     printf("[%d]=%lu\n",j,(unsigned long int)nodes[j].leaf);
 | |
|   
 | |
| }
 | |
| // treeXquadrantXinterval->quadrant_minXquadrant_max
 | |
| static void quadrant_interval(RL_Tree *tree,short quadrant,NUM interval,NUM *quad_interval) {
 | |
|   
 | |
|   if ( IS_ROOT(tree,interval) ) {
 | |
|     *quad_interval=tree->root_i;
 | |
|   } else {
 | |
|     *quad_interval=NEXT_INTERVAL(interval);
 | |
|   }
 | |
| }
 | |
| 
 | |
| // numberXtreeXinterval->quadrantXquadrant_minXquadrant_max
 | |
| static void number_quadrant(NUM number,RL_Tree *tree,NUM node_interval,NUM node_num,short *quadrant,NUM *quad_min,NUM *quad_max) {
 | |
|   NUM tmp=node_num-1,quad_interval;
 | |
|   int i;
 | |
|   quadrant_interval(tree,1,node_interval,&quad_interval);
 | |
|   i=(number-node_num)/quad_interval+1;
 | |
|   tmp=node_num-1+quad_interval*i;
 | |
|   *quad_max=tmp;
 | |
|   *quadrant=i;
 | |
|   *quad_min=tmp-quad_interval+1;
 | |
|   //printf("number=%lu node num=%lu quad_interval=%lu-------> quadrant=%d   quad_max=%lu\n",number,node_num,quad_interval,i,tmp);
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * returns the index to the quadrant "quadrant" node
 | |
|  */
 | |
| static NUM get_quadrant_node(RL_Tree* tree,NUM node,short quadrant,NUM interval) {
 | |
|   int d=get_location(tree,node,quadrant,interval);
 | |
|   return node+d;
 | |
| }
 | |
| /*                 src    s 
 | |
|  *  src= 1 2 3 4 5 6 _ _
 | |
|  *  offset= 2
 | |
|  *  nbytes=6
 | |
|  *  >>>src= 1 2 1 2 3 4 5 6 
 | |
|  *                    src    s
 | |
|  */
 | |
| void shift_right(RL_Tree *tree,const NUM idx,const long nnodes){
 | |
|   long n=idx+nnodes;
 | |
|   RL_Node *s=tree->root;
 | |
| 
 | |
|   if (nnodes<=0) return;
 | |
|   //print_nodes(tree);
 | |
|   while(n>=idx) {
 | |
|     s[n+1].leaf=s[n].leaf;
 | |
|     --n;
 | |
|   }
 | |
|   //print_nodes(tree); 
 | |
|   //printf(">>----------------\n");
 | |
| }
 | |
| 
 | |
| void shift_left(RL_Tree *tree,const NUM idx, const long nnodes){
 | |
|   long n=idx;
 | |
|   RL_Node *s=tree->root;
 | |
| 
 | |
|   //printf("sfit left: idx=%u nnodes=%u max=%u\n",idx,nnodes,tree->size);
 | |
|   if ( nnodes<=0 )  // last element
 | |
|     return;
 | |
|   
 | |
|   //  print_nodes(tree);
 | |
|   while(n<idx+nnodes) {
 | |
|     s[n].leaf=s[n+1].leaf;
 | |
|     ++n;;
 | |
|   }
 | |
|   //  print_nodes(tree);
 | |
|   //printf("<<----------------\n");
 | |
| }
 | |
| 
 | |
| /*
 | |
|  *
 | |
|  *
 | |
|  */
 | |
| NUM new_node(RL_Tree* tree,NUM node_father,short quadrant,NUM father_interval,NUM quad_min,NUM quad_max,STATUS status) {
 | |
|   //RL_Node *new,*root_node=tree->root;
 | |
|   NUM new_interval=+NEXT_INTERVAL(father_interval);
 | |
|   NUM times;
 | |
|   NUM new;
 | |
|   RL_Node* ptr;
 | |
|   new=get_quadrant_node(tree,node_father,quadrant,father_interval);
 | |
|   
 | |
|   if ( tree->mem_alloc!=0 ) {
 | |
|     // increase array size and shift elements right
 | |
|     if ( REALLOC_MEM(tree) ) {
 | |
|       //printf("new node:resizing memory: current %lu -> new %lu  [%lu]\n",tree->mem_alloc,MEM_SIZE(tree),tree->size);
 | |
|       ptr=(RL_Node*)realloc(tree->root,MEM_SIZE(tree));
 | |
|       if ( ptr==NULL ) {
 | |
| 	fprintf(stderr,"Fatal error:range_list: Unable to allocate memory");
 | |
| 	exit(1);
 | |
|       }
 | |
|       tree->root=ptr;
 | |
|       tree->mem_alloc=MEM_SIZE(tree);
 | |
|     }
 | |
|     // SHIFT elements at the right and including the current node one position
 | |
|     times=tree->size-1-new;
 | |
|     shift_right(tree,new,times);
 | |
|       //      SHIFT_NODES((void*)new,times*NODE_SIZE);
 | |
|   }
 | |
|   // update father reference
 | |
|   set_quadrant(NODE(tree,node_father),quadrant,R_PARCIALLY_IN_INTERVAL);
 | |
|   // initialize node
 | |
|   if ( status==IN) {
 | |
|     ALL_OUT(NODE(tree,new));    // clear all bits
 | |
|     if ( !IS_LEAF(new_interval) ) {
 | |
|       short q;
 | |
|       RL_Node* node_ptr=NODE(tree,new);
 | |
|       node_ptr->i_node.num_subnodes=1;
 | |
|       for(q=2;q<=BRANCH_FACTOR;++q) 
 | |
| 	if (  MIN(quad_max,tree->range_max) < quad_min+NEXT_INTERVAL(new_interval)*(q-1)  ) //QUADRANT_MAX_VALUE(
 | |
| 	  set_quadrant(NODE(tree,new),q,R_IGNORE);
 | |
|     }
 | |
|   } else {
 | |
|     // status ==out
 | |
|     //SET_LEAF_IN(tree->range_max,NODE(tree,new),quad_min);
 | |
|     tree->root[new].leaf=ON_BITS(MIN(16,tree->range_max-quad_min+1));
 | |
|     if ( !IS_LEAF(new_interval) ) {
 | |
|       short q;
 | |
|       RL_Node* node_ptr=NODE(tree,new);
 | |
|       node_ptr->i_node.num_subnodes=1;
 | |
|       node_ptr->i_node.quadrant_1=node_ptr->i_node.quadrant_2=node_ptr->i_node.quadrant_3=node_ptr->i_node.quadrant_4=R_TOTALLY_IN_INTERVAL;
 | |
|       for(q=2;q<=BRANCH_FACTOR;++q) 
 | |
| 	if (  MIN(quad_max,tree->range_max) < quad_min+NEXT_INTERVAL(new_interval)*(q-1)  ) //QUADRANT_MAX_VALUE(
 | |
| 	  set_quadrant(NODE(tree,new),q,R_IGNORE);
 | |
|     }
 | |
|   }
 | |
|   // update tree size
 | |
|   tree->size++;
 | |
|   return new;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * returns the offset
 | |
|  *
 | |
|  */
 | |
| int get_location(RL_Tree* tree,NUM node,short quadrant,NUM node_interval) {
 | |
|   int i,c=1,tmp;
 | |
|   NUM next_node;
 | |
|   NUM next_interval;
 | |
| 
 | |
|   if (quadrant==1 || IS_LEAF(node_interval)) return 1;
 | |
| 
 | |
|   //
 | |
|   if ( LAST_LEVEL_INODE(node_interval) ) {
 | |
|     // 1 node = current
 | |
|     for(i=1;i<quadrant;++i) {
 | |
|       if ( quadrant_status(NODE(tree,node),i)==R_PARCIALLY_IN_INTERVAL )
 | |
| 	++c;
 | |
|     }
 | |
|     return c;
 | |
|   }
 | |
|   
 | |
|   //
 | |
|   // internal range list nodes
 | |
|   quadrant_interval(tree,quadrant,node_interval,&next_interval);
 | |
|   i=1;
 | |
|   next_node=node+1;
 | |
|   while(i!=quadrant && i<=BRANCH_FACTOR) {
 | |
|     if ( quadrant_status(NODE(tree,node),i)==R_PARCIALLY_IN_INTERVAL ) {
 | |
|       tmp=tree_size(tree,next_node,next_interval);
 | |
|       next_node+=tmp;
 | |
|       c+=tmp;
 | |
|     }
 | |
|     ++i;
 | |
|   }
 | |
|   
 | |
|   return c;
 | |
| }
 | |
| /*
 | |
|  * Returns the number of nodes created/deleted.
 | |
|  *
 | |
|  * number: number to insert from the interval
 | |
|  * node:   index of current node
 | |
|  * node_num: number corresponding to the beginning o the interval represented by node
 | |
|  * interval: size of the interval represented in the current node
 | |
|  */
 | |
| long set_in(NUM number,NUM node, NUM node_num, NUM node_interval,NUM max,RL_Tree* tree,STATUS status) {
 | |
|   NUM next_node;
 | |
|   long ret_val=tree->size,compacted;
 | |
|   NUM interval=node_interval;
 | |
|   NUM quad_min,quad_max;
 | |
|   short quadrant;
 | |
|   NUM size;
 | |
|   /* */
 | |
|   if ( IS_LEAF(interval) ) {
 | |
|     // current node is a leaf
 | |
|     set_num_bit(number-node_num,(char*)NODE(tree,node),status);
 | |
|     return 0;
 | |
|   }
 | |
|   //
 | |
|   number_quadrant(number,tree,node_interval,node_num,&quadrant,&quad_min,&quad_max);
 | |
|   interval=quad_max-quad_min+1;
 | |
|   // select next node
 | |
|   switch(status) {
 | |
|   case IN:
 | |
|   // move pointer to next node
 | |
|     if ( quadrant_status(NODE(tree,node),quadrant)==R_NOT_IN_INTERVAL ) {
 | |
|       // new node
 | |
|       //display_tree(tree);
 | |
|       next_node=new_node(tree,node,quadrant,node_interval,quad_min,quad_max,status);
 | |
|     }else if ( quadrant_status(NODE(tree,node),quadrant)==R_TOTALLY_IN_INTERVAL ) 
 | |
|       return 0;
 | |
|     else
 | |
|       next_node=get_quadrant_node(tree,node,quadrant,node_interval);
 | |
|     break;
 | |
|   case OUT:
 | |
|     if ( quadrant_status(NODE(tree,node),quadrant)==R_TOTALLY_IN_INTERVAL ) {
 | |
|       // new node
 | |
|       next_node=new_node(tree,node,quadrant,node_interval,quad_min,quad_max,status);
 | |
|     } else if ( quadrant_status(NODE(tree,node),quadrant)==R_NOT_IN_INTERVAL ) 
 | |
|       return 0;
 | |
|     else
 | |
|       next_node=get_quadrant_node(tree,node,quadrant,node_interval);
 | |
|     break;
 | |
|   default:
 | |
|     printf("set_in: invalid number status %d\n",status);
 | |
|     exit(1);
 | |
|   }
 | |
|   // insert in tree
 | |
|   set_in(number,next_node,quad_min,interval,quad_max,tree,status);
 | |
|   ret_val=tree->size-ret_val; // number of nodes added/removed
 | |
|   // compact tree: only if we didn't create new nodes
 | |
|   //compacted=compact_node(tree,node,next_node,node_interval,interval,quad_min,quadrant,MIN(quad_max,tree->range_max));
 | |
|   compacted=0;
 | |
|   if ( compacted==-1 ) {
 | |
|     //NUM times=tree->size-1-next_node; // -1 because array position 0
 | |
|     shift_left(tree,next_node,1);
 | |
|     // update tree size
 | |
|     tree->size+=compacted;
 | |
|     ret_val+=compacted;
 | |
|     //ret_val=0;//compacted;  
 | |
|   }
 | |
|   // update subnodes number
 | |
|   if ( tree->root[node].i_node.num_subnodes ==255 ) 
 | |
|     size=tree_size(tree,node,interval);
 | |
|   else
 | |
|     size=ret_val+tree->root[node].i_node.num_subnodes; // new subnodes value
 | |
| 
 | |
|   if ( size > 254 )
 | |
|     tree->root[node].i_node.num_subnodes=255;
 | |
|   else
 | |
|     tree->root[node].i_node.num_subnodes=size;
 | |
|   
 | |
|   //  if (size <0 ) exit(1);
 | |
|   return ret_val;
 | |
| }
 | |
| /*
 | |
|  * Check if can change quadrant color of node. If it changes, the node is deleted and all nodes at right in the array are shifted one position.
 | |
|  *
 | |
|  */
 | |
| long compact_node(RL_Tree *tree,NUM node,NUM next_node,NUM node_interval,NUM next_node_interval,NUM next_node_num,short quadrant,NUM max){
 | |
|   unsigned int j;
 | |
| 
 | |
|   RL_Node* node_ptr=NODE(tree,next_node); // next node pointer
 | |
|   
 | |
|   // Try to compact a leaf
 | |
|   if ( IS_LEAF(next_node_interval) ) {
 | |
| #ifdef DEBUG
 | |
|     fprintf(stderr,"compact_node: interval node\n");
 | |
| #endif
 | |
|     // ALL IN
 | |
|     if ( LEAF_ALL_IN(node_ptr->leaf) ) {
 | |
|       set_quadrant(NODE(tree,node),quadrant,R_TOTALLY_IN_INTERVAL);
 | |
|       return -1;
 | |
|     }
 | |
|     // ALL IN: part II
 | |
|     // The last node does not need to be all in
 | |
|     if ( max-next_node_num+1 <= LEAF_SIZE ) {
 | |
|       j=ON_BITS(max-next_node_num+1); //153,154,155,156,157,.,.,.,[158   -> valor do max=200 devia ser 158
 | |
|       if ( node_ptr->leaf==j ) {
 | |
| 	set_quadrant(NODE(tree,node),quadrant,R_TOTALLY_IN_INTERVAL);
 | |
| 	return -1;
 | |
|       }
 | |
|     }
 | |
|     // ALL OUT
 | |
|     if ( LEAF_ALL_OUT(node_ptr->leaf) ) {
 | |
|       set_quadrant(NODE(tree,node),quadrant,R_NOT_IN_INTERVAL);
 | |
| #ifdef DEBUG
 | |
|       printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>compacted leaf1\n");
 | |
| #endif
 | |
|       return -1;
 | |
|     }
 | |
|   } else {
 | |
| #ifdef DEBUG
 | |
|     fprintf(stderr,"compact_node:range node\n");
 | |
| #endif
 | |
|     // INODE - range list node
 | |
|     if ( node_ptr->i_node.num_subnodes>1 ) // unable to compact
 | |
|       return 0;
 | |
|     // ALL IN
 | |
|     for(j=1;j<=BRANCH_FACTOR;++j)
 | |
|       if ( quadrant_status(NODE(tree,next_node),j)!=R_IGNORE && quadrant_status(NODE(tree,next_node),j)!=R_TOTALLY_IN_INTERVAL )
 | |
|     	break;
 | |
| 
 | |
|     if (j>BRANCH_FACTOR) {
 | |
|       set_quadrant(NODE(tree,node),quadrant,R_TOTALLY_IN_INTERVAL);
 | |
|       return -1;
 | |
|     }
 | |
|     // ALL OUT
 | |
|     for(j=1;j<=BRANCH_FACTOR;++j)
 | |
|       if ( quadrant_status(NODE(tree,next_node),j)!=R_IGNORE && quadrant_status(NODE(tree,next_node),j)!=R_NOT_IN_INTERVAL )
 | |
|     	break;
 | |
| 
 | |
|     if (j>BRANCH_FACTOR) {
 | |
|       set_quadrant(NODE(tree,node),quadrant,R_NOT_IN_INTERVAL);
 | |
|       return -1;
 | |
|     }
 | |
|   }
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * interval: interval associated to the node
 | |
|  */
 | |
| static  unsigned int tree_size(RL_Tree *tree,NUM node,NUM interval) {
 | |
|   unsigned int c=1,tmp;
 | |
|   int i=1;
 | |
|   short status;
 | |
|   NUM next_interval;
 | |
|   NUM next_node;
 | |
|   RL_Node* node_ptr=NODE(tree,node);
 | |
| 
 | |
|   if ( IS_LEAF(interval)) return 1;
 | |
| 
 | |
|   if ( node_ptr->i_node.num_subnodes==255) {
 | |
|     // compute the size of all subtrees
 | |
|     next_interval=NEXT_INTERVAL(interval);
 | |
|     for(i=1;i<=BRANCH_FACTOR;++i) {
 | |
|       status=quadrant_status(NODE(tree,node),i);
 | |
|       switch(status) {
 | |
|       case R_PARCIALLY_IN_INTERVAL:
 | |
| 	next_node=node+c; //      
 | |
| 	tmp=tree_size(tree,next_node,next_interval);
 | |
| 	c+=tmp;
 | |
| 	//      default: 
 | |
|       }
 | |
|     }
 | |
|   } 
 | |
|   else c=node_ptr->i_node.num_subnodes;
 | |
|   return c;
 | |
| }
 | |
| /*
 | |
|  * number >=1 && number <=16
 | |
|  */
 | |
| void set_num_bit(unsigned int number,char *storage,STATUS status) {
 | |
|   if ( number >= 8 ) {
 | |
|     storage++;
 | |
|     number=number-8; // =-8
 | |
|   } 
 | |
|   if ( status==IN )
 | |
|     BITMAP_insert(*storage,number);
 | |
|   else
 | |
|     BITMAP_delete(*storage,number);
 | |
| }
 | |
| /*
 | |
|  */
 | |
| BOOLEAN is_num_bit(unsigned int number,char *storage,STATUS status) {
 | |
|   if ( number >= 8 ) {
 | |
|     storage++;
 | |
|     number=number-8; // =-8
 | |
|   } 
 | |
|   if ( status==IN )
 | |
|     return BITMAP_member(*storage,number);
 | |
|   else
 | |
|     return !BITMAP_member(*storage,number);
 | |
| }
 | |
| /*
 | |
|  *
 | |
|  */
 | |
| static void set_quadrant(RL_Node *node,short quadrant,QUADRANT_STATUS status){
 | |
| 
 | |
|   switch(quadrant){
 | |
|   case 1:
 | |
|     node->i_node.quadrant_1=status;
 | |
|     break;
 | |
|   case 2:
 | |
|     node->i_node.quadrant_2=status;
 | |
|     break;
 | |
|   case 3:
 | |
|     node->i_node.quadrant_3=status;
 | |
|     break;
 | |
|   case 4:
 | |
|     node->i_node.quadrant_4=status;
 | |
|     break;
 | |
|   default:
 | |
|     fprintf(stderr,"ERROR: set_quadrant: invalid quadrant %d(%d)\n",quadrant,status);
 | |
|   }
 | |
| }
 | |
| /*
 | |
|  *
 | |
|  */
 | |
| static QUADRANT_STATUS quadrant_status(RL_Node *node,short  quadrant){
 | |
| 
 | |
|   switch(quadrant){
 | |
|   case 1:
 | |
|     return node->i_node.quadrant_1;
 | |
|   case 2:
 | |
|     return node->i_node.quadrant_2;
 | |
|   case 3:
 | |
|     return node->i_node.quadrant_3;
 | |
|   case 4:
 | |
|     return node->i_node.quadrant_4;
 | |
|   default:
 | |
|     fprintf(stderr,"ERROR: quadrant_status: invalid quadrant(%d)\n",quadrant);
 | |
|   }
 | |
|   return 0;
 | |
| }
 | |
| /*
 | |
|  *
 | |
|  *
 | |
|  */
 | |
| static BOOLEAN in_leaf(NUM number,RL_Tree *tree,NUM node,NUM node_num,NUM max) {
 | |
| 
 | |
|   if(is_num_bit(number-node_num,(char*)NODE(tree,node),IN))
 | |
|       return TRUE;
 | |
|   return FALSE;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  *
 | |
|  *
 | |
|  */
 | |
| BOOLEAN in_tree(NUM number,RL_Tree *tree,NUM node,NUM node_num,NUM node_interval) {
 | |
|   NUM next_node;
 | |
|   short quadrant;
 | |
|   NUM interval=node_interval;
 | |
|   NUM max=MIN(node_num+interval,tree->range_max);
 | |
|   NUM quad_min,quad_max;
 | |
| 
 | |
|   /* */
 | |
|   if ( IS_LEAF(interval))
 | |
|     // current node is a leaf
 | |
|     return in_leaf(number,tree,node,node_num,max);
 | |
|     
 | |
|   number_quadrant(number,tree,node_interval,node_num,&quadrant,&quad_min,&quad_max);
 | |
|   interval=quad_max-quad_min+1;
 | |
|   node_num=quad_min;
 | |
|   
 | |
|   if ( quadrant_status(NODE(tree,node),quadrant)==R_PARCIALLY_IN_INTERVAL ) {
 | |
|     next_node=get_quadrant_node(tree,node,quadrant,node_interval);
 | |
|     return in_tree(number,tree,next_node,node_num,interval);
 | |
|   } 
 | |
|   if ( quadrant_status(NODE(tree,node),quadrant)==R_TOTALLY_IN_INTERVAL ) 
 | |
|     return TRUE;
 | |
|   
 | |
|   return FALSE;
 | |
| }
 | |
| 
 | |
| 
 | |
| /* ************************************************************************************************* */
 | |
| /* I/O                                                                                               */
 | |
| /* ************************************************************************************************* */
 | |
| 
 | |
| /*
 | |
|  *
 | |
|  */
 | |
| static void display_leaf(RL_Tree *tree,NUM node,NUM node_num,NUM max) {
 | |
|   int i;
 | |
|   printf("|");
 | |
|   //for(i=0;i<LEAF_SIZE && node_num+i<=max;++i)
 | |
|   for(i=0;i<LEAF_SIZE ;++i)
 | |
|     if(is_num_bit(i,(char*)NODE(tree,node),IN))
 | |
|       printf(",%lu",node_num+i);
 | |
|     else
 | |
|       printf(",.");
 | |
|   printf("|");
 | |
| }
 | |
| /*
 | |
|  *
 | |
|  */
 | |
| void display_tree(RL_Tree *tree) {
 | |
|     
 | |
|   // root node
 | |
|   NUM init,max;
 | |
|   NUM next_node;
 | |
|   int i;
 | |
|   short status;
 | |
| 
 | |
|   NUM qi,tmp=0;
 | |
|   next_node=0;//tree->root;
 | |
| 
 | |
|   printf("Size:%lu -[1,%lu]\n",tree->size,tree->range_max);
 | |
|   qi=ROOT_INTERVAL(tree)/BRANCH_FACTOR;
 | |
|   //quadrant_interval(tree,1,tree->range_max,&qi);
 | |
|   for(i=1;i<=BRANCH_FACTOR;++i) {
 | |
|     tmp+=qi;
 | |
|     //
 | |
|     init=tmp-qi+1;
 | |
|     max=tmp;
 | |
|     status=quadrant_status(NODE(tree,0),i);
 | |
|     switch(status) {
 | |
|     case R_PARCIALLY_IN_INTERVAL:
 | |
|       next_node=get_quadrant_node(tree,ROOT(tree),i,qi*BRANCH_FACTOR);
 | |
|       idisplay_tree(tree,next_node,init,qi,max);
 | |
|       break;
 | |
|     case R_TOTALLY_IN_INTERVAL:
 | |
|       printf(",[%lu-%lu]",init,MIN(max,tree->range_max));
 | |
|       break;
 | |
|     case R_IGNORE: 
 | |
|       break;
 | |
|     default: 
 | |
|       /*  not in */
 | |
|       printf(",]%lu-%lu[",init,MIN(max,tree->range_max));
 | |
|     }
 | |
|   }
 | |
|   printf("\n");
 | |
| }
 | |
| /*
 | |
|  *
 | |
|  *
 | |
|  */
 | |
| void idisplay_tree(RL_Tree *tree,NUM node,NUM node_num,NUM interval,NUM max) {
 | |
|   NUM next_node;
 | |
|   short quadrant;
 | |
|   NUM interval2;
 | |
|   NUM node_num2;
 | |
|   NUM quadrant_max;
 | |
|   short status;
 | |
| 
 | |
|   if ( IS_LEAF(interval) )
 | |
|     return display_leaf(tree,node,node_num,MIN(max,tree->range_max));
 | |
|    
 | |
|   interval2=NEXT_INTERVAL(interval);
 | |
|   //
 | |
|   for(quadrant=1;quadrant<=BRANCH_FACTOR;++quadrant){
 | |
|     node_num2=node_num+(quadrant-1)*interval2;
 | |
|     quadrant_max=QUADRANT_MAX_VALUE(node_num,quadrant,interval2,max);
 | |
|     status=quadrant_status(NODE(tree,node),quadrant);
 | |
|     switch(status) {
 | |
|     case R_PARCIALLY_IN_INTERVAL:
 | |
|       next_node=get_quadrant_node(tree,node,quadrant,interval);
 | |
|       if ( IS_LEAF(interval2) )
 | |
| 	display_leaf(tree,next_node,node_num2,MIN(quadrant_max,tree->range_max));
 | |
|       else 
 | |
| 	idisplay_tree(tree,next_node,node_num2,interval2,quadrant_max);
 | |
|       break;
 | |
|     case R_TOTALLY_IN_INTERVAL:
 | |
|       printf(",[%lu-%lu]",node_num2,MIN(node_num2+interval2-1,max));
 | |
|       break;
 | |
|     case R_IGNORE:
 | |
|       break;
 | |
|     default:
 | |
|       printf(",]%lu-%lu[",node_num2,MIN(tree->range_max,node_num2+interval2-1));
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| /* *************************************************************************************************** */
 | |
| static NUM next_in_leaf(RL_Tree *tree,NUM node,NUM node_num,NUM max,NUM min) {
 | |
|   NUM number;
 | |
|   number=node_num;
 | |
|   if ( number<min) number=min;
 | |
|   //fprintf(stderr,"next_in_leaf:[%lu,%lu]:min=%lu-->number=%lu\n",node_num,max,min,number);
 | |
|   for (;number<=max;++number)
 | |
|     if(is_num_bit(number-node_num,(char*)NODE(tree,node),IN)) {
 | |
|       //fprintf(stdout,"next_in_leaf:[%lu,%lu]:min=%lu>>>>number=%lu\n",node_num,max,min,number);
 | |
|       return number;
 | |
|     }
 | |
|   //fprintf(stderr,"!next_in_leaf:[%lu,%lu]:min=%lu-->number=%lu\n",node_num,max,min,number);
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Find next element bigger than min
 | |
|  *
 | |
|  */
 | |
| NUM next_min(RL_Tree *tree,NUM node,NUM node_num,NUM interval,NUM max,NUM min) {
 | |
|   NUM next_node;
 | |
|   short quadrant;
 | |
|   NUM interval2;
 | |
|   NUM node_num2;
 | |
|   NUM quadrant_max;
 | |
|   short status;
 | |
|   
 | |
|   if ( min > tree->range_max ) return 0;
 | |
|   if ( IS_LEAF(interval) )
 | |
|     return next_in_leaf(tree,node,node_num,MIN(max,tree->range_max),min);
 | |
|    
 | |
|   interval2=NEXT_INTERVAL(interval);
 | |
|   //
 | |
|   for(quadrant=1;quadrant<=BRANCH_FACTOR;++quadrant){
 | |
|     NUM found;
 | |
|     node_num2=node_num+(quadrant-1)*interval2;
 | |
|     quadrant_max=QUADRANT_MAX_VALUE(node_num,quadrant,interval2,max);
 | |
|     //------------------------------------------
 | |
|     status=quadrant_status(NODE(tree,node),quadrant);
 | |
|     switch(status) {
 | |
|     case R_PARCIALLY_IN_INTERVAL:
 | |
|       next_node=get_quadrant_node(tree,node,quadrant,interval);
 | |
|       found=next_min(tree,next_node,node_num2,interval2,quadrant_max,min);
 | |
|       if ( found>0) return found;
 | |
|       break;
 | |
|     case R_TOTALLY_IN_INTERVAL:
 | |
|       if (min<=quadrant_max && min>=node_num2)
 | |
| 	return min;
 | |
|       if ( min < node_num2 ) return node_num2;
 | |
|     }
 | |
|     
 | |
|   }
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| /* *******************************************************************************************************/
 | |
| /*
 | |
|  * 
 | |
|  */
 | |
| void intersect_leafs(char *storage1,char *storage2) {
 | |
|   
 | |
|   BITMAP_difference(*storage1,*storage1,*storage2);
 | |
|   storage1++;  storage2++;
 | |
|   BITMAP_difference(*storage1,*storage1,*storage2);
 | |
| }
 | |
| /*
 | |
|  * Removes the elements in tree1 that are in tree2
 | |
|  *
 | |
|  */
 | |
| /*NUM tree_minus(RL_Tree *tree1,RL_Tree *tree2,NUM node1,NUM node2,NUM node_num,NUM interval,NUM max) {
 | |
|   NUM next_node1,next_node2;
 | |
|   short quadrant;
 | |
|   NUM interval2;
 | |
|   NUM node_num2;
 | |
|   NUM quadrant_max;
 | |
|   short status1,status2;
 | |
|   
 | |
|   
 | |
|   if ( IS_LEAF(interval) ) //
 | |
|     return intersect_leafs((char*)NODE(tree1,node1),(char*)NODE(tree2,node2));
 | |
|    
 | |
|   interval2=NEXT_INTERVAL(interval);
 | |
|   //
 | |
|   for(quadrant=1;quadrant<=BRANCH_FACTOR;++quadrant){
 | |
|     node_num2=node_num+(quadrant-1)*interval2;
 | |
|     quadrant_max=QUADRANT_MAX_VALUE(node_num,quadrant,interval2,max);
 | |
|     //------------------------------------------
 | |
|     status1=quadrant_status(NODE(tree1,node1),quadrant);
 | |
|     status2=quadrant_status(NODE(tree2,node2),quadrant);
 | |
|     if (status2==R_IGNORE || status2==R_NOT_IN_INTERVAL) {
 | |
|       // do nothing
 | |
|     } else if ( status2==R_TOTALLY_IN_INTERVAL && (status1==R_IGNORE || status1==R_NOT_IN_INTERVAL )) {
 | |
|       // do nothing
 | |
|     } else if ( status2==R_TOTALLY_IN_INTERVAL && status1==R_TOTALLY_IN_INTERVAL ) {
 | |
|       //  delete entire quadrant subtree in tree1
 | |
|     } else if ( status2==R_PARTIALLY_IN_INTERVAL && status1==R_PARTIALLY_IN_INTERVAL){
 | |
|       // call same function
 | |
|       next_node1=get_quadrant_node(tree1,node1,quadrant,interval);
 | |
|       next_node2=get_quadrant_node(tree1,node2,quadrant,interval);
 | |
|       tree_minus(tree1,tree2,next_node1,next_node2,node_num2,interval2,quadrant_max);
 | |
|     } else if ( status2==R_PARTIALLY_IN_INTERVAL && status1==R_TOTALLY_IN_INTERVAL) {
 | |
|       // foreach element of tree2, remove it in tree1
 | |
|       
 | |
|     } else {
 | |
|       // this should never happen!!!!
 | |
|     }
 | |
|     switch(status) {
 | |
|     case R_PARCIALLY_IN_INTERVAL:
 | |
|       next_node=get_quadrant_node(tree,node,quadrant,interval);
 | |
|       found=next_min(tree,next_node,node_num2,interval2,quadrant_max,min);
 | |
|       if ( found>0) return found;
 | |
|       break;
 | |
|     case R_TOTALLY_IN_INTERVAL:
 | |
|       if (min<=quadrant_max && min>=node_num2)
 | |
| 	return min;
 | |
|       if ( min < node_num2 ) return node_num2;
 | |
|     }
 | |
|     
 | |
|   }
 | |
|   return 0;
 | |
| }*/
 | |
| /* *************************************************************************************************** */
 | |
| // root level
 | |
| static NUM norm_tree_size(NUM interval){
 | |
|   NUM tmp;
 | |
|   NUM j=BRANCH_FACTOR;;
 | |
| 
 | |
|   if ( interval<= LEAF_SIZE*BRANCH_FACTOR) return LEAF_SIZE;
 | |
|   while(1) {
 | |
|     tmp=LEAF_SIZE*j;
 | |
|     if ( tmp * BRANCH_FACTOR >= interval )break;
 | |
|     j*=BRANCH_FACTOR;;
 | |
|   }
 | |
|   return tmp;
 | |
| }
 | |
| //
 | |
| static void root_intervals(RL_Tree* tree) {
 | |
|    NUM first_i;
 | |
| 
 | |
|   first_i=norm_tree_size(tree->range_max);
 | |
|   //k=tree->range_max/first_i+1; // number of large intervals
 | |
|   
 | |
|   tree->root_i=first_i;
 | |
| 
 | |
|   if (   tree->root_i*BRANCH_FACTOR < tree->range_max ) {
 | |
|     tree->root_i=tree->root_i*BRANCH_FACTOR;
 | |
|     //printf("%lu---->>%lu\n",tree->range_max,tree->root_i);
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 |