Init
This commit is contained in:
175
cppdraft/ratio.md
Normal file
175
cppdraft/ratio.md
Normal file
@@ -0,0 +1,175 @@
|
||||
[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.3 Class template ratio"), class template ratiotemplate<intmax_t N, intmax_t D = 1> class ratio; // [[ratio.arithmetic]](#arithmetic "21.5.4 Arithmetic 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.5 Comparison 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.2 Header <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.2 Header <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.2 Header <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.2 Header <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.2 Header <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.2 Header <ratio> synopsis [ratio.syn]") = ratio_greater_equal<R1, R2>::value; // [[ratio.si]](#si "21.5.6 SI types for ratio"), convenience SI typedefsusing [quecto](#lib:quecto "21.5.6 SI 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.6 SI 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.6 SI types for ratio [ratio.si]") = ratio<1, 1'000'000'000'000'000'000'000'000>; // *see below*using [zepto](#lib:zepto "21.5.6 SI types for ratio [ratio.si]") = ratio<1, 1'000'000'000'000'000'000'000>; // *see below*using [atto](#lib:atto "21.5.2 Header <ratio> synopsis [ratio.syn]") = ratio<1, 1'000'000'000'000'000'000>; using [femto](#lib:femto "21.5.2 Header <ratio> synopsis [ratio.syn]") = ratio<1, 1'000'000'000'000'000>; using [pico](#lib:pico "21.5.2 Header <ratio> synopsis [ratio.syn]") = ratio<1, 1'000'000'000'000>; using [nano](#lib:nano "21.5.2 Header <ratio> synopsis [ratio.syn]") = ratio<1, 1'000'000'000>; using [micro](#lib:micro "21.5.2 Header <ratio> synopsis [ratio.syn]") = ratio<1, 1'000'000>; using [milli](#lib:milli "21.5.2 Header <ratio> synopsis [ratio.syn]") = ratio<1, 1'000>; using [centi](#lib:centi "21.5.2 Header <ratio> synopsis [ratio.syn]") = ratio<1, 100>; using [deci](#lib:deci "21.5.2 Header <ratio> synopsis [ratio.syn]") = ratio<1, 10>; using [deca](#lib:deca "21.5.2 Header <ratio> synopsis [ratio.syn]") = ratio< 10, 1>; using [hecto](#lib:hecto "21.5.2 Header <ratio> synopsis [ratio.syn]") = ratio< 100, 1>; using [kilo](#lib:kilo "21.5.2 Header <ratio> synopsis [ratio.syn]") = ratio< 1'000, 1>; using [mega](#lib:mega "21.5.2 Header <ratio> synopsis [ratio.syn]") = ratio< 1'000'000, 1>; using [giga](#lib:giga "21.5.2 Header <ratio> synopsis [ratio.syn]") = ratio< 1'000'000'000, 1>; using [tera](#lib:tera "21.5.2 Header <ratio> synopsis [ratio.syn]") = ratio< 1'000'000'000'000, 1>; using [peta](#lib:peta "21.5.2 Header <ratio> synopsis [ratio.syn]") = ratio< 1'000'000'000'000'000, 1>; using [exa](#lib:exa "21.5.2 Header <ratio> synopsis [ratio.syn]") = ratio< 1'000'000'000'000'000'000, 1>; using [zetta](#lib:zetta "21.5.6 SI types for ratio [ratio.si]") = ratio< 1'000'000'000'000'000'000'000, 1>; // *see below*using [yotta](#lib:yotta "21.5.6 SI types for ratio [ratio.si]") = ratio< 1'000'000'000'000'000'000'000'000, 1>; // *see below*using [ronna](#lib:ronna "21.5.6 SI 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.6 SI 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.4 The 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)
|
||||
Reference in New Issue
Block a user