/*++ Copyright (c) 2006 Microsoft Corporation Module Name: fvi_def.h Abstract: Feature Vector Indexing. Author: Leonardo de Moura (leonardo) 2008-02-01. Revision History: --*/ #ifndef _FVI_DEF_H_ #define _FVI_DEF_H_ #include"fvi.h" #include"splay_tree_def.h" #include"buffer.h" template fvi::fvi(unsigned num_features, ToVector const & t): ToVector(t), m_num_features(num_features), m_root(0) { m_tmp_buffer.resize(num_features, 0); m_root = alloc(non_leaf); SASSERT(num_features >= 2); DEBUG_CODE(m_visiting = false;); } template void fvi::reset() { SASSERT(!m_visiting); dealloc(m_root); m_root = alloc(non_leaf); } template void fvi::insert(T * d) { SASSERT(!m_visiting); to_fvector(d); non_leaf * n = m_root; unsigned i = 0; for (; i < m_num_features - 1; i++) { node * child = 0; if (!n->m_children.find(m_tmp_buffer[i], child)) { child = alloc(non_leaf); n->m_children.insert(m_tmp_buffer[i], child); } SASSERT(child); SASSERT(!child->is_leaf()); n = static_cast(child); } node * l = 0; SASSERT(i == m_num_features - 1); if (!n->m_children.find(m_tmp_buffer[i], l)) { l = alloc(leaf); n->m_children.insert(m_tmp_buffer[i], l); } SASSERT(l); SASSERT(l->is_leaf()); static_cast(l)->m_set.insert(d); } template bool fvi::contains(T * d) const { to_fvector(d); non_leaf * n = m_root; node * child; unsigned i = 0; for (; i < m_num_features - 1; i++) { if (!n->m_children.find(m_tmp_buffer[i], child)) return false; SASSERT(child); SASSERT(!child->is_leaf()); n = static_cast(child); } SASSERT(i == m_num_features - 1); return n->m_children.find(m_tmp_buffer[i], child) && static_cast(child)->m_set.contains(d); } template void fvi::erase(T * d) { SASSERT(!m_visiting); SASSERT(contains(d)); ptr_buffer path; to_fvector(d); non_leaf * n = m_root; node * child; unsigned i = 0; for (; i < m_num_features - 1; i++) { path.push_back(n); if (!n->m_children.find(m_tmp_buffer[i], child)) { UNREACHABLE(); } SASSERT(child); SASSERT(!child->is_leaf()); n = static_cast(child); } path.push_back(n); SASSERT(i == m_num_features - 1); if (!n->m_children.find(m_tmp_buffer[i], child)) { UNREACHABLE(); } SASSERT(child); SASSERT(child->is_leaf()); leaf * l = static_cast(child); l->m_set.erase(d); if (l->m_set.empty()) { dealloc(l); while (true) { non_leaf * n = path.back(); n->m_children.erase(m_tmp_buffer[i]); path.pop_back(); i--; if (!n->m_children.empty() || n == m_root) break; dealloc(n); } } } template void fvi::non_leaf_stat_visitor::operator()(unsigned k, node * n) { if (n->is_leaf()) m_owner.stats(static_cast(n), m_stats); else m_owner.stats(static_cast(n), m_stats); } template void fvi::stats(leaf * n, statistics & result) const { unsigned sz = n->m_set.size(); result.m_size += sz; if (sz > result.m_max_leaf_size) result.m_max_leaf_size = sz; if (sz < result.m_min_leaf_size) result.m_min_leaf_size = sz; result.m_num_leaves ++; result.m_num_nodes ++; } template void fvi::stats(non_leaf * n, statistics & result) const { result.m_num_nodes++; // Remark: this function is recursive, but there is no risk // of stack overflow since the number of features is small. non_leaf_stat_visitor v(*this, result); n->m_children.visit(v); } template void fvi::stats(statistics & result) const { result.reset(); stats(m_root, result); if (m_root->m_children.empty()) result.m_min_leaf_size = 0; if (result.m_num_leaves > 0) result.m_avg_leaf_size = result.m_size / result.m_num_leaves; } template void fvi::non_leaf_collect_visitor::operator()(unsigned k, node * n) { if (n->is_leaf()) m_owner.collect(static_cast(n), m_elems); else m_owner.collect(static_cast(n), m_elems); } template void fvi::collect(leaf * n, ptr_vector & result) const { typename set::iterator it = n->m_set.begin(); typename set::iterator end = n->m_set.end(); for (; it != end; ++it) result.push_back(*it); } template void fvi::collect(non_leaf * n, ptr_vector & result) const { // Remark: this function is recursive, but there is no risk // of stack overflow since the number of features is small. non_leaf_collect_visitor v(*this, result); n->m_children.visit(v); } template void fvi::collect(ptr_vector & result) const { collect(m_root, result); } #endif /* _FVI_DEF_H_ */