Reactions  0.1.0
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>
171 
173 
176 
178  template <class Value, class Error>
179  value_and_error_with_tag(Value value_, Error error_, TagType tag_)
180  : base_type{value_, error_}, tag(tag_) {}
182  template <class Value, class Error>
184  : base_type{std::get<0>(f), std::get<1>(f)}, tag(std::get<2>(f)) {}
185 
187  TagType tag;
188  };
189 
191  template <class T, class Enable = void> struct value_and_errors;
192 
194  template <class T>
196  std::enable_if_t<std::is_floating_point_v<T>, void>> {
197 
198  using value_type = T;
199 
201  value_and_errors() = default;
203  template <class Value, class ErrorLower, class ErrorUpper>
204  value_and_errors(Value value_, ErrorLower error_lower_,
205  ErrorUpper error_upper_)
206  : value(value_), error_lower(error_lower_), error_upper(error_upper_) {}
208  template <class Value, class ErrorLower, class ErrorUpper>
210  : value(std::get<0>(f)), error_lower(std::get<1>(f)),
211  error_upper(std::get<2>(f)) {}
212 
221  return error_lower * error_lower + error_upper * error_upper;
222  };
224  value_type error() const { return std::sqrt(error_squared()); }
225  };
226 
229  template <class T> constexpr auto const &access_value(T const &c) {
230  return c;
231  }
232 
234  template <class T>
235  constexpr auto const &access_value(std::optional<T> const &opt) {
236  return opt.value();
237  }
238 
240  template <class Field> struct get_t;
241 
243  template <> struct get_t<value> {
244  template <class T> constexpr auto const &operator()(T const &t) const {
245  return access_value(t).value;
246  }
247  };
248 
250  template <> struct get_t<error> {
251  template <class T> constexpr auto const &operator()(T const &t) const {
252  return access_value(t).error;
253  }
254  };
255 
257  template <> struct get_t<error_lower> {
258  template <class T> constexpr auto const &operator()(T const &t) const {
259  return access_value(t).error_lower;
260  }
261  };
262 
264  template <> struct get_t<error_upper> {
265  template <class T> constexpr auto const &operator()(T const &t) const {
266  return access_value(t).error_upper;
267  }
268  };
269 
271  template <> struct get_t<tag> {
272  template <class T> constexpr auto const &operator()(T const &t) const {
273  return access_value(t).tag;
274  }
275  };
276 
278  template <class T, class Subfield, class... S> struct type_of {
279  using type = typename type_of<Subfield, S...>::type;
280  };
281 
283  template <class T, class Subfield> struct type_of<T, Subfield> {
284  using type =
287  };
288 
290  template <class T, class... Subfield>
291  using type_of_t = typename type_of<T, Subfield...>::type;
292 
294  template <class T>
296  return {f * vae.value, f * vae.error};
297  }
298 
300  template <class T>
302  return vae * f;
303  }
304 
306  template <class V, class T>
309  return {f * vae.value, f * vae.error, vae.tag};
310  }
311 
313  template <class V, class T>
316  return vae * f;
317  }
318 
320  template <class T>
322  return {f * vae.value, f * vae.error_lower, f * vae.error_upper};
323  }
324 
326  template <class T>
328  return vae * f;
329  }
330 
332  template <class Field> static constexpr get_t<Field> get;
333 
344  template <class TagType>
348  template <class TagType>
349  using vet_double_opt =
355 
357  enum conversion_status : int {
361  };
362 
364  namespace detail {
365 
368 
369  if (s.empty())
370  return empty;
371 
372  try {
373  out = std::stoi(s);
374  } catch (std::invalid_argument &e) {
375  return failed;
376  }
377 
378  return success;
379  }
380 
383 
384  if (s.empty())
385  return empty;
386 
387  try {
388  out = std::stof(s);
389  } catch (std::invalid_argument &e) {
390  return failed;
391  }
392 
393  return success;
394  }
395 
398 
399  if (s.empty())
400  return empty;
401 
402  try {
403  out = std::stod(s);
404  } catch (std::invalid_argument &e) {
405  return failed;
406  }
407 
408  return success;
409  }
410 
413 
414  if (s.empty())
415  return empty;
416 
417  try {
418  out = std::stoi(s);
419  } catch (std::invalid_argument &e) {
420  return failed;
421  }
422 
423  return success;
424  }
425 
428 
429  out = s;
430 
431  if (out.size() == 0)
432  return empty;
433  else
434  return success;
435  }
436  } // namespace detail
437 
439  template <class Range, class T>
441  // std::from_chars is not correctly implemented in GCC, and
442  // we can not work with std::string_view objects
443  auto b = s.find_first_not_of(' ', Range::min);
444 
445  if (b >= Range::max)
446  return empty;
447 
448  auto e = s.find_last_not_of(' ', Range::max) + 1;
449 
450  return detail::string_to_type(out, s.substr(b, e - b));
451  }
452 
454  template <class Ranges, class T>
456  // std::from_chars is not correctly implemented in GCC, and
457  // we can not work with std::string_view objects
458  static_assert(std::tuple_size_v<Ranges> == 3);
459 
460  auto b = s.find_first_not_of(' ', std::tuple_element_t<0, Ranges>::min);
461 
462  if (b >= std::tuple_element_t<1, Ranges>::max)
463  return empty;
464 
465  auto value_sc = read_field<std::tuple_element_t<0, Ranges>>(out.value, s);
466  auto error_sc = read_field<std::tuple_element_t<1, Ranges>>(out.error, s);
467 
468  if (value_sc == empty || error_sc == empty)
469  return failed; // either all are defined or none
470  else if (value_sc == failed || error_sc == failed)
471  return failed;
472  else
473  return success;
474  }
475 
477  template <class Ranges, class ValueType, class TagType>
480  std::string const &s) {
481  // std::from_chars is not correctly implemented in GCC, and
482  // we can not work with std::string_view objects
483  static_assert(std::tuple_size_v<Ranges> == 3);
484 
485  auto b = s.find_first_not_of(' ', std::tuple_element_t<0, Ranges>::min);
486 
487  if (b >= std::tuple_element_t<2, Ranges>::max)
488  return empty;
489 
490  auto value_sc = read_field<std::tuple_element_t<0, Ranges>>(out.value, s);
491  auto error_sc = read_field<std::tuple_element_t<1, Ranges>>(out.error, s);
492  auto tag_sc = read_field<std::tuple_element_t<2, Ranges>>(out.tag, s);
493 
494  if (value_sc == empty || error_sc == empty || tag_sc == empty)
495  return failed; // either all are defined or none
496  else if (value_sc == failed || error_sc == failed || tag_sc == failed)
497  return failed;
498  else
499  return success;
500  }
501 
503  template <class Ranges, class T>
505  // std::from_chars is not correctly implemented in GCC, and
506  // we can not work with std::string_view objects
507  static_assert(std::tuple_size_v<Ranges> == 3);
508 
509  auto b = s.find_first_not_of(' ', std::tuple_element_t<0, Ranges>::min);
510 
511  if (b >= std::tuple_element_t<2, Ranges>::max)
512  return empty;
513 
514  auto value_sc = read_field<std::tuple_element_t<0, Ranges>>(out.value, s);
515  auto error_lower_sc =
516  read_field<std::tuple_element_t<1, Ranges>>(out.error_lower, s);
517  auto error_upper_sc =
518  read_field<std::tuple_element_t<2, Ranges>>(out.error_upper, s);
519 
520  if (value_sc == empty || error_lower_sc == empty || error_upper_sc == empty)
521  return failed; // either all are defined or none
522  else if (value_sc == failed || error_lower_sc == failed ||
523  error_upper_sc == failed)
524  return failed;
525  else
526  return success;
527  }
528 
530  template <class Field, class... Subfield> struct field_member_type {
531  using type =
533  };
534 
536  template <class Field> struct field_member_type<Field> {
538  };
539 
541  template <class Field, class... Subfield>
542  using field_member_type_t =
543  typename field_member_type<Field, Subfield...>::type;
544 
546  template <class T> std::string to_string(T const &v) {
547  return std::to_string(v);
548  }
549 
551  template <> std::string to_string(std::string const &v) { return v; }
552 } // namespace reactions::fields
constexpr auto const & operator()(T const &t) const
Definition: fields.hpp:244
value_and_errors(fill< Value, ErrorLower, ErrorUpper > &&f)
Build the class from a field constant expression.
Definition: fields.hpp:209
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:240
value_type error_squared() const
Calculate the squared error from the lower and upper errors.
Definition: fields.hpp:220
the conversion succeeded
Definition: fields.hpp:358
remove_optional_t< typename Field::value_type > type
Definition: fields.hpp:537
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:224
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:291
constexpr fill(Args &&... args)
Definition: fields.hpp:24
constexpr auto const & operator()(T const &t) const
Definition: fields.hpp:258
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:204
Contain the information whether a field is optional or not.
Definition: fields.hpp:83
Determine a returned type.
Definition: fields.hpp:278
T stof(T... args)
T to_string(T... args)
value_and_error_with_tag(Value value_, Error error_, TagType tag_)
Build the class with forwarded arguments.
Definition: fields.hpp:179
TagType tag
Internal tag.
Definition: fields.hpp:187
constexpr auto const & operator()(T const &t) const
Definition: fields.hpp:272
STL namespace.
the conversion failed
Definition: fields.hpp:360
Access the subtype of a set of fields.
Definition: fields.hpp:530
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:251
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:279
conversion_status string_to_type(std::string &out, std::string const &s)
Convert a range of characters to string.
Definition: fields.hpp:427
typename field_member_type< Field, Subfield... >::type field_member_type_t
Access the subtype of a set of fields.
Definition: fields.hpp:543
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
Field for an lower error.
Definition: fields.hpp:114
value_and_error_with_tag(fill< Value, Error, TagType > &&f)
Build the class from a field constant expression.
Definition: fields.hpp:183
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:327
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:265
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:359
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:504
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:357
Simple structure composed by a value and the lower and upper errors.
Definition: fields.hpp:191
value_and_error_with_tag()
Empty constructor.
Definition: fields.hpp:175
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:235
type_of_t< remove_optional_t< typename Field::value_type >, Subfield... > type
Definition: fields.hpp:532
T stoi(T... args)
static constexpr get_t< Field > get
Accessor to a value/error field.
Definition: fields.hpp:332
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:551