frequency.h
Go to the documentation of this file.
1 /**
2  * @file lardataalg/Utilities/quantities/frequency.h
3  * @brief Dimensioned variables representing frequency quantities.
4  * @author Gianluca Petrillo (petrillo@slac.stanford.edu)
5  * @date October 30, 2018
6  * @see lardataalg/Utilities/quantities.h,
7  * lardataalg/Utilities/quantities/spacetime.h
8  *
9  * Set of quantities related to frequency (inverse of time). Currently,
10  * quantities are defined based on the following units:
11  * * hertz (Hz, kHz, MHz, GHz)
12  *
13  * Also, special operations with units from`util::quantities::unit::Second` are
14  * supported:
15  * * _t_ x _f_ = _s_
16  * * _s_ / _t_ = _f_
17  * * _s_ / _f_ = _t_
18  * where _t_ is a time, _f_ a frequency and _s_ a pure number.
19  *
20  * This is a header-only library.
21  *
22  */
23 
24 #ifndef LARDATAALG_UTILITIES_QUANTITIES_FREQUENCY_H
25 #define LARDATAALG_UTILITIES_QUANTITIES_FREQUENCY_H
26 
27 // LArSoft libraries
28 #include "lardataalg/Utilities/quantities/spacetime.h" // ...::units::Second
30 
31 
32 // C/C++ standard libraries
33 #include <string_view>
34 #include <ratio>
35 
36 
37 //------------------------------------------------------------------------------
38 namespace util::quantities {
39 
40  namespace units {
41 
42  using namespace std::string_view_literals; // for operator""sv()
43 
44  struct Hertz: public concepts::UnitBase {
45  static constexpr auto symbol = "Hz"sv;
46  static constexpr auto name = "hertz"sv;
47  };
48 
49  } // namespace units
50 
51 
52  // -- BEGIN Frequency --------------------------------------------------------
53  /**
54  * @name Frequency quantities
55  *
56  * These frequency quantities are tied to `util::quantities::units::Hertz`.
57  * A few options are provided:
58  *
59  * * most general template, `scaled_hertz`, allowing to choose both the scale
60  * of the unit (e.g. `std::kilo` for kilohertz) and the type of the
61  * numerical representation
62  * * generic template (e.g. `hertz_as`), allowing to choose which numerical
63  * representation to use
64  * * double precision (e.g. `hertz`), ready for use
65  *
66  */
67  /// @{
68 
69  /// The most generic `units::Hertz`-based quantity.
70  template <typename R, typename T = double>
72 
73  //
74  // hertz
75  //
76  /// Type of frequency stored in hertz.
77  template <typename T = double>
79 
80  /// Type of frequency stored in hertz, in double precision.
81  using hertz = hertz_as<>;
82 
83  //
84  // kilohertz
85  //
86  /// Type of frequency stored in kilohertz.
87  template <typename T = double>
89 
90  /// Type of frequency stored in kilohertz, in double precision.
92 
93  //
94  // megahertz
95  //
96  /// Type of frequency stored in megahertz.
97  template <typename T = double>
99 
100  /// Type of frequency stored in megahertz, in double precision.
102 
103  //
104  // gigahertz
105  //
106  /// Type of frequency stored in gigahertz.
107  template <typename T = double>
109 
110  /// Type of frequency stored in gigahertz, in double precision.
112 
113 
114  /**
115  * @brief Literal constants for frequency quantities.
116  *
117  * These functions allow a simplified syntax for specifying a frequency
118  * quantity. In order to use these, their namespace must be used:
119  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
120  * using namespace util::quantities::frequency_literals;
121  *
122  * // definition of `util::quantities::hertz` constant:
123  * constexpr auto f_Hz = 12_Hz;
124  *
125  * // assignment (likely to a quantity) of `util::quantities::megahertz{50.0}`
126  * f_Hz = 50_MHz;
127  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
128  *
129  */
130  namespace frequency_literals {
131 
132  // @{
133  /// Literal hertz value.
134  constexpr hertz operator""_Hz (long double v)
135  { return hertz{ static_cast<double>(v) }; }
136  constexpr hertz operator""_Hz (unsigned long long int v)
137  { return hertz{ static_cast<double>(v) }; }
138  // @}
139 
140  // @{
141  /// Literal kilohertz value.
142  constexpr kilohertz operator""_kHz (long double v)
143  { return kilohertz{ static_cast<double>(v) }; }
144  constexpr kilohertz operator""_kHz (unsigned long long int v)
145  { return kilohertz{ static_cast<double>(v) }; }
146  // @}
147 
148  // @{
149  /// Literal megahertz value.
150  constexpr megahertz operator""_MHz (long double v)
151  { return megahertz{ static_cast<double>(v) }; }
152  constexpr megahertz operator""_MHz (unsigned long long int v)
153  { return megahertz{ static_cast<double>(v) }; }
154  // @}
155 
156  // @{
157  /// Literal gigahertz value.
158  constexpr gigahertz operator""_GHz (long double v)
159  { return gigahertz{ static_cast<double>(v) }; }
160  constexpr gigahertz operator""_GHz (unsigned long long int v)
161  { return gigahertz{ static_cast<double>(v) }; }
162  // @}
163 
164  } // namespace frequency_literals
165 
166 
167  /// @}
168  // -- END Frequency ----------------------------------------------------------
169 
170 
171  // -- BEGIN Special operations between Second and Hertz units ----------------
172  /**
173  * @name Special operations between Second and Hertz units.
174  *
175  * The following operations are supported:
176  * * _t_ x _f_ = _s_
177  * * _s_ / _t_ = _f_ // TODO
178  * * _s_ / _f_ = _t_ // TODO
179  * where _t_ is a time, _f_ a frequency and _s_ a pure number.
180  *
181  */
182  /// @{
183 
184  namespace concepts {
185  //@{
186  /**
187  * @brief Returns the product (as scalar) of a time and a frequency.
188  * @tparam TR type of time unit scale (e.g. `std::micro`)
189  * @tparam TT type of time value representation
190  * @tparam FR type of frequency unit scale (e.g. `std::mega`)
191  * @tparam FT type of frequency value representation
192  * @param t time quantity, based on `util::quantities::units::Second`
193  * @param f frequency quantity, based on `util::quantities::units::Hertz`
194  * @return the product of the two (using the C++ type of `TT * FT`)
195  *
196  */
197  template <typename TR, typename TT, typename FR, typename FT>
198  constexpr auto operator*(
199  scaled_quantity<util::quantities::units::Second, TR, TT> t,
200  scaled_quantity<util::quantities::units::Hertz, FR, FT> f
201  )
202  -> decltype(std::declval<TT>() * std::declval<FT>())
203  ;
204  template <typename FR, typename FT, typename TR, typename TT>
205  constexpr auto operator*(
208  )
209  { return t * f; }
210  //@}
211 
212 
213  /**
214  * @brief Returns a frequency as the inverse of a time.
215  * @tparam T type of pure number
216  * @tparam TR type of time unit scale (e.g. `std::micro`)
217  * @tparam TT type of time value representation
218  * @param v scalar value to be divided
219  * @param t time quantity, based on `util::quantities::unit::Second`
220  * @return a frequency _f_ so that `f * t` equals `v`
221  *
222  * The scale of the frequency unit is the inverse of the time one (e.g.,
223  * a division by `util::quantities::millisecond` gives
224  * `util::quantities::kilohertz`).
225  */
226  template <typename T, typename TR, typename TT>
227  constexpr auto operator/(T v, scaled_second<TR, TT> t)
228  -> std::enable_if_t<
229  std::is_convertible_v<T, TT>,
230  scaled_hertz<
232  decltype(std::declval<T>() / std::declval<TT>())
233  >
234  >
235  ;
236 
237 
238  /**
239  * @brief Returns a time as the inverse of a frequency.
240  * @tparam T type of pure number
241  * @tparam FR type of frequency unit scale (e.g. `std::mega`)
242  * @tparam FT type of frequency value representation
243  * @param v scalar value to be divided
244  * @param t frequency quantity, based on `util::quantities::unit::Hertz`
245  * @return a time _t_ so that `t * f` equals `v`
246  *
247  * The scale of the time unit is the inverse of the frequency one (e.g.,
248  * a division by `util::quantities::kilohertz` gives
249  * `util::quantities::millisecond`).
250  */
251  template <typename T, typename FR, typename FT>
252  constexpr auto operator/(T v, scaled_hertz<FR, FT> f)
253  -> std::enable_if_t<
254  std::is_convertible_v<T, FT>,
257  decltype(std::declval<T>() / std::declval<FT>())
258  >
259  >
260  ;
261 
262 
263  } // namespace concepts
264 
265  /// @}
266  // -- END Special operations between Second and Hertz units ------------------
267 
268 
269 } // namespace util::quantities
270 
271 //------------------------------------------------------------------------------
272 //--- template implementation
273 template <typename TR, typename TT, typename FR, typename FT>
277  )
278  -> decltype(std::declval<TT>() * std::declval<FT>())
279 {
280  return details::applyRatioToValue<simplified_ratio_multiply<TR, FR> >
281  (t.value() * f.value());
282 } // util::quantities::operator*(Second, Hertz)
283 
284 
285 //------------------------------------------------------------------------------
286 template <typename T, typename TR, typename TT>
287 constexpr auto util::quantities::concepts::operator/
289  -> std::enable_if_t<
290  std::is_convertible_v<T, TT>,
292  <details::invert_t<TR>, decltype(std::declval<T>() / std::declval<TT>())>
293  >
294 {
295  return scaled_hertz
296  <details::invert_t<TR>, decltype(std::declval<T>() / std::declval<TT>())>
297  ::castFrom(v / t.value());
298 } // util::quantities::operator/(Second)
299 
300 
301 //------------------------------------------------------------------------------
302 template <typename T, typename FR, typename FT>
303 constexpr auto util::quantities::concepts::operator/
305  -> std::enable_if_t<
306  std::is_convertible_v<T, FT>,
308  <details::invert_t<FR>, decltype(std::declval<T>() / std::declval<FT>())>
309  >
310 {
311  return scaled_second
312  <details::invert_t<FR>, decltype(std::declval<T>() / std::declval<FT>())>
313  ::castFrom( v / f.value() );
314 } // util::quantities::operator/(Hertz)
315 
316 
317 //------------------------------------------------------------------------------
318 
319 
320 //------------------------------------------------------------------------------
321 
322 
323 #endif // LARDATAALG_UTILITIES_QUANTITIES_FREQUENCY_H
static QCString name
Definition: declinfo.cpp:673
A value measured in the specified unit.
Definition: quantities.h:566
constexpr auto operator/(T v, scaled_hertz< FR, FT > f) -> std::enable_if_t< std::is_convertible_v< T, FT >, scaled_second< details::invert_t< FR >, decltype(std::declval< T >()/std::declval< FT >()) > >
Returns a time as the inverse of a frequency.
Definition: frequency.h:304
Numeric variable proxies with embedded unit of measurement.
Dimensioned variables representing space or time quantities.
typename invert_ratio< R >::type invert_t
Definition: quantities.h:243
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
Types of variables with a unit.
Definition: intervals.h:20
QuadExpr operator*(double v, const QuadExpr &e)
Definition: QuadExpr.h:39