diff --git a/fastlib/trunk/contrib/dongryel/thesis_research/core/math/math_lib.h b/fastlib/trunk/contrib/dongryel/thesis_research/core/math/math_lib.h index 4b67f3cb1a..0feda64013 100644 --- a/fastlib/trunk/contrib/dongryel/thesis_research/core/math/math_lib.h +++ b/fastlib/trunk/contrib/dongryel/thesis_research/core/math/math_lib.h @@ -202,25 +202,40 @@ void RandomCombination( } } +/** @brief Implements Algorithm 1 in "Fast Construction of $k$-Nearest + * Neighbor Graphs for Point Clouds" by Connor and Kumar, TVCG + * 2009. + */ template int XorMsb(T a, T b) { - union { + typedef union { T float_rep_; int int_rep_; } float_helper; - // The number of Mantissa bits. - int num_mantissa_bits = std::numeric_limits::digits(); int a_exp, b_exp; - union float_helper a_mantissa, b_mantissa; + float_helper a_mantissa, b_mantissa; a_mantissa.float_rep_ = frexp(a, &a_exp); b_mantissa.float_rep_ = frexp(b, &b_exp); - if(false) { - a_exp -= 0; - return a_exp; + if(a_exp == b_exp) { + + // Take the XOR of the two Mantissa bit representations and find + // the most significant bit. + int a_mantissa_xor_b_mantissa = a_mantissa.int_rep_ ^ b_mantissa.int_rep_; + int most_significant_bit = 0; + int shift_bit = 1; + int num_bits_in_int = std::numeric_limits::digits; + for(int i = 0; i <= num_bits_in_int; i++) { + if((shift_bit & a_mantissa_xor_b_mantissa) != 0) { + most_significant_bit = shift_bit; + } + shift_bit = shift_bit << 1; + } + return a_exp - shift_bit; } - if(false) { + if(b_exp < a_exp) { + return a_exp; } else { return b_exp; @@ -235,7 +250,7 @@ inline bool MortonOrderPoints(const PointType &a, const PointType &b) { int selected_dim = 0; for(int d = 0; d < a.length(); d++) { - int y = XorMsb(a[d], b[d]); + long int y = XorMsb(a[d], b[d]); if(x < y) { x = y; selected_dim = d; diff --git a/fastlib/trunk/contrib/dongryel/thesis_research/core/tree/distributed_tree.test.cc b/fastlib/trunk/contrib/dongryel/thesis_research/core/tree/distributed_tree.test.cc index ac767eac73..dae987b767 100644 --- a/fastlib/trunk/contrib/dongryel/thesis_research/core/tree/distributed_tree.test.cc +++ b/fastlib/trunk/contrib/dongryel/thesis_research/core/tree/distributed_tree.test.cc @@ -92,17 +92,27 @@ class TestDistributedTree { }; }; -BOOST_AUTO_TEST_SUITE(TestSuiteDistributedTree) -BOOST_AUTO_TEST_CASE(TestCaseDistributedTree) { +int main(int argc, char *argv[]) { + + // Initialize boost MPI. + boost::mpi::environment env(argc, argv); + boost::mpi::communicator world; // Tree type: hard-coded for a metric tree. - typedef core::table::Table < - core::tree::GenMetricTree > TableType; + typedef core::tree::GenMetricTree TreeSpecType; + typedef core::table::Table TableType; + typedef core::table::DistributedTable DistributedTableType; + + DistributedTableType distributed_table; + core::tree::DistributedTreeBuilder builder; + builder.Init(distributed_table, 0.2); + core::metric_kernels::LMetric<2> l2_metric; + builder.Build(l2_metric, world); // Call the tests. core::tree::TestDistributedTree tree_test; tree_test.StressTestMain(); std::cout << "All tests passed!\n"; + return 0; } -BOOST_AUTO_TEST_SUITE_END() diff --git a/fastlib/trunk/contrib/dongryel/thesis_research/core/tree/distributed_tree_builder.h b/fastlib/trunk/contrib/dongryel/thesis_research/core/tree/distributed_tree_builder.h index b6050ebce8..5652b894c4 100644 --- a/fastlib/trunk/contrib/dongryel/thesis_research/core/tree/distributed_tree_builder.h +++ b/fastlib/trunk/contrib/dongryel/thesis_research/core/tree/distributed_tree_builder.h @@ -31,6 +31,12 @@ class DistributedTreeBuilder { private: + static bool MortonOrderNodes_(TreeType *first_node, TreeType *second_node) { + return + core::math::MortonOrderPoints( + first_node->bound().center(), second_node->bound().center()); + } + void AugmentNodes_( boost::mpi::communicator &world, const typename TreeType::BoundType &root_bound, @@ -57,7 +63,6 @@ class DistributedTreeBuilder { } tmp_point_alias = (1.0 / static_cast(num_samples)) * tmp_point_alias; - tmp_point_alias = 0.5 * (tmp_point_alias + random_point_on_surface); top_leaf_nodes.push_back(new TreeType()); top_leaf_nodes[ top_leaf_nodes.size() - 1 ]->bound().center().Copy( tmp_point); @@ -88,7 +93,7 @@ class DistributedTreeBuilder { // send to the master. This is a MPI gather operation. TableType sampled_table; std::vector sampled_indices; - SelectSubset_(sampling_rate_, &sampled_indices); + SelectSubset_(&sampled_indices); // Send the number of points chosen in this process to the // master so that the master can allocate the appropriate amount @@ -123,8 +128,13 @@ class DistributedTreeBuilder { if(top_leaf_nodes_out->size() < static_cast(world.size())) { AugmentNodes_( - world, sampled_table.get_tree()->bound(), top_leaf_nodes_out); + world, sampled_table.get_tree()->bound(), *top_leaf_nodes_out); } + + // Sort the nodes by Z-ordering their centroids. + std::sort( + top_leaf_nodes_out->begin(), top_leaf_nodes_out->end(), + MortonOrderNodes_); } boost::mpi::broadcast(world, *top_leaf_nodes_out, 0); } @@ -157,7 +167,7 @@ class DistributedTreeBuilder { sampling_rate_ = sampling_rate_in; } - void BuildTree( + void Build( const core::metric_kernels::AbstractMetric &metric_in, boost::mpi::communicator &world) { @@ -165,8 +175,6 @@ class DistributedTreeBuilder { std::vector top_leaf_nodes; BuildSampleTree_(metric_in, world, &top_leaf_nodes); - // Sort the top leaf nodes by their Z-ordering. - } }; };