RL-Trees module.

git-svn-id: https://yap.svn.sf.net/svnroot/yap/trunk@2169 b08c6af1-5177-4d33-ba66-4b1c6b8b522a
This commit is contained in:
nunofonseca 2008-03-26 23:05:22 +00:00
parent bee5cd8c0b
commit 48f393bedf
5 changed files with 1649 additions and 0 deletions

21
library/rltree.yap Normal file
View File

@ -0,0 +1,21 @@
/****************************************
File: rltree.yap
Author: Nuno A. Fonseca
Comments: Range-List (RL) tree data structure implementation for YAP
version: $Id: rltree.yap,v 1.1 2008-03-26 23:05:22 nunofonseca Exp $
****************************************/
:- module(rltree, [
rl_new/2, %% (+Maximum Interval value, -Range-List Id)
rl_free/1, %% (+Range-List Id)
rl_size/2, %% (+Range-List Id,-Size in bytes)
rl_copy/2, %% (+Range-List Id,-New Range-List Id) - copies one rl_tree
rl_set_out/2, %%(+Range-List Id,+Number) - removes Number from the range-list
rl_in/2, %%(+Range-List Id,?Number) - checks if a number is in the rl-tree
rl_set_in/2, %%(+Range-List Id,+Number)
rl_set_all_in/1,%%(+Range-List Id)
rl_print/1, %%(+Range-List Id)
rl_freeze/1 %%(+Range-List Id)
]).
:- load_foreign_files([yap_rl], [], init_rl).

View File

@ -0,0 +1,69 @@
#
# default base directory for YAP installation
# (EROOT for architecture-dependent files)
#
#
# default base directory for YAP installation
# (EROOT for architecture-dependent files)
#
prefix = @prefix@
ROOTDIR = $(prefix)
EROOTDIR = @exec_prefix@
#
# where the binary should be
#
BINDIR = $(EROOTDIR)/bin
#
# where YAP should look for libraries
#
LIBDIR=$(EROOTDIR)/lib/Yap
#
#
CC=@CC@
MPI_CC=mpicc
CFLAGS= @CFLAGS@ $(YAP_EXTRAS) $(DEFS) -I$(srcdir) -I../.. -I$(srcdir)/../../include
#
#
# You shouldn't need to change what follows.
#
INSTALL=@INSTALL@
INSTALL_DATA=@INSTALL_DATA@
INSTALL_PROGRAM=@INSTALL_PROGRAM@
SHELL=/bin/sh
RANLIB=@RANLIB@
srcdir=@srcdir@
SHLIB_CFLAGS=@SHLIB_CFLAGS@
SHLIB_SUFFIX=@SHLIB_SUFFIX@
#
OBJS=yap_rl.o range_list.o
#in some systems we just create a single object, in others we need to
# create a libray
all: $(SOBJS)
yap_rl.so: yap_rl.c range_list.o
$(CC) $(CFLAGS) -c yap_rl.c
ld $(LDFLAGS) -o yap_rl.so yap_rl.o range_list.o
range_list.o: $(srcdir)/range_list.c $(srcdir)/range_list.h
$(CC) -c $(CFLAGS) $(SHLIB_CFLAGS) $(srcdir)/range_list.c -o range_list.o
yap_rl.o: $(srcdir)/yap_rl.c
$(CC) -c $(CFLAGS) $(SHLIB_CFLAGS) $(srcdir)/yap_rl.c -o yap_rl.o
@DO_SECOND_LD@%@SHLIB_SUFFIX@: %.o
@DO_SECOND_LD@ @SHLIB_LD@ -o $@ $<
@DO_SECOND_LD@yap_mpi@SHLIB_SUFFIX@: $(OBJS)
@DO_SECOND_LD@ @SHLIB_LD@ $(MPILDF) -o yap_rl@SHLIB_SUFFIX@ $(OBJS)
install: all
@if test "$(SOBJS)" = "no"; then echo ""; else $(INSTALL_PROGRAM) $(SOBJS) $(DESTDIR)$(LIBDIR); fi
clean:
rm -f *.o *~ $(OBJS) $(SOBJS) *.BAK
no:
@echo "YAP RL module not compiled."

947
library/rltree/range_list.c Normal file
View File

@ -0,0 +1,947 @@
/*******************************************************************************************
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);
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);
}
}

166
library/rltree/range_list.h Normal file
View File

@ -0,0 +1,166 @@
/*******************************************************************************************
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.h,v 1.1 2008-03-26 23:05:22 nunofonseca Exp $
**************************************************************************/
/*
Leaf
Each leaf uses 16 bits ( each bit represents one number )
*/
#define NUM unsigned long
/*
Node
Each node (non leaf) uses 8 bits.
- 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
An extra byte is used to keep the number of nodes in the subtrees.
*/
struct s_node {
//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;
};
typedef enum { R_TOTALLY_IN_INTERVAL=3, R_PARCIALLY_IN_INTERVAL=2, R_NOT_IN_INTERVAL=0, R_IGNORE=1} QUADRANT_STATUS;
#define BRANCH_FACTOR 4 /* factor of division of the range */
#define LEAF_SIZE 16 /* how many numbers are represented by a leaf */
#define NODE_SIZE sizeof(RL_Node)
#define NODE(tree,idx) (RL_Node*)&tree->root[idx]
#define ROOT(tree) 0
#define IS_ROOT(tree,interval) (tree->range_max<=interval)
#define ROOT_INTERVAL(tree) (tree->root_i*BRANCH_FACTOR)
#define MIN(a,b) ((a<b)?a:b)
#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
#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
#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
// returns the maximum number that a quadrant stores
#define QUADRANT_MAX_VALUE(node_num,quadrant,quadrant_interval,max) (MIN(node_num+quadrant_interval*quadrant-1,max))
// returns the interval size for the next level in the tree
#define NEXT_INTERVAL(interval) ((interval<=LEAF_SIZE*BRANCH_FACTOR)?LEAF_SIZE:interval/BRANCH_FACTOR+interval%BRANCH_FACTOR)
#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)
#define REALLOC_MEM(tree) (tree->mem_alloc < (tree->size+1)*NODE_SIZE)
#define MEM_SIZE(tree) (tree->size+2)*NODE_SIZE
#define TREE_SIZE(tree) tree->mem_alloc+sizeof(RL_Tree)
typedef union {
struct s_node i_node;
unsigned short int leaf;
} RL_Node; /* A node is a internal node (inode) or a leaf depending on their depth in the tree */
/*
Range_List
Contains the root node, max range size,
*/
struct rl_struct {
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
};
typedef struct rl_struct RL_Tree;
/* Buffer */
struct s_buffer {
RL_Node* root_node;
unsigned long size; // memory (in bytes) allocated for root_node
};
typedef struct s_buffer RL_Buffer;
//----------------------------------------------------------------
// Bits operations
#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))))
#
//----------------------------------------------------------------
typedef enum { TRUE=1, FALSE=0} BOOLEAN;
typedef enum { IN=1, OUT=0} STATUS;
//
#define BUFFER_SIZE 1000
/* ********************************************************************************** */
/* API */
RL_Tree* new_rl(NUM max_size);
RL_Tree* copy_rl(RL_Tree *tree);
void free_rl(RL_Tree* range);
void rl_all(RL_Tree* tree,STATUS status);
void display_tree(RL_Tree *tree);
RL_Tree* set_in_rl(RL_Tree* tree,NUM number,STATUS status);
BOOLEAN in_rl(RL_Tree* range,NUM number);
BOOLEAN freeze_rl(RL_Tree* tree); /* write operations on the range are finishe */
RL_Tree* intersect_rl(RL_Tree* range1,RL_Tree* range2);
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)

446
library/rltree/yap_rl.c Normal file
View File

@ -0,0 +1,446 @@
/*******************************************************************************************
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: yap_rl.c,v 1.1 2008-03-26 23:05:22 nunofonseca Exp $
**************************************************************************/
#include <time.h>
#include <stdio.h>
#include "range_list.h"
#include <YapInterface.h>
#define IDTYPE long
#define PTR2ID(ptr) (IDTYPE)ptr
#define ID2PTR(id) (RL_Tree*)id
/* ############################################################ */
unsigned long int memory_usage=0;
unsigned long int tree_mem=0;
#define STORE_TREE_SIZE(tree) tree_mem=tree->mem_alloc
#define UPDATE_MEM_USAGE(tree) memory_usage+=(tree->mem_alloc>0?tree->mem_alloc-tree_mem:0)
#define FREE_MEM_USAGE(tree) (memory_usage-=tree->mem_alloc)
#define ADD_MEM_USAGE(tree) (memory_usage+=tree->mem_alloc)
/*
*/
static
int
p_rl_new(void) {
YAP_Term t1=YAP_Deref(YAP_ARG1);
YAP_Term t2=YAP_Deref(YAP_ARG2);
RL_Tree* new_tree;
IDTYPE newid;
// Check args
if (!YAP_IsIntTerm(t1) || !YAP_IsVarTerm(t2)) {
fprintf(stderr,"Error in rl_new arguments\n");
return(FALSE);
}
//
new_tree=new_rl(YAP_IntOfTerm(t1));
if(new_tree==NULL) {
fprintf(stderr,"Error creating new rl.");
return (FALSE);
}
//printf("New rl %d %p--%u\n",PTR2ID(new_tree),new_tree,(int)new_tree,YAP_IntOfTerm(t1));
// return reference
newid=YAP_MkIntTerm(PTR2ID(new_tree));
if(!YAP_Unify(YAP_Deref(YAP_ARG2),newid))
return (FALSE);
return(TRUE);
}
/*
*
*
*/
static
int
p_rl_copy(void) {
YAP_Term t1=YAP_Deref(YAP_ARG1); // src
YAP_Term t2=YAP_Deref(YAP_ARG2); // dest
RL_Tree* new_tree;
IDTYPE id1,newid;
RL_Tree* tree;
// Check args
if (!YAP_IsIntTerm(t1))
return(FALSE);
if (!YAP_IsVarTerm(t2))
return(FALSE);
//
id1=YAP_IntOfTerm(t1);
tree=ID2PTR(id1);
new_tree=copy_rl(tree);
if(new_tree==NULL) {
fprintf(stderr,"Error creating new rl.");
return (FALSE);
}
//
#ifdef STATS
ADD_MEM_USAGE(new_tree);
#endif
// return list reference
newid=YAP_MkIntTerm(PTR2ID(new_tree));
if(!YAP_Unify(YAP_Deref(YAP_ARG2),newid))
return (FALSE);
return(TRUE);
}
/*
*
*
*/
static
int
p_rl_size(void) {
YAP_Term t1=YAP_Deref(YAP_ARG1),t2=YAP_Deref(YAP_ARG2),t_size;
IDTYPE id;
RL_Tree* tree;
unsigned int size;
if (YAP_IsVarTerm(t1))
return(FALSE);
id = YAP_IntOfTerm(t1);
tree=ID2PTR(id);
size=tree->size*sizeof(RL_Node)+sizeof(RL_Tree);
t_size=YAP_MkIntTerm(size);
if(!YAP_Unify(YAP_Deref(YAP_ARG2),t_size) )
return (FALSE);
return(TRUE);
}
/*
*
*
*/
static
int
p_rl_mem_usage(void) {
YAP_Term t1=YAP_Deref(YAP_ARG1);
if(!YAP_Unify(t1,YAP_MkIntTerm(memory_usage)) )
return (FALSE);
return(TRUE);
}
/*
*/
static
int
p_rl_free(void) {
YAP_Term t1=YAP_Deref(YAP_ARG1);
IDTYPE id;
RL_Tree* tree;
// Check args
if (YAP_IsVarTerm(t1))
return(FALSE);
id=YAP_IntOfTerm(t1);
tree=ID2PTR(id);
#ifdef STATS
FREE_MEM_USAGE(tree);
#endif
free_rl(tree);
return (TRUE);
}
/*
*
*
*/
static
int
p_rl_set_in(void) {
YAP_Term t1=YAP_Deref(YAP_ARG1);
YAP_Term t2=YAP_Deref(YAP_ARG2);
IDTYPE id;
NUM val;
RL_Tree *tree;
// Check args
if (YAP_IsVarTerm(t1) || YAP_IsVarTerm(t2) )
return(FALSE);
id = YAP_IntOfTerm(t1);
val = YAP_IntOfTerm(t2);
tree=ID2PTR(id);
#ifdef STATS
STORE_TREE_SIZE(tree);
set_in_rl(tree,val,IN);
UPDATE_MEM_USAGE(tree);
#else
set_in_rl(tree,val,IN);
#endif
return (TRUE);
}
/*
*
*
*/
static
int
p_rl_in(void) {
YAP_Term t1=YAP_Deref(YAP_ARG1);
YAP_Term t2=YAP_Deref(YAP_ARG2);
IDTYPE id;
NUM val;
RL_Tree *tree;
// Check args
if (YAP_IsVarTerm(t1) || YAP_IsVarTerm(t2) )
return(FALSE);
id = YAP_IntOfTerm(t1);
val = YAP_IntOfTerm(t2);
tree=ID2PTR(id);
if ( in_rl(tree,val) )
return (TRUE);
return (FALSE);
}
/*
*
*
*/
static
int
p_rl_set_out(void) {
YAP_Term t1=YAP_Deref(YAP_ARG1);
YAP_Term t2=YAP_Deref(YAP_ARG2);
IDTYPE id;
NUM val;
RL_Tree *tree;
// Check args
if (YAP_IsVarTerm(t1) || YAP_IsVarTerm(t2) )
return(FALSE);
id = YAP_IntOfTerm(t1);
val = YAP_IntOfTerm(t2);
tree=ID2PTR(id);
#ifdef STATS
STORE_TREE_SIZE(tree);
set_in_rl(tree,val,OUT);
UPDATE_MEM_USAGE(tree);
#else
set_in_rl(tree,val,OUT);
#endif
return (TRUE);
}
/*
*
*
*/
static
int
p_rl_freeze(void) {
YAP_Term t1=YAP_Deref(YAP_ARG1);
IDTYPE id;
RL_Tree *tree;
// Check args
if (YAP_IsVarTerm(t1) )
return(FALSE);
id = YAP_IntOfTerm(t1);
tree=ID2PTR(id);
#ifdef STATS
STORE_TREE_SIZE(tree);
freeze_rl(tree);
UPDATE_MEM_USAGE(tree);
#else
freeze_rl(tree);
#endif
return (TRUE);
}
/*
*
*
*/
static
int
p_rl_set_all_in(void) {
YAP_Term t1=YAP_Deref(YAP_ARG1);
IDTYPE id;
RL_Tree *tree;
// Check args
if (YAP_IsVarTerm(t1) )
return(FALSE);
id = YAP_IntOfTerm(t1);
tree=ID2PTR(id);
#ifdef STATS
STORE_TREE_SIZE(tree);
rl_all(tree,IN);
freeze_rl(tree);
UPDATE_MEM_USAGE(tree);
#else
rl_all(tree,IN);
freeze_rl(tree);
#endif
return (TRUE);
}
/*
*
*
*/
static
int
p_rl_print(void) {
YAP_Term t1=YAP_Deref(YAP_ARG1);
IDTYPE id;
RL_Tree *tree;
// Check args
if (YAP_IsVarTerm(t1) ) {
fprintf(stderr,"Error printing tree..");
return(FALSE);
}
id = YAP_IntOfTerm(t1);
tree=ID2PTR(id);
display_tree(tree);
return (TRUE);
}
/* ==============================================================================
*
*
*/
typedef struct {
YAP_Term last_solution; /* the last solution */
} yap_back_data_type;
yap_back_data_type *back_data;
/*
*
*
*/
static
int
p_rl_b_in2(void) {
YAP_Term t1=YAP_Deref(YAP_ARG1);
YAP_Term t2=YAP_Deref(YAP_ARG2);
IDTYPE id;
NUM val;
RL_Tree *tree;
YAP_PRESERVED_DATA(back_data,yap_back_data_type);
id = YAP_IntOfTerm(t1);
tree=ID2PTR(id);
val=YAP_IntOfTerm(back_data->last_solution);
val=rl_next_in_bigger(tree,val);
if ( val > 0 && YAP_Unify(YAP_Deref(YAP_ARG2),YAP_MkIntTerm(val))) {
back_data->last_solution=YAP_MkIntTerm(val);
return TRUE;
}
YAP_cut_fail();
return (FALSE);
}
static
int
p_rl_b_in1(void) {
YAP_Term t1=YAP_Deref(YAP_ARG1);
YAP_Term t2=YAP_Deref(YAP_ARG2);
IDTYPE id;
NUM val;
RL_Tree *tree;
// Check args
if (!YAP_IsIntTerm(t1)) {
YAP_cut_fail();
return(FALSE);
}
if ( YAP_IsVarTerm(t2) ) {
// return all in through backtracking
YAP_PRESERVE_DATA(back_data,yap_back_data_type);
back_data->last_solution = YAP_MkIntTerm(0);
return p_rl_b_in2();
} else {
id = YAP_IntOfTerm(t1);
tree=ID2PTR(id);
val = YAP_IntOfTerm(t2);
if ( in_rl(tree,val) ) {
YAP_cut_succeed();
return (TRUE);
}
YAP_cut_fail();
return (FALSE);
}
}
/* ******************************************************* */
void init_rl(){
YAP_UserCPredicate("rl_new", p_rl_new,2); // Maximum -> RangeID
YAP_UserCPredicate("rl_free", p_rl_free,1); // RangeId ->
YAP_UserCPredicate("rl_size", p_rl_size,2); // RangeId -> Size (in bytes)
YAP_UserCPredicate("rl_mem", p_rl_mem_usage,1); // -> TotalMemory (in bytes)
YAP_UserCPredicate("rl_copy", p_rl_copy,2); // RangeId -> NewRangeId
YAP_UserCPredicate("rl_set_out", p_rl_set_out,2);// RangeId x Number ->
YAP_UserBackCPredicate("rl_in", p_rl_b_in1,p_rl_b_in2,2,sizeof(yap_back_data_type)); // +RangeId x ?Number
//YAP_UserCPredicate("rl_in", p_rl_in,2); // RangeId x Number ->
YAP_UserCPredicate("rl_set_in", p_rl_set_in,2); // RangeIdxNumber ->
YAP_UserCPredicate("rl_set_all_in", p_rl_set_all_in,1); // RangeId ->
YAP_UserCPredicate("rl_print", p_rl_print,1); // RangeId ->
YAP_UserCPredicate("rl_freeze", p_rl_freeze,1); // RangeId
// fprintf(stderr,"Range list module succesfully loaded.");
//fflush(stderr);
}