include/utilities/orderlist.hpp
author Christos Mantoulidis <cmad@stanford.edu>
Tue, 04 Aug 2009 13:23:16 -0700
branchdev
changeset 156 f75fb57d2831
parent 30 6d4e450015e4
child 208 36ea2751f290
permissions -rw-r--r--
Changed implementation of WeightedRips to store simplex values (max distance between simplices' vertices) as an invisible layer on top of each simplex object, so that the data() field of WeightedRips has been freed for use by the users again.

/* Implementations */

#ifdef LOGGING
static rlog::RLogChannel* rlOrderList = 					DEF_CHANNEL("utilities/orderlist", rlog::Log_Debug);
#endif // LOGGING

template<class T>
void 
OrderList<T>::
swap(iterator i, iterator j)
{
	typename Parent::iterator i_base = i.get_base();
	typename Parent::iterator j_base = j.get_base();
	std::swap(i_base->tag, j_base->tag);

	// Exchange the actual elements in the list --- so that iterators behave as expected
	typename Parent::iterator after_j = boost::next(j_base);	
	Parent::splice(i_base, *this, j_base);
	Parent::splice(after_j, *this, i_base);
}

template<class T>
template<class BinaryPredicate>
void 
OrderList<T>::
sort(BinaryPredicate cmp)
{
	Parent::sort(OrderListNodeComparison<T, BinaryPredicate>(cmp));
	OrderType cur_order = 0;
	for (typename Parent::iterator cur = Parent::begin(); cur != Parent::end(); ++cur)
		cur->tag = cur_order++;
}

template<class T>
typename OrderList<T>::iterator 
OrderList<T>::
push_back(const_reference x)
{
	if (empty()) 
		Parent::push_back(NodeType(x, 0));
	else
		Parent::push_back(NodeType(x, last().get_base()->tag + 1));
	
	return last();
}

template<class T>
typename OrderList<T>::iterator 
OrderList<T>::
insert(iterator p, const_reference x)
{
	typename Parent::iterator p_base = p.get_base();
	OrderType tag = (p_base++)->tag + 1;
	typename Parent::iterator new_base = Parent::insert(p_base, NodeType(x, tag));

	if (p_base->tag != tag)
		return iterator(new_base);

	// Find non-overflowing region
	unsigned int num_elements = 1, maximum = 1, lower = tag, upper = tag, level = 0;
	float inv_density = 1;
	typename Parent::iterator prev = p_base, next = p_base;
	--(--prev); ++next; 		// move prev back twice to skip over the newly inserted element

	do
	{
		lower &= ~(1 << level);
		upper |= (1 << level);
		maximum <<= 1; inv_density *= density_threshold;
		++level;

		while (prev != Parent::end() && prev->tag >= lower) { --prev; ++num_elements; }
		while (next != Parent::end() && next->tag <= upper) { ++next; ++num_elements; }
	} while (inv_density * num_elements >= maximum);
	++num_elements;			// for the extra element inserted

	rLog(rlOrderList, "%i, %i, %i", num_elements, lower, upper);
	rLog(rlOrderList, "prev is at the end: %i", (prev == Parent::end()));
	rLog(rlOrderList, "next is at the end: %i", (next == Parent::end()));
	
	// Reorder
	AssertMsg((upper - lower + 1)/num_elements > 0, "Spacing between new tags must be non-zero");
	for (unsigned int i = 0; i < num_elements; ++i)
	{
		(++prev)->tag = lower + i*((upper - lower + 1)/num_elements);
		rLog(rlOrderList, "%i", prev->tag);
		AssertMsg(prev->tag != 0 || prev == Parent::begin(), "Cannot assign 0 tag except at the beginning of OrderList");
	}

	AssertMsg(++prev == next, "prev + num_elements != next in OrderList::insert()");

	return iterator(new_base);
}

template<class T>
void
OrderList<T>::
show_elements() const
{
	for (const_iterator cur = begin(); cur != end(); ++cur)
		std::cout << *(cur.get_base()) << std::endl;
	std::cout << std::endl;
}

/* OrderComparison */
template<class T>
int 
OrderList<T>::OrderComparison::
compare(ComparableType a, ComparableType b) const
{
	if (a.get_base()->tag == b.get_base()->tag)			return 0;
	if (a.get_base()->tag < b.get_base()->tag)			return -1;
	return 1;
}

template<class T>
bool
OrderList<T>::OrderComparison::
operator()(ComparableType a, ComparableType b) const
{
	return (compare(a,b) < 0);
}