| 
									
										
										
										
											2008-03-26 23:05:22 +00:00
										 |  |  | /*******************************************************************************************
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-01 23:25:58 +01:00
										 |  |  | Copyright (C) 2004,2005,2006,2007,2008 (Nuno A. Fonseca) | 
					
						
							|  |  |  | <nuno.fonseca@gmail.com> | 
					
						
							| 
									
										
										
										
											2008-03-26 23:05:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-01 23:25:58 +01:00
										 |  |  | 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 | 
					
						
							| 
									
										
										
										
											2008-03-26 23:05:22 +00:00
										 |  |  | 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.h,v 1.1 2008-03-26 23:05:22 nunofonseca Exp $ | 
					
						
							|  |  |  | **************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-01 23:25:58 +01:00
										 |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2018-05-02 17:04:14 +01:00
										 |  |  |  * @file range_list.h | 
					
						
							| 
									
										
										
										
											2018-05-01 23:25:58 +01:00
										 |  |  |  * | 
					
						
							|  |  |  |  *  range list core data-structures. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * @namespace rltree | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2008-03-26 23:05:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |   Leaf | 
					
						
							|  |  |  |   Each leaf uses 16 bits ( each bit represents one number ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | #define NUM unsigned long
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |   Node | 
					
						
							| 
									
										
										
										
											2018-05-01 23:25:58 +01:00
										 |  |  |   Each node (non leaf) uses 8 bits. | 
					
						
							| 
									
										
										
										
											2008-03-26 23:05:22 +00:00
										 |  |  |   - 8 bits are used to represent the state of the 4 subtrees ( subranges ). | 
					
						
							|  |  |  |   - 2 bits are used to represent the state for each subtreee | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   States of a subtree: | 
					
						
							|  |  |  |     00 (0) - range not in interval | 
					
						
							|  |  |  |     11 (3)- all range in interval | 
					
						
							|  |  |  |     10 (2)- range parcially in interval | 
					
						
							| 
									
										
										
										
											2018-05-01 23:25:58 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-03-26 23:05:22 +00:00
										 |  |  |   An extra byte is used to keep the number of nodes in the subtrees. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | struct s_node { | 
					
						
							| 
									
										
										
										
											2018-05-01 23:25:58 +01:00
										 |  |  |   // short quadrant;
 | 
					
						
							|  |  |  |   unsigned short int quadrant_1 : 2; //
 | 
					
						
							|  |  |  |   unsigned short int quadrant_2 : 2; | 
					
						
							|  |  |  |   unsigned short int quadrant_3 : 2; | 
					
						
							|  |  |  |   unsigned short int quadrant_4 : 2; | 
					
						
							|  |  |  |   unsigned short int num_subnodes : 8; | 
					
						
							| 
									
										
										
										
											2008-03-26 23:05:22 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-01 23:25:58 +01:00
										 |  |  | typedef enum { | 
					
						
							|  |  |  |   R_TOTALLY_IN_INTERVAL = 3, | 
					
						
							|  |  |  |   R_PARCIALLY_IN_INTERVAL = 2, | 
					
						
							|  |  |  |   R_NOT_IN_INTERVAL = 0, | 
					
						
							|  |  |  |   R_IGNORE = 1 | 
					
						
							|  |  |  | } QUADRANT_STATUS; | 
					
						
							| 
									
										
										
										
											2008-03-26 23:05:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-01 23:25:58 +01:00
										 |  |  | #define BRANCH_FACTOR 4 /* factor of division of the range */
 | 
					
						
							|  |  |  | #define LEAF_SIZE 16    /* how many numbers are represented by a leaf */
 | 
					
						
							| 
									
										
										
										
											2008-03-26 23:05:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #define NODE_SIZE sizeof(RL_Node)
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-01 23:25:58 +01:00
										 |  |  | #define NODE(tree, idx) (RL_Node *)&tree->root[idx]
 | 
					
						
							| 
									
										
										
										
											2008-03-26 23:05:22 +00:00
										 |  |  | #define ROOT(tree) 0
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-01 23:25:58 +01:00
										 |  |  | #define IS_ROOT(tree, interval) (tree->range_max <= interval)
 | 
					
						
							|  |  |  | #define ROOT_INTERVAL(tree) (tree->root_i * BRANCH_FACTOR)
 | 
					
						
							| 
									
										
										
										
											2008-03-26 23:05:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-01 23:25:58 +01:00
										 |  |  | #define MIN(a, b) ((a < b) ? a : b)
 | 
					
						
							| 
									
										
										
										
											2008-03-26 23:05:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-01 23:25:58 +01:00
										 |  |  | #define ON_BITS(n) (active_bits[n - 1]) // mask to check if bits until n are in
 | 
					
						
							|  |  |  | #define SET_LEAF_IN(max, node, quad_i)                                         \
 | 
					
						
							|  |  |  |   (node.leaf =                                                                 \ | 
					
						
							|  |  |  |        ON_BITS(max - quad_i + 1)) // mask to check if bits until n are in
 | 
					
						
							| 
									
										
										
										
											2008-03-26 23:05:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-01 23:25:58 +01:00
										 |  |  | #define LEAF_ALL_IN(leaf)                                                      \
 | 
					
						
							|  |  |  |   (leaf == 65535) // return true if all numbers in leaf are IN (selected)
 | 
					
						
							|  |  |  | #define LEAF_ALL_OUT(leaf)                                                     \
 | 
					
						
							|  |  |  |   (leaf == 0) // return true if all numbers in leaf are OUT
 | 
					
						
							| 
									
										
										
										
											2008-03-26 23:05:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-01 23:25:58 +01:00
										 |  |  | #define ALL_OUT(n) memset(n, 0, NODE_SIZE)    // turn out a node
 | 
					
						
							|  |  |  | #define ALL_IN(n) memset(n, 32767, NODE_SIZE) // turn in a leaf
 | 
					
						
							|  |  |  | #define INODE_CAPACITY                                                         \
 | 
					
						
							|  |  |  |   (LEAF_SIZE * BRANCH_FACTOR) // minimum range that a inode stores
 | 
					
						
							| 
									
										
										
										
											2008-03-26 23:05:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | // returns the maximum number that a quadrant stores
 | 
					
						
							| 
									
										
										
										
											2018-05-01 23:25:58 +01:00
										 |  |  | #define QUADRANT_MAX_VALUE(node_num, quadrant, quadrant_interval, max)         \
 | 
					
						
							|  |  |  |   (MIN(node_num + quadrant_interval * quadrant - 1, max)) | 
					
						
							| 
									
										
										
										
											2008-03-26 23:05:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | // returns the interval size for the next level in the tree
 | 
					
						
							| 
									
										
										
										
											2018-05-01 23:25:58 +01:00
										 |  |  | #define NEXT_INTERVAL(interval)                                                \
 | 
					
						
							|  |  |  |   ((interval <= LEAF_SIZE * BRANCH_FACTOR)                                     \ | 
					
						
							|  |  |  |        ? LEAF_SIZE                                                             \ | 
					
						
							|  |  |  |        : interval / BRANCH_FACTOR + interval % BRANCH_FACTOR) | 
					
						
							| 
									
										
										
										
											2008-03-26 23:05:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-01 23:25:58 +01:00
										 |  |  | #define IS_LEAF(interval)                                                      \
 | 
					
						
							|  |  |  |   ((interval <= LEAF_SIZE) ? 1 : 0) // check if a interval of type Leaf
 | 
					
						
							|  |  |  | #define LAST_LEVEL_INODE(interval)                                             \
 | 
					
						
							|  |  |  |   ((interval <= LEAF_SIZE * BRANCH_FACTOR && interval > LEAF_SIZE) ? 1 : 0) | 
					
						
							| 
									
										
										
										
											2008-03-26 23:05:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-01 23:25:58 +01:00
										 |  |  | #define REALLOC_MEM(tree) (tree->mem_alloc < (tree->size + 1) * NODE_SIZE)
 | 
					
						
							|  |  |  | #define MEM_SIZE(tree) (tree->size + 2) * NODE_SIZE
 | 
					
						
							| 
									
										
										
										
											2008-03-26 23:05:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-01 23:25:58 +01:00
										 |  |  | #define TREE_SIZE(tree) tree->mem_alloc + sizeof(RL_Tree)
 | 
					
						
							| 
									
										
										
										
											2008-03-26 23:05:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | typedef union { | 
					
						
							|  |  |  |   struct s_node i_node; | 
					
						
							|  |  |  |   unsigned short int leaf; | 
					
						
							| 
									
										
										
										
											2018-05-01 23:25:58 +01:00
										 |  |  | } RL_Node; /* A node is a internal node (inode) or a leaf depending on their
 | 
					
						
							|  |  |  |               depth in the tree */ | 
					
						
							| 
									
										
										
										
											2008-03-26 23:05:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |   Range_List | 
					
						
							|  |  |  |   Contains the root node, max range size, | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | struct rl_struct { | 
					
						
							| 
									
										
										
										
											2018-05-01 23:25:58 +01:00
										 |  |  |   RL_Node *root; | 
					
						
							|  |  |  |   NUM size;      // number of nodes
 | 
					
						
							|  |  |  |   NUM mem_alloc; // memory allocated for *root
 | 
					
						
							|  |  |  |   NUM range_max; // maximum value of the interval
 | 
					
						
							|  |  |  |   NUM root_i;    // root interval
 | 
					
						
							| 
									
										
										
										
											2008-03-26 23:05:22 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | typedef struct rl_struct RL_Tree; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Buffer */ | 
					
						
							|  |  |  | struct s_buffer { | 
					
						
							| 
									
										
										
										
											2018-05-01 23:25:58 +01:00
										 |  |  |   RL_Node *root_node; | 
					
						
							| 
									
										
										
										
											2008-03-26 23:05:22 +00:00
										 |  |  |   unsigned long size; // memory (in bytes) allocated for root_node
 | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | typedef struct s_buffer RL_Buffer; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //----------------------------------------------------------------
 | 
					
						
							|  |  |  | // Bits operations
 | 
					
						
							| 
									
										
										
										
											2018-05-01 23:25:58 +01:00
										 |  |  | #define BITMAP_empty(b) ((b) == 0)
 | 
					
						
							|  |  |  | #define BITMAP_member(b, n) (((b) & (1 << (n))) != 0)
 | 
					
						
							|  |  |  | #define BITMAP_alone(b, n) ((b) == (1 << (n)))
 | 
					
						
							|  |  |  | #define BITMAP_subset(b1, b2) (((b1) & (b2)) == b2)
 | 
					
						
							|  |  |  | #define BITMAP_same(b1, b2) ((b1) == (b2))
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define BITMAP_on_all(b) ((b) = 255)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define BITMAP_clear(b) ((b) = 0)
 | 
					
						
							|  |  |  | #define BITMAP_and(b1, b2) ((b1) &= (b2))
 | 
					
						
							|  |  |  | #define BITMAP_minus(b1, b2) ((b1) &= ~(b2))
 | 
					
						
							|  |  |  | #define BITMAP_insert(b, n) ((b) |= (1 << (n)))
 | 
					
						
							|  |  |  | #define BITMAP_delete(b, n) ((b) &= (~(1 << (n))))
 | 
					
						
							|  |  |  | #define BITMAP_copy(b1, b2) ((b1) = (b2))
 | 
					
						
							|  |  |  | #define BITMAP_intersection(b1, b2, b3) ((b1) = ((b2) & (b3)))
 | 
					
						
							|  |  |  | #define BITMAP_difference(b1, b2, b3) ((b1) = ((b2) & (~(b3))))
 | 
					
						
							| 
									
										
										
										
											2008-03-26 23:05:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #
 | 
					
						
							|  |  |  | //----------------------------------------------------------------
 | 
					
						
							| 
									
										
										
										
											2018-05-01 23:25:58 +01:00
										 |  |  | typedef enum { TRUE = 1, FALSE = 0 } BOOLEAN; | 
					
						
							|  |  |  | typedef enum { IN = 1, OUT = 0 } STATUS; | 
					
						
							| 
									
										
										
										
											2008-03-26 23:05:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | #define BUFFER_SIZE 1000
 | 
					
						
							| 
									
										
										
										
											2018-05-01 23:25:58 +01:00
										 |  |  | /* **********************************************************************************
 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | /* API */ | 
					
						
							|  |  |  | extern RL_Tree *new_rl(NUM max_size); | 
					
						
							|  |  |  | extern RL_Tree *copy_rl(RL_Tree *tree); | 
					
						
							|  |  |  | extern void free_rl(RL_Tree *range); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | extern void rl_all(RL_Tree *tree, STATUS status); | 
					
						
							|  |  |  | extern void display_tree(RL_Tree *tree); | 
					
						
							|  |  |  | extern RL_Tree *set_in_rl(RL_Tree *tree, NUM number, STATUS status); | 
					
						
							|  |  |  | extern BOOLEAN in_rl(RL_Tree *range, NUM number); | 
					
						
							|  |  |  | extern BOOLEAN | 
					
						
							|  |  |  | freeze_rl(RL_Tree *tree); /* write operations on the range are finishe */ | 
					
						
							|  |  |  | extern RL_Tree *intersect_rl(RL_Tree *range1, RL_Tree *range2); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | extern NUM | 
					
						
							|  |  |  | rl_next_in_bigger(RL_Tree *tree, | 
					
						
							|  |  |  |                   NUM min); /* Returns next number in tree bigger than min */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define IS_FREEZED(tree) (tree->mem_alloc != 0)
 |