LArSoft  v07_13_02
Liquid Argon Software toolkit - http://larsoft.org/
geo_vectors_utils.h
Go to the documentation of this file.
1 
17 #ifndef LARCOREOBJ_SIMPLETYPESANDCONSTANTS_GEO_VECTORS_UTILS_H
18 #define LARCOREOBJ_SIMPLETYPESANDCONSTANTS_GEO_VECTORS_UTILS_H
19 
20 // LArSoft libraries
22 
23 // C/C++ standard library
24 #include <array>
25 #include <vector>
26 #include <iterator> // std::back_inserter()
27 #include <type_traits> // std::declval(), std::is_same<>, ...
28 #include <functional> // std::mem_fn()
29 #include <cassert>
30 
31 
32 namespace geo {
33 
41  namespace vect {
42 
43  //--------------------------------------------------------------------------
44  namespace details {
45  //------------------------------------------------------------------------
46  template <typename Op, typename... T>
48 
49  template
50  <typename Op, typename First, typename Second, typename... Others>
51  struct AccumulateImpl<Op, First, Second, Others...> {
52  static auto compute(Op op, First&& a, Second&& b, Others&&... others)
53  -> decltype(auto)
54  {
55  return op(
56  a,
58  (op, std::forward<Second>(b), std::forward<Others>(others)...)
59  );
60  }
61  }; // AccumulateImpl<>
62 
63  template <typename Op, typename T>
64  struct AccumulateImpl<Op, T> {
65  static auto compute(Op, T&& v) -> decltype(auto)
66  { return std::forward<T>(v); }
67  };
68 
69  template <typename Op, typename... T>
70  auto extended_accumulate(Op op, T&&... args)
71  { return AccumulateImpl<Op, T...>::compute(op, std::forward<T>(args)...); }
72 
73 
74  template <typename... T>
75  auto extended_and(T... args) -> decltype(auto)
76  {
77  auto and_op = [](auto&& a, auto&& b) { return a && b; };
78  return extended_accumulate(and_op, std::forward<T>(args)...);
79  }
80 
81  //------------------------------------------------------------------------
82  //
83  // These two pages of metaprogramming madness are aimed to have objects
84  // that can provide a uniform coordinate get/set for any type of vector,
85  // with the minimal run-time overhead.
86  // Complications arise from the fact that TVector3 setter returns void,
87  // while GenVector vectors return a reference to the vector itself
88  // (hence the need of the additional SetterResult template parameter,
89  // and of quite some code to autodetect its value).
90  // The makeXxxx() functions are aimed to enclose the additional
91  // autodetection overlay, which should become unnecessary with C++17.
92  //
93 
94  template <typename Vector>
95  struct VectorScalar { using type = typename Vector::Scalar; };
96 
97  template <typename Vector>
99 
100 
101  //------------------------------------------------------------------------
102  template <typename Vector>
103  struct HasGetter {
104  private:
105 
106  template<typename Class>
107  static constexpr bool TestX(decltype(std::declval<Class>().X())*) { return true; }
108  template<typename Class>
109  static constexpr bool TestX(...) { return false; }
110  template<typename Class>
111  static constexpr bool TestY(decltype(std::declval<Class>().Y())*) { return true; }
112  template<typename Class>
113  static constexpr bool TestY(...) { return false; }
114  template<typename Class>
115  static constexpr bool TestZ(decltype(std::declval<Class>().Z())*) { return true; }
116  template<typename Class>
117  static constexpr bool TestZ(...) { return false; }
118  template<typename Class>
119  static constexpr bool TestT(decltype(std::declval<Class>().T())*) { return true; }
120  template<typename Class>
121  static constexpr bool TestT(...) { return false; }
122 
123  public:
124  static constexpr bool X = TestX<Vector>(nullptr);
125  static constexpr bool Y = TestY<Vector>(nullptr);
126  static constexpr bool Z = TestZ<Vector>(nullptr);
127  static constexpr bool T = TestT<Vector>(nullptr);
128  }; // struct HasGetter<>
129 
130  template <typename Vector>
131  constexpr bool HasX() { return HasGetter<Vector>::X; }
132  template <typename Vector>
133  constexpr bool HasY() { return HasGetter<Vector>::Y; }
134  template <typename Vector>
135  constexpr bool HasZ() { return HasGetter<Vector>::Z; }
136  template <typename Vector>
137  constexpr bool HasT() { return HasGetter<Vector>::T; }
138 
139  template <typename Vector>
140  constexpr unsigned int dimension() {
141  return HasT<Vector>()? 4U
142  : HasZ<Vector>()? 3U
143  : HasY<Vector>()? 2U
144  : HasX<Vector>()? 1U
145  : 0U;
146  } // dimension()
147 
148 
150  template <typename Vector>
151  using CoordinateArray_t
152  = std::array<VectorScalar_t<Vector>, dimension<Vector>()>;
153 
154 
155  template <typename T>
157  // with C++17 `result_type` is deprecated,
158  // and a different way will be needed
159  using type
160  = typename decltype(std::mem_fn(std::declval<T>()))::result_type;
161  }; // MemberFuncReturnType
162 
163  template <typename T>
165 
166  template <typename T>
168 
169  template <typename Class, typename Func>
170  struct MemberFuncClassType<Func Class::*> { using type = Class; };
171 
172  template <typename T>
174 
175 
176  template <typename Vector, typename SetterType = void>
178 
179  template <typename Vector>
180  struct BaseCoordTypes<Vector, void> {
181  using Vector_t = std::decay_t<Vector>;
183  using Getter_t = Scalar_t (Vector_t::*)() const;
184  }; // struct BaseCoordTypes<void>
185 
186  template <typename Vector, typename SetterType>
187  struct BaseCoordTypes {
188  private:
190 
191  public:
192  using Scalar_t = typename BaseTypes_t::Scalar_t;
193  using Vector_t = typename BaseTypes_t::Vector_t;
194  using Getter_t = typename BaseTypes_t::Getter_t;
195  using Setter_t = SetterType;
197  static_assert(
198  std::is_same<Setter_t, SetterReturn_t (Vector_t::*)(Scalar_t)>(),
199  "Invalid setter type"
200  );
201  }; // struct BaseCoordTypes<>
202 
203 
204  template <typename Vector>
206  private:
208  public:
209  using Vector_t = typename BaseTypes_t::Vector_t;
210  using Scalar_t = typename BaseTypes_t::Scalar_t;
211  using Getter_t = typename BaseTypes_t::Getter_t;
212  }; // struct CoordGetterTraits
213 
214 
216  template <typename Vector>
217  class CoordGetter {
219 
220  public:
221  using Vector_t = typename Traits_t::Vector_t;
222  using Scalar_t = typename Traits_t::Scalar_t;
223  using Getter_t = typename Traits_t::Getter_t;
224 
226  constexpr CoordGetter(Getter_t getter): fGetter(getter) {}
227 
229  Scalar_t operator() (Vector_t const& v) const { return get(v); }
230 
232  Scalar_t get(Vector_t const& v) const { return (v.*fGetter)(); }
233 
234  private:
236 
237  }; // class CoordGetter<>
238 
239  template <typename Getter>
240  constexpr auto makeCoordReader(Getter getter)
241  {
242  using Vector_t = std::remove_reference_t<MemberFuncClass_t<Getter>>;
243  return CoordGetter<Vector_t>{ getter };
244  }
245 
246 
247  template <typename Vector, typename SetterType>
249  private:
251  public:
252  using Vector_t = typename BaseTypes_t::Vector_t;
253  using Scalar_t = typename BaseTypes_t::Scalar_t;
254  using Getter_t = typename BaseTypes_t::Getter_t;
255  using Setter_t = typename BaseTypes_t::Setter_t;
256  }; // struct VectorCoordManagerTraits<>
257 
258 
260  template <typename Vector, typename SetterType>
261  class CoordManager: public CoordGetter<Vector> {
264 
265  public:
266  using Vector_t = typename Traits_t::Vector_t; // this is not constant
267  using Scalar_t = typename Traits_t::Scalar_t;
268  using Getter_t = typename Traits_t::Getter_t;
269  using Setter_t = typename Traits_t::Setter_t;
270 
272  constexpr CoordManager(Getter_t getter, Setter_t setter)
273  : Base_t(getter), fSetter(setter) {}
274 
276  void operator()(Vector_t& v, Scalar_t c) const { set(v, c); }
277 
279  void set(Vector_t& v, Scalar_t c) const { (v.*fSetter)(c); }
280 
282  void incr(Vector_t& v, Scalar_t c) const { set(v, Base_t::get(v) + c); }
283 
285  void decr(Vector_t& v, Scalar_t c) const { set(v, Base_t::get(v) - c); }
286 
288  void mult(Vector_t& v, Scalar_t f) const { set(v, Base_t::get(v) * f); }
289 
291  void div(Vector_t& v, Scalar_t f) const { set(v, Base_t::get(v) / f); }
292 
293  private:
295  }; // class CoordManager<>
296 
297 
298  template <typename Getter, typename Setter>
299  constexpr auto makeCoordManager(Getter getter, Setter setter)
300  {
301  using Vector_t = std::remove_reference_t<MemberFuncClass_t<Getter>>;
302  return CoordManager<Vector_t, Setter>{getter, setter};
303  }
304 
305 
306 
307  template <typename CoordHelper, typename StoredVector>
309 
310  public:
311  using Stored_t = StoredVector;
312 
313  using CoordHelper_t = CoordHelper;
315  using Scalar_t = typename CoordHelper_t::Scalar_t;
316  using Getter_t = typename CoordHelper_t::Getter_t;
317 
320  : fCoord(coordManager), fVector(v) {}
321 
324  : fCoord(getter), fVector(v) {}
325 
327  Scalar_t get() const { return manager().get(vector()); }
328 
330  Scalar_t operator() () const { return get(); }
331 
333  operator Scalar_t() const { return manager().get(vector()); }
334 
335  protected:
336  CoordHelper_t const& manager() const { return fCoord; }
337  Stored_t& vector() const { return fVector; }
338 
339  private:
342  }; // class VectorCoordGetter<>
343 
344 
345  template <typename CoordHelper, typename StoredVector>
347  : public BoundCoordGetter<CoordHelper, StoredVector>
348  {
350 
351  public:
352  using typename Base_t::Stored_t;
353 
354  using CoordHelper_t = CoordHelper;
356  using Scalar_t = typename CoordHelper_t::Scalar_t;
357  using Getter_t = typename CoordHelper_t::Getter_t;
358  using Setter_t = typename CoordHelper_t::Setter_t;
359 
362  : Base_t(v, coordManager) {}
363 
366  : Base_t(v, CoordHelper_t(getter, setter)) {}
367 
370  { Base_t::manager().set(Base_t::vector(), c); return *this; }
371 
374  { Base_t::manager().incr(Base_t::vector(), c); return *this; }
375 
377  BoundCoordManager& operator-= (Scalar_t c)
378  { Base_t::manager().decr(Base_t::vector(), c); return *this; }
379 
382  { Base_t::manager().mult(Base_t::vector(), f); return *this; }
383 
386  { Base_t::manager().div(Base_t::vector(), f); return *this; }
387 
388  }; // class BoundCoordManager
389 
390  //------------------------------------------------------------------------
391 
392  } // namespace details
393 
394 
395  // BEGIN Geometry group ------------------------------------------------------
398 
400  namespace extra {
401 
403  template <typename T>
404  T roundValue01(T value, T tol) {
405  if (std::abs(value) < tol) return 0.;
406  if (std::abs(std::abs(value) - 1.) < tol) return (value > 0.)? 1.: -1.;
407  return value;
408  } // roundValue01()
409 
410  } // namespace extra
411 
412 
413  // --- BEGIN Vector coordinate access abstraction --------------------------
415 
568  template <typename Vector>
570  constexpr unsigned int dimension() { return details::dimension<Vector>(); }
571  template <typename Vector>
572  constexpr unsigned int dimension(Vector&&) { return dimension<Vector>(); }
574 
576  template <typename Vector>
578  constexpr std::array<std::size_t, geo::vect::dimension<Vector>()> indices();
579  template <typename Vector>
580  constexpr auto indices(Vector const&) -> decltype(indices<Vector>());
582 
584  template <typename Vector>
586 
607  template <typename Vector, typename Coords>
608  constexpr Vector makeFromCoords(Coords&& coords);
609 
611  template <typename Vector>
612  using CoordReader_t
614 
616  template <typename Vector>
617  using CoordManager_t = decltype
619 
641  template <typename Vector>
642  static constexpr auto XcoordManager
644 
666  template <typename Vector>
667  static constexpr auto XcoordManager<Vector const>
669 
672  template <typename Vector>
673  static constexpr auto const YcoordManager
675 
678  template <typename Vector>
679  static constexpr auto YcoordManager<Vector const>
681 
684  template <typename Vector>
685  static constexpr auto ZcoordManager
687 
690  template <typename Vector>
691  static constexpr auto ZcoordManager<Vector const>
693 
696  template <typename Vector>
697  static constexpr auto TcoordManager
698  = details::makeCoordManager(&Vector::T, &Vector::SetT);
699 
702  template <typename Vector>
703  static constexpr auto TcoordManager<Vector const>
705 
706 
747  template <typename Vector>
748  constexpr auto coordManager(unsigned int n);
749 
761  template <typename Vector>
762  constexpr auto coordManager(unsigned int n, Vector& v);
763 
764 
766  template <typename Vector>
768  constexpr auto coordManagers();
769  template <typename Vector>
770  constexpr auto coordManagers(Vector&&);
772 
774  template <typename Vector>
776  constexpr auto coordReaders();
777  template <typename Vector>
778  constexpr auto coordReaders(Vector&&);
780 
781 
783  template <typename Vector>
784  constexpr auto bindCoord
785  (Vector const& v, CoordReader_t<Vector> helper)
786  {
788  (v, helper);
789  }
790 
792  template <typename Vector>
793  auto bindCoord(Vector& v, CoordManager_t<Vector> helper)
795  { return { v, helper }; }
796 
797 
808  template <typename Vector>
809  auto Xcoord(Vector& v)
810  { return bindCoord(v, XcoordManager<Vector>); }
811 
822  template <typename Vector>
823  auto Ycoord(Vector& v)
824  { return bindCoord<Vector>(v, YcoordManager<Vector>); }
825 
836  template <typename Vector>
837  auto Zcoord(Vector& v)
838  { return bindCoord<Vector>(v, ZcoordManager<Vector>); }
839 
850  template <typename Vector>
851  auto Tcoord(Vector& v)
852  { return bindCoord<Vector>(v, TcoordManager<Vector>); }
853 
865  template <typename Vector>
866  auto coord(Vector& v, unsigned int n) noexcept;
867 
868 
871  template <typename Vector>
872  constexpr auto bindCoordManagers(Vector& v);
873 
876  template <typename Vector>
877  constexpr auto bindCoordReaders(Vector const& v);
878 
879 
890  template <typename Dest, typename Source>
891  Dest convertTo(Source const& v);
892 
893 
909  template <typename Dest, typename Source>
910  std::vector<Dest> convertCollTo(std::vector<Source> const& coll);
911 
912 
924  template <typename Vector, typename Pred>
925  Vector transformCoords(Vector const& v, Pred&& pred);
926 
928  // --- END Vector coordinate access abstraction ----------------------------
929 
930 
931  // --- BEGIN Functions for common vector operations ------------------------
933 
963  template <typename Vector, typename Scalar>
965  Vector rounded01(Vector const& v, Scalar tol)
966  {
967  return transformCoords
968  (v, [tol](auto c){ return extra::roundValue01(c, tol); });
969  }
970 
972  template <typename Vector, typename Scalar>
973  void round01(Vector& v, Scalar tol) { v = rounded01(v, tol); }
974 
975 
977  template <typename Vector>
978  bool isfinite(Vector const& v);
979 
981  template <typename Vector>
982  Vector normalize(Vector const& v) { return v.Unit(); }
983 
985  template <typename Vector>
986  Vector cross(Vector const& a, Vector const& b) { return a.Cross(b); }
987 
989  template <typename Vector>
990  constexpr auto dot(Vector const& a, Vector const& b) { return a.Dot(b); }
991 
993  template <typename Vector>
994  auto mag2(Vector const& v) { return v.Mag2(); }
995 
997  template <typename Vector>
998  auto norm(Vector const& v) { return v.Mag(); }
999 
1002  template <typename Vector>
1003  auto mixedProduct(Vector const& a, Vector const& b, Vector const& c)
1004  { return dot(cross(a, b), c); }
1005 
1006 
1008  // --- END Functions for common vector operations --------------------------
1009 
1010 
1041  template <unsigned int N = 3U>
1043  static constexpr unsigned int Dim = N;
1044  std::array<Length_t, Dim> fSums;
1045  double fW = 0.0;
1046 
1047  public:
1049  MiddlePointAccumulatorDim() { fSums.fill(0.); }
1050 
1059  template <typename BeginIter, typename EndIter>
1062  { add(begin, end); }
1063 
1064 
1065  // --- BEGIN Result query ------------------------------------------------
1068 
1070  bool empty() const { return fW == 0.0; }
1071 
1073  double weight() const { return fW; }
1074 
1086  template <typename Point>
1088  // { return { fSums[0] / fW, fSums[1] / fW, fSums[2] / fW }; }
1089  { return makeWeightedPoint<Point>(1.0 / fW); }
1090 
1094  { return middlePointAs<geo::Point_t>(); }
1095 
1096 
1098  // --- END Result query --------------------------------------------------
1099 
1100  // --- BEGIN Addition of points ------------------------------------------
1103 
1111  template <typename Point>
1112  void add(Point const& p)
1113  {
1114  std::size_t ic = 0U;
1115  for (auto c: geo::vect::bindCoordManagers(p)) fSums[ic++] += c();
1116  fW += 1.0;
1117  }
1118 
1125  template <typename Point>
1126  void add(Point const& p, double weight)
1127  {
1128  std::size_t ic = 0U;
1129  for (auto c: geo::vect::bindCoordManagers(p))
1130  fSums[ic++] += weight * c();
1131  fW += weight;
1132  }
1133 
1143  template <typename BeginIter, typename EndIter>
1144  void add(BeginIter begin, EndIter end)
1145  { std::for_each(begin, end, [this](auto const& p){ this->add(p); }); }
1146 
1148  void clear() { fSums.fill(0.); fW = 0.0; }
1149 
1151  // --- END Addition of points --------------------------------------------
1152 
1153  private:
1154  using IndexSequence_t = std::make_index_sequence<Dim>;
1155 
1156  template <typename Point, std::size_t... I>
1157  Point makePointImpl(std::index_sequence<I...>) const
1158  { return { fSums.operator[](I)... }; }
1159 
1160  template <typename Point, std::size_t... I>
1161  Point makeWeightedPointImpl(double w, std::index_sequence<I...>) const
1162  { return { (fSums.operator[](I) * w)... }; }
1163 
1165  template <typename Point>
1167  { return geo::vect::makeFromCoords<Point>(fSums); }
1168 
1171  template <typename Point>
1172  Point makeWeightedPoint(double w) const
1173  { return makeWeightedPointImpl<Point>(w, IndexSequence_t{}); }
1174 
1175 
1176  }; // MiddlePointAccumulatorDim()
1177 
1178 
1181 
1182 
1183  // --- BEGIN Middle point functions ----------------------------------------
1186 
1210  template <typename Point, typename BeginIter, typename EndIter>
1211  Point middlePointAs(BeginIter begin, EndIter end)
1212  {
1213  constexpr auto Dim = geo::vect::dimension<Point>();
1215  .template middlePointAs<Point>();
1216  }
1217 
1239  template <typename BeginIter, typename EndIter>
1240  geo::Point_t middlePoint(BeginIter begin, EndIter end)
1241  { return middlePointAs<geo::Point_t>(begin, end); }
1242 
1259  template <typename Point>
1260  Point middlePoint(std::initializer_list<Point> points)
1261  {
1262  constexpr auto Dim = geo::vect::dimension<Point>();
1263  return MiddlePointAccumulatorDim<Dim>(points.begin(), points.end())
1264  .template middlePointAs<Point>();
1265  }
1266 
1268  // --- END Middle point functions ------------------------------------------
1269 
1270 
1271  // --- BEGIN Support for LArSoft geometry vectors --------------------------
1274 
1275  // import global definitions
1278 
1280  template <typename Point>
1282  { return geo::vect::convertTo<::geo::Point_t>(p); }
1283 
1285  template <typename Vector>
1286  ::geo::Vector_t toVector(Vector const& v)
1287  { return geo::vect::convertTo<::geo::Vector_t>(v); }
1288 
1289 
1292  template <typename Point>
1293  std::vector<geo::Point_t> convertCollToPoint
1294  (std::vector<Point> const& coll)
1295  { return convertCollTo<geo::Point_t>(coll); }
1296 
1299  template <typename Vector>
1300  std::vector<geo::Vector_t> convertCollToVector
1301  (std::vector<Vector> const& coll)
1302  { return convertCollTo<geo::Vector_t>(coll); }
1303 
1304 
1306  template <typename Coords>
1308  { return makeFromCoords<::geo::Point_t>(std::forward<Coords>(coords)); }
1309 
1311  template <typename Coords>
1313  { return makeFromCoords<::geo::Vector_t>(std::forward<Coords>(coords)); }
1314 
1316  // --- END Support for LArSoft geometry vectors ----------------------------
1317 
1318 
1319  } // namespace vect
1320 
1322  // END Geometry group --------------------------------------------------------
1323 
1324 } // namespace geo
1325 
1326 
1327 //------------------------------------------------------------------------------
1328 //--- template specializations for standard geometry vectors
1329 //---
1330 namespace geo {
1331  namespace vect {
1332 
1333  //--------------------------------------------------------------------------
1334  template <>
1335  inline auto norm(geo::Vector_t const& v) { return v.R(); }
1336 
1337  //--------------------------------------------------------------------------
1338 
1339  } // namespace vect
1340 } // namespace geo
1341 
1342 
1343 //------------------------------------------------------------------------------
1344 //--- template implementation
1345 
1346 namespace geo {
1347  namespace vect {
1348  namespace details {
1349 
1350  //------------------------------------------------------------------------
1351  template <typename> struct AlwaysFalse: std::false_type {};
1352 
1353 
1354  // constexpr variant of forward (from StackExchange)
1355  template <typename T>
1356  constexpr T&& constexpr_forward(std::remove_reference_t<T>& t)
1357  { return static_cast<T&&>(t); }
1358 
1359  template<typename T>
1360  constexpr T&& constexpr_forward(std::remove_reference_t<T>&& t)
1361  {
1362  static_assert(!std::is_lvalue_reference<T>(),
1363  "template argument substituting T is an lvalue reference type");
1364  return static_cast<T&&>(t);
1365  }
1366 
1367  //------------------------------------------------------------------------
1369  template <typename Vector>
1370  using VectorIndices_t = std::make_index_sequence<dimension<Vector>()>;
1371 
1372  template <typename Vector>
1373  constexpr auto makeVectorIndices() { return VectorIndices_t<Vector>{}; }
1374 
1375  template <typename Vector>
1376  constexpr auto makeVectorIndices(Vector&&)
1377  { return makeVectorIndices<Vector>(); }
1378 
1379 
1380  template <typename T, T... Indices>
1381  constexpr auto makeIndexSeqImpl(std::integer_sequence<T, Indices...>)
1382  // BUG the double brace syntax is required to work around clang bug 21629
1383  // (https://bugs.llvm.org/show_bug.cgi?id=21629)
1384  { return std::array<T, sizeof...(Indices)>{{ Indices... }}; }
1385 
1386  // fill a sequence object with the first `N` values of type `T`.
1387  template <typename T, T N>
1388  constexpr auto makeIndexSeq()
1389  { return makeIndexSeqImpl<T>(std::make_integer_sequence<T, N>{}); }
1390 
1391 
1392  //------------------------------------------------------------------------
1393  template <std::size_t I, typename Data>
1394  constexpr auto accessElement(Data&& data) { return data[I]; }
1395 
1396  template <typename Vector, typename Coords, std::size_t... Indices>
1397  constexpr Vector makeFromCoordsImpl
1398  (Coords&& coords, std::index_sequence<Indices...>)
1399  {
1400  return
1401  { accessElement<Indices>(constexpr_forward<Coords>(coords))... };
1402  }
1403 
1404 
1405  //------------------------------------------------------------------------
1406  template <typename Vector>
1407  constexpr CoordManager_t<Vector> NoCoordManager{ nullptr, nullptr };
1408 
1409  template <typename Vector, unsigned int Dim = dimension<Vector>()>
1411 
1412  template <typename Vector>
1413  struct CoordManagerImpl<Vector, 1U> {
1414  static auto get(unsigned int n) noexcept
1415  { return (n == 0)? XcoordManager<Vector>: NoCoordManager<Vector>; }
1416  }; // CoordManagerImpl<1U>
1417 
1418  template <typename Vector>
1419  struct CoordManagerImpl<Vector, 2U> {
1420  static auto get(unsigned int n) noexcept
1421  {
1422  return (n == 1)
1423  ? YcoordManager<Vector>: CoordManagerImpl<Vector, 1U>::get(n);
1424  }
1425  }; // CoordManagerImpl<2U>
1426 
1427  template <typename Vector>
1428  struct CoordManagerImpl<Vector, 3U> {
1429  static auto get(unsigned int n) noexcept
1430  {
1431  return (n == 2)
1432  ? ZcoordManager<Vector>: CoordManagerImpl<Vector, 2U>::get(n);
1433  }
1434  }; // CoordManagerImpl<3U>
1435 
1436  template <typename Vector>
1437  struct CoordManagerImpl<Vector, 4U> {
1438  static auto get(unsigned int n) noexcept
1439  {
1440  return (n == 3)
1441  ? TcoordManager<Vector>: CoordManagerImpl<Vector, 3U>::get(n);
1442  }
1443 
1444  }; // CoordManagerImpl<4U>
1445 
1446 
1447  //------------------------------------------------------------------------
1448  template <typename Vector, unsigned int N>
1450  static constexpr unsigned int Dim = N;
1451 
1452  using Manager_t = decltype(XcoordManager<Vector>);
1453  using Return_t = std::array<Manager_t, Dim>;
1454 
1455  static_assert(dimension<Vector>() == Dim, "Inconsistent vector size.");
1456  }; // CoordManagersImplBase
1457 
1458  template <typename Vector, unsigned int N>
1460 
1461  template <typename Vector>
1462  struct CoordManagersImpl<Vector, 2U>
1463  : private CoordManagersImplBase<Vector, 2U>
1464  {
1466  using typename Base_t::Return_t;
1467  static constexpr Return_t get()
1468  {
1469  // BUG the double brace syntax is required to work around clang bug 21629
1470  // (https://bugs.llvm.org/show_bug.cgi?id=21629)
1471  return {{
1472  XcoordManager<Vector>
1473  , YcoordManager<Vector>
1474  }};
1475  }
1476  }; // CoordManagersImpl<2U>
1477 
1478  template <typename Vector>
1479  struct CoordManagersImpl<Vector, 3U>
1480  : private CoordManagersImplBase<Vector, 3U>
1481  {
1483  using typename Base_t::Return_t;
1484  static constexpr Return_t get()
1485  {
1486  // BUG the double brace syntax is required to work around clang bug 21629
1487  // (https://bugs.llvm.org/show_bug.cgi?id=21629)
1488  return {{
1489  XcoordManager<Vector>
1490  , YcoordManager<Vector>
1491  , ZcoordManager<Vector>
1492  }};
1493  }
1494  }; // CoordManagersImpl<3U>
1495 
1496  template <typename Vector>
1497  struct CoordManagersImpl<Vector, 4U>
1498  : private CoordManagersImplBase<Vector, 4U>
1499  {
1501  using typename Base_t::Return_t;
1502  static constexpr Return_t get()
1503  {
1504  // BUG the double brace syntax is required to work around clang bug 21629
1505  // (https://bugs.llvm.org/show_bug.cgi?id=21629)
1506  return {{
1507  XcoordManager<Vector>
1508  , YcoordManager<Vector>
1509  , ZcoordManager<Vector>
1510  , TcoordManager<Vector>
1511  }};
1512  }
1513  }; // CoordManagersImpl<4U>
1514 
1515 
1516  //------------------------------------------------------------------------
1517  template <typename Vector, unsigned int N>
1519  static constexpr unsigned int Dim = N;
1520 
1521  using Manager_t = decltype(Xcoord(std::declval<Vector>()));
1522  using Return_t = std::array<Manager_t, Dim>;
1523 
1524  static_assert(dimension<Vector>() == Dim, "Inconsistent vector size.");
1525  }; // CoordManagersImplBase
1526 
1527  template <typename Vector, unsigned int N>
1529 
1530  template <typename Vector>
1531  struct BindCoordManagersImpl<Vector, 2U>
1532  : private BindCoordManagersImplBase<Vector, 2U>
1533  {
1535  using typename Base_t::Return_t;
1536  static Return_t bind(Vector& v)
1537  {
1538  // BUG the double brace syntax is required to work around clang bug 21629
1539  // (https://bugs.llvm.org/show_bug.cgi?id=21629)
1540  return {{
1541  Xcoord(v)
1542  , Ycoord(v)
1543  }};
1544  }
1545  }; // BindCoordManagersImpl<2U>
1546 
1547  template <typename Vector>
1548  struct BindCoordManagersImpl<Vector, 3U>
1549  : private BindCoordManagersImplBase<Vector, 3U>
1550  {
1552  using typename Base_t::Return_t;
1553  static Return_t bind(Vector& v)
1554  {
1555  // BUG the double brace syntax is required to work around clang bug 21629
1556  // (https://bugs.llvm.org/show_bug.cgi?id=21629)
1557  return {{
1558  Xcoord(v)
1559  , Ycoord(v)
1560  , Zcoord(v)
1561  }};
1562  }
1563  }; // BindCoordManagersImpl<3U>
1564 
1565  template <typename Vector>
1566  struct BindCoordManagersImpl<Vector, 4U>
1567  : private BindCoordManagersImplBase<Vector, 4U>
1568  {
1570  using typename Base_t::Return_t;
1571  static Return_t bind(Vector& v)
1572  {
1573  // BUG the double brace syntax is required to work around clang bug 21629
1574  // (https://bugs.llvm.org/show_bug.cgi?id=21629)
1575  return {{
1576  Xcoord(v)
1577  , Ycoord(v)
1578  , Zcoord(v)
1579  , Tcoord(v)
1580  }};
1581  }
1582  }; // BindCoordManagersImpl<4U>
1583 
1584 
1585  //------------------------------------------------------------------------
1586  template<typename Dest, typename Source>
1588  static_assert(dimension<Source>() == dimension<Dest>(),
1589  "Source and destination vectors must have the same dimension.");
1590  }; // struct ConvertToImplBase
1591 
1592 
1593  // special pass-through case
1594  template <typename Dest, typename Source, unsigned int Dim>
1595  struct ConvertToImpl {
1596  // trivial to do: open a feature request!
1597  static_assert(
1599  "This vector dimensionality is not implemented yet."
1600  );
1601  }; // struct ConvertToImpl
1602 
1603  template <typename Dest, typename Source>
1604  struct ConvertToImpl<Dest, Source, 2U>
1605  : private ConvertToImplBase<Dest, Source>
1606  {
1607  static Dest convert(Source const& v)
1608  { return { Xcoord(v)(), Ycoord(v)() }; }
1609  }; // struct ConvertToImpl<2U>
1610 
1611  template <typename Dest, typename Source>
1612  struct ConvertToImpl<Dest, Source, 3U>
1613  : private ConvertToImplBase<Dest, Source>
1614  {
1615  static Dest convert(Source const& v)
1616  { return { Xcoord(v)(), Ycoord(v)(), Zcoord(v)() }; }
1617  }; // struct ConvertToImpl<3U>
1618 
1619  template <typename Dest, typename Source>
1620  struct ConvertToImpl<Dest, Source, 4U>
1621  : private ConvertToImplBase<Dest, Source>
1622  {
1623  static Dest convert(Source const& v)
1624  { return { Xcoord(v)(), Ycoord(v)(), Zcoord(v)(), Tcoord(v)() }; }
1625  }; // struct ConvertToImpl<4U>
1626 
1627 
1628  template
1629  <typename Dest, typename Source, unsigned int Dim = dimension<Source>()>
1631 
1632  // special pass-through case
1633  template <typename Vector, unsigned int Dim>
1635  static_assert
1636  (Dim == dimension<Vector>(), "Inconsistent vector dimension");
1637  static constexpr Vector convert(Vector const& v) { return v; }
1638  }; // struct ConvertToDispatcher<pass through>
1639 
1640 
1641  //------------------------------------------------------------------------
1642  template <typename Point, std::size_t... I>
1643  bool isfiniteImpl(Point const& point, std::index_sequence<I...>)
1644  { return extended_and(std::isfinite(coord(point, I).get())...); }
1645 
1646  //------------------------------------------------------------------------
1647 
1648  } // namespace details
1649  } // namespace vect
1650 } // namespace geo
1651 
1652 
1653 //------------------------------------------------------------------------------
1654 template <typename Vector>
1655 constexpr std::array<std::size_t, geo::vect::dimension<Vector>()>
1657 {
1658  return details::makeIndexSeq<std::size_t, dimension<Vector>()>();
1659 }
1660 
1661 template <typename Vector>
1662 constexpr auto geo::vect::indices(Vector const&) -> decltype(indices<Vector>())
1663  { return indices<Vector>(); }
1664 
1665 
1666 //------------------------------------------------------------------------
1667 template <typename Vector, typename Coords>
1668 constexpr Vector geo::vect::makeFromCoords(Coords&& coords) {
1669  using namespace geo::vect::details;
1670  return makeFromCoordsImpl<Vector>
1671  (constexpr_forward<Coords>(coords), makeVectorIndices<Vector>());
1672 } // geo::vect::makeFromCoords()
1673 
1674 
1675 //------------------------------------------------------------------------------
1676 template <typename Vector>
1677 constexpr auto geo::vect::coordManager(unsigned int n)
1679 
1680 
1681 //------------------------------------------------------------------------------
1682 template <typename Vector>
1683 auto geo::vect::coord(Vector& v, unsigned int n) noexcept {
1684  return vect::bindCoord<Vector>(v, coordManager<Vector>(n));
1685 }
1686 
1687 
1688 //------------------------------------------------------------------------------
1689 template <typename Vector>
1690 constexpr auto geo::vect::coordManagers() {
1691  using PlainVector = std::remove_reference_t<Vector>;
1692  return
1694 } // geo::vect::coordManagers()
1695 
1696 template <typename Vector>
1697 constexpr auto geo::vect::coordManagers(Vector&&)
1698  { return coordManagers<Vector>(); }
1699 
1700 
1701 template <typename Vector>
1702 constexpr auto geo::vect::coordReaders() {
1703  using ConstVector = std::add_const_t<std::remove_reference_t<Vector>>;
1704  return
1706 } // geo::vect::coordReaders()
1707 
1708 template <typename Vector>
1709 constexpr auto geo::vect::coordReaders(Vector&&)
1710  { return coordReaders<Vector>(); }
1711 
1712 
1713 //------------------------------------------------------------------------------
1714 template <typename Vector>
1715 constexpr auto geo::vect::bindCoordManagers(Vector& v) {
1717 } // geo::vect::bindCoordManagers()
1718 
1719 
1720 template <typename Vector>
1721 constexpr auto geo::vect::bindCoordReaders(Vector const& v) {
1722  using ConstVector = std::add_const_t<std::remove_reference_t<Vector>>;
1724  ::bind(v);
1725 } // geo::vect::bindCoordReaders()
1726 
1727 
1728 //------------------------------------------------------------------------------
1729 template <typename Dest, typename Source>
1730 Dest geo::vect::convertTo(Source const& v)
1732 
1733 
1734 //----------------------------------------------------------------------------
1735 template <typename Dest, typename Source>
1736 std::vector<Dest> geo::vect::convertCollTo(std::vector<Source> const& coll) {
1737 
1738  std::vector<Dest> dest;
1739  dest.reserve(coll.size());
1740  std::transform(coll.begin(), coll.end(), std::back_inserter(dest),
1741  geo::vect::convertTo<Dest, Source>);
1742  return dest;
1743 
1744 } // geo::vect::convertCollTo()
1745 
1746 
1747 //------------------------------------------------------------------------
1748 template <typename Vector, typename Pred>
1749 Vector geo::vect::transformCoords(Vector const& v, Pred&& pred) {
1751  unsigned int i = 0;
1752  for (auto c: bindCoordReaders(v)) values[i++] = pred(c());
1753  return makeFromCoords<Vector>(values);
1754 } // geo::vect::transformCoords()
1755 
1756 
1757 //------------------------------------------------------------------------------
1758 template <typename Vector>
1759 bool geo::vect::isfinite(Vector const& v)
1760  { return details::isfiniteImpl(v, details::makeVectorIndices<Vector>()); }
1761 
1762 //------------------------------------------------------------------------------
1763 
1764 
1765 #endif // LARCOREOBJ_SIMPLETYPESANDCONSTANTS_GEO_VECTORS_UTILS_H
void operator()(Vector_t &v, Scalar_t c) const
Setter: assigns a value to the bound coordinate of specified vector.
constexpr auto coordManager(unsigned int n)
Returns an object that can be bound to a vector to manage one of its coordinates. ...
static constexpr bool TestZ(...)
void round01(Vector &v, Scalar tol)
Returns a vector with all components rounded if close to 0, -1 or +1.
static constexpr auto XcoordManager< Vector const >
Object that can be bound to a vector to access its X coordinate.
constexpr T && constexpr_forward(std::remove_reference_t< T > &t)
ROOT::Math::DisplacementVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Vector_t
Type for representation of momenta in 3D space.
Definition: geo_vectors.h:167
typename BaseTypes_t::Scalar_t Scalar_t
BoundCoordManager(Stored_t &v, CoordHelper_t coordManager)
Constructor: manage the specified coordinate of specified vector.
typename Traits_t::Getter_t Getter_t
void clear()
Resets the status of the object to no accumulated points.
typename CoordHelper_t::Getter_t Getter_t
constexpr auto dot(Vector const &a, Vector const &b)
Return cross product of two vectors.
Point makePoint() const
Converts the internal sums into a Point.
constexpr auto accessElement(Data &&data)
static auto compute(Op op, First &&a, Second &&b, Others &&...others) -> decltype(auto)
Point middlePointAs() const
Returns the middle point, NaN components if no point.
auto Zcoord(Vector &v)
Returns an object to manage the coordinate Z of the vector v.
static constexpr bool TestX(...)
constexpr auto makeIndexSeq()
constexpr auto makeVectorIndices()
static constexpr auto XcoordManager
Object that can be bound to a vector to manage its X coordinate.
Point makePointImpl(std::index_sequence< I... >) const
std::vector< Dest > convertCollTo(std::vector< Source > const &coll)
Returns a vector of type Dest with the same content as a Src.
void mult(Vector_t &v, Scalar_t f) const
Multiplies the coordinate by the specified amount.
static constexpr auto YcoordManager< Vector const >
static constexpr auto const YcoordManager
typename BaseTypes_t::Vector_t Vector_t
auto mixedProduct(Vector const &a, Vector const &b, Vector const &c)
auto coord(Vector &v, unsigned int n) noexcept
Returns an object to manage the coordinate n of a vector.
constexpr auto bindCoordReaders(Vector const &v)
typename Vector::Scalar type
Helper class to compute the middle point in a point set.
constexpr auto makeCoordReader(Getter getter)
Float_t Y
Definition: plot.C:39
typename Traits_t::Setter_t Setter_t
constexpr auto makeIndexSeqImpl(std::integer_sequence< T, Indices... >)
typename MemberFuncReturnType< T >::type MemberFuncReturn_t
double weight() const
Returns the total weight (number of points if all have weight 1).
::geo::Point_t toPoint(Point const &p)
Convert the specified point into a geo::Point_t.
constexpr bool HasX()
::geo::Vector_t toVector(Vector const &v)
Convert the specified vector into a geo::Vector_t.
static constexpr auto TcoordManager
constexpr auto bindCoord(Vector const &v, CoordReader_t< Vector > helper)
Binds the specified constant vector to the coordinate reader.
BoundCoordManager(Stored_t &v, Getter_t getter, Setter_t setter)
Constructor: manage the specified vector with specified methods.
static constexpr auto ZcoordManager
decltype(Xcoord(std::declval< Vector >())) Manager_t
typename BaseTypes_t::Getter_t Getter_t
typename BaseTypes_t::Setter_t Setter_t
constexpr auto coordManagers()
Returns an array with all coordinate managers for a type of vector.
Helper class for read/write of a single vector coordinate.
typename CoordHelper_t::Vector_t Vector_t
typename MemberFuncClassType< T >::type MemberFuncClass_t
BoundCoordGetter(Stored_t &v, Getter_t getter)
Constructor: manage the specified vector with specified methods.
std::array< Length_t, Dim > fSums
Sum of each of the point components.
void add(Point const &p)
Accumulates a point.
static constexpr auto ZcoordManager< Vector const >
recob::tracking::Point_t Point_t
typename BaseTypes_t::Scalar_t Scalar_t
Point middlePointAs(BeginIter begin, EndIter end)
Returns the middle of the specified points.
void add(Point const &p, double weight)
Accumulates a point.
Float_t Z
Definition: plot.C:39
static constexpr bool TestX(decltype(std::declval< Class >().X())*)
TFile f
Definition: plotHisto.C:6
typename VectorScalar< Vector >::type VectorScalar_t
typename Traits_t::Vector_t Vector_t
constexpr unsigned int dimension()
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:265
constexpr auto coordReaders()
Returns an array with all coordinate readers for a type of vector.
void decr(Vector_t &v, Scalar_t c) const
Decrements the coordinate by the specified amount.
bool isfinite(Vector const &v)
Returns whether all components of the vector are finite.
typename BaseTypes_t::Vector_t Vector_t
auto array(Array const &a)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:228
typename Traits_t::Scalar_t Scalar_t
Getter_t fGetter
Member function returning the coordinate value.
constexpr CoordManager_t< Vector > NoCoordManager
void add(BeginIter begin, EndIter end)
Adds a sequence of points.
bool empty() const
Returns whether the total weight is zero (usually means no points).
typename BaseTypes_t::Vector_t Vector_t
void incr(Vector_t &v, Scalar_t c) const
Increments the coordinate by the specified amount.
Definitions of geometry vector data types.
std::vector< geo::Point_t > convertCollToPoint(std::vector< Point > const &coll)
T roundValue01(T value, T tol)
Returns value, rounded to 0, -1 or +1 if closer than tol.
constexpr Vector makeFromCoordsImpl(Coords &&coords, std::index_sequence< Indices... >)
constexpr CoordGetter(Getter_t getter)
Constructor: sets getter and setter functions.
typename BaseTypes_t::Scalar_t Scalar_t
std::tuple< double, double, const reco::ClusterHit3D * > Point
Definitions used by the VoronoiDiagram algorithm.
Definition: DCEL.h:34
MiddlePointAccumulatorDim(BeginIter begin, EndIter end)
Constructor: starts with accumulating a sequence of points.
typename CoordHelper_t::Setter_t Setter_t
std::vector< evd::details::RawDigitInfo_t >::const_iterator begin(RawDigitCacheDataClass const &cache)
typename CoordHelper_t::Scalar_t Scalar_t
constexpr std::array< std::size_t, geo::vect::dimension< Vector >)> indices()
Returns a sequence of indices valid for a vector of the specified type.
MemberFuncReturn_t< Setter_t > SetterReturn_t
constexpr auto makeCoordManager(Getter getter, Setter setter)
String & operator+=(String &s, VectorDumper< Vector > const &manip)
Appends a string rendering of a vector to the specified string.
Definition: DumpUtils.h:424
auto Ycoord(Vector &v)
Returns an object to manage the coordinate Y of the vector v.
typename decltype(std::mem_fn(std::declval< T >()))::result_type type
static constexpr bool TestY(...)
constexpr bool HasT()
bool isfiniteImpl(Point const &point, std::index_sequence< I... >)
Vector transformCoords(Vector const &v, Pred &&pred)
Returns a new vector applying a predicate to each component.
static auto compute(Op, T &&v) -> decltype(auto)
CoordHelper_t fCoord
Helper to manage a specific coordinate.
auto norm(Vector const &v)
Return norm of the specified vector.
Vector rounded01(Vector const &v, Scalar tol)
Returns a vector with all components rounded if close to 0, -1 or +1.
auto mag2(Vector const &v)
Return norm of the specified vector.
auto Xcoord(Vector &v)
Returns an object to manage the coordinate X of the vector v.
typename BaseTypes_t::Getter_t Getter_t
Point makeWeightedPointImpl(double w, std::index_sequence< I... >) const
BoundCoordGetter(Stored_t &v, CoordHelper_t coordManager)
Constructor: manage the specified coordinate of specified vector.
constexpr bool HasZ()
double weight
Definition: plottest35.C:25
auto Tcoord(Vector &v)
Returns an object to manage the coordinate T of the vector v.
std::string value(boost::any const &)
constexpr bool HasY()
CoordHelper_t const & manager() const
auto extended_accumulate(Op op, T &&...args)
typename BaseTypes_t::Getter_t Getter_t
auto extended_and(T...args) -> decltype(auto)
std::make_index_sequence< Dim > IndexSequence_t
static constexpr auto TcoordManager< Vector const >
std::array< VectorScalar_t< Vector >, dimension< Vector >()> CoordinateArray_t
A STL array suitable to contain all coordinate values of a Vector.
decltype(details::makeCoordReader(&Vector::X)) CoordReader_t
Type of a coordinate reader for a vector type.
std::vector< geo::Vector_t > convertCollToVector(std::vector< Vector > const &coll)
constexpr auto bindCoordManagers(Vector &v)
constexpr CoordManager(Getter_t getter, Setter_t setter)
Constructor: sets getter and setter functions.
Setter_t fSetter
Member function setting the coordinate value.
Stored_t & fVector
The vector to manage the coordinate of.
MiddlePointAccumulatorDim()
Default constructor: starts with no accumulated point.
Helper class for read of a single vector coordinate.
Char_t n[5]
details::VectorScalar_t< Vector > coordinate_t
Type of coordinate of the specified vector type.
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
constexpr Vector makeFromCoords(Coords &&coords)
Creates a Vector object with coordinates from coords.
static constexpr bool TestT(...)
std::make_index_sequence< dimension< Vector >()> VectorIndices_t
Type of sequence of indices up to Vector size.
Vector cross(Vector const &a, Vector const &b)
Return cross product of two vectors.
Vector normalize(Vector const &v)
Returns a vector parallel to v and with norm 1.
Dest convertTo(Source const &v)
Returns a vector of type Dest with the same content as a Src.
Eigen::Vector3f Coords
Definition: DCEL.h:36
void div(Vector_t &v, Scalar_t f) const
Divides the coordinate by the specified amount.
decltype(details::makeCoordManager(&Vector::X,&Vector::SetX)) CoordManager_t
Type of a coordinate manager for a vector type.
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
Definition: geo_vectors.h:187
Float_t X
Definition: plot.C:39
GENVECTOR_CONSTEXPR::geo::Point_t makePointFromCoords(Coords &&coords)
Creates a geo::Point_t from its coordinates (see makeFromCoords()).
Namespace collecting geometry-related classes utilities.
Float_t w
Definition: plot.C:23
GENVECTOR_CONSTEXPR::geo::Vector_t makeVectorFromCoords(Coords &&coords)
Creates a geo::Vector_t from its coordinates (see makeFromCoords()).
recob::tracking::Vector_t Vector_t
geo::Point_t middlePoint(BeginIter begin, EndIter end)
Returns the middle of the specified points.
static constexpr bool TestY(decltype(std::declval< Class >().Y())*)
static constexpr bool TestZ(decltype(std::declval< Class >().Z())*)
static constexpr bool TestT(decltype(std::declval< Class >().T())*)