Reactions  0.1.2
Handling reaction trees and decays
fields.hpp
Go to the documentation of this file.
1 
4 #pragma once
5 
6 #include <algorithm>
7 #include <cmath>
8 #include <optional>
9 #include <string>
10 #include <tuple>
11 #include <type_traits>
12 
13 namespace reactions {
14 
21  template <class... Args> struct fill : std::tuple<Args...> {
23  using base_type = std::tuple<Args...>;
24  constexpr fill(Args &&...args) : base_type{std::forward<Args>(args)...} {}
25  };
26 
28  static constexpr auto missing = std::nullopt;
29 } // namespace reactions
30 
58 namespace reactions::fields {
59 
61  template <class Tuple> struct underlying_types;
62 
64  template <class... Field> struct underlying_types<std::tuple<Field...>> {
65  using type = std::tuple<typename Field::value_type...>;
66  };
67 
69  template <class Fields>
71 
73  template <class> struct is_optional : std::false_type {};
74 
76  template <class T> struct is_optional<std::optional<T>> : std::true_type {};
77 
79  template <class T> constexpr auto is_optional_v = is_optional<T>::value;
80 
82  template <class Field, class Enable = void>
84 
86  template <class Field>
88  Field, std::enable_if_t<is_optional_v<typename Field::value_type>>>
89  : std::true_type {};
90 
92  template <class Field>
94 
96  template <class T> struct remove_optional { using type = T; };
97 
99  template <class T> struct remove_optional<std::optional<T>> {
100  using type = T;
101  };
102 
104  template <class T>
106 
108  struct value {};
110  struct error {};
112  struct error_lower {};
114  struct error_upper {};
116  struct tag {};
117 
119  template <std::size_t Min, std::size_t Max> struct range {
120  static constexpr auto min = Min, max = Max;
121  };
122 
124  template <class... R> using range_collection = std::tuple<R...>;
125 
127  template <class R> struct overall_range {
129  };
130 
132  template <class R0, class... R, class Rn>
133  struct overall_range<range_collection<R0, R..., Rn>> {
135  };
136 
138  template <class R> using overall_range_t = typename overall_range<R>::type;
139 
141  template <class T, class Enable = void> struct value_and_error;
142 
144  template <class T>
145  struct value_and_error<T,
146  std::enable_if_t<std::is_floating_point_v<T>, void>> {
147 
148  using value_type = T;
149 
152 
154  template <class Value, class Error>
155  value_and_error(Value value_, Error error_)
156  : value(value_), error(error_) {}
158  template <class Value, class Error>
160  : value(std::get<0>(f)), error(std::get<1>(f)) {}
161 
166  };
167 
169  template <class ValueType, class TagType, class Enable = void>
171 
173  template <class ValueType, class TagType>
175  ValueType, TagType,
176  std::enable_if_t<(std::is_floating_point_v<ValueType> &&
177  std::is_integral_v<TagType>),
178  void>> : value_and_error<ValueType> {
179 
181 
184 
186  template <class Value, class Error>
187  value_and_error_with_tag(Value value_, Error error_, TagType tag_)
188  : base_type{value_, error_}, tag(tag_) {}
190  template <class Value, class Error>
192  : base_type{std::get<0>(f), std::get<1>(f)}, tag(std::get<2>(f)) {}
193 
195  TagType tag;
196  };
197 
199  template <class T, class Enable = void> struct value_and_errors;
200 
202  template <class T>
204  std::enable_if_t<std::is_floating_point_v<T>, void>> {
205 
206  using value_type = T;
207 
209  value_and_errors() = default;
211  template <class Value, class ErrorLower, class ErrorUpper>
212  value_and_errors(Value value_, ErrorLower error_lower_,
213  ErrorUpper error_upper_)
214  : value(value_), error_lower(error_lower_), error_upper(error_upper_) {}
216  template <class Value, class ErrorLower, class ErrorUpper>
218  : value(std::get<0>(f)), error_lower(std::get<1>(f)),
219  error_upper(std::get<2>(f)) {}
220 
229  return error_lower * error_lower + error_upper * error_upper;
230  };
232  value_type error() const { return std::sqrt(error_squared()); }
233  };
234 
237  template <class T> constexpr auto const &access_value(T const &c) {
238  return c;
239  }
240 
242  template <class T>
243  constexpr auto const &access_value(std::optional<T> const &opt) {
244  return opt.value();
245  }
246 
248  template <class Field> struct get_t;
249 
251  template <> struct get_t<value> {
252  template <class T> constexpr auto const &operator()(T const &t) const {
253  return access_value(t).value;
254  }
255  };
256 
258  template <> struct get_t<error> {
259  template <class T> constexpr auto const &operator()(T const &t) const {
260  return access_value(t).error;
261  }
262  };
263 
265  template <> struct get_t<error_lower> {
266  template <class T> constexpr auto const &operator()(T const &t) const {
267  return access_value(t).error_lower;
268  }
269  };
270 
272  template <> struct get_t<error_upper> {
273  template <class T> constexpr auto const &operator()(T const &t) const {
274  return access_value(t).error_upper;
275  }
276  };
277 
279  template <> struct get_t<tag> {
280  template <class T> constexpr auto const &operator()(T const &t) const {
281  return access_value(t).tag;
282  }
283  };
284 
286  template <class T, class Subfield, class... S> struct type_of {
287  using type = typename type_of<Subfield, S...>::type;
288  };
289 
291  template <class T, class Subfield> struct type_of<T, Subfield> {
292  using type =
295  };
296 
298  template <class T, class... Subfield>
299  using type_of_t = typename type_of<T, Subfield...>::type;
300 
302  template <class T>
304  return {f * vae.value, f * vae.error};
305  }
306 
308  template <class T>
310  return vae * f;
311  }
312 
314  template <class V, class T>
317  return {f * vae.value, f * vae.error, vae.tag};
318  }
319 
321  template <class V, class T>
324  return vae * f;
325  }
326 
328  template <class T>
330  return {f * vae.value, f * vae.error_lower, f * vae.error_upper};
331  }
332 
334  template <class T>
336  return vae * f;
337  }
338 
340  template <class Field> static constexpr get_t<Field> get;
341 
352  template <class TagType>
356  template <class TagType>
357  using vet_double_opt =
363 
365  enum conversion_status : int {
369  };
370 
372  namespace detail {
373 
376 
377  if (s.empty())
378  return empty;
379 
380  try {
381  out = std::stoi(s);
382  } catch (std::invalid_argument &e) {
383  return failed;
384  }
385 
386  return success;
387  }
388 
391 
392  if (s.empty())
393  return empty;
394 
395  try {
396  out = std::stof(s);
397  } catch (std::invalid_argument &e) {
398  return failed;
399  }
400 
401  return success;
402  }
403 
406 
407  if (s.empty())
408  return empty;
409 
410  try {
411  out = std::stod(s);
412  } catch (std::invalid_argument &e) {
413  return failed;
414  }
415 
416  return success;
417  }
418 
421 
422  if (s.empty())
423  return empty;
424 
425  try {
426  out = std::stoi(s);
427  } catch (std::invalid_argument &e) {
428  return failed;
429  }
430 
431  return success;
432  }
433 
436 
437  out = s;
438 
439  if (out.size() == 0)
440  return empty;
441  else
442  return success;
443  }
444  } // namespace detail
445 
447  template <class Range, class T>
449  // std::from_chars is not correctly implemented in GCC, and
450  // we can not work with std::string_view objects
451  auto b = s.find_first_not_of(' ', Range::min);
452 
453  if (b >= Range::max)
454  return empty;
455 
456  auto e = s.find_last_not_of(' ', Range::max) + 1;
457 
458  return detail::string_to_type(out, s.substr(b, e - b));
459  }
460 
462  template <class Ranges, class T>
464  // std::from_chars is not correctly implemented in GCC, and
465  // we can not work with std::string_view objects
466  static_assert(std::tuple_size_v<Ranges> == 3);
467 
468  auto b = s.find_first_not_of(' ', std::tuple_element_t<0, Ranges>::min);
469 
470  if (b >= std::tuple_element_t<1, Ranges>::max)
471  return empty;
472 
473  auto value_sc = read_field<std::tuple_element_t<0, Ranges>>(out.value, s);
474  auto error_sc = read_field<std::tuple_element_t<1, Ranges>>(out.error, s);
475 
476  if (value_sc == empty || error_sc == empty)
477  return failed; // either all are defined or none
478  else if (value_sc == failed || error_sc == failed)
479  return failed;
480  else
481  return success;
482  }
483 
485  template <class Ranges, class ValueType, class TagType>
488  std::string const &s) {
489  // std::from_chars is not correctly implemented in GCC, and
490  // we can not work with std::string_view objects
491  static_assert(std::tuple_size_v<Ranges> == 3);
492 
493  auto b = s.find_first_not_of(' ', std::tuple_element_t<0, Ranges>::min);
494 
495  if (b >= std::tuple_element_t<2, Ranges>::max)
496  return empty;
497 
498  auto value_sc = read_field<std::tuple_element_t<0, Ranges>>(out.value, s);
499  auto error_sc = read_field<std::tuple_element_t<1, Ranges>>(out.error, s);
500  auto tag_sc = read_field<std::tuple_element_t<2, Ranges>>(out.tag, s);
501 
502  if (value_sc == empty || error_sc == empty || tag_sc == empty)
503  return failed; // either all are defined or none
504  else if (value_sc == failed || error_sc == failed || tag_sc == failed)
505  return failed;
506  else
507  return success;
508  }
509 
511  template <class Ranges, class T>
513  // std::from_chars is not correctly implemented in GCC, and
514  // we can not work with std::string_view objects
515  static_assert(std::tuple_size_v<Ranges> == 3);
516 
517  auto b = s.find_first_not_of(' ', std::tuple_element_t<0, Ranges>::min);
518 
519  if (b >= std::tuple_element_t<2, Ranges>::max)
520  return empty;
521 
522  auto value_sc = read_field<std::tuple_element_t<0, Ranges>>(out.value, s);
523  auto error_lower_sc =
524  read_field<std::tuple_element_t<1, Ranges>>(out.error_lower, s);
525  auto error_upper_sc =
526  read_field<std::tuple_element_t<2, Ranges>>(out.error_upper, s);
527 
528  if (value_sc == empty || error_lower_sc == empty || error_upper_sc == empty)
529  return failed; // either all are defined or none
530  else if (value_sc == failed || error_lower_sc == failed ||
531  error_upper_sc == failed)
532  return failed;
533  else
534  return success;
535  }
536 
538  template <class Field, class... Subfield> struct field_member_type {
539  using type =
541  };
542 
544  template <class Field> struct field_member_type<Field> {
546  };
547 
549  template <class Field, class... Subfield>
550  using field_member_type_t =
551  typename field_member_type<Field, Subfield...>::type;
552 
554  template <class T> std::string to_string(T const &v) {
555  return std::to_string(v);
556  }
557 
559  template <> std::string to_string(std::string const &v) { return v; }
560 } // namespace reactions::fields
constexpr auto const & operator()(T const &t) const
Definition: fields.hpp:252
value_and_errors(fill< Value, ErrorLower, ErrorUpper > &&f)
Build the class from a field constant expression.
Definition: fields.hpp:217
Field for an error.
Definition: fields.hpp:110
Define a range with minimum and maximum indices.
Definition: fields.hpp:119
T empty(T... args)
T value(T... args)
Type defining an accessor to a value/error field.
Definition: fields.hpp:248
value_type error_squared() const
Calculate the squared error from the lower and upper errors.
Definition: fields.hpp:228
the conversion succeeded
Definition: fields.hpp:366
remove_optional_t< typename Field::value_type > type
Definition: fields.hpp:545
Field for a lower error.
Definition: fields.hpp:112
value_type error() const
Calculate the error from the lower and upper errors.
Definition: fields.hpp:232
T find_first_not_of(T... args)
T type
Definition: fields.hpp:96
typename type_of< T, Subfield... >::type type_of_t
Determine a returned type.
Definition: fields.hpp:299
constexpr auto const & operator()(T const &t) const
Definition: fields.hpp:266
static constexpr auto missing
Static object that defines a missing field within an object.
Definition: fields.hpp:28
value_and_errors(Value value_, ErrorLower error_lower_, ErrorUpper error_upper_)
Build the class with forwarded arguments.
Definition: fields.hpp:212
Contain the information whether a field is optional or not.
Definition: fields.hpp:83
Determine a returned type.
Definition: fields.hpp:286
T stof(T... args)
T to_string(T... args)
constexpr auto const & operator()(T const &t) const
Definition: fields.hpp:280
STL namespace.
the conversion failed
Definition: fields.hpp:368
value_and_error_with_tag(Value value_, Error error_, TagType tag_)
Build the class with forwarded arguments.
Definition: fields.hpp:187
Access the subtype of a set of fields.
Definition: fields.hpp:538
typename remove_optional< T >::type remove_optional_t
If the input type is an optional, get the underying type.
Definition: fields.hpp:105
constexpr auto const & operator()(T const &t) const
Definition: fields.hpp:259
Small structure to define fields without explicitely knowing its type.
Definition: fields.hpp:21
typename underlying_types< Fields >::type underlying_types_t
Define a std::tuple with the types of the fields provided.
Definition: fields.hpp:70
STL class.
Define a std::tuple with the types of the fields provided.
Definition: fields.hpp:61
typename type_of< Subfield, S... >::type type
Definition: fields.hpp:287
conversion_status string_to_type(std::string &out, std::string const &s)
Convert a range of characters to string.
Definition: fields.hpp:435
typename field_member_type< Field, Subfield... >::type field_member_type_t
Access the subtype of a set of fields.
Definition: fields.hpp:551
typename overall_range< R >::type overall_range_t
Overall range of a variable (that can be a composite)
Definition: fields.hpp:138
Main namespace of the Reactions package.
Definition: all.hpp:22
value_and_error_with_tag(fill< Value, Error, TagType > &&f)
Build the class from a field constant expression.
Definition: fields.hpp:191
Field for an lower error.
Definition: fields.hpp:114
value_and_errors< T > operator*(T f, value_and_errors< T > const &vae)
Multiplication of the value and errors by a constant.
Definition: fields.hpp:335
Check if a type represents an optional.
Definition: fields.hpp:73
Simple structure composed by a value and its error.
Definition: fields.hpp:141
constexpr auto const & operator()(T const &t) const
Definition: fields.hpp:273
value_and_error(fill< Value, Error > &&f)
Build the class from a field constant expression.
Definition: fields.hpp:159
T find_last_not_of(T... args)
T size(T... args)
constexpr auto is_optional_v
Alias to check if a type represents an optional.
Definition: fields.hpp:79
the object is missing
Definition: fields.hpp:367
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: fields.hpp:512
constexpr fill(Args &&...args)
Definition: fields.hpp:24
value_and_error(Value value_, Error error_)
Build the class with forwarded arguments.
Definition: fields.hpp:155
Represent a value, its error and a identifier tag.
Definition: fields.hpp:170
Field for a value.
Definition: fields.hpp:108
conversion_status
Status code of a conversion to an arithmetic or std::optional type.
Definition: fields.hpp:365
Simple structure composed by a value and the lower and upper errors.
Definition: fields.hpp:199
T substr(T... args)
If the input type is an optional, get the underying type.
Definition: fields.hpp:96
Field for a tag.
Definition: fields.hpp:116
T sqrt(T... args)
constexpr auto const & access_value(std::optional< T > const &opt)
Definition: fields.hpp:243
type_of_t< remove_optional_t< typename Field::value_type >, Subfield... > type
Definition: fields.hpp:540
T stoi(T... args)
static constexpr get_t< Field > get
Accessor to a value/error field.
Definition: fields.hpp:340
constexpr auto is_optional_field_v
Contain the information whether a field is optional or not.
Definition: fields.hpp:93
Get the overall range for a range with/without subranges.
Definition: fields.hpp:127
Utilities to handle database objects and their elements.
Definition: fields.hpp:58
std::string to_string(std::string const &v)
Convert the given object to a string.
Definition: fields.hpp:559