Belle II Software  release-08-01-10
ESign.h
1 /**************************************************************************
2  * basf2 (Belle II Analysis Software Framework) *
3  * Author: The Belle II Collaboration *
4  * *
5  * See git log for contributors and copyright holders. *
6  * This file is licensed under LGPL-3.0, see LICENSE.md. *
7  **************************************************************************/
8 #pragma once
9 
10 #include <algorithm>
11 #include <cstdlib> // for abs
12 #include <cmath> // for isnan
13 #include <climits> // for SHRT_MIN
14 
15 namespace Belle2 {
21  namespace TrackFindingCDC {
22 
24  namespace ESignUtil {
25 
27  enum ESign : signed short {
29  c_Plus = 1,
30 
32  c_Minus = -1,
33 
35  c_Zero = 0,
36 
38  c_Invalid = SHRT_MIN,
39  };
40 
42  inline ESign opposite(ESign s)
43  { return static_cast<ESign>(-s); }
44 
46  inline bool isValid(ESign s)
47  { return std::abs(s) <= 1; }
48 
57  static inline ESign common(ESign n1, ESign n2)
58  {
59  return ((not isValid(n1) and not isValid(n2)) ?
60  ESign::c_Invalid :
61  static_cast<ESign>((not(n1 <= 0) and not(n2 <= 0)) - (not(n1 >= 0) and not(n2 >= 0))));
62  }
63 
72  static inline ESign common(float n1, float n2)
73  {
74  return ((std::isnan(n1) and std::isnan(n2)) ?
75  ESign::c_Invalid :
76  static_cast<ESign>((not(n1 <= 0) and not(n2 <= 0)) - (not(n1 >= 0) and not(n2 >= 0))));
77  }
78 
87  static inline ESign common(float n1, float n2, float n3, float n4)
88  {
89  return ((std::isnan(n1) and std::isnan(n2) and std::isnan(n3) and std::isnan(n4)) ?
90  ESign::c_Invalid :
91  static_cast<ESign>((not(n1 <= 0) and not(n2 <= 0) and not(n3 <= 0) and not(n4 <= 0)) -
92  (not(n1 >= 0) and not(n2 >= 0) and not(n3 >= 0) and not(n4 >= 0))));
93  }
94 
103  template<class FloatRange>
104  static inline ESign common(const FloatRange& as)
105  {
106  bool allNaN = std::all_of(as.begin(), as.end(), [](float a) { return std::isnan(a); });
107  if (allNaN) {
108  return ESign::c_Invalid;
109  } else {
110  return static_cast<ESign>(std::all_of(as.begin(), as.end(), [](float a) { return not(a <= 0); }) -
111  std::all_of(as.begin(), as.end(), [](float a) { return not(a >= 0); }));
112  }
113  }
114 
115  };
116 
118  using ESign = ESignUtil::ESign;
119 
126  inline ESign sign(double x)
127  {
128  return std::isnan(x) ? ESign::c_Invalid : (std::signbit(x) ? ESign::c_Minus : ESign::c_Plus);
129  }
130 
132  inline ESign sign(int x)
133  {
134  return static_cast<ESign>((x > 0) - (x < 0));
135  }
136 
138  template<class Enum, Enum invalid = Enum::c_Invalid>
139  inline ESign sign(Enum x)
140  {
141  if (x == Enum::c_Invalid) return ESign::c_Invalid;
142  return sign(static_cast<int>(x));
143  }
144  }
145 
147 }
ESign
Enumeration for the distinct sign values of floating point variables.
Definition: ESign.h:27
@ c_Invalid
Constant for invalid sign, e.g. the sign of NAN.
Definition: ESign.h:38
@ c_Zero
Constant for undefined sign.
Definition: ESign.h:35
@ c_Minus
Constant for minus sign.
Definition: ESign.h:32
@ c_Plus
Constant for plus sign.
Definition: ESign.h:29
ESign opposite(ESign s)
Return the opposite sign. Leaves ESign::c_Invalid the same.
Definition: ESign.h:42
bool isValid(ESign s)
Returns true if sign is ESign::c_Plus, ESign::c_Minus or ESign::c_Zero.
Definition: ESign.h:46
static ESign common(ESign n1, ESign n2)
Check if two values have a common sign.
Definition: ESign.h:57
Abstract base class for different kinds of events.