All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
rounding.h
Go to the documentation of this file.
1 /**
2  * @file icarusalg/Utilities/rounding.h
3  * @brief Utilities for numerical rounding.
4  * @author Gianluca Petrillo (petrillo@slac.stanford.edu)
5  * @date April 17, 2020
6  *
7  * This is a header-only library.
8  */
9 
10 #ifndef ICARUSALG_UTILITIES_ROUNDING_H
11 #define ICARUSALG_UTILITIES_ROUNDING_H
12 
13 
14 // C/C++ standard libraries
15 #include <cmath> // std::floor()
16 
17 
18 // ---------------------------------------------------------------------------
19 namespace icarus::ns::util {
20 
21  template <typename T, typename U>
22  constexpr T rounddown(T const value, U const quantum, T const offset = T{});
23 
24  template <typename T, typename U>
25  constexpr T roundup(T const value, U const quantum, T const offset = T{});
26 
27 } // namespace icarus::ns::util
28 
29 
30 // ---------------------------------------------------------------------------
31 /**
32  * @brief Returns the `value`, rounded down.
33  * @tparam T type of the value to be rounded
34  * @tparam U type of the quantization value
35  * @param value the value to be rounded down
36  * @param quantum the rounding unit
37  * @param offset an offset to subtract for the rounding
38  * @return `value` rounded down to multiples of `quantum`
39  *
40  * The `value` is returned rounded _down_ into multiples of `quantum`.
41  * Optionally, the rounding happens only for the amount of `value` above an
42  * `offset`.
43  * Examples:
44  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
45  * std::cout << icarus::ns::util::rounddown(23.0, 2.5)
46  * << "\n" << icarus::ns::util::rounddown(23.0, 2.5, 1.0)
47  * << std::endl;
48  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
49  * will print `22.5` and `21`.
50  *
51  *
52  * Type requirements
53  * ------------------
54  *
55  * * `T` must support addition and subtraction;
56  * * `U` must support product to `double`: `P operator* (U, double)`, with
57  * the result `P` implicitly convertible to `T`;
58  * * `T` and `U` must support multiplication (`P operator* (T, U)`), and the
59  * result `P` must be convertible back to `T`;
60  * * `T` and `U` must support division (`R operator/ (T, U)`), and the result
61  * `R` must be implicitly convertible to an integral or floating point type;
62  * * `T` and `U` must support addition (`S operator+ (T, U)`), and the result
63  * `S` must be convertible back to type `T`.
64  *
65  */
66 template <typename T, typename U>
68  (T const value, U const quantum, T const offset /* = T{} */)
69 {
70  return
71  static_cast<T>(offset + quantum * std::floor((value - offset) / quantum));
72 } // icarus::ns::util::rounddown()
73 
74 
75 /**
76  * @brief Returns the `value`, rounded up.
77  * @tparam T type of the value to be rounded
78  * @tparam U type of the quantization value
79  * @param value the value to be rounded up
80  * @param quantum the rounding unit
81  * @param offset an offset to subtract for the rounding
82  * @return `value` rounded up to multiples of `quantum`
83  *
84  * The `value` is returned rounded _up_ into multiples of `quantum`.
85  * Optionally, the rounding happens only for the amount of `value` above an
86  * `offset`.
87  * Examples:
88  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
89  * std::cout << icarus::ns::util::roundup(23.0, 2.5)
90  * << "\n" << icarus::ns::util::roundup(23.0, 2.5, 1.0)
91  * << std::endl;
92  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
93  * will print `25` and `23.5`.
94  *
95  *
96  * Type requirements
97  * ------------------
98  *
99  * * `T` must support comparison (`operator < (T, T)`;
100  * * `T` must support addition and subtraction;
101  * * `double` must be convertivle _into_ `T`;
102  * * `T` and `U` must support multiplication (`P operator* (T, U)`), and the
103  * result `P` must be convertible back to type `T`;
104  * * `T` and `U` must support division (`R operator/ (T, U)`), and the result
105  * `R` must be implicitly convertible to an integral or floating point type;
106  * * `T` and `U` must support addition (`S operator+ (T, U)`), and the result
107  * `S` must be convertible back to type `T`.
108  *
109  */
110 template <typename T, typename U>
111 constexpr T icarus::ns::util::roundup
112  (T const value, U const quantum, T const offset /* = T{} */)
113 {
114  T const rounded = rounddown(value, quantum, offset);
115  return (rounded < value)? static_cast<T>(rounded + quantum): rounded;
116 } // icarus::ns::util::roundup()
117 
118 
119 // ---------------------------------------------------------------------------
120 
121 
122 #endif // ICARUSALG_UTILITIES_ROUNDING_H
123 
BEGIN_PROLOG TPC Trig offset(g4 rise time) ProjectToHeight
Definition: CORSIKAGen.fcl:7
constexpr T roundup(T const value, U const quantum, T const offset=T{})
Returns the value, rounded up.
Definition: rounding.h:112
constexpr T rounddown(T const value, U const quantum, T const offset=T{})
Returns the value, rounded down.
Definition: rounding.h:68
temporary value