Created
January 9, 2015 19:27
-
-
Save kuhar/baaf11bafba4907a2fd4 to your computer and use it in GitHub Desktop.
compile-time fixed-point
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <ratio> | |
template <char... Ts> | |
struct seq; | |
template <class Seq> | |
struct parse_sign | |
{ | |
static constexpr auto sign = intmax_t{1}; | |
using tail = Seq; | |
}; | |
template <char... Ts> | |
struct parse_sign<seq<'+', Ts...>> | |
{ | |
static constexpr auto sign = intmax_t{1}; | |
using tail = seq<Ts...>; | |
}; | |
template <char... Ts> | |
struct parse_sign<seq<'-', Ts...>> | |
{ | |
static constexpr auto sign = intmax_t{-1}; | |
using tail = seq<Ts...>; | |
}; | |
template <bool BeforePoint, intmax_t Num, intmax_t Den, class Seq> | |
struct parse_frac; | |
template <bool BeforePoint, intmax_t Num, intmax_t Den> | |
struct parse_frac<BeforePoint, Num, Den, seq<>> | |
{ | |
static constexpr auto num = Num; | |
static constexpr auto den = Den; | |
}; | |
template <intmax_t Num, intmax_t Den, char... Ts> | |
struct parse_frac<true, Num, Den, seq<'.', Ts...>> | |
{ | |
using next = parse_frac<false, Num, Den, seq<Ts...>>; | |
static constexpr auto num = next::num; | |
static constexpr auto den = next::den; | |
}; | |
template <intmax_t Num, intmax_t Den, char T, char... Ts> | |
struct parse_frac<true, Num, Den, seq<T, Ts...>> | |
{ | |
static_assert( | |
T >= '0' && T <= '9', | |
"Expected digit." | |
); | |
using next = parse_frac<true, 10 * Num + (T - '0'), Den, seq<Ts...>>; | |
static constexpr auto num = next::num; | |
static constexpr auto den = next::den; | |
}; | |
template <intmax_t Num, intmax_t Den, char T, char... Ts> | |
struct parse_frac<false, Num, Den, seq<T, Ts...>> | |
{ | |
static_assert( | |
T >= '0' && T <= '9', | |
"Expected digit." | |
); | |
using next = parse_frac<false, 10 * Num + (T - '0'), 10 * Den, seq<Ts...>>; | |
static constexpr auto num = next::num; | |
static constexpr auto den = next::den; | |
}; | |
template <class Char, Char... Ts> | |
constexpr auto operator"" _f() | |
{ | |
using sign_parser = parse_sign<seq<Ts...>>; | |
using tail = typename sign_parser::tail; | |
using frac_parser = parse_frac<true, 0, 1, tail>; | |
return std::ratio< | |
sign_parser::sign * frac_parser::num, | |
frac_parser::den | |
>{}; | |
} | |
#define cc_fixed(x) decltype(#x ## _f) | |
int main() | |
{ | |
using x = cc_fixed(123.456); | |
using y = cc_fixed(+123.456); | |
using z = cc_fixed(-123.456); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment