carl  24.04
Computer ARithmetic Library
settings_utils.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <array>
4 #include <chrono>
5 #include <iostream>
6 #include <string>
7 #include <utility>
8 #include <vector>
9 
10 namespace boost {
11  class any;
12 }
13 
14 namespace carl::settings {
15 
16 /**
17  * Helper method to obtain proper (unit) suffix entry from a value and a given set of possible suffixes.
18  *
19  * Can be called, for example, with a value of nanoseconds and the following array `a = { {"ns", 1000}, {"µs", 1000}, {"ms", 1000}, {"s", 60}, {"m", 60}, {"h", 1} }`.
20  * This method will find the largest suffix such that the value will not be zero if represented with respect to this suffix.
21  * The return value is the value converted to this unit suffix and the index into the array to retrieve the appropriate suffix string.
22  * For the above example, `get_proper_suffix(30000000000, a) = {30, 3}`, that is `30s`.
23  */
24 template<typename Array>
25 std::pair<std::intmax_t,std::size_t> get_proper_suffix(std::intmax_t value, const Array& a) {
26  std::size_t id = 0;
27  std::intmax_t mult = 1;
28  for (; id < a.size()-1; ++id) {
29  if (value < (a[id].second * mult)) {
30  break;
31  }
32  mult *= a[id].second;
33  }
34  return std::make_pair(value / mult, id);
35 }
36 
37 /**
38  * Helper type to parse duration as std::chrono values with boost::program_options.
39  * Intended usage:
40  * - use boost to parse values as durations
41  * - access values with `std::chrono::seconds(d)`
42  */
43 struct duration: std::chrono::nanoseconds {
44  duration() = default;
45  template<typename... Args>
46  // NOLINTNEXTLINE(google-explicit-constructor,hicpp-explicit-conversions): we actually want to implicitly convert here.
47  constexpr duration(Args&&... args): std::chrono::nanoseconds(std::forward<Args>(args)...) {}
48  template<typename R, typename P>
49  explicit constexpr operator std::chrono::duration<R,P>() const {
50  return std::chrono::duration_cast<std::chrono::duration<R,P>>(std::chrono::nanoseconds(*this));
51  }
52 };
53 
54 /// Streaming operator for duration. Auto-detects proper time suffix.
55 inline std::ostream& operator<<(std::ostream& os, const duration& d) {
56  std::array<std::pair<std::string,intmax_t>,6> suffixes = {{
57  {"ns", 1000}, {"µs", 1000}, {"ms", 1000},
58  {"s", 60}, {"m", 60}, {"h", 1},
59  }};
60  auto res = get_proper_suffix(d.count(), suffixes);
61  return os << res.first << suffixes[res.second].first;
62 }
63 
64 /**
65  * Custom validator for duration that wraps some std::chrono::duration.
66  * Accepts the format `<number><suffix>` where suffix is one of the following:
67  * `ns,µs,us,ms,s,m,h`.
68  */
69 void validate(boost::any& v, const std::vector<std::string>& values, carl::settings::duration* /*unused*/, int /*unused*/);
70 
71 /**
72  * Helper type to parse quantities with binary SI-style suffixes.
73  * Intended usage:
74  * - use boost to parse values as quantity
75  * - access values with `q.mibi()`
76  */
78 private:
79  std::size_t mN = 0;
80 public:
81  constexpr binary_quantity() = default;
82  explicit constexpr binary_quantity(std::size_t n): mN(n) {}
83  constexpr auto n() const { return mN; }
84  constexpr auto kibi() const { return mN >> 10U; }
85  constexpr auto mebi() const { return mN >> 20U; }
86  constexpr auto gibi() const { return mN >> 30U; }
87  constexpr auto tebi() const { return mN >> 40U; }
88  constexpr auto pebi() const { return mN >> 50U; }
89  constexpr auto exbi() const { return mN >> 60U; }
90 };
91 /// Compare two binary quantities for equality.
92 constexpr bool operator==(binary_quantity lhs, binary_quantity rhs) {
93  return lhs.n() == rhs.n();
94 }
95 /// Compare two binary quantities.
96 constexpr bool operator<(binary_quantity lhs, binary_quantity rhs) {
97  return lhs.n() < rhs.n();
98 }
99 
100 /// Streaming operator for binary quantity. Auto-detects proper suffix.
101 inline std::ostream& operator<<(std::ostream& os, const binary_quantity& q) {
102  std::array<std::pair<std::string,long>,7> suffixes = {{
103  {"", 1024}, {"Ki", 1024}, {"Mi", 1024},
104  {"Gi", 1024}, {"Ti", 1024}, {"Pi", 1024}, {"Ei", 1},
105  }};
106  auto res = get_proper_suffix(static_cast<std::intmax_t>(q.n()), suffixes);
107  return os << res.first << suffixes[res.second].first;
108 }
109 
110 /**
111  * Custom validator for binary quantities.
112  * Accepts the format `<number><suffix>` where suffix is one of the following:
113  * `Ki,Mi,Gi,Ti,Pi,Ei`.
114  */
115 void validate(boost::any& v, const std::vector<std::string>& values, carl::settings::binary_quantity* /*unused*/, int /*unused*/);
116 
117 /**
118  * Helper type to parse quantities with SI-style suffixes.
119  * Intended usage:
120  * - use boost to parse values as quantity
121  * - access values with `q.mega()`
122  */
124 private:
125  std::size_t mN = 0;
126 public:
127  constexpr metric_quantity() = default;
128  explicit constexpr metric_quantity(std::size_t n): mN(n) {}
129  constexpr auto n() const { return mN; }
130  constexpr auto kilo() const { return mN / 1000; }
131  constexpr auto mega() const { return mN / 1000000; }
132  constexpr auto giga() const { return mN / 1000000000; }
133  constexpr auto tera() const { return mN / 1000000000000; }
134  constexpr auto peta() const { return mN / 1000000000000000; }
135  constexpr auto exa() const { return mN / 1000000000000000000; }
136 };
137 /// Compare two metric quantities for equality.
138 constexpr bool operator==(metric_quantity lhs, metric_quantity rhs) {
139  return lhs.n() == rhs.n();
140 }
141 /// Compare two metric quantities.
142 constexpr bool operator<(metric_quantity lhs, metric_quantity rhs) {
143  return lhs.n() < rhs.n();
144 }
145 
146 /// Streaming operator for metric quantity. Auto-detects proper suffix.
147 inline std::ostream& operator<<(std::ostream& os, const metric_quantity& q) {
148  std::array<std::pair<std::string,long>,7> suffixes = {{
149  {"", 1000}, {"K", 1000}, {"M", 1000},
150  {"G", 1000}, {"T", 1000}, {"P", 1000}, {"E", 1},
151  }};
152  auto res = get_proper_suffix(static_cast<std::intmax_t>(q.n()), suffixes);
153  return os << res.first << suffixes[res.second].first;
154 }
155 
156 /**
157  * Custom validator for metric quantities.
158  * Accepts the format `<number><suffix>` where suffix is one of the following:
159  * `K,M,G,T,P,E`.
160  */
161 void validate(boost::any& v, const std::vector<std::string>& values, carl::settings::metric_quantity* /*unused*/, int /*unused*/);
162 
163 }
std::pair< std::intmax_t, std::size_t > get_proper_suffix(std::intmax_t value, const Array &a)
Helper method to obtain proper (unit) suffix entry from a value and a given set of possible suffixes.
constexpr bool operator<(binary_quantity lhs, binary_quantity rhs)
Compare two binary quantities.
void validate(boost::any &v, const std::vector< std::string > &values, carl::settings::duration *, int)
Custom validator for duration that wraps some std::chrono::duration.
constexpr bool operator==(binary_quantity lhs, binary_quantity rhs)
Compare two binary quantities for equality.
std::ostream & operator<<(std::ostream &os, const duration &d)
Streaming operator for duration. Auto-detects proper time suffix.
Helper type to parse duration as std::chrono values with boost::program_options.
constexpr duration(Args &&... args)
Helper type to parse quantities with binary SI-style suffixes.
constexpr auto gibi() const
constexpr auto exbi() const
constexpr auto pebi() const
constexpr auto n() const
constexpr auto kibi() const
constexpr auto mebi() const
constexpr auto tebi() const
constexpr binary_quantity(std::size_t n)
constexpr binary_quantity()=default
Helper type to parse quantities with SI-style suffixes.
constexpr auto tera() const
constexpr auto kilo() const
constexpr metric_quantity(std::size_t n)
constexpr auto giga() const
constexpr auto n() const
constexpr auto peta() const
constexpr auto mega() const
constexpr metric_quantity()=default
constexpr auto exa() const