Skip to content

Commit

Permalink
Port to C++11
Browse files Browse the repository at this point in the history
  • Loading branch information
rolandreichweinbmw committed Jan 21, 2025
1 parent 86057c5 commit e455757
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 71 deletions.
137 changes: 87 additions & 50 deletions include/etl/ratio.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,114 +101,151 @@ namespace etl
/// An approximation of e.
typedef ratio<326, 120> ratio_e;

#if ETL_USING_CPP14
namespace internal
#if ETL_USING_CPP11
namespace private_ratio
{
template<class R1>
struct _ratio_reduce
// 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_CONSTEXPR14 intmax_t gcd = etl::gcd(R1::num, R1::den);

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<class R1, class R2>
struct _ratio_add
template<typename R1, typename R2>
struct ratio_add
{
private:
static ETL_CONSTEXPR14 intmax_t lcm = etl::lcm(R1::den, R2::den);

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;

using value = typename ratio_reduce<ratio<R1::num * lcm / R1::den + R2::num * lcm / R2::den, lcm>>::value;
};

template<class R1, class R2>
struct _ratio_subtract
template<typename R1, typename R2>
struct ratio_subtract
{
public:
using value = typename _ratio_add<R1, ratio<-R2::num, R2::den>>::value;
using value = typename ratio_add<R1, ratio<-R2::num, R2::den>>::value;
};

template<class R1, class R2>
struct _ratio_multiply
template<typename R1, typename R2>
struct ratio_multiply
{
private:
static ETL_CONSTEXPR14 intmax_t gcd1 = etl::gcd(R1::num, R2::den);
static ETL_CONSTEXPR14 intmax_t gcd2 = etl::gcd(R2::num, R1::den);
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<class R1, class R2>
struct _ratio_divide
template<typename R1, typename R2>
struct ratio_divide
{
public:
using value = typename _ratio_multiply<R1, ratio<R2::den, R2::num>>::value;
using value = typename ratio_multiply<R1, ratio<R2::den, R2::num>>::value;
};
}

template<class R1, class R2>
using ratio_add = typename internal::_ratio_add<R1, R2>::value;
template<typename R1, typename R2>
using ratio_add = typename private_ratio::ratio_add<R1, R2>::value;

template<class R1, class R2>
using ratio_subtract = typename internal::_ratio_subtract<R1, R2>::value;
template<typename R1, typename R2>
using ratio_subtract = typename private_ratio::ratio_subtract<R1, R2>::value;

template<class R1, class R2>
using ratio_multiply = typename internal::_ratio_multiply<R1, R2>::value;
template<typename R1, typename R2>
using ratio_multiply = typename private_ratio::ratio_multiply<R1, R2>::value;

template<class R1, class R2>
using ratio_divide = typename internal::_ratio_divide<R1, R2>::value;
template<typename R1, typename R2>
using ratio_divide = typename private_ratio::ratio_divide<R1, R2>::value;

template<class R1, class R2>
template<typename R1, typename R2>
struct ratio_equal: etl::integral_constant<bool, (R1::num == R2::num && R1::den == R2::den)>
{
};

template<class R1, class R2>
ETL_CONSTEXPR14 bool ratio_equal_v = ratio_equal<R1, R2>::value;

template<class R1, class R2>
template<typename R1, typename R2>
struct ratio_not_equal: etl::integral_constant<bool, (R1::num != R2::num || R1::den != R2::den)>
{
};

template<class R1, class R2>
ETL_CONSTEXPR14 bool ratio_not_equal_v = ratio_not_equal<R1, R2>::value;

template<class R1, class R2>
template<typename R1, typename R2>
struct ratio_less: etl::integral_constant<bool, (R1::num * R2::den < R2::num * R1::den)>
{
};

template<class R1, class R2>
ETL_CONSTEXPR14 bool ratio_less_v = ratio_less<R1, R2>::value;

template<class R1, class R2>
template<typename R1, typename R2>
struct ratio_less_equal: etl::integral_constant<bool, (R1::num * R2::den <= R2::num * R1::den)>
{
};

template<class R1, class R2>
ETL_CONSTEXPR14 bool ratio_less_equal_v = ratio_less_equal<R1, R2>::value;

template<class R1, class R2>
template<typename R1, typename R2>
struct ratio_greater: etl::integral_constant<bool, (R1::num * R2::den > R2::num * R1::den)>
{
};

template<class R1, class R2>
ETL_CONSTEXPR14 bool ratio_greater_v = ratio_greater<R1, R2>::value;

template<class R1, class R2>
template<typename R1, typename R2>
struct ratio_greater_equal: etl::integral_constant<bool, (R1::num * R2::den >= R2::num * R1::den)>
{
};

template<class R1, class R2>
ETL_CONSTEXPR14 bool ratio_greater_equal_v = ratio_greater_equal<R1, R2>::value;
#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
}

Expand Down
42 changes: 21 additions & 21 deletions test/test_ratio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ SOFTWARE.

#include "etl/ratio.h"

#if ETL_USING_CPP14
#if ETL_USING_CPP11
namespace
{
SUITE(test_ratio)
Expand All @@ -42,8 +42,8 @@ namespace
using r2 = etl::ratio<2, 3>;
using r3 = etl::ratio_add<r1, r2>;

CHECK((etl::ratio_equal_v<r3, etl::ratio<7, 6>>));
CHECK((!etl::ratio_equal_v<r3, etl::ratio<1, 6>>));
CHECK((etl::ratio_equal<r3, etl::ratio<7, 6>>::value));
CHECK((!etl::ratio_equal<r3, etl::ratio<1, 6>>::value));
}

//*************************************************************************
Expand All @@ -53,8 +53,8 @@ namespace
using r2 = etl::ratio<2, 3>;
using r3 = etl::ratio_subtract<r1, r2>;

CHECK((etl::ratio_equal_v<r3, etl::ratio<-1, 6>>));
CHECK((!etl::ratio_equal_v<r3, etl::ratio<-2, 6>>));
CHECK((etl::ratio_equal<r3, etl::ratio<-1, 6>>::value));
CHECK((!etl::ratio_equal<r3, etl::ratio<-2, 6>>::value));
}

//*************************************************************************
Expand All @@ -64,8 +64,8 @@ namespace
using r2 = etl::ratio<2, 3>;
using r3 = etl::ratio_multiply<r1, r2>;

CHECK((etl::ratio_equal_v<r3, etl::ratio<1, 3>>));
CHECK((!etl::ratio_equal_v<r3, etl::ratio<1, 4>>));
CHECK((etl::ratio_equal<r3, etl::ratio<1, 3>>::value));
CHECK((!etl::ratio_equal<r3, etl::ratio<1, 4>>::value));
}

//*************************************************************************
Expand All @@ -75,8 +75,8 @@ namespace
using r2 = etl::ratio<2, 3>;
using r3 = etl::ratio_divide<r1, r2>;

CHECK((!etl::ratio_not_equal_v<r3, etl::ratio<3, 4>>));
CHECK((etl::ratio_not_equal_v<r3, etl::ratio<4, 3>>));
CHECK((!etl::ratio_not_equal<r3, etl::ratio<3, 4>>::value));
CHECK((etl::ratio_not_equal<r3, etl::ratio<4, 3>>::value));
}

//*************************************************************************
Expand All @@ -85,8 +85,8 @@ namespace
using r1 = etl::ratio<1, 2>;
using r2 = etl::ratio<2, 3>;

CHECK((etl::ratio_equal_v<r1, r1>));
CHECK((!etl::ratio_equal_v<r1, r2>));
CHECK((etl::ratio_equal<r1, r1>::value));
CHECK((!etl::ratio_equal<r1, r2>::value));
}

//*************************************************************************
Expand All @@ -95,8 +95,8 @@ namespace
using r1 = etl::ratio<1, 2>;
using r2 = etl::ratio<2, 3>;

CHECK((!etl::ratio_not_equal_v<r1, r1>));
CHECK((etl::ratio_not_equal_v<r1, r2>));
CHECK((!etl::ratio_not_equal<r1, r1>::value));
CHECK((etl::ratio_not_equal<r1, r2>::value));
}

//*************************************************************************
Expand All @@ -105,8 +105,8 @@ namespace
using r1 = etl::ratio<1, 2>;
using r2 = etl::ratio<2, 3>;

CHECK((etl::ratio_less_v<r1, r2>));
CHECK((!etl::ratio_less_v<r2, r1>));
CHECK((etl::ratio_less<r1, r2>::value));
CHECK((!etl::ratio_less<r2, r1>::value));
}

//*************************************************************************
Expand All @@ -115,8 +115,8 @@ namespace
using r1 = etl::ratio<1, 2>;
using r2 = etl::ratio<2, 3>;

CHECK((etl::ratio_less_equal_v<r1, r1>));
CHECK((etl::ratio_less_equal_v<r1, r2>));
CHECK((etl::ratio_less_equal<r1, r1>::value));
CHECK((etl::ratio_less_equal<r1, r2>::value));
}

//*************************************************************************
Expand All @@ -125,8 +125,8 @@ namespace
using r1 = etl::ratio<4, 3>;
using r2 = etl::ratio<2, 3>;

CHECK((etl::ratio_greater_v<r1, r2>));
CHECK((!etl::ratio_greater_v<r2, r1>));
CHECK((etl::ratio_greater<r1, r2>::value));
CHECK((!etl::ratio_greater<r2, r1>::value));
}

//*************************************************************************
Expand All @@ -135,8 +135,8 @@ namespace
using r1 = etl::ratio<4, 3>;
using r2 = etl::ratio<2, 3>;

CHECK((etl::ratio_greater_equal_v<r1, r1>));
CHECK((etl::ratio_greater_equal_v<r1, r2>));
CHECK((etl::ratio_greater_equal<r1, r1>::value));
CHECK((etl::ratio_greater_equal<r1, r2>::value));
}
};

Expand Down

0 comments on commit e455757

Please sign in to comment.