All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
geo_vectors_utils.h
Go to the documentation of this file.
1 /**
2  * @file larcorealg/Geometry/geo_vectors_utils.h
3  * @brief Utilities to extend the interface of geometry vectors.
4  * @author Gianluca Petrillo (petrillo@fnal.gov)
5  * @date November 27, 2017
6  * @ingroup Geometry
7  *
8  * This library provides facilities that can be used for both LArSoft geometry
9  * vectors (`geo_vectors.h`) and ROOT `TVector3` and related, with the same
10  * interface.
11  *
12  * This library depends on ROOT GenVector.
13  * In the CET link list in `CMakeLists.txt`, link to `${ROOT_GENVECTOR}`.
14  *
15  */
16 
17 #ifndef LARCOREOBJ_SIMPLETYPESANDCONSTANTS_GEO_VECTORS_UTILS_H
18 #define LARCOREOBJ_SIMPLETYPESANDCONSTANTS_GEO_VECTORS_UTILS_H
19 
20 // LArSoft libraries
23 
24 // ROOT libraries
25 #include "Math/GenVector/PositionVector2D.h"
26 #include "Math/GenVector/DisplacementVector2D.h"
27 #include "Math/GenVector/PositionVector3D.h"
28 #include "Math/GenVector/DisplacementVector3D.h"
29 #include "Math/GenVector/LorentzVector.h"
30 
31 // C/C++ standard library
32 #include <array>
33 #include <vector>
34 #include <iterator> // std::back_inserter()
35 #include <type_traits> // std::declval(), std::is_same<>, ...
36 #include <functional> // std::mem_fn()
37 #include <cassert>
38 
39 
40 namespace geo {
41 
42  /**
43  * @brief Utilities to manipulate geometry vectors.
44  * @ingroup Geometry
45  *
46  * The utilities include generic vector interface facilities allowing to
47  * use different vector types via templates.
48  */
49  namespace vect {
50 
51  //--------------------------------------------------------------------------
52  namespace details {
53  //------------------------------------------------------------------------
54  template <typename Op, typename... T>
56 
57  template
58  <typename Op, typename First, typename Second, typename... Others>
59  struct AccumulateImpl<Op, First, Second, Others...> {
60  static auto compute(Op op, First&& a, Second&& b, Others&&... others)
61  -> decltype(auto)
62  {
63  return op(
64  a,
66  (op, std::forward<Second>(b), std::forward<Others>(others)...)
67  );
68  }
69  }; // AccumulateImpl<>
70 
71  template <typename Op, typename T>
72  struct AccumulateImpl<Op, T> {
73  static auto compute(Op, T&& v) -> decltype(auto)
74  { return std::forward<T>(v); }
75  };
76 
77  template <typename Op, typename... T>
78  auto extended_accumulate(Op op, T&&... args)
79  { return AccumulateImpl<Op, T...>::compute(op, std::forward<T>(args)...); }
80 
81 
82  template <typename... T>
83  auto extended_and(T... args) -> decltype(auto)
84  {
85  auto and_op = [](auto&& a, auto&& b) { return a && b; };
86  return extended_accumulate(and_op, std::forward<T>(args)...);
87  }
88 
89  //------------------------------------------------------------------------
90  //
91  // These two pages of metaprogramming madness are aimed to have objects
92  // that can provide a uniform coordinate get/set for any type of vector,
93  // with the minimal run-time overhead.
94  // Complications arise from the fact that TVector3 setter returns void,
95  // while GenVector vectors return a reference to the vector itself
96  // (hence the need of the additional SetterResult template parameter,
97  // and of quite some code to autodetect its value).
98  // The makeXxxx() functions are aimed to enclose the additional
99  // autodetection overlay, which should become unnecessary with C++17.
100  //
101 
102  template <typename Vector>
103  struct VectorScalar { using type = typename Vector::Scalar; };
104 
105  template <typename Vector>
107 
108 
109  //------------------------------------------------------------------------
110  template <typename Vector>
111  struct HasGetter {
112  private:
113 
114  template<typename Class>
115  static constexpr bool TestX(decltype(std::declval<Class>().X())*) { return true; }
116  template<typename Class>
117  static constexpr bool TestX(...) { return false; }
118  template<typename Class>
119  static constexpr bool TestY(decltype(std::declval<Class>().Y())*) { return true; }
120  template<typename Class>
121  static constexpr bool TestY(...) { return false; }
122  template<typename Class>
123  static constexpr bool TestZ(decltype(std::declval<Class>().Z())*) { return true; }
124  template<typename Class>
125  static constexpr bool TestZ(...) { return false; }
126  template<typename Class>
127  static constexpr bool TestT(decltype(std::declval<Class>().T())*) { return true; }
128  template<typename Class>
129  static constexpr bool TestT(...) { return false; }
130 
131  public:
132  static constexpr bool X = TestX<Vector>(nullptr);
133  static constexpr bool Y = TestY<Vector>(nullptr);
134  static constexpr bool Z = TestZ<Vector>(nullptr);
135  static constexpr bool T = TestT<Vector>(nullptr);
136  }; // struct HasGetter<>
137 
138  template <typename Vector>
139  constexpr bool HasX() { return HasGetter<Vector>::X; }
140  template <typename Vector>
141  constexpr bool HasY() { return HasGetter<Vector>::Y; }
142  template <typename Vector>
143  constexpr bool HasZ() { return HasGetter<Vector>::Z; }
144  template <typename Vector>
145  constexpr bool HasT() { return HasGetter<Vector>::T; }
146 
147  template <typename Vector, typename = void>
149 
150  template <typename Vector>
151  constexpr unsigned int dimension()
152  { return DimensionImpl<Vector>::value; }
153 
154 
155  /// A STL array suitable to contain all coordinate values of a `Vector`.
156  template <typename Vector>
157  using CoordinateArray_t
158  = std::array<VectorScalar_t<Vector>, dimension<Vector>()>;
159 
160 
161  template <typename T>
163  // with C++17 `result_type` is deprecated,
164  // and a different way will be needed
165  using type
166  = typename decltype(std::mem_fn(std::declval<T>()))::result_type;
167  }; // MemberFuncReturnType
168 
169  template <typename T>
171 
172  template <typename T>
174 
175  template <typename Class, typename Func>
176  struct MemberFuncClassType<Func Class::*> { using type = Class; };
177 
178  template <typename T>
180 
181 
182  template <typename Vector, typename SetterType = void>
184 
185  template <typename Vector>
186  struct BaseCoordTypes<Vector, void> {
187  using Vector_t = std::decay_t<Vector>;
189  using Getter_t = Scalar_t (Vector_t::*)() const;
190  }; // struct BaseCoordTypes<void>
191 
192  template <typename Vector, typename SetterType>
193  struct BaseCoordTypes {
194  private:
196 
197  public:
198  using Scalar_t = typename BaseTypes_t::Scalar_t;
199  using Vector_t = typename BaseTypes_t::Vector_t;
200  using Getter_t = typename BaseTypes_t::Getter_t;
201  using Setter_t = SetterType;
203  static_assert(
204  std::is_same<Setter_t, SetterReturn_t (Vector_t::*)(Scalar_t)>(),
205  "Invalid setter type"
206  );
207  }; // struct BaseCoordTypes<>
208 
209 
210  template <typename Vector>
212  private:
214  public:
215  using Vector_t = typename BaseTypes_t::Vector_t;
216  using Scalar_t = typename BaseTypes_t::Scalar_t;
217  using Getter_t = typename BaseTypes_t::Getter_t;
218  }; // struct CoordGetterTraits
219 
220 
221  /// Helper class for read of a single vector coordinate.
222  template <typename Vector>
223  class CoordGetter {
225 
226  public:
227  using Vector_t = typename Traits_t::Vector_t;
228  using Scalar_t = typename Traits_t::Scalar_t;
229  using Getter_t = typename Traits_t::Getter_t;
230 
231  /// Constructor: sets getter and setter functions.
232  constexpr CoordGetter(Getter_t getter): fGetter(getter) {}
233 
234  /// Returns the value of the bound coordinate.
235  Scalar_t operator() (Vector_t const& v) const { return get(v); }
236 
237  /// Returns the value of the bound coordinate.
238  Scalar_t get(Vector_t const& v) const { return (v.*fGetter)(); }
239 
240  private:
241  Getter_t fGetter; ///< Member function returning the coordinate value.
242 
243  }; // class CoordGetter<>
244 
245  template <typename Getter>
246  constexpr auto makeCoordReader(Getter getter)
247  {
248  using Vector_t = std::remove_reference_t<MemberFuncClass_t<Getter>>;
249  return CoordGetter<Vector_t>{ getter };
250  }
251 
252 
253  template <typename Vector, typename SetterType>
255  private:
257  public:
258  using Vector_t = typename BaseTypes_t::Vector_t;
259  using Scalar_t = typename BaseTypes_t::Scalar_t;
260  using Getter_t = typename BaseTypes_t::Getter_t;
261  using Setter_t = typename BaseTypes_t::Setter_t;
262  }; // struct VectorCoordManagerTraits<>
263 
264 
265  /// Helper class for read/write of a single vector coordinate.
266  template <typename Vector, typename SetterType>
267  class CoordManager: public CoordGetter<Vector> {
270 
271  public:
272  using Vector_t = typename Traits_t::Vector_t; // this is not constant
273  using Scalar_t = typename Traits_t::Scalar_t;
274  using Getter_t = typename Traits_t::Getter_t;
275  using Setter_t = typename Traits_t::Setter_t;
276 
277  /// Constructor: sets getter and setter functions.
278  constexpr CoordManager(Getter_t getter, Setter_t setter)
279  : Base_t(getter), fSetter(setter) {}
280 
281  /// Setter: assigns a value to the bound coordinate of specified vector.
282  void operator()(Vector_t& v, Scalar_t c) const { set(v, c); }
283 
284  /// Setter: assigns a value to the bound coordinate of specified vector.
285  void set(Vector_t& v, Scalar_t c) const { (v.*fSetter)(c); }
286 
287  /// Increments the coordinate by the specified amount.
288  void incr(Vector_t& v, Scalar_t c) const { set(v, Base_t::get(v) + c); }
289 
290  /// Decrements the coordinate by the specified amount.
291  void decr(Vector_t& v, Scalar_t c) const { set(v, Base_t::get(v) - c); }
292 
293  /// Multiplies the coordinate by the specified amount.
294  void mult(Vector_t& v, Scalar_t f) const { set(v, Base_t::get(v) * f); }
295 
296  /// Divides the coordinate by the specified amount.
297  void div(Vector_t& v, Scalar_t f) const { set(v, Base_t::get(v) / f); }
298 
299  private:
300  Setter_t fSetter; ///< Member function setting the coordinate value.
301  }; // class CoordManager<>
302 
303 
304  template <typename Getter, typename Setter>
305  constexpr auto makeCoordManager(Getter getter, Setter setter)
306  {
307  using Vector_t = std::remove_reference_t<MemberFuncClass_t<Getter>>;
308  return CoordManager<Vector_t, Setter>{getter, setter};
309  }
310 
311 
312 
313  template <typename CoordHelper, typename StoredVector>
315 
316  public:
317  using Stored_t = StoredVector;
318 
319  using CoordHelper_t = CoordHelper;
321  using Scalar_t = typename CoordHelper_t::Scalar_t;
322  using Getter_t = typename CoordHelper_t::Getter_t;
323 
324  /// Constructor: manage the specified coordinate of specified vector.
326  : fCoord(coordManager), fVector(v) {}
327 
328  /// Constructor: manage the specified vector with specified methods.
330  : fCoord(getter), fVector(v) {}
331 
332  /// Returns the value of the bound coordinate.
333  Scalar_t get() const { return manager().get(vector()); }
334 
335  /// Returns the value of the bound coordinate.
336  Scalar_t operator() () const { return get(); }
337 
338  /// Returns the value of the bound coordinate.
339  operator Scalar_t() const { return manager().get(vector()); }
340 
341  protected:
342  CoordHelper_t const& manager() const { return fCoord; }
343  Stored_t& vector() const { return fVector; }
344 
345  private:
346  CoordHelper_t fCoord; ///< Helper to manage a specific coordinate.
347  Stored_t& fVector; ///< The vector to manage the coordinate of.
348  }; // class VectorCoordGetter<>
349 
350 
351  template <typename CoordHelper, typename StoredVector>
353  : public BoundCoordGetter<CoordHelper, StoredVector>
354  {
356 
357  public:
358  using typename Base_t::Stored_t;
359 
360  using CoordHelper_t = CoordHelper;
362  using Scalar_t = typename CoordHelper_t::Scalar_t;
363  using Getter_t = typename CoordHelper_t::Getter_t;
364  using Setter_t = typename CoordHelper_t::Setter_t;
365 
366  /// Constructor: manage the specified coordinate of specified vector.
368  : Base_t(v, coordManager) {}
369 
370  /// Constructor: manage the specified vector with specified methods.
372  : Base_t(v, CoordHelper_t(getter, setter)) {}
373 
374  /// Setter: assigns a value to the bound coordinate of specified vector.
376  { Base_t::manager().set(Base_t::vector(), c); return *this; }
377 
378  /// Increments by the specified amount.
380  { Base_t::manager().incr(Base_t::vector(), c); return *this; }
381 
382  /// Decrements by the specified amount.
384  { Base_t::manager().decr(Base_t::vector(), c); return *this; }
385 
386  /// Multiplies by the specified amount.
388  { Base_t::manager().mult(Base_t::vector(), f); return *this; }
389 
390  /// Divides by the specified amount.
392  { Base_t::manager().div(Base_t::vector(), f); return *this; }
393 
394  }; // class BoundCoordManager
395 
396  //------------------------------------------------------------------------
397 
398  } // namespace details
399 
400 
401  // BEGIN Geometry group ------------------------------------------------------
402  /// @ingroup Geometry
403  /// @{
404 
405  /// Convenience utilities not directly related to vectors.
406  namespace extra {
407 
408  /// Returns `value`, rounded to 0 if closer than `tol`.
409  template <typename T>
410  constexpr T roundValue0(T value, T tol) {
411  return (std::abs(value) < tol)? T{}: value;
412  } // roundValue0()
413 
414  /// Returns `value`, rounded to 0, -1 or +1 if closer than `tol`.
415  template <typename T>
416  constexpr T roundValue01(T value, T tol) {
417  if (std::abs(value) < tol) return 0.;
418  if (std::abs(std::abs(value) - 1.) < tol) return (value > 0.)? 1.: -1.;
419  return value;
420  } // roundValue01()
421 
422  } // namespace extra
423 
424 
425  // --- BEGIN Vector coordinate access abstraction --------------------------
426  /// @{
427  /**
428  * @name Vector coordinate access abstraction
429  *
430  * This group of utilities provides a common interface for tasks involving
431  * geometry vectors, which may have different interface.
432  * An example of that is the access of coordinates by an index: it is
433  * supported (and "slow") in `TVector3` for read/write access, while in
434  * GenVector it is not supported (and given that the internal representation
435  * might be not cartesian, it's not surprising). We provide utilities which
436  * fill the gaps, relying on some looser requirements.
437  *
438  *
439  * Coordinate managers
440  * ====================
441  *
442  * A "coordinate manager" is an object handling a specific coordinate out of
443  * a specific vector type; i.e., a coordinate manager object will manage for
444  * its entire lifetime the same coordinate, e.g. _x_ or _z_.
445  * A coordinate manager can be:
446  * - bound to a vector object: that manager handles exclusively its managed
447  * coordinate for that vector object;
448  * - unbound: such a manager can handle the managed coordinate of any
449  * vector, which can be passed as an argument; or the unbound manager can
450  * be used to create a bound one.
451  *
452  * Two types of managers are available:
453  * - reader, accesses the coordinate but can't modify it
454  * - manager, requires to be bound to a mutable vector and can assign and
455  * modify the coordinate via selected operations
456  *
457  * Note that a coordinate is never returned as a reference, either mutable
458  * or constant.
459  *
460  *
461  * Handling a coordinate of a vector object: bound managers
462  * ---------------------------------------------------------
463  *
464  * A bound coordinate manager can be created directly:
465  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
466  * geo::Point_t p { 1.0, 2.0, 3.0 };
467  *
468  * auto px = geo::vect::Xcoord(p);
469  * std::cout << p << " has x=" << px() << std::endl;
470  * px += 5.0;
471  * std::cout << p << " has now x=" << px() << std::endl;
472  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
473  * will return something along the line of
474  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
475  * (1,2,3) has x=1
476  * (6,2,3) has now x=6
477  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
478  * Functions `Xcoord()`, `Ycoord()`, `Zcoord()` and `Tcoord()` (in namespace
479  * `geo::vect`) are available for the supporting vector types.
480  *
481  * If access by numeric index is necessary, `coord()` can be used instead:
482  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
483  * geo::Vector_t const v { 1.0, 2.0, 3.0 };
484  *
485  * for (unsigned c = 0; c < 3; ++c) {
486  * auto vc = geo::vect::coord(v, c);
487  * std::cout << v << "[" << c << "]=" << vc() << std::endl;
488  * }
489  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
490  * (note that for this example we have implicitly obtained a coordinate
491  * reader instead of a full coordinate manager because `v` is constant).
492  * This will print:
493  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
494  * v[0]=1
495  * v[1]=2
496  * v[2]=3
497  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
498  * If there are more vectors to access the same coordinate of, it's better
499  * to use unbound managers (see below).
500  *
501  *
502  * Handling a coordinate for any vector object
503  * --------------------------------------------
504  *
505  * Unbound coordinate managers (and readers) can't operate directly on
506  * vectors but they need to be bound to one. Binding produces a new bound
507  * manager, leaving the unbound manager untouched.
508  * Binding is done with `geo::vect::bindCoord()`. For example:
509  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
510  * geo::Point_t A { 1.0, 2.0, 3.0 };
511  * auto Ax = geo::vect::bindCoord(A, YcoordManager<geo::Point_t>);
512  * std::cout << A << " has y=" << Ax << std::endl;
513  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
514  * should produce an output like
515  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
516  * (1,2,3) has y=2
517  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
518  * In the example, `YcoordManager` is a template coordinate manager.
519  * There are managers available for `X`, `Y`, `Z` and `T` coordinates, and
520  * each one can deal only with a specific vector type; also, specifying a
521  * non-constant vector type will deliver a full manager, which can't operate
522  * on constant vectors.
523  * The unbound coordinate managers are not as useful, but a possible use is
524  * for loops on coordinates from multiple vectors:
525  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
526  * geo::Point_t A { 1.0, 2.0, 3.0 }, geo::Point_t B {5.0, 7.0, 9.0 };
527  * for (unsigned c = 0; c < 3; ++c) {
528  * auto coordMan = geo::vect::coordManager(c);
529  * auto Ac = geo::vect::bindCoord(A, coordMan);
530  * auto Bc = geo::vect::bindCoord(B, coordMan);
531  * std::cout << (Bc() - Ac() * 2.0) << std::endl;
532  * } // for
533  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
534  * which will emit
535  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
536  * 3
537  * 3
538  * 3
539  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
540  * This is marginally faster than the same code with
541  * `geo::vect::bindCoord()` call replaced by `geo::vect::coord()`. More
542  * convenient still, if the coordinates are treated all just the same and
543  * `c` is not needed (as above):
544  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
545  * geo::Point_t A { 1.0, 2.0, 3.0 }, geo::Point_t B {5.0, 7.0, 9.0 };
546  * for (auto coordMan: geo::vect::coordManagers<geo::Point_t const>()) {
547  * auto Ac = geo::vect::bindCoord(A, coordMan);
548  * auto Bc = geo::vect::bindCoord(B, coordMan);
549  * std::cout << (Bc() - Ac() * 2.0) << std::endl;
550  * } // for
551  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
552  *
553  *
554  * Conversion between vector types
555  * ================================
556  *
557  * A convenience function `convertTo()` is provided to convert a vector into
558  * another of a different type (for example, from `TVector3` to
559  * `geo::Vector_t`).
560  *
561  *
562  * Vector requirements
563  * ====================
564  *
565  * So far, the requirements for this set of utilities are the following.
566  * The vector type must support:
567  * - a cartesian coordinate constructor: `Vector v { 1.0, 2.0, 3.0 };`
568  * - accessor methods named after the name of the coordinate, acting on
569  * constant vectors, taking no arguments, and returning a copy of the
570  * coordinate value, e.g. `double X() const`
571  * - coordinate assignment methods named `SetC`, where `C` is the name of
572  * each coordinate, after the name of the coordinate, with a single
573  * argument; the return type is not prescribed; e.g. `void SetY(double)`
574  * - the coordinate names must be `X` and `Y` for 2D vectors, plus `Z` for
575  * 3D vectors and `T` for 4D vectors (metric is irrelevant here)
576  *
577  */
578 
579  //@{
580  /// Returns the dimension of the specified vector type.
581  template <typename Vector>
582  constexpr unsigned int dimension() { return details::dimension<Vector>(); }
583  template <typename Vector>
584  constexpr unsigned int dimension(Vector&&) { return dimension<Vector>(); }
585  //@}
586 
587  //@{
588  /// Returns a sequence of indices valid for a vector of the specified type.
589  template <typename Vector>
590  constexpr std::array<std::size_t, geo::vect::dimension<Vector>()> indices();
591  template <typename Vector>
592  constexpr auto indices(Vector const&) -> decltype(indices<Vector>());
593  //@}
594 
595  /// Type of coordinate of the specified vector type.
596  template <typename Vector>
598 
599  /**
600  * @brief Creates a `Vector` object with coordinates from `coords`.
601  * @tparam Vector the type of vector to be created
602  * @tparam Coords type of object holding the value of the needed coordinates
603  * @param coords object holding the value of the needed coordinates
604  * @return a newly created `Vector` object with coordinates from `coords`
605  * @see `geo::vect::fillCoords()`
606  *
607  * To create a vector of dimension _N_, the first _N_ values are extracted
608  * from `coords` using `Coords::operator[](std::size_t)`. For example:
609  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
610  * constexpr std::array<float, 5U> data { 2.0, 5.0, 7.0, 11.0, 15.5 };
611  * constexpr auto p = geo::vect::makeFromCoords<geo::Point_t>(data);
612  * auto v = geo::vect::makeFromCoords<geo::Vector_t>(data.data() + 1);
613  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
614  * will set `p` as `constexpr geo::Point_t {2.0, 5.0, 7.0 }`, ignoring the
615  * additional data. Likewise, it will set `v` to
616  * `geo::Vector_t{ 5.0, 7.0, 11.0 }`. In both cases, the coordinates are
617  * implicitly converted from `float` into the scalar type of the target
618  * vectors (in both cases, `double`).
619  */
620  template <typename Vector, typename Coords>
621  constexpr Vector makeFromCoords(Coords&& coords);
622 
623 
624  /**
625  * @brief Fills a coordinate array with the coordinates of a vector.
626  * @tparam Vector type of vector being copied from
627  * @tparam Coords type of coordinate array to be filled
628  * @param src the vector to read the coordinates from
629  * @param dest the array to be filled
630  * @return the number of coordinates filled (that's `Vector`'s dimension)
631  * @see `geo::vect::makeFromCoords()`
632  *
633  * The `Coords` array type is expected to provide a indexing operator
634  * returning a r-value, that is `coords[i]` can be assigned to.
635  */
636  template <typename Vector, typename Coords>
637  unsigned int fillCoords(Coords& dest, Vector const& src);
638 
639 
640  /// Type of a coordinate reader for a vector type.
641  template <typename Vector>
642  using CoordReader_t
644 
645  /// Type of a coordinate manager for a vector type.
646  template <typename Vector>
647  using CoordManager_t = decltype
649 
650  /**
651  * @brief Object that can be bound to a vector to manage its X coordinate.
652  * @tparam Vector type of vector to get a manager for
653  * (mutable type required)
654  *
655  * The manager exposes a read/write interface.
656  * Example of usage:
657  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
658  * // mutable vectors get a full-featured "manager":
659  * geo::Point_t p { 1.0, 2.0, 3.0 };
660  * auto px
661  * = geo::vect::bindCoord(p, geo::vect::XcoordManager<geo::Point_t>);
662  * px *= 5.0;
663  * std::cout << p << " has now x=" << px() << std::endl;
664  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
665  * will print something like:
666  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
667  * (5,2,3) has now x=5
668  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
669  * Note that the use in the example, `Xcoord()` is preferred.
670  */
671  template <typename Vector>
672  static constexpr auto XcoordManager
674 
675  /**
676  * @brief Object that can be bound to a vector to access its X coordinate.
677  * @tparam Vector type of vector to get a manager for
678  * (constant type required)
679  *
680  * The manager exposes a read-only interface.
681  * Example of usage:
682  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
683  * // constant vectors get a "reader" (read-only manager):
684  * geo::Vector_t v { 1.0, 2.0, 3.0 };
685  *
686  * auto vx = geo::vect::bindCoord
687  * (v, geo::vect::XcoordManager<geo::Vector_t const>);
688  * std::cout << v << " has x=" << vx() << std::endl;
689  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
690  * will print something like:
691  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
692  * (1,2,3) has x=1
693  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
694  * Note that the use in the example, `Xcoord()` is preferred.
695  */
696  template <typename Vector>
697  static constexpr auto XcoordManager<Vector const>
699 
700  /// An object that can be bound to a vector to manage its Y coordinate.
701  /// @see `geo::vect::XcoordManager`
702  template <typename Vector>
703  static constexpr auto const YcoordManager
704  = details::makeCoordManager(&Vector::Y, &Vector::SetY);
705 
706  /// An object that can be bound to a vector to manage its Y coordinate.
707  /// @see `geo::vect::XcoordManager`
708  template <typename Vector>
709  static constexpr auto YcoordManager<Vector const>
711 
712  /// An object that can be bound to a vector to manage its Z coordinate.
713  /// @see `geo::vect::XcoordManager`
714  template <typename Vector>
715  static constexpr auto ZcoordManager
716  = details::makeCoordManager(&Vector::Z, &Vector::SetZ);
717 
718  /// An object that can be bound to a vector to manage its Z coordinate.
719  /// @see `geo::vect::XcoordManager`
720  template <typename Vector>
721  static constexpr auto ZcoordManager<Vector const>
723 
724  /// An object that can be bound to a vector to manage its T coordinate.
725  /// @see `geo::vect::XcoordManager`
726  template <typename Vector>
727  static constexpr auto TcoordManager
728  = details::makeCoordManager(&Vector::T, &Vector::SetT);
729 
730  /// An object that can be bound to a vector to manage its T coordinate.
731  /// @see `geo::vect::XcoordManager`
732  template <typename Vector>
733  static constexpr auto TcoordManager<Vector const>
735 
736 
737  /**
738  * @brief Returns an object that can be bound to a vector to manage one of
739  * its coordinates.
740  * @tparam Vector type of vector to get a manager for (constantness matters)
741  * @param n index of the coordinate (`0`: X, `1`: Y, `2`: Z, `3`: T)
742  * @return a coordinate manager, undefined if index is invalid
743  *
744  * Index `n` is assumed to be smaller than the dimension of the vector.
745  * The manager returned for a mutable vector exposes a read/write interface.
746  * Example of usage:
747  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
748  * // mutable vectors get a full-featured "manager":
749  * geo::Point_t p { 1.0, 2.0, 3.0 };
750  * auto px
751  * = geo::vect::bindCoord(p, geo::vect::coordManager<geo::Point_t>(0U));
752  * px *= 5.0;
753  * std::cout << p << " has now x=" << px() << std::endl;
754  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
755  * will print something like:
756  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
757  * (5,2,3) has now x=5
758  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
759  *
760  * For a constant vector, the returned manager exposes a read-only
761  * interface.
762  * Example of usage:
763  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
764  * // constant vectors get a "reader" (read-only manager):
765  * geo::Vector_t v { 1.0, 2.0, 3.0 };
766  *
767  * auto vx = geo::vect::bindCoord
768  * (v, geo::vect::coordManager<geo::Vector_t const>(1U));
769  * std::cout << v << " has y=" << vy() << std::endl;
770  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
771  * will print something like:
772  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
773  * {1,2,3) has y=2
774  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
775  * Note that the use in these examples, `coord()` is preferred.
776  */
777  template <typename Vector>
778  constexpr auto coordManager(unsigned int n);
779 
780  /**
781  * @brief Returns an object that can be bound to a vector to manage one of
782  * its coordinates.
783  * @tparam Vector type of vector to get a manager for (constantness matters)
784  * @param n index of the coordinate (`0`: X, `1`: Y, `2`: Z, `3`: T)
785  * @param v a vector of type `Vector` (ignored)
786  * @return a coordinate manager, undefined if index is invalid
787  * @see `geo::vect::coordManager(unsigned int)`
788  *
789  * An alias of `geo::vect::coordManager(unsigned int)`.
790  */
791  template <typename Vector>
792  constexpr auto coordManager(unsigned int n, Vector& v);
793 
794 
795  //@{
796  /// Returns an array with all coordinate managers for a type of vector.
797  template <typename Vector>
798  constexpr auto coordManagers();
799  template <typename Vector>
800  constexpr auto coordManagers(Vector&&);
801  //@}
802 
803  //@{
804  /// Returns an array with all coordinate readers for a type of vector.
805  template <typename Vector>
806  constexpr auto coordReaders();
807  template <typename Vector>
808  constexpr auto coordReaders(Vector&&);
809  //@}
810 
811  /// Binds the specified constant vector to the coordinate reader.
812  template <typename Vector>
813  constexpr auto bindCoord
814  (Vector const& v, CoordReader_t<Vector> helper)
815  {
817  (v, helper);
818  }
819 
820  /// Binds the specified vector to the coordinate manager.
821  template <typename Vector>
822  auto bindCoord(Vector& v, CoordManager_t<Vector> helper)
824  { return { v, helper }; }
825 
826 
827 
828  /**
829  * @brief Returns an object to manage the coordinate X of the vector `v`.
830  * @tparam Vector the type of vector to be managed
831  * @param v the vector with the coordinate X to be managed
832  * @return an object to manage the coordinate X of `v`
833  *
834  * The type `Vector` needs to have a `double X() const` method and a
835  * `auto SetX(auto)` method, where the argument is the type of the managed
836  * coordinate and the return value is unspecified.
837  */
838  template <typename Vector>
839  auto Xcoord(Vector& v)
840  { return bindCoord(v, XcoordManager<Vector>); }
841 
842  /**
843  * @brief Returns an object to manage the coordinate Y of the vector `v`.
844  * @tparam Vector the type of vector to be managed
845  * @param v the vector with the coordinate Y to be managed
846  * @return an object to manage the coordinate Y of `v`
847  *
848  * The type `Vector` needs to have a `double Y() const` method and a
849  * `auto SetY(auto)` method, where the argument is the type of the managed
850  * coordinate and the return value is unspecified.
851  */
852  template <typename Vector>
853  auto Ycoord(Vector& v)
854  { return bindCoord<Vector>(v, YcoordManager<Vector>); }
855 
856  /**
857  * @brief Returns an object to manage the coordinate Z of the vector `v`.
858  * @tparam Vector the type of vector to be managed
859  * @param v the vector with the coordinate Z to be managed
860  * @return an object to manage the coordinate Z of `v`
861  *
862  * The type `Vector` needs to have a `double Z() const` method and a
863  * `auto SetZ(auto)` method, where the argument is the type of the managed
864  * coordinate and the return value is unspecified.
865  */
866  template <typename Vector>
867  auto Zcoord(Vector& v)
868  { return bindCoord<Vector>(v, ZcoordManager<Vector>); }
869 
870  /**
871  * @brief Returns an object to manage the coordinate T of the vector `v`.
872  * @tparam Vector the type of vector to be managed
873  * @param v the vector with the coordinate T to be managed
874  * @return an object to manage the coordinate T of `v`
875  *
876  * The type `Vector` needs to have a `double T() const` method and a
877  * `auto SetT(auto)` method, where the argument is the type of the managed
878  * coordinate and the return value is unspecified.
879  */
880  template <typename Vector>
881  auto Tcoord(Vector& v)
882  { return bindCoord<Vector>(v, TcoordManager<Vector>); }
883 
884  /**
885  * @brief Returns an object to manage the coordinate `n` of a vector
886  * @tparam Vector the type of vector to be managed
887  * @param v the vector to be managed
888  * @param n the coordinate index: `0` for X, `1` for Y and `2` for Z
889  * @return an object to manage the coordinate `n` of a vector
890  * @see `Xcoord()`, `Ycoord()`, `Zcoord()`
891  *
892  * Result is undefined for any value of `n` other than `0`, `1` and `2`.
893  * See `Xcoord()`, `Ycoord()` and `Zcoord()` for `Vector` type requirements.
894  */
895  template <typename Vector>
896  auto coord(Vector& v, unsigned int n) noexcept;
897 
898 
899  /// Returns an array with all coordinate managers bound to the specified
900  /// vector.
901  template <typename Vector>
902  constexpr auto bindCoordManagers(Vector& v);
903 
904  /// Returns an array with all coordinate readers bound to the specified
905  /// vector.
906  template <typename Vector>
907  constexpr auto bindCoordReaders(Vector const& v);
908 
909 
910 
911  /**
912  * @brief Constant iterator to vector coordinates.
913  * @tparam Vector the type of vector being iterated
914  * @see `vector_cbegin()`, `vector_cend()`, `iterateCoords()`
915  * @todo Not fully unit-tested yet!
916  */
917  template <typename Vector>
919 
920  public:
921  using iterator_t = CoordConstIterator<Vector>; ///< Type of this iterator.
922 
923  private:
924  using Vector_t = Vector; ///< Type of vector being iterated.
925  /// Type of vector coordinate.
927 
928  Vector* v = nullptr;
929  unsigned int index = std::numeric_limits<unsigned int>::max();
930 
931  decltype(auto) access(unsigned int c) const
932  { return geo::vect::bindCoord(v, index); }
933 
934  iterator_t copy() const { return *this; }
935 
936  public:
937 
938  /// --- BEGIN Iterator traits ------------------------------------------------
939  /// @name Iterator traits
940  /// @{
941  using value_type = std::remove_cv_t<Coord_t>;
942  using difference_type = std::ptrdiff_t;
944  using pointer = Coord_t const*;
945  using iterator_category = std::random_access_iterator_tag;
946  /// @}
947  /// --- END Iterator traits --------------------------------------------------
948 
949  /// Default constructor: invalid iterator.
950  CoordConstIterator() = default;
951 
952  /// Constructor: points to `index` coordinate of vector `v`.
953  CoordConstIterator(Vector& v, unsigned int index = 0)
954  : v(&v), index(index)
955  {}
956 
957  // --- BEGIN Access ----------------------------------------------------------
958  /// @name Access
959  /// @{
960 
961  /// Access the current coordinate.
962  reference operator* () const { return geo::vect::coord(*v, index); }
963 
964  /// Access the current coordinate.
966  { return geo::vect::coord(*v, index + n); }
967 
968  /// @}
969  // --- END Access ------------------------------------------------------------
970 
971 
972  // --- BEGIN Moving ----------------------------------------------------------
973  /// @name Moving
974  /// @{
975 
976  /// Points to the next coordinate (unchecked).
977  iterator_t& operator++() { ++index; return *this; }
978 
979  /// Points to the next coordinate (unchecked), returns the previous iterator.
980  iterator_t operator++(int) { iterator_t it(*this); ++index; return it; }
981 
982  /// Points to the previous coordinate (unchecked).
983  iterator_t& operator--() { --index; return *this; }
984 
985  /// Points to previous coordinate (unchecked), returns the previous iterator.
986  iterator_t operator--(int) { iterator_t it(*this); --index; return it; }
987 
988  /// Increments the iterator by `d` positions (unchecked).
989  iterator_t& operator+=(difference_type d) { index += d; return *this; }
990 
991  /// Returns an iterator incremented by `d` positions (unchecked).
992  iterator_t operator+(difference_type d) const { return (copy() += d); }
993 
994  /// Decrements the iterator by `d` positions (unchecked).
995  iterator_t& operator-=(difference_type d) { index -= d; return *this; }
996 
997  /// Returns an iterator decremented by `d` positions (unchecked).
998  iterator_t operator-(difference_type d) const { return (copy() -= d); }
999 
1000  /// Returns the distance from another iterator.
1001  iterator_t operator-(iterator_t const& other) const
1002  { return index - other.index; }
1003 
1004  ///@}
1005  // --- END Moving ------------------------------------------------------------
1006 
1007 
1008  // --- BEGIN Comparison operators --------------------------------------------
1009  /// @name Comparison operators
1010  ///
1011  /// All comparisons between iterators on different vectors fail.
1012  /// @{
1013 
1014  bool operator== (iterator_t const& other) const
1015  { return (v == other.v) && (index == other.index); }
1016 
1017  bool operator!= (iterator_t const& other) const
1018  { return (v != other.v) || (index != other.index); }
1019 
1020  bool operator<= (iterator_t const& other) const
1021  { return (v == other.v) && (index <= other.index); }
1022 
1023  bool operator>= (iterator_t const& other) const
1024  { return (v == other.v) && (index >= other.index); }
1025 
1026  bool operator< (iterator_t const& other) const
1027  { return (v == other.v) && (index < other.index); }
1028 
1029  bool operator> (iterator_t const& other) const
1030  { return (v == other.v) && (index > other.index); }
1031 
1032  /// @}
1033  // --- END Comparison operators ----------------------------------------------
1034 
1035  }; // class CoordConstIterator
1036 
1037  template <typename Vector>
1041  )
1042  { return v + n; }
1043 
1044  /// Returns a const-iterator pointing to the first coordinate of `v`.
1045  template <typename Vector>
1046  auto vector_cbegin(Vector const& v)
1047  { return CoordConstIterator(v, 0); }
1048 
1049  /// Returns a const-iterator pointing after the last coordinate of `v`.
1050  template <typename Vector>
1051  auto vector_cend(Vector const& v)
1052  { return CoordConstIterator(v, geo::vect::dimension(v)); }
1053 
1054  /**
1055  * @brief Returns an object for ranged-for iteration on coordinates.
1056  * @tparam Vector type of vector to iterate through
1057  * @param v vector whose coordinates will be iterated
1058  * @return an object suitable for range-for loop
1059  *
1060  * Example:
1061  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
1062  * geo::Vector_t v{ 3.0, 4.0, 5.0 };
1063  * for (auto c: geo::vect::iterateCoords(v)) std::cout << c << ' ';
1064  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1065  * will print `3 4 5 `.
1066  */
1067  template <typename Vector>
1068  auto iterateCoords(Vector const& v)
1069  { return util::span(vector_cbegin(v), vector_cend(v)); }
1070 
1071 
1072  /**
1073  * @brief Returns a vector of type `Dest` with the same content as a `Src`.
1074  * @tparam Dest target vector type
1075  * @tparam Source type of the vector to be converted from
1076  * @param v the vector to be converted from
1077  * @return a vector with the same content as `v`, but of type `Dest`
1078  *
1079  * For this to work, both `Src` and `Dest` types must satisfy the
1080  * requirements of `Xcoord()`, `Ycoord()`, `Zcoord()` etc.
1081  */
1082  template <typename Dest, typename Source>
1083  Dest convertTo(Source const& v);
1084 
1085 
1086  /**
1087  * @brief Returns a vector of type `Dest` with the same content as a `Src`.
1088  * @tparam Dest target vector type
1089  * @tparam Source type of the vector to be converted from
1090  * @param coll the collection of vectors to be converted from
1091  * @return a collection of vectors with the same content as `coll`, but of
1092  * type `Dest`
1093  * @see `convertTo()`
1094  *
1095  * This version applies `convertTo()` to all the elements of the specified
1096  * collection, returning a collection of the same template type
1097  * (`std::vector`).
1098  *
1099  * For the requirements, see `convertTo()`.
1100  */
1101  template <typename Dest, typename Source>
1102  std::vector<Dest> convertCollTo(std::vector<Source> const& coll);
1103 
1104 
1105  /**
1106  * @brief Returns a new vector applying a predicate to each component.
1107  * @tparam Vector type of the vector in input (and output)
1108  * @tparam Pred type of unary predicate to be applied
1109  * @param v the vector to be transformed
1110  * @param pred the predicate to be applied
1111  * @return a vector equivelent to `{ pred(x), pred(y), ... }`
1112  *
1113  * The predicate is a "functor" type, taking as the single argument the
1114  * coordinate to be transformed, and returning the transformed value of it.
1115  */
1116  template <typename Vector, typename Pred>
1117  Vector transformCoords(Vector const& v, Pred&& pred);
1118 
1119  /// @}
1120  // --- END Vector coordinate access abstraction ----------------------------
1121 
1122 
1123  // --- BEGIN Functions for common vector operations ------------------------
1124  /// @{
1125  /** ************************************************************************
1126  * @name Functions for common vector operations.
1127  *
1128  * This group of template functions are meant to be used with vectors in a
1129  * generic way.
1130  * The default implementation is for `TVector3`. Specializations can be
1131  * easily written for other vector types.
1132  *
1133  * In addition, two "standard" representations for vectors and points are
1134  * provided.
1135  *
1136  * @note The representations for vector and point objects are currently the
1137  * same; this prevents relying on overload resolution to decide which
1138  * function to use. For example, defining two functions with signature:
1139  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
1140  * Vector_t Project(Vector_t const& v);
1141  * Point_t Project(Point_t const& v);
1142  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1143  * will not compile since these two are exactly the same.
1144  * A solution might be to derive two different classes from the common
1145  * one:
1146  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
1147  * struct Vector_t: public VectorBase_t { using VectorBase_t::VectorBase_t; };
1148  * struct Point_t: public VectorBase_t { using VectorBase_t::VectorBase_t; };
1149  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1150  * This will likely have consequences though (for example, the sum of
1151  * two `Vector_t` or `Point_t` will become a `VectorBase_t`).
1152  *
1153  */
1154 
1155  /// Returns a vector with all components rounded if close to 0.
1156  template <typename Vector, typename Scalar>
1157  Vector rounded0(Vector const& v, Scalar tol)
1158  {
1159  return transformCoords
1160  (v, [tol](auto c){ return extra::roundValue0(c, tol); });
1161  }
1162 
1163  /// Returns a vector with all components rounded if close to 0.
1164  template <typename Vector, typename Scalar>
1165  void round0(Vector& v, Scalar tol) { v = rounded0(v, tol); }
1166 
1167  /// Returns a vector with all components rounded if close to 0, -1 or +1.
1168  template <typename Vector, typename Scalar>
1169  Vector rounded01(Vector const& v, Scalar tol)
1170  {
1171  return transformCoords
1172  (v, [tol](auto c){ return extra::roundValue01(c, tol); });
1173  }
1174 
1175  /// Returns a vector with all components rounded if close to 0, -1 or +1.
1176  template <typename Vector, typename Scalar>
1177  void round01(Vector& v, Scalar tol) { v = rounded01(v, tol); }
1178 
1179 
1180  /// Returns whether all components of the vector are finite.
1181  template <typename Vector>
1182  bool isfinite(Vector const& v);
1183 
1184  /// Returns a vector parallel to v and with norm 1
1185  template <typename Vector>
1186  Vector normalize(Vector const& v) { return v.Unit(); }
1187 
1188  /// Return cross product of two vectors
1189  template <typename Vector>
1190  Vector cross(Vector const& a, Vector const& b) { return a.Cross(b); }
1191 
1192  /// Return cross product of two vectors
1193  template <typename Vector>
1194  constexpr auto dot(Vector const& a, Vector const& b) { return a.Dot(b); }
1195 
1196  /// Return norm of the specified vector
1197  template <typename Vector>
1198  auto mag2(Vector const& v) { return v.Mag2(); }
1199 
1200  /// Return norm of the specified vector
1201  template <typename Vector>
1202  auto norm(Vector const& v) { return v.Mag(); }
1203 
1204  /// Return "mixed" product of three vectors:
1205  /// @f$ \vec{a} \times \vec{b} \cdot \vec{c} @f$
1206  template <typename Vector>
1207  auto mixedProduct(Vector const& a, Vector const& b, Vector const& c)
1208  { return dot(cross(a, b), c); }
1209 
1210 
1211  /// @}
1212  // --- END Functions for common vector operations --------------------------
1213 
1214 
1215  /** ************************************************************************
1216  * @brief Helper class to compute the middle point in a point set.
1217  * @tparam N _(default: `3`)_ dimension of the points
1218  *
1219  * This class accumulates cartesian points and returns their middle point
1220  * when asked.
1221  *
1222  * In the following example, only the points from a list (`points`) which
1223  * have _y_ coordinate larger than 0 are averaged, all with the same weight:
1224  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
1225  * std::array<geo::Point_t, 4> const points = {
1226  * geo::Point_t{ 0.0, 1.0, 2.0 },
1227  * geo::Point_t{ 0.0, -1.0, 2.0 },
1228  * geo::Point_t{ 0.0, 1.0, -2.0 },
1229  * geo::Point_t{ 0.0, -1.0, -2.0 }
1230  * };
1231  *
1232  * geo::vect::MiddlePointAccumulatorDim pointsAboveGround;
1233  * for (auto const& point: points)
1234  * if (point.Y() > 0.0) pointsAboveGround.add(point);
1235  *
1236  * if (pointsAboveGround.empty())
1237  * throw std::runtime_error("No point above ground!");
1238  *
1239  * auto middleAboveGround = pointsAboveGround.middlePoint();
1240  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1241  * Note the check to make sure that there are points that fulfil the
1242  * requirement.
1243  *
1244  */
1245  template <unsigned int N = 3U>
1247  static constexpr unsigned int Dim = N; ///< Dimension of the points.
1248  std::array<Length_t, Dim> fSums; ///< Sum of each of the point components.
1249  double fW = 0.0; ///< Total weight.
1250 
1251  public:
1252  /// Default constructor: starts with no accumulated point.
1254 
1255  /**
1256  * @brief Constructor: starts with accumulating a sequence of points.
1257  * @tparam BeginIter type of iterator to a point type compatible with add()
1258  * @tparam EndIter type of end iterator
1259  * @param begin iterator to the first point to be added
1260  * @param end iterator after the last point to be added
1261  * @see add()
1262  */
1263  template <typename BeginIter, typename EndIter>
1266  { add(begin, end); }
1267 
1268 
1269  // --- BEGIN Result query ------------------------------------------------
1270  /// @{
1271  /// @name Result query
1272 
1273  /// Returns whether the total weight is zero (usually means no points).
1274  bool empty() const { return fW == 0.0; }
1275 
1276  /// Returns the total weight (number of points if all have weight 1).
1277  double weight() const { return fW; }
1278 
1279  /**
1280  * @brief Returns the middle point, NaN components if no point.
1281  * @tparam Point type of the output point
1282  *
1283  * The type of return point must be specified as template argument, e.g.
1284  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
1285  * auto mp = accumulator.middlePointAs<TVector3>();
1286  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1287  * The `Point` type is required to have a constructor with the three
1288  * cartesian components as arguments.
1289  */
1290  template <typename Point>
1292  // { return { fSums[0] / fW, fSums[1] / fW, fSums[2] / fW }; }
1293  { return makeWeightedPoint<Point>(1.0 / fW); }
1294 
1295  /// Returns the middle point as a `geo::Point_t`,
1296  /// NaN components if no point.
1298  { return middlePointAs<geo::Point_t>(); }
1299 
1300 
1301  /// @}
1302  // --- END Result query --------------------------------------------------
1303 
1304  // --- BEGIN Addition of points ------------------------------------------
1305  /// @{
1306  /// @name Addition of points
1307 
1308  /**
1309  * @brief Accumulates a point.
1310  * @tparam Point point type, required to have X(), Y() and Z() accessors
1311  * @param p point to be included
1312  *
1313  * The point is added with weight 1.
1314  */
1315  template <typename Point>
1316  void add(Point const& p)
1317  {
1318  std::size_t ic = 0U;
1319  for (auto c: geo::vect::bindCoordManagers(p)) fSums[ic++] += c();
1320  fW += 1.0;
1321  }
1322 
1323  /**
1324  * @brief Accumulates a point.
1325  * @tparam Point point type, required to have X(), Y() and Z() accessors
1326  * @param p point to be included
1327  * @param weight the relative weight of this point
1328  */
1329  template <typename Point>
1330  void add(Point const& p, double weight)
1331  {
1332  std::size_t ic = 0U;
1333  for (auto c: geo::vect::bindCoordManagers(p))
1334  fSums[ic++] += weight * c();
1335  fW += weight;
1336  }
1337 
1338  /**
1339  * @brief Adds a sequence of points.
1340  * @tparam BeginIter type of iterator to a point type compatible with add()
1341  * @tparam EndIter type of end iterator
1342  * @param begin iterator to the first point to be added
1343  * @param end iterator after the last point to be added
1344  *
1345  * Each point is added with weight 1.0.
1346  */
1347  template <typename BeginIter, typename EndIter>
1348  void add(BeginIter begin, EndIter end)
1349  { std::for_each(begin, end, [this](auto const& p){ this->add(p); }); }
1350 
1351  /// Resets the status of the object to no accumulated points.
1352  void clear() { fSums.fill(0.); fW = 0.0; }
1353 
1354  /// @}
1355  // --- END Addition of points --------------------------------------------
1356 
1357  private:
1358  using IndexSequence_t = std::make_index_sequence<Dim>;
1359 
1360  template <typename Point, std::size_t... I>
1361  Point makePointImpl(std::index_sequence<I...>) const
1362  { return { fSums.operator[](I)... }; }
1363 
1364  template <typename Point, std::size_t... I>
1365  Point makeWeightedPointImpl(double w, std::index_sequence<I...>) const
1366  { return { (fSums.operator[](I) * w)... }; }
1367 
1368  /// Converts the internal sums into a `Point`.
1369  template <typename Point>
1371  { return geo::vect::makeFromCoords<Point>(fSums); }
1372 
1373  /// Converts the internal sums into a `Point` with components scaled by
1374  /// `w`.
1375  template <typename Point>
1376  Point makeWeightedPoint(double w) const
1377  { return makeWeightedPointImpl<Point>(w, IndexSequence_t{}); }
1378 
1379 
1380  }; // MiddlePointAccumulatorDim()
1381 
1382 
1383  /// Middle-point accumulator for vectors of dimension 3.
1385 
1386 
1387  // --- BEGIN Middle point functions ----------------------------------------
1388  /// @{
1389  /// @name Middle point functions
1390 
1391  /**
1392  * @brief Returns the middle of the specified points.
1393  * @tparam Point cartesian-represented point type with 3-component constructor
1394  * @tparam BeginIter type of iterator to a point type compatible with add()
1395  * @tparam EndIter type of end iterator
1396  * @param begin iterator to the first point to be averaged
1397  * @param end iterator after the last point to be averaged
1398  * @return an object of type `Point` with the value of the middle point
1399  *
1400  * Example of usage:
1401  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
1402  * std::vector<geo::Point_t> points {
1403  * geo::Point_t(1., 2., 3.),
1404  * geo::Point_t(2., 4., 6.),
1405  * geo::Point_t(3., 6., 9.)
1406  * };
1407  *
1408  * auto mp = geo::vect::middlePointAs<geo::Vector_t>(points.begin(), points.end());
1409  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1410  * The variable `mp` of the example will be of type `geo::Vector_t` (converted
1411  * component by components from a `geo::Point_t`).
1412  *
1413  */
1414  template <typename Point, typename BeginIter, typename EndIter>
1415  Point middlePointAs(BeginIter begin, EndIter end)
1416  {
1417  constexpr auto Dim = geo::vect::dimension<Point>();
1419  .template middlePointAs<Point>();
1420  }
1421 
1422  /**
1423  * @brief Returns the middle of the specified points.
1424  * @tparam BeginIter type of iterator to a point type compatible with add()
1425  * @tparam EndIter type of end iterator
1426  * @param begin iterator to the first point to be averaged
1427  * @param end iterator after the last point to be averaged
1428  * @return an object of type `Point_t` with the value of the middle point
1429  *
1430  * Example of usage:
1431  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
1432  * std::vector<geo::Point_t> points {
1433  * geo::Point_t(1., 2., 3.),
1434  * geo::Point_t(2., 4., 6.),
1435  * geo::Point_t(3., 6., 9.)
1436  * };
1437  *
1438  * auto mp = geo::vect::middlePoint(points.begin(), points.end());
1439  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1440  * The variable `mp` of the example will be of type `geo::Point_t`.
1441  *
1442  */
1443  template <typename BeginIter, typename EndIter>
1444  geo::Point_t middlePoint(BeginIter begin, EndIter end)
1445  { return middlePointAs<geo::Point_t>(begin, end); }
1446 
1447  /**
1448  * @brief Returns the middle of the specified points.
1449  * @tparam Point cartesian-represented point type with 3-component constructor
1450  * and X(), Y() and Z() accessors.
1451  * @param points the list of points to be included
1452  * @return the value of the middle point
1453  *
1454  * Example of usage:
1455  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
1456  * auto mp = geo::vect::middlePoint
1457  * ({ geo::Point_t(1., 2., 3.), geo::Point_t(3., 6., 9.) });
1458  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1459  * The variable `mp` will contain the middle point between the two specified
1460  * in the initializer list.
1461  *
1462  */
1463  template <typename Point>
1464  Point middlePoint(std::initializer_list<Point> points)
1465  {
1466  constexpr auto Dim = geo::vect::dimension<Point>();
1467  return MiddlePointAccumulatorDim<Dim>(points.begin(), points.end())
1468  .template middlePointAs<Point>();
1469  }
1470 
1471  /// @}
1472  // --- END Middle point functions ------------------------------------------
1473 
1474 
1475  // --- BEGIN Support for LArSoft geometry vectors --------------------------
1476  /// @{
1477  /// @name Support for LArSoft geometry vectors
1478 
1479  // import global definitions
1482 
1483  /// Convert the specified point into a `geo::Point_t`.
1484  template <typename Point>
1486  { return geo::vect::convertTo<::geo::Point_t>(p); }
1487 
1488  /// Convert the specified vector into a `geo::Vector_t`.
1489  template <typename Vector>
1490  ::geo::Vector_t toVector(Vector const& v)
1491  { return geo::vect::convertTo<::geo::Vector_t>(v); }
1492 
1493 
1494  /// Convert the specified collection of points into a collection of
1495  /// `geo::Point_t`.
1496  template <typename Point>
1497  std::vector<geo::Point_t> convertCollToPoint
1498  (std::vector<Point> const& coll)
1499  { return convertCollTo<geo::Point_t>(coll); }
1500 
1501  /// Convert the specified collection of vectors into a collection of
1502  /// `geo::Vector_t`.
1503  template <typename Vector>
1504  std::vector<geo::Vector_t> convertCollToVector
1505  (std::vector<Vector> const& coll)
1506  { return convertCollTo<geo::Vector_t>(coll); }
1507 
1508 
1509  /// Creates a `geo::Point_t` from its coordinates (see `makeFromCoords()`).
1510  template <typename Coords>
1512  { return makeFromCoords<::geo::Point_t>(std::forward<Coords>(coords)); }
1513 
1514  /// Creates a `geo::Vector_t` from its coordinates (see `makeFromCoords()`).
1515  template <typename Coords>
1517  { return makeFromCoords<::geo::Vector_t>(std::forward<Coords>(coords)); }
1518 
1519  /// @}
1520  // --- END Support for LArSoft geometry vectors ----------------------------
1521 
1522  /// @}
1523  // END Geometry group ------------------------------------------------------
1524 
1525 
1526  } // namespace vect
1527 
1528 } // namespace geo
1529 
1530 
1531 //------------------------------------------------------------------------------
1532 //--- STL specialization for ROOT GenVector vectors
1533 //------------------------------------------------------------------------------
1534 namespace ROOT::Math {
1535 
1536  /// @name Overloads of STL C++ functions for ROOT GenVector vectors
1537  /// @{
1538 
1539  // --- BEGIN 2D vectors ------------------------------------------------------
1540  template<class CoordSystem, class Tag>
1541  decltype(auto) begin(ROOT::Math::PositionVector2D<CoordSystem, Tag> const& v)
1542  { return geo::vect::vector_cbegin(v); }
1543 
1544  template<class CoordSystem, class Tag>
1545  decltype(auto) cbegin(ROOT::Math::PositionVector2D<CoordSystem, Tag> const& v)
1546  { return geo::vect::vector_cbegin(v); }
1547 
1548  template<class CoordSystem, class Tag>
1549  decltype(auto) end(ROOT::Math::PositionVector2D<CoordSystem, Tag> const& v)
1550  { return geo::vect::vector_cend(v); }
1551 
1552  template<class CoordSystem, class Tag>
1553  decltype(auto) cend(ROOT::Math::PositionVector2D<CoordSystem, Tag> const& v)
1554  { return geo::vect::vector_cend(v); }
1555 
1556  template<class CoordSystem, class Tag>
1557  decltype(auto)
1558  begin(ROOT::Math::DisplacementVector2D<CoordSystem, Tag> const& v)
1559  { return geo::vect::vector_cbegin(v); }
1560 
1561  template<class CoordSystem, class Tag>
1562  decltype(auto) cbegin(ROOT::Math::DisplacementVector2D<CoordSystem, Tag> const& v)
1563  { return geo::vect::vector_cbegin(v); }
1564 
1565  template<class CoordSystem, class Tag>
1566  decltype(auto) end(ROOT::Math::DisplacementVector2D<CoordSystem, Tag> const& v)
1567  { return geo::vect::vector_cend(v); }
1568 
1569  template<class CoordSystem, class Tag>
1570  decltype(auto) cend(ROOT::Math::DisplacementVector2D<CoordSystem, Tag> const& v)
1571  { return geo::vect::vector_cend(v); }
1572 
1573  // --- END 2D vectors --------------------------------------------------------
1574 
1575 
1576  // --- BEGIN 3D vectors ------------------------------------------------------
1577  template<class CoordSystem, class Tag>
1578  decltype(auto) begin(ROOT::Math::PositionVector3D<CoordSystem, Tag> const& v)
1579  { return geo::vect::vector_cbegin(v); }
1580 
1581  template<class CoordSystem, class Tag>
1582  decltype(auto) cbegin(ROOT::Math::PositionVector3D<CoordSystem, Tag> const& v)
1583  { return geo::vect::vector_cbegin(v); }
1584 
1585  template<class CoordSystem, class Tag>
1586  decltype(auto) end(ROOT::Math::PositionVector3D<CoordSystem, Tag> const& v)
1587  { return geo::vect::vector_cend(v); }
1588 
1589  template<class CoordSystem, class Tag>
1590  decltype(auto) cend(ROOT::Math::PositionVector3D<CoordSystem, Tag> const& v)
1591  { return geo::vect::vector_cend(v); }
1592 
1593  template<class CoordSystem, class Tag>
1594  decltype(auto)
1595  begin(ROOT::Math::DisplacementVector3D<CoordSystem, Tag> const& v)
1596  { return geo::vect::vector_cbegin(v); }
1597 
1598  template<class CoordSystem, class Tag>
1599  decltype(auto) cbegin(ROOT::Math::DisplacementVector3D<CoordSystem, Tag> const& v)
1600  { return geo::vect::vector_cbegin(v); }
1601 
1602  template<class CoordSystem, class Tag>
1603  decltype(auto) end(ROOT::Math::DisplacementVector3D<CoordSystem, Tag> const& v)
1604  { return geo::vect::vector_cend(v); }
1605 
1606  template<class CoordSystem, class Tag>
1607  decltype(auto) cend(ROOT::Math::DisplacementVector3D<CoordSystem, Tag> const& v)
1608  { return geo::vect::vector_cend(v); }
1609 
1610  // --- END 3D vectors --------------------------------------------------------
1611 
1612 
1613  // --- BEGIN 4D vectors ------------------------------------------------------
1614  template<class CoordSystem>
1615  decltype(auto) begin(ROOT::Math::LorentzVector<CoordSystem> const& v)
1616  { return geo::vect::vector_cbegin(v); }
1617 
1618  template<class CoordSystem>
1619  decltype(auto) cbegin(ROOT::Math::LorentzVector<CoordSystem> const& v)
1620  { return geo::vect::vector_cbegin(v); }
1621 
1622  template<class CoordSystem>
1623  decltype(auto) end(ROOT::Math::LorentzVector<CoordSystem> const& v)
1624  { return geo::vect::vector_cend(v); }
1625 
1626  template<class CoordSystem>
1627  decltype(auto) cend(ROOT::Math::LorentzVector<CoordSystem> const& v)
1628  { return geo::vect::vector_cend(v); }
1629 
1630  // --- END 4D vectors --------------------------------------------------------
1631 
1632 
1633  /// @}
1634 
1635 } // namespace ROOT::Math
1636 
1637 //------------------------------------------------------------------------------
1638 
1639 //------------------------------------------------------------------------------
1640 //--- template specializations for standard geometry vectors
1641 //---
1642 namespace geo::vect {
1643 
1644  //----------------------------------------------------------------------------
1645  template <>
1646  inline auto norm(geo::Vector_t const& v) { return v.R(); }
1647 
1648  //----------------------------------------------------------------------------
1649 
1650 } // namespace geo::vect
1651 
1652 
1653 //------------------------------------------------------------------------------
1654 //--- template implementation
1655 
1656 namespace geo::vect::details {
1657 
1658  //----------------------------------------------------------------------------
1659  template <typename> struct AlwaysFalse: std::false_type {};
1660 
1661 
1662  // constexpr variant of forward (from StackExchange)
1663  template <typename T>
1664  constexpr T&& constexpr_forward(std::remove_reference_t<T>& t)
1665  { return static_cast<T&&>(t); }
1666 
1667  template<typename T>
1668  constexpr T&& constexpr_forward(std::remove_reference_t<T>&& t)
1669  {
1670  static_assert(!std::is_lvalue_reference<T>(),
1671  "template argument substituting T is an lvalue reference type");
1672  return static_cast<T&&>(t);
1673  }
1674 
1675  //----------------------------------------------------------------------------
1676  template <typename Vector, typename /* = void */>
1677  struct DimensionImpl
1678  : public std::integral_constant<
1679  unsigned int,
1680  HasT<Vector>()? 4U
1681  : HasZ<Vector>()? 3U
1682  : HasY<Vector>()? 2U
1683  : HasX<Vector>()? 1U
1684  : 0U
1685  >
1686  {};
1687 
1688  template <typename Array>
1689  struct DimensionImpl<Array, std::enable_if_t<(std::extent_v<Array> > 0)>>
1690  : public std::integral_constant<unsigned int, std::extent_v<Array>>
1691  {};
1692 
1693  template <typename T, std::size_t Dim>
1694  struct DimensionImpl<std::array<T, Dim>, void>
1695  : public std::integral_constant<unsigned int, Dim>
1696  {};
1697 
1698 
1699  //----------------------------------------------------------------------------
1700  /// Type of sequence of indices up to `Vector` size.
1701  template <typename Vector>
1702  using VectorIndices_t = std::make_index_sequence<dimension<Vector>()>;
1703 
1704  template <typename Vector>
1705  constexpr auto makeVectorIndices() { return VectorIndices_t<Vector>{}; }
1706 
1707  template <typename Vector>
1708  constexpr auto makeVectorIndices(Vector&&)
1709  { return makeVectorIndices<Vector>(); }
1710 
1711 
1712  template <typename T, T... Indices>
1713  constexpr auto makeIndexSeqImpl(std::integer_sequence<T, Indices...>)
1714  // BUG the double brace syntax is required to work around clang bug 21629
1715  // (https://bugs.llvm.org/show_bug.cgi?id=21629)
1716  { return std::array<T, sizeof...(Indices)>{{ Indices... }}; }
1717 
1718  // fill a sequence object with the first `N` values of type `T`.
1719  template <typename T, T N>
1720  constexpr auto makeIndexSeq()
1721  { return makeIndexSeqImpl<T>(std::make_integer_sequence<T, N>{}); }
1722 
1723 
1724  //----------------------------------------------------------------------------
1725  template <std::size_t I, typename Data>
1726  constexpr auto accessElement(Data&& data) { return data[I]; }
1727 
1728  template <typename Vector, typename Coords, std::size_t... Indices>
1729  constexpr Vector makeFromCoordsImpl
1730  (Coords&& coords, std::index_sequence<Indices...>)
1731  {
1732  return
1733  { accessElement<Indices>(constexpr_forward<Coords>(coords))... };
1734  }
1735 
1736 
1737  //----------------------------------------------------------------------------
1738  template <typename Vector>
1739  constexpr CoordManager_t<Vector> NoCoordManager{ nullptr, nullptr };
1740 
1741  template <typename Vector, unsigned int Dim = dimension<Vector>()>
1743 
1744  template <typename Vector>
1745  struct CoordManagerImpl<Vector, 1U> {
1746  static auto get(unsigned int n) noexcept
1747  { return (n == 0)? XcoordManager<Vector>: NoCoordManager<Vector>; }
1748  }; // CoordManagerImpl<1U>
1749 
1750  template <typename Vector>
1751  struct CoordManagerImpl<Vector, 2U> {
1752  static auto get(unsigned int n) noexcept
1753  {
1754  return (n == 1)
1755  ? YcoordManager<Vector>: CoordManagerImpl<Vector, 1U>::get(n);
1756  }
1757  }; // CoordManagerImpl<2U>
1758 
1759  template <typename Vector>
1760  struct CoordManagerImpl<Vector, 3U> {
1761  static auto get(unsigned int n) noexcept
1762  {
1763  return (n == 2)
1764  ? ZcoordManager<Vector>: CoordManagerImpl<Vector, 2U>::get(n);
1765  }
1766  }; // CoordManagerImpl<3U>
1767 
1768  template <typename Vector>
1769  struct CoordManagerImpl<Vector, 4U> {
1770  static auto get(unsigned int n) noexcept
1771  {
1772  return (n == 3)
1773  ? TcoordManager<Vector>: CoordManagerImpl<Vector, 3U>::get(n);
1774  }
1775 
1776  }; // CoordManagerImpl<4U>
1777 
1778 
1779  //----------------------------------------------------------------------------
1780  template <typename Vector, unsigned int N>
1782  static constexpr unsigned int Dim = N;
1783 
1784  using Manager_t = decltype(XcoordManager<Vector>);
1785  using Return_t = std::array<Manager_t, Dim>;
1786 
1787  static_assert(dimension<Vector>() == Dim, "Inconsistent vector size.");
1788  }; // CoordManagersImplBase
1789 
1790  template <typename Vector, unsigned int N>
1792 
1793  template <typename Vector>
1794  struct CoordManagersImpl<Vector, 2U>
1795  : private CoordManagersImplBase<Vector, 2U>
1796  {
1798  using typename Base_t::Return_t;
1799  static constexpr Return_t get()
1800  {
1801  // BUG the double brace syntax is required to work around clang bug 21629
1802  // (https://bugs.llvm.org/show_bug.cgi?id=21629)
1803  return {{
1804  XcoordManager<Vector>
1805  , YcoordManager<Vector>
1806  }};
1807  }
1808  }; // CoordManagersImpl<2U>
1809 
1810  template <typename Vector>
1811  struct CoordManagersImpl<Vector, 3U>
1812  : private CoordManagersImplBase<Vector, 3U>
1813  {
1815  using typename Base_t::Return_t;
1816  static constexpr Return_t get()
1817  {
1818  // BUG the double brace syntax is required to work around clang bug 21629
1819  // (https://bugs.llvm.org/show_bug.cgi?id=21629)
1820  return {{
1821  XcoordManager<Vector>
1822  , YcoordManager<Vector>
1823  , ZcoordManager<Vector>
1824  }};
1825  }
1826  }; // CoordManagersImpl<3U>
1827 
1828  template <typename Vector>
1829  struct CoordManagersImpl<Vector, 4U>
1830  : private CoordManagersImplBase<Vector, 4U>
1831  {
1833  using typename Base_t::Return_t;
1834  static constexpr Return_t get()
1835  {
1836  // BUG the double brace syntax is required to work around clang bug 21629
1837  // (https://bugs.llvm.org/show_bug.cgi?id=21629)
1838  return {{
1839  XcoordManager<Vector>
1840  , YcoordManager<Vector>
1841  , ZcoordManager<Vector>
1842  , TcoordManager<Vector>
1843  }};
1844  }
1845  }; // CoordManagersImpl<4U>
1846 
1847 
1848  //----------------------------------------------------------------------------
1849  template <typename Vector, unsigned int N>
1851  static constexpr unsigned int Dim = N;
1852 
1853  using Manager_t = decltype(Xcoord(std::declval<Vector>()));
1854  using Return_t = std::array<Manager_t, Dim>;
1855 
1856  static_assert(dimension<Vector>() == Dim, "Inconsistent vector size.");
1857  }; // CoordManagersImplBase
1858 
1859  template <typename Vector, unsigned int N>
1861 
1862  template <typename Vector>
1863  struct BindCoordManagersImpl<Vector, 2U>
1864  : private BindCoordManagersImplBase<Vector, 2U>
1865  {
1867  using typename Base_t::Return_t;
1868  static Return_t bind(Vector& v)
1869  {
1870  // BUG the double brace syntax is required to work around clang bug 21629
1871  // (https://bugs.llvm.org/show_bug.cgi?id=21629)
1872  return {{
1873  Xcoord(v)
1874  , Ycoord(v)
1875  }};
1876  }
1877  }; // BindCoordManagersImpl<2U>
1878 
1879  template <typename Vector>
1880  struct BindCoordManagersImpl<Vector, 3U>
1881  : private BindCoordManagersImplBase<Vector, 3U>
1882  {
1884  using typename Base_t::Return_t;
1885  static Return_t bind(Vector& v)
1886  {
1887  // BUG the double brace syntax is required to work around clang bug 21629
1888  // (https://bugs.llvm.org/show_bug.cgi?id=21629)
1889  return {{
1890  Xcoord(v)
1891  , Ycoord(v)
1892  , Zcoord(v)
1893  }};
1894  }
1895  }; // BindCoordManagersImpl<3U>
1896 
1897  template <typename Vector>
1898  struct BindCoordManagersImpl<Vector, 4U>
1899  : private BindCoordManagersImplBase<Vector, 4U>
1900  {
1902  using typename Base_t::Return_t;
1903  static Return_t bind(Vector& v)
1904  {
1905  // BUG the double brace syntax is required to work around clang bug 21629
1906  // (https://bugs.llvm.org/show_bug.cgi?id=21629)
1907  return {{
1908  Xcoord(v)
1909  , Ycoord(v)
1910  , Zcoord(v)
1911  , Tcoord(v)
1912  }};
1913  }
1914  }; // BindCoordManagersImpl<4U>
1915 
1916 
1917  //----------------------------------------------------------------------------
1918  template<typename Dest, typename Source>
1920  static_assert(dimension<Source>() == dimension<Dest>(),
1921  "Source and destination vectors must have the same dimension.");
1922  }; // struct ConvertToImplBase
1923 
1924 
1925  template <typename Dest, typename Source, unsigned int Dim>
1926  struct ConvertArrayTo: private ConvertToImplBase<Dest, Source>
1927  {
1928  static_assert
1929  (std::is_arithmetic_v<std::decay_t<decltype(std::declval<Source>()[0])>>);
1930  static Dest convert(Source const& v)
1931  { return geo::vect::makeFromCoords<Dest>(v); }
1932  }; // struct ConvertArrayTo
1933 
1934 
1935  // will handle cases with specific dimensionality
1936  template <typename Dest, typename Source, unsigned int Dim>
1938 
1939 
1940  template <typename Dest, typename Source>
1942  : public ConvertToImplDim<Dest, Source, dimension<Source>()>
1943  {};
1944 
1945 
1946  template <typename Dest, typename T, std::size_t Dim>
1947  struct ConvertToImpl<Dest, std::array<T, Dim>>
1948  : public ConvertArrayTo<Dest, std::array<T, Dim>, Dim>
1949  {};
1950 
1951  template <typename Dest, typename T, std::size_t Dim>
1952  struct ConvertToImpl<Dest, T[Dim]>
1953  : public ConvertArrayTo<Dest, T[Dim], Dim>
1954  {};
1955 
1956  // special special implementation for T*, since we can't guess its dimension
1957  template <typename Dest, typename T>
1958  struct ConvertToImpl<Dest, T*> {
1959  static_assert(std::is_arithmetic_v<T>);
1960  static Dest convert(T* v) { return geo::vect::makeFromCoords<Dest>(v); }
1961  }; // struct ConvertToImpl<T*>
1962 
1963 
1964  // handled cases with specific dimensionality
1965  template <typename Dest, typename Source, unsigned int Dim>
1966  struct ConvertToImplDim {
1967  // trivial to do: open a feature request!
1968  static_assert(
1969  AlwaysFalse<Dest>(),
1970  "This vector dimensionality is not implemented yet."
1971  );
1972  }; // struct ConvertToImplDim
1973 
1974  template <typename Dest, typename Source>
1975  struct ConvertToImplDim<Dest, Source, 2U>
1976  : private ConvertToImplBase<Dest, Source>
1977  {
1978  static Dest convert(Source const& v)
1979  { return { Xcoord(v)(), Ycoord(v)() }; }
1980  }; // struct ConvertToImplDim<2U>
1981 
1982  template <typename Dest, typename Source>
1983  struct ConvertToImplDim<Dest, Source, 3U>
1984  : private ConvertToImplBase<Dest, Source>
1985  {
1986  static Dest convert(Source const& v)
1987  { return { Xcoord(v)(), Ycoord(v)(), Zcoord(v)() }; }
1988  }; // struct ConvertToImplDim<3U>
1989 
1990  template <typename Dest, typename Source>
1991  struct ConvertToImplDim<Dest, Source, 4U>
1992  : private ConvertToImplBase<Dest, Source>
1993  {
1994  static Dest convert(Source const& v)
1995  { return { Xcoord(v)(), Ycoord(v)(), Zcoord(v)(), Tcoord(v)() }; }
1996  }; // struct ConvertToImplDim<4U>
1997 
1998 
1999  template <typename Dest, typename Source>
2000  struct ConvertToDispatcher: public ConvertToImpl<Dest, Source> {};
2001 
2002  // special pass-through case
2003  template <typename Vector>
2004  struct ConvertToDispatcher<Vector, Vector> {
2005  static constexpr decltype(auto) convert(Vector const& v) { return v; }
2006  }; // struct ConvertToDispatcher<pass through>
2007 
2008 
2009  //----------------------------------------------------------------------------
2010  template <typename Point, std::size_t... I>
2011  bool isfiniteImpl(Point const& point, std::index_sequence<I...>)
2012  { return extended_and(std::isfinite(coord(point, I).get())...); }
2013 
2014  //----------------------------------------------------------------------------
2015 
2016 } // namespace geo::vect::details
2017 
2018 
2019 //------------------------------------------------------------------------------
2020 template <typename Vector>
2021 constexpr std::array<std::size_t, geo::vect::dimension<Vector>()>
2023 {
2024  return details::makeIndexSeq<std::size_t, dimension<Vector>()>();
2025 }
2026 
2027 template <typename Vector>
2028 constexpr auto geo::vect::indices(Vector const&) -> decltype(indices<Vector>())
2029  { return indices<Vector>(); }
2030 
2031 
2032 //------------------------------------------------------------------------
2033 template <typename Vector, typename Coords>
2034 constexpr Vector geo::vect::makeFromCoords(Coords&& coords) {
2035  using namespace geo::vect::details;
2036  return makeFromCoordsImpl<Vector>
2037  (constexpr_forward<Coords>(coords), makeVectorIndices<Vector>());
2038 } // geo::vect::makeFromCoords()
2039 
2040 
2041 //------------------------------------------------------------------------------
2042 template <typename Vector>
2043 constexpr auto geo::vect::coordManager(unsigned int n)
2045 
2046 
2047 //------------------------------------------------------------------------------
2048 template <typename Vector>
2049 auto geo::vect::coord(Vector& v, unsigned int n) noexcept {
2050  return vect::bindCoord<Vector>(v, coordManager<Vector>(n));
2051 }
2052 
2053 
2054 //------------------------------------------------------------------------
2055 template <typename Vector, typename Coords>
2056 unsigned int geo::vect::fillCoords(Coords& dest, Vector const& src) {
2057  // this is simpler than makeFromCoords() because doesn't attempt constexpr
2058  for (std::size_t i = 0; i < geo::vect::dimension(src); ++i)
2059  dest[i] = geo::vect::coord(src, i);
2060  return geo::vect::dimension(src);
2061 } // geo::vect::fillCoords()
2062 
2063 
2064 //------------------------------------------------------------------------------
2065 template <typename Vector>
2066 constexpr auto geo::vect::coordManagers() {
2067  using PlainVector = std::remove_reference_t<Vector>;
2068  return
2070 } // geo::vect::coordManagers()
2071 
2072 template <typename Vector>
2073 constexpr auto geo::vect::coordManagers(Vector&&)
2074  { return coordManagers<Vector>(); }
2075 
2076 
2077 template <typename Vector>
2078 constexpr auto geo::vect::coordReaders() {
2079  using ConstVector = std::add_const_t<std::remove_reference_t<Vector>>;
2080  return
2082 } // geo::vect::coordReaders()
2083 
2084 template <typename Vector>
2085 constexpr auto geo::vect::coordReaders(Vector&&)
2086  { return coordReaders<Vector>(); }
2087 
2088 
2089 //------------------------------------------------------------------------------
2090 template <typename Vector>
2091 constexpr auto geo::vect::bindCoordManagers(Vector& v) {
2093 } // geo::vect::bindCoordManagers()
2094 
2095 
2096 template <typename Vector>
2097 constexpr auto geo::vect::bindCoordReaders(Vector const& v) {
2098  using ConstVector = std::add_const_t<std::remove_reference_t<Vector>>;
2100  ::bind(v);
2101 } // geo::vect::bindCoordReaders()
2102 
2103 
2104 //------------------------------------------------------------------------------
2105 template <typename Dest, typename Source>
2106 Dest geo::vect::convertTo(Source const& v)
2108 
2109 
2110 //----------------------------------------------------------------------------
2111 template <typename Dest, typename Source>
2112 std::vector<Dest> geo::vect::convertCollTo(std::vector<Source> const& coll) {
2113 
2114  std::vector<Dest> dest;
2115  dest.reserve(coll.size());
2116  std::transform(coll.begin(), coll.end(), std::back_inserter(dest),
2117  geo::vect::convertTo<Dest, Source>);
2118  return dest;
2119 
2120 } // geo::vect::convertCollTo()
2121 
2122 
2123 //------------------------------------------------------------------------
2124 template <typename Vector, typename Pred>
2125 Vector geo::vect::transformCoords(Vector const& v, Pred&& pred) {
2127  unsigned int i = 0;
2128  for (auto c: bindCoordReaders(v)) values[i++] = pred(c());
2129  return makeFromCoords<Vector>(values);
2130 } // geo::vect::transformCoords()
2131 
2132 
2133 //------------------------------------------------------------------------------
2134 template <typename Vector>
2135 bool geo::vect::isfinite(Vector const& v)
2136  { return details::isfiniteImpl(v, details::makeVectorIndices<Vector>()); }
2137 
2138 //------------------------------------------------------------------------------
2139 
2140 
2141 #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.
see a below echo or echo I(indirect symbol).'echo" If the symbol is local (non-external)
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:164
Constant iterator to vector coordinates.
double std(const std::vector< short > &wf, const double ped_mean, size_t start, size_t nsample)
Definition: UtilFunc.cxx:42
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)
CoordConstIterator(Vector &v, unsigned int index=0)
Constructor: points to index coordinate of vector v.
decltype(auto) access(unsigned int c) const
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()
static auto compute(Op, T &&v) -> decltype(auto)
constexpr auto makeVectorIndices()
static constexpr Sample_t transform(Sample_t sample)
An object with a begin and end iterator.
static constexpr auto XcoordManager
Object that can be bound to a vector to manage its X coordinate.
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)
static constexpr unsigned int Dim
Dimension of the points.
auto coord(Vector &v, unsigned int n) noexcept
Returns an object to manage the coordinate n of a vector.
auto const tol
Definition: SurfXYZTest.cc:16
constexpr auto bindCoordReaders(Vector const &v)
Helper class to compute the middle point in a point set.
bool operator<=(iterator_t const &other) const
geo::vect::coordinate_t< Vector_t > Coord_t
Type of vector coordinate.
constexpr auto makeCoordReader(Getter getter)
pdgs p
Definition: selectors.fcl:22
typename Traits_t::Setter_t Setter_t
CoordConstIterator< Vector > operator+(typename CoordConstIterator< Vector >::difference_type n, CoordConstIterator< Vector > const &v)
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()
iterator_t operator-(iterator_t const &other) const
Returns the distance from another iterator.
auto iterateCoords(Vector const &v)
Returns an object for ranged-for iteration on coordinates.
::geo::Vector_t toVector(Vector const &v)
Convert the specified vector into a geo::Vector_t.
static constexpr auto TcoordManager
std::remove_cv_t< Coord_t > value_type
BoundCoordManager & operator+=(Scalar_t c)
Increments by the specified amount.
constexpr auto bindCoord(Vector const &v, CoordReader_t< Vector > helper)
Binds the specified constant vector to the coordinate reader.
auto cbegin(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:567
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
iterator_t operator-(difference_type d) const
Returns an iterator decremented by d positions (unchecked).
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.
Simple class with a begin and an end.
Definition: span.h:125
void round0(Vector &v, Scalar tol)
Returns a vector with all components rounded if close to 0.
Helper class for read/write of a single vector coordinate.
then echo echo For and will not be changed by echo further linking echo echo B echo The symbol is in the uninitialized data multiple common symbols may appear with the echo same name If the symbol is defined the common echo symbols are treated as undefined references For more echo details on common see the discussion of warn common echo in *Note Linker see the discussion of warn common echo in *Note Linker such as a global int variable echo as opposed to a large global array echo echo I echo The symbol is an indirect reference to another symbol This echo is a GNU extension to the a out object file format which is echo rarely used echo echo N echo The symbol is a debugging symbol echo echo R echo The symbol is in a read only data section echo echo S echo The symbol is in an uninitialized data section for small echo objects echo echo T echo The symbol is in the the normal defined echo symbol is used with no error When a weak undefined symbol echo is linked and the symbol is not the value of the echo weak symbol becomes zero with no error echo echo W echo The symbol is a weak symbol that has not been specifically echo tagged as a weak object symbol When a weak defined symbol echo is linked with a normal defined the normal defined echo symbol is used with no error When a weak undefined symbol echo is linked and the symbol is not the value of the echo weak symbol becomes zero with no error echo echo echo The symbol is a stabs symbol in an a out object file In echo this the next values printed are the stabs other echo the stabs desc and the stab type Stabs symbols are echo used to hold debugging information For more echo see *Note or object file format specific echo echo For Mac OS X
typename CoordHelper_t::Vector_t Vector_t
bool operator>(iterator_t const &other) const
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.
constexpr unsigned int dimension()
Returns the dimension of the specified vector type.
auto cend(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:579
static constexpr auto ZcoordManager< Vector const >
recob::tracking::Point_t Point_t
unsigned int fillCoords(Coords &dest, Vector const &src)
Fills a coordinate array with the coordinates of a vector.
typename BaseTypes_t::Scalar_t Scalar_t
void add(Point const &p, double weight)
Accumulates a point.
process_name gaushit a
iterator_t operator+(difference_type d) const
Returns an iterator incremented by d positions (unchecked).
static constexpr bool TestX(decltype(std::declval< Class >().X())*)
typename VectorScalar< Vector >::type VectorScalar_t
typename Traits_t::Vector_t Vector_t
constexpr unsigned int dimension()
T abs(T value)
iterator_t operator--(int)
Points to previous coordinate (unchecked), returns the previous iterator.
std::random_access_iterator_tag iterator_category
constexpr auto coordReaders()
Returns an array with all coordinate readers for a type of vector.
BoundCoordManager & operator/=(Scalar_t f)
Divides by the specified amount.
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
then echo ***************************************echo array
Definition: find_fhicl.sh:28
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.
iterator_t & operator--()
Points to the previous coordinate (unchecked).
Definitions of geometry vector data types.
std::vector< geo::Point_t > convertCollToPoint(std::vector< Point > const &coll)
auto vector_cend(Vector const &v)
Returns a const-iterator pointing after the last coordinate of v.
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:44
Point makeWeightedPointImpl(double w, std::index_sequence< I...>) const
Point makePointImpl(std::index_sequence< I...>) const
MiddlePointAccumulatorDim(BeginIter begin, EndIter end)
Constructor: starts with accumulating a sequence of points.
typename CoordHelper_t::Setter_t Setter_t
typename CoordHelper_t::Scalar_t Scalar_t
auto extended_and(T...args) -> decltype(auto)
constexpr std::array< std::size_t, geo::vect::dimension< Vector >)> indices()
Returns a sequence of indices valid for a vector of the specified type.
bool operator>=(iterator_t const &other) const
MemberFuncReturn_t< Setter_t > SetterReturn_t
constexpr auto makeCoordManager(Getter getter, Setter setter)
constexpr T roundValue0(T value, T tol)
Returns value, rounded to 0 if closer than tol.
auto end(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:585
typename std::enable_if< B, T >::type enable_if_t
Definition: json.hpp:2191
void LorentzVector(Stream &&out, TLorentzVector const &v)
Print a TLorentzVector to an output stream.
iterator_t & operator++()
Points to the next coordinate (unchecked).
BoundCoordManager & operator*=(Scalar_t f)
Multiplies by the specified amount.
auto Ycoord(Vector &v)
Returns an object to manage the coordinate Y of the vector v.
Scalar_t get(Vector_t const &v) const
Returns the value of the bound coordinate.
typename decltype(std::mem_fn(std::declval< T >()))::result_type type
static constexpr bool TestY(...)
constexpr bool HasT()
j template void())
Definition: json.hpp:3108
Vector transformCoords(Vector const &v, Pred &&pred)
Returns a new vector applying a predicate to each component.
constexpr Vector makeFromCoordsImpl(Coords &&coords, std::index_sequence< Indices...>)
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.
BoundCoordManager & operator-=(Scalar_t c)
Decrements by the specified amount.
auto begin(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:573
typename BaseTypes_t::Getter_t Getter_t
BoundCoordGetter(Stored_t &v, CoordHelper_t coordManager)
Constructor: manage the specified coordinate of specified vector.
Scalar_t operator()(Vector_t const &v) const
Returns the value of the bound coordinate.
constexpr bool HasZ()
auto Tcoord(Vector &v)
Returns an object to manage the coordinate T of the vector v.
constexpr bool HasY()
CoordHelper_t const & manager() const
auto extended_accumulate(Op op, T &&...args)
BoundCoordManager & operator=(Scalar_t c)
Setter: assigns a value to the bound coordinate of specified vector.
typename BaseTypes_t::Getter_t Getter_t
static auto compute(Op op, First &&a, Second &&b, Others &&...others) -> decltype(auto)
bool isfiniteImpl(Point const &point, std::index_sequence< I...>)
std::make_index_sequence< Dim > IndexSequence_t
static constexpr auto TcoordManager< Vector const >
auto vector_cbegin(Vector const &v)
Returns a const-iterator pointing to the first coordinate of v.
std::array< VectorScalar_t< Vector >, dimension< Vector >()> CoordinateArray_t
A STL array suitable to contain all coordinate values of a Vector.
CoordConstIterator()=default
Default constructor: invalid iterator.
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)
process_name largeant stream1 can override from command line with o or output physics producers generator N
Scalar_t operator()() const
Returns the value of the bound coordinate.
constexpr T roundValue01(T value, T tol)
Returns value, rounded to 0, -1 or +1 if closer than tol.
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.
reference operator[](difference_type n) const
Access the current coordinate.
bool operator==(iterator_t const &other) const
Stored_t & fVector
The vector to manage the coordinate of.
void set(Vector_t &v, Scalar_t c) const
Setter: assigns a value to the bound coordinate of specified vector.
MiddlePointAccumulatorDim()
Default constructor: starts with no accumulated point.
Helper class for read of a single vector coordinate.
bool operator!=(iterator_t const &other) const
details::VectorScalar_t< Vector > coordinate_t
Type of coordinate of the specified vector type.
temporary value
constexpr Vector makeFromCoords(Coords &&coords)
Creates a Vector object with coordinates from coords.
static constexpr bool TestT(...)
constexpr auto makeIndexSeqImpl(std::integer_sequence< T, Indices...>)
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:46
void div(Vector_t &v, Scalar_t f) const
Divides the coordinate by the specified amount.
Vector rounded0(Vector const &v, Scalar tol)
Returns a vector with all components rounded if close to 0.
reference operator*() const
Access the current coordinate.
iterator_t & operator+=(difference_type d)
Increments the iterator by d positions (unchecked).
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:184
GENVECTOR_CONSTEXPR::geo::Point_t makePointFromCoords(Coords &&coords)
Creates a geo::Point_t from its coordinates (see makeFromCoords()).
GENVECTOR_CONSTEXPR::geo::Vector_t makeVectorFromCoords(Coords &&coords)
Creates a geo::Vector_t from its coordinates (see makeFromCoords()).
recob::tracking::Vector_t Vector_t
static Dest convert(Source const &v)
iterator_t & operator-=(difference_type d)
Decrements the iterator by d positions (unchecked).
iterator_t operator++(int)
Points to the next coordinate (unchecked), returns the previous iterator.
TimeTrackTreeStorage::TriggerInputSpec_t convert(TimeTrackTreeStorage::Config::TriggerSpecConfig const &config)
bool operator<(iterator_t const &other) const
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())*)