/* @file ratio_util.hpp */ #pragma once #include "ratio_concept.hpp" #include "stringliteral.hpp" #include #include namespace xo { namespace unit { // ----- ratio_floor ----- template struct ratio_floor { using type = std::ratio; }; template using ratio_floor_t = ratio_floor::type; // ----- ratio_frac ----- template struct ratio_frac { static_assert(ratio_concept); using type = std::ratio_subtract>::type; }; template using ratio_frac_t = ratio_frac::type; // ----- ratio_power ----- /** ratio to an integer power * * ratio_power::type * * yields a std::ratio representing Base^Power. **/ template struct ratio_power_aux; template struct ratio_power_aux { /** std::ratio representing Base^(-Power) **/ using _inverse_ratio_type = typename ratio_power_aux::type; /** Base^(-Power)^-1 = Base^Power **/ using type = std::ratio_divide, _inverse_ratio_type>; static_assert(ratio_concept); }; template struct ratio_power_aux { using type = std::ratio<1>; }; template struct ratio_power_aux { using type = Base; }; template struct ratio_power_aux { /** Base^(Power/2) **/ using _p2_ratio_type = ratio_power_aux::type; /** Base^(Power%2) : * - Base^0 if Power is even * - Base^1 if Power is odd **/ using _x_ratio_type = ratio_power_aux::type; using type = std::ratio_multiply< _x_ratio_type, std::ratio_multiply<_p2_ratio_type, _p2_ratio_type> >; static_assert(ratio_concept); }; // ----- ratio_power_v ----- /** compute Base^Power at compile time **/ template using ratio_power_t = ratio_power_aux::type; // ----- from_ratio ----- /** Example: * from_ratio --> 0.1 * from_ratio --> 0.8 **/ template constexpr Repr from_ratio() { static_assert(ratio_concept); return Ratio::num / static_cast(Ratio::den); } // ----- ratio2str_aux ----- /* note: using struct wrapper because partial specialization of function templates * is not allowed */ template struct ratio2str_aux; template struct ratio2str_aux { static constexpr auto value = stringliteral_concat("(", stringliteral_from_int_v().value_, "/", stringliteral_from_int_v().value_, ")"); }; template struct ratio2str_aux { /* note: using struct wrapper because partial specialization of function templates * is not allowed */ static constexpr auto value = stringliteral_concat("-(", stringliteral_from_int_v<-Num>().value_, "/", stringliteral_from_int_v().value_, ")"); }; template struct ratio2str_aux { static constexpr auto value = stringliteral_concat("-", stringliteral_from_int_v<-Num>().value_); }; template struct ratio2str_aux { static constexpr auto value = stringliteral_from_int_v(); }; template <> struct ratio2str_aux<1, 1, false> { static constexpr auto value = stringliteral(""); }; // ----- stringliteral_from_ratio ----- /** Example: * - stringliteral_from_ratio -> "^(2,3)" **/ template constexpr auto stringliteral_from_ratio() { static_assert(ratio_concept); using lowest_terms_type = Ratio::type; return ratio2str_aux().value; }; template constexpr char const * cstr_from_ratio() { static_assert(ratio_concept); using lowest_terms_type = Ratio::type; return ratio2str_aux().value.c_str(); }; // ----- exponent2str_aux ----- /* note: using struct wrapper because partial specialization of function templates * is not allowed */ template struct exponent2str_aux; template struct exponent2str_aux { static constexpr auto value = stringliteral_concat("^(", stringliteral_from_int_v().value_, "/", stringliteral_from_int_v().value_, ")"); }; template struct exponent2str_aux { /* note: using struct wrapper because partial specialization of function templates * is not allowed */ static constexpr auto value = stringliteral_concat("^-(", stringliteral_from_int_v<-Num>().value_, "/", stringliteral_from_int_v().value_, ")"); }; template struct exponent2str_aux { static constexpr auto value = stringliteral_concat("^", stringliteral_from_int_v().value_); }; template struct exponent2str_aux { /* Example: * - exponent2str_aux<-1, 1, true> --> "^-1" * - exponent2str_aux<-2, 1, true> --> "^-2" */ static constexpr auto value = stringliteral_concat("^", stringliteral_from_int_v().value_); }; template <> struct exponent2str_aux<1, 1, false> { static constexpr auto value = stringliteral(""); }; // ----- stringliteral_from_exponent ----- template constexpr auto stringliteral_from_exponent() { static_assert(ratio_concept); return exponent2str_aux().value; }; } /*namespace unit*/ } /*namespace xo*/ /* end ratio_util.hpp */