12 KiB
[ratio]
21 Metaprogramming library [meta]
21.5 Compile-time rational arithmetic [ratio]
21.5.1 General [ratio.general]
Subclause [ratio] describes the ratio library.
It provides a class templateratio which exactly represents any finite rational number with a numerator and denominator representable by compile-time constants of typeintmax_t.
Throughout subclause [ratio], the names of template parameters are used to express type requirements.
If a template parameter is named R1 or R2, and the template argument is not a specialization of the ratio template, the program is ill-formed.
21.5.2 Header synopsis [ratio.syn]
// all freestandingnamespace std {// [ratio.ratio], class template ratiotemplate<intmax_t N, intmax_t D = 1> class ratio; // [ratio.arithmetic], ratio arithmetictemplate<class R1, class R2> using ratio_add = see below; template<class R1, class R2> using ratio_subtract = see below; template<class R1, class R2> using ratio_multiply = see below; template<class R1, class R2> using ratio_divide = see below; // [ratio.comparison], ratio comparisontemplate<class R1, class R2> struct ratio_equal; template<class R1, class R2> struct ratio_not_equal; template<class R1, class R2> struct ratio_less; template<class R1, class R2> struct ratio_less_equal; template<class R1, class R2> struct ratio_greater; template<class R1, class R2> struct ratio_greater_equal; template<class R1, class R2>constexpr bool ratio_equal_v = ratio_equal<R1, R2>::value; template<class R1, class R2>constexpr bool ratio_not_equal_v = ratio_not_equal<R1, R2>::value; template<class R1, class R2>constexpr bool ratio_less_v = ratio_less<R1, R2>::value; template<class R1, class R2>constexpr bool ratio_less_equal_v = ratio_less_equal<R1, R2>::value; template<class R1, class R2>constexpr bool ratio_greater_v = ratio_greater<R1, R2>::value; template<class R1, class R2>constexpr bool ratio_greater_equal_v = ratio_greater_equal<R1, R2>::value; // [ratio.si], convenience SI typedefsusing quecto = ratio<1, 1'000'000'000'000'000'000'000'000'000'000>; // see belowusing ronto = ratio<1, 1'000'000'000'000'000'000'000'000'000>; // see belowusing yocto = ratio<1, 1'000'000'000'000'000'000'000'000>; // see belowusing zepto = ratio<1, 1'000'000'000'000'000'000'000>; // see belowusing atto = ratio<1, 1'000'000'000'000'000'000>; using femto = ratio<1, 1'000'000'000'000'000>; using pico = ratio<1, 1'000'000'000'000>; using nano = ratio<1, 1'000'000'000>; using micro = ratio<1, 1'000'000>; using milli = ratio<1, 1'000>; using centi = ratio<1, 100>; using deci = ratio<1, 10>; using deca = ratio< 10, 1>; using hecto = ratio< 100, 1>; using kilo = ratio< 1'000, 1>; using mega = ratio< 1'000'000, 1>; using giga = ratio< 1'000'000'000, 1>; using tera = ratio< 1'000'000'000'000, 1>; using peta = ratio< 1'000'000'000'000'000, 1>; using exa = ratio< 1'000'000'000'000'000'000, 1>; using zetta = ratio< 1'000'000'000'000'000'000'000, 1>; // see belowusing yotta = ratio< 1'000'000'000'000'000'000'000'000, 1>; // see belowusing ronna = ratio< 1'000'000'000'000'000'000'000'000'000, 1>; // see belowusing quetta = ratio<1'000'000'000'000'000'000'000'000'000'000, 1>; // see below}
21.5.3 Class template ratio [ratio.ratio]
namespace std {template<intmax_t N, intmax_t D = 1> class ratio {public:static constexpr intmax_t num; static constexpr intmax_t den; using type = ratio<num, den>; };}
If the template argument D is zero or the absolute values of either of the template arguments N and D is not representable by typeintmax_t, the program is ill-formed.
[Note 1:
These rules ensure that infinite ratios are avoided and that for any negative input, there exists a representable value of its absolute value which is positive.
This excludes the most negative value.
â end note]
The static data members num and den shall have the following values, where gcd represents the greatest common divisor of the absolute values ofN and D:
21.5.4 Arithmetic on ratios [ratio.arithmetic]
Each of the alias templates ratio_add, ratio_subtract, ratio_multiply, and ratio_divide denotes the result of an arithmetic computation on tworatios R1 and R2.
With X and Y computed (in the absence of arithmetic overflow) as specified by Table 65, each alias denotes a ratio<U, V> such that U is the same as ratio<X, Y>::num andV is the same as ratio<X, Y>::den.
If it is not possible to represent U or V with intmax_t, the program is ill-formed.
Otherwise, an implementation should yield correct values of U andV.
If it is not possible to represent X or Y with intmax_t, the program is ill-formed unless the implementation yields correct values of U andV.
Table 65 — Expressions used to perform ratio arithmetic [tab:ratio.arithmetic]
| ð Type |
Value of X | Value of Y |
|---|---|---|
| ð ratio_add<R1, R2> |
R1::num * R2::den + | R1::den * R2::den |
| ð | R2::num * R1::den | |
| ð ratio_subtract<R1, R2> |
R1::num * R2::den - | R1::den * R2::den |
| ð | R2::num * R1::den | |
| ð ratio_multiply<R1, R2> |
R1::num * R2::num | R1::den * R2::den |
| ð ratio_divide<R1, R2> |
R1::num * R2::den | R1::den * R2::num |
[Example 1: static_assert(ratio_add<ratio<1, 3>, ratio<1, 6>>::num == 1, "1/3+1/6 == 1/2");static_assert(ratio_add<ratio<1, 3>, ratio<1, 6>>::den == 2, "1/3+1/6 == 1/2");static_assert(ratio_multiply<ratio<1, 3>, ratio<3, 2>>::num == 1, "1/33/2 == 1/2");static_assert(ratio_multiply<ratio<1, 3>, ratio<3, 2>>::den == 2, "1/33/2 == 1/2");
// The following cases may cause the program to be ill-formed under some implementationsstatic_assert(ratio_add<ratio<1, INT_MAX>, ratio<1, INT_MAX>>::num == 2, "1/MAX+1/MAX == 2/MAX");static_assert(ratio_add<ratio<1, INT_MAX>, ratio<1, INT_MAX>>::den == INT_MAX, "1/MAX+1/MAX == 2/MAX");static_assert(ratio_multiply<ratio<1, INT_MAX>, ratio<INT_MAX, 2>>::num == 1, "1/MAX * MAX/2 == 1/2");static_assert(ratio_multiply<ratio<1, INT_MAX>, ratio<INT_MAX, 2>>::den == 2, "1/MAX * MAX/2 == 1/2"); â end example]
21.5.5 Comparison of ratios [ratio.comparison]
template<class R1, class R2> struct ratio_equal : bool_constant<R1::num == R2::num && R1::den == R2::den> { };
template<class R1, class R2> struct ratio_not_equal : bool_constant<!ratio_equal_v<R1, R2>> { };
template<class R1, class R2> struct ratio_less : bool_constant<see below> { };
If R1::num × R2::den is less than R2::num × R1::den,ratio_less<R1, R2> shall be derived from bool_constant; otherwise it shall be derived frombool_constant.
Implementations may use other algorithms to compute this relationship to avoid overflow.
If overflow occurs, the program is ill-formed.
template<class R1, class R2> struct ratio_less_equal : bool_constant<!ratio_less_v<R2, R1>> { };
template<class R1, class R2> struct ratio_greater : bool_constant<ratio_less_v<R2, R1>> { };
template<class R1, class R2> struct ratio_greater_equal : bool_constant<!ratio_less_v<R1, R2>> { };
21.5.6 SI types for ratio [ratio.si]
For each of the typedef-namesquecto, ronto,yocto, zepto,zetta, yotta,ronna, and quetta, if both of the constants used in its specification are representable by intmax_t, the typedef is defined; if either of the constants is not representable by intmax_t, the typedef is not defined.