Files
2025-10-25 03:02:53 +03:00

176 lines
12 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[ratio]
# 21 Metaprogramming library [[meta]](./#meta)
## 21.5 Compile-time rational arithmetic [ratio]
### [21.5.1](#general) General [[ratio.general]](ratio.general)
[1](#general-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L7036)
Subclause [ratio] describes the ratio library[.](#general-1.sentence-1)
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[.](#general-1.sentence-2)
[2](#general-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L7043)
Throughout subclause [ratio], the names of template parameters are used to express
type requirements[.](#general-2.sentence-1)
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[.](#general-2.sentence-2)
### [21.5.2](#syn) Header <ratio> synopsis [[ratio.syn]](ratio.syn)
// all freestandingnamespace std {// [[ratio.ratio]](#ratio "21.5.3Class template ratio"), class template ratiotemplate<intmax_t N, intmax_t D = 1> class ratio; // [[ratio.arithmetic]](#arithmetic "21.5.4Arithmetic on ratios"), 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]](#comparison "21.5.5Comparison of ratios"), 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](#lib:ratio_equal_v "21.5.2Header <ratio> synopsis[ratio.syn]") = ratio_equal<R1, R2>::value; template<class R1, class R2>constexpr bool [ratio_not_equal_v](#lib:ratio_not_equal_v "21.5.2Header <ratio> synopsis[ratio.syn]") = ratio_not_equal<R1, R2>::value; template<class R1, class R2>constexpr bool [ratio_less_v](#lib:ratio_less_v "21.5.2Header <ratio> synopsis[ratio.syn]") = ratio_less<R1, R2>::value; template<class R1, class R2>constexpr bool [ratio_less_equal_v](#lib:ratio_less_equal_v "21.5.2Header <ratio> synopsis[ratio.syn]") = ratio_less_equal<R1, R2>::value; template<class R1, class R2>constexpr bool [ratio_greater_v](#lib:ratio_greater_v "21.5.2Header <ratio> synopsis[ratio.syn]") = ratio_greater<R1, R2>::value; template<class R1, class R2>constexpr bool [ratio_greater_equal_v](#lib:ratio_greater_equal_v "21.5.2Header <ratio> synopsis[ratio.syn]") = ratio_greater_equal<R1, R2>::value; // [[ratio.si]](#si "21.5.6SI types for ratio"), convenience SI typedefsusing [quecto](#lib:quecto "21.5.6SI types for ratio[ratio.si]") = ratio<1, 1'000'000'000'000'000'000'000'000'000'000>; // *see below*using [ronto](#lib:ronto "21.5.6SI types for ratio[ratio.si]") = ratio<1, 1'000'000'000'000'000'000'000'000'000>; // *see below*using [yocto](#lib:yocto "21.5.6SI types for ratio[ratio.si]") = ratio<1, 1'000'000'000'000'000'000'000'000>; // *see below*using [zepto](#lib:zepto "21.5.6SI types for ratio[ratio.si]") = ratio<1, 1'000'000'000'000'000'000'000>; // *see below*using [atto](#lib:atto "21.5.2Header <ratio> synopsis[ratio.syn]") = ratio<1, 1'000'000'000'000'000'000>; using [femto](#lib:femto "21.5.2Header <ratio> synopsis[ratio.syn]") = ratio<1, 1'000'000'000'000'000>; using [pico](#lib:pico "21.5.2Header <ratio> synopsis[ratio.syn]") = ratio<1, 1'000'000'000'000>; using [nano](#lib:nano "21.5.2Header <ratio> synopsis[ratio.syn]") = ratio<1, 1'000'000'000>; using [micro](#lib:micro "21.5.2Header <ratio> synopsis[ratio.syn]") = ratio<1, 1'000'000>; using [milli](#lib:milli "21.5.2Header <ratio> synopsis[ratio.syn]") = ratio<1, 1'000>; using [centi](#lib:centi "21.5.2Header <ratio> synopsis[ratio.syn]") = ratio<1, 100>; using [deci](#lib:deci "21.5.2Header <ratio> synopsis[ratio.syn]") = ratio<1, 10>; using [deca](#lib:deca "21.5.2Header <ratio> synopsis[ratio.syn]") = ratio< 10, 1>; using [hecto](#lib:hecto "21.5.2Header <ratio> synopsis[ratio.syn]") = ratio< 100, 1>; using [kilo](#lib:kilo "21.5.2Header <ratio> synopsis[ratio.syn]") = ratio< 1'000, 1>; using [mega](#lib:mega "21.5.2Header <ratio> synopsis[ratio.syn]") = ratio< 1'000'000, 1>; using [giga](#lib:giga "21.5.2Header <ratio> synopsis[ratio.syn]") = ratio< 1'000'000'000, 1>; using [tera](#lib:tera "21.5.2Header <ratio> synopsis[ratio.syn]") = ratio< 1'000'000'000'000, 1>; using [peta](#lib:peta "21.5.2Header <ratio> synopsis[ratio.syn]") = ratio< 1'000'000'000'000'000, 1>; using [exa](#lib:exa "21.5.2Header <ratio> synopsis[ratio.syn]") = ratio< 1'000'000'000'000'000'000, 1>; using [zetta](#lib:zetta "21.5.6SI types for ratio[ratio.si]") = ratio< 1'000'000'000'000'000'000'000, 1>; // *see below*using [yotta](#lib:yotta "21.5.6SI types for ratio[ratio.si]") = ratio< 1'000'000'000'000'000'000'000'000, 1>; // *see below*using [ronna](#lib:ronna "21.5.6SI types for ratio[ratio.si]") = ratio< 1'000'000'000'000'000'000'000'000'000, 1>; // *see below*using [quetta](#lib:quetta "21.5.6SI types for ratio[ratio.si]") = ratio<1'000'000'000'000'000'000'000'000'000'000, 1>; // *see below*}
### [21.5.3](#ratio) Class template ratio [[ratio.ratio]](ratio.ratio)
[🔗](#lib: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>; };}
[1](#ratio-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L7127)
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[.](#ratio-1.sentence-1)
[*Note [1](#ratio-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[.](#ratio-1.sentence-2)
This excludes the most negative value[.](#ratio-1.sentence-3)
— *end note*]
[2](#ratio-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L7139)
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:
- [(2.1)](#ratio-2.1)
num shall have the value sgn(N) * sgn(D) * abs(N) / gcd[.](#ratio-2.1.sentence-1)
- [(2.2)](#ratio-2.2)
den shall have the value abs(D) / gcd[.](#ratio-2.2.sentence-1)
### [21.5.4](#arithmetic) Arithmetic on ratios [[ratio.arithmetic]](ratio.arithmetic)
[1](#arithmetic-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L7151)
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[.](#arithmetic-1.sentence-1)
With X and Y computed (in the
absence of arithmetic overflow) as specified by Table [65](#tab:ratio.arithmetic "Table 65: Expressions used to perform ratio arithmetic"), 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[.](#arithmetic-1.sentence-2)
[2](#arithmetic-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L7163)
If it is not possible to represent U or V with intmax_t, the program is
ill-formed[.](#arithmetic-2.sentence-1)
Otherwise, an implementation should yield correct values of U andV[.](#arithmetic-2.sentence-2)
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[.](#arithmetic-2.sentence-3)
Table [65](#tab:ratio.arithmetic) — Expressions used to perform ratio arithmetic [[tab:ratio.arithmetic]](./tab:ratio.arithmetic)
| [🔗](#tab:ratio.arithmetic-row-1)<br>**Type** | **Value of X** | **Value of Y** |
| --- | --- | --- |
| [🔗](#tab:ratio.arithmetic-row-2)<br>ratio_add<R1, R2> | R1::num * R2::den + | R1::den * R2::den |
| [🔗](#tab:ratio.arithmetic-row-3) | R2::num * R1::den | |
| [🔗](#tab:ratio.arithmetic-row-4)<br>ratio_subtract<R1, R2> | R1::num * R2::den - | R1::den * R2::den |
| [🔗](#tab:ratio.arithmetic-row-5) | R2::num * R1::den | |
| [🔗](#tab:ratio.arithmetic-row-6)<br>ratio_multiply<R1, R2> | R1::num * R2::num | R1::den * R2::den |
| [🔗](#tab:ratio.arithmetic-row-7)<br>ratio_divide<R1, R2> | R1::num * R2::den | R1::den * R2::num |
[3](#arithmetic-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L7200)
[*Example [1](#arithmetic-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/3*3/2 == 1/2");static_assert(ratio_multiply<ratio<1, 3>, ratio<3, 2>>::den == 2, "1/3*3/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) Comparison of ratios [[ratio.comparison]](ratio.comparison)
[🔗](#lib:ratio_equal)
`template<class R1, class R2>
struct ratio_equal : bool_constant<R1::num == R2::num && R1::den == R2::den> { };
`
[🔗](#lib:ratio_not_equal)
`template<class R1, class R2>
struct ratio_not_equal : bool_constant<!ratio_equal_v<R1, R2>> { };
`
[🔗](#lib:ratio_less)
`template<class R1, class R2>
struct ratio_less : bool_constant<see below> { };
`
[1](#comparison-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L7242)
If R1::num × R2::den is less than R2::num × R1::den,ratio_less<R1, R2> shall be
derived from bool_constant<true>; otherwise it shall be derived frombool_constant<false>[.](#comparison-1.sentence-1)
Implementations may use other algorithms to
compute this relationship to avoid overflow[.](#comparison-1.sentence-2)
If overflow occurs, the program is ill-formed[.](#comparison-1.sentence-3)
[🔗](#lib:ratio_less_equal)
`template<class R1, class R2>
struct ratio_less_equal : bool_constant<!ratio_less_v<R2, R1>> { };
`
[🔗](#lib:ratio_greater)
`template<class R1, class R2>
struct ratio_greater : bool_constant<ratio_less_v<R2, R1>> { };
`
[🔗](#lib:ratio_greater_equal)
`template<class R1, class R2>
struct ratio_greater_equal : bool_constant<!ratio_less_v<R1, R2>> { };
`
### [21.5.6](#si) SI types for ratio [[ratio.si]](ratio.si)
[1](#si-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L7270)
For each of the [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4The typedef specifier[dcl.typedef]")*s*quecto, 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[.](#si-1.sentence-1)