LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
intervals.h
Go to the documentation of this file.
1 
10 #ifndef LARDATAALG_UTILITIES_INTERVALS_H
11 #define LARDATAALG_UTILITIES_INTERVALS_H
12 
13 // LArSoft libraries
15 
16 // C/C++ standard libraries
17 #include <ostream>
18 #include <type_traits> // std::enable_if_t<>, ...
19 
20 namespace util::quantities {
21 
23  struct NoCategory;
24 
25  namespace concepts {
26 
27  namespace details {
28 
29  //------------------------------------------------------------------------
30 
31  template <typename Cat, typename = void>
33 
34  template <typename Cat>
36 
37  //------------------------------------------------------------------------
39  template <typename Cat>
40  struct WithCategory;
41 
42  //------------------------------------------------------------------------
43 
44  } // namespace details
45 
46  //--------------------------------------------------------------------------
48  struct CategoryBase {
50  static std::string name() = delete;
51  }; // struct CategoryBase
52 
53  //--------------------------------------------------------------------------
54  //--- traits
55  //--------------------------------------------------------------------------
57  template <typename IV>
58  struct is_interval;
59 
61  template <typename IV>
62  constexpr bool is_interval_v = is_interval<IV>();
63 
64  //--------------------------------------------------------------------------
66  template <typename PT>
67  struct is_point;
68 
70  template <typename PT>
71  constexpr bool is_point_v = is_point<PT>();
72 
73  //--------------------------------------------------------------------------
75  template <typename T>
76  using is_interval_or_point = std::disjunction<is_interval<T>, is_point<T>>;
77 
79  template <typename T>
81 
82  //--------------------------------------------------------------------------
83 
85  template <typename T>
86  using interval_of = typename T::interval_t;
87 
88  //--------------------------------------------------------------------------
89 
105  template <typename Q, typename Cat = NoCategory>
106  struct Interval : private Q, public details::WithCategory<Cat> {
107 
109 
112 
113  template <typename OC, typename Type = void>
114  using enable_if_compatible_t =
115  std::enable_if_t<category_base_t::template category_compatible_with<OC>(), Type>;
116 
117  public:
119 
120  // --- BEGIN -- Types from the base quantity -----------------------------
123 
124  using quantity_t = Q;
125 
128 
130  template <typename R>
132 
134  using value_t = typename quantity_t::value_t;
135 
137  using unit_t = typename quantity_t::unit_t;
138 
140  using baseunit_t = typename quantity_t::baseunit_t;
141 
143  template <typename OQ, typename OI>
145 
147  // --- END -- Types from the base quantity -------------------------------
148 
150  // NOTE: this is not `constexpr` because using it in a constexpr would
151  // yield an uninitialized constant
152  explicit Interval() = default;
153 
155  explicit constexpr Interval(value_t v) : Interval(quantity_t{v}) {}
156 
167  template <typename... Args>
169  {}
170 
180  template <typename IV, typename std::enable_if_t<is_interval_v<IV>>* = nullptr>
181  constexpr Interval(IV iv) : Interval(quantity_t{iv.quantity()})
182  {}
183 
185  constexpr quantity_t const& quantity() const { return *this; }
186 
188  using quantity_t::value;
189 
191  explicit constexpr operator value_t() const { return value(); }
192 
193  // -- BEGIN Access to the scaled unit ------------------------------------
196 
197  using quantity_t::baseUnit;
198  using quantity_t::unit;
199  using quantity_t::unitName;
200  using quantity_t::unitSymbol;
201 
202  /*
203  * due to C++ (up to 17 at least) syntax limitations, we can't import
204  * a dependent template (in this case, `Q::baseUnit<U>`, which depends
205  * on a template parameter `Q`) as such: C++ will import it if we use the
206  * "standard" syntax `using quantity_t::sameUnitAs;`, but without
207  * knowning it as a template; the correct syntax to express this would be
208  * `using quantity_t::template sameUnitAs;`, which is not allowed in C++.
209  * So we have to redefine the thing entirely.
210  */
211 
213  template <typename OU>
214  static constexpr bool sameBaseUnitAs()
215  {
216  return quantity_t::template sameBaseUnitAs<OU>();
217  }
218 
220  template <typename OU>
221  static constexpr bool sameUnitAs()
222  {
223  return quantity_t::template sameUnitAs<OU>();
224  }
225 
227  // -- END Access to the scaled unit --------------------------------------
228 
229  // -- BEGIN Asymmetric arithmetic operations -----------------------------
259 
263  constexpr interval_t operator+(interval_t const other) const
264  {
265  return interval_t{quantity() + other.quantity()};
266  }
267 
270  constexpr interval_t operator-(interval_t const other) const
271  {
272  return interval_t{quantity() - other.quantity()};
273  }
274 
276  template <typename OQ, typename OC>
278  Interval<OQ, OC> const denom) const
279  {
280  return quantity() / denom.quantity();
281  }
282 
284  template <typename R>
286  {
287  quantity_t::operator+=(other);
288  return *this;
289  }
290 
292  template <typename OQ, typename OC>
293  enable_if_compatible_t<Interval<OQ, OC>, interval_t&> operator+=(Interval<OQ, OC> const other)
294  {
295  return operator+=(other.quantity());
296  }
297 
299  template <typename R>
301  {
302  quantity_t::operator-=(other);
303  return *this;
304  }
305 
307  template <typename OQ, typename OC>
308  enable_if_compatible_t<Interval<OQ, OC>, interval_t&> operator-=(Interval<OQ, OC> const other)
309  {
310  return operator-=(other.quantity());
311  }
312 
314  template <typename T>
316  {
317  quantity_t::operator*=(factor);
318  return *this;
319  }
320 
322  template <typename T>
324  {
325  quantity_t::operator/=(factor);
326  return *this;
327  }
328 
330  constexpr interval_t operator+() const { return interval_t(quantity()); }
331 
333  constexpr interval_t operator-() const { return interval_t(-quantity()); }
334 
336  constexpr interval_t abs() const { return interval_t(quantity().abs()); }
337 
339  // -- END Asymmetric arithmetic operations -------------------------------
340 
341  // -- BEGIN Comparisons --------------------------------------------------
357 
359  template <typename OQ, typename OC>
360  constexpr enable_if_compatible_t<Interval<OQ, OC>, bool> operator==(
361  Interval<OQ, OC> const other) const
362  {
363  return quantity_t::operator==(other.quantity());
364  }
365 
366  template <typename OQ, typename OC>
367  constexpr enable_if_compatible_t<Interval<OQ, OC>, bool> operator!=(
368  Interval<OQ, OC> const other) const
369  {
370  return quantity_t::operator!=(other.quantity());
371  }
372 
373  template <typename OQ, typename OC>
374  constexpr enable_if_compatible_t<Interval<OQ, OC>, bool> operator>=(
375  Interval<OQ, OC> const other) const
376  {
377  return quantity_t::operator>=(other.quantity());
378  }
379 
380  template <typename OQ, typename OC>
381  constexpr enable_if_compatible_t<Interval<OQ, OC>, bool> operator>(
382  Interval<OQ, OC> const other) const
383  {
384  return quantity_t::operator>(other.quantity());
385  }
386 
387  template <typename OQ, typename OC>
388  constexpr enable_if_compatible_t<Interval<OQ, OC>, bool> operator<=(
389  Interval<OQ, OC> const other) const
390  {
391  return quantity_t::operator<=(other.quantity());
392  }
393 
394  template <typename OQ, typename OC>
395  constexpr enable_if_compatible_t<Interval<OQ, OC>, bool> operator<(
396  Interval<OQ, OC> const other) const
397  {
398  return quantity_t::operator<(other.quantity());
399  }
400 
402  // -- END Asymmetric arithmetic operations -------------------------------
403 
405  template <typename IV>
406  constexpr IV convertInto() const
407  {
408  return IV(*this);
409  }
410 
419  template <typename U>
421  {
422  return interval_t{static_cast<value_t>(value)};
423  }
424 
425  }; // struct Interval
426 
427  template <typename... Args>
428  std::ostream& operator<<(std::ostream& out, Interval<Args...> const iv)
429  {
430  return out << iv.quantity();
431  }
432 
433  // -- BEGIN Comparison operations ------------------------------------------
444 
446  template <typename Q, typename Cat, typename... Args>
447  constexpr bool operator==(Interval<Q, Cat> const a, Quantity<Args...> const b) noexcept
448  {
449  return a.quantity() == b;
450  }
451 
452  template <typename Q, typename Cat, typename... Args>
453  constexpr bool operator==(Quantity<Args...> const a, Interval<Q, Cat> const b) noexcept
454  {
455  return b == a;
456  }
457 
458  template <typename Q, typename Cat, typename... Args>
459  constexpr bool operator!=(Interval<Q, Cat> const a, Quantity<Args...> const b) noexcept
460  {
461  return a.quantity() != b;
462  }
463 
464  template <typename Q, typename Cat, typename... Args>
465  constexpr bool operator!=(Quantity<Args...> const a, Interval<Q, Cat> const b) noexcept
466  {
467  return b != a;
468  }
469 
470  template <typename Q, typename Cat, typename... Args>
471  constexpr bool operator<=(Interval<Q, Cat> const a, Quantity<Args...> const b) noexcept
472  {
473  return a.quantity() <= b;
474  }
475 
476  template <typename Q, typename Cat, typename... Args>
477  constexpr bool operator<=(Quantity<Args...> const a, Interval<Q, Cat> const b) noexcept
478  {
479  return b >= a;
480  }
481 
482  template <typename Q, typename Cat, typename... Args>
483  constexpr bool operator<(Interval<Q, Cat> const a, Quantity<Args...> const b) noexcept
484  {
485  return a.quantity() < b;
486  }
487 
488  template <typename Q, typename Cat, typename... Args>
489  constexpr bool operator<(Quantity<Args...> const a, Interval<Q, Cat> const b) noexcept
490  {
491  return b > a;
492  }
493 
494  template <typename Q, typename Cat, typename... Args>
495  constexpr bool operator>=(Interval<Q, Cat> const a, Quantity<Args...> const b) noexcept
496  {
497  return a.quantity() >= b;
498  }
499 
500  template <typename Q, typename Cat, typename... Args>
501  constexpr bool operator>=(Quantity<Args...> const a, Interval<Q, Cat> const b) noexcept
502  {
503  return b <= a;
504  }
505 
506  template <typename Q, typename Cat, typename... Args>
507  constexpr bool operator>(Interval<Q, Cat> const a, Quantity<Args...> const b) noexcept
508  {
509  return a.quantity() > b;
510  }
511 
512  template <typename Q, typename Cat, typename... Args>
513  constexpr bool operator>(Quantity<Args...> const a, Interval<Q, Cat> const b) noexcept
514  {
515  return b < a;
516  }
517 
519  // -- END Comparison operations --------------------------------------------
520 
521  // -- BEGIN Arithmetic operations ------------------------------------------
532 
535  template <typename Q, typename Cat, typename T>
537  constexpr std::enable_if_t<std::is_arithmetic_v<T>, Interval<Q, Cat>> operator*(
538  Interval<Q, Cat> const iv,
539  T const factor)
540  {
541  return Interval<Q, Cat>{iv.quantity() * factor};
542  }
543  template <typename Q, typename Cat, typename T>
544  constexpr std::enable_if_t<std::is_arithmetic_v<T>, Interval<Q, Cat>> operator*(
545  T const factor,
546  Interval<Q, Cat> const iv)
547  {
548  return iv * factor;
549  }
551 
553  template <typename AQ, typename AC, typename BQ, typename BC>
554  constexpr auto operator*(Interval<AQ, AC> const, Interval<BQ, BC> const)
555  // -> decltype(std::declval<AQ>() * std::declval<AQ>())
556  = delete;
557 
558  // Division by a scalar.
559  template <typename Q, typename Cat, typename T>
560  constexpr std::enable_if_t<std::is_arithmetic_v<T>, Interval<Q, Cat>> operator/(
561  Interval<Q, Cat> const iv,
562  T const quot)
563  {
564  return Interval<Q, Cat>{iv.quantity() / quot};
565  }
566 
568  // -- END Arithmetic operations --------------------------------------------
569 
570  // -------------------------------------------------------------------------
572  template <typename IV, typename R, typename T = typename IV::value_t>
573  using rescale_interval =
575 
576  // -------------------------------------------------------------------------
577  template <typename Q, typename Cat>
578  std::string to_string(Interval<Q, Cat> const& iv)
579  {
580  return util::to_string(iv.quantity());
581  }
582 
583  // -------------------------------------------------------------------------
584 
604  template <typename Q, typename Cat = NoCategory, typename IV = Interval<Q, Cat>>
605  struct Point : private Q, public details::WithCategory<Cat> {
606 
608 
611 
612  template <typename OC, typename Type = void>
613  using enable_if_compatible_t =
614  std::enable_if_t<category_base_t::template category_compatible_with<OC>(), Type>;
615 
616  public:
618 
619  // --- BEGIN -- Types from the base quantity -----------------------------
622 
623  using quantity_t = Q;
624 
627 
629  using interval_t = IV;
630 
632  template <typename R>
634 
636  using value_t = typename quantity_t::value_t;
637 
639  using unit_t = typename quantity_t::unit_t;
640 
642  using baseunit_t = typename quantity_t::baseunit_t;
643 
645  template <typename OQ, typename OI>
647 
649  // --- END -- Types from the base quantity -------------------------------
650 
652  // NOTE: this is not `constexpr` because using it in a constexpr would
653  // yield an uninitialized constant
654  explicit Point() = default;
655 
657  explicit constexpr Point(value_t v) : Point(quantity_t{v}) {}
658 
669  template <typename... Args>
670  constexpr Point(Quantity<Args...> const q) : quantity_t(quantity_t{q})
671  {}
672 
682  template <typename PT, typename std::enable_if_t<is_point_v<PT>>* = nullptr>
683  constexpr Point(PT const p) : Point(quantity_t{p.quantity()})
684  {}
685 
687  constexpr quantity_t const& quantity() const { return *this; }
688 
690  using quantity_t::value;
691 
693  explicit constexpr operator value_t() const { return value(); }
694 
695  // -- BEGIN Asymmetric arithmetic operations -----------------------------
721 
725  template <typename R>
726  constexpr point_t operator+(scaled_quantity_t<R> const delta) const
727  {
728  return point_t(quantity().plus(delta));
729  }
730 
733  template <typename OQ, typename OC>
735  Interval<OQ, OC> const delta) const
736  {
737  return operator+(delta.quantity());
738  }
739 
741  template <typename R>
742  constexpr point_t operator-(scaled_quantity_t<R> const delta) const
743  {
744  return point_t(quantity().minus(delta));
745  }
746 
748  template <typename OQ, typename OC>
749  constexpr enable_if_compatible_t<Interval<OQ, OC>, point_t> operator-(
750  Interval<OQ, OC> const delta) const
751  {
752  return operator-(delta.quantity());
753  }
754 
756  template <typename R>
758  {
759  quantity_t::operator+=(other);
760  return *this;
761  }
762 
764  template <typename OQ, typename OC>
765  enable_if_compatible_t<Interval<OQ, OC>, point_t&> operator+=(Interval<OQ, OC> const other)
766  {
767  return operator+=(other.quantity());
768  }
769 
771  template <typename R>
773  {
774  quantity_t::operator-=(other);
775  return *this;
776  }
777 
779  template <typename OQ, typename OC>
780  enable_if_compatible_t<Interval<OQ, OC>, point_t&> operator-=(Interval<OQ, OC> const other)
781  {
782  return operator-=(other.quantity());
783  }
784 
786  constexpr point_t operator+() const { return point_t(quantity()); }
787 
789  constexpr point_t operator-() const { return point_t(-quantity()); }
790 
792  // -- END Asymmetric arithmetic operations -------------------------------
793 
794  // -- BEGIN Comparisons --------------------------------------------------
812 
814  template <typename OQ, typename OI>
816  other_point_t<OQ, OI> const other) const
817  {
818  return quantity_t::operator==(other.quantity());
819  }
820 
821  template <typename OQ, typename OI>
822  constexpr enable_if_compatible_t<other_point_t<OQ, OI>, bool> operator!=(
823  other_point_t<OQ, OI> const other) const
824  {
825  return quantity_t::operator!=(other.quantity());
826  }
827 
828  template <typename OQ, typename OI>
829  constexpr enable_if_compatible_t<other_point_t<OQ, OI>, bool> operator>=(
830  other_point_t<OQ, OI> const other) const
831  {
832  return quantity_t::operator>=(other.quantity());
833  }
834 
835  template <typename OQ, typename OI>
836  constexpr enable_if_compatible_t<other_point_t<OQ, OI>, bool> operator>(
837  other_point_t<OQ, OI> const other) const
838  {
839  return quantity_t::operator>(other.quantity());
840  }
841 
842  template <typename OQ, typename OI>
843  constexpr enable_if_compatible_t<other_point_t<OQ, OI>, bool> operator<=(
844  other_point_t<OQ, OI> const other) const
845  {
846  return quantity_t::operator<=(other.quantity());
847  }
848 
849  template <typename OQ, typename OI>
850  constexpr enable_if_compatible_t<other_point_t<OQ, OI>, bool> operator<(
851  other_point_t<OQ, OI> const other) const
852  {
853  return quantity_t::operator<(other.quantity());
854  }
855 
857  // -- END Asymmetric arithmetic operations -------------------------------
858 
859  // -- BEGIN Access to the scaled unit ------------------------------------
862 
863  using quantity_t::baseUnit;
864  using quantity_t::unit;
865  using quantity_t::unitName;
866  using quantity_t::unitSymbol;
867 
869  // -- END Access to the scaled unit --------------------------------------
870 
872  template <typename PT>
873  constexpr std::enable_if_t<is_point_v<PT>, PT> convertInto() const
874  {
875  return PT(*this);
876  }
877 
886  template <typename U>
888  {
889  return point_t{static_cast<value_t>(value)};
890  }
891 
892  }; // struct Point
893 
894  template <typename... Args>
895  std::ostream& operator<<(std::ostream& out, Point<Args...> const p)
896  {
897  return out << p.quantity();
898  }
899 
900  // -- BEGIN Comparison operations ------------------------------------------
911 
913  template <typename Q, typename Cat, typename IV, typename... Args>
914  constexpr bool operator==(Point<Q, Cat, IV> const a, Quantity<Args...> const b) noexcept
915  {
916  return a.quantity() == b;
917  }
918 
919  template <typename Q, typename Cat, typename IV, typename... Args>
920  constexpr bool operator==(Quantity<Args...> const a, Point<Q, Cat, IV> const b) noexcept
921  {
922  return b == a;
923  }
924 
925  template <typename Q, typename Cat, typename IV, typename... Args>
926  constexpr bool operator!=(Point<Q, Cat, IV> const a, Quantity<Args...> const b) noexcept
927  {
928  return a.quantity() != b;
929  }
930 
931  template <typename Q, typename Cat, typename IV, typename... Args>
932  constexpr bool operator!=(Quantity<Args...> const a, Point<Q, Cat, IV> const b) noexcept
933  {
934  return b != a;
935  }
936 
937  template <typename Q, typename Cat, typename IV, typename... Args>
938  constexpr bool operator<=(Point<Q, Cat, IV> const a, Quantity<Args...> const b) noexcept
939  {
940  return a.quantity() <= b;
941  }
942 
943  template <typename Q, typename Cat, typename IV, typename... Args>
944  constexpr bool operator<=(Quantity<Args...> const a, Point<Q, Cat, IV> const b) noexcept
945  {
946  return b >= a;
947  }
948 
949  template <typename Q, typename Cat, typename IV, typename... Args>
950  constexpr bool operator<(Point<Q, Cat, IV> const a, Quantity<Args...> const b) noexcept
951  {
952  return a.quantity() < b;
953  }
954 
955  template <typename Q, typename Cat, typename IV, typename... Args>
956  constexpr bool operator<(Quantity<Args...> const a, Point<Q, Cat, IV> const b) noexcept
957  {
958  return b > a;
959  }
960 
961  template <typename Q, typename Cat, typename IV, typename... Args>
962  constexpr bool operator>=(Point<Q, Cat, IV> const a, Quantity<Args...> const b) noexcept
963  {
964  return a.quantity() >= b;
965  }
966 
967  template <typename Q, typename Cat, typename IV, typename... Args>
968  constexpr bool operator>=(Quantity<Args...> const a, Point<Q, Cat, IV> const b) noexcept
969  {
970  return b <= a;
971  }
972 
973  template <typename Q, typename Cat, typename IV, typename... Args>
974  constexpr bool operator>(Point<Q, Cat, IV> const a, Quantity<Args...> const b) noexcept
975  {
976  return a.quantity() > b;
977  }
978 
979  template <typename Q, typename Cat, typename IV, typename... Args>
980  constexpr bool operator>(Quantity<Args...> const a, Point<Q, Cat, IV> const b) noexcept
981  {
982  return b < a;
983  }
984 
986  // -- END Comparison operations --------------------------------------------
987 
988  // -- BEGIN Arithmetic operations ------------------------------------------
999 
1001  template <typename Q, typename Cat, typename IV, typename OQ, typename OC>
1002  constexpr Point<Q, Cat, IV> operator+(Interval<OQ, OC> const delta, Point<Q, Cat, IV> const p) =
1003  delete; // use `point + interval`, not `interval + point`
1004 
1005  template <typename Q, typename Cat, typename IV, typename OQ, typename OC>
1006  constexpr Point<Q, Cat, IV> operator-(Interval<OQ, OC> const delta, Point<Q, Cat, IV> const p) =
1007  delete; // use `point + interval`, not `interval + point`
1008 
1009  // two different points but with the same interval type
1010  template <typename Q, typename Cat, typename IV, typename OQ, typename OCat>
1011  constexpr typename Point<Q, Cat, IV>::template enable_if_compatible_t<Point<OQ, OCat, IV>, IV>
1013  {
1014  return IV(a.quantity() - b.quantity());
1015  }
1016 
1018  // -- END Arithmetic operations --------------------------------------------
1019 
1020  // -------------------------------------------------------------------------
1022  template <typename PT, typename R, typename T = typename PT::value_t>
1024 
1025  // -------------------------------------------------------------------------
1026  template <typename Q, typename Cat, typename IV>
1027  std::string to_string(Point<Q, Cat, IV> const& p)
1028  {
1029  return util::to_string(p.quantity());
1030  }
1031 
1032  // -------------------------------------------------------------------------
1033 
1034  } // namespace concepts
1035 
1036  // ---------------------------------------------------------------------------
1038 
1039  static std::string name() { return "generic"; }
1040 
1041  }; // struct NoCategory
1042 
1043  // ---------------------------------------------------------------------------
1044  // @{
1058  template <typename IV>
1059  IV makeInterval(std::string_view s, bool unitOptional = false);
1060 
1061  template <typename IV>
1062  IV makeInterval(std::string const& s, bool unitOptional = false);
1063 
1064  template <typename IV>
1065  IV makeInterval(char const* s, bool unitOptional = false);
1066 
1068 
1069  // @{
1083  template <typename PT>
1084  PT makePoint(std::string_view s, bool unitOptional = false);
1085 
1086  template <typename PT>
1087  PT makePoint(std::string const& s, bool unitOptional = false);
1088 
1089  template <typename PT>
1090  PT makePoint(char const* s, bool unitOptional = false);
1091 
1093 
1094  // ---------------------------------------------------------------------------
1095 
1096 } // namespace util::quantities
1097 
1098 //------------------------------------------------------------------------------
1099 //--- template implementation
1100 //------------------------------------------------------------------------------
1102 
1103  //----------------------------------------------------------------------------
1104  template <typename, typename = std::void_t<>>
1105  struct has_category : std::false_type {};
1106 
1107  template <typename Obj>
1108  struct has_category<Obj, std::void_t<typename Obj::category_t>> : std::true_type {};
1109 
1110  template <typename Obj>
1111  constexpr bool has_category_v = has_category<Obj>();
1112 
1113  //----------------------------------------------------------------------------
1114  template <typename, typename = std::void_t<>>
1115  struct category_has_name : std::false_type {};
1116 
1117  template <typename Cat>
1118  struct category_has_name<Cat, std::void_t<decltype(Cat::name())>> : std::true_type {};
1119 
1120  template <typename Cat>
1122 
1123  using category_t = Cat;
1124 
1126  static constexpr bool has_name = category_has_name<category_t>();
1127 
1129  template <typename OC>
1130  static constexpr bool compatible_with()
1131  {
1132  return util::is_any_of_v<OC, NoCategory, category_t>;
1133  }
1134 
1135  }; // struct category_traits<>
1136 
1137  //----------------------------------------------------------------------------
1138  template <typename Cat, typename /* = void */>
1139  struct category_of_type {
1140  using type = Cat;
1141  };
1142 
1143  template <typename Cat>
1144  struct category_of_type<Cat, std::void_t<typename Cat::category_t>> {
1145  using type = typename Cat::category_t;
1146  };
1147 
1148  //----------------------------------------------------------------------------
1149  template <typename Cat>
1150  struct WithCategory {
1151 
1152  using category_t = Cat;
1153 
1156 
1158  static constexpr category_t category();
1159 
1160  // @{
1162  template <typename OC>
1163  static constexpr bool same_category_as();
1164 
1165  template <typename OC>
1166  static constexpr bool same_category_as(OC const&);
1167  // @}
1168 
1169  // @{
1171  template <typename OC>
1172  static constexpr bool category_compatible_with();
1173 
1174  template <typename OC>
1175  static constexpr bool category_compatible_with(OC const&);
1176  // @}
1177 
1179  static constexpr bool hasCategoryName();
1180 
1182  static std::string categoryName();
1183 
1184  }; // struct WithCategory<>
1185 
1186  //----------------------------------------------------------------------------
1187  //--- WithCategory
1188  //----------------------------------------------------------------------------
1189  template <typename Cat>
1191  {
1192  return {};
1193  }
1194 
1195  //----------------------------------------------------------------------------
1196  template <typename Cat>
1197  template <typename OC>
1199  {
1200  return details::has_category_v<OC> && std::is_same_v<typename OC::category_t, category_t>;
1201  } // WithCategory<>::same_category_as()
1202 
1203  template <typename Cat>
1204  template <typename OC>
1205  constexpr bool WithCategory<Cat>::same_category_as(OC const&)
1206  {
1207  return same_category_as<OC>();
1208  }
1209 
1210  //----------------------------------------------------------------------------
1211  template <typename Cat>
1212  template <typename OC>
1214  {
1215  return traits_t::template compatible_with<category_of<OC>>();
1216  }
1217 
1218  template <typename Cat>
1219  template <typename OC>
1221  {
1222  return category_compatible_with<OC>();
1223  }
1224 
1225  //----------------------------------------------------------------------------
1226  template <typename Cat>
1228  {
1230  }
1231 
1232  //----------------------------------------------------------------------------
1233  template <typename Cat>
1235  {
1236  return Cat::name();
1237  }
1238 
1239  //----------------------------------------------------------------------------
1240 
1241 } // namespace util::quantities::concepts::details
1242 
1243 //------------------------------------------------------------------------------
1244 //--- template implementation
1245 //------------------------------------------------------------------------------
1246 namespace util::quantities::concepts {
1247 
1248  //----------------------------------------------------------------------------
1249  template <typename>
1250  struct is_interval : public std::false_type {};
1251 
1252  template <typename... Args>
1253  struct is_interval<Interval<Args...>> : public std::true_type {};
1254 
1255  //----------------------------------------------------------------------------
1256  template <typename>
1257  struct is_point : public std::false_type {};
1258 
1259  template <typename... Args>
1260  struct is_point<Point<Args...>> : public std::true_type {};
1261 
1262  //----------------------------------------------------------------------------
1263 
1264 } // namespace util::quantities::concepts
1265 
1266 //------------------------------------------------------------------------------
1267 //--- Template implementation
1268 //------------------------------------------------------------------------------
1269 template <typename IV>
1270 IV util::quantities::makeInterval(std::string_view s, bool unitOptional /* = false */)
1271 {
1272  using quantity_t = typename IV::quantity_t;
1273  return {util::quantities::makeQuantity<quantity_t>(s, unitOptional)};
1274 } // util::quantities::makeInterval(string_view)
1275 
1276 //------------------------------------------------------------------------------
1277 template <typename IV>
1278 IV util::quantities::makeInterval(std::string const& s, bool unitOptional /* = false */)
1279 {
1280  using quantity_t = typename IV::quantity_t;
1281  return {util::quantities::makeQuantity<quantity_t>(s, unitOptional)};
1282 } // util::quantities::makeInterval(string)
1283 
1284 //------------------------------------------------------------------------------
1285 template <typename IV>
1286 IV util::quantities::makeInterval(char const* s, bool unitOptional /* = false */)
1287 {
1288  using quantity_t = typename IV::quantity_t;
1289  return {util::quantities::makeQuantity<quantity_t>(s, unitOptional)};
1290 } // util::quantities::makeInterval(C-string)
1291 
1292 //------------------------------------------------------------------------------
1293 template <typename PT>
1294 PT util::quantities::makePoint(std::string_view s, bool unitOptional /* = false */)
1295 {
1296  using quantity_t = typename PT::quantity_t;
1297  return {util::quantities::makeQuantity<quantity_t>(s, unitOptional)};
1298 } // util::quantities::makePoint(string_view)
1299 
1300 //------------------------------------------------------------------------------
1301 template <typename PT>
1302 PT util::quantities::makePoint(std::string const& s, bool unitOptional /* = false */)
1303 {
1304  using quantity_t = typename PT::quantity_t;
1305  return {util::quantities::makeQuantity<quantity_t>(s, unitOptional)};
1306 } // util::quantities::makePoint(string)
1307 
1308 //------------------------------------------------------------------------------
1309 template <typename PT>
1310 PT util::quantities::makePoint(char const* s, bool unitOptional /* = false */)
1311 {
1312  using quantity_t = typename PT::quantity_t;
1313  return {util::quantities::makeQuantity<quantity_t>(s, unitOptional)};
1314 } // util::quantities::makePoint(C-string)
1315 
1316 //------------------------------------------------------------------------------
1317 //--- Standard library extensions
1318 //------------------------------------------------------------------------------
1319 namespace std {
1320 
1321  // ---------------------------------------------------------------------------
1323  template <typename Q, typename Cat>
1324  struct hash<util::quantities::concepts::Interval<Q, Cat>> {
1326  noexcept(noexcept(std::hash(key.quantity())))
1327  {
1328  return std::hash(key.quantity());
1329  }
1330  }; // hash<Interval>
1331 
1332  template <typename Q, typename Cat, typename IV>
1333  struct hash<util::quantities::concepts::Point<Q, Cat, IV>> {
1335  noexcept(noexcept(std::hash(key.quantity())))
1336  {
1337  return std::hash(key.quantity());
1338  }
1339  }; // hash<Interval>
1340 
1341  // ---------------------------------------------------------------------------
1344  template <typename Q, typename Cat>
1345  class numeric_limits<util::quantities::concepts::Interval<Q, Cat>>
1347  util::quantities::concepts::Interval<Q, Cat>> {};
1348 
1349  template <typename Q, typename Cat>
1350  class numeric_limits<util::quantities::concepts::Interval<Q, Cat> const>
1352  util::quantities::concepts::Interval<Q, Cat> const> {};
1353 
1354  template <typename Q, typename Cat>
1355  class numeric_limits<util::quantities::concepts::Interval<Q, Cat> volatile>
1357  util::quantities::concepts::Interval<Q, Cat> volatile> {};
1358 
1359  template <typename Q, typename Cat>
1360  class numeric_limits<util::quantities::concepts::Interval<Q, Cat> const volatile>
1362  util::quantities::concepts::Interval<Q, Cat> const volatile> {};
1363 
1364  template <typename Q, typename Cat, typename IV>
1365  class numeric_limits<util::quantities::concepts::Point<Q, Cat, IV>>
1367  util::quantities::concepts::Point<Q, Cat, IV>> {};
1368 
1369  template <typename Q, typename Cat, typename IV>
1370  class numeric_limits<util::quantities::concepts::Point<Q, Cat, IV> const>
1372  util::quantities::concepts::Point<Q, Cat, IV> const> {};
1373 
1374  template <typename Q, typename Cat, typename IV>
1375  class numeric_limits<util::quantities::concepts::Point<Q, Cat, IV> volatile>
1377  util::quantities::concepts::Point<Q, Cat, IV> volatile> {};
1378 
1379  template <typename Q, typename Cat, typename IV>
1380  class numeric_limits<util::quantities::concepts::Point<Q, Cat, IV> const volatile>
1382  util::quantities::concepts::Point<Q, Cat, IV> const volatile> {};
1383 
1384  // ---------------------------------------------------------------------------
1385 
1386 } // namespace std
1387 
1388 //------------------------------------------------------------------------------
1389 
1390 #endif // LARDATAALG_UTILITIES_INTERVALS_H
point_t & operator+=(scaled_quantity_t< R > const other)
Add a quantity (possibly converted) to this one.
Definition: intervals.h:757
constexpr interval_t operator+() const
Returns an interval with same value.
Definition: intervals.h:330
typename category_base_t::category_t category_t
Quantity the interval is based on.
Definition: intervals.h:127
constexpr enable_if_compatible_t< other_point_t< OQ, OI >, bool > operator<(other_point_t< OQ, OI > const other) const
Definition: intervals.h:850
Namespace for general, non-LArSoft-specific utilities.
Definition: PIDAAlg.h:26
constexpr enable_if_compatible_t< Interval< OQ, OC >, point_t > operator+(Interval< OQ, OC > const delta) const
Definition: intervals.h:734
constexpr enable_if_compatible_t< Interval< OQ, OC >, bool > operator==(Interval< OQ, OC > const other) const
Definition: intervals.h:360
constexpr std::enable_if_t< std::is_arithmetic_v< T >, Interval< Q, Cat > > operator/(Interval< Q, Cat > const iv, T const quot)
Definition: intervals.h:560
constexpr Interval(IV iv)
Constructor: converts from another interval.
Definition: intervals.h:181
static constexpr bool sameBaseUnitAs()
Returns whether objects of type OU have the same base unit as this.
Definition: intervals.h:214
constexpr bool operator<=(Interval< Q, Cat > const a, Quantity< Args... > const b) noexcept
Definition: intervals.h:471
std::enable_if_t< category_base_t::template category_compatible_with< OC >(), Type > enable_if_compatible_t
Definition: intervals.h:115
constexpr enable_if_compatible_t< Interval< OQ, OC >, value_t > operator/(Interval< OQ, OC > const denom) const
Division by an interval, returns a pure number.
Definition: intervals.h:277
constexpr interval_t operator-(interval_t const other) const
Definition: intervals.h:270
constexpr bool operator>(Interval< Q, Cat > const a, Quantity< Args... > const b) noexcept
Definition: intervals.h:507
Q quantity_t
Quantity the interval is based on.
Definition: intervals.h:623
constexpr point_t operator+(scaled_quantity_t< R > const delta) const
Definition: intervals.h:726
constexpr Interval(value_t v)
Constructor: takes a value in the intended representation.
Definition: intervals.h:155
interval_t & operator*=(T factor)
Scale this interval by a factor.
Definition: intervals.h:315
static interval_t castFrom(U value)
Returns a new interval initialized with the specified value.
Definition: intervals.h:420
typename T::interval_t interval_of
Type of interval contained in specified type T.
Definition: intervals.h:86
enable_if_compatible_t< Interval< OQ, OC >, point_t & > operator+=(Interval< OQ, OC > const other)
Add the other interval (possibly converted) to this point.
Definition: intervals.h:765
constexpr Point< Q, Cat, IV > operator+(Interval< OQ, OC > const delta, Point< Q, Cat, IV > const p)=delete
Multiplication with a scalar.
interval_t & operator/=(T factor)
Scale the interval dividing it by a quotient.
Definition: intervals.h:323
constexpr enable_if_compatible_t< other_point_t< OQ, OI >, bool > operator>=(other_point_t< OQ, OI > const other) const
Definition: intervals.h:829
constexpr enable_if_compatible_t< Interval< OQ, OC >, bool > operator<(Interval< OQ, OC > const other) const
Definition: intervals.h:395
constexpr bool operator<(Interval< Q, Cat > const a, Quantity< Args... > const b) noexcept
Definition: intervals.h:483
PT makePoint(std::string_view s, bool unitOptional=false)
Returns a point of the specified type parsed from a string.
Definition: intervals.h:1294
Trait: true_type if IV is a Interval specialization.
Definition: intervals.h:58
STL namespace.
constexpr auto operator()(util::quantities::concepts::Interval< Q, Cat > key) const noexcept(noexcept(std::hash(key.quantity())))
Definition: intervals.h:1325
typename category_of_type< Cat >::type category_of
Definition: intervals.h:35
constexpr enable_if_compatible_t< Interval< OQ, OC >, bool > operator<=(Interval< OQ, OC > const other) const
Definition: intervals.h:388
constexpr enable_if_compatible_t< Interval< OQ, OC >, bool > operator>=(Interval< OQ, OC > const other) const
Definition: intervals.h:374
static constexpr category_t category()
Returns an instance of the category of this object.
Definition: intervals.h:1190
constexpr point_t operator-(scaled_quantity_t< R > const delta) const
Returns the value of this point after subtraction of an interval.
Definition: intervals.h:742
std::string to_string(Interval< Q, Cat > const &iv)
Definition: intervals.h:578
typename quantity_t::baseunit_t baseunit_t
Description of the unscaled unit.
Definition: intervals.h:642
constexpr bool operator<(Quantity< Args... > const a, Point< Q, Cat, IV > const b) noexcept
Definition: intervals.h:956
constexpr quantity_t const & quantity() const
Returns the value of the interval as a quantity.
Definition: intervals.h:687
typename category_base_t::traits_t traits_t
Traits of the category.
Definition: intervals.h:111
typename category_base_t::category_t category_t
The category this point belongs to.
Definition: intervals.h:626
constexpr auto operator()(util::quantities::concepts::Point< Q, Cat, IV > key) const noexcept(noexcept(std::hash(key.quantity())))
Definition: intervals.h:1334
constexpr Interval(Quantity< Args... > const &q)
Constructor: converts from a quantity.
Definition: intervals.h:168
constexpr bool is_interval_v
Trait: true if IV is a Interval specialization.
Definition: intervals.h:62
enable_if_compatible_t< Interval< OQ, OC >, interval_t & > operator+=(Interval< OQ, OC > const other)
Add the other interval (possibly converted) to this one.
Definition: intervals.h:293
An object belonging to a category Cat.
Definition: intervals.h:40
Infrastructure for the quantities library.
Definition: intervals.h:25
static std::string categoryName()
Returns the name of the category of this object.
Definition: intervals.h:1234
static point_t castFrom(U value)
Returns a new point initialized with the specified value.
Definition: intervals.h:887
static constexpr bool sameUnitAs()
Returns whether objects of type OU have same unit and scale as this.
Definition: intervals.h:221
static constexpr bool same_category_as()
Returns whether the type OC belongs to category_t.
Definition: intervals.h:1198
constexpr enable_if_compatible_t< other_point_t< OQ, OI >, bool > operator<=(other_point_t< OQ, OI > const other) const
Definition: intervals.h:843
decltype(auto) constexpr to_string(T &&obj)
ADL-aware version of std::to_string.
constexpr bool operator>=(Interval< Q, Cat > const a, Quantity< Args... > const b) noexcept
Definition: intervals.h:495
static constexpr bool category_compatible_with()
Returns whether OC has a category compatible with this one.
Definition: intervals.h:1213
constexpr point_t operator-() const
Returns a parity-changed point.
Definition: intervals.h:789
constexpr bool operator==(Quantity< Args... > const a, Point< Q, Cat, IV > const b) noexcept
Definition: intervals.h:920
A value measured in the specified unit.
Definition: quantities.h:554
constexpr enable_if_compatible_t< other_point_t< OQ, OI >, bool > operator>(other_point_t< OQ, OI > const other) const
Definition: intervals.h:836
point_t & operator-=(scaled_quantity_t< R > const other)
Subtract a quantity (possibly converted) from this one.
Definition: intervals.h:772
constexpr bool operator==(Interval< Q, Cat > const a, Quantity< Args... > const b) noexcept
Definition: intervals.h:447
enable_if_compatible_t< Interval< OQ, OC >, interval_t & > operator-=(Interval< OQ, OC > const other)
Subtract the other interval (possibly converted) from this one.
Definition: intervals.h:308
typename quantity_t::baseunit_t baseunit_t
Description of the unscaled unit.
Definition: intervals.h:140
String & operator+=(String &s, VectorDumper< Vector > const &manip)
Appends a string rendering of a vector to the specified string.
Definition: DumpUtils.h:463
constexpr interval_t operator+(interval_t const other) const
Definition: intervals.h:263
constexpr quantity_t const & quantity() const
Returns the value of the interval as a quantity.
Definition: intervals.h:185
Cat category_t
The categories the traits are about.
Definition: intervals.h:1123
constexpr IV convertInto() const
Convert this interval into the specified one.
Definition: intervals.h:406
constexpr bool operator!=(Quantity< Args... > const a, Point< Q, Cat, IV > const b) noexcept
Definition: intervals.h:932
constexpr bool operator<=(Quantity< Args... > const a, Point< Q, Cat, IV > const b) noexcept
Definition: intervals.h:944
constexpr bool operator!=(Interval< Q, Cat > const a, Quantity< Args... > const b) noexcept
Definition: intervals.h:459
An interval (duration, length, distance) between two quantity points.
Definition: intervals.h:106
interval_t & operator-=(scaled_quantity_t< R > const other)
Subtract a quantity (possibly converted) from this one.
Definition: intervals.h:300
struct point_s point_t
Definition: DBScan3DAlg.h:56
double value
Definition: spectrum.C:18
IV interval_t
The interval type corresponding to the unit of this point.
Definition: intervals.h:629
constexpr std::enable_if_t< is_point_v< PT >, PT > convertInto() const
Convert this interval into the specified one.
Definition: intervals.h:873
static constexpr bool compatible_with()
Returns whether the category OC is "compatible" with this one.
Definition: intervals.h:1130
constexpr bool operator>(Quantity< Args... > const a, Point< Q, Cat, IV > const b) noexcept
Definition: intervals.h:980
enable_if_compatible_t< Interval< OQ, OC >, point_t & > operator-=(Interval< OQ, OC > const other)
Subtract the other interval (possibly converted) from this point.
Definition: intervals.h:780
Trait: true_type if PT is a Point specialization.
Definition: intervals.h:67
constexpr Point(Quantity< Args... > const q)
Constructor: converts from a quantity.
Definition: intervals.h:670
Numeric variable proxies with embedded unit of measurement.
constexpr Point(PT const p)
Constructor: converts from another point.
Definition: intervals.h:683
static std::string name()
Definition: intervals.h:1039
constexpr bool operator>=(Quantity< Args... > const a, Point< Q, Cat, IV > const b) noexcept
Definition: intervals.h:968
constexpr enable_if_compatible_t< other_point_t< OQ, OI >, bool > operator!=(other_point_t< OQ, OI > const other) const
Definition: intervals.h:822
Cat category_t
The category of this object.
Definition: intervals.h:1152
std::ostream & operator<<(std::ostream &out, Interval< Args... > const iv)
Definition: intervals.h:428
constexpr Point< Q, Cat, IV > operator-(Interval< OQ, OC > const delta, Point< Q, Cat, IV > const p)=delete
Multiplication with a scalar.
An non-mandatory base class for interval and point categories.
Definition: intervals.h:48
std::tuple< double, double, const reco::ClusterHit3D * > Point
Definitions used by the VoronoiDiagram algorithm.
Definition: DCEL.h:42
std::enable_if_t< category_base_t::template category_compatible_with< OC >(), Type > enable_if_compatible_t
Definition: intervals.h:614
constexpr enable_if_compatible_t< Interval< OQ, OC >, bool > operator>(Interval< OQ, OC > const other) const
Definition: intervals.h:381
constexpr interval_t abs() const
Returns an interval with the absolute value of this one.
Definition: intervals.h:336
typename quantity_t::value_t value_t
Type of the stored value.
Definition: intervals.h:636
constexpr std::enable_if_t< std::is_arithmetic_v< T >, Interval< Q, Cat > > operator*(Interval< Q, Cat > const iv, T const factor)
Multiplication with a scalar.
Definition: intervals.h:537
typename quantity_t::value_t value_t
Type of the stored value.
Definition: intervals.h:134
constexpr interval_t operator-() const
Returns an interval with same value but the sign flipped.
Definition: intervals.h:333
Limits of a quantity are the same as the underlying type.
Definition: quantities.h:324
Q quantity_t
Quantity the interval is based on.
Definition: intervals.h:124
IV makeInterval(std::string_view s, bool unitOptional=false)
Returns an interval of the specified type parsed from a string.
Definition: intervals.h:1270
constexpr enable_if_compatible_t< other_point_t< OQ, OI >, bool > operator==(other_point_t< OQ, OI > const other) const
Definition: intervals.h:815
constexpr bool is_interval_or_point_v
Trait: true if PT is a specialization of Interval or Point.
Definition: intervals.h:80
Types of variables with a unit.
Definition: intervals.h:20
typename category_base_t::traits_t traits_t
Traits of the category.
Definition: intervals.h:610
constexpr enable_if_compatible_t< Interval< OQ, OC >, point_t > operator-(Interval< OQ, OC > const delta) const
Returns the value of this point after subtraction of an interval.
Definition: intervals.h:749
constexpr point_t operator+() const
Returns a point with same value.
Definition: intervals.h:786
constexpr bool is_point_v
Trait: true if PT is a Point specialization.
Definition: intervals.h:71
constexpr Point(value_t v)
Constructor: takes a value in the intended representation.
Definition: intervals.h:657
typename quantity_t::unit_t unit_t
Description of the scaled unit.
Definition: intervals.h:639
static constexpr bool hasCategoryName()
Returns whether this category has a name.
Definition: intervals.h:1227
constexpr enable_if_compatible_t< Interval< OQ, OC >, bool > operator!=(Interval< OQ, OC > const other) const
Definition: intervals.h:367
interval_t & operator+=(scaled_quantity_t< R > const other)
Add a quantity (possibly converted) to this one.
Definition: intervals.h:285
typename quantity_t::unit_t unit_t
Description of the scaled unit.
Definition: intervals.h:137
std::disjunction< is_interval< T >, is_point< T >> is_interval_or_point
Trait: true_type if PT is a specialization of Interval or Point.
Definition: intervals.h:76