Skip to content
Snippets Groups Projects
Select Git revision
  • 4e32168f5c1a3c860afb0c559547ffbbcd3e15f6
  • develop default protected
  • feature/gmsh-reader
  • origin/stage/bouguettaia
  • feature/kinetic-schemes
  • feature/reconstruction
  • feature/local-dt-fsi
  • feature/composite-scheme-sources
  • feature/composite-scheme-other-fluxes
  • feature/serraille
  • feature/variational-hydro
  • feature/composite-scheme
  • hyperplastic
  • feature/polynomials
  • feature/gks
  • feature/implicit-solver-o2
  • feature/coupling_module
  • feature/implicit-solver
  • feature/merge-local-dt-fsi
  • master protected
  • feature/escobar-smoother
  • 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

test_BuiltinFunctionEmbedder.cpp

Blame
  • test_BuiltinFunctionEmbedder.cpp 15.63 KiB
    #include <catch2/catch_test_macros.hpp>
    #include <catch2/matchers/catch_matchers_all.hpp>
    
    #include <language/utils/BuiltinFunctionEmbedder.hpp>
    
    // clazy:excludeall=non-pod-global-static
    
    template <>
    inline ASTNodeDataType ast_node_data_type_from<std::shared_ptr<const double>> =
      ASTNodeDataType::build<ASTNodeDataType::type_id_t>("shared_const_double");
    
    template <>
    inline ASTNodeDataType ast_node_data_type_from<std::shared_ptr<double>> =
      ASTNodeDataType::build<ASTNodeDataType::type_id_t>("shared_double");
    
    template <>
    inline ASTNodeDataType ast_node_data_type_from<std::shared_ptr<uint64_t>> =
      ASTNodeDataType::build<ASTNodeDataType::type_id_t>("shared_uint64_t");
    
    TEST_CASE("BuiltinFunctionEmbedder", "[language]")
    {
      rang::setControlMode(rang::control::Off);
    
      SECTION("math")
      {
        BuiltinFunctionEmbedder<double(double)> embedded_sin{[](double x) -> double { return std::sin(x); }};
    
        double arg              = 2;
        DataVariant arg_variant = arg;
    
        DataVariant result = embedded_sin.apply({arg_variant});
    
        REQUIRE(std::get<double>(result) == std::sin(arg));
        REQUIRE(embedded_sin.numberOfParameters() == 1);
    
        REQUIRE(embedded_sin.getReturnDataType() == ASTNodeDataType::double_t);
        REQUIRE(embedded_sin.getParameterDataTypes()[0] == ASTNodeDataType::double_t);
      }
    
      SECTION("multiple variant args")
      {
        std::function c = [](double x, uint64_t i) -> bool { return x > i; };
    
        BuiltinFunctionEmbedder<bool(double, uint64_t)> embedded_c{c};
    
        double d_arg   = 2.3;
        uint64_t i_arg = 3;
    
        std::vector<DataVariant> args;
        args.push_back(d_arg);
        args.push_back(i_arg);
    
        DataVariant result = embedded_c.apply(args);
    
        REQUIRE(std::get<bool>(result) == c(d_arg, i_arg));
        REQUIRE(embedded_c.numberOfParameters() == 2);
    
        REQUIRE(embedded_c.getReturnDataType() == ASTNodeDataType::bool_t);
        REQUIRE(embedded_c.getParameterDataTypes()[0] == ASTNodeDataType::double_t);
        REQUIRE(embedded_c.getParameterDataTypes()[1] == ASTNodeDataType::unsigned_int_t);
      }
    
      SECTION("R*R^2 -> R^2")
      {
        std::function c = [](double a, TinyVector<2> x) -> TinyVector<2> { return a * x; };
    
        BuiltinFunctionEmbedder<TinyVector<2>(double, TinyVector<2>)> embedded_c{c};
    
        double a_arg = 2.3;
        TinyVector<2> x_arg{3, 2};
    
        std::vector<DataVariant> args;
        args.push_back(a_arg);
        args.push_back(x_arg);
    
        DataVariant result = embedded_c.apply(args);
    
        REQUIRE(std::get<TinyVector<2>>(result) == c(a_arg, x_arg));
        REQUIRE(embedded_c.numberOfParameters() == 2);
    
        REQUIRE(embedded_c.getReturnDataType() == ASTNodeDataType::vector_t);
        REQUIRE(embedded_c.getParameterDataTypes()[0] == ASTNodeDataType::double_t);
        REQUIRE(embedded_c.getParameterDataTypes()[1] == ASTNodeDataType::vector_t);
      }
    
      SECTION("R^2x2*R^2 -> R^2")
      {
        std::function c = [](TinyMatrix<2> A, TinyVector<2> x) -> TinyVector<2> { return A * x; };
    
        BuiltinFunctionEmbedder<TinyVector<2>(TinyMatrix<2>, TinyVector<2>)> embedded_c{c};
    
        TinyMatrix<2> a_arg = {2.3, 1, -2, 3};
        TinyVector<2> x_arg{3, 2};
    
        std::vector<DataVariant> args;
        args.push_back(a_arg);
        args.push_back(x_arg);
    
        DataVariant result = embedded_c.apply(args);
    
        REQUIRE(std::get<TinyVector<2>>(result) == c(a_arg, x_arg));
        REQUIRE(embedded_c.numberOfParameters() == 2);
    
        REQUIRE(embedded_c.getReturnDataType() == ASTNodeDataType::vector_t);
        REQUIRE(embedded_c.getParameterDataTypes()[0] == ASTNodeDataType::matrix_t);
        REQUIRE(embedded_c.getParameterDataTypes()[1] == ASTNodeDataType::vector_t);
      }
    
      SECTION("POD BuiltinFunctionEmbedder")
      {
        std::function c = [](double x, uint64_t i) -> bool { return x > i; };
    
        std::unique_ptr<IBuiltinFunctionEmbedder> i_embedded_c =
          std::make_unique<BuiltinFunctionEmbedder<bool(double, uint64_t)>>(c);
    
        double d_arg   = 2.3;
        uint64_t i_arg = 3;
    
        std::vector<DataVariant> args;
        args.push_back(d_arg);
        args.push_back(i_arg);
    
        DataVariant result = i_embedded_c->apply(args);
    
        REQUIRE(std::get<bool>(result) == c(d_arg, i_arg));
        REQUIRE(i_embedded_c->numberOfParameters() == 2);
    
        REQUIRE(i_embedded_c->getReturnDataType() == ASTNodeDataType::bool_t);
        REQUIRE(i_embedded_c->getParameterDataTypes()[0] == ASTNodeDataType::double_t);
        REQUIRE(i_embedded_c->getParameterDataTypes()[1] == ASTNodeDataType::unsigned_int_t);
      }
    
      SECTION("void(double) BuiltinFunctionEmbedder")
      {
        double y = 1;
    
        std::function add_to_y = [&](double x) -> void { y += x; };
    
        std::unique_ptr<IBuiltinFunctionEmbedder> i_embedded_c =
          std::make_unique<BuiltinFunctionEmbedder<void(double)>>(add_to_y);
    
        double x = 0.5;
        i_embedded_c->apply(std::vector<DataVariant>{x});
        REQUIRE(y == 1.5);
        REQUIRE(i_embedded_c->numberOfParameters() == 1);
        REQUIRE(i_embedded_c->getParameterDataTypes().size() == 1);
    
        REQUIRE(i_embedded_c->getReturnDataType() == ASTNodeDataType::void_t);
    
        REQUIRE_THROWS_WITH(i_embedded_c->apply({std::vector<EmbeddedData>{}}),
                            "unexpected error: unexpected argument types while casting \"" +
                              demangle<std::vector<EmbeddedData>>() + "\" to \"" + demangle<double>() + '"');
      }
    
      SECTION("EmbeddedData(double, double) BuiltinFunctionEmbedder")
      {
        std::function sum = [&](double x, double y) -> std::shared_ptr<const double> {
          return std::make_shared<const double>(x + y);
        };
    
        std::unique_ptr<IBuiltinFunctionEmbedder> i_embedded_c =
          std::make_unique<BuiltinFunctionEmbedder<std::shared_ptr<const double>(double, double)>>(sum);
    
        // using 4ul enforces cast test
        REQUIRE(i_embedded_c->numberOfParameters() == 2);
        REQUIRE(i_embedded_c->getParameterDataTypes().size() == 2);
        REQUIRE(i_embedded_c->getParameterDataTypes()[0] == ASTNodeDataType::double_t);
        REQUIRE(i_embedded_c->getParameterDataTypes()[1] == ASTNodeDataType::double_t);
    
        REQUIRE(i_embedded_c->getReturnDataType() == ast_node_data_type_from<std::shared_ptr<const double>>);
    
        DataVariant result         = i_embedded_c->apply(std::vector<DataVariant>{2.3, 4ul});
        EmbeddedData embedded_data = std::get<EmbeddedData>(result);
    
        const IDataHandler& handled_data      = embedded_data.get();
        const DataHandler<const double>& data = dynamic_cast<const DataHandler<const double>&>(handled_data);
        REQUIRE(*data.data_ptr() == (2.3 + 4ul));
      }
    
      SECTION("double(std::shared_ptr<double>) BuiltinFunctionEmbedder")
      {
        std::function abs = [&](std::shared_ptr<const double> x) -> double { return std::abs(*x); };
    
        std::unique_ptr<IBuiltinFunctionEmbedder> i_embedded_c =
          std::make_unique<BuiltinFunctionEmbedder<double(std::shared_ptr<const double>)>>(abs);
    
        REQUIRE(i_embedded_c->numberOfParameters() == 1);
        REQUIRE(i_embedded_c->getParameterDataTypes().size() == 1);
        REQUIRE(i_embedded_c->getParameterDataTypes()[0] == ast_node_data_type_from<std::shared_ptr<const double>>);
        REQUIRE(i_embedded_c->getReturnDataType() == ASTNodeDataType::double_t);
    
        EmbeddedData data(std::make_shared<DataHandler<const double>>(std::make_shared<const double>(-2.3)));
        DataVariant result = i_embedded_c->apply({data});
    
        REQUIRE(std::get<double>(result) == 2.3);
    
        REQUIRE_THROWS_WITH(i_embedded_c->apply({2.3}),
                            "unexpected error: unexpected argument types while casting: expecting EmbeddedData");
    
        EmbeddedData wrong_embedded_data_type(
          std::make_shared<DataHandler<const TinyVector<2>>>(std::make_shared<const TinyVector<2>>(-2, -2)));
        REQUIRE_THROWS_WITH(i_embedded_c->apply({wrong_embedded_data_type}),
                            "unexpected error: unexpected argument types while casting: "
                            "invalid EmbeddedData type, expecting " +
                              demangle<DataHandler<const double>>());
      }
    
      SECTION("uint64_t(std::vector<uint64_t>) BuiltinFunctionEmbedder")
      {
        std::function sum = [&](const std::vector<uint64_t>& x) -> uint64_t {
          uint64_t sum = 0;
          for (size_t i = 0; i < x.size(); ++i) {
            sum += x[i];
          }
          return sum;
        };
    
        std::unique_ptr<IBuiltinFunctionEmbedder> i_embedded_c =
          std::make_unique<BuiltinFunctionEmbedder<uint64_t(const std::vector<uint64_t>&)>>(sum);
    
        REQUIRE(i_embedded_c->numberOfParameters() == 1);
        REQUIRE(i_embedded_c->getParameterDataTypes().size() == 1);
        REQUIRE(i_embedded_c->getParameterDataTypes()[0] == ASTNodeDataType::tuple_t);
        REQUIRE(i_embedded_c->getReturnDataType() == ASTNodeDataType::unsigned_int_t);
    
        REQUIRE(std::get<uint64_t>(i_embedded_c->apply({std::vector{1ul, 2ul, 3ul}})) == 6);
        REQUIRE(std::get<uint64_t>(i_embedded_c->apply({std::vector{1ul, 2ul, 3ul, 4ul}})) == 10);
    
        REQUIRE_THROWS_WITH(i_embedded_c->apply({std::vector{1.2, 2.3, 3.1, 4.4}}),
                            "unexpected error: unexpected argument types while casting \"" +
                              demangle<std::vector<double>>() + "\" to \"" + demangle<std::vector<uint64_t>>() + '"');
    
        REQUIRE_THROWS_WITH(i_embedded_c->apply({std::vector<EmbeddedData>{}}),
                            "unexpected error: unexpected argument types while casting \"" +
                              demangle<std::vector<EmbeddedData>>() + "\" to \"" + demangle<std::vector<uint64_t>>() + '"');
      }
    
      SECTION("uint64_t(std::vector<EmbeddedData>) BuiltinFunctionEmbedder")
      {
        std::function sum = [&](const std::vector<std::shared_ptr<uint64_t>>& x) -> uint64_t {
          uint64_t sum = 0;
          for (size_t i = 0; i < x.size(); ++i) {
            sum += *x[i];
          }
          return sum;
        };
    
        std::unique_ptr<IBuiltinFunctionEmbedder> i_embedded_c =
          std::make_unique<BuiltinFunctionEmbedder<uint64_t(const std::vector<std::shared_ptr<uint64_t>>&)>>(sum);
    
        REQUIRE(i_embedded_c->numberOfParameters() == 1);
        REQUIRE(i_embedded_c->getParameterDataTypes().size() == 1);
        REQUIRE(i_embedded_c->getParameterDataTypes()[0] == ASTNodeDataType::tuple_t);
        REQUIRE(i_embedded_c->getReturnDataType() == ASTNodeDataType::unsigned_int_t);
    
        std::vector<EmbeddedData> embedded_data;
        REQUIRE(std::get<uint64_t>(i_embedded_c->apply({embedded_data})) == 0);
        embedded_data.emplace_back(std::make_shared<DataHandler<uint64_t>>(std::make_shared<uint64_t>(1)));
        embedded_data.emplace_back(std::make_shared<DataHandler<uint64_t>>(std::make_shared<uint64_t>(2)));
        embedded_data.emplace_back(std::make_shared<DataHandler<uint64_t>>(std::make_shared<uint64_t>(3)));
    
        REQUIRE(std::get<uint64_t>(i_embedded_c->apply({embedded_data})) == 6);
    
        embedded_data.emplace_back(std::make_shared<DataHandler<double>>(std::make_shared<double>(4)));
        REQUIRE_THROWS_WITH(i_embedded_c->apply({embedded_data}),
                            "unexpected error: unexpected argument types while casting: invalid"
                            " EmbeddedData type, expecting " +
                              demangle<DataHandler<uint64_t>>());
    
        REQUIRE_THROWS_WITH(i_embedded_c->apply({TinyVector<1>{13}}),
                            "unexpected error: unexpected argument types while casting \"" + demangle<TinyVector<1>>() +
                              "\" to \"" + demangle<std::vector<std::shared_ptr<uint64_t>>>() + '"');
      }
    
      SECTION("double(void) BuiltinFunctionEmbedder")
      {
        std::function c = [](void) -> double { return 1.5; };
    
        std::unique_ptr<IBuiltinFunctionEmbedder> i_embedded_c = std::make_unique<BuiltinFunctionEmbedder<double(void)>>(c);
    
        REQUIRE(1.5 == c());
        REQUIRE(std::get<double>(i_embedded_c->apply(std::vector<DataVariant>{})) == c());
        REQUIRE(i_embedded_c->numberOfParameters() == 0);
        REQUIRE(i_embedded_c->getParameterDataTypes().size() == 0);
    
        REQUIRE(i_embedded_c->getReturnDataType() == ASTNodeDataType::double_t);
      }
    
      SECTION("R*R -> R*R^2*shared_double BuiltinFunctionEmbedder")
      {
        std::function c = [](double a, double b) -> std::tuple<double, TinyVector<2>, std::shared_ptr<double>> {
          return std::make_tuple(a + b, TinyVector<2>{b, -a}, std::make_shared<double>(a - b));
        };
    
        std::unique_ptr<IBuiltinFunctionEmbedder> i_embedded_c = std::make_unique<
          BuiltinFunctionEmbedder<std::tuple<double, TinyVector<2>, std::shared_ptr<double>>(double, double)>>(c);
    
        const double a = 3.2;
        const double b = 1.5;
    
        REQUIRE(a + b == std::get<0>(c(a, b)));
        REQUIRE(TinyVector<2>{b, -a} == std::get<1>(c(a, b)));
        REQUIRE(a - b == *std::get<2>(c(a, b)));
        const AggregateDataVariant value_list =
          std::get<AggregateDataVariant>(i_embedded_c->apply(std::vector<DataVariant>{a, b}));
    
        REQUIRE(std::get<double>(value_list[0]) == a + b);
        REQUIRE(std::get<TinyVector<2>>(value_list[1]) == TinyVector<2>{b, -a});
        auto data_type = i_embedded_c->getReturnDataType();
        REQUIRE(data_type == ASTNodeDataType::list_t);
    
        REQUIRE(*data_type.contentTypeList()[0] == ASTNodeDataType::double_t);
        REQUIRE(*data_type.contentTypeList()[1] == ASTNodeDataType::build<ASTNodeDataType::vector_t>(2));
        REQUIRE(*data_type.contentTypeList()[2] == ast_node_data_type_from<std::shared_ptr<double>>);
      }
    
      SECTION("void -> N*R*shared_double BuiltinFunctionEmbedder")
      {
        std::function c = [](void) -> std::tuple<uint64_t, double, std::shared_ptr<double>> {
          uint64_t a = 1;
          double b   = 3.5;
          return std::make_tuple(a, b, std::make_shared<double>(a + b));
        };
    
        std::unique_ptr<IBuiltinFunctionEmbedder> i_embedded_c =
          std::make_unique<BuiltinFunctionEmbedder<std::tuple<uint64_t, double, std::shared_ptr<double>>(void)>>(c);
    
        REQUIRE(1ul == std::get<0>(c()));
        REQUIRE(3.5 == std::get<1>(c()));
        REQUIRE((1ul + 3.5) == *std::get<2>(c()));
        const AggregateDataVariant value_list =
          std::get<AggregateDataVariant>(i_embedded_c->apply(std::vector<DataVariant>{}));
    
        REQUIRE(std::get<uint64_t>(value_list[0]) == 1ul);
        REQUIRE(std::get<double>(value_list[1]) == 3.5);
    
        auto data_type = i_embedded_c->getReturnDataType();
        REQUIRE(data_type == ASTNodeDataType::list_t);
    
        REQUIRE(*data_type.contentTypeList()[0] == ASTNodeDataType::unsigned_int_t);
        REQUIRE(*data_type.contentTypeList()[1] == ASTNodeDataType::double_t);
        REQUIRE(*data_type.contentTypeList()[2] == ast_node_data_type_from<std::shared_ptr<double>>);
      }
    
      SECTION("void(void) BuiltinFunctionEmbedder")
      {
        std::function c = [](void) -> void {};
    
        std::unique_ptr<IBuiltinFunctionEmbedder> i_embedded_c = std::make_unique<BuiltinFunctionEmbedder<void(void)>>(c);
    
        REQUIRE_NOTHROW(std::get<std::monostate>(i_embedded_c->apply(std::vector<DataVariant>{})));
        REQUIRE(i_embedded_c->numberOfParameters() == 0);
        REQUIRE(i_embedded_c->getParameterDataTypes().size() == 0);
    
        REQUIRE(i_embedded_c->getReturnDataType() == ASTNodeDataType::void_t);
      }
    
      SECTION("EmbeddedData(void) BuiltinFunctionEmbedder")
      {
        std::function c = [](void) -> std::shared_ptr<double> { return std::make_shared<double>(1.5); };
    
        std::unique_ptr<IBuiltinFunctionEmbedder> i_embedded_c =
          std::make_unique<BuiltinFunctionEmbedder<std::shared_ptr<double>(void)>>(c);
    
        REQUIRE(i_embedded_c->numberOfParameters() == 0);
        REQUIRE(i_embedded_c->getParameterDataTypes().size() == 0);
    
        REQUIRE(i_embedded_c->getReturnDataType() == ast_node_data_type_from<std::shared_ptr<double>>);
    
        const auto embedded_data         = std::get<EmbeddedData>(i_embedded_c->apply(std::vector<DataVariant>{}));
        const IDataHandler& handled_data = embedded_data.get();
        const DataHandler<double>& data  = dynamic_cast<const DataHandler<double>&>(handled_data);
        REQUIRE(*data.data_ptr() == 1.5);
      }
    
      SECTION("error")
      {
        std::function positive = [](double x) -> bool { return x >= 0; };
    
        BuiltinFunctionEmbedder<bool(double)> embedded_positive{positive};
    
        std::string arg = std::string{"2.3"};
    
        std::vector<DataVariant> args;
        args.push_back(arg);
    
        REQUIRE_THROWS(embedded_positive.apply(args));
      }
    }