/**********************************************************************
This file is part of Crack dot Com's free source code release of
Golgotha.
for
information about compiling & licensing issues visit this URL
If that doesn't help, contact Jonathan Clark at
golgotha_source@usa.net (Subject should have "GOLG" in it)
***********************************************************************/
//{{{ Numeric Interval template
//
// Allows the manipulation of numeric closed intervals, or the union of
// all numbers that fall between pairs of numbers, inclusively.
//
//Usage:
// Instantiate the template on a numeric type
// Add intervals using 'add_interval', which also returns whether the specified
// interval was not contained
// Test for containment using 'contains'
// Reset the interval with 'clear'
//
// To allow for printing of the interval list, define 'DEBUG_INTERVAL' and
// use 'print' in the debugger.
//
//$Id: interval.hh,v 1.4 1996/09/03 05:12:19 oliy Exp $
//}}}
#include "arch.hh"
#include "math/num_type.hh"
template
class i4_interval_template
{
protected:
class interval_node;
typedef interval_node *interval_link;
class interval_node
//{{{
{
friend class i4_interval_template;
protected:
interval_link left, right;
public:
T min, max;
interval_node() : left(0), right(0) {}
interval_node(T _min, T _max)
: min(_min), max(_max), left(0), right(0) {}
~interval_node() { delete left; delete right; }
};
//}}}
interval_link root;
interval_link *find_interval(T val, interval_link *pp)
//{{{
{
interval_link p;
while ((p = *pp)!=0)
{
if (valmin)
pp = &p->left;
else if (val>p->max)
pp = &p->right;
else
return pp;
}
return pp;
}
//}}}
i4_bool recurse_combine(interval_link *pp,
T min,
T max,
interval_link replace)
//{{{
{
interval_link p = *pp;
if (!p)
{
if (!replace)
{
*pp = new interval_node(min,max);
return 1;
}
else
return 0;
}
if (maxmin)
// interval totally to the left of me
recurse_combine(&p->left,min,max,replace);
else if (min>p->max)
// interval totally to the right of me
recurse_combine(&p->right,min,max,replace);
else
{
// interval touches me
T local_min, local_max;
if (min<=p->min)
// can possibly combine more to the left
recurse_combine(&p->left,min,max,p);
if (max>=p->max)
// can possibly combine more to the right
recurse_combine(&p->right,min,max,p);
local_min = (min < p->min)? min : p->min;
local_max = (max > p->max)? max : p->max;
if (replace)
{
// combine me into my ancestor
replace->min = (local_min < replace->min)? local_min : replace->min;
replace->max = (local_max > replace->max)? local_max : replace->max;
delete p;
*pp = 0;
}
else
{
// combine interval with me
p->min = local_min;
p->max = local_max;
}
}
return 0;
}
//}}}
//{{{ Debugging Tools
#ifdef DEBUG_INTERVAL
void print_tree(interval_link tree)
//{{{
{
if (!tree)
return;
print_tree(tree->left);
printf("[%f %f]\n",tree->min,tree->max);
print_tree(tree->right);
}
//}}}
#endif
#ifdef DEBUG_INTERVAL
public:
void print()
//{{{
{
print_tree(root);
}
//}}}
protected:
#endif
//}}}
public:
i4_interval_template() : root(0) {}
i4_bool contains(T val)
//{{{
{
return (*find_interval(val,&root) != 0);
}
//}}}
i4_bool add_interval(T min, T max)
//{{{
{
return recurse_combine(&root,min,max,0);
}
//}}}
void clear()
//{{{
{
if (root)
delete root;
root = 0;
}
//}}}
};
//{{{ Emacs Locals
// Local Variables:
// folded-file: t
// End:
//}}}