diff --git a/src/language/modules/MathModule.cpp b/src/language/modules/MathModule.cpp
index 69f6890fbc5e8c3e3515901acd5b5102100e8c35..2217424e43bb9b276cf2260ce88c547252f88982 100644
--- a/src/language/modules/MathModule.cpp
+++ b/src/language/modules/MathModule.cpp
@@ -70,6 +70,18 @@ MathModule::MathModule()
   this->_addBuiltinFunction("round", std::make_shared<BuiltinFunctionEmbedder<int64_t(double)>>(
                                        [](double x) -> int64_t { return std::lround(x); }));
 
+  this->_addBuiltinFunction("min", std::make_shared<BuiltinFunctionEmbedder<double(double, double)>>(
+                                     [](double x, double y) -> double { return std::min(x, y); }));
+
+  this->_addBuiltinFunction("min", std::make_shared<BuiltinFunctionEmbedder<int64_t(int64_t, int64_t)>>(
+                                     [](int64_t x, int64_t y) -> int64_t { return std::min(x, y); }));
+
+  this->_addBuiltinFunction("max", std::make_shared<BuiltinFunctionEmbedder<double(double, double)>>(
+                                     [](double x, double y) -> double { return std::max(x, y); }));
+
+  this->_addBuiltinFunction("max", std::make_shared<BuiltinFunctionEmbedder<int64_t(int64_t, int64_t)>>(
+                                     [](int64_t x, int64_t y) -> int64_t { return std::max(x, y); }));
+
   this->_addBuiltinFunction("dot",
                             std::make_shared<BuiltinFunctionEmbedder<double(const TinyVector<1>, const TinyVector<1>)>>(
                               [](const TinyVector<1> x, const TinyVector<1> y) -> double { return dot(x, y); }));
diff --git a/tests/test_BuiltinFunctionProcessor.cpp b/tests/test_BuiltinFunctionProcessor.cpp
index a1fb3fe82b982bc50d2b5247c1158941da24ce0d..bbc5ac52e1a6e8034b68b591adff83c1d8701ff5 100644
--- a/tests/test_BuiltinFunctionProcessor.cpp
+++ b/tests/test_BuiltinFunctionProcessor.cpp
@@ -278,6 +278,42 @@ let z:Z, z = round(-1.2);
       CHECK_BUILTIN_FUNCTION_EVALUATION_RESULT(data, "z", int64_t{-1});
     }
 
+    {   // min
+      tested_function_set.insert("min:R*R");
+      std::string_view data = R"(
+import math;
+let x:R, x = min(-2,2.3);
+)";
+      CHECK_BUILTIN_FUNCTION_EVALUATION_RESULT(data, "x", double{-2});
+    }
+
+    {   // min
+      tested_function_set.insert("min:Z*Z");
+      std::string_view data = R"(
+import math;
+let z:Z, z = min(-1,2);
+)";
+      CHECK_BUILTIN_FUNCTION_EVALUATION_RESULT(data, "z", int64_t{-1});
+    }
+
+    {   // max
+      tested_function_set.insert("max:R*R");
+      std::string_view data = R"(
+import math;
+let x:R, x = max(-1,2.3);
+)";
+      CHECK_BUILTIN_FUNCTION_EVALUATION_RESULT(data, "x", double{2.3});
+    }
+
+    {   // max
+      tested_function_set.insert("max:Z*Z");
+      std::string_view data = R"(
+import math;
+let z:Z, z = max(-1,2);
+)";
+      CHECK_BUILTIN_FUNCTION_EVALUATION_RESULT(data, "z", int64_t{2});
+    }
+
     {   // dot
       tested_function_set.insert("dot:R^1*R^1");
       std::string_view data = R"(
diff --git a/tests/test_MathModule.cpp b/tests/test_MathModule.cpp
index 7c2a9bc5438367b7f3cf70d14d3b8acc58a29ae7..4d71927f13d3229d450c941250bb4202d071b109 100644
--- a/tests/test_MathModule.cpp
+++ b/tests/test_MathModule.cpp
@@ -15,7 +15,7 @@ TEST_CASE("MathModule", "[language]")
   MathModule math_module;
   const auto& name_builtin_function = math_module.getNameBuiltinFunctionMap();
 
-  REQUIRE(name_builtin_function.size() == 25);
+  REQUIRE(name_builtin_function.size() == 29);
 
   SECTION("double -> double")
   {
@@ -323,6 +323,63 @@ TEST_CASE("MathModule", "[language]")
       auto result = std::pow(arg0, arg1);
       REQUIRE(std::get<decltype(result)>(result_variant) == Catch::Approx(result));
     }
+
+    SECTION("min")
+    {
+      auto i_function = name_builtin_function.find("min:R*R");
+      REQUIRE(i_function != name_builtin_function.end());
+
+      IBuiltinFunctionEmbedder& function_embedder = *i_function->second;
+      DataVariant result_variant                  = function_embedder.apply({arg0_variant, arg1_variant});
+
+      auto result = std::min(arg0, arg1);
+      REQUIRE(std::get<decltype(result)>(result_variant) == Catch::Approx(result));
+    }
+
+    SECTION("max")
+    {
+      auto i_function = name_builtin_function.find("max:R*R");
+      REQUIRE(i_function != name_builtin_function.end());
+
+      IBuiltinFunctionEmbedder& function_embedder = *i_function->second;
+      DataVariant result_variant                  = function_embedder.apply({arg0_variant, arg1_variant});
+
+      auto result = std::max(arg0, arg1);
+      REQUIRE(std::get<decltype(result)>(result_variant) == Catch::Approx(result));
+    }
+  }
+
+  SECTION("(uint64_t, uint64_t) -> uint64_t")
+  {
+    int64_t arg0 = 3;
+    int64_t arg1 = -2;
+
+    DataVariant arg0_variant = arg0;
+    DataVariant arg1_variant = arg1;
+
+    SECTION("min")
+    {
+      auto i_function = name_builtin_function.find("min:Z*Z");
+      REQUIRE(i_function != name_builtin_function.end());
+
+      IBuiltinFunctionEmbedder& function_embedder = *i_function->second;
+      DataVariant result_variant                  = function_embedder.apply({arg0_variant, arg1_variant});
+
+      auto result = std::min(arg0, arg1);
+      REQUIRE(std::get<decltype(result)>(result_variant) == Catch::Approx(result));
+    }
+
+    SECTION("max")
+    {
+      auto i_function = name_builtin_function.find("max:Z*Z");
+      REQUIRE(i_function != name_builtin_function.end());
+
+      IBuiltinFunctionEmbedder& function_embedder = *i_function->second;
+      DataVariant result_variant                  = function_embedder.apply({arg0_variant, arg1_variant});
+
+      auto result = std::max(arg0, arg1);
+      REQUIRE(std::get<decltype(result)>(result_variant) == Catch::Approx(result));
+    }
   }
 
   SECTION("(R^d, R^d) -> double")