intervals.h
Go to the documentation of this file.
1 /**
2  * @file lardataalg/Utilities/intervals.h
3  * @brief Defines point and interval variables based on quantities.
4  * @author Gianluca Petrillo (petrillo@slac.stanford.edu)
5  * @date May 29, 2019
6  * @see lardataalg/Utilities/quantites.h
7  *
8  */
9 
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 
22  /// Category type for intervals and point not belonging to any category.
23  struct NoCategory;
24 
25 
26  namespace concepts {
27 
28  namespace details {
29 
30  //------------------------------------------------------------------------
31 
32  template <typename Cat, typename = void>
34 
35  template <typename Cat>
37 
38 
39  //------------------------------------------------------------------------
40  /// An object belonging to a category `Cat`.
41  template <typename Cat>
42  struct WithCategory;
43 
44 
45  //------------------------------------------------------------------------
46 
47  } // namespace details
48 
49 
50  //--------------------------------------------------------------------------
51  /// An non-mandatory base class for interval and point categories.
52  struct CategoryBase {
53  /// Returns the name of this category. Optional.
54  static std::string name() = delete;
55  }; // struct CategoryBase
56 
57 
58  //--------------------------------------------------------------------------
59  //--- traits
60  //--------------------------------------------------------------------------
61  /// Trait: `true_type` if `IV` is a `Interval` specialization.
62  template <typename IV>
63  struct is_interval;
64 
65  /// Trait: `true` if `IV` is a `Interval` specialization.
66  template <typename IV>
67  constexpr bool is_interval_v = is_interval<IV>();
68 
69 
70  //--------------------------------------------------------------------------
71  /// Trait: `true_type` if `PT` is a `Point` specialization.
72  template <typename PT>
73  struct is_point;
74 
75  /// Trait: `true` if `PT` is a `Point` specialization.
76  template <typename PT>
77  constexpr bool is_point_v = is_point<PT>();
78 
79 
80  //--------------------------------------------------------------------------
81  /// Trait: `true_type` if `PT` is a specialization of `Interval` or `Point`.
82  template <typename T>
83  using is_interval_or_point = std::disjunction<is_interval<T>, is_point<T>>;
84 
85  /// Trait: `true` if `PT` is a specialization of `Interval` or `Point`.
86  template <typename T>
88 
89 
90  //--------------------------------------------------------------------------
91 
92  /// Type of interval contained in specified type `T`.
93  template <typename T>
94  using interval_of = typename T::interval_t;
95 
96  //--------------------------------------------------------------------------
97 
98  /** ************************************************************************
99  * @brief An interval (duration, length, distance) between two
100  * quantity points.
101  * @tparam Q quantity the interval is based on
102  *
103  * An interval shares most of the concepts of a `Quantity`, but it interacts
104  * only with other intervals rather than with bare `Quantity` objects,
105  * with the exception of construction.
106  * In this sense, the relation between `Interval` and `Quantity` is similar
107  * to the one between `Quantity` and its base type (`Quantity::value_t`).
108  *
109  * In addition, an interval can be added to a quantity point (`Point`) to
110  * translate it, and it can be obtained as difference between two quantity
111  * points.
112  */
113  template <typename Q, typename Cat = NoCategory>
114  struct Interval: private Q, public details::WithCategory<Cat> {
115 
117 
118  /// Traits of the category.
120 
121  template <typename OC, typename Type = void>
123  = std::enable_if_t
124  <category_base_t::template category_compatible_with<OC>(), Type>
125  ;
126 
127  public:
128 
129  using interval_t = Interval<Q, Cat>; ///< This type.
130 
131 
132  // --- BEGIN -- Types from the base quantity -----------------------------
133  /// @name Types from the base quantity
134  /// @{
135 
136  using quantity_t = Q; /// Quantity the interval is based on.
137 
138  /// The category this point belongs to.
140 
141  /// A quantity in the same unit, but possibly a different scale.
142  template <typename R>
144 
145  /// Type of the stored value.
146  using value_t = typename quantity_t::value_t;
147 
148  /// Description of the scaled unit.
149  using unit_t = typename quantity_t::unit_t;
150 
151  /// Description of the unscaled unit.
152  using baseunit_t = typename quantity_t::baseunit_t;
153 
154  /// An interval based on a different quantity but with the same category.
155  template <typename OQ, typename OI>
157 
158  /// @}
159  // --- END -- Types from the base quantity -------------------------------
160 
161  /// Constructor: value is left uninitialized.
162  // NOTE: this is not `constexpr` because using it in a constexpr would
163  // yield an uninitialized constant
164  explicit Interval() = default;
165 
166  /// Constructor: takes a value in the intended representation.
167  explicit constexpr Interval(value_t v): Interval(quantity_t{ v }) {}
168 
169  /**
170  * @brief Constructor: converts from a quantity.
171  * @tparam OQ type of the quantity
172  * @param q quantity to be converted from
173  *
174  * The quantity is required to be in the same unit as this interval
175  * (unit scale may differ).
176  * The value in `q` is converted from its native scale into the one of
177  * this interval.
178  */
179  template <typename... Args>
180  constexpr Interval(Quantity<Args...> const& q)
181  : quantity_t(quantity_t{ q })
182  {}
183 
184  /**
185  * @brief Constructor: converts from another interval.
186  * @tparam I type of the other interval
187  * @param iv interval to be converted from
188  *
189  * Intervals are required to be in the same unit (unit scale may differ).
190  * The value in `iv` is converted from its native scale into the one of
191  * this interval.
192  */
193  template
194  <typename IV, typename std::enable_if_t<is_interval_v<IV>>* = nullptr>
195  constexpr Interval(IV iv): Interval(quantity_t { iv.quantity() }) {}
196 
197  /// Returns the value of the interval as a quantity.
198  constexpr quantity_t const& quantity() const { return *this; }
199 
200  /// Returns the value of the interval as plain value.
201  using quantity_t::value;
202 
203  /// Conversion to the base quantity.
204  explicit constexpr operator value_t() const
205  { return value(); }
206 
207 
208  // -- BEGIN Access to the scaled unit ------------------------------------
209  /// @name Access to the scaled unit.
210  /// @{
211 
212  using quantity_t::unit;
213  using quantity_t::unitName;
214  using quantity_t::unitSymbol;
215  using quantity_t::baseUnit;
216 
217  /*
218  * due to C++ (up to 17 at least) syntax limitations, we can't import
219  * a dependent template (in this case, `Q::baseUnit<U>`, which depends
220  * on a template parameter `Q`) as such: C++ will import it if we use the
221  * "standard" syntax `using quantity_t::sameUnitAs;`, but without
222  * knowning it as a template; the correct syntax to express this would be
223  * `using quantity_t::template sameUnitAs;`, which is not allowed in C++.
224  * So we have to redefine the thing entirely.
225  */
226 
227  /// Returns whether objects of type `OU` have the same base unit as this.
228  template <typename OU>
229  static constexpr bool sameBaseUnitAs()
230  { return quantity_t::template sameBaseUnitAs<OU>(); }
231 
232  /// Returns whether objects of type `OU` have same unit and scale as this.
233  template <typename OU>
234  static constexpr bool sameUnitAs()
235  { return quantity_t::template sameUnitAs<OU>(); }
236 
237 
238  /// @}
239  // -- END Access to the scaled unit --------------------------------------
240 
241 
242  // -- BEGIN Asymmetric arithmetic operations -----------------------------
243  /**
244  * @name Asymmetric operand arithmetic operations
245  *
246  * These arithmetic operations take care of preserving the interval unit
247  * through them.
248  * Not all possible (or reasonable) operations are supported yet.
249  * Some operations that may be symmetric (like multiplication by a scalar)
250  * are implemented as free functions rather than methods.
251  *
252  * @note These operations are essentially provided by convenience. There
253  * are many cases (corner and not) where the implicit conversion
254  * to the base type kicks in. This implementation does not aim to
255  * _prevent_ that from happening, but requests are welcome to add
256  * features to _allow_ that not to happen, with some care of the
257  * user.
258  *
259  * @note The addition and subtraction of intervals is conceptually
260  * symmetric. This leaves open the question whether the result of
261  * `a + b` should be of the type of `a` or the one of `b`, and
262  * whether having `b + a` of a different type than `a + b` is
263  * acceptable. Here we decide it's not, and therefore the operation
264  * `a + b` (and `a - b` as well) are supported only if `a` and `b`
265  * have the same type.
266  * On the other end, if either `a` or `b` are not an interval but
267  * rather a simple quantity, it is clear that the result must still
268  * be an interval and of the same type as the interval operand.
269  * We are in this case allowed to accept quantities of any unit
270  * scale.
271  */
272  /// @{
273 
274  /// Returns an interval sum of this and `other`
275  /// (must have exactly the same unit _and_ scale).
276  constexpr interval_t operator+(interval_t const other) const
277  { return interval_t{ quantity() + other.quantity() }; }
278 
279  /// Returns an interval difference of this and `other`
280  /// (must have exactly the same unit _and_ scale).
281  constexpr interval_t operator-(interval_t const other) const
282  { return interval_t{ quantity() - other.quantity() }; }
283 
284  /// Division by an interval, returns a pure number.
285  template <typename OQ, typename OC>
287  operator/ (Interval<OQ, OC> const denom) const
288  { return quantity() / denom.quantity(); }
289 
290  /// Add a quantity (possibly converted) to this one.
291  template <typename R>
293  { quantity_t::operator+= (other); return *this; }
294 
295  /// Add the `other` interval (possibly converted) to this one.
296  template <typename OQ, typename OC>
297  enable_if_compatible_t<Interval<OQ, OC>, interval_t&>
299  { return operator+= (other.quantity()); }
300 
301  /// Subtract a quantity (possibly converted) from this one.
302  template <typename R>
304  { quantity_t::operator-= (other); return *this; }
305 
306  /// Subtract the `other` interval (possibly converted) from this one.
307  template <typename OQ, typename OC>
308  enable_if_compatible_t<Interval<OQ, OC>, interval_t&>
309  operator-= (Interval<OQ, OC> const other)
310  { return operator-= (other.quantity()); }
311 
312  /// Scale this interval by a factor.
313  template <typename T>
315  { quantity_t::operator*= (factor); return *this; }
316 
317  /// Scale the interval dividing it by a quotient.
318  template <typename T>
320  { quantity_t::operator/= (factor); return *this; }
321 
322  /// Returns an interval with same value.
323  constexpr interval_t operator+() const { return interval_t(quantity()); }
324 
325  /// Returns an interval with same value but the sign flipped.
326  constexpr interval_t operator-() const { return interval_t(-quantity()); }
327 
328  /// Returns an interval with the absolute value of this one.
329  constexpr interval_t abs() const { return interval_t(quantity().abs()); }
330 
331  /// @}
332  // -- END Asymmetric arithmetic operations -------------------------------
333 
334 
335  // -- BEGIN Comparisons --------------------------------------------------
336  /**
337  * @name Comparisons.
338  *
339  * Comparisons with plain numbers are managed by implicit conversion.
340  * More care is needed for quantities.
341  * Comparisons between two quantity instances `a` and `b` work this way:
342  * * if `a` and `b` do not have the same unit, they are _not_ comparable
343  * * if `a` and `b` have the same unit, one is converted to the other and
344  * the comparison is performed there
345  * * if `a` and `b` have the same scaled unit, their values are compared
346  * directly
347  *
348  * Value storage types are compared according to C++ rules.
349  *
350  */
351  /// @{
352 
353  template <typename OQ, typename OC>
354  constexpr enable_if_compatible_t<Interval<OQ, OC>, bool>
356  { return quantity_t::operator==(other.quantity()); }
357 
358  template <typename OQ, typename OC>
359  constexpr enable_if_compatible_t<Interval<OQ, OC>, bool>
361  { return quantity_t::operator!=(other.quantity()); }
362 
363  template <typename OQ, typename OC>
364  constexpr enable_if_compatible_t<Interval<OQ, OC>, bool>
366  { return quantity_t::operator>=(other.quantity()); }
367 
368  template <typename OQ, typename OC>
369  constexpr enable_if_compatible_t<Interval<OQ, OC>, bool>
371  { return quantity_t::operator>(other.quantity()); }
372 
373  template <typename OQ, typename OC>
374  constexpr enable_if_compatible_t<Interval<OQ, OC>, bool>
375  operator<=(Interval<OQ, OC> const other) const
376  { return quantity_t::operator<=(other.quantity()); }
377 
378  template <typename OQ, typename OC>
379  constexpr enable_if_compatible_t<Interval<OQ, OC>, bool>
380  operator<(Interval<OQ, OC> const other) const
381  { return quantity_t::operator<(other.quantity()); }
382 
383 
384  /// @}
385  // -- END Asymmetric arithmetic operations -------------------------------
386 
387  /// Convert this interval into the specified one.
388  template <typename IV>
389  constexpr IV convertInto() const { return IV(*this); }
390 
391  /**
392  * @brief Returns a new interval initialized with the specified value.
393  * @tparam U type to initialize the quantity with
394  * @param value the value to initialize the interval with
395  * @return a new `Interval` object initialized with `value`
396  *
397  * The `value` is cast into `value_t` via `static_cast()`.
398  */
399  template <typename U>
401  { return interval_t{ static_cast<value_t>(value) }; }
402 
403 
404  }; // struct Interval
405 
406  template <typename... Args>
407  std::ostream& operator<< (std::ostream& out, Interval<Args...> const iv)
408  { return out << iv.quantity(); }
409 
410 
411  // -- BEGIN Comparison operations ------------------------------------------
412  /**
413  * @name Comparison operations on `Interval`
414  *
415  * These operations, as well as the ones implemented as member functions,
416  * are provided for convenience.
417  *
418  * Here the symmetric operations are defined, where different operands can
419  * be swapped.
420  *
421  */
422  /// @{
423 
424  template <typename Q, typename Cat, typename... Args>
425  constexpr bool operator==
426  (Interval<Q, Cat> const a, Quantity<Args...> const b) noexcept
427  { return a.quantity() == b; }
428 
429  template <typename Q, typename Cat, typename... Args>
430  constexpr bool operator==
431  (Quantity<Args...> const a, Interval<Q, Cat> const b) noexcept
432  { return b == a; }
433 
434  template <typename Q, typename Cat, typename... Args>
435  constexpr bool operator!=
436  (Interval<Q, Cat> const a, Quantity<Args...> const b) noexcept
437  { return a.quantity() != b; }
438 
439  template <typename Q, typename Cat, typename... Args>
440  constexpr bool operator!=
441  (Quantity<Args...> const a, Interval<Q, Cat> const b) noexcept
442  { return b != a; }
443 
444  template <typename Q, typename Cat, typename... Args>
445  constexpr bool operator<=
446  (Interval<Q, Cat> const a, Quantity<Args...> const b) noexcept
447  { return a.quantity() <= b; }
448 
449  template <typename Q, typename Cat, typename... Args>
450  constexpr bool operator<=
451  (Quantity<Args...> const a, Interval<Q, Cat> const b) noexcept
452  { return b >= a; }
453 
454  template <typename Q, typename Cat, typename... Args>
455  constexpr bool operator<
456  (Interval<Q, Cat> const a, Quantity<Args...> const b) noexcept
457  { return a.quantity() < b; }
458 
459  template <typename Q, typename Cat, typename... Args>
460  constexpr bool operator<
461  (Quantity<Args...> const a, Interval<Q, Cat> const b) noexcept
462  { return b > a; }
463 
464  template <typename Q, typename Cat, typename... Args>
465  constexpr bool operator>=
466  (Interval<Q, Cat> const a, Quantity<Args...> const b) noexcept
467  { return a.quantity() >= b; }
468 
469  template <typename Q, typename Cat, typename... Args>
470  constexpr bool operator>=
471  (Quantity<Args...> const a, Interval<Q, Cat> const b) noexcept
472  { return b <= a; }
473 
474  template <typename Q, typename Cat, typename... Args>
475  constexpr bool operator>
476  (Interval<Q, Cat> const a, Quantity<Args...> const b) noexcept
477  { return a.quantity() > b; }
478 
479  template <typename Q, typename Cat, typename... Args>
480  constexpr bool operator>
481  (Quantity<Args...> const a, Interval<Q, Cat> const b) noexcept
482  { return b < a; }
483 
484  /// @}
485  // -- END Comparison operations --------------------------------------------
486 
487 
488  // -- BEGIN Arithmetic operations ------------------------------------------
489  /**
490  * @name Arithmetic operations on `Quantity`
491  *
492  * These operations, as well as the ones implemented as member functions,
493  * are provided for convenience.
494  *
495  * Here the symmetric operations are defined, where different operands can
496  * be swapped.
497  *
498  */
499  /// @{
500 
501  //@{
502  /// Multiplication with a scalar.
503  template <typename Q, typename Cat, typename T>
504  constexpr std::enable_if_t<std::is_arithmetic_v<T>, Interval<Q, Cat>>
505  operator* (Interval<Q, Cat> const iv, T const factor)
506  { return Interval<Q, Cat>{ iv.quantity() * factor }; }
507  template <typename Q, typename Cat, typename T>
508  constexpr std::enable_if_t<std::is_arithmetic_v<T>, Interval<Q, Cat>>
509  operator* (T const factor, Interval<Q, Cat> const iv) { return iv * factor; }
510  //@}
511 
512  /// Multiplication between quantities is forbidden.
513  template <typename AQ, typename AC, typename BQ, typename BC>
514  constexpr auto operator* (Interval<AQ, AC> const, Interval<BQ, BC> const)
515 // -> decltype(std::declval<AQ>() * std::declval<AQ>())
516  = delete;
517 
518  // Division by a scalar.
519  template <typename Q, typename Cat, typename T>
520  constexpr std::enable_if_t<std::is_arithmetic_v<T>, Interval<Q, Cat>>
521  operator/ (Interval<Q, Cat> const iv, T const quot)
522  { return Interval<Q, Cat>{ iv.quantity() / quot }; }
523 
524  /// @}
525  // -- END Arithmetic operations --------------------------------------------
526 
527 
528  // -------------------------------------------------------------------------
529  /// Type of an interval like `IV`, but with a different unit scale `R`.
530  template <typename IV, typename R, typename T = typename IV::value_t>
531  using rescale_interval = Interval
532  <rescale<typename IV::quantity_t, R, T>, typename IV::category_t>;
533 
534 
535  // -------------------------------------------------------------------------
536  template <typename Q, typename Cat>
538  { return util::to_string(iv.quantity()); }
539 
540 
541  // -------------------------------------------------------------------------
542 
543  /** ************************************************************************
544  * @brief A quantity point.
545  * @tparam Q quantity the interval is based on
546  * @tparam Cat category this point belongs to (`NoCategory` by default)
547  *
548  * A point shares most of the concepts of a `Quantity`, but it interacts
549  * only with other points rather than with bare `Quantity` objects,
550  * with the exception of construction.
551  * In this sense, the relation between `Point` and `Quantity` is similar
552  * to the one between `Quantity` and its base type (`Quantity::value_t`).
553  *
554  * In addition, `Point` has some interaction with the corresponding
555  * `Interval`: an interval can be seen as the distance, or difference,
556  * between two quantity points.
557  *
558  * The point belongs to a category, which is just a tag that prevents
559  * different points from being mixed up. Note that intervals do not have a
560  * category.
561  */
562  template <
563  typename Q, typename Cat = NoCategory,
564  typename IV = Interval<Q, Cat>
565  >
566  struct Point: private Q, public details::WithCategory<Cat> {
567 
569 
570  /// Traits of the category.
572 
573  template <typename OC, typename Type = void>
575  = std::enable_if_t
576  <category_base_t::template category_compatible_with<OC>(), Type>
577  ;
578 
579 
580  public:
581 
582  using point_t = Point<Q, Cat, IV>; ///< This type.
583 
584 
585  // --- BEGIN -- Types from the base quantity -----------------------------
586  /// @name Types from the base quantity
587  /// @{
588 
589  using quantity_t = Q; ///< Quantity the interval is based on.
590 
591  /// The category this point belongs to.
593 
594  /// The interval type corresponding to the unit of this point.
595  using interval_t = IV;
596 
597  /// A quantity in the same unit, but possibly a different scale.
598  template <typename R>
600 
601  /// Type of the stored value.
602  using value_t = typename quantity_t::value_t;
603 
604  /// Description of the scaled unit.
605  using unit_t = typename quantity_t::unit_t;
606 
607  /// Description of the unscaled unit.
608  using baseunit_t = typename quantity_t::baseunit_t;
609 
610  /// A point based on a different quantity but with the same category.
611  template <typename OQ, typename OI>
613 
614  /// @}
615  // --- END -- Types from the base quantity -------------------------------
616 
617  /// Constructor: value is left uninitialized.
618  // NOTE: this is not `constexpr` because using it in a constexpr would
619  // yield an uninitialized constant
620  explicit Point() = default;
621 
622  /// Constructor: takes a value in the intended representation.
623  explicit constexpr Point(value_t v): Point(quantity_t{ v }) {}
624 
625  /**
626  * @brief Constructor: converts from a quantity.
627  * @tparam OQ type of the quantity
628  * @param q quantity to be converted from
629  *
630  * The quantity is required to be in the same unit as this point
631  * (unit scale may differ).
632  * The value in `q` is converted from its native scale into the one of
633  * this point.
634  */
635  template <typename... Args>
636  constexpr Point(Quantity<Args...> const q)
637  : quantity_t(quantity_t{ q }) {}
638 
639  /**
640  * @brief Constructor: converts from another point.
641  * @tparam PT type of the other point
642  * @param p point to be converted from
643  *
644  * Points are required to be in the same unit (unit scale may differ).
645  * The value in `p` is converted from its native scale into the one of
646  * this point.
647  */
648  template
649  <typename PT, typename std::enable_if_t<is_point_v<PT>>* = nullptr>
650  constexpr Point(PT const p): Point(quantity_t{ p.quantity() }) {}
651 
652  /// Returns the value of the interval as a quantity.
653  constexpr quantity_t const& quantity() const { return *this; }
654 
655  /// Returns the value of the interval as plain value.
656  using quantity_t::value;
657 
658  /// Conversion to the base quantity.
659  explicit constexpr operator value_t() const
660  { return value(); }
661 
662 
663 
664  // -- BEGIN Asymmetric arithmetic operations -----------------------------
665  /**
666  * @name Asymmetric operand arithmetic operations
667  *
668  * These arithmetic operations take care of preserving the point unit
669  * through them.
670  * Not all possible (or reasonable) operations are supported yet.
671  * Some operations that may be symmetric (like addition of interval)
672  * are implemented as free functions rather than methods.
673  *
674  * @note These operations are essentially provided by convenience. There
675  * are many cases (corner and not) where the implicit conversion
676  * to the base type kicks in. This implementation does not aim to
677  * _prevent_ that from happening, but requests are welcome to add
678  * features to _allow_ that not to happen, with some care of the
679  * user.
680  *
681  * @note Differently from `Interval`, the addition and subtraction of
682  * interval to _points_ is not symmetric, i.e. adding an interval
683  * to a point is supported (resulting in another point) but adding
684  * a point to an interval is not. Another difference is that since
685  * the result is unmistakably associated with the one operand of
686  * point type, the result has the same unit and type as that operand
687  * and the other operand, the interval, can be converted from a
688  * different unit scale.
689  */
690  /// @{
691 
692  /// Returns the sum of this point plus an interval (from quantity)
693  /// (note that addition is not symmetric).
694  template <typename R>
695  constexpr point_t operator+ (scaled_quantity_t<R> const delta) const
696  { return point_t(quantity().plus(delta)); }
697 
698  /// Returns the sum of this point plus an interval
699  /// (note that addition is not symmetric).
700  template <typename OQ, typename OC>
702  operator+ (Interval<OQ, OC> const delta) const
703  { return operator+ (delta.quantity()); }
704 
705  /// Returns the value of this point after subtraction of an interval.
706  template <typename R>
707  constexpr point_t operator- (scaled_quantity_t<R> const delta) const
708  { return point_t(quantity().minus(delta)); }
709 
710  /// Returns the value of this point after subtraction of an interval.
711  template <typename OQ, typename OC>
712  constexpr enable_if_compatible_t<Interval<OQ, OC>, point_t>
713  operator- (Interval<OQ, OC> const delta) const
714  { return operator- (delta.quantity()); }
715 
716  /// Add a quantity (possibly converted) to this one.
717  template <typename R>
719  { quantity_t::operator+= (other); return *this; }
720 
721  /// Add the `other` interval (possibly converted) to this point.
722  template <typename OQ, typename OC>
723  enable_if_compatible_t<Interval<OQ, OC>, point_t&> operator+=
725  { return operator+= (other.quantity()); }
726 
727  /// Subtract a quantity (possibly converted) from this one.
728  template <typename R>
729  point_t& operator-= (scaled_quantity_t<R> const other)
730  { quantity_t::operator-= (other); return *this; }
731 
732  /// Subtract the `other` interval (possibly converted) from this point.
733  template <typename OQ, typename OC>
734  enable_if_compatible_t<Interval<OQ, OC>, point_t&> operator-=
736  { return operator-= (other.quantity()); }
737 
738  /// Returns a point with same value.
739  constexpr point_t operator+() const { return point_t(quantity()); }
740 
741  /// Returns a parity-changed point.
742  constexpr point_t operator-() const { return point_t(-quantity()); }
743 
744  /// @}
745  // -- END Asymmetric arithmetic operations -------------------------------
746 
747 
748  // -- BEGIN Comparisons --------------------------------------------------
749  /**
750  * @name Comparisons.
751  *
752  * Comparisons with plain numbers are managed by implicit conversion.
753  * More care is needed for quantities.
754  * Comparisons between two point instances `a` and `b` work this way:
755  * * if `a` and `b` belong to different categories, they are _not_
756  * comparable
757  * * if `a` and `b` do not have the same unit, they are _not_ comparable
758  * * if `a` and `b` have the same unit, one is converted to the other and
759  * the comparison is performed there
760  * * if `a` and `b` have the same scaled unit, their values are compared
761  * directly
762  *
763  * Value storage types are compared according to C++ rules.
764  *
765  */
766  /// @{
767 
768  template <typename OQ, typename OI>
770  { return quantity_t::operator==(other.quantity()); }
771 
772  template <typename OQ, typename OI>
773  constexpr enable_if_compatible_t<other_point_t<OQ, OI>, bool>
775  { return quantity_t::operator!=(other.quantity()); }
776 
777  template <typename OQ, typename OI>
778  constexpr enable_if_compatible_t<other_point_t<OQ, OI>, bool>
780  { return quantity_t::operator>=(other.quantity()); }
781 
782  template <typename OQ, typename OI>
783  constexpr enable_if_compatible_t<other_point_t<OQ, OI>, bool>
785  { return quantity_t::operator>(other.quantity()); }
786 
787  template <typename OQ, typename OI>
788  constexpr enable_if_compatible_t<other_point_t<OQ, OI>, bool>
789  operator<=(other_point_t<OQ, OI> const other) const
790  { return quantity_t::operator<=(other.quantity()); }
791 
792  template <typename OQ, typename OI>
793  constexpr enable_if_compatible_t<other_point_t<OQ, OI>, bool>
794  operator<(other_point_t<OQ, OI> const other) const
795  { return quantity_t::operator<(other.quantity()); }
796 
797 
798  /// @}
799  // -- END Asymmetric arithmetic operations -------------------------------
800 
801 
802  // -- BEGIN Access to the scaled unit ------------------------------------
803  /// @name Access to the scaled unit.
804  /// @{
805 
806  using quantity_t::unit;
807  using quantity_t::baseUnit;
808  using quantity_t::unitName;
809  using quantity_t::unitSymbol;
810 
811  /// @}
812  // -- END Access to the scaled unit --------------------------------------
813 
814  /// Convert this interval into the specified one.
815  template <typename PT>
816  constexpr std::enable_if_t<is_point_v<PT>, PT> convertInto() const { return PT(*this); }
817 
818  /**
819  * @brief Returns a new point initialized with the specified value.
820  * @tparam U type to initialize the quantity with
821  * @param value the value to initialize the point with
822  * @return a new `Point` object initialized with `value`
823  *
824  * The `value` is cast into `value_t` via `static_cast()`.
825  */
826  template <typename U>
827  static point_t castFrom(U value)
828  { return point_t{ static_cast<value_t>(value) }; }
829 
830 
831  }; // struct Point
832 
833  template <typename... Args>
834  std::ostream& operator<< (std::ostream& out, Point<Args...> const p)
835  { return out << p.quantity(); }
836 
837 
838  // -- BEGIN Comparison operations ------------------------------------------
839  /**
840  * @name Comparison operations on `Interval`
841  *
842  * These operations, as well as the ones implemented as member functions,
843  * are provided for convenience.
844  *
845  * Here the symmetric operations are defined, where different operands can
846  * be swapped.
847  *
848  */
849  /// @{
850 
851 
852  template <typename Q, typename Cat, typename IV, typename... Args>
853  constexpr bool operator==
854  (Point<Q, Cat, IV> const a, Quantity<Args...> const b) noexcept
855  { return a.quantity() == b; }
856 
857  template <typename Q, typename Cat, typename IV, typename... Args>
858  constexpr bool operator==
859  (Quantity<Args...> const a, Point<Q, Cat, IV> const b) noexcept
860  { return b == a; }
861 
862  template <typename Q, typename Cat, typename IV, typename... Args>
863  constexpr bool operator!=
864  (Point<Q, Cat, IV> const a, Quantity<Args...> const b) noexcept
865  { return a.quantity() != b; }
866 
867  template <typename Q, typename Cat, typename IV, typename... Args>
868  constexpr bool operator!=
869  (Quantity<Args...> const a, Point<Q, Cat, IV> const b) noexcept
870  { return b != a; }
871 
872  template <typename Q, typename Cat, typename IV, typename... Args>
873  constexpr bool operator<=
874  (Point<Q, Cat, IV> const a, Quantity<Args...> const b) noexcept
875  { return a.quantity() <= b; }
876 
877  template <typename Q, typename Cat, typename IV, typename... Args>
878  constexpr bool operator<=
879  (Quantity<Args...> const a, Point<Q, Cat, IV> const b) noexcept
880  { return b >= a; }
881 
882  template <typename Q, typename Cat, typename IV, typename... Args>
883  constexpr bool operator<
884  (Point<Q, Cat, IV> const a, Quantity<Args...> const b) noexcept
885  { return a.quantity() < b; }
886 
887  template <typename Q, typename Cat, typename IV, typename... Args>
888  constexpr bool operator<
889  (Quantity<Args...> const a, Point<Q, Cat, IV> const b) noexcept
890  { return b > a; }
891 
892  template <typename Q, typename Cat, typename IV, typename... Args>
893  constexpr bool operator>=
894  (Point<Q, Cat, IV> const a, Quantity<Args...> const b) noexcept
895  { return a.quantity() >= b; }
896 
897  template <typename Q, typename Cat, typename IV, typename... Args>
898  constexpr bool operator>=
899  (Quantity<Args...> const a, Point<Q, Cat, IV> const b) noexcept
900  { return b <= a; }
901 
902  template <typename Q, typename Cat, typename IV, typename... Args>
903  constexpr bool operator>
904  (Point<Q, Cat, IV> const a, Quantity<Args...> const b) noexcept
905  { return a.quantity() > b; }
906 
907  template <typename Q, typename Cat, typename IV, typename... Args>
908  constexpr bool operator>
909  (Quantity<Args...> const a, Point<Q, Cat, IV> const b) noexcept
910  { return b < a; }
911 
912  /// @}
913  // -- END Comparison operations --------------------------------------------
914 
915  // -- BEGIN Arithmetic operations ------------------------------------------
916  /**
917  * @name Arithmetic operations on `Quantity`
918  *
919  * These operations, as well as the ones implemented as member functions,
920  * are provided for convenience.
921  *
922  * Here the symmetric operations are defined, where different operands can
923  * be swapped.
924  *
925  */
926  /// @{
927 
928  template <typename Q, typename Cat, typename IV, typename OQ, typename OC>
929  constexpr Point<Q, Cat, IV> operator+
930  (Interval<OQ, OC> const delta, Point<Q, Cat, IV> const p)
931  = delete; // use `point + interval`, not `interval + point`
932 
933  template <typename Q, typename Cat, typename IV, typename OQ, typename OC>
934  constexpr Point<Q, Cat, IV> operator-
935  (Interval<OQ, OC> const delta, Point<Q, Cat, IV> const p)
936  = delete; // use `point + interval`, not `interval + point`
937 
938  // two different points but with the same interval type
939  template
940  <typename Q, typename Cat, typename IV, typename OQ, typename OCat>
941  constexpr
942  typename Point<Q, Cat, IV>
943  ::template enable_if_compatible_t<Point<OQ, OCat, IV>, IV>
945  { return IV(a.quantity() - b.quantity()); }
946 
947  /// @}
948  // -- END Arithmetic operations --------------------------------------------
949 
950 
951  // -------------------------------------------------------------------------
952  /// Type of a point like `PT`, but with a different unit scale `R`.
953  template <typename PT, typename R, typename T = typename PT::value_t>
954  using rescale_point
955  = Point<rescale<typename PT::quantity_t, R, T>, typename PT::category_t>;
956 
957 
958  // -------------------------------------------------------------------------
959  template <typename Q, typename Cat, typename IV>
961  { return util::to_string(p.quantity()); }
962 
963  // -------------------------------------------------------------------------
964 
965  } // namespace concepts
966 
967 
968  // ---------------------------------------------------------------------------
970 
971  static std::string name() { return "generic"; }
972 
973  }; // struct NoCategory
974 
975 
976  // ---------------------------------------------------------------------------
977  // @{
978  /**
979  * @brief Returns an interval of the specified type parsed from a string.
980  * @tparam IV the type of quantity interval to be returned
981  * @param s the string to be parsed
982  * @param unitOptional (default: `false`) whether unit is not required in `s`
983  * @return a quantity interval of the specified type parsed from a string
984  * @throw MissingUnit `s` does not contain the required unit
985  * @throw ValueError the numerical value in `s` is not parseable
986  * @throw ExtraCharactersError spurious characters after the numeric value
987  * @see `util::makeQuantity()`
988  *
989  * This function behaves like `util::makeQuantity()`.
990  */
991  template <typename IV>
992  IV makeInterval(std::string_view s, bool unitOptional = false);
993 
994  template <typename IV>
995  IV makeInterval(std::string const& s, bool unitOptional = false);
996 
997  template <typename IV>
998  IV makeInterval(char const* s, bool unitOptional = false);
999 
1000  //@}
1001 
1002 
1003  // @{
1004  /**
1005  * @brief Returns a point of the specified type parsed from a string.
1006  * @tparam PT the type of quantity point to be returned
1007  * @param s the string to be parsed
1008  * @param unitOptional (default: `false`) whether unit is not required in `s`
1009  * @return a quantity point of the specified type parsed from a string
1010  * @throw MissingUnit `s` does not contain the required unit
1011  * @throw ValueError the numerical value in `s` is not parseable
1012  * @throw ExtraCharactersError spurious characters after the numeric value
1013  * @see `util::makeQuantity()`
1014  *
1015  * This function behaves like `util::makeQuantity()`.
1016  */
1017  template <typename PT>
1018  PT makePoint(std::string_view s, bool unitOptional = false);
1019 
1020  template <typename PT>
1021  PT makePoint(std::string const& s, bool unitOptional = false);
1022 
1023  template <typename PT>
1024  PT makePoint(char const* s, bool unitOptional = false);
1025 
1026  //@}
1027 
1028 
1029  // ---------------------------------------------------------------------------
1030 
1031 } // namespace util::quantities
1032 
1033 
1034 //------------------------------------------------------------------------------
1035 //--- template implementation
1036 //------------------------------------------------------------------------------
1038 
1039  //----------------------------------------------------------------------------
1040  template <typename, typename = std::void_t<>>
1041  struct has_category: std::false_type {};
1042 
1043  template <typename Obj>
1044  struct has_category<Obj, std::void_t<typename Obj::category_t>>
1045  : std::true_type
1046  {};
1047 
1048  template <typename Obj>
1049  constexpr bool has_category_v = has_category<Obj>();
1050 
1051  //----------------------------------------------------------------------------
1052  template <typename, typename = std::void_t<>>
1053  struct category_has_name: std::false_type {};
1054 
1055  template <typename Cat>
1056  struct category_has_name<Cat, std::void_t<decltype(Cat::name())>>
1057  : std::true_type {};
1058 
1059  template <typename Cat>
1061 
1062  using category_t = Cat; ///< The categories the traits are about.
1063 
1064  /// Whether the category supports `name()` call.
1065  static constexpr bool has_name = category_has_name<category_t>();
1066 
1067  /// Returns whether the category `OC` is "compatible" with this one.
1068  template <typename OC>
1069  static constexpr bool compatible_with()
1070  { return util::is_any_of_v<OC, NoCategory, category_t>; }
1071 
1072  }; // struct category_traits<>
1073 
1074 
1075  //----------------------------------------------------------------------------
1076  template <typename Cat, typename /* = void */>
1077  struct category_of_type { using type = Cat; };
1078 
1079  template <typename Cat>
1080  struct category_of_type<Cat, std::void_t<typename Cat::category_t>>
1081  { using type = typename Cat::category_t; };
1082 
1083 
1084  //----------------------------------------------------------------------------
1085  template <typename Cat>
1086  struct WithCategory {
1087 
1088  using category_t = Cat; ///< The category of this object.
1089 
1090  /// Traits of this category.
1092 
1093  /// Returns an instance of the category of this object.
1094  static constexpr category_t category();
1095 
1096  // @{
1097  /// Returns whether the type `OC` belongs to `category_t`.
1098  template <typename OC>
1099  static constexpr bool same_category_as();
1100 
1101  template <typename OC>
1102  static constexpr bool same_category_as(OC const&);
1103  // @}
1104 
1105  // @{
1106  /// Returns whether `OC` has a category compatible with this one.
1107  template <typename OC>
1108  static constexpr bool category_compatible_with();
1109 
1110  template <typename OC>
1111  static constexpr bool category_compatible_with(OC const&);
1112  // @}
1113 
1114 
1115  /// Returns whether this category has a name.
1116  static constexpr bool hasCategoryName();
1117 
1118  /// Returns the name of the category of this object.
1119  static std::string categoryName();
1120 
1121  }; // struct WithCategory<>
1122 
1123 
1124  //----------------------------------------------------------------------------
1125  //--- WithCategory
1126  //----------------------------------------------------------------------------
1127  template <typename Cat>
1128  constexpr auto WithCategory<Cat>::category() -> category_t { return {}; }
1129 
1130 
1131  //----------------------------------------------------------------------------
1132  template <typename Cat>
1133  template <typename OC>
1135  return details::has_category_v<OC>
1136  && std::is_same_v<typename OC::category_t, category_t>;
1137  } // WithCategory<>::same_category_as()
1138 
1139  template <typename Cat>
1140  template <typename OC>
1141  constexpr bool WithCategory<Cat>::same_category_as(OC const&)
1142  { return same_category_as<OC>(); }
1143 
1144 
1145  //----------------------------------------------------------------------------
1146  template <typename Cat>
1147  template <typename OC>
1149  { return traits_t::template compatible_with<category_of<OC>>(); }
1150 
1151 
1152  template <typename Cat>
1153  template <typename OC>
1155  { return category_compatible_with<OC>(); }
1156 
1157  //----------------------------------------------------------------------------
1158  template <typename Cat>
1161 
1162 
1163  //----------------------------------------------------------------------------
1164  template <typename Cat>
1166  { return Cat::name(); }
1167 
1168 
1169  //----------------------------------------------------------------------------
1170 
1171 } // namespace util::quantities::concepts::details
1172 
1173 
1174 //------------------------------------------------------------------------------
1175 //--- template implementation
1176 //------------------------------------------------------------------------------
1177 namespace util::quantities::concepts {
1178 
1179  //----------------------------------------------------------------------------
1180  template <typename>
1181  struct is_interval: public std::false_type {};
1182 
1183  template <typename... Args>
1184  struct is_interval<Interval<Args...>>: public std::true_type {};
1185 
1186 
1187  //----------------------------------------------------------------------------
1188  template <typename>
1189  struct is_point: public std::false_type {};
1190 
1191  template <typename... Args>
1192  struct is_point<Point<Args...>>: public std::true_type {};
1193 
1194 
1195  //----------------------------------------------------------------------------
1196 
1197 } // namespace util::quantities::concepts
1198 
1199 
1200 //------------------------------------------------------------------------------
1201 //--- Template implementation
1202 //------------------------------------------------------------------------------
1203 template <typename IV>
1205  (std::string_view s, bool unitOptional /* = false */)
1206 {
1207  using quantity_t = typename IV::quantity_t;
1208  return { util::quantities::makeQuantity<quantity_t>(s, unitOptional) };
1209 } // util::quantities::makeInterval(string_view)
1210 
1211 
1212 //------------------------------------------------------------------------------
1213 template <typename IV>
1215  (std::string const& s, bool unitOptional /* = false */)
1216 {
1217  using quantity_t = typename IV::quantity_t;
1218  return { util::quantities::makeQuantity<quantity_t>(s, unitOptional) };
1219 } // util::quantities::makeInterval(string)
1220 
1221 
1222 //------------------------------------------------------------------------------
1223 template <typename IV>
1225  (char const* s, bool unitOptional /* = false */)
1226 {
1227  using quantity_t = typename IV::quantity_t;
1228  return { util::quantities::makeQuantity<quantity_t>(s, unitOptional) };
1229 } // util::quantities::makeInterval(C-string)
1230 
1231 
1232 //------------------------------------------------------------------------------
1233 template <typename PT>
1235  (std::string_view s, bool unitOptional /* = false */)
1236 {
1237  using quantity_t = typename PT::quantity_t;
1238  return { util::quantities::makeQuantity<quantity_t>(s, unitOptional) };
1239 } // util::quantities::makePoint(string_view)
1240 
1241 
1242 //------------------------------------------------------------------------------
1243 template <typename PT>
1245  (std::string const& s, bool unitOptional /* = false */)
1246 {
1247  using quantity_t = typename PT::quantity_t;
1248  return { util::quantities::makeQuantity<quantity_t>(s, unitOptional) };
1249 } // util::quantities::makePoint(string)
1250 
1251 
1252 //------------------------------------------------------------------------------
1253 template <typename PT>
1255  (char const* s, bool unitOptional /* = false */)
1256 {
1257  using quantity_t = typename PT::quantity_t;
1258  return { util::quantities::makeQuantity<quantity_t>(s, unitOptional) };
1259 } // util::quantities::makePoint(C-string)
1260 
1261 
1262 //------------------------------------------------------------------------------
1263 //--- Standard library extensions
1264 //------------------------------------------------------------------------------
1265 namespace std {
1266 
1267  // ---------------------------------------------------------------------------
1268  /// Hash function of a interval or point is delegated to its quantity.
1269  template <typename Q, typename Cat>
1270  struct hash<util::quantities::concepts::Interval<Q, Cat>> {
1271  constexpr auto operator()
1273  noexcept(noexcept(std::hash(key.quantity())))
1274  { return std::hash(key.quantity()); }
1275  }; // hash<Interval>
1276 
1277  template <typename Q, typename Cat, typename IV>
1278  struct hash<util::quantities::concepts::Point<Q, Cat, IV>> {
1279  constexpr auto operator()
1281  noexcept(noexcept(std::hash(key.quantity())))
1282  { return std::hash(key.quantity()); }
1283  }; // hash<Interval>
1284 
1285 
1286  // ---------------------------------------------------------------------------
1287  /// Limits of a interval or point are the same as the underlying quantity and
1288  /// base type.
1289  template <typename Q, typename Cat>
1290  class numeric_limits<util::quantities::concepts::Interval<Q, Cat>>
1292  <util::quantities::concepts::Interval<Q, Cat>>
1293  {};
1294 
1295  template <typename Q, typename Cat>
1296  class numeric_limits<util::quantities::concepts::Interval<Q, Cat> const>
1298  <util::quantities::concepts::Interval<Q, Cat> const>
1299  {};
1300 
1301  template <typename Q, typename Cat>
1302  class numeric_limits<util::quantities::concepts::Interval<Q, Cat> volatile>
1304  <util::quantities::concepts::Interval<Q, Cat> volatile>
1305  {};
1306 
1307  template <typename Q, typename Cat>
1308  class numeric_limits
1309  <util::quantities::concepts::Interval<Q, Cat> const volatile>
1311  <util::quantities::concepts::Interval<Q, Cat> const volatile>
1312  {};
1313 
1314 
1315  template <typename Q, typename Cat, typename IV>
1316  class numeric_limits<util::quantities::concepts::Point<Q, Cat, IV>>
1318  <util::quantities::concepts::Point<Q, Cat, IV>>
1319  {};
1320 
1321  template <typename Q, typename Cat, typename IV>
1322  class numeric_limits<util::quantities::concepts::Point<Q, Cat, IV> const>
1324  <util::quantities::concepts::Point<Q, Cat, IV> const>
1325  {};
1326 
1327  template <typename Q, typename Cat, typename IV>
1328  class numeric_limits<util::quantities::concepts::Point<Q, Cat, IV> volatile>
1330  <util::quantities::concepts::Point<Q, Cat, IV> volatile>
1331  {};
1332 
1333  template <typename Q, typename Cat, typename IV>
1334  class numeric_limits
1335  <util::quantities::concepts::Point<Q, Cat, IV> const volatile>
1337  <util::quantities::concepts::Point<Q, Cat, IV> const volatile>
1338  {};
1339 
1340 
1341  // ---------------------------------------------------------------------------
1342 
1343 } // namespace std
1344 
1345 
1346 //------------------------------------------------------------------------------
1347 
1348 #endif // LARDATAALG_UTILITIES_INTERVALS_H
static QCString name
Definition: declinfo.cpp:673
constexpr interval_t operator+() const
Returns an interval with same value.
Definition: intervals.h:323
typename category_base_t::category_t category_t
Quantity the interval is based on.
Definition: intervals.h:139
Namespace for general, non-LArSoft-specific utilities.
constexpr enable_if_compatible_t< Interval< OQ, OC >, bool > operator==(Interval< OQ, OC > const other) const
Definition: intervals.h:355
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:521
std::enable_if_t< category_base_t::template category_compatible_with< OC >(), Type > enable_if_compatible_t
Definition: intervals.h:125
constexpr Interval(IV iv)
Constructor: converts from another interval.
Definition: intervals.h:195
static constexpr bool sameBaseUnitAs()
Returns whether objects of type OU have the same base unit as this.
Definition: intervals.h:229
int Type
Definition: 018_def.c:12
constexpr interval_t operator-(interval_t const other) const
Definition: intervals.h:281
DoubleProduct & operator+=(DoubleProduct &left, DoubleProduct const &right)
Definition: ToyProducts.h:103
Q quantity_t
Quantity the interval is based on.
Definition: intervals.h:589
std::string string
Definition: nybbler.cc:12
constexpr Interval(value_t v)
Constructor: takes a value in the intended representation.
Definition: intervals.h:167
interval_t & operator*=(T factor)
Scale this interval by a factor.
Definition: intervals.h:314
static interval_t castFrom(U value)
Returns a new interval initialized with the specified value.
Definition: intervals.h:400
typename T::interval_t interval_of
Type of interval contained in specified type T.
Definition: intervals.h:94
constexpr Point< Q, Cat, IV > operator+(Interval< OQ, OC > const delta, Point< Q, Cat, IV > const p)=delete
interval_t & operator/=(T factor)
Scale the interval dividing it by a quotient.
Definition: intervals.h:319
constexpr enable_if_compatible_t< other_point_t< OQ, OI >, bool > operator>=(other_point_t< OQ, OI > const other) const
Definition: intervals.h:779
PT makePoint(std::string_view s, bool unitOptional=false)
Returns a point of the specified type parsed from a string.
Definition: intervals.h:1235
Trait: true_type if IV is a Interval specialization.
Definition: intervals.h:63
STL namespace.
typename category_of_type< Cat >::type category_of
Definition: intervals.h:36
constexpr enable_if_compatible_t< Interval< OQ, OC >, bool > operator>=(Interval< OQ, OC > const other) const
Definition: intervals.h:365
static constexpr category_t category()
Returns an instance of the category of this object.
Definition: intervals.h:1128
std::string to_string(Interval< Q, Cat > const &iv)
Definition: intervals.h:537
typename quantity_t::baseunit_t baseunit_t
Description of the unscaled unit.
Definition: intervals.h:608
constexpr bool operator<(Quantity< Args... > const a, Point< Q, Cat, IV > const b) noexcept
Definition: intervals.h:889
constexpr quantity_t const & quantity() const
Returns the value of the interval as a quantity.
Definition: intervals.h:653
quantity
Definition: statistics_t.cc:15
typename category_base_t::traits_t traits_t
Traits of the category.
Definition: intervals.h:119
typename category_base_t::category_t category_t
The category this point belongs to.
Definition: intervals.h:592
constexpr Interval(Quantity< Args... > const &q)
Constructor: converts from a quantity.
Definition: intervals.h:180
constexpr bool is_interval_v
Trait: true if IV is a Interval specialization.
Definition: intervals.h:67
An object belonging to a category Cat.
Definition: intervals.h:42
Infrastructure for the quantities library.
Definition: intervals.h:26
static std::string categoryName()
Returns the name of the category of this object.
Definition: intervals.h:1165
static point_t castFrom(U value)
Returns a new point initialized with the specified value.
Definition: intervals.h:827
static constexpr bool sameUnitAs()
Returns whether objects of type OU have same unit and scale as this.
Definition: intervals.h:234
static constexpr bool same_category_as()
Returns whether the type OC belongs to category_t.
Definition: intervals.h:1134
def key(type, name=None)
Definition: graph.py:13
decltype(auto) constexpr to_string(T &&obj)
ADL-aware version of std::to_string.
static constexpr bool category_compatible_with()
Returns whether OC has a category compatible with this one.
Definition: intervals.h:1148
constexpr point_t operator-() const
Returns a parity-changed point.
Definition: intervals.h:742
std::tuple< double, double, const reco::ClusterHit3D * > Point
Definitions used by the VoronoiDiagram algorithm.
Definition: DCEL.h:44
constexpr bool operator==(Quantity< Args... > const a, Point< Q, Cat, IV > const b) noexcept
Definition: intervals.h:859
const double a
A value measured in the specified unit.
Definition: quantities.h:566
constexpr enable_if_compatible_t< other_point_t< OQ, OI >, bool > operator>(other_point_t< OQ, OI > const other) const
Definition: intervals.h:784
std::enable_if_t< category_base_t::template category_compatible_with< OC >(), Type > enable_if_compatible_t
Definition: intervals.h:577
p
Definition: test.py:223
typename quantity_t::baseunit_t baseunit_t
Description of the unscaled unit.
Definition: intervals.h:152
constexpr interval_t operator+(interval_t const other) const
Definition: intervals.h:276
constexpr quantity_t const & quantity() const
Returns the value of the interval as a quantity.
Definition: intervals.h:198
Cat category_t
The categories the traits are about.
Definition: intervals.h:1062
constexpr IV convertInto() const
Convert this interval into the specified one.
Definition: intervals.h:389
constexpr bool operator!=(Quantity< Args... > const a, Point< Q, Cat, IV > const b) noexcept
Definition: intervals.h:869
constexpr bool operator<=(Quantity< Args... > const a, Point< Q, Cat, IV > const b) noexcept
Definition: intervals.h:879
An interval (duration, length, distance) between two quantity points.
Definition: intervals.h:114
struct point_s point_t
Definition: DBScan3DAlg.h:55
IV interval_t
The interval type corresponding to the unit of this point.
Definition: intervals.h:595
constexpr std::enable_if_t< is_point_v< PT >, PT > convertInto() const
Convert this interval into the specified one.
Definition: intervals.h:816
static constexpr bool compatible_with()
Returns whether the category OC is "compatible" with this one.
Definition: intervals.h:1069
constexpr bool operator>(Quantity< Args... > const a, Point< Q, Cat, IV > const b) noexcept
Definition: intervals.h:909
Trait: true_type if PT is a Point specialization.
Definition: intervals.h:73
constexpr Point(Quantity< Args... > const q)
Constructor: converts from a quantity.
Definition: intervals.h:636
Numeric variable proxies with embedded unit of measurement.
constexpr Point(PT const p)
Constructor: converts from another point.
Definition: intervals.h:650
static std::string name()
Definition: intervals.h:971
constexpr bool operator>=(Quantity< Args... > const a, Point< Q, Cat, IV > const b) noexcept
Definition: intervals.h:899
constexpr enable_if_compatible_t< other_point_t< OQ, OI >, bool > operator!=(other_point_t< OQ, OI > const other) const
Definition: intervals.h:774
Cat category_t
The category of this object.
Definition: intervals.h:1088
std::ostream & operator<<(std::ostream &out, Interval< Args... > const iv)
Definition: intervals.h:407
constexpr Point< Q, Cat, IV > operator-(Interval< OQ, OC > const delta, Point< Q, Cat, IV > const p)=delete
An non-mandatory base class for interval and point categories.
Definition: intervals.h:52
constexpr enable_if_compatible_t< Interval< OQ, OC >, bool > operator>(Interval< OQ, OC > const other) const
Definition: intervals.h:370
constexpr interval_t abs() const
Returns an interval with the absolute value of this one.
Definition: intervals.h:329
typename quantity_t::value_t value_t
Type of the stored value.
Definition: intervals.h:602
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:505
static bool * b
Definition: config.cpp:1043
typename quantity_t::value_t value_t
Type of the stored value.
Definition: intervals.h:146
constexpr interval_t operator-() const
Returns an interval with same value but the sign flipped.
Definition: intervals.h:326
Limits of a quantity are the same as the underlying type.
Definition: quantities.h:329
IV makeInterval(std::string_view s, bool unitOptional=false)
Returns an interval of the specified type parsed from a string.
Definition: intervals.h:1205
constexpr enable_if_compatible_t< other_point_t< OQ, OI >, bool > operator==(other_point_t< OQ, OI > const other) const
Definition: intervals.h:769
constexpr bool is_interval_or_point_v
Trait: true if PT is a specialization of Interval or Point.
Definition: intervals.h:87
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:571
constexpr point_t operator+() const
Returns a point with same value.
Definition: intervals.h:739
constexpr bool is_point_v
Trait: true if PT is a Point specialization.
Definition: intervals.h:77
static QCString * s
Definition: config.cpp:1042
constexpr Point(value_t v)
Constructor: takes a value in the intended representation.
Definition: intervals.h:623
typename quantity_t::unit_t unit_t
Description of the scaled unit.
Definition: intervals.h:605
static constexpr bool hasCategoryName()
Returns whether this category has a name.
Definition: intervals.h:1159
constexpr enable_if_compatible_t< Interval< OQ, OC >, bool > operator!=(Interval< OQ, OC > const other) const
Definition: intervals.h:360
typename quantity_t::unit_t unit_t
Description of the scaled unit.
Definition: intervals.h:149
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:83