266 lines
6.4 KiB
C++
266 lines
6.4 KiB
C++
#include "thor/thor.h"
|
|
#include "fastlib/fastlib.h"
|
|
|
|
/**
|
|
* An N-Body-Reduce problem.
|
|
*/
|
|
class Range {
|
|
public:
|
|
/** The bounding type. Required by THOR. */
|
|
typedef DHrectBound<2> Bound;
|
|
/** The type of point in use. Required by THOR. */
|
|
|
|
typedef ThorVectorPoint QPoint;
|
|
typedef ThorVectorPoint RPoint;
|
|
|
|
/**
|
|
* All parameters required by the execution of the algorithm.
|
|
*
|
|
* Required by N-Body Reduce.
|
|
*/
|
|
struct Param {
|
|
public:
|
|
index_t dim;
|
|
index_t count;
|
|
double h_orig;
|
|
double h_sq;
|
|
|
|
OT_DEF_BASIC(Param) {
|
|
OT_MY_OBJECT(dim);
|
|
OT_MY_OBJECT(count);
|
|
OT_MY_OBJECT(h_sq);
|
|
OT_MY_OBJECT(h_orig);
|
|
}
|
|
|
|
public:
|
|
/**
|
|
* Initialize parameters from a data node (Req THOR).
|
|
*/
|
|
void Init(datanode *datanode) {
|
|
dim = -1;
|
|
count = -1;
|
|
h_orig = fx_param_double_req(datanode, "h");
|
|
h_sq = h_orig * h_orig;
|
|
}
|
|
|
|
void SetDimensions(index_t dim_in, index_t count_in) {
|
|
dim = dim_in;
|
|
count = count_in;
|
|
}
|
|
};
|
|
|
|
typedef BlankStat QStat;
|
|
typedef BlankStat RStat;
|
|
|
|
typedef ThorNode<Bound, BlankStat> RNode;
|
|
typedef ThorNode<Bound, BlankStat> QNode;
|
|
|
|
typedef BlankDelta Delta;
|
|
|
|
/**
|
|
* Coarse result on a region.
|
|
*/
|
|
struct QPostponed {
|
|
public:
|
|
int count;
|
|
|
|
OT_DEF_BASIC(QPostponed) {
|
|
OT_MY_OBJECT(count);
|
|
}
|
|
|
|
public:
|
|
void Init(const Param& param) {
|
|
count = 0;
|
|
}
|
|
|
|
void Reset(const Param& param) {
|
|
count = 0;
|
|
}
|
|
|
|
void ApplyPostponed(const Param& param, const QPostponed& other) {
|
|
count += other.count;
|
|
}
|
|
};
|
|
|
|
|
|
// rho
|
|
struct QResult {
|
|
public:
|
|
index_t count;
|
|
|
|
OT_DEF_BASIC(QResult) {
|
|
OT_MY_OBJECT(count);
|
|
}
|
|
|
|
public:
|
|
void Init(const Param& param) {
|
|
count = 0;
|
|
}
|
|
|
|
void Postprocess(const Param& param,
|
|
const QPoint& q_point, index_t q_index,
|
|
const RNode& r_root) {}
|
|
void ApplyPostponed(const Param& param,
|
|
const QPostponed& postponed,
|
|
const QPoint& q_point,
|
|
index_t q_index) {
|
|
count += postponed.count;
|
|
}
|
|
};
|
|
|
|
typedef BlankQSummaryResult QSummaryResult;
|
|
|
|
struct GlobalResult {
|
|
public:
|
|
uint64 count;
|
|
|
|
OT_DEF_BASIC(GlobalResult) {
|
|
OT_MY_OBJECT(count);
|
|
}
|
|
|
|
public:
|
|
void Init(const Param& param) {
|
|
count = 0;
|
|
}
|
|
void Accumulate(const Param& param, const GlobalResult& other) {
|
|
count += other.count;
|
|
}
|
|
void Postprocess(const Param& param) {}
|
|
void Report(const Param& param, datanode *datanode) {
|
|
fx_format_result(datanode, "per_point_avg", "%g",
|
|
count / double(param.count));
|
|
fx_format_result(datanode, "per_pair_avg", "%g",
|
|
count / (double(param.count) * double(param.count)));
|
|
}
|
|
void ApplyResult(const Param& param,
|
|
const QPoint& q_point, index_t q_i,
|
|
const QResult& result) {}
|
|
|
|
public:
|
|
void Add(index_t q_count, index_t r_count) {
|
|
count += uint64(q_count) * r_count;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Abstract out the inner loop in a way that allows temporary variables
|
|
* to be register-allocated.
|
|
*/
|
|
struct PairVisitor {
|
|
public:
|
|
index_t count;
|
|
|
|
public:
|
|
void Init(const Param& param) {}
|
|
|
|
bool StartVisitingQueryPoint(const Param& param,
|
|
const QPoint& q_point,
|
|
index_t q_index,
|
|
const RNode& r_node,
|
|
const QSummaryResult& unapplied_summary_results,
|
|
QResult* q_result,
|
|
GlobalResult* global_result) {
|
|
double distance_sq_lo =
|
|
r_node.bound().MinDistanceSq(q_point.vec());
|
|
if (unlikely(distance_sq_lo > param.h_sq)) {
|
|
return false;
|
|
}
|
|
double distance_sq_hi =
|
|
r_node.bound().MaxDistanceSq(q_point.vec());
|
|
if (unlikely(distance_sq_hi <= param.h_sq)) {
|
|
q_result->count += r_node.count();
|
|
global_result->count += r_node.count();
|
|
return false;
|
|
}
|
|
count = 0;
|
|
return true;
|
|
}
|
|
|
|
void VisitPair(const Param& param,
|
|
const QPoint& q_point, index_t q_index,
|
|
const RPoint& r_point, index_t r_index) {
|
|
double trial_distance_sq = la::DistanceSqEuclidean(
|
|
q_point.vec(), r_point.vec());
|
|
if (trial_distance_sq <= param.h_sq) {
|
|
count++;
|
|
}
|
|
}
|
|
|
|
void FinishVisitingQueryPoint(const Param& param,
|
|
const QPoint& q_point,
|
|
index_t q_index,
|
|
const RNode& r_node,
|
|
const QSummaryResult& unapplied_summary_results,
|
|
QResult* q_result,
|
|
GlobalResult* global_result) {
|
|
q_result->count += count;
|
|
global_result->count += count;
|
|
}
|
|
};
|
|
|
|
class Algorithm {
|
|
public:
|
|
/**
|
|
* Calculates a delta....
|
|
*
|
|
* - If this returns true, delta is calculated, and global_result is
|
|
* updated. q_postponed is not touched.
|
|
* - If this returns false, delta is not touched.
|
|
*/
|
|
static bool ConsiderPairIntrinsic(const Param& param,
|
|
const QNode& q_node, const RNode& r_node,
|
|
Delta* delta,
|
|
GlobalResult* global_result, QPostponed* q_postponed) {
|
|
double distance_sq_lo =
|
|
q_node.bound().MinDistanceSq(r_node.bound());
|
|
if (unlikely(distance_sq_lo > param.h_sq)) {
|
|
return false;
|
|
}
|
|
double distance_sq_hi =
|
|
q_node.bound().MaxDistanceSq(r_node.bound());
|
|
if (unlikely(distance_sq_hi <= param.h_sq)) {
|
|
q_postponed->count += r_node.count();
|
|
global_result->Add(q_node.count(), r_node.count());
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool ConsiderPairExtrinsic(const Param& param,
|
|
const QNode& q_node, const RNode& r_node, const Delta& delta,
|
|
const QSummaryResult& q_summary_result, const GlobalResult& global_result,
|
|
QPostponed* q_postponed) {
|
|
return true;
|
|
}
|
|
|
|
static bool ConsiderQueryTermination(const Param& param,
|
|
const QNode& q_node,
|
|
const QSummaryResult& q_summary_result, const GlobalResult& global_result,
|
|
QPostponed* q_postponed) {
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Computes a heuristic for how early a computation should occur -- smaller
|
|
* values are earlier.
|
|
*/
|
|
static double Heuristic(const Param& param,
|
|
const QNode& q_node, const RNode& r_node, const Delta& delta) {
|
|
return 0;
|
|
}
|
|
};
|
|
};
|
|
|
|
int main(int argc, char *argv[]) {
|
|
fx_init(argc, argv);
|
|
|
|
thor::MonochromaticDualTreeMain<Range, DualTreeDepthFirst<Range> >(
|
|
fx_root, "range");
|
|
|
|
fx_done();
|
|
|
|
exit(0);
|
|
|
|
return 0;
|
|
}
|