close to compiling

This commit is contained in:
vasiloglou
2007-05-04 22:42:58 +00:00
parent f81dd10d69
commit 402dca52fa
16 changed files with 297 additions and 243 deletions
Binary file not shown.
+2 -1
View File
@@ -77,6 +77,7 @@ class BinaryTree {
BinaryTree();
~BinaryTree();
void Init(BinaryDataset<Precision_t> &data);
void Destruct() {}
// Call this function to build Depth first a tree
void BuildDepthFirst();
void BuildDepthFirst(NodePtr_t &ptr, PivotInfo_t *pivot);
@@ -86,7 +87,7 @@ class BinaryTree {
// Builds tree k depth first. It builds all the subtrees depth first up to k level
void BuildKDepthFirst();
template<typename POINTTYPE, typename NEIGHBORTYPE>
void NearestNeighbor(POINTTYPE &test_point,
void NearestNeighbor(POINTTYPE test_point,
vector<pair<Precision_t, Point_t> > *nearest_point,
NEIGHBORTYPE range);
+2 -1
View File
@@ -52,7 +52,7 @@ class BinaryTree {
typedef BinaryTree<TYPELIST, diagnostic> BinaryTree_t;
typedef typename Pivot_t::PivotInfo PivotInfo_t;
// For testing purposes only
template<typename >friend class BinaryTreeTest;
template<typename, bool >friend class BinaryTreeTest;
class OutPutAllocator {
public:
@@ -77,6 +77,7 @@ class BinaryTree {
BinaryTree();
~BinaryTree();
void Init(BinaryDataset<Precision_t> &data);
void Destruct() {}
// Call this function to build Depth first a tree
void BuildDepthFirst();
void BuildDepthFirst(NodePtr_t &ptr, PivotInfo_t *pivot);
+66 -59
View File
@@ -47,7 +47,7 @@ void TREE__::BuildBreadthFirst() {
fifo.push_front(make_pair(parent_->get_left().Reference(), pivot_pair.first));
fifo.push_front(make_pair(parent_->get_right().Reference(), pivot_pair.second));
current_level_ =1;
BreadthFirst(fifo);
BuildBreadthFirst(fifo);
if (log_progress_==true) {
printf("\n");
}
@@ -82,14 +82,14 @@ void TREE__::BuildBreadthFirst(
total_points_visited_ += fifo_pair.second->num_of_points_;
progress_.Show(total_points_visited_, get_num_of_points());
}
(*fifo_pair.first).Reset(new Node_t(fifo_pair.second, node_id_, data_));
(*fifo_pair.first)->Init(fifo_pair.second.box_,
fifo_pair.second.statistics_,
(*fifo_pair.first).Reset(new Node_t());
(*fifo_pair.first)->Init(fifo_pair.second->box_,
fifo_pair.second->statistics_,
node_id_,
fifo_pair.second.num_of_points_,
&data_,
fifo_pair.second.start_,
dimension_);
fifo_pair.second->start_,
fifo_pair.second->num_of_points_,
dimension_,
&data_);
num_of_leafs_++;
node_id_++;
@@ -116,13 +116,13 @@ void TREE__::BuildDepthFirst(typename TREE__::NodePtr_t &ptr,
pair<PivotInfo_t *, PivotInfo_t *> pivot_pair;
if (pivot_info->num_of_points_ > max_points_on_leaf_) {
ptr.Reset(new Node_t(pivot_info, node_id_));
ptr.Reset(new Node_t());
ptr->Init(pivot_info->box_,
pivot_info->statistics_,
node_id_,
pivot_info->num_of_points_);
node_id_++;
pivot_pair = pivoter(pivot_info);
pivot_pair = pivoter_(pivot_info);
// There is a case where on all the points are the same
// so pivoting returns 0 points on the left side
// In that case we create a gigantic leaf
@@ -138,13 +138,13 @@ void TREE__::BuildDepthFirst(typename TREE__::NodePtr_t &ptr,
min_depth_=current_level_;
}
ptr.Reset(new Node_t());
ptr->Init(pivot_pair.second.box_,
pivot_pair.second.statistics_,
ptr->Init(pivot_pair.second->box_,
pivot_pair.second->statistics_,
node_id_,
pivot_pair.second.num_of_points_,
&data_,
pivot_pair.second.start_,
dimension_);
pivot_pair.second->start_,
pivot_pair.second->num_of_points_,
dimension_,
&data_);
node_id_++;
num_of_leafs_++;
@@ -155,8 +155,8 @@ void TREE__::BuildDepthFirst(typename TREE__::NodePtr_t &ptr,
}
delete pivot_info;
current_level_++;
SerialBuildDepthFirst(ptr->get_left(), pivot_pair.first);
SerialBuildDepthFirst(ptr->get_right(), pivot_pair.second);
BuildDepthFirst(ptr->get_left(), pivot_pair.first);
BuildDepthFirst(ptr->get_right(), pivot_pair.second);
current_level_--;
} else {
if (log_progress_==true) {
@@ -169,14 +169,14 @@ void TREE__::BuildDepthFirst(typename TREE__::NodePtr_t &ptr,
if (current_level_ < min_depth_) {
min_depth_=current_level_;
}
ptr.Reset(new Node_t(pivot_info, node_id_, data_));
ptr->Init(pivot_info.second.box_,
pivot_info.second.statistics_,
ptr.Reset(new Node_t());
ptr->Init(pivot_info->box_,
pivot_info->statistics_,
node_id_,
pivot_info.second.num_of_points_,
&data_,
pivot_info.second.start_,
dimension_);
pivot_info->start_,
pivot_info->num_of_points_,
dimension_,
&data_);
node_id_++;
num_of_leafs_++;
@@ -188,19 +188,24 @@ void TREE__::BuildDepthFirst(typename TREE__::NodePtr_t &ptr,
// k nearest, range nearest or just nearest
TEMPLATE__
template<typename POINTTYPE, typename NEIGHBORTYPE>
void TREE__::NearestNeighbor(POINTTYPE &test_point,
vector<pair<Precision_t, Point_t> > *nearest_point,
void TREE__::NearestNeighbor(POINTTYPE test_point,
vector<pair<typename TREE__::Precision_t,
typename TREE__::Point_t> > *nearest_point,
NEIGHBORTYPE range) {
bool found = false;
*distance = numeric_limits<Precision_t>::max();
NearestNeighbor(parent_, test_point, nearest_point, distance, range, found);
NearestNeighbor(parent_,
test_point,
nearest_point,
range,
found);
}
TEMPLATE__
template<typename POINTTYPE, typename NEIGHBORTYPE>
void TREE__::NearestNeighbor(NodePtr_t ptr,
POINTTYPE &test_point,
vector<pair<Precision_t, Point_t> > *nearest_point,
vector<pair<typename TREE__::Precision_t,
typename TREE__::Point_t> > *nearest_point,
NEIGHBORTYPE range,
bool &found) {
computations_.UpdateComparisons();
@@ -209,16 +214,15 @@ void TREE__::NearestNeighbor(NodePtr_t ptr,
pair<NodePtr_t, NodePtr_t> child_pair =
ptr->ClosestChild(test_point, dimension_, computations_);
NearestNeighbor(child_pair.first, test_point, nearest_point, distance,
NearestNeighbor(child_pair.first, test_point, nearest_point,
range, found);
if (child_pair.second->get_box().CrossesBoundaries(test_point,
dimension_,
*distance,
nearest_point->end()->first,
computations_)) {
NearestNeighbor(child_pair.second,
test_point,
nearest_point,
distance,
range, found);
}
@@ -226,7 +230,7 @@ void TREE__::NearestNeighbor(NodePtr_t ptr,
return;
} else {
found = ptr->get_box().IsWithin(test_point,
dimension_, *distance,
dimension_, nearest_point->end()->first,
computations_)==0;
if (found == true) {
return;
@@ -234,11 +238,12 @@ void TREE__::NearestNeighbor(NodePtr_t ptr,
}
} else {
ptr->FindNearest(test_point, *nearest_point,
*distance, range, dimension_,
*discriminator_,
range, dimension_,
discriminator_,
computations_);
found = ptr->get_box().IsWithin(test_point, dimension_, *distance,
computations_);
found = ptr->get_box().IsWithin(test_point, dimension_,
nearest_point->end()->first,
computations_);
}
}
@@ -255,10 +260,10 @@ void TREE__::AllNearestNeighbors(typename TREE__::NodePtr_t query,
TEMPLATE__
template<typename NEIGHBORTYPE >
void TREE__::AllNearestNeighbors(NodePtr_t query,
NodePtr_t reference,
void TREE__::AllNearestNeighbors(typename TREE__::NodePtr_t query,
typename TREE__::NodePtr_t reference,
NEIGHBORTYPE range,
Precision_t distance) {
typename TREE__::Precision_t distance) {
if (distance > query->get_min_dist_so_far()) {
return ;
@@ -269,7 +274,7 @@ void TREE__::AllNearestNeighbors(NodePtr_t query,
max_distance,
range,
dimension_,
*discriminator_,
discriminator_,
computations_);
query->set_min_dist_so_far(max_distance);
} else {
@@ -307,8 +312,8 @@ void TREE__::AllNearestNeighbors(NodePtr_t query,
range,
closest_child.second.second);
query->set_min_dist_so_far(
min(query->get_min_dist_so_far(),
max(query->get_left()->get_min_dist_so_far(),
std::min<Precision_t>(query->get_min_dist_so_far(),
std::max<Precision_t>(query->get_left()->get_min_dist_so_far(),
query->get_right()->get_min_dist_so_far())));
} else {
if (!query->IsLeaf() && !reference->IsLeaf()) {
@@ -342,8 +347,8 @@ void TREE__::AllNearestNeighbors(NodePtr_t query,
range,
closest_child.second.second);
query->set_min_dist_so_far(
min(query->get_min_dist_so_far(),
max(query->get_left()->get_min_dist_so_far(),
std::min<Precision_t>(query->get_min_dist_so_far(),
std::max<Precision_t>(query->get_left()->get_min_dist_so_far(),
query->get_right()->get_min_dist_so_far())));
}
@@ -359,18 +364,18 @@ void TREE__::InitAllKNearestNeighborOutput(string file,
int32 knns) {
FILE *fp=fopen(file.c_str(), "w");
const int32 kChunk=8192;
typename Node_t::Result buffer;
buffer=new typename Node_t::Result[kChunk*knns];
typename Node_t::NNResult *buffer;
buffer=new typename Node_t::NNResult[kChunk*knns];
for(index_t i=0; i<num_of_points_/kChunk; i++) {
fwrite(buffer.get(), sizeof(typename Node_t::Result),kChunk*knns, fp );
fwrite(buffer, sizeof(typename Node_t::NNResult),kChunk*knns, fp );
}
fwrite(buffer, sizeof(typename Node_t::Result),
fwrite(buffer, sizeof(typename Node_t::NNResult),
(num_of_points_%kChunk)*knns, fp );
fclose(fp);
delete buffer;
int fd=open(file.c_str(), O_RDWR);
typename Node_t::Result *ptr =(typename Node_t::Result *)mmap(NULL,
sizeof(typename Node_t::Result)*knns*num_of_points_,
typename Node_t::NNResult *ptr =(typename Node_t::NNResult *)mmap(NULL,
sizeof(typename Node_t::NNResult)*knns*num_of_points_,
PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (ptr==MAP_FAILED) {
fprintf(stderr, "Unable to map file: %s", strerror(errno));
@@ -383,11 +388,11 @@ void TREE__::InitAllKNearestNeighborOutput(string file,
TEMPLATE__
void TREE__::InitAllKNearestNeighborOutput(NodePtr_t ptr,
void TREE__::InitAllKNearestNeighborOutput(typename TREE__::NodePtr_t ptr,
int32 knns) {
if (ptr->IsLeaf()) {
ptr->set_kneighbors(all_nn_out_.Allocate(ptr->get_num_of_points(),
knns));
ptr->set_kneighbors(all_nn_out_.Allocate(ptr->get_num_of_points(), knns),
knns);
ptr->InitKNeighbors(knns);
} else {
InitAllKNearestNeighborOutput(ptr->get_left(), knns);
@@ -399,9 +404,11 @@ void TREE__::InitAllKNearestNeighborOutput(NodePtr_t ptr,
TEMPLATE__
void TREE__::InitAllRangeNearestNeighborOutput(string file) {
FILE *fp=fopen(file.c_str(), "w");
FATAL(fp==NULL, "Cannot open %s, error: %s\n",
file.c_str(),
strerror(errno));
if (fp==NULL) {
FATAL("Cannot open %s, error: %s\n",
file.c_str(),
strerror(errno));
}
parent_->set_range_neighbors(fp);
InitAllRangeNearestNeighborOutput(parent_, fp);
}
@@ -422,7 +429,7 @@ void TREE__::InitAllRangeNearestNeighborOutput(
TEMPLATE__
void TREE__::CloseAllKNearestNeighborOutput(int32 knns) {
if (munmap(all_nn_out_.get_ptr(),
sizeof(typename Node_t::Result)*knns*num_of_points_)<0) {
sizeof(typename Node_t::NNResult)*knns*num_of_points_)<0) {
fprintf(stderr, "Failed to umap file: %s", strerror(errno));
assert(false);
}
+66 -59
View File
@@ -47,7 +47,7 @@ void TREE__::BuildBreadthFirst() {
fifo.push_front(make_pair(parent_->get_left().Reference(), pivot_pair.first));
fifo.push_front(make_pair(parent_->get_right().Reference(), pivot_pair.second));
current_level_ =1;
BreadthFirst(fifo);
BuildBreadthFirst(fifo);
if (log_progress_==true) {
printf("\n");
}
@@ -82,14 +82,14 @@ void TREE__::BuildBreadthFirst(
total_points_visited_ += fifo_pair.second->num_of_points_;
progress_.Show(total_points_visited_, get_num_of_points());
}
(*fifo_pair.first).Reset(new Node_t(fifo_pair.second, node_id_, data_));
(*fifo_pair.first)->Init(fifo_pair.second.box_,
fifo_pair.second.statistics_,
(*fifo_pair.first).Reset(new Node_t());
(*fifo_pair.first)->Init(fifo_pair.second->box_,
fifo_pair.second->statistics_,
node_id_,
fifo_pair.second.num_of_points_,
&data_,
fifo_pair.second.start_,
dimension_);
fifo_pair.second->start_,
fifo_pair.second->num_of_points_,
dimension_,
&data_);
num_of_leafs_++;
node_id_++;
@@ -116,13 +116,13 @@ void TREE__::BuildDepthFirst(typename TREE__::NodePtr_t &ptr,
pair<PivotInfo_t *, PivotInfo_t *> pivot_pair;
if (pivot_info->num_of_points_ > max_points_on_leaf_) {
ptr.Reset(new Node_t(pivot_info, node_id_));
ptr.Reset(new Node_t());
ptr->Init(pivot_info->box_,
pivot_info->statistics_,
node_id_,
pivot_info->num_of_points_);
node_id_++;
pivot_pair = pivoter(pivot_info);
pivot_pair = pivoter_(pivot_info);
// There is a case where on all the points are the same
// so pivoting returns 0 points on the left side
// In that case we create a gigantic leaf
@@ -138,13 +138,13 @@ void TREE__::BuildDepthFirst(typename TREE__::NodePtr_t &ptr,
min_depth_=current_level_;
}
ptr.Reset(new Node_t());
ptr->Init(pivot_pair.second.box_,
pivot_pair.second.statistics_,
ptr->Init(pivot_pair.second->box_,
pivot_pair.second->statistics_,
node_id_,
pivot_pair.second.num_of_points_,
&data_,
pivot_pair.second.start_,
dimension_);
pivot_pair.second->start_,
pivot_pair.second->num_of_points_,
dimension_,
&data_);
node_id_++;
num_of_leafs_++;
@@ -155,8 +155,8 @@ void TREE__::BuildDepthFirst(typename TREE__::NodePtr_t &ptr,
}
delete pivot_info;
current_level_++;
SerialBuildDepthFirst(ptr->get_left(), pivot_pair.first);
SerialBuildDepthFirst(ptr->get_right(), pivot_pair.second);
BuildDepthFirst(ptr->get_left(), pivot_pair.first);
BuildDepthFirst(ptr->get_right(), pivot_pair.second);
current_level_--;
} else {
if (log_progress_==true) {
@@ -169,14 +169,14 @@ void TREE__::BuildDepthFirst(typename TREE__::NodePtr_t &ptr,
if (current_level_ < min_depth_) {
min_depth_=current_level_;
}
ptr.Reset(new Node_t(pivot_info, node_id_, data_));
ptr->Init(pivot_info.second.box_,
pivot_info.second.statistics_,
ptr.Reset(new Node_t());
ptr->Init(pivot_info->box_,
pivot_info->statistics_,
node_id_,
pivot_info.second.num_of_points_,
&data_,
pivot_info.second.start_,
dimension_);
pivot_info->start_,
pivot_info->num_of_points_,
dimension_,
&data_);
node_id_++;
num_of_leafs_++;
@@ -188,19 +188,24 @@ void TREE__::BuildDepthFirst(typename TREE__::NodePtr_t &ptr,
// k nearest, range nearest or just nearest
TEMPLATE__
template<typename POINTTYPE, typename NEIGHBORTYPE>
void TREE__::NearestNeighbor(POINTTYPE &test_point,
vector<pair<Precision_t, Point_t> > *nearest_point,
void TREE__::NearestNeighbor(POINTTYPE test_point,
vector<pair<typename TREE__::Precision_t,
typename TREE__::Point_t> > *nearest_point,
NEIGHBORTYPE range) {
bool found = false;
*distance = std::numeric_limits<Precision_t>::max();
NearestNeighbor(parent_, test_point, nearest_point, distance, range, found);
NearestNeighbor(parent_,
test_point,
nearest_point,
range,
found);
}
TEMPLATE__
template<typename POINTTYPE, typename NEIGHBORTYPE>
void TREE__::NearestNeighbor(NodePtr_t ptr,
POINTTYPE &test_point,
vector<pair<Precision_t, Point_t> > *nearest_point,
vector<pair<typename TREE__::Precision_t,
typename TREE__::Point_t> > *nearest_point,
NEIGHBORTYPE range,
bool &found) {
computations_.UpdateComparisons();
@@ -209,16 +214,15 @@ void TREE__::NearestNeighbor(NodePtr_t ptr,
pair<NodePtr_t, NodePtr_t> child_pair =
ptr->ClosestChild(test_point, dimension_, computations_);
NearestNeighbor(child_pair.first, test_point, nearest_point, distance,
NearestNeighbor(child_pair.first, test_point, nearest_point,
range, found);
if (child_pair.second->get_box().CrossesBoundaries(test_point,
dimension_,
*distance,
nearest_point->end()->first,
computations_)) {
NearestNeighbor(child_pair.second,
test_point,
nearest_point,
distance,
range, found);
}
@@ -226,7 +230,7 @@ void TREE__::NearestNeighbor(NodePtr_t ptr,
return;
} else {
found = ptr->get_box().IsWithin(test_point,
dimension_, *distance,
dimension_, nearest_point->end()->first,
computations_)==0;
if (found == true) {
return;
@@ -234,11 +238,12 @@ void TREE__::NearestNeighbor(NodePtr_t ptr,
}
} else {
ptr->FindNearest(test_point, *nearest_point,
*distance, range, dimension_,
*discriminator_,
range, dimension_,
discriminator_,
computations_);
found = ptr->get_box().IsWithin(test_point, dimension_, *distance,
computations_);
found = ptr->get_box().IsWithin(test_point, dimension_,
nearest_point->end()->first,
computations_);
}
}
@@ -255,10 +260,10 @@ void TREE__::AllNearestNeighbors(typename TREE__::NodePtr_t query,
TEMPLATE__
template<typename NEIGHBORTYPE >
void TREE__::AllNearestNeighbors(NodePtr_t query,
NodePtr_t reference,
void TREE__::AllNearestNeighbors(typename TREE__::NodePtr_t query,
typename TREE__::NodePtr_t reference,
NEIGHBORTYPE range,
Precision_t distance) {
typename TREE__::Precision_t distance) {
if (distance > query->get_min_dist_so_far()) {
return ;
@@ -269,7 +274,7 @@ void TREE__::AllNearestNeighbors(NodePtr_t query,
max_distance,
range,
dimension_,
*discriminator_,
discriminator_,
computations_);
query->set_min_dist_so_far(max_distance);
} else {
@@ -307,8 +312,8 @@ void TREE__::AllNearestNeighbors(NodePtr_t query,
range,
closest_child.second.second);
query->set_min_dist_so_far(
min(query->get_min_dist_so_far(),
max(query->get_left()->get_min_dist_so_far(),
std::min<Precision_t>(query->get_min_dist_so_far(),
std::max<Precision_t>(query->get_left()->get_min_dist_so_far(),
query->get_right()->get_min_dist_so_far())));
} else {
if (!query->IsLeaf() && !reference->IsLeaf()) {
@@ -342,8 +347,8 @@ void TREE__::AllNearestNeighbors(NodePtr_t query,
range,
closest_child.second.second);
query->set_min_dist_so_far(
min(query->get_min_dist_so_far(),
max(query->get_left()->get_min_dist_so_far(),
min<Precision_t>(query->get_min_dist_so_far(),
max<Precision_t>(query->get_left()->get_min_dist_so_far(),
query->get_right()->get_min_dist_so_far())));
}
@@ -359,18 +364,18 @@ void TREE__::InitAllKNearestNeighborOutput(string file,
int32 knns) {
FILE *fp=fopen(file.c_str(), "w");
const int32 kChunk=8192;
typename Node_t::Result buffer;
buffer=new typename Node_t::Result[kChunk*knns];
typename Node_t::NNResult *buffer;
buffer=new typename Node_t::NNResult[kChunk*knns];
for(index_t i=0; i<num_of_points_/kChunk; i++) {
fwrite(buffer.get(), sizeof(typename Node_t::Result),kChunk*knns, fp );
fwrite(buffer, sizeof(typename Node_t::NNResult),kChunk*knns, fp );
}
fwrite(buffer, sizeof(typename Node_t::Result),
fwrite(buffer, sizeof(typename Node_t::NNResult),
(num_of_points_%kChunk)*knns, fp );
fclose(fp);
delete buffer;
int fd=open(file.c_str(), O_RDWR);
typename Node_t::Result *ptr =(typename Node_t::Result *)mmap(NULL,
sizeof(typename Node_t::Result)*knns*num_of_points_,
typename Node_t::NNResult *ptr =(typename Node_t::NNResult *)mmap(NULL,
sizeof(typename Node_t::NNResult)*knns*num_of_points_,
PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (ptr==MAP_FAILED) {
fprintf(stderr, "Unable to map file: %s", strerror(errno));
@@ -383,11 +388,11 @@ void TREE__::InitAllKNearestNeighborOutput(string file,
TEMPLATE__
void TREE__::InitAllKNearestNeighborOutput(NodePtr_t ptr,
void TREE__::InitAllKNearestNeighborOutput(typename TREE__::NodePtr_t ptr,
int32 knns) {
if (ptr->IsLeaf()) {
ptr->set_kneighbors(all_nn_out_.Allocate(ptr->get_num_of_points(),
knns));
ptr->set_kneighbors(all_nn_out_.Allocate(ptr->get_num_of_points(), knns),
knns);
ptr->InitKNeighbors(knns);
} else {
InitAllKNearestNeighborOutput(ptr->get_left(), knns);
@@ -399,9 +404,11 @@ void TREE__::InitAllKNearestNeighborOutput(NodePtr_t ptr,
TEMPLATE__
void TREE__::InitAllRangeNearestNeighborOutput(string file) {
FILE *fp=fopen(file.c_str(), "w");
FATAL(fp==NULL, "Cannot open %s, error: %s\n",
file.c_str(),
strerror(errno));
if (fp==NULL) {
FATAL("Cannot open %s, error: %s\n",
file.c_str(),
strerror(errno));
}
parent_->set_range_neighbors(fp);
InitAllRangeNearestNeighborOutput(parent_, fp);
}
@@ -422,7 +429,7 @@ void TREE__::InitAllRangeNearestNeighborOutput(
TEMPLATE__
void TREE__::CloseAllKNearestNeighborOutput(int32 knns) {
if (munmap(all_nn_out_.get_ptr(),
sizeof(typename Node_t::Result)*knns*num_of_points_)<0) {
sizeof(typename Node_t::NNResult)*knns*num_of_points_)<0) {
fprintf(stderr, "Failed to umap file: %s", strerror(errno));
assert(false);
}
+57 -39
View File
@@ -46,7 +46,8 @@ class BinaryTreeTest {
typedef Point<Precision_t, Allocator_t> Point_t;
typedef BinaryTree<TYPELIST, diagnostic> BinaryTree_t;
typedef typename BinaryTree_t::Node_t Node_t;
BinaryTreeTest() {
}
void Init() {
dimension_=2;
num_of_points_=1000;
@@ -71,40 +72,40 @@ class BinaryTreeTest {
unlink(result_file_.c_str());
}
void BuildDepthFirst(){
tree_.BuildDepstFirst();
tree_.BuildDepthFirst();
}
void BuildBreadthFirst() {
tree_.BuildBreadthFirst();
}
void kNearestNeighbor() {
tree_->BuildDepthFirst();
vector<pair<Precision_t, Point_t> nearest_tree;
tree_.BuildDepthFirst();
vector<pair<Precision_t, Point_t> > nearest_tree;
pair<Precision_t, index_t> nearest_naive[num_of_points_];
for(index_t i=0; i<num_of_points_; i++) {
tree_.NearestNeighbor(data_.At(i),
tree_.NearestNeighbor(data_.get_point(i),
&nearest_tree,
knns_);
Naive(data_.At(i), knns_, nearest_naive);
Naive(i, nearest_naive);
for(index_t j=0; j<knns_; j++) {
ASSERT_DOUBLE_APPROX(nearest_naive[j+1].first,
nearest_tree[j].first,
numeric_limits<Precision_t>::epsilon());
TEST_DOUBLE_APPROX(nearest_naive[j+1].first,
nearest_tree[j].first,
numeric_limits<Precision_t>::epsilon());
TEST_ASSERT(nearest_tree[j].second.get_id()==
naive_tree[j+1].second) ;
nearest_naive[j+1].second) ;
}
}
}
void RangeNearestNeighbor() {
tree_.BuildBreadthFirst();
vector<pair<Precision_t, Point_t> nearest_tree;
pair<Precisiont_t, index_t> nearest_naive[num_of_points_];
vector<pair<Precision_t, Point_t> > nearest_tree;
pair<Precision_t, index_t> nearest_naive[num_of_points_];
for(index_t i=0; i<num_of_points_; i++) {
tree_.NearestNeighbor(data_.At(i),
tree_.NearestNeighbor(data_.get_point(i),
&nearest_tree,
range_);
Naive(data_.At(i), neares_naive);
for(index_t j=0; j<nearest_tree.size(); j++) {
ASSERT_DOUBLE_APPROX(nearest_naive[j+1].first,
Naive(i, nearest_naive);
for(index_t j=0; j<(index_t)nearest_tree.size(); j++) {
TEST_DOUBLE_APPROX(nearest_naive[j+1].first,
nearest_tree[j].first,
numeric_limits<Precision_t>::epsilon());
TEST_ASSERT(nearest_tree[j].second.get_id()==
@@ -116,7 +117,7 @@ class BinaryTreeTest {
tree_.BuildBreadthFirst();
tree_.InitAllKNearestNeighborOutput(result_file_,
knns_);
tree_.AllKNearestNeighbor(tree_.parent_, knns_);
tree_.AllNearestNeighbors(tree_.parent_, knns_);
tree_.CloseAllKNearestNeighborOutput(knns_);
struct stat info;
if (stat(data_file_.c_str(), &info)!=0) {
@@ -126,7 +127,8 @@ class BinaryTreeTest {
uint64 map_size = info.st_size-sizeof(int32);
int fp=open(result_file_.c_str(), O_RDWR);
typename Node_t::NNResult *res=mmap(NULL,
typename Node_t::NNResult *res;
res=(typename Node_t::NNResult *) mmap(NULL,
map_size,
PROT_READ | PROT_WRITE,
MAP_SHARED, fp,
@@ -135,12 +137,12 @@ class BinaryTreeTest {
std::sort(res, res+num_of_points_*knns_);
pair<Precision_t, index_t> nearest_naive[num_of_points_];
for(index_t i=0; i<num_of_points_; i++) {
Naive(data_.At(res[i].point_id_), nearest_naive);
Naive(res[i].point_id_, nearest_naive);
for(index_t j=0; j<knns_; j++) {
ASSERT_DOUBLE_APPROX(nearest_naive[j+1].first,
TEST_DOUBLE_APPROX(nearest_naive[j+1].first,
res[i*knns_+j].distance_,
numeric_limits<Precision_t>::epsilon());
TEST_ASSERT(res[j].second.get_id()==
TEST_ASSERT(res[j].nearest_.get_id()==
nearest_naive[j+1].second);
}
}
@@ -149,10 +151,9 @@ class BinaryTreeTest {
void AllRangeNearestNeighbors() {
tree_.BuildBreadthFirst();
tree_.InitAllKNearestNeighborOutput(result_file_,
range_);
tree_.AllKNearestNeighbor(tree_.parent_, range_);
tree_.CloseAllKNearestNeighborOutput();
tree_.InitAllRangeNearestNeighborOutput(result_file_);
tree_.AllNearestNeighbors(tree_.parent_, range_);
tree_.CloseAllRangeNearestNeighborOutput();
struct stat info;
if (stat(data_file_.c_str(), &info)!=0) {
FATAL( "Error %s file %s\n",
@@ -161,7 +162,8 @@ class BinaryTreeTest {
uint64 map_size = info.st_size-sizeof(int32);
int fp=open(result_file_.c_str(), O_RDWR);
typename Node_t::NNResult *res=mmap(NULL,
typename Node_t::NNResult *res;
res=(typename Node_t::NNResult *)mmap(NULL,
map_size,
PROT_READ | PROT_WRITE,
MAP_SHARED, fp,
@@ -171,13 +173,13 @@ class BinaryTreeTest {
pair<Precision_t, index_t> nearest_naive[num_of_points_];
index_t i=0;
while (i<num_of_points_) {
Naive(data_.At(res[i].point_id_), nearest_naive);
Naive(res[i].point_id_, nearest_naive);
index_t j=0;
while (nearest_naive[j+1].first<range_) {
ASSERT_DOUBLE_APPROX(nearest_naive[j+1].first,
TEST_DOUBLE_APPROX(nearest_naive[j+1].first,
res[i].distance_,
numeric_limits<Precision_t>::epsilon());
TEST_ASSERT(res[i].second.get_id()==
TEST_ASSERT(res[i].nearest_.get_id()==
nearest_naive[j+1].second);
i++;
j++;
@@ -186,13 +188,26 @@ class BinaryTreeTest {
munmap(res, map_size);
}
TEST_SUITE(BuildDepthFirst,
BuildBreadthFirst,
kNearestNeighbor,
RangeNearestNeighbor,
AllKNearestNeighbors,
AllRangeNearestNeighbors)
void TestAll() {
Init();
BuildDepthFirst();
Destruct();
Init();
BuildBreadthFirst();
Destruct();
Init();
kNearestNeighbor();
Destruct();
Init();
RangeNearestNeighbor();
Destruct();
Init();
AllKNearestNeighbors();
Destruct();
Init();
AllRangeNearestNeighbors();
Destruct();
}
private:
BinaryTree_t tree_;
BinaryDataset<Precision_t> data_;
@@ -213,8 +228,8 @@ class BinaryTreeTest {
Precision_t dist=Metric_t::Distance(data_.At(i),
data_.At(query),
dimension_);
result[i].first=i;
result[i].second=dist;
result[i].first=dist;
result[i].second=i;
}
sort(result, result+num_of_points_);
}
@@ -244,4 +259,7 @@ struct Parameters {
typedef KdPivoter1<BasicTypes, false> Pivot_t;
};
typedef BinaryTreeTest<Parameters, false> BinaryTreeTest_t;
RUN_ALL_TESTS(BinaryTreeTest_t)
int main(int argc, char *argv[]) {
BinaryTreeTest_t test;
test.TestAll();
}
+56 -40
View File
@@ -46,7 +46,8 @@ class BinaryTreeTest {
typedef Point<Precision_t, Allocator_t> Point_t;
typedef BinaryTree<TYPELIST, diagnostic> BinaryTree_t;
typedef typename BinaryTree_t::Node_t Node_t;
BinaryTreeTest() {
}
void Init() {
dimension_=2;
num_of_points_=1000;
@@ -71,40 +72,40 @@ class BinaryTreeTest {
unlink(result_file_.c_str());
}
void BuildDepthFirst(){
tree_.BuildDepstFirst();
tree_.BuildDepthFirst();
}
void BuildBreadthFirst() {
tree_.BuildBreadthFirst();
}
void kNearestNeighbor() {
tree_->BuildDepthFirst();
vector<pair<Precision_t, Point_t> nearest_tree;
tree_.BuildDepthFirst();
vector<pair<Precision_t, Point_t> > nearest_tree;
pair<Precision_t, index_t> nearest_naive[num_of_points_];
for(index_t i=0; i<num_of_points_; i++) {
tree_.NearestNeighbor(data_.At(i),
tree_.NearestNeighbor(data_.get_point(i),
&nearest_tree,
knns_);
Naive(data_.At(i), knns_, nearest_naive);
Naive(i, nearest_naive);
for(index_t j=0; j<knns_; j++) {
ASSERT_DOUBLE_APPROX(nearest_naive[j+1].first,
nearest_tree[j].first,
numeric_limits<Precision_t>::epsilon());
TEST_DOUBLE_APPROX(nearest_naive[j+1].first,
nearest_tree[j].first,
numeric_limits<Precision_t>::epsilon());
TEST_ASSERT(nearest_tree[j].second.get_id()==
naive_tree[j+1].second) ;
nearest_naive[j+1].second) ;
}
}
}
void RangeNearestNeighbor() {
tree_.BuildBreadthFirst();
vector<pair<Precision_t, Point_t> nearest_tree;
pair<Precisiont_t, index_t> nearest_naive[num_of_points_];
vector<pair<Precision_t, Point_t> > nearest_tree;
pair<Precision_t, index_t> nearest_naive[num_of_points_];
for(index_t i=0; i<num_of_points_; i++) {
tree_.NearestNeighbor(data_.At(i),
tree_.NearestNeighbor(data_.get_point(i),
&nearest_tree,
range_);
Naive(data_.At(i), neares_naive);
Naive(i, nearest_naive);
for(index_t j=0; j<nearest_tree.size(); j++) {
ASSERT_DOUBLE_APPROX(nearest_naive[j+1].first,
TEST_DOUBLE_APPROX(nearest_naive[j+1].first,
nearest_tree[j].first,
numeric_limits<Precision_t>::epsilon());
TEST_ASSERT(nearest_tree[j].second.get_id()==
@@ -116,7 +117,7 @@ class BinaryTreeTest {
tree_.BuildBreadthFirst();
tree_.InitAllKNearestNeighborOutput(result_file_,
knns_);
tree_.AllKNearestNeighbor(tree_.parent_, knns_);
tree_.AllNearestNeighbors(tree_.parent_, knns_);
tree_.CloseAllKNearestNeighborOutput(knns_);
struct stat info;
if (stat(data_file_.c_str(), &info)!=0) {
@@ -126,7 +127,8 @@ class BinaryTreeTest {
uint64 map_size = info.st_size-sizeof(int32);
int fp=open(result_file_.c_str(), O_RDWR);
typename Node_t::NNResult *res=mmap(NULL,
typename Node_t::NNResult *res;
res=(typename Node_t::NNResult *) mmap(NULL,
map_size,
PROT_READ | PROT_WRITE,
MAP_SHARED, fp,
@@ -135,12 +137,12 @@ class BinaryTreeTest {
std::sort(res, res+num_of_points_*knns_);
pair<Precision_t, index_t> nearest_naive[num_of_points_];
for(index_t i=0; i<num_of_points_; i++) {
Naive(data_.At(res[i].point_id_), nearest_naive);
Naive(res[i].point_id_, nearest_naive);
for(index_t j=0; j<knns_; j++) {
ASSERT_DOUBLE_APPROX(nearest_naive[j+1].first,
TEST_DOUBLE_APPROX(nearest_naive[j+1].first,
res[i*knns_+j].distance_,
numeric_limits<Precision_t>::epsilon());
TEST_ASSERT(res[j].second.get_id()==
TEST_ASSERT(res[j].nearest_.get_id()==
nearest_naive[j+1].second);
}
}
@@ -149,10 +151,9 @@ class BinaryTreeTest {
void AllRangeNearestNeighbors() {
tree_.BuildBreadthFirst();
tree_.InitAllKNearestNeighborOutput(result_file_,
range_);
tree_.AllKNearestNeighbor(tree_.parent_, range_);
tree_.CloseAllKNearestNeighborOutput();
tree_.InitAllRangeNearestNeighborOutput(result_file_);
tree_.AllNearestNeighbors(tree_.parent_, range_);
tree_.CloseAllRangeNearestNeighborOutput();
struct stat info;
if (stat(data_file_.c_str(), &info)!=0) {
FATAL( "Error %s file %s\n",
@@ -161,7 +162,8 @@ class BinaryTreeTest {
uint64 map_size = info.st_size-sizeof(int32);
int fp=open(result_file_.c_str(), O_RDWR);
typename Node_t::NNResult *res=mmap(NULL,
typename Node_t::NNResult *res;
res=(typename Node_t::NNResult *)mmap(NULL,
map_size,
PROT_READ | PROT_WRITE,
MAP_SHARED, fp,
@@ -171,13 +173,13 @@ class BinaryTreeTest {
pair<Precision_t, index_t> nearest_naive[num_of_points_];
index_t i=0;
while (i<num_of_points_) {
Naive(data_.At(res[i].point_id_), nearest_naive);
Naive(res[i].point_id_, nearest_naive);
index_t j=0;
while (nearest_naive[j+1].first<range_) {
ASSERT_DOUBLE_APPROX(nearest_naive[j+1].first,
TEST_DOUBLE_APPROX(nearest_naive[j+1].first,
res[i].distance_,
numeric_limits<Precision_t>::epsilon());
TEST_ASSERT(res[i].second.get_id()==
TEST_ASSERT(res[i].nearest_.get_id()==
nearest_naive[j+1].second);
i++;
j++;
@@ -186,13 +188,26 @@ class BinaryTreeTest {
munmap(res, map_size);
}
TEST_SUITE(BuildDepthFirst,
BuildBreadthFirst,
kNearestNeighbor,
RangeNearestNeighbor,
AllKNearestNeighbors,
AllRangeNearestNeighbors)
void TestAll() {
Init();
BuildDepthFirst();
Destruct();
Init();
BuildBreadthFirst();
Destruct();
Init();
kNearestNeighbor();
Destruct();
Init();
RangeNearestNeighbor();
Destruct();
Init();
AllKNearestNeighbors();
Destruct();
Init();
AllRangeNearestNeighbors();
Destruct();
}
private:
BinaryTree_t tree_;
BinaryDataset<Precision_t> data_;
@@ -213,8 +228,8 @@ class BinaryTreeTest {
Precision_t dist=Metric_t::Distance(data_.At(i),
data_.At(query),
dimension_);
result[i].first=i;
result[i].second=dist;
result[i].first=dist;
result[i].second=i;
}
sort(result, result+num_of_points_);
}
@@ -234,8 +249,6 @@ struct BasicTypes {
typedef MemoryManager<false> Allocator_t;
typedef EuclideanMetric<float32> Metric_t;
};
template<class T, bool d> class KdPivoter1 {
};
struct Parameters {
typedef float32 Precision_t;
typedef MemoryManager<false> Allocator_t;
@@ -246,4 +259,7 @@ struct Parameters {
typedef KdPivoter1<BasicTypes, false> Pivot_t;
};
typedef BinaryTreeTest<Parameters, false> BinaryTreeTest_t;
RUN_ALL_TESTS(BinaryTreeTest_t)
int main(int argc, char *argv[]) {
BinaryTreeTest_t test;
test.TestAll();
}
+4 -3
View File
@@ -33,7 +33,7 @@ class KdPivoter1 {
struct PivotInfo {
public:
void Init(index_t start, index_t num_of_points, HyperRectangle_t &box) {
box_.Copy(box_);
box_.Alias(box);
start_=start;
num_of_points_=num_of_points;
}
@@ -102,7 +102,8 @@ class KdPivoter1 {
UpdateHyperRectangle(point, hr);
}
FindPivotDimensionValue(hr);
PivotInfo *pv = new PivotInfo(0, num_of_points, hr);
PivotInfo *pv = new PivotInfo();
pv->Init(0, num_of_points, hr);
return pv;
}
@@ -126,7 +127,7 @@ class KdPivoter1 {
void UpdateHyperRectangle(Precision_t *point,
HyperRectangle_t &hr) {
for(int32 j=0; j<data_.get_dimension(); j++) {
for(int32 j=0; j<data_->get_dimension(); j++) {
if (point[j] > hr.get_max()[j]) {
hr.get_max()[j] = point[j];
}
+4 -3
View File
@@ -33,7 +33,7 @@ class KdPivoter1 {
struct PivotInfo {
public:
void Init(index_t start, index_t num_of_points, HyperRectangle_t &box) {
box_.Copy(box_);
box_.Alias(box);
start_=start;
num_of_points_=num_of_points;
}
@@ -98,11 +98,12 @@ class KdPivoter1 {
HyperRectangle_t hr;
hr.Init(data_->get_dimension());
for(index_t i=0; i<num_of_points; i++) {
Precision_t *point = data->At(i);
Precision_t *point = data_->At(i);
UpdateHyperRectangle(point, hr);
}
FindPivotDimensionValue(hr);
PivotInfo *pv = new PivotInfo(0, num_of_points, hr);
PivotInfo *pv = new PivotInfo();
pv->Init(0, num_of_points, hr);
return pv;
}
+1 -1
View File
@@ -19,7 +19,7 @@ class Node {
typedef typename TYPELIST::Metric_t Metric_t;
typedef typename TYPELIST::BoundingBox_t BoundingBox_t;
typedef typename TYPELIST::NodeCachedStatistics_t NodeCachedStatistics_t;
typedef typename TYPELIST::PointIdDescriminator_t PointIdDiscriminator_t;
typedef typename TYPELIST::PointIdDiscriminator_t PointIdDiscriminator_t;
typedef typename Allocator_t::template ArrayPtr<Precision_t> Array_t;
typedef Node<TYPELIST, diagnostic> Node_t;
typedef typename Allocator_t::template Ptr<Node> NodePtr_t;
+1 -1
View File
@@ -19,7 +19,7 @@ class Node {
typedef typename TYPELIST::Metric_t Metric_t;
typedef typename TYPELIST::BoundingBox_t BoundingBox_t;
typedef typename TYPELIST::NodeCachedStatistics_t NodeCachedStatistics_t;
typedef typename TYPELIST::PointIdDescriminator_t PointIdDescriminator_t;
typedef typename TYPELIST::PointIdDescriminator_t PointIdDiscriminator_t;
typedef typename Allocator_t::template ArrayPtr<Precision_t> Array_t;
typedef Node<TYPELIST, diagnostic> Node_t;
typedef typename Allocator_t::template Ptr<Node> NodePtr_t;
+13 -12
View File
@@ -136,10 +136,11 @@ inline void NODE__::FindNearest(POINTTYPE query_point,
nearest.push_back(make_pair(dist, point));
}
}
// for k-nearest neighbors
typename std::vector<pair<Precision_t, Point_t> >::iterator it;
it=nearest.begin()+range;
if (Loki::TypeTraits<NEIGHBORTYPE>::isStdFloat==false) {
// for k-nearest neighbors
if (Loki::TypeTraits<NEIGHBORTYPE>::isStdFloat==false) {
typename std::vector<pair<Precision_t, Point_t> >::iterator it;
it=nearest.begin()+(index_t)range;
std::partial_sort(nearest.begin(),
it,
nearest.end(),
@@ -166,7 +167,7 @@ inline void NODE__::FindAllNearest(
// for k nearest neighbors
if (Loki::TypeTraits<NEIGHBORTYPE>::isStdFloat==false) {
// get the current maximum distance for the specific point
distance = query_node->kneighbors_[i*range+range-1].distance_;
distance = query_node->kneighbors_[i*(int32)range+(int32)range-1].distance_;
} else {
distance=range;
}
@@ -179,23 +180,23 @@ inline void NODE__::FindAllNearest(
comp)) {
// for k nearest neighbors
if (Loki::TypeTraits<NEIGHBORTYPE>::isStdFloat==false) {
vector<pair<Precision_t, Point_t> > temp(range);
vector<pair<Precision_t, Point_t> > temp((index_t)range);
for(int32 j=0; j<range; j++) {
temp[j].first=query_node->kneighbors_[i*range+j].distance_;
temp[j].second=query_node->kneighbors_[i*range+j].nearest_;
temp[j].first=query_node->kneighbors_[i*(index_t)range+j].distance_;
temp[j].second=query_node->kneighbors_[i*(index_t)range+j].nearest_;
}
Point_t point;
point.Alias(query_node->points_.get()+i*dimension, index_[i]);
FindNearest(point, temp,
range, dimension,
discriminator, comp);
for(int32 j=range-1; j>=0; j--) {
if (query_node->kneighbors_[i*range+j].nearest_.get_id()
for(int32 j=(index_t)range-1; j>=0; j--) {
if (query_node->kneighbors_[i*(index_t)range+j].nearest_.get_id()
==temp[j].second.get_id()) {
break;
}
query_node->kneighbors_[i*range+j].distance_=temp[j].first;
query_node->kneighbors_[i*range+j].nearest_=temp[j].second;
query_node->kneighbors_[i*(index_t)range+j].distance_=temp[j].first;
query_node->kneighbors_[i*(index_t)range+j].nearest_=temp[j].second;
}
// Estimate the maximum nearest neighbor distance
comp.UpdateComparisons();
+19 -22
View File
@@ -135,22 +135,19 @@ inline void NODE__::FindNearest(POINTTYPE query_point,
point.Alias(points_.get()+i*dimension, index_[i]);
nearest.push_back(make_pair(dist, point));
}
// for k-nearest neighbors
typename std::vector<pair<Precision_t, Point_t> >::iterator it;
it=nearest.begin()+range;
//for(index_t k=0; k<range; k++) {
// it++;
//}
if (Loki::TypeTraits<NEIGHBORTYPE>::isStdFloat==false) {
std::partial_sort(nearest.begin(),
it,
nearest.end(),
PairComparator());
if (nearest.size()>(uint32)range) {
nearest.erase(it, nearest.end());
}
}
}
// for k-nearest neighbors
if (Loki::TypeTraits<NEIGHBORTYPE>::isStdFloat==false) {
typename std::vector<pair<Precision_t, Point_t> >::iterator it;
it=nearest.begin()+(index_t)range;
std::partial_sort(nearest.begin(),
it,
nearest.end(),
PairComparator());
if (nearest.size()>(uint32)range) {
nearest.erase(it, nearest.end());
}
}
}
@@ -170,7 +167,7 @@ inline void NODE__::FindAllNearest(
// for k nearest neighbors
if (Loki::TypeTraits<NEIGHBORTYPE>::isStdFloat==false) {
// get the current maximum distance for the specific point
distance = query_node->kneighbors_[i*range+range-1].distance_;
distance = query_node->kneighbors_[i*(int32)range+(int32)range-1].distance_;
} else {
distance=range;
}
@@ -183,18 +180,18 @@ inline void NODE__::FindAllNearest(
comp)) {
// for k nearest neighbors
if (Loki::TypeTraits<NEIGHBORTYPE>::isStdFloat==false) {
vector<pair<Precision_t, Point_t> > temp(range);
vector<pair<Precision_t, Point_t> > temp((index_t)range);
for(int32 j=0; j<range; j++) {
temp[j].first=query_node->kneighbors_[i*range+j].distance_;
temp[j].second=query_node->kneighbors_[i*range+j].nearest_;
temp[j].first=query_node->kneighbors_[i*(index_t)range+j].distance_;
temp[j].second=query_node->kneighbors_[i*(index_t)range+j].nearest_;
}
Point_t point;
point.Alias(query_node->points_.get()+i*dimension, index_[i]);
FindNearest(point, temp,
range, dimension,
discriminator, comp);
for(int32 j=range-1; j>=0; j--) {
if (query_node->kneighbors_[i*range+j].nearest_.get_id()
for(int32 j=(index_t)range-1; j>=0; j--) {
if (query_node->kneighbors_[i*(index_t)range+j].nearest_.get_id()
==temp[j].second.get_id()) {
break;
}
+1 -1
View File
@@ -37,7 +37,7 @@ class NodeTest {
struct NodeParameters : public TYPELIST {
typedef HyperRectangle_t BoundingBox_t;
typedef NullStatistics NodeCachedStatistics_t;
typedef SimpleDiscriminator PointIdDescriminator_t;
typedef SimpleDiscriminator PointIdDiscriminator_t;
};
typedef Node<NodeParameters, diagnostic> Node_t;
typedef typename Allocator_t:: template ArrayPtr<Precision_t> Array_t;
+1 -1
View File
@@ -180,6 +180,6 @@ struct BasicParameters{
};
int main(int argc, char *argv[]) {
NodeTest<BasicParameters}, false> node_test;
NodeTest<BasicParameters, false> node_test;
node_test.TestAll();
}
+4
View File
@@ -19,5 +19,9 @@
class NullStatistics {
public:
void Alias(const NullStatistics &other) {
}
NullStatistics &operator=(const NullStatistics &other) {
return *this;
}
};