#ifndef TRIPLETS_TRIPLET_H_ #define TRIPLETS_TRIPLET_H_ /** @file triplet.h implementation of a single triplet */ #include #include #include "data.h" #include "layout-ptr.h" #include "util.h" #include "vec.h" /** common base class for Triplets, Skewlets and half-skewlets */ template struct TripletBase_flex { typedef float layfield_t; typedef laygroup_t group_t; typedef TripletBase_flex TripletBase; hostdevice__ TripletBase_flex() : min_hit_time(FLT_MAX), max_hit_time(0), //sum_hit_time(0), pivot_time(0), //oldest_tube_id(0), pivot_tube_id(0), nhits(0), sum_hit_pos(fvec3::from(0.0f)) //, is_active(false) {} /** copies from id layout to current layout */ hostdevice__ void copy_from_id(const TripletBase &t) { sum_hit_pos = t.sum_hit_pos; max_hit_time = t.max_hit_time; min_hit_time = t.min_hit_time; pivot_time = t.pivot_time; pivot_tube_id = t.pivot_tube_id; nhits = t.nhits; } /** copies from current layout to id layout */ hostdevice__ void copy_to_id(TripletBase &t) const { t.sum_hit_pos = (fvec3)sum_hit_pos; t.max_hit_time = max_hit_time; t.min_hit_time = min_hit_time; t.pivot_time = pivot_time; t.pivot_tube_id = pivot_tube_id; t.nhits = nhits; } /** checks whether the triplet accepts the hit */ hostdevice__ bool accepts_hit(const Hit &hit) const; /** checks whether the triplet is good */ hostdevice__ bool is_good(void) const { return nhits >= 3 && nhits <= 6; } /** saves the CMS into the triplet, to avoid computing it multiple times later */ hostdevice__ void save_cms(void) { sum_hit_pos /= fvec3::from(nhits); } /** gets triplet's center of mass */ //hostdevice__ fvec3 cms(void) const { return sum_hit_pos / fvec3::from(nhits); } //hostdevice__ fvec3 cms(void) const { return sum_hit_pos * (1.0f / nhits); } hostdevice__ fvec3 cms(void) const { return sum_hit_pos; } /** time-related methods */ hostdevice__ float min_accept_window(void) const { return max_hit_time - DRIFT_TIME; } hostdevice__ float max_accept_window(void) const { return min_hit_time + DRIFT_TIME; } hostdevice__ float min_t0(void) const { return max_hit_time - DRIFT_TIME; } hostdevice__ float max_t0(void) const { return min_hit_time; } /** the number of neighbors */ hostdevice__ int nneighbors(void) const { return nhits - 1; } /** triplet's sum of hit positions; divide by nhits to get the CMS; for full skewlets this value stores poca */ vec3_flex sum_hit_pos; /** minimum, maximum, pivot and summed hit times */ union {float max_hit_time; group_t dummy0;}; union {float min_hit_time; group_t dummy1;}; union {float pivot_time; group_t dummy2;}; //float sum_hit_time; /** id of the oldest tube */ //int oldest_tube_id; union { struct { /** id of the pivot tube */ short pivot_tube_id; /** number of hits accumulated in a triplet */ short nhits; }; group_t dummy3; }; /** whether the triplet is active */ //bool is_active; }; // struct TripletBase_flex typedef TripletBase_flex TripletBase; template struct ParamTripletBase_flex : public TripletBase_flex { /** default constructor */ hostdevice__ ParamTripletBase_flex() : TripletBase_flex() {} /** helper constructor */ hostdevice__ ParamTripletBase_flex(const TripletBase &triplet) : TripletBase_flex (triplet) {} /** add hits from neighboring tubes to the triplet TODO: reconsider this function in case of bunched processing */ hostdevice__ void add_neighbors (const int *nneighbors, const int *neighbor_tubes, int neighbor_pitch, layptr tube_hits, const int *tube_hit_starts, layptr tubes); /** sets the pivot hit of the triplet */ hostdevice__ void set_pivot_hit (const Hit &pivot_hit, layptr tubes); /** adds a hit to the triplet @remarks acceptance tests are performed outside of triplet hit */ hostdevice__ void add_hit(const Hit &hit, layptr tubes); /** updates the CMS (sum of hit positions), to account for fancy updates in case of skewed straws */ }; /** triplet class */ template struct Triplet_flex : public ParamTripletBase_flex > { typedef Triplet_flex Triplet; hostdevice__ operator Triplet() const { Triplet triplet; TripletBase_flex::copy_to_id(triplet); return triplet; } hostdevice__ Triplet operator=(const Triplet &triplet) { TripletBase_flex::copy_from_id(triplet); return (Triplet)*this; } /** default constructor */ hostdevice__ Triplet_flex () : ParamTripletBase_flex >() {} /** helper constructor */ hostdevice__ Triplet_flex(const TripletBase &triplet) : ParamTripletBase_flex >(triplet) {} hostdevice__ void update_cms(const Hit &hits, layptr tubes); }; // struct Triplet_flex typedef Triplet_flex Triplet; template struct layflex_t { typedef Triplet_flex flex_t; }; /** half-skewlet class */ template struct HalfSkewlet_flex : public ParamTripletBase_flex > { typedef float layfield_t; typedef laygroup_t group_t; typedef HalfSkewlet_flex HalfSkewlet; hostdevice__ operator HalfSkewlet() const { HalfSkewlet skewlet; TripletBase_flex::copy_to_id(skewlet); skewlet.zmin = zmin; skewlet.zmax = zmax; return skewlet; } hostdevice__ HalfSkewlet operator=(const HalfSkewlet &skewlet) { TripletBase_flex::copy_from_id(skewlet); zmin = skewlet.zmin; zmax = skewlet.zmax; return (HalfSkewlet)*this; } /** default constructor */ hostdevice__ HalfSkewlet_flex() : ParamTripletBase_flex >(), zmin(35 - 75), zmax(35 + 75) {} hostdevice__ void update_cms(const Hit &hits, layptr tubes); /** minimum and maximum z values (only for half-skewlets) */ union {float zmin; group_t dummy10;}; union {float zmax; group_t dummy11;}; }; // struct HalfSkewlet typedef HalfSkewlet_flex HalfSkewlet; template struct layflex_t { typedef HalfSkewlet_flex flex_t; }; /** a skewlet; differs from the triplet only by adding the index of the next skewlet */ template struct Skewlet_flex : public Triplet_flex { typedef float layfield_t; typedef laygroup_t group_t; typedef Skewlet_flex Skewlet; hostdevice__ operator Skewlet() const { Skewlet skewlet; TripletBase_flex::copy_to_id(skewlet); skewlet.inext = inext; return skewlet; } hostdevice__ Skewlet operator=(const Skewlet &skewlet) { TripletBase_flex::copy_from_id(skewlet); inext = skewlet.inext; return (Skewlet)*this; } hostdevice__ Skewlet_flex() : Triplet_flex(), inext(-1) { //is_active = true; } hostdevice__ Skewlet_flex(const HalfSkewlet &triplet) : Triplet_flex(triplet), inext(-1) { //is_active = true; } /** adds another triplet to this triplet; mostly used to combine two half-skewlets into a single skewlet */ hostdevice__ void add_triplet(const HalfSkewlet &triplet); /** the index of the next skewlet */ union {int inext; group_t dummy10; }; }; // struct Skewlet typedef Skewlet_flex Skewlet; template struct layflex_t { typedef Skewlet_flex flex_t; }; /** finds crossing which is needed for skewlet construction */ inline __host__ __device__ fvec3 find_crossing (const fvec3 &p1, const fvec3 &u1, const fvec3 &p2, const fvec3 &u2); /** finds crossing which is needed for skewlet construction; uses additional knowledge of the properties of pi and ui vectors to avoid unnecessary computations */ inline __host__ __device__ fvec3 find_crossing_fast (const fvec3 &p1, const fvec3 &u1, const fvec3 &p2, const fvec3 &u2); #endif