Skip to content
Snippets Groups Projects
Select Git revision
  • 8fac48c5df1cacfb4c9ab5fee9920f9027a34900
  • develop default protected
  • feature/advection
  • feature/composite-scheme-other-fluxes
  • origin/stage/bouguettaia
  • save_clemence
  • feature/local-dt-fsi
  • feature/variational-hydro
  • feature/gmsh-reader
  • feature/reconstruction
  • feature/kinetic-schemes
  • feature/composite-scheme-sources
  • feature/serraille
  • feature/composite-scheme
  • hyperplastic
  • feature/polynomials
  • feature/gks
  • feature/implicit-solver-o2
  • feature/coupling_module
  • feature/implicit-solver
  • feature/merge-local-dt-fsi
  • v0.5.0 protected
  • v0.4.1 protected
  • v0.4.0 protected
  • v0.3.0 protected
  • v0.2.0 protected
  • v0.1.0 protected
  • Kidder
  • v0.0.4 protected
  • v0.0.3 protected
  • v0.0.2 protected
  • v0 protected
  • v0.0.1 protected
33 results

FPEManager.cpp

Blame
  • BinaryExpressionProcessor.hpp 8.71 KiB
    #ifndef BINARY_EXPRESSION_PROCESSOR_HPP
    #define BINARY_EXPRESSION_PROCESSOR_HPP
    
    #include <language/PEGGrammar.hpp>
    #include <language/ast/ASTNode.hpp>
    #include <language/node_processor/INodeProcessor.hpp>
    #include <language/utils/ParseError.hpp>
    
    #include <type_traits>
    
    template <typename DataType>
    class DataHandler;
    
    template <typename Op>
    struct BinOp;
    
    template <>
    struct BinOp<language::and_op>
    {
      template <typename A, typename B>
      PUGS_INLINE auto
      eval(const A& a, const B& b) -> decltype(a and b)
      {
        return a and b;
      }
    };
    
    template <>
    struct BinOp<language::or_op>
    {
      template <typename A, typename B>
      PUGS_INLINE auto
      eval(const A& a, const B& b) -> decltype(a or b)
      {
        return a or b;
      }
    };
    
    template <>
    struct BinOp<language::xor_op>
    {
      // C++ xor returns bitwise xor integer. Here we want to just test if one and
      // only one of {a,b} is true so we enforce a bool cast
      template <typename A, typename B>
      PUGS_INLINE auto
      eval(const A& a, const B& b) -> bool
      {
        return a xor b;
      }
    };
    
    template <>
    struct BinOp<language::eqeq_op>
    {
      template <typename A, typename B>
      PUGS_INLINE auto
      eval(const A& a, const B& b) -> decltype(a == b)
      {
        return a == b;
      }
    };
    
    template <>
    struct BinOp<language::not_eq_op>
    {
      template <typename A, typename B>
      PUGS_INLINE auto
      eval(const A& a, const B& b) -> decltype(a != b)
      {
        return a != b;
      }
    };
    
    template <>
    struct BinOp<language::lesser_op>
    {
      template <typename A, typename B>
      PUGS_INLINE auto
      eval(const A& a, const B& b) -> decltype(a < b)
      {
        return a < b;
      }
    };
    
    class OStream;
    
    template <>
    struct BinOp<language::shift_left_op>
    {
      template <typename A, typename B>
      PUGS_INLINE auto
      eval(const A& a, const B& b) -> decltype(a << b)
      {
        if constexpr (std::is_same_v<A, std::shared_ptr<const OStream>> and std::is_same_v<B, bool>) {
          return a << std::boolalpha << b;
        } else {
          return a << b;
        }
      }
    };
    
    template <>
    struct BinOp<language::shift_right_op>
    {
      template <typename A, typename B>
      PUGS_INLINE auto
      eval(const A& a, const B& b) -> decltype(a >> b)
      {
        return a >> b;
      }
    };
    
    template <>
    struct BinOp<language::lesser_or_eq_op>
    {
      template <typename A, typename B>
      PUGS_INLINE auto
      eval(const A& a, const B& b) -> decltype(a <= b)
      {
        return a <= b;
      }
    };
    
    template <>
    struct BinOp<language::greater_op>
    {
      template <typename A, typename B>
      PUGS_INLINE auto
      eval(const A& a, const B& b) -> decltype(a > b)
      {
        return a > b;
      }
    };
    
    template <>
    struct BinOp<language::greater_or_eq_op>
    {
      template <typename A, typename B>
      PUGS_INLINE auto
      eval(const A& a, const B& b) -> decltype(a >= b)
      {
        return a >= b;
      }
    };
    
    template <>
    struct BinOp<language::plus_op>
    {
      template <typename A, typename B>
      PUGS_INLINE auto
      eval(const A& a, const B& b) -> decltype(a + b)
      {
        return a + b;
      }
    };
    
    template <>
    struct BinOp<language::minus_op>
    {
      template <typename A, typename B>
      PUGS_INLINE auto
      eval(const A& a, const B& b) -> decltype(a - b)
      {
        return a - b;
      }
    };
    
    template <>
    struct BinOp<language::multiply_op>
    {
      template <typename A, typename B>
      PUGS_INLINE auto
      eval(const A& a, const B& b) -> decltype(a * b)
      {
        return a * b;
      }
    };
    
    template <>
    struct BinOp<language::divide_op>
    {
      template <typename A, typename B>
      PUGS_INLINE auto
      eval(const A& a, const B& b) -> decltype(a / b)
      {
        return a / b;
      }
    };
    
    template <typename BinaryOpT, typename ValueT, typename A_DataT, typename B_DataT>
    struct BinaryExpressionProcessor final : public INodeProcessor
    {
     private:
      ASTNode& m_node;
    
      PUGS_INLINE DataVariant
      _eval(const DataVariant& a, const DataVariant& b)
      {
        if constexpr (std::is_arithmetic_v<A_DataT> and std::is_arithmetic_v<B_DataT>) {
          if constexpr (std::is_signed_v<A_DataT> and not std::is_signed_v<B_DataT>) {
            if constexpr (std::is_same_v<B_DataT, bool>) {
              return static_cast<ValueT>(
                BinOp<BinaryOpT>().eval(std::get<A_DataT>(a), static_cast<int64_t>(std::get<B_DataT>(b))));
            } else {
              return static_cast<ValueT>(
                BinOp<BinaryOpT>().eval(std::get<A_DataT>(a), std::make_signed_t<B_DataT>(std::get<B_DataT>(b))));
            }
    
          } else if constexpr (not std::is_signed_v<A_DataT> and std::is_signed_v<B_DataT>) {
            if constexpr (std::is_same_v<A_DataT, bool>) {
              return static_cast<ValueT>(
                BinOp<BinaryOpT>().eval(static_cast<int64_t>(std::get<A_DataT>(a)), std::get<B_DataT>(b)));
            } else {
              return static_cast<ValueT>(
                BinOp<BinaryOpT>().eval(std::make_signed_t<A_DataT>(std::get<A_DataT>(a)), std::get<B_DataT>(b)));
            }
          } else {
            return static_cast<ValueT>(BinOp<BinaryOpT>().eval(std::get<A_DataT>(a), std::get<B_DataT>(b)));
          }
        } else {
          return static_cast<ValueT>(BinOp<BinaryOpT>().eval(std::get<A_DataT>(a), std::get<B_DataT>(b)));
        }
      }
    
     public:
      DataVariant
      execute(ExecutionPolicy& exec_policy)
      {
        return this->_eval(m_node.children[0]->execute(exec_policy), m_node.children[1]->execute(exec_policy));
      }
    
      BinaryExpressionProcessor(ASTNode& node) : m_node{node} {}
    };
    
    template <typename BinaryOpT, typename ValueT, typename A_DataT, typename B_DataT>
    struct BinaryExpressionProcessor<BinaryOpT, std::shared_ptr<ValueT>, std::shared_ptr<A_DataT>, std::shared_ptr<B_DataT>>
      final : public INodeProcessor
    {
     private:
      ASTNode& m_node;
    
      PUGS_INLINE DataVariant
      _eval(const DataVariant& a, const DataVariant& b)
      {
        const auto& embedded_a = std::get<EmbeddedData>(a);
        const auto& embedded_b = std::get<EmbeddedData>(b);
    
        std::shared_ptr a_ptr = dynamic_cast<const DataHandler<A_DataT>&>(embedded_a.get()).data_ptr();
    
        std::shared_ptr b_ptr = dynamic_cast<const DataHandler<B_DataT>&>(embedded_b.get()).data_ptr();
    
        return EmbeddedData(std::make_shared<DataHandler<ValueT>>(BinOp<BinaryOpT>().eval(a_ptr, b_ptr)));
      }
    
     public:
      DataVariant
      execute(ExecutionPolicy& exec_policy)
      {
        try {
          return this->_eval(m_node.children[0]->execute(exec_policy), m_node.children[1]->execute(exec_policy));
        }
        catch (const NormalError& error) {
          throw ParseError(error.what(), m_node.begin());
        }
      }
    
      BinaryExpressionProcessor(ASTNode& node) : m_node{node} {}
    };
    
    template <typename BinaryOpT, typename ValueT, typename A_DataT, typename B_DataT>
    struct BinaryExpressionProcessor<BinaryOpT, std::shared_ptr<ValueT>, A_DataT, std::shared_ptr<B_DataT>> final
      : public INodeProcessor
    {
     private:
      ASTNode& m_node;
    
      PUGS_INLINE DataVariant
      _eval(const DataVariant& a, const DataVariant& b)
      {
        if constexpr ((std::is_arithmetic_v<A_DataT>) or (is_tiny_vector_v<A_DataT>) or (is_tiny_matrix_v<A_DataT>)) {
          const auto& a_value    = std::get<A_DataT>(a);
          const auto& embedded_b = std::get<EmbeddedData>(b);
    
          std::shared_ptr b_ptr = dynamic_cast<const DataHandler<B_DataT>&>(embedded_b.get()).data_ptr();
    
          return EmbeddedData(std::make_shared<DataHandler<ValueT>>(BinOp<BinaryOpT>().eval(a_value, b_ptr)));
        } else {
          static_assert(std::is_arithmetic_v<A_DataT>, "invalid left hand side type");
        }
      }
    
     public:
      DataVariant
      execute(ExecutionPolicy& exec_policy)
      {
        try {
          return this->_eval(m_node.children[0]->execute(exec_policy), m_node.children[1]->execute(exec_policy));
        }
        catch (const NormalError& error) {
          throw ParseError(error.what(), m_node.begin());
        }
      }
    
      BinaryExpressionProcessor(ASTNode& node) : m_node{node} {}
    };
    
    template <typename BinaryOpT, typename ValueT, typename A_DataT, typename B_DataT>
    struct BinaryExpressionProcessor<BinaryOpT, std::shared_ptr<ValueT>, std::shared_ptr<A_DataT>, B_DataT> final
      : public INodeProcessor
    {
     private:
      ASTNode& m_node;
    
      PUGS_INLINE DataVariant
      _eval(const DataVariant& a, const DataVariant& b)
      {
        if constexpr ((std::is_arithmetic_v<B_DataT>) or (is_tiny_matrix_v<B_DataT>) or (is_tiny_vector_v<B_DataT>) or
                      (std::is_same_v<std::string, B_DataT>)) {
          const auto& embedded_a = std::get<EmbeddedData>(a);
          const auto& b_value    = std::get<B_DataT>(b);
    
          std::shared_ptr a_ptr = dynamic_cast<const DataHandler<A_DataT>&>(embedded_a.get()).data_ptr();
    
          return EmbeddedData(std::make_shared<DataHandler<ValueT>>(BinOp<BinaryOpT>().eval(a_ptr, b_value)));
        } else {
          static_assert(std::is_arithmetic_v<B_DataT>, "invalid right hand side type");
        }
      }
    
     public:
      DataVariant
      execute(ExecutionPolicy& exec_policy)
      {
        try {
          return this->_eval(m_node.children[0]->execute(exec_policy), m_node.children[1]->execute(exec_policy));
        }
        catch (const NormalError& error) {
          throw ParseError(error.what(), m_node.begin());
        }
      }
    
      BinaryExpressionProcessor(ASTNode& node) : m_node{node} {}
    };
    
    #endif   // BINARY_EXPRESSION_PROCESSOR_HPP