| Line | Branch | Exec | Source | 
|---|---|---|---|
| 1 | #pragma once | ||
| 2 | |||
| 3 | #ifndef REAL_TYPE | ||
| 4 | #define REAL_TYPE double | ||
| 5 | #endif | ||
| 6 | |||
| 7 | #ifndef DIM | ||
| 8 | #define DIM 3 | ||
| 9 | #endif | ||
| 10 | |||
| 11 | #include <eigen3/Eigen/Dense> | ||
| 12 | #include <yaml-cpp/yaml.h> | ||
| 13 | |||
| 14 | using Real = REAL_TYPE; | ||
| 15 | using Vec = Eigen::Matrix<Real, DIM, 1>; | ||
| 16 | using VecVec = Eigen::Matrix<Real, DIM, Eigen::Dynamic>; | ||
| 17 | using ArrayI = Eigen::Array<int, DIM, 1>; | ||
| 18 | |||
| 19 | /** | ||
| 20 | * Get the minimum image vector from position r1 to r2 with respect to a box of size L. | ||
| 21 | */ | ||
| 22 | 695205614 | inline Vec r_ij(const Vec &L, const Vec &r1, const Vec &r2) { | |
| 23 | 695205614 | Vec result; | |
| 24 | 695205614 | result = r2 - r1; | |
| 25 | 695205614 | result.array() -= (result.array() / L.array()).round() * L.array(); | |
| 26 | 695205614 | return result; | |
| 27 | } | ||
| 28 | |||
| 29 | namespace YAML { | ||
| 30 | |||
| 31 | // The following enables yaml-cpp to natively encode and decode Eigen matrices and arrays. | ||
| 32 | // For example, one can now use node[key].as<Vec>() | ||
| 33 | template <template <typename, int...> class EigenClass, typename Scalar, int d> | ||
| 34 | struct convert<EigenClass<Scalar, d, 1>> { | ||
| 35 | 20 | static Node encode(const EigenClass<Scalar, d, 1> &rhs) { | |
| 36 | 20 | Node node; | |
| 37 | 
        2/2✓ Branch 0 taken 60 times. 
          ✓ Branch 1 taken 20 times. 
         | 
      80 | for (int i = 0; i < d; ++i) { | 
| 38 | 
        1/2✓ Branch 2 taken 60 times. 
          ✗ Branch 3 not taken. 
         | 
      60 | node.push_back(rhs[i]); | 
| 39 | } | ||
| 40 | 20 | return node; | |
| 41 | } | ||
| 42 | |||
| 43 | 110 | static bool decode(const Node &node, EigenClass<Scalar, d, 1> &rhs) { | |
| 44 | 
        2/4✓ Branch 0 taken 106 times. 
          ✗ Branch 1 not taken. 
          ✗ Branch 3 not taken. 
          ✓ Branch 4 taken 106 times. 
         | 
      110 | if (!node.IsSequence() || node.size() != d) { | 
| 45 | ✗ | return false; | |
| 46 | } | ||
| 47 | |||
| 48 | 
        2/2✓ Branch 0 taken 318 times. 
          ✓ Branch 1 taken 106 times. 
         | 
      440 | for (int i = 0; i < d; ++i) { | 
| 49 | 
        1/2✓ Branch 2 taken 318 times. 
          ✗ Branch 3 not taken. 
         | 
      330 | rhs[i] = node[i].as<Scalar>(); | 
| 50 | } | ||
| 51 | 110 | return true; | |
| 52 | } | ||
| 53 | }; | ||
| 54 | |||
| 55 | // This helper class is needed because C++ forbids partial specialization of functions. | ||
| 56 | // In our case, we want to specialize the parse function to generic Eigen types. | ||
| 57 | template <typename ReturnT, typename DefaultT = ReturnT> struct ParseHelper { | ||
| 58 | 
        1/2✓ Branch 2 taken 484 times. 
          ✗ Branch 3 not taken. 
         | 
      968 | ReturnT operator()(const Node &node, const std::string &key) { return node[key].as<ReturnT>(); } | 
| 59 | 1468 | ReturnT operator()(const Node &node, const std::string &key, DefaultT defaultValue) { | |
| 60 | 
        4/6✓ Branch 1 taken 416 times. 
          ✓ Branch 2 taken 318 times. 
          ✓ Branch 4 taken 416 times. 
          ✗ Branch 5 not taken. 
          ✓ Branch 7 taken 58 times. 
          ✗ Branch 8 not taken. 
         | 
      1468 | return node[key] ? (*this)(node, key) : defaultValue; | 
| 61 | } | ||
| 62 | }; | ||
| 63 | |||
| 64 | template <template <typename, int...> class EigenClass, typename Scalar1, int d, typename Scalar2> | ||
| 65 | struct ParseHelper<EigenClass<Scalar1, d, 1>, Scalar2> { | ||
| 66 | 144 | EigenClass<Scalar1, d, 1> operator()(const Node &node, const std::string &key) { | |
| 67 | 
        4/6✓ Branch 1 taken 31 times. 
          ✓ Branch 2 taken 106 times. 
          ✓ Branch 4 taken 31 times. 
          ✗ Branch 5 not taken. 
          ✓ Branch 7 taken 31 times. 
          ✗ Branch 8 not taken. 
         | 
      432 | return node[key].IsScalar() ? EigenClass<Scalar1, d, 1>::Constant(node[key].as<Scalar1>()) | 
| 68 | 
        4/7✓ Branch 3 taken 106 times. 
          ✗ Branch 4 not taken. 
          ✓ Branch 6 taken 106 times. 
          ✗ Branch 7 not taken. 
          ✓ Branch 9 taken 31 times. 
          ✓ Branch 10 taken 106 times. 
          ✗ Branch 13 not taken. 
         | 
      288 | : node[key].as<EigenClass<Scalar1, d, 1>>(); | 
| 69 | } | ||
| 70 | 84 | EigenClass<Scalar1, d, 1> operator()(const Node &node, const std::string &key, | |
| 71 | Scalar2 defaultValue) { | ||
| 72 | 
        3/4✓ Branch 1 taken 55 times. 
          ✓ Branch 2 taken 29 times. 
          ✓ Branch 4 taken 55 times. 
          ✗ Branch 5 not taken. 
         | 
      113 | return node[key] ? (*this)(node, key) : EigenClass<Scalar1, d, 1>::Constant(defaultValue); | 
| 73 | } | ||
| 74 | }; | ||
| 75 | |||
| 76 | template <template <typename, int...> class EigenClass, typename Scalar1, int d, | ||
| 77 | template <typename, int...> class EigenClass2, typename Scalar2> | ||
| 78 | struct ParseHelper<EigenClass<Scalar1, d, 1>, EigenClass2<Scalar2, d, 1>> { | ||
| 79 | 82 | EigenClass<Scalar1, d, 1> operator()(const Node &node, const std::string &key) { | |
| 80 | 164 | return ParseHelper<EigenClass<Scalar1, d, 1>, Scalar1>{}(node, key); | |
| 81 | } | ||
| 82 | EigenClass<Scalar1, d, 1> operator()(const Node &node, const std::string &key, | ||
| 83 | EigenClass2<Scalar2, d, 1> defaultValue) { | ||
| 84 | return node[key] ? (*this)(node, key) : EigenClass<Scalar1, d, 1>(defaultValue); | ||
| 85 | } | ||
| 86 | }; | ||
| 87 | |||
| 88 | // Two helper methods are provided for easy and consistent parsing of yaml nodes (with and without | ||
| 89 | // setting defaults) | ||
| 90 | 300 | template <typename ReturnT> auto parse(const Node &node, const std::string &key) { | |
| 91 | 300 | return ParseHelper<ReturnT>{}(node, key); | |
| 92 | } | ||
| 93 | |||
| 94 | template <typename ReturnT, typename DefaultT> | ||
| 95 | 818 | auto parse(const Node &node, const std::string &key, DefaultT defaultValue) { | |
| 96 | 818 | return ParseHelper<ReturnT, DefaultT>{}(node, key, defaultValue); | |
| 97 | } | ||
| 98 | |||
| 99 | } // namespace YAML | ||
| 100 |