diff --git a/include/etl/ratio.h b/include/etl/ratio.h
index 8c7fa81d9..1035e7741 100644
--- a/include/etl/ratio.h
+++ b/include/etl/ratio.h
@@ -33,6 +33,8 @@ SOFTWARE.
 
 #include "platform.h"
 
+#include "type_traits.h"
+
 #include <stddef.h>
 #include <stdint.h>
 
@@ -41,17 +43,17 @@ SOFTWARE.
 
 namespace etl
 {
-  template <size_t NUM, size_t DEN = 1UL>
+  template <intmax_t NUM, intmax_t DEN = 1UL>
   struct ratio
   {
     static ETL_CONSTANT intmax_t num = NUM;
     static ETL_CONSTANT intmax_t den = DEN;
   };
 
-  template <size_t NUM, size_t DEN>
+  template <intmax_t NUM, intmax_t DEN>
   ETL_CONSTANT intmax_t ratio<NUM, DEN>::num;
 
-  template <size_t NUM, size_t DEN>
+  template <intmax_t NUM, intmax_t DEN>
   ETL_CONSTANT intmax_t ratio<NUM, DEN>::den;
 
   #if INT_MAX > INT32_MAX
@@ -97,6 +99,153 @@ namespace etl
 
   /// An approximation of e.
   typedef ratio<326, 120> ratio_e;
+
+#if ETL_USING_CPP11
+  namespace private_ratio
+  {
+    // Primary template for GCD calculation
+    template <typename T, T A, T B, bool = (B == 0)>
+    struct ratio_gcd;
+
+    // Specialisation for the case when B is not zero
+    template <typename T, T A, T B>
+    struct ratio_gcd<T, A, B, false>
+    {
+      static constexpr T value = ratio_gcd<T, B, A % B>::value;
+    };
+
+    // Specialisation for the case when B is zero
+    template <typename T, T A, T B>
+    struct ratio_gcd<T, A, B, true>
+    {
+      static constexpr T value = (A < 0) ? -A : A;
+    };
+
+    // Primary template for LCM calculation
+    template <typename T, T A, T B>
+    struct ratio_lcm
+    {
+    private:
+
+      static constexpr T product = ((A * B) < 0) ? -(A * B) : A * B;
+
+    public:
+
+      static constexpr T value = product / ratio_gcd<T, A, B>::value;
+    };
+
+    template<typename R1>
+    struct ratio_reduce
+    {
+    private:
+
+      static ETL_CONSTEXPR11 intmax_t gcd = etl::private_ratio::ratio_gcd<intmax_t, R1::num, R1::den>::value;
+
+    public:
+
+      using value = ratio<R1::num / gcd, R1::den / gcd>;
+    };
+
+    template<typename R1, typename R2>
+    struct ratio_add
+    {
+    private:
+
+      static ETL_CONSTEXPR11 intmax_t lcm = etl::private_ratio::ratio_lcm<intmax_t, R1::den, R2::den>::value;
+
+    public:
+
+      using value = typename ratio_reduce<ratio<R1::num * lcm / R1::den + R2::num * lcm / R2::den, lcm>>::value;
+    };
+
+    template<typename R1, typename R2>
+    struct ratio_subtract
+    {
+    public:
+      using value = typename ratio_add<R1, ratio<-R2::num, R2::den>>::value;
+    };
+
+    template<typename R1, typename R2>
+    struct ratio_multiply
+    {
+    private:
+      static ETL_CONSTEXPR11 intmax_t gcd1 = etl::private_ratio::ratio_gcd<intmax_t, R1::num, R2::den>::value;
+      static ETL_CONSTEXPR11 intmax_t gcd2 = etl::private_ratio::ratio_gcd<intmax_t, R2::num, R1::den>::value;
+
+    public:
+      using value = ratio<(R1::num / gcd1) * (R2::num / gcd2), (R1::den / gcd2) * (R2::den / gcd1)>;
+    };
+
+    template<typename R1, typename R2>
+    struct ratio_divide
+    {
+    public:
+      using value = typename ratio_multiply<R1, ratio<R2::den, R2::num>>::value;
+    };
+  }
+
+  template<typename R1, typename R2>
+  using ratio_add = typename private_ratio::ratio_add<R1, R2>::value;
+
+  template<typename R1, typename R2>
+  using ratio_subtract = typename private_ratio::ratio_subtract<R1, R2>::value;
+
+  template<typename R1, typename R2>
+  using ratio_multiply = typename private_ratio::ratio_multiply<R1, R2>::value;
+
+  template<typename R1, typename R2>
+  using ratio_divide = typename private_ratio::ratio_divide<R1, R2>::value;
+
+  template<typename R1, typename R2>
+  struct ratio_equal: etl::integral_constant<bool, (R1::num == R2::num && R1::den == R2::den)>
+  {
+  };
+
+  template<typename R1, typename R2>
+  struct ratio_not_equal: etl::integral_constant<bool, (R1::num != R2::num || R1::den != R2::den)>
+  {
+  };
+
+  template<typename R1, typename R2>
+  struct ratio_less: etl::integral_constant<bool, (R1::num * R2::den < R2::num * R1::den)>
+  {
+  };
+
+  template<typename R1, typename R2>
+  struct ratio_less_equal: etl::integral_constant<bool, (R1::num * R2::den <= R2::num * R1::den)>
+  {
+  };
+
+  template<typename R1, typename R2>
+  struct ratio_greater: etl::integral_constant<bool, (R1::num * R2::den > R2::num * R1::den)>
+  {
+  };
+
+  template<typename R1, typename R2>
+  struct ratio_greater_equal: etl::integral_constant<bool, (R1::num * R2::den >= R2::num * R1::den)>
+  {
+  };
+
+#if ETL_USING_CPP14
+  template<typename R1, typename R2>
+  ETL_CONSTEXPR14 bool ratio_equal_v = ratio_equal<R1, R2>::value;
+
+  template<typename R1, typename R2>
+  ETL_CONSTEXPR14 bool ratio_not_equal_v = ratio_not_equal<R1, R2>::value;
+
+  template<typename R1, typename R2>
+  ETL_CONSTEXPR14 bool ratio_less_v = ratio_less<R1, R2>::value;
+
+  template<typename R1, typename R2>
+  ETL_CONSTEXPR14 bool ratio_less_equal_v = ratio_less_equal<R1, R2>::value;
+
+  template<typename R1, typename R2>
+  ETL_CONSTEXPR14 bool ratio_greater_v = ratio_greater<R1, R2>::value;
+
+  template<typename R1, typename R2>
+  ETL_CONSTEXPR14 bool ratio_greater_equal_v = ratio_greater_equal<R1, R2>::value;
+#endif
+#endif
 }
 
 #endif
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index ce9e2a664..725b6928f 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -222,6 +222,7 @@ add_executable(etl_tests
 	test_queue_spsc_locked.cpp
 	test_queue_spsc_locked_small.cpp
 	test_random.cpp
+	test_ratio.cpp
 	test_reference_flat_map.cpp
 	test_reference_flat_multimap.cpp
 	test_reference_flat_multiset.cpp
diff --git a/test/test_ratio.cpp b/test/test_ratio.cpp
new file mode 100644
index 000000000..12a0b406f
--- /dev/null
+++ b/test/test_ratio.cpp
@@ -0,0 +1,144 @@
+/******************************************************************************
+The MIT License(MIT)
+
+Embedded Template Library.
+https://github.com/ETLCPP/etl
+https://www.etlcpp.com
+
+Copyright(c) 2025 BMW AG
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files(the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions :
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+******************************************************************************/
+
+#include "unit_test_framework.h"
+
+#include "etl/ratio.h"
+
+#if ETL_USING_CPP11
+namespace
+{
+  SUITE(test_ratio)
+  {
+    //*************************************************************************
+    TEST(test_ratio_add)
+    {
+      using r1 = etl::ratio<1, 2>;
+      using r2 = etl::ratio<2, 3>;
+      using r3 = etl::ratio_add<r1, r2>;
+
+      CHECK((etl::ratio_equal<r3, etl::ratio<7, 6>>::value));
+      CHECK((!etl::ratio_equal<r3, etl::ratio<1, 6>>::value));
+    }
+
+    //*************************************************************************
+    TEST(test_ratio_subtract)
+    {
+      using r1 = etl::ratio<1, 2>;
+      using r2 = etl::ratio<2, 3>;
+      using r3 = etl::ratio_subtract<r1, r2>;
+
+      CHECK((etl::ratio_equal<r3, etl::ratio<-1, 6>>::value));
+      CHECK((!etl::ratio_equal<r3, etl::ratio<-2, 6>>::value));
+    }
+
+    //*************************************************************************
+    TEST(test_ratio_multiply)
+    {
+      using r1 = etl::ratio<1, 2>;
+      using r2 = etl::ratio<2, 3>;
+      using r3 = etl::ratio_multiply<r1, r2>;
+
+      CHECK((etl::ratio_equal<r3, etl::ratio<1, 3>>::value));
+      CHECK((!etl::ratio_equal<r3, etl::ratio<1, 4>>::value));
+    }
+
+    //*************************************************************************
+    TEST(test_ratio_divide)
+    {
+      using r1 = etl::ratio<1, 2>;
+      using r2 = etl::ratio<2, 3>;
+      using r3 = etl::ratio_divide<r1, r2>;
+
+      CHECK((!etl::ratio_not_equal<r3, etl::ratio<3, 4>>::value));
+      CHECK((etl::ratio_not_equal<r3, etl::ratio<4, 3>>::value));
+    }
+
+    //*************************************************************************
+    TEST(test_ratio_equal)
+    {
+      using r1 = etl::ratio<1, 2>;
+      using r2 = etl::ratio<2, 3>;
+
+      CHECK((etl::ratio_equal<r1, r1>::value));
+      CHECK((!etl::ratio_equal<r1, r2>::value));
+    }
+
+    //*************************************************************************
+    TEST(test_ratio_not_equal)
+    {
+      using r1 = etl::ratio<1, 2>;
+      using r2 = etl::ratio<2, 3>;
+
+      CHECK((!etl::ratio_not_equal<r1, r1>::value));
+      CHECK((etl::ratio_not_equal<r1, r2>::value));
+    }
+
+    //*************************************************************************
+    TEST(test_ratio_less)
+    {
+      using r1 = etl::ratio<1, 2>;
+      using r2 = etl::ratio<2, 3>;
+
+      CHECK((etl::ratio_less<r1, r2>::value));
+      CHECK((!etl::ratio_less<r2, r1>::value));
+    }
+
+    //*************************************************************************
+    TEST(test_ratio_less_equal)
+    {
+      using r1 = etl::ratio<1, 2>;
+      using r2 = etl::ratio<2, 3>;
+
+      CHECK((etl::ratio_less_equal<r1, r1>::value));
+      CHECK((etl::ratio_less_equal<r1, r2>::value));
+    }
+
+    //*************************************************************************
+    TEST(test_ratio_greater)
+    {
+      using r1 = etl::ratio<4, 3>;
+      using r2 = etl::ratio<2, 3>;
+
+      CHECK((etl::ratio_greater<r1, r2>::value));
+      CHECK((!etl::ratio_greater<r2, r1>::value));
+    }
+
+    //*************************************************************************
+    TEST(test_ratio_greater_equal)
+    {
+      using r1 = etl::ratio<4, 3>;
+      using r2 = etl::ratio<2, 3>;
+
+      CHECK((etl::ratio_greater_equal<r1, r1>::value));
+      CHECK((etl::ratio_greater_equal<r1, r2>::value));
+    }
+  };
+
+}
+#endif