#ifndef NODE_H_ #define NODE_H_ #include #include #include "u/nvasil/loki/TypeTraits.h" #include "u/nvasil/loki/Typelist.h" #include "fastlib/fastlib.h" #include "point.h" #include "point_identity_discriminator.h" #include "computations_counter.h" #include "u/nvasil/dataset/binary_dataset.h" template class Node { public: typedef typename TYPELIST::Precision_t Precision_t; typedef typename TYPELIST::Allocator_t Allocator_t; typedef typename TYPELIST::Metric_t Metric_t; typedef typename TYPELIST::BoundingBox_t BoundingBox_t; typedef typename TYPELIST::NodeCachedStatistics_t NodeCachedStatistics_t; typedef typename TYPELIST::PointIdDiscriminator_t PointIdDiscriminator_t; typedef typename Allocator_t::template ArrayPtr Array_t; typedef Node Node_t; typedef typename Allocator_t::template Ptr NodePtr_t; typedef Point Point_t; typedef Point NullPoint_t; template friend class NodeTest; static const int kSpecialId=0; struct NNResult { NNResult() : point_id_(0), distance_(numeric_limits::max()) { } bool operator<(const NNResult &other) const { if (point_id_==other.point_id_) { return distance_ &a, const pair &b) { return a.first *dataset); ~Node(); static void *operator new(size_t size); static void operator delete(void *p); bool IsLeaf() { return !points_.IsNULL(); } template pair ClosestChild(POINTTYPE point, int32 dimension, ComputationsCounter &comp); pair, pair > ClosestNode(NodePtr_t, NodePtr_t, int32 dimension, ComputationsCounter &comp); // This one is using a custom discriminator // We use this for timit experiments so that we exclude points // from the same speaker template void FindNearest(POINTTYPE query_point, vector > &nearest, NEIGHBORTYPE range, int32 dimension, PointIdDiscriminator_t &discriminator, ComputationsCounter &comp); // This one store the results directly on a memmory mapped file // for k-nearest neighbors and to a normal file for range nearest neighbors // very efficient for large datasets // Uses a custom descriminator template void FindAllNearest(NodePtr_t query_node, Precision_t &max_neighbor_distance, NEIGHBORTYPE range, int32 dimension, PointIdDiscriminator_t &discriminator, ComputationsCounter &comp); NodePtr_t& get_left() { return left_; } NodePtr_t& get_right() { return right_; } BoundingBox_t &get_box() { return box_; } typename Allocator_t::template ArrayPtr& get_points() { return points_; } index_t get_num_of_points() { return num_of_points_; } NNResult *get_kneighbors() { return kneighbors_; } void set_kneighbors(index_t knns) { //This is empty it is supposed to be used during the initialization //of the node. It has meaning only for the KnnNode } // This is used on an all knn query void set_kneighbors(NNResult *chunk, uint32 knns) { kneighbors_=chunk; index_.Lock(); for(index_t i=0; i< num_of_points_; i++) { for(index_t j=0; j<(index_t)knns; j++) { kneighbors_[i*knns+j].point_id_ = index_[i]; kneighbors_[i*knns+j].nearest_.Lock(); kneighbors_[i*knns+j].nearest_. set_id(numeric_limits::max()); kneighbors_[i*knns+j].nearest_.Unlock(); } } index_.Unlock(); } void InitKNeighbors(int32 knns); void set_range_neighbors(FILE *fp) { range_nn_fp_=fp; } FILE *get_range_nn_fp() { return range_nn_fp_; } Precision_t get_min_dist_so_far() { return min_dist_so_far_; } void set_min_dist_so_far(Precision_t distance) { min_dist_so_far_=distance; } index_t get_node_id() { return node_id_; } inline void LockPoints() { points_.Lock(); index_.Lock(); } inline void UnlockPoints() { points_.Unlock(); index_.Unlock(); } string Print(int32 dimension); private: BoundingBox_t box_; index_t node_id_; NodePtr_t left_; NodePtr_t right_; typename Allocator_t::template ArrayPtr index_; typename Allocator_t::template ArrayPtr points_; NodeCachedStatistics_t statistics_; index_t num_of_points_; union { NNResult *kneighbors_; FILE *range_nn_fp_; }; Precision_t min_dist_so_far_; }; #include "node_impl.h" #endif /*NODE_H_*/