Reactions  0.0.0
Handling reaction trees and decays
database.hpp
Go to the documentation of this file.
1 
4 #pragma once
5 
6 #include <algorithm>
7 #include <cmath>
8 #include <optional>
9 #include <stdexcept>
10 #include <string>
11 #include <tuple>
12 #include <type_traits>
13 
14 namespace reactions {
15 
22  template <class... Args> struct fill : std::tuple<Args...> {
24  using base_type = std::tuple<Args...>;
25  constexpr fill(Args &&... args) : base_type{std::forward<Args>(args)...} {}
26  };
27 
29  static constexpr auto missing = std::nullopt;
30 } // namespace reactions
31 
34 
36  template <class Tuple> struct underlying_types;
37 
39  template <class... F> struct underlying_types<std::tuple<F...>> {
40  using type = std::tuple<typename F::value_type...>;
41  };
42 
44  template <class> struct is_optional : std::false_type {};
45 
47  template <class T> struct is_optional<std::optional<T>> : std::true_type {};
48 
50  template <class T> constexpr auto is_optional_v = is_optional<T>::value;
51 
53  template <class F, class Enable = void>
55 
57  template <class F>
59  F, std::enable_if_t<is_optional_v<typename F::value_type>>>
60  : std::true_type {};
61 
63  template <class F>
65 
67  template <class T> struct remove_optional { using type = T; };
68 
70  template <class T> struct remove_optional<std::optional<T>> {
71  using type = T;
72  };
73 
75  template <class T>
77 
79  struct value {};
81  struct error {};
83  struct error_lower {};
85  struct error_upper {};
86 
88  template <std::size_t Min, std::size_t Max> struct range {
89  static constexpr auto min = Min, max = Max;
90  };
91 
93  template <class... R> using range_collection = std::tuple<R...>;
94 
96  template <class R> struct overall_range {
98  };
99 
101  template <class R0, class... R, class Rn>
102  struct overall_range<range_collection<R0, R..., Rn>> {
104  };
105 
107  template <class R> using overall_range_t = typename overall_range<R>::type;
108 
110  template <class T, class Enable = void> struct value_and_errors;
111 
113  template <class T>
115  std::enable_if_t<std::is_floating_point_v<T>, void>> {
116 
117  using value_type = T;
118 
120  value_and_errors() = default;
122  template <class Value, class ErrorLower, class ErrorUpper>
123  value_and_errors(Value &&value_, ErrorLower &&error_lower_,
124  ErrorUpper &&error_upper_)
125  : value(value_), error_lower(error_lower_), error_upper(error_upper_) {}
127  template <class Value, class ErrorLower, class ErrorUpper>
129  : value(std::get<0>(f)), error_lower(std::get<1>(f)),
130  error_upper(std::get<2>(f)) {}
131 
140  return error_lower * error_lower + error_upper * error_upper;
141  };
143  value_type error() const { return std::sqrt(error_squared()); }
144  };
145 
148  template <class T> constexpr auto const &access_value(T const &c) {
149  return c;
150  }
151 
153  template <class T>
154  constexpr auto const &access_value(std::optional<T> const &opt) {
155  return opt.value();
156  }
157 
159  template <class F> struct get_t;
160 
162  template <> struct get_t<value> {
163  template <class T> constexpr auto const &operator()(T const &t) const {
164  return access_value(t).value;
165  }
166  };
167 
169  template <> struct get_t<error> {
170  template <class T> constexpr auto const &operator()(T const &t) const {
171  return access_value(t).error;
172  }
173  };
174 
176  template <> struct get_t<error_lower> {
177  template <class T> constexpr auto const &operator()(T const &t) const {
178  return access_value(t).error_lower;
179  }
180  };
181 
183  template <> struct get_t<error_upper> {
184  template <class T> constexpr auto const &operator()(T const &t) const {
185  return access_value(t).error_upper;
186  }
187  };
188 
190  template <class F> static constexpr get_t<F> get;
191 
200 
202  enum conversion_status : int {
206  };
207 
209  namespace detail {
210 
213 
214  if (s.empty())
215  return empty;
216 
217  try {
218  out = std::stoi(s);
219  } catch (std::invalid_argument &e) {
220  return failed;
221  }
222 
223  return success;
224  }
225 
228 
229  if (s.empty())
230  return empty;
231 
232  try {
233  out = std::stof(s);
234  } catch (std::invalid_argument &e) {
235  return failed;
236  }
237 
238  return success;
239  }
240 
243 
244  if (s.empty())
245  return empty;
246 
247  try {
248  out = std::stod(s);
249  } catch (std::invalid_argument &e) {
250  return failed;
251  }
252 
253  return success;
254  }
255 
258 
259  if (s.empty())
260  return empty;
261 
262  try {
263  out = std::stoi(s);
264  } catch (std::invalid_argument &e) {
265  return failed;
266  }
267 
268  return success;
269  }
270 
273 
274  out = s;
275 
276  if (out.size() == 0)
277  return empty;
278  else
279  return success;
280  }
281  } // namespace detail
282 
284  template <class Range, class T>
286  // std::from_chars is not correctly implemented in GCC, and
287  // we can not work with std::string_view objects
288  auto b = s.find_first_not_of(' ', Range::min);
289 
290  if (b >= Range::max)
291  return empty;
292 
293  auto e = s.find_last_not_of(' ', Range::max) + 1;
294 
295  return detail::string_to_type(out, s.substr(b, e - b));
296  }
297 
299  template <class Ranges, class T>
301  // std::from_chars is not correctly implemented in GCC, and
302  // we can not work with std::string_view objects
303  static_assert(std::tuple_size_v<Ranges> == 3);
304 
305  auto b = s.find_first_not_of(' ', std::tuple_element_t<0, Ranges>::min);
306 
307  if (b >= std::tuple_element_t<2, Ranges>::max)
308  return empty;
309 
310  auto value_sc = detail::string_to_type(
311  out.value, s.substr(std::tuple_element_t<0, Ranges>::min,
312  std::tuple_element_t<0, Ranges>::max));
313  auto error_lower_sc = detail::string_to_type(
314  out.error_lower, s.substr(std::tuple_element_t<1, Ranges>::min,
315  std::tuple_element_t<1, Ranges>::max));
316  auto error_upper_sc = detail::string_to_type(
317  out.error_upper, s.substr(std::tuple_element_t<2, Ranges>::min,
318  std::tuple_element_t<2, Ranges>::max));
319 
320  if (value_sc == empty || error_lower_sc == empty || error_upper_sc == empty)
321  return failed; // either all are defined or none
322  else if (value_sc == failed || error_lower_sc == failed ||
323  error_upper_sc == failed)
324  return failed;
325  else
326  return success;
327  }
328 } // namespace reactions::database
T empty(T... args)
T value(T... args)
T find_first_not_of(T... args)
Define a range with minimum and maximum indices.
Definition: database.hpp:88
static constexpr get_t< F > get
Accessor to a value/error field.
Definition: database.hpp:190
constexpr fill(Args &&... args)
Definition: database.hpp:25
static constexpr auto missing
Static object that defines a missing field within an object.
Definition: database.hpp:29
typename remove_optional< T >::type remove_optional_t
If the input type is an optional, get the underying type.
Definition: database.hpp:76
constexpr auto is_optional_field_v
Contain the information whether a field is optional or not.
Definition: database.hpp:64
conversion_status string_to_type(std::string &out, std::string const &s)
Convert a range of characters to string.
Definition: database.hpp:272
T stof(T... args)
STL namespace.
T type
Definition: database.hpp:67
constexpr auto is_optional_v
Alias to check if a type represents an optional.
Definition: database.hpp:50
value_type error_squared() const
Calculate the squared error from the lower and upper errors.
Definition: database.hpp:139
Type defining an accessor to a value/error field.
Definition: database.hpp:159
value_and_errors(fill< Value, ErrorLower, ErrorUpper > &&f)
Build the class from a field constant expression.
Definition: database.hpp:128
Small structure to define fields without explicitely knowing its type.
Definition: database.hpp:22
constexpr auto const & operator()(T const &t) const
Definition: database.hpp:184
constexpr auto const & operator()(T const &t) const
Definition: database.hpp:163
value_and_errors(Value &&value_, ErrorLower &&error_lower_, ErrorUpper &&error_upper_)
Build the class with forwarded arguments.
Definition: database.hpp:123
conversion_status
Status code of a conversion to an arithmetic or std::optional type.
Definition: database.hpp:202
STL class.
Simple structure composed by a value and the lower and upper errors.
Definition: database.hpp:110
constexpr auto const & operator()(T const &t) const
Definition: database.hpp:170
Check if a type represents an optional.
Definition: database.hpp:44
value_type error() const
Calculate the error from the lower and upper errors.
Definition: database.hpp:143
Field for an lower error.
Definition: database.hpp:85
the conversion failed
Definition: database.hpp:205
Main namespace of the Reactions package.
Definition: all.hpp:21
Utilities to handle database objects and their elements.
Definition: database.hpp:33
constexpr auto const & access_value(std::optional< T > const &opt)
Definition: database.hpp:154
Get the overall range for a range with/without subranges.
Definition: database.hpp:96
conversion_status read_field(value_and_errors< T > &out, std::string const &s)
Read a field composed by value and errors in a line from a file.
Definition: database.hpp:300
T find_last_not_of(T... args)
If the input type is an optional, get the underying type.
Definition: database.hpp:67
T size(T... args)
the object is missing
Definition: database.hpp:204
T substr(T... args)
Define a std::tuple with the types of the fields provided.
Definition: database.hpp:36
typename overall_range< R >::type overall_range_t
Overall range of a variable (that can be a composite)
Definition: database.hpp:107
T sqrt(T... args)
Field for a value.
Definition: database.hpp:79
constexpr auto const & operator()(T const &t) const
Definition: database.hpp:177
T stoi(T... args)
Field for an error.
Definition: database.hpp:81
the conversion succeeded
Definition: database.hpp:203
Contain the information whether a field is optional or not.
Definition: database.hpp:54
Field for a lower error.
Definition: database.hpp:83